All files / src/internal/client/dom/elements actions.js

100% Statements 41/41
100% Branches 11/11
100% Functions 1/1
100% Lines 39/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 402x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 105x 101x 101x 101x 20x 20x 20x 44x 44x 44x 44x 44x 44x 44x 44x 24x 24x 20x 20x 20x 20x 101x 101x 48x 48x 105x 105x  
/** @import { ActionPayload } from '#client' */
import { effect, render_effect } from '../../reactivity/effects.js';
import { deep_read_state, untrack } from '../../runtime.js';
 
/**
 * @template P
 * @param {Element} dom
 * @param {(dom: Element, value?: P) => ActionPayload<P>} action
 * @param {() => P} [get_value]
 * @returns {void}
 */
export function action(dom, action, get_value) {
	effect(() => {
		var payload = untrack(() => action(dom, get_value?.()) || {});
 
		if (get_value && payload?.update) {
			var inited = false;
 
			render_effect(() => {
				var value = get_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.
				deep_read_state(value);
 
				if (inited) {
					/** @type {Function} */ (payload.update)(value);
				}
			});
 
			inited = true;
		}
 
		if (payload?.destroy) {
			return () => /** @type {Function} */ (payload.destroy)();
		}
	});
}