Skip to content

Commit

Permalink
fix: onChange$ only executes on client & simpler disabled state
Browse files Browse the repository at this point in the history
  • Loading branch information
thejackshelton committed Sep 21, 2024
1 parent 160886d commit d244a18
Showing 1 changed file with 14 additions and 41 deletions.
55 changes: 14 additions & 41 deletions packages/kit-headless/src/components/combobox/combobox-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ export type HComboboxRootImplProps<M extends boolean = boolean> = Omit<
export const HComboboxRootImpl = component$<
HComboboxRootImplProps<boolean> & InternalComboboxProps
>((props: HComboboxRootImplProps<boolean> & InternalComboboxProps) => {
const isListboxOpenSig = useSignal(false);
const {
onInput$,
onChange$,
onOpenChange$,
'bind:value': givenValueSig,
'bind:open': givenOpenSig,
_valuePropIndex: givenValuePropIndex,
_value,
loop: givenLoop,
Expand All @@ -137,11 +137,16 @@ export const HComboboxRootImpl = component$<
removeOnBackspace = false,
name,
required,
disabled,
...rest
} = props;

// source of truth
const isListboxOpenSig = useBoundSignal(givenOpenSig, false);
const selectedValuesSig = useBoundSignal(
givenValueSig,
multiple ? (_value ? [_value] : []) : _value || '',
);

const itemsMapSig = useComputed$(() => {
return props._itemsMap ?? new Map();
});
Expand All @@ -156,14 +161,9 @@ export const HComboboxRootImpl = component$<
const localId = useId();
/** We use selected values to preserve the item state when the consumer filters the items. */
const selectedValueSetSig = useSignal<Set<string>>(new Set(_value ? [_value] : []));
const selectedValuesSig = useBoundSignal(
givenValueSig,
multiple ? (_value ? [_value] : []) : _value || '',
);

const disabledIndexSetSig = useSignal<Set<number>>(new Set());
const isMouseOverPopupSig = useSignal<boolean>(false);
const isDisabledSig = useSignal<boolean>(disabled ?? false);
const highlightedIndexSig = useSignal<number | null>(givenValuePropIndex ?? null);
const initialLoadSig = useSignal<boolean>(true);
const currDisplayValueSig = useSignal<string | string[]>();
Expand All @@ -174,6 +174,7 @@ export const HComboboxRootImpl = component$<
};
const inputValueSig = useSignal<string>(inputRef.value?.value ?? '');
const isInvalidSig = useSignal<boolean>(hasErrorComp ?? false);
const isDisabledSig = useComputed$(() => props.disabled ?? false);

// check any initial disabled items before the computed read below
useTask$(() => {
Expand Down Expand Up @@ -238,60 +239,32 @@ export const HComboboxRootImpl = component$<

useContextProvider(comboboxContextId, context);

useTask$(function reactiveUserOpen({ track }) {
const bindOpenSig = props['bind:open'];
if (!bindOpenSig) return;
track(() => bindOpenSig.value);

isListboxOpenSig.value = bindOpenSig.value ?? isListboxOpenSig.value;
});

useTask$(function onOpenChangeTask({ track }) {
const bindOpenSig = props['bind:open'];
useTask$(function handleOpenChange({ track }) {
track(() => isListboxOpenSig.value);

if (!initialLoadSig.value) {
onOpenChange$?.(isListboxOpenSig.value);
}

// sync the user's given signal for the open state
if (bindOpenSig && bindOpenSig.value !== isListboxOpenSig.value) {
bindOpenSig.value = isListboxOpenSig.value;
}
});

useTask$(function onInputTask({ track }) {
useTask$(function handleInput({ track }) {
track(() => context.inputValueSig.value);

if (!initialLoadSig.value) {
onInput$?.(context.inputValueSig.value);
}
});

useTask$(async function updateConsumerProps({ track }) {
useTask$(async function handleChange({ track }) {
track(() => selectedValuesSig.value);

const values = selectedValuesSig.value;
const displayValues = [];

for (const value of values) {
for (const item of context.itemsMapSig.value.values()) {
if (item.value === value) {
displayValues.push(item.displayValue);
break;
}
}
}
if (!onChange$) return;

if (onChange$ && selectedValuesSig.value.length > 0) {
await onChange$(values);
if (!initialLoadSig.value && selectedValuesSig.value.length > 0) {
await onChange$(selectedValuesSig.value);
}
});

useTask$(({ track }) => {
isDisabledSig.value = track(() => disabled ?? false);
});

useTask$(() => {
initialLoadSig.value = false;
});
Expand Down

0 comments on commit d244a18

Please sign in to comment.