@react-md/core 6.4.0 → 6.5.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/dist/_a11y.scss +3 -1
- package/dist/_box-shadows.scss +20 -12
- package/dist/_core.scss +1 -1
- package/dist/_utils.scss +25 -11
- package/dist/app-bar/_app-bar.scss +3 -3
- package/dist/autocomplete/_autocomplete.scss +20 -16
- package/dist/avatar/_avatar.scss +2 -1
- package/dist/button/_button.scss +9 -5
- package/dist/card/_card.scss +6 -6
- package/dist/chip/_chip.scss +6 -6
- package/dist/dialog/_dialog.scss +6 -6
- package/dist/divider/_divider.scss +6 -2
- package/dist/form/Select.d.ts +24 -0
- package/dist/form/Select.js +14 -3
- package/dist/form/Select.js.map +1 -1
- package/dist/form/SelectedOption.d.ts +1 -2
- package/dist/form/SelectedOption.js +2 -2
- package/dist/form/SelectedOption.js.map +1 -1
- package/dist/form/_input-toggle.scss +6 -5
- package/dist/form/_label.scss +2 -2
- package/dist/form/_legend.scss +22 -13
- package/dist/form/_slider.scss +7 -5
- package/dist/form/_switch.scss +7 -5
- package/dist/form/_text-field.scss +13 -11
- package/dist/form/defaultGetSelectedOptionChildren.d.ts +1 -0
- package/dist/form/getSelectedOptionChildren.d.ts +1 -0
- package/dist/form/legendStyles.d.ts +1 -1
- package/dist/form/legendStyles.js.map +1 -1
- package/dist/interaction/_interaction.scss +5 -3
- package/dist/snackbar/_snackbar.scss +3 -3
- package/dist/tabs/_tabs.scss +5 -6
- package/dist/theme/_a11y.scss +3 -1
- package/dist/theme/_theme.scss +16 -12
- package/dist/window-splitter/_window-splitter.scss +15 -17
- package/package.json +7 -7
- package/src/form/Select.tsx +53 -2
- package/src/form/SelectedOption.tsx +2 -4
- package/src/form/legendStyles.ts +1 -1
package/dist/_a11y.scss
CHANGED
|
@@ -183,5 +183,7 @@ $_linear-channel-values: (
|
|
|
183
183
|
$light-contrast: _contrast($background-color, $light-color);
|
|
184
184
|
$dark-contrast: _contrast($background-color, $dark-color);
|
|
185
185
|
|
|
186
|
-
@return if(
|
|
186
|
+
@return if(
|
|
187
|
+
sass($light-contrast > $dark-contrast): $light-color; else: $dark-color
|
|
188
|
+
);
|
|
187
189
|
}
|
package/dist/_box-shadows.scss
CHANGED
|
@@ -203,7 +203,11 @@ $box-shadow-3-layers: (
|
|
|
203
203
|
$create-pseudo: true,
|
|
204
204
|
$position-relative: true
|
|
205
205
|
) {
|
|
206
|
-
$pseudo-selector:
|
|
206
|
+
$pseudo-selector: "&::after";
|
|
207
|
+
@if $pseudo-before {
|
|
208
|
+
$pseudo-selector: "&::before";
|
|
209
|
+
}
|
|
210
|
+
|
|
207
211
|
$suffix: string.slice($pseudo-selector, 2);
|
|
208
212
|
$active-string: "";
|
|
209
213
|
|
|
@@ -230,7 +234,11 @@ $box-shadow-3-layers: (
|
|
|
230
234
|
@for $i from 1 to list.length($active-selectors) + 1 {
|
|
231
235
|
$selector: list.nth($active-selectors, $i);
|
|
232
236
|
|
|
233
|
-
$
|
|
237
|
+
$maybe-comma: "";
|
|
238
|
+
@if $i > 1 {
|
|
239
|
+
$maybe-comma: ", ";
|
|
240
|
+
}
|
|
241
|
+
$prefix: $active-string + $maybe-comma;
|
|
234
242
|
$active-string: $prefix + $selector + $suffix;
|
|
235
243
|
}
|
|
236
244
|
}
|
|
@@ -282,16 +290,16 @@ $box-shadow-3-layers: (
|
|
|
282
290
|
$opacity-boost: 0,
|
|
283
291
|
$position-relative: true
|
|
284
292
|
) {
|
|
285
|
-
$start-shadow:
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
box-shadow($start-z-value, $color, $opacity-boost)
|
|
289
|
-
|
|
290
|
-
$end-
|
|
291
|
-
$end-z-value
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
293
|
+
$start-shadow: none;
|
|
294
|
+
$end-shadow: null;
|
|
295
|
+
@if $start-z-value != none and $start-z-value != 0 {
|
|
296
|
+
$start-shadow: box-shadow($start-z-value, $color, $opacity-boost);
|
|
297
|
+
}
|
|
298
|
+
@if $end-z-value {
|
|
299
|
+
@if $end-z-value != none and $end-z-value != 0 {
|
|
300
|
+
$end-shadow: box-shadow($end-z-value, $color, $opacity-boost);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
295
303
|
|
|
296
304
|
@include box-shadow-transition(
|
|
297
305
|
$start-shadow,
|
package/dist/_core.scss
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
@forward "box-shadows";
|
|
16
16
|
@forward "interaction/interaction" as interaction-*;
|
|
17
17
|
@forward "draggable/draggable" as draggable-*;
|
|
18
|
+
@forward "divider/divider" as divider-*;
|
|
18
19
|
@forward "window-splitter/window-splitter" as window-splitter-*;
|
|
19
20
|
@forward "icon/icon" as icon-*;
|
|
20
|
-
@forward "divider/divider" as divider-*;
|
|
21
21
|
@forward "progress/progress" as progress-*;
|
|
22
22
|
@forward "overlay/overlay" as overlay-*;
|
|
23
23
|
@forward "button/button" as button-*;
|
package/dist/_utils.scss
CHANGED
|
@@ -97,30 +97,40 @@ $_swappable-properties: text-align;
|
|
|
97
97
|
/// @param {String} error-message - The additional error message to display
|
|
98
98
|
/// @returns {any} the value from the list or map
|
|
99
99
|
@function validate($options, $key-or-value, $error-message) {
|
|
100
|
-
$options
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
$options
|
|
104
|
-
);
|
|
100
|
+
@if meta.type-of($options) == string {
|
|
101
|
+
$options: list.append((), $options);
|
|
102
|
+
}
|
|
105
103
|
|
|
106
104
|
$type: meta.type-of($options);
|
|
107
105
|
$is-map: $type == map;
|
|
108
106
|
$is-list: $type == list;
|
|
109
107
|
|
|
110
108
|
@if $disable-validation {
|
|
111
|
-
@
|
|
109
|
+
@if $is-list {
|
|
110
|
+
@return $key-or-value;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@return map.get($options, $key-or-value);
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
@if not $is-map and not $is-list {
|
|
115
117
|
@error "Unable to validate anything except for lists and maps at this time. Received: '#{$options}'.";
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
$choices:
|
|
120
|
+
$choices: $options;
|
|
121
|
+
@if $is-map {
|
|
122
|
+
$choices: map.keys($options);
|
|
123
|
+
}
|
|
124
|
+
|
|
119
125
|
@if not list.index($choices, $key-or-value) {
|
|
120
126
|
@error "Invalid #{$error-message}: '#{$key-or-value}'. Choose one of: #{$choices}";
|
|
121
127
|
}
|
|
122
128
|
|
|
123
|
-
@
|
|
129
|
+
@if $is-list {
|
|
130
|
+
@return $key-or-value;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@return map.get($options, $key-or-value);
|
|
124
134
|
}
|
|
125
135
|
|
|
126
136
|
/// Used to get a custom property variable name.
|
|
@@ -272,7 +282,7 @@ $_swappable-properties: text-align;
|
|
|
272
282
|
content: "";
|
|
273
283
|
inset: $inset;
|
|
274
284
|
pointer-events: none;
|
|
275
|
-
position: if($fixed
|
|
285
|
+
position: if(sass($fixed): fixed; else: absolute);
|
|
276
286
|
z-index: $z-index;
|
|
277
287
|
}
|
|
278
288
|
|
|
@@ -349,8 +359,12 @@ $_swappable-properties: text-align;
|
|
|
349
359
|
$css-modules: false,
|
|
350
360
|
$parent-selector: true
|
|
351
361
|
) {
|
|
352
|
-
|
|
353
|
-
|
|
362
|
+
@if $css-modules {
|
|
363
|
+
$selector: ":global #{$selector} :local";
|
|
364
|
+
}
|
|
365
|
+
@if $parent-selector {
|
|
366
|
+
$selector: "#{$selector} &";
|
|
367
|
+
}
|
|
354
368
|
|
|
355
369
|
#{$selector} {
|
|
356
370
|
@content;
|
|
@@ -115,10 +115,10 @@ $light-theme-surface-color: a11y.contrast-color(
|
|
|
115
115
|
/// The background color to use when `theme="surface"` and using the global dark
|
|
116
116
|
/// theme
|
|
117
117
|
/// @type Color
|
|
118
|
+
// prettier-ignore
|
|
118
119
|
$dark-theme-surface-background-color: if(
|
|
119
|
-
theme.$disable-dark-elevation
|
|
120
|
-
theme.$dark-
|
|
121
|
-
map.get(theme.$dark-elevation-colors, $fixed-elevation)
|
|
120
|
+
sass(theme.$disable-dark-elevation): theme.$dark-theme-surface-color;
|
|
121
|
+
else: map.get(theme.$dark-elevation-colors, $fixed-elevation)
|
|
122
122
|
) !default;
|
|
123
123
|
|
|
124
124
|
/// The text color to use when `theme="surface"` and using the global dark theme
|
|
@@ -195,21 +195,22 @@ $variables: (
|
|
|
195
195
|
@function _right-addon-calc() {
|
|
196
196
|
$calc-spacing: get-var(addon-spacing);
|
|
197
197
|
$calc-total-gap: calc(get-var(gap-count, 0) * get-var(addon-gap));
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
" + " + get-var(clear-button-size, 0px)
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
" + " + get-var(dropdown-button-size, 0px)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
" + " + get-var(circular-progress-size, 0px)
|
|
212
|
-
|
|
198
|
+
|
|
199
|
+
$calc-clear-button: "";
|
|
200
|
+
@if not $disable-clear-button {
|
|
201
|
+
$calc-clear-button: " + " + get-var(clear-button-size, 0px);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
$calc-dropdown-button: "";
|
|
205
|
+
@if not $disable-dropdown-button {
|
|
206
|
+
$calc-dropdown-button: " + " + get-var(dropdown-button-size, 0px);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
$calc-circular-progress: "";
|
|
210
|
+
@if not $disable-circular-progress {
|
|
211
|
+
$calc-circular-progress: " + " + get-var(circular-progress-size, 0px);
|
|
212
|
+
}
|
|
213
|
+
|
|
213
214
|
$calc-addon-size: $calc-clear-button + $calc-dropdown-button +
|
|
214
215
|
$calc-circular-progress;
|
|
215
216
|
|
|
@@ -223,7 +224,10 @@ $variables: (
|
|
|
223
224
|
/// @param {String} addon-selector
|
|
224
225
|
/// @returns {String} a class name selector
|
|
225
226
|
@function _add-has-selector($appending-selector, $addon-selector) {
|
|
226
|
-
$prefix:
|
|
227
|
+
$prefix: "";
|
|
228
|
+
@if not string.length($appending-selector) {
|
|
229
|
+
$prefix: "&";
|
|
230
|
+
}
|
|
227
231
|
|
|
228
232
|
@return $appending-selector + $prefix + ":has(" + $addon-selector + ")";
|
|
229
233
|
}
|
package/dist/avatar/_avatar.scss
CHANGED
|
@@ -165,7 +165,8 @@ $variables: (
|
|
|
165
165
|
/// @param {Boolean} disable-prefix [false] - Set to `true` to disable the
|
|
166
166
|
/// `.rmd-avatar--` prefix for the class name
|
|
167
167
|
@mixin custom-color($name, $color, $background-color, $disable-prefix: false) {
|
|
168
|
-
|
|
168
|
+
// prettier-ignore
|
|
169
|
+
$class-name: if(sass($disable-prefix): $name; else: ".rmd-avatar--#{$name}");
|
|
169
170
|
|
|
170
171
|
#{$class-name} {
|
|
171
172
|
@include set-var(background-color, $background-color);
|
package/dist/button/_button.scss
CHANGED
|
@@ -408,6 +408,14 @@ $variables: (
|
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
@if not $disable-contained {
|
|
411
|
+
$contained-elevation-end: null;
|
|
412
|
+
@if not
|
|
413
|
+
$disable-contained-pressed-elevation and
|
|
414
|
+
$contained-pressed-elevation
|
|
415
|
+
{
|
|
416
|
+
$contained-elevation-end: $contained-pressed-elevation;
|
|
417
|
+
}
|
|
418
|
+
|
|
411
419
|
&--contained {
|
|
412
420
|
// contained buttons should _normally_ always force dark background
|
|
413
421
|
// colors for the interaction states This means use the default light
|
|
@@ -424,11 +432,7 @@ $variables: (
|
|
|
424
432
|
|
|
425
433
|
@include box-shadows.elevation-transition(
|
|
426
434
|
$contained-elevation,
|
|
427
|
-
|
|
428
|
-
$disable-contained-pressed-elevation,
|
|
429
|
-
null,
|
|
430
|
-
$contained-pressed-elevation
|
|
431
|
-
),
|
|
435
|
+
$contained-elevation-end,
|
|
432
436
|
"&.rmd-button--pressed",
|
|
433
437
|
$pseudo-before: false,
|
|
434
438
|
$position-relative: false
|
package/dist/card/_card.scss
CHANGED
|
@@ -59,10 +59,10 @@ $light-theme-background-color: theme.theme-get-var(surface-color) !default;
|
|
|
59
59
|
|
|
60
60
|
/// The background color to use when using the global dark theme
|
|
61
61
|
/// @type Color
|
|
62
|
+
// prettier-ignore
|
|
62
63
|
$dark-theme-background-color: if(
|
|
63
|
-
theme.$disable-dark-elevation
|
|
64
|
-
theme.$dark-
|
|
65
|
-
map.get(theme.$dark-elevation-colors, $elevation)
|
|
64
|
+
sass(theme.$disable-dark-elevation): theme.$dark-theme-surface-color;
|
|
65
|
+
else: map.get(theme.$dark-elevation-colors, $elevation)
|
|
66
66
|
) !default;
|
|
67
67
|
|
|
68
68
|
/// The default card background color
|
|
@@ -226,10 +226,10 @@ $variables: (background-color, color);
|
|
|
226
226
|
column-gap: $header-spacing;
|
|
227
227
|
display: flex;
|
|
228
228
|
max-width: 100%;
|
|
229
|
+
// prettier-ignore
|
|
229
230
|
padding: if(
|
|
230
|
-
$header-padding == $header-padding-top or not $header-padding-top
|
|
231
|
-
$header-padding
|
|
232
|
-
$header-padding-top $header-padding $header-padding
|
|
231
|
+
sass($header-padding == $header-padding-top or not $header-padding-top): $header-padding;
|
|
232
|
+
else: $header-padding-top $header-padding $header-padding
|
|
233
233
|
);
|
|
234
234
|
}
|
|
235
235
|
|
package/dist/chip/_chip.scss
CHANGED
|
@@ -182,10 +182,10 @@ $solid-light-color: a11y.contrast-color($solid-light-background-color) !default;
|
|
|
182
182
|
|
|
183
183
|
/// The dark theme background color for the `theme="solid"`
|
|
184
184
|
/// @type Color
|
|
185
|
+
// prettier-ignore
|
|
185
186
|
$solid-dark-background-color: if(
|
|
186
|
-
theme.$disable-dark-elevation
|
|
187
|
-
|
|
188
|
-
map.get(theme.$dark-elevation-colors, 12)
|
|
187
|
+
sass(theme.$disable-dark-elevation): colors.$grey-900;
|
|
188
|
+
else: map.get(theme.$dark-elevation-colors, 12)
|
|
189
189
|
) !default;
|
|
190
190
|
|
|
191
191
|
/// The dark theme background color for the `theme="solid"` and the `Chip` is
|
|
@@ -261,10 +261,10 @@ $outline-dark-color: $outline-light-color !default;
|
|
|
261
261
|
|
|
262
262
|
/// The background-color to use in dark themes when `theme="outline"`
|
|
263
263
|
/// @type Color
|
|
264
|
+
// prettier-ignore
|
|
264
265
|
$outline-dark-background-color: if(
|
|
265
|
-
theme.$disable-dark-elevation
|
|
266
|
-
theme.$dark-
|
|
267
|
-
map.get(theme.$dark-elevation-colors, $outline-raisable-box-shadow-z-value)
|
|
266
|
+
sass(theme.$disable-dark-elevation): theme.$dark-theme-surface-color;
|
|
267
|
+
else: map.get( theme.$dark-elevation-colors, $outline-raisable-box-shadow-z-value)
|
|
268
268
|
) !default;
|
|
269
269
|
|
|
270
270
|
/// The text color to use in dark themes when `theme="outline"`
|
package/dist/dialog/_dialog.scss
CHANGED
|
@@ -87,18 +87,18 @@ $z-index: utils.$temporary-element-z-index !default;
|
|
|
87
87
|
|
|
88
88
|
/// The default background color for a dialog.
|
|
89
89
|
/// @type Color
|
|
90
|
+
// prettier-ignore
|
|
90
91
|
$background-color: if(
|
|
91
|
-
theme.$disable-dark-elevation
|
|
92
|
-
|
|
93
|
-
null
|
|
92
|
+
sass(theme.$disable-dark-elevation): theme.theme-get-var(surface-color);
|
|
93
|
+
else: null
|
|
94
94
|
) !default;
|
|
95
95
|
|
|
96
96
|
/// The default text color for a dialog.
|
|
97
97
|
/// @type Color
|
|
98
|
+
// prettier-ignore
|
|
98
99
|
$color: if(
|
|
99
|
-
theme.$disable-dark-elevation
|
|
100
|
-
|
|
101
|
-
null
|
|
100
|
+
sass(theme.$disable-dark-elevation): theme.theme-get-var(text-primary-color);
|
|
101
|
+
else: null,
|
|
102
102
|
) !default;
|
|
103
103
|
|
|
104
104
|
/// The `min-width` to apply to all `Dialog`s.
|
|
@@ -125,8 +125,12 @@ $variables: (
|
|
|
125
125
|
/// @param {String} position [null] - This should be one of `left`, `right`,
|
|
126
126
|
/// `top`, `bottom`
|
|
127
127
|
@mixin border-style($position: null) {
|
|
128
|
-
$property:
|
|
129
|
-
$var-name:
|
|
128
|
+
$property: border;
|
|
129
|
+
$var-name: size;
|
|
130
|
+
@if $position {
|
|
131
|
+
$property: "border-#{$position}";
|
|
132
|
+
$var-name: border-size;
|
|
133
|
+
}
|
|
130
134
|
|
|
131
135
|
#{$property}: get-var($var-name) solid get-var(color);
|
|
132
136
|
}
|
package/dist/form/Select.d.ts
CHANGED
|
@@ -2,8 +2,27 @@ import { type ChangeEvent, type HTMLAttributes, type InputHTMLAttributes, type R
|
|
|
2
2
|
import { type BoxProps } from "../box/Box.js";
|
|
3
3
|
import { type MenuProps } from "../menu/Menu.js";
|
|
4
4
|
import { type LabelA11y, type PropsWithRef, type RequireAtLeastOne } from "../types.js";
|
|
5
|
+
import { type OptionProps } from "./Option.js";
|
|
5
6
|
import { type TextFieldContainerProps } from "./TextFieldContainer.js";
|
|
6
7
|
import { type UserAgentAutocompleteProps } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* @since 6.5.0
|
|
10
|
+
*/
|
|
11
|
+
export interface GetSelectedOptionChildrenOptions<Value extends string = string> {
|
|
12
|
+
value: "" | Value;
|
|
13
|
+
/**
|
|
14
|
+
* The option will be undefined if there is no value or matching option.
|
|
15
|
+
*/
|
|
16
|
+
option: OptionProps | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* This is a pass-through of the {@link SelectProps.placeholder}
|
|
19
|
+
*/
|
|
20
|
+
placeholder?: ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* This is a pass-through of the {@link SelectProps.selectedOptionProps}
|
|
23
|
+
*/
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}
|
|
7
26
|
/**
|
|
8
27
|
* This is a convenience type for casting the `event.currentTarget.value` of a
|
|
9
28
|
* `Select`'s change event to be union of available values.
|
|
@@ -145,6 +164,11 @@ export interface SelectProps<Value extends string> extends Omit<TextFieldContain
|
|
|
145
164
|
* @defaultValue `false`
|
|
146
165
|
*/
|
|
147
166
|
disableSelectedIcon?: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* @since 6.5.0
|
|
169
|
+
* @defaultValue `({ children, option, placeholder }) => children ?? (option?.children || placeholder)`
|
|
170
|
+
*/
|
|
171
|
+
getSelectedOptionChildren?: (options: GetSelectedOptionChildrenOptions<Value>) => ReactNode;
|
|
148
172
|
/**
|
|
149
173
|
* This should be the available `Option`s for the select to choose from. It
|
|
150
174
|
* can also contain `OptGroup` or any other elements but only clicking on an
|
package/dist/form/Select.js
CHANGED
|
@@ -22,6 +22,12 @@ const EMPTY_STRING = "";
|
|
|
22
22
|
const noop = ()=>{
|
|
23
23
|
// do nothing
|
|
24
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* @since 6.5.0
|
|
27
|
+
*/ const defaultGetSelectedOptionChildren = (options)=>{
|
|
28
|
+
const { children, option, placeholder } = options;
|
|
29
|
+
return children ?? (option?.children || placeholder);
|
|
30
|
+
};
|
|
25
31
|
/**
|
|
26
32
|
* **Client Component**
|
|
27
33
|
*
|
|
@@ -53,7 +59,7 @@ const noop = ()=>{
|
|
|
53
59
|
* @see {@link https://react-md.dev/components/select | Select Demos}
|
|
54
60
|
* @since 6.0.0 Rewritten with a new API.
|
|
55
61
|
*/ export function Select(props) {
|
|
56
|
-
const { id, form, autoCompleteValue, autoComplete = autoCompleteValue, name = autoCompleteValue, className, onClick, onFocus, onKeyDown, inputRef: propInputRef, inputProps, containerRef, placeholder, menuProps = {}, label, labelProps = {}, selectedOptionProps, icon: propIcon, value, defaultValue, theme: propTheme, onChange = noop, rightAddon: propRightAddon, active = false, required, selectedIconAfter = false, disableOptionAddon = false, disableSelectedIcon = false, children, ...remaining } = props;
|
|
62
|
+
const { id, form, autoCompleteValue, autoComplete = autoCompleteValue, name = autoCompleteValue, className, onClick, onFocus, onKeyDown, inputRef: propInputRef, inputProps, containerRef, placeholder, menuProps = {}, label, labelProps = {}, selectedOptionProps, getSelectedOptionChildren = defaultGetSelectedOptionChildren, icon: propIcon, value, defaultValue, theme: propTheme, onChange = noop, rightAddon: propRightAddon, active = false, required, selectedIconAfter = false, disableOptionAddon = false, disableSelectedIcon = false, children, ...remaining } = props;
|
|
57
63
|
const { dense, error, disabled } = props;
|
|
58
64
|
const comboboxId = useEnsuredId(id, "select");
|
|
59
65
|
const inputId = useEnsuredId(inputProps?.id, "select-value");
|
|
@@ -117,9 +123,14 @@ const noop = ()=>{
|
|
|
117
123
|
children: [
|
|
118
124
|
/*#__PURE__*/ _jsx(SelectedOption, {
|
|
119
125
|
option: currentOption,
|
|
120
|
-
placeholder: placeholder,
|
|
121
126
|
disableAddon: disableOptionAddon,
|
|
122
|
-
...selectedOptionProps
|
|
127
|
+
...selectedOptionProps,
|
|
128
|
+
children: getSelectedOptionChildren({
|
|
129
|
+
value: currentValue,
|
|
130
|
+
option: currentOption,
|
|
131
|
+
placeholder,
|
|
132
|
+
children: selectedOptionProps?.children
|
|
133
|
+
})
|
|
123
134
|
}),
|
|
124
135
|
/*#__PURE__*/ _jsx("input", {
|
|
125
136
|
"aria-hidden": true,
|
package/dist/form/Select.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/form/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport { cnb } from \"cnbuilder\";\nimport {\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactElement,\n type ReactNode,\n type Ref,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nimport { type BoxProps } from \"../box/Box.js\";\nimport { IconRotator } from \"../icon/IconRotator.js\";\nimport { getIcon } from \"../icon/config.js\";\nimport { type MenuProps } from \"../menu/Menu.js\";\nimport { KeyboardMovementProvider } from \"../movement/useKeyboardMovementProvider.js\";\nimport {\n type LabelA11y,\n type PropsWithRef,\n type RequireAtLeastOne,\n} from \"../types.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { Listbox } from \"./Listbox.js\";\nimport { SelectedOption } from \"./SelectedOption.js\";\nimport {\n TextFieldContainer,\n type TextFieldContainerProps,\n} from \"./TextFieldContainer.js\";\nimport { getFormConfig } from \"./formConfig.js\";\nimport { label as labelStyles } from \"./labelStyles.js\";\nimport { select } from \"./selectStyles.js\";\nimport { extractOptionsFromChildren } from \"./selectUtils.js\";\nimport { textField } from \"./textFieldStyles.js\";\nimport { type UserAgentAutocompleteProps } from \"./types.js\";\nimport { useFormReset } from \"./useFormReset.js\";\nimport { useSelectCombobox } from \"./useSelectCombobox.js\";\nimport { triggerManualChangeEvent } from \"./utils.js\";\n\nconst EMPTY_STRING = \"\" as const;\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * This is a convenience type for casting the `event.currentTarget.value` of a\n * `Select`'s change event to be union of available values.\n *\n * Note: The change event does not provide any sort of validation on the value\n * so automation tools like Cypress, Playwright, or Selenium might set an\n * invalid value. This also does not work for numbers, so you will need to\n * implement that yourself.\n *\n * @example Simple Usage\n * ```tsx\n * import { Select, type SelectChangeEvent } from \"@react-md/core/form/Select\";\n * import { Option } from \"@react-md/core/form/Option\";\n * import type { ReactElement } from \"react\";\n *\n * type Value = \"\" | \"a\" | \"b\" | \"c\" | \"d\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState<Value>(\"\");\n *\n * const handleChange = (event: SelectChangeEvent<Value>): void => {\n * // No type error!\n * // `event.currentTarget.value`'s type is `Value` instead of a generic `string`\n * setValue(event.currentTarget.value);\n * };\n *\n * return (\n * <Select\n * label=\"Label\"\n * value={value}\n * onChange={handleChange}\n * >\n * <Option value=\"a\">First</Option>\n * <Option value=\"b\">Second</Option>\n * <Option value=\"c\">Third</Option>\n * <Option value=\"d\">Fourth</Option>\n * </Select>\n * );\n * }\n * ```\n * @since 6.0.0\n */\nexport type SelectChangeEvent<Value extends string> =\n ChangeEvent<HTMLInputElement> & { currentTarget: { value: Value } };\n\n/**\n * @since 6.0.0 Rewritten with a new API.\n */\nexport interface SelectProps<Value extends string>\n extends\n Omit<TextFieldContainerProps, \"label\">,\n Pick<InputHTMLAttributes<HTMLInputElement>, \"form\" | \"required\">,\n UserAgentAutocompleteProps {\n /**\n * @defaultValue `\"select-\" + useId()`\n */\n id?: string;\n\n /**\n * Optional placeholder text or element to render while no options have been\n * selected.\n */\n placeholder?: ReactNode;\n\n /**\n * Set this to a custom dropdown icon or `null` to not render a dropdown icon.\n *\n * @defaultValue `getIcon(\"dropdown\")`\n */\n icon?: ReactNode;\n\n /**\n * Set this value to fully control the value of the select component. The\n * {@link onChange} handler **must** also be provided if this prop exists.\n */\n value?: Value;\n\n /**\n * An optional default value when the value of the select component is\n * uncontrolled.\n *\n * @defaultValue `\"\"`\n */\n defaultValue?: Value;\n\n /** @see {@link SelectChangeEvent} */\n onChange?: (event: SelectChangeEvent<Value>) => void;\n\n /**\n * An optional floating label to display like other form fields.\n */\n label?: ReactNode;\n\n /**\n * Optional props to pass to the `<span>` that surrounds the {@link label}\n */\n labelProps?: PropsWithRef<HTMLAttributes<HTMLSpanElement>>;\n\n /**\n * An optional ref to pass to the hidden `<input type=\"text\" />` element that\n * stores the current value. This is really only useful if you'd like to keep\n * this component uncontrolled and access the value through\n * `inputRef.current.value`.\n */\n inputRef?: Ref<HTMLInputElement>;\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n\n /**\n * A ref for the container `<div>` element.\n */\n containerRef?: Ref<HTMLDivElement>;\n\n /**\n * Any additional props to provide to the `Menu` component that renders all\n * the `Option`s.\n *\n * The menu will always have these default values unless explicity\n * overwritten by this prop:\n *\n * - `aria-labelledby={label ? labelId : id}` -- this will be undefined if\n * `aria-label` is provided\n * - `anchor={BELOW_CENTER_ANCHOR}`\n * - `width=\"min\"`\n */\n menuProps?: PropsWithRef<\n Omit<MenuProps, \"visible\" | \"onRequestClose\" | \"fixedTo\">\n >;\n\n /**\n * Any additional props to pass to the div that contains the current visible\n * option.\n */\n selectedOptionProps?: BoxProps;\n\n /**\n * Set this to `true` if all the `Option` components should display the\n * selected icon after the children instead of before.\n *\n * @see {@link disableSelectedIcon} to remove the selected icon instead.\n *\n * @defaultValue `false`\n */\n selectedIconAfter?: boolean;\n\n /**\n * Set this to `true` to prevent the current option from rendering the\n * `leftAddon` in the `TextFieldContainer`.\n *\n * @defaultValue `false`\n */\n disableOptionAddon?: boolean;\n\n /**\n * Set this to `true` to update all the `Option` components to no longer\n * render an icon while selected.\n *\n * @defaultValue `false`\n */\n disableSelectedIcon?: boolean;\n\n /**\n * This should be the available `Option`s for the select to choose from. It\n * can also contain `OptGroup` or any other elements but only clicking on an\n * `Option` component will update the value.\n */\n children: ReactNode;\n}\n\n/**\n * **Client Component**\n *\n * @example Simple Example\n * ```tsx\n * import { Option } from \"@react-md/core/form/Option\";\n * import { Select } from \"@react-md/core/form/Select\";\n * import { useState, type ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState(\"\");\n *\n * return (\n * <Select\n * label=\"Select\"\n * value={value}\n * onChange={(event) => setValue(event.currentTarget.value)}\n * placeholder=\"Select a value\"\n * >\n * <Option value=\"a\">Option 1</Option>\n * <Option value=\"b\">Option 2</Option>\n * <Option value=\"c\">Option 3</Option>\n * <Option value=\"d\">Option 4</Option>\n * </Select>\n * );\n * }\n * ```\n *\n * @see {@link https://react-md.dev/components/select | Select Demos}\n * @since 6.0.0 Rewritten with a new API.\n */\nexport function Select<Value extends string>(\n props: RequireAtLeastOne<SelectProps<Value>, \"label\" | keyof LabelA11y>\n): ReactElement {\n const {\n id,\n form,\n autoCompleteValue,\n autoComplete = autoCompleteValue,\n name = autoCompleteValue,\n className,\n onClick,\n onFocus,\n onKeyDown,\n inputRef: propInputRef,\n inputProps,\n containerRef,\n placeholder,\n menuProps = {},\n label,\n labelProps = {},\n selectedOptionProps,\n icon: propIcon,\n value,\n defaultValue,\n theme: propTheme,\n onChange = noop,\n rightAddon: propRightAddon,\n active = false,\n required,\n selectedIconAfter = false,\n disableOptionAddon = false,\n disableSelectedIcon = false,\n children,\n ...remaining\n } = props;\n const { dense, error, disabled } = props;\n\n const comboboxId = useEnsuredId(id, \"select\");\n const inputId = useEnsuredId(inputProps?.id, \"select-value\");\n const selectLabelId = useEnsuredId(labelProps.id, \"select-label\");\n const labelId = label ? selectLabelId : undefined;\n\n const [localValue, setLocalValue] = useState(() => {\n if (typeof defaultValue !== \"undefined\") {\n return defaultValue;\n }\n\n return typeof value !== \"undefined\" ? value : EMPTY_STRING;\n });\n const currentValue = typeof value === \"undefined\" ? localValue : value;\n const initialValue = useRef(currentValue);\n const { options, currentOption } = extractOptionsFromChildren(\n children,\n currentValue\n );\n\n const { visible, comboboxProps, movementContext, getMenuProps } =\n useSelectCombobox({\n form,\n value: currentValue,\n values: options,\n onClick,\n onFocus,\n onKeyDown,\n disabled,\n popupId: menuProps.id,\n popupRef: menuProps.ref,\n comboboxId,\n comboboxRef: containerRef,\n });\n\n const [inputRef, inputRefCallback] = useEnsuredRef(propInputRef);\n useFormReset({\n form,\n elementRef: inputRef,\n defaultValue: initialValue.current,\n });\n\n const icon = getIcon(\"dropdown\", propIcon);\n const theme = getFormConfig(\"theme\", propTheme);\n let rightAddon = propRightAddon;\n if (typeof rightAddon === \"undefined\" && icon) {\n rightAddon = <IconRotator rotated={visible}>{icon}</IconRotator>;\n }\n\n const { ref: listboxRef, ...listboxProps } = getMenuProps(menuProps);\n let listboxLabelledBy = menuProps[\"aria-labelledby\"];\n const listboxLabel = menuProps[\"aria-label\"];\n if (!listboxLabel && !listboxLabelledBy) {\n listboxLabelledBy = labelId || comboboxId;\n }\n\n return (\n <KeyboardMovementProvider value={movementContext}>\n <TextFieldContainer\n aria-labelledby={labelId}\n {...remaining}\n {...comboboxProps}\n label={!!label}\n theme={theme}\n active={active || visible}\n className={cnb(\"rmd-select-container\", className)}\n rightAddon={rightAddon}\n >\n <SelectedOption\n option={currentOption}\n placeholder={placeholder}\n disableAddon={disableOptionAddon}\n {...selectedOptionProps}\n />\n <input\n aria-hidden\n id={inputId}\n ref={inputRefCallback}\n type=\"text\"\n autoComplete={autoComplete}\n name={name}\n tabIndex={-1}\n disabled={disabled}\n required={required}\n placeholder=\" \"\n {...inputProps}\n value={value}\n defaultValue={defaultValue}\n className={cnb(select({ theme }), textField())}\n onChange={(event) => {\n onChange(event as SelectChangeEvent<Value>);\n if (typeof value !== \"undefined\") {\n return;\n }\n\n const nextValue = event.currentTarget.value;\n const nextOption = options.find((option) => option === nextValue);\n\n setLocalValue(nextOption ?? initialValue.current);\n }}\n />\n {label && (\n <span\n {...labelProps}\n id={labelId}\n className={labelStyles({\n dense,\n error,\n disabled,\n active: active || visible,\n floating: true,\n floatingActive: !!placeholder || !!currentOption,\n className: labelProps.className,\n })}\n >\n {label}\n </span>\n )}\n </TextFieldContainer>\n <Listbox\n {...listboxProps}\n aria-label={listboxLabel}\n aria-labelledby={listboxLabelledBy as string}\n nodeRef={listboxRef}\n value={currentValue}\n setValue={useCallback(\n (option: \"\" | Value) => {\n triggerManualChangeEvent(inputRef.current, option);\n },\n [inputRef]\n )}\n selectedIconAfter={selectedIconAfter}\n disableSelectedIcon={disableSelectedIcon}\n >\n {children}\n </Listbox>\n </KeyboardMovementProvider>\n );\n}\n"],"names":["cnb","useCallback","useRef","useState","IconRotator","getIcon","KeyboardMovementProvider","useEnsuredId","useEnsuredRef","Listbox","SelectedOption","TextFieldContainer","getFormConfig","label","labelStyles","select","extractOptionsFromChildren","textField","useFormReset","useSelectCombobox","triggerManualChangeEvent","EMPTY_STRING","noop","Select","props","id","form","autoCompleteValue","autoComplete","name","className","onClick","onFocus","onKeyDown","inputRef","propInputRef","inputProps","containerRef","placeholder","menuProps","labelProps","selectedOptionProps","icon","propIcon","value","defaultValue","theme","propTheme","onChange","rightAddon","propRightAddon","active","required","selectedIconAfter","disableOptionAddon","disableSelectedIcon","children","remaining","dense","error","disabled","comboboxId","inputId","selectLabelId","labelId","undefined","localValue","setLocalValue","currentValue","initialValue","options","currentOption","visible","comboboxProps","movementContext","getMenuProps","values","popupId","popupRef","ref","comboboxRef","inputRefCallback","elementRef","current","rotated","listboxRef","listboxProps","listboxLabelledBy","listboxLabel","aria-labelledby","option","disableAddon","input","aria-hidden","type","tabIndex","event","nextValue","currentTarget","nextOption","find","span","floating","floatingActive","aria-label","nodeRef","setValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/form/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport { cnb } from \"cnbuilder\";\nimport {\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactElement,\n type ReactNode,\n type Ref,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nimport { type BoxProps } from \"../box/Box.js\";\nimport { IconRotator } from \"../icon/IconRotator.js\";\nimport { getIcon } from \"../icon/config.js\";\nimport { type MenuProps } from \"../menu/Menu.js\";\nimport { KeyboardMovementProvider } from \"../movement/useKeyboardMovementProvider.js\";\nimport {\n type LabelA11y,\n type PropsWithRef,\n type RequireAtLeastOne,\n} from \"../types.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { Listbox } from \"./Listbox.js\";\nimport { type OptionProps } from \"./Option.js\";\nimport { SelectedOption } from \"./SelectedOption.js\";\nimport {\n TextFieldContainer,\n type TextFieldContainerProps,\n} from \"./TextFieldContainer.js\";\nimport { getFormConfig } from \"./formConfig.js\";\nimport { label as labelStyles } from \"./labelStyles.js\";\nimport { select } from \"./selectStyles.js\";\nimport { extractOptionsFromChildren } from \"./selectUtils.js\";\nimport { textField } from \"./textFieldStyles.js\";\nimport { type UserAgentAutocompleteProps } from \"./types.js\";\nimport { useFormReset } from \"./useFormReset.js\";\nimport { useSelectCombobox } from \"./useSelectCombobox.js\";\nimport { triggerManualChangeEvent } from \"./utils.js\";\n\nconst EMPTY_STRING = \"\" as const;\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * @since 6.5.0\n */\nexport interface GetSelectedOptionChildrenOptions<\n Value extends string = string,\n> {\n value: \"\" | Value;\n\n /**\n * The option will be undefined if there is no value or matching option.\n */\n option: OptionProps | undefined;\n\n /**\n * This is a pass-through of the {@link SelectProps.placeholder}\n */\n placeholder?: ReactNode;\n\n /**\n * This is a pass-through of the {@link SelectProps.selectedOptionProps}\n */\n children?: ReactNode;\n}\n\n/**\n * @since 6.5.0\n */\nconst defaultGetSelectedOptionChildren = (\n options: GetSelectedOptionChildrenOptions\n): ReactNode => {\n const { children, option, placeholder } = options;\n\n return children ?? (option?.children || placeholder);\n};\n\n/**\n * This is a convenience type for casting the `event.currentTarget.value` of a\n * `Select`'s change event to be union of available values.\n *\n * Note: The change event does not provide any sort of validation on the value\n * so automation tools like Cypress, Playwright, or Selenium might set an\n * invalid value. This also does not work for numbers, so you will need to\n * implement that yourself.\n *\n * @example Simple Usage\n * ```tsx\n * import { Select, type SelectChangeEvent } from \"@react-md/core/form/Select\";\n * import { Option } from \"@react-md/core/form/Option\";\n * import type { ReactElement } from \"react\";\n *\n * type Value = \"\" | \"a\" | \"b\" | \"c\" | \"d\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState<Value>(\"\");\n *\n * const handleChange = (event: SelectChangeEvent<Value>): void => {\n * // No type error!\n * // `event.currentTarget.value`'s type is `Value` instead of a generic `string`\n * setValue(event.currentTarget.value);\n * };\n *\n * return (\n * <Select\n * label=\"Label\"\n * value={value}\n * onChange={handleChange}\n * >\n * <Option value=\"a\">First</Option>\n * <Option value=\"b\">Second</Option>\n * <Option value=\"c\">Third</Option>\n * <Option value=\"d\">Fourth</Option>\n * </Select>\n * );\n * }\n * ```\n * @since 6.0.0\n */\nexport type SelectChangeEvent<Value extends string> =\n ChangeEvent<HTMLInputElement> & { currentTarget: { value: Value } };\n\n/**\n * @since 6.0.0 Rewritten with a new API.\n */\nexport interface SelectProps<Value extends string>\n extends\n Omit<TextFieldContainerProps, \"label\">,\n Pick<InputHTMLAttributes<HTMLInputElement>, \"form\" | \"required\">,\n UserAgentAutocompleteProps {\n /**\n * @defaultValue `\"select-\" + useId()`\n */\n id?: string;\n\n /**\n * Optional placeholder text or element to render while no options have been\n * selected.\n */\n placeholder?: ReactNode;\n\n /**\n * Set this to a custom dropdown icon or `null` to not render a dropdown icon.\n *\n * @defaultValue `getIcon(\"dropdown\")`\n */\n icon?: ReactNode;\n\n /**\n * Set this value to fully control the value of the select component. The\n * {@link onChange} handler **must** also be provided if this prop exists.\n */\n value?: Value;\n\n /**\n * An optional default value when the value of the select component is\n * uncontrolled.\n *\n * @defaultValue `\"\"`\n */\n defaultValue?: Value;\n\n /** @see {@link SelectChangeEvent} */\n onChange?: (event: SelectChangeEvent<Value>) => void;\n\n /**\n * An optional floating label to display like other form fields.\n */\n label?: ReactNode;\n\n /**\n * Optional props to pass to the `<span>` that surrounds the {@link label}\n */\n labelProps?: PropsWithRef<HTMLAttributes<HTMLSpanElement>>;\n\n /**\n * An optional ref to pass to the hidden `<input type=\"text\" />` element that\n * stores the current value. This is really only useful if you'd like to keep\n * this component uncontrolled and access the value through\n * `inputRef.current.value`.\n */\n inputRef?: Ref<HTMLInputElement>;\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n\n /**\n * A ref for the container `<div>` element.\n */\n containerRef?: Ref<HTMLDivElement>;\n\n /**\n * Any additional props to provide to the `Menu` component that renders all\n * the `Option`s.\n *\n * The menu will always have these default values unless explicity\n * overwritten by this prop:\n *\n * - `aria-labelledby={label ? labelId : id}` -- this will be undefined if\n * `aria-label` is provided\n * - `anchor={BELOW_CENTER_ANCHOR}`\n * - `width=\"min\"`\n */\n menuProps?: PropsWithRef<\n Omit<MenuProps, \"visible\" | \"onRequestClose\" | \"fixedTo\">\n >;\n\n /**\n * Any additional props to pass to the div that contains the current visible\n * option.\n */\n selectedOptionProps?: BoxProps;\n\n /**\n * Set this to `true` if all the `Option` components should display the\n * selected icon after the children instead of before.\n *\n * @see {@link disableSelectedIcon} to remove the selected icon instead.\n *\n * @defaultValue `false`\n */\n selectedIconAfter?: boolean;\n\n /**\n * Set this to `true` to prevent the current option from rendering the\n * `leftAddon` in the `TextFieldContainer`.\n *\n * @defaultValue `false`\n */\n disableOptionAddon?: boolean;\n\n /**\n * Set this to `true` to update all the `Option` components to no longer\n * render an icon while selected.\n *\n * @defaultValue `false`\n */\n disableSelectedIcon?: boolean;\n\n /**\n * @since 6.5.0\n * @defaultValue `({ children, option, placeholder }) => children ?? (option?.children || placeholder)`\n */\n getSelectedOptionChildren?: (\n options: GetSelectedOptionChildrenOptions<Value>\n ) => ReactNode;\n\n /**\n * This should be the available `Option`s for the select to choose from. It\n * can also contain `OptGroup` or any other elements but only clicking on an\n * `Option` component will update the value.\n */\n children: ReactNode;\n}\n\n/**\n * **Client Component**\n *\n * @example Simple Example\n * ```tsx\n * import { Option } from \"@react-md/core/form/Option\";\n * import { Select } from \"@react-md/core/form/Select\";\n * import { useState, type ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState(\"\");\n *\n * return (\n * <Select\n * label=\"Select\"\n * value={value}\n * onChange={(event) => setValue(event.currentTarget.value)}\n * placeholder=\"Select a value\"\n * >\n * <Option value=\"a\">Option 1</Option>\n * <Option value=\"b\">Option 2</Option>\n * <Option value=\"c\">Option 3</Option>\n * <Option value=\"d\">Option 4</Option>\n * </Select>\n * );\n * }\n * ```\n *\n * @see {@link https://react-md.dev/components/select | Select Demos}\n * @since 6.0.0 Rewritten with a new API.\n */\nexport function Select<Value extends string>(\n props: RequireAtLeastOne<SelectProps<Value>, \"label\" | keyof LabelA11y>\n): ReactElement {\n const {\n id,\n form,\n autoCompleteValue,\n autoComplete = autoCompleteValue,\n name = autoCompleteValue,\n className,\n onClick,\n onFocus,\n onKeyDown,\n inputRef: propInputRef,\n inputProps,\n containerRef,\n placeholder,\n menuProps = {},\n label,\n labelProps = {},\n selectedOptionProps,\n getSelectedOptionChildren = defaultGetSelectedOptionChildren,\n icon: propIcon,\n value,\n defaultValue,\n theme: propTheme,\n onChange = noop,\n rightAddon: propRightAddon,\n active = false,\n required,\n selectedIconAfter = false,\n disableOptionAddon = false,\n disableSelectedIcon = false,\n children,\n ...remaining\n } = props;\n const { dense, error, disabled } = props;\n\n const comboboxId = useEnsuredId(id, \"select\");\n const inputId = useEnsuredId(inputProps?.id, \"select-value\");\n const selectLabelId = useEnsuredId(labelProps.id, \"select-label\");\n const labelId = label ? selectLabelId : undefined;\n\n const [localValue, setLocalValue] = useState(() => {\n if (typeof defaultValue !== \"undefined\") {\n return defaultValue;\n }\n\n return typeof value !== \"undefined\" ? value : EMPTY_STRING;\n });\n const currentValue = typeof value === \"undefined\" ? localValue : value;\n const initialValue = useRef(currentValue);\n const { options, currentOption } = extractOptionsFromChildren(\n children,\n currentValue\n );\n\n const { visible, comboboxProps, movementContext, getMenuProps } =\n useSelectCombobox({\n form,\n value: currentValue,\n values: options,\n onClick,\n onFocus,\n onKeyDown,\n disabled,\n popupId: menuProps.id,\n popupRef: menuProps.ref,\n comboboxId,\n comboboxRef: containerRef,\n });\n\n const [inputRef, inputRefCallback] = useEnsuredRef(propInputRef);\n useFormReset({\n form,\n elementRef: inputRef,\n defaultValue: initialValue.current,\n });\n\n const icon = getIcon(\"dropdown\", propIcon);\n const theme = getFormConfig(\"theme\", propTheme);\n let rightAddon = propRightAddon;\n if (typeof rightAddon === \"undefined\" && icon) {\n rightAddon = <IconRotator rotated={visible}>{icon}</IconRotator>;\n }\n\n const { ref: listboxRef, ...listboxProps } = getMenuProps(menuProps);\n let listboxLabelledBy = menuProps[\"aria-labelledby\"];\n const listboxLabel = menuProps[\"aria-label\"];\n if (!listboxLabel && !listboxLabelledBy) {\n listboxLabelledBy = labelId || comboboxId;\n }\n\n return (\n <KeyboardMovementProvider value={movementContext}>\n <TextFieldContainer\n aria-labelledby={labelId}\n {...remaining}\n {...comboboxProps}\n label={!!label}\n theme={theme}\n active={active || visible}\n className={cnb(\"rmd-select-container\", className)}\n rightAddon={rightAddon}\n >\n <SelectedOption\n option={currentOption}\n disableAddon={disableOptionAddon}\n {...selectedOptionProps}\n >\n {getSelectedOptionChildren({\n value: currentValue,\n option: currentOption,\n placeholder,\n children: selectedOptionProps?.children,\n })}\n </SelectedOption>\n <input\n aria-hidden\n id={inputId}\n ref={inputRefCallback}\n type=\"text\"\n autoComplete={autoComplete}\n name={name}\n tabIndex={-1}\n disabled={disabled}\n required={required}\n placeholder=\" \"\n {...inputProps}\n value={value}\n defaultValue={defaultValue}\n className={cnb(select({ theme }), textField())}\n onChange={(event) => {\n onChange(event as SelectChangeEvent<Value>);\n if (typeof value !== \"undefined\") {\n return;\n }\n\n const nextValue = event.currentTarget.value;\n const nextOption = options.find((option) => option === nextValue);\n\n setLocalValue(nextOption ?? initialValue.current);\n }}\n />\n {label && (\n <span\n {...labelProps}\n id={labelId}\n className={labelStyles({\n dense,\n error,\n disabled,\n active: active || visible,\n floating: true,\n floatingActive: !!placeholder || !!currentOption,\n className: labelProps.className,\n })}\n >\n {label}\n </span>\n )}\n </TextFieldContainer>\n <Listbox\n {...listboxProps}\n aria-label={listboxLabel}\n aria-labelledby={listboxLabelledBy as string}\n nodeRef={listboxRef}\n value={currentValue}\n setValue={useCallback(\n (option: \"\" | Value) => {\n triggerManualChangeEvent(inputRef.current, option);\n },\n [inputRef]\n )}\n selectedIconAfter={selectedIconAfter}\n disableSelectedIcon={disableSelectedIcon}\n >\n {children}\n </Listbox>\n </KeyboardMovementProvider>\n );\n}\n"],"names":["cnb","useCallback","useRef","useState","IconRotator","getIcon","KeyboardMovementProvider","useEnsuredId","useEnsuredRef","Listbox","SelectedOption","TextFieldContainer","getFormConfig","label","labelStyles","select","extractOptionsFromChildren","textField","useFormReset","useSelectCombobox","triggerManualChangeEvent","EMPTY_STRING","noop","defaultGetSelectedOptionChildren","options","children","option","placeholder","Select","props","id","form","autoCompleteValue","autoComplete","name","className","onClick","onFocus","onKeyDown","inputRef","propInputRef","inputProps","containerRef","menuProps","labelProps","selectedOptionProps","getSelectedOptionChildren","icon","propIcon","value","defaultValue","theme","propTheme","onChange","rightAddon","propRightAddon","active","required","selectedIconAfter","disableOptionAddon","disableSelectedIcon","remaining","dense","error","disabled","comboboxId","inputId","selectLabelId","labelId","undefined","localValue","setLocalValue","currentValue","initialValue","currentOption","visible","comboboxProps","movementContext","getMenuProps","values","popupId","popupRef","ref","comboboxRef","inputRefCallback","elementRef","current","rotated","listboxRef","listboxProps","listboxLabelledBy","listboxLabel","aria-labelledby","disableAddon","input","aria-hidden","type","tabIndex","event","nextValue","currentTarget","nextOption","find","span","floating","floatingActive","aria-label","nodeRef","setValue"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ReactElement
|
|
1
|
+
import { type ReactElement } from "react";
|
|
2
2
|
import { type BoxProps } from "../box/Box.js";
|
|
3
3
|
import { type OptionProps } from "./Option.js";
|
|
4
4
|
/**
|
|
@@ -7,7 +7,6 @@ import { type OptionProps } from "./Option.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export interface SelectedOptionProps extends BoxProps {
|
|
9
9
|
option: OptionProps | undefined;
|
|
10
|
-
placeholder?: ReactNode;
|
|
11
10
|
disableAddon: boolean;
|
|
12
11
|
}
|
|
13
12
|
/**
|
|
@@ -9,8 +9,8 @@ import { textField } from "./textFieldStyles.js";
|
|
|
9
9
|
* @since 6.0.0
|
|
10
10
|
* @internal
|
|
11
11
|
*/ export function SelectedOption(props) {
|
|
12
|
-
const { disableAddon, option, className, disableWrap = true, disablePadding = true,
|
|
13
|
-
let children =
|
|
12
|
+
const { disableAddon, option, className, disableWrap = true, disablePadding = true, ...remaining } = props;
|
|
13
|
+
let { children } = remaining;
|
|
14
14
|
// when the children are a string or number, wrap it in additional span so
|
|
15
15
|
// that overflow can be ellipsis-ed
|
|
16
16
|
if (typeof children === "string" || typeof children === "number") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/form/SelectedOption.tsx"],"sourcesContent":["import { cnb } from \"cnbuilder\";\nimport { type ReactElement
|
|
1
|
+
{"version":3,"sources":["../../src/form/SelectedOption.tsx"],"sourcesContent":["import { cnb } from \"cnbuilder\";\nimport { type ReactElement } from \"react\";\n\nimport { Box, type BoxProps } from \"../box/Box.js\";\nimport { cssUtils } from \"../cssUtils.js\";\nimport { type OptionProps } from \"./Option.js\";\nimport { textField } from \"./textFieldStyles.js\";\n\n/**\n * @since 6.0.0\n * @internal\n */\nexport interface SelectedOptionProps extends BoxProps {\n option: OptionProps | undefined;\n disableAddon: boolean;\n}\n\n/**\n * This component is used to render the current option.\n *\n * @since 6.0.0\n * @internal\n */\nexport function SelectedOption(props: SelectedOptionProps): ReactElement {\n const {\n disableAddon,\n option,\n className,\n disableWrap = true,\n disablePadding = true,\n ...remaining\n } = props;\n\n let { children } = remaining;\n // when the children are a string or number, wrap it in additional span so\n // that overflow can be ellipsis-ed\n if (typeof children === \"string\" || typeof children === \"number\") {\n children = (\n <span className={cssUtils({ textOverflow: \"ellipsis\" })}>{children}</span>\n );\n }\n\n return (\n <Box\n {...remaining}\n className={cnb(\"rmd-selected-option\", textField(), className)}\n disableWrap={disableWrap}\n disablePadding={disablePadding}\n >\n {!disableAddon && option?.leftAddon}\n {children}\n </Box>\n );\n}\n"],"names":["cnb","Box","cssUtils","textField","SelectedOption","props","disableAddon","option","className","disableWrap","disablePadding","remaining","children","span","textOverflow","leftAddon"],"mappings":";AAAA,SAASA,GAAG,QAAQ,YAAY;AAGhC,SAASC,GAAG,QAAuB,gBAAgB;AACnD,SAASC,QAAQ,QAAQ,iBAAiB;AAE1C,SAASC,SAAS,QAAQ,uBAAuB;AAWjD;;;;;CAKC,GACD,OAAO,SAASC,eAAeC,KAA0B;IACvD,MAAM,EACJC,YAAY,EACZC,MAAM,EACNC,SAAS,EACTC,cAAc,IAAI,EAClBC,iBAAiB,IAAI,EACrB,GAAGC,WACJ,GAAGN;IAEJ,IAAI,EAAEO,QAAQ,EAAE,GAAGD;IACnB,0EAA0E;IAC1E,mCAAmC;IACnC,IAAI,OAAOC,aAAa,YAAY,OAAOA,aAAa,UAAU;QAChEA,yBACE,KAACC;YAAKL,WAAWN,SAAS;gBAAEY,cAAc;YAAW;sBAAKF;;IAE9D;IAEA,qBACE,MAACX;QACE,GAAGU,SAAS;QACbH,WAAWR,IAAI,uBAAuBG,aAAaK;QACnDC,aAAaA;QACbC,gBAAgBA;;YAEf,CAACJ,gBAAgBC,QAAQQ;YACzBH;;;AAGP"}
|
|
@@ -91,13 +91,14 @@ $large-size: 2rem !default;
|
|
|
91
91
|
@include hidden-input-styles(true);
|
|
92
92
|
|
|
93
93
|
.rmd-input-toggle {
|
|
94
|
+
$focus-selector: "&:has(:focus-visible)";
|
|
95
|
+
@if utils.$disable-has-selectors or utils.$disable-focus-visible {
|
|
96
|
+
$focus-selector: "&:focus-within";
|
|
97
|
+
}
|
|
98
|
+
|
|
94
99
|
@include icon.set-var(color, currentcolor);
|
|
95
100
|
@include interaction.surface(
|
|
96
|
-
$focus-selector:
|
|
97
|
-
utils.$disable-has-selectors or utils.$disable-focus-visible,
|
|
98
|
-
"&:focus-within",
|
|
99
|
-
"&:has(:focus-visible)"
|
|
100
|
-
),
|
|
101
|
+
$focus-selector: $focus-selector,
|
|
101
102
|
$keyboard-only-focus: utils.$disable-has-selectors or
|
|
102
103
|
utils.$disable-focus-visible,
|
|
103
104
|
$disabled-selector: "&--disabled",
|
package/dist/form/_label.scss
CHANGED
|
@@ -151,8 +151,8 @@ $variables: (
|
|
|
151
151
|
@include use-var(background-color, active-background-color);
|
|
152
152
|
@include use-var(padding, active-padding);
|
|
153
153
|
|
|
154
|
-
transform:
|
|
155
|
-
|
|
154
|
+
transform: translate(get-var(floating-active-x), get-var(floating-active-y))
|
|
155
|
+
scale($floating-scale);
|
|
156
156
|
// need to add the `transform-origin` because of the scaling applied.
|
|
157
157
|
// it'll change the position based on the size of the label otherwise
|
|
158
158
|
transform-origin: 0 0;
|
package/dist/form/_legend.scss
CHANGED
|
@@ -28,33 +28,42 @@ $disable-floating: false !default;
|
|
|
28
28
|
@if not $disable-floating {
|
|
29
29
|
&--floating {
|
|
30
30
|
@include label.set-var(floating-active-y, -50%);
|
|
31
|
-
@include label.set-var(active-padding, 0 label.$floating-padding);
|
|
32
|
-
@include label.set-var(
|
|
33
|
-
active-background-color,
|
|
34
|
-
theme.theme-get-var(background-color)
|
|
35
|
-
);
|
|
36
31
|
@include label.set-var(
|
|
37
32
|
floating-active-x,
|
|
38
33
|
text-field.get-var(padding-left)
|
|
39
34
|
);
|
|
35
|
+
|
|
36
|
+
.rmd-fieldset:has(:focus-within) & {
|
|
37
|
+
@include label.active-styles;
|
|
38
|
+
}
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
@if not base.$form-disable-filled-theme {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
&--floating-filled {
|
|
43
|
+
@include text-field.set-var(
|
|
44
|
+
padding-left,
|
|
45
|
+
text-field.get-var(filled-padding)
|
|
46
|
+
);
|
|
47
|
+
@include label.set-var(floating-active-y, -100%);
|
|
48
|
+
}
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
@if not base.$form-disable-underlined-theme {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
&--floating-underline {
|
|
53
|
+
@include text-field.set-var(
|
|
54
|
+
padding-left,
|
|
55
|
+
text-field.get-var(underlined-padding)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
@if not base.$form-disable-outlined-theme {
|
|
57
61
|
&--floating-outline {
|
|
62
|
+
@include label.set-var(active-padding, 0 label.$floating-padding);
|
|
63
|
+
@include label.set-var(
|
|
64
|
+
active-background-color,
|
|
65
|
+
theme.theme-get-var(background-color)
|
|
66
|
+
);
|
|
58
67
|
@include text-field.set-var(
|
|
59
68
|
padding-left,
|
|
60
69
|
text-field.get-var(outlined-padding)
|
package/dist/form/_slider.scss
CHANGED
|
@@ -634,11 +634,13 @@ $variables: (
|
|
|
634
634
|
}
|
|
635
635
|
|
|
636
636
|
.rmd-slider-thumb {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
637
|
+
$color-name: active-color;
|
|
638
|
+
$color-fallback: null;
|
|
639
|
+
@if $track-color {
|
|
640
|
+
$color-name: color;
|
|
641
|
+
$color-fallback: theme.theme-color-var-fallback($track-color);
|
|
642
|
+
}
|
|
643
|
+
@include use-var(background-color, $color-name, $color-fallback);
|
|
642
644
|
|
|
643
645
|
border-radius: $thumb-border-radius;
|
|
644
646
|
height: $thumb-size;
|
package/dist/form/_switch.scss
CHANGED
|
@@ -80,10 +80,10 @@ $track-light-background-color: colors.$grey-400 !default;
|
|
|
80
80
|
|
|
81
81
|
/// The background color to apply to the `SwitchTrack` in the dark theme.
|
|
82
82
|
/// @type Color
|
|
83
|
+
// prettier-ignore
|
|
83
84
|
$track-dark-background-color: if(
|
|
84
|
-
theme.$disable-dark-elevation
|
|
85
|
-
|
|
86
|
-
map.get(theme.$dark-elevation-colors, 24)
|
|
85
|
+
sass(theme.$disable-dark-elevation): $track-light-background-color;
|
|
86
|
+
else: map.get(theme.$dark-elevation-colors, 24)
|
|
87
87
|
) !default;
|
|
88
88
|
|
|
89
89
|
/// The default background color to apply to the `SwitchTrack`.
|
|
@@ -274,8 +274,10 @@ $variables: (track-background-color, ball-background-color);
|
|
|
274
274
|
z-index: 0;
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
$active-selector: ".rmd-switch__input:checked + &"
|
|
278
|
-
|
|
277
|
+
$active-selector: ".rmd-switch__input:checked + &";
|
|
278
|
+
@if not $disable-menu-item-switch {
|
|
279
|
+
$active-selector: $active-selector + ", &--active";
|
|
280
|
+
}
|
|
279
281
|
|
|
280
282
|
#{$active-selector} {
|
|
281
283
|
$offset: $ball-size + $ball-offset;
|
|
@@ -271,6 +271,11 @@ $variables: (
|
|
|
271
271
|
/// @param {any} fallback [null] - An optional fallback value
|
|
272
272
|
/// @returns {String} a `var()` statement
|
|
273
273
|
@function get-var($name, $fallback: null) {
|
|
274
|
+
@if $name == underlined-padding and not $underlined-padding and not $fallback
|
|
275
|
+
{
|
|
276
|
+
$fallback: 0px;
|
|
277
|
+
}
|
|
278
|
+
|
|
274
279
|
$var: utils.get-var-name($variables, $name, "text-field");
|
|
275
280
|
@if $fallback {
|
|
276
281
|
@return var(#{$var}, #{$fallback});
|
|
@@ -502,17 +507,14 @@ $variables: (
|
|
|
502
507
|
&--filled {
|
|
503
508
|
@include theme.theme-set-var(background-color, get-var(filled-color));
|
|
504
509
|
@include theme.theme-use-var(background-color);
|
|
505
|
-
@include set-var(padding-left,
|
|
506
|
-
@include set-var(padding-right,
|
|
510
|
+
@include set-var(padding-left, get-var(filled-padding));
|
|
511
|
+
@include set-var(padding-right, get-var(filled-padding));
|
|
507
512
|
@if not label.$disable-floating {
|
|
508
|
-
@include label.set-var(
|
|
509
|
-
floating-active-x,
|
|
510
|
-
$filled-padding + label.$floating-padding
|
|
511
|
-
);
|
|
513
|
+
@include label.set-var(floating-active-x, get-var(filled-padding));
|
|
512
514
|
}
|
|
513
515
|
|
|
514
516
|
@if not $disable-addon {
|
|
515
|
-
@include set-var(addon-left-offset,
|
|
517
|
+
@include set-var(addon-left-offset, get-var(filled-padding));
|
|
516
518
|
}
|
|
517
519
|
}
|
|
518
520
|
}
|
|
@@ -529,8 +531,8 @@ $variables: (
|
|
|
529
531
|
border-bottom-width: $border-width;
|
|
530
532
|
|
|
531
533
|
@if $underlined-padding {
|
|
532
|
-
@include set-var(padding-left,
|
|
533
|
-
@include set-var(padding-right,
|
|
534
|
+
@include set-var(padding-left, get-var(underlined-padding));
|
|
535
|
+
@include set-var(padding-right, get-var(underlined-padding));
|
|
534
536
|
}
|
|
535
537
|
|
|
536
538
|
&::after {
|
|
@@ -594,8 +596,8 @@ $variables: (
|
|
|
594
596
|
|
|
595
597
|
@if not $disable-addon {
|
|
596
598
|
$addon-offset: calc(
|
|
597
|
-
|
|
598
|
-
|
|
599
|
+
icon.get-var(size) +
|
|
600
|
+
get-var(underlined-padding) +
|
|
599
601
|
$underlined-label-left-offset *
|
|
600
602
|
2
|
|
601
603
|
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,7 +2,7 @@ import { type FormTheme, type LabelClassNameOptions } from "./types.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* @since 6.4.0
|
|
4
4
|
*/
|
|
5
|
-
export type LegendLabelClassNameOptions = Pick<LabelClassNameOptions, "active" | "gap" | "
|
|
5
|
+
export type LegendLabelClassNameOptions = Pick<LabelClassNameOptions, "active" | "gap" | "error" | "stacked" | "disabled" | "reversed">;
|
|
6
6
|
/**
|
|
7
7
|
* @since 6.4.0
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/form/legendStyles.ts"],"sourcesContent":["import { cnb } from \"cnbuilder\";\n\nimport { cssUtils } from \"../cssUtils.js\";\nimport { bem } from \"../utils/bem.js\";\nimport { getFormConfig } from \"./formConfig.js\";\nimport { label } from \"./labelStyles.js\";\nimport { type FormTheme, type LabelClassNameOptions } from \"./types.js\";\n\nconst styles = bem(\"rmd-legend\");\n\n/**\n * @since 6.4.0\n */\nexport type LegendLabelClassNameOptions = Pick<\n LabelClassNameOptions,\n \"active\" | \"gap\" | \"
|
|
1
|
+
{"version":3,"sources":["../../src/form/legendStyles.ts"],"sourcesContent":["import { cnb } from \"cnbuilder\";\n\nimport { cssUtils } from \"../cssUtils.js\";\nimport { bem } from \"../utils/bem.js\";\nimport { getFormConfig } from \"./formConfig.js\";\nimport { label } from \"./labelStyles.js\";\nimport { type FormTheme, type LabelClassNameOptions } from \"./types.js\";\n\nconst styles = bem(\"rmd-legend\");\n\n/**\n * @since 6.4.0\n */\nexport type LegendLabelClassNameOptions = Pick<\n LabelClassNameOptions,\n \"active\" | \"gap\" | \"error\" | \"stacked\" | \"disabled\" | \"reversed\"\n>;\n\n/**\n * @since 6.4.0\n */\nexport interface LegendClassNameOptions extends LegendLabelClassNameOptions {\n className?: string;\n\n /**\n * @defaultValue `false`\n */\n srOnly?: boolean;\n\n /**\n * Set this to `true` to make the `<legend>` have the styles of a floating label.\n * This requires the parent `<fieldset>` to have the `floatingLegend` flag\n * enabled.\n *\n * @defaultValue `false`\n */\n floating?: boolean;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link FormTheme}\n * @defaultValue `getFormConfig(\"theme\")`\n */\n theme?: FormTheme;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link LabelClassNameOptions.active}\n * @defaultValue `false`\n */\n active?: boolean;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link LabelClassNameOptions.gap}\n * @defaultValue `false`\n */\n gap?: boolean;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link LabelClassNameOptions.disabled}\n * @defaultValue `false`\n */\n disabled?: boolean;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link LabelClassNameOptions.dense}\n * @defaultValue `false`\n */\n dense?: boolean;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link LabelClassNameOptions.error}\n * @defaultValue `false`\n */\n error?: boolean;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link LabelClassNameOptions.stacked}\n * @defaultValue `false`\n */\n stacked?: boolean;\n\n /**\n * This will only apply if {@link floating} is `true`.\n *\n * @see {@link LabelClassNameOptions.reversed}\n * @defaultValue `false`\n */\n reversed?: boolean;\n}\n\n/**\n * @since 6.4.0\n */\nexport function legend(options: LegendClassNameOptions = {}): string {\n const {\n className,\n srOnly,\n floating,\n theme = getFormConfig(\"theme\"),\n ...labelOptions\n } = options;\n\n return cnb(\n styles({\n floating,\n \"floating-filled\": floating && theme === \"filled\",\n \"floating-underline\": floating && theme === \"underline\",\n \"floating-outline\": floating && theme === \"outline\",\n }),\n floating &&\n label({\n ...labelOptions,\n floating: true,\n floatingActive: true,\n }),\n cssUtils({ srOnly }),\n className\n );\n}\n"],"names":["cnb","cssUtils","bem","getFormConfig","label","styles","legend","options","className","srOnly","floating","theme","labelOptions","floatingActive"],"mappings":"AAAA,SAASA,GAAG,QAAQ,YAAY;AAEhC,SAASC,QAAQ,QAAQ,iBAAiB;AAC1C,SAASC,GAAG,QAAQ,kBAAkB;AACtC,SAASC,aAAa,QAAQ,kBAAkB;AAChD,SAASC,KAAK,QAAQ,mBAAmB;AAGzC,MAAMC,SAASH,IAAI;AA+FnB;;CAEC,GACD,OAAO,SAASI,OAAOC,UAAkC,CAAC,CAAC;IACzD,MAAM,EACJC,SAAS,EACTC,MAAM,EACNC,QAAQ,EACRC,QAAQR,cAAc,QAAQ,EAC9B,GAAGS,cACJ,GAAGL;IAEJ,OAAOP,IACLK,OAAO;QACLK;QACA,mBAAmBA,YAAYC,UAAU;QACzC,sBAAsBD,YAAYC,UAAU;QAC5C,oBAAoBD,YAAYC,UAAU;IAC5C,IACAD,YACEN,MAAM;QACJ,GAAGQ,YAAY;QACfF,UAAU;QACVG,gBAAgB;IAClB,IACFZ,SAAS;QAAEQ;IAAO,IAClBD;AAEJ"}
|
|
@@ -533,7 +533,7 @@ $variables: (
|
|
|
533
533
|
/// @include surface;
|
|
534
534
|
/// }
|
|
535
535
|
///
|
|
536
|
-
/// @param {String} $focus-selector ["&:focus" + if(utils.disable-focus-visible
|
|
536
|
+
/// @param {String} $focus-selector ["&:focus" + if(sass(not utils.disable-focus-visible): "-visible"; else: "")] -
|
|
537
537
|
/// The selector to use indicating the element has been focused.
|
|
538
538
|
/// @param {Boolean} $keyboard-only-focus [utils.$disable-focus-visible] -
|
|
539
539
|
/// @param {String} $disabled-selector ["&:disabled"] - The selector to use
|
|
@@ -552,7 +552,8 @@ $variables: (
|
|
|
552
552
|
/// @param {Boolean} $disable-background [$disable-focus-background] - Set to
|
|
553
553
|
/// `true` to disable the focus background color styles.
|
|
554
554
|
@mixin surface(
|
|
555
|
-
$focus-selector: "&:focus" +
|
|
555
|
+
$focus-selector: "&:focus" +
|
|
556
|
+
if(sass(not utils.$disable-focus-visible): "-visible" ; else: ""),
|
|
556
557
|
$keyboard-only-focus: utils.$disable-focus-visible,
|
|
557
558
|
$disabled-selector: "&:disabled",
|
|
558
559
|
$clickable: true,
|
|
@@ -586,7 +587,8 @@ $variables: (
|
|
|
586
587
|
|
|
587
588
|
transition-duration: transition.$linear-duration;
|
|
588
589
|
transition-property:
|
|
589
|
-
background-color,
|
|
590
|
+
background-color,
|
|
591
|
+
if(sass(not $focus-box-shadow): outline-color; else: box-shadow);
|
|
590
592
|
transition-timing-function: transition.$linear-timing-function;
|
|
591
593
|
}
|
|
592
594
|
|
|
@@ -152,10 +152,10 @@ $light-theme-color: a11y.contrast-color($light-theme-background-color) !default;
|
|
|
152
152
|
|
|
153
153
|
/// The background-color to use in the dark theme.
|
|
154
154
|
/// @type Color
|
|
155
|
+
// prettier-ignore
|
|
155
156
|
$dark-theme-background-color: if(
|
|
156
|
-
theme.$disable-dark-elevation
|
|
157
|
-
|
|
158
|
-
map.get(theme.$dark-elevation-colors, $elevation)
|
|
157
|
+
sass(theme.$disable-dark-elevation): $light-theme-background-color;
|
|
158
|
+
else: map.get(theme.$dark-elevation-colors, $elevation)
|
|
159
159
|
) !default;
|
|
160
160
|
|
|
161
161
|
/// The text color to use in the dark theme.
|
package/dist/tabs/_tabs.scss
CHANGED
|
@@ -368,12 +368,11 @@ $variables: (
|
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
@include utils.rtl {
|
|
371
|
-
$button-selector: "&__button"
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
""
|
|
375
|
-
|
|
376
|
-
);
|
|
371
|
+
$button-selector: "&__button";
|
|
372
|
+
@if not $disable-tablist-scroll-button-vertical {
|
|
373
|
+
$button-selector: $button-selector +
|
|
374
|
+
":where(:not(.rmd-tablist-button__button--v))";
|
|
375
|
+
}
|
|
377
376
|
|
|
378
377
|
&--left {
|
|
379
378
|
left: auto;
|
package/dist/theme/_a11y.scss
CHANGED
|
@@ -183,5 +183,7 @@ $_linear-channel-values: (
|
|
|
183
183
|
$light-contrast: _contrast($background-color, $light-color);
|
|
184
184
|
$dark-contrast: _contrast($background-color, $dark-color);
|
|
185
185
|
|
|
186
|
-
@return if(
|
|
186
|
+
@return if(
|
|
187
|
+
sass($light-contrast > $dark-contrast): $light-color; else: $dark-color
|
|
188
|
+
);
|
|
187
189
|
}
|
package/dist/theme/_theme.scss
CHANGED
|
@@ -222,10 +222,10 @@ $dark-theme-background-color: #121212 !default;
|
|
|
222
222
|
/// color depending on its elevation.
|
|
223
223
|
///
|
|
224
224
|
/// @type Color
|
|
225
|
+
// prettier-ignore
|
|
225
226
|
$dark-theme-surface-color: if(
|
|
226
|
-
$disable-dark-elevation
|
|
227
|
-
|
|
228
|
-
null
|
|
227
|
+
sass($disable-dark-elevation): colors.$grey-800;
|
|
228
|
+
else: null
|
|
229
229
|
) !default;
|
|
230
230
|
|
|
231
231
|
/// The primary text color when using the dark theme.
|
|
@@ -250,7 +250,7 @@ $dark-theme-text-disabled-color: rgba($dark-theme-inverse-color, 0.38) !default;
|
|
|
250
250
|
/// @param {Color} dark-color - The dark theme color
|
|
251
251
|
/// @returns {Color} The correct color depending on the `$color-scheme`
|
|
252
252
|
@function get-default-color($light-color, $dark-color) {
|
|
253
|
-
@return if($color-scheme == dark
|
|
253
|
+
@return if(sass($color-scheme == dark): $dark-color; else: $light-color);
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
/// The default background color
|
|
@@ -519,7 +519,7 @@ $theme-variables: (
|
|
|
519
519
|
/// @param {any} value - The value to maybe return
|
|
520
520
|
/// @return {any} the `$value` if it was theme var, otherwise null
|
|
521
521
|
@function theme-color-var-fallback($value) {
|
|
522
|
-
@return if(is-theme-color-var($value)
|
|
522
|
+
@return if(sass(is-theme-color-var($value)): $value; else: null);
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
/// @param {Number} z-value - The dark elevation value
|
|
@@ -777,11 +777,10 @@ $theme-variables: (
|
|
|
777
777
|
|
|
778
778
|
@if not $current-color-index {
|
|
779
779
|
@if not $fallback-color {
|
|
780
|
-
$fallback:
|
|
781
|
-
|
|
782
|
-
"the '$#{$fallback-name}' variable"
|
|
783
|
-
|
|
784
|
-
);
|
|
780
|
+
$fallback: "a fallback color";
|
|
781
|
+
@if $fallback-name {
|
|
782
|
+
$fallback: "the '$#{$fallback-name}' variable";
|
|
783
|
+
}
|
|
785
784
|
|
|
786
785
|
$error-msg: "Invalid material design color: '#{$color}'. If this was intentional because your app does " +
|
|
787
786
|
"not use material design colors, set #{$fallback} instead to get a correct color for the provided swatch: " +
|
|
@@ -794,8 +793,13 @@ $theme-variables: (
|
|
|
794
793
|
}
|
|
795
794
|
}
|
|
796
795
|
|
|
796
|
+
// prettier-ignore
|
|
797
|
+
$current-suffixes: if(
|
|
798
|
+
sass(not $accent): colors.$primary-suffixes;
|
|
799
|
+
else: colors.$accent-suffixes
|
|
800
|
+
);
|
|
797
801
|
$suffixes: utils.validate(
|
|
798
|
-
|
|
802
|
+
$current-suffixes,
|
|
799
803
|
$swatch,
|
|
800
804
|
"material design color swatch"
|
|
801
805
|
);
|
|
@@ -829,7 +833,7 @@ $theme-variables: (
|
|
|
829
833
|
}
|
|
830
834
|
}
|
|
831
835
|
|
|
832
|
-
$color-name: "#{$current-color-name}#{if($accent
|
|
836
|
+
$color-name: "#{$current-color-name}#{if(sass(not $accent): ""; else: "-a")}-#{$swatch}";
|
|
833
837
|
|
|
834
838
|
@return map.get(colors.$color-map, $color-name);
|
|
835
839
|
}
|
|
@@ -125,12 +125,11 @@ $variables: (
|
|
|
125
125
|
/// layer behavior
|
|
126
126
|
@mixin styles($disable-layer: false) {
|
|
127
127
|
@if not $disable-everything {
|
|
128
|
+
// prettier-ignore
|
|
128
129
|
$pseudo-selectors: if(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
) +
|
|
133
|
-
"&::after";
|
|
130
|
+
sass(not $disable-inactive-background-color): "&::before, ";
|
|
131
|
+
else: "",
|
|
132
|
+
) + "&::after";
|
|
134
133
|
|
|
135
134
|
@include utils.optional-layer(window-splitter, $disable-layer) {
|
|
136
135
|
.rmd-window-splitter {
|
|
@@ -150,14 +149,12 @@ $variables: (
|
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
&::after {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
$
|
|
156
|
-
|
|
157
|
-
$background-color,
|
|
158
|
-
null
|
|
159
|
-
)
|
|
152
|
+
// prettier-ignore
|
|
153
|
+
$fallback: if(
|
|
154
|
+
sass($background-color == interaction.get-var(focus-color)): $background-color;
|
|
155
|
+
else: null
|
|
160
156
|
);
|
|
157
|
+
@include use-var(background-color, $fallback: $fallback);
|
|
161
158
|
@include use-var(opacity);
|
|
162
159
|
|
|
163
160
|
transition: opacity transition.$linear-duration;
|
|
@@ -169,14 +166,15 @@ $variables: (
|
|
|
169
166
|
}
|
|
170
167
|
|
|
171
168
|
&::before {
|
|
169
|
+
// prettier-ignore
|
|
170
|
+
$fallback: if(
|
|
171
|
+
sass($inactive-background-color == divider.get-var(color)): $inactive-background-color;
|
|
172
|
+
else: null,
|
|
173
|
+
);
|
|
172
174
|
@include use-var(
|
|
173
175
|
background-color,
|
|
174
176
|
inactive-background-color,
|
|
175
|
-
|
|
176
|
-
$inactive-background-color == divider.get-var(color),
|
|
177
|
-
$inactive-background-color,
|
|
178
|
-
null
|
|
179
|
-
)
|
|
177
|
+
$fallback
|
|
180
178
|
);
|
|
181
179
|
|
|
182
180
|
pointer-events: none;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-md/core",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.0",
|
|
4
4
|
"description": "The core components and functionality for react-md.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sass": "./dist/_core.scss",
|
|
@@ -80,25 +80,25 @@
|
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@jest/globals": "^30.2.0",
|
|
82
82
|
"@jest/types": "^30.2.0",
|
|
83
|
-
"@microsoft/api-extractor": "^7.55.
|
|
83
|
+
"@microsoft/api-extractor": "^7.55.2",
|
|
84
84
|
"@swc/cli": "^0.7.9",
|
|
85
|
-
"@swc/core": "^1.15.
|
|
85
|
+
"@swc/core": "^1.15.7",
|
|
86
86
|
"@testing-library/dom": "^10.4.1",
|
|
87
87
|
"@testing-library/jest-dom": "^6.9.1",
|
|
88
|
-
"@testing-library/react": "^16.3.
|
|
88
|
+
"@testing-library/react": "^16.3.1",
|
|
89
89
|
"@testing-library/user-event": "^14.6.1",
|
|
90
90
|
"@trivago/prettier-plugin-sort-imports": "^6.0.0",
|
|
91
91
|
"@types/lodash": "^4.17.21",
|
|
92
|
-
"@types/node": "^24.10.
|
|
92
|
+
"@types/node": "^24.10.4",
|
|
93
93
|
"@types/react": "^18.3.27",
|
|
94
94
|
"@types/react-dom": "^18.3.7",
|
|
95
95
|
"@vitejs/plugin-react-swc": "^4.2.2",
|
|
96
96
|
"@vitest/coverage-v8": "^3.2.4",
|
|
97
97
|
"chokidar": "^5.0.0",
|
|
98
|
-
"eslint": "^9.39.
|
|
98
|
+
"eslint": "^9.39.2",
|
|
99
99
|
"filesize": "^11.0.13",
|
|
100
100
|
"glob": "13.0.0",
|
|
101
|
-
"jsdom": "^27.
|
|
101
|
+
"jsdom": "^27.3.0",
|
|
102
102
|
"lodash": "^4.17.21",
|
|
103
103
|
"lz-string": "^1.5.0",
|
|
104
104
|
"npm-run-all2": "^8.0.2",
|
package/src/form/Select.tsx
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { useEnsuredId } from "../useEnsuredId.js";
|
|
27
27
|
import { useEnsuredRef } from "../useEnsuredRef.js";
|
|
28
28
|
import { Listbox } from "./Listbox.js";
|
|
29
|
+
import { type OptionProps } from "./Option.js";
|
|
29
30
|
import { SelectedOption } from "./SelectedOption.js";
|
|
30
31
|
import {
|
|
31
32
|
TextFieldContainer,
|
|
@@ -46,6 +47,41 @@ const noop = (): void => {
|
|
|
46
47
|
// do nothing
|
|
47
48
|
};
|
|
48
49
|
|
|
50
|
+
/**
|
|
51
|
+
* @since 6.5.0
|
|
52
|
+
*/
|
|
53
|
+
export interface GetSelectedOptionChildrenOptions<
|
|
54
|
+
Value extends string = string,
|
|
55
|
+
> {
|
|
56
|
+
value: "" | Value;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The option will be undefined if there is no value or matching option.
|
|
60
|
+
*/
|
|
61
|
+
option: OptionProps | undefined;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* This is a pass-through of the {@link SelectProps.placeholder}
|
|
65
|
+
*/
|
|
66
|
+
placeholder?: ReactNode;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* This is a pass-through of the {@link SelectProps.selectedOptionProps}
|
|
70
|
+
*/
|
|
71
|
+
children?: ReactNode;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @since 6.5.0
|
|
76
|
+
*/
|
|
77
|
+
const defaultGetSelectedOptionChildren = (
|
|
78
|
+
options: GetSelectedOptionChildrenOptions
|
|
79
|
+
): ReactNode => {
|
|
80
|
+
const { children, option, placeholder } = options;
|
|
81
|
+
|
|
82
|
+
return children ?? (option?.children || placeholder);
|
|
83
|
+
};
|
|
84
|
+
|
|
49
85
|
/**
|
|
50
86
|
* This is a convenience type for casting the `event.currentTarget.value` of a
|
|
51
87
|
* `Select`'s change event to be union of available values.
|
|
@@ -206,6 +242,14 @@ export interface SelectProps<Value extends string>
|
|
|
206
242
|
*/
|
|
207
243
|
disableSelectedIcon?: boolean;
|
|
208
244
|
|
|
245
|
+
/**
|
|
246
|
+
* @since 6.5.0
|
|
247
|
+
* @defaultValue `({ children, option, placeholder }) => children ?? (option?.children || placeholder)`
|
|
248
|
+
*/
|
|
249
|
+
getSelectedOptionChildren?: (
|
|
250
|
+
options: GetSelectedOptionChildrenOptions<Value>
|
|
251
|
+
) => ReactNode;
|
|
252
|
+
|
|
209
253
|
/**
|
|
210
254
|
* This should be the available `Option`s for the select to choose from. It
|
|
211
255
|
* can also contain `OptGroup` or any other elements but only clicking on an
|
|
@@ -266,6 +310,7 @@ export function Select<Value extends string>(
|
|
|
266
310
|
label,
|
|
267
311
|
labelProps = {},
|
|
268
312
|
selectedOptionProps,
|
|
313
|
+
getSelectedOptionChildren = defaultGetSelectedOptionChildren,
|
|
269
314
|
icon: propIcon,
|
|
270
315
|
value,
|
|
271
316
|
defaultValue,
|
|
@@ -351,10 +396,16 @@ export function Select<Value extends string>(
|
|
|
351
396
|
>
|
|
352
397
|
<SelectedOption
|
|
353
398
|
option={currentOption}
|
|
354
|
-
placeholder={placeholder}
|
|
355
399
|
disableAddon={disableOptionAddon}
|
|
356
400
|
{...selectedOptionProps}
|
|
357
|
-
|
|
401
|
+
>
|
|
402
|
+
{getSelectedOptionChildren({
|
|
403
|
+
value: currentValue,
|
|
404
|
+
option: currentOption,
|
|
405
|
+
placeholder,
|
|
406
|
+
children: selectedOptionProps?.children,
|
|
407
|
+
})}
|
|
408
|
+
</SelectedOption>
|
|
358
409
|
<input
|
|
359
410
|
aria-hidden
|
|
360
411
|
id={inputId}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cnb } from "cnbuilder";
|
|
2
|
-
import { type ReactElement
|
|
2
|
+
import { type ReactElement } from "react";
|
|
3
3
|
|
|
4
4
|
import { Box, type BoxProps } from "../box/Box.js";
|
|
5
5
|
import { cssUtils } from "../cssUtils.js";
|
|
@@ -12,7 +12,6 @@ import { textField } from "./textFieldStyles.js";
|
|
|
12
12
|
*/
|
|
13
13
|
export interface SelectedOptionProps extends BoxProps {
|
|
14
14
|
option: OptionProps | undefined;
|
|
15
|
-
placeholder?: ReactNode;
|
|
16
15
|
disableAddon: boolean;
|
|
17
16
|
}
|
|
18
17
|
|
|
@@ -29,11 +28,10 @@ export function SelectedOption(props: SelectedOptionProps): ReactElement {
|
|
|
29
28
|
className,
|
|
30
29
|
disableWrap = true,
|
|
31
30
|
disablePadding = true,
|
|
32
|
-
placeholder,
|
|
33
31
|
...remaining
|
|
34
32
|
} = props;
|
|
35
33
|
|
|
36
|
-
let children =
|
|
34
|
+
let { children } = remaining;
|
|
37
35
|
// when the children are a string or number, wrap it in additional span so
|
|
38
36
|
// that overflow can be ellipsis-ed
|
|
39
37
|
if (typeof children === "string" || typeof children === "number") {
|
package/src/form/legendStyles.ts
CHANGED
|
@@ -13,7 +13,7 @@ const styles = bem("rmd-legend");
|
|
|
13
13
|
*/
|
|
14
14
|
export type LegendLabelClassNameOptions = Pick<
|
|
15
15
|
LabelClassNameOptions,
|
|
16
|
-
"active" | "gap" | "
|
|
16
|
+
"active" | "gap" | "error" | "stacked" | "disabled" | "reversed"
|
|
17
17
|
>;
|
|
18
18
|
|
|
19
19
|
/**
|