New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@netless/app-embedded-page

Package Overview
Dependencies
Maintainers
10
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@netless/app-embedded-page - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

src/style.scss

12

dist/index.d.ts
import type { NetlessApp } from "@netless/window-manager";
import type { State } from "./types";
export type { DiffOne, InitData, MetaData, ReceiveMessages, SendMessages, State } from "./types";
export interface Attributes {
export * from "./types";
export declare type Attributes = {
src: string;
state: State;
store: Record<string, unknown>;
page: string;
};
export interface AppOptions {
debug?: boolean;
}
declare const EmbeddedPage: NetlessApp<Attributes>;
declare const EmbeddedPage: NetlessApp<Attributes, void, AppOptions>;
export default EmbeddedPage;

@@ -1,2 +0,3 @@

"use strict";var C=Object.defineProperty;var v=Object.getOwnPropertySymbols;var D=Object.prototype.hasOwnProperty,A=Object.prototype.propertyIsEnumerable;var I=(t,s,e)=>s in t?C(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e,y=(t,s)=>{for(var e in s||(s={}))D.call(s,e)&&I(t,e,s[e]);if(v)for(var e of v(s))A.call(s,e)&&I(t,e,s[e]);return t};Object.defineProperty(exports,"__esModule",{value:!0});exports[Symbol.toStringTag]="Module";class M{constructor(){this.disposers=new Map,this.disposerIDGenCount=-1}add(s,e=this.genDisposerID()){return this.flush(e),this.disposers.set(e,s()),e}addEventListener(s,e,n,l,i=this.genDisposerID()){return this.add(()=>(s.addEventListener(e,n,l),()=>s.removeEventListener(e,n,l)),i),i}setTimeout(s,e,n=this.genDisposerID()){return this.add(()=>{const l=window.setTimeout(()=>{this.remove(n),s()},e);return()=>window.clearTimeout(l)},n)}setInterval(s,e,n=this.genDisposerID()){return this.add(()=>{const l=window.setInterval(s,e);return()=>window.clearInterval(l)},n)}remove(s){const e=this.disposers.get(s);return this.disposers.delete(s),e}flush(s){const e=this.remove(s);if(e)try{e()}catch(n){console.error(n)}}flushAll(){this.disposers.forEach(s=>{try{s()}catch(e){console.error(e)}}),this.disposers.clear()}genDisposerID(){const{MAX_SAFE_INTEGER:s=9007199254740991}=Number;return this.disposerIDGenCount=(this.disposerIDGenCount+1)%s,`disposer-${this.disposerIDGenCount}`}}function j(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function O(t,s){let e=t.getAttributes();if(e||(t.setAttributes(s),e=t.getAttributes()),!e)throw new Error("[NetlessAppMonaco] No attributes");return j(s)&&Object.keys(s).forEach(n=>{Object.prototype.hasOwnProperty.call(e,n)||t.updateAttributes([n],s[n])}),e}function S(t){return typeof t=="object"&&t!==null}const G=new Set(["clicker","selector"]),L={kind:"EmbeddedPage",setup(t){const s=t.getDisplayer(),e=t.getRoom(),n=t.getBox(),l=t.getView(),i=O(t,{src:"https://example.org",state:{},page:""}),p=new M,b=document.createElement("div");Object.assign(b.style,{width:"100%",height:"100%",position:"relative"});const g=document.createElement("iframe");Object.assign(g.style,{width:"100%",height:"100%",border:"none"}),b.appendChild(g),n.mountContent(b);let m=()=>{};const w=a=>G.has(a);if(l){const a=document.createElement("div");Object.assign(a.style,{width:"100%",height:"100%",position:"absolute",top:0,left:0}),b.appendChild(a),t.mountView(a),m=r=>{a.style.pointerEvents=r?"none":"auto"},m(w(e==null?void 0:e.state.memberState.currentApplianceName))}const u=a=>{var r;(r=g.contentWindow)==null||r.postMessage(a,"*")},f=`channel-${t.appId}`,E=a=>{a.event===f&&a.authorId!==s.observerId&&u({type:"ReceiveMessage",payload:a.payload})};p.add(()=>(s.addMagixEventListener(f,E),()=>s.removeMagixEventListener(f))),e&&p.add(()=>{const a=r=>{r.memberState&&m(w(r.memberState.currentApplianceName))};return e.callbacks.on("onRoomStateChanged",a),()=>e.callbacks.off("onRoomStateChanged",a)}),p.addEventListener(g,"load",()=>{var o;const a=s.observerId,r=(o=s.state.roomMembers.find(d=>d.memberId===a))==null?void 0:o.payload;u({type:"Init",payload:{state:i.state,page:i.page,writable:t.getIsWritable(),meta:{roomUUID:e==null?void 0:e.uuid,userPayload:r&&JSON.parse(JSON.stringify(r))}}})}),p.addEventListener(window,"message",a=>{if(a.source!==g.contentWindow||!S(a.data))return;const{data:r}=a,o=r.type;if(console.log("[EmbeddedPage] receive",r),o==="GetState")u({type:"GetState",payload:i.state});else if(o==="SetState"){if(S(r.payload)&&t.getIsWritable())for(const[d,c]of Object.entries(r.payload))t.updateAttributes(["state",d],c)}else if(o==="GetPage")u({type:"GetPage",payload:i.page});else if(o==="SetPage")if(!l)console.warn("[EmbeddedPage] SetPage: page api is only available with 'scenePath'");else{const d=r.payload,c=t.getInitScenePath();if(typeof d=="string"&&t.getIsWritable()&&c&&e){const h=[c,d].join("/");e.scenePathType(h)==="none"&&e.putScenes(c,[{name:d}]),t.setScenePath(h),t.updateAttributes(["page"],d)}}else o==="GetWritable"?u({type:"GetWritable",payload:t.getIsWritable()}):o==="SendMessage"&&t.getIsWritable()&&(e==null||e.dispatchMagixEvent(f,r.payload))}),p.add(()=>{let a=y({},i.state);const r=d=>{const c={};for(const{key:h,value:P}of d)c[h]={oldValue:a[h],newValue:P};a=y({},i.state),u({type:"StateChanged",payload:c})},o=()=>t.objectUtils.listenUpdated(i.state,r);return t.mobxUtils.reaction(()=>i.state,o,{fireImmediately:!0})}),p.add(()=>{const a=(r,o)=>{u({type:"PageChanged",payload:{oldValue:o,newValue:r}})};return t.mobxUtils.reaction(()=>i.page,a)}),p.add(()=>{const a=()=>{const r=t.getIsWritable();u({type:"WritableChanged",payload:{oldValue:!r,newValue:r}})};return t.emitter.on("writableChange",a),()=>t.emitter.off("writableChange",a)}),g.src=i.src,t.emitter.on("destroy",()=>{console.log("[EmbeddedPage]: destroy"),p.flushAll()})}};exports.default=L;
"use strict";var F=Object.defineProperty;var G=(o,i,s)=>i in o?F(o,i,{enumerable:!0,configurable:!0,writable:!0,value:s}):o[i]=s;var j=(o,i,s)=>(G(o,typeof i!="symbol"?i+"":i,s),s);Object.defineProperty(exports,"__esModule",{value:!0});exports[Symbol.toStringTag]="Module";class W{constructor(){this.disposers=new Map,this.disposerIDGenCount=-1}add(i,s=this.genDisposerID()){return this.flush(s),this.disposers.set(s,i()),s}addEventListener(i,s,l,c,y=this.genDisposerID()){return this.add(()=>(i.addEventListener(s,l,c),()=>i.removeEventListener(s,l,c)),y),y}setTimeout(i,s,l=this.genDisposerID()){return this.add(()=>{const c=window.setTimeout(()=>{this.remove(l),i()},s);return()=>window.clearTimeout(c)},l)}setInterval(i,s,l=this.genDisposerID()){return this.add(()=>{const c=window.setInterval(i,s);return()=>window.clearInterval(c)},l)}remove(i){const s=this.disposers.get(i);return this.disposers.delete(i),s}flush(i){const s=this.remove(i);if(s)try{s()}catch(l){console.error(l)}}flushAll(){this.disposers.forEach(i=>{try{i()}catch(s){console.error(s)}}),this.disposers.clear()}genDisposerID(){const{MAX_SAFE_INTEGER:i=9007199254740991}=Number;return this.disposerIDGenCount=(this.disposerIDGenCount+1)%i,`disposer-${this.disposerIDGenCount}`}}function B(o){return o!=null&&typeof o=="object"&&!Array.isArray(o)}function H(o,i){let s=o.getAttributes();if(s||(o.setAttributes(i),s=o.getAttributes()),!s)throw new Error("[NetlessAppMonaco] No attributes");return B(i)&&Object.keys(i).forEach(l=>{Object.prototype.hasOwnProperty.call(s,l)||o.updateAttributes([l],i[l])}),s}var V=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},U={exports:{}};(function(o,i){(function(s,l){{var c=l();o&&o.exports&&(i=o.exports=c),i.randomColor=c}})(V,function(){var s=null,l={};L();var c=[],y=function(r){if(r=r||{},r.seed!==void 0&&r.seed!==null&&r.seed===parseInt(r.seed,10))s=r.seed;else if(typeof r.seed=="string")s=E(r.seed);else{if(r.seed!==void 0&&r.seed!==null)throw new TypeError("The seed value must be an integer or string");s=null}var n,e,t;if(r.count!==null&&r.count!==void 0){for(var a=r.count,d=[],u=0;u<r.count;u++)c.push(!1);for(r.count=null;a>d.length;){var v=y(r);s!==null&&(r.seed=s),d.push(v)}return r.count=a,d}return n=D(r),e=T(n,r),t=g(n,e,r),b([n,e,t],r)};function D(r){if(c.length>0){var n=$(r.hue),e=p(n),t=(n[1]-n[0])/c.length,a=parseInt((e-n[0])/t);c[a]===!0?a=(a+2)%c.length:c[a]=!0;var d=(n[0]+a*t)%359,u=(n[0]+(a+1)*t)%359;return n=[d,u],e=p(n),e<0&&(e=360+e),e}else{var n=M(r.hue);return e=p(n),e<0&&(e=360+e),e}}function T(r,n){if(n.hue==="monochrome")return 0;if(n.luminosity==="random")return p([0,100]);var e=S(r),t=e[0],a=e[1];switch(n.luminosity){case"bright":t=55;break;case"dark":t=a-10;break;case"light":a=55;break}return p([t,a])}function g(r,n,e){var t=h(r,n),a=100;switch(e.luminosity){case"dark":a=t+20;break;case"light":t=(a+t)/2;break;case"random":t=0,a=100;break}return p([t,a])}function b(r,n){switch(n.format){case"hsvArray":return r;case"hslArray":return P(r);case"hsl":var e=P(r);return"hsl("+e[0]+", "+e[1]+"%, "+e[2]+"%)";case"hsla":var t=P(r),a=n.alpha||Math.random();return"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+a+")";case"rgbArray":return C(r);case"rgb":var d=C(r);return"rgb("+d.join(", ")+")";case"rgba":var u=C(r),a=n.alpha||Math.random();return"rgba("+u.join(", ")+", "+a+")";default:return N(r)}}function h(r,n){for(var e=m(r).lowerBounds,t=0;t<e.length-1;t++){var a=e[t][0],d=e[t][1],u=e[t+1][0],v=e[t+1][1];if(n>=a&&n<=u){var A=(v-d)/(u-a),w=d-A*a;return A*n+w}}return 0}function M(r){if(typeof parseInt(r)=="number"){var n=parseInt(r);if(n<360&&n>0)return[n,n]}if(typeof r=="string"){if(l[r]){var e=l[r];if(e.hueRange)return e.hueRange}else if(r.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)){var t=O(r)[0];return[t,t]}}return[0,360]}function S(r){return m(r).saturationRange}function m(r){r>=334&&r<=360&&(r-=360);for(var n in l){var e=l[n];if(e.hueRange&&r>=e.hueRange[0]&&r<=e.hueRange[1])return l[n]}return"Color not found"}function p(r){if(s===null){var n=.618033988749895,e=Math.random();return e+=n,e%=1,Math.floor(r[0]+e*(r[1]+1-r[0]))}else{var t=r[1]||1,a=r[0]||0;s=(s*9301+49297)%233280;var d=s/233280;return Math.floor(a+d*(t-a))}}function N(r){var n=C(r);function e(a){var d=a.toString(16);return d.length==1?"0"+d:d}var t="#"+e(n[0])+e(n[1])+e(n[2]);return t}function f(r,n,e){var t=e[0][0],a=e[e.length-1][0],d=e[e.length-1][1],u=e[0][1];l[r]={hueRange:n,lowerBounds:e,saturationRange:[t,a],brightnessRange:[d,u]}}function L(){f("monochrome",null,[[0,0],[100,0]]),f("red",[-26,18],[[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]),f("orange",[18,46],[[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]),f("yellow",[46,62],[[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]),f("green",[62,178],[[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]),f("blue",[178,257],[[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]),f("purple",[257,282],[[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]),f("pink",[282,334],[[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]])}function C(r){var n=r[0];n===0&&(n=1),n===360&&(n=359),n=n/360;var e=r[1]/100,t=r[2]/100,a=Math.floor(n*6),d=n*6-a,u=t*(1-e),v=t*(1-d*e),A=t*(1-(1-d)*e),w=256,k=256,I=256;switch(a){case 0:w=t,k=A,I=u;break;case 1:w=v,k=t,I=u;break;case 2:w=u,k=t,I=A;break;case 3:w=u,k=v,I=t;break;case 4:w=A,k=u,I=t;break;case 5:w=t,k=u,I=v;break}var _=[Math.floor(w*255),Math.floor(k*255),Math.floor(I*255)];return _}function O(r){r=r.replace(/^#/,""),r=r.length===3?r.replace(/(.)/g,"$1$1"):r;var n=parseInt(r.substr(0,2),16)/255,e=parseInt(r.substr(2,2),16)/255,t=parseInt(r.substr(4,2),16)/255,a=Math.max(n,e,t),d=a-Math.min(n,e,t),u=a?d/a:0;switch(a){case n:return[60*((e-t)/d%6)||0,u,a];case e:return[60*((t-n)/d+2)||0,u,a];case t:return[60*((n-e)/d+4)||0,u,a]}}function P(r){var n=r[0],e=r[1]/100,t=r[2]/100,a=(2-e)*t;return[n,Math.round(e*t/(a<1?a:2-a)*1e4)/100,a/2*100]}function E(r){for(var n=0,e=0;e!==r.length&&!(n>=Number.MAX_SAFE_INTEGER);e++)n+=r.charCodeAt(e);return n}function $(r){if(isNaN(r)){if(typeof r=="string"){if(l[r]){var e=l[r];if(e.hueRange)return e.hueRange}else if(r.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)){var t=O(r)[0];return m(t).hueRange}}}else{var n=parseInt(r);if(n<360&&n>0)return m(r).hueRange}return[0,360]}return y})})(U,U.exports);var J=U.exports;class K{constructor(i="NetlessApp",s="error"){j(this,"kind");j(this,"debug");j(this,"color",J({luminosity:"dark"}));this.kind=i,this.debug=s}log(...i){if(this.debug===!0||this.debug==="log")return this._log("log",i)}warn(...i){if(this.debug&&this.debug!=="error")return this._log("warn",i)}error(...i){if(this.debug)return this._log("error",i)}_log(i,s){console[i](`%c[${this.kind}]:`,`color: ${this.color}; font-weight: bold;`,...s)}}function R(o){return typeof o=="object"&&o!==null}var X=`.netless-app-embedded-page{width:100%;height:100%;position:relative}.netless-app-embedded-page iframe{width:100%;height:100%;border:none;display:block}.netless-app-embedded-page-wb-view{width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}
`;const q=new Set(["clicker","selector"]),Y={kind:"EmbeddedPage",setup(o){var n;const i=o.getDisplayer(),s=o.getRoom(),l=o.getBox(),c=o.getView(),y=(n=o.getAppOptions())==null?void 0:n.debug,D={mainId:"state",nsPrefix:"$scope-"},T=D.nsPrefix+D.mainId,g=H(o,{src:"https://example.org",store:{[T]:{}},page:""}),b=new W,h=new K("EmbeddedPage",y),M=e=>{try{return R(e)?JSON.parse(JSON.stringify(e)):e}catch(t){throw h.error("Cannot parse to JSON object",e),t}},S=document.createElement("div");S.dataset.appKind="EmbeddedPage",S.classList.add("netless-app-embedded-page");const m=document.createElement("iframe");S.appendChild(m),l.mountStyles(X),l.mountContent(S);const p=e=>e.map(({memberId:t,payload:a})=>({sessionUID:t,uid:(s==null?void 0:s.uid)||(a==null?void 0:a.uid)||"",userPayload:M(a)})),N=(e,t)=>{let a=null;const d=o.mobxUtils.reaction(e,()=>{a&&(a(),a=null);const u=e();a=()=>o.objectUtils.unlistenUpdated(u,t),o.objectUtils.listenUpdated(u,t)},{fireImmediately:!0});return()=>{a==null||a(),d()}},f=e=>{var t;h.log("Message to SDK",e),(t=m.contentWindow)==null||t.postMessage(e,"*")};if(c){const e=document.createElement("div");if(e.classList.add("netless-app-embedded-page-wb-view"),S.appendChild(e),o.mountView(e),s){const t=a=>{e.style.pointerEvents=!a||q.has(a)?"none":"auto"};t(s.state.memberState.currentApplianceName),b.add(()=>{const a=d=>{d.memberState&&t(d.memberState.currentApplianceName)};return i.callbacks.on("onRoomStateChanged",a),()=>i.callbacks.off("onRoomStateChanged",a)})}}const L=e=>{c&&R(e)&&c.moveCamera({centerX:e.x,centerY:e.y,scale:e.scale,animationMode:"immediately"})},C=e=>{R(e)&&Object.keys(e).forEach(t=>{if(t!==T){const a=e[t];o.updateAttributes(["store",t],a)}})},O=e=>{if(R(e)&&e.namespace&&R(e.state)){const{namespace:t,state:a}=e;if(!o.getIsWritable()){h.error(`Cannot setState on store ${t} without writable access`,a);return}Object.keys(a).forEach(d=>{o.updateAttributes(["store",t,d],a[d])})}};b.add(()=>{const e=new W,t=d=>{e.add(()=>N(()=>g.store[d],u=>{f({type:"StateChanged",payload:{namespace:d,actions:M(u)}})}),d)};Object.keys(g.store).forEach(t);const a=N(()=>g.store,d=>{f({type:"StoreChanged",payload:M(d)}),g.store&&d.forEach(({key:u,kind:v})=>{switch(v){case 2:{e.flush(u);break}default:{t(u);break}}})});return()=>{e.flushAll(),a()}}),b.add(()=>{const e=t=>{(t==null?void 0:t.roomMembers)&&f({type:"RoomMembersChanged",payload:p(t.roomMembers)})};return i.callbacks.on("onRoomStateChanged",e),()=>i.callbacks.off("onRoomStateChanged",e)});const P=e=>{if(!c)h.warn("SetPage: page api is only available with 'scenePath' options enabled.");else{const t=o.getInitScenePath();if(typeof e=="string"&&o.getIsWritable()&&t&&s){const a=[t,e].join("/");s.scenePathType(a)==="none"&&s.putScenes(t,[{name:e}]),o.setScenePath(a),o.updateAttributes(["page"],e)}}};b.add(()=>{const e=(t,a)=>{f({type:"PageChanged",payload:{oldValue:a,newValue:t}})};return o.mobxUtils.reaction(()=>g.page,e)}),b.add(()=>{const e=()=>{const t=o.getIsWritable();f({type:"WritableChanged",payload:t}),h.log(`WritableChange changed to ${t}`)};return o.emitter.on("writableChange",e),()=>o.emitter.off("writableChange",e)});const E=`channel-${o.appId}`,$=e=>{o.getIsWritable()&&s&&s.dispatchMagixEvent(E,e)};b.add(()=>{const e=t=>{t.event===E&&t.authorId!==i.observerId&&f({type:"ReceiveMagixMessage",payload:t.payload})};return i.addMagixEventListener(E,e),()=>i.removeMagixEventListener(E,e)});const r=()=>{var a;const e=i.observerId,t=(a=i.state.roomMembers.find(d=>d.memberId===e))==null?void 0:a.payload;f({type:"Init",payload:{page:g.page,writable:o.getIsWritable(),roomMembers:p(i.state.roomMembers),debug:y,store:M(g.store),storeConfig:D,meta:{sessionUID:e,uid:(s==null?void 0:s.uid)||(t==null?void 0:t.uid)||"",roomUUID:s==null?void 0:s.uuid,userPayload:M(t)}}})};b.addEventListener(window,"message",e=>{if(e.source!==m.contentWindow)return;if(!R(e.data)){h.error("window message data should be object, instead got",e.data);return}const t=e.data;switch(h.log("Message From SDK",t),t.type){case"Init":{r();break}case"SetState":{O(t.payload);break}case"SetStore":{C(t.payload);break}case"SetPage":{P(t.payload);break}case"SendMagixMessage":{$(t.payload);break}case"MoveCamera":{L(t.payload);break}}}),o.emitter.on("destroy",()=>{h.log("destroy"),b.flushAll()}),m.src=g.src}};exports.default=Y;
//# sourceMappingURL=main.cjs.js.map
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};

@@ -89,5 +79,363 @@ class s {

}
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
var randomColor$1 = { exports: {} };
(function(module, exports) {
(function(root, factory) {
{
var randomColor2 = factory();
if (module && module.exports) {
exports = module.exports = randomColor2;
}
exports.randomColor = randomColor2;
}
})(commonjsGlobal, function() {
var seed = null;
var colorDictionary = {};
loadColorBounds();
var colorRanges = [];
var randomColor2 = function(options) {
options = options || {};
if (options.seed !== void 0 && options.seed !== null && options.seed === parseInt(options.seed, 10)) {
seed = options.seed;
} else if (typeof options.seed === "string") {
seed = stringToInteger(options.seed);
} else if (options.seed !== void 0 && options.seed !== null) {
throw new TypeError("The seed value must be an integer or string");
} else {
seed = null;
}
var H, S, B;
if (options.count !== null && options.count !== void 0) {
var totalColors = options.count, colors = [];
for (var i = 0; i < options.count; i++) {
colorRanges.push(false);
}
options.count = null;
while (totalColors > colors.length) {
var color = randomColor2(options);
if (seed !== null) {
options.seed = seed;
}
colors.push(color);
}
options.count = totalColors;
return colors;
}
H = pickHue(options);
S = pickSaturation(H, options);
B = pickBrightness(H, S, options);
return setFormat([H, S, B], options);
};
function pickHue(options) {
if (colorRanges.length > 0) {
var hueRange = getRealHueRange(options.hue);
var hue = randomWithin(hueRange);
var step = (hueRange[1] - hueRange[0]) / colorRanges.length;
var j = parseInt((hue - hueRange[0]) / step);
if (colorRanges[j] === true) {
j = (j + 2) % colorRanges.length;
} else {
colorRanges[j] = true;
}
var min = (hueRange[0] + j * step) % 359, max = (hueRange[0] + (j + 1) * step) % 359;
hueRange = [min, max];
hue = randomWithin(hueRange);
if (hue < 0) {
hue = 360 + hue;
}
return hue;
} else {
var hueRange = getHueRange(options.hue);
hue = randomWithin(hueRange);
if (hue < 0) {
hue = 360 + hue;
}
return hue;
}
}
function pickSaturation(hue, options) {
if (options.hue === "monochrome") {
return 0;
}
if (options.luminosity === "random") {
return randomWithin([0, 100]);
}
var saturationRange = getSaturationRange(hue);
var sMin = saturationRange[0], sMax = saturationRange[1];
switch (options.luminosity) {
case "bright":
sMin = 55;
break;
case "dark":
sMin = sMax - 10;
break;
case "light":
sMax = 55;
break;
}
return randomWithin([sMin, sMax]);
}
function pickBrightness(H, S, options) {
var bMin = getMinimumBrightness(H, S), bMax = 100;
switch (options.luminosity) {
case "dark":
bMax = bMin + 20;
break;
case "light":
bMin = (bMax + bMin) / 2;
break;
case "random":
bMin = 0;
bMax = 100;
break;
}
return randomWithin([bMin, bMax]);
}
function setFormat(hsv, options) {
switch (options.format) {
case "hsvArray":
return hsv;
case "hslArray":
return HSVtoHSL(hsv);
case "hsl":
var hsl = HSVtoHSL(hsv);
return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)";
case "hsla":
var hslColor = HSVtoHSL(hsv);
var alpha = options.alpha || Math.random();
return "hsla(" + hslColor[0] + ", " + hslColor[1] + "%, " + hslColor[2] + "%, " + alpha + ")";
case "rgbArray":
return HSVtoRGB(hsv);
case "rgb":
var rgb = HSVtoRGB(hsv);
return "rgb(" + rgb.join(", ") + ")";
case "rgba":
var rgbColor = HSVtoRGB(hsv);
var alpha = options.alpha || Math.random();
return "rgba(" + rgbColor.join(", ") + ", " + alpha + ")";
default:
return HSVtoHex(hsv);
}
}
function getMinimumBrightness(H, S) {
var lowerBounds = getColorInfo(H).lowerBounds;
for (var i = 0; i < lowerBounds.length - 1; i++) {
var s1 = lowerBounds[i][0], v1 = lowerBounds[i][1];
var s2 = lowerBounds[i + 1][0], v2 = lowerBounds[i + 1][1];
if (S >= s1 && S <= s2) {
var m = (v2 - v1) / (s2 - s1), b = v1 - m * s1;
return m * S + b;
}
}
return 0;
}
function getHueRange(colorInput) {
if (typeof parseInt(colorInput) === "number") {
var number = parseInt(colorInput);
if (number < 360 && number > 0) {
return [number, number];
}
}
if (typeof colorInput === "string") {
if (colorDictionary[colorInput]) {
var color = colorDictionary[colorInput];
if (color.hueRange) {
return color.hueRange;
}
} else if (colorInput.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)) {
var hue = HexToHSB(colorInput)[0];
return [hue, hue];
}
}
return [0, 360];
}
function getSaturationRange(hue) {
return getColorInfo(hue).saturationRange;
}
function getColorInfo(hue) {
if (hue >= 334 && hue <= 360) {
hue -= 360;
}
for (var colorName in colorDictionary) {
var color = colorDictionary[colorName];
if (color.hueRange && hue >= color.hueRange[0] && hue <= color.hueRange[1]) {
return colorDictionary[colorName];
}
}
return "Color not found";
}
function randomWithin(range) {
if (seed === null) {
var golden_ratio = 0.618033988749895;
var r = Math.random();
r += golden_ratio;
r %= 1;
return Math.floor(range[0] + r * (range[1] + 1 - range[0]));
} else {
var max = range[1] || 1;
var min = range[0] || 0;
seed = (seed * 9301 + 49297) % 233280;
var rnd = seed / 233280;
return Math.floor(min + rnd * (max - min));
}
}
function HSVtoHex(hsv) {
var rgb = HSVtoRGB(hsv);
function componentToHex(c) {
var hex2 = c.toString(16);
return hex2.length == 1 ? "0" + hex2 : hex2;
}
var hex = "#" + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
return hex;
}
function defineColor(name, hueRange, lowerBounds) {
var sMin = lowerBounds[0][0], sMax = lowerBounds[lowerBounds.length - 1][0], bMin = lowerBounds[lowerBounds.length - 1][1], bMax = lowerBounds[0][1];
colorDictionary[name] = {
hueRange,
lowerBounds,
saturationRange: [sMin, sMax],
brightnessRange: [bMin, bMax]
};
}
function loadColorBounds() {
defineColor("monochrome", null, [[0, 0], [100, 0]]);
defineColor("red", [-26, 18], [[20, 100], [30, 92], [40, 89], [50, 85], [60, 78], [70, 70], [80, 60], [90, 55], [100, 50]]);
defineColor("orange", [18, 46], [[20, 100], [30, 93], [40, 88], [50, 86], [60, 85], [70, 70], [100, 70]]);
defineColor("yellow", [46, 62], [[25, 100], [40, 94], [50, 89], [60, 86], [70, 84], [80, 82], [90, 80], [100, 75]]);
defineColor("green", [62, 178], [[30, 100], [40, 90], [50, 85], [60, 81], [70, 74], [80, 64], [90, 50], [100, 40]]);
defineColor("blue", [178, 257], [[20, 100], [30, 86], [40, 80], [50, 74], [60, 60], [70, 52], [80, 44], [90, 39], [100, 35]]);
defineColor("purple", [257, 282], [[20, 100], [30, 87], [40, 79], [50, 70], [60, 65], [70, 59], [80, 52], [90, 45], [100, 42]]);
defineColor("pink", [282, 334], [[20, 100], [30, 90], [40, 86], [60, 84], [80, 80], [90, 75], [100, 73]]);
}
function HSVtoRGB(hsv) {
var h = hsv[0];
if (h === 0) {
h = 1;
}
if (h === 360) {
h = 359;
}
h = h / 360;
var s2 = hsv[1] / 100, v = hsv[2] / 100;
var h_i = Math.floor(h * 6), f = h * 6 - h_i, p = v * (1 - s2), q = v * (1 - f * s2), t = v * (1 - (1 - f) * s2), r = 256, g = 256, b = 256;
switch (h_i) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
var result = [Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)];
return result;
}
function HexToHSB(hex) {
hex = hex.replace(/^#/, "");
hex = hex.length === 3 ? hex.replace(/(.)/g, "$1$1") : hex;
var red = parseInt(hex.substr(0, 2), 16) / 255, green = parseInt(hex.substr(2, 2), 16) / 255, blue = parseInt(hex.substr(4, 2), 16) / 255;
var cMax = Math.max(red, green, blue), delta = cMax - Math.min(red, green, blue), saturation = cMax ? delta / cMax : 0;
switch (cMax) {
case red:
return [60 * ((green - blue) / delta % 6) || 0, saturation, cMax];
case green:
return [60 * ((blue - red) / delta + 2) || 0, saturation, cMax];
case blue:
return [60 * ((red - green) / delta + 4) || 0, saturation, cMax];
}
}
function HSVtoHSL(hsv) {
var h = hsv[0], s2 = hsv[1] / 100, v = hsv[2] / 100, k = (2 - s2) * v;
return [
h,
Math.round(s2 * v / (k < 1 ? k : 2 - k) * 1e4) / 100,
k / 2 * 100
];
}
function stringToInteger(string) {
var total = 0;
for (var i = 0; i !== string.length; i++) {
if (total >= Number.MAX_SAFE_INTEGER)
break;
total += string.charCodeAt(i);
}
return total;
}
function getRealHueRange(colorHue) {
if (!isNaN(colorHue)) {
var number = parseInt(colorHue);
if (number < 360 && number > 0) {
return getColorInfo(colorHue).hueRange;
}
} else if (typeof colorHue === "string") {
if (colorDictionary[colorHue]) {
var color = colorDictionary[colorHue];
if (color.hueRange) {
return color.hueRange;
}
} else if (colorHue.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)) {
var hue = HexToHSB(colorHue)[0];
return getColorInfo(hue).hueRange;
}
}
return [0, 360];
}
return randomColor2;
});
})(randomColor$1, randomColor$1.exports);
var randomColor = randomColor$1.exports;
class Logger {
constructor(kind = "NetlessApp", debug = "error") {
__publicField(this, "kind");
__publicField(this, "debug");
__publicField(this, "color", randomColor({ luminosity: "dark" }));
this.kind = kind;
this.debug = debug;
}
log(...messages) {
if (this.debug === true || this.debug === "log") {
return this._log("log", messages);
}
}
warn(...messages) {
if (this.debug && this.debug !== "error") {
return this._log("warn", messages);
}
}
error(...messages) {
if (this.debug) {
return this._log("error", messages);
}
}
_log(type, messages) {
console[type](`%c[${this.kind}]:`, `color: ${this.color}; font-weight: bold;`, ...messages);
}
}
function isObj(e) {
return typeof e === "object" && e !== null;
}
var styles = ".netless-app-embedded-page{width:100%;height:100%;position:relative}.netless-app-embedded-page iframe{width:100%;height:100%;border:none;display:block}.netless-app-embedded-page-wb-view{width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}\n";
const ClickThroughAppliances = new Set(["clicker", "selector"]);

@@ -97,2 +445,3 @@ const EmbeddedPage = {

setup(context) {
var _a;
const displayer = context.getDisplayer();

@@ -102,153 +451,265 @@ const room = context.getRoom();

const view = context.getView();
const debug = (_a = context.getAppOptions()) == null ? void 0 : _a.debug;
const storeConfig = {
mainId: "state",
nsPrefix: "$scope-"
};
const stateNamespace = storeConfig.nsPrefix + storeConfig.mainId;
const attrs = ensureAttributes(context, {
src: "https://example.org",
state: {},
store: { [stateNamespace]: {} },
page: ""
});
const sideEffectManager = new s();
const logger = new Logger("EmbeddedPage", debug);
const toJSON = (o) => {
try {
return isObj(o) ? JSON.parse(JSON.stringify(o)) : o;
} catch (e) {
logger.error("Cannot parse to JSON object", o);
throw e;
}
};
const container = document.createElement("div");
Object.assign(container.style, { width: "100%", height: "100%", position: "relative" });
container.dataset.appKind = "EmbeddedPage";
container.classList.add("netless-app-embedded-page");
const iframe = document.createElement("iframe");
Object.assign(iframe.style, { width: "100%", height: "100%", border: "none" });
container.appendChild(iframe);
box.mountStyles(styles);
box.mountContent(container);
let toggleClickThrough = () => {
const transformRoomMembers = (array) => array.map(({ memberId, payload }) => ({
sessionUID: memberId,
uid: (room == null ? void 0 : room.uid) || (payload == null ? void 0 : payload.uid) || "",
userPayload: toJSON(payload)
}));
const safeListenPropsUpdated = (getProps, callback) => {
let disposeListenUpdated = null;
const disposeReaction = context.mobxUtils.reaction(getProps, () => {
if (disposeListenUpdated) {
disposeListenUpdated();
disposeListenUpdated = null;
}
const props = getProps();
disposeListenUpdated = () => context.objectUtils.unlistenUpdated(props, callback);
context.objectUtils.listenUpdated(props, callback);
}, { fireImmediately: true });
return () => {
disposeListenUpdated == null ? void 0 : disposeListenUpdated();
disposeReaction();
};
};
const shouldClickThrough = (tool) => {
return ClickThroughAppliances.has(tool);
const postMessage = (message) => {
var _a2;
logger.log("Message to SDK", message);
(_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage(message, "*");
};
if (view) {
const viewBox = document.createElement("div");
Object.assign(viewBox.style, {
width: "100%",
height: "100%",
position: "absolute",
top: 0,
left: 0
});
viewBox.classList.add("netless-app-embedded-page-wb-view");
container.appendChild(viewBox);
context.mountView(viewBox);
toggleClickThrough = (enable) => {
viewBox.style.pointerEvents = enable ? "none" : "auto";
};
toggleClickThrough(shouldClickThrough(room == null ? void 0 : room.state.memberState.currentApplianceName));
if (room) {
const toggleClickThrough = (tool) => {
viewBox.style.pointerEvents = !tool || ClickThroughAppliances.has(tool) ? "none" : "auto";
};
toggleClickThrough(room.state.memberState.currentApplianceName);
sideEffectManager.add(() => {
const onRoomStateChanged = (e) => {
if (e.memberState) {
toggleClickThrough(e.memberState.currentApplianceName);
}
};
displayer.callbacks.on("onRoomStateChanged", onRoomStateChanged);
return () => displayer.callbacks.off("onRoomStateChanged", onRoomStateChanged);
});
}
}
const postMessage = (payload) => {
var _a;
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(payload, "*");
const moveCamera = (config) => {
if (view && isObj(config)) {
view.moveCamera({
centerX: config.x,
centerY: config.y,
scale: config.scale,
animationMode: "immediately"
});
}
};
const event = `channel-${context.appId}`;
const magixListener = (e) => {
if (e.event === event && e.authorId !== displayer.observerId) {
postMessage({ type: "ReceiveMessage", payload: e.payload });
const setStore = (payload) => {
if (isObj(payload)) {
Object.keys(payload).forEach((namespace) => {
if (namespace !== stateNamespace) {
const state = payload[namespace];
context.updateAttributes(["store", namespace], state);
}
});
}
};
const setState = (payload) => {
if (isObj(payload) && payload.namespace && isObj(payload.state)) {
const { namespace, state } = payload;
if (!context.getIsWritable()) {
logger.error(`Cannot setState on store ${namespace} without writable access`, state);
return;
}
Object.keys(state).forEach((key) => {
context.updateAttributes(["store", namespace, key], state[key]);
});
}
};
sideEffectManager.add(() => {
displayer.addMagixEventListener(event, magixListener);
return () => displayer.removeMagixEventListener(event);
const storeSideEffect = new s();
const listenStateUpdated = (namespace) => {
storeSideEffect.add(() => safeListenPropsUpdated(() => attrs.store[namespace], (actions) => {
postMessage({
type: "StateChanged",
payload: { namespace, actions: toJSON(actions) }
});
}), namespace);
};
Object.keys(attrs.store).forEach(listenStateUpdated);
const disposer = safeListenPropsUpdated(() => attrs.store, (actions) => {
postMessage({ type: "StoreChanged", payload: toJSON(actions) });
if (attrs.store) {
actions.forEach(({ key, kind }) => {
switch (kind) {
case 2: {
storeSideEffect.flush(key);
break;
}
default: {
listenStateUpdated(key);
break;
}
}
});
}
});
return () => {
storeSideEffect.flushAll();
disposer();
};
});
if (room) {
sideEffectManager.add(() => {
const onRoomStateChanged = (e) => {
if (e.memberState) {
toggleClickThrough(shouldClickThrough(e.memberState.currentApplianceName));
sideEffectManager.add(() => {
const onRoomStateChanged = (e) => {
if (e == null ? void 0 : e.roomMembers) {
postMessage({
type: "RoomMembersChanged",
payload: transformRoomMembers(e.roomMembers)
});
}
};
displayer.callbacks.on("onRoomStateChanged", onRoomStateChanged);
return () => displayer.callbacks.off("onRoomStateChanged", onRoomStateChanged);
});
const setPage = (page) => {
if (!view) {
logger.warn("SetPage: page api is only available with 'scenePath' options enabled.");
} else {
const scenePath = context.getInitScenePath();
if (typeof page === "string" && context.getIsWritable() && scenePath && room) {
const fullScenePath = [scenePath, page].join("/");
if (room.scenePathType(fullScenePath) === "none") {
room.putScenes(scenePath, [{ name: page }]);
}
};
room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
return () => room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
});
}
sideEffectManager.addEventListener(iframe, "load", () => {
var _a;
context.setScenePath(fullScenePath);
context.updateAttributes(["page"], page);
}
}
};
sideEffectManager.add(() => {
const updateListener = (newValue, oldValue) => {
postMessage({ type: "PageChanged", payload: { oldValue, newValue } });
};
return context.mobxUtils.reaction(() => attrs.page, updateListener);
});
sideEffectManager.add(() => {
const updateListener = () => {
const isWritable = context.getIsWritable();
postMessage({
type: "WritableChanged",
payload: isWritable
});
logger.log(`WritableChange changed to ${isWritable}`);
};
context.emitter.on("writableChange", updateListener);
return () => context.emitter.off("writableChange", updateListener);
});
const magixEventChannel = `channel-${context.appId}`;
const sendMagixMessage = (message) => {
if (context.getIsWritable() && room) {
room.dispatchMagixEvent(magixEventChannel, message);
}
};
sideEffectManager.add(() => {
const magixListener = (e) => {
if (e.event === magixEventChannel && e.authorId !== displayer.observerId) {
postMessage({ type: "ReceiveMagixMessage", payload: e.payload });
}
};
displayer.addMagixEventListener(magixEventChannel, magixListener);
return () => displayer.removeMagixEventListener(magixEventChannel, magixListener);
});
const sendInitData = () => {
var _a2;
const memberId = displayer.observerId;
const userPayload = (_a = displayer.state.roomMembers.find((member) => member.memberId === memberId)) == null ? void 0 : _a.payload;
const userPayload = (_a2 = displayer.state.roomMembers.find((member) => member.memberId === memberId)) == null ? void 0 : _a2.payload;
postMessage({
type: "Init",
payload: {
state: attrs.state,
page: attrs.page,
writable: context.getIsWritable(),
roomMembers: transformRoomMembers(displayer.state.roomMembers),
debug,
store: toJSON(attrs.store),
storeConfig,
meta: {
sessionUID: memberId,
uid: (room == null ? void 0 : room.uid) || (userPayload == null ? void 0 : userPayload.uid) || "",
roomUUID: room == null ? void 0 : room.uuid,
userPayload: userPayload && JSON.parse(JSON.stringify(userPayload))
userPayload: toJSON(userPayload)
}
}
});
});
};
sideEffectManager.addEventListener(window, "message", (e) => {
if (e.source !== iframe.contentWindow)
return;
if (!isObj(e.data))
if (!isObj(e.data)) {
logger.error("window message data should be object, instead got", e.data);
return;
const { data } = e;
const type = data.type;
console.log("[EmbeddedPage] receive", data);
if (type === "GetState") {
postMessage({ type: "GetState", payload: attrs.state });
} else if (type === "SetState") {
if (isObj(data.payload) && context.getIsWritable()) {
for (const [key, value] of Object.entries(data.payload)) {
context.updateAttributes(["state", key], value);
}
}
const data = e.data;
logger.log("Message From SDK", data);
switch (data.type) {
case "Init": {
sendInitData();
break;
}
} else if (type === "GetPage") {
postMessage({ type: "GetPage", payload: attrs.page });
} else if (type === "SetPage") {
if (!view) {
console.warn("[EmbeddedPage] SetPage: page api is only available with 'scenePath'");
} else {
const value = data.payload;
const scenePath = context.getInitScenePath();
if (typeof value === "string" && context.getIsWritable() && scenePath && room) {
const fullScenePath = [scenePath, value].join("/");
if (room.scenePathType(fullScenePath) === "none") {
room.putScenes(scenePath, [{ name: value }]);
}
context.setScenePath(fullScenePath);
context.updateAttributes(["page"], value);
}
case "SetState": {
setState(data.payload);
break;
}
} else if (type === "GetWritable") {
postMessage({ type: "GetWritable", payload: context.getIsWritable() });
} else if (type === "SendMessage") {
if (context.getIsWritable()) {
room == null ? void 0 : room.dispatchMagixEvent(event, data.payload);
case "SetStore": {
setStore(data.payload);
break;
}
case "SetPage": {
setPage(data.payload);
break;
}
case "SendMagixMessage": {
sendMagixMessage(data.payload);
break;
}
case "MoveCamera": {
moveCamera(data.payload);
break;
}
}
});
sideEffectManager.add(() => {
let oldState = __spreadValues({}, attrs.state);
const updateListener = (updatedProperties) => {
const payload = {};
for (const { key, value } of updatedProperties) {
payload[key] = { oldValue: oldState[key], newValue: value };
}
oldState = __spreadValues({}, attrs.state);
postMessage({ type: "StateChanged", payload });
};
const listen = () => context.objectUtils.listenUpdated(attrs.state, updateListener);
return context.mobxUtils.reaction(() => attrs.state, listen, { fireImmediately: true });
});
sideEffectManager.add(() => {
const updateListener = (newValue, oldValue) => {
postMessage({ type: "PageChanged", payload: { oldValue, newValue } });
};
return context.mobxUtils.reaction(() => attrs.page, updateListener);
});
sideEffectManager.add(() => {
const updateListener = () => {
const writable = context.getIsWritable();
postMessage({
type: "WritableChanged",
payload: { oldValue: !writable, newValue: writable }
});
};
context.emitter.on("writableChange", updateListener);
return () => context.emitter.off("writableChange", updateListener);
});
iframe.src = attrs.src;
context.emitter.on("destroy", () => {
console.log("[EmbeddedPage]: destroy");
logger.log("destroy");
sideEffectManager.flushAll();
});
iframe.src = attrs.src;
}

@@ -255,0 +716,0 @@ };

@@ -1,2 +0,3 @@

(()=>{var G=Object.defineProperty;var P=Object.getOwnPropertySymbols;var L=Object.prototype.hasOwnProperty,W=Object.prototype.propertyIsEnumerable;var C=(d,l,p)=>l in d?G(d,l,{enumerable:!0,configurable:!0,writable:!0,value:p}):d[l]=p,I=(d,l)=>{for(var p in l||(l={}))L.call(l,p)&&C(d,p,l[p]);if(P)for(var p of P(l))W.call(l,p)&&C(d,p,l[p]);return d};var T=function(d){"use strict";class l{constructor(){this.disposers=new Map,this.disposerIDGenCount=-1}add(a,e=this.genDisposerID()){return this.flush(e),this.disposers.set(e,a()),e}addEventListener(a,e,n,c,i=this.genDisposerID()){return this.add(()=>(a.addEventListener(e,n,c),()=>a.removeEventListener(e,n,c)),i),i}setTimeout(a,e,n=this.genDisposerID()){return this.add(()=>{const c=window.setTimeout(()=>{this.remove(n),a()},e);return()=>window.clearTimeout(c)},n)}setInterval(a,e,n=this.genDisposerID()){return this.add(()=>{const c=window.setInterval(a,e);return()=>window.clearInterval(c)},n)}remove(a){const e=this.disposers.get(a);return this.disposers.delete(a),e}flush(a){const e=this.remove(a);if(e)try{e()}catch(n){console.error(n)}}flushAll(){this.disposers.forEach(a=>{try{a()}catch(e){console.error(e)}}),this.disposers.clear()}genDisposerID(){const{MAX_SAFE_INTEGER:a=9007199254740991}=Number;return this.disposerIDGenCount=(this.disposerIDGenCount+1)%a,`disposer-${this.disposerIDGenCount}`}}function p(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function D(t,a){let e=t.getAttributes();if(e||(t.setAttributes(a),e=t.getAttributes()),!e)throw new Error("[NetlessAppMonaco] No attributes");return p(a)&&Object.keys(a).forEach(n=>{Object.prototype.hasOwnProperty.call(e,n)||t.updateAttributes([n],a[n])}),e}function E(t){return typeof t=="object"&&t!==null}const A=new Set(["clicker","selector"]),M={kind:"EmbeddedPage",setup(t){const a=t.getDisplayer(),e=t.getRoom(),n=t.getBox(),c=t.getView(),i=D(t,{src:"https://example.org",state:{},page:""}),g=new l,y=document.createElement("div");Object.assign(y.style,{width:"100%",height:"100%",position:"relative"});const f=document.createElement("iframe");Object.assign(f.style,{width:"100%",height:"100%",border:"none"}),y.appendChild(f),n.mountContent(y);let v=()=>{};const S=s=>A.has(s);if(c){const s=document.createElement("div");Object.assign(s.style,{width:"100%",height:"100%",position:"absolute",top:0,left:0}),y.appendChild(s),t.mountView(s),v=r=>{s.style.pointerEvents=r?"none":"auto"},v(S(e==null?void 0:e.state.memberState.currentApplianceName))}const h=s=>{var r;(r=f.contentWindow)==null||r.postMessage(s,"*")},w=`channel-${t.appId}`,j=s=>{s.event===w&&s.authorId!==a.observerId&&h({type:"ReceiveMessage",payload:s.payload})};g.add(()=>(a.addMagixEventListener(w,j),()=>a.removeMagixEventListener(w))),e&&g.add(()=>{const s=r=>{r.memberState&&v(S(r.memberState.currentApplianceName))};return e.callbacks.on("onRoomStateChanged",s),()=>e.callbacks.off("onRoomStateChanged",s)}),g.addEventListener(f,"load",()=>{var o;const s=a.observerId,r=(o=a.state.roomMembers.find(u=>u.memberId===s))==null?void 0:o.payload;h({type:"Init",payload:{state:i.state,page:i.page,writable:t.getIsWritable(),meta:{roomUUID:e==null?void 0:e.uuid,userPayload:r&&JSON.parse(JSON.stringify(r))}}})}),g.addEventListener(window,"message",s=>{if(s.source!==f.contentWindow||!E(s.data))return;const{data:r}=s,o=r.type;if(console.log("[EmbeddedPage] receive",r),o==="GetState")h({type:"GetState",payload:i.state});else if(o==="SetState"){if(E(r.payload)&&t.getIsWritable())for(const[u,b]of Object.entries(r.payload))t.updateAttributes(["state",u],b)}else if(o==="GetPage")h({type:"GetPage",payload:i.page});else if(o==="SetPage")if(!c)console.warn("[EmbeddedPage] SetPage: page api is only available with 'scenePath'");else{const u=r.payload,b=t.getInitScenePath();if(typeof u=="string"&&t.getIsWritable()&&b&&e){const m=[b,u].join("/");e.scenePathType(m)==="none"&&e.putScenes(b,[{name:u}]),t.setScenePath(m),t.updateAttributes(["page"],u)}}else o==="GetWritable"?h({type:"GetWritable",payload:t.getIsWritable()}):o==="SendMessage"&&t.getIsWritable()&&(e==null||e.dispatchMagixEvent(w,r.payload))}),g.add(()=>{let s=I({},i.state);const r=u=>{const b={};for(const{key:m,value:O}of u)b[m]={oldValue:s[m],newValue:O};s=I({},i.state),h({type:"StateChanged",payload:b})},o=()=>t.objectUtils.listenUpdated(i.state,r);return t.mobxUtils.reaction(()=>i.state,o,{fireImmediately:!0})}),g.add(()=>{const s=(r,o)=>{h({type:"PageChanged",payload:{oldValue:o,newValue:r}})};return t.mobxUtils.reaction(()=>i.page,s)}),g.add(()=>{const s=()=>{const r=t.getIsWritable();h({type:"WritableChanged",payload:{oldValue:!r,newValue:r}})};return t.emitter.on("writableChange",s),()=>t.emitter.off("writableChange",s)}),f.src=i.src,t.emitter.on("destroy",()=>{console.log("[EmbeddedPage]: destroy"),g.flushAll()})}};return d.default=M,Object.defineProperty(d,"__esModule",{value:!0}),d[Symbol.toStringTag]="Module",d}({});})();
(()=>{var Y=Object.defineProperty;var z=(g,b,k)=>b in g?Y(g,b,{enumerable:!0,configurable:!0,writable:!0,value:k}):g[b]=k;var U=(g,b,k)=>(z(g,typeof b!="symbol"?b+"":b,k),k);var Z=function(g){"use strict";class b{constructor(){this.disposers=new Map,this.disposerIDGenCount=-1}add(i,s=this.genDisposerID()){return this.flush(s),this.disposers.set(s,i()),s}addEventListener(i,s,l,c,S=this.genDisposerID()){return this.add(()=>(i.addEventListener(s,l,c),()=>i.removeEventListener(s,l,c)),S),S}setTimeout(i,s,l=this.genDisposerID()){return this.add(()=>{const c=window.setTimeout(()=>{this.remove(l),i()},s);return()=>window.clearTimeout(c)},l)}setInterval(i,s,l=this.genDisposerID()){return this.add(()=>{const c=window.setInterval(i,s);return()=>window.clearInterval(c)},l)}remove(i){const s=this.disposers.get(i);return this.disposers.delete(i),s}flush(i){const s=this.remove(i);if(s)try{s()}catch(l){console.error(l)}}flushAll(){this.disposers.forEach(i=>{try{i()}catch(s){console.error(s)}}),this.disposers.clear()}genDisposerID(){const{MAX_SAFE_INTEGER:i=9007199254740991}=Number;return this.disposerIDGenCount=(this.disposerIDGenCount+1)%i,`disposer-${this.disposerIDGenCount}`}}function k(o){return o!=null&&typeof o=="object"&&!Array.isArray(o)}function G(o,i){let s=o.getAttributes();if(s||(o.setAttributes(i),s=o.getAttributes()),!s)throw new Error("[NetlessAppMonaco] No attributes");return k(i)&&Object.keys(i).forEach(l=>{Object.prototype.hasOwnProperty.call(s,l)||o.updateAttributes([l],i[l])}),s}var B=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},W={exports:{}};(function(o,i){(function(s,l){{var c=l();o&&o.exports&&(i=o.exports=c),i.randomColor=c}})(B,function(){var s=null,l={};_();var c=[],S=function(r){if(r=r||{},r.seed!==void 0&&r.seed!==null&&r.seed===parseInt(r.seed,10))s=r.seed;else if(typeof r.seed=="string")s=P(r.seed);else{if(r.seed!==void 0&&r.seed!==null)throw new TypeError("The seed value must be an integer or string");s=null}var n,e,t;if(r.count!==null&&r.count!==void 0){for(var a=r.count,d=[],u=0;u<r.count;u++)c.push(!1);for(r.count=null;a>d.length;){var y=S(r);s!==null&&(r.seed=s),d.push(y)}return r.count=a,d}return n=T(r),e=j(n,r),t=h(n,e,r),m([n,e,t],r)};function T(r){if(c.length>0){var n=F(r.hue),e=w(n),t=(n[1]-n[0])/c.length,a=parseInt((e-n[0])/t);c[a]===!0?a=(a+2)%c.length:c[a]=!0;var d=(n[0]+a*t)%359,u=(n[0]+(a+1)*t)%359;return n=[d,u],e=w(n),e<0&&(e=360+e),e}else{var n=I(r.hue);return e=w(n),e<0&&(e=360+e),e}}function j(r,n){if(n.hue==="monochrome")return 0;if(n.luminosity==="random")return w([0,100]);var e=C(r),t=e[0],a=e[1];switch(n.luminosity){case"bright":t=55;break;case"dark":t=a-10;break;case"light":a=55;break}return w([t,a])}function h(r,n,e){var t=p(r,n),a=100;switch(e.luminosity){case"dark":a=t+20;break;case"light":t=(a+t)/2;break;case"random":t=0,a=100;break}return w([t,a])}function m(r,n){switch(n.format){case"hsvArray":return r;case"hslArray":return O(r);case"hsl":var e=O(r);return"hsl("+e[0]+", "+e[1]+"%, "+e[2]+"%)";case"hsla":var t=O(r),a=n.alpha||Math.random();return"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+a+")";case"rgbArray":return D(r);case"rgb":var d=D(r);return"rgb("+d.join(", ")+")";case"rgba":var u=D(r),a=n.alpha||Math.random();return"rgba("+u.join(", ")+", "+a+")";default:return L(r)}}function p(r,n){for(var e=v(r).lowerBounds,t=0;t<e.length-1;t++){var a=e[t][0],d=e[t][1],u=e[t+1][0],y=e[t+1][1];if(n>=a&&n<=u){var N=(y-d)/(u-a),M=d-N*a;return N*n+M}}return 0}function I(r){if(typeof parseInt(r)=="number"){var n=parseInt(r);if(n<360&&n>0)return[n,n]}if(typeof r=="string"){if(l[r]){var e=l[r];if(e.hueRange)return e.hueRange}else if(r.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)){var t=$(r)[0];return[t,t]}}return[0,360]}function C(r){return v(r).saturationRange}function v(r){r>=334&&r<=360&&(r-=360);for(var n in l){var e=l[n];if(e.hueRange&&r>=e.hueRange[0]&&r<=e.hueRange[1])return l[n]}return"Color not found"}function w(r){if(s===null){var n=.618033988749895,e=Math.random();return e+=n,e%=1,Math.floor(r[0]+e*(r[1]+1-r[0]))}else{var t=r[1]||1,a=r[0]||0;s=(s*9301+49297)%233280;var d=s/233280;return Math.floor(a+d*(t-a))}}function L(r){var n=D(r);function e(a){var d=a.toString(16);return d.length==1?"0"+d:d}var t="#"+e(n[0])+e(n[1])+e(n[2]);return t}function f(r,n,e){var t=e[0][0],a=e[e.length-1][0],d=e[e.length-1][1],u=e[0][1];l[r]={hueRange:n,lowerBounds:e,saturationRange:[t,a],brightnessRange:[d,u]}}function _(){f("monochrome",null,[[0,0],[100,0]]),f("red",[-26,18],[[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]),f("orange",[18,46],[[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]),f("yellow",[46,62],[[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]),f("green",[62,178],[[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]),f("blue",[178,257],[[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]),f("purple",[257,282],[[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]),f("pink",[282,334],[[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]])}function D(r){var n=r[0];n===0&&(n=1),n===360&&(n=359),n=n/360;var e=r[1]/100,t=r[2]/100,a=Math.floor(n*6),d=n*6-a,u=t*(1-e),y=t*(1-d*e),N=t*(1-(1-d)*e),M=256,E=256,A=256;switch(a){case 0:M=t,E=N,A=u;break;case 1:M=y,E=t,A=u;break;case 2:M=u,E=t,A=N;break;case 3:M=u,E=y,A=t;break;case 4:M=N,E=u,A=t;break;case 5:M=t,E=u,A=y;break}var q=[Math.floor(M*255),Math.floor(E*255),Math.floor(A*255)];return q}function $(r){r=r.replace(/^#/,""),r=r.length===3?r.replace(/(.)/g,"$1$1"):r;var n=parseInt(r.substr(0,2),16)/255,e=parseInt(r.substr(2,2),16)/255,t=parseInt(r.substr(4,2),16)/255,a=Math.max(n,e,t),d=a-Math.min(n,e,t),u=a?d/a:0;switch(a){case n:return[60*((e-t)/d%6)||0,u,a];case e:return[60*((t-n)/d+2)||0,u,a];case t:return[60*((n-e)/d+4)||0,u,a]}}function O(r){var n=r[0],e=r[1]/100,t=r[2]/100,a=(2-e)*t;return[n,Math.round(e*t/(a<1?a:2-a)*1e4)/100,a/2*100]}function P(r){for(var n=0,e=0;e!==r.length&&!(n>=Number.MAX_SAFE_INTEGER);e++)n+=r.charCodeAt(e);return n}function F(r){if(isNaN(r)){if(typeof r=="string"){if(l[r]){var e=l[r];if(e.hueRange)return e.hueRange}else if(r.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)){var t=$(r)[0];return v(t).hueRange}}}else{var n=parseInt(r);if(n<360&&n>0)return v(r).hueRange}return[0,360]}return S})})(W,W.exports);var H=W.exports;class V{constructor(i="NetlessApp",s="error"){U(this,"kind");U(this,"debug");U(this,"color",H({luminosity:"dark"}));this.kind=i,this.debug=s}log(...i){if(this.debug===!0||this.debug==="log")return this._log("log",i)}warn(...i){if(this.debug&&this.debug!=="error")return this._log("warn",i)}error(...i){if(this.debug)return this._log("error",i)}_log(i,s){console[i](`%c[${this.kind}]:`,`color: ${this.color}; font-weight: bold;`,...s)}}function R(o){return typeof o=="object"&&o!==null}var J=`.netless-app-embedded-page{width:100%;height:100%;position:relative}.netless-app-embedded-page iframe{width:100%;height:100%;border:none;display:block}.netless-app-embedded-page-wb-view{width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}
`;const K=new Set(["clicker","selector"]),X={kind:"EmbeddedPage",setup(o){var n;const i=o.getDisplayer(),s=o.getRoom(),l=o.getBox(),c=o.getView(),S=(n=o.getAppOptions())==null?void 0:n.debug,T={mainId:"state",nsPrefix:"$scope-"},j=T.nsPrefix+T.mainId,h=G(o,{src:"https://example.org",store:{[j]:{}},page:""}),m=new b,p=new V("EmbeddedPage",S),I=e=>{try{return R(e)?JSON.parse(JSON.stringify(e)):e}catch(t){throw p.error("Cannot parse to JSON object",e),t}},C=document.createElement("div");C.dataset.appKind="EmbeddedPage",C.classList.add("netless-app-embedded-page");const v=document.createElement("iframe");C.appendChild(v),l.mountStyles(J),l.mountContent(C);const w=e=>e.map(({memberId:t,payload:a})=>({sessionUID:t,uid:(s==null?void 0:s.uid)||(a==null?void 0:a.uid)||"",userPayload:I(a)})),L=(e,t)=>{let a=null;const d=o.mobxUtils.reaction(e,()=>{a&&(a(),a=null);const u=e();a=()=>o.objectUtils.unlistenUpdated(u,t),o.objectUtils.listenUpdated(u,t)},{fireImmediately:!0});return()=>{a==null||a(),d()}},f=e=>{var t;p.log("Message to SDK",e),(t=v.contentWindow)==null||t.postMessage(e,"*")};if(c){const e=document.createElement("div");if(e.classList.add("netless-app-embedded-page-wb-view"),C.appendChild(e),o.mountView(e),s){const t=a=>{e.style.pointerEvents=!a||K.has(a)?"none":"auto"};t(s.state.memberState.currentApplianceName),m.add(()=>{const a=d=>{d.memberState&&t(d.memberState.currentApplianceName)};return i.callbacks.on("onRoomStateChanged",a),()=>i.callbacks.off("onRoomStateChanged",a)})}}const _=e=>{c&&R(e)&&c.moveCamera({centerX:e.x,centerY:e.y,scale:e.scale,animationMode:"immediately"})},D=e=>{R(e)&&Object.keys(e).forEach(t=>{if(t!==j){const a=e[t];o.updateAttributes(["store",t],a)}})},$=e=>{if(R(e)&&e.namespace&&R(e.state)){const{namespace:t,state:a}=e;if(!o.getIsWritable()){p.error(`Cannot setState on store ${t} without writable access`,a);return}Object.keys(a).forEach(d=>{o.updateAttributes(["store",t,d],a[d])})}};m.add(()=>{const e=new b,t=d=>{e.add(()=>L(()=>h.store[d],u=>{f({type:"StateChanged",payload:{namespace:d,actions:I(u)}})}),d)};Object.keys(h.store).forEach(t);const a=L(()=>h.store,d=>{f({type:"StoreChanged",payload:I(d)}),h.store&&d.forEach(({key:u,kind:y})=>{switch(y){case 2:{e.flush(u);break}default:{t(u);break}}})});return()=>{e.flushAll(),a()}}),m.add(()=>{const e=t=>{(t==null?void 0:t.roomMembers)&&f({type:"RoomMembersChanged",payload:w(t.roomMembers)})};return i.callbacks.on("onRoomStateChanged",e),()=>i.callbacks.off("onRoomStateChanged",e)});const O=e=>{if(!c)p.warn("SetPage: page api is only available with 'scenePath' options enabled.");else{const t=o.getInitScenePath();if(typeof e=="string"&&o.getIsWritable()&&t&&s){const a=[t,e].join("/");s.scenePathType(a)==="none"&&s.putScenes(t,[{name:e}]),o.setScenePath(a),o.updateAttributes(["page"],e)}}};m.add(()=>{const e=(t,a)=>{f({type:"PageChanged",payload:{oldValue:a,newValue:t}})};return o.mobxUtils.reaction(()=>h.page,e)}),m.add(()=>{const e=()=>{const t=o.getIsWritable();f({type:"WritableChanged",payload:t}),p.log(`WritableChange changed to ${t}`)};return o.emitter.on("writableChange",e),()=>o.emitter.off("writableChange",e)});const P=`channel-${o.appId}`,F=e=>{o.getIsWritable()&&s&&s.dispatchMagixEvent(P,e)};m.add(()=>{const e=t=>{t.event===P&&t.authorId!==i.observerId&&f({type:"ReceiveMagixMessage",payload:t.payload})};return i.addMagixEventListener(P,e),()=>i.removeMagixEventListener(P,e)});const r=()=>{var a;const e=i.observerId,t=(a=i.state.roomMembers.find(d=>d.memberId===e))==null?void 0:a.payload;f({type:"Init",payload:{page:h.page,writable:o.getIsWritable(),roomMembers:w(i.state.roomMembers),debug:S,store:I(h.store),storeConfig:T,meta:{sessionUID:e,uid:(s==null?void 0:s.uid)||(t==null?void 0:t.uid)||"",roomUUID:s==null?void 0:s.uuid,userPayload:I(t)}}})};m.addEventListener(window,"message",e=>{if(e.source!==v.contentWindow)return;if(!R(e.data)){p.error("window message data should be object, instead got",e.data);return}const t=e.data;switch(p.log("Message From SDK",t),t.type){case"Init":{r();break}case"SetState":{$(t.payload);break}case"SetStore":{D(t.payload);break}case"SetPage":{O(t.payload);break}case"SendMagixMessage":{F(t.payload);break}case"MoveCamera":{_(t.payload);break}}}),o.emitter.on("destroy",()=>{p.log("destroy"),m.flushAll()}),v.src=h.src}};return g.default=X,Object.defineProperty(g,"__esModule",{value:!0}),g[Symbol.toStringTag]="Module",g}({});})();
//# sourceMappingURL=main.iife.js.map

@@ -1,10 +0,55 @@

export declare type State = Record<string, unknown>;
export interface ReceiveMessages {
GetState: void;
SetState: State;
SendMessage: unknown;
GetPage: void;
import type { AkkoObjectUpdatedProperty } from "white-web-sdk";
declare type TransformMessage<TKey extends keyof Messages, Messages> = TKey extends keyof Messages ? Messages[TKey] extends void ? {
type: TKey;
payload?: Messages[TKey];
} : {
type: TKey;
payload: Messages[TKey];
} : never;
export declare type DefaultState = Record<string, unknown>;
export interface CameraState {
x: number;
y: number;
scale: number;
}
export interface RoomMember {
sessionUID: number;
uid: string;
userPayload: unknown;
}
export interface ToSDKMessagePayloads<TState = DefaultState, TMagix = unknown> {
Init: InitData<TState>;
StateChanged: {
namespace: string;
actions: ReadonlyArray<AkkoObjectUpdatedProperty<TState, Extract<keyof TState, string>>>;
};
StoreChanged: ReadonlyArray<AkkoObjectUpdatedProperty<{
[K: string]: TState;
}>>;
PageChanged: DiffOne<string>;
ReceiveMagixMessage: TMagix;
WritableChanged: boolean;
RoomMembersChanged: ReadonlyArray<RoomMember>;
}
export declare type ToSDKMessageKey = keyof ToSDKMessagePayloads;
export declare type ToSDKMessage<TKey extends ToSDKMessageKey = ToSDKMessageKey, TState = DefaultState, TMagix = unknown> = TransformMessage<TKey, ToSDKMessagePayloads<TState, TMagix>>;
export interface FromSDKMessagePayloads<TState = DefaultState, TMagix = unknown> {
Init: void;
SetState: {
namespace: string;
state: Partial<TState>;
};
GetState: {
namespace: string;
ensureState: TState;
};
SetStore: {
[namespace: string]: unknown;
};
SetPage: string;
GetWritable: void;
SendMagixMessage: TMagix;
MoveCamera: Partial<CameraState>;
}
export declare type FromSDKMessageKey = keyof FromSDKMessagePayloads;
export declare type FromSDKMessage<TKey extends FromSDKMessageKey = FromSDKMessageKey, TState = DefaultState, TMagix = unknown> = TransformMessage<TKey, FromSDKMessagePayloads<TState, TMagix>>;
export declare type DiffOne<T> = {

@@ -14,21 +59,25 @@ oldValue?: T;

};
export declare type Diff<T> = {
[K in keyof T]?: DiffOne<T[K]>;
};
export interface MetaData {
roomUUID?: string;
userPayload?: unknown;
readonly sessionUID: number;
readonly uid: string;
readonly roomUUID?: string;
readonly userPayload: unknown;
}
export interface InitData {
state: State;
export interface InitData<TState = DefaultState> {
page?: string;
writable: boolean;
meta: MetaData;
roomMembers: ReadonlyArray<RoomMember>;
debug?: boolean;
store: {
[k: string]: TState;
};
storeConfig: {
mainId: string;
nsPrefix: string;
};
}
export interface SendMessages {
Init: InitData;
GetState: State;
StateChanged: Record<string, DiffOne<unknown>>;
ReceiveMessage: unknown;
GetPage: string | undefined;
PageChanged: DiffOne<string>;
GetWritable: boolean;
WritableChanged: DiffOne<boolean>;
}
export {};
{
"name": "@netless/app-embedded-page",
"version": "0.0.3",
"version": "0.0.4",
"main": "dist/main.cjs.js",

@@ -5,0 +5,0 @@ "module": "dist/main.es.js",

import type { PlaygroundConfigs } from "../playground/typings";
import type { Attributes } from "./src";
const demo: { title: string; src: string }[] = [
{
title: "Scratch",
src: "http://192.168.31.195:8601/",
// scenePath: `/embedded-page/${title}`,
},
];
const options: PlaygroundConfigs<Attributes> = [

@@ -16,4 +24,14 @@ {

},
...demo.map(({ title, src }) => ({
kind: "EmbeddedPage",
src: () => import("./src"),
options: {
title,
},
attributes: {
src,
},
})),
];
export default options;

@@ -1,6 +0,5 @@

import { ensureAttributes } from "@netless/app-shared";
import type { NetlessApp } from "@netless/window-manager";
import { SideEffectManager } from "side-effect-manager";
import type {
AkkoObjectUpdatedListener,
AnimationMode,
ApplianceNames,

@@ -10,12 +9,29 @@ Event,

ScenePathType,
RoomMember as PlainRoomMember,
} from "white-web-sdk";
import type { ReceiveMessages, SendMessages, State } from "./types";
import { ensureAttributes, Logger } from "@netless/app-shared";
import { SideEffectManager } from "side-effect-manager";
import type {
FromSDKMessage,
RoomMember,
ToSDKMessageKey,
ToSDKMessage,
DefaultState,
CameraState,
} from "./types";
import { isObj } from "./utils";
import styles from "./style.scss?inline";
export type { DiffOne, InitData, MetaData, ReceiveMessages, SendMessages, State } from "./types";
export * from "./types";
export interface Attributes {
export type Attributes = {
src: string;
state: State;
store: Record<string, unknown>;
page: string;
};
export interface AppOptions {
debug?: boolean;
}

@@ -25,5 +41,9 @@

const EmbeddedPage: NetlessApp<Attributes> = {
const EmbeddedPage: NetlessApp<Attributes, void, AppOptions> = {
kind: "EmbeddedPage",
setup(context) {
if (import.meta.env.DEV) {
(window as any).EmbeddedPageContext = context;
}
const displayer = context.getDisplayer();

@@ -33,6 +53,12 @@ const room = context.getRoom();

const view = context.getView();
const debug = context.getAppOptions()?.debug;
const storeConfig = {
mainId: "state",
nsPrefix: "$scope-",
};
const stateNamespace = storeConfig.nsPrefix + storeConfig.mainId;
const attrs = ensureAttributes<Attributes>(context, {
src: "https://example.org",
state: {},
store: { [stateNamespace]: {} },
page: "",

@@ -42,148 +68,216 @@ });

const sideEffectManager = new SideEffectManager();
const logger = new Logger("EmbeddedPage", debug);
const toJSON = <T = unknown>(o: unknown): T => {
try {
return isObj(o) ? JSON.parse(JSON.stringify(o)) : o;
} catch (e) {
logger.error("Cannot parse to JSON object", o);
throw e;
}
};
const container = document.createElement("div");
Object.assign(container.style, { width: "100%", height: "100%", position: "relative" });
container.dataset.appKind = "EmbeddedPage";
container.classList.add("netless-app-embedded-page");
const iframe = document.createElement("iframe");
Object.assign(iframe.style, { width: "100%", height: "100%", border: "none" });
container.appendChild(iframe);
box.mountStyles(styles);
box.mountContent(container);
// eslint-disable-next-line @typescript-eslint/no-empty-function
let toggleClickThrough: (enable?: boolean) => void = () => {};
const shouldClickThrough = (tool?: ApplianceNames) => {
return ClickThroughAppliances.has(tool as ApplianceNames);
const transformRoomMembers = (
array: ReadonlyArray<PlainRoomMember>
): ReadonlyArray<RoomMember> =>
array.map(({ memberId, payload }) => ({
sessionUID: memberId,
uid: room?.uid || payload?.uid || "",
userPayload: toJSON(payload),
}));
const safeListenPropsUpdated = <T>(
getProps: () => T,
callback: AkkoObjectUpdatedListener<T>
) => {
let disposeListenUpdated: (() => void) | null = null;
const disposeReaction = context.mobxUtils.reaction(
getProps,
() => {
if (disposeListenUpdated) {
disposeListenUpdated();
disposeListenUpdated = null;
}
const props = getProps();
disposeListenUpdated = () => context.objectUtils.unlistenUpdated(props, callback);
context.objectUtils.listenUpdated(props, callback);
},
{ fireImmediately: true }
);
return () => {
disposeListenUpdated?.();
disposeReaction();
};
};
const postMessage = <T extends ToSDKMessageKey>(message: ToSDKMessage<T>) => {
logger.log("Message to SDK", message);
iframe.contentWindow?.postMessage(message, "*");
};
/* --------------------------------------------- *\
# Whiteboard panel
\* --------------------------------------------- */
if (view) {
// cover a whiteboard panel on top of the iframe
const viewBox = document.createElement("div");
Object.assign(viewBox.style, {
width: "100%",
height: "100%",
position: "absolute",
top: 0,
left: 0,
});
viewBox.classList.add("netless-app-embedded-page-wb-view");
container.appendChild(viewBox);
context.mountView(viewBox);
toggleClickThrough = (enable?: boolean) => {
viewBox.style.pointerEvents = enable ? "none" : "auto";
};
if (room) {
const toggleClickThrough = (tool?: ApplianceNames) => {
viewBox.style.pointerEvents = !tool || ClickThroughAppliances.has(tool) ? "none" : "auto";
};
toggleClickThrough(shouldClickThrough(room?.state.memberState.currentApplianceName));
toggleClickThrough(room.state.memberState.currentApplianceName);
sideEffectManager.add(() => {
const onRoomStateChanged = (e: Partial<RoomState>) => {
if (e.memberState) {
toggleClickThrough(e.memberState.currentApplianceName);
}
};
displayer.callbacks.on("onRoomStateChanged", onRoomStateChanged);
return () => displayer.callbacks.off("onRoomStateChanged", onRoomStateChanged);
});
}
}
const postMessage = <T extends keyof SendMessages>(payload: {
type: T;
payload: SendMessages[T];
}) => {
iframe.contentWindow?.postMessage(payload, "*");
const moveCamera = (config?: Partial<CameraState>): void => {
if (view && isObj(config)) {
view.moveCamera({
centerX: config.x,
centerY: config.y,
scale: config.scale,
animationMode: "immediately" as AnimationMode.Immediately,
});
}
};
const event = `channel-${context.appId}`;
/* --------------------------------------------- *\
# App store
\* --------------------------------------------- */
const magixListener = (e: Event) => {
if (e.event === event && e.authorId !== displayer.observerId) {
postMessage({ type: "ReceiveMessage", payload: e.payload });
const setStore = (payload: unknown): void => {
if (isObj(payload)) {
Object.keys(payload).forEach(namespace => {
if (namespace !== stateNamespace) {
const state = payload[namespace];
context.updateAttributes(["store", namespace], state);
}
});
}
};
const setState = (payload: unknown): void => {
if (isObj(payload) && payload.namespace && isObj(payload.state)) {
const { namespace, state } = payload as FromSDKMessage<"SetState", DefaultState>["payload"];
if (!context.getIsWritable()) {
logger.error(`Cannot setState on store ${namespace} without writable access`, state);
return;
}
Object.keys(state).forEach(key => {
context.updateAttributes(["store", namespace, key], state[key]);
});
}
};
sideEffectManager.add(() => {
displayer.addMagixEventListener(event, magixListener);
return () => displayer.removeMagixEventListener(event);
});
const storeSideEffect = new SideEffectManager();
if (room) {
sideEffectManager.add(() => {
const onRoomStateChanged = (e: Partial<RoomState>) => {
if (e.memberState) {
toggleClickThrough(shouldClickThrough(e.memberState.currentApplianceName));
}
};
room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
return () => room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
});
}
const listenStateUpdated = (namespace: string): void => {
storeSideEffect.add(
() =>
safeListenPropsUpdated(
() => attrs.store[namespace],
actions => {
postMessage({
type: "StateChanged",
payload: { namespace, actions: toJSON(actions) },
});
}
),
namespace
);
};
sideEffectManager.addEventListener(iframe, "load", () => {
const memberId = displayer.observerId;
const userPayload = displayer.state.roomMembers.find(
member => member.memberId === memberId
)?.payload;
Object.keys(attrs.store).forEach(listenStateUpdated);
postMessage({
type: "Init",
payload: {
state: attrs.state,
page: attrs.page,
writable: context.getIsWritable(),
meta: {
roomUUID: room?.uuid,
userPayload: userPayload && JSON.parse(JSON.stringify(userPayload)),
},
},
});
});
const disposer = safeListenPropsUpdated(
() => attrs.store,
actions => {
postMessage({ type: "StoreChanged", payload: toJSON(actions) });
sideEffectManager.addEventListener(window, "message", e => {
if (e.source !== iframe.contentWindow) return;
if (!isObj(e.data)) return;
const { data } = e;
const type = data.type as keyof ReceiveMessages;
console.log("[EmbeddedPage] receive", data);
if (type === "GetState") {
postMessage({ type: "GetState", payload: attrs.state });
} else if (type === "SetState") {
if (isObj(data.payload) && context.getIsWritable()) {
for (const [key, value] of Object.entries(data.payload)) {
context.updateAttributes(["state", key], value);
if (attrs.store) {
actions.forEach(({ key, kind }) => {
switch (kind) {
case 2: {
storeSideEffect.flush(key);
break;
}
default: {
listenStateUpdated(key);
break;
}
}
});
}
}
} else if (type === "GetPage") {
postMessage({ type: "GetPage", payload: attrs.page });
} else if (type === "SetPage") {
if (!view) {
console.warn("[EmbeddedPage] SetPage: page api is only available with 'scenePath'");
} else {
const value = data.payload as ReceiveMessages["SetPage"];
const scenePath = context.getInitScenePath();
if (typeof value === "string" && context.getIsWritable() && scenePath && room) {
const fullScenePath = [scenePath, value].join("/");
if (room.scenePathType(fullScenePath) === ("none" as ScenePathType)) {
room.putScenes(scenePath, [{ name: value }]);
}
context.setScenePath(fullScenePath);
context.updateAttributes(["page"], value);
}
}
} else if (type === "GetWritable") {
postMessage({ type: "GetWritable", payload: context.getIsWritable() });
} else if (type === "SendMessage") {
if (context.getIsWritable()) {
room?.dispatchMagixEvent(event, data.payload);
}
}
);
return () => {
storeSideEffect.flushAll();
disposer();
};
});
/* --------------------------------------------- *\
# Room Members State
\* --------------------------------------------- */
sideEffectManager.add(() => {
let oldState = { ...attrs.state };
const updateListener: AkkoObjectUpdatedListener<State> = updatedProperties => {
const payload: SendMessages["StateChanged"] = {};
for (const { key, value } of updatedProperties) {
payload[key] = { oldValue: oldState[key], newValue: value };
const onRoomStateChanged = (e: Partial<RoomState>) => {
if (e?.roomMembers) {
postMessage({
type: "RoomMembersChanged",
payload: transformRoomMembers(e.roomMembers),
});
}
oldState = { ...attrs.state };
postMessage({ type: "StateChanged", payload });
};
displayer.callbacks.on("onRoomStateChanged", onRoomStateChanged);
return () => displayer.callbacks.off("onRoomStateChanged", onRoomStateChanged);
});
const listen = () => context.objectUtils.listenUpdated(attrs.state, updateListener);
/* --------------------------------------------- *\
# Page State
\* --------------------------------------------- */
return context.mobxUtils.reaction(() => attrs.state, listen, { fireImmediately: true });
});
const setPage = (page: unknown): void => {
if (!view) {
logger.warn("SetPage: page api is only available with 'scenePath' options enabled.");
} else {
const scenePath = context.getInitScenePath();
if (typeof page === "string" && context.getIsWritable() && scenePath && room) {
const fullScenePath = [scenePath, page].join("/");
if (room.scenePathType(fullScenePath) === ("none" as ScenePathType.None)) {
room.putScenes(scenePath, [{ name: page }]);
}
context.setScenePath(fullScenePath);
context.updateAttributes(["page"], page);
}
}
};

@@ -197,9 +291,14 @@ sideEffectManager.add(() => {

/* --------------------------------------------- *\
# Writable State
\* --------------------------------------------- */
sideEffectManager.add(() => {
const updateListener = () => {
const writable = context.getIsWritable();
const isWritable = context.getIsWritable();
postMessage({
type: "WritableChanged",
payload: { oldValue: !writable, newValue: writable },
payload: isWritable,
});
logger.log(`WritableChange changed to ${isWritable}`);
};

@@ -210,8 +309,103 @@ context.emitter.on("writableChange", updateListener);

iframe.src = attrs.src;
/* --------------------------------------------- *\
# Magix Events
\* --------------------------------------------- */
const magixEventChannel = `channel-${context.appId}`;
const sendMagixMessage = (message: unknown): void => {
if (context.getIsWritable() && room) {
room.dispatchMagixEvent(magixEventChannel, message);
}
};
sideEffectManager.add(() => {
// pass through magix events
const magixListener = (e: Event) => {
if (e.event === magixEventChannel && e.authorId !== displayer.observerId) {
postMessage({ type: "ReceiveMagixMessage", payload: e.payload });
}
};
displayer.addMagixEventListener(magixEventChannel, magixListener);
return () => displayer.removeMagixEventListener(magixEventChannel, magixListener);
});
/* --------------------------------------------- *\
# Pass app data on init
\* --------------------------------------------- */
const sendInitData = () => {
const memberId = displayer.observerId;
const userPayload = displayer.state.roomMembers.find(
member => member.memberId === memberId
)?.payload;
postMessage({
type: "Init",
payload: {
page: attrs.page,
writable: context.getIsWritable(),
roomMembers: transformRoomMembers(displayer.state.roomMembers),
debug,
store: toJSON(attrs.store),
storeConfig,
meta: {
sessionUID: memberId,
uid: room?.uid || userPayload?.uid || "",
roomUUID: room?.uuid,
userPayload: toJSON(userPayload),
},
},
});
};
/* --------------------------------------------- *\
# Setup iframe message hub
\* --------------------------------------------- */
sideEffectManager.addEventListener(window, "message", e => {
if (e.source !== iframe.contentWindow) return;
if (!isObj(e.data)) {
logger.error("window message data should be object, instead got", e.data);
return;
}
const data = e.data as FromSDKMessage;
logger.log("Message From SDK", data);
switch (data.type) {
case "Init": {
sendInitData();
break;
}
case "SetState": {
setState(data.payload);
break;
}
case "SetStore": {
setStore(data.payload);
break;
}
case "SetPage": {
setPage(data.payload);
break;
}
case "SendMagixMessage": {
sendMagixMessage(data.payload);
break;
}
case "MoveCamera": {
moveCamera(data.payload);
break;
}
}
});
context.emitter.on("destroy", () => {
console.log("[EmbeddedPage]: destroy");
logger.log("destroy");
sideEffectManager.flushAll();
});
// Load the iframe page
iframe.src = attrs.src;
},

@@ -218,0 +412,0 @@ };

@@ -1,37 +0,86 @@

export type State = Record<string, unknown>;
import type { AkkoObjectUpdatedProperty } from "white-web-sdk";
type TransformMessage<TKey extends keyof Messages, Messages> = TKey extends keyof Messages
? Messages[TKey] extends void
? { type: TKey; payload?: Messages[TKey] }
: { type: TKey; payload: Messages[TKey] }
: never;
export type DefaultState = Record<string, unknown>;
export interface CameraState {
x: number;
y: number;
scale: number;
}
export interface RoomMember {
sessionUID: number;
uid: string;
userPayload: unknown;
}
// me --> iframe
export interface ToSDKMessagePayloads<TState = DefaultState, TMagix = unknown> {
Init: InitData<TState>;
StateChanged: {
namespace: string;
actions: ReadonlyArray<AkkoObjectUpdatedProperty<TState, Extract<keyof TState, string>>>;
};
StoreChanged: ReadonlyArray<AkkoObjectUpdatedProperty<{ [K: string]: TState }>>;
PageChanged: DiffOne<string>;
ReceiveMagixMessage: TMagix;
WritableChanged: boolean;
RoomMembersChanged: ReadonlyArray<RoomMember>;
}
export type ToSDKMessageKey = keyof ToSDKMessagePayloads;
export type ToSDKMessage<
TKey extends ToSDKMessageKey = ToSDKMessageKey,
TState = DefaultState,
TMagix = unknown
> = TransformMessage<TKey, ToSDKMessagePayloads<TState, TMagix>>;
// iframe --> me
export interface ReceiveMessages {
GetState: void;
SetState: State;
SendMessage: unknown;
GetPage: void;
export interface FromSDKMessagePayloads<TState = DefaultState, TMagix = unknown> {
Init: void;
SetState: { namespace: string; state: Partial<TState> };
GetState: { namespace: string; ensureState: TState };
SetStore: { [namespace: string]: unknown };
SetPage: string;
GetWritable: void;
SendMagixMessage: TMagix;
MoveCamera: Partial<CameraState>;
}
export type FromSDKMessageKey = keyof FromSDKMessagePayloads;
export type FromSDKMessage<
TKey extends FromSDKMessageKey = FromSDKMessageKey,
TState = DefaultState,
TMagix = unknown
> = TransformMessage<TKey, FromSDKMessagePayloads<TState, TMagix>>;
export type DiffOne<T> = { oldValue?: T; newValue?: T };
export type Diff<T> = { [K in keyof T]?: DiffOne<T[K]> };
export interface MetaData {
roomUUID?: string;
userPayload?: unknown;
readonly sessionUID: number;
readonly uid: string;
readonly roomUUID?: string;
readonly userPayload: unknown;
}
export interface InitData {
state: State;
export interface InitData<TState = DefaultState> {
page?: string;
writable: boolean;
meta: MetaData;
roomMembers: ReadonlyArray<RoomMember>;
debug?: boolean;
store: { [k: string]: TState };
storeConfig: {
mainId: string;
nsPrefix: string;
};
}
// me --> iframe
export interface SendMessages {
Init: InitData;
GetState: State;
StateChanged: Record<string, DiffOne<unknown>>;
ReceiveMessage: unknown;
GetPage: string | undefined;
PageChanged: DiffOne<string>;
GetWritable: boolean;
WritableChanged: DiffOne<boolean>;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc