diff --git a/.changeset/nine-houses-flow.md b/.changeset/nine-houses-flow.md new file mode 100644 index 0000000000..d3783c6c1c --- /dev/null +++ b/.changeset/nine-houses-flow.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: allow child element with slot attribute within svelte:element diff --git a/.changeset/twelve-suits-drive.md b/.changeset/twelve-suits-drive.md new file mode 100644 index 0000000000..de7390ae95 --- /dev/null +++ b/.changeset/twelve-suits-drive.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: Add data-* to svg attributes diff --git a/documentation/docs/02-template-syntax/02-basic-markup.md b/documentation/docs/02-template-syntax/02-basic-markup.md index 7656a599be..9e230078b5 100644 --- a/documentation/docs/02-template-syntax/02-basic-markup.md +++ b/documentation/docs/02-template-syntax/02-basic-markup.md @@ -85,13 +85,13 @@ An element or component can have multiple spread attributes, interspersed with r ``` -`$$props` references all props that are passed to a component, including ones that are not declared with `export`. It is not generally recommended, as it is difficult for Svelte to optimise. But it can be useful in rare cases – for example, when you don't know at compile time what props might be passed to a component. +`$$props` references all props that are passed to a component, including ones that are not declared with `export`. Using `$$props` will not perform as well as references to a specific prop because changes to any prop will cause Svelte to recheck all usages of `$$props`. But it can be useful in some cases – for example, when you don't know at compile time what props might be passed to a component. ```svelte ``` -`$$restProps` contains only the props which are _not_ declared with `export`. It can be used to pass down other unknown attributes to an element in a component. It shares the same optimisation problems as `$$props`, and is likewise not recommended. +`$$restProps` contains only the props which are _not_ declared with `export`. It can be used to pass down other unknown attributes to an element in a component. It shares the same performance characteristics compared to specific property access as `$$props`. ```svelte @@ -113,11 +113,12 @@ Text can also contain JavaScript expressions: > If you're using a regular expression (`RegExp`) [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor), you'll need to wrap it in parentheses. + ```svelte

Hello {name}!

{a} + {b} = {a + b}.

-
{/^[A-Za-z ]+$/.test(value) ? x : y}
+
{(/^[A-Za-z ]+$/).test(value) ? x : y}
``` ## Comments diff --git a/documentation/docs/02-template-syntax/06-component-directives.md b/documentation/docs/02-template-syntax/06-component-directives.md index b072074a59..f1d49323bd 100644 --- a/documentation/docs/02-template-syntax/06-component-directives.md +++ b/documentation/docs/02-template-syntax/06-component-directives.md @@ -8,13 +8,34 @@ title: Component directives on:eventname={handler} ``` -Components can emit events using [createEventDispatcher](/docs/svelte#createeventdispatcher), or by forwarding DOM events. Listening for component events looks the same as listening for DOM events: +Components can emit events using [`createEventDispatcher`](/docs/svelte#createeventdispatcher) or by forwarding DOM events. + +```svelte + + + + + + + + +``` + +Listening for component events looks the same as listening for DOM events: ```svelte ``` -As with DOM events, if the `on:` directive is used without a value, the component will _forward_ the event, meaning that a consumer of the component can listen for it. +As with DOM events, if the `on:` directive is used without a value, the event will be forwarded, meaning that a consumer can listen for it. ```svelte @@ -92,6 +113,8 @@ You can bind to component props using the same syntax as for elements. ``` +While Svelte props are reactive without binding, that reactivity only flows downward into the component by default. Using `bind:property` allows changes to the property from within the component to flow back up out of the component. + ## bind:this ```svelte @@ -100,10 +123,10 @@ bind:this={component_instance} Components also support `bind:this`, allowing you to interact with component instances programmatically. -> Note that we can't do `{cart.empty}` since `cart` is `undefined` when the button is first rendered and throws an error. - ```svelte ``` + +> Note that we can't do `{cart.empty}` since `cart` is `undefined` when the button is first rendered and throws an error. diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index ec450284c5..9a7e7b3aa8 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -1451,6 +1451,9 @@ export interface SVGAttributes extends AriaAttributes, DO yChannelSelector?: string | undefined | null; z?: number | string | undefined | null; zoomAndPan?: string | undefined | null; + + // allow any data- attribute + [key: `data-${string}`]: any; } export interface HTMLWebViewAttributes extends HTMLAttributes { diff --git a/packages/svelte/src/compiler/compile/nodes/Element.js b/packages/svelte/src/compiler/compile/nodes/Element.js index 6715eb1e5d..654c2c48f0 100644 --- a/packages/svelte/src/compiler/compile/nodes/Element.js +++ b/packages/svelte/src/compiler/compile/nodes/Element.js @@ -530,7 +530,6 @@ export default class Element extends Node { this.name === 'option' || this.is_dynamic_element || this.tag_expr.dynamic_dependencies().length || - this.is_dynamic_element || component.compile_options.dev ) { this.parent.cannot_use_innerhtml(); // need to use add_location @@ -1414,7 +1413,9 @@ const regex_minus_sign = /-/; function within_custom_element(parent) { while (parent) { if (parent.type === 'InlineComponent') return false; - if (parent.type === 'Element' && regex_minus_sign.test(parent.name)) return true; + if (parent.type === 'Element') { + if (regex_minus_sign.test(parent.name) || parent.is_dynamic_element) return true; + } parent = parent.parent; } return false; diff --git a/packages/svelte/test/helpers.js b/packages/svelte/test/helpers.js index 596086f986..b5ee539be8 100644 --- a/packages/svelte/test/helpers.js +++ b/packages/svelte/test/helpers.js @@ -100,7 +100,7 @@ export function show_output(cwd, options = {}) { }); } -const svelte_path = fileURLToPath(new URL('..', import.meta.url)).replace(/\\/g, '/'); +const svelte_path = fileURLToPath(new URL('..', import.meta.url).href).replace(/\\/g, '/'); const AsyncFunction = /** @type {typeof Function} */ (async function () {}.constructor); diff --git a/packages/svelte/test/runtime/samples/slot-in-dynamic-element/_config.js b/packages/svelte/test/runtime/samples/slot-in-dynamic-element/_config.js new file mode 100644 index 0000000000..589e57d78e --- /dev/null +++ b/packages/svelte/test/runtime/samples/slot-in-dynamic-element/_config.js @@ -0,0 +1,7 @@ +export default { + html: ` + +
header header header
+
+ ` +}; diff --git a/packages/svelte/test/runtime/samples/slot-in-dynamic-element/main.svelte b/packages/svelte/test/runtime/samples/slot-in-dynamic-element/main.svelte new file mode 100644 index 0000000000..38d7cd233e --- /dev/null +++ b/packages/svelte/test/runtime/samples/slot-in-dynamic-element/main.svelte @@ -0,0 +1,7 @@ + + + +
header header header
+
\ No newline at end of file