Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cecton committed Feb 9, 2022
0 parents commit d0e34c4
Show file tree
Hide file tree
Showing 9 changed files with 556 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "yew-immutable"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
web-sys = "0.3.56"
yew = "0.19.3"

[dev-dependencies]
wasm-bindgen = "0.2.79"
xtask-wasm = { path = "/home/cecile/repos/xtask-wasm", features = ["run-example"] }
97 changes: 97 additions & 0 deletions examples/array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use wasm_bindgen::JsCast;
use wasm_bindgen::UnwrapThrowExt;
use web_sys::{HtmlInputElement, KeyboardEvent};
use yew::prelude::*;
use yew_immutable::*;

struct MyComponent;

#[derive(Properties, PartialEq)]
struct MyComponentProps {
values: IArray<IString>,
}

impl Component for MyComponent {
type Message = ();
type Properties = MyComponentProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();

html! {
<>
<p>{"Hello to:"}</p>
<ul>
{ for props.values.iter().map(|s| html!(<li>{s}</li>)) }
</ul>
</>
}
}
}

struct App {
values: IArray<IString>,
}

enum AppMessage {
AddName(String),
Noop,
}

impl Component for App {
type Message = AppMessage;
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self {
values: Default::default(),
}
}

fn update(&mut self, _: &Context<Self>, msg: Self::Message) -> bool {
match msg {
AppMessage::AddName(name) => {
self.values = self
.values
.iter()
.cloned()
.chain(std::iter::once(IString::from(name)))
.collect();
true
}
AppMessage::Noop => false,
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
let onkeyup = link.callback(|e: KeyboardEvent| {
if e.key() == "Enter" {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
let value = target.value();
target.set_value("");
AppMessage::AddName(value)
} else {
AppMessage::Noop
}
});

html! {
<>
<input {onkeyup} />
<MyComponent values={&self.values} />
</>
}
}
}

#[xtask_wasm::run_example]
fn run_app() {
yew::start_app::<App>();
}
100 changes: 100 additions & 0 deletions examples/map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use wasm_bindgen::JsCast;
use wasm_bindgen::UnwrapThrowExt;
use web_sys::{HtmlInputElement, KeyboardEvent};
use yew::prelude::*;
use yew_immutable::*;

struct MyComponent;

#[derive(Properties, PartialEq)]
struct MyComponentProps {
values: IMap<u32, IString>,
}

impl Component for MyComponent {
type Message = ();
type Properties = MyComponentProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();

html! {
<>
<p>{"Hello to:"}</p>
<ul>
{ for props.values.iter().map(|(i, s)| html!(<li>{i}{" => "}{s}</li>)) }
</ul>
</>
}
}
}

struct App {
values: IMap<u32, IString>,
}

enum AppMessage {
AddName(String),
Noop,
}

impl Component for App {
type Message = AppMessage;
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self {
values: Default::default(),
}
}

fn update(&mut self, _: &Context<Self>, msg: Self::Message) -> bool {
match msg {
AppMessage::AddName(name) => {
self.values = self
.values
.iter()
.map(|(i, s)| (*i, s.clone()))
.chain(std::iter::once((
self.values.len() as u32,
IString::from(name),
)))
.collect();
true
}
AppMessage::Noop => false,
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
let onkeyup = link.callback(|e: KeyboardEvent| {
if e.key() == "Enter" {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
let value = target.value();
target.set_value("");
AppMessage::AddName(value)
} else {
AppMessage::Noop
}
});

html! {
<>
<input {onkeyup} />
<MyComponent values={&self.values} />
</>
}
}
}

#[xtask_wasm::run_example]
fn run_app() {
yew::start_app::<App>();
}
79 changes: 79 additions & 0 deletions examples/string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use wasm_bindgen::JsCast;
use wasm_bindgen::UnwrapThrowExt;
use web_sys::{HtmlInputElement, InputEvent};
use yew::prelude::*;
use yew_immutable::*;

struct MyComponent;

#[derive(Properties, PartialEq)]
struct MyComponentProps {
name: IString,
}

impl Component for MyComponent {
type Message = ();
type Properties = MyComponentProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();

html! {
<p>{"Hello "}{&props.name}{"!"}</p>
}
}
}

struct App {
name: IString,
}

enum AppMessage {
UpdateName(String),
}

impl Component for App {
type Message = AppMessage;
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self {
name: "World".into(),
}
}

fn update(&mut self, _: &Context<Self>, msg: Self::Message) -> bool {
match msg {
AppMessage::UpdateName(name) => {
self.name = name.into();
true
}
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
let oninput = link.callback(|e: InputEvent| {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
AppMessage::UpdateName(target.value())
});

html! {
<>
<input value={&self.name} {oninput} />
<MyComponent name={&self.name} />
</>
}
}
}

#[xtask_wasm::run_example]
fn run_app() {
yew::start_app::<App>();
}
78 changes: 78 additions & 0 deletions src/array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::rc::Rc;
use yew::html::{ImplicitClone, IntoPropValue};

#[derive(PartialEq)]
pub enum IArray<T: 'static> {
Static(&'static [T]),
Rc(Rc<[T]>),
}

impl<T: 'static> Clone for IArray<T> {
fn clone(&self) -> Self {
match self {
Self::Static(a) => Self::Static(a),
Self::Rc(a) => Self::Rc(a.clone()),
}
}
}

impl<T: 'static> Default for IArray<T> {
fn default() -> Self {
Self::Static(&[])
}
}

impl<T: 'static> FromIterator<T> for IArray<T> {
fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Self {
let vec = it.into_iter().collect::<Vec<T>>();
Self::Rc(Rc::from(vec))
}
}

impl<T: 'static> IntoPropValue<IArray<T>> for &'static [T] {
fn into_prop_value(self) -> IArray<T> {
IArray::from(self)
}
}

impl<T: 'static> IntoPropValue<IArray<T>> for Vec<T> {
fn into_prop_value(self) -> IArray<T> {
IArray::from(self)
}
}

impl<T: 'static> ImplicitClone for IArray<T> {}

impl<T: 'static> From<&'static [T]> for IArray<T> {
fn from(a: &'static [T]) -> IArray<T> {
IArray::Static(a)
}
}

impl<T: 'static> From<Vec<T>> for IArray<T> {
fn from(a: Vec<T>) -> IArray<T> {
IArray::Rc(Rc::from(a))
}
}

impl<T: 'static> From<Rc<[T]>> for IArray<T> {
fn from(a: Rc<[T]>) -> IArray<T> {
IArray::Rc(a)
}
}

impl<T: 'static> IArray<T> {
pub fn iter(&self) -> impl Iterator<Item = &T> {
match self {
Self::Static(a) => a.iter(),
Self::Rc(a) => a.iter(),
}
}

pub fn len(&self) -> usize {
match self {
Self::Static(a) => a.len(),
Self::Rc(a) => a.len(),
}
}
}
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod array;
mod map;
mod string;

pub use array::*;
pub use map::*;
pub use string::*;
Loading

0 comments on commit d0e34c4

Please sign in to comment.