@takaro/lib-components 0.0.13 → 0.0.15
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/Dockerfile.dev +1 -1
- package/package.json +21 -20
- package/src/components/actions/ToggleButton/ToggleButton.stories.tsx +1 -0
- package/src/components/actions/ToggleButton/ToggleButton.tsx +3 -1
- package/src/components/actions/ToggleButton/ToggleButtonGroup.tsx +16 -2
- package/src/components/charts/AreaChart/AreaChart.stories.tsx +15 -20
- package/src/components/charts/GeoMercator/GeoMercator.stories.tsx +24 -18
- package/src/components/charts/GeoMercator/index.tsx +160 -58
- package/src/components/charts/GeoMercator/iso3166-alpha2-to-alpha3.ts +250 -0
- package/src/components/charts/GeoMercator/world.json +333 -0
- package/src/components/charts/ZoomControls.tsx +47 -0
- package/src/components/charts/index.tsx +3 -0
- package/src/components/data/Drawer/Drawer.stories.tsx +19 -10
- package/src/components/data/Drawer/DrawerContent.tsx +56 -1
- package/src/components/data/Drawer/useDrawer.tsx +16 -2
- package/src/components/data/Table/index.tsx +94 -33
- package/src/components/data/Table/style.ts +21 -0
- package/src/components/data/Table/subcomponents/Pagination/PageSizeSelect.tsx +1 -0
- package/src/components/dialogs/Dialog/DialogContent.tsx +1 -5
- package/src/components/feedback/Alert/Alert.stories.tsx +1 -10
- package/src/components/feedback/Alert/index.tsx +11 -15
- package/src/components/feedback/Alert/style.ts +9 -11
- package/src/components/feedback/ErrorPage/index.tsx +2 -2
- package/src/components/feedback/snacks/Drawer/Drawer.stories.tsx +1 -1
- package/src/components/feedback/snacks/Drawer/index.tsx +4 -0
- package/src/components/inputs/Date/DatePicker/Controlled.tsx +2 -0
- package/src/components/inputs/Date/DatePicker/DatePicker.stories.tsx +1 -1
- package/src/components/inputs/Date/DatePicker/Generic.tsx +20 -4
- package/src/components/inputs/Date/DatePicker/style.ts +3 -4
- package/src/components/inputs/index.ts +7 -0
- package/src/components/inputs/selects/SelectQueryField/Controlled.tsx +10 -0
- package/src/components/inputs/selects/SelectQueryField/Generic/index.tsx +39 -16
- package/src/components/inputs/selects/SelectQueryField/SelectQueryField.stories.tsx +20 -0
- package/src/components/inputs/selects/SubComponents/OptionGroup.tsx +4 -2
- package/src/components/other/CollapseList/index.tsx +26 -31
- package/src/components/visual/Card/Card.stories.tsx +4 -1
- package/src/components/visual/Card/CardBody.tsx +11 -0
- package/src/components/visual/Card/CardTitle.tsx +23 -0
- package/src/components/visual/Card/index.tsx +21 -14
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { forwardRef, HTMLProps, useState } from 'react';
|
|
2
2
|
import { styled } from '../../../styled';
|
|
3
|
+
import { Button } from '../../../components';
|
|
3
4
|
import { AnimatePresence, motion, PanInfo } from 'framer-motion';
|
|
4
5
|
import SimpleBar from 'simplebar-react';
|
|
5
6
|
|
|
@@ -15,6 +16,39 @@ const Container = styled(motion.div)`
|
|
|
15
16
|
border-left: 1px solid ${({ theme }) => theme.colors.backgroundAccent};
|
|
16
17
|
`;
|
|
17
18
|
|
|
19
|
+
const ButtonContainer = styled.div`
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: flex-start;
|
|
23
|
+
gap: ${({ theme }) => theme.spacing[1]};
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
const CloseConfirmationWrapper = styled.div`
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 0;
|
|
29
|
+
left: 0;
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
width: 100%;
|
|
34
|
+
height: 100%;
|
|
35
|
+
background: rgba(0, 0, 0, 0.8);
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const CloseConfirmationContainer = styled.div`
|
|
39
|
+
height: 150px;
|
|
40
|
+
padding: ${({ theme }) => theme.spacing[2]};
|
|
41
|
+
width: calc(100% - 200px);
|
|
42
|
+
background-color: ${({ theme }) => theme.colors.background};
|
|
43
|
+
border: 1px solid ${({ theme }) => theme.colors.backgroundAccent};
|
|
44
|
+
border-radius: ${({ theme }) => theme.borderRadius.medium};
|
|
45
|
+
|
|
46
|
+
h2,
|
|
47
|
+
p {
|
|
48
|
+
margin-bottom: ${({ theme }) => theme.spacing[1]};
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
|
|
18
52
|
export const HandleContainer = styled.div`
|
|
19
53
|
height: 80vh;
|
|
20
54
|
top: 10vh;
|
|
@@ -35,7 +69,16 @@ export const HandleContainer = styled.div`
|
|
|
35
69
|
`;
|
|
36
70
|
|
|
37
71
|
export const DrawerContent = forwardRef<HTMLElement, HTMLProps<HTMLDivElement>>(function DrawerContent(props, propRef) {
|
|
38
|
-
const {
|
|
72
|
+
const {
|
|
73
|
+
context,
|
|
74
|
+
labelId,
|
|
75
|
+
descriptionId,
|
|
76
|
+
getFloatingProps,
|
|
77
|
+
setOpen,
|
|
78
|
+
canDrag,
|
|
79
|
+
showConfirmDialog,
|
|
80
|
+
setShowConfirmDialog,
|
|
81
|
+
} = useDrawerContext();
|
|
39
82
|
|
|
40
83
|
const ref = useMergeRefs([context.refs.setFloating, propRef]);
|
|
41
84
|
const [dragPosition, setDragPosition] = useState<number>(0);
|
|
@@ -100,6 +143,18 @@ export const DrawerContent = forwardRef<HTMLElement, HTMLProps<HTMLDivElement>>(
|
|
|
100
143
|
</HandleContainer>
|
|
101
144
|
)}
|
|
102
145
|
<SimpleBar style={{ maxHeight: '92vh' }}>{props.children}</SimpleBar>
|
|
146
|
+
{showConfirmDialog && (
|
|
147
|
+
<CloseConfirmationWrapper>
|
|
148
|
+
<CloseConfirmationContainer>
|
|
149
|
+
<h2>Your progress will be lost</h2>
|
|
150
|
+
<p>Are you sure you want to exit? Your progress will not be saved.</p>
|
|
151
|
+
<ButtonContainer>
|
|
152
|
+
<Button text="Cancel" color="secondary" onClick={() => setShowConfirmDialog(false)} />
|
|
153
|
+
<Button text="Discard changes" onClick={() => setOpen(false)} color="error" />
|
|
154
|
+
</ButtonContainer>
|
|
155
|
+
</CloseConfirmationContainer>
|
|
156
|
+
</CloseConfirmationWrapper>
|
|
157
|
+
)}
|
|
103
158
|
</Container>
|
|
104
159
|
</FloatingFocusManager>
|
|
105
160
|
</FloatingOverlay>
|
|
@@ -6,17 +6,20 @@ export interface DrawerOptions {
|
|
|
6
6
|
initialOpen?: boolean;
|
|
7
7
|
onOpenChange?: (open: boolean) => void;
|
|
8
8
|
canDrag?: boolean;
|
|
9
|
+
promptCloseConfirmation?: boolean;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export function useDrawer({
|
|
12
13
|
initialOpen = false,
|
|
13
14
|
canDrag = false,
|
|
14
15
|
open: controlledOpen,
|
|
16
|
+
promptCloseConfirmation = false,
|
|
15
17
|
onOpenChange: setControlledOpen,
|
|
16
18
|
}: DrawerOptions) {
|
|
17
19
|
const [uncontrolledOpen, setUncontrolledOpen] = useState(initialOpen);
|
|
18
20
|
const [labelId, setLabelId] = useState<string | undefined>();
|
|
19
21
|
const [descriptionId, setDescriptionId] = useState<string | undefined>();
|
|
22
|
+
const [showConfirmDialog, setShowConfirmDialog] = useState<boolean>(false);
|
|
20
23
|
|
|
21
24
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
22
25
|
const setOpen = setControlledOpen ?? setUncontrolledOpen;
|
|
@@ -32,13 +35,24 @@ export function useDrawer({
|
|
|
32
35
|
useClick(context, {
|
|
33
36
|
enabled: controlledOpen == null,
|
|
34
37
|
}),
|
|
35
|
-
useDismiss(context, {
|
|
38
|
+
useDismiss(context, {
|
|
39
|
+
outsidePressEvent: 'mousedown',
|
|
40
|
+
outsidePress: (_mouseEvent) => {
|
|
41
|
+
if (promptCloseConfirmation === true) {
|
|
42
|
+
setShowConfirmDialog(true);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
36
48
|
]);
|
|
37
49
|
|
|
38
50
|
return useMemo(
|
|
39
51
|
() => ({
|
|
40
52
|
open,
|
|
41
53
|
setOpen,
|
|
54
|
+
showConfirmDialog,
|
|
55
|
+
setShowConfirmDialog,
|
|
42
56
|
...interactions,
|
|
43
57
|
...data,
|
|
44
58
|
labelId,
|
|
@@ -47,6 +61,6 @@ export function useDrawer({
|
|
|
47
61
|
setDescriptionId,
|
|
48
62
|
canDrag,
|
|
49
63
|
}),
|
|
50
|
-
[open, setOpen, interactions, data, labelId, descriptionId],
|
|
64
|
+
[open, setOpen, interactions, data, labelId, descriptionId, showConfirmDialog],
|
|
51
65
|
);
|
|
52
66
|
}
|
|
@@ -17,11 +17,18 @@ import {
|
|
|
17
17
|
VisibilityState,
|
|
18
18
|
ColumnPinningState,
|
|
19
19
|
RowSelectionState,
|
|
20
|
+
ExpandedState,
|
|
21
|
+
getExpandedRowModel,
|
|
22
|
+
Row,
|
|
20
23
|
} from '@tanstack/react-table';
|
|
21
24
|
import { Wrapper, StyledTable, Toolbar, Flex, TableWrapper } from './style';
|
|
22
|
-
import { Button, Empty, Spinner, ToggleButtonGroup } from '../../../components';
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
+
import { Button, Empty, IconButton, Spinner, ToggleButtonGroup } from '../../../components';
|
|
26
|
+
import {
|
|
27
|
+
AiOutlinePicCenter as RelaxedDensityIcon,
|
|
28
|
+
AiOutlinePicRight as TightDensityIcon,
|
|
29
|
+
AiOutlineRight as ExpandIcon,
|
|
30
|
+
AiOutlineUp as CollapseIcon,
|
|
31
|
+
} from 'react-icons/ai';
|
|
25
32
|
import { ColumnHeader } from './subcomponents/ColumnHeader';
|
|
26
33
|
import { ColumnVisibility } from './subcomponents/ColumnVisibility';
|
|
27
34
|
import { Filter } from './subcomponents/Filter';
|
|
@@ -37,8 +44,12 @@ export interface TableProps<DataType extends object> {
|
|
|
37
44
|
data: DataType[];
|
|
38
45
|
isLoading?: boolean;
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
/// Condition for row to be expandable
|
|
48
|
+
canExpand?: (row: Row<DataType>) => boolean;
|
|
49
|
+
/// What to render when row can be expanded
|
|
50
|
+
renderDetailPanel?: (row: Row<DataType>) => JSX.Element;
|
|
41
51
|
|
|
52
|
+
/// currently not possible to type this properly: https://github.com/TanStack/table/issues/4241
|
|
42
53
|
columns: ColumnDef<DataType, any>[];
|
|
43
54
|
|
|
44
55
|
/// Renders actions that are always visible
|
|
@@ -83,7 +94,9 @@ export function Table<DataType extends object>({
|
|
|
83
94
|
title,
|
|
84
95
|
rowSelection,
|
|
85
96
|
columnSearch,
|
|
97
|
+
renderDetailPanel,
|
|
86
98
|
renderToolbar,
|
|
99
|
+
canExpand = () => false,
|
|
87
100
|
renderRowSelectionActions,
|
|
88
101
|
isLoading = false,
|
|
89
102
|
}: TableProps<DataType>) {
|
|
@@ -111,9 +124,13 @@ export function Table<DataType extends object>({
|
|
|
111
124
|
{} as Record<string, boolean>,
|
|
112
125
|
);
|
|
113
126
|
});
|
|
127
|
+
|
|
114
128
|
const [columnPinning, setColumnPinning] = useState<ColumnPinningState>({});
|
|
115
129
|
const { storedValue: density, setValue: setDensity } = useLocalStorage<Density>(`table-density-${id}`, 'tight');
|
|
116
130
|
|
|
131
|
+
// Might because potentially none fullfil the canExpand condtion.
|
|
132
|
+
const rowsMightExpand = renderDetailPanel ? true : false;
|
|
133
|
+
const [expanded, setExpanded] = useState<ExpandedState>({});
|
|
117
134
|
const [openColumnVisibilityTooltip, setOpenColumnVisibilityTooltip] = useState<boolean>(false);
|
|
118
135
|
const [hasShownColumnVisibilityTooltip, setHasShownColumnVisibilityTooltip] = useState<boolean>(false);
|
|
119
136
|
const [columnOrder, setColumnOrder] = useState<ColumnOrderState>(
|
|
@@ -126,6 +143,7 @@ export function Table<DataType extends object>({
|
|
|
126
143
|
);
|
|
127
144
|
|
|
128
145
|
const ROW_SELECTION_COL_SPAN = rowSelection ? 1 : 0;
|
|
146
|
+
const EXPAND_ROW_COL_SPAN = rowsMightExpand ? 1 : 0;
|
|
129
147
|
const MINIMUM_ROW_COUNT_FOR_PAGINATION = 5;
|
|
130
148
|
|
|
131
149
|
// handles the column visibility tooltip (shows tooltip when the first column is hidden)
|
|
@@ -154,6 +172,7 @@ export function Table<DataType extends object>({
|
|
|
154
172
|
data,
|
|
155
173
|
columns,
|
|
156
174
|
getCoreRowModel: getCoreRowModel(),
|
|
175
|
+
getExpandedRowModel: getExpandedRowModel(),
|
|
157
176
|
pageCount: pagination?.pageOptions.pageCount ?? -1,
|
|
158
177
|
manualPagination: true,
|
|
159
178
|
paginateExpandedRows: true, // Expanded rows will be paginated this means that rows that take up more space will be shown on next page.
|
|
@@ -169,6 +188,7 @@ export function Table<DataType extends object>({
|
|
|
169
188
|
enablePinning: true,
|
|
170
189
|
enableHiding: !!columnVisibility,
|
|
171
190
|
enableRowSelection: !!rowSelection,
|
|
191
|
+
getRowCanExpand: canExpand,
|
|
172
192
|
autoResetPageIndex: false,
|
|
173
193
|
|
|
174
194
|
columnResizeMode: 'onChange',
|
|
@@ -180,6 +200,7 @@ export function Table<DataType extends object>({
|
|
|
180
200
|
onColumnOrderChange: setColumnOrder,
|
|
181
201
|
onColumnPinningChange: setColumnPinning,
|
|
182
202
|
onRowSelectionChange: rowSelection ? rowSelection?.setRowSelectionState : undefined,
|
|
203
|
+
onExpandedChange: setExpanded,
|
|
183
204
|
|
|
184
205
|
initialState: {
|
|
185
206
|
columnVisibility,
|
|
@@ -194,6 +215,7 @@ export function Table<DataType extends object>({
|
|
|
194
215
|
state: {
|
|
195
216
|
columnVisibility,
|
|
196
217
|
columnOrder,
|
|
218
|
+
expanded,
|
|
197
219
|
sorting: sorting.sortingState,
|
|
198
220
|
columnFilters: columnFiltering.columnFiltersState,
|
|
199
221
|
globalFilter: columnSearch.columnSearchState,
|
|
@@ -204,6 +226,7 @@ export function Table<DataType extends object>({
|
|
|
204
226
|
});
|
|
205
227
|
|
|
206
228
|
const tableHasNoData = isLoading === false && table.getRowModel().rows.length === 0;
|
|
229
|
+
const tableHasData = isLoading === false && table.getRowModel().rows.length !== 0;
|
|
207
230
|
|
|
208
231
|
// rowSelection.rowSelectionState has the following shape: { [rowId: string]: boolean }
|
|
209
232
|
const hasRowSelection = useMemo(() => {
|
|
@@ -254,7 +277,7 @@ export function Table<DataType extends object>({
|
|
|
254
277
|
<thead>
|
|
255
278
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
256
279
|
<tr key={headerGroup.id}>
|
|
257
|
-
{rowSelection &&
|
|
280
|
+
{rowSelection && tableHasData && (
|
|
258
281
|
<Th
|
|
259
282
|
isActive={false}
|
|
260
283
|
isRight={false}
|
|
@@ -276,6 +299,17 @@ export function Table<DataType extends object>({
|
|
|
276
299
|
</div>
|
|
277
300
|
</Th>
|
|
278
301
|
)}
|
|
302
|
+
{rowsMightExpand && tableHasData && (
|
|
303
|
+
<Th
|
|
304
|
+
isActive={false}
|
|
305
|
+
isRight={false}
|
|
306
|
+
isDragging={false}
|
|
307
|
+
canDrag={false}
|
|
308
|
+
isRowSelection={true}
|
|
309
|
+
width={15}
|
|
310
|
+
/>
|
|
311
|
+
)}
|
|
312
|
+
|
|
279
313
|
{headerGroup.headers.map((header) => (
|
|
280
314
|
<ColumnHeader
|
|
281
315
|
header={header}
|
|
@@ -291,7 +325,7 @@ export function Table<DataType extends object>({
|
|
|
291
325
|
{/* loading state */}
|
|
292
326
|
{isLoading && (
|
|
293
327
|
<tr>
|
|
294
|
-
<td colSpan={table.getAllColumns().length + ROW_SELECTION_COL_SPAN}>
|
|
328
|
+
<td colSpan={table.getAllColumns().length + ROW_SELECTION_COL_SPAN + EXPAND_ROW_COL_SPAN}>
|
|
295
329
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '15px' }}>
|
|
296
330
|
<Spinner size="small" />
|
|
297
331
|
</div>
|
|
@@ -302,11 +336,11 @@ export function Table<DataType extends object>({
|
|
|
302
336
|
{/* empty state */}
|
|
303
337
|
{tableHasNoData && (
|
|
304
338
|
<tr>
|
|
305
|
-
<td colSpan={table.getAllColumns().length + ROW_SELECTION_COL_SPAN}>
|
|
339
|
+
<td colSpan={table.getAllColumns().length + ROW_SELECTION_COL_SPAN + EXPAND_ROW_COL_SPAN}>
|
|
306
340
|
<div style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
307
341
|
<Empty
|
|
308
342
|
header=""
|
|
309
|
-
description="
|
|
343
|
+
description="Data will appear here."
|
|
310
344
|
actions={[
|
|
311
345
|
<Button
|
|
312
346
|
key={id + '-learn-more-button'}
|
|
@@ -323,30 +357,51 @@ export function Table<DataType extends object>({
|
|
|
323
357
|
|
|
324
358
|
{!isLoading &&
|
|
325
359
|
table.getRowModel().rows.map((row) => (
|
|
326
|
-
|
|
327
|
-
{row.
|
|
328
|
-
|
|
329
|
-
<
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
360
|
+
<>
|
|
361
|
+
<tr key={row.id}>
|
|
362
|
+
{row.getCanExpand() ? (
|
|
363
|
+
<td style={{ paddingRight: '10px', width: '15px' }}>
|
|
364
|
+
{row.getIsExpanded() ? (
|
|
365
|
+
<IconButton
|
|
366
|
+
size="tiny"
|
|
367
|
+
icon={<CollapseIcon />}
|
|
368
|
+
ariaLabel="Collapse expanded row"
|
|
369
|
+
onClick={() => row.toggleExpanded(false)}
|
|
370
|
+
/>
|
|
371
|
+
) : (
|
|
372
|
+
<IconButton
|
|
373
|
+
size="tiny"
|
|
374
|
+
icon={<ExpandIcon />}
|
|
375
|
+
ariaLabel="expand row"
|
|
376
|
+
onClick={() => row.toggleExpanded(true)}
|
|
377
|
+
/>
|
|
378
|
+
)}
|
|
379
|
+
</td>
|
|
380
|
+
) : rowsMightExpand ? (
|
|
381
|
+
<td />
|
|
382
|
+
) : (
|
|
383
|
+
<></>
|
|
384
|
+
)}
|
|
385
|
+
{row.getCanSelect() && (
|
|
386
|
+
<td style={{ paddingRight: '10px', width: '15px' }}>
|
|
387
|
+
<CheckBox
|
|
388
|
+
value={row.getIsSelected()}
|
|
389
|
+
id={row.id}
|
|
390
|
+
name={row.id}
|
|
391
|
+
hasError={false}
|
|
392
|
+
disabled={!row.getCanSelect()}
|
|
393
|
+
onChange={() => row.toggleSelected()}
|
|
394
|
+
hasDescription={false}
|
|
395
|
+
size="small"
|
|
396
|
+
/>
|
|
397
|
+
</td>
|
|
398
|
+
)}
|
|
399
|
+
{row.getVisibleCells().map(({ column, id, getContext }) => (
|
|
400
|
+
<td key={id}>{flexRender(column.columnDef.cell, getContext())}</td>
|
|
401
|
+
))}
|
|
402
|
+
</tr>
|
|
403
|
+
{row.getIsExpanded() && renderDetailPanel!(row)}
|
|
404
|
+
</>
|
|
350
405
|
))}
|
|
351
406
|
</tbody>
|
|
352
407
|
|
|
@@ -355,9 +410,15 @@ export function Table<DataType extends object>({
|
|
|
355
410
|
<tr>
|
|
356
411
|
{/* This is the row selection */}
|
|
357
412
|
{ROW_SELECTION_COL_SPAN ? <td colSpan={1} /> : null}
|
|
413
|
+
{/* This is for the row expansion icon */}
|
|
414
|
+
{EXPAND_ROW_COL_SPAN ? <td colSpan={1} /> : null}
|
|
358
415
|
{pagination && (
|
|
359
416
|
<>
|
|
360
|
-
<td
|
|
417
|
+
<td
|
|
418
|
+
colSpan={
|
|
419
|
+
table.getVisibleLeafColumns().length - 3 - ROW_SELECTION_COL_SPAN - EXPAND_ROW_COL_SPAN
|
|
420
|
+
}
|
|
421
|
+
/>
|
|
361
422
|
<td colSpan={1}>
|
|
362
423
|
<span>
|
|
363
424
|
showing {table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1}-
|
|
@@ -46,6 +46,27 @@ export const StyledTable = styled.table<{ density: Density }>`
|
|
|
46
46
|
border-bottom: none;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
tr.subrow {
|
|
50
|
+
border-bottom: 1px solid ${({ theme }) => theme.colors.backgroundAccent};
|
|
51
|
+
|
|
52
|
+
&:nth-child(even) {
|
|
53
|
+
background-color: ${({ theme }) => theme.colors.background};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
&:nth-child(odd) {
|
|
57
|
+
background-color: ${({ theme }) => theme.colors.backgroundAlt};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
td {
|
|
61
|
+
&:first-child {
|
|
62
|
+
padding-left: 0;
|
|
63
|
+
padding-bottom: 0;
|
|
64
|
+
}
|
|
65
|
+
padding: ${({ theme, density }) =>
|
|
66
|
+
density === 'tight' ? `${theme.spacing['0_5']} 0` : `${theme.spacing['0_5']} 0`};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
49
70
|
td {
|
|
50
71
|
border-right: none;
|
|
51
72
|
border-bottom: 1px solid ${({ theme }) => theme.colors.backgroundAccent};
|
|
@@ -10,10 +10,6 @@ const StyledFloatingOverlay = styled(FloatingOverlay)`
|
|
|
10
10
|
place-items: center;
|
|
11
11
|
`;
|
|
12
12
|
|
|
13
|
-
const CardBody = styled.div`
|
|
14
|
-
min-width: 300px;
|
|
15
|
-
`;
|
|
16
|
-
|
|
17
13
|
export const DialogContent = forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
|
|
18
14
|
function DialogContent(props, propRef) {
|
|
19
15
|
const { context: floatingContext, ...context } = useDialogContext();
|
|
@@ -37,7 +33,7 @@ export const DialogContent = forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivE
|
|
|
37
33
|
...props,
|
|
38
34
|
})}
|
|
39
35
|
>
|
|
40
|
-
<
|
|
36
|
+
<Card.Body>{props.children}</Card.Body>
|
|
41
37
|
</Card>
|
|
42
38
|
</FloatingFocusManager>
|
|
43
39
|
</StyledFloatingOverlay>
|
|
@@ -13,16 +13,7 @@ export default {
|
|
|
13
13
|
|
|
14
14
|
export const Default: StoryFn<AlertProps> = (args) => <Alert {...args} />;
|
|
15
15
|
|
|
16
|
-
export const
|
|
17
|
-
args: {
|
|
18
|
-
title: 'Order complete',
|
|
19
|
-
text: 'Your order has been sucessfully processed. We are completing the report.',
|
|
20
|
-
variant: 'success',
|
|
21
|
-
dismiss: true,
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const Error: StoryObj<AlertProps> = {
|
|
16
|
+
export const WithList: StoryObj<AlertProps> = {
|
|
26
17
|
args: {
|
|
27
18
|
title: 'There were errors with your submission',
|
|
28
19
|
text: [
|
|
@@ -24,11 +24,10 @@ export interface AlertProps {
|
|
|
24
24
|
elevation?: Elevation;
|
|
25
25
|
dismiss?: boolean;
|
|
26
26
|
action?: Action;
|
|
27
|
-
showIcon?: boolean;
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
export const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
31
|
-
{ variant, title, text, dismiss = false, elevation = 4, action
|
|
30
|
+
{ variant, title, text, dismiss = false, elevation = 4, action },
|
|
32
31
|
ref,
|
|
33
32
|
) {
|
|
34
33
|
const [visible, setVisible] = useState(true);
|
|
@@ -85,19 +84,16 @@ export const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
|
85
84
|
ref={ref}
|
|
86
85
|
role="status"
|
|
87
86
|
>
|
|
88
|
-
<Grid
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{renderText()}
|
|
99
|
-
{hasTitle ? <div /> : null}
|
|
100
|
-
<ButtonContainer hasTitle={hasTitle} show={dismiss || action ? true : false} variant={variant}>
|
|
87
|
+
<Grid>
|
|
88
|
+
<IconContainer variant={variant}>{getIcon()}</IconContainer>
|
|
89
|
+
{title && <h2>{title}</h2>}
|
|
90
|
+
<p>{renderText()}</p>
|
|
91
|
+
<ButtonContainer
|
|
92
|
+
hasTitle={hasTitle}
|
|
93
|
+
show={dismiss || action ? true : false}
|
|
94
|
+
variant={variant}
|
|
95
|
+
className="action"
|
|
96
|
+
>
|
|
101
97
|
{action && (
|
|
102
98
|
<Button size="tiny" variant="outline" onClick={handleExecute} text={action.text} color={variant} />
|
|
103
99
|
)}
|
|
@@ -12,7 +12,8 @@ export const Container = styled(motion.div)<{
|
|
|
12
12
|
$elevation: Elevation;
|
|
13
13
|
}>`
|
|
14
14
|
width: 100%;
|
|
15
|
-
padding: ${({ theme }) =>
|
|
15
|
+
padding: ${({ theme }) =>
|
|
16
|
+
`${theme.spacing['0_75']} ${theme.spacing['0_75']} ${theme.spacing['0_75']} ${theme.spacing['0']}`};
|
|
16
17
|
border-radius: ${({ theme }) => theme.borderRadius.large};
|
|
17
18
|
box-shadow: ${({ theme, $elevation }) => theme.elevation[$elevation]};
|
|
18
19
|
margin: ${({ theme }) => `${theme.spacing['1_5']} auto`};
|
|
@@ -58,24 +59,21 @@ export const Container = styled(motion.div)<{
|
|
|
58
59
|
}}
|
|
59
60
|
`;
|
|
60
61
|
|
|
61
|
-
export const Grid = styled.div
|
|
62
|
+
export const Grid = styled.div`
|
|
62
63
|
display: grid;
|
|
63
|
-
grid-template-columns:
|
|
64
|
-
const result = '';
|
|
65
|
-
if (showIcon) result.concat(`${theme.spacing[5]}`);
|
|
66
|
-
result.concat(' 1fr');
|
|
67
|
-
if (hasTitle) result.concat(' fit-content(100px)');
|
|
68
|
-
return result;
|
|
69
|
-
}}
|
|
64
|
+
grid-template-columns: 40px 1fr;
|
|
70
65
|
align-items: center;
|
|
71
|
-
|
|
66
|
+
|
|
67
|
+
p,
|
|
68
|
+
.action {
|
|
69
|
+
grid-column: 2;
|
|
70
|
+
}
|
|
72
71
|
`;
|
|
73
72
|
|
|
74
73
|
export const IconContainer = styled.div<{ variant: AlertVariants }>`
|
|
75
74
|
display: flex;
|
|
76
75
|
align-items: center;
|
|
77
76
|
justify-content: center;
|
|
78
|
-
margin-right: ${({ theme }) => theme.spacing['1']};
|
|
79
77
|
svg {
|
|
80
78
|
fill: ${({ variant, theme }): string => theme.colors[variant]};
|
|
81
79
|
}
|
|
@@ -122,13 +122,13 @@ const defaultListItems = [
|
|
|
122
122
|
icon: <AiOutlineBook />,
|
|
123
123
|
title: 'Documentation',
|
|
124
124
|
description: 'Learn how to integrate our tools with your app',
|
|
125
|
-
to: 'docs.takaro.io',
|
|
125
|
+
to: 'https://docs.takaro.io',
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
128
|
icon: <AiOutlineMenu />,
|
|
129
129
|
title: 'Api reference',
|
|
130
130
|
description: 'A complete API reference for our libraries',
|
|
131
|
-
to: 'https://api.
|
|
131
|
+
to: 'https://api.takaro.io/api.html',
|
|
132
132
|
},
|
|
133
133
|
/*
|
|
134
134
|
{
|
|
@@ -43,6 +43,10 @@ const Content = styled.div<{ expanded: boolean }>`
|
|
|
43
43
|
border-radius: ${({ theme }) => `0 0 ${theme.borderRadius.large} ${theme.borderRadius.large}`};
|
|
44
44
|
border-radius-top-left: 0;
|
|
45
45
|
border-radius-top-right: 0;
|
|
46
|
+
|
|
47
|
+
h4 {
|
|
48
|
+
margin-bottom: ${({ theme }) => theme.spacing['0_5']};
|
|
49
|
+
}
|
|
46
50
|
`;
|
|
47
51
|
|
|
48
52
|
export const DrawerSnack = forwardRef<HTMLDivElement, PropsWithChildren<CustomContentProps>>(function DrawerSnack(
|
|
@@ -29,6 +29,7 @@ export const ControlledDatePicker: FC<ControlledDatePickerProps> = (props) => {
|
|
|
29
29
|
description,
|
|
30
30
|
allowFutureDates = true,
|
|
31
31
|
allowPastDates = true,
|
|
32
|
+
canClear,
|
|
32
33
|
customDateFilter,
|
|
33
34
|
} = defaultsApplier(props);
|
|
34
35
|
|
|
@@ -91,6 +92,7 @@ export const ControlledDatePicker: FC<ControlledDatePickerProps> = (props) => {
|
|
|
91
92
|
format={format}
|
|
92
93
|
placeholder={placeholder}
|
|
93
94
|
mode={mode}
|
|
95
|
+
canClear={canClear}
|
|
94
96
|
/>
|
|
95
97
|
)}
|
|
96
98
|
{showError && error?.message && <ErrorMessage message={error.message} />}
|
|
@@ -253,7 +253,7 @@ export const AbsoluteSubmit = () => {
|
|
|
253
253
|
name="date"
|
|
254
254
|
required={false}
|
|
255
255
|
loading={false}
|
|
256
|
-
description={'The role will be automatically removed after this date'}
|
|
256
|
+
description={'The role will be automatically removed after this date.'}
|
|
257
257
|
popOverPlacement={'bottom'}
|
|
258
258
|
timePickerOptions={{ interval: 30 }}
|
|
259
259
|
allowPastDates={false}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FC, useLayoutEffect, useMemo, useState } from 'react';
|
|
2
|
-
import { Button, Popover } from '../../../../components';
|
|
1
|
+
import { FC, MouseEvent, useLayoutEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { Button, IconButton, Popover } from '../../../../components';
|
|
3
3
|
import { DateTime, DateTimeFormatOptions, Settings } from 'luxon';
|
|
4
4
|
import { dateFormats, timeFormats } from './formats';
|
|
5
5
|
import { GenericInputProps } from '../../InputProps';
|
|
@@ -8,6 +8,7 @@ import { TimePicker } from '../subcomponents/TimePicker';
|
|
|
8
8
|
import { Calendar } from '../subcomponents/Calendar';
|
|
9
9
|
import { RelativePicker, timeDirection } from '../subcomponents/RelativePicker';
|
|
10
10
|
import { Placement } from '@floating-ui/react';
|
|
11
|
+
import { AiOutlineClose as ClearIcon } from 'react-icons/ai';
|
|
11
12
|
|
|
12
13
|
interface TimePickerOptions {
|
|
13
14
|
/// Determines the interval between time options
|
|
@@ -51,6 +52,9 @@ export interface DatePickerProps {
|
|
|
51
52
|
|
|
52
53
|
/// Placeholder text for the input
|
|
53
54
|
placeholder?: string;
|
|
55
|
+
|
|
56
|
+
/// Can set field back to undefined
|
|
57
|
+
canClear?: boolean;
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
export type GenericDatePickerProps = GenericInputProps<string, HTMLInputElement> & DatePickerProps;
|
|
@@ -71,6 +75,7 @@ export const GenericDatePicker: FC<GenericDatePickerProps> = ({
|
|
|
71
75
|
format = DateTime.DATE_SHORT,
|
|
72
76
|
allowPastDates = true,
|
|
73
77
|
allowFutureDates = true,
|
|
78
|
+
canClear = false,
|
|
74
79
|
customDateFilter,
|
|
75
80
|
mode,
|
|
76
81
|
}) => {
|
|
@@ -172,11 +177,22 @@ export const GenericDatePicker: FC<GenericDatePickerProps> = ({
|
|
|
172
177
|
return renderPlaceholder();
|
|
173
178
|
};
|
|
174
179
|
|
|
180
|
+
const handleClear = (e: MouseEvent) => {
|
|
181
|
+
e.preventDefault();
|
|
182
|
+
e.stopPropagation();
|
|
183
|
+
if (onChange) {
|
|
184
|
+
onChange(null as any);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
175
188
|
return (
|
|
176
189
|
<Popover placement={popOverPlacement} open={open} onOpenChange={setOpen}>
|
|
177
|
-
<Popover.Trigger asChild>
|
|
190
|
+
<Popover.Trigger asChild readOnly={readOnly}>
|
|
178
191
|
<ResultContainer readOnly={readOnly} hasError={hasError} onClick={() => setOpen(!open)}>
|
|
179
|
-
{renderResult()}
|
|
192
|
+
<span>{renderResult()}</span>
|
|
193
|
+
{!readOnly && canClear && value && !open && (
|
|
194
|
+
<IconButton size="tiny" icon={<ClearIcon />} ariaLabel="clear" onClick={handleClear} />
|
|
195
|
+
)}
|
|
180
196
|
</ResultContainer>
|
|
181
197
|
</Popover.Trigger>
|
|
182
198
|
<Popover.Content>
|