Skip to content

Commit

Permalink
big cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte committed Apr 25, 2024
1 parent 3835de2 commit a68c521
Show file tree
Hide file tree
Showing 22 changed files with 170 additions and 230 deletions.
121 changes: 12 additions & 109 deletions packages/bits-ui/src/lib/bits/dialog/types.ts
Original file line number Diff line number Diff line change
@@ -1,113 +1,16 @@
import type { HTMLButtonAttributes } from "svelte/elements";
import type { CreateDialogProps as MeltDialogProps } from "@melt-ui/svelte";
import type {
DOMElement,
Expand,
HTMLDivAttributes,
HTMLHeadingAttributes,
OmitOpen,
OnChangeFn,
SvelteEvent,
Transition,
TransitionProps,
} from "$lib/internal/index.js";
import type { CustomEventHandler } from "$lib/index.js";
import type { Snippet } from "svelte";
import type { OnChangeFn, WithAsChild } from "$lib/internal/types.js";

import type { FocusProp } from "$lib/shared/index.js";
export type DialogRootPropsWithoutHTML = {
/**
* The open state of the dialog.
*/
open?: boolean;

export type DialogPropsWithoutHTML = Expand<
OmitOpen<
Omit<MeltDialogProps, "role" | "ids" | "forceVisible" | "openFocus" | "closeFocus">
> & {
/**
* The open state of the dialog.
* You can bind this to a boolean value to programmatically control the open state.
*
* @defaultValue false
*/
open?: MeltDialogProps["defaultOpen"] & {};
/**
* A callback that is called when the popover's open state changes.
*/
onOpenChange?: OnChangeFn<boolean>;

/**
* A callback function called when the open state changes.
*/
onOpenChange?: OnChangeFn<boolean>;

/**
* Override the default autofocus behavior of the dialog when it opens
*/
openFocus?: FocusProp;

/**
* Override the default autofocus behavior of the dialog after close
*/
closeFocus?: FocusProp;
}
>;

export type DialogTriggerPropsWithoutHTML = DOMElement<HTMLButtonElement>;

export type DialogClosePropsWithoutHTML = DialogTriggerPropsWithoutHTML;

export type DialogContentPropsWithoutHTML<
T extends Transition = Transition,
In extends Transition = Transition,
Out extends Transition = Transition,
> = Expand<TransitionProps<T, In, Out> & DOMElement>;

export type DialogDescriptionPropsWithoutHTML = DOMElement;

export type DialogOverlayPropsWithoutHTML<
T extends Transition = Transition,
In extends Transition = Transition,
Out extends Transition = Transition,
> = Expand<TransitionProps<T, In, Out> & DOMElement>;

export type DialogPortalPropsWithoutHTML = DOMElement;

export type DialogTitlePropsWithoutHTML = Expand<
{
level?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
} & DOMElement<HTMLHeadingElement>
>;

export type DialogProps = DialogPropsWithoutHTML;

export type DialogTriggerProps = DialogTriggerPropsWithoutHTML & HTMLButtonAttributes;
export type DialogCloseProps = DialogTriggerProps;

export type DialogContentProps<
T extends Transition = Transition,
In extends Transition = Transition,
Out extends Transition = Transition,
> = DialogContentPropsWithoutHTML<T, In, Out> & HTMLDivAttributes;

export type DialogDescriptionProps = DialogDescriptionPropsWithoutHTML & HTMLDivAttributes;

export type DialogOverlayProps<
T extends Transition = Transition,
In extends Transition = Transition,
Out extends Transition = Transition,
> = DialogOverlayPropsWithoutHTML<T, In, Out> & HTMLDivAttributes;

export type DialogPortalProps = DialogPortalPropsWithoutHTML & HTMLDivAttributes;
export type DialogTitleProps = DialogTitlePropsWithoutHTML & HTMLHeadingAttributes;

export type DialogOverlayEvents<T extends Element = HTMLElement> = {
mouseup: SvelteEvent<MouseEvent, T>;
};

export type DialogContentEvents<T extends Element = HTMLElement> = {
pointerdown: SvelteEvent<PointerEvent, T>;
pointerup: SvelteEvent<PointerEvent, T>;
pointermove: SvelteEvent<PointerEvent, T>;
touchend: SvelteEvent<TouchEvent, T>;
touchstart: SvelteEvent<TouchEvent, T>;
touchcancel: SvelteEvent<TouchEvent, T>;
touchmove: SvelteEvent<TouchEvent, T>;
};

export type DialogTriggerEvents<T extends Element = HTMLButtonElement> = {
click: CustomEventHandler<MouseEvent, T>;
keydown: CustomEventHandler<KeyboardEvent, T>;
children?: Snippet;
};
export type DialogCloseEvents = DialogTriggerEvents;
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
id = useId(),
forceMount = false,
onDestroyAutoFocus = noop,
onEscapeKeydown = noop,
onInteractOutside = noop,
loop = true,
...restProps
}: ContentProps = $props();
Expand All @@ -24,16 +27,24 @@
{...restProps}
present={state.root.open.value || forceMount}
{id}
onInteractOutside={state.root.close}
onEscape={state.root.close}
onInteractOutside={(e) => {
onInteractOutside(e);
if (e.defaultPrevented) return;
state.root.close();
}}
onEscapeKeydown={(e) => {
// TODO: users should be able to cancel this
onEscapeKeydown(e);
state.root.close();
}}
onDestroyAutoFocus={(e) => {
onDestroyAutoFocus(e);
if (e.defaultPrevented) return;
e.preventDefault();
state.root.triggerNode?.value?.focus();
}}
trapped
loop
{loop}
>
{#snippet popper({ props })}
{@const mergedProps = mergeProps(restProps, state.props, props)}
Expand Down
20 changes: 3 additions & 17 deletions packages/bits-ui/src/lib/bits/popover/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Snippet } from "svelte";
import type { ArrowProps, ArrowPropsWithoutHTML } from "../utilities/arrow/types.js";
import type { PopperLayerProps } from "../utilities/popper-layer/types.js";
import type {
EventCallback,
OnChangeFn,
Expand All @@ -8,7 +9,6 @@ import type {
WithAsChild,
} from "$lib/internal/index.js";
import type { CustomEventHandler } from "$lib/index.js";
import type { FloatingLayer } from "$lib/bits/utilities/floating-layer/index.js";

export type PopoverRootPropsWithoutHTML = {
/**
Expand All @@ -27,23 +27,9 @@ export type PopoverRootPropsWithoutHTML = {
children?: Snippet;
};

export type PopoverRootProps = PopoverRootPropsWithoutHTML & PrimitiveDivAttributes;
export type PopoverRootProps = PopoverRootPropsWithoutHTML;

export type PopoverContentPropsWithoutHTML = WithAsChild<
Partial<Omit<FloatingLayer.ContentProps, "content">> & {
forceMount?: boolean;
} & {
onMountAutoFocus?: EventCallback;
onDestroyAutoFocus?: EventCallback;
} & {
/**
* Whether to prevent scrolling the body when the popover is open or not.
*
* @defaultValue true
*/
preventScroll?: boolean;
}
>;
export type PopoverContentPropsWithoutHTML = WithAsChild<PopperLayerProps>;

export type PopoverContentProps = PopoverContentPropsWithoutHTML & PrimitiveDivAttributes;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<script lang="ts">
import type { DismissableLayerProps } from "./types.js";
import type { DismissableLayerImplProps } from "./types.js";
import { useDismissableLayer } from "./useDismissableLayer.svelte.js";
import { noop, readonlyBox } from "$lib/internal/index.js";
let {
behaviorType = "close",
interactOutsideBehavior = "close",
onInteractOutside = noop,
onInteractOutsideStart = noop,
id,
children,
present,
}: DismissableLayerProps = $props();
}: DismissableLayerImplProps = $props();
useDismissableLayer({
id: readonlyBox(() => id),
behaviorType: readonlyBox(() => behaviorType),
interactOutsideBehavior: readonlyBox(() => interactOutsideBehavior),
onInteractOutside: readonlyBox(() => onInteractOutside),
onInteractOutsideStart: readonlyBox(() => onInteractOutsideStart),
present: readonlyBox(() => present),
Expand Down
20 changes: 11 additions & 9 deletions packages/bits-ui/src/lib/bits/utilities/dismissable-layer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ export type InteractOutsideBehaviorType =
| "ignore";

export type DismissableLayerProps = {
/**
* DOM ID of the node.
*/
id: string;

children?: Snippet;

/**
* Callback fired when an outside interaction event completes,
* which is either a `pointerup`, `mouseup`, or `touchend`
Expand Down Expand Up @@ -44,14 +37,23 @@ export type DismissableLayerProps = {
*
* @defaultValue `close`
*/
behaviorType?: InteractOutsideBehaviorType;
interactOutsideBehavior?: InteractOutsideBehaviorType;
};

export type DismissableLayerImplProps = {
/**
* Whether the layer is active. Currently, we determine this with the
* `presence` returned from the `presence` layer.
*/
present: boolean;
};

/**
* ID of the layer.
*/
id: string;

children?: Snippet;
} & DismissableLayerProps;

export type InteractOutsideInterceptEventType =
| "pointerdown"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { untrack } from "svelte";
import type {
DismissableLayerImplProps,
DismissableLayerProps,
InteractOutsideBehaviorType,
InteractOutsideEvent,
Expand Down Expand Up @@ -36,7 +37,7 @@ const interactOutsideEndEvents = [
] satisfies InteractOutsideInterceptEventType[];

type DismissableLayerStateProps = ReadonlyBoxedValues<
Required<Omit<DismissableLayerProps, "children">>
Required<Omit<DismissableLayerImplProps, "children">>
>;

export class DismissableLayerState {
Expand All @@ -60,7 +61,7 @@ export class DismissableLayerState {

constructor(props: DismissableLayerStateProps) {
this.node = useNodeById(props.id);
this.#behaviorType = props.behaviorType;
this.#behaviorType = props.interactOutsideBehavior;
this.#interactOutsideStartProp = props.onInteractOutsideStart;
this.#interactOutsideProp = props.onInteractOutside;
this.#present = props.present;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
<script lang="ts">
import type { EscapeLayerProps } from "./types.js";
import type { EscapeLayerImplProps } from "./types.js";
import { useEscapeLayer } from "./useEscapeLayer.svelte.js";
import { noop, readonlyBox } from "$lib/internal/index.js";
let { behaviorType = "close", onEscape = noop, children, present }: EscapeLayerProps = $props();
let {
behaviorType = "close",
onEscapeKeydown = noop,
children,
present,
}: EscapeLayerImplProps = $props();
useEscapeLayer({
behaviorType: readonlyBox(() => behaviorType),
onEscape: readonlyBox(() => onEscape),
onEscapeKeydown: readonlyBox(() => onEscapeKeydown),
present: readonlyBox(() => present),
});
</script>
Expand Down
11 changes: 7 additions & 4 deletions packages/bits-ui/src/lib/bits/utilities/escape-layer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ export type EscapeBehaviorType =
| "ignore";

export type EscapeLayerProps = {
children?: Snippet;

/**
* Callback fired when escape is pressed.
*/
onEscape?: (e: KeyboardEvent) => void;
onEscapeKeydown?: (e: KeyboardEvent) => void;

/**
* Escape behavior type.
Expand All @@ -24,10 +22,15 @@ export type EscapeLayerProps = {
* @defaultValue `close`
*/
behaviorType?: EscapeBehaviorType;
};

// internal props not exposed to the user but used in the implementation
export type EscapeLayerImplProps = {
/**
* Whether the layer is enabled. Currently, we determine this with the
* `presence` returned from the `presence` layer.
*/
present: boolean;
};

children?: Snippet;
} & EscapeLayerProps;
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { untrack } from "svelte";
import type { EscapeBehaviorType, EscapeLayerProps } from "./types.js";
import type { EscapeBehaviorType, EscapeLayerImplProps } from "./types.js";
import type { ReadonlyBox, ReadonlyBoxedValues } from "$lib/internal/box.svelte.js";
import { type EventCallback, addEventListener } from "$lib/internal/events.js";
import { kbd } from "$lib/internal/kbd.js";
import { noop } from "$lib/internal/callbacks.js";

const layers = new Map<EscapeLayerState, ReadonlyBox<EscapeBehaviorType>>();

type EscapeLayerStateProps = ReadonlyBoxedValues<Required<Omit<EscapeLayerProps, "children">>>;
type EscapeLayerStateProps = ReadonlyBoxedValues<Required<Omit<EscapeLayerImplProps, "children">>>;

export class EscapeLayerState {
#onEscapeProp: ReadonlyBox<EventCallback<KeyboardEvent>>;
Expand All @@ -16,7 +16,7 @@ export class EscapeLayerState {

constructor(props: EscapeLayerStateProps) {
this.#behaviorType = props.behaviorType;
this.#onEscapeProp = props.onEscape;
this.#onEscapeProp = props.onEscapeKeydown;
this.#present = props.present;

let unsubEvents = noop;
Expand Down
Loading

0 comments on commit a68c521

Please sign in to comment.