Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions js-lib/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");

module.exports = {
root: true,
extends: [
"eslint:recommended",
"@vue/eslint-config-prettier",
],
env : {
browser : true,
es6 : true,
},
rules : {
"no-unused-vars" : 2,
"no-undef" : 2
},
parserOptions: {
sourceType: "module",
ecmaVersion: "latest",
},
};
1 change: 1 addition & 0 deletions js-lib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
15 changes: 15 additions & 0 deletions js-lib/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Apache Software License 2.0

Copyright (c) 2024, Kitware Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
46 changes: 46 additions & 0 deletions js-lib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Trame iframe client library for plain JS
This library aims to simplify interaction between a trame application living inside an iframe and its iframe parent.
This work is inspired by the [official trame-client js lib](https://github.com/Kitware/trame-client/tree/master/js-lib)

## Examples
- [Vite](./examples/vite/)

## Usage
First you need to grab the iframe that contains your trame application.
```js
import ClientCommunicator from "@kitware/trame-iframe-client";

const iframe = document.getElementById("trame_app");
const iframe_url = "http://localhost:3000";

const trame = new ClientCommunicator(iframe, iframe_url);

// set
trame.state.set("a", 2);
trame.state.set('b', 3);
trame.state.update({
a: 2.5,
b: 3.5,
c: 4.5,
})

// get
console.log(trame.state.get("c"));
console.log(trame.state.get('a'));


// simple api for state change
trame.state.watch(
["a", "b", "c"],
(a, b, c) => {
console.log(`a(${a}) or b(${b}) or c(${c}) have changed`);
}
);

// -----------------------------------
// Method execution API
// -----------------------------------

// method execution on Python side
trame.trigger("name", ['arg_0', 'arg_1'], { kwarg_0: 1, kwarg_1: 2 });
```
25 changes: 25 additions & 0 deletions js-lib/examples/vite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Vite project

This example use npm package to illustrate how to use the trame iframe client.

## Trame setup

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install trame trame-iframe
```

## Build the client

```bash
cd client
npm i
npm run build
```

## Running example

```bash
python ./server.py --port 3000 --server
```
24 changes: 24 additions & 0 deletions js-lib/examples/vite/client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
9 changes: 9 additions & 0 deletions js-lib/examples/vite/client/counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function setupCounter(element, trame) {
trame.state.onReady(() => {
trame.state.watch(["count"], (count) => {
console.log(`count is ${count}`);
element.innerHTML = `count is ${count}`;
});
});
element.addEventListener("click", () => trame.trigger("add"));
}
12 changes: 12 additions & 0 deletions js-lib/examples/vite/client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.js"></script>
</body>
</html>
29 changes: 29 additions & 0 deletions js-lib/examples/vite/client/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import ClientCommunicator from "@kitware/trame-iframe-client";
import "./style.css";
import { setupCounter } from "./counter.js";

document.querySelector("#app").innerHTML = `
<div>
<h1>Hello Trame !</h1>
<div class="card">
<button id="counter" type="button"></button>
<button id="play" type="button">Auto update</button>
<button id="subtract" type="button">-1</button>
<iframe src="http://localhost:3000" frameborder="0" id="trame_app"></iframe>
</div>
</div>
`;

const url = "http://localhost:3000";
const iframe = document.getElementById("trame_app");

iframe.addEventListener("load", () => {
const trame = new ClientCommunicator(iframe, url);
setupCounter(document.querySelector("#counter"), trame);
document
.querySelector("#play")
.addEventListener("click", () => trame.trigger("toggle_play"));
document
.querySelector("#subtract")
.addEventListener("click", () => trame.trigger("subtract"));
});
17 changes: 17 additions & 0 deletions js-lib/examples/vite/client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "trame",
"version": "0.0.0",
"type": "module",
"main": "main.js",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^5.2.0"
},
"dependencies": {
"@kitware/trame-iframe-client": "/home/jules/projects/kitware/trame/repos/trame-iframe/js-lib/dist/trame-iframe.mjs"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix that

}
}
96 changes: 96 additions & 0 deletions js-lib/examples/vite/client/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;

color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;

font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}

body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}

h1 {
font-size: 3.2em;
line-height: 1.1;
}

#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vanilla:hover {
filter: drop-shadow(0 0 2em #f7df1eaa);
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
}

button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}

@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
46 changes: 46 additions & 0 deletions js-lib/examples/vite/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import asyncio
from trame.app import get_server
from trame.widgets import iframe
from trame.ui.html import DivLayout

server = get_server()
state, ctrl = server.state, server.controller

state.count = 1
state.play = False


@state.change("count")
def count_change(count, **_):
print(f"count={count}")


@ctrl.trigger("add")
def add_to_count():
state.count += 1


@ctrl.trigger("subtract")
def subtract_to_count():
state.count -= 1


@ctrl.trigger("toggle_play")
def toggle_play():
state.play = not state.play


async def animate(**kwargs):
while True:
await asyncio.sleep(0.5)
if state.play:
with state:
state.count += 1


ctrl.on_server_ready.add_task(animate)

with DivLayout(server) as layout:
comm = iframe.Communicator(target_origin="http://localhost:2222", enable_rpc=True)

server.start()
Loading
Loading