dioxus-native-dom 0.8.0-alpha.0

Core headless native renderer for Dioxus based on blitz
Documentation
use std::{cell::RefCell, rc::Rc, sync::atomic::AtomicUsize};

use blitz_dom::{BaseDocument, PlainDocument, Widget};
use dioxus_core::{AttributeValue, IntoAttributeValue};

#[derive(Clone, PartialEq)]
pub struct SubDocumentAttr(WriteOnceAttr<Box<PlainDocument>>);

impl SubDocumentAttr {
    pub fn new(doc: BaseDocument) -> Self {
        Self(WriteOnceAttr::new(doc.id(), Box::new(PlainDocument(doc))))
    }
}

impl IntoAttributeValue for SubDocumentAttr {
    fn into_value(self) -> AttributeValue {
        AttributeValue::Any(Rc::new(self.0))
    }
}

static ID_COUNTER: AtomicUsize = AtomicUsize::new(0);

#[derive(Clone, PartialEq)]
pub struct CustomWidgetAttr(WriteOnceAttr<Box<dyn Widget>>);

impl CustomWidgetAttr {
    pub fn new<T: Widget + 'static>(widget: T) -> Self {
        let id = ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
        let boxed = Box::new(widget) as Box<dyn Widget>;
        Self(WriteOnceAttr::new(id, boxed))
    }
}

impl IntoAttributeValue for CustomWidgetAttr {
    fn into_value(self) -> AttributeValue {
        AttributeValue::Any(Rc::new(self.0))
    }
}

pub(crate) struct WriteOnceAttr<T> {
    id: usize,
    value: Rc<RefCell<Option<T>>>,
}

impl<T> WriteOnceAttr<T> {
    pub(crate) fn new(id: usize, value: T) -> Self {
        let value = Rc::new(RefCell::new(Some(value)));
        Self { id, value }
    }
    pub(crate) fn take(&self) -> Option<T> {
        self.value.borrow_mut().take()
    }
}

impl<T> Clone for WriteOnceAttr<T> {
    fn clone(&self) -> Self {
        Self {
            id: self.id,
            value: Rc::clone(&self.value),
        }
    }
}

impl<T> PartialEq for WriteOnceAttr<T> {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}