diff --git a/packages/svelte/src/attachments/index.js b/packages/svelte/src/attachments/index.js index bfd5525850df..514c9433f444 100644 --- a/packages/svelte/src/attachments/index.js +++ b/packages/svelte/src/attachments/index.js @@ -1,4 +1,5 @@ -/** @import { FromAction } from './public.js' */ +/** @import { Action, ActionReturn } from 'svelte/action' */ +/** @import { Attachment } from 'svelte/attachments' */ import { noop, render_effect } from 'svelte/internal/client'; import { ATTACHMENT_KEY } from '../constants.js'; import { untrack } from 'svelte'; @@ -30,20 +31,42 @@ export function createAttachmentKey() { return Symbol(ATTACHMENT_KEY); } +/** + * @template {EventTarget} E + * @template {unknown} T + * @overload + * @param {Action | function(E, T): void | ActionReturn} action The action function + * @param {() => T} fn A function that returns the argument for the action + * @returns {Attachment} + */ +/** + * @template {EventTarget} E + * @overload + * @param {Action | function(E): void | ActionReturn} action The action function + * @returns {Attachment} + */ /** * Converts an Action into an Attachment keeping the same behavior. It's useful if you want to start using * attachments on Components but you have library provided actions. - * @type {FromAction} + * + * Note that the second argument, if provided, must be a function that _returns_ the argument to the + * action function, not the argument itself. + * + * @template {EventTarget} E + * @template {unknown} T + * @param {Action | function(E, T): void | ActionReturn} action The action function + * @param {() => T} fn A function that returns the argument for the action + * @returns {Attachment} * @since 5.32 */ -export function fromAction(action, /** @type {() => any} */ get_arg = noop) { +export function fromAction(action, fn = /** @type {() => T} */ (noop)) { return (element) => { - const { update, destroy } = untrack(() => action(element, get_arg()) ?? {}); + const { update, destroy } = untrack(() => action(element, fn()) ?? {}); if (update) { var ran = false; render_effect(() => { - const arg = get_arg(); + const arg = fn(); if (ran) update(arg); }); ran = true; diff --git a/packages/svelte/src/attachments/public.d.ts b/packages/svelte/src/attachments/public.d.ts index 8680139bc7ea..44b0e2a225b4 100644 --- a/packages/svelte/src/attachments/public.d.ts +++ b/packages/svelte/src/attachments/public.d.ts @@ -11,18 +11,4 @@ export interface Attachment { (element: T): void | (() => void); } -export interface FromAction { - ( - ...args: undefined extends NoInfer - ? [ - action: (node: Node, parameter?: never) => void | ActionReturn, - parameter?: () => NoInfer - ] - : [ - action: (node: Node, parameter: Parameter) => void | ActionReturn, - parameter: () => NoInfer - ] - ): Attachment; -} - export * from './index.js'; diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index fa0d7014220f..067e04db5b3e 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -625,7 +625,7 @@ declare module 'svelte/animate' { } declare module 'svelte/attachments' { - import type { ActionReturn } from 'svelte/action'; + import type { ActionReturn, Action } from 'svelte/action'; /** * An [attachment](https://svelte.dev/docs/svelte/@attach) is a function that runs when an element is mounted * to the DOM, and optionally returns a function that is called when the element is later removed. @@ -636,20 +636,6 @@ declare module 'svelte/attachments' { export interface Attachment { (element: T): void | (() => void); } - - export interface FromAction { - ( - ...args: undefined extends NoInfer - ? [ - action: (node: Node, parameter?: never) => void | ActionReturn, - parameter?: () => NoInfer - ] - : [ - action: (node: Node, parameter: Parameter) => void | ActionReturn, - parameter: () => NoInfer - ] - ): Attachment; - } /** * Creates an object key that will be recognised as an attachment when the object is spread onto an element, * as a programmatic alternative to using `{@attach ...}`. This can be useful for library authors, though @@ -673,49 +659,10 @@ declare module 'svelte/attachments' { * @since 5.29 */ export function createAttachmentKey(): symbol; - export function fromAction(...args: undefined extends NoInfer ? [action: (node: Node, parameter?: never) => void | ActionReturn_1>, parameter?: (() => NoInfer) | undefined] : [action: (node: Node, parameter: Parameter) => void | ActionReturn_1>, parameter: () => NoInfer]): Attachment; - /** - * Actions can return an object containing the two properties defined in this interface. Both are optional. - * - update: An action can have a parameter. This method will be called whenever that parameter changes, - * immediately after Svelte has applied updates to the markup. `ActionReturn` and `ActionReturn` both - * mean that the action accepts no parameters. - * - destroy: Method that is called after the element is unmounted - * - * Additionally, you can specify which additional attributes and events the action enables on the applied element. - * This applies to TypeScript typings only and has no effect at runtime. - * - * Example usage: - * ```ts - * interface Attributes { - * newprop?: string; - * 'on:event': (e: CustomEvent) => void; - * } - * - * export function myAction(node: HTMLElement, parameter: Parameter): ActionReturn { - * // ... - * return { - * update: (updatedParameter) => {...}, - * destroy: () => {...} - * }; - * } - * ``` - */ - interface ActionReturn_1< - Parameter = undefined, - Attributes extends Record = Record - > { - update?: (parameter: Parameter) => void; - destroy?: () => void; - /** - * ### DO NOT USE THIS - * This exists solely for type-checking and has no effect at runtime. - * Set this through the `Attributes` generic instead. - */ - $$_attributes?: Attributes; - } - // Implementation notes: - // - undefined extends X instead of X extends undefined makes this work better with both strict and nonstrict mode + export function fromAction(action: Action | ((arg0: E, arg1: T) => void | ActionReturn), fn: () => T): Attachment; + + export function fromAction(action: Action | ((arg0: E) => void | ActionReturn)): Attachment; export {}; }