import 'atomico/ssr/load';
import {html} from "atomico";
import type {VNode, VNodeAny} from "atomico/types/vnode";
import {type ActionArgs, emit, type EventObject,type MachineContext, type ParameterizedObject} from "xstate";
import {EventMessage} from "@/iterator";
export type StreamOptions ={
href:string
connect: (options?:{event?:string, swap?:string}) => Record
};
export type RenderStream = StreamOptions & {
service:(id?: string) => RenderStream;
event:(type:string)=>StreamOptions
};
export function workflowStream(workflow: string ):RenderStream {
return {
href: workflow,
event: (type: string) => streamElements(workflow, type),
service: (id?: string) => workflowStream(`${workflow}/${id}` ),
connect: streamElements(workflow).connect
}
}
export function streamElements(workflow: string, type?: string | undefined):StreamOptions {
const href = `${workflow}${type ? `/events/${type}` : ''}`;
return {
href,
connect(options) {
const {event, swap}= options ||{ }
return {
'hx-swap': swap || 'beforeend' ,
'sse-swap':event || type,
'sse-connect': `${workflow}/events`,
'ext':'sse'
}
}
}
}
//render action
export type Html={(
strings: TemplateStringsArray,
...values: any[]
): R;}
export type NodeExpression=(args:ActionArgs & {stream:RenderStream , html:Html},params:TParams) => VNodeAny;
export function render( nodeOrExpr:NodeExpression | VNodeAny, ) {
return renderTo('render', nodeOrExpr)
}
export function renderTo(type:string, nodeOrExpr:NodeExpression | VNodeAny, ) {
const expr = typeof nodeOrExpr === 'function' ? nodeOrExpr : () => nodeOrExpr;
return emit(({context, self, ...args}: ActionArgs, params: TParams) => {
const selfId = self.id;
const node = expr({
stream: context?.stream || workflowStream(selfId),
self,
html, ...args,
context: context
}, params);
return renderEvent(type,node);
})
function renderEvent(type:string, node:VNode) {
if(!node?.render) {
console.log('No render method',type, node);
debugger;
return {
type: type,
event: type,
data: node.toString(),
};
}
const rendered = node.render() as unknown as {
type: string,
name: string,
nodeName: string,
attributes: any,
innerHTML: string,
outerHTML: string,
};
return {
type: type,
event: type,
data: rendered?.toString(),
} satisfies EventMessage & { type: typeof type, event: string }
}
}