Skip to content

Commit 6632f86

Browse files
committed
doc(README): add readme + minimal example
1 parent cecb226 commit 6632f86

File tree

9 files changed

+303
-14
lines changed

9 files changed

+303
-14
lines changed

js-lib/README.md

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,46 @@
1-
// const trame = new Trame({ iframe });
2-
// await trame.connect({ application: 'trame' });
1+
# Trame iframe client library for plain JS
2+
This library aims to simplify interaction between a trame application living inside an iframe and its iframe parent.
3+
This work is inspired by the [official trame-client js lib](https://github.com/Kitware/trame-client/tree/master/js-lib)
34

4-
// State handing
5-
trame.state.set("a", 5);
6-
console.log(trame.state.get("b"));
7-
trame.state.update({
8-
a: 1,
9-
b: 2,
10-
});
5+
## Examples
6+
- [Vite](./examples/vite/)
7+
8+
## Usage
9+
First you need to grab the iframe that contains your trame application.
10+
```js
11+
import ClientCommunicator from "@kitware/trame-iframe-client";
12+
13+
const iframe = document.getElementById("trame_app");
14+
const iframe_url = "http://localhost:3000";
1115

12-
// Method call on Python
13-
const result = await trame.trigger("name", [arg_0, arg_1], { kwarg_0: 1, kwarg_1: 2 });
16+
const trame = new ClientCommunicator(iframe, iframe_url);
1417

15-
// TODO - state watching
16-
trame.state.watch(["a"], (a) => {
17-
console.log(`a changed to ${a}`);
18+
// set
19+
trame.state.set("a", 2);
20+
trame.state.set('b', 3);
21+
trame.state.update({
22+
a: 2.5,
23+
b: 3.5,
24+
c: 4.5,
1825
})
26+
27+
// get
28+
console.log(trame.state.get("c"));
29+
console.log(trame.state.get('a'));
30+
31+
32+
// simple api for state change
33+
trame.state.watch(
34+
["a", "b", "c"],
35+
(a, b, c) => {
36+
console.log(`a(${a}) or b(${b}) or c(${c}) have changed`);
37+
}
38+
);
39+
40+
// -----------------------------------
41+
// Method execution API
42+
// -----------------------------------
43+
44+
// method execution on Python side
45+
trame.trigger("name", ['arg_0', 'arg_1'], { kwarg_0: 1, kwarg_1: 2 });
46+
```

js-lib/examples/vite/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Vite project
2+
3+
This example use npm package to illustrate how to use the trame iframe client.
4+
5+
## Trame setup
6+
7+
```bash
8+
python3 -m venv .venv
9+
source .venv/bin/activate
10+
pip install trame trame-iframe
11+
```
12+
13+
## Build the client
14+
15+
```bash
16+
cd client
17+
npm i
18+
npm run build
19+
```
20+
21+
## Running example
22+
23+
```bash
24+
python ./server.py --port 3000 --server
25+
```
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export function setupCounter(element, trame) {
2+
trame.state.onReady(() => {
3+
trame.state.watch(["count"], (count) => {
4+
console.log(`count is ${count}`);
5+
element.innerHTML = `count is ${count}`;
6+
});
7+
});
8+
element.addEventListener("click", () => trame.trigger("add"));
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Vite App</title>
7+
</head>
8+
<body>
9+
<div id="app"></div>
10+
<script type="module" src="/main.js"></script>
11+
</body>
12+
</html>

js-lib/examples/vite/client/main.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import ClientCommunicator from "@kitware/trame-iframe-client";
2+
import "./style.css";
3+
import { setupCounter } from "./counter.js";
4+
5+
document.querySelector("#app").innerHTML = `
6+
<div>
7+
<h1>Hello Trame !</h1>
8+
<div class="card">
9+
<button id="counter" type="button"></button>
10+
<button id="play" type="button">Auto update</button>
11+
<button id="subtract" type="button">-1</button>
12+
<iframe src="http://localhost:3000" frameborder="0" id="trame_app"></iframe>
13+
</div>
14+
</div>
15+
`;
16+
17+
const url = "http://localhost:3000";
18+
const iframe = document.getElementById("trame_app");
19+
20+
iframe.addEventListener("load", () => {
21+
const trame = new ClientCommunicator(iframe, url);
22+
setupCounter(document.querySelector("#counter"), trame);
23+
document
24+
.querySelector("#play")
25+
.addEventListener("click", () => trame.trigger("toggle_play"));
26+
document
27+
.querySelector("#subtract")
28+
.addEventListener("click", () => trame.trigger("subtract"));
29+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "trame",
3+
"version": "0.0.0",
4+
"type": "module",
5+
"main": "main.js",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "vite build",
9+
"preview": "vite preview"
10+
},
11+
"devDependencies": {
12+
"vite": "^5.2.0"
13+
},
14+
"dependencies": {
15+
"@kitware/trame-iframe-client": "/home/jules/projects/kitware/trame/repos/trame-iframe/js-lib/dist/trame-iframe.mjs"
16+
}
17+
}

js-lib/examples/vite/client/style.css

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
:root {
2+
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3+
line-height: 1.5;
4+
font-weight: 400;
5+
6+
color-scheme: light dark;
7+
color: rgba(255, 255, 255, 0.87);
8+
background-color: #242424;
9+
10+
font-synthesis: none;
11+
text-rendering: optimizeLegibility;
12+
-webkit-font-smoothing: antialiased;
13+
-moz-osx-font-smoothing: grayscale;
14+
}
15+
16+
a {
17+
font-weight: 500;
18+
color: #646cff;
19+
text-decoration: inherit;
20+
}
21+
a:hover {
22+
color: #535bf2;
23+
}
24+
25+
body {
26+
margin: 0;
27+
display: flex;
28+
place-items: center;
29+
min-width: 320px;
30+
min-height: 100vh;
31+
}
32+
33+
h1 {
34+
font-size: 3.2em;
35+
line-height: 1.1;
36+
}
37+
38+
#app {
39+
max-width: 1280px;
40+
margin: 0 auto;
41+
padding: 2rem;
42+
text-align: center;
43+
}
44+
45+
.logo {
46+
height: 6em;
47+
padding: 1.5em;
48+
will-change: filter;
49+
transition: filter 300ms;
50+
}
51+
.logo:hover {
52+
filter: drop-shadow(0 0 2em #646cffaa);
53+
}
54+
.logo.vanilla:hover {
55+
filter: drop-shadow(0 0 2em #f7df1eaa);
56+
}
57+
58+
.card {
59+
padding: 2em;
60+
}
61+
62+
.read-the-docs {
63+
color: #888;
64+
}
65+
66+
button {
67+
border-radius: 8px;
68+
border: 1px solid transparent;
69+
padding: 0.6em 1.2em;
70+
font-size: 1em;
71+
font-weight: 500;
72+
font-family: inherit;
73+
background-color: #1a1a1a;
74+
cursor: pointer;
75+
transition: border-color 0.25s;
76+
}
77+
button:hover {
78+
border-color: #646cff;
79+
}
80+
button:focus,
81+
button:focus-visible {
82+
outline: 4px auto -webkit-focus-ring-color;
83+
}
84+
85+
@media (prefers-color-scheme: light) {
86+
:root {
87+
color: #213547;
88+
background-color: #ffffff;
89+
}
90+
a:hover {
91+
color: #747bff;
92+
}
93+
button {
94+
background-color: #f9f9f9;
95+
}
96+
}

js-lib/examples/vite/server.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import asyncio
2+
import random
3+
from trame.app import get_server
4+
from trame.widgets import iframe
5+
from trame.ui.html import DivLayout
6+
7+
server = get_server()
8+
state, ctrl = server.state, server.controller
9+
10+
state.count = 1
11+
state.play = False
12+
13+
14+
@state.change("count")
15+
def count_change(count, **_):
16+
print(f"count={count}")
17+
18+
19+
@ctrl.trigger("add")
20+
def add_to_count():
21+
state.count += 1
22+
23+
24+
@ctrl.trigger("subtract")
25+
def subtract_to_count():
26+
state.count -= 1
27+
28+
29+
@ctrl.trigger("toggle_play")
30+
def toggle_play():
31+
state.play = not state.play
32+
33+
34+
async def animate(**kwargs):
35+
while True:
36+
await asyncio.sleep(0.5)
37+
if state.play:
38+
with state:
39+
state.count += 1
40+
41+
42+
ctrl.on_server_ready.add_task(animate)
43+
44+
with DivLayout(server) as layout:
45+
comm = iframe.Communicator(
46+
target_origin="http://localhost:2222", enable_rpc=True
47+
)
48+
49+
server.start()

0 commit comments

Comments
 (0)