this repo has no description
1import { custom_event } from './dom.js';
2
3export let current_component;
4
5/** @returns {void} */
6export function set_current_component(component) {
7 current_component = component;
8}
9
10export function get_current_component() {
11 if (!current_component) throw new Error('Function called outside component initialization');
12 return current_component;
13}
14
15/**
16 * Schedules a callback to run immediately before the component is updated after any state change.
17 *
18 * The first time the callback runs will be before the initial `onMount`
19 *
20 * https://svelte.dev/docs/svelte#beforeupdate
21 * @param {() => any} fn
22 * @returns {void}
23 */
24export function beforeUpdate(fn) {
25 get_current_component().$$.before_update.push(fn);
26}
27
28/**
29 * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
30 * It must be called during the component's initialisation (but doesn't need to live *inside* the component;
31 * it can be called from an external module).
32 *
33 * If a function is returned _synchronously_ from `onMount`, it will be called when the component is unmounted.
34 *
35 * `onMount` does not run inside a [server-side component](https://svelte.dev/docs#run-time-server-side-component-api).
36 *
37 * https://svelte.dev/docs/svelte#onmount
38 * @template T
39 * @param {() => import('./private.js').NotFunction<T> | Promise<import('./private.js').NotFunction<T>> | (() => any)} fn
40 * @returns {void}
41 */
42export function onMount(fn) {
43 get_current_component().$$.on_mount.push(fn);
44}
45
46/**
47 * Schedules a callback to run immediately after the component has been updated.
48 *
49 * The first time the callback runs will be after the initial `onMount`
50 *
51 * https://svelte.dev/docs/svelte#afterupdate
52 * @param {() => any} fn
53 * @returns {void}
54 */
55export function afterUpdate(fn) {
56 get_current_component().$$.after_update.push(fn);
57}
58
59/**
60 * Schedules a callback to run immediately before the component is unmounted.
61 *
62 * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the
63 * only one that runs inside a server-side component.
64 *
65 * https://svelte.dev/docs/svelte#ondestroy
66 * @param {() => any} fn
67 * @returns {void}
68 */
69export function onDestroy(fn) {
70 get_current_component().$$.on_destroy.push(fn);
71}
72
73/**
74 * Creates an event dispatcher that can be used to dispatch [component events](https://svelte.dev/docs#template-syntax-component-directives-on-eventname).
75 * Event dispatchers are functions that can take two arguments: `name` and `detail`.
76 *
77 * Component events created with `createEventDispatcher` create a
78 * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent).
79 * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture).
80 * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail)
81 * property and can contain any type of data.
82 *
83 * The event dispatcher can be typed to narrow the allowed event names and the type of the `detail` argument:
84 * ```ts
85 * const dispatch = createEventDispatcher<{
86 * loaded: never; // does not take a detail argument
87 * change: string; // takes a detail argument of type string, which is required
88 * optional: number | null; // takes an optional detail argument of type number
89 * }>();
90 * ```
91 *
92 * https://svelte.dev/docs/svelte#createeventdispatcher
93 * @template {Record<string, any>} [EventMap=any]
94 * @returns {import('./public.js').EventDispatcher<EventMap>}
95 */
96export function createEventDispatcher() {
97 const component = get_current_component();
98 return (type, detail, { cancelable = false } = {}) => {
99 const callbacks = component.$$.callbacks[type];
100 if (callbacks) {
101 // TODO are there situations where events could be dispatched
102 // in a server (non-DOM) environment?
103 const event = custom_event(/** @type {string} */ (type), detail, { cancelable });
104 callbacks.slice().forEach((fn) => {
105 fn.call(component, event);
106 });
107 return !event.defaultPrevented;
108 }
109 return true;
110 };
111}
112
113/**
114 * Associates an arbitrary `context` object with the current component and the specified `key`
115 * and returns that object. The context is then available to children of the component
116 * (including slotted content) with `getContext`.
117 *
118 * Like lifecycle functions, this must be called during component initialisation.
119 *
120 * https://svelte.dev/docs/svelte#setcontext
121 * @template T
122 * @param {any} key
123 * @param {T} context
124 * @returns {T}
125 */
126export function setContext(key, context) {
127 get_current_component().$$.context.set(key, context);
128 return context;
129}
130
131/**
132 * Retrieves the context that belongs to the closest parent component with the specified `key`.
133 * Must be called during component initialisation.
134 *
135 * https://svelte.dev/docs/svelte#getcontext
136 * @template T
137 * @param {any} key
138 * @returns {T}
139 */
140export function getContext(key) {
141 return get_current_component().$$.context.get(key);
142}
143
144/**
145 * Retrieves the whole context map that belongs to the closest parent component.
146 * Must be called during component initialisation. Useful, for example, if you
147 * programmatically create a component and want to pass the existing context to it.
148 *
149 * https://svelte.dev/docs/svelte#getallcontexts
150 * @template {Map<any, any>} [T=Map<any, any>]
151 * @returns {T}
152 */
153export function getAllContexts() {
154 return get_current_component().$$.context;
155}
156
157/**
158 * Checks whether a given `key` has been set in the context of a parent component.
159 * Must be called during component initialisation.
160 *
161 * https://svelte.dev/docs/svelte#hascontext
162 * @param {any} key
163 * @returns {boolean}
164 */
165export function hasContext(key) {
166 return get_current_component().$$.context.has(key);
167}
168
169// TODO figure out if we still want to support
170// shorthand events, or if we want to implement
171// a real bubbling mechanism
172/**
173 * @param component
174 * @param event
175 * @returns {void}
176 */
177export function bubble(component, event) {
178 const callbacks = component.$$.callbacks[event.type];
179 if (callbacks) {
180 // @ts-ignore
181 callbacks.slice().forEach((fn) => fn.call(this, event));
182 }
183}