@wippy-fe/webcomponent-vue 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +173 -0
- package/package.json +22 -0
- package/src/index.ts +21 -0
- package/src/providers.ts +116 -0
- package/src/vue-element.ts +128 -0
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# @wippy-fe/webcomponent-vue
|
|
2
|
+
|
|
3
|
+
Vue 3 integration layer for Wippy web components. Extends `@wippy-fe/webcomponent-core` with reactive props, Pinia state management, and Vue provider injection.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- **Vue app lifecycle** — creates and mounts a Vue 3 app inside the shadow DOM container
|
|
8
|
+
- **Reactive props** — attribute changes flow through a Vue `ref()` that components can `inject()`
|
|
9
|
+
- **Pinia** — automatically installed on every Vue app instance
|
|
10
|
+
- **Provider injection** — exposes props, errors, and an event emitter via Vue's `provide`/`inject`
|
|
11
|
+
- **Plugin support** — install additional Vue plugins via `vueConfig.plugins`
|
|
12
|
+
- **Custom providers** — hook into the Vue app before mount via `vueConfig.providers`
|
|
13
|
+
|
|
14
|
+
## What it does NOT do
|
|
15
|
+
|
|
16
|
+
- DOM setup, CSS loading, or prop parsing — that's handled by `@wippy-fe/webcomponent-core` (see its README for CSS guide)
|
|
17
|
+
- Component registration — use `define(import.meta.url, YourElement)` (re-exported from core)
|
|
18
|
+
- Any React/Svelte/etc. integration — this package is Vue-only
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { WippyVueElement, define } from '@wippy-fe/webcomponent-vue'
|
|
24
|
+
import MyApp from './app/my-app.vue'
|
|
25
|
+
import stylesText from './styles.css?inline'
|
|
26
|
+
import pkg from '../package.json'
|
|
27
|
+
|
|
28
|
+
class MyElement extends WippyVueElement {
|
|
29
|
+
static get wippyConfig() {
|
|
30
|
+
return {
|
|
31
|
+
propsSchema: pkg.wippy.props,
|
|
32
|
+
hostCssKeys: ['fontCssUrl', 'themeConfigUrl', 'primeVueCssUrl', 'iframeCssUrl'],
|
|
33
|
+
containerClasses: ['h-full'],
|
|
34
|
+
inlineCss: stylesText,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static get vueConfig() {
|
|
39
|
+
return {
|
|
40
|
+
rootComponent: MyApp,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function webComponent() {
|
|
46
|
+
return MyElement
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
define(import.meta.url, MyElement)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API Reference
|
|
53
|
+
|
|
54
|
+
### `WippyVueElement` (abstract class)
|
|
55
|
+
|
|
56
|
+
Extends `WippyElement` from `@wippy-fe/webcomponent-core`.
|
|
57
|
+
|
|
58
|
+
#### Static getters to override
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
static get wippyConfig(): WippyElementConfig // from core — see core README for full options
|
|
62
|
+
static get vueConfig(): WippyVueElementConfig
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### `WippyVueElementConfig`
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
interface WippyVueElementConfig {
|
|
69
|
+
/** The root Vue component to mount. */
|
|
70
|
+
rootComponent: Component
|
|
71
|
+
|
|
72
|
+
/** Additional Vue plugins to install (beyond Pinia). */
|
|
73
|
+
plugins?: Array<{ install: (app: App) => void }>
|
|
74
|
+
|
|
75
|
+
/** Extra providers to inject. Called after standard providers are set up. */
|
|
76
|
+
providers?: (app: App, element: WippyVueElement) => void
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Lifecycle hooks
|
|
81
|
+
|
|
82
|
+
`WippyVueElement` implements `onMount`, `onUnmount`, and `onPropsChanged` from the base class. You can still override the other hooks from `WippyElement`:
|
|
83
|
+
|
|
84
|
+
| Hook | Available? | Notes |
|
|
85
|
+
|------|-----------|-------|
|
|
86
|
+
| `onInit(shadow)` | Override freely | Runs before CSS/container |
|
|
87
|
+
| `onMount(...)` | Implemented by WippyVueElement | Do not override — use `vueConfig` instead |
|
|
88
|
+
| `onReady()` | Override freely | Runs after Vue app is mounted and state is `ready` |
|
|
89
|
+
| `onError(error)` | Override freely | Custom error handling |
|
|
90
|
+
| `onUnmount()` | Implemented by WippyVueElement | Do not override |
|
|
91
|
+
| `onPropsChanged(...)` | Implemented by WippyVueElement | Updates reactive refs automatically |
|
|
92
|
+
|
|
93
|
+
### Provider Symbols
|
|
94
|
+
|
|
95
|
+
Import these in your Vue components to access injected values:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { EVENT_PROVIDER, PROPS_PROVIDER, PROPS_ERROR_PROVIDER } from '@wippy-fe/webcomponent-vue'
|
|
99
|
+
|
|
100
|
+
// In setup()
|
|
101
|
+
const props = inject(PROPS_PROVIDER)! // Ref<Record<string, unknown>>
|
|
102
|
+
const errors = inject(PROPS_ERROR_PROVIDER)! // Ref<string[]>
|
|
103
|
+
const emit = inject(EVENT_PROVIDER)! // (event: string, detail?) => void
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Symbol | Type | Description |
|
|
107
|
+
|--------|------|-------------|
|
|
108
|
+
| `EVENT_PROVIDER` | `(event: string, detail?) => void` | Emits CustomEvents from the host element |
|
|
109
|
+
| `PROPS_PROVIDER` | `Ref<Record<string, unknown>>` | Reactive parsed props from attributes |
|
|
110
|
+
| `PROPS_ERROR_PROVIDER` | `Ref<string[]>` | Reactive list of prop parsing errors |
|
|
111
|
+
|
|
112
|
+
### Re-exports from core
|
|
113
|
+
|
|
114
|
+
For convenience, this package re-exports everything from `@wippy-fe/webcomponent-core`:
|
|
115
|
+
|
|
116
|
+
- `WippyElement`, `define`
|
|
117
|
+
- `WippyElementConfig`, `WippyPropsSchema`, `WippyPropDefinition`, `HostCssKey`, `ParseResult`
|
|
118
|
+
|
|
119
|
+
## Adding Plugins
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
static get vueConfig() {
|
|
123
|
+
return {
|
|
124
|
+
rootComponent: MyApp,
|
|
125
|
+
plugins: [createI18n({ /* ... */ })],
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Custom Providers
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { MY_SERVICE } from './services'
|
|
134
|
+
|
|
135
|
+
static get vueConfig() {
|
|
136
|
+
return {
|
|
137
|
+
rootComponent: MyApp,
|
|
138
|
+
providers(app, element) {
|
|
139
|
+
app.provide(MY_SERVICE, new MyService(element))
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Migration from monolithic pattern
|
|
146
|
+
|
|
147
|
+
**Before** — every component duplicates ~170 lines:
|
|
148
|
+
```ts
|
|
149
|
+
class MyElement extends HTMLElement {
|
|
150
|
+
private vueApp: App | null = null
|
|
151
|
+
private props: Ref<...> = ref({})
|
|
152
|
+
// ... shadow DOM, CSS loading, prop parsing, Vue setup, events ...
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**After** — ~20 lines:
|
|
157
|
+
```ts
|
|
158
|
+
class MyElement extends WippyVueElement {
|
|
159
|
+
static get wippyConfig() {
|
|
160
|
+
return {
|
|
161
|
+
propsSchema: pkg.wippy.props,
|
|
162
|
+
hostCssKeys: ['fontCssUrl', 'themeConfigUrl', 'primeVueCssUrl', 'iframeCssUrl'],
|
|
163
|
+
containerClasses: ['h-full'],
|
|
164
|
+
inlineCss: stylesText,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
static get vueConfig() {
|
|
168
|
+
return { rootComponent: MyApp }
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
All the boilerplate (shadow DOM, CSS, prop parsing, Vue lifecycle, Pinia, providers) is handled by the base classes.
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wippy-fe/webcomponent-vue",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "Vue 3 integration layer for Wippy web components — extends @wippy-fe/webcomponent-core with reactive props, Pinia, and provider injection.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"src/",
|
|
10
|
+
"package.json"
|
|
11
|
+
],
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@wippy-fe/webcomponent-core": "^0.0.6"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@wippy-fe/proxy": "^0.0.6",
|
|
17
|
+
"@iconify/vue": "^5.0.0",
|
|
18
|
+
"pinia": "^2.1.0",
|
|
19
|
+
"vue": "^3.5.0"
|
|
20
|
+
},
|
|
21
|
+
"license": "UNLICENSED"
|
|
22
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Vue layer
|
|
2
|
+
export { WippyVueElement } from './vue-element.ts'
|
|
3
|
+
export type { WippyVueElementConfig } from './vue-element.ts'
|
|
4
|
+
|
|
5
|
+
// Providers: base symbols, composables, and createProviders utility
|
|
6
|
+
export {
|
|
7
|
+
EVENT_PROVIDER, PROPS_PROVIDER, PROPS_ERROR_PROVIDER, CONTENT_PROVIDER,
|
|
8
|
+
useProps, useEvents, usePropsErrors, useContent,
|
|
9
|
+
createProviders,
|
|
10
|
+
} from './providers.ts'
|
|
11
|
+
export type { TypedProviders } from './providers.ts'
|
|
12
|
+
|
|
13
|
+
// Re-export core for convenience
|
|
14
|
+
export { WippyElement, define } from '@wippy-fe/webcomponent-core'
|
|
15
|
+
export type {
|
|
16
|
+
WippyElementConfig,
|
|
17
|
+
WippyPropsSchema,
|
|
18
|
+
WippyPropDefinition,
|
|
19
|
+
HostCssKey,
|
|
20
|
+
ParseResult,
|
|
21
|
+
} from '@wippy-fe/webcomponent-core'
|
package/src/providers.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { InjectionKey, Ref } from 'vue'
|
|
2
|
+
import { inject } from 'vue'
|
|
3
|
+
|
|
4
|
+
// ── Base injection keys (untyped) ────────────────────────────
|
|
5
|
+
|
|
6
|
+
/** Injection key for the event emitter function. */
|
|
7
|
+
export const EVENT_PROVIDER = Symbol('wippy:emit') as InjectionKey<
|
|
8
|
+
(event: string, detail?: unknown) => void
|
|
9
|
+
>
|
|
10
|
+
|
|
11
|
+
/** Injection key for the reactive props ref. */
|
|
12
|
+
export const PROPS_PROVIDER = Symbol('wippy:props') as InjectionKey<Ref<Record<string, unknown>>>
|
|
13
|
+
|
|
14
|
+
/** Injection key for the reactive props error ref. */
|
|
15
|
+
export const PROPS_ERROR_PROVIDER = Symbol('wippy:props_error') as InjectionKey<Ref<string[]>>
|
|
16
|
+
|
|
17
|
+
/** Injection key for reactive content from child <template data-type="..."> elements. */
|
|
18
|
+
export const CONTENT_PROVIDER = Symbol('wippy:content') as InjectionKey<Ref<string | null>>
|
|
19
|
+
|
|
20
|
+
// ── Composables (typed) ──────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Inject the reactive props ref, typed to your component's props interface.
|
|
24
|
+
*
|
|
25
|
+
* Must be called inside a Vue component's `setup()` that lives within a `WippyVueElement`.
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* const props = useProps<ComponentProps>()
|
|
29
|
+
* // props is Ref<ComponentProps>
|
|
30
|
+
* console.log(props.value.maxFileSize)
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function useProps<Props>(): Ref<Props> {
|
|
34
|
+
const props = inject(PROPS_PROVIDER)
|
|
35
|
+
if (!props) throw new Error('useProps() must be called inside a WippyVueElement')
|
|
36
|
+
return props as unknown as Ref<Props>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Inject the typed event emitter, constrained to your component's event map.
|
|
41
|
+
*
|
|
42
|
+
* Must be called inside a Vue component's `setup()` that lives within a `WippyVueElement`.
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* const emit = useEvents<Events>()
|
|
46
|
+
* emit('upload-complete', { fileId: '123', status: 'done' }) // fully typed
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function useEvents<Events>(): <K extends keyof Events>(event: K, detail: Events[K]) => void {
|
|
50
|
+
const emit = inject(EVENT_PROVIDER)
|
|
51
|
+
if (!emit) throw new Error('useEvents() must be called inside a WippyVueElement')
|
|
52
|
+
return emit as unknown as <K extends keyof Events>(event: K, detail: Events[K]) => void
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Inject the reactive prop validation errors ref.
|
|
57
|
+
*
|
|
58
|
+
* Must be called inside a Vue component's `setup()` that lives within a `WippyVueElement`.
|
|
59
|
+
*
|
|
60
|
+
* ```ts
|
|
61
|
+
* const errors = usePropsErrors()
|
|
62
|
+
* // errors is Ref<string[]>
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function usePropsErrors(): Ref<string[]> {
|
|
66
|
+
const errors = inject(PROPS_ERROR_PROVIDER)
|
|
67
|
+
if (!errors) throw new Error('usePropsErrors() must be called inside a WippyVueElement')
|
|
68
|
+
return errors
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Inject the reactive content ref (from child `<template data-type="...">` elements).
|
|
73
|
+
*
|
|
74
|
+
* Must be called inside a Vue component's `setup()` within a `WippyVueElement`
|
|
75
|
+
* that has `contentTemplate` configured.
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* const content = useContent()
|
|
79
|
+
* // content is Ref<string | null>
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function useContent(): Ref<string | null> {
|
|
83
|
+
const content = inject(CONTENT_PROVIDER)
|
|
84
|
+
if (!content) throw new Error('useContent() must be called inside a WippyVueElement with contentTemplate configured')
|
|
85
|
+
return content
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ── createProviders (typed injection keys) ───────────────────
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Typed provider keys for a specific component.
|
|
92
|
+
*/
|
|
93
|
+
export interface TypedProviders<Props, Events> {
|
|
94
|
+
EVENT_PROVIDER: InjectionKey<<K extends keyof Events>(event: K, detail: Events[K]) => void>
|
|
95
|
+
PROPS_PROVIDER: InjectionKey<Ref<Props>>
|
|
96
|
+
PROPS_ERROR_PROVIDER: InjectionKey<Ref<string[]>>
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Creates typed provider injection keys for a specific component.
|
|
101
|
+
*
|
|
102
|
+
* Use this if you prefer raw `inject(KEY)` over the composable helpers.
|
|
103
|
+
* Returns the same Symbol instances with narrowed types.
|
|
104
|
+
*
|
|
105
|
+
* ```ts
|
|
106
|
+
* export const { EVENT_PROVIDER, PROPS_PROVIDER, PROPS_ERROR_PROVIDER } =
|
|
107
|
+
* createProviders<ComponentProps, Events>()
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export function createProviders<Props, Events = Record<string, unknown>>(): TypedProviders<Props, Events> {
|
|
111
|
+
return {
|
|
112
|
+
EVENT_PROVIDER: EVENT_PROVIDER as unknown as TypedProviders<Props, Events>['EVENT_PROVIDER'],
|
|
113
|
+
PROPS_PROVIDER: PROPS_PROVIDER as unknown as TypedProviders<Props, Events>['PROPS_PROVIDER'],
|
|
114
|
+
PROPS_ERROR_PROVIDER,
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { App, Component, Ref } from 'vue'
|
|
2
|
+
import { WippyElement } from '@wippy-fe/webcomponent-core'
|
|
3
|
+
import { createPinia } from 'pinia'
|
|
4
|
+
import { createApp, ref } from 'vue'
|
|
5
|
+
import { EVENT_PROVIDER, PROPS_PROVIDER, PROPS_ERROR_PROVIDER, CONTENT_PROVIDER } from './providers.ts'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Vue-specific configuration returned by `static get vueConfig()`.
|
|
9
|
+
*/
|
|
10
|
+
export interface WippyVueElementConfig {
|
|
11
|
+
/** The root Vue component to mount. */
|
|
12
|
+
rootComponent: Component
|
|
13
|
+
/** Additional Vue plugins to install (beyond Pinia which is always installed). */
|
|
14
|
+
plugins?: Array<{ install: (app: App) => void }>
|
|
15
|
+
/** Extra providers to inject into the Vue app. */
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
providers?: (app: App, element: WippyVueElement<any, any>) => void
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Vue 3 integration for Wippy web components.
|
|
22
|
+
*
|
|
23
|
+
* Generic over `Props` (parsed prop object type) and `Events` (event map).
|
|
24
|
+
* These flow through to typed hooks, reactive refs, and composable helpers.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```ts
|
|
28
|
+
* class MyElement extends WippyVueElement<MyProps, MyEvents> {
|
|
29
|
+
* static get wippyConfig(): WippyElementConfig<MyProps> {
|
|
30
|
+
* return { propsSchema: pkg.wippy.props, inlineCss: stylesText }
|
|
31
|
+
* }
|
|
32
|
+
* static get vueConfig() {
|
|
33
|
+
* return { rootComponent: MyApp }
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* In Vue components, use the typed composable helpers:
|
|
39
|
+
* ```ts
|
|
40
|
+
* const props = useProps<MyProps>()
|
|
41
|
+
* const emit = useEvents<MyEvents>()
|
|
42
|
+
* const errors = usePropsErrors()
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export abstract class WippyVueElement<
|
|
46
|
+
Props = Record<string, unknown>,
|
|
47
|
+
Events = Record<string, unknown>,
|
|
48
|
+
> extends WippyElement<Props> {
|
|
49
|
+
private _vueApp: App<Element> | null = null
|
|
50
|
+
private _propsRef: Ref<Props> = ref({}) as Ref<Props>
|
|
51
|
+
private _errorsRef: Ref<string[]> = ref([])
|
|
52
|
+
private _contentRef: Ref<string | null> = ref(null)
|
|
53
|
+
|
|
54
|
+
/** @internal Phantom field to retain the Events type parameter. */
|
|
55
|
+
declare readonly _events: Events
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Override to provide Vue-specific configuration.
|
|
59
|
+
*/
|
|
60
|
+
static get vueConfig(): WippyVueElementConfig {
|
|
61
|
+
throw new Error('WippyVueElement subclass must override static get vueConfig()')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected onMount(
|
|
65
|
+
_shadow: ShadowRoot,
|
|
66
|
+
container: HTMLElement,
|
|
67
|
+
initialProps: Props,
|
|
68
|
+
initialErrors: string[],
|
|
69
|
+
initialContent?: string | null,
|
|
70
|
+
): void {
|
|
71
|
+
const vueConfig = (this.constructor as typeof WippyVueElement).vueConfig
|
|
72
|
+
|
|
73
|
+
// 1. Set reactive state
|
|
74
|
+
this._propsRef.value = initialProps
|
|
75
|
+
this._errorsRef.value = initialErrors
|
|
76
|
+
this._contentRef.value = initialContent ?? null
|
|
77
|
+
|
|
78
|
+
// Emit initial errors as invalid events
|
|
79
|
+
for (const error of initialErrors) {
|
|
80
|
+
this.emitEvent('invalid', { message: error })
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 2. Create Vue app
|
|
84
|
+
this._vueApp = createApp(vueConfig.rootComponent)
|
|
85
|
+
this._vueApp.use(createPinia())
|
|
86
|
+
|
|
87
|
+
// 3. Install extra plugins
|
|
88
|
+
if (vueConfig.plugins) {
|
|
89
|
+
for (const plugin of vueConfig.plugins) {
|
|
90
|
+
this._vueApp.use(plugin)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 4. Provide standard injection keys
|
|
95
|
+
this._vueApp.provide(PROPS_PROVIDER, this._propsRef as Ref<Record<string, unknown>>)
|
|
96
|
+
this._vueApp.provide(PROPS_ERROR_PROVIDER, this._errorsRef)
|
|
97
|
+
this._vueApp.provide(EVENT_PROVIDER, this.emitEvent.bind(this))
|
|
98
|
+
this._vueApp.provide(CONTENT_PROVIDER, this._contentRef)
|
|
99
|
+
|
|
100
|
+
// 5. Custom providers
|
|
101
|
+
if (vueConfig.providers) {
|
|
102
|
+
vueConfig.providers(this._vueApp, this)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 6. Mount
|
|
106
|
+
this._vueApp.mount(container)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
protected onUnmount(): void {
|
|
110
|
+
if (this._vueApp) {
|
|
111
|
+
this._vueApp.unmount()
|
|
112
|
+
this._vueApp = null
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
protected onPropsChanged(props: Props, errors: string[]): void {
|
|
117
|
+
this._propsRef.value = props
|
|
118
|
+
this._errorsRef.value = errors
|
|
119
|
+
|
|
120
|
+
for (const error of errors) {
|
|
121
|
+
this.emitEvent('invalid', { message: error })
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
protected onContentChanged(content: string | null): void {
|
|
126
|
+
this._contentRef.value = content
|
|
127
|
+
}
|
|
128
|
+
}
|