@stack-spot/citric-react 0.38.0 → 0.39.1

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 (191) hide show
  1. package/CHANGELOG.md +13 -13
  2. package/dist/citric.css +2844 -2844
  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/Avatar.d.ts +1 -1
  10. package/dist/components/Avatar.js +1 -1
  11. package/dist/components/AvatarGroup.d.ts +1 -1
  12. package/dist/components/AvatarGroup.js +1 -1
  13. package/dist/components/Badge.d.ts +1 -1
  14. package/dist/components/Badge.js +1 -1
  15. package/dist/components/Blockquote.d.ts +1 -1
  16. package/dist/components/Blockquote.js +1 -1
  17. package/dist/components/Breadcrumb.d.ts +1 -1
  18. package/dist/components/Breadcrumb.js +1 -1
  19. package/dist/components/Button.d.ts +1 -1
  20. package/dist/components/Button.js +1 -1
  21. package/dist/components/ButtonLink.d.ts +1 -1
  22. package/dist/components/ButtonLink.js +1 -1
  23. package/dist/components/Card.d.ts +1 -1
  24. package/dist/components/Card.js +1 -1
  25. package/dist/components/Checkbox.d.ts +1 -1
  26. package/dist/components/Checkbox.js +1 -1
  27. package/dist/components/CheckboxGroup.d.ts +1 -1
  28. package/dist/components/CheckboxGroup.d.ts.map +1 -1
  29. package/dist/components/CheckboxGroup.js +2 -2
  30. package/dist/components/CheckboxGroup.js.map +1 -1
  31. package/dist/components/Circle.d.ts +1 -1
  32. package/dist/components/Circle.js +1 -1
  33. package/dist/components/Divider.d.ts +1 -1
  34. package/dist/components/Divider.js +1 -1
  35. package/dist/components/ErrorBoundary.d.ts +1 -1
  36. package/dist/components/ErrorBoundary.js +1 -1
  37. package/dist/components/ErrorMessage.d.ts +1 -1
  38. package/dist/components/ErrorMessage.js +1 -1
  39. package/dist/components/FallbackBoundary.d.ts +1 -1
  40. package/dist/components/FallbackBoundary.js +1 -1
  41. package/dist/components/Favorite.d.ts +1 -1
  42. package/dist/components/Favorite.js +1 -1
  43. package/dist/components/FieldGroup.d.ts +1 -1
  44. package/dist/components/FieldGroup.js +1 -1
  45. package/dist/components/Form.d.ts +2 -2
  46. package/dist/components/Form.js +1 -1
  47. package/dist/components/FormGroup.d.ts +1 -1
  48. package/dist/components/FormGroup.js +1 -1
  49. package/dist/components/Icon.d.ts +1 -1
  50. package/dist/components/Icon.js +1 -1
  51. package/dist/components/IconBox.d.ts +3 -3
  52. package/dist/components/IconBox.js +1 -1
  53. package/dist/components/ImageBox.d.ts +3 -3
  54. package/dist/components/ImageBox.js +1 -1
  55. package/dist/components/ImageWithFallback.d.ts +1 -1
  56. package/dist/components/ImageWithFallback.js +1 -1
  57. package/dist/components/Input.d.ts +1 -1
  58. package/dist/components/Input.js +1 -1
  59. package/dist/components/Link.d.ts +1 -1
  60. package/dist/components/Link.js +1 -1
  61. package/dist/components/LoadingPanel.d.ts +1 -1
  62. package/dist/components/LoadingPanel.js +1 -1
  63. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  64. package/dist/components/MenuOverlay/Menu.js +1 -1
  65. package/dist/components/MenuOverlay/index.d.ts +1 -1
  66. package/dist/components/MenuOverlay/index.js +1 -1
  67. package/dist/components/Overlay/index.d.ts +4 -1
  68. package/dist/components/Overlay/index.d.ts.map +1 -1
  69. package/dist/components/Overlay/index.js +4 -1
  70. package/dist/components/Overlay/index.js.map +1 -1
  71. package/dist/components/Pagination.d.ts +1 -1
  72. package/dist/components/Pagination.js +1 -1
  73. package/dist/components/ProgressBar.d.ts +1 -1
  74. package/dist/components/ProgressBar.js +1 -1
  75. package/dist/components/ProgressCircular.d.ts +1 -1
  76. package/dist/components/ProgressCircular.js +1 -1
  77. package/dist/components/RadioGroup.d.ts +1 -1
  78. package/dist/components/RadioGroup.d.ts.map +1 -1
  79. package/dist/components/RadioGroup.js +2 -2
  80. package/dist/components/RadioGroup.js.map +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 +1 -1
  92. package/dist/components/SelectBox.js +1 -1
  93. package/dist/components/Skeleton.d.ts +1 -1
  94. package/dist/components/Skeleton.js +1 -1
  95. package/dist/components/Slider.d.ts +1 -1
  96. package/dist/components/Slider.js +1 -1
  97. package/dist/components/SmartTable.d.ts +1 -1
  98. package/dist/components/SmartTable.js +1 -1
  99. package/dist/components/Stepper.d.ts +1 -1
  100. package/dist/components/Stepper.js +1 -1
  101. package/dist/components/Table.d.ts +3 -3
  102. package/dist/components/Table.js +1 -1
  103. package/dist/components/Tabs/index.d.ts +1 -1
  104. package/dist/components/Tabs/index.js +1 -1
  105. package/dist/components/Textarea.d.ts +1 -1
  106. package/dist/components/Textarea.js +1 -1
  107. package/dist/components/Tooltip.d.ts +1 -1
  108. package/dist/components/Tooltip.js +1 -1
  109. package/dist/context/CitricProvider.d.ts +1 -1
  110. package/dist/context/CitricProvider.js +1 -1
  111. package/dist/overlay.js +1 -1
  112. package/dist/theme.css +415 -415
  113. package/package.json +1 -1
  114. package/scripts/build-css.ts +49 -49
  115. package/src/components/Accordion.tsx +130 -130
  116. package/src/components/Alert.tsx +24 -24
  117. package/src/components/AsyncContent.tsx +70 -70
  118. package/src/components/Avatar.tsx +45 -45
  119. package/src/components/AvatarGroup.tsx +49 -49
  120. package/src/components/Badge.tsx +47 -47
  121. package/src/components/Blockquote.tsx +18 -18
  122. package/src/components/Breadcrumb.tsx +33 -33
  123. package/src/components/Button.tsx +105 -105
  124. package/src/components/ButtonLink.tsx +45 -45
  125. package/src/components/Card.tsx +68 -68
  126. package/src/components/Checkbox.tsx +51 -51
  127. package/src/components/CheckboxGroup.tsx +153 -152
  128. package/src/components/Circle.tsx +43 -43
  129. package/src/components/CitricComponent.ts +47 -47
  130. package/src/components/Divider.tsx +24 -24
  131. package/src/components/ErrorBoundary.tsx +75 -75
  132. package/src/components/ErrorMessage.tsx +11 -11
  133. package/src/components/FallbackBoundary.tsx +40 -40
  134. package/src/components/Favorite.tsx +57 -57
  135. package/src/components/FieldGroup.tsx +46 -46
  136. package/src/components/Form.tsx +36 -36
  137. package/src/components/FormGroup.tsx +57 -57
  138. package/src/components/Icon.tsx +35 -35
  139. package/src/components/IconBox.tsx +134 -134
  140. package/src/components/ImageBox.tsx +125 -125
  141. package/src/components/ImageWithFallback.tsx +65 -65
  142. package/src/components/Input.tsx +49 -49
  143. package/src/components/Link.tsx +55 -55
  144. package/src/components/LoadingPanel.tsx +8 -8
  145. package/src/components/MenuOverlay/Menu.tsx +158 -158
  146. package/src/components/MenuOverlay/context.ts +20 -20
  147. package/src/components/MenuOverlay/index.tsx +55 -55
  148. package/src/components/MenuOverlay/keyboard.ts +60 -60
  149. package/src/components/MenuOverlay/types.ts +171 -171
  150. package/src/components/Overlay/context.ts +10 -10
  151. package/src/components/Overlay/index.tsx +167 -164
  152. package/src/components/Overlay/types.ts +70 -70
  153. package/src/components/Pagination.tsx +133 -133
  154. package/src/components/ProgressBar.tsx +45 -45
  155. package/src/components/ProgressCircular.tsx +45 -45
  156. package/src/components/RadioGroup.tsx +147 -146
  157. package/src/components/Rating.tsx +98 -98
  158. package/src/components/Select/MultiSelect.tsx +217 -217
  159. package/src/components/Select/RichSelect.tsx +128 -128
  160. package/src/components/Select/SimpleSelect.tsx +73 -73
  161. package/src/components/Select/hooks.ts +133 -133
  162. package/src/components/Select/index.tsx +35 -35
  163. package/src/components/Select/types.ts +134 -134
  164. package/src/components/SelectBox.tsx +167 -167
  165. package/src/components/Skeleton.tsx +53 -53
  166. package/src/components/Slider.tsx +89 -89
  167. package/src/components/SmartTable.tsx +227 -227
  168. package/src/components/Stepper.tsx +163 -163
  169. package/src/components/Table.tsx +234 -234
  170. package/src/components/Tabs/TabController.ts +54 -54
  171. package/src/components/Tabs/index.tsx +87 -87
  172. package/src/components/Tabs/types.ts +54 -54
  173. package/src/components/Tabs/utils.ts +6 -6
  174. package/src/components/Text.ts +111 -111
  175. package/src/components/Textarea.tsx +27 -27
  176. package/src/components/Tooltip.tsx +72 -72
  177. package/src/components/layout.tsx +101 -101
  178. package/src/context/CitricContext.tsx +4 -4
  179. package/src/context/CitricProvider.tsx +14 -14
  180. package/src/context/hooks.ts +6 -6
  181. package/src/index.ts +58 -58
  182. package/src/overlay.ts +341 -341
  183. package/src/types.ts +216 -216
  184. package/src/utils/ValueController.ts +28 -28
  185. package/src/utils/acessibility.ts +92 -92
  186. package/src/utils/checkbox.ts +121 -121
  187. package/src/utils/css.ts +119 -119
  188. package/src/utils/options.ts +9 -9
  189. package/src/utils/radio.ts +93 -93
  190. package/src/utils/react.ts +6 -6
  191. package/tsconfig.json +10 -10
@@ -1,36 +1,36 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { withRef } from '../utils/react'
3
- import { CitricComponent } from './CitricComponent'
4
-
5
- export type FormProps = JSX.IntrinsicElements['form']
6
- export type ButtonGroupProps = JSX.IntrinsicElements['div']
7
-
8
- /**
9
- * A form, styled to receive rows, form groups and button groups.
10
- *
11
- * This has the exact same interface as the HTML form.
12
- */
13
- export const Form = ({ children, ...props }: FormProps) => (
14
- <CitricComponent tag="form" component="form" {...props}>
15
- {children}
16
- </CitricComponent>
17
- )
18
-
19
- /**
20
- * Renders a group of buttons in a form.
21
- *
22
- * @example
23
- * ```
24
- * <Form>
25
- * <ButtonGroup>
26
- * <Button>Cancel</Button>
27
- * <Button type="submit">Submit</Button>
28
- * </ButtonGroup>
29
- * </Form>
30
- * ```
31
- */
32
- export const ButtonGroup = withRef(({ className, children, ...props }: ButtonGroupProps) => (
33
- <div className={listToClass([className, 'button-group'])} {...props}>
34
- {children}
35
- </div>
36
- ))
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { withRef } from '../utils/react'
3
+ import { CitricComponent } from './CitricComponent'
4
+
5
+ export type FormProps = JSX.IntrinsicElements['form']
6
+ export type ButtonGroupProps = JSX.IntrinsicElements['div']
7
+
8
+ /**
9
+ * A form, styled to receive rows, form groups and button groups.
10
+ *
11
+ * This has the exact same interface as the HTML form.
12
+ */
13
+ export const Form = ({ children, ...props }: FormProps) => (
14
+ <CitricComponent tag="form" component="form" {...props}>
15
+ {children}
16
+ </CitricComponent>
17
+ )
18
+
19
+ /**
20
+ * Renders a group of buttons in a form.
21
+ *
22
+ * @example
23
+ * ```
24
+ * <Form>
25
+ * <ButtonGroup>
26
+ * <Button>Cancel</Button>
27
+ * <Button type="submit">Submit</Button>
28
+ * </ButtonGroup>
29
+ * </Form>
30
+ * ```
31
+ */
32
+ export const ButtonGroup = withRef(({ className, children, ...props }: ButtonGroupProps) => (
33
+ <div className={listToClass([className, 'button-group'])} {...props}>
34
+ {children}
35
+ </div>
36
+ ))
@@ -1,57 +1,57 @@
1
- import { listToClass } from '@stack-spot/portal-theme'
2
- import { withRef } from '../utils/react'
3
- import { CitricComponent } from './CitricComponent'
4
- import { IconButton } from './IconBox'
5
- import { Text } from './Text'
6
- import { Tooltip } from './Tooltip'
7
-
8
- export interface BaseFormGroupProps {
9
- /**
10
- * The error string to show, if any. The empty string is equivalent to undefined, i.e. no errors.
11
- */
12
- error?: string,
13
- /**
14
- * The input's label.
15
- */
16
- label?: string,
17
- /**
18
- * A help string, to show as a tooltip.
19
- */
20
- help?: string,
21
- /**
22
- * A warning string, to show right below the field, at all times.
23
- */
24
- warning?: string,
25
- }
26
-
27
- export type FormGroupProps = React.JSX.IntrinsicElements['div'] & BaseFormGroupProps
28
-
29
- /**
30
- * A form group renders everything a field in a form needs: the input, its label, a tooltip (help), an error and a remark (warning).
31
- *
32
- * Labels, errors, tooltips and warnings are only rendered when they're strings with at least one character.
33
- *
34
- * @example
35
- * ```
36
- * <FormGroup label="Birth Date" help="The date when you were born" error="The date you typed is invalid!">
37
- * <Input type="date" />
38
- * </FormGroup>
39
- * ```
40
- */
41
- export const FormGroup = withRef(({ error, help, label, warning, className, children, ...props }: FormGroupProps) => (
42
- <CitricComponent tag="div" component="form-group" className={listToClass([className, error && 'error'])} {...props}>
43
- <label>
44
- {help ? (
45
- <div className="row">
46
- <Text>{label}</Text>
47
- <Tooltip content={help}>
48
- <IconButton icon="InfoCircle" size="xs" />
49
- </Tooltip>
50
- </div>
51
- ): label}
52
- {children}
53
- <div className="feedback">{error}</div>
54
- {warning && <div className="warning">{warning}</div>}
55
- </label>
56
- </CitricComponent>
57
- ))
1
+ import { listToClass } from '@stack-spot/portal-theme'
2
+ import { withRef } from '../utils/react'
3
+ import { CitricComponent } from './CitricComponent'
4
+ import { IconButton } from './IconBox'
5
+ import { Text } from './Text'
6
+ import { Tooltip } from './Tooltip'
7
+
8
+ export interface BaseFormGroupProps {
9
+ /**
10
+ * The error string to show, if any. The empty string is equivalent to undefined, i.e. no errors.
11
+ */
12
+ error?: string,
13
+ /**
14
+ * The input's label.
15
+ */
16
+ label?: string,
17
+ /**
18
+ * A help string, to show as a tooltip.
19
+ */
20
+ help?: string,
21
+ /**
22
+ * A warning string, to show right below the field, at all times.
23
+ */
24
+ warning?: string,
25
+ }
26
+
27
+ export type FormGroupProps = React.JSX.IntrinsicElements['div'] & BaseFormGroupProps
28
+
29
+ /**
30
+ * A form group renders everything a field in a form needs: the input, its label, a tooltip (help), an error and a remark (warning).
31
+ *
32
+ * Labels, errors, tooltips and warnings are only rendered when they're strings with at least one character.
33
+ *
34
+ * @example
35
+ * ```
36
+ * <FormGroup label="Birth Date" help="The date when you were born" error="The date you typed is invalid!">
37
+ * <Input type="date" />
38
+ * </FormGroup>
39
+ * ```
40
+ */
41
+ export const FormGroup = withRef(({ error, help, label, warning, className, children, ...props }: FormGroupProps) => (
42
+ <CitricComponent tag="div" component="form-group" className={listToClass([className, error && 'error'])} {...props}>
43
+ <label>
44
+ {help ? (
45
+ <div className="row">
46
+ <Text>{label}</Text>
47
+ <Tooltip content={help}>
48
+ <IconButton icon="InfoCircle" size="xs" />
49
+ </Tooltip>
50
+ </div>
51
+ ): label}
52
+ {children}
53
+ <div className="feedback">{error}</div>
54
+ {warning && <div className="warning">{warning}</div>}
55
+ </label>
56
+ </CitricComponent>
57
+ ))
@@ -1,35 +1,35 @@
1
- import { IconGroup, Icon as OgIcon, IconProps as OgIconProps } from '@stack-spot/citric-icons'
2
- import { ColorKey } from '@stack-spot/portal-theme'
3
- import { colorNameToColorVariable } from '../utils/css'
4
-
5
- export type IconProps<T extends IconGroup> = Omit<OgIconProps<T>, 'color'> & {
6
- /**
7
- * The color for the icon. Can be any color in the theme.
8
- */
9
- color?: ColorKey,
10
- }
11
-
12
- /**
13
- * Renders an icon based on the properties "icon" and "group".
14
- *
15
- * There are three icon groups:
16
- * - outline: most of the icons are in this group. The icons are stroke only.
17
- * - fill: most outline icons have a fill version. Fill icons are filled with solid colors, they're not just strokes.
18
- * - social: icons for brands (logos).
19
- *
20
- * By default, the group is "outline".
21
- *
22
- * The icon size depends on the font-size of the current context. To set a specific size, use the property "size".
23
- *
24
- * Attention: this is the same as using the component Icon from the icons component, the only difference is that this accepts the property
25
- * "color".
26
- *
27
- * @example
28
- *
29
- * ```
30
- * <Icon icon="Search" />
31
- * ```
32
- */
33
- export function Icon<T extends IconGroup>({ color, style, ...props }: IconProps<T>) {
34
- return <OgIcon {...props} style={{ color: color ? colorNameToColorVariable(color) : undefined, ...style }} />
35
- }
1
+ import { IconGroup, Icon as OgIcon, IconProps as OgIconProps } from '@stack-spot/citric-icons'
2
+ import { ColorKey } from '@stack-spot/portal-theme'
3
+ import { colorNameToColorVariable } from '../utils/css'
4
+
5
+ export type IconProps<T extends IconGroup> = Omit<OgIconProps<T>, 'color'> & {
6
+ /**
7
+ * The color for the icon. Can be any color in the theme.
8
+ */
9
+ color?: ColorKey,
10
+ }
11
+
12
+ /**
13
+ * Renders an icon based on the properties "icon" and "group".
14
+ *
15
+ * There are three icon groups:
16
+ * - outline: most of the icons are in this group. The icons are stroke only.
17
+ * - fill: most outline icons have a fill version. Fill icons are filled with solid colors, they're not just strokes.
18
+ * - social: icons for brands (logos).
19
+ *
20
+ * By default, the group is "outline".
21
+ *
22
+ * The icon size depends on the font-size of the current context. To set a specific size, use the property "size".
23
+ *
24
+ * Attention: this is the same as using the component Icon from the icons component, the only difference is that this accepts the property
25
+ * "color".
26
+ *
27
+ * @example
28
+ *
29
+ * ```
30
+ * <Icon icon="Search" />
31
+ * ```
32
+ */
33
+ export function Icon<T extends IconGroup>({ color, style, ...props }: IconProps<T>) {
34
+ return <OgIcon {...props} style={{ color: color ? colorNameToColorVariable(color) : undefined, ...style }} />
35
+ }
@@ -1,134 +1,134 @@
1
- import { BaseIconProps, IconGroup } from '@stack-spot/citric-icons'
2
- import { listToClass } from '@stack-spot/portal-theme'
3
- import { useCitricController } from '../context/hooks'
4
- import { HTMLTag, WithColorPalette, WithColorScheme } from '../types'
5
- import { withRef } from '../utils/react'
6
- import { asCitricProps, CitricComponent } from './CitricComponent'
7
-
8
- type IconBoxTag = 'a' | 'button' | 'i' | 'span' | 'div'
9
-
10
- export interface BaseIconBoxProps<T extends IconBoxTag, G extends IconGroup> extends BaseIconProps<G>, WithColorScheme, WithColorPalette {
11
- /**
12
- * The HTML element to render.
13
- *
14
- * @default 'i'
15
- */
16
- tag?: T,
17
- /**
18
- * The box appearance.
19
- *
20
- * - circle: a circle with a background color. Its size depends on the value of `size`. If this is clickable, the background and
21
- * foreground colors change on hover or focus.
22
- * - square: a square with rounded corners and a background color. Its size depends on the value of `size`. If this is clickable, the
23
- * background and foreground colors change on hover or focus.
24
- * - text: a circle with transparent background. Its size depends on the value of `size`. If this is clickable, the background and
25
- * foreground colors change on hover or focus (it won't be transparent).
26
- * - none: no special styling, its size depends only on the size of the icon (the property `size` is ignored). Even if this is clickable,
27
- * the style doesn't change on hover or focus.
28
- *
29
- * @default 'circle'
30
- */
31
- appearance?: 'circle' | 'square' | 'text' | 'none',
32
- /**
33
- * Size of the box.
34
- *
35
- * - xs: 20px;
36
- * - sm: 24px;
37
- * - md: 32px;
38
- * - lg: 40px.
39
- *
40
- * @default 'sm'
41
- */
42
- size?: 'xs' | 'sm' | 'md' | 'lg',
43
- /**
44
- * Animated text to show on when the button/link is clicked. This is only valid for buttons and anchors.
45
- */
46
- feedback?: string,
47
- /**
48
- * Only valid if `tag` is "button" or "a".
49
- *
50
- * Metadata for the general onClick event, set by the CitricController. Useful for creating analytics data.
51
- *
52
- * This only takes effect if there's a CitricController in React's context. The value of `metadata` is passed to the function
53
- * `onClickButton/onClickLink` of the controller.
54
- *
55
- * @default false
56
- */
57
- metadata?: any,
58
- }
59
-
60
- export type IconBoxProps<T extends IconBoxTag, G extends IconGroup> = Omit<HTMLTag[T], 'children'> & BaseIconBoxProps<T, G>
61
-
62
- /**
63
- * Renders a wrapper for an icon. The icon must specified by the properties "icon" and "group", this component accepts no children.
64
- *
65
- * If you don't need the icon to be rendered within a box, consider using the component "Icon" directly.
66
- *
67
- * Hover and focus effects are applied if the IconBox is focusable.
68
- *
69
- * @example
70
- * ```
71
- * <IconBox icon="Search" colorScheme="primary" />
72
- * ```
73
- */
74
- export const IconBox = withRef(
75
- function IconBox<T extends IconBoxTag = 'i', G extends IconGroup = 'outline'>(
76
- { group, icon, tag, appearance, size, className, metadata, onClick, feedback, ...props }: IconBoxProps<T, G>,
77
- ) {
78
- props['aria-label'] ||= props.title // accessibility
79
- const citric = useCitricController()
80
-
81
- function handleClick(e: React.MouseEvent<any>) {
82
- onClick?.(e)
83
- if (tag === 'button') citric?.onClickButton?.(e, metadata)
84
- else if (tag === 'a') citric?.onClickLink?.(e, metadata)
85
- }
86
-
87
- const componentProps = {
88
- tag: (tag || 'i') as any,
89
- component: 'icon-box',
90
- className: listToClass(['citric-icon', group || 'outline', icon, appearance, size, className]),
91
- 'data-feedback': feedback || undefined,
92
- onClick: ['button', 'a'].includes(tag ?? '') ? handleClick : onClick,
93
- ...props,
94
- } as const
95
-
96
- return tag === 'a' && citric?.renderLink
97
- ? citric.renderLink(asCitricProps(componentProps))
98
- : <CitricComponent {...componentProps} />
99
- },
100
- )
101
-
102
- /**
103
- * A shortcut for `<IconBox tag="button">`.
104
- *
105
- * Whenever a button is clicked, the function `onClickButton` of the nearest CitricController is called with the event and the value of the
106
- * prop `metadata`.
107
- *
108
- * @example
109
- * ```
110
- * <IconButton icon="Search" />
111
- * ```
112
- */
113
- export const IconButton = withRef(
114
- function IconButton<G extends IconGroup = 'outline'>({ type, ...props }: Omit<IconBoxProps<'button', G>, 'tag'>) {
115
- return <IconBox {...props} tag="button" type={type || 'button' } />
116
- },
117
- )
118
-
119
- /**
120
- * A shortcut for `<IconBox tag="a">`.
121
- *
122
- * Whenever a link is clicked, the function `onClickLink` of the nearest CitricController is called with the event and the value of the
123
- * prop `metadata`.
124
- *
125
- * @example
126
- * ```
127
- * <IconLink icon="Search" href="#" />
128
- * ```
129
- */
130
- export const IconLink = withRef(
131
- function IconLink<G extends IconGroup = 'outline'>(props: Omit<IconBoxProps<'a', G>, 'tag'>) {
132
- return <IconBox {...props} tag="a" />
133
- },
134
- )
1
+ import { BaseIconProps, IconGroup } from '@stack-spot/citric-icons'
2
+ import { listToClass } from '@stack-spot/portal-theme'
3
+ import { useCitricController } from '../context/hooks'
4
+ import { HTMLTag, WithColorPalette, WithColorScheme } from '../types'
5
+ import { withRef } from '../utils/react'
6
+ import { asCitricProps, CitricComponent } from './CitricComponent'
7
+
8
+ type IconBoxTag = 'a' | 'button' | 'i' | 'span' | 'div'
9
+
10
+ export interface BaseIconBoxProps<T extends IconBoxTag, G extends IconGroup> extends BaseIconProps<G>, WithColorScheme, WithColorPalette {
11
+ /**
12
+ * The HTML element to render.
13
+ *
14
+ * @default 'i'
15
+ */
16
+ tag?: T,
17
+ /**
18
+ * The box appearance.
19
+ *
20
+ * - circle: a circle with a background color. Its size depends on the value of `size`. If this is clickable, the background and
21
+ * foreground colors change on hover or focus.
22
+ * - square: a square with rounded corners and a background color. Its size depends on the value of `size`. If this is clickable, the
23
+ * background and foreground colors change on hover or focus.
24
+ * - text: a circle with transparent background. Its size depends on the value of `size`. If this is clickable, the background and
25
+ * foreground colors change on hover or focus (it won't be transparent).
26
+ * - none: no special styling, its size depends only on the size of the icon (the property `size` is ignored). Even if this is clickable,
27
+ * the style doesn't change on hover or focus.
28
+ *
29
+ * @default 'circle'
30
+ */
31
+ appearance?: 'circle' | 'square' | 'text' | 'none',
32
+ /**
33
+ * Size of the box.
34
+ *
35
+ * - xs: 20px;
36
+ * - sm: 24px;
37
+ * - md: 32px;
38
+ * - lg: 40px.
39
+ *
40
+ * @default 'sm'
41
+ */
42
+ size?: 'xs' | 'sm' | 'md' | 'lg',
43
+ /**
44
+ * Animated text to show on when the button/link is clicked. This is only valid for buttons and anchors.
45
+ */
46
+ feedback?: string,
47
+ /**
48
+ * Only valid if `tag` is "button" or "a".
49
+ *
50
+ * Metadata for the general onClick event, set by the CitricController. Useful for creating analytics data.
51
+ *
52
+ * This only takes effect if there's a CitricController in React's context. The value of `metadata` is passed to the function
53
+ * `onClickButton/onClickLink` of the controller.
54
+ *
55
+ * @default false
56
+ */
57
+ metadata?: any,
58
+ }
59
+
60
+ export type IconBoxProps<T extends IconBoxTag, G extends IconGroup> = Omit<HTMLTag[T], 'children'> & BaseIconBoxProps<T, G>
61
+
62
+ /**
63
+ * Renders a wrapper for an icon. The icon must specified by the properties "icon" and "group", this component accepts no children.
64
+ *
65
+ * If you don't need the icon to be rendered within a box, consider using the component "Icon" directly.
66
+ *
67
+ * Hover and focus effects are applied if the IconBox is focusable.
68
+ *
69
+ * @example
70
+ * ```
71
+ * <IconBox icon="Search" colorScheme="primary" />
72
+ * ```
73
+ */
74
+ export const IconBox = withRef(
75
+ function IconBox<T extends IconBoxTag = 'i', G extends IconGroup = 'outline'>(
76
+ { group, icon, tag, appearance, size, className, metadata, onClick, feedback, ...props }: IconBoxProps<T, G>,
77
+ ) {
78
+ props['aria-label'] ||= props.title // accessibility
79
+ const citric = useCitricController()
80
+
81
+ function handleClick(e: React.MouseEvent<any>) {
82
+ onClick?.(e)
83
+ if (tag === 'button') citric?.onClickButton?.(e, metadata)
84
+ else if (tag === 'a') citric?.onClickLink?.(e, metadata)
85
+ }
86
+
87
+ const componentProps = {
88
+ tag: (tag || 'i') as any,
89
+ component: 'icon-box',
90
+ className: listToClass(['citric-icon', group || 'outline', icon, appearance, size, className]),
91
+ 'data-feedback': feedback || undefined,
92
+ onClick: ['button', 'a'].includes(tag ?? '') ? handleClick : onClick,
93
+ ...props,
94
+ } as const
95
+
96
+ return tag === 'a' && citric?.renderLink
97
+ ? citric.renderLink(asCitricProps(componentProps))
98
+ : <CitricComponent {...componentProps} />
99
+ },
100
+ )
101
+
102
+ /**
103
+ * A shortcut for `<IconBox tag="button">`.
104
+ *
105
+ * Whenever a button is clicked, the function `onClickButton` of the nearest CitricController is called with the event and the value of the
106
+ * prop `metadata`.
107
+ *
108
+ * @example
109
+ * ```
110
+ * <IconButton icon="Search" />
111
+ * ```
112
+ */
113
+ export const IconButton = withRef(
114
+ function IconButton<G extends IconGroup = 'outline'>({ type, ...props }: Omit<IconBoxProps<'button', G>, 'tag'>) {
115
+ return <IconBox {...props} tag="button" type={type || 'button' } />
116
+ },
117
+ )
118
+
119
+ /**
120
+ * A shortcut for `<IconBox tag="a">`.
121
+ *
122
+ * Whenever a link is clicked, the function `onClickLink` of the nearest CitricController is called with the event and the value of the
123
+ * prop `metadata`.
124
+ *
125
+ * @example
126
+ * ```
127
+ * <IconLink icon="Search" href="#" />
128
+ * ```
129
+ */
130
+ export const IconLink = withRef(
131
+ function IconLink<G extends IconGroup = 'outline'>(props: Omit<IconBoxProps<'a', G>, 'tag'>) {
132
+ return <IconBox {...props} tag="a" />
133
+ },
134
+ )