UNPKG

@tinymce/tinymce-svelte

Version:

TinyMCE Svelte Component

792 lines (713 loc) 20.4 kB
/** @returns {void} */ function noop() {} function run(fn) { return fn(); } function blank_object() { return Object.create(null); } /** * @param {Function[]} fns * @returns {void} */ function run_all(fns) { fns.forEach(run); } /** * @param {any} thing * @returns {thing is Function} */ function is_function(thing) { return typeof thing === 'function'; } /** @returns {boolean} */ function safe_not_equal(a, b) { return a != a ? b == b : a !== b || (a && typeof a === 'object') || typeof a === 'function'; } /** @returns {boolean} */ function is_empty(obj) { return Object.keys(obj).length === 0; } /** * @param {Node} target * @param {Node} node * @param {Node} [anchor] * @returns {void} */ function insert(target, node, anchor) { target.insertBefore(node, anchor || null); } /** * @param {Node} node * @returns {void} */ function detach(node) { if (node.parentNode) { node.parentNode.removeChild(node); } } /** * @template {keyof HTMLElementTagNameMap} K * @param {K} name * @returns {HTMLElementTagNameMap[K]} */ function element(name) { return document.createElement(name); } /** * @param {Element} node * @param {string} attribute * @param {string} [value] * @returns {void} */ function attr(node, attribute, value) { if (value == null) node.removeAttribute(attribute); else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value); } /** * @param {Element} element * @returns {ChildNode[]} */ function children(element) { return Array.from(element.childNodes); } /** * @returns {void} */ function set_style(node, key, value, important) { if (value == null) { node.style.removeProperty(key); } else { node.style.setProperty(key, value, important ? 'important' : ''); } } /** * @template T * @param {string} type * @param {T} [detail] * @param {{ bubbles?: boolean, cancelable?: boolean }} [options] * @returns {CustomEvent<T>} */ function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) { return new CustomEvent(type, { detail, bubbles, cancelable }); } /** * @typedef {Node & { * claim_order?: number; * hydrate_init?: true; * actual_end_child?: NodeEx; * childNodes: NodeListOf<NodeEx>; * }} NodeEx */ /** @typedef {ChildNode & NodeEx} ChildNodeEx */ /** @typedef {NodeEx & { claim_order: number }} NodeEx2 */ /** * @typedef {ChildNodeEx[] & { * claim_info?: { * last_index: number; * total_claimed: number; * }; * }} ChildNodeArray */ let current_component; /** @returns {void} */ function set_current_component(component) { current_component = component; } 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 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} */ 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<string, any>} [EventMap=any] * @returns {import('./public.js').EventDispatcher<EventMap>} */ 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; }; } const dirty_components = []; const binding_callbacks = []; let render_callbacks = []; const flush_callbacks = []; const resolved_promise = /* @__PURE__ */ Promise.resolve(); let update_scheduled = false; /** @returns {void} */ function schedule_update() { if (!update_scheduled) { update_scheduled = true; resolved_promise.then(flush); } } /** @returns {void} */ function add_render_callback(fn) { render_callbacks.push(fn); } // flush() calls callbacks in this order: // 1. All beforeUpdate callbacks, in order: parents before children // 2. All bind:this callbacks, in reverse order: children before parents. // 3. All afterUpdate callbacks, in order: parents before children. EXCEPT // for afterUpdates called during the initial onMount, which are called in // reverse order: children before parents. // Since callbacks might update component values, which could trigger another // call to flush(), the following steps guard against this: // 1. During beforeUpdate, any updated components will be added to the // dirty_components array and will cause a reentrant call to flush(). Because // the flush index is kept outside the function, the reentrant call will pick // up where the earlier call left off and go through all dirty components. The // current_component value is saved and restored so that the reentrant call will // not interfere with the "parent" flush() call. // 2. bind:this callbacks cannot trigger new flush() calls. // 3. During afterUpdate, any updated components will NOT have their afterUpdate // callback called a second time; the seen_callbacks set, outside the flush() // function, guarantees this behavior. const seen_callbacks = new Set(); let flushidx = 0; // Do *not* move this inside the flush() function /** @returns {void} */ function flush() { // Do not reenter flush while dirty components are updated, as this can // result in an infinite loop. Instead, let the inner flush handle it. // Reentrancy is ok afterwards for bindings etc. if (flushidx !== 0) { return; } const saved_component = current_component; do { // first, call beforeUpdate functions // and update components try { while (flushidx < dirty_components.length) { const component = dirty_components[flushidx]; flushidx++; set_current_component(component); update(component.$$); } } catch (e) { // reset dirty state to not end up in a deadlocked state and then rethrow dirty_components.length = 0; flushidx = 0; throw e; } set_current_component(null); dirty_components.length = 0; flushidx = 0; while (binding_callbacks.length) binding_callbacks.pop()(); // then, once components are updated, call // afterUpdate functions. This may cause // subsequent updates... for (let i = 0; i < render_callbacks.length; i += 1) { const callback = render_callbacks[i]; if (!seen_callbacks.has(callback)) { // ...so guard against infinite loops seen_callbacks.add(callback); callback(); } } render_callbacks.length = 0; } while (dirty_components.length); while (flush_callbacks.length) { flush_callbacks.pop()(); } update_scheduled = false; seen_callbacks.clear(); set_current_component(saved_component); } /** @returns {void} */ function update($$) { if ($$.fragment !== null) { $$.update(); run_all($$.before_update); const dirty = $$.dirty; $$.dirty = [-1]; $$.fragment && $$.fragment.p($$.ctx, dirty); $$.after_update.forEach(add_render_callback); } } /** * Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`. * @param {Function[]} fns * @returns {void} */ function flush_render_callbacks(fns) { const filtered = []; const targets = []; render_callbacks.forEach((c) => (fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c))); targets.forEach((c) => c()); render_callbacks = filtered; } const outroing = new Set(); /** * @param {import('./private.js').Fragment} block * @param {0 | 1} [local] * @returns {void} */ function transition_in(block, local) { if (block && block.i) { outroing.delete(block); block.i(local); } } /** @typedef {1} INTRO */ /** @typedef {0} OUTRO */ /** @typedef {{ direction: 'in' | 'out' | 'both' }} TransitionOptions */ /** @typedef {(node: Element, params: any, options: TransitionOptions) => import('../transition/public.js').TransitionConfig} TransitionFn */ /** * @typedef {Object} Outro * @property {number} r * @property {Function[]} c * @property {Object} p */ /** * @typedef {Object} PendingProgram * @property {number} start * @property {INTRO|OUTRO} b * @property {Outro} [group] */ /** * @typedef {Object} Program * @property {number} a * @property {INTRO|OUTRO} b * @property {1|-1} d * @property {number} duration * @property {number} start * @property {number} end * @property {Outro} [group] */ /** @returns {void} */ 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} */ 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} */ 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) { // 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); flush(); } set_current_component(parent_component); } /** * Base class for Svelte components. Used when dev=false. * * @template {Record<string, any>} [Props=any] * @template {Record<string, any>} [Events=any] */ 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] */ // generated during release, do not modify const PUBLIC_VERSION = '4'; if (typeof window !== 'undefined') // @ts-ignore (window.__svelte || (window.__svelte = { v: new Set() })).v.add(PUBLIC_VERSION); /* src/main/component/Editor.svelte generated by Svelte v4.2.19 */ function create_else_block(ctx) { let textarea; return { c() { textarea = element("textarea"); attr(textarea, "id", /*id*/ ctx[0]); set_style(textarea, "visibility", "hidden"); }, m(target, anchor) { insert(target, textarea, anchor); /*textarea_binding*/ ctx[20](textarea); }, p(ctx, dirty) { if (dirty & /*id*/ 1) { attr(textarea, "id", /*id*/ ctx[0]); } }, d(detaching) { if (detaching) { detach(textarea); } /*textarea_binding*/ ctx[20](null); } }; } // (157:0) {#if inline} function create_if_block(ctx) { let div; return { c() { div = element("div"); attr(div, "id", /*id*/ ctx[0]); }, m(target, anchor) { insert(target, div, anchor); /*div_binding*/ ctx[19](div); }, p(ctx, dirty) { if (dirty & /*id*/ 1) { attr(div, "id", /*id*/ ctx[0]); } }, d(detaching) { if (detaching) { detach(div); } /*div_binding*/ ctx[19](null); } }; } function create_fragment(ctx) { let div; function select_block_type(ctx, dirty) { if (/*inline*/ ctx[1]) return create_if_block; return create_else_block; } let current_block_type = select_block_type(ctx); let if_block = current_block_type(ctx); return { c() { div = element("div"); if_block.c(); attr(div, "class", /*cssClass*/ ctx[2]); }, m(target, anchor) { insert(target, div, anchor); if_block.m(div, null); /*div_binding_1*/ ctx[21](div); }, p(ctx, [dirty]) { if (current_block_type === (current_block_type = select_block_type(ctx)) && if_block) { if_block.p(ctx, dirty); } else { if_block.d(1); if_block = current_block_type(ctx); if (if_block) { if_block.c(); if_block.m(div, null); } } if (dirty & /*cssClass*/ 4) { attr(div, "class", /*cssClass*/ ctx[2]); } }, i: noop, o: noop, d(detaching) { if (detaching) { detach(div); } if_block.d(); /*div_binding_1*/ ctx[21](null); } }; } const uuid = prefix => { return prefix + '_' + Math.floor(Math.random() * 1000000000) + String(Date.now()); }; function instance($$self, $$props, $$invalidate) { let { id = uuid('tinymce-svelte') } = $$props; let { inline = undefined } = $$props; let { disabled = false } = $$props; let { readonly = false } = $$props; let { apiKey = 'no-api-key' } = $$props; let { licenseKey = undefined } = $$props; let { channel = '8' } = $$props; let { scriptSrc = undefined } = $$props; let { conf = {} } = $$props; let { modelEvents = 'change input undo redo' } = $$props; let { value = '' } = $$props; let { text = '' } = $$props; let { cssClass = 'tinymce-wrapper' } = $$props; let container; let element; let editorRef; let lastVal = value; let disablindCache = disabled; let readonlyCache = readonly; createEventDispatcher(); onDestroy(() => { }); function div_binding($$value) { binding_callbacks[$$value ? 'unshift' : 'push'](() => { element = $$value; $$invalidate(4, element); }); } function textarea_binding($$value) { binding_callbacks[$$value ? 'unshift' : 'push'](() => { element = $$value; $$invalidate(4, element); }); } function div_binding_1($$value) { binding_callbacks[$$value ? 'unshift' : 'push'](() => { container = $$value; $$invalidate(3, container); }); } $$self.$$set = $$props => { if ('id' in $$props) $$invalidate(0, id = $$props.id); if ('inline' in $$props) $$invalidate(1, inline = $$props.inline); if ('disabled' in $$props) $$invalidate(7, disabled = $$props.disabled); if ('readonly' in $$props) $$invalidate(8, readonly = $$props.readonly); if ('apiKey' in $$props) $$invalidate(9, apiKey = $$props.apiKey); if ('licenseKey' in $$props) $$invalidate(10, licenseKey = $$props.licenseKey); if ('channel' in $$props) $$invalidate(11, channel = $$props.channel); if ('scriptSrc' in $$props) $$invalidate(12, scriptSrc = $$props.scriptSrc); if ('conf' in $$props) $$invalidate(13, conf = $$props.conf); if ('modelEvents' in $$props) $$invalidate(14, modelEvents = $$props.modelEvents); if ('value' in $$props) $$invalidate(5, value = $$props.value); if ('text' in $$props) $$invalidate(6, text = $$props.text); if ('cssClass' in $$props) $$invalidate(2, cssClass = $$props.cssClass); }; $$self.$$.update = () => { if ($$self.$$.dirty & /*editorRef, lastVal, value, readonly, readonlyCache, disabled, disablindCache*/ 491936) ; }; return [ id, inline, cssClass, container, element, value, text, disabled, readonly, apiKey, licenseKey, channel, scriptSrc, conf, modelEvents, editorRef, lastVal, disablindCache, readonlyCache, div_binding, textarea_binding, div_binding_1 ]; } class Editor extends SvelteComponent { constructor(options) { super(); init(this, options, instance, create_fragment, safe_not_equal, { id: 0, inline: 1, disabled: 7, readonly: 8, apiKey: 9, licenseKey: 10, channel: 11, scriptSrc: 12, conf: 13, modelEvents: 14, value: 5, text: 6, cssClass: 2 }); } } export { Editor as default }; //# sourceMappingURL=index.mjs.map