Packages

Use the fixi.js hypermedia library with Lustre!

Current section

Files

Jump to
flixi src flixi.erl
Raw

src/flixi.erl

-module(flixi).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/flixi.gleam").
-export([action/1, method/1, target/1, swap/1, swap_inner_html/0, swap_outer_html/0, swap_before_begin/0, swap_after_begin/0, swap_before_end/0, swap_after_end/0, swap_none/0, trigger/1, ignore/0, script/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/flixi.gleam", 8).
?DOC(" The URL to which an HTTP request will be issued.\n").
-spec action(binary()) -> lustre@vdom@vattr:attribute(any()).
action(Url) ->
lustre@attribute:attribute(<<"fx-action"/utf8>>, Url).
-file("src/flixi.gleam", 14).
?DOC(" The HTTP Method that will be used for the request, defaults to GET.\n").
-spec method(gleam@http:method()) -> lustre@vdom@vattr:attribute(any()).
method(Method) ->
lustre@attribute:attribute(
<<"fx-method"/utf8>>,
gleam@http:method_to_string(Method)
).
-file("src/flixi.gleam", 23).
?DOC(
" A CSS selector specifying where to place the response HTML in the DOM, e.g.\n"
" `#my-id`.\n"
"\n"
" Defaults to the current element.\n"
).
-spec target(binary()) -> lustre@vdom@vattr:attribute(any()).
target(Selector) ->
lustre@attribute:attribute(<<"fx-target"/utf8>>, Selector).
-file("src/flixi.gleam", 39).
?DOC(
" How the content should be swapped into the DOM, can be one of `innerHTML`,\n"
" `outerHTML`, `beforebegin`, `afterbegin`, `beforeend`, `afterend`, `none`, or\n"
" any valid property on the element (e.g. `className` or `value`).\n"
"\n"
" Defaults to outerHTML.\n"
).
-spec swap(binary()) -> lustre@vdom@vattr:attribute(any()).
swap(Property) ->
lustre@attribute:attribute(<<"fx-swap"/utf8>>, Property).
-file("src/flixi.gleam", 45).
?DOC(" Swap `innerHTML`.\n").
-spec swap_inner_html() -> lustre@vdom@vattr:attribute(any()).
swap_inner_html() ->
swap(<<"innerHTML"/utf8>>).
-file("src/flixi.gleam", 51).
?DOC(" Swap `outerHTML`.\n").
-spec swap_outer_html() -> lustre@vdom@vattr:attribute(any()).
swap_outer_html() ->
swap(<<"outerHTML"/utf8>>).
-file("src/flixi.gleam", 57).
?DOC(" Swap `beforebegin`.\n").
-spec swap_before_begin() -> lustre@vdom@vattr:attribute(any()).
swap_before_begin() ->
swap(<<"beforebegin"/utf8>>).
-file("src/flixi.gleam", 63).
?DOC(" Swap `afterbegin`.\n").
-spec swap_after_begin() -> lustre@vdom@vattr:attribute(any()).
swap_after_begin() ->
swap(<<"afterbegin"/utf8>>).
-file("src/flixi.gleam", 69).
?DOC(" Swap `beforeend`.\n").
-spec swap_before_end() -> lustre@vdom@vattr:attribute(any()).
swap_before_end() ->
swap(<<"beforeend"/utf8>>).
-file("src/flixi.gleam", 75).
?DOC(" Swap `afterend`.\n").
-spec swap_after_end() -> lustre@vdom@vattr:attribute(any()).
swap_after_end() ->
swap(<<"afterend"/utf8>>).
-file("src/flixi.gleam", 81).
?DOC(" Swap `none`.\n").
-spec swap_none() -> lustre@vdom@vattr:attribute(any()).
swap_none() ->
swap(<<"none"/utf8>>).
-file("src/flixi.gleam", 88).
?DOC(
" The event that will trigger a request, defaults to submit for form\n"
" elements, change for input-like elements & click for all other elements.\n"
).
-spec trigger(binary()) -> lustre@vdom@vattr:attribute(any()).
trigger(Event) ->
lustre@attribute:attribute(<<"fx-trigger"/utf8>>, Event).
-file("src/flixi.gleam", 95).
?DOC(
" Any element with this attribute on it or on an ancestor will not be\n"
" processed for `fx-*` attributes.\n"
).
-spec ignore() -> lustre@vdom@vattr:attribute(any()).
ignore() ->
lustre@attribute:attribute(<<"fx-ignore"/utf8>>, <<""/utf8>>).
-file("src/flixi.gleam", 29).
?DOC(" Create a script element the runs the fixi JavaScript.\n").
-spec script(list(lustre@vdom@vattr:attribute(PXU))) -> lustre@vdom@vnode:element(PXU).
script(Attributes) ->
lustre@element@html:script(
Attributes,
<<"(()=>{if(document.__fixi_mo)return;document.__fixi_mo=new MutationObserver(e=>e.forEach(e=>'childList'===e.type&&e.addedNodes.forEach(e=>r(e))));let e=(e,t,i,n)=>e.dispatchEvent(new CustomEvent('fx:'+t,{detail:i,cancelable:!0,bubbles:!1!==n,composed:!0})),t=(e,t,i)=>e.getAttribute(t)||i,i=e=>null!=e.closest('[fx-ignore]'),n=n=>{let r={};n.__fixi||i(n)||!e(n,'init',{options:r})||(n.__fixi=async i=>{let r=n.__fixi.requests||=new Set,o=n.form||n.closest('form'),a=new FormData(o??void 0,i.submitter);!n.name||i.submitter||o&&(n.form!==o||'submit'!==n.type)||a.append(n.name,n.value);let s=new AbortController,c={trigger:i,action:t(n,'fx-action'),method:t(n,'fx-method','GET').toUpperCase(),target:document.querySelector(t(n,'fx-target'))??n,swap:t(n,'fx-swap','outerHTML'),body:a,drop:r.size,headers:{'FX-Request':'true'},abort:s.abort.bind(s),signal:s.signal,preventTrigger:!0,transition:document.startViewTransition?.bind(document),fetch:fetch.bind(window)},f=e(n,'config',{cfg:c,requests:r});if(c.preventTrigger&&i.preventDefault(),!f||c.drop)return;if(/GET|DELETE/.test(c.method)){let e=new URLSearchParams(c.body);e.size&&(c.action+=(/\\?/.test(c.action)?'&':'?')+e),c.body=null}r.add(c);try{if(c.confirm){if(!await c.confirm())return}if(!e(n,'before',{cfg:c,requests:r}))return;if(c.response=await c.fetch(c.action,c),c.text=await c.response.text(),!e(n,'after',{cfg:c}))return}catch(t){return void e(n,'error',{cfg:c,error:t})}finally{r.delete(c),e(n,'finally',{cfg:c})}let d=()=>{if(c.swap instanceof Function)return c.swap(c);if(/(before|after)(begin|end)/.test(c.swap))c.target.insertAdjacentHTML(c.swap,c.text);else if(c.swap in c.target)c.target[c.swap]=c.text;else if('none'!==c.swap)throw c.swap};c.transition?await c.transition(d).finished:await d(),e(n,'swapped',{cfg:c}),document.contains(n)||e(document,'swapped',{cfg:c})},n.__fixi.evt=t(n,'fx-trigger',n.matches('form')?'submit':n.matches('input:not([type=button]),select,textarea')?'change':'click'),n.addEventListener(n.__fixi.evt,n.__fixi,r),e(n,'inited',{},!1))},r=e=>{if(e.matches){if(i(e))return;e.matches('[fx-action]')&&n(e)}e.querySelectorAll&&e.querySelectorAll('[fx-action]').forEach(n)};document.addEventListener('fx:process',e=>r(e.target)),document.addEventListener('DOMContentLoaded',()=>{document.__fixi_mo.observe(document.documentElement,{childList:!0,subtree:!0}),r(document.body)})})();"/utf8>>
).