@stack-spot/citric-react 0.22.0 → 0.24.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.
- package/dist/citric.css +17 -4
- package/dist/components/Accordion.d.ts +34 -0
- package/dist/components/Accordion.d.ts.map +1 -1
- package/dist/components/Accordion.js +34 -0
- package/dist/components/Accordion.js.map +1 -1
- package/dist/components/Alert.d.ts +8 -0
- package/dist/components/Alert.d.ts.map +1 -1
- package/dist/components/Alert.js +8 -0
- package/dist/components/Alert.js.map +1 -1
- package/dist/components/AsyncContent.d.ts +18 -4
- package/dist/components/AsyncContent.d.ts.map +1 -1
- package/dist/components/AsyncContent.js +18 -4
- package/dist/components/AsyncContent.js.map +1 -1
- package/dist/components/Avatar.d.ts +9 -0
- package/dist/components/Avatar.d.ts.map +1 -1
- package/dist/components/Avatar.js +11 -1
- package/dist/components/Avatar.js.map +1 -1
- package/dist/components/AvatarGroup.d.ts +8 -0
- package/dist/components/AvatarGroup.d.ts.map +1 -1
- package/dist/components/AvatarGroup.js +8 -0
- package/dist/components/AvatarGroup.js.map +1 -1
- package/dist/components/Badge.d.ts +13 -2
- package/dist/components/Badge.d.ts.map +1 -1
- package/dist/components/Badge.js +14 -3
- package/dist/components/Badge.js.map +1 -1
- package/dist/components/Blockquote.d.ts +8 -0
- package/dist/components/Blockquote.d.ts.map +1 -1
- package/dist/components/Blockquote.js +8 -0
- package/dist/components/Blockquote.js.map +1 -1
- package/dist/components/Breadcrumb.d.ts +8 -0
- package/dist/components/Breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb.js +10 -1
- package/dist/components/Breadcrumb.js.map +1 -1
- package/dist/components/Button.d.ts +11 -0
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +14 -2
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Card.d.ts +15 -4
- package/dist/components/Card.d.ts.map +1 -1
- package/dist/components/Card.js +13 -1
- package/dist/components/Card.js.map +1 -1
- package/dist/components/Checkbox.d.ts +14 -0
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox.js +14 -0
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/CheckboxGroup.d.ts +22 -3
- package/dist/components/CheckboxGroup.d.ts.map +1 -1
- package/dist/components/CheckboxGroup.js +23 -3
- package/dist/components/CheckboxGroup.js.map +1 -1
- package/dist/components/Circle.d.ts +16 -0
- package/dist/components/Circle.d.ts.map +1 -1
- package/dist/components/Circle.js +8 -0
- package/dist/components/Circle.js.map +1 -1
- package/dist/components/CitricComponent.d.ts +14 -0
- package/dist/components/CitricComponent.d.ts.map +1 -1
- package/dist/components/CitricComponent.js +14 -0
- package/dist/components/CitricComponent.js.map +1 -1
- package/dist/components/Divider.d.ts +4 -1
- package/dist/components/Divider.d.ts.map +1 -1
- package/dist/components/Divider.js +4 -1
- package/dist/components/Divider.js.map +1 -1
- package/dist/components/ErrorBoundary.d.ts +13 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/ErrorBoundary.js +13 -0
- package/dist/components/ErrorBoundary.js.map +1 -1
- package/dist/components/ErrorMessage.js +1 -1
- package/dist/components/ErrorMessage.js.map +1 -1
- package/dist/components/FallbackBoundary.d.ts +12 -1
- package/dist/components/FallbackBoundary.d.ts.map +1 -1
- package/dist/components/FallbackBoundary.js +12 -1
- package/dist/components/FallbackBoundary.js.map +1 -1
- package/dist/components/Favorite.d.ts +12 -0
- package/dist/components/Favorite.d.ts.map +1 -1
- package/dist/components/Favorite.js +12 -0
- package/dist/components/Favorite.js.map +1 -1
- package/dist/components/FieldGroup.d.ts +13 -0
- package/dist/components/FieldGroup.d.ts.map +1 -1
- package/dist/components/FieldGroup.js +13 -0
- package/dist/components/FieldGroup.js.map +1 -1
- package/dist/components/Form.d.ts +18 -0
- package/dist/components/Form.d.ts.map +1 -1
- package/dist/components/Form.js +18 -0
- package/dist/components/Form.js.map +1 -1
- package/dist/components/FormGroup.d.ts +12 -0
- package/dist/components/FormGroup.d.ts.map +1 -1
- package/dist/components/FormGroup.js +12 -0
- package/dist/components/FormGroup.js.map +1 -1
- package/dist/components/IconBox.d.ts +33 -8
- package/dist/components/IconBox.d.ts.map +1 -1
- package/dist/components/IconBox.js +37 -11
- package/dist/components/IconBox.js.map +1 -1
- package/dist/components/ImageBox.d.ts +32 -8
- package/dist/components/ImageBox.d.ts.map +1 -1
- package/dist/components/ImageBox.js +36 -11
- package/dist/components/ImageBox.js.map +1 -1
- package/dist/components/ImageWithFallback.d.ts +18 -0
- package/dist/components/ImageWithFallback.d.ts.map +1 -1
- package/dist/components/ImageWithFallback.js +11 -0
- package/dist/components/ImageWithFallback.js.map +1 -1
- package/dist/components/Input.d.ts +15 -3
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Input.js +16 -3
- package/dist/components/Input.js.map +1 -1
- package/dist/components/Link.d.ts +6 -0
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/Link.js +6 -0
- package/dist/components/Link.js.map +1 -1
- package/dist/components/MenuOverlay/index.d.ts +20 -0
- package/dist/components/MenuOverlay/index.d.ts.map +1 -1
- package/dist/components/MenuOverlay/index.js +20 -0
- package/dist/components/MenuOverlay/index.js.map +1 -1
- package/dist/components/Overlay/index.d.ts +16 -0
- package/dist/components/Overlay/index.d.ts.map +1 -1
- package/dist/components/Overlay/index.js +16 -0
- package/dist/components/Overlay/index.js.map +1 -1
- package/dist/components/Pagination.d.ts +27 -8
- package/dist/components/Pagination.d.ts.map +1 -1
- package/dist/components/Pagination.js +18 -5
- package/dist/components/Pagination.js.map +1 -1
- package/dist/components/ProgressBar.d.ts +14 -0
- package/dist/components/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar.js +14 -0
- package/dist/components/ProgressBar.js.map +1 -1
- package/dist/components/ProgressCircular.d.ts +14 -0
- package/dist/components/ProgressCircular.d.ts.map +1 -1
- package/dist/components/ProgressCircular.js +14 -0
- package/dist/components/ProgressCircular.js.map +1 -1
- package/dist/components/RadioGroup.d.ts +24 -3
- package/dist/components/RadioGroup.d.ts.map +1 -1
- package/dist/components/RadioGroup.js +25 -3
- package/dist/components/RadioGroup.js.map +1 -1
- package/dist/components/Rating.d.ts +10 -0
- package/dist/components/Rating.d.ts.map +1 -1
- package/dist/components/Rating.js +10 -0
- package/dist/components/Rating.js.map +1 -1
- package/dist/components/Select/RichSelect.d.ts +3 -5
- package/dist/components/Select/RichSelect.d.ts.map +1 -1
- package/dist/components/Select/RichSelect.js +4 -4
- package/dist/components/Select/RichSelect.js.map +1 -1
- package/dist/components/Select/SimpleSelect.d.ts +2 -3
- package/dist/components/Select/SimpleSelect.d.ts.map +1 -1
- package/dist/components/Select/SimpleSelect.js +2 -3
- package/dist/components/Select/SimpleSelect.js.map +1 -1
- package/dist/components/Select/index.d.ts +25 -2
- package/dist/components/Select/index.d.ts.map +1 -1
- package/dist/components/Select/index.js +26 -3
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/Select/types.d.ts +1 -2
- package/dist/components/Select/types.d.ts.map +1 -1
- package/dist/components/SelectBox.d.ts +31 -2
- package/dist/components/SelectBox.d.ts.map +1 -1
- package/dist/components/SelectBox.js +32 -3
- package/dist/components/SelectBox.js.map +1 -1
- package/dist/components/Skeleton.d.ts +11 -0
- package/dist/components/Skeleton.d.ts.map +1 -1
- package/dist/components/Skeleton.js +11 -0
- package/dist/components/Skeleton.js.map +1 -1
- package/dist/components/Slider.d.ts +12 -0
- package/dist/components/Slider.d.ts.map +1 -1
- package/dist/components/Slider.js +12 -0
- package/dist/components/Slider.js.map +1 -1
- package/dist/components/SmartTable.d.ts +36 -2
- package/dist/components/SmartTable.d.ts.map +1 -1
- package/dist/components/SmartTable.js +37 -3
- package/dist/components/SmartTable.js.map +1 -1
- package/dist/components/Stepper.d.ts +20 -3
- package/dist/components/Stepper.d.ts.map +1 -1
- package/dist/components/Stepper.js +21 -3
- package/dist/components/Stepper.js.map +1 -1
- package/dist/components/Table.d.ts +10 -0
- package/dist/components/Table.d.ts.map +1 -1
- package/dist/components/Table.js +10 -0
- package/dist/components/Table.js.map +1 -1
- package/dist/components/Tabs/TabController.d.ts +14 -0
- package/dist/components/Tabs/TabController.d.ts.map +1 -1
- package/dist/components/Tabs/TabController.js +14 -0
- package/dist/components/Tabs/TabController.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +20 -3
- package/dist/components/Tabs/index.d.ts.map +1 -1
- package/dist/components/Tabs/index.js +21 -3
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Text.d.ts +16 -2
- package/dist/components/Text.d.ts.map +1 -1
- package/dist/components/Text.js +17 -3
- package/dist/components/Text.js.map +1 -1
- package/dist/components/Textarea.d.ts +11 -1
- package/dist/components/Textarea.d.ts.map +1 -1
- package/dist/components/Textarea.js +12 -2
- package/dist/components/Textarea.js.map +1 -1
- package/dist/components/Tooltip.d.ts +14 -1
- package/dist/components/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip.js +13 -0
- package/dist/components/Tooltip.js.map +1 -1
- package/dist/components/layout.d.ts +41 -7
- package/dist/components/layout.d.ts.map +1 -1
- package/dist/components/layout.js +44 -9
- package/dist/components/layout.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Accordion.tsx +34 -0
- package/src/components/Alert.tsx +8 -0
- package/src/components/AsyncContent.tsx +18 -4
- package/src/components/Avatar.tsx +11 -1
- package/src/components/AvatarGroup.tsx +8 -0
- package/src/components/Badge.tsx +24 -8
- package/src/components/Blockquote.tsx +8 -0
- package/src/components/Breadcrumb.tsx +10 -1
- package/src/components/Button.tsx +17 -2
- package/src/components/Card.tsx +34 -14
- package/src/components/Checkbox.tsx +14 -0
- package/src/components/CheckboxGroup.tsx +61 -40
- package/src/components/Circle.tsx +16 -0
- package/src/components/CitricComponent.ts +14 -0
- package/src/components/Divider.tsx +6 -5
- package/src/components/ErrorBoundary.tsx +13 -0
- package/src/components/ErrorMessage.tsx +1 -1
- package/src/components/FallbackBoundary.tsx +12 -1
- package/src/components/Favorite.tsx +12 -0
- package/src/components/FieldGroup.tsx +13 -0
- package/src/components/Form.tsx +18 -0
- package/src/components/FormGroup.tsx +12 -0
- package/src/components/IconBox.tsx +61 -30
- package/src/components/ImageBox.tsx +60 -30
- package/src/components/ImageWithFallback.tsx +18 -0
- package/src/components/Input.tsx +28 -14
- package/src/components/Link.tsx +6 -0
- package/src/components/MenuOverlay/index.tsx +20 -0
- package/src/components/Overlay/index.tsx +17 -0
- package/src/components/Pagination.tsx +40 -17
- package/src/components/ProgressBar.tsx +14 -0
- package/src/components/ProgressCircular.tsx +14 -0
- package/src/components/RadioGroup.tsx +62 -39
- package/src/components/Rating.tsx +10 -0
- package/src/components/Select/RichSelect.tsx +183 -182
- package/src/components/Select/SimpleSelect.tsx +57 -57
- package/src/components/Select/index.tsx +29 -5
- package/src/components/Select/types.ts +1 -1
- package/src/components/SelectBox.tsx +92 -62
- package/src/components/Skeleton.tsx +11 -0
- package/src/components/Slider.tsx +12 -0
- package/src/components/SmartTable.tsx +91 -56
- package/src/components/Stepper.tsx +76 -57
- package/src/components/Table.tsx +10 -0
- package/src/components/Tabs/TabController.ts +14 -0
- package/src/components/Tabs/index.tsx +56 -37
- package/src/components/Text.ts +36 -21
- package/src/components/Textarea.tsx +14 -4
- package/src/components/Tooltip.tsx +14 -1
- package/src/components/layout.tsx +56 -13
- package/src/index.ts +0 -1
- package/dist/components/Switch.d.ts +0 -10
- package/dist/components/Switch.d.ts.map +0 -1
- package/dist/components/Switch.js +0 -8
- package/dist/components/Switch.js.map +0 -1
- package/src/components/Switch.tsx +0 -30
|
@@ -26,6 +26,18 @@ export interface BaseFormGroupProps {
|
|
|
26
26
|
|
|
27
27
|
export type FormGroupProps = React.JSX.IntrinsicElements['div'] & BaseFormGroupProps
|
|
28
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
|
+
*/
|
|
29
41
|
export const FormGroup = withRef(({ error, help, label, warning, className, children, ...props }: FormGroupProps) => (
|
|
30
42
|
<CitricComponent tag="div" component="form-group" className={listToClass([className, error && 'error'])} {...props}>
|
|
31
43
|
<label>
|
|
@@ -59,41 +59,72 @@ export interface BaseIconBoxProps<T extends IconBoxTag, G extends IconGroup> ext
|
|
|
59
59
|
|
|
60
60
|
export type IconBoxProps<T extends IconBoxTag, G extends IconGroup> = Omit<HTMLTag[T], 'children'> & BaseIconBoxProps<T, G>
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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, analytics, onClick, feedback, ...props }: IconBoxProps<T, G>,
|
|
77
|
+
) {
|
|
78
|
+
props['aria-label'] ||= props.title // accessibility
|
|
79
|
+
const citric = useCitricController()
|
|
66
80
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
function handleClick(e: React.MouseEvent<any>) {
|
|
82
|
+
onClick?.(e)
|
|
83
|
+
if (tag === 'button') citric?.onClickButton?.(e, analytics ?? false)
|
|
84
|
+
else if (tag === 'a') citric?.onClickLink?.(e, analytics ?? false)
|
|
85
|
+
}
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
87
|
+
return <CitricComponent
|
|
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
|
+
/>
|
|
95
|
+
},
|
|
96
|
+
)
|
|
82
97
|
|
|
83
98
|
/**
|
|
84
|
-
*
|
|
99
|
+
* A shortcut for `<IconBox tag="button">`.
|
|
100
|
+
*
|
|
101
|
+
* Whenever a button is clicked, the function `onClickButton` of the nearest CitricController is called with the event and the value of the
|
|
102
|
+
* prop `analytics`.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```
|
|
106
|
+
* <IconButton icon="Search" />
|
|
107
|
+
* ```
|
|
85
108
|
*/
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
109
|
+
export const IconButton = withRef(
|
|
110
|
+
function IconButton<G extends IconGroup = 'outline'>({ type, ...props }: Omit<IconBoxProps<'button', G>, 'tag'>) {
|
|
111
|
+
return <IconBox {...props} tag="button" type={type || 'button' } />
|
|
112
|
+
},
|
|
113
|
+
)
|
|
89
114
|
|
|
90
115
|
/**
|
|
91
|
-
*
|
|
116
|
+
* A shortcut for `<IconBox tag="a">`.
|
|
117
|
+
*
|
|
118
|
+
* Whenever a link is clicked, the function `onClickLink` of the nearest CitricController is called with the event and the value of the
|
|
119
|
+
* prop `analytics`.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```
|
|
123
|
+
* <IconLink icon="Search" href="#" />
|
|
124
|
+
* ```
|
|
92
125
|
*/
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
export const IconButton = withRef(_IconButton)
|
|
99
|
-
export const IconLink = withRef(_IconLink)
|
|
126
|
+
export const IconLink = withRef(
|
|
127
|
+
function IconLink<G extends IconGroup = 'outline'>(props: Omit<IconBoxProps<'a', G>, 'tag'>) {
|
|
128
|
+
return <IconBox {...props} tag="a" />
|
|
129
|
+
},
|
|
130
|
+
)
|
|
@@ -49,41 +49,71 @@ export interface BaseImageBoxProps<T extends ImageBoxTag> extends WithColorPalet
|
|
|
49
49
|
|
|
50
50
|
export type ImageBoxProps<T extends ImageBoxTag> = HTMLTag[T] & BaseImageBoxProps<T>
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Renders a wrapper for its child (normally an image). The image will be resized and cropped to fit the container. The image is not cropped
|
|
54
|
+
* if the property "feedback" is set.
|
|
55
|
+
*
|
|
56
|
+
* Hover and focus effects are applied if the ImageBox is focusable.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```
|
|
60
|
+
* <ImageBox><img src="https://images.com/myimage.png" /></ImageBox>
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export const ImageBox = withRef(
|
|
64
|
+
function ImageBox<T extends ImageBoxTag = 'div'>(
|
|
65
|
+
{ tag, appearance, size, className, analytics, onClick, feedback, ...props }: ImageBoxProps<T>,
|
|
66
|
+
) {
|
|
67
|
+
props['aria-label'] ||= props.title // accessibility
|
|
68
|
+
const citric = useCitricController()
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
function handleClick(e: React.MouseEvent<any>) {
|
|
71
|
+
onClick?.(e)
|
|
72
|
+
if (tag === 'button') citric?.onClickButton?.(e, analytics ?? false)
|
|
73
|
+
else if (tag === 'a') citric?.onClickLink?.(e, analytics ?? false)
|
|
74
|
+
}
|
|
62
75
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
76
|
+
return <CitricComponent
|
|
77
|
+
tag={(tag || 'i') as any}
|
|
78
|
+
component="icon-box"
|
|
79
|
+
className={listToClass([appearance, size, className])}
|
|
80
|
+
data-feedback={feedback || undefined}
|
|
81
|
+
onClick={['button', 'a'].includes(tag ?? '') ? handleClick : onClick}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
},
|
|
85
|
+
)
|
|
72
86
|
|
|
73
87
|
/**
|
|
74
|
-
*
|
|
88
|
+
* A shortcut for `<ImageBox tag="button">`.
|
|
89
|
+
*
|
|
90
|
+
* Whenever a button is clicked, the function `onClickButton` of the nearest CitricController is called with the event and the value of the
|
|
91
|
+
* prop `analytics`.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```
|
|
95
|
+
* <ImageButton><img src="https://images.com/myimage.png" /></ImageButton>
|
|
96
|
+
* ```
|
|
75
97
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
98
|
+
export const ImageButton = withRef(
|
|
99
|
+
function ImageButton(props: Omit<ImageBoxProps<'button'>, 'tag'>) {
|
|
100
|
+
return <ImageBox {...props} tag="button" type={props.type || 'button'} />
|
|
101
|
+
},
|
|
102
|
+
)
|
|
79
103
|
|
|
80
104
|
/**
|
|
81
|
-
*
|
|
105
|
+
* A shortcut for `<ImageBox tag="a">`.
|
|
106
|
+
*
|
|
107
|
+
* Whenever a link is clicked, the function `onClickLink` of the nearest CitricController is called with the event and the value of the
|
|
108
|
+
* prop `analytics`.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```
|
|
112
|
+
* <ImageLink href="#"><img src="https://images.com/myimage.png" /></ImageButton>
|
|
113
|
+
* ```
|
|
82
114
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
export const ImageButton = withRef(_ImageButton)
|
|
89
|
-
export const ImageLink = withRef(_ImageLink)
|
|
115
|
+
export const ImageLink = withRef(
|
|
116
|
+
function ImageLink(props: Omit<ImageBoxProps<'a'>, 'tag'>) {
|
|
117
|
+
return <ImageBox {...props} tag="a" />
|
|
118
|
+
},
|
|
119
|
+
)
|
|
@@ -5,12 +5,30 @@ import { getStyleFromProps } from '../utils/css'
|
|
|
5
5
|
import { Skeleton } from './Skeleton'
|
|
6
6
|
|
|
7
7
|
export interface BaseImageWithFallbackProps extends Pick<WithStyleShortcuts, 'w' | 'h' | 'radius' | 'bg'> {
|
|
8
|
+
/**
|
|
9
|
+
* The react element to fallback to if the image can't be rendered.
|
|
10
|
+
*/
|
|
8
11
|
fallback: React.ReactNode,
|
|
12
|
+
/**
|
|
13
|
+
* Whether or not to show a skeleton when the image is still loading.
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
9
16
|
showLoading?: boolean,
|
|
10
17
|
}
|
|
11
18
|
|
|
12
19
|
export type ImageWithFallbackProps = JSX.IntrinsicElements['img'] & BaseImageWithFallbackProps
|
|
13
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Attempts to render an image. If it succeeds, the image is displayed, otherwise, a fallback is rendered.
|
|
23
|
+
*
|
|
24
|
+
* This is very useful if the value of "src" may be empty or if it may be broken. Instead of rendering nothing or the default browser error,
|
|
25
|
+
* it renders the fallback passed as parameter.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```
|
|
29
|
+
* <ImageWithFallback src={item.image} fallback={<Icon icon="Agent" />} />
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
14
32
|
export const ImageWithFallback = (
|
|
15
33
|
{ onLoad, onError, className, style: ogStyle, fallback, showLoading, w, h, radius, bg, ...props }: ImageWithFallbackProps,
|
|
16
34
|
) => {
|
package/src/components/Input.tsx
CHANGED
|
@@ -17,19 +17,33 @@ export interface BaseInputProps<T extends SupportedInputType> extends WithColorS
|
|
|
17
17
|
export type InputProps<T extends SupportedInputType = 'text'> =
|
|
18
18
|
ControlledInput & BaseInputProps<T> & { type?: T }
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Renders a input.
|
|
22
|
+
*
|
|
23
|
+
* Attention: "onChange" doesn't receive an event, instead, it receives the new value of the input: a string, unless "type" is "number",
|
|
24
|
+
* in this case, it receives a number.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
*
|
|
28
|
+
* ```
|
|
29
|
+
* const [value, setValue] = useState('')
|
|
30
|
+
*
|
|
31
|
+
* return <Input value={value} onChange={setValue} />
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const Input = withRef(
|
|
35
|
+
function Input<T extends SupportedInputType = 'text'>({ type, value, onChange, ...props }: InputProps<T>) {
|
|
36
|
+
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
37
|
+
if (!onChange) return
|
|
38
|
+
const newValue = e.target.value
|
|
39
|
+
if (type === 'number') {
|
|
40
|
+
const parsed = newValue ? parseFloat(newValue) : undefined
|
|
41
|
+
onChange(parsed as any)
|
|
42
|
+
} else {
|
|
43
|
+
onChange(newValue as any)
|
|
44
|
+
}
|
|
29
45
|
}
|
|
30
|
-
}
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const Input = withRef(_Input)
|
|
47
|
+
return <CitricComponent tag="input" component="input" type={type} value={value} onChange={handleChange} {...props} />
|
|
48
|
+
},
|
|
49
|
+
)
|
package/src/components/Link.tsx
CHANGED
|
@@ -23,6 +23,12 @@ export interface BaseLinkProps extends WithColor {
|
|
|
23
23
|
|
|
24
24
|
export type LinkProps = React.JSX.IntrinsicElements['a'] & BaseLinkProps
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Renders an html anchor by default, the actual component to render may be set on a CitricController, through the function `renderLink`.
|
|
28
|
+
*
|
|
29
|
+
* Whenever a link is clicked, the function `onClickLink` of the nearest CitricController is called with the event and the value of the
|
|
30
|
+
* prop `analytics`.
|
|
31
|
+
*/
|
|
26
32
|
export const Link = withRef(({ appearance, color, style, className, children, onClick, analytics, ...props }: LinkProps) => {
|
|
27
33
|
const citric = useCitricController()
|
|
28
34
|
const linkProps = {
|
|
@@ -5,6 +5,26 @@ import { Overlay } from '../Overlay'
|
|
|
5
5
|
import { Menu } from './Menu'
|
|
6
6
|
import { MenuOverlayProps } from './types'
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Creates a menu overlay for its child element. Whenever the child element is clicked, the menu appears. Closing the menu is also handled
|
|
10
|
+
* by this component.
|
|
11
|
+
*
|
|
12
|
+
* The menu is defined by the property "items" and can contain sections and sub menus.
|
|
13
|
+
*
|
|
14
|
+
* If no child is provided, a button with the vertical ellipsis icon is rendered.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
*
|
|
18
|
+
* ```
|
|
19
|
+
* const items: MenuItem[] = useMemo([
|
|
20
|
+
* { label: 'View', href: `/resource/${id}` },
|
|
21
|
+
* { label: 'Edit', onClick: () => editResource(id) },
|
|
22
|
+
* { label: 'Remove', onClick: () => removeResource(id), style: { color: theme.color.danger[500] } },
|
|
23
|
+
* ], [id])
|
|
24
|
+
*
|
|
25
|
+
* return <MenuOverlay items={items}><IconButton icon="Plus" /></MenuOverlay>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
8
28
|
export const MenuOverlay = ({
|
|
9
29
|
id, items, appearance, bgLevel, header, roundedItems, showBorders, showShadows, spaced, menuClass, menuStyle, children, ...props
|
|
10
30
|
}: MenuOverlayProps) => {
|
|
@@ -21,6 +21,23 @@ const arbitraryRenderTime = 20
|
|
|
21
21
|
* hidden by the scroll.
|
|
22
22
|
* TODO: use React Portal to implement overlays. The current implementation will lose every React context in the tree.
|
|
23
23
|
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Creates an overlay for the child component. The overlay can be any React element. The overlay can be triggered by "click" or "hover"
|
|
27
|
+
* (default).
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
*
|
|
31
|
+
* ```
|
|
32
|
+
* const overlay = <Card>Hey, this is my overlay!</Card>
|
|
33
|
+
*
|
|
34
|
+
* return (
|
|
35
|
+
* <Overlay content={overlay} attributes={{ style: { margin: '20px' } }}>
|
|
36
|
+
* <Button>Hover to see the overlay</Button>
|
|
37
|
+
* </Overlay>
|
|
38
|
+
* )
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
24
41
|
export function Overlay<T extends keyof HTMLTag>({
|
|
25
42
|
tag,
|
|
26
43
|
children,
|
|
@@ -4,6 +4,17 @@ import { withRef } from '../utils/react'
|
|
|
4
4
|
import { CitricComponent } from './CitricComponent'
|
|
5
5
|
import { IconButton } from './IconBox'
|
|
6
6
|
|
|
7
|
+
export interface PaginationValue {
|
|
8
|
+
/**
|
|
9
|
+
* The first page is 1. If "0" is provided, it will be treated as if it was "1".
|
|
10
|
+
*/
|
|
11
|
+
page: number,
|
|
12
|
+
/**
|
|
13
|
+
* The current number of items in a page.
|
|
14
|
+
*/
|
|
15
|
+
size: number,
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
export interface BasePaginationProps {
|
|
8
19
|
/**
|
|
9
20
|
* The options for the page size.
|
|
@@ -16,60 +27,72 @@ export interface BasePaginationProps {
|
|
|
16
27
|
*/
|
|
17
28
|
totalPages: number,
|
|
18
29
|
/**
|
|
19
|
-
* The
|
|
30
|
+
* The current page and page size.
|
|
20
31
|
*/
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The current number of items in a page.
|
|
24
|
-
*/
|
|
25
|
-
pageSize: number,
|
|
32
|
+
value: PaginationValue,
|
|
26
33
|
/**
|
|
27
34
|
* Function to run whenever the page size or current page changes.
|
|
28
35
|
*/
|
|
29
|
-
onChange: (
|
|
36
|
+
onChange: (value: PaginationValue) => void,
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
export type PaginationProps = Omit<React.JSX.IntrinsicElements['div'], 'onChange'> & BasePaginationProps
|
|
33
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Renders a pagination UI, letting the user chose one among multiple pages. This is generally rendered at the bottom of a table.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```
|
|
46
|
+
* const [pageData, setPageData] = useState({ page: 1, size: 10 })
|
|
47
|
+
* return <Pagination
|
|
48
|
+
* value={pageData}
|
|
49
|
+
* totalPages={50}
|
|
50
|
+
* onChange={setPageData}
|
|
51
|
+
* />
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
34
54
|
export const Pagination = withRef((
|
|
35
|
-
{ pageSizeOptions = [10, 20, 30],
|
|
55
|
+
{ pageSizeOptions = [10, 20, 30], totalPages, value, onChange, ...props }: PaginationProps,
|
|
36
56
|
) => {
|
|
37
57
|
const t = useTranslate(dictionary)
|
|
38
|
-
const sizeOptions = useMemo(
|
|
58
|
+
const sizeOptions = useMemo(
|
|
59
|
+
() => pageSizeOptions.map(o => <option key={o} selected={value.size === o}>{o}</option>),
|
|
60
|
+
[pageSizeOptions],
|
|
61
|
+
)
|
|
39
62
|
const pageOptions = useMemo(() => {
|
|
40
63
|
const options: React.ReactElement[] = []
|
|
41
64
|
for (let i = 1; i <= totalPages; i++) {
|
|
42
|
-
options.push(<option key={i} value={i} selected={page === i}>{i}</option>)
|
|
65
|
+
options.push(<option key={i} value={i} selected={value.page === i}>{i}</option>)
|
|
43
66
|
}
|
|
44
67
|
return options
|
|
45
|
-
}, [page, totalPages])
|
|
68
|
+
}, [value.page, totalPages])
|
|
46
69
|
|
|
47
70
|
return (
|
|
48
71
|
<CitricComponent tag="div" component="pagination" {...props}>
|
|
49
72
|
<div className="page-size">
|
|
50
73
|
<label>
|
|
51
74
|
{t.itemsPerPage}:
|
|
52
|
-
<select name="itemsPerPage" onChange={e => onChange(page, parseInt(e.target.value))}>{sizeOptions}</select>
|
|
75
|
+
<select name="itemsPerPage" onChange={e => onChange({ page: value.page, size: parseInt(e.target.value) })}>{sizeOptions}</select>
|
|
53
76
|
</label>
|
|
54
77
|
</div>
|
|
55
78
|
<div className="page-number">
|
|
56
79
|
<label>
|
|
57
|
-
<select name="page" onChange={e => onChange(parseInt(e.target.value),
|
|
80
|
+
<select name="page" onChange={e => onChange({ page: parseInt(e.target.value), size: value.size })}>{pageOptions}</select>
|
|
58
81
|
</label>
|
|
59
82
|
{totalPages > 1 ? interpolate(t.ofTotalPlural, totalPages) : t.ofTotalSingular}
|
|
60
83
|
<IconButton
|
|
61
84
|
icon="ChevronLeft"
|
|
62
85
|
aria-label="previous"
|
|
63
86
|
title="previous"
|
|
64
|
-
disabled={page === 1}
|
|
65
|
-
onClick={() => onChange(page - 1,
|
|
87
|
+
disabled={value.page === 1}
|
|
88
|
+
onClick={() => onChange({ page: value.page - 1, size: value.size })}
|
|
66
89
|
/>
|
|
67
90
|
<IconButton
|
|
68
91
|
icon="ChevronRight"
|
|
69
92
|
aria-label="next"
|
|
70
93
|
title="next"
|
|
71
|
-
disabled={page === totalPages}
|
|
72
|
-
onClick={() => onChange(page + 1,
|
|
94
|
+
disabled={value.page === totalPages}
|
|
95
|
+
onClick={() => onChange({ page: value.page + 1, size: value.size })}
|
|
73
96
|
/>
|
|
74
97
|
</div>
|
|
75
98
|
</CitricComponent>
|
|
@@ -20,6 +20,20 @@ export interface BaseProgressBarProps extends WithColorScheme, WithColorPalette
|
|
|
20
20
|
|
|
21
21
|
export type ProgressBarProps = React.JSX.IntrinsicElements['div'] & BaseProgressBarProps
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Shows a progress bar. This can indicate a loading state or the progress of a task. When "progress" is not set, the bar is animated,
|
|
25
|
+
* indicating a busy state.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* A simple loading with a Progress Bar.
|
|
29
|
+
* ```
|
|
30
|
+
* <ProgressBar />
|
|
31
|
+
* ```
|
|
32
|
+
* A Progress Bar that is 50% complete.
|
|
33
|
+
* ```
|
|
34
|
+
* <ProgressBar progress={50} />
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
23
37
|
export const ProgressBar = withRef(({ progress, speed, style, className, ...props }: ProgressBarProps) =>
|
|
24
38
|
<CitricComponent
|
|
25
39
|
tag="div"
|
|
@@ -20,6 +20,20 @@ export interface BaseProgressCircularProps extends WithColorScheme, WithColorPal
|
|
|
20
20
|
|
|
21
21
|
export type ProgressCircularProps = React.JSX.IntrinsicElements['div'] & BaseProgressCircularProps
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Shows a circular progress. This can indicate a loading state (spinner) or the progress of a task. When "progress" is not set, the
|
|
25
|
+
* spinner is animated, indicating a busy state.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* A simple loading with a Progress Circular.
|
|
29
|
+
* ```
|
|
30
|
+
* <ProgressCircular />
|
|
31
|
+
* ```
|
|
32
|
+
* A Progress Circular that is 50% complete.
|
|
33
|
+
* ```
|
|
34
|
+
* <ProgressCircular progress={50} />
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
23
37
|
export const ProgressCircular = withRef(({ progress, size, style, className, ...props }: ProgressCircularProps) =>
|
|
24
38
|
<CitricComponent
|
|
25
39
|
tag="div"
|
|
@@ -67,42 +67,65 @@ export interface BaseRadioGroupProps<T> extends WithColorScheme {
|
|
|
67
67
|
|
|
68
68
|
export type RadioGroupProps<T> = Omit<React.JSX.IntrinsicElements['div'], 'onChange' | 'children'> & BaseRadioGroupProps<T>
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Renders a list of radio button for single-selection. One radio button is rendered for each option.
|
|
72
|
+
*
|
|
73
|
+
* Attention: single radio buttons don't make sense, this is why they're not provided by this library.
|
|
74
|
+
*
|
|
75
|
+
* This component can be heavily customized via its properties. Check the storybook for complex examples.
|
|
76
|
+
*
|
|
77
|
+
* Tip: if you need to implement features like "search", use the hook `useRadioGroupControls`.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
*
|
|
81
|
+
* ```
|
|
82
|
+
* const options = useMemo(() => [
|
|
83
|
+
* { id: 1, name: 'Option 1' },
|
|
84
|
+
* { id: 2, name: 'Option 2' },
|
|
85
|
+
* { id: 3, name: 'Option 3' },
|
|
86
|
+
* ], [])
|
|
87
|
+
*
|
|
88
|
+
* const [value, setValue] = useState<(typeof options)[number] | undefined>()
|
|
89
|
+
*
|
|
90
|
+
* return <RadioGroup options={options} renderLabel={o => o.name} renderKey={o => o.id} value={value} setValue={setValue} />
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export const RadioGroup = withRef(
|
|
94
|
+
function RadioGroup<T>({
|
|
95
|
+
name,
|
|
96
|
+
value,
|
|
97
|
+
options,
|
|
98
|
+
onChange,
|
|
99
|
+
renderLabel = defaultRenderLabel,
|
|
100
|
+
renderKey = defaultRenderKey,
|
|
101
|
+
renderItem,
|
|
102
|
+
isDisabled,
|
|
103
|
+
colorScheme,
|
|
104
|
+
style,
|
|
105
|
+
...props
|
|
106
|
+
}: RadioGroupProps<T>) {
|
|
107
|
+
const items = useMemo(() => {
|
|
108
|
+
const valueKey = value ? renderKey(value) : undefined
|
|
109
|
+
return options.map((o) => {
|
|
110
|
+
const key = renderKey(o)
|
|
111
|
+
const radio = <CitricComponent
|
|
112
|
+
tag="input"
|
|
113
|
+
component="radio"
|
|
114
|
+
type="radio"
|
|
115
|
+
name={name}
|
|
116
|
+
value={key}
|
|
117
|
+
checked={value === o || (!isNil(key) && valueKey === key)}
|
|
118
|
+
onChange={() => onChange?.(o)}
|
|
119
|
+
disabled={isDisabled?.(o)}
|
|
120
|
+
/>
|
|
121
|
+
return renderItem ? renderItem(radio, o) : (
|
|
122
|
+
<CitricComponent tag="label" component="radio-row" key={key} colorScheme={colorScheme}>
|
|
123
|
+
{radio}
|
|
124
|
+
{renderLabel(o)}
|
|
125
|
+
</CitricComponent>
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
|
+
}, [options, value, name, colorScheme])
|
|
129
|
+
return <Column {...props} style={{ gap: '8px', ...style }}>{items}</Column>
|
|
130
|
+
},
|
|
131
|
+
)
|
|
@@ -14,6 +14,16 @@ export interface BaseRatingProps {
|
|
|
14
14
|
|
|
15
15
|
export type RatingProps = Omit<React.JSX.IntrinsicElements['div'], 'onChange' | 'children'> & BaseRatingProps
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Renders a 5 star rating UI. The user can select 1 to 5 stars.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```
|
|
22
|
+
* const [value, setValue] = useState<RatingValue | undefined>()
|
|
23
|
+
* return <Rating value={value} setValue={setValue} />
|
|
24
|
+
* ```
|
|
25
|
+
* In the example above, `RatingValue` is any integer from 1 to 5.
|
|
26
|
+
*/
|
|
17
27
|
export const Rating = withRef(({ value, onChange, name, ...props }: RatingProps) => (
|
|
18
28
|
<CitricComponent tag="div" component="rating" {...props}>
|
|
19
29
|
<input type="radio" value="1" name={name} checked={value === 5} onChange={() => onChange(5)} />
|