@web-applets/sdk 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +29 -138
- package/dist/components/applet-frame.d.ts +19 -0
- package/dist/components/applet-frame.js +93 -0
- package/dist/core/applet.d.ts +21 -0
- package/dist/core/applet.js +117 -0
- package/dist/core/context.d.ts +32 -0
- package/dist/core/context.js +138 -0
- package/dist/core/host.d.ts +31 -0
- package/dist/core/host.js +134 -0
- package/dist/core/shared.d.ts +121 -0
- package/dist/core/shared.js +171 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.js +9 -6
- package/dist/lib/utils.d.ts +17 -0
- package/dist/lib/utils.js +37 -0
- package/dist/utils.d.ts +3 -4
- package/dist/utils.js +10 -30
- package/package.json +1 -1
- package/dist/client.d.ts +0 -32
- package/dist/client.js +0 -197
- package/dist/context.d.ts +0 -27
- package/dist/context.js +0 -136
- package/dist/types.d.ts +0 -74
- package/dist/types.js +0 -21
- package/dist/web-component/index.d.ts +0 -1
- package/dist/web-component/index.js +0 -52
- package/dist/web-components/applet-frame.d.ts +0 -1
- package/dist/web-components/applet-frame.js +0 -52
package/dist/client.js
DELETED
@@ -1,197 +0,0 @@
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
6
|
-
};
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
11
|
-
};
|
12
|
-
var _Applet_instances, _Applet_state, _Applet_dispatchEvent;
|
13
|
-
import { AppletMessage, } from './types';
|
14
|
-
const hiddenContainer = document.createElement('iframe');
|
15
|
-
hiddenContainer.style.display = 'none';
|
16
|
-
document.body.appendChild(hiddenContainer);
|
17
|
-
export async function list(url) {
|
18
|
-
url = parseUrl(url);
|
19
|
-
try {
|
20
|
-
const request = await fetch(`${url}/manifest.json`);
|
21
|
-
const appManifest = await request.json();
|
22
|
-
const appletUrls = appManifest.applets;
|
23
|
-
const manifests = {};
|
24
|
-
const manifestRequests = appletUrls.map(async (appletUrl) => {
|
25
|
-
appletUrl = parseUrl(appletUrl, url);
|
26
|
-
const request = await fetch(`${appletUrl}/manifest.json`);
|
27
|
-
const manifest = await request.json();
|
28
|
-
manifests[appletUrl] = manifest;
|
29
|
-
});
|
30
|
-
await Promise.all(manifestRequests);
|
31
|
-
return manifests;
|
32
|
-
}
|
33
|
-
catch {
|
34
|
-
return {};
|
35
|
-
}
|
36
|
-
}
|
37
|
-
const defaultOpts = {
|
38
|
-
headless: false,
|
39
|
-
unsafe: false,
|
40
|
-
};
|
41
|
-
export async function load(url, container, opts) {
|
42
|
-
const _opts = Object.assign(defaultOpts, opts ?? {});
|
43
|
-
url = parseUrl(url);
|
44
|
-
const manifest = await loadManifest(`${url}`);
|
45
|
-
if (!container) {
|
46
|
-
container = hiddenContainer;
|
47
|
-
_opts.headless = true;
|
48
|
-
}
|
49
|
-
if (_opts.unsafe || manifest.unsafe) {
|
50
|
-
container.setAttribute('sandbox', 'allow-scripts allow-forms allow-same-origin');
|
51
|
-
}
|
52
|
-
else {
|
53
|
-
container.setAttribute('sandbox', 'allow-scripts allow-forms');
|
54
|
-
}
|
55
|
-
const applet = new Applet();
|
56
|
-
applet.manifest = manifest;
|
57
|
-
applet.actions = manifest.actions;
|
58
|
-
applet.container = container;
|
59
|
-
container.src = applet.manifest.entrypoint;
|
60
|
-
return new Promise((resolve) => {
|
61
|
-
applet.on('ready', () => {
|
62
|
-
const initMessage = new AppletMessage('init', {
|
63
|
-
headless: _opts.headless,
|
64
|
-
});
|
65
|
-
applet.send(initMessage);
|
66
|
-
resolve(applet);
|
67
|
-
});
|
68
|
-
});
|
69
|
-
}
|
70
|
-
export class Applet extends EventTarget {
|
71
|
-
constructor() {
|
72
|
-
super();
|
73
|
-
_Applet_instances.add(this);
|
74
|
-
this.actions = [];
|
75
|
-
_Applet_state.set(this, void 0);
|
76
|
-
this.on('state', (message) => {
|
77
|
-
__classPrivateFieldSet(this, _Applet_state, message.state, "f");
|
78
|
-
__classPrivateFieldGet(this, _Applet_instances, "m", _Applet_dispatchEvent).call(this, 'stateupdated', message.state);
|
79
|
-
});
|
80
|
-
this.on('resize', (message) => {
|
81
|
-
this.resizeContainer(message.dimensions);
|
82
|
-
});
|
83
|
-
}
|
84
|
-
get state() {
|
85
|
-
return __classPrivateFieldGet(this, _Applet_state, "f");
|
86
|
-
}
|
87
|
-
set state(state) {
|
88
|
-
__classPrivateFieldSet(this, _Applet_state, state, "f");
|
89
|
-
this.send(new AppletMessage('state', { state }));
|
90
|
-
}
|
91
|
-
toJson() {
|
92
|
-
return Object.fromEntries(Object.entries(this).filter(([_, value]) => {
|
93
|
-
try {
|
94
|
-
JSON.stringify(value);
|
95
|
-
return true;
|
96
|
-
}
|
97
|
-
catch {
|
98
|
-
return false;
|
99
|
-
}
|
100
|
-
}));
|
101
|
-
}
|
102
|
-
resizeContainer(dimensions) {
|
103
|
-
this.container.style.height = `${dimensions.height + 2}px`;
|
104
|
-
// if (!this.#styleOverrides) {
|
105
|
-
// this.#container.style.height = `${dimensions.height}px`;
|
106
|
-
// }
|
107
|
-
}
|
108
|
-
onstateupdated(event) { }
|
109
|
-
disconnect() {
|
110
|
-
this.onstateupdated = () => { };
|
111
|
-
this.container.src = 'about:blank';
|
112
|
-
}
|
113
|
-
async dispatchAction(actionId, params) {
|
114
|
-
const requestMessage = new AppletMessage('action', {
|
115
|
-
actionId,
|
116
|
-
params,
|
117
|
-
});
|
118
|
-
return await this.send(requestMessage);
|
119
|
-
}
|
120
|
-
async send(message) {
|
121
|
-
this.container.contentWindow?.postMessage(message.toJson(), '*');
|
122
|
-
return new Promise((resolve) => {
|
123
|
-
const listener = (messageEvent) => {
|
124
|
-
const responseMessage = new AppletMessage(messageEvent.data.type, messageEvent.data);
|
125
|
-
if (responseMessage.type === 'resolve' &&
|
126
|
-
responseMessage.id === message.id) {
|
127
|
-
window.removeEventListener('message', listener);
|
128
|
-
resolve(responseMessage);
|
129
|
-
}
|
130
|
-
};
|
131
|
-
window.addEventListener('message', listener);
|
132
|
-
});
|
133
|
-
}
|
134
|
-
async on(messageType, callback) {
|
135
|
-
const listener = async (messageEvent) => {
|
136
|
-
if (messageEvent.source !== this.container.contentWindow)
|
137
|
-
return;
|
138
|
-
if (messageEvent.data.type !== messageType)
|
139
|
-
return;
|
140
|
-
const message = new AppletMessage(messageEvent.data.type, messageEvent.data);
|
141
|
-
await callback(message);
|
142
|
-
this.container.contentWindow?.postMessage(new AppletMessage('resolve', { id: message.id }), '*');
|
143
|
-
};
|
144
|
-
window.addEventListener('message', listener);
|
145
|
-
}
|
146
|
-
}
|
147
|
-
_Applet_state = new WeakMap(), _Applet_instances = new WeakSet(), _Applet_dispatchEvent = function _Applet_dispatchEvent(id, detail) {
|
148
|
-
if (typeof this[`on${id}`] === 'function') {
|
149
|
-
this[`on${id}`](detail);
|
150
|
-
}
|
151
|
-
this.dispatchEvent(new CustomEvent(id, { detail }));
|
152
|
-
};
|
153
|
-
/* Helpers */
|
154
|
-
function parseUrl(url, base) {
|
155
|
-
if (['http', 'https'].includes(url.split('://')[0])) {
|
156
|
-
return url;
|
157
|
-
}
|
158
|
-
let path = trimSlashes(url);
|
159
|
-
url = `${base || window.location.origin}/${path}`;
|
160
|
-
return url;
|
161
|
-
}
|
162
|
-
function trimSlashes(str) {
|
163
|
-
return str.replace(/^\/+|\/+$/g, '');
|
164
|
-
}
|
165
|
-
export async function loadManifest(url) {
|
166
|
-
url = parseUrl(url);
|
167
|
-
const request = await fetch(`${url}/manifest.json`);
|
168
|
-
const appletManifest = await request.json();
|
169
|
-
if (appletManifest.type !== 'applet') {
|
170
|
-
throw new Error("URL doesn't point to a valid applet manifest.");
|
171
|
-
}
|
172
|
-
appletManifest.entrypoint = parseUrl(appletManifest.entrypoint, url);
|
173
|
-
return appletManifest;
|
174
|
-
}
|
175
|
-
export async function getHeaders(url) {
|
176
|
-
url = parseUrl(url);
|
177
|
-
try {
|
178
|
-
const request = await fetch(`${url}/manifest.json`);
|
179
|
-
const appManifest = await request.json();
|
180
|
-
const appletHeaders = appManifest.applets;
|
181
|
-
return appletHeaders ?? [];
|
182
|
-
}
|
183
|
-
catch {
|
184
|
-
return [];
|
185
|
-
}
|
186
|
-
}
|
187
|
-
export async function getManifests(url) {
|
188
|
-
url = parseUrl(url);
|
189
|
-
const request = await fetch(`${url}/manifest.json`);
|
190
|
-
const headers = (await request.json()).applets;
|
191
|
-
const manifests = await Promise.all(headers.map(async (header) => {
|
192
|
-
const appletUrl = parseUrl(header.url);
|
193
|
-
const request = await fetch(`${appletUrl}/manifest.json`);
|
194
|
-
return await request.json();
|
195
|
-
}));
|
196
|
-
return manifests ?? [];
|
197
|
-
}
|
package/dist/context.d.ts
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
import { ActionHandlerDict, AppletMessage, AppletMessageType, AppletMessageCallback, ActionParams, ActionHandler } from './types';
|
2
|
-
/**
|
3
|
-
* Context
|
4
|
-
*/
|
5
|
-
export declare class AppletContext<StateType = any> extends EventTarget {
|
6
|
-
#private;
|
7
|
-
client: AppletClient;
|
8
|
-
actionHandlers: ActionHandlerDict;
|
9
|
-
headless: boolean;
|
10
|
-
connect(): this;
|
11
|
-
setActionHandler<T extends ActionParams>(actionId: string, handler: ActionHandler<T>): void;
|
12
|
-
set state(state: StateType);
|
13
|
-
get state(): StateType;
|
14
|
-
setState(state: StateType, shouldRender?: boolean): Promise<void>;
|
15
|
-
onload(): Promise<void> | void;
|
16
|
-
onready(): Promise<void> | void;
|
17
|
-
onrender(): void;
|
18
|
-
}
|
19
|
-
/**
|
20
|
-
* Client
|
21
|
-
*/
|
22
|
-
declare class AppletClient {
|
23
|
-
on(messageType: AppletMessageType, callback: AppletMessageCallback): void;
|
24
|
-
send(message: AppletMessage): Promise<void>;
|
25
|
-
}
|
26
|
-
export declare const appletContext: AppletContext<any>;
|
27
|
-
export {};
|
package/dist/context.js
DELETED
@@ -1,136 +0,0 @@
|
|
1
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
2
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
3
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
4
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
5
|
-
};
|
6
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
7
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
10
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
11
|
-
};
|
12
|
-
var _AppletContext_state;
|
13
|
-
import { AppletMessage, } from './types';
|
14
|
-
/**
|
15
|
-
* Context
|
16
|
-
*/
|
17
|
-
export class AppletContext extends EventTarget {
|
18
|
-
constructor() {
|
19
|
-
super(...arguments);
|
20
|
-
this.actionHandlers = {};
|
21
|
-
_AppletContext_state.set(this, void 0);
|
22
|
-
this.headless = false;
|
23
|
-
}
|
24
|
-
connect() {
|
25
|
-
this.client = new AppletClient();
|
26
|
-
const startup = async () => {
|
27
|
-
await this.onload();
|
28
|
-
this.client.send(new AppletMessage('ready'));
|
29
|
-
this.dispatchEvent(new CustomEvent('ready'));
|
30
|
-
await this.onready();
|
31
|
-
};
|
32
|
-
if (document.readyState === 'complete' ||
|
33
|
-
document.readyState === 'interactive') {
|
34
|
-
setTimeout(startup, 1);
|
35
|
-
}
|
36
|
-
else {
|
37
|
-
window.addEventListener('DOMContentLoaded', startup);
|
38
|
-
}
|
39
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
40
|
-
for (let entry of entries) {
|
41
|
-
const message = new AppletMessage('resize', {
|
42
|
-
dimensions: {
|
43
|
-
width: entry.contentRect.width,
|
44
|
-
height: entry.contentRect.height,
|
45
|
-
},
|
46
|
-
});
|
47
|
-
this.client.send(message);
|
48
|
-
}
|
49
|
-
});
|
50
|
-
resizeObserver.observe(document.querySelector('html'));
|
51
|
-
this.client.on('init', (message) => {
|
52
|
-
const initMessage = message;
|
53
|
-
this.headless = initMessage.headless;
|
54
|
-
});
|
55
|
-
this.client.on('state', (message) => {
|
56
|
-
if (!isStateMessage(message)) {
|
57
|
-
throw new TypeError("Message doesn't match type StateMessage");
|
58
|
-
}
|
59
|
-
// Don't render when state updates match the current state
|
60
|
-
// this retains cursor positions in text fields, for example
|
61
|
-
if (JSON.stringify(message.state) === JSON.stringify(__classPrivateFieldGet(this, _AppletContext_state, "f")))
|
62
|
-
return;
|
63
|
-
__classPrivateFieldSet(this, _AppletContext_state, message.state, "f");
|
64
|
-
// BUG: For some reason regular applets were loading headless, when instantiated not on a page reload
|
65
|
-
// if (!this.headless) {
|
66
|
-
this.onrender();
|
67
|
-
this.dispatchEvent(new CustomEvent('render'));
|
68
|
-
// }
|
69
|
-
});
|
70
|
-
this.client.on('action', async (message) => {
|
71
|
-
if (!isActionMessage(message)) {
|
72
|
-
throw new TypeError("Message doesn't match type AppletMessage.");
|
73
|
-
}
|
74
|
-
if (Object.keys(this.actionHandlers).includes(message.actionId)) {
|
75
|
-
await this.actionHandlers[message.actionId](message.params);
|
76
|
-
}
|
77
|
-
});
|
78
|
-
return this;
|
79
|
-
}
|
80
|
-
setActionHandler(actionId, handler) {
|
81
|
-
this.actionHandlers[actionId] = handler;
|
82
|
-
}
|
83
|
-
set state(state) {
|
84
|
-
this.setState(state);
|
85
|
-
}
|
86
|
-
get state() {
|
87
|
-
return __classPrivateFieldGet(this, _AppletContext_state, "f");
|
88
|
-
}
|
89
|
-
async setState(state, shouldRender) {
|
90
|
-
const message = new AppletMessage('state', { state });
|
91
|
-
await this.client.send(message);
|
92
|
-
__classPrivateFieldSet(this, _AppletContext_state, state, "f");
|
93
|
-
if (shouldRender !== false && !this.headless) {
|
94
|
-
this.onrender();
|
95
|
-
this.dispatchEvent(new CustomEvent('render'));
|
96
|
-
}
|
97
|
-
}
|
98
|
-
onload() { }
|
99
|
-
onready() { }
|
100
|
-
onrender() { }
|
101
|
-
}
|
102
|
-
_AppletContext_state = new WeakMap();
|
103
|
-
function isActionMessage(message) {
|
104
|
-
return message.type === 'action';
|
105
|
-
}
|
106
|
-
function isStateMessage(message) {
|
107
|
-
return message.type === 'state';
|
108
|
-
}
|
109
|
-
/**
|
110
|
-
* Client
|
111
|
-
*/
|
112
|
-
class AppletClient {
|
113
|
-
on(messageType, callback) {
|
114
|
-
window.addEventListener('message', async (messageEvent) => {
|
115
|
-
if (messageEvent.data.type !== messageType)
|
116
|
-
return;
|
117
|
-
const message = new AppletMessage(messageEvent.data.type, messageEvent.data);
|
118
|
-
await callback(message);
|
119
|
-
window.parent.postMessage(new AppletMessage('resolve', { id: message.id }), '*');
|
120
|
-
});
|
121
|
-
}
|
122
|
-
send(message) {
|
123
|
-
window.parent.postMessage(message.toJson(), '*');
|
124
|
-
return new Promise((resolve) => {
|
125
|
-
const listener = (messageEvent) => {
|
126
|
-
if (messageEvent.data.type === 'resolve' &&
|
127
|
-
messageEvent.data.id === message.id) {
|
128
|
-
window.removeEventListener('message', listener);
|
129
|
-
resolve();
|
130
|
-
}
|
131
|
-
};
|
132
|
-
window.addEventListener('message', listener);
|
133
|
-
});
|
134
|
-
}
|
135
|
-
}
|
136
|
-
export const appletContext = new AppletContext();
|
package/dist/types.d.ts
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
export interface AppletManifest {
|
2
|
-
type: 'applet';
|
3
|
-
name: string;
|
4
|
-
description?: string;
|
5
|
-
icon?: string;
|
6
|
-
unsafe?: boolean;
|
7
|
-
frameless?: boolean;
|
8
|
-
entrypoint?: string;
|
9
|
-
actions?: AppletAction[];
|
10
|
-
}
|
11
|
-
export interface AppletManifestDict {
|
12
|
-
[url: string]: AppletManifest;
|
13
|
-
}
|
14
|
-
export interface AppletAction {
|
15
|
-
id: string;
|
16
|
-
name?: string;
|
17
|
-
description?: string;
|
18
|
-
params?: ActionParamSchema;
|
19
|
-
}
|
20
|
-
export interface AppletHeader {
|
21
|
-
name: string;
|
22
|
-
description: string;
|
23
|
-
url: string;
|
24
|
-
actions: {
|
25
|
-
id: string;
|
26
|
-
description: string;
|
27
|
-
params: {
|
28
|
-
[key: string]: string;
|
29
|
-
};
|
30
|
-
}[];
|
31
|
-
}
|
32
|
-
export type AppletState = any;
|
33
|
-
export type ActionParamSchema = Record<string, {
|
34
|
-
description: string;
|
35
|
-
type: 'string';
|
36
|
-
}>;
|
37
|
-
export type ActionParams<T = any> = Record<string, T>;
|
38
|
-
export type ActionHandlerDict = {
|
39
|
-
[key: string]: ActionHandler<any>;
|
40
|
-
};
|
41
|
-
export type ActionHandler<T extends ActionParams> = (params: T) => void | Promise<void>;
|
42
|
-
export type AnyAppletMessage = AppletMessage | AppletStateMessage | AppletActionMessage;
|
43
|
-
export interface AppletStateMessage<T = any> extends AppletMessage {
|
44
|
-
type: 'state';
|
45
|
-
state: T;
|
46
|
-
}
|
47
|
-
export interface AppletResizeMessage extends AppletMessage {
|
48
|
-
type: 'resize';
|
49
|
-
dimensions: {
|
50
|
-
height: number;
|
51
|
-
width: number;
|
52
|
-
};
|
53
|
-
}
|
54
|
-
export interface AppletActionMessage<T = any> extends AppletMessage {
|
55
|
-
type: 'action';
|
56
|
-
actionId: string;
|
57
|
-
params: T;
|
58
|
-
}
|
59
|
-
export interface AppletInitMessage extends AppletMessage {
|
60
|
-
type: 'init';
|
61
|
-
headless: boolean;
|
62
|
-
}
|
63
|
-
export declare class AppletMessage<T = any> {
|
64
|
-
type: AppletMessageType;
|
65
|
-
id: string;
|
66
|
-
timeStamp: number;
|
67
|
-
constructor(type: AppletMessageType, values?: T);
|
68
|
-
toJson(): {
|
69
|
-
[k: string]: any;
|
70
|
-
};
|
71
|
-
resolve(): void;
|
72
|
-
}
|
73
|
-
export type AppletMessageType = 'action' | 'actions' | 'render' | 'state' | 'init' | 'ready' | 'resolve' | 'resize';
|
74
|
-
export type AppletMessageCallback = (message: AnyAppletMessage) => Promise<void> | void;
|
package/dist/types.js
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
export class AppletMessage {
|
2
|
-
constructor(type, values) {
|
3
|
-
this.timeStamp = Date.now();
|
4
|
-
this.type = type;
|
5
|
-
this.id = crypto.randomUUID();
|
6
|
-
if (values)
|
7
|
-
Object.assign(this, values);
|
8
|
-
}
|
9
|
-
toJson() {
|
10
|
-
return Object.fromEntries(Object.entries(this).filter(([_, value]) => {
|
11
|
-
try {
|
12
|
-
JSON.stringify(value);
|
13
|
-
return true;
|
14
|
-
}
|
15
|
-
catch {
|
16
|
-
return false;
|
17
|
-
}
|
18
|
-
}));
|
19
|
-
}
|
20
|
-
resolve() { }
|
21
|
-
}
|
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|
@@ -1,52 +0,0 @@
|
|
1
|
-
import { applets } from '../index';
|
2
|
-
class AppletView extends HTMLElement {
|
3
|
-
connectedCallback() {
|
4
|
-
const styles = document.createElement('style');
|
5
|
-
styles.textContent = this.styles;
|
6
|
-
this.appendChild(styles);
|
7
|
-
this.container = document.createElement('iframe');
|
8
|
-
this.appendChild(this.container);
|
9
|
-
}
|
10
|
-
get styles() {
|
11
|
-
return /*css*/ `
|
12
|
-
applet-frame {
|
13
|
-
display: flex;
|
14
|
-
flex-direction: column;
|
15
|
-
}
|
16
|
-
|
17
|
-
applet-frame iframe {
|
18
|
-
border: none;
|
19
|
-
}
|
20
|
-
|
21
|
-
applet-frame:not(.frameless) {
|
22
|
-
border: 1px solid #ddd;
|
23
|
-
}
|
24
|
-
|
25
|
-
applet-frame.frameless {
|
26
|
-
padding: 0 7px;
|
27
|
-
}
|
28
|
-
`;
|
29
|
-
}
|
30
|
-
set url(url) {
|
31
|
-
setTimeout(() => this.loadApplet(url), 1);
|
32
|
-
}
|
33
|
-
async loadApplet(url) {
|
34
|
-
if (!this.container)
|
35
|
-
return;
|
36
|
-
this.applet = await applets.load(url, this.container);
|
37
|
-
if (this.applet.manifest.frameless)
|
38
|
-
this.classList.add('frameless');
|
39
|
-
this.applet.onstateupdated = () => {
|
40
|
-
this.dispatchEvent(new CustomEvent('stateupdated', { detail: this.applet.state }));
|
41
|
-
};
|
42
|
-
this.dispatchEvent(new CustomEvent('load'));
|
43
|
-
}
|
44
|
-
set state(state) {
|
45
|
-
if (this.applet)
|
46
|
-
this.applet.state = state;
|
47
|
-
this.addEventListener('load', () => {
|
48
|
-
this.applet.state = state;
|
49
|
-
});
|
50
|
-
}
|
51
|
-
}
|
52
|
-
customElements.define('applet-frame', AppletView);
|
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|
@@ -1,52 +0,0 @@
|
|
1
|
-
import { applets } from '../index.js';
|
2
|
-
class AppletFrame extends HTMLElement {
|
3
|
-
connectedCallback() {
|
4
|
-
const styles = document.createElement('style');
|
5
|
-
styles.textContent = this.styles;
|
6
|
-
this.appendChild(styles);
|
7
|
-
this.container = document.createElement('iframe');
|
8
|
-
this.appendChild(this.container);
|
9
|
-
}
|
10
|
-
get styles() {
|
11
|
-
return /*css*/ `
|
12
|
-
applet-frame {
|
13
|
-
display: flex;
|
14
|
-
flex-direction: column;
|
15
|
-
}
|
16
|
-
|
17
|
-
applet-frame iframe {
|
18
|
-
border: none;
|
19
|
-
}
|
20
|
-
|
21
|
-
applet-frame:not(.frameless) {
|
22
|
-
border: 1px solid #ddd;
|
23
|
-
}
|
24
|
-
|
25
|
-
applet-frame.frameless {
|
26
|
-
padding: 0 7px;
|
27
|
-
}
|
28
|
-
`;
|
29
|
-
}
|
30
|
-
set url(url) {
|
31
|
-
setTimeout(() => this.loadApplet(url), 1);
|
32
|
-
}
|
33
|
-
async loadApplet(url) {
|
34
|
-
if (!this.container)
|
35
|
-
return;
|
36
|
-
this.applet = await applets.load(url, this.container);
|
37
|
-
if (this.applet.manifest.frameless)
|
38
|
-
this.classList.add('frameless');
|
39
|
-
this.applet.onstateupdated = () => {
|
40
|
-
this.dispatchEvent(new CustomEvent('stateupdated', { detail: this.applet.state }));
|
41
|
-
};
|
42
|
-
this.dispatchEvent(new CustomEvent('load'));
|
43
|
-
}
|
44
|
-
set state(state) {
|
45
|
-
if (this.applet)
|
46
|
-
this.applet.state = state;
|
47
|
-
this.addEventListener('load', () => {
|
48
|
-
this.applet.state = state;
|
49
|
-
});
|
50
|
-
}
|
51
|
-
}
|
52
|
-
customElements.define('applet-frame', AppletFrame);
|