replace type arguments with a single one

svelte-custom-renderer-single-type-argument
Rich Harris 2 weeks ago
parent 2c5b556b56
commit 1d2bc79cd2

@ -1,5 +1,5 @@
/** @import { ComponentContext } from '#client' */
/** @import { Renderer } from "./types.js" */
/** @import { AnyNode, Renderer, RendererNodes } from "./types.js" */
/** @import { Component, ComponentType, SvelteComponent } from '../../../index.js' */
import { boundary } from '../dom/blocks/boundary.js';
import { branch, effect_root } from '../reactivity/effects.js';
@ -8,12 +8,9 @@ import { push_renderer } from './state.js';
import { get_parent_node, remove_child } from '../dom/operations.js';
/**
* @template {object} [TFragment=object]
* @template {object} [TElement=object]
* @template {object} [TTextNode=object]
* @template {object} [TComment=object]
* @param {Renderer<TFragment, TElement, TTextNode, TComment>} renderer
* @returns {Renderer<TFragment, TElement, TTextNode, TComment> & { render: <Props extends Record<string, any>, Exports extends Record<string, any>>(component: ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: {} extends Props ? { target: TFragment | TElement | TTextNode | TComment, props?: Props, context?: Map<any, any> } : { target: TFragment | TElement | TTextNode | TComment, props: Props, context?: Map<any, any> }) => { component: Exports, unmount: () => void } }}
* @template {RendererNodes} T
* @param {Renderer<T>} renderer
* @returns {Renderer<T> & { render: <Props extends Record<string, any>, Exports extends Record<string, any>>(component: ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: {} extends Props ? { target: AnyNode<T>, props?: Props, context?: Map<any, any> } : { target: AnyNode<T>, props: Props, context?: Map<any, any> }) => { component: Exports, unmount: () => void } }}
*/
export function createRenderer(renderer) {
const compound_renderer = {
@ -22,7 +19,7 @@ export function createRenderer(renderer) {
* @template {Record<string, any>} Props
* @template {Record<string, any>} Exports
* @param {ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>} Component
* @param {{} extends Props ? { target: TFragment | TElement | TTextNode | TComment, props?: Props, context?: Map<any, any> } : { target: TFragment | TElement | TTextNode | TComment, props: Props, context?: Map<any, any> }} options
* @param {{} extends Props ? { target: AnyNode<T>, props?: Props, context?: Map<any, any> } : { target: AnyNode<T>, props: Props, context?: Map<any, any> }} options
*/
render(Component, { target, props, context }) {
var pop_renderer = push_renderer(compound_renderer);

@ -1,33 +1,32 @@
export type NodeType = 'fragment' | 'element' | 'text' | 'comment';
export type Renderer<
TFragment extends object = object,
TElement extends object = object,
TTextNode extends object = object,
TComment extends object = object,
TNode extends TFragment | TElement | TTextNode | TComment =
| TFragment
| TElement
| TTextNode
| TComment
> = {
type NodeType = 'fragment' | 'element' | 'text' | 'comment';
export type RendererNodes<
Fragment extends object = object,
Element extends object = object,
TextNode extends object = object,
Comment extends object = object
> = { fragment: Fragment; element: Element; text: TextNode; comment: Comment };
type AnyNode<T extends RendererNodes> = T[NodeType];
export type Renderer<T extends RendererNodes = RendererNodes> = {
/** Creates a fragment, a container for multiple nodes. Inserting a fragment should insert all of its children. */
createFragment(): TFragment;
createFragment(): T['fragment'];
/** Creates an element with the given name. */
createElement(name: string): TElement;
createElement(name: string): T['element'];
/** Creates a text node with the given data. */
createTextNode(data: string): TTextNode;
createTextNode(data: string): T['text'];
/**
* Creates a comment node with the given data.
* This is often used as an anchor for inserting elements; it doesn't necessarily need to be rendered.
*/
createComment(data: string): TComment;
createComment(data: string): T['comment'];
/** Should return the type of the node in string form. */
nodeType(node: TNode): NodeType;
nodeType(node: AnyNode<T>): NodeType;
/**
* Return the value of the node:
@ -35,54 +34,54 @@ export type Renderer<
* - data value of a comment
* - null for elements and fragments
*/
getNodeValue(node: TTextNode | TComment): string | null;
getNodeValue(node: T['text'] | T['comment']): string | null;
/** Return the value of the attribute with the given name on the element, or null if it doesn't exist. */
getAttribute(element: TElement, name: string): string | null;
getAttribute(element: T['element'], name: string): string | null;
/** Set the attribute with the given name and value on the element. */
setAttribute(element: TElement, key: string, value: any): void;
setAttribute(element: T['element'], key: string, value: any): void;
/** Remove the attribute with the given name from the element. */
removeAttribute(element: TElement, name: string): void;
removeAttribute(element: T['element'], name: string): void;
/** Return true if the element has an attribute with the given name. */
hasAttribute(element: TElement, name: string): boolean;
hasAttribute(element: T['element'], name: string): boolean;
/**
* Set the text content of the node to the given value.
* This should work for both text nodes and elements.
*/
setText(node: TElement | TTextNode | TComment, text: string): void;
setText(node: T['element'] | T['text'] | T['comment'], text: string): void;
/** Return the first child of the element or fragment, or null if it has no children. */
getFirstChild(element: TElement | TFragment): TNode | null;
getFirstChild(element: T['element'] | T['fragment']): AnyNode<T> | null;
/** Return the last child of the element or fragment, or null if it has no children. */
getLastChild(element: TElement | TFragment): TNode | null;
getLastChild(element: T['element'] | T['fragment']): AnyNode<T> | null;
/** Return the next sibling of the node, or null if it has no next sibling. */
getNextSibling(node: TElement | TTextNode | TComment): TNode | null;
getNextSibling(node: T['element'] | T['text'] | T['comment']): AnyNode<T> | null;
/**
* Insert the element into the parent before the anchor.
* If anchor is null, insert at the end.
*/
insert(
parent: TElement | TFragment,
element: TNode,
anchor: TElement | TTextNode | TComment | null
parent: T['element'] | T['fragment'],
element: AnyNode<T>,
anchor: T['element'] | T['text'] | T['comment'] | null
): void;
/** Remove the node from the tree. */
remove(node: TElement | TTextNode | TComment): void;
remove(node: T['element'] | T['text'] | T['comment']): void;
/** Return the parent of the element, or null if it has no parent. */
getParent(element: TElement | TTextNode | TComment): TNode | null;
getParent(element: T['element'] | T['text'] | T['comment']): AnyNode<T> | null;
/** Add an event listener of the given type and handler to the target node. */
addEventListener(target: TElement, type: string, handler: any, options?: any): void;
addEventListener(target: T['element'], type: string, handler: any, options?: any): void;
/** Remove an event listener of the given type and handler from the target node. */
removeEventListener(target: TElement, type: string, handler: any, options?: any): void;
removeEventListener(target: T['element'], type: string, handler: any, options?: any): void;
};

@ -2568,50 +2568,35 @@ declare module 'svelte/reactivity/window' {
}
declare module 'svelte/renderer' {
export function createRenderer<TFragment extends object = object, TElement extends object = object, TTextNode extends object = object, TComment extends object = object>(renderer: Renderer<TFragment, TElement, TTextNode, TComment>): Renderer<TFragment, TElement, TTextNode, TComment> & {
render: <Props extends Record<string, any>, Exports extends Record<string, any>>(component: ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: {} extends Props ? {
target: TFragment | TElement | TTextNode | TComment;
props?: Props;
context?: Map<any, any>;
} : {
target: TFragment | TElement | TTextNode | TComment;
props: Props;
context?: Map<any, any>;
}) => {
component: Exports;
unmount: () => void;
};
};
type NodeType = 'fragment' | 'element' | 'text' | 'comment';
type Renderer<
TFragment extends object = object,
TElement extends object = object,
TTextNode extends object = object,
TComment extends object = object,
TNode extends TFragment | TElement | TTextNode | TComment =
| TFragment
| TElement
| TTextNode
| TComment
> = {
type RendererNodes<
Fragment extends object = object,
Element extends object = object,
TextNode extends object = object,
Comment extends object = object
> = { fragment: Fragment; element: Element; text: TextNode; comment: Comment };
type AnyNode<T extends RendererNodes> = T[NodeType];
export type Renderer<T extends RendererNodes = RendererNodes> = {
/** Creates a fragment, a container for multiple nodes. Inserting a fragment should insert all of its children. */
createFragment(): TFragment;
createFragment(): T['fragment'];
/** Creates an element with the given name. */
createElement(name: string): TElement;
createElement(name: string): T['element'];
/** Creates a text node with the given data. */
createTextNode(data: string): TTextNode;
createTextNode(data: string): T['text'];
/**
* Creates a comment node with the given data.
* This is often used as an anchor for inserting elements; it doesn't necessarily need to be rendered.
*/
createComment(data: string): TComment;
createComment(data: string): T['comment'];
/** Should return the type of the node in string form. */
nodeType(node: TNode): NodeType;
nodeType(node: AnyNode<T>): NodeType;
/**
* Return the value of the node:
@ -2619,56 +2604,70 @@ declare module 'svelte/renderer' {
* - data value of a comment
* - null for elements and fragments
*/
getNodeValue(node: TTextNode | TComment): string | null;
getNodeValue(node: T['text'] | T['comment']): string | null;
/** Return the value of the attribute with the given name on the element, or null if it doesn't exist. */
getAttribute(element: TElement, name: string): string | null;
getAttribute(element: T['element'], name: string): string | null;
/** Set the attribute with the given name and value on the element. */
setAttribute(element: TElement, key: string, value: any): void;
setAttribute(element: T['element'], key: string, value: any): void;
/** Remove the attribute with the given name from the element. */
removeAttribute(element: TElement, name: string): void;
removeAttribute(element: T['element'], name: string): void;
/** Return true if the element has an attribute with the given name. */
hasAttribute(element: TElement, name: string): boolean;
hasAttribute(element: T['element'], name: string): boolean;
/**
* Set the text content of the node to the given value.
* This should work for both text nodes and elements.
*/
setText(node: TElement | TTextNode | TComment, text: string): void;
setText(node: T['element'] | T['text'] | T['comment'], text: string): void;
/** Return the first child of the element or fragment, or null if it has no children. */
getFirstChild(element: TElement | TFragment): TNode | null;
getFirstChild(element: T['element'] | T['fragment']): AnyNode<T> | null;
/** Return the last child of the element or fragment, or null if it has no children. */
getLastChild(element: TElement | TFragment): TNode | null;
getLastChild(element: T['element'] | T['fragment']): AnyNode<T> | null;
/** Return the next sibling of the node, or null if it has no next sibling. */
getNextSibling(node: TElement | TTextNode | TComment): TNode | null;
getNextSibling(node: T['element'] | T['text'] | T['comment']): AnyNode<T> | null;
/**
* Insert the element into the parent before the anchor.
* If anchor is null, insert at the end.
*/
insert(
parent: TElement | TFragment,
element: TNode,
anchor: TElement | TTextNode | TComment | null
parent: T['element'] | T['fragment'],
element: AnyNode<T>,
anchor: T['element'] | T['text'] | T['comment'] | null
): void;
/** Remove the node from the tree. */
remove(node: TElement | TTextNode | TComment): void;
remove(node: T['element'] | T['text'] | T['comment']): void;
/** Return the parent of the element, or null if it has no parent. */
getParent(element: TElement | TTextNode | TComment): TNode | null;
getParent(element: T['element'] | T['text'] | T['comment']): AnyNode<T> | null;
/** Add an event listener of the given type and handler to the target node. */
addEventListener(target: TElement, type: string, handler: any, options?: any): void;
addEventListener(target: T['element'], type: string, handler: any, options?: any): void;
/** Remove an event listener of the given type and handler from the target node. */
removeEventListener(target: TElement, type: string, handler: any, options?: any): void;
removeEventListener(target: T['element'], type: string, handler: any, options?: any): void;
};
export function createRenderer<T extends RendererNodes>(renderer: Renderer<T>): Renderer<T> & {
render: <Props extends Record<string, any>, Exports extends Record<string, any>>(component: ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: {} extends Props ? {
target: TFragment | TElement | TTextNode | TComment;
props?: Props;
context?: Map<any, any>;
} : {
target: TFragment | TElement | TTextNode | TComment;
props: Props;
context?: Map<any, any>;
}) => {
component: Exports;
unmount: () => void;
};
};
/**
* @deprecated In Svelte 4, components are classes. In Svelte 5, they are functions.

Loading…
Cancel
Save