@drivenets/design-system 0.8.0 → 0.9.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/CHANGELOG.md +22 -0
- package/dist/index.cjs +1559 -1074
- package/dist/index.d.cts +559 -135
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +559 -135
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1547 -1076
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +12 -11
- package/src/components/ds-autocomplete/ds-autocomplete.module.scss +0 -1
- package/src/components/ds-button/versions/ds-button-new/ds-button-new.module.scss +25 -9
- package/src/components/ds-button/versions/ds-button-new/ds-button-new.tsx +5 -5
- package/src/components/ds-button/versions/ds-button-new/ds-button-new.types.ts +11 -1
- package/src/components/ds-button/versions/ds-button-new/index.ts +4 -1
- package/src/components/ds-button-v3/ds-button-v3.module.scss +391 -0
- package/src/components/ds-button-v3/ds-button-v3.tsx +55 -0
- package/src/components/ds-button-v3/ds-button-v3.types.ts +49 -0
- package/src/components/ds-button-v3/index.ts +2 -0
- package/src/components/ds-comments-drawer/components/comments-filter-modal/comments-filter-modal.tsx +1 -1
- package/src/components/ds-comments-drawer/ds-comments-drawer.tsx +3 -9
- package/src/components/ds-date-picker/ds-date-picker.module.scss +10 -0
- package/src/components/ds-date-picker/ds-date-picker.tsx +4 -2
- package/src/components/ds-date-range-picker/ds-date-range-picker.tsx +2 -2
- package/src/components/ds-drawer/ds-drawer.tsx +6 -9
- package/src/components/ds-drawer/ds-drawer.types.ts +4 -2
- package/src/components/ds-form-control/ds-form-control.tsx +2 -3
- package/src/components/ds-panel/ds-panel.module.scss +4 -1
- package/src/components/ds-panel/ds-panel.tsx +8 -3
- package/src/components/ds-panel/ds-panel.types.ts +8 -1
- package/src/components/ds-panel/index.ts +4 -1
- package/src/components/ds-select/ds-select.module.scss +4 -1
- package/src/components/ds-split-button/ds-split-button.module.scss +99 -0
- package/src/components/ds-split-button/ds-split-button.tsx +49 -0
- package/src/components/ds-split-button/ds-split-button.types.ts +25 -0
- package/src/components/ds-split-button/index.ts +10 -0
- package/src/components/ds-stack/ds-stack.module.scss +4 -0
- package/src/components/ds-stack/ds-stack.tsx +35 -0
- package/src/components/ds-stack/ds-stack.types.ts +19 -0
- package/src/components/ds-stack/index.ts +18 -0
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx +2 -2
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.module.scss +5 -8
- package/src/components/ds-table/ds-table.module.scss +6 -0
- package/src/components/ds-table/ds-table.tsx +3 -0
- package/src/components/ds-time-picker/ds-time-picker.module.scss +11 -0
- package/src/components/ds-time-picker/ds-time-picker.tsx +32 -12
- package/src/components/ds-time-picker/ds-time-picker.types.ts +6 -0
- package/src/index.ts +4 -0
- package/src/styles/_breakpoints.module.scss +5 -0
- package/src/styles/_responsive.scss +13 -0
- package/src/styles/_variables.scss +2 -0
- package/src/styles/shared/_button.scss +2 -0
- package/src/styles/shared/_input.scss +3 -40
- package/src/utils/responsive.browser.test.ts +94 -0
- package/src/utils/responsive.ts +79 -0
- package/src/utils/responsive.unit.test.ts +54 -0
- package/src/utils/type-utils.ts +1 -0
- package/src/utils/use-controlled.browser.test.ts +6 -6
- package/src/utils/use-controlled.ts +1 -1
package/src/components/ds-comments-drawer/components/comments-filter-modal/comments-filter-modal.tsx
CHANGED
|
@@ -19,7 +19,7 @@ export const CommentsFilterModal = ({
|
|
|
19
19
|
availableAuthors,
|
|
20
20
|
availableLabels,
|
|
21
21
|
}: CommentsFilterModalProps) => {
|
|
22
|
-
const [selectedTab, setSelectedTab] = useState
|
|
22
|
+
const [selectedTab, setSelectedTab] = useState('statuses');
|
|
23
23
|
|
|
24
24
|
const handleStatusToggle = (status: 'unresolved' | 'resolved' | 'action-required', checked: boolean) => {
|
|
25
25
|
onFiltersChange({
|
|
@@ -7,13 +7,7 @@ import { DsButton } from '../ds-button';
|
|
|
7
7
|
import { DsIcon } from '../ds-icon';
|
|
8
8
|
import { DsTextInput } from '../ds-text-input';
|
|
9
9
|
import { DsTagFilter, type TagFilterItem } from '../ds-tag-filter';
|
|
10
|
-
import {
|
|
11
|
-
type CommentsFilterState,
|
|
12
|
-
initialFilterState,
|
|
13
|
-
applyFilters,
|
|
14
|
-
filtersToTags,
|
|
15
|
-
removeTag,
|
|
16
|
-
} from './comments-filters';
|
|
10
|
+
import { initialFilterState, applyFilters, filtersToTags, removeTag } from './comments-filters';
|
|
17
11
|
import { CommentsFilterModal } from './components/comments-filter-modal';
|
|
18
12
|
|
|
19
13
|
export const DsCommentsDrawer = ({
|
|
@@ -36,8 +30,8 @@ export const DsCommentsDrawer = ({
|
|
|
36
30
|
style,
|
|
37
31
|
}: DsCommentsDrawerProps) => {
|
|
38
32
|
const [isFilterModalOpen, setIsFilterModalOpen] = useState(false);
|
|
39
|
-
const [pendingFilters, setPendingFilters] = useState
|
|
40
|
-
const [appliedFilters, setAppliedFilters] = useState
|
|
33
|
+
const [pendingFilters, setPendingFilters] = useState(initialFilterState);
|
|
34
|
+
const [appliedFilters, setAppliedFilters] = useState(initialFilterState);
|
|
41
35
|
|
|
42
36
|
const authorsMap = new Map<string, string>();
|
|
43
37
|
const labelsSet = new Set<string>();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ChangeEvent, Fragment, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { DatePicker
|
|
2
|
+
import { DatePicker } from '@ark-ui/react/date-picker';
|
|
3
3
|
import { Portal } from '@ark-ui/react/portal';
|
|
4
4
|
import type { DsDatePickerProps } from './ds-date-picker.types';
|
|
5
5
|
import {
|
|
@@ -42,7 +42,7 @@ const DsDatePicker = ({
|
|
|
42
42
|
}: DsDatePickerProps) => {
|
|
43
43
|
const defaultValue = toIntlDate(_defaultValue);
|
|
44
44
|
|
|
45
|
-
const [value, setValue] = useControlled
|
|
45
|
+
const [value, setValue] = useControlled(
|
|
46
46
|
toIntlDate(_value),
|
|
47
47
|
onChange ? (v) => onChange(fromIntlDate(v)) : undefined,
|
|
48
48
|
defaultValue ?? null,
|
|
@@ -145,6 +145,7 @@ const DsDatePicker = ({
|
|
|
145
145
|
{showClearButton && (
|
|
146
146
|
<DatePicker.ClearTrigger asChild onClick={() => setValue(null)}>
|
|
147
147
|
<DsButton
|
|
148
|
+
className={styles.clearTrigger}
|
|
148
149
|
design="v1.2"
|
|
149
150
|
size="tiny"
|
|
150
151
|
buttonType="tertiary"
|
|
@@ -184,6 +185,7 @@ const DsDatePicker = ({
|
|
|
184
185
|
}}
|
|
185
186
|
min={isSameDay(value, min) ? _min : undefined}
|
|
186
187
|
max={isSameDay(value, max) ? _max : undefined}
|
|
188
|
+
hideClearButton={true}
|
|
187
189
|
disabled={disabled || !value}
|
|
188
190
|
readOnly={readOnly}
|
|
189
191
|
{...slotProps?.timePicker}
|
|
@@ -3,7 +3,7 @@ import { DsFormControl } from '../ds-form-control';
|
|
|
3
3
|
import { DsButton } from '../ds-button';
|
|
4
4
|
import { DsIcon } from '../ds-icon';
|
|
5
5
|
import { useControlled } from '../../utils/use-controlled';
|
|
6
|
-
import type {
|
|
6
|
+
import type { DsDateRangePickerProps } from './ds-date-range-picker.types';
|
|
7
7
|
import styles from './ds-date-range-picker.module.scss';
|
|
8
8
|
import { earlierDate, laterDate } from './ds-date-range-picker.utils';
|
|
9
9
|
|
|
@@ -24,7 +24,7 @@ const DsDateRangePicker = ({
|
|
|
24
24
|
locale,
|
|
25
25
|
slotProps,
|
|
26
26
|
}: DsDateRangePickerProps) => {
|
|
27
|
-
const [value, setValue] = useControlled
|
|
27
|
+
const [value, setValue] = useControlled(valueProp, onChange, defaultValue);
|
|
28
28
|
|
|
29
29
|
const [startDate, endDate] = value;
|
|
30
30
|
|
|
@@ -6,12 +6,8 @@ import type { DsDrawerProps } from './ds-drawer.types';
|
|
|
6
6
|
import styles from './ds-drawer.module.scss';
|
|
7
7
|
import { DsIcon } from '../ds-icon';
|
|
8
8
|
import { DsTypography } from '../ds-typography';
|
|
9
|
+
import { useResponsiveValue } from '../../utils/responsive';
|
|
9
10
|
|
|
10
|
-
/**
|
|
11
|
-
* Composable drawer component.
|
|
12
|
-
* Supports grid-based sizing, flexible positioning, and compound components.
|
|
13
|
-
* Use columns prop to control drawer width (1-12 grid columns).
|
|
14
|
-
*/
|
|
15
11
|
const DsDrawer = ({
|
|
16
12
|
open,
|
|
17
13
|
onOpenChange,
|
|
@@ -25,9 +21,12 @@ const DsDrawer = ({
|
|
|
25
21
|
className,
|
|
26
22
|
children,
|
|
27
23
|
}: DsDrawerProps) => {
|
|
24
|
+
const resolvedColumns = useResponsiveValue(columns);
|
|
25
|
+
|
|
28
26
|
const handleOpenChange = (details: { open: boolean }) => {
|
|
29
27
|
onOpenChange(details.open);
|
|
30
28
|
};
|
|
29
|
+
|
|
31
30
|
const Wrapper = portal ? Portal : Fragment;
|
|
32
31
|
|
|
33
32
|
return (
|
|
@@ -48,10 +47,8 @@ const DsDrawer = ({
|
|
|
48
47
|
styles.drawer,
|
|
49
48
|
styles[`position-${position}`],
|
|
50
49
|
className,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
54
|
-
styles[`cols-${String(columns)}`],
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
51
|
+
styles[`cols-${resolvedColumns}`],
|
|
55
52
|
)}
|
|
56
53
|
>
|
|
57
54
|
<div className={styles.content}>{children}</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import type { UseDialogProps as DialogProps } from '@ark-ui/react/dialog';
|
|
3
|
+
import type { ResponsiveValue } from '../../utils/responsive';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Available positions for the drawer
|
|
@@ -20,10 +21,11 @@ export interface DsDrawerProps extends Pick<DialogProps, 'closeOnEscape' | 'clos
|
|
|
20
21
|
*/
|
|
21
22
|
onOpenChange: (open: boolean) => void;
|
|
22
23
|
/**
|
|
23
|
-
* Number of grid columns the drawer should span (1-12)
|
|
24
|
+
* Number of grid columns the drawer should span (1-12).
|
|
25
|
+
* Accepts a responsive value, e.g. `{ lg: 4, md: 6 }`.
|
|
24
26
|
* @default 4
|
|
25
27
|
*/
|
|
26
|
-
columns?: DsDrawerColumns
|
|
28
|
+
columns?: ResponsiveValue<DsDrawerColumns>;
|
|
27
29
|
/**
|
|
28
30
|
* Position of the drawer
|
|
29
31
|
* @default 'end'
|
|
@@ -63,9 +63,8 @@ const DsFormControl = ({
|
|
|
63
63
|
styles.container,
|
|
64
64
|
className,
|
|
65
65
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
status && message && styles[status],
|
|
66
|
+
// Casting because `info` doesn't have its own classname
|
|
67
|
+
status && message && styles[status as keyof typeof styles],
|
|
69
68
|
)}
|
|
70
69
|
style={style}
|
|
71
70
|
>
|
|
@@ -3,7 +3,7 @@ import * as Collapsible from '@radix-ui/react-collapsible';
|
|
|
3
3
|
import classnames from 'classnames';
|
|
4
4
|
import styles from './ds-panel.module.scss';
|
|
5
5
|
import { DsIcon } from '../ds-icon';
|
|
6
|
-
import type {
|
|
6
|
+
import type { DsPanelBaseProps, DsPanelCollapseButtonProps } from './ds-panel.types';
|
|
7
7
|
|
|
8
8
|
function useDraggable(enabled: boolean) {
|
|
9
9
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
@@ -84,20 +84,24 @@ function useDraggable(enabled: boolean) {
|
|
|
84
84
|
return rootRef;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
export function
|
|
87
|
+
export function DsPanelBase({
|
|
88
88
|
open,
|
|
89
89
|
onOpenChange,
|
|
90
90
|
children,
|
|
91
91
|
className,
|
|
92
|
+
style,
|
|
92
93
|
slotProps,
|
|
93
94
|
variant = 'docked',
|
|
95
|
+
width,
|
|
94
96
|
draggable = false,
|
|
95
97
|
disablePadding = false,
|
|
96
98
|
...props
|
|
97
|
-
}:
|
|
99
|
+
}: DsPanelBaseProps) {
|
|
98
100
|
const isDraggable = variant === 'floating' && draggable;
|
|
99
101
|
const rootRef = useDraggable(isDraggable);
|
|
100
102
|
|
|
103
|
+
const rootStyle = width ? { ...style, width } : style;
|
|
104
|
+
|
|
101
105
|
return (
|
|
102
106
|
<Collapsible.Root
|
|
103
107
|
ref={rootRef}
|
|
@@ -108,6 +112,7 @@ export function DsPanel({
|
|
|
108
112
|
[styles.variantFloating]: variant === 'floating',
|
|
109
113
|
[styles.disablePadding]: disablePadding,
|
|
110
114
|
})}
|
|
115
|
+
style={rootStyle}
|
|
111
116
|
{...props}
|
|
112
117
|
>
|
|
113
118
|
<DsPanelCollapseButton {...slotProps?.collapseButton} />
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type * as Collapsible from '@radix-ui/react-collapsible';
|
|
2
2
|
|
|
3
|
+
import type { ResponsiveValue } from '../../utils/responsive';
|
|
4
|
+
|
|
3
5
|
export type DsPanelVariant = 'docked' | 'floating';
|
|
4
6
|
|
|
5
|
-
export type
|
|
7
|
+
export type DsPanelBaseProps = Omit<Collapsible.CollapsibleProps, 'onOpenChange'> & {
|
|
6
8
|
variant?: DsPanelVariant;
|
|
9
|
+
width?: number;
|
|
7
10
|
draggable?: boolean;
|
|
8
11
|
disablePadding?: boolean;
|
|
9
12
|
slotProps?: {
|
|
@@ -12,6 +15,10 @@ export type DsPanelProps = Omit<Collapsible.CollapsibleProps, 'onOpenChange'> &
|
|
|
12
15
|
onOpenChange?: (open: boolean) => void;
|
|
13
16
|
};
|
|
14
17
|
|
|
18
|
+
export type DsPanelProps = Omit<DsPanelBaseProps, 'width'> & {
|
|
19
|
+
width?: ResponsiveValue<number>;
|
|
20
|
+
};
|
|
21
|
+
|
|
15
22
|
export type DsPanelCollapseButtonProps = {
|
|
16
23
|
onClick?: () => void;
|
|
17
24
|
collapsed?: boolean;
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { withResponsiveProps } from '../../utils/responsive';
|
|
2
|
+
import { DsPanelBase } from './ds-panel';
|
|
3
|
+
|
|
4
|
+
export const DsPanel = withResponsiveProps(DsPanelBase, ['width']);
|
|
2
5
|
export type { DsPanelProps, DsPanelVariant, DsPanelCollapseButtonProps } from './ds-panel.types';
|
|
@@ -53,8 +53,11 @@
|
|
|
53
53
|
@include typography.ellipsis;
|
|
54
54
|
grid-column: 1;
|
|
55
55
|
grid-row: 1;
|
|
56
|
-
color: var(--color-font-secondary);
|
|
57
56
|
text-align: start;
|
|
57
|
+
|
|
58
|
+
.trigger:not([data-disabled]) & {
|
|
59
|
+
color: var(--color-font-secondary);
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
.multiSelectItemsContainer {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
@use '../../styles/shared/button' as button;
|
|
2
|
+
|
|
3
|
+
$highlighted-z-index: 1;
|
|
4
|
+
$divider-z-index: $highlighted-z-index + 1;
|
|
5
|
+
$divider-width: 1px;
|
|
6
|
+
$border-width: 1px;
|
|
7
|
+
|
|
8
|
+
@mixin when-button-disabled {
|
|
9
|
+
.root:has(.actionButton:disabled) & {
|
|
10
|
+
@content;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@mixin when-select-disabled {
|
|
15
|
+
.root:has(.select[data-disabled]) & {
|
|
16
|
+
@content;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@mixin when-button-highlighted {
|
|
21
|
+
.root:has(.actionButton:not(:disabled):is(:hover, :focus-visible, :active, [data-selected='true'])) & {
|
|
22
|
+
@content;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@mixin when-select-highlighted {
|
|
27
|
+
.root:has(
|
|
28
|
+
.select:not([data-disabled]):is(:hover, :active, [data-state='open']),
|
|
29
|
+
.select:not([data-disabled]) :focus-visible
|
|
30
|
+
)
|
|
31
|
+
& {
|
|
32
|
+
@content;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.root {
|
|
37
|
+
display: inline-flex;
|
|
38
|
+
|
|
39
|
+
.actionButton {
|
|
40
|
+
border-top-right-radius: 0;
|
|
41
|
+
border-bottom-right-radius: 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.actionButton {
|
|
46
|
+
@include when-button-highlighted {
|
|
47
|
+
z-index: $highlighted-z-index;
|
|
48
|
+
transition: border-color button.$transition-duration-quick;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&:not(:disabled):is(:hover, :active, [data-selected='true']) {
|
|
52
|
+
border-right-color: var(--border-border-secondary-hover);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&:not(:disabled):focus-visible {
|
|
56
|
+
border-right-color: var(--border-border-inverse);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.select {
|
|
61
|
+
margin-left: -$divider-width;
|
|
62
|
+
border-top-left-radius: 0;
|
|
63
|
+
border-bottom-left-radius: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.dividerAnchor {
|
|
67
|
+
position: relative;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.dividerWrapper {
|
|
71
|
+
position: absolute;
|
|
72
|
+
top: $border-width;
|
|
73
|
+
bottom: $border-width;
|
|
74
|
+
left: -$divider-width;
|
|
75
|
+
z-index: $divider-z-index;
|
|
76
|
+
width: $divider-width;
|
|
77
|
+
padding: var(--spacing-3xs) 0;
|
|
78
|
+
background-color: var(--background-background);
|
|
79
|
+
|
|
80
|
+
@include when-button-highlighted {
|
|
81
|
+
display: none;
|
|
82
|
+
}
|
|
83
|
+
@include when-select-highlighted {
|
|
84
|
+
display: none;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.divider {
|
|
89
|
+
background-color: var(--color-border-secondary);
|
|
90
|
+
width: $divider-width;
|
|
91
|
+
height: 100%;
|
|
92
|
+
|
|
93
|
+
@include when-button-disabled {
|
|
94
|
+
background-color: var(--border-border-disabled);
|
|
95
|
+
}
|
|
96
|
+
@include when-select-disabled {
|
|
97
|
+
background-color: var(--border-border-disabled);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { DsSelect, type SelectSize } from '../ds-select';
|
|
3
|
+
import styles from './ds-split-button.module.scss';
|
|
4
|
+
import type { DsSplitButtonProps, SplitButtonSize } from './ds-split-button.types';
|
|
5
|
+
import { DsButtonV3 } from '../ds-button-v3';
|
|
6
|
+
|
|
7
|
+
const DsSplitButton = ({
|
|
8
|
+
ref,
|
|
9
|
+
className,
|
|
10
|
+
style,
|
|
11
|
+
size = 'medium',
|
|
12
|
+
disabled,
|
|
13
|
+
slotProps,
|
|
14
|
+
}: DsSplitButtonProps) => {
|
|
15
|
+
const { className: buttonClassName, disabled: buttonDisabled, ...buttonProps } = slotProps.button;
|
|
16
|
+
|
|
17
|
+
const { className: selectClassName, disabled: selectDisabled, ...selectProps } = slotProps.select;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div ref={ref} className={classNames(styles.root, className)} style={style}>
|
|
21
|
+
<DsButtonV3
|
|
22
|
+
{...buttonProps}
|
|
23
|
+
variant="secondary"
|
|
24
|
+
size={size}
|
|
25
|
+
disabled={buttonDisabled ?? disabled}
|
|
26
|
+
className={classNames(styles.actionButton, buttonClassName)}
|
|
27
|
+
/>
|
|
28
|
+
|
|
29
|
+
<div className={styles.dividerAnchor}>
|
|
30
|
+
<div className={styles.dividerWrapper}>
|
|
31
|
+
<div className={styles.divider} />
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<DsSelect
|
|
36
|
+
{...selectProps}
|
|
37
|
+
size={getSelectSize(size)}
|
|
38
|
+
disabled={selectDisabled ?? disabled}
|
|
39
|
+
className={classNames(styles.select, selectClassName)}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const getSelectSize = (size: SplitButtonSize): SelectSize => {
|
|
46
|
+
return size === 'medium' ? 'default' : 'small';
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default DsSplitButton;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CSSProperties, Ref } from 'react';
|
|
2
|
+
import type { DsButtonV3Props } from '../ds-button-v3';
|
|
3
|
+
import type { DsSelectProps } from '../ds-select';
|
|
4
|
+
import type { DistributiveOmit } from '../../utils/type-utils';
|
|
5
|
+
|
|
6
|
+
export const splitButtonSizes = ['medium', 'small'] as const;
|
|
7
|
+
export type SplitButtonSize = (typeof splitButtonSizes)[number];
|
|
8
|
+
|
|
9
|
+
type ButtonSlotProps = Omit<DsButtonV3Props, 'variant' | 'color' | 'size'>;
|
|
10
|
+
|
|
11
|
+
type SelectSlotProps = DistributiveOmit<DsSelectProps, 'size'>;
|
|
12
|
+
|
|
13
|
+
export interface DsSplitButtonSlotProps {
|
|
14
|
+
button: ButtonSlotProps;
|
|
15
|
+
select: SelectSlotProps;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DsSplitButtonProps {
|
|
19
|
+
ref?: Ref<HTMLDivElement>;
|
|
20
|
+
className?: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
size?: SplitButtonSize;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
slotProps: DsSplitButtonSlotProps;
|
|
25
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import { withResponsiveProps } from '../../utils/responsive';
|
|
3
|
+
import DsSplitButtonBase from './ds-split-button';
|
|
4
|
+
export { type DsSplitButtonSlotProps, splitButtonSizes } from './ds-split-button.types';
|
|
5
|
+
|
|
6
|
+
export const DsSplitButton = withResponsiveProps(DsSplitButtonBase, ['size']);
|
|
7
|
+
|
|
8
|
+
DsSplitButton.displayName = 'DsSplitButton';
|
|
9
|
+
|
|
10
|
+
export type DsSplitButtonProps = ComponentProps<typeof DsSplitButton>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
|
|
3
|
+
import styles from './ds-stack.module.scss';
|
|
4
|
+
import type { DsStackProps } from './ds-stack.types';
|
|
5
|
+
|
|
6
|
+
export const DsStack = ({
|
|
7
|
+
direction,
|
|
8
|
+
gap,
|
|
9
|
+
alignItems,
|
|
10
|
+
justifyContent,
|
|
11
|
+
flex,
|
|
12
|
+
flexWrap,
|
|
13
|
+
width,
|
|
14
|
+
children,
|
|
15
|
+
className,
|
|
16
|
+
style,
|
|
17
|
+
ref,
|
|
18
|
+
}: DsStackProps) => {
|
|
19
|
+
const layoutStyle: React.CSSProperties = {
|
|
20
|
+
flexDirection: direction,
|
|
21
|
+
gap,
|
|
22
|
+
alignItems,
|
|
23
|
+
justifyContent,
|
|
24
|
+
flex,
|
|
25
|
+
flexWrap,
|
|
26
|
+
width,
|
|
27
|
+
...style,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div ref={ref} className={classNames(styles.root, className)} style={layoutStyle}>
|
|
32
|
+
{children}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Properties } from 'csstype';
|
|
2
|
+
|
|
3
|
+
type CSSProps = Properties<string | number>;
|
|
4
|
+
import type { CSSProperties, ReactNode, Ref } from 'react';
|
|
5
|
+
|
|
6
|
+
export interface DsStackProps {
|
|
7
|
+
direction?: CSSProps['flexDirection'];
|
|
8
|
+
gap?: CSSProps['gap'];
|
|
9
|
+
alignItems?: CSSProps['alignItems'];
|
|
10
|
+
justifyContent?: CSSProps['justifyContent'];
|
|
11
|
+
flex?: CSSProps['flex'];
|
|
12
|
+
flexWrap?: CSSProps['flexWrap'];
|
|
13
|
+
width?: CSSProps['width'];
|
|
14
|
+
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
style?: CSSProperties;
|
|
18
|
+
ref?: Ref<HTMLDivElement>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
|
|
3
|
+
import { withResponsiveProps } from '../../utils/responsive';
|
|
4
|
+
import { DsStack as DsStackBase } from './ds-stack';
|
|
5
|
+
|
|
6
|
+
export const DsStack = withResponsiveProps(DsStackBase, [
|
|
7
|
+
'direction',
|
|
8
|
+
'gap',
|
|
9
|
+
'alignItems',
|
|
10
|
+
'justifyContent',
|
|
11
|
+
'flex',
|
|
12
|
+
'flexWrap',
|
|
13
|
+
'width',
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
DsStack.displayName = 'DsStack';
|
|
17
|
+
|
|
18
|
+
export type DsStackProps = ComponentProps<typeof DsStack>;
|
package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx
CHANGED
|
@@ -16,8 +16,8 @@ export const DsTableBodyVirtualized = <TData,>({
|
|
|
16
16
|
onScroll,
|
|
17
17
|
rowSelection,
|
|
18
18
|
}: DsTableBodyVirtualizedProps<TData>) => {
|
|
19
|
-
const rowsMapRef = useRef
|
|
20
|
-
const rowHeightsMapRef = useRef
|
|
19
|
+
const rowsMapRef = useRef(new Map<string, HTMLTableRowElement>());
|
|
20
|
+
const rowHeightsMapRef = useRef(new Map<string, number>());
|
|
21
21
|
|
|
22
22
|
const { rows } = table.getRowModel();
|
|
23
23
|
|
package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.module.scss
CHANGED
|
@@ -58,18 +58,15 @@
|
|
|
58
58
|
gap: 8px;
|
|
59
59
|
|
|
60
60
|
> .actionButton {
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-direction: column;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
gap: var(--spacing-3xs);
|
|
61
66
|
border-right: 1px solid var(--neutral-6);
|
|
62
67
|
width: 68px;
|
|
63
68
|
height: 48px;
|
|
64
69
|
border-radius: 0;
|
|
65
|
-
|
|
66
|
-
> .actionButtonContent {
|
|
67
|
-
display: flex;
|
|
68
|
-
flex-direction: column;
|
|
69
|
-
align-items: center;
|
|
70
|
-
justify-content: center;
|
|
71
|
-
gap: 4px;
|
|
72
|
-
}
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
> .actionButton:first-child {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
@use '../../styles/utilities' as utils;
|
|
3
3
|
@use './styles/variables' as vars;
|
|
4
4
|
|
|
5
|
+
$bulk-actions-height: 60px;
|
|
6
|
+
|
|
5
7
|
.container {
|
|
6
8
|
border-radius: vars.$border-radius;
|
|
7
9
|
border-width: vars.$border-width;
|
|
@@ -45,3 +47,7 @@
|
|
|
45
47
|
height: vars.$virtualized-height;
|
|
46
48
|
overflow: auto;
|
|
47
49
|
}
|
|
50
|
+
|
|
51
|
+
.bulkActionsVisible {
|
|
52
|
+
padding-bottom: $bulk-actions-height;
|
|
53
|
+
}
|
|
@@ -204,6 +204,8 @@ const DsTable = <TData extends { id: string }, TValue>({
|
|
|
204
204
|
.map(([key]) => rowsById[key]?.original)
|
|
205
205
|
.filter((v) => !!v);
|
|
206
206
|
|
|
207
|
+
const isBulkActionsVisible = selectable && actions.length > 0 && selectedRows.length > 0;
|
|
208
|
+
|
|
207
209
|
const contextValue: DsTableContextType<TData, TValue> = {
|
|
208
210
|
stickyHeader,
|
|
209
211
|
bordered,
|
|
@@ -230,6 +232,7 @@ const DsTable = <TData extends { id: string }, TValue>({
|
|
|
230
232
|
styles.container,
|
|
231
233
|
!virtualized && styles.dataTableContainer,
|
|
232
234
|
virtualized && styles.virtualizedContainer,
|
|
235
|
+
isBulkActionsVisible && styles.bulkActionsVisible,
|
|
233
236
|
className,
|
|
234
237
|
)}
|
|
235
238
|
>
|