Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f49d62b
feat: Vue3 support
mariobuikhuizen Oct 31, 2023
9d8a21e
feat: backward compatibility for templates using 'modules.export'
mariobuikhuizen Oct 31, 2023
0ec320e
docs: fix examples
mariobuikhuizen Nov 1, 2023
cfa3568
chore: bump version 1.10.1 -> 3.0.0-dev.0
mariobuikhuizen Nov 1, 2023
599429d
fix: convert python to js version when prerelease
maartenbreddels Nov 1, 2023
0e8c50e
temp: install solara from branch
maartenbreddels Nov 1, 2023
30e9613
ci: install vuetify3
maartenbreddels Nov 1, 2023
356320c
fix: prevent warnings about resolving default HTML tags like 'div`
mariobuikhuizen Nov 8, 2023
d8b125e
chore: add package-lock with new version
mariobuikhuizen Nov 15, 2023
fec057b
feat: make it possible to add modules for use in templates
mariobuikhuizen Nov 15, 2023
77f5fcc
feat: add more extension points to VueView
mariobuikhuizen Nov 15, 2023
d7bae3e
fix: embed the es-module-shims script
mariobuikhuizen Nov 16, 2023
429abcc
feat: remove unused traits css, methods and data
mariobuikhuizen Nov 17, 2023
28ef04f
chore: remove comments and console.log
mariobuikhuizen Nov 17, 2023
8143302
chore: release v3.0.0.alpha1
mariobuikhuizen Nov 17, 2023
d5fe12e
fix: templates not rendering in Voila
mariobuikhuizen Nov 28, 2023
daa98c3
chore:release v3.0.0.alpha2
mariobuikhuizen Nov 28, 2023
aa6fa5b
fix: make setup() and <script setup> work
mariobuikhuizen Sep 26, 2024
58ddcdd
ci: fix outdated action
mariobuikhuizen Sep 26, 2024
c4dd38e
chore: release v3.0.0.alpha3
mariobuikhuizen Sep 26, 2024
725ebfd
fix: don't fail if there is no template part in the SFC
mariobuikhuizen Sep 30, 2024
403c6ce
feat: typescript support
mariobuikhuizen Oct 1, 2024
db673cf
chore: release v3.0.0.alpha4
mariobuikhuizen Oct 1, 2024
1b968ee
CI: fix unsupported versions
mariobuikhuizen Feb 10, 2026
2bb39e3
make building with lab 4 work, make glue-jupyter work
mariobuikhuizen Feb 25, 2026
ebbabc1
chore: release v3.0.0.alpha5
mariobuikhuizen Feb 25, 2026
a6409d2
fix error with props is slots
mariobuikhuizen Mar 3, 2026
e064426
fix: get the right vue export for nodeps for solara
mariobuikhuizen Mar 5, 2026
3d13944
publish dev release to github releases
mariobuikhuizen Mar 5, 2026
82d6303
use proper id
mariobuikhuizen Mar 6, 2026
90efc48
use object storage instead of github releases
mariobuikhuizen Mar 9, 2026
76320f1
fix: scoped styles not entirely implemented
mariobuikhuizen Mar 31, 2026
7732593
Fix template listener cleanup on unmount
mariobuikhuizen Apr 1, 2026
5af38ad
Use Vue 3 unmount hook for destroy_widget
mariobuikhuizen Apr 1, 2026
f7601ad
Fix scoped v_on resolution for Vue 3
mariobuikhuizen Apr 1, 2026
ae736e3
Add scoped v_bind support for Vue 3 slots
mariobuikhuizen Apr 1, 2026
1454e33
Clean up runtime styles on template updates
mariobuikhuizen Apr 2, 2026
15e66e2
give nodeps the same esm exports
mariobuikhuizen Apr 21, 2026
42d229a
fix: make jupyter-widget tag and full-vue-component work in solara
mariobuikhuizen May 14, 2026
780b65b
refactor: Expose Vue widget component factory
mariobuikhuizen May 18, 2026
2eb335a
fix: add a default sourceURL to aid debugging
mariobuikhuizen May 20, 2026
399ad34
ci: avoid duplicate branch and PR runs
mariobuikhuizen May 20, 2026
4ddfa0f
fix: preserve falsy event payloads
mariobuikhuizen May 20, 2026
f1c0fe6
fix: convert CommonJS Vue templates by assignment
mariobuikhuizen May 20, 2026
e8487f0
ci: publish dev wheels from vue3 pull request
mariobuikhuizen May 20, 2026
d0086f2
build: add pyproject build-system metadata
mariobuikhuizen May 20, 2026
64bcebe
fix: prevent removal of vue from import map
mariobuikhuizen Jun 15, 2026
61e86e2
Merge v1.12 changes into Vue 3 branch
mariobuikhuizen Jun 15, 2026
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
73 changes: 53 additions & 20 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@ on:
pull_request:
workflow_dispatch:

env:
PKG_URL: https://nbg1.your-objectstorage.com/ipyvue3-packages/packages

permissions:
contents: read

jobs:
code-quality:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
Expand All @@ -28,23 +34,23 @@ jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Install node
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: "14.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"

- name: Install Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install twine wheel jupyter-packaging "jupyterlab<4"
pip install twine wheel jupyter-packaging "jupyterlab<5"

- name: Build
run: |
Expand All @@ -70,22 +76,43 @@ jobs:
./dist
./js/*.tgz

- name: Publish dev wheel to object storage
if: >
github.event_name == 'pull_request' &&
github.event.pull_request.head.ref == 'vue3' &&
github.event.pull_request.head.repo.full_name == github.repository
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
AWS_REGION: nbg1
AWS_ENDPOINT_URL_S3: https://nbg1.your-objectstorage.com
S3_BUCKET: ipyvue3-packages
run: |
python -m pip install --upgrade awscli

aws s3 cp dist/ "s3://${S3_BUCKET}/packages/ipyvue/" \
--recursive \
--exclude "*" \
--include "*.whl" \
--endpoint-url "$AWS_ENDPOINT_URL_S3" \
--region "$AWS_REGION"

test:
needs: [build]
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
python-version: [3.8, 3.9, "3.10", "3.11"]
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: ipyvue-dist-${{ github.run_number }}

- name: Install Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

Expand All @@ -107,21 +134,26 @@ jobs:
needs: [build]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: ipyvue-dist-${{ github.run_number }}

- name: Install Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.8

- name: Install vuetify and test deps
run: |
wheel=(dist/*.whl)
pip install ${wheel}[test] "jupyter_server<2"
pip install ${wheel}
pip install "${PKG_URL}/ipyvuetify/ipyvuetify-3.0.0a3-py2.py3-none-any.whl"
pip install "solara-ui[all] @ ${PKG_URL}/solara/solara_ui-1.57.3-py3-none-any.whl"
pip install "solara-server[starlette,dev] @ ${PKG_URL}/solara-server/solara_server-1.57.3-py3-none-any.whl"
pip install "pytest-ipywidgets[all] @ ${PKG_URL}/pytest-ipywidgets/pytest_ipywidgets-1.57.3-py3-none-any.whl"
pip install "jupyter_server<2"

- name: Install playwright browsers
run: playwright install chromium
Expand All @@ -137,17 +169,17 @@ jobs:
path: test-results

release-dry-run:
needs: [ test,ui-test,code-quality ]
needs: [test, ui-test, code-quality]
runs-on: ubuntu-24.04
steps:
- uses: actions/download-artifact@v4
with:
name: ipyvue-dist-${{ github.run_number }}

- name: Install node
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: "14.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"

- name: Publish the NPM package
Expand All @@ -159,6 +191,7 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
PRE_RELEASE: ${{ github.event.release.prerelease }}

release:
if: startsWith(github.event.ref, 'refs/tags/v')
needs: [release-dry-run]
Expand All @@ -169,15 +202,15 @@ jobs:
name: ipyvue-dist-${{ github.run_number }}

- name: Install node
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: "14.x"
node-version: "20.x"
registry-url: "https://registry.npmjs.org"

- name: Install Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: "3.11"

- name: Install dependencies
run: |
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ repos:
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 3.9.2
rev: 7.1.1
hooks:
- id: flake8
29 changes: 3 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,8 @@ For a development installation (requires npm),
Scoped CSS Support
------------------

`<style scoped>` in `VueTemplate` templates is supported but disabled by default for backwards
compatibility. When enabled, CSS rules only apply to the component's own elements.

Enable globally via environment variable:

$ IPYVUE_SCOPED_CSS_SUPPORT=1 jupyter lab

Or in Python:

```python
import ipyvue
ipyvue.scoped_css_support = True
```

Or per widget:
`<style scoped>` in `VueTemplate` templates is supported. Scoped CSS rules only apply
to the component's own elements.

```python
from ipyvue import VueTemplate
Expand All @@ -58,17 +45,7 @@ class MyComponent(VueTemplate):
</style>
"""

widget = MyComponent(scoped_css_support=True)
```

Note: The `css` trait with `scoped=True` always works, regardless of this setting:

```python
widget = VueTemplate(
template="<template><span class='x'>Hi</span></template>",
css=".x { color: blue; }",
scoped=True
)
widget = MyComponent()
```

Sponsors
Expand Down
8 changes: 8 additions & 0 deletions class_components.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
" input = Unicode().tag(sync=True)\n",
" something = Unicode('defaultvalue').tag(sync=True)\n",
" template = Unicode('''\n",
" <template>\n",
" <div style=\"border: 1px solid green; margin: 2px\" @click=\"append_one()\">\n",
" [{{ something }}] input: {{ input }} \n",
" </div>\n",
" </template> \n",
" ''').tag(sync=True)\n",
" \n",
" def vue_append_one(self, *args):\n",
Expand All @@ -44,6 +46,7 @@
" texts = List(['xxxx', 'yyyy']).tag(sync=True)\n",
" direct = Unicode('aaa').tag(sync=True)\n",
" template = Unicode('''\n",
" <template>\n",
" <div>\n",
" <div style=\"border: 1px solid black\">\n",
" <sub-component v-for=\"t in texts\" :input=\"t\" :key=\"t\" />\n",
Expand All @@ -52,6 +55,7 @@
" <w-button v-for=\"t in texts\" :description=\"t\" :key=\"t\" />\n",
" <w-button description=\"no v-for\"/>\n",
" </div>\n",
" </template>\n",
" ''').tag(sync=True)\n",
" \n",
" components=Dict({\n",
Expand Down Expand Up @@ -113,9 +117,11 @@
" label = Unicode().tag(sync=True)\n",
" \n",
" template = Unicode('''\n",
" <template>\n",
" <div style=\"border: 1px solid green; margin: 2px\">\n",
" [{{ label }}] Db URL: {{ info }}\n",
" </div>\n",
" </template>\n",
" ''').tag(sync=True)\n",
" \n",
" @observe('db')\n",
Expand All @@ -135,6 +141,7 @@
" supplier_db_collection = Dict().tag(sync_ref=True)\n",
" \n",
" template = Unicode('''\n",
" <template>\n",
" <div>\n",
" <database-info label=\"customers\" :db=\"customer_db\" />\n",
" \n",
Expand All @@ -146,6 +153,7 @@
" \n",
" <database-info label=\"function\" :db=\"{functionRef: 'db_factory', args: ['localhost/function1']}\" />\n",
" </div>\n",
" </template>\n",
" ''').tag(sync=True)\n",
" \n",
" components = Dict({\n",
Expand Down
2 changes: 2 additions & 0 deletions examples/DeepWatch.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
" deep_array = traitlets.List(['array']).tag(sync=True)\n",
" deep_array2 = traitlets.List([{'prop': 'array2'}]).tag(sync=True)\n",
" template = traitlets.Unicode('''\n",
" <template>\n",
" <div>\n",
" <v-text-field v-model=\"deep.prop\" />\n",
" <v-text-field v-model=\"deep.deeper.prop\" />\n",
Expand All @@ -27,6 +28,7 @@
" {{ deep_array[0] }} |\n",
" {{ deep_array2[0].prop }}\n",
" </div>\n",
" </template>\n",
" ''').tag(sync=True)\n",
" \n",
"md = MyDeep()\n",
Expand Down
12 changes: 7 additions & 5 deletions examples/EmbeddingJupyterWidgetsInVueTemplate.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@
"\n",
"\n",
" template=Unicode(\"\"\"\n",
" <div>\n",
" <div v-for=\"item in items\" :key=\"item.title + item.content\">\n",
" {{ item.title }}: <jupyter-widget :widget=\"item.content\" />\n",
" <template>\n",
" <div>\n",
" <div v-for=\"item in items\" :key=\"item.title + item.content\">\n",
" {{ item.title }}: <jupyter-widget :widget=\"item.content\" />\n",
" </div>\n",
" Single widget: <jupyter-widget :widget=\"single_widget\" />\n",
" </div>\n",
" Single widget: <jupyter-widget :widget=\"single_widget\" />\n",
" </div>\n",
" </template>\n",
" \"\"\").tag(sync=True)\n",
"\n",
"my_component = MyComponent()\n",
Expand Down
52 changes: 2 additions & 50 deletions examples/ScopedCSS.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
"source": [
"# Scoped CSS\n",
"\n",
"By default, CSS in ipyvue templates is **global** — it affects all elements on the page with matching selectors. Scoped CSS limits styles to the component that defines them.\n",
"CSS in ipyvue templates is global unless it is marked with `<style scoped>`. Scoped CSS limits styles to the component that defines them.\n",
"\n",
"**How it works:** ipyvue adds a unique `data-v-*` attribute to your component's elements and rewrites your CSS selectors to include it (e.g., `.my-class` `.my-class[data-v-abc123]`)."
"**How it works:** ipyvue adds a unique `data-v-*` attribute to your component's elements and rewrites your CSS selectors to include it (e.g., `.my-class` -> `.my-class[data-v-abc123]`)."
]
},
{
Expand All @@ -22,28 +22,6 @@
"from traitlets import default"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Enable scoped CSS support\n",
"\n",
"For backwards compatibility, `<style scoped>` in templates is **disabled by default**. Existing code that accidentally relied on CSS leaking would break if we enabled it automatically.\n",
"\n",
"Enable it globally for this notebook:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Enable scoped CSS support for <style scoped> in templates\n",
"# Can also be set via environment variable: IPYVUE_SCOPED_CSS_SUPPORT=1\n",
"vue.scoped_css_support = True"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -103,32 +81,6 @@
"\n",
"widgets.VBox([ScopedStyle(), widget_b]) # Only Widget A is green"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Using the `css` trait with `scoped=True`\n",
"\n",
"Alternative syntax when defining CSS outside the template:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class CssTrait(vue.VueTemplate):\n",
" @default(\"template\")\n",
" def _default_template(self):\n",
" return \"<template><span class='trait-demo'>Widget C (scoped via trait)</span></template>\"\n",
"\n",
"widget_c = CssTrait(css=\".trait-demo { color: blue; }\", scoped=True)\n",
"widget_d = vue.Html(tag=\"span\", children=[\"Widget D (unaffected)\"], class_=\"trait-demo\")\n",
"\n",
"widgets.VBox([widget_c, widget_d])"
]
}
],
"metadata": {
Expand Down
Loading
Loading