Generate web slides from Markdoc
at main 74 lines 1.9 kB view raw
1import { assign, setup } from "xstate"; 2import { Context, Events } from "./types.ts"; 3 4export const machineBase = setup({ 5 types: { 6 context: {} as Context, 7 events: {} as Events, 8 }, 9 actions: { 10 registerSlides: assign(({ context, event }) => { 11 if (event.type === "presentation.start") { 12 const currentIndex = event.slides.findIndex((s) => 13 s.id === event.currentSlide 14 ); 15 16 return { 17 ...context, 18 presentationId: event.presentationId, 19 slides: event.slides, 20 currentIndex: Math.max(currentIndex, 0), 21 channel: new BroadcastChannel(event.presentationId), 22 }; 23 } else { 24 return context; 25 } 26 }), 27 scrollToSlide({ context }) { 28 if (context.currentIndex > 0) { 29 const slide = context.slides[context.currentIndex]; 30 31 document.querySelector(`#${slide.id}`)?.scrollIntoView({ 32 behavior: "instant", 33 }); 34 } 35 }, 36 updateUrl({ context }) { 37 const url = new URL(document.URL); 38 const hash = `#${context.slides[context.currentIndex].id}`; 39 40 url.hash = hash; 41 42 location.replace(url); 43 }, 44 updateCurrentSlide: assign({ 45 currentIndex: ({ context, event }) => { 46 if (event.type === "navigate.scroll") { 47 const index = context.slides.findIndex((s) => s.id === event.slideId); 48 49 return Math.max(index, 0); 50 } 51 52 return context.currentIndex; 53 }, 54 }), 55 nextSlide: assign({ 56 currentIndex: ({ context }) => { 57 if (context.currentIndex + 1 > context.slides.length - 1) { 58 return context.currentIndex; 59 } 60 61 return context.currentIndex + 1; 62 }, 63 }), 64 previousSlide: assign({ 65 currentIndex: ({ context }) => { 66 if (context.currentIndex - 1 < 0) { 67 return context.currentIndex; 68 } 69 70 return context.currentIndex - 1; 71 }, 72 }), 73 }, 74});