|
1 | | -import { Accessor, Component, createComputed, createSignal } from 'solid-js' |
| 1 | +import { createEffect, on, onCleanup, onMount } from 'solid-js' |
| 2 | +import type { Component, JSX } from 'solid-js' |
| 3 | +import type { createPlayground, EmbedOptions, Playground } from 'livecodes' |
2 | 4 |
|
3 | | -export function createHello(): [Accessor<string>, (to: string) => void] { |
4 | | - const [hello, setHello] = createSignal('Hello World!') |
5 | | - |
6 | | - return [hello, (to: string) => setHello(`Hello ${to}!`)] |
| 5 | +export interface Props extends EmbedOptions { |
| 6 | + class?: string |
| 7 | + style?: JSX.CSSProperties |
| 8 | + height?: string |
| 9 | + sdkReady?: (sdk: Playground) => void |
7 | 10 | } |
8 | 11 |
|
9 | | -export const Hello: Component<{ to?: string }> = props => { |
10 | | - const [hello, setHello] = createHello() |
| 12 | +export const createComponent = |
| 13 | + (createPlaygroundFn: typeof createPlayground): Component<Props> => |
| 14 | + props => { |
| 15 | + let containerRef!: HTMLDivElement |
| 16 | + let playground: Playground | undefined |
| 17 | + let configCache = JSON.stringify(props.config || '') |
| 18 | + let otherOptionsCache = '' |
11 | 19 |
|
12 | | - // Console calls will be removed in production if `dropConsole` is enabled |
| 20 | + const getOtherOptions = (): Omit<EmbedOptions, 'config'> => { |
| 21 | + const opts: Record<string, unknown> = {} |
| 22 | + if (props.appUrl !== undefined) opts.appUrl = props.appUrl |
| 23 | + if (props.import !== undefined) opts.import = props.import |
| 24 | + if (props.headless !== undefined) opts.headless = props.headless |
| 25 | + if (props.lite !== undefined) opts.lite = props.lite |
| 26 | + if (props.loading !== undefined) opts.loading = props.loading |
| 27 | + if (props.params !== undefined) opts.params = props.params |
| 28 | + if (props.template !== undefined) opts.template = props.template |
| 29 | + if (props.view !== undefined) opts.view = props.view |
| 30 | + return opts as Omit<EmbedOptions, 'config'> |
| 31 | + } |
13 | 32 |
|
14 | | - // eslint-disable-next-line no-console |
15 | | - console.log('Hello World!') |
| 33 | + const initOrUpdate = () => { |
| 34 | + if (!containerRef) return |
16 | 35 |
|
17 | | - createComputed(() => { |
18 | | - if (typeof props.to === 'string') setHello(props.to) |
19 | | - }) |
| 36 | + const config = props.config |
| 37 | + const sdkReady = props.sdkReady |
| 38 | + const otherOptions = getOtherOptions() |
| 39 | + const currentOtherOptionsStr = JSON.stringify(otherOptions) |
20 | 40 |
|
21 | | - return ( |
22 | | - <> |
23 | | - <div>{hello()}</div> |
24 | | - </> |
25 | | - ) |
26 | | -} |
| 41 | + if (!playground || otherOptionsCache !== currentOtherOptionsStr) { |
| 42 | + otherOptionsCache = currentOtherOptionsStr |
| 43 | + configCache = JSON.stringify(config || '') |
| 44 | + playground?.destroy() |
| 45 | + createPlaygroundFn(containerRef, { config, ...otherOptions }).then(sdk => { |
| 46 | + playground = sdk |
| 47 | + if (typeof sdkReady === 'function') { |
| 48 | + sdkReady(sdk) |
| 49 | + } |
| 50 | + }) |
| 51 | + } else { |
| 52 | + const currentConfigStr = JSON.stringify(config) |
| 53 | + if (configCache === currentConfigStr) return |
| 54 | + configCache = currentConfigStr |
| 55 | + |
| 56 | + if (typeof config === 'string') { |
| 57 | + fetch(config) |
| 58 | + .then(res => res.json()) |
| 59 | + .then(json => { |
| 60 | + playground?.setConfig(json) |
| 61 | + }) |
| 62 | + } else if (config) { |
| 63 | + playground.setConfig(config) |
| 64 | + } |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + onMount(() => { |
| 69 | + initOrUpdate() |
| 70 | + }) |
| 71 | + |
| 72 | + createEffect( |
| 73 | + on( |
| 74 | + () => [ |
| 75 | + props.config, |
| 76 | + props.appUrl, |
| 77 | + props.import, |
| 78 | + props.headless, |
| 79 | + props.lite, |
| 80 | + props.loading, |
| 81 | + props.params, |
| 82 | + props.template, |
| 83 | + props.view, |
| 84 | + props.sdkReady, |
| 85 | + ], |
| 86 | + () => { |
| 87 | + initOrUpdate() |
| 88 | + }, |
| 89 | + { defer: true }, |
| 90 | + ), |
| 91 | + ) |
| 92 | + |
| 93 | + onCleanup(() => { |
| 94 | + playground?.destroy() |
| 95 | + }) |
| 96 | + |
| 97 | + return ( |
| 98 | + <div ref={containerRef} class={props.class} style={props.style} data-height={props.height} /> |
| 99 | + ) |
| 100 | + } |
0 commit comments