helper.tsx 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. import { createContext, createMemo, Show, useContext, type ParentProps, type Accessor } from "solid-js"
  2. export function createSimpleContext<T, Props extends Record<string, any>>(
  3. input: {
  4. name: string
  5. init: ((input: Props) => T) | (() => T)
  6. } & (T extends { ready: unknown } ? { gate: boolean } : { gate?: boolean }),
  7. ) {
  8. const ctx = createContext<T>()
  9. return {
  10. provider: (props: ParentProps<Props>) => {
  11. const init = input.init(props)
  12. const gate = input.gate ?? true
  13. if (!gate) {
  14. return <ctx.Provider value={init}>{props.children}</ctx.Provider>
  15. }
  16. // Access init.ready inside the memo to make it reactive for getter properties
  17. const isReady = createMemo(() => {
  18. // @ts-expect-error
  19. const ready = init.ready as Accessor<boolean> | boolean | undefined
  20. return ready === undefined || (typeof ready === "function" ? ready() : ready)
  21. })
  22. return (
  23. <Show when={isReady()}>
  24. <ctx.Provider value={init}>{props.children}</ctx.Provider>
  25. </Show>
  26. )
  27. },
  28. use() {
  29. const value = useContext(ctx)
  30. if (!value) throw new Error(`${input.name} context must be used within a context provider`)
  31. return value
  32. },
  33. }
  34. }