dioxus_core/view/
attribute.rs1use std::marker::PhantomData;
5
6use crate::{Attribute, DynamicValues, HasAttributes, IntoAttributeValue};
7use dioxus_core_template::TemplateRawTree;
8
9use super::{ElementBuilder, View, ViewTemplate};
10
11pub trait AttributeDescriptor {
13 const NAME: &'static str;
15
16 const NAMESPACE: Option<&'static str> = None;
18
19 const VOLATILE: bool = false;
21}
22
23pub struct StaticAttributeBuilder<Descriptor, Value = Descriptor>(PhantomData<(Descriptor, Value)>);
25
26#[inline]
28pub const fn static_attribute<A: AttributeDescriptor + StaticAttributeValue>()
29-> StaticAttributeBuilder<A> {
30 StaticAttributeBuilder(PhantomData)
31}
32
33impl<Descriptor, Value> ViewTemplate for StaticAttributeBuilder<Descriptor, Value>
34where
35 Descriptor: AttributeDescriptor,
36 Value: StaticAttributeValue,
37{
38 const TEMPLATE_TREE: &'static TemplateRawTree = &TemplateRawTree::StaticAttr {
39 name: Descriptor::NAME,
40 value: Value::VALUE,
41 namespace: Descriptor::NAMESPACE,
42 };
43}
44
45impl<Descriptor, Value> View for StaticAttributeBuilder<Descriptor, Value>
46where
47 Descriptor: AttributeDescriptor,
48 Value: StaticAttributeValue,
49{
50}
51
52pub trait StaticAttributeValue {
54 const VALUE: &'static str;
56}
57
58pub struct StaticAttributeValueBuilder<V>(#[doc(hidden)] pub PhantomData<V>);
60
61#[doc(hidden)]
63pub struct StaticAttributeValueBuilderMarker;
64
65pub trait IntoAttributeBuilderValue<Target, Descriptor, Marker>
67where
68 Target: AttributeBuilderTarget,
69 Descriptor: AttributeDescriptor,
70{
71 type Output;
73
74 fn append_to(self, target: Target) -> Self::Output;
76}
77
78pub struct DynamicAttributesBuilder {
80 attrs: Box<[Attribute]>,
81}
82
83#[inline]
85#[doc(hidden)]
86pub fn dynamic_attributes_builder(attrs: Box<[Attribute]>) -> DynamicAttributesBuilder {
87 DynamicAttributesBuilder { attrs }
88}
89
90impl ViewTemplate for DynamicAttributesBuilder {
91 const TEMPLATE_TREE: &'static TemplateRawTree = &TemplateRawTree::DynamicAttr;
92}
93
94impl View for DynamicAttributesBuilder {
95 fn push(self, dynamic: &mut DynamicValues) {
96 dynamic.push_attrs(self.attrs);
97 }
98}
99
100pub trait AttributeBuilderTarget: Sized {
102 type Output;
104
105 fn append_attribute(self, attr: Attribute) -> Self::Output;
107}
108
109impl<Target> AttributeBuilderTarget for Target
110where
111 Target: HasAttributes,
112{
113 type Output = Self;
114
115 #[inline]
116 fn append_attribute(self, attr: Attribute) -> Self::Output {
117 self.push_attribute(attr.name, attr.namespace, attr.value, attr.volatile)
118 }
119}
120
121impl<Tag, Attributes, Children> AttributeBuilderTarget
122 for ElementBuilder<Tag, Attributes, Children>
123{
124 type Output = ElementBuilder<Tag, (Attributes, DynamicAttributesBuilder), Children>;
125
126 #[inline]
127 fn append_attribute(self, attr: Attribute) -> Self::Output {
128 self.attribute(dynamic_attributes_builder(Box::new([attr])))
129 }
130}
131
132impl AttributeBuilderTarget for Vec<Attribute> {
133 type Output = Self;
134
135 #[inline]
136 fn append_attribute(mut self, attr: Attribute) -> Self::Output {
137 self.push(attr);
138 self
139 }
140}
141
142impl<Target, Descriptor, Marker, Value> IntoAttributeBuilderValue<Target, Descriptor, Marker>
143 for Value
144where
145 Target: AttributeBuilderTarget,
146 Descriptor: AttributeDescriptor,
147 Value: IntoAttributeValue<Marker>,
148{
149 type Output = <Target as AttributeBuilderTarget>::Output;
150
151 #[inline]
152 fn append_to(self, target: Target) -> Self::Output {
153 AttributeBuilderTarget::append_attribute(
154 target,
155 Attribute::new(
156 Descriptor::NAME,
157 self,
158 Descriptor::NAMESPACE,
159 Descriptor::VOLATILE,
160 ),
161 )
162 }
163}
164
165impl<Tag, Attributes, Children, Descriptor, Value>
166 IntoAttributeBuilderValue<
167 ElementBuilder<Tag, Attributes, Children>,
168 Descriptor,
169 StaticAttributeValueBuilderMarker,
170 > for StaticAttributeValueBuilder<Value>
171where
172 Descriptor: AttributeDescriptor,
173 Value: StaticAttributeValue,
174{
175 type Output =
176 ElementBuilder<Tag, (Attributes, StaticAttributeBuilder<Descriptor, Value>), Children>;
177
178 #[inline]
179 fn append_to(self, target: ElementBuilder<Tag, Attributes, Children>) -> Self::Output {
180 target.attribute(StaticAttributeBuilder(PhantomData))
181 }
182}