@lucidclient/elements
Version:
A lightweight, reactive UI library that bridges HTML and JavaScript through attributes, powered by SolidJS. Adds reactive state and dynamic behaviors to markup while maintaining simplicity.
1 lines • 5.01 kB
Source Map (JSON)
{"version":3,"sources":["/Users/williamyallop/Documents/projects/protodigital/internal/lucid-client/packages/elements/dist/handlers.cjs","../src/handlers/events/index.ts"],"names":["namespace","createEventHandler","member","e","createEventKey","eventName","actionKey"],"mappings":"AAAA,qoBAA+D,ICazDA,CAAAA,CAAY,OAAA,CAKZC,CAAAA,CAAsBC,CAAAA,EACvBA,CAAAA,CAAO,IAAA,GAAS,QAAA,CAAkBC,CAAAA,EAAaD,CAAAA,CAAO,MAAA,CAAOC,CAAC,CAAA,CAC1DA,CAAAA,EAAa,OAAA,CAAQ,GAAA,CAAID,CAAAA,CAAO,MAAM,CAAA,CAMzCE,CAAAA,CAAiB,CAACC,CAAAA,CAAmBC,CAAAA,CAAAA,EACnC,CAAA,EAAA","file":"/Users/williamyallop/Documents/projects/protodigital/internal/lucid-client/packages/elements/dist/handlers.cjs","sourcesContent":[null,"import Elements from \"../../core/elements.js\";\nimport { buildHandlerSelector, findStoreMember } from \"../../helpers.js\";\nimport type { EventConfig } from \"./types.js\";\nimport type {\n\tHandler,\n\tHandlerSpecifiersMap,\n\tAction,\n\tStoreMember,\n} from \"../../types/index.js\";\n\n/**\n * The namespace for the event handler\n */\nconst namespace = \"event\";\n\n/**\n * Create an event handler function that can be stored and removed later\n */\nconst createEventHandler = (member: StoreMember): Action => {\n\tif (member.type === \"action\") return (e: Event) => member.member(e);\n\treturn (e: Event) => console.log(member.member);\n};\n\n/**\n * Create a unique key for storing event listeners\n */\nconst createEventKey = (eventName: string, actionKey: string): string => {\n\treturn `${eventName}:${actionKey}`;\n};\n\n/**\n * Parses the event specifier and determins the target and event type\n */\nconst parseEventSpecifier = (specifier: string): EventConfig => {\n\tconst parts = specifier.split(Elements.options.attributes.seperators.handler);\n\n\tconst config: EventConfig = {\n\t\ttarget: \"element\",\n\t\teventName: parts[0],\n\t};\n\n\tif (parts[0] && parts.length > 1) {\n\t\tconst possibleTargets = [\"document\", \"body\", \"head\", \"window\"];\n\n\t\tif (possibleTargets.includes(parts[0])) {\n\t\t\tconfig.target = parts[0] as EventConfig[\"target\"];\n\t\t\tconfig.eventName = parts[1];\n\t\t}\n\t}\n\n\treturn config;\n};\n\n/**\n * Returns the correct target based\n */\nconst getTargetElement = (\n\tconfig: EventConfig,\n): HTMLElement | Document | Window => {\n\tswitch (config.target) {\n\t\tcase \"document\":\n\t\t\treturn document;\n\t\tcase \"body\":\n\t\t\treturn document.body;\n\t\tcase \"head\":\n\t\t\treturn document.head;\n\t\tcase \"window\":\n\t\t\treturn window;\n\t\tdefault:\n\t\t\treturn document;\n\t}\n};\n\n/**\n * Handles registering event listeners\n */\nconst registerEvents = (\n\tattributes: HandlerSpecifiersMap,\n\tabortController: AbortController,\n\teventListenerMap: Map<string, Map<Element | Document | Window, Action>>,\n) => {\n\tfor (const event of attributes) {\n\t\tconst [eventSpecifier, actions] = event;\n\t\tconst config = parseEventSpecifier(eventSpecifier);\n\t\tif (!config.eventName) continue;\n\n\t\tfor (const key of actions) {\n\t\t\tconst member = findStoreMember(key);\n\t\t\tif (!member) continue;\n\n\t\t\tconst eventKey = createEventKey(eventSpecifier, key);\n\n\t\t\tif (!eventListenerMap.has(eventKey)) {\n\t\t\t\teventListenerMap.set(eventKey, new Map());\n\t\t\t}\n\t\t\tconst elementMap = eventListenerMap.get(eventKey);\n\t\t\tif (!elementMap) continue;\n\n\t\t\tif (config.target === \"element\") {\n\t\t\t\tconst targets = document.querySelectorAll(\n\t\t\t\t\tbuildHandlerSelector(namespace, eventSpecifier, key),\n\t\t\t\t);\n\n\t\t\t\tfor (const target of targets) {\n\t\t\t\t\tif (elementMap.has(target)) continue;\n\n\t\t\t\t\tconst handler = createEventHandler(member);\n\t\t\t\t\ttarget.addEventListener(config.eventName, handler, {\n\t\t\t\t\t\tsignal: abortController?.signal,\n\t\t\t\t\t});\n\t\t\t\t\telementMap.set(target, handler);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst target = getTargetElement(config);\n\t\t\t\tif (elementMap.has(target)) continue;\n\n\t\t\t\tconst handler = createEventHandler(member);\n\t\t\t\ttarget.addEventListener(config.eventName, handler, {\n\t\t\t\t\tsignal: abortController?.signal,\n\t\t\t\t});\n\t\t\t\telementMap.set(target, handler);\n\t\t\t}\n\t\t}\n\t}\n};\n\n/**\n * Registers the event handler which supports all event listeners. These can be used like so:\n * - data-handler--event.click\n * - data-handler--event.scroll\n * - data-handler--event.keydown\n * - data-handler--event.keyup\n *\n * Any actions assigned to these events will have the Event as the first argument.\n */\nconst eventsHandler: Handler = {\n\tnamespace: namespace,\n\tinitialise: (attributes, options) => {\n\t\tconst abortController = new AbortController();\n\t\tconst eventListenerMap = new Map<\n\t\t\tstring,\n\t\t\tMap<Element | Document | Window, Action>\n\t\t>();\n\n\t\tregisterEvents(attributes, abortController, eventListenerMap);\n\n\t\treturn () => {\n\t\t\tabortController.abort();\n\t\t\teventListenerMap.clear();\n\t\t};\n\t},\n};\n\nexport default eventsHandler;\n"]}