@drivenets/design-system 0.7.3 → 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 +47 -0
- package/dist/index.cjs +5730 -4569
- package/dist/index.d.cts +1768 -1065
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1768 -1065
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5718 -4577
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +14 -14
- package/src/components/ds-autocomplete/ds-autocomplete.module.scss +1 -2
- package/src/components/ds-autocomplete/ds-autocomplete.tsx +13 -8
- package/src/components/ds-autocomplete/ds-autocomplete.types.ts +2 -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-comment-bubble/ds-comment-bubble.module.scss +6 -2
- package/src/components/ds-comment-bubble/ds-comment-bubble.tsx +22 -15
- package/src/components/ds-comment-bubble/ds-comment-bubble.types.ts +1 -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-input/ds-date-input.tsx +3 -4
- package/src/components/ds-date-input/ds-date-input.types.ts +3 -1
- package/src/components/ds-date-input/index.ts +10 -0
- package/src/components/ds-date-picker/components/calendar-table.module.scss +93 -0
- package/src/components/ds-date-picker/components/calendar-view-control/calendar-view-control.module.scss +48 -0
- package/src/components/ds-date-picker/components/calendar-view-control/calendar-view-control.tsx +20 -0
- package/src/components/ds-date-picker/components/calendar-view-control/index.ts +1 -0
- package/src/components/ds-date-picker/components/day-view/day-view.module.scss +12 -0
- package/src/components/ds-date-picker/components/day-view/day-view.tsx +45 -0
- package/src/components/ds-date-picker/components/day-view/index.ts +1 -0
- package/src/components/ds-date-picker/components/month-view/index.ts +1 -0
- package/src/components/ds-date-picker/components/month-view/month-view.module.scss +4 -0
- package/src/components/ds-date-picker/components/month-view/month-view.tsx +35 -0
- package/src/components/ds-date-picker/components/year-view/index.ts +1 -0
- package/src/components/ds-date-picker/components/year-view/year-view.module.scss +4 -0
- package/src/components/ds-date-picker/components/year-view/year-view.tsx +35 -0
- package/src/components/ds-date-picker/ds-date-picker.module.scss +29 -0
- package/src/components/ds-date-picker/ds-date-picker.tsx +211 -0
- package/src/components/ds-date-picker/ds-date-picker.types.ts +94 -0
- package/src/components/ds-date-picker/ds-date-picker.utils.ts +87 -0
- package/src/components/ds-date-picker/ds-date-picker.utils.unit.test.ts +226 -0
- package/src/components/ds-date-picker/index.ts +2 -0
- package/src/components/ds-date-range-picker/ds-date-range-picker.module.scss +20 -0
- package/src/components/ds-date-range-picker/ds-date-range-picker.tsx +101 -0
- package/src/components/ds-date-range-picker/ds-date-range-picker.types.ts +95 -0
- package/src/components/ds-date-range-picker/ds-date-range-picker.utils.ts +19 -0
- package/src/components/ds-date-range-picker/ds-date-range-picker.utils.unit.test.ts +48 -0
- package/src/components/ds-date-range-picker/index.ts +9 -0
- 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-file-upload/ds-file-upload-api.types.ts +1 -0
- package/src/components/ds-file-upload/hooks/use-file-upload.ts +1 -1
- package/src/components/ds-file-upload/index.ts +6 -1
- package/src/components/ds-file-upload/utils/file-factory.ts +1 -0
- package/src/components/ds-file-upload/utils/file-factory.unit.test.ts +37 -0
- package/src/components/ds-form-control/ds-form-control.tsx +7 -3
- package/src/components/ds-key-value-pair/ds-key-value-pair.module.scss +72 -0
- package/src/components/ds-key-value-pair/ds-key-value-pair.tsx +47 -0
- package/src/components/ds-key-value-pair/ds-key-value-pair.types.ts +24 -0
- package/src/components/ds-key-value-pair/index.ts +3 -0
- package/src/components/ds-loader/ds-loader.tsx +1 -1
- 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-status-badge/ds-status-badge.module.scss +1 -1
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx +6 -4
- 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/components/time-item/index.ts +1 -0
- package/src/components/ds-time-picker/components/time-item/time-item.module.scss +37 -0
- package/src/components/ds-time-picker/components/time-item/time-item.tsx +26 -0
- package/src/components/ds-time-picker/components/time-item/time-item.types.ts +10 -0
- package/src/components/ds-time-picker/components/time-scroller/index.ts +2 -0
- package/src/components/ds-time-picker/components/time-scroller/time-scroller.module.scss +25 -0
- package/src/components/ds-time-picker/components/time-scroller/time-scroller.tsx +61 -0
- package/src/components/ds-time-picker/components/time-scroller/time-scroller.types.ts +17 -0
- package/src/components/ds-time-picker/components/time-scroller/time-scroller.utils.ts +44 -0
- package/src/components/ds-time-picker/ds-time-picker.module.scss +11 -0
- package/src/components/ds-time-picker/ds-time-picker.tsx +178 -0
- package/src/components/ds-time-picker/ds-time-picker.types.ts +54 -0
- package/src/components/ds-time-picker/ds-time-picker.utils.ts +176 -0
- package/src/components/ds-time-picker/ds-time-picker.utils.unit.test.ts +316 -0
- package/src/components/ds-time-picker/index.ts +3 -0
- package/src/components/ds-tooltip/ds-tooltip.module.scss +1 -7
- package/src/components/ds-tooltip/ds-tooltip.tsx +9 -9
- package/src/components/ds-tooltip/ds-tooltip.types.ts +7 -1
- package/src/index.ts +8 -0
- package/src/styles/_breakpoints.module.scss +5 -0
- package/src/styles/_responsive.scss +13 -0
- package/src/styles/_root_updated.scss +593 -0
- package/src/styles/_variables.scss +2 -0
- package/src/styles/shared/_button.scss +2 -0
- package/src/styles/shared/_dropdown.scss +4 -1
- 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 +79 -0
- package/src/utils/use-controlled.ts +18 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { clampTime, formatTime, parseTime, timeScrollerAdapter } from './ds-time-picker.utils';
|
|
3
|
+
|
|
4
|
+
const createTime = (h: number, m: number) => {
|
|
5
|
+
const d = new Date(2025, 0, 1);
|
|
6
|
+
d.setHours(h, m, 0, 0);
|
|
7
|
+
return d;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function assertDate(value: unknown): asserts value is Date {
|
|
11
|
+
expect(value).toBeInstanceOf(Date);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe('Time Picker Utils', () => {
|
|
15
|
+
describe('clampTime', () => {
|
|
16
|
+
it('should return the original date when within bounds', () => {
|
|
17
|
+
const date = createTime(10, 30);
|
|
18
|
+
const result = clampTime(date, createTime(8, 0), createTime(18, 0));
|
|
19
|
+
|
|
20
|
+
expect(result).toBe(date);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should clamp to min when time is before min', () => {
|
|
24
|
+
const date = createTime(6, 0);
|
|
25
|
+
const min = createTime(8, 0);
|
|
26
|
+
const result = clampTime(date, min);
|
|
27
|
+
|
|
28
|
+
expect(result.getHours()).toBe(8);
|
|
29
|
+
expect(result.getMinutes()).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should clamp to max when time is after max', () => {
|
|
33
|
+
const date = createTime(20, 0);
|
|
34
|
+
const max = createTime(18, 30);
|
|
35
|
+
const result = clampTime(date, undefined, max);
|
|
36
|
+
|
|
37
|
+
expect(result.getHours()).toBe(18);
|
|
38
|
+
expect(result.getMinutes()).toBe(30);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should not clamp when min and max are undefined', () => {
|
|
42
|
+
const date = createTime(12, 0);
|
|
43
|
+
const result = clampTime(date);
|
|
44
|
+
|
|
45
|
+
expect(result).toBe(date);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should preserve the date portion when clamping', () => {
|
|
49
|
+
const date = new Date(2025, 5, 15, 6, 0, 0, 0);
|
|
50
|
+
const min = createTime(8, 0);
|
|
51
|
+
const result = clampTime(date, min);
|
|
52
|
+
|
|
53
|
+
expect(result.getFullYear()).toBe(2025);
|
|
54
|
+
expect(result.getMonth()).toBe(5);
|
|
55
|
+
expect(result.getDate()).toBe(15);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('formatTime', () => {
|
|
60
|
+
it('should return empty string for undefined', () => {
|
|
61
|
+
expect(formatTime(undefined)).toBe('');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should return empty string for null', () => {
|
|
65
|
+
expect(formatTime(null)).toBe('');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should format midnight as 12:00 AM', () => {
|
|
69
|
+
expect(formatTime(createTime(0, 0))).toBe('12:00 AM');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should format noon as 12:00 PM', () => {
|
|
73
|
+
expect(formatTime(createTime(12, 0))).toBe('12:00 PM');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should format afternoon time', () => {
|
|
77
|
+
expect(formatTime(createTime(14, 30))).toBe('02:30 PM');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should format morning time', () => {
|
|
81
|
+
expect(formatTime(createTime(9, 5))).toBe('09:05 AM');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should pad single-digit hours', () => {
|
|
85
|
+
expect(formatTime(createTime(1, 0))).toBe('01:00 AM');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should pad single-digit minutes', () => {
|
|
89
|
+
expect(formatTime(createTime(10, 3))).toBe('10:03 AM');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should format 11:59 PM', () => {
|
|
93
|
+
expect(formatTime(createTime(23, 59))).toBe('11:59 PM');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('parseTime', () => {
|
|
98
|
+
it('should parse valid AM time', () => {
|
|
99
|
+
expect(parseTime('09:30 AM')).toEqual({ hours: 9, minutes: 30 });
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should parse valid PM time', () => {
|
|
103
|
+
expect(parseTime('02:45 PM')).toEqual({ hours: 14, minutes: 45 });
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should convert 12 AM to hour 0', () => {
|
|
107
|
+
expect(parseTime('12:00 AM')).toEqual({ hours: 0, minutes: 0 });
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should keep 12 PM as hour 12', () => {
|
|
111
|
+
expect(parseTime('12:00 PM')).toEqual({ hours: 12, minutes: 0 });
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should handle case-insensitive period', () => {
|
|
115
|
+
expect(parseTime('09:30 am')).toEqual({ hours: 9, minutes: 30 });
|
|
116
|
+
expect(parseTime('09:30 Am')).toEqual({ hours: 9, minutes: 30 });
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should parse single-digit hour', () => {
|
|
120
|
+
expect(parseTime('1:00 AM')).toEqual({ hours: 1, minutes: 0 });
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should return null for empty string', () => {
|
|
124
|
+
expect(parseTime('')).toBeNull();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should return null for garbage input', () => {
|
|
128
|
+
expect(parseTime('not a time')).toBeNull();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should return null for missing period', () => {
|
|
132
|
+
expect(parseTime('09:30')).toBeNull();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should return null for hour 0', () => {
|
|
136
|
+
expect(parseTime('00:30 AM')).toBeNull();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should return null for hour 13', () => {
|
|
140
|
+
expect(parseTime('13:00 PM')).toBeNull();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('should return null for minute 60', () => {
|
|
144
|
+
expect(parseTime('09:60 AM')).toBeNull();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('timeScrollerAdapter', () => {
|
|
149
|
+
it('should extract hour, minute, period from a PM date', () => {
|
|
150
|
+
const adapter = timeScrollerAdapter(createTime(14, 30));
|
|
151
|
+
|
|
152
|
+
expect(adapter.slotProps.hour.value).toBe(2);
|
|
153
|
+
expect(adapter.slotProps.minute.value).toBe(30);
|
|
154
|
+
expect(adapter.slotProps.period.value).toBe('PM');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should extract hour, minute, period from an AM date', () => {
|
|
158
|
+
const adapter = timeScrollerAdapter(createTime(9, 15));
|
|
159
|
+
|
|
160
|
+
expect(adapter.slotProps.hour.value).toBe(9);
|
|
161
|
+
expect(adapter.slotProps.minute.value).toBe(15);
|
|
162
|
+
expect(adapter.slotProps.period.value).toBe('AM');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('should return 12 for midnight', () => {
|
|
166
|
+
const adapter = timeScrollerAdapter(createTime(0, 0));
|
|
167
|
+
|
|
168
|
+
expect(adapter.slotProps.hour.value).toBe(12);
|
|
169
|
+
expect(adapter.slotProps.period.value).toBe('AM');
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should return 12 for noon', () => {
|
|
173
|
+
const adapter = timeScrollerAdapter(createTime(12, 0));
|
|
174
|
+
|
|
175
|
+
expect(adapter.slotProps.hour.value).toBe(12);
|
|
176
|
+
expect(adapter.slotProps.period.value).toBe('PM');
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should return undefined fields when no date', () => {
|
|
180
|
+
const adapter = timeScrollerAdapter(null);
|
|
181
|
+
|
|
182
|
+
expect(adapter.slotProps.hour.value).toBeUndefined();
|
|
183
|
+
expect(adapter.slotProps.minute.value).toBeUndefined();
|
|
184
|
+
expect(adapter.slotProps.period.value).toBeUndefined();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('onHourChange', () => {
|
|
188
|
+
it('should call setDate with the correct 24h hour', () => {
|
|
189
|
+
const setDate = vi.fn<(date: Date | null) => void>();
|
|
190
|
+
const adapter = timeScrollerAdapter(createTime(14, 30), setDate);
|
|
191
|
+
|
|
192
|
+
adapter.slotProps.hour.onChange(5);
|
|
193
|
+
|
|
194
|
+
expect(setDate).toHaveBeenCalledOnce();
|
|
195
|
+
const result = setDate.mock.calls[0]?.[0];
|
|
196
|
+
assertDate(result);
|
|
197
|
+
expect(result.getHours()).toBe(17);
|
|
198
|
+
expect(result.getMinutes()).toBe(30);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should default to AM when no date is provided', () => {
|
|
202
|
+
const setDate = vi.fn<(date: Date | null) => void>();
|
|
203
|
+
const adapter = timeScrollerAdapter(undefined, setDate);
|
|
204
|
+
|
|
205
|
+
adapter.slotProps.hour.onChange(9);
|
|
206
|
+
|
|
207
|
+
expect(setDate).toHaveBeenCalledOnce();
|
|
208
|
+
const result = setDate.mock.calls[0]?.[0];
|
|
209
|
+
assertDate(result);
|
|
210
|
+
expect(result.getHours()).toBe(9);
|
|
211
|
+
expect(result.getMinutes()).toBe(0);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
describe('onMinuteChange', () => {
|
|
216
|
+
it('should call setDate with the new minute', () => {
|
|
217
|
+
const setDate = vi.fn<(date: Date | null) => void>();
|
|
218
|
+
const adapter = timeScrollerAdapter(createTime(14, 30), setDate);
|
|
219
|
+
|
|
220
|
+
adapter.slotProps.minute.onChange(45);
|
|
221
|
+
|
|
222
|
+
expect(setDate).toHaveBeenCalledOnce();
|
|
223
|
+
const result = setDate.mock.calls[0]?.[0];
|
|
224
|
+
assertDate(result);
|
|
225
|
+
expect(result.getHours()).toBe(14);
|
|
226
|
+
expect(result.getMinutes()).toBe(45);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
describe('onPeriodChange', () => {
|
|
231
|
+
it('should toggle from PM to AM', () => {
|
|
232
|
+
const setDate = vi.fn<(date: Date | null) => void>();
|
|
233
|
+
const adapter = timeScrollerAdapter(createTime(14, 30), setDate);
|
|
234
|
+
|
|
235
|
+
adapter.slotProps.period.onChange('AM');
|
|
236
|
+
|
|
237
|
+
expect(setDate).toHaveBeenCalledOnce();
|
|
238
|
+
const result = setDate.mock.calls[0]?.[0];
|
|
239
|
+
assertDate(result);
|
|
240
|
+
expect(result.getHours()).toBe(2);
|
|
241
|
+
expect(result.getMinutes()).toBe(30);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('should toggle from AM to PM', () => {
|
|
245
|
+
const setDate = vi.fn<(date: Date | null) => void>();
|
|
246
|
+
const adapter = timeScrollerAdapter(createTime(9, 15), setDate);
|
|
247
|
+
|
|
248
|
+
adapter.slotProps.period.onChange('PM');
|
|
249
|
+
|
|
250
|
+
expect(setDate).toHaveBeenCalledOnce();
|
|
251
|
+
const result = setDate.mock.calls[0]?.[0];
|
|
252
|
+
assertDate(result);
|
|
253
|
+
expect(result.getHours()).toBe(21);
|
|
254
|
+
expect(result.getMinutes()).toBe(15);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe('validation callbacks', () => {
|
|
259
|
+
it('should not include validation callbacks when no min/max', () => {
|
|
260
|
+
const adapter = timeScrollerAdapter(createTime(10, 0));
|
|
261
|
+
|
|
262
|
+
expect(adapter.slotProps.hour.isDisabled).toBeUndefined();
|
|
263
|
+
expect(adapter.slotProps.minute.isDisabled).toBeUndefined();
|
|
264
|
+
expect(adapter.slotProps.period.isDisabled).toBeUndefined();
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should disable AM when min is in PM range', () => {
|
|
268
|
+
const min = createTime(13, 0);
|
|
269
|
+
const adapter = timeScrollerAdapter(createTime(14, 0), undefined, min);
|
|
270
|
+
|
|
271
|
+
expect(adapter.slotProps.period.isDisabled?.('AM')).toBe(true);
|
|
272
|
+
expect(adapter.slotProps.period.isDisabled?.('PM')).toBe(false);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('should disable PM when max is in AM range', () => {
|
|
276
|
+
const max = createTime(11, 0);
|
|
277
|
+
const adapter = timeScrollerAdapter(createTime(9, 0), undefined, undefined, max);
|
|
278
|
+
|
|
279
|
+
expect(adapter.slotProps.period.isDisabled?.('PM')).toBe(true);
|
|
280
|
+
expect(adapter.slotProps.period.isDisabled?.('AM')).toBe(false);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should disable hours outside min/max range', () => {
|
|
284
|
+
const min = createTime(9, 0);
|
|
285
|
+
const max = createTime(17, 0);
|
|
286
|
+
const adapter = timeScrollerAdapter(createTime(10, 0), undefined, min, max);
|
|
287
|
+
|
|
288
|
+
expect(adapter.slotProps.hour.isDisabled?.(8)).toBe(true);
|
|
289
|
+
expect(adapter.slotProps.hour.isDisabled?.(10)).toBe(false);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('should disable minutes outside min/max range', () => {
|
|
293
|
+
const min = createTime(9, 30);
|
|
294
|
+
const adapter = timeScrollerAdapter(createTime(9, 45), undefined, min);
|
|
295
|
+
|
|
296
|
+
expect(adapter.slotProps.minute.isDisabled?.(15)).toBe(true);
|
|
297
|
+
expect(adapter.slotProps.minute.isDisabled?.(30)).toBe(false);
|
|
298
|
+
expect(adapter.slotProps.minute.isDisabled?.(45)).toBe(false);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should clamp setDate result to min/max', () => {
|
|
302
|
+
const setDate = vi.fn<(date: Date | null) => void>();
|
|
303
|
+
const min = createTime(9, 0);
|
|
304
|
+
const max = createTime(17, 0);
|
|
305
|
+
const adapter = timeScrollerAdapter(createTime(10, 0), setDate, min, max);
|
|
306
|
+
|
|
307
|
+
adapter.slotProps.hour.onChange(7);
|
|
308
|
+
|
|
309
|
+
const result = setDate.mock.calls[0]?.[0];
|
|
310
|
+
assertDate(result);
|
|
311
|
+
expect(result.getHours()).toBe(9);
|
|
312
|
+
expect(result.getMinutes()).toBe(0);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
});
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
@use '../../styles/typography';
|
|
2
|
-
|
|
3
1
|
.tooltip {
|
|
4
2
|
color: var(--color-font-on-action);
|
|
5
3
|
background-color: var(--color-background-brand);
|
|
6
4
|
padding: var(--spacing-xs) var(--spacing-sm);
|
|
7
5
|
border-radius: var(--exo-spacing-2x-small);
|
|
8
|
-
// approx. 6 grid columns
|
|
9
6
|
max-width: 384px;
|
|
7
|
+
overflow-wrap: break-word;
|
|
10
8
|
z-index: 9999;
|
|
11
|
-
|
|
12
|
-
.content {
|
|
13
|
-
@include typography.line-clamp(3);
|
|
14
|
-
}
|
|
15
9
|
}
|
|
16
10
|
|
|
17
11
|
.arrow {
|
|
@@ -5,7 +5,7 @@ import styles from './ds-tooltip.module.scss';
|
|
|
5
5
|
import type { DsTooltipProps } from './ds-tooltip.types';
|
|
6
6
|
import { DsTypography } from '../ds-typography';
|
|
7
7
|
|
|
8
|
-
const DsTooltip: FC<DsTooltipProps> = ({ content, children }) => {
|
|
8
|
+
const DsTooltip: FC<DsTooltipProps> = ({ content, children, slotProps }) => {
|
|
9
9
|
if (content === undefined) {
|
|
10
10
|
return children;
|
|
11
11
|
}
|
|
@@ -14,14 +14,14 @@ const DsTooltip: FC<DsTooltipProps> = ({ content, children }) => {
|
|
|
14
14
|
<Tooltip.Root>
|
|
15
15
|
<Tooltip.Trigger asChild>{children}</Tooltip.Trigger>
|
|
16
16
|
<Tooltip.Portal>
|
|
17
|
-
<Tooltip.Content
|
|
18
|
-
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)}
|
|
17
|
+
<Tooltip.Content
|
|
18
|
+
className={classNames(styles.tooltip, slotProps?.content?.className)}
|
|
19
|
+
style={slotProps?.content?.style}
|
|
20
|
+
side="top"
|
|
21
|
+
align="center"
|
|
22
|
+
sideOffset={4}
|
|
23
|
+
>
|
|
24
|
+
{isValidElement(content) ? content : <DsTypography variant="body-xs-reg">{content}</DsTypography>}
|
|
25
25
|
<Tooltip.Arrow className={styles.arrow} />
|
|
26
26
|
</Tooltip.Content>
|
|
27
27
|
</Tooltip.Portal>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
export interface DsTooltipProps {
|
|
4
4
|
/**
|
|
@@ -9,4 +9,10 @@ export interface DsTooltipProps {
|
|
|
9
9
|
* The content to be rendered inside the tooltip
|
|
10
10
|
*/
|
|
11
11
|
children: ReactNode;
|
|
12
|
+
slotProps?: {
|
|
13
|
+
content?: {
|
|
14
|
+
className?: string;
|
|
15
|
+
style?: CSSProperties;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
12
18
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './components/ds-avatar';
|
|
|
4
4
|
export * from './components/ds-avatar-group';
|
|
5
5
|
export * from './components/ds-breadcrumb';
|
|
6
6
|
export * from './components/ds-button';
|
|
7
|
+
export * from './components/ds-button-v3';
|
|
7
8
|
export * from './components/ds-card';
|
|
8
9
|
export * from './components/ds-checkbox';
|
|
9
10
|
export * from './components/ds-chip';
|
|
@@ -14,6 +15,8 @@ export * from './components/ds-comment-indicator';
|
|
|
14
15
|
export * from './components/ds-comments-drawer';
|
|
15
16
|
export * from './components/ds-confirmation';
|
|
16
17
|
export * from './components/ds-date-input';
|
|
18
|
+
export * from './components/ds-date-picker';
|
|
19
|
+
export * from './components/ds-date-range-picker';
|
|
17
20
|
export * from './components/ds-dialog';
|
|
18
21
|
export * from './components/ds-divider';
|
|
19
22
|
export * from './components/ds-drawer';
|
|
@@ -24,6 +27,7 @@ export * from './components/ds-filter-status-icon';
|
|
|
24
27
|
export * from './components/ds-form-control';
|
|
25
28
|
export * from './components/ds-grid';
|
|
26
29
|
export * from './components/ds-icon';
|
|
30
|
+
export * from './components/ds-key-value-pair';
|
|
27
31
|
export * from './components/ds-loader';
|
|
28
32
|
export * from './components/ds-modal';
|
|
29
33
|
export * from './components/ds-number-input';
|
|
@@ -39,6 +43,8 @@ export * from './components/ds-select';
|
|
|
39
43
|
export * from './components/ds-skeleton';
|
|
40
44
|
export * from './components/ds-smart-tabs';
|
|
41
45
|
export * from './components/ds-spinner';
|
|
46
|
+
export * from './components/ds-split-button';
|
|
47
|
+
export * from './components/ds-stack';
|
|
42
48
|
export * from './components/ds-status-badge';
|
|
43
49
|
export * from './components/ds-stepper';
|
|
44
50
|
export * from './components/ds-system-status';
|
|
@@ -48,9 +54,11 @@ export * from './components/ds-tag';
|
|
|
48
54
|
export * from './components/ds-tag-filter';
|
|
49
55
|
export * from './components/ds-text-input';
|
|
50
56
|
export * from './components/ds-textarea';
|
|
57
|
+
export * from './components/ds-time-picker';
|
|
51
58
|
export * from './components/ds-toast';
|
|
52
59
|
export * from './components/ds-toggle';
|
|
53
60
|
export * from './components/ds-tooltip';
|
|
54
61
|
export * from './components/ds-tree';
|
|
55
62
|
export * from './components/ds-typography';
|
|
56
63
|
export * from './components/ds-vertical-tabs';
|
|
64
|
+
export * from './utils/responsive';
|