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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

This file contains the changelog for the PlutoExtras package. It follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.

## [0.7.16] - 2025-09-26

### Fixed
- Fixed problems with `ExtendedTableOfContents` with recent PlutoUI versions, also resolving an issue with `hide-heading` icon not appearing next to the corresponding heading in the ToC.
- Fixed styling issue with `BondsTable` in #19

### Added
- Added possibility of providing any valid object with a `MIME"text/html"` representation as description of the `@NTBond` macro.
- Added the possibility of simplifying application of `PlutoUI.Experimental.transformed_value` to the fields of an `@NTBond` using the `@tv` decorator (see the example notebook for details).

### Changed
- Changed the hiding behavior of the `Popout` container so that it stays displayed if the mouse is hovering over its contents even if not popped out


## [0.7.15] - 2025-04-22
Changelog was introduced in this version. Only changes w.r.t. version v0.7.14 are listed

Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
PlutoExtras = "ed5d0301-4775-4676-b788-cf71e66ff8ed"

[compat]
Documenter = "0.27"
Documenter = "1"
5 changes: 3 additions & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ using Documenter
DocMeta.setdocmeta!(PlutoExtras, :DocTestSetup, :(using PlutoExtras); recursive=true)

makedocs(;
modules= Module[],
modules= [PlutoExtras],
authors="Alberto Mengali <disberd@gmail.com>",
repo="https://github.com/disberd/PlutoExtras.jl/blob/{commit}{path}#{line}",
repo=Remotes.GitHub("disberd", "PlutoExtras.jl"),
sitename="PlutoExtras.jl",
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", "false") == "true",
edit_link="master",
assets=String[],
),
warnonly = true,
pages=[
"index.md",
"basic_widgets.md",
Expand Down
48 changes: 46 additions & 2 deletions docs/src/structbond.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The StructBondModule submodule of PlutoExtras defines and exports functionality
!!! note
The StructBondModule is currently not re-exported by PlutoExtras so it has to be explicitly used with `using PlutoExtras.StructBondModule`

Open the [structbond test notebook static html](https://rawcdn.githack.com/disberd/PlutoExtras.jl/0e3153d29d3b112f93507c042a35b8161a3bb661/html_exports/test_bondstable.jl.html) to see the look of the widgets exported.\
Open the [structbond module notebook static html](https://raw.githack.com/disberd/PlutoExtras.jl/assets/html/structbondmodule.html) to see the look of the widgets exported.\
Or open the [related notebook](https://github.com/disberd/PlutoExtras.jl/blob/master/test/notebooks/structbondmodule.jl) directy in Pluto to check their functionality in action!
!!! note
The notebook must be run from the original folder (`test/notebooks`) within the `PlutoExtras` package folder to properly load the PlutoExtras package
Expand Down Expand Up @@ -37,6 +37,49 @@ The macro simply create a [`StructBond`](@ref) wrapping the desired NamedTuple t
</video>
```

### Transforming the resulting NamedTuple
Since version v0.7.16, it is possible to `PlutoUI.Experimental.transformed_value` to transform the resulting value of the NamedTuple return by the `@NTBond` macro by either providing a third argument to the macro (acting on the full `NamedTuple`) or by using the `@tv` decorator directly when defining the bond for a specific field:

#### Transforming the full NamedTuple

When calling the macro with a third argument, this is interpreted as a function that is used to create a bond transformation using `PlutoUI.Experimental.transformed_value`.

This means that the two expressions below yield the same result:
```julia
@NTBond "WoW" begin
a = ("Description", Slider(1:10))
end x -> x.a + 2
```
and
```julia
PlutoUI.Experimental.transformed_value(x -> x.a + 2, @NTBond "WoW" begin
a = ("Description", Slider(1:10))
end)
```

!!! note
The synthax accepting a function to transformed the resulting NamedTuple also has a convenience shorthand where `_` can be used to represent the original bond value.

The above example could then also be written as:
```julia
@NTBond "WoW" begin
a = ("Description", Slider(1:10))
end _.a + 2
```

#### Transforming a single field

For the use directly at field level, it is sufficient to use the `@tv` decorator in place of the bond widget directly, using the following form and as shown in the image below:
```julia
@tv transform_function widget
```

![@tv decorator](https://raw.githubusercontent.com/disberd/PlutoExtras.jl/assets/imgs/ntbond_transform_fieldbond.png)

!!! note
The `@tv` decorator is not a macro actually defined within PlutoExtras, but is directly parsed during the macro expansion of `@NTBond`.


## StructBondSelect
Sometimes, one wants to create a more complex binding where the number of parameters to control a bond can vary depending on some other variable. The `StructBondSelect` can be of help in some of these cases, by providing a way to select out of a number of arbitrary `StructBonds` (which include `@NTBond`) by using a dropdown to select the one to be displayed and used for generating the `StructBondSelect` widget's output.

Expand All @@ -52,7 +95,7 @@ The `description` kwarg can be used to customize the text in the widget containe

```@raw html
<video controls=true>
<source src="https://private-user-images.githubusercontent.com/12846528/435671114-795c3da9-ede1-4f96-a971-038a8ce506c3.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDUyNDA0ODgsIm5iZiI6MTc0NTI0MDE4OCwicGF0aCI6Ii8xMjg0NjUyOC80MzU2NzExMTQtNzk1YzNkYTktZWRlMS00Zjk2LWE5NzEtMDM4YThjZTUwNmMzLm1wND9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA0MjElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNDIxVDEyNTYyOFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTdmMWZmYjJhNTIyNGI5NDFmMDk3ODcxZWU2ZTE3Njk1MGYyZDk2MmQ5ZTI1NzEyNzJlZTZkNjUxMDhkNDI4ODYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.XXQ6NJLqc1MoBVQXY9MNageij2F0DhsEzvQpHSP9F4A" type="video/mp4">
<source src="https://raw.githubusercontent.com/disberd/PlutoExtras.jl/assets/videos/structbond_select_example.mp4" type="video/mp4">
</video>
```

Expand Down Expand Up @@ -117,6 +160,7 @@ StructBondModule.@NTBond
StructBondModule.@BondsList
StructBondModule.popoutwrap
StructBondModule.BondTable
StructBondModule.StructBondSelect
```

### Secondary/Advanced
Expand Down
17 changes: 0 additions & 17 deletions html_exports/test_bondstable.jl.html

This file was deleted.

22 changes: 4 additions & 18 deletions src/extended_toc.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ function propagate_state(div, state) {
}

// Floating UI functionality
const floating_ui = await import('https://esm.sh/@floating-ui/dom')
const floating_ui = await import('https://esm.sh/@floating-ui/dom@1.7.4')

// Cell attributes modification
function has_cell_attribute(cell_id, attr) {
Expand Down Expand Up @@ -374,15 +374,8 @@ function repositionTooltip(e) {
computePosition(ref, tooltip, {
placement: "left",
strategy: "fixed",
middleware: [
offset({
mainAxis: 0, // No offset along the main axis (left/right)
crossAxis: -scrollTop, // Compensate for vertical scroll
alignmentAxis: 0 // No alignment offset
})
]
}).then(pos => {
tooltip.style.top = pos.y + "px"
tooltip.style.top = pos.y - scrollTop + "px"
})
}

Expand Down Expand Up @@ -725,7 +718,7 @@ header.addEventListener('click', e => {
})

header.addEventListener('mouseenter', (e) => {
const { computePosition, offset } = floating_ui
const { computePosition } = floating_ui

// Get the scroll container - this is crucial for proper offset calculation
const scrollContainer = document.querySelector('main') || document.documentElement
Expand All @@ -734,15 +727,8 @@ header.addEventListener('mouseenter', (e) => {
computePosition(header, header_container, {
placement: "left",
strategy: "fixed",
middleware: [
offset({
mainAxis: 0, // No offset along the main axis (left/right)
crossAxis: -scrollTop, // Compensate for vertical scroll
alignmentAxis: 0 // No alignment offset
})
]
}).then(pos => {
header_container.style.top = pos.y + "px"
header_container.style.top = pos.y - scrollTop + "px"
// header_container.style.left = pos.x + "px"
// header_container.style.right = `calc(1rem + min(80vw, 300px))`
})
Expand Down
68 changes: 3 additions & 65 deletions src/structbond/basics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ function typehtml(T::Type)
])
"""
end
togglereactive_container(inner_bond; description = typedescription(T), title = "This generates a struct of type $(nameof(T))")
collapsible_togglereactive_container(inner_bond; description_html = typedescription(T), title = "This generates a struct of type $(nameof(T))")
end

## ToggleReactiveContainer ##
# This is a helperfunction to create a togglereactive container around a bond with collapsible content
function togglereactive_container(inner_bond; description, title, classes = String[])
function collapsible_togglereactive_container(inner_bond; description = "", description_html, title, classes = String[])
ToggleReactiveBond(wrapped() do Child
@htl("""
$(Child(inner_bond))
Expand All @@ -144,71 +144,9 @@ function togglereactive_container(inner_bond; description, title, classes = Stri
const header = trc.firstElementChild
const desc = header.querySelector('.description')
desc.setAttribute('title', $title)

// add the collapse button
const collapse_btn = html`<span class='collapse'>`
header.insertAdjacentElement('afterbegin', collapse_btn)

trc.collapse = () => {
trc.classList.toggle('collapsed')
}

collapse_btn.onclick = (e) => trc.collapse()

</script>
<style>
togglereactive-container field-html {
display: contents;
}
togglereactive-container {
display: grid;
grid-template-columns: 1fr minmax(min(50px, 100%), .4fr);
grid-auto-rows: fit-content(40px);
justify-items: center;
align-items: center;
row-gap: 5px;
/* The flex below is needed in some weird cases where the bond is display flex and the child becomes small. */
flex: 1;
}
togglereactive-header {
grid-column: 1 / -1;
display: flex;
}
togglereactive-header > .collapse {
--size: 17px;
display: block;
align-self: stretch;
background-size: var(--size) var(--size);
background-repeat: no-repeat;
background-position: center;
width: var(--size);
filter: var(--image-filters);
background-image: url(https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/chevron-down.svg);
cursor: pointer;
}
togglereactive-container.collapsed > togglereactive-header > .collapse {
background-image: url(https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/chevron-forward.svg);
}
togglereactive-header {
display: flex;
align-items: stretch;
width: 100%;
}
togglereactive-header > .description {
text-align: center;
flex-grow: 1;
font-size: 18px;
font-weight: 600;
}
togglereactive-header > .toggle {
align-self: center
}
togglereactive-container.collapsed togglereactive-header + * {
display: none !important;
}
</style>
""")
end; description, classes)
end; description, description_html, classes = String["collapsible", classes...])
end

### Constructor ###
Expand Down
2 changes: 1 addition & 1 deletion src/structbond/css/bondslist.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,6 @@ bondslist-container {
align-items: center;
row-gap: 5px;
}
bondstable-container bondslist-container {
bondtable-container bondslist-container {
display: contents;
}
1 change: 1 addition & 0 deletions src/structbond/css/popout.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ popout-contents {
padding: 8px;
}
popout-container.popped > popout-contents,
popout-container.contents-hover > popout-contents,
popout-container.header-hover > popout-contents {
display: block;
position: fixed;
Expand Down
4 changes: 2 additions & 2 deletions src/structbond/css/structbondselect.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ structbond-select > struct-bond.hidden {

structbond-select,
structbond-select > struct-bond,
structbond-select togglereactive-container {
structbond-select togglereactive-container.collapsible {
display: contents;
}

Expand All @@ -20,7 +20,7 @@ structbond-select > .selector .description {
color: var(--pluto-output-color, #404040);
}

structbond-select >struct-bond>togglereactive-container>togglereactive-header {
structbond-select >struct-bond>togglereactive-container.collapsible>togglereactive-header {
display: none;
}

Expand Down
77 changes: 71 additions & 6 deletions src/structbond/css/togglereactive.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
togglereactive-header > .toggle {
togglereactive-header>.toggle {
cursor: pointer;
--size: 15px;
position: relative;
Expand All @@ -8,13 +8,15 @@ togglereactive-header > .toggle {
background: #c6c6c6;
outline: none;
border-radius: calc(var(--size)/2);
box-shadow: inset 0 0 calc(var(--size)/8) rgba(0,0,0,.2);
box-shadow: inset 0 0 calc(var(--size)/8) rgba(0, 0, 0, .2);
margin: 0 10px;
}
togglereactive-header > .toggle:checked {

togglereactive-header>.toggle:checked {
background: #4BD865;
}
togglereactive-header > .toggle:before {

togglereactive-header>.toggle:before {
content: '';
position: absolute;
width: var(--size);
Expand All @@ -24,9 +26,72 @@ togglereactive-header > .toggle:before {
left: 0px;
background: #fff;
transform: scale(1.1);
box-shadow: 0 calc(var(--size)/20) calc(var(--size)/8) rgba(0,0,0,.2);
box-shadow: 0 calc(var(--size)/20) calc(var(--size)/8) rgba(0, 0, 0, .2);
transition: .1s;
}
togglereactive-header > .toggle:checked:before {

togglereactive-header>.toggle:checked:before {
left: var(--size)
}

togglereactive-container.collapsible field-html {
display: contents;
}

togglereactive-container.collapsible {
display: grid;
grid-template-columns: 1fr minmax(min(50px, 100%), .4fr);
grid-auto-rows: fit-content(40px);
justify-items: center;
align-items: center;
row-gap: 5px;
/* The flex below is needed in some weird cases where the bond is display flex and the child becomes small. */
flex: 1;
}

togglereactive-container.collapsible>togglereactive-header {
grid-column: 1 / -1;
display: flex;
}

.collapse-btn {
display: none;
}

togglereactive-container.collapsible>togglereactive-header>.collapse-btn {
--size: 17px;
display: block;
align-self: stretch;
background-size: var(--size) var(--size);
background-repeat: no-repeat;
background-position: center;
width: var(--size);
filter: var(--image-filters);
background-image: url(https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/chevron-down.svg);
cursor: pointer;
}

togglereactive-container.collapsible.collapsed>togglereactive-header>.collapse-btn {
background-image: url(https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/chevron-forward.svg);
}

togglereactive-container.collapsible>togglereactive-header {
display: flex;
align-items: stretch;
width: 100%;
}

togglereactive-container.collapsible>togglereactive-header>.description {
text-align: center;
flex-grow: 1;
font-size: 18px;
font-weight: 600;
}

togglereactive-container.collapsible>togglereactive-header>.toggle {
align-self: center
}

togglereactive-container.collapsible.collapsed togglereactive-header+* {
display: none !important;
}
Loading
Loading