panel-splitjs 0.0.1a0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.github/workflows/build.yml +1 -1
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.github/workflows/test.yml +41 -3
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.github/workflows/update-lockfiles.yml +3 -3
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/PKG-INFO +116 -41
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/README.md +114 -39
- panel_splitjs-0.2.0/examples/apps/multi.py +21 -0
- panel_splitjs-0.2.0/examples/apps/simple.py +8 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/pixi.lock +4080 -4237
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/pixi.toml +5 -7
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/pyproject.toml +1 -1
- panel_splitjs-0.2.0/src/panel_splitjs/__init__.py +4 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/_version.py +2 -2
- panel_splitjs-0.2.0/src/panel_splitjs/base.py +164 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/dist/css/splitjs.css +54 -17
- panel_splitjs-0.2.0/src/panel_splitjs/dist/panel-splitjs.bundle.js +1 -0
- panel_splitjs-0.2.0/src/panel_splitjs/models/multi_split.js +102 -0
- panel_splitjs-0.2.0/src/panel_splitjs/models/split.js +190 -0
- panel_splitjs-0.2.0/tests/conftest.py +18 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/tests/test_base.py +11 -10
- panel_splitjs-0.2.0/tests/test_ui.py +138 -0
- panel_splitjs-0.0.1a0/examples/apps/simple.py +0 -7
- panel_splitjs-0.0.1a0/src/panel_splitjs/__init__.py +0 -4
- panel_splitjs-0.0.1a0/src/panel_splitjs/base.py +0 -139
- panel_splitjs-0.0.1a0/src/panel_splitjs/dist/panel-splitjs.bundle.js +0 -1
- panel_splitjs-0.0.1a0/src/panel_splitjs/models/splitjs.js +0 -215
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.copier-answers.yml +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.gitattributes +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.github/CODEOWNERS +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.github/dependabot.yml +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.gitignore +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.pre-commit-config.yaml +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/.prettierrc +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/MANIFEST.in +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/docs/assets/logo.svg +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/docs/index.md +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/docs/reference/panel_splitjs.md +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/hatch_build.py +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/mkdocs.yml +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/__version.py +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/dist/css/arrow_down.svg +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/dist/css/arrow_left.svg +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/dist/css/arrow_right.svg +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/dist/css/arrow_up.svg +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/dist/css/handle.svg +0 -0
- {panel_splitjs-0.0.1a0 → panel_splitjs-0.2.0}/src/panel_splitjs/dist/css/handle_vertical.svg +0 -0
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
needs: [setup]
|
|
43
43
|
runs-on: "ubuntu-latest"
|
|
44
44
|
steps:
|
|
45
|
-
- uses: actions/checkout@v5
|
|
45
|
+
- uses: actions/checkout@v5.0.0
|
|
46
46
|
- name: Set up pixi
|
|
47
47
|
uses: prefix-dev/setup-pixi@v0.9.1
|
|
48
48
|
- uses: holoviz-dev/holoviz_tasks/pre-commit@v0
|
|
@@ -50,7 +50,7 @@ jobs:
|
|
|
50
50
|
if: needs.setup.outputs.img_change == 'true'
|
|
51
51
|
with:
|
|
52
52
|
extra_args: -a --hook-stage manual oxipng || true --
|
|
53
|
-
- uses: stefanzweifel/git-auto-commit-action@
|
|
53
|
+
- uses: stefanzweifel/git-auto-commit-action@v7
|
|
54
54
|
if: needs.setup.outputs.img_change == 'true'
|
|
55
55
|
with:
|
|
56
56
|
commit_message: "Optimize PNG images (lossless)"
|
|
@@ -64,7 +64,7 @@ jobs:
|
|
|
64
64
|
code_change: ${{ steps.filter.outputs.code }}
|
|
65
65
|
matrix: ${{ env.MATRIX }}
|
|
66
66
|
steps:
|
|
67
|
-
- uses: actions/checkout@v5
|
|
67
|
+
- uses: actions/checkout@v5.0.0
|
|
68
68
|
if: github.event_name != 'pull_request'
|
|
69
69
|
- name: Check for code changes
|
|
70
70
|
uses: dorny/paths-filter@v3
|
|
@@ -142,3 +142,41 @@ jobs:
|
|
|
142
142
|
with:
|
|
143
143
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
144
144
|
slug: panel-extensions/panel-splitjs
|
|
145
|
+
ui_test:
|
|
146
|
+
name: ui:${{ matrix.environment }}:${{ matrix.os }}
|
|
147
|
+
needs: [pre_commit, setup, pixi_lock]
|
|
148
|
+
runs-on: ${{ matrix.os }}
|
|
149
|
+
if: needs.setup.outputs.code_change == 'true'
|
|
150
|
+
strategy:
|
|
151
|
+
fail-fast: false
|
|
152
|
+
matrix:
|
|
153
|
+
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
|
|
154
|
+
environment: ["test-ui"]
|
|
155
|
+
timeout-minutes: 60
|
|
156
|
+
env:
|
|
157
|
+
PANEL_LOG_LEVEL: info
|
|
158
|
+
steps:
|
|
159
|
+
- uses: holoviz-dev/holoviz_tasks/pixi_install@v0
|
|
160
|
+
with:
|
|
161
|
+
environments: ${{ matrix.environment }}
|
|
162
|
+
install: false
|
|
163
|
+
id: install
|
|
164
|
+
- name: Test UI
|
|
165
|
+
run: |
|
|
166
|
+
# Create a .uicoveragerc file to set the concurrency library to greenlet
|
|
167
|
+
# https://github.com/microsoft/playwright-python/issues/313
|
|
168
|
+
echo "[run]\nconcurrency = greenlet" > .uicoveragerc
|
|
169
|
+
FAIL="--screenshot only-on-failure --full-page-screenshot --output ui_screenshots --tracing retain-on-failure"
|
|
170
|
+
pixi run -e ${{ matrix.environment }} test-ui $COV --cov-config=.uicoveragerc $FAIL
|
|
171
|
+
- name: Upload UI Screenshots
|
|
172
|
+
uses: actions/upload-artifact@v4
|
|
173
|
+
if: always()
|
|
174
|
+
with:
|
|
175
|
+
name: ui_screenshots_${{ runner.os }}
|
|
176
|
+
path: ./ui_screenshots
|
|
177
|
+
if-no-files-found: ignore
|
|
178
|
+
- name: Upload coverage reports to Codecov
|
|
179
|
+
uses: codecov/codecov-action@v5
|
|
180
|
+
with:
|
|
181
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
182
|
+
slug: panel-extensions/panel-splitjs
|
|
@@ -12,16 +12,16 @@ jobs:
|
|
|
12
12
|
pixi-update:
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
15
|
+
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.2.2
|
|
16
16
|
- name: Set up pixi
|
|
17
|
-
uses: prefix-dev/setup-pixi@
|
|
17
|
+
uses: prefix-dev/setup-pixi@194d461b21b6c5717c722ffc597fa91ed2ff29fa # v0.9.1
|
|
18
18
|
with:
|
|
19
19
|
run-install: false
|
|
20
20
|
- name: Update lockfiles
|
|
21
21
|
run: |
|
|
22
22
|
pixi update --json --no-install | pixi exec pixi-diff-to-markdown >> diff.md
|
|
23
23
|
- name: Create pull request
|
|
24
|
-
uses: peter-evans/create-pull-request@
|
|
24
|
+
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
|
25
25
|
with:
|
|
26
26
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
27
27
|
commit-message: Update pixi lockfile
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: panel-splitjs
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Provides split.js components for Panel.
|
|
5
5
|
Project-URL: Homepage, https://github.com/panel-extensions/panel-splitjs
|
|
6
6
|
Project-URL: Source, https://github.com/panel-extensions/panel-splitjs
|
|
@@ -22,7 +22,7 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries
|
|
23
23
|
Requires-Python: >=3.10
|
|
24
24
|
Requires-Dist: packaging
|
|
25
|
-
Requires-Dist: panel>=1.8.
|
|
25
|
+
Requires-Dist: panel>=1.8.3
|
|
26
26
|
Provides-Extra: dev
|
|
27
27
|
Requires-Dist: mkdocs-material; extra == 'dev'
|
|
28
28
|
Requires-Dist: mkdocstrings[python]; extra == 'dev'
|
|
@@ -48,13 +48,13 @@ A responsive, draggable split panel component for [Panel](https://panel.holoviz.
|
|
|
48
48
|
|
|
49
49
|
## Features
|
|
50
50
|
|
|
51
|
-
- **Draggable
|
|
52
|
-
- **Collapsible panels** -
|
|
51
|
+
- **Draggable dividers** - Resize panels by dragging the divider between them
|
|
52
|
+
- **Collapsible panels** - Collapse individual panels with toggle buttons
|
|
53
53
|
- **Flexible orientation** - Support for both horizontal and vertical splits
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
54
|
+
- **Size constraints** - Enforce minimum and maximum panel sizes
|
|
55
|
+
- **Snap behavior** - Smart snapping to minimum sizes for better UX
|
|
56
56
|
- **Customizable sizes** - Control initial and expanded panel sizes
|
|
57
|
-
- **
|
|
57
|
+
- **Multi-panel support** - Create layouts with 2+ panels using `MultiSplit`
|
|
58
58
|
|
|
59
59
|
## Installation
|
|
60
60
|
|
|
@@ -82,7 +82,8 @@ pn.extension()
|
|
|
82
82
|
split = Split(
|
|
83
83
|
pn.pane.Markdown("## Left Panel\nContent here"),
|
|
84
84
|
pn.pane.Markdown("## Right Panel\nMore content"),
|
|
85
|
-
sizes=(50, 50), # Equal sizing
|
|
85
|
+
sizes=(50, 50), # Equal sizing initially
|
|
86
|
+
min_size=100, # Minimum 100px for each panel
|
|
86
87
|
show_buttons=True
|
|
87
88
|
)
|
|
88
89
|
|
|
@@ -114,6 +115,7 @@ split = HSplit(
|
|
|
114
115
|
left_panel,
|
|
115
116
|
right_panel,
|
|
116
117
|
sizes=(70, 30), # 70% left, 30% right
|
|
118
|
+
min_size=200, # Minimum 200px for each panel
|
|
117
119
|
show_buttons=True
|
|
118
120
|
)
|
|
119
121
|
|
|
@@ -135,7 +137,7 @@ split = VSplit(
|
|
|
135
137
|
top_panel,
|
|
136
138
|
bottom_panel,
|
|
137
139
|
sizes=(60, 40),
|
|
138
|
-
|
|
140
|
+
min_size=150
|
|
139
141
|
)
|
|
140
142
|
|
|
141
143
|
split.servable()
|
|
@@ -149,72 +151,90 @@ from panel_splitjs import Split
|
|
|
149
151
|
|
|
150
152
|
pn.extension()
|
|
151
153
|
|
|
152
|
-
# Start with
|
|
154
|
+
# Start with right panel collapsed
|
|
153
155
|
split = Split(
|
|
154
156
|
pn.pane.Markdown("## Main Content"),
|
|
155
157
|
pn.pane.Markdown("## Collapsible Sidebar"),
|
|
156
|
-
collapsed=
|
|
158
|
+
collapsed=1, # 0 for first panel, 1 for second panel, None for not collapsed
|
|
157
159
|
expanded_sizes=(65, 35), # When expanded, 65% main, 35% sidebar
|
|
158
160
|
show_buttons=True,
|
|
159
|
-
|
|
161
|
+
min_size=(200, 200) # Minimum 200px for each panel
|
|
160
162
|
)
|
|
161
163
|
|
|
162
164
|
# Toggle collapse programmatically
|
|
163
165
|
button = pn.widgets.Button(name="Toggle Sidebar")
|
|
164
|
-
|
|
166
|
+
def toggle(event):
|
|
167
|
+
split.collapsed = None if split.collapsed == 1 else 1
|
|
168
|
+
button.on_click(toggle)
|
|
165
169
|
|
|
166
170
|
pn.Column(button, split).servable()
|
|
167
171
|
```
|
|
168
172
|
|
|
169
|
-
###
|
|
173
|
+
### Multi-Panel Split
|
|
170
174
|
|
|
171
175
|
```python
|
|
172
176
|
import panel as pn
|
|
173
|
-
from panel_splitjs import
|
|
177
|
+
from panel_splitjs import MultiSplit
|
|
174
178
|
|
|
175
179
|
pn.extension()
|
|
176
180
|
|
|
177
|
-
#
|
|
178
|
-
|
|
179
|
-
pn.pane.Markdown("##
|
|
180
|
-
pn.pane.Markdown("##
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
# Create a layout with three panels
|
|
182
|
+
multi = MultiSplit(
|
|
183
|
+
pn.pane.Markdown("## Panel 1"),
|
|
184
|
+
pn.pane.Markdown("## Panel 2"),
|
|
185
|
+
pn.pane.Markdown("## Panel 3"),
|
|
186
|
+
sizes=(30, 40, 30), # Three panels with custom sizing
|
|
187
|
+
min_size=100, # Minimum 100px for each panel
|
|
188
|
+
orientation="horizontal"
|
|
185
189
|
)
|
|
186
190
|
|
|
187
|
-
|
|
191
|
+
multi.servable()
|
|
188
192
|
```
|
|
189
193
|
|
|
190
194
|
## API Reference
|
|
191
195
|
|
|
192
196
|
### Split
|
|
193
197
|
|
|
194
|
-
The main split panel component with
|
|
198
|
+
The main split panel component for creating two-panel layouts with collapsible functionality.
|
|
195
199
|
|
|
196
200
|
**Parameters:**
|
|
197
201
|
|
|
198
202
|
- `objects` (list): Two Panel components to display in the split panels
|
|
199
|
-
- `collapsed` (
|
|
200
|
-
- `expanded_sizes` (tuple, default=(50, 50)): Percentage sizes when
|
|
201
|
-
- `
|
|
202
|
-
- `
|
|
203
|
-
- `orientation` (str, default="horizontal"): Either "horizontal" or "vertical"
|
|
204
|
-
- `show_buttons` (bool, default=
|
|
205
|
-
- `sizes` (tuple, default=(
|
|
203
|
+
- `collapsed` (int | None, default=None): Which panel is collapsed - `0` for first panel, `1` for second panel, `None` for not collapsed
|
|
204
|
+
- `expanded_sizes` (tuple, default=(50, 50)): Percentage sizes when both panels are expanded
|
|
205
|
+
- `max_size` (int | tuple, default=None): Maximum sizes in pixels - single value applies to both panels, tuple for individual sizes
|
|
206
|
+
- `min_size` (int | tuple, default=0): Minimum sizes in pixels - single value applies to both panels, tuple for individual sizes
|
|
207
|
+
- `orientation` (str, default="horizontal"): Either `"horizontal"` or `"vertical"`
|
|
208
|
+
- `show_buttons` (bool, default=True): Show collapse/expand toggle buttons on the divider
|
|
209
|
+
- `sizes` (tuple, default=(50, 50)): Initial percentage sizes of the panels
|
|
210
|
+
- `snap_size` (int, default=30): Snap to minimum size at this offset in pixels
|
|
211
|
+
- `step_size` (int, default=1): Step size in pixels at which panel sizes can be changed
|
|
206
212
|
|
|
207
213
|
### HSplit
|
|
208
214
|
|
|
209
215
|
Horizontal split panel (convenience class).
|
|
210
216
|
|
|
211
|
-
Same parameters as `Split` but `orientation` is locked to "horizontal"
|
|
217
|
+
Same parameters as `Split` but `orientation` is locked to `"horizontal"`.
|
|
212
218
|
|
|
213
219
|
### VSplit
|
|
214
220
|
|
|
215
221
|
Vertical split panel (convenience class).
|
|
216
222
|
|
|
217
|
-
Same parameters as `Split` but `orientation` is locked to "vertical"
|
|
223
|
+
Same parameters as `Split` but `orientation` is locked to `"vertical"`.
|
|
224
|
+
|
|
225
|
+
### MultiSplit
|
|
226
|
+
|
|
227
|
+
Multi-panel split component for creating layouts with three or more panels.
|
|
228
|
+
|
|
229
|
+
**Parameters:**
|
|
230
|
+
|
|
231
|
+
- `objects` (list): List of Panel components to display (3 or more)
|
|
232
|
+
- `max_size` (int | tuple, default=None): Maximum sizes in pixels - single value applies to all panels, tuple for individual sizes
|
|
233
|
+
- `min_size` (int | tuple, default=100): Minimum sizes in pixels - single value applies to all panels, tuple for individual sizes
|
|
234
|
+
- `orientation` (str, default="horizontal"): Either `"horizontal"` or `"vertical"`
|
|
235
|
+
- `sizes` (tuple, default=None): Initial percentage sizes of the panels (length must match number of objects)
|
|
236
|
+
- `snap_size` (int, default=30): Snap to minimum size at this offset in pixels
|
|
237
|
+
- `step_size` (int, default=1): Step size in pixels at which panel sizes can be changed
|
|
218
238
|
|
|
219
239
|
## Common Use Cases
|
|
220
240
|
|
|
@@ -232,10 +252,10 @@ output = pn.Column("# Output Area")
|
|
|
232
252
|
split = Split(
|
|
233
253
|
chat,
|
|
234
254
|
output,
|
|
235
|
-
collapsed=
|
|
255
|
+
collapsed=None, # Both panels visible
|
|
236
256
|
expanded_sizes=(50, 50),
|
|
237
257
|
show_buttons=True,
|
|
238
|
-
|
|
258
|
+
min_size=(300, 300) # Minimum 300px for each panel
|
|
239
259
|
)
|
|
240
260
|
|
|
241
261
|
split.servable()
|
|
@@ -260,16 +280,16 @@ visualization = pn.pane.Markdown("## Main Visualization Area")
|
|
|
260
280
|
split = Split(
|
|
261
281
|
controls,
|
|
262
282
|
visualization,
|
|
263
|
-
collapsed=
|
|
283
|
+
collapsed=0, # Start with controls collapsed
|
|
264
284
|
expanded_sizes=(25, 75),
|
|
265
285
|
show_buttons=True,
|
|
266
|
-
|
|
286
|
+
min_size=(250, 400) # Minimum sizes for each panel
|
|
267
287
|
)
|
|
268
288
|
|
|
269
289
|
split.servable()
|
|
270
290
|
```
|
|
271
291
|
|
|
272
|
-
### Responsive Layout
|
|
292
|
+
### Responsive Layout with Size Constraints
|
|
273
293
|
|
|
274
294
|
```python
|
|
275
295
|
import panel as pn
|
|
@@ -277,18 +297,73 @@ from panel_splitjs import Split
|
|
|
277
297
|
|
|
278
298
|
pn.extension()
|
|
279
299
|
|
|
280
|
-
# Automatically adjust to available space
|
|
281
300
|
split = Split(
|
|
282
301
|
pn.pane.Markdown("## Panel 1\nResponsive content"),
|
|
283
302
|
pn.pane.Markdown("## Panel 2\nMore responsive content"),
|
|
284
303
|
sizes=(50, 50),
|
|
285
|
-
|
|
304
|
+
min_size=200, # Minimum 200px per panel
|
|
305
|
+
max_size=800, # Maximum 800px per panel
|
|
306
|
+
snap_size=50, # Snap to min size when within 50px
|
|
286
307
|
show_buttons=True
|
|
287
308
|
)
|
|
288
309
|
|
|
289
310
|
split.servable()
|
|
290
311
|
```
|
|
291
312
|
|
|
313
|
+
### Complex Multi-Panel Layout
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
import panel as pn
|
|
317
|
+
from panel_splitjs import MultiSplit
|
|
318
|
+
|
|
319
|
+
pn.extension()
|
|
320
|
+
|
|
321
|
+
# Create a four-panel layout
|
|
322
|
+
sidebar = pn.Column("## Sidebar", pn.widgets.Select(options=["A", "B", "C"]))
|
|
323
|
+
main = pn.pane.Markdown("## Main Content Area")
|
|
324
|
+
detail = pn.pane.Markdown("## Detail Panel")
|
|
325
|
+
console = pn.pane.Markdown("## Console Output")
|
|
326
|
+
|
|
327
|
+
multi = MultiSplit(
|
|
328
|
+
sidebar,
|
|
329
|
+
main,
|
|
330
|
+
detail,
|
|
331
|
+
console,
|
|
332
|
+
sizes=(15, 40, 25, 20), # Custom sizing for each panel
|
|
333
|
+
min_size=(150, 300, 200, 150), # Individual minimums
|
|
334
|
+
orientation="horizontal"
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
multi.servable()
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Nested Splits
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
import panel as pn
|
|
344
|
+
from panel_splitjs import HSplit, VSplit
|
|
345
|
+
|
|
346
|
+
pn.extension()
|
|
347
|
+
|
|
348
|
+
# Create a nested layout: horizontal split with vertical split on right
|
|
349
|
+
left = pn.pane.Markdown("## Left Panel")
|
|
350
|
+
|
|
351
|
+
# Right side has a vertical split
|
|
352
|
+
top_right = pn.pane.Markdown("## Top Right")
|
|
353
|
+
bottom_right = pn.pane.Markdown("## Bottom Right")
|
|
354
|
+
right = VSplit(top_right, bottom_right, sizes=(60, 40))
|
|
355
|
+
|
|
356
|
+
# Main horizontal split
|
|
357
|
+
layout = HSplit(
|
|
358
|
+
left,
|
|
359
|
+
right,
|
|
360
|
+
sizes=(30, 70),
|
|
361
|
+
min_size=200
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
layout.servable()
|
|
365
|
+
```
|
|
366
|
+
|
|
292
367
|
## Development
|
|
293
368
|
|
|
294
369
|
This project is managed by [pixi](https://pixi.sh).
|
|
@@ -9,13 +9,13 @@ A responsive, draggable split panel component for [Panel](https://panel.holoviz.
|
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
- **Draggable
|
|
13
|
-
- **Collapsible panels** -
|
|
12
|
+
- **Draggable dividers** - Resize panels by dragging the divider between them
|
|
13
|
+
- **Collapsible panels** - Collapse individual panels with toggle buttons
|
|
14
14
|
- **Flexible orientation** - Support for both horizontal and vertical splits
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
15
|
+
- **Size constraints** - Enforce minimum and maximum panel sizes
|
|
16
|
+
- **Snap behavior** - Smart snapping to minimum sizes for better UX
|
|
17
17
|
- **Customizable sizes** - Control initial and expanded panel sizes
|
|
18
|
-
- **
|
|
18
|
+
- **Multi-panel support** - Create layouts with 2+ panels using `MultiSplit`
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
21
21
|
|
|
@@ -43,7 +43,8 @@ pn.extension()
|
|
|
43
43
|
split = Split(
|
|
44
44
|
pn.pane.Markdown("## Left Panel\nContent here"),
|
|
45
45
|
pn.pane.Markdown("## Right Panel\nMore content"),
|
|
46
|
-
sizes=(50, 50), # Equal sizing
|
|
46
|
+
sizes=(50, 50), # Equal sizing initially
|
|
47
|
+
min_size=100, # Minimum 100px for each panel
|
|
47
48
|
show_buttons=True
|
|
48
49
|
)
|
|
49
50
|
|
|
@@ -75,6 +76,7 @@ split = HSplit(
|
|
|
75
76
|
left_panel,
|
|
76
77
|
right_panel,
|
|
77
78
|
sizes=(70, 30), # 70% left, 30% right
|
|
79
|
+
min_size=200, # Minimum 200px for each panel
|
|
78
80
|
show_buttons=True
|
|
79
81
|
)
|
|
80
82
|
|
|
@@ -96,7 +98,7 @@ split = VSplit(
|
|
|
96
98
|
top_panel,
|
|
97
99
|
bottom_panel,
|
|
98
100
|
sizes=(60, 40),
|
|
99
|
-
|
|
101
|
+
min_size=150
|
|
100
102
|
)
|
|
101
103
|
|
|
102
104
|
split.servable()
|
|
@@ -110,72 +112,90 @@ from panel_splitjs import Split
|
|
|
110
112
|
|
|
111
113
|
pn.extension()
|
|
112
114
|
|
|
113
|
-
# Start with
|
|
115
|
+
# Start with right panel collapsed
|
|
114
116
|
split = Split(
|
|
115
117
|
pn.pane.Markdown("## Main Content"),
|
|
116
118
|
pn.pane.Markdown("## Collapsible Sidebar"),
|
|
117
|
-
collapsed=
|
|
119
|
+
collapsed=1, # 0 for first panel, 1 for second panel, None for not collapsed
|
|
118
120
|
expanded_sizes=(65, 35), # When expanded, 65% main, 35% sidebar
|
|
119
121
|
show_buttons=True,
|
|
120
|
-
|
|
122
|
+
min_size=(200, 200) # Minimum 200px for each panel
|
|
121
123
|
)
|
|
122
124
|
|
|
123
125
|
# Toggle collapse programmatically
|
|
124
126
|
button = pn.widgets.Button(name="Toggle Sidebar")
|
|
125
|
-
|
|
127
|
+
def toggle(event):
|
|
128
|
+
split.collapsed = None if split.collapsed == 1 else 1
|
|
129
|
+
button.on_click(toggle)
|
|
126
130
|
|
|
127
131
|
pn.Column(button, split).servable()
|
|
128
132
|
```
|
|
129
133
|
|
|
130
|
-
###
|
|
134
|
+
### Multi-Panel Split
|
|
131
135
|
|
|
132
136
|
```python
|
|
133
137
|
import panel as pn
|
|
134
|
-
from panel_splitjs import
|
|
138
|
+
from panel_splitjs import MultiSplit
|
|
135
139
|
|
|
136
140
|
pn.extension()
|
|
137
141
|
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
pn.pane.Markdown("##
|
|
141
|
-
pn.pane.Markdown("##
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
# Create a layout with three panels
|
|
143
|
+
multi = MultiSplit(
|
|
144
|
+
pn.pane.Markdown("## Panel 1"),
|
|
145
|
+
pn.pane.Markdown("## Panel 2"),
|
|
146
|
+
pn.pane.Markdown("## Panel 3"),
|
|
147
|
+
sizes=(30, 40, 30), # Three panels with custom sizing
|
|
148
|
+
min_size=100, # Minimum 100px for each panel
|
|
149
|
+
orientation="horizontal"
|
|
146
150
|
)
|
|
147
151
|
|
|
148
|
-
|
|
152
|
+
multi.servable()
|
|
149
153
|
```
|
|
150
154
|
|
|
151
155
|
## API Reference
|
|
152
156
|
|
|
153
157
|
### Split
|
|
154
158
|
|
|
155
|
-
The main split panel component with
|
|
159
|
+
The main split panel component for creating two-panel layouts with collapsible functionality.
|
|
156
160
|
|
|
157
161
|
**Parameters:**
|
|
158
162
|
|
|
159
163
|
- `objects` (list): Two Panel components to display in the split panels
|
|
160
|
-
- `collapsed` (
|
|
161
|
-
- `expanded_sizes` (tuple, default=(50, 50)): Percentage sizes when
|
|
162
|
-
- `
|
|
163
|
-
- `
|
|
164
|
-
- `orientation` (str, default="horizontal"): Either "horizontal" or "vertical"
|
|
165
|
-
- `show_buttons` (bool, default=
|
|
166
|
-
- `sizes` (tuple, default=(
|
|
164
|
+
- `collapsed` (int | None, default=None): Which panel is collapsed - `0` for first panel, `1` for second panel, `None` for not collapsed
|
|
165
|
+
- `expanded_sizes` (tuple, default=(50, 50)): Percentage sizes when both panels are expanded
|
|
166
|
+
- `max_size` (int | tuple, default=None): Maximum sizes in pixels - single value applies to both panels, tuple for individual sizes
|
|
167
|
+
- `min_size` (int | tuple, default=0): Minimum sizes in pixels - single value applies to both panels, tuple for individual sizes
|
|
168
|
+
- `orientation` (str, default="horizontal"): Either `"horizontal"` or `"vertical"`
|
|
169
|
+
- `show_buttons` (bool, default=True): Show collapse/expand toggle buttons on the divider
|
|
170
|
+
- `sizes` (tuple, default=(50, 50)): Initial percentage sizes of the panels
|
|
171
|
+
- `snap_size` (int, default=30): Snap to minimum size at this offset in pixels
|
|
172
|
+
- `step_size` (int, default=1): Step size in pixels at which panel sizes can be changed
|
|
167
173
|
|
|
168
174
|
### HSplit
|
|
169
175
|
|
|
170
176
|
Horizontal split panel (convenience class).
|
|
171
177
|
|
|
172
|
-
Same parameters as `Split` but `orientation` is locked to "horizontal"
|
|
178
|
+
Same parameters as `Split` but `orientation` is locked to `"horizontal"`.
|
|
173
179
|
|
|
174
180
|
### VSplit
|
|
175
181
|
|
|
176
182
|
Vertical split panel (convenience class).
|
|
177
183
|
|
|
178
|
-
Same parameters as `Split` but `orientation` is locked to "vertical"
|
|
184
|
+
Same parameters as `Split` but `orientation` is locked to `"vertical"`.
|
|
185
|
+
|
|
186
|
+
### MultiSplit
|
|
187
|
+
|
|
188
|
+
Multi-panel split component for creating layouts with three or more panels.
|
|
189
|
+
|
|
190
|
+
**Parameters:**
|
|
191
|
+
|
|
192
|
+
- `objects` (list): List of Panel components to display (3 or more)
|
|
193
|
+
- `max_size` (int | tuple, default=None): Maximum sizes in pixels - single value applies to all panels, tuple for individual sizes
|
|
194
|
+
- `min_size` (int | tuple, default=100): Minimum sizes in pixels - single value applies to all panels, tuple for individual sizes
|
|
195
|
+
- `orientation` (str, default="horizontal"): Either `"horizontal"` or `"vertical"`
|
|
196
|
+
- `sizes` (tuple, default=None): Initial percentage sizes of the panels (length must match number of objects)
|
|
197
|
+
- `snap_size` (int, default=30): Snap to minimum size at this offset in pixels
|
|
198
|
+
- `step_size` (int, default=1): Step size in pixels at which panel sizes can be changed
|
|
179
199
|
|
|
180
200
|
## Common Use Cases
|
|
181
201
|
|
|
@@ -193,10 +213,10 @@ output = pn.Column("# Output Area")
|
|
|
193
213
|
split = Split(
|
|
194
214
|
chat,
|
|
195
215
|
output,
|
|
196
|
-
collapsed=
|
|
216
|
+
collapsed=None, # Both panels visible
|
|
197
217
|
expanded_sizes=(50, 50),
|
|
198
218
|
show_buttons=True,
|
|
199
|
-
|
|
219
|
+
min_size=(300, 300) # Minimum 300px for each panel
|
|
200
220
|
)
|
|
201
221
|
|
|
202
222
|
split.servable()
|
|
@@ -221,16 +241,16 @@ visualization = pn.pane.Markdown("## Main Visualization Area")
|
|
|
221
241
|
split = Split(
|
|
222
242
|
controls,
|
|
223
243
|
visualization,
|
|
224
|
-
collapsed=
|
|
244
|
+
collapsed=0, # Start with controls collapsed
|
|
225
245
|
expanded_sizes=(25, 75),
|
|
226
246
|
show_buttons=True,
|
|
227
|
-
|
|
247
|
+
min_size=(250, 400) # Minimum sizes for each panel
|
|
228
248
|
)
|
|
229
249
|
|
|
230
250
|
split.servable()
|
|
231
251
|
```
|
|
232
252
|
|
|
233
|
-
### Responsive Layout
|
|
253
|
+
### Responsive Layout with Size Constraints
|
|
234
254
|
|
|
235
255
|
```python
|
|
236
256
|
import panel as pn
|
|
@@ -238,18 +258,73 @@ from panel_splitjs import Split
|
|
|
238
258
|
|
|
239
259
|
pn.extension()
|
|
240
260
|
|
|
241
|
-
# Automatically adjust to available space
|
|
242
261
|
split = Split(
|
|
243
262
|
pn.pane.Markdown("## Panel 1\nResponsive content"),
|
|
244
263
|
pn.pane.Markdown("## Panel 2\nMore responsive content"),
|
|
245
264
|
sizes=(50, 50),
|
|
246
|
-
|
|
265
|
+
min_size=200, # Minimum 200px per panel
|
|
266
|
+
max_size=800, # Maximum 800px per panel
|
|
267
|
+
snap_size=50, # Snap to min size when within 50px
|
|
247
268
|
show_buttons=True
|
|
248
269
|
)
|
|
249
270
|
|
|
250
271
|
split.servable()
|
|
251
272
|
```
|
|
252
273
|
|
|
274
|
+
### Complex Multi-Panel Layout
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
import panel as pn
|
|
278
|
+
from panel_splitjs import MultiSplit
|
|
279
|
+
|
|
280
|
+
pn.extension()
|
|
281
|
+
|
|
282
|
+
# Create a four-panel layout
|
|
283
|
+
sidebar = pn.Column("## Sidebar", pn.widgets.Select(options=["A", "B", "C"]))
|
|
284
|
+
main = pn.pane.Markdown("## Main Content Area")
|
|
285
|
+
detail = pn.pane.Markdown("## Detail Panel")
|
|
286
|
+
console = pn.pane.Markdown("## Console Output")
|
|
287
|
+
|
|
288
|
+
multi = MultiSplit(
|
|
289
|
+
sidebar,
|
|
290
|
+
main,
|
|
291
|
+
detail,
|
|
292
|
+
console,
|
|
293
|
+
sizes=(15, 40, 25, 20), # Custom sizing for each panel
|
|
294
|
+
min_size=(150, 300, 200, 150), # Individual minimums
|
|
295
|
+
orientation="horizontal"
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
multi.servable()
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Nested Splits
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
import panel as pn
|
|
305
|
+
from panel_splitjs import HSplit, VSplit
|
|
306
|
+
|
|
307
|
+
pn.extension()
|
|
308
|
+
|
|
309
|
+
# Create a nested layout: horizontal split with vertical split on right
|
|
310
|
+
left = pn.pane.Markdown("## Left Panel")
|
|
311
|
+
|
|
312
|
+
# Right side has a vertical split
|
|
313
|
+
top_right = pn.pane.Markdown("## Top Right")
|
|
314
|
+
bottom_right = pn.pane.Markdown("## Bottom Right")
|
|
315
|
+
right = VSplit(top_right, bottom_right, sizes=(60, 40))
|
|
316
|
+
|
|
317
|
+
# Main horizontal split
|
|
318
|
+
layout = HSplit(
|
|
319
|
+
left,
|
|
320
|
+
right,
|
|
321
|
+
sizes=(30, 70),
|
|
322
|
+
min_size=200
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
layout.servable()
|
|
326
|
+
```
|
|
327
|
+
|
|
253
328
|
## Development
|
|
254
329
|
|
|
255
330
|
This project is managed by [pixi](https://pixi.sh).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from panel_splitjs import MultiSplit
|
|
2
|
+
from panel_material_ui import Button, Column, Paper, Row
|
|
3
|
+
|
|
4
|
+
paper_opts = dict(elevation=3, margin=10, sizing_mode="stretch_both")
|
|
5
|
+
|
|
6
|
+
add = Button(label="Add item", on_click=lambda _: ms.append(Paper("Added", **paper_opts)))
|
|
7
|
+
insert = Button(label="Insert item", on_click=lambda _: ms.insert(2, Paper("Inserted", **paper_opts)))
|
|
8
|
+
|
|
9
|
+
ms = MultiSplit(
|
|
10
|
+
Paper("Foo", **paper_opts),
|
|
11
|
+
Paper("Bar", **paper_opts),
|
|
12
|
+
Paper("Baz", **paper_opts),
|
|
13
|
+
Paper("Qux", **paper_opts),
|
|
14
|
+
Paper("Quux", **paper_opts),
|
|
15
|
+
sizes=(20, 30, 20, 10, 20),
|
|
16
|
+
min_size=100,
|
|
17
|
+
sizing_mode="stretch_width",
|
|
18
|
+
height=400
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
Column(Row(add, insert), ms).servable()
|