fixes, public/private.dts, d.ts generation

pull/8569/head
Simon Holthausen 3 years ago
parent bc5ebb0dd8
commit 47da31e84f

@ -0,0 +1,117 @@
// This script generates the TypeScript definitions
import { execSync } from 'child_process';
import { readFileSync, writeFileSync, readdirSync, existsSync, copyFileSync } from 'fs';
execSync('tsc -p src/compiler --emitDeclarationOnly && tsc -p src/runtime --emitDeclarationOnly', { stdio: 'inherit' });
function modify(path, modifyFn) {
const content = readFileSync(path, 'utf8');
writeFileSync(path, modifyFn(content));
}
function adjust(input) {
// Remove typedef jsdoc (duplicated in the type definition)
input = input.replace(/\/\*\*\n(\r)? \* @typedef .+?\*\//gs, '');
input = input.replace(/\/\*\* @typedef .+?\*\//gs, '');
// Extract the import paths and types
const import_regex = /import\(("|')(.+?)("|')\)\.(\w+)/g;
let import_match;
const import_map = new Map();
while ((import_match = import_regex.exec(input)) !== null) {
const imports = import_map.get(import_match[2]) || new Set();
imports.add(import_match[4]);
import_map.set(import_match[2], imports);
}
// Replace inline imports with their type names
const transformed = input.replace(import_regex, "$4");
// Remove/adjust @template, @param and @returns lines
// TODO rethink if we really need to do this for @param and @returns, doesn't show up in hover so unnecessary
const lines = transformed.split("\n");
let filtered_lines = [];
let removing = null;
let openCount = 1;
let closedCount = 0;
for (let line of lines) {
let start_removing = false;
if (line.trim().startsWith("* @template")) {
removing = "template";
start_removing = true;
}
if (line.trim().startsWith("* @param {")) {
openCount = 1;
closedCount = 0;
removing = "param";
start_removing = true;
}
if (line.trim().startsWith("* @returns {")) {
openCount = 1;
closedCount = 0;
removing = "returns";
start_removing = true;
}
if (removing === "returns" || removing === "param") {
let i = start_removing ? line.indexOf('{') + 1 : 0;
for (; i < line.length; i++) {
if (line[i] === "{") openCount++;
if (line[i] === "}") closedCount++;
if (openCount === closedCount) break;
}
if (openCount === closedCount) {
line = start_removing ? (line.slice(0, line.indexOf('{')) + line.slice(i + 1)) : (` * @${removing} ` + line.slice(i + 1));
removing = null;
}
}
if (removing && !start_removing && (line.trim().startsWith("* @") || line.trim().startsWith("*/"))) {
removing = null;
}
if (!removing) {
filtered_lines.push(line);
}
}
// Replace generic type names with their plain versions
const renamed_generics = filtered_lines.map(line => {
return line.replace(/(\W|\s)([A-Z][\w\d$]*)_\d+(\W|\s)/g, "$1$2$3");
});
// Generate the import statement for the types used
const import_statements = Array.from(import_map.entries())
.map(([path, types]) => `import { ${[...types].join(', ')} } from '${path}';`)
.join("\n");
return [import_statements, ...renamed_generics].join("\n");
}
for (const dir of readdirSync('types/runtime')) {
if (dir.endsWith('.d.ts')) continue;
modify(
`types/runtime/${dir}/index.d.ts`,
content => {
// TODO adjust all d.ts files
content = adjust(content);
if (existsSync(`src/runtime/${dir}/public.d.ts`)) {
copyFileSync(`src/runtime/${dir}/public.d.ts`, `types/runtime/${dir}/public.d.ts`);
content + "\nexport * from './public.js'";
}
return content;
}
);
}
copyFileSync(`src/runtime/ambient.d.ts`, `types/runtime/ambient.d.ts`);
modify(`types/runtime/index.d.ts`, content => content + "\nimport './ambient.js'");

@ -92,7 +92,7 @@
"dev": "rollup -cw",
"posttest": "agadoo internal/index.mjs",
"prepublishOnly": "node check_publish_env.js && npm run lint && npm run build && npm test",
"tsd": "tsc -p src/compiler --emitDeclarationOnly && tsc -p src/runtime --emitDeclarationOnly",
"tsd": "node ./generate-types.mjs",
"lint": "eslint \"{src,test}/**/*.{ts,js}\" --cache"
},
"repository": {

@ -32,7 +32,7 @@ const runtime_entrypoints = Object.fromEntries(
fs
.readdirSync('src/runtime', { withFileTypes: true })
.filter((dirent) => dirent.isDirectory())
.map((dirent) => [dirent.name, `src/runtime/${dirent.name}/index.ts`])
.map((dirent) => [dirent.name, `src/runtime/${dirent.name}/index.js`])
);
/**
@ -42,8 +42,8 @@ export default [
{
input: {
...runtime_entrypoints,
index: 'src/runtime/index.ts',
ssr: 'src/runtime/ssr.ts'
index: 'src/runtime/index.js',
ssr: 'src/runtime/ssr.js'
},
output: ['es', 'cjs'].map(
/** @returns {import('rollup').OutputOptions} */

@ -3,7 +3,9 @@
"include": ["."],
"compilerOptions": {
"lib": ["es2017", "webworker"]
"lib": ["es2017", "webworker"],
"allowJs": true,
"checkJs": true
// TODO: remove mocha types from the whole project
// "types": ["node", "estree"]

@ -1,8 +1,7 @@
/**
* 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<never>` both
* mean that the action accepts no parameters, which makes it illegal to set the `update` method.
* immediately after Svelte has applied updates to the markup.
* - 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.
@ -27,10 +26,10 @@
* Docs: https://svelte.dev/docs#template-syntax-element-directives-use-action
*/
export interface ActionReturn<
Parameter = never,
Parameter = any,
Attributes extends Record<string, any> = Record<never, any>
> {
update?: [Parameter] extends [never] ? never : (parameter: Parameter) => void;
update?: (parameter: Parameter) => void;
destroy?: () => void;
/**
* ### DO NOT USE THIS
@ -46,12 +45,10 @@ export interface ActionReturn<
* The following example defines an action that only works on `<div>` elements
* and optionally accepts a parameter which it has a default value for:
* ```ts
* export const myAction: Action<HTMLDivElement, { someProperty: boolean } | undefined> = (node, param = { someProperty: true }) => {
* export const myAction: Action<HTMLDivElement, { someProperty: boolean }> = (node, param = { someProperty: true }) => {
* // ...
* }
* ```
* `Action<HTMLDivElement>` and `Action<HTMLDiveElement, never>` both signal that the action accepts no parameters.
*
* You can return an object with methods `update` and `destroy` from the function and type which additional attributes and events it has.
* See interface `ActionReturn` for more details.
*
@ -59,18 +56,11 @@ export interface ActionReturn<
*/
export interface Action<
Element = HTMLElement,
Parameter = never,
Parameter = any,
Attributes extends Record<string, any> = Record<never, any>
> {
<Node extends Element>(
...args: [Parameter] extends [never]
? [node: Node]
: undefined extends Parameter
? [node: Node, parameter?: Parameter]
: [node: Node, parameter: Parameter]
): void | ActionReturn<Parameter, Attributes>;
<Node extends Element>(node: Node, parameter?: Parameter): void | ActionReturn<
Parameter,
Attributes
>;
}
// Implementation notes:
// - undefined extends X instead of X extends undefined makes this work better with both strict and nonstrict mode
// - [X] extends [never] is needed, X extends never would reduce the whole resulting type to never and not to one of the condition outcomes

@ -4,8 +4,8 @@ import { is_function } from '../internal/index.js';
/**
* @param {Element} node
* @param {{ from: DOMRect; to: DOMRect }} fromTo
* @param {import('.').FlipParams} params
* @returns {import('.').AnimationConfig}
* @param {import('./public.js').FlipParams} params
* @returns {import('./public.js').AnimationConfig}
*/
export function flip(node, { from, to }, params = {}) {
const style = getComputedStyle(node);

@ -1,4 +1,3 @@
import './ambient.js';
export {
onMount,
onDestroy,

@ -95,7 +95,7 @@ export function init(
) {
const parent_component = current_component;
set_current_component(component);
/** @type {import('./public.d.ts').T$$} */
/** @type {import('./private.js').T$$} */
const $$ = (component.$$ = {
fragment: null,
ctx: [],
@ -352,7 +352,7 @@ function get_custom_element_value(prop, value, props_definition, transform) {
* @internal
*
* Turn a Svelte component into a custom element.
* @param {import('./public.d.ts').ComponentType} Component A Svelte component constructor
* @param {import('./public.js').ComponentType} Component A Svelte component constructor
* @param {Record<string, CustomElementPropDefinition>} props_definition The props to observe
* @param {string[]} slots The slots to create
* @param {string[]} accessors Other accessors besides the ones for props the component has

@ -6,14 +6,30 @@ import { globals } from './globals.js';
* https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ
*/
export class ResizeObserverSingleton {
/**
* @private
* @readonly
* @type {WeakMap<Element, import('./private.js').Listener>}
*/
_listeners = 'WeakMap' in globals ? new WeakMap() : undefined;
/**
* @private
* @type {ResizeObserver}
*/
_observer = undefined;
/** @type {ResizeObserverOptions} */
options;
/** @param {ResizeObserverOptions} options */
constructor(options) {
this.options = options;
}
/**
* @param {Element} element
* @param {import('./private.d.ts').Listener} listener
* @param {import('./private.js').Listener} listener
* @returns {() => void}
*/
observe(element, listener) {
@ -27,16 +43,6 @@ export class ResizeObserverSingleton {
/**
* @private
* @readonly
* @default 'WeakMap' in globals ? new WeakMap() : undefined
*/
_listeners = 'WeakMap' in globals ? new WeakMap() : undefined;
/** @private */
_observer = undefined;
/** @private
* @returns {ResizeObserver}
*/
_getObserver() {
return (

@ -5,8 +5,8 @@ import { create_rule, delete_rule } from './style_manager.js';
/**
* @param {Element & ElementCSSInlineStyle} node
* @param {import('./private.d.ts').PositionRect} from
* @param {import('./private.d.ts').AnimationFn} fn
* @param {import('./private.js').PositionRect} from
* @param {import('./private.js').AnimationFn} fn
* @returns {any}
*/
export function create_animation(node, from, fn, params) {
@ -88,7 +88,7 @@ export function fix_position(node) {
/**
* @param {Element & ElementCSSInlineStyle} node
* @param {import('./private.d.ts').PositionRect} a
* @param {import('./private.js').PositionRect} a
* @returns {void}
*/
export function add_transform(node, a) {

@ -6,13 +6,13 @@ import { get_current_component, set_current_component } from './lifecycle.js';
/**
* @template T
* @param {Promise<T>} promise
* @param {import('./private.d.ts').PromiseInfo<T>} info
* @param {import('./private.js').PromiseInfo<T>} info
* @returns {boolean}
*/
export function handle_promise(promise, info) {
const token = (info.token = {});
/**
* @param {import('./public.d.ts').FragmentFactory} type
* @param {import('./private.js').FragmentFactory} type
* @param {0 | 1 | 2} index
* @param {number} [key]
* @param {any} [value]

@ -294,9 +294,9 @@ export function construct_svelte_component_dev(component, props) {
* </script>
* <MyComponent foo={'bar'} />
* ```
* @template {Record<string, any>} Props
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
* @template {Record<string, any>} [Props=any]
* @template {Record<string, any>} [Events=any]
* @template {Record<string, any>} [Slots=any]
* @extends SvelteComponent
*/
export class SvelteComponentDev extends SvelteComponent {
@ -325,6 +325,7 @@ export class SvelteComponentDev extends SvelteComponent {
/** @type {Slots} */
$$slot_def = undefined;
/** @param {import('./public.js').ComponentConstructorOptions<Props>} options */
constructor(options) {
if (!options || (!options.target && !options.$$inline)) {
throw new Error("'target' is a required option");
@ -347,9 +348,9 @@ export class SvelteComponentDev extends SvelteComponent {
$inject_state() {}
}
/**
* @template {Record<string, any>} Props
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
* @template {Record<string, any>} [Props=any]
* @template {Record<string, any>} [Events=any]
* @template {Record<string, any>} [Slots=any]
* @deprecated Use `SvelteComponent` instead. See PR for more information: https://github.com/sveltejs/svelte/pull/8512
* @extends SvelteComponentDev<Props, Events, Slots>
*/

@ -1,3 +1,8 @@
/** @type {typeof globalThis} */
export const globals =
typeof window !== 'undefined' ? window : typeof globalThis !== 'undefined' ? globalThis : global;
typeof window !== 'undefined'
? window
: typeof globalThis !== 'undefined'
? globalThis
: // @ts-ignore Node typings have this
global;

@ -92,7 +92,7 @@ export function onDestroy(fn) {
*
* https://svelte.dev/docs#run-time-svelte-createeventdispatcher
* @template {Record<string, any>} EventMap
* @returns {import('./public.d.ts').EventDispatcher<EventMap>}
* @returns {import('./public.js').EventDispatcher<EventMap>}
*/
export function createEventDispatcher() {
const component = get_current_component();
@ -120,6 +120,7 @@ export function createEventDispatcher() {
*
* https://svelte.dev/docs#run-time-svelte-setcontext
* @template T
* @param {string} key
* @param {T} context
* @returns {T}
*/
@ -134,6 +135,7 @@ export function setContext(key, context) {
*
* https://svelte.dev/docs#run-time-svelte-getcontext
* @template T
* @param {string} key
* @returns {T}
*/
export function getContext(key) {
@ -146,7 +148,7 @@ export function getContext(key) {
* programmatically create a component and want to pass the existing context to it.
*
* https://svelte.dev/docs#run-time-svelte-getallcontexts
* @template T
* @template {Map<any, any>} [T=Map<any, any>]
* @returns {T}
*/
export function getAllContexts() {
@ -158,6 +160,7 @@ export function getAllContexts() {
* Must be called during component initialisation.
*
* https://svelte.dev/docs#run-time-svelte-hascontext
* @param {string} key
* @returns {boolean}
*/
export function hasContext(key) {
@ -167,7 +170,11 @@ export function hasContext(key) {
// TODO figure out if we still want to support
// shorthand events, or if we want to implement
// a real bubbling mechanism
/** @returns {void} */
/**
* @param component
* @param event
* @returns {void}
*/
export function bubble(component, event) {
const callbacks = component.$$.callbacks[event.type];
if (callbacks) {

@ -27,11 +27,11 @@ export function clear_loops() {
/**
* Creates a new task that runs on each raf frame
* until it returns a falsy value or is aborted
* @param {import('./private.d.ts').TaskCallback} callback
* @returns {import('./public.d.ts').Task}
* @param {import('./private.js').TaskCallback} callback
* @returns {import('./private.js').Task}
*/
export function loop(callback) {
/** @type {import('./private.d.ts').TaskEntry} */
/** @type {import('./private.js').TaskEntry} */
let task;
if (tasks.size === 0) raf(run_tasks);
return {

@ -1,5 +1,4 @@
import type { AnimationConfig } from '../animate';
import type { Fragment, FragmentFactory } from './public';
import type { AnimationConfig } from '../animate/public.js';
export type AnimationFn = (
node: Element,
@ -7,7 +6,7 @@ export type AnimationFn = (
params: any
) => AnimationConfig;
type Listener = (entry: ResizeObserverEntry) => any;
export type Listener = (entry: ResizeObserverEntry) => any;
//todo: documentation says it is DOMRect, but in IE it would be ClientRect
export type PositionRect = DOMRect | ClientRect;
@ -79,3 +78,48 @@ export interface StyleInformation {
export type TaskCallback = (now: number) => boolean | void;
export type TaskEntry = { c: TaskCallback; f: () => void };
/**
* INTERNAL, DO NOT USE. Code may change at any time.
*/
export interface Fragment {
key: string | null;
first: null;
/* create */ c: () => void;
/* claim */ l: (nodes: any) => void;
/* hydrate */ h: () => void;
/* mount */ m: (target: HTMLElement, anchor: any) => void;
/* update */ p: (ctx: T$$['ctx'], dirty: T$$['dirty']) => void;
/* measure */ r: () => void;
/* fix */ f: () => void;
/* animate */ a: () => void;
/* intro */ i: (local: any) => void;
/* outro */ o: (local: any) => void;
/* destroy */ d: (detaching: 0 | 1) => void;
}
export type FragmentFactory = (ctx: any) => Fragment;
export interface T$$ {
dirty: number[];
ctx: any[];
bound: any;
update: () => void;
callbacks: any;
after_update: any[];
props: Record<string, 0 | string>;
fragment: null | false | Fragment;
not_equal: any;
before_update: any[];
context: Map<any, any>;
on_mount: any[];
on_destroy: any[];
skip_bound: boolean;
on_disconnect: any[];
root: Element | ShadowRoot;
}
export interface Task {
abort(): void;
promise: Promise<void>;
}

@ -1,4 +1,4 @@
import type { SvelteComponent } from './Component';
import type { SvelteComponent } from './Component.js';
export interface ComponentConstructorOptions<
Props extends Record<string, any> = Record<string, any>
@ -91,27 +91,6 @@ export interface EventDispatcher<EventMap extends Record<string, any>> {
): boolean;
}
/**
* INTERNAL, DO NOT USE. Code may change at any time.
*/
export interface Fragment {
key: string | null;
first: null;
/* create */ c: () => void;
/* claim */ l: (nodes: any) => void;
/* hydrate */ h: () => void;
/* mount */ m: (target: HTMLElement, anchor: any) => void;
/* update */ p: (ctx: T$$['ctx'], dirty: T$$['dirty']) => void;
/* measure */ r: () => void;
/* fix */ f: () => void;
/* animate */ a: () => void;
/* intro */ i: (local: any) => void;
/* outro */ o: (local: any) => void;
/* destroy */ d: (detaching: 0 | 1) => void;
}
export type FragmentFactory = (ctx: any) => Fragment;
export interface SvelteComponentDev<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
@ -126,33 +105,9 @@ export interface SvelteComponentDev<
[accessor: string]: any;
}
export interface T$$ {
dirty: number[];
ctx: any[];
bound: any;
update: () => void;
callbacks: any;
after_update: any[];
props: Record<string, 0 | string>;
fragment: null | false | Fragment;
not_equal: any;
before_update: any[];
context: Map<any, any>;
on_mount: any[];
on_destroy: any[];
skip_bound: boolean;
on_disconnect: any[];
root: Element | ShadowRoot;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface SvelteComponentTyped<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any
> extends SvelteComponentDev<Props, Events, Slots> {}
export interface Task {
abort(): void;
promise: Promise<void>;
}

@ -60,7 +60,7 @@ export function check_outros() {
}
/**
* @param {import('./public.js').Fragment} block
* @param {import('./private.js').Fragment} block
* @param {0 | 1} [local]
* @returns {void}
*/
@ -72,7 +72,7 @@ export function transition_in(block, local) {
}
/**
* @param {import('./public.js').Fragment} block
* @param {import('./private.js').Fragment} block
* @param {0 | 1} local
* @param {0 | 1} detach
* @returns {void}
@ -95,7 +95,7 @@ export function transition_out(block, local, detach, callback) {
}
/**
* @type {import('types/transition').TransitionConfig}
* @type {import('../transition/public.js').TransitionConfig}
*/
const null_transition = { duration: 0 };
@ -401,7 +401,7 @@ export function create_bidirectional_transition(node, fn, params, intro) {
/** @typedef {1} INTRO */
/** @typedef {0} OUTRO */
/** @typedef {{ direction: 'in' | 'out' | 'both' }} TransitionOptions */
/** @typedef {(node: Element, params: any, options: TransitionOptions) => import('types/transition').TransitionConfig} TransitionFn */
/** @typedef {(node: Element, params: any, options: TransitionOptions) => import('../transition/public.js').TransitionConfig} TransitionFn */
/**
* @typedef {Object} Outro

@ -112,7 +112,7 @@ export function subscribe(store, ...callbacks) {
/**
* @template T
* @param {import('../store').Readable<T>} store
* @param {import('../store/public.js').Readable<T>} store
* @returns {T}
*/
export function get_store_value(store) {

@ -0,0 +1,28 @@
import { Spring } from './public';
export interface TickContext<T> {
inv_mass: number;
dt: number;
opts: Spring<T>;
settled: boolean;
}
export interface SpringOpts {
stiffness?: number;
damping?: number;
precision?: number;
}
export interface SpringUpdateOpts {
hard?: any;
soft?: string | number | boolean;
}
export type Updater<T> = (target_value: T, value: T) => T;
export interface TweenedOptions<T> {
delay?: number;
duration?: number | ((from: T, to: T) => number);
easing?: (t: number) => number;
interpolate?: (a: T, b: T) => (t: number) => T;
}

@ -0,0 +1,15 @@
import { Readable } from '../store/public.js';
import { SpringUpdateOpts, TweenedOptions, Updater } from './private';
export interface Spring<T> extends Readable<T> {
set: (new_value: T, opts?: SpringUpdateOpts) => Promise<void>;
update: (fn: Updater<T>, opts?: SpringUpdateOpts) => Promise<void>;
precision: number;
damping: number;
stiffness: number;
}
export interface Tweened<T> extends Readable<T> {
set(value: T, opts?: TweenedOptions<T>): Promise<void>;
update(updater: Updater<T>, opts?: TweenedOptions<T>): Promise<void>;
}

@ -3,7 +3,8 @@ import { loop, now } from '../internal/index.js';
import { is_date } from './utils.js';
/**
* @param {TickContext<T>} ctx
* @template T
* @param {import('./private.js').TickContext<T>} ctx
* @param {T} last_value
* @param {T} current_value
* @param {T} target_value
@ -45,16 +46,17 @@ function tick_spring(ctx, last_value, current_value, target_value) {
}
/**
* @template T
* @param {T} value
* @param {SpringOpts} opts
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/spring.ts-to-jsdoc").Spring<T>}
* @param {import('./private.js').SpringOpts} opts
* @returns {import('./public.js').Spring<T>}
*/
export function spring(value, opts = {}) {
const store = writable(value);
const { stiffness = 0.15, damping = 0.8, precision = 0.01 } = opts;
/** @type {number} */
let last_time;
/** @type {Task} */
/** @type {import('../internal/private.js').Task} */
let task;
/** @type {object} */
let current_token;
@ -65,8 +67,9 @@ export function spring(value, opts = {}) {
let inv_mass = 1;
let inv_mass_recovery_rate = 0;
let cancel_task = false;
/** @param {T} new_value
* @param {SpringUpdateOpts} opts
/**
* @param {T} new_value
* @param {import('./private.js').SpringUpdateOpts} opts
* @returns {Promise<void>}
*/
function set(new_value, opts = {}) {
@ -115,7 +118,7 @@ export function spring(value, opts = {}) {
});
});
}
/** @type {Spring<T>} */
/** @type {import('./public.js').Spring<T>} */
const spring = {
set,
update: (fn, opts) => set(fn(target_value, value), opts),
@ -126,38 +129,3 @@ export function spring(value, opts = {}) {
};
return spring;
}
/**
* @typedef {(target_value: T, value: T) => T} Updater
* @template T
*/
/**
* @typedef {Object} TickContext
* @property {number} inv_mass
* @property {number} dt
* @property {Spring<T>} opts
* @property {boolean} settled
*/
/**
* @typedef {Object} SpringOpts
* @property {number} [stiffness]
* @property {number} [damping]
* @property {number} [precision]
*/
/**
* @typedef {Object} SpringUpdateOpts
* @property {any} [hard]
* @property {string|number|boolean} [soft]
*/
/**
* @typedef {Object} Spring
* @property {(new_value:T,opts?:SpringUpdateOpts)=>Promise<void>} set
* @property {(fn:Updater<T>,opts?:SpringUpdateOpts)=>Promise<void>} update
* @property {number} precision
* @property {number} damping
* @property {number} stiffness
*/

@ -45,18 +45,19 @@ function get_interpolator(a, b) {
}
/**
* @template T
* @param {T} value
* @param {Options<T>} defaults
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/tweened.ts-to-jsdoc").Tweened<T>}
* @param {import('./private.js').TweenedOptions<T>} defaults
* @returns {import('./public.js').Tweened<T>}
*/
export function tweened(value, defaults = {}) {
const store = writable(value);
/** @type {Task} */
/** @type {import('../internal/private.js').Task} */
let task;
let target_value = value;
/**
* @param {T} new_value
* @param {Options<T>} opts
* @param {import('./private.js').TweenedOptions<T>} opts
* @returns {any}
*/
function set(new_value, opts) {
@ -95,7 +96,7 @@ export function tweened(value, defaults = {}) {
previous_task = null;
}
const elapsed = now - start;
if (elapsed > duration) {
if (elapsed > /** @type {number} */ (duration)) {
store.set((value = new_value));
return false;
}
@ -111,17 +112,3 @@ export function tweened(value, defaults = {}) {
subscribe: store.subscribe
};
}
/**
* @typedef {(target_value: T, value: T) => T} Updater
* @template T
*/
/**
* @typedef {Object} Options
* @property {number} [delay]
* @property {number|((from:T,to:T)=>number)} [duration]
* @property {(t:number)=>number} [easing]
* @property {(a:T,b:T)=>(t:number)=>T} [interpolate]
*/
/** @typedef {Object} Tweened */

@ -11,9 +11,10 @@ const subscriber_queue = [];
/**
* Creates a `Readable` store that allows reading by subscription.
* @param {T} value initial value
* @param {StartStopNotifier<T>} start undefined
* @returns {Readable<T>}
* @template T
* @param {T} value initial value
* @param {import('./public.js').StartStopNotifier<T>} start
* @returns {import('./public.js').Readable<T>}
*/
export function readable(value, start) {
return {
@ -23,14 +24,15 @@ export function readable(value, start) {
/**
* Create a `Writable` store that allows both updating and reading by subscription.
* @param {T} value initial value
* @param {StartStopNotifier<T>} start undefined
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").Writable<T>}
* @template T
* @param {T} value initial value
* @param {import('./public.js').StartStopNotifier<T>} start
* @returns {import('./public.js').Writable<T>}
*/
export function writable(value, start = noop) {
/** @type {Unsubscriber} */
/** @type {import('./public.js').Unsubscriber} */
let stop;
/** @type {Set<SubscribeInvalidateTuple<T>>} */
/** @type {Set<import('./public.js').SubscribeInvalidateTuple<T>>} */
const subscribers = new Set();
/** @param {T} new_value
* @returns {void}
@ -55,19 +57,19 @@ export function writable(value, start = noop) {
}
}
/**
* @param {Updater<T>} fn
* @param {import('./public.js').Updater<T>} fn
* @returns {void}
*/
function update(fn) {
set(fn(value));
}
/**
* @param {Subscriber<T>} run
* @param {Invalidator<T>} invalidate
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").Unsubscriber}
* @param {import('./public.js').Subscriber<T>} run
* @param {import('./public.js').Invalidator<T>} invalidate
* @returns {import('./public.js').Unsubscriber}
*/
function subscribe(run, invalidate = noop) {
/** @type {SubscribeInvalidateTuple<T>} */
/** @type {import('./public.js').SubscribeInvalidateTuple<T>} */
const subscriber = [run, invalidate];
subscribers.add(subscriber);
if (subscribers.size === 1) {
@ -86,14 +88,42 @@ export function writable(value, start = noop) {
}
/**
* @param {Stores} stores
* Derived value store by synchronizing one or more readable stores and
* applying an aggregation function over its input values.
*
* @template {import('./public.js').Stores} S
* @template T
* @overload
* @param {S} stores - input stores
* @param {(values: import('./public.js').StoresValues<S>, set: import('./public.js').Subscriber<T>, update: (fn: import('./public.js').Updater<T>) => void) => import('./public.js').Unsubscriber | void} fn - function callback that aggregates the values
* @param {T} [initial_value] - initial value
* @returns {import('./public.js').Readable<T>}
*/
/**
* Derived value store by synchronizing one or more readable stores and
* applying an aggregation function over its input values.
*
* @template {import('./public.js').Stores} S
* @template T
* @overload
* @param {S} stores - input stores
* @param {(values: import('./public.js').StoresValues<S>) => T} fn - function callback that aggregates the values
* @param {T} [initial_value] - initial value
* @returns {import('./public.js').Readable<T>}
*/
/**
* @template {import('./public.js').Stores} S
* @template T
* @param {S} stores
* @param {Function} fn
* @param {T} initial_value
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").Readable<T>}
* @param {T} [initial_value]
* @returns {import('./public.js').Readable<T>}
*/
export function derived(stores, fn, initial_value) {
const single = !Array.isArray(stores);
/** @type {Array<Readable<any>>} */
/** @type {Array<import('./public.js').Readable<any>>} */
const stores_array = single ? [stores] : stores;
if (!stores_array.every(Boolean)) {
throw new Error('derived() expects stores as input, got a falsy value');
@ -147,8 +177,9 @@ export function derived(stores, fn, initial_value) {
/**
* Takes a store and returns a new one derived from the old one that is readable.
*
* @param {Readable<T>} store - store to make readonly
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").Readable<T>}
* @template T
* @param {import('./public.js').Readable<T>} store - store to make readonly
* @returns {import('./public.js').Readable<T>}
*/
export function readonly(store) {
return {
@ -158,55 +189,8 @@ export function readonly(store) {
/**
* Get the current value from a store by subscribing and immediately unsubscribing.
* @param store readable
*/
export { get_store_value as get };
/**
* @typedef {(value: T) => void} Subscriber
* @template T
* @param {import('./public.js').Readable<T>} store readable
* @returns {T}
*/
/** @typedef {() => void} Unsubscriber */
/**
* @typedef {(value: T) => T} Updater
* @template T
*/
/**
* @typedef {(value?: T) => void} Invalidator
* @template T
*/
/**
* @typedef {(
* set: (value: T) => void,
* update: (fn: Updater<T>) => void
* ) => void | (() => void)} StartStopNotifier
* @template T
*/
/**
* @typedef {[Subscriber<T>, Invalidator<T>]} SubscribeInvalidateTuple
* @template T
*/
/** @typedef {Readable<any> | [Readable<any>, ...Array<Readable<any>>] | Array<Readable<any>>} Stores */
/**
* @typedef {T extends Readable<infer U>
* ? U
* : { [K in keyof T]: T[K] extends Readable<infer U> ? U : never }} StoresValues
* @template T
*/
/**
* Readable interface for subscribing.
* @typedef {Object} Readable
*/
/**
* Writable interface for both updating and subscribing.
* @typedef {Object} Writable
*/
export { get_store_value as get };

@ -0,0 +1,61 @@
/** Callback to inform of a value updates. */
export type Subscriber<T> = (value: T) => void;
/** Unsubscribes from value updates. */
export type Unsubscriber = () => void;
/** Callback to update a value. */
export type Updater<T> = (value: T) => T;
/** Cleanup logic callback. */
type Invalidator<T> = (value?: T) => void;
/**
* Start and stop notification callbacks.
* This function is called when the first subscriber subscribes.
*
* @param {(value: T) => void} set Function that sets the value of the store.
* @param {(value: Updater<T>) => void} set Function that sets the value of the store after passing the current value to the update function.
* @returns {void | (() => void)} Optionally, a cleanup function that is called when the last remaining
* subscriber unsubscribes.
*/
export type StartStopNotifier<T> = (
set: (value: T) => void,
update: (fn: Updater<T>) => void
) => void | (() => void);
/** Readable interface for subscribing. */
export interface Readable<T> {
/**
* Subscribe on value changes.
* @param run subscription callback
* @param invalidate cleanup callback
*/
subscribe(this: void, run: Subscriber<T>, invalidate?: Invalidator<T>): Unsubscriber;
}
/** Writable interface for both updating and subscribing. */
export interface Writable<T> extends Readable<T> {
/**
* Set value and inform subscribers.
* @param value to set
*/
set(this: void, value: T): void;
/**
* Update value using callback and inform subscribers.
* @param updater callback
*/
update(this: void, updater: Updater<T>): void;
}
/** Pair of subscriber and invalidator. */
type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidator<T>];
/** One or more `Readable`s. */
type Stores = Readable<any> | [Readable<any>, ...Array<Readable<any>>] | Array<Readable<any>>;
/** One or more values from `Readable` stores. */
type StoresValues<T> = T extends Readable<infer U>
? U
: { [K in keyof T]: T[K] extends Readable<infer U> ? U : never };

@ -3,8 +3,8 @@ import { assign, split_css_unit, is_function } from '../internal';
/**
* @param {Element} node
* @param {BlurParams}
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @param {import('./public').BlurParams} [params]
* @returns {import('./public').TransitionConfig}
*/
export function blur(
node,
@ -25,8 +25,8 @@ export function blur(
/**
* @param {Element} node
* @param {FadeParams}
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @param {import('./public').FadeParams} [params]
* @returns {import('./public').TransitionConfig}
*/
export function fade(node, { delay = 0, duration = 400, easing = linear } = {}) {
const o = +getComputedStyle(node).opacity;
@ -40,8 +40,8 @@ export function fade(node, { delay = 0, duration = 400, easing = linear } = {})
/**
* @param {Element} node
* @param {FlyParams}
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @param {import('./public').FlyParams} [params]
* @returns {import('./public').TransitionConfig}
*/
export function fly(
node,
@ -65,8 +65,8 @@ export function fly(
/**
* @param {Element} node
* @param {SlideParams}
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @param {import('./public').SlideParams} [params]
* @returns {import('./public').TransitionConfig}
*/
export function slide(node, { delay = 0, duration = 400, easing = cubicOut, axis = 'y' } = {}) {
const style = getComputedStyle(node);
@ -106,8 +106,8 @@ export function slide(node, { delay = 0, duration = 400, easing = cubicOut, axis
/**
* @param {Element} node
* @param {ScaleParams}
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @param {import('./public').ScaleParams} [params]
* @returns {import('./public').TransitionConfig}
*/
export function scale(
node,
@ -131,8 +131,8 @@ export function scale(
/**
* @param {SVGElement & { getTotalLength(): number }} node
* @param {DrawParams}
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @param {import('./public').DrawParams} [params]
* @returns {import('./public').TransitionConfig}
*/
export function draw(node, { delay = 0, speed, duration, easing = cubicInOut } = {}) {
let len = node.getTotalLength();
@ -161,21 +161,21 @@ export function draw(node, { delay = 0, speed, duration, easing = cubicInOut } =
}
/**
* @param {CrossfadeParams & {
* fallback?: (node: Element, params: CrossfadeParams, intro: boolean) => TransitionConfig;
* }}
* @returns {[(node: any, params: import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").CrossfadeParams & { key: any; }) => () => import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig, (node: any, params: import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").CrossfadeParams & { key: any; }) => () => import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig]}
* @param {import('./public').CrossfadeParams & {
* fallback?: (node: Element, params: import('./public').CrossfadeParams, intro: boolean) => import('./public').TransitionConfig;
* }} params
* @returns {[(node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig, (node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig]}
*/
export function crossfade({ fallback, ...defaults }) {
/** @type {ClientRectMap} */
/** @type {Map<any, Element>} */
const to_receive = new Map();
/** @type {ClientRectMap} */
/** @type {Map<any, Element>} */
const to_send = new Map();
/**
* @param {Element} from_node
* @param {Element} node
* @param {CrossfadeParams} params
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @param {import('./public').CrossfadeParams} params
* @returns {import('./public').TransitionConfig}
*/
function crossfade(from_node, node, params) {
const {
@ -208,10 +208,10 @@ export function crossfade({ fallback, ...defaults }) {
}
/**
* @param {ClientRectMap} items
* @param {ClientRectMap} counterparts
* @param {Map<any, Element>} items
* @param {Map<any, Element>} counterparts
* @param {boolean} intro
* @returns {(node: any, params: import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").CrossfadeParams & { key: any; }) => () => import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
* @returns {(node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig}
*/
function transition(items, counterparts, intro) {
return (node, params) => {
@ -232,73 +232,3 @@ export function crossfade({ fallback, ...defaults }) {
}
return [transition(to_send, to_receive, false), transition(to_receive, to_send, true)];
}
/** @typedef {(t: number) => number} EasingFunction */
/** @typedef {Map<any, Element>} ClientRectMap */
/**
* @typedef {Object} TransitionConfig
* @property {number} [delay]
* @property {number} [duration]
* @property {EasingFunction} [easing]
* @property {(t:number,u:number)=>string} [css]
* @property {(t:number,u:number)=>void} [tick]
*/
/**
* @typedef {Object} BlurParams
* @property {number} [delay]
* @property {number} [duration]
* @property {EasingFunction} [easing]
* @property {number|string} [amount]
* @property {number} [opacity]
*/
/**
* @typedef {Object} FadeParams
* @property {number} [delay]
* @property {number} [duration]
* @property {EasingFunction} [easing]
*/
/**
* @typedef {Object} FlyParams
* @property {number} [delay]
* @property {number} [duration]
* @property {EasingFunction} [easing]
* @property {number|string} [x]
* @property {number|string} [y]
* @property {number} [opacity]
*/
/**
* @typedef {Object} SlideParams
* @property {number} [delay]
* @property {number} [duration]
* @property {EasingFunction} [easing]
* @property {'x'|'y'} [axis]
*/
/**
* @typedef {Object} ScaleParams
* @property {number} [delay]
* @property {number} [duration]
* @property {EasingFunction} [easing]
* @property {number} [start]
* @property {number} [opacity]
*/
/**
* @typedef {Object} DrawParams
* @property {number} [delay]
* @property {number} [speed]
* @property {number|((len:number)=>number)} [duration]
* @property {EasingFunction} [easing]
*/
/**
* @typedef {Object} CrossfadeParams
* @property {number} [delay]
* @property {number|((len:number)=>number)} [duration]
* @property {EasingFunction} [easing]
*/

@ -0,0 +1,60 @@
export type EasingFunction = (t: number) => number;
export interface TransitionConfig {
delay?: number;
duration?: number;
easing?: EasingFunction;
css?: (t: number, u: number) => string;
tick?: (t: number, u: number) => void;
}
export interface BlurParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
amount?: number | string;
opacity?: number;
}
export interface FadeParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
}
export interface FlyParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
x?: number | string;
y?: number | string;
opacity?: number;
}
export interface SlideParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
axis?: 'x' | 'y';
}
export interface ScaleParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
start?: number;
opacity?: number;
}
export interface DrawParams {
delay?: number;
speed?: number;
duration?: number | ((len: number) => number);
easing?: EasingFunction;
}
export interface CrossfadeParams {
delay?: number;
duration?: number | ((len: number) => number);
easing?: EasingFunction;
}

@ -15,6 +15,9 @@
"noEmitOnError": true,
"noErrorTruncation": true,
"allowJs": true,
"checkJs": true,
// rollup takes care of these
"module": "esnext",
"moduleResolution": "node",

Loading…
Cancel
Save