@web-applets/sdk 0.1.5 → 0.2.0-alpha.9
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 +9 -130
- package/dist/applets/actions.d.ts +6 -0
- package/dist/applets/applet-factory.d.ts +6 -0
- package/dist/applets/applet-factory.js +23 -0
- package/dist/applets/applet-scope.d.ts +31 -0
- package/dist/applets/applet-scope.js +209 -0
- package/dist/applets/applet.d.ts +21 -0
- package/dist/applets/applet.js +161 -0
- package/dist/applets/errors.d.ts +6 -0
- package/dist/applets/errors.js +12 -0
- package/dist/applets/events.d.ts +15 -0
- package/dist/applets/events.js +11 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +5 -0
- package/dist/debug.d.ts +5 -0
- package/dist/debug.js +6 -0
- package/dist/elements/applet-frame.d.ts +16 -0
- package/dist/elements/applet-frame.js +110 -0
- package/dist/index.d.ts +10 -9
- package/dist/index.js +8 -9
- package/dist/messages.d.ts +46 -0
- package/dist/messages.js +1 -0
- package/dist/polyfill.d.ts +11 -0
- package/dist/polyfill.js +6 -0
- package/dist/utils.d.ts +28 -1
- package/dist/utils.js +4 -26
- package/dist/web-applets.min.js +13 -0
- package/package.json +6 -2
- package/dist/components/applet-frame.d.ts +0 -19
- package/dist/components/applet-frame.js +0 -94
- package/dist/core/applet.d.ts +0 -21
- package/dist/core/applet.js +0 -117
- package/dist/core/context.d.ts +0 -32
- package/dist/core/context.js +0 -138
- package/dist/core/shared.d.ts +0 -124
- package/dist/core/shared.js +0 -177
- package/dist/types.d.ts +0 -9
- /package/dist/{types.js → applets/actions.js} +0 -0
package/dist/debug.d.ts
ADDED
package/dist/debug.js
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
import { AppletEvent } from '../index.js';
|
2
|
+
export declare class AppletFrameElement extends HTMLElement {
|
3
|
+
#private;
|
4
|
+
onload: (event: Event) => Promise<void> | void;
|
5
|
+
onactions: (event: AppletEvent) => Promise<void> | void;
|
6
|
+
ondata: (event: AppletEvent) => Promise<void> | void;
|
7
|
+
static observedAttributes: string[];
|
8
|
+
connectedCallback(): void;
|
9
|
+
get contentWindow(): Window;
|
10
|
+
set src(value: string);
|
11
|
+
get src(): string;
|
12
|
+
attributeChangedCallback(name: string, oldValue: string, newValue: string): void;
|
13
|
+
get applet(): import("../applets/applet.js").Applet<unknown>;
|
14
|
+
set data(data: any);
|
15
|
+
get styles(): string;
|
16
|
+
}
|
@@ -0,0 +1,110 @@
|
|
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 _AppletFrameElement_instances, _AppletFrameElement_root, _AppletFrameElement_src, _AppletFrameElement_applet, _AppletFrameElement_dispatchEventAndHandler, _AppletFrameElement_iframe, _AppletFrameElement_loadApplet, _AppletFrameElement_resizeContainer;
|
13
|
+
import { applets } from '../index.js';
|
14
|
+
import { dispatchEventAndHandler } from '../utils.js';
|
15
|
+
export class AppletFrameElement extends HTMLElement {
|
16
|
+
constructor() {
|
17
|
+
super(...arguments);
|
18
|
+
_AppletFrameElement_instances.add(this);
|
19
|
+
_AppletFrameElement_root.set(this, void 0);
|
20
|
+
_AppletFrameElement_src.set(this, void 0);
|
21
|
+
_AppletFrameElement_applet.set(this, void 0);
|
22
|
+
_AppletFrameElement_dispatchEventAndHandler.set(this, dispatchEventAndHandler.bind(this));
|
23
|
+
_AppletFrameElement_iframe.set(this, document.createElement('iframe'));
|
24
|
+
}
|
25
|
+
connectedCallback() {
|
26
|
+
__classPrivateFieldSet(this, _AppletFrameElement_root, this.attachShadow({ mode: 'closed' }), "f");
|
27
|
+
__classPrivateFieldGet(this, _AppletFrameElement_root, "f").appendChild(__classPrivateFieldGet(this, _AppletFrameElement_iframe, "f"));
|
28
|
+
const styles = document.createElement('style');
|
29
|
+
styles.textContent = this.styles;
|
30
|
+
__classPrivateFieldGet(this, _AppletFrameElement_root, "f").appendChild(styles);
|
31
|
+
this.src = this.getAttribute('src');
|
32
|
+
}
|
33
|
+
get contentWindow() {
|
34
|
+
return __classPrivateFieldGet(this, _AppletFrameElement_iframe, "f").contentWindow;
|
35
|
+
}
|
36
|
+
set src(value) {
|
37
|
+
__classPrivateFieldSet(this, _AppletFrameElement_src, value, "f");
|
38
|
+
__classPrivateFieldSet(this, _AppletFrameElement_applet, undefined, "f");
|
39
|
+
__classPrivateFieldGet(this, _AppletFrameElement_instances, "m", _AppletFrameElement_loadApplet).call(this, value);
|
40
|
+
}
|
41
|
+
get src() {
|
42
|
+
return __classPrivateFieldGet(this, _AppletFrameElement_src, "f") || '';
|
43
|
+
}
|
44
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
45
|
+
if (name === 'src') {
|
46
|
+
this.src = newValue;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
get applet() {
|
50
|
+
return __classPrivateFieldGet(this, _AppletFrameElement_applet, "f");
|
51
|
+
}
|
52
|
+
set data(data) {
|
53
|
+
if (this.applet) {
|
54
|
+
this.applet.data = data;
|
55
|
+
}
|
56
|
+
else {
|
57
|
+
const listener = () => {
|
58
|
+
if (this.applet)
|
59
|
+
this.applet.data = data;
|
60
|
+
this.removeEventListener('load', listener);
|
61
|
+
};
|
62
|
+
this.addEventListener('load', listener);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
get styles() {
|
66
|
+
return /*css*/ `
|
67
|
+
:host {
|
68
|
+
display: flex;
|
69
|
+
flex-direction: column;
|
70
|
+
height: 350px;
|
71
|
+
}
|
72
|
+
|
73
|
+
iframe {
|
74
|
+
border: none;
|
75
|
+
height: 100%;
|
76
|
+
width: 100%;
|
77
|
+
}
|
78
|
+
`;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
_AppletFrameElement_root = new WeakMap(), _AppletFrameElement_src = new WeakMap(), _AppletFrameElement_applet = new WeakMap(), _AppletFrameElement_dispatchEventAndHandler = new WeakMap(), _AppletFrameElement_iframe = new WeakMap(), _AppletFrameElement_instances = new WeakSet(), _AppletFrameElement_loadApplet = async function _AppletFrameElement_loadApplet(url) {
|
82
|
+
__classPrivateFieldGet(this, _AppletFrameElement_iframe, "f").src = url;
|
83
|
+
const window = __classPrivateFieldGet(this, _AppletFrameElement_iframe, "f").contentWindow;
|
84
|
+
if (!window)
|
85
|
+
return;
|
86
|
+
__classPrivateFieldSet(this, _AppletFrameElement_applet, await applets.connect(window), "f");
|
87
|
+
// When data received, bubble the event up
|
88
|
+
__classPrivateFieldGet(this, _AppletFrameElement_applet, "f").ondata = (event) => {
|
89
|
+
__classPrivateFieldGet(this, _AppletFrameElement_dispatchEventAndHandler, "f").call(this, event);
|
90
|
+
};
|
91
|
+
// Resize
|
92
|
+
__classPrivateFieldGet(this, _AppletFrameElement_applet, "f").onresize = (event) => {
|
93
|
+
__classPrivateFieldGet(this, _AppletFrameElement_instances, "m", _AppletFrameElement_resizeContainer).call(this, {
|
94
|
+
width: __classPrivateFieldGet(this, _AppletFrameElement_applet, "f").width,
|
95
|
+
height: __classPrivateFieldGet(this, _AppletFrameElement_applet, "f").height,
|
96
|
+
});
|
97
|
+
};
|
98
|
+
__classPrivateFieldGet(this, _AppletFrameElement_applet, "f").onactions = (event) => {
|
99
|
+
__classPrivateFieldGet(this, _AppletFrameElement_dispatchEventAndHandler, "f").call(this, event);
|
100
|
+
};
|
101
|
+
// Emit load event when setup & connection complete
|
102
|
+
__classPrivateFieldGet(this, _AppletFrameElement_dispatchEventAndHandler, "f").call(this, new Event('load'));
|
103
|
+
if (this['load'] && typeof this['load'] === 'function') {
|
104
|
+
this.onload(new Event('load'));
|
105
|
+
}
|
106
|
+
}, _AppletFrameElement_resizeContainer = function _AppletFrameElement_resizeContainer(dimensions) {
|
107
|
+
this.style.height = `${dimensions.height}px`;
|
108
|
+
};
|
109
|
+
AppletFrameElement.observedAttributes = ['src'];
|
110
|
+
customElements.define('applet-frame', AppletFrameElement);
|
package/dist/index.d.ts
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
|
2
|
-
export
|
3
|
-
|
4
|
-
import {
|
5
|
-
|
6
|
-
export
|
7
|
-
|
8
|
-
|
9
|
-
};
|
1
|
+
import { AppletFactory } from './applets/applet-factory.js';
|
2
|
+
export declare const applets: AppletFactory;
|
3
|
+
import { Applet as AppletClass } from './applets/applet.js';
|
4
|
+
import { AppletScope as AppletScopeClass } from './applets/applet-scope.js';
|
5
|
+
export type Applet = InstanceType<typeof AppletClass>;
|
6
|
+
export type AppletScope = InstanceType<typeof AppletScopeClass>;
|
7
|
+
import './elements/applet-frame.js';
|
8
|
+
export { AppletFrameElement } from './elements/applet-frame.js';
|
9
|
+
export { AppletEvent } from './applets/events.js';
|
10
|
+
export { type AppletActionDescriptor } from './applets/actions.js';
|
package/dist/index.js
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
export
|
4
|
-
|
5
|
-
import
|
6
|
-
export
|
7
|
-
|
8
|
-
|
9
|
-
};
|
1
|
+
// AppletFactory
|
2
|
+
import { AppletFactory } from './applets/applet-factory.js';
|
3
|
+
export const applets = new AppletFactory();
|
4
|
+
// AppletFrame
|
5
|
+
import './elements/applet-frame.js';
|
6
|
+
export { AppletFrameElement } from './elements/applet-frame.js';
|
7
|
+
// AppletEvent
|
8
|
+
export { AppletEvent } from './applets/events.js';
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import { AppletActionDescriptor } from './applets/actions.js';
|
2
|
+
import { AppletManifest } from './utils.js';
|
3
|
+
export interface AppletMessage {
|
4
|
+
type: string;
|
5
|
+
}
|
6
|
+
export interface AppletConnectMessage {
|
7
|
+
type: 'appletconnect';
|
8
|
+
}
|
9
|
+
export interface AppletRegisterMessage {
|
10
|
+
type: 'register';
|
11
|
+
manifest?: AppletManifest;
|
12
|
+
actions?: {
|
13
|
+
[id: string]: AppletActionDescriptor;
|
14
|
+
};
|
15
|
+
data?: any;
|
16
|
+
}
|
17
|
+
export interface AppletActionMessage extends AppletMessage {
|
18
|
+
type: 'action';
|
19
|
+
id: string;
|
20
|
+
actionId: string;
|
21
|
+
arguments: any;
|
22
|
+
}
|
23
|
+
export interface AppletActionCompleteMessage extends AppletMessage {
|
24
|
+
type: 'actioncomplete';
|
25
|
+
id: string;
|
26
|
+
}
|
27
|
+
export interface AppletActionErrorMessage extends AppletMessage {
|
28
|
+
type: 'actionerror';
|
29
|
+
id: string;
|
30
|
+
message: string;
|
31
|
+
}
|
32
|
+
export interface AppletActionsMessage extends AppletMessage {
|
33
|
+
type: 'actions';
|
34
|
+
actions: {
|
35
|
+
[key: string]: AppletActionDescriptor;
|
36
|
+
};
|
37
|
+
}
|
38
|
+
export interface AppletDataMessage<T = any> extends AppletMessage {
|
39
|
+
type: 'data';
|
40
|
+
data: T;
|
41
|
+
}
|
42
|
+
export interface AppletResizeMessage extends AppletMessage {
|
43
|
+
type: 'resize';
|
44
|
+
height: number;
|
45
|
+
width: number;
|
46
|
+
}
|
package/dist/messages.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { AppletFrameElement } from './index.js';
|
2
|
+
import './index.js';
|
3
|
+
import { type AppletFactory } from './applets/applet-factory.js';
|
4
|
+
import { AppletEvent } from './applets/events.js';
|
5
|
+
declare global {
|
6
|
+
interface Window {
|
7
|
+
applets: AppletFactory;
|
8
|
+
AppletEvent: typeof AppletEvent;
|
9
|
+
AppletFrameElement: typeof AppletFrameElement;
|
10
|
+
}
|
11
|
+
}
|
package/dist/polyfill.js
ADDED
package/dist/utils.d.ts
CHANGED
@@ -1 +1,28 @@
|
|
1
|
-
|
1
|
+
import { AppletActionDescriptor } from './applets/actions.js';
|
2
|
+
export declare function dispatchEventAndHandler(event: Event): void;
|
3
|
+
export interface AppletManifest {
|
4
|
+
name?: string;
|
5
|
+
short_name?: string;
|
6
|
+
icons?: {
|
7
|
+
src: string;
|
8
|
+
purpose?: string;
|
9
|
+
sizes?: string;
|
10
|
+
type?: string;
|
11
|
+
}[];
|
12
|
+
description?: string;
|
13
|
+
display?: string;
|
14
|
+
start_url?: string;
|
15
|
+
actions?: {
|
16
|
+
[id: string]: AppletActionDescriptor;
|
17
|
+
};
|
18
|
+
[key: string]: any;
|
19
|
+
}
|
20
|
+
export interface JSONSchemaObject {
|
21
|
+
type: 'object' | 'string' | 'number' | 'integer' | 'array' | 'boolean' | 'null';
|
22
|
+
description?: string;
|
23
|
+
properties?: {
|
24
|
+
[key: string]: JSONSchemaObject;
|
25
|
+
};
|
26
|
+
required?: string[];
|
27
|
+
additionalProperties?: boolean;
|
28
|
+
}
|
package/dist/utils.js
CHANGED
@@ -1,28 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
return '';
|
5
|
-
try {
|
6
|
-
// If the base URL is provided, ensure it has a trailing slash for proper path resolution
|
7
|
-
if (base) {
|
8
|
-
// Don't add trailing slash if the base already ends with a file extension
|
9
|
-
if (!base.match(/\.[a-zA-Z0-9]+$/)) {
|
10
|
-
base = base.endsWith('/') ? base : base + '/';
|
11
|
-
}
|
12
|
-
}
|
13
|
-
// Use URL constructor to properly resolve relative paths
|
14
|
-
const resolvedUrl = new URL(url, base ?? window.location.href);
|
15
|
-
return trimTrailingSlash(resolvedUrl.href);
|
1
|
+
export function dispatchEventAndHandler(event) {
|
2
|
+
if (typeof this[`on${event.type}`] === 'function') {
|
3
|
+
this[`on${event.type}`](event);
|
16
4
|
}
|
17
|
-
|
18
|
-
// Return original URL if parsing fails
|
19
|
-
console.warn('Failed to parse URL:', e);
|
20
|
-
return url;
|
21
|
-
}
|
22
|
-
}
|
23
|
-
function trimTrailingSlash(url) {
|
24
|
-
if (url.endsWith('/')) {
|
25
|
-
return url.slice(0, -1);
|
26
|
-
}
|
27
|
-
return url;
|
5
|
+
this.dispatchEvent(event);
|
28
6
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
(()=>{var h=class extends Error{constructor(e){super(e),this.name="AppletExecutionError"}},A=class extends Error{constructor(e){super(e),this.name="AppletConnectionError"}};function c(p){typeof this[`on${p.type}`]=="function"&&this[`on${p.type}`](p),this.dispatchEvent(p)}var o=class extends Event{constructor(e,t){super(e,{bubbles:t?.bubbles,composed:t?.composed,cancelable:t?.cancelable}),this.data=t?.data,this.actions=t?.actions}};function b(p,...e){console.log(`[${p}]`,...e)}var a={log:b};var f=class extends EventTarget{#s;#o={};#t;#i;#n;#e;#a;#p;#r;constructor(e){super(),a.log("Applet","Constructor called"),this.#s=e,this.#n=c.bind(this),this.#c();let t=s=>{s.source===this.#s&&"type"in s.data&&s.data.type==="appletconnect"&&(a.log("Applet","Recieved message",s.data),this.#c(),this.removeEventListener("message",t))};window.addEventListener("message",t)}#c(){this.#e&&this.#e.close();let e=new MessageChannel,t={type:"appletconnect"};a.log("Applet","Send message",t),this.#e=e.port1,this.#e.onmessage=this.#h.bind(this),this.#s.postMessage(t,"*",[e.port2]),this.#a=this.#e.postMessage.bind(this.#e)}#h(e){let t=e.data;switch(a.log("Applet","Recieved message",t),t.type){case"register":let s=t;this.#t=s.manifest;let n=new o("connect");this.#n(n),this.#o=s.actions,this.#d(s.actions),this.#i=s.data,this.#l(s.data);break;case"data":let i=t;this.#i=i.data,this.#l(i.data);break;case"resize":let r=t;this.#p=r.width,this.#r=r.height;let g=new o("resize");this.#n(g);break;case"actions":let m=t;this.#o=m.actions,this.#d(m.actions);break}}#l(e){let t=new o("data",{data:e});this.#n(t)}#d(e){let t=new o("actions",{actions:e});this.#n(t)}async sendAction(e,t){let s={id:crypto.randomUUID(),type:"action",actionId:e,arguments:t};return new Promise((n,i)=>{this.#a(s);let r=setTimeout(()=>{i(new h(`Applet action handler failed to complete before timeout (${1e4}ms)`))},1e4),g=m=>{let d=m.data;if(["actioncomplete","actionerror"].includes(d.type)&&"id"in d&&d.id===s.id)if(this.#e.removeEventListener("message",g),clearTimeout(r),d.type==="actionerror"){let w=d;i(new h(w.message))}else n()};this.#e.addEventListener("message",g)})}get data(){return this.#i}set data(e){this.#i=e;let t={type:"data",data:e};this.#a(t)}get window(){return this.#s}get manifest(){return this.#t}get actions(){return this.#o}get width(){return this.#p}get height(){return this.#r}};var E=class extends EventTarget{#s={};#o;#t;#i;#n;#e;#a;#p;constructor(e){super(),a.log("AppletScope","Constructor called"),this.#n=c.bind(this),e&&(this.#o=e);let t=n=>{if(n.source===window.parent&&n.data.type==="appletconnect"&&n.ports&&n.ports.length>0){a.log("AppletScope","Recieved message",n.data);let i=n.ports[0];this.#e=i.postMessage.bind(i),i.onmessage=this.#c.bind(this),this.removeEventListener("message",t),this.#r()}};window.addEventListener("message",t);let s={type:"appletconnect"};window.parent.postMessage(s,"*"),a.log("AppletScope","Send message",s)}async#r(){let e=this.manifest??await this.#g();this.#o=e||{},this.#t=this.#t||e?.actions||{};let t={type:"register",manifest:this.#o,actions:this.#t,data:this.#i};this.#e(t),a.log("AppletScope","Send message",t);let s=new o("connect");this.#n(s),this.#l()}#c(e){let t=e.data;switch(a.log("AppletScope","Recieved message",t),t.type){case"data":"data"in t&&(this.data=t.data);break;case"action":"type"in t&&t.type==="action"&&"id"in t&&typeof t.id=="string"&&"actionId"in t&&typeof t.actionId=="string"&&"arguments"in t&&this.#h(t);break}}async#h(e){if(Object.keys(this.#s).includes(e.actionId))try{await this.#s[e.actionId](e.arguments);let t={type:"actioncomplete",id:e.id};this.#e(t)}catch(t){let s={type:"actionerror",id:e.id,message:t.message};this.#e(s),console.error(t)}}#l(){new ResizeObserver(t=>{for(let s of t)this.#d({width:s.contentRect.width,height:s.contentRect.height})}).observe(document.querySelector("html"))}#d({width:e,height:t}){this.#a=e,this.#p=t;let s={type:"resize",width:e,height:t};a.log("AppletScope","Send message",s),this.#e(s)}async#g(){let e=document.querySelector('link[rel="manifest"]');if(e)try{let s=await(await fetch(e.href)).json();for(let n in s.actions){let i=s.actions[n];i.params_schema&&!Object.keys(i.params_schema).length&&(i.params_schema=void 0)}return s}catch{return}}setActionHandler(e,t){this.#s[e]=t}defineAction(e,t){let{handler:s,...n}=t;s&&(this.#s[e]=s),this.actions={...this.actions,[e]:n}}set actions(e){if(!e)return;this.#t=e;let t={type:"actions",actions:this.#t};a.log("AppletScope","Send message",t),this.#e&&this.#e(t);let s=new o("actions",{actions:e});setTimeout(()=>this.#n(s),1)}get actions(){return this.#t}get manifest(){return this.#o}get actionHandlers(){return this.#s}set actionHandlers(e){this.#s=e}set data(e){this.#i=e;let t={type:"data",data:e};a.log("AppletScope","Send message",t),this.#e&&this.#e(t);let s=new o("data",{data:e});setTimeout(()=>this.#n(s),1)}get data(){return this.#i}get width(){return this.#a}get height(){return this.#p}};var u=class{async connect(e){return new Promise((t,s)=>{let n=new f(e),i=setTimeout(()=>{s(new A(`Applet failed to connect before the timeout was reached (${1e4}ms)`))},1e4),r=()=>{t(n),n.removeEventListener("connect",r),clearTimeout(i)};n.addEventListener("connect",r)})}register(e){return new E(e)}};var l=class extends HTMLElement{#s;#o;#t;#i=c.bind(this);#n=document.createElement("iframe");static{this.observedAttributes=["src"]}connectedCallback(){this.#s=this.attachShadow({mode:"closed"}),this.#s.appendChild(this.#n);let e=document.createElement("style");e.textContent=this.styles,this.#s.appendChild(e),this.src=this.getAttribute("src")}get contentWindow(){return this.#n.contentWindow}set src(e){this.#o=e,this.#t=void 0,this.#e(e)}get src(){return this.#o||""}attributeChangedCallback(e,t,s){e==="src"&&(this.src=s)}async#e(e){this.#n.src=e;let t=this.#n.contentWindow;t&&(this.#t=await y.connect(t),this.#t.ondata=s=>{this.#i(s)},this.#t.onresize=s=>{this.#a({width:this.#t.width,height:this.#t.height})},this.#t.onactions=s=>{this.#i(s)},this.#i(new Event("load")),this.load&&typeof this.load=="function"&&this.onload(new Event("load")))}get applet(){return this.#t}set data(e){if(this.applet)this.applet.data=e;else{let t=()=>{this.applet&&(this.applet.data=e),this.removeEventListener("load",t)};this.addEventListener("load",t)}}#a(e){this.style.height=`${e.height}px`}get styles(){return`
|
2
|
+
:host {
|
3
|
+
display: flex;
|
4
|
+
flex-direction: column;
|
5
|
+
height: 350px;
|
6
|
+
}
|
7
|
+
|
8
|
+
iframe {
|
9
|
+
border: none;
|
10
|
+
height: 100%;
|
11
|
+
width: 100%;
|
12
|
+
}
|
13
|
+
`}};customElements.define("applet-frame",l);var y=new u;window.applets=y;window.AppletEvent=o;window.AppletFrameElement=l;})();
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@web-applets/sdk",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.2.0-alpha.9",
|
4
4
|
"description": "The Web Applets SDK, for creating & hosting Web Applets.",
|
5
5
|
"author": "Rupert Manfredi <rupert@unternet.co>",
|
6
6
|
"license": "MIT",
|
@@ -18,10 +18,14 @@
|
|
18
18
|
"url": "git+https://github.com/unternet-co/web-applets.git"
|
19
19
|
},
|
20
20
|
"scripts": {
|
21
|
-
"build": "
|
21
|
+
"build": "npm run build:module && npm run build:shim",
|
22
|
+
"build:module": "tsc && cp ../README.md ./README.md",
|
23
|
+
"build:shim": "node ./scripts/build.js",
|
22
24
|
"prepublishOnly": "npm run build"
|
23
25
|
},
|
24
26
|
"devDependencies": {
|
27
|
+
"@types/node": "^22.13.9",
|
28
|
+
"esbuild": "^0.25.0",
|
25
29
|
"typescript": "^5.6.2"
|
26
30
|
}
|
27
31
|
}
|
@@ -1,19 +0,0 @@
|
|
1
|
-
import { Applet } from '../index';
|
2
|
-
export declare class AppletFrame extends HTMLElement {
|
3
|
-
#private;
|
4
|
-
container?: HTMLIFrameElement;
|
5
|
-
applet?: Applet;
|
6
|
-
loaded?: boolean;
|
7
|
-
static observedAttributes: string[];
|
8
|
-
connectedCallback(): void;
|
9
|
-
set src(value: string);
|
10
|
-
get src(): string;
|
11
|
-
attributeChangedCallback(name: string, oldValue: string, newValue: string): void;
|
12
|
-
loadApplet(url: string): Promise<void>;
|
13
|
-
set data(data: any);
|
14
|
-
resizeContainer(dimensions: {
|
15
|
-
height: number;
|
16
|
-
width: number;
|
17
|
-
}): void;
|
18
|
-
get styles(): string;
|
19
|
-
}
|
@@ -1,94 +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 _AppletFrame_root, _AppletFrame_src;
|
13
|
-
import { applets, } from '../index';
|
14
|
-
// TODO: Add resize event handler, and resize DOM element
|
15
|
-
export class AppletFrame extends HTMLElement {
|
16
|
-
constructor() {
|
17
|
-
super(...arguments);
|
18
|
-
_AppletFrame_root.set(this, void 0);
|
19
|
-
_AppletFrame_src.set(this, void 0);
|
20
|
-
}
|
21
|
-
connectedCallback() {
|
22
|
-
__classPrivateFieldSet(this, _AppletFrame_root, this.attachShadow({ mode: 'open' }), "f");
|
23
|
-
this.container = document.createElement('iframe');
|
24
|
-
__classPrivateFieldGet(this, _AppletFrame_root, "f").appendChild(this.container);
|
25
|
-
const styles = document.createElement('style');
|
26
|
-
styles.textContent = this.styles;
|
27
|
-
__classPrivateFieldGet(this, _AppletFrame_root, "f").appendChild(styles);
|
28
|
-
const url = this.getAttribute('src');
|
29
|
-
if (url)
|
30
|
-
this.loadApplet(url);
|
31
|
-
}
|
32
|
-
set src(value) {
|
33
|
-
__classPrivateFieldSet(this, _AppletFrame_src, value, "f");
|
34
|
-
this.loadApplet(value);
|
35
|
-
}
|
36
|
-
get src() {
|
37
|
-
return __classPrivateFieldGet(this, _AppletFrame_src, "f");
|
38
|
-
}
|
39
|
-
attributeChangedCallback(name, oldValue, newValue) {
|
40
|
-
if (name === 'src') {
|
41
|
-
this.src = newValue;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
async loadApplet(url) {
|
45
|
-
if (!this.container)
|
46
|
-
return;
|
47
|
-
this.applet = await applets.load(url, this.container);
|
48
|
-
// When data received, bubble the event up
|
49
|
-
this.applet.ondata = (dataEvent) => {
|
50
|
-
this.dispatchEvent(dataEvent);
|
51
|
-
};
|
52
|
-
// Resize
|
53
|
-
this.applet.onresize = (resizeEvent) => {
|
54
|
-
this.resizeContainer(resizeEvent.dimensions);
|
55
|
-
};
|
56
|
-
this.applet.onactions = (e) => { };
|
57
|
-
// Emit a load event when loading complete
|
58
|
-
this.dispatchEvent(new Event('load'));
|
59
|
-
this.loaded = true;
|
60
|
-
}
|
61
|
-
set data(data) {
|
62
|
-
if (this.applet && this.loaded) {
|
63
|
-
this.applet.data = data;
|
64
|
-
}
|
65
|
-
else {
|
66
|
-
const loadListener = () => {
|
67
|
-
this.applet.data = data;
|
68
|
-
this.removeEventListener('load', loadListener);
|
69
|
-
};
|
70
|
-
this.addEventListener('load', loadListener);
|
71
|
-
}
|
72
|
-
}
|
73
|
-
resizeContainer(dimensions) {
|
74
|
-
this.style.height = `${dimensions.height}px`;
|
75
|
-
}
|
76
|
-
get styles() {
|
77
|
-
return /*css*/ `
|
78
|
-
:host {
|
79
|
-
display: flex;
|
80
|
-
flex-direction: column;
|
81
|
-
height: 350px;
|
82
|
-
}
|
83
|
-
|
84
|
-
iframe {
|
85
|
-
border: none;
|
86
|
-
height: 100%;
|
87
|
-
width: 100%;
|
88
|
-
}
|
89
|
-
`;
|
90
|
-
}
|
91
|
-
}
|
92
|
-
_AppletFrame_root = new WeakMap(), _AppletFrame_src = new WeakMap();
|
93
|
-
AppletFrame.observedAttributes = ['src'];
|
94
|
-
customElements.define('applet-frame', AppletFrame);
|
package/dist/core/applet.d.ts
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
import { AppletAction, ActionParams, AppletManifest, AppletDataEvent, AppletResizeEvent, AppletActionsEvent, AppletMessageRelay, AppletReadyEvent } from './shared';
|
2
|
-
export declare function load(url: string, container?: HTMLIFrameElement): Promise<Applet>;
|
3
|
-
export interface AppletOptions {
|
4
|
-
manifest: AppletManifest;
|
5
|
-
container: HTMLIFrameElement;
|
6
|
-
}
|
7
|
-
export declare class Applet<T = any> extends EventTarget {
|
8
|
-
#private;
|
9
|
-
messageRelay: AppletMessageRelay;
|
10
|
-
actions: AppletAction[];
|
11
|
-
container: HTMLIFrameElement;
|
12
|
-
constructor(manifest: AppletManifest, targetWindow: Window);
|
13
|
-
dispatchAction(actionId: string, params?: ActionParams): Promise<import("./shared").AppletMessage>;
|
14
|
-
get data(): T;
|
15
|
-
set data(data: T);
|
16
|
-
get manifest(): AppletManifest;
|
17
|
-
onready(event: AppletReadyEvent): void;
|
18
|
-
onresize(event: AppletResizeEvent): void;
|
19
|
-
onactions(event: AppletActionsEvent): void;
|
20
|
-
ondata(event: AppletDataEvent): void;
|
21
|
-
}
|
package/dist/core/applet.js
DELETED
@@ -1,117 +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_manifest, _Applet_data, _Applet_addListeners;
|
13
|
-
import { parseUrl } from '../utils';
|
14
|
-
import { AppletDataMessage, AppletInitMessage, AppletDataEvent, AppletResizeEvent, AppletActionsEvent, AppletMessageRelay, loadManifest, AppletReadyEvent, AppletActionMessage, } from './shared';
|
15
|
-
// Container for initializing applets without an explicit container
|
16
|
-
const hiddenContainer = document.createElement('iframe');
|
17
|
-
hiddenContainer.style.display = 'none';
|
18
|
-
document.body.appendChild(hiddenContainer);
|
19
|
-
// Options for loading an applet
|
20
|
-
// interface LoadOpts {
|
21
|
-
// unsafe?: boolean;
|
22
|
-
// }
|
23
|
-
// const defaultOpts: LoadOpts = {
|
24
|
-
// unsafe: false,
|
25
|
-
// };
|
26
|
-
// Load an applet object from a URL
|
27
|
-
export async function load(url, container
|
28
|
-
// opts?: LoadOpts
|
29
|
-
) {
|
30
|
-
if (!container)
|
31
|
-
container = hiddenContainer;
|
32
|
-
url = parseUrl(url);
|
33
|
-
const manifest = await loadManifest(url);
|
34
|
-
// If unsafe enabled, allow same origin sandbox
|
35
|
-
// This is required for e.g. YouTube embeds
|
36
|
-
// const _opts = Object.assign(defaultOpts, opts ?? {});
|
37
|
-
// if (_opts.unsafe && manifest.unsafe) {
|
38
|
-
// container.setAttribute(
|
39
|
-
// 'sandbox',
|
40
|
-
// 'allow-scripts allow-forms allow-same-origin'
|
41
|
-
// );
|
42
|
-
// } else {
|
43
|
-
// container.setAttribute('sandbox', 'allow-scripts allow-forms');
|
44
|
-
// }
|
45
|
-
container.setAttribute('sandbox', 'allow-scripts allow-forms allow-same-origin');
|
46
|
-
container.src = url;
|
47
|
-
const applet = new Applet(manifest, container.contentWindow);
|
48
|
-
return new Promise((resolve) => {
|
49
|
-
applet.onready = () => resolve(applet);
|
50
|
-
});
|
51
|
-
}
|
52
|
-
export class Applet extends EventTarget {
|
53
|
-
constructor(manifest, targetWindow) {
|
54
|
-
super();
|
55
|
-
_Applet_instances.add(this);
|
56
|
-
this.actions = [];
|
57
|
-
_Applet_manifest.set(this, void 0);
|
58
|
-
_Applet_data.set(this, void 0);
|
59
|
-
this.messageRelay = new AppletMessageRelay(targetWindow);
|
60
|
-
__classPrivateFieldSet(this, _Applet_manifest, manifest, "f");
|
61
|
-
__classPrivateFieldGet(this, _Applet_instances, "m", _Applet_addListeners).call(this);
|
62
|
-
this.messageRelay.on('ready', () => {
|
63
|
-
this.messageRelay.send(new AppletInitMessage());
|
64
|
-
});
|
65
|
-
}
|
66
|
-
async dispatchAction(actionId, params) {
|
67
|
-
const actionMessage = new AppletActionMessage({
|
68
|
-
actionId,
|
69
|
-
params,
|
70
|
-
});
|
71
|
-
return await this.messageRelay.send(actionMessage);
|
72
|
-
}
|
73
|
-
get data() {
|
74
|
-
return __classPrivateFieldGet(this, _Applet_data, "f");
|
75
|
-
}
|
76
|
-
set data(data) {
|
77
|
-
__classPrivateFieldSet(this, _Applet_data, data, "f");
|
78
|
-
this.messageRelay.send(new AppletDataMessage({ data }));
|
79
|
-
}
|
80
|
-
get manifest() {
|
81
|
-
return __classPrivateFieldGet(this, _Applet_manifest, "f");
|
82
|
-
}
|
83
|
-
onready(event) { }
|
84
|
-
onresize(event) { }
|
85
|
-
onactions(event) { }
|
86
|
-
ondata(event) { }
|
87
|
-
}
|
88
|
-
_Applet_manifest = new WeakMap(), _Applet_data = new WeakMap(), _Applet_instances = new WeakSet(), _Applet_addListeners = function _Applet_addListeners() {
|
89
|
-
this.messageRelay.on('ready', (message) => {
|
90
|
-
const readyEvent = new AppletReadyEvent();
|
91
|
-
if (typeof this.onready === 'function')
|
92
|
-
this.onready(readyEvent);
|
93
|
-
this.dispatchEvent(readyEvent);
|
94
|
-
});
|
95
|
-
this.messageRelay.on('data', (message) => {
|
96
|
-
__classPrivateFieldSet(this, _Applet_data, message.data, "f");
|
97
|
-
const dataEvent = new AppletDataEvent({ data: message.data });
|
98
|
-
if (typeof this.ondata === 'function')
|
99
|
-
this.ondata(dataEvent);
|
100
|
-
this.dispatchEvent(dataEvent);
|
101
|
-
});
|
102
|
-
this.messageRelay.on('resize', (message) => {
|
103
|
-
const resizeEvent = new AppletResizeEvent({
|
104
|
-
dimensions: message.dimensions,
|
105
|
-
});
|
106
|
-
if (typeof this.onresize === 'function')
|
107
|
-
this.onresize(resizeEvent);
|
108
|
-
this.dispatchEvent(resizeEvent);
|
109
|
-
});
|
110
|
-
this.messageRelay.on('actions', (message) => {
|
111
|
-
this.actions = message.actions;
|
112
|
-
const actionsEvent = new AppletActionsEvent({ actions: message.actions });
|
113
|
-
if (typeof this.onactions === 'function')
|
114
|
-
this.onactions(actionsEvent);
|
115
|
-
this.dispatchEvent(actionsEvent);
|
116
|
-
});
|
117
|
-
};
|