Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: various bug fixes #456

Merged
merged 11 commits into from
Aug 26, 2024
4 changes: 2 additions & 2 deletions apps/docs/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ export default defineConfig({
},
prerender: {
routes: ["/docs/core/overview/introduction"],
crawlLinks: true
}
crawlLinks: true,
},
},

extensions: ["mdx", "md"],
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"files": {
"ignore": ["./tsconfig.json", "*/netlify/*"]
"ignore": ["./tsconfig.json", "*/netlify/*", "**/package.json"]
},
"vcs": {
"enabled": true,
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 @@ -596,9 +596,8 @@ export function ComboboxBase<
focusStrategy: FocusStrategy | boolean,
triggerMode?: ComboboxTriggerMode,
) => {

// If set to only open manually, ignore other triggers
if (local.triggerMode === 'manual' && triggerMode !== 'manual') {
if (local.triggerMode === "manual" && triggerMode !== "manual") {
return;
}

Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/combobox/combobox-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,14 @@ export function ComboboxContent<T extends ValidComponent = "div">(
"onFocusOutside",
]);

const close = () => {
const dismiss = () => {
context.resetInputValue(
context.listState().selectionManager().selectedKeys(),
);
context.close();
setTimeout(() => {
context.close();
});
};

const onFocusOutside = (e: FocusOutsideEvent) => {
Expand Down Expand Up @@ -165,7 +168,7 @@ export function ComboboxContent<T extends ValidComponent = "div">(
local.style,
)}
onFocusOutside={onFocusOutside}
onDismiss={close}
onDismiss={dismiss}
{...context.dataset()}
{...others}
/>
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/combobox/combobox-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface ComboboxInputCommonProps<
ref: T | ((el: T) => void);
onInput: JSX.EventHandlerUnion<T, InputEvent>;
onKeyDown: JSX.EventHandlerUnion<T, KeyboardEvent>;
onClick: JSX.EventHandlerUnion<T, MouseEvent>;
onFocus: JSX.EventHandlerUnion<T, FocusEvent>;
onBlur: JSX.EventHandlerUnion<T, FocusEvent>;
onTouchEnd: JSX.EventHandlerUnion<T, TouchEvent>;
Expand Down Expand Up @@ -93,6 +94,7 @@ export function ComboboxInput<T extends ValidComponent = "input">(
[
"ref",
"disabled",
"onClick",
"onInput",
"onKeyDown",
"onFocus",
Expand All @@ -113,6 +115,14 @@ export function ComboboxInput<T extends ValidComponent = "input">(

const { fieldProps } = createFormControlField(formControlFieldProps);

const onClick: JSX.EventHandlerUnion<HTMLInputElement, MouseEvent> = (e) => {
callHandler(e, local.onClick);

if (context.triggerMode() === "focus" && !context.isOpen()) {
context.open(false, "focus");
}
};

const onInput: JSX.EventHandlerUnion<HTMLInputElement, InputEvent> = (e) => {
callHandler(e, local.onInput);

Expand Down Expand Up @@ -315,6 +325,7 @@ export function ComboboxInput<T extends ValidComponent = "input">(
aria-required={formControlContext.isRequired() || undefined}
aria-disabled={formControlContext.isDisabled() || undefined}
aria-readonly={formControlContext.isReadOnly() || undefined}
onClick={onClick}
onInput={onInput}
onKeyDown={onKeyDown}
onFocus={onFocus}
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/combobox/combobox-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {

export interface ComboboxSingleSelectionOptions<T> {
/** The controlled value of the combobox. */
value?: T;
value?: T | null;

/**
* The value of the combobox when initially rendered.
Expand All @@ -24,7 +24,7 @@ export interface ComboboxSingleSelectionOptions<T> {
defaultValue?: T;

/** Event handler called when the value changes. */
onChange?: (value: T) => void;
onChange?: (value: T | null) => void;

/** Whether the combobox allow multiple selection. */
multiple?: false;
Expand Down Expand Up @@ -100,10 +100,10 @@ export function ComboboxRoot<

const onChange = (value: Option[]) => {
if (local.multiple) {
local.onChange?.(value as any);
local.onChange?.((value ?? []) as any);
} else {
// use `null` as "no value" because `undefined` mean the component is "uncontrolled".
local.onChange?.((value[0] ?? null) as any);
local.onChange?.((value[0] ?? null) as any); // TODO: maybe return undefined? breaking change!
}
};

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/menu/menu-content-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ export function MenuContentBase<T extends ValidComponent = "div">(

createEffect(() => onCleanup(context.registerContentId(local.id!)));

onCleanup(() => context.setContentRef(undefined));

const commonAttributes: Omit<MenuContentBaseRenderProps, keyof MenuDataSet> =
{
ref: mergeRefs((el) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/menu/menu-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface MenuContextValue {
triggerId: Accessor<string | undefined>;
contentId: Accessor<string | undefined>;
setTriggerRef: (el: HTMLElement) => void;
setContentRef: (el: HTMLElement) => void;
setContentRef: (el: HTMLElement | undefined) => void;
open: (focusStrategy: FocusStrategy | boolean) => void;
close: (recursively?: boolean) => void;
toggle: (focusStrategy: FocusStrategy | boolean) => void;
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/navigation-menu/navigation-menu-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ export function NavigationMenuRoot<T extends ValidComponent = "ul">(
element: () => viewportRef() ?? null,
});

createEffect(() => {
if (!viewportPresent()) {
context.setPreviousMenu(undefined);
}
});

const context: NavigationMenuContextValue = {
dataset,
delayDuration: () => local.delayDuration!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ export function NavigationMenuTrigger<T extends ValidComponent = "button">(
if (context.dataset()["data-expanded"] === "") return;

timeoutId = window.setTimeout(() => {
context.setAutoFocusMenu(true);
menuContext?.triggerRef()?.focus();
setTimeout(() => {
context.setAutoFocusMenu(true);
});
}, context.delayDuration());
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,12 @@ export function NavigationMenuViewport<T extends ValidComponent = "li">(
);

const height = createMemo((prev) => {
if (ref() === undefined || !context.viewportPresent()) return undefined;
if (size.height() === 0) return prev;
return size.height();
});
const width = createMemo((prev) => {
if (ref() === undefined || !context.viewportPresent()) return undefined;
if (size.width() === 0) return prev;
return size.width();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/number-field/number-field-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export function NumberFieldInput<T extends ValidComponent = "input">(
>
as={local.as || "input"}
value={
Number.isNaN(context.rawValue())
Number.isNaN(context.rawValue()) || context.value() === undefined
? ""
: context.formatNumber(context.rawValue())
}
Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/number-field/number-field-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ export function NumberFieldRoot<T extends ValidComponent = "div">(
return new NumberFormatter(locale(), local.formatOptions);
});

const formatNumber = (number: number) =>
local.format ? numberFormatter().format(number) : number.toString();

const parseRawValue = (value: string | number | undefined) =>
local.format && typeof value !== "number"
? numberParser().parse(value ?? "")
Expand All @@ -203,14 +206,12 @@ export function NumberFieldRoot<T extends ValidComponent = "div">(
value: () => local.value,
defaultValue: () => local.defaultValue ?? local.rawValue,
onChange: (value) => {
local.onChange?.(
typeof value === "number" ? numberFormatter().format(value) : value,
);
local.onChange?.(typeof value === "number" ? formatNumber(value) : value);
local.onRawValueChange?.(parseRawValue(value));
},
});

local.onRawValueChange?.(parseRawValue(value()));
if (value() !== undefined) local.onRawValueChange?.(parseRawValue(value()));

function isAllowedInput(char: string): boolean {
if (local.allowedInput !== undefined) return local.allowedInput.test(char);
Expand Down Expand Up @@ -267,7 +268,7 @@ export function NumberFieldRoot<T extends ValidComponent = "div">(
setValue,
rawValue: () => parseRawValue(value()),
generateId: createGenerateId(() => access(formControlProps.id)!),
formatNumber: (number: number) => numberFormatter().format(number),
formatNumber,
format: () => {
if (!local.format) return;
let rawValue = context.rawValue();
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/select/select-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {

export interface SelectSingleSelectionOptions<T> {
/** The controlled value of the select. */
value?: T;
value?: T | null;

/**
* The value of the select when initially rendered.
Expand All @@ -24,7 +24,7 @@ export interface SelectSingleSelectionOptions<T> {
defaultValue?: T;

/** Event handler called when the value changes. */
onChange?: (value: T) => void;
onChange?: (value: T | null) => void;

/** Whether the select allow multiple selection. */
multiple?: false;
Expand Down Expand Up @@ -101,10 +101,10 @@ export function SelectRoot<

const onChange = (value: Option[]) => {
if (local.multiple) {
local.onChange?.(value as any);
local.onChange?.((value ?? []) as any);
} else {
// use `null` as "no value" because `undefined` mean the component is "uncontrolled".
local.onChange?.((value[0] ?? null) as any);
local.onChange?.((value[0] ?? null) as any); // TODO: maybe return undefined? breaking change!
}
};

Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/skeleton/skeleton-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export interface SkeletonRootCommonProps<T extends HTMLElement = HTMLElement> {

export interface SkeletonRootRenderProps extends SkeletonRootCommonProps {
role: "group";
"data-animate": boolean;
"data-visible": boolean;
"data-animate": boolean | undefined;
"data-visible": boolean | undefined;
}

export type SkeletonRootProps<
Expand Down Expand Up @@ -82,8 +82,8 @@ export function Skeleton<T extends ValidComponent = "div">(
<Polymorphic<SkeletonRootRenderProps>
as="div"
role="group"
data-animate={local.animate}
data-visible={local.visible}
data-animate={local.animate || undefined}
data-visible={local.visible || undefined}
style={combineStyle(
{
"border-radius": local.circle
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/text-field/text-field-root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
OverrideComponentProps,
type ValidationState,
access,
createGenerateId,
Expand Down Expand Up @@ -108,8 +107,12 @@ export function TextFieldRoot<T extends ValidComponent = "div">(
FORM_CONTROL_PROP_NAMES,
);

// Disable reactivity to only track controllability on first run
// Our current implementation breaks with undefined (stops tracking controlled value)
const initialValue = local.value;

const [value, setValue] = createControllableSignal({
value: () => local.value,
value: () => (initialValue === undefined ? undefined : local.value ?? ""),
defaultValue: () => local.defaultValue,
onChange: (value) => local.onChange?.(value),
});
Expand Down
Loading