import { custom_event } from './dom.js'; export let current_component; /** @returns {void} */ export function set_current_component(component) { current_component = component; } export function get_current_component() { if (!current_component) throw new Error('Function called outside component initialization'); return current_component; } /** * Schedules a callback to run immediately before the component is updated after any state change. * * The first time the callback runs will be before the initial `onMount` * * https://svelte.dev/docs/svelte#beforeupdate * @param {() => any} fn * @returns {void} */ export function beforeUpdate(fn) { get_current_component().$$.before_update.push(fn); } /** * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. * It must be called during the component's initialisation (but doesn't need to live *inside* the component; * it can be called from an external module). * * If a function is returned _synchronously_ from `onMount`, it will be called when the component is unmounted. * * `onMount` does not run inside a [server-side component](https://svelte.dev/docs#run-time-server-side-component-api). * * https://svelte.dev/docs/svelte#onmount * @template T * @param {() => import('./private.js').NotFunction | Promise> | (() => any)} fn * @returns {void} */ export function onMount(fn) { get_current_component().$$.on_mount.push(fn); } /** * Schedules a callback to run immediately after the component has been updated. * * The first time the callback runs will be after the initial `onMount` * * https://svelte.dev/docs/svelte#afterupdate * @param {() => any} fn * @returns {void} */ export function afterUpdate(fn) { get_current_component().$$.after_update.push(fn); } /** * Schedules a callback to run immediately before the component is unmounted. * * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the * only one that runs inside a server-side component. * * https://svelte.dev/docs/svelte#ondestroy * @param {() => any} fn * @returns {void} */ export function onDestroy(fn) { get_current_component().$$.on_destroy.push(fn); } /** * Creates an event dispatcher that can be used to dispatch [component events](https://svelte.dev/docs#template-syntax-component-directives-on-eventname). * Event dispatchers are functions that can take two arguments: `name` and `detail`. * * Component events created with `createEventDispatcher` create a * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture). * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) * property and can contain any type of data. * * The event dispatcher can be typed to narrow the allowed event names and the type of the `detail` argument: * ```ts * const dispatch = createEventDispatcher<{ * loaded: never; // does not take a detail argument * change: string; // takes a detail argument of type string, which is required * optional: number | null; // takes an optional detail argument of type number * }>(); * ``` * * https://svelte.dev/docs/svelte#createeventdispatcher * @template {Record} [EventMap=any] * @returns {import('./public.js').EventDispatcher} */ export function createEventDispatcher() { const component = get_current_component(); return (type, detail, { cancelable = false } = {}) => { const callbacks = component.$$.callbacks[type]; if (callbacks) { // TODO are there situations where events could be dispatched // in a server (non-DOM) environment? const event = custom_event(/** @type {string} */ (type), detail, { cancelable }); callbacks.slice().forEach((fn) => { fn.call(component, event); }); return !event.defaultPrevented; } return true; }; } /** * Associates an arbitrary `context` object with the current component and the specified `key` * and returns that object. The context is then available to children of the component * (including slotted content) with `getContext`. * * Like lifecycle functions, this must be called during component initialisation. * * https://svelte.dev/docs/svelte#setcontext * @template T * @param {any} key * @param {T} context * @returns {T} */ export function setContext(key, context) { get_current_component().$$.context.set(key, context); return context; } /** * Retrieves the context that belongs to the closest parent component with the specified `key`. * Must be called during component initialisation. * * https://svelte.dev/docs/svelte#getcontext * @template T * @param {any} key * @returns {T} */ export function getContext(key) { return get_current_component().$$.context.get(key); } /** * Retrieves the whole context map that belongs to the closest parent component. * Must be called during component initialisation. Useful, for example, if you * programmatically create a component and want to pass the existing context to it. * * https://svelte.dev/docs/svelte#getallcontexts * @template {Map} [T=Map] * @returns {T} */ export function getAllContexts() { return get_current_component().$$.context; } /** * Checks whether a given `key` has been set in the context of a parent component. * Must be called during component initialisation. * * https://svelte.dev/docs/svelte#hascontext * @param {any} key * @returns {boolean} */ export function hasContext(key) { return get_current_component().$$.context.has(key); } // TODO figure out if we still want to support // shorthand events, or if we want to implement // a real bubbling mechanism /** * @param component * @param event * @returns {void} */ export function bubble(component, event) { const callbacks = component.$$.callbacks[event.type]; if (callbacks) { // @ts-ignore callbacks.slice().forEach((fn) => fn.call(this, event)); } }