svelte
Advanced tools
Comparing version 5.0.0-next.80 to 5.0.0-next.81
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.0.0-next.80", | ||
"version": "5.0.0-next.81", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "types": "./types/index.d.ts", |
@@ -403,5 +403,5 @@ import is_reference from 'is-reference'; | ||
) { | ||
// <div slot="..."> inherits the scope above the component, because slots are hella weird | ||
scopes.set(child, state.scope); | ||
visit(child); | ||
// <div slot="..."> inherits the scope above the component unless the component is a named slot itself, because slots are hella weird | ||
scopes.set(child, is_default_slot ? state.scope : scope); | ||
visit(child, { scope: is_default_slot ? state.scope : scope }); | ||
} else { | ||
@@ -603,22 +603,34 @@ if (child.type === 'ExpressionTag') { | ||
AwaitBlock(node, context) { | ||
context.next(); | ||
context.visit(node.expression); | ||
if (node.then && node.value !== null) { | ||
const then_scope = /** @type {Scope} */ (scopes.get(node.then)); | ||
const value_scope = context.state.scope.child(); | ||
for (const id of extract_identifiers(node.value)) { | ||
then_scope.declare(id, 'normal', 'const'); | ||
value_scope.declare(id, 'normal', 'const'); | ||
if (node.pending) { | ||
context.visit(node.pending); | ||
} | ||
if (node.then) { | ||
context.visit(node.then); | ||
if (node.value) { | ||
const then_scope = /** @type {Scope} */ (scopes.get(node.then)); | ||
const value_scope = context.state.scope.child(); | ||
scopes.set(node.value, value_scope); | ||
context.visit(node.value, { scope: value_scope }); | ||
for (const id of extract_identifiers(node.value)) { | ||
then_scope.declare(id, 'normal', 'const'); | ||
value_scope.declare(id, 'normal', 'const'); | ||
} | ||
} | ||
scopes.set(node.value, value_scope); | ||
} | ||
if (node.catch && node.error !== null) { | ||
const catch_scope = /** @type {Scope} */ (scopes.get(node.catch)); | ||
const error_scope = context.state.scope.child(); | ||
for (const id of extract_identifiers(node.error)) { | ||
catch_scope.declare(id, 'normal', 'const'); | ||
error_scope.declare(id, 'normal', 'const'); | ||
if (node.catch) { | ||
context.visit(node.catch); | ||
if (node.error) { | ||
const catch_scope = /** @type {Scope} */ (scopes.get(node.catch)); | ||
const error_scope = context.state.scope.child(); | ||
scopes.set(node.error, error_scope); | ||
context.visit(node.error, { scope: error_scope }); | ||
for (const id of extract_identifiers(node.error)) { | ||
catch_scope.declare(id, 'normal', 'const'); | ||
error_scope.declare(id, 'normal', 'const'); | ||
} | ||
} | ||
scopes.set(node.error, error_scope); | ||
} | ||
@@ -625,0 +637,0 @@ }, |
@@ -86,3 +86,4 @@ export const EACH_ITEM_REACTIVE = 1; | ||
'seamless', | ||
'selected' | ||
'selected', | ||
'webkitdirectory' | ||
]; | ||
@@ -89,0 +90,0 @@ |
import { effect } from '../../../reactivity/effects.js'; | ||
import { untrack } from '../../../runtime.js'; | ||
@@ -29,22 +30,39 @@ /** | ||
/** | ||
* Finds the containing `<select>` element and potentially updates its `selected` state. | ||
* @param {HTMLOptionElement} option | ||
* @returns {void} | ||
* Selects the correct option(s) if `value` is given, | ||
* and then sets up a mutation observer to sync the | ||
* current selection to the dom when it changes. Such | ||
* changes could for example occur when options are | ||
* inside an `#each` block. | ||
* @template V | ||
* @param {HTMLSelectElement} select | ||
* @param {() => V} [get_value] | ||
*/ | ||
export function selected(option) { | ||
// Inside an effect because the element might not be connected | ||
// to the parent <select> yet when this is called | ||
export function init_select(select, get_value) { | ||
effect(() => { | ||
var select = option.parentNode; | ||
while (select != null) { | ||
if (select.nodeName === 'SELECT') break; | ||
select = select.parentNode; | ||
if (get_value) { | ||
select_option(select, untrack(get_value)); | ||
} | ||
// @ts-ignore | ||
if (select != null && option.__value === select.__value) { | ||
// never set to false, since this causes browser to select default option | ||
option.selected = true; | ||
} | ||
var observer = new MutationObserver(() => { | ||
// @ts-ignore | ||
var value = select.__value; | ||
select_option(select, value); | ||
// Deliberately don't update the potential binding value, | ||
// the model should be preserved unless explicitly changed | ||
}); | ||
observer.observe(select, { | ||
// Listen to option element changes | ||
childList: true, | ||
subtree: true, // because of <optgroup> | ||
// Listen to option element value attribute changes | ||
// (doesn't get notified of select value changes, | ||
// because that property is not reflected as an attribute) | ||
attributes: true, | ||
attributeFilter: ['value'] | ||
}); | ||
return () => { | ||
observer.disconnect(); | ||
}; | ||
}); | ||
@@ -82,2 +100,3 @@ } | ||
// Mounting and value undefined -> take selection from dom | ||
if (mounting && value === undefined) { | ||
@@ -96,2 +115,5 @@ /** @type {HTMLOptionElement | null} */ | ||
}); | ||
// don't pass get_value, we already initialize it in the effect above | ||
init_select(select); | ||
} | ||
@@ -98,0 +120,0 @@ |
@@ -6,3 +6,3 @@ import { hydrating } from '../hydration.js'; | ||
/** | ||
* @param {Element} dom | ||
* @param {HTMLElement} dom | ||
* @param {() => string} value | ||
@@ -18,6 +18,46 @@ * @returns {void} | ||
/** | ||
* @param {Element} dom | ||
* @param {SVGElement} dom | ||
* @param {() => string} value | ||
* @returns {void} | ||
*/ | ||
export function svg_class_name_effect(dom, value) { | ||
render_effect(() => { | ||
svg_class_name(dom, value()); | ||
}); | ||
} | ||
/** | ||
* @param {SVGElement} dom | ||
* @param {string} value | ||
* @returns {void} | ||
*/ | ||
export function svg_class_name(dom, value) { | ||
// @ts-expect-error need to add __className to patched prototype | ||
var prev_class_name = dom.__className; | ||
var next_class_name = to_class(value); | ||
if (hydrating && dom.getAttribute('class') === next_class_name) { | ||
// In case of hydration don't reset the class as it's already correct. | ||
// @ts-expect-error need to add __className to patched prototype | ||
dom.__className = next_class_name; | ||
} else if ( | ||
prev_class_name !== next_class_name || | ||
(hydrating && dom.getAttribute('class') !== next_class_name) | ||
) { | ||
if (next_class_name === '') { | ||
dom.removeAttribute('class'); | ||
} else { | ||
dom.setAttribute('class', next_class_name); | ||
} | ||
// @ts-expect-error need to add __className to patched prototype | ||
dom.__className = next_class_name; | ||
} | ||
} | ||
/** | ||
* @param {HTMLElement} dom | ||
* @param {string} value | ||
* @returns {void} | ||
*/ | ||
export function class_name(dom, value) { | ||
@@ -36,3 +76,6 @@ // @ts-expect-error need to add __className to patched prototype | ||
) { | ||
if (next_class_name === '') { | ||
// Removing the attribute when the value is only an empty string causes | ||
// peformance issues vs simply making the className an empty string. So | ||
// we should only remove the class if the the value is nullish. | ||
if (value == null) { | ||
dom.removeAttribute('class'); | ||
@@ -39,0 +82,0 @@ } else { |
@@ -20,3 +20,6 @@ import { render_effect } from '../../reactivity/effects.js'; | ||
function target_handler(/** @type {Event} */ event) { | ||
handle_event_propagation(dom, event); | ||
if (!capture) { | ||
// Only call in the bubble phase, else delegated events would be called before the capturing events | ||
handle_event_propagation(dom, event); | ||
} | ||
if (!event.cancelBubble) { | ||
@@ -23,0 +26,0 @@ return handler.call(this, event); |
@@ -44,3 +44,3 @@ import { DEV } from 'esm-env'; | ||
if (current_reaction !== null) { | ||
if (current_reaction !== null && (current_reaction.f & DERIVED) !== 0) { | ||
if (current_reaction.deriveds === null) { | ||
@@ -47,0 +47,0 @@ current_reaction.deriveds = [signal]; |
@@ -82,2 +82,3 @@ import { define_property } from '../internal/client/utils.js'; | ||
for (const key of Object.keys(this.#instance)) { | ||
if (key === '$set' || key === '$destroy' || key === '$on') continue; | ||
define_property(this, key, { | ||
@@ -84,0 +85,0 @@ get() { |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.0.0-next.80'; | ||
export const VERSION = '5.0.0-next.81'; | ||
export const PUBLIC_VERSION = '5'; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
1946289
42517