scaffold.tsx 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { ErrorBoundary, type ValidComponent } from "solid-js"
  2. import { Dynamic } from "solid-js/web"
  3. function fn(value: unknown): value is (...args: never[]) => unknown {
  4. return typeof value === "function"
  5. }
  6. function pick(mod: Record<string, unknown>, name?: string) {
  7. if (name && fn(mod[name])) return mod[name]
  8. if (fn(mod.default)) return mod.default
  9. const preferred = Object.keys(mod)
  10. .filter((k) => k[0] && k[0] === k[0].toUpperCase())
  11. .find((k) => fn(mod[k]))
  12. if (preferred) return mod[preferred]
  13. const first = Object.keys(mod).find((k) => fn(mod[k]))
  14. if (first) return mod[first]
  15. return () => {
  16. return (
  17. <div data-component="storybook-missing">
  18. <div>Missing component export.</div>
  19. <div style="opacity:0.7;font-size:12px">Exports: {Object.keys(mod).join(", ") || "(none)"}</div>
  20. </div>
  21. )
  22. }
  23. }
  24. export function create(input: {
  25. title: string
  26. mod: Record<string, unknown>
  27. name?: string
  28. args?: Record<string, unknown>
  29. }) {
  30. const component = pick(input.mod, input.name) as unknown as ValidComponent
  31. return {
  32. meta: {
  33. title: input.title,
  34. component,
  35. },
  36. Basic: {
  37. args: input.args ?? {},
  38. render: (args: Record<string, unknown>) => {
  39. return (
  40. <ErrorBoundary
  41. fallback={(err) => {
  42. return (
  43. <pre data-component="storybook-error" style="white-space:pre-wrap">
  44. {String(err)}
  45. </pre>
  46. )
  47. }}
  48. >
  49. <Dynamic component={component} {...args} />
  50. </ErrorBoundary>
  51. )
  52. },
  53. },
  54. }
  55. }