react-science 0.25.0 → 0.26.2
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/lib/app/explorer/MeasurementExplorer.js +29 -7
- package/lib/app/explorer/MeasurementExplorerWithState.js +2 -2
- package/lib/app/helpers/MeasurementPlot.js +28 -19
- package/lib/app/helpers/react-plot.js +1 -1
- package/lib/app/kinds/mass/MassPlotView.js +2 -2
- package/lib/app/kinds/mass/MeasurementMassPlot.js +49 -33
- package/lib/app/panels/measurement-info/MeasurementInfoPanel.js +13 -58
- package/lib/app-data/state/data/data.helpers.js +32 -8
- package/lib/components/forms/Checkbox.js +4 -5
- package/lib/components/forms/Input.js +3 -87
- package/lib/components/forms/TextArea.js +25 -0
- package/lib/components/forms/index.js +2 -0
- package/lib/components/forms/radio-group/ButtonRadioItem.js +76 -0
- package/lib/components/forms/radio-group/ClassicRadioItem.js +92 -0
- package/lib/components/forms/radio-group/RadioGroup.js +69 -0
- package/lib/components/forms/radio-group/index.js +17 -0
- package/lib/components/forms/styles.js +80 -0
- package/lib/components/forms/utils/SubText.js +20 -0
- package/lib/components/forms/utils/index.js +17 -0
- package/lib/components/header/PanelHeader.js +51 -0
- package/lib/components/header/index.js +1 -0
- package/lib/components/index.js +1 -0
- package/lib/components/info-panel/InfoPanel.js +94 -0
- package/lib/components/info-panel/index.js +17 -0
- package/lib/components/modal/ConfirmModal.js +3 -2
- package/lib/components/modal/Modal.js +3 -1
- package/lib/components/table/Table.js +2 -2
- package/lib/components/toolbar/PanelPreferencesToolbar.js +26 -0
- package/lib/components/toolbar/index.js +1 -0
- package/lib-esm/app/explorer/MeasurementExplorer.d.ts.map +1 -1
- package/lib-esm/app/explorer/MeasurementExplorer.js +30 -8
- package/lib-esm/app/explorer/MeasurementExplorer.js.map +1 -1
- package/lib-esm/app/explorer/MeasurementExplorerWithState.d.ts.map +1 -1
- package/lib-esm/app/explorer/MeasurementExplorerWithState.js +2 -2
- package/lib-esm/app/explorer/MeasurementExplorerWithState.js.map +1 -1
- package/lib-esm/app/helpers/MeasurementPlot.d.ts +3 -3
- package/lib-esm/app/helpers/MeasurementPlot.d.ts.map +1 -1
- package/lib-esm/app/helpers/MeasurementPlot.js +28 -19
- package/lib-esm/app/helpers/MeasurementPlot.js.map +1 -1
- package/lib-esm/app/helpers/react-plot.d.ts.map +1 -1
- package/lib-esm/app/helpers/react-plot.js +1 -1
- package/lib-esm/app/helpers/react-plot.js.map +1 -1
- package/lib-esm/app/kinds/mass/MassPlotView.d.ts.map +1 -1
- package/lib-esm/app/kinds/mass/MassPlotView.js +2 -2
- package/lib-esm/app/kinds/mass/MassPlotView.js.map +1 -1
- package/lib-esm/app/kinds/mass/MeasurementMassPlot.d.ts.map +1 -1
- package/lib-esm/app/kinds/mass/MeasurementMassPlot.js +49 -33
- package/lib-esm/app/kinds/mass/MeasurementMassPlot.js.map +1 -1
- package/lib-esm/app/panels/measurement-info/MeasurementInfoPanel.d.ts.map +1 -1
- package/lib-esm/app/panels/measurement-info/MeasurementInfoPanel.js +15 -60
- package/lib-esm/app/panels/measurement-info/MeasurementInfoPanel.js.map +1 -1
- package/lib-esm/app-data/state/data/data.helpers.d.ts +20 -12
- package/lib-esm/app-data/state/data/data.helpers.d.ts.map +1 -1
- package/lib-esm/app-data/state/data/data.helpers.js +30 -7
- package/lib-esm/app-data/state/data/data.helpers.js.map +1 -1
- package/lib-esm/components/forms/Checkbox.d.ts.map +1 -1
- package/lib-esm/components/forms/Checkbox.js +1 -2
- package/lib-esm/components/forms/Checkbox.js.map +1 -1
- package/lib-esm/components/forms/Input.d.ts +4 -2
- package/lib-esm/components/forms/Input.d.ts.map +1 -1
- package/lib-esm/components/forms/Input.js +3 -87
- package/lib-esm/components/forms/Input.js.map +1 -1
- package/lib-esm/components/forms/TextArea.d.ts +8 -0
- package/lib-esm/components/forms/TextArea.d.ts.map +1 -0
- package/lib-esm/components/forms/TextArea.js +19 -0
- package/lib-esm/components/forms/TextArea.js.map +1 -0
- package/lib-esm/components/forms/index.d.ts +2 -0
- package/lib-esm/components/forms/index.d.ts.map +1 -1
- package/lib-esm/components/forms/index.js +2 -0
- package/lib-esm/components/forms/index.js.map +1 -1
- package/lib-esm/components/forms/radio-group/ButtonRadioItem.d.ts +3 -0
- package/lib-esm/components/forms/radio-group/ButtonRadioItem.d.ts.map +1 -0
- package/lib-esm/components/forms/radio-group/ButtonRadioItem.js +50 -0
- package/lib-esm/components/forms/radio-group/ButtonRadioItem.js.map +1 -0
- package/lib-esm/components/forms/radio-group/ClassicRadioItem.d.ts +3 -0
- package/lib-esm/components/forms/radio-group/ClassicRadioItem.d.ts.map +1 -0
- package/lib-esm/components/forms/radio-group/ClassicRadioItem.js +66 -0
- package/lib-esm/components/forms/radio-group/ClassicRadioItem.js.map +1 -0
- package/lib-esm/components/forms/radio-group/RadioGroup.d.ts +18 -0
- package/lib-esm/components/forms/radio-group/RadioGroup.d.ts.map +1 -0
- package/lib-esm/components/forms/radio-group/RadioGroup.js +43 -0
- package/lib-esm/components/forms/radio-group/RadioGroup.js.map +1 -0
- package/lib-esm/components/forms/radio-group/index.d.ts +2 -0
- package/lib-esm/components/forms/radio-group/index.d.ts.map +1 -0
- package/lib-esm/components/forms/radio-group/index.js +2 -0
- package/lib-esm/components/forms/radio-group/index.js.map +1 -0
- package/lib-esm/components/forms/styles.d.ts +26 -0
- package/lib-esm/components/forms/styles.d.ts.map +1 -0
- package/lib-esm/components/forms/styles.js +75 -0
- package/lib-esm/components/forms/styles.js.map +1 -0
- package/lib-esm/components/forms/utils/SubText.d.ts +7 -0
- package/lib-esm/components/forms/utils/SubText.d.ts.map +1 -0
- package/lib-esm/components/forms/utils/SubText.js +17 -0
- package/lib-esm/components/forms/utils/SubText.js.map +1 -0
- package/lib-esm/components/forms/utils/index.d.ts +2 -0
- package/lib-esm/components/forms/utils/index.d.ts.map +1 -0
- package/lib-esm/components/forms/utils/index.js +2 -0
- package/lib-esm/components/forms/utils/index.js.map +1 -0
- package/lib-esm/components/header/PanelHeader.d.ts +10 -0
- package/lib-esm/components/header/PanelHeader.d.ts.map +1 -0
- package/lib-esm/components/header/PanelHeader.js +48 -0
- package/lib-esm/components/header/PanelHeader.js.map +1 -0
- package/lib-esm/components/header/index.d.ts +1 -0
- package/lib-esm/components/header/index.d.ts.map +1 -1
- package/lib-esm/components/header/index.js +1 -0
- package/lib-esm/components/header/index.js.map +1 -1
- package/lib-esm/components/index.d.ts +1 -0
- package/lib-esm/components/index.d.ts.map +1 -1
- package/lib-esm/components/index.js +1 -0
- package/lib-esm/components/index.js.map +1 -1
- package/lib-esm/components/info-panel/InfoPanel.d.ts +15 -0
- package/lib-esm/components/info-panel/InfoPanel.d.ts.map +1 -0
- package/lib-esm/components/info-panel/InfoPanel.js +91 -0
- package/lib-esm/components/info-panel/InfoPanel.js.map +1 -0
- package/lib-esm/components/info-panel/index.d.ts +2 -0
- package/lib-esm/components/info-panel/index.d.ts.map +1 -0
- package/lib-esm/components/info-panel/index.js +2 -0
- package/lib-esm/components/info-panel/index.js.map +1 -0
- package/lib-esm/components/modal/ConfirmModal.d.ts.map +1 -1
- package/lib-esm/components/modal/ConfirmModal.js +3 -2
- package/lib-esm/components/modal/ConfirmModal.js.map +1 -1
- package/lib-esm/components/modal/Modal.d.ts.map +1 -1
- package/lib-esm/components/modal/Modal.js +3 -1
- package/lib-esm/components/modal/Modal.js.map +1 -1
- package/lib-esm/components/table/Table.d.ts +2 -3
- package/lib-esm/components/table/Table.d.ts.map +1 -1
- package/lib-esm/components/table/Table.js +2 -2
- package/lib-esm/components/table/Table.js.map +1 -1
- package/lib-esm/components/toolbar/PanelPreferencesToolbar.d.ts +7 -0
- package/lib-esm/components/toolbar/PanelPreferencesToolbar.d.ts.map +1 -0
- package/lib-esm/components/toolbar/PanelPreferencesToolbar.js +23 -0
- package/lib-esm/components/toolbar/PanelPreferencesToolbar.js.map +1 -0
- package/lib-esm/components/toolbar/index.d.ts +1 -0
- package/lib-esm/components/toolbar/index.d.ts.map +1 -1
- package/lib-esm/components/toolbar/index.js +1 -0
- package/lib-esm/components/toolbar/index.js.map +1 -1
- package/package.json +16 -14
- package/src/app/explorer/MeasurementExplorer.tsx +34 -12
- package/src/app/explorer/MeasurementExplorerWithState.tsx +2 -2
- package/src/app/helpers/MeasurementPlot.tsx +44 -33
- package/src/app/helpers/react-plot.tsx +6 -4
- package/src/app/kinds/mass/MassPlotView.tsx +2 -2
- package/src/app/kinds/mass/MeasurementMassPlot.tsx +57 -37
- package/src/app/panels/measurement-info/MeasurementInfoPanel.tsx +14 -84
- package/src/app-data/state/data/data.helpers.ts +49 -16
- package/src/components/forms/Checkbox.tsx +2 -3
- package/src/components/forms/Input.tsx +14 -125
- package/src/components/forms/TextArea.tsx +45 -0
- package/src/components/forms/index.ts +2 -0
- package/src/components/forms/radio-group/ButtonRadioItem.tsx +77 -0
- package/src/components/forms/radio-group/ClassicRadioItem.tsx +95 -0
- package/src/components/forms/radio-group/RadioGroup.tsx +83 -0
- package/src/components/forms/radio-group/index.ts +1 -0
- package/src/components/forms/styles.ts +96 -0
- package/src/components/forms/utils/SubText.tsx +31 -0
- package/src/components/forms/utils/index.ts +1 -0
- package/src/components/header/PanelHeader.tsx +75 -0
- package/src/components/header/index.ts +1 -0
- package/src/components/index.ts +1 -0
- package/src/components/info-panel/InfoPanel.tsx +150 -0
- package/src/components/info-panel/index.ts +1 -0
- package/src/components/modal/ConfirmModal.tsx +3 -2
- package/src/components/modal/Modal.tsx +3 -1
- package/src/components/table/Table.tsx +3 -5
- package/src/components/toolbar/PanelPreferencesToolbar.tsx +46 -0
- package/src/components/toolbar/index.ts +1 -0
|
@@ -1,96 +1,16 @@
|
|
|
1
1
|
import styled from '@emotion/styled';
|
|
2
|
-
import {
|
|
2
|
+
import { InputHTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
import { FullSpinner } from '../index';
|
|
5
5
|
|
|
6
6
|
import { useFieldsContext } from './context/FieldsContext';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const LabelStyled = styled.label<StyledProps>`
|
|
17
|
-
padding: ${(props) =>
|
|
18
|
-
props.variant === 'default'
|
|
19
|
-
? props.hasTrailing
|
|
20
|
-
? '2px 9px 4px 9px'
|
|
21
|
-
: '2px 9px'
|
|
22
|
-
: props.hasTrailing
|
|
23
|
-
? '1px 7px 1px 7px'
|
|
24
|
-
: '1px 7px'};
|
|
25
|
-
|
|
26
|
-
font-size: ${(props) => (props.variant === 'small' ? '1em' : '1.125em')};
|
|
27
|
-
line-height: '17px';
|
|
28
|
-
|
|
29
|
-
background-color: white;
|
|
30
|
-
border-width: 1px;
|
|
31
|
-
align-items: center;
|
|
32
|
-
flex-direction: row;
|
|
33
|
-
flex: 1 1 0%;
|
|
34
|
-
display: flex;
|
|
35
|
-
position: relative;
|
|
36
|
-
|
|
37
|
-
border-top-right-radius: ${(props) =>
|
|
38
|
-
props.hasLeading && !props.hasTrailing && '0.375rem'};
|
|
39
|
-
|
|
40
|
-
border-bottom-right-radius: ${(props) =>
|
|
41
|
-
props.hasLeading && !props.hasTrailing && '0.375rem'};
|
|
42
|
-
|
|
43
|
-
border-top-left-radius: ${(props) =>
|
|
44
|
-
props.hasTrailing && !props.hasLeading && '0.375rem'};
|
|
45
|
-
|
|
46
|
-
border-bottom-left-radius: ${(props) =>
|
|
47
|
-
props.hasTrailing && !props.hasLeading && '0.375rem'};
|
|
48
|
-
|
|
49
|
-
border-radius: ${(props) =>
|
|
50
|
-
!props.hasLeading && !props.hasTrailing && '0.375rem'};
|
|
51
|
-
|
|
52
|
-
border-color: var(--custom-border-color);
|
|
53
|
-
`;
|
|
54
|
-
|
|
55
|
-
function getStyleColor(hasError: boolean, hasValid: boolean) {
|
|
56
|
-
if (hasError) {
|
|
57
|
-
return {
|
|
58
|
-
default: '#ffa39e',
|
|
59
|
-
hover: '#f95d55',
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (hasValid) {
|
|
64
|
-
return {
|
|
65
|
-
default: '#6adc24',
|
|
66
|
-
hover: '#62cb21',
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
default: 'rgb(217, 217, 217)',
|
|
72
|
-
hover: '#4096ff',
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const GroupStyled = styled.div<{ hasError: boolean; hasValid: boolean }>`
|
|
77
|
-
display: flex;
|
|
78
|
-
border-radius: 0.375rem;
|
|
79
|
-
margin-top: 0.25rem;
|
|
80
|
-
|
|
81
|
-
.addon {
|
|
82
|
-
color: ${({ hasError }) => hasError && '#f95d55'};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
--custom-border-color: ${({ hasError, hasValid }) =>
|
|
86
|
-
getStyleColor(hasError, hasValid).default};
|
|
87
|
-
|
|
88
|
-
:hover,
|
|
89
|
-
:focus-within {
|
|
90
|
-
--custom-border-color: ${({ hasError, hasValid }) =>
|
|
91
|
-
getStyleColor(hasError, hasValid).hover};
|
|
92
|
-
}
|
|
93
|
-
`;
|
|
7
|
+
import {
|
|
8
|
+
InputContainer,
|
|
9
|
+
GroupStyled,
|
|
10
|
+
LabelStyled,
|
|
11
|
+
InputVariant,
|
|
12
|
+
} from './styles';
|
|
13
|
+
import { SubText, SubTextProps } from './utils';
|
|
94
14
|
|
|
95
15
|
const InputStyled = styled.input`
|
|
96
16
|
padding: 0;
|
|
@@ -142,27 +62,20 @@ const TrailingInlineAddonStyled = styled.div`
|
|
|
142
62
|
padding-left: 0.5rem;
|
|
143
63
|
`;
|
|
144
64
|
|
|
145
|
-
const RootInput = styled.div`
|
|
146
|
-
display: flex;
|
|
147
|
-
flex-direction: column;
|
|
148
|
-
gap: 2px;
|
|
149
|
-
`;
|
|
150
|
-
|
|
151
65
|
interface RenderAddon {
|
|
152
66
|
addon: ReactNode;
|
|
153
67
|
inline?: boolean;
|
|
154
68
|
}
|
|
155
69
|
|
|
156
|
-
export interface InputProps
|
|
157
|
-
|
|
158
|
-
|
|
70
|
+
export interface InputProps
|
|
71
|
+
extends InputHTMLAttributes<HTMLInputElement>,
|
|
72
|
+
SubTextProps {
|
|
73
|
+
variant?: InputVariant;
|
|
159
74
|
leadingAddon?: RenderAddon;
|
|
160
75
|
trailingAddon?: RenderAddon;
|
|
161
|
-
|
|
162
76
|
help?: string;
|
|
163
77
|
error?: string;
|
|
164
78
|
valid?: true | string;
|
|
165
|
-
|
|
166
79
|
loading?: boolean;
|
|
167
80
|
}
|
|
168
81
|
|
|
@@ -185,7 +98,7 @@ export function Input(props: InputProps) {
|
|
|
185
98
|
const variant = variantProps || contextVariant;
|
|
186
99
|
|
|
187
100
|
return (
|
|
188
|
-
<
|
|
101
|
+
<InputContainer>
|
|
189
102
|
<GroupStyled hasError={!!error} hasValid={!!valid}>
|
|
190
103
|
{leadingAddon && !leadingAddon.inline && (
|
|
191
104
|
<LeadingAddonStyled>{leadingAddon.addon}</LeadingAddonStyled>
|
|
@@ -226,30 +139,6 @@ export function Input(props: InputProps) {
|
|
|
226
139
|
</GroupStyled>
|
|
227
140
|
|
|
228
141
|
<SubText error={error} help={help} valid={valid} />
|
|
229
|
-
</
|
|
142
|
+
</InputContainer>
|
|
230
143
|
);
|
|
231
144
|
}
|
|
232
|
-
|
|
233
|
-
function SubText(props: Pick<InputProps, 'help' | 'error' | 'valid'>) {
|
|
234
|
-
const { error, help, valid: validProps } = props;
|
|
235
|
-
|
|
236
|
-
const valid = typeof validProps === 'string' ? validProps : undefined;
|
|
237
|
-
const text = error || valid || help;
|
|
238
|
-
|
|
239
|
-
return <p style={{ color: getColor(error, validProps) }}>{text}</p>;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function getColor(
|
|
243
|
-
error?: string,
|
|
244
|
-
valid?: true | string,
|
|
245
|
-
): CSSProperties['color'] {
|
|
246
|
-
if (error) {
|
|
247
|
-
return '#f95d55';
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (valid && typeof valid !== 'boolean') {
|
|
251
|
-
return '#62cb21';
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return 'gray';
|
|
255
|
-
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import { TextareaHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useFieldsContext } from './context/FieldsContext';
|
|
5
|
+
import {
|
|
6
|
+
InputContainer,
|
|
7
|
+
GroupStyled,
|
|
8
|
+
LabelStyled,
|
|
9
|
+
InputVariant,
|
|
10
|
+
} from './styles';
|
|
11
|
+
import { SubText, SubTextProps } from './utils';
|
|
12
|
+
|
|
13
|
+
const TextAreaStyled = styled.textarea`
|
|
14
|
+
padding: 0;
|
|
15
|
+
flex: 1 1 0%;
|
|
16
|
+
border: none;
|
|
17
|
+
position: relative;
|
|
18
|
+
outline: none;
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
export interface TextAreaProps
|
|
22
|
+
extends TextareaHTMLAttributes<HTMLTextAreaElement>,
|
|
23
|
+
SubTextProps {
|
|
24
|
+
variant?: InputVariant;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function TextArea(props: TextAreaProps) {
|
|
28
|
+
const { variant: variantProps, help, error, valid, ...otherProps } = props;
|
|
29
|
+
|
|
30
|
+
const { name, variant: contextVariant } = useFieldsContext();
|
|
31
|
+
|
|
32
|
+
const variant = variantProps || contextVariant;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<InputContainer>
|
|
36
|
+
<GroupStyled hasError={!!error} hasValid={!!valid}>
|
|
37
|
+
<LabelStyled variant={variant}>
|
|
38
|
+
<TextAreaStyled id={name} name={name} {...otherProps} />
|
|
39
|
+
</LabelStyled>
|
|
40
|
+
</GroupStyled>
|
|
41
|
+
|
|
42
|
+
<SubText error={error} help={help} valid={valid} />
|
|
43
|
+
</InputContainer>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** @jsxImportSource @emotion/react */
|
|
2
|
+
import { css } from '@emotion/react';
|
|
3
|
+
import * as RadioGroup from '@radix-ui/react-radio-group';
|
|
4
|
+
|
|
5
|
+
import { enabledColor, InputVariant } from '../styles';
|
|
6
|
+
|
|
7
|
+
import { RadioOption, RadioGroupProps } from './RadioGroup';
|
|
8
|
+
|
|
9
|
+
const buttonStyles = {
|
|
10
|
+
container: css({
|
|
11
|
+
border: '1px solid rgba(0, 0, 0, 0.25)',
|
|
12
|
+
borderRightWidth: 0,
|
|
13
|
+
position: 'relative',
|
|
14
|
+
}),
|
|
15
|
+
item: (disabled: boolean, variant?: InputVariant) =>
|
|
16
|
+
css({
|
|
17
|
+
opacity: disabled ? 0.25 : 1,
|
|
18
|
+
padding: variant === 'default' ? '0px 15px' : '0px 7px',
|
|
19
|
+
width: '100%',
|
|
20
|
+
height: '100%',
|
|
21
|
+
cursor: 'pointer',
|
|
22
|
+
':hover': {
|
|
23
|
+
'& > label': {
|
|
24
|
+
color: disabled ? '' : enabledColor,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
|
|
29
|
+
indicator: css({
|
|
30
|
+
position: 'absolute',
|
|
31
|
+
top: -1,
|
|
32
|
+
left: -1,
|
|
33
|
+
right: -1,
|
|
34
|
+
bottom: -1,
|
|
35
|
+
zIndex: 10,
|
|
36
|
+
border: '1px solid',
|
|
37
|
+
borderColor: enabledColor,
|
|
38
|
+
|
|
39
|
+
'& ~ label': {
|
|
40
|
+
color: enabledColor,
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
|
|
44
|
+
label: (variant?: InputVariant) =>
|
|
45
|
+
css({
|
|
46
|
+
cursor: 'pointer',
|
|
47
|
+
fontSize: variant === 'small' ? '1em' : '1.125em',
|
|
48
|
+
lineHeight: variant === 'default' ? '30px' : '22px',
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export function ButtonRadioItem(
|
|
53
|
+
prop: RadioOption & Pick<RadioGroupProps, 'onSelect' | 'variant' | 'name'>,
|
|
54
|
+
) {
|
|
55
|
+
const { value, label, disabled = false, onSelect, variant, name } = prop;
|
|
56
|
+
return (
|
|
57
|
+
<div css={buttonStyles.container}>
|
|
58
|
+
<RadioGroup.Item
|
|
59
|
+
css={buttonStyles.item(disabled, variant)}
|
|
60
|
+
value={value}
|
|
61
|
+
id={`${value}${name}`}
|
|
62
|
+
onClick={() => {
|
|
63
|
+
if (!disabled) onSelect?.(prop);
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<RadioGroup.Indicator css={buttonStyles.indicator} />
|
|
67
|
+
<label
|
|
68
|
+
css={buttonStyles.label(variant)}
|
|
69
|
+
htmlFor={`${value}${name}`}
|
|
70
|
+
style={{}}
|
|
71
|
+
>
|
|
72
|
+
{label}
|
|
73
|
+
</label>
|
|
74
|
+
</RadioGroup.Item>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** @jsxImportSource @emotion/react */
|
|
2
|
+
import { css } from '@emotion/react';
|
|
3
|
+
import * as RadioGroup from '@radix-ui/react-radio-group';
|
|
4
|
+
|
|
5
|
+
import { disabledColor, enabledColor, InputVariant } from '../styles';
|
|
6
|
+
|
|
7
|
+
import { RadioOption, RadioGroupProps } from './RadioGroup';
|
|
8
|
+
|
|
9
|
+
const classicStyles = {
|
|
10
|
+
container: (disabled: boolean) =>
|
|
11
|
+
css({
|
|
12
|
+
display: 'flex',
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
flexDirection: 'row-reverse',
|
|
15
|
+
opacity: disabled ? 0.25 : 1,
|
|
16
|
+
overflow: 'hidden',
|
|
17
|
+
border: 'none',
|
|
18
|
+
}),
|
|
19
|
+
item: (disabled: boolean, variant?: InputVariant) =>
|
|
20
|
+
css({
|
|
21
|
+
position: 'relative',
|
|
22
|
+
width: variant === 'default' ? 16 : 14,
|
|
23
|
+
height: variant === 'default' ? 16 : 14,
|
|
24
|
+
borderRadius: '50%',
|
|
25
|
+
border: '1px solid grey',
|
|
26
|
+
backgroundColor: disabled ? disabledColor : 'white',
|
|
27
|
+
':hover': {
|
|
28
|
+
borderColor: disabled ? 'grey' : enabledColor,
|
|
29
|
+
},
|
|
30
|
+
}),
|
|
31
|
+
|
|
32
|
+
indicator: css({
|
|
33
|
+
position: 'absolute',
|
|
34
|
+
top: -1,
|
|
35
|
+
left: -1,
|
|
36
|
+
right: -1,
|
|
37
|
+
bottom: -1,
|
|
38
|
+
zIndex: 10,
|
|
39
|
+
display: 'flex',
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
justifyContent: 'center',
|
|
42
|
+
backgroundColor: enabledColor,
|
|
43
|
+
borderRadius: '50%',
|
|
44
|
+
}),
|
|
45
|
+
circle: css({
|
|
46
|
+
width: '40%',
|
|
47
|
+
height: '40%',
|
|
48
|
+
borderRadius: '50%',
|
|
49
|
+
backgroundColor: 'white',
|
|
50
|
+
}),
|
|
51
|
+
|
|
52
|
+
label: (disabled: boolean) =>
|
|
53
|
+
css({
|
|
54
|
+
cursor: 'pointer',
|
|
55
|
+
lineHeight: 1,
|
|
56
|
+
paddingLeft: 5,
|
|
57
|
+
fontSize: '12px',
|
|
58
|
+
':hover': {
|
|
59
|
+
'& ~ button': {
|
|
60
|
+
borderColor: disabled ? 'grey' : enabledColor,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export function ClassicRadioItem(
|
|
67
|
+
props: RadioOption & Pick<RadioGroupProps, 'onSelect' | 'variant' | 'name'>,
|
|
68
|
+
) {
|
|
69
|
+
const { value, label, disabled = false, onSelect, variant, name } = props;
|
|
70
|
+
return (
|
|
71
|
+
<div css={classicStyles.container(disabled)}>
|
|
72
|
+
<label
|
|
73
|
+
css={classicStyles.label(disabled)}
|
|
74
|
+
style={{
|
|
75
|
+
fontSize: variant === 'small' ? '1em' : '1.125em',
|
|
76
|
+
}}
|
|
77
|
+
htmlFor={`${value}${name}`}
|
|
78
|
+
>
|
|
79
|
+
{label}
|
|
80
|
+
</label>
|
|
81
|
+
<RadioGroup.Item
|
|
82
|
+
css={classicStyles.item(disabled, variant)}
|
|
83
|
+
value={value}
|
|
84
|
+
id={`${value}${name}`}
|
|
85
|
+
onClick={() => {
|
|
86
|
+
if (!disabled) onSelect?.(props);
|
|
87
|
+
}}
|
|
88
|
+
>
|
|
89
|
+
<RadioGroup.Indicator css={classicStyles.indicator}>
|
|
90
|
+
<div css={classicStyles.circle} />
|
|
91
|
+
</RadioGroup.Indicator>
|
|
92
|
+
</RadioGroup.Item>
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** @jsxImportSource @emotion/react */
|
|
2
|
+
import { css } from '@emotion/react';
|
|
3
|
+
import * as RadioGroupRadix from '@radix-ui/react-radio-group';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
import { InputVariant } from '../styles';
|
|
7
|
+
|
|
8
|
+
import { ButtonRadioItem } from './ButtonRadioItem';
|
|
9
|
+
import { ClassicRadioItem } from './ClassicRadioItem';
|
|
10
|
+
|
|
11
|
+
export interface RadioOption {
|
|
12
|
+
value: string;
|
|
13
|
+
label: ReactNode;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface RadioGroupProps {
|
|
17
|
+
selected?: RadioOption;
|
|
18
|
+
type?: 'classic' | 'button';
|
|
19
|
+
options?: RadioOption[];
|
|
20
|
+
onSelect?: (option: RadioOption) => void;
|
|
21
|
+
name?: string;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
variant?: InputVariant;
|
|
24
|
+
}
|
|
25
|
+
const rootStyles = {
|
|
26
|
+
basic: css({
|
|
27
|
+
display: 'flex',
|
|
28
|
+
flexDirection: 'row',
|
|
29
|
+
width: 'fit-content',
|
|
30
|
+
}),
|
|
31
|
+
button: (variant: InputVariant) =>
|
|
32
|
+
css({
|
|
33
|
+
' & > *:first-of-type, & > *:first-of-type span': {
|
|
34
|
+
borderRadius: variant === 'default' ? '6px 0 0 6px' : '4px 0 0 4px',
|
|
35
|
+
},
|
|
36
|
+
' & > *:last-of-type, & > *:last-of-type span': {
|
|
37
|
+
borderRightWidth: 1,
|
|
38
|
+
borderRadius: variant === 'default' ? '0 6px 6px 0' : '0 4px 4px 0',
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
};
|
|
42
|
+
export function RadioGroup(props: RadioGroupProps) {
|
|
43
|
+
const {
|
|
44
|
+
selected,
|
|
45
|
+
type = 'classic',
|
|
46
|
+
disabled: groupDisabled = false,
|
|
47
|
+
options = [],
|
|
48
|
+
onSelect,
|
|
49
|
+
name = '',
|
|
50
|
+
variant = 'default',
|
|
51
|
+
} = props;
|
|
52
|
+
return (
|
|
53
|
+
<RadioGroupRadix.Root
|
|
54
|
+
css={[
|
|
55
|
+
rootStyles.basic,
|
|
56
|
+
type === 'classic' ? null : rootStyles.button(variant),
|
|
57
|
+
]}
|
|
58
|
+
style={{
|
|
59
|
+
gap: type === 'classic' ? (variant === 'default' ? 10 : 5) : 0,
|
|
60
|
+
}}
|
|
61
|
+
value={selected?.value}
|
|
62
|
+
name={name}
|
|
63
|
+
disabled={groupDisabled}
|
|
64
|
+
>
|
|
65
|
+
{options?.map(({ value, label, disabled }) => {
|
|
66
|
+
const childProps = {
|
|
67
|
+
key: value,
|
|
68
|
+
value,
|
|
69
|
+
label,
|
|
70
|
+
disabled: groupDisabled || disabled,
|
|
71
|
+
onSelect,
|
|
72
|
+
variant,
|
|
73
|
+
name,
|
|
74
|
+
};
|
|
75
|
+
return type === 'classic' ? (
|
|
76
|
+
<ClassicRadioItem {...childProps} />
|
|
77
|
+
) : (
|
|
78
|
+
<ButtonRadioItem {...childProps} />
|
|
79
|
+
);
|
|
80
|
+
})}
|
|
81
|
+
</RadioGroupRadix.Root>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './RadioGroup';
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
|
|
3
|
+
export type InputVariant = 'default' | 'small';
|
|
4
|
+
|
|
5
|
+
interface StyledProps {
|
|
6
|
+
variant: InputVariant;
|
|
7
|
+
hasLeading?: boolean;
|
|
8
|
+
hasTrailing?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export const enabledColor = '#1677ff';
|
|
11
|
+
export const disabledColor = '#b8b8b8';
|
|
12
|
+
|
|
13
|
+
export const LabelStyled = styled.label<StyledProps>`
|
|
14
|
+
padding: ${(props) =>
|
|
15
|
+
props.variant === 'default'
|
|
16
|
+
? props.hasTrailing
|
|
17
|
+
? '2px 9px 4px 9px'
|
|
18
|
+
: '2px 9px'
|
|
19
|
+
: props.hasTrailing
|
|
20
|
+
? '1px 7px 1px 7px'
|
|
21
|
+
: '1px 7px'};
|
|
22
|
+
|
|
23
|
+
font-size: ${(props) => (props.variant === 'small' ? '1em' : '1.125em')};
|
|
24
|
+
line-height: '17px';
|
|
25
|
+
|
|
26
|
+
background-color: white;
|
|
27
|
+
border-width: 1px;
|
|
28
|
+
align-items: center;
|
|
29
|
+
flex-direction: row;
|
|
30
|
+
flex: 1 1 0%;
|
|
31
|
+
display: flex;
|
|
32
|
+
position: relative;
|
|
33
|
+
|
|
34
|
+
border-top-right-radius: ${(props) =>
|
|
35
|
+
props.hasLeading && !props.hasTrailing && '0.375rem'};
|
|
36
|
+
|
|
37
|
+
border-bottom-right-radius: ${(props) =>
|
|
38
|
+
props.hasLeading && !props.hasTrailing && '0.375rem'};
|
|
39
|
+
|
|
40
|
+
border-top-left-radius: ${(props) =>
|
|
41
|
+
props.hasTrailing && !props.hasLeading && '0.375rem'};
|
|
42
|
+
|
|
43
|
+
border-bottom-left-radius: ${(props) =>
|
|
44
|
+
props.hasTrailing && !props.hasLeading && '0.375rem'};
|
|
45
|
+
|
|
46
|
+
border-radius: ${(props) =>
|
|
47
|
+
!props.hasLeading && !props.hasTrailing && '0.375rem'};
|
|
48
|
+
|
|
49
|
+
border-color: var(--custom-border-color);
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
function getStyleColor(hasError: boolean, hasValid: boolean) {
|
|
53
|
+
if (hasError) {
|
|
54
|
+
return {
|
|
55
|
+
default: '#ffa39e',
|
|
56
|
+
hover: '#f95d55',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (hasValid) {
|
|
61
|
+
return {
|
|
62
|
+
default: '#6adc24',
|
|
63
|
+
hover: '#62cb21',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
default: 'rgb(217, 217, 217)',
|
|
69
|
+
hover: '#4096ff',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const GroupStyled = styled.div<{ hasError: boolean; hasValid: boolean }>`
|
|
74
|
+
display: flex;
|
|
75
|
+
border-radius: 0.375rem;
|
|
76
|
+
margin-top: 0.25rem;
|
|
77
|
+
|
|
78
|
+
.addon {
|
|
79
|
+
color: ${({ hasError }) => hasError && '#f95d55'};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
--custom-border-color: ${({ hasError, hasValid }) =>
|
|
83
|
+
getStyleColor(hasError, hasValid).default};
|
|
84
|
+
|
|
85
|
+
:hover,
|
|
86
|
+
:focus-within {
|
|
87
|
+
--custom-border-color: ${({ hasError, hasValid }) =>
|
|
88
|
+
getStyleColor(hasError, hasValid).hover};
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
export const InputContainer = styled.div`
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
gap: 2px;
|
|
96
|
+
`;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface SubTextProps {
|
|
4
|
+
help?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
valid?: true | string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function SubText(props: SubTextProps) {
|
|
10
|
+
const { error, help, valid: validProps } = props;
|
|
11
|
+
|
|
12
|
+
const valid = typeof validProps === 'string' ? validProps : undefined;
|
|
13
|
+
const text = error || valid || help;
|
|
14
|
+
|
|
15
|
+
return <p style={{ color: getColor(error, validProps) }}>{text}</p>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getColor(
|
|
19
|
+
error?: string,
|
|
20
|
+
valid?: true | string,
|
|
21
|
+
): CSSProperties['color'] {
|
|
22
|
+
if (error) {
|
|
23
|
+
return '#f95d55';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (valid && typeof valid !== 'boolean') {
|
|
27
|
+
return '#62cb21';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return 'gray';
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SubText';
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** @jsxImportSource @emotion/react */
|
|
2
|
+
import { css } from '@emotion/react';
|
|
3
|
+
import { ReactNode, useEffect, useRef } from 'react';
|
|
4
|
+
import { FaCog } from 'react-icons/fa';
|
|
5
|
+
|
|
6
|
+
import { Button } from '../button/Button';
|
|
7
|
+
|
|
8
|
+
const styles = {
|
|
9
|
+
container: css({
|
|
10
|
+
display: 'flex',
|
|
11
|
+
flexDirection: 'row',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
justifyContent: 'space-between',
|
|
14
|
+
borderBottom: '0.55px solid rgb(240, 240, 240)',
|
|
15
|
+
}),
|
|
16
|
+
leftContainer: css({
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flexDirection: 'row',
|
|
19
|
+
flex: 1,
|
|
20
|
+
'& > button': {
|
|
21
|
+
padding: '0 5px',
|
|
22
|
+
minWidth: 'auto',
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
counterLabel: css({
|
|
26
|
+
margin: 0,
|
|
27
|
+
textAlign: 'right',
|
|
28
|
+
lineHeight: '22px',
|
|
29
|
+
whiteSpace: 'nowrap',
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
interface PanelHeaderProps {
|
|
34
|
+
total?: number;
|
|
35
|
+
current?: number;
|
|
36
|
+
onClickSettings?: () => void;
|
|
37
|
+
children?: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function PanelHeader({
|
|
41
|
+
total,
|
|
42
|
+
current,
|
|
43
|
+
children,
|
|
44
|
+
onClickSettings,
|
|
45
|
+
}: PanelHeaderProps) {
|
|
46
|
+
const labelRef = useRef<HTMLParagraphElement>(null);
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!labelRef.current) return;
|
|
50
|
+
|
|
51
|
+
if (current !== undefined && total !== undefined) {
|
|
52
|
+
labelRef.current.textContent = `${current} / ${total}`;
|
|
53
|
+
} else if (current !== undefined) {
|
|
54
|
+
labelRef.current.textContent = `[ ${current} ]`;
|
|
55
|
+
} else if (total !== undefined) {
|
|
56
|
+
labelRef.current.textContent = `[ ${total} ]`;
|
|
57
|
+
}
|
|
58
|
+
}, [current, total]);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div css={styles.container}>
|
|
62
|
+
<div css={styles.leftContainer}>{children}</div>
|
|
63
|
+
<p ref={labelRef} css={styles.counterLabel} />
|
|
64
|
+
{onClickSettings && (
|
|
65
|
+
<Button
|
|
66
|
+
onClick={onClickSettings}
|
|
67
|
+
color={{ basic: 'black', hover: 'black' }}
|
|
68
|
+
backgroundColor={{ basic: 'white', hover: '#f7f7f7' }}
|
|
69
|
+
>
|
|
70
|
+
<FaCog />
|
|
71
|
+
</Button>
|
|
72
|
+
)}
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|