useStoriesLoader.tsx 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import type React from 'react';
  2. import {useMemo} from 'react';
  3. import {useQuery, type UseQueryResult} from 'sentry/utils/queryClient';
  4. const context = require.context('sentry', true, /\.stories.tsx$/, 'lazy');
  5. export interface StoryDescriptor {
  6. exports: Record<string, React.ComponentType | any>;
  7. filename: string;
  8. }
  9. export function useStoryBookFiles() {
  10. return useMemo(() => context.keys().map(file => file.replace(/^\.\//, 'app/')), []);
  11. }
  12. async function importStory(filename: string): Promise<StoryDescriptor> {
  13. const story = await context(filename.replace(/^app\//, './'));
  14. return {
  15. exports: story,
  16. filename,
  17. };
  18. }
  19. type StoriesResult<T> = T extends string ? StoryDescriptor : StoryDescriptor[];
  20. interface UseStoriesLoaderOptions<T extends string | string[]> {
  21. filename: T;
  22. }
  23. export default function useStoriesLoader<T extends string | string[]>(
  24. options: UseStoriesLoaderOptions<T>
  25. ): UseQueryResult<StoriesResult<T>, Error> {
  26. return useQuery({
  27. queryKey: [options.filename],
  28. queryFn: (): Promise<StoriesResult<T>> => {
  29. if (Array.isArray(options.filename)) {
  30. return Promise.all(options.filename.map(importStory)) as Promise<
  31. StoriesResult<T>
  32. >;
  33. }
  34. return importStory(options.filename) as Promise<StoriesResult<T>>;
  35. },
  36. enabled: !!options.filename,
  37. });
  38. }