UNPKG

@helpwave/hightide

Version:

helpwave's component and theming library

1 lines 14.4 kB
{"version":3,"sources":["../../src/components/LoadingAndErrorComponent.tsx","../../src/hooks/useLanguage.tsx","../../src/hooks/useLocalStorage.tsx","../../src/hooks/useTranslation.ts","../../src/components/icons/Helpwave.tsx","../../src/components/LoadingAnimation.tsx","../../src/components/ErrorComponent.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react'\nimport { useState } from 'react'\nimport type { LoadingAnimationProps } from './LoadingAnimation'\nimport type { ErrorComponentProps } from './ErrorComponent'\nimport { LoadingAnimation } from './LoadingAnimation'\nimport { ErrorComponent } from './ErrorComponent'\n\nexport type LoadingAndErrorComponentProps = PropsWithChildren<{\n isLoading?: boolean,\n hasError?: boolean,\n loadingProps?: LoadingAnimationProps,\n errorProps?: ErrorComponentProps,\n /**\n * in milliseconds\n */\n minimumLoadingDuration?: number,\n}>\n\n/**\n * A Component that shows the Error and Loading animation, when appropriate and the children otherwise\n */\nexport const LoadingAndErrorComponent = ({\n children,\n isLoading = false,\n hasError = false,\n errorProps,\n loadingProps,\n minimumLoadingDuration\n}: LoadingAndErrorComponentProps) => {\n const [isInMinimumLoading, setIsInMinimumLoading] = useState(false)\n const [hasUsedMinimumLoading, setHasUsedMinimumLoading] = useState(false)\n if (minimumLoadingDuration && !isInMinimumLoading && !hasUsedMinimumLoading) {\n setIsInMinimumLoading(true)\n setTimeout(() => {\n setIsInMinimumLoading(false)\n setHasUsedMinimumLoading(true)\n }, minimumLoadingDuration)\n }\n\n if (isLoading || (minimumLoadingDuration && isInMinimumLoading)) {\n return <LoadingAnimation {...loadingProps}/>\n }\n if (hasError) {\n return <ErrorComponent {...errorProps}/>\n }\n return children\n}\n","import type { Dispatch, PropsWithChildren, SetStateAction } from 'react'\nimport { createContext, useContext, useEffect, useState } from 'react'\nimport { useLocalStorage } from './useLocalStorage'\n\nexport const languages = ['en', 'de'] as const\nexport type Languages = typeof languages[number]\nexport const languagesLocalNames: Record<Languages, string> = {\n en: 'English',\n de: 'Deutsch',\n}\n\nexport const DEFAULT_LANGUAGE = 'en'\n\nexport type LanguageContextValue = {\n language: Languages,\n setLanguage: Dispatch<SetStateAction<Languages>>,\n}\n\nexport const LanguageContext = createContext<LanguageContextValue>({ language: DEFAULT_LANGUAGE, setLanguage: (v) => v })\n\nexport const useLanguage = () => useContext(LanguageContext)\n\nexport const useLocale = (overWriteLanguage?: Languages) => {\n const { language } = useLanguage()\n const mapping: Record<Languages, string> = {\n en: 'en-US',\n de: 'de-DE'\n }\n return mapping[overWriteLanguage ?? language]\n}\n\ntype ProvideLanguageProps = {\n initialLanguage?: Languages,\n}\n\nexport const ProvideLanguage = ({ initialLanguage, children }: PropsWithChildren<ProvideLanguageProps>) => {\n const [language, setLanguage] = useState<Languages>(initialLanguage ?? DEFAULT_LANGUAGE)\n const [storedLanguage, setStoredLanguage] = useLocalStorage<Languages>('language', initialLanguage ?? DEFAULT_LANGUAGE)\n\n useEffect(() => {\n if(language !== initialLanguage && initialLanguage){\n console.warn('LanguageProvider initial state changed: Prefer using useLanguages\\'s setLanguage instead')\n setLanguage(initialLanguage)\n }\n }, [initialLanguage]) // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n // TODO set locale of html tag here as well\n setStoredLanguage(language)\n }, [language, setStoredLanguage])\n\n useEffect(() => {\n if (storedLanguage !== null) {\n setLanguage(storedLanguage)\n return\n }\n\n const languagesToTestAgainst = Object.values(languages)\n\n const matchingBrowserLanguages = window.navigator.languages\n .map(language => languagesToTestAgainst.find((test) => language === test || language.split('-')[0] === test))\n .filter(entry => entry !== undefined)\n\n if (matchingBrowserLanguages.length === 0) return\n\n const firstMatch = matchingBrowserLanguages[0] as Languages\n setLanguage(firstMatch)\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return (\n <LanguageContext.Provider value={{\n language,\n setLanguage\n }}>\n {children}\n </LanguageContext.Provider>\n )\n}\n","import type { Dispatch, SetStateAction } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport { LocalStorageService } from '../util/storage'\n\ntype SetValue<T> = Dispatch<SetStateAction<T>>\nexport const useLocalStorage = <T, >(key: string, initValue: T): [T, SetValue<T>] => {\n const get = useCallback((): T => {\n if (typeof window === 'undefined') {\n return initValue\n }\n const storageService = new LocalStorageService()\n const value = storageService.get<T>(key)\n return value || initValue\n }, [initValue, key])\n\n const [storedValue, setStoredValue] = useState<T>(get)\n\n const setValue: SetValue<T> = useCallback(value => {\n const newValue = value instanceof Function ? value(storedValue) : value\n const storageService = new LocalStorageService()\n storageService.set(key, value)\n\n setStoredValue(newValue)\n }, [storedValue, setStoredValue, key])\n\n useEffect(() => {\n setStoredValue(get())\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return [storedValue, setValue]\n}","import type { Languages } from './useLanguage'\nimport { useLanguage } from './useLanguage'\n\nexport type Translation<T> = Record<Languages, T>\n\ntype OverwriteTranslationType<Translation extends Record<string, unknown>> = {\n language?: Languages,\n translation?: Partial<Record<Languages, Partial<Translation>>>,\n}\n\n/**\n * Adds the `language` prop to the component props.\n *\n * @param Translation the type of the translation object\n *\n * @param Props the type of the component props, defaults to `Record<string, never>`,\n * if you don't expect any other props other than `language` and get an\n * error when using your component (because it uses `forwardRef` etc.)\n * you can try out `Record<string, unknown>`, this might resolve your\n * problem as `SomeType & never` is still `never` but `SomeType & unknown`\n * is `SomeType` which means that adding back props (like `ref` etc.)\n * works properly\n */\nexport type PropsForTranslation<\n Translation extends Record<string, unknown>,\n Props = Record<string, never>\n> = Props & {\n overwriteTranslation?: OverwriteTranslationType<Translation>,\n};\n\nexport const useTranslation = <Translation extends Record<string, unknown>>(\n defaults: Record<Languages, Translation>,\n translationOverwrite: OverwriteTranslationType<Translation> = {}\n) : Translation => {\n const { language: languageProp, translation: overwrite } = translationOverwrite\n const { language: inferredLanguage } = useLanguage()\n const usedLanguage = languageProp ?? inferredLanguage\n let defaultValues: Translation = defaults[usedLanguage]\n if (overwrite && overwrite[usedLanguage]) {\n defaultValues = { ...defaultValues, ...overwrite[usedLanguage] }\n }\n return defaultValues\n}\n","import type { SVGProps } from 'react'\nimport { clsx } from 'clsx'\n\nexport type HelpwaveProps = SVGProps<SVGSVGElement> & {\n color?: string,\n animate?: 'none' | 'loading' | 'pulse' | 'bounce',\n size?: number,\n}\n\n/**\n * The helpwave loading spinner based on the svg logo.\n */\nexport const Helpwave = ({\n color = 'currentColor',\n animate = 'none',\n size = 64,\n ...props\n}: HelpwaveProps) => {\n const isLoadingAnimation = animate === 'loading'\n let svgAnimationKey = ''\n\n if (animate === 'pulse') {\n svgAnimationKey = 'animate-pulse'\n } else if (animate === 'bounce') {\n svgAnimationKey = 'animate-bounce'\n }\n\n if (size < 0) {\n console.error('size cannot be less than 0')\n size = 64\n }\n\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 888 888\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeWidth={48}\n {...props}\n >\n <g className={clsx(svgAnimationKey)}>\n <path className={clsx({ 'animate-wave-big-left-up': isLoadingAnimation })} d=\"M144 543.235C144 423.259 232.164 326 340.92 326\" stroke={color} strokeDasharray=\"1000\" />\n <path className={clsx({ 'animate-wave-big-right-down': isLoadingAnimation })} d=\"M537.84 544.104C429.084 544.104 340.92 446.844 340.92 326.869\" stroke={color} strokeDasharray=\"1000\" />\n <path className={clsx({ 'animate-wave-small-left-up': isLoadingAnimation })} d=\"M462.223 518.035C462.223 432.133 525.348 362.495 603.217 362.495\" stroke={color} strokeDasharray=\"1000\" />\n <path className={clsx({ 'animate-wave-small-right-down': isLoadingAnimation })} d=\"M745.001 519.773C666.696 519.773 603.218 450.136 603.218 364.233\" stroke={color} strokeDasharray=\"1000\" />\n </g>\n </svg>\n )\n}\n","import type { Languages } from '../hooks/useLanguage'\nimport type { PropsForTranslation } from '../hooks/useTranslation'\nimport { useTranslation } from '../hooks/useTranslation'\nimport { Helpwave } from './icons/Helpwave'\nimport clsx from 'clsx'\n\ntype LoadingAnimationTranslation = {\n loading: string,\n}\n\nconst defaultLoadingAnimationTranslation: Record<Languages, LoadingAnimationTranslation> = {\n en: {\n loading: 'Loading data'\n },\n de: {\n loading: 'Lade Daten'\n }\n}\n\nexport type LoadingAnimationProps = {\n loadingText?: string,\n classname?: string,\n}\n\n/**\n * A Component to show when loading data\n */\nexport const LoadingAnimation = ({\n overwriteTranslation,\n loadingText,\n classname\n}: PropsForTranslation<LoadingAnimationTranslation, LoadingAnimationProps>) => {\n const translation = useTranslation(defaultLoadingAnimationTranslation, overwriteTranslation)\n return (\n <div className={clsx('col items-center justify-center w-full h-24', classname)}>\n <Helpwave animate=\"loading\" />\n {loadingText ?? `${translation.loading}...`}\n </div>\n )\n}\n","import { AlertOctagon } from 'lucide-react'\nimport type { Languages } from '../hooks/useLanguage'\nimport type { PropsForTranslation } from '../hooks/useTranslation'\nimport { useTranslation } from '../hooks/useTranslation'\nimport clsx from 'clsx'\n\ntype ErrorComponentTranslation = {\n errorOccurred: string,\n}\n\nconst defaultErrorComponentTranslation: Record<Languages, ErrorComponentTranslation> = {\n en: {\n errorOccurred: 'An error occurred'\n },\n de: {\n errorOccurred: 'Ein Fehler ist aufgetreten'\n }\n}\n\nexport type ErrorComponentProps = {\n errorText?: string,\n classname?: string,\n}\n\n/**\n * The Component to show when an error occurred\n */\nexport const ErrorComponent = ({\n overwriteTranslation,\n errorText,\n classname\n}: PropsForTranslation<ErrorComponentTranslation, ErrorComponentProps>) => {\n const translation = useTranslation(defaultErrorComponentTranslation, overwriteTranslation)\n return (\n <div className={clsx('col items-center justify-center gap-y-4 w-full h-24', classname)}>\n <AlertOctagon size={64} className=\"text-warning\"/>\n {errorText ?? `${translation.errorOccurred} :(`}\n </div>\n )\n}\n"],"mappings":"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","names":["useState","useEffect","useState","jsx","clsx","jsx","jsxs","clsx","jsx","jsxs","jsx","useState"]}