@drivenets/design-system 0.9.1 → 0.10.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 +1065 -594
- package/dist/index.d.cts +1797 -635
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1800 -638
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1072 -603
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +11 -13
- package/src/components/ds-breadcrumb/ds-breadcrumb.types.ts +40 -6
- package/src/components/ds-button/ds-button.types.ts +13 -2
- package/src/components/ds-button-v3/ds-button-v3.module.scss +105 -106
- package/src/components/ds-button-v3/ds-button-v3.types.ts +7 -0
- package/src/components/ds-card/ds-card.types.ts +3 -1
- package/src/components/ds-checkbox/ds-checkbox.module.scss +106 -123
- package/src/components/ds-checkbox/ds-checkbox.tsx +24 -35
- package/src/components/ds-checkbox/ds-checkbox.types.ts +12 -11
- package/src/components/ds-checkbox-group/ds-checkbox-group.module.scss +13 -0
- package/src/components/ds-checkbox-group/ds-checkbox-group.tsx +20 -0
- package/src/components/ds-checkbox-group/ds-checkbox-group.types.ts +8 -0
- package/src/components/ds-checkbox-group/hooks/index.ts +6 -0
- package/src/components/ds-checkbox-group/hooks/use-checkbox-select-all.ts +65 -0
- package/src/components/ds-checkbox-group/index.ts +3 -0
- package/src/components/ds-comment-bubble/components/ds-comment-thread/ds-comment-thread.types.ts +26 -0
- package/src/components/ds-comment-bubble/components/ds-thread-item/ds-thread-item.types.ts +38 -0
- package/src/components/ds-comment-bubble/ds-comment-bubble.types.ts +78 -0
- package/src/components/ds-comment-card/ds-comment-card.types.ts +114 -0
- package/src/components/ds-comment-indicator/ds-comment-indicator.types.ts +26 -0
- package/src/components/ds-comments-drawer/comments-filters.types.ts +33 -0
- package/src/components/ds-comments-drawer/components/comments-filter-modal/comments-filter-modal.types.ts +37 -1
- package/src/components/ds-comments-drawer/ds-comments-drawer.types.ts +64 -0
- package/src/components/ds-date-input/ds-date-input.types.ts +23 -0
- package/src/components/ds-date-picker/ds-date-picker.tsx +3 -0
- package/src/components/ds-date-picker/ds-date-picker.types.ts +20 -0
- package/src/components/ds-date-range-picker/ds-date-range-picker.types.ts +28 -0
- package/src/components/ds-dialog/ds-dialog.types.ts +10 -1
- package/src/components/ds-dropdown-menu/ds-dropdown-menu.types.ts +24 -0
- package/src/components/ds-file-upload/components/file-upload/file-upload.types.ts +1 -0
- package/src/components/ds-file-upload/ds-file-upload-api.types.ts +55 -0
- package/src/components/ds-form-control/ds-form-control.types.ts +3 -0
- package/src/components/ds-grid/ds-grid.tsx +29 -12
- package/src/components/ds-grid/ds-grid.types.ts +16 -13
- package/src/components/ds-grid/index.ts +10 -2
- package/src/components/ds-icon/custom-icons/index.ts +2 -0
- package/src/components/ds-icon/custom-icons/special-leading-icon.tsx +11 -0
- package/src/components/ds-icon/ds-icon.tsx +10 -4
- package/src/components/ds-icon/ds-icon.types.ts +30 -0
- package/src/components/ds-key-value-pair/ds-key-value-pair.types.ts +12 -2
- package/src/components/ds-modal/ds-modal.types.ts +16 -0
- package/src/components/ds-panel/ds-panel.types.ts +39 -0
- package/src/components/ds-radio-group/ds-radio-group.module.scss +58 -56
- package/src/components/ds-radio-group/ds-radio-group.tsx +35 -28
- package/src/components/ds-radio-group/ds-radio-group.types.ts +38 -7
- package/src/components/ds-segment-group/ds-segment-group.types.ts +17 -0
- package/src/components/ds-select/ds-select.types.ts +32 -0
- package/src/components/ds-split-button/ds-split-button.module.scss +7 -7
- package/src/components/ds-split-button/ds-split-button.types.ts +28 -0
- package/src/components/ds-stack/ds-stack.types.ts +23 -0
- package/src/components/ds-stepper/ds-stepper.types.ts +34 -1
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.types.ts +27 -0
- package/src/components/ds-table/components/ds-table-row-expandable-cell/ds-table-row-expandable-cell.types.ts +10 -0
- package/src/components/ds-table/components/ds-table-row-selectable-cell/ds-table-row-selectable-cell.types.ts +11 -0
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.types.ts +27 -0
- package/src/components/ds-table/filters/types/filter-adapter.types.ts +6 -0
- package/src/components/ds-tag/ds-tag.types.ts +6 -0
- package/src/components/ds-tag-filter/ds-tag-filter.types.ts +16 -0
- package/src/components/ds-text-input/ds-text-input.types.ts +3 -0
- package/src/components/ds-time-picker/components/time-item/time-item.types.ts +19 -0
- package/src/components/ds-time-picker/components/time-scroller/time-scroller.types.ts +29 -0
- package/src/components/ds-time-picker/ds-time-picker.module.scss +7 -0
- package/src/components/ds-time-picker/ds-time-picker.tsx +8 -1
- package/src/components/ds-time-picker/ds-time-picker.types.ts +80 -0
- package/src/components/ds-tooltip/ds-tooltip.types.ts +6 -0
- package/src/components/ds-tree/ds-tree.types.ts +84 -2
- package/src/components/ds-typography/ds-typography.config.ts +46 -27
- package/src/components/ds-typography/ds-typography.tsx +22 -7
- package/src/components/ds-typography/ds-typography.types.ts +15 -4
- package/src/components/ds-workspace/ds-workspace.module.scss +55 -0
- package/src/components/ds-workspace/ds-workspace.tsx +37 -0
- package/src/components/ds-workspace/ds-workspace.types.ts +17 -0
- package/src/components/ds-workspace/index.ts +8 -0
- package/src/index.ts +2 -0
- package/src/styles/_grid.scss +2 -2
- package/src/styles/_root_new.scss +449 -0
- package/src/styles/shared/_input.scss +0 -2
- package/src/styles/styles.scss +1 -0
- package/src/styles/_root_updated.scss +0 -593
|
@@ -1,161 +1,144 @@
|
|
|
1
|
+
@use '../../styles/root_new';
|
|
1
2
|
@use '../../styles/typography';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
$checkbox-size: 16px;
|
|
5
|
+
$checkbox-border-radius: 2px;
|
|
6
|
+
$checkbox-focus-ring-width: 2px;
|
|
7
|
+
$transition-duration: 0.2s;
|
|
8
|
+
|
|
9
|
+
.root {
|
|
4
10
|
position: relative;
|
|
5
|
-
display: flex;
|
|
6
|
-
align-items:
|
|
7
|
-
gap:
|
|
8
|
-
padding
|
|
9
|
-
border:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
&:has([data-disabled]) {
|
|
13
|
-
cursor: not-allowed;
|
|
14
|
-
pointer-events: none;
|
|
11
|
+
display: inline-flex;
|
|
12
|
+
align-items: flex-start;
|
|
13
|
+
gap: var(--3xs);
|
|
14
|
+
padding: var(--4xs);
|
|
15
|
+
border-radius: $checkbox-border-radius;
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
transition: background-color $transition-duration ease-in-out;
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
&:hover,
|
|
20
|
+
&[data-hover],
|
|
21
|
+
&[data-focus-visible] {
|
|
22
|
+
background-color: var(--background-secondary-hover);
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
&[data-focus-visible] {
|
|
26
|
+
outline: $checkbox-focus-ring-width solid var(--background-primary-hover);
|
|
27
|
+
outline-offset: 0;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
.control {
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
flex-shrink: 0;
|
|
35
|
+
width: $checkbox-size;
|
|
36
|
+
height: $checkbox-size;
|
|
37
|
+
border: 1px solid var(--secondary-400);
|
|
38
|
+
border-radius: $checkbox-border-radius;
|
|
39
|
+
background-color: transparent;
|
|
40
|
+
transition:
|
|
41
|
+
background-color $transition-duration ease-in-out,
|
|
42
|
+
border-color $transition-duration ease-in-out;
|
|
27
43
|
}
|
|
28
|
-
}
|
|
29
44
|
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
border-radius: 2px;
|
|
34
|
-
display: flex;
|
|
35
|
-
align-items: center;
|
|
36
|
-
justify-content: center;
|
|
37
|
-
transition: all 0.2s ease-in-out;
|
|
38
|
-
cursor: pointer;
|
|
39
|
-
|
|
40
|
-
&[data-disabled] {
|
|
41
|
-
border-color: var(--color-background-disable);
|
|
42
|
-
pointer-events: none;
|
|
43
|
-
|
|
44
|
-
&[data-state='unchecked'] {
|
|
45
|
-
.checkboxWrapper {
|
|
46
|
-
border-color: var(--color-background-disable);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
45
|
+
.indicator {
|
|
46
|
+
line-height: 0;
|
|
47
|
+
color: var(--icon-inverse);
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
border-color: var(--color-background-disable);
|
|
54
|
-
background-color: var(--color-background-disable);
|
|
55
|
-
}
|
|
49
|
+
svg {
|
|
50
|
+
width: 100%;
|
|
51
|
+
height: 100%;
|
|
56
52
|
}
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
&:hover,
|
|
66
|
-
&:focus-visible {
|
|
67
|
-
background: var(--color-background-action-secondary-hover);
|
|
68
|
-
}
|
|
55
|
+
.labelColumn {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
gap: var(--4xs);
|
|
59
|
+
min-width: 0;
|
|
69
60
|
}
|
|
70
61
|
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
|
|
74
|
-
|
|
62
|
+
.label {
|
|
63
|
+
@include typography.body-sm-reg;
|
|
64
|
+
line-height: normal;
|
|
65
|
+
color: var(--font-main);
|
|
66
|
+
}
|
|
75
67
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
.labelInfo {
|
|
69
|
+
@include typography.body-xs-reg;
|
|
70
|
+
@include typography.ellipsis;
|
|
71
|
+
color: var(--font-secondary);
|
|
80
72
|
}
|
|
81
73
|
|
|
74
|
+
&[data-state='checked'],
|
|
82
75
|
&[data-state='indeterminate'] {
|
|
83
|
-
.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
&:hover,
|
|
89
|
-
&:focus-visible {
|
|
90
|
-
background: var(--color-background-action-secondary-hover);
|
|
76
|
+
.control {
|
|
77
|
+
background-color: var(--background-primary);
|
|
78
|
+
border-color: var(--background-primary);
|
|
91
79
|
}
|
|
92
80
|
}
|
|
93
81
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
justify-content: center;
|
|
98
|
-
align-items: center;
|
|
99
|
-
height: 16px;
|
|
100
|
-
width: 16px;
|
|
101
|
-
margin: var(--spacing-4xs);
|
|
102
|
-
border: 2px solid transparent;
|
|
103
|
-
border-radius: 2px;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
82
|
+
&[data-disabled] {
|
|
83
|
+
cursor: not-allowed;
|
|
84
|
+
background-color: transparent;
|
|
106
85
|
|
|
107
|
-
.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
display: flex;
|
|
111
|
-
align-items: center;
|
|
112
|
-
justify-content: center;
|
|
86
|
+
.label {
|
|
87
|
+
color: var(--font-disabled);
|
|
88
|
+
}
|
|
113
89
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
}
|
|
90
|
+
.labelInfo {
|
|
91
|
+
color: var(--font-disabled);
|
|
92
|
+
}
|
|
119
93
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
94
|
+
&[data-state='checked'],
|
|
95
|
+
&[data-state='indeterminate'] {
|
|
96
|
+
.label {
|
|
97
|
+
color: var(--font-disabled);
|
|
98
|
+
}
|
|
125
99
|
|
|
126
|
-
.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
width: 100%;
|
|
100
|
+
.control {
|
|
101
|
+
background-color: var(--background-disable);
|
|
102
|
+
border-color: var(--background-disable);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
133
106
|
}
|
|
134
107
|
|
|
135
|
-
|
|
136
|
-
|
|
108
|
+
// Overlay the native input over the control so `getByRole('checkbox')` clicks
|
|
109
|
+
// land on a real interactive surface. Ark applies `visuallyHiddenStyle` inline
|
|
110
|
+
// (1x1, clipped, off-screen) which Playwright refuses to click; `!important`
|
|
111
|
+
// is required to beat inline-style specificity.
|
|
112
|
+
.hiddenInput {
|
|
113
|
+
position: absolute !important;
|
|
114
|
+
inset-block-start: var(--4xs) !important;
|
|
115
|
+
inset-inline-start: var(--4xs) !important;
|
|
116
|
+
width: $checkbox-size !important;
|
|
117
|
+
height: $checkbox-size !important;
|
|
118
|
+
margin: 0 !important;
|
|
119
|
+
padding: 0 !important;
|
|
120
|
+
clip: auto !important;
|
|
121
|
+
overflow: visible !important;
|
|
122
|
+
opacity: 0 !important;
|
|
123
|
+
cursor: inherit !important;
|
|
137
124
|
}
|
|
138
125
|
|
|
139
126
|
.warning {
|
|
140
|
-
&:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
127
|
+
&:hover,
|
|
128
|
+
&[data-hover],
|
|
129
|
+
&[data-focus-visible] {
|
|
130
|
+
background-color: var(--background-warning);
|
|
145
131
|
}
|
|
146
132
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
background-color: var(--color-background-warning-strong);
|
|
153
|
-
}
|
|
133
|
+
&[data-state='checked'],
|
|
134
|
+
&[data-state='indeterminate'] {
|
|
135
|
+
.label {
|
|
136
|
+
color: var(--font-warning);
|
|
137
|
+
}
|
|
154
138
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
139
|
+
.control {
|
|
140
|
+
background-color: var(--background-warning-strong);
|
|
141
|
+
border-color: var(--background-warning-strong);
|
|
159
142
|
}
|
|
160
143
|
}
|
|
161
144
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useId } from 'react';
|
|
3
|
-
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
1
|
+
import { Checkbox } from '@ark-ui/react/checkbox';
|
|
4
2
|
import classNames from 'classnames';
|
|
5
3
|
import styles from './ds-checkbox.module.scss';
|
|
6
4
|
import type { DsCheckboxProps } from './ds-checkbox.types';
|
|
@@ -9,47 +7,38 @@ import { DsIcon } from '../ds-icon';
|
|
|
9
7
|
/**
|
|
10
8
|
* Design system Checkbox component
|
|
11
9
|
*/
|
|
12
|
-
const DsCheckbox
|
|
13
|
-
id,
|
|
10
|
+
const DsCheckbox = ({
|
|
14
11
|
variant = 'default',
|
|
15
12
|
label,
|
|
16
13
|
labelInfo,
|
|
17
14
|
className,
|
|
18
|
-
checked,
|
|
19
|
-
defaultChecked,
|
|
20
15
|
onCheckedChange,
|
|
16
|
+
value,
|
|
21
17
|
...props
|
|
22
|
-
}) => {
|
|
23
|
-
const generatedId = useId();
|
|
24
|
-
const checkboxId = id || generatedId;
|
|
25
|
-
|
|
18
|
+
}: DsCheckboxProps) => {
|
|
26
19
|
return (
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</CheckboxPrimitive.Root>
|
|
46
|
-
{label && (
|
|
47
|
-
<label className={styles.label} htmlFor={checkboxId}>
|
|
48
|
-
{label}
|
|
20
|
+
<Checkbox.Root
|
|
21
|
+
className={classNames(styles.root, variant === 'warning' && styles.warning, className)}
|
|
22
|
+
onCheckedChange={(details) => onCheckedChange?.(details.checked)}
|
|
23
|
+
{...props}
|
|
24
|
+
value={value === undefined ? undefined : String(value)}
|
|
25
|
+
>
|
|
26
|
+
<Checkbox.Control className={styles.control}>
|
|
27
|
+
<Checkbox.Indicator className={styles.indicator}>
|
|
28
|
+
<DsIcon icon="check_small" size="tiny" variant="rounded" />
|
|
29
|
+
</Checkbox.Indicator>
|
|
30
|
+
<Checkbox.Indicator className={styles.indicator} indeterminate>
|
|
31
|
+
<DsIcon icon="check_indeterminate_small" size="tiny" variant="rounded" />
|
|
32
|
+
</Checkbox.Indicator>
|
|
33
|
+
</Checkbox.Control>
|
|
34
|
+
<Checkbox.HiddenInput className={styles.hiddenInput} />
|
|
35
|
+
{(label || labelInfo) && (
|
|
36
|
+
<div className={styles.labelColumn}>
|
|
37
|
+
{label && <Checkbox.Label className={styles.label}>{label}</Checkbox.Label>}
|
|
49
38
|
{labelInfo && <div className={styles.labelInfo}>{labelInfo}</div>}
|
|
50
|
-
</
|
|
39
|
+
</div>
|
|
51
40
|
)}
|
|
52
|
-
</
|
|
41
|
+
</Checkbox.Root>
|
|
53
42
|
);
|
|
54
43
|
};
|
|
55
44
|
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
-
import type
|
|
2
|
+
import { type Checkbox } from '@ark-ui/react/checkbox';
|
|
3
3
|
|
|
4
4
|
export const checkboxVariants = ['default', 'warning'] as const;
|
|
5
5
|
export type CheckboxVariant = (typeof checkboxVariants)[number];
|
|
6
6
|
|
|
7
|
-
export interface DsCheckboxProps extends
|
|
7
|
+
export interface DsCheckboxProps extends Omit<
|
|
8
|
+
ComponentPropsWithoutRef<typeof Checkbox.Root>,
|
|
9
|
+
'onCheckedChange' | 'value'
|
|
10
|
+
> {
|
|
11
|
+
/**
|
|
12
|
+
* Value when used in a group or for form submission. Coerced to string for the native control.
|
|
13
|
+
*/
|
|
14
|
+
value?: string | number;
|
|
8
15
|
/**
|
|
9
16
|
* Visual variant of the checkbox
|
|
10
17
|
*/
|
|
@@ -18,17 +25,11 @@ export interface DsCheckboxProps extends ComponentPropsWithoutRef<typeof Root> {
|
|
|
18
25
|
*/
|
|
19
26
|
labelInfo?: ReactNode;
|
|
20
27
|
/**
|
|
21
|
-
*
|
|
22
|
-
*/
|
|
23
|
-
checked?: boolean | 'indeterminate';
|
|
24
|
-
/**
|
|
25
|
-
* The default checked state of the checkbox
|
|
28
|
+
* Disables the checkbox, preventing user interaction
|
|
26
29
|
*/
|
|
27
|
-
|
|
30
|
+
disabled?: boolean;
|
|
28
31
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @param checked
|
|
32
|
+
* Callback invoked when the checked state changes
|
|
32
33
|
*/
|
|
33
34
|
onCheckedChange?: (checked: boolean | 'indeterminate') => void;
|
|
34
35
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { Checkbox } from '@ark-ui/react/checkbox';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import styles from './ds-checkbox-group.module.scss';
|
|
5
|
+
import type { DsCheckboxGroupProps } from './ds-checkbox-group.types';
|
|
6
|
+
|
|
7
|
+
const DsCheckboxGroup: React.FC<DsCheckboxGroupProps> = ({
|
|
8
|
+
orientation = 'vertical',
|
|
9
|
+
className,
|
|
10
|
+
children,
|
|
11
|
+
...props
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<Checkbox.Group className={classNames(styles.root, styles[orientation], className)} {...props}>
|
|
15
|
+
{children}
|
|
16
|
+
</Checkbox.Group>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default DsCheckboxGroup;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
import { type Checkbox } from '@ark-ui/react/checkbox';
|
|
3
|
+
|
|
4
|
+
export type DsCheckboxGroupOrientation = 'vertical' | 'horizontal';
|
|
5
|
+
|
|
6
|
+
export interface DsCheckboxGroupProps extends ComponentPropsWithoutRef<typeof Checkbox.Group> {
|
|
7
|
+
orientation?: DsCheckboxGroupOrientation;
|
|
8
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export type CheckedState = boolean | 'indeterminate';
|
|
2
|
+
|
|
3
|
+
export interface UseCheckboxSelectAllOptions<T> {
|
|
4
|
+
/** Currently selected values. */
|
|
5
|
+
value: T[];
|
|
6
|
+
/** Full set of values represented by the group. */
|
|
7
|
+
allValues: readonly T[];
|
|
8
|
+
/** Callback to update selected values. */
|
|
9
|
+
onValueChange: (next: T[]) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Optional predicate to exclude values from bulk select/deselect.
|
|
12
|
+
* Non-selectable values that are already in `value` are preserved on toggle.
|
|
13
|
+
*/
|
|
14
|
+
isSelectable?: (value: T) => boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface UseCheckboxSelectAllResult {
|
|
18
|
+
/** Tri-state value for the select-all checkbox. */
|
|
19
|
+
selectAllState: CheckedState;
|
|
20
|
+
/** Count of selected values that are also selectable. */
|
|
21
|
+
selectedCount: number;
|
|
22
|
+
/** Count of selectable values. */
|
|
23
|
+
selectableCount: number;
|
|
24
|
+
/** Handler for the select-all checkbox's `onCheckedChange`. */
|
|
25
|
+
onSelectAllChange: (checked: CheckedState) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Headless helper for a "select all" checkbox bound to a checkbox group.
|
|
30
|
+
*
|
|
31
|
+
* - Derives tri-state (`true` / `false` / `'indeterminate'`) from current selection.
|
|
32
|
+
* - Toggling selects or clears only selectable values; preserves any already-selected
|
|
33
|
+
* non-selectable values so bulk actions don't silently mutate protected items.
|
|
34
|
+
*/
|
|
35
|
+
export function useCheckboxSelectAll<T>({
|
|
36
|
+
value,
|
|
37
|
+
allValues,
|
|
38
|
+
onValueChange,
|
|
39
|
+
isSelectable,
|
|
40
|
+
}: UseCheckboxSelectAllOptions<T>): UseCheckboxSelectAllResult {
|
|
41
|
+
const selectableValues = isSelectable ? allValues.filter(isSelectable) : [...allValues];
|
|
42
|
+
const selectableSet = new Set(selectableValues);
|
|
43
|
+
const selectedCount = value.reduce((count, v) => (selectableSet.has(v) ? count + 1 : count), 0);
|
|
44
|
+
const selectableCount = selectableValues.length;
|
|
45
|
+
|
|
46
|
+
let selectAllState: CheckedState = 'indeterminate';
|
|
47
|
+
|
|
48
|
+
if (selectableCount === 0 || selectedCount === 0) {
|
|
49
|
+
selectAllState = false;
|
|
50
|
+
} else if (selectedCount === selectableCount) {
|
|
51
|
+
selectAllState = true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const onSelectAllChange = (checked: CheckedState) => {
|
|
55
|
+
const preserved = value.filter((v) => !selectableSet.has(v));
|
|
56
|
+
onValueChange(checked === true ? [...preserved, ...selectableValues] : preserved);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
selectAllState,
|
|
61
|
+
selectedCount,
|
|
62
|
+
selectableCount,
|
|
63
|
+
onSelectAllChange,
|
|
64
|
+
};
|
|
65
|
+
}
|
package/src/components/ds-comment-bubble/components/ds-comment-thread/ds-comment-thread.types.ts
CHANGED
|
@@ -1,12 +1,38 @@
|
|
|
1
1
|
import type { CommentMessage, CommentAuthor } from '../../../ds-comment-card';
|
|
2
2
|
|
|
3
3
|
export interface DsCommentThreadProps {
|
|
4
|
+
/**
|
|
5
|
+
* Ordered list of messages in the thread, from oldest to newest.
|
|
6
|
+
*/
|
|
4
7
|
messages: CommentMessage[];
|
|
8
|
+
/**
|
|
9
|
+
* Author of the top-level comment. Used to visually distinguish their messages
|
|
10
|
+
* from replies by other participants.
|
|
11
|
+
*/
|
|
5
12
|
commentAuthor: CommentAuthor;
|
|
13
|
+
/**
|
|
14
|
+
* The user currently viewing the thread. Used to decide which messages the viewer
|
|
15
|
+
* can edit or delete.
|
|
16
|
+
*/
|
|
6
17
|
currentUser?: CommentAuthor;
|
|
18
|
+
/**
|
|
19
|
+
* Called when a message is edited. Receives the message id and the new content.
|
|
20
|
+
*/
|
|
7
21
|
onEditMessage?: (messageId: string, newContent: string) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Called when a message is deleted. Receives the message id.
|
|
24
|
+
*/
|
|
8
25
|
onDeleteMessage?: (messageId: string) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Called when a message is marked as unread. Receives the message id.
|
|
28
|
+
*/
|
|
9
29
|
onMarkUnread?: (messageId: string) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Called when a message is resolved. Receives the message id.
|
|
32
|
+
*/
|
|
10
33
|
onResolved?: (messageId: string) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Additional CSS class name applied to the thread root
|
|
36
|
+
*/
|
|
11
37
|
className?: string;
|
|
12
38
|
}
|
|
@@ -1,15 +1,53 @@
|
|
|
1
1
|
import type { CommentAuthor } from '../../../ds-comment-card';
|
|
2
2
|
|
|
3
3
|
export interface DsThreadItemProps {
|
|
4
|
+
/**
|
|
5
|
+
* Stable identifier for the message. Passed to callbacks to identify which
|
|
6
|
+
* message the user acted on.
|
|
7
|
+
*/
|
|
4
8
|
id: string;
|
|
9
|
+
/**
|
|
10
|
+
* Author of the message
|
|
11
|
+
*/
|
|
5
12
|
author: CommentAuthor;
|
|
13
|
+
/**
|
|
14
|
+
* Text content of the message
|
|
15
|
+
*/
|
|
6
16
|
content: string;
|
|
17
|
+
/**
|
|
18
|
+
* Timestamp when the message was created
|
|
19
|
+
*/
|
|
7
20
|
createdAt: Date;
|
|
21
|
+
/**
|
|
22
|
+
* Whether this message was posted by the author of the top-level comment.
|
|
23
|
+
* Styled slightly differently from replies by other participants.
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
8
26
|
isCommentAuthorMessage?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Whether the current viewer can edit or delete this message. Typically true
|
|
29
|
+
* only when the viewer is the message's author.
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
9
32
|
canModify?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Called when the viewer saves an edit. Receives the message id and the new content.
|
|
35
|
+
*/
|
|
10
36
|
onEdit?: (messageId: string, newContent: string) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Called when the viewer deletes the message. Receives the message id.
|
|
39
|
+
*/
|
|
11
40
|
onDelete?: (messageId: string) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Called when the viewer marks the message as unread. Receives the message id.
|
|
43
|
+
*/
|
|
12
44
|
onMarkUnread?: (messageId: string) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Called when the viewer resolves the message. Receives the message id.
|
|
47
|
+
*/
|
|
13
48
|
onResolved?: (messageId: string) => void;
|
|
49
|
+
/**
|
|
50
|
+
* Additional CSS class name applied to the item root
|
|
51
|
+
*/
|
|
14
52
|
className?: string;
|
|
15
53
|
}
|