Commit Graph

22 Commits

Author SHA1 Message Date
Philipp Mildenberger f32277ab70
xilem_web: Add a few boolean attribute modifiers for `HtmlInputElement` and factor element state flags out of these modifiers into `ElementFlags` (#717)
This PR starts with supporting specialized elements (i.e. more than just
the `Element` DOM interface), starting with boolean attributes in
`HtmlInputElement` (`checked`, `default_checked`, `disabled`,
`required`, `multiple`).
With a general `OverwriteBool` modifier which is optimized by encoding
boolean flags into a `u32`, thus not requiring allocations (compared to
the other modifiers we currently have), but is limited to max 32
overwrites, which I don't think should be a real-world limitation (i.e.
`input_el.checked().checked()...checked()` 32 times makes no sense), I
also started adding tests for this, as it juggles around with
bit-operations (and we should generally start writing more tests).
I have originally planned to feature-flag this (i.e. have a feature like
`HtmlInputElement`).
But I'd like to see how far we can go without this, I haven't yet
noticed significant (binary-size) regressions in the todomvc example
(which uses `input` elements) that justifies the worse DX that
additional features introduce.
Having features for this is also not optimal for another reason: It
changes the API (e.g. `DomNode::Props` is `props::HtmlInputElement`
instead of `props::Element`.

It also factors the element state flags (`was_created`, `in_hydration`)
into a separate `ElementFlags` which is shared within a `Modifier<M>`
struct (similar as `PodMut` or `WidgetMut` in masonry), so that we don't
have to duplicate that state in every modifier. Additionally a new flag
`needs_update` is introduced, which indicates that the element in
general needs to update any modifier, and is entirely an optimization to
avoid checking every modifier whether it has changed (not yet that
important, but when we have a lot of modifiers per element, having to
check every modifier is less efficient, it's also already *slightly*
visible in the js-framework-benchmark).
For this, it unfortunately suffers similar as #705 from the free-form
syntax by being a little bit more verbose (which may be reverted after
`arbitrary_self_types` are stable).

It should also fix #716
2024-10-28 13:20:36 +00:00
Philipp Mildenberger 53a5354c2d
xilem_web: Rewrite modifiers (`Attributes`, `Classes` and `Styles`), and cleanup/extend docs (#699)
Previously the modifier systems had design issues i.e. bugs (non-deleted
styles/classes/attributes), and were unnecessary complex.
This aims to solve this (partly) by not using separate traits, but
concrete types and a different mechanism that is closer to how
`ElementSplice` works.

There's a few fundamental properties that composable type-based
modifiers need to support to avoid surprising/buggy behavior:

* Minimize actual changes to the underlying element, as DOM traffic is
expensive.
* Be compatible to memoization: e.g. a `Rotate` view should still be
applicable to possibly memoized transform values of the underlying
element.
* Recreation when the underlying element has changed (e.g. with a change
of variants of a `OneOf`).

To support all this, the modifier system needs to retain modifiers for
each modifier-view, and track its changes of the corresponding view.
Previously all elements were directly written and separated with markers
into a `Vec` to limit the boundaries of such views, but this had issues,
when e.g. all modifiers were deleted (e.g. clearing a `Vec` of classes),
by not reacting to this (I noticed that issue in the todomvc example
with the footer).

With this PR, the count of modifiers of a modifier-view are directly
stored either (hardcoded) in the view impl or its view state, which
cleans up the concrete modifier elements (such as `AttributeModifier`,
not including a separate `Marker` variant), and makes it less prone for
errors (and is slightly less memory-intensive).

The API to use these modifiers in modifier-views was also redesigned to
hopefully be more straight-forward/idiomatic. But as mentioned above
there's still challenges, which introduce complexity (which I'd like to
hide at least for simpler cases than these modifiers, likely in a future
PR).
All of this should now be documented in the new `modifier` module, where
now the modifiers `Attributes`, `Classes` and `Styles` reside. Other
views (like events) may also end up there...

One interesting aspect compared to the previous system is the use of a
new trait `With` for modifiers.
Instead of (roughly) `Element: WithStyle`, it works with `Element:
With<Styles>`.
This prevents all kinds of reimplementations of something like
`WithStyle` for elements.
This gets especially visible in the `one_of` module, which now can be
covered by a single blanket implementation.

Further the cargo-feature "hydration" was deleted, as it causes more
headaches to maintain than it really brings benefits (minimally less
binary size), depending on the future, it may or may not make sense to
reintroduce this.
2024-10-23 18:24:43 +00:00
Philipp Mildenberger 4817f24e86
Clippy pass, cosmetic fixes, and `rust-version.workspace=true` for web examples (#689)
Phew, fixing (future) clippy-lints is grunt-work (I enabled
`unnameable_types` for this), this is by far not complete, mostly
xilem-side, but at least a small step towards enabling more of our lint
set.

There's a few "drive-by fixes" like hiding `View::ViewState` types in
Xilem (I don't think we generally want to expose these), or exposing
event types in xilem_web.

I would suggest disabling the `allow_attributes_without_reason` lint for
now, so that we can update the rust version. I feel like adding comments
next to these is just unnecessary extra-work. I think adding more
reasons should probably be a separate pass, after a rust version update,
so that `#[allow(..., reason="")]` is supported.
2024-10-20 15:57:22 +00:00
Richard Dodd 011929321e
update web-sys dep and fix deprecation warning (#668) 2024-10-12 15:41:29 +00:00
Philipp Mildenberger a4f88b7d5c
xilem_web: Add `Rotate` and `Scale` (CSS) transform views (#621)
This sketches/implements (parts of) the transform modifier API described
in [Add `Affine` transform to `Widget`
trait?](https://xi.zulipchat.com/#narrow/stream/317477-masonry/topic/Add.20.60Affine.60.20transform.20to.20.60Widget.60.20trait.3F/near/472076600)
for xilem_web.

This currently includes `rotate` and `scale`, because there are less
cases to handle for these [CSS transform
functions](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function).
In `rotate` I think we can reduce this to just radians (there are more
units for `<angle>`: `turn`, `grad`, `deg` and `rad` (used here) but
they can all be derived from radians), and percent in scale is kinda
redundant (as `200%` == `2.0`)), for example `translate` has more cases
as it includes all kinds of units (like `px`, `em`, `%` etc.), so this
may require more thought (and is thus probably better for a future PR).

This can be combined with untyped `transform: ...` as style, these
modifier views extend the `transform` style (while the untyped
`style(..)` overwrites previous set values).

The `svgtoy` example is updated to include these views.
2024-10-10 17:44:47 +00:00
Andrii Zymohliad f90772a0d2
Rename async_repeat into task (#528)
Following [the discussion in
Zulip](https://xi.zulipchat.com/#narrow/stream/354396-xilem/topic/.60async_repeat.60.20name.20brainstorming),
this PR renames `async_repeat` view into `task`, and its `future_future`
argument into `init_future`. I also assumed we would want to do a
corresponding rename in `xilem_web` for consistency.
2024-08-20 08:50:47 +00:00
Philipp Mildenberger a52c3c7b3c
xilem_web: Add support for opacity in `svg::Fill` and dashes, opacity in `svg::Stroke` (#493)
Uses `ViewState` for a little bit of optimization (of allocations
mostly).
2024-08-09 09:28:52 +00:00
Markus Kohlhase 5b6ebc324f
xilem_web: Add an `AfterBuild`, `AfterRebuild` and `BeforeTeardown` view, which reflects `Ref` in React (#481)
Co-authored-by: Philipp Mildenberger <philipp@mildenberger.me>
2024-08-08 22:44:49 +00:00
Markus Kohlhase 2eda5a2a50
xilem_web: Add async_repeat (#485)
Co-authored-by: Philipp Mildenberger <philipp@mildenberger.me>
2024-08-08 17:51:04 +00:00
Philipp Mildenberger bb13f1a760
xilem_web: Allow `DomFragment` instead of `DomView` as `app_logic` (#482)
Should fix #461. This allows a `ViewSequence` (called `DomFragment`) of
`DomView`s as root component.

The `counter` example is updated to show this new behavior.
2024-08-05 13:03:19 +00:00
Philipp Mildenberger 19454e3dc8
Improve `calc` and xilem_web's `mathml_svg` example (#487)
Reduces a little bit of the boilerplate in `calc`
2024-08-05 12:54:22 +00:00
Philipp Mildenberger 24427bbb44
Use `ViewMarker` trait instead of the generic `Marker` to allow `impl ViewSequence` as return type (#472)
This allows returning `impl ViewSequence` as this was previously not
possibly as the `Marker` generic parameter couldn't be named (easily) in
`ViewSequence<..., Marker>`.

This also provides specialized `ViewSequence`s for xilem
(`WidgetViewSequence` and `FlexSequence`) as well as for xilem_web
(`DomFragment`). Additional doc-tests/documentation and a small example
(in `counter`) for xilem_web is provided as well.

This has the drawback to not being able to reeimplement `ViewSequence`
for types that already implement `View`, which was previously possible
(as seen by the now removed `NoElementView` `ViewSequence`
implementation).
And additionally by introducing more boilerplate by having to implement
`ViewMarker` for every type that implements `View`.

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2024-08-05 10:53:19 +00:00
Bruce Mitchener dd938d4af4
Fix doc warnings in xilem_core, xilem_web (#478) 2024-08-02 06:50:10 +00:00
Markus Kohlhase 727d696488
xilem_web: Use separate FetchState in fetch example (#454) 2024-07-28 10:30:26 +00:00
Philipp Mildenberger 981fcc4b5a
xilem_web: Add a `MemoizedAwait` view (#448)
This is the `rerun_on_change` view described in #440, I named it
`MemoizedAwait` as I think that fits its functionality.

It got also additional features `debounce_ms` (default `0`) and
`reset_debounce_on_update` (default `true`) as I think that's quite
useful, in case a lot of updates are happening.

When `reset_debounce_on_update == false`, `debounce` is more a throttle
than an actual debounce.

This also adds a more heavily modified version of the example added in
#427, also showing `OneOf` in xilem_web (which didn't have an example
yet).

This *could* be considered as alternative to #440 (at the very least the
example) but those approaches could also well live next to each other.

---------

Co-authored-by: Markus Kohlhase <markus.kohlhase@slowtec.de>
2024-07-26 16:11:34 +00:00
Daniel McNab d70076262d
Update dependencies and bump to Rust 1.80 (#450)
There is one "semi-false-positive" lint triggered, which I have fixed.
Otherwise, the required
```
cargo upgrade --ignore-rust-version
cargo update
```
2024-07-26 13:02:41 +00:00
Daniel McNab f11b64892c
Import our intended set of lints (#432)
See discussion in [#linebender > Standard Lint
set](https://xi.zulipchat.com/#narrow/stream/419691-linebender/topic/Standard.20Lint.20set)

Of note: I have taken steps to ensure that this can be practically
reviewed by *not* applying most of the lints.
The commented out lints make good follow-ups

---------

Co-authored-by: Olivier FAURE <couteaubleu@gmail.com>
2024-07-18 08:58:16 +00:00
Markus Kohlhase 62c06c9f98
xilem_web: Add Elm Architecture example (#425)
I have intentionally left out the `xilem_core::adapt` variant here in
order to have a clear classic Elm example. I would rather show the
`adapt` variant in a separate example.
2024-07-12 11:39:37 +00:00
Daniel McNab df85194c88
Fix the `head` elements of Xilem Web (#422)
These got mixed up in https://github.com/linebender/xilem/pull/142
2024-07-02 10:07:13 +00:00
Philipp Mildenberger b33a2a680d
Rewrite xilem_web to support new xilem_core (#403)
This ports xilem_web to the new xilem_core.

There's also a lot of cleanup internally:
* Get rid of all of the complex macros to support DOM interfaces, and
instead use associated type bounds on the `View::Element`.
* Introduce an extendable modifier based system, which should also work
on top of memoization (`Arc`, `Memoize`) and `OneOf` views with an
intersection of the modifiable properties.
* This modifier based system gets rid of the hacky way to propagate
attributes to elements, and takes inspiration by masonrys `WidgetMut`
type to apply changes.
* Currently that means `Attributes`, `Classes` and `Styles` to reflect
what xilem_web previously offered.

Downsides (currently, needs some investigation):

~~Due to more internal type complexity via associated types this suffers
from https://github.com/rust-lang/rust/issues/105900. The new trait
solver should hopefully mitigate some of that, but it seems currently it
completely stalls in the todomvc example (not in other examples).~~
~~The deep, possibly completely static composition via associated
type-bounds of the view and element tree unfortunately can take some
time to compile, this gets (already) obvious in the todomvc example. The
other examples don't seem to suffer that bad yet from that issue,
probably because they're quite simple.~~

~~I really hope we can mitigate this mostly, because I think this is the
idiomatic (and more correct) way to implement what the previous API has
offered.~~

One idea is to add a `Box<dyn AnyViewSequence>`, as every element takes
a "type-erased" `ViewSequence` as parameter, so this may solve most of
the issues (at the slight cost of dynamic dispatch/allocations).

Edit: idea was mostly successful, see comment right below.

I think it also closes #274

It's a draft, as there's a lot of changes in xilem_core that should be
upstreamed (and cleaned up) via separate PRs and I would like to
(mostly) fix the slow-compile time issue.

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2024-06-28 08:30:18 +00:00
Alex Pyattaev c12aa851bf
fix invalid HTML in examples (#304)
For some reason the recent version of Trunk refused to serve some of the
examples due to them missing the <html> tags. Adding the tags calms it
down and allows it to work again. Trivial change, but would save someone
the pain of having to fix examples before running them with trunk serve.

Co-authored-by: Alex Pyattaev <me@example.com>
2024-05-12 06:03:24 +00:00
Olivier FAURE ef5d36e8fc
Move crates to the repository root (#302)
Follows the convention proposed in this discussion:

https://xi.zulipchat.com/#narrow/stream/419691-linebender/topic/Standardizing.20multi-package.20repos
2024-05-11 21:59:03 +00:00