draft-components 4.20.0 → 4.21.1

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.
@@ -1,210 +1,251 @@
1
- .dc-search-select-button-label {
1
+ .dc-search-select {
2
+ --button-height: 36px;
3
+ --button-padding-left: 12px;
4
+ --button-slot-width: 32px;
5
+ --button-font-size: 14px;
6
+ --button-font-weight: 400;
7
+ --button-line-height: 20px;
8
+ --button-color: var(--dc-neutral-900);
9
+ --button-background: var(--dc-white);
10
+ --button-border-width: 1px;
11
+ --button-border-style: solid;
12
+ --button-border-color: var(--dc-neutral-300);
13
+ --button-border-color-error: var(--dc-red-500);
14
+ --button-border-radius: 7px;
15
+ --button-focus-ring-color: var(--dc-focus-ring-color);
16
+ --popup-min-width: 240px;
17
+ --popup-max-width: 720px;
18
+ --popup-offset: 4px;
19
+ --popup-color: var(--dc-neutral-900);
20
+ --popup-background: var(--dc-white);
21
+ --popup-border-width: 1px;
22
+ --popup-border-style: solid;
23
+ --popup-border-color: var(--dc-neutral-300);
24
+ --popup-border-radius: 7px;
25
+ --popup-shadow:
26
+ 0 2px 4px 0 rgb(var(--dc-neutral-950-rgb) / 5%),
27
+ 0 2px 10px 0 rgb(var(--dc-neutral-950-rgb) / 10%);
28
+ --input-padding: 8px 12px;
29
+ --input-font-size: 14px;
30
+ --input-font-weight: 400;
31
+ --input-line-height: 1;
32
+ --input-border-width: 1px;
33
+ --input-border-style: solid;
34
+ --input-border-color: var(--dc-neutral-300);
35
+ --list-box-max-height: 256px;
36
+ --list-box-padding: 4px;
37
+ --option-padding: 4px 8px;
38
+ --option-font: var(--dc-text-sm);
39
+ --option-scroll-margin-block: 4px;
40
+ --option-scroll-border-radius: 4px;
41
+ --option-color: var(--dc-neutral-900);
42
+ --option-background: none;
43
+ --option-color-selected: var(--dc-neutral-950);
44
+ --option-background-selected: rgb(var(--dc-neutral-950-rgb) / 12%);
45
+ --option-color-checked: var(--dc-white);
46
+ --option-background-checked: var(--dc-blue-500);
47
+ --option-label-font: 600 var(--dc-text-sm);
48
+ --option-label-color: inherit;
49
+ --option-caption-font: var(--dc-text-sm);
50
+ --option-caption-color: inherit;
51
+ --empty-state-padding: 16px;
52
+ --empty-state-font: var(--dc-text-sm);
53
+ --empty-state-text-align: center;
54
+ --empty-state-color: var(--dc-neutral-600);
55
+ --empty-state-color-error: var(--dc-red-600);
56
+
57
+ position: relative;
58
+ box-sizing: border-box;
2
59
  display: inline-flex;
3
- gap: 0.5em;
4
- align-items: center;
60
+ font-family: var(--dc-primary-font);
61
+ color-scheme: light;
5
62
  }
6
63
 
7
- .dc-search-select-button-label > b {
8
- font-weight: 700;
64
+ .dc-search-select_full-width {
65
+ display: flex;
66
+ width: 100%;
9
67
  }
10
68
 
11
- .dc-search-select-option {
69
+ .dc-search-select__button {
12
70
  box-sizing: border-box;
13
71
  display: flex;
14
- flex-direction: column;
15
- justify-content: center;
16
- min-height: 28px;
17
- padding: 4px 8px;
18
- font-size: 14px;
19
- line-height: 1.25;
20
- color: inherit;
72
+ align-items: center;
73
+ width: 100%;
74
+ height: var(--button-height);
75
+ padding: 0;
76
+ font-size: var(--button-font-size);
77
+ font-weight: var(--button-font-weight);
78
+ line-height: var(--button-line-height);
79
+ color: var(--button-color);
80
+ text-align: left;
21
81
  cursor: default;
22
- border-radius: 5px;
23
- }
24
-
25
- .dc-search-select-option_highlighted {
26
- color: var(--dc-neutral-900);
27
- background: var(--dc-neutral-300);
82
+ background: var(--button-background);
83
+ border: var(--button-border-width) var(--button-border-style)
84
+ var(--button-border-color);
85
+ border-radius: var(--button-border-radius);
28
86
  }
29
87
 
30
- .dark .dc-search-select-option_highlighted {
31
- color: var(--dc-white);
32
- background: var(--dc-neutral-600);
88
+ .dc-search-select__button[data-invalid="true"] {
89
+ --button-border-color: var(--button-border-color-error);
33
90
  }
34
91
 
35
- .dc-search-select-option_selected {
36
- color: var(--dc-white);
37
- background: var(--dc-blue-500);
38
- }
92
+ .dc-search-select__button:focus,
93
+ .dc-search-select__button[aria-expanded="true"] {
94
+ --button-border-color: var(--button-focus-ring-color);
39
95
 
40
- .dark .dc-search-select-option_selected {
41
- color: var(--dc-white);
42
- background: var(--dc-blue-500);
96
+ outline: 1px solid var(--button-focus-ring-color);
43
97
  }
44
98
 
45
- .dc-search-select-option__caption {
46
- font-size: 80%;
47
- opacity: 0.75;
48
- }
49
-
50
- .dc-search-select-separator {
51
- display: flex;
52
- align-items: center;
53
- width: 100%;
54
- padding: 8px 0;
99
+ .dc-search-select__button:disabled {
100
+ opacity: var(--dc-disabled-state-opacity);
55
101
  }
56
102
 
57
- .dc-search-select-separator::before,
58
- .dc-search-select-separator::after {
59
- display: block;
60
- height: 1px;
61
- content: "";
62
- background: var(--dc-neutral-300);
103
+ .dc-search-select__button_size_sm {
104
+ --button-font-size: 13px;
105
+ --button-height: 32px;
106
+ --button-padding-left: 8px;
107
+ --button-slot-width: 28px;
108
+ --button-border-radius: 6px;
63
109
  }
64
110
 
65
- .dc-search-select-separator::before {
66
- flex-shrink: 0;
67
- width: 12px;
111
+ .dc-search-select__button_size_lg {
112
+ --button-font-size: 15px;
113
+ --button-height: 40px;
114
+ --button-padding-left: 16px;
115
+ --button-slot-width: 40px;
116
+ --button-border-radius: 8px;
68
117
  }
69
118
 
70
- .dc-search-select-separator::after {
119
+ .dc-search-select__button-label {
71
120
  flex-grow: 1;
72
121
  }
73
122
 
74
- .dark .dc-search-select-separator::before,
75
- .dark .dc-search-select-separator::after {
76
- background: var(--dc-neutral-600);
77
- }
78
-
79
- .dc-search-select-separator__label {
80
- padding: 0 8px;
81
- font-size: 12px;
82
- color: var(--dc-neutral-500);
123
+ .dc-search-select__button-label:first-child {
124
+ padding-left: var(--button-padding-left);
83
125
  }
84
126
 
85
- .dark .dc-search-select-separator__label {
86
- color: var(--dc-neutral-400);
87
- }
88
-
89
- .dc-search-select {
90
- --font-size: 14px;
91
- --color: var(--dc-black-950);
92
- --height: 36px;
93
- --padding-x: 12px;
94
- --radius: 7px;
95
- --border-color: var(--dc-neutral-300);
96
- --border-color-error: var(--dc-red-500);
97
- --background: var(--dc-white);
98
- --focus-ring-color: var(--dc-focus-ring-color);
99
-
100
- position: relative;
101
- box-sizing: border-box;
127
+ .dc-search-select__button-slot {
102
128
  display: inline-flex;
129
+ flex-shrink: 0;
103
130
  align-items: center;
104
- max-width: 100%;
105
- height: var(--height);
106
- padding: 0 var(--padding-x);
107
- padding-right: calc(var(--height) + 0.15em);
108
- font-family: var(--dc-primary-font);
109
- font-size: var(--font-size);
110
- font-weight: 400;
111
- line-height: 1.25;
112
- vertical-align: middle;
113
- color: var(--color);
114
- color-scheme: light;
115
- background: var(--background);
116
- border: 1px solid var(--border-color);
117
- border-radius: var(--radius);
118
- }
119
-
120
- .dc-search-select:focus {
121
- outline: none;
122
- border-color: var(--focus-ring-color);
123
- box-shadow: 0 0 0 1px var(--focus-ring-color);
131
+ justify-content: center;
132
+ width: var(--button-slot-width);
124
133
  }
125
134
 
126
- .dc-search-select_loading,
127
- .dc-search-select_disabled {
128
- pointer-events: none;
135
+ .dc-search-select__caret {
136
+ opacity: 0.65;
137
+ transform: translateY(10%);
129
138
  }
130
139
 
131
- .dc-search-select_disabled {
132
- opacity: var(--dc-disabled-state-opacity);
140
+ .dc-search-select__popup {
141
+ position: absolute;
142
+ top: 100%;
143
+ left: 0;
144
+ z-index: var(--dc-overlay-z-index);
145
+ width: 100%;
146
+ min-width: var(--popup-min-width);
147
+ max-width: var(--popup-max-width);
148
+ margin-top: var(--popup-offset);
149
+ overflow: hidden;
150
+ color: var(--popup-color);
151
+ background: var(--popup-background);
152
+ border: var(--popup-border-width) var(--popup-border-style)
153
+ var(--popup-border-color);
154
+ border-radius: var(--popup-border-radius);
155
+ box-shadow: var(--popup-shadow);
156
+ }
157
+
158
+ .dc-search-select__input {
159
+ box-sizing: border-box;
160
+ width: 100%;
161
+ padding: var(--input-padding);
162
+ margin: 0;
163
+ font-family: inherit;
164
+ font-size: var(--input-font-size);
165
+ font-weight: var(--input-font-weight);
166
+ line-height: var(--input-line-height);
167
+ -webkit-appearance: none;
168
+ -moz-appearance: none;
169
+ appearance: none;
170
+ background: none;
171
+ border: none;
172
+ border-bottom: var(--input-border-width) var(--input-border-style)
173
+ var(--input-border-color);
174
+ }
175
+
176
+ .dc-search-select__input::-moz-placeholder {
177
+ color: inherit;
178
+ opacity: 0.4;
133
179
  }
134
180
 
135
- .dc-search-select_invalid {
136
- border-color: var(--border-color-error);
181
+ .dc-search-select__input::placeholder {
182
+ color: inherit;
183
+ opacity: 0.4;
137
184
  }
138
185
 
139
- .dc-search-select_full-width {
140
- display: flex;
141
- width: 100%;
186
+ .dc-search-select__input:focus {
187
+ outline: none;
142
188
  }
143
189
 
144
- .dc-search-select_size_sm {
145
- --font-size: 13px;
146
- --height: 32px;
147
- --padding-x: 8px;
148
- --radius: 6px;
190
+ .dc-search-select__content {
191
+ font: var(--dc-text-sm);
149
192
  }
150
193
 
151
- .dc-search-select_size_lg {
152
- --font-size: 15px;
153
- --height: 40px;
154
- --padding-x: 16px;
155
- --radius: 8px;
194
+ .dc-search-select__list-box {
195
+ box-sizing: border-box;
196
+ display: grid;
197
+ max-height: var(--list-box-max-height);
198
+ padding: var(--list-box-padding);
199
+ margin: 0;
200
+ overflow-y: auto;
201
+ overscroll-behavior: contain;
202
+ contain: content;
203
+ list-style: none;
204
+ scrollbar-width: thin;
156
205
  }
157
206
 
158
- .dc-search-select__slot-right {
159
- position: absolute;
160
- top: 0;
161
- right: 0;
162
- display: inline-flex;
163
- flex-shrink: 0;
164
- align-items: center;
165
- justify-content: center;
166
- width: var(--height);
167
- height: var(--height);
168
- pointer-events: none;
207
+ .dc-search-select__option {
208
+ box-sizing: border-box;
209
+ display: flex;
210
+ flex-direction: column;
211
+ padding: var(--option-padding);
212
+ font: var(--option-font);
213
+ color: var(--option-color);
214
+ cursor: default;
215
+ scroll-margin-top: var(--option-scroll-margin-block);
216
+ scroll-margin-bottom: var(--option-scroll-margin-block);
217
+ background: var(--option-background);
218
+ border-radius: var(--option-scroll-border-radius);
169
219
  }
170
220
 
171
- .dc-search-select__arrow {
172
- transform: translateY(5%);
221
+ .dc-search-select__option[aria-selected="true"] {
222
+ color: var(--option-color-selected);
223
+ background: var(--option-background-selected);
173
224
  }
174
225
 
175
- .dc-search-select__popover {
176
- --popover-padding: 8px;
177
- --popover-radius: 8px;
178
-
179
- padding: 0;
180
- padding-bottom: var(--popover-padding);
181
- border-radius: var(--popover-radius);
226
+ .dc-search-select__option[aria-checked="true"] {
227
+ color: var(--option-color-checked);
228
+ background: var(--option-background-checked);
182
229
  }
183
230
 
184
- .dc-search-select__textbox {
185
- padding: var(--popover-padding);
231
+ .dc-search-select__option-label {
232
+ font: var(--option-label-font);
233
+ color: var(--option-label-color);
186
234
  }
187
235
 
188
- .dc-search-select__listbox {
189
- max-height: 352px;
190
- padding: 0 var(--popover-padding);
191
- margin: 0;
192
- overflow-y: auto;
193
- list-style: none;
194
- border-bottom-right-radius: inherit;
195
- border-bottom-left-radius: inherit;
236
+ .dc-search-select__option-caption {
237
+ font: var(--option-caption-font);
238
+ color: var(--option-caption-color);
196
239
  }
197
240
 
198
- .dc-search-select__listbox > [role="option"] + [role="option"] {
199
- margin-top: 2px;
241
+ .dc-search-select__empty-state {
242
+ box-sizing: border-box;
243
+ padding: var(--empty-state-padding);
244
+ font: var(--empty-state-font);
245
+ color: var(--empty-state-color);
246
+ text-align: var(--empty-state-text-align);
200
247
  }
201
248
 
202
- .dark .dc-search-select,
203
- .dark.dc-search-select {
204
- --color: var(--dc-white);
205
- --border-color: var(--dc-neutral-600);
206
- --border-color-error: var(--dc-red-400);
207
- --background: var(--dc-neutral-800);
208
-
209
- color-scheme: dark;
249
+ .dc-search-select__empty-state_error {
250
+ color: var(--empty-state-color-error);
210
251
  }
@@ -1,43 +1,42 @@
1
- import { type ReactNode } from 'react';
2
- export type SearchSelectLabelRenderer<Value> = (value: Value) => ReactNode;
3
- export type SearchSelectOptionsRenderer = (props: {
4
- searchQuery: string;
5
- searchQueryLowerCased: string;
6
- }) => ReactNode;
1
+ import { type CSSProperties, type ReactNode } from 'react';
7
2
  export type SearchSelectSize = 'sm' | 'md' | 'lg';
8
- export type SearchSelectProps<T> = {
3
+ export type SearchSelectItem = {
4
+ id: string | number;
5
+ };
6
+ export type SearchSelectItemFilter<T> = (searchQuery: string, item: T) => boolean;
7
+ export type SearchSelectItemIdGetter<T, R> = (item: T) => R;
8
+ export type SearchSelectItemLabelGetter<T> = (item: T) => ReactNode;
9
+ export type SearchSelectItemCaptionGetter<T> = (item: T) => ReactNode;
10
+ export type SearchSelectRenderButtonLabel<T> = (item: T | null) => ReactNode;
11
+ export type SearchSelectChangeHandler<T> = (id: T) => void;
12
+ export type SearchSelectOpenHandler = () => void;
13
+ export type SearchSelectCloseHandler = () => void;
14
+ export declare function SearchSelect<IdType extends string | number, ItemType = unknown>({ style, className, fullWidth, size, inputId: defaultInputId, inputAriaLabel, inputPlaceholder, noDataMessage, notFoundMessage, itemsLoadingMessage, items, itemsError, itemsLoading, loading, invalid, disabled, readOnly, icon, value, onChange, filterItem, getItemId, getItemLabel, getItemCaption, buttonLabel, onOpen, onClose, }: {
15
+ style?: CSSProperties;
9
16
  className?: string;
10
- size?: SearchSelectSize;
11
17
  fullWidth?: boolean;
12
- invalid?: boolean;
18
+ size?: SearchSelectSize;
19
+ inputId?: string;
20
+ inputAriaLabel?: string;
21
+ inputPlaceholder?: string;
22
+ noDataMessage?: ReactNode;
23
+ notFoundMessage?: ReactNode;
24
+ itemsLoadingMessage?: ReactNode;
25
+ items: ItemType[];
26
+ itemsError?: ReactNode;
27
+ itemsLoading?: boolean;
13
28
  loading?: boolean;
29
+ invalid?: boolean;
14
30
  disabled?: boolean;
15
31
  readOnly?: boolean;
16
- textboxIcon?: ReactNode;
17
- textboxAriaLabel?: string;
18
- textboxPlaceholder?: string;
19
- labelledBy?: string;
20
- displayedValue?: ReactNode | SearchSelectLabelRenderer<T>;
21
- children?: ReactNode | SearchSelectOptionsRenderer;
22
- value: T;
23
- onChange: (value: T) => void;
24
- };
25
- export declare function SearchSelect<T>({ className, size, fullWidth, invalid, loading, disabled, readOnly, textboxIcon, textboxAriaLabel, textboxPlaceholder, labelledBy, displayedValue, children, value: selectedValue, onChange: onSelectedValueChange, }: SearchSelectProps<T>): import("react/jsx-runtime").JSX.Element;
26
- export declare namespace SearchSelect {
27
- var Option: <T>({ className, value, children, caption, }: {
28
- className?: string;
29
- value: T;
30
- children: ReactNode;
31
- caption?: ReactNode;
32
- }) => import("react/jsx-runtime").JSX.Element;
33
- var Separator: ({ className, children, }: {
34
- className?: string;
35
- children?: ReactNode;
36
- }) => import("react/jsx-runtime").JSX.Element;
37
- var ButtonLabel: ({ className, icon, value, children, }: {
38
- className?: string;
39
- icon?: ReactNode;
40
- value: ReactNode;
41
- children: ReactNode;
42
- }) => import("react/jsx-runtime").JSX.Element;
43
- }
32
+ icon?: ReactNode;
33
+ value: IdType | null;
34
+ onChange: SearchSelectChangeHandler<IdType>;
35
+ filterItem: SearchSelectItemFilter<ItemType>;
36
+ getItemId: SearchSelectItemIdGetter<ItemType, IdType>;
37
+ getItemLabel: SearchSelectItemLabelGetter<ItemType>;
38
+ getItemCaption?: SearchSelectItemCaptionGetter<ItemType>;
39
+ buttonLabel?: SearchSelectRenderButtonLabel<ItemType>;
40
+ onOpen?: SearchSelectOpenHandler;
41
+ onClose?: SearchSelectCloseHandler;
42
+ }): import("react/jsx-runtime").JSX.Element;