diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js index f57249df1f..1a12eb4b3e 100644 --- a/packages/svelte/src/internal/client/dom/blocks/await.js +++ b/packages/svelte/src/internal/client/dom/blocks/await.js @@ -1,9 +1,9 @@ import { is_promise } from '../../../common.js'; -import { hydrate_block_anchor } from '../../hydration.js'; -import { remove } from '../../reconciler.js'; +import { hydrate_block_anchor } from '../hydration.js'; +import { remove } from '../reconciler.js'; import { current_block, execute_effect, flushSync } from '../../runtime.js'; import { destroy_effect, render_effect } from '../../reactivity/effects.js'; -import { trigger_transitions } from '../../transitions.js'; +import { trigger_transitions } from '../elements/transitions.js'; import { AWAIT_BLOCK, UNINITIALIZED } from '../../constants.js'; /** @returns {import('../../types.js').AwaitBlock} */ diff --git a/packages/svelte/src/internal/client/dom/blocks/css-props.js b/packages/svelte/src/internal/client/dom/blocks/css-props.js index 6829cdf0e6..aee98617d7 100644 --- a/packages/svelte/src/internal/client/dom/blocks/css-props.js +++ b/packages/svelte/src/internal/client/dom/blocks/css-props.js @@ -1,8 +1,8 @@ import { namespace_svg } from '../../../../constants.js'; -import { current_hydration_fragment, hydrate_block_anchor, hydrating } from '../../hydration.js'; -import { empty } from '../../operations.js'; +import { current_hydration_fragment, hydrate_block_anchor, hydrating } from '../hydration.js'; +import { empty } from '../operations.js'; import { render_effect } from '../../reactivity/effects.js'; -import { insert, remove } from '../../reconciler.js'; +import { insert, remove } from '../reconciler.js'; /** * @param {Element | Text | Comment} anchor diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index 5a572a9729..fd3cf82ae3 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -13,14 +13,14 @@ import { hydrate_block_anchor, hydrating, set_current_hydration_fragment -} from '../../hydration.js'; -import { clear_text_content, empty, map_get, map_set } from '../../operations.js'; -import { insert, remove } from '../../reconciler.js'; +} from '../hydration.js'; +import { clear_text_content, empty } from '../operations.js'; +import { insert, remove } from '../reconciler.js'; import { current_block, execute_effect } from '../../runtime.js'; import { destroy_effect, render_effect } from '../../reactivity/effects.js'; import { source, mutable_source, set } from '../../reactivity/sources.js'; -import { trigger_transitions } from '../../transitions.js'; -import { is_array, is_frozen } from '../../utils.js'; +import { trigger_transitions } from '../elements/transitions.js'; +import { is_array, is_frozen, map_get, map_set } from '../../utils.js'; import { EACH_BLOCK, EACH_ITEM_BLOCK, STATE_SYMBOL } from '../../constants.js'; const NEW_BLOCK = -1; diff --git a/packages/svelte/src/internal/client/dom/blocks/html.js b/packages/svelte/src/internal/client/dom/blocks/html.js index 1a02ad476f..2e03cbc3bb 100644 --- a/packages/svelte/src/internal/client/dom/blocks/html.js +++ b/packages/svelte/src/internal/client/dom/blocks/html.js @@ -1,5 +1,5 @@ import { render_effect } from '../../reactivity/effects.js'; -import { reconcile_html, remove } from '../../reconciler.js'; +import { reconcile_html, remove } from '../reconciler.js'; /** * @param {Element | Text | Comment} dom diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js index 5fb43fd0ed..9f8f717508 100644 --- a/packages/svelte/src/internal/client/dom/blocks/if.js +++ b/packages/svelte/src/internal/client/dom/blocks/if.js @@ -4,11 +4,11 @@ import { hydrate_block_anchor, hydrating, set_current_hydration_fragment -} from '../../hydration.js'; -import { remove } from '../../reconciler.js'; +} from '../hydration.js'; +import { remove } from '../reconciler.js'; import { current_block, execute_effect } from '../../runtime.js'; import { destroy_effect, render_effect } from '../../reactivity/effects.js'; -import { trigger_transitions } from '../../transitions.js'; +import { trigger_transitions } from '../elements/transitions.js'; /** @returns {import('../../types.js').IfBlock} */ function create_if_block() { diff --git a/packages/svelte/src/internal/client/dom/blocks/key.js b/packages/svelte/src/internal/client/dom/blocks/key.js index 1ac78accd1..4267b96546 100644 --- a/packages/svelte/src/internal/client/dom/blocks/key.js +++ b/packages/svelte/src/internal/client/dom/blocks/key.js @@ -1,9 +1,9 @@ import { UNINITIALIZED, KEY_BLOCK } from '../../constants.js'; -import { hydrate_block_anchor } from '../../hydration.js'; -import { remove } from '../../reconciler.js'; +import { hydrate_block_anchor } from '../hydration.js'; +import { remove } from '../reconciler.js'; import { current_block, execute_effect } from '../../runtime.js'; import { destroy_effect, render_effect } from '../../reactivity/effects.js'; -import { trigger_transitions } from '../../transitions.js'; +import { trigger_transitions } from '../elements/transitions.js'; import { safe_not_equal } from '../../reactivity/equality.js'; /** @returns {import('../../types.js').KeyBlock} */ diff --git a/packages/svelte/src/internal/client/dom/blocks/snippet.js b/packages/svelte/src/internal/client/dom/blocks/snippet.js index be7411d88f..c07eca4d44 100644 --- a/packages/svelte/src/internal/client/dom/blocks/snippet.js +++ b/packages/svelte/src/internal/client/dom/blocks/snippet.js @@ -1,6 +1,6 @@ import { SNIPPET_BLOCK } from '../../constants.js'; import { render_effect } from '../../reactivity/effects.js'; -import { remove } from '../../reconciler.js'; +import { remove } from '../reconciler.js'; import { current_block, untrack } from '../../runtime.js'; /** diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-component.js b/packages/svelte/src/internal/client/dom/blocks/svelte-component.js index aee3a07130..3f170462ef 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-component.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-component.js @@ -1,9 +1,9 @@ import { DYNAMIC_COMPONENT_BLOCK } from '../../constants.js'; -import { hydrate_block_anchor } from '../../hydration.js'; +import { hydrate_block_anchor } from '../hydration.js'; import { destroy_effect, render_effect } from '../../reactivity/effects.js'; -import { remove } from '../../reconciler.js'; +import { remove } from '../reconciler.js'; import { current_block, execute_effect } from '../../runtime.js'; -import { trigger_transitions } from '../../transitions.js'; +import { trigger_transitions } from '../elements/transitions.js'; /** * @template P diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js index b4608cca8f..98950fd317 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js @@ -1,9 +1,9 @@ import { namespace_svg } from '../../../../constants.js'; import { DYNAMIC_ELEMENT_BLOCK } from '../../constants.js'; -import { current_hydration_fragment, hydrate_block_anchor, hydrating } from '../../hydration.js'; -import { empty } from '../../operations.js'; +import { current_hydration_fragment, hydrate_block_anchor, hydrating } from '../hydration.js'; +import { empty } from '../operations.js'; import { destroy_effect, render_effect } from '../../reactivity/effects.js'; -import { insert, remove } from '../../reconciler.js'; +import { insert, remove } from '../reconciler.js'; import { current_block, execute_effect } from '../../runtime.js'; import { is_array } from '../../utils.js'; diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-head.js b/packages/svelte/src/internal/client/dom/blocks/svelte-head.js index 08b1c52471..0147a5fe88 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-head.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-head.js @@ -4,10 +4,10 @@ import { get_hydration_fragment, hydrating, set_current_hydration_fragment -} from '../../hydration.js'; -import { empty } from '../../operations.js'; +} from '../hydration.js'; +import { empty } from '../operations.js'; import { render_effect } from '../../reactivity/effects.js'; -import { remove } from '../../reconciler.js'; +import { remove } from '../reconciler.js'; import { current_block } from '../../runtime.js'; /** diff --git a/packages/svelte/src/internal/client/dom/elements/actions.js b/packages/svelte/src/internal/client/dom/elements/actions.js new file mode 100644 index 0000000000..e6de87e78f --- /dev/null +++ b/packages/svelte/src/internal/client/dom/elements/actions.js @@ -0,0 +1,53 @@ +import { effect } from '../../reactivity/effects.js'; +import { deep_read_state, untrack } from '../../runtime.js'; + +/** + * @template P + * @param {Element} dom + * @param {(dom: Element, value?: P) => import('#client').ActionPayload

} action + * @param {() => P} [value_fn] + * @returns {void} + */ +export function action(dom, action, value_fn) { + /** @type {undefined | import('#client').ActionPayload

} */ + var payload = undefined; + var needs_deep_read = false; + + // Action could come from a prop, therefore could be a signal, therefore untrack + // TODO we could take advantage of this and enable https://github.com/sveltejs/svelte/issues/6942 + effect(() => { + if (value_fn) { + var value = value_fn(); + untrack(() => { + if (payload === undefined) { + payload = action(dom, value) || {}; + needs_deep_read = !!payload?.update; + } else { + var update = payload.update; + if (typeof update === 'function') { + update(value); + } + } + }); + // Action's update method is coarse-grained, i.e. when anything in the passed value changes, update. + // This works in legacy mode because of mutable_source being updated as a whole, but when using $state + // together with actions and mutation, it wouldn't notice the change without a deep read. + if (needs_deep_read) { + deep_read_state(value); + } + } else { + untrack(() => (payload = action(dom))); + } + }); + + effect(() => { + if (payload !== undefined) { + var destroy = payload.destroy; + if (typeof destroy === 'function') { + return () => { + /** @type {Function} */ (destroy)(); + }; + } + } + }); +} diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index 5e5a530eb0..7ba3be585e 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -1,8 +1,7 @@ import { DEV } from 'esm-env'; -import { hydrating } from '../../hydration.js'; +import { hydrating } from '../hydration.js'; import { render_effect } from '../../reactivity/effects.js'; -import { get_descriptors, object_assign } from '../../utils.js'; -import { map_get, map_set } from '../../operations.js'; +import { get_descriptors, map_get, map_set, object_assign } from '../../utils.js'; import { AttributeAliases, DelegatedEvents, namespace_svg } from '../../../../constants.js'; import { delegate } from './events.js'; import { autofocus } from './misc.js'; diff --git a/packages/svelte/src/internal/client/dom/bindings/input.js b/packages/svelte/src/internal/client/dom/elements/bindings/input.js similarity index 97% rename from packages/svelte/src/internal/client/dom/bindings/input.js rename to packages/svelte/src/internal/client/dom/elements/bindings/input.js index 67ffd7562e..fcf56b7e89 100644 --- a/packages/svelte/src/internal/client/dom/bindings/input.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/input.js @@ -1,6 +1,6 @@ import { DEV } from 'esm-env'; -import { render_effect } from '../../reactivity/effects.js'; -import { stringify } from '../../render.js'; +import { render_effect } from '../../../reactivity/effects.js'; +import { stringify } from '../../../render.js'; /** * @param {HTMLInputElement} input diff --git a/packages/svelte/src/internal/client/dom/bindings/media.js b/packages/svelte/src/internal/client/dom/elements/bindings/media.js similarity index 99% rename from packages/svelte/src/internal/client/dom/bindings/media.js rename to packages/svelte/src/internal/client/dom/elements/bindings/media.js index 35ec4fa196..bd559b1565 100644 --- a/packages/svelte/src/internal/client/dom/bindings/media.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/media.js @@ -1,5 +1,5 @@ import { hydrating } from '../../hydration.js'; -import { destroy_effect, managed_effect, render_effect } from '../../reactivity/effects.js'; +import { destroy_effect, managed_effect, render_effect } from '../../../reactivity/effects.js'; import { listen } from './shared.js'; /** @param {TimeRanges} ranges */ diff --git a/packages/svelte/src/internal/client/dom/bindings/navigator.js b/packages/svelte/src/internal/client/dom/elements/bindings/navigator.js similarity index 100% rename from packages/svelte/src/internal/client/dom/bindings/navigator.js rename to packages/svelte/src/internal/client/dom/elements/bindings/navigator.js diff --git a/packages/svelte/src/internal/client/dom/bindings/props.js b/packages/svelte/src/internal/client/dom/elements/bindings/props.js similarity index 79% rename from packages/svelte/src/internal/client/dom/bindings/props.js rename to packages/svelte/src/internal/client/dom/elements/bindings/props.js index 0142f3a6f8..4b5a24cc92 100644 --- a/packages/svelte/src/internal/client/dom/bindings/props.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/props.js @@ -1,5 +1,5 @@ -import { render_effect } from '../../reactivity/effects.js'; -import { get_descriptor } from '../../utils.js'; +import { render_effect } from '../../../reactivity/effects.js'; +import { get_descriptor } from '../../../utils.js'; /** * Makes an `export`ed (non-prop) variable available on the `$$props` object diff --git a/packages/svelte/src/internal/client/dom/bindings/select.js b/packages/svelte/src/internal/client/dom/elements/bindings/select.js similarity index 98% rename from packages/svelte/src/internal/client/dom/bindings/select.js rename to packages/svelte/src/internal/client/dom/elements/bindings/select.js index 32b01c0472..5e6241f8cd 100644 --- a/packages/svelte/src/internal/client/dom/bindings/select.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/select.js @@ -1,4 +1,4 @@ -import { effect } from '../../reactivity/effects.js'; +import { effect } from '../../../reactivity/effects.js'; /** * Selects the correct option(s) (depending on whether this is a multiple select) diff --git a/packages/svelte/src/internal/client/dom/bindings/shared.js b/packages/svelte/src/internal/client/dom/elements/bindings/shared.js similarity index 91% rename from packages/svelte/src/internal/client/dom/bindings/shared.js rename to packages/svelte/src/internal/client/dom/elements/bindings/shared.js index 8d457d66d9..379ce82f1e 100644 --- a/packages/svelte/src/internal/client/dom/bindings/shared.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/shared.js @@ -1,4 +1,4 @@ -import { render_effect } from '../../reactivity/effects.js'; +import { render_effect } from '../../../reactivity/effects.js'; /** * Fires the handler once immediately (unless corresponding arg is set to `false`), diff --git a/packages/svelte/src/internal/client/dom/bindings/size.js b/packages/svelte/src/internal/client/dom/elements/bindings/size.js similarity index 95% rename from packages/svelte/src/internal/client/dom/bindings/size.js rename to packages/svelte/src/internal/client/dom/elements/bindings/size.js index 0182dcf08b..afbba473aa 100644 --- a/packages/svelte/src/internal/client/dom/bindings/size.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/size.js @@ -1,5 +1,5 @@ -import { effect, render_effect } from '../../reactivity/effects.js'; -import { untrack } from '../../runtime.js'; +import { effect, render_effect } from '../../../reactivity/effects.js'; +import { untrack } from '../../../runtime.js'; /** * Resize observer singleton. diff --git a/packages/svelte/src/internal/client/dom/bindings/this.js b/packages/svelte/src/internal/client/dom/elements/bindings/this.js similarity index 93% rename from packages/svelte/src/internal/client/dom/bindings/this.js rename to packages/svelte/src/internal/client/dom/elements/bindings/this.js index e7a7a20197..c91fac434a 100644 --- a/packages/svelte/src/internal/client/dom/bindings/this.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/this.js @@ -1,6 +1,6 @@ -import { STATE_SYMBOL } from '../../constants.js'; -import { effect } from '../../reactivity/effects.js'; -import { untrack } from '../../runtime.js'; +import { STATE_SYMBOL } from '../../../constants.js'; +import { effect } from '../../../reactivity/effects.js'; +import { untrack } from '../../../runtime.js'; /** * @param {any} bound_value diff --git a/packages/svelte/src/internal/client/dom/bindings/universal.js b/packages/svelte/src/internal/client/dom/elements/bindings/universal.js similarity index 95% rename from packages/svelte/src/internal/client/dom/bindings/universal.js rename to packages/svelte/src/internal/client/dom/elements/bindings/universal.js index f98ebe1f4a..8c40c04da5 100644 --- a/packages/svelte/src/internal/client/dom/bindings/universal.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/universal.js @@ -1,4 +1,4 @@ -import { render_effect } from '../../reactivity/effects.js'; +import { render_effect } from '../../../reactivity/effects.js'; /** * @param {'innerHTML' | 'textContent' | 'innerText'} property diff --git a/packages/svelte/src/internal/client/dom/bindings/window.js b/packages/svelte/src/internal/client/dom/elements/bindings/window.js similarity index 95% rename from packages/svelte/src/internal/client/dom/bindings/window.js rename to packages/svelte/src/internal/client/dom/elements/bindings/window.js index 646560b62a..8cab87122b 100644 --- a/packages/svelte/src/internal/client/dom/bindings/window.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/window.js @@ -1,4 +1,4 @@ -import { render_effect } from '../../reactivity/effects.js'; +import { render_effect } from '../../../reactivity/effects.js'; import { listen } from './shared.js'; /** diff --git a/packages/svelte/src/internal/client/dom/elements/class.js b/packages/svelte/src/internal/client/dom/elements/class.js index e180ed522b..84466e8058 100644 --- a/packages/svelte/src/internal/client/dom/elements/class.js +++ b/packages/svelte/src/internal/client/dom/elements/class.js @@ -1,5 +1,5 @@ -import { hydrating } from '../../hydration.js'; -import { set_class_name } from '../../operations.js'; +import { hydrating } from '../hydration.js'; +import { set_class_name } from '../operations.js'; import { render_effect } from '../../reactivity/effects.js'; /** diff --git a/packages/svelte/src/internal/client/custom-element.js b/packages/svelte/src/internal/client/dom/elements/custom-element.js similarity index 97% rename from packages/svelte/src/internal/client/custom-element.js rename to packages/svelte/src/internal/client/dom/elements/custom-element.js index 5a1318e6a9..cd2d2dfc60 100644 --- a/packages/svelte/src/internal/client/custom-element.js +++ b/packages/svelte/src/internal/client/dom/elements/custom-element.js @@ -1,7 +1,7 @@ -import { createClassComponent } from '../../legacy/legacy-client.js'; -import { destroy_effect, render_effect } from './reactivity/effects.js'; -import { open, close } from './dom/template.js'; -import { define_property } from './utils.js'; +import { createClassComponent } from '../../../../legacy/legacy-client.js'; +import { destroy_effect, render_effect } from '../../reactivity/effects.js'; +import { open, close } from '../template.js'; +import { define_property } from '../../utils.js'; /** * @typedef {Object} CustomElementPropDefinition diff --git a/packages/svelte/src/internal/client/dom/elements/misc.js b/packages/svelte/src/internal/client/dom/elements/misc.js index 3a117dcd69..e0fc8d2a19 100644 --- a/packages/svelte/src/internal/client/dom/elements/misc.js +++ b/packages/svelte/src/internal/client/dom/elements/misc.js @@ -1,4 +1,4 @@ -import { hydrating } from '../../hydration.js'; +import { hydrating } from '../hydration.js'; import { render_effect } from '../../reactivity/effects.js'; import { current_block } from '../../runtime.js'; diff --git a/packages/svelte/src/internal/client/transitions.js b/packages/svelte/src/internal/client/dom/elements/transitions.js similarity index 83% rename from packages/svelte/src/internal/client/transitions.js rename to packages/svelte/src/internal/client/dom/elements/transitions.js index 416f38f592..4a9615d387 100644 --- a/packages/svelte/src/internal/client/transitions.js +++ b/packages/svelte/src/internal/client/dom/elements/transitions.js @@ -1,5 +1,5 @@ -import { EACH_IS_ANIMATED, EACH_IS_CONTROLLED } from '../../constants.js'; -import { run_all } from '../common.js'; +import { EACH_IS_ANIMATED, EACH_IS_CONTROLLED } from '../../../../constants.js'; +import { run_all } from '../../../common.js'; import { AWAIT_BLOCK, DYNAMIC_COMPONENT_BLOCK, @@ -8,24 +8,24 @@ import { IF_BLOCK, KEY_BLOCK, ROOT_BLOCK -} from './constants.js'; -import { destroy_each_item_block, get_first_element } from './dom/blocks/each.js'; -import { schedule_raf_task } from './dom/task.js'; -import { append_child, empty } from './operations.js'; +} from '../../constants.js'; +import { destroy_each_item_block, get_first_element } from '../blocks/each.js'; +import { schedule_raf_task } from '../task.js'; +import { append_child, empty } from '../operations.js'; import { destroy_effect, effect, managed_effect, managed_pre_effect -} from './reactivity/effects.js'; +} from '../../reactivity/effects.js'; import { current_block, current_effect, execute_effect, mark_subtree_inert, untrack -} from './runtime.js'; -import { raf } from './timing.js'; +} from '../../runtime.js'; +import { raf } from '../../timing.js'; const active_tick_animations = new Set(); const DELAY_NEXT_TICK = Number.MIN_SAFE_INTEGER; @@ -33,6 +33,54 @@ const DELAY_NEXT_TICK = Number.MIN_SAFE_INTEGER; /** @type {undefined | number} */ let active_tick_ref = undefined; +/** + * @template P + * @param {HTMLElement} dom + * @param {() => import('#client').TransitionFn

} get_transition_fn + * @param {(() => P) | null} props + * @param {any} global + * @returns {void} + */ +export function transition(dom, get_transition_fn, props, global = false) { + bind_transition(dom, get_transition_fn, props, 'both', global); +} + +/** + * @template P + * @param {HTMLElement} dom + * @param {() => import('#client').TransitionFn

} get_transition_fn + * @param {(() => P) | null} props + * @returns {void} + */ +export function animate(dom, get_transition_fn, props) { + bind_transition(dom, get_transition_fn, props, 'key', false); +} + +/** + * @template P + * @param {HTMLElement} dom + * @param {() => import('#client').TransitionFn

} get_transition_fn + * @param {(() => P) | null} props + * @param {any} global + * @returns {void} + */ +function in_fn(dom, get_transition_fn, props, global = false) { + bind_transition(dom, get_transition_fn, props, 'in', global); +} +export { in_fn as in }; + +/** + * @template P + * @param {HTMLElement} dom + * @param {() => import('#client').TransitionFn

} get_transition_fn + * @param {(() => P) | null} props + * @param {any} global + * @returns {void} + */ +export function out(dom, get_transition_fn, props, global = false) { + bind_transition(dom, get_transition_fn, props, 'out', global); +} + /** * @template T * @param {string} type @@ -297,10 +345,10 @@ const linear = (t) => t; /** * @param {HTMLElement} dom - * @param {() => import('./types.js').TransitionPayload} init + * @param {() => import('../../types.js').TransitionPayload} init * @param {'in' | 'out' | 'both' | 'key'} direction - * @param {import('./types.js').Effect} effect - * @returns {import('./types.js').Transition} + * @param {import('../../types.js').Effect} effect + * @returns {import('../../types.js').Transition} */ function create_transition(dom, init, direction, effect) { let curr_direction = 'in'; @@ -313,7 +361,7 @@ function create_transition(dom, init, direction, effect) { let cancelled = false; const create_animation = () => { - let payload = /** @type {import('./types.js').TransitionPayload} */ (transition.p); + let payload = /** @type {import('../../types.js').TransitionPayload} */ (transition.p); if (typeof payload === 'function') { // @ts-ignore payload = payload({ direction: curr_direction }); @@ -354,7 +402,7 @@ function create_transition(dom, init, direction, effect) { }; }; - /** @type {import('./types.js').Transition} */ + /** @type {import('../../types.js').Transition} */ const transition = { e: effect, i: init, @@ -482,7 +530,7 @@ function create_transition(dom, init, direction, effect) { } /** - * @param {import('./types.js').Block} block + * @param {import('../../types.js').Block} block * @returns {boolean} */ function is_transition_block(block) { @@ -500,14 +548,14 @@ function is_transition_block(block) { /** * @template P * @param {HTMLElement} dom - * @param {() => import('./types.js').TransitionFn

| import('./types.js').AnimateFn

} get_transition_fn + * @param {() => import('../../types.js').TransitionFn

| import('../../types.js').AnimateFn

} get_transition_fn * @param {(() => P) | null} props_fn * @param {'in' | 'out' | 'both' | 'key'} direction * @param {boolean} global * @returns {void} */ -export function bind_transition(dom, get_transition_fn, props_fn, direction, global) { - const transition_effect = /** @type {import('./types.js').Effect} */ (current_effect); +function bind_transition(dom, get_transition_fn, props_fn, direction, global) { + const transition_effect = /** @type {import('../../types.js').Effect} */ (current_effect); const block = current_block; const is_keyed_transition = direction === 'key'; @@ -518,7 +566,7 @@ export function bind_transition(dom, get_transition_fn, props_fn, direction, glo // @ts-ignore dom.__animate = true; } - /** @type {import('./types.js').Block | null} */ + /** @type {import('../../types.js').Block | null} */ let transition_block = block; main: while (transition_block !== null) { if (is_transition_block(transition_block)) { @@ -532,7 +580,7 @@ export function bind_transition(dom, get_transition_fn, props_fn, direction, glo } else if (transition_block.t === IF_BLOCK) { transition_block.r = if_block_transition; if (can_show_intro_on_mount) { - /** @type {import('./types.js').Block | null} */ + /** @type {import('../../types.js').Block | null} */ let if_block = transition_block; while (if_block.t === IF_BLOCK) { // If we have an if block parent that is currently falsy then @@ -557,7 +605,7 @@ export function bind_transition(dom, get_transition_fn, props_fn, direction, glo transition_block = transition_block.p; } - /** @type {import('./types.js').Transition} */ + /** @type {import('../../types.js').Transition} */ let transition; effect(() => { @@ -573,13 +621,13 @@ export function bind_transition(dom, get_transition_fn, props_fn, direction, glo untrack(() => { const props = props_fn === null ? {} : props_fn(); return is_keyed_transition - ? /** @type {import('./types.js').AnimateFn} */ (transition_fn)( + ? /** @type {import('../../types.js').AnimateFn} */ (transition_fn)( dom, { from: /** @type {DOMRect} */ (from), to: dom.getBoundingClientRect() }, props, {} ) - : /** @type {import('./types.js').TransitionFn} */ (transition_fn)(dom, props, { + : /** @type {import('../../types.js').TransitionFn} */ (transition_fn)(dom, props, { direction }); }); @@ -600,7 +648,7 @@ export function bind_transition(dom, get_transition_fn, props_fn, direction, glo transition.in(); } - /** @type {import('./types.js').Block | null} */ + /** @type {import('../../types.js').Block | null} */ let transition_block = block; while (!is_intro && transition_block !== null) { const parent = transition_block.p; @@ -630,7 +678,7 @@ export function bind_transition(dom, get_transition_fn, props_fn, direction, glo } /** - * @param {Set} transitions + * @param {Set} transitions * @param {'in' | 'out' | 'key'} target_direction * @param {DOMRect} [from] * @returns {void} @@ -680,8 +728,8 @@ export function trigger_transitions(transitions, target_direction, from) { } /** - * @this {import('./types.js').IfBlock} - * @param {import('./types.js').Transition} transition + * @this {import('../../types.js').IfBlock} + * @param {import('../../types.js').Transition} transition * @returns {void} */ function if_block_transition(transition) { @@ -691,32 +739,32 @@ function if_block_transition(transition) { const consequent_transitions = (block.c ??= new Set()); consequent_transitions.add(transition); transition.f(() => { - const c = /** @type {Set} */ (consequent_transitions); + const c = /** @type {Set} */ (consequent_transitions); c.delete(transition); // If the block has changed to falsy and has transitions if (!block.v && c.size === 0) { const consequent_effect = block.ce; - execute_effect(/** @type {import('./types.js').Effect} */ (consequent_effect)); + execute_effect(/** @type {import('../../types.js').Effect} */ (consequent_effect)); } }); } else { const alternate_transitions = (block.a ??= new Set()); alternate_transitions.add(transition); transition.f(() => { - const a = /** @type {Set} */ (alternate_transitions); + const a = /** @type {Set} */ (alternate_transitions); a.delete(transition); // If the block has changed to truthy and has transitions if (block.v && a.size === 0) { const alternate_effect = block.ae; - execute_effect(/** @type {import('./types.js').Effect} */ (alternate_effect)); + execute_effect(/** @type {import('../../types.js').Effect} */ (alternate_effect)); } }); } } /** - * @this {import('./types.js').EachItemBlock} - * @param {import('./types.js').Transition} transition + * @this {import('../../types.js').EachItemBlock} + * @param {import('../../types.js').Transition} transition * @returns {void} */ function each_item_transition(transition) { @@ -754,8 +802,8 @@ function each_item_transition(transition) { /** * - * @param {import('./types.js').EachItemBlock} block - * @param {Set} transitions + * @param {import('../../types.js').EachItemBlock} block + * @param {Set} transitions */ function each_item_animate(block, transitions) { const from_dom = /** @type {Element} */ (get_first_element(block)); diff --git a/packages/svelte/src/internal/client/hydration.js b/packages/svelte/src/internal/client/dom/hydration.js similarity index 89% rename from packages/svelte/src/internal/client/hydration.js rename to packages/svelte/src/internal/client/dom/hydration.js index d6912dfb59..1b15a9ddbb 100644 --- a/packages/svelte/src/internal/client/hydration.js +++ b/packages/svelte/src/internal/client/dom/hydration.js @@ -1,6 +1,6 @@ // Handle hydration -import { schedule_task } from './dom/task.js'; +import { schedule_task } from './task.js'; import { empty } from './operations.js'; /** @@ -13,27 +13,27 @@ export let hydrating = false; * Array of nodes to traverse for hydration. This will be null if we're not hydrating, but for * the sake of simplicity we're not going to use `null` checks everywhere and instead rely on * the `hydrating` flag to tell whether or not we're in hydration mode at which point this is set. - * @type {import('./types.js').TemplateNode[]} + * @type {import('../types.js').TemplateNode[]} */ export let current_hydration_fragment = /** @type {any} */ (null); /** - * @param {null | import('./types.js').TemplateNode[]} fragment + * @param {null | import('../types.js').TemplateNode[]} fragment * @returns {void} */ export function set_current_hydration_fragment(fragment) { hydrating = fragment !== null; - current_hydration_fragment = /** @type {import('./types.js').TemplateNode[]} */ (fragment); + current_hydration_fragment = /** @type {import('../types.js').TemplateNode[]} */ (fragment); } /** * Returns all nodes between the first `` comment tag pair encountered. * @param {Node | null} node * @param {boolean} [insert_text] Whether to insert an empty text node if the fragment is empty - * @returns {import('./types.js').TemplateNode[] | null} + * @returns {import('../types.js').TemplateNode[] | null} */ export function get_hydration_fragment(node, insert_text = false) { - /** @type {import('./types.js').TemplateNode[]} */ + /** @type {import('../types.js').TemplateNode[]} */ const fragment = []; /** @type {null | Node} */ diff --git a/packages/svelte/src/internal/client/operations.js b/packages/svelte/src/internal/client/dom/operations.js similarity index 89% rename from packages/svelte/src/internal/client/operations.js rename to packages/svelte/src/internal/client/dom/operations.js index 5e73eb4d1a..8b8746cb3f 100644 --- a/packages/svelte/src/internal/client/operations.js +++ b/packages/svelte/src/internal/client/dom/operations.js @@ -1,5 +1,5 @@ import { current_hydration_fragment, get_hydration_fragment, hydrating } from './hydration.js'; -import { get_descriptor } from './utils.js'; +import { get_descriptor } from '../utils.js'; // We cache the Node and Element prototype methods, so that we can avoid doing // expensive prototype chain lookups. @@ -13,12 +13,6 @@ var element_prototype; /** @type {Text} */ var text_prototype; -/** @type {Map} */ -var map_prototype = Map.prototype; -var map_set_method = map_prototype.set; -var map_get_method = map_prototype.get; -var map_delete_method = map_prototype.delete; - /** @type {typeof Node.prototype.appendChild} */ var append_child_method; @@ -105,38 +99,6 @@ export function append_child(element, child) { append_child_method.call(element, child); } -/** - * @template K - * @template V - * @param {Map} map - * @param {K} key - * @param {V} value - */ -export function map_set(map, key, value) { - map_set_method.call(map, key, value); -} - -/** - * @template K - * @template V - * @param {Map} map - * @param {K} key - */ -export function map_delete(map, key) { - map_delete_method.call(map, key); -} - -/** - * @template K - * @template V - * @param {Map} map - * @param {K} key - * @return {V} - */ -export function map_get(map, key) { - return map_get_method.call(map, key); -} - /** * @template {Node} N * @param {N} node diff --git a/packages/svelte/src/internal/client/reconciler.js b/packages/svelte/src/internal/client/dom/reconciler.js similarity index 93% rename from packages/svelte/src/internal/client/reconciler.js rename to packages/svelte/src/internal/client/dom/reconciler.js index 0e74b33af6..becdac20d9 100644 --- a/packages/svelte/src/internal/client/reconciler.js +++ b/packages/svelte/src/internal/client/dom/reconciler.js @@ -1,6 +1,6 @@ import { append_child } from './operations.js'; import { current_hydration_fragment, hydrate_block_anchor, hydrating } from './hydration.js'; -import { is_array } from './utils.js'; +import { is_array } from '../utils.js'; /** @param {string} html */ export function create_fragment_from_html(html) { @@ -29,7 +29,7 @@ export function create_fragment_with_script_from_html(html) { } /** - * @param {Array | import('./types.js').TemplateNode} current + * @param {Array | import('../types.js').TemplateNode} current * @param {null | Element} parent_element * @param {null | Text | Element | Comment} sibling * @returns {Text | Element | Comment} @@ -58,7 +58,7 @@ export function insert(current, parent_element, sibling) { } /** - * @param {Array | import('./types.js').TemplateNode} current + * @param {Array | import('../types.js').TemplateNode} current * @returns {Element | Comment | Text} */ export function remove(current) { diff --git a/packages/svelte/src/internal/client/dom/template.js b/packages/svelte/src/internal/client/dom/template.js index 690609203e..6ec040a317 100644 --- a/packages/svelte/src/internal/client/dom/template.js +++ b/packages/svelte/src/internal/client/dom/template.js @@ -1,10 +1,10 @@ -import { current_hydration_fragment, hydrate_block_anchor, hydrating } from '../hydration.js'; -import { child, clone_node, empty } from '../operations.js'; +import { current_hydration_fragment, hydrate_block_anchor, hydrating } from './hydration.js'; +import { child, clone_node, empty } from './operations.js'; import { create_fragment_from_html, create_fragment_with_script_from_html, insert -} from '../reconciler.js'; +} from './reconciler.js'; import { current_block } from '../runtime.js'; import { is_array } from '../utils.js'; diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index f2704e9d26..70d8ba31a1 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -1,25 +1,17 @@ import { DEV } from 'esm-env'; -import { append_child, create_element, empty, init_operations } from './operations.js'; +import { append_child, create_element, empty, init_operations } from './dom/operations.js'; import { PassiveDelegatedEvents } from '../../constants.js'; -import { remove } from './reconciler.js'; -import { - untrack, - flush_sync, - push, - pop, - current_component_context, - deep_read_state -} from './runtime.js'; -import { render_effect, effect, destroy_effect } from './reactivity/effects.js'; +import { remove } from './dom/reconciler.js'; +import { flush_sync, push, pop, current_component_context } from './runtime.js'; +import { render_effect, destroy_effect } from './reactivity/effects.js'; import { current_hydration_fragment, get_hydration_fragment, hydrate_block_anchor, hydrating, set_current_hydration_fragment -} from './hydration.js'; +} from './dom/hydration.js'; import { array_from } from './utils.js'; -import { bind_transition } from './transitions.js'; import { ROOT_BLOCK } from './constants.js'; import { handle_event_propagation } from './dom/elements/events.js'; @@ -83,103 +75,6 @@ export function stringify(value) { return typeof value === 'string' ? value : value == null ? '' : value + ''; } -/** - * @template P - * @param {HTMLElement} dom - * @param {() => import('./types.js').TransitionFn

} get_transition_fn - * @param {(() => P) | null} props - * @param {any} global - * @returns {void} - */ -export function transition(dom, get_transition_fn, props, global = false) { - bind_transition(dom, get_transition_fn, props, 'both', global); -} - -/** - * @template P - * @param {HTMLElement} dom - * @param {() => import('./types.js').TransitionFn

} get_transition_fn - * @param {(() => P) | null} props - * @returns {void} - */ -export function animate(dom, get_transition_fn, props) { - bind_transition(dom, get_transition_fn, props, 'key', false); -} - -/** - * @template P - * @param {HTMLElement} dom - * @param {() => import('./types.js').TransitionFn

} get_transition_fn - * @param {(() => P) | null} props - * @param {any} global - * @returns {void} - */ -function in_fn(dom, get_transition_fn, props, global = false) { - bind_transition(dom, get_transition_fn, props, 'in', global); -} -export { in_fn as in }; - -/** - * @template P - * @param {HTMLElement} dom - * @param {() => import('./types.js').TransitionFn

} get_transition_fn - * @param {(() => P) | null} props - * @param {any} global - * @returns {void} - */ -export function out(dom, get_transition_fn, props, global = false) { - bind_transition(dom, get_transition_fn, props, 'out', global); -} - -/** - * @template P - * @param {Element} dom - * @param {(dom: Element, value?: P) => import('./types.js').ActionPayload

} action - * @param {() => P} [value_fn] - * @returns {void} - */ -export function action(dom, action, value_fn) { - /** @type {undefined | import('./types.js').ActionPayload

} */ - let payload = undefined; - let needs_deep_read = false; - // Action could come from a prop, therefore could be a signal, therefore untrack - // TODO we could take advantage of this and enable https://github.com/sveltejs/svelte/issues/6942 - effect(() => { - if (value_fn) { - const value = value_fn(); - untrack(() => { - if (payload === undefined) { - payload = action(dom, value) || {}; - needs_deep_read = !!payload?.update; - } else { - const update = payload.update; - if (typeof update === 'function') { - update(value); - } - } - }); - // Action's update method is coarse-grained, i.e. when anything in the passed value changes, update. - // This works in legacy mode because of mutable_source being updated as a whole, but when using $state - // together with actions and mutation, it wouldn't notice the change without a deep read. - if (needs_deep_read) { - deep_read_state(value); - } - } else { - untrack(() => (payload = action(dom))); - } - }); - effect(() => { - if (payload !== undefined) { - const destroy = payload.destroy; - if (typeof destroy === 'function') { - return () => { - destroy(); - }; - } - } - }); -} - // TODO 5.0 remove this /** * @deprecated Use `mount` or `hydrate` instead diff --git a/packages/svelte/src/internal/client/utils.js b/packages/svelte/src/internal/client/utils.js index 6b7cba30b8..65a32cdd2b 100644 --- a/packages/svelte/src/internal/client/utils.js +++ b/packages/svelte/src/internal/client/utils.js @@ -13,6 +13,44 @@ export var object_prototype = Object.prototype; export var array_prototype = Array.prototype; export var get_prototype_of = Object.getPrototypeOf; +/** @type {Map} */ +var map_prototype = Map.prototype; +var map_set_method = map_prototype.set; +var map_get_method = map_prototype.get; +var map_delete_method = map_prototype.delete; + +/** + * @template K + * @template V + * @param {Map} map + * @param {K} key + * @param {V} value + */ +export function map_set(map, key, value) { + map_set_method.call(map, key, value); +} + +/** + * @template K + * @template V + * @param {Map} map + * @param {K} key + */ +export function map_delete(map, key) { + map_delete_method.call(map, key); +} + +/** + * @template K + * @template V + * @param {Map} map + * @param {K} key + * @return {V} + */ +export function map_get(map, key) { + return map_get_method.call(map, key); +} + /** * @param {any} thing * @returns {thing is Function} diff --git a/packages/svelte/src/internal/index.js b/packages/svelte/src/internal/index.js index 8ef8ee18ff..71dd6e0f84 100644 --- a/packages/svelte/src/internal/index.js +++ b/packages/svelte/src/internal/index.js @@ -21,15 +21,6 @@ export { hasContext } from './client/runtime.js'; export * from './client/dev/ownership.js'; -export * from './client/dom/bindings/input.js'; -export * from './client/dom/bindings/media.js'; -export * from './client/dom/bindings/navigator.js'; -export * from './client/dom/bindings/props.js'; -export * from './client/dom/bindings/select.js'; -export * from './client/dom/bindings/size.js'; -export * from './client/dom/bindings/this.js'; -export * from './client/dom/bindings/universal.js'; -export * from './client/dom/bindings/window.js'; export { await_block as await } from './client/dom/blocks/await.js'; export { if_block as if } from './client/dom/blocks/if.js'; export { key_block as key } from './client/dom/blocks/key.js'; @@ -40,11 +31,22 @@ export * from './client/dom/blocks/snippet.js'; export * from './client/dom/blocks/svelte-component.js'; export * from './client/dom/blocks/svelte-element.js'; export * from './client/dom/blocks/svelte-head.js'; +export * from './client/dom/elements/actions.js'; export * from './client/dom/elements/attributes.js'; export * from './client/dom/elements/class.js'; export * from './client/dom/elements/events.js'; export * from './client/dom/elements/misc.js'; export * from './client/dom/elements/style.js'; +export * from './client/dom/elements/transitions.js'; +export * from './client/dom/elements/bindings/input.js'; +export * from './client/dom/elements/bindings/media.js'; +export * from './client/dom/elements/bindings/navigator.js'; +export * from './client/dom/elements/bindings/props.js'; +export * from './client/dom/elements/bindings/select.js'; +export * from './client/dom/elements/bindings/size.js'; +export * from './client/dom/elements/bindings/this.js'; +export * from './client/dom/elements/bindings/universal.js'; +export * from './client/dom/elements/bindings/window.js'; export * from './client/dom/legacy/event-modifiers.js'; export * from './client/dom/legacy/lifecycle.js'; export * from './client/dom/legacy/misc.js'; @@ -59,12 +61,12 @@ export * from './client/render.js'; export * from './client/validate.js'; export { raf } from './client/timing.js'; export { proxy, unstate } from './client/proxy.js'; -export { create_custom_element } from './client/custom-element.js'; +export { create_custom_element } from './client/dom/elements/custom-element.js'; export { child, child_frag, sibling, $window as window, $document as document -} from './client/operations.js'; +} from './client/dom/operations.js'; export { noop } from './common.js';