nodebuilder.rs 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. //! Helpers for building virtual DOM VNodes.
  2. use crate::{
  3. innerlude::VComponent,
  4. nodes::{Attribute, Listener, NodeKey, VNode},
  5. prelude::VElement,
  6. };
  7. use bumpalo::Bump;
  8. /// A virtual DOM element builder.
  9. ///
  10. /// Typically constructed with element-specific constructors, eg the `div`
  11. /// function for building `<div>` elements or the `button` function for building
  12. /// `<button>` elements.
  13. #[derive(Clone, Debug)]
  14. pub struct ElementBuilder<'a, Listeners, Attributes, Children>
  15. where
  16. Listeners: 'a + AsRef<[Listener<'a>]>,
  17. Attributes: 'a + AsRef<[Attribute<'a>]>,
  18. Children: 'a + AsRef<[VNode<'a>]>,
  19. {
  20. bump: &'a Bump,
  21. key: NodeKey,
  22. tag_name: &'a str,
  23. listeners: Listeners,
  24. attributes: Attributes,
  25. children: Children,
  26. namespace: Option<&'a str>,
  27. }
  28. impl<'a>
  29. ElementBuilder<
  30. 'a,
  31. bumpalo::collections::Vec<'a, Listener<'a>>,
  32. bumpalo::collections::Vec<'a, Attribute<'a>>,
  33. bumpalo::collections::Vec<'a, VNode<'a>>,
  34. >
  35. {
  36. /// Create a new `ElementBuilder` for an element with the given tag name.
  37. ///
  38. /// In general, only use this constructor if the tag is dynamic (i.e. you
  39. /// might build a `<div>` or you might build a `<span>` and you don't know
  40. /// until runtime). Prefer using the tag-specific constructors instead:
  41. /// `div(bump)` or `span(bump)`, etc.
  42. ///
  43. /// # Example
  44. ///
  45. /// ```
  46. /// use dioxus::{builder::*, bumpalo::Bump};
  47. ///
  48. /// let b = Bump::new();
  49. ///
  50. /// let tag_name = if flip_coin() {
  51. /// "div"
  52. /// } else {
  53. /// "span"
  54. /// };
  55. ///
  56. /// let my_element_builder = ElementBuilder::new(&b, tag_name);
  57. /// # fn flip_coin() -> bool { true }
  58. /// ```
  59. pub fn new<B>(bump: B, tag_name: &'a str) -> Self
  60. where
  61. B: Into<&'a Bump>,
  62. {
  63. let bump = bump.into();
  64. ElementBuilder {
  65. bump,
  66. key: NodeKey::NONE,
  67. tag_name,
  68. listeners: bumpalo::collections::Vec::new_in(bump),
  69. attributes: bumpalo::collections::Vec::new_in(bump),
  70. children: bumpalo::collections::Vec::new_in(bump),
  71. namespace: None,
  72. }
  73. }
  74. }
  75. impl<'a, Listeners, Attributes, Children> ElementBuilder<'a, Listeners, Attributes, Children>
  76. where
  77. Listeners: 'a + AsRef<[Listener<'a>]>,
  78. Attributes: 'a + AsRef<[Attribute<'a>]>,
  79. Children: 'a + AsRef<[VNode<'a>]>,
  80. {
  81. /// Set the listeners for this element.
  82. ///
  83. /// You can use this method to customize the backing storage for listeners,
  84. /// for example to use a fixed-size array instead of the default
  85. /// dynamically-sized `bumpalo::collections::Vec`.
  86. ///
  87. /// Any listeners already added to the builder will be overridden.
  88. ///
  89. /// # Example
  90. ///
  91. /// ```no_run
  92. /// use dioxus::{builder::*, bumpalo::Bump};
  93. ///
  94. /// let b = Bump::new();
  95. ///
  96. /// // Create a `<div>` with a fixed-size array of two listeners.
  97. /// let my_div = div(&b)
  98. /// .listeners([
  99. /// on(&b, "click", |root, vdom, event| {
  100. /// // ...
  101. /// }),
  102. /// on(&b, "dblclick", |root, vdom, event| {
  103. /// // ...
  104. /// }),
  105. /// ])
  106. /// .finish();
  107. /// ```
  108. #[inline]
  109. pub fn listeners<L>(self, listeners: L) -> ElementBuilder<'a, L, Attributes, Children>
  110. where
  111. L: 'a + AsRef<[Listener<'a>]>,
  112. {
  113. ElementBuilder {
  114. bump: self.bump,
  115. key: self.key,
  116. tag_name: self.tag_name,
  117. listeners,
  118. attributes: self.attributes,
  119. children: self.children,
  120. namespace: self.namespace,
  121. }
  122. }
  123. /// Set the attributes for this element.
  124. ///
  125. /// You can use this method to customize the backing storage for attributes,
  126. /// for example to use a fixed-size array instead of the default
  127. /// dynamically-sized `bumpalo::collections::Vec`.
  128. ///
  129. /// Any attributes already added to the builder will be overridden.
  130. ///
  131. /// # Example
  132. ///
  133. /// ```no_run
  134. /// use dioxus::{builder::*, bumpalo::Bump, Attribute};
  135. ///
  136. /// let b = Bump::new();
  137. ///
  138. /// // Create a `<div>` with a fixed-size array of two attributes.
  139. /// let my_div = div(&b)
  140. /// .attributes([
  141. /// attr("id", "my-div"),
  142. /// attr("class", "notification"),
  143. /// ])
  144. /// .finish();
  145. /// ```
  146. #[inline]
  147. pub fn attributes<A>(self, attributes: A) -> ElementBuilder<'a, Listeners, A, Children>
  148. where
  149. A: 'a + AsRef<[Attribute<'a>]>,
  150. {
  151. ElementBuilder {
  152. bump: self.bump,
  153. key: self.key,
  154. tag_name: self.tag_name,
  155. listeners: self.listeners,
  156. attributes,
  157. children: self.children,
  158. namespace: self.namespace,
  159. }
  160. }
  161. /// Set the children for this element.
  162. ///
  163. /// You can use this method to customize the backing storage for children,
  164. /// for example to use a fixed-size array instead of the default
  165. /// dynamically-sized `bumpalo::collections::Vec`.
  166. ///
  167. /// Any children already added to the builder will be overridden.
  168. ///
  169. /// # Example
  170. ///
  171. /// ```no_run
  172. /// use dioxus::{builder::*, bumpalo::Bump};
  173. ///
  174. /// let b = Bump::new();
  175. ///
  176. /// // Create a `<div>` with a fixed-size array of two `<span>` children.
  177. /// let my_div = div(&b)
  178. /// .children([
  179. /// span(&b).finish(),
  180. /// span(&b).finish(),
  181. /// ])
  182. /// .finish();
  183. /// ```
  184. #[inline]
  185. pub fn children<C>(self, children: C) -> ElementBuilder<'a, Listeners, Attributes, C>
  186. where
  187. C: 'a + AsRef<[VNode<'a>]>,
  188. {
  189. ElementBuilder {
  190. bump: self.bump,
  191. key: self.key,
  192. tag_name: self.tag_name,
  193. listeners: self.listeners,
  194. attributes: self.attributes,
  195. children,
  196. namespace: self.namespace,
  197. }
  198. }
  199. /// Set the namespace for this element.
  200. ///
  201. /// # Example
  202. ///
  203. /// ```no_run
  204. /// use dioxus::{builder::*, bumpalo::Bump};
  205. ///
  206. /// let b = Bump::new();
  207. ///
  208. /// // Create a `<td>` tag with an xhtml namespace
  209. /// let my_td = td(&b)
  210. /// .namespace(Some("http://www.w3.org/1999/xhtml"))
  211. /// .finish();
  212. /// ```
  213. #[inline]
  214. pub fn namespace(self, namespace: Option<&'a str>) -> Self {
  215. ElementBuilder {
  216. bump: self.bump,
  217. key: self.key,
  218. tag_name: self.tag_name,
  219. listeners: self.listeners,
  220. attributes: self.attributes,
  221. children: self.children,
  222. namespace,
  223. }
  224. }
  225. /// Set this element's key.
  226. ///
  227. /// When diffing sets of siblings, if an old sibling and new sibling share a
  228. /// key, then they will always reuse the same physical DOM VNode. This is
  229. /// important when using CSS animations, web components, third party JS, or
  230. /// anything else that makes the diffing implementation observable.
  231. ///
  232. /// Do not use keys if such a scenario does not apply. Keyed diffing is
  233. /// generally more expensive than not, since it is putting greater
  234. /// constraints on the diffing algorithm.
  235. ///
  236. /// # Invariants You Must Uphold
  237. ///
  238. /// The key may not be `u32::MAX`, which is a reserved key value.
  239. ///
  240. /// Keys must be unique among siblings.
  241. ///
  242. /// All sibling VNodes must be keyed, or they must all not be keyed. You may
  243. /// not mix keyed and unkeyed siblings.
  244. ///
  245. /// # Example
  246. ///
  247. /// ```no_run
  248. /// use dioxus::{builder::*, bumpalo::Bump};
  249. ///
  250. /// let b = Bump::new();
  251. ///
  252. /// let my_li = li(&b)
  253. /// .key(1337)
  254. /// .finish();
  255. /// ```
  256. #[inline]
  257. pub fn key(mut self, key: u32) -> Self {
  258. use std::u32;
  259. debug_assert!(key != u32::MAX);
  260. self.key = NodeKey(key);
  261. self
  262. }
  263. /// Create the virtual DOM VNode described by this builder.
  264. ///
  265. /// # Example
  266. ///
  267. /// ```no_run
  268. /// use dioxus::{builder::*, bumpalo::Bump, VNode};
  269. ///
  270. /// let b = Bump::new();
  271. ///
  272. /// // Start with a builder...
  273. /// let builder: ElementBuilder<_, _, _> = div(&b);
  274. ///
  275. /// // ...and finish it to create a virtual DOM VNode!
  276. /// let my_div: VNode = builder.finish();
  277. /// ```
  278. #[inline]
  279. pub fn finish(self) -> VNode<'a> {
  280. let children: &'a Children = self.bump.alloc(self.children);
  281. let children: &'a [VNode<'a>] = children.as_ref();
  282. let listeners: &'a Listeners = self.bump.alloc(self.listeners);
  283. let listeners: &'a [Listener<'a>] = listeners.as_ref();
  284. let attributes: &'a Attributes = self.bump.alloc(self.attributes);
  285. let attributes: &'a [Attribute<'a>] = attributes.as_ref();
  286. VNode::element(
  287. self.bump,
  288. self.key,
  289. self.tag_name,
  290. listeners,
  291. attributes,
  292. children,
  293. self.namespace,
  294. )
  295. }
  296. }
  297. impl<'a, Attributes, Children>
  298. ElementBuilder<'a, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children>
  299. where
  300. Attributes: 'a + AsRef<[Attribute<'a>]>,
  301. Children: 'a + AsRef<[VNode<'a>]>,
  302. {
  303. /// Add a new event listener to this element.
  304. ///
  305. /// The `event` string specifies which event will be listened for. The
  306. /// `callback` function is the function that will be invoked if the
  307. /// specified event occurs.
  308. ///
  309. /// # Example
  310. ///
  311. /// ```no_run
  312. /// use dioxus::{builder::*, bumpalo::Bump};
  313. ///
  314. /// let b = Bump::new();
  315. ///
  316. /// // A button that does something when clicked!
  317. /// let my_button = button(&b)
  318. /// .on("click", |root, vdom, event| {
  319. /// // ...
  320. /// })
  321. /// .finish();
  322. /// ```
  323. #[inline]
  324. pub fn on(mut self, event: &'a str, callback: impl Fn(()) + 'a) -> Self
  325. // pub fn on<F>(mut self, event: &'a str, callback: impl Fn(()) -> () + 'static) -> Self
  326. // F: Fn(()) + 'static,
  327. // F: Fn(()) + 'a,
  328. {
  329. // self.listeners.push(Listener {
  330. // event,
  331. // callback: self.bump.alloc(callback),
  332. // });
  333. self
  334. }
  335. }
  336. impl<'a, Listeners, Children>
  337. ElementBuilder<'a, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children>
  338. where
  339. Listeners: 'a + AsRef<[Listener<'a>]>,
  340. Children: 'a + AsRef<[VNode<'a>]>,
  341. {
  342. /// Add a new attribute to this element.
  343. ///
  344. /// # Example
  345. ///
  346. /// ```no_run
  347. /// use dioxus::{builder::*, bumpalo::Bump};
  348. ///
  349. /// let b = Bump::new();
  350. ///
  351. /// // Create the `<div id="my-div"/>` element.
  352. /// let my_div = div(&b).attr("id", "my-div").finish();
  353. /// ```
  354. #[inline]
  355. pub fn attr(mut self, name: &'static str, value: &'a str) -> Self {
  356. self.attributes.push(Attribute { name, value });
  357. self
  358. }
  359. /// Conditionally add a "boolean-style" attribute to this element.
  360. ///
  361. /// If the `should_add` parameter is true, then adds an attribute with the
  362. /// given `name` and an empty string value. If the `should_add` parameter is
  363. /// false, then the attribute is not added.
  364. ///
  365. /// This method is useful for attributes whose semantics are defined by
  366. /// whether or not the attribute is present or not, and whose value is
  367. /// ignored. Example attributes like this include:
  368. ///
  369. /// * `checked`
  370. /// * `hidden`
  371. /// * `selected`
  372. ///
  373. /// # Example
  374. ///
  375. /// ```no_run
  376. /// use dioxus::{builder::*, bumpalo::Bump};
  377. /// use js_sys::Math;
  378. ///
  379. /// let b = Bump::new();
  380. ///
  381. /// // Create the `<div>` that is randomly hidden 50% of the time.
  382. /// let my_div = div(&b)
  383. /// .bool_attr("hidden", Math::random() >= 0.5)
  384. /// .finish();
  385. /// ```
  386. pub fn bool_attr(mut self, name: &'static str, should_add: bool) -> Self {
  387. if should_add {
  388. self.attributes.push(Attribute { name, value: "" });
  389. }
  390. self
  391. }
  392. }
  393. impl<'a, Listeners, Attributes>
  394. ElementBuilder<'a, Listeners, Attributes, bumpalo::collections::Vec<'a, VNode<'a>>>
  395. where
  396. Listeners: 'a + AsRef<[Listener<'a>]>,
  397. Attributes: 'a + AsRef<[Attribute<'a>]>,
  398. {
  399. /// Add a new child to this element.
  400. ///
  401. /// # Example
  402. ///
  403. /// ```no_run
  404. /// use dioxus::{builder::*, bumpalo::Bump};
  405. /// use js_sys::Math;
  406. ///
  407. /// let b = Bump::new();
  408. ///
  409. /// // Create `<p><span></span></p>`.
  410. /// let my_div = p(&b)
  411. /// .child(span(&b).finish())
  412. /// .finish();
  413. /// ```
  414. #[inline]
  415. pub fn child(mut self, child: VNode<'a>) -> Self {
  416. self.children.push(child);
  417. self
  418. }
  419. }
  420. macro_rules! builder_constructors {
  421. ( $(
  422. $(#[$attr:meta])*
  423. $name:ident;
  424. )* ) => {
  425. $(
  426. $(#[$attr])*
  427. #[inline]
  428. pub fn $name<'a, B>(
  429. bump: B,
  430. ) -> ElementBuilder<
  431. 'a,
  432. bumpalo::collections::Vec<'a, Listener<'a>>,
  433. bumpalo::collections::Vec<'a, Attribute<'a>>,
  434. bumpalo::collections::Vec<'a, VNode<'a>>,
  435. >
  436. where
  437. B: Into<&'a Bump>
  438. {
  439. ElementBuilder::new(bump, stringify!($name))
  440. }
  441. )*
  442. };
  443. ( $(
  444. $(#[$attr:meta])*
  445. $name:ident <> $namespace:tt;
  446. )* ) => {
  447. $(
  448. $(#[$attr])*
  449. #[inline]
  450. pub fn $name<'a>(
  451. bump: &'a Bump,
  452. ) -> ElementBuilder<
  453. 'a,
  454. bumpalo::collections::Vec<'a, Listener<'a>>,
  455. bumpalo::collections::Vec<'a, Attribute<'a>>,
  456. bumpalo::collections::Vec<'a, VNode<'a>>,
  457. > {
  458. let builder = ElementBuilder::new(bump, stringify!($name));
  459. builder.namespace(Some($namespace))
  460. }
  461. )*
  462. }
  463. }
  464. // Organized in the same order as
  465. // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
  466. //
  467. // Does not include obsolete elements.
  468. builder_constructors! {
  469. // Document metadata
  470. /// Build a
  471. /// [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
  472. /// element.
  473. base;
  474. /// Build a
  475. /// [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
  476. /// element.
  477. head;
  478. /// Build a
  479. /// [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
  480. /// element.
  481. link;
  482. /// Build a
  483. /// [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
  484. /// element.
  485. meta;
  486. /// Build a
  487. /// [`<style>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style)
  488. /// element.
  489. style;
  490. /// Build a
  491. /// [`<title>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title)
  492. /// element.
  493. title;
  494. // Sectioning root
  495. /// Build a
  496. /// [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
  497. /// element.
  498. body;
  499. // Content sectioning
  500. /// Build a
  501. /// [`<address>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address)
  502. /// element.
  503. address;
  504. /// Build a
  505. /// [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
  506. /// element.
  507. article;
  508. /// Build a
  509. /// [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
  510. /// element.
  511. aside;
  512. /// Build a
  513. /// [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
  514. /// element.
  515. footer;
  516. /// Build a
  517. /// [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
  518. /// element.
  519. header;
  520. /// Build a
  521. /// [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
  522. /// element.
  523. h1;
  524. /// Build a
  525. /// [`<h2>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2)
  526. /// element.
  527. h2;
  528. /// Build a
  529. /// [`<h3>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3)
  530. /// element.
  531. h3;
  532. /// Build a
  533. /// [`<h4>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4)
  534. /// element.
  535. h4;
  536. /// Build a
  537. /// [`<h5>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5)
  538. /// element.
  539. h5;
  540. /// Build a
  541. /// [`<h6>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6)
  542. /// element.
  543. h6;
  544. /// Build a
  545. /// [`<hgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup)
  546. /// element.
  547. hgroup;
  548. /// Build a
  549. /// [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
  550. /// element.
  551. main;
  552. /// Build a
  553. /// [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
  554. /// element.
  555. nav;
  556. /// Build a
  557. /// [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
  558. /// element.
  559. section;
  560. // Text content
  561. /// Build a
  562. /// [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
  563. /// element.
  564. blockquote;
  565. /// Build a
  566. /// [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
  567. /// element.
  568. dd;
  569. /// Build a
  570. /// [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
  571. /// element.
  572. div;
  573. /// Build a
  574. /// [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
  575. /// element.
  576. dl;
  577. /// Build a
  578. /// [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
  579. /// element.
  580. dt;
  581. /// Build a
  582. /// [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
  583. /// element.
  584. figcaption;
  585. /// Build a
  586. /// [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
  587. /// element.
  588. figure;
  589. /// Build a
  590. /// [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
  591. /// element.
  592. hr;
  593. /// Build a
  594. /// [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
  595. /// element.
  596. li;
  597. /// Build a
  598. /// [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
  599. /// element.
  600. ol;
  601. /// Build a
  602. /// [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
  603. /// element.
  604. p;
  605. /// Build a
  606. /// [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
  607. /// element.
  608. pre;
  609. /// Build a
  610. /// [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
  611. /// element.
  612. ul;
  613. // Inline text semantics
  614. /// Build a
  615. /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
  616. /// element.
  617. a;
  618. /// Build a
  619. /// [`<abbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr)
  620. /// element.
  621. abbr;
  622. /// Build a
  623. /// [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
  624. /// element.
  625. b;
  626. /// Build a
  627. /// [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
  628. /// element.
  629. bdi;
  630. /// Build a
  631. /// [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
  632. /// element.
  633. bdo;
  634. /// Build a
  635. /// [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
  636. /// element.
  637. br;
  638. /// Build a
  639. /// [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
  640. /// element.
  641. cite;
  642. /// Build a
  643. /// [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
  644. /// element.
  645. code;
  646. /// Build a
  647. /// [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
  648. /// element.
  649. data;
  650. /// Build a
  651. /// [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
  652. /// element.
  653. dfn;
  654. /// Build a
  655. /// [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
  656. /// element.
  657. em;
  658. /// Build a
  659. /// [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
  660. /// element.
  661. i;
  662. /// Build a
  663. /// [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
  664. /// element.
  665. kbd;
  666. /// Build a
  667. /// [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
  668. /// element.
  669. mark;
  670. /// Build a
  671. /// [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
  672. /// element.
  673. q;
  674. /// Build a
  675. /// [`<rb>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb)
  676. /// element.
  677. rb;
  678. /// Build a
  679. /// [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
  680. /// element.
  681. rp;
  682. /// Build a
  683. /// [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
  684. /// element.
  685. rt;
  686. /// Build a
  687. /// [`<rtc>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rtc)
  688. /// element.
  689. rtc;
  690. /// Build a
  691. /// [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
  692. /// element.
  693. ruby;
  694. /// Build a
  695. /// [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
  696. /// element.
  697. s;
  698. /// Build a
  699. /// [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
  700. /// element.
  701. samp;
  702. /// Build a
  703. /// [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
  704. /// element.
  705. small;
  706. /// Build a
  707. /// [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
  708. /// element.
  709. span;
  710. /// Build a
  711. /// [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
  712. /// element.
  713. strong;
  714. /// Build a
  715. /// [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
  716. /// element.
  717. sub;
  718. /// Build a
  719. /// [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
  720. /// element.
  721. sup;
  722. /// Build a
  723. /// [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
  724. /// element.
  725. time;
  726. /// Build a
  727. /// [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
  728. /// element.
  729. u;
  730. /// Build a
  731. /// [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
  732. /// element.
  733. var;
  734. /// Build a
  735. /// [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
  736. /// element.
  737. wbr;
  738. // Image and multimedia
  739. /// Build a
  740. /// [`<area>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area)
  741. /// element.
  742. area;
  743. /// Build a
  744. /// [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
  745. /// element.
  746. audio;
  747. /// Build a
  748. /// [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
  749. /// element.
  750. img;
  751. /// Build a
  752. /// [`<map>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map)
  753. /// element.
  754. map;
  755. /// Build a
  756. /// [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
  757. /// element.
  758. track;
  759. /// Build a
  760. /// [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)
  761. /// element.
  762. video;
  763. // Embedded content
  764. /// Build a
  765. /// [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed)
  766. /// element.
  767. embed;
  768. /// Build a
  769. /// [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
  770. /// element.
  771. iframe;
  772. /// Build a
  773. /// [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
  774. /// element.
  775. object;
  776. /// Build a
  777. /// [`<param>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param)
  778. /// element.
  779. param;
  780. /// Build a
  781. /// [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
  782. /// element.
  783. picture;
  784. /// Build a
  785. /// [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
  786. /// element.
  787. source;
  788. // Scripting
  789. /// Build a
  790. /// [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
  791. /// element.
  792. canvas;
  793. /// Build a
  794. /// [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
  795. /// element.
  796. noscript;
  797. /// Build a
  798. /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
  799. /// element.
  800. script;
  801. // Demarcating edits
  802. /// Build a
  803. /// [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
  804. /// element.
  805. del;
  806. /// Build a
  807. /// [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
  808. /// element.
  809. ins;
  810. // Table content
  811. /// Build a
  812. /// [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
  813. /// element.
  814. caption;
  815. /// Build a
  816. /// [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
  817. /// element.
  818. col;
  819. /// Build a
  820. /// [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
  821. /// element.
  822. colgroup;
  823. /// Build a
  824. /// [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
  825. /// element.
  826. table;
  827. /// Build a
  828. /// [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
  829. /// element.
  830. tbody;
  831. /// Build a
  832. /// [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
  833. /// element.
  834. td;
  835. /// Build a
  836. /// [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
  837. /// element.
  838. tfoot;
  839. /// Build a
  840. /// [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
  841. /// element.
  842. th;
  843. /// Build a
  844. /// [`<thead>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead)
  845. /// element.
  846. thead;
  847. /// Build a
  848. /// [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
  849. /// element.
  850. tr;
  851. // Forms
  852. /// Build a
  853. /// [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
  854. /// element.
  855. button;
  856. /// Build a
  857. /// [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
  858. /// element.
  859. datalist;
  860. /// Build a
  861. /// [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
  862. /// element.
  863. fieldset;
  864. /// Build a
  865. /// [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
  866. /// element.
  867. form;
  868. /// Build a
  869. /// [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
  870. /// element.
  871. input;
  872. /// Build a
  873. /// [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
  874. /// element.
  875. label;
  876. /// Build a
  877. /// [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
  878. /// element.
  879. legend;
  880. /// Build a
  881. /// [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
  882. /// element.
  883. meter;
  884. /// Build a
  885. /// [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup)
  886. /// element.
  887. optgroup;
  888. /// Build a
  889. /// [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
  890. /// element.
  891. option;
  892. /// Build a
  893. /// [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
  894. /// element.
  895. output;
  896. /// Build a
  897. /// [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
  898. /// element.
  899. progress;
  900. /// Build a
  901. /// [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
  902. /// element.
  903. select;
  904. /// Build a
  905. /// [`<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
  906. /// element.
  907. textarea;
  908. // Interactive elements
  909. /// Build a
  910. /// [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
  911. /// element.
  912. details;
  913. /// Build a
  914. /// [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog)
  915. /// element.
  916. dialog;
  917. /// Build a
  918. /// [`<menu>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu)
  919. /// element.
  920. menu;
  921. /// Build a
  922. /// [`<menuitem>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menuitem)
  923. /// element.
  924. menuitem;
  925. /// Build a
  926. /// [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
  927. /// element.
  928. summary;
  929. // Web components
  930. /// Build a
  931. /// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
  932. /// element.
  933. slot;
  934. /// Build a
  935. /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
  936. /// element.
  937. template;
  938. }
  939. builder_constructors! {
  940. // SVG components
  941. /// Build a
  942. /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
  943. /// element.
  944. svg <> "http://www.w3.org/2000/svg" ;
  945. /// Build a
  946. /// [`<path>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)
  947. /// element.
  948. path <> "http://www.w3.org/2000/svg";
  949. /// Build a
  950. /// [`<circle>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle)
  951. /// element.
  952. circle <> "http://www.w3.org/2000/svg";
  953. /// Build a
  954. /// [`<ellipse>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse)
  955. /// element.
  956. ellipse <> "http://www.w3.org/2000/svg";
  957. /// Build a
  958. /// [`<line>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line)
  959. /// element.
  960. line <> "http://www.w3.org/2000/svg";
  961. /// Build a
  962. /// [`<polygon>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon)
  963. /// element.
  964. polygon <> "http://www.w3.org/2000/svg";
  965. /// Build a
  966. /// [`<polyline>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline)
  967. /// element.
  968. polyline <> "http://www.w3.org/2000/svg";
  969. /// Build a
  970. /// [`<rect>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect)
  971. /// element.
  972. rect <> "http://www.w3.org/2000/svg";
  973. /// Build a
  974. /// [`<image>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image)
  975. /// element.
  976. image <> "http://www.w3.org/2000/svg";
  977. }
  978. /// Construct a text VNode.
  979. ///
  980. /// This is `dioxus`'s virtual DOM equivalent of `document.createTextVNode`.
  981. ///
  982. /// # Example
  983. ///
  984. /// ```no_run
  985. /// use dioxus::builder::*;
  986. ///
  987. /// let my_text = text("hello, dioxus!");
  988. /// ```
  989. #[inline]
  990. pub fn text<'a>(contents: &'a str) -> VNode<'a> {
  991. VNode::text(contents)
  992. }
  993. /// Construct an attribute for an element.
  994. ///
  995. /// # Example
  996. ///
  997. /// This example creates the `id="my-id"` for some element like `<div
  998. /// id="my-id"/>`.
  999. ///
  1000. /// ```no_run
  1001. /// use dioxus::builder::*;
  1002. ///
  1003. /// let my_id_attr = attr("id", "my-id");
  1004. /// ```
  1005. pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
  1006. Attribute { name, value }
  1007. }
  1008. /// Create an event listener.
  1009. ///
  1010. /// `event` is the type of event to listen for, e.g. `"click"`. The `callback`
  1011. /// is the function that will be invoked when the event occurs.
  1012. ///
  1013. /// # Example
  1014. ///
  1015. /// ```no_run
  1016. /// use dioxus::{builder::*, bumpalo::Bump};
  1017. ///
  1018. /// let b = Bump::new();
  1019. ///
  1020. /// let listener = on(&b, "click", |root, vdom, event| {
  1021. /// // do something when a click happens...
  1022. /// });
  1023. /// ```
  1024. pub fn on<'a, 'b, F: 'static>(
  1025. bump: &'a Bump,
  1026. event: &'static str,
  1027. callback: impl Fn(()) + 'a,
  1028. ) -> Listener<'a> {
  1029. Listener {
  1030. event,
  1031. callback: bump.alloc(callback),
  1032. }
  1033. }
  1034. pub fn virtual_child<'a, T>(bump: &'a Bump, props: T, f: crate::innerlude::FC<T>) -> VNode<'a> {
  1035. todo!()
  1036. // VNode::Component()
  1037. }