Merge pull request #6 from jkelleyrtp/jk/diff_machine_own_vdom

wip: new approach at direct access to vdom
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2021-06-10 01:02:12 -04:00
commit 984828f399
61 files changed
+1155 -2739

No files matched your search

+2
View File
@@ -46,3 +46,5 @@ impl
destructured
linting
lodash
crates.io
utilties
+3 -3
View File
@@ -5,11 +5,11 @@ members = [
"packages/core",
"packages/web",
"packages/dioxus",
"packages/recoil",
"packages/docsite",
"packages/ssr",
"packages/webview",
]
# "packages/recoil",
# "packages/docsite",
# "packages/webview",
# "packages/cli",
# "packages/webview",
+4 -6
View File
@@ -8,15 +8,13 @@
Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust.
```rust
fn Example(ctx: Context<()>) -> VNode {
fn Example(ctx: Context<()>) -> VNodes {
let (selection, set_selection) = use_state(&ctx, move || "..?");
ctx.render(rsx! {
div {
h1 { "Hello, {selection}" }
button { "?", onclick: move |_| set_selection("world!")}
button { "?", onclick: move |_| set_selection("Dioxus 🎉")}
}
h1 { "Hello, {selection}" }
button { "?", onclick: move |_| set_selection("world!")}
button { "?", onclick: move |_| set_selection("Dioxus 🎉")}
})
};
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

+3
View File
@@ -0,0 +1,3 @@
# Getting Started
This page is an overview of the Dioxus documentation.
+57
View File
@@ -0,0 +1,57 @@
# Overview
Dioxus aims to provide a fast, friendly, and portable toolkit for building user interfaces with Rust.
This guide assumes you'll be building a SPA (single page application) for the web. The process for building desktop apps, server-rendered apps, static sites, and mobile apps, is more-or-less the same. You can check out the [Platform Specific Guides](../platforms/00-index.md) for more information on setting up Dioxus for any of the various targets you are building for.
# Setting up Dioxus
Dioxus requires a few main things to get up and running:
- The [Rust compiler](https://www.rust-lang.org) and associated build tooling
- An editor of your choice, with the [Rust-Analyzer LSP plugin](https://rust-analyzer.github.io)
Dioxus integrates very well with the Rust-Analyzer IDE plugin which will provide appropriate syntax highlighting, code navigation, folding, and more.
We also recommend installing the Dioxus CLI. The Dioxus CLI automates building and packaging for various targets and integrates with simulators, development servers, and app deployment. It'll be our one-stop-shop for anything related to building and sharing our Dioxus Apps. To install the CLI, you'll need cargo (should be automatically installed with Rust):
```
$ cargo install dioxus-cli
```
You can update the dioxus-cli at any time with:
```
$ cargo install --force dioxus-cli
```
If your version of the CLI is out of date, it'll remind you to update whenever a new version is uploaded to Rust's package manager [crates.io](https://crates.io). We use a dedicated 1st-party CLI to save you from having to run potentially untrusted code every time you add a crate to your project - as is standard in the NPM ecosystem. You can vet the source of the Dioxus-CLI yourself at its [GitHub repo](https://github.com/jkelleyrtp/dioxus/tree/master/packages/cli).
If you want to keep your traditional `npm install XXX` workflow for adding packages, you might want to install `cargo-edit` and a few other fun `cargo` extensions:
- [cargo edit](https://github.com/killercup/cargo-edit) for adding dependencies from the CLI
- [cargo-expand](https://github.com/dtolnay/cargo-expand) for expanding macro calls
- `cargo tree` - an integrated cargo command that lets you inspect your dependency tree
That's it! We won't need to touch NPM/WebPack/Babel/Parcel, etc.
# Important tools
With Rust, things like benchmarking, testing, and documentation are included in the language. We strongly recommend going through the official Rust book _completely_. However, our hope is that a Dioxus app can serve as a great first project. With Dioxus you'll learn about:
- Error handling
- Structs, Functions, Enums
- Closures
- Macros
We've put a lot of care into making Dioxus syntax familiar and easy to understand, so you won't need knowledge on async, lifetimes, and smart pointers until you really start building complex Dioxus apps.
We strongly encourage exploring the guides for more information on how to work with the integrated tooling:
- [Testing](Testing.md)
- [Documentation](Documentation.md)
- [Benchmarking](Benchmarking.md)
- [Building](Building.md)
- [Modules](Modules.md)
- [Crates](Crates.md)
+142
View File
@@ -0,0 +1,142 @@
# Hello World
Let's put together a simple "hello world" to get acquainted with Dioxus. The Dioxus-CLI has an equivalent to "create-react-app" built-in, but setting up Dioxus apps is simple enough to not need additional tooling.
First, let's start a new project. Rust has the concept of executables and libraries. Executables have a `main.rs` and libraries have `lib.rs`. A project may have both. Our `hello world` will be an executable - we expect our app to launch when we run it! Cargo provides this for us:
```shell
$ cargo new --bin hello-dioxus
```
Now, we can `cd` into our project and poke around:
```shell
$ cd hello-dioxus
$ tree
.
├── Cargo.toml
├── .git
├── .gitignore
└── src
└── main.rs
```
We are greeted with a pre-initialized git repository, our code folder (`src`) and our project file (`Cargo.toml`).
Our `src` folder holds our code. Our `main.rs` file holds our `fn main` which will be executed when our app is ran.
```shell
$ more src/main.rs
```
```rust
fn main() {
println!("Hello, world!");
}
```
Right now, whenever our app is launched, "Hello world" will be echoed to the terminal.
```shell
$ cargo run
Compiling hello-dioxus v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
Running `target/debug/hello-dioxus`
Hello, world!
```
Our `Cargo.toml` file holds our dependencies and project flags.
```shell
$ cat Cargo.toml
```
```toml
[package]
name = "hello-dioxus"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
```
To use the Dioxus library, we'll want to add the most recent version of `Dioxus` to our crate. If you have `cargo edit` installed, simply call:
```shell
$ cargo add dioxus --features web
```
It's very important to add `dioxus` with the `web` feature for this example. The `dioxus` crate is a batteries-include crate that combines a bunch of utility crates together, ensuring compatibility of the most important parts of the ecosystem. Under the hood, the `dioxus` crate configures various renderers, hooks, debug tooling, and more. The `web` feature ensures the we only depend on the smallest set of required crates to compile.
If you plan to develop extensions for the `Dioxus` ecosystem, please use `dioxus-core` crate. The `dioxus` crate re-exports `dioxus-core` alongside other utilties. As a result, `dioxus-core` is much more stable than the batteries-included `dioxus` crate.
Now, let's edit our `main.rs` file:
```rust
use diouxs::prelude::*;
fn main() {
dioxus::web::start(App)
}
fn App(ctx: Context<()>) -> VNode {
ctx.render(rsx! {
div { "Hello, world!" }
})
}
```
Let's dissect our example a bit.
This bit of code imports everything from the the `prelude` module. This brings into scope the right traits, types, and macros needed for working with Dioxus.
```rust
use diouxs::prelude::*;
```
This bit of code starts the WASM renderer as a future (JS Promise) and then awaits it. This is very similar to the `ReactDOM.render()` method you use for a React app. We pass in the `App` function as a our app.
```rust
fn main() {
dioxus::web::start(App)
}
```
Finally, our app. Every component in Dioxus is a function that takes in a `Context` object and returns a `VNode`.
```rust
fn App(ctx: Context<()>) -> VNode {
ctx.render(rsx! {
div { "Hello, world!" }
})
};
```
In React, you'll save data between renders with hooks. However, hooks rely on global variables which make them difficult to integrate in multi-tenant systems like server-rendering. In Dioxus, you are given an explicit `Context` object to control how the component renders and stores data.
Next, we're greeted with the `rsx!` macro. This lets us add a custom DSL for declaratively building the structure of our app. The semantics of this macro are similar to that of JSX and HTML, though with a familiar Rust-y interface. The `html!` macro is also available for writing components with a JSX/HTML syntax.
The `rsx!` macro is lazy: it does not immediately produce elements or allocates, but rather builds a closure which can be rendered with `ctx.render`.
Now, let's launch our app in a development server:
```shell
$ dioxus develop
```
Huzzah! We have a simple app.
![Hello world](../assets/01-setup-helloworld.png)
If we wanted to golf a bit, we can shrink our hello-world even smaller:
```rust
fn main() {
dioxus::web::start(|ctx| ctx.render(diouxs::rsx!( div { "Hello, World!" } ))
}
```
Anyways, let's move on to something a bit more complex.
+156
View File
@@ -0,0 +1,156 @@
# VNode Macros
Dioxus comes preloaded with two macros for creating VNodes.
## html! macro
The html! macro supports a limited subset of the html standard. This macro will happily accept a copy-paste from something like tailwind builder. However, writing HTML by hand is a bit tedious - IDE tools for Rust don't support linting/autocomplete/syntax highlighting. RSX is much more natural for Rust programs and _does_ integrate well with Rust IDE tools.
There is also limited support for dynamic handlers, but it will function similarly to JSX.
You'll want to write RSX where you can, and in a future release we'll have a tool that automatically converts HTML to RSX.
```rust
#[fc]
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
ctx.render(html! {
<div>
<p> "Hello, {name}!" </p>
<p> "Status: {pending}!" </p>
<p> "Count {count}!" </p>
</div>
})
}
```
## rsx! macro
The rsx! macro is a VNode builder macro designed especially for Rust programs. Writing these should feel very natural, much like assembling a struct. VSCode also supports these with code folding, bracket-tabbing, bracket highlighting, and section selecting.
The Dioxus VSCode extension will eventually provide a macro to convert a selection of html! template and turn it into rsx!, so you'll never need to transcribe templates by hand.
It's also a bit easier on the eyes 🙂.
```rust
#[fc]
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
ctx.render(rsx! {
div {
p {"Hello, {name}!"}
p {"Status: {pending}!"}
p {"Count {count}!"}
}
})
}
```
Each element takes a comma-separated list of expressions to build the node. Roughly, here's how they work:
- `name: value` sets the property on this element.
- `"text"` adds a new text element
- `tag {}` adds a new child element
- `CustomTag {}` adds a new child component
- `{expr}` pastes the `expr` tokens literally. They must be IntoCtx<Vnode> to work properly
Commas are entirely optional, but might be useful to delineate between elements and attributes.
The `render` function provides an **extremely efficient** allocator for VNodes and text, so try not to use the `format!` macro in your components. Rust's default `ToString` methods pass through the global allocator, but all text in components is allocated inside a manually-managed Bump arena.
```rust
static Example: FC<()> = |ctx| {
let text = "example";
let g = async {
wait(10).await;
"hello"
};
let user_name = use_read_async(ctx, USERNAME);
let title = ctx.suspend(user_name, |user_name| rsx!{ h1 { "Welcome back, {user_name}" } });
ctx.render(rsx!{
div {
h1 { "Example" },
{title}
// fstring interpolation
"{text}"
p {
// Attributes
tag: "type",
// Anything that implements display can be an attribute
abc: 123,
enabled: true,
// attributes also supports interpolation
// `class` is not a restricted keyword unlike JS and ClassName
class: "big small wide short {text}",
// bool-based classnames
classes: [("big", true), ("small", false)]
// Bool-based props
// *must* be in the tuple form, cannot enter as a variable
tag: ("type", false)
tag: {"these tokens are placed directly"}
// Children
a { "abcder" },
// Children with attributes
h2 { "hello", class: "abc-123" },
// Child components
CustomComponent { a: 123, b: 456, key: "1" },
// Child components with paths
crate::components::CustomComponent { a: 123, b: 456, key: "1" },
// Iterators
{ 0..3.map(|i| rsx!( h1 {"{:i}"} )) },
// More rsx!, or even html!
{ rsx! { div { } } },
{ html! { <div> </div> } },
// Matching
// Requires rendering the nodes first.
// rsx! is lazy, and the underlying closures cannot have the same type
// Rendering produces the VNode type
{match rand::gen_range::<i32>(1..3) {
1 => rsx!(in ctx, h1 { "big" })
2 => rsx!(in ctx, h2 { "medium" })
_ => rsx!(in ctx, h3 { "small" })
}}
// Optionals
{true.and_then(|f| rsx!{ h1 {"Conditional Rendering"} })}
// Bool options
{(rsx!{ h1 {"Conditional Rendering"}, true)}
// Child nodes
// Returns &[VNode]
{ctx.children()}
// Duplicating nodes
// Clones the nodes by reference, so they are literally identical
{{
let node = rsx!(in ctx, h1{ "TopNode" });
(0..10).map(|_| node.clone())
}}
// Any expression that is `IntoVNode`
{expr}
}
}
})
}
```
+29
View File
@@ -0,0 +1,29 @@
## Testing
To test your Rust code, you can annotate any function with the `#[test]` block. In VSCode with RA, this will provide a lens to click and run the test.
```rust
#[test]
fn component_runs() {
assert!(true)
}
```
This will test your Rust code _without_ going through the browser. This is ideal for squashing logic bugs and ensuring components render appropriately when the browsers's DOM is not needed. If you need to run tests in the browser, you can annotate your blocks with the `#[dioxus::test]` block.
```rust
#[dioxus::test]
fn runs_in_browser() {
// ...
}
```
Then, when you run
```
$ dioxus test --chrome
```
Dioxus will build and test your code using the Chrome browser as a harness.
There's a lot more to testing if you dive in, so check out the [Testing]() guide for more information
@@ -1,4 +1,7 @@
# Welcome to Dioxus!
## Running Examples
We use the dedicated `dioxus-cli` to build and test dioxus web-apps. This can run examples, tests, build web workers, launch development servers, bundle, and more. It's general purpose, but currently very tailored to Dioxus for liveview and bundling. If you've not used it before, `cargo install --path pacakages/dioxus-cli` will get it installed. This CLI tool should feel like using `cargo` but with 1st party support for assets, bundling, and other important dioxus-specific features.
Alternatively, `trunk` works but can't run examples.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 856 B

@@ -1 +0,0 @@
<svg width="57" height="57" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M28.44 49.58v-1a20.07 20.07 0 0 1-14.23-5.9 20.07 20.07 0 0 1 0-28.47 20.07 20.07 0 0 1 28.47 0 20.08 20.08 0 0 1 0 28.47 20.07 20.07 0 0 1-14.24 5.9v2a22.16 22.16 0 0 0 22.14-22.14c0-12.2-9.93-22.13-22.14-22.14A22.16 22.16 0 0 0 6.3 28.44a22.16 22.16 0 0 0 22.14 22.14v-1"/><path d="M28.44 55.89v-1c-7.29 0-13.9-2.97-18.69-7.76a26.36 26.36 0 0 1 0-37.38 26.36 26.36 0 0 1 37.38 0 26.36 26.36 0 0 1 0 37.38 26.35 26.35 0 0 1-18.69 7.76v2a28.47 28.47 0 0 0 28.44-28.45A28.47 28.47 0 0 0 28.44 0 28.47 28.47 0 0 0 0 28.44 28.47 28.47 0 0 0 28.44 56.9v-1"/><path d="M43.04 28.44h-1 .03-.03.03-.03l-.02.05a1.66 1.66 0 0 1-.27.37c-.21.25-.53.54-.85.88a4.5 4.5 0 0 0-.46.57 2.4 2.4 0 0 0-.35.8 2.25 2.25 0 0 0-.06.5c0 .34.07.64.14.91.11.42.26.79.37 1.1.1.32.16.58.15.68v.05l.08.03-.08-.04v.01l.08.03-.08-.04.03.02-.02-.02.02.02-.02-.02s-.09.08-.27.17c-.27.13-.7.27-1.18.44a5.07 5.07 0 0 0-.74.33 2.49 2.49 0 0 0-.73.6c-.31.4-.43.82-.51 1.2-.12.56-.14 1.1-.2 1.49a2.05 2.05 0 0 1-.11.43l-.04.07.03.05-.03-.05.03.05-.03-.05.04.06-.03-.06h-.01l.04.06-.03-.06s-.12.04-.32.04a7.04 7.04 0 0 1-.78-.07c-.3-.03-.64-.07-1-.07-.37 0-.78.03-1.2.24a2.6 2.6 0 0 0-.98.85c-.35.45-.6.92-.82 1.24a2.1 2.1 0 0 1-.29.34l-.07.06v.04-.04.04-.04l.01.06v-.06h-.01l.01.06v-.06a.89.89 0 0 1-.3-.1c-.27-.14-.65-.4-1.08-.66a5.08 5.08 0 0 0-.73-.36 2.55 2.55 0 0 0-.93-.2c-.47 0-.85.15-1.19.3-.49.25-.9.54-1.24.74l-.43.23a.58.58 0 0 1-.18.05v.06l.02-.06h-.02v.06l.02-.06-.02.05.02-.05-.02.05.02-.05c-.03-.02-.14-.1-.26-.26-.2-.25-.42-.64-.69-1.05a4.94 4.94 0 0 0-.48-.63 2.47 2.47 0 0 0-.73-.55c-.43-.2-.83-.24-1.2-.24-.36 0-.7.04-1 .07a7.28 7.28 0 0 1-.78.07 1.21 1.21 0 0 1-.28-.03l-.04-.01-.04.06.05-.06h-.01l-.04.06.05-.06-.03.03.03-.02-.03.02.03-.02s-.06-.1-.1-.3c-.08-.29-.1-.75-.18-1.25a5.18 5.18 0 0 0-.16-.8 2.5 2.5 0 0 0-.43-.84c-.32-.4-.7-.6-1.04-.77-.53-.23-1.04-.37-1.4-.52a2.06 2.06 0 0 1-.4-.2l-.07-.06-.04.02.04-.02-.04.02.04-.02-.07.04.08-.03-.08.03.08-.03h-.02.02-.02.02v-.05a1.6 1.6 0 0 1 .06-.38c.07-.27.2-.61.33-1 .13-.38.26-.8.26-1.31 0-.16-.01-.33-.05-.5-.12-.5-.37-.85-.61-1.15-.37-.43-.77-.78-1.03-1.07a2 2 0 0 1-.27-.36l-.04-.08v-.01h-.02.02-.02.02-.04.04-.04.04l.02-.05a1.65 1.65 0 0 1 .26-.37c.22-.24.54-.53.85-.87.16-.17.32-.36.47-.58a2.18 2.18 0 0 0 .4-1.29 3.51 3.51 0 0 0-.14-.92c-.1-.41-.26-.78-.36-1.1-.1-.32-.16-.58-.16-.68v-.05l-.07-.02.07.03-.07-.03.07.03-.03-.01.03.02-.03-.02.03.02s.08-.09.26-.17c.27-.14.71-.27 1.19-.45a5.06 5.06 0 0 0 .73-.33c.25-.14.51-.33.73-.6.32-.4.44-.82.52-1.2.11-.56.14-1.09.2-1.48.03-.2.07-.35.11-.43l.04-.08-.04-.04.04.04-.04-.04.04.04-.05-.06.04.07-.04-.07.04.07a.92.92 0 0 1 .32-.04c.2 0 .47.03.78.06.3.04.64.08 1 .08.37 0 .77-.04 1.2-.24.46-.23.74-.55.98-.85.34-.46.59-.93.82-1.25.11-.16.21-.28.28-.34l.07-.05h.01l-.01-.04v.04h.01l-.01-.04v.04-.07.07-.07.07a.89.89 0 0 1 .29.1c.27.13.65.4 1.09.65.22.13.45.26.72.37.27.1.58.19.93.19.47 0 .86-.15 1.2-.3.48-.24.9-.54 1.24-.74.17-.1.32-.18.43-.22a.58.58 0 0 1 .17-.05v-.07l-.01.06h.01v-.06l-.01.06.01-.04-.02.04.02-.04-.02.04h.01c.03.02.13.1.26.27.2.24.41.64.68 1.05.14.2.3.41.48.62.2.2.42.4.73.56.43.2.84.24 1.2.24.37 0 .7-.04 1-.08.31-.03.59-.06.79-.06l.27.02.04.02.04-.07-.04.06.04-.05-.04.05.03-.03-.04.03h.01l.03-.03-.04.03s.07.1.11.3c.07.28.1.75.17 1.25.03.25.08.51.16.79.09.27.21.57.43.85.32.39.7.6 1.05.76.52.24 1.03.37 1.4.53a2 2 0 0 1 .4.2l.06.05.05-.02-.05.02.05-.02-.05.02.08-.03-.08.02v.01l.08-.03-.08.02h.01-.01.01-.01v.05c0 .07-.02.2-.06.39l-.34 1c-.12.38-.25.8-.26 1.3 0 .17.02.34.06.51.12.5.37.84.6 1.14.38.44.78.78 1.04 1.08a2 2 0 0 1 .27.35l.03.08v.01h.03-.02.02-.02 2a2.07 2.07 0 0 0-.14-.74 3.24 3.24 0 0 0-.6-.94c-.32-.37-.66-.68-.9-.95a2.8 2.8 0 0 1-.29-.33.53.53 0 0 1-.07-.14v-.06a1.61 1.61 0 0 1 .06-.4c.07-.27.2-.61.33-.99s.26-.8.26-1.3c0-.29-.05-.6-.2-.92a2.04 2.04 0 0 0-.45-.6c-.3-.28-.62-.45-.93-.58-.46-.2-.9-.33-1.23-.46a2.83 2.83 0 0 1-.4-.18.52.52 0 0 1-.14-.1 1 1 0 0 1-.12-.35c-.07-.34-.1-.85-.18-1.4a3.94 3.94 0 0 0-.23-.87 2.15 2.15 0 0 0-.64-.88 2.08 2.08 0 0 0-.81-.39 3.16 3.16 0 0 0-.75-.08c-.37 0-.7.04-1 .07a7.43 7.43 0 0 1-.79.07.89.89 0 0 1-.33-.04s-.11-.08-.25-.26c-.21-.28-.46-.73-.78-1.19a3.93 3.93 0 0 0-.59-.68 2.17 2.17 0 0 0-.96-.52 1.89 1.89 0 0 0-.43-.04c-.47 0-.85.15-1.17.3-.48.24-.89.53-1.23.73-.17.1-.32.18-.44.23a.62.62 0 0 1-.2.05.9.9 0 0 1-.32-.1c-.28-.14-.66-.4-1.09-.66a5.13 5.13 0 0 0-.7-.36 2.47 2.47 0 0 0-.93-.2c-.14 0-.28.02-.43.06a2.05 2.05 0 0 0-.69.3 3.25 3.25 0 0 0-.78.78c-.3.4-.51.8-.72 1.1l-.26.35a.54.54 0 0 1-.13.1c0 .01-.12.05-.33.05a7.28 7.28 0 0 1-.78-.07c-.3-.03-.64-.07-1-.07-.24 0-.49.02-.75.08a2.08 2.08 0 0 0-.81.39 2.04 2.04 0 0 0-.5.57c-.2.36-.28.71-.35 1.04-.09.49-.11.95-.17 1.3a2.77 2.77 0 0 1-.09.43.53.53 0 0 1-.07.16s-.1.1-.31.2c-.32.14-.81.28-1.33.48a3.93 3.93 0 0 0-.8.42 2.15 2.15 0 0 0-.71.82 2.08 2.08 0 0 0-.2.91c0 .34.07.64.14.91.11.41.26.78.36 1.1.11.31.17.58.16.69v.06l-.04.08a2.54 2.54 0 0 1-.35.43c-.26Line truncated

Before

Width:  |  Height:  |  Size: 6.2 KiB

@@ -1 +0,0 @@
<svg width="72" height="58" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M51.1 35.7a3 3 0 0 1-2.8-3c0-.4 0-.8.2-1.1l.4-1-1-.3a5.1 5.1 0 0 1-3.3-4.8l.1-1.1.3-1.2h-1.4a4.6 4.6 0 0 1-4.6-4.6V17l-1.2.4a3.2 3.2 0 0 1-1.1.2 3.3 3.3 0 0 1-3.3-3.2c0-.6.2-1.2.5-1.7l.7-1-1.2-.4a26 26 0 0 0-7.4-1 26 26 0 1 0 26 26.3v-.9h-.9z" id="b"/><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dx="2" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation=".5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" in="shadowBlurOuter1"/></filter></defs><g fill="none" fill-rule="evenodd"><g transform="rotate(14 33.7 105.7)" fill="#FFF"><path d="M51.1 25.4a3 3 0 0 1-2.8-3c0-.3 0-.7.2-1l.4-1-1-.3a5.1 5.1 0 0 1-3.3-4.8l.1-1.2.3-1.1h-1.4A4.6 4.6 0 0 1 39 8.4V6.8l-1.2.4a3.2 3.2 0 0 1-1.1.2 3.3 3.3 0 0 1-3.3-3.2c0-.6.2-1.2.5-1.7l.7-1-1.2-.4A26 26 0 0 0 26 0a26 26 0 1 0 26 26.4v-1h-.9zM26 50.1c-7.5 0-14.3-3.4-18.7-8.9a3.2 3.2 0 1 0 .3-6.3 3.2 3.2 0 0 0-3 2.2 24 24 0 0 1-2.7-10.7 2 2 0 0 0 2 1.5 2 2 0 0 0 0-4.1 2 2 0 0 0-2 1.5 24.2 24.2 0 0 1 19.4-23l-.2 1a2.2 2.2 0 1 0 4.4 0 2.2 2.2 0 0 0-.5-1.4h1c2 0 4 .2 5.8.7a5 5 0 0 0-.2 1.6 5.1 5.1 0 0 0 5 5h.6a6.5 6.5 0 0 0 5.5 5.6 6.5 6.5 0 0 0 0 .5 7 7 0 0 0 3.8 6.2 4.8 4.8 0 0 0 3.6 5.7 24.2 24.2 0 0 1-24.1 23z" stroke="#FFF"/><ellipse cx="14.5" cy="11.4" rx="2" ry="2"/><ellipse cx="27.9" cy="14.1" rx="2.9" ry="2.9"/><ellipse cx="15.5" cy="21.6" rx="3.1" ry="3.1"/><circle cx="26.5" cy="29.5" r="3.8"/><ellipse cx="34" cy="42.5" rx="2.3" ry="2.3"/><ellipse cx="41.6" cy="32.9" rx="2" ry="2"/><circle cx="20.8" cy="41.7" r="2.6"/><ellipse cx="39.1" cy="20.7" rx="2" ry="2"/></g><g transform="translate(0 -6)"><use fill="#000" filter="url(#a)" xlink:href="#b"/><use fill="#282828" xlink:href="#b"/></g><g transform="translate(1.9 4.2)" fill="#FFF" stroke="#FFF"><path d="M51.1 25.4a3 3 0 0 1-2.8-3c0-.3 0-.7.2-1l.4-1-1-.3a5.1 5.1 0 0 1-3.3-4.8l.1-1.2.3-1.1h-1.4A4.6 4.6 0 0 1 39 8.4V6.8l-1.2.4a3.2 3.2 0 0 1-1.1.2 3.3 3.3 0 0 1-3.3-3.2c0-.6.2-1.2.5-1.7l.7-1-1.2-.4A26 26 0 0 0 26 0a26 26 0 1 0 26 26.4v-1h-.9zM26 50.1c-7.5 0-14.3-3.4-18.7-8.9a3.2 3.2 0 1 0 .3-6.3 3.2 3.2 0 0 0-3 2.2 24 24 0 0 1-2.7-10.7 2 2 0 0 0 2 1.5 2 2 0 0 0 0-4.1 2 2 0 0 0-2 1.5 24.2 24.2 0 0 1 19.4-23l-.2 1a2.2 2.2 0 1 0 4.4 0 2.2 2.2 0 0 0-.5-1.4h1c2 0 4 .2 5.8.7a5 5 0 0 0-.2 1.6 5.1 5.1 0 0 0 5 5h.6a6.5 6.5 0 0 0 5.5 5.6 6.5 6.5 0 0 0 0 .5 7 7 0 0 0 3.8 6.2 4.8 4.8 0 0 0 3.6 5.7 24.2 24.2 0 0 1-24.1 23z"/><ellipse cx="14.5" cy="11.4" rx="2" ry="2"/><ellipse cx="27.9" cy="14.1" rx="2.9" ry="2.9"/><ellipse cx="15.5" cy="21.6" rx="3.1" ry="3.1"/><ellipse cx="26.5" cy="29.5" rx="3.8" ry="3.8"/><ellipse cx="34" cy="42.5" rx="2.3" ry="2.3"/><ellipse cx="41.6" cy="32.9" rx="2" ry="2"/><ellipse cx="20.8" cy="41.7" rx="2.6" ry="2.6"/><ellipse cx="39.1" cy="20.7" rx="2" ry="2"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

-32
View File
@@ -1,32 +0,0 @@
/* latin-ext */
@font-face {
font-family: 'Proza Libre';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjGdGHgj0k1DIQRyUEyyEomdNr1Wpyyzzc.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Proza Libre';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjGdGHgj0k1DIQRyUEyyEoodNr1Wpyy.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Proza Libre';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjbdGHgj0k1DIQRyUEyyELbV8_WeJGY9T6Mh1k.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Proza Libre';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/prozalibre/v5/LYjbdGHgj0k1DIQRyUEyyELbV8_YeJGY9T6M.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
-1
View File
@@ -1 +0,0 @@
<svg width="69" height="71" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M61 41.5h-1.2v.2c0 3.7 0 7.1-.4 10.2a20 20 0 0 1-1.7 6.1 12.3 12.3 0 0 1-2.7 3.6 17 17 0 0 1-7.3 3.9c-3.3 1-7.6 1.4-13.1 1.4-6.5 0-11.4-.7-14.9-2-2.6-1-4.6-2.2-6-3.7a16 16 0 0 1-2.5-3.7c-.9-2.1-1.3-4.6-1.6-7.3-.2-2.7-.2-5.6-.2-8.7a25.5 25.5 0 0 1 7.4-18 25 25 0 0 1 35.6 0 25.5 25.5 0 0 1 7.4 18h2.5c0-15.5-12.4-28-27.7-28a27.9 27.9 0 0 0-27.8 28c0 3.7 0 7.2.5 10.5.3 2.5.8 4.9 1.9 7a15 15 0 0 0 3.1 4.4c2 2 4.8 3.5 8.5 4.5 3.6 1 8.1 1.6 13.8 1.6a47 47 0 0 0 15.7-2.2c3-1 5.2-2.5 7-4.2 1.2-1.4 2.2-2.9 2.9-4.5 1-2.4 1.6-5.1 1.9-8 .2-2.8.2-5.8.2-8.9v-.2h-1.2"/><path d="M61 41.5h-1.2v.2c0 3.7 0 7.1-.4 10.2a20 20 0 0 1-1.7 6.1 12.3 12.3 0 0 1-2.7 3.6 17 17 0 0 1-7.3 3.9c-3.3 1-7.6 1.4-13.1 1.4-6.5 0-11.4-.7-14.9-2-2.6-1-4.6-2.2-6-3.7a16 16 0 0 1-2.5-3.7c-.9-2.1-1.3-4.6-1.6-7.3-.2-2.7-.2-5.6-.2-8.7a25.5 25.5 0 0 1 7.4-18 25 25 0 0 1 35.6 0 25.5 25.5 0 0 1 7.4 18h2.5c0-15.5-12.4-28-27.7-28a27.9 27.9 0 0 0-27.8 28c0 3.7 0 7.2.5 10.5.3 2.5.8 4.9 1.9 7a15 15 0 0 0 3.1 4.4c2 2 4.8 3.5 8.5 4.5 3.6 1 8.1 1.6 13.8 1.6a47 47 0 0 0 15.7-2.2c3-1 5.2-2.5 7-4.2 1.2-1.4 2.2-2.9 2.9-4.5 1-2.4 1.6-5.1 1.9-8 .2-2.8.2-5.8.2-8.9v-.2h-1.2"/><path d="M55.7 54.5h-1.3a4.3 4.3 0 0 1-2.2 3.7 3.5 3.5 0 0 1-1.6.3H19a4.8 4.8 0 0 1-1.9-.3 6.2 6.2 0 0 1-2.3-1.8 4.3 4.3 0 0 1-.7-1 2.3 2.3 0 0 1-.2-.9V39.7c0-.4.1-.6.3-1 .4-.4 1-.9 1.9-1.2.8-.4 1.8-.6 2.9-.6h31.6c1.4 0 2.3.4 3 .8a2.3 2.3 0 0 1 .8 2v14.8H57V39.7a5.1 5.1 0 0 0-.5-2.2 5 5 0 0 0-2.3-2.4c-1-.5-2.3-.7-3.6-.7H19c-1.8 0-3.6.4-5 1.3-.7.4-1.4 1-1.8 1.6a4.2 4.2 0 0 0-.8 2.4v14.8c0 1 .3 1.7.7 2.5a8.2 8.2 0 0 0 6.9 4h31.6a6 6 0 0 0 2.7-.5 6.7 6.7 0 0 0 3.7-6h-1.3M37.7 5h-1.3a2 2 0 0 1-2 2 2 2 0 0 1-2.1-2 2 2 0 0 1 2-2.1 2 2 0 0 1 2 2H39c0-2.5-2-4.5-4.6-4.5-2.5 0-4.6 2-4.6 4.6A4.6 4.6 0 1 0 39 5h-1.3"/><path d="M32.3 15.3h2.5V7.6h-2.5zM19.6 19v6.4a1.3 1.3 0 0 0 1.3 1.2c.7 0 1.3-.5 1.3-1.2V19a1.3 1.3 0 0 0-1.3-1.3c-.7 0-1.3.6-1.3 1.3m26.6 0v6.4a1.3 1.3 0 0 0 1.3 1.2c.7 0 1.2-.5 1.2-1.2V19a1.3 1.3 0 0 0-1.2-1.3c-.7 0-1.3.6-1.3 1.3M7.6 52.6H6.3l.1.6.2.4h.5-.5.5-.5l1-.2h-1v.2l1-.2h-1 1.2l-1.2-.3v.3h1.2l-1.2-.3 1.2.3-1-.6a1.3 1.3 0 0 0-.2.3l1.2.3-1-.6 1 .6-.6-1c-.2 0-.4.3-.5.4l1.1.6-.6-1 .6 1v-1.2a1.2 1.2 0 0 0-.6.1l.6 1.1v-1.2H2.2v1.1l.4-1-.4-.1v1.1l.4-1-.3.6.4-.6h-.1l-.3.6.4-.6a2 2 0 0 1-.3-.2l-.5.3.5-.3-.5.3.5-.3-1 .5h1.1v-.5l-1 .5h1V37H1.4l1 .6a1.2 1.2 0 0 0 .1-.6H1.4l1 .6-1-.6.6 1 .3-.4-1-.6.7 1-.6-1 .2 1.1.4-.1-.6-1 .2 1.1-.2-.8v.8h.2l-.2-.8v.8-.3.3-.3.3l.2.1h6.2A1.3 1.3 0 0 0 9.1 37a1.3 1.3 0 0 0-.1-.6l-.3-.4a1.5 1.5 0 0 0-.4-.2 1.4 1.4 0 0 0-.6-.2 1.3 1.3 0 0 0-1 .4 1.4 1.4 0 0 0-.3.5 1.4 1.4 0 0 0 0 .5v15.7h2.5V37H7.8l1 .3a1 1 0 0 0 0-.3h-1l1 .3-1.1-.3.7 1a1.2 1.2 0 0 0 .4-.7L7.7 37l.7 1-.7-1v1c.1 0 .4 0 .7-.2l-.7-1V38v-1l-.5 1h.5v-1l-.5 1 .4-1-.7.8a1 1 0 0 0 .3.2l.4-1-.7.8.8-.8-1 .6.2.2.8-.8-1 .6 1-.7-1 .4v.3l1-.7-1 .4 1.1-.4H6.6v.4l1.2-.4H6.6h1.2l-1-.6c-.2.2-.2.4-.2.6h1.2l-1-.6 1 .6-.8-1a1.3 1.3 0 0 0-.3.4l1.1.6-.8-1 .8 1-.3-1.2a1.2 1.2 0 0 0-.5.2l.8 1-.3-1.2.3 1.1v-1.2a1.2 1.2 0 0 0-.3 0l.3 1.2v-1.2H2.2v1l.2-1h-.2v1l.2-1v.2-.2.2-.2H2l-.6-.1c-.2 0-.4 0-.7.2a1.4 1.4 0 0 0-.6.4 1.4 1.4 0 0 0-.2.8v15.7l.2.8.4.5a4.4 4.4 0 0 0 1 .6 1.8 1.8 0 0 0 .3.2h6a1.3 1.3 0 0 0 1.3-1V53l-.2-.3v-.2l-.8.1H9v-.1l-.8.1H9 7.6m59.5 0h-1.3l.1.6.2.4h.5-.5.5-.5l1-.2h-1v.2l1-.2h-1 1.2l-1.2-.3v.3h1.2l-1.2-.3 1.2.3-1-.6a1.3 1.3 0 0 0-.2.3l1.2.3-1-.6 1 .6-.6-1c-.2 0-.4.3-.5.4l1.1.6-.6-1 .6 1v-1.2a1.2 1.2 0 0 0-.6.1l.6 1.1v-1.2h-5.6v1.1l.4-1-.4-.1v1.1l.4-1-.3.6.4-.6H62l-.3.6.4-.6a2 2 0 0 1-.3-.2l-.5.3.5-.3-.5.3.5-.3-1 .5H62v-.5l-1 .5h1V37h-1l1 .6a1.2 1.2 0 0 0 .1-.6H61l1 .6-1-.6.6 1 .3-.4-1-.6.7 1-.6-1 .2 1.1a1 1 0 0 0 .4-.1l-.6-1 .2 1.1-.1-.8v.8h.1l-.1-.8v.8-.3.3-.3.3l.2.1h6.1a1.3 1.3 0 0 0 1.3-1.2 1.3 1.3 0 0 0-.1-.6l-.3-.4a1.5 1.5 0 0 0-.4-.2 1.4 1.4 0 0 0-.6-.2 1.3 1.3 0 0 0-1.3 1 1.4 1.4 0 0 0 0 .4v15.7h2.5V37h-1.1l1 .3a1 1 0 0 0 0-.3h-1l1 .3-1.1-.4.7 1a1.2 1.2 0 0 0 .4-.6l-1.1-.4.7 1-.7-1V38c.2 0 .4 0 .7-.2l-.7-1V38v-1l-.5 1h.5v-1l-.5 1 .4-1-.7.8a1 1 0 0 0 .3.2l.4-1-.7.8.8-.8-1 .6.2.2.8-.8-1 .6 1-.7-1 .4v.3l1-.7-1 .4 1.1-.4h-1.2v.4l1.2-.4h-1.2 1.2l-1-.6a1.3 1.3 0 0 0-.2.6h1.2l-1-.6 1 .6-.8-1a1.3 1.3 0 0 0-.3.4l1.1.6-.8-1 .8 1-.3-1.2a1.2 1.2 0 0 0-.5.2l.8 1-.3-1.2.3 1.1v-1.2a1.2 1.2 0 0 0-.3 0l.3 1.2v-1.2h-5.6v1l.2-1h-.2v1l.2-1v.2-.2.2-.2h-.3l-.6-.1c-.2 0-.4 0-.7.2a1.4 1.4 0 0 0-.8 1.2v15.7l.2.8.4.5a4.4 4.4 0 0 0 1 .6 1.8 1.8 0 0 0 .3.2 1.3 1.3 0 0 0 .3 0h5.6a1.3 1.3 0 0 0 1.3-1V53l-.1-.3-.1-.2-.8.1h.8v-.1l-.8.1h.8H67m-42.9-5.8l4.8-4.9a1.3 1.3 0 0 0 0-1.8 1.3 1.3 0 0 0-1.8 0L22.4 45a1.3 1.3 0 0 0 0 1.8 1.3 1.3 0 0Line truncated

Before

Width:  |  Height:  |  Size: 5.1 KiB

-1
View File
@@ -1 +0,0 @@
<svg width="139" height="28" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dx="-2" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter><linearGradient x1="-18.384%" y1="118.346%" x2="91.782%" y2="8.547%" id="b"><stop offset="0%"/><stop stop-color="#FFF" offset="100%"/></linearGradient></defs><g filter="url(#a)" transform="rotate(45 103.014 54.088)" fill="none" fill-rule="evenodd"><path d="M63.563 29.254c0 1.444.367 2.725 1.1 3.793L62.1 35.615c-.272.294-.072.497.216.786l2.012 2.003c.277.294.465.475.748.187l2.78-2.778c.624.229 2.121.628 4.385.296l1.74-1.311c.13-.099.357-.245.507-.327l1.563-.855-1.253 1.266c-.12.121-.324.3-.453.398l-1.496 1.127 2.55 6.977a.45.45 0 0 0 .735.171l5.985-5.693a.455.455 0 0 0 .134-.248l1.342-7.499c1.632-1.411 3.284-3.053 4.913-4.882 9.376-10.53 10.775-18.76 10.775-22.728 0-1.307-.159-2.027-.165-2.057a.452.452 0 0 0-.365-.346c-.466-.08-11.581-1.793-26.046 12.662-.018.02-1.897 1.957-3.92 4.674l-7.428 2.065a.451.451 0 0 0-.226.147l-5.284 6.349a.452.452 0 0 0 .221.722l7.1 2.064 1.195-1.375c.106-.122.295-.308.423-.418l1.334-1.143-.945 1.48a4.67 4.67 0 0 1-.356.478l-1.258 1.447zM79.24 13.868c2.348-2.348 5.694-2.81 7.473-1.03 1.78 1.78 1.319 5.125-1.03 7.474-2.348 2.348-5.693 2.809-7.473 1.03-1.78-1.78-1.318-5.126 1.03-7.474z" fill="#FFF"/><path d="M79.225 13.894c2.348-2.349 5.694-2.81 7.473-1.03 1.78 1.78 1.319 5.125-1.03 7.473-2.348 2.349-5.693 2.81-7.473 1.03-1.78-1.78-1.318-5.125 1.03-7.473z" fill-opacity=".1" fill="url(#b)"/><path d="M62.342 40.43L9.359 93.336a.815.815 0 0 1-1.152 0l-.573-.572a.813.813 0 0 1 0-1.15l52.982-52.909a.815.815 0 0 1 1.152 0l.574.573a.813.813 0 0 1 0 1.15m-.762 6.738L8.595 100.074a.815.815 0 0 1-1.152 0l-.573-.573a.813.813 0 0 1 0-1.15l52.983-52.908a.815.815 0 0 1 1.152 0l.573.572a.813.813 0 0 1 0 1.15M2.027 94.388a.817.817 0 0 1-1.152 0L.3 93.816a.813.813 0 0 1 0-1.15l52.983-52.91a.815.815 0 0 1 1.152 0l.574.573a.813.813 0 0 1 0 1.15L2.027 94.39z" fill="#FFF"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

-1
View File
@@ -1 +0,0 @@
<svg width="78" height="71" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M36.24 21.208h-1.155c0 .36-.14.673-.36.901a1.15 1.15 0 0 1-1.667 0 1.286 1.286 0 0 1-.361-.9c0-.361.14-.674.36-.901.224-.228.51-.357.834-.359.324.002.61.131.833.359.221.227.361.54.361.9h2.311a3.6 3.6 0 0 0-1.016-2.515 3.468 3.468 0 0 0-2.489-1.058 3.47 3.47 0 0 0-2.49 1.058 3.604 3.604 0 0 0-1.015 2.515 3.6 3.6 0 0 0 1.016 2.515 3.469 3.469 0 0 0 2.49 1.058c.973 0 1.861-.41 2.488-1.058a3.6 3.6 0 0 0 1.016-2.515h-1.155m5.225-17.097H40.31c0 .36-.14.674-.36.902a1.152 1.152 0 0 1-1.666 0 1.287 1.287 0 0 1-.361-.902c0-.36.14-.672.36-.9a1.15 1.15 0 0 1 1.667 0c.22.228.36.54.36.9h2.312a3.6 3.6 0 0 0-1.016-2.515A3.464 3.464 0 0 0 39.117.54a3.467 3.467 0 0 0-2.49 1.057 3.605 3.605 0 0 0-1.015 2.515 3.6 3.6 0 0 0 1.016 2.516 3.467 3.467 0 0 0 2.49 1.057 3.464 3.464 0 0 0 2.488-1.057 3.6 3.6 0 0 0 1.016-2.516h-1.156m5.226 17.096h-1.156c0 .36-.14.673-.36.901a1.146 1.146 0 0 1-1.666 0 1.286 1.286 0 0 1-.361-.9c0-.361.14-.674.36-.902.224-.227.51-.356.834-.358.324.002.61.131.833.359.22.227.36.54.36.9h2.312a3.6 3.6 0 0 0-1.016-2.515 3.47 3.47 0 0 0-2.49-1.058c-.973 0-1.861.41-2.488 1.058a3.602 3.602 0 0 0-1.016 2.515 3.6 3.6 0 0 0 1.016 2.515 3.468 3.468 0 0 0 2.489 1.058c.973 0 1.862-.41 2.489-1.058a3.6 3.6 0 0 0 1.016-2.515h-1.156"/><path d="M52.94 21.116h-1.156c0 2.355-.923 4.444-2.412 5.957a8.121 8.121 0 0 1-5.809 2.431h-8.825a8.12 8.12 0 0 1-5.809-2.431c-1.489-1.513-2.412-3.602-2.413-5.957.001-2.356.924-4.445 2.413-5.957a8.12 8.12 0 0 1 5.809-2.432h8.825a8.121 8.121 0 0 1 5.809 2.432c1.489 1.512 2.412 3.601 2.412 5.957h2.312c0-2.97-1.175-5.654-3.08-7.583a10.43 10.43 0 0 0-7.453-3.12h-8.825a10.429 10.429 0 0 0-7.453 3.12c-1.905 1.93-3.081 4.613-3.08 7.583-.001 2.97 1.175 5.653 3.08 7.582a10.429 10.429 0 0 0 7.453 3.12h8.825a10.43 10.43 0 0 0 7.453-3.12c1.905-1.93 3.08-4.613 3.08-7.582H52.94m3.104 37.314v-1.157H21.956V38.182h32.933V58.43h1.155v-1.157 1.157H57.2V35.868H19.644v23.719H57.2V58.43h-1.156"/><path d="M67.282 59.298h-1.155c-.001 2.355-.925 4.444-2.414 5.956a8.12 8.12 0 0 1-5.808 2.432h-37.51a8.12 8.12 0 0 1-5.807-2.432c-1.49-1.512-2.413-3.6-2.414-5.956 0-2.356.924-4.445 2.414-5.957a8.12 8.12 0 0 1 5.808-2.432h37.509a8.12 8.12 0 0 1 5.808 2.432c1.49 1.512 2.413 3.6 2.414 5.957h2.31c.001-2.97-1.174-5.654-3.08-7.583a10.43 10.43 0 0 0-7.452-3.12h-37.51a10.43 10.43 0 0 0-7.452 3.12c-1.905 1.93-3.08 4.613-3.08 7.583 0 2.969 1.175 5.653 3.08 7.582A10.43 10.43 0 0 0 20.396 70h37.509a10.43 10.43 0 0 0 7.453-3.12c1.905-1.93 3.08-4.613 3.08-7.582h-1.156"/><path d="M20.396 63.636c-2.342 0-4.177-1.905-4.177-4.338s1.835-4.34 4.177-4.34h37.509c2.342 0 4.177 1.907 4.177 4.34s-1.835 4.338-4.177 4.338h-37.51M41.6 36.446V35.29h-4.622v-2.892h3.466v4.05H41.6V35.29v1.157h1.156v-6.363h-8.09v7.52h8.09v-1.157H41.6m-20.12 5.511L9.544 29.688 7.89 31.302l11.934 12.27m37.04 1.321L70.336 31.31l-1.64-1.63-13.471 13.582"/><path d="M5.851 27.344l-.828-.808c-.33.349-.877.593-1.411.718a5.251 5.251 0 0 1-1.147.142h-.03v.035-.036.036-.036l.003.001-.082-.002a1.96 1.96 0 0 0-1.308.467 1.766 1.766 0 0 0-.59 1.33c0 .3.069.583.18.842.062.146.285.58.915 1.227l.045.047-.046-.047a5.67 5.67 0 0 0 4.076 1.733 5.67 5.67 0 0 0 4.075-1.733 5.936 5.936 0 0 0 1.672-4.147 5.933 5.933 0 0 0-1.672-4.146l-.007-.006.005.005c-.624-.64-1.023-.863-1.182-.936a2.12 2.12 0 0 0-.874-.198 1.728 1.728 0 0 0-1.531.897 2.038 2.038 0 0 0-.244.993v.113c.002.143-.012.66-.14 1.22-.123.564-.37 1.145-.706 1.481l.827.808.828.807c.78-.811 1.12-1.784 1.306-2.587a8.15 8.15 0 0 0 .197-1.73l-.001-.109v-.003l-.415-.03.283.274a.444.444 0 0 0 .132-.244l-.415-.03.283.274-.404-.392v.572a.589.589 0 0 0 .404-.18l-.404-.392v.572-.32l-.073.312.073.008v-.32l-.073.312.028-.116-.04.114.012.002.028-.116-.04.114.004.001.244-.54-.302.511.058.029.244-.54-.302.511c.004.002.19.114.541.474a3.617 3.617 0 0 1 1.017 2.531c0 .925-.34 1.837-1.017 2.533a3.357 3.357 0 0 1-2.42 1.033 3.355 3.355 0 0 1-2.418-1.033 3.907 3.907 0 0 1-.42-.496l-.05-.076-.596.312.618-.266-.021-.046-.597.312.618-.266-.05-.118.05.118-.002-.004-.229.075h.239l-.01-.075-.229.075h.239-.552l.358.407a.575.575 0 0 0 .194-.407h-.552l.358.407-.316-.36.152.458a.486.486 0 0 0 .164-.098l-.316-.36.152.458-.087-.26.041.271.046-.011-.087-.26.041.271-.009-.062v.063h.01l-.01-.063v.063h.005c.012 0 .048.002.104.002a7.51 7.51 0 0 0 1.686-.205c.784-.192 1.741-.552 2.529-1.354l-.829-.807m66.531 0l-.828.807c.788.802 1.745 1.162 2.529 1.354a7.498 7.498 0 0 0 1.79.203h.005v-.063l-.01.062.01.001v-.063l-.01.062.069-.446-.322.293a.47.47 0 0 0 .254.153l.068-.446-.32Line truncated

Before

Width:  |  Height:  |  Size: 6.8 KiB

-1
View File
@@ -1 +0,0 @@
<svg width="98" height="74" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M96.384 53.5h-1.617c-.001 1.045-.26 2.068-.793 3.11-.927 1.82-2.738 3.681-5.355 5.399-3.919 2.58-9.597 4.817-16.405 6.377C65.407 69.95 57.468 70.852 49 70.852c-12.903.003-24.582-2.102-32.892-5.426-4.155-1.657-7.459-3.622-9.643-5.69-1.094-1.032-1.908-2.085-2.44-3.125-.532-1.043-.791-2.066-.792-3.111 0-1.046.26-2.07.792-3.112.927-1.82 2.738-3.68 5.355-5.398 3.92-2.58 9.598-4.817 16.405-6.377C32.593 37.05 40.531 36.148 49 36.148c12.903-.004 24.58 2.101 32.892 5.426 4.155 1.657 7.458 3.621 9.642 5.689 1.095 1.032 1.908 2.086 2.44 3.125.533 1.042.792 2.066.793 3.112H98c0-1.568-.403-3.096-1.133-4.517-1.283-2.493-3.517-4.677-6.44-6.602-4.39-2.882-10.387-5.202-17.47-6.832C65.873 33.923 57.703 33 49 33c-13.267.004-25.28 2.135-34.12 5.66-4.419 1.77-8.055 3.882-10.665 6.343-1.304 1.231-2.352 2.556-3.083 3.98C.402 50.404-.002 51.932 0 53.5c-.002 1.567.402 3.094 1.132 4.517 1.283 2.492 3.517 4.676 6.44 6.601 4.391 2.882 10.387 5.202 17.471 6.832C32.125 73.077 40.295 74 49 74c13.266-.004 25.28-2.136 34.118-5.661 4.42-1.77 8.056-3.882 10.667-6.343 1.304-1.23 2.352-2.555 3.082-3.98.73-1.422 1.134-2.95 1.133-4.516h-1.616"/><path d="M89.78 46.567c0 .866.72 1.568 1.61 1.568.89 0 1.61-.702 1.61-1.568 0-.865-.72-1.567-1.61-1.567-.89 0-1.61.702-1.61 1.567zm-1.957 4.701a1.539 1.539 0 0 0 .226 2.206 1.64 1.64 0 0 0 2.266-.22 1.539 1.539 0 0 0-.226-2.205 1.641 1.641 0 0 0-2.266.219zM83.32 54.97a1.543 1.543 0 0 0-.504 2.162 1.637 1.637 0 0 0 2.221.49c.753-.461.978-1.43.503-2.162a1.637 1.637 0 0 0-2.22-.49zm-5.493 2.718a1.553 1.553 0 0 0-.872 2.048c.34.8 1.283 1.18 2.104.848.822-.332 1.212-1.249.872-2.048-.341-.8-1.283-1.18-2.104-.848zm-5.916 1.995c-.854.24-1.347 1.11-1.1 1.94.246.832 1.14 1.312 1.993 1.072.856-.24 1.348-1.109 1.101-1.94-.246-.832-1.138-1.311-1.994-1.072zm-6.128 1.44c-.873.169-1.44.993-1.267 1.843.173.848 1.02 1.4 1.893 1.231.872-.168 1.44-.992 1.267-1.842-.173-.849-1.021-1.4-1.893-1.232zm-6.248.977c-.882.108-1.508.891-1.398 1.75.11.86.916 1.468 1.799 1.36.882-.107 1.508-.89 1.397-1.75-.11-.858-.915-1.467-1.798-1.36zm-6.313.57c-.888.053-1.563.797-1.509 1.66.054.865.819 1.523 1.706 1.47.888-.054 1.564-.797 1.509-1.661-.055-.864-.818-1.521-1.706-1.468zm-6.344.195c-.89.002-1.609.706-1.607 1.57.002.867.725 1.567 1.614 1.565.89-.002 1.61-.705 1.607-1.57-.002-.867-.725-1.566-1.614-1.565zm-6.351-.156c-.889-.046-1.647.618-1.694 1.482-.047.865.635 1.603 1.523 1.648.888.047 1.646-.617 1.693-1.482.048-.864-.634-1.602-1.522-1.648zm-6.325-.51c-.883-.098-1.68.52-1.781 1.38-.101.86.534 1.637 1.418 1.735.883.097 1.68-.52 1.781-1.38.101-.86-.533-1.637-1.418-1.735zm-6.262-.901c-.875-.158-1.715.406-1.876 1.257-.16.851.417 1.668 1.292 1.825.874.158 1.714-.406 1.875-1.257.162-.851-.417-1.668-1.291-1.825zm-6.15-1.356c-.86-.228-1.744.264-1.978 1.1-.235.834.271 1.696 1.129 1.924.858.228 1.744-.264 1.978-1.1.234-.834-.271-1.696-1.13-1.924zm-5.94-1.914c-.827-.321-1.764.07-2.094.874-.33.804.073 1.716.9 2.037.824.321 1.762-.07 2.092-.875.33-.803-.073-1.715-.899-2.037v.001zm-5.512-2.657c-.756-.457-1.749-.232-2.218.504a1.542 1.542 0 0 0 .517 2.158 1.636 1.636 0 0 0 2.218-.503 1.543 1.543 0 0 0-.517-2.159zM5.87 51.684a1.641 1.641 0 0 0-2.263-.251 1.54 1.54 0 0 0-.258 2.202 1.64 1.64 0 0 0 2.263.251 1.54 1.54 0 0 0 .258-2.202zm22.24-25.73c2.976 1.4 10.46 4.391 20.173 4.396 5.905 0 12.634-1.114 19.63-4.375 4.502 4.369 7.453 10.212 7.996 16.71a50.737 50.737 0 0 1-4.564 2.236c-3.207 1.375-7.215 2.648-10.837 2.643-.45 0-.814.35-.814.782 0 .43.365.781.814.781 4.276-.005 8.732-1.546 12.153-3.064a52.697 52.697 0 0 0 3.335-1.629c.003.144.004.287.004.431 0 14.847-56 14.847-56 0 0-.225.003-.45.009-.674a52.741 52.741 0 0 0 3.786 1.872c3.421 1.518 7.878 3.059 12.152 3.064.45 0 .815-.35.815-.781 0-.432-.364-.782-.815-.782-3.862.006-8.165-1.445-11.467-2.918a51.002 51.002 0 0 1-4.368-2.204c.597-6.411 3.54-12.172 7.997-16.488zm1.264-1.151C34.324 20.57 40.85 18 48 18c7.162 0 13.697 2.579 18.649 6.822-6.557 2.953-12.828 3.964-18.366 3.965-6.089 0-11.29-1.227-14.963-2.454a42.813 42.813 0 0 1-3.946-1.53z"/><path d="M49.48 9.283l7.268-1.692a1.63 1.63 0 0 0 1.24-1.385 1.609 1.609 0 0 0-.884-1.626l-8.69-4.4a1.692 1.692 0 0 0-1.62.055A1.62 1.62 0 0 0 46 1.62v18.76c0 .895.74 1.62 1.655 1.62.914 0 1.655-.725 1.655-1.62l.17-11.097z"/></g></svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

@@ -1 +0,0 @@
<svg width="82" height="81" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M17.41 20.294c0 2.096-1.732 3.795-3.87 3.795-2.137 0-3.869-1.699-3.869-3.795s1.732-3.796 3.87-3.796c2.137 0 3.869 1.7 3.869 3.796m48.14 48.052c0 .828-.684 1.5-1.528 1.5-.846 0-1.53-.672-1.53-1.5 0-.83.684-1.5 1.53-1.5.844 0 1.529.67 1.529 1.5M35.542 55.012l-1.377.553a15.557 15.557 0 0 1 1.208 6.002c0 3.127-.95 6.18-2.685 8.76a16.045 16.045 0 0 1-7.387 5.949 16.41 16.41 0 0 1-6.12 1.185c-3.19 0-6.301-.932-8.932-2.633a15.872 15.872 0 0 1-6.064-7.247 15.558 15.558 0 0 1-1.21-6.002c0-3.128.95-6.18 2.686-8.76a16.04 16.04 0 0 1 7.388-5.949 16.406 16.406 0 0 1 6.12-1.185c3.189 0 6.3.932 8.931 2.633a15.878 15.878 0 0 1 6.065 7.247l1.377-.553 1.378-.551a18.806 18.806 0 0 0-7.182-8.58 19.46 19.46 0 0 0-17.815-1.713 19.015 19.015 0 0 0-8.747 7.044A18.607 18.607 0 0 0 0 61.579c0 2.37.46 4.781 1.43 7.106a18.804 18.804 0 0 0 7.18 8.58 19.46 19.46 0 0 0 17.816 1.713c3.71-1.487 6.697-3.99 8.747-7.044a18.6 18.6 0 0 0 3.176-10.367c0-2.37-.46-4.781-1.43-7.107l-1.377.552"/><path d="M10.119 48.911L45.309 2.78a1.441 1.441 0 0 0-.3-2.043 1.508 1.508 0 0 0-2.082.295L7.737 47.163a1.44 1.44 0 0 0 .3 2.043c.657.482 1.59.35 2.082-.295m24.25 24.432l47.034-34.516a1.44 1.44 0 0 0 .3-2.042 1.507 1.507 0 0 0-2.082-.295L32.586 71.006a1.441 1.441 0 0 0-.3 2.043 1.507 1.507 0 0 0 2.083.294m3.907-27.893l30.631-31.594a1.44 1.44 0 0 0-.053-2.064 1.51 1.51 0 0 0-2.104.052L36.12 43.439a1.44 1.44 0 0 0 .054 2.064 1.508 1.508 0 0 0 2.103-.053M25.648 75.23c-2.724-4.05-5.68-7.907-9.206-11.319-1.828-1.769-3.996-3.122-6.07-4.585-1.797-1.268-4.234-1.856-5.919-3.144-1.1-.84-2.623.347-2.123 1.59.544 1.349 1.643 1.665 2.86 2.409 2.077 1.271 3.884 3.002 5.71 4.586 4.205 3.645 7.617 8.153 10.211 13.025 1.784 3.345 6.654.583 4.537-2.562"/><path d="M35.876 60.62c-2.09.656-8.949-1.58-11.42-2.508-2.914-1.094-5.503-2.671-7.921-4.584-1.58-1.248-4.243-3.255-4.894-5.29-.747-2.33-4.626-.554-3.109 1.758 3.506 5.342 10.075 9.056 16.056 10.963 1.287.41 12.404 3.44 12.321.257-.012-.515-.607-.729-1.033-.596"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

File diff suppressed because it is too large. Load diff
-1
View File
@@ -1 +0,0 @@
<svg width="68" height="69" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M1.3 33.8h1.2H2l.5.3a.6.6 0 0 0 .1-.3H2l.5.3-.2-.1.2.2-.2-.2.2.2.4-.3c.5-.3 1.3-.5 2.1-.8 1.3-.4 2.8-.8 4-1.3.7-.2 1.2-.4 1.7-.8l.8-.5a2 2 0 0 0 .5-1.4 2.2 2.2 0 0 0-.1-.8l-.8-1.1-1.8-1.8L6 22.8l-1-1a1.6 1.6 0 0 1-.2-.3l-.4.1H5h-.4.4-.6l.6.3a.7.7 0 0 0 0-.3h-.6l.6.3-.5-.2.3.5a.6.6 0 0 0 .2-.3l-.5-.2.3.5-.2-.2.2.2-.2-.2.2.2A1.2 1.2 0 0 1 5 22h.7c.9 0 2 0 3.2.2l3.4.2 1.5-.1.7-.3.7-.6c.3-.4.3-.9.3-1.2 0-.4 0-.8-.2-1.2-.2-.7-.5-1.4-1-2.2l-1.7-3.3a13.8 13.8 0 0 1-.8-2.1l-.4-.1.4.2a.4.4 0 0 0 0-.1l-.4-.1.4.2-.6-.3.5.5a.7.7 0 0 0 0-.2l-.5-.3.5.5-.5-.5.2.6a.6.6 0 0 0 .3-.1l-.5-.5.2.6-.1-.3v.3h.1l-.1-.3v.3l.5.1 1.8.8 3.4 1.8 1.6.7 1.6.4a2 2 0 0 0 1.2-.4c.3-.2.5-.4.6-.7l.3-1 .1-1.2-.2-3.4a33.6 33.6 0 0 1-.2-4.1v-.1l-.2-.2.2.2-.2-.2.2.2-.5-.4.3.6a.6.6 0 0 0 .2-.2l-.5-.4.3.6-.3-.6V5a.7.7 0 0 0 .3 0l-.3-.6V5v-.4.4-.4.4-.2.2-.2.2l.4.3L23.3 7l2.7 3c.4.5.8 1 1.3 1.3l.7.5 1 .2h.4a2 2 0 0 0 .8-.4c.5-.4.7-.8 1-1.2L32 8l1.3-4 .5-1.2.1-.2-.2-.2.2.3-.2-.3.2.3-.3-.6v.6a.6.6 0 0 0 .3 0l-.3-.6v.6V2l-.3.5a.6.6 0 0 0 .3.1V2l-.3.5.2-.2-.2.2.2-.2-.2.2.3.4.8 2.1c.4 1.3.8 2.8 1.3 4l.7 1.7.6.8a2 2 0 0 0 1.4.5l.8-.1 1.1-.8 1.8-1.8 2.5-3 1-1A1.7 1.7 0 0 1 46 5v-.4.4-.4.4-.6l-.3.6a.7.7 0 0 0 .2 0v-.6l-.2.6.2-.5-.5.3.3.2.2-.5-.5.3.2-.1h-.2.2-.2a1.3 1.3 0 0 1 0 .4l.1.8c0 .8 0 2-.2 3l-.2 3.5.1 1.5c0 .2.1.5.3.7.1.3.3.5.6.7a2 2 0 0 0 1.2.4l1.2-.3 2.2-.9 3.3-1.8a13.8 13.8 0 0 1 2.1-.8v-.4.4-.4.4l.2-.6-.5.5a.7.7 0 0 0 .2.1l.3-.6-.5.5.5-.5-.6.2a.6.6 0 0 0 .1.3l.5-.5-.6.2h.3-.4.4-.4a2 2 0 0 1 0 .4l-.8 1.8-1.8 3.4a16.4 16.4 0 0 0-.7 1.6c-.2.5-.4 1-.4 1.6 0 .3 0 .8.4 1.2.2.3.4.5.7.6.3.2.7.3 1 .3l1.2.1 3.4-.2a33.6 33.6 0 0 1 4.1-.2h.1l.2-.2-.3.2h.1l.2-.2-.3.2.5-.5-.6.3a.6.6 0 0 0 .1.2l.5-.5-.6.3.6-.3h-.7v.3l.7-.3h-.7.5-.4.4-.4.1-.1.1-.1l-.4.4-1.5 1.4-3.2 2.7c-.5.4-.9.8-1.2 1.3l-.5.7a2.3 2.3 0 0 0-.3 1v.4l.5.9c.3.4.7.6 1.1.8l2.6 1 4 1.3 1.2.6h.1l.3-.1H65a.3.3 0 0 0 0 .2l.3-.2H65l.6-.2H65a.6.6 0 0 0 0 .3l.6-.3H65h.5l-.5-.3a.6.6 0 0 0 0 .3h.5l-.5-.3.3.2-.2-.2.2.2-.2-.2-.5.3-2 .8c-1.3.4-2.8.8-4 1.3l-1.8.7-.7.6a2 2 0 0 0-.5 1 1.8 1.8 0 0 0 0 .4l.1.8.7 1.1 1.9 1.8 3 2.6a8.7 8.7 0 0 1 1.2 1.2h.4-.4.4-.4.7l-.6-.3a.7.7 0 0 0 0 .2h.6l-.6-.2.5.2-.3-.5a.6.6 0 0 0-.2.3l.5.2-.3-.5.1.2v-.2h-.1l.1.2v-.2l-.4.1h-.8c-.8 0-2 0-3.1-.2l-3.4-.2-1.5.1a3 3 0 0 0-.7.3 2 2 0 0 0-.7.6 2 2 0 0 0-.4 1.2l.2 1.2 1 2.2 1.7 3.3a13.9 13.9 0 0 1 .8 2.1h.5-.4.4-.4l.6.2-.5-.5a.7.7 0 0 0-.1.2l.6.3-.5-.5.5.5-.2-.6a.6.6 0 0 0-.3.1l.5.5-.2-.6v.3-.3.3-.3a2 2 0 0 1-.5-.1l-1.7-.8-3.4-1.8-1.6-.7c-.5-.2-1-.4-1.6-.4a2 2 0 0 0-1.2.4 2 2 0 0 0-.6.7l-.4 1a8 8 0 0 0 0 1.2c0 1 0 2.2.2 3.4a33.6 33.6 0 0 1 .1 4.1v.1l.3.2-.2-.3v.1l.2.2-.2-.3.4.5-.2-.6a.6.6 0 0 0-.2.1l.4.5-.2-.6.2.6v-.6a.7.7 0 0 0-.2 0l.2.6v-.6.4l.1-.4v.4-.4.1-.1.1-.1a2 2 0 0 1-.4-.3l-1.5-1.6-2.6-3.2-1.3-1.2a4.1 4.1 0 0 0-.8-.5 2.3 2.3 0 0 0-1-.2h-.3a2 2 0 0 0-.9.4c-.4.4-.6.7-.8 1.2-.4.7-.7 1.6-1 2.5l-1.3 4-.6 1.2v.1l.1.3-.1-.3.1.3-.1-.3.2.6V65a.6.6 0 0 0-.2 0l.2.6V65v.5l.3-.5a.6.6 0 0 0-.3 0v.5l.3-.5-.1.3.2-.2-.2.2.2-.2-.3-.5c-.3-.4-.5-1.2-.8-2-.4-1.3-.8-2.8-1.3-4-.2-.7-.5-1.3-.8-1.8a3.4 3.4 0 0 0-.5-.7 2 2 0 0 0-1-.5 1.9 1.9 0 0 0-.4 0 2.2 2.2 0 0 0-.8.1l-1.1.7-1.8 1.9-2.6 3a8.7 8.7 0 0 1-1.3 1.3l.1.3v-.4.4-.4.7l.3-.6a.7.7 0 0 0-.3 0v.6l.3-.6-.2.5.4-.3a.6.6 0 0 0-.2-.2l-.2.5.4-.3-.2.1h.3v-.1l-.3.1h.3a1.3 1.3 0 0 1-.1-.4 5.8 5.8 0 0 1 0-.8c0-.8 0-2 .2-3.1l.2-3.4-.1-1.5a3 3 0 0 0-.3-.7 2 2 0 0 0-.6-.7 2 2 0 0 0-1.2-.4l-1.2.3-2.2.9-3.3 1.7a14.3 14.3 0 0 1-2.2.9v.4l.2-.4a.4.4 0 0 0-.2 0v.4l.2-.4-.3.6.5-.5a.7.7 0 0 0-.2-.1l-.3.6.5-.5-.5.5.6-.2a.6.6 0 0 0-.1-.3l-.5.5.6-.2h-.3.3-.3.3a1.9 1.9 0 0 1 .1-.5l.8-1.7 1.8-3.4.7-1.6c.2-.5.3-1 .3-1.6a2 2 0 0 0-.3-1.2 2 2 0 0 0-.7-.6l-1.1-.4a7.8 7.8 0 0 0-1.1 0c-1 0-2.3 0-3.4.2a34.3 34.3 0 0 1-4.2.2l-.2.2.2-.2-.2.2.2-.2-.4.4.6-.2a.6.6 0 0 0-.2-.2l-.4.4.6-.2-.6.2h.6a.7.7 0 0 0 0-.2l-.6.2h.6-.4l.4.1h-.4.4-.2.2-.2.2l.3-.4 1.6-1.5c1-.8 2.2-1.7 3.1-2.6l1.3-1.3.5-.8a2.3 2.3 0 0 0 .2-1v-.3a2 2 0 0 0-.4-.9c-.4-.4-.8-.6-1.2-.8-.7-.4-1.6-.7-2.5-1l-4-1.3-1.2-.6h-.2l-.2.1.3-.1-.3.1.3-.1-.6.2h.6a.6.6 0 0 0 0-.2l-.6.2h.6H0c0 .4.2.8.3 1l.5.6L2 36l2.4 1c1.3.3 2.8.7 3.8 1.1a6.8 6.8 0 0 1 1.4.7l.1-.2-.2.2.2-.2-.2.2.5-.3h-.5a.6.6 0 0 0 0 .3l.5-.3h-.5.5-.5.5-.5.4l-.4-.1h.4-.4.1-.1.1-.1L9 39l-1.6 1.5-3 2.5-1.3 1.3a4 4 0 0 0-.4.7 2.3 2.3 0 0 0-.2 1 1.8 1.8 0 0 0 .8 1.5c.4.3.8.4 1.2.4l1.2.1 3.4-.2a34 34 0 0 1 4.1-.2h.1l.1-.2-.1.2.1-.2-.1.2.3-.4-.4.3a.6.6 0 0 0 0 .1l.4-.4-.4.3.4-.3-.5.1v.2l.5-.3-.5.1h.2-.2.2-.2l-.1.5-.8 1.8-1.8 3.3-.7 1.6c-.2.6-.3 1-.3 1.6v.7a1.8 1.8 0 0 0 1.2 1.2l.7.1c.5 0 .9 0 1.3-.2a15 15 0 0 0 2.1-1l3.4-1.7a1Line truncated

Before

Width:  |  Height:  |  Size: 8.4 KiB

-1
View File
@@ -1 +0,0 @@
<svg width="71" height="62" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowOffsetOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" fill="#FFF" fill-rule="evenodd"><path d="M69.102 15.534l-.176-1.251-17.997 2.504-1.604-11.455 16.742-2.33 1.78 12.707 1.255-.175-.176-1.251.176 1.251 1.256-.174L68.228.15 46.463 3.178l2.305 16.461 21.765-3.029-.175-1.251-1.256.174"/><path d="M48.858 15.387l-.175-1.252-15.082 2.099-.708-5.057 13.825-1.925.884 6.31 1.256-.175-.175-1.252.175 1.252 1.256-.175-1.236-8.813-18.847 2.623 1.41 10.065 18.849-2.623-.176-1.252-1.256.175"/><path d="M33.104 17.58l-.175-1.253-22.666 3.155-.708-5.058 21.41-2.98.884 6.31 1.255-.175-.175-1.252.175 1.252 1.256-.175-1.234-8.812L6.692 12.27l1.41 10.064 26.433-3.678-.175-1.252-1.256.175"/><path d="M9.345 22.071L9.17 20.82l-4.58.637-1.033-7.384 3.322-.462 1.21 8.635 1.256-.175-.175-1.251.175 1.251 1.256-.175-1.56-11.138-8.346 1.161L2.43 24.31l8.347-1.16-.176-1.253-1.256.175m17.914-3.115v39.81c0 .7.567 1.265 1.268 1.265.7 0 1.268-.566 1.268-1.264v-39.81c0-.699-.568-1.264-1.268-1.264-.7 0-1.268.565-1.268 1.263m-3.804 0v39.81c0 .7.568 1.265 1.268 1.265.7 0 1.268-.566 1.268-1.264v-39.81c0-.699-.567-1.264-1.268-1.264-.7 0-1.268.565-1.268 1.263"/><path d="M24.723 60.032h3.804c.7 0 1.268-.566 1.268-1.264 0-.698-.568-1.264-1.268-1.264h-3.804c-.7 0-1.268.566-1.268 1.264 0 .698.568 1.264 1.268 1.264m3.607-31.537l22.559 22.487a1.271 1.271 0 0 0 1.793 0 1.261 1.261 0 0 0 0-1.788L30.123 26.707a1.271 1.271 0 0 0-1.793 0 1.261 1.261 0 0 0 0 1.788m-.144 4.84l20.57 20.504a1.27 1.27 0 0 0 1.792 0 1.26 1.26 0 0 0 0-1.787L29.98 31.548a1.27 1.27 0 0 0-1.793 0 1.26 1.26 0 0 0 0 1.787"/><path d="M50.548 53.839l2.5-2.491a1.261 1.261 0 0 0 0-1.788 1.271 1.271 0 0 0-1.793 0l-2.5 2.492a1.26 1.26 0 0 0 0 1.787 1.27 1.27 0 0 0 1.793 0M23.696 26.707L1.136 49.194a1.261 1.261 0 0 0 0 1.788 1.27 1.27 0 0 0 1.793 0l22.56-22.487a1.261 1.261 0 0 0 0-1.788 1.27 1.27 0 0 0-1.793 0m.142 4.841L3.27 52.052a1.26 1.26 0 0 0 0 1.787 1.271 1.271 0 0 0 1.793 0l20.568-20.504a1.26 1.26 0 0 0 0-1.787 1.271 1.271 0 0 0-1.793 0"/><path d="M5.063 52.052l-2.5-2.492a1.27 1.27 0 0 0-1.793 0 1.261 1.261 0 0 0 0 1.788l2.5 2.491a1.271 1.271 0 0 0 1.793 0 1.26 1.26 0 0 0 0-1.787"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

@@ -1 +0,0 @@
<svg width="101" height="52" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M37.102 50.632V26h10.306v-2.737H34.354v27.369h2.748"/><path d="M28.857 52H42.6v-2.737H28.857zm0-4.79H42.6v-2.736H28.857zm39.163 3.422V23.263H54.966V26h10.306v24.632h2.748"/><path d="M59.776 52h13.741v-2.737H59.776zm0-4.79h13.741v-2.736H59.776zM39.163 13h22.674a1.37 1.37 0 0 0 1.374-1.368 1.37 1.37 0 0 0-1.374-1.369H39.163a1.37 1.37 0 0 0-1.374 1.369A1.37 1.37 0 0 0 39.163 13"/><path d="M99.626 15.737v-1.369H63.21v-4.79h35.04v6.159h1.375v-1.369 1.369H101V6.842H60.463v10.263H101v-1.368h-1.374m-60.463-.684v-1.369H2.748v-4.79H37.79v6.159h1.374v-1.369 1.369h1.374V6.158H0V16.42h40.537v-1.368h-1.374"/><path d="M9.619 7.526v6.842a1.37 1.37 0 0 0 1.374 1.369 1.37 1.37 0 0 0 1.374-1.369V7.526a1.37 1.37 0 0 0-1.374-1.368A1.37 1.37 0 0 0 9.62 7.526m15.115 0v6.842a1.37 1.37 0 0 0 1.374 1.369 1.37 1.37 0 0 0 1.374-1.369V7.526a1.37 1.37 0 0 0-1.374-1.368 1.37 1.37 0 0 0-1.374 1.368m63.898 1.369v6.842a1.37 1.37 0 0 0 1.374 1.368 1.37 1.37 0 0 0 1.374-1.368V8.895a1.37 1.37 0 0 0-1.374-1.369 1.37 1.37 0 0 0-1.374 1.369m-15.116 0v6.842a1.37 1.37 0 0 0 1.374 1.368 1.37 1.37 0 0 0 1.374-1.368V8.895a1.37 1.37 0 0 0-1.374-1.369 1.37 1.37 0 0 0-1.374 1.369M55.653 34.21v-1.368h-7.558V2.737h6.184V34.21h1.374v-1.369 1.369h1.374V0h-11.68v35.579h11.68V34.21h-1.374"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1 +0,0 @@
<svg width="47" height="54" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" fill-rule="evenodd"><path d="M38.339 48h-1.08c-.004.12-.029.224-.157.407-.113.155-.314.35-.61.55-.515.352-1.31.71-2.296 1.018-1.48.465-3.389.83-5.498 1.07-2.11.242-4.425.364-6.739.364-4.027.002-8.065-.374-11.006-1.094-1.468-.356-2.662-.808-3.395-1.273-.368-.23-.613-.457-.74-.635-.13-.183-.154-.287-.157-.407a7.28 7.28 0 0 1 1.122-3.897c1.09-1.764 2.98-3.27 5.442-4.328 2.458-1.058 5.473-1.66 8.734-1.66 4.35-.003 8.258 1.075 10.998 2.86 1.371.89 2.45 1.952 3.179 3.128A7.286 7.286 0 0 1 37.259 48h2.16a9.492 9.492 0 0 0-1.452-5.055c-1.395-2.245-3.66-3.987-6.426-5.178-2.77-1.19-6.058-1.833-9.582-1.834-4.697.003-8.978 1.14-12.166 3.207-1.593 1.035-2.913 2.31-3.841 3.805A9.482 9.482 0 0 0 4.5 48c-.004.63.228 1.23.579 1.702.307.42.697.763 1.143 1.066.782.527 1.744.938 2.86 1.29 1.67.524 3.69.901 5.895 1.155 2.205.252 4.593.378 6.982.378 4.163-.002 8.314-.376 11.515-1.156 1.604-.394 2.97-.88 4.028-1.54.528-.333.986-.714 1.338-1.192A2.878 2.878 0 0 0 39.42 48h-1.081"/><path d="M23.394 37.09V36h-2.702V2.182h1.621V37.09h1.08V36v1.09h1.081V0h-5.942v38.182h5.942V37.09h-1.08"/><path d="M45.543 16.003l.496-.969c-1.65-.864-3.33-1.182-4.953-1.18-2.222.003-4.346.566-6.41 1.092-2.066.53-4.07 1.027-6.015 1.024-1.426-.001-2.819-.254-4.26-.95l-.467.983h1.08V2.913h-1.08l-.467.983c1.755.853 3.51 1.167 5.194 1.165 2.304-.002 4.477-.564 6.545-1.091 2.069-.533 4.032-1.028 5.88-1.025 1.354.002 2.643.25 3.961.936l.496-.969h-1.08v13.091h1.08l.496-.969-.496.97h1.08V2.247l-.584-.305c-1.65-.864-3.33-1.182-4.953-1.18-2.222.003-4.346.566-6.41 1.092-2.066.53-4.07 1.027-6.015 1.024-1.426-.001-2.819-.254-4.26-.95l-1.548-.75V16.69l.614.297c1.755.853 3.51 1.167 5.194 1.165 2.304-.003 4.477-.564 6.545-1.091 2.069-.533 4.032-1.028 5.88-1.025 1.354.002 2.643.25 3.961.936l1.576.823v-1.792h-1.08M5.157 14.22l.741.33.029-.055v-.001l-.198-.146.128.206a.244.244 0 0 0 .07-.06l-.198-.146.128.206-.264-.427v.5c.11.001.21-.038.264-.073l-.264-.427v.5-.46l-.315.348a.479.479 0 0 0 .315.112v-.46l-.315.348.133-.147-.151.129.018.018.133-.147-.151.129.029-.025-.03.022v.003l.03-.025-.03.022.028.057.643 1.471c.192.435.51.762.873.996.366.231.788.377 1.25.38.071 0 .143-.005.216-.012l1.583-.174.05-.003h.014l.023-.199-.073.184.05.015.023-.199-.073.184.175-.44-.38.271a.479.479 0 0 0 .205.17l.175-.442-.38.272.412-.295h-.509c-.002.075.027.2.097.295l.412-.295h-.509.277l-.26-.106a.276.276 0 0 0-.017.106h.277l-.26-.106-.006.011-.029.042-.94 1.298a2.33 2.33 0 0 0-.42 1.364c.002.468.122.946.42 1.363L9.546 22l.029.042.005.012.121-.055-.128.031.007.024.121-.055-.128.031.343-.083h-.351l.008.083.343-.083h-.351.498l-.445-.223a.508.508 0 0 0-.053.223h.498l-.445-.223.437.22-.204-.455a.508.508 0 0 0-.233.235l.437.22-.204-.455.109.242-.048-.262-.06.02.108.242-.048-.262.006.037-.003-.038-.003.001.006.037-.003-.038h-.013l-.05-.002-1.583-.174a1.946 1.946 0 0 0-.217-.012 2.35 2.35 0 0 0-1.249.379c-.363.234-.68.56-.873.996l-.643 1.472-.028.055-.001.002.198.145-.127-.206c-.056.036-.07.06-.071.06l.198.146-.127-.206.264.428v-.5a.506.506 0 0 0-.264.072l.264.428v-.5.458l.315-.346a.475.475 0 0 0-.315-.112v.458l.315-.346-.133.146.15-.128-.017-.018-.133.146.15-.128-.028.025.03-.023-.001-.002-.03.025.032-.023-.03-.056-.642-1.472a2.29 2.29 0 0 0-.873-.996 2.349 2.349 0 0 0-1.25-.38c-.071 0-.143.005-.216.013l-1.584.174-.05.003-.013-.001-.024.2.073-.185-.05-.015-.023.2.073-.185-.174.441.379-.272a.476.476 0 0 0-.205-.17l-.174.442.379-.272-.412.295h.509a.528.528 0 0 0-.097-.295l-.412.295h.509-.277l.261.107a.305.305 0 0 0 .016-.107h-.277l.261.107.006-.012.028-.042.94-1.298c.299-.417.418-.895.42-1.363a2.33 2.33 0 0 0-.42-1.364l-.972-1.342.032.044-.028-.042-.007-.012-.12.055.128-.032-.008-.023-.12.055.128-.032-.343.084h.352l-.009-.084-.343.084h.352-.499l.445.223a.52.52 0 0 0 .054-.223h-.499l.445.223-.437-.22.204.455a.511.511 0 0 0 .233-.235l-.437-.22.204.455-.108-.242.048.263.06-.021-.108-.242.048.263-.007-.038.003.038h.004l-.007-.038.003.038h.014l.049.003 1.584.174c.073.007.145.011.216.011a2.351 2.351 0 0 0 1.25-.379c.363-.234.68-.56.873-.996l.642-1.471-.741-.33-.742-.33-.642 1.47a.678.678 0 0 1-.257.274.752.752 0 0 1-.383.126l-.04-.002-1.585-.174a2.069 2.069 0 0 0-.224-.013 1.38 1.38 0 0 0-.827.248 1.115 1.115 0 0 0-.457.91c.006.38.153.662.331.914l.94 1.297c.054.068.11.228.108.398a.705.705 0 0 1-.107.397l-.94 1.297c-.18.252-.326.534-.332.914a1.124 1.124 0 0 0 .665 1.032c.213.097.419.125.619.126.075 0 .15-.004.224-.013l1.584-.174.041-.002a.755.755 0 0 1 .383.126c.132.083.227.2.257.273l.642 1.472c.094.212.213.409.398.582.18.17.461.32.78.318.318.001.6-.147.779-.318.186-.173.305-.37.398-.582l.643-1.472a.678.678 0 0 1 .256-.273.757.757 0 0 1 .383-.126l.042.002 1.583.174c.075.009.15.013.225.013.263-.002.55-.05.827-.248a1.109 1.109 0 0 0 .456-.91c-.006-.38-.152-.661-.33-.913l-.941-1.298a.706.706 0 0 1-.107-.397.706.706 0 0 1 .107-.398l.958-1.32-.017.022c.178-.251.324-.533.33-.913a1.13 1.13 0 0 0-.116-.505 1.126 1.126 0 0 0-.549-.527 1.476 1Line truncated

Before

Width:  |  Height:  |  Size: 5.1 KiB

+35 -35
View File
@@ -2,41 +2,41 @@
Sorted by priority
| Feature | Dioxus | React | Notes |
| ---------------------- | ------ | ----- | ------------------------------------ |
| ----- Phase 1 ----- | ----- | ----- | ----- |
| Conditional Rendering | ✅ | ✅ | if/then to hide/show component |
| Map, Iterator | ✅ | ✅ | map/filter/reduce rsx! |
| Keyed Components | ✅ | ✅ | advanced diffing with keys |
| Web | ✅ | ✅ | renderer for web browser |
| Desktop (webview) | ✅ | ✅ | renderer for desktop |
| Context | ✅ | ✅ | share state through the tree |
| Hook | ✅ | ✅ | memory cells in components |
| SSR | ✅ | ✅ | render directly to string |
| Runs natively | ✅ | 👀 | runs as a sharable binary |
| Null components | 👀 | ✅ | allow returning None |
| Fragments | 👀 | ✅ | no requirement on main root |
| Component Children | 👀 | ✅ | ctx.children() as a list of nodes |
| NodeRef | 👀 | ✅ | gain direct access to nodes |
| Controlled Inputs | 👀 | ✅ | stateful wrappers around inputs |
| No-div components | 👀 | ✅ | components that render components |
| CSS/Inline Styles | 🛠 | ✅ | syntax for inline/conditional styles |
| 1st class global state | 🛠 | ✅ | redux/recoil/mobx on top of context |
| ----- Phase 2 ----- | ----- | ----- | ----- |
| 1st class router | 👀 | ✅ | Hook built on top of history |
| Assets | 👀 | ✅ | include css/svg/img url statically |
| Integrated classnames | 🛠 | 👀 | built-in `classnames` |
| Suspense | 👀 | 👀 | schedule future render from future |
| Transition | 👀 | 👀 | High-level control over suspense |
| Animation | 👀 | ✅ | Spring-style animations |
| Mobile | 👀 | ✅ | Render with cacao |
| Desktop (native) | 👀 | ✅ | Render with native desktop |
| 3D Renderer | 👀 | ✅ | react-three-fiber |
| ----- Phase 3 ----- | ----- | ----- | ----- |
| Portal | 👀 | ✅ | cast elements through tree |
| Error/Panic boundary | 👀 | ✅ | catch panics and display BSOD |
| Code-splitting | 👀 | ✅ | Make bundle smaller/lazy |
| LiveView | 👀 | 👀 | Example for SSR + WASM apps |
| Feature | Dioxus | React | Notes |
| ---------------------- | ------ | ----- | ------------------------------------------------ |
| ----- Phase 1 ----- | ----- | ----- | ----- |
| Conditional Rendering | ✅ | ✅ | if/then to hide/show component |
| Map, Iterator | ✅ | ✅ | map/filter/reduce rsx! |
| Keyed Components | ✅ | ✅ | advanced diffing with keys |
| Web | ✅ | ✅ | renderer for web browser |
| Desktop (webview) | ✅ | ✅ | renderer for desktop |
| Context | ✅ | ✅ | share state through the tree |
| Hook | ✅ | ✅ | memory cells in components |
| SSR | ✅ | ✅ | render directly to string |
| Runs natively | ✅ | 👀 | runs as a sharable binary |
| Component Children | ✅ | ✅ | ctx.children() as a list of nodes |
| Null components | ✅ | ✅ | allow returning no components |
| No-div components | ✅ | ✅ | components that render components |
| Fragments | ✅ | ✅ | rsx! can return multiple elements without a root |
| NodeRef | 👀 | ✅ | gain direct access to nodes |
| Controlled Inputs | 👀 | ✅ | stateful wrappers around inputs |
| CSS/Inline Styles | 🛠 | ✅ | syntax for inline/conditional styles |
| 1st class global state | 🛠 | ✅ | redux/recoil/mobx on top of context |
| ----- Phase 2 ----- | ----- | ----- | ----- |
| 1st class router | 👀 | ✅ | Hook built on top of history |
| Assets | 👀 | ✅ | include css/svg/img url statically |
| Integrated classnames | 🛠 | 👀 | built-in `classnames` |
| Suspense | 👀 | 👀 | schedule future render from future |
| Transition | 👀 | 👀 | High-level control over suspense |
| Animation | 👀 | ✅ | Spring-style animations |
| Mobile | 👀 | ✅ | Render with cacao |
| Desktop (native) | 👀 | ✅ | Render with native desktop |
| 3D Renderer | 👀 | ✅ | react-three-fiber |
| ----- Phase 3 ----- | ----- | ----- | ----- |
| Portal | 👀 | ✅ | cast elements through tree |
| Error/Panic boundary | 👀 | ✅ | catch panics and display BSOD |
| Code-splitting | 👀 | ✅ | Make bundle smaller/lazy |
| LiveView | 👀 | 👀 | Example for SSR + WASM apps |
## Required services:
+2 -1
View File
@@ -2,8 +2,9 @@ fn main() {}
pub mod dioxus {
pub mod prelude {
pub trait Properties {
pub unsafe trait Properties {
type Builder;
const CAN_BE_MEMOIZED: bool;
fn builder() -> Self::Builder;
}
}
+2 -1
View File
@@ -679,8 +679,9 @@ Finally, call `.build()` to create the instance of `{name}`.
}
}
impl #impl_generics dioxus::prelude::Properties for #name #ty_generics{
unsafe impl #impl_generics dioxus::prelude::Properties for #name #ty_generics{
type Builder = #builder_name #generics_with_empty;
const CAN_BE_MEMOIZED: bool = true;
fn builder() -> Self::Builder {
#name::builder()
}
+5 -6
View File
@@ -50,14 +50,13 @@ impl Parse for AmbiguousElement {
false => {
let first_char = name_str.chars().next().unwrap();
if first_char.is_ascii_uppercase() {
if name_str == "Fragment" {
input
match name_str.as_str() {
"Fragment" => input
.parse::<Fragment>()
.map(|c| AmbiguousElement::Fragment(c))
} else {
input
.map(|c| AmbiguousElement::Fragment(c)),
_ => input
.parse::<Component>()
.map(|c| AmbiguousElement::Component(c))
.map(|c| AmbiguousElement::Component(c)),
}
} else {
let name = input.parse::<Ident>().unwrap();
+25 -11
View File
@@ -26,7 +26,7 @@ pub struct Component {
// accept any path-like argument
name: syn::Path,
body: Vec<ComponentField>,
_children: Vec<Node>,
children: Vec<Node>,
}
impl Parse for Component {
@@ -41,7 +41,7 @@ impl Parse for Component {
syn::braced!(content in s);
let mut body: Vec<ComponentField> = Vec::new();
let _children: Vec<Node> = Vec::new();
let mut children: Vec<Node> = Vec::new();
'parsing: loop {
// [1] Break if empty
@@ -49,7 +49,7 @@ impl Parse for Component {
break 'parsing;
}
if content.peek(token::Brace) {
if content.peek(token::Brace) && content.peek2(Token![...]) {
let inner: ParseBuffer;
syn::braced!(inner in content);
if inner.peek(Token![...]) {
@@ -57,7 +57,11 @@ impl Parse for Component {
}
}
body.push(content.parse::<ComponentField>()?);
if content.peek(Ident) && content.peek2(Token![:]) {
body.push(content.parse::<ComponentField>()?);
} else {
children.push(content.parse::<Node>()?);
}
// consume comma if it exists
// we don't actually care if there *are* commas between attrs
@@ -66,13 +70,10 @@ impl Parse for Component {
}
}
// todo: add support for children
let children: Vec<Node> = vec![];
Ok(Self {
name,
body,
_children: children,
children,
})
}
}
@@ -109,9 +110,22 @@ impl ToTokens for Component {
None => quote! {None},
};
let _toks = tokens.append_all(quote! {
dioxus::builder::virtual_child(__ctx, #name, #builder, #key_token)
});
let childs = &self.children;
let children = quote! {
ChildrenList::new(__ctx)
#( .add_child(#childs) )*
.finish()
};
tokens.append_all(quote! {
dioxus::builder::virtual_child(
__ctx,
#name,
#builder,
#key_token,
#children
)
})
}
}
+20 -8
View File
@@ -133,6 +133,10 @@ impl Parse for ElementAttr {
}
} else {
match name_str.as_str() {
"key" => {
// todo: better error here
AttrType::BumpText(s.parse::<LitStr>()?)
}
"style" => {
//
todo!("inline style not yet supported")
@@ -196,10 +200,23 @@ impl ToTokens for ElementAttr {
let name = self.name.to_string();
let nameident = &self.name;
let _attr_stream = TokenStream2::new();
match &self.ty {
AttrType::BumpText(value) => {
AttrType::BumpText(value) => match name.as_str() {
"key" => {
tokens.append_all(quote! {
.key2(format_args_f!(#value))
});
}
_ => {
tokens.append_all(quote! {
.attr(#name, format_args_f!(#value))
});
}
},
AttrType::FieldTokens(exp) => {
tokens.append_all(quote! {
.attr(#name, format_args_f!(#value))
.attr(#name, #exp)
});
}
AttrType::Event(event) => {
@@ -207,16 +224,11 @@ impl ToTokens for ElementAttr {
.add_listener(dioxus::events::on::#nameident(__ctx, #event))
});
}
AttrType::FieldTokens(exp) => {
tokens.append_all(quote! {
.attr(#name, #exp)
});
}
AttrType::EventTokens(event) => {
//
tokens.append_all(quote! {
.add_listener(dioxus::events::on::#nameident(__ctx, #event))
})
});
}
}
}
+36 -3
View File
@@ -8,6 +8,10 @@
//! - [ ] Children
//! - [ ] Keys
use syn::parse::ParseBuffer;
use super::AmbiguousElement;
use {
proc_macro::TokenStream,
proc_macro2::{Span, TokenStream as TokenStream2},
@@ -19,15 +23,44 @@ use {
},
};
pub struct Fragment {}
pub struct Fragment {
children: Vec<AmbiguousElement>,
}
impl Parse for Fragment {
fn parse(input: ParseStream) -> Result<Self> {
todo!()
input.parse::<Ident>()?;
let children = Vec::new();
// parse the guts
let content: ParseBuffer;
syn::braced!(content in input);
while !content.is_empty() {
content.parse::<AmbiguousElement>()?;
if content.peek(Token![,]) {
let _ = content.parse::<Token![,]>();
}
}
Ok(Self { children })
}
}
impl ToTokens for Fragment {
fn to_tokens(&self, tokens: &mut TokenStream2) {
todo!()
let childs = &self.children;
let children = quote! {
ChildrenList::new(__ctx)
#( .add_child(#childs) )*
.finish()
};
tokens.append_all(quote! {
// #key_token,
dioxus::builder::vfragment(
__ctx,
None,
#children
)
})
}
}
+40 -29
View File
@@ -26,7 +26,7 @@ pub use node::*;
use crate::util::is_valid_tag;
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens};
use quote::{quote, ToTokens, TokenStreamExt};
use syn::{
parse::{Parse, ParseStream},
Error, Ident, LitStr, Result, Token,
@@ -34,7 +34,7 @@ use syn::{
pub struct RsxRender {
custom_context: Option<Ident>,
root: AmbiguousElement,
roots: Vec<AmbiguousElement>,
}
impl Parse for RsxRender {
@@ -61,16 +61,13 @@ impl Parse for RsxRender {
None
};
let root = { input.parse::<AmbiguousElement>() }?;
if !input.is_empty() {
return Err(Error::new(
input.span(),
"Currently only one element is allowed per component. Try wrapping your list of components in a `Fragment` tag",
));
let mut roots = Vec::new();
while !input.is_empty() {
roots.push(input.parse::<AmbiguousElement>()?);
}
Ok(Self {
root,
roots,
custom_context,
})
}
@@ -78,27 +75,41 @@ impl Parse for RsxRender {
impl ToTokens for RsxRender {
fn to_tokens(&self, out_tokens: &mut TokenStream2) {
let inner = &self.root;
let output = match &self.custom_context {
// The `in ctx` pattern allows directly rendering
Some(ident) => {
quote! {
#ident.render(dioxus::prelude::LazyNodes::new(move |__ctx|{
let bump = &__ctx.bump();
#inner
}))
}
}
// Otherwise we just build the LazyNode wrapper
None => {
quote! {
dioxus::prelude::LazyNodes::new(move |__ctx|{
let bump = &__ctx.bump();
#inner
})
}
let inner = if self.roots.len() == 1 {
let inner = &self.roots[0];
quote! {#inner}
} else {
let childs = &self.roots;
let children = quote! {
ChildrenList::new(__ctx)
#( .add_child(#childs) )*
.finish()
};
quote! {
// #key_token,
dioxus::builder::vfragment(
__ctx,
None,
#children
)
}
};
output.to_tokens(out_tokens)
match &self.custom_context {
// The `in ctx` pattern allows directly rendering
Some(ident) => out_tokens.append_all(quote! {
#ident.render(dioxus::prelude::LazyNodes::new(move |__ctx|{
let bump = &__ctx.bump();
#inner
}))
}),
// Otherwise we just build the LazyNode wrapper
None => out_tokens.append_all(quote! {
dioxus::prelude::LazyNodes::new(move |__ctx|{
let bump = &__ctx.bump();
#inner
})
}),
};
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
{
"rust-analyzer.inlayHints.enable": false
"rust-analyzer.inlayHints.enable": true
}
+1
View File
@@ -39,6 +39,7 @@ fn app(ctx: Context<Props>) -> VNode {
.item_handler(Callback(set_val.clone()))
.build(),
None,
&[],
));
}
root.finish()
+2
View File
@@ -15,9 +15,11 @@ static Header: FC<()> = |ctx| {
ctx.render(dioxus::prelude::LazyNodes::new(|nodectx| {
builder::ElementBuilder::new(nodectx, "div")
.child(VNode::Component(nodectx.bump().alloc(VComponent::new(
nodectx,
Bottom,
(),
None,
&[],
))))
.finish()
}))
+27 -2
View File
@@ -9,9 +9,9 @@ use generational_arena::Arena;
use crate::innerlude::*;
#[derive(Clone)]
pub struct ScopeArena(Rc<RefCell<ScopeArenaInner>>);
pub struct ScopeArena(pub Rc<RefCell<ScopeArenaInner>>);
struct ScopeArenaInner {
pub struct ScopeArenaInner {
pub(crate) arena: UnsafeCell<Arena<Scope>>,
locks: HashMap<ScopeIdx, MutStatus>,
}
@@ -61,6 +61,31 @@ impl ScopeArena {
// todo!()
}
pub fn with_scope<'b, O: 'static>(
&'b self,
id: ScopeIdx,
f: impl FnOnce(&'b mut Scope) -> O,
) -> Result<O> {
todo!()
}
// return a bumpframe with a lifetime attached to the arena borrow
// this is useful for merging lifetimes
pub fn with_scope_vnode<'b>(
&self,
id: ScopeIdx,
f: impl FnOnce(&mut Scope) -> &VNode<'b>,
) -> Result<&VNode<'b>> {
todo!()
}
pub fn try_remove(&mut self, id: ScopeIdx) -> Result<Scope> {
let inner = unsafe { &mut *self.0.borrow().arena.get() };
inner
.remove(id)
.ok_or_else(|| Error::FatalInternal("Scope not found"))
}
unsafe fn inner_unchecked<'s>() -> &'s mut Arena<Scope> {
todo!()
}
+13 -118
View File
@@ -7,21 +7,14 @@
use crate::innerlude::FC;
pub type ScopeIdx = generational_arena::Index;
pub trait Properties: PartialEq {
pub unsafe trait Properties: PartialEq + Sized {
type Builder;
const CAN_BE_MEMOIZED: bool;
fn builder() -> Self::Builder;
}
pub struct EmptyBuilder;
impl EmptyBuilder {
pub fn build(self) -> () {
()
}
}
impl Properties for () {
unsafe impl Properties for () {
const CAN_BE_MEMOIZED: bool = true;
type Builder = EmptyBuilder;
fn builder() -> Self::Builder {
@@ -29,112 +22,14 @@ impl Properties for () {
}
}
pub fn fc_to_builder<T: Properties>(_f: FC<T>) -> T::Builder {
pub struct EmptyBuilder;
impl EmptyBuilder {
#[inline]
pub fn build(self) -> () {
()
}
}
pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
T::builder()
}
mod testing {
use std::any::Any;
// trait PossibleProps {
// type POut: PartialEq;
// fn as_partial_eq(&self) -> Option<&Self::POut> {
// None
// }
// }
// impl<T: PartialEq> PossibleProps for T {
// type POut = Self;
// }
// struct SomeProps2<'a> {
// inner: &'a str,
// }
// Fallback trait for to all types to default to `false`.
trait NotEq {
const IS_EQ: bool = false;
}
impl<T> NotEq for T {}
// Concrete wrapper type where `IS_COPY` becomes `true` if `T: Copy`.
struct IsEq<G, T>(std::marker::PhantomData<(G, T)>);
impl<G: PartialEq, T: PartialEq<G>> IsEq<G, T> {
// Because this is implemented directly on `IsCopy`, it has priority over
// the `NotCopy` trait impl.
//
// Note: this is a *totally different* associated constant from that in
// `NotCopy`. This does not specialize the `NotCopy` trait impl on `IsCopy`.
const IS_EQ: bool = true;
}
#[derive(PartialEq)]
struct SomeProps {
inner: &'static str,
}
struct SomeProps2 {
inner: &'static str,
}
#[test]
fn test() {
let g = IsEq::<SomeProps, SomeProps>::IS_EQ;
// let g = IsEq::<Vec<u32>>::IS_COPY;
// let g = IsEq::<u32>::IS_COPY;
// dbg!(g);
// let props = SomeProps { inner: "asd" };
// let intermediate: Box<dyn PartialEq<SomeProps>> = Box::new(props);
// let as_any: Box<dyn Any> = Box::new(intermediate);
// let as_partialeq = as_any
// .downcast_ref::<Box<dyn PartialEq<SomeProps>>>()
// .unwrap();
}
// struct blah {}
// #[reorder_args]
pub fn blah(a: i32, b: &str, c: &str) {}
// pub mod blah {
// pub const a: u8 = 0;
// pub const b: u8 = 1;
// }
trait Eat {}
impl Eat for fn() {}
impl<T> Eat for fn(T) {}
impl<T, K> Eat for fn(T, K) {}
mod other {
use super::blah;
fn test2() {
// rsx!{
// div {
// Ele {
// a: 10,
// b: "asd"
// c: impl Fn() -> ()
// }
// }
// }
// becomes
// const reorder: fn(_, _) = |a, b| {};
// blah::META;
// let a = 10;
// let b = "asd";
// let g = [10, 10.0];
// let c = g.a;
// blah(10, "asd");
}
}
}
mod style {}
+196 -110
View File
@@ -32,7 +32,7 @@
//!
//! More info on how to improve this diffing algorithm:
//! - https://hacks.mozilla.org/2019/03/fast-bump-allocated-virtual-doms-with-rust-and-wasm/
use crate::innerlude::*;
use crate::{arena::ScopeArena, innerlude::*};
use bumpalo::Bump;
use fxhash::{FxHashMap, FxHashSet};
use generational_arena::Arena;
@@ -59,50 +59,29 @@ use std::{
/// subscriptions and props changes.
pub struct DiffMachine<'a> {
pub create_diffs: bool,
pub cur_idx: ScopeIdx,
pub change_list: EditMachine<'a>,
pub diffed: FxHashSet<ScopeIdx>,
pub lifecycle_events: VecDeque<LifeCycleEvent<'a>>,
}
pub enum LifeCycleEvent<'a> {
Mount {
caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
stable_scope_addr: Weak<VCompAssociatedScope>,
root_id: u32,
},
PropsChanged {
caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
stable_scope_addr: Weak<VCompAssociatedScope>,
root_id: u32,
},
SameProps {
caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
stable_scope_addr: Weak<VCompAssociatedScope>,
root_id: u32,
},
Replace {
caller: Weak<dyn Fn(&Scope) -> VNode + 'a>,
old_scope: Weak<VCompAssociatedScope>,
new_scope: Weak<VCompAssociatedScope>,
root_id: u32,
},
Remove {
stable_scope_addr: Weak<VCompAssociatedScope>,
root_id: u32,
},
pub components: ScopeArena,
pub event_queue: EventQueue,
pub seen_nodes: FxHashSet<ScopeIdx>,
}
static COUNTER: AtomicU32 = AtomicU32::new(1);
fn get_id() -> u32 {
fn next_id() -> u32 {
COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
}
impl<'a> DiffMachine<'a> {
pub fn new() -> Self {
pub fn new(components: ScopeArena, cur_idx: ScopeIdx, event_queue: EventQueue) -> Self {
Self {
components,
cur_idx,
event_queue,
create_diffs: true,
lifecycle_events: VecDeque::new(),
change_list: EditMachine::new(),
diffed: FxHashSet::default(),
seen_nodes: FxHashSet::default(),
}
}
@@ -110,15 +89,15 @@ impl<'a> DiffMachine<'a> {
self.change_list.emitter
}
pub fn diff_node(&mut self, old: &VNode<'a>, new: &VNode<'a>) {
pub fn diff_node(&mut self, old_node: &VNode<'a>, new_node: &VNode<'a>) {
// pub fn diff_node(&mut self, old: &VNode<'a>, new: &VNode<'a>) {
/*
For each valid case, we "commit traversal", meaning we save this current position in the tree.
Then, we diff and queue an edit event (via chagelist). s single trees - when components show up, we save that traversal and then re-enter later.
When re-entering, we reuse the EditList in DiffState
*/
match (old, new) {
(VNode::Text(VText { text: old_text }), VNode::Text(VText { text: new_text })) => {
match (old_node, new_node) {
(VNode::Text(old_text), VNode::Text(new_text)) => {
if old_text != new_text {
self.change_list.commit_traversal();
self.change_list.set_text(new_text);
@@ -127,13 +106,13 @@ impl<'a> DiffMachine<'a> {
(VNode::Text(_), VNode::Element(_)) => {
self.change_list.commit_traversal();
self.create(new);
self.create(new_node);
self.change_list.replace_with();
}
(VNode::Element(_), VNode::Text(_)) => {
self.change_list.commit_traversal();
self.create(new);
self.create(new_node);
self.change_list.replace_with();
}
@@ -151,55 +130,86 @@ impl<'a> DiffMachine<'a> {
}
(VNode::Component(cold), VNode::Component(cnew)) => {
// todo!("should not happen")
// self.change_list.commit_traversal();
// Make sure we're dealing with the same component (by function pointer)
if cold.user_fc == cnew.user_fc {
// todo: create a stable addr
let caller = Rc::downgrade(&cnew.caller);
let id = cold.stable_addr.borrow().unwrap();
*cnew.stable_addr.borrow_mut() = Some(id);
*cnew.ass_scope.borrow_mut() = *cold.ass_scope.borrow();
// Make sure the new component vnode is referencing the right scope id
let scope_id = cold.ass_scope.borrow().clone();
*cnew.ass_scope.borrow_mut() = scope_id;
let scope = Rc::downgrade(&cold.ass_scope);
self.lifecycle_events
.push_back(LifeCycleEvent::PropsChanged {
caller,
root_id: id,
stable_scope_addr: scope,
});
// make sure the component's caller function is up to date
self.components
.with_scope(scope_id.unwrap(), |scope| {
scope.caller = Rc::downgrade(&cnew.caller)
})
.unwrap();
// React doesn't automatically memoize, but we do.
// The cost is low enough to make it worth checking
let should_render = match cold.comparator {
Some(comparator) => comparator(cnew),
None => true,
};
if should_render {
self.change_list.commit_traversal();
self.components
.with_scope(scope_id.unwrap(), |f| {
f.run_scope().unwrap();
})
.unwrap();
// diff_machine.change_list.load_known_root(root_id);
// run the scope
//
} else {
// Component has memoized itself and doesn't need to be re-rendered.
// We still need to make sure the child's props are up-to-date.
// Don't commit traversal
}
} else {
let caller = Rc::downgrade(&cnew.caller);
let id = cold.stable_addr.borrow().unwrap();
let old_scope = Rc::downgrade(&cold.ass_scope);
let new_scope = Rc::downgrade(&cnew.ass_scope);
// A new component has shown up! We need to destroy the old node
self.lifecycle_events.push_back(LifeCycleEvent::Replace {
caller,
root_id: id,
old_scope,
new_scope,
});
// Wipe the old one and plant the new one
self.change_list.commit_traversal();
self.create(new_node);
self.change_list.replace_with();
// Now we need to remove the old scope and all of its descendents
let old_scope = cold.ass_scope.borrow().as_ref().unwrap().clone();
self.destroy_scopes(old_scope);
}
}
// todo: knock out any listeners
(_, VNode::Component(_new)) => {
(_, VNode::Component(_)) => {
self.change_list.commit_traversal();
self.create(new_node);
self.change_list.replace_with();
}
// A component is being torn down in favor of a non-component node
(VNode::Component(_old), _) => {
todo!("Usage of component VNode not currently supported");
self.change_list.commit_traversal();
self.create(new_node);
self.change_list.replace_with();
// Destroy the original scope and any of its children
self.destroy_scopes(_old.ass_scope.borrow().unwrap());
}
// Anything suspended is not enabled ATM
(VNode::Suspended, _) | (_, VNode::Suspended) => {
todo!("Suspended components not currently available")
}
(VNode::Fragment(_), VNode::Fragment(_)) => {
// Fragments are special
// we actually have to remove a bunch of nodes
(VNode::Fragment(_), _) => {
todo!("Fragments not currently supported in diffing")
}
(_, VNode::Fragment(_)) => {
todo!("Fragments not currently supported in diffing")
}
(_, VNode::Fragment(_)) => todo!("Fragments not currently supported in diffing"),
(VNode::Fragment(_), _) => todo!("Fragments not currently supported in diffing"),
}
}
@@ -215,11 +225,11 @@ impl<'a> DiffMachine<'a> {
fn create(&mut self, node: &VNode<'a>) {
debug_assert!(self.change_list.traversal_is_committed());
match node {
VNode::Text(VText { text }) => {
VNode::Text(text) => {
self.change_list.create_text_node(text);
}
VNode::Element(&VElement {
key: _,
key,
tag_name,
listeners,
attributes,
@@ -250,7 +260,7 @@ impl<'a> DiffMachine<'a> {
// text content, and finally (3) append the text node to this
// parent.
if children.len() == 1 {
if let VNode::Text(VText { text }) = children[0] {
if let VNode::Text(text) = children[0] {
self.change_list.set_text(text);
return;
}
@@ -258,35 +268,121 @@ impl<'a> DiffMachine<'a> {
for child in children {
self.create(child);
self.change_list.append_child();
if let VNode::Fragment(_) = child {
// do nothing
// fragments append themselves
} else {
self.change_list.append_child();
}
}
}
/*
todo: integrate re-entrace
*/
VNode::Component(component) => {
self.change_list
.create_text_node("placeholder for vcomponent");
let id = get_id();
*component.stable_addr.as_ref().borrow_mut() = Some(id);
self.change_list.save_known_root(id);
let scope = Rc::downgrade(&component.ass_scope);
self.lifecycle_events.push_back(LifeCycleEvent::Mount {
caller: Rc::downgrade(&component.caller),
root_id: id,
stable_scope_addr: scope,
});
let root_id = next_id();
self.change_list.save_known_root(root_id);
log::debug!("Mounting a new component");
let caller: Weak<OpaqueComponent> = Rc::downgrade(&component.caller);
// We're modifying the component arena while holding onto references into the assoiated bump arenas of its children
// those references are stable, even if the component arena moves around in memory, thanks to the bump arenas.
// However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime.
let parent_idx = self.cur_idx;
// Insert a new scope into our component list
let idx = self
.components
.with(|components| {
components.insert_with(|new_idx| {
let parent_scope = self.components.try_get(parent_idx).unwrap();
let height = parent_scope.height + 1;
Scope::new(
caller,
new_idx,
Some(parent_idx),
height,
self.event_queue.new_channel(height, new_idx),
self.components.clone(),
component.children,
)
})
})
.unwrap();
{
let cur_component = self.components.try_get_mut(idx).unwrap();
let mut ch = cur_component.descendents.borrow_mut();
ch.insert(idx);
std::mem::drop(ch);
}
// yaaaaay lifetimes out of thin air
// really tho, we're merging the frame lifetimes together
let inner: &'a mut _ = unsafe { &mut *self.components.0.borrow().arena.get() };
let new_component = inner.get_mut(idx).unwrap();
// Actually initialize the caller's slot with the right address
*component.ass_scope.borrow_mut() = Some(idx);
// Run the scope for one iteration to initialize it
new_component.run_scope().unwrap();
// And then run the diff algorithm
self.diff_node(new_component.old_frame(), new_component.next_frame());
// Finally, insert this node as a seen node.
self.seen_nodes.insert(idx);
}
// we go the the "known root" but only operate on a sibling basis
VNode::Fragment(frag) => {
// create the children directly in the space
for child in frag.children {
self.create(child);
self.change_list.append_child();
}
}
VNode::Suspended => {
todo!("Creation of VNode::Suspended not yet supported")
}
VNode::Fragment(frag) => {
//
todo!("Cannot current create fragments")
}
}
/// Destroy a scope and all of its descendents.
///
/// Calling this will run the destuctors on all hooks in the tree.
/// It will also add the destroyed nodes to the `seen_nodes` cache to prevent them from being renderered.
fn destroy_scopes(&mut self, old_scope: ScopeIdx) {
let mut nodes_to_delete = vec![old_scope];
let mut scopes_to_explore = vec![old_scope];
// explore the scope tree breadth first
while let Some(scope_id) = scopes_to_explore.pop() {
// If we're planning on deleting this node, then we don't need to both rendering it
self.seen_nodes.insert(scope_id);
let scope = self.components.try_get(scope_id).unwrap();
for child in scope.descendents.borrow().iter() {
// Add this node to be explored
scopes_to_explore.push(child.clone());
// Also add it for deletion
nodes_to_delete.push(child.clone());
}
}
// Delete all scopes that we found as part of this subtree
for node in nodes_to_delete {
log::debug!("Removing scope {:#?}", node);
let _scope = self.components.try_remove(node).unwrap();
// do anything we need to do to delete the scope
// I think we need to run the destructors on the hooks
// TODO
}
}
// Diff event listeners between `old` and `new`.
@@ -297,7 +393,6 @@ impl<'a> DiffMachine<'a> {
//
// The change list stack is left unchanged.
fn diff_listeners(&mut self, old: &[Listener<'_>], new: &[Listener<'_>]) {
// fn diff_listeners(&mut self, old: &[Listener<'a>], new: &[Listener<'a>]) {
if !old.is_empty() || !new.is_empty() {
self.change_list.commit_traversal();
}
@@ -319,26 +414,15 @@ impl<'a> DiffMachine<'a> {
.update_event_listener(event_type, new_l.scope, new_l.id)
}
// if let Some(scope) = self.current_idx {
// let cb = CbIdx::from_gi_index(scope, l_idx);
// self.change_list
// .update_event_listener(event_type, new_l.scope, new_l.id);
// }
continue 'outer1;
}
}
// if let Some(scope) = self.current_idx {
// let cb = CbIdx::from_gi_index(scope, l_idx);
self.change_list
.new_event_listener(event_type, new_l.scope, new_l.id);
// }
}
'outer2: for old_l in old {
// registry.remove(old_l);
for new_l in new {
if new_l.event == old_l.event {
continue 'outer2;
@@ -363,6 +447,9 @@ impl<'a> DiffMachine<'a> {
) {
// Do O(n^2) passes to add/update and remove attributes, since
// there are almost always very few attributes.
//
// The "fast" path is when the list of attributes name is identical and in the same order
// With the Rsx and Html macros, this will almost always be the case
'outer: for new_attr in new {
if new_attr.is_volatile() {
self.change_list.commit_traversal();
@@ -380,6 +467,8 @@ impl<'a> DiffMachine<'a> {
);
}
continue 'outer;
} else {
// names are different, a varying order of attributes has arrived
}
}
@@ -420,22 +509,17 @@ impl<'a> DiffMachine<'a> {
if new.len() == 1 {
match (old.first(), &new[0]) {
(
Some(&VNode::Text(VText { text: old_text })),
&VNode::Text(VText { text: new_text }),
) if old_text == new_text => {
(Some(&VNode::Text(old_text)), &VNode::Text(new_text)) if old_text == new_text => {
// Don't take this fast path...
}
(_, &VNode::Text(VText { text })) => {
(_, &VNode::Text(text)) => {
self.change_list.commit_traversal();
self.change_list.set_text(text);
// for o in old {
// registry.remove_subtree(o);
// }
return;
}
// todo: any more optimizations
(_, _) => {}
}
}
@@ -462,6 +546,7 @@ impl<'a> DiffMachine<'a> {
if new_is_keyed && old_is_keyed {
let t = self.change_list.next_temporary();
self.diff_keyed_children(old, new);
self.change_list.set_next_temporary(t);
} else {
self.diff_non_keyed_children(old, new);
@@ -977,11 +1062,12 @@ impl<'a> DiffMachine<'a> {
// self.change_list
// .create_text_node("placeholder for vcomponent");
let root_id = vcomp.stable_addr.as_ref().borrow().unwrap();
self.lifecycle_events.push_back(LifeCycleEvent::Remove {
root_id,
stable_scope_addr: Rc::downgrade(&vcomp.ass_scope),
})
todo!()
// let root_id = vcomp.stable_addr.as_ref().borrow().unwrap();
// self.lifecycle_events.push_back(LifeCycleEvent::Remove {
// root_id,
// stable_scope_addr: Rc::downgrade(&vcomp.ass_scope),
// })
// let id = get_id();
// *component.stable_addr.as_ref().borrow_mut() = Some(id);
// self.change_list.save_known_root(id);
+2 -14
View File
@@ -120,14 +120,12 @@ pub mod prelude {
pub use crate::nodebuilder::LazyNodes;
pub use crate::nodebuilder::ChildrenList;
pub use crate::virtual_dom::NodeCtx;
// pub use nodes::iterables::IterableNodes;
/// This type alias is an internal way of abstracting over the static functions that represent components.
pub use crate::innerlude::FC;
// TODO @Jon, fix this
// hack the VNode type until VirtualNode is fixed in the macro crate
// expose our bumpalo type
pub use bumpalo;
pub use bumpalo::Bump;
@@ -139,19 +137,9 @@ pub mod prelude {
pub use dioxus_core_macro::{format_args_f, html, rsx, Props};
pub use crate::component::ScopeIdx;
pub use crate::diff::DiffMachine;
pub use crate::virtual_dom::ScopeIdx;
pub use crate::debug_renderer::DebugRenderer;
pub use crate::dioxus_main;
pub use crate::hooks::*;
}
#[macro_export]
macro_rules! dioxus_main {
($i:ident) => {
fn main() {
todo!("this macro is a placeholder for launching a dioxus app on different platforms. \nYou probably don't want to use this, but it's okay for small apps.")
}
};
}
+59 -8
View File
@@ -1,12 +1,12 @@
//! Helpers for building virtual DOM VNodes.
use std::{any::Any, borrow::BorrowMut, intrinsics::transmute, u128};
use std::{any::Any, borrow::BorrowMut, fmt::Arguments, intrinsics::transmute, u128};
use crate::{
events::VirtualEvent,
innerlude::{Properties, VComponent, FC},
nodes::{Attribute, Listener, NodeKey, VNode},
prelude::VElement,
prelude::{VElement, VFragment},
virtual_dom::NodeCtx,
};
@@ -269,6 +269,20 @@ where
self
}
pub fn key2(mut self, args: Arguments) -> Self {
let key = match args.as_str() {
Some(static_str) => static_str,
None => {
use bumpalo::core_alloc::fmt::Write;
let mut s = bumpalo::collections::String::new_in(self.ctx.bump());
s.write_fmt(args).unwrap();
s.into_bump_str()
}
};
self.key = NodeKey(Some(key));
self
}
/// Create the virtual DOM VNode described by this builder.
///
/// # Example
@@ -650,17 +664,54 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
Attribute { name, value }
}
pub fn virtual_child<'a, T: Properties>(
pub fn virtual_child<'a, T: Properties + 'a>(
ctx: &NodeCtx<'a>,
f: FC<T>,
props: T,
key: Option<&'a str>, // key: NodeKey<'a>,
children: &'a [VNode<'a>],
) -> VNode<'a> {
// currently concerned about if props have a custom drop implementation
// might override it with the props macro
todo!()
// VNode::Component(
// ctx.bump()
// .alloc(crate::nodes::VComponent::new(f, props, key)),
// )
// todo!()
VNode::Component(
ctx.bump()
.alloc(crate::nodes::VComponent::new(ctx, f, props, key, children)),
// ctx.bump()
// .alloc(crate::nodes::VComponent::new(f, props, key)),
)
}
pub fn vfragment<'a>(
ctx: &NodeCtx<'a>,
key: Option<&'a str>, // key: NodeKey<'a>,
children: &'a [VNode<'a>],
) -> VNode<'a> {
VNode::Fragment(ctx.bump().alloc(VFragment::new(key, children)))
}
pub struct ChildrenList<'a, 'b> {
ctx: &'b NodeCtx<'a>,
children: bumpalo::collections::Vec<'a, VNode<'a>>,
}
impl<'a, 'b> ChildrenList<'a, 'b> {
pub fn new(ctx: &'b NodeCtx<'a>) -> Self {
Self {
ctx,
children: bumpalo::collections::Vec::new_in(ctx.bump()),
}
}
pub fn add_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
for item in nodes {
let child = item.into_vnode(&self.ctx);
self.children.push(child);
}
self
}
pub fn finish(self) -> &'a [VNode<'a>] {
self.children.into_bump_slice()
}
}
+105 -67
View File
@@ -7,6 +7,8 @@ use crate::{
events::VirtualEvent,
innerlude::{Context, Properties, Scope, ScopeIdx, FC},
nodebuilder::text3,
virtual_dom::NodeCtx,
// support::NodeCtx,
};
use bumpalo::Bump;
use std::{
@@ -27,7 +29,7 @@ pub enum VNode<'src> {
Element(&'src VElement<'src>),
/// A text node (node type `TEXT_NODE`).
Text(VText<'src>),
Text(&'src str),
/// A fragment is a "virtual position" in the DOM
/// Fragments may have children and keys
@@ -46,11 +48,11 @@ pub enum VNode<'src> {
impl<'a> Clone for VNode<'a> {
fn clone(&self) -> Self {
match self {
VNode::Element(el) => VNode::Element(el),
VNode::Text(origi) => VNode::Text(VText { text: origi.text }),
VNode::Fragment(frag) => VNode::Fragment(frag),
VNode::Element(element) => VNode::Element(element),
VNode::Text(text) => VNode::Text(text),
VNode::Fragment(fragment) => VNode::Fragment(fragment),
VNode::Component(component) => VNode::Component(component),
VNode::Suspended => VNode::Suspended,
VNode::Component(c) => VNode::Component(c),
}
}
}
@@ -86,7 +88,7 @@ impl<'a> VNode<'a> {
/// Construct a new text node with the given text.
#[inline]
pub fn text(text: &'a str) -> VNode<'a> {
VNode::Text(VText { text })
VNode::Text(text)
}
pub fn text_args(bump: &'a Bump, args: Arguments) -> VNode<'a> {
@@ -210,51 +212,34 @@ impl<'a> NodeKey<'a> {
}
}
#[derive(Debug, PartialEq)]
pub struct VText<'bump> {
pub text: &'bump str,
}
impl<'b> Clone for VText<'b> {
fn clone(&self) -> Self {
Self { text: self.text }
}
}
impl<'a> VText<'a> {
// / Create an new `VText` instance with the specified text.
pub fn new(text: &'a str) -> Self {
VText { text: text.into() }
}
}
// ==============================
// Custom components
// ==============================
/// Virtual Components for custom user-defined components
/// Only supports the functional syntax
pub type StableScopeAddres = RefCell<Option<u32>>;
pub type VCompAssociatedScope = RefCell<Option<ScopeIdx>>;
pub type StableScopeAddres = Option<u32>;
pub type VCompAssociatedScope = Option<ScopeIdx>;
pub struct VComponent<'src> {
pub key: NodeKey<'src>,
pub stable_addr: Rc<StableScopeAddres>,
pub ass_scope: Rc<VCompAssociatedScope>,
pub stable_addr: RefCell<StableScopeAddres>,
pub ass_scope: RefCell<VCompAssociatedScope>,
// pub comparator: Rc<dyn Fn(&VComponent) -> bool + 'src>,
pub caller: Rc<dyn Fn(&Scope) -> VNode + 'src>,
pub caller: Rc<dyn Fn(&Scope) -> VNode>,
pub children: &'src [VNode<'src>],
pub comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
// a pointer into the bump arena (given by the 'src lifetime)
// raw_props: Box<dyn Any>,
// raw_props: *const (),
raw_props: *const (),
// a pointer to the raw fn typ
pub user_fc: *const (),
_p: PhantomData<&'src ()>,
}
impl<'a> VComponent<'a> {
@@ -264,70 +249,123 @@ impl<'a> VComponent<'a> {
// TODO: lift the requirement that props need to be static
// we want them to borrow references... maybe force implementing a "to_static_unsafe" trait
pub fn new<P: Properties>(
pub fn new<P: Properties + 'a>(
// bump: &'a Bump,
ctx: &NodeCtx<'a>,
component: FC<P>,
// props: bumpalo::boxed::Box<'a, P>,
props: P,
key: Option<&'a str>,
children: &'a [VNode<'a>],
) -> Self {
// pub fn new<P: Properties + 'a>(component: FC<P>, props: P, key: Option<&'a str>) -> Self {
// let bad_props = unsafe { transmogrify(props) };
let bump = ctx.bump();
let caller_ref = component as *const ();
let props = bump.alloc(props);
// let raw_props = props as *const P as *const ();
let raw_props = props as *const P as *const ();
// let props_comparator = move |other: &VComponent| {
// // Safety:
// // We are guaranteed that the props will be of the same type because
// // there is no way to create a VComponent other than this `new` method.
// //
// // Therefore, if the render functions are identical (by address), then so will be
// // props type paramter (because it is the same render function). Therefore, we can be
// // sure
// if caller_ref == other.user_fc {
// let g = other.raw_ctx.downcast_ref::<P>().unwrap();
// // let real_other = unsafe { &*(other.raw_props as *const _ as *const P) };
// &props == g
// } else {
// false
// }
// };
let comparator: Option<&dyn Fn(&VComponent) -> bool> = {
if P::CAN_BE_MEMOIZED {
Some(bump.alloc(move |other: &VComponent| {
// Safety:
// We are guaranteed that the props will be of the same type because
// there is no way to create a VComponent other than this `new` method.
//
// Therefore, if the render functions are identical (by address), then so will be
// props type paramter (because it is the same render function). Therefore, we can be
// sure
if caller_ref == other.user_fc {
// let g = other.raw_ctx.downcast_ref::<P>().unwrap();
let real_other = unsafe { &*(other.raw_props as *const _ as *const P) };
&props == &real_other
} else {
false
}
}))
} else {
None
}
};
// let prref: &'a P = props.as_ref();
let caller: Rc<dyn Fn(&Scope) -> VNode> = Rc::new(move |scope| {
//
// let props2 = bad_props;
// props.as_ref()
// let ctx = Context {
// props: prref,
// scope,
// };
todo!()
// component(ctx)
});
// let caller = Rc::new(create_closure(component, raw_props));
// let r = create_closure(component, raw_props);
// let caller: Rc<dyn for<'g> Fn(&'g Scope) -> VNode<'g>> = Rc::new(move |scope| {
// // r(scope);
// //
// // let props2 = bad_props;
// // props.as_ref();
// // let ctx = Context {
// // props: prref,
// // scope,
// // };
// // let ctx: Context<'g, P> = todo!();
// // todo!()
// // let r = component(ctx);
// todo!()
// });
let caller = create_closure(component, raw_props);
// let caller: Rc<dyn Fn(&Scope) -> VNode> = Rc::new(create_closure(component, raw_props));
let key = match key {
Some(key) => NodeKey::new(key),
None => NodeKey(None),
};
// raw_props: Box::new(props),
// comparator: Rc::new(props_comparator),
Self {
key,
ass_scope: Rc::new(RefCell::new(None)),
ass_scope: RefCell::new(None),
user_fc: caller_ref,
// raw_props: Box::new(props),
_p: PhantomData,
children: &[],
comparator,
raw_props,
children,
caller,
// comparator: Rc::new(props_comparator),
stable_addr: Rc::new(RefCell::new(None)),
stable_addr: RefCell::new(None),
}
}
}
type Captured<'a> = Rc<dyn for<'r> Fn(&'r Scope) -> VNode<'r> + 'a>;
fn create_closure<'a, P: Properties + 'a>(
component: FC<P>,
raw_props: *const (),
) -> Rc<dyn for<'r> Fn(&'r Scope) -> VNode<'r>> {
// ) -> impl for<'r> Fn(&'r Scope) -> VNode<'r> {
let g: Captured = Rc::new(move |scp: &Scope| -> VNode {
// cast back into the right lifetime
let safe_props: &'_ P = unsafe { &*(raw_props as *const P) };
// let ctx: Context<P2> = todo!();
let ctx: Context<P> = Context {
props: safe_props,
scope: scp,
};
let g = component(ctx);
let g2 = unsafe { std::mem::transmute(g) };
g2
});
let r: Captured<'static> = unsafe { std::mem::transmute(g) };
r
}
pub struct VFragment<'src> {
pub key: NodeKey<'src>,
pub children: &'src [VNode<'src>],
}
impl<'a> VFragment<'a> {
pub fn new(key: Option<&'a str>, children: &'a [VNode<'a>]) -> Self {
let key = match key {
Some(key) => NodeKey::new(key),
None => NodeKey(None),
};
Self { key, children }
}
}
+2
View File
@@ -146,6 +146,7 @@ pub struct EditMachine<'lock> {
pub traversal: Traversal,
next_temporary: u32,
forcing_new_listeners: bool,
pub cur_height: u32,
// // if the current node is a "known" node
// // any actions that modify this node should update the mapping
@@ -158,6 +159,7 @@ impl<'lock> EditMachine<'lock> {
Self {
// current_known: None,
traversal: Traversal::new(),
cur_height: 0,
next_temporary: 0,
forcing_new_listeners: false,
emitter: EditList::<'lock>::default(),
+65 -211
View File
@@ -32,6 +32,7 @@ use std::{
pin::Pin,
rc::{Rc, Weak},
};
pub type ScopeIdx = generational_arena::Index;
/// An integrated virtual node system that progresses events and diffs UI trees.
/// Differences are converted into patches which a renderer can use to draw the UI.
@@ -52,8 +53,8 @@ pub struct VirtualDom {
/// a strong allocation to the "caller" for the original component and its props
#[doc(hidden)]
_root_caller: Rc<OpaqueComponent<'static>>,
_root_caller: Rc<OpaqueComponent>,
// _root_caller: Rc<OpaqueComponent<'static>>,
/// Type of the original ctx. This is stored as TypeId so VirtualDom does not need to be generic.
///
/// Whenver props need to be updated, an Error will be thrown if the new props do not
@@ -137,7 +138,8 @@ impl VirtualDom {
// Normally, a component would be passed as a child in the RSX macro which automatically produces OpaqueComponents
// Here, we need to make it manually, using an RC to force the Weak reference to stick around for the main scope.
let _root_caller: Rc<OpaqueComponent<'static>> = Rc::new(move |scope| {
let _root_caller: Rc<OpaqueComponent> = Rc::new(move |scope| {
// let _root_caller: Rc<OpaqueComponent<'static>> = Rc::new(move |scope| {
// the lifetime of this closure is just as long as the lifetime on the scope reference
// this closure moves root props (which is static) into this closure
let props = unsafe { &*(&root_props as *const _) };
@@ -154,10 +156,11 @@ impl VirtualDom {
// Make the first scope
// We don't run the component though, so renderers will need to call "rebuild" when they initialize their DOM
let link = components.clone();
let event_channel = Rc::new(move || {});
let base_scope = components
.with(|arena| {
arena.insert_with(move |myidx| {
let event_channel = _event_queue.new_channel(0, myidx);
Scope::new(caller_ref, myidx, None, 0, event_channel, link, &[])
})
})
@@ -175,7 +178,11 @@ impl VirtualDom {
/// Performs a *full* rebuild of the virtual dom, returning every edit required to generate the actual dom rom scratch
/// Currently this doesn't do what we want it to do
pub fn rebuild<'s>(&'s mut self) -> Result<EditList<'s>> {
let mut diff_machine = DiffMachine::new();
let mut diff_machine = DiffMachine::new(
self.components.clone(),
self.base_scope,
self.event_queue.clone(),
);
// Schedule an update and then immediately call it on the root component
// This is akin to a hook being called from a listener and requring a re-render
@@ -190,10 +197,6 @@ impl VirtualDom {
Ok(diff_machine.consume())
}
pub fn base_scope(&self) -> &Scope {
todo!()
}
}
// ======================================
@@ -248,7 +251,9 @@ impl VirtualDom {
self.components.try_get_mut(id)?.call_listener(event)?;
let mut diff_machine = DiffMachine::new();
let mut diff_machine =
DiffMachine::new(self.components.clone(), id, self.event_queue.clone());
self.progress_completely(&mut diff_machine)?;
Ok(diff_machine.consume())
@@ -263,212 +268,48 @@ impl VirtualDom {
diff_machine: &'_ mut DiffMachine<'s>,
) -> Result<()> {
// Add this component to the list of components that need to be difed
#[allow(unused_assignments)]
let mut cur_height: u32 = 0;
// #[allow(unused_assignments)]
// let mut cur_height: u32 = 0;
// Now, there are events in the queue
let mut seen_nodes = HashSet::<ScopeIdx>::new();
let mut updates = self.event_queue.0.as_ref().borrow_mut();
// Order the nodes by their height, we want the biggest nodes on the top
// This prevents us from running the same component multiple times
updates.sort_unstable();
log::debug!("There are: {:#?} updates to be processed", updates.len());
// Iterate through the triggered nodes (sorted by height) and begin to diff them
for update in updates.drain(..) {
log::debug!("Running updates for: {:#?}", update);
// Make sure this isn't a node we've already seen, we don't want to double-render anything
// If we double-renderer something, this would cause memory safety issues
if seen_nodes.contains(&update.idx) {
if diff_machine.seen_nodes.contains(&update.idx) {
continue;
}
// Now, all the "seen nodes" are nodes that got notified by running this listener
seen_nodes.insert(update.idx.clone());
diff_machine.seen_nodes.insert(update.idx.clone());
// Start a new mutable borrow to components
// We are guaranteeed that this scope is unique because we are tracking which nodes have modified
let cur_component = self.components.try_get_mut(update.idx).unwrap();
// let inner: &'s mut _ = unsafe { &mut *self.components.0.borrow().arena.get() };
// let cur_component = inner.get_mut(update.idx).unwrap();
cur_component.run_scope()?;
diff_machine.diff_node(cur_component.old_frame(), cur_component.next_frame());
cur_height = cur_component.height;
// cur_height = cur_component.height;
log::debug!(
"Processing update: {:#?} with height {}",
&update.idx,
cur_height
);
// Now, the entire subtree has been invalidated. We need to descend depth-first and process
// any updates that the diff machine has proprogated into the component lifecycle queue
while let Some(event) = diff_machine.lifecycle_events.pop_front() {
match event {
// A new component has been computed from the diffing algorithm
// create a new component in the arena, run it, move the diffing machine to this new spot, and then diff it
// this will flood the lifecycle queue with new updates to build up the subtree
LifeCycleEvent::Mount {
caller,
root_id: id,
stable_scope_addr,
} => {
log::debug!("Mounting a new component");
// We're modifying the component arena while holding onto references into the assoiated bump arenas of its children
// those references are stable, even if the component arena moves around in memory, thanks to the bump arenas.
// However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime.
// Insert a new scope into our component list
let idx = self.components.with(|components| {
components.insert_with(|new_idx| {
let height = cur_height + 1;
Scope::new(
caller,
new_idx,
Some(cur_component.arena_idx),
height,
self.event_queue.new_channel(height, new_idx),
self.components.clone(),
&[],
)
})
})?;
{
let cur_component = self.components.try_get_mut(update.idx).unwrap();
let mut ch = cur_component.descendents.borrow_mut();
ch.insert(idx);
std::mem::drop(ch);
}
// Grab out that component
let new_component = self.components.try_get_mut(idx).unwrap();
// Actually initialize the caller's slot with the right address
*stable_scope_addr.upgrade().unwrap().as_ref().borrow_mut() = Some(idx);
// Run the scope for one iteration to initialize it
new_component.run_scope()?;
// Navigate the diff machine to the right point in the output dom
diff_machine.change_list.load_known_root(id);
// And then run the diff algorithm
diff_machine
.diff_node(new_component.old_frame(), new_component.next_frame());
// Finally, insert this node as a seen node.
seen_nodes.insert(idx);
}
// A component has remained in the same location but its properties have changed
// We need to process this component and then dump the output lifecycle events into the queue
LifeCycleEvent::PropsChanged {
caller,
root_id,
stable_scope_addr,
} => {
log::debug!("Updating a component after its props have changed");
// Get the stable index to the target component
// This *should* exist due to guarantees in the diff algorithm
let idx = stable_scope_addr
.upgrade()
.unwrap()
.as_ref()
.borrow()
.unwrap();
// Grab out that component
let component = self.components.try_get_mut(idx).unwrap();
// We have to move the caller over or running the scope will fail
component.update_caller(caller);
// Run the scope
component.run_scope()?;
// Navigate the diff machine to the right point in the output dom
diff_machine.change_list.load_known_root(root_id);
// And then run the diff algorithm
diff_machine.diff_node(component.old_frame(), component.next_frame());
// Finally, insert this node as a seen node.
seen_nodes.insert(idx);
}
// A component's parent has updated, but its properties did not change.
// This means the caller ptr is invalidated and needs to be updated, but the component itself does not need to be re-ran
LifeCycleEvent::SameProps {
caller,
stable_scope_addr,
..
} => {
// In this case, the parent made a new VNode that resulted in the same props for us
// However, since our caller is located in a Bump frame, we need to update the caller pointer (which is now invalid)
log::debug!("Received the same props");
// Get the stable index to the target component
// This *should* exist due to guarantees in the diff algorithm
let idx = stable_scope_addr
.upgrade()
.unwrap()
.as_ref()
.borrow()
.unwrap();
// Grab out that component
let component = self.components.try_get_mut(idx).unwrap();
// We have to move the caller over or running the scope will fail
component.update_caller(caller);
// This time, we will not add it to our seen nodes since we did not actually run it
}
LifeCycleEvent::Remove {
root_id,
stable_scope_addr,
} => {
let id = stable_scope_addr
.upgrade()
.unwrap()
.as_ref()
.borrow()
.unwrap();
log::warn!("Removing node {:#?}", id);
// This would normally be recursive but makes sense to do linear to
let mut children_to_remove = VecDeque::new();
children_to_remove.push_back(id);
// Accumulate all the child components that need to be removed
while let Some(child_id) = children_to_remove.pop_back() {
let comp = self.components.try_get(child_id).unwrap();
let children = comp.descendents.borrow();
for child in children.iter() {
children_to_remove.push_front(*child);
}
log::debug!("Removing component: {:#?}", child_id);
self.components
.with(|components| components.remove(child_id).unwrap())
.unwrap();
}
}
LifeCycleEvent::Replace {
caller,
root_id: id,
..
} => {
unimplemented!("This feature (Replace) is unimplemented")
}
}
}
// log::debug!(
// "Processing update: {:#?} with height {}",
// &update.idx,
// cur_height
// );
}
Ok(())
@@ -492,7 +333,7 @@ pub struct Scope {
// IDs of children that this scope has created
// This enables us to drop the children and their children when this scope is destroyed
descendents: RefCell<HashSet<ScopeIdx>>,
pub(crate) descendents: RefCell<HashSet<ScopeIdx>>,
child_nodes: &'static [VNode<'static>],
@@ -510,8 +351,8 @@ pub struct Scope {
pub event_channel: Rc<dyn Fn() + 'static>,
// pub event_queue: EventQueue,
pub caller: Weak<OpaqueComponent<'static>>,
pub caller: Weak<OpaqueComponent>,
// pub caller: Weak<OpaqueComponent<'static>>,
pub hookidx: RefCell<usize>,
// ==========================
@@ -545,8 +386,9 @@ impl Scope {
//
// Scopes cannot be made anywhere else except for this file
// Therefore, their lifetimes are connected exclusively to the virtual dom
fn new<'creator_node>(
caller: Weak<OpaqueComponent<'creator_node>>,
pub fn new<'creator_node>(
caller: Weak<OpaqueComponent>,
// caller: Weak<OpaqueComponent<'creator_node>>,
arena_idx: ScopeIdx,
parent: Option<ScopeIdx>,
height: u32,
@@ -572,13 +414,17 @@ impl Scope {
// Not the best solution, so TODO on removing this in favor of a dedicated resource abstraction.
let caller = unsafe {
std::mem::transmute::<
Weak<OpaqueComponent<'creator_node>>,
Weak<OpaqueComponent<'static>>,
Weak<OpaqueComponent>,
Weak<OpaqueComponent>,
// Weak<OpaqueComponent<'creator_node>>,
// Weak<OpaqueComponent<'static>>,
>(caller)
};
let child_nodes = unsafe { std::mem::transmute(child_nodes) };
Self {
child_nodes: &[],
child_nodes: child_nodes,
caller,
parent,
arena_idx,
@@ -594,11 +440,14 @@ impl Scope {
}
}
pub fn update_caller<'creator_node>(&mut self, caller: Weak<OpaqueComponent<'creator_node>>) {
pub fn update_caller<'creator_node>(&mut self, caller: Weak<OpaqueComponent>) {
// pub fn update_caller<'creator_node>(&mut self, caller: Weak<OpaqueComponent<'creator_node>>) {
let broken_caller = unsafe {
std::mem::transmute::<
Weak<OpaqueComponent<'creator_node>>,
Weak<OpaqueComponent<'static>>,
Weak<OpaqueComponent>,
Weak<OpaqueComponent>,
// Weak<OpaqueComponent<'creator_node>>,
// Weak<OpaqueComponent<'static>>,
>(caller)
};
@@ -630,8 +479,10 @@ impl Scope {
.ok_or(Error::FatalInternal("Failed to get caller"))?;
// Cast the caller ptr from static to one with our own reference
let c2: &OpaqueComponent<'static> = caller.as_ref();
let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
let c2: &OpaqueComponent = caller.as_ref();
let c3: &OpaqueComponent = unsafe { std::mem::transmute(c2) };
// let c2: &OpaqueComponent<'static> = caller.as_ref();
// let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
let unsafe_head = unsafe { self.own_vnodes(c3) };
@@ -641,7 +492,7 @@ impl Scope {
}
// this is its own function so we can preciesly control how lifetimes flow
unsafe fn own_vnodes<'a>(&'a self, f: &OpaqueComponent<'a>) -> VNode<'static> {
unsafe fn own_vnodes<'a>(&'a self, f: &OpaqueComponent) -> VNode<'static> {
let new_head: VNode<'a> = f(self);
let out: VNode<'static> = std::mem::transmute(new_head);
out
@@ -959,22 +810,25 @@ Any function prefixed with "use" should not be called conditionally.
// We actually allocate the properties for components in their parent's properties
// We then expose a handle to use those props for render in the form of "OpaqueComponent"
pub(crate) type OpaqueComponent<'e> = dyn for<'b> Fn(&'b Scope) -> VNode<'b> + 'e;
pub type OpaqueComponent = dyn for<'b> Fn(&'b Scope) -> VNode<'b>;
#[derive(PartialEq, Debug, Clone, Default)]
pub(crate) struct EventQueue(pub Rc<RefCell<Vec<HeightMarker>>>);
pub struct EventQueue(pub Rc<RefCell<Vec<HeightMarker>>>);
impl EventQueue {
pub fn new_channel(&self, height: u32, idx: ScopeIdx) -> Rc<dyn Fn()> {
let inner = self.clone();
let marker = HeightMarker { height, idx };
Rc::new(move || inner.0.as_ref().borrow_mut().push(marker))
Rc::new(move || {
log::debug!("channel updated {:#?}", marker);
inner.0.as_ref().borrow_mut().push(marker)
})
}
}
/// A helper type that lets scopes be ordered by their height
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct HeightMarker {
pub struct HeightMarker {
pub idx: ScopeIdx,
pub height: u32,
}
@@ -1050,20 +904,20 @@ impl ActiveFrame {
)
}
fn from_frames(a: BumpFrame, b: BumpFrame) -> Self {
pub fn from_frames(a: BumpFrame, b: BumpFrame) -> Self {
Self {
generation: 0.into(),
frames: [a, b],
}
}
fn cur_frame(&self) -> &BumpFrame {
pub fn cur_frame(&self) -> &BumpFrame {
match *self.generation.borrow() & 1 == 0 {
true => &self.frames[0],
false => &self.frames[1],
}
}
fn cur_frame_mut(&mut self) -> &mut BumpFrame {
pub fn cur_frame_mut(&mut self) -> &mut BumpFrame {
match *self.generation.borrow() & 1 == 0 {
true => &mut self.frames[0],
false => &mut self.frames[1],
@@ -1098,7 +952,7 @@ impl ActiveFrame {
}
}
fn next(&mut self) -> &mut BumpFrame {
pub fn next(&mut self) -> &mut BumpFrame {
*self.generation.borrow_mut() += 1;
if *self.generation.borrow() % 2 == 0 {
+1 -1
View File
@@ -84,7 +84,7 @@ fn use_map() {}
// Elements are received as Rc<T> in case the underlying collection is shuffled around
// Setters/getters can be generated
fn use_collection<'a, T: Collection>(
ctx: &Context<'a>,
ctx: &impl Scoped<'a>,
f: impl Fn() -> T,
) -> CollectionHandle<'a, T> {
ctx.use_hook(
+1 -1
View File
@@ -20,7 +20,7 @@ fn update_title(api: &RecoilApi) {
}
static App: FC<()> = |ctx| {
let title = use_read(ctx, &TITLE);
let title = use_read(&ctx, &TITLE);
let next_light = use_recoil_api(ctx, |api| move |_| update_title(&api));
rsx! { in ctx,
+15 -18
View File
@@ -32,7 +32,7 @@ mod traits {
// Atoms, selectors, and their family variants are readable
pub trait Readable<T: AtomValue>: Sized + Copy {
fn use_read<'a, P: 'static>(self, ctx: Context<'a, P>) -> &'a T {
hooks::use_read(ctx, self)
hooks::use_read(&ctx, self)
}
// This returns a future of the value
@@ -95,9 +95,9 @@ mod atoms {
const EXAMPLE_ATOM: Atom<i32> = |_| 10;
// ensure that atoms are both read and write
let _ = use_read(ctx, &EXAMPLE_ATOM);
let _ = use_read_write(ctx, &EXAMPLE_ATOM);
let _ = use_write(ctx, &EXAMPLE_ATOM);
let _ = use_read(&ctx, &EXAMPLE_ATOM);
let _ = use_read_write(&ctx, &EXAMPLE_ATOM);
let _ = use_write(&ctx, &EXAMPLE_ATOM);
}
}
}
@@ -161,7 +161,7 @@ mod atomfamily {
fn test(ctx: Context<()>) {
let title = Titles.select(&10).use_read(ctx);
let t2 = use_read(ctx, &Titles.select(&10));
let t2 = use_read(&ctx, &Titles.select(&10));
}
}
}
@@ -368,7 +368,7 @@ mod root {
mod hooks {
use super::*;
use dioxus_core::{hooks::use_ref, prelude::Context};
use dioxus_core::{hooks::use_ref, prelude::Context, virtual_dom::Scoped};
pub fn use_init_recoil_root<P>(ctx: Context<P>, cfg: impl Fn(())) {
ctx.use_create_context(move || RefCell::new(RecoilRoot::new()))
@@ -381,12 +381,12 @@ mod hooks {
///
/// You can use this method to create controllers that perform much more complex actions than set/get
/// However, be aware that "getting" values through this hook will not subscribe the component to any updates.
pub fn use_recoil_api<'a, P>(ctx: Context<'a, P>) -> &Rc<RecoilContext> {
pub fn use_recoil_api<'a>(ctx: &impl Scoped<'a>) -> &'a Rc<RecoilContext> {
ctx.use_context::<RecoilContext>()
}
pub fn use_write<'a, T: AtomValue, P>(
ctx: Context<'a, P>,
pub fn use_write<'a, T: AtomValue>(
ctx: &impl Scoped<'a>,
// todo: this shouldn't need to be static
writable: impl Writable<T>,
) -> &'a Rc<dyn Fn(T)> {
@@ -412,10 +412,10 @@ mod hooks {
/// Read the atom and get the Rc directly to the Atom's slot
/// This is useful if you need the memoized Atom value. However, Rc<T> is not as easy to
/// work with as
pub fn use_read_raw<'a, T: AtomValue, P: 'static>(
ctx: Context<'a, P>,
pub fn use_read_raw<'a, T: AtomValue>(
ctx: &impl Scoped<'a>,
readable: impl Readable<T>,
) -> &Rc<T> {
) -> &'a Rc<T> {
struct ReadHook<T> {
value: Rc<T>,
consumer_id: u32,
@@ -449,10 +449,7 @@ mod hooks {
}
///
pub fn use_read<'a, T: AtomValue, P: 'static>(
ctx: Context<'a, P>,
readable: impl Readable<T>,
) -> &'a T {
pub fn use_read<'a, T: AtomValue>(ctx: &impl Scoped<'a>, readable: impl Readable<T>) -> &'a T {
use_read_raw(ctx, readable).as_ref()
}
@@ -471,8 +468,8 @@ mod hooks {
/// // equivalent to:
/// let (title, set_title) = (use_read(ctx, &Title), use_write(ctx, &Title));
/// ```
pub fn use_read_write<'a, T: AtomValue + 'static, P: 'static>(
ctx: Context<'a, P>,
pub fn use_read_write<'a, T: AtomValue + 'static>(
ctx: &impl Scoped<'a>,
writable: impl Writable<T>,
) -> (&'a T, &'a Rc<dyn Fn(T)>) {
(use_read(ctx, writable), use_write(ctx, writable))
+36
View File
@@ -0,0 +1,36 @@
//! Basic example that renders a simple VNode to the browser.
use dioxus_core::prelude::*;
use dioxus_web::*;
fn main() {
// Setup logging
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
// Run the app
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
}
static App: FC<()> = |ctx| {
ctx.render(rsx! {
Calcier {
h2 {"abc 1"}
h2 {"abc 2"}
h2 {"abc 3"}
h2 {"abc 4"}
h2 {"abc 5"}
}
})
};
static Calcier: FC<()> = |ctx| {
ctx.render(rsx! {
div {
h1 {
"abc 0"
}
{ctx.children()}
}
})
};
+1 -1
View File
@@ -52,7 +52,7 @@ struct ButtonProps {
id: u8,
}
fn CustomButton(ctx: Context, props: &ButtonProps) -> VNode {
fn CustomButton(ctx: Context<ButtonProps>) -> VNode {
let names = ctx.use_context::<CustomContext>();
let name = names.0[ctx.id as usize];
+25
View File
@@ -0,0 +1,25 @@
//! Basic example that renders a simple VNode to the browser.
use dioxus_core::prelude::*;
use dioxus_web::*;
fn main() {
// Setup logging
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
// Run the app
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
}
static App: FC<()> = |ctx| {
ctx.render(rsx! {
h2 { "abc 1" }
div {
"hello world!"
}
Fragment {
h2 { "abc 2"}
}
})
};
+11
View File
@@ -0,0 +1,11 @@
use dioxus_web::prelude::*;
fn main() {
wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(App))
}
fn App(ctx: Context<()>) -> VNode {
ctx.render(rsx! {
div { "Hello, world!" }
})
}
+21
View File
@@ -0,0 +1,21 @@
use dioxus_core::prelude::*;
use dioxus_web::WebsysRenderer;
fn main() {
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
log::info!("hello world");
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(Example));
}
static Example: FC<()> = |ctx| {
ctx.render(rsx! {
div {
span {
class: "px-2 py-1 flex w-36 mt-4 items-center text-xs rounded-md font-semibold text-yellow-500 bg-yellow-100"
"DUE DATE : 18 JUN"
}
}
})
};
+2 -2
View File
@@ -53,7 +53,7 @@ struct ButtonProps<'src, F: Fn(MouseEvent)> {
handler: F
}
fn CustomButton<'b, 'a, F: Fn(MouseEvent)>(ctx: Context<'a>, props: &'b ButtonProps<'b, F>) -> VNode {
fn CustomButton<'a, F: Fn(MouseEvent)>(ctx: Context<'a, ButtonProps<'a, F>>) -> VNode {
ctx.render(rsx!{
button {
class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
@@ -74,7 +74,7 @@ impl<F: Fn(MouseEvent)> PartialEq for ButtonProps<'_, F> {
struct PlaceholderProps {
val: &'static str
}
fn Placeholder(ctx: Context, props: &PlaceholderProps) -> VNode {
fn Placeholder(ctx: Context<PlaceholderProps>) -> VNode {
ctx.render(rsx!{
div {
"child: {ctx.val}"
+5 -6
View File
@@ -149,11 +149,11 @@ pub fn FilterToggles(ctx: Context<()>) -> VNode {
.iter()
.map(|(name, path, filter)| {
rsx!(
li {
class: "{name}"
a { "{name}",
li { class: "{name}"
a {
href: "{path}",
onclick: move |_| reducer.set_filter(&filter),
"{name}",
}
}
)
@@ -168,7 +168,7 @@ pub fn FilterToggles(ctx: Context<()>) -> VNode {
footer {
span {
strong {"{items_left}"}
span {"{item_text} left"}
span { "{item_text} left" }
}
ul {
class: "filters"
@@ -180,8 +180,7 @@ pub fn FilterToggles(ctx: Context<()>) -> VNode {
pub fn Footer(ctx: Context<()>) -> VNode {
rsx! { in ctx,
footer {
class: "info"
footer { class: "info"
p {"Double-click to edit a todo"}
p {
"Created by "