Skip to content

Commit

Permalink
fix: close c-select menu on focus lost, fix open-on-clear
Browse files Browse the repository at this point in the history
  • Loading branch information
ascott18 committed Dec 4, 2024
1 parent 066198e commit 8bf9ffe
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# 5.3.0

## Features

- Added `multiple` prop to `c-select`, allowing for the selection of multiple models.
- `c-select-many-to-many` is now based on `c-select` rather than `v-autocomplete`. As a result, it has gained support for all of the props and slots of `c-select`.
- Added strong types for pass-through Vuetify slots and props to `c-input`, `c-select`, `c-select-many-to-many`, and `c-datetime-picker`.
- Added a `color` prop to `c-datetime-picker`.
- Added experimental client-side support for System.Text.Json's PreserveReferences reference handling option in server responses. This does not require changes to your JSON settings in Program.cs - instead, it is activated by setting `refResponse` on the `DataSourceParameters` for a request (i.e. the `$params` object on a ViewModel or ListViewModel). This option can significantly reduce response sizes in cases where the same object occurs many times in a response.

## Fixes

- `c-select` `open-on-clear` prop once again functions as expected.
- `c-select` now closes when changing focus to other elements on the page

# 5.2.1

## Fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
for="Person"
multiple
v-model:objectValue="selectedModels"
open-on-clear
:create="{
getLabel(search: string, items: Person[]) { return items.length == 0 ? search : false },
async getItem(search: string, label: string) { return new Person({ name: label }) }
Expand Down
34 changes: 29 additions & 5 deletions src/coalesce-vue-vuetify3/src/components/input/c-select.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<v-input
ref="rootRef"
class="c-select"
:class="{
'c-select--is-menu-active': menuOpen,
Expand Down Expand Up @@ -99,6 +100,7 @@
location="bottom"
>
<v-sheet
ref="menuContentRef"
@keydown.capture.down.stop.prevent="
pendingSelection = Math.min(
listItems.length - 1,
Expand All @@ -110,6 +112,7 @@
"
@keydown.capture.enter.stop.prevent="confirmPendingSelection"
@keydown.capture.tab.stop.prevent="confirmPendingSelection"
@blur.capture="onMenuContentBlur"
>
<v-text-field
v-model="search"
Expand Down Expand Up @@ -145,7 +148,6 @@
<v-list
class="py-0"
max-height="302"
ref="listRef"
density="compact"
:aria-multiselectable="effectiveMultiple"
role="listbox"
Expand Down Expand Up @@ -508,7 +510,7 @@ const props = withDefaults(
} & /* @vue-ignore */ InheritedProps
>(),
{
openOnClear: true,
openOnClear: false,
canDeselect: true,
clearable: undefined,
multiple: undefined,
Expand All @@ -531,8 +533,9 @@ const passthroughSlots = computed(() => {
return ret;
});
const rootRef = ref<ComponentPublicInstance>();
const mainInputRef = ref<HTMLInputElement>();
const listRef = ref<ComponentPublicInstance>();
const menuContentRef = ref<ComponentPublicInstance>();
const searchRef = ref<ComponentPublicInstance>();
const fieldAttrs = computed(() =>
Expand Down Expand Up @@ -945,10 +948,25 @@ function onInput(value: SelectedModelTypeSingle | null, dontFocus = false) {
if (!dontFocus && !effectiveMultiple.value) {
if (!value) {
openMenu();
return;
} else {
closeMenu(true);
return;
}
}
if (value == null && props.openOnClear) {
openMenu();
}
}
function onMenuContentBlur(event: FocusEvent) {
if (
!menuContentRef.value?.$el.contains(event.relatedTarget as HTMLElement) &&
!rootRef.value?.$el.contains(event.target as HTMLElement)
) {
closeMenu(true);
}
}
/** When a key is pressed on the top level input */
Expand Down Expand Up @@ -1018,7 +1036,7 @@ async function createItem() {
}
async function openMenu(select?: boolean) {
if (!isInteractive.value) return;
if (!isInteractive.value || forceClosed) return;
if (select == undefined) {
// Select the whole search input if it hasn't changed recently.
Expand Down Expand Up @@ -1061,7 +1079,13 @@ async function openMenu(select?: boolean) {
}
}
let forceClosed = false;
function closeMenu(force = false) {
if (force) {
forceClosed = true;
setTimeout(() => (forceClosed = false), 300);
}
if (!menuOpen.value) return;
if (menuOpenForced.value && !force) return;
Expand Down Expand Up @@ -1173,7 +1197,7 @@ watch(
watch(pendingSelection, async () => {
await nextTick();
await nextTick();
var listDiv = listRef.value?.$el as HTMLElement;
var listDiv = menuContentRef.value?.$el as HTMLElement;
var selectedItem = listDiv?.querySelector(".pending-selection");
selectedItem?.scrollIntoView?.({
behavior: "auto",
Expand Down

0 comments on commit 8bf9ffe

Please sign in to comment.