Merge branch 'main' into use_webtransport

# Conflicts:
#	.cargo/config.toml
#	.idea/leptos-use.iml
#	Cargo.toml
#	src/lib.rs
This commit is contained in:
Maccesch 2023-12-11 22:10:36 +00:00
commit 52a72a7f87
144 changed files with 5117 additions and 1060 deletions

View file

@ -1,3 +0,0 @@
[build]
rustflags = ["--cfg=web_sys_unstable_apis"]
rustdocflags = ["--cfg=web_sys_unstable_apis"]

View file

@ -3,14 +3,14 @@
{
"type": "cargo",
"name": "Tests",
"cargoArgs": ["test", "--features", "math,storage,docs"],
"cargoArgs": ["test", "--features", "math,prost,serde,docs"],
},
{
"type": "cargo",
"name": "Clippy",
"cargoArgs": ["+nightly", "clippy", "--features", "math,storage,docs", "--tests", "--", "-D", "warnings"],
"cargoArgs": ["+nightly", "clippy", "--features", "math,prost,serde,docs", "--tests", "--", "-D", "warnings"],
"workingDir": "./",
},
]
}
}

View file

@ -30,7 +30,7 @@ jobs:
- name: Check formatting
run: cargo fmt --check
- name: Clippy
run: cargo clippy --features storage,docs,math --tests -- -D warnings
run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
- name: Run tests
run: cargo test --all-features
@ -110,4 +110,4 @@ jobs:
# - name: Publish to Coveralls
# uses: coverallsapp/github-action@master
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# github-token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -23,6 +23,6 @@ jobs:
- name: Check formatting
run: cargo fmt --check
- name: Clippy
run: cargo clippy --features storage,docs,math --tests -- -D warnings
run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
- name: Run tests
run: cargo test --all-features

9
.idea/leptos-use.iml generated
View file

@ -12,6 +12,7 @@
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_throttle_fn/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_debounce_fn/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_display_media/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_scroll/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_resize_observer/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_mouse/src" isTestSource="false" />
@ -56,6 +57,10 @@
<sourceFolder url="file://$MODULE_DIR$/examples/use_geolocation/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_idle/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_timestamp/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_sorted/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_service_worker/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_infinite_scroll/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_web_notification/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_webtransport_with_server/client/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_webtransport_with_server/server/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_event_listener/target" />
@ -65,7 +70,9 @@
<excludeFolder url="file://$MODULE_DIR$/examples/use_throttle_fn/dist" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_throttle_fn/target" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_debounce_fn/dist" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_display_media/dist" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_debounce_fn/target" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_display_media/target" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_scroll/target" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_resize_observer/target" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_mouse/target" />
@ -126,4 +133,4 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Python 3.9 interpreter library" level="application" />
</component>
</module>
</module>

View file

@ -3,6 +3,80 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.9.0] - 2023-12-06
### New Functions 🚀
- `use_display_media` (thanks to @seanaye)
### Breaking Changes 🛠
- (@feral-dot-io) The use `use_<type>_storage` functions have been rewritten to use `Codec`s instead of always
requiring `serde`.
- This also removes the feature `storage`
- By default the `StringCodec` is used which relies on types implementing `FromString + ToString`
- If you want to use `JsonCodec` you have to enable the feature `serde`
- If you want to use `ProstCodec` (new!) you have to enable the feature `prost`.
- (@feral-dot-io) The Rust flag `--cfg=web_sys_unstable_apis` is not needed anymore since relevant `web_sys` APIs are
now stable.
This affects in particular
- `use_element_size`
- `use_resize_observer`
### Fixes 🍕
- `use_raf_fn` and `use_timestamp` no longer spam warnings because of `get`ting signals outside of reactive contexts.
- `use_infinite_scroll` no longer calls the callback twice for the same event
- `use_scroll` now uses `try_get_untracked` in the debounced callback to avoid panics if the context has been destroyed
while the callback was waiting to be called.
- `use_idle` works properly now (no more idles too early).
- `use_web_notification` doesn't panic on the server anymore.
## [0.8.2] - 2023-11-09
### Fixes 🍕
- Fixed SSR for
- use_timestamp
- use_raf_fn
- use_idle
## [0.8.1] - 2023-10-28
### Fixes 🍕
- Using strings for `ElementMaybeSignal` and `ElementsMaybeSignal` is now SSR safe.
- This fixes specifically `use_color_mode` to work on the server.
## [0.8.0] - 2023-10-24
### New Functions 🚀
- `use_web_notification` (thanks to @centershocks44)
- `use_infinite_scroll`
- `use_service_worker` (thanks to @lpotthast)
### Breaking Changes 🛠
- `use_scroll` returns `impl Fn(T) + Clone` instead of `Box<dyn Fn(T)>`.
### Other Changes 🔥
- `UseScrollReturn` is now documented
## [0.7.2] - 2023-10-21
### Fixes 🍕
- Some functions still used `window()` which could lead to panics in SSR. This is now fixed.
Specifically for `use_draggable`.
## [0.7.1] - 2023-10-02
### New Function 🚀
- `use_sorted`
## [0.7.0] - 2023-09-30
### New Functions 🚀

View file

@ -1,6 +1,6 @@
[package]
name = "leptos-use"
version = "0.7.0"
version = "0.9.0"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
categories = ["gui", "web-programming"]
@ -13,23 +13,30 @@ repository = "https://github.com/Synphonyte/leptos-use"
homepage = "https://leptos-use.rs"
[dependencies]
leptos = "0.5"
wasm-bindgen = "0.2"
js-sys = "0.3"
base64 = { version = "0.21", optional = true }
cfg-if = "1"
default-struct-builder = "0.5"
futures-util = "0.3"
gloo-timers = { version = "0.3.0", features = ["futures"] }
gloo-utils = { version = "0.2.0" }
js-sys = "0.3"
lazy_static = "1"
leptos = "0.5"
num = { version = "0.4", optional = true }
paste = "1"
prost = { version = "0.12", optional = true }
serde = { version = "1", optional = true }
serde_json = { version = "1", optional = true }
paste = "1"
lazy_static = "1"
cfg-if = "1"
thiserror = "1.0"
wasm-bindgen = "0.2.88"
wasm-bindgen-futures = "0.4"
wasm-bindgen-futures = "0.4"
async-trait = "0.1"
rmp-serde = { version = "1.1", optional = true }
thiserror = "1"
[dependencies.web-sys]
version = "0.3"
version = "0.3.65"
features = [
"AddEventListenerOptions",
"BinaryType",
@ -38,6 +45,7 @@ features = [
"CssStyleDeclaration",
"CustomEvent",
"CustomEventInit",
"DisplayMediaStreamConstraints",
"DomRect",
"DomRectReadOnly",
"DataTransfer",
@ -55,13 +63,20 @@ features = [
"IntersectionObserver",
"IntersectionObserverInit",
"IntersectionObserverEntry",
"MediaDevices",
"MediaQueryList",
"MediaStream",
"MediaStreamTrack",
"MouseEvent",
"MutationObserver",
"MutationObserverInit",
"MutationRecord",
"Navigator",
"NodeList",
"Notification",
"NotificationDirection",
"NotificationOptions",
"NotificationPermission",
"PointerEvent",
"Position",
"PositionError",
@ -77,7 +92,12 @@ features = [
"ResizeObserverSize",
"ScrollBehavior",
"ScrollToOptions",
"ServiceWorker",
"ServiceWorkerContainer",
"ServiceWorkerRegistration",
"ServiceWorkerState",
"Storage",
"StorageEvent",
"Touch",
"TouchEvent",
"TouchList",
@ -97,12 +117,10 @@ features = [
[features]
docs = []
math = ["num"]
storage = ["dep:serde", "dep:serde_json", "web-sys/StorageEvent"]
prost = ["base64", "dep:prost"]
serde = ["dep:serde", "serde_json"]
ssr = []
msgpack = ["dep:rmp-serde", "dep:serde"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg=web_sys_unstable_apis"]
rustc-args = ["--cfg=web_sys_unstable_apis"]

View file

@ -13,7 +13,7 @@
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-58%20functions-%23EF3939" alt="58 Functions" /></a>
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-63%20functions-%23EF3939" alt="63 Functions" /></a>
</p>
<br/>
@ -87,8 +87,8 @@ This will create the function file in the src directory, scaffold an example dir
## Leptos compatibility
| Crate version | Compatible Leptos version |
|---------------|---------------------------|
| <= 0.3 | 0.3 |
| 0.4, 0.5, 0.6 | 0.4 |
| 0.7 | 0.5 |
| Crate version | Compatible Leptos version |
|----------------|---------------------------|
| <= 0.3 | 0.3 |
| 0.4, 0.5, 0.6 | 0.4 |
| 0.7, 0.8, 0.9 | 0.5 |

View file

@ -2,6 +2,7 @@ import os
import shutil
import subprocess
import sys
import re
def main():
@ -43,7 +44,7 @@ def build_and_copy_demo(category, md_name):
html = f.read()
head_split = html.split("<head>")
target_head = head_split[1].split("</head>")[0]
body_split = html.split("<body>")[1].split("</body>")
body_split = re.split("<body[^>]*>", html)[1].split("</body>")
target_body = body_split[0]
with open(book_html_path, "w") as f:

View file

@ -6,7 +6,7 @@
[Changelog](changelog.md)
[Functions](functions.md)
# @Storage
# Storage
- [use_local_storage](storage/use_local_storage.md)
- [use_session_storage](storage/use_session_storage.md)
@ -33,11 +33,14 @@
- [use_breakpoints](browser/use_breakpoints.md)
- [use_color_mode](browser/use_color_mode.md)
- [use_css_var](browser/use_css_var.md)
- [use_display_media](browser/use_display_media.md)
- [use_event_listener](browser/use_event_listener.md)
- [use_favicon](browser/use_favicon.md)
- [use_media_query](browser/use_media_query.md)
- [use_preferred_contrast](browser/use_preferred_contrast.md)
- [use_preferred_dark](browser/use_preferred_dark.md)
- [use_service_worker](browser/use_service_worker.md)
- [use_web_notification](browser/use_web_notification.md)
# Sensors
@ -45,6 +48,7 @@
- [use_element_hover](sensors/use_element_hover.md)
- [use_geolocation](sensors/use_geolocation.md)
- [use_idle](sensors/use_idle.md)
- [use_infinite_scroll](sensors/use_infinite_scroll.md)
- [use_mouse](sensors/use_mouse.md)
- [use_scroll](sensors/use_scroll.md)
@ -73,8 +77,11 @@
- [signal_debounced](reactivity/signal_debounced.md)
- [signal_throttled](reactivity/signal_throttled.md)
# Utilities
# Iterable
- [use_sorted](iterable/use_sorted.md)
# Utilities
- [is_err](utilities/is_err.md)
- [is_none](utilities/is_none.md)
- [is_ok](utilities/is_ok.md)

View file

@ -0,0 +1,3 @@
# use_display_media
<!-- cmdrun python3 ../extract_doc_comment.py use_display_media -->

View file

@ -0,0 +1,3 @@
# use_service_worker
<!-- cmdrun python3 ../extract_doc_comment.py use_service_worker -->

View file

@ -0,0 +1,3 @@
# use_web_notification
<!-- cmdrun python3 ../extract_doc_comment.py use_web_notification -->

View file

@ -99,4 +99,8 @@ h1 {
h2, h3, h4 {
font-weight: 600;
}
#searchbar {
font-size: 1.6rem;
}

View file

@ -12,6 +12,6 @@
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
<a href="./get_started.html"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
<a href="./functions.html"><img src="https://img.shields.io/badge/-58%20functions-%23EF3939" alt="58 Functions" /></a>
<a href="./functions.html"><img src="https://img.shields.io/badge/-63%20functions-%23EF3939" alt="63 Functions" /></a>
</p>
</div>

View file

@ -0,0 +1,3 @@
# use_sorted
<!-- cmdrun python3 ../extract_doc_comment.py use_sorted -->

View file

@ -0,0 +1,3 @@
# use_infinite_scroll
<!-- cmdrun python3 ../extract_doc_comment.py use_infinite_scroll -->

View file

@ -1,3 +1,3 @@
# use_local_storage
<!-- cmdrun python3 ../extract_doc_comment.py storage/use_local_storage storage -->
<!-- cmdrun python3 ../extract_doc_comment.py storage/use_local_storage -->

View file

@ -1,3 +1,3 @@
# use_session_storage
<!-- cmdrun python3 ../extract_doc_comment.py storage/use_session_storage storage -->
<!-- cmdrun python3 ../extract_doc_comment.py storage/use_session_storage -->

View file

@ -1,3 +1,3 @@
# use_storage
<!-- cmdrun python3 ../extract_doc_comment.py storage/use_storage storage -->
<!-- cmdrun python3 ../extract_doc_comment.py storage/use_storage -->

View file

@ -1,2 +0,0 @@
[build]
rustflags = ["--cfg=web_sys_unstable_apis", "--cfg=has_std"]

View file

@ -13,6 +13,7 @@ members = [
"use_css_var",
"use_cycle_list",
"use_debounce_fn",
"use_display_media",
"use_document_visibility",
"use_draggable",
"use_drop_zone",
@ -24,6 +25,7 @@ members = [
"use_floor",
"use_geolocation",
"use_idle",
"use_infinite_scroll",
"use_intersection_observer",
"use_interval",
"use_interval_fn",
@ -35,9 +37,12 @@ members = [
"use_resize_observer",
"use_round",
"use_scroll",
"use_service_worker",
"use_sorted",
"use_storage",
"use_throttle_fn",
"use_timestamp",
"use_web_notification",
"use_websocket",
"use_webtransport",
"use_window_focus",

View file

@ -15,17 +15,9 @@ fn Demo() -> impl IntoView {
on:input=move |event| set_input(event_target_value(&event))
placeholder="Try to type quickly, then stop..."
/>
<Note>
Delay is set to 1000ms for this demo.
</Note>
<p>
Input signal:
{input}
</p>
<p>
Debounced signal:
{debounced}
</p>
<Note>Delay is set to 1000ms for this demo.</Note>
<p>Input signal: {input}</p>
<p>Debounced signal: {debounced}</p>
</div>
}
}

View file

@ -15,17 +15,9 @@ fn Demo() -> impl IntoView {
on:input=move |event| set_input(event_target_value(&event))
placeholder="Try to type quickly..."
/>
<Note>
Delay is set to 1000ms for this demo.
</Note>
<p>
Input signal:
{input}
</p>
<p>
Throttled signal:
{throttled}
</p>
<Note>Delay is set to 1000ms for this demo.</Note>
<p>Input signal: {input}</p>
<p>Throttled signal: {throttled}</p>
</div>
}
}

View file

@ -1,5 +1,5 @@
[package]
name = "start-axum"
name = "leptos-use-ssr"
version = "0.1.0"
edition = "2021"
@ -15,13 +15,13 @@ leptos = { version = "0.5", features = ["nightly"] }
leptos_axum = { version = "0.5", optional = true }
leptos_meta = { version = "0.5", features = ["nightly"] }
leptos_router = { version = "0.5", features = ["nightly"] }
leptos-use = { path = "../..", features = ["storage"] }
leptos-use = { path = "../.." }
log = "0.4"
simple_logger = "4"
tokio = { version = "1.25.0", optional = true }
tower = { version = "0.4.13", optional = true }
tower-http = { version = "0.4.3", features = ["fs"], optional = true }
wasm-bindgen = "=0.2.87"
wasm-bindgen = "0.2.88"
thiserror = "1.0.38"
tracing = { version = "0.1.37", optional = true }
http = "0.2.8"

View file

@ -3,10 +3,10 @@ use leptos::ev::{keypress, KeyboardEvent};
use leptos::*;
use leptos_meta::*;
use leptos_router::*;
use leptos_use::storage::use_local_storage;
use leptos_use::storage::{use_local_storage, StringCodec};
use leptos_use::{
use_debounce_fn, use_event_listener, use_intl_number_format, use_window,
UseIntlNumberFormatOptions,
use_color_mode, use_debounce_fn, use_event_listener, use_intl_number_format, use_timestamp,
use_window, ColorMode, UseColorModeReturn, UseIntlNumberFormatOptions,
};
#[component]
@ -37,7 +37,7 @@ pub fn App() -> impl IntoView {
#[component]
fn HomePage() -> impl IntoView {
// Creates a reactive value to update the button
let (count, set_count, _) = use_local_storage("count-state", 0);
let (count, set_count, _) = use_local_storage::<i32, StringCodec>("count-state");
let on_click = move |_| set_count.update(|count| *count += 1);
let nf = use_intl_number_format(
@ -63,25 +63,20 @@ fn HomePage() -> impl IntoView {
);
debounced_fn();
let UseColorModeReturn { mode, set_mode, .. } = use_color_mode();
let timestamp = use_timestamp();
view! {
<h1>
Leptos-Use SSR Example
</h1>
<button on:click=on_click>
Click Me:
{count}
</button>
<p>
Locale zh-Hans-CN-u-nu-hanidec:
{zh_count}
</p>
<p>
Press any key:
{key}
</p>
<p>
Debounced called:
{debounce_value}
</p>
<h1>Leptos-Use SSR Example</h1>
<button on:click=on_click>Click Me: {count}</button>
<p>Locale zh-Hans-CN-u-nu-hanidec: {zh_count}</p>
<p>Press any key: {key}</p>
<p>Debounced called: {debounce_value}</p>
<p>Color mode: {move || format!("{:?}", mode.get())}</p>
<button on:click=move |_| set_mode.set(ColorMode::Light)>Change to Light</button>
<button on:click=move |_| set_mode.set(ColorMode::Dark)>Change to Dark</button>
<button on:click=move |_| set_mode.set(ColorMode::Auto)>Change to Auto</button>
<p>{timestamp}</p>
}
}

View file

@ -5,8 +5,8 @@ async fn main() {
use leptos::logging::log;
use leptos::*;
use leptos_axum::{generate_route_list, LeptosRoutes};
use start_axum::app::*;
use start_axum::fileserv::file_and_error_handler;
use leptos_use_ssr::app::*;
use leptos_use_ssr::fileserv::file_and_error_handler;
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
@ -18,7 +18,7 @@ async fn main() {
let conf = get_configuration(None).await.unwrap();
let leptos_options = conf.leptos_options;
let addr = leptos_options.site_addr;
let routes = generate_route_list(|| view! { <App/> }).await;
let routes = generate_route_list(|| view! { <App/> });
// build our application with a route
let app = Router::new()

View file

@ -1,4 +1,9 @@
body {
font-family: sans-serif;
text-align: center;
font-family: sans-serif;
text-align: center;
}
.dark {
background-color: black;
color: white;
}

View file

@ -19,11 +19,7 @@ fn Demo() -> impl IntoView {
<Note class="mb-3">"Select the inputs below to see the changes"</Note>
<div class="grid grid-cols-1 md:grid-cols-3 gap-2">
<For
each=move || (1..7)
key=|i| *i
let:i
>
<For each=move || (1..7) key=|i| *i let:i>
<input type="text" data-id=i class="!my-0 !min-w-0" placeholder=i/>
</For>

View file

@ -8,7 +8,7 @@ leptos = { version = "0.5", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs", "storage"] }
leptos-use = { path = "../..", features = ["docs"] }
web-sys = "0.3"
[dev-dependencies]

View file

@ -0,0 +1,16 @@
[package]
name = "use_display_media"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.5", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs"] }
web-sys = "0.3"
[dev-dependencies]
wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.0"

View file

@ -0,0 +1,23 @@
A simple example for `use_display_media`.
If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation)
as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target:
```bash
cargo install trunk
npm install -D tailwindcss @tailwindcss/forms
rustup toolchain install nightly
rustup target add wasm32-unknown-unknown
```
Then, open two terminals. In the first one, run:
```
npx tailwindcss -i ./input.css -o ./style/output.css --watch
```
In the second one, run:
```bash
trunk serve --open
```

View file

@ -0,0 +1,2 @@
[build]
public_url = "/demo/"

View file

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<link data-trunk rel="css" href="style/output.css">
</head>
<body></body>
</html>

View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View file

@ -0,0 +1,57 @@
use leptos::*;
use leptos_use::docs::demo_or_body;
use leptos_use::{use_display_media, UseDisplayMediaReturn};
#[component]
fn Demo() -> impl IntoView {
let video_ref = create_node_ref::<leptos::html::Video>();
let UseDisplayMediaReturn {
stream,
enabled,
set_enabled,
..
} = use_display_media();
create_effect(move |_| {
match stream.get() {
Some(Ok(s)) => {
video_ref.get().map(|v| v.set_src_object(Some(&s)));
return;
}
Some(Err(e)) => logging::error!("Failed to get media stream: {:?}", e),
None => logging::log!("No stream yet"),
}
video_ref.get().map(|v| v.set_src_object(None));
});
view! {
<div class="flex flex-col gap-4 text-center">
<div>
<button on:click=move |_| set_enabled(
!enabled(),
)>{move || if enabled() { "Stop" } else { "Start" }} sharing my screen</button>
</div>
<div>
<video
node_ref=video_ref
controls=false
autoplay=true
muted=true
class="h-96 w-auto"
></video>
</div>
</div>
}
}
fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to(demo_or_body(), || {
view! { <Demo/> }
})
}

View file

@ -0,0 +1,342 @@
[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
border-radius: 0px;
padding-top: 0.5rem;
padding-right: 0.75rem;
padding-bottom: 0.5rem;
padding-left: 0.75rem;
font-size: 1rem;
line-height: 1.5rem;
--tw-shadow: 0 0 #0000;
}
[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
border-color: #2563eb;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #6b7280;
opacity: 1;
}
input::placeholder,textarea::placeholder {
color: #6b7280;
opacity: 1;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-date-and-time-value {
min-height: 1.5em;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
padding-top: 0;
padding-bottom: 0;
}
select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
[multiple],[size]:where(select:not([size="1"])) {
background-image: initial;
background-position: initial;
background-repeat: unset;
background-size: initial;
padding-right: 0.75rem;
-webkit-print-color-adjust: unset;
print-color-adjust: unset;
}
[type='checkbox'],[type='radio'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
display: inline-block;
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
width: 1rem;
color: #2563eb;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
--tw-shadow: 0 0 #0000;
}
[type='checkbox'] {
border-radius: 0px;
}
[type='radio'] {
border-radius: 100%;
}
[type='checkbox']:focus,[type='radio']:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 2px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
[type='checkbox']:checked,[type='radio']:checked {
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
@media (forced-colors: active) {
[type='checkbox']:checked {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='radio']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
}
@media (forced-colors: active) {
[type='radio']:checked {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
border-color: transparent;
background-color: currentColor;
}
[type='checkbox']:indeterminate {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
@media (forced-colors: active) {
[type='checkbox']:indeterminate {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
border-color: transparent;
background-color: currentColor;
}
[type='file'] {
background: unset;
border-color: inherit;
border-width: 0;
border-radius: 0;
padding: 0;
font-size: unset;
line-height: inherit;
}
[type='file']:focus {
outline: 1px solid ButtonText;
outline: 1px auto -webkit-focus-ring-color;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.static {
position: static;
}
.flex {
display: flex;
}
.h-96 {
height: 24rem;
}
.w-auto {
width: auto;
}
.flex-col {
flex-direction: column;
}
.gap-4 {
gap: 1rem;
}
.text-center {
text-align: center;
}
.text-\[--brand-color\] {
color: var(--brand-color);
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.opacity-75 {
opacity: 0.75;
}
@media (prefers-color-scheme: dark) {
.dark\:text-green-500 {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity));
}
}

View file

@ -0,0 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"],
},
theme: {
extend: {},
},
corePlugins: {
preflight: false,
},
plugins: [
require('@tailwindcss/forms'),
],
}

View file

@ -2,13 +2,16 @@ use leptos::html::Div;
use leptos::*;
use leptos_use::core::Position;
use leptos_use::docs::demo_or_body;
use leptos_use::{use_draggable_with_options, UseDraggableOptions, UseDraggableReturn};
use leptos_use::{use_draggable_with_options, use_window, UseDraggableOptions, UseDraggableReturn};
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let inner_width = window().inner_width().unwrap().as_f64().unwrap();
let inner_width = use_window()
.as_ref()
.map(|w| w.inner_width().unwrap().as_f64().unwrap())
.unwrap_or(0.0);
let UseDraggableReturn { x, y, style, .. } = use_draggable_with_options(
el,
@ -21,20 +24,14 @@ fn Demo() -> impl IntoView {
);
view! {
<p class="italic op50 text-center">
Check the floating box
</p>
<p class="italic op50 text-center">Check the floating box</p>
<div
node_ref=el
class="px-4 py-2 border border-gray-400/30 rounded shadow hover:shadow-lg fixed bg-[--bg] select-none cursor-move z-24"
style=move || format!("touch-action: none; {}", style())
>
"👋 Drag me!"
<div class="text-sm opacity-50">
I am
{move || x().round()},
{move || y().round()}
</div>
<div class="text-sm opacity-50">I am {move || x().round()} , {move || y().round()}</div>
</div>
}
}

View file

@ -22,45 +22,21 @@ fn Demo() -> impl IntoView {
view! {
<div class="flex">
<div class="w-full h-auto relative">
<p>
Drop files into dropZone
</p>
<p>Drop files into dropZone</p>
<img width="64" src="use_drop_zone/demo/img/leptos-use-logo.svg" alt="Drop me"/>
<div
node_ref=drop_zone_el
class="flex flex-col w-full min-h-[200px] h-auto bg-gray-400/10 justify-center items-center pt-6"
>
<div>
is_over_drop_zone:
<BooleanDisplay value=is_over_drop_zone/>
</div>
<div>
dropped:
<BooleanDisplay value=dropped/>
</div>
<div>is_over_drop_zone: <BooleanDisplay value=is_over_drop_zone/></div>
<div>dropped: <BooleanDisplay value=dropped/></div>
<div class="flex flex-wrap justify-center items-center">
<For
each=files
key=|f| f.name()
let:file
>
<For each=files key=|f| f.name() let:file>
<div class="w-200px bg-black-200/10 ma-2 pa-6">
<p>
Name:
{file.name()}
</p>
<p>
Size:
{file.size()}
</p>
<p>
Type:
{file.type_()}
</p>
<p>
Last modified:
{file.last_modified()}
</p>
<p>Name: {file.name()}</p>
<p>Size: {file.size()}</p>
<p>Type: {file.type_()}</p>
<p>Last modified: {file.last_modified()}</p>
</div>
</For>
</div>

View file

@ -1,2 +0,0 @@
[build]
rustflags = ["--cfg=web_sys_unstable_apis"]

View file

@ -2,11 +2,11 @@ use leptos::ev::{click, keydown};
use leptos::html::A;
use leptos::logging::log;
use leptos::*;
use leptos_use::use_event_listener;
use leptos_use::{use_event_listener, use_window};
#[component]
fn Demo() -> impl IntoView {
let _ = use_event_listener(window(), keydown, |evt| {
let _ = use_event_listener(use_window(), keydown, |evt| {
log!("window keydown: '{}'", evt.key());
});

View file

@ -27,20 +27,22 @@ fn Demo() -> impl IntoView {
heading: {:?},
speed: {:?},
}}"#,
coords.accuracy(), coords.latitude(), coords.longitude(), coords.altitude(),
coords.altitude_accuracy(), coords.heading(), coords.speed()
coords.accuracy(),
coords.latitude(),
coords.longitude(),
coords.altitude(),
coords.altitude_accuracy(),
coords.heading(),
coords.speed(),
)
} else {
"None".to_string()
}
}}
,
located_at:
{located_at}
,
located_at: {located_at} ,
error:
{move || if let Some(error) = error() { error.message() } else { "None".to_string() }}
,
{move || if let Some(error) = error() { error.message() } else { "None".to_string() }} ,
</pre>
<button on:click=move |_| pause()>"Pause watch"</button>
<button on:click=move |_| resume()>"Resume watch"</button>

View file

@ -14,20 +14,11 @@ fn Demo() -> impl IntoView {
view! {
<Note class="mb-2">
For demonstration purpose, the idle timeout is set to
<b>
5s
</b>
For demonstration purpose, the idle timeout is set to <b>5s</b>
in this demo (default 1min).
</Note>
<div class="mb-2">
Idle:
<BooleanDisplay value=idle/>
</div>
<div>
Inactive:
<b>{idled_for} s</b>
</div>
<div class="mb-2">Idle: <BooleanDisplay value=idle/></div>
<div>Inactive: <b>{idled_for} s</b></div>
}
}

View file

@ -0,0 +1,16 @@
[package]
name = "use_infinite_scroll"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.5", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs"] }
web-sys = "0.3"
[dev-dependencies]
wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.0"

View file

@ -0,0 +1,23 @@
A simple example for `use_infinite_scroll`.
If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation)
as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target:
```bash
cargo install trunk
npm install -D tailwindcss @tailwindcss/forms
rustup toolchain install nightly
rustup target add wasm32-unknown-unknown
```
Then, open two terminals. In the first one, run:
```
npx tailwindcss -i ./input.css -o ./style/output.css --watch
```
In the second one, run:
```bash
trunk serve --open
```

View file

@ -0,0 +1,2 @@
[build]
public_url = "/demo/"

View file

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<link data-trunk rel="css" href="style/output.css">
</head>
<body></body>
</html>

View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View file

@ -0,0 +1,40 @@
use leptos::html::Div;
use leptos::*;
use leptos_use::docs::demo_or_body;
use leptos_use::{use_infinite_scroll_with_options, UseInfiniteScrollOptions};
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let (data, set_data) = create_signal(vec![1, 2, 3, 4, 5, 6]);
let _ = use_infinite_scroll_with_options(
el,
move |_| async move {
let len = data.with_untracked(|d| d.len());
set_data.update(|data| *data = (1..len + 6).collect());
},
UseInfiniteScrollOptions::default().distance(10.0),
);
view! {
<div
node_ref=el
class="flex flex-col gap-2 p-4 w-[300px] h-[300px] m-auto overflow-y-scroll bg-gray-500/5 rounded"
>
<For each=move || data.get() key=|i| *i let:item>
<div class="h-15 bg-gray-500/5 rounded p-3">{item}</div>
</For>
</div>
}
}
fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to(demo_or_body(), || {
view! { <Demo/> }
})
}

View file

@ -0,0 +1,338 @@
[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
border-radius: 0px;
padding-top: 0.5rem;
padding-right: 0.75rem;
padding-bottom: 0.5rem;
padding-left: 0.75rem;
font-size: 1rem;
line-height: 1.5rem;
--tw-shadow: 0 0 #0000;
}
[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
border-color: #2563eb;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #6b7280;
opacity: 1;
}
input::placeholder,textarea::placeholder {
color: #6b7280;
opacity: 1;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-date-and-time-value {
min-height: 1.5em;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
padding-top: 0;
padding-bottom: 0;
}
select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
[multiple],[size]:where(select:not([size="1"])) {
background-image: initial;
background-position: initial;
background-repeat: unset;
background-size: initial;
padding-right: 0.75rem;
-webkit-print-color-adjust: unset;
print-color-adjust: unset;
}
[type='checkbox'],[type='radio'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
display: inline-block;
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
width: 1rem;
color: #2563eb;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
--tw-shadow: 0 0 #0000;
}
[type='checkbox'] {
border-radius: 0px;
}
[type='radio'] {
border-radius: 100%;
}
[type='checkbox']:focus,[type='radio']:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 2px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
[type='checkbox']:checked,[type='radio']:checked {
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
[type='radio']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
}
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
border-color: transparent;
background-color: currentColor;
}
[type='checkbox']:indeterminate {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
border-color: transparent;
background-color: currentColor;
}
[type='file'] {
background: unset;
border-color: inherit;
border-width: 0;
border-radius: 0;
padding: 0;
font-size: unset;
line-height: inherit;
}
[type='file']:focus {
outline: 1px solid ButtonText;
outline: 1px auto -webkit-focus-ring-color;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.static {
position: static;
}
.m-auto {
margin: auto;
}
.flex {
display: flex;
}
.h-\[300px\] {
height: 300px;
}
.w-\[300px\] {
width: 300px;
}
.flex-col {
flex-direction: column;
}
.gap-2 {
gap: 0.5rem;
}
.overflow-y-scroll {
overflow-y: scroll;
}
.rounded {
border-radius: 0.25rem;
}
.bg-gray-500\/5 {
background-color: rgb(107 114 128 / 0.05);
}
.p-3 {
padding: 0.75rem;
}
.p-4 {
padding: 1rem;
}
.text-\[--brand-color\] {
color: var(--brand-color);
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.opacity-75 {
opacity: 0.75;
}
@media (prefers-color-scheme: dark) {
.dark\:text-green-500 {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity));
}
}

View file

@ -0,0 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"],
},
theme: {
extend: {},
},
corePlugins: {
preflight: false,
},
plugins: [
require('@tailwindcss/forms'),
],
}

View file

@ -42,8 +42,10 @@ fn Demo() -> impl IntoView {
r#" x: {}
y: {}
source_type: {:?}
"#, mouse_default.x.get(),
mouse_default.y.get(), mouse_default.source_type.get()
"#,
mouse_default.x.get(),
mouse_default.y.get(),
mouse_default.source_type.get(),
)
}}
@ -56,8 +58,10 @@ fn Demo() -> impl IntoView {
r#" x: {}
y: {}
source_type: {:?}
"#, mouse_with_extractor.x
.get(), mouse_with_extractor.y.get(), mouse_with_extractor.source_type.get()
"#,
mouse_with_extractor.x.get(),
mouse_with_extractor.y.get(),
mouse_with_extractor.source_type.get(),
)
}}

View file

@ -15,10 +15,7 @@ fn Demo() -> impl IntoView {
});
view! {
<div>
Count:
{count}
</div>
<div>Count: {count}</div>
<button on:click=move |_| pause() disabled=move || !is_active()>
Pause
</button>

View file

@ -0,0 +1,16 @@
[package]
name = "use_service_worker"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.5", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs"] }
web-sys = "0.3"
[dev-dependencies]
wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.0"

View file

@ -0,0 +1,23 @@
A simple example for `use_service_worker`.
If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation)
as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target:
```bash
cargo install trunk
npm install -D tailwindcss @tailwindcss/forms
rustup toolchain install nightly
rustup target add wasm32-unknown-unknown
```
Then, open two terminals. In the first one, run:
```
npx tailwindcss -i ./input.css -o ./style/output.css --watch
```
In the second one, run:
```bash
trunk serve --open
```

View file

@ -0,0 +1,7 @@
[build]
public_url = "/demo/"
[[hooks]]
stage = "post_build"
command = "bash"
command_arguments = ["post_build.sh"]

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta name="version" content="{{buildVersion}}">
<link data-trunk rel="css" href="style/output.css">
<link data-trunk rel="copy-file" href="manifest.json" />
<link data-trunk rel="copy-file" href="service-worker.js" />
</head>
<body></body>
</html>

View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -0,0 +1,54 @@
{
"name": "Demo",
"short_name": "Demo",
"icons": [
{
"src": "./res/icon/maskable_icon_x48.png",
"sizes": "48x48",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "./res/icon/maskable_icon_x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "./res/icon/maskable_icon_x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "./res/icon/maskable_icon_x128.png",
"sizes": "128x128",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "./res/icon/maskable_icon_x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "./res/icon/maskable_icon_x384.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "./res/icon/maskable_icon_x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"lang": "en-US",
"id": "/demo/",
"start_url": "/demo/",
"display": "standalone",
"background_color": "#e52320",
"theme_color": "#e52320"
}

View file

@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -e
appName="use_service_worker"
stylePrefix="output"
styleFormat="css"
# Extract build version
indexJsFile=$(find ./dist/.stage -iname "${appName}-*.js")
echo "Extracting build version from file: ${indexJsFile}"
regex="(.*)${appName}-(.*).js"
_src="${indexJsFile}"
while [[ "${_src}" =~ ${regex} ]]; do
buildVersion="${BASH_REMATCH[2]}"
_i=${#BASH_REMATCH}
_src=${_src:_i}
done
if [ -z "${buildVersion}" ]; then
echo "Could not determine build version!"
exit 1
fi
echo "Build-Version is: ${buildVersion}"
# Replace placeholder in service-worker.js
serviceWorkerJsFile=$(find ./dist/.stage -iname "service-worker.js")
echo "Replacing {{buildVersion}} placeholder in: ${serviceWorkerJsFile}"
sed "s/{{buildVersion}}/${buildVersion}/g" "${serviceWorkerJsFile}" > "${serviceWorkerJsFile}.modified"
mv -f "${serviceWorkerJsFile}.modified" "${serviceWorkerJsFile}"
# Replace placeholder in index.html
indexHtmlFile=$(find ./dist/.stage -iname "index.html")
echo "Replacing {{buildVersion}} placeholder in: ${indexHtmlFile}"
sed "s/{{buildVersion}}/${buildVersion}/g" "${indexHtmlFile}" > "${indexHtmlFile}.modified"
mv -f "${indexHtmlFile}.modified" "${indexHtmlFile}"
# Extract CSS build version
indexJsFile=$(find ./dist/.stage -iname "${stylePrefix}-*.${styleFormat}")
echo "Extracting style build version from file: ${indexJsFile}"
regex="(.*)${stylePrefix}-(.*).${styleFormat}"
_src="${indexJsFile}"
while [[ "${_src}" =~ ${regex} ]]; do
cssBuildVersion="${BASH_REMATCH[2]}"
_i=${#BASH_REMATCH}
_src=${_src:_i}
done
if [ -z "${cssBuildVersion}" ]; then
echo "Could not determine style build version!"
exit 1
fi
echo "CSS Build-Version is: ${cssBuildVersion}"
# Replace placeholder in service-worker.js
serviceWorkerJsFile=$(find ./dist/.stage -iname "service-worker.js")
echo "Replacing {{cssBuildVersion}} placeholder in: ${serviceWorkerJsFile}"
sed "s/{{cssBuildVersion}}/${cssBuildVersion}/g" "${serviceWorkerJsFile}" > "${serviceWorkerJsFile}.modified"
mv -f "${serviceWorkerJsFile}.modified" "${serviceWorkerJsFile}"

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="1952" height="734.935" viewBox="0 0 1952.00 734.93" enable-background="new 0 0 1952.00 734.93" xml:space="preserve">
<g>
<path fill="#3D3D3D" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 1436.62,603.304L 1493.01,460.705L 1655.83,460.705L 1578.56,244.39L 1675.2,0.000528336L 1952,734.933L 1747.87,734.933L 1700.57,603.304L 1436.62,603.304 Z "/>
<path fill="#5A0FC8" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 1262.47,734.935L 1558.79,0.00156593L 1362.34,0.0025425L 1159.64,474.933L 1015.5,0.00351906L 864.499,0.00351906L 709.731,474.933L 600.585,258.517L 501.812,562.819L 602.096,734.935L 795.427,734.935L 935.284,309.025L 1068.63,734.935L 1262.47,734.935 Z "/>
<path fill="#3D3D3D" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 186.476,482.643L 307.479,482.643C 344.133,482.643 376.772,478.552 405.396,470.37L 436.689,373.962L 524.148,104.516C 517.484,93.9535 509.876,83.9667 501.324,74.5569C 456.419,24.852 390.719,0.000406265 304.222,0.000406265L -3.8147e-006,0.000406265L -3.8147e-006,734.933L 186.476,734.933L 186.476,482.643 Z M 346.642,169.079C 364.182,186.732 372.951,210.355 372.951,239.95C 372.951,269.772 365.238,293.424 349.813,310.906C 332.903,330.331 301.766,340.043 256.404,340.043L 186.476,340.043L 186.476,142.598L 256.918,142.598C 299.195,142.598 329.103,151.425 346.642,169.079 Z "/>
</g>
</svg>

View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View file

@ -0,0 +1,82 @@
var buildVersion = "{{buildVersion}}"
var cssBuildVersion = "{{cssBuildVersion}}"
var cacheName = "demo";
var filesToCache = [
'./',
'./index.html',
'./manifest.json',
'./use_service_worker-' + buildVersion + '_bg.wasm',
'./use_service_worker-' + buildVersion + '.js',
'./output-' + cssBuildVersion + '.css',
'./res/icon/maskable_icon_x48.png',
'./res/icon/maskable_icon_x72.png',
'./res/icon/maskable_icon_x96.png',
'./res/icon/maskable_icon_x128.png',
'./res/icon/maskable_icon_x192.png',
'./res/icon/maskable_icon_x384.png',
'./res/icon/maskable_icon_x512.png',
// TODO: Add files you want the SW to cache. Rename entries to match your build output!
];
/* Start the service worker and cache all of the app's content */
self.addEventListener('install', function (event) {
console.log("Installing service-worker for build", buildVersion);
const preCache = async () => {
get_cache().then(function (cache) {
// We clear the whole cache, as we do not know which resources were updated!
cache.keys().then(function (requests) {
for (let request of requests) {
cache.delete(request);
}
});
cache.addAll(filesToCache.map(url => new Request(url, { credentials: 'same-origin' })));
})
};
event.waitUntil(preCache);
});
self.addEventListener('message', function (messageEvent) {
if (messageEvent.data === "skipWaiting") {
console.log("Service-worker received skipWaiting event", buildVersion);
self.skipWaiting();
}
});
self.addEventListener('fetch', function (e) {
e.respondWith(cache_then_network(e.request));
});
async function get_cache() {
return caches.open(cacheName);
}
async function cache_then_network(request) {
const cache = await get_cache();
return cache.match(request).then(
(cache_response) => {
if (!cache_response) {
return fetch_from_network(request, cache);
} else {
return cache_response;
}
},
(reason) => {
return fetch_from_network(request, cache);
}
);
}
function fetch_from_network(request, cache) {
return fetch(request).then(
(net_response) => {
return net_response;
},
(reason) => {
console.error("Network fetch rejected. Falling back to ./index.html. Reason: ", reason);
return cache.match("./index.html").then(function (cache_root_response) {
return cache_root_response;
});
}
)
}

View file

@ -0,0 +1,59 @@
use leptos::*;
use leptos_use::docs::{demo_or_body, BooleanDisplay};
use leptos_use::{use_document, use_service_worker, UseServiceWorkerReturn};
use web_sys::HtmlMetaElement;
#[component]
fn Demo() -> impl IntoView {
let build = load_meta_element("version")
.map(|meta| meta.content())
.expect("'version' meta element");
let UseServiceWorkerReturn {
registration,
installing,
waiting,
active,
skip_waiting,
..
} = use_service_worker();
view! {
<p>"Current build: " {build}</p>
<br/>
<p>"registration: " {move || format!("{:#?}", registration())}</p>
<p>"installing: " <BooleanDisplay value=installing/></p>
<p>"waiting: " <BooleanDisplay value=waiting/></p>
<p>"active: " <BooleanDisplay value=active/></p>
<br/>
<button on:click=move |_| { skip_waiting() }>"Send skip_waiting event"</button>
}
}
fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to(demo_or_body(), || {
view! { <Demo/> }
})
}
fn load_meta_element(name: &str) -> Result<web_sys::HtmlMetaElement, String> {
use wasm_bindgen::JsCast;
if let Some(document) = &*use_document() {
document
.query_selector(format!("meta[name=\"{name}\"]").as_str())
.ok()
.flatten()
.ok_or_else(|| format!("Unable to find meta element with name '{name}'."))?
.dyn_into::<HtmlMetaElement>()
.map_err(|err| format!("Unable to cast element to HtmlMetaElement. Err: '{err:?}'."))
} else {
Err("Unable to find document.".into())
}
}

View file

@ -0,0 +1,294 @@
[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
border-radius: 0px;
padding-top: 0.5rem;
padding-right: 0.75rem;
padding-bottom: 0.5rem;
padding-left: 0.75rem;
font-size: 1rem;
line-height: 1.5rem;
--tw-shadow: 0 0 #0000;
}
[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
border-color: #2563eb;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #6b7280;
opacity: 1;
}
input::placeholder,textarea::placeholder {
color: #6b7280;
opacity: 1;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-date-and-time-value {
min-height: 1.5em;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
padding-top: 0;
padding-bottom: 0;
}
select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
[multiple],[size]:where(select:not([size="1"])) {
background-image: initial;
background-position: initial;
background-repeat: unset;
background-size: initial;
padding-right: 0.75rem;
-webkit-print-color-adjust: unset;
print-color-adjust: unset;
}
[type='checkbox'],[type='radio'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
display: inline-block;
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
width: 1rem;
color: #2563eb;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
--tw-shadow: 0 0 #0000;
}
[type='checkbox'] {
border-radius: 0px;
}
[type='radio'] {
border-radius: 100%;
}
[type='checkbox']:focus,[type='radio']:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 2px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
[type='checkbox']:checked,[type='radio']:checked {
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
[type='radio']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
}
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
border-color: transparent;
background-color: currentColor;
}
[type='checkbox']:indeterminate {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
border-color: transparent;
background-color: currentColor;
}
[type='file'] {
background: unset;
border-color: inherit;
border-width: 0;
border-radius: 0;
padding: 0;
font-size: unset;
line-height: inherit;
}
[type='file']:focus {
outline: 1px solid ButtonText;
outline: 1px auto -webkit-focus-ring-color;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.static {
position: static;
}
.text-\[--brand-color\] {
color: var(--brand-color);
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.opacity-75 {
opacity: 0.75;
}
@media (prefers-color-scheme: dark) {
.dark\:text-green-500 {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity));
}
}

View file

@ -0,0 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"],
},
theme: {
extend: {},
},
corePlugins: {
preflight: false,
},
plugins: [
require('@tailwindcss/forms'),
],
}

View file

@ -0,0 +1,16 @@
[package]
name = "use_sorted"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.5", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs"] }
web-sys = "0.3"
[dev-dependencies]
wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.0"

View file

@ -0,0 +1,23 @@
A simple example for `use_sorted`.
If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation)
as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target:
```bash
cargo install trunk
npm install -D tailwindcss @tailwindcss/forms
rustup toolchain install nightly
rustup target add wasm32-unknown-unknown
```
Then, open two terminals. In the first one, run:
```
npx tailwindcss -i ./input.css -o ./style/output.css --watch
```
In the second one, run:
```bash
trunk serve --open
```

View file

@ -0,0 +1,2 @@
[build]
public_url = "/demo/"

View file

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<link data-trunk rel="css" href="style/output.css">
</head>
<body></body>
</html>

View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View file

@ -0,0 +1,44 @@
use leptos::*;
use leptos_use::docs::demo_or_body;
use leptos_use::use_sorted;
fn string_list(list: &[i32]) -> String {
list.into_iter()
.map(i32::to_string)
.collect::<Vec<_>>()
.join(",")
}
#[component]
fn Demo() -> impl IntoView {
let (list, set_list) = create_signal::<Vec<i32>>(vec![4, 2, 67, 34, 76, 22, 2, 4, 65, 23]);
let sorted: Signal<Vec<i32>> = use_sorted(list);
let on_input = move |evt| {
set_list.update(|list| {
*list = event_target_value(&evt)
.split(",")
.map(|n| n.parse::<i32>().unwrap_or(0))
.collect::<Vec<i32>>()
});
};
let input_text = move || string_list(&list());
let sorted_text = move || string_list(&sorted());
view! {
<div>Input:</div>
<input prop:value=input_text on:input=on_input type="text"/>
<p>Output: {sorted_text}</p>
}
}
fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to(demo_or_body(), || {
view! { <Demo/> }
})
}

View file

@ -0,0 +1,289 @@
[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
border-radius: 0px;
padding-top: 0.5rem;
padding-right: 0.75rem;
padding-bottom: 0.5rem;
padding-left: 0.75rem;
font-size: 1rem;
line-height: 1.5rem;
--tw-shadow: 0 0 #0000;
}
[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
border-color: #2563eb;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #6b7280;
opacity: 1;
}
input::placeholder,textarea::placeholder {
color: #6b7280;
opacity: 1;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-date-and-time-value {
min-height: 1.5em;
}
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
padding-top: 0;
padding-bottom: 0;
}
select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
[multiple] {
background-image: initial;
background-position: initial;
background-repeat: unset;
background-size: initial;
padding-right: 0.75rem;
-webkit-print-color-adjust: unset;
print-color-adjust: unset;
}
[type='checkbox'],[type='radio'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
display: inline-block;
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
width: 1rem;
color: #2563eb;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
--tw-shadow: 0 0 #0000;
}
[type='checkbox'] {
border-radius: 0px;
}
[type='radio'] {
border-radius: 100%;
}
[type='checkbox']:focus,[type='radio']:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 2px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
[type='checkbox']:checked,[type='radio']:checked {
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
[type='radio']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
}
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
border-color: transparent;
background-color: currentColor;
}
[type='checkbox']:indeterminate {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
border-color: transparent;
background-color: currentColor;
}
[type='file'] {
background: unset;
border-color: inherit;
border-width: 0;
border-radius: 0;
padding: 0;
font-size: unset;
line-height: inherit;
}
[type='file']:focus {
outline: 1px solid ButtonText;
outline: 1px auto -webkit-focus-ring-color;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.block {
display: block;
}
.text-\[--brand-color\] {
color: var(--brand-color);
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.opacity-75 {
opacity: 0.75;
}
@media (prefers-color-scheme: dark) {
.dark\:text-green-500 {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity));
}
}

View file

@ -0,0 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"],
},
theme: {
extend: {},
},
corePlugins: {
preflight: false,
},
plugins: [
require('@tailwindcss/forms'),
],
}

View file

@ -8,7 +8,7 @@ leptos = { version = "0.5", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs", "storage"] }
leptos-use = { path = "../..", features = ["docs", "prost", "serde"] }
web-sys = "0.3"
serde = "1.0.163"

View file

@ -1,28 +1,31 @@
use leptos::*;
use leptos_use::docs::{demo_or_body, Note};
use leptos_use::storage::use_storage;
use leptos_use::storage::{use_local_storage, JsonCodec};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct BananaState {
pub name: String,
pub color: String,
pub size: String,
pub wearing: String,
pub descending: String,
pub count: u32,
}
impl Default for BananaState {
fn default() -> Self {
Self {
name: "Bananas".to_string(),
wearing: "pyjamas".to_string(),
descending: "stairs".to_string(),
count: 2,
}
}
}
#[component]
fn Demo() -> impl IntoView {
let the_default = BananaState {
name: "Banana".to_string(),
color: "Yellow".to_string(),
size: "Medium".to_string(),
count: 0,
};
let (state, set_state, _) = use_storage("banana-state", the_default.clone());
let (state2, ..) = use_storage("banana-state", the_default.clone());
let (state, set_state, reset) = use_local_storage::<BananaState, JsonCodec>("banana-state");
let (state2, _, _) = use_local_storage::<BananaState, JsonCodec>("banana-state");
view! {
<input
@ -33,14 +36,14 @@ fn Demo() -> impl IntoView {
/>
<input
class="block"
prop:value=move || state.get().color
on:input=move |e| set_state.update(|s| s.color = event_target_value(&e))
prop:value=move || state.get().wearing
on:input=move |e| set_state.update(|s| s.wearing = event_target_value(&e))
type="text"
/>
<input
class="block"
prop:value=move || state.get().size
on:input=move |e| set_state.update(|s| s.size = event_target_value(&e))
prop:value=move || state.get().descending
on:input=move |e| set_state.update(|s| s.descending = event_target_value(&e))
type="text"
/>
<input
@ -57,6 +60,7 @@ fn Demo() -> impl IntoView {
step="1"
max="1000"
/>
<button on:click=move |_| reset()>"Delete from storage"</button>
<p>
"Second " <b>
@ -67,7 +71,9 @@ fn Demo() -> impl IntoView {
<pre>{move || format!("{:#?}", state2.get())}</pre>
<Note>
"The values are persistent. When you reload the page the values will be the same."
"The values are persistent. When you reload the page or "
<a href="#" target="_blank">"open a second window"</a>
", the values will be the same."
</Note>
}
}

View file

@ -6,12 +6,7 @@ use leptos_use::use_timestamp;
fn Demo() -> impl IntoView {
let timestamp = use_timestamp();
view! {
<div>
Timestamp:
{timestamp}
</div>
}
view! { <div>Timestamp: {timestamp}</div> }
}
fn main() {

View file

@ -0,0 +1,16 @@
[package]
name = "use_web_notification"
version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.5", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs"] }
web-sys = "0.3"
[dev-dependencies]
wasm-bindgen = "0.2"
wasm-bindgen-test = "0.3.0"

View file

@ -0,0 +1,23 @@
A simple example for `use_web_notification`.
If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation)
as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target:
```bash
cargo install trunk
npm install -D tailwindcss @tailwindcss/forms
rustup toolchain install nightly
rustup target add wasm32-unknown-unknown
```
Then, open two terminals. In the first one, run:
```
npx tailwindcss -i ./input.css -o ./style/output.css --watch
```
In the second one, run:
```bash
trunk serve --open
```

View file

@ -0,0 +1,2 @@
[build]
public_url = "/demo/"

View file

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<link data-trunk rel="css" href="style/output.css">
</head>
<body></body>
</html>

View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View file

@ -0,0 +1,52 @@
use leptos::*;
use leptos_use::docs::{demo_or_body, BooleanDisplay};
use leptos_use::{
use_web_notification_with_options, NotificationDirection, ShowOptions,
UseWebNotificationOptions, UseWebNotificationReturn,
};
#[component]
fn Demo() -> impl IntoView {
let UseWebNotificationReturn {
is_supported, show, ..
} = use_web_notification_with_options(
UseWebNotificationOptions::default()
.title("Hello World from leptos-use")
.direction(NotificationDirection::Auto)
.language("en")
// .renotify(true)
.tag("test"),
);
let show = move || {
show(ShowOptions::default());
};
view! {
<div>
<p>Supported: <BooleanDisplay value=is_supported/></p>
</div>
<Show
when=is_supported
fallback=|| {
view! { <div>The Notification Web API is not supported in your browser.</div> }
}
>
<button on:click={
let show = show.clone();
move |_| show()
}>Show Notification</button>
</Show>
}
}
fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to(demo_or_body(), || {
view! { <Demo/> }
})
}

View file

@ -0,0 +1,289 @@
[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
border-radius: 0px;
padding-top: 0.5rem;
padding-right: 0.75rem;
padding-bottom: 0.5rem;
padding-left: 0.75rem;
font-size: 1rem;
line-height: 1.5rem;
--tw-shadow: 0 0 #0000;
}
[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
border-color: #2563eb;
}
input::-moz-placeholder, textarea::-moz-placeholder {
color: #6b7280;
opacity: 1;
}
input::placeholder,textarea::placeholder {
color: #6b7280;
opacity: 1;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-date-and-time-value {
min-height: 1.5em;
}
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
padding-top: 0;
padding-bottom: 0;
}
select {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
[multiple] {
background-image: initial;
background-position: initial;
background-repeat: unset;
background-size: initial;
padding-right: 0.75rem;
-webkit-print-color-adjust: unset;
print-color-adjust: unset;
}
[type='checkbox'],[type='radio'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
display: inline-block;
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
width: 1rem;
color: #2563eb;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
--tw-shadow: 0 0 #0000;
}
[type='checkbox'] {
border-radius: 0px;
}
[type='radio'] {
border-radius: 100%;
}
[type='checkbox']:focus,[type='radio']:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 2px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #2563eb;
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
[type='checkbox']:checked,[type='radio']:checked {
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
[type='radio']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
}
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
border-color: transparent;
background-color: currentColor;
}
[type='checkbox']:indeterminate {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
border-color: transparent;
background-color: currentColor;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
border-color: transparent;
background-color: currentColor;
}
[type='file'] {
background: unset;
border-color: inherit;
border-width: 0;
border-radius: 0;
padding: 0;
font-size: unset;
line-height: inherit;
}
[type='file']:focus {
outline: 1px solid ButtonText;
outline: 1px auto -webkit-focus-ring-color;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.block {
display: block;
}
.text-\[--brand-color\] {
color: var(--brand-color);
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.opacity-75 {
opacity: 0.75;
}
@media (prefers-color-scheme: dark) {
.dark\:text-green-500 {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity));
}
}

View file

@ -0,0 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"],
},
theme: {
extend: {},
},
corePlugins: {
preflight: false,
},
plugins: [
require('@tailwindcss/forms'),
],
}

View file

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEEDCCAvigAwIBAgIUM7q41K5+wQF+tIUZVVjHRLVP8WYwDQYJKoZIhvcNAQEL
BQAwgZAxCzAJBgNVBAYTAkVTMREwDwYDVQQIDAhUZW5lcmlmZTETMBEGA1UEBwwK
R3JhbmFkaWxsYTETMBEGA1UECgwKU3lucGhvbnl0ZTEcMBoGA1UEAwwTUm9vdCBD
ZXJ0IEF1dGhvcml0eTEmMCQGCSqGSIb3DQEJARYXbWFjY2VzY2hAc3lucGhvbnl0
ZS5jb20wHhcNMjMwOTE3MjI0NDExWhcNMjUxMjIwMjI0NDExWjCBgDELMAkGA1UE
BhMCRVMxETAPBgNVBAgMCFRlbmVyaWZlMRMwEQYDVQQHDApHcmFuYWRpbGxhMRMw
EQYDVQQKDApTeW5waG9ueXRlMQwwCgYDVQQDDANCbGExJjAkBgkqhkiG9w0BCQEW
F21hY2Nlc2NoQHN5bnBob255dGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAvDj30GptcuZcTnYZxSULMQqU1csp/54kRM7Emdpsf21es16rRoUO
xXfvxGnbGgWb6F2lAG8Gmv7YoliOAliPpFTrmquGhAO/4pMGPsEWVa35/jPIZEpl
oi3p9ouoDi3LIqgNFE3BlnW0Xf3ThnMw3P9pndA5+2NnJDKYKHp0tPZwGph6qgOf
2nqp0UXZ9U5AqUdjxh7/rAec8NDmAz6TXPSDT2Tc7Xb5bUfWPf2IjxZvcdttjhlf
8CyYVZPGWSWClc7R0yaydubnOH0uOYdQhwwQdGnYA+hca+esWoT8IejmD3oup0KE
tRFFg7oCmD7H4v/r3jZb5XAvyqXTzzxwdwIDAQABo3AwbjAfBgNVHSMEGDAWgBS1
MicRfZi+HsV8udux5h1T1EWDZTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DAUBgNV
HREEDTALgglsb2NhbGhvc3QwHQYDVR0OBBYEFJFXRB1VgjrDhxU287mxGisg+MzV
MA0GCSqGSIb3DQEBCwUAA4IBAQCXBIKF8ylDhq80OxAe1EaRZKEwVKoVtoXEQLQy
0voiIx00AjfMjUC16+8rAhDDLL5PWi56zonH/2hCfJyVec/oF059MghzCPAALv1G
3koaU+4Tp9S17zLbmlExQN72LOGYs9hswWdrtqpWPeeLxzoYn+LMxANVzhBMz66y
KwnwP/BFyeVKYIVTOZfH67j3PYCLizHCOoPOh0m9/ub8QIgFzKhYl4tWKRzJBug1
wGYoMIbBasU9N4UoeeWC4OP6YA9MDmpy5D2xFDM0DKW7qYP/KsQSAgPbKKd0a//S
xKv6DFpBeEhh6+d+MAHBYu+m7nTHeO90PCtVSohtTH7fSk0r
-----END CERTIFICATE-----

View file

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC8OPfQam1y5lxO
dhnFJQsxCpTVyyn/niREzsSZ2mx/bV6zXqtGhQ7Fd+/EadsaBZvoXaUAbwaa/tii
WI4CWI+kVOuaq4aEA7/ikwY+wRZVrfn+M8hkSmWiLen2i6gOLcsiqA0UTcGWdbRd
/dOGczDc/2md0Dn7Y2ckMpgoenS09nAamHqqA5/aeqnRRdn1TkCpR2PGHv+sB5zw
0OYDPpNc9INPZNztdvltR9Y9/YiPFm9x222OGV/wLJhVk8ZZJYKVztHTJrJ25uc4
fS45h1CHDBB0adgD6Fxr56xahPwh6OYPei6nQoS1EUWDugKYPsfi/+veNlvlcC/K
pdPPPHB3AgMBAAECggEADj4FSmjzNTGHJIy9MHS4HxLc5jyERgpSVj6LE9U6Rn4h
H1N3hFOHJZwIsYUNBjAMdw228Yx1JH9KJyaqQDUxUU73sPFvsUeTWnKjk1YK+Zq7
gueqLySOAjKVNImmwsPmTg4HR1UG4/quFjqhqdfHh8Fv3XgnGwWPhWaqqs1xTUwD
DgatljfrjTt8Nx2RHtwgUQ8ZrAgrb4arQk6WjGqN4smg7n0oszmwmpRtB+9m6aNw
CXULF+qxFSWVb/5fiV4B0D2US7aNHNcrSG4yg3FYgW1HsGdFhGhnUCAGpvrzenmm
7bkijuQgkmcpd0+KMXM7rcayUCcW6wt2/ZTVL0BJ+QKBgQD09Vuymz5SBAkwbjPB
YD4JJFl8ffhW4JiXRa2q5+BwKjesk2nBLUncC8Y+lL9T8tp4+NGGujKjd/EcM03r
viq+Bh3ZZqo0WwFAQscQ9iHncf783JxSfkx60LrKpaSd7GQkvuifRizkZR0z3bde
pMcueNtGTE3hQGxSvZYWHPCqWwKBgQDEtOs8k6yxDL/DfK/ldAL+AFbQ3tj+Zt22
r6MBi/PuyGsvasXSyX/6n92a8kSC67dOwQyOwquTb/1nTMTErctD2gIyo8hjS9cw
+DdUkgaUxG0xcpWeHHTRHGwu70hqu0SRBw3AURj1NI4eohYt/gcoNEfZaFSgUprB
sDNFGZ8VFQKBgDcpQVr5BpGlgwQ67MCxEYcxfk1AeLnnnbUC5dbEnI/lkd/02i28
KxO4Ow5ApM0ctQHk1hoGt/yDt/Hnw7ZAfpOIARTBv7ZGgAOehgFVy9C4pPkAHNue
wU4uzsFvh6BgaTS1IOEtBlLwSiEx3mcbqBbY9FfiOu9seHgxZSjZn4BdAoGALNLl
P9qO4ZF8KTnCg1DaVbMSFWqSm/Yo07ZWOMYBggodkqKMDappBV1kjChkwEiibsnC
6M0nd+NvJRjzRbYsuXt2QL/dq/LeSIRnZ1gXM9NG5puryGnHnNcTN+bC479ksn+e
/JH+U/Hz6LsavsRCMUEoljwV/KqWJUjXhgl+nLkCgYA4D8lWtsMkKMh4d6iA4tR3
93VdUYZG+nwJ0Cj6fgXCapWZ/ncRXlrUzD616W4poT+R9qG1dhNnUiaw81NsbjFj
YK/sBHRTPnm8LbTGZ9WUOPcdQ+T2VNj0DLekiZ6RICazGZLTnj/RaJmJRb1w+ej1
yNaquFcA6XZ3WLDYrrcvRA==
-----END PRIVATE KEY-----

Some files were not shown because too many files have changed in this diff Show more