{"version":3,"file":"echo.cjs","sources":["../packages/echo/interfaces.js","../packages/echo/target.js","../packages/echo/echo.js"],"sourcesContent":["/**\n * Identificador exclusivo do callback executado ao conectar um arco Echo.\n *\n * @const {symbol}\n * @description\n * Utilizado internamente pelo mixin `Echo` para configurar os listeners associados\n * ao atributo `on`. Esse callback é chamado quando o atributo `on` é adicionado ou alterado,\n * permitindo o registro de novos arcos declarativos (eventos que chegam no componente).\n */\nexport const connectArc = Symbol.for(\"connectArc\");\n\n/**\n * Identificador exclusivo do callback executado ao desconectar um arco Echo.\n *\n * @const {symbol}\n * @description\n * Utilizado internamente pelo mixin `Echo` para remover listeners de eventos\n * registrados via o atributo `on`. É chamado ao remover o valor do atributo `on` ou\n * quando o componente é desconectado do DOM.\n */\nexport const disconnectArc = Symbol.for(\"disconnectArc\");\n\n/**\n * Identificador exclusivo para o atributo `on`, utilizado para declarar escutas reativas.\n *\n * @const {symbol}\n * @description\n * Usado para indicar que o mixin `Echo` deve observar mudanças no atributo `on`,\n * que define os protocolos de roteamento de eventos externos para destinos internos\n * (atributos, setters ou métodos). Cada valor do `on` representa um grafo declarativo.\n */\nexport const on = \"on\";\n","/**\n * Canal global de eventos utilizado pelo mixin `Echo`.\n *\n * @const {EventTarget}\n *\n * @description\n * O `target` atua como um barramento de eventos interno entre componentes personalizados.\n * Ele é usado pelo mixin `Echo` para despachar e ouvir eventos com base nos protocolos\n * declarados no atributo `on`.\n *\n * Ao invés de registrar eventos diretamente no `document` ou em elementos específicos,\n * o `Echo` utiliza esta instância única de `EventTarget` para garantir isolamento e performance.\n *\n * Esse canal também facilita a composição entre componentes sem acoplamento direto.\n *\n * @example\n * target.addEventListener(\"deck/review:method>markCorrect\", (event) => {\n *   // processa valor transformado e repassa para o método\n * });\n */\nconst target = new EventTarget();\n\nexport default target;\n","import spark from \"@spark\";\nimport { connectArc, disconnectArc, on } from \"./interfaces\";\nimport target from \"./target\";\n\n/**\n * Mixin Echo\n *\n * @param {CustomElementConstructor} Klass - A classe base (geralmente HTMLElement).\n * @returns {Klass} Uma nova classe estendida com suporte ao atributo `on`.\n *\n * @description\n * O mixin `Echo` adiciona suporte ao atributo `on`, permitindo que eventos externos\n * sejam mapeados para atributos, métodos ou setters do próprio componente.\n *\n * Ele observa o atributo `on`, escuta eventos no escopo do DOM e realiza o roteamento\n * declarativo via arcos no formato: `source/event:type/sink|sparks`.\n *\n * Os filtros (sparks) são aplicados antes da atribuição do valor no destino.\n * Este mixin é não opinativo, compatível com o ciclo de vida nativo e com outros decorators.\n *\n * @example\n * class MyElement extends Echo(HTMLElement) {\n *   set color(value) {\n *     this.style.color = value;\n *   }\n * }\n */\nconst Echo = (Klass) => {\n  class Host extends Klass {\n    #controllers = {};\n\n    /**\n     * Define os atributos observados pelo componente, incluindo o `on`.\n     * Isso permite reagir dinamicamente a alterações no atributo `on` e\n     * registrar ou remover arcos declarados.\n     */\n    static observedAttributes = [...(Klass.observedAttributes ?? []), on];\n\n    /**\n     * Intercepta mudanças em atributos observados.\n     * No caso do Echo, lida com a ativação/desativação de arcos declarados via `on`.\n     *\n     * @param {string} name - Nome do atributo alterado.\n     * @param {string|null} oldValue - Valor anterior do atributo.\n     * @param {string|null} newValue - Novo valor do atributo.\n     * @returns {this}\n     */\n    attributeChangedCallback(name, oldValue, newValue) {\n      super.attributeChangedCallback?.(name, oldValue, newValue);\n\n      if (name === on) {\n        this[disconnectArc](oldValue);\n        this[connectArc](newValue);\n      }\n\n      return this;\n    }\n\n    /**\n     * Encerra todos os arcos ativos quando o elemento é removido do DOM.\n     *\n     * @returns {this}\n     */\n    disconnectedCallback() {\n      super.disconnectedCallback?.();\n\n      for (const arc of Object.keys(this.#controllers)) {\n        this[disconnectArc](arc);\n      }\n\n      return this;\n    }\n\n    /**\n     * Dispara um evento customizado para que outros componentes Echo possam reagir.\n     *\n     * O nome do evento é mantido (sem prefixo) e o payload `detail` inclui:\n     *\n     * - `attribute.id`: valor do atributo `id` do componente.\n     * - `attribute.name`: valor do atributo `name`.\n     * - `node`: nome da tag (`localName`).\n     * - `token`: conteúdo original do `event.detail` recebido.\n     *\n     * Essa estrutura padroniza os metadados de origem para filtragem por parte dos listeners.\n     *\n     * @param {CustomEvent} event - Evento a ser despachado.\n     */\n    dispatchEvent(event) {\n      super.dispatchEvent?.(event);\n\n      target.dispatchEvent(\n        new CustomEvent(event.type, {\n          detail: {\n            attribute: {\n              id: this.getAttribute(\"id\"),\n              name: this.getAttribute(\"name\"),\n            },\n            node: this.localName,\n            token: event.detail,\n          },\n        }),\n      );\n    }\n\n    /**\n     * Interpreta e executa um arco definido no atributo `on`.\n     *\n     * Um arco define:\n     * - `source`: origem do evento (`id`, `name` ou `tag`).\n     * - `event`: tipo do evento.\n     * - `type`: tipo de execução (method, setter ou attribute).\n     * - `sink`: destino no componente.\n     * - `filters`: transformations aplicadas ao valor antes de chegar no destino.\n     *\n     * @param {string} arc - Arco no formato `source/event:type/sink|filters`.\n     * @returns {this}\n     */\n    [connectArc](arc) {\n      this.#controllers[arc] = new AbortController();\n\n      const [, source, event, type, sink, filters] =\n        arc.match(/^([*#\\w-]+)\\/([\\w-]+):([a-z]+)\\/([\\w-]+)(?:\\|(.*))?$/i) ||\n        [];\n\n      const transforms = (filters || \"\")\n        .split(\"|\")\n        .filter(Boolean)\n        .map((filter) => filter.split(\"=\"))\n        .map(([name, value]) => [spark.get(name), value]);\n\n      target.addEventListener(\n        event,\n        (e) => {\n          const {\n            attribute: { id, name },\n            node,\n            token,\n          } = e.detail;\n\n          if (new RegExp(`^(\\\\*|#${id}|${name}|${node})$`, \"i\").test(source)) {\n            const payload = transforms.reduce(\n              (data, [fn, value]) => fn(data, value),\n              token,\n            );\n\n            if (/method$/i.test(type)) this[sink]?.(payload);\n            if (/attribute$/i.test(type)) this.setAttribute(sink, payload);\n            if (/setter$/i.test(type)) this[sink] = payload;\n          }\n\n          return this;\n        },\n        {\n          signal: this.#controllers[arc].signal,\n        },\n      );\n\n      return this;\n    }\n\n    /**\n     * Remove o listener associado a um arco específico utilizando AbortController.\n     *\n     * @param {string} arc - Arco que será desconectado.\n     * @returns {this}\n     */\n    [disconnectArc](arc) {\n      this.#controllers[arc]?.abort();\n      return this;\n    }\n  }\n\n  return Host;\n};\n\nexport default Echo;\n"],"names":["connectArc","Symbol","for","disconnectArc","target","EventTarget","Klass","Host","controllers","name","oldValue","newValue","super","attributeChangedCallback","this","disconnectedCallback","arc","Object","keys","event","dispatchEvent","CustomEvent","type","detail","attribute","id","getAttribute","node","localName","token","AbortController","source","sink","filters","match","transforms","split","filter","Boolean","map","value","spark","default","get","addEventListener","e","RegExp","test","payload","reduce","data","fn","setAttribute","signal","abort","static","observedAttributes"],"mappings":";;;;;;;;;;;kCASaA,IAAaC,OAAOC,IAAI,YAAA,GAWxBC,IAAgBF,OAAOC,IAAI,eAAA,GCAlCE,IAAS,IAAIC;kBCOLC,OACZ;;EAAA,MAAMC,UAAaD,EAAAA;AAAAA,IAAnB;AAAA;AACEE,6BAAe,CAAE;AAAA;AAAA,IAkBjB,yBAAyBC,IAAMC,IAAUC,IAQvC;;AAAA,cAPAC,WAAMC,6BAAND,8BAAiCH,IAAMC,IAAUC,KFjBrC,SEmBRF,OACFK,KAAKX,GAAeO,EACpBI,GAAAA,KAAKd,CAAYW,EAAAA,EAAAA,IAGZG;AAAAA,IACb;AAAA,IAOI,uBAAAC;;AACEH,kBAAMG,yBAANH;AAEA,iBAAWI,MAAOC,OAAOC,KAAKJ,mBAAKN,GAAAA,EACjCM,MAAKX,CAAAA,EAAea,EAGtB;AAAA,aAAOF;AAAAA,IACb;AAAA,IAgBI,cAAcK,IACZP;;AAAAA,kBAAMQ,kBAANR,8BAAsBO,KAEtBf,EAAOgB,cACL,IAAIC,YAAYF,GAAMG,MAAM,EAC1BC,QAAQ,EACNC,WAAW,EACTC,IAAIX,KAAKY,aAAa,IAAA,GACtBjB,MAAMK,KAAKY,aAAa,MAE1BC,EAAAA,GAAAA,MAAMb,KAAKc,WACXC,OAAOV,GAAMI,OAIzB,EAAA,CAAA,CAAA;AAAA,IAAA;AAAA,IAeI,CAACvB,CAAAA,EAAYgB,IACXF;AAAAA,yBAAAA,IAAkBE,EAAO,IAAA,IAAIc;AAE7B,YAAA,CAAS,EAAAC,IAAQZ,IAAOG,IAAMU,GAAMC,CAAAA,IAClCjB,GAAIkB,MAAM,uDACV,KAAA,CAAA,GAEIC,KAAcF,KAAW,IAC5BG,MAAM,GAAA,EACNC,OAAOC,OAAAA,EACPC,IAAKF,CAAAA,OAAWA,GAAOD,MAAM,GAC7BG,CAAAA,EAAAA,IAAI,CAAE9B,CAAAA,IAAM+B,QAAW,CAACC,EAAKC,QAACC,IAAIlC,EAAO+B,GAAAA,EAAAA,CAAAA;AA6B5C,aA3BApC,EAAOwC,iBACLzB,IACC0B,CAAAA,OACC;;AAAA,cAAA,EACErB,WAAWC,EAAAA,IAAEA,IAAEhB,MAAEA,GAAAA,GAAMkB,MACvBA,IAAIE,OACJA,GAAAA,IACEgB,GAAEtB;AAEN,YAAI,IAAIuB,OAAO,UAAUrB,EAAMhB,IAAAA,EAAAA,IAAQkB,QAAU,GAAKoB,EAAAA,KAAKhB,EAAS,GAAA;AAClE,gBAAMiB,KAAUb,EAAWc,OACzB,CAACC,IAAAA,CAAOC,IAAIX,EAAAA,MAAWW,GAAGD,IAAMV,KAChCX,EAGE;AAAA,qBAAWkB,KAAKzB,EAAAA,OAAOR,UAAKkB,OAALlB,8BAAakC,MACpC,cAAcD,KAAKzB,EAAAA,KAAOR,KAAKsC,aAAapB,GAAMgB,EAAAA,GAClD,WAAWD,KAAKzB,EAAAA,MAAOR,KAAKkB,CAAAA,IAAQgB;AAAAA,QACpD;AAEU,eAAOlC;AAAAA,MAAI,GAEb,EACEuC,QAAQvC,mBAAAA,IAAkBE,EAAAA,EAAKqC,OAI5BvC,CAAAA,GAAAA;AAAAA,IACb;AAAA,IAQI,CAACX,CAAea,EAAAA,IAAAA;;AAEd,cADAF,wBAAAA,IAAkBE,EAAAA,MAAlBF,mBAAwBwC,SACjBxC;AAAAA,IACb;AAAA,EAGE;AA/IEN;AAOA+C,gBARIhD,GAQJgD,sBAA4B,CAAKjD,GAAAA,EAAMkD,sBAAsB,CAAA,GFL/C;AE6IhB,SAAOjD;AAAI;"}