@prose-reader/react-reader 1.117.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +50 -0
  2. package/package.json +36 -0
  3. package/src/common/useFullscreen.ts +44 -0
  4. package/src/components/ui/avatar.tsx +74 -0
  5. package/src/components/ui/checkbox.tsx +25 -0
  6. package/src/components/ui/close-button.tsx +17 -0
  7. package/src/components/ui/color-mode.tsx +75 -0
  8. package/src/components/ui/dialog.tsx +62 -0
  9. package/src/components/ui/drawer.tsx +52 -0
  10. package/src/components/ui/field.tsx +33 -0
  11. package/src/components/ui/input-group.tsx +53 -0
  12. package/src/components/ui/popover.tsx +59 -0
  13. package/src/components/ui/progress.tsx +34 -0
  14. package/src/components/ui/provider.tsx +12 -0
  15. package/src/components/ui/radio.tsx +24 -0
  16. package/src/components/ui/slider.tsx +82 -0
  17. package/src/components/ui/toggle-tip.tsx +70 -0
  18. package/src/components/ui/tooltip.tsx +46 -0
  19. package/src/context/ReactReaderProvider.tsx +14 -0
  20. package/src/context/context.ts +6 -0
  21. package/src/context/useReader.ts +9 -0
  22. package/src/index.ts +2 -0
  23. package/src/navigation/QuickMenu/BottomBar.tsx +65 -0
  24. package/src/navigation/QuickMenu/PaginationInfoSection.tsx +62 -0
  25. package/src/navigation/QuickMenu/QuickBar.tsx +40 -0
  26. package/src/navigation/QuickMenu/QuickMenu.tsx +22 -0
  27. package/src/navigation/QuickMenu/Scrubber.tsx +138 -0
  28. package/src/navigation/QuickMenu/TimeIndicator.tsx +29 -0
  29. package/src/navigation/QuickMenu/TopBar.tsx +72 -0
  30. package/src/navigation/useNavigationContext.ts +46 -0
  31. package/src/pagination/usePagination.ts +29 -0
  32. package/src/settings/useSettings.ts +9 -0
  33. package/src/vite-env.d.ts +1 -0
  34. package/tsconfig.app.json +26 -0
  35. package/tsconfig.json +7 -0
  36. package/tsconfig.node.json +22 -0
  37. package/vite.config.ts +32 -0
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+
10
+ ## Expanding the ESLint configuration
11
+
12
+ If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13
+
14
+ - Configure the top-level `parserOptions` property like this:
15
+
16
+ ```js
17
+ export default tseslint.config({
18
+ languageOptions: {
19
+ // other options...
20
+ parserOptions: {
21
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
22
+ tsconfigRootDir: import.meta.dirname,
23
+ },
24
+ },
25
+ })
26
+ ```
27
+
28
+ - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
29
+ - Optionally add `...tseslint.configs.stylisticTypeChecked`
30
+ - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
31
+
32
+ ```js
33
+ // eslint.config.js
34
+ import react from 'eslint-plugin-react'
35
+
36
+ export default tseslint.config({
37
+ // Set the react version
38
+ settings: { react: { version: '18.3' } },
39
+ plugins: {
40
+ // Add the react plugin
41
+ react,
42
+ },
43
+ rules: {
44
+ // other rules...
45
+ // Enable its recommended rules
46
+ ...react.configs.recommended.rules,
47
+ ...react.configs['jsx-runtime'].rules,
48
+ },
49
+ })
50
+ ```
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@prose-reader/react-reader",
3
+ "private": false,
4
+ "version": "1.117.0",
5
+ "type": "module",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "start": "vite build --watch --mode development",
12
+ "build": "tsc -b && vite build"
13
+ },
14
+ "devDependencies": {
15
+ "@eslint/js": "^9.17.0",
16
+ "@types/react": "^19.0.0",
17
+ "@types/react-dom": "^19.0.0",
18
+ "@vitejs/plugin-react": "^4.3.4",
19
+ "globals": "^15.14.0",
20
+ "react": "^19.0.0",
21
+ "react-dom": "^19.0.0",
22
+ "rollup-plugin-node-externals": "^8.0.0",
23
+ "typescript": "~5.6.2",
24
+ "vite": "^6.0.5"
25
+ },
26
+ "peerDependencies": {
27
+ "@chakra-ui/react": "3.x",
28
+ "@emotion/react": "11.x",
29
+ "@prose-reader/core": "^1.169.0",
30
+ "rc-slider": "11.1.x",
31
+ "react": "19.x",
32
+ "react-dom": "19.x",
33
+ "react-icons": "^5.4.0",
34
+ "reactjrx": "1.x"
35
+ }
36
+ }
@@ -0,0 +1,44 @@
1
+ import { useEffect } from "react"
2
+
3
+ import { useCallback } from "react"
4
+
5
+ import { useState } from "react"
6
+
7
+ export const useFullscreen = () => {
8
+ const [isFullscreen, setIsFullscreen] = useState(false)
9
+
10
+ const onToggleFullscreenClick = useCallback(() => {
11
+ if (document.fullscreenElement) {
12
+ return document
13
+ .exitFullscreen()
14
+ .catch(console.error)
15
+ .then(() => {
16
+ setIsFullscreen(false)
17
+ })
18
+ }
19
+
20
+ return document.documentElement
21
+ .requestFullscreen({ navigationUI: "hide" })
22
+ .catch(console.error)
23
+ .then(() => {
24
+ setIsFullscreen(true)
25
+ })
26
+ }, [])
27
+
28
+ useEffect(() => {
29
+ function fullscreenchangeHandler() {
30
+ setIsFullscreen(!!document.fullscreenElement)
31
+ }
32
+
33
+ document.addEventListener("fullscreenchange", fullscreenchangeHandler)
34
+
35
+ return () => {
36
+ document.removeEventListener("fullscreenchange", fullscreenchangeHandler)
37
+ }
38
+ }, [])
39
+
40
+ return {
41
+ isFullscreen,
42
+ onToggleFullscreenClick,
43
+ }
44
+ }
@@ -0,0 +1,74 @@
1
+ "use client"
2
+
3
+ import type { GroupProps, SlotRecipeProps } from "@chakra-ui/react"
4
+ import { Avatar as ChakraAvatar, Group } from "@chakra-ui/react"
5
+ import * as React from "react"
6
+
7
+ type ImageProps = React.ImgHTMLAttributes<HTMLImageElement>
8
+
9
+ export interface AvatarProps extends ChakraAvatar.RootProps {
10
+ name?: string
11
+ src?: string
12
+ srcSet?: string
13
+ loading?: ImageProps["loading"]
14
+ icon?: React.ReactElement
15
+ fallback?: React.ReactNode
16
+ }
17
+
18
+ export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
19
+ function Avatar(props, ref) {
20
+ const { name, src, srcSet, loading, icon, fallback, children, ...rest } =
21
+ props
22
+ return (
23
+ <ChakraAvatar.Root ref={ref} {...rest}>
24
+ <AvatarFallback name={name} icon={icon}>
25
+ {fallback}
26
+ </AvatarFallback>
27
+ <ChakraAvatar.Image src={src} srcSet={srcSet} loading={loading} />
28
+ {children}
29
+ </ChakraAvatar.Root>
30
+ )
31
+ },
32
+ )
33
+
34
+ interface AvatarFallbackProps extends ChakraAvatar.FallbackProps {
35
+ name?: string
36
+ icon?: React.ReactElement
37
+ }
38
+
39
+ const AvatarFallback = React.forwardRef<HTMLDivElement, AvatarFallbackProps>(
40
+ function AvatarFallback(props, ref) {
41
+ const { name, icon, children, ...rest } = props
42
+ return (
43
+ <ChakraAvatar.Fallback ref={ref} {...rest}>
44
+ {children}
45
+ {name != null && children == null && <>{getInitials(name)}</>}
46
+ {name == null && children == null && (
47
+ <ChakraAvatar.Icon asChild={!!icon}>{icon}</ChakraAvatar.Icon>
48
+ )}
49
+ </ChakraAvatar.Fallback>
50
+ )
51
+ },
52
+ )
53
+
54
+ function getInitials(name: string) {
55
+ const names = name.trim().split(" ")
56
+ const firstName = names[0] != null ? names[0] : ""
57
+ const lastName = names.length > 1 ? names[names.length - 1] : ""
58
+ return firstName && lastName
59
+ ? `${firstName.charAt(0)}${lastName.charAt(0)}`
60
+ : firstName.charAt(0)
61
+ }
62
+
63
+ interface AvatarGroupProps extends GroupProps, SlotRecipeProps<"avatar"> {}
64
+
65
+ export const AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(
66
+ function AvatarGroup(props, ref) {
67
+ const { size, variant, borderless, ...rest } = props
68
+ return (
69
+ <ChakraAvatar.PropsProvider value={{ size, variant, borderless }}>
70
+ <Group gap="0" spaceX="-3" ref={ref} {...rest} />
71
+ </ChakraAvatar.PropsProvider>
72
+ )
73
+ },
74
+ )
@@ -0,0 +1,25 @@
1
+ import { Checkbox as ChakraCheckbox } from "@chakra-ui/react"
2
+ import * as React from "react"
3
+
4
+ export interface CheckboxProps extends ChakraCheckbox.RootProps {
5
+ icon?: React.ReactNode
6
+ inputProps?: React.InputHTMLAttributes<HTMLInputElement>
7
+ rootRef?: React.Ref<HTMLLabelElement>
8
+ }
9
+
10
+ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
11
+ function Checkbox(props, ref) {
12
+ const { icon, children, inputProps, rootRef, ...rest } = props
13
+ return (
14
+ <ChakraCheckbox.Root ref={rootRef} {...rest}>
15
+ <ChakraCheckbox.HiddenInput ref={ref} {...inputProps} />
16
+ <ChakraCheckbox.Control>
17
+ {icon || <ChakraCheckbox.Indicator />}
18
+ </ChakraCheckbox.Control>
19
+ {children != null && (
20
+ <ChakraCheckbox.Label>{children}</ChakraCheckbox.Label>
21
+ )}
22
+ </ChakraCheckbox.Root>
23
+ )
24
+ },
25
+ )
@@ -0,0 +1,17 @@
1
+ import type { ButtonProps } from "@chakra-ui/react"
2
+ import { IconButton as ChakraIconButton } from "@chakra-ui/react"
3
+ import * as React from "react"
4
+ import { LuX } from "react-icons/lu"
5
+
6
+ export type CloseButtonProps = ButtonProps
7
+
8
+ export const CloseButton = React.forwardRef<
9
+ HTMLButtonElement,
10
+ CloseButtonProps
11
+ >(function CloseButton(props, ref) {
12
+ return (
13
+ <ChakraIconButton variant="ghost" aria-label="Close" ref={ref} {...props}>
14
+ {props.children ?? <LuX />}
15
+ </ChakraIconButton>
16
+ )
17
+ })
@@ -0,0 +1,75 @@
1
+ "use client"
2
+
3
+ import type { IconButtonProps } from "@chakra-ui/react"
4
+ import { ClientOnly, IconButton, Skeleton } from "@chakra-ui/react"
5
+ import { ThemeProvider, useTheme } from "next-themes"
6
+ import type { ThemeProviderProps } from "next-themes"
7
+ import * as React from "react"
8
+ import { LuMoon, LuSun } from "react-icons/lu"
9
+
10
+ export interface ColorModeProviderProps extends ThemeProviderProps {}
11
+
12
+ export function ColorModeProvider(props: ColorModeProviderProps) {
13
+ return (
14
+ <ThemeProvider attribute="class" disableTransitionOnChange {...props} />
15
+ )
16
+ }
17
+
18
+ export type ColorMode = "light" | "dark"
19
+
20
+ export interface UseColorModeReturn {
21
+ colorMode: ColorMode
22
+ setColorMode: (colorMode: ColorMode) => void
23
+ toggleColorMode: () => void
24
+ }
25
+
26
+ export function useColorMode(): UseColorModeReturn {
27
+ const { resolvedTheme, setTheme } = useTheme()
28
+ const toggleColorMode = () => {
29
+ setTheme(resolvedTheme === "light" ? "dark" : "light")
30
+ }
31
+ return {
32
+ colorMode: resolvedTheme as ColorMode,
33
+ setColorMode: setTheme,
34
+ toggleColorMode,
35
+ }
36
+ }
37
+
38
+ export function useColorModeValue<T>(light: T, dark: T) {
39
+ const { colorMode } = useColorMode()
40
+ return colorMode === "dark" ? dark : light
41
+ }
42
+
43
+ export function ColorModeIcon() {
44
+ const { colorMode } = useColorMode()
45
+ return colorMode === "dark" ? <LuMoon /> : <LuSun />
46
+ }
47
+
48
+ interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}
49
+
50
+ export const ColorModeButton = React.forwardRef<
51
+ HTMLButtonElement,
52
+ ColorModeButtonProps
53
+ >(function ColorModeButton(props, ref) {
54
+ const { toggleColorMode } = useColorMode()
55
+ return (
56
+ <ClientOnly fallback={<Skeleton boxSize="8" />}>
57
+ <IconButton
58
+ onClick={toggleColorMode}
59
+ variant="ghost"
60
+ aria-label="Toggle color mode"
61
+ size="sm"
62
+ ref={ref}
63
+ {...props}
64
+ css={{
65
+ _icon: {
66
+ width: "5",
67
+ height: "5",
68
+ },
69
+ }}
70
+ >
71
+ <ColorModeIcon />
72
+ </IconButton>
73
+ </ClientOnly>
74
+ )
75
+ })
@@ -0,0 +1,62 @@
1
+ import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react"
2
+ import { CloseButton } from "./close-button"
3
+ import * as React from "react"
4
+
5
+ interface DialogContentProps extends ChakraDialog.ContentProps {
6
+ portalled?: boolean
7
+ portalRef?: React.RefObject<HTMLElement>
8
+ backdrop?: boolean
9
+ }
10
+
11
+ export const DialogContent = React.forwardRef<
12
+ HTMLDivElement,
13
+ DialogContentProps
14
+ >(function DialogContent(props, ref) {
15
+ const {
16
+ children,
17
+ portalled = true,
18
+ portalRef,
19
+ backdrop = true,
20
+ ...rest
21
+ } = props
22
+
23
+ return (
24
+ <Portal disabled={!portalled} container={portalRef}>
25
+ {backdrop && <ChakraDialog.Backdrop />}
26
+ <ChakraDialog.Positioner>
27
+ <ChakraDialog.Content ref={ref} {...rest} asChild={false}>
28
+ {children}
29
+ </ChakraDialog.Content>
30
+ </ChakraDialog.Positioner>
31
+ </Portal>
32
+ )
33
+ })
34
+
35
+ export const DialogCloseTrigger = React.forwardRef<
36
+ HTMLButtonElement,
37
+ ChakraDialog.CloseTriggerProps
38
+ >(function DialogCloseTrigger(props, ref) {
39
+ return (
40
+ <ChakraDialog.CloseTrigger
41
+ position="absolute"
42
+ top="2"
43
+ insetEnd="2"
44
+ {...props}
45
+ asChild
46
+ >
47
+ <CloseButton size="sm" ref={ref}>
48
+ {props.children}
49
+ </CloseButton>
50
+ </ChakraDialog.CloseTrigger>
51
+ )
52
+ })
53
+
54
+ export const DialogRoot = ChakraDialog.Root
55
+ export const DialogFooter = ChakraDialog.Footer
56
+ export const DialogHeader = ChakraDialog.Header
57
+ export const DialogBody = ChakraDialog.Body
58
+ export const DialogBackdrop = ChakraDialog.Backdrop
59
+ export const DialogTitle = ChakraDialog.Title
60
+ export const DialogDescription = ChakraDialog.Description
61
+ export const DialogTrigger = ChakraDialog.Trigger
62
+ export const DialogActionTrigger = ChakraDialog.ActionTrigger
@@ -0,0 +1,52 @@
1
+ import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react"
2
+ import { CloseButton } from "./close-button"
3
+ import * as React from "react"
4
+
5
+ interface DrawerContentProps extends ChakraDrawer.ContentProps {
6
+ portalled?: boolean
7
+ portalRef?: React.RefObject<HTMLElement>
8
+ offset?: ChakraDrawer.ContentProps["padding"]
9
+ }
10
+
11
+ export const DrawerContent = React.forwardRef<
12
+ HTMLDivElement,
13
+ DrawerContentProps
14
+ >(function DrawerContent(props, ref) {
15
+ const { children, portalled = true, portalRef, offset, ...rest } = props
16
+ return (
17
+ <Portal disabled={!portalled} container={portalRef}>
18
+ <ChakraDrawer.Positioner padding={offset}>
19
+ <ChakraDrawer.Content ref={ref} {...rest} asChild={false}>
20
+ {children}
21
+ </ChakraDrawer.Content>
22
+ </ChakraDrawer.Positioner>
23
+ </Portal>
24
+ )
25
+ })
26
+
27
+ export const DrawerCloseTrigger = React.forwardRef<
28
+ HTMLButtonElement,
29
+ ChakraDrawer.CloseTriggerProps
30
+ >(function DrawerCloseTrigger(props, ref) {
31
+ return (
32
+ <ChakraDrawer.CloseTrigger
33
+ position="absolute"
34
+ top="2"
35
+ insetEnd="2"
36
+ {...props}
37
+ asChild
38
+ >
39
+ <CloseButton size="sm" ref={ref} />
40
+ </ChakraDrawer.CloseTrigger>
41
+ )
42
+ })
43
+
44
+ export const DrawerTrigger = ChakraDrawer.Trigger
45
+ export const DrawerRoot = ChakraDrawer.Root
46
+ export const DrawerFooter = ChakraDrawer.Footer
47
+ export const DrawerHeader = ChakraDrawer.Header
48
+ export const DrawerBody = ChakraDrawer.Body
49
+ export const DrawerBackdrop = ChakraDrawer.Backdrop
50
+ export const DrawerDescription = ChakraDrawer.Description
51
+ export const DrawerTitle = ChakraDrawer.Title
52
+ export const DrawerActionTrigger = ChakraDrawer.ActionTrigger
@@ -0,0 +1,33 @@
1
+ import { Field as ChakraField } from "@chakra-ui/react"
2
+ import * as React from "react"
3
+
4
+ export interface FieldProps extends Omit<ChakraField.RootProps, "label"> {
5
+ label?: React.ReactNode
6
+ helperText?: React.ReactNode
7
+ errorText?: React.ReactNode
8
+ optionalText?: React.ReactNode
9
+ }
10
+
11
+ export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
12
+ function Field(props, ref) {
13
+ const { label, children, helperText, errorText, optionalText, ...rest } =
14
+ props
15
+ return (
16
+ <ChakraField.Root ref={ref} {...rest}>
17
+ {label && (
18
+ <ChakraField.Label>
19
+ {label}
20
+ <ChakraField.RequiredIndicator fallback={optionalText} />
21
+ </ChakraField.Label>
22
+ )}
23
+ {children}
24
+ {helperText && (
25
+ <ChakraField.HelperText>{helperText}</ChakraField.HelperText>
26
+ )}
27
+ {errorText && (
28
+ <ChakraField.ErrorText>{errorText}</ChakraField.ErrorText>
29
+ )}
30
+ </ChakraField.Root>
31
+ )
32
+ },
33
+ )
@@ -0,0 +1,53 @@
1
+ import type { BoxProps, InputElementProps } from "@chakra-ui/react"
2
+ import { Group, InputElement } from "@chakra-ui/react"
3
+ import * as React from "react"
4
+
5
+ export interface InputGroupProps extends BoxProps {
6
+ startElementProps?: InputElementProps
7
+ endElementProps?: InputElementProps
8
+ startElement?: React.ReactNode
9
+ endElement?: React.ReactNode
10
+ children: React.ReactElement<InputElementProps>
11
+ startOffset?: InputElementProps["paddingStart"]
12
+ endOffset?: InputElementProps["paddingEnd"]
13
+ }
14
+
15
+ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
16
+ function InputGroup(props, ref) {
17
+ const {
18
+ startElement,
19
+ startElementProps,
20
+ endElement,
21
+ endElementProps,
22
+ children,
23
+ startOffset = "6px",
24
+ endOffset = "6px",
25
+ ...rest
26
+ } = props
27
+
28
+ const child =
29
+ React.Children.only<React.ReactElement<InputElementProps>>(children)
30
+
31
+ return (
32
+ <Group ref={ref} {...rest}>
33
+ {startElement && (
34
+ <InputElement pointerEvents="none" {...startElementProps}>
35
+ {startElement}
36
+ </InputElement>
37
+ )}
38
+ {React.cloneElement(child, {
39
+ ...(startElement && {
40
+ ps: `calc(var(--input-height) - ${startOffset})`,
41
+ }),
42
+ ...(endElement && { pe: `calc(var(--input-height) - ${endOffset})` }),
43
+ ...children.props,
44
+ })}
45
+ {endElement && (
46
+ <InputElement placement="end" {...endElementProps}>
47
+ {endElement}
48
+ </InputElement>
49
+ )}
50
+ </Group>
51
+ )
52
+ },
53
+ )
@@ -0,0 +1,59 @@
1
+ import { Popover as ChakraPopover, Portal } from "@chakra-ui/react"
2
+ import { CloseButton } from "./close-button"
3
+ import * as React from "react"
4
+
5
+ interface PopoverContentProps extends ChakraPopover.ContentProps {
6
+ portalled?: boolean
7
+ portalRef?: React.RefObject<HTMLElement>
8
+ }
9
+
10
+ export const PopoverContent = React.forwardRef<
11
+ HTMLDivElement,
12
+ PopoverContentProps
13
+ >(function PopoverContent(props, ref) {
14
+ const { portalled = true, portalRef, ...rest } = props
15
+ return (
16
+ <Portal disabled={!portalled} container={portalRef}>
17
+ <ChakraPopover.Positioner>
18
+ <ChakraPopover.Content ref={ref} {...rest} />
19
+ </ChakraPopover.Positioner>
20
+ </Portal>
21
+ )
22
+ })
23
+
24
+ export const PopoverArrow = React.forwardRef<
25
+ HTMLDivElement,
26
+ ChakraPopover.ArrowProps
27
+ >(function PopoverArrow(props, ref) {
28
+ return (
29
+ <ChakraPopover.Arrow {...props} ref={ref}>
30
+ <ChakraPopover.ArrowTip />
31
+ </ChakraPopover.Arrow>
32
+ )
33
+ })
34
+
35
+ export const PopoverCloseTrigger = React.forwardRef<
36
+ HTMLButtonElement,
37
+ ChakraPopover.CloseTriggerProps
38
+ >(function PopoverCloseTrigger(props, ref) {
39
+ return (
40
+ <ChakraPopover.CloseTrigger
41
+ position="absolute"
42
+ top="1"
43
+ insetEnd="1"
44
+ {...props}
45
+ asChild
46
+ ref={ref}
47
+ >
48
+ <CloseButton size="sm" />
49
+ </ChakraPopover.CloseTrigger>
50
+ )
51
+ })
52
+
53
+ export const PopoverTitle = ChakraPopover.Title
54
+ export const PopoverDescription = ChakraPopover.Description
55
+ export const PopoverFooter = ChakraPopover.Footer
56
+ export const PopoverHeader = ChakraPopover.Header
57
+ export const PopoverRoot = ChakraPopover.Root
58
+ export const PopoverBody = ChakraPopover.Body
59
+ export const PopoverTrigger = ChakraPopover.Trigger
@@ -0,0 +1,34 @@
1
+ import { Progress as ChakraProgress } from "@chakra-ui/react"
2
+ import { InfoTip } from "./toggle-tip"
3
+ import * as React from "react"
4
+
5
+ export const ProgressBar = React.forwardRef<
6
+ HTMLDivElement,
7
+ ChakraProgress.TrackProps
8
+ >(function ProgressBar(props, ref) {
9
+ return (
10
+ <ChakraProgress.Track {...props} ref={ref}>
11
+ <ChakraProgress.Range />
12
+ </ChakraProgress.Track>
13
+ )
14
+ })
15
+
16
+ export interface ProgressLabelProps extends ChakraProgress.LabelProps {
17
+ info?: React.ReactNode
18
+ }
19
+
20
+ export const ProgressLabel = React.forwardRef<
21
+ HTMLDivElement,
22
+ ProgressLabelProps
23
+ >(function ProgressLabel(props, ref) {
24
+ const { children, info, ...rest } = props
25
+ return (
26
+ <ChakraProgress.Label {...rest} ref={ref}>
27
+ {children}
28
+ {info && <InfoTip>{info}</InfoTip>}
29
+ </ChakraProgress.Label>
30
+ )
31
+ })
32
+
33
+ export const ProgressRoot = ChakraProgress.Root
34
+ export const ProgressValueText = ChakraProgress.ValueText
@@ -0,0 +1,12 @@
1
+ "use client"
2
+
3
+ import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
4
+ import { ColorModeProvider, type ColorModeProviderProps } from "./color-mode"
5
+
6
+ export function Provider(props: ColorModeProviderProps) {
7
+ return (
8
+ <ChakraProvider value={defaultSystem}>
9
+ <ColorModeProvider {...props} />
10
+ </ChakraProvider>
11
+ )
12
+ }
@@ -0,0 +1,24 @@
1
+ import { RadioGroup as ChakraRadioGroup } from "@chakra-ui/react"
2
+ import * as React from "react"
3
+
4
+ export interface RadioProps extends ChakraRadioGroup.ItemProps {
5
+ rootRef?: React.Ref<HTMLDivElement>
6
+ inputProps?: React.InputHTMLAttributes<HTMLInputElement>
7
+ }
8
+
9
+ export const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
10
+ function Radio(props, ref) {
11
+ const { children, inputProps, rootRef, ...rest } = props
12
+ return (
13
+ <ChakraRadioGroup.Item ref={rootRef} {...rest}>
14
+ <ChakraRadioGroup.ItemHiddenInput ref={ref} {...inputProps} />
15
+ <ChakraRadioGroup.ItemIndicator />
16
+ {children && (
17
+ <ChakraRadioGroup.ItemText>{children}</ChakraRadioGroup.ItemText>
18
+ )}
19
+ </ChakraRadioGroup.Item>
20
+ )
21
+ },
22
+ )
23
+
24
+ export const RadioGroup = ChakraRadioGroup.Root