@hypen-space/web 0.2.12 → 0.3.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.
Files changed (39) hide show
  1. package/dist/src/dom/applicators/effects.js +38 -2
  2. package/dist/src/dom/applicators/effects.js.map +3 -3
  3. package/dist/src/dom/applicators/events.js +280 -397
  4. package/dist/src/dom/applicators/events.js.map +5 -4
  5. package/dist/src/dom/applicators/font.js +94 -5
  6. package/dist/src/dom/applicators/font.js.map +3 -3
  7. package/dist/src/dom/applicators/index.js +590 -425
  8. package/dist/src/dom/applicators/index.js.map +10 -9
  9. package/dist/src/dom/applicators/layout.js +33 -5
  10. package/dist/src/dom/applicators/layout.js.map +3 -3
  11. package/dist/src/dom/applicators/size.js +81 -16
  12. package/dist/src/dom/applicators/size.js.map +3 -3
  13. package/dist/src/dom/components/hypenapp.js +296 -0
  14. package/dist/src/dom/components/hypenapp.js.map +10 -0
  15. package/dist/src/dom/components/index.js +263 -1
  16. package/dist/src/dom/components/index.js.map +5 -4
  17. package/dist/src/dom/element-data.js +140 -0
  18. package/dist/src/dom/element-data.js.map +10 -0
  19. package/dist/src/dom/index.js +857 -430
  20. package/dist/src/dom/index.js.map +13 -11
  21. package/dist/src/dom/renderer.js +857 -430
  22. package/dist/src/dom/renderer.js.map +13 -11
  23. package/dist/src/hypen.js +857 -430
  24. package/dist/src/hypen.js.map +13 -11
  25. package/dist/src/index.js +862 -430
  26. package/dist/src/index.js.map +15 -12
  27. package/package.json +3 -3
  28. package/src/canvas/QUICKSTART.md +2 -4
  29. package/src/dom/applicators/effects.ts +45 -1
  30. package/src/dom/applicators/events.ts +348 -537
  31. package/src/dom/applicators/font.ts +127 -2
  32. package/src/dom/applicators/index.ts +117 -7
  33. package/src/dom/applicators/layout.ts +40 -4
  34. package/src/dom/applicators/size.ts +101 -16
  35. package/src/dom/components/hypenapp.ts +348 -0
  36. package/src/dom/components/index.ts +2 -0
  37. package/src/dom/element-data.ts +234 -0
  38. package/src/dom/renderer.ts +8 -5
  39. package/src/index.ts +3 -0
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/dom/applicators/events.ts"],
3
+ "sources": ["../src/dom/element-data.ts", "../src/dom/applicators/events.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * Event Applicators\n * \n * Handles event applicators like onClick, onPress, etc.\n */\n\nimport type { ApplicatorHandler } from \"./index.js\";\n\nfunction toPlainObject(value: any): any {\n if (value instanceof Map) {\n const obj: Record<string, any> = {};\n for (const [key, val] of value.entries()) {\n obj[key] = toPlainObject(val);\n }\n return obj;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => toPlainObject(item));\n }\n\n if (value && typeof value === \"object\") {\n const obj: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n obj[key] = toPlainObject(val);\n }\n return obj;\n }\n\n return value;\n}\n\nfunction extractActionDetails(value: any): { actionName: string | null; payload: Record<string, any> } {\n if (typeof value === \"string\") {\n if (!value.startsWith(\"@\")) {\n return { actionName: null, payload: {} };\n }\n\n let actionName = value.substring(1);\n if (actionName.startsWith(\"actions.\")) {\n actionName = actionName.substring(8);\n }\n return { actionName, payload: {} };\n }\n\n if (value && typeof value === \"object\") {\n const plain = toPlainObject(value);\n const payload: Record<string, any> = {};\n let actionName: string | null = null;\n\n if (plain && typeof plain === \"object\") {\n const actionValue = plain[\"0\"];\n if (typeof actionValue === \"string\" && actionValue.startsWith(\"@\")) {\n actionName = actionValue.substring(1);\n if (actionName.startsWith(\"actions.\")) {\n actionName = actionName.substring(8);\n }\n }\n\n for (const [key, val] of Object.entries(plain)) {\n if (key !== \"0\") {\n payload[key] = val;\n }\n }\n }\n\n return { actionName, payload };\n }\n\n return { actionName: null, payload: {} };\n}\n\nexport const eventHandlers: Record<string, ApplicatorHandler> = {\n onClick: (element, value) => {\n console.log(`[EventApplicator] onClick called with value:`, value);\n\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onClick value must be an action reference, got:`, value);\n return;\n }\n\n // Remove existing click listener if any\n const existingListener = (element as any).__hypenClickListener;\n if (existingListener) {\n element.removeEventListener(\"click\", existingListener);\n }\n\n // Create new click listener\n const listener = (event: Event) => {\n console.log(`🔥 [EventApplicator] onClick fired, dispatching action: ${actionName}`);\n\n // Use custom payload if provided, otherwise extract event data\n const payload = Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : extractEventData(event, element);\n\n console.log(`[EventApplicator] onClick payload:`, payload);\n\n // Dispatch action to engine\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onClick`);\n }\n };\n\n // Store listener reference and attach to DOM\n (element as any).__hypenClickListener = listener;\n element.addEventListener(\"click\", listener);\n\n console.log(`[EventApplicator] onClick handler attached for action: ${actionName}`);\n },\n\n onPress: (element, value) => {\n // For now, treat onPress same as onClick\n // In the future, this could handle touch events differently\n eventHandlers.onClick(element, value);\n },\n\n onChange: (element, value) => {\n const { actionName } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onChange value must be an action reference starting with @, got:`, value);\n return;\n }\n\n const existingListener = (element as any).__hypenChangeListener;\n if (existingListener) {\n element.removeEventListener(\"change\", existingListener);\n }\n\n const listener = (event: Event) => {\n console.log(`🔥 [EventApplicator] onChange fired, dispatching action: ${actionName}`);\n\n const payload = extractEventData(event, element);\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onChange`);\n }\n };\n\n (element as any).__hypenChangeListener = listener;\n element.addEventListener(\"change\", listener);\n\n console.log(`[EventApplicator] onChange handler attached for action: ${actionName}`);\n },\n\n onSubmit: (element, value) => {\n const { actionName } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onSubmit value must be an action reference starting with @, got:`, value);\n return;\n }\n\n const existingListener = (element as any).__hypenSubmitListener;\n if (existingListener) {\n element.removeEventListener(\"submit\", existingListener);\n }\n\n const listener = (event: Event) => {\n console.log(`🔥 [EventApplicator] onSubmit fired, dispatching action: ${actionName}`);\n\n event.preventDefault();\n\n const payload = extractEventData(event, element);\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onSubmit`);\n }\n };\n\n (element as any).__hypenSubmitListener = listener;\n element.addEventListener(\"submit\", listener);\n\n console.log(`[EventApplicator] onSubmit handler attached for action: ${actionName}`);\n },\n\n onInput: (element, value) => {\n console.log(`[EventApplicator] onInput called with value:`, value);\n \n const { actionName } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onInput value must be an action reference starting with @, got:`, value);\n return;\n }\n\n const existingListener = (element as any).__hypenInputListener;\n if (existingListener) {\n element.removeEventListener(\"input\", existingListener);\n }\n\n const listener = (event: Event) => {\n console.log(`🔥 [EventApplicator] onInput fired, dispatching action: ${actionName}`);\n\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n const payload = {\n type: event.type,\n timestamp: Date.now(),\n value: target.value,\n input: target.value,\n };\n\n console.log(`[EventApplicator] onInput payload:`, payload);\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onInput`);\n }\n };\n\n (element as any).__hypenInputListener = listener;\n element.addEventListener(\"input\", listener);\n\n console.log(`[EventApplicator] onInput handler attached for action: ${actionName}`);\n },\n\n onKey: (element, value) => {\n console.log(`[EventApplicator] onKey called with value:`, value);\n \n // onKey can receive either:\n // 1. Just an action: \"@action.submit\"\n // 2. Key-specific format from props like onKey.key = \"return\", onKey.action = \"@action.submit\"\n \n // For now, we'll handle the simple case where onKey receives the action directly\n // and triggers on Enter key by default\n const { actionName } = extractActionDetails(value);\n\n if (actionName) {\n \n const existingListener = (element as any).__hypenKeyListener;\n if (existingListener) {\n element.removeEventListener(\"keydown\", existingListener);\n }\n \n const listener = (event: KeyboardEvent) => {\n // Default to Enter key\n if (event.key === \"Enter\") {\n console.log(`🔥 [EventApplicator] onKey fired (Enter), dispatching action: ${actionName}`);\n \n event.preventDefault();\n \n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n const payload = {\n type: event.type,\n timestamp: Date.now(),\n key: event.key,\n code: event.code,\n value: target.value,\n input: target.value,\n ctrlKey: event.ctrlKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n metaKey: event.metaKey,\n };\n \n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onKey`);\n }\n }\n };\n \n (element as any).__hypenKeyListener = listener;\n element.addEventListener(\"keydown\", listener);\n \n console.log(`[EventApplicator] onKey handler attached for action: ${actionName} (triggers on Enter)`);\n } else {\n console.warn(`[EventApplicator] onKey value must be an action reference starting with @, got: ${value}`);\n }\n },\n\n // Handle key-specific applicator: onKey.key for specifying which key\n \"onKey.key\": (element, keyValue) => {\n console.log(`[EventApplicator] onKey.key called with value:`, keyValue);\n // Store the key to check in the listener\n (element as any).__hypenKeyTarget = keyValue;\n },\n\n // Handle action for specific key: onKey.action\n \"onKey.action\": (element, value) => {\n console.log(`[EventApplicator] onKey.action called with value:`, value);\n \n const { actionName } = extractActionDetails(value);\n\n if (actionName) {\n \n const targetKey = (element as any).__hypenKeyTarget || \"Enter\";\n \n const existingListener = (element as any).__hypenKeyListener;\n if (existingListener) {\n element.removeEventListener(\"keydown\", existingListener);\n }\n \n const listener = (event: KeyboardEvent) => {\n const keyToMatch = targetKey.toLowerCase() === \"return\" ? \"Enter\" : targetKey;\n \n if (event.key === keyToMatch) {\n console.log(`🔥 [EventApplicator] onKey fired (${keyToMatch}), dispatching action: ${actionName}`);\n \n event.preventDefault();\n \n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n const payload = {\n type: event.type,\n timestamp: Date.now(),\n key: event.key,\n code: event.code,\n value: target.value,\n input: target.value,\n ctrlKey: event.ctrlKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n metaKey: event.metaKey,\n };\n \n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n }\n }\n };\n \n (element as any).__hypenKeyListener = listener;\n element.addEventListener(\"keydown\", listener);\n \n console.log(`[EventApplicator] onKey handler attached for action: ${actionName} on key: ${targetKey}`);\n }\n },\n\n onScroll: (element, value) => {\n console.log(`[EventApplicator] onScroll called with value:`, value);\n\n const { actionName } = extractActionDetails(value);\n\n if (actionName) {\n\n // Remove existing scroll listener if any\n const existingListener = (element as any).__hypenScrollListener;\n if (existingListener) {\n element.removeEventListener(\"scroll\", existingListener);\n }\n\n // Create new scroll listener with throttling to avoid too many events\n let throttleTimer: number | null = null;\n const listener = (event: Event) => {\n if (throttleTimer) return;\n\n throttleTimer = setTimeout(() => {\n throttleTimer = null;\n }, 100) as unknown as number; // Throttle to max 10 events/second\n\n const target = event.target as HTMLElement;\n const scrollTop = target.scrollTop;\n const scrollHeight = target.scrollHeight;\n const clientHeight = target.clientHeight;\n const scrollPercentage = (scrollTop / (scrollHeight - clientHeight)) * 100;\n\n // Calculate if near bottom (within 100px or 90% scrolled)\n const nearBottom = scrollHeight - scrollTop - clientHeight < 100 || scrollPercentage > 90;\n\n console.log(`🔥 [EventApplicator] onScroll fired, scrollTop: ${scrollTop}, nearBottom: ${nearBottom}`);\n\n const payload = {\n type: \"scroll\",\n timestamp: Date.now(),\n scrollTop,\n scrollLeft: target.scrollLeft,\n scrollHeight,\n scrollWidth: target.scrollWidth,\n clientHeight,\n clientWidth: target.clientWidth,\n scrollPercentage: Math.round(scrollPercentage),\n nearBottom,\n atBottom: scrollHeight - scrollTop === clientHeight,\n atTop: scrollTop === 0,\n };\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onScroll`);\n }\n };\n\n (element as any).__hypenScrollListener = listener;\n element.addEventListener(\"scroll\", listener, { passive: true });\n\n console.log(`[EventApplicator] onScroll handler attached for action: ${actionName}`);\n } else {\n console.warn(`[EventApplicator] onScroll value must be an action reference starting with @, got: ${value}`);\n }\n },\n\n onLongClick: (element, value) => {\n console.log(`[EventApplicator] onLongClick called with value:`, value);\n\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onLongClick value must be an action reference, got:`, value);\n return;\n }\n\n // Remove existing long click listeners if any\n const existingDownListener = (element as any).__hypenLongClickDownListener;\n const existingUpListener = (element as any).__hypenLongClickUpListener;\n if (existingDownListener) {\n element.removeEventListener(\"pointerdown\", existingDownListener);\n }\n if (existingUpListener) {\n element.removeEventListener(\"pointerup\", existingUpListener);\n element.removeEventListener(\"pointerleave\", existingUpListener);\n }\n\n // Long click implementation using pointer events with 500ms threshold\n let longClickTimer: ReturnType<typeof setTimeout> | null = null;\n const LONG_CLICK_THRESHOLD = 500; // 500ms\n\n const downListener = (event: PointerEvent) => {\n longClickTimer = setTimeout(() => {\n console.log(`🔥 [EventApplicator] onLongClick fired, dispatching action: ${actionName}`);\n\n const payload = Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : {\n type: \"longclick\",\n timestamp: Date.now(),\n clientX: event.clientX,\n clientY: event.clientY,\n };\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onLongClick`);\n }\n\n longClickTimer = null;\n }, LONG_CLICK_THRESHOLD);\n };\n\n const upListener = () => {\n if (longClickTimer) {\n clearTimeout(longClickTimer);\n longClickTimer = null;\n }\n };\n\n (element as any).__hypenLongClickDownListener = downListener;\n (element as any).__hypenLongClickUpListener = upListener;\n element.addEventListener(\"pointerdown\", downListener);\n element.addEventListener(\"pointerup\", upListener);\n element.addEventListener(\"pointerleave\", upListener);\n\n console.log(`[EventApplicator] onLongClick handler attached for action: ${actionName}`);\n },\n\n onFocus: (element, value) => {\n console.log(`[EventApplicator] onFocus called with value:`, value);\n\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onFocus value must be an action reference, got:`, value);\n return;\n }\n\n // Remove existing focus listener if any\n const existingListener = (element as any).__hypenFocusListener;\n if (existingListener) {\n element.removeEventListener(\"focus\", existingListener);\n }\n\n const listener = (event: FocusEvent) => {\n console.log(`🔥 [EventApplicator] onFocus fired, dispatching action: ${actionName}`);\n\n const target = event.target as HTMLElement;\n const payload = Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : {\n type: \"focus\",\n timestamp: Date.now(),\n value: (target as HTMLInputElement).value ?? undefined,\n };\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onFocus`);\n }\n };\n\n (element as any).__hypenFocusListener = listener;\n element.addEventListener(\"focus\", listener);\n\n console.log(`[EventApplicator] onFocus handler attached for action: ${actionName}`);\n },\n\n onBlur: (element, value) => {\n console.log(`[EventApplicator] onBlur called with value:`, value);\n\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onBlur value must be an action reference, got:`, value);\n return;\n }\n\n // Remove existing blur listener if any\n const existingListener = (element as any).__hypenBlurListener;\n if (existingListener) {\n element.removeEventListener(\"blur\", existingListener);\n }\n\n const listener = (event: FocusEvent) => {\n console.log(`🔥 [EventApplicator] onBlur fired, dispatching action: ${actionName}`);\n\n const target = event.target as HTMLElement;\n const payload = Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : {\n type: \"blur\",\n timestamp: Date.now(),\n value: (target as HTMLInputElement).value ?? undefined,\n };\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onBlur`);\n }\n };\n\n (element as any).__hypenBlurListener = listener;\n element.addEventListener(\"blur\", listener);\n\n console.log(`[EventApplicator] onBlur handler attached for action: ${actionName}`);\n },\n\n onMouseEnter: (element, value) => {\n console.log(`[EventApplicator] onMouseEnter called with value:`, value);\n\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onMouseEnter value must be an action reference, got:`, value);\n return;\n }\n\n // Remove existing listener if any\n const existingListener = (element as any).__hypenMouseEnterListener;\n if (existingListener) {\n element.removeEventListener(\"mouseenter\", existingListener);\n }\n\n const listener = (event: MouseEvent) => {\n console.log(`🔥 [EventApplicator] onMouseEnter fired, dispatching action: ${actionName}`);\n\n const payload = Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : {\n type: \"mouseenter\",\n timestamp: Date.now(),\n clientX: event.clientX,\n clientY: event.clientY,\n };\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onMouseEnter`);\n }\n };\n\n (element as any).__hypenMouseEnterListener = listener;\n element.addEventListener(\"mouseenter\", listener);\n\n console.log(`[EventApplicator] onMouseEnter handler attached for action: ${actionName}`);\n },\n\n onMouseLeave: (element, value) => {\n console.log(`[EventApplicator] onMouseLeave called with value:`, value);\n\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(`[EventApplicator] onMouseLeave value must be an action reference, got:`, value);\n return;\n }\n\n // Remove existing listener if any\n const existingListener = (element as any).__hypenMouseLeaveListener;\n if (existingListener) {\n element.removeEventListener(\"mouseleave\", existingListener);\n }\n\n const listener = (event: MouseEvent) => {\n console.log(`🔥 [EventApplicator] onMouseLeave fired, dispatching action: ${actionName}`);\n\n const payload = Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : {\n type: \"mouseleave\",\n timestamp: Date.now(),\n clientX: event.clientX,\n clientY: event.clientY,\n };\n\n const engine = (element as any).__hypenEngine;\n if (engine) {\n engine.dispatchAction(actionName, payload);\n } else {\n console.warn(`[EventApplicator] No engine attached to element for onMouseLeave`);\n }\n };\n\n (element as any).__hypenMouseLeaveListener = listener;\n element.addEventListener(\"mouseleave\", listener);\n\n console.log(`[EventApplicator] onMouseLeave handler attached for action: ${actionName}`);\n },\n\n};\n\n/**\n * Extract relevant data from an event\n */\nfunction extractEventData(event: Event, element: HTMLElement): any {\n const data: any = {\n type: event.type,\n timestamp: Date.now(),\n };\n\n // Mouse events\n if (event instanceof MouseEvent) {\n data.clientX = event.clientX;\n data.clientY = event.clientY;\n data.button = event.button;\n }\n\n // Keyboard events\n if (event instanceof KeyboardEvent) {\n data.key = event.key;\n data.code = event.code;\n data.ctrlKey = event.ctrlKey;\n data.shiftKey = event.shiftKey;\n data.altKey = event.altKey;\n data.metaKey = event.metaKey;\n }\n\n // Input events (for form elements)\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n data.value = element.value;\n }\n\n // Select events\n if (element instanceof HTMLSelectElement) {\n data.value = element.value;\n data.selectedIndex = element.selectedIndex;\n }\n\n // Form events\n if (event.type === \"submit\" && element instanceof HTMLFormElement) {\n data.formData = new FormData(element);\n }\n\n return data;\n}\n"
5
+ "/**\n * Type-Safe Element Data\n *\n * Provides strongly-typed access to Hypen-specific data attached to DOM elements.\n * Eliminates `as any` casts throughout the codebase.\n */\n\nimport { type DisposableStack, getElementDisposables } from \"@hypen/core\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Engine interface for dispatching actions\n */\nexport interface IEngine {\n dispatchAction(name: string, payload?: unknown): void;\n}\n\n/**\n * All Hypen-specific data attached to an element\n */\nexport interface HypenElementData {\n /** Engine reference for action dispatch */\n engine?: IEngine;\n /** Target key for keyboard events (e.g., \"Enter\", \"Escape\") */\n keyTarget?: string;\n /** Set of registered event type:action pairs */\n registeredEvents?: Set<string>;\n /** Custom element metadata */\n meta?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Private Storage\n// ============================================================================\n\n/**\n * WeakMap to store Hypen data without polluting the element\n */\nconst elementDataMap = new WeakMap<HTMLElement, HypenElementData>();\n\n// ============================================================================\n// Core API\n// ============================================================================\n\n/**\n * Get Hypen data for an element, creating if needed\n */\nexport function getHypenData(element: HTMLElement): HypenElementData {\n let data = elementDataMap.get(element);\n if (!data) {\n data = {};\n elementDataMap.set(element, data);\n }\n return data;\n}\n\n/**\n * Check if element has Hypen data\n */\nexport function hasHypenData(element: HTMLElement): boolean {\n return elementDataMap.has(element);\n}\n\n/**\n * Clear Hypen data from an element\n */\nexport function clearHypenData(element: HTMLElement): void {\n elementDataMap.delete(element);\n}\n\n// ============================================================================\n// Engine Access\n// ============================================================================\n\n/**\n * Get the engine attached to an element\n */\nexport function getEngine(element: HTMLElement): IEngine | undefined {\n return getHypenData(element).engine;\n}\n\n/**\n * Set the engine on an element\n */\nexport function setEngine(element: HTMLElement, engine: IEngine): void {\n getHypenData(element).engine = engine;\n}\n\n/**\n * Find engine by walking up the DOM tree\n */\nexport function findEngine(element: HTMLElement): IEngine | undefined {\n let current: HTMLElement | null = element;\n while (current) {\n const engine = getEngine(current);\n if (engine) return engine;\n current = current.parentElement;\n }\n return undefined;\n}\n\n// ============================================================================\n// Event Registration Tracking\n// ============================================================================\n\n/**\n * Get registered events set for an element\n */\nexport function getRegisteredEvents(element: HTMLElement): Set<string> {\n const data = getHypenData(element);\n if (!data.registeredEvents) {\n data.registeredEvents = new Set();\n }\n return data.registeredEvents;\n}\n\n/**\n * Check if an event handler is registered\n */\nexport function isEventRegistered(element: HTMLElement, eventKey: string): boolean {\n return getRegisteredEvents(element).has(eventKey);\n}\n\n/**\n * Mark an event handler as registered\n */\nexport function registerEvent(element: HTMLElement, eventKey: string): void {\n getRegisteredEvents(element).add(eventKey);\n}\n\n/**\n * Unregister an event handler\n */\nexport function unregisterEvent(element: HTMLElement, eventKey: string): void {\n getRegisteredEvents(element).delete(eventKey);\n}\n\n// ============================================================================\n// Keyboard Event Key Target\n// ============================================================================\n\n/**\n * Get the target key for keyboard events\n */\nexport function getKeyTarget(element: HTMLElement): string | undefined {\n return getHypenData(element).keyTarget;\n}\n\n/**\n * Set the target key for keyboard events\n */\nexport function setKeyTarget(element: HTMLElement, key: string): void {\n getHypenData(element).keyTarget = key;\n}\n\n// ============================================================================\n// Metadata\n// ============================================================================\n\n/**\n * Get custom metadata value\n */\nexport function getMeta<T>(element: HTMLElement, key: string): T | undefined {\n return getHypenData(element).meta?.[key] as T | undefined;\n}\n\n/**\n * Set custom metadata value\n */\nexport function setMeta<T>(element: HTMLElement, key: string, value: T): void {\n const data = getHypenData(element);\n if (!data.meta) {\n data.meta = {};\n }\n data.meta[key] = value;\n}\n\n// ============================================================================\n// Cleanup\n// ============================================================================\n\n/**\n * Dispose all resources attached to an element and clear data\n * Call this when removing an element from the DOM\n */\nexport function disposeHypenElement(element: HTMLElement): void {\n // Dispose any registered disposables\n try {\n const disposables = getElementDisposables(element);\n disposables.dispose();\n } catch {\n // Ignore if no disposables\n }\n\n // Clear Hypen data\n clearHypenData(element);\n}\n\n// ============================================================================\n// Legacy Compatibility Layer\n// ============================================================================\n\n/**\n * Symbol-based legacy accessor (for backwards compatibility)\n * Use the typed functions above instead when possible\n */\nconst HYPEN_ENGINE_SYMBOL = Symbol.for(\"hypen.engine\");\nconst REGISTERED_EVENTS_SYMBOL = Symbol.for(\"hypen.registeredEvents\");\nconst KEY_TARGET_SYMBOL = Symbol.for(\"hypen.keyTarget\");\n\n/**\n * Legacy accessor for engine (backwards compatible with existing code)\n */\nexport function getLegacyEngine(element: HTMLElement): IEngine | undefined {\n // Try new storage first\n const engine = getEngine(element);\n if (engine) return engine;\n\n // Fall back to legacy storage\n return (element as any)[HYPEN_ENGINE_SYMBOL] ??\n (element as any).__hypenEngine;\n}\n\n/**\n * Legacy setter for engine (backwards compatible)\n */\nexport function setLegacyEngine(element: HTMLElement, engine: IEngine): void {\n // Set in both locations for compatibility\n setEngine(element, engine);\n (element as any).__hypenEngine = engine;\n}\n",
6
+ "/**\n * Event Applicators\n *\n * Handles event applicators like onClick, onPress, etc.\n * Uses a factory pattern to reduce boilerplate and ensure consistency.\n */\n\nimport type { ApplicatorHandler } from \"./index.js\";\nimport {\n getElementDisposables,\n disposableListener,\n disposableTimeout,\n type Disposable,\n} from \"@hypen/core\";\nimport {\n type IEngine,\n getEngine,\n getRegisteredEvents,\n registerEvent,\n unregisterEvent,\n getKeyTarget,\n setKeyTarget,\n} from \"../element-data.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface EventHandlerOptions {\n /** Custom payload extractor for this event type */\n extractPayload?: (event: Event, element: HTMLElement) => Record<string, unknown>;\n /** Throttle events to max one per N milliseconds */\n throttleMs?: number;\n /** Prevent default behavior */\n preventDefault?: boolean;\n /** Use passive listener (for scroll, touch) */\n passive?: boolean;\n /** Key to listen for (keyboard events) */\n key?: string;\n}\n\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Convert Map or nested objects to plain objects\n */\nfunction toPlainObject(value: unknown): unknown {\n if (value instanceof Map) {\n const obj: Record<string, unknown> = {};\n for (const [key, val] of value.entries()) {\n obj[key] = toPlainObject(val);\n }\n return obj;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => toPlainObject(item));\n }\n\n if (value && typeof value === \"object\") {\n const obj: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n obj[key] = toPlainObject(val);\n }\n return obj;\n }\n\n return value;\n}\n\n/**\n * Extract action name and custom payload from an applicator value\n */\nfunction extractActionDetails(value: unknown): {\n actionName: string | null;\n payload: Record<string, unknown>;\n} {\n // String format: \"@actions.doSomething\" or \"@doSomething\"\n if (typeof value === \"string\") {\n if (!value.startsWith(\"@\")) {\n return { actionName: null, payload: {} };\n }\n\n let actionName = value.substring(1);\n if (actionName.startsWith(\"actions.\")) {\n actionName = actionName.substring(8);\n }\n return { actionName, payload: {} };\n }\n\n // Object format: { \"0\": \"@actions.doSomething\", \"customKey\": \"value\" }\n if (value && typeof value === \"object\") {\n const plain = toPlainObject(value) as Record<string, unknown>;\n const payload: Record<string, unknown> = {};\n let actionName: string | null = null;\n\n if (plain && typeof plain === \"object\") {\n const actionValue = plain[\"0\"];\n if (typeof actionValue === \"string\" && actionValue.startsWith(\"@\")) {\n actionName = actionValue.substring(1);\n if (actionName.startsWith(\"actions.\")) {\n actionName = actionName.substring(8);\n }\n }\n\n for (const [key, val] of Object.entries(plain)) {\n if (key !== \"0\") {\n // If the key is numeric (like \"1\", \"2\") and the value is an object,\n // merge the object's keys into the payload directly.\n // This handles: .onClick(\"@actions.foo\", { id: \"123\" })\n // where the second positional arg becomes \"1\": { id: \"123\" }\n if (/^\\d+$/.test(key) && val && typeof val === \"object\" && !Array.isArray(val)) {\n for (const [innerKey, innerVal] of Object.entries(val)) {\n payload[innerKey] = innerVal;\n }\n } else {\n payload[key] = val;\n }\n }\n }\n }\n\n return { actionName, payload };\n }\n\n return { actionName: null, payload: {} };\n}\n\n/**\n * Extract relevant data from a DOM event\n */\nfunction extractEventData(event: Event, element: HTMLElement): Record<string, unknown> {\n const data: Record<string, unknown> = {\n type: event.type,\n timestamp: Date.now(),\n };\n\n // Mouse events\n if (event instanceof MouseEvent) {\n data.clientX = event.clientX;\n data.clientY = event.clientY;\n data.button = event.button;\n }\n\n // Keyboard events\n if (event instanceof KeyboardEvent) {\n data.key = event.key;\n data.code = event.code;\n data.ctrlKey = event.ctrlKey;\n data.shiftKey = event.shiftKey;\n data.altKey = event.altKey;\n data.metaKey = event.metaKey;\n }\n\n // Input element values\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n data.value = element.value;\n }\n\n // Select element values\n if (element instanceof HTMLSelectElement) {\n data.value = element.value;\n data.selectedIndex = element.selectedIndex;\n }\n\n // Form data\n if (event.type === \"submit\" && element instanceof HTMLFormElement) {\n data.formData = new FormData(element);\n }\n\n return data;\n}\n\n\n/**\n * Capitalize first letter of a string\n */\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n// ============================================================================\n// Event Handler Factory\n// ============================================================================\n\n\n/**\n * Create an event handler applicator with common boilerplate\n */\nfunction createEventHandler(\n eventType: string,\n options: EventHandlerOptions = {}\n): ApplicatorHandler {\n return (element: HTMLElement, value: unknown) => {\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(\n `[EventApplicator] ${eventType} requires an action reference starting with @, got:`,\n value\n );\n return;\n }\n\n const disposables = getElementDisposables(element);\n\n // Track that we've registered this event type\n // The disposable stack handles cleanup automatically\n const eventKey = `${eventType}:${actionName}`;\n if (getRegisteredEvents(element).has(eventKey)) {\n // Already registered - skip to avoid duplicates\n // This can happen during re-renders\n return;\n }\n registerEvent(element, eventKey);\n\n // Create throttle state if needed\n let throttleTimer: Disposable | null = null;\n\n // Create the event listener\n const listener = (event: Event) => {\n // Handle throttling\n if (options.throttleMs && throttleTimer) {\n return;\n }\n\n if (options.throttleMs) {\n throttleTimer = disposableTimeout(() => {\n throttleTimer = null;\n }, options.throttleMs);\n }\n\n // Handle preventDefault\n if (options.preventDefault) {\n event.preventDefault();\n }\n\n // Build payload\n const payload =\n Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : options.extractPayload\n ? options.extractPayload(event, element)\n : extractEventData(event, element);\n\n // Dispatch to engine\n const engine = getEngine(element);\n if (engine) {\n engine.dispatchAction(actionName, payload);\n }\n };\n\n // Register the listener using disposable pattern\n disposables.add(\n disposableListener(element, eventType, listener, {\n passive: options.passive,\n })\n );\n\n // Clean up registered events tracking on dispose\n disposables.addCallback(() => {\n unregisterEvent(element, eventKey);\n if (throttleTimer) {\n throttleTimer.dispose();\n }\n });\n };\n}\n\n/**\n * Create a keyboard event handler that filters by key\n */\nfunction createKeyHandler(defaultKey: string = \"Enter\"): ApplicatorHandler {\n return (element: HTMLElement, value: unknown) => {\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(\n `[EventApplicator] onKey requires an action reference starting with @, got:`,\n value\n );\n return;\n }\n\n const disposables = getElementDisposables(element);\n\n const eventKey = `keydown:${actionName}:${defaultKey}`;\n if (getRegisteredEvents(element).has(eventKey)) {\n return;\n }\n registerEvent(element, eventKey);\n\n // Get target key from element data or use default\n const targetKey = getKeyTarget(element) || defaultKey;\n const keyToMatch = targetKey.toLowerCase() === \"return\" ? \"Enter\" : targetKey;\n\n const listener = (event: Event) => {\n const keyEvent = event as KeyboardEvent;\n if (keyEvent.key !== keyToMatch) {\n return;\n }\n\n event.preventDefault();\n\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n const payload =\n Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : {\n type: event.type,\n timestamp: Date.now(),\n key: keyEvent.key,\n code: keyEvent.code,\n value: target.value,\n input: target.value,\n ctrlKey: keyEvent.ctrlKey,\n shiftKey: keyEvent.shiftKey,\n altKey: keyEvent.altKey,\n metaKey: keyEvent.metaKey,\n };\n\n const engine = getEngine(element);\n if (engine) {\n engine.dispatchAction(actionName, payload);\n }\n };\n\n disposables.add(disposableListener(element, \"keydown\", listener));\n disposables.addCallback(() => {\n unregisterEvent(element, eventKey);\n });\n };\n}\n\n/**\n * Create a long-click/long-press handler\n */\nfunction createLongClickHandler(thresholdMs: number = 500): ApplicatorHandler {\n return (element: HTMLElement, value: unknown) => {\n const { actionName, payload: customPayload } = extractActionDetails(value);\n\n if (!actionName) {\n console.warn(\n `[EventApplicator] onLongClick requires an action reference starting with @, got:`,\n value\n );\n return;\n }\n\n const disposables = getElementDisposables(element);\n\n const eventKey = `longclick:${actionName}`;\n if (getRegisteredEvents(element).has(eventKey)) {\n return;\n }\n registerEvent(element, eventKey);\n\n let longClickTimer: Disposable | null = null;\n\n const downListener = (event: Event) => {\n const pointerEvent = event as PointerEvent;\n\n longClickTimer = disposableTimeout(() => {\n const payload =\n Object.keys(customPayload).length > 0\n ? { ...customPayload }\n : {\n type: \"longclick\",\n timestamp: Date.now(),\n clientX: pointerEvent.clientX,\n clientY: pointerEvent.clientY,\n };\n\n const engine = getEngine(element);\n if (engine) {\n engine.dispatchAction(actionName, payload);\n }\n\n longClickTimer = null;\n }, thresholdMs);\n };\n\n const cancelListener = () => {\n if (longClickTimer) {\n longClickTimer.dispose();\n longClickTimer = null;\n }\n };\n\n disposables.add(disposableListener(element, \"pointerdown\", downListener));\n disposables.add(disposableListener(element, \"pointerup\", cancelListener));\n disposables.add(disposableListener(element, \"pointerleave\", cancelListener));\n disposables.addCallback(() => {\n unregisterEvent(element, eventKey);\n cancelListener();\n });\n };\n}\n\n// ============================================================================\n// Payload Extractors\n// ============================================================================\n\nconst inputPayload = (event: Event, element: HTMLElement): Record<string, unknown> => {\n const target = element as HTMLInputElement | HTMLTextAreaElement;\n return {\n type: event.type,\n timestamp: Date.now(),\n value: target.value,\n input: target.value,\n };\n};\n\nconst scrollPayload = (_event: Event, element: HTMLElement): Record<string, unknown> => {\n const scrollTop = element.scrollTop;\n const scrollHeight = element.scrollHeight;\n const clientHeight = element.clientHeight;\n const scrollPercentage =\n scrollHeight - clientHeight > 0\n ? (scrollTop / (scrollHeight - clientHeight)) * 100\n : 0;\n\n const nearBottom =\n scrollHeight - scrollTop - clientHeight < 100 || scrollPercentage > 90;\n\n return {\n type: \"scroll\",\n timestamp: Date.now(),\n scrollTop,\n scrollLeft: element.scrollLeft,\n scrollHeight,\n scrollWidth: element.scrollWidth,\n clientHeight,\n clientWidth: element.clientWidth,\n scrollPercentage: Math.round(scrollPercentage),\n nearBottom,\n atBottom: scrollHeight - scrollTop === clientHeight,\n atTop: scrollTop === 0,\n };\n};\n\nconst focusPayload = (event: Event, element: HTMLElement): Record<string, unknown> => ({\n type: event.type,\n timestamp: Date.now(),\n value: (element as HTMLInputElement).value ?? undefined,\n});\n\nconst mousePayload = (event: Event, _element: HTMLElement): Record<string, unknown> => {\n const mouseEvent = event as MouseEvent;\n return {\n type: event.type,\n timestamp: Date.now(),\n clientX: mouseEvent.clientX,\n clientY: mouseEvent.clientY,\n };\n};\n\n// ============================================================================\n// Event Handlers Export\n// ============================================================================\n\nexport const eventHandlers: Record<string, ApplicatorHandler> = {\n // Basic click/press\n onClick: createEventHandler(\"click\"),\n onPress: createEventHandler(\"click\"), // Alias for mobile-style naming\n\n // Form events\n onChange: createEventHandler(\"change\"),\n onSubmit: createEventHandler(\"submit\", { preventDefault: true }),\n onInput: createEventHandler(\"input\", { extractPayload: inputPayload }),\n\n // Keyboard events\n onKey: createKeyHandler(\"Enter\"),\n \"onKey.key\": (element: HTMLElement, value: unknown) => {\n // Store the target key for the action handler to use\n setKeyTarget(element, String(value));\n },\n \"onKey.action\": createKeyHandler(\"Enter\"),\n\n // Scroll (throttled)\n onScroll: createEventHandler(\"scroll\", {\n throttleMs: 100,\n passive: true,\n extractPayload: scrollPayload,\n }),\n\n // Long click/press\n onLongClick: createLongClickHandler(500),\n\n // Focus events\n onFocus: createEventHandler(\"focus\", { extractPayload: focusPayload }),\n onBlur: createEventHandler(\"blur\", { extractPayload: focusPayload }),\n\n // Mouse hover events\n onMouseEnter: createEventHandler(\"mouseenter\", { extractPayload: mousePayload }),\n onMouseLeave: createEventHandler(\"mouseleave\", { extractPayload: mousePayload }),\n};\n"
6
7
  ],
7
- "mappings": "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",
8
- "debugId": "86E1367389759DD764756E2164756E21",
8
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA;AA2CO,SAAS,YAAY,CAAC,SAAwC;AAAA,EACnE,IAAI,OAAO,eAAe,IAAI,OAAO;AAAA,EACrC,IAAI,CAAC,MAAM;AAAA,IACT,OAAO,CAAC;AAAA,IACR,eAAe,IAAI,SAAS,IAAI;AAAA,EAClC;AAAA,EACA,OAAO;AAAA;AAMF,SAAS,YAAY,CAAC,SAA+B;AAAA,EAC1D,OAAO,eAAe,IAAI,OAAO;AAAA;AAM5B,SAAS,cAAc,CAAC,SAA4B;AAAA,EACzD,eAAe,OAAO,OAAO;AAAA;AAUxB,SAAS,SAAS,CAAC,SAA2C;AAAA,EACnE,OAAO,aAAa,OAAO,EAAE;AAAA;AAMxB,SAAS,SAAS,CAAC,SAAsB,QAAuB;AAAA,EACrE,aAAa,OAAO,EAAE,SAAS;AAAA;AAM1B,SAAS,UAAU,CAAC,SAA2C;AAAA,EACpE,IAAI,UAA8B;AAAA,EAClC,OAAO,SAAS;AAAA,IACd,MAAM,SAAS,UAAU,OAAO;AAAA,IAChC,IAAI;AAAA,MAAQ,OAAO;AAAA,IACnB,UAAU,QAAQ;AAAA,EACpB;AAAA,EACA;AAAA;AAUK,SAAS,mBAAmB,CAAC,SAAmC;AAAA,EACrE,MAAM,OAAO,aAAa,OAAO;AAAA,EACjC,IAAI,CAAC,KAAK,kBAAkB;AAAA,IAC1B,KAAK,mBAAmB,IAAI;AAAA,EAC9B;AAAA,EACA,OAAO,KAAK;AAAA;AAMP,SAAS,iBAAiB,CAAC,SAAsB,UAA2B;AAAA,EACjF,OAAO,oBAAoB,OAAO,EAAE,IAAI,QAAQ;AAAA;AAM3C,SAAS,aAAa,CAAC,SAAsB,UAAwB;AAAA,EAC1E,oBAAoB,OAAO,EAAE,IAAI,QAAQ;AAAA;AAMpC,SAAS,eAAe,CAAC,SAAsB,UAAwB;AAAA,EAC5E,oBAAoB,OAAO,EAAE,OAAO,QAAQ;AAAA;AAUvC,SAAS,YAAY,CAAC,SAA0C;AAAA,EACrE,OAAO,aAAa,OAAO,EAAE;AAAA;AAMxB,SAAS,YAAY,CAAC,SAAsB,KAAmB;AAAA,EACpE,aAAa,OAAO,EAAE,YAAY;AAAA;AAU7B,SAAS,OAAU,CAAC,SAAsB,KAA4B;AAAA,EAC3E,OAAO,aAAa,OAAO,EAAE,OAAO;AAAA;AAM/B,SAAS,OAAU,CAAC,SAAsB,KAAa,OAAgB;AAAA,EAC5E,MAAM,OAAO,aAAa,OAAO;AAAA,EACjC,IAAI,CAAC,KAAK,MAAM;AAAA,IACd,KAAK,OAAO,CAAC;AAAA,EACf;AAAA,EACA,KAAK,KAAK,OAAO;AAAA;AAWZ,SAAS,mBAAmB,CAAC,SAA4B;AAAA,EAE9D,IAAI;AAAA,IACF,MAAM,cAAc,sBAAsB,OAAO;AAAA,IACjD,YAAY,QAAQ;AAAA,IACpB,MAAM;AAAA,EAKR,eAAe,OAAO;AAAA;AAkBjB,SAAS,eAAe,CAAC,SAA2C;AAAA,EAEzE,MAAM,SAAS,UAAU,OAAO;AAAA,EAChC,IAAI;AAAA,IAAQ,OAAO;AAAA,EAGnB,OAAQ,QAAgB,wBACrB,QAAgB;AAAA;AAMd,SAAS,eAAe,CAAC,SAAsB,QAAuB;AAAA,EAE3E,UAAU,SAAS,MAAM;AAAA,EACxB,QAAgB,gBAAgB;AAAA;AAAA,IA/L7B,gBAwKA,qBACA,0BACA;AAAA;AAAA,EA1KA,iBAAiB,IAAI;AAAA,EAwKrB,sBAAsB,OAAO,IAAI,cAAc;AAAA,EAC/C,2BAA2B,OAAO,IAAI,wBAAwB;AAAA,EAC9D,oBAAoB,OAAO,IAAI,iBAAiB;AAAA;;;;;;;AC3MtD;AAAA,2BACE;AAAA;AAAA;AAAA;AAwCF,SAAS,aAAa,CAAC,OAAyB;AAAA,EAC9C,IAAI,iBAAiB,KAAK;AAAA,IACxB,MAAM,MAA+B,CAAC;AAAA,IACtC,YAAY,KAAK,QAAQ,MAAM,QAAQ,GAAG;AAAA,MACxC,IAAI,OAAO,cAAc,GAAG;AAAA,IAC9B;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,IACxB,OAAO,MAAM,IAAI,CAAC,SAAS,cAAc,IAAI,CAAC;AAAA,EAChD;AAAA,EAEA,IAAI,SAAS,OAAO,UAAU,UAAU;AAAA,IACtC,MAAM,MAA+B,CAAC;AAAA,IACtC,YAAY,KAAK,QAAQ,OAAO,QAAQ,KAAK,GAAG;AAAA,MAC9C,IAAI,OAAO,cAAc,GAAG;AAAA,IAC9B;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAEA,OAAO;AAAA;AAMT,SAAS,oBAAoB,CAAC,OAG5B;AAAA,EAEA,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG;AAAA,MAC1B,OAAO,EAAE,YAAY,MAAM,SAAS,CAAC,EAAE;AAAA,IACzC;AAAA,IAEA,IAAI,aAAa,MAAM,UAAU,CAAC;AAAA,IAClC,IAAI,WAAW,WAAW,UAAU,GAAG;AAAA,MACrC,aAAa,WAAW,UAAU,CAAC;AAAA,IACrC;AAAA,IACA,OAAO,EAAE,YAAY,SAAS,CAAC,EAAE;AAAA,EACnC;AAAA,EAGA,IAAI,SAAS,OAAO,UAAU,UAAU;AAAA,IACtC,MAAM,QAAQ,cAAc,KAAK;AAAA,IACjC,MAAM,UAAmC,CAAC;AAAA,IAC1C,IAAI,aAA4B;AAAA,IAEhC,IAAI,SAAS,OAAO,UAAU,UAAU;AAAA,MACtC,MAAM,cAAc,MAAM;AAAA,MAC1B,IAAI,OAAO,gBAAgB,YAAY,YAAY,WAAW,GAAG,GAAG;AAAA,QAClE,aAAa,YAAY,UAAU,CAAC;AAAA,QACpC,IAAI,WAAW,WAAW,UAAU,GAAG;AAAA,UACrC,aAAa,WAAW,UAAU,CAAC;AAAA,QACrC;AAAA,MACF;AAAA,MAEA,YAAY,KAAK,QAAQ,OAAO,QAAQ,KAAK,GAAG;AAAA,QAC9C,IAAI,QAAQ,KAAK;AAAA,UAKf,IAAI,QAAQ,KAAK,GAAG,KAAK,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AAAA,YAC9E,YAAY,UAAU,aAAa,OAAO,QAAQ,GAAG,GAAG;AAAA,cACtD,QAAQ,YAAY;AAAA,YACtB;AAAA,UACF,EAAO;AAAA,YACL,QAAQ,OAAO;AAAA;AAAA,QAEnB;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OAAO,EAAE,YAAY,QAAQ;AAAA,EAC/B;AAAA,EAEA,OAAO,EAAE,YAAY,MAAM,SAAS,CAAC,EAAE;AAAA;AAMzC,SAAS,gBAAgB,CAAC,OAAc,SAA+C;AAAA,EACrF,MAAM,OAAgC;AAAA,IACpC,MAAM,MAAM;AAAA,IACZ,WAAW,KAAK,IAAI;AAAA,EACtB;AAAA,EAGA,IAAI,iBAAiB,YAAY;AAAA,IAC/B,KAAK,UAAU,MAAM;AAAA,IACrB,KAAK,UAAU,MAAM;AAAA,IACrB,KAAK,SAAS,MAAM;AAAA,EACtB;AAAA,EAGA,IAAI,iBAAiB,eAAe;AAAA,IAClC,KAAK,MAAM,MAAM;AAAA,IACjB,KAAK,OAAO,MAAM;AAAA,IAClB,KAAK,UAAU,MAAM;AAAA,IACrB,KAAK,WAAW,MAAM;AAAA,IACtB,KAAK,SAAS,MAAM;AAAA,IACpB,KAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAGA,IAAI,mBAAmB,oBAAoB,mBAAmB,qBAAqB;AAAA,IACjF,KAAK,QAAQ,QAAQ;AAAA,EACvB;AAAA,EAGA,IAAI,mBAAmB,mBAAmB;AAAA,IACxC,KAAK,QAAQ,QAAQ;AAAA,IACrB,KAAK,gBAAgB,QAAQ;AAAA,EAC/B;AAAA,EAGA,IAAI,MAAM,SAAS,YAAY,mBAAmB,iBAAiB;AAAA,IACjE,KAAK,WAAW,IAAI,SAAS,OAAO;AAAA,EACtC;AAAA,EAEA,OAAO;AAAA;AAmBT,SAAS,kBAAkB,CACzB,WACA,UAA+B,CAAC,GACb;AAAA,EACnB,OAAO,CAAC,SAAsB,UAAmB;AAAA,IAC/C,QAAQ,YAAY,SAAS,kBAAkB,qBAAqB,KAAK;AAAA,IAEzE,IAAI,CAAC,YAAY;AAAA,MACf,QAAQ,KACN,qBAAqB,gEACrB,KACF;AAAA,MACA;AAAA,IACF;AAAA,IAEA,MAAM,cAAc,uBAAsB,OAAO;AAAA,IAIjD,MAAM,WAAW,GAAG,aAAa;AAAA,IACjC,IAAI,oBAAoB,OAAO,EAAE,IAAI,QAAQ,GAAG;AAAA,MAG9C;AAAA,IACF;AAAA,IACA,cAAc,SAAS,QAAQ;AAAA,IAG/B,IAAI,gBAAmC;AAAA,IAGvC,MAAM,WAAW,CAAC,UAAiB;AAAA,MAEjC,IAAI,QAAQ,cAAc,eAAe;AAAA,QACvC;AAAA,MACF;AAAA,MAEA,IAAI,QAAQ,YAAY;AAAA,QACtB,gBAAgB,kBAAkB,MAAM;AAAA,UACtC,gBAAgB;AAAA,WACf,QAAQ,UAAU;AAAA,MACvB;AAAA,MAGA,IAAI,QAAQ,gBAAgB;AAAA,QAC1B,MAAM,eAAe;AAAA,MACvB;AAAA,MAGA,MAAM,UACJ,OAAO,KAAK,aAAa,EAAE,SAAS,IAChC,KAAK,cAAc,IACnB,QAAQ,iBACN,QAAQ,eAAe,OAAO,OAAO,IACrC,iBAAiB,OAAO,OAAO;AAAA,MAGvC,MAAM,SAAS,UAAU,OAAO;AAAA,MAChC,IAAI,QAAQ;AAAA,QACV,OAAO,eAAe,YAAY,OAAO;AAAA,MAC3C;AAAA;AAAA,IAIF,YAAY,IACV,mBAAmB,SAAS,WAAW,UAAU;AAAA,MAC/C,SAAS,QAAQ;AAAA,IACnB,CAAC,CACH;AAAA,IAGA,YAAY,YAAY,MAAM;AAAA,MAC5B,gBAAgB,SAAS,QAAQ;AAAA,MACjC,IAAI,eAAe;AAAA,QACjB,cAAc,QAAQ;AAAA,MACxB;AAAA,KACD;AAAA;AAAA;AAOL,SAAS,gBAAgB,CAAC,aAAqB,SAA4B;AAAA,EACzE,OAAO,CAAC,SAAsB,UAAmB;AAAA,IAC/C,QAAQ,YAAY,SAAS,kBAAkB,qBAAqB,KAAK;AAAA,IAEzE,IAAI,CAAC,YAAY;AAAA,MACf,QAAQ,KACN,8EACA,KACF;AAAA,MACA;AAAA,IACF;AAAA,IAEA,MAAM,cAAc,uBAAsB,OAAO;AAAA,IAEjD,MAAM,WAAW,WAAW,cAAc;AAAA,IAC1C,IAAI,oBAAoB,OAAO,EAAE,IAAI,QAAQ,GAAG;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,cAAc,SAAS,QAAQ;AAAA,IAG/B,MAAM,YAAY,aAAa,OAAO,KAAK;AAAA,IAC3C,MAAM,aAAa,UAAU,YAAY,MAAM,WAAW,UAAU;AAAA,IAEpE,MAAM,WAAW,CAAC,UAAiB;AAAA,MACjC,MAAM,WAAW;AAAA,MACjB,IAAI,SAAS,QAAQ,YAAY;AAAA,QAC/B;AAAA,MACF;AAAA,MAEA,MAAM,eAAe;AAAA,MAErB,MAAM,SAAS,MAAM;AAAA,MACrB,MAAM,UACJ,OAAO,KAAK,aAAa,EAAE,SAAS,IAChC,KAAK,cAAc,IACnB;AAAA,QACE,MAAM,MAAM;AAAA,QACZ,WAAW,KAAK,IAAI;AAAA,QACpB,KAAK,SAAS;AAAA,QACd,MAAM,SAAS;AAAA,QACf,OAAO,OAAO;AAAA,QACd,OAAO,OAAO;AAAA,QACd,SAAS,SAAS;AAAA,QAClB,UAAU,SAAS;AAAA,QACnB,QAAQ,SAAS;AAAA,QACjB,SAAS,SAAS;AAAA,MACpB;AAAA,MAEN,MAAM,SAAS,UAAU,OAAO;AAAA,MAChC,IAAI,QAAQ;AAAA,QACV,OAAO,eAAe,YAAY,OAAO;AAAA,MAC3C;AAAA;AAAA,IAGF,YAAY,IAAI,mBAAmB,SAAS,WAAW,QAAQ,CAAC;AAAA,IAChE,YAAY,YAAY,MAAM;AAAA,MAC5B,gBAAgB,SAAS,QAAQ;AAAA,KAClC;AAAA;AAAA;AAOL,SAAS,sBAAsB,CAAC,cAAsB,KAAwB;AAAA,EAC5E,OAAO,CAAC,SAAsB,UAAmB;AAAA,IAC/C,QAAQ,YAAY,SAAS,kBAAkB,qBAAqB,KAAK;AAAA,IAEzE,IAAI,CAAC,YAAY;AAAA,MACf,QAAQ,KACN,oFACA,KACF;AAAA,MACA;AAAA,IACF;AAAA,IAEA,MAAM,cAAc,uBAAsB,OAAO;AAAA,IAEjD,MAAM,WAAW,aAAa;AAAA,IAC9B,IAAI,oBAAoB,OAAO,EAAE,IAAI,QAAQ,GAAG;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,cAAc,SAAS,QAAQ;AAAA,IAE/B,IAAI,iBAAoC;AAAA,IAExC,MAAM,eAAe,CAAC,UAAiB;AAAA,MACrC,MAAM,eAAe;AAAA,MAErB,iBAAiB,kBAAkB,MAAM;AAAA,QACvC,MAAM,UACJ,OAAO,KAAK,aAAa,EAAE,SAAS,IAChC,KAAK,cAAc,IACnB;AAAA,UACE,MAAM;AAAA,UACN,WAAW,KAAK,IAAI;AAAA,UACpB,SAAS,aAAa;AAAA,UACtB,SAAS,aAAa;AAAA,QACxB;AAAA,QAEN,MAAM,SAAS,UAAU,OAAO;AAAA,QAChC,IAAI,QAAQ;AAAA,UACV,OAAO,eAAe,YAAY,OAAO;AAAA,QAC3C;AAAA,QAEA,iBAAiB;AAAA,SAChB,WAAW;AAAA;AAAA,IAGhB,MAAM,iBAAiB,MAAM;AAAA,MAC3B,IAAI,gBAAgB;AAAA,QAClB,eAAe,QAAQ;AAAA,QACvB,iBAAiB;AAAA,MACnB;AAAA;AAAA,IAGF,YAAY,IAAI,mBAAmB,SAAS,eAAe,YAAY,CAAC;AAAA,IACxE,YAAY,IAAI,mBAAmB,SAAS,aAAa,cAAc,CAAC;AAAA,IACxE,YAAY,IAAI,mBAAmB,SAAS,gBAAgB,cAAc,CAAC;AAAA,IAC3E,YAAY,YAAY,MAAM;AAAA,MAC5B,gBAAgB,SAAS,QAAQ;AAAA,MACjC,eAAe;AAAA,KAChB;AAAA;AAAA;AAAA,IAQC,eAAe,CAAC,OAAc,YAAkD;AAAA,EACpF,MAAM,SAAS;AAAA,EACf,OAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,WAAW,KAAK,IAAI;AAAA,IACpB,OAAO,OAAO;AAAA,IACd,OAAO,OAAO;AAAA,EAChB;AAAA,GAGI,gBAAgB,CAAC,QAAe,YAAkD;AAAA,EACtF,MAAM,YAAY,QAAQ;AAAA,EAC1B,MAAM,eAAe,QAAQ;AAAA,EAC7B,MAAM,eAAe,QAAQ;AAAA,EAC7B,MAAM,mBACJ,eAAe,eAAe,IACzB,aAAa,eAAe,gBAAiB,MAC9C;AAAA,EAEN,MAAM,aACJ,eAAe,YAAY,eAAe,OAAO,mBAAmB;AAAA,EAEtE,OAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,IACA,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,kBAAkB,KAAK,MAAM,gBAAgB;AAAA,IAC7C;AAAA,IACA,UAAU,eAAe,cAAc;AAAA,IACvC,OAAO,cAAc;AAAA,EACvB;AAAA,GAGI,eAAe,CAAC,OAAc,aAAmD;AAAA,EACrF,MAAM,MAAM;AAAA,EACZ,WAAW,KAAK,IAAI;AAAA,EACpB,OAAQ,QAA6B,SAAS;AAChD,IAEM,eAAe,CAAC,OAAc,aAAmD;AAAA,EACrF,MAAM,aAAa;AAAA,EACnB,OAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,WAAW,KAAK,IAAI;AAAA,IACpB,SAAS,WAAW;AAAA,IACpB,SAAS,WAAW;AAAA,EACtB;AAAA,GAOW;AAAA;AAAA,EAlcb;AAAA,EAkca,gBAAmD;AAAA,IAE9D,SAAS,mBAAmB,OAAO;AAAA,IACnC,SAAS,mBAAmB,OAAO;AAAA,IAGnC,UAAU,mBAAmB,QAAQ;AAAA,IACrC,UAAU,mBAAmB,UAAU,EAAE,gBAAgB,KAAK,CAAC;AAAA,IAC/D,SAAS,mBAAmB,SAAS,EAAE,gBAAgB,aAAa,CAAC;AAAA,IAGrE,OAAO,iBAAiB,OAAO;AAAA,IAC/B,aAAa,CAAC,SAAsB,UAAmB;AAAA,MAErD,aAAa,SAAS,OAAO,KAAK,CAAC;AAAA;AAAA,IAErC,gBAAgB,iBAAiB,OAAO;AAAA,IAGxC,UAAU,mBAAmB,UAAU;AAAA,MACrC,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,gBAAgB;AAAA,IAClB,CAAC;AAAA,IAGD,aAAa,uBAAuB,GAAG;AAAA,IAGvC,SAAS,mBAAmB,SAAS,EAAE,gBAAgB,aAAa,CAAC;AAAA,IACrE,QAAQ,mBAAmB,QAAQ,EAAE,gBAAgB,aAAa,CAAC;AAAA,IAGnE,cAAc,mBAAmB,cAAc,EAAE,gBAAgB,aAAa,CAAC;AAAA,IAC/E,cAAc,mBAAmB,cAAc,EAAE,gBAAgB,aAAa,CAAC;AAAA,EACjF;AAAA;",
9
+ "debugId": "CA4C1AC3006CE18464756E2164756E21",
9
10
  "names": []
10
11
  }
@@ -30,10 +30,64 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
30
  // src/dom/applicators/font.ts
31
31
  var exports_font = {};
32
32
  __export(exports_font, {
33
- fontHandlers: () => fontHandlers
33
+ fontHandlers: () => fontHandlers,
34
+ GoogleFonts: () => GoogleFonts
34
35
  });
35
- var fontHandlers;
36
+ function isSystemFont(fontName) {
37
+ const normalized = fontName.toLowerCase().trim();
38
+ return systemFontKeywords.has(normalized) || normalized.startsWith("-") || normalized.startsWith("ui-");
39
+ }
40
+ function loadGoogleFont(fontName) {
41
+ const normalized = fontName.trim();
42
+ if (loadedGoogleFonts.has(normalized) || isSystemFont(normalized)) {
43
+ return;
44
+ }
45
+ loadedGoogleFonts.add(normalized);
46
+ const link = document.createElement("link");
47
+ link.rel = "stylesheet";
48
+ link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(normalized)}:wght@100;200;300;400;500;600;700;800;900&display=swap`;
49
+ document.head.appendChild(link);
50
+ }
51
+ function processFontFamily(value) {
52
+ const fonts = value.split(",").map((f) => f.trim().replace(/["']/g, ""));
53
+ for (const font of fonts) {
54
+ if (!isSystemFont(font)) {
55
+ loadGoogleFont(font);
56
+ }
57
+ }
58
+ return fonts.map((f) => {
59
+ if (f.includes(" ") && !f.startsWith('"') && !f.startsWith("'")) {
60
+ return `"${f}"`;
61
+ }
62
+ return f;
63
+ }).join(", ");
64
+ }
65
+ var loadedGoogleFonts, systemFontKeywords, fontHandlers, GoogleFonts;
36
66
  var init_font = __esm(() => {
67
+ loadedGoogleFonts = new Set;
68
+ systemFontKeywords = new Set([
69
+ "default",
70
+ "system",
71
+ "system-ui",
72
+ "inherit",
73
+ "initial",
74
+ "unset",
75
+ "serif",
76
+ "sans-serif",
77
+ "monospace",
78
+ "cursive",
79
+ "fantasy",
80
+ "-apple-system",
81
+ "BlinkMacSystemFont",
82
+ "Segoe UI",
83
+ "Arial",
84
+ "Helvetica",
85
+ "Times New Roman",
86
+ "Georgia",
87
+ "Courier New",
88
+ "Verdana",
89
+ "Tahoma"
90
+ ]);
37
91
  fontHandlers = {
38
92
  fontSize: (el, value) => {
39
93
  el.style.fontSize = typeof value === "number" ? `${value}px` : String(value);
@@ -42,20 +96,55 @@ var init_font = __esm(() => {
42
96
  el.style.fontWeight = String(value);
43
97
  },
44
98
  fontFamily: (el, value) => {
45
- el.style.fontFamily = String(value);
99
+ const fontValue = String(value);
100
+ el.style.fontFamily = processFontFamily(fontValue);
46
101
  },
47
102
  textAlign: (el, value) => {
48
103
  el.style.textAlign = String(value);
49
104
  },
50
105
  lineHeight: (el, value) => {
51
106
  el.style.lineHeight = String(value);
107
+ },
108
+ fontStyle: (el, value) => {
109
+ el.style.fontStyle = String(value);
110
+ },
111
+ textTransform: (el, value) => {
112
+ el.style.textTransform = String(value);
52
113
  }
53
114
  };
115
+ GoogleFonts = {
116
+ preload: loadGoogleFont,
117
+ isLoaded: (fontName) => loadedGoogleFonts.has(fontName.trim()),
118
+ getLoadedFonts: () => Array.from(loadedGoogleFonts),
119
+ popular: [
120
+ "Roboto",
121
+ "Open Sans",
122
+ "Lato",
123
+ "Montserrat",
124
+ "Poppins",
125
+ "Inter",
126
+ "Nunito",
127
+ "Playfair Display",
128
+ "Merriweather",
129
+ "Source Code Pro",
130
+ "Fira Code",
131
+ "JetBrains Mono",
132
+ "Raleway",
133
+ "Ubuntu",
134
+ "Oswald",
135
+ "Quicksand",
136
+ "Work Sans",
137
+ "Rubik",
138
+ "Karla",
139
+ "DM Sans"
140
+ ]
141
+ };
54
142
  });
55
143
  init_font();
56
144
 
57
145
  export {
58
- fontHandlers
146
+ fontHandlers,
147
+ GoogleFonts
59
148
  };
60
149
 
61
- //# debugId=4C6C968B3602704064756E2164756E21
150
+ //# debugId=EACB7C8E1E2F066664756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/dom/applicators/font.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * Font Applicators\n */\n\nimport type { ApplicatorHandler } from \"./index.js\";\n\nexport const fontHandlers: Record<string, ApplicatorHandler> = {\n fontSize: (el, value) => {\n el.style.fontSize = typeof value === \"number\" ? `${value}px` : String(value);\n },\n\n fontWeight: (el, value) => {\n el.style.fontWeight = String(value);\n },\n\n fontFamily: (el, value) => {\n el.style.fontFamily = String(value);\n },\n\n textAlign: (el, value) => {\n el.style.textAlign = String(value);\n },\n\n lineHeight: (el, value) => {\n el.style.lineHeight = String(value);\n },\n};\n"
5
+ "/**\n * Font Applicators with Google Fonts support\n */\n\nimport type { ApplicatorHandler } from \"./index.js\";\n\n// Track loaded Google Fonts to avoid duplicate link tags\nconst loadedGoogleFonts = new Set<string>();\n\n// System font keywords that shouldn't be loaded from Google Fonts\nconst systemFontKeywords = new Set([\n \"default\", \"system\", \"system-ui\", \"inherit\", \"initial\", \"unset\",\n \"serif\", \"sans-serif\", \"monospace\", \"cursive\", \"fantasy\",\n \"-apple-system\", \"BlinkMacSystemFont\", \"Segoe UI\", \"Arial\", \"Helvetica\",\n \"Times New Roman\", \"Georgia\", \"Courier New\", \"Verdana\", \"Tahoma\",\n]);\n\n/**\n * Check if a font name is a system font or generic CSS font.\n */\nfunction isSystemFont(fontName: string): boolean {\n const normalized = fontName.toLowerCase().trim();\n return systemFontKeywords.has(normalized) ||\n normalized.startsWith(\"-\") ||\n normalized.startsWith(\"ui-\");\n}\n\n/**\n * Load a Google Font by injecting a link tag.\n * @param fontName - The Google Font name (e.g., \"Roboto\", \"Open Sans\")\n */\nfunction loadGoogleFont(fontName: string): void {\n const normalized = fontName.trim();\n\n // Skip if already loaded or is a system font\n if (loadedGoogleFonts.has(normalized) || isSystemFont(normalized)) {\n return;\n }\n\n // Mark as loading to avoid duplicates\n loadedGoogleFonts.add(normalized);\n\n // Create link element for Google Fonts\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(normalized)}:wght@100;200;300;400;500;600;700;800;900&display=swap`;\n\n // Add to document head\n document.head.appendChild(link);\n}\n\n/**\n * Parse a fontFamily value and load any Google Fonts.\n * Returns a CSS-safe font-family string.\n */\nfunction processFontFamily(value: string): string {\n // Split by comma to handle font stacks\n const fonts = value.split(\",\").map(f => f.trim().replace(/[\"']/g, \"\"));\n\n for (const font of fonts) {\n if (!isSystemFont(font)) {\n loadGoogleFont(font);\n }\n }\n\n // Return original value with proper quoting for CSS\n return fonts.map(f => {\n // Quote font names that contain spaces or special characters\n if (f.includes(\" \") && !f.startsWith('\"') && !f.startsWith(\"'\")) {\n return `\"${f}\"`;\n }\n return f;\n }).join(\", \");\n}\n\nexport const fontHandlers: Record<string, ApplicatorHandler> = {\n fontSize: (el, value) => {\n el.style.fontSize = typeof value === \"number\" ? `${value}px` : String(value);\n },\n\n fontWeight: (el, value) => {\n el.style.fontWeight = String(value);\n },\n\n fontFamily: (el, value) => {\n const fontValue = String(value);\n // Process font family and load Google Fonts as needed\n el.style.fontFamily = processFontFamily(fontValue);\n },\n\n textAlign: (el, value) => {\n el.style.textAlign = String(value);\n },\n\n lineHeight: (el, value) => {\n el.style.lineHeight = String(value);\n },\n\n fontStyle: (el, value) => {\n // Support: normal, italic, oblique\n el.style.fontStyle = String(value);\n },\n\n textTransform: (el, value) => {\n // Support: none, capitalize, uppercase, lowercase\n el.style.textTransform = String(value);\n },\n};\n\n// Export the font loading utility for manual use\nexport const GoogleFonts = {\n /**\n * Preload a Google Font before it's used.\n */\n preload: loadGoogleFont,\n\n /**\n * Check if a font has been loaded.\n */\n isLoaded: (fontName: string) => loadedGoogleFonts.has(fontName.trim()),\n\n /**\n * Get list of loaded fonts.\n */\n getLoadedFonts: () => Array.from(loadedGoogleFonts),\n\n /**\n * Popular Google Fonts for reference.\n */\n popular: [\n \"Roboto\",\n \"Open Sans\",\n \"Lato\",\n \"Montserrat\",\n \"Poppins\",\n \"Inter\",\n \"Nunito\",\n \"Playfair Display\",\n \"Merriweather\",\n \"Source Code Pro\",\n \"Fira Code\",\n \"JetBrains Mono\",\n \"Raleway\",\n \"Ubuntu\",\n \"Oswald\",\n \"Quicksand\",\n \"Work Sans\",\n \"Rubik\",\n \"Karla\",\n \"DM Sans\",\n ],\n};\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMa;AAAA;AAAA,iBAAkD;AAAA,IAC7D,UAAU,CAAC,IAAI,UAAU;AAAA,MACvB,GAAG,MAAM,WAAW,OAAO,UAAU,WAAW,GAAG,YAAY,OAAO,KAAK;AAAA;AAAA,IAG7E,YAAY,CAAC,IAAI,UAAU;AAAA,MACzB,GAAG,MAAM,aAAa,OAAO,KAAK;AAAA;AAAA,IAGpC,YAAY,CAAC,IAAI,UAAU;AAAA,MACzB,GAAG,MAAM,aAAa,OAAO,KAAK;AAAA;AAAA,IAGpC,WAAW,CAAC,IAAI,UAAU;AAAA,MACxB,GAAG,MAAM,YAAY,OAAO,KAAK;AAAA;AAAA,IAGnC,YAAY,CAAC,IAAI,UAAU;AAAA,MACzB,GAAG,MAAM,aAAa,OAAO,KAAK;AAAA;AAAA,EAEtC;AAAA;",
8
- "debugId": "4C6C968B3602704064756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "EACB7C8E1E2F066664756E2164756E21",
9
9
  "names": []
10
10
  }