@codingfactory/mediables-vue 2.19.2 → 2.20.0
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/{PixiFrameExporter-CRe8z6ua.js → PixiFrameExporter-CGQJH9OE.js} +2 -2
- package/dist/{PixiFrameExporter-CRe8z6ua.js.map → PixiFrameExporter-CGQJH9OE.js.map} +1 -1
- package/dist/{PixiFrameExporter-R6iQjzVw.cjs → PixiFrameExporter-CfUbYDmD.cjs} +2 -2
- package/dist/{PixiFrameExporter-R6iQjzVw.cjs.map → PixiFrameExporter-CfUbYDmD.cjs.map} +1 -1
- package/dist/editor-v2-CFLWp7RZ.cjs +2 -0
- package/dist/editor-v2-CFLWp7RZ.cjs.map +1 -0
- package/dist/editor-v2-DjhJBaCS.js +7187 -0
- package/dist/editor-v2-DjhJBaCS.js.map +1 -0
- package/dist/filters/index.d.ts +1 -0
- package/dist/filters/recipeToCssFilter.d.ts +71 -0
- package/dist/index-Dae8SHT7.js.map +1 -1
- package/dist/index-QOKC8XA_.cjs.map +1 -1
- package/dist/index-ST4ukv22.cjs +357 -0
- package/dist/index-ST4ukv22.cjs.map +1 -0
- package/dist/index-rw6mdaKW.js +38906 -0
- package/dist/index-rw6mdaKW.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/mediables-vanilla.cjs +1 -1
- package/dist/mediables-vanilla.mjs +10 -9
- package/dist/mediables-vue.cjs +1 -1
- package/dist/mediables-vue.mjs +97 -87
- package/dist/style.css +1 -1
- package/dist/utils/videoRecipeCapabilities.d.ts +15 -0
- package/dist/vanilla-exports.d.ts +2 -1
- package/package.json +1 -1
- package/dist/editor-BQ_nY4P6.js +0 -4302
- package/dist/editor-BQ_nY4P6.js.map +0 -1
- package/dist/editor-CUV1pIsV.cjs +0 -2
- package/dist/editor-CUV1pIsV.cjs.map +0 -1
- package/dist/index-B8LxZ37n.js +0 -41633
- package/dist/index-B8LxZ37n.js.map +0 -1
- package/dist/index-DutUeSES.cjs +0 -357
- package/dist/index-DutUeSES.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-QOKC8XA_.cjs","sources":["../resources/js/vanilla-editor/core/EventEmitter.js","../resources/js/vanilla-editor/core/State.js","../resources/js/filters/registry.ts","../resources/js/filters/definitions/adjustment.ts","../resources/js/filters/definitions/adjustmentAdvanced.ts","../resources/js/filters/definitions/alpha.ts","../resources/js/filters/definitions/blur.ts","../resources/js/filters/definitions/colorMatrix.ts","../resources/js/filters/definitions/colorOverlay.ts","../resources/js/filters/definitions/dropShadow.ts","../resources/js/filters/definitions/grayscale.ts","../resources/js/filters/definitions/hslAdjustment.ts","../resources/js/filters/definitions/kawaseBlur.ts","../resources/js/filters/definitions/motionBlur.ts","../resources/js/filters/definitions/radialBlur.ts","../resources/js/filters/definitions/tiltShift.ts","../resources/js/filters/definitions/zoomBlur.ts","../resources/js/filters/definitions/colorGradient.ts","../resources/js/filters/definitions/colorMap.ts","../resources/js/filters/definitions/colorReplace.ts","../resources/js/filters/definitions/multiColorReplace.ts","../resources/js/filters/definitions/rgbSplit.ts","../resources/js/filters/definitions/advancedBloom.ts","../resources/js/filters/definitions/ascii.ts","../resources/js/filters/definitions/backdropBlur.ts","../resources/js/filters/definitions/bevel.ts","../resources/js/filters/definitions/bloom.ts","../resources/js/filters/definitions/bulgePinch.ts","../resources/js/filters/definitions/convolution.ts","../resources/js/filters/definitions/crossHatch.ts","../resources/js/filters/definitions/crt.ts","../resources/js/filters/definitions/displacement.ts","../resources/js/filters/definitions/dot.ts","../resources/js/filters/definitions/emboss.ts","../resources/js/filters/definitions/glitch.ts","../resources/js/filters/definitions/glow.ts","../resources/js/filters/definitions/godray.ts","../resources/js/filters/definitions/lightmap.ts","../resources/js/filters/definitions/noise.ts","../resources/js/filters/definitions/oldFilm.ts","../resources/js/filters/definitions/outline.ts","../resources/js/filters/definitions/pixelate.ts","../resources/js/filters/definitions/reflection.ts","../resources/js/filters/definitions/shockwave.ts","../resources/js/filters/definitions/simplexNoise.ts","../resources/js/filters/definitions/twist.ts","../resources/js/filters/definitions/vignette.ts","../resources/js/filters/index.ts"],"sourcesContent":["/**\n * Simple EventEmitter for vanilla JS\n * Provides pub/sub functionality without external dependencies\n */\nexport class EventEmitter {\n constructor() {\n this._events = new Map()\n }\n\n on(event, callback) {\n if (!this._events.has(event)) {\n this._events.set(event, new Set())\n }\n this._events.get(event).add(callback)\n return () => this.off(event, callback)\n }\n\n off(event, callback) {\n const listeners = this._events.get(event)\n if (listeners) {\n listeners.delete(callback)\n }\n }\n\n emit(event, ...args) {\n const listeners = this._events.get(event)\n if (listeners) {\n listeners.forEach(callback => {\n try {\n callback(...args)\n } catch (e) {\n console.error(`Error in event listener for ${event}:`, e)\n }\n })\n }\n }\n\n once(event, callback) {\n const wrapper = (...args) => {\n this.off(event, wrapper)\n callback(...args)\n }\n return this.on(event, wrapper)\n }\n\n removeAllListeners(event) {\n if (event) {\n this._events.delete(event)\n } else {\n this._events.clear()\n }\n }\n}\n","/**\n * Central state management for the vanilla image editor\n * Replaces Vue's reactivity system with a simple observable pattern\n */\nimport { EventEmitter } from './EventEmitter.js'\n\nexport const TEXT_LAYER_FONT_FAMILIES = Object.freeze([\n 'Inter',\n 'Arial',\n 'Helvetica',\n 'Georgia',\n 'Times New Roman',\n 'Courier New',\n 'Verdana',\n])\n\nconst TEXT_LAYER_BLEND_MODES = Object.freeze(['normal', 'multiply', 'screen', 'overlay'])\nconst DEFAULT_TEXT_BOX = Object.freeze({ x: 0.2, y: 0.2, width: 0.6, height: 0.18 })\nconst DEFAULT_TEXT_STYLE = Object.freeze({\n fontFamily: 'Inter',\n fontSize: 64,\n fontWeight: 700,\n fontStyle: 'normal',\n fill: '#ffffff',\n align: 'center',\n lineHeight: 1.2,\n letterSpacing: 0,\n})\nconst DEFAULT_TEXT_EFFECTS = Object.freeze({\n stroke: Object.freeze({ enabled: false, color: '#000000', width: 0 }),\n shadow: Object.freeze({ enabled: false, color: '#000000', alpha: 0.5, blur: 0, distance: 0, angle: 45 }),\n glow: Object.freeze({ enabled: false, color: '#ffffff', alpha: 0.5, blur: 0 }),\n backdrop: Object.freeze({ enabled: false, color: '#000000', opacity: 0.5, padding: 0, radius: 0, blur: 0 }),\n})\n\nexport class State extends EventEmitter {\n constructor() {\n super()\n this._state = {\n // Image state\n hasImage: false,\n imageUrl: null,\n\n // Mode state\n mode: 'filters', // 'filters' | 'crop'\n\n // View state\n zoom: 1,\n fitScale: 1,\n\n // Filter state\n activeFilters: new Set(),\n filterValues: {},\n selectedFilter: null,\n selectedCategory: 'adjust',\n\n // Crop state\n crop: {\n shape: 'free', // 'free' | 'square' | 'circle'\n aspect: 'free', // 'free' | '1:1' | '4:3' | '16:9' | '3:2' | '2:3'\n rect: null, // { x, y, width, height }\n dirty: false // true once the user changes the generated crop frame\n },\n\n // Transform state\n transform: {\n rotation: 0 // degrees clockwise, normalized to 0..359.999\n },\n\n // Layered editor document state (v2 document contract)\n editorDocument: null,\n editorDocumentId: null,\n editorDocumentRevisionId: null,\n editorDocumentRevisionNumber: null,\n layers: [],\n activeLayerId: null,\n\n // UI state\n theme: 'auto', // 'light' | 'dark' | 'auto'\n isDarkMode: false,\n backgroundRemovalAvailable: false,\n isProcessing: false,\n isSaving: false\n }\n }\n\n /**\n * Get a state value\n * @param {string} key - State key (supports dot notation: 'crop.shape')\n * @returns {*} The state value\n */\n get(key) {\n if (key.includes('.')) {\n const parts = key.split('.')\n let value = this._state\n for (const part of parts) {\n if (value === undefined || value === null) return undefined\n value = value[part]\n }\n return value\n }\n return this._state[key]\n }\n\n /**\n * Set a state value and emit change event\n * @param {string} key - State key (supports dot notation: 'crop.shape')\n * @param {*} value - New value\n */\n set(key, value) {\n const old = this.get(key)\n\n if (key.includes('.')) {\n const parts = key.split('.')\n const lastKey = parts.pop()\n let target = this._state\n for (const part of parts) {\n if (target[part] === undefined) target[part] = {}\n target = target[part]\n }\n target[lastKey] = value\n } else {\n this._state[key] = value\n }\n\n this.emit(`change:${key}`, { value, old })\n this.emit('change', { key, value, old })\n }\n\n /**\n * Get the entire state object (for debugging).\n * WARNING: Shallow copy only — nested objects are live references.\n * For persistence, use getSerializableState() instead.\n */\n getAll() {\n return { ...this._state }\n }\n\n /**\n * Deep clone a JSON-compatible editor payload.\n * @param {*} value\n * @returns {*}\n */\n _clonePlain(value) {\n if (value === null || value === undefined) return value\n return JSON.parse(JSON.stringify(value))\n }\n\n /**\n * Get a deep, serializable snapshot of the editor state.\n * Safe for persistence — no mutable references leak out.\n * @returns {Object} ImageEditorSessionState-compatible object\n */\n getSerializableState() {\n const filters = []\n if (this._state.activeFilters) {\n for (const filterId of this._state.activeFilters) {\n const values = this._state.filterValues[filterId]\n filters.push({\n id: filterId,\n enabled: true,\n values: values ? { ...values } : {}\n })\n }\n }\n\n const crop = this._state.crop\n return {\n version: 1,\n crop: {\n rect: crop?.rect ? { ...crop.rect } : null,\n aspectRatio: crop?.aspect || 'free',\n shape: crop?.shape || 'free'\n },\n transform: {\n rotation: Number(this._state.transform?.rotation) || 0\n },\n filters\n }\n }\n\n /**\n * Store the active immutable v2 editor document snapshot.\n * @param {Object|null} document\n * @param {{ documentId?: string|null, documentRevisionId?: string|null, documentRevisionNumber?: number|null }} binding\n */\n setEditorDocument(document, binding = {}) {\n if (!document || document.version !== 2 || !Array.isArray(document.layers)) {\n this.clearEditorDocument()\n return\n }\n\n const snapshot = this._clonePlain(document)\n const layers = this._clonePlain(snapshot.layers)\n .map(layer => this._normalizeLayerForState(layer))\n const activeLayerId = typeof snapshot.activeLayerId === 'string'\n ? snapshot.activeLayerId\n : (layers[0]?.id ?? null)\n\n this._state.editorDocument = {\n ...snapshot,\n layers,\n activeLayerId,\n }\n this._state.editorDocumentId = binding.documentId ?? snapshot.id ?? null\n this._state.editorDocumentRevisionId = binding.documentRevisionId ?? null\n this._state.editorDocumentRevisionNumber = binding.documentRevisionNumber ?? snapshot.revision ?? null\n this._state.layers = layers\n this._state.activeLayerId = activeLayerId\n\n this.emit('change:editorDocument', { value: this.getSerializableDocument() })\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:activeLayerId', { value: activeLayerId })\n this._syncFilterStateFromActiveLayer()\n }\n\n clearEditorDocument() {\n this._state.editorDocument = null\n this._state.editorDocumentId = null\n this._state.editorDocumentRevisionId = null\n this._state.editorDocumentRevisionNumber = null\n this._state.layers = []\n this._state.activeLayerId = null\n this._state.activeFilters = new Set()\n this._state.filterValues = {}\n this._state.selectedFilter = null\n this.emit('change:editorDocument', { value: null })\n this.emit('change:layers', { value: [] })\n this.emit('change:activeLayerId', { value: null })\n this.emit('change:activeFilters', { value: this._state.activeFilters })\n this.emit('change:filterValues', this._state.filterValues)\n this.emit('change:selectedFilter', { value: null })\n }\n\n /**\n * @returns {Object|null}\n */\n getSerializableDocument() {\n if (!this._state.editorDocument) return null\n\n const document = this._clonePlain(this._state.editorDocument)\n document.layers = this._clonePlain(this._state.layers)\n document.activeLayerId = this._state.activeLayerId\n\n // Fold the editor's transform/crop session state into the active subject\n // layer so the persisted document records the user-applied edits. The\n // editor tracks `_state.transform.rotation` and `_state.crop.applied*`\n // separately from per-layer state for renderer simplicity, but the\n // server-side document contract expects per-layer `transform.rotation`\n // and a per-layer `crop` payload. Without this fold, a user who rotated\n // or cropped would save a no-op edit (rotation: 0 / crop: null).\n const subjectIndex = document.layers.findIndex(layer => layer && (\n layer.role === 'subject' || (layer.type === 'image' && layer.role !== 'overlay')\n ))\n if (subjectIndex !== -1) {\n const subject = document.layers[subjectIndex]\n const rotation = this._normalizeDegrees(this._state.transform?.rotation ?? 0)\n const baseTransform = subject.transform && typeof subject.transform === 'object'\n ? subject.transform\n : { x: 0, y: 0, scaleX: 1, scaleY: 1, rotation: 0 }\n subject.transform = {\n ...baseTransform,\n rotation,\n }\n\n const cropState = this._state.crop && typeof this._state.crop === 'object' ? this._state.crop : null\n const appliedRect = cropState?.appliedRect && typeof cropState.appliedRect === 'object'\n ? cropState.appliedRect\n : null\n if (appliedRect) {\n subject.crop = {\n rect: { ...appliedRect },\n shape: cropState.appliedShape || 'free',\n aspect: cropState.appliedAspect || 'free',\n }\n }\n\n document.layers[subjectIndex] = subject\n }\n\n return document\n }\n\n /**\n * @returns {{ documentId: string|null, documentRevisionId: string|null, documentRevisionNumber: number|null }|null}\n */\n getEditorDocumentBinding() {\n if (!this._state.editorDocument) return null\n\n return {\n documentId: this._state.editorDocumentId,\n documentRevisionId: this._state.editorDocumentRevisionId,\n documentRevisionNumber: this._state.editorDocumentRevisionNumber,\n }\n }\n\n /**\n * @param {string} layerId\n * @returns {number}\n */\n _findLayerIndex(layerId) {\n return this._state.layers.findIndex(layer => layer?.id === layerId)\n }\n\n /**\n * @param {Object|null|undefined} layer\n * @returns {boolean}\n */\n _layerLocked(layer) {\n return layer?.locked === true\n }\n\n /**\n * @param {Object[]|null|undefined} layers\n * @returns {boolean}\n */\n _backgroundLayerLocked(layers = this._state.layers) {\n const index = this._backgroundLayerIndex(layers)\n return index !== -1 && this._layerLocked(layers[index])\n }\n\n /**\n * @returns {boolean}\n */\n isBackgroundLayerLocked() {\n return this._backgroundLayerLocked()\n }\n\n /**\n * @param {string} baseId\n * @returns {string}\n */\n _uniqueLayerId(baseId) {\n const existingIds = new Set(this._state.layers.map(layer => layer?.id).filter(Boolean))\n const safeBase = String(baseId || 'layer').replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || 'layer'\n if (!existingIds.has(safeBase)) return safeBase\n\n for (let suffix = 2; suffix < 10000; suffix += 1) {\n const candidate = `${safeBase}-${suffix}`\n if (!existingIds.has(candidate)) return candidate\n }\n\n return `${safeBase}-${Date.now()}`\n }\n\n /**\n * @param {Object|null|undefined} layer\n * @returns {Object|null|undefined}\n */\n _normalizeLayerForState(layer) {\n if (!layer || typeof layer !== 'object') return layer\n if (layer.type !== 'text' && layer.role !== 'text') {\n return {\n ...layer,\n filters: this._normalizeLayerFilters(layer.filters),\n }\n }\n\n return this._normalizeTextLayer({\n ...layer,\n id: typeof layer.id === 'string' && layer.id.trim() !== '' ? layer.id : this._uniqueLayerId('text-layer'),\n name: typeof layer.name === 'string' && layer.name.trim() !== '' ? layer.name : 'Text',\n }, layer)\n }\n\n /**\n * @param {Array|null|undefined} filters\n * @returns {Array}\n */\n _normalizeLayerFilters(filters) {\n if (!Array.isArray(filters)) return []\n\n return filters\n .filter(filter => filter && typeof filter === 'object' && typeof filter.id === 'string' && filter.id.trim() !== '')\n .map(filter => ({\n id: filter.id.trim(),\n enabled: filter.enabled !== false,\n values: filter.values && typeof filter.values === 'object'\n ? this._clonePlain(filter.values)\n : {},\n }))\n }\n\n /**\n * @param {Object|null|undefined} layer\n * @returns {boolean}\n */\n _layerSupportsFilters(layer) {\n if (!layer || typeof layer !== 'object') return false\n if (layer.type === 'image') return true\n if (layer.type === 'background' || layer.role === 'background') {\n return layer.fill?.kind === 'media'\n }\n\n return false\n }\n\n /**\n * @returns {number}\n */\n _activeFilterLayerIndex() {\n const activeLayerId = this._state.activeLayerId\n if (!activeLayerId || !Array.isArray(this._state.layers)) return -1\n\n const index = this._findLayerIndex(activeLayerId)\n return index !== -1 && this._layerSupportsFilters(this._state.layers[index]) ? index : -1\n }\n\n /**\n * @returns {string|null}\n */\n getActiveFilterLayerId() {\n const index = this._activeFilterLayerIndex()\n return index !== -1 ? this._state.layers[index]?.id ?? null : null\n }\n\n /**\n * @param {string|null|undefined} expectedLayerId\n * @returns {boolean}\n */\n _matchesExpectedFilterLayer(expectedLayerId) {\n if (!this._state.editorDocument) return true\n if (expectedLayerId === undefined) return true\n if (expectedLayerId === null) return this.getActiveFilterLayerId() === null\n\n const expected = typeof expectedLayerId === 'string' ? expectedLayerId.trim() : ''\n if (expected === '') return false\n\n return this.getActiveFilterLayerId() === expected\n }\n\n /**\n * Project the active filterable layer into the legacy filter UI state.\n */\n _syncFilterStateFromActiveLayer() {\n if (!this._state.editorDocument) return\n\n const index = this._activeFilterLayerIndex()\n const activeFilters = new Set()\n const filterValues = {}\n\n if (index !== -1) {\n for (const filter of this._normalizeLayerFilters(this._state.layers[index]?.filters)) {\n if (filter.enabled === false) continue\n activeFilters.add(filter.id)\n filterValues[filter.id] = this._clonePlain(filter.values || {})\n }\n }\n\n const oldSelectedFilter = this._state.selectedFilter\n this._state.activeFilters = activeFilters\n this._state.filterValues = filterValues\n if (oldSelectedFilter && !activeFilters.has(oldSelectedFilter)) {\n this._state.selectedFilter = null\n }\n\n this.emit('change:activeFilters', { value: this._state.activeFilters })\n this.emit('change:filterValues', this._state.filterValues)\n if (this._state.selectedFilter !== oldSelectedFilter) {\n this.emit('change:selectedFilter', { value: this._state.selectedFilter, old: oldSelectedFilter })\n }\n }\n\n /**\n * @param {*} value\n * @param {number} min\n * @param {number} max\n * @param {number} fallback\n * @returns {number}\n */\n _clampNumber(value, min, max, fallback) {\n const numeric = Number(value)\n if (!Number.isFinite(numeric)) return fallback\n\n return Math.max(min, Math.min(max, numeric))\n }\n\n /**\n * @param {*} value\n * @returns {number}\n */\n _normalizeDegrees(value) {\n const numeric = Number(value)\n if (!Number.isFinite(numeric)) return 0\n\n const normalized = numeric % 360\n return normalized < 0 ? normalized + 360 : normalized\n }\n\n /**\n * @param {*} value\n * @returns {boolean}\n */\n _isSupportedTextColor(value) {\n return typeof value === 'string' && /^#[0-9a-f]{6}$/i.test(value)\n }\n\n /**\n * @param {*} value\n * @param {string} fallback\n * @returns {string}\n */\n _normalizeTextColor(value, fallback) {\n return this._isSupportedTextColor(value)\n ? value\n : (this._isSupportedTextColor(fallback) ? fallback : '#000000')\n }\n\n /**\n * @param {*} value\n * @param {boolean} fallback\n * @returns {boolean}\n */\n _normalizeBoolean(value, fallback = false) {\n return typeof value === 'boolean' ? value : fallback === true\n }\n\n /**\n * @param {*} value\n * @param {string} fallback\n * @returns {string}\n */\n _normalizeBlendMode(value, fallback = 'normal') {\n if (TEXT_LAYER_BLEND_MODES.includes(value)) return value\n if (TEXT_LAYER_BLEND_MODES.includes(fallback)) return fallback\n\n return 'normal'\n }\n\n /**\n * @param {*} value\n * @returns {string}\n */\n _normalizeTextFontFamily(value) {\n const candidate = typeof value === 'string' ? value.trim() : ''\n return TEXT_LAYER_FONT_FAMILIES.includes(candidate) ? candidate : DEFAULT_TEXT_STYLE.fontFamily\n }\n\n /**\n * @param {*} value\n * @param {number} fallback\n * @returns {number}\n */\n _normalizeTextFontWeight(value, fallback = DEFAULT_TEXT_STYLE.fontWeight) {\n if (value === 'normal') return 400\n if (value === 'bold') return 700\n\n const numeric = Number(value)\n if (!Number.isFinite(numeric)) return fallback\n if (numeric < 100 || numeric > 900 || numeric % 100 !== 0) return fallback\n\n return numeric\n }\n\n /**\n * @param {Object|null|undefined} box\n * @param {Object|null|undefined} base\n * @returns {{ x: number, y: number, width: number, height: number }}\n */\n _normalizeTextBox(box, base = null) {\n const fallback = base && typeof base === 'object' ? base : DEFAULT_TEXT_BOX\n const source = box && typeof box === 'object' ? box : {}\n\n return {\n x: this._clampNumber(source.x, 0, 1, this._clampNumber(fallback.x, 0, 1, DEFAULT_TEXT_BOX.x)),\n y: this._clampNumber(source.y, 0, 1, this._clampNumber(fallback.y, 0, 1, DEFAULT_TEXT_BOX.y)),\n width: this._clampNumber(source.width, 0.05, 1, this._clampNumber(fallback.width, 0.05, 1, DEFAULT_TEXT_BOX.width)),\n height: this._clampNumber(source.height, 0.05, 1, this._clampNumber(fallback.height, 0.05, 1, DEFAULT_TEXT_BOX.height)),\n }\n }\n\n /**\n * @param {Object|null|undefined} style\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextStyle(style, base = null) {\n const fallback = {\n ...DEFAULT_TEXT_STYLE,\n ...(base && typeof base === 'object' ? base : {}),\n }\n const source = style && typeof style === 'object' ? style : {}\n const hasUnsupportedFontSource = !!source.fontSource || !!source.source || !!source.url\n const fontFamily = hasUnsupportedFontSource\n ? DEFAULT_TEXT_STYLE.fontFamily\n : this._normalizeTextFontFamily(source.fontFamily ?? fallback.fontFamily)\n const fontStyle = ['normal', 'italic'].includes(source.fontStyle)\n ? source.fontStyle\n : (['normal', 'italic'].includes(fallback.fontStyle) ? fallback.fontStyle : DEFAULT_TEXT_STYLE.fontStyle)\n const align = ['left', 'center', 'right'].includes(source.align)\n ? source.align\n : (['left', 'center', 'right'].includes(fallback.align) ? fallback.align : DEFAULT_TEXT_STYLE.align)\n const fill = this._isSupportedTextColor(source.fill)\n ? source.fill\n : (this._isSupportedTextColor(fallback.fill) ? fallback.fill : DEFAULT_TEXT_STYLE.fill)\n\n return {\n fontFamily,\n fontSize: this._clampNumber(source.fontSize, 8, 400, this._clampNumber(fallback.fontSize, 8, 400, DEFAULT_TEXT_STYLE.fontSize)),\n fontWeight: this._normalizeTextFontWeight(source.fontWeight, this._normalizeTextFontWeight(fallback.fontWeight, DEFAULT_TEXT_STYLE.fontWeight)),\n fontStyle,\n fill,\n align,\n lineHeight: this._clampNumber(source.lineHeight, 0.8, 3, this._clampNumber(fallback.lineHeight, 0.8, 3, DEFAULT_TEXT_STYLE.lineHeight)),\n letterSpacing: this._clampNumber(source.letterSpacing, -100, 100, this._clampNumber(fallback.letterSpacing, -100, 100, DEFAULT_TEXT_STYLE.letterSpacing)),\n }\n }\n\n /**\n * @param {Object|null|undefined} effects\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextEffects(effects, base = null) {\n const source = effects && typeof effects === 'object' ? effects : {}\n const baseEffects = base && typeof base === 'object' ? base : {}\n\n const fallback = {\n stroke: { ...DEFAULT_TEXT_EFFECTS.stroke, ...(baseEffects.stroke && typeof baseEffects.stroke === 'object' ? baseEffects.stroke : {}) },\n shadow: { ...DEFAULT_TEXT_EFFECTS.shadow, ...(baseEffects.shadow && typeof baseEffects.shadow === 'object' ? baseEffects.shadow : {}) },\n glow: { ...DEFAULT_TEXT_EFFECTS.glow, ...(baseEffects.glow && typeof baseEffects.glow === 'object' ? baseEffects.glow : {}) },\n backdrop: { ...DEFAULT_TEXT_EFFECTS.backdrop, ...(baseEffects.backdrop && typeof baseEffects.backdrop === 'object' ? baseEffects.backdrop : {}) },\n }\n const stroke = source.stroke && typeof source.stroke === 'object' ? source.stroke : {}\n const shadow = source.shadow && typeof source.shadow === 'object' ? source.shadow : {}\n const glow = source.glow && typeof source.glow === 'object' ? source.glow : {}\n const backdrop = source.backdrop && typeof source.backdrop === 'object' ? source.backdrop : {}\n\n return {\n stroke: {\n enabled: this._normalizeBoolean(stroke.enabled, fallback.stroke.enabled),\n color: this._normalizeTextColor(stroke.color, fallback.stroke.color),\n width: this._clampNumber(stroke.width, 0, 80, this._clampNumber(fallback.stroke.width, 0, 80, DEFAULT_TEXT_EFFECTS.stroke.width)),\n },\n shadow: {\n enabled: this._normalizeBoolean(shadow.enabled, fallback.shadow.enabled),\n color: this._normalizeTextColor(shadow.color, fallback.shadow.color),\n alpha: this._clampNumber(shadow.alpha, 0, 1, this._clampNumber(fallback.shadow.alpha, 0, 1, DEFAULT_TEXT_EFFECTS.shadow.alpha)),\n blur: this._clampNumber(shadow.blur, 0, 120, this._clampNumber(fallback.shadow.blur, 0, 120, DEFAULT_TEXT_EFFECTS.shadow.blur)),\n distance: this._clampNumber(shadow.distance, 0, 200, this._clampNumber(fallback.shadow.distance, 0, 200, DEFAULT_TEXT_EFFECTS.shadow.distance)),\n angle: this._normalizeDegrees(shadow.angle ?? fallback.shadow.angle ?? DEFAULT_TEXT_EFFECTS.shadow.angle),\n },\n glow: {\n enabled: this._normalizeBoolean(glow.enabled, fallback.glow.enabled),\n color: this._normalizeTextColor(glow.color, fallback.glow.color),\n alpha: this._clampNumber(glow.alpha, 0, 1, this._clampNumber(fallback.glow.alpha, 0, 1, DEFAULT_TEXT_EFFECTS.glow.alpha)),\n blur: this._clampNumber(glow.blur, 0, 120, this._clampNumber(fallback.glow.blur, 0, 120, DEFAULT_TEXT_EFFECTS.glow.blur)),\n },\n backdrop: {\n enabled: this._normalizeBoolean(backdrop.enabled, fallback.backdrop.enabled),\n color: this._normalizeTextColor(backdrop.color, fallback.backdrop.color),\n opacity: this._clampNumber(backdrop.opacity, 0, 1, this._clampNumber(fallback.backdrop.opacity, 0, 1, DEFAULT_TEXT_EFFECTS.backdrop.opacity)),\n padding: this._clampNumber(backdrop.padding, 0, 200, this._clampNumber(fallback.backdrop.padding, 0, 200, DEFAULT_TEXT_EFFECTS.backdrop.padding)),\n radius: this._clampNumber(backdrop.radius, 0, 200, this._clampNumber(fallback.backdrop.radius, 0, 200, DEFAULT_TEXT_EFFECTS.backdrop.radius)),\n blur: this._clampNumber(backdrop.blur, 0, 80, this._clampNumber(fallback.backdrop.blur, 0, 80, DEFAULT_TEXT_EFFECTS.backdrop.blur)),\n },\n }\n }\n\n /**\n * @param {Object|null|undefined} transform\n * @param {Object|null|undefined} base\n * @returns {{ x: number, y: number, scaleX: number, scaleY: number, rotation: number }}\n */\n _normalizeLayerTransform(transform, base = null) {\n const fallback = base && typeof base === 'object' ? base : {}\n const source = transform && typeof transform === 'object' ? transform : {}\n\n return {\n x: this._clampNumber(source.x, -100000, 100000, this._clampNumber(fallback.x, -100000, 100000, 0)),\n y: this._clampNumber(source.y, -100000, 100000, this._clampNumber(fallback.y, -100000, 100000, 0)),\n scaleX: this._clampNumber(source.scaleX, 0.01, 100, this._clampNumber(fallback.scaleX, 0.01, 100, 1)),\n scaleY: this._clampNumber(source.scaleY, 0.01, 100, this._clampNumber(fallback.scaleY, 0.01, 100, 1)),\n rotation: this._normalizeDegrees(source.rotation ?? fallback.rotation ?? 0),\n }\n }\n\n /**\n * @param {Object|null|undefined} input\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextPayload(input = {}, base = null) {\n const source = input && typeof input === 'object' ? input : {}\n const baseText = base?.text && typeof base.text === 'object' ? base.text : base\n const contentSource = source.content ?? source.text?.content ?? baseText?.content ?? 'Add text'\n const boxSource = source.box ?? source.text?.box\n const styleSource = source.style ?? source.text?.style\n const effectsSource = source.text?.effects ?? (source.effects && !Array.isArray(source.effects) ? source.effects : undefined)\n\n return {\n content: contentSource == null ? '' : String(contentSource),\n box: this._normalizeTextBox(boxSource, baseText?.box),\n style: this._normalizeTextStyle(styleSource, baseText?.style),\n effects: this._normalizeTextEffects(effectsSource, baseText?.effects),\n }\n }\n\n /**\n * @param {Object} input\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextLayer(input = {}, base = null) {\n const source = input && typeof input === 'object' ? input : {}\n\n return {\n id: typeof source.id === 'string' && source.id.trim() !== '' ? source.id : this._uniqueLayerId('text-layer'),\n type: 'text',\n role: 'text',\n name: typeof source.name === 'string' && source.name.trim() !== '' ? source.name.trim() : 'Text',\n visible: source.visible === false ? false : true,\n locked: source.locked === true,\n opacity: this._clampNumber(source.opacity, 0, 1, 1),\n blendMode: this._normalizeBlendMode(source.blendMode, base?.blendMode),\n transform: this._normalizeLayerTransform(source.transform, base?.transform),\n effects: Array.isArray(source.effects) ? this._clonePlain(source.effects) : [],\n metadata: source.metadata && typeof source.metadata === 'object' ? this._clonePlain(source.metadata) : {},\n text: this._normalizeTextPayload(source, base),\n crop: null,\n filters: Array.isArray(source.filters) ? this._clonePlain(source.filters) : [],\n }\n }\n\n /**\n * @param {Object[]} layers\n * @param {number} removedIndex\n * @returns {string|null}\n */\n _nearestEditableLayerId(layers, removedIndex) {\n if (!layers.length) return null\n\n for (let distance = 0; distance < layers.length; distance += 1) {\n const nextIndex = removedIndex + distance\n if (nextIndex < layers.length && !this._layerLocked(layers[nextIndex]) && layers[nextIndex]?.visible !== false) {\n return layers[nextIndex].id ?? null\n }\n\n const previousIndex = removedIndex - distance - 1\n if (previousIndex >= 0 && !this._layerLocked(layers[previousIndex]) && layers[previousIndex]?.visible !== false) {\n return layers[previousIndex].id ?? null\n }\n }\n\n return null\n }\n\n /**\n * @param {Object[]} layers\n * @param {number} fromIndex\n * @param {number} toIndex\n * @returns {boolean}\n */\n _moveCrossesLockedLayer(layers, fromIndex, toIndex) {\n const start = Math.min(fromIndex, toIndex)\n const end = Math.max(fromIndex, toIndex)\n\n for (let index = start; index <= end; index += 1) {\n if (index === fromIndex) continue\n if (this._layerLocked(layers[index])) return true\n }\n\n return false\n }\n\n /**\n * @param {string} layerId\n * @returns {Object|null}\n */\n getLayer(layerId) {\n const layer = this._state.layers.find(candidate => candidate?.id === layerId)\n return layer ? this._clonePlain(layer) : null\n }\n\n /**\n * @param {string|null} layerId\n * @returns {boolean}\n */\n setActiveLayer(layerId) {\n if (layerId !== null && this._findLayerIndex(layerId) === -1) {\n return false\n }\n\n const old = this._state.activeLayerId\n this._state.activeLayerId = layerId\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = layerId\n }\n this.emit('change:activeLayerId', { value: layerId, old })\n this._syncFilterStateFromActiveLayer()\n\n return true\n }\n\n /**\n * @returns {boolean}\n */\n isActiveLayerLocked() {\n const activeLayerId = this._state.activeLayerId\n if (!activeLayerId) return false\n\n const activeLayer = this._state.layers.find(layer => layer?.id === activeLayerId)\n return !!activeLayer?.locked\n }\n\n /**\n * @param {string} layerId\n * @param {boolean} visible\n * @returns {boolean}\n */\n setLayerVisibility(layerId, visible) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n layers[index].visible = !!visible\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:layerVisibility', { layerId, visible: !!visible })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {string} name\n * @returns {boolean}\n */\n renameLayer(layerId, name) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n const nextName = String(name ?? '').trim()\n if (nextName === '') return false\n\n const oldName = layers[index].name ?? ''\n layers[index].name = nextName\n this._commitLayers(layers, 'change:layerRenamed', { layerId, name: nextName, oldName })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @returns {string|null}\n */\n duplicateLayer(layerId) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return null\n\n const layers = this._clonePlain(this._state.layers)\n const sourceLayer = layers[index]\n if (this._layerLocked(sourceLayer)) return null\n\n const duplicate = this._clonePlain(sourceLayer)\n duplicate.id = this._uniqueLayerId(`${sourceLayer.id || 'layer'}-copy`)\n duplicate.name = `${String(sourceLayer.name || 'Layer').trim() || 'Layer'} copy`\n duplicate.locked = false\n duplicate.metadata = {\n ...(duplicate.metadata && typeof duplicate.metadata === 'object' ? duplicate.metadata : {}),\n duplicatedFromLayerId: sourceLayer.id ?? null,\n duplicatedAt: new Date().toISOString(),\n }\n\n layers.splice(index + 1, 0, duplicate)\n const oldActiveLayerId = this._state.activeLayerId\n this._state.activeLayerId = duplicate.id\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = duplicate.id\n }\n\n this._commitLayers(layers, 'change:layerDuplicated', { layerId, duplicateLayerId: duplicate.id })\n this.emit('change:activeLayerId', { value: duplicate.id, old: oldActiveLayerId })\n\n return duplicate.id\n }\n\n /**\n * @param {string} layerId\n * @returns {boolean}\n */\n deleteLayer(layerId) {\n const index = this._findLayerIndex(layerId)\n if (index === -1 || this._state.layers.length <= 1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n const [removed] = layers.splice(index, 1)\n let nextActiveLayerId = this._state.activeLayerId\n if (nextActiveLayerId === layerId || !layers.some(layer => layer?.id === nextActiveLayerId)) {\n nextActiveLayerId = this._nearestEditableLayerId(layers, index)\n const oldActiveLayerId = this._state.activeLayerId\n this._state.activeLayerId = nextActiveLayerId\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = nextActiveLayerId\n }\n this.emit('change:activeLayerId', { value: nextActiveLayerId, old: oldActiveLayerId })\n }\n\n this._commitLayers(layers, 'change:layerDeleted', { layerId: removed?.id ?? layerId })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {'up'|'down'|'front'|'back'|'bring-forward'|'send-backward'|'bring-to-front'|'send-to-back'} direction\n * @returns {boolean}\n */\n moveLayer(layerId, direction) {\n const fromIndex = this._findLayerIndex(layerId)\n if (fromIndex === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[fromIndex])) return false\n\n let toIndex = fromIndex\n switch (direction) {\n case 'up':\n case 'bring-forward':\n toIndex = Math.min(layers.length - 1, fromIndex + 1)\n break\n case 'down':\n case 'send-backward':\n toIndex = Math.max(0, fromIndex - 1)\n break\n case 'front':\n case 'bring-to-front':\n toIndex = layers.length - 1\n break\n case 'back':\n case 'send-to-back':\n toIndex = 0\n break\n default:\n return false\n }\n\n if (toIndex === fromIndex) return false\n if (this._moveCrossesLockedLayer(layers, fromIndex, toIndex)) return false\n\n const [layer] = layers.splice(fromIndex, 1)\n layers.splice(toIndex, 0, layer)\n this._commitLayers(layers, 'change:layerMoved', { layerId, fromIndex, toIndex, direction })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {boolean} locked\n * @returns {boolean}\n */\n setLayerLocked(layerId, locked) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n layers[index].locked = !!locked\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:layerLocked', { layerId, locked: !!locked })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {Object} source\n * @returns {boolean}\n */\n replaceLayerSource(layerId, source) {\n const index = this._findLayerIndex(layerId)\n if (index === -1 || !source || typeof source !== 'object') return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n layers[index].source = this._clonePlain(source)\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n this._state.editorDocument.updatedAt = new Date().toISOString()\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:layerSource', { layerId, source: this._clonePlain(source) })\n\n return true\n }\n\n /**\n * @param {Object} payload\n * @returns {string|null}\n */\n addTextLayer(payload = {}) {\n if (!this._state.editorDocument || !Array.isArray(this._state.layers)) {\n return null\n }\n\n const layers = this._clonePlain(this._state.layers)\n const layer = this._normalizeTextLayer({\n ...(payload && typeof payload === 'object' ? payload : {}),\n id: this._uniqueLayerId(payload?.id || 'text-layer'),\n })\n\n layers.push(layer)\n const oldActiveLayerId = this._state.activeLayerId\n this._state.activeLayerId = layer.id\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = layer.id\n }\n\n this._commitLayers(layers, 'change:textLayer', { action: 'created', layerId: layer.id })\n this.emit('change:activeLayerId', { value: layer.id, old: oldActiveLayerId })\n\n return layer.id\n }\n\n /**\n * @param {string} layerId\n * @param {Object} patch\n * @returns {boolean}\n */\n updateTextLayer(layerId, patch = {}) {\n const index = this._findLayerIndex(layerId)\n if (index === -1 || !patch || typeof patch !== 'object') return false\n\n const layers = this._clonePlain(this._state.layers)\n const layer = layers[index]\n if (this._layerLocked(layer) || (layer.type !== 'text' && layer.role !== 'text')) {\n return false\n }\n\n const textPatch = patch.text && typeof patch.text === 'object' ? patch.text : {}\n const nextLayer = this._normalizeTextLayer({\n ...layer,\n transform: patch.transform && typeof patch.transform === 'object'\n ? { ...layer.transform, ...patch.transform }\n : layer.transform,\n text: {\n ...(layer.text && typeof layer.text === 'object' ? layer.text : {}),\n ...textPatch,\n ...('content' in patch ? { content: patch.content } : {}),\n ...('box' in patch ? { box: patch.box } : {}),\n ...('style' in patch ? { style: { ...(layer.text?.style || {}), ...(patch.style || {}) } } : {}),\n ...('effects' in patch ? { effects: patch.effects } : {}),\n },\n ...(patch.name !== undefined ? { name: patch.name } : {}),\n ...(patch.opacity !== undefined ? { opacity: patch.opacity } : {}),\n ...(patch.blendMode !== undefined ? { blendMode: patch.blendMode } : {}),\n }, layer)\n\n layers[index] = nextLayer\n this._commitLayers(layers, 'change:textLayer', {\n action: 'updated',\n layerId,\n text: this._clonePlain(nextLayer.text),\n })\n\n return true\n }\n\n _commitLayers(layers, eventName = null, eventPayload = {}) {\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n this._state.editorDocument.updatedAt = new Date().toISOString()\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n if (eventName) {\n this.emit(eventName, eventPayload)\n }\n }\n\n _backgroundLayerIndex(layers = this._state.layers) {\n return layers.findIndex(layer => layer?.type === 'background' || layer?.role === 'background')\n }\n\n _defaultBackgroundLayer(fill = { kind: 'transparent' }) {\n const existingIds = new Set(this._state.layers.map(layer => layer?.id).filter(Boolean))\n let id = 'background-layer'\n if (existingIds.has(id)) {\n id = `background-layer-${Date.now()}`\n }\n\n return {\n id,\n type: 'background',\n role: 'background',\n name: 'Background',\n visible: true,\n locked: false,\n opacity: 1,\n blendMode: 'normal',\n transform: { x: 0, y: 0, scaleX: 1, scaleY: 1, rotation: 0 },\n effects: [],\n metadata: {},\n fill: this._clonePlain(fill),\n crop: null,\n filters: [],\n }\n }\n\n _normalizeBackgroundFill(fill) {\n if (!fill || typeof fill !== 'object') {\n return { kind: 'transparent' }\n }\n\n const fit = ['cover', 'contain', 'stretch', 'tile'].includes(fill.fit) ? fill.fit : undefined\n if (fill.kind === 'color') {\n return {\n kind: 'color',\n value: typeof fill.value === 'string' ? fill.value : (typeof fill.color === 'string' ? fill.color : '#ffffff'),\n ...(fit ? { fit } : {}),\n }\n }\n\n if (fill.kind === 'gradient') {\n const stops = Array.isArray(fill.stops) && fill.stops.length > 0\n ? fill.stops\n .filter(stop => stop && typeof stop === 'object' && typeof stop.color === 'string')\n .map(stop => ({\n offset: Number.isFinite(Number(stop.offset)) ? Math.max(0, Math.min(1, Number(stop.offset))) : 0,\n color: stop.color,\n }))\n : [\n { offset: 0, color: '#111827' },\n { offset: 1, color: '#f59e0b' },\n ]\n\n return {\n kind: 'gradient',\n gradientType: ['linear', 'radial'].includes(fill.gradientType) ? fill.gradientType : 'linear',\n angle: Number.isFinite(Number(fill.angle)) ? Number(fill.angle) : 135,\n stops,\n fit: fit || 'cover',\n }\n }\n\n if (fill.kind === 'media' && fill.source && typeof fill.source === 'object') {\n return {\n kind: 'media',\n source: this._clonePlain(fill.source),\n fit: fit || 'cover',\n }\n }\n\n return { kind: 'transparent' }\n }\n\n ensureBackgroundLayer(fill = { kind: 'transparent' }) {\n const layers = this._clonePlain(this._state.layers)\n const existingIndex = this._backgroundLayerIndex(layers)\n if (existingIndex !== -1) {\n if (this._layerLocked(layers[existingIndex])) return null\n return layers[existingIndex].id\n }\n\n const layer = this._defaultBackgroundLayer(this._normalizeBackgroundFill(fill))\n const firstSubjectIndex = layers.findIndex(candidate => candidate?.role === 'subject' || candidate?.type === 'image')\n const insertAt = firstSubjectIndex >= 0 ? firstSubjectIndex : 0\n layers.splice(insertAt, 0, layer)\n this._commitLayers(layers, 'change:backgroundLayer', { layerId: layer.id, action: 'created' })\n\n return layer.id\n }\n\n setBackgroundFill(fill) {\n const normalizedFill = this._normalizeBackgroundFill(fill)\n const layerId = this.ensureBackgroundLayer(normalizedFill)\n if (!layerId) return null\n\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return null\n if (this._layerLocked(layers[index])) return null\n\n const previousFit = layers[index].fill?.fit\n layers[index].fill = this._clonePlain({\n ...normalizedFill,\n ...(\n !normalizedFill.fit && previousFit && normalizedFill.kind !== 'transparent'\n ? { fit: previousFit }\n : {}\n ),\n })\n this._commitLayers(layers, 'change:backgroundFill', { layerId, fill: this._clonePlain(layers[index].fill) })\n\n return layerId\n }\n\n setBackgroundFit(fit) {\n if (!['cover', 'contain', 'stretch', 'tile'].includes(fit)) {\n return false\n }\n\n const layerId = this.ensureBackgroundLayer()\n if (!layerId) return false\n\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return false\n if (this._layerLocked(layers[index])) return false\n\n const fill = layers[index].fill && typeof layers[index].fill === 'object'\n ? layers[index].fill\n : { kind: 'transparent' }\n layers[index].fill = { ...fill, fit }\n this._commitLayers(layers, 'change:backgroundFit', { layerId, fit })\n\n return true\n }\n\n setBackgroundBlur(amount) {\n const numericAmount = Number.isFinite(Number(amount)) ? Math.max(0, Math.min(100, Number(amount))) : 0\n const layerId = this.ensureBackgroundLayer()\n if (!layerId) return false\n\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return false\n if (this._layerLocked(layers[index])) return false\n\n const effects = Array.isArray(layers[index].effects)\n ? layers[index].effects.filter(effect => effect?.id !== 'background-blur')\n : []\n if (numericAmount > 0) {\n effects.push({\n id: 'background-blur',\n type: 'blur',\n params: { amount: numericAmount },\n })\n }\n layers[index].effects = effects\n this._commitLayers(layers, 'change:backgroundBlur', { layerId, amount: numericAmount })\n\n return true\n }\n\n removeBackgroundLayer() {\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return false\n if (this._layerLocked(layers[index])) return false\n\n const [removed] = layers.splice(index, 1)\n if (removed?.id && this._state.activeLayerId === removed.id) {\n const nextActive = this._nearestEditableLayerId(layers, index)\n this._state.activeLayerId = nextActive\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = nextActive\n }\n this.emit('change:activeLayerId', { value: nextActive, old: removed.id })\n }\n\n this._commitLayers(layers, 'change:backgroundLayer', { layerId: removed?.id ?? null, action: 'removed' })\n\n return true\n }\n\n /**\n * Toggle a filter in the active filters set\n * @param {string} filterId\n * @param {boolean} enabled\n */\n toggleFilter(filterId, enabled, expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const index = this._activeFilterLayerIndex()\n if (index === -1) {\n this._syncFilterStateFromActiveLayer()\n return false\n }\n\n const id = typeof filterId === 'string' ? filterId.trim() : ''\n if (id === '') return false\n\n const layers = this._clonePlain(this._state.layers)\n const layer = layers[index]\n const filters = this._normalizeLayerFilters(layer.filters)\n const existingIndex = filters.findIndex(filter => filter.id === id)\n\n if (enabled) {\n if (existingIndex === -1) {\n filters.push({ id, enabled: true, values: {} })\n } else {\n filters[existingIndex].enabled = true\n }\n } else if (existingIndex !== -1) {\n filters.splice(existingIndex, 1)\n }\n\n layer.filters = filters\n this._commitLayers(layers, 'change:layerFilters', {\n layerId: layer.id,\n filterId: id,\n enabled: !!enabled,\n })\n this._syncFilterStateFromActiveLayer()\n\n return true\n }\n\n const filters = new Set(this._state.activeFilters)\n if (enabled) {\n filters.add(filterId)\n } else {\n filters.delete(filterId)\n delete this._state.filterValues[filterId]\n }\n this.set('activeFilters', filters)\n\n return true\n }\n\n /**\n * Update a filter's control value\n * @param {string} filterId\n * @param {string} controlId\n * @param {*} value\n */\n setFilterValue(filterId, controlId, value, expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const index = this._activeFilterLayerIndex()\n if (index === -1) {\n this._syncFilterStateFromActiveLayer()\n return false\n }\n\n const id = typeof filterId === 'string' ? filterId.trim() : ''\n if (id === '' || !this._state.activeFilters?.has?.(id)) return false\n\n const layers = this._clonePlain(this._state.layers)\n const layer = layers[index]\n const filters = this._normalizeLayerFilters(layer.filters)\n const filterIndex = filters.findIndex(filter => filter.id === id && filter.enabled !== false)\n if (filterIndex === -1) return false\n\n filters[filterIndex].values = {\n ...(filters[filterIndex].values && typeof filters[filterIndex].values === 'object' ? filters[filterIndex].values : {}),\n [controlId]: this._clonePlain(value),\n }\n layer.filters = filters\n this._commitLayers(layers, 'change:layerFilters', {\n layerId: layer.id,\n filterId: id,\n controlId,\n value: this._clonePlain(value),\n })\n this._syncFilterStateFromActiveLayer()\n this.emit('change:filterValue', { filterId: id, controlId, value })\n\n return true\n }\n\n if (!this._state.filterValues[filterId]) {\n this._state.filterValues[filterId] = {}\n }\n this._state.filterValues[filterId][controlId] = value\n this.emit('change:filterValue', { filterId, controlId, value })\n this.emit('change:filterValues', this._state.filterValues)\n\n return true\n }\n\n /**\n * Get a filter's control values\n * @param {string} filterId\n * @returns {Object} Filter values\n */\n getFilterValues(filterId) {\n return this._state.filterValues[filterId] || {}\n }\n\n /**\n * Initialize filter values from definition defaults\n * @param {string} filterId\n * @param {Array} controls - Control definitions with defaults\n */\n initFilterValues(filterId, controls, expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const existing = this.getFilterValues(filterId)\n controls.forEach(ctl => {\n if (!(ctl.id in existing)) {\n this.setFilterValue(filterId, ctl.id, ctl.default, expectedLayerId)\n }\n })\n return true\n }\n\n if (!this._state.filterValues[filterId]) {\n this._state.filterValues[filterId] = {}\n }\n controls.forEach(ctl => {\n if (!(ctl.id in this._state.filterValues[filterId])) {\n this._state.filterValues[filterId][ctl.id] = ctl.default\n }\n })\n this.emit('change:filterValues', this._state.filterValues)\n\n return true\n }\n\n /**\n * Reset all filters\n */\n resetFilters(expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const index = this._activeFilterLayerIndex()\n if (index === -1) {\n this._syncFilterStateFromActiveLayer()\n this.emit('filtersReset')\n return false\n }\n\n const layers = this._clonePlain(this._state.layers)\n layers[index].filters = []\n this._commitLayers(layers, 'change:layerFilters', {\n layerId: layers[index].id,\n action: 'reset',\n })\n this._syncFilterStateFromActiveLayer()\n this.emit('filtersReset')\n\n return true\n }\n\n this._state.activeFilters = new Set()\n this._state.filterValues = {}\n this._state.selectedFilter = null\n this.emit('change:activeFilters', { value: this._state.activeFilters })\n this.emit('change:filterValues', this._state.filterValues)\n this.emit('change:selectedFilter', { value: null })\n this.emit('filtersReset')\n\n return true\n }\n\n /**\n * Detect and set dark mode based on preference\n */\n detectTheme() {\n if (this._state.theme === 'auto') {\n const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches\n this.set('isDarkMode', prefersDark)\n } else {\n this.set('isDarkMode', this._state.theme === 'dark')\n }\n }\n}\n\n// Singleton instance\nlet instance = null\n\nexport function getState() {\n if (!instance) {\n instance = new State()\n }\n return instance\n}\n\nexport function createState() {\n return new State()\n}\n","/**\n * Filter Registry System\n * Centralized storage and management for filter definitions\n */\n// Since we can't directly import Filter, use any for now\n// and let the type system infer from usage\ntype Filter = any;\n\n/**\n * Interface for a filter control definition \n * Defines the UI representation of a filter parameter\n */\nexport interface ControlDefinition {\n id: string;\n type: 'slider' | 'toggle' | 'color' | 'select' | 'range' | 'button' | 'text';\n label: string;\n property?: string;\n action?: string;\n min?: number;\n max?: number;\n step?: number;\n default?: number | boolean | string;\n options?: Array<{ label: string; value: string | number }>;\n tooltip?: string;\n /** Placeholder text for 'text' type controls. */\n placeholder?: string;\n /** Hide this control from the UI without removing it from the definition. */\n hidden?: boolean;\n}\n\nexport type FilterMediaTarget = 'image' | 'video';\n\n/**\n * Interface for a filter definition\n * Contains all metadata needed to create and manage a filter\n */\nexport interface FilterDefinition {\n id: string;\n name: string;\n category: string;\n description?: string;\n thumbnail?: string;\n /**\n * Optional media compatibility tags.\n * Omitted means compatible with both image and video pipelines.\n */\n mediaTargets?: FilterMediaTarget[];\n createFilter: (params: Record<string, any>) => Filter;\n defaultParams: Record<string, any>;\n controls: ControlDefinition[];\n}\n\n// Filter registry storage\nconst filters = new Map<string, FilterDefinition>();\n\n// Category registry storage\nconst categories = new Map<string, string[]>();\n\nfunction isMediaCompatible(\n definition: FilterDefinition,\n target: FilterMediaTarget\n): boolean {\n if (!Array.isArray(definition.mediaTargets) || definition.mediaTargets.length === 0) {\n return true;\n }\n\n return definition.mediaTargets.includes(target);\n}\n\n/**\n * Register a filter in the global registry\n * @param definition The filter definition to register\n * @returns The provided filter definition (for chaining)\n */\nexport function registerFilter(definition: FilterDefinition): FilterDefinition {\n // Ensure the filter has a unique ID\n if (filters.has(definition.id)) {\n console.warn(`Filter with ID ${definition.id} already exists. Overwriting.`);\n }\n \n // Store the filter definition\n filters.set(definition.id, definition);\n \n // Add to category registry\n if (!categories.has(definition.category)) {\n categories.set(definition.category, []);\n }\n categories.get(definition.category)?.push(definition.id);\n \n return definition;\n}\n\n/**\n * Get a filter definition by ID\n * @param id The ID of the filter to retrieve\n * @returns The filter definition or undefined if not found\n */\nexport function getFilter(id: string): FilterDefinition | undefined {\n return filters.get(id);\n}\n\n/**\n * Get all registered filter definitions\n * @returns Array of all registered filter definitions\n */\nexport function getAllFilters(): FilterDefinition[] {\n return Array.from(filters.values());\n}\n\n/**\n * NEW: Bulk-register all classes re-exported by the `pixi-filters` bundle.\n * – Keeps bundle size reasonable (tree-shaken in prod)\n * – Lets you use *any* filter without first writing boilerplate\n */\nimport * as PixiFilters from 'pixi-filters';\n\n/**\n * Register all core PixiJS filters if they don't already have custom definitions,\n * but only using the actual custom definitions from their respective files.\n */\nexport function registerCorePixiFilters(): void {\n // Get the filters that are already loaded\n const customFilterIds = getAllFilters().map(f => f.id);\n \n // Get all available PixiJS filters from the pixi-filters package\n type FilterConstructor = new (...args: unknown[]) => unknown\n\n const pixiFilterEntries = Object.entries(PixiFilters) as Array<[string, unknown]>\n\n const pixiFilterClasses = pixiFilterEntries.filter(\n (entry): entry is [string, FilterConstructor] => /Filter$/.test(entry[0]) && typeof entry[1] === 'function'\n );\n \n // Reduce logging in production\n if (import.meta.env.DEV) {\n // Only log filter count, not the entire list\n console.log(`Found ${customFilterIds.length} custom filters and ${pixiFilterClasses.length} PixiJS filters`);\n }\n \n // We'll ONLY register core filters where we DON'T have a custom definition\n // This is intentionally minimalist to ensure we prioritize custom definitions\n let newlyRegisteredCount = 0;\n \n pixiFilterClasses.forEach(([exportName, FilterClass]) => {\n const id = exportName\n .replace(/Filter$/, '')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase();\n \n // Skip if this filter already has a custom definition\n if (filters.has(id)) {\n return;\n }\n \n // For remaining filters without custom definitions, just provide a minimal registration\n // that just allows the filter to be created but doesn't provide any controls\n // Reduce verbose logging in production\n if (import.meta.env.DEV) {\n console.debug(`Registering minimal entry for ${exportName}`);\n }\n newlyRegisteredCount++;\n \n // Register with minimal information - these won't appear in the UI properly\n // but will be available for debugging or programmatic use\n registerFilter({\n id,\n name: exportName.replace(/Filter$/, ''),\n category: 'unlisted', // Put in a category that won't be shown in UI\n mediaTargets: ['image'],\n defaultParams: {},\n controls: [], // No controls - we don't want to add generic controls\n createFilter: (params = {}) => {\n try {\n // Simply create the filter with params\n return new FilterClass(params);\n } catch (error) {\n console.error(`Error creating filter ${id}:`, error);\n return null;\n }\n },\n });\n });\n \n // Only log in development environment\n if (import.meta.env.DEV && newlyRegisteredCount > 0) {\n console.log(`Registered ${newlyRegisteredCount} additional filters`);\n }\n}\n\n// We will NOT auto-register at module load. \n// Instead, custom filter definitions will be loaded first, then we'll only register missing ones.\n// The actual registration happens when initializeFilterRegistry is called.\n\n/**\n * Get all filters in a specific category\n * @param category The category to retrieve filters for\n * @returns Array of filter definitions in the requested category\n */\nexport function getFiltersByCategory(category: string): FilterDefinition[] {\n const filterIds = categories.get(category) || [];\n return filterIds.map(id => filters.get(id)).filter(Boolean) as FilterDefinition[];\n}\n\n/**\n * Get all filter categories\n * @returns Array of category names\n */\nexport function getAllCategories(): string[] {\n return Array.from(categories.keys());\n}\n\n/**\n * Check if a filter is registered\n * @param id The ID of the filter to check\n * @returns True if the filter is registered, false otherwise\n */\nexport function hasFilter(id: string): boolean {\n return filters.has(id);\n}\n\n/**\n * Remove a filter from the registry.\n * @param id The ID of the filter to remove\n * @returns True if the filter was found and removed\n */\nexport function unregisterFilter(id: string): boolean {\n const definition = filters.get(id);\n if (!definition) {\n return false;\n }\n\n filters.delete(id);\n\n // Remove from category index\n const categoryIds = categories.get(definition.category);\n if (categoryIds) {\n const idx = categoryIds.indexOf(id);\n if (idx !== -1) {\n categoryIds.splice(idx, 1);\n }\n if (categoryIds.length === 0) {\n categories.delete(definition.category);\n }\n }\n\n return true;\n}\n\n/**\n * Check whether a registered filter is compatible with a media target.\n * Unknown filters are treated as incompatible.\n */\nexport function isFilterCompatibleWithMedia(\n id: string,\n target: FilterMediaTarget\n): boolean {\n const definition = filters.get(id);\n if (!definition) {\n return false;\n }\n\n return isMediaCompatible(definition, target);\n}\n\n/**\n * Return all registered filters compatible with the given media target.\n */\nexport function getFiltersByMedia(target: FilterMediaTarget): FilterDefinition[] {\n return Array.from(filters.values()).filter((definition) => isMediaCompatible(definition, target));\n}\n\n/**\n * Get all registered filters with simplified format for UI\n * @returns Array of filter definitions with only UI-relevant properties\n */\nexport function getRegisteredFilters(): Array<{\n id: string;\n name: string;\n category: string;\n controls: ControlDefinition[];\n}> {\n return Array.from(filters.values()).map(filter => ({\n id: filter.id,\n name: filter.name,\n category: filter.category,\n controls: filter.controls\n }));\n}\n\n// Add a debug function to expose filter registry in window\nif (typeof window !== 'undefined') {\n // Store filter list in window for debugging\n (window as any).__DEBUG_FILTERS_LIST = Array.from(filters.keys());\n \n // Expose registry functions for debugging\n (window as any).getAllFilters = getAllFilters;\n (window as any).getFilter = getFilter;\n (window as any).getFiltersByCategory = getFiltersByCategory;\n (window as any).getRegisteredFilters = getRegisteredFilters;\n \n // Update the debug list whenever a new filter is registered\n const originalRegisterFilter = registerFilter;\n (window as any).registerFilter = (definition: FilterDefinition) => {\n const result = originalRegisterFilter(definition);\n (window as any).__DEBUG_FILTERS_LIST = Array.from(filters.keys());\n console.log(`Filter \"${definition.id}\" registered. Total filters: ${filters.size}`);\n return result;\n };\n \n // Remove this console log - it's causing duplicate logging\n // if (process.env.NODE_ENV !== 'production') {\n // console.log(`Registry initialized with ${filters.size} filters`);\n // }\n}\n\n// Add a safety check for initializeFilterRegistry in case it's not working\n// This is a fallback in case the main implementation is facing issues\nif (typeof window !== 'undefined') {\n (window as any).initializeFilterRegistry = (window as any).initializeFilterRegistry || function() {\n console.warn('Using fallback window.initializeFilterRegistry');\n return [];\n };\n}\n","/**\n * Adjustment Filter Definition\n * Controls basic image adjustments like brightness, contrast, saturation, etc.\n */\nimport { registerFilter } from '../registry';\n// Import the AdjustmentFilter directly from the pixi-filters package\nimport * as PixiFilters from 'pixi-filters';\n// Access AdjustmentFilter from the pixi-filters package\nconst { AdjustmentFilter } = PixiFilters;\n\n// Import ColorMatrixFilter as fallback\nimport * as PIXI from 'pixi.js';\n// Access ColorMatrixFilter from pixi.js package\nconst { ColorMatrixFilter } = PIXI;\n\ninterface AdjustmentParams {\n gamma: number;\n saturation: number;\n contrast: number;\n brightness: number;\n red: number;\n green: number;\n blue: number;\n alpha: number;\n}\n\ntype AdjustmentParamKey = keyof AdjustmentParams;\n\nconst DEFAULT_ADJUSTMENT_PARAMS: AdjustmentParams = {\n gamma: 1,\n saturation: 1,\n contrast: 1,\n brightness: 1,\n red: 1,\n green: 1,\n blue: 1,\n alpha: 1,\n};\n\nconst ADJUSTMENT_PARAM_KEYS = new Set<AdjustmentParamKey>([\n 'gamma',\n 'saturation',\n 'contrast',\n 'brightness',\n 'red',\n 'green',\n 'blue',\n 'alpha',\n]);\n\nfunction toFiniteNumber(value: unknown, fallback: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value === 'string') {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n\n return fallback;\n}\n\nfunction isAdjustmentParamKey(key: string): key is AdjustmentParamKey {\n return ADJUSTMENT_PARAM_KEYS.has(key as AdjustmentParamKey);\n}\n\nfunction normalizeAdjustmentParams(params: Record<string, unknown>): AdjustmentParams {\n return {\n gamma: toFiniteNumber(params.gamma, DEFAULT_ADJUSTMENT_PARAMS.gamma),\n saturation: toFiniteNumber(params.saturation, DEFAULT_ADJUSTMENT_PARAMS.saturation),\n contrast: toFiniteNumber(params.contrast, DEFAULT_ADJUSTMENT_PARAMS.contrast),\n brightness: toFiniteNumber(params.brightness, DEFAULT_ADJUSTMENT_PARAMS.brightness),\n red: toFiniteNumber(params.red, DEFAULT_ADJUSTMENT_PARAMS.red),\n green: toFiniteNumber(params.green, DEFAULT_ADJUSTMENT_PARAMS.green),\n blue: toFiniteNumber(params.blue, DEFAULT_ADJUSTMENT_PARAMS.blue),\n alpha: toFiniteNumber(params.alpha, DEFAULT_ADJUSTMENT_PARAMS.alpha),\n };\n}\n\nfunction applyColorMatrixAdjustments(filter: PIXI.ColorMatrixFilter, params: AdjustmentParams): void {\n filter.reset();\n\n // ColorMatrixFilter operations must be multiplied to compose adjustments.\n filter.brightness(params.brightness, true);\n filter.contrast(params.contrast, true);\n filter.saturate(params.saturation, true);\n}\n\n// Register the adjustment filter\nexport default registerFilter({\n id: 'adjustment',\n name: 'Adjustment',\n category: 'adjust',\n description: 'Adjust basic image properties like brightness, contrast, and saturation',\n \n // Create an instance of the AdjustmentFilter with the provided parameters\n createFilter: (params) => {\n try {\n const normalizedParams = normalizeAdjustmentParams((params ?? {}) as Record<string, unknown>);\n console.log('Creating AdjustmentFilter with params:', normalizedParams);\n \n // Create options object for filter parameters\n const options = { ...normalizedParams };\n \n // Attempt to create AdjustmentFilter first (preferred)\n try {\n const filter = new AdjustmentFilter(options);\n\n type AdjustmentFilterWithUI = typeof filter & {\n _customParams?: AdjustmentParams;\n updateUIParam?: (key: string, value: unknown) => void;\n };\n const filterWithUI = filter as AdjustmentFilterWithUI;\n\n // Add custom updateUIParam method for dynamic updates\n filterWithUI._customParams = { ...normalizedParams };\n filterWithUI.updateUIParam = function updateUIParam(key: string, value: unknown): void {\n try {\n if (!isAdjustmentParamKey(key)) {\n return;\n }\n\n const customParams = this._customParams ?? { ...DEFAULT_ADJUSTMENT_PARAMS };\n const numericValue = toFiniteNumber(value, customParams[key]);\n customParams[key] = numericValue;\n this._customParams = customParams;\n\n const target = this as unknown as Record<string, unknown>;\n if (key in target) {\n target[key] = numericValue;\n }\n } catch (error) {\n console.error(`Error updating AdjustmentFilter parameter ${key}:`, error);\n }\n };\n \n console.log('AdjustmentFilter created successfully');\n return filter;\n } catch (error) {\n console.warn('Failed to create AdjustmentFilter, falling back to ColorMatrixFilter:', error);\n \n // Fall back to ColorMatrixFilter if AdjustmentFilter fails\n const filter = new ColorMatrixFilter();\n\n type ColorMatrixWithUI = typeof filter & {\n _customParams?: AdjustmentParams;\n updateUIParam?: (key: string, value: unknown) => void;\n };\n const filterWithUI = filter as ColorMatrixWithUI;\n\n // Store original parameters\n filterWithUI._customParams = { ...normalizedParams };\n\n // Apply initial adjustments as a composed matrix.\n applyColorMatrixAdjustments(filter, normalizedParams);\n \n // Add custom update method\n filterWithUI.updateUIParam = function updateUIParam(key: string, value: unknown): void {\n try {\n if (!isAdjustmentParamKey(key)) {\n return;\n }\n\n const customParams = this._customParams ?? { ...DEFAULT_ADJUSTMENT_PARAMS };\n const numericValue = toFiniteNumber(value, customParams[key]);\n customParams[key] = numericValue;\n this._customParams = customParams;\n\n applyColorMatrixAdjustments(this, customParams);\n } catch (error) {\n console.error(`Error updating ColorMatrixFilter parameter ${key}:`, error);\n }\n };\n \n console.log('ColorMatrixFilter created as fallback');\n return filter;\n }\n } catch (error) {\n console.error('Failed to create any adjustment filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n gamma: 1,\n saturation: 1,\n contrast: 1,\n brightness: 1,\n red: 1,\n green: 1,\n blue: 1,\n alpha: 1,\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'contrast',\n type: 'slider',\n label: 'Contrast',\n property: 'contrast',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'gamma',\n type: 'slider',\n label: 'Gamma',\n property: 'gamma',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'red',\n type: 'slider',\n label: 'Red',\n property: 'red',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'green',\n type: 'slider',\n label: 'Green',\n property: 'green',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'blue',\n type: 'slider',\n label: 'Blue',\n property: 'blue',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n ],\n});\n","/**\n * Advanced Adjustment Filter Definition\n * Provides advanced image adjustment options with a single filter\n */\nimport { registerFilter } from '../registry';\n// Import ColorMatrixFilter directly\nimport * as PIXI from 'pixi.js';\n// Access ColorMatrixFilter class\nconst { ColorMatrixFilter } = PIXI;\n\ninterface AdvancedAdjustmentParams {\n brightness: number;\n contrast: number;\n saturation: number;\n hue: number;\n sepia: number;\n negative: boolean;\n}\n\ntype AdvancedAdjustmentParamKey = keyof AdvancedAdjustmentParams;\n\nconst DEFAULT_ADVANCED_ADJUSTMENT_PARAMS: AdvancedAdjustmentParams = {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n hue: 0,\n sepia: 0,\n negative: false,\n};\n\nconst ADVANCED_ADJUSTMENT_PARAM_KEYS = new Set<AdvancedAdjustmentParamKey>([\n 'brightness',\n 'contrast',\n 'saturation',\n 'hue',\n 'sepia',\n 'negative',\n]);\n\nfunction isAdvancedAdjustmentParamKey(key: string): key is AdvancedAdjustmentParamKey {\n return ADVANCED_ADJUSTMENT_PARAM_KEYS.has(key as AdvancedAdjustmentParamKey);\n}\n\nfunction toFiniteNumber(value: unknown, fallback: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value === 'string') {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n\n return fallback;\n}\n\nfunction toBoolean(value: unknown, fallback: boolean): boolean {\n if (typeof value === 'boolean') {\n return value;\n }\n\n if (typeof value === 'string') {\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n }\n\n return fallback;\n}\n\nfunction normalizeAdvancedAdjustmentParams(params: Record<string, unknown>): AdvancedAdjustmentParams {\n return {\n brightness: toFiniteNumber(params.brightness, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.brightness),\n contrast: toFiniteNumber(params.contrast, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.contrast),\n saturation: toFiniteNumber(params.saturation, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.saturation),\n hue: toFiniteNumber(params.hue, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.hue),\n sepia: toFiniteNumber(params.sepia, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.sepia),\n negative: toBoolean(params.negative, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.negative),\n };\n}\n\nfunction applyAdvancedAdjustments(filter: PIXI.ColorMatrixFilter, params: AdvancedAdjustmentParams): void {\n // Reset first so we always apply from a clean identity matrix.\n filter.reset();\n\n if (params.brightness !== 1) {\n filter.brightness(params.brightness, true);\n }\n\n if (params.contrast !== 1) {\n filter.contrast(params.contrast, true);\n }\n\n if (params.saturation !== 1) {\n filter.saturate(params.saturation, true);\n }\n\n if (params.hue !== 0) {\n filter.hue(params.hue, true);\n }\n\n if (params.sepia > 0) {\n filter.sepia(true);\n }\n\n if (params.negative) {\n filter.negative(true);\n }\n}\n\n// Register the advanced adjustment filter\nexport default registerFilter({\n id: 'adjustment-advanced',\n name: 'Advanced Adjustment',\n category: 'adjust',\n description: 'Comprehensive image adjustments including brightness, contrast, saturation, hue, and more',\n \n // Create an instance of the ColorMatrixFilter with the provided parameters\n createFilter: (params) => {\n try {\n const normalizedParams = normalizeAdvancedAdjustmentParams((params ?? {}) as Record<string, unknown>);\n console.log('Creating Advanced Adjustment filter with params:', normalizedParams);\n \n // Create filter instance\n const filter = new ColorMatrixFilter();\n\n type AdvancedFilterWithUI = typeof filter & {\n _customParams?: AdvancedAdjustmentParams;\n updateUIParam?: (key: string, value: unknown) => void;\n };\n const filterWithUI = filter as AdvancedFilterWithUI;\n\n // Store custom parameters for later reference\n filterWithUI._customParams = { ...normalizedParams };\n\n // Apply initial adjustments from full parameter set.\n applyAdvancedAdjustments(filter, normalizedParams);\n \n // Add custom updateUIParam method for dynamic updates\n filterWithUI.updateUIParam = function updateUIParam(key: string, value: unknown): void {\n try {\n if (!isAdvancedAdjustmentParamKey(key)) {\n return;\n }\n\n const customParams = this._customParams ?? { ...DEFAULT_ADVANCED_ADJUSTMENT_PARAMS };\n if (key === 'negative') {\n customParams.negative = toBoolean(value, customParams.negative);\n } else {\n const numericKey = key as Exclude<AdvancedAdjustmentParamKey, 'negative'>;\n customParams[numericKey] = toFiniteNumber(value, customParams[numericKey]);\n }\n\n this._customParams = customParams;\n applyAdvancedAdjustments(this, customParams);\n } catch (error) {\n console.error(`Error updating Advanced Adjustment parameter ${key}:`, error);\n }\n };\n \n console.log('Advanced Adjustment filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create Advanced Adjustment filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n hue: 0,\n sepia: 0,\n negative: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1,\n },\n {\n id: 'contrast',\n type: 'slider',\n label: 'Contrast',\n property: 'contrast',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1,\n },\n {\n id: 'hue',\n type: 'slider',\n label: 'Hue Rotation',\n property: 'hue',\n min: 0,\n max: 360,\n step: 1,\n default: 0,\n },\n {\n id: 'sepia',\n type: 'slider',\n label: 'Sepia',\n property: 'sepia',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'negative',\n type: 'toggle',\n label: 'Negative',\n property: 'negative',\n default: false,\n },\n ],\n});\n","/**\n * Alpha Filter Definition\n * Controls image opacity using PIXI.AlphaFilter.\n *\n * NOTE: Previously used ColorMatrixFilter with an identity matrix, which\n * does not produce visible transparency — ColorMatrixFilter.alpha is a\n * blend ratio between filtered and unfiltered output, so with an identity\n * matrix every value produces identical output.\n */\nimport { registerFilter } from '../registry';\nimport * as PIXI from 'pixi.js';\n\nconst clamp01 = (n: number) => Math.max(0, Math.min(1, n));\n\nexport default registerFilter({\n id: 'alpha',\n name: 'Alpha',\n category: 'adjust',\n description: 'Adjust the opacity of the image',\n\n createFilter: (params) => {\n const alpha = clamp01(params.alpha !== undefined ? Number(params.alpha) : 1);\n\n // AlphaFilter genuinely controls display-object opacity. PIXI v8 accepts\n // either a number or an options object; pass the number directly so we\n // work on any minor version that's installed.\n const filter = new (PIXI as any).AlphaFilter(alpha);\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n if (key === 'alpha') {\n this.alpha = clamp01(Number(value));\n }\n };\n\n return filter;\n },\n\n defaultParams: {\n alpha: 1.0,\n },\n\n controls: [\n {\n id: 'alpha',\n type: 'slider',\n label: 'Opacity',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1.0,\n },\n ],\n});\n","/**\n * Blur Filter Definition\n * Applies a Gaussian blur effect to the image\n * \n * This implementation uses the proper BlurFilter from pixi.js\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import PIXI namespace\nimport * as PIXI from 'pixi.js';\n\n// Register the blur filter\nexport default registerFilter({\n id: 'blur',\n name: 'Blur',\n category: 'blur',\n description: 'Apply a smooth blur effect to the entire image',\n \n /**\n * Create an instance of the BlurFilter from pixi.js package\n * This implementation matches the PixiJS example exactly, using 'blur' and 'quality' parameters\n */\n createFilter: (params) => {\n try {\n console.log('Creating BlurFilter with params:', params);\n \n // Create filter with proper options object for v8\n const filter = new PIXI.BlurFilter({\n strength: params.blur || 8,\n quality: params.quality || 4\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'blur':\n this.strength = value; // PixiJS BlurFilter uses 'strength' internally\n console.log(`Updated blur to ${this.strength}`);\n break;\n \n case 'quality':\n this.quality = value;\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('BlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create BlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n blur: 8,\n quality: 4,\n },\n \n // UI controls for the filter - matching PixiJS example exactly\n controls: [\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur',\n property: 'blur',\n min: 0,\n max: 100,\n step: 0.1,\n default: 8,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n ],\n});","/**\n * Color Matrix Filter Definition\n *\n * Applies brightness/contrast/saturation/hue/sepia/negative via PIXI's\n * ColorMatrixFilter. These operations are method calls on the filter\n * instance (not writable properties) and are non-commutative: applying\n * brightness-then-hue produces a different matrix than hue-then-brightness.\n *\n * Every update rebuilds the matrix from reset() in a fixed order so the\n * output is deterministic regardless of which slider was moved last, and\n * so a slider update cannot corrupt the filter by accidentally overwriting\n * one of the methods.\n */\nimport * as PIXI from 'pixi.js';\nimport { registerFilter } from '../registry';\n\ninterface ColorMatrixParams {\n brightness: number;\n contrast: number;\n saturation: number;\n hue: number;\n sepia: boolean;\n negative: boolean;\n}\n\nfunction applyColorMatrixParams(\n filter: PIXI.ColorMatrixFilter,\n params: ColorMatrixParams,\n): void {\n if (typeof (filter as any).reset === 'function') {\n (filter as any).reset();\n }\n\n // Deterministic order — matrix ops don't commute.\n if (params.brightness !== 1) {\n filter.brightness(params.brightness, false);\n }\n if (params.contrast !== 1) {\n filter.contrast(params.contrast, false);\n }\n if (params.saturation !== 1) {\n filter.saturate(params.saturation, false);\n }\n if (params.hue !== 0) {\n filter.hue(params.hue, false);\n }\n if (params.sepia) {\n filter.sepia(false);\n }\n if (params.negative) {\n filter.negative(false);\n }\n}\n\nfunction normalizeParams(raw: Record<string, unknown>): ColorMatrixParams {\n return {\n brightness: Number(raw.brightness ?? 1),\n contrast: Number(raw.contrast ?? 1),\n saturation: Number(raw.saturation ?? 1),\n hue: Number(raw.hue ?? 0),\n sepia: Boolean(raw.sepia),\n negative: Boolean(raw.negative),\n };\n}\n\nexport default registerFilter({\n id: 'color-matrix',\n name: 'Color Matrix',\n category: 'advanced',\n description: 'Advanced color adjustments including sepia, hue rotation, and negative',\n\n createFilter: (params) => {\n const MatrixFilterClass = (PIXI as any).ColorMatrixFilter;\n if (!MatrixFilterClass) return null;\n\n const filter: PIXI.ColorMatrixFilter = new MatrixFilterClass();\n const normalized = normalizeParams(params);\n\n (filter as any)._customParams = { ...normalized };\n applyColorMatrixParams(filter, normalized);\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n const stored: ColorMatrixParams = (this as any)._customParams ?? normalizeParams({});\n\n switch (key) {\n case 'brightness':\n case 'contrast':\n case 'saturation':\n case 'hue':\n stored[key] = Number(value);\n break;\n case 'sepia':\n case 'negative':\n stored[key] = Boolean(value);\n break;\n default:\n return;\n }\n\n (this as any)._customParams = stored;\n applyColorMatrixParams(this, stored);\n };\n\n return filter;\n },\n\n defaultParams: {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n hue: 0,\n sepia: false,\n negative: false,\n },\n\n controls: [\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'contrast',\n type: 'slider',\n label: 'Contrast',\n property: 'contrast',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'hue',\n type: 'slider',\n label: 'Hue Rotation',\n property: 'hue',\n min: -180,\n max: 180,\n step: 1,\n default: 0,\n },\n // Sepia is a toggle in phase 1 — PIXI v8's ColorMatrixFilter.sepia()\n // doesn't accept a smooth intensity, so a slider here would be misleading.\n {\n id: 'sepia',\n type: 'toggle',\n label: 'Sepia',\n property: 'sepia',\n default: false,\n },\n {\n id: 'negative',\n type: 'toggle',\n label: 'Negative',\n property: 'negative',\n default: false,\n },\n ],\n});\n","/**\n * Color Overlay Filter Definition\n * Applies a colored overlay to the entire image\n * \n * This implementation uses the proper ColorOverlayFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access ColorOverlayFilter from the pixi-filters package\nconst { ColorOverlayFilter } = PixiFilters;\n\n// Register the color overlay filter\nexport default registerFilter({\n id: 'colorOverlay',\n name: 'Color Overlay',\n category: 'color',\n description: 'Apply a colored tint or overlay to the entire image',\n \n /**\n * Create an instance of ColorOverlayFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating ColorOverlayFilter with params:', params);\n \n // Parse color string to number if needed\n let colorValue = 0xff0000; // Default red\n if (params.color) {\n if (typeof params.color === 'string') {\n colorValue = parseInt(params.color.replace('#', '0x'), 16);\n } else if (typeof params.color === 'number') {\n colorValue = params.color;\n }\n }\n \n // Create filter with the ColorOverlayFilter from pixi-filters\n // Using the options object syntax for v6+\n console.log('Creating ColorOverlayFilter with options object:', {\n color: colorValue,\n alpha: params.alpha || 0.5\n });\n \n const filter = new ColorOverlayFilter({\n color: colorValue,\n alpha: params.alpha || 0.5\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n // IMPORTANT: Must update BOTH the JS property AND the shader uniform\n // The JS property is used for state tracking, but the shader uses uniforms for rendering\n switch (key) {\n case 'color':\n // Convert hex string to number for the color property\n let colorNum: number;\n if (typeof value === 'string') {\n colorNum = parseInt(value.replace('#', '0x'), 16);\n } else {\n colorNum = Number(value);\n }\n this.color = colorNum;\n if (this.uniforms) this.uniforms.uColor = colorNum;\n console.log(`Updated color to ${colorNum}`);\n break;\n\n case 'alpha':\n // Direct alpha update\n this.alpha = Number(value);\n if (this.uniforms) this.uniforms.uAlpha = Number(value);\n console.log(`Updated alpha to ${this.alpha}`);\n break;\n\n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ColorOverlayFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ColorOverlayFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n color: '#ff0000',\n alpha: 0.5,\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#ff0000',\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Opacity',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n ],\n});","/**\n * Drop Shadow Filter Definition\n * Applies a drop shadow effect to the image\n */\nimport { registerFilter } from '../registry';\nimport * as filters from 'pixi-filters';\n\n// Register the drop shadow filter\nexport default registerFilter({\n id: 'drop-shadow',\n name: 'Drop Shadow',\n category: 'effects',\n description: 'Add a soft drop shadow to the image',\n \n /**\n * Create an instance of the DropShadowFilter with the provided parameters\n * Using the official pixi-filters implementation\n */\n createFilter: (params) => {\n try {\n // Parse color from hex string\n const color = params.color ? params.color.replace('#', '0x') : '0x000000';\n\n // Create offset object based on distance and angle\n const distance = params.distance !== undefined ? params.distance : 5;\n const angle = params.angle !== undefined ? params.angle : 90;\n const blur = params.blur !== undefined ? params.blur : 2;\n const quality = params.quality !== undefined ? params.quality : 3;\n const offset = {\n x: distance * Math.cos(angle * Math.PI / 180),\n y: distance * Math.sin(angle * Math.PI / 180)\n };\n\n // Create the filter with the official pixi-filters package\n const filter = new filters.DropShadowFilter({\n offset: offset,\n color: parseInt(color, 16),\n alpha: params.alpha !== undefined ? params.alpha : 0.5,\n blur,\n quality,\n shadowOnly: params.shadowOnly !== undefined ? params.shadowOnly : false,\n pixelSize: {\n x: params.pixelSizeX !== undefined ? params.pixelSizeX : 1,\n y: params.pixelSizeY !== undefined ? params.pixelSizeY : 1\n }\n });\n\n // pixi-filters' DropShadowFilter does NOT set a .padding large enough\n // to contain its bleed (blur kernel + offset). Export needs to know the\n // actual reach so it can expand the render canvas. Compute it here and\n // expose it via _exportPadding so PixiRenderer.exportImage can read it.\n //\n // Rule of thumb: blur-kernel reach (blur * quality * 2) + offset magnitude\n // plus a small safety margin. This is the bleed from the SPRITE edge,\n // not the bleed radius around a single point.\n const computePadding = (b: number, q: number, offX: number, offY: number) => {\n const kernel = b * q * 2;\n const mag = Math.sqrt(offX * offX + offY * offY);\n return Math.ceil(kernel + mag + 2);\n };\n (filter as any)._exportPadding = computePadding(blur, quality, offset.x, offset.y);\n // Also set the built-in padding so PIXI's own bounds math doesn't clip\n // the preview at some inner boundary on certain configs.\n filter.padding = Math.max(filter.padding ?? 0, (filter as any)._exportPadding);\n\n // Store custom parameters for later reference\n (filter as any)._customParams = {\n ...params,\n // Also store the calculated offset for use in updateUIParam\n _offset: offset,\n _distance: distance,\n _angle: angle\n };\n\n /**\n * Build a fresh DropShadowFilter sized for export.\n *\n * The user tunes drop-shadow values while looking at the preview, where\n * the image is downscaled to fit the viewport. The same `distance=11`\n * that looks correct on a 600px-wide preview becomes microscopic on a\n * native-size 3224px export. This factory rebuilds the filter with\n * size-dependent params (distance, blur) multiplied by the\n * preview-to-native scale so the saved image visually matches the\n * preview at the user's intended apparent shadow size.\n *\n * Quality is unitless and stays as-is. Color, alpha, shadowOnly are\n * also intensity-only / boolean and don't scale.\n */\n const createScaledForExport = (rawParams: any, scale: number) => {\n const dist = Number(rawParams._distance ?? rawParams.distance ?? 5) * scale;\n const ang = Number(rawParams._angle ?? rawParams.angle ?? 90);\n const blr = Number(rawParams.blur ?? 2) * scale;\n const qual = Number(rawParams.quality ?? 3);\n const off = {\n x: dist * Math.cos(ang * Math.PI / 180),\n y: dist * Math.sin(ang * Math.PI / 180),\n };\n const colorStr = rawParams.color\n ? String(rawParams.color).replace('#', '0x')\n : '0x000000';\n\n const next = new filters.DropShadowFilter({\n offset: off,\n color: parseInt(colorStr, 16),\n alpha: rawParams.alpha !== undefined ? Number(rawParams.alpha) : 0.5,\n blur: blr,\n quality: qual,\n shadowOnly: rawParams.shadowOnly !== undefined ? Boolean(rawParams.shadowOnly) : false,\n pixelSize: {\n x: rawParams.pixelSizeX !== undefined ? Number(rawParams.pixelSizeX) : 1,\n y: rawParams.pixelSizeY !== undefined ? Number(rawParams.pixelSizeY) : 1,\n },\n });\n\n const padding = computePadding(blr, qual, off.x, off.y);\n (next as any)._exportPadding = padding;\n next.padding = Math.max(next.padding ?? 0, padding);\n return next;\n };\n\n /**\n * Hook used by PixiRenderer.exportImage(). Returns a fresh filter\n * instance with size params scaled to native pixels — never mutates\n * the live preview filter.\n */\n (filter as any).createExportFilter = function (options: { previewToNativeScale?: number } = {}) {\n const scale = Number.isFinite(options.previewToNativeScale)\n ? Math.max(1, Number(options.previewToNativeScale))\n : 1;\n const stored = (this as any)._customParams || params;\n return createScaledForExport(stored, scale);\n };\n\n /** Conservative export-time bleed for the renderer to reserve. */\n (filter as any).getExportPadding = function () {\n return Number((this as any)._exportPadding || this.padding || 0);\n };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n */\n const refreshPadding = (f: any) => {\n const off = f._customParams?._offset ?? { x: 0, y: 0 };\n const b = Number(f.blur ?? 0);\n const q = Number(f.quality ?? 1);\n const p = computePadding(b, q, off.x, off.y);\n f._exportPadding = p;\n f.padding = Math.max(f.padding ?? 0, p);\n };\n\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n\n switch (key) {\n case 'color':\n if (typeof value === 'string') {\n this.color = parseInt(value.replace('#', '0x'), 16);\n }\n break;\n\n case 'alpha':\n this.alpha = Number(value);\n break;\n\n case 'blur':\n this.blur = Number(value);\n refreshPadding(this);\n break;\n\n case 'quality':\n this.quality = Number(value);\n refreshPadding(this);\n break;\n\n case 'shadowOnly':\n this.shadowOnly = Boolean(value);\n break;\n\n case 'pixelSizeX':\n this.pixelSizeX = Number(value);\n customParams.pixelSizeX = Number(value);\n break;\n\n case 'pixelSizeY':\n this.pixelSizeY = Number(value);\n customParams.pixelSizeY = Number(value);\n break;\n\n case 'distance':\n case 'angle': {\n if (key === 'distance') {\n customParams._distance = Number(value);\n customParams.distance = Number(value);\n } else {\n customParams._angle = Number(value);\n customParams.angle = Number(value);\n }\n const newOffset = {\n x: customParams._distance * Math.cos(customParams._angle * Math.PI / 180),\n y: customParams._distance * Math.sin(customParams._angle * Math.PI / 180),\n };\n customParams._offset = newOffset;\n this.offset = newOffset;\n refreshPadding(this);\n break;\n }\n\n default:\n if (key in this) {\n this[key] = value;\n }\n break;\n }\n\n return true;\n } catch {\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n return false;\n }\n };\n\n return filter;\n } catch (error) {\n console.error('Failed to create Drop Shadow filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n alpha: 0.5,\n blur: 2,\n color: '#000000',\n distance: 5,\n angle: 90,\n quality: 3,\n shadowOnly: false,\n pixelSizeX: 1,\n pixelSizeY: 1\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'alpha',\n type: 'slider',\n label: 'Opacity',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur',\n property: 'blur',\n min: 0,\n max: 20,\n step: 0.1,\n default: 2,\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#000000',\n },\n {\n id: 'distance',\n type: 'slider',\n label: 'Distance',\n property: 'distance',\n min: 0,\n max: 50,\n step: 1,\n default: 5,\n },\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: 0,\n max: 360,\n step: 1,\n default: 90,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 0,\n max: 20,\n step: 1,\n default: 3,\n },\n {\n id: 'shadowOnly',\n type: 'toggle',\n label: 'Shadow Only',\n property: 'shadowOnly',\n default: false,\n },\n {\n id: 'pixelSizeX',\n type: 'slider',\n label: 'Pixel Size X',\n property: 'pixelSizeX',\n min: 0.5,\n max: 8,\n step: 0.5,\n default: 1,\n },\n {\n id: 'pixelSizeY',\n type: 'slider',\n label: 'Pixel Size Y',\n property: 'pixelSizeY',\n min: 0.5,\n max: 8,\n step: 0.5,\n default: 1,\n }\n ],\n});","/**\n * Grayscale Filter Definition\n * Converts image to grayscale with customizable intensity\n * \n * This implementation uses the ColorMatrixFilter from pixi.js\n * to provide a grayscale effect with adjustable intensity.\n */\nimport { registerFilter } from '../registry';\n// Import from pixi.js with namespace\nimport * as PIXI from 'pixi.js';\n// @ts-ignore - Module structure doesn't match TypeScript definitions\nconst { ColorMatrixFilter } = PIXI;;\n\n// Register the grayscale filter\nexport default registerFilter({\n id: 'grayscale',\n name: 'Grayscale',\n category: 'color',\n description: 'Convert the image to black and white with adjustable intensity',\n \n /**\n * Create a ColorMatrixFilter instance configured for grayscale effect with adjustable intensity\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating grayscale filter with params:', params);\n \n // Create a new ColorMatrixFilter\n const filter = new ColorMatrixFilter();\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n // Apply the initial grayscale effect based on intensity\n const intensity = params.intensity !== undefined ? params.intensity : 1.0;\n applyGrayscaleEffect(filter as any, intensity);\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This follows the same pattern as ColorOverlayFilter and ColorGradientFilter\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'intensity':\n // Apply grayscale effect with the new intensity\n applyGrayscaleEffect(this, value);\n console.log(`Updated grayscale intensity to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('Grayscale filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create grayscale filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n intensity: 0.35,\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'intensity',\n type: 'slider',\n label: 'Intensity',\n property: 'intensity',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.35,\n },\n ],\n});\n\n/**\n * Helper function to apply grayscale effect with a specific intensity\n * @param filter The ColorMatrixFilter instance\n * @param intensity The intensity of the grayscale effect (0-1)\n */\nfunction applyGrayscaleEffect(filter: any, intensity: number): void {\n // Reset the matrix to identity (no effect)\n filter.reset();\n\n // Apply grayscale with the specified intensity\n // The greyscale method takes a single parameter for intensity (0-1)\n filter.greyscale(intensity);\n}","/**\n * HSL Adjustment Filter Definition\n * Adjusts hue, saturation, and lightness with fine control\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { HslAdjustmentFilter } = PixiFilters;;\n\n// Register the HSL adjustment filter\nexport default registerFilter({\n id: 'hsl-adjustment',\n name: 'HSL Adjustment',\n category: 'color',\n description: 'Control hue, saturation, and lightness independently',\n \n /**\n * Create an instance of the HslAdjustmentFilter with the provided parameters\n * Using the official pixi-filters implementation instead of a custom one\n */\n createFilter: (params) => {\n try {\n console.log('Creating HSL Adjustment filter with params:', params);\n \n // Create a new HslAdjustmentFilter instance from the pixi-filters package\n const filter = new HslAdjustmentFilter({\n hue: params.hue !== undefined ? params.hue : 0,\n saturation: params.saturation !== undefined ? params.saturation : 0,\n lightness: params.lightness !== undefined ? params.lightness : 0, \n colorize: params.colorize !== undefined ? params.colorize : false,\n alpha: params.alpha !== undefined ? params.alpha : 1.0\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n // IMPORTANT: Must update BOTH the JS property AND the shader uniform\n // The JS property is used for state tracking, but the shader uses uniforms for rendering\n switch (key) {\n case 'hue':\n // The filter handles the degrees to radians conversion internally\n this.hue = Number(value);\n if (this.uniforms) this.uniforms.uHue = Number(value);\n console.log(`Updated hue to ${value}`);\n break;\n\n case 'saturation':\n this.saturation = Number(value);\n if (this.uniforms) this.uniforms.uSaturation = Number(value);\n console.log(`Updated saturation to ${value}`);\n break;\n\n case 'lightness':\n this.lightness = Number(value);\n if (this.uniforms) this.uniforms.uLightness = Number(value);\n console.log(`Updated lightness to ${value}`);\n break;\n\n case 'colorize':\n this.colorize = Boolean(value);\n if (this.uniforms) this.uniforms.uColorize = value ? 1 : 0;\n console.log(`Updated colorize to ${value}`);\n break;\n\n case 'alpha':\n this.alpha = Number(value);\n if (this.uniforms) this.uniforms.uAlpha = Number(value);\n console.log(`Updated alpha to ${value}`);\n break;\n\n // For any other properties, try direct assignment\n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n } catch (error) {\n console.error(`Failed to update parameter ${key} using updateUIParam:`, error);\n \n // Still store the value in customParams even if setting it failed\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n \n return false;\n }\n };\n \n console.log('HSL Adjustment filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create HSL Adjustment filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n hue: 0,\n saturation: 0,\n lightness: 0,\n colorize: false,\n alpha: 1.0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'hue',\n type: 'slider',\n label: 'Hue',\n property: 'hue',\n min: -180,\n max: 180,\n step: 1,\n default: 0,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'lightness',\n type: 'slider',\n label: 'Lightness',\n property: 'lightness',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'colorize',\n type: 'toggle',\n label: 'Colorize',\n property: 'colorize',\n default: false,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1.0,\n },\n ],\n});","/**\n * Kawase Blur Filter Definition\n * A much faster blur than Gaussian blur, with similar quality\n * \n * This implementation uses the proper KawaseBlurFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import KawaseBlurFilter directly from pixi-filters\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { KawaseBlurFilter } = PixiFilters;;\n\n// Register the kawase blur filter\nexport default registerFilter({\n id: 'kawase-blur',\n name: 'Kawase Blur',\n category: 'blur',\n description: 'A more optimized blur algorithm that is faster than standard blur',\n \n /**\n * Create an instance of the KawaseBlurFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating KawaseBlurFilter with params:', params);\n \n // Create filter with proper options object for v6+\n const filter = new KawaseBlurFilter({\n strength: params.strength || 4,\n quality: params.quality || 3,\n clamp: params.clamp || false,\n pixelSize: params.pixelSize || 1\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'strength':\n this.strength = value;\n console.log(`Updated strength to ${this.strength}`);\n break;\n \n case 'quality':\n this.quality = value;\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'clamp':\n this.clamp = value;\n console.log(`Updated clamp to ${this.clamp}`);\n break;\n \n case 'pixelSize':\n // pixelSize can be set as a single number or as an object with x and y\n if (typeof value === 'number') {\n this.pixelSize = value;\n } else if (typeof value === 'object' && value !== null) {\n if ('x' in value && 'y' in value) {\n this.pixelSize = value;\n }\n }\n console.log(`Updated pixelSize to ${JSON.stringify(this.pixelSize)}`);\n break;\n\n case 'pixelSizeX':\n this.pixelSizeX = value;\n console.log(`Updated pixelSizeX to ${this.pixelSizeX}`);\n break;\n \n case 'pixelSizeY':\n this.pixelSizeY = value;\n console.log(`Updated pixelSizeY to ${this.pixelSizeY}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('KawaseBlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create KawaseBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strength: 4,\n quality: 3,\n clamp: false,\n pixelSize: 1\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 20,\n step: 0.1,\n default: 4,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 20,\n step: 1,\n default: 3,\n },\n {\n id: 'clamp',\n type: 'toggle',\n label: 'Clamp Edges',\n property: 'clamp',\n default: false,\n },\n {\n id: 'pixelSize',\n type: 'slider',\n label: 'Pixel Size',\n property: 'pixelSize',\n min: 0.5,\n max: 10,\n step: 0.5,\n default: 1,\n },\n {\n id: 'pixelSizeX',\n type: 'slider',\n label: 'Pixel Size X',\n property: 'pixelSizeX',\n min: 0,\n max: 10,\n step: 0.1,\n default: 1,\n },\n {\n id: 'pixelSizeY',\n type: 'slider',\n label: 'Pixel Size Y',\n property: 'pixelSizeY',\n min: 0,\n max: 10,\n step: 0.1,\n default: 1,\n },\n ],\n});","/**\n * Motion Blur Filter Definition\n * Applies a directional motion blur effect to the image\n * \n * This implementation uses the proper MotionBlurFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import MotionBlurFilter directly from pixi-filters\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { MotionBlurFilter } = PixiFilters;;\n\n// Register the motion blur filter\nexport default registerFilter({\n id: 'motion-blur',\n name: 'Motion Blur',\n category: 'blur',\n description: 'Creates a directional blur effect simulating motion',\n \n /**\n * Create an instance of the MotionBlurFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating MotionBlurFilter with params:', params);\n \n // Create filter with proper options object for v6+\n const filter = new MotionBlurFilter({\n velocity: { \n x: params.velocityX !== undefined ? params.velocityX : 0, \n y: params.velocityY !== undefined ? params.velocityY : 0 \n },\n kernelSize: params.kernelSize || 5,\n offset: params.offset !== undefined ? params.offset : 0\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'velocityX':\n // Update just the X component of the velocity\n this.velocityX = value;\n console.log(`Updated velocityX to ${this.velocityX}`);\n break;\n \n case 'velocityY':\n // Update just the Y component of the velocity\n this.velocityY = value;\n console.log(`Updated velocityY to ${this.velocityY}`);\n break;\n \n case 'kernelSize':\n this.kernelSize = value;\n console.log(`Updated kernelSize to ${this.kernelSize}`);\n break;\n \n case 'offset':\n this.offset = value;\n console.log(`Updated offset to ${this.offset}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('MotionBlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create MotionBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n velocityX: 0,\n velocityY: 0,\n kernelSize: 5,\n offset: 0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'velocityX',\n type: 'slider',\n label: 'Velocity X',\n property: 'velocityX',\n min: -90,\n max: 90,\n step: 1,\n default: 0,\n },\n {\n id: 'velocityY',\n type: 'slider',\n label: 'Velocity Y',\n property: 'velocityY',\n min: -90,\n max: 90,\n step: 1,\n default: 0,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '3', value: 3 },\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 },\n { label: '17', value: 17 },\n { label: '19', value: 19 },\n { label: '21', value: 21 },\n { label: '23', value: 23 },\n { label: '25', value: 25 },\n ],\n default: 5,\n },\n {\n id: 'offset',\n type: 'slider',\n label: 'Offset',\n property: 'offset',\n min: -150,\n max: 150,\n step: 1,\n default: 0,\n },\n ],\n});","/**\n * Radial Blur Filter Definition\n * Applies a radial motion blur effect that emanates from a center point\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { RadialBlurFilter } = PixiFilters;;\n\n// Register the radial blur filter\nexport default registerFilter({\n id: 'radial-blur',\n name: 'Radial Blur',\n category: 'blur',\n description: 'Creates a circular blur effect emanating from a center point',\n \n // Create an instance of the RadialBlurFilter with the provided parameters\n createFilter: (params) => {\n try {\n // Create filter with options object\n const filter = new RadialBlurFilter({\n angle: params.angle ?? 20,\n center: { x: params.centerX ?? 0, y: params.centerY ?? 0 },\n kernelSize: params.kernelSize ?? 15,\n radius: params.radius ?? 300\n });\n\n // Store custom params for reference\n (filter as any)._customParams = {\n centerX: params.centerX ?? 0,\n centerY: params.centerY ?? 0\n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n switch (key) {\n case 'angle':\n this.angle = Number(value);\n break;\n case 'centerX':\n (this as any)._customParams.centerX = Number(value);\n this.center = { \n x: Number(value), \n y: (this as any)._customParams.centerY \n };\n break;\n case 'centerY':\n (this as any)._customParams.centerY = Number(value);\n this.center = { \n x: (this as any)._customParams.centerX, \n y: Number(value) \n };\n break;\n case 'kernelSize':\n this.kernelSize = Number(value);\n break;\n case 'radius':\n this.radius = Number(value);\n break;\n default:\n console.warn(`Unknown parameter for RadialBlurFilter: ${key}`);\n }\n } catch (error) {\n console.error(`Error updating RadialBlurFilter parameter ${key}:`, error);\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create RadialBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n angle: 20,\n centerX: 0,\n centerY: 0,\n kernelSize: 15,\n radius: 300\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: -180,\n max: 180,\n step: 1,\n default: 20,\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '3', value: 3 },\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 },\n { label: '17', value: 17 },\n { label: '19', value: 19 },\n { label: '21', value: 21 },\n { label: '23', value: 23 },\n { label: '25', value: 25 },\n ],\n default: 15,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: -1,\n max: 1000,\n step: 10,\n default: 300,\n },\n ],\n});","/**\n * Tilt Shift Filter Definition\n * Creates a depth-of-field effect like a miniature model\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { TiltShiftFilter } = PixiFilters;\n\n// Register the tilt shift filter\nexport default registerFilter({\n id: 'tilt-shift',\n name: 'Tilt Shift',\n category: 'blur',\n description: 'Creates a depth-of-field effect simulating miniature photography',\n \n // Create an instance of the TiltShiftFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating TiltShiftFilter with params:', params);\n \n // Ensure parameters have default values if missing\n const blur = typeof params.blur === 'number' ? params.blur : 100;\n const gradientBlur = typeof params.gradientBlur === 'number' ? params.gradientBlur : 600;\n const startX = typeof params.startX === 'number' ? params.startX : 0;\n const startY = typeof params.startY === 'number' ? params.startY : 0.5;\n const endX = typeof params.endX === 'number' ? params.endX : 1;\n const endY = typeof params.endY === 'number' ? params.endY : 0.5;\n \n // Create the filter with proper options\n const filter = new TiltShiftFilter({\n blur: Number(blur),\n gradientBlur: Number(gradientBlur),\n start: { x: Number(startX), y: Number(startY) },\n end: { x: Number(endX), y: Number(endY) }\n });\n \n // Log the actual filter object to see its properties\n console.log('Created TiltShiftFilter instance with properties:', {\n blur: filter.blur,\n gradientBlur: filter.gradientBlur,\n start: filter.start,\n end: filter.end\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n blur: blur,\n gradientBlur: gradientBlur,\n startX: startX,\n startY: startY,\n endX: endX,\n endY: endY\n };\n \n // Add updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`TiltShiftFilter.updateUIParam called: ${key} = ${value}`);\n \n // Force numeric conversion\n const numValue = Number(value);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = numValue;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'blur':\n this.blur = numValue;\n console.log(`Updated blur to ${this.blur}`);\n break;\n \n case 'gradientBlur':\n this.gradientBlur = numValue;\n console.log(`Updated gradientBlur to ${this.gradientBlur}`);\n break;\n \n case 'startX':\n if (this.start && typeof this.start === 'object') {\n this.start.x = numValue;\n console.log(`Updated startX to ${numValue}`, this.start);\n }\n break;\n \n case 'startY':\n if (this.start && typeof this.start === 'object') {\n this.start.y = numValue;\n console.log(`Updated startY to ${numValue}`, this.start);\n }\n break;\n \n case 'endX':\n if (this.end && typeof this.end === 'object') {\n this.end.x = numValue;\n console.log(`Updated endX to ${numValue}`, this.end);\n }\n break;\n \n case 'endY':\n if (this.end && typeof this.end === 'object') {\n this.end.y = numValue;\n console.log(`Updated endY to ${numValue}`, this.end);\n }\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = numValue;\n console.log(`Updated ${key} to ${numValue}`);\n } else {\n console.warn(`Unknown parameter for TiltShiftFilter: ${key}`);\n }\n break;\n }\n \n // Log the current state after updates\n console.log('TiltShiftFilter state after update:', {\n blur: this.blur,\n gradientBlur: this.gradientBlur,\n start: this.start,\n end: this.end\n });\n } catch (error) {\n console.error(`Error updating TiltShiftFilter parameter ${key}:`, error);\n }\n };\n \n console.log('TiltShiftFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create TiltShiftFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n blur: 100,\n gradientBlur: 600,\n startX: 0,\n startY: 0.5,\n endX: 1,\n endY: 0.5\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur Strength',\n property: 'blur',\n min: 0,\n max: 200,\n step: 1,\n default: 100,\n },\n {\n id: 'gradientBlur',\n type: 'slider',\n label: 'Gradient Width',\n property: 'gradientBlur',\n min: 0,\n max: 1000,\n step: 10,\n default: 600,\n },\n {\n id: 'startX',\n type: 'slider',\n label: 'Start X',\n property: 'startX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'startY',\n type: 'slider',\n label: 'Start Y',\n property: 'startY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'endX',\n type: 'slider',\n label: 'End X',\n property: 'endX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'endY',\n type: 'slider',\n label: 'End Y',\n property: 'endY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n ],\n});","/**\n * Zoom Blur Filter Definition\n * Creates a radial blur that simulates a camera zoom effect\n * \n * This implementation uses the proper ZoomBlurFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import ZoomBlurFilter directly from pixi-filters\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { ZoomBlurFilter } = PixiFilters;;\n\n// Register the zoom blur filter\nexport default registerFilter({\n id: 'zoom-blur',\n name: 'Zoom Blur',\n category: 'blur',\n description: 'Creates a zoom blur effect from a center point',\n \n /**\n * Create an instance of the ZoomBlurFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating ZoomBlurFilter with params:', params);\n \n // Create filter with proper options object for v6+\n const filter = new ZoomBlurFilter({\n strength: params.strength || 0.1,\n center: { \n x: params.centerX !== undefined ? params.centerX : 0.5, \n y: params.centerY !== undefined ? params.centerY : 0.5 \n },\n innerRadius: params.innerRadius || 80,\n radius: params.radius !== undefined ? params.radius : -1,\n maxKernelSize: params.maxKernelSize || 32\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'strength':\n this.strength = value;\n console.log(`Updated strength to ${this.strength}`);\n break;\n \n case 'centerX':\n // Update just the X component of the center point\n this.centerX = value;\n console.log(`Updated centerX to ${this.centerX}`);\n break;\n \n case 'centerY':\n // Update just the Y component of the center point\n this.centerY = value;\n console.log(`Updated centerY to ${this.centerY}`);\n break;\n \n case 'innerRadius':\n this.innerRadius = value;\n console.log(`Updated innerRadius to ${this.innerRadius}`);\n break;\n \n case 'radius':\n this.radius = value;\n console.log(`Updated radius to ${this.radius}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ZoomBlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ZoomBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strength: 0.1,\n centerX: 0.5,\n centerY: 0.5,\n innerRadius: 80,\n radius: -1,\n maxKernelSize: 32\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 0.5,\n step: 0.01,\n default: 0.1,\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'innerRadius',\n type: 'slider',\n label: 'Inner Radius',\n property: 'innerRadius',\n min: 0,\n max: 1000,\n step: 1,\n default: 80,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Outer Radius',\n property: 'radius',\n min: -1,\n max: 1000,\n step: 10,\n default: -1,\n },\n {\n id: 'maxKernelSize',\n type: 'select',\n label: 'Quality',\n property: 'maxKernelSize',\n options: [\n { label: 'Low', value: 16 },\n { label: 'Medium', value: 32 },\n { label: 'High', value: 48 },\n { label: 'Very High', value: 64 },\n ],\n default: 32,\n },\n ],\n});","/**\n * Color Gradient Filter Definition\n *\n * Applies a linear/radial/conic gradient via pixi-filters' ColorGradientFilter.\n * Supports unlimited color stops with per-stop color/offset/alpha editing,\n * add/remove stop commands, and CSS gradient string parsing.\n *\n * The filter instance exposes:\n * getSerializableParams() - canonical state snapshot for FilterManager sync\n * getDynamicControls() - per-stop control rows for FilterAdjustments UI\n * updateUIParam(key,val) - mutation entry point (static + dynamic + actions)\n * handleButtonAction(act) - thin wrapper for add/remove stop commands\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n\nconst { ColorGradientFilter } = PixiFilters as any;\n\ntype HexString = `#${string}`;\n\ninterface ColorStopNum {\n offset: number;\n color: number; // integer RGB\n alpha: number;\n}\n\ninterface ColorStopHex {\n offset: number;\n color: HexString;\n alpha: number;\n}\n\ninterface SerializedParams {\n gradientType: number;\n colorStops: ColorStopHex[];\n angle: number;\n alpha: number;\n maxColors: number;\n replace: boolean;\n cssGradient: string;\n}\n\nfunction hexToInt(hex: string): number {\n return parseInt(hex.replace('#', '0x'), 16);\n}\n\nfunction intToHex(num: number): HexString {\n return ('#' + num.toString(16).padStart(6, '0')) as HexString;\n}\n\nfunction normalizeStopForFilter(stop: { offset: number; color: string | number; alpha: number }): ColorStopNum {\n return {\n offset: Number(stop.offset),\n color: typeof stop.color === 'string' ? hexToInt(stop.color) : Number(stop.color),\n alpha: Number(stop.alpha),\n };\n}\n\nfunction hexStopFromFilter(stop: { offset: number; color: number | string; alpha: number }): ColorStopHex {\n return {\n offset: stop.offset,\n color: typeof stop.color === 'number' ? intToHex(stop.color) : (stop.color as HexString),\n alpha: stop.alpha,\n };\n}\n\nexport default registerFilter({\n id: 'color-gradient',\n name: 'Color Gradient',\n category: 'color',\n description: 'Applies a linear, radial or conic color gradient over the image with multiple color stops',\n\n createFilter: (params) => {\n const incomingStops = (params.colorStops as any[]) || [\n { offset: 0, color: '#ff0000', alpha: 1 },\n { offset: 1, color: '#0000ff', alpha: 1 },\n ];\n\n let stops: ColorStopNum[] = incomingStops.map(normalizeStopForFilter);\n if (stops.length < 2) {\n stops = [\n { offset: 0, color: 0xff0000, alpha: 1 },\n { offset: 1, color: 0x0000ff, alpha: 1 },\n ];\n }\n // Sort on creation — the UI layer avoids re-sorting during a drag.\n stops.sort((a, b) => a.offset - b.offset);\n\n const filter = new ColorGradientFilter({\n type: params.gradientType,\n stops,\n angle: params.angle,\n alpha: params.alpha,\n maxColors: params.maxColors || 0,\n replace: params.replace,\n });\n\n (filter as any)._customParams = {\n cssGradient: params.cssGradient || '',\n };\n\n /**\n * Canonical snapshot for persistence + recreation.\n */\n (filter as any).getSerializableParams = function (): SerializedParams {\n const stopsHex: ColorStopHex[] = Array.isArray(this.stops)\n ? this.stops.map(hexStopFromFilter)\n : [];\n\n return {\n gradientType: this.type,\n colorStops: stopsHex,\n angle: this.angle,\n alpha: this.alpha,\n maxColors: this.maxColors,\n replace: this.replace,\n cssGradient: this._customParams?.cssGradient ?? '',\n };\n };\n\n /**\n * Color stops formatted for UI consumption.\n */\n (filter as any).getColorStopsForUI = function (): ColorStopHex[] {\n if (!Array.isArray(this.stops)) return [];\n return this.stops.map(hexStopFromFilter);\n };\n\n /**\n * Generate one control row per color stop (color, offset, alpha).\n * Called by FilterAdjustments after rendering static controls.\n */\n (filter as any).getDynamicControls = function () {\n const colorStops: ColorStopHex[] = this.getColorStopsForUI();\n\n const controls: Array<{\n id: string;\n type: string;\n label: string;\n property: string;\n default: unknown;\n min?: number;\n max?: number;\n step?: number;\n }> = [];\n\n colorStops.forEach((stop, index) => {\n controls.push({\n id: `colorStop-${index}-color`,\n type: 'color',\n label: `Stop ${index + 1} Color`,\n property: `colorStops[${index}].color`,\n default: stop.color,\n });\n\n controls.push({\n id: `colorStop-${index}-offset`,\n type: 'slider',\n label: `Stop ${index + 1} Position`,\n property: `colorStops[${index}].offset`,\n min: 0,\n max: 1,\n step: 0.01,\n default: stop.offset,\n });\n\n controls.push({\n id: `colorStop-${index}-alpha`,\n type: 'slider',\n label: `Stop ${index + 1} Alpha`,\n property: `colorStops[${index}].alpha`,\n min: 0,\n max: 1,\n step: 0.01,\n default: stop.alpha,\n });\n });\n\n return controls;\n };\n\n /**\n * Thin wrapper so the UI can dispatch named actions without knowing\n * that they're routed through updateUIParam.\n */\n (filter as any).handleButtonAction = function (action: string) {\n if (action === 'addColorStop' || action === 'removeColorStop') {\n this.updateUIParam(action, true);\n }\n };\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n const customParams = (this as any)._customParams ?? {};\n (this as any)._customParams = customParams;\n\n switch (key) {\n case 'gradientType':\n this.type = Number(value);\n return;\n\n case 'angle':\n case 'alpha':\n case 'maxColors':\n this[key] = Number(value);\n return;\n\n case 'replace':\n this.replace = Boolean(value);\n return;\n\n case 'addColorStop': {\n const current: ColorStopNum[] = Array.isArray(this.stops) ? [...this.stops] : [];\n const randomColor =\n (Math.floor(Math.random() * 255) << 16) |\n (Math.floor(Math.random() * 255) << 8) |\n Math.floor(Math.random() * 255);\n\n // Rescale existing stops so the new one fits at the tail.\n if (current.length > 0) {\n const scale = 0.8;\n for (const stop of current) {\n stop.offset *= scale;\n }\n }\n current.push({ offset: 1.0, color: randomColor, alpha: 1.0 });\n current.sort((a, b) => a.offset - b.offset);\n this.stops = current;\n return;\n }\n\n case 'removeColorStop': {\n const current: ColorStopNum[] = Array.isArray(this.stops) ? [...this.stops] : [];\n if (current.length > 2) {\n current.pop();\n this.stops = current;\n }\n return;\n }\n\n case 'cssGradient': {\n const str = typeof value === 'string' ? value.trim() : '';\n customParams.cssGradient = str;\n if (!str) return;\n try {\n const parsed = new ColorGradientFilter({ css: str });\n this.type = parsed.type;\n this.angle = parsed.angle;\n this.stops = [...parsed.stops];\n } catch {\n // Silently ignore invalid CSS gradient strings —\n // the user can fix the input and retry.\n }\n return;\n }\n\n case 'colorStops': {\n if (!Array.isArray(value)) return;\n const normalized = (value as any[]).map(normalizeStopForFilter);\n normalized.sort((a, b) => a.offset - b.offset);\n this.stops = normalized;\n return;\n }\n\n default: {\n const dynamicMatch = /^colorStops\\[(\\d+)\\]\\.(offset|color|alpha)$/.exec(key);\n if (dynamicMatch) {\n const [, indexStr, prop] = dynamicMatch;\n const index = Number(indexStr);\n const stops: ColorStopNum[] = Array.isArray(this.stops) ? [...this.stops] : [];\n if (index < 0 || index >= stops.length) return;\n\n if (prop === 'color') {\n stops[index].color =\n typeof value === 'string' ? hexToInt(value) : Number(value);\n } else if (prop === 'offset' || prop === 'alpha') {\n stops[index][prop] = Number(value);\n }\n // IMPORTANT: do NOT sort during offset drag — would re-index\n // controls mid-interaction and swap the row the user is dragging.\n // The UI re-renders after pointer up.\n this.stops = stops;\n }\n }\n }\n };\n\n return filter;\n },\n\n defaultParams: {\n gradientType: 0,\n colorStops: [\n { offset: 0, color: '#ff0000', alpha: 1 },\n { offset: 1, color: '#0000ff', alpha: 1 },\n ],\n cssGradient: '',\n angle: 90,\n alpha: 0.75,\n maxColors: 0,\n replace: false,\n },\n\n controls: [\n {\n id: 'gradientType',\n type: 'select',\n label: 'Gradient Type',\n property: 'gradientType',\n options: [\n { label: 'Linear', value: 0 },\n { label: 'Radial', value: 1 },\n { label: 'Conic', value: 2 },\n ],\n default: 0,\n },\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: 0,\n max: 360,\n step: 1,\n default: 90,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Overall Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.75,\n },\n {\n id: 'maxColors',\n type: 'slider',\n label: 'Max Colors',\n property: 'maxColors',\n min: 0,\n max: 24,\n step: 1,\n default: 0,\n },\n {\n id: 'replace',\n type: 'toggle',\n label: 'Replace Original Colors',\n property: 'replace',\n default: false,\n },\n {\n id: 'addColorStop',\n type: 'button',\n label: 'Add New Color Stop',\n action: 'addColorStop',\n },\n {\n id: 'removeColorStop',\n type: 'button',\n label: 'Remove Last Color Stop',\n action: 'removeColorStop',\n },\n {\n id: 'cssGradient',\n type: 'text',\n label: 'CSS Gradient',\n property: 'cssGradient',\n default: '',\n placeholder: 'e.g. linear-gradient(to right, red, blue)',\n },\n ],\n});\n","/**\n * Color Map Filter Definition\n * Applies a color transformation based on a reference texture\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\nimport * as PIXI from 'pixi.js';\n\n// Register the Color Map filter\nexport default registerFilter({\n id: 'color-map',\n name: 'Color Map',\n category: 'color',\n description: 'Maps colors using a reference texture as a lookup table',\n \n // Create an instance of the ColorMapFilter with the provided parameters\n createFilter: (params) => {\n try {\n // Access filter class via direct indexing with type casting to avoid TypeScript errors \n // @ts-ignore - Runtime access of property that TypeScript doesn't know about\n const ColorMapFilterClass = PixiFilters['ColorMapFilter'];\n \n if (!ColorMapFilterClass) {\n console.error('ColorMapFilter not found in pixi-filters package');\n return null;\n }\n \n console.log('Creating ColorMapFilter with params:', params);\n \n // Get the color map texture\n let colorMapTexture = null;\n \n // If texture path is provided, create a new texture\n if (params.texturePath) {\n colorMapTexture = PIXI.Texture.from(params.texturePath);\n } else {\n // Use a default colormap texture\n // This is just a fallback - ideally user should provide their own\n colorMapTexture = PIXI.Texture.from('/examples/filters-main/examples/images/colormap.png');\n }\n \n // Create filter with proper options object\n const filter = new ColorMapFilterClass({\n colorMap: colorMapTexture,\n nearest: params.nearest,\n mix: params.mix\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'texturePath':\n // Update the color map texture\n if (value) {\n this.colorMap = PIXI.Texture.from(value);\n console.log(`Updated colorMap texture to ${value}`);\n }\n break;\n \n case 'mix':\n // Direct mix update\n this.mix = value;\n console.log(`Updated mix to ${this.mix}`);\n break;\n \n case 'nearest':\n // Direct nearest update\n this.nearest = value;\n console.log(`Updated nearest to ${this.nearest}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ColorMapFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ColorMapFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n texturePath: '', // User should provide a texture path\n mix: 1, // Mix between original and mapped colors (0-1)\n nearest: false // Whether to use nearest-neighbor sampling for the texture\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'texturePath',\n type: 'select',\n label: 'Color Map',\n property: 'texturePath',\n options: [\n { label: 'Default', value: '/examples/filters-main/examples/images/colormap.png' },\n { label: 'Grayscale', value: '/examples/filters-main/examples/images/colormap-grayscale.png' },\n { label: 'Sepia', value: '/examples/filters-main/examples/images/colormap-sepia.png' },\n // Add more options as needed\n ],\n default: '/examples/filters-main/examples/images/colormap.png',\n },\n {\n id: 'mix',\n type: 'slider',\n label: 'Mix',\n property: 'mix',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'nearest',\n type: 'toggle',\n label: 'Nearest Neighbor Sampling',\n property: 'nearest',\n default: false,\n }\n ],\n});","/**\n * Color Replace Filter Definition\n * Replaces a specific color in the image with another color\n * \n * This implementation uses the proper ColorReplaceFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n\n// Access filter class via direct indexing with type casting to avoid TypeScript errors \n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst ColorReplaceFilter = PixiFilters['ColorReplaceFilter'];\n\n// Register the Color Replace filter\nexport default registerFilter({\n id: 'color-replace',\n name: 'Color Replace',\n category: 'color',\n description: 'Replaces a specific color in the image with another color',\n \n /**\n * Create an instance of ColorReplaceFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating ColorReplaceFilter with params:', params);\n \n // Parse hex colors to numbers if they're strings\n let originalColorValue = 0xff0000; // Default red\n if (params.originalColor) {\n if (typeof params.originalColor === 'string') {\n originalColorValue = parseInt(params.originalColor.replace('#', '0x'), 16);\n } else if (typeof params.originalColor === 'number') {\n originalColorValue = params.originalColor;\n }\n }\n \n let targetColorValue = 0x0000ff; // Default blue\n if (params.targetColor) {\n if (typeof params.targetColor === 'string') {\n targetColorValue = parseInt(params.targetColor.replace('#', '0x'), 16);\n } else if (typeof params.targetColor === 'number') {\n targetColorValue = params.targetColor;\n }\n }\n \n // Create filter with proper options object for v6+\n const filter = new ColorReplaceFilter({\n originalColor: originalColorValue,\n targetColor: targetColorValue,\n tolerance: params.tolerance || 0.4\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'originalColor':\n // Convert hex string to number for the originalColor property\n if (typeof value === 'string') {\n this.originalColor = parseInt(value.replace('#', '0x'), 16);\n console.log(`Updated originalColor to ${this.originalColor} from ${value}`);\n } else if (typeof value === 'number') {\n this.originalColor = value;\n console.log(`Updated originalColor to ${this.originalColor}`);\n }\n break;\n \n case 'targetColor':\n // Convert hex string to number for the targetColor property\n if (typeof value === 'string') {\n this.targetColor = parseInt(value.replace('#', '0x'), 16);\n console.log(`Updated targetColor to ${this.targetColor} from ${value}`);\n } else if (typeof value === 'number') {\n this.targetColor = value;\n console.log(`Updated targetColor to ${this.targetColor}`);\n }\n break;\n \n case 'tolerance':\n // Direct tolerance update\n this.tolerance = value;\n console.log(`Updated tolerance to ${this.tolerance}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ColorReplaceFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ColorReplaceFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n originalColor: '#ff0000', // Red\n targetColor: '#0000ff', // Blue\n tolerance: 0.4 // Match sensitivity\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'originalColor',\n type: 'color',\n label: 'Original Color',\n property: 'originalColor',\n default: '#ff0000',\n },\n {\n id: 'targetColor',\n type: 'color',\n label: 'Target Color',\n property: 'targetColor',\n default: '#0000ff',\n },\n {\n id: 'tolerance',\n type: 'slider',\n label: 'Tolerance',\n property: 'tolerance',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.4,\n }\n ],\n});","/**\n * Multi-Color Replace Filter Definition\n * Replaces multiple colors in the image with different target colors\n * \n * This implementation uses the proper MultiColorReplaceFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n\n// Access filter class via direct indexing with type casting to avoid TypeScript errors \n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst MultiColorReplaceFilter = PixiFilters['MultiColorReplaceFilter'];\n\n// Register the Multi-Color Replace filter\nexport default registerFilter({\n id: 'multi-color-replace',\n name: 'Multi-Color Replace',\n category: 'color',\n description: 'Replaces multiple colors in the image with different target colors',\n \n /**\n * Create an instance of MultiColorReplaceFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating MultiColorReplaceFilter with params:', params);\n \n // Prepare the replacements array with proper color value conversion\n const replacements = [];\n \n // Add first replacement pair\n if (params.originalColor1 && params.targetColor1) {\n const original = typeof params.originalColor1 === 'string' \n ? parseInt(params.originalColor1.replace('#', '0x'), 16)\n : params.originalColor1;\n const target = typeof params.targetColor1 === 'string'\n ? parseInt(params.targetColor1.replace('#', '0x'), 16)\n : params.targetColor1;\n \n replacements.push([original, target]);\n }\n \n // Add second replacement pair\n if (params.originalColor2 && params.targetColor2) {\n const original = typeof params.originalColor2 === 'string'\n ? parseInt(params.originalColor2.replace('#', '0x'), 16)\n : params.originalColor2;\n const target = typeof params.targetColor2 === 'string'\n ? parseInt(params.targetColor2.replace('#', '0x'), 16)\n : params.targetColor2;\n \n replacements.push([original, target]);\n }\n \n // Add third replacement pair if enabled\n if (params.enableThirdPair && params.originalColor3 && params.targetColor3) {\n const original = typeof params.originalColor3 === 'string'\n ? parseInt(params.originalColor3.replace('#', '0x'), 16)\n : params.originalColor3;\n const target = typeof params.targetColor3 === 'string'\n ? parseInt(params.targetColor3.replace('#', '0x'), 16)\n : params.targetColor3;\n \n replacements.push([original, target]);\n }\n \n // Create filter with PIXI v8 API (constructor takes replacements, epsilon, maxColors)\n const filter = new MultiColorReplaceFilter(\n replacements as any,\n params.tolerance || 0.05,\n 3 // Allow up to 3 color pairs\n );\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Create new replacements array if needed\n \n // Process standard color pair updates\n if (key === 'originalColor1' || key === 'targetColor1' || \n key === 'originalColor2' || key === 'targetColor2' ||\n key === 'originalColor3' || key === 'targetColor3' ||\n key === 'enableThirdPair') {\n \n // Create a new replacements array based on current params\n const newReplacements = [];\n \n // Add first replacement pair\n if (customParams.originalColor1 && customParams.targetColor1) {\n const original = typeof customParams.originalColor1 === 'string' \n ? parseInt(customParams.originalColor1.replace('#', '0x'), 16)\n : customParams.originalColor1;\n const target = typeof customParams.targetColor1 === 'string'\n ? parseInt(customParams.targetColor1.replace('#', '0x'), 16)\n : customParams.targetColor1;\n \n newReplacements.push([original, target]);\n }\n \n // Add second replacement pair\n if (customParams.originalColor2 && customParams.targetColor2) {\n const original = typeof customParams.originalColor2 === 'string'\n ? parseInt(customParams.originalColor2.replace('#', '0x'), 16)\n : customParams.originalColor2;\n const target = typeof customParams.targetColor2 === 'string'\n ? parseInt(customParams.targetColor2.replace('#', '0x'), 16)\n : customParams.targetColor2;\n \n newReplacements.push([original, target]);\n }\n \n // Add third replacement pair if enabled\n if (customParams.enableThirdPair && customParams.originalColor3 && customParams.targetColor3) {\n const original = typeof customParams.originalColor3 === 'string'\n ? parseInt(customParams.originalColor3.replace('#', '0x'), 16)\n : customParams.originalColor3;\n const target = typeof customParams.targetColor3 === 'string'\n ? parseInt(customParams.targetColor3.replace('#', '0x'), 16)\n : customParams.targetColor3;\n \n newReplacements.push([original, target]);\n }\n \n // Update the replacements and refresh\n this.replacements = newReplacements;\n this.refresh(); // Apply the changes\n console.log(`Updated replacements for ${key}:`, newReplacements);\n } \n // Handle tolerance updates directly\n else if (key === 'tolerance') {\n this.tolerance = value;\n console.log(`Updated tolerance to ${this.tolerance}`);\n } \n // For any other properties, try direct assignment\n else if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n \n return true;\n };\n \n console.log('MultiColorReplaceFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create MultiColorReplaceFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n originalColor1: '#ff0000', // Red\n targetColor1: '#0000ff', // Blue\n originalColor2: '#00ff00', // Green\n targetColor2: '#ffff00', // Yellow\n enableThirdPair: false,\n originalColor3: '#ff00ff', // Magenta\n targetColor3: '#00ffff', // Cyan\n tolerance: 0.05 // Match sensitivity\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'originalColor1',\n type: 'color',\n label: 'Original Color 1',\n property: 'originalColor1',\n default: '#ff0000',\n },\n {\n id: 'targetColor1',\n type: 'color',\n label: 'Target Color 1',\n property: 'targetColor1',\n default: '#0000ff',\n },\n {\n id: 'originalColor2',\n type: 'color',\n label: 'Original Color 2',\n property: 'originalColor2',\n default: '#00ff00',\n },\n {\n id: 'targetColor2',\n type: 'color',\n label: 'Target Color 2',\n property: 'targetColor2',\n default: '#ffff00',\n },\n {\n id: 'enableThirdPair',\n type: 'toggle',\n label: 'Enable Third Color Pair',\n property: 'enableThirdPair',\n default: false,\n },\n {\n id: 'originalColor3',\n type: 'color',\n label: 'Original Color 3',\n property: 'originalColor3',\n default: '#ff00ff',\n },\n {\n id: 'targetColor3',\n type: 'color',\n label: 'Target Color 3',\n property: 'targetColor3',\n default: '#00ffff',\n },\n {\n id: 'tolerance',\n type: 'slider',\n label: 'Tolerance',\n property: 'tolerance',\n min: 0,\n max: 0.5,\n step: 0.01,\n default: 0.05,\n }\n ],\n});","/**\n * RGB Split Filter Definition\n * Displaces the red, green, and blue channels separately to create a glitch or 3D effect\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { RGBSplitFilter } = PixiFilters;;\n\n// Register the RGB Split filter\nexport default registerFilter({\n id: 'rgb-split',\n name: 'RGB Split',\n category: 'color',\n description: 'Shifts the red, green, and blue channels to create a retro 3D or glitch effect',\n \n /**\n * Create an instance of the RGBSplitFilter with the provided parameters\n * Using the official pixi-filters implementation\n */\n createFilter: (params) => {\n try {\n console.log('Creating RGB Split filter with params:', params);\n \n // Create point objects for each channel from the params\n const red = { \n x: params.redX !== undefined ? params.redX : -10, \n y: params.redY !== undefined ? params.redY : 0 \n };\n const green = { \n x: params.greenX !== undefined ? params.greenX : 0, \n y: params.greenY !== undefined ? params.greenY : 10 \n };\n const blue = { \n x: params.blueX !== undefined ? params.blueX : 0, \n y: params.blueY !== undefined ? params.blueY : 0 \n };\n \n // Create the filter with the official pixi-filters package\n const filter = new RGBSplitFilter({\n red,\n green,\n blue\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'redX':\n this.redX = Number(value);\n console.log(`Updated redX to ${value}`);\n break;\n \n case 'redY':\n this.redY = Number(value);\n console.log(`Updated redY to ${value}`);\n break;\n \n case 'greenX':\n this.greenX = Number(value);\n console.log(`Updated greenX to ${value}`);\n break;\n \n case 'greenY':\n this.greenY = Number(value);\n console.log(`Updated greenY to ${value}`);\n break;\n \n case 'blueX':\n this.blueX = Number(value);\n console.log(`Updated blueX to ${value}`);\n break;\n \n case 'blueY':\n this.blueY = Number(value);\n console.log(`Updated blueY to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n } catch (error) {\n console.error(`Failed to update parameter ${key} using updateUIParam:`, error);\n \n // Still store the value in customParams even if setting it failed\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n \n return false;\n }\n };\n \n console.log('RGB Split filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create RGB Split filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n redX: -10,\n redY: 0,\n greenX: 0,\n greenY: 10,\n blueX: 0,\n blueY: 0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'redX',\n type: 'slider',\n label: 'Red X Offset',\n property: 'redX',\n min: -20,\n max: 20,\n step: 1,\n default: -10,\n },\n {\n id: 'redY',\n type: 'slider',\n label: 'Red Y Offset',\n property: 'redY',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n },\n {\n id: 'greenX',\n type: 'slider',\n label: 'Green X Offset',\n property: 'greenX',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n },\n {\n id: 'greenY',\n type: 'slider',\n label: 'Green Y Offset',\n property: 'greenY',\n min: -20,\n max: 20,\n step: 1,\n default: 10,\n },\n {\n id: 'blueX',\n type: 'slider',\n label: 'Blue X Offset',\n property: 'blueX',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n },\n {\n id: 'blueY',\n type: 'slider',\n label: 'Blue Y Offset',\n property: 'blueY',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n }\n ],\n});","/**\n * Advanced Bloom Filter Definition\n * Applies a sophisticated bloom effect with fine-grained control over parameters\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access AdvancedBloomFilter from the pixi-filters package\nconst { AdvancedBloomFilter } = PixiFilters;\n\n// Register the Advanced Bloom filter\nexport default registerFilter({\n id: 'advanced-bloom',\n name: 'Advanced Bloom',\n category: 'light',\n description: 'Adds a sophisticated bloom/glow effect with fine-grained control',\n \n // Create an instance of the AdvancedBloomFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating AdvancedBloomFilter with params:', params);\n \n // Using PixiJS v8 style options object\n const filter = new AdvancedBloomFilter({\n threshold: params.threshold || 0.5,\n bloomScale: params.bloomScale || 1.0,\n brightness: params.brightness || 1.0,\n blur: params.blur || 8,\n quality: params.quality || 4,\n pixelSize: { \n x: params.pixelSizeX || 1, \n y: params.pixelSizeY || 1 \n }\n });\n \n // Store custom params for reference\n (filter as any)._customParams = {\n pixelSizeX: params.pixelSizeX || 1,\n pixelSizeY: params.pixelSizeY || 1\n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n switch (key) {\n case 'threshold':\n this.threshold = Number(value);\n console.log(`Updated threshold to ${this.threshold}`);\n break;\n \n case 'bloomScale':\n this.bloomScale = Number(value);\n console.log(`Updated bloomScale to ${this.bloomScale}`);\n break;\n \n case 'brightness':\n this.brightness = Number(value);\n console.log(`Updated brightness to ${this.brightness}`);\n break;\n \n case 'blur':\n this.blur = Number(value);\n console.log(`Updated blur to ${this.blur}`);\n break;\n \n case 'quality':\n this.quality = Number(value);\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'pixelSizeX':\n customParams.pixelSizeX = Number(value);\n // Need to update the entire pixelSize object\n this.pixelSize = { \n x: Number(value), \n y: customParams.pixelSizeY \n };\n console.log(`Updated pixelSizeX to ${value}`);\n break;\n \n case 'pixelSizeY':\n customParams.pixelSizeY = Number(value);\n // Need to update the entire pixelSize object\n this.pixelSize = { \n x: customParams.pixelSizeX, \n y: Number(value) \n };\n console.log(`Updated pixelSizeY to ${value}`);\n break;\n \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for AdvancedBloomFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating AdvancedBloomFilter parameter ${key}:`, error);\n }\n };\n \n console.log('AdvancedBloomFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create AdvancedBloomFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n threshold: 0.5, // Brightness threshold\n bloomScale: 1.0, // Intensity of the bloom effect\n brightness: 1.0, // Overall brightness\n blur: 8, // Blur strength\n quality: 4, // Quality of the blur (higher = better but slower)\n pixelSizeX: 1, // Horizontal pixel size\n pixelSizeY: 1 // Vertical pixel size\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'threshold',\n type: 'slider',\n label: 'Threshold',\n property: 'threshold',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'bloomScale',\n type: 'slider',\n label: 'Bloom Intensity',\n property: 'bloomScale',\n min: 0,\n max: 3,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 3,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur Strength',\n property: 'blur',\n min: 0,\n max: 20,\n step: 1,\n default: 8,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n {\n id: 'pixelSizeX',\n type: 'slider',\n label: 'Pixel Size X',\n property: 'pixelSizeX',\n min: 0.5,\n max: 10,\n step: 0.5,\n default: 1,\n },\n {\n id: 'pixelSizeY',\n type: 'slider',\n label: 'Pixel Size Y',\n property: 'pixelSizeY',\n min: 0.5,\n max: 10,\n step: 0.5,\n default: 1,\n }\n ],\n});","/**\n * ASCII Filter Definition\n * Applies an ASCII art effect to the image\n */\nimport { registerFilter } from '../registry';\n// Import from the central PixiFilters export\nimport * as PixiFilters from 'pixi-filters';\n// Define AsciiFilter as a variable to allow fallback implementation\nconst AsciiFilter = (PixiFilters as any).AsciiFilter;\n\n// Register the ASCII filter\nexport default registerFilter({\n id: 'ascii',\n name: 'ASCII',\n category: 'stylize',\n description: 'Convert image to ASCII text characters',\n \n // Create an instance of the AsciiFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating AsciiFilter with params:', params);\n \n // Ensure parameters have default values if missing\n const size = typeof params.size === 'number' ? params.size : 8;\n \n // Convert color string to number if needed\n let color = params.color;\n if (typeof color === 'string' && color.startsWith('#')) {\n color = parseInt(color.replace('#', '0x'), 16);\n }\n \n const replaceColor = params.replaceColor === true;\n \n // Create the filter with proper options\n const filter = new AsciiFilter({\n size: size,\n color: color,\n replaceColor: replaceColor\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n size: size,\n color: color,\n replaceColor: replaceColor\n };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`AsciiFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'size':\n this.size = Number(value);\n console.log(`Updated size to ${this.size}`);\n break;\n \n case 'color':\n // Convert color string to number if needed\n if (typeof value === 'string' && value.startsWith('#')) {\n customParams.color = value;\n this.color = parseInt(value.replace('#', '0x'), 16);\n } else {\n this.color = value;\n }\n console.log(`Updated color to ${this.color}`);\n break;\n \n case 'replaceColor':\n this.replaceColor = Boolean(value);\n console.log(`Updated replaceColor to ${this.replaceColor}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for AsciiFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating AsciiFilter parameter ${key}:`, error);\n }\n };\n \n console.log('AsciiFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create AsciiFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n size: 8,\n color: '#ffffff',\n replaceColor: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'size',\n type: 'slider',\n label: 'Character Size',\n property: 'size',\n min: 2,\n max: 20,\n step: 1,\n default: 8,\n },\n {\n id: 'color',\n type: 'color',\n label: 'Character Color',\n property: 'color',\n default: '#ffffff',\n },\n {\n id: 'replaceColor',\n type: 'toggle',\n label: 'Replace Original Colors',\n property: 'replaceColor',\n default: false,\n }\n ],\n});","/**\n * Backdrop Blur Filter Definition\n * Applies a blur effect to the background behind an object\n * \n * IMPORTANT: This filter requires setting useBackBuffer: true in the renderer options,\n * which has been added to the PixiApplication.ts file. It's a special filter that\n * applies a blur to what's behind the objects rather than to the objects themselves.\n */\nimport { registerFilter } from '../registry';\n// Import from the central PixiFilters export\nimport * as PixiFilters from 'pixi-filters';\n// Define BackdropBlurFilter as a variable to allow fallback implementation\nconst BackdropBlurFilter = (PixiFilters as any).BackdropBlurFilter;\n\n// Register the backdrop blur filter\nexport default registerFilter({\n id: 'backdrop-blur',\n name: 'Backdrop Blur',\n category: 'blur',\n description: 'Blurs what is behind the object, creating a glass-like effect',\n \n // Create an instance of the BackdropBlurFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating BackdropBlurFilter with params:', params);\n \n // Create filter with options object\n // This is a special filter - it inherits from BlurFilter but adds a blend pass\n // to apply the blur only to what's behind the object\n const filter = new BackdropBlurFilter({\n // Higher strength values (20-50) make the effect more noticeable\n strength: params.strength || 20, \n quality: params.quality || 4,\n // Lower resolution values (0.2-0.5) can make the effect more visible but less sharp\n resolution: params.resolution || 0.5,\n kernelSize: params.kernelSize || 9\n });\n \n // Store custom params for reference\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle all supported parameters\n switch (key) {\n case 'strength':\n // Higher strength values will make the effect more visible\n this.strength = Number(value);\n // For this filter, we can also update blur, which is a deprecated alias\n // but might be used internally\n this.blur = Number(value) / 4; // Scale down for blur property\n console.log(`Updated strength to ${this.strength}`);\n break;\n \n case 'quality':\n this.quality = Number(value);\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'resolution':\n // Lower resolution values make the effect more pronounced\n this.resolution = Number(value);\n console.log(`Updated resolution to ${this.resolution}`);\n break;\n \n case 'kernelSize':\n // Larger kernel sizes increase the blur radius and quality\n const kernelSize = Number(value);\n \n // Update both the X and Y kernel sizes\n if (this.blurXFilter && this.blurYFilter) {\n this.blurXFilter.kernelSize = kernelSize;\n this.blurYFilter.kernelSize = kernelSize;\n } else {\n // Fallback for older versions\n (this as any).kernelSize = kernelSize;\n }\n \n console.log(`Updated kernelSize to ${kernelSize}`);\n break;\n \n // For any other properties that might exist directly on the filter\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for BackdropBlurFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating BackdropBlurFilter parameter ${key}:`, error);\n }\n };\n \n // Log successful creation\n console.log('BackdropBlurFilter created successfully');\n \n return filter;\n } catch (error) {\n console.error('Failed to create BackdropBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values - optimized for better visibility\n defaultParams: {\n strength: 20, // Higher value for stronger effect\n quality: 4, // Moderate quality for performance\n resolution: 0.5, // Lower resolution makes effect more visible\n kernelSize: 9 // Larger kernel for wider blur\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 50, // Increased max to allow stronger effects\n step: 1,\n default: 20,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n {\n id: 'resolution',\n type: 'slider',\n label: 'Resolution',\n property: 'resolution',\n min: 0.1,\n max: 1, // Reduced max to focus on lower values that show effect better\n step: 0.1,\n default: 0.5,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 },\n ],\n default: 9,\n },\n ],\n});","/**\n * Bevel Filter Definition\n * Applies a beveled edge effect to the image\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access BevelFilter from the pixi-filters package\nconst { BevelFilter } = PixiFilters;\n\n// Register the Bevel filter\nexport default registerFilter({\n id: 'bevel',\n name: 'Bevel',\n category: 'effects',\n description: 'Add a 3D-like beveled edge effect to the image',\n \n /**\n * Create an instance of the BevelFilter with the provided parameters\n * Using the official pixi-filters implementation\n */\n createFilter: (params) => {\n try {\n console.log('Creating Bevel filter with params:', params);\n \n // Parse colors from hex strings\n const lightColor = params.lightColor ? params.lightColor.replace('#', '0x') : '0xffffff';\n const shadowColor = params.shadowColor ? params.shadowColor.replace('#', '0x') : '0x000000';\n \n // Create the filter with the official pixi-filters package\n const filter = new BevelFilter({\n rotation: params.rotation !== undefined ? params.rotation : 45,\n thickness: params.thickness !== undefined ? params.thickness : 2,\n lightColor: parseInt(lightColor, 16),\n lightAlpha: params.lightAlpha !== undefined ? params.lightAlpha : 0.7,\n shadowColor: parseInt(shadowColor, 16),\n shadowAlpha: params.shadowAlpha !== undefined ? params.shadowAlpha : 0.7\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'rotation':\n this.rotation = Number(value);\n console.log(`Updated rotation to ${value}`);\n break;\n \n case 'thickness':\n this.thickness = Number(value);\n console.log(`Updated thickness to ${value}`);\n break;\n \n case 'lightColor':\n // Convert hex string to number for the lightColor property\n if (typeof value === 'string') {\n const colorNum = parseInt(value.replace('#', '0x'), 16);\n this.lightColor = colorNum;\n console.log(`Updated lightColor to ${value} (${colorNum})`);\n }\n break;\n \n case 'lightAlpha':\n this.lightAlpha = Number(value);\n console.log(`Updated lightAlpha to ${value}`);\n break;\n \n case 'shadowColor':\n // Convert hex string to number for the shadowColor property\n if (typeof value === 'string') {\n const colorNum = parseInt(value.replace('#', '0x'), 16);\n this.shadowColor = colorNum;\n console.log(`Updated shadowColor to ${value} (${colorNum})`);\n }\n break;\n \n case 'shadowAlpha':\n this.shadowAlpha = Number(value);\n console.log(`Updated shadowAlpha to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n } catch (error) {\n console.error(`Failed to update parameter ${key} using updateUIParam:`, error);\n \n // Still store the value in customParams even if setting it failed\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n \n return false;\n }\n };\n \n console.log('Bevel filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create Bevel filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n rotation: 45,\n thickness: 2,\n lightColor: '#ffffff',\n lightAlpha: 0.7,\n shadowColor: '#000000',\n shadowAlpha: 0.7\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'rotation',\n type: 'slider',\n label: 'Angle',\n property: 'rotation',\n min: 0,\n max: 360,\n step: 1,\n default: 45,\n },\n {\n id: 'thickness',\n type: 'slider',\n label: 'Thickness',\n property: 'thickness',\n min: 0,\n max: 10,\n step: 0.1,\n default: 2,\n },\n {\n id: 'lightColor',\n type: 'color',\n label: 'Light Color',\n property: 'lightColor',\n default: '#ffffff',\n },\n {\n id: 'lightAlpha',\n type: 'slider',\n label: 'Light Opacity',\n property: 'lightAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.7,\n },\n {\n id: 'shadowColor',\n type: 'color',\n label: 'Shadow Color',\n property: 'shadowColor',\n default: '#000000',\n },\n {\n id: 'shadowAlpha',\n type: 'slider',\n label: 'Shadow Opacity',\n property: 'shadowAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.7,\n }\n ],\n});","/**\n * Bloom Filter Definition\n * Creates a glowing effect by emphasizing bright areas\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { BloomFilter } = PixiFilters;\n\n// Register the bloom filter\nexport default registerFilter({\n id: 'bloom',\n name: 'Bloom/Glow',\n category: 'light',\n description: 'Add a subtle glow effect to bright areas of the image',\n \n // Create an instance of the BloomFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating BloomFilter with params:', params);\n \n // Ensure parameters have default values if missing\n const strengthX = typeof params.strengthX === 'number' ? params.strengthX : 2;\n const strengthY = typeof params.strengthY === 'number' ? params.strengthY : 2;\n const quality = typeof params.quality === 'number' ? params.quality : 4;\n const resolution = typeof params.resolution === 'number' ? params.resolution : 1;\n const kernelSize = typeof params.kernelSize === 'number' ? params.kernelSize : 5;\n \n // Create the filter with proper options - force cast types to numbers\n const filter = new BloomFilter({\n strength: { \n x: Number(strengthX), \n y: Number(strengthY)\n },\n quality: Number(quality),\n resolution: Number(resolution),\n kernelSize: Number(kernelSize)\n });\n \n // Log the actual filter object to see its properties\n console.log('Created BloomFilter instance with properties:', {\n strength: filter.strength,\n quality: (filter as any).quality,\n resolution: filter.resolution,\n kernelSize: (filter as any).kernelSize\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n strengthX: strengthX,\n strengthY: strengthY,\n quality: quality,\n resolution: resolution,\n kernelSize: kernelSize\n };\n \n // Add a more direct approach to updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`BloomFilter.updateUIParam called: ${key} = ${value}`);\n \n // Force numeric conversion\n const numValue = Number(value);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = numValue;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'strengthX':\n // Direct property access to ensure the update happens\n if (this.strength && typeof this.strength === 'object') {\n this.strength.x = numValue;\n // Force a refresh of the internal filters\n this._updateStrength?.();\n console.log(`Updated strengthX to ${numValue}`, this.strength);\n } else {\n console.warn('Filter strength property not found or not an object');\n }\n break;\n \n case 'strengthY':\n // Direct property access to ensure the update happens\n if (this.strength && typeof this.strength === 'object') {\n this.strength.y = numValue;\n // Force a refresh of the internal filters\n this._updateStrength?.();\n console.log(`Updated strengthY to ${numValue}`, this.strength);\n } else {\n console.warn('Filter strength property not found or not an object');\n }\n break;\n \n case 'quality':\n (this as any).quality = numValue;\n console.log(`Updated quality to ${(this as any).quality}`);\n break;\n\n case 'resolution':\n this.resolution = numValue;\n console.log(`Updated resolution to ${this.resolution}`);\n break;\n\n case 'kernelSize':\n (this as any).kernelSize = numValue;\n console.log(`Updated kernelSize to ${(this as any).kernelSize}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = numValue;\n console.log(`Updated ${key} to ${numValue}`);\n } else {\n console.warn(`Unknown parameter for BloomFilter: ${key}`);\n }\n break;\n }\n \n // Log the current state after updates\n console.log('BloomFilter state after update:', {\n strength: this.strength,\n quality: (this as any).quality,\n resolution: this.resolution,\n kernelSize: (this as any).kernelSize\n });\n } catch (error) {\n console.error(`Error updating BloomFilter parameter ${key}:`, error);\n }\n };\n \n console.log('BloomFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create BloomFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strengthX: 2,\n strengthY: 2,\n quality: 4,\n resolution: 1,\n kernelSize: 5\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strengthX',\n type: 'slider',\n label: 'Horizontal Strength',\n property: 'strengthX',\n min: 0,\n max: 20,\n step: 0.1,\n default: 2,\n },\n {\n id: 'strengthY',\n type: 'slider',\n label: 'Vertical Strength',\n property: 'strengthY',\n min: 0,\n max: 20,\n step: 0.1,\n default: 2,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 }\n ],\n default: 5,\n }\n ],\n});","/**\n * Bulge Pinch Filter Definition\n * Creates a bulge or pinch effect in a circular area\n */\nimport { registerFilter } from '../registry';\n// Import the BulgePinchFilter using wildcard import pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { BulgePinchFilter } = PixiFilters;\n\n/**\n * Bulge-pinch paints displaced pixels that can extend up to `radius` past\n * the sprite edge when the effect's center is near the boundary. PIXI's\n * default filter bounds match the sprite rect, so without explicit padding\n * the bulge gets clipped at the image edge. Reserve a ring of `radius`\n * pixels around the sprite for the filter to render into.\n */\nconst computeBulgePadding = (radius: number): number => {\n const r = Math.max(0, Number(radius) || 0);\n return Math.ceil(r + 2);\n};\n\nexport default registerFilter({\n id: 'bulge-pinch',\n name: 'Bulge/Pinch',\n category: 'distortion',\n description: 'Creates a bulge or pinch effect in a circular area',\n\n createFilter: (params) => {\n try {\n const centerX = params.centerX ?? 0.5;\n const centerY = params.centerY ?? 0.5;\n const radius = params.radius ?? 100;\n const strength = params.strength ?? 1;\n\n const filter = new BulgePinchFilter({\n center: { x: centerX, y: centerY },\n radius,\n strength,\n });\n\n // Reserve room for the bulge to extend past the sprite. Setting\n // .padding forces PIXI to allocate a larger filter framebuffer so\n // the effect renders completely instead of clipping at the image\n // edge. Also expose _exportPadding so the renderer's bbox-based\n // trim path knows how far out to scan for non-transparent content.\n const padding = computeBulgePadding(radius);\n filter.padding = Math.max(filter.padding ?? 0, padding);\n (filter as any)._exportPadding = padding;\n\n (filter as any)._customParams = { ...params };\n\n const refreshPadding = (f: any) => {\n const r = Number(f._customParams?.radius ?? f.radius ?? 0);\n const p = computeBulgePadding(r);\n f._exportPadding = p;\n f.padding = Math.max(f.padding ?? 0, p);\n };\n\n (filter as any).updateUIParam = function (key: string, value: any) {\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n\n switch (key) {\n case 'centerX':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.x = value;\n break;\n\n case 'centerY':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.y = value;\n break;\n\n case 'radius':\n this.radius = Number(value);\n refreshPadding(this);\n break;\n\n case 'strength':\n this.strength = Number(value);\n break;\n\n default:\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n\n return true;\n };\n\n /**\n * Build a fresh BulgePinchFilter sized for export.\n *\n * The radius value is in render-target pixels. The user tunes it\n * while looking at the preview, where the image is downscaled. To\n * preserve the visual proportions on the native-size export,\n * scale radius by preview-to-native. Same pattern as drop-shadow.\n * (centerX/centerY are unitless 0-1, strength is unitless; they\n * don't scale.)\n */\n (filter as any).createExportFilter = function (options: { previewToNativeScale?: number } = {}) {\n const scale = Number.isFinite(options.previewToNativeScale)\n ? Math.max(1, Number(options.previewToNativeScale))\n : 1;\n const stored = (this as any)._customParams || params;\n\n const scaledRadius = Number(stored.radius ?? 100) * scale;\n const next = new BulgePinchFilter({\n center: {\n x: Number(stored.centerX ?? 0.5),\n y: Number(stored.centerY ?? 0.5),\n },\n radius: scaledRadius,\n strength: Number(stored.strength ?? 1),\n });\n\n const padding = computeBulgePadding(scaledRadius);\n (next as any)._exportPadding = padding;\n next.padding = Math.max(next.padding ?? 0, padding);\n return next;\n };\n\n (filter as any).getExportPadding = function () {\n return Number((this as any)._exportPadding || this.padding || 0);\n };\n\n return filter;\n } catch (error) {\n console.error('Failed to create BulgePinchFilter:', error);\n return null;\n }\n },\n\n defaultParams: {\n centerX: 0.5,\n centerY: 0.5,\n radius: 100,\n strength: 1,\n },\n\n controls: [\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: 0,\n max: 1000,\n step: 1,\n default: 100,\n },\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: -1,\n max: 1,\n step: 0.01,\n default: 1,\n },\n ],\n});\n","/**\n * Convolution Matrix Filter Definition\n * Applies a matrix convolution filter for effects like blur, sharpen, edge detection\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access ConvolutionFilter from the pixi-filters package\nconst { ConvolutionFilter } = PixiFilters;\n\n// Predefined convolution matrices for common effects\nconst MATRICES = {\n normal: [0, 0, 0, 0, 1, 0, 0, 0, 0],\n gaussianBlur: [0.045, 0.122, 0.045, 0.122, 0.332, 0.122, 0.045, 0.122, 0.045],\n boxBlur: [1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9],\n edgeDetection: [-1, -1, -1, -1, 8, -1, -1, -1, -1],\n edgeEnhance: [0, 0, 0, -1, 1, 0, 0, 0, 0],\n emboss: [-2, -1, 0, -1, 1, 1, 0, 1, 2],\n sharpen: [0, -1, 0, -1, 5, -1, 0, -1, 0],\n sobelHorizontal: [1, 2, 1, 0, 0, 0, -1, -2, -1],\n sobelVertical: [1, 0, -1, 2, 0, -2, 1, 0, -1],\n};\n\nexport default registerFilter({\n id: 'convolution',\n name: 'Convolution Matrix',\n category: 'effects',\n description: 'Apply custom image effects using matrix convolution',\n \n createFilter: (params) => {\n try {\n console.log('Creating ConvolutionFilter with params:', params);\n \n // Get the appropriate matrix based on the selected preset or use custom values\n let matrix;\n \n if (params.customMatrix) {\n // Create matrix from individual matrix element values\n matrix = [\n params.m00, params.m01, params.m02,\n params.m10, params.m11, params.m12,\n params.m20, params.m21, params.m22\n ];\n } else {\n // Use preset matrix with type safety\n const presetKey = params.preset as keyof typeof MATRICES;\n matrix = MATRICES[presetKey] || MATRICES.normal;\n }\n \n // Create the filter with direct constructor call (PIXI v8 API)\n const filter = new ConvolutionFilter(matrix as any, params.width || 200, params.height || 200);\n\n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for UI parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'preset':\n // Update matrix from preset\n if (!customParams.customMatrix) {\n const presetKey = value as keyof typeof MATRICES;\n if (MATRICES[presetKey]) {\n this.matrix = MATRICES[presetKey];\n }\n }\n break;\n \n case 'customMatrix':\n // Toggle between preset and custom matrix\n if (value) {\n // Switch to custom matrix - copy current values to individual parameters\n const currentMatrix = this.matrix;\n customParams.m00 = currentMatrix[0];\n customParams.m01 = currentMatrix[1];\n customParams.m02 = currentMatrix[2];\n customParams.m10 = currentMatrix[3];\n customParams.m11 = currentMatrix[4];\n customParams.m12 = currentMatrix[5];\n customParams.m20 = currentMatrix[6];\n customParams.m21 = currentMatrix[7];\n customParams.m22 = currentMatrix[8];\n } else {\n // Switch back to preset\n const presetKey = customParams.preset as keyof typeof MATRICES;\n this.matrix = MATRICES[presetKey] || MATRICES.normal;\n }\n break;\n \n // Handle individual matrix element updates\n case 'm00': case 'm01': case 'm02':\n case 'm10': case 'm11': case 'm12':\n case 'm20': case 'm21': case 'm22':\n if (customParams.customMatrix) {\n // Update the matrix if in custom matrix mode\n const newMatrix = [...this.matrix];\n \n // Map UI parameter to matrix index\n const indices: Record<string, number> = {\n 'm00': 0, 'm01': 1, 'm02': 2,\n 'm10': 3, 'm11': 4, 'm12': 5,\n 'm20': 6, 'm21': 7, 'm22': 8\n };\n \n const idx = indices[key];\n if (idx !== undefined) {\n newMatrix[idx] = value;\n this.matrix = newMatrix;\n }\n }\n break;\n \n case 'width':\n this.width = value;\n break;\n \n case 'height':\n this.height = value;\n break;\n \n default:\n // For any other parameters that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create ConvolutionFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n preset: 'normal',\n customMatrix: false,\n m00: 0, m01: 0, m02: 0,\n m10: 0, m11: 1, m12: 0,\n m20: 0, m21: 0, m22: 0,\n width: 200,\n height: 200\n },\n \n controls: [\n {\n id: 'preset',\n type: 'select',\n label: 'Effect Preset',\n property: 'preset',\n options: [\n { value: 'normal', label: 'Normal' },\n { value: 'gaussianBlur', label: 'Gaussian Blur' },\n { value: 'boxBlur', label: 'Box Blur' },\n { value: 'edgeDetection', label: 'Edge Detection' },\n { value: 'edgeEnhance', label: 'Edge Enhance' },\n { value: 'emboss', label: 'Emboss' },\n { value: 'sharpen', label: 'Sharpen' },\n { value: 'sobelHorizontal', label: 'Sobel Horizontal' },\n { value: 'sobelVertical', label: 'Sobel Vertical' }\n ],\n default: 'normal'\n },\n {\n id: 'customMatrix',\n type: 'toggle',\n label: 'Use Custom Matrix',\n property: 'customMatrix',\n default: false\n },\n {\n id: 'width',\n type: 'slider',\n label: 'Width',\n property: 'width',\n min: 50,\n max: 500,\n step: 10,\n default: 200\n },\n {\n id: 'height',\n type: 'slider',\n label: 'Height',\n property: 'height',\n min: 50,\n max: 500,\n step: 10,\n default: 200\n },\n {\n id: 'm00',\n type: 'slider',\n label: 'Matrix [0,0]',\n property: 'm00',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm01',\n type: 'slider',\n label: 'Matrix [0,1]',\n property: 'm01',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm02',\n type: 'slider',\n label: 'Matrix [0,2]',\n property: 'm02',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm10',\n type: 'slider',\n label: 'Matrix [1,0]',\n property: 'm10',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm11',\n type: 'slider',\n label: 'Matrix [1,1]',\n property: 'm11',\n min: -5,\n max: 5,\n step: 0.1,\n default: 1\n },\n {\n id: 'm12',\n type: 'slider',\n label: 'Matrix [1,2]',\n property: 'm12',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm20',\n type: 'slider',\n label: 'Matrix [2,0]',\n property: 'm20',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm21',\n type: 'slider',\n label: 'Matrix [2,1]',\n property: 'm21',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm22',\n type: 'slider',\n label: 'Matrix [2,2]',\n property: 'm22',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n }\n ]\n});","/**\n * Cross Hatch Filter Definition\n * Creates a crosshatching effect like in a pencil drawing\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { CrossHatchFilter } = PixiFilters;\n\n// Register the CrossHatch filter\nexport default registerFilter({\n id: 'cross-hatch',\n name: 'Cross Hatch',\n category: 'stylize',\n description: 'Creates a crosshatching effect like in a pencil drawing',\n \n // Create an instance of the CrossHatchFilter\n // Note: CrossHatchFilter has NO parameters according to PixiJS examples\n createFilter: (_params) => {\n try {\n console.log('Creating CrossHatchFilter');\n \n // Create the filter - CrossHatchFilter has no constructor parameters\n const filter = new CrossHatchFilter();\n \n // Add a minimal updateUIParam method for consistency\n // Even though CrossHatchFilter has no parameters to update\n (filter as any).updateUIParam = function(key: string, value: any) {\n console.log(`CrossHatchFilter has no configurable parameters. Ignoring: ${key} = ${value}`);\n return true;\n };\n \n console.log('CrossHatchFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create CrossHatchFilter:', error);\n return null;\n }\n },\n \n // No parameters for this filter\n defaultParams: {},\n \n // No UI controls since CrossHatchFilter has no parameters\n controls: [],\n});","/**\n * CRT Screen Filter Definition\n * Simulates an old CRT screen with scan lines and noise\n */\nimport { registerFilter } from '../registry';\nimport * as filters from 'pixi-filters';\n\n// Register the CRT filter\nexport default registerFilter({\n id: 'crt',\n name: 'CRT Screen',\n category: 'stylize',\n description: 'Simulates an old CRT screen with scan lines and noise',\n \n // Create an instance of the CRTFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating CRTFilter with params:', params);\n \n // Ensure parameters have default values\n const options = {\n lineWidth: typeof params.lineWidth === 'number' ? params.lineWidth : 1.0,\n noise: typeof params.noise === 'number' ? params.noise : 0.3,\n curvature: typeof params.curvature === 'number' ? params.curvature : 1.0,\n lineContrast: typeof params.lineContrast === 'number' ? params.lineContrast : 0.25,\n verticalLine: params.verticalLine === true,\n noiseSize: typeof params.noiseSize === 'number' ? params.noiseSize : 1.0,\n vignetting: typeof params.vignetting === 'number' ? params.vignetting : 0.3,\n vignettingAlpha: typeof params.vignettingAlpha === 'number' ? params.vignettingAlpha : 1.0,\n vignettingBlur: typeof params.vignettingBlur === 'number' ? params.vignettingBlur : 0.3,\n time: typeof params.time === 'number' ? params.time : 0.0,\n seed: typeof params.seed === 'number' ? params.seed : Math.random()\n };\n \n // Create the filter with proper options\n const filter = new filters.CRTFilter(options);\n \n // Store custom parameters for reference\n (filter as any)._customParams = { ...options };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`CRTFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key with proper type conversion\n switch (key) {\n case 'lineWidth':\n this.lineWidth = Number(value);\n console.log(`Updated lineWidth to ${this.lineWidth}`);\n break;\n \n case 'noise':\n this.noise = Number(value);\n console.log(`Updated noise to ${this.noise}`);\n break;\n \n case 'curvature':\n this.curvature = Number(value);\n console.log(`Updated curvature to ${this.curvature}`);\n break;\n \n case 'lineContrast':\n this.lineContrast = Number(value);\n console.log(`Updated lineContrast to ${this.lineContrast}`);\n break;\n \n case 'verticalLine':\n this.verticalLine = Boolean(value);\n console.log(`Updated verticalLine to ${this.verticalLine}`);\n break;\n \n case 'noiseSize':\n this.noiseSize = Number(value);\n console.log(`Updated noiseSize to ${this.noiseSize}`);\n break;\n \n case 'vignetting':\n this.vignetting = Number(value);\n console.log(`Updated vignetting to ${this.vignetting}`);\n break;\n \n case 'vignettingAlpha':\n this.vignettingAlpha = Number(value);\n console.log(`Updated vignettingAlpha to ${this.vignettingAlpha}`);\n break;\n \n case 'vignettingBlur':\n this.vignettingBlur = Number(value);\n console.log(`Updated vignettingBlur to ${this.vignettingBlur}`);\n break;\n \n case 'time':\n this.time = Number(value);\n console.log(`Updated time to ${this.time}`);\n break;\n \n case 'seed':\n this.seed = Number(value);\n console.log(`Updated seed to ${this.seed}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for CRTFilter: ${key}`);\n }\n break;\n }\n \n // Log current state\n console.log('CRTFilter state:', {\n lineWidth: this.lineWidth,\n noise: this.noise,\n curvature: this.curvature,\n verticalLine: this.verticalLine,\n time: this.time\n });\n } catch (error) {\n console.error(`Error updating CRTFilter parameter ${key}:`, error);\n }\n };\n \n console.log('CRTFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create CRTFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n lineWidth: 1.0,\n noise: 0.3,\n curvature: 1.0,\n lineContrast: 0.25,\n verticalLine: false,\n noiseSize: 1.0,\n vignetting: 0.3,\n vignettingAlpha: 1.0,\n vignettingBlur: 0.3,\n time: 0.0,\n seed: 1.0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'lineWidth',\n type: 'slider',\n label: 'Scan Line Width',\n property: 'lineWidth',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'noise',\n type: 'slider',\n label: 'Noise Amount',\n property: 'noise',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3,\n },\n {\n id: 'curvature',\n type: 'slider',\n label: 'Screen Curvature',\n property: 'curvature',\n min: 0,\n max: 10,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'lineContrast',\n type: 'slider',\n label: 'Line Contrast',\n property: 'lineContrast',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.25,\n },\n {\n id: 'verticalLine',\n type: 'toggle',\n label: 'Vertical Lines',\n property: 'verticalLine',\n default: false,\n },\n {\n id: 'noiseSize',\n type: 'slider',\n label: 'Noise Size',\n property: 'noiseSize',\n min: 0.5,\n max: 5,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'vignetting',\n type: 'slider',\n label: 'Vignette Size',\n property: 'vignetting',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3,\n },\n {\n id: 'vignettingAlpha',\n type: 'slider',\n label: 'Vignette Opacity',\n property: 'vignettingAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1.0,\n },\n {\n id: 'vignettingBlur',\n type: 'slider',\n label: 'Vignette Blur',\n property: 'vignettingBlur',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Animation Time',\n property: 'time',\n min: 0,\n max: 10,\n step: 0.1,\n default: 0.0,\n }\n ],\n});","/**\n * Displacement Filter Definition\n * Applies a displacement map effect to distort the image\n */\nimport { registerFilter } from '../registry';\n// Import PIXI namespace\nimport * as PIXI from 'pixi.js';\n\n// Access classes via direct indexing\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst DisplacementFilter = PIXI['DisplacementFilter']; \n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst Sprite = PIXI['Sprite'];\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst Texture = PIXI['Texture'];\n\n// Register the Displacement filter\nexport default registerFilter({\n id: 'displacement', // ID must match what the application expects\n name: 'Displacement Map',\n category: 'distortion',\n description: 'Distorts the image using a displacement map texture',\n \n // Create an instance of the DisplacementFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating DisplacementFilter with params:', params);\n \n // The displacement map texture URL (default or from params)\n const mapUrl = params.mapTexture || '/assets/images/displacement_map.png';\n \n // Create a texture from the map URL\n let mapTexture;\n try {\n mapTexture = Texture.from(mapUrl);\n // Set the texture to repeat\n mapTexture.source.addressMode = 'repeat';\n } catch (error) {\n console.error('Failed to load displacement map texture:', error);\n // Create a fallback texture\n const canvas = document.createElement('canvas');\n canvas.width = 256;\n canvas.height = 256;\n const ctx = canvas.getContext('2d');\n if (ctx) {\n // Draw a simple pattern\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.fillStyle = '#000000';\n for (let i = 0; i < 10; i++) {\n for (let j = 0; j < 10; j++) {\n if ((i + j) % 2 === 0) {\n ctx.fillRect(i * 25, j * 25, 25, 25);\n }\n }\n }\n }\n mapTexture = Texture.from(canvas);\n }\n \n // Create sprite for the displacement map\n const displacementSprite = new Sprite(mapTexture);\n \n // Create the filter with the sprite and scale\n const filter = new DisplacementFilter(displacementSprite, params.scale || 50);\n \n // Set individual scale components\n filter.scale.x = params.scaleX || 50;\n filter.scale.y = params.scaleY || 50;\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n (filter as any)._displacementSprite = displacementSprite;\n \n /**\n * Custom method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'scaleX':\n this.scale.x = value;\n console.log(`Updated scale.x to ${value}`);\n break;\n \n case 'scaleY':\n this.scale.y = value;\n console.log(`Updated scale.y to ${value}`);\n break;\n \n case 'mapTexture':\n try {\n // Try to update the sprite's texture\n const sprite = (this as any)._displacementSprite;\n if (sprite) {\n const newTexture = Texture.from(value);\n newTexture.source.addressMode = 'repeat';\n sprite.texture = newTexture;\n console.log(`Updated displacement map texture to ${value}`);\n }\n } catch (error) {\n console.error('Failed to update displacement map texture:', error);\n }\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else if (key in this.scale) {\n this.scale[key] = value;\n console.log(`Updated scale.${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('DisplacementFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create DisplacementFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n mapTexture: '/assets/images/displacement_map.png',\n scale: 50,\n scaleX: 50,\n scaleY: 50\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'mapTexture',\n type: 'select',\n label: 'Displacement Map',\n property: 'mapTexture',\n options: [\n { label: 'Default', value: '/assets/images/displacement_map.png' },\n { label: 'Clouds', value: '/assets/images/clouds.png' },\n { label: 'Ripple', value: '/assets/images/ripple.png' }\n ],\n default: '/assets/images/displacement_map.png',\n },\n {\n id: 'scaleX',\n type: 'slider',\n label: 'Scale X',\n property: 'scaleX',\n min: 1,\n max: 200,\n step: 1,\n default: 50,\n },\n {\n id: 'scaleY',\n type: 'slider',\n label: 'Scale Y',\n property: 'scaleY',\n min: 1,\n max: 200,\n step: 1,\n default: 50,\n }\n ],\n});","/**\n * Dot Screen Filter Definition\n * Simulates a halftone printing pattern with dots\n */\nimport { registerFilter } from '../registry';\nimport * as filters from 'pixi-filters';\n\n// Register the Dot Screen filter\nexport default registerFilter({\n id: 'dot',\n name: 'Dot Screen',\n category: 'stylize',\n description: 'Simulates a halftone printing pattern with dots',\n \n // Create an instance of the DotFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating DotFilter with params:', params);\n \n // Ensure parameters have default values\n const options = {\n scale: typeof params.scale === 'number' ? params.scale : 1,\n angle: typeof params.angle === 'number' ? params.angle : 5,\n grayscale: params.grayscale === true\n };\n \n // Create the filter with proper options\n const filter = new filters.DotFilter(options);\n \n // Store custom parameters for reference\n (filter as any)._customParams = { ...options };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`DotFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key with proper type conversion\n switch (key) {\n case 'scale':\n this.scale = Number(value);\n console.log(`Updated scale to ${this.scale}`);\n break;\n \n case 'angle':\n this.angle = Number(value);\n console.log(`Updated angle to ${this.angle}`);\n break;\n \n case 'grayscale':\n this.grayscale = Boolean(value);\n console.log(`Updated grayscale to ${this.grayscale}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for DotFilter: ${key}`);\n }\n break;\n }\n \n // Log current state\n console.log('DotFilter state:', {\n scale: this.scale,\n angle: this.angle,\n grayscale: this.grayscale\n });\n } catch (error) {\n console.error(`Error updating DotFilter parameter ${key}:`, error);\n }\n };\n \n console.log('DotFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create DotFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n scale: 1,\n angle: 5,\n grayscale: true\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'scale',\n type: 'slider',\n label: 'Dot Scale',\n property: 'scale',\n min: 0.5,\n max: 10,\n step: 0.1,\n default: 1,\n },\n {\n id: 'angle',\n type: 'slider',\n label: 'Dot Angle',\n property: 'angle',\n min: 0,\n max: 10,\n step: 0.1,\n default: 5,\n },\n {\n id: 'grayscale',\n type: 'toggle',\n label: 'Grayscale',\n property: 'grayscale',\n default: true,\n }\n ],\n});","/**\n * Emboss Filter Definition\n * Creates an embossed relief effect using the proper EmbossFilter from pixi-filters\n */\nimport { registerFilter } from '../registry';\n// Import EmbossFilter from pixi-filters\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { EmbossFilter } = PixiFilters;\n\n// Register the Emboss filter\nexport default registerFilter({\n id: 'emboss',\n name: 'Emboss',\n category: 'stylize',\n description: 'Creates an embossed relief effect',\n \n // Create an instance of the Emboss filter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating Emboss filter with params:', params);\n \n // Ensure parameters have default values\n const strength = typeof params.strength === 'number' ? params.strength : 5;\n \n // Use the proper EmbossFilter from pixi-filters\n const filter = new EmbossFilter(strength);\n \n console.log('Created emboss effect with EmbossFilter, strength:', strength);\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n strength: strength\n };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`Emboss filter updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates\n switch (key) {\n case 'strength':\n const numValue = Number(value);\n customParams.strength = numValue;\n \n // For EmbossFilter, set the strength property directly\n this.strength = numValue;\n \n console.log(`Updated EmbossFilter strength to ${numValue}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for EmbossFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating emboss filter parameter ${key}:`, error);\n }\n };\n \n console.log('Emboss filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create emboss filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strength: 5\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 20,\n step: 0.5,\n default: 5,\n }\n ],\n});","/**\n * Glitch Filter Definition\n * Applies digital distortion and glitch effects to images\n */\nimport { registerFilter } from '../registry';\n// Import the GlitchFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { GlitchFilter } = PixiFilters;;\n\n// Define constants for fill modes\nconst FILL_MODES = {\n TRANSPARENT: 0,\n ORIGINAL: 1,\n LOOP: 2,\n CLAMP: 3,\n MIRROR: 4\n};\n\nexport default registerFilter({\n id: 'glitch',\n name: 'Glitch',\n category: 'effects',\n description: 'Apply digital distortion and glitch effects',\n \n createFilter: (params) => {\n try {\n console.log('Creating GlitchFilter with params:', params);\n \n // Create color offset objects from individual components\n const redOffset = { x: params.redX, y: params.redY };\n const greenOffset = { x: params.greenX, y: params.greenY };\n const blueOffset = { x: params.blueX, y: params.blueY };\n \n // Create the filter with options\n const filter = new GlitchFilter({\n slices: params.slices,\n offset: params.offset,\n direction: params.direction,\n fillMode: params.fillMode,\n seed: params.seed,\n average: params.average,\n minSize: params.minSize,\n sampleSize: params.sampleSize,\n red: redOffset,\n green: greenOffset,\n blue: blueOffset\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Trigger a refresh to ensure the filter initializes correctly\n if (typeof filter.refresh === 'function') {\n filter.refresh();\n }\n \n // Set up an animation loop for the filter if it's animating\n let animationFrameId: number | null = null;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update the seed with a random value for animation\n filter.seed = Math.random();\n }\n // Continue the animation loop\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if needed\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for dynamic UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if it's not running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'slices':\n // Ensure slices is an integer\n this.slices = Math.round(value);\n break;\n \n case 'redX':\n case 'redY':\n // Update red offset\n const red = this.red;\n if (key === 'redX') red.x = value;\n else red.y = value;\n this.red = red;\n break;\n \n case 'greenX':\n case 'greenY':\n // Update green offset\n const green = this.green;\n if (key === 'greenX') green.x = value;\n else green.y = value;\n this.green = green;\n break;\n \n case 'blueX':\n case 'blueY':\n // Update blue offset\n const blue = this.blue;\n if (key === 'blueX') blue.x = value;\n else blue.y = value;\n this.blue = blue;\n break;\n \n case 'seed':\n // Only update seed manually if not animating\n if (!(this as any).animating) {\n this.seed = value;\n }\n break;\n \n case 'randomizeSeed':\n // Action button to randomize seed\n if (value && !customParams.animating) {\n this.seed = Math.random();\n }\n break;\n \n case 'refresh':\n // Action button to refresh the filter\n if (value) {\n try {\n this.refresh();\n } catch (e) {\n console.warn('Error refreshing GlitchFilter:', e);\n }\n }\n break;\n \n // Handle direct properties\n case 'offset':\n case 'direction':\n case 'fillMode':\n case 'average':\n case 'minSize':\n case 'sampleSize':\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create GlitchFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n slices: 10,\n offset: 100,\n direction: 0,\n fillMode: FILL_MODES.LOOP, // LOOP mode looks better for the demo\n seed: 0.5,\n average: false,\n minSize: 8,\n sampleSize: 512,\n redX: 2,\n redY: 2,\n greenX: -10,\n greenY: 4,\n blueX: 10,\n blueY: -4,\n animating: false, // Control for automatic animation\n randomizeSeed: false, // Button trigger for randomizing seed\n refresh: false, // Button trigger for refreshing the filter\n },\n \n controls: [\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Automatically',\n property: 'animating',\n default: false\n },\n {\n id: 'slices',\n type: 'slider',\n label: 'Slices',\n property: 'slices',\n min: 2,\n max: 20,\n step: 1,\n default: 10\n },\n {\n id: 'offset',\n type: 'slider',\n label: 'Offset Amount',\n property: 'offset',\n min: -400,\n max: 400,\n step: 1,\n default: 100\n },\n {\n id: 'direction',\n type: 'slider',\n label: 'Direction',\n property: 'direction',\n min: -180,\n max: 180,\n step: 1,\n default: 0\n },\n {\n id: 'fillMode',\n type: 'select',\n label: 'Fill Mode',\n property: 'fillMode',\n options: [\n { value: FILL_MODES.TRANSPARENT, label: 'Transparent' },\n { value: FILL_MODES.ORIGINAL, label: 'Original' },\n { value: FILL_MODES.LOOP, label: 'Loop' },\n { value: FILL_MODES.CLAMP, label: 'Clamp' },\n { value: FILL_MODES.MIRROR, label: 'Mirror' }\n ],\n default: FILL_MODES.LOOP\n },\n {\n id: 'seed',\n type: 'slider',\n label: 'Seed',\n property: 'seed',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Seed',\n action: 'randomizeSeed'\n },\n {\n id: 'refresh',\n type: 'button',\n label: 'Refresh Filter',\n action: 'refresh'\n },\n {\n id: 'average',\n type: 'toggle',\n label: 'Average Slices',\n property: 'average',\n default: false\n },\n // Color channel offsets\n {\n id: 'redX',\n type: 'slider',\n label: 'Red X Offset',\n property: 'redX',\n min: -50,\n max: 50,\n step: 0.5,\n default: 2\n },\n {\n id: 'redY',\n type: 'slider',\n label: 'Red Y Offset',\n property: 'redY',\n min: -50,\n max: 50,\n step: 0.5,\n default: 2\n },\n {\n id: 'greenX',\n type: 'slider',\n label: 'Green X Offset',\n property: 'greenX',\n min: -50,\n max: 50,\n step: 0.5,\n default: -10\n },\n {\n id: 'greenY',\n type: 'slider',\n label: 'Green Y Offset',\n property: 'greenY',\n min: -50,\n max: 50,\n step: 0.5,\n default: 4\n },\n {\n id: 'blueX',\n type: 'slider',\n label: 'Blue X Offset',\n property: 'blueX',\n min: -50,\n max: 50,\n step: 0.5,\n default: 10\n },\n {\n id: 'blueY',\n type: 'slider',\n label: 'Blue Y Offset',\n property: 'blueY',\n min: -50,\n max: 50,\n step: 0.5,\n default: -4\n }\n ]\n});","/**\n * Glow Filter Definition\n * Applies a customizable glow effect around the image\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { GlowFilter } = PixiFilters;;\n\n// Register the Glow filter\nexport default registerFilter({\n id: 'glow',\n name: 'Glow',\n category: 'light',\n description: 'Adds a customizable glow effect around the image',\n \n // Create an instance of the GlowFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating GlowFilter with params:', params);\n \n // Parse color from hex string\n const color = parseInt(params.color.replace('#', '0x'), 16);\n \n // Create filter with proper options\n const filter = new GlowFilter({\n distance: params.distance || 10,\n outerStrength: params.outerStrength || 4,\n innerStrength: params.innerStrength || 0,\n color: color,\n alpha: params.alpha ?? 1,\n quality: params.quality || 0.1,\n knockout: params.knockout || false\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = { \n color: params.color || '#ffffff', \n ...params \n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'distance':\n this.distance = Number(value);\n console.log(`Updated distance to ${this.distance}`);\n break;\n \n case 'outerStrength':\n this.outerStrength = Number(value);\n console.log(`Updated outerStrength to ${this.outerStrength}`);\n break;\n \n case 'innerStrength':\n this.innerStrength = Number(value);\n console.log(`Updated innerStrength to ${this.innerStrength}`);\n break;\n \n case 'color':\n // Store the hex color for reference\n customParams.color = value;\n // Convert hex color string to number for the filter\n this.color = parseInt(value.replace('#', '0x'), 16);\n console.log(`Updated color to ${value} (${this.color})`);\n break;\n \n case 'alpha':\n this.alpha = Number(value);\n console.log(`Updated alpha to ${this.alpha}`);\n break;\n \n case 'quality':\n this.quality = Number(value);\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'knockout':\n this.knockout = Boolean(value);\n console.log(`Updated knockout to ${this.knockout}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for GlowFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating GlowFilter parameter ${key}:`, error);\n }\n };\n \n console.log('GlowFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create GlowFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n distance: 10,\n outerStrength: 4,\n innerStrength: 0,\n color: '#ffffff',\n alpha: 1,\n quality: 0.1,\n knockout: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'distance',\n type: 'slider',\n label: 'Distance',\n property: 'distance',\n min: 0,\n max: 20,\n step: 1,\n default: 10,\n },\n {\n id: 'outerStrength',\n type: 'slider',\n label: 'Outer Strength',\n property: 'outerStrength',\n min: 0,\n max: 20,\n step: 0.1,\n default: 4,\n },\n {\n id: 'innerStrength',\n type: 'slider',\n label: 'Inner Strength',\n property: 'innerStrength',\n min: 0,\n max: 20,\n step: 0.1,\n default: 0,\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#ffffff',\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 0.01,\n max: 1,\n step: 0.01,\n default: 0.1,\n },\n {\n id: 'knockout',\n type: 'toggle',\n label: 'Show Glow Only',\n property: 'knockout',\n default: false,\n }\n ],\n});","/**\n * Godray Filter Definition\n * Creates volumetric light-ray effects\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { GodrayFilter } = PixiFilters;;\n\n// Register the Godray filter\nexport default registerFilter({\n id: 'godray',\n name: 'Godray',\n category: 'light',\n description: 'Creates volumetric light-ray effects (crepuscular rays)',\n \n // Create an instance of the GodrayFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating GodrayFilter with params:', params);\n \n // Create filter with proper options\n const filter = new GodrayFilter({\n angle: params.angle || 30,\n parallel: params.parallel ?? true,\n center: { \n x: params.centerX || 0, \n y: params.centerY || 0 \n },\n gain: params.gain || 0.5,\n lacunarity: params.lacunarity || 2.5,\n time: params.time || 0,\n alpha: params.alpha || 1\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = { \n centerX: params.centerX || 0,\n centerY: params.centerY || 0,\n ...params \n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'angle':\n this.angle = Number(value);\n console.log(`Updated angle to ${this.angle}`);\n break;\n \n case 'parallel':\n this.parallel = Boolean(value);\n console.log(`Updated parallel to ${this.parallel}`);\n break;\n \n case 'centerX':\n customParams.centerX = Number(value);\n // Need to update the entire center object\n this.center = { \n x: Number(value), \n y: customParams.centerY \n };\n console.log(`Updated centerX to ${value}`);\n break;\n \n case 'centerY':\n customParams.centerY = Number(value);\n // Need to update the entire center object\n this.center = { \n x: customParams.centerX, \n y: Number(value) \n };\n console.log(`Updated centerY to ${value}`);\n break;\n \n case 'gain':\n this.gain = Number(value);\n console.log(`Updated gain to ${this.gain}`);\n break;\n \n case 'lacunarity':\n this.lacunarity = Number(value);\n console.log(`Updated lacunarity to ${this.lacunarity}`);\n break;\n \n case 'time':\n this.time = Number(value);\n console.log(`Updated time to ${this.time}`);\n break;\n \n case 'alpha':\n this.alpha = Number(value);\n console.log(`Updated alpha to ${this.alpha}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for GodrayFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating GodrayFilter parameter ${key}:`, error);\n }\n };\n \n console.log('GodrayFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create GodrayFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n angle: 30,\n parallel: true,\n centerX: 0,\n centerY: 0,\n gain: 0.5,\n lacunarity: 2.5,\n time: 0,\n alpha: 1\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: 0,\n max: 360,\n step: 1,\n default: 30,\n },\n {\n id: 'parallel',\n type: 'toggle',\n label: 'Parallel Rays',\n property: 'parallel',\n default: true,\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Light Source X',\n property: 'centerX',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Light Source Y',\n property: 'centerY',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'gain',\n type: 'slider',\n label: 'Gain/Intensity',\n property: 'gain',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'lacunarity',\n type: 'slider',\n label: 'Density',\n property: 'lacunarity',\n min: 0.1,\n max: 10,\n step: 0.1,\n default: 2.5,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Time',\n property: 'time',\n min: 0,\n max: 10,\n step: 0.1,\n default: 0,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n }\n ],\n});","/**\n * Lightmap Filter Definition\n * Applies a lighting effect using a reference texture as a light map\n */\nimport { registerFilter } from '../registry';\n// Import packages\nimport * as PixiFilters from 'pixi-filters';\nimport * as PIXI from 'pixi.js';\n\n// Access classes via direct indexing\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst SimpleLightmapFilter = PixiFilters['SimpleLightmapFilter'];\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst Texture = PIXI['Texture'];\n\n// Register the Lightmap filter\nexport default registerFilter({\n id: 'lightmap',\n name: 'Lightmap',\n category: 'light',\n description: 'Applies lighting effects using a reference texture as a light map',\n \n // Create an instance of the SimpleLightmapFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating SimpleLightmapFilter with params:', params);\n \n // Ensure we have default values\n const textureType = params.textureType || 'default';\n const colorValue = params.color || '#000000';\n const alphaValue = typeof params.alpha === 'number' ? params.alpha : 1;\n \n // Create canvas for texture generation\n const canvas = document.createElement('canvas');\n canvas.width = 256;\n canvas.height = 256;\n const ctx = canvas.getContext('2d');\n \n if (!ctx) {\n console.error('Could not get 2D context for canvas');\n throw new Error('Canvas 2D context not available');\n }\n \n // Generate a texture based on the selected type\n if (textureType === 'spotlight') {\n // Create a stronger spotlight effect\n ctx.fillStyle = 'black';\n ctx.fillRect(0, 0, 256, 256);\n \n const gradient = ctx.createRadialGradient(128, 128, 5, 128, 128, 80);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.5)'); // Stronger middle\n gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');\n \n ctx.fillStyle = gradient;\n ctx.beginPath();\n ctx.arc(128, 128, 100, 0, Math.PI * 2);\n ctx.fill();\n \n console.log('Generated spotlight texture with stronger center');\n } else if (textureType === 'softlight') {\n // Create a more pronounced soft light effect\n const gradient = ctx.createLinearGradient(0, 0, 256, 256);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.7, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'rgba(80, 80, 80, 1)');\n \n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, 256, 256);\n \n console.log('Generated enhanced softlight texture');\n } else {\n // Default - create a more pronounced radial gradient\n const gradient = ctx.createRadialGradient(128, 128, 10, 128, 128, 160);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.6, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'black');\n \n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, 256, 256);\n \n console.log('Generated enhanced default texture');\n }\n \n // Create a texture from the canvas\n const lightMapTexture = Texture.from(canvas);\n console.log('Created lightmap texture from canvas');\n \n // Parse color from hex string with safer parsing\n let color;\n try {\n // Handle potential bad color input\n if (typeof colorValue === 'string' && colorValue.startsWith('#')) {\n color = parseInt(colorValue.replace('#', '0x'), 16);\n } else {\n color = 0x000000; // Default black\n }\n } catch (e) {\n console.warn('Error parsing color, using default black');\n color = 0x000000;\n }\n \n // Create filter with proper options\n const filter = new SimpleLightmapFilter(lightMapTexture, color, alphaValue);\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n textureType: textureType,\n color: colorValue,\n alpha: alphaValue\n };\n \n // Add custom updateUIParam method with improved parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`SimpleLightmapFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'textureType':\n customParams.textureType = value;\n \n // Create a new canvas with the selected texture type\n const updateCanvas = document.createElement('canvas');\n updateCanvas.width = 256;\n updateCanvas.height = 256;\n const updateCtx = updateCanvas.getContext('2d');\n \n if (updateCtx) {\n // Generate texture based on type with stronger effects\n if (value === 'spotlight') {\n updateCtx.fillStyle = 'black';\n updateCtx.fillRect(0, 0, 256, 256);\n \n const gradient = updateCtx.createRadialGradient(128, 128, 5, 128, 128, 80);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.5)');\n gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');\n \n updateCtx.fillStyle = gradient;\n updateCtx.beginPath();\n updateCtx.arc(128, 128, 100, 0, Math.PI * 2);\n updateCtx.fill();\n } else if (value === 'softlight') {\n const gradient = updateCtx.createLinearGradient(0, 0, 256, 256);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.7, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'rgba(80, 80, 80, 1)');\n \n updateCtx.fillStyle = gradient;\n updateCtx.fillRect(0, 0, 256, 256);\n } else {\n const gradient = updateCtx.createRadialGradient(128, 128, 10, 128, 128, 160);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.6, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'black');\n \n updateCtx.fillStyle = gradient;\n updateCtx.fillRect(0, 0, 256, 256);\n }\n \n // Create a new texture\n const newTexture = Texture.from(updateCanvas);\n \n // Update the filter - directly access the property\n this.lightMap = newTexture;\n \n // Force the filter to redraw by invalidating the transform\n if (this.enabled !== undefined) {\n // Toggle enabled to force a redraw\n const wasEnabled = this.enabled;\n this.enabled = false;\n setTimeout(() => {\n this.enabled = wasEnabled;\n }, 0);\n }\n \n console.log(`Updated lightMap texture to ${value} type`);\n }\n break;\n \n case 'color':\n // Store the hex color for reference\n customParams.color = value;\n // Convert hex color string to number for the filter with safe parsing\n try {\n if (typeof value === 'string' && value.startsWith('#')) {\n this.color = parseInt(value.replace('#', '0x'), 16);\n } else {\n this.color = 0x000000; // Default black\n }\n } catch (e) {\n this.color = 0x000000;\n }\n console.log(`Updated color to ${value} (${this.color})`);\n break;\n \n case 'alpha':\n // Directly set the alpha value - this is the intensity of the effect\n this.alpha = Number(value);\n \n // Log the actual value for debugging\n console.log(`Updated alpha to ${this.alpha}, actual filter:`, {\n alpha: this.alpha,\n color: this.color,\n hasLightmap: !!this.lightMap\n });\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for SimpleLightmapFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating SimpleLightmapFilter parameter ${key}:`, error);\n }\n };\n \n // Log the created filter properties for debugging\n console.log('SimpleLightmapFilter created successfully:', {\n alpha: filter.alpha,\n color: filter.color,\n hasLightmap: !!filter.lightMap\n });\n \n return filter;\n } catch (error) {\n console.error('Failed to create SimpleLightmapFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n textureType: 'default',\n color: '#000000', // Ambient color (black typically)\n alpha: 1 // Coefficient for alpha multiplication\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'textureType',\n type: 'select',\n label: 'Light Map Type',\n property: 'textureType',\n options: [\n { label: 'Default', value: 'default' },\n { label: 'Spotlight', value: 'spotlight' },\n { label: 'Soft Light', value: 'softlight' }\n ],\n default: 'default',\n },\n {\n id: 'color',\n type: 'color',\n label: 'Ambient Color',\n property: 'color',\n default: '#000000',\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Intensity', // Renamed from Alpha to Intensity for clarity\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n }\n ],\n});","/**\n * Noise Filter Definition\n * Adds random noise to the image\n */\nimport { registerFilter } from '../registry';\n// Import directly from PixiJS (not pixi-filters) as this is a built-in filter\n// Import from pixi.js with namespace\nimport * as PIXI from 'pixi.js';\n// @ts-ignore - Module structure doesn't match TypeScript definitions\nconst { NoiseFilter } = PIXI;;\n\nexport default registerFilter({\n id: 'noise',\n name: 'Noise',\n category: 'effects',\n description: 'Add random noise to the image',\n \n createFilter: (params) => {\n try {\n console.log('Creating NoiseFilter with params:', params);\n \n // Create the filter with direct options\n const filter = new NoiseFilter({\n noise: params.noise || 0.5,\n seed: params.seed || Math.random()\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Set up animation loop for randomizing seed if animation is enabled\n let animationFrameId: number | null = null;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update with a new random seed for animation\n filter.seed = Math.random();\n }\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if enabled\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if not already running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'noise':\n // Update noise amount (with validation) - PIXI NoiseFilter expects 0-1 range\n this.noise = Math.max(0, Math.min(1, value));\n break;\n \n case 'seed':\n // Only update seed manually if not animating\n if (!(this as any).animating) {\n this.seed = value;\n }\n break;\n \n case 'randomizeSeed':\n // Button action to randomize seed\n if (value) {\n this.seed = Math.random();\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create NoiseFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n noise: 0.5,\n seed: 0.5,\n animating: false,\n randomizeSeed: false\n },\n \n controls: [\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Noise',\n property: 'animating',\n default: false\n },\n {\n id: 'noise',\n type: 'slider',\n label: 'Noise Amount',\n property: 'noise',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'seed',\n type: 'slider',\n label: 'Random Seed',\n property: 'seed',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Seed',\n action: 'randomizeSeed'\n }\n ]\n});","/**\n * Old Film Filter Definition\n * Applies a vintage film effect with sepia tone, scratches, grain, and vignetting\n */\nimport { registerFilter } from '../registry';\n// Import the OldFilmFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { OldFilmFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'old-film',\n name: 'Old Film',\n category: 'effects',\n description: 'Apply a vintage film effect with scratches and grain',\n \n createFilter: (params) => {\n try {\n console.log('Creating OldFilmFilter with params:', params);\n \n // Create the filter with direct options\n const filter = new OldFilmFilter({\n sepia: params.sepia,\n noise: params.noise,\n noiseSize: params.noiseSize,\n scratch: params.scratch,\n scratchDensity: params.scratchDensity,\n scratchWidth: params.scratchWidth,\n vignetting: params.vignetting,\n vignettingAlpha: params.vignettingAlpha,\n vignettingBlur: params.vignettingBlur,\n seed: params.seed || Math.random()\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Set up animation loop for randomizing seed if animation is enabled\n let animationFrameId: number | null = null;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update with a new random seed for animation\n filter.seed = Math.random();\n }\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if enabled\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if not already running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'seed':\n // Only update seed manually if not animating\n if (!(this as any).animating) {\n this.seed = value;\n }\n break;\n \n case 'randomizeSeed':\n // Button action to randomize seed\n if (value) {\n this.seed = Math.random();\n }\n break;\n \n // Direct properties that are part of the OldFilmFilter\n case 'sepia':\n case 'noise':\n case 'noiseSize':\n case 'scratch':\n case 'scratchDensity':\n case 'scratchWidth':\n case 'vignetting':\n case 'vignettingAlpha':\n case 'vignettingBlur':\n // Apply with validation if needed\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create OldFilmFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n sepia: 0.3,\n noise: 0.3,\n noiseSize: 1,\n scratch: 0.5,\n scratchDensity: 0.3,\n scratchWidth: 1,\n vignetting: 0.3,\n vignettingAlpha: 1,\n vignettingBlur: 0.3,\n seed: 0.5,\n animating: false,\n randomizeSeed: false\n },\n \n controls: [\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Film',\n property: 'animating',\n default: false\n },\n {\n id: 'sepia',\n type: 'slider',\n label: 'Sepia Tone',\n property: 'sepia',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'noise',\n type: 'slider',\n label: 'Noise Amount',\n property: 'noise',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'noiseSize',\n type: 'slider',\n label: 'Noise Size',\n property: 'noiseSize',\n min: 1,\n max: 10,\n step: 0.1,\n default: 1\n },\n {\n id: 'scratch',\n type: 'slider',\n label: 'Scratch Amount',\n property: 'scratch',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'scratchDensity',\n type: 'slider',\n label: 'Scratch Density',\n property: 'scratchDensity',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'scratchWidth',\n type: 'slider',\n label: 'Scratch Width',\n property: 'scratchWidth',\n min: 1,\n max: 20,\n step: 1,\n default: 1\n },\n {\n id: 'vignetting',\n type: 'slider',\n label: 'Vignette Size',\n property: 'vignetting',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'vignettingAlpha',\n type: 'slider',\n label: 'Vignette Opacity',\n property: 'vignettingAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1\n },\n {\n id: 'vignettingBlur',\n type: 'slider',\n label: 'Vignette Blur',\n property: 'vignettingBlur',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'seed',\n type: 'slider',\n label: 'Random Seed',\n property: 'seed',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Seed',\n action: 'randomizeSeed'\n }\n ]\n});","/**\n * Outline Filter Definition\n * Adds an outline/stroke around the image\n */\nimport { registerFilter } from '../registry';\n// Import the OutlineFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { OutlineFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'outline',\n name: 'Outline',\n category: 'effects',\n description: 'Add an outline or stroke around the image',\n \n createFilter: (params) => {\n try {\n console.log('Creating OutlineFilter with params:', params);\n \n // Parse color from hex string if needed\n let color = params.color;\n if (typeof color === 'string') {\n color = parseInt(color.replace('#', '0x'), 16);\n }\n \n // Create the filter with direct options\n const filter = new OutlineFilter({\n thickness: params.thickness || 4,\n color: color,\n alpha: params.alpha || 1,\n quality: params.quality || 0.1,\n knockout: params.knockout || false\n });\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for UI parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'thickness':\n // Apply with validation (non-negative)\n this.thickness = Math.max(0, value);\n break;\n \n case 'color':\n // Handle color in different formats\n if (typeof value === 'string') {\n // Convert hex string to number\n this.color = parseInt(value.replace('#', '0x'), 16);\n customParams.color = value; // Store the string version for UI\n } else {\n // Direct numeric assignment\n this.color = value;\n }\n break;\n \n case 'alpha':\n // Apply with validation (0-1 range)\n this.alpha = Math.max(0, Math.min(1, value));\n break;\n \n case 'quality':\n // Apply with validation (0.01-1 range for performance reasons)\n this.quality = Math.max(0.01, Math.min(1, value));\n break;\n \n case 'knockout':\n // Boolean toggle\n this.knockout = !!value;\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create OutlineFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n thickness: 4,\n color: '#000000',\n alpha: 1,\n quality: 0.1,\n knockout: false\n },\n \n controls: [\n {\n id: 'thickness',\n type: 'slider',\n label: 'Thickness',\n property: 'thickness',\n min: 0,\n max: 20,\n step: 0.1,\n default: 4\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#000000'\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 0.01,\n max: 1,\n step: 0.01,\n default: 0.1,\n tooltip: 'Higher values give better quality but slower performance'\n },\n {\n id: 'knockout',\n type: 'toggle',\n label: 'Outline Only',\n property: 'knockout',\n default: false,\n tooltip: 'Only show the outline, not the image content'\n }\n ]\n});","/**\n * Pixelate Filter Definition\n * Creates a pixelated mosaic effect by reducing the resolution in specific areas\n */\nimport { registerFilter } from '../registry';\n// Import the PixelateFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { PixelateFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'pixelate',\n name: 'Pixelate',\n category: 'effects',\n description: 'Create a pixelated or mosaic effect',\n \n createFilter: (params) => {\n try {\n console.log('Creating PixelateFilter with params:', params);\n \n // Create the filter with correct parameters\n // If separate X and Y values are provided, use them\n // Otherwise, use a single size value for both dimensions\n const filter = new PixelateFilter(\n params.useUniform \n ? Math.max(4, params.size || 10) \n : [Math.max(4, params.sizeX || 10), Math.max(4, params.sizeY || 10)]\n );\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'useUniform':\n // Toggle between uniform (single value) or separate x/y values\n customParams.useUniform = value;\n if (value) {\n // Switch to uniform size - use average of X and Y\n const avgSize = Math.round((this.sizeX + this.sizeY) / 2);\n this.size = Math.max(4, avgSize);\n customParams.size = avgSize;\n } else {\n // Switch to separate values - use current size for both\n const currentSize = Array.isArray(this.size) ? this.size[0] : this.size;\n this.sizeX = Math.max(4, currentSize);\n this.sizeY = Math.max(4, currentSize);\n customParams.sizeX = this.sizeX;\n customParams.sizeY = this.sizeY;\n }\n break;\n \n case 'size':\n // Update uniform size (both X and Y the same)\n if (customParams.useUniform) {\n this.size = Math.max(4, value);\n }\n break;\n \n case 'sizeX':\n // Update only X dimension\n if (!customParams.useUniform) {\n this.sizeX = Math.max(4, value);\n }\n break;\n \n case 'sizeY':\n // Update only Y dimension\n if (!customParams.useUniform) {\n this.sizeY = Math.max(4, value);\n }\n break;\n \n default:\n // For any other properties that might exist on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create PixelateFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n useUniform: true,\n size: 10,\n sizeX: 10,\n sizeY: 10\n },\n \n controls: [\n {\n id: 'useUniform',\n type: 'toggle',\n label: 'Uniform Pixels',\n property: 'useUniform',\n default: true,\n tooltip: 'Use the same size for both X and Y dimensions'\n },\n {\n id: 'size',\n type: 'slider',\n label: 'Pixel Size',\n property: 'size',\n min: 4,\n max: 40,\n step: 1,\n default: 10,\n tooltip: 'Size of the pixels in both dimensions'\n },\n {\n id: 'sizeX',\n type: 'slider',\n label: 'Horizontal Size',\n property: 'sizeX',\n min: 4,\n max: 40,\n step: 1,\n default: 10,\n tooltip: 'Size of the pixels in the horizontal direction'\n },\n {\n id: 'sizeY',\n type: 'slider',\n label: 'Vertical Size',\n property: 'sizeY',\n min: 4,\n max: 40,\n step: 1,\n default: 10,\n tooltip: 'Size of the pixels in the vertical direction'\n }\n ]\n});","/**\n * Reflection Filter Definition\n * Creates a water reflection effect with configurable waves\n */\nimport { registerFilter } from '../registry';\n// Import the ReflectionFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { ReflectionFilter } = PixiFilters;;\n\n// Register the Reflection filter\nexport default registerFilter({\n id: 'reflection', // ID must match what the application expects\n name: 'Reflection',\n category: 'distortion',\n description: 'Creates a water reflection effect with configurable waves',\n \n // Create an instance of the ReflectionFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating ReflectionFilter with params:', params);\n \n // Extract parameters with defaults\n const options = {\n mirror: params.mirror ?? true,\n boundary: params.boundary ?? 0.5,\n amplitude: new Float32Array([params.amplitudeStart ?? 0, params.amplitudeEnd ?? 20]),\n waveLength: new Float32Array([params.wavelengthStart ?? 30, params.wavelengthEnd ?? 100]),\n alpha: new Float32Array([params.alphaStart ?? 1, params.alphaEnd ?? 1]),\n time: params.time ?? 0\n };\n\n // Create the filter with PixiJS v8 style options object\n const filter = new ReflectionFilter(options as any);\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n // Add an animating flag for potential animation support\n (filter as any).animating = params.animating ?? false;\n \n /**\n * Custom method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'mirror':\n case 'boundary':\n case 'time':\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n break;\n \n case 'amplitudeStart':\n if (!Array.isArray(this.amplitude)) {\n this.amplitude = [0, this._customParams.amplitudeEnd || 20];\n }\n this.amplitude[0] = value;\n console.log(`Updated amplitude[0] to ${value}`);\n break;\n \n case 'amplitudeEnd':\n if (!Array.isArray(this.amplitude)) {\n this.amplitude = [this._customParams.amplitudeStart || 0, 20];\n }\n this.amplitude[1] = value;\n console.log(`Updated amplitude[1] to ${value}`);\n break;\n \n case 'wavelengthStart':\n if (!Array.isArray(this.waveLength)) {\n this.waveLength = [30, this._customParams.wavelengthEnd || 100];\n }\n this.waveLength[0] = value;\n console.log(`Updated waveLength[0] to ${value}`);\n break;\n \n case 'wavelengthEnd':\n if (!Array.isArray(this.waveLength)) {\n this.waveLength = [this._customParams.wavelengthStart || 30, 100];\n }\n this.waveLength[1] = value;\n console.log(`Updated waveLength[1] to ${value}`);\n break;\n \n case 'alphaStart':\n if (!Array.isArray(this.alpha)) {\n this.alpha = [1, this._customParams.alphaEnd || 1];\n }\n this.alpha[0] = value;\n console.log(`Updated alpha[0] to ${value}`);\n break;\n \n case 'alphaEnd':\n if (!Array.isArray(this.alpha)) {\n this.alpha = [this._customParams.alphaStart || 1, 1];\n }\n this.alpha[1] = value;\n console.log(`Updated alpha[1] to ${value}`);\n break;\n \n case 'animating':\n (this as any).animating = value;\n console.log(`Updated animating to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ReflectionFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ReflectionFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n mirror: true,\n boundary: 0.5,\n amplitudeStart: 0,\n amplitudeEnd: 20,\n wavelengthStart: 30,\n wavelengthEnd: 100,\n alphaStart: 1,\n alphaEnd: 1,\n time: 0,\n animating: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'mirror',\n type: 'toggle',\n label: 'Mirror Image',\n property: 'mirror',\n default: true,\n },\n {\n id: 'boundary',\n type: 'slider',\n label: 'Boundary Line',\n property: 'boundary',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'amplitudeStart',\n type: 'slider',\n label: 'Wave Height (Start)',\n property: 'amplitudeStart',\n min: 0,\n max: 50,\n step: 1,\n default: 0,\n },\n {\n id: 'amplitudeEnd',\n type: 'slider',\n label: 'Wave Height (End)',\n property: 'amplitudeEnd',\n min: 0,\n max: 50,\n step: 1,\n default: 20,\n },\n {\n id: 'wavelengthStart',\n type: 'slider',\n label: 'Wave Length (Start)',\n property: 'wavelengthStart',\n min: 10,\n max: 200,\n step: 1,\n default: 30,\n },\n {\n id: 'wavelengthEnd',\n type: 'slider',\n label: 'Wave Length (End)',\n property: 'wavelengthEnd',\n min: 10,\n max: 200,\n step: 1,\n default: 100,\n },\n {\n id: 'alphaStart',\n type: 'slider',\n label: 'Opacity (Start)',\n property: 'alphaStart',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'alphaEnd',\n type: 'slider',\n label: 'Opacity (End)',\n property: 'alphaEnd',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Animation Time',\n property: 'time',\n min: 0,\n max: 10,\n step: 0.1,\n default: 0,\n },\n {\n id: 'animating',\n type: 'toggle',\n label: 'Auto Animate',\n property: 'animating',\n default: false,\n }\n ],\n});","/**\n * Shockwave Filter Definition\n * Creates a rippling shockwave effect\n */\nimport { registerFilter } from '../registry';\n// Import the ShockwaveFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { ShockwaveFilter } = PixiFilters;;\n\n// Register the Shockwave filter\nexport default registerFilter({\n id: 'shockwave', // ID must match what the application expects\n name: 'Shockwave',\n category: 'distortion',\n description: 'Creates a rippling shockwave or blast wave effect',\n \n // Create an instance of the ShockwaveFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating ShockwaveFilter with params:', params);\n \n // Extract parameters with defaults\n const centerX = params.centerX ?? 0.5;\n const centerY = params.centerY ?? 0.5;\n const center = { x: centerX, y: centerY };\n const amplitude = params.amplitude ?? 30;\n const wavelength = params.wavelength ?? 160;\n const speed = params.speed ?? 500;\n const brightness = params.brightness ?? 1;\n const radius = params.radius ?? -1;\n const time = params.time ?? 0;\n \n // Create the filter with PixiJS v8 style options object\n const filter = new ShockwaveFilter({\n center,\n amplitude,\n wavelength,\n speed,\n brightness,\n radius,\n time\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n // Add an animating flag for potential animation support\n (filter as any).animating = params.animating ?? false;\n \n /**\n * Custom method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'centerX':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.x = value;\n console.log(`Updated center.x to ${value}`);\n break;\n \n case 'centerY':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.y = value;\n console.log(`Updated center.y to ${value}`);\n break;\n \n case 'amplitude':\n case 'wavelength':\n case 'speed':\n case 'brightness':\n case 'radius':\n case 'time':\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n break;\n \n case 'animating':\n (this as any).animating = value;\n console.log(`Updated animating to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ShockwaveFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ShockwaveFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n centerX: 0.5,\n centerY: 0.5,\n amplitude: 30,\n wavelength: 160,\n speed: 500,\n brightness: 1,\n radius: -1,\n time: 0,\n animating: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'amplitude',\n type: 'slider',\n label: 'Amplitude',\n property: 'amplitude',\n min: 0,\n max: 100,\n step: 1,\n default: 30,\n },\n {\n id: 'wavelength',\n type: 'slider',\n label: 'Wavelength',\n property: 'wavelength',\n min: 10,\n max: 500,\n step: 1,\n default: 160,\n },\n {\n id: 'speed',\n type: 'slider',\n label: 'Speed',\n property: 'speed',\n min: 1,\n max: 1000,\n step: 10,\n default: 500,\n },\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Max Radius',\n property: 'radius',\n min: -1,\n max: 1000,\n step: 10,\n default: -1,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Time',\n property: 'time',\n min: 0,\n max: 5,\n step: 0.1,\n default: 0,\n },\n {\n id: 'animating',\n type: 'toggle',\n label: 'Auto Animate',\n property: 'animating',\n default: false,\n }\n ],\n});","/**\n * Simplex Noise Filter Definition\n * Applies procedural noise to create various texture effects\n */\nimport { registerFilter } from '../registry';\n// Import the SimplexNoiseFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { SimplexNoiseFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'simplex-noise',\n name: 'Simplex Noise',\n category: 'effects',\n description: 'Apply procedural noise to create texture effects',\n \n createFilter: (params) => {\n try {\n console.log('Creating SimplexNoiseFilter with params:', params);\n \n // Use params.time for animation if this is enabled\n const zOffset = params.animating ? 0 : (params.offsetZ || 0);\n \n // Create the filter with direct options\n const filter = new SimplexNoiseFilter({\n strength: params.strength,\n noiseScale: params.noiseScale,\n offsetX: params.offsetX,\n offsetY: params.offsetY,\n offsetZ: zOffset,\n step: params.step\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n (filter as any).animationSpeed = params.animationSpeed || 0.01;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Set up animation loop for changing the Z offset over time\n let animationFrameId: number | null = null;\n let currentTime = 0;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update the Z offset over time for animation\n currentTime += (filter as any).animationSpeed;\n filter.offsetZ = currentTime;\n }\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if enabled\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if not already running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'animationSpeed':\n // Update animation speed\n (this as any).animationSpeed = value;\n break;\n \n case 'offsetZ':\n // Only update Z offset manually if not animating\n if (!(this as any).animating) {\n this.offsetZ = value;\n }\n break;\n \n case 'randomizeSeed':\n // Randomize all offsets for a new pattern\n if (value) {\n const randomValue = () => Math.random() * 100 - 50;\n this.offsetX = randomValue();\n this.offsetY = randomValue();\n this.offsetZ = randomValue();\n \n // Update stored values\n customParams.offsetX = this.offsetX;\n customParams.offsetY = this.offsetY;\n customParams.offsetZ = this.offsetZ;\n }\n break;\n \n // Direct properties that exist on the filter\n case 'strength':\n case 'noiseScale':\n case 'offsetX':\n case 'offsetY':\n case 'step':\n // Apply with any needed validation\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n \n default:\n // For any other properties that might exist on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create SimplexNoiseFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n strength: 0.5,\n noiseScale: 10.0,\n offsetX: 0,\n offsetY: 0,\n offsetZ: 0,\n step: -1,\n animating: false,\n animationSpeed: 0.01,\n randomizeSeed: false\n },\n \n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Noise Strength',\n property: 'strength',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'noiseScale',\n type: 'slider',\n label: 'Noise Scale',\n property: 'noiseScale',\n min: 1,\n max: 50,\n step: 0.5,\n default: 10.0\n },\n {\n id: 'offsetX',\n type: 'slider',\n label: 'X Offset',\n property: 'offsetX',\n min: -50,\n max: 50,\n step: 0.5,\n default: 0\n },\n {\n id: 'offsetY',\n type: 'slider',\n label: 'Y Offset',\n property: 'offsetY',\n min: -50,\n max: 50,\n step: 0.5,\n default: 0\n },\n {\n id: 'offsetZ',\n type: 'slider',\n label: 'Z Offset',\n property: 'offsetZ',\n min: -50,\n max: 50,\n step: 0.5,\n default: 0\n },\n {\n id: 'step',\n type: 'slider',\n label: 'Step Threshold',\n property: 'step',\n min: -1,\n max: 1,\n step: 0.01,\n default: -1,\n tooltip: 'Values above 0 create a blocky effect'\n },\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Noise',\n property: 'animating',\n default: false\n },\n {\n id: 'animationSpeed',\n type: 'slider',\n label: 'Animation Speed',\n property: 'animationSpeed',\n min: 0.001,\n max: 0.05,\n step: 0.001,\n default: 0.01\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Pattern',\n action: 'randomizeSeed'\n }\n ]\n});","/**\n * Twist Filter Definition\n *\n * Uses pixi-filters' built-in TwistFilter. The previous custom shader\n * worked in PIXI v7 but silently rendered transparent in PIXI v8 because\n * its vertex shader set `vTextureCoord = aPosition`, which isn't how v8's\n * filter pipeline computes texture coordinates.\n *\n * UI keeps normalized [0,1] inputs for centerX/centerY/radius so they're\n * intuitive across any image size. The filter factory converts those to\n * pixel-space offset/radius using the source image dimensions threaded\n * through `params._sourceWidth/_sourceHeight` by FilterManager.\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore — pixi-filters lacks first-class TypeScript types here\nconst { TwistFilter } = PixiFilters;\n\nconst computeTwistPadding = (radiusPx: number): number => {\n // Twist displaces pixels within the radius; extend the render area a bit\n // so edge fringes don't clip when the twist center is near the boundary.\n return Math.ceil(Math.max(0, Number(radiusPx) || 0) + 2);\n};\n\ninterface TwistParams {\n centerX?: number;\n centerY?: number;\n /** Radius as a fraction of the smaller image edge, 0-1. */\n radius?: number;\n /** Twist angle in radians. */\n angle?: number;\n _sourceWidth?: number;\n _sourceHeight?: number;\n}\n\nconst buildTwistFilter = (raw: TwistParams, previewToNativeScale = 1) => {\n const width = Math.max(1, Number(raw._sourceWidth ?? 0));\n const height = Math.max(1, Number(raw._sourceHeight ?? 0));\n const minEdge = Math.min(width, height);\n\n const centerX = Number(raw.centerX ?? 0.5);\n const centerY = Number(raw.centerY ?? 0.5);\n const normalizedRadius = Number(raw.radius ?? 0.25);\n const angle = Number(raw.angle ?? 4);\n\n // Normalized (0-1) → pixels. Center is in the filter area's coord space;\n // pixi-filters TwistFilter's offset is in pixels relative to (0,0) of\n // the filter area. We also scale by previewToNativeScale so exports at\n // higher resolution keep the same visual radius.\n const offsetX = centerX * width * previewToNativeScale;\n const offsetY = centerY * height * previewToNativeScale;\n const radiusPx = normalizedRadius * minEdge * previewToNativeScale;\n\n const filter = new TwistFilter({\n offset: { x: offsetX, y: offsetY },\n radius: radiusPx,\n angle,\n });\n\n // Reserve padding so the twist fringe doesn't clip when centered near\n // the sprite edge. Matches the drop-shadow / bulge-pinch pattern.\n const padding = computeTwistPadding(radiusPx);\n filter.padding = Math.max(filter.padding ?? 0, padding);\n (filter as any)._exportPadding = padding;\n\n return filter;\n};\n\nexport default registerFilter({\n id: 'twist',\n name: 'Twist',\n category: 'distortion',\n description: 'Creates a twisting distortion effect around a central point',\n\n createFilter: (params) => {\n try {\n const raw: TwistParams = {\n centerX: params.centerX ?? 0.5,\n centerY: params.centerY ?? 0.5,\n radius: params.radius ?? 0.25,\n angle: params.angle ?? 4,\n _sourceWidth: params._sourceWidth,\n _sourceHeight: params._sourceHeight,\n };\n\n const filter = buildTwistFilter(raw, 1);\n (filter as any)._customParams = { ...raw };\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n\n // Twist params are coupled (center → offset in pixels using dims,\n // radius → px using min edge). Recompute all uniforms whenever any\n // slider moves rather than mapping per-key.\n const width = Math.max(1, Number(customParams._sourceWidth ?? 0));\n const height = Math.max(1, Number(customParams._sourceHeight ?? 0));\n const minEdge = Math.min(width, height);\n const centerX = Number(customParams.centerX ?? 0.5);\n const centerY = Number(customParams.centerY ?? 0.5);\n const normalizedRadius = Number(customParams.radius ?? 0.25);\n const angle = Number(customParams.angle ?? 4);\n\n if (this.offset) {\n this.offset.x = centerX * width;\n this.offset.y = centerY * height;\n }\n this.radius = normalizedRadius * minEdge;\n this.angle = angle;\n\n const padding = computeTwistPadding(this.radius);\n (this as any)._exportPadding = padding;\n this.padding = Math.max(this.padding ?? 0, padding);\n return true;\n };\n\n (filter as any).createExportFilter = function (options: { previewToNativeScale?: number } = {}) {\n const scale = Number.isFinite(options.previewToNativeScale)\n ? Math.max(1, Number(options.previewToNativeScale))\n : 1;\n const stored: TwistParams = (this as any)._customParams || raw;\n return buildTwistFilter(stored, scale);\n };\n\n (filter as any).getExportPadding = function () {\n return Number((this as any)._exportPadding || this.padding || 0);\n };\n\n return filter;\n } catch (error) {\n console.error('Failed to create TwistFilter:', error);\n return null;\n }\n },\n\n // Default parameter values — normalized (0-1) for intuitive slider use.\n defaultParams: {\n centerX: 0.5,\n centerY: 0.5,\n radius: 0.25,\n angle: 4,\n },\n\n controls: [\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: -10,\n max: 10,\n step: 0.1,\n default: 4,\n tooltip: 'Amount of twisting (positive is clockwise)',\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: 0.05,\n max: 0.75,\n step: 0.01,\n default: 0.25,\n tooltip: 'Size of the twist effect (relative to image)',\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n tooltip: 'Horizontal position of twist center',\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n tooltip: 'Vertical position of twist center',\n },\n ],\n});\n","/**\n * Vignette Filter Definition\n * Adds a classic darkened border effect to the image\n * \n * NOTE: This is a CUSTOM implementation as pixi-filters does not provide a VignetteFilter.\n * It uses AdjustmentFilter to simulate a vignette effect by manipulating brightness/contrast.\n * This is not a true radial gradient vignette but provides a similar visual effect.\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { AdjustmentFilter } = PixiFilters;;\n\n/**\n * Helper to convert a hex color value to RGB array\n */\nfunction hexToRgb(hex: number | string): number[] {\n const parsedHex = typeof hex === 'string' ? parseInt(hex.replace('#', '0x'), 16) : hex;\n return [\n ((parsedHex >> 16) & 0xFF) / 255,\n ((parsedHex >> 8) & 0xFF) / 255,\n (parsedHex & 0xFF) / 255\n ];\n}\n\n/**\n * Simple Vignette implementation using AdjustmentFilter\n * \n * This approach simulates a vignette effect by manipulating\n * brightness, contrast and color tint - it's not a true vignette\n * but provides a similar visual effect using stable filter mechanisms.\n */\nclass VignetteFilter extends AdjustmentFilter {\n private _radius: number = 0.8;\n private _strength: number = 1.0;\n private _colorRgb: number[] = [0, 0, 0];\n private _colorValue: string = '#000000';\n\n constructor(options: { radius?: number; strength?: number; color?: number | string } = {}) {\n // Initialize with default adjustment values\n super({\n brightness: 1.0,\n contrast: 1.0,\n saturation: 1.0,\n alpha: 1.0\n });\n \n this._radius = options.radius ?? 0.8;\n this._strength = options.strength ?? 1.0;\n \n // Parse color\n if (options.color !== undefined) {\n if (typeof options.color === 'string') {\n this._colorValue = options.color;\n this._colorRgb = hexToRgb(options.color);\n } else {\n this._colorValue = '#' + options.color.toString(16).padStart(6, '0');\n this._colorRgb = hexToRgb(options.color);\n }\n }\n \n // Apply the initial vignette effect\n this.updateVignette();\n }\n \n /**\n * Updates the filter parameters to simulate a vignette effect\n */\n private updateVignette(): void {\n // Calculate effect intensity based on radius and strength\n // Radius inversely affects strength (higher radius = less effect)\n const radiusFactor = 1 - (this._radius / 2); // Normalize to 0.5-1 range\n const effectiveStrength = this._strength * radiusFactor;\n \n // Darker with higher strength (0.5-1.0 range to avoid making everything black)\n this.brightness = Math.max(0.5, 1.0 - effectiveStrength * 0.5);\n \n // Increase contrast slightly with strength to emphasize the vignette\n this.contrast = 1.0 + (effectiveStrength * 0.2);\n \n // Apply a slight tint in the color direction\n if (this._colorRgb[0] > 0 || this._colorRgb[1] > 0 || this._colorRgb[2] > 0) {\n // Tint RGB based on color and strength\n // Since AdjustmentFilter doesn't have direct tint properties,\n // we can't apply a true color tint, but we can adjust\n // saturation to hint at the color\n this.saturation = 1.0 - (effectiveStrength * 0.3);\n }\n }\n\n // Properties with getters/setters\n get radius(): number { return this._radius; }\n set radius(value: number) { \n this._radius = Math.max(0.1, Math.min(1.5, value));\n this.updateVignette();\n }\n\n get strength(): number { return this._strength; }\n set strength(value: number) { \n this._strength = Math.max(0, Math.min(2, value));\n this.updateVignette();\n }\n\n get color(): string { return this._colorValue; }\n set color(value: number | string) { \n if (typeof value === 'string') {\n this._colorValue = value;\n this._colorRgb = hexToRgb(value);\n } else {\n this._colorValue = '#' + value.toString(16).padStart(6, '0');\n this._colorRgb = hexToRgb(value);\n }\n this.updateVignette();\n }\n}\n\nexport default registerFilter({\n id: 'vignette',\n name: 'Vignette',\n category: 'effects',\n description: 'Add a classic darkened border effect to the image',\n \n createFilter: (params) => {\n try {\n console.log('Creating VignetteFilter with params:', params);\n \n // Create the custom VignetteFilter implementation\n const filter = new VignetteFilter({\n radius: params.radius || 0.8,\n strength: params.strength || 1.0,\n color: params.color || '#000000'\n });\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for UI parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'radius':\n // Apply with validation (0.1-1.5 range for visual quality)\n this.radius = Math.max(0.1, Math.min(1.5, value));\n break;\n \n case 'strength':\n // Apply with validation (non-negative)\n this.strength = Math.max(0, value);\n break;\n \n case 'color':\n // Handle color in different formats\n this.color = value;\n // Store the string version for UI if it's a string\n if (typeof value === 'string') {\n customParams.color = value;\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create VignetteFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n radius: 0.8,\n strength: 1.0,\n color: '#000000'\n },\n \n controls: [\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: 0.1,\n max: 1.5,\n step: 0.01,\n default: 0.8,\n tooltip: 'Size of the vignette effect (larger values create a smaller vignette)'\n },\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1.0,\n tooltip: 'Intensity of the vignette effect'\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#000000',\n tooltip: 'Color of the vignette (usually black)'\n }\n ]\n});","/**\n * Filters Module Index\n * Exports all filter-related functionality\n */\n\n// First import the functions so they exist in this module's scope\nimport {\n registerFilter,\n getFilter,\n getAllFilters,\n getFiltersByCategory,\n getAllCategories,\n hasFilter,\n unregisterFilter,\n getFiltersByMedia,\n isFilterCompatibleWithMedia,\n getRegisteredFilters,\n registerCorePixiFilters,\n} from './registry';\n\n// Then re-export them for downstream consumers\nexport {\n registerFilter,\n getFilter,\n getAllFilters,\n getFiltersByCategory,\n getAllCategories,\n hasFilter,\n unregisterFilter,\n getFiltersByMedia,\n isFilterCompatibleWithMedia,\n getRegisteredFilters,\n registerCorePixiFilters,\n};\nexport type { FilterDefinition, ControlDefinition, FilterMediaTarget } from './registry';\n\n// Re-export from factory\nexport {\n createFilterInstance,\n createFilterInstances,\n updateFilterParams,\n} from './factory';\nexport type { FilterInstanceConfig } from './factory';\n\n// Re-export from controlMapping\nexport {\n mapControlTypeToComponent,\n validateControlValue,\n generateDefaultParams,\n convertControlValue,\n} from './controlMapping';\n\n// Import and re-export all filter definitions\n// This ensures all filters are registered when this module is imported\n\n// Basic adjustments\nimport './definitions/adjustment';\nimport './definitions/adjustmentAdvanced';\nimport './definitions/alpha';\nimport './definitions/blur';\nimport './definitions/colorMatrix';\nimport './definitions/colorOverlay';\nimport './definitions/dropShadow';\nimport './definitions/grayscale';\nimport './definitions/hslAdjustment';\n\n// Blur effects\nimport './definitions/kawaseBlur';\nimport './definitions/motionBlur';\nimport './definitions/radialBlur';\nimport './definitions/tiltShift';\nimport './definitions/zoomBlur';\n\n// Color effects\nimport './definitions/colorGradient';\nimport './definitions/colorMap';\nimport './definitions/colorReplace';\nimport './definitions/multiColorReplace';\nimport './definitions/rgbSplit';\n\n// Stylistic effects\nimport './definitions/advancedBloom';\nimport './definitions/ascii';\nimport './definitions/backdropBlur';\nimport './definitions/bevel';\nimport './definitions/bloom';\nimport './definitions/bulgePinch';\nimport './definitions/convolution';\nimport './definitions/crossHatch';\nimport './definitions/crt';\nimport './definitions/displacement';\nimport './definitions/dot';\nimport './definitions/emboss';\nimport './definitions/glitch';\nimport './definitions/glow';\nimport './definitions/godray';\nimport './definitions/lightmap';\nimport './definitions/noise';\nimport './definitions/oldFilm';\nimport './definitions/outline';\nimport './definitions/pixelate';\nimport './definitions/reflection';\nimport './definitions/shockwave';\nimport './definitions/simplexNoise';\nimport './definitions/twist';\nimport './definitions/vignette';\n\n/**\n * Options for initializeFilterRegistry.\n * @property disabled - Filter IDs to remove from the registry after initialization.\n */\ninterface FilterRegistryOptions {\n disabled?: string[];\n}\n\n/**\n * Initialize the filter registry with all available filters.\n *\n * @param options.disabled - Array of filter IDs to remove after registration\n * (e.g., fetched from the server's mediables.pixi_filters.disabled config).\n */\nexport function initializeFilterRegistry(options?: FilterRegistryOptions) {\n try {\n // Just verify functions exist (they should because of proper imports)\n verifyFilterRegistryFunctions();\n\n // Add explicit type annotations to fix TS7034 errors\n let filters: any[] = [];\n let categories: any[] = [];\n\n // First, try to register core filters\n try {\n // Check if any filters have already been registered\n filters = getAllFilters(); // Now we know this function exists\n\n if (filters.length === 0) {\n // Register core filters if none are registered yet\n console.log('No filters found, registering core filters');\n registerCorePixiFilters(); // Now we know this function exists\n }\n } catch (e) {\n console.warn('Error registering core filters:', e);\n }\n\n // Remove disabled filters from the registry\n const disabled = options?.disabled;\n if (Array.isArray(disabled) && disabled.length > 0) {\n let removedCount = 0;\n for (const id of disabled) {\n if (unregisterFilter(id)) {\n removedCount++;\n }\n }\n if (removedCount > 0) {\n console.log(`Removed ${removedCount} disabled filter(s) from registry`);\n }\n }\n\n // Try to get the filters again after registration\n try {\n filters = getAllFilters();\n categories = getAllCategories(); // Now we know this function exists\n } catch (e) {\n console.warn('Error getting filters or categories:', e);\n // Ensure we have valid defaults even after an error\n if (!filters) filters = [] as any[];\n if (!categories) categories = [] as any[];\n }\n\n // Log the initialization status\n console.log(`Filter registry initialized with ${filters.length} filters in ${categories.length} categories`);\n\n // If we have no filters, log a warning\n if (filters.length === 0) {\n console.warn('No filters found in registry. Filter functionality may be limited.');\n }\n\n return filters as any[];\n } catch (error) {\n // Log the error but don't crash\n console.error('Error initializing filter registry:', error);\n\n // Return an empty array to avoid further errors\n return [];\n }\n}\n\n/**\n * Verify that the required filter registry functions exist\n * This is now just for debugging/validation since we're properly importing the functions\n */\nfunction verifyFilterRegistryFunctions() {\n // Just verify functions exist - they should because of the imports\n const missingFunctions = [];\n \n if (typeof getAllFilters !== 'function') missingFunctions.push('getAllFilters');\n if (typeof getAllCategories !== 'function') missingFunctions.push('getAllCategories');\n if (typeof registerCorePixiFilters !== 'function') missingFunctions.push('registerCorePixiFilters');\n \n if (missingFunctions.length > 0) {\n console.warn(`Warning: Some registry functions are still missing: ${missingFunctions.join(', ')}`);\n }\n}\n\n/**\n * Alternative initialization function with a minimal approach\n * Use this if the main initializeFilterRegistry function is having issues\n */\nexport function safeInitializeFilterRegistry() {\n console.warn('Using minimal safeInitializeFilterRegistry implementation');\n \n try {\n // Verify functions exist but don't create fallbacks\n verifyFilterRegistryFunctions();\n \n // Try to use the getAllFilters function to get any existing filters\n const existingFilters = getAllFilters();\n \n if (existingFilters && existingFilters.length > 0) {\n console.log(`Found ${existingFilters.length} existing filters`);\n return Promise.resolve(existingFilters);\n }\n \n // If no existing filters, try one more attempt with registerCorePixiFilters\n try {\n registerCorePixiFilters();\n const registeredFilters = getAllFilters();\n console.log(`Registered ${registeredFilters.length} core filters`);\n return Promise.resolve(registeredFilters);\n } catch (e) {\n console.warn('Error registering core filters:', e);\n }\n \n // If all else fails, return empty array\n console.warn('Filter functionality will be limited');\n return Promise.resolve([]);\n } catch (e) {\n console.error('Error in safeInitializeFilterRegistry:', e);\n return Promise.resolve([]);\n }\n}\n\n/**\n * Simplified factory for creating a minimal filter\n * Returns a no-op filter that won't cause errors but doesn't do anything\n */\nexport function createMinimalFilter(id: string) {\n console.warn(`Creating minimal placeholder filter for: ${id}`);\n \n // Create a more complete filter stub that matches the expected interface\n return {\n id,\n name: id,\n enabled: true,\n // Basic filter methods\n apply: () => {/* No-op */},\n // Properties needed by the UI\n uniforms: {},\n // Custom interface properties\n updateUIParam: (param: string, value: any) => {\n console.log(`Minimal filter ${id} updateUIParam called with ${param}=${value}`);\n return true;\n },\n handleButtonAction: (action: string) => {\n console.log(`Minimal filter ${id} handleButtonAction called with ${action}`);\n return true;\n },\n // Add any other expected properties based on your filter interface\n // This ensures the minimal filter can be used in place of a real filter\n // without causing errors\n reset: () => {/* No-op */},\n // Clone method for deep copying\n clone: () => createMinimalFilter(id),\n // Allow property access with indexing\n [Symbol.toPrimitive]: () => `[Minimal Filter ${id}]`\n };\n}\n"],"names":["EventEmitter","event","callback","listeners","args","wrapper","TEXT_LAYER_FONT_FAMILIES","TEXT_LAYER_BLEND_MODES","DEFAULT_TEXT_BOX","DEFAULT_TEXT_STYLE","DEFAULT_TEXT_EFFECTS","State","key","parts","value","part","old","lastKey","target","filters","filterId","values","crop","_a","document","binding","snapshot","layers","layer","activeLayerId","subjectIndex","subject","rotation","baseTransform","cropState","appliedRect","layerId","index","baseId","existingIds","safeBase","suffix","candidate","filter","expectedLayerId","expected","activeFilters","filterValues","oldSelectedFilter","min","max","fallback","numeric","normalized","box","base","source","style","fontFamily","fontStyle","align","fill","effects","baseEffects","stroke","shadow","glow","backdrop","transform","input","baseText","contentSource","boxSource","_b","styleSource","_c","effectsSource","_d","removedIndex","distance","nextIndex","previousIndex","fromIndex","toIndex","start","end","activeLayer","visible","name","nextName","oldName","sourceLayer","duplicate","oldActiveLayerId","removed","nextActiveLayerId","direction","locked","payload","patch","textPatch","nextLayer","eventName","eventPayload","id","fit","stops","stop","existingIndex","firstSubjectIndex","insertAt","normalizedFill","previousFit","amount","numericAmount","effect","nextActive","enabled","controlId","filterIndex","controls","existing","ctl","prefersDark","createState","categories","isMediaCompatible","definition","registerFilter","getFilter","getAllFilters","registerCorePixiFilters","f","PixiFilters","entry","exportName","FilterClass","params","getFiltersByCategory","category","getAllCategories","hasFilter","unregisterFilter","categoryIds","idx","isFilterCompatibleWithMedia","getRegisteredFilters","originalRegisterFilter","result","AdjustmentFilter","ColorMatrixFilter","PIXI","DEFAULT_ADJUSTMENT_PARAMS","ADJUSTMENT_PARAM_KEYS","toFiniteNumber","parsed","isAdjustmentParamKey","normalizeAdjustmentParams","applyColorMatrixAdjustments","normalizedParams","options","filterWithUI","customParams","numericValue","DEFAULT_ADVANCED_ADJUSTMENT_PARAMS","ADVANCED_ADJUSTMENT_PARAM_KEYS","isAdvancedAdjustmentParamKey","toBoolean","normalizeAdvancedAdjustmentParams","applyAdvancedAdjustments","numericKey","clamp01","n","alpha","applyColorMatrixParams","normalizeParams","raw","MatrixFilterClass","stored","ColorOverlayFilter","colorValue","colorNum","color","angle","blur","quality","offset","computePadding","b","q","offX","offY","kernel","mag","createScaledForExport","rawParams","scale","dist","ang","blr","qual","off","colorStr","next","padding","refreshPadding","p","newOffset","intensity","applyGrayscaleEffect","HslAdjustmentFilter","KawaseBlurFilter","MotionBlurFilter","RadialBlurFilter","TiltShiftFilter","gradientBlur","startX","startY","endX","endY","numValue","ZoomBlurFilter","ColorGradientFilter","hexToInt","hex","intToHex","num","normalizeStopForFilter","hexStopFromFilter","stopsHex","colorStops","action","current","randomColor","a","str","dynamicMatch","indexStr","prop","ColorMapFilterClass","colorMapTexture","ColorReplaceFilter","originalColorValue","targetColorValue","MultiColorReplaceFilter","replacements","original","newReplacements","RGBSplitFilter","red","green","blue","AdvancedBloomFilter","AsciiFilter","size","replaceColor","BackdropBlurFilter","kernelSize","BevelFilter","lightColor","shadowColor","BloomFilter","strengthX","strengthY","resolution","BulgePinchFilter","computeBulgePadding","radius","r","centerX","centerY","strength","scaledRadius","ConvolutionFilter","MATRICES","matrix","presetKey","currentMatrix","newMatrix","CrossHatchFilter","_params","DisplacementFilter","Sprite","Texture","mapUrl","mapTexture","canvas","ctx","i","j","displacementSprite","sprite","newTexture","EmbossFilter","GlitchFilter","FILL_MODES","redOffset","greenOffset","blueOffset","animationFrameId","animate","GlowFilter","GodrayFilter","SimpleLightmapFilter","textureType","alphaValue","gradient","lightMapTexture","updateCanvas","updateCtx","wasEnabled","NoiseFilter","OldFilmFilter","OutlineFilter","PixelateFilter","avgSize","currentSize","ReflectionFilter","ShockwaveFilter","center","amplitude","wavelength","speed","brightness","time","SimplexNoiseFilter","zOffset","currentTime","randomValue","TwistFilter","computeTwistPadding","radiusPx","buildTwistFilter","previewToNativeScale","width","height","minEdge","normalizedRadius","offsetX","offsetY","hexToRgb","parsedHex","VignetteFilter","radiusFactor","effectiveStrength","initializeFilterRegistry","disabled","removedCount"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-QOKC8XA_.cjs","sources":["../resources/js/vanilla-editor/core/EventEmitter.js","../resources/js/vanilla-editor/core/State.js","../resources/js/filters/registry.ts","../resources/js/filters/definitions/adjustment.ts","../resources/js/filters/definitions/adjustmentAdvanced.ts","../resources/js/filters/definitions/alpha.ts","../resources/js/filters/definitions/blur.ts","../resources/js/filters/definitions/colorMatrix.ts","../resources/js/filters/definitions/colorOverlay.ts","../resources/js/filters/definitions/dropShadow.ts","../resources/js/filters/definitions/grayscale.ts","../resources/js/filters/definitions/hslAdjustment.ts","../resources/js/filters/definitions/kawaseBlur.ts","../resources/js/filters/definitions/motionBlur.ts","../resources/js/filters/definitions/radialBlur.ts","../resources/js/filters/definitions/tiltShift.ts","../resources/js/filters/definitions/zoomBlur.ts","../resources/js/filters/definitions/colorGradient.ts","../resources/js/filters/definitions/colorMap.ts","../resources/js/filters/definitions/colorReplace.ts","../resources/js/filters/definitions/multiColorReplace.ts","../resources/js/filters/definitions/rgbSplit.ts","../resources/js/filters/definitions/advancedBloom.ts","../resources/js/filters/definitions/ascii.ts","../resources/js/filters/definitions/backdropBlur.ts","../resources/js/filters/definitions/bevel.ts","../resources/js/filters/definitions/bloom.ts","../resources/js/filters/definitions/bulgePinch.ts","../resources/js/filters/definitions/convolution.ts","../resources/js/filters/definitions/crossHatch.ts","../resources/js/filters/definitions/crt.ts","../resources/js/filters/definitions/displacement.ts","../resources/js/filters/definitions/dot.ts","../resources/js/filters/definitions/emboss.ts","../resources/js/filters/definitions/glitch.ts","../resources/js/filters/definitions/glow.ts","../resources/js/filters/definitions/godray.ts","../resources/js/filters/definitions/lightmap.ts","../resources/js/filters/definitions/noise.ts","../resources/js/filters/definitions/oldFilm.ts","../resources/js/filters/definitions/outline.ts","../resources/js/filters/definitions/pixelate.ts","../resources/js/filters/definitions/reflection.ts","../resources/js/filters/definitions/shockwave.ts","../resources/js/filters/definitions/simplexNoise.ts","../resources/js/filters/definitions/twist.ts","../resources/js/filters/definitions/vignette.ts","../resources/js/filters/index.ts"],"sourcesContent":["/**\n * Simple EventEmitter for vanilla JS\n * Provides pub/sub functionality without external dependencies\n */\nexport class EventEmitter {\n constructor() {\n this._events = new Map()\n }\n\n on(event, callback) {\n if (!this._events.has(event)) {\n this._events.set(event, new Set())\n }\n this._events.get(event).add(callback)\n return () => this.off(event, callback)\n }\n\n off(event, callback) {\n const listeners = this._events.get(event)\n if (listeners) {\n listeners.delete(callback)\n }\n }\n\n emit(event, ...args) {\n const listeners = this._events.get(event)\n if (listeners) {\n listeners.forEach(callback => {\n try {\n callback(...args)\n } catch (e) {\n console.error(`Error in event listener for ${event}:`, e)\n }\n })\n }\n }\n\n once(event, callback) {\n const wrapper = (...args) => {\n this.off(event, wrapper)\n callback(...args)\n }\n return this.on(event, wrapper)\n }\n\n removeAllListeners(event) {\n if (event) {\n this._events.delete(event)\n } else {\n this._events.clear()\n }\n }\n}\n","/**\n * Central state management for the vanilla image editor\n * Replaces Vue's reactivity system with a simple observable pattern\n */\nimport { EventEmitter } from './EventEmitter.js'\n\nexport const TEXT_LAYER_FONT_FAMILIES = Object.freeze([\n 'Inter',\n 'Arial',\n 'Helvetica',\n 'Georgia',\n 'Times New Roman',\n 'Courier New',\n 'Verdana',\n])\n\nconst TEXT_LAYER_BLEND_MODES = Object.freeze(['normal', 'multiply', 'screen', 'overlay'])\nconst DEFAULT_TEXT_BOX = Object.freeze({ x: 0.2, y: 0.2, width: 0.6, height: 0.18 })\nconst DEFAULT_TEXT_STYLE = Object.freeze({\n fontFamily: 'Inter',\n fontSize: 64,\n fontWeight: 700,\n fontStyle: 'normal',\n fill: '#ffffff',\n align: 'center',\n lineHeight: 1.2,\n letterSpacing: 0,\n})\nconst DEFAULT_TEXT_EFFECTS = Object.freeze({\n stroke: Object.freeze({ enabled: false, color: '#000000', width: 0 }),\n shadow: Object.freeze({ enabled: false, color: '#000000', alpha: 0.5, blur: 0, distance: 0, angle: 45 }),\n glow: Object.freeze({ enabled: false, color: '#ffffff', alpha: 0.5, blur: 0 }),\n backdrop: Object.freeze({ enabled: false, color: '#000000', opacity: 0.5, padding: 0, radius: 0, blur: 0 }),\n})\n\nexport class State extends EventEmitter {\n constructor() {\n super()\n this._state = {\n // Image state\n hasImage: false,\n imageUrl: null,\n\n // Mode state\n mode: 'filters', // 'filters' | 'crop'\n\n // View state\n zoom: 1,\n fitScale: 1,\n\n // Filter state\n activeFilters: new Set(),\n filterValues: {},\n selectedFilter: null,\n selectedCategory: 'adjust',\n\n // Crop state\n crop: {\n shape: 'free', // 'free' | 'square' | 'circle'\n aspect: 'free', // 'free' | '1:1' | '4:3' | '16:9' | '3:2' | '2:3'\n rect: null, // { x, y, width, height }\n dirty: false // true once the user changes the generated crop frame\n },\n\n // Transform state\n transform: {\n rotation: 0 // degrees clockwise, normalized to 0..359.999\n },\n\n // Layered editor document state (v2 document contract)\n editorDocument: null,\n editorDocumentId: null,\n editorDocumentRevisionId: null,\n editorDocumentRevisionNumber: null,\n layers: [],\n activeLayerId: null,\n\n // UI state\n theme: 'auto', // 'light' | 'dark' | 'auto'\n isDarkMode: false,\n backgroundRemovalAvailable: false,\n isProcessing: false,\n isSaving: false\n }\n }\n\n /**\n * Get a state value\n * @param {string} key - State key (supports dot notation: 'crop.shape')\n * @returns {*} The state value\n */\n get(key) {\n if (key.includes('.')) {\n const parts = key.split('.')\n let value = this._state\n for (const part of parts) {\n if (value === undefined || value === null) return undefined\n value = value[part]\n }\n return value\n }\n return this._state[key]\n }\n\n /**\n * Set a state value and emit change event\n * @param {string} key - State key (supports dot notation: 'crop.shape')\n * @param {*} value - New value\n */\n set(key, value) {\n const old = this.get(key)\n\n if (key.includes('.')) {\n const parts = key.split('.')\n const lastKey = parts.pop()\n let target = this._state\n for (const part of parts) {\n if (target[part] === undefined) target[part] = {}\n target = target[part]\n }\n target[lastKey] = value\n } else {\n this._state[key] = value\n }\n\n this.emit(`change:${key}`, { value, old })\n this.emit('change', { key, value, old })\n }\n\n /**\n * Get the entire state object (for debugging).\n * WARNING: Shallow copy only — nested objects are live references.\n * For persistence, use getSerializableState() instead.\n */\n getAll() {\n return { ...this._state }\n }\n\n /**\n * Deep clone a JSON-compatible editor payload.\n * @param {*} value\n * @returns {*}\n */\n _clonePlain(value) {\n if (value === null || value === undefined) return value\n return JSON.parse(JSON.stringify(value))\n }\n\n /**\n * Get a deep, serializable snapshot of the editor state.\n * Safe for persistence — no mutable references leak out.\n * @returns {Object} ImageEditorSessionState-compatible object\n */\n getSerializableState() {\n const filters = []\n if (this._state.activeFilters) {\n for (const filterId of this._state.activeFilters) {\n const values = this._state.filterValues[filterId]\n filters.push({\n id: filterId,\n enabled: true,\n values: values ? { ...values } : {}\n })\n }\n }\n\n const crop = this._state.crop\n return {\n version: 1,\n crop: {\n rect: crop?.rect ? { ...crop.rect } : null,\n aspectRatio: crop?.aspect || 'free',\n shape: crop?.shape || 'free'\n },\n transform: {\n rotation: Number(this._state.transform?.rotation) || 0\n },\n filters\n }\n }\n\n /**\n * Store the active immutable v2 editor document snapshot.\n * @param {Object|null} document\n * @param {{ documentId?: string|null, documentRevisionId?: string|null, documentRevisionNumber?: number|null }} binding\n */\n setEditorDocument(document, binding = {}) {\n if (!document || document.version !== 2 || !Array.isArray(document.layers)) {\n this.clearEditorDocument()\n return\n }\n\n const snapshot = this._clonePlain(document)\n const layers = this._clonePlain(snapshot.layers)\n .map(layer => this._normalizeLayerForState(layer))\n const activeLayerId = typeof snapshot.activeLayerId === 'string'\n ? snapshot.activeLayerId\n : (layers[0]?.id ?? null)\n\n this._state.editorDocument = {\n ...snapshot,\n layers,\n activeLayerId,\n }\n this._state.editorDocumentId = binding.documentId ?? snapshot.id ?? null\n this._state.editorDocumentRevisionId = binding.documentRevisionId ?? null\n this._state.editorDocumentRevisionNumber = binding.documentRevisionNumber ?? snapshot.revision ?? null\n this._state.layers = layers\n this._state.activeLayerId = activeLayerId\n\n this.emit('change:editorDocument', { value: this.getSerializableDocument() })\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:activeLayerId', { value: activeLayerId })\n this._syncFilterStateFromActiveLayer()\n }\n\n clearEditorDocument() {\n this._state.editorDocument = null\n this._state.editorDocumentId = null\n this._state.editorDocumentRevisionId = null\n this._state.editorDocumentRevisionNumber = null\n this._state.layers = []\n this._state.activeLayerId = null\n this._state.activeFilters = new Set()\n this._state.filterValues = {}\n this._state.selectedFilter = null\n this.emit('change:editorDocument', { value: null })\n this.emit('change:layers', { value: [] })\n this.emit('change:activeLayerId', { value: null })\n this.emit('change:activeFilters', { value: this._state.activeFilters })\n this.emit('change:filterValues', this._state.filterValues)\n this.emit('change:selectedFilter', { value: null })\n }\n\n /**\n * @returns {Object|null}\n */\n getSerializableDocument() {\n if (!this._state.editorDocument) return null\n\n const document = this._clonePlain(this._state.editorDocument)\n document.layers = this._clonePlain(this._state.layers)\n document.activeLayerId = this._state.activeLayerId\n\n // Fold the editor's transform/crop session state into the active subject\n // layer so the persisted document records the user-applied edits. The\n // editor tracks `_state.transform.rotation` and `_state.crop.applied*`\n // separately from per-layer state for renderer simplicity, but the\n // server-side document contract expects per-layer `transform.rotation`\n // and a per-layer `crop` payload. Without this fold, a user who rotated\n // or cropped would save a no-op edit (rotation: 0 / crop: null).\n const subjectIndex = document.layers.findIndex(layer => layer && (\n layer.role === 'subject' || (layer.type === 'image' && layer.role !== 'overlay')\n ))\n if (subjectIndex !== -1) {\n const subject = document.layers[subjectIndex]\n const rotation = this._normalizeDegrees(this._state.transform?.rotation ?? 0)\n const baseTransform = subject.transform && typeof subject.transform === 'object'\n ? subject.transform\n : { x: 0, y: 0, scaleX: 1, scaleY: 1, rotation: 0 }\n subject.transform = {\n ...baseTransform,\n rotation,\n }\n\n const cropState = this._state.crop && typeof this._state.crop === 'object' ? this._state.crop : null\n const appliedRect = cropState?.appliedRect && typeof cropState.appliedRect === 'object'\n ? cropState.appliedRect\n : null\n if (appliedRect) {\n subject.crop = {\n rect: { ...appliedRect },\n shape: cropState.appliedShape || 'free',\n aspect: cropState.appliedAspect || 'free',\n }\n }\n\n document.layers[subjectIndex] = subject\n }\n\n return document\n }\n\n /**\n * @returns {{ documentId: string|null, documentRevisionId: string|null, documentRevisionNumber: number|null }|null}\n */\n getEditorDocumentBinding() {\n if (!this._state.editorDocument) return null\n\n return {\n documentId: this._state.editorDocumentId,\n documentRevisionId: this._state.editorDocumentRevisionId,\n documentRevisionNumber: this._state.editorDocumentRevisionNumber,\n }\n }\n\n /**\n * @param {string} layerId\n * @returns {number}\n */\n _findLayerIndex(layerId) {\n return this._state.layers.findIndex(layer => layer?.id === layerId)\n }\n\n /**\n * @param {Object|null|undefined} layer\n * @returns {boolean}\n */\n _layerLocked(layer) {\n return layer?.locked === true\n }\n\n /**\n * @param {Object[]|null|undefined} layers\n * @returns {boolean}\n */\n _backgroundLayerLocked(layers = this._state.layers) {\n const index = this._backgroundLayerIndex(layers)\n return index !== -1 && this._layerLocked(layers[index])\n }\n\n /**\n * @returns {boolean}\n */\n isBackgroundLayerLocked() {\n return this._backgroundLayerLocked()\n }\n\n /**\n * @param {string} baseId\n * @returns {string}\n */\n _uniqueLayerId(baseId) {\n const existingIds = new Set(this._state.layers.map(layer => layer?.id).filter(Boolean))\n const safeBase = String(baseId || 'layer').replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || 'layer'\n if (!existingIds.has(safeBase)) return safeBase\n\n for (let suffix = 2; suffix < 10000; suffix += 1) {\n const candidate = `${safeBase}-${suffix}`\n if (!existingIds.has(candidate)) return candidate\n }\n\n return `${safeBase}-${Date.now()}`\n }\n\n /**\n * @param {Object|null|undefined} layer\n * @returns {Object|null|undefined}\n */\n _normalizeLayerForState(layer) {\n if (!layer || typeof layer !== 'object') return layer\n if (layer.type !== 'text' && layer.role !== 'text') {\n return {\n ...layer,\n filters: this._normalizeLayerFilters(layer.filters),\n }\n }\n\n return this._normalizeTextLayer({\n ...layer,\n id: typeof layer.id === 'string' && layer.id.trim() !== '' ? layer.id : this._uniqueLayerId('text-layer'),\n name: typeof layer.name === 'string' && layer.name.trim() !== '' ? layer.name : 'Text',\n }, layer)\n }\n\n /**\n * @param {Array|null|undefined} filters\n * @returns {Array}\n */\n _normalizeLayerFilters(filters) {\n if (!Array.isArray(filters)) return []\n\n return filters\n .filter(filter => filter && typeof filter === 'object' && typeof filter.id === 'string' && filter.id.trim() !== '')\n .map(filter => ({\n id: filter.id.trim(),\n enabled: filter.enabled !== false,\n values: filter.values && typeof filter.values === 'object'\n ? this._clonePlain(filter.values)\n : {},\n }))\n }\n\n /**\n * @param {Object|null|undefined} layer\n * @returns {boolean}\n */\n _layerSupportsFilters(layer) {\n if (!layer || typeof layer !== 'object') return false\n if (layer.type === 'image') return true\n if (layer.type === 'background' || layer.role === 'background') {\n return layer.fill?.kind === 'media'\n }\n\n return false\n }\n\n /**\n * @returns {number}\n */\n _activeFilterLayerIndex() {\n const activeLayerId = this._state.activeLayerId\n if (!activeLayerId || !Array.isArray(this._state.layers)) return -1\n\n const index = this._findLayerIndex(activeLayerId)\n return index !== -1 && this._layerSupportsFilters(this._state.layers[index]) ? index : -1\n }\n\n /**\n * @returns {string|null}\n */\n getActiveFilterLayerId() {\n const index = this._activeFilterLayerIndex()\n return index !== -1 ? this._state.layers[index]?.id ?? null : null\n }\n\n /**\n * @param {string|null|undefined} expectedLayerId\n * @returns {boolean}\n */\n _matchesExpectedFilterLayer(expectedLayerId) {\n if (!this._state.editorDocument) return true\n if (expectedLayerId === undefined) return true\n if (expectedLayerId === null) return this.getActiveFilterLayerId() === null\n\n const expected = typeof expectedLayerId === 'string' ? expectedLayerId.trim() : ''\n if (expected === '') return false\n\n return this.getActiveFilterLayerId() === expected\n }\n\n /**\n * Project the active filterable layer into the legacy filter UI state.\n */\n _syncFilterStateFromActiveLayer() {\n if (!this._state.editorDocument) return\n\n const index = this._activeFilterLayerIndex()\n const activeFilters = new Set()\n const filterValues = {}\n\n if (index !== -1) {\n for (const filter of this._normalizeLayerFilters(this._state.layers[index]?.filters)) {\n if (filter.enabled === false) continue\n activeFilters.add(filter.id)\n filterValues[filter.id] = this._clonePlain(filter.values || {})\n }\n }\n\n const oldSelectedFilter = this._state.selectedFilter\n this._state.activeFilters = activeFilters\n this._state.filterValues = filterValues\n if (oldSelectedFilter && !activeFilters.has(oldSelectedFilter)) {\n this._state.selectedFilter = null\n }\n\n this.emit('change:activeFilters', { value: this._state.activeFilters })\n this.emit('change:filterValues', this._state.filterValues)\n if (this._state.selectedFilter !== oldSelectedFilter) {\n this.emit('change:selectedFilter', { value: this._state.selectedFilter, old: oldSelectedFilter })\n }\n }\n\n /**\n * @param {*} value\n * @param {number} min\n * @param {number} max\n * @param {number} fallback\n * @returns {number}\n */\n _clampNumber(value, min, max, fallback) {\n const numeric = Number(value)\n if (!Number.isFinite(numeric)) return fallback\n\n return Math.max(min, Math.min(max, numeric))\n }\n\n /**\n * @param {*} value\n * @returns {number}\n */\n _normalizeDegrees(value) {\n const numeric = Number(value)\n if (!Number.isFinite(numeric)) return 0\n\n const normalized = numeric % 360\n return normalized < 0 ? normalized + 360 : normalized\n }\n\n /**\n * @param {*} value\n * @returns {boolean}\n */\n _isSupportedTextColor(value) {\n return typeof value === 'string' && /^#[0-9a-f]{6}$/i.test(value)\n }\n\n /**\n * @param {*} value\n * @param {string} fallback\n * @returns {string}\n */\n _normalizeTextColor(value, fallback) {\n return this._isSupportedTextColor(value)\n ? value\n : (this._isSupportedTextColor(fallback) ? fallback : '#000000')\n }\n\n /**\n * @param {*} value\n * @param {boolean} fallback\n * @returns {boolean}\n */\n _normalizeBoolean(value, fallback = false) {\n return typeof value === 'boolean' ? value : fallback === true\n }\n\n /**\n * @param {*} value\n * @param {string} fallback\n * @returns {string}\n */\n _normalizeBlendMode(value, fallback = 'normal') {\n if (TEXT_LAYER_BLEND_MODES.includes(value)) return value\n if (TEXT_LAYER_BLEND_MODES.includes(fallback)) return fallback\n\n return 'normal'\n }\n\n /**\n * @param {*} value\n * @returns {string}\n */\n _normalizeTextFontFamily(value) {\n const candidate = typeof value === 'string' ? value.trim() : ''\n return TEXT_LAYER_FONT_FAMILIES.includes(candidate) ? candidate : DEFAULT_TEXT_STYLE.fontFamily\n }\n\n /**\n * @param {*} value\n * @param {number} fallback\n * @returns {number}\n */\n _normalizeTextFontWeight(value, fallback = DEFAULT_TEXT_STYLE.fontWeight) {\n if (value === 'normal') return 400\n if (value === 'bold') return 700\n\n const numeric = Number(value)\n if (!Number.isFinite(numeric)) return fallback\n if (numeric < 100 || numeric > 900 || numeric % 100 !== 0) return fallback\n\n return numeric\n }\n\n /**\n * @param {Object|null|undefined} box\n * @param {Object|null|undefined} base\n * @returns {{ x: number, y: number, width: number, height: number }}\n */\n _normalizeTextBox(box, base = null) {\n const fallback = base && typeof base === 'object' ? base : DEFAULT_TEXT_BOX\n const source = box && typeof box === 'object' ? box : {}\n\n return {\n x: this._clampNumber(source.x, 0, 1, this._clampNumber(fallback.x, 0, 1, DEFAULT_TEXT_BOX.x)),\n y: this._clampNumber(source.y, 0, 1, this._clampNumber(fallback.y, 0, 1, DEFAULT_TEXT_BOX.y)),\n width: this._clampNumber(source.width, 0.05, 1, this._clampNumber(fallback.width, 0.05, 1, DEFAULT_TEXT_BOX.width)),\n height: this._clampNumber(source.height, 0.05, 1, this._clampNumber(fallback.height, 0.05, 1, DEFAULT_TEXT_BOX.height)),\n }\n }\n\n /**\n * @param {Object|null|undefined} style\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextStyle(style, base = null) {\n const fallback = {\n ...DEFAULT_TEXT_STYLE,\n ...(base && typeof base === 'object' ? base : {}),\n }\n const source = style && typeof style === 'object' ? style : {}\n const hasUnsupportedFontSource = !!source.fontSource || !!source.source || !!source.url\n const fontFamily = hasUnsupportedFontSource\n ? DEFAULT_TEXT_STYLE.fontFamily\n : this._normalizeTextFontFamily(source.fontFamily ?? fallback.fontFamily)\n const fontStyle = ['normal', 'italic'].includes(source.fontStyle)\n ? source.fontStyle\n : (['normal', 'italic'].includes(fallback.fontStyle) ? fallback.fontStyle : DEFAULT_TEXT_STYLE.fontStyle)\n const align = ['left', 'center', 'right'].includes(source.align)\n ? source.align\n : (['left', 'center', 'right'].includes(fallback.align) ? fallback.align : DEFAULT_TEXT_STYLE.align)\n const fill = this._isSupportedTextColor(source.fill)\n ? source.fill\n : (this._isSupportedTextColor(fallback.fill) ? fallback.fill : DEFAULT_TEXT_STYLE.fill)\n\n return {\n fontFamily,\n fontSize: this._clampNumber(source.fontSize, 8, 400, this._clampNumber(fallback.fontSize, 8, 400, DEFAULT_TEXT_STYLE.fontSize)),\n fontWeight: this._normalizeTextFontWeight(source.fontWeight, this._normalizeTextFontWeight(fallback.fontWeight, DEFAULT_TEXT_STYLE.fontWeight)),\n fontStyle,\n fill,\n align,\n lineHeight: this._clampNumber(source.lineHeight, 0.8, 3, this._clampNumber(fallback.lineHeight, 0.8, 3, DEFAULT_TEXT_STYLE.lineHeight)),\n letterSpacing: this._clampNumber(source.letterSpacing, -100, 100, this._clampNumber(fallback.letterSpacing, -100, 100, DEFAULT_TEXT_STYLE.letterSpacing)),\n }\n }\n\n /**\n * @param {Object|null|undefined} effects\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextEffects(effects, base = null) {\n const source = effects && typeof effects === 'object' ? effects : {}\n const baseEffects = base && typeof base === 'object' ? base : {}\n\n const fallback = {\n stroke: { ...DEFAULT_TEXT_EFFECTS.stroke, ...(baseEffects.stroke && typeof baseEffects.stroke === 'object' ? baseEffects.stroke : {}) },\n shadow: { ...DEFAULT_TEXT_EFFECTS.shadow, ...(baseEffects.shadow && typeof baseEffects.shadow === 'object' ? baseEffects.shadow : {}) },\n glow: { ...DEFAULT_TEXT_EFFECTS.glow, ...(baseEffects.glow && typeof baseEffects.glow === 'object' ? baseEffects.glow : {}) },\n backdrop: { ...DEFAULT_TEXT_EFFECTS.backdrop, ...(baseEffects.backdrop && typeof baseEffects.backdrop === 'object' ? baseEffects.backdrop : {}) },\n }\n const stroke = source.stroke && typeof source.stroke === 'object' ? source.stroke : {}\n const shadow = source.shadow && typeof source.shadow === 'object' ? source.shadow : {}\n const glow = source.glow && typeof source.glow === 'object' ? source.glow : {}\n const backdrop = source.backdrop && typeof source.backdrop === 'object' ? source.backdrop : {}\n\n return {\n stroke: {\n enabled: this._normalizeBoolean(stroke.enabled, fallback.stroke.enabled),\n color: this._normalizeTextColor(stroke.color, fallback.stroke.color),\n width: this._clampNumber(stroke.width, 0, 80, this._clampNumber(fallback.stroke.width, 0, 80, DEFAULT_TEXT_EFFECTS.stroke.width)),\n },\n shadow: {\n enabled: this._normalizeBoolean(shadow.enabled, fallback.shadow.enabled),\n color: this._normalizeTextColor(shadow.color, fallback.shadow.color),\n alpha: this._clampNumber(shadow.alpha, 0, 1, this._clampNumber(fallback.shadow.alpha, 0, 1, DEFAULT_TEXT_EFFECTS.shadow.alpha)),\n blur: this._clampNumber(shadow.blur, 0, 120, this._clampNumber(fallback.shadow.blur, 0, 120, DEFAULT_TEXT_EFFECTS.shadow.blur)),\n distance: this._clampNumber(shadow.distance, 0, 200, this._clampNumber(fallback.shadow.distance, 0, 200, DEFAULT_TEXT_EFFECTS.shadow.distance)),\n angle: this._normalizeDegrees(shadow.angle ?? fallback.shadow.angle ?? DEFAULT_TEXT_EFFECTS.shadow.angle),\n },\n glow: {\n enabled: this._normalizeBoolean(glow.enabled, fallback.glow.enabled),\n color: this._normalizeTextColor(glow.color, fallback.glow.color),\n alpha: this._clampNumber(glow.alpha, 0, 1, this._clampNumber(fallback.glow.alpha, 0, 1, DEFAULT_TEXT_EFFECTS.glow.alpha)),\n blur: this._clampNumber(glow.blur, 0, 120, this._clampNumber(fallback.glow.blur, 0, 120, DEFAULT_TEXT_EFFECTS.glow.blur)),\n },\n backdrop: {\n enabled: this._normalizeBoolean(backdrop.enabled, fallback.backdrop.enabled),\n color: this._normalizeTextColor(backdrop.color, fallback.backdrop.color),\n opacity: this._clampNumber(backdrop.opacity, 0, 1, this._clampNumber(fallback.backdrop.opacity, 0, 1, DEFAULT_TEXT_EFFECTS.backdrop.opacity)),\n padding: this._clampNumber(backdrop.padding, 0, 200, this._clampNumber(fallback.backdrop.padding, 0, 200, DEFAULT_TEXT_EFFECTS.backdrop.padding)),\n radius: this._clampNumber(backdrop.radius, 0, 200, this._clampNumber(fallback.backdrop.radius, 0, 200, DEFAULT_TEXT_EFFECTS.backdrop.radius)),\n blur: this._clampNumber(backdrop.blur, 0, 80, this._clampNumber(fallback.backdrop.blur, 0, 80, DEFAULT_TEXT_EFFECTS.backdrop.blur)),\n },\n }\n }\n\n /**\n * @param {Object|null|undefined} transform\n * @param {Object|null|undefined} base\n * @returns {{ x: number, y: number, scaleX: number, scaleY: number, rotation: number }}\n */\n _normalizeLayerTransform(transform, base = null) {\n const fallback = base && typeof base === 'object' ? base : {}\n const source = transform && typeof transform === 'object' ? transform : {}\n\n return {\n x: this._clampNumber(source.x, -100000, 100000, this._clampNumber(fallback.x, -100000, 100000, 0)),\n y: this._clampNumber(source.y, -100000, 100000, this._clampNumber(fallback.y, -100000, 100000, 0)),\n scaleX: this._clampNumber(source.scaleX, 0.01, 100, this._clampNumber(fallback.scaleX, 0.01, 100, 1)),\n scaleY: this._clampNumber(source.scaleY, 0.01, 100, this._clampNumber(fallback.scaleY, 0.01, 100, 1)),\n rotation: this._normalizeDegrees(source.rotation ?? fallback.rotation ?? 0),\n }\n }\n\n /**\n * @param {Object|null|undefined} input\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextPayload(input = {}, base = null) {\n const source = input && typeof input === 'object' ? input : {}\n const baseText = base?.text && typeof base.text === 'object' ? base.text : base\n const contentSource = source.content ?? source.text?.content ?? baseText?.content ?? 'Add text'\n const boxSource = source.box ?? source.text?.box\n const styleSource = source.style ?? source.text?.style\n const effectsSource = source.text?.effects ?? (source.effects && !Array.isArray(source.effects) ? source.effects : undefined)\n\n return {\n content: contentSource == null ? '' : String(contentSource),\n box: this._normalizeTextBox(boxSource, baseText?.box),\n style: this._normalizeTextStyle(styleSource, baseText?.style),\n effects: this._normalizeTextEffects(effectsSource, baseText?.effects),\n }\n }\n\n /**\n * @param {Object} input\n * @param {Object|null|undefined} base\n * @returns {Object}\n */\n _normalizeTextLayer(input = {}, base = null) {\n const source = input && typeof input === 'object' ? input : {}\n\n return {\n id: typeof source.id === 'string' && source.id.trim() !== '' ? source.id : this._uniqueLayerId('text-layer'),\n type: 'text',\n role: 'text',\n name: typeof source.name === 'string' && source.name.trim() !== '' ? source.name.trim() : 'Text',\n visible: source.visible === false ? false : true,\n locked: source.locked === true,\n opacity: this._clampNumber(source.opacity, 0, 1, 1),\n blendMode: this._normalizeBlendMode(source.blendMode, base?.blendMode),\n transform: this._normalizeLayerTransform(source.transform, base?.transform),\n effects: Array.isArray(source.effects) ? this._clonePlain(source.effects) : [],\n metadata: source.metadata && typeof source.metadata === 'object' ? this._clonePlain(source.metadata) : {},\n text: this._normalizeTextPayload(source, base),\n crop: null,\n filters: Array.isArray(source.filters) ? this._clonePlain(source.filters) : [],\n }\n }\n\n /**\n * @param {Object[]} layers\n * @param {number} removedIndex\n * @returns {string|null}\n */\n _nearestEditableLayerId(layers, removedIndex) {\n if (!layers.length) return null\n\n for (let distance = 0; distance < layers.length; distance += 1) {\n const nextIndex = removedIndex + distance\n if (nextIndex < layers.length && !this._layerLocked(layers[nextIndex]) && layers[nextIndex]?.visible !== false) {\n return layers[nextIndex].id ?? null\n }\n\n const previousIndex = removedIndex - distance - 1\n if (previousIndex >= 0 && !this._layerLocked(layers[previousIndex]) && layers[previousIndex]?.visible !== false) {\n return layers[previousIndex].id ?? null\n }\n }\n\n return null\n }\n\n /**\n * @param {Object[]} layers\n * @param {number} fromIndex\n * @param {number} toIndex\n * @returns {boolean}\n */\n _moveCrossesLockedLayer(layers, fromIndex, toIndex) {\n const start = Math.min(fromIndex, toIndex)\n const end = Math.max(fromIndex, toIndex)\n\n for (let index = start; index <= end; index += 1) {\n if (index === fromIndex) continue\n if (this._layerLocked(layers[index])) return true\n }\n\n return false\n }\n\n /**\n * @param {string} layerId\n * @returns {Object|null}\n */\n getLayer(layerId) {\n const layer = this._state.layers.find(candidate => candidate?.id === layerId)\n return layer ? this._clonePlain(layer) : null\n }\n\n /**\n * @param {string|null} layerId\n * @returns {boolean}\n */\n setActiveLayer(layerId) {\n if (layerId !== null && this._findLayerIndex(layerId) === -1) {\n return false\n }\n\n const old = this._state.activeLayerId\n this._state.activeLayerId = layerId\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = layerId\n }\n this.emit('change:activeLayerId', { value: layerId, old })\n this._syncFilterStateFromActiveLayer()\n\n return true\n }\n\n /**\n * @returns {boolean}\n */\n isActiveLayerLocked() {\n const activeLayerId = this._state.activeLayerId\n if (!activeLayerId) return false\n\n const activeLayer = this._state.layers.find(layer => layer?.id === activeLayerId)\n return !!activeLayer?.locked\n }\n\n /**\n * @param {string} layerId\n * @param {boolean} visible\n * @returns {boolean}\n */\n setLayerVisibility(layerId, visible) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n layers[index].visible = !!visible\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:layerVisibility', { layerId, visible: !!visible })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {string} name\n * @returns {boolean}\n */\n renameLayer(layerId, name) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n const nextName = String(name ?? '').trim()\n if (nextName === '') return false\n\n const oldName = layers[index].name ?? ''\n layers[index].name = nextName\n this._commitLayers(layers, 'change:layerRenamed', { layerId, name: nextName, oldName })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @returns {string|null}\n */\n duplicateLayer(layerId) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return null\n\n const layers = this._clonePlain(this._state.layers)\n const sourceLayer = layers[index]\n if (this._layerLocked(sourceLayer)) return null\n\n const duplicate = this._clonePlain(sourceLayer)\n duplicate.id = this._uniqueLayerId(`${sourceLayer.id || 'layer'}-copy`)\n duplicate.name = `${String(sourceLayer.name || 'Layer').trim() || 'Layer'} copy`\n duplicate.locked = false\n duplicate.metadata = {\n ...(duplicate.metadata && typeof duplicate.metadata === 'object' ? duplicate.metadata : {}),\n duplicatedFromLayerId: sourceLayer.id ?? null,\n duplicatedAt: new Date().toISOString(),\n }\n\n layers.splice(index + 1, 0, duplicate)\n const oldActiveLayerId = this._state.activeLayerId\n this._state.activeLayerId = duplicate.id\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = duplicate.id\n }\n\n this._commitLayers(layers, 'change:layerDuplicated', { layerId, duplicateLayerId: duplicate.id })\n this.emit('change:activeLayerId', { value: duplicate.id, old: oldActiveLayerId })\n\n return duplicate.id\n }\n\n /**\n * @param {string} layerId\n * @returns {boolean}\n */\n deleteLayer(layerId) {\n const index = this._findLayerIndex(layerId)\n if (index === -1 || this._state.layers.length <= 1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n const [removed] = layers.splice(index, 1)\n let nextActiveLayerId = this._state.activeLayerId\n if (nextActiveLayerId === layerId || !layers.some(layer => layer?.id === nextActiveLayerId)) {\n nextActiveLayerId = this._nearestEditableLayerId(layers, index)\n const oldActiveLayerId = this._state.activeLayerId\n this._state.activeLayerId = nextActiveLayerId\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = nextActiveLayerId\n }\n this.emit('change:activeLayerId', { value: nextActiveLayerId, old: oldActiveLayerId })\n }\n\n this._commitLayers(layers, 'change:layerDeleted', { layerId: removed?.id ?? layerId })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {'up'|'down'|'front'|'back'|'bring-forward'|'send-backward'|'bring-to-front'|'send-to-back'} direction\n * @returns {boolean}\n */\n moveLayer(layerId, direction) {\n const fromIndex = this._findLayerIndex(layerId)\n if (fromIndex === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[fromIndex])) return false\n\n let toIndex = fromIndex\n switch (direction) {\n case 'up':\n case 'bring-forward':\n toIndex = Math.min(layers.length - 1, fromIndex + 1)\n break\n case 'down':\n case 'send-backward':\n toIndex = Math.max(0, fromIndex - 1)\n break\n case 'front':\n case 'bring-to-front':\n toIndex = layers.length - 1\n break\n case 'back':\n case 'send-to-back':\n toIndex = 0\n break\n default:\n return false\n }\n\n if (toIndex === fromIndex) return false\n if (this._moveCrossesLockedLayer(layers, fromIndex, toIndex)) return false\n\n const [layer] = layers.splice(fromIndex, 1)\n layers.splice(toIndex, 0, layer)\n this._commitLayers(layers, 'change:layerMoved', { layerId, fromIndex, toIndex, direction })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {boolean} locked\n * @returns {boolean}\n */\n setLayerLocked(layerId, locked) {\n const index = this._findLayerIndex(layerId)\n if (index === -1) return false\n\n const layers = this._clonePlain(this._state.layers)\n layers[index].locked = !!locked\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:layerLocked', { layerId, locked: !!locked })\n\n return true\n }\n\n /**\n * @param {string} layerId\n * @param {Object} source\n * @returns {boolean}\n */\n replaceLayerSource(layerId, source) {\n const index = this._findLayerIndex(layerId)\n if (index === -1 || !source || typeof source !== 'object') return false\n\n const layers = this._clonePlain(this._state.layers)\n if (this._layerLocked(layers[index])) return false\n\n layers[index].source = this._clonePlain(source)\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n this._state.editorDocument.updatedAt = new Date().toISOString()\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n this.emit('change:layerSource', { layerId, source: this._clonePlain(source) })\n\n return true\n }\n\n /**\n * @param {Object} payload\n * @returns {string|null}\n */\n addTextLayer(payload = {}) {\n if (!this._state.editorDocument || !Array.isArray(this._state.layers)) {\n return null\n }\n\n const layers = this._clonePlain(this._state.layers)\n const layer = this._normalizeTextLayer({\n ...(payload && typeof payload === 'object' ? payload : {}),\n id: this._uniqueLayerId(payload?.id || 'text-layer'),\n })\n\n layers.push(layer)\n const oldActiveLayerId = this._state.activeLayerId\n this._state.activeLayerId = layer.id\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = layer.id\n }\n\n this._commitLayers(layers, 'change:textLayer', { action: 'created', layerId: layer.id })\n this.emit('change:activeLayerId', { value: layer.id, old: oldActiveLayerId })\n\n return layer.id\n }\n\n /**\n * @param {string} layerId\n * @param {Object} patch\n * @returns {boolean}\n */\n updateTextLayer(layerId, patch = {}) {\n const index = this._findLayerIndex(layerId)\n if (index === -1 || !patch || typeof patch !== 'object') return false\n\n const layers = this._clonePlain(this._state.layers)\n const layer = layers[index]\n if (this._layerLocked(layer) || (layer.type !== 'text' && layer.role !== 'text')) {\n return false\n }\n\n const textPatch = patch.text && typeof patch.text === 'object' ? patch.text : {}\n const nextLayer = this._normalizeTextLayer({\n ...layer,\n transform: patch.transform && typeof patch.transform === 'object'\n ? { ...layer.transform, ...patch.transform }\n : layer.transform,\n text: {\n ...(layer.text && typeof layer.text === 'object' ? layer.text : {}),\n ...textPatch,\n ...('content' in patch ? { content: patch.content } : {}),\n ...('box' in patch ? { box: patch.box } : {}),\n ...('style' in patch ? { style: { ...(layer.text?.style || {}), ...(patch.style || {}) } } : {}),\n ...('effects' in patch ? { effects: patch.effects } : {}),\n },\n ...(patch.name !== undefined ? { name: patch.name } : {}),\n ...(patch.opacity !== undefined ? { opacity: patch.opacity } : {}),\n ...(patch.blendMode !== undefined ? { blendMode: patch.blendMode } : {}),\n }, layer)\n\n layers[index] = nextLayer\n this._commitLayers(layers, 'change:textLayer', {\n action: 'updated',\n layerId,\n text: this._clonePlain(nextLayer.text),\n })\n\n return true\n }\n\n _commitLayers(layers, eventName = null, eventPayload = {}) {\n this._state.layers = layers\n if (this._state.editorDocument) {\n this._state.editorDocument.layers = this._clonePlain(layers)\n this._state.editorDocument.updatedAt = new Date().toISOString()\n }\n\n this.emit('change:layers', { value: this._clonePlain(layers) })\n if (eventName) {\n this.emit(eventName, eventPayload)\n }\n }\n\n _backgroundLayerIndex(layers = this._state.layers) {\n return layers.findIndex(layer => layer?.type === 'background' || layer?.role === 'background')\n }\n\n _defaultBackgroundLayer(fill = { kind: 'transparent' }) {\n const existingIds = new Set(this._state.layers.map(layer => layer?.id).filter(Boolean))\n let id = 'background-layer'\n if (existingIds.has(id)) {\n id = `background-layer-${Date.now()}`\n }\n\n return {\n id,\n type: 'background',\n role: 'background',\n name: 'Background',\n visible: true,\n locked: false,\n opacity: 1,\n blendMode: 'normal',\n transform: { x: 0, y: 0, scaleX: 1, scaleY: 1, rotation: 0 },\n effects: [],\n metadata: {},\n fill: this._clonePlain(fill),\n crop: null,\n filters: [],\n }\n }\n\n _normalizeBackgroundFill(fill) {\n if (!fill || typeof fill !== 'object') {\n return { kind: 'transparent' }\n }\n\n const fit = ['cover', 'contain', 'stretch', 'tile'].includes(fill.fit) ? fill.fit : undefined\n if (fill.kind === 'color') {\n return {\n kind: 'color',\n value: typeof fill.value === 'string' ? fill.value : (typeof fill.color === 'string' ? fill.color : '#ffffff'),\n ...(fit ? { fit } : {}),\n }\n }\n\n if (fill.kind === 'gradient') {\n const stops = Array.isArray(fill.stops) && fill.stops.length > 0\n ? fill.stops\n .filter(stop => stop && typeof stop === 'object' && typeof stop.color === 'string')\n .map(stop => ({\n offset: Number.isFinite(Number(stop.offset)) ? Math.max(0, Math.min(1, Number(stop.offset))) : 0,\n color: stop.color,\n }))\n : [\n { offset: 0, color: '#111827' },\n { offset: 1, color: '#f59e0b' },\n ]\n\n return {\n kind: 'gradient',\n gradientType: ['linear', 'radial'].includes(fill.gradientType) ? fill.gradientType : 'linear',\n angle: Number.isFinite(Number(fill.angle)) ? Number(fill.angle) : 135,\n stops,\n fit: fit || 'cover',\n }\n }\n\n if (fill.kind === 'media' && fill.source && typeof fill.source === 'object') {\n return {\n kind: 'media',\n source: this._clonePlain(fill.source),\n fit: fit || 'cover',\n }\n }\n\n return { kind: 'transparent' }\n }\n\n ensureBackgroundLayer(fill = { kind: 'transparent' }) {\n const layers = this._clonePlain(this._state.layers)\n const existingIndex = this._backgroundLayerIndex(layers)\n if (existingIndex !== -1) {\n if (this._layerLocked(layers[existingIndex])) return null\n return layers[existingIndex].id\n }\n\n const layer = this._defaultBackgroundLayer(this._normalizeBackgroundFill(fill))\n const firstSubjectIndex = layers.findIndex(candidate => candidate?.role === 'subject' || candidate?.type === 'image')\n const insertAt = firstSubjectIndex >= 0 ? firstSubjectIndex : 0\n layers.splice(insertAt, 0, layer)\n this._commitLayers(layers, 'change:backgroundLayer', { layerId: layer.id, action: 'created' })\n\n return layer.id\n }\n\n setBackgroundFill(fill) {\n const normalizedFill = this._normalizeBackgroundFill(fill)\n const layerId = this.ensureBackgroundLayer(normalizedFill)\n if (!layerId) return null\n\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return null\n if (this._layerLocked(layers[index])) return null\n\n const previousFit = layers[index].fill?.fit\n layers[index].fill = this._clonePlain({\n ...normalizedFill,\n ...(\n !normalizedFill.fit && previousFit && normalizedFill.kind !== 'transparent'\n ? { fit: previousFit }\n : {}\n ),\n })\n this._commitLayers(layers, 'change:backgroundFill', { layerId, fill: this._clonePlain(layers[index].fill) })\n\n return layerId\n }\n\n setBackgroundFit(fit) {\n if (!['cover', 'contain', 'stretch', 'tile'].includes(fit)) {\n return false\n }\n\n const layerId = this.ensureBackgroundLayer()\n if (!layerId) return false\n\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return false\n if (this._layerLocked(layers[index])) return false\n\n const fill = layers[index].fill && typeof layers[index].fill === 'object'\n ? layers[index].fill\n : { kind: 'transparent' }\n layers[index].fill = { ...fill, fit }\n this._commitLayers(layers, 'change:backgroundFit', { layerId, fit })\n\n return true\n }\n\n setBackgroundBlur(amount) {\n const numericAmount = Number.isFinite(Number(amount)) ? Math.max(0, Math.min(100, Number(amount))) : 0\n const layerId = this.ensureBackgroundLayer()\n if (!layerId) return false\n\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return false\n if (this._layerLocked(layers[index])) return false\n\n const effects = Array.isArray(layers[index].effects)\n ? layers[index].effects.filter(effect => effect?.id !== 'background-blur')\n : []\n if (numericAmount > 0) {\n effects.push({\n id: 'background-blur',\n type: 'blur',\n params: { amount: numericAmount },\n })\n }\n layers[index].effects = effects\n this._commitLayers(layers, 'change:backgroundBlur', { layerId, amount: numericAmount })\n\n return true\n }\n\n removeBackgroundLayer() {\n const layers = this._clonePlain(this._state.layers)\n const index = this._backgroundLayerIndex(layers)\n if (index === -1) return false\n if (this._layerLocked(layers[index])) return false\n\n const [removed] = layers.splice(index, 1)\n if (removed?.id && this._state.activeLayerId === removed.id) {\n const nextActive = this._nearestEditableLayerId(layers, index)\n this._state.activeLayerId = nextActive\n if (this._state.editorDocument) {\n this._state.editorDocument.activeLayerId = nextActive\n }\n this.emit('change:activeLayerId', { value: nextActive, old: removed.id })\n }\n\n this._commitLayers(layers, 'change:backgroundLayer', { layerId: removed?.id ?? null, action: 'removed' })\n\n return true\n }\n\n /**\n * Toggle a filter in the active filters set\n * @param {string} filterId\n * @param {boolean} enabled\n */\n toggleFilter(filterId, enabled, expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const index = this._activeFilterLayerIndex()\n if (index === -1) {\n this._syncFilterStateFromActiveLayer()\n return false\n }\n\n const id = typeof filterId === 'string' ? filterId.trim() : ''\n if (id === '') return false\n\n const layers = this._clonePlain(this._state.layers)\n const layer = layers[index]\n const filters = this._normalizeLayerFilters(layer.filters)\n const existingIndex = filters.findIndex(filter => filter.id === id)\n\n if (enabled) {\n if (existingIndex === -1) {\n filters.push({ id, enabled: true, values: {} })\n } else {\n filters[existingIndex].enabled = true\n }\n } else if (existingIndex !== -1) {\n filters.splice(existingIndex, 1)\n }\n\n layer.filters = filters\n this._commitLayers(layers, 'change:layerFilters', {\n layerId: layer.id,\n filterId: id,\n enabled: !!enabled,\n })\n this._syncFilterStateFromActiveLayer()\n\n return true\n }\n\n const filters = new Set(this._state.activeFilters)\n if (enabled) {\n filters.add(filterId)\n } else {\n filters.delete(filterId)\n delete this._state.filterValues[filterId]\n }\n this.set('activeFilters', filters)\n\n return true\n }\n\n /**\n * Update a filter's control value\n * @param {string} filterId\n * @param {string} controlId\n * @param {*} value\n */\n setFilterValue(filterId, controlId, value, expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const index = this._activeFilterLayerIndex()\n if (index === -1) {\n this._syncFilterStateFromActiveLayer()\n return false\n }\n\n const id = typeof filterId === 'string' ? filterId.trim() : ''\n if (id === '' || !this._state.activeFilters?.has?.(id)) return false\n\n const layers = this._clonePlain(this._state.layers)\n const layer = layers[index]\n const filters = this._normalizeLayerFilters(layer.filters)\n const filterIndex = filters.findIndex(filter => filter.id === id && filter.enabled !== false)\n if (filterIndex === -1) return false\n\n filters[filterIndex].values = {\n ...(filters[filterIndex].values && typeof filters[filterIndex].values === 'object' ? filters[filterIndex].values : {}),\n [controlId]: this._clonePlain(value),\n }\n layer.filters = filters\n this._commitLayers(layers, 'change:layerFilters', {\n layerId: layer.id,\n filterId: id,\n controlId,\n value: this._clonePlain(value),\n })\n this._syncFilterStateFromActiveLayer()\n this.emit('change:filterValue', { filterId: id, controlId, value })\n\n return true\n }\n\n if (!this._state.filterValues[filterId]) {\n this._state.filterValues[filterId] = {}\n }\n this._state.filterValues[filterId][controlId] = value\n this.emit('change:filterValue', { filterId, controlId, value })\n this.emit('change:filterValues', this._state.filterValues)\n\n return true\n }\n\n /**\n * Get a filter's control values\n * @param {string} filterId\n * @returns {Object} Filter values\n */\n getFilterValues(filterId) {\n return this._state.filterValues[filterId] || {}\n }\n\n /**\n * Initialize filter values from definition defaults\n * @param {string} filterId\n * @param {Array} controls - Control definitions with defaults\n */\n initFilterValues(filterId, controls, expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const existing = this.getFilterValues(filterId)\n controls.forEach(ctl => {\n if (!(ctl.id in existing)) {\n this.setFilterValue(filterId, ctl.id, ctl.default, expectedLayerId)\n }\n })\n return true\n }\n\n if (!this._state.filterValues[filterId]) {\n this._state.filterValues[filterId] = {}\n }\n controls.forEach(ctl => {\n if (!(ctl.id in this._state.filterValues[filterId])) {\n this._state.filterValues[filterId][ctl.id] = ctl.default\n }\n })\n this.emit('change:filterValues', this._state.filterValues)\n\n return true\n }\n\n /**\n * Reset all filters\n */\n resetFilters(expectedLayerId = undefined) {\n if (this._state.editorDocument) {\n if (!this._matchesExpectedFilterLayer(expectedLayerId)) return false\n\n const index = this._activeFilterLayerIndex()\n if (index === -1) {\n this._syncFilterStateFromActiveLayer()\n this.emit('filtersReset')\n return false\n }\n\n const layers = this._clonePlain(this._state.layers)\n layers[index].filters = []\n this._commitLayers(layers, 'change:layerFilters', {\n layerId: layers[index].id,\n action: 'reset',\n })\n this._syncFilterStateFromActiveLayer()\n this.emit('filtersReset')\n\n return true\n }\n\n this._state.activeFilters = new Set()\n this._state.filterValues = {}\n this._state.selectedFilter = null\n this.emit('change:activeFilters', { value: this._state.activeFilters })\n this.emit('change:filterValues', this._state.filterValues)\n this.emit('change:selectedFilter', { value: null })\n this.emit('filtersReset')\n\n return true\n }\n\n /**\n * Detect and set dark mode based on preference\n */\n detectTheme() {\n if (this._state.theme === 'auto') {\n const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches\n this.set('isDarkMode', prefersDark)\n } else {\n this.set('isDarkMode', this._state.theme === 'dark')\n }\n }\n}\n\n// Singleton instance\nlet instance = null\n\nexport function getState() {\n if (!instance) {\n instance = new State()\n }\n return instance\n}\n\nexport function createState() {\n return new State()\n}\n","/**\n * Filter Registry System\n * Centralized storage and management for filter definitions\n */\n// Since we can't directly import Filter, use any for now\n// and let the type system infer from usage\ntype Filter = any;\n\n/**\n * Interface for a filter control definition \n * Defines the UI representation of a filter parameter\n */\nexport interface ControlDefinition {\n id: string;\n type: 'slider' | 'toggle' | 'color' | 'select' | 'range' | 'button' | 'text';\n label: string;\n property?: string;\n action?: string;\n min?: number;\n max?: number;\n step?: number;\n default?: number | boolean | string;\n options?: Array<{ label: string; value: string | number }>;\n tooltip?: string;\n /** Placeholder text for 'text' type controls. */\n placeholder?: string;\n /** Hide this control from the UI without removing it from the definition. */\n hidden?: boolean;\n}\n\nexport type FilterMediaTarget = 'image' | 'video';\n\n/**\n * Interface for a filter definition\n * Contains all metadata needed to create and manage a filter\n */\nexport interface FilterDefinition {\n id: string;\n name: string;\n category: string;\n description?: string;\n thumbnail?: string;\n /**\n * Optional media compatibility tags.\n * Omitted means compatible with both image and video pipelines.\n */\n mediaTargets?: FilterMediaTarget[];\n createFilter: (params: Record<string, any>) => Filter;\n defaultParams: Record<string, any>;\n controls: ControlDefinition[];\n}\n\n// Filter registry storage\nconst filters = new Map<string, FilterDefinition>();\n\n// Category registry storage\nconst categories = new Map<string, string[]>();\n\nfunction isMediaCompatible(\n definition: FilterDefinition,\n target: FilterMediaTarget\n): boolean {\n if (!Array.isArray(definition.mediaTargets) || definition.mediaTargets.length === 0) {\n return true;\n }\n\n return definition.mediaTargets.includes(target);\n}\n\n/**\n * Register a filter in the global registry\n * @param definition The filter definition to register\n * @returns The provided filter definition (for chaining)\n */\nexport function registerFilter(definition: FilterDefinition): FilterDefinition {\n // Ensure the filter has a unique ID\n if (filters.has(definition.id)) {\n console.warn(`Filter with ID ${definition.id} already exists. Overwriting.`);\n }\n \n // Store the filter definition\n filters.set(definition.id, definition);\n \n // Add to category registry\n if (!categories.has(definition.category)) {\n categories.set(definition.category, []);\n }\n categories.get(definition.category)?.push(definition.id);\n \n return definition;\n}\n\n/**\n * Get a filter definition by ID\n * @param id The ID of the filter to retrieve\n * @returns The filter definition or undefined if not found\n */\nexport function getFilter(id: string): FilterDefinition | undefined {\n return filters.get(id);\n}\n\n/**\n * Get all registered filter definitions\n * @returns Array of all registered filter definitions\n */\nexport function getAllFilters(): FilterDefinition[] {\n return Array.from(filters.values());\n}\n\n/**\n * NEW: Bulk-register all classes re-exported by the `pixi-filters` bundle.\n * – Keeps bundle size reasonable (tree-shaken in prod)\n * – Lets you use *any* filter without first writing boilerplate\n */\nimport * as PixiFilters from 'pixi-filters';\n\n/**\n * Register all core PixiJS filters if they don't already have custom definitions,\n * but only using the actual custom definitions from their respective files.\n */\nexport function registerCorePixiFilters(): void {\n // Get the filters that are already loaded\n const customFilterIds = getAllFilters().map(f => f.id);\n \n // Get all available PixiJS filters from the pixi-filters package\n type FilterConstructor = new (...args: unknown[]) => unknown\n\n const pixiFilterEntries = Object.entries(PixiFilters) as Array<[string, unknown]>\n\n const pixiFilterClasses = pixiFilterEntries.filter(\n (entry): entry is [string, FilterConstructor] => /Filter$/.test(entry[0]) && typeof entry[1] === 'function'\n );\n \n // Reduce logging in production\n if (import.meta.env.DEV) {\n // Only log filter count, not the entire list\n console.log(`Found ${customFilterIds.length} custom filters and ${pixiFilterClasses.length} PixiJS filters`);\n }\n \n // We'll ONLY register core filters where we DON'T have a custom definition\n // This is intentionally minimalist to ensure we prioritize custom definitions\n let newlyRegisteredCount = 0;\n \n pixiFilterClasses.forEach(([exportName, FilterClass]) => {\n const id = exportName\n .replace(/Filter$/, '')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase();\n \n // Skip if this filter already has a custom definition\n if (filters.has(id)) {\n return;\n }\n \n // For remaining filters without custom definitions, just provide a minimal registration\n // that just allows the filter to be created but doesn't provide any controls\n // Reduce verbose logging in production\n if (import.meta.env.DEV) {\n console.debug(`Registering minimal entry for ${exportName}`);\n }\n newlyRegisteredCount++;\n \n // Register with minimal information - these won't appear in the UI properly\n // but will be available for debugging or programmatic use\n registerFilter({\n id,\n name: exportName.replace(/Filter$/, ''),\n category: 'unlisted', // Put in a category that won't be shown in UI\n mediaTargets: ['image'],\n defaultParams: {},\n controls: [], // No controls - we don't want to add generic controls\n createFilter: (params = {}) => {\n try {\n // Simply create the filter with params\n return new FilterClass(params);\n } catch (error) {\n console.error(`Error creating filter ${id}:`, error);\n return null;\n }\n },\n });\n });\n \n // Only log in development environment\n if (import.meta.env.DEV && newlyRegisteredCount > 0) {\n console.log(`Registered ${newlyRegisteredCount} additional filters`);\n }\n}\n\n// We will NOT auto-register at module load. \n// Instead, custom filter definitions will be loaded first, then we'll only register missing ones.\n// The actual registration happens when initializeFilterRegistry is called.\n\n/**\n * Get all filters in a specific category\n * @param category The category to retrieve filters for\n * @returns Array of filter definitions in the requested category\n */\nexport function getFiltersByCategory(category: string): FilterDefinition[] {\n const filterIds = categories.get(category) || [];\n return filterIds.map(id => filters.get(id)).filter(Boolean) as FilterDefinition[];\n}\n\n/**\n * Get all filter categories\n * @returns Array of category names\n */\nexport function getAllCategories(): string[] {\n return Array.from(categories.keys());\n}\n\n/**\n * Check if a filter is registered\n * @param id The ID of the filter to check\n * @returns True if the filter is registered, false otherwise\n */\nexport function hasFilter(id: string): boolean {\n return filters.has(id);\n}\n\n/**\n * Remove a filter from the registry.\n * @param id The ID of the filter to remove\n * @returns True if the filter was found and removed\n */\nexport function unregisterFilter(id: string): boolean {\n const definition = filters.get(id);\n if (!definition) {\n return false;\n }\n\n filters.delete(id);\n\n // Remove from category index\n const categoryIds = categories.get(definition.category);\n if (categoryIds) {\n const idx = categoryIds.indexOf(id);\n if (idx !== -1) {\n categoryIds.splice(idx, 1);\n }\n if (categoryIds.length === 0) {\n categories.delete(definition.category);\n }\n }\n\n return true;\n}\n\n/**\n * Check whether a registered filter is compatible with a media target.\n * Unknown filters are treated as incompatible.\n */\nexport function isFilterCompatibleWithMedia(\n id: string,\n target: FilterMediaTarget\n): boolean {\n const definition = filters.get(id);\n if (!definition) {\n return false;\n }\n\n return isMediaCompatible(definition, target);\n}\n\n/**\n * Return all registered filters compatible with the given media target.\n */\nexport function getFiltersByMedia(target: FilterMediaTarget): FilterDefinition[] {\n return Array.from(filters.values()).filter((definition) => isMediaCompatible(definition, target));\n}\n\n/**\n * Get all registered filters with simplified format for UI\n * @returns Array of filter definitions with only UI-relevant properties\n */\nexport function getRegisteredFilters(): Array<{\n id: string;\n name: string;\n category: string;\n controls: ControlDefinition[];\n}> {\n return Array.from(filters.values()).map(filter => ({\n id: filter.id,\n name: filter.name,\n category: filter.category,\n controls: filter.controls\n }));\n}\n\n// Add a debug function to expose filter registry in window\nif (typeof window !== 'undefined') {\n // Store filter list in window for debugging\n (window as any).__DEBUG_FILTERS_LIST = Array.from(filters.keys());\n \n // Expose registry functions for debugging\n (window as any).getAllFilters = getAllFilters;\n (window as any).getFilter = getFilter;\n (window as any).getFiltersByCategory = getFiltersByCategory;\n (window as any).getRegisteredFilters = getRegisteredFilters;\n \n // Update the debug list whenever a new filter is registered\n const originalRegisterFilter = registerFilter;\n (window as any).registerFilter = (definition: FilterDefinition) => {\n const result = originalRegisterFilter(definition);\n (window as any).__DEBUG_FILTERS_LIST = Array.from(filters.keys());\n console.log(`Filter \"${definition.id}\" registered. Total filters: ${filters.size}`);\n return result;\n };\n \n // Remove this console log - it's causing duplicate logging\n // if (process.env.NODE_ENV !== 'production') {\n // console.log(`Registry initialized with ${filters.size} filters`);\n // }\n}\n\n// Add a safety check for initializeFilterRegistry in case it's not working\n// This is a fallback in case the main implementation is facing issues\nif (typeof window !== 'undefined') {\n (window as any).initializeFilterRegistry = (window as any).initializeFilterRegistry || function() {\n console.warn('Using fallback window.initializeFilterRegistry');\n return [];\n };\n}\n","/**\n * Adjustment Filter Definition\n * Controls basic image adjustments like brightness, contrast, saturation, etc.\n */\nimport { registerFilter } from '../registry';\n// Import the AdjustmentFilter directly from the pixi-filters package\nimport * as PixiFilters from 'pixi-filters';\n// Access AdjustmentFilter from the pixi-filters package\nconst { AdjustmentFilter } = PixiFilters;\n\n// Import ColorMatrixFilter as fallback\nimport * as PIXI from 'pixi.js';\n// Access ColorMatrixFilter from pixi.js package\nconst { ColorMatrixFilter } = PIXI;\n\ninterface AdjustmentParams {\n gamma: number;\n saturation: number;\n contrast: number;\n brightness: number;\n red: number;\n green: number;\n blue: number;\n alpha: number;\n}\n\ntype AdjustmentParamKey = keyof AdjustmentParams;\n\nconst DEFAULT_ADJUSTMENT_PARAMS: AdjustmentParams = {\n gamma: 1,\n saturation: 1,\n contrast: 1,\n brightness: 1,\n red: 1,\n green: 1,\n blue: 1,\n alpha: 1,\n};\n\nconst ADJUSTMENT_PARAM_KEYS = new Set<AdjustmentParamKey>([\n 'gamma',\n 'saturation',\n 'contrast',\n 'brightness',\n 'red',\n 'green',\n 'blue',\n 'alpha',\n]);\n\nfunction toFiniteNumber(value: unknown, fallback: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value === 'string') {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n\n return fallback;\n}\n\nfunction isAdjustmentParamKey(key: string): key is AdjustmentParamKey {\n return ADJUSTMENT_PARAM_KEYS.has(key as AdjustmentParamKey);\n}\n\nfunction normalizeAdjustmentParams(params: Record<string, unknown>): AdjustmentParams {\n return {\n gamma: toFiniteNumber(params.gamma, DEFAULT_ADJUSTMENT_PARAMS.gamma),\n saturation: toFiniteNumber(params.saturation, DEFAULT_ADJUSTMENT_PARAMS.saturation),\n contrast: toFiniteNumber(params.contrast, DEFAULT_ADJUSTMENT_PARAMS.contrast),\n brightness: toFiniteNumber(params.brightness, DEFAULT_ADJUSTMENT_PARAMS.brightness),\n red: toFiniteNumber(params.red, DEFAULT_ADJUSTMENT_PARAMS.red),\n green: toFiniteNumber(params.green, DEFAULT_ADJUSTMENT_PARAMS.green),\n blue: toFiniteNumber(params.blue, DEFAULT_ADJUSTMENT_PARAMS.blue),\n alpha: toFiniteNumber(params.alpha, DEFAULT_ADJUSTMENT_PARAMS.alpha),\n };\n}\n\nfunction applyColorMatrixAdjustments(filter: PIXI.ColorMatrixFilter, params: AdjustmentParams): void {\n filter.reset();\n\n // ColorMatrixFilter operations must be multiplied to compose adjustments.\n filter.brightness(params.brightness, true);\n filter.contrast(params.contrast, true);\n filter.saturate(params.saturation, true);\n}\n\n// Register the adjustment filter\nexport default registerFilter({\n id: 'adjustment',\n name: 'Adjustment',\n category: 'adjust',\n description: 'Adjust basic image properties like brightness, contrast, and saturation',\n \n // Create an instance of the AdjustmentFilter with the provided parameters\n createFilter: (params) => {\n try {\n const normalizedParams = normalizeAdjustmentParams((params ?? {}) as Record<string, unknown>);\n console.log('Creating AdjustmentFilter with params:', normalizedParams);\n \n // Create options object for filter parameters\n const options = { ...normalizedParams };\n \n // Attempt to create AdjustmentFilter first (preferred)\n try {\n const filter = new AdjustmentFilter(options);\n\n type AdjustmentFilterWithUI = typeof filter & {\n _customParams?: AdjustmentParams;\n updateUIParam?: (key: string, value: unknown) => void;\n };\n const filterWithUI = filter as AdjustmentFilterWithUI;\n\n // Add custom updateUIParam method for dynamic updates\n filterWithUI._customParams = { ...normalizedParams };\n filterWithUI.updateUIParam = function updateUIParam(key: string, value: unknown): void {\n try {\n if (!isAdjustmentParamKey(key)) {\n return;\n }\n\n const customParams = this._customParams ?? { ...DEFAULT_ADJUSTMENT_PARAMS };\n const numericValue = toFiniteNumber(value, customParams[key]);\n customParams[key] = numericValue;\n this._customParams = customParams;\n\n const target = this as unknown as Record<string, unknown>;\n if (key in target) {\n target[key] = numericValue;\n }\n } catch (error) {\n console.error(`Error updating AdjustmentFilter parameter ${key}:`, error);\n }\n };\n \n console.log('AdjustmentFilter created successfully');\n return filter;\n } catch (error) {\n console.warn('Failed to create AdjustmentFilter, falling back to ColorMatrixFilter:', error);\n \n // Fall back to ColorMatrixFilter if AdjustmentFilter fails\n const filter = new ColorMatrixFilter();\n\n type ColorMatrixWithUI = typeof filter & {\n _customParams?: AdjustmentParams;\n updateUIParam?: (key: string, value: unknown) => void;\n };\n const filterWithUI = filter as ColorMatrixWithUI;\n\n // Store original parameters\n filterWithUI._customParams = { ...normalizedParams };\n\n // Apply initial adjustments as a composed matrix.\n applyColorMatrixAdjustments(filter, normalizedParams);\n \n // Add custom update method\n filterWithUI.updateUIParam = function updateUIParam(key: string, value: unknown): void {\n try {\n if (!isAdjustmentParamKey(key)) {\n return;\n }\n\n const customParams = this._customParams ?? { ...DEFAULT_ADJUSTMENT_PARAMS };\n const numericValue = toFiniteNumber(value, customParams[key]);\n customParams[key] = numericValue;\n this._customParams = customParams;\n\n applyColorMatrixAdjustments(this, customParams);\n } catch (error) {\n console.error(`Error updating ColorMatrixFilter parameter ${key}:`, error);\n }\n };\n \n console.log('ColorMatrixFilter created as fallback');\n return filter;\n }\n } catch (error) {\n console.error('Failed to create any adjustment filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n gamma: 1,\n saturation: 1,\n contrast: 1,\n brightness: 1,\n red: 1,\n green: 1,\n blue: 1,\n alpha: 1,\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'contrast',\n type: 'slider',\n label: 'Contrast',\n property: 'contrast',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'gamma',\n type: 'slider',\n label: 'Gamma',\n property: 'gamma',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'red',\n type: 'slider',\n label: 'Red',\n property: 'red',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'green',\n type: 'slider',\n label: 'Green',\n property: 'green',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'blue',\n type: 'slider',\n label: 'Blue',\n property: 'blue',\n min: 0,\n max: 5,\n step: 0.01,\n default: 1,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n ],\n});\n","/**\n * Advanced Adjustment Filter Definition\n * Provides advanced image adjustment options with a single filter\n */\nimport { registerFilter } from '../registry';\n// Import ColorMatrixFilter directly\nimport * as PIXI from 'pixi.js';\n// Access ColorMatrixFilter class\nconst { ColorMatrixFilter } = PIXI;\n\ninterface AdvancedAdjustmentParams {\n brightness: number;\n contrast: number;\n saturation: number;\n hue: number;\n sepia: number;\n negative: boolean;\n}\n\ntype AdvancedAdjustmentParamKey = keyof AdvancedAdjustmentParams;\n\nconst DEFAULT_ADVANCED_ADJUSTMENT_PARAMS: AdvancedAdjustmentParams = {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n hue: 0,\n sepia: 0,\n negative: false,\n};\n\nconst ADVANCED_ADJUSTMENT_PARAM_KEYS = new Set<AdvancedAdjustmentParamKey>([\n 'brightness',\n 'contrast',\n 'saturation',\n 'hue',\n 'sepia',\n 'negative',\n]);\n\nfunction isAdvancedAdjustmentParamKey(key: string): key is AdvancedAdjustmentParamKey {\n return ADVANCED_ADJUSTMENT_PARAM_KEYS.has(key as AdvancedAdjustmentParamKey);\n}\n\nfunction toFiniteNumber(value: unknown, fallback: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value === 'string') {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n\n return fallback;\n}\n\nfunction toBoolean(value: unknown, fallback: boolean): boolean {\n if (typeof value === 'boolean') {\n return value;\n }\n\n if (typeof value === 'string') {\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n }\n\n return fallback;\n}\n\nfunction normalizeAdvancedAdjustmentParams(params: Record<string, unknown>): AdvancedAdjustmentParams {\n return {\n brightness: toFiniteNumber(params.brightness, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.brightness),\n contrast: toFiniteNumber(params.contrast, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.contrast),\n saturation: toFiniteNumber(params.saturation, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.saturation),\n hue: toFiniteNumber(params.hue, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.hue),\n sepia: toFiniteNumber(params.sepia, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.sepia),\n negative: toBoolean(params.negative, DEFAULT_ADVANCED_ADJUSTMENT_PARAMS.negative),\n };\n}\n\nfunction applyAdvancedAdjustments(filter: PIXI.ColorMatrixFilter, params: AdvancedAdjustmentParams): void {\n // Reset first so we always apply from a clean identity matrix.\n filter.reset();\n\n if (params.brightness !== 1) {\n filter.brightness(params.brightness, true);\n }\n\n if (params.contrast !== 1) {\n filter.contrast(params.contrast, true);\n }\n\n if (params.saturation !== 1) {\n filter.saturate(params.saturation, true);\n }\n\n if (params.hue !== 0) {\n filter.hue(params.hue, true);\n }\n\n if (params.sepia > 0) {\n filter.sepia(true);\n }\n\n if (params.negative) {\n filter.negative(true);\n }\n}\n\n// Register the advanced adjustment filter\nexport default registerFilter({\n id: 'adjustment-advanced',\n name: 'Advanced Adjustment',\n category: 'adjust',\n description: 'Comprehensive image adjustments including brightness, contrast, saturation, hue, and more',\n \n // Create an instance of the ColorMatrixFilter with the provided parameters\n createFilter: (params) => {\n try {\n const normalizedParams = normalizeAdvancedAdjustmentParams((params ?? {}) as Record<string, unknown>);\n console.log('Creating Advanced Adjustment filter with params:', normalizedParams);\n \n // Create filter instance\n const filter = new ColorMatrixFilter();\n\n type AdvancedFilterWithUI = typeof filter & {\n _customParams?: AdvancedAdjustmentParams;\n updateUIParam?: (key: string, value: unknown) => void;\n };\n const filterWithUI = filter as AdvancedFilterWithUI;\n\n // Store custom parameters for later reference\n filterWithUI._customParams = { ...normalizedParams };\n\n // Apply initial adjustments from full parameter set.\n applyAdvancedAdjustments(filter, normalizedParams);\n \n // Add custom updateUIParam method for dynamic updates\n filterWithUI.updateUIParam = function updateUIParam(key: string, value: unknown): void {\n try {\n if (!isAdvancedAdjustmentParamKey(key)) {\n return;\n }\n\n const customParams = this._customParams ?? { ...DEFAULT_ADVANCED_ADJUSTMENT_PARAMS };\n if (key === 'negative') {\n customParams.negative = toBoolean(value, customParams.negative);\n } else {\n const numericKey = key as Exclude<AdvancedAdjustmentParamKey, 'negative'>;\n customParams[numericKey] = toFiniteNumber(value, customParams[numericKey]);\n }\n\n this._customParams = customParams;\n applyAdvancedAdjustments(this, customParams);\n } catch (error) {\n console.error(`Error updating Advanced Adjustment parameter ${key}:`, error);\n }\n };\n \n console.log('Advanced Adjustment filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create Advanced Adjustment filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n hue: 0,\n sepia: 0,\n negative: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1,\n },\n {\n id: 'contrast',\n type: 'slider',\n label: 'Contrast',\n property: 'contrast',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1,\n },\n {\n id: 'hue',\n type: 'slider',\n label: 'Hue Rotation',\n property: 'hue',\n min: 0,\n max: 360,\n step: 1,\n default: 0,\n },\n {\n id: 'sepia',\n type: 'slider',\n label: 'Sepia',\n property: 'sepia',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'negative',\n type: 'toggle',\n label: 'Negative',\n property: 'negative',\n default: false,\n },\n ],\n});\n","/**\n * Alpha Filter Definition\n * Controls image opacity using PIXI.AlphaFilter.\n *\n * NOTE: Previously used ColorMatrixFilter with an identity matrix, which\n * does not produce visible transparency — ColorMatrixFilter.alpha is a\n * blend ratio between filtered and unfiltered output, so with an identity\n * matrix every value produces identical output.\n */\nimport { registerFilter } from '../registry';\nimport * as PIXI from 'pixi.js';\n\nconst clamp01 = (n: number) => Math.max(0, Math.min(1, n));\n\nexport default registerFilter({\n id: 'alpha',\n name: 'Alpha',\n category: 'adjust',\n description: 'Adjust the opacity of the image',\n\n createFilter: (params) => {\n const alpha = clamp01(params.alpha !== undefined ? Number(params.alpha) : 1);\n\n // AlphaFilter genuinely controls display-object opacity. PIXI v8 accepts\n // either a number or an options object; pass the number directly so we\n // work on any minor version that's installed.\n const filter = new (PIXI as any).AlphaFilter(alpha);\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n if (key === 'alpha') {\n this.alpha = clamp01(Number(value));\n }\n };\n\n return filter;\n },\n\n defaultParams: {\n alpha: 1.0,\n },\n\n controls: [\n {\n id: 'alpha',\n type: 'slider',\n label: 'Opacity',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1.0,\n },\n ],\n});\n","/**\n * Blur Filter Definition\n * Applies a Gaussian blur effect to the image\n * \n * This implementation uses the proper BlurFilter from pixi.js\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import PIXI namespace\nimport * as PIXI from 'pixi.js';\n\n// Register the blur filter\nexport default registerFilter({\n id: 'blur',\n name: 'Blur',\n category: 'blur',\n description: 'Apply a smooth blur effect to the entire image',\n \n /**\n * Create an instance of the BlurFilter from pixi.js package\n * This implementation matches the PixiJS example exactly, using 'blur' and 'quality' parameters\n */\n createFilter: (params) => {\n try {\n console.log('Creating BlurFilter with params:', params);\n \n // Create filter with proper options object for v8\n const filter = new PIXI.BlurFilter({\n strength: params.blur || 8,\n quality: params.quality || 4\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'blur':\n this.strength = value; // PixiJS BlurFilter uses 'strength' internally\n console.log(`Updated blur to ${this.strength}`);\n break;\n \n case 'quality':\n this.quality = value;\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('BlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create BlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n blur: 8,\n quality: 4,\n },\n \n // UI controls for the filter - matching PixiJS example exactly\n controls: [\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur',\n property: 'blur',\n min: 0,\n max: 100,\n step: 0.1,\n default: 8,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n ],\n});","/**\n * Color Matrix Filter Definition\n *\n * Applies brightness/contrast/saturation/hue/sepia/negative via PIXI's\n * ColorMatrixFilter. These operations are method calls on the filter\n * instance (not writable properties) and are non-commutative: applying\n * brightness-then-hue produces a different matrix than hue-then-brightness.\n *\n * Every update rebuilds the matrix from reset() in a fixed order so the\n * output is deterministic regardless of which slider was moved last, and\n * so a slider update cannot corrupt the filter by accidentally overwriting\n * one of the methods.\n */\nimport * as PIXI from 'pixi.js';\nimport { registerFilter } from '../registry';\n\ninterface ColorMatrixParams {\n brightness: number;\n contrast: number;\n saturation: number;\n hue: number;\n sepia: boolean;\n negative: boolean;\n}\n\nfunction applyColorMatrixParams(\n filter: PIXI.ColorMatrixFilter,\n params: ColorMatrixParams,\n): void {\n if (typeof (filter as any).reset === 'function') {\n (filter as any).reset();\n }\n\n // Deterministic order — matrix ops don't commute.\n if (params.brightness !== 1) {\n filter.brightness(params.brightness, false);\n }\n if (params.contrast !== 1) {\n filter.contrast(params.contrast, false);\n }\n if (params.saturation !== 1) {\n filter.saturate(params.saturation, false);\n }\n if (params.hue !== 0) {\n filter.hue(params.hue, false);\n }\n if (params.sepia) {\n filter.sepia(false);\n }\n if (params.negative) {\n filter.negative(false);\n }\n}\n\nfunction normalizeParams(raw: Record<string, unknown>): ColorMatrixParams {\n return {\n brightness: Number(raw.brightness ?? 1),\n contrast: Number(raw.contrast ?? 1),\n saturation: Number(raw.saturation ?? 1),\n hue: Number(raw.hue ?? 0),\n sepia: Boolean(raw.sepia),\n negative: Boolean(raw.negative),\n };\n}\n\nexport default registerFilter({\n id: 'color-matrix',\n name: 'Color Matrix',\n category: 'advanced',\n description: 'Advanced color adjustments including sepia, hue rotation, and negative',\n\n createFilter: (params) => {\n const MatrixFilterClass = (PIXI as any).ColorMatrixFilter;\n if (!MatrixFilterClass) return null;\n\n const filter: PIXI.ColorMatrixFilter = new MatrixFilterClass();\n const normalized = normalizeParams(params);\n\n (filter as any)._customParams = { ...normalized };\n applyColorMatrixParams(filter, normalized);\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n const stored: ColorMatrixParams = (this as any)._customParams ?? normalizeParams({});\n\n switch (key) {\n case 'brightness':\n case 'contrast':\n case 'saturation':\n case 'hue':\n stored[key] = Number(value);\n break;\n case 'sepia':\n case 'negative':\n stored[key] = Boolean(value);\n break;\n default:\n return;\n }\n\n (this as any)._customParams = stored;\n applyColorMatrixParams(this, stored);\n };\n\n return filter;\n },\n\n defaultParams: {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n hue: 0,\n sepia: false,\n negative: false,\n },\n\n controls: [\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'contrast',\n type: 'slider',\n label: 'Contrast',\n property: 'contrast',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'hue',\n type: 'slider',\n label: 'Hue Rotation',\n property: 'hue',\n min: -180,\n max: 180,\n step: 1,\n default: 0,\n },\n // Sepia is a toggle in phase 1 — PIXI v8's ColorMatrixFilter.sepia()\n // doesn't accept a smooth intensity, so a slider here would be misleading.\n {\n id: 'sepia',\n type: 'toggle',\n label: 'Sepia',\n property: 'sepia',\n default: false,\n },\n {\n id: 'negative',\n type: 'toggle',\n label: 'Negative',\n property: 'negative',\n default: false,\n },\n ],\n});\n","/**\n * Color Overlay Filter Definition\n * Applies a colored overlay to the entire image\n * \n * This implementation uses the proper ColorOverlayFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access ColorOverlayFilter from the pixi-filters package\nconst { ColorOverlayFilter } = PixiFilters;\n\n// Register the color overlay filter\nexport default registerFilter({\n id: 'colorOverlay',\n name: 'Color Overlay',\n category: 'color',\n description: 'Apply a colored tint or overlay to the entire image',\n \n /**\n * Create an instance of ColorOverlayFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating ColorOverlayFilter with params:', params);\n \n // Parse color string to number if needed\n let colorValue = 0xff0000; // Default red\n if (params.color) {\n if (typeof params.color === 'string') {\n colorValue = parseInt(params.color.replace('#', '0x'), 16);\n } else if (typeof params.color === 'number') {\n colorValue = params.color;\n }\n }\n \n // Create filter with the ColorOverlayFilter from pixi-filters\n // Using the options object syntax for v6+\n console.log('Creating ColorOverlayFilter with options object:', {\n color: colorValue,\n alpha: params.alpha || 0.5\n });\n \n const filter = new ColorOverlayFilter({\n color: colorValue,\n alpha: params.alpha || 0.5\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n // IMPORTANT: Must update BOTH the JS property AND the shader uniform\n // The JS property is used for state tracking, but the shader uses uniforms for rendering\n switch (key) {\n case 'color':\n // Convert hex string to number for the color property\n let colorNum: number;\n if (typeof value === 'string') {\n colorNum = parseInt(value.replace('#', '0x'), 16);\n } else {\n colorNum = Number(value);\n }\n this.color = colorNum;\n if (this.uniforms) this.uniforms.uColor = colorNum;\n console.log(`Updated color to ${colorNum}`);\n break;\n\n case 'alpha':\n // Direct alpha update\n this.alpha = Number(value);\n if (this.uniforms) this.uniforms.uAlpha = Number(value);\n console.log(`Updated alpha to ${this.alpha}`);\n break;\n\n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ColorOverlayFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ColorOverlayFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n color: '#ff0000',\n alpha: 0.5,\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#ff0000',\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Opacity',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n ],\n});","/**\n * Drop Shadow Filter Definition\n * Applies a drop shadow effect to the image\n */\nimport { registerFilter } from '../registry';\nimport * as filters from 'pixi-filters';\n\n// Register the drop shadow filter\nexport default registerFilter({\n id: 'drop-shadow',\n name: 'Drop Shadow',\n category: 'effects',\n description: 'Add a soft drop shadow to the image',\n \n /**\n * Create an instance of the DropShadowFilter with the provided parameters\n * Using the official pixi-filters implementation\n */\n createFilter: (params) => {\n try {\n // Parse color from hex string\n const color = params.color ? params.color.replace('#', '0x') : '0x000000';\n\n // Create offset object based on distance and angle\n const distance = params.distance !== undefined ? params.distance : 5;\n const angle = params.angle !== undefined ? params.angle : 90;\n const blur = params.blur !== undefined ? params.blur : 2;\n const quality = params.quality !== undefined ? params.quality : 3;\n const offset = {\n x: distance * Math.cos(angle * Math.PI / 180),\n y: distance * Math.sin(angle * Math.PI / 180)\n };\n\n // Create the filter with the official pixi-filters package\n const filter = new filters.DropShadowFilter({\n offset: offset,\n color: parseInt(color, 16),\n alpha: params.alpha !== undefined ? params.alpha : 0.5,\n blur,\n quality,\n shadowOnly: params.shadowOnly !== undefined ? params.shadowOnly : false,\n pixelSize: {\n x: params.pixelSizeX !== undefined ? params.pixelSizeX : 1,\n y: params.pixelSizeY !== undefined ? params.pixelSizeY : 1\n }\n });\n\n // pixi-filters' DropShadowFilter does NOT set a .padding large enough\n // to contain its bleed (blur kernel + offset). Export needs to know the\n // actual reach so it can expand the render canvas. Compute it here and\n // expose it via _exportPadding so PixiRenderer.exportImage can read it.\n //\n // Rule of thumb: blur-kernel reach (blur * quality * 2) + offset magnitude\n // plus a small safety margin. This is the bleed from the SPRITE edge,\n // not the bleed radius around a single point.\n const computePadding = (b: number, q: number, offX: number, offY: number) => {\n const kernel = b * q * 2;\n const mag = Math.sqrt(offX * offX + offY * offY);\n return Math.ceil(kernel + mag + 2);\n };\n (filter as any)._exportPadding = computePadding(blur, quality, offset.x, offset.y);\n // Also set the built-in padding so PIXI's own bounds math doesn't clip\n // the preview at some inner boundary on certain configs.\n filter.padding = Math.max(filter.padding ?? 0, (filter as any)._exportPadding);\n\n // Store custom parameters for later reference\n (filter as any)._customParams = {\n ...params,\n // Also store the calculated offset for use in updateUIParam\n _offset: offset,\n _distance: distance,\n _angle: angle\n };\n\n /**\n * Build a fresh DropShadowFilter sized for export.\n *\n * The user tunes drop-shadow values while looking at the preview, where\n * the image is downscaled to fit the viewport. The same `distance=11`\n * that looks correct on a 600px-wide preview becomes microscopic on a\n * native-size 3224px export. This factory rebuilds the filter with\n * size-dependent params (distance, blur) multiplied by the\n * preview-to-native scale so the saved image visually matches the\n * preview at the user's intended apparent shadow size.\n *\n * Quality is unitless and stays as-is. Color, alpha, shadowOnly are\n * also intensity-only / boolean and don't scale.\n */\n const createScaledForExport = (rawParams: any, scale: number) => {\n const dist = Number(rawParams._distance ?? rawParams.distance ?? 5) * scale;\n const ang = Number(rawParams._angle ?? rawParams.angle ?? 90);\n const blr = Number(rawParams.blur ?? 2) * scale;\n const qual = Number(rawParams.quality ?? 3);\n const off = {\n x: dist * Math.cos(ang * Math.PI / 180),\n y: dist * Math.sin(ang * Math.PI / 180),\n };\n const colorStr = rawParams.color\n ? String(rawParams.color).replace('#', '0x')\n : '0x000000';\n\n const next = new filters.DropShadowFilter({\n offset: off,\n color: parseInt(colorStr, 16),\n alpha: rawParams.alpha !== undefined ? Number(rawParams.alpha) : 0.5,\n blur: blr,\n quality: qual,\n shadowOnly: rawParams.shadowOnly !== undefined ? Boolean(rawParams.shadowOnly) : false,\n pixelSize: {\n x: rawParams.pixelSizeX !== undefined ? Number(rawParams.pixelSizeX) : 1,\n y: rawParams.pixelSizeY !== undefined ? Number(rawParams.pixelSizeY) : 1,\n },\n });\n\n const padding = computePadding(blr, qual, off.x, off.y);\n (next as any)._exportPadding = padding;\n next.padding = Math.max(next.padding ?? 0, padding);\n return next;\n };\n\n /**\n * Hook used by PixiRenderer.exportImage(). Returns a fresh filter\n * instance with size params scaled to native pixels — never mutates\n * the live preview filter.\n */\n (filter as any).createExportFilter = function (options: { previewToNativeScale?: number } = {}) {\n const scale = Number.isFinite(options.previewToNativeScale)\n ? Math.max(1, Number(options.previewToNativeScale))\n : 1;\n const stored = (this as any)._customParams || params;\n return createScaledForExport(stored, scale);\n };\n\n /** Conservative export-time bleed for the renderer to reserve. */\n (filter as any).getExportPadding = function () {\n return Number((this as any)._exportPadding || this.padding || 0);\n };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n */\n const refreshPadding = (f: any) => {\n const off = f._customParams?._offset ?? { x: 0, y: 0 };\n const b = Number(f.blur ?? 0);\n const q = Number(f.quality ?? 1);\n const p = computePadding(b, q, off.x, off.y);\n f._exportPadding = p;\n f.padding = Math.max(f.padding ?? 0, p);\n };\n\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n\n switch (key) {\n case 'color':\n if (typeof value === 'string') {\n this.color = parseInt(value.replace('#', '0x'), 16);\n }\n break;\n\n case 'alpha':\n this.alpha = Number(value);\n break;\n\n case 'blur':\n this.blur = Number(value);\n refreshPadding(this);\n break;\n\n case 'quality':\n this.quality = Number(value);\n refreshPadding(this);\n break;\n\n case 'shadowOnly':\n this.shadowOnly = Boolean(value);\n break;\n\n case 'pixelSizeX':\n this.pixelSizeX = Number(value);\n customParams.pixelSizeX = Number(value);\n break;\n\n case 'pixelSizeY':\n this.pixelSizeY = Number(value);\n customParams.pixelSizeY = Number(value);\n break;\n\n case 'distance':\n case 'angle': {\n if (key === 'distance') {\n customParams._distance = Number(value);\n customParams.distance = Number(value);\n } else {\n customParams._angle = Number(value);\n customParams.angle = Number(value);\n }\n const newOffset = {\n x: customParams._distance * Math.cos(customParams._angle * Math.PI / 180),\n y: customParams._distance * Math.sin(customParams._angle * Math.PI / 180),\n };\n customParams._offset = newOffset;\n this.offset = newOffset;\n refreshPadding(this);\n break;\n }\n\n default:\n if (key in this) {\n this[key] = value;\n }\n break;\n }\n\n return true;\n } catch {\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n return false;\n }\n };\n\n return filter;\n } catch (error) {\n console.error('Failed to create Drop Shadow filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n alpha: 0.5,\n blur: 2,\n color: '#000000',\n distance: 5,\n angle: 90,\n quality: 3,\n shadowOnly: false,\n pixelSizeX: 1,\n pixelSizeY: 1\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'alpha',\n type: 'slider',\n label: 'Opacity',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur',\n property: 'blur',\n min: 0,\n max: 20,\n step: 0.1,\n default: 2,\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#000000',\n },\n {\n id: 'distance',\n type: 'slider',\n label: 'Distance',\n property: 'distance',\n min: 0,\n max: 50,\n step: 1,\n default: 5,\n },\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: 0,\n max: 360,\n step: 1,\n default: 90,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 0,\n max: 20,\n step: 1,\n default: 3,\n },\n {\n id: 'shadowOnly',\n type: 'toggle',\n label: 'Shadow Only',\n property: 'shadowOnly',\n default: false,\n },\n {\n id: 'pixelSizeX',\n type: 'slider',\n label: 'Pixel Size X',\n property: 'pixelSizeX',\n min: 0.5,\n max: 8,\n step: 0.5,\n default: 1,\n },\n {\n id: 'pixelSizeY',\n type: 'slider',\n label: 'Pixel Size Y',\n property: 'pixelSizeY',\n min: 0.5,\n max: 8,\n step: 0.5,\n default: 1,\n }\n ],\n});","/**\n * Grayscale Filter Definition\n * Converts image to grayscale with customizable intensity\n * \n * This implementation uses the ColorMatrixFilter from pixi.js\n * to provide a grayscale effect with adjustable intensity.\n */\nimport { registerFilter } from '../registry';\n// Import from pixi.js with namespace\nimport * as PIXI from 'pixi.js';\n// @ts-ignore - Module structure doesn't match TypeScript definitions\nconst { ColorMatrixFilter } = PIXI;;\n\n// Register the grayscale filter\nexport default registerFilter({\n id: 'grayscale',\n name: 'Grayscale',\n category: 'color',\n description: 'Convert the image to black and white with adjustable intensity',\n \n /**\n * Create a ColorMatrixFilter instance configured for grayscale effect with adjustable intensity\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating grayscale filter with params:', params);\n \n // Create a new ColorMatrixFilter\n const filter = new ColorMatrixFilter();\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n // Apply the initial grayscale effect based on intensity\n const intensity = params.intensity !== undefined ? params.intensity : 1.0;\n applyGrayscaleEffect(filter as any, intensity);\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This follows the same pattern as ColorOverlayFilter and ColorGradientFilter\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'intensity':\n // Apply grayscale effect with the new intensity\n applyGrayscaleEffect(this, value);\n console.log(`Updated grayscale intensity to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('Grayscale filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create grayscale filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n intensity: 0.35,\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'intensity',\n type: 'slider',\n label: 'Intensity',\n property: 'intensity',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.35,\n },\n ],\n});\n\n/**\n * Helper function to apply grayscale effect with a specific intensity\n * @param filter The ColorMatrixFilter instance\n * @param intensity The intensity of the grayscale effect (0-1)\n */\nfunction applyGrayscaleEffect(filter: any, intensity: number): void {\n // Reset the matrix to identity (no effect)\n filter.reset();\n\n // Apply grayscale with the specified intensity\n // The greyscale method takes a single parameter for intensity (0-1)\n filter.greyscale(intensity);\n}","/**\n * HSL Adjustment Filter Definition\n * Adjusts hue, saturation, and lightness with fine control\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { HslAdjustmentFilter } = PixiFilters;;\n\n// Register the HSL adjustment filter\nexport default registerFilter({\n id: 'hsl-adjustment',\n name: 'HSL Adjustment',\n category: 'color',\n description: 'Control hue, saturation, and lightness independently',\n \n /**\n * Create an instance of the HslAdjustmentFilter with the provided parameters\n * Using the official pixi-filters implementation instead of a custom one\n */\n createFilter: (params) => {\n try {\n console.log('Creating HSL Adjustment filter with params:', params);\n \n // Create a new HslAdjustmentFilter instance from the pixi-filters package\n const filter = new HslAdjustmentFilter({\n hue: params.hue !== undefined ? params.hue : 0,\n saturation: params.saturation !== undefined ? params.saturation : 0,\n lightness: params.lightness !== undefined ? params.lightness : 0, \n colorize: params.colorize !== undefined ? params.colorize : false,\n alpha: params.alpha !== undefined ? params.alpha : 1.0\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n // IMPORTANT: Must update BOTH the JS property AND the shader uniform\n // The JS property is used for state tracking, but the shader uses uniforms for rendering\n switch (key) {\n case 'hue':\n // The filter handles the degrees to radians conversion internally\n this.hue = Number(value);\n if (this.uniforms) this.uniforms.uHue = Number(value);\n console.log(`Updated hue to ${value}`);\n break;\n\n case 'saturation':\n this.saturation = Number(value);\n if (this.uniforms) this.uniforms.uSaturation = Number(value);\n console.log(`Updated saturation to ${value}`);\n break;\n\n case 'lightness':\n this.lightness = Number(value);\n if (this.uniforms) this.uniforms.uLightness = Number(value);\n console.log(`Updated lightness to ${value}`);\n break;\n\n case 'colorize':\n this.colorize = Boolean(value);\n if (this.uniforms) this.uniforms.uColorize = value ? 1 : 0;\n console.log(`Updated colorize to ${value}`);\n break;\n\n case 'alpha':\n this.alpha = Number(value);\n if (this.uniforms) this.uniforms.uAlpha = Number(value);\n console.log(`Updated alpha to ${value}`);\n break;\n\n // For any other properties, try direct assignment\n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n } catch (error) {\n console.error(`Failed to update parameter ${key} using updateUIParam:`, error);\n \n // Still store the value in customParams even if setting it failed\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n \n return false;\n }\n };\n \n console.log('HSL Adjustment filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create HSL Adjustment filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n hue: 0,\n saturation: 0,\n lightness: 0,\n colorize: false,\n alpha: 1.0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'hue',\n type: 'slider',\n label: 'Hue',\n property: 'hue',\n min: -180,\n max: 180,\n step: 1,\n default: 0,\n },\n {\n id: 'saturation',\n type: 'slider',\n label: 'Saturation',\n property: 'saturation',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'lightness',\n type: 'slider',\n label: 'Lightness',\n property: 'lightness',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'colorize',\n type: 'toggle',\n label: 'Colorize',\n property: 'colorize',\n default: false,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1.0,\n },\n ],\n});","/**\n * Kawase Blur Filter Definition\n * A much faster blur than Gaussian blur, with similar quality\n * \n * This implementation uses the proper KawaseBlurFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import KawaseBlurFilter directly from pixi-filters\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { KawaseBlurFilter } = PixiFilters;;\n\n// Register the kawase blur filter\nexport default registerFilter({\n id: 'kawase-blur',\n name: 'Kawase Blur',\n category: 'blur',\n description: 'A more optimized blur algorithm that is faster than standard blur',\n \n /**\n * Create an instance of the KawaseBlurFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating KawaseBlurFilter with params:', params);\n \n // Create filter with proper options object for v6+\n const filter = new KawaseBlurFilter({\n strength: params.strength || 4,\n quality: params.quality || 3,\n clamp: params.clamp || false,\n pixelSize: params.pixelSize || 1\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'strength':\n this.strength = value;\n console.log(`Updated strength to ${this.strength}`);\n break;\n \n case 'quality':\n this.quality = value;\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'clamp':\n this.clamp = value;\n console.log(`Updated clamp to ${this.clamp}`);\n break;\n \n case 'pixelSize':\n // pixelSize can be set as a single number or as an object with x and y\n if (typeof value === 'number') {\n this.pixelSize = value;\n } else if (typeof value === 'object' && value !== null) {\n if ('x' in value && 'y' in value) {\n this.pixelSize = value;\n }\n }\n console.log(`Updated pixelSize to ${JSON.stringify(this.pixelSize)}`);\n break;\n\n case 'pixelSizeX':\n this.pixelSizeX = value;\n console.log(`Updated pixelSizeX to ${this.pixelSizeX}`);\n break;\n \n case 'pixelSizeY':\n this.pixelSizeY = value;\n console.log(`Updated pixelSizeY to ${this.pixelSizeY}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('KawaseBlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create KawaseBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strength: 4,\n quality: 3,\n clamp: false,\n pixelSize: 1\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 20,\n step: 0.1,\n default: 4,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 20,\n step: 1,\n default: 3,\n },\n {\n id: 'clamp',\n type: 'toggle',\n label: 'Clamp Edges',\n property: 'clamp',\n default: false,\n },\n {\n id: 'pixelSize',\n type: 'slider',\n label: 'Pixel Size',\n property: 'pixelSize',\n min: 0.5,\n max: 10,\n step: 0.5,\n default: 1,\n },\n {\n id: 'pixelSizeX',\n type: 'slider',\n label: 'Pixel Size X',\n property: 'pixelSizeX',\n min: 0,\n max: 10,\n step: 0.1,\n default: 1,\n },\n {\n id: 'pixelSizeY',\n type: 'slider',\n label: 'Pixel Size Y',\n property: 'pixelSizeY',\n min: 0,\n max: 10,\n step: 0.1,\n default: 1,\n },\n ],\n});","/**\n * Motion Blur Filter Definition\n * Applies a directional motion blur effect to the image\n * \n * This implementation uses the proper MotionBlurFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import MotionBlurFilter directly from pixi-filters\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { MotionBlurFilter } = PixiFilters;;\n\n// Register the motion blur filter\nexport default registerFilter({\n id: 'motion-blur',\n name: 'Motion Blur',\n category: 'blur',\n description: 'Creates a directional blur effect simulating motion',\n \n /**\n * Create an instance of the MotionBlurFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating MotionBlurFilter with params:', params);\n \n // Create filter with proper options object for v6+\n const filter = new MotionBlurFilter({\n velocity: { \n x: params.velocityX !== undefined ? params.velocityX : 0, \n y: params.velocityY !== undefined ? params.velocityY : 0 \n },\n kernelSize: params.kernelSize || 5,\n offset: params.offset !== undefined ? params.offset : 0\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'velocityX':\n // Update just the X component of the velocity\n this.velocityX = value;\n console.log(`Updated velocityX to ${this.velocityX}`);\n break;\n \n case 'velocityY':\n // Update just the Y component of the velocity\n this.velocityY = value;\n console.log(`Updated velocityY to ${this.velocityY}`);\n break;\n \n case 'kernelSize':\n this.kernelSize = value;\n console.log(`Updated kernelSize to ${this.kernelSize}`);\n break;\n \n case 'offset':\n this.offset = value;\n console.log(`Updated offset to ${this.offset}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('MotionBlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create MotionBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n velocityX: 0,\n velocityY: 0,\n kernelSize: 5,\n offset: 0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'velocityX',\n type: 'slider',\n label: 'Velocity X',\n property: 'velocityX',\n min: -90,\n max: 90,\n step: 1,\n default: 0,\n },\n {\n id: 'velocityY',\n type: 'slider',\n label: 'Velocity Y',\n property: 'velocityY',\n min: -90,\n max: 90,\n step: 1,\n default: 0,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '3', value: 3 },\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 },\n { label: '17', value: 17 },\n { label: '19', value: 19 },\n { label: '21', value: 21 },\n { label: '23', value: 23 },\n { label: '25', value: 25 },\n ],\n default: 5,\n },\n {\n id: 'offset',\n type: 'slider',\n label: 'Offset',\n property: 'offset',\n min: -150,\n max: 150,\n step: 1,\n default: 0,\n },\n ],\n});","/**\n * Radial Blur Filter Definition\n * Applies a radial motion blur effect that emanates from a center point\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { RadialBlurFilter } = PixiFilters;;\n\n// Register the radial blur filter\nexport default registerFilter({\n id: 'radial-blur',\n name: 'Radial Blur',\n category: 'blur',\n description: 'Creates a circular blur effect emanating from a center point',\n \n // Create an instance of the RadialBlurFilter with the provided parameters\n createFilter: (params) => {\n try {\n // Create filter with options object\n const filter = new RadialBlurFilter({\n angle: params.angle ?? 20,\n center: { x: params.centerX ?? 0, y: params.centerY ?? 0 },\n kernelSize: params.kernelSize ?? 15,\n radius: params.radius ?? 300\n });\n\n // Store custom params for reference\n (filter as any)._customParams = {\n centerX: params.centerX ?? 0,\n centerY: params.centerY ?? 0\n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n switch (key) {\n case 'angle':\n this.angle = Number(value);\n break;\n case 'centerX':\n (this as any)._customParams.centerX = Number(value);\n this.center = { \n x: Number(value), \n y: (this as any)._customParams.centerY \n };\n break;\n case 'centerY':\n (this as any)._customParams.centerY = Number(value);\n this.center = { \n x: (this as any)._customParams.centerX, \n y: Number(value) \n };\n break;\n case 'kernelSize':\n this.kernelSize = Number(value);\n break;\n case 'radius':\n this.radius = Number(value);\n break;\n default:\n console.warn(`Unknown parameter for RadialBlurFilter: ${key}`);\n }\n } catch (error) {\n console.error(`Error updating RadialBlurFilter parameter ${key}:`, error);\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create RadialBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n angle: 20,\n centerX: 0,\n centerY: 0,\n kernelSize: 15,\n radius: 300\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: -180,\n max: 180,\n step: 1,\n default: 20,\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '3', value: 3 },\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 },\n { label: '17', value: 17 },\n { label: '19', value: 19 },\n { label: '21', value: 21 },\n { label: '23', value: 23 },\n { label: '25', value: 25 },\n ],\n default: 15,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: -1,\n max: 1000,\n step: 10,\n default: 300,\n },\n ],\n});","/**\n * Tilt Shift Filter Definition\n * Creates a depth-of-field effect like a miniature model\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { TiltShiftFilter } = PixiFilters;\n\n// Register the tilt shift filter\nexport default registerFilter({\n id: 'tilt-shift',\n name: 'Tilt Shift',\n category: 'blur',\n description: 'Creates a depth-of-field effect simulating miniature photography',\n \n // Create an instance of the TiltShiftFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating TiltShiftFilter with params:', params);\n \n // Ensure parameters have default values if missing\n const blur = typeof params.blur === 'number' ? params.blur : 100;\n const gradientBlur = typeof params.gradientBlur === 'number' ? params.gradientBlur : 600;\n const startX = typeof params.startX === 'number' ? params.startX : 0;\n const startY = typeof params.startY === 'number' ? params.startY : 0.5;\n const endX = typeof params.endX === 'number' ? params.endX : 1;\n const endY = typeof params.endY === 'number' ? params.endY : 0.5;\n \n // Create the filter with proper options\n const filter = new TiltShiftFilter({\n blur: Number(blur),\n gradientBlur: Number(gradientBlur),\n start: { x: Number(startX), y: Number(startY) },\n end: { x: Number(endX), y: Number(endY) }\n });\n \n // Log the actual filter object to see its properties\n console.log('Created TiltShiftFilter instance with properties:', {\n blur: filter.blur,\n gradientBlur: filter.gradientBlur,\n start: filter.start,\n end: filter.end\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n blur: blur,\n gradientBlur: gradientBlur,\n startX: startX,\n startY: startY,\n endX: endX,\n endY: endY\n };\n \n // Add updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`TiltShiftFilter.updateUIParam called: ${key} = ${value}`);\n \n // Force numeric conversion\n const numValue = Number(value);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = numValue;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'blur':\n this.blur = numValue;\n console.log(`Updated blur to ${this.blur}`);\n break;\n \n case 'gradientBlur':\n this.gradientBlur = numValue;\n console.log(`Updated gradientBlur to ${this.gradientBlur}`);\n break;\n \n case 'startX':\n if (this.start && typeof this.start === 'object') {\n this.start.x = numValue;\n console.log(`Updated startX to ${numValue}`, this.start);\n }\n break;\n \n case 'startY':\n if (this.start && typeof this.start === 'object') {\n this.start.y = numValue;\n console.log(`Updated startY to ${numValue}`, this.start);\n }\n break;\n \n case 'endX':\n if (this.end && typeof this.end === 'object') {\n this.end.x = numValue;\n console.log(`Updated endX to ${numValue}`, this.end);\n }\n break;\n \n case 'endY':\n if (this.end && typeof this.end === 'object') {\n this.end.y = numValue;\n console.log(`Updated endY to ${numValue}`, this.end);\n }\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = numValue;\n console.log(`Updated ${key} to ${numValue}`);\n } else {\n console.warn(`Unknown parameter for TiltShiftFilter: ${key}`);\n }\n break;\n }\n \n // Log the current state after updates\n console.log('TiltShiftFilter state after update:', {\n blur: this.blur,\n gradientBlur: this.gradientBlur,\n start: this.start,\n end: this.end\n });\n } catch (error) {\n console.error(`Error updating TiltShiftFilter parameter ${key}:`, error);\n }\n };\n \n console.log('TiltShiftFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create TiltShiftFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n blur: 100,\n gradientBlur: 600,\n startX: 0,\n startY: 0.5,\n endX: 1,\n endY: 0.5\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur Strength',\n property: 'blur',\n min: 0,\n max: 200,\n step: 1,\n default: 100,\n },\n {\n id: 'gradientBlur',\n type: 'slider',\n label: 'Gradient Width',\n property: 'gradientBlur',\n min: 0,\n max: 1000,\n step: 10,\n default: 600,\n },\n {\n id: 'startX',\n type: 'slider',\n label: 'Start X',\n property: 'startX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'startY',\n type: 'slider',\n label: 'Start Y',\n property: 'startY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'endX',\n type: 'slider',\n label: 'End X',\n property: 'endX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'endY',\n type: 'slider',\n label: 'End Y',\n property: 'endY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n ],\n});","/**\n * Zoom Blur Filter Definition\n * Creates a radial blur that simulates a camera zoom effect\n * \n * This implementation uses the proper ZoomBlurFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import ZoomBlurFilter directly from pixi-filters\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { ZoomBlurFilter } = PixiFilters;;\n\n// Register the zoom blur filter\nexport default registerFilter({\n id: 'zoom-blur',\n name: 'Zoom Blur',\n category: 'blur',\n description: 'Creates a zoom blur effect from a center point',\n \n /**\n * Create an instance of the ZoomBlurFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating ZoomBlurFilter with params:', params);\n \n // Create filter with proper options object for v6+\n const filter = new ZoomBlurFilter({\n strength: params.strength || 0.1,\n center: { \n x: params.centerX !== undefined ? params.centerX : 0.5, \n y: params.centerY !== undefined ? params.centerY : 0.5 \n },\n innerRadius: params.innerRadius || 80,\n radius: params.radius !== undefined ? params.radius : -1,\n maxKernelSize: params.maxKernelSize || 32\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'strength':\n this.strength = value;\n console.log(`Updated strength to ${this.strength}`);\n break;\n \n case 'centerX':\n // Update just the X component of the center point\n this.centerX = value;\n console.log(`Updated centerX to ${this.centerX}`);\n break;\n \n case 'centerY':\n // Update just the Y component of the center point\n this.centerY = value;\n console.log(`Updated centerY to ${this.centerY}`);\n break;\n \n case 'innerRadius':\n this.innerRadius = value;\n console.log(`Updated innerRadius to ${this.innerRadius}`);\n break;\n \n case 'radius':\n this.radius = value;\n console.log(`Updated radius to ${this.radius}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ZoomBlurFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ZoomBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strength: 0.1,\n centerX: 0.5,\n centerY: 0.5,\n innerRadius: 80,\n radius: -1,\n maxKernelSize: 32\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 0.5,\n step: 0.01,\n default: 0.1,\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'innerRadius',\n type: 'slider',\n label: 'Inner Radius',\n property: 'innerRadius',\n min: 0,\n max: 1000,\n step: 1,\n default: 80,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Outer Radius',\n property: 'radius',\n min: -1,\n max: 1000,\n step: 10,\n default: -1,\n },\n {\n id: 'maxKernelSize',\n type: 'select',\n label: 'Quality',\n property: 'maxKernelSize',\n options: [\n { label: 'Low', value: 16 },\n { label: 'Medium', value: 32 },\n { label: 'High', value: 48 },\n { label: 'Very High', value: 64 },\n ],\n default: 32,\n },\n ],\n});","/**\n * Color Gradient Filter Definition\n *\n * Applies a linear/radial/conic gradient via pixi-filters' ColorGradientFilter.\n * Supports unlimited color stops with per-stop color/offset/alpha editing,\n * add/remove stop commands, and CSS gradient string parsing.\n *\n * The filter instance exposes:\n * getSerializableParams() - canonical state snapshot for FilterManager sync\n * getDynamicControls() - per-stop control rows for FilterAdjustments UI\n * updateUIParam(key,val) - mutation entry point (static + dynamic + actions)\n * handleButtonAction(act) - thin wrapper for add/remove stop commands\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n\nconst { ColorGradientFilter } = PixiFilters as any;\n\ntype HexString = `#${string}`;\n\ninterface ColorStopNum {\n offset: number;\n color: number; // integer RGB\n alpha: number;\n}\n\ninterface ColorStopHex {\n offset: number;\n color: HexString;\n alpha: number;\n}\n\ninterface SerializedParams {\n gradientType: number;\n colorStops: ColorStopHex[];\n angle: number;\n alpha: number;\n maxColors: number;\n replace: boolean;\n cssGradient: string;\n}\n\nfunction hexToInt(hex: string): number {\n return parseInt(hex.replace('#', '0x'), 16);\n}\n\nfunction intToHex(num: number): HexString {\n return ('#' + num.toString(16).padStart(6, '0')) as HexString;\n}\n\nfunction normalizeStopForFilter(stop: { offset: number; color: string | number; alpha: number }): ColorStopNum {\n return {\n offset: Number(stop.offset),\n color: typeof stop.color === 'string' ? hexToInt(stop.color) : Number(stop.color),\n alpha: Number(stop.alpha),\n };\n}\n\nfunction hexStopFromFilter(stop: { offset: number; color: number | string; alpha: number }): ColorStopHex {\n return {\n offset: stop.offset,\n color: typeof stop.color === 'number' ? intToHex(stop.color) : (stop.color as HexString),\n alpha: stop.alpha,\n };\n}\n\nexport default registerFilter({\n id: 'color-gradient',\n name: 'Color Gradient',\n category: 'color',\n description: 'Applies a linear, radial or conic color gradient over the image with multiple color stops',\n\n createFilter: (params) => {\n const incomingStops = (params.colorStops as any[]) || [\n { offset: 0, color: '#ff0000', alpha: 1 },\n { offset: 1, color: '#0000ff', alpha: 1 },\n ];\n\n let stops: ColorStopNum[] = incomingStops.map(normalizeStopForFilter);\n if (stops.length < 2) {\n stops = [\n { offset: 0, color: 0xff0000, alpha: 1 },\n { offset: 1, color: 0x0000ff, alpha: 1 },\n ];\n }\n // Sort on creation — the UI layer avoids re-sorting during a drag.\n stops.sort((a, b) => a.offset - b.offset);\n\n const filter = new ColorGradientFilter({\n type: params.gradientType,\n stops,\n angle: params.angle,\n alpha: params.alpha,\n maxColors: params.maxColors || 0,\n replace: params.replace,\n });\n\n (filter as any)._customParams = {\n cssGradient: params.cssGradient || '',\n };\n\n /**\n * Canonical snapshot for persistence + recreation.\n */\n (filter as any).getSerializableParams = function (): SerializedParams {\n const stopsHex: ColorStopHex[] = Array.isArray(this.stops)\n ? this.stops.map(hexStopFromFilter)\n : [];\n\n return {\n gradientType: this.type,\n colorStops: stopsHex,\n angle: this.angle,\n alpha: this.alpha,\n maxColors: this.maxColors,\n replace: this.replace,\n cssGradient: this._customParams?.cssGradient ?? '',\n };\n };\n\n /**\n * Color stops formatted for UI consumption.\n */\n (filter as any).getColorStopsForUI = function (): ColorStopHex[] {\n if (!Array.isArray(this.stops)) return [];\n return this.stops.map(hexStopFromFilter);\n };\n\n /**\n * Generate one control row per color stop (color, offset, alpha).\n * Called by FilterAdjustments after rendering static controls.\n */\n (filter as any).getDynamicControls = function () {\n const colorStops: ColorStopHex[] = this.getColorStopsForUI();\n\n const controls: Array<{\n id: string;\n type: string;\n label: string;\n property: string;\n default: unknown;\n min?: number;\n max?: number;\n step?: number;\n }> = [];\n\n colorStops.forEach((stop, index) => {\n controls.push({\n id: `colorStop-${index}-color`,\n type: 'color',\n label: `Stop ${index + 1} Color`,\n property: `colorStops[${index}].color`,\n default: stop.color,\n });\n\n controls.push({\n id: `colorStop-${index}-offset`,\n type: 'slider',\n label: `Stop ${index + 1} Position`,\n property: `colorStops[${index}].offset`,\n min: 0,\n max: 1,\n step: 0.01,\n default: stop.offset,\n });\n\n controls.push({\n id: `colorStop-${index}-alpha`,\n type: 'slider',\n label: `Stop ${index + 1} Alpha`,\n property: `colorStops[${index}].alpha`,\n min: 0,\n max: 1,\n step: 0.01,\n default: stop.alpha,\n });\n });\n\n return controls;\n };\n\n /**\n * Thin wrapper so the UI can dispatch named actions without knowing\n * that they're routed through updateUIParam.\n */\n (filter as any).handleButtonAction = function (action: string) {\n if (action === 'addColorStop' || action === 'removeColorStop') {\n this.updateUIParam(action, true);\n }\n };\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n const customParams = (this as any)._customParams ?? {};\n (this as any)._customParams = customParams;\n\n switch (key) {\n case 'gradientType':\n this.type = Number(value);\n return;\n\n case 'angle':\n case 'alpha':\n case 'maxColors':\n this[key] = Number(value);\n return;\n\n case 'replace':\n this.replace = Boolean(value);\n return;\n\n case 'addColorStop': {\n const current: ColorStopNum[] = Array.isArray(this.stops) ? [...this.stops] : [];\n const randomColor =\n (Math.floor(Math.random() * 255) << 16) |\n (Math.floor(Math.random() * 255) << 8) |\n Math.floor(Math.random() * 255);\n\n // Rescale existing stops so the new one fits at the tail.\n if (current.length > 0) {\n const scale = 0.8;\n for (const stop of current) {\n stop.offset *= scale;\n }\n }\n current.push({ offset: 1.0, color: randomColor, alpha: 1.0 });\n current.sort((a, b) => a.offset - b.offset);\n this.stops = current;\n return;\n }\n\n case 'removeColorStop': {\n const current: ColorStopNum[] = Array.isArray(this.stops) ? [...this.stops] : [];\n if (current.length > 2) {\n current.pop();\n this.stops = current;\n }\n return;\n }\n\n case 'cssGradient': {\n const str = typeof value === 'string' ? value.trim() : '';\n customParams.cssGradient = str;\n if (!str) return;\n try {\n const parsed = new ColorGradientFilter({ css: str });\n this.type = parsed.type;\n this.angle = parsed.angle;\n this.stops = [...parsed.stops];\n } catch {\n // Silently ignore invalid CSS gradient strings —\n // the user can fix the input and retry.\n }\n return;\n }\n\n case 'colorStops': {\n if (!Array.isArray(value)) return;\n const normalized = (value as any[]).map(normalizeStopForFilter);\n normalized.sort((a, b) => a.offset - b.offset);\n this.stops = normalized;\n return;\n }\n\n default: {\n const dynamicMatch = /^colorStops\\[(\\d+)\\]\\.(offset|color|alpha)$/.exec(key);\n if (dynamicMatch) {\n const [, indexStr, prop] = dynamicMatch;\n const index = Number(indexStr);\n const stops: ColorStopNum[] = Array.isArray(this.stops) ? [...this.stops] : [];\n if (index < 0 || index >= stops.length) return;\n\n if (prop === 'color') {\n stops[index].color =\n typeof value === 'string' ? hexToInt(value) : Number(value);\n } else if (prop === 'offset' || prop === 'alpha') {\n stops[index][prop] = Number(value);\n }\n // IMPORTANT: do NOT sort during offset drag — would re-index\n // controls mid-interaction and swap the row the user is dragging.\n // The UI re-renders after pointer up.\n this.stops = stops;\n }\n }\n }\n };\n\n return filter;\n },\n\n defaultParams: {\n gradientType: 0,\n colorStops: [\n { offset: 0, color: '#ff0000', alpha: 1 },\n { offset: 1, color: '#0000ff', alpha: 1 },\n ],\n cssGradient: '',\n angle: 90,\n alpha: 0.75,\n maxColors: 0,\n replace: false,\n },\n\n controls: [\n {\n id: 'gradientType',\n type: 'select',\n label: 'Gradient Type',\n property: 'gradientType',\n options: [\n { label: 'Linear', value: 0 },\n { label: 'Radial', value: 1 },\n { label: 'Conic', value: 2 },\n ],\n default: 0,\n },\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: 0,\n max: 360,\n step: 1,\n default: 90,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Overall Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.75,\n },\n {\n id: 'maxColors',\n type: 'slider',\n label: 'Max Colors',\n property: 'maxColors',\n min: 0,\n max: 24,\n step: 1,\n default: 0,\n },\n {\n id: 'replace',\n type: 'toggle',\n label: 'Replace Original Colors',\n property: 'replace',\n default: false,\n },\n {\n id: 'addColorStop',\n type: 'button',\n label: 'Add New Color Stop',\n action: 'addColorStop',\n },\n {\n id: 'removeColorStop',\n type: 'button',\n label: 'Remove Last Color Stop',\n action: 'removeColorStop',\n },\n {\n id: 'cssGradient',\n type: 'text',\n label: 'CSS Gradient',\n property: 'cssGradient',\n default: '',\n placeholder: 'e.g. linear-gradient(to right, red, blue)',\n },\n ],\n});\n","/**\n * Color Map Filter Definition\n * Applies a color transformation based on a reference texture\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\nimport * as PIXI from 'pixi.js';\n\n// Register the Color Map filter\nexport default registerFilter({\n id: 'color-map',\n name: 'Color Map',\n category: 'color',\n description: 'Maps colors using a reference texture as a lookup table',\n \n // Create an instance of the ColorMapFilter with the provided parameters\n createFilter: (params) => {\n try {\n // Access filter class via direct indexing with type casting to avoid TypeScript errors \n // @ts-ignore - Runtime access of property that TypeScript doesn't know about\n const ColorMapFilterClass = PixiFilters['ColorMapFilter'];\n \n if (!ColorMapFilterClass) {\n console.error('ColorMapFilter not found in pixi-filters package');\n return null;\n }\n \n console.log('Creating ColorMapFilter with params:', params);\n \n // Get the color map texture\n let colorMapTexture = null;\n \n // If texture path is provided, create a new texture\n if (params.texturePath) {\n colorMapTexture = PIXI.Texture.from(params.texturePath);\n } else {\n // Use a default colormap texture\n // This is just a fallback - ideally user should provide their own\n colorMapTexture = PIXI.Texture.from('/examples/filters-main/examples/images/colormap.png');\n }\n \n // Create filter with proper options object\n const filter = new ColorMapFilterClass({\n colorMap: colorMapTexture,\n nearest: params.nearest,\n mix: params.mix\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'texturePath':\n // Update the color map texture\n if (value) {\n this.colorMap = PIXI.Texture.from(value);\n console.log(`Updated colorMap texture to ${value}`);\n }\n break;\n \n case 'mix':\n // Direct mix update\n this.mix = value;\n console.log(`Updated mix to ${this.mix}`);\n break;\n \n case 'nearest':\n // Direct nearest update\n this.nearest = value;\n console.log(`Updated nearest to ${this.nearest}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ColorMapFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ColorMapFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n texturePath: '', // User should provide a texture path\n mix: 1, // Mix between original and mapped colors (0-1)\n nearest: false // Whether to use nearest-neighbor sampling for the texture\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'texturePath',\n type: 'select',\n label: 'Color Map',\n property: 'texturePath',\n options: [\n { label: 'Default', value: '/examples/filters-main/examples/images/colormap.png' },\n { label: 'Grayscale', value: '/examples/filters-main/examples/images/colormap-grayscale.png' },\n { label: 'Sepia', value: '/examples/filters-main/examples/images/colormap-sepia.png' },\n // Add more options as needed\n ],\n default: '/examples/filters-main/examples/images/colormap.png',\n },\n {\n id: 'mix',\n type: 'slider',\n label: 'Mix',\n property: 'mix',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'nearest',\n type: 'toggle',\n label: 'Nearest Neighbor Sampling',\n property: 'nearest',\n default: false,\n }\n ],\n});","/**\n * Color Replace Filter Definition\n * Replaces a specific color in the image with another color\n * \n * This implementation uses the proper ColorReplaceFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n\n// Access filter class via direct indexing with type casting to avoid TypeScript errors \n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst ColorReplaceFilter = PixiFilters['ColorReplaceFilter'];\n\n// Register the Color Replace filter\nexport default registerFilter({\n id: 'color-replace',\n name: 'Color Replace',\n category: 'color',\n description: 'Replaces a specific color in the image with another color',\n \n /**\n * Create an instance of ColorReplaceFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating ColorReplaceFilter with params:', params);\n \n // Parse hex colors to numbers if they're strings\n let originalColorValue = 0xff0000; // Default red\n if (params.originalColor) {\n if (typeof params.originalColor === 'string') {\n originalColorValue = parseInt(params.originalColor.replace('#', '0x'), 16);\n } else if (typeof params.originalColor === 'number') {\n originalColorValue = params.originalColor;\n }\n }\n \n let targetColorValue = 0x0000ff; // Default blue\n if (params.targetColor) {\n if (typeof params.targetColor === 'string') {\n targetColorValue = parseInt(params.targetColor.replace('#', '0x'), 16);\n } else if (typeof params.targetColor === 'number') {\n targetColorValue = params.targetColor;\n }\n }\n \n // Create filter with proper options object for v6+\n const filter = new ColorReplaceFilter({\n originalColor: originalColorValue,\n targetColor: targetColorValue,\n tolerance: params.tolerance || 0.4\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'originalColor':\n // Convert hex string to number for the originalColor property\n if (typeof value === 'string') {\n this.originalColor = parseInt(value.replace('#', '0x'), 16);\n console.log(`Updated originalColor to ${this.originalColor} from ${value}`);\n } else if (typeof value === 'number') {\n this.originalColor = value;\n console.log(`Updated originalColor to ${this.originalColor}`);\n }\n break;\n \n case 'targetColor':\n // Convert hex string to number for the targetColor property\n if (typeof value === 'string') {\n this.targetColor = parseInt(value.replace('#', '0x'), 16);\n console.log(`Updated targetColor to ${this.targetColor} from ${value}`);\n } else if (typeof value === 'number') {\n this.targetColor = value;\n console.log(`Updated targetColor to ${this.targetColor}`);\n }\n break;\n \n case 'tolerance':\n // Direct tolerance update\n this.tolerance = value;\n console.log(`Updated tolerance to ${this.tolerance}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ColorReplaceFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ColorReplaceFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n originalColor: '#ff0000', // Red\n targetColor: '#0000ff', // Blue\n tolerance: 0.4 // Match sensitivity\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'originalColor',\n type: 'color',\n label: 'Original Color',\n property: 'originalColor',\n default: '#ff0000',\n },\n {\n id: 'targetColor',\n type: 'color',\n label: 'Target Color',\n property: 'targetColor',\n default: '#0000ff',\n },\n {\n id: 'tolerance',\n type: 'slider',\n label: 'Tolerance',\n property: 'tolerance',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.4,\n }\n ],\n});","/**\n * Multi-Color Replace Filter Definition\n * Replaces multiple colors in the image with different target colors\n * \n * This implementation uses the proper MultiColorReplaceFilter from pixi-filters\n * which is compatible with PixiJS v8\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n\n// Access filter class via direct indexing with type casting to avoid TypeScript errors \n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst MultiColorReplaceFilter = PixiFilters['MultiColorReplaceFilter'];\n\n// Register the Multi-Color Replace filter\nexport default registerFilter({\n id: 'multi-color-replace',\n name: 'Multi-Color Replace',\n category: 'color',\n description: 'Replaces multiple colors in the image with different target colors',\n \n /**\n * Create an instance of MultiColorReplaceFilter from pixi-filters package\n * This implementation follows the pattern from ColorGradientFilter, adding\n * proper parameter handling with an updateUIParam method\n */\n createFilter: (params) => {\n try {\n console.log('Creating MultiColorReplaceFilter with params:', params);\n \n // Prepare the replacements array with proper color value conversion\n const replacements = [];\n \n // Add first replacement pair\n if (params.originalColor1 && params.targetColor1) {\n const original = typeof params.originalColor1 === 'string' \n ? parseInt(params.originalColor1.replace('#', '0x'), 16)\n : params.originalColor1;\n const target = typeof params.targetColor1 === 'string'\n ? parseInt(params.targetColor1.replace('#', '0x'), 16)\n : params.targetColor1;\n \n replacements.push([original, target]);\n }\n \n // Add second replacement pair\n if (params.originalColor2 && params.targetColor2) {\n const original = typeof params.originalColor2 === 'string'\n ? parseInt(params.originalColor2.replace('#', '0x'), 16)\n : params.originalColor2;\n const target = typeof params.targetColor2 === 'string'\n ? parseInt(params.targetColor2.replace('#', '0x'), 16)\n : params.targetColor2;\n \n replacements.push([original, target]);\n }\n \n // Add third replacement pair if enabled\n if (params.enableThirdPair && params.originalColor3 && params.targetColor3) {\n const original = typeof params.originalColor3 === 'string'\n ? parseInt(params.originalColor3.replace('#', '0x'), 16)\n : params.originalColor3;\n const target = typeof params.targetColor3 === 'string'\n ? parseInt(params.targetColor3.replace('#', '0x'), 16)\n : params.targetColor3;\n \n replacements.push([original, target]);\n }\n \n // Create filter with PIXI v8 API (constructor takes replacements, epsilon, maxColors)\n const filter = new MultiColorReplaceFilter(\n replacements as any,\n params.tolerance || 0.05,\n 3 // Allow up to 3 color pairs\n );\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n * and provides consistent parameter handling across all filters.\n * \n * @param key The UI parameter name\n * @param value The new value for the parameter\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Create new replacements array if needed\n \n // Process standard color pair updates\n if (key === 'originalColor1' || key === 'targetColor1' || \n key === 'originalColor2' || key === 'targetColor2' ||\n key === 'originalColor3' || key === 'targetColor3' ||\n key === 'enableThirdPair') {\n \n // Create a new replacements array based on current params\n const newReplacements = [];\n \n // Add first replacement pair\n if (customParams.originalColor1 && customParams.targetColor1) {\n const original = typeof customParams.originalColor1 === 'string' \n ? parseInt(customParams.originalColor1.replace('#', '0x'), 16)\n : customParams.originalColor1;\n const target = typeof customParams.targetColor1 === 'string'\n ? parseInt(customParams.targetColor1.replace('#', '0x'), 16)\n : customParams.targetColor1;\n \n newReplacements.push([original, target]);\n }\n \n // Add second replacement pair\n if (customParams.originalColor2 && customParams.targetColor2) {\n const original = typeof customParams.originalColor2 === 'string'\n ? parseInt(customParams.originalColor2.replace('#', '0x'), 16)\n : customParams.originalColor2;\n const target = typeof customParams.targetColor2 === 'string'\n ? parseInt(customParams.targetColor2.replace('#', '0x'), 16)\n : customParams.targetColor2;\n \n newReplacements.push([original, target]);\n }\n \n // Add third replacement pair if enabled\n if (customParams.enableThirdPair && customParams.originalColor3 && customParams.targetColor3) {\n const original = typeof customParams.originalColor3 === 'string'\n ? parseInt(customParams.originalColor3.replace('#', '0x'), 16)\n : customParams.originalColor3;\n const target = typeof customParams.targetColor3 === 'string'\n ? parseInt(customParams.targetColor3.replace('#', '0x'), 16)\n : customParams.targetColor3;\n \n newReplacements.push([original, target]);\n }\n \n // Update the replacements and refresh\n this.replacements = newReplacements;\n this.refresh(); // Apply the changes\n console.log(`Updated replacements for ${key}:`, newReplacements);\n } \n // Handle tolerance updates directly\n else if (key === 'tolerance') {\n this.tolerance = value;\n console.log(`Updated tolerance to ${this.tolerance}`);\n } \n // For any other properties, try direct assignment\n else if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n \n return true;\n };\n \n console.log('MultiColorReplaceFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create MultiColorReplaceFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n originalColor1: '#ff0000', // Red\n targetColor1: '#0000ff', // Blue\n originalColor2: '#00ff00', // Green\n targetColor2: '#ffff00', // Yellow\n enableThirdPair: false,\n originalColor3: '#ff00ff', // Magenta\n targetColor3: '#00ffff', // Cyan\n tolerance: 0.05 // Match sensitivity\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'originalColor1',\n type: 'color',\n label: 'Original Color 1',\n property: 'originalColor1',\n default: '#ff0000',\n },\n {\n id: 'targetColor1',\n type: 'color',\n label: 'Target Color 1',\n property: 'targetColor1',\n default: '#0000ff',\n },\n {\n id: 'originalColor2',\n type: 'color',\n label: 'Original Color 2',\n property: 'originalColor2',\n default: '#00ff00',\n },\n {\n id: 'targetColor2',\n type: 'color',\n label: 'Target Color 2',\n property: 'targetColor2',\n default: '#ffff00',\n },\n {\n id: 'enableThirdPair',\n type: 'toggle',\n label: 'Enable Third Color Pair',\n property: 'enableThirdPair',\n default: false,\n },\n {\n id: 'originalColor3',\n type: 'color',\n label: 'Original Color 3',\n property: 'originalColor3',\n default: '#ff00ff',\n },\n {\n id: 'targetColor3',\n type: 'color',\n label: 'Target Color 3',\n property: 'targetColor3',\n default: '#00ffff',\n },\n {\n id: 'tolerance',\n type: 'slider',\n label: 'Tolerance',\n property: 'tolerance',\n min: 0,\n max: 0.5,\n step: 0.01,\n default: 0.05,\n }\n ],\n});","/**\n * RGB Split Filter Definition\n * Displaces the red, green, and blue channels separately to create a glitch or 3D effect\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { RGBSplitFilter } = PixiFilters;;\n\n// Register the RGB Split filter\nexport default registerFilter({\n id: 'rgb-split',\n name: 'RGB Split',\n category: 'color',\n description: 'Shifts the red, green, and blue channels to create a retro 3D or glitch effect',\n \n /**\n * Create an instance of the RGBSplitFilter with the provided parameters\n * Using the official pixi-filters implementation\n */\n createFilter: (params) => {\n try {\n console.log('Creating RGB Split filter with params:', params);\n \n // Create point objects for each channel from the params\n const red = { \n x: params.redX !== undefined ? params.redX : -10, \n y: params.redY !== undefined ? params.redY : 0 \n };\n const green = { \n x: params.greenX !== undefined ? params.greenX : 0, \n y: params.greenY !== undefined ? params.greenY : 10 \n };\n const blue = { \n x: params.blueX !== undefined ? params.blueX : 0, \n y: params.blueY !== undefined ? params.blueY : 0 \n };\n \n // Create the filter with the official pixi-filters package\n const filter = new RGBSplitFilter({\n red,\n green,\n blue\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'redX':\n this.redX = Number(value);\n console.log(`Updated redX to ${value}`);\n break;\n \n case 'redY':\n this.redY = Number(value);\n console.log(`Updated redY to ${value}`);\n break;\n \n case 'greenX':\n this.greenX = Number(value);\n console.log(`Updated greenX to ${value}`);\n break;\n \n case 'greenY':\n this.greenY = Number(value);\n console.log(`Updated greenY to ${value}`);\n break;\n \n case 'blueX':\n this.blueX = Number(value);\n console.log(`Updated blueX to ${value}`);\n break;\n \n case 'blueY':\n this.blueY = Number(value);\n console.log(`Updated blueY to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n } catch (error) {\n console.error(`Failed to update parameter ${key} using updateUIParam:`, error);\n \n // Still store the value in customParams even if setting it failed\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n \n return false;\n }\n };\n \n console.log('RGB Split filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create RGB Split filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n redX: -10,\n redY: 0,\n greenX: 0,\n greenY: 10,\n blueX: 0,\n blueY: 0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'redX',\n type: 'slider',\n label: 'Red X Offset',\n property: 'redX',\n min: -20,\n max: 20,\n step: 1,\n default: -10,\n },\n {\n id: 'redY',\n type: 'slider',\n label: 'Red Y Offset',\n property: 'redY',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n },\n {\n id: 'greenX',\n type: 'slider',\n label: 'Green X Offset',\n property: 'greenX',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n },\n {\n id: 'greenY',\n type: 'slider',\n label: 'Green Y Offset',\n property: 'greenY',\n min: -20,\n max: 20,\n step: 1,\n default: 10,\n },\n {\n id: 'blueX',\n type: 'slider',\n label: 'Blue X Offset',\n property: 'blueX',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n },\n {\n id: 'blueY',\n type: 'slider',\n label: 'Blue Y Offset',\n property: 'blueY',\n min: -20,\n max: 20,\n step: 1,\n default: 0,\n }\n ],\n});","/**\n * Advanced Bloom Filter Definition\n * Applies a sophisticated bloom effect with fine-grained control over parameters\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access AdvancedBloomFilter from the pixi-filters package\nconst { AdvancedBloomFilter } = PixiFilters;\n\n// Register the Advanced Bloom filter\nexport default registerFilter({\n id: 'advanced-bloom',\n name: 'Advanced Bloom',\n category: 'light',\n description: 'Adds a sophisticated bloom/glow effect with fine-grained control',\n \n // Create an instance of the AdvancedBloomFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating AdvancedBloomFilter with params:', params);\n \n // Using PixiJS v8 style options object\n const filter = new AdvancedBloomFilter({\n threshold: params.threshold || 0.5,\n bloomScale: params.bloomScale || 1.0,\n brightness: params.brightness || 1.0,\n blur: params.blur || 8,\n quality: params.quality || 4,\n pixelSize: { \n x: params.pixelSizeX || 1, \n y: params.pixelSizeY || 1 \n }\n });\n \n // Store custom params for reference\n (filter as any)._customParams = {\n pixelSizeX: params.pixelSizeX || 1,\n pixelSizeY: params.pixelSizeY || 1\n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n switch (key) {\n case 'threshold':\n this.threshold = Number(value);\n console.log(`Updated threshold to ${this.threshold}`);\n break;\n \n case 'bloomScale':\n this.bloomScale = Number(value);\n console.log(`Updated bloomScale to ${this.bloomScale}`);\n break;\n \n case 'brightness':\n this.brightness = Number(value);\n console.log(`Updated brightness to ${this.brightness}`);\n break;\n \n case 'blur':\n this.blur = Number(value);\n console.log(`Updated blur to ${this.blur}`);\n break;\n \n case 'quality':\n this.quality = Number(value);\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'pixelSizeX':\n customParams.pixelSizeX = Number(value);\n // Need to update the entire pixelSize object\n this.pixelSize = { \n x: Number(value), \n y: customParams.pixelSizeY \n };\n console.log(`Updated pixelSizeX to ${value}`);\n break;\n \n case 'pixelSizeY':\n customParams.pixelSizeY = Number(value);\n // Need to update the entire pixelSize object\n this.pixelSize = { \n x: customParams.pixelSizeX, \n y: Number(value) \n };\n console.log(`Updated pixelSizeY to ${value}`);\n break;\n \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for AdvancedBloomFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating AdvancedBloomFilter parameter ${key}:`, error);\n }\n };\n \n console.log('AdvancedBloomFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create AdvancedBloomFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n threshold: 0.5, // Brightness threshold\n bloomScale: 1.0, // Intensity of the bloom effect\n brightness: 1.0, // Overall brightness\n blur: 8, // Blur strength\n quality: 4, // Quality of the blur (higher = better but slower)\n pixelSizeX: 1, // Horizontal pixel size\n pixelSizeY: 1 // Vertical pixel size\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'threshold',\n type: 'slider',\n label: 'Threshold',\n property: 'threshold',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'bloomScale',\n type: 'slider',\n label: 'Bloom Intensity',\n property: 'bloomScale',\n min: 0,\n max: 3,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 3,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'blur',\n type: 'slider',\n label: 'Blur Strength',\n property: 'blur',\n min: 0,\n max: 20,\n step: 1,\n default: 8,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n {\n id: 'pixelSizeX',\n type: 'slider',\n label: 'Pixel Size X',\n property: 'pixelSizeX',\n min: 0.5,\n max: 10,\n step: 0.5,\n default: 1,\n },\n {\n id: 'pixelSizeY',\n type: 'slider',\n label: 'Pixel Size Y',\n property: 'pixelSizeY',\n min: 0.5,\n max: 10,\n step: 0.5,\n default: 1,\n }\n ],\n});","/**\n * ASCII Filter Definition\n * Applies an ASCII art effect to the image\n */\nimport { registerFilter } from '../registry';\n// Import from the central PixiFilters export\nimport * as PixiFilters from 'pixi-filters';\n// Define AsciiFilter as a variable to allow fallback implementation\nconst AsciiFilter = (PixiFilters as any).AsciiFilter;\n\n// Register the ASCII filter\nexport default registerFilter({\n id: 'ascii',\n name: 'ASCII',\n category: 'stylize',\n description: 'Convert image to ASCII text characters',\n \n // Create an instance of the AsciiFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating AsciiFilter with params:', params);\n \n // Ensure parameters have default values if missing\n const size = typeof params.size === 'number' ? params.size : 8;\n \n // Convert color string to number if needed\n let color = params.color;\n if (typeof color === 'string' && color.startsWith('#')) {\n color = parseInt(color.replace('#', '0x'), 16);\n }\n \n const replaceColor = params.replaceColor === true;\n \n // Create the filter with proper options\n const filter = new AsciiFilter({\n size: size,\n color: color,\n replaceColor: replaceColor\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n size: size,\n color: color,\n replaceColor: replaceColor\n };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`AsciiFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'size':\n this.size = Number(value);\n console.log(`Updated size to ${this.size}`);\n break;\n \n case 'color':\n // Convert color string to number if needed\n if (typeof value === 'string' && value.startsWith('#')) {\n customParams.color = value;\n this.color = parseInt(value.replace('#', '0x'), 16);\n } else {\n this.color = value;\n }\n console.log(`Updated color to ${this.color}`);\n break;\n \n case 'replaceColor':\n this.replaceColor = Boolean(value);\n console.log(`Updated replaceColor to ${this.replaceColor}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for AsciiFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating AsciiFilter parameter ${key}:`, error);\n }\n };\n \n console.log('AsciiFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create AsciiFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n size: 8,\n color: '#ffffff',\n replaceColor: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'size',\n type: 'slider',\n label: 'Character Size',\n property: 'size',\n min: 2,\n max: 20,\n step: 1,\n default: 8,\n },\n {\n id: 'color',\n type: 'color',\n label: 'Character Color',\n property: 'color',\n default: '#ffffff',\n },\n {\n id: 'replaceColor',\n type: 'toggle',\n label: 'Replace Original Colors',\n property: 'replaceColor',\n default: false,\n }\n ],\n});","/**\n * Backdrop Blur Filter Definition\n * Applies a blur effect to the background behind an object\n * \n * IMPORTANT: This filter requires setting useBackBuffer: true in the renderer options,\n * which has been added to the PixiApplication.ts file. It's a special filter that\n * applies a blur to what's behind the objects rather than to the objects themselves.\n */\nimport { registerFilter } from '../registry';\n// Import from the central PixiFilters export\nimport * as PixiFilters from 'pixi-filters';\n// Define BackdropBlurFilter as a variable to allow fallback implementation\nconst BackdropBlurFilter = (PixiFilters as any).BackdropBlurFilter;\n\n// Register the backdrop blur filter\nexport default registerFilter({\n id: 'backdrop-blur',\n name: 'Backdrop Blur',\n category: 'blur',\n description: 'Blurs what is behind the object, creating a glass-like effect',\n \n // Create an instance of the BackdropBlurFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating BackdropBlurFilter with params:', params);\n \n // Create filter with options object\n // This is a special filter - it inherits from BlurFilter but adds a blend pass\n // to apply the blur only to what's behind the object\n const filter = new BackdropBlurFilter({\n // Higher strength values (20-50) make the effect more noticeable\n strength: params.strength || 20, \n quality: params.quality || 4,\n // Lower resolution values (0.2-0.5) can make the effect more visible but less sharp\n resolution: params.resolution || 0.5,\n kernelSize: params.kernelSize || 9\n });\n \n // Store custom params for reference\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle all supported parameters\n switch (key) {\n case 'strength':\n // Higher strength values will make the effect more visible\n this.strength = Number(value);\n // For this filter, we can also update blur, which is a deprecated alias\n // but might be used internally\n this.blur = Number(value) / 4; // Scale down for blur property\n console.log(`Updated strength to ${this.strength}`);\n break;\n \n case 'quality':\n this.quality = Number(value);\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'resolution':\n // Lower resolution values make the effect more pronounced\n this.resolution = Number(value);\n console.log(`Updated resolution to ${this.resolution}`);\n break;\n \n case 'kernelSize':\n // Larger kernel sizes increase the blur radius and quality\n const kernelSize = Number(value);\n \n // Update both the X and Y kernel sizes\n if (this.blurXFilter && this.blurYFilter) {\n this.blurXFilter.kernelSize = kernelSize;\n this.blurYFilter.kernelSize = kernelSize;\n } else {\n // Fallback for older versions\n (this as any).kernelSize = kernelSize;\n }\n \n console.log(`Updated kernelSize to ${kernelSize}`);\n break;\n \n // For any other properties that might exist directly on the filter\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for BackdropBlurFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating BackdropBlurFilter parameter ${key}:`, error);\n }\n };\n \n // Log successful creation\n console.log('BackdropBlurFilter created successfully');\n \n return filter;\n } catch (error) {\n console.error('Failed to create BackdropBlurFilter:', error);\n return null;\n }\n },\n \n // Default parameter values - optimized for better visibility\n defaultParams: {\n strength: 20, // Higher value for stronger effect\n quality: 4, // Moderate quality for performance\n resolution: 0.5, // Lower resolution makes effect more visible\n kernelSize: 9 // Larger kernel for wider blur\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 50, // Increased max to allow stronger effects\n step: 1,\n default: 20,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n {\n id: 'resolution',\n type: 'slider',\n label: 'Resolution',\n property: 'resolution',\n min: 0.1,\n max: 1, // Reduced max to focus on lower values that show effect better\n step: 0.1,\n default: 0.5,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 },\n ],\n default: 9,\n },\n ],\n});","/**\n * Bevel Filter Definition\n * Applies a beveled edge effect to the image\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access BevelFilter from the pixi-filters package\nconst { BevelFilter } = PixiFilters;\n\n// Register the Bevel filter\nexport default registerFilter({\n id: 'bevel',\n name: 'Bevel',\n category: 'effects',\n description: 'Add a 3D-like beveled edge effect to the image',\n \n /**\n * Create an instance of the BevelFilter with the provided parameters\n * Using the official pixi-filters implementation\n */\n createFilter: (params) => {\n try {\n console.log('Creating Bevel filter with params:', params);\n \n // Parse colors from hex strings\n const lightColor = params.lightColor ? params.lightColor.replace('#', '0x') : '0xffffff';\n const shadowColor = params.shadowColor ? params.shadowColor.replace('#', '0x') : '0x000000';\n \n // Create the filter with the official pixi-filters package\n const filter = new BevelFilter({\n rotation: params.rotation !== undefined ? params.rotation : 45,\n thickness: params.thickness !== undefined ? params.thickness : 2,\n lightColor: parseInt(lightColor, 16),\n lightAlpha: params.lightAlpha !== undefined ? params.lightAlpha : 0.7,\n shadowColor: parseInt(shadowColor, 16),\n shadowAlpha: params.shadowAlpha !== undefined ? params.shadowAlpha : 0.7\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n /**\n * Add a custom updateUIParam method to handle UI parameter updates\n * Following the pattern from the fix_filters.md document\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'rotation':\n this.rotation = Number(value);\n console.log(`Updated rotation to ${value}`);\n break;\n \n case 'thickness':\n this.thickness = Number(value);\n console.log(`Updated thickness to ${value}`);\n break;\n \n case 'lightColor':\n // Convert hex string to number for the lightColor property\n if (typeof value === 'string') {\n const colorNum = parseInt(value.replace('#', '0x'), 16);\n this.lightColor = colorNum;\n console.log(`Updated lightColor to ${value} (${colorNum})`);\n }\n break;\n \n case 'lightAlpha':\n this.lightAlpha = Number(value);\n console.log(`Updated lightAlpha to ${value}`);\n break;\n \n case 'shadowColor':\n // Convert hex string to number for the shadowColor property\n if (typeof value === 'string') {\n const colorNum = parseInt(value.replace('#', '0x'), 16);\n this.shadowColor = colorNum;\n console.log(`Updated shadowColor to ${value} (${colorNum})`);\n }\n break;\n \n case 'shadowAlpha':\n this.shadowAlpha = Number(value);\n console.log(`Updated shadowAlpha to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n } catch (error) {\n console.error(`Failed to update parameter ${key} using updateUIParam:`, error);\n \n // Still store the value in customParams even if setting it failed\n if ((this as any)._customParams) {\n (this as any)._customParams[key] = value;\n }\n \n return false;\n }\n };\n \n console.log('Bevel filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create Bevel filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n rotation: 45,\n thickness: 2,\n lightColor: '#ffffff',\n lightAlpha: 0.7,\n shadowColor: '#000000',\n shadowAlpha: 0.7\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'rotation',\n type: 'slider',\n label: 'Angle',\n property: 'rotation',\n min: 0,\n max: 360,\n step: 1,\n default: 45,\n },\n {\n id: 'thickness',\n type: 'slider',\n label: 'Thickness',\n property: 'thickness',\n min: 0,\n max: 10,\n step: 0.1,\n default: 2,\n },\n {\n id: 'lightColor',\n type: 'color',\n label: 'Light Color',\n property: 'lightColor',\n default: '#ffffff',\n },\n {\n id: 'lightAlpha',\n type: 'slider',\n label: 'Light Opacity',\n property: 'lightAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.7,\n },\n {\n id: 'shadowColor',\n type: 'color',\n label: 'Shadow Color',\n property: 'shadowColor',\n default: '#000000',\n },\n {\n id: 'shadowAlpha',\n type: 'slider',\n label: 'Shadow Opacity',\n property: 'shadowAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.7,\n }\n ],\n});","/**\n * Bloom Filter Definition\n * Creates a glowing effect by emphasizing bright areas\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { BloomFilter } = PixiFilters;\n\n// Register the bloom filter\nexport default registerFilter({\n id: 'bloom',\n name: 'Bloom/Glow',\n category: 'light',\n description: 'Add a subtle glow effect to bright areas of the image',\n \n // Create an instance of the BloomFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating BloomFilter with params:', params);\n \n // Ensure parameters have default values if missing\n const strengthX = typeof params.strengthX === 'number' ? params.strengthX : 2;\n const strengthY = typeof params.strengthY === 'number' ? params.strengthY : 2;\n const quality = typeof params.quality === 'number' ? params.quality : 4;\n const resolution = typeof params.resolution === 'number' ? params.resolution : 1;\n const kernelSize = typeof params.kernelSize === 'number' ? params.kernelSize : 5;\n \n // Create the filter with proper options - force cast types to numbers\n const filter = new BloomFilter({\n strength: { \n x: Number(strengthX), \n y: Number(strengthY)\n },\n quality: Number(quality),\n resolution: Number(resolution),\n kernelSize: Number(kernelSize)\n });\n \n // Log the actual filter object to see its properties\n console.log('Created BloomFilter instance with properties:', {\n strength: filter.strength,\n quality: (filter as any).quality,\n resolution: filter.resolution,\n kernelSize: (filter as any).kernelSize\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n strengthX: strengthX,\n strengthY: strengthY,\n quality: quality,\n resolution: resolution,\n kernelSize: kernelSize\n };\n \n // Add a more direct approach to updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`BloomFilter.updateUIParam called: ${key} = ${value}`);\n \n // Force numeric conversion\n const numValue = Number(value);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = numValue;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'strengthX':\n // Direct property access to ensure the update happens\n if (this.strength && typeof this.strength === 'object') {\n this.strength.x = numValue;\n // Force a refresh of the internal filters\n this._updateStrength?.();\n console.log(`Updated strengthX to ${numValue}`, this.strength);\n } else {\n console.warn('Filter strength property not found or not an object');\n }\n break;\n \n case 'strengthY':\n // Direct property access to ensure the update happens\n if (this.strength && typeof this.strength === 'object') {\n this.strength.y = numValue;\n // Force a refresh of the internal filters\n this._updateStrength?.();\n console.log(`Updated strengthY to ${numValue}`, this.strength);\n } else {\n console.warn('Filter strength property not found or not an object');\n }\n break;\n \n case 'quality':\n (this as any).quality = numValue;\n console.log(`Updated quality to ${(this as any).quality}`);\n break;\n\n case 'resolution':\n this.resolution = numValue;\n console.log(`Updated resolution to ${this.resolution}`);\n break;\n\n case 'kernelSize':\n (this as any).kernelSize = numValue;\n console.log(`Updated kernelSize to ${(this as any).kernelSize}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = numValue;\n console.log(`Updated ${key} to ${numValue}`);\n } else {\n console.warn(`Unknown parameter for BloomFilter: ${key}`);\n }\n break;\n }\n \n // Log the current state after updates\n console.log('BloomFilter state after update:', {\n strength: this.strength,\n quality: (this as any).quality,\n resolution: this.resolution,\n kernelSize: (this as any).kernelSize\n });\n } catch (error) {\n console.error(`Error updating BloomFilter parameter ${key}:`, error);\n }\n };\n \n console.log('BloomFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create BloomFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strengthX: 2,\n strengthY: 2,\n quality: 4,\n resolution: 1,\n kernelSize: 5\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strengthX',\n type: 'slider',\n label: 'Horizontal Strength',\n property: 'strengthX',\n min: 0,\n max: 20,\n step: 0.1,\n default: 2,\n },\n {\n id: 'strengthY',\n type: 'slider',\n label: 'Vertical Strength',\n property: 'strengthY',\n min: 0,\n max: 20,\n step: 0.1,\n default: 2,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 1,\n max: 10,\n step: 1,\n default: 4,\n },\n {\n id: 'kernelSize',\n type: 'select',\n label: 'Kernel Size',\n property: 'kernelSize',\n options: [\n { label: '5', value: 5 },\n { label: '7', value: 7 },\n { label: '9', value: 9 },\n { label: '11', value: 11 },\n { label: '13', value: 13 },\n { label: '15', value: 15 }\n ],\n default: 5,\n }\n ],\n});","/**\n * Bulge Pinch Filter Definition\n * Creates a bulge or pinch effect in a circular area\n */\nimport { registerFilter } from '../registry';\n// Import the BulgePinchFilter using wildcard import pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { BulgePinchFilter } = PixiFilters;\n\n/**\n * Bulge-pinch paints displaced pixels that can extend up to `radius` past\n * the sprite edge when the effect's center is near the boundary. PIXI's\n * default filter bounds match the sprite rect, so without explicit padding\n * the bulge gets clipped at the image edge. Reserve a ring of `radius`\n * pixels around the sprite for the filter to render into.\n */\nconst computeBulgePadding = (radius: number): number => {\n const r = Math.max(0, Number(radius) || 0);\n return Math.ceil(r + 2);\n};\n\nexport default registerFilter({\n id: 'bulge-pinch',\n name: 'Bulge/Pinch',\n category: 'distortion',\n description: 'Creates a bulge or pinch effect in a circular area',\n\n createFilter: (params) => {\n try {\n const centerX = params.centerX ?? 0.5;\n const centerY = params.centerY ?? 0.5;\n const radius = params.radius ?? 100;\n const strength = params.strength ?? 1;\n\n const filter = new BulgePinchFilter({\n center: { x: centerX, y: centerY },\n radius,\n strength,\n });\n\n // Reserve room for the bulge to extend past the sprite. Setting\n // .padding forces PIXI to allocate a larger filter framebuffer so\n // the effect renders completely instead of clipping at the image\n // edge. Also expose _exportPadding so the renderer's bbox-based\n // trim path knows how far out to scan for non-transparent content.\n const padding = computeBulgePadding(radius);\n filter.padding = Math.max(filter.padding ?? 0, padding);\n (filter as any)._exportPadding = padding;\n\n (filter as any)._customParams = { ...params };\n\n const refreshPadding = (f: any) => {\n const r = Number(f._customParams?.radius ?? f.radius ?? 0);\n const p = computeBulgePadding(r);\n f._exportPadding = p;\n f.padding = Math.max(f.padding ?? 0, p);\n };\n\n (filter as any).updateUIParam = function (key: string, value: any) {\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n\n switch (key) {\n case 'centerX':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.x = value;\n break;\n\n case 'centerY':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.y = value;\n break;\n\n case 'radius':\n this.radius = Number(value);\n refreshPadding(this);\n break;\n\n case 'strength':\n this.strength = Number(value);\n break;\n\n default:\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n\n return true;\n };\n\n /**\n * Build a fresh BulgePinchFilter sized for export.\n *\n * The radius value is in render-target pixels. The user tunes it\n * while looking at the preview, where the image is downscaled. To\n * preserve the visual proportions on the native-size export,\n * scale radius by preview-to-native. Same pattern as drop-shadow.\n * (centerX/centerY are unitless 0-1, strength is unitless; they\n * don't scale.)\n */\n (filter as any).createExportFilter = function (options: { previewToNativeScale?: number } = {}) {\n const scale = Number.isFinite(options.previewToNativeScale)\n ? Math.max(1, Number(options.previewToNativeScale))\n : 1;\n const stored = (this as any)._customParams || params;\n\n const scaledRadius = Number(stored.radius ?? 100) * scale;\n const next = new BulgePinchFilter({\n center: {\n x: Number(stored.centerX ?? 0.5),\n y: Number(stored.centerY ?? 0.5),\n },\n radius: scaledRadius,\n strength: Number(stored.strength ?? 1),\n });\n\n const padding = computeBulgePadding(scaledRadius);\n (next as any)._exportPadding = padding;\n next.padding = Math.max(next.padding ?? 0, padding);\n return next;\n };\n\n (filter as any).getExportPadding = function () {\n return Number((this as any)._exportPadding || this.padding || 0);\n };\n\n return filter;\n } catch (error) {\n console.error('Failed to create BulgePinchFilter:', error);\n return null;\n }\n },\n\n defaultParams: {\n centerX: 0.5,\n centerY: 0.5,\n radius: 100,\n strength: 1,\n },\n\n controls: [\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: 0,\n max: 1000,\n step: 1,\n default: 100,\n },\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: -1,\n max: 1,\n step: 0.01,\n default: 1,\n },\n ],\n});\n","/**\n * Convolution Matrix Filter Definition\n * Applies a matrix convolution filter for effects like blur, sharpen, edge detection\n */\nimport { registerFilter } from '../registry';\n// Import from the central package for pixi filters\nimport * as PixiFilters from 'pixi-filters';\n// Access ConvolutionFilter from the pixi-filters package\nconst { ConvolutionFilter } = PixiFilters;\n\n// Predefined convolution matrices for common effects\nconst MATRICES = {\n normal: [0, 0, 0, 0, 1, 0, 0, 0, 0],\n gaussianBlur: [0.045, 0.122, 0.045, 0.122, 0.332, 0.122, 0.045, 0.122, 0.045],\n boxBlur: [1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9],\n edgeDetection: [-1, -1, -1, -1, 8, -1, -1, -1, -1],\n edgeEnhance: [0, 0, 0, -1, 1, 0, 0, 0, 0],\n emboss: [-2, -1, 0, -1, 1, 1, 0, 1, 2],\n sharpen: [0, -1, 0, -1, 5, -1, 0, -1, 0],\n sobelHorizontal: [1, 2, 1, 0, 0, 0, -1, -2, -1],\n sobelVertical: [1, 0, -1, 2, 0, -2, 1, 0, -1],\n};\n\nexport default registerFilter({\n id: 'convolution',\n name: 'Convolution Matrix',\n category: 'effects',\n description: 'Apply custom image effects using matrix convolution',\n \n createFilter: (params) => {\n try {\n console.log('Creating ConvolutionFilter with params:', params);\n \n // Get the appropriate matrix based on the selected preset or use custom values\n let matrix;\n \n if (params.customMatrix) {\n // Create matrix from individual matrix element values\n matrix = [\n params.m00, params.m01, params.m02,\n params.m10, params.m11, params.m12,\n params.m20, params.m21, params.m22\n ];\n } else {\n // Use preset matrix with type safety\n const presetKey = params.preset as keyof typeof MATRICES;\n matrix = MATRICES[presetKey] || MATRICES.normal;\n }\n \n // Create the filter with direct constructor call (PIXI v8 API)\n const filter = new ConvolutionFilter(matrix as any, params.width || 200, params.height || 200);\n\n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for UI parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'preset':\n // Update matrix from preset\n if (!customParams.customMatrix) {\n const presetKey = value as keyof typeof MATRICES;\n if (MATRICES[presetKey]) {\n this.matrix = MATRICES[presetKey];\n }\n }\n break;\n \n case 'customMatrix':\n // Toggle between preset and custom matrix\n if (value) {\n // Switch to custom matrix - copy current values to individual parameters\n const currentMatrix = this.matrix;\n customParams.m00 = currentMatrix[0];\n customParams.m01 = currentMatrix[1];\n customParams.m02 = currentMatrix[2];\n customParams.m10 = currentMatrix[3];\n customParams.m11 = currentMatrix[4];\n customParams.m12 = currentMatrix[5];\n customParams.m20 = currentMatrix[6];\n customParams.m21 = currentMatrix[7];\n customParams.m22 = currentMatrix[8];\n } else {\n // Switch back to preset\n const presetKey = customParams.preset as keyof typeof MATRICES;\n this.matrix = MATRICES[presetKey] || MATRICES.normal;\n }\n break;\n \n // Handle individual matrix element updates\n case 'm00': case 'm01': case 'm02':\n case 'm10': case 'm11': case 'm12':\n case 'm20': case 'm21': case 'm22':\n if (customParams.customMatrix) {\n // Update the matrix if in custom matrix mode\n const newMatrix = [...this.matrix];\n \n // Map UI parameter to matrix index\n const indices: Record<string, number> = {\n 'm00': 0, 'm01': 1, 'm02': 2,\n 'm10': 3, 'm11': 4, 'm12': 5,\n 'm20': 6, 'm21': 7, 'm22': 8\n };\n \n const idx = indices[key];\n if (idx !== undefined) {\n newMatrix[idx] = value;\n this.matrix = newMatrix;\n }\n }\n break;\n \n case 'width':\n this.width = value;\n break;\n \n case 'height':\n this.height = value;\n break;\n \n default:\n // For any other parameters that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create ConvolutionFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n preset: 'normal',\n customMatrix: false,\n m00: 0, m01: 0, m02: 0,\n m10: 0, m11: 1, m12: 0,\n m20: 0, m21: 0, m22: 0,\n width: 200,\n height: 200\n },\n \n controls: [\n {\n id: 'preset',\n type: 'select',\n label: 'Effect Preset',\n property: 'preset',\n options: [\n { value: 'normal', label: 'Normal' },\n { value: 'gaussianBlur', label: 'Gaussian Blur' },\n { value: 'boxBlur', label: 'Box Blur' },\n { value: 'edgeDetection', label: 'Edge Detection' },\n { value: 'edgeEnhance', label: 'Edge Enhance' },\n { value: 'emboss', label: 'Emboss' },\n { value: 'sharpen', label: 'Sharpen' },\n { value: 'sobelHorizontal', label: 'Sobel Horizontal' },\n { value: 'sobelVertical', label: 'Sobel Vertical' }\n ],\n default: 'normal'\n },\n {\n id: 'customMatrix',\n type: 'toggle',\n label: 'Use Custom Matrix',\n property: 'customMatrix',\n default: false\n },\n {\n id: 'width',\n type: 'slider',\n label: 'Width',\n property: 'width',\n min: 50,\n max: 500,\n step: 10,\n default: 200\n },\n {\n id: 'height',\n type: 'slider',\n label: 'Height',\n property: 'height',\n min: 50,\n max: 500,\n step: 10,\n default: 200\n },\n {\n id: 'm00',\n type: 'slider',\n label: 'Matrix [0,0]',\n property: 'm00',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm01',\n type: 'slider',\n label: 'Matrix [0,1]',\n property: 'm01',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm02',\n type: 'slider',\n label: 'Matrix [0,2]',\n property: 'm02',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm10',\n type: 'slider',\n label: 'Matrix [1,0]',\n property: 'm10',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm11',\n type: 'slider',\n label: 'Matrix [1,1]',\n property: 'm11',\n min: -5,\n max: 5,\n step: 0.1,\n default: 1\n },\n {\n id: 'm12',\n type: 'slider',\n label: 'Matrix [1,2]',\n property: 'm12',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm20',\n type: 'slider',\n label: 'Matrix [2,0]',\n property: 'm20',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm21',\n type: 'slider',\n label: 'Matrix [2,1]',\n property: 'm21',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n },\n {\n id: 'm22',\n type: 'slider',\n label: 'Matrix [2,2]',\n property: 'm22',\n min: -5,\n max: 5,\n step: 0.1,\n default: 0\n }\n ]\n});","/**\n * Cross Hatch Filter Definition\n * Creates a crosshatching effect like in a pencil drawing\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { CrossHatchFilter } = PixiFilters;\n\n// Register the CrossHatch filter\nexport default registerFilter({\n id: 'cross-hatch',\n name: 'Cross Hatch',\n category: 'stylize',\n description: 'Creates a crosshatching effect like in a pencil drawing',\n \n // Create an instance of the CrossHatchFilter\n // Note: CrossHatchFilter has NO parameters according to PixiJS examples\n createFilter: (_params) => {\n try {\n console.log('Creating CrossHatchFilter');\n \n // Create the filter - CrossHatchFilter has no constructor parameters\n const filter = new CrossHatchFilter();\n \n // Add a minimal updateUIParam method for consistency\n // Even though CrossHatchFilter has no parameters to update\n (filter as any).updateUIParam = function(key: string, value: any) {\n console.log(`CrossHatchFilter has no configurable parameters. Ignoring: ${key} = ${value}`);\n return true;\n };\n \n console.log('CrossHatchFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create CrossHatchFilter:', error);\n return null;\n }\n },\n \n // No parameters for this filter\n defaultParams: {},\n \n // No UI controls since CrossHatchFilter has no parameters\n controls: [],\n});","/**\n * CRT Screen Filter Definition\n * Simulates an old CRT screen with scan lines and noise\n */\nimport { registerFilter } from '../registry';\nimport * as filters from 'pixi-filters';\n\n// Register the CRT filter\nexport default registerFilter({\n id: 'crt',\n name: 'CRT Screen',\n category: 'stylize',\n description: 'Simulates an old CRT screen with scan lines and noise',\n \n // Create an instance of the CRTFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating CRTFilter with params:', params);\n \n // Ensure parameters have default values\n const options = {\n lineWidth: typeof params.lineWidth === 'number' ? params.lineWidth : 1.0,\n noise: typeof params.noise === 'number' ? params.noise : 0.3,\n curvature: typeof params.curvature === 'number' ? params.curvature : 1.0,\n lineContrast: typeof params.lineContrast === 'number' ? params.lineContrast : 0.25,\n verticalLine: params.verticalLine === true,\n noiseSize: typeof params.noiseSize === 'number' ? params.noiseSize : 1.0,\n vignetting: typeof params.vignetting === 'number' ? params.vignetting : 0.3,\n vignettingAlpha: typeof params.vignettingAlpha === 'number' ? params.vignettingAlpha : 1.0,\n vignettingBlur: typeof params.vignettingBlur === 'number' ? params.vignettingBlur : 0.3,\n time: typeof params.time === 'number' ? params.time : 0.0,\n seed: typeof params.seed === 'number' ? params.seed : Math.random()\n };\n \n // Create the filter with proper options\n const filter = new filters.CRTFilter(options);\n \n // Store custom parameters for reference\n (filter as any)._customParams = { ...options };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`CRTFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key with proper type conversion\n switch (key) {\n case 'lineWidth':\n this.lineWidth = Number(value);\n console.log(`Updated lineWidth to ${this.lineWidth}`);\n break;\n \n case 'noise':\n this.noise = Number(value);\n console.log(`Updated noise to ${this.noise}`);\n break;\n \n case 'curvature':\n this.curvature = Number(value);\n console.log(`Updated curvature to ${this.curvature}`);\n break;\n \n case 'lineContrast':\n this.lineContrast = Number(value);\n console.log(`Updated lineContrast to ${this.lineContrast}`);\n break;\n \n case 'verticalLine':\n this.verticalLine = Boolean(value);\n console.log(`Updated verticalLine to ${this.verticalLine}`);\n break;\n \n case 'noiseSize':\n this.noiseSize = Number(value);\n console.log(`Updated noiseSize to ${this.noiseSize}`);\n break;\n \n case 'vignetting':\n this.vignetting = Number(value);\n console.log(`Updated vignetting to ${this.vignetting}`);\n break;\n \n case 'vignettingAlpha':\n this.vignettingAlpha = Number(value);\n console.log(`Updated vignettingAlpha to ${this.vignettingAlpha}`);\n break;\n \n case 'vignettingBlur':\n this.vignettingBlur = Number(value);\n console.log(`Updated vignettingBlur to ${this.vignettingBlur}`);\n break;\n \n case 'time':\n this.time = Number(value);\n console.log(`Updated time to ${this.time}`);\n break;\n \n case 'seed':\n this.seed = Number(value);\n console.log(`Updated seed to ${this.seed}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for CRTFilter: ${key}`);\n }\n break;\n }\n \n // Log current state\n console.log('CRTFilter state:', {\n lineWidth: this.lineWidth,\n noise: this.noise,\n curvature: this.curvature,\n verticalLine: this.verticalLine,\n time: this.time\n });\n } catch (error) {\n console.error(`Error updating CRTFilter parameter ${key}:`, error);\n }\n };\n \n console.log('CRTFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create CRTFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n lineWidth: 1.0,\n noise: 0.3,\n curvature: 1.0,\n lineContrast: 0.25,\n verticalLine: false,\n noiseSize: 1.0,\n vignetting: 0.3,\n vignettingAlpha: 1.0,\n vignettingBlur: 0.3,\n time: 0.0,\n seed: 1.0\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'lineWidth',\n type: 'slider',\n label: 'Scan Line Width',\n property: 'lineWidth',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'noise',\n type: 'slider',\n label: 'Noise Amount',\n property: 'noise',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3,\n },\n {\n id: 'curvature',\n type: 'slider',\n label: 'Screen Curvature',\n property: 'curvature',\n min: 0,\n max: 10,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'lineContrast',\n type: 'slider',\n label: 'Line Contrast',\n property: 'lineContrast',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.25,\n },\n {\n id: 'verticalLine',\n type: 'toggle',\n label: 'Vertical Lines',\n property: 'verticalLine',\n default: false,\n },\n {\n id: 'noiseSize',\n type: 'slider',\n label: 'Noise Size',\n property: 'noiseSize',\n min: 0.5,\n max: 5,\n step: 0.1,\n default: 1.0,\n },\n {\n id: 'vignetting',\n type: 'slider',\n label: 'Vignette Size',\n property: 'vignetting',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3,\n },\n {\n id: 'vignettingAlpha',\n type: 'slider',\n label: 'Vignette Opacity',\n property: 'vignettingAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1.0,\n },\n {\n id: 'vignettingBlur',\n type: 'slider',\n label: 'Vignette Blur',\n property: 'vignettingBlur',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Animation Time',\n property: 'time',\n min: 0,\n max: 10,\n step: 0.1,\n default: 0.0,\n }\n ],\n});","/**\n * Displacement Filter Definition\n * Applies a displacement map effect to distort the image\n */\nimport { registerFilter } from '../registry';\n// Import PIXI namespace\nimport * as PIXI from 'pixi.js';\n\n// Access classes via direct indexing\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst DisplacementFilter = PIXI['DisplacementFilter']; \n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst Sprite = PIXI['Sprite'];\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst Texture = PIXI['Texture'];\n\n// Register the Displacement filter\nexport default registerFilter({\n id: 'displacement', // ID must match what the application expects\n name: 'Displacement Map',\n category: 'distortion',\n description: 'Distorts the image using a displacement map texture',\n \n // Create an instance of the DisplacementFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating DisplacementFilter with params:', params);\n \n // The displacement map texture URL (default or from params)\n const mapUrl = params.mapTexture || '/assets/images/displacement_map.png';\n \n // Create a texture from the map URL\n let mapTexture;\n try {\n mapTexture = Texture.from(mapUrl);\n // Set the texture to repeat\n mapTexture.source.addressMode = 'repeat';\n } catch (error) {\n console.error('Failed to load displacement map texture:', error);\n // Create a fallback texture\n const canvas = document.createElement('canvas');\n canvas.width = 256;\n canvas.height = 256;\n const ctx = canvas.getContext('2d');\n if (ctx) {\n // Draw a simple pattern\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.fillStyle = '#000000';\n for (let i = 0; i < 10; i++) {\n for (let j = 0; j < 10; j++) {\n if ((i + j) % 2 === 0) {\n ctx.fillRect(i * 25, j * 25, 25, 25);\n }\n }\n }\n }\n mapTexture = Texture.from(canvas);\n }\n \n // Create sprite for the displacement map\n const displacementSprite = new Sprite(mapTexture);\n \n // Create the filter with the sprite and scale\n const filter = new DisplacementFilter(displacementSprite, params.scale || 50);\n \n // Set individual scale components\n filter.scale.x = params.scaleX || 50;\n filter.scale.y = params.scaleY || 50;\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n (filter as any)._displacementSprite = displacementSprite;\n \n /**\n * Custom method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'scaleX':\n this.scale.x = value;\n console.log(`Updated scale.x to ${value}`);\n break;\n \n case 'scaleY':\n this.scale.y = value;\n console.log(`Updated scale.y to ${value}`);\n break;\n \n case 'mapTexture':\n try {\n // Try to update the sprite's texture\n const sprite = (this as any)._displacementSprite;\n if (sprite) {\n const newTexture = Texture.from(value);\n newTexture.source.addressMode = 'repeat';\n sprite.texture = newTexture;\n console.log(`Updated displacement map texture to ${value}`);\n }\n } catch (error) {\n console.error('Failed to update displacement map texture:', error);\n }\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else if (key in this.scale) {\n this.scale[key] = value;\n console.log(`Updated scale.${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('DisplacementFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create DisplacementFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n mapTexture: '/assets/images/displacement_map.png',\n scale: 50,\n scaleX: 50,\n scaleY: 50\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'mapTexture',\n type: 'select',\n label: 'Displacement Map',\n property: 'mapTexture',\n options: [\n { label: 'Default', value: '/assets/images/displacement_map.png' },\n { label: 'Clouds', value: '/assets/images/clouds.png' },\n { label: 'Ripple', value: '/assets/images/ripple.png' }\n ],\n default: '/assets/images/displacement_map.png',\n },\n {\n id: 'scaleX',\n type: 'slider',\n label: 'Scale X',\n property: 'scaleX',\n min: 1,\n max: 200,\n step: 1,\n default: 50,\n },\n {\n id: 'scaleY',\n type: 'slider',\n label: 'Scale Y',\n property: 'scaleY',\n min: 1,\n max: 200,\n step: 1,\n default: 50,\n }\n ],\n});","/**\n * Dot Screen Filter Definition\n * Simulates a halftone printing pattern with dots\n */\nimport { registerFilter } from '../registry';\nimport * as filters from 'pixi-filters';\n\n// Register the Dot Screen filter\nexport default registerFilter({\n id: 'dot',\n name: 'Dot Screen',\n category: 'stylize',\n description: 'Simulates a halftone printing pattern with dots',\n \n // Create an instance of the DotFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating DotFilter with params:', params);\n \n // Ensure parameters have default values\n const options = {\n scale: typeof params.scale === 'number' ? params.scale : 1,\n angle: typeof params.angle === 'number' ? params.angle : 5,\n grayscale: params.grayscale === true\n };\n \n // Create the filter with proper options\n const filter = new filters.DotFilter(options);\n \n // Store custom parameters for reference\n (filter as any)._customParams = { ...options };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`DotFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key with proper type conversion\n switch (key) {\n case 'scale':\n this.scale = Number(value);\n console.log(`Updated scale to ${this.scale}`);\n break;\n \n case 'angle':\n this.angle = Number(value);\n console.log(`Updated angle to ${this.angle}`);\n break;\n \n case 'grayscale':\n this.grayscale = Boolean(value);\n console.log(`Updated grayscale to ${this.grayscale}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for DotFilter: ${key}`);\n }\n break;\n }\n \n // Log current state\n console.log('DotFilter state:', {\n scale: this.scale,\n angle: this.angle,\n grayscale: this.grayscale\n });\n } catch (error) {\n console.error(`Error updating DotFilter parameter ${key}:`, error);\n }\n };\n \n console.log('DotFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create DotFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n scale: 1,\n angle: 5,\n grayscale: true\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'scale',\n type: 'slider',\n label: 'Dot Scale',\n property: 'scale',\n min: 0.5,\n max: 10,\n step: 0.1,\n default: 1,\n },\n {\n id: 'angle',\n type: 'slider',\n label: 'Dot Angle',\n property: 'angle',\n min: 0,\n max: 10,\n step: 0.1,\n default: 5,\n },\n {\n id: 'grayscale',\n type: 'toggle',\n label: 'Grayscale',\n property: 'grayscale',\n default: true,\n }\n ],\n});","/**\n * Emboss Filter Definition\n * Creates an embossed relief effect using the proper EmbossFilter from pixi-filters\n */\nimport { registerFilter } from '../registry';\n// Import EmbossFilter from pixi-filters\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { EmbossFilter } = PixiFilters;\n\n// Register the Emboss filter\nexport default registerFilter({\n id: 'emboss',\n name: 'Emboss',\n category: 'stylize',\n description: 'Creates an embossed relief effect',\n \n // Create an instance of the Emboss filter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating Emboss filter with params:', params);\n \n // Ensure parameters have default values\n const strength = typeof params.strength === 'number' ? params.strength : 5;\n \n // Use the proper EmbossFilter from pixi-filters\n const filter = new EmbossFilter(strength);\n \n console.log('Created emboss effect with EmbossFilter, strength:', strength);\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n strength: strength\n };\n \n // Add custom updateUIParam method for dynamic parameter updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`Emboss filter updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates\n switch (key) {\n case 'strength':\n const numValue = Number(value);\n customParams.strength = numValue;\n \n // For EmbossFilter, set the strength property directly\n this.strength = numValue;\n \n console.log(`Updated EmbossFilter strength to ${numValue}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for EmbossFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating emboss filter parameter ${key}:`, error);\n }\n };\n \n console.log('Emboss filter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create emboss filter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n strength: 5\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 20,\n step: 0.5,\n default: 5,\n }\n ],\n});","/**\n * Glitch Filter Definition\n * Applies digital distortion and glitch effects to images\n */\nimport { registerFilter } from '../registry';\n// Import the GlitchFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { GlitchFilter } = PixiFilters;;\n\n// Define constants for fill modes\nconst FILL_MODES = {\n TRANSPARENT: 0,\n ORIGINAL: 1,\n LOOP: 2,\n CLAMP: 3,\n MIRROR: 4\n};\n\nexport default registerFilter({\n id: 'glitch',\n name: 'Glitch',\n category: 'effects',\n description: 'Apply digital distortion and glitch effects',\n \n createFilter: (params) => {\n try {\n console.log('Creating GlitchFilter with params:', params);\n \n // Create color offset objects from individual components\n const redOffset = { x: params.redX, y: params.redY };\n const greenOffset = { x: params.greenX, y: params.greenY };\n const blueOffset = { x: params.blueX, y: params.blueY };\n \n // Create the filter with options\n const filter = new GlitchFilter({\n slices: params.slices,\n offset: params.offset,\n direction: params.direction,\n fillMode: params.fillMode,\n seed: params.seed,\n average: params.average,\n minSize: params.minSize,\n sampleSize: params.sampleSize,\n red: redOffset,\n green: greenOffset,\n blue: blueOffset\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Trigger a refresh to ensure the filter initializes correctly\n if (typeof filter.refresh === 'function') {\n filter.refresh();\n }\n \n // Set up an animation loop for the filter if it's animating\n let animationFrameId: number | null = null;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update the seed with a random value for animation\n filter.seed = Math.random();\n }\n // Continue the animation loop\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if needed\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for dynamic UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if it's not running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'slices':\n // Ensure slices is an integer\n this.slices = Math.round(value);\n break;\n \n case 'redX':\n case 'redY':\n // Update red offset\n const red = this.red;\n if (key === 'redX') red.x = value;\n else red.y = value;\n this.red = red;\n break;\n \n case 'greenX':\n case 'greenY':\n // Update green offset\n const green = this.green;\n if (key === 'greenX') green.x = value;\n else green.y = value;\n this.green = green;\n break;\n \n case 'blueX':\n case 'blueY':\n // Update blue offset\n const blue = this.blue;\n if (key === 'blueX') blue.x = value;\n else blue.y = value;\n this.blue = blue;\n break;\n \n case 'seed':\n // Only update seed manually if not animating\n if (!(this as any).animating) {\n this.seed = value;\n }\n break;\n \n case 'randomizeSeed':\n // Action button to randomize seed\n if (value && !customParams.animating) {\n this.seed = Math.random();\n }\n break;\n \n case 'refresh':\n // Action button to refresh the filter\n if (value) {\n try {\n this.refresh();\n } catch (e) {\n console.warn('Error refreshing GlitchFilter:', e);\n }\n }\n break;\n \n // Handle direct properties\n case 'offset':\n case 'direction':\n case 'fillMode':\n case 'average':\n case 'minSize':\n case 'sampleSize':\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create GlitchFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n slices: 10,\n offset: 100,\n direction: 0,\n fillMode: FILL_MODES.LOOP, // LOOP mode looks better for the demo\n seed: 0.5,\n average: false,\n minSize: 8,\n sampleSize: 512,\n redX: 2,\n redY: 2,\n greenX: -10,\n greenY: 4,\n blueX: 10,\n blueY: -4,\n animating: false, // Control for automatic animation\n randomizeSeed: false, // Button trigger for randomizing seed\n refresh: false, // Button trigger for refreshing the filter\n },\n \n controls: [\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Automatically',\n property: 'animating',\n default: false\n },\n {\n id: 'slices',\n type: 'slider',\n label: 'Slices',\n property: 'slices',\n min: 2,\n max: 20,\n step: 1,\n default: 10\n },\n {\n id: 'offset',\n type: 'slider',\n label: 'Offset Amount',\n property: 'offset',\n min: -400,\n max: 400,\n step: 1,\n default: 100\n },\n {\n id: 'direction',\n type: 'slider',\n label: 'Direction',\n property: 'direction',\n min: -180,\n max: 180,\n step: 1,\n default: 0\n },\n {\n id: 'fillMode',\n type: 'select',\n label: 'Fill Mode',\n property: 'fillMode',\n options: [\n { value: FILL_MODES.TRANSPARENT, label: 'Transparent' },\n { value: FILL_MODES.ORIGINAL, label: 'Original' },\n { value: FILL_MODES.LOOP, label: 'Loop' },\n { value: FILL_MODES.CLAMP, label: 'Clamp' },\n { value: FILL_MODES.MIRROR, label: 'Mirror' }\n ],\n default: FILL_MODES.LOOP\n },\n {\n id: 'seed',\n type: 'slider',\n label: 'Seed',\n property: 'seed',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Seed',\n action: 'randomizeSeed'\n },\n {\n id: 'refresh',\n type: 'button',\n label: 'Refresh Filter',\n action: 'refresh'\n },\n {\n id: 'average',\n type: 'toggle',\n label: 'Average Slices',\n property: 'average',\n default: false\n },\n // Color channel offsets\n {\n id: 'redX',\n type: 'slider',\n label: 'Red X Offset',\n property: 'redX',\n min: -50,\n max: 50,\n step: 0.5,\n default: 2\n },\n {\n id: 'redY',\n type: 'slider',\n label: 'Red Y Offset',\n property: 'redY',\n min: -50,\n max: 50,\n step: 0.5,\n default: 2\n },\n {\n id: 'greenX',\n type: 'slider',\n label: 'Green X Offset',\n property: 'greenX',\n min: -50,\n max: 50,\n step: 0.5,\n default: -10\n },\n {\n id: 'greenY',\n type: 'slider',\n label: 'Green Y Offset',\n property: 'greenY',\n min: -50,\n max: 50,\n step: 0.5,\n default: 4\n },\n {\n id: 'blueX',\n type: 'slider',\n label: 'Blue X Offset',\n property: 'blueX',\n min: -50,\n max: 50,\n step: 0.5,\n default: 10\n },\n {\n id: 'blueY',\n type: 'slider',\n label: 'Blue Y Offset',\n property: 'blueY',\n min: -50,\n max: 50,\n step: 0.5,\n default: -4\n }\n ]\n});","/**\n * Glow Filter Definition\n * Applies a customizable glow effect around the image\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { GlowFilter } = PixiFilters;;\n\n// Register the Glow filter\nexport default registerFilter({\n id: 'glow',\n name: 'Glow',\n category: 'light',\n description: 'Adds a customizable glow effect around the image',\n \n // Create an instance of the GlowFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating GlowFilter with params:', params);\n \n // Parse color from hex string\n const color = parseInt(params.color.replace('#', '0x'), 16);\n \n // Create filter with proper options\n const filter = new GlowFilter({\n distance: params.distance || 10,\n outerStrength: params.outerStrength || 4,\n innerStrength: params.innerStrength || 0,\n color: color,\n alpha: params.alpha ?? 1,\n quality: params.quality || 0.1,\n knockout: params.knockout || false\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = { \n color: params.color || '#ffffff', \n ...params \n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'distance':\n this.distance = Number(value);\n console.log(`Updated distance to ${this.distance}`);\n break;\n \n case 'outerStrength':\n this.outerStrength = Number(value);\n console.log(`Updated outerStrength to ${this.outerStrength}`);\n break;\n \n case 'innerStrength':\n this.innerStrength = Number(value);\n console.log(`Updated innerStrength to ${this.innerStrength}`);\n break;\n \n case 'color':\n // Store the hex color for reference\n customParams.color = value;\n // Convert hex color string to number for the filter\n this.color = parseInt(value.replace('#', '0x'), 16);\n console.log(`Updated color to ${value} (${this.color})`);\n break;\n \n case 'alpha':\n this.alpha = Number(value);\n console.log(`Updated alpha to ${this.alpha}`);\n break;\n \n case 'quality':\n this.quality = Number(value);\n console.log(`Updated quality to ${this.quality}`);\n break;\n \n case 'knockout':\n this.knockout = Boolean(value);\n console.log(`Updated knockout to ${this.knockout}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for GlowFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating GlowFilter parameter ${key}:`, error);\n }\n };\n \n console.log('GlowFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create GlowFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n distance: 10,\n outerStrength: 4,\n innerStrength: 0,\n color: '#ffffff',\n alpha: 1,\n quality: 0.1,\n knockout: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'distance',\n type: 'slider',\n label: 'Distance',\n property: 'distance',\n min: 0,\n max: 20,\n step: 1,\n default: 10,\n },\n {\n id: 'outerStrength',\n type: 'slider',\n label: 'Outer Strength',\n property: 'outerStrength',\n min: 0,\n max: 20,\n step: 0.1,\n default: 4,\n },\n {\n id: 'innerStrength',\n type: 'slider',\n label: 'Inner Strength',\n property: 'innerStrength',\n min: 0,\n max: 20,\n step: 0.1,\n default: 0,\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#ffffff',\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 0.01,\n max: 1,\n step: 0.01,\n default: 0.1,\n },\n {\n id: 'knockout',\n type: 'toggle',\n label: 'Show Glow Only',\n property: 'knockout',\n default: false,\n }\n ],\n});","/**\n * Godray Filter Definition\n * Creates volumetric light-ray effects\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { GodrayFilter } = PixiFilters;;\n\n// Register the Godray filter\nexport default registerFilter({\n id: 'godray',\n name: 'Godray',\n category: 'light',\n description: 'Creates volumetric light-ray effects (crepuscular rays)',\n \n // Create an instance of the GodrayFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating GodrayFilter with params:', params);\n \n // Create filter with proper options\n const filter = new GodrayFilter({\n angle: params.angle || 30,\n parallel: params.parallel ?? true,\n center: { \n x: params.centerX || 0, \n y: params.centerY || 0 \n },\n gain: params.gain || 0.5,\n lacunarity: params.lacunarity || 2.5,\n time: params.time || 0,\n alpha: params.alpha || 1\n });\n \n // Store custom parameters for reference\n (filter as any)._customParams = { \n centerX: params.centerX || 0,\n centerY: params.centerY || 0,\n ...params \n };\n \n // Add custom updateUIParam method for dynamic updates\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'angle':\n this.angle = Number(value);\n console.log(`Updated angle to ${this.angle}`);\n break;\n \n case 'parallel':\n this.parallel = Boolean(value);\n console.log(`Updated parallel to ${this.parallel}`);\n break;\n \n case 'centerX':\n customParams.centerX = Number(value);\n // Need to update the entire center object\n this.center = { \n x: Number(value), \n y: customParams.centerY \n };\n console.log(`Updated centerX to ${value}`);\n break;\n \n case 'centerY':\n customParams.centerY = Number(value);\n // Need to update the entire center object\n this.center = { \n x: customParams.centerX, \n y: Number(value) \n };\n console.log(`Updated centerY to ${value}`);\n break;\n \n case 'gain':\n this.gain = Number(value);\n console.log(`Updated gain to ${this.gain}`);\n break;\n \n case 'lacunarity':\n this.lacunarity = Number(value);\n console.log(`Updated lacunarity to ${this.lacunarity}`);\n break;\n \n case 'time':\n this.time = Number(value);\n console.log(`Updated time to ${this.time}`);\n break;\n \n case 'alpha':\n this.alpha = Number(value);\n console.log(`Updated alpha to ${this.alpha}`);\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for GodrayFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating GodrayFilter parameter ${key}:`, error);\n }\n };\n \n console.log('GodrayFilter created successfully');\n return filter;\n } catch (error) {\n console.error('Failed to create GodrayFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n angle: 30,\n parallel: true,\n centerX: 0,\n centerY: 0,\n gain: 0.5,\n lacunarity: 2.5,\n time: 0,\n alpha: 1\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: 0,\n max: 360,\n step: 1,\n default: 30,\n },\n {\n id: 'parallel',\n type: 'toggle',\n label: 'Parallel Rays',\n property: 'parallel',\n default: true,\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Light Source X',\n property: 'centerX',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Light Source Y',\n property: 'centerY',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0,\n },\n {\n id: 'gain',\n type: 'slider',\n label: 'Gain/Intensity',\n property: 'gain',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'lacunarity',\n type: 'slider',\n label: 'Density',\n property: 'lacunarity',\n min: 0.1,\n max: 10,\n step: 0.1,\n default: 2.5,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Time',\n property: 'time',\n min: 0,\n max: 10,\n step: 0.1,\n default: 0,\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n }\n ],\n});","/**\n * Lightmap Filter Definition\n * Applies a lighting effect using a reference texture as a light map\n */\nimport { registerFilter } from '../registry';\n// Import packages\nimport * as PixiFilters from 'pixi-filters';\nimport * as PIXI from 'pixi.js';\n\n// Access classes via direct indexing\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst SimpleLightmapFilter = PixiFilters['SimpleLightmapFilter'];\n// @ts-ignore - Runtime access of property that TypeScript doesn't know about\nconst Texture = PIXI['Texture'];\n\n// Register the Lightmap filter\nexport default registerFilter({\n id: 'lightmap',\n name: 'Lightmap',\n category: 'light',\n description: 'Applies lighting effects using a reference texture as a light map',\n \n // Create an instance of the SimpleLightmapFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating SimpleLightmapFilter with params:', params);\n \n // Ensure we have default values\n const textureType = params.textureType || 'default';\n const colorValue = params.color || '#000000';\n const alphaValue = typeof params.alpha === 'number' ? params.alpha : 1;\n \n // Create canvas for texture generation\n const canvas = document.createElement('canvas');\n canvas.width = 256;\n canvas.height = 256;\n const ctx = canvas.getContext('2d');\n \n if (!ctx) {\n console.error('Could not get 2D context for canvas');\n throw new Error('Canvas 2D context not available');\n }\n \n // Generate a texture based on the selected type\n if (textureType === 'spotlight') {\n // Create a stronger spotlight effect\n ctx.fillStyle = 'black';\n ctx.fillRect(0, 0, 256, 256);\n \n const gradient = ctx.createRadialGradient(128, 128, 5, 128, 128, 80);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.5)'); // Stronger middle\n gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');\n \n ctx.fillStyle = gradient;\n ctx.beginPath();\n ctx.arc(128, 128, 100, 0, Math.PI * 2);\n ctx.fill();\n \n console.log('Generated spotlight texture with stronger center');\n } else if (textureType === 'softlight') {\n // Create a more pronounced soft light effect\n const gradient = ctx.createLinearGradient(0, 0, 256, 256);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.7, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'rgba(80, 80, 80, 1)');\n \n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, 256, 256);\n \n console.log('Generated enhanced softlight texture');\n } else {\n // Default - create a more pronounced radial gradient\n const gradient = ctx.createRadialGradient(128, 128, 10, 128, 128, 160);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.6, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'black');\n \n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, 256, 256);\n \n console.log('Generated enhanced default texture');\n }\n \n // Create a texture from the canvas\n const lightMapTexture = Texture.from(canvas);\n console.log('Created lightmap texture from canvas');\n \n // Parse color from hex string with safer parsing\n let color;\n try {\n // Handle potential bad color input\n if (typeof colorValue === 'string' && colorValue.startsWith('#')) {\n color = parseInt(colorValue.replace('#', '0x'), 16);\n } else {\n color = 0x000000; // Default black\n }\n } catch (e) {\n console.warn('Error parsing color, using default black');\n color = 0x000000;\n }\n \n // Create filter with proper options\n const filter = new SimpleLightmapFilter(lightMapTexture, color, alphaValue);\n \n // Store custom parameters for reference\n (filter as any)._customParams = {\n textureType: textureType,\n color: colorValue,\n alpha: alphaValue\n };\n \n // Add custom updateUIParam method with improved parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n try {\n console.log(`SimpleLightmapFilter.updateUIParam called: ${key} = ${value}`);\n \n // Store UI parameters for reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update stored params\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'textureType':\n customParams.textureType = value;\n \n // Create a new canvas with the selected texture type\n const updateCanvas = document.createElement('canvas');\n updateCanvas.width = 256;\n updateCanvas.height = 256;\n const updateCtx = updateCanvas.getContext('2d');\n \n if (updateCtx) {\n // Generate texture based on type with stronger effects\n if (value === 'spotlight') {\n updateCtx.fillStyle = 'black';\n updateCtx.fillRect(0, 0, 256, 256);\n \n const gradient = updateCtx.createRadialGradient(128, 128, 5, 128, 128, 80);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.5)');\n gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');\n \n updateCtx.fillStyle = gradient;\n updateCtx.beginPath();\n updateCtx.arc(128, 128, 100, 0, Math.PI * 2);\n updateCtx.fill();\n } else if (value === 'softlight') {\n const gradient = updateCtx.createLinearGradient(0, 0, 256, 256);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.7, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'rgba(80, 80, 80, 1)');\n \n updateCtx.fillStyle = gradient;\n updateCtx.fillRect(0, 0, 256, 256);\n } else {\n const gradient = updateCtx.createRadialGradient(128, 128, 10, 128, 128, 160);\n gradient.addColorStop(0, 'white');\n gradient.addColorStop(0.3, 'rgba(220, 220, 220, 1)');\n gradient.addColorStop(0.6, 'rgba(150, 150, 150, 1)');\n gradient.addColorStop(1, 'black');\n \n updateCtx.fillStyle = gradient;\n updateCtx.fillRect(0, 0, 256, 256);\n }\n \n // Create a new texture\n const newTexture = Texture.from(updateCanvas);\n \n // Update the filter - directly access the property\n this.lightMap = newTexture;\n \n // Force the filter to redraw by invalidating the transform\n if (this.enabled !== undefined) {\n // Toggle enabled to force a redraw\n const wasEnabled = this.enabled;\n this.enabled = false;\n setTimeout(() => {\n this.enabled = wasEnabled;\n }, 0);\n }\n \n console.log(`Updated lightMap texture to ${value} type`);\n }\n break;\n \n case 'color':\n // Store the hex color for reference\n customParams.color = value;\n // Convert hex color string to number for the filter with safe parsing\n try {\n if (typeof value === 'string' && value.startsWith('#')) {\n this.color = parseInt(value.replace('#', '0x'), 16);\n } else {\n this.color = 0x000000; // Default black\n }\n } catch (e) {\n this.color = 0x000000;\n }\n console.log(`Updated color to ${value} (${this.color})`);\n break;\n \n case 'alpha':\n // Directly set the alpha value - this is the intensity of the effect\n this.alpha = Number(value);\n \n // Log the actual value for debugging\n console.log(`Updated alpha to ${this.alpha}, actual filter:`, {\n alpha: this.alpha,\n color: this.color,\n hasLightmap: !!this.lightMap\n });\n break;\n \n // For any other properties, try direct assignment\n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Unknown parameter for SimpleLightmapFilter: ${key}`);\n }\n break;\n }\n } catch (error) {\n console.error(`Error updating SimpleLightmapFilter parameter ${key}:`, error);\n }\n };\n \n // Log the created filter properties for debugging\n console.log('SimpleLightmapFilter created successfully:', {\n alpha: filter.alpha,\n color: filter.color,\n hasLightmap: !!filter.lightMap\n });\n \n return filter;\n } catch (error) {\n console.error('Failed to create SimpleLightmapFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n textureType: 'default',\n color: '#000000', // Ambient color (black typically)\n alpha: 1 // Coefficient for alpha multiplication\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'textureType',\n type: 'select',\n label: 'Light Map Type',\n property: 'textureType',\n options: [\n { label: 'Default', value: 'default' },\n { label: 'Spotlight', value: 'spotlight' },\n { label: 'Soft Light', value: 'softlight' }\n ],\n default: 'default',\n },\n {\n id: 'color',\n type: 'color',\n label: 'Ambient Color',\n property: 'color',\n default: '#000000',\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Intensity', // Renamed from Alpha to Intensity for clarity\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n }\n ],\n});","/**\n * Noise Filter Definition\n * Adds random noise to the image\n */\nimport { registerFilter } from '../registry';\n// Import directly from PixiJS (not pixi-filters) as this is a built-in filter\n// Import from pixi.js with namespace\nimport * as PIXI from 'pixi.js';\n// @ts-ignore - Module structure doesn't match TypeScript definitions\nconst { NoiseFilter } = PIXI;;\n\nexport default registerFilter({\n id: 'noise',\n name: 'Noise',\n category: 'effects',\n description: 'Add random noise to the image',\n \n createFilter: (params) => {\n try {\n console.log('Creating NoiseFilter with params:', params);\n \n // Create the filter with direct options\n const filter = new NoiseFilter({\n noise: params.noise || 0.5,\n seed: params.seed || Math.random()\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Set up animation loop for randomizing seed if animation is enabled\n let animationFrameId: number | null = null;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update with a new random seed for animation\n filter.seed = Math.random();\n }\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if enabled\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if not already running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'noise':\n // Update noise amount (with validation) - PIXI NoiseFilter expects 0-1 range\n this.noise = Math.max(0, Math.min(1, value));\n break;\n \n case 'seed':\n // Only update seed manually if not animating\n if (!(this as any).animating) {\n this.seed = value;\n }\n break;\n \n case 'randomizeSeed':\n // Button action to randomize seed\n if (value) {\n this.seed = Math.random();\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create NoiseFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n noise: 0.5,\n seed: 0.5,\n animating: false,\n randomizeSeed: false\n },\n \n controls: [\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Noise',\n property: 'animating',\n default: false\n },\n {\n id: 'noise',\n type: 'slider',\n label: 'Noise Amount',\n property: 'noise',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'seed',\n type: 'slider',\n label: 'Random Seed',\n property: 'seed',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Seed',\n action: 'randomizeSeed'\n }\n ]\n});","/**\n * Old Film Filter Definition\n * Applies a vintage film effect with sepia tone, scratches, grain, and vignetting\n */\nimport { registerFilter } from '../registry';\n// Import the OldFilmFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { OldFilmFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'old-film',\n name: 'Old Film',\n category: 'effects',\n description: 'Apply a vintage film effect with scratches and grain',\n \n createFilter: (params) => {\n try {\n console.log('Creating OldFilmFilter with params:', params);\n \n // Create the filter with direct options\n const filter = new OldFilmFilter({\n sepia: params.sepia,\n noise: params.noise,\n noiseSize: params.noiseSize,\n scratch: params.scratch,\n scratchDensity: params.scratchDensity,\n scratchWidth: params.scratchWidth,\n vignetting: params.vignetting,\n vignettingAlpha: params.vignettingAlpha,\n vignettingBlur: params.vignettingBlur,\n seed: params.seed || Math.random()\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Set up animation loop for randomizing seed if animation is enabled\n let animationFrameId: number | null = null;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update with a new random seed for animation\n filter.seed = Math.random();\n }\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if enabled\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if not already running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'seed':\n // Only update seed manually if not animating\n if (!(this as any).animating) {\n this.seed = value;\n }\n break;\n \n case 'randomizeSeed':\n // Button action to randomize seed\n if (value) {\n this.seed = Math.random();\n }\n break;\n \n // Direct properties that are part of the OldFilmFilter\n case 'sepia':\n case 'noise':\n case 'noiseSize':\n case 'scratch':\n case 'scratchDensity':\n case 'scratchWidth':\n case 'vignetting':\n case 'vignettingAlpha':\n case 'vignettingBlur':\n // Apply with validation if needed\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create OldFilmFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n sepia: 0.3,\n noise: 0.3,\n noiseSize: 1,\n scratch: 0.5,\n scratchDensity: 0.3,\n scratchWidth: 1,\n vignetting: 0.3,\n vignettingAlpha: 1,\n vignettingBlur: 0.3,\n seed: 0.5,\n animating: false,\n randomizeSeed: false\n },\n \n controls: [\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Film',\n property: 'animating',\n default: false\n },\n {\n id: 'sepia',\n type: 'slider',\n label: 'Sepia Tone',\n property: 'sepia',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'noise',\n type: 'slider',\n label: 'Noise Amount',\n property: 'noise',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'noiseSize',\n type: 'slider',\n label: 'Noise Size',\n property: 'noiseSize',\n min: 1,\n max: 10,\n step: 0.1,\n default: 1\n },\n {\n id: 'scratch',\n type: 'slider',\n label: 'Scratch Amount',\n property: 'scratch',\n min: -1,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'scratchDensity',\n type: 'slider',\n label: 'Scratch Density',\n property: 'scratchDensity',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'scratchWidth',\n type: 'slider',\n label: 'Scratch Width',\n property: 'scratchWidth',\n min: 1,\n max: 20,\n step: 1,\n default: 1\n },\n {\n id: 'vignetting',\n type: 'slider',\n label: 'Vignette Size',\n property: 'vignetting',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'vignettingAlpha',\n type: 'slider',\n label: 'Vignette Opacity',\n property: 'vignettingAlpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1\n },\n {\n id: 'vignettingBlur',\n type: 'slider',\n label: 'Vignette Blur',\n property: 'vignettingBlur',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.3\n },\n {\n id: 'seed',\n type: 'slider',\n label: 'Random Seed',\n property: 'seed',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Seed',\n action: 'randomizeSeed'\n }\n ]\n});","/**\n * Outline Filter Definition\n * Adds an outline/stroke around the image\n */\nimport { registerFilter } from '../registry';\n// Import the OutlineFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { OutlineFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'outline',\n name: 'Outline',\n category: 'effects',\n description: 'Add an outline or stroke around the image',\n \n createFilter: (params) => {\n try {\n console.log('Creating OutlineFilter with params:', params);\n \n // Parse color from hex string if needed\n let color = params.color;\n if (typeof color === 'string') {\n color = parseInt(color.replace('#', '0x'), 16);\n }\n \n // Create the filter with direct options\n const filter = new OutlineFilter({\n thickness: params.thickness || 4,\n color: color,\n alpha: params.alpha || 1,\n quality: params.quality || 0.1,\n knockout: params.knockout || false\n });\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for UI parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'thickness':\n // Apply with validation (non-negative)\n this.thickness = Math.max(0, value);\n break;\n \n case 'color':\n // Handle color in different formats\n if (typeof value === 'string') {\n // Convert hex string to number\n this.color = parseInt(value.replace('#', '0x'), 16);\n customParams.color = value; // Store the string version for UI\n } else {\n // Direct numeric assignment\n this.color = value;\n }\n break;\n \n case 'alpha':\n // Apply with validation (0-1 range)\n this.alpha = Math.max(0, Math.min(1, value));\n break;\n \n case 'quality':\n // Apply with validation (0.01-1 range for performance reasons)\n this.quality = Math.max(0.01, Math.min(1, value));\n break;\n \n case 'knockout':\n // Boolean toggle\n this.knockout = !!value;\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create OutlineFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n thickness: 4,\n color: '#000000',\n alpha: 1,\n quality: 0.1,\n knockout: false\n },\n \n controls: [\n {\n id: 'thickness',\n type: 'slider',\n label: 'Thickness',\n property: 'thickness',\n min: 0,\n max: 20,\n step: 0.1,\n default: 4\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#000000'\n },\n {\n id: 'alpha',\n type: 'slider',\n label: 'Alpha',\n property: 'alpha',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1\n },\n {\n id: 'quality',\n type: 'slider',\n label: 'Quality',\n property: 'quality',\n min: 0.01,\n max: 1,\n step: 0.01,\n default: 0.1,\n tooltip: 'Higher values give better quality but slower performance'\n },\n {\n id: 'knockout',\n type: 'toggle',\n label: 'Outline Only',\n property: 'knockout',\n default: false,\n tooltip: 'Only show the outline, not the image content'\n }\n ]\n});","/**\n * Pixelate Filter Definition\n * Creates a pixelated mosaic effect by reducing the resolution in specific areas\n */\nimport { registerFilter } from '../registry';\n// Import the PixelateFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { PixelateFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'pixelate',\n name: 'Pixelate',\n category: 'effects',\n description: 'Create a pixelated or mosaic effect',\n \n createFilter: (params) => {\n try {\n console.log('Creating PixelateFilter with params:', params);\n \n // Create the filter with correct parameters\n // If separate X and Y values are provided, use them\n // Otherwise, use a single size value for both dimensions\n const filter = new PixelateFilter(\n params.useUniform \n ? Math.max(4, params.size || 10) \n : [Math.max(4, params.sizeX || 10), Math.max(4, params.sizeY || 10)]\n );\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'useUniform':\n // Toggle between uniform (single value) or separate x/y values\n customParams.useUniform = value;\n if (value) {\n // Switch to uniform size - use average of X and Y\n const avgSize = Math.round((this.sizeX + this.sizeY) / 2);\n this.size = Math.max(4, avgSize);\n customParams.size = avgSize;\n } else {\n // Switch to separate values - use current size for both\n const currentSize = Array.isArray(this.size) ? this.size[0] : this.size;\n this.sizeX = Math.max(4, currentSize);\n this.sizeY = Math.max(4, currentSize);\n customParams.sizeX = this.sizeX;\n customParams.sizeY = this.sizeY;\n }\n break;\n \n case 'size':\n // Update uniform size (both X and Y the same)\n if (customParams.useUniform) {\n this.size = Math.max(4, value);\n }\n break;\n \n case 'sizeX':\n // Update only X dimension\n if (!customParams.useUniform) {\n this.sizeX = Math.max(4, value);\n }\n break;\n \n case 'sizeY':\n // Update only Y dimension\n if (!customParams.useUniform) {\n this.sizeY = Math.max(4, value);\n }\n break;\n \n default:\n // For any other properties that might exist on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create PixelateFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n useUniform: true,\n size: 10,\n sizeX: 10,\n sizeY: 10\n },\n \n controls: [\n {\n id: 'useUniform',\n type: 'toggle',\n label: 'Uniform Pixels',\n property: 'useUniform',\n default: true,\n tooltip: 'Use the same size for both X and Y dimensions'\n },\n {\n id: 'size',\n type: 'slider',\n label: 'Pixel Size',\n property: 'size',\n min: 4,\n max: 40,\n step: 1,\n default: 10,\n tooltip: 'Size of the pixels in both dimensions'\n },\n {\n id: 'sizeX',\n type: 'slider',\n label: 'Horizontal Size',\n property: 'sizeX',\n min: 4,\n max: 40,\n step: 1,\n default: 10,\n tooltip: 'Size of the pixels in the horizontal direction'\n },\n {\n id: 'sizeY',\n type: 'slider',\n label: 'Vertical Size',\n property: 'sizeY',\n min: 4,\n max: 40,\n step: 1,\n default: 10,\n tooltip: 'Size of the pixels in the vertical direction'\n }\n ]\n});","/**\n * Reflection Filter Definition\n * Creates a water reflection effect with configurable waves\n */\nimport { registerFilter } from '../registry';\n// Import the ReflectionFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { ReflectionFilter } = PixiFilters;;\n\n// Register the Reflection filter\nexport default registerFilter({\n id: 'reflection', // ID must match what the application expects\n name: 'Reflection',\n category: 'distortion',\n description: 'Creates a water reflection effect with configurable waves',\n \n // Create an instance of the ReflectionFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating ReflectionFilter with params:', params);\n \n // Extract parameters with defaults\n const options = {\n mirror: params.mirror ?? true,\n boundary: params.boundary ?? 0.5,\n amplitude: new Float32Array([params.amplitudeStart ?? 0, params.amplitudeEnd ?? 20]),\n waveLength: new Float32Array([params.wavelengthStart ?? 30, params.wavelengthEnd ?? 100]),\n alpha: new Float32Array([params.alphaStart ?? 1, params.alphaEnd ?? 1]),\n time: params.time ?? 0\n };\n\n // Create the filter with PixiJS v8 style options object\n const filter = new ReflectionFilter(options as any);\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n // Add an animating flag for potential animation support\n (filter as any).animating = params.animating ?? false;\n \n /**\n * Custom method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'mirror':\n case 'boundary':\n case 'time':\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n break;\n \n case 'amplitudeStart':\n if (!Array.isArray(this.amplitude)) {\n this.amplitude = [0, this._customParams.amplitudeEnd || 20];\n }\n this.amplitude[0] = value;\n console.log(`Updated amplitude[0] to ${value}`);\n break;\n \n case 'amplitudeEnd':\n if (!Array.isArray(this.amplitude)) {\n this.amplitude = [this._customParams.amplitudeStart || 0, 20];\n }\n this.amplitude[1] = value;\n console.log(`Updated amplitude[1] to ${value}`);\n break;\n \n case 'wavelengthStart':\n if (!Array.isArray(this.waveLength)) {\n this.waveLength = [30, this._customParams.wavelengthEnd || 100];\n }\n this.waveLength[0] = value;\n console.log(`Updated waveLength[0] to ${value}`);\n break;\n \n case 'wavelengthEnd':\n if (!Array.isArray(this.waveLength)) {\n this.waveLength = [this._customParams.wavelengthStart || 30, 100];\n }\n this.waveLength[1] = value;\n console.log(`Updated waveLength[1] to ${value}`);\n break;\n \n case 'alphaStart':\n if (!Array.isArray(this.alpha)) {\n this.alpha = [1, this._customParams.alphaEnd || 1];\n }\n this.alpha[0] = value;\n console.log(`Updated alpha[0] to ${value}`);\n break;\n \n case 'alphaEnd':\n if (!Array.isArray(this.alpha)) {\n this.alpha = [this._customParams.alphaStart || 1, 1];\n }\n this.alpha[1] = value;\n console.log(`Updated alpha[1] to ${value}`);\n break;\n \n case 'animating':\n (this as any).animating = value;\n console.log(`Updated animating to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ReflectionFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ReflectionFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n mirror: true,\n boundary: 0.5,\n amplitudeStart: 0,\n amplitudeEnd: 20,\n wavelengthStart: 30,\n wavelengthEnd: 100,\n alphaStart: 1,\n alphaEnd: 1,\n time: 0,\n animating: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'mirror',\n type: 'toggle',\n label: 'Mirror Image',\n property: 'mirror',\n default: true,\n },\n {\n id: 'boundary',\n type: 'slider',\n label: 'Boundary Line',\n property: 'boundary',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'amplitudeStart',\n type: 'slider',\n label: 'Wave Height (Start)',\n property: 'amplitudeStart',\n min: 0,\n max: 50,\n step: 1,\n default: 0,\n },\n {\n id: 'amplitudeEnd',\n type: 'slider',\n label: 'Wave Height (End)',\n property: 'amplitudeEnd',\n min: 0,\n max: 50,\n step: 1,\n default: 20,\n },\n {\n id: 'wavelengthStart',\n type: 'slider',\n label: 'Wave Length (Start)',\n property: 'wavelengthStart',\n min: 10,\n max: 200,\n step: 1,\n default: 30,\n },\n {\n id: 'wavelengthEnd',\n type: 'slider',\n label: 'Wave Length (End)',\n property: 'wavelengthEnd',\n min: 10,\n max: 200,\n step: 1,\n default: 100,\n },\n {\n id: 'alphaStart',\n type: 'slider',\n label: 'Opacity (Start)',\n property: 'alphaStart',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'alphaEnd',\n type: 'slider',\n label: 'Opacity (End)',\n property: 'alphaEnd',\n min: 0,\n max: 1,\n step: 0.01,\n default: 1,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Animation Time',\n property: 'time',\n min: 0,\n max: 10,\n step: 0.1,\n default: 0,\n },\n {\n id: 'animating',\n type: 'toggle',\n label: 'Auto Animate',\n property: 'animating',\n default: false,\n }\n ],\n});","/**\n * Shockwave Filter Definition\n * Creates a rippling shockwave effect\n */\nimport { registerFilter } from '../registry';\n// Import the ShockwaveFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { ShockwaveFilter } = PixiFilters;;\n\n// Register the Shockwave filter\nexport default registerFilter({\n id: 'shockwave', // ID must match what the application expects\n name: 'Shockwave',\n category: 'distortion',\n description: 'Creates a rippling shockwave or blast wave effect',\n \n // Create an instance of the ShockwaveFilter with the provided parameters\n createFilter: (params) => {\n try {\n console.log('Creating ShockwaveFilter with params:', params);\n \n // Extract parameters with defaults\n const centerX = params.centerX ?? 0.5;\n const centerY = params.centerY ?? 0.5;\n const center = { x: centerX, y: centerY };\n const amplitude = params.amplitude ?? 30;\n const wavelength = params.wavelength ?? 160;\n const speed = params.speed ?? 500;\n const brightness = params.brightness ?? 1;\n const radius = params.radius ?? -1;\n const time = params.time ?? 0;\n \n // Create the filter with PixiJS v8 style options object\n const filter = new ShockwaveFilter({\n center,\n amplitude,\n wavelength,\n speed,\n brightness,\n radius,\n time\n });\n \n // Store custom parameters for later reference\n (filter as any)._customParams = { ...params };\n \n // Add an animating flag for potential animation support\n (filter as any).animating = params.animating ?? false;\n \n /**\n * Custom method to handle UI parameter updates\n * This is called by PixiApplication.updateFilter when UI controls change\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store UI parameters for later reference\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n \n // Update the stored params value\n customParams[key] = value;\n \n // Handle parameter updates based on key\n switch (key) {\n case 'centerX':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.x = value;\n console.log(`Updated center.x to ${value}`);\n break;\n \n case 'centerY':\n if (!this.center) this.center = { x: 0.5, y: 0.5 };\n this.center.y = value;\n console.log(`Updated center.y to ${value}`);\n break;\n \n case 'amplitude':\n case 'wavelength':\n case 'speed':\n case 'brightness':\n case 'radius':\n case 'time':\n this[key] = value;\n console.log(`Updated ${key} to ${value}`);\n break;\n \n case 'animating':\n (this as any).animating = value;\n console.log(`Updated animating to ${value}`);\n break;\n \n // For any other properties, try direct assignment \n default:\n if (key in this) {\n (this as any)[key] = value;\n console.log(`Updated ${key} to ${value}`);\n } else {\n console.warn(`Attempted to update unknown property ${key}`);\n }\n break;\n }\n \n return true;\n };\n \n console.log('ShockwaveFilter created successfully with updateUIParam method');\n return filter;\n } catch (error) {\n console.error('Failed to create ShockwaveFilter:', error);\n return null;\n }\n },\n \n // Default parameter values\n defaultParams: {\n centerX: 0.5,\n centerY: 0.5,\n amplitude: 30,\n wavelength: 160,\n speed: 500,\n brightness: 1,\n radius: -1,\n time: 0,\n animating: false\n },\n \n // UI controls for the filter\n controls: [\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n },\n {\n id: 'amplitude',\n type: 'slider',\n label: 'Amplitude',\n property: 'amplitude',\n min: 0,\n max: 100,\n step: 1,\n default: 30,\n },\n {\n id: 'wavelength',\n type: 'slider',\n label: 'Wavelength',\n property: 'wavelength',\n min: 10,\n max: 500,\n step: 1,\n default: 160,\n },\n {\n id: 'speed',\n type: 'slider',\n label: 'Speed',\n property: 'speed',\n min: 1,\n max: 1000,\n step: 10,\n default: 500,\n },\n {\n id: 'brightness',\n type: 'slider',\n label: 'Brightness',\n property: 'brightness',\n min: 0,\n max: 5,\n step: 0.1,\n default: 1,\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Max Radius',\n property: 'radius',\n min: -1,\n max: 1000,\n step: 10,\n default: -1,\n },\n {\n id: 'time',\n type: 'slider',\n label: 'Time',\n property: 'time',\n min: 0,\n max: 5,\n step: 0.1,\n default: 0,\n },\n {\n id: 'animating',\n type: 'toggle',\n label: 'Auto Animate',\n property: 'animating',\n default: false,\n }\n ],\n});","/**\n * Simplex Noise Filter Definition\n * Applies procedural noise to create various texture effects\n */\nimport { registerFilter } from '../registry';\n// Import the SimplexNoiseFilter directly from pixi-filters package\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { SimplexNoiseFilter } = PixiFilters;;\n\nexport default registerFilter({\n id: 'simplex-noise',\n name: 'Simplex Noise',\n category: 'effects',\n description: 'Apply procedural noise to create texture effects',\n \n createFilter: (params) => {\n try {\n console.log('Creating SimplexNoiseFilter with params:', params);\n \n // Use params.time for animation if this is enabled\n const zOffset = params.animating ? 0 : (params.offsetZ || 0);\n \n // Create the filter with direct options\n const filter = new SimplexNoiseFilter({\n strength: params.strength,\n noiseScale: params.noiseScale,\n offsetX: params.offsetX,\n offsetY: params.offsetY,\n offsetZ: zOffset,\n step: params.step\n });\n \n // Store animation state\n (filter as any).animating = params.animating || false;\n (filter as any).animationSpeed = params.animationSpeed || 0.01;\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Set up animation loop for changing the Z offset over time\n let animationFrameId: number | null = null;\n let currentTime = 0;\n \n const animate = () => {\n if ((filter as any).animating) {\n // Update the Z offset over time for animation\n currentTime += (filter as any).animationSpeed;\n filter.offsetZ = currentTime;\n }\n animationFrameId = requestAnimationFrame(animate);\n };\n \n // Start animation if enabled\n if ((filter as any).animating) {\n animationFrameId = requestAnimationFrame(animate);\n }\n \n // Method to clean up animation when filter is destroyed\n (filter as any)._stopAnimation = () => {\n if (animationFrameId !== null) {\n cancelAnimationFrame(animationFrameId);\n animationFrameId = null;\n }\n };\n \n /**\n * Add custom updateUIParam method for UI parameter handling\n */\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'animating':\n // Toggle animation state\n (this as any).animating = value;\n if (value && !animationFrameId) {\n // Start animation if not already running\n animationFrameId = requestAnimationFrame(animate);\n }\n break;\n \n case 'animationSpeed':\n // Update animation speed\n (this as any).animationSpeed = value;\n break;\n \n case 'offsetZ':\n // Only update Z offset manually if not animating\n if (!(this as any).animating) {\n this.offsetZ = value;\n }\n break;\n \n case 'randomizeSeed':\n // Randomize all offsets for a new pattern\n if (value) {\n const randomValue = () => Math.random() * 100 - 50;\n this.offsetX = randomValue();\n this.offsetY = randomValue();\n this.offsetZ = randomValue();\n \n // Update stored values\n customParams.offsetX = this.offsetX;\n customParams.offsetY = this.offsetY;\n customParams.offsetZ = this.offsetZ;\n }\n break;\n \n // Direct properties that exist on the filter\n case 'strength':\n case 'noiseScale':\n case 'offsetX':\n case 'offsetY':\n case 'step':\n // Apply with any needed validation\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n \n default:\n // For any other properties that might exist on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create SimplexNoiseFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n strength: 0.5,\n noiseScale: 10.0,\n offsetX: 0,\n offsetY: 0,\n offsetZ: 0,\n step: -1,\n animating: false,\n animationSpeed: 0.01,\n randomizeSeed: false\n },\n \n controls: [\n {\n id: 'strength',\n type: 'slider',\n label: 'Noise Strength',\n property: 'strength',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5\n },\n {\n id: 'noiseScale',\n type: 'slider',\n label: 'Noise Scale',\n property: 'noiseScale',\n min: 1,\n max: 50,\n step: 0.5,\n default: 10.0\n },\n {\n id: 'offsetX',\n type: 'slider',\n label: 'X Offset',\n property: 'offsetX',\n min: -50,\n max: 50,\n step: 0.5,\n default: 0\n },\n {\n id: 'offsetY',\n type: 'slider',\n label: 'Y Offset',\n property: 'offsetY',\n min: -50,\n max: 50,\n step: 0.5,\n default: 0\n },\n {\n id: 'offsetZ',\n type: 'slider',\n label: 'Z Offset',\n property: 'offsetZ',\n min: -50,\n max: 50,\n step: 0.5,\n default: 0\n },\n {\n id: 'step',\n type: 'slider',\n label: 'Step Threshold',\n property: 'step',\n min: -1,\n max: 1,\n step: 0.01,\n default: -1,\n tooltip: 'Values above 0 create a blocky effect'\n },\n {\n id: 'animating',\n type: 'toggle',\n label: 'Animate Noise',\n property: 'animating',\n default: false\n },\n {\n id: 'animationSpeed',\n type: 'slider',\n label: 'Animation Speed',\n property: 'animationSpeed',\n min: 0.001,\n max: 0.05,\n step: 0.001,\n default: 0.01\n },\n {\n id: 'randomizeSeed',\n type: 'button',\n label: 'Randomize Pattern',\n action: 'randomizeSeed'\n }\n ]\n});","/**\n * Twist Filter Definition\n *\n * Uses pixi-filters' built-in TwistFilter. The previous custom shader\n * worked in PIXI v7 but silently rendered transparent in PIXI v8 because\n * its vertex shader set `vTextureCoord = aPosition`, which isn't how v8's\n * filter pipeline computes texture coordinates.\n *\n * UI keeps normalized [0,1] inputs for centerX/centerY/radius so they're\n * intuitive across any image size. The filter factory converts those to\n * pixel-space offset/radius using the source image dimensions threaded\n * through `params._sourceWidth/_sourceHeight` by FilterManager.\n */\nimport { registerFilter } from '../registry';\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore — pixi-filters lacks first-class TypeScript types here\nconst { TwistFilter } = PixiFilters;\n\nconst computeTwistPadding = (radiusPx: number): number => {\n // Twist displaces pixels within the radius; extend the render area a bit\n // so edge fringes don't clip when the twist center is near the boundary.\n return Math.ceil(Math.max(0, Number(radiusPx) || 0) + 2);\n};\n\ninterface TwistParams {\n centerX?: number;\n centerY?: number;\n /** Radius as a fraction of the smaller image edge, 0-1. */\n radius?: number;\n /** Twist angle in radians. */\n angle?: number;\n _sourceWidth?: number;\n _sourceHeight?: number;\n}\n\nconst buildTwistFilter = (raw: TwistParams, previewToNativeScale = 1) => {\n const width = Math.max(1, Number(raw._sourceWidth ?? 0));\n const height = Math.max(1, Number(raw._sourceHeight ?? 0));\n const minEdge = Math.min(width, height);\n\n const centerX = Number(raw.centerX ?? 0.5);\n const centerY = Number(raw.centerY ?? 0.5);\n const normalizedRadius = Number(raw.radius ?? 0.25);\n const angle = Number(raw.angle ?? 4);\n\n // Normalized (0-1) → pixels. Center is in the filter area's coord space;\n // pixi-filters TwistFilter's offset is in pixels relative to (0,0) of\n // the filter area. We also scale by previewToNativeScale so exports at\n // higher resolution keep the same visual radius.\n const offsetX = centerX * width * previewToNativeScale;\n const offsetY = centerY * height * previewToNativeScale;\n const radiusPx = normalizedRadius * minEdge * previewToNativeScale;\n\n const filter = new TwistFilter({\n offset: { x: offsetX, y: offsetY },\n radius: radiusPx,\n angle,\n });\n\n // Reserve padding so the twist fringe doesn't clip when centered near\n // the sprite edge. Matches the drop-shadow / bulge-pinch pattern.\n const padding = computeTwistPadding(radiusPx);\n filter.padding = Math.max(filter.padding ?? 0, padding);\n (filter as any)._exportPadding = padding;\n\n return filter;\n};\n\nexport default registerFilter({\n id: 'twist',\n name: 'Twist',\n category: 'distortion',\n description: 'Creates a twisting distortion effect around a central point',\n\n createFilter: (params) => {\n try {\n const raw: TwistParams = {\n centerX: params.centerX ?? 0.5,\n centerY: params.centerY ?? 0.5,\n radius: params.radius ?? 0.25,\n angle: params.angle ?? 4,\n _sourceWidth: params._sourceWidth,\n _sourceHeight: params._sourceHeight,\n };\n\n const filter = buildTwistFilter(raw, 1);\n (filter as any)._customParams = { ...raw };\n\n (filter as any).updateUIParam = function (key: string, value: unknown) {\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n\n // Twist params are coupled (center → offset in pixels using dims,\n // radius → px using min edge). Recompute all uniforms whenever any\n // slider moves rather than mapping per-key.\n const width = Math.max(1, Number(customParams._sourceWidth ?? 0));\n const height = Math.max(1, Number(customParams._sourceHeight ?? 0));\n const minEdge = Math.min(width, height);\n const centerX = Number(customParams.centerX ?? 0.5);\n const centerY = Number(customParams.centerY ?? 0.5);\n const normalizedRadius = Number(customParams.radius ?? 0.25);\n const angle = Number(customParams.angle ?? 4);\n\n if (this.offset) {\n this.offset.x = centerX * width;\n this.offset.y = centerY * height;\n }\n this.radius = normalizedRadius * minEdge;\n this.angle = angle;\n\n const padding = computeTwistPadding(this.radius);\n (this as any)._exportPadding = padding;\n this.padding = Math.max(this.padding ?? 0, padding);\n return true;\n };\n\n (filter as any).createExportFilter = function (options: { previewToNativeScale?: number } = {}) {\n const scale = Number.isFinite(options.previewToNativeScale)\n ? Math.max(1, Number(options.previewToNativeScale))\n : 1;\n const stored: TwistParams = (this as any)._customParams || raw;\n return buildTwistFilter(stored, scale);\n };\n\n (filter as any).getExportPadding = function () {\n return Number((this as any)._exportPadding || this.padding || 0);\n };\n\n return filter;\n } catch (error) {\n console.error('Failed to create TwistFilter:', error);\n return null;\n }\n },\n\n // Default parameter values — normalized (0-1) for intuitive slider use.\n defaultParams: {\n centerX: 0.5,\n centerY: 0.5,\n radius: 0.25,\n angle: 4,\n },\n\n controls: [\n {\n id: 'angle',\n type: 'slider',\n label: 'Angle',\n property: 'angle',\n min: -10,\n max: 10,\n step: 0.1,\n default: 4,\n tooltip: 'Amount of twisting (positive is clockwise)',\n },\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: 0.05,\n max: 0.75,\n step: 0.01,\n default: 0.25,\n tooltip: 'Size of the twist effect (relative to image)',\n },\n {\n id: 'centerX',\n type: 'slider',\n label: 'Center X',\n property: 'centerX',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n tooltip: 'Horizontal position of twist center',\n },\n {\n id: 'centerY',\n type: 'slider',\n label: 'Center Y',\n property: 'centerY',\n min: 0,\n max: 1,\n step: 0.01,\n default: 0.5,\n tooltip: 'Vertical position of twist center',\n },\n ],\n});\n","/**\n * Vignette Filter Definition\n * Adds a classic darkened border effect to the image\n * \n * NOTE: This is a CUSTOM implementation as pixi-filters does not provide a VignetteFilter.\n * It uses AdjustmentFilter to simulate a vignette effect by manipulating brightness/contrast.\n * This is not a true radial gradient vignette but provides a similar visual effect.\n */\nimport { registerFilter } from '../registry';\n// Import from pixi-filters with wildcard and destructuring pattern\nimport * as PixiFilters from 'pixi-filters';\n// @ts-ignore - Module lacks TypeScript definitions\nconst { AdjustmentFilter } = PixiFilters;;\n\n/**\n * Helper to convert a hex color value to RGB array\n */\nfunction hexToRgb(hex: number | string): number[] {\n const parsedHex = typeof hex === 'string' ? parseInt(hex.replace('#', '0x'), 16) : hex;\n return [\n ((parsedHex >> 16) & 0xFF) / 255,\n ((parsedHex >> 8) & 0xFF) / 255,\n (parsedHex & 0xFF) / 255\n ];\n}\n\n/**\n * Simple Vignette implementation using AdjustmentFilter\n * \n * This approach simulates a vignette effect by manipulating\n * brightness, contrast and color tint - it's not a true vignette\n * but provides a similar visual effect using stable filter mechanisms.\n */\nclass VignetteFilter extends AdjustmentFilter {\n private _radius: number = 0.8;\n private _strength: number = 1.0;\n private _colorRgb: number[] = [0, 0, 0];\n private _colorValue: string = '#000000';\n\n constructor(options: { radius?: number; strength?: number; color?: number | string } = {}) {\n // Initialize with default adjustment values\n super({\n brightness: 1.0,\n contrast: 1.0,\n saturation: 1.0,\n alpha: 1.0\n });\n \n this._radius = options.radius ?? 0.8;\n this._strength = options.strength ?? 1.0;\n \n // Parse color\n if (options.color !== undefined) {\n if (typeof options.color === 'string') {\n this._colorValue = options.color;\n this._colorRgb = hexToRgb(options.color);\n } else {\n this._colorValue = '#' + options.color.toString(16).padStart(6, '0');\n this._colorRgb = hexToRgb(options.color);\n }\n }\n \n // Apply the initial vignette effect\n this.updateVignette();\n }\n \n /**\n * Updates the filter parameters to simulate a vignette effect\n */\n private updateVignette(): void {\n // Calculate effect intensity based on radius and strength\n // Radius inversely affects strength (higher radius = less effect)\n const radiusFactor = 1 - (this._radius / 2); // Normalize to 0.5-1 range\n const effectiveStrength = this._strength * radiusFactor;\n \n // Darker with higher strength (0.5-1.0 range to avoid making everything black)\n this.brightness = Math.max(0.5, 1.0 - effectiveStrength * 0.5);\n \n // Increase contrast slightly with strength to emphasize the vignette\n this.contrast = 1.0 + (effectiveStrength * 0.2);\n \n // Apply a slight tint in the color direction\n if (this._colorRgb[0] > 0 || this._colorRgb[1] > 0 || this._colorRgb[2] > 0) {\n // Tint RGB based on color and strength\n // Since AdjustmentFilter doesn't have direct tint properties,\n // we can't apply a true color tint, but we can adjust\n // saturation to hint at the color\n this.saturation = 1.0 - (effectiveStrength * 0.3);\n }\n }\n\n // Properties with getters/setters\n get radius(): number { return this._radius; }\n set radius(value: number) { \n this._radius = Math.max(0.1, Math.min(1.5, value));\n this.updateVignette();\n }\n\n get strength(): number { return this._strength; }\n set strength(value: number) { \n this._strength = Math.max(0, Math.min(2, value));\n this.updateVignette();\n }\n\n get color(): string { return this._colorValue; }\n set color(value: number | string) { \n if (typeof value === 'string') {\n this._colorValue = value;\n this._colorRgb = hexToRgb(value);\n } else {\n this._colorValue = '#' + value.toString(16).padStart(6, '0');\n this._colorRgb = hexToRgb(value);\n }\n this.updateVignette();\n }\n}\n\nexport default registerFilter({\n id: 'vignette',\n name: 'Vignette',\n category: 'effects',\n description: 'Add a classic darkened border effect to the image',\n \n createFilter: (params) => {\n try {\n console.log('Creating VignetteFilter with params:', params);\n \n // Create the custom VignetteFilter implementation\n const filter = new VignetteFilter({\n radius: params.radius || 0.8,\n strength: params.strength || 1.0,\n color: params.color || '#000000'\n });\n \n // Store custom params for UI updates\n (filter as any)._customParams = { ...params };\n \n // Add custom updateUIParam method for UI parameter handling\n (filter as any).updateUIParam = function(key: string, value: any) {\n // Store the updated parameter\n const customParams = (this as any)._customParams || {};\n (this as any)._customParams = customParams;\n customParams[key] = value;\n \n switch (key) {\n case 'radius':\n // Apply with validation (0.1-1.5 range for visual quality)\n this.radius = Math.max(0.1, Math.min(1.5, value));\n break;\n \n case 'strength':\n // Apply with validation (non-negative)\n this.strength = Math.max(0, value);\n break;\n \n case 'color':\n // Handle color in different formats\n this.color = value;\n // Store the string version for UI if it's a string\n if (typeof value === 'string') {\n customParams.color = value;\n }\n break;\n \n default:\n // For any other properties that might exist directly on the filter\n if (key in this) {\n (this as any)[key] = value;\n }\n break;\n }\n };\n \n return filter;\n } catch (error) {\n console.error('Failed to create VignetteFilter:', error);\n return null;\n }\n },\n \n defaultParams: {\n radius: 0.8,\n strength: 1.0,\n color: '#000000'\n },\n \n controls: [\n {\n id: 'radius',\n type: 'slider',\n label: 'Radius',\n property: 'radius',\n min: 0.1,\n max: 1.5,\n step: 0.01,\n default: 0.8,\n tooltip: 'Size of the vignette effect (larger values create a smaller vignette)'\n },\n {\n id: 'strength',\n type: 'slider',\n label: 'Strength',\n property: 'strength',\n min: 0,\n max: 2,\n step: 0.01,\n default: 1.0,\n tooltip: 'Intensity of the vignette effect'\n },\n {\n id: 'color',\n type: 'color',\n label: 'Color',\n property: 'color',\n default: '#000000',\n tooltip: 'Color of the vignette (usually black)'\n }\n ]\n});","/**\n * Filters Module Index\n * Exports all filter-related functionality\n */\n\n// First import the functions so they exist in this module's scope\nimport {\n registerFilter,\n getFilter,\n getAllFilters,\n getFiltersByCategory,\n getAllCategories,\n hasFilter,\n unregisterFilter,\n getFiltersByMedia,\n isFilterCompatibleWithMedia,\n getRegisteredFilters,\n registerCorePixiFilters,\n} from './registry';\n\n// Then re-export them for downstream consumers\nexport {\n registerFilter,\n getFilter,\n getAllFilters,\n getFiltersByCategory,\n getAllCategories,\n hasFilter,\n unregisterFilter,\n getFiltersByMedia,\n isFilterCompatibleWithMedia,\n getRegisteredFilters,\n registerCorePixiFilters,\n};\nexport type { FilterDefinition, ControlDefinition, FilterMediaTarget } from './registry';\n\n// Re-export from factory\nexport {\n createFilterInstance,\n createFilterInstances,\n updateFilterParams,\n} from './factory';\nexport type { FilterInstanceConfig } from './factory';\n\n// Re-export from controlMapping\nexport {\n mapControlTypeToComponent,\n validateControlValue,\n generateDefaultParams,\n convertControlValue,\n} from './controlMapping';\n\n// Re-export the canonical recipe → CSS filter translation helpers.\n// These are the single source of truth for converting a VideoRecipe's\n// clip-level filters into a CSS `filter:` value string. Consumers that\n// previously inlined this translation (e.g. app-side video thumbnail\n// previews) should import from here instead.\nexport {\n videoRecipeToCssFilter,\n filterToCssFunction,\n hasUsableFilterPayload,\n recipeHasFilters,\n recipeNoiseAmount,\n resolveFilterType,\n resolveFilterValue,\n resolvedRecipeFilters,\n} from './recipeToCssFilter';\n\n// Import and re-export all filter definitions\n// This ensures all filters are registered when this module is imported\n\n// Basic adjustments\nimport './definitions/adjustment';\nimport './definitions/adjustmentAdvanced';\nimport './definitions/alpha';\nimport './definitions/blur';\nimport './definitions/colorMatrix';\nimport './definitions/colorOverlay';\nimport './definitions/dropShadow';\nimport './definitions/grayscale';\nimport './definitions/hslAdjustment';\n\n// Blur effects\nimport './definitions/kawaseBlur';\nimport './definitions/motionBlur';\nimport './definitions/radialBlur';\nimport './definitions/tiltShift';\nimport './definitions/zoomBlur';\n\n// Color effects\nimport './definitions/colorGradient';\nimport './definitions/colorMap';\nimport './definitions/colorReplace';\nimport './definitions/multiColorReplace';\nimport './definitions/rgbSplit';\n\n// Stylistic effects\nimport './definitions/advancedBloom';\nimport './definitions/ascii';\nimport './definitions/backdropBlur';\nimport './definitions/bevel';\nimport './definitions/bloom';\nimport './definitions/bulgePinch';\nimport './definitions/convolution';\nimport './definitions/crossHatch';\nimport './definitions/crt';\nimport './definitions/displacement';\nimport './definitions/dot';\nimport './definitions/emboss';\nimport './definitions/glitch';\nimport './definitions/glow';\nimport './definitions/godray';\nimport './definitions/lightmap';\nimport './definitions/noise';\nimport './definitions/oldFilm';\nimport './definitions/outline';\nimport './definitions/pixelate';\nimport './definitions/reflection';\nimport './definitions/shockwave';\nimport './definitions/simplexNoise';\nimport './definitions/twist';\nimport './definitions/vignette';\n\n/**\n * Options for initializeFilterRegistry.\n * @property disabled - Filter IDs to remove from the registry after initialization.\n */\ninterface FilterRegistryOptions {\n disabled?: string[];\n}\n\n/**\n * Initialize the filter registry with all available filters.\n *\n * @param options.disabled - Array of filter IDs to remove after registration\n * (e.g., fetched from the server's mediables.pixi_filters.disabled config).\n */\nexport function initializeFilterRegistry(options?: FilterRegistryOptions) {\n try {\n // Just verify functions exist (they should because of proper imports)\n verifyFilterRegistryFunctions();\n\n // Add explicit type annotations to fix TS7034 errors\n let filters: any[] = [];\n let categories: any[] = [];\n\n // First, try to register core filters\n try {\n // Check if any filters have already been registered\n filters = getAllFilters(); // Now we know this function exists\n\n if (filters.length === 0) {\n // Register core filters if none are registered yet\n console.log('No filters found, registering core filters');\n registerCorePixiFilters(); // Now we know this function exists\n }\n } catch (e) {\n console.warn('Error registering core filters:', e);\n }\n\n // Remove disabled filters from the registry\n const disabled = options?.disabled;\n if (Array.isArray(disabled) && disabled.length > 0) {\n let removedCount = 0;\n for (const id of disabled) {\n if (unregisterFilter(id)) {\n removedCount++;\n }\n }\n if (removedCount > 0) {\n console.log(`Removed ${removedCount} disabled filter(s) from registry`);\n }\n }\n\n // Try to get the filters again after registration\n try {\n filters = getAllFilters();\n categories = getAllCategories(); // Now we know this function exists\n } catch (e) {\n console.warn('Error getting filters or categories:', e);\n // Ensure we have valid defaults even after an error\n if (!filters) filters = [] as any[];\n if (!categories) categories = [] as any[];\n }\n\n // Log the initialization status\n console.log(`Filter registry initialized with ${filters.length} filters in ${categories.length} categories`);\n\n // If we have no filters, log a warning\n if (filters.length === 0) {\n console.warn('No filters found in registry. Filter functionality may be limited.');\n }\n\n return filters as any[];\n } catch (error) {\n // Log the error but don't crash\n console.error('Error initializing filter registry:', error);\n\n // Return an empty array to avoid further errors\n return [];\n }\n}\n\n/**\n * Verify that the required filter registry functions exist\n * This is now just for debugging/validation since we're properly importing the functions\n */\nfunction verifyFilterRegistryFunctions() {\n // Just verify functions exist - they should because of the imports\n const missingFunctions = [];\n \n if (typeof getAllFilters !== 'function') missingFunctions.push('getAllFilters');\n if (typeof getAllCategories !== 'function') missingFunctions.push('getAllCategories');\n if (typeof registerCorePixiFilters !== 'function') missingFunctions.push('registerCorePixiFilters');\n \n if (missingFunctions.length > 0) {\n console.warn(`Warning: Some registry functions are still missing: ${missingFunctions.join(', ')}`);\n }\n}\n\n/**\n * Alternative initialization function with a minimal approach\n * Use this if the main initializeFilterRegistry function is having issues\n */\nexport function safeInitializeFilterRegistry() {\n console.warn('Using minimal safeInitializeFilterRegistry implementation');\n \n try {\n // Verify functions exist but don't create fallbacks\n verifyFilterRegistryFunctions();\n \n // Try to use the getAllFilters function to get any existing filters\n const existingFilters = getAllFilters();\n \n if (existingFilters && existingFilters.length > 0) {\n console.log(`Found ${existingFilters.length} existing filters`);\n return Promise.resolve(existingFilters);\n }\n \n // If no existing filters, try one more attempt with registerCorePixiFilters\n try {\n registerCorePixiFilters();\n const registeredFilters = getAllFilters();\n console.log(`Registered ${registeredFilters.length} core filters`);\n return Promise.resolve(registeredFilters);\n } catch (e) {\n console.warn('Error registering core filters:', e);\n }\n \n // If all else fails, return empty array\n console.warn('Filter functionality will be limited');\n return Promise.resolve([]);\n } catch (e) {\n console.error('Error in safeInitializeFilterRegistry:', e);\n return Promise.resolve([]);\n }\n}\n\n/**\n * Simplified factory for creating a minimal filter\n * Returns a no-op filter that won't cause errors but doesn't do anything\n */\nexport function createMinimalFilter(id: string) {\n console.warn(`Creating minimal placeholder filter for: ${id}`);\n \n // Create a more complete filter stub that matches the expected interface\n return {\n id,\n name: id,\n enabled: true,\n // Basic filter methods\n apply: () => {/* No-op */},\n // Properties needed by the UI\n uniforms: {},\n // Custom interface properties\n updateUIParam: (param: string, value: any) => {\n console.log(`Minimal filter ${id} updateUIParam called with ${param}=${value}`);\n return true;\n },\n handleButtonAction: (action: string) => {\n console.log(`Minimal filter ${id} handleButtonAction called with ${action}`);\n return true;\n },\n // Add any other expected properties based on your filter interface\n // This ensures the minimal filter can be used in place of a real filter\n // without causing errors\n reset: () => {/* No-op */},\n // Clone method for deep copying\n clone: () => createMinimalFilter(id),\n // Allow property access with indexing\n [Symbol.toPrimitive]: () => `[Minimal Filter ${id}]`\n };\n}\n"],"names":["EventEmitter","event","callback","listeners","args","wrapper","TEXT_LAYER_FONT_FAMILIES","TEXT_LAYER_BLEND_MODES","DEFAULT_TEXT_BOX","DEFAULT_TEXT_STYLE","DEFAULT_TEXT_EFFECTS","State","key","parts","value","part","old","lastKey","target","filters","filterId","values","crop","_a","document","binding","snapshot","layers","layer","activeLayerId","subjectIndex","subject","rotation","baseTransform","cropState","appliedRect","layerId","index","baseId","existingIds","safeBase","suffix","candidate","filter","expectedLayerId","expected","activeFilters","filterValues","oldSelectedFilter","min","max","fallback","numeric","normalized","box","base","source","style","fontFamily","fontStyle","align","fill","effects","baseEffects","stroke","shadow","glow","backdrop","transform","input","baseText","contentSource","boxSource","_b","styleSource","_c","effectsSource","_d","removedIndex","distance","nextIndex","previousIndex","fromIndex","toIndex","start","end","activeLayer","visible","name","nextName","oldName","sourceLayer","duplicate","oldActiveLayerId","removed","nextActiveLayerId","direction","locked","payload","patch","textPatch","nextLayer","eventName","eventPayload","id","fit","stops","stop","existingIndex","firstSubjectIndex","insertAt","normalizedFill","previousFit","amount","numericAmount","effect","nextActive","enabled","controlId","filterIndex","controls","existing","ctl","prefersDark","createState","categories","isMediaCompatible","definition","registerFilter","getFilter","getAllFilters","registerCorePixiFilters","f","PixiFilters","entry","exportName","FilterClass","params","getFiltersByCategory","category","getAllCategories","hasFilter","unregisterFilter","categoryIds","idx","isFilterCompatibleWithMedia","getRegisteredFilters","originalRegisterFilter","result","AdjustmentFilter","ColorMatrixFilter","PIXI","DEFAULT_ADJUSTMENT_PARAMS","ADJUSTMENT_PARAM_KEYS","toFiniteNumber","parsed","isAdjustmentParamKey","normalizeAdjustmentParams","applyColorMatrixAdjustments","normalizedParams","options","filterWithUI","customParams","numericValue","DEFAULT_ADVANCED_ADJUSTMENT_PARAMS","ADVANCED_ADJUSTMENT_PARAM_KEYS","isAdvancedAdjustmentParamKey","toBoolean","normalizeAdvancedAdjustmentParams","applyAdvancedAdjustments","numericKey","clamp01","n","alpha","applyColorMatrixParams","normalizeParams","raw","MatrixFilterClass","stored","ColorOverlayFilter","colorValue","colorNum","color","angle","blur","quality","offset","computePadding","b","q","offX","offY","kernel","mag","createScaledForExport","rawParams","scale","dist","ang","blr","qual","off","colorStr","next","padding","refreshPadding","p","newOffset","intensity","applyGrayscaleEffect","HslAdjustmentFilter","KawaseBlurFilter","MotionBlurFilter","RadialBlurFilter","TiltShiftFilter","gradientBlur","startX","startY","endX","endY","numValue","ZoomBlurFilter","ColorGradientFilter","hexToInt","hex","intToHex","num","normalizeStopForFilter","hexStopFromFilter","stopsHex","colorStops","action","current","randomColor","a","str","dynamicMatch","indexStr","prop","ColorMapFilterClass","colorMapTexture","ColorReplaceFilter","originalColorValue","targetColorValue","MultiColorReplaceFilter","replacements","original","newReplacements","RGBSplitFilter","red","green","blue","AdvancedBloomFilter","AsciiFilter","size","replaceColor","BackdropBlurFilter","kernelSize","BevelFilter","lightColor","shadowColor","BloomFilter","strengthX","strengthY","resolution","BulgePinchFilter","computeBulgePadding","radius","r","centerX","centerY","strength","scaledRadius","ConvolutionFilter","MATRICES","matrix","presetKey","currentMatrix","newMatrix","CrossHatchFilter","_params","DisplacementFilter","Sprite","Texture","mapUrl","mapTexture","canvas","ctx","i","j","displacementSprite","sprite","newTexture","EmbossFilter","GlitchFilter","FILL_MODES","redOffset","greenOffset","blueOffset","animationFrameId","animate","GlowFilter","GodrayFilter","SimpleLightmapFilter","textureType","alphaValue","gradient","lightMapTexture","updateCanvas","updateCtx","wasEnabled","NoiseFilter","OldFilmFilter","OutlineFilter","PixelateFilter","avgSize","currentSize","ReflectionFilter","ShockwaveFilter","center","amplitude","wavelength","speed","brightness","time","SimplexNoiseFilter","zOffset","currentTime","randomValue","TwistFilter","computeTwistPadding","radiusPx","buildTwistFilter","previewToNativeScale","width","height","minEdge","normalizedRadius","offsetX","offsetY","hexToRgb","parsedHex","VignetteFilter","radiusFactor","effectiveStrength","initializeFilterRegistry","disabled","removedCount"],"mappings":"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"}
|