@eunomia/elements 1.0.0-beta.7 → 1.0.0-beta.8
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/cdn/components/chunks/{chunk-3PNGQEG4.js → chunk-32L2QYWQ.js} +2 -2
- package/dist/cdn/components/chunks/{chunk-Z3OFIE7S.js → chunk-3UUZM7X2.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-BVASCT2V.js → chunk-55PUDL7D.js} +13 -13
- package/dist/cdn/components/chunks/chunk-5LA5DQMP.js +1 -0
- package/dist/cdn/components/chunks/chunk-5LXGJVJR.js +1 -0
- package/dist/cdn/components/chunks/chunk-6TIEBY34.js +1 -0
- package/dist/cdn/components/chunks/{chunk-LVKMAHMU.js → chunk-AH2SKZ7T.js} +4 -1
- package/dist/cdn/components/chunks/chunk-JAGZL7JH.js +1 -0
- package/dist/cdn/components/chunks/{chunk-DGI7TKCU.js → chunk-LD35BFNK.js} +5 -9
- package/dist/cdn/components/chunks/chunk-P6LGU3FT.js +1 -0
- package/dist/cdn/components/chunks/{chunk-UYZR4JXZ.js → chunk-QSZO4GIH.js} +45 -9
- package/dist/cdn/components/chunks/{chunk-PXF554MD.js → chunk-QYB6Z6FG.js} +5 -5
- package/dist/cdn/components/chunks/{chunk-RIFF2D2F.js → chunk-RGC3I6MK.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-N6ZW5CDN.js → chunk-TCSB2MLU.js} +1 -1
- package/dist/cdn/components/chunks/chunk-WIUERJII.js +1 -0
- package/dist/cdn/components/eun-animate.js +4 -4
- package/dist/cdn/components/eun-button.js +1 -1
- package/dist/cdn/components/eun-carousel.js +10 -9
- package/dist/cdn/components/eun-chip.js +17 -11
- package/dist/cdn/components/eun-collapse.js +1 -1
- package/dist/cdn/components/eun-color-picker.js +18 -5
- package/dist/cdn/components/eun-counter.js +10 -8
- package/dist/cdn/components/eun-date-picker.js +46 -43
- package/dist/cdn/components/eun-drawer.js +19 -20
- package/dist/cdn/components/eun-dropdown-button.js +1 -1
- package/dist/cdn/components/eun-dropdown-item.js +3 -3
- package/dist/cdn/components/eun-fab.js +1 -1
- package/dist/cdn/components/eun-image-carousel.js +4 -4
- package/dist/cdn/components/eun-input-phone.js +11 -8
- package/dist/cdn/components/eun-input.js +1 -1
- package/dist/cdn/components/eun-link.js +59 -13
- package/dist/cdn/components/eun-modal.js +23 -13
- package/dist/cdn/components/eun-scheduler-event-editor.js +1 -1
- package/dist/cdn/components/eun-search.js +34 -28
- package/dist/cdn/components/eun-select.js +3 -3
- package/dist/cdn/components/eun-sidebar.js +66 -21
- package/dist/cdn/components/eun-sliding-card.js +1 -1
- package/dist/cdn/components/eun-stepper.js +16 -16
- package/dist/cdn/components/eun-tab-panel.js +1 -1
- package/dist/cdn/components/eun-table-action-bar.js +1 -1
- package/dist/cdn/components/eun-table.js +2 -2
- package/dist/cdn/components/eun-textarea.js +16 -13
- package/dist/cdn/components/eun-time-picker.js +25 -23
- package/dist/cdn/components/eun-toast.js +8 -8
- package/dist/cdn/components/eun-toggle-group.js +71 -35
- package/dist/cdn/components/eun-toggle-item.js +8 -8
- package/dist/cdn/components/eun-toolbar.js +20 -20
- package/dist/cdn/components/eun-tooltip.js +6 -6
- package/dist/cdn/styles/eunomia-themes.css +1 -1
- package/dist/cdn/styles/themes/mixins/eunomia-neutrals.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia-dark.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire-dark.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest-dark.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold-dark.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean-dark.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon-dark.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet-dark.mixin.scss +6 -2
- package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet.theme.css +1 -1
- package/dist/components/action/button/button.d.ts +2 -2
- package/dist/components/action/button/button.js +3 -7
- package/dist/components/action/button/button.styles.js +3 -3
- package/dist/components/action/dropdown-button/dropdown-button.d.ts +4 -6
- package/dist/components/action/dropdown-button/dropdown-button.js +6 -8
- package/dist/components/action/dropdown-button/dropdown-item.d.ts +10 -2
- package/dist/components/action/dropdown-button/dropdown-item.js +24 -9
- package/dist/components/action/link/link.d.ts +10 -1
- package/dist/components/action/link/link.js +13 -1
- package/dist/components/action/link/link.styles.js +50 -3
- package/dist/components/action/toggle/toggle-group.d.ts +12 -2
- package/dist/components/action/toggle/toggle-group.js +17 -2
- package/dist/components/action/toggle/toggle-group.styles.js +54 -18
- package/dist/components/action/toggle/toggle-item.js +1 -3
- package/dist/components/action/toggle/toggle-item.styles.js +7 -7
- package/dist/components/alert/drawer/drawer.d.ts +25 -0
- package/dist/components/alert/drawer/drawer.js +42 -3
- package/dist/components/alert/drawer/drawer.styles.js +6 -6
- package/dist/components/alert/modal/modal.d.ts +25 -0
- package/dist/components/alert/modal/modal.js +42 -3
- package/dist/components/alert/modal/modal.styles.js +17 -6
- package/dist/components/alert/toast/toast.js +3 -2
- package/dist/components/alert/toast/toast.styles.js +3 -3
- package/dist/components/content/chip/chip.js +3 -2
- package/dist/components/content/chip/chip.styles.js +9 -3
- package/dist/components/content/image-carousel/image-carousel.js +5 -4
- package/dist/components/content/tooltip/tooltip.d.ts +16 -9
- package/dist/components/content/tooltip/tooltip.js +28 -12
- package/dist/components/content/tooltip/tooltip.styles.js +1 -1
- package/dist/components/form/color-picker/color-picker.d.ts +7 -1
- package/dist/components/form/color-picker/color-picker.js +8 -2
- package/dist/components/form/color-picker/color-picker.styles.js +13 -0
- package/dist/components/form/counter/counter.d.ts +3 -1
- package/dist/components/form/counter/counter.js +3 -1
- package/dist/components/form/counter/counter.styles.js +6 -4
- package/dist/components/form/date-picker/date-picker.d.ts +6 -1
- package/dist/components/form/date-picker/date-picker.js +7 -2
- package/dist/components/form/date-picker/date-picker.styles.js +9 -6
- package/dist/components/form/input/input.d.ts +6 -1
- package/dist/components/form/input/input.js +7 -2
- package/dist/components/form/input-phone/input-phone.d.ts +7 -1
- package/dist/components/form/input-phone/input-phone.js +7 -1
- package/dist/components/form/input-phone/input-phone.styles.js +6 -3
- package/dist/components/form/search/search.d.ts +64 -10
- package/dist/components/form/search/search.js +112 -31
- package/dist/components/form/search/search.styles.js +2 -0
- package/dist/components/form/select/select.d.ts +7 -1
- package/dist/components/form/select/select.js +7 -1
- package/dist/components/form/shared-styles/field.styles.js +45 -8
- package/dist/components/form/shared-styles/listbox.styles.js +5 -1
- package/dist/components/form/textarea/textarea.d.ts +1 -0
- package/dist/components/form/textarea/textarea.js +2 -1
- package/dist/components/form/textarea/textarea.styles.js +3 -0
- package/dist/components/form/time-picker/time-picker.d.ts +6 -1
- package/dist/components/form/time-picker/time-picker.js +7 -2
- package/dist/components/form/time-picker/time-picker.styles.js +7 -5
- package/dist/components/layout/animate/animate.js +2 -1
- package/dist/components/navigation/carousel/carousel.d.ts +1 -2
- package/dist/components/navigation/carousel/carousel.js +14 -6
- package/dist/components/navigation/carousel/carousel.styles.js +5 -4
- package/dist/components/navigation/sidebar/sidebar.d.ts +98 -52
- package/dist/components/navigation/sidebar/sidebar.js +140 -85
- package/dist/components/navigation/sidebar/sidebar.styles.d.ts +1 -1
- package/dist/components/navigation/sidebar/sidebar.styles.js +69 -21
- package/dist/components/navigation/stepper/stepper.d.ts +1 -3
- package/dist/components/navigation/stepper/stepper.js +3 -21
- package/dist/components/navigation/toolbar/toolbar.d.ts +10 -0
- package/dist/components/navigation/toolbar/toolbar.js +8 -1
- package/dist/components/navigation/toolbar/toolbar.styles.js +18 -17
- package/dist/events/select.event.d.ts +3 -2
- package/dist/events/select.event.js +2 -1
- package/dist/features/scheduler/scheduler-event-editor/scheduler-event-editor.js +1 -1
- package/dist/features/table/table/table.js +1 -1
- package/dist/features/table/table-action-bar/table-action-bar.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/mixins/button.mixin.d.ts +1 -1
- package/dist/mixins/button.mixin.js +6 -4
- package/dist/mixins/dialog-surface.mixin.d.ts +8 -0
- package/dist/mixins/field-size.mixin.d.ts +19 -0
- package/dist/mixins/field-size.mixin.js +33 -0
- package/dist/mixins/rounded.mixin.d.ts +18 -0
- package/dist/mixins/rounded.mixin.js +32 -0
- package/dist/ssr/button-ssr.css +5 -5
- package/dist/ssr/carousel-ssr.css +9 -0
- package/dist/ssr/chip-ssr.css +8 -0
- package/dist/ssr/collapse-ssr.css +29 -0
- package/dist/ssr/field-ssr.css +43 -4
- package/dist/ssr/image-carousel-ssr.css +10 -0
- package/dist/ssr/links-ssr.css +38 -1
- package/dist/ssr/sidebar-ssr.css +95 -4
- package/dist/ssr/toggle-group-ssr.css +64 -13
- package/dist/ssr/toolbar-ssr.css +50 -0
- package/dist/types/variant.type.d.ts +4 -1
- package/dist/utils/boolean.utils.d.ts +14 -0
- package/dist/utils/boolean.utils.js +20 -0
- package/dist/utils/dropdown-menu.utils.d.ts +1 -1
- package/dist/utils/focusable-elements.utils.d.ts +12 -0
- package/dist/utils/focusable-elements.utils.js +26 -0
- package/dist/utils/input-modality.utils.d.ts +13 -0
- package/dist/utils/input-modality.utils.js +34 -0
- package/dist/utils/theme-generator.utils.d.ts +8 -2
- package/dist/utils/theme-generator.utils.js +30 -9
- package/package.json +1 -1
- package/styles/themes/mixins/eunomia-neutrals.mixin.scss +6 -2
- package/styles/themes/prebuilt-themes/eunomia/eunomia-dark.mixin.scss +6 -2
- package/styles/themes/prebuilt-themes/fire/eunomia-fire-dark.mixin.scss +6 -2
- package/styles/themes/prebuilt-themes/forest/eunomia-forest-dark.mixin.scss +6 -2
- package/styles/themes/prebuilt-themes/gold/eunomia-gold-dark.mixin.scss +6 -2
- package/styles/themes/prebuilt-themes/ocean/eunomia-ocean-dark.mixin.scss +6 -2
- package/styles/themes/prebuilt-themes/salmon/eunomia-salmon-dark.mixin.scss +6 -2
- package/styles/themes/prebuilt-themes/violet/eunomia-violet-dark.mixin.scss +6 -2
- package/dist/cdn/components/chunks/chunk-6VK6SHCG.js +0 -1
- package/dist/cdn/components/chunks/chunk-UDOZRIJZ.js +0 -1
|
@@ -5,6 +5,12 @@ import { EunomiaIconName } from "../../content/icon/icon.type.js";
|
|
|
5
5
|
* Tag name of the search component.
|
|
6
6
|
*/
|
|
7
7
|
export declare const EunomiaSearchTagName = "eun-search";
|
|
8
|
+
/**
|
|
9
|
+
* How the suggestions dropdown filters its options against the typed value.
|
|
10
|
+
* `contains` keeps the options whose label contains it, `none` shows every
|
|
11
|
+
* option as is, for results already filtered by a server.
|
|
12
|
+
*/
|
|
13
|
+
export type EunomiaSearchFilter = "contains" | "none";
|
|
8
14
|
declare const EunomiaSearch_base: import("../../../utils/constructor.type.js").Constructor<import("../../../mixins/anchor-position.mixin.js").AnchorPositionMixinInterface> & typeof EunomiaInput;
|
|
9
15
|
/**
|
|
10
16
|
* An input field specialized for search: the native type is locked to
|
|
@@ -24,6 +30,8 @@ declare const EunomiaSearch_base: import("../../../utils/constructor.type.js").C
|
|
|
24
30
|
*
|
|
25
31
|
* @slot [icon] - Replaces the leading icon entirely with any content, not just an icon element. Falls back to icon when empty. Applies to the real field, inline or inside the panel modal. The compact panel trigger button always shows the plain icon glyph, since it can't project the same slotted content a second time
|
|
26
32
|
* @slot results - Content rendered below the field inside the panel, such as a result list. Only relevant when panel is set
|
|
33
|
+
* @slot trigger - Replaces the panel's built-in trigger button, for example with an icon button. A click on it opens the panel, and focus returns to it on close. Give it its own accessible name. Only relevant when panel is set
|
|
34
|
+
* @csspart trigger - The panel's built-in trigger button, shown while nothing is slotted in trigger
|
|
27
35
|
* @prop {boolean} [shortcut=false] - Enables the Ctrl+K or Cmd+K global shortcut and its visual key hint badge
|
|
28
36
|
* @prop {boolean} [panel=false] - Opens a modal command palette panel on shortcut or click instead of focusing inline
|
|
29
37
|
* @prop {string} [panelLabel] - The accessible name of the panel's dialog, used when label isn't set. Defaults to the localized string for the current locale (English: "Search")
|
|
@@ -31,8 +39,11 @@ declare const EunomiaSearch_base: import("../../../utils/constructor.type.js").C
|
|
|
31
39
|
* @prop {string} [loadingLabel='Loading…'] - The accessible label announced by the loading indicator while loading is set
|
|
32
40
|
* @prop {boolean} [suggestions=false] - Opens a dropdown listbox showing light DOM option and optgroup children matching the typed value, highlighting the matched substring. Ignored while panel is set
|
|
33
41
|
* @prop {string} [noResultsLabel='No results'] - Text displayed in the dropdown when no option matches, while suggestions is set
|
|
34
|
-
* @
|
|
42
|
+
* @prop {'contains' | 'none'} [filter='contains'] - How the suggestions are filtered against the typed value. Contains keeps the options whose label contains it, none shows every option as is, for results already filtered by a server
|
|
43
|
+
* @fires {ChangeEvent} eunchange - Fired on every value change, typed or picked from the suggestions
|
|
44
|
+
* @fires {SelectEvent} eunselect - Fired when a suggestion is picked, with the option's value as key
|
|
35
45
|
* @cssprop [--field-listbox-max-height=260px] - Sets the maximum height of the suggestions dropdown, past which it scrolls. Shared with the select component
|
|
46
|
+
* @cssprop [--field-listbox-border-radius] - Sets the corner radius of the suggestions dropdown, independent of the field's own radius. Shared with the select component
|
|
36
47
|
* @cssprop [--field-listbox-transition-duration=200ms] - Sets the duration of the suggestions dropdown's open and close transition. Shared with the select component
|
|
37
48
|
* @cssprop [--field-match-color] - Sets the color of the matched search substring, highlighted while suggestions is set. Shared with the select component
|
|
38
49
|
* @cssprop [--field-match-background] - Sets the background of the matched search substring, none by default. Shared with the select component
|
|
@@ -120,9 +131,10 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
120
131
|
* mechanic (`AnchorPositionMixin`, CSS Anchor Positioning with a JS
|
|
121
132
|
* fallback) as `eun-select`'s own dropdown, sharing its CSS custom
|
|
122
133
|
* properties (`--field-listbox-max-height`, `--field-match-*`, etc.).
|
|
123
|
-
* Picking a suggestion sets `value` to its label
|
|
124
|
-
*
|
|
125
|
-
*
|
|
134
|
+
* Picking a suggestion sets `value` to its label, then fires `eunselect`
|
|
135
|
+
* with the option's own `value` attribute, so two options sharing a label
|
|
136
|
+
* stay distinguishable. Ignored while `panel` is set — combining the two
|
|
137
|
+
* isn't supported.
|
|
126
138
|
* @default false
|
|
127
139
|
*/
|
|
128
140
|
suggestions: boolean;
|
|
@@ -132,6 +144,14 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
132
144
|
* @default No results
|
|
133
145
|
*/
|
|
134
146
|
noResultsLabel: string;
|
|
147
|
+
/**
|
|
148
|
+
* How the suggestions are filtered against the typed value : `contains`
|
|
149
|
+
* keeps the options whose label contains it, `none` shows every option as
|
|
150
|
+
* is, for results a server already filtered, possibly on another field
|
|
151
|
+
* than the label.
|
|
152
|
+
* @default contains
|
|
153
|
+
*/
|
|
154
|
+
filter: EunomiaSearchFilter;
|
|
135
155
|
/**
|
|
136
156
|
* Whether the suggestions dropdown is currently open.
|
|
137
157
|
* @internal
|
|
@@ -156,6 +176,12 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
156
176
|
* @readonly
|
|
157
177
|
*/
|
|
158
178
|
private readonly fieldWrapperEl?;
|
|
179
|
+
/**
|
|
180
|
+
* The `trigger` slot, rendered in place of the field while `panel` is set,
|
|
181
|
+
* with the built-in trigger button as its fallback content.
|
|
182
|
+
* @internal
|
|
183
|
+
*/
|
|
184
|
+
private readonly triggerSlot?;
|
|
159
185
|
/**
|
|
160
186
|
* The collapsed trigger button rendered in place of the field while
|
|
161
187
|
* `panel` is set.
|
|
@@ -191,6 +217,14 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
191
217
|
* @private
|
|
192
218
|
*/
|
|
193
219
|
private static readonly FIELD_POINTER_DOWN_WINDOW_MS;
|
|
220
|
+
/**
|
|
221
|
+
* Re-renders the suggestions whenever the light DOM `option`/`optgroup`
|
|
222
|
+
* children change, since they aren't reactive properties : a consumer
|
|
223
|
+
* replacing them with a server's results would otherwise stay unseen until
|
|
224
|
+
* some unrelated property changed.
|
|
225
|
+
* @internal
|
|
226
|
+
*/
|
|
227
|
+
private readonly optionsObserver;
|
|
194
228
|
connectedCallback(): void;
|
|
195
229
|
disconnectedCallback(): void;
|
|
196
230
|
/**
|
|
@@ -207,7 +241,7 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
207
241
|
* still-closed modal at this point, and focusing hidden popover content
|
|
208
242
|
* is a no-op — leaving focus stranded on the (invisible) host with
|
|
209
243
|
* nowhere to land, e.g. on a Shift+Tab back onto it from just past the
|
|
210
|
-
* trigger.
|
|
244
|
+
* trigger. A trigger slotted in `trigger` takes its place.
|
|
211
245
|
* @protected
|
|
212
246
|
*/
|
|
213
247
|
protected focusTarget(): HTMLElement | undefined;
|
|
@@ -219,6 +253,12 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
219
253
|
* Closes the command-palette panel. No-op when `panel` isn't set.
|
|
220
254
|
*/
|
|
221
255
|
closePanel(): void;
|
|
256
|
+
/**
|
|
257
|
+
* Opens the panel on a click anywhere in the `trigger` slot, its slotted
|
|
258
|
+
* content or the built-in button it falls back to, unless disabled.
|
|
259
|
+
* @private
|
|
260
|
+
*/
|
|
261
|
+
private readonly handleTriggerClick;
|
|
222
262
|
/**
|
|
223
263
|
* Lifecycle hook called after the component's first render. Attaches the
|
|
224
264
|
* suggestions dropdown's event listeners directly on the field element,
|
|
@@ -250,7 +290,7 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
250
290
|
private get effectiveQuery();
|
|
251
291
|
/**
|
|
252
292
|
* Options filtered by {@link effectiveQuery}. Shows every option when the
|
|
253
|
-
* field is empty
|
|
293
|
+
* field is empty, or when {@link filter} is `none`.
|
|
254
294
|
* @internal
|
|
255
295
|
*/
|
|
256
296
|
private get filteredOptions();
|
|
@@ -318,6 +358,19 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
318
358
|
* @private
|
|
319
359
|
*/
|
|
320
360
|
private readonly handleSuggestionsFieldActivate;
|
|
361
|
+
/**
|
|
362
|
+
* Closes the dropdown once focus has left the component entirely, e.g.
|
|
363
|
+
* `Tab`-ing away, same as `eun-select`'s own `handleFocusOut` : the
|
|
364
|
+
* Popover API's light-dismiss only reacts to outside clicks, not to focus
|
|
365
|
+
* moving via the keyboard. `closeSuggestions` checks the popover itself
|
|
366
|
+
* rather than `isOpen`, which only follows the asynchronous `toggle`
|
|
367
|
+
* event. Checked a frame later, since the newly focused
|
|
368
|
+
* element hasn't received focus yet when `focusout` fires. Picking an
|
|
369
|
+
* option never gets here, its row cancels `mousedown` so the field keeps
|
|
370
|
+
* focus.
|
|
371
|
+
* @private
|
|
372
|
+
*/
|
|
373
|
+
private readonly handleSuggestionsFocusOut;
|
|
321
374
|
/**
|
|
322
375
|
* Opens the dropdown and resets the highlight on every keystroke. Bound to
|
|
323
376
|
* the field's native `input` event (rather than reacting to `value`
|
|
@@ -329,9 +382,9 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
329
382
|
*/
|
|
330
383
|
private readonly handleSuggestionsInput;
|
|
331
384
|
/**
|
|
332
|
-
* Picks a suggestion : sets `value` to its label
|
|
333
|
-
*
|
|
334
|
-
*
|
|
385
|
+
* Picks a suggestion : sets `value` to its label, fires `eunchange` with
|
|
386
|
+
* it like a keystroke would, then `eunselect` with the option's own
|
|
387
|
+
* `value`, and closes the dropdown.
|
|
335
388
|
*
|
|
336
389
|
* @param option the chosen option.
|
|
337
390
|
* @private
|
|
@@ -495,7 +548,8 @@ export declare class EunomiaSearch extends EunomiaSearch_base {
|
|
|
495
548
|
private syncSuggestionsAria;
|
|
496
549
|
/**
|
|
497
550
|
* Renders the search component: the inherited inline field, or — when
|
|
498
|
-
* `panel` is set — a trigger
|
|
551
|
+
* `panel` is set — a trigger (the `trigger` slot, falling back to a
|
|
552
|
+
* built-in button) plus a `eun-modal[kind=search]`
|
|
499
553
|
* (flush, no padding, no close button) containing the real field (reused
|
|
500
554
|
* via `renderField`, wrapped for its own full-width/no-border styling) and
|
|
501
555
|
* a `results` slot.
|
|
@@ -13,10 +13,12 @@ import { EunomiaInput } from "../input/input.js";
|
|
|
13
13
|
import { searchStyles } from "./search.styles.js";
|
|
14
14
|
import { AnchorPositionMixin } from "../../../mixins/anchor-position.mixin.js";
|
|
15
15
|
import { ChangeEvent } from "../../../events/change.event.js";
|
|
16
|
+
import { SelectEvent } from "../../../events/select.event.js";
|
|
16
17
|
import { listboxStyles, listboxAnchorPositioningStyles, } from "../shared-styles/listbox.styles.js";
|
|
17
18
|
import { parseListboxOptions, renderHighlightedLabel, renderListboxRows, } from "../../../utils/listbox-options.utils.js";
|
|
18
19
|
import { isWebKit } from "../../../utils/browser.utils.js";
|
|
19
20
|
import { resolveDurationMs, resolveEasing, } from "../../../utils/motion.utils.js";
|
|
21
|
+
import { defaultTrueConverter } from "../../../utils/boolean.utils.js";
|
|
20
22
|
/**
|
|
21
23
|
* Tag name of the search component.
|
|
22
24
|
*/
|
|
@@ -39,6 +41,8 @@ export const EunomiaSearchTagName = "eun-search";
|
|
|
39
41
|
*
|
|
40
42
|
* @slot [icon] - Replaces the leading icon entirely with any content, not just an icon element. Falls back to icon when empty. Applies to the real field, inline or inside the panel modal. The compact panel trigger button always shows the plain icon glyph, since it can't project the same slotted content a second time
|
|
41
43
|
* @slot results - Content rendered below the field inside the panel, such as a result list. Only relevant when panel is set
|
|
44
|
+
* @slot trigger - Replaces the panel's built-in trigger button, for example with an icon button. A click on it opens the panel, and focus returns to it on close. Give it its own accessible name. Only relevant when panel is set
|
|
45
|
+
* @csspart trigger - The panel's built-in trigger button, shown while nothing is slotted in trigger
|
|
42
46
|
* @prop {boolean} [shortcut=false] - Enables the Ctrl+K or Cmd+K global shortcut and its visual key hint badge
|
|
43
47
|
* @prop {boolean} [panel=false] - Opens a modal command palette panel on shortcut or click instead of focusing inline
|
|
44
48
|
* @prop {string} [panelLabel] - The accessible name of the panel's dialog, used when label isn't set. Defaults to the localized string for the current locale (English: "Search")
|
|
@@ -46,8 +50,11 @@ export const EunomiaSearchTagName = "eun-search";
|
|
|
46
50
|
* @prop {string} [loadingLabel='Loading…'] - The accessible label announced by the loading indicator while loading is set
|
|
47
51
|
* @prop {boolean} [suggestions=false] - Opens a dropdown listbox showing light DOM option and optgroup children matching the typed value, highlighting the matched substring. Ignored while panel is set
|
|
48
52
|
* @prop {string} [noResultsLabel='No results'] - Text displayed in the dropdown when no option matches, while suggestions is set
|
|
49
|
-
* @
|
|
53
|
+
* @prop {'contains' | 'none'} [filter='contains'] - How the suggestions are filtered against the typed value. Contains keeps the options whose label contains it, none shows every option as is, for results already filtered by a server
|
|
54
|
+
* @fires {ChangeEvent} eunchange - Fired on every value change, typed or picked from the suggestions
|
|
55
|
+
* @fires {SelectEvent} eunselect - Fired when a suggestion is picked, with the option's value as key
|
|
50
56
|
* @cssprop [--field-listbox-max-height=260px] - Sets the maximum height of the suggestions dropdown, past which it scrolls. Shared with the select component
|
|
57
|
+
* @cssprop [--field-listbox-border-radius] - Sets the corner radius of the suggestions dropdown, independent of the field's own radius. Shared with the select component
|
|
51
58
|
* @cssprop [--field-listbox-transition-duration=200ms] - Sets the duration of the suggestions dropdown's open and close transition. Shared with the select component
|
|
52
59
|
* @cssprop [--field-match-color] - Sets the color of the matched search substring, highlighted while suggestions is set. Shared with the select component
|
|
53
60
|
* @cssprop [--field-match-background] - Sets the background of the matched search substring, none by default. Shared with the select component
|
|
@@ -123,9 +130,10 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
123
130
|
* mechanic (`AnchorPositionMixin`, CSS Anchor Positioning with a JS
|
|
124
131
|
* fallback) as `eun-select`'s own dropdown, sharing its CSS custom
|
|
125
132
|
* properties (`--field-listbox-max-height`, `--field-match-*`, etc.).
|
|
126
|
-
* Picking a suggestion sets `value` to its label
|
|
127
|
-
*
|
|
128
|
-
*
|
|
133
|
+
* Picking a suggestion sets `value` to its label, then fires `eunselect`
|
|
134
|
+
* with the option's own `value` attribute, so two options sharing a label
|
|
135
|
+
* stay distinguishable. Ignored while `panel` is set — combining the two
|
|
136
|
+
* isn't supported.
|
|
129
137
|
* @default false
|
|
130
138
|
*/
|
|
131
139
|
this.suggestions = false;
|
|
@@ -135,6 +143,14 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
135
143
|
* @default No results
|
|
136
144
|
*/
|
|
137
145
|
this.noResultsLabel = "No results";
|
|
146
|
+
/**
|
|
147
|
+
* How the suggestions are filtered against the typed value : `contains`
|
|
148
|
+
* keeps the options whose label contains it, `none` shows every option as
|
|
149
|
+
* is, for results a server already filtered, possibly on another field
|
|
150
|
+
* than the label.
|
|
151
|
+
* @default contains
|
|
152
|
+
*/
|
|
153
|
+
this.filter = "contains";
|
|
138
154
|
/**
|
|
139
155
|
* Whether the suggestions dropdown is currently open.
|
|
140
156
|
* @internal
|
|
@@ -146,6 +162,29 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
146
162
|
* @internal
|
|
147
163
|
*/
|
|
148
164
|
this.highlightedIndex = -1;
|
|
165
|
+
/**
|
|
166
|
+
* Re-renders the suggestions whenever the light DOM `option`/`optgroup`
|
|
167
|
+
* children change, since they aren't reactive properties : a consumer
|
|
168
|
+
* replacing them with a server's results would otherwise stay unseen until
|
|
169
|
+
* some unrelated property changed.
|
|
170
|
+
* @internal
|
|
171
|
+
*/
|
|
172
|
+
this.optionsObserver = new MutationObserver(() => {
|
|
173
|
+
if (this.highlightedIndex >= this.filteredOptions.length) {
|
|
174
|
+
this.highlightedIndex = -1;
|
|
175
|
+
}
|
|
176
|
+
this.requestUpdate();
|
|
177
|
+
});
|
|
178
|
+
/**
|
|
179
|
+
* Opens the panel on a click anywhere in the `trigger` slot, its slotted
|
|
180
|
+
* content or the built-in button it falls back to, unless disabled.
|
|
181
|
+
* @private
|
|
182
|
+
*/
|
|
183
|
+
this.handleTriggerClick = () => {
|
|
184
|
+
if (!this.disabled) {
|
|
185
|
+
this.openPanel();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
149
188
|
/**
|
|
150
189
|
* Records that the field itself was the pointerdown target — see
|
|
151
190
|
* {@link fieldPointerDownAt}.
|
|
@@ -165,6 +204,25 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
165
204
|
}
|
|
166
205
|
this.openSuggestions();
|
|
167
206
|
};
|
|
207
|
+
/**
|
|
208
|
+
* Closes the dropdown once focus has left the component entirely, e.g.
|
|
209
|
+
* `Tab`-ing away, same as `eun-select`'s own `handleFocusOut` : the
|
|
210
|
+
* Popover API's light-dismiss only reacts to outside clicks, not to focus
|
|
211
|
+
* moving via the keyboard. `closeSuggestions` checks the popover itself
|
|
212
|
+
* rather than `isOpen`, which only follows the asynchronous `toggle`
|
|
213
|
+
* event. Checked a frame later, since the newly focused
|
|
214
|
+
* element hasn't received focus yet when `focusout` fires. Picking an
|
|
215
|
+
* option never gets here, its row cancels `mousedown` so the field keeps
|
|
216
|
+
* focus.
|
|
217
|
+
* @private
|
|
218
|
+
*/
|
|
219
|
+
this.handleSuggestionsFocusOut = () => {
|
|
220
|
+
requestAnimationFrame(() => {
|
|
221
|
+
if (!this.matches(":focus-within")) {
|
|
222
|
+
this.closeSuggestions();
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
};
|
|
168
226
|
/**
|
|
169
227
|
* Opens the dropdown and resets the highlight on every keystroke. Bound to
|
|
170
228
|
* the field's native `input` event (rather than reacting to `value`
|
|
@@ -289,9 +347,17 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
289
347
|
connectedCallback() {
|
|
290
348
|
super.connectedCallback?.();
|
|
291
349
|
window.addEventListener("keydown", this.handleShortcut);
|
|
350
|
+
this.optionsObserver.observe(this, {
|
|
351
|
+
childList: true,
|
|
352
|
+
subtree: true,
|
|
353
|
+
characterData: true,
|
|
354
|
+
attributes: true,
|
|
355
|
+
attributeFilter: ["value", "label"],
|
|
356
|
+
});
|
|
292
357
|
}
|
|
293
358
|
disconnectedCallback() {
|
|
294
359
|
window.removeEventListener("keydown", this.handleShortcut);
|
|
360
|
+
this.optionsObserver.disconnect();
|
|
295
361
|
super.disconnectedCallback?.();
|
|
296
362
|
}
|
|
297
363
|
/**
|
|
@@ -313,12 +379,13 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
313
379
|
* still-closed modal at this point, and focusing hidden popover content
|
|
314
380
|
* is a no-op — leaving focus stranded on the (invisible) host with
|
|
315
381
|
* nowhere to land, e.g. on a Shift+Tab back onto it from just past the
|
|
316
|
-
* trigger.
|
|
382
|
+
* trigger. A trigger slotted in `trigger` takes its place.
|
|
317
383
|
* @protected
|
|
318
384
|
*/
|
|
319
385
|
focusTarget() {
|
|
320
386
|
if (this.panel) {
|
|
321
|
-
|
|
387
|
+
const [slotted] = this.triggerSlot?.assignedElements() ?? [];
|
|
388
|
+
return slotted instanceof HTMLElement ? slotted : this.triggerEl;
|
|
322
389
|
}
|
|
323
390
|
return super.focusTarget();
|
|
324
391
|
}
|
|
@@ -357,6 +424,7 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
357
424
|
field.addEventListener("click", this.handleSuggestionsFieldActivate);
|
|
358
425
|
field.addEventListener("input", this.handleSuggestionsInput);
|
|
359
426
|
field.addEventListener("keydown", this.handleSuggestionsKeydown);
|
|
427
|
+
this.addEventListener("focusout", this.handleSuggestionsFocusOut);
|
|
360
428
|
}
|
|
361
429
|
/**
|
|
362
430
|
* The available suggestions, parsed from the light DOM `option`/`optgroup`
|
|
@@ -380,12 +448,12 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
380
448
|
}
|
|
381
449
|
/**
|
|
382
450
|
* Options filtered by {@link effectiveQuery}. Shows every option when the
|
|
383
|
-
* field is empty
|
|
451
|
+
* field is empty, or when {@link filter} is `none`.
|
|
384
452
|
* @internal
|
|
385
453
|
*/
|
|
386
454
|
get filteredOptions() {
|
|
387
455
|
const query = this.effectiveQuery;
|
|
388
|
-
if (!query) {
|
|
456
|
+
if (!query || this.filter === "none") {
|
|
389
457
|
return this.options;
|
|
390
458
|
}
|
|
391
459
|
return this.options.filter((option) => option.label.toLowerCase().includes(query));
|
|
@@ -501,16 +569,17 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
501
569
|
});
|
|
502
570
|
}
|
|
503
571
|
/**
|
|
504
|
-
* Picks a suggestion : sets `value` to its label
|
|
505
|
-
*
|
|
506
|
-
*
|
|
572
|
+
* Picks a suggestion : sets `value` to its label, fires `eunchange` with
|
|
573
|
+
* it like a keystroke would, then `eunselect` with the option's own
|
|
574
|
+
* `value`, and closes the dropdown.
|
|
507
575
|
*
|
|
508
576
|
* @param option the chosen option.
|
|
509
577
|
* @private
|
|
510
578
|
*/
|
|
511
579
|
handleSelect(option) {
|
|
512
580
|
this.value = option.label;
|
|
513
|
-
this.dispatchEvent(new ChangeEvent());
|
|
581
|
+
this.dispatchEvent(new ChangeEvent(this.value));
|
|
582
|
+
this.dispatchEvent(new SelectEvent(option.value));
|
|
514
583
|
this.closeSuggestions();
|
|
515
584
|
}
|
|
516
585
|
/**
|
|
@@ -779,12 +848,14 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
779
848
|
}
|
|
780
849
|
/**
|
|
781
850
|
* Renders the search component: the inherited inline field, or — when
|
|
782
|
-
* `panel` is set — a trigger
|
|
851
|
+
* `panel` is set — a trigger (the `trigger` slot, falling back to a
|
|
852
|
+
* built-in button) plus a `eun-modal[kind=search]`
|
|
783
853
|
* (flush, no padding, no close button) containing the real field (reused
|
|
784
854
|
* via `renderField`, wrapped for its own full-width/no-border styling) and
|
|
785
855
|
* a `results` slot.
|
|
786
856
|
* @returns The rendered HTML template
|
|
787
857
|
*/
|
|
858
|
+
/* eslint-disable lit-a11y/click-events-have-key-events */
|
|
788
859
|
render() {
|
|
789
860
|
if (!this.panel) {
|
|
790
861
|
return super.render();
|
|
@@ -793,25 +864,29 @@ let EunomiaSearch = EunomiaSearch_1 = class EunomiaSearch extends AnchorPosition
|
|
|
793
864
|
return html `
|
|
794
865
|
<div id="wrapper">
|
|
795
866
|
${this.renderFormLabels("search-trigger")}
|
|
796
|
-
<
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
867
|
+
<slot name="trigger" @click=${this.handleTriggerClick}>
|
|
868
|
+
<button
|
|
869
|
+
id="search-trigger"
|
|
870
|
+
part="trigger"
|
|
871
|
+
type="button"
|
|
872
|
+
aria-haspopup="dialog"
|
|
873
|
+
aria-label=${ifDefined(this.label)}
|
|
874
|
+
aria-keyshortcuts=${ifDefined(this.shortcut ? "Control+K Meta+K" : undefined)}
|
|
875
|
+
?disabled=${this.disabled}
|
|
876
|
+
>
|
|
877
|
+
${this.icon
|
|
806
878
|
? html `<eun-icon
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
879
|
+
id="trigger-icon"
|
|
880
|
+
name=${this.icon}
|
|
881
|
+
size="16"
|
|
882
|
+
></eun-icon>`
|
|
811
883
|
: nothing}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
884
|
+
<span id="trigger-text" class="empty"
|
|
885
|
+
>${this.placeholder || ""}</span
|
|
886
|
+
>
|
|
887
|
+
${this.renderTriggerIndicator()}
|
|
888
|
+
</button>
|
|
889
|
+
</slot>
|
|
815
890
|
<eun-modal
|
|
816
891
|
id="panel"
|
|
817
892
|
kind="search"
|
|
@@ -857,7 +932,7 @@ __decorate([
|
|
|
857
932
|
property()
|
|
858
933
|
], EunomiaSearch.prototype, "icon", void 0);
|
|
859
934
|
__decorate([
|
|
860
|
-
property({
|
|
935
|
+
property({ converter: defaultTrueConverter })
|
|
861
936
|
], EunomiaSearch.prototype, "clearable", void 0);
|
|
862
937
|
__decorate([
|
|
863
938
|
property({ type: Boolean })
|
|
@@ -880,6 +955,9 @@ __decorate([
|
|
|
880
955
|
__decorate([
|
|
881
956
|
property({ attribute: "no-results-label" })
|
|
882
957
|
], EunomiaSearch.prototype, "noResultsLabel", void 0);
|
|
958
|
+
__decorate([
|
|
959
|
+
property()
|
|
960
|
+
], EunomiaSearch.prototype, "filter", void 0);
|
|
883
961
|
__decorate([
|
|
884
962
|
state()
|
|
885
963
|
], EunomiaSearch.prototype, "isOpen", void 0);
|
|
@@ -892,6 +970,9 @@ __decorate([
|
|
|
892
970
|
__decorate([
|
|
893
971
|
query("#field-wrapper")
|
|
894
972
|
], EunomiaSearch.prototype, "fieldWrapperEl", void 0);
|
|
973
|
+
__decorate([
|
|
974
|
+
query('slot[name="trigger"]')
|
|
975
|
+
], EunomiaSearch.prototype, "triggerSlot", void 0);
|
|
895
976
|
__decorate([
|
|
896
977
|
query("#search-trigger")
|
|
897
978
|
], EunomiaSearch.prototype, "triggerEl", void 0);
|
|
@@ -6,6 +6,8 @@ import { FormMixinInterface } from "../../../mixins/form.mixin.js";
|
|
|
6
6
|
import { FormLabelMixinInterface } from "../../../mixins/form-label.mixin.js";
|
|
7
7
|
import { EditableMixinInterface } from "../../../mixins/editable.mixin.js";
|
|
8
8
|
import { FieldAppearanceMixinInterface } from "../../../mixins/field-appearance.mixin.js";
|
|
9
|
+
import { RoundedMixinInterface } from "../../../mixins/rounded.mixin.js";
|
|
10
|
+
import { FieldSizeMixinInterface } from "../../../mixins/field-size.mixin.js";
|
|
9
11
|
import { AnchorPositionMixinInterface } from "../../../mixins/anchor-position.mixin.js";
|
|
10
12
|
import { EunomiaIconName } from "../../content/icon/icon.type.js";
|
|
11
13
|
import { Constructor } from "../../../utils/constructor.type.js";
|
|
@@ -23,7 +25,7 @@ type SelectValue = string | string[];
|
|
|
23
25
|
* Type of the select base used to declare every necessary Mixin interface elements.
|
|
24
26
|
* @internal
|
|
25
27
|
*/
|
|
26
|
-
type EunomiaSelectBase = LitElement & DisabledMixinInterface & ReadonlyMixinInterface & ValidatorsMixinInterface<SelectValue> & FormMixinInterface<SelectValue> & EditableMixinInterface & FormLabelMixinInterface & FieldAppearanceMixinInterface & AnchorPositionMixinInterface & LocalizableMixinInterface;
|
|
28
|
+
type EunomiaSelectBase = LitElement & DisabledMixinInterface & ReadonlyMixinInterface & ValidatorsMixinInterface<SelectValue> & FormMixinInterface<SelectValue> & EditableMixinInterface & FormLabelMixinInterface & FieldAppearanceMixinInterface & RoundedMixinInterface & FieldSizeMixinInterface & AnchorPositionMixinInterface & LocalizableMixinInterface;
|
|
27
29
|
declare const EunomiaSelectMixinBase: Constructor<EunomiaSelectBase>;
|
|
28
30
|
/**
|
|
29
31
|
* A field that picks one or more values from a list of option and optgroup
|
|
@@ -51,6 +53,8 @@ declare const EunomiaSelectMixinBase: Constructor<EunomiaSelectBase>;
|
|
|
51
53
|
* @prop {boolean} [native=false] - Renders the field as a real select, using the browser's own dropdown instead of the listbox panel. Takes priority over searchable and multiple, neither of which a native dropdown can support
|
|
52
54
|
* @prop {boolean} [multiple=false] - Whether more than one option can be picked at once. Each option then renders a checkbox, and picking one toggles it without closing the dropdown, so value becomes an array of every picked option's value. Ignored while native is set
|
|
53
55
|
* @prop {'outline' | 'flat' | 'underline'} [appearance='outline'] - How the field's surface is drawn: a bordered box, a muted background with no border, or a bottom border only
|
|
56
|
+
* @prop {boolean} [rounded=false] - Whether the field is fully rounded, as a pill. A custom border radius still wins over it
|
|
57
|
+
* @prop {'xs' | 's' | 'm' | 'l' | 'xl'} [size='m'] - The field size. A field and a button of the same size share the same height
|
|
54
58
|
* @prop {string} label - The title label of the field, rendered through the label component
|
|
55
59
|
* @prop {string} instructions - Instructions displayed below the label
|
|
56
60
|
* @prop {string} name - The field name
|
|
@@ -104,10 +108,12 @@ declare const EunomiaSelectMixinBase: Constructor<EunomiaSelectBase>;
|
|
|
104
108
|
* @cssprop [--field-confirm-link-color] - Sets the color of the confirm slot's link, while editing in readonlyAvailable mode
|
|
105
109
|
* @cssprop [--field-confirm-link-color-hover] - Sets the hover color of the confirm slot's link
|
|
106
110
|
* @cssprop [--field-listbox-max-height=260px] - Sets the maximum height of the dropdown panel, past which it scrolls
|
|
111
|
+
* @cssprop [--field-listbox-border-radius] - Sets the corner radius of the dropdown panel, independent of the field's own radius
|
|
107
112
|
* @cssprop [--field-listbox-transition-duration=200ms] - Sets the duration of the dropdown panel's open and close height transition, disabled entirely by the no-animation attribute or reduced motion settings
|
|
108
113
|
* @cssprop [--eun-viewport-inset-top] - Reserves space, such as a page's sticky header height, that the dropdown panel keeps clear of at the top of the viewport. Set on the root or an ancestor rather than on the field itself
|
|
109
114
|
* @cssprop [--eun-viewport-inset-bottom] - The same as eun-viewport-inset-top, reserved at the bottom of the viewport, such as for a sticky footer
|
|
110
115
|
* @cssprop [--field-font-size] - Sets the font size of the field's value and placeholder
|
|
116
|
+
* @cssprop [--field-line-height] - Sets the line height of the field's value and placeholder
|
|
111
117
|
* @cssprop [--field-label-font-size] - Sets the font size of the label
|
|
112
118
|
* @cssprop [--field-message-font-size] - Sets the font size of the hint, error messages and instructions
|
|
113
119
|
* @element eun-select
|
|
@@ -16,6 +16,8 @@ import { FormMixin } from "../../../mixins/form.mixin.js";
|
|
|
16
16
|
import { FormLabelMixin, } from "../../../mixins/form-label.mixin.js";
|
|
17
17
|
import { EditableMixin, } from "../../../mixins/editable.mixin.js";
|
|
18
18
|
import { FieldAppearanceMixin, } from "../../../mixins/field-appearance.mixin.js";
|
|
19
|
+
import { RoundedMixin, } from "../../../mixins/rounded.mixin.js";
|
|
20
|
+
import { FieldSizeMixin, } from "../../../mixins/field-size.mixin.js";
|
|
19
21
|
import { AnchorPositionMixin, } from "../../../mixins/anchor-position.mixin.js";
|
|
20
22
|
import { ChangeEvent } from "../../../events/change.event.js";
|
|
21
23
|
import { formLabelsStyles } from "../shared-styles/form-labels.styles.js";
|
|
@@ -33,7 +35,7 @@ export const EunomiaSelectTagName = "eun-select";
|
|
|
33
35
|
* @internal
|
|
34
36
|
*/
|
|
35
37
|
const Base = DisabledMixin(ValidatorsMixin(LitElement));
|
|
36
|
-
const EunomiaSelectMixinBase = LocalizableMixin(AnchorPositionMixin(FieldAppearanceMixin(FormLabelMixin(ReadonlyMixin(EditableMixin(FormMixin(Base)))))));
|
|
38
|
+
const EunomiaSelectMixinBase = LocalizableMixin(AnchorPositionMixin(RoundedMixin(FieldSizeMixin(FieldAppearanceMixin(FormLabelMixin(ReadonlyMixin(EditableMixin(FormMixin(Base)))))))));
|
|
37
39
|
/**
|
|
38
40
|
* A field that picks one or more values from a list of option and optgroup
|
|
39
41
|
* children. Set searchable to let the field also filter that list as the
|
|
@@ -60,6 +62,8 @@ const EunomiaSelectMixinBase = LocalizableMixin(AnchorPositionMixin(FieldAppeara
|
|
|
60
62
|
* @prop {boolean} [native=false] - Renders the field as a real select, using the browser's own dropdown instead of the listbox panel. Takes priority over searchable and multiple, neither of which a native dropdown can support
|
|
61
63
|
* @prop {boolean} [multiple=false] - Whether more than one option can be picked at once. Each option then renders a checkbox, and picking one toggles it without closing the dropdown, so value becomes an array of every picked option's value. Ignored while native is set
|
|
62
64
|
* @prop {'outline' | 'flat' | 'underline'} [appearance='outline'] - How the field's surface is drawn: a bordered box, a muted background with no border, or a bottom border only
|
|
65
|
+
* @prop {boolean} [rounded=false] - Whether the field is fully rounded, as a pill. A custom border radius still wins over it
|
|
66
|
+
* @prop {'xs' | 's' | 'm' | 'l' | 'xl'} [size='m'] - The field size. A field and a button of the same size share the same height
|
|
63
67
|
* @prop {string} label - The title label of the field, rendered through the label component
|
|
64
68
|
* @prop {string} instructions - Instructions displayed below the label
|
|
65
69
|
* @prop {string} name - The field name
|
|
@@ -113,10 +117,12 @@ const EunomiaSelectMixinBase = LocalizableMixin(AnchorPositionMixin(FieldAppeara
|
|
|
113
117
|
* @cssprop [--field-confirm-link-color] - Sets the color of the confirm slot's link, while editing in readonlyAvailable mode
|
|
114
118
|
* @cssprop [--field-confirm-link-color-hover] - Sets the hover color of the confirm slot's link
|
|
115
119
|
* @cssprop [--field-listbox-max-height=260px] - Sets the maximum height of the dropdown panel, past which it scrolls
|
|
120
|
+
* @cssprop [--field-listbox-border-radius] - Sets the corner radius of the dropdown panel, independent of the field's own radius
|
|
116
121
|
* @cssprop [--field-listbox-transition-duration=200ms] - Sets the duration of the dropdown panel's open and close height transition, disabled entirely by the no-animation attribute or reduced motion settings
|
|
117
122
|
* @cssprop [--eun-viewport-inset-top] - Reserves space, such as a page's sticky header height, that the dropdown panel keeps clear of at the top of the viewport. Set on the root or an ancestor rather than on the field itself
|
|
118
123
|
* @cssprop [--eun-viewport-inset-bottom] - The same as eun-viewport-inset-top, reserved at the bottom of the viewport, such as for a sticky footer
|
|
119
124
|
* @cssprop [--field-font-size] - Sets the font size of the field's value and placeholder
|
|
125
|
+
* @cssprop [--field-line-height] - Sets the line height of the field's value and placeholder
|
|
120
126
|
* @cssprop [--field-label-font-size] - Sets the font size of the label
|
|
121
127
|
* @cssprop [--field-message-font-size] - Sets the font size of the hint, error messages and instructions
|
|
122
128
|
* @element eun-select
|
|
@@ -16,7 +16,8 @@ import { css } from "lit";
|
|
|
16
16
|
* [--field-icon-color] - Set a custom color to the leading icon and action buttons
|
|
17
17
|
* [--field-error-color] - Set a custom color to the error state content
|
|
18
18
|
* [--field-hint-color] - Set a custom color to the hint message
|
|
19
|
-
* [--field-font-size] - Set a custom font size for the field's value and placeholder
|
|
19
|
+
* [--field-font-size] - Set a custom font size for the field's value and placeholder, for every size
|
|
20
|
+
* [--field-line-height] - Set a custom line height for the field's value and placeholder, for every size
|
|
20
21
|
* [--field-label-font-size] - Set a custom font size for the label (see label.styles.ts)
|
|
21
22
|
* [--field-message-font-size] - Set a custom font size for the hint, error and instructions (see form-labels.styles.ts)
|
|
22
23
|
* [--field-focus-outline-color] - Set a custom color to the focus outline
|
|
@@ -43,22 +44,50 @@ const base = css `
|
|
|
43
44
|
--field-focus-outline-color,
|
|
44
45
|
var(--eun-color-primary-500, #3d6fff)
|
|
45
46
|
);
|
|
46
|
-
--
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
47
|
+
--_defaultBorderRadius: var(--eun-border-radius-m, 8px);
|
|
48
|
+
--_borderRadius: var(--field-border-radius, var(--_defaultBorderRadius));
|
|
49
|
+
--_defaultPaddingInline: var(--eun-space-s, 8px);
|
|
50
|
+
--_defaultPaddingBlock: var(--eun-space-s, 8px);
|
|
51
|
+
--_defaultFontSize: var(--eun-font-size-s, 14px);
|
|
52
|
+
--_defaultLineHeight: 1rem;
|
|
53
|
+
--_paddingBlock: var(--field-padding-block, var(--_defaultPaddingBlock));
|
|
50
54
|
--_padding: var(
|
|
51
55
|
--field-padding,
|
|
52
|
-
var(--
|
|
53
|
-
var(--field-padding-inline, var(--
|
|
56
|
+
var(--_paddingBlock)
|
|
57
|
+
var(--field-padding-inline, var(--_defaultPaddingInline))
|
|
54
58
|
);
|
|
59
|
+
--_lineHeight: var(--field-line-height, var(--_defaultLineHeight));
|
|
55
60
|
--_shadow: var(--field-shadow, none);
|
|
56
61
|
font-family: var(--eun-font-family, "Mulish", sans-serif);
|
|
57
|
-
font-size: var(--field-font-size, var(--
|
|
62
|
+
font-size: var(--field-font-size, var(--_defaultFontSize));
|
|
58
63
|
display: block;
|
|
59
64
|
width: 100%;
|
|
60
65
|
outline: none;
|
|
61
66
|
}
|
|
67
|
+
:host([rounded]) {
|
|
68
|
+
--_defaultBorderRadius: var(--eun-border-radius-xl, 999px);
|
|
69
|
+
--_defaultPaddingInline: var(--eun-space-m, 16px);
|
|
70
|
+
}
|
|
71
|
+
:host([size="xs"]) {
|
|
72
|
+
--_defaultFontSize: var(--eun-font-size-xs, 10px);
|
|
73
|
+
--_defaultPaddingBlock: var(--eun-space-xxs, 1.6px);
|
|
74
|
+
--_defaultLineHeight: 10px;
|
|
75
|
+
}
|
|
76
|
+
:host([size="s"]) {
|
|
77
|
+
--_defaultFontSize: var(--eun-font-size-xs, 10px);
|
|
78
|
+
--_defaultPaddingBlock: calc(var(--eun-space-s, 8px) / 2);
|
|
79
|
+
--_defaultLineHeight: 10px;
|
|
80
|
+
}
|
|
81
|
+
:host([size="l"]) {
|
|
82
|
+
--_defaultFontSize: var(--eun-font-size-m, 16px);
|
|
83
|
+
--_defaultPaddingBlock: calc(var(--eun-space-s, 8px) * 1.25);
|
|
84
|
+
--_defaultLineHeight: 1.1rem;
|
|
85
|
+
}
|
|
86
|
+
:host([size="xl"]) {
|
|
87
|
+
--_defaultFontSize: var(--eun-font-size-l, 1.3rem);
|
|
88
|
+
--_defaultPaddingBlock: calc(var(--eun-space-s, 8px) * 1.5);
|
|
89
|
+
--_defaultLineHeight: 1.3rem;
|
|
90
|
+
}
|
|
62
91
|
#wrapper {
|
|
63
92
|
display: flex;
|
|
64
93
|
flex-direction: column;
|
|
@@ -77,6 +106,7 @@ const base = css `
|
|
|
77
106
|
border: var(--eun-border-width-m, 1.5px) solid var(--_borderColor);
|
|
78
107
|
border-radius: var(--_borderRadius);
|
|
79
108
|
padding: var(--_padding);
|
|
109
|
+
line-height: var(--_lineHeight);
|
|
80
110
|
outline: 1px solid transparent;
|
|
81
111
|
box-shadow: var(--_shadow);
|
|
82
112
|
box-sizing: border-box;
|
|
@@ -85,6 +115,12 @@ const base = css `
|
|
|
85
115
|
outline-color var(--eun-duration-s, 150ms) var(--eun-easing-default, ease);
|
|
86
116
|
appearance: none;
|
|
87
117
|
}
|
|
118
|
+
input#field,
|
|
119
|
+
button#field {
|
|
120
|
+
box-sizing: content-box;
|
|
121
|
+
min-width: 0;
|
|
122
|
+
height: var(--_lineHeight);
|
|
123
|
+
}
|
|
88
124
|
#field::placeholder {
|
|
89
125
|
color: var(--_placeholderColor);
|
|
90
126
|
}
|
|
@@ -181,6 +217,7 @@ const base = css `
|
|
|
181
217
|
}
|
|
182
218
|
#readonly-display {
|
|
183
219
|
padding: var(--_padding);
|
|
220
|
+
line-height: var(--_lineHeight);
|
|
184
221
|
border: var(--eun-border-width-m, 1.5px) solid transparent;
|
|
185
222
|
border-radius: var(--_borderRadius);
|
|
186
223
|
box-sizing: border-box;
|