add static method for element internals formAssociated property

pull/8473/head
Austin John Mayer (井上 オースティン) 3 years ago
parent d42ca041dd
commit 38da3d265b

@ -45,6 +45,7 @@ interface ComponentOptions {
immutable?: boolean; immutable?: boolean;
accessors?: boolean; accessors?: boolean;
preserveWhitespace?: boolean; preserveWhitespace?: boolean;
elementInternals?: boolean;
} }
const regex_leading_directory_separator = /^[/\\]/; const regex_leading_directory_separator = /^[/\\]/;
@ -1570,6 +1571,17 @@ function process_component_options(component: Component, nodes) {
break; break;
} }
case 'elementInternals': {
const value = get_value(attribute, compiler_errors.invalid_attribute_value(name));
if (typeof value !== 'boolean') {
return component.error(attribute, compiler_errors.invalid_attribute_value(name));
}
component_options.elementInternals = value;
break;
}
case 'namespace': { case 'namespace': {
const ns = get_value(attribute, compiler_errors.invalid_namespace_attribute); const ns = get_value(attribute, compiler_errors.invalid_namespace_attribute);

@ -224,7 +224,7 @@ export default {
}, },
invalid_options_attribute: { invalid_options_attribute: {
code: 'invalid-options-attribute', code: 'invalid-options-attribute',
message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes" message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable', 'preserveWhitespace' and 'elementInternals' attributes"
}, },
css_invalid_global: { css_invalid_global: {
code: 'css-invalid-global', code: 'css-invalid-global',

@ -32,7 +32,8 @@ const valid_options = [
'loopGuardTimeout', 'loopGuardTimeout',
'preserveComments', 'preserveComments',
'preserveWhitespace', 'preserveWhitespace',
'cssHash' 'cssHash',
'elementInternals'
]; ];
const valid_css_values = [ const valid_css_values = [

@ -553,6 +553,16 @@ export default function dom(
} }
`[0] as ClassDeclaration; `[0] as ClassDeclaration;
if (component.component_options.elementInternals) {
declaration.body.body.push({
type: "PropertyDefinition",
static: true,
computed: false,
key: { type: "Identifier", name: "formAssociated" },
value: x`true`,
});
}
if (props.length > 0) { if (props.length > 0) {
declaration.body.body.push({ declaration.body.body.push({
type: 'MethodDefinition', type: 'MethodDefinition',

@ -179,6 +179,7 @@ export interface CompileOptions {
legacy?: boolean; legacy?: boolean;
customElement?: boolean; customElement?: boolean;
tag?: string; tag?: string;
elementInternals?: boolean;
css?: 'injected' | 'external' | 'none' | boolean; css?: 'injected' | 'external' | 'none' | boolean;
loopGuardTimeout?: number; loopGuardTimeout?: number;
namespace?: string; namespace?: string;

@ -13,9 +13,9 @@ export function get_current_component() {
/** /**
* Schedules a callback to run immediately before the component is updated after any state change. * Schedules a callback to run immediately before the component is updated after any state change.
* *
* The first time the callback runs will be before the initial `onMount` * The first time the callback runs will be before the initial `onMount`
* *
* https://svelte.dev/docs#run-time-svelte-beforeupdate * https://svelte.dev/docs#run-time-svelte-beforeupdate
*/ */
export function beforeUpdate(fn: () => any) { export function beforeUpdate(fn: () => any) {
@ -23,12 +23,12 @@ export function beforeUpdate(fn: () => any) {
} }
/** /**
* The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
* It must be called during the component's initialisation (but doesn't need to live *inside* the component; * It must be called during the component's initialisation (but doesn't need to live *inside* the component;
* it can be called from an external module). * it can be called from an external module).
* *
* `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api). * `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
* *
* https://svelte.dev/docs#run-time-svelte-onmount * https://svelte.dev/docs#run-time-svelte-onmount
*/ */
export function onMount(fn: () => any) { export function onMount(fn: () => any) {
@ -37,19 +37,19 @@ export function onMount(fn: () => any) {
/** /**
* Schedules a callback to run immediately after the component has been updated. * Schedules a callback to run immediately after the component has been updated.
* *
* The first time the callback runs will be after the initial `onMount` * The first time the callback runs will be after the initial `onMount`
*/ */
export function afterUpdate(fn: () => any) { export function afterUpdate(fn: () => any) {
get_current_component().$$.after_update.push(fn); get_current_component().$$.after_update.push(fn);
} }
/** /**
* Schedules a callback to run immediately before the component is unmounted. * Schedules a callback to run immediately before the component is unmounted.
* *
* Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the
* only one that runs inside a server-side component. * only one that runs inside a server-side component.
* *
* https://svelte.dev/docs#run-time-svelte-ondestroy * https://svelte.dev/docs#run-time-svelte-ondestroy
*/ */
export function onDestroy(fn: () => any) { export function onDestroy(fn: () => any) {
@ -61,15 +61,15 @@ export interface DispatchOptions {
} }
/** /**
* Creates an event dispatcher that can be used to dispatch [component events](/docs#template-syntax-component-directives-on-eventname). * Creates an event dispatcher that can be used to dispatch [component events](/docs#template-syntax-component-directives-on-eventname).
* Event dispatchers are functions that can take two arguments: `name` and `detail`. * Event dispatchers are functions that can take two arguments: `name` and `detail`.
* *
* Component events created with `createEventDispatcher` create a * Component events created with `createEventDispatcher` create a
* [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent).
* These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture). * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture).
* The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail)
* property and can contain any type of data. * property and can contain any type of data.
* *
* https://svelte.dev/docs#run-time-svelte-createeventdispatcher * https://svelte.dev/docs#run-time-svelte-createeventdispatcher
*/ */
export function createEventDispatcher<EventMap extends {} = any>(): < export function createEventDispatcher<EventMap extends {} = any>(): <
@ -99,12 +99,12 @@ export function createEventDispatcher<EventMap extends {} = any>(): <
} }
/** /**
* Associates an arbitrary `context` object with the current component and the specified `key` * Associates an arbitrary `context` object with the current component and the specified `key`
* and returns that object. The context is then available to children of the component * and returns that object. The context is then available to children of the component
* (including slotted content) with `getContext`. * (including slotted content) with `getContext`.
* *
* Like lifecycle functions, this must be called during component initialisation. * Like lifecycle functions, this must be called during component initialisation.
* *
* https://svelte.dev/docs#run-time-svelte-setcontext * https://svelte.dev/docs#run-time-svelte-setcontext
*/ */
export function setContext<T>(key, context: T): T { export function setContext<T>(key, context: T): T {
@ -113,9 +113,9 @@ export function setContext<T>(key, context: T): T {
} }
/** /**
* Retrieves the context that belongs to the closest parent component with the specified `key`. * Retrieves the context that belongs to the closest parent component with the specified `key`.
* Must be called during component initialisation. * Must be called during component initialisation.
* *
* https://svelte.dev/docs#run-time-svelte-getcontext * https://svelte.dev/docs#run-time-svelte-getcontext
*/ */
export function getContext<T>(key): T { export function getContext<T>(key): T {
@ -123,10 +123,10 @@ export function getContext<T>(key): T {
} }
/** /**
* Retrieves the whole context map that belongs to the closest parent component. * Retrieves the whole context map that belongs to the closest parent component.
* Must be called during component initialisation. Useful, for example, if you * Must be called during component initialisation. Useful, for example, if you
* programmatically create a component and want to pass the existing context to it. * programmatically create a component and want to pass the existing context to it.
* *
* https://svelte.dev/docs#run-time-svelte-getallcontexts * https://svelte.dev/docs#run-time-svelte-getallcontexts
*/ */
export function getAllContexts<T extends Map<any, any> = Map<any, any>>(): T { export function getAllContexts<T extends Map<any, any> = Map<any, any>>(): T {
@ -134,13 +134,13 @@ export function getAllContexts<T extends Map<any, any> = Map<any, any>>(): T {
} }
/** /**
* Checks whether a given `key` has been set in the context of a parent component. * Checks whether a given `key` has been set in the context of a parent component.
* Must be called during component initialisation. * Must be called during component initialisation.
* *
* https://svelte.dev/docs#run-time-svelte-hascontext * https://svelte.dev/docs#run-time-svelte-hascontext
*/ */
export function hasContext(key): boolean { export function hasContext(key): boolean {
return get_current_component().$$.context.has(key); return get_current_component().$$.context.has(key);
} }
// TODO figure out if we still want to support // TODO figure out if we still want to support
@ -154,3 +154,23 @@ export function bubble(component, event) {
callbacks.slice().forEach(fn => fn.call(this, event)); callbacks.slice().forEach(fn => fn.call(this, event));
} }
} }
// Element internals not in TS3.x.x
declare global {
// eslint-disable-next-line
interface ElementInternals {}
interface HTMLElement {
attachInternals(): ElementInternals;
}
}
/**
* Creates element internals for Web Components to participate in forms.
*/
export function createCustomElementInternals(): ElementInternals {
const component = get_current_component();
if (!(component instanceof HTMLElement)) {
throw ReferenceError('NotHTMLElement');
}
return component.attachInternals();
}

Loading…
Cancel
Save