Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: formatting in new web-components content #3114

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 24 additions & 30 deletions src/guide/extras/web-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ export function register() {
}
```

A consumer can use the elements in a Vue file,
A consumer can use the elements in a Vue file:

```vue
<script setup>
Expand All @@ -253,7 +253,7 @@ register()
</template>
```

or in any other framework such as one with JSX, and with custom names:
Or in any other framework such as one with JSX, and with custom names:

```jsx
import { MyFoo, MyBar } from 'path/to/elements.js'
Expand All @@ -263,8 +263,8 @@ customElements.define('some-bar', MyBar)

export function MyComponent() {
return <>
<some-foo ...>
<some-bar ...></some-bar>
<some-foo ... >
<some-bar ... ></some-bar>
</some-foo>
</>
}
Expand Down Expand Up @@ -293,24 +293,24 @@ customElements.define('some-element', SomeElement)
// Add the new element type to Vue's GlobalComponents type.
declare module 'vue' {
interface GlobalComponents {
// Be sure to pass in the Vue component type here (SomeComponent, *not* SomeElement).
// Custom Elements require a hyphen in their name, so use the hyphenated element name here.
// Be sure to pass in the Vue component type here
// (SomeComponent, *not* SomeElement).
// Custom Elements require a hyphen in their name,
// so use the hyphenated element name here.
'some-element': typeof SomeComponent
}
}
```

## Non-Vue Web Components and TypeScript

Here is the recommended way to enable type checking in SFC templates of Custom
Elements that are not built with Vue.
Here is the recommended way to enable type checking in SFC templates of Custom Elements that are not built with Vue.

> [!Note]
> This approach is one possible way to do it, but it may vary depending on the
> framework being used to create the custom elements.

Suppose we have a custom element with some JS properties and events defined, and
it is shipped in a library called `some-lib`:
Suppose we have a custom element with some JS properties and events defined, and it is shipped in a library called `some-lib`:

```ts
// file: some-lib/src/SomeElement.ts
Expand Down Expand Up @@ -348,11 +348,9 @@ export class AppleFellEvent extends Event {
}
```

The implementation details have been omitted, but the important part is that we
have type definitions for two things: prop types and event types.
The implementation details have been omitted, but the important part is that we have type definitions for two things: prop types and event types.

Let's create a type helper for easily registering custom element type
definitions in Vue:
Let's create a type helper for easily registering custom element type definitions in Vue:

```ts
// file: some-lib/src/DefineCustomElement.ts
Expand All @@ -367,15 +365,17 @@ type DefineCustomElement<
// specifically reads prop definitions from the `$props` type. Note that we
// combine the element's props with the global HTML props and Vue's special
// props.
/** @deprecated Do not use the $props property on a Custom Element ref, this is for template prop types only. */
/** @deprecated Do not use the $props property on a Custom Element ref,
this is for template prop types only. */
$props: HTMLAttributes &
Partial<Pick<ElementType, SelectedAttributes>> &
PublicProps

// Use $emit to specifically define event types. Vue specifically reads event
// types from the `$emit` type. Note that `$emit` expects a particular format
// that we map `Events` to.
/** @deprecated Do not use the $emit property on a Custom Element ref, this is for template prop types only. */
/** @deprecated Do not use the $emit property on a Custom Element ref,
this is for template prop types only. */
$emit: VueEmit<Events>
}

Expand All @@ -390,13 +390,12 @@ type VueEmit<T extends EventMap> = EmitFn<{
```

> [!Note]
> We marked `$props` and `$emit` as deprecated so that when we get a `ref` to a
> custom element we will not be tempted to use these properties, as these
> We marked `$props` and `$emit` as deprecated so that when we get a `ref` to
> a custom element we will not be tempted to use these properties, as these
> properties are for type checking purposes only when it comes to custom elements.
> These properties do not actually exist on the custom element instances.

Using the type helper we can now select the JS properties that should be exposed
for type checking in Vue templates:
Using the type helper we can now select the JS properties that should be exposed for type checking in Vue templates:

```ts
// file: some-lib/src/SomeElement.vue.ts
Expand All @@ -421,8 +420,7 @@ declare module 'vue' {
}
```

Suppose that `some-lib` builds its source TypeScript files into a `dist/` folder. A user of
`some-lib` can then import `SomeElement` and use it in a Vue SFC like so:
Suppose that `some-lib` builds its source TypeScript files into a `dist/` folder. A user of `some-lib` can then import `SomeElement` and use it in a Vue SFC like so:

```vue
<script setup lang="ts">
Expand All @@ -446,7 +444,8 @@ onMounted(() => {
el.value!.someMethod()
)

// Do not use these props, they are `undefined` (IDE will show them crossed out):
// Do not use these props, they are `undefined`
// IDE will show them crossed out
el.$props
el.$emit
})
Expand All @@ -467,8 +466,7 @@ onMounted(() => {
</template>
```

If an element does not have type definitions, the types of the properties and events can be
defined in a more manual fashion:
If an element does not have type definitions, the types of the properties and events can be defined in a more manual fashion:

```vue
<script setup lang="ts">
Expand Down Expand Up @@ -503,11 +501,7 @@ declare module 'vue' {
</template>
```

Custom Element authors should not automatically export framework-specific custom
element type definitions from their libraries, for example they should not
export them from an `index.ts` file that also exports the rest of the library,
otherwise users will have unexpected module augmentation errors. Users should
import the framework-specific type definition file that they need.
Custom Element authors should not automatically export framework-specific custom element type definitions from their libraries, for example they should not export them from an `index.ts` file that also exports the rest of the library, otherwise users will have unexpected module augmentation errors. Users should import the framework-specific type definition file that they need.

## Web Components vs. Vue Components {#web-components-vs-vue-components}

Expand Down