Comparing version 0.0.6 to 0.0.7
@@ -0,1 +1,2 @@ | ||
import { WritableAtom } from 'nanostores/atom'; | ||
/** | ||
@@ -107,2 +108,6 @@ * Config for the framecast | ||
/** | ||
* Creates state that is synced between the two windows | ||
*/ | ||
state<StateType = any>(key: string, initialValue: StateType): WritableAtom<StateType>; | ||
/** | ||
* Handles the raw messages posted to the window | ||
@@ -109,0 +114,0 @@ * @param event The event that was posted to the window |
@@ -62,2 +62,4 @@ "use strict"; | ||
exports.Framecast = void 0; | ||
var atom_1 = require("nanostores/atom"); | ||
var lifecycle_1 = require("nanostores/lifecycle"); | ||
var superjson_1 = require("superjson"); | ||
@@ -238,2 +240,62 @@ var Framecast = /** @class */ (function () { | ||
/** | ||
* Creates state that is synced between the two windows | ||
*/ | ||
Framecast.prototype.state = function (key, initialValue) { | ||
var _this = this; | ||
var isInitialValue = true; | ||
var $atom = (0, atom_1.atom)(initialValue); | ||
/** | ||
* Get the initial value from the other window | ||
*/ | ||
this.call("state:get:".concat(key)) | ||
.then(function (value) { | ||
// if we have received another value already, | ||
// don't set the initial value | ||
if (isInitialValue) { | ||
$atom.set(value); | ||
} | ||
}) | ||
.catch(function () { | ||
// do nothing since we already have the initial value | ||
// if we are the first to mount, we'll set the value | ||
}); | ||
(0, lifecycle_1.onMount)($atom, function () { | ||
/** | ||
* Listen for changes to the state from other windows | ||
*/ | ||
function receiveValue(message) { | ||
if (!isStateSyncMessage(message)) { | ||
return; | ||
} | ||
if (message.key !== key) { | ||
return; | ||
} | ||
isInitialValue = false; | ||
$atom.set(message.value); | ||
} | ||
/** | ||
* Provide the initial value to the other window | ||
*/ | ||
function sendValue() { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, $atom.get()]; | ||
}); | ||
}); | ||
} | ||
_this.on('broadcast', receiveValue); | ||
_this.on("function:state:get:".concat(key), sendValue); | ||
return function () { | ||
_this.off('broadcast', receiveValue); | ||
_this.off("function:state:get:".concat(key), sendValue); | ||
}; | ||
}); | ||
var broadcast = this.broadcast.bind(this); | ||
return __assign(__assign({}, $atom), { set: function (value) { | ||
isInitialValue = false; | ||
$atom.set(value); | ||
broadcast({ type: 'state:sync', key: key, value: value }); | ||
} }); | ||
}; | ||
/** | ||
* Handles the raw messages posted to the window | ||
@@ -405,1 +467,13 @@ * @param event The event that was posted to the window | ||
exports.Framecast = Framecast; | ||
function isStateSyncMessage(message) { | ||
if (!message) { | ||
return false; | ||
} | ||
if (typeof message !== 'object') { | ||
return false; | ||
} | ||
return ('key' in message && | ||
'value' in message && | ||
'type' in message && | ||
message.type === 'state:sync'); | ||
} |
{ | ||
"name": "framecast", | ||
"version": "0.0.6", | ||
"version": "0.0.7", | ||
"description": "TypeScript cross-frame communication library.", | ||
@@ -22,8 +22,8 @@ "main": "lib/index.js", | ||
"type": "git", | ||
"url": "https://github.com/useparcel/framecast.git" | ||
"url": "https://github.com/customerio/framecast.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/useparcel/framecast/issues" | ||
"url": "https://github.com/customerio/framecast/issues" | ||
}, | ||
"homepage": "https://github.com/useparcel/framecast", | ||
"homepage": "https://github.com/customerio/framecast", | ||
"husky": { | ||
@@ -59,4 +59,5 @@ "hooks": { | ||
"dependencies": { | ||
"nanostores": "^0.9.5", | ||
"superjson": "^1.9.1" | ||
} | ||
} |
@@ -111,2 +111,61 @@ <h1 align="center">framecast</h1> | ||
## Shared State | ||
Framecast has support for shared state between the parent and child frames. This is done by using [`nanostores`](http://github.com/nanostores/nanostores). | ||
Each state is an [`atom`](https://github.com/nanostores/nanostores#atoms) and can be subscribed to. When the state is updated in one frame it will be updated in the other frame. | ||
### Creating shared state | ||
You can create a shared state by calling `state` on the framecast instance. The first argument is the name of the state and the second is the initial value. | ||
```ts | ||
const $counter = framecast.state('counter', 0); | ||
$counter.subscribe((value) => { | ||
console.log('counter', value); | ||
}); | ||
``` | ||
On initial creation the state will be set to the initial value. If the state already exists in the other frame will be synced to the value of the other frame. | ||
**Note: you must subscribe to the state to mount it.** | ||
### Example | ||
In the following example when either the parent or child frame updates the `$counter` the other frame will be updated. | ||
The implmentation is identical in both the parent and child frames. | ||
###### Child | ||
```ts | ||
import { Framecast } from 'framecast'; | ||
const framecast = new Framecast(window.parent); | ||
const $counter = framecast.state('counter', 0); | ||
$counter.subscribe((value) => { | ||
console.log('counter', value); | ||
}); | ||
document.querySelector('button').addEventListener('click', () => { | ||
$counter.set($counter.get() + 1); | ||
}); | ||
``` | ||
###### Parent | ||
```ts | ||
import { Framecast } from 'framecast'; | ||
import { persistentAtom, setPersistentEngine } from '@nanostores/persistent'; | ||
const framecast = new Framecast(document.querySelector('iframe').contentWindow); | ||
$counter.subscribe((value) => { | ||
console.log('counter', value); | ||
}); | ||
``` | ||
## Evaluating arbitrary code | ||
@@ -113,0 +172,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
43479
655
247
2
+ Addednanostores@^0.9.5
+ Addednanostores@0.9.5(transitive)