-module(lightspeed@component@stateful). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/lightspeed/component/stateful.gleam"). -export([mount_context/3, route/2, route_event/2, start/4, update/2, handle_event/2, model/1, rendered/1, html/1, context/1]). -export_type([lifecycle/0, mount_context/0, event_route/1, lifecycle_component/3, instance/3]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(" Stateful component lifecycle and event routing compatibility helpers.\n"). -type lifecycle() :: disconnected | connected. -type mount_context() :: {mount_context, binary(), binary(), lifecycle()}. -type event_route(HYU) :: {event_route, binary(), fun((lightspeed@event:inbound_event()) -> {ok, HYU} | {error, lightspeed@event:decode_error()})}. -type lifecycle_component(HYV, HYW, HYX) :: {lifecycle_component, fun((mount_context(), HYW) -> {HYV, list(lightspeed@component:command(HYX))}), fun((HYV, HYW) -> {HYV, list(lightspeed@component:command(HYX))}), fun((HYV, HYX) -> {HYV, list(lightspeed@component:command(HYX))}), fun((HYV) -> lightspeed@component:rendered()), list(event_route(HYX))}. -opaque instance(HYY, HYZ, HZA) :: {instance, lifecycle_component(HYY, HYZ, HZA), HYY, HYZ, mount_context(), binary(), lightspeed@component:rendered()}. -file("src/lightspeed/component/stateful.gleam", 50). ?DOC(" Build a mount context.\n"). -spec mount_context(binary(), binary(), lifecycle()) -> mount_context(). mount_context(Id, Route, Lifecycle) -> {mount_context, Id, Route, Lifecycle}. -file("src/lightspeed/component/stateful.gleam", 59). ?DOC(" Build one event route.\n"). -spec route( binary(), fun((lightspeed@event:inbound_event()) -> {ok, HZB} | {error, lightspeed@event:decode_error()}) ) -> event_route(HZB). route(Name, Decode) -> {event_route, Name, Decode}. -file("src/lightspeed/component/stateful.gleam", 195). -spec route_names(list(event_route(any()))) -> binary(). route_names(Routes) -> case Routes of [] -> <<"no_routes_registered"/utf8>>; [{event_route, Name, _}] -> Name; [{event_route, Name@1, _} | Rest] -> <<<>/binary, (route_names(Rest))/binary>> end. -file("src/lightspeed/component/stateful.gleam", 175). -spec route_event_with_expected( lightspeed@event:inbound_event(), list(event_route(IBU)), binary() ) -> {ok, IBU} | {error, lightspeed@event:decode_error()}. route_event_with_expected(Inbound, Routes, Expected) -> case Routes of [] -> {error, {unexpected_event, Expected, lightspeed@event:name(Inbound)}}; [{event_route, Name, Decode} | Rest] -> case lightspeed@event:name(Inbound) =:= Name of true -> Decode(Inbound); false -> route_event_with_expected(Inbound, Rest, Expected) end end. -file("src/lightspeed/component/stateful.gleam", 67). ?DOC(" Resolve an inbound event against named routes.\n"). -spec route_event(lightspeed@event:inbound_event(), list(event_route(HZF))) -> {ok, HZF} | {error, lightspeed@event:decode_error()}. route_event(Inbound, Routes) -> route_event_with_expected(Inbound, Routes, route_names(Routes)). -file("src/lightspeed/component/stateful.gleam", 77). ?DOC( " Start a stateful component instance from mount assigns.\n" "\n" " Returns initial commands and one deterministic replace patch.\n" ). -spec start(lifecycle_component(HZK, HZL, HZM), mount_context(), HZL, binary()) -> {instance(HZK, HZL, HZM), list(lightspeed@component:command(HZM)), list(lightspeed@diff:patch())}. start(Definition, Context, Assigns, Target) -> {Model, Commands} = (erlang:element(2, Definition))(Context, Assigns), Rendered = (erlang:element(5, Definition))(Model), Patch = {replace, Target, lightspeed@component:to_html(Rendered)}, {{instance, Definition, Model, Assigns, Context, Target, Rendered}, Commands, [Patch]}. -file("src/lightspeed/component/stateful.gleam", 203). -spec patch_plan( binary(), lightspeed@component:rendered(), lightspeed@component:rendered() ) -> list(lightspeed@diff:patch()). patch_plan(Target, Previous, Next) -> case Previous =:= Next of true -> []; false -> case lightspeed@component:fingerprint(Previous) =:= lightspeed@component:fingerprint( Next ) of true -> [{update_segments, Target, lightspeed@component:fingerprint(Next), [lightspeed@diff:slot( <<"html"/utf8>>, lightspeed@component:to_html(Next) )]}]; false -> [{replace, Target, lightspeed@component:to_html(Next)}] end end. -file("src/lightspeed/component/stateful.gleam", 106). ?DOC(" Apply parent assigns updates.\n"). -spec update(instance(HZW, HZX, HZY), HZX) -> {instance(HZW, HZX, HZY), list(lightspeed@component:command(HZY)), list(lightspeed@diff:patch())}. update(Instance, Assigns) -> {Model, Commands} = (erlang:element(3, erlang:element(2, Instance)))( erlang:element(3, Instance), Assigns ), Rendered = (erlang:element(5, erlang:element(2, Instance)))(Model), Patches = patch_plan( erlang:element(6, Instance), erlang:element(7, Instance), Rendered ), {{instance, erlang:element(2, Instance), Model, Assigns, erlang:element(5, Instance), erlang:element(6, Instance), Rendered}, Commands, Patches}. -file("src/lightspeed/component/stateful.gleam", 126). ?DOC(" Route and handle one inbound event.\n"). -spec handle_event(instance(IAI, IAJ, IAK), lightspeed@event:inbound_event()) -> {instance(IAI, IAJ, IAK), {ok, IAK} | {error, lightspeed@event:decode_error()}, list(lightspeed@component:command(IAK)), list(lightspeed@diff:patch())}. handle_event(Instance, Inbound) -> case route_event(Inbound, erlang:element(6, erlang:element(2, Instance))) of {error, Error} -> {Instance, {error, Error}, [], []}; {ok, Message} -> {Model, Commands} = (erlang:element(4, erlang:element(2, Instance)))( erlang:element(3, Instance), Message ), Rendered = (erlang:element(5, erlang:element(2, Instance)))(Model), Patches = patch_plan( erlang:element(6, Instance), erlang:element(7, Instance), Rendered ), {{instance, erlang:element(2, Instance), Model, erlang:element(4, Instance), erlang:element(5, Instance), erlang:element(6, Instance), Rendered}, {ok, Message}, Commands, Patches} end. -file("src/lightspeed/component/stateful.gleam", 155). ?DOC(" Current model.\n"). -spec model(instance(IAW, any(), any())) -> IAW. model(Instance) -> erlang:element(3, Instance). -file("src/lightspeed/component/stateful.gleam", 160). ?DOC(" Last rendered value.\n"). -spec rendered(instance(any(), any(), any())) -> lightspeed@component:rendered(). rendered(Instance) -> erlang:element(7, Instance). -file("src/lightspeed/component/stateful.gleam", 165). ?DOC(" Latest HTML snapshot.\n"). -spec html(instance(any(), any(), any())) -> binary(). html(Instance) -> _pipe = erlang:element(7, Instance), lightspeed@component:to_html(_pipe). -file("src/lightspeed/component/stateful.gleam", 171). ?DOC(" Current mount context.\n"). -spec context(instance(any(), any(), any())) -> mount_context(). context(Instance) -> erlang:element(5, Instance).