diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 88331fcb..3f1816d4 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -21,4 +21,4 @@ values =
[bumpversion:file:docs/conf.py]
-[bumpversion:file:pyproject.toml]
+[bumpversion:file:js/src/VuetifyWidget.js]
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ff9f1479..3b53f3bc 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -9,34 +9,42 @@ on:
pull_request:
workflow_dispatch:
+permissions:
+ contents: read
+ id-token: write
+
jobs:
lint:
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-python@v6
with:
python-version: "3.10"
- - uses: pre-commit/action@v3.0.1
+ - name: Install pre-commit
+ run: python -m pip install pre-commit
+ - uses: actions/cache@v5
+ with:
+ path: ~/.cache/pre-commit
+ key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
+ - name: Run pre-commit
+ run: pre-commit run --show-diff-on-failure --color=always --all-files
build:
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-python@v6
with:
python-version: "3.10"
- # https://github.com/webpack/webpack/issues/14532
- - uses: actions/setup-node@v4
+ - uses: actions/setup-node@v5
with:
- node-version: 16
- - name: install build
- run: python -m pip install build
-
+ node-version: "24"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- pip install "reacton[generate]" ipyvue
+ pip install "reacton[generate]" "ipyvue>=3.0.0" build
+
- name: build wheel
run: python -m build
@@ -45,11 +53,10 @@ jobs:
cp ipyvuetify/components.py ipyvuetify/components-previous.py
python -m ipyvuetify.components
diff ipyvuetify/components.py ipyvuetify/components-previous.py
-
- name: Package js
- run: (cd js && npm pack)
+ run: (cd js && npm pack --ignore-scripts)
- name: Upload build artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: ipyvuetify-dist-${{ github.run_number }}
path: |
@@ -57,7 +64,7 @@ jobs:
./js/*.tgz
- name: Upload components
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: ipyvuetify-components-${{ github.run_number }}
path: |
@@ -65,105 +72,92 @@ jobs:
test:
needs: [lint, build]
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
- python-version: ["3.8", "3.9", "3.10", "3.11"]
+ python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v7
with:
name: ipyvuetify-dist-${{ github.run_number }}
- name: Install ipyvuetify
- run: python -m pip install "$(find dist -name *.whl)"
+ run: |
+ python -m pip install "$(find dist -name '*.whl')"
- name: test import
run: (mkdir test-install; cd test-install; python -c "from ipyvuetify import Btn")
ui-test:
needs: [lint, build]
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-python@v6
with:
python-version: "3.10"
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v7
with:
name: ipyvuetify-dist-${{ github.run_number }}
- name: Install ipyvuetify
- run: python -m pip install "$(find dist -name *.whl)[test]"
+ run: python -m pip install "$(find dist -name '*.whl')[test]"
- name: Install chromium
run: playwright install chromium
- name: Run ui-tests
- run: pytest tests/ui/ --video=retain-on-failure --solara-update-snapshots-ci -s
+ run: pytest tests/ui/ --video=retain-on-failure -s
- name: Upload Test artifacts
if: always()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: ipyvuetify-test-results
path: test-results
release-dry-run:
needs: [test, ui-test]
- if: github.event.pull_request.head.repo.full_name == 'widgetti/ipyvuetify'
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v7
with:
name: ipyvuetify-dist-${{ github.run_number }}
- name: Install node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v5
with:
- node-version: 14
+ node-version: "24"
registry-url: "https://registry.npmjs.org"
-
- - name: Install Python
- uses: actions/setup-python@v5
- with:
- python-version: 3.8
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install twine
-
- - name: Publish the Python package
- env:
- TWINE_USERNAME: __token__
- TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
- run: twine upload --skip-existing --repository testpypi dist/*
-
+ package-manager-cache: false
+ # No --dry-run available for twine
+ # - name: Publish the Python package
- name: Publish the NPM package
run: |
cd js
echo $PRE_RELEASE
if [[ $PRE_RELEASE == "true" ]]; then export TAG="next"; else export TAG="latest"; fi
- npm publish --dry-run --tag ${TAG} --access public *.tgz
+ npm publish --dry-run --tag ${TAG} --access public *.tgz
env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
PRE_RELEASE: ${{ github.event.release.prerelease }}
release:
if: startsWith(github.event.ref, 'refs/tags/v')
- needs: [test, ui-test]
- runs-on: ubuntu-24.04
+ needs: [release-dry-run]
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v7
with:
name: ipyvuetify-dist-${{ github.run_number }}
- name: Install node
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v5
with:
- node-version: 14
+ node-version: "24"
registry-url: "https://registry.npmjs.org"
+ package-manager-cache: false
- name: Install Python
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
python-version: 3.8
@@ -185,5 +179,4 @@ jobs:
if [[ $PRE_RELEASE == "true" ]]; then export TAG="next"; else export TAG="latest"; fi
npm publish --tag ${TAG} --access public *.tgz
env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
PRE_RELEASE: ${{ github.event.release.prerelease }}
diff --git a/.gitignore b/.gitignore
index 1722c7d6..09450290 100755
--- a/.gitignore
+++ b/.gitignore
@@ -10,7 +10,6 @@ dist/
build/
# generated code
-generate_source/build
generate_source/vuetify
ipyvuetify/generated
js/src/generated
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0207538a..730b9ca3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -4,6 +4,7 @@ repos:
hooks:
- id: black
stages: [commit]
+ exclude: ^ipyvuetify/components\.py$
- repo: "https://github.com/commitizen-tools/commitizen"
rev: "v2.18.0"
hooks:
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index a661804e..cfb65d72 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -6,10 +6,16 @@ version: 2
# build with latest available ubuntu version
build:
- os: ubuntu-20.04
+ os: ubuntu-22.04
tools:
python: "3.10"
- nodejs: "16"
+ nodejs: "20"
+ jobs:
+ pre_install:
+ - cd js && npm ci --ignore-scripts
+ - cd js && npm run build:docs
+ - mkdir -p prefix/share/jupyter/nbextensions/jupyter-vuetify
+ - touch prefix/share/jupyter/nbextensions/jupyter-vuetify/index.js
# Build documentation in the docs/ directory with Sphinx
sphinx:
diff --git a/README.md b/README.md
index b7ac0d99..ab64b698 100755
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
[](https://github.com/psf/black)
[](https://conventionalcommits.org)
-Jupyter widgets based on [vuetify UI components](https://v2.vuetifyjs.com/) which implement Google's
+Jupyter widgets based on [vuetify UI components](https://v3.vuetifyjs.com/) which implement Google's
[Material Design Spec](https://material.io/) with the [Vue.js framework](https://vuejs.org/).
A small selection of widgets:
@@ -43,16 +43,16 @@ https://ipyvuetify.readthedocs.io/
For examples see the [example notebook](examples/Examples.ipynb).
-The [Vuetify documentation](https://v2.vuetifyjs.com/components/buttons#buttons) can be used to find all available
+The [Vuetify 3 documentation](https://v3.vuetifyjs.com/en/components/buttons/) can be used to find all available
components and attributes (in the left side bar or use the search field). Ipyvuetify tries to stay close to the Vue.js
and Vuetify template syntax, but there are some differences:
| Description | Vuetify | ipyvuetify |
| ----------------------------------------------------------------------- | --------------------------------------- | --------------------------------------- |
-| Component names are in CamelCase and the v- prefix is stripped | `` | `ListTile(...)` |
+| Component names are in CamelCase and the v- prefix is stripped | `` | `ListItem(...)` |
| Child components and text are defined in the children traitlet | `text ` | `Btn(children=['text', Icon(...)])` |
-| Flag attributes require a boolean value | `` | `Btn(rounded=True, ...)` |
+| Attributes are snake_case | `` | `Select(append_icon='mdi-menu', ...)` |
| The v_model attribute (value in ipywidgets) contains the value directly | `
```
##### ipyvuetify:
```python
-drawer = v.NavigationDrawer(mini_variant=True, ...)
+drawer = v.NavigationDrawer(rail=True, ...)
-def update_mini(widget, event, data):
- drawer.mini_variant = data`
+def update_rail(widget, event, data):
+ drawer.rail = data
-drawer.on_event('update:miniVariant', update_mini)
+drawer.on_event('update:rail', update_rail)
```
### (scoped) slots
@@ -89,8 +89,8 @@ drawer.on_event('update:miniVariant', update_mini)
```HTML
-
- ...
+
+ ...
...
@@ -104,13 +104,13 @@ drawer.on_event('update:miniVariant', update_mini)
Menu(v_slots=[{
'name': 'activator',
'variable': 'x',
- 'children': Btn(v_on='x.on', children=[...])
+ 'children': Btn(v_on='x.props', children=[...])
}], children=[
List(...)
])
```
-For non scoped slots `'scope': 'x'` and `v_on` can be omitted.
+For non-scoped slots, `variable` and `v_on` can be omitted.
### Icons
diff --git a/docs/_static/jupyter-vuetify-embed-amd.js b/docs/_static/jupyter-vuetify-embed-amd.js
new file mode 100644
index 00000000..483fa471
--- /dev/null
+++ b/docs/_static/jupyter-vuetify-embed-amd.js
@@ -0,0 +1,15 @@
+const localVuetify = new URL("_static/jupyter-vuetify/index", document.baseURI)
+ .href;
+
+require.config({
+ paths: {
+ "jupyter-vue":
+ "https://cdn.jsdelivr.net/npm/jupyter-vue@3.0.0-alpha.5/dist/index",
+ "jupyter-vuetify": localVuetify,
+ },
+});
+
+const script = document.createElement("script");
+script.src =
+ "https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@^1.0.1/dist/embed-amd.js";
+document.head.appendChild(script);
diff --git a/docs/advanced_usage.rst b/docs/advanced_usage.rst
index 6b6681ec..5a4d0ede 100644
--- a/docs/advanced_usage.rst
+++ b/docs/advanced_usage.rst
@@ -6,9 +6,8 @@ Advanced Usage
Slots are used to add content at a certain location in a widget. You can find out what slots a widget supports by using
the Vuetify documentation. If you want to know what slots :code:`Select` has, search for :code:`v-select` on the
-`Vuetify API explorer `_ or for this example use the `direct link
-`_. On the left-hand side of the list of attributes you will find a tab
-'slots'.
+`Vuetify API explorer `_ or for this example use the `direct link
+`_. In the component API you will find the slots it supports.
An example for using the slot 'no-data', which changes what the Select widget shows when it has no items:
@@ -43,8 +42,8 @@ ipyvuetify:
v.ListItemTitle(children=['My custom no data message'])])]
}])
-Scoped slots are used if the parent widget needs to share its scope with the content. In the example below the events
-of the parent widget are used in the slot content.
+Scoped slots are used if the parent widget needs to share its scope with the content. In the example below the activator
+props of the parent widget are used in the slot content.
Vuetify:
@@ -52,7 +51,7 @@ Vuetify:
-
+
button with tooltip
@@ -64,10 +63,10 @@ ipyvuetify:
.. jupyter-execute::
v.Container(children=[
- v.Tooltip(bottom=True, v_slots=[{
+ v.Tooltip(location='bottom', v_slots=[{
'name': 'activator',
'variable': 'tooltip',
- 'children': v.Btn(v_on='tooltip.on', color='primary', children=[
+ 'children': v.Btn(v_on='tooltip.props', color='primary', children=[
'button with tooltip'
]),
}], children=['Insert tooltip text here'])
@@ -78,8 +77,8 @@ In the Vuetify examples you will actually see:
.. code-block:: html
...
-
-
+
+
...
Instead of the functionally equivalent (like used in the example above):
@@ -88,11 +87,11 @@ Instead of the functionally equivalent (like used in the example above):
...
-
+
...
-The :code:`{ on }` is JavaScript syntax for destructuring an object. It takes the 'on' attribute from an object and
-exposes it as the 'on' variable.
+The :code:`{ props }` is JavaScript syntax for destructuring an object. It takes the 'props' attribute from an object and
+exposes it as the 'props' variable.
.. note::
@@ -102,7 +101,7 @@ Responsive Layout
-----------------
When making dashboards with Voilà you can change the layout depending on the user's screen size. This is done with a `grid
-system `_. For example on a laptop (breakpoint md) you could fit two
+system `_. For example on a laptop (breakpoint md) you could fit two
elements next to each other while on a smartphone (defined with 'cols' as default) you would want one element to take up
the full width:
@@ -111,7 +110,7 @@ the full width:
v.Row(children=[
v.Col(cols=12, md=6, children=[
- v.Card(outlined=True, style_='height: 400px', children=[f'Element {i}'])
+ v.Card(variant='outlined', style_='height: 400px', children=[f'Element {i}'])
]) for i in range (1,3)
])
@@ -125,20 +124,20 @@ On a phone as:
.. image:: images/responsive-mobile.png
:width: 263
-In the `display section `_ you will find CSS helper classes to do more
+In the `display section `_ you will find CSS helper classes to do more
customizations based on screen size.
Event modifiers
---------------
-In Vue `event modifiers `_ can be used to change event behavior.
+In Vue `event modifiers `_ can be used to change event behavior.
For example when you have two nested elements and want a different click handler for the inner and outer element, the
``stop`` event modifier can be used by appending ``.stop`` to the event name:
.. jupyter-execute::
- icon = v.Icon(right=True, children=['mdi-account-lock'])
+ icon = v.Icon(end=True, children=['mdi-account-lock'])
btn = v.Btn(color='primary', children=[
'button',
icon
@@ -153,12 +152,12 @@ For example when you have two nested elements and want a different click handler
# Note: the event handlers won't work in this page because there is no active kernel.
-.sync
------
+v-model arguments
+-----------------
-When you see ``.sync`` appended to an attribute in Vuetify syntax, it means the attribute has a `two-way binding
-`_ (like ``v-model``). This is shorthand in Vue
-that automatically listens to an event named ``update:``.
+When you see a ``v-model`` argument such as ``v-model:rail`` in Vuetify syntax, it means the attribute has a `two-way binding
+`_ (like the default ``v-model``). Vue
+automatically listens to an event named ``update:``.
We can achieve the same manually in ipyvuetify by setting an event handler
``.on_event('update:', )``
@@ -167,15 +166,15 @@ Vuetify:
.. code-block:: none
- {{ index }}