diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index dfcf031..da1a408 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -25,7 +25,7 @@ jobs: matrix: version: - '1' - - '1.9' + - 'lts' os: - ubuntu-latest - windows-latest diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f130a4d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +This file contains the changelog for the PlutoExtras package. It follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format. + +## [Unreleased] +Changelog was introduced in this version. Only changes w.r.t. version v0.7.14 are listed + +### Added +- Added an option to the `@NTBond` macro to provide a function as third argument which is applied via `PlutoUI.Experimental.transformed_value` to the bond resulting from the `@NTBond` macro. +- Added a new exported type `StructBondSelect` to the module `StructBondModule` which simplifies creating a widget whose value may have different number of fields/parameters depending on a dropdown selector. +- The package now re-exports the names exported by its `StructBondModule` submodule. \ No newline at end of file diff --git a/Project.toml b/Project.toml index ad0fb73..e1f3584 100644 --- a/Project.toml +++ b/Project.toml @@ -22,4 +22,4 @@ Markdown = "1" PlutoUI = "0.7.51" REPL = "1" Random = "1" -julia = "1.9" +julia = "1.10" diff --git a/docs/src/structbond.md b/docs/src/structbond.md index 4b4cb5d..d5dd8f2 100644 --- a/docs/src/structbond.md +++ b/docs/src/structbond.md @@ -37,6 +37,25 @@ The macro simply create a [`StructBond`](@ref) wrapping the desired NamedTuple t ``` +## 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. + +This structure can be constructed with a vector of `StructBond` or `transformed_value(f, ::StructBond)` elements, and will take care of generating an appropriate widget to display and process only the selected one. + +The main signature of the constructor is the following: +```julia +StructBondSelect(els::Vector; description = "StructBondSelect", default_idx = 1, selector_text = "Selector") +``` + +The names to select upon will be taken from the `description` of the provided `StructBonds`, while the text displayed next to the _selector_ will default to `Selector` but can be customized with the `selector_text` kwarg to the constructor. +The `description` kwarg can be used to customize the text in the widget container (similar to the same kwarg in `StructBond` and to `@NTBond`). Finally, the `default_idx` should be an integer and will select which of the provided `StructBond`s will be selected as default when instantiating the widget. + +```@raw html + +``` + ## @BondsList In some cases, one does not want to have a single bond wrapping either a Structure or a NamedTuple because single independent bonds are more convenient. diff --git a/html_exports/test_bondstable.jl.html b/html_exports/test_bondstable.jl.html index f8ec184..44ed124 100755 --- a/html_exports/test_bondstable.jl.html +++ b/html_exports/test_bondstable.jl.html @@ -1,15 +1,17 @@ - -
\ No newline at end of file + + +
\ No newline at end of file diff --git a/notebooks/test_bondstable.jl b/notebooks/test_bondstable.jl index b6a2879..fbcf232 100644 --- a/notebooks/test_bondstable.jl +++ b/notebooks/test_bondstable.jl @@ -1,5 +1,5 @@ ### A Pluto.jl notebook ### -# v0.19.43 +# v0.20.5 #> custom_attrs = ["hide-enabled"] @@ -8,54 +8,55 @@ using InteractiveUtils # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). macro bind(def, element) - quote + #! format: off + return quote local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end local el = $(esc(element)) global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) el end + #! format: on end -# ╔═╡ 1ffc6489-6a3d-4bd1-94e5-4a843b614b20 -# ╠═╡ show_logs = false -# ╠═╡ skip_as_script = true -#=╠═╡ +# ╔═╡ 949ac1ef-c502-4e28-81ff-f99b0d19aa03 begin - import Pkg - Pkg.activate(Base.current_project()) - using Revise -end - ╠═╡ =# - -# ╔═╡ 5a4abd25-143a-49ea-a6b9-2b6c55e70a2c -begin - using PlutoExtras - using PlutoExtras.StructBondModule # This submodule has the features listed in this notebook - using PlutoUI + using PlutoExtras.StructBondModule + using PlutoExtras + using PlutoExtras: ExtendedTableOfContents, Editable using HypertextLiteral + using PlutoUI end -# ╔═╡ 5fbd1401-c7a1-4d4f-b16d-ac9d45e2fed5 +# ╔═╡ 9d4455af-96f1-46d7-a4f3-434495b11c8a md""" # Packages """ -# ╔═╡ cfa79196-9e04-4d0e-a6b1-5641e123f3d3 +# ╔═╡ 707175a9-d356-43cf-8038-620ebc401c93 ExtendedTableOfContents() -# ╔═╡ 5a9b27c3-df02-415c-87bd-06ebd3c9d246 +# ╔═╡ cbfc6eec-8991-4a9c-ada0-295c8052854d +# html""" +# +# """ + +# ╔═╡ 4843983c-df64-4b94-8634-7a10d9423a70 md""" # StructBond """ -# ╔═╡ 9da65874-608a-4c84-a0e6-813c624c07ba +# ╔═╡ a8995224-83c6-4f82-b5a5-87a6f86fc7a0 md""" Generating automatic widgets for custom structs is quite straightforward with the aid of the `@fielddata` macro and the `StructBond` type. The top-left arrow can be used to show-hide the field elements (useful inside a `BondTable`, shown below), while the green toggle on the top-right can be used to disable temporarily the synch between the JS widgets and the bond values in Pluto. """ -# ╔═╡ 9a9fc01e-c25d-11ed-0147-b155e63ffba7 +# ╔═╡ 9e3601f5-efc2-44e9-83d8-5b65ce7e9ccf begin """ struct ASD @@ -68,25 +69,51 @@ Base.@kwdef struct ASD d::String e::Int end +@typeasfield String = TextField() # String fields with no struct-specific default will use this @fielddata ASD begin a = (md"Markdown description, including ``LaTeX``", Slider(1:10)) b = (@htl("Field with HTML description"), Scrubbable(1:10)) c = ("Normal String Description", TextField()) - d = TextField() # No description, defaults to the docstring since it's present + # d has no ASD-specific custom bond, so it will use the field docstring as description and the default String widget as widget e = Slider(20:25) # No description, defaults to the fieldname as no docstring is present end asd_bond = @bind asd StructBond(ASD; description = "Custom Description") end -# ╔═╡ 1442a2eb-b38b-4757-b02c-96b599084889 +# ╔═╡ cdc0a7ad-a3ac-4270-b707-35b1939da276 asd -# ╔═╡ 65a3ed8e-6204-4aee-adfc-befe9ea5153e +# ╔═╡ fe891b4e-f440-4823-b43b-72572f6a6c12 +md""" +## Default Type Widgets +""" + +# ╔═╡ 86a80228-f495-43e8-b1d4-c93b7b52c8d8 +begin + @kwdef struct MAH + a::Int + end + @kwdef struct BOH + mah::MAH + end + + # This will make the default widget for an Int a Slider + @typeasfield Int = Slider(1:10) + # This will make the default widget for fields of type ASD a popout that wraps a StructBond{ASD} + @popoutasfield MAH + + @bind boh StructBond(BOH) +end + +# ╔═╡ 2358f686-1950-40f9-9d5c-dac2d98f4c24 +boh + +# ╔═╡ 49516374-f625-4a84-ac5c-f92497d45025 md""" # @NTBond """ -# ╔═╡ 8c8fd549-0afc-4452-bd6a-6564862a1d63 +# ╔═╡ 8cc53cd2-9114-4067-ab0b-37fd8cd79240 md""" Sometimes custom structs are not needed and it would be useful to just use the same nice bond structure of `StructBond` to simply create arbitrary NamedTuples. @@ -95,24 +122,77 @@ This is possible with the convenience macro `@NTBond` which can be called as sho The macro simply create a `StructBond` wrapping the desired NamedTuple type. """ -# ╔═╡ 9faf2258-3f2b-450c-bbfe-d8231e0e4d74 +# ╔═╡ 0db51d39-7c05-4e00-b951-7fe776a8e0f9 nt_bond = @bind nt @NTBond "My Fancy NTuple" begin a = ("Description", Slider(1:10)) b = (md"**Bold** field", Slider(1:10)) c = Slider(1:10) # No description, defaults to the name of the field end -# ╔═╡ c183e38f-84e3-4a1f-a631-6d1db39f1179 +# ╔═╡ e2b79a58-e66e-4d40-8673-418823753b38 nt -# ╔═╡ 8ab2af4c-92a2-429f-b641-95a028808ae5 +# ╔═╡ 466995a2-dfd4-4374-8339-bc0232039b27 +md""" +## transformed_value +""" + +# ╔═╡ 4cb128aa-7ad8-4d17-bced-36845703e6a8 +md""" +`@NTBond` is also quite useful in combination with `transformed_value` from `PlutoUI.Experimental`. For this reason, the `@NTBond` macro supports an optional third argument which shall be a function that when provided is directly used to transform the value of the widget. +""" + +# ╔═╡ 7855826e-ccaa-4c27-a060-f5ceb927bbe8 +@bind transformed_value_example @NTBond "Transformed!" begin + a = Slider(1:10) + b = Slider(1:10) +end nt -> nt.a + nt.b + +# ╔═╡ 1d5573ee-872e-4dfb-a785-1ac9e836ad98 +transformed_value_example + +# ╔═╡ f65b3231-f2b2-45dc-b72e-1ad3107083fc +md""" +# StructBondSelect +""" + +# ╔═╡ 67c0860b-b4c1-412d-870a-a4ce4987465e +md""" +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. + +This structure can be constructed with a vector of `StructBond` or `transformed_value(f, ::StructBond)` elements, and will take care of generating an appropriate widget to display and process only the selected one. + +The main signature of the constructor is the following: +```julia +StructBondSelect(els::Vector; description = "StructBondSelect", default_idx = 1, selector_text = "Selector") +``` + +The names to select upon will be taken from the `description` of the provided `StructBonds`, while the text displayed next to the _selector_ will default to `Selector` but can be customized with the `selector_text` kwarg to the constructor. +The `description` kwarg can be used to customize the text in the widget container (similar to the same kwarg in `StructBond` and to `@NTBond`). Finally, the `default_idx` should be an integer and will select which of the provided `StructBond`s will be selected as default when instantiating the widget. +""" + +# ╔═╡ bd5ec086-5156-4e7c-a70b-5ca9f089bb49 +sbs_bond = @bind sbs StructBondSelect([ + @NTBond "cos(arg)" begin + arg = Slider(range(0,1,100)) + end (nt -> cos(nt.arg)) # We need to wrap the function given to `@NTBond` in () to avoid parse problems when providing a function + @NTBond "atan(y,x)" begin + x = Slider(range(0,10; step = 0.1); default = 3, show_value=true) + y = Slider(range(0, 10; step = 0.1); default = 5, show_value=true) + end nt -> atan(nt.y, nt.x) +]; default_idx = 2, selector_text = "Options:") + +# ╔═╡ 7853cc7f-4e58-44d1-8d3b-f8d4745564e6 +sbs + +# ╔═╡ 9d23382c-cf35-4b20-a46c-0f4e2de17fc7 md""" # @BondsList """ -# ╔═╡ 29592194-2f89-49cc-9a20-7a8e9cd44ae9 +# ╔═╡ 959acb40-1fd6-43f5-a1a6-73a6ceaae1d7 md""" -In some cases, one does not want to have a single bond wrapping either a Structure or a NamedTuple, and single independent bonds are more convenient. +In some cases, one does not want to have a single bond wrapping either a Structure or a NamedTuple because single independent bonds are more convenient. `@BondsList` is a convenience macro to create an object of type `BondsList` which simply allow to add a description to separate bonds and group them all together in a table-like format equivalent to those of `StructBond`. @@ -123,22 +203,25 @@ In some cases, one does not want to have a single bond wrapping either a Structu See the example below for understanding the synthax. The header of a BondsList is shown in an orange background to easily differentiate it from `StructBond`. """ -# ╔═╡ 6091cdf4-c0ec-45f6-8aa0-d4faf6666d2d +# ╔═╡ 4d611425-c8e3-4bc3-912b-8bc0465363bc bl = @BondsList "My Group of Bonds" let tv = PlutoUI.Experimental.transformed_value # We use transformed_value to translate GHz to Hz in the bound variable `freq` "Frequency [GHz]" = @bind freq tv(x -> x * 1e9, Editable(20; suffix = " GHz")) md"Altitude ``h`` [m]" = @bind alt Scrubbable(100:10:200) end -# ╔═╡ 8d912297-925e-4c8b-98b8-19b43c9b29d7 +# ╔═╡ a5490a6b-dc11-42b7-87e0-d38870fc55e4 freq -# ╔═╡ 9a1baa3d-1420-473c-8380-bb5c23881e00 +# ╔═╡ 705e30fe-77a3-4b06-8b99-1807290edffb +alt + +# ╔═╡ 2ee7f26d-f383-4e7e-a69a-8fb72717467c md""" # Popout """ -# ╔═╡ 93255c24-d486-416d-aefc-7575feff7543 +# ╔═╡ 79beba88-932f-4147-b3a0-d821ef1bc1e2 md""" The structures above can also be used nested within one another. To facilitate accessing nested structures, one can use the `Popout` type. @@ -149,7 +232,7 @@ The StructBond table appears on hover upon the icon, can be made fixed by clicki A double click on the header of the popout hides it again: """ -# ╔═╡ 978f70ea-393e-4f3d-93fb-c5a83443d079 +# ╔═╡ 63d6c2df-a411-407c-af11-4f5d09fbb322 begin Base.@kwdef struct LOL a::Int @@ -161,28 +244,38 @@ end end end -# ╔═╡ 6c56c205-ac72-4556-b95e-b278e4b3f822 -popoutwrap(LOL) +# ╔═╡ 633029af-8cac-426e-b35c-c9fb3938b784 +@bind lol_pop popoutwrap(LOL) + +# ╔═╡ 065bad73-5fa8-4496-ba33-9e66940b5806 +lol_pop -# ╔═╡ 38535cbe-093d-4452-b2a9-999183199801 +# ╔═╡ 2073f11e-8196-4ebc-922f-5fa589e91797 md""" The ability to also wrap pre-existing bonds around StructBonds is convenient for organizing the various bonds one have in a `BondsList` or `BondTable` As an example, one can create a `BondsList` containing the two `StructBond` bonds generated at the beginning of this notebook with the follwing code. """ -# ╔═╡ 95ad9428-73f8-4f57-9185-9685b9a2123f +# ╔═╡ 811cf78b-e870-45bb-9173-89a3b3d495f5 blc = @BondsList "Popout Container" begin "Structure ASD" = Popout(asd_bond) "NamedTuple" = Popout(nt_bond) + "StructBondSelect" = Popout(sbs_bond) end -# ╔═╡ 373bc244-110a-43f8-aaa1-51b5cb751128 +# ╔═╡ e7d67662-77b3-482a-b032-8db4afbc01a6 +asd + +# ╔═╡ 996b4085-114c-48f4-9f90-8e637f29c06a +nt + +# ╔═╡ 3a066bf4-3466-469e-90d0-6b14be3ed8d5 md""" # BondTable """ -# ╔═╡ b3fb23b8-8652-469b-8d0c-0c6c2723b631 +# ╔═╡ 3213d977-7b65-43b0-a881-10fcc2523f14 md""" The final convenience structure provided by this module is the `BondTable`. It can be created to group a list of bonds in a floating table that stays on the left side of the notebook (similar to the TableOfContents of PlutoUI) and can be moved around and resized or hidden for convenience. @@ -191,7 +284,7 @@ The BondTable is intended to be used either with bonds containing `StructBond` o Here is an example of a bondtable containing all the examples of this notebook. """ -# ╔═╡ 75fc40a3-4231-4125-b52c-ad21f5b8a388 +# ╔═╡ 903fee67-6b23-41dc-a03d-f1040b696be6 BondTable([ asd_bond, nt_bond, @@ -199,29 +292,375 @@ BondTable([ blc ]; description = "My Bonds") +# ╔═╡ 08d711c0-e2cc-4444-94ca-0c4c3cfe901f +nt + +# ╔═╡ 03e9d75e-e6c9-4199-933b-2be306daf978 +asd + +# ╔═╡ 26d11600-2827-4e08-9195-109c8a8bddc3 +freq + +# ╔═╡ be2a7820-e194-4410-b00d-a9332b234ad6 +alt + +# ╔═╡ 00000000-0000-0000-0000-000000000001 +PLUTO_PROJECT_TOML_CONTENTS = """ +[deps] +HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" +PlutoExtras = "ed5d0301-4775-4676-b788-cf71e66ff8ed" +PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" +""" + +# ╔═╡ 00000000-0000-0000-0000-000000000002 +PLUTO_MANIFEST_TOML_CONTENTS = """ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.11.4" +manifest_format = "2.0" +project_hash = "0ca0567f5f0621438fc69800c85ba1867d3b56e4" + +[[deps.AbstractPlutoDingetjes]] +deps = ["Pkg"] +git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a" +uuid = "6e696c72-6542-2067-7265-42206c756150" +version = "1.3.2" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.2" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +version = "1.11.0" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +version = "1.11.0" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.5" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.1.1+0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +version = "1.11.0" + +[[deps.DocStringExtensions]] +git-tree-sha1 = "e7b7e6f178525d17c720ab9c081e4ef04429f860" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.4" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +version = "1.11.0" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.5" + +[[deps.Hyperscript]] +deps = ["Test"] +git-tree-sha1 = "179267cfa5e712760cd43dcae385d7ea90cc25a4" +uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" +version = "0.0.5" + +[[deps.HypertextLiteral]] +deps = ["Tricks"] +git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" +uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" +version = "0.9.5" + +[[deps.IOCapture]] +deps = ["Logging", "Random"] +git-tree-sha1 = "b6d6bfdd7ce25b0f9b2f6b3dd56b2673a66c8770" +uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" +version = "0.2.5" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +version = "1.11.0" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.4" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.6.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +version = "1.11.0" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.7.2+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +version = "1.11.0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +version = "1.11.0" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" +version = "1.11.0" + +[[deps.MIMEs]] +git-tree-sha1 = "c64d943587f7187e751162b3b84445bbbd79f691" +uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65" +version = "1.1.0" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +version = "1.11.0" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.6+0" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" +version = "1.11.0" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.12.12" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.27+1" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "44f6c1f38f77cafef9450ff93946c53bd9ca16ff" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.8.2" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.11.0" +weakdeps = ["REPL"] + + [deps.Pkg.extensions] + REPLExt = "REPL" + +[[deps.PlutoExtras]] +deps = ["AbstractPlutoDingetjes", "DocStringExtensions", "HypertextLiteral", "InteractiveUtils", "Markdown", "PlutoUI", "REPL", "Random"] +git-tree-sha1 = "3d3ec40825d248b096fd4afe780db72919c4b979" +repo-rev = "69805dacb340097257462ceb535f8ddeac406a90" +repo-url = "https://github.com/disberd/PlutoExtras.jl.git" +uuid = "ed5d0301-4775-4676-b788-cf71e66ff8ed" +version = "0.7.14" + +[[deps.PlutoUI]] +deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"] +git-tree-sha1 = "d3de2694b52a01ce61a036f18ea9c0f61c4a9230" +uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" +version = "0.7.62" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.1" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +version = "1.11.0" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +version = "1.11.0" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +version = "1.11.0" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" +version = "1.11.0" + +[[deps.Statistics]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.11.1" + + [deps.Statistics.extensions] + SparseArraysExt = ["SparseArrays"] + + [deps.Statistics.weakdeps] + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[deps.StyledStrings]] +uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b" +version = "1.11.0" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +version = "1.11.0" + +[[deps.Tricks]] +git-tree-sha1 = "6cae795a5a9313bbb4f60683f7263318fc7d1505" +uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" +version = "0.1.10" + +[[deps.URIs]] +git-tree-sha1 = "cbbebadbcc76c5ca1cc4b4f3b0614b3e603b5000" +uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +version = "1.5.2" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +version = "1.11.0" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.11.0+0" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.59.0+0" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" +""" + # ╔═╡ Cell order: -# ╠═1ffc6489-6a3d-4bd1-94e5-4a843b614b20 -# ╟─5fbd1401-c7a1-4d4f-b16d-ac9d45e2fed5 -# ╠═5a4abd25-143a-49ea-a6b9-2b6c55e70a2c -# ╠═cfa79196-9e04-4d0e-a6b1-5641e123f3d3 -# ╟─5a9b27c3-df02-415c-87bd-06ebd3c9d246 -# ╟─9da65874-608a-4c84-a0e6-813c624c07ba -# ╠═9a9fc01e-c25d-11ed-0147-b155e63ffba7 -# ╠═1442a2eb-b38b-4757-b02c-96b599084889 -# ╟─65a3ed8e-6204-4aee-adfc-befe9ea5153e -# ╟─8c8fd549-0afc-4452-bd6a-6564862a1d63 -# ╠═9faf2258-3f2b-450c-bbfe-d8231e0e4d74 -# ╠═c183e38f-84e3-4a1f-a631-6d1db39f1179 -# ╟─8ab2af4c-92a2-429f-b641-95a028808ae5 -# ╟─29592194-2f89-49cc-9a20-7a8e9cd44ae9 -# ╠═6091cdf4-c0ec-45f6-8aa0-d4faf6666d2d -# ╠═8d912297-925e-4c8b-98b8-19b43c9b29d7 -# ╟─9a1baa3d-1420-473c-8380-bb5c23881e00 -# ╟─93255c24-d486-416d-aefc-7575feff7543 -# ╠═978f70ea-393e-4f3d-93fb-c5a83443d079 -# ╠═6c56c205-ac72-4556-b95e-b278e4b3f822 -# ╟─38535cbe-093d-4452-b2a9-999183199801 -# ╠═95ad9428-73f8-4f57-9185-9685b9a2123f -# ╟─373bc244-110a-43f8-aaa1-51b5cb751128 -# ╟─b3fb23b8-8652-469b-8d0c-0c6c2723b631 -# ╠═75fc40a3-4231-4125-b52c-ad21f5b8a388 +# ╟─9d4455af-96f1-46d7-a4f3-434495b11c8a +# ╠═949ac1ef-c502-4e28-81ff-f99b0d19aa03 +# ╠═707175a9-d356-43cf-8038-620ebc401c93 +# ╠═cbfc6eec-8991-4a9c-ada0-295c8052854d +# ╟─4843983c-df64-4b94-8634-7a10d9423a70 +# ╟─a8995224-83c6-4f82-b5a5-87a6f86fc7a0 +# ╠═9e3601f5-efc2-44e9-83d8-5b65ce7e9ccf +# ╠═cdc0a7ad-a3ac-4270-b707-35b1939da276 +# ╟─fe891b4e-f440-4823-b43b-72572f6a6c12 +# ╠═86a80228-f495-43e8-b1d4-c93b7b52c8d8 +# ╠═2358f686-1950-40f9-9d5c-dac2d98f4c24 +# ╟─49516374-f625-4a84-ac5c-f92497d45025 +# ╟─8cc53cd2-9114-4067-ab0b-37fd8cd79240 +# ╠═0db51d39-7c05-4e00-b951-7fe776a8e0f9 +# ╠═e2b79a58-e66e-4d40-8673-418823753b38 +# ╟─466995a2-dfd4-4374-8339-bc0232039b27 +# ╟─4cb128aa-7ad8-4d17-bced-36845703e6a8 +# ╠═7855826e-ccaa-4c27-a060-f5ceb927bbe8 +# ╠═1d5573ee-872e-4dfb-a785-1ac9e836ad98 +# ╟─f65b3231-f2b2-45dc-b72e-1ad3107083fc +# ╟─67c0860b-b4c1-412d-870a-a4ce4987465e +# ╠═bd5ec086-5156-4e7c-a70b-5ca9f089bb49 +# ╠═7853cc7f-4e58-44d1-8d3b-f8d4745564e6 +# ╟─9d23382c-cf35-4b20-a46c-0f4e2de17fc7 +# ╟─959acb40-1fd6-43f5-a1a6-73a6ceaae1d7 +# ╠═4d611425-c8e3-4bc3-912b-8bc0465363bc +# ╠═a5490a6b-dc11-42b7-87e0-d38870fc55e4 +# ╠═705e30fe-77a3-4b06-8b99-1807290edffb +# ╟─2ee7f26d-f383-4e7e-a69a-8fb72717467c +# ╟─79beba88-932f-4147-b3a0-d821ef1bc1e2 +# ╠═63d6c2df-a411-407c-af11-4f5d09fbb322 +# ╠═633029af-8cac-426e-b35c-c9fb3938b784 +# ╠═065bad73-5fa8-4496-ba33-9e66940b5806 +# ╟─2073f11e-8196-4ebc-922f-5fa589e91797 +# ╠═811cf78b-e870-45bb-9173-89a3b3d495f5 +# ╠═e7d67662-77b3-482a-b032-8db4afbc01a6 +# ╠═996b4085-114c-48f4-9f90-8e637f29c06a +# ╟─3a066bf4-3466-469e-90d0-6b14be3ed8d5 +# ╟─3213d977-7b65-43b0-a881-10fcc2523f14 +# ╠═903fee67-6b23-41dc-a03d-f1040b696be6 +# ╠═08d711c0-e2cc-4444-94ca-0c4c3cfe901f +# ╠═03e9d75e-e6c9-4199-933b-2be306daf978 +# ╠═26d11600-2827-4e08-9195-109c8a8bddc3 +# ╠═be2a7820-e194-4410-b00d-a9332b234ad6 +# ╟─00000000-0000-0000-0000-000000000001 +# ╟─00000000-0000-0000-0000-000000000002 diff --git a/src/PlutoExtras.jl b/src/PlutoExtras.jl index 20e08e2..3738d66 100644 --- a/src/PlutoExtras.jl +++ b/src/PlutoExtras.jl @@ -17,7 +17,6 @@ function re_export(m::Module; modname = false) end export Editable, StringOnEnter # from basic_widgets.jl -export ToggleReactiveBond # From within StructBondModule include("helpers.jl") @@ -31,6 +30,7 @@ include("structbond/StructBondModule.jl") using .StructBondModule ## ReExports ## +re_export(StructBondModule) re_export.((ExtendedToc, LaTeXEqModule); modname = false) re_export(PlutoUI) diff --git a/src/structbond/StructBondModule.jl b/src/structbond/StructBondModule.jl index 149ea1a..d49acf0 100644 --- a/src/structbond/StructBondModule.jl +++ b/src/structbond/StructBondModule.jl @@ -4,11 +4,12 @@ module StructBondModule import AbstractPlutoDingetjes.Bonds import REPL: fielddoc using HypertextLiteral - using PlutoUI: combine + using PlutoUI: combine, Select, Experimental.TransformedValueNotebook.TransformedWidget, Experimental.transformed_value using ..PlutoExtras: cell_id_letters export BondTable, StructBond, @NTBond, @BondsList, Popout, @popoutasfield, @typeasfield, popoutwrap, @fieldbond, @fielddescription, @fielddata + export StructBondSelect export ToggleReactiveBond const CSS_Sheets = map(readdir(joinpath(@__DIR__, "css"))) do file @@ -20,5 +21,6 @@ module StructBondModule include("toggle_reactive.jl") include("basics.jl") include("main_definitions.jl") + include("structbond_select.jl") include("macro.jl") end \ No newline at end of file diff --git a/src/structbond/basics.jl b/src/structbond/basics.jl index 6c1cbbd..5b1dbc9 100644 --- a/src/structbond/basics.jl +++ b/src/structbond/basics.jl @@ -129,6 +129,12 @@ function typehtml(T::Type) ]) """ end + togglereactive_container(inner_bond; description = 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[]) ToggleReactiveBond(wrapped() do Child @htl(""" $(Child(inner_bond)) @@ -137,7 +143,7 @@ function typehtml(T::Type) const trc = currentScript.closest('togglereactive-container') const header = trc.firstElementChild const desc = header.querySelector('.description') - desc.setAttribute('title', "This generates a struct of type `$(nameof(T))`") + desc.setAttribute('title', $title) // add the collapse button const collapse_btn = html`` @@ -202,7 +208,7 @@ function typehtml(T::Type) } """) - end; description = typedescription(T)) + end; description, classes) end ### Constructor ### diff --git a/src/structbond/css/bondslist.css b/src/structbond/css/bondslist.css index 8514259..ac79219 100644 --- a/src/structbond/css/bondslist.css +++ b/src/structbond/css/bondslist.css @@ -7,7 +7,7 @@ bondslist-header:before { content: ""; display: inline-block; position: absolute; - top: 0px; + top: 1px; bottom: 0px; left: 0px; right: 0px; diff --git a/src/structbond/css/structbondselect.css b/src/structbond/css/structbondselect.css new file mode 100644 index 0000000..47b54a0 --- /dev/null +++ b/src/structbond/css/structbondselect.css @@ -0,0 +1,109 @@ +structbond-select togglereactive-container:first-of-type.no-popout:before { + display: none; +} + +structbond-select > struct-bond.hidden { + display: none; +} + +structbond-select, +structbond-select > struct-bond, +structbond-select togglereactive-container { + display: contents; +} + +structbond-select > .selector { + display: contents; +} + +structbond-select > .selector .description { + color: var(--pluto-output-color, #404040); +} + +structbond-select >struct-bond>togglereactive-container>togglereactive-header { + display: none; +} + +structbond-select > .selector select { + padding: 6px 12px; + border: 2px solid #e7e7e7; + border-radius: 6px; + background-color: var(--overlay-button-bg); + color: var(--pluto-output-color, #404040); + font-family: inherit; + cursor: pointer; + outline: none; + transition: border-color 0.2s; + text-align: center; + + /* Size constraints */ + max-width: 50px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + + /* Custom arrow styling */ + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + /* Light mode arrow - #404040 */ + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 8px center; + background-size: 16px; + padding-right: 32px; + min-width: 120px; +} + +structbond-select > .selector select:hover { + border-color: #d0d0d0; +} + +structbond-select > .selector select:focus { + border-color: #c0c0c0; +} + +@media (prefers-color-scheme: dark) { + structbond-select > .selector select { + border-color: #7d7d7d; + color: var(--pluto-output-color, #c4c4c4); + /* Dark mode arrow - #c4c4c4 */ + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c4c4c4' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e"); + } + + structbond-select > .selector select:hover { + border-color: #8a8a8a; + } + + structbond-select > .selector select:focus { + border-color: #7d7d7d; + } +} + +/* Add styling for dropdown options */ +structbond-select > .selector select option { + text-align: center; +} + +togglereactive-container.structbond-select togglereactive-header:before { + content: ""; + display: inline-block; + position: absolute; + top: 1px; + bottom: 0px; + left: 0px; + right: 0px; + z-index: -1; + background: #c8edd5; +} + +togglereactive-container.structbond-select togglereactive-header { + position: relative; + z-index: 10; +} + +@media (prefers-color-scheme: dark) { + togglereactive-container.structbond-select togglereactive-header:before { + background: #26582e; + } +} \ No newline at end of file diff --git a/src/structbond/macro.jl b/src/structbond/macro.jl index 4cadf5e..9ac4fae 100644 --- a/src/structbond/macro.jl +++ b/src/structbond/macro.jl @@ -258,6 +258,7 @@ end """ @NTBond description block + @NTBond description block transform_function Convenience macro to create a [`StructBond`](@ref) wrapping a NamedTuple with field names provided in the second argument `block`. Useful when one wants a quick way of generating a bond that creates a NamedTuple. An example usage is given in the code below: @@ -270,10 +271,29 @@ end ``` which will create a `NamedTuple{(:a, :b, :c)}` and assign it to variable `nt`. +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) +``` + See also: [`BondTable`](@ref), [`@NTBond`](@ref), [`@BondsList`](@ref), [`Popout`](@ref), [`popoutwrap`](@ref), [`@fielddata`](@ref), [`@fieldhtml`](@ref), [`@typeasfield`](@ref), [`@popoutasfield`](@ref) """ -macro NTBond(desc, block) - Meta.isexpr(block, [:let, :block]) || error("You can only give `let` or `begin` blocks to the `@NTBond` macro") +macro NTBond(desc, args...) + return _NTBond(desc, args...) +end + +function _NTBond(desc, block) + Meta.isexpr(block, [:let, :block]) || error("You can only give `let` or `begin` blocks to the `@NTBond` macro") # We will return a let block at the end anyhow to avoid method redefinitino errors in Pluto. We already create the two blocks composing the let bindings, block = if block.head == :let block.args @@ -292,7 +312,6 @@ macro NTBond(desc, block) Meta.isexpr(arg, :(=)) || error("Only expression of type `fieldname = fieldbond` or `fieldname = (fielddescription, fieldbond)` can be provided inside the block fed to @NTBond") push!(fields, arg.args[1]) end - Mod = @__MODULE__ T = NamedTuple{Tuple(fields)} out = _add_generic_field(T, block, [:fielddescription, :fieldbond]) # We add the generation of the StructBond @@ -300,6 +319,11 @@ macro NTBond(desc, block) Expr(:let, bindings, out) end +function _NTBond(desc, block, tv) + expr = _NTBond(desc, block) + return :($(transformed_value)($(esc(tv)), $expr)) +end + # BondsList # """ diff --git a/src/structbond/main_definitions.jl b/src/structbond/main_definitions.jl index 6ff16b4..fcf7d03 100644 --- a/src/structbond/main_definitions.jl +++ b/src/structbond/main_definitions.jl @@ -137,6 +137,7 @@ function Bonds.transform_value(t::StructBond{T}, from_js) where T transformed = Bonds.transform_value(t.widget, collect_reinterpret!(from_js)) typeconstructor(T)(transformed) end +Bonds.validate_value(::StructBond, from_js) = true # BondWithDescription # struct BondWithDescription diff --git a/src/structbond/structbond_select.jl b/src/structbond/structbond_select.jl new file mode 100644 index 0000000..6b99bce --- /dev/null +++ b/src/structbond/structbond_select.jl @@ -0,0 +1,155 @@ +# Valid elements for StructBondSelect + +valid_structbondselect_el(::StructBond) = true +valid_structbondselect_el(::TransformedWidget{<:StructBond}) = true +valid_structbondselect_el(::Any) = false + +extract_description(el::StructBond) = el.description +extract_description(el::TransformedWidget{<:StructBond}) = el.x.description + +""" + +A widget to select one subwidget out of an array of provided elements, which can be either `StructBond` or the resulting form `transformed_value(f, ::StructBond)`. + +This will show a selection dropdown to choose the subwidget to display and use for generating the StructBondSelect output when coupled with `@bind`. + +See the extended help below for a GIF example or the [docs page](https://disberd.github.io/PlutoExtras.jl/stable/structbond/#StructBondSelect) for a video one. + +## Constructor + +```julia +StructBondSelect(els::Vector[, selectors::Vector{String}]; description = "StructBondSelect", default_idx = 1, selector_text = "Selector") +``` + +### Arguments +- `els`: A vector of `StructBond` or `transformed_value(f, ::StructBond)` elements. +- `selectors`: A vector of strings to be used as the names to select upon. If not provided, the names will be taken from the `description` of the provided `StructBond` elements. + +### Keyword Arguments +- `description`: A string to be used as the description of the widget, defaults to `"StructBondSelect"`. +- `default_idx`: The index of the element to be selected by default for display/output, defaults to `1`. +- `selector_text`: The text to be displayed next to the selector dropdown, defaults to `"Selector"`. + +# Extended Help + +See this image for a visual example: +![structbondselect-example](https://private-user-images.githubusercontent.com/12846528/435671705-91ff7e4a-2b4c-4688-8f2b-ea53a622dd04.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDUyNDAzMTgsIm5iZiI6MTc0NTI0MDAxOCwicGF0aCI6Ii8xMjg0NjUyOC80MzU2NzE3MDUtOTFmZjdlNGEtMmI0Yy00Njg4LThmMmItZWE1M2E2MjJkZDA0LmdpZj9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA0MjElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNDIxVDEyNTMzOFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTYwMmI1ZTYyNGQ1NDMyZGNlZTE3NzljMjJlNWQyOTU5ODUyMDdiODkzYWQxNDRmNzEwZjYxZmEzNTgwZDUyYmEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.L9eC42c4-Gz0tpjzGgF95LhOvcrGAEPOkJ71HhiICrs) + +See also: [`StructBond`](@ref), [`@NTBond`](@ref) +""" +struct StructBondSelect + els::Vector + selectors::Vector{String} + selector_text::String + default_idx::Int + description::String +end + + +function StructBondSelect(els::Vector, selectors::Vector{String}; default_idx::Int = 1, description = "StructBondSelect", selector_text = "Selector") + all(valid_structbondselect_el, els) || throw(ArgumentError("All elements in els must be either a StructBond or a TransformedWidget{StructBond} (obtained from a StructBond using `PlutoUI.Experimental.transformed_value`)")) + default_idx > 0 && default_idx <= length(els) || throw(ArgumentError("default_idx must be a positive integer less than or equal to the number of `StructBond` elements provided as input.")) + StructBondSelect(els, selectors, selector_text, default_idx, description) +end + +function StructBondSelect(els::Vector; kwargs...) + all(valid_structbondselect_el, els) || throw(ArgumentError("All elements in els must be either a StructBond or a TransformedWidget{StructBond} (obtained from a StructBond using `PlutoUI.Experimental.transformed_value`)")) + StructBondSelect(els, map(extract_description, els); kwargs...) +end + +function StructBondSelect(ps::Vector{<:Pair{<:AbstractString, <:Any}}; kwargs...) + StructBondSelect(last.(ps), first.(ps); kwargs...) +end + +function Base.show(io::IO, mime::MIME"text/html", sb::StructBondSelect) + inner_bond = @htl(""" + + + $(sb.selector_text) + $(Select(sb.selectors, default = sb.selectors[sb.default_idx])) + + $([el for el in sb.els]) + + + + """) + show(io, mime, togglereactive_container(inner_bond; description = sb.description, title = "Use the selector to choose which StructBond to display and use.", classes = ["structbond-select"])) +end + +Bonds.initial_value(sbc::StructBondSelect) = Bonds.initial_value(sbc.els[sbc.default_idx]) + +function Bonds.validate_value(sbc::StructBondSelect, from_js) + idx, value = from_js |> first + idx <= length(sbc.els) && Bonds.validate_value(sbc.els[idx], value) +end + +function Bonds.transform_value(sbc::StructBondSelect, from_js) + idx, value = from_js |> first + Bonds.transform_value(sbc.els[idx], value) +end \ No newline at end of file diff --git a/src/structbond/toggle_reactive.jl b/src/structbond/toggle_reactive.jl index 5e70b02..f9dec5b 100644 --- a/src/structbond/toggle_reactive.jl +++ b/src/structbond/toggle_reactive.jl @@ -3,8 +3,9 @@ Base.@kwdef struct ToggleReactiveBond element::Any description::String secret_key::String=String(rand('a':'z', 10)) + classes::Vector{String}=String[] end -ToggleReactiveBond(element; description = "") = ToggleReactiveBond(;element, description) +ToggleReactiveBond(element; description = "", classes = String[]) = ToggleReactiveBond(;element, description, classes) # AbstractPlutoDingetjes Methods # function Bonds.initial_value(r::ToggleReactiveBond) @@ -22,7 +23,7 @@ end # Show Method # Base.show(io::IO, mime::MIME"text/html", r::ToggleReactiveBond) = show(io, mime, @htl(""" - + $(r.description) diff --git a/test/Project.toml b/test/Project.toml index 06c7ab7..d835c7c 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -3,5 +3,5 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781" -SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a" diff --git a/test/basics.jl b/test/basics.jl index 199e1c7..918f66d 100644 --- a/test/basics.jl +++ b/test/basics.jl @@ -1,18 +1,13 @@ -import Pluto: update_save_run!, update_run!, WorkspaceManager, ClientSession, -ServerSession, Notebook, Cell, project_relative_path, SessionActions, -load_notebook, Configuration, set_bond_values_reactive -using PlutoExtras -import PlutoExtras.AbstractPlutoDingetjes.Bonds -using Test - -function noerror(cell; verbose=true) - if cell.errored && verbose - @show cell.output.body - end - !cell.errored +@testsnippet setup_basics begin + using PlutoExtras + import PlutoExtras.AbstractPlutoDingetjes.Bonds + using Test + + include(joinpath(@__DIR__, "setup_helper.jl")) end -@testset "APD methods" begin + +@testitem "APD methods" setup=[setup_basics] begin ed = Editable(3) @test Base.get(ed) == 3 @test Bonds.initial_value(ed) == 3 @@ -30,22 +25,8 @@ end end -options = Configuration.from_flat_kwargs(; disable_writing_notebook_files=true, workspace_use_distributed_stdlib = true) -srcdir = normpath(@__DIR__, "./notebooks") -eval_in_nb(sn, expr) = WorkspaceManager.eval_fetch_in_workspace(sn, expr) - -function set_bond_value_sn(sn) - (session, notebook) = sn - function set_bond_value(name, value, is_first_value=false) - notebook.bonds[name] = Dict("value" => value) - set_bond_values_reactive(; session, notebook, bound_sym_names=[name], - is_first_values=[is_first_value], - run_async=false, - ) - end -end -@testset "Basic Widgets notebook" begin +@testitem "Basic Widgets notebook" setup=[setup_basics] begin ss = ServerSession(; options) path = joinpath(srcdir, "basic_widgets.jl") nb = SessionActions.open(ss, path; run_async=false) diff --git a/test/combinehtl_module.jl b/test/combinehtl_module.jl index b284b02..ba18512 100644 --- a/test/combinehtl_module.jl +++ b/test/combinehtl_module.jl @@ -1,15 +1,17 @@ -using Test -using PlutoExtras.PlutoCombineHTL.WithTypes -using PlutoExtras.PlutoCombineHTL: LOCAL_MODULE_URL -using PlutoExtras.HypertextLiteral -using PlutoExtras.PlutoCombineHTL: shouldskip, children, print_html, -script_id, inner_node, plutodefault, haslisteners, is_inside_pluto, hasreturn, -add_pluto_compat, hasinvalidation, displaylocation, returned_element, to_string, -formatted_contents -import PlutoExtras -using PlutoExtras.PlutoCombineHTL.AbstractPlutoDingetjes.Display - -@testset "make_script" begin +@testsnippet setup_combinehtl begin + using Test + using PlutoExtras.PlutoCombineHTL.WithTypes + using PlutoExtras.PlutoCombineHTL: LOCAL_MODULE_URL + using PlutoExtras.HypertextLiteral + using PlutoExtras.PlutoCombineHTL: shouldskip, children, print_html, + script_id, inner_node, plutodefault, haslisteners, is_inside_pluto, hasreturn, + add_pluto_compat, hasinvalidation, displaylocation, returned_element, to_string, + formatted_contents + import PlutoExtras + using PlutoExtras.PlutoCombineHTL.AbstractPlutoDingetjes.Display +end + +@testitem "make_script" setup=[setup_combinehtl] begin ds = make_script("test") @test make_script(ds) === ds @test ds isa DualScript @@ -131,7 +133,7 @@ using PlutoExtras.PlutoCombineHTL.AbstractPlutoDingetjes.Display @test pts.el isa DualScript end -@testset "make_node" begin +@testitem "make_node" setup=[setup_combinehtl] begin dn = make_node() @test dn isa DualNode @test shouldskip(dn, InsidePluto()) && shouldskip(dn, OutsidePluto()) @@ -216,7 +218,7 @@ end @test make_node(:both, "asd", "lol") === make_node("asd", "lol") end -@testset "Other Helpers" begin +@testitem "Other Helpers" setup=[setup_combinehtl] begin @test shouldskip(3) === false s = make_html(PlutoScript()) @test s isa ShowWithPrintHTML @@ -316,7 +318,7 @@ end @test_throws "You can't wrap object" ShowWithPrintHTML(PrintToScript(3)) end -@testset "Show methods" begin +@testitem "Show methods" setup=[setup_combinehtl] tags=[:before] begin ps = PlutoScript("asd", "lol") s = to_string(ps, MIME"text/javascript"()) hs = to_string(ps, MIME"text/html"()) @@ -500,29 +502,4 @@ end s_out = to_string(v, print_javascript; pluto = false) @test contains(s_in, "published object on Pluto") @test s_out === """["asd", "lol"]""" -end - -# import Pluto: update_save_run!, update_run!, WorkspaceManager, ClientSession, -# ServerSession, Notebook, Cell, project_relative_path, SessionActions, -# load_notebook, Configuration - -# function noerror(cell; verbose=true) -# if cell.errored && verbose -# @show cell.output.body -# end -# !cell.errored -# end - -# options = Configuration.from_flat_kwargs(; disable_writing_notebook_files=true, workspace_use_distributed_stdlib = true) -# srcdir = normpath(@__DIR__, "./notebooks") -# eval_in_nb(sn, expr) = WorkspaceManager.eval_fetch_in_workspace(sn, expr) - -# @testset "Script test notebook" begin -# ss = ServerSession(; options) -# path = joinpath(srcdir, "Script.jl") -# nb = SessionActions.open(ss, path; run_async=false) -# for cell in nb.cells -# @test noerror(cell) -# end -# SessionActions.shutdown(ss, nb) -# end \ No newline at end of file +end \ No newline at end of file diff --git a/test/latex.jl b/test/latex.jl index 4fd2ad9..111a58f 100644 --- a/test/latex.jl +++ b/test/latex.jl @@ -1,32 +1,9 @@ -import Pluto: update_save_run!, update_run!, WorkspaceManager, ClientSession, -ServerSession, Notebook, Cell, project_relative_path, SessionActions, -load_notebook, Configuration, set_bond_values_reactive -using PlutoExtras - -function noerror(cell; verbose=true) - if cell.errored && verbose - @show cell.output.body - end - !cell.errored -end - - -options = Configuration.from_flat_kwargs(; disable_writing_notebook_files=true, workspace_use_distributed_stdlib = true) -srcdir = normpath(@__DIR__, "./notebooks") -eval_in_nb(sn, expr) = WorkspaceManager.eval_fetch_in_workspace(sn, expr) - -function set_bond_value_sn(sn) - (session, notebook) = sn - function set_bond_value(name, value, is_first_value=false) - notebook.bonds[name] = Dict("value" => value) - set_bond_values_reactive(; session, notebook, bound_sym_names=[name], - is_first_values=[is_first_value], - run_async=false, - ) - end +@testsnippet setup_latex begin + using PlutoExtras + include(joinpath(@__DIR__, "setup_helper.jl")) end -@testset "Latex Equations notebook" begin +@testitem "Latex Equations notebook" setup=[setup_latex] begin ss = ServerSession(; options) path = joinpath(srcdir, "latex_equations.jl") nb = SessionActions.open(ss, path; run_async=false) diff --git a/test/notebooks/structbondmodule backup 1.jl b/test/notebooks/structbondmodule backup 1.jl new file mode 100644 index 0000000..3247da9 --- /dev/null +++ b/test/notebooks/structbondmodule backup 1.jl @@ -0,0 +1,490 @@ +### A Pluto.jl notebook ### +# v0.20.5 + +#> custom_attrs = ["hide-enabled"] + +using Markdown +using InteractiveUtils + +# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). +macro bind(def, element) + #! format: off + return quote + local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end + local el = $(esc(element)) + global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) + el + end + #! format: on +end + +# ╔═╡ 8db82e94-5c81-4c52-9228-7e22395fb68f +begin + using PlutoDevMacros +end + +# ╔═╡ 949ac1ef-c502-4e28-81ff-f99b0d19aa03 +@frompackage "../.." begin + using ^.StructBondModule + using ^: ExtendedTableOfContents, Editable + using >.HypertextLiteral + using >.PlutoUI +end + +# ╔═╡ 9d4455af-96f1-46d7-a4f3-434495b11c8a +md""" +# Packages +""" + +# ╔═╡ 707175a9-d356-43cf-8038-620ebc401c93 +ExtendedTableOfContents() + +# ╔═╡ cbfc6eec-8991-4a9c-ada0-295c8052854d +# html""" +# +# """ + +# ╔═╡ 4843983c-df64-4b94-8634-7a10d9423a70 +md""" +# StructBond +""" + +# ╔═╡ a8995224-83c6-4f82-b5a5-87a6f86fc7a0 +md""" +Generating automatic widgets for custom structs is quite straightforward with the aid of the `@fielddata` macro and the `StructBond` type. + +The top-left arrow can be used to show-hide the field elements (useful inside a `BondTable`, shown below), while the green toggle on the top-right can be used to disable temporarily the synch between the JS widgets and the bond values in Pluto. +""" + +# ╔═╡ 9e3601f5-efc2-44e9-83d8-5b65ce7e9ccf +begin +""" + struct ASD +""" +Base.@kwdef struct ASD + a::Int + b::Int + c::String + "This field is _special_" + d::String + e::Int +end +@typeasfield String = TextField() # String fields with no struct-specific default will use this +@fielddata ASD begin + a = (md"Markdown description, including ``LaTeX``", Slider(1:10)) + b = (@htl("Field with HTML description"), Scrubbable(1:10)) + c = ("Normal String Description", TextField()) + # d has no ASD-specific custom bond, so it will use the field docstring as description and the default String widget as widget + e = Slider(20:25) # No description, defaults to the fieldname as no docstring is present +end +asd_bond = @bind asd StructBond(ASD; description = "Custom Description") +end + +# ╔═╡ cdc0a7ad-a3ac-4270-b707-35b1939da276 +asd + +# ╔═╡ fe891b4e-f440-4823-b43b-72572f6a6c12 +md""" +## Default Type Widgets +""" + +# ╔═╡ 86a80228-f495-43e8-b1d4-c93b7b52c8d8 +begin + @kwdef struct MAH + a::Int + end + @kwdef struct BOH + mah::MAH + end + + # This will make the default widget for an Int a Slider + @typeasfield Int = Slider(1:10) + # This will make the default widget for fields of type ASD a popout that wraps a StructBond{ASD} + @popoutasfield MAH + + @bind boh StructBond(BOH) +end + +# ╔═╡ 2358f686-1950-40f9-9d5c-dac2d98f4c24 +boh + +# ╔═╡ 49516374-f625-4a84-ac5c-f92497d45025 +md""" +# @NTBond +""" + +# ╔═╡ 8cc53cd2-9114-4067-ab0b-37fd8cd79240 +md""" +Sometimes custom structs are not needed and it would be useful to just use the same nice bond structure of `StructBond` to simply create arbitrary NamedTuples. + +This is possible with the convenience macro `@NTBond` which can be called as shown below to create a nice display for an interactive bond creating an arbitrary NamedTuple. + +The macro simply create a `StructBond` wrapping the desired NamedTuple type. +""" + +# ╔═╡ 0db51d39-7c05-4e00-b951-7fe776a8e0f9 +nt_bond = @bind nt @NTBond "My Fancy NTuple" begin + a = ("Description", Slider(1:10)) + b = (md"**Bold** field", Slider(1:10)) + c = Slider(1:10) # No description, defaults to the name of the field +end + +# ╔═╡ e2b79a58-e66e-4d40-8673-418823753b38 +nt + +# ╔═╡ 9d23382c-cf35-4b20-a46c-0f4e2de17fc7 +md""" +# @BondsList +""" + +# ╔═╡ 959acb40-1fd6-43f5-a1a6-73a6ceaae1d7 +md""" +In some cases, one does not want to have a single bond wrapping either a Structure or a NamedTuple because single independent bonds are more convenient. + +`@BondsList` is a convenience macro to create an object of type `BondsList` which simply allow to add a description to separate bonds and group them all together in a table-like format equivalent to those of `StructBond`. + +!!! note + Unlike `StructBond`, a BondsList is already composed of bond created with `@bind` and it just groups them up with a description. The output of `@BondsList` is not supposed to be bound to a variable using `@bind`.\ + The bonds grouped in a BondsList still act and update independently from one another. + +See the example below for understanding the synthax. The header of a BondsList is shown in an orange background to easily differentiate it from `StructBond`. +""" + +# ╔═╡ 4d611425-c8e3-4bc3-912b-8bc0465363bc +bl = @BondsList "My Group of Bonds" let tv = PlutoUI.Experimental.transformed_value + # We use transformed_value to translate GHz to Hz in the bound variable `freq` + "Frequency [GHz]" = @bind freq tv(x -> x * 1e9, Editable(20; suffix = " GHz")) + md"Altitude ``h`` [m]" = @bind alt Scrubbable(100:10:200) +end + +# ╔═╡ a5490a6b-dc11-42b7-87e0-d38870fc55e4 +freq + +# ╔═╡ 705e30fe-77a3-4b06-8b99-1807290edffb +alt + +# ╔═╡ 2ee7f26d-f383-4e7e-a69a-8fb72717467c +md""" +# Popout +""" + +# ╔═╡ 79beba88-932f-4147-b3a0-d821ef1bc1e2 +md""" +The structures above can also be used nested within one another. To facilitate accessing nested structures, one can use the `Popout` type. + +In its simple form, you can give an instance of a StructBond, a bond wrapping a StructBond or a BondsList as input to Popout to create a table that is hidden behind a popup window. +If an instance present, but you want a custom type for which you have defined custom bonds and descriptions with `@fielddata` to appear as popout, you can use the function `popoutwrap(TYPE)` to generate a small icon which hides a popup containing the `StructBond` of the provided type `TYPE`. + +The StructBond table appears on hover upon the icon, can be made fixed by clicking on the icon and can then be moved around or resized. +A double click on the header of the popout hides it again: +""" + +# ╔═╡ 63d6c2df-a411-407c-af11-4f5d09fbb322 +begin +Base.@kwdef struct LOL + a::Int + b::Int +end +@fielddata LOL begin + a = (md"Wonder!", Slider(1:10)) + b = (@htl("Field B"), Scrubbable(1:10)) +end +end + +# ╔═╡ 633029af-8cac-426e-b35c-c9fb3938b784 +@bind lol_pop popoutwrap(LOL) + +# ╔═╡ 065bad73-5fa8-4496-ba33-9e66940b5806 +lol_pop + +# ╔═╡ 2073f11e-8196-4ebc-922f-5fa589e91797 +md""" +The ability to also wrap pre-existing bonds around StructBonds is convenient for organizing the various bonds one have in a `BondsList` or `BondTable` + +As an example, one can create a `BondsList` containing the two `StructBond` bonds generated at the beginning of this notebook with the follwing code. +""" + +# ╔═╡ 811cf78b-e870-45bb-9173-89a3b3d495f5 +blc = @BondsList "Popout Container" begin + "Structure ASD" = Popout(asd_bond) + "NamedTuple" = Popout(nt_bond) +end + +# ╔═╡ e7d67662-77b3-482a-b032-8db4afbc01a6 +asd + +# ╔═╡ 996b4085-114c-48f4-9f90-8e637f29c06a +nt + +# ╔═╡ 3a066bf4-3466-469e-90d0-6b14be3ed8d5 +md""" +# BondTable +""" + +# ╔═╡ 3213d977-7b65-43b0-a881-10fcc2523f14 +md""" +The final convenience structure provided by this module is the `BondTable`. It can be created to group a list of bonds in a floating table that stays on the left side of the notebook (similar to the TableOfContents of PlutoUI) and can be moved around and resized or hidden for convenience. + +The BondTable is intended to be used either with bonds containing `StructBond` or with `BondsList`. Future types with similar structure will also be added. + +Here is an example of a bondtable containing all the examples of this notebook. +""" + +# ╔═╡ 903fee67-6b23-41dc-a03d-f1040b696be6 +BondTable([ + asd_bond, + nt_bond, + bl, + blc +]; description = "My Bonds") + +# ╔═╡ 08d711c0-e2cc-4444-94ca-0c4c3cfe901f +nt + +# ╔═╡ 03e9d75e-e6c9-4199-933b-2be306daf978 +asd + +# ╔═╡ 26d11600-2827-4e08-9195-109c8a8bddc3 +freq + +# ╔═╡ be2a7820-e194-4410-b00d-a9332b234ad6 +alt + +# ╔═╡ 00000000-0000-0000-0000-000000000001 +PLUTO_PROJECT_TOML_CONTENTS = """ +[deps] +PlutoDevMacros = "a0499f29-c39b-4c5c-807c-88074221b949" + +[compat] +PlutoDevMacros = "~0.7.0" +""" + +# ╔═╡ 00000000-0000-0000-0000-000000000002 +PLUTO_MANIFEST_TOML_CONTENTS = """ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.11.4" +manifest_format = "2.0" +project_hash = "9088728c15a23247dcd792960c847dd5035deb53" + +[[deps.AbstractPlutoDingetjes]] +deps = ["Pkg"] +git-tree-sha1 = "0f748c81756f2e5e6854298f11ad8b2dfae6911a" +uuid = "6e696c72-6542-2067-7265-42206c756150" +version = "1.3.0" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.2" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +version = "1.11.0" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +version = "1.11.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +version = "1.11.0" + +[[deps.DocStringExtensions]] +deps = ["LibGit2"] +git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.3" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +version = "1.11.0" + +[[deps.HypertextLiteral]] +deps = ["Tricks"] +git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" +uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" +version = "0.9.5" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +version = "1.11.0" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.6.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +version = "1.11.0" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.7.2+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +version = "1.11.0" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" +version = "1.11.0" + +[[deps.MacroTools]] +deps = ["Markdown", "Random"] +git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.13" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +version = "1.11.0" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.6+0" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.12.12" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.11.0" + + [deps.Pkg.extensions] + REPLExt = "REPL" + + [deps.Pkg.weakdeps] + REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.PlutoDevMacros]] +deps = ["AbstractPlutoDingetjes", "DocStringExtensions", "HypertextLiteral", "InteractiveUtils", "MacroTools", "Markdown", "Pkg", "Random", "TOML"] +git-tree-sha1 = "2944f76ac8c11c913a620da0a6b035e2fadf94c1" +uuid = "a0499f29-c39b-4c5c-807c-88074221b949" +version = "0.7.2" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +version = "1.11.0" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.Tricks]] +git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f" +uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" +version = "0.1.8" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +version = "1.11.0" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.59.0+0" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" +""" + +# ╔═╡ Cell order: +# ╟─9d4455af-96f1-46d7-a4f3-434495b11c8a +# ╠═8db82e94-5c81-4c52-9228-7e22395fb68f +# ╠═949ac1ef-c502-4e28-81ff-f99b0d19aa03 +# ╠═707175a9-d356-43cf-8038-620ebc401c93 +# ╠═cbfc6eec-8991-4a9c-ada0-295c8052854d +# ╟─4843983c-df64-4b94-8634-7a10d9423a70 +# ╟─a8995224-83c6-4f82-b5a5-87a6f86fc7a0 +# ╠═9e3601f5-efc2-44e9-83d8-5b65ce7e9ccf +# ╠═cdc0a7ad-a3ac-4270-b707-35b1939da276 +# ╟─fe891b4e-f440-4823-b43b-72572f6a6c12 +# ╠═86a80228-f495-43e8-b1d4-c93b7b52c8d8 +# ╠═2358f686-1950-40f9-9d5c-dac2d98f4c24 +# ╟─49516374-f625-4a84-ac5c-f92497d45025 +# ╟─8cc53cd2-9114-4067-ab0b-37fd8cd79240 +# ╠═0db51d39-7c05-4e00-b951-7fe776a8e0f9 +# ╠═e2b79a58-e66e-4d40-8673-418823753b38 +# ╟─9d23382c-cf35-4b20-a46c-0f4e2de17fc7 +# ╟─959acb40-1fd6-43f5-a1a6-73a6ceaae1d7 +# ╠═4d611425-c8e3-4bc3-912b-8bc0465363bc +# ╠═a5490a6b-dc11-42b7-87e0-d38870fc55e4 +# ╠═705e30fe-77a3-4b06-8b99-1807290edffb +# ╟─2ee7f26d-f383-4e7e-a69a-8fb72717467c +# ╟─79beba88-932f-4147-b3a0-d821ef1bc1e2 +# ╠═63d6c2df-a411-407c-af11-4f5d09fbb322 +# ╠═633029af-8cac-426e-b35c-c9fb3938b784 +# ╠═065bad73-5fa8-4496-ba33-9e66940b5806 +# ╟─2073f11e-8196-4ebc-922f-5fa589e91797 +# ╠═811cf78b-e870-45bb-9173-89a3b3d495f5 +# ╠═e7d67662-77b3-482a-b032-8db4afbc01a6 +# ╠═996b4085-114c-48f4-9f90-8e637f29c06a +# ╟─3a066bf4-3466-469e-90d0-6b14be3ed8d5 +# ╟─3213d977-7b65-43b0-a881-10fcc2523f14 +# ╠═903fee67-6b23-41dc-a03d-f1040b696be6 +# ╠═08d711c0-e2cc-4444-94ca-0c4c3cfe901f +# ╠═03e9d75e-e6c9-4199-933b-2be306daf978 +# ╠═26d11600-2827-4e08-9195-109c8a8bddc3 +# ╠═be2a7820-e194-4410-b00d-a9332b234ad6 +# ╟─00000000-0000-0000-0000-000000000001 +# ╟─00000000-0000-0000-0000-000000000002 diff --git a/test/notebooks/structbondmodule.jl b/test/notebooks/structbondmodule.jl index d1f4fdf..1a7eaec 100644 --- a/test/notebooks/structbondmodule.jl +++ b/test/notebooks/structbondmodule.jl @@ -1,5 +1,5 @@ ### A Pluto.jl notebook ### -# v0.19.40 +# v0.20.5 #> custom_attrs = ["hide-enabled"] @@ -8,12 +8,14 @@ using InteractiveUtils # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). macro bind(def, element) - quote + #! format: off + return quote local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end local el = $(esc(element)) global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) el end + #! format: on end # ╔═╡ 8db82e94-5c81-4c52-9228-7e22395fb68f @@ -134,6 +136,59 @@ end # ╔═╡ e2b79a58-e66e-4d40-8673-418823753b38 nt +# ╔═╡ 466995a2-dfd4-4374-8339-bc0232039b27 +md""" +## transformed_value +""" + +# ╔═╡ 4cb128aa-7ad8-4d17-bced-36845703e6a8 +md""" +`@NTBond` is also quite useful in combination with `transformed_value` from `PlutoUI.Experimental`. For this reason, the `@NTBond` macro supports an optional third argument which shall be a function that when provided is directly used to transform the value of the widget. +""" + +# ╔═╡ 7855826e-ccaa-4c27-a060-f5ceb927bbe8 +@bind transformed_value_example @NTBond "Transformed!" begin + a = Slider(1:10) + b = Slider(1:10) +end nt -> nt.a + nt.b + +# ╔═╡ 1d5573ee-872e-4dfb-a785-1ac9e836ad98 +transformed_value_example + +# ╔═╡ f65b3231-f2b2-45dc-b72e-1ad3107083fc +md""" +# StructBondSelect +""" + +# ╔═╡ 67c0860b-b4c1-412d-870a-a4ce4987465e +md""" +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. + +This structure can be constructed with a vector of `StructBond` or `transformed_value(f, ::StructBond)` elements, and will take care of generating an appropriate widget to display and process only the selected one. + +The main signature of the constructor is the following: +```julia +StructBondSelect(els::Vector; description = "StructBondSelect", default_idx = 1, selector_text = "Selector") +``` + +The names to select upon will be taken from the `description` of the provided `StructBonds`, while the text displayed next to the _selector_ will default to `Selector` but can be customized with the `selector_text` kwarg to the constructor. +The `description` kwarg can be used to customize the text in the widget container (similar to the same kwarg in `StructBond` and to `@NTBond`). Finally, the `default_idx` should be an integer and will select which of the provided `StructBond`s will be selected as default when instantiating the widget. +""" + +# ╔═╡ bd5ec086-5156-4e7c-a70b-5ca9f089bb49 +sbs_bond = @bind sbs StructBondSelect([ + @NTBond "cos(arg)" begin + arg = Slider(range(0,1,100)) + end (nt -> cos(nt.arg)) # We need to wrap the function given to `@NTBond` in () to avoid parse problems when providing a function + @NTBond "atan(y,x)" begin + x = Slider(range(0,10; step = 0.1); default = 3, show_value=true) + y = Slider(range(0, 10; step = 0.1); default = 5, show_value=true) + end nt -> atan(nt.y, nt.x) +]; default_idx = 2, selector_text = "Options:") + +# ╔═╡ 7853cc7f-4e58-44d1-8d3b-f8d4745564e6 +sbs + # ╔═╡ 9d23382c-cf35-4b20-a46c-0f4e2de17fc7 md""" # @BondsList @@ -210,6 +265,7 @@ As an example, one can create a `BondsList` containing the two `StructBond` bond blc = @BondsList "Popout Container" begin "Structure ASD" = Popout(asd_bond) "NamedTuple" = Popout(nt_bond) + "StructBondSelect" = Popout(sbs_bond) end # ╔═╡ e7d67662-77b3-482a-b032-8db4afbc01a6 @@ -258,42 +314,39 @@ PLUTO_PROJECT_TOML_CONTENTS = """ PlutoDevMacros = "a0499f29-c39b-4c5c-807c-88074221b949" [compat] -PlutoDevMacros = "~0.7.0" +PlutoDevMacros = "~0.9.0" """ # ╔═╡ 00000000-0000-0000-0000-000000000002 PLUTO_MANIFEST_TOML_CONTENTS = """ # This file is machine-generated - editing it directly is not advised -julia_version = "1.10.2" +julia_version = "1.11.4" manifest_format = "2.0" -project_hash = "9088728c15a23247dcd792960c847dd5035deb53" - -[[deps.AbstractPlutoDingetjes]] -deps = ["Pkg"] -git-tree-sha1 = "0f748c81756f2e5e6854298f11ad8b2dfae6911a" -uuid = "6e696c72-6542-2067-7265-42206c756150" -version = "1.3.0" +project_hash = "9c51cf46a1e177639a0c248b9cdccbfd7b4d05d7" [[deps.ArgTools]] uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" -version = "1.1.1" +version = "1.1.2" [[deps.Artifacts]] uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +version = "1.11.0" [[deps.Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +version = "1.11.0" + +[[deps.CodeTracking]] +deps = ["InteractiveUtils", "UUIDs"] +git-tree-sha1 = "062c5e1a5bf6ada13db96a4ae4749a4c2234f521" +uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" +version = "1.3.9" [[deps.Dates]] deps = ["Printf"] uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[deps.DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.9.3" +version = "1.11.0" [[deps.Downloads]] deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] @@ -302,16 +355,18 @@ version = "1.6.0" [[deps.FileWatching]] uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" - -[[deps.HypertextLiteral]] -deps = ["Tricks"] -git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" -uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" -version = "0.9.5" +version = "1.11.0" [[deps.InteractiveUtils]] deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +version = "1.11.0" + +[[deps.JuliaInterpreter]] +deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"] +git-tree-sha1 = "872cd273cb995ed873c58f196659e32f11f31543" +uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a" +version = "0.9.44" [[deps.LibCURL]] deps = ["LibCURL_jll", "MozillaCACerts_jll"] @@ -321,16 +376,17 @@ version = "0.6.4" [[deps.LibCURL_jll]] deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "8.4.0+0" +version = "8.6.0+0" [[deps.LibGit2]] deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +version = "1.11.0" [[deps.LibGit2_jll]] deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" -version = "1.6.4+0" +version = "1.7.2+0" [[deps.LibSSH2_jll]] deps = ["Artifacts", "Libdl", "MbedTLS_jll"] @@ -339,66 +395,66 @@ version = "1.11.0+1" [[deps.Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +version = "1.11.0" [[deps.Logging]] uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" +version = "1.11.0" [[deps.MacroTools]] -deps = ["Markdown", "Random"] -git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" +git-tree-sha1 = "1e0228a030642014fe5cfe68c2c0a818f9e3f522" uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.13" +version = "0.5.16" [[deps.Markdown]] deps = ["Base64"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +version = "1.11.0" [[deps.MbedTLS_jll]] deps = ["Artifacts", "Libdl"] uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.2+1" +version = "2.28.6+0" [[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2023.1.10" +version = "2023.12.12" [[deps.NetworkOptions]] uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" version = "1.2.0" [[deps.Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.10.0" +version = "1.11.0" + + [deps.Pkg.extensions] + REPLExt = "REPL" + + [deps.Pkg.weakdeps] + REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[deps.PlutoDevMacros]] -deps = ["AbstractPlutoDingetjes", "DocStringExtensions", "HypertextLiteral", "InteractiveUtils", "MacroTools", "Markdown", "Pkg", "Random", "TOML"] -git-tree-sha1 = "2944f76ac8c11c913a620da0a6b035e2fadf94c1" +deps = ["JuliaInterpreter", "Logging", "MacroTools", "Pkg", "TOML"] +git-tree-sha1 = "72f65885168722413c7b9a9debc504c7e7df7709" uuid = "a0499f29-c39b-4c5c-807c-88074221b949" -version = "0.7.2" +version = "0.9.0" [[deps.Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +version = "1.11.0" [[deps.Random]] deps = ["SHA"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" [[deps.SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" version = "0.7.0" -[[deps.Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[deps.Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - [[deps.TOML]] deps = ["Dates"] uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" @@ -409,17 +465,14 @@ deps = ["ArgTools", "SHA"] uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" version = "1.10.0" -[[deps.Tricks]] -git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f" -uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" -version = "0.1.8" - [[deps.UUIDs]] deps = ["Random", "SHA"] uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +version = "1.11.0" [[deps.Unicode]] uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" [[deps.Zlib_jll]] deps = ["Libdl"] @@ -429,7 +482,7 @@ version = "1.2.13+1" [[deps.nghttp2_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.52.0+1" +version = "1.59.0+0" [[deps.p7zip_jll]] deps = ["Artifacts", "Libdl"] @@ -454,6 +507,14 @@ version = "17.4.0+2" # ╟─8cc53cd2-9114-4067-ab0b-37fd8cd79240 # ╠═0db51d39-7c05-4e00-b951-7fe776a8e0f9 # ╠═e2b79a58-e66e-4d40-8673-418823753b38 +# ╟─466995a2-dfd4-4374-8339-bc0232039b27 +# ╟─4cb128aa-7ad8-4d17-bced-36845703e6a8 +# ╠═7855826e-ccaa-4c27-a060-f5ceb927bbe8 +# ╠═1d5573ee-872e-4dfb-a785-1ac9e836ad98 +# ╟─f65b3231-f2b2-45dc-b72e-1ad3107083fc +# ╟─67c0860b-b4c1-412d-870a-a4ce4987465e +# ╠═bd5ec086-5156-4e7c-a70b-5ca9f089bb49 +# ╠═7853cc7f-4e58-44d1-8d3b-f8d4745564e6 # ╟─9d23382c-cf35-4b20-a46c-0f4e2de17fc7 # ╟─959acb40-1fd6-43f5-a1a6-73a6ceaae1d7 # ╠═4d611425-c8e3-4bc3-912b-8bc0465363bc diff --git a/test/runtests.jl b/test/runtests.jl index 65803ec..709cfa9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,11 +1,12 @@ -using SafeTestsets -using Aqua -using PlutoExtras +using TestItemRunner -Aqua.test_all(PlutoExtras) +@testitem "Aqua" begin + using Aqua + using PlutoExtras + Aqua.test_all(PlutoExtras) +end -@safetestset "PlutoCombineHTL Module" begin include("combinehtl_module.jl") end -@safetestset "Basic Widgets" begin include("basics.jl") end -@safetestset "LaTeX Equations" begin include("latex.jl") end -@safetestset "Extended Toc" begin include("toc.jl") end -@safetestset "StructBond Module" begin include("structbond.jl") end \ No newline at end of file +@run_package_tests filter = ti -> :before ∈ ti.tags verbose=true +@run_package_tests filter = ti -> :before ∉ ti.tags verbose=true + + \ No newline at end of file diff --git a/test/setup_helper.jl b/test/setup_helper.jl new file mode 100644 index 0000000..8d57630 --- /dev/null +++ b/test/setup_helper.jl @@ -0,0 +1,25 @@ +import Pluto: update_save_run!, update_run!, WorkspaceManager, ClientSession, +ServerSession, Notebook, Cell, project_relative_path, SessionActions, +load_notebook, Configuration, set_bond_values_reactive + +function noerror(cell; verbose=true) + if cell.errored && verbose + @show cell.output.body + end + !cell.errored +end + +options = Configuration.from_flat_kwargs(; disable_writing_notebook_files=true, workspace_use_distributed_stdlib=true) +srcdir = normpath(@__DIR__, "./notebooks") +eval_in_nb(sn, expr) = WorkspaceManager.eval_fetch_in_workspace(sn, expr) + +function set_bond_value_sn(sn) + (session, notebook) = sn + function set_bond_value(name, value, is_first_value=false) + notebook.bonds[name] = Dict("value" => value) + set_bond_values_reactive(; session, notebook, bound_sym_names=[name], + is_first_values=[is_first_value], + run_async=false, + ) + end +end \ No newline at end of file diff --git a/test/structbond.jl b/test/structbond.jl index be704f6..86eda79 100644 --- a/test/structbond.jl +++ b/test/structbond.jl @@ -1,15 +1,16 @@ -import Pluto: update_save_run!, update_run!, WorkspaceManager, ClientSession, -ServerSession, Notebook, Cell, project_relative_path, SessionActions, -load_notebook, Configuration, set_bond_values_reactive -using PlutoExtras -using Markdown -using PlutoExtras.StructBondModule -using PlutoExtras.StructBondModule: structbondtype, popoutwrap, fieldbond, NotDefined, typeasfield, collect_reinterpret! -import PlutoExtras.AbstractPlutoDingetjes.Bonds -using Test - - -@testset "APD methods and Coverage" begin +@testsnippet setup_structbond begin + using PlutoExtras + using Markdown + using PlutoExtras.StructBondModule + using PlutoExtras.StructBondModule: structbondtype, popoutwrap, fieldbond, NotDefined, typeasfield, collect_reinterpret! + import PlutoExtras.AbstractPlutoDingetjes.Bonds + using Test + + include(joinpath(@__DIR__, "setup_helper.jl")) +end + + +@testitem "APD methods and Coverage" setup=[setup_structbond] begin tr = ToggleReactiveBond(Editable(3)) @testset "Toggle Reactive" begin @test Bonds.validate_value(tr, 3) === true @@ -59,14 +60,43 @@ using Test end end -function noerror(cell; verbose=true) - if cell.errored && verbose - @show cell.output.body - end - !cell.errored +@testitem "StructBondSelect" setup=[setup_structbond] begin + els = [ + @NTBond "cos(arg)" begin + arg = Slider(range(0,1,100)) + end nt -> cos(nt.arg) + @NTBond "atan(y,x)" begin + x = Slider(range(0,10; step = 0.1); default = 3, show_value=true) + y = Slider(range(0, 10; step = 0.1); default = 5, show_value=true) + end nt -> atan(nt.y, nt.x) + @NTBond "mah" begin + a = Slider(1:10) + end + ] +sbs = StructBondSelect(els; default_idx = 2, selector_text = "Options:") +@test sbs.selectors == ["cos(arg)", "atan(y,x)", "mah"] + +@test Bonds.initial_value(sbs) == Bonds.initial_value(els[2]) + +sbs = StructBondSelect(els; default_idx = 3, selector_text = "Options:") +@test Bonds.initial_value(sbs) == Bonds.initial_value(els[3]) +@test Bonds.validate_value(sbs, [[3, [3]]]) === true +@test Bonds.transform_value(sbs, [[3, [[[3]]]]]) == (;a = 3) + +@test_throws "default_idx must be a positive integer" StructBondSelect(els; default_idx = 0, selector_text = "Options:") +@test_throws "default_idx must be a positive integer" StructBondSelect(els; default_idx = 4, selector_text = "Options:") + +@test_throws "must be either a StructBond" StructBondSelect([1]) + +custom_names = ["asd", "qwe", "zxc"] +sbs_custom = StructBondSelect(els, custom_names; default_idx = 2, selector_text = "Options:") +@test sbs_custom.selectors == custom_names + +sbs_custom = StructBondSelect([nm => el for (nm, el) in zip(custom_names, els)]; default_idx = 2, selector_text = "Options:") +@test sbs_custom.selectors == custom_names end -@testset "collect_reinterpret!" begin +@testitem "collect_reinterpret!" setup=[setup_structbond] begin @test collect_reinterpret!(3) === 3 re = collect(reinterpret(UInt8, [.5])) |> x -> reinterpret(Float64, x) arr = [ @@ -81,22 +111,7 @@ end ] end -options = Configuration.from_flat_kwargs(; disable_writing_notebook_files=true, workspace_use_distributed_stdlib = true) -srcdir = normpath(@__DIR__, "./notebooks") -eval_in_nb(sn, expr) = WorkspaceManager.eval_fetch_in_workspace(sn, expr) - -function set_bond_value_sn(sn) - (session, notebook) = sn - function set_bond_value(name, value, is_first_value=false) - notebook.bonds[name] = Dict("value" => value) - set_bond_values_reactive(; session, notebook, bound_sym_names=[name], - is_first_values=[is_first_value], - run_async=false, - ) - end -end - -@testset "Struct Bond notebook" begin +@testitem "Struct Bond notebook" setup=[setup_structbond] begin ss = ServerSession(; options) path = joinpath(srcdir, "structbondmodule.jl") nb = SessionActions.open(ss, path; run_async=false) diff --git a/test/toc.jl b/test/toc.jl index 72480ad..01d319f 100644 --- a/test/toc.jl +++ b/test/toc.jl @@ -1,21 +1,9 @@ -import Pluto: update_save_run!, update_run!, WorkspaceManager, ClientSession, -ServerSession, Notebook, Cell, project_relative_path, SessionActions, -load_notebook, Configuration -using PlutoExtras - -function noerror(cell; verbose=true) - if cell.errored && verbose - @show cell.output.body - end - !cell.errored +@testsnippet setup_toc begin + using PlutoExtras + include(joinpath(@__DIR__, "setup_helper.jl")) end - -options = Configuration.from_flat_kwargs(; disable_writing_notebook_files=true, workspace_use_distributed_stdlib = true) -srcdir = normpath(@__DIR__, "./notebooks") -eval_in_nb(sn, expr) = WorkspaceManager.eval_fetch_in_workspace(sn, expr) - -@testset "ToC notebook" begin +@testitem "ToC notebook" setup=[setup_toc] begin ss = ServerSession(; options) path = joinpath(srcdir, "extended_toc.jl") nb = SessionActions.open(ss, path; run_async=false)