Skip to content

Commit

Permalink
Merge branch 'main' into chore/deps
Browse files Browse the repository at this point in the history
  • Loading branch information
jer3m01 authored Jan 11, 2024
2 parents bce07a2 + 347bc66 commit c41ecd6
Show file tree
Hide file tree
Showing 13 changed files with 78 additions and 41 deletions.
46 changes: 33 additions & 13 deletions packages/core/src/checkbox/checkbox-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
OverrideComponentProps,
visuallyHiddenStyles,
} from "@kobalte/utils";
import { createEffect, JSX, on, splitProps } from "solid-js";
import { createEffect, createSignal, JSX, on, splitProps } from "solid-js";

import {
createFormControlField,
Expand Down Expand Up @@ -54,23 +54,28 @@ export function CheckboxInput(props: CheckboxInputProps) {

const { fieldProps } = createFormControlField(formControlFieldProps);

const [isInternalChangeEvent, setIsInternalChangeEvent] = createSignal(false);

const onChange: JSX.ChangeEventHandlerUnion<HTMLInputElement, Event> = e => {
callHandler(e, local.onChange);

e.stopPropagation();

const target = e.target as HTMLInputElement;

context.setIsChecked(target.checked);

// Unlike in React, inputs `checked` state can be out of sync with our toggle state.
// for example a readonly `<input type="checkbox" />` is always "checkable".
//
// Also, even if an input is controlled (ex: `<input type="checkbox" checked={isChecked} />`,
// clicking on the input will change its internal `checked` state.
//
// To prevent this, we need to force the input `checked` state to be in sync with the toggle state.
target.checked = context.checked();
if (!isInternalChangeEvent()) {
const target = e.target as HTMLInputElement;

context.setIsChecked(target.checked);

// Unlike in React, inputs `checked` state can be out of sync with our toggle state.
// for example a readonly `<input type="checkbox" />` is always "checkable".
//
// Also, even if an input is controlled (ex: `<input type="checkbox" checked={isChecked} />`,
// clicking on the input will change its internal `checked` state.
//
// To prevent this, we need to force the input `checked` state to be in sync with the toggle state.
target.checked = context.checked();
}
setIsInternalChangeEvent(false);
};

const onFocus: JSX.FocusEventHandlerUnion<any, FocusEvent> = e => {
Expand All @@ -83,6 +88,21 @@ export function CheckboxInput(props: CheckboxInputProps) {
context.setIsFocused(false);
};

createEffect(
on(
[() => context.checked(), () => context.value()],
() => {
setIsInternalChangeEvent(true);

ref?.dispatchEvent(new Event("input", { bubbles: true, cancelable: true }));
ref?.dispatchEvent(new Event("change", { bubbles: true, cancelable: true }));
},
{
defer: true,
},
),
);

// indeterminate is a property, but it can only be set via javascript
// https://css-tricks.com/indeterminate-checkboxes/
// Unlike in React, inputs `indeterminate` state can be out of sync with our.
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/combobox/combobox-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ export function ComboboxBase<Option, OptGroup = never>(props: ComboboxBaseProps<
gutter: 8,
sameWidth: true,
modal: false,
preventScroll: false,
defaultFilter: "contains",
triggerMode: "input",
translations: COMBOBOX_INTL_TRANSLATIONS,
Expand Down Expand Up @@ -747,7 +746,7 @@ export function ComboboxBase<Option, OptGroup = never>(props: ComboboxBaseProps<
isMultiple: () => access(local.selectionMode) === "multiple",
isVirtualized: () => local.virtualized ?? false,
isModal: () => local.modal ?? false,
preventScroll: () => local.preventScroll ?? false,
preventScroll: () => local.preventScroll ?? context.isModal(),
allowsEmptyCollection: () => local.allowsEmptyCollection ?? false,
shouldFocusWrap: () => local.shouldFocusWrap ?? false,
removeOnBackspace: () => local.removeOnBackspace ?? true,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/combobox/combobox-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function ComboboxContent(props: ComboboxContentProps) {

createPreventScroll({
ownerRef: () => ref,
isDisabled: () => !(context.isOpen() && (context.isModal() || context.preventScroll())),
isDisabled: () => !(context.isOpen() && context.preventScroll()),
});

createFocusScope(
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/context-menu/context-menu-trigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export function ContextMenuTrigger(props: ContextMenuTriggerProps) {
clearLongPressTimeout();

e.preventDefault();
e.stopPropagation();

context.setAnchorRect({ x: e.clientX, y: e.clientY });

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/dialog/dialog-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export function DialogContent(props: DialogContentProps) {

createPreventScroll({
ownerRef: () => ref,
isDisabled: () => !(context.isOpen() && (context.modal() || context.preventScroll())),
isDisabled: () => !(context.isOpen() && context.preventScroll()),
});

createFocusScope(
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/dialog/dialog-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export function DialogRoot(props: DialogRootProps) {
{
id: defaultId,
modal: true,
preventScroll: false,
translations: DIALOG_INTL_TRANSLATIONS,
},
props,
Expand All @@ -87,7 +86,7 @@ export function DialogRoot(props: DialogRootProps) {
translations: () => props.translations ?? DIALOG_INTL_TRANSLATIONS,
isOpen: disclosureState.isOpen,
modal: () => props.modal ?? true,
preventScroll: () => props.preventScroll ?? false,
preventScroll: () => props.preventScroll ?? context.modal(),
contentId,
titleId,
descriptionId,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/menu/menu-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function MenuContent(props: MenuContentProps) {

createPreventScroll({
ownerRef: () => ref,
isDisabled: () => !(context.isOpen() && (rootContext.isModal() || rootContext.preventScroll())),
isDisabled: () => !(context.isOpen() && rootContext.preventScroll()),
});

return <MenuContentBase ref={mergeRefs(el => (ref = el), local.ref)} {...others} />;
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/menu/menu-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export function MenuRoot(props: MenuRootProps) {
{
id: defaultId,
modal: true,
preventScroll: false,
},
props,
);
Expand All @@ -69,7 +68,7 @@ export function MenuRoot(props: MenuRootProps) {

const context: MenuRootContextValue = {
isModal: () => local.modal ?? true,
preventScroll: () => local.preventScroll ?? false,
preventScroll: () => local.preventScroll ?? context.isModal(),
forceMount: () => local.forceMount ?? false,
generateId: createGenerateId(() => local.id!),
};
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/popover/popover-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export function PopoverContent(props: PopoverContentProps) {

createPreventScroll({
ownerRef: () => ref,
isDisabled: () => !(context.isOpen() && (context.isModal() || context.preventScroll())),
isDisabled: () => !(context.isOpen() && context.preventScroll()),
});

createFocusScope(
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/popover/popover-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ export function PopoverRoot(props: PopoverRootProps) {
{
id: defaultId,
modal: false,
preventScroll: false,
translations: POPOVER_INTL_TRANSLATIONS,
},
props,
Expand Down Expand Up @@ -131,7 +130,7 @@ export function PopoverRoot(props: PopoverRootProps) {
dataset,
isOpen: disclosureState.isOpen,
isModal: () => local.modal ?? false,
preventScroll: () => local.preventScroll ?? false,
preventScroll: () => local.preventScroll ?? context.isModal(),
contentPresence,
triggerRef,
contentId,
Expand Down
47 changes: 34 additions & 13 deletions packages/core/src/radio-group/radio-group-item-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
OverrideComponentProps,
visuallyHiddenStyles,
} from "@kobalte/utils";
import { createEffect, JSX, onCleanup, splitProps } from "solid-js";
import { createEffect, createSignal, JSX, on, onCleanup, splitProps } from "solid-js";

import { useFormControlContext } from "../form-control";
import { useRadioGroupContext } from "./radio-group-context";
Expand Down Expand Up @@ -73,23 +73,28 @@ export function RadioGroupItemInput(props: RadioGroupItemInputProps) {
);
};

const [isInternalChangeEvent, setIsInternalChangeEvent] = createSignal(false);

const onChange: JSX.ChangeEventHandlerUnion<HTMLInputElement, Event> = e => {
callHandler(e, local.onChange);

e.stopPropagation();

radioGroupContext.setSelectedValue(radioContext.value());

const target = e.target as HTMLInputElement;

// Unlike in React, inputs `checked` state can be out of sync with our state.
// for example a readonly `<input type="radio" />` is always "checkable".
//
// Also, even if an input is controlled (ex: `<input type="radio" checked={isChecked} />`,
// clicking on the input will change its internal `checked` state.
//
// To prevent this, we need to force the input `checked` state to be in sync with our state.
target.checked = radioContext.isSelected();
if (!isInternalChangeEvent()) {
radioGroupContext.setSelectedValue(radioContext.value());

const target = e.target as HTMLInputElement;

// Unlike in React, inputs `checked` state can be out of sync with our state.
// for example a readonly `<input type="radio" />` is always "checkable".
//
// Also, even if an input is controlled (ex: `<input type="radio" checked={isChecked} />`,
// clicking on the input will change its internal `checked` state.
//
// To prevent this, we need to force the input `checked` state to be in sync with our state.
target.checked = radioContext.isSelected();
}
setIsInternalChangeEvent(false);
};

const onFocus: JSX.FocusEventHandlerUnion<any, FocusEvent> = e => {
Expand All @@ -102,6 +107,22 @@ export function RadioGroupItemInput(props: RadioGroupItemInputProps) {
radioContext.setIsFocused(false);
};

createEffect(
on(
[() => radioContext.isSelected(), () => radioContext.value()],
c => {
if (!c[0] && c[1] === radioContext.value()) return;
setIsInternalChangeEvent(true);

const ref = radioContext.inputRef();
ref?.dispatchEvent(new Event("input", { bubbles: true, cancelable: true }));
ref?.dispatchEvent(new Event("change", { bubbles: true, cancelable: true }));
},
{
defer: true,
},
),
);
createEffect(() => onCleanup(radioContext.registerInput(others.id!)));

return (
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/select/select-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ export function SelectBase<Option, OptGroup = never>(props: SelectBaseProps<Opti
gutter: 8,
sameWidth: true,
modal: false,
preventScroll: false,
},
props,
);
Expand Down Expand Up @@ -462,7 +461,7 @@ export function SelectBase<Option, OptGroup = never>(props: SelectBaseProps<Opti
isMultiple: () => access(local.selectionMode) === "multiple",
isVirtualized: () => local.virtualized ?? false,
isModal: () => local.modal ?? false,
preventScroll: () => local.preventScroll ?? false,
preventScroll: () => local.preventScroll ?? context.isModal(),
disallowTypeAhead: () => local.disallowTypeAhead ?? false,
shouldFocusWrap: () => local.shouldFocusWrap ?? false,
selectedOptions,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/select/select-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export function SelectContent(props: SelectContentProps) {

createPreventScroll({
ownerRef: () => ref,
isDisabled: () => !(context.isOpen() && (context.isModal() || context.preventScroll())),
isDisabled: () => !(context.isOpen() && context.preventScroll()),
});

createFocusScope(
Expand Down

0 comments on commit c41ecd6

Please sign in to comment.