remove the option to pass function to `shadow`

pull/17088/head
Bladesheng 8 months ago
parent 8d32602f99
commit 974bf0c6ba

@ -2,4 +2,4 @@
'svelte': minor
---
feat: allow passing `ShadowRootInit` to custom element `shadow` option
feat: allow passing `ShadowRootInit` object to custom element `shadow` option

@ -69,7 +69,7 @@ When constructing a custom element, you can tailor several aspects by defining `
- `shadow`: an optional property to modify shadow root properties. It accepts the following values:
- `"none"`: No shadow root is created. Note that styles are then no longer encapsulated, and you can't use slots.
- `"open"`: Shadow root is created with the `mode: "open"` option.
- [`ShadowRootInit`](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#options): You can pass a settings object that will be passed to `attachShadow()` when shadow root is created. Alternatively, you can pass function that returns the options object. This comes in handy if you need to dynamically change the options values - for example, based on value of environment variables.
- [`ShadowRootInit`](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#options): You can pass a settings object that will be passed to `attachShadow()` when shadow root is created.
- `props`: an optional property to modify certain details and behaviors of your component's properties. It offers the following settings:
- `attribute: string`: To update a custom element's prop, you have two alternatives: either set the property on the custom element's reference as illustrated above or use an HTML attribute. For the latter, the default attribute name is the lowercase property name. Modify this by assigning `attribute: "<desired name>"`.
- `reflect: boolean`: By default, updated prop values do not reflect back to the DOM. To enable this behavior, set `reflect: true`.
@ -81,11 +81,11 @@ When constructing a custom element, you can tailor several aspects by defining `
<svelte:options
customElement={{
tag: 'custom-element',
shadow: () => ({
shadow: {
mode: import.meta.env.DEV ? 'open' : 'closed',
clonable: true,
// ...
}),
},
props: {
name: { reflect: true, type: 'Number', attribute: 'element-index' }
},

@ -1090,7 +1090,7 @@ Value must be %list%, if specified
### svelte_options_invalid_customelement
```
"customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | `ShadowRootInit` | (() => `ShadowRootInit` | undefined); props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
"customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | `ShadowRootInit`; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
```
### svelte_options_invalid_customelement_props
@ -1102,7 +1102,7 @@ Value must be %list%, if specified
### svelte_options_invalid_customelement_shadow
```
"shadow" must be either "open", "none", `ShadowRootInit` or function that returns `ShadowRootInit`
"shadow" must be either "open", "none" or `ShadowRootInit` object
```
See https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#options for more information on valid shadow root constructor options

@ -2061,12 +2061,7 @@ export interface SvelteHTMLElements {
| undefined
| {
tag?: string;
shadow?:
| 'open'
| 'none'
| ShadowRootInit
| (() => ShadowRootInit | undefined)
| undefined;
shadow?: 'open' | 'none' | ShadowRootInit | undefined;
props?:
| Record<
string,

@ -403,7 +403,7 @@ HTML restricts where certain elements can appear. In case of a violation the bro
## svelte_options_invalid_customelement
> "customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | `ShadowRootInit` | (() => `ShadowRootInit` | undefined); props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
> "customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | `ShadowRootInit`; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
## svelte_options_invalid_customelement_props
@ -411,7 +411,7 @@ HTML restricts where certain elements can appear. In case of a violation the bro
## svelte_options_invalid_customelement_shadow
> "shadow" must be either "open", "none", `ShadowRootInit` or function that returns `ShadowRootInit`
> "shadow" must be either "open", "none" or `ShadowRootInit` object.
See https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#options for more information on valid shadow root constructor options

@ -1532,12 +1532,12 @@ export function svelte_options_invalid_attribute_value(node, list) {
}
/**
* "customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | `ShadowRootInit` | (() => `ShadowRootInit` | undefined); props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
* "customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | `ShadowRootInit`; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function svelte_options_invalid_customelement(node) {
e(node, 'svelte_options_invalid_customelement', `"customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | \`ShadowRootInit\` | (() => \`ShadowRootInit\` | undefined); props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }\nhttps://svelte.dev/e/svelte_options_invalid_customelement`);
e(node, 'svelte_options_invalid_customelement', `"customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none" | \`ShadowRootInit\`; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }\nhttps://svelte.dev/e/svelte_options_invalid_customelement`);
}
/**
@ -1550,12 +1550,12 @@ export function svelte_options_invalid_customelement_props(node) {
}
/**
* "shadow" must be either "open", "none", `ShadowRootInit` or function that returns `ShadowRootInit`
* "shadow" must be either "open", "none" or `ShadowRootInit` object
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function svelte_options_invalid_customelement_shadow(node) {
e(node, 'svelte_options_invalid_customelement_shadow', `"shadow" must be either "open", "none", \`ShadowRootInit\` or function that returns \`ShadowRootInit\`\nhttps://svelte.dev/e/svelte_options_invalid_customelement_shadow`);
e(node, 'svelte_options_invalid_customelement_shadow', `"shadow" must be either "open", "none" or \`ShadowRootInit\` object\nhttps://svelte.dev/e/svelte_options_invalid_customelement_shadow`);
}
/**

@ -135,10 +135,7 @@ export default function read_options(node) {
if (shadow) {
if (shadow.type === 'Literal' && (shadow.value === 'open' || shadow.value === 'none')) {
ce.shadow = shadow.value;
} else if (
shadow.type === 'ObjectExpression' ||
shadow.type === 'ArrowFunctionExpression'
) {
} else if (shadow.type === 'ObjectExpression') {
ce.shadow = shadow;
} else {
e.svelte_options_invalid_customelement_shadow(attribute);

@ -644,7 +644,7 @@ export function client_component(analysis, options) {
analysis.exports.map(({ name, alias }) => b.literal(alias ?? name))
);
/** @type {ESTree.ObjectExpression | ESTree.ArrowFunctionExpression | undefined} */
/** @type {ESTree.ObjectExpression | undefined} */
let shadow_root_init;
if (typeof ce === 'boolean' || ce.shadow === 'open' || ce.shadow === undefined) {
shadow_root_init = b.object([b.init('mode', b.literal('open'))]);

@ -88,7 +88,7 @@ export namespace AST {
css?: 'injected';
customElement?: {
tag?: string;
shadow?: 'open' | 'none' | ObjectExpression | ArrowFunctionExpression | undefined;
shadow?: 'open' | 'none' | ObjectExpression | undefined;
props?: Record<
string,
{

@ -41,19 +41,17 @@ if (typeof HTMLElement === 'function') {
/**
* @param {*} $$componentCtor
* @param {*} $$slots
* @param {ShadowRootInit | (() => ShadowRootInit | undefined) | undefined} shadow_root_init
* @param {ShadowRootInit | undefined} shadow_root_init
*/
constructor($$componentCtor, $$slots, shadow_root_init) {
super();
this.$$ctor = $$componentCtor;
this.$$s = $$slots;
const shadow_root_init_value =
typeof shadow_root_init === 'function' ? shadow_root_init() : shadow_root_init;
if (shadow_root_init_value) {
if (shadow_root_init) {
// We need to store the reference to shadow root, because `closed` shadow root cannot be
// accessed with `this.shadowRoot`.
this.$$shadowRoot = this.attachShadow(shadow_root_init_value);
this.$$shadowRoot = this.attachShadow(shadow_root_init);
}
}
@ -284,7 +282,7 @@ function get_custom_elements_slots(element) {
* @param {Record<string, CustomElementPropDefinition>} props_definition The props to observe
* @param {string[]} slots The slots to create
* @param {string[]} exports Explicitly exported values, other than props
* @param {ShadowRootInit | (() => ShadowRootInit | undefined) | undefined} shadow_root_init Options passed to shadow DOM constructor
* @param {ShadowRootInit | undefined} shadow_root_init Options passed to shadow DOM constructor
* @param {(ce: new () => HTMLElement) => new () => HTMLElement} [extend]
*/
export function create_custom_element(

@ -1,19 +0,0 @@
import { test } from '../../assert';
const tick = () => Promise.resolve();
export default test({
async test({ assert, target, window }) {
window.temp_variable = true;
target.innerHTML = '<custom-element></custom-element>';
await tick();
/** @type {ShadowRoot} */
const shadowRoot = target.querySelector('custom-element').shadowRoot;
assert.equal(shadowRoot.mode, 'open');
assert.equal(shadowRoot.clonable, true);
delete window.temp_variable;
}
});

@ -1,12 +0,0 @@
<svelte:options
customElement={{
tag: 'custom-element',
shadow: () => ({
mode: 'open',
// This could also be some env variable.
clonable: window.temp_variable
})
}}
/>
<h1>Hello world!</h1>

@ -1,7 +1,7 @@
[
{
"code": "svelte_options_invalid_customelement",
"message": "\"customElement\" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: \"open\" | \"none\" | `ShadowRootInit` | (() => `ShadowRootInit` | undefined); props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }",
"message": "\"customElement\" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: \"open\" | \"none\" | `ShadowRootInit`; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }",
"start": {
"line": 1,
"column": 16

@ -1224,7 +1224,7 @@ declare module 'svelte/compiler' {
css?: 'injected';
customElement?: {
tag?: string;
shadow?: 'open' | 'none' | ObjectExpression | ArrowFunctionExpression | undefined;
shadow?: 'open' | 'none' | ObjectExpression | undefined;
props?: Record<
string,
{
@ -2152,10 +2152,10 @@ declare module 'svelte/motion' {
* const tween = Tween.of(() => number);
* </script>
* ```
*
*
*/
static of<U>(fn: () => U, options?: TweenedOptions<U> | undefined): Tween<U>;
constructor(value: T, options?: TweenedOptions<T>);
/**
* Sets `tween.target` to `value` and returns a `Promise` that resolves if and when `tween.current` catches up to it.
@ -2206,7 +2206,7 @@ declare module 'svelte/reactivity' {
* ```
*/
export class SvelteDate extends Date {
constructor(...params: any[]);
#private;
}
@ -2242,12 +2242,12 @@ declare module 'svelte/reactivity' {
* {#if monkeys.has('🙊')}<p>speak no evil</p>{/if}
* ```
*
*
*
*/
export class SvelteSet<T> extends Set<T> {
constructor(value?: Iterable<T> | null | undefined);
add(value: T): this;
#private;
}
@ -2293,12 +2293,12 @@ declare module 'svelte/reactivity' {
* {/if}
* ```
*
*
*
*/
export class SvelteMap<K, V> extends Map<K, V> {
constructor(value?: Iterable<readonly [K, V]> | null | undefined);
set(key: K, value: V): this;
#private;
}
@ -2361,7 +2361,7 @@ declare module 'svelte/reactivity' {
* ```
*/
export class SvelteURLSearchParams extends URLSearchParams {
[REPLACE](params: URLSearchParams): void;
#private;
}
@ -2437,7 +2437,7 @@ declare module 'svelte/reactivity' {
*/
export function createSubscriber(start: (update: () => void) => (() => void) | void): () => void;
class ReactiveValue<T> {
constructor(fn: () => T, onsubscribe: (update: () => void) => void);
get current(): T;
#private;
@ -2502,7 +2502,7 @@ declare module 'svelte/reactivity/window' {
get current(): number | undefined;
};
class ReactiveValue<T> {
constructor(fn: () => T, onsubscribe: (update: () => void) => void);
get current(): T;
#private;

Loading…
Cancel
Save