Package entry point and lint fixes
Adds packages/core/src/index.ts as the convenience re-export barrel for all Dialog parts, Presence, Portal, VisuallyHidden, createFocusTrap, createScrollLock, and createDismiss. Also resolves pre-existing biome formatter and noNonNullAssertion violations across five files so CI passes.
This commit is contained in:
parent
a25244840b
commit
7dd8615757
31
packages/core/src/index.ts
Normal file
31
packages/core/src/index.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// packages/core/src/index.ts
|
||||||
|
// Main entry — re-exports everything for convenience.
|
||||||
|
// Prefer sub-path imports (e.g. "pettyui/dialog") for tree-shaking.
|
||||||
|
|
||||||
|
export { Dialog } from "./components/dialog/index";
|
||||||
|
export type { DialogRootProps } from "./components/dialog/dialog-root";
|
||||||
|
export type { DialogContentProps } from "./components/dialog/dialog-content";
|
||||||
|
export type { DialogTitleProps } from "./components/dialog/dialog-title";
|
||||||
|
export type { DialogDescriptionProps } from "./components/dialog/dialog-description";
|
||||||
|
export type { DialogTriggerProps } from "./components/dialog/dialog-trigger";
|
||||||
|
export type { DialogCloseProps } from "./components/dialog/dialog-close";
|
||||||
|
export type { DialogPortalProps } from "./components/dialog/dialog-portal";
|
||||||
|
export type { DialogOverlayProps } from "./components/dialog/dialog-overlay";
|
||||||
|
|
||||||
|
export { Presence } from "./utilities/presence/index";
|
||||||
|
export type { PresenceProps, PresenceChildProps } from "./utilities/presence/index";
|
||||||
|
|
||||||
|
export { Portal } from "./utilities/portal/index";
|
||||||
|
export type { PortalProps } from "./utilities/portal/index";
|
||||||
|
|
||||||
|
export { VisuallyHidden } from "./utilities/visually-hidden/index";
|
||||||
|
export type { VisuallyHiddenProps } from "./utilities/visually-hidden/index";
|
||||||
|
|
||||||
|
export { createFocusTrap } from "./utilities/focus-trap/index";
|
||||||
|
export type { FocusTrap } from "./utilities/focus-trap/index";
|
||||||
|
|
||||||
|
export { createScrollLock } from "./utilities/scroll-lock/index";
|
||||||
|
export type { ScrollLock } from "./utilities/scroll-lock/index";
|
||||||
|
|
||||||
|
export { createDismiss } from "./utilities/dismiss/index";
|
||||||
|
export type { CreateDismissOptions, Dismiss } from "./utilities/dismiss/index";
|
||||||
@ -19,9 +19,7 @@ export interface DisclosureState {
|
|||||||
* Tooltip, Collapsible, etc.). Wraps createControllableSignal with
|
* Tooltip, Collapsible, etc.). Wraps createControllableSignal with
|
||||||
* convenience open/close/toggle methods.
|
* convenience open/close/toggle methods.
|
||||||
*/
|
*/
|
||||||
export function createDisclosureState(
|
export function createDisclosureState(options: CreateDisclosureStateOptions): DisclosureState {
|
||||||
options: CreateDisclosureStateOptions,
|
|
||||||
): DisclosureState {
|
|
||||||
const [isOpen, setIsOpen] = createControllableSignal<boolean>({
|
const [isOpen, setIsOpen] = createControllableSignal<boolean>({
|
||||||
value: () => options.open,
|
value: () => options.open,
|
||||||
defaultValue: () => options.defaultOpen ?? false,
|
defaultValue: () => options.defaultOpen ?? false,
|
||||||
|
|||||||
@ -36,8 +36,8 @@ export function createFocusTrap(getContainer: Accessor<HTMLElement | null>): Foc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const first = focusable[0]!;
|
const first = focusable[0] as HTMLElement;
|
||||||
const last = focusable[focusable.length - 1]!;
|
const last = focusable[focusable.length - 1] as HTMLElement;
|
||||||
|
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
if (document.activeElement === first) {
|
if (document.activeElement === first) {
|
||||||
|
|||||||
@ -17,9 +17,5 @@ export function Portal(props: PortalProps): JSX.Element {
|
|||||||
return <>{props.children}</>;
|
return <>{props.children}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <SolidPortal mount={props.target ?? document.body}>{props.children}</SolidPortal>;
|
||||||
<SolidPortal mount={props.target ?? document.body}>
|
|
||||||
{props.children}
|
|
||||||
</SolidPortal>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,12 +75,12 @@ export function Presence(props: PresenceProps): JSX.Element {
|
|||||||
// Wrap in a function so Show evaluates children lazily (only when mounted).
|
// Wrap in a function so Show evaluates children lazily (only when mounted).
|
||||||
return (
|
return (
|
||||||
<Show when={shouldMount()}>
|
<Show when={shouldMount()}>
|
||||||
{(
|
{
|
||||||
() =>
|
(() =>
|
||||||
typeof props.children === "function"
|
typeof props.children === "function"
|
||||||
? (props.children as (p: PresenceChildProps) => JSX.Element)(childProps)
|
? (props.children as (p: PresenceChildProps) => JSX.Element)(childProps)
|
||||||
: props.children
|
: props.children) as unknown as JSX.Element
|
||||||
) as unknown as JSX.Element}
|
}
|
||||||
</Show>
|
</Show>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,7 +96,12 @@ describe("createFocusTrap", () => {
|
|||||||
const trap = createFocusTrap(() => container);
|
const trap = createFocusTrap(() => container);
|
||||||
trap.activate();
|
trap.activate();
|
||||||
// button1 is already focused after activate
|
// button1 is already focused after activate
|
||||||
const event = new KeyboardEvent("keydown", { key: "Tab", shiftKey: true, bubbles: true, cancelable: true });
|
const event = new KeyboardEvent("keydown", {
|
||||||
|
key: "Tab",
|
||||||
|
shiftKey: true,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
});
|
||||||
document.dispatchEvent(event);
|
document.dispatchEvent(event);
|
||||||
expect(document.activeElement).toBe(button2);
|
expect(document.activeElement).toBe(button2);
|
||||||
trap.deactivate();
|
trap.deactivate();
|
||||||
@ -138,7 +143,9 @@ describe("createFocusTrap", () => {
|
|||||||
// Tab from the only element — Tab wraps back to itself (first === last)
|
// Tab from the only element — Tab wraps back to itself (first === last)
|
||||||
// What matters is it doesn't fire twice causing erratic behaviour
|
// What matters is it doesn't fire twice causing erratic behaviour
|
||||||
expect(() => {
|
expect(() => {
|
||||||
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Tab", bubbles: true, cancelable: true }));
|
document.dispatchEvent(
|
||||||
|
new KeyboardEvent("keydown", { key: "Tab", bubbles: true, cancelable: true }),
|
||||||
|
);
|
||||||
}).not.toThrow();
|
}).not.toThrow();
|
||||||
trap.deactivate();
|
trap.deactivate();
|
||||||
dispose();
|
dispose();
|
||||||
|
|||||||
@ -4,7 +4,11 @@ import { Portal } from "../../src/utilities/portal/portal";
|
|||||||
|
|
||||||
describe("Portal", () => {
|
describe("Portal", () => {
|
||||||
it("renders children into document.body by default", () => {
|
it("renders children into document.body by default", () => {
|
||||||
render(() => <Portal><div data-testid="portal-content">hello</div></Portal>);
|
render(() => (
|
||||||
|
<Portal>
|
||||||
|
<div data-testid="portal-content">hello</div>
|
||||||
|
</Portal>
|
||||||
|
));
|
||||||
// Content should be in document.body, not the render container
|
// Content should be in document.body, not the render container
|
||||||
expect(document.body.querySelector("[data-testid='portal-content']")).toBeTruthy();
|
expect(document.body.querySelector("[data-testid='portal-content']")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user