@stack-spot/citric-react 0.42.0-beta.0 → 0.43.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 (209) hide show
  1. package/CHANGELOG.md +13 -13
  2. package/dist/citric.css +2926 -2920
  3. package/dist/components/Accordion.d.ts +1 -1
  4. package/dist/components/Accordion.js +1 -1
  5. package/dist/components/Alert.d.ts +1 -1
  6. package/dist/components/Alert.js +1 -1
  7. package/dist/components/AsyncContent.d.ts +1 -1
  8. package/dist/components/AsyncContent.js +1 -1
  9. package/dist/components/Autocomplete.d.ts +370 -0
  10. package/dist/components/Autocomplete.d.ts.map +1 -0
  11. package/dist/components/{Autocomplete/Autocomplete.js → Autocomplete.js} +163 -98
  12. package/dist/components/Autocomplete.js.map +1 -0
  13. package/dist/components/Avatar.d.ts +1 -1
  14. package/dist/components/Avatar.js +1 -1
  15. package/dist/components/AvatarGroup.d.ts +1 -1
  16. package/dist/components/AvatarGroup.js +1 -1
  17. package/dist/components/Badge.d.ts +1 -1
  18. package/dist/components/Badge.js +1 -1
  19. package/dist/components/Blockquote.d.ts +1 -1
  20. package/dist/components/Blockquote.js +1 -1
  21. package/dist/components/Breadcrumb.d.ts +1 -1
  22. package/dist/components/Breadcrumb.js +1 -1
  23. package/dist/components/Button.d.ts +1 -1
  24. package/dist/components/Button.js +1 -1
  25. package/dist/components/ButtonLink.d.ts +1 -1
  26. package/dist/components/ButtonLink.js +1 -1
  27. package/dist/components/Card.d.ts +1 -1
  28. package/dist/components/Card.js +1 -1
  29. package/dist/components/Checkbox.d.ts +1 -1
  30. package/dist/components/Checkbox.d.ts.map +1 -1
  31. package/dist/components/Checkbox.js +2 -2
  32. package/dist/components/Checkbox.js.map +1 -1
  33. package/dist/components/CheckboxGroup.d.ts +1 -1
  34. package/dist/components/CheckboxGroup.js +1 -1
  35. package/dist/components/Circle.d.ts +1 -1
  36. package/dist/components/Circle.js +1 -1
  37. package/dist/components/Divider.d.ts +1 -1
  38. package/dist/components/Divider.js +1 -1
  39. package/dist/components/ErrorBoundary.d.ts +1 -1
  40. package/dist/components/ErrorBoundary.js +1 -1
  41. package/dist/components/ErrorMessage.d.ts +1 -1
  42. package/dist/components/ErrorMessage.js +1 -1
  43. package/dist/components/FallbackBoundary.d.ts +1 -1
  44. package/dist/components/FallbackBoundary.js +1 -1
  45. package/dist/components/Favorite.d.ts +1 -1
  46. package/dist/components/Favorite.js +1 -1
  47. package/dist/components/FieldGroup.d.ts +1 -1
  48. package/dist/components/FieldGroup.js +1 -1
  49. package/dist/components/Form.d.ts +2 -2
  50. package/dist/components/Form.js +1 -1
  51. package/dist/components/FormGroup.d.ts +1 -1
  52. package/dist/components/FormGroup.js +1 -1
  53. package/dist/components/Icon.d.ts +1 -1
  54. package/dist/components/Icon.js +1 -1
  55. package/dist/components/IconBox.d.ts +3 -3
  56. package/dist/components/IconBox.js +1 -1
  57. package/dist/components/ImageBox.d.ts +3 -3
  58. package/dist/components/ImageBox.js +1 -1
  59. package/dist/components/ImageWithFallback.d.ts +1 -1
  60. package/dist/components/ImageWithFallback.js +1 -1
  61. package/dist/components/Input.d.ts +1 -1
  62. package/dist/components/Input.js +1 -1
  63. package/dist/components/Link.d.ts +1 -1
  64. package/dist/components/Link.js +1 -1
  65. package/dist/components/LoadingPanel.d.ts +1 -1
  66. package/dist/components/LoadingPanel.js +1 -1
  67. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  68. package/dist/components/MenuOverlay/Menu.js +1 -1
  69. package/dist/components/MenuOverlay/index.d.ts +1 -1
  70. package/dist/components/MenuOverlay/index.js +1 -1
  71. package/dist/components/Overlay/index.d.ts +1 -1
  72. package/dist/components/Overlay/index.js +1 -1
  73. package/dist/components/Pagination.d.ts +1 -1
  74. package/dist/components/Pagination.js +1 -1
  75. package/dist/components/ProgressBar.d.ts +1 -1
  76. package/dist/components/ProgressBar.js +1 -1
  77. package/dist/components/ProgressCircular.d.ts +1 -1
  78. package/dist/components/ProgressCircular.js +1 -1
  79. package/dist/components/RadioGroup.d.ts +1 -1
  80. package/dist/components/RadioGroup.js +1 -1
  81. package/dist/components/Rating.d.ts +1 -1
  82. package/dist/components/Rating.js +1 -1
  83. package/dist/components/Select/MultiSelect.d.ts +1 -1
  84. package/dist/components/Select/MultiSelect.js +1 -1
  85. package/dist/components/Select/RichSelect.d.ts +1 -1
  86. package/dist/components/Select/RichSelect.js +1 -1
  87. package/dist/components/Select/SimpleSelect.d.ts +1 -1
  88. package/dist/components/Select/SimpleSelect.js +1 -1
  89. package/dist/components/Select/index.d.ts +1 -1
  90. package/dist/components/Select/index.js +1 -1
  91. package/dist/components/SelectBox.d.ts +9 -1
  92. package/dist/components/SelectBox.d.ts.map +1 -1
  93. package/dist/components/SelectBox.js +6 -5
  94. package/dist/components/SelectBox.js.map +1 -1
  95. package/dist/components/Skeleton.d.ts +1 -1
  96. package/dist/components/Skeleton.js +1 -1
  97. package/dist/components/Slider.d.ts +1 -1
  98. package/dist/components/Slider.js +1 -1
  99. package/dist/components/SmartTable.d.ts +1 -1
  100. package/dist/components/SmartTable.js +1 -1
  101. package/dist/components/Stepper.d.ts +1 -1
  102. package/dist/components/Stepper.js +1 -1
  103. package/dist/components/Table.d.ts +3 -3
  104. package/dist/components/Table.js +1 -1
  105. package/dist/components/Tabs/index.d.ts +1 -1
  106. package/dist/components/Tabs/index.js +1 -1
  107. package/dist/components/Textarea.d.ts +1 -1
  108. package/dist/components/Textarea.js +1 -1
  109. package/dist/components/Tooltip.d.ts +1 -1
  110. package/dist/components/Tooltip.js +1 -1
  111. package/dist/context/CitricProvider.d.ts +1 -1
  112. package/dist/context/CitricProvider.js +1 -1
  113. package/dist/index.d.ts +2 -1
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +2 -1
  116. package/dist/index.js.map +1 -1
  117. package/dist/overlay.js +1 -1
  118. package/dist/theme.css +415 -415
  119. package/dist/utils/css.js +1 -1
  120. package/dist/utils/css.js.map +1 -1
  121. package/package.json +1 -1
  122. package/scripts/build-css.ts +49 -49
  123. package/src/components/Accordion.tsx +130 -130
  124. package/src/components/Alert.tsx +24 -24
  125. package/src/components/AsyncContent.tsx +75 -75
  126. package/src/components/{Autocomplete/Autocomplete.tsx → Autocomplete.tsx} +403 -159
  127. package/src/components/Avatar.tsx +45 -45
  128. package/src/components/AvatarGroup.tsx +49 -49
  129. package/src/components/Badge.tsx +47 -47
  130. package/src/components/Blockquote.tsx +18 -18
  131. package/src/components/Breadcrumb.tsx +33 -33
  132. package/src/components/Button.tsx +105 -105
  133. package/src/components/ButtonLink.tsx +45 -45
  134. package/src/components/Card.tsx +68 -68
  135. package/src/components/Checkbox.tsx +51 -52
  136. package/src/components/CheckboxGroup.tsx +153 -153
  137. package/src/components/Circle.tsx +43 -43
  138. package/src/components/CitricComponent.ts +47 -47
  139. package/src/components/Divider.tsx +24 -24
  140. package/src/components/ErrorBoundary.tsx +75 -75
  141. package/src/components/ErrorMessage.tsx +11 -11
  142. package/src/components/FallbackBoundary.tsx +40 -40
  143. package/src/components/Favorite.tsx +57 -57
  144. package/src/components/FieldGroup.tsx +46 -46
  145. package/src/components/Form.tsx +36 -36
  146. package/src/components/FormGroup.tsx +57 -57
  147. package/src/components/Icon.tsx +35 -35
  148. package/src/components/IconBox.tsx +134 -134
  149. package/src/components/ImageBox.tsx +125 -125
  150. package/src/components/ImageWithFallback.tsx +65 -65
  151. package/src/components/Input.tsx +49 -49
  152. package/src/components/Link.tsx +55 -55
  153. package/src/components/LoadingPanel.tsx +12 -12
  154. package/src/components/MenuOverlay/Menu.tsx +158 -158
  155. package/src/components/MenuOverlay/context.ts +20 -20
  156. package/src/components/MenuOverlay/index.tsx +55 -55
  157. package/src/components/MenuOverlay/keyboard.ts +60 -60
  158. package/src/components/MenuOverlay/types.ts +171 -171
  159. package/src/components/Overlay/context.ts +10 -10
  160. package/src/components/Overlay/index.tsx +182 -182
  161. package/src/components/Overlay/types.ts +75 -75
  162. package/src/components/Pagination.tsx +133 -133
  163. package/src/components/ProgressBar.tsx +45 -45
  164. package/src/components/ProgressCircular.tsx +45 -45
  165. package/src/components/RadioGroup.tsx +147 -147
  166. package/src/components/Rating.tsx +98 -98
  167. package/src/components/Select/MultiSelect.tsx +217 -217
  168. package/src/components/Select/RichSelect.tsx +128 -128
  169. package/src/components/Select/SimpleSelect.tsx +73 -73
  170. package/src/components/Select/hooks.ts +133 -133
  171. package/src/components/Select/index.tsx +35 -35
  172. package/src/components/Select/types.ts +134 -134
  173. package/src/components/SelectBox.tsx +181 -167
  174. package/src/components/Skeleton.tsx +53 -53
  175. package/src/components/Slider.tsx +89 -89
  176. package/src/components/SmartTable.tsx +227 -227
  177. package/src/components/Stepper.tsx +163 -163
  178. package/src/components/Table.tsx +234 -234
  179. package/src/components/Tabs/TabController.ts +54 -54
  180. package/src/components/Tabs/index.tsx +106 -106
  181. package/src/components/Tabs/types.ts +67 -67
  182. package/src/components/Tabs/utils.ts +6 -6
  183. package/src/components/Text.ts +111 -111
  184. package/src/components/Textarea.tsx +27 -27
  185. package/src/components/Tooltip.tsx +83 -83
  186. package/src/components/layout.tsx +101 -101
  187. package/src/context/CitricContext.tsx +4 -4
  188. package/src/context/CitricProvider.tsx +14 -14
  189. package/src/context/hooks.ts +6 -6
  190. package/src/index.ts +59 -59
  191. package/src/overlay.ts +348 -348
  192. package/src/types.ts +235 -235
  193. package/src/utils/ValueController.ts +28 -28
  194. package/src/utils/acessibility.ts +92 -92
  195. package/src/utils/checkbox.ts +121 -121
  196. package/src/utils/css.ts +119 -119
  197. package/src/utils/options.ts +9 -9
  198. package/src/utils/radio.ts +93 -93
  199. package/src/utils/react.ts +6 -6
  200. package/src/utils/time.ts +5 -5
  201. package/tsconfig.json +10 -10
  202. package/dist/components/Autocomplete/Autocomplete.d.ts +0 -211
  203. package/dist/components/Autocomplete/Autocomplete.d.ts.map +0 -1
  204. package/dist/components/Autocomplete/Autocomplete.js.map +0 -1
  205. package/dist/components/Autocomplete/index.d.ts +0 -3
  206. package/dist/components/Autocomplete/index.d.ts.map +0 -1
  207. package/dist/components/Autocomplete/index.js +0 -2
  208. package/dist/components/Autocomplete/index.js.map +0 -1
  209. package/src/components/Autocomplete/index.ts +0 -3
@@ -1,43 +1,43 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { WithColorPalette, WithColorScheme } from '../types'
3
- import { withRef } from '../utils/react'
4
- import { CitricComponent } from './CitricComponent'
5
-
6
- export interface BaseCircleProps extends WithColorPalette, WithColorScheme {
7
- /**
8
- * Whether or not to show borders.
9
- *
10
- * @default false
11
- */
12
- showBorders?: boolean,
13
- /**
14
- * The size of the circle.
15
- *
16
- * - xxs: 8px;
17
- * - xs: 12px;
18
- * - sm: 18px;
19
- * - md: 27px;
20
- * - lg: 40px;
21
- * - xl: 60px;
22
- * - xxl: 90px.
23
- *
24
- * @default 'xs'
25
- */
26
- size?: 'xxs' | 'xs' | 'sm' | 'lg' | 'xl' | 'xxl',
27
- }
28
-
29
- export type CircleProps = React.JSX.IntrinsicElements['div'] & BaseCircleProps
30
-
31
- /**
32
- * Renders a simple circle. If the circle has any children, it gets cropped by the circle borders. The content of the circle is centered.
33
- *
34
- * @example
35
- * ```
36
- * <Circle colorScheme="success" />
37
- * ```
38
- */
39
- export const Circle = withRef(({ showBorders, className, size, children, ...props }: CircleProps) => (
40
- <CitricComponent tag="div" component="circle" className={listToClass([className, showBorders && 'bordered', size])} {...props}>
41
- {children}
42
- </CitricComponent>
43
- ))
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { WithColorPalette, WithColorScheme } from '../types'
3
+ import { withRef } from '../utils/react'
4
+ import { CitricComponent } from './CitricComponent'
5
+
6
+ export interface BaseCircleProps extends WithColorPalette, WithColorScheme {
7
+ /**
8
+ * Whether or not to show borders.
9
+ *
10
+ * @default false
11
+ */
12
+ showBorders?: boolean,
13
+ /**
14
+ * The size of the circle.
15
+ *
16
+ * - xxs: 8px;
17
+ * - xs: 12px;
18
+ * - sm: 18px;
19
+ * - md: 27px;
20
+ * - lg: 40px;
21
+ * - xl: 60px;
22
+ * - xxl: 90px.
23
+ *
24
+ * @default 'xs'
25
+ */
26
+ size?: 'xxs' | 'xs' | 'sm' | 'lg' | 'xl' | 'xxl',
27
+ }
28
+
29
+ export type CircleProps = React.JSX.IntrinsicElements['div'] & BaseCircleProps
30
+
31
+ /**
32
+ * Renders a simple circle. If the circle has any children, it gets cropped by the circle borders. The content of the circle is centered.
33
+ *
34
+ * @example
35
+ * ```
36
+ * <Circle colorScheme="success" />
37
+ * ```
38
+ */
39
+ export const Circle = withRef(({ showBorders, className, size, children, ...props }: CircleProps) => (
40
+ <CitricComponent tag="div" component="circle" className={listToClass([className, showBorders && 'bordered', size])} {...props}>
41
+ {children}
42
+ </CitricComponent>
43
+ ))
@@ -1,47 +1,47 @@
1
- import { createElement, forwardRef } from 'react'
2
- import { WithColorPalette, WithColorScheme } from '../types'
3
-
4
- export type CitricComponentName = 'alert' | 'avatar' | 'badge' | 'blockquote' | 'breadcrumb' | 'button' | 'card' | 'checkbox' |
5
- 'checkbox-row' | 'divider' | 'field-group' | 'form-group' | 'form' | 'icon-box' | 'input' | 'link' | 'pagination' | 'progress-bar' |
6
- 'progress-circular' | 'radio' | 'radio-row' | 'rating' | 'select' | 'select-box' | 'skeleton' | 'slider' | 'switch' | 'switch-row' |
7
- 'table' | 'tabs' | 'accordion' | 'favorite' | 'textarea' | 'avatar-group' | 'labeled-slider' | 'rich-select' | 'tooltip' | 'menu' |
8
- 'circle' | 'multi-select' | 'autocomplete'
9
-
10
- interface BaseCitricProps extends WithColorScheme, WithColorPalette {
11
- component: CitricComponentName,
12
- ref?: any,
13
- }
14
-
15
- interface CitricComponentType {
16
- <T extends keyof JSX.IntrinsicElements>(props: { tag: T } & BaseCitricProps & JSX.IntrinsicElements[T]): React.ReactNode,
17
- <T extends Record<string, any>>(props: { render: React.FC<T> } & BaseCitricProps & T): React.ReactNode,
18
- }
19
-
20
- export function asCitricProps({ colorScheme, colorPalette, component, ...props }: BaseCitricProps & Record<string, any>) {
21
- const citricProps: Record<string, any> = { ...props, 'data-citric': component }
22
- if (colorScheme) citricProps['data-color-scheme'] = colorScheme
23
- if (colorPalette) citricProps['data-color-palette'] = colorPalette
24
- return citricProps
25
- }
26
-
27
- /**
28
- * Renders any tag or component with the appearance of a Citric Component.
29
- *
30
- * @example
31
- * An anchor that looks like a card.
32
- * ```
33
- * <CitricComponent tag="a" component="card" href="https://www.google.com" target="_blank">This is a card link</CitricComponent>
34
- * ```
35
- *
36
- * Suppose we have a component called "MyComponent" that accepts the property "myProp". We can make it look like a citric component:
37
- * ```
38
- * <CitricComponent render={MyComponent} component="card" myProp="my value" />
39
- * ```
40
- */
41
- // eslint-disable-next-line react/display-name
42
- export const CitricComponent: CitricComponentType = forwardRef<any, any>(
43
- (props, ref) => {
44
- const { tag, render, ...citricProps } = asCitricProps(props)
45
- return createElement(tag || render, { ...citricProps, ref })
46
- },
47
- )
1
+ import { createElement, forwardRef } from 'react'
2
+ import { WithColorPalette, WithColorScheme } from '../types'
3
+
4
+ export type CitricComponentName = 'alert' | 'avatar' | 'badge' | 'blockquote' | 'breadcrumb' | 'button' | 'card' | 'checkbox' |
5
+ 'checkbox-row' | 'divider' | 'field-group' | 'form-group' | 'form' | 'icon-box' | 'input' | 'link' | 'pagination' | 'progress-bar' |
6
+ 'progress-circular' | 'radio' | 'radio-row' | 'rating' | 'select' | 'select-box' | 'skeleton' | 'slider' | 'switch' | 'switch-row' |
7
+ 'table' | 'tabs' | 'accordion' | 'favorite' | 'textarea' | 'avatar-group' | 'labeled-slider' | 'rich-select' | 'tooltip' | 'menu' |
8
+ 'circle' | 'multi-select' | 'autocomplete'
9
+
10
+ interface BaseCitricProps extends WithColorScheme, WithColorPalette {
11
+ component: CitricComponentName,
12
+ ref?: any,
13
+ }
14
+
15
+ interface CitricComponentType {
16
+ <T extends keyof JSX.IntrinsicElements>(props: { tag: T } & BaseCitricProps & JSX.IntrinsicElements[T]): React.ReactNode,
17
+ <T extends Record<string, any>>(props: { render: React.FC<T> } & BaseCitricProps & T): React.ReactNode,
18
+ }
19
+
20
+ export function asCitricProps({ colorScheme, colorPalette, component, ...props }: BaseCitricProps & Record<string, any>) {
21
+ const citricProps: Record<string, any> = { ...props, 'data-citric': component }
22
+ if (colorScheme) citricProps['data-color-scheme'] = colorScheme
23
+ if (colorPalette) citricProps['data-color-palette'] = colorPalette
24
+ return citricProps
25
+ }
26
+
27
+ /**
28
+ * Renders any tag or component with the appearance of a Citric Component.
29
+ *
30
+ * @example
31
+ * An anchor that looks like a card.
32
+ * ```
33
+ * <CitricComponent tag="a" component="card" href="https://www.google.com" target="_blank">This is a card link</CitricComponent>
34
+ * ```
35
+ *
36
+ * Suppose we have a component called "MyComponent" that accepts the property "myProp". We can make it look like a citric component:
37
+ * ```
38
+ * <CitricComponent render={MyComponent} component="card" myProp="my value" />
39
+ * ```
40
+ */
41
+ // eslint-disable-next-line react/display-name
42
+ export const CitricComponent: CitricComponentType = forwardRef<any, any>(
43
+ (props, ref) => {
44
+ const { tag, render, ...citricProps } = asCitricProps(props)
45
+ return createElement(tag || render, { ...citricProps, ref })
46
+ },
47
+ )
@@ -1,24 +1,24 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { WithColorScheme } from '../types'
3
- import { withRef } from '../utils/react'
4
- import { CitricComponent } from './CitricComponent'
5
-
6
- export interface BaseDividerProps extends WithColorScheme {
7
- /**
8
- * @default 'horizontal'
9
- */
10
- direction?: 'horizontal' | 'vertical',
11
- /**
12
- * @default 'sm'
13
- */
14
- size?: 'sm' | 'md' | 'lg',
15
- }
16
-
17
- export type DividerProps = React.JSX.IntrinsicElements['hr'] & BaseDividerProps
18
-
19
- /**
20
- * Renders a divider (hr). "size" determines how thick the ruler is and "direction" places it on the vertical or horizontal axis.
21
- */
22
- export const Divider = withRef(({ size, direction, className, ...props }: DividerProps) =>
23
- <CitricComponent tag="hr" component="divider" className={listToClass([className, size, direction])} {...props} />,
24
- )
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { WithColorScheme } from '../types'
3
+ import { withRef } from '../utils/react'
4
+ import { CitricComponent } from './CitricComponent'
5
+
6
+ export interface BaseDividerProps extends WithColorScheme {
7
+ /**
8
+ * @default 'horizontal'
9
+ */
10
+ direction?: 'horizontal' | 'vertical',
11
+ /**
12
+ * @default 'sm'
13
+ */
14
+ size?: 'sm' | 'md' | 'lg',
15
+ }
16
+
17
+ export type DividerProps = React.JSX.IntrinsicElements['hr'] & BaseDividerProps
18
+
19
+ /**
20
+ * Renders a divider (hr). "size" determines how thick the ruler is and "direction" places it on the vertical or horizontal axis.
21
+ */
22
+ export const Divider = withRef(({ size, direction, className, ...props }: DividerProps) =>
23
+ <CitricComponent tag="hr" component="divider" className={listToClass([className, size, direction])} {...props} />,
24
+ )
@@ -1,75 +1,75 @@
1
- import { Component } from 'react'
2
- import { CitricContext } from '../context/CitricContext'
3
- import { ErrorMessage } from './ErrorMessage'
4
-
5
- interface State {
6
- error?: any,
7
- }
8
-
9
- interface Props {
10
- children: React.ReactNode,
11
- /**
12
- * Sets a default error string when a string is provided.
13
- *
14
- * Replaces the error component, if a function is provided.
15
- */
16
- message?: React.ReactNode | ((error: any) => React.ReactNode),
17
- }
18
-
19
- /**
20
- * An Error Boundary that renders an error feedback instead of its content if any of its children throws.
21
- *
22
- * You can customize the appearance of the error through the function `renderError` of a CitricController.
23
- *
24
- * Errors can be watched through the function `onError` of a CitricController.
25
- *
26
- * Attention: if you're using React Suspense, consider using the component "FallbackBoundary" instead.
27
- *
28
- * @example
29
- * ```
30
- * <ErrorBoundary>
31
- * {content}
32
- * </ErrorBoundary>
33
- * ```
34
- */
35
- export class ErrorBoundary extends Component<Props, State> {
36
- static contextType = CitricContext
37
- declare context: React.ContextType<typeof CitricContext>
38
-
39
- constructor(props: Props) {
40
- super(props)
41
- this.state = {}
42
- }
43
-
44
- static getDerivedStateFromError(error: any) {
45
- return { error }
46
- }
47
-
48
- componentDidCatch(error: any, errorInfo: any) {
49
- this.context?.onError?.(error)
50
- // eslint-disable-next-line no-console
51
- console.error(error, errorInfo)
52
- }
53
-
54
- componentDidUpdate(prevProps: Readonly<Props>) {
55
- if (this.state.error && this.props.children !== prevProps.children) {
56
- this.setState({ error: null })
57
- }
58
- }
59
-
60
- private renderCustomErrorUI() {
61
- return this.context?.renderError?.(this.state.error)
62
- }
63
-
64
- private renderErrorUI() {
65
- if (typeof this.props.message === 'function') return this.props.message(this.state.error)
66
- return (this.props.message || !this.context?.renderError)
67
- ? <ErrorMessage error={this.props.message || this.state.error} />
68
- : this.renderCustomErrorUI()
69
- }
70
-
71
-
72
- render() {
73
- return this.state.error ? this.renderErrorUI() : this.props.children
74
- }
75
- }
1
+ import { Component } from 'react'
2
+ import { CitricContext } from '../context/CitricContext'
3
+ import { ErrorMessage } from './ErrorMessage'
4
+
5
+ interface State {
6
+ error?: any,
7
+ }
8
+
9
+ interface Props {
10
+ children: React.ReactNode,
11
+ /**
12
+ * Sets a default error string when a string is provided.
13
+ *
14
+ * Replaces the error component, if a function is provided.
15
+ */
16
+ message?: React.ReactNode | ((error: any) => React.ReactNode),
17
+ }
18
+
19
+ /**
20
+ * An Error Boundary that renders an error feedback instead of its content if any of its children throws.
21
+ *
22
+ * You can customize the appearance of the error through the function `renderError` of a CitricController.
23
+ *
24
+ * Errors can be watched through the function `onError` of a CitricController.
25
+ *
26
+ * Attention: if you're using React Suspense, consider using the component "FallbackBoundary" instead.
27
+ *
28
+ * @example
29
+ * ```
30
+ * <ErrorBoundary>
31
+ * {content}
32
+ * </ErrorBoundary>
33
+ * ```
34
+ */
35
+ export class ErrorBoundary extends Component<Props, State> {
36
+ static contextType = CitricContext
37
+ declare context: React.ContextType<typeof CitricContext>
38
+
39
+ constructor(props: Props) {
40
+ super(props)
41
+ this.state = {}
42
+ }
43
+
44
+ static getDerivedStateFromError(error: any) {
45
+ return { error }
46
+ }
47
+
48
+ componentDidCatch(error: any, errorInfo: any) {
49
+ this.context?.onError?.(error)
50
+ // eslint-disable-next-line no-console
51
+ console.error(error, errorInfo)
52
+ }
53
+
54
+ componentDidUpdate(prevProps: Readonly<Props>) {
55
+ if (this.state.error && this.props.children !== prevProps.children) {
56
+ this.setState({ error: null })
57
+ }
58
+ }
59
+
60
+ private renderCustomErrorUI() {
61
+ return this.context?.renderError?.(this.state.error)
62
+ }
63
+
64
+ private renderErrorUI() {
65
+ if (typeof this.props.message === 'function') return this.props.message(this.state.error)
66
+ return (this.props.message || !this.context?.renderError)
67
+ ? <ErrorMessage error={this.props.message || this.state.error} />
68
+ : this.renderCustomErrorUI()
69
+ }
70
+
71
+
72
+ render() {
73
+ return this.state.error ? this.renderErrorUI() : this.props.children
74
+ }
75
+ }
@@ -1,11 +1,11 @@
1
- import { Icon } from '@stack-spot/citric-icons'
2
- import { theme } from '@stack-spot/portal-theme'
3
- import { Row } from './layout'
4
- import { Text } from './Text'
5
-
6
- export const ErrorMessage = ({ error }: { error: any }) => (
7
- <Row gap="18px" p="20px" justifyContent="center">
8
- <Icon icon="TimesCircle" size="xl" style={{ color: theme.color.danger[500] }} />
9
- <Text>{error.message || `${error}`}</Text>
10
- </Row>
11
- )
1
+ import { Icon } from '@stack-spot/citric-icons'
2
+ import { theme } from '@stack-spot/portal-theme'
3
+ import { Row } from './layout'
4
+ import { Text } from './Text'
5
+
6
+ export const ErrorMessage = ({ error }: { error: any }) => (
7
+ <Row gap="18px" p="20px" justifyContent="center">
8
+ <Icon icon="TimesCircle" size="xl" style={{ color: theme.color.danger[500] }} />
9
+ <Text>{error.message || `${error}`}</Text>
10
+ </Row>
11
+ )
@@ -1,40 +1,40 @@
1
- import { Suspense } from 'react'
2
- import { ErrorBoundary } from './ErrorBoundary'
3
- import { Center } from './layout'
4
- import { ProgressCircular } from './ProgressCircular'
5
-
6
- interface Props {
7
- /**
8
- * Replaces the error message with this text.
9
- */
10
- message?: string,
11
- children: React.ReactNode,
12
- }
13
-
14
- const loading = (
15
- <Center flex={1} p="80px" data-test-hint="loading">
16
- <ProgressCircular />
17
- </Center>
18
- )
19
-
20
- /**
21
- * A Boundary that renders an error feedback if a child throws an error or a loading feedback if it suspends.
22
- *
23
- * You can customize the appearance of the loading and error views through a CitricController.
24
- *
25
- * Errors can be watched through the function `onError` of a CitricController.
26
- *
27
- * @example
28
- * ```
29
- * <FallbackBoundary>
30
- * {content}
31
- * </FallbackBoundary>
32
- * ```
33
- */
34
- export const FallbackBoundary = ({ children, message }: Props) => (
35
- <ErrorBoundary message={message}>
36
- <Suspense fallback={loading}>
37
- {children}
38
- </Suspense>
39
- </ErrorBoundary>
40
- )
1
+ import { Suspense } from 'react'
2
+ import { ErrorBoundary } from './ErrorBoundary'
3
+ import { Center } from './layout'
4
+ import { ProgressCircular } from './ProgressCircular'
5
+
6
+ interface Props {
7
+ /**
8
+ * Replaces the error message with this text.
9
+ */
10
+ message?: string,
11
+ children: React.ReactNode,
12
+ }
13
+
14
+ const loading = (
15
+ <Center flex={1} p="80px" data-test-hint="loading">
16
+ <ProgressCircular />
17
+ </Center>
18
+ )
19
+
20
+ /**
21
+ * A Boundary that renders an error feedback if a child throws an error or a loading feedback if it suspends.
22
+ *
23
+ * You can customize the appearance of the loading and error views through a CitricController.
24
+ *
25
+ * Errors can be watched through the function `onError` of a CitricController.
26
+ *
27
+ * @example
28
+ * ```
29
+ * <FallbackBoundary>
30
+ * {content}
31
+ * </FallbackBoundary>
32
+ * ```
33
+ */
34
+ export const FallbackBoundary = ({ children, message }: Props) => (
35
+ <ErrorBoundary message={message}>
36
+ <Suspense fallback={loading}>
37
+ {children}
38
+ </Suspense>
39
+ </ErrorBoundary>
40
+ )
@@ -1,57 +1,57 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { ControlledInput } from '../types'
3
- import { withRef } from '../utils/react'
4
- import { CitricComponent } from './CitricComponent'
5
-
6
- type FavoriteAppearance = 'square' | 'circle' | 'text'
7
-
8
- export interface BaseFavoriteProps {
9
- value: boolean | undefined,
10
- /**
11
- * Size of the button.
12
- *
13
- * @default 'md'
14
- */
15
- size?: 'sm' | 'md' | 'lg' | 'fit-parent',
16
- /**
17
- * Button appearance.
18
- *
19
- * @default 'text'
20
- */
21
- appearance?: FavoriteAppearance,
22
- onChange: (value: boolean) => void,
23
- /**
24
- * Whether or not to show the loading feedback.
25
- *
26
- * If `loading` is true, this button becomes disabled.
27
- */
28
- loading?: boolean,
29
- }
30
-
31
- export type FavoriteProps = Omit<ControlledInput, 'size'> & BaseFavoriteProps
32
-
33
- /**
34
- * Renders a checkbox with the appearance of a favorite button. If unchecked, the stroke of a star is rendered, when checked, a filled
35
- * yellow star is rendered.
36
- *
37
- * You can also set a loading state to indicate the component is busy.
38
- *
39
- * @example
40
- * ```
41
- * const { isFavorite, setFavorite, isLoading } = useRemoteFavoriteStatus()
42
- * return <Favorite value={isFavorite} onChange={setFavorite} loading={isLoading} />
43
- * ```
44
- */
45
- export const Favorite = withRef(({ value, size, appearance, onChange, loading, disabled, className, ...props }: FavoriteProps) =>
46
- <CitricComponent
47
- tag="input"
48
- type="checkbox"
49
- component="favorite"
50
- className={listToClass([appearance, size, className])}
51
- checked={!!value}
52
- onChange={() => onChange(!value)}
53
- aria-busy={loading}
54
- disabled={loading || disabled}
55
- {...props}
56
- />,
57
- )
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { ControlledInput } from '../types'
3
+ import { withRef } from '../utils/react'
4
+ import { CitricComponent } from './CitricComponent'
5
+
6
+ type FavoriteAppearance = 'square' | 'circle' | 'text'
7
+
8
+ export interface BaseFavoriteProps {
9
+ value: boolean | undefined,
10
+ /**
11
+ * Size of the button.
12
+ *
13
+ * @default 'md'
14
+ */
15
+ size?: 'sm' | 'md' | 'lg' | 'fit-parent',
16
+ /**
17
+ * Button appearance.
18
+ *
19
+ * @default 'text'
20
+ */
21
+ appearance?: FavoriteAppearance,
22
+ onChange: (value: boolean) => void,
23
+ /**
24
+ * Whether or not to show the loading feedback.
25
+ *
26
+ * If `loading` is true, this button becomes disabled.
27
+ */
28
+ loading?: boolean,
29
+ }
30
+
31
+ export type FavoriteProps = Omit<ControlledInput, 'size'> & BaseFavoriteProps
32
+
33
+ /**
34
+ * Renders a checkbox with the appearance of a favorite button. If unchecked, the stroke of a star is rendered, when checked, a filled
35
+ * yellow star is rendered.
36
+ *
37
+ * You can also set a loading state to indicate the component is busy.
38
+ *
39
+ * @example
40
+ * ```
41
+ * const { isFavorite, setFavorite, isLoading } = useRemoteFavoriteStatus()
42
+ * return <Favorite value={isFavorite} onChange={setFavorite} loading={isLoading} />
43
+ * ```
44
+ */
45
+ export const Favorite = withRef(({ value, size, appearance, onChange, loading, disabled, className, ...props }: FavoriteProps) =>
46
+ <CitricComponent
47
+ tag="input"
48
+ type="checkbox"
49
+ component="favorite"
50
+ className={listToClass([appearance, size, className])}
51
+ checked={!!value}
52
+ onChange={() => onChange(!value)}
53
+ aria-busy={loading}
54
+ disabled={loading || disabled}
55
+ {...props}
56
+ />,
57
+ )