@itwin/itwinui-react 3.5.0 → 3.6.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.
- package/CHANGELOG.md +34 -0
- package/cjs/core/Carousel/Carousel.d.ts +4 -4
- package/cjs/core/Carousel/CarouselNavigation.d.ts +4 -4
- package/cjs/core/Dialog/Dialog.js +19 -17
- package/cjs/core/Dialog/DialogContext.d.ts +4 -0
- package/cjs/core/Dialog/DialogMain.js +1 -1
- package/cjs/core/Dialog/DialogTitleBar.js +1 -1
- package/cjs/core/InputGroup/InputGroup.d.ts +4 -0
- package/cjs/core/InputGroup/InputGroup.js +20 -4
- package/cjs/core/InputWithDecorations/InputWithDecorations.d.ts +18 -62
- package/cjs/core/InputWithDecorations/InputWithDecorations.js +21 -6
- package/cjs/core/LabeledSelect/LabeledSelect.d.ts +376 -4
- package/cjs/core/LabeledSelect/LabeledSelect.js +1 -1
- package/cjs/core/Popover/Popover.d.ts +6 -3
- package/cjs/core/SearchBox/SearchBox.js +4 -6
- package/cjs/core/Select/Select.d.ts +194 -101
- package/cjs/core/Select/Select.js +71 -18
- package/cjs/core/Table/Table.js +2 -1
- package/cjs/core/Tabs/Tabs.js +19 -3
- package/cjs/core/Tile/Tile.d.ts +2 -2
- package/cjs/core/utils/components/InputFlexContainer.d.ts +25 -0
- package/cjs/core/utils/components/InputFlexContainer.js +19 -1
- package/cjs/core/utils/components/LineClamp.d.ts +5 -0
- package/cjs/core/utils/components/LineClamp.js +49 -0
- package/cjs/core/utils/components/index.d.ts +1 -0
- package/cjs/core/utils/components/index.js +1 -0
- package/cjs/core/utils/icons/SvgStatusError.js +1 -1
- package/esm/core/Carousel/Carousel.d.ts +4 -4
- package/esm/core/Carousel/CarouselNavigation.d.ts +4 -4
- package/esm/core/Dialog/Dialog.js +19 -17
- package/esm/core/Dialog/DialogContext.d.ts +4 -0
- package/esm/core/Dialog/DialogMain.js +1 -1
- package/esm/core/Dialog/DialogTitleBar.js +1 -1
- package/esm/core/InputGroup/InputGroup.d.ts +4 -0
- package/esm/core/InputGroup/InputGroup.js +20 -4
- package/esm/core/InputWithDecorations/InputWithDecorations.d.ts +18 -62
- package/esm/core/InputWithDecorations/InputWithDecorations.js +22 -7
- package/esm/core/LabeledSelect/LabeledSelect.d.ts +376 -4
- package/esm/core/LabeledSelect/LabeledSelect.js +1 -1
- package/esm/core/Popover/Popover.d.ts +6 -3
- package/esm/core/SearchBox/SearchBox.js +5 -7
- package/esm/core/Select/Select.d.ts +194 -101
- package/esm/core/Select/Select.js +72 -19
- package/esm/core/Table/Table.js +2 -1
- package/esm/core/Tabs/Tabs.js +19 -3
- package/esm/core/Tile/Tile.d.ts +2 -2
- package/esm/core/utils/components/InputFlexContainer.d.ts +25 -0
- package/esm/core/utils/components/InputFlexContainer.js +18 -0
- package/esm/core/utils/components/LineClamp.d.ts +5 -0
- package/esm/core/utils/components/LineClamp.js +23 -0
- package/esm/core/utils/components/index.d.ts +1 -0
- package/esm/core/utils/components/index.js +1 -0
- package/esm/core/utils/icons/SvgStatusError.js +1 -1
- package/package.json +24 -26
- package/styles.css +23 -23
|
@@ -1,54 +1,193 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { CommonProps } from '../utils/index.js';
|
|
3
3
|
import { usePopover } from '../Popover/Popover.js';
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Select component to select value from options.
|
|
6
|
+
* Generic type is used for value. It prevents you from mistakenly using other types in `options`, `value` and `onChange`.
|
|
7
|
+
* @example
|
|
8
|
+
* <caption>Basic select.</caption>
|
|
9
|
+
* <Select
|
|
10
|
+
* options={[
|
|
11
|
+
* { value: '1', label: 'Option 1' },
|
|
12
|
+
* { value: '2', label: 'Option 2' },
|
|
13
|
+
* { value: '3', label: 'Option 3' },
|
|
14
|
+
* ]}
|
|
15
|
+
* />
|
|
16
|
+
* @example
|
|
17
|
+
* <caption>Native select.</caption>
|
|
18
|
+
* <Select
|
|
19
|
+
* native
|
|
20
|
+
* options={[
|
|
21
|
+
* { value: '1', label: 'Option 1' },
|
|
22
|
+
* { value: '2', label: 'Option 2' },
|
|
23
|
+
* { value: '3', label: 'Option 3' },
|
|
24
|
+
* ]}
|
|
25
|
+
* />
|
|
26
|
+
* @example
|
|
27
|
+
* <caption>Disabled select with placeholder.</caption>
|
|
28
|
+
* <Select
|
|
29
|
+
* disabled={true}
|
|
30
|
+
* placeholder='Placeholder text'
|
|
31
|
+
* options={[{ value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }]}
|
|
32
|
+
* />
|
|
33
|
+
* @example
|
|
34
|
+
* <caption>Select with selected value and change handler.</caption>
|
|
35
|
+
* <Select
|
|
36
|
+
* value={selectedValue}
|
|
37
|
+
* onChange={(value) => setSelectedValue(value)}
|
|
38
|
+
* options={[{ value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }]}
|
|
39
|
+
* />
|
|
40
|
+
* @example
|
|
41
|
+
* <caption>Select using custom renderers for menu items and selected value.</caption>
|
|
42
|
+
* <Select
|
|
43
|
+
* options={[
|
|
44
|
+
* { value: 'yellow', label: 'Yellow' },
|
|
45
|
+
* { value: 'green', label: 'Green' },
|
|
46
|
+
* { value: 'red', label: 'Red' },
|
|
47
|
+
* ]}
|
|
48
|
+
* value={selectedValue}
|
|
49
|
+
* placeholder='Placeholder text'
|
|
50
|
+
* itemRenderer={(option, itemProps) => (
|
|
51
|
+
* <MenuItem
|
|
52
|
+
* style={{ color: option.value }}
|
|
53
|
+
* isSelected={itemProps.isSelected}
|
|
54
|
+
* onClick={() => {
|
|
55
|
+
* setSelectedValue(option.value);
|
|
56
|
+
* itemProps.close();
|
|
57
|
+
* }}
|
|
58
|
+
* role='option'
|
|
59
|
+
* ref={(el) => itemProps.isSelected && el?.scrollIntoView()}
|
|
60
|
+
* >
|
|
61
|
+
* {option.label}
|
|
62
|
+
* </MenuItem>
|
|
63
|
+
* )}
|
|
64
|
+
* selectedItemRenderer={(option) => (
|
|
65
|
+
* <span style={{ backgroundColor: option.value }}>{option.label}</span>
|
|
66
|
+
* )}
|
|
67
|
+
* />
|
|
68
|
+
*/
|
|
69
|
+
export declare const Select: <T>(props: SelectProps<T> & {
|
|
70
|
+
ref?: React.ForwardedRef<HTMLElement> | undefined;
|
|
71
|
+
}) => JSX.Element;
|
|
72
|
+
export type SelectProps<T> = Omit<React.ComponentPropsWithoutRef<'div'>, 'onChange' | 'placeholder' | 'value' | 'defaultValue'> & (({
|
|
5
73
|
/**
|
|
6
|
-
*
|
|
74
|
+
* If true, the native `<select>` element will be rendered.
|
|
75
|
+
*
|
|
76
|
+
* Extra props, such as `name` can be passed to the `<select>` using `triggerProps`.
|
|
77
|
+
*
|
|
78
|
+
* @default false
|
|
7
79
|
*/
|
|
8
|
-
|
|
80
|
+
native: true;
|
|
81
|
+
} & NativeSelectProps) | ({
|
|
82
|
+
native?: false;
|
|
83
|
+
} & CustomSelectProps<T> & {
|
|
9
84
|
/**
|
|
10
|
-
*
|
|
85
|
+
* styleType is only supported for `<Select native>`.
|
|
11
86
|
*/
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
|
|
87
|
+
styleType?: never;
|
|
88
|
+
}));
|
|
89
|
+
type NativeSelectProps = SelectCommonProps & {
|
|
15
90
|
/**
|
|
16
|
-
*
|
|
91
|
+
* Selected option value.
|
|
92
|
+
*
|
|
93
|
+
* Must be a string, because it is passed as an attribute to the native <select>.
|
|
94
|
+
*
|
|
95
|
+
* Alternatively, pass `null` to reset the value.
|
|
17
96
|
*/
|
|
18
|
-
|
|
97
|
+
value?: string | null;
|
|
19
98
|
/**
|
|
20
|
-
*
|
|
99
|
+
* Callback invoked when the selected value changes.
|
|
21
100
|
*/
|
|
22
|
-
|
|
101
|
+
onChange?: (value: string, event: React.ChangeEvent<HTMLSelectElement>) => void;
|
|
23
102
|
/**
|
|
24
|
-
*
|
|
25
|
-
* Use 'large' when any of the select options have `sublabel`.
|
|
103
|
+
* Array of options that populates the select menu.
|
|
26
104
|
*
|
|
27
|
-
*
|
|
105
|
+
* The `value` property of each option must be a string.
|
|
28
106
|
*/
|
|
29
|
-
|
|
107
|
+
options: Array<{
|
|
108
|
+
label: string;
|
|
109
|
+
value: string;
|
|
110
|
+
disabled?: boolean;
|
|
111
|
+
}>;
|
|
30
112
|
/**
|
|
31
|
-
*
|
|
113
|
+
* Default value that is selected on initial render. This is useful when you don't want to
|
|
114
|
+
* maintain your own state but still want to control the initial value.
|
|
115
|
+
*
|
|
116
|
+
* If not passed, the first option (or placeholder) will be automatically selected.
|
|
32
117
|
*/
|
|
33
|
-
|
|
118
|
+
defaultValue?: string;
|
|
34
119
|
/**
|
|
35
|
-
*
|
|
36
|
-
* SVG icon component shown on the left.
|
|
120
|
+
* Props to pass to the select element.
|
|
37
121
|
*/
|
|
38
|
-
|
|
122
|
+
triggerProps?: Omit<React.ComponentPropsWithRef<'select'>, 'size'>;
|
|
123
|
+
required?: boolean;
|
|
124
|
+
multiple?: never;
|
|
125
|
+
} & NativeSelectStyleTypeProps;
|
|
126
|
+
type NativeSelectStyleTypeProps = {
|
|
39
127
|
/**
|
|
40
|
-
*
|
|
128
|
+
* Style of the select.
|
|
129
|
+
* Use 'borderless' to hide outline.
|
|
130
|
+
* @default 'default'
|
|
41
131
|
*/
|
|
42
|
-
|
|
132
|
+
styleType?: 'default';
|
|
43
133
|
/**
|
|
44
|
-
*
|
|
134
|
+
* Placeholder for when no item is selected.
|
|
135
|
+
*
|
|
136
|
+
* Will be rendered as a disabled option at the top of the list, and automatically
|
|
137
|
+
* selected when no `value` or `defaultValue` is provided.
|
|
138
|
+
*
|
|
139
|
+
* Not allowed when `styleType` is `borderless`.
|
|
140
|
+
*/
|
|
141
|
+
placeholder?: string;
|
|
142
|
+
} | {
|
|
143
|
+
styleType: 'borderless';
|
|
144
|
+
placeholder?: never;
|
|
145
|
+
};
|
|
146
|
+
type SelectCommonProps = {
|
|
147
|
+
/**
|
|
148
|
+
* Disables select.
|
|
149
|
+
* @default false
|
|
45
150
|
*/
|
|
46
151
|
disabled?: boolean;
|
|
47
152
|
/**
|
|
48
|
-
*
|
|
153
|
+
* Modify size of select.
|
|
49
154
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
155
|
+
size?: 'small' | 'large';
|
|
156
|
+
/**
|
|
157
|
+
* Status of select.
|
|
158
|
+
*/
|
|
159
|
+
status?: 'positive' | 'warning' | 'negative';
|
|
160
|
+
};
|
|
161
|
+
export type CustomSelectProps<T> = SelectCommonProps & {
|
|
162
|
+
/**
|
|
163
|
+
* Placeholder when no item is selected.
|
|
164
|
+
*/
|
|
165
|
+
placeholder?: React.ReactNode;
|
|
166
|
+
/**
|
|
167
|
+
* Array of options that populates the select menu.
|
|
168
|
+
*/
|
|
169
|
+
options: SelectOption<T>[];
|
|
170
|
+
/**
|
|
171
|
+
* Custom renderer for an item in the dropdown list. `MenuItem` item props are going to be populated if not provided.
|
|
172
|
+
*/
|
|
173
|
+
itemRenderer?: (option: SelectOption<T>, itemProps: ItemRendererProps) => JSX.Element;
|
|
174
|
+
/**
|
|
175
|
+
* Custom class for menu.
|
|
176
|
+
*/
|
|
177
|
+
menuClassName?: string;
|
|
178
|
+
/**
|
|
179
|
+
* Custom style for menu.
|
|
180
|
+
*/
|
|
181
|
+
menuStyle?: React.CSSProperties;
|
|
182
|
+
/**
|
|
183
|
+
* Props to customize Popover behavior.
|
|
184
|
+
*/
|
|
185
|
+
popoverProps?: Pick<Parameters<typeof usePopover>[0], 'visible' | 'onVisibleChange' | 'placement' | 'matchWidth' | 'closeOnOutsideClick'>;
|
|
186
|
+
/**
|
|
187
|
+
* Props to pass to the select button (trigger) element.
|
|
188
|
+
*/
|
|
189
|
+
triggerProps?: React.ComponentPropsWithRef<'div'>;
|
|
190
|
+
} & SelectMultipleTypeProps<T> & Omit<React.ComponentPropsWithoutRef<'div'>, 'size' | 'disabled' | 'placeholder' | 'onChange'>;
|
|
52
191
|
export type SelectValueChangeEvent = 'added' | 'removed';
|
|
53
192
|
export type SelectMultipleTypeProps<T> = {
|
|
54
193
|
/**
|
|
@@ -78,98 +217,52 @@ export type SelectMultipleTypeProps<T> = {
|
|
|
78
217
|
value?: T[];
|
|
79
218
|
onChange?: (value: T, event: SelectValueChangeEvent) => void;
|
|
80
219
|
};
|
|
81
|
-
export type
|
|
220
|
+
export type ItemRendererProps = {
|
|
82
221
|
/**
|
|
83
|
-
*
|
|
222
|
+
* Close handler that closes the dropdown.
|
|
84
223
|
*/
|
|
85
|
-
|
|
224
|
+
close: () => void;
|
|
86
225
|
/**
|
|
87
|
-
*
|
|
226
|
+
* Indicates whether an item is selected.
|
|
88
227
|
*/
|
|
89
|
-
|
|
228
|
+
isSelected: boolean;
|
|
229
|
+
};
|
|
230
|
+
export type SelectOption<T> = {
|
|
90
231
|
/**
|
|
91
|
-
*
|
|
92
|
-
* @default false
|
|
232
|
+
* Label of the item used in dropdown list and when selected.
|
|
93
233
|
*/
|
|
94
|
-
|
|
234
|
+
label: string;
|
|
95
235
|
/**
|
|
96
|
-
*
|
|
236
|
+
* Sublabel of the item shown below the label.
|
|
97
237
|
*/
|
|
98
|
-
|
|
238
|
+
sublabel?: React.ReactNode;
|
|
99
239
|
/**
|
|
100
|
-
*
|
|
240
|
+
* Modify height of the item.
|
|
241
|
+
* Use 'large' when any of the select options have `sublabel`.
|
|
242
|
+
*
|
|
243
|
+
* Defaults to 'large' if `sublabel` provided, otherwise 'default'.
|
|
101
244
|
*/
|
|
102
|
-
|
|
245
|
+
size?: 'default' | 'large';
|
|
103
246
|
/**
|
|
104
|
-
*
|
|
247
|
+
* Value of the item.
|
|
105
248
|
*/
|
|
106
|
-
|
|
249
|
+
value: T;
|
|
107
250
|
/**
|
|
108
|
-
*
|
|
251
|
+
* @deprecated Use startIcon
|
|
252
|
+
* SVG icon component shown on the left.
|
|
109
253
|
*/
|
|
110
|
-
|
|
254
|
+
icon?: JSX.Element;
|
|
111
255
|
/**
|
|
112
|
-
*
|
|
256
|
+
* SVG icon component shown on the left.
|
|
113
257
|
*/
|
|
114
|
-
|
|
258
|
+
startIcon?: JSX.Element;
|
|
115
259
|
/**
|
|
116
|
-
*
|
|
260
|
+
* Item is disabled.
|
|
117
261
|
*/
|
|
118
|
-
|
|
262
|
+
disabled?: boolean;
|
|
119
263
|
/**
|
|
120
|
-
*
|
|
264
|
+
* Any other props.
|
|
121
265
|
*/
|
|
122
|
-
|
|
123
|
-
} &
|
|
124
|
-
|
|
125
|
-
* Select component to select value from options.
|
|
126
|
-
* Generic type is used for value. It prevents you from mistakenly using other types in `options`, `value` and `onChange`.
|
|
127
|
-
* @example
|
|
128
|
-
* <caption>Basic select.</caption>
|
|
129
|
-
* <Select<number> options={[{ value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }]} />
|
|
130
|
-
* @example
|
|
131
|
-
* <caption>Disabled select with placeholder.</caption>
|
|
132
|
-
* <Select
|
|
133
|
-
* disabled={true}
|
|
134
|
-
* placeholder='Placeholder text'
|
|
135
|
-
* options={[{ value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }]}
|
|
136
|
-
* />
|
|
137
|
-
* @example
|
|
138
|
-
* <caption>Select with selected value and change handler.</caption>
|
|
139
|
-
* <Select<number>
|
|
140
|
-
* value={selectedValue}
|
|
141
|
-
* onChange={(value) => setSelectedValue(value)}
|
|
142
|
-
* options={[{ value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }]}
|
|
143
|
-
* />
|
|
144
|
-
* @example
|
|
145
|
-
* <caption>Select using custom renderers for menu items and selected value.</caption>
|
|
146
|
-
* <Select<string>
|
|
147
|
-
* options={[
|
|
148
|
-
* { value: 'yellow', label: 'Yellow' },
|
|
149
|
-
* { value: 'green', label: 'Green' },
|
|
150
|
-
* { value: 'red', label: 'Red' },
|
|
151
|
-
* ]}
|
|
152
|
-
* value={selectedValue}
|
|
153
|
-
* placeholder='Placeholder text'
|
|
154
|
-
* itemRenderer={(option, itemProps) => (
|
|
155
|
-
* <MenuItem
|
|
156
|
-
* style={{ color: option.value }}
|
|
157
|
-
* isSelected={itemProps.isSelected}
|
|
158
|
-
* onClick={() => {
|
|
159
|
-
* setSelectedValue(option.value);
|
|
160
|
-
* itemProps.close();
|
|
161
|
-
* }}
|
|
162
|
-
* role='option'
|
|
163
|
-
* ref={(el) => itemProps.isSelected && el?.scrollIntoView()}
|
|
164
|
-
* >
|
|
165
|
-
* {option.label}
|
|
166
|
-
* </MenuItem>
|
|
167
|
-
* )}
|
|
168
|
-
* selectedItemRenderer={(option) => (
|
|
169
|
-
* <span style={{ backgroundColor: option.value }}>{option.label}</span>
|
|
170
|
-
* )}
|
|
171
|
-
* />
|
|
172
|
-
*/
|
|
173
|
-
export declare const Select: <T>(props: SelectProps<T> & {
|
|
174
|
-
ref?: React.ForwardedRef<HTMLElement> | undefined;
|
|
175
|
-
}) => JSX.Element;
|
|
266
|
+
[key: string]: unknown;
|
|
267
|
+
} & CommonProps;
|
|
268
|
+
export {};
|
|
@@ -40,19 +40,29 @@ const SelectTag_js_1 = require("./SelectTag.js");
|
|
|
40
40
|
const SelectTagContainer_js_1 = require("./SelectTagContainer.js");
|
|
41
41
|
const Icon_js_1 = require("../Icon/Icon.js");
|
|
42
42
|
const Popover_js_1 = require("../Popover/Popover.js");
|
|
43
|
-
|
|
44
|
-
return multiple;
|
|
45
|
-
};
|
|
46
|
-
// Type guard for multiple did not work
|
|
47
|
-
const isSingleOnChange = (onChange, multiple) => {
|
|
48
|
-
return !multiple;
|
|
49
|
-
};
|
|
43
|
+
// ----------------------------------------------------------------------------
|
|
50
44
|
/**
|
|
51
45
|
* Select component to select value from options.
|
|
52
46
|
* Generic type is used for value. It prevents you from mistakenly using other types in `options`, `value` and `onChange`.
|
|
53
47
|
* @example
|
|
54
48
|
* <caption>Basic select.</caption>
|
|
55
|
-
* <Select
|
|
49
|
+
* <Select
|
|
50
|
+
* options={[
|
|
51
|
+
* { value: '1', label: 'Option 1' },
|
|
52
|
+
* { value: '2', label: 'Option 2' },
|
|
53
|
+
* { value: '3', label: 'Option 3' },
|
|
54
|
+
* ]}
|
|
55
|
+
* />
|
|
56
|
+
* @example
|
|
57
|
+
* <caption>Native select.</caption>
|
|
58
|
+
* <Select
|
|
59
|
+
* native
|
|
60
|
+
* options={[
|
|
61
|
+
* { value: '1', label: 'Option 1' },
|
|
62
|
+
* { value: '2', label: 'Option 2' },
|
|
63
|
+
* { value: '3', label: 'Option 3' },
|
|
64
|
+
* ]}
|
|
65
|
+
* />
|
|
56
66
|
* @example
|
|
57
67
|
* <caption>Disabled select with placeholder.</caption>
|
|
58
68
|
* <Select
|
|
@@ -62,14 +72,14 @@ const isSingleOnChange = (onChange, multiple) => {
|
|
|
62
72
|
* />
|
|
63
73
|
* @example
|
|
64
74
|
* <caption>Select with selected value and change handler.</caption>
|
|
65
|
-
* <Select
|
|
75
|
+
* <Select
|
|
66
76
|
* value={selectedValue}
|
|
67
77
|
* onChange={(value) => setSelectedValue(value)}
|
|
68
78
|
* options={[{ value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }]}
|
|
69
79
|
* />
|
|
70
80
|
* @example
|
|
71
81
|
* <caption>Select using custom renderers for menu items and selected value.</caption>
|
|
72
|
-
* <Select
|
|
82
|
+
* <Select
|
|
73
83
|
* options={[
|
|
74
84
|
* { value: 'yellow', label: 'Yellow' },
|
|
75
85
|
* { value: 'green', label: 'Green' },
|
|
@@ -97,6 +107,32 @@ const isSingleOnChange = (onChange, multiple) => {
|
|
|
97
107
|
* />
|
|
98
108
|
*/
|
|
99
109
|
exports.Select = React.forwardRef((props, forwardedRef) => {
|
|
110
|
+
const { native, ...rest } = props;
|
|
111
|
+
const Component = native ? NativeSelect : CustomSelect;
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
return React.createElement(Component, { ...rest, ref: forwardedRef });
|
|
115
|
+
});
|
|
116
|
+
// ----------------------------------------------------------------------------
|
|
117
|
+
const NativeSelect = React.forwardRef((props, forwardedRef) => {
|
|
118
|
+
const { triggerProps, options, disabled, placeholder, defaultValue: defaultValueProp = placeholder !== undefined ? '' : undefined, value: valueProp, onChange: onChangeProp, size, status, styleType, required, ...rest } = props;
|
|
119
|
+
return (React.createElement(index_js_1.InputWithIcon, { ...rest, ref: forwardedRef },
|
|
120
|
+
React.createElement(SelectButton, { as: 'select', size: size, status: status, styleType: styleType, disabled: disabled, defaultValue: valueProp === undefined ? defaultValueProp : undefined, value: valueProp === null ? '' : valueProp, required: required, ...triggerProps, onKeyDown: (0, index_js_1.mergeEventHandlers)(triggerProps?.onKeyDown, (event) => {
|
|
121
|
+
// Firefox does not open the menu on Enter, so we need to do it manually.
|
|
122
|
+
if (event.key === 'Enter') {
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
124
|
+
// @ts-ignore
|
|
125
|
+
event.currentTarget.showPicker?.();
|
|
126
|
+
}
|
|
127
|
+
}), onChange: (0, index_js_1.mergeEventHandlers)(triggerProps?.onChange, (event) => {
|
|
128
|
+
onChangeProp?.(event.currentTarget.value, event);
|
|
129
|
+
}) },
|
|
130
|
+
styleType !== 'borderless' && placeholder !== undefined ? (React.createElement("option", { value: '', disabled: true }, placeholder)) : null,
|
|
131
|
+
options.map((option) => (React.createElement("option", { key: option.value, ...option }, option.label)))),
|
|
132
|
+
React.createElement(SelectEndIcon, { disabled: disabled })));
|
|
133
|
+
});
|
|
134
|
+
// ----------------------------------------------------------------------------
|
|
135
|
+
const CustomSelect = React.forwardRef((props, forwardedRef) => {
|
|
100
136
|
const uid = (0, index_js_1.useId)();
|
|
101
137
|
const { options, value: valueProp, onChange: onChangeProp, placeholder, disabled = false, size, itemRenderer, selectedItemRenderer, menuClassName, menuStyle, multiple = false, triggerProps, status, popoverProps, ...rest } = props;
|
|
102
138
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
@@ -190,18 +226,13 @@ exports.Select = React.forwardRef((props, forwardedRef) => {
|
|
|
190
226
|
});
|
|
191
227
|
return (React.createElement(React.Fragment, null,
|
|
192
228
|
React.createElement(index_js_1.InputWithIcon, { ...rest, ref: (0, index_js_1.useMergedRefs)(popover.refs.setPositionReference, forwardedRef) },
|
|
193
|
-
React.createElement(
|
|
194
|
-
'iui-placeholder': (!selectedItems || selectedItems.length === 0) &&
|
|
195
|
-
!!placeholder,
|
|
229
|
+
React.createElement(SelectButton, { ...popover.getReferenceProps(), tabIndex: 0, role: 'combobox', size: size, status: status, "aria-disabled": disabled ? 'true' : undefined, "aria-autocomplete": 'none', "aria-expanded": isOpen, "aria-haspopup": 'listbox', "aria-controls": `${uid}-menu`, ...triggerProps, ref: (0, index_js_1.useMergedRefs)(selectRef, triggerProps?.ref, popover.refs.setReference), className: (0, classnames_1.default)({
|
|
230
|
+
'iui-placeholder': (!selectedItems || selectedItems.length === 0) && !!placeholder,
|
|
196
231
|
'iui-disabled': disabled,
|
|
197
232
|
}, triggerProps?.className) },
|
|
198
233
|
(!selectedItems || selectedItems.length === 0) && (React.createElement(index_js_1.Box, { as: 'span', className: 'iui-content' }, placeholder)),
|
|
199
234
|
isMultipleEnabled(selectedItems, multiple) ? (React.createElement(MultipleSelectButton, { selectedItems: selectedItems, selectedItemsRenderer: selectedItemRenderer, tagRenderer: tagRenderer })) : (React.createElement(SingleSelectButton, { selectedItem: selectedItems, selectedItemRenderer: selectedItemRenderer }))),
|
|
200
|
-
React.createElement(
|
|
201
|
-
'iui-disabled': disabled,
|
|
202
|
-
'iui-open': isOpen,
|
|
203
|
-
}) },
|
|
204
|
-
React.createElement(index_js_1.SvgCaretDownSmall, null)),
|
|
235
|
+
React.createElement(SelectEndIcon, { disabled: disabled, isOpen: isOpen }),
|
|
205
236
|
multiple ? (React.createElement(index_js_1.AutoclearingHiddenLiveRegion, { text: liveRegionSelection })) : null),
|
|
206
237
|
popover.open && (React.createElement(index_js_1.Portal, null,
|
|
207
238
|
React.createElement(Menu_js_1.Menu, { role: 'listbox', className: menuClassName, id: `${uid}-menu`, key: `${uid}-menu`, ...popover.getFloatingProps({
|
|
@@ -213,6 +244,27 @@ exports.Select = React.forwardRef((props, forwardedRef) => {
|
|
|
213
244
|
},
|
|
214
245
|
}), ref: popover.refs.setFloating }, menuItems)))));
|
|
215
246
|
});
|
|
247
|
+
// ----------------------------------------------------------------------------
|
|
248
|
+
// Type guards
|
|
249
|
+
const isMultipleEnabled = (variable, multiple) => {
|
|
250
|
+
return multiple;
|
|
251
|
+
};
|
|
252
|
+
// Type guard for multiple did not work
|
|
253
|
+
const isSingleOnChange = (onChange, multiple) => {
|
|
254
|
+
return !multiple;
|
|
255
|
+
};
|
|
256
|
+
// ----------------------------------------------------------------------------
|
|
257
|
+
const SelectButton = React.forwardRef((props, forwardedRef) => {
|
|
258
|
+
const { size, status, styleType = 'default', ...rest } = props;
|
|
259
|
+
return (React.createElement(index_js_1.Box, { "data-iui-size": size, "data-iui-status": status, "data-iui-variant": styleType !== 'default' ? styleType : undefined, ...rest, ref: forwardedRef, className: (0, classnames_1.default)('iui-select-button', props.className) }));
|
|
260
|
+
});
|
|
261
|
+
// ----------------------------------------------------------------------------
|
|
262
|
+
const SelectEndIcon = React.forwardRef((props, forwardedRef) => {
|
|
263
|
+
const { disabled, isOpen, ...rest } = props;
|
|
264
|
+
return (React.createElement(Icon_js_1.Icon, { "aria-hidden": true, ...rest, ref: forwardedRef, className: (0, classnames_1.default)('iui-end-icon', { 'iui-disabled': disabled, 'iui-open': isOpen }, props.className) },
|
|
265
|
+
React.createElement(index_js_1.SvgCaretDownSmall, null)));
|
|
266
|
+
});
|
|
267
|
+
// ----------------------------------------------------------------------------
|
|
216
268
|
const SingleSelectButton = ({ selectedItem, selectedItemRenderer, }) => {
|
|
217
269
|
const startIcon = selectedItem?.startIcon ?? selectedItem?.icon;
|
|
218
270
|
return (React.createElement(React.Fragment, null,
|
|
@@ -223,6 +275,7 @@ const SingleSelectButton = ({ selectedItem, selectedItemRenderer, }) => {
|
|
|
223
275
|
startIcon && (React.createElement(index_js_1.Box, { as: 'span', className: 'iui-icon', "aria-hidden": true }, startIcon)),
|
|
224
276
|
React.createElement(index_js_1.Box, { as: 'span', className: 'iui-content' }, selectedItem.label)))));
|
|
225
277
|
};
|
|
278
|
+
// ----------------------------------------------------------------------------
|
|
226
279
|
const MultipleSelectButton = ({ selectedItems, selectedItemsRenderer, tagRenderer, }) => {
|
|
227
280
|
const selectedItemsElements = React.useMemo(() => {
|
|
228
281
|
if (!selectedItems) {
|
package/cjs/core/Table/Table.js
CHANGED
|
@@ -290,7 +290,8 @@ const Table = (props) => {
|
|
|
290
290
|
// This is to avoid the old columnOrder from affecting the new columns' columnOrder
|
|
291
291
|
React.useEffect(() => {
|
|
292
292
|
// Check if columns have changed (by value)
|
|
293
|
-
if (
|
|
293
|
+
if (lastPassedColumns.current.length > 0 &&
|
|
294
|
+
JSON.stringify(lastPassedColumns.current) !== JSON.stringify(columns)) {
|
|
294
295
|
instance.setColumnOrder([]);
|
|
295
296
|
}
|
|
296
297
|
lastPassedColumns.current = columns;
|
package/cjs/core/Tabs/Tabs.js
CHANGED
|
@@ -71,13 +71,14 @@ const TabList = React.forwardRef((props, ref) => {
|
|
|
71
71
|
}, className), role: 'tablist', ref: refs, ...rest },
|
|
72
72
|
React.createElement(TabListContext.Provider, { value: {
|
|
73
73
|
tabsWidth,
|
|
74
|
+
tablistRef,
|
|
74
75
|
} }, children)));
|
|
75
76
|
});
|
|
76
77
|
TabList.displayName = 'Tabs.TabList';
|
|
77
78
|
const Tab = React.forwardRef((props, forwardedRef) => {
|
|
78
79
|
const { className, children, value, label, ...rest } = props;
|
|
79
80
|
const { orientation, activeValue, setActiveValue, type, setStripeProperties, idPrefix, focusActivationMode, } = (0, index_js_1.useSafeContext)(TabsContext);
|
|
80
|
-
const { tabsWidth } = (0, index_js_1.useSafeContext)(TabListContext);
|
|
81
|
+
const { tabsWidth, tablistRef } = (0, index_js_1.useSafeContext)(TabListContext);
|
|
81
82
|
const tabRef = React.useRef();
|
|
82
83
|
const isActive = activeValue === value;
|
|
83
84
|
const isActiveRef = (0, index_js_1.useLatestRef)(isActive);
|
|
@@ -94,13 +95,27 @@ const Tab = React.forwardRef((props, forwardedRef) => {
|
|
|
94
95
|
(0, index_js_1.useLayoutEffect)(() => {
|
|
95
96
|
const updateStripe = () => {
|
|
96
97
|
const currentTabRect = tabRef.current?.getBoundingClientRect();
|
|
98
|
+
const tabslistRect = tablistRef.current?.getBoundingClientRect();
|
|
99
|
+
// Using getBoundingClientRect() to get decimal granularity.
|
|
100
|
+
// Not using offsetLeft/offsetTop because they round to the nearest integer.
|
|
101
|
+
// Even minor inaccuracies in the stripe position can cause unexpected scroll/scrollbar.
|
|
102
|
+
// See: https://github.com/iTwin/iTwinUI/issues/1870
|
|
103
|
+
const tabsStripePosition = currentTabRect != null && tabslistRect != null
|
|
104
|
+
? {
|
|
105
|
+
horizontal: currentTabRect.x - tabslistRect.x,
|
|
106
|
+
vertical: currentTabRect.y - tabslistRect.y,
|
|
107
|
+
}
|
|
108
|
+
: {
|
|
109
|
+
horizontal: 0,
|
|
110
|
+
vertical: 0,
|
|
111
|
+
};
|
|
97
112
|
setStripeProperties({
|
|
98
113
|
'--iui-tabs-stripe-size': orientation === 'horizontal'
|
|
99
114
|
? `${currentTabRect?.width}px`
|
|
100
115
|
: `${currentTabRect?.height}px`,
|
|
101
116
|
'--iui-tabs-stripe-position': orientation === 'horizontal'
|
|
102
|
-
? `${
|
|
103
|
-
: `${
|
|
117
|
+
? `${tabsStripePosition.horizontal}px`
|
|
118
|
+
: `${tabsStripePosition.vertical}px`,
|
|
104
119
|
});
|
|
105
120
|
};
|
|
106
121
|
if (type !== 'default' && isActive) {
|
|
@@ -112,6 +127,7 @@ const Tab = React.forwardRef((props, forwardedRef) => {
|
|
|
112
127
|
isActive,
|
|
113
128
|
tabsWidth,
|
|
114
129
|
setStripeProperties,
|
|
130
|
+
tablistRef,
|
|
115
131
|
]);
|
|
116
132
|
const onKeyDown = (event) => {
|
|
117
133
|
if (event.altKey) {
|
package/cjs/core/Tile/Tile.d.ts
CHANGED
|
@@ -255,7 +255,7 @@ export declare const Tile: PolymorphicForwardRefComponent<"div", TileLegacyProps
|
|
|
255
255
|
labelProps?: Omit<Omit<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
|
256
256
|
ref?: ((instance: HTMLDivElement | null) => void) | React.RefObject<HTMLDivElement> | null | undefined;
|
|
257
257
|
}, "as" | "children" | "content" | "portal" | keyof {
|
|
258
|
-
placement?: import("@floating-ui/
|
|
258
|
+
placement?: import("@floating-ui/core").Placement | undefined;
|
|
259
259
|
visible?: boolean | undefined;
|
|
260
260
|
onVisibleChange?: ((visible: boolean) => void) | undefined;
|
|
261
261
|
autoUpdateOptions?: {
|
|
@@ -284,7 +284,7 @@ export declare const Tile: PolymorphicForwardRefComponent<"div", TileLegacyProps
|
|
|
284
284
|
content: React.ReactNode;
|
|
285
285
|
children?: React.ReactNode;
|
|
286
286
|
} & import("../utils/index.js").PortalProps & {
|
|
287
|
-
placement?: import("@floating-ui/
|
|
287
|
+
placement?: import("@floating-ui/core").Placement | undefined;
|
|
288
288
|
visible?: boolean | undefined;
|
|
289
289
|
onVisibleChange?: ((visible: boolean) => void) | undefined;
|
|
290
290
|
autoUpdateOptions?: {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { PolymorphicForwardRefComponent } from '../props.js';
|
|
2
|
+
import type { IconProps } from '../../Icon/Icon.js';
|
|
3
|
+
import type { IconButtonProps } from '../../Buttons/IconButton.js';
|
|
2
4
|
export type InputFlexContainerProps = {
|
|
3
5
|
isDisabled?: boolean;
|
|
4
6
|
status?: 'positive' | 'warning' | 'negative';
|
|
@@ -9,3 +11,26 @@ export type InputFlexContainerProps = {
|
|
|
9
11
|
* @private
|
|
10
12
|
*/
|
|
11
13
|
export declare const InputFlexContainer: PolymorphicForwardRefComponent<"div", InputFlexContainerProps>;
|
|
14
|
+
/**
|
|
15
|
+
* Button inside InputFlexContainer that collapses the padding between the button and the input/textarea.
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
export declare const InputFlexContainerButton: PolymorphicForwardRefComponent<"button", Omit<IconButtonProps, "styleType"> & {
|
|
19
|
+
/**
|
|
20
|
+
* Style of the button.
|
|
21
|
+
* Use 'borderless' to hide outline.
|
|
22
|
+
* @default 'borderless'
|
|
23
|
+
*/
|
|
24
|
+
styleType?: IconButtonProps['styleType'];
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Icon inside InputFlexContainer that collapses the padding between the icon and the input/textarea.
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
export declare const InputFlexContainerIcon: PolymorphicForwardRefComponent<"span", Omit<IconProps, "padded"> & {
|
|
31
|
+
/**
|
|
32
|
+
* Option to add padding to the icon.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
padded?: IconProps['padded'];
|
|
36
|
+
}>;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.InputFlexContainer = void 0;
|
|
6
|
+
exports.InputFlexContainerIcon = exports.InputFlexContainerButton = exports.InputFlexContainer = void 0;
|
|
7
7
|
/*---------------------------------------------------------------------------------------------
|
|
8
8
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
9
9
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -11,6 +11,8 @@ exports.InputFlexContainer = void 0;
|
|
|
11
11
|
const react_1 = __importDefault(require("react"));
|
|
12
12
|
const classnames_1 = __importDefault(require("classnames"));
|
|
13
13
|
const Box_js_1 = require("./Box.js");
|
|
14
|
+
const Icon_js_1 = require("../../Icon/Icon.js");
|
|
15
|
+
const IconButton_js_1 = require("../../Buttons/IconButton.js");
|
|
14
16
|
/**
|
|
15
17
|
* Utility component for input container with display flex abilities.
|
|
16
18
|
* @private
|
|
@@ -19,3 +21,19 @@ exports.InputFlexContainer = react_1.default.forwardRef((props, ref) => {
|
|
|
19
21
|
const { isDisabled, status, children, className, size, style, ...rest } = props;
|
|
20
22
|
return (react_1.default.createElement(Box_js_1.Box, { className: (0, classnames_1.default)('iui-input-flex-container', className), "data-iui-status": status, "data-iui-size": size, "data-iui-disabled": isDisabled ? 'true' : undefined, ref: ref, style: style, ...rest }, children));
|
|
21
23
|
});
|
|
24
|
+
/**
|
|
25
|
+
* Button inside InputFlexContainer that collapses the padding between the button and the input/textarea.
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
exports.InputFlexContainerButton = react_1.default.forwardRef((props, ref) => {
|
|
29
|
+
const { className, ...rest } = props;
|
|
30
|
+
return (react_1.default.createElement(IconButton_js_1.IconButton, { ref: ref, className: (0, classnames_1.default)('iui-input-flex-container-icon', className), styleType: 'borderless', ...rest }));
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Icon inside InputFlexContainer that collapses the padding between the icon and the input/textarea.
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
exports.InputFlexContainerIcon = react_1.default.forwardRef((props, ref) => {
|
|
37
|
+
const { className, ...rest } = props;
|
|
38
|
+
return (react_1.default.createElement(Icon_js_1.Icon, { ref: ref, className: (0, classnames_1.default)('iui-input-flex-container-icon', className), padded: true, ...rest }));
|
|
39
|
+
});
|