import { add_render_callback, flush, intros, schedule_update } from './scheduler.js'; import { current_component, set_current_component } from './lifecycle.js' import { is_function, run, run_all, noop } from './utils.js'; import { blankObject } from './utils.js'; import { children } from './dom.js'; export function bind(component, name, callback) { component.$$.bound[name] = callback; callback(component.$$.ctx[name]); } export function mount_component(component, target, anchor) { const { fragment, on_mount, on_destroy, after_render } = component.$$; fragment[fragment.i ? 'i' : 'm'](target, anchor); // onMount happens after the initial afterUpdate. Because // afterUpdate callbacks happen in reverse order (inner first) // we schedule onMount callbacks before afterUpdate callbacks add_render_callback(() => { const new_on_destroy = on_mount.map(run).filter(is_function); if (on_destroy) { on_destroy.push(...new_on_destroy); } else { // Edge case — component was destroyed immediately, // most likely as a result of a binding initialising run_all(new_on_destroy); } component.$$.on_mount = []; }); after_render.forEach(add_render_callback); } function destroy(component, detach) { if (component.$$) { run_all(component.$$.on_destroy); component.$$.fragment.d(detach); // TODO null out other refs, including component.$$ (but need to // preserve final state?) component.$$.on_destroy = component.$$.fragment = null; component.$$.ctx = {}; } } function make_dirty(component, key) { if (!component.$$.dirty) { schedule_update(component); component.$$.dirty = {}; } component.$$.dirty[key] = true; } export function init(component, options, instance, create_fragment, not_equal) { const previous_component = current_component; set_current_component(component); const $$ = component.$$ = { fragment: null, ctx: null, // state set: noop, update: noop, not_equal, bound: blankObject(), // lifecycle on_mount: [], on_destroy: [], before_render: [], after_render: [], // everything else callbacks: blankObject(), slotted: options.slots || {}, dirty: null, binding_groups: [] }; let ready = false; $$.ctx = instance(component, options.props || {}, (key, value) => { if ($$.bound[key]) $$.bound[key](value); if ($$.ctx) { const changed = not_equal(value, $$.ctx[key]); if (ready && changed) { make_dirty(component, key); } $$.ctx[key] = value; return changed; } }); $$.update(); ready = true; run_all($$.before_render); $$.fragment = create_fragment($$, $$.ctx); if (options.target) { intros.enabled = !!options.intro; if (options.hydrate) { $$.fragment.l(children(options.target)); } else { $$.fragment.c(); } mount_component(component, options.target, options.anchor); flush(); intros.enabled = true; } set_current_component(previous_component); } export let SvelteElement; if (typeof HTMLElement !== 'undefined') { SvelteElement = class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } connectedCallback() { for (let key in this.$$.slotted) { this.appendChild(this.$$.slotted[key]); } } attributeChangedCallback(attr, oldValue, newValue) { this[attr] = newValue; } $destroy() { destroy(this, true); this.$destroy = noop; } $on(type, callback) { // TODO should this delegate to addEventListener? const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = [])); callbacks.push(callback); return () => { const index = callbacks.indexOf(callback); if (index !== -1) callbacks.splice(index, 1); }; } $set() { // overridden by instance, if it has props } } } export class SvelteComponent { $destroy() { destroy(this, true); this.$destroy = noop; } $on(type, callback) { const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = [])); callbacks.push(callback); return () => { const index = callbacks.indexOf(callback); if (index !== -1) callbacks.splice(index, 1); }; } $set() { // overridden by instance, if it has props } } export class SvelteComponentDev extends SvelteComponent { constructor(options) { if (!options || (!options.target && !options.$$inline)) { throw new Error(`'target' is a required option`); } super(); } $destroy() { super.$destroy(); this.$destroy = () => { console.warn(`Component was already destroyed`); }; } }