forked from off-topic/apps.apple.com
init commit
This commit is contained in:
524
node_modules/svelte/src/runtime/internal/Component.js
generated
vendored
Normal file
524
node_modules/svelte/src/runtime/internal/Component.js
generated
vendored
Normal file
@@ -0,0 +1,524 @@
|
||||
import {
|
||||
add_render_callback,
|
||||
flush,
|
||||
flush_render_callbacks,
|
||||
schedule_update,
|
||||
dirty_components
|
||||
} from './scheduler.js';
|
||||
import { current_component, set_current_component } from './lifecycle.js';
|
||||
import { blank_object, is_empty, is_function, run, run_all, noop } from './utils.js';
|
||||
import {
|
||||
children,
|
||||
detach,
|
||||
start_hydrating,
|
||||
end_hydrating,
|
||||
get_custom_elements_slots,
|
||||
insert,
|
||||
element,
|
||||
attr
|
||||
} from './dom.js';
|
||||
import { transition_in } from './transitions.js';
|
||||
|
||||
/** @returns {void} */
|
||||
export function bind(component, name, callback) {
|
||||
const index = component.$$.props[name];
|
||||
if (index !== undefined) {
|
||||
component.$$.bound[index] = callback;
|
||||
callback(component.$$.ctx[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/** @returns {void} */
|
||||
export function create_component(block) {
|
||||
block && block.c();
|
||||
}
|
||||
|
||||
/** @returns {void} */
|
||||
export function claim_component(block, parent_nodes) {
|
||||
block && block.l(parent_nodes);
|
||||
}
|
||||
|
||||
/** @returns {void} */
|
||||
export function mount_component(component, target, anchor) {
|
||||
const { fragment, after_update } = component.$$;
|
||||
fragment && fragment.m(target, anchor);
|
||||
// onMount happens before the initial afterUpdate
|
||||
add_render_callback(() => {
|
||||
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
||||
// if the component was destroyed immediately
|
||||
// it will update the `$$.on_destroy` reference to `null`.
|
||||
// the destructured on_destroy may still reference to the old array
|
||||
if (component.$$.on_destroy) {
|
||||
component.$$.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_update.forEach(add_render_callback);
|
||||
}
|
||||
|
||||
/** @returns {void} */
|
||||
export function destroy_component(component, detaching) {
|
||||
const $$ = component.$$;
|
||||
if ($$.fragment !== null) {
|
||||
flush_render_callbacks($$.after_update);
|
||||
run_all($$.on_destroy);
|
||||
$$.fragment && $$.fragment.d(detaching);
|
||||
// TODO null out other refs, including component.$$ (but need to
|
||||
// preserve final state?)
|
||||
$$.on_destroy = $$.fragment = null;
|
||||
$$.ctx = [];
|
||||
}
|
||||
}
|
||||
|
||||
/** @returns {void} */
|
||||
function make_dirty(component, i) {
|
||||
if (component.$$.dirty[0] === -1) {
|
||||
dirty_components.push(component);
|
||||
schedule_update();
|
||||
component.$$.dirty.fill(0);
|
||||
}
|
||||
component.$$.dirty[(i / 31) | 0] |= 1 << i % 31;
|
||||
}
|
||||
|
||||
// TODO: Document the other params
|
||||
/**
|
||||
* @param {SvelteComponent} component
|
||||
* @param {import('./public.js').ComponentConstructorOptions} options
|
||||
*
|
||||
* @param {import('./utils.js')['not_equal']} not_equal Used to compare props and state values.
|
||||
* @param {(target: Element | ShadowRoot) => void} [append_styles] Function that appends styles to the DOM when the component is first initialised.
|
||||
* This will be the `add_css` function from the compiled component.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function init(
|
||||
component,
|
||||
options,
|
||||
instance,
|
||||
create_fragment,
|
||||
not_equal,
|
||||
props,
|
||||
append_styles = null,
|
||||
dirty = [-1]
|
||||
) {
|
||||
const parent_component = current_component;
|
||||
set_current_component(component);
|
||||
/** @type {import('./private.js').T$$} */
|
||||
const $$ = (component.$$ = {
|
||||
fragment: null,
|
||||
ctx: [],
|
||||
// state
|
||||
props,
|
||||
update: noop,
|
||||
not_equal,
|
||||
bound: blank_object(),
|
||||
// lifecycle
|
||||
on_mount: [],
|
||||
on_destroy: [],
|
||||
on_disconnect: [],
|
||||
before_update: [],
|
||||
after_update: [],
|
||||
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
||||
// everything else
|
||||
callbacks: blank_object(),
|
||||
dirty,
|
||||
skip_bound: false,
|
||||
root: options.target || parent_component.$$.root
|
||||
});
|
||||
append_styles && append_styles($$.root);
|
||||
let ready = false;
|
||||
$$.ctx = instance
|
||||
? instance(component, options.props || {}, (i, ret, ...rest) => {
|
||||
const value = rest.length ? rest[0] : ret;
|
||||
if ($$.ctx && not_equal($$.ctx[i], ($$.ctx[i] = value))) {
|
||||
if (!$$.skip_bound && $$.bound[i]) $$.bound[i](value);
|
||||
if (ready) make_dirty(component, i);
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
: [];
|
||||
$$.update();
|
||||
ready = true;
|
||||
run_all($$.before_update);
|
||||
// `false` as a special case of no DOM component
|
||||
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
|
||||
if (options.target) {
|
||||
if (options.hydrate) {
|
||||
start_hydrating();
|
||||
// TODO: what is the correct type here?
|
||||
// @ts-expect-error
|
||||
const nodes = children(options.target);
|
||||
$$.fragment && $$.fragment.l(nodes);
|
||||
nodes.forEach(detach);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.c();
|
||||
}
|
||||
if (options.intro) transition_in(component.$$.fragment);
|
||||
mount_component(component, options.target, options.anchor);
|
||||
end_hydrating();
|
||||
flush();
|
||||
}
|
||||
set_current_component(parent_component);
|
||||
}
|
||||
|
||||
export let SvelteElement;
|
||||
|
||||
if (typeof HTMLElement === 'function') {
|
||||
SvelteElement = class extends HTMLElement {
|
||||
/** The Svelte component constructor */
|
||||
$$ctor;
|
||||
/** Slots */
|
||||
$$s;
|
||||
/** The Svelte component instance */
|
||||
$$c;
|
||||
/** Whether or not the custom element is connected */
|
||||
$$cn = false;
|
||||
/** Component props data */
|
||||
$$d = {};
|
||||
/** `true` if currently in the process of reflecting component props back to attributes */
|
||||
$$r = false;
|
||||
/** @type {Record<string, CustomElementPropDefinition>} Props definition (name, reflected, type etc) */
|
||||
$$p_d = {};
|
||||
/** @type {Record<string, Function[]>} Event listeners */
|
||||
$$l = {};
|
||||
/** @type {Map<Function, Function>} Event listener unsubscribe functions */
|
||||
$$l_u = new Map();
|
||||
|
||||
constructor($$componentCtor, $$slots, use_shadow_dom) {
|
||||
super();
|
||||
this.$$ctor = $$componentCtor;
|
||||
this.$$s = $$slots;
|
||||
if (use_shadow_dom) {
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener(type, listener, options) {
|
||||
// We can't determine upfront if the event is a custom event or not, so we have to
|
||||
// listen to both. If someone uses a custom event with the same name as a regular
|
||||
// browser event, this fires twice - we can't avoid that.
|
||||
this.$$l[type] = this.$$l[type] || [];
|
||||
this.$$l[type].push(listener);
|
||||
if (this.$$c) {
|
||||
const unsub = this.$$c.$on(type, listener);
|
||||
this.$$l_u.set(listener, unsub);
|
||||
}
|
||||
super.addEventListener(type, listener, options);
|
||||
}
|
||||
|
||||
removeEventListener(type, listener, options) {
|
||||
super.removeEventListener(type, listener, options);
|
||||
if (this.$$c) {
|
||||
const unsub = this.$$l_u.get(listener);
|
||||
if (unsub) {
|
||||
unsub();
|
||||
this.$$l_u.delete(listener);
|
||||
}
|
||||
}
|
||||
if (this.$$l[type]) {
|
||||
const idx = this.$$l[type].indexOf(listener);
|
||||
if (idx >= 0) {
|
||||
this.$$l[type].splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
this.$$cn = true;
|
||||
if (!this.$$c) {
|
||||
// We wait one tick to let possible child slot elements be created/mounted
|
||||
await Promise.resolve();
|
||||
if (!this.$$cn || this.$$c) {
|
||||
return;
|
||||
}
|
||||
function create_slot(name) {
|
||||
return () => {
|
||||
let node;
|
||||
const obj = {
|
||||
c: function create() {
|
||||
node = element('slot');
|
||||
if (name !== 'default') {
|
||||
attr(node, 'name', name);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @param {HTMLElement} target
|
||||
* @param {HTMLElement} [anchor]
|
||||
*/
|
||||
m: function mount(target, anchor) {
|
||||
insert(target, node, anchor);
|
||||
},
|
||||
d: function destroy(detaching) {
|
||||
if (detaching) {
|
||||
detach(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
const $$slots = {};
|
||||
const existing_slots = get_custom_elements_slots(this);
|
||||
for (const name of this.$$s) {
|
||||
if (name in existing_slots) {
|
||||
$$slots[name] = [create_slot(name)];
|
||||
}
|
||||
}
|
||||
for (const attribute of this.attributes) {
|
||||
// this.$$data takes precedence over this.attributes
|
||||
const name = this.$$g_p(attribute.name);
|
||||
if (!(name in this.$$d)) {
|
||||
this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, 'toProp');
|
||||
}
|
||||
}
|
||||
// Port over props that were set programmatically before ce was initialized
|
||||
for (const key in this.$$p_d) {
|
||||
if (!(key in this.$$d) && this[key] !== undefined) {
|
||||
this.$$d[key] = this[key]; // don't transform, these were set through JavaScript
|
||||
delete this[key]; // remove the property that shadows the getter/setter
|
||||
}
|
||||
}
|
||||
this.$$c = new this.$$ctor({
|
||||
target: this.shadowRoot || this,
|
||||
props: {
|
||||
...this.$$d,
|
||||
$$slots,
|
||||
$$scope: {
|
||||
ctx: []
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Reflect component props as attributes
|
||||
const reflect_attributes = () => {
|
||||
this.$$r = true;
|
||||
for (const key in this.$$p_d) {
|
||||
this.$$d[key] = this.$$c.$$.ctx[this.$$c.$$.props[key]];
|
||||
if (this.$$p_d[key].reflect) {
|
||||
const attribute_value = get_custom_element_value(
|
||||
key,
|
||||
this.$$d[key],
|
||||
this.$$p_d,
|
||||
'toAttribute'
|
||||
);
|
||||
if (attribute_value == null) {
|
||||
this.removeAttribute(this.$$p_d[key].attribute || key);
|
||||
} else {
|
||||
this.setAttribute(this.$$p_d[key].attribute || key, attribute_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$$r = false;
|
||||
};
|
||||
this.$$c.$$.after_update.push(reflect_attributes);
|
||||
reflect_attributes(); // once initially because after_update is added too late for first render
|
||||
|
||||
for (const type in this.$$l) {
|
||||
for (const listener of this.$$l[type]) {
|
||||
const unsub = this.$$c.$on(type, listener);
|
||||
this.$$l_u.set(listener, unsub);
|
||||
}
|
||||
}
|
||||
this.$$l = {};
|
||||
}
|
||||
}
|
||||
|
||||
// We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte
|
||||
// and setting attributes through setAttribute etc, this is helpful
|
||||
attributeChangedCallback(attr, _oldValue, newValue) {
|
||||
if (this.$$r) return;
|
||||
attr = this.$$g_p(attr);
|
||||
this.$$d[attr] = get_custom_element_value(attr, newValue, this.$$p_d, 'toProp');
|
||||
this.$$c?.$set({ [attr]: this.$$d[attr] });
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.$$cn = false;
|
||||
// In a microtask, because this could be a move within the DOM
|
||||
Promise.resolve().then(() => {
|
||||
if (!this.$$cn && this.$$c) {
|
||||
this.$$c.$destroy();
|
||||
this.$$c = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$$g_p(attribute_name) {
|
||||
return (
|
||||
Object.keys(this.$$p_d).find(
|
||||
(key) =>
|
||||
this.$$p_d[key].attribute === attribute_name ||
|
||||
(!this.$$p_d[key].attribute && key.toLowerCase() === attribute_name)
|
||||
) || attribute_name
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} prop
|
||||
* @param {any} value
|
||||
* @param {Record<string, CustomElementPropDefinition>} props_definition
|
||||
* @param {'toAttribute' | 'toProp'} [transform]
|
||||
*/
|
||||
function get_custom_element_value(prop, value, props_definition, transform) {
|
||||
const type = props_definition[prop]?.type;
|
||||
value = type === 'Boolean' && typeof value !== 'boolean' ? value != null : value;
|
||||
if (!transform || !props_definition[prop]) {
|
||||
return value;
|
||||
} else if (transform === 'toAttribute') {
|
||||
switch (type) {
|
||||
case 'Object':
|
||||
case 'Array':
|
||||
return value == null ? null : JSON.stringify(value);
|
||||
case 'Boolean':
|
||||
return value ? '' : null;
|
||||
case 'Number':
|
||||
return value == null ? null : value;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case 'Object':
|
||||
case 'Array':
|
||||
return value && JSON.parse(value);
|
||||
case 'Boolean':
|
||||
return value; // conversion already handled above
|
||||
case 'Number':
|
||||
return value != null ? +value : value;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Turn a Svelte component into a custom element.
|
||||
* @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
|
||||
* @param {boolean} use_shadow_dom Whether to use shadow DOM
|
||||
* @param {(ce: new () => HTMLElement) => new () => HTMLElement} [extend]
|
||||
*/
|
||||
export function create_custom_element(
|
||||
Component,
|
||||
props_definition,
|
||||
slots,
|
||||
accessors,
|
||||
use_shadow_dom,
|
||||
extend
|
||||
) {
|
||||
let Class = class extends SvelteElement {
|
||||
constructor() {
|
||||
super(Component, slots, use_shadow_dom);
|
||||
this.$$p_d = props_definition;
|
||||
}
|
||||
static get observedAttributes() {
|
||||
return Object.keys(props_definition).map((key) =>
|
||||
(props_definition[key].attribute || key).toLowerCase()
|
||||
);
|
||||
}
|
||||
};
|
||||
Object.keys(props_definition).forEach((prop) => {
|
||||
Object.defineProperty(Class.prototype, prop, {
|
||||
get() {
|
||||
return this.$$c && prop in this.$$c ? this.$$c[prop] : this.$$d[prop];
|
||||
},
|
||||
set(value) {
|
||||
value = get_custom_element_value(prop, value, props_definition);
|
||||
this.$$d[prop] = value;
|
||||
this.$$c?.$set({ [prop]: value });
|
||||
}
|
||||
});
|
||||
});
|
||||
accessors.forEach((accessor) => {
|
||||
Object.defineProperty(Class.prototype, accessor, {
|
||||
get() {
|
||||
return this.$$c?.[accessor];
|
||||
}
|
||||
});
|
||||
});
|
||||
if (extend) {
|
||||
// @ts-expect-error - assigning here is fine
|
||||
Class = extend(Class);
|
||||
}
|
||||
Component.element = /** @type {any} */ (Class);
|
||||
return Class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for Svelte components. Used when dev=false.
|
||||
*
|
||||
* @template {Record<string, any>} [Props=any]
|
||||
* @template {Record<string, any>} [Events=any]
|
||||
*/
|
||||
export class SvelteComponent {
|
||||
/**
|
||||
* ### PRIVATE API
|
||||
*
|
||||
* Do not use, may change at any time
|
||||
*
|
||||
* @type {any}
|
||||
*/
|
||||
$$ = undefined;
|
||||
/**
|
||||
* ### PRIVATE API
|
||||
*
|
||||
* Do not use, may change at any time
|
||||
*
|
||||
* @type {any}
|
||||
*/
|
||||
$$set = undefined;
|
||||
|
||||
/** @returns {void} */
|
||||
$destroy() {
|
||||
destroy_component(this, 1);
|
||||
this.$destroy = noop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {Extract<keyof Events, string>} K
|
||||
* @param {K} type
|
||||
* @param {((e: Events[K]) => void) | null | undefined} callback
|
||||
* @returns {() => void}
|
||||
*/
|
||||
$on(type, callback) {
|
||||
if (!is_function(callback)) {
|
||||
return noop;
|
||||
}
|
||||
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
|
||||
callbacks.push(callback);
|
||||
return () => {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index !== -1) callbacks.splice(index, 1);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Partial<Props>} props
|
||||
* @returns {void}
|
||||
*/
|
||||
$set(props) {
|
||||
if (this.$$set && !is_empty(props)) {
|
||||
this.$$.skip_bound = true;
|
||||
this.$$set(props);
|
||||
this.$$.skip_bound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CustomElementPropDefinition
|
||||
* @property {string} [attribute]
|
||||
* @property {boolean} [reflect]
|
||||
* @property {'String'|'Boolean'|'Number'|'Array'|'Object'} [type]
|
||||
*/
|
||||
Reference in New Issue
Block a user