Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/lib/components/dialog/dialog-root.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
> = HtmlAtomProps<E, B> & {
open?: boolean;
disabled?: boolean;
portal?: string | PortalBond;
factory?: (props: DialogBondProps) => DialogBond;
children?: Snippet<[{ dialog: DialogBond }]>;
};
Expand All @@ -13,7 +14,7 @@
<script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
import type { Snippet } from 'svelte';
import { animate as motion } from 'motion';
import { Teleport, ActivePortal } from '$svelte-atoms/core/components/portal';
import { Teleport, ActivePortal, PortalBond } from '$svelte-atoms/core/components/portal';
import { defineProperty, defineState } from '$svelte-atoms/core/utils';
import type { HtmlAtomProps, Base } from '$svelte-atoms/core/components/atom';
import { DURATION } from '$svelte-atoms/core/shared';
Expand All @@ -24,6 +25,7 @@
open = $bindable(false),
disabled = false,
as = 'dialog' as E,
portal = undefined,
factory = _factory,
onmount = undefined,
ondestroy = undefined,
Expand Down Expand Up @@ -95,7 +97,7 @@
{as}
{bond}
preset="dialog"
portal="root.l1"
portal={portal ?? 'root.l1'}
class={[
'border-border pointer-events-auto fixed top-0 left-0 flex h-full w-full items-center justify-center bg-neutral-900/10 opacity-0',
!open && 'pointer-events-none',
Expand All @@ -115,9 +117,7 @@
}}
{...rootProps}
>
<!-- <div class="w-full h-full flex items-center justify-center"> -->
<ActivePortal id="root.l1">
<ActivePortal portal={portal ?? 'root.l1'}>
{@render children?.({ dialog: bond })}
</ActivePortal>
<!-- </div> -->
</Teleport>
11 changes: 8 additions & 3 deletions src/lib/components/drawer/drawer-root.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
> = Override<
HtmlAtomProps<E, B>,
{
children?: Snippet<[{ slideover: DrawerBond }]>;
children?: Snippet<[{ drawer: DrawerBond }]>;
initial?: (node: HTMLElement, bond: DrawerBond) => void;
enter?: (node: HTMLElement, bond: DrawerBond) => TransitionFunction<'dialog'>;
exit?: (node: HTMLElement, bond: DrawerBond) => TransitionFunction<'dialog'>;
}
> & {
open?: boolean;
disabled?: boolean;
portal?: string | PortalBond;
onclose?: (event: Event, bond: DrawerBond) => void;
factory?: Factory<DrawerBond>;
};
Expand All @@ -29,6 +30,7 @@
import Teleport from '$svelte-atoms/core/components/portal/teleport.svelte';
import type { HtmlAtomProps, Base } from '$svelte-atoms/core/components/atom';
import { DrawerBond, DrawerBondState, type DrawerBondProps } from './bond.svelte';
import { ActivePortal, type PortalBond } from '../portal';

type Element = HTMLElementTagNameMap[E];

Expand All @@ -38,6 +40,7 @@
class: klass = '',
as = 'dialog',
disabled = false,
portal = undefined,
onclose = undefined,
onmount = undefined,
ondestroy = undefined,
Expand Down Expand Up @@ -92,7 +95,7 @@
<Teleport
{as}
{bond}
portal="root.l1"
portal={portal ?? 'root.l1'}
preset="drawer"
class={[
'border-border pointer-events-auto h-full w-full overflow-hidden bg-transparent',
Expand All @@ -109,5 +112,7 @@
animate={animate?.bind(bond.state)}
{...rootProps}
>
{@render children?.({ drawer: bond })}
<ActivePortal portal={portal ?? 'root.l1'}>
{@render children?.({ drawer: bond })}
</ActivePortal>
</Teleport>
2 changes: 2 additions & 0 deletions src/lib/components/popover/bond.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { debounce } from 'es-toolkit';
import { getElementId, isBrowser } from '$svelte-atoms/core/utils/dom.svelte.js';
import { Bond, BondState, type BondStateProps } from '$svelte-atoms/core/shared/bond.svelte.js';
import type { PortalBond } from '../portal';

export type PopoverParams = {
apply?: (
Expand All @@ -30,6 +31,7 @@ export type PopoverStateProps<T extends Record<string, unknown> = Record<string,
placements: Placement[];
placement: Placement | undefined;
offset: number;
portal?: string | PortalBond;
extend: T;
};

Expand Down
8 changes: 1 addition & 7 deletions src/lib/components/popover/popover-arrow.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
<script module lang="ts">
export type PopoverArrowProps<
E extends keyof HTMLElementTagNameMap = 'div',
B extends Base = Base
> = HtmlAtomProps<E, B>;
</script>

<script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
import type { HTMLAttributes } from 'svelte/elements';
import { animate as motion } from 'motion';
import { HtmlAtom, type HtmlAtomProps, type Base } from '$svelte-atoms/core/components/atom';
import { PopoverBond } from './bond.svelte';
import type { PopoverArrowProps } from './types';

type Element = HTMLElementTagNameMap[E];

Expand Down
47 changes: 19 additions & 28 deletions src/lib/components/popover/popover-content.svelte
Original file line number Diff line number Diff line change
@@ -1,39 +1,30 @@
<script module lang="ts">
import type { Override } from '$svelte-atoms/core/types';

export type AnimateParams = {
x: number;
y: number;
xOffset: number;
yOffset: number;
open: boolean;
};

export type PopoverOverlayProps<T extends HtmlElementTagName, B extends Base = Base> = Override<
HtmlAtomProps<T, B>,
{
children?: Snippet<[{ popover?: PopoverBond }]>;
}
>;

const k: PopoverOverlayProps<'div'> = {
class: []
};
</script>

<script lang="ts" generics="E extends HtmlElementTagName, B extends Base = Base">
import { type Snippet } from 'svelte';
import { animate as motion } from 'motion';
import { PortalBond, Teleport } from '$svelte-atoms/core/components/portal';
import { HtmlAtom, type HtmlAtomProps, type Base } from '$svelte-atoms/core/components/atom';
import { PortalBond, PortalsBond, Teleport } from '$svelte-atoms/core/components/portal';
import { HtmlAtom, type Base } from '$svelte-atoms/core/components/atom';
import type { HtmlElementTagName, HtmlElementType } from '$svelte-atoms/core/components/element';
import { PopoverBond } from './bond.svelte';
import { DURATION } from '$svelte-atoms/core/shared';
import type { AnimateParams, PopoverContentProps } from './types';

type Element = HtmlElementType<E>;

const bond = PopoverBond.get();
const activePortalBond = PortalBond.get();
const activePortalBond = (() => {
const key = bond.state.props.portal;
if (key instanceof PortalBond) {
return key;
}

let portal: PortalBond | undefined | null = undefined;

if (typeof key === 'string') {
portal = PortalsBond.get()?.state.get(key);
console.error('portal was not found');
}

return portal ?? PortalBond.get();
})();

if (!bond) {
throw new Error('<PopoverOverlay /> must be used within a <Popover />');
Expand All @@ -49,7 +40,7 @@
exit = undefined,
initial = undefined,
...restProps
}: PopoverOverlayProps<E, B> = $props();
}: PopoverContentProps<E, B> = $props();

const isOpen = $derived(bond.state.isOpen && !!bond.elements.trigger);
const portalId = $derived(activePortalBond?.id);
Expand Down
22 changes: 4 additions & 18 deletions src/lib/components/popover/popover-root.svelte
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
<script module lang="ts">
import type { Factory } from '$svelte-atoms/core/types';

export type PopoverRootProps = {
open?: boolean;
disabled?: boolean;
placements?: Placement[];
placement?: Placement;
offset?: number;
extend?: Record<string, unknown>;
factory?: Factory<PopoverBond>;
children?: Snippet<[{ popover: PopoverBond }]>;
};
</script>

<script lang="ts">
import type { Snippet } from 'svelte';
import type { Placement } from '@floating-ui/dom';
import { PopoverState, PopoverBond, type PopoverStateProps } from './bond.svelte';
import { defineProperty, defineState } from '$svelte-atoms/core/utils';
import type { PopoverRootProps } from './types';

let {
open = $bindable(false),
disabled = false,
placements = ['bottom-start', 'bottom-end', 'top-start', 'top-end'],
placement = 'bottom-start',
offset = 0,
portal = undefined,
extend = {},
factory = _factory,
children = undefined
Expand All @@ -42,7 +27,8 @@
defineProperty('disabled', () => disabled),
defineProperty('placement', () => placement),
defineProperty('offset', () => offset),
defineProperty('placements', () => placements ?? [])
defineProperty('placements', () => placements ?? []),
defineProperty('portal', () => portal)
],
() => ({ extend })
);
Expand Down
13 changes: 2 additions & 11 deletions src/lib/components/popover/popover-trigger.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
<script module lang="ts">
export type PopoverTriggerProps<
T extends keyof HTMLElementTagNameMap,
B extends Base = Base
> = HtmlAtomProps<T, B> & {
children?: Snippet<[{ popover?: PopoverBond }]>;
};
</script>

<script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
import type { Snippet } from 'svelte';
import { HtmlAtom, type HtmlAtomProps, type Base } from '$svelte-atoms/core/components/atom';
import { HtmlAtom, type Base } from '$svelte-atoms/core/components/atom';
import { PopoverBond } from './bond.svelte';
import type { PopoverTriggerProps } from './types';

const bond = PopoverBond.get();

Expand Down
47 changes: 47 additions & 0 deletions src/lib/components/popover/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { Snippet } from 'svelte';
import type { Placement } from '@floating-ui/dom';
import type { Factory } from '$svelte-atoms/core/types';
import type { PopoverBond } from './bond.svelte';
import type { Override } from '$svelte-atoms/core/types';
import type { Base, HtmlAtomProps } from '../atom';
import type { HtmlElementTagName } from '../element';
import type { PortalBond } from '../portal';

export type PopoverRootProps = {
open?: boolean;
disabled?: boolean;
placements?: Placement[];
placement?: Placement;
offset?: number;
portal?: string | PortalBond;
extend?: Record<string, unknown>;
factory?: Factory<PopoverBond>;
children?: Snippet<[{ popover: PopoverBond }]>;
};

export type AnimateParams = {
x: number;
y: number;
xOffset: number;
yOffset: number;
open: boolean;
};

export type PopoverContentProps<T extends HtmlElementTagName, B extends Base = Base> = Override<
HtmlAtomProps<T, B>,
{
children?: Snippet<[{ popover?: PopoverBond }]>;
}
>;

export type PopoverArrowProps<
E extends keyof HTMLElementTagNameMap = 'div',
B extends Base = Base
> = HtmlAtomProps<E, B>;

export type PopoverTriggerProps<
T extends keyof HTMLElementTagNameMap,
B extends Base = Base
> = HtmlAtomProps<T, B> & {
children?: Snippet<[{ popover?: PopoverBond }]>;
};
10 changes: 8 additions & 2 deletions src/lib/components/portal/active-portal.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<script>
import { PortalsBond } from './portals/bond.svelte';

let { id, children = undefined } = $props();
let { portal, children = undefined } = $props();

const portalsBond = PortalsBond.get();
const activePortal = portalsBond?.state.get(id)?.share();
const activePortal = (() => {
if (typeof portal === 'string') {
return portalsBond?.state?.get(portal) ?? undefined;
}

return portal;
})()?.share();

if (!portalsBond) {
throw new Error('Portals bond is not found');
Expand Down
14 changes: 10 additions & 4 deletions src/lib/components/portal/teleport.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
E extends HtmlElementTagName = 'div',
B extends Base = Base
> = HtmlAtomProps<E, B> & {
portal?: string;
portal?: string | PortalBond;
};
</script>

Expand All @@ -15,6 +15,7 @@
import { PortalsBond } from './portals';
import { RootBond } from '$svelte-atoms/core/components/root/bond.svelte';
import { port } from './utils';
import type { PortalBond } from '.';

type Element = HtmlElementType<E>;

Expand All @@ -24,9 +25,14 @@
const portalsBond = PortalsBond.get();
const rootBond = RootBond.get();

const portalBond = $derived(
portalsBond?.state?.get(portal!) ?? rootBond?.state?.getPortal(portal!)
);
const portalBond = $derived.by(() => {
if (typeof portal === 'string') {
return portalsBond?.state?.get(portal!) ?? rootBond?.state?.getPortal(portal!);
}

return portal;
});

const targetElement = $derived(portalBond?.targetElement);

function _port(node: HTMLElement) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/root/root.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
</Portal.Outer>
{/if}

<ActivePortal id="root.l0">
<ActivePortal portal="root.l0">
{@render children?.()}
</ActivePortal>
</HtmlAtom>
Expand Down