yew_and_bulma/elements/
table.rs

1use yew::{function_component, html};
2use yew::{html::ChildrenRenderer, virtual_dom::VChild, AttrValue, Children, Html, Properties};
3use yew_and_bulma_macros::base_component_properties;
4
5use crate::utils::class::ClassBuilder;
6use crate::utils::constants::IS_NARROW;
7
8/// Defines the properties of the [Bulma table element][bd].
9///
10/// Defines the properties of the table element, based on the specification
11/// found in the [Bulma table element documentation][bd].
12///
13/// # Examples
14///
15/// ```rust
16/// use yew::prelude::*;
17/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
18///
19/// #[function_component(App)]
20/// fn app() -> Html {
21///     html! {
22///         <Table>
23///             <TableHeader>{"One"}</TableHeader>
24///             <TableHeader>{"Two"}</TableHeader>
25///
26///             <TableRow>
27///                 <TableData>{ "Three" }</TableData>
28///                 <TableData>{ "Four" }</TableData>
29///             </TableRow>
30///             <TableRow>
31///                 <TableData>{ "Five" }</TableData>
32///                 <TableData>{ "Six" }</TableData>
33///             </TableRow>
34///             <TableRow>
35///                 <TableData>{ "Seven" }</TableData>
36///                 <TableData>{ "Eight" }</TableData>
37///             </TableRow>
38///         </Table>
39///     }
40/// }
41/// ```
42///
43/// [bd]: https://bulma.io/documentation/elements/table/
44#[base_component_properties]
45#[derive(Properties, PartialEq)]
46pub struct TableProperties {
47    /// Whether or not the [Bulma table element][bd] should be scrollable.
48    ///
49    /// Whether or not the [Bulma table element][bd], which will receive these
50    /// properties, will be scrollable.
51    ///
52    /// # Examples
53    ///
54    /// ```rust
55    /// use yew::prelude::*;
56    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
57    ///
58    /// #[function_component(App)]
59    /// fn app() -> Html {
60    ///     html! {
61    ///         <Table scrollable=true>
62    ///             <TableHeader>{"One"}</TableHeader>
63    ///             <TableHeader>{"Two"}</TableHeader>
64    ///
65    ///             <TableRow>
66    ///                 <TableData>{ "Three" }</TableData>
67    ///                 <TableData>{ "Four" }</TableData>
68    ///             </TableRow>
69    ///             <TableRow>
70    ///                 <TableData>{ "Five" }</TableData>
71    ///                 <TableData>{ "Six" }</TableData>
72    ///             </TableRow>
73    ///             <TableRow>
74    ///                 <TableData>{ "Seven" }</TableData>
75    ///                 <TableData>{ "Eight" }</TableData>
76    ///             </TableRow>
77    ///         </Table>
78    ///     }
79    /// }
80    /// ```
81    ///
82    /// [bd]: https://bulma.io/documentation/elements/table/#table-container
83    #[prop_or_default]
84    pub scrollable: bool,
85    /// Whether or not the [Bulma table element][bd] should be bordered.
86    ///
87    /// Whether or not the [Bulma table element][bd], which will receive these
88    /// properties, will be bordered.
89    ///
90    /// # Examples
91    ///
92    /// ```rust
93    /// use yew::prelude::*;
94    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
95    ///
96    /// #[function_component(App)]
97    /// fn app() -> Html {
98    ///     html! {
99    ///         <Table bordered=true>
100    ///             <TableHeader>{"One"}</TableHeader>
101    ///             <TableHeader>{"Two"}</TableHeader>
102    ///
103    ///             <TableRow>
104    ///                 <TableData>{ "Three" }</TableData>
105    ///                 <TableData>{ "Four" }</TableData>
106    ///             </TableRow>
107    ///             <TableRow>
108    ///                 <TableData>{ "Five" }</TableData>
109    ///                 <TableData>{ "Six" }</TableData>
110    ///             </TableRow>
111    ///             <TableRow>
112    ///                 <TableData>{ "Seven" }</TableData>
113    ///                 <TableData>{ "Eight" }</TableData>
114    ///             </TableRow>
115    ///         </Table>
116    ///     }
117    /// }
118    /// ```
119    ///
120    /// [bd]: https://bulma.io/documentation/elements/table/#modifiers
121    #[prop_or_default]
122    pub bordered: bool,
123    /// Whether or not the [Bulma table element][bd] should be striped.
124    ///
125    /// Whether or not the [Bulma table element][bd], which will receive these
126    /// properties, will be striped.
127    ///
128    /// # Examples
129    ///
130    /// ```rust
131    /// use yew::prelude::*;
132    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
133    ///
134    /// #[function_component(App)]
135    /// fn app() -> Html {
136    ///     html! {
137    ///         <Table striped=true>
138    ///             <TableHeader>{"One"}</TableHeader>
139    ///             <TableHeader>{"Two"}</TableHeader>
140    ///
141    ///             <TableRow>
142    ///                 <TableData>{ "Three" }</TableData>
143    ///                 <TableData>{ "Four" }</TableData>
144    ///             </TableRow>
145    ///             <TableRow>
146    ///                 <TableData>{ "Five" }</TableData>
147    ///                 <TableData>{ "Six" }</TableData>
148    ///             </TableRow>
149    ///             <TableRow>
150    ///                 <TableData>{ "Seven" }</TableData>
151    ///                 <TableData>{ "Eight" }</TableData>
152    ///             </TableRow>
153    ///         </Table>
154    ///     }
155    /// }
156    /// ```
157    ///
158    /// [bd]: https://bulma.io/documentation/elements/table/#modifiers
159    #[prop_or_default]
160    pub striped: bool,
161    /// Whether or not the [Bulma table element][bd] should be narrow.
162    ///
163    /// Whether or not the [Bulma table element][bd], which will receive these
164    /// properties, will be narrow.
165    ///
166    /// # Examples
167    ///
168    /// ```rust
169    /// use yew::prelude::*;
170    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
171    ///
172    /// #[function_component(App)]
173    /// fn app() -> Html {
174    ///     html! {
175    ///         <Table narrow=true>
176    ///             <TableHeader>{"One"}</TableHeader>
177    ///             <TableHeader>{"Two"}</TableHeader>
178    ///
179    ///             <TableRow>
180    ///                 <TableData>{ "Three" }</TableData>
181    ///                 <TableData>{ "Four" }</TableData>
182    ///             </TableRow>
183    ///             <TableRow>
184    ///                 <TableData>{ "Five" }</TableData>
185    ///                 <TableData>{ "Six" }</TableData>
186    ///             </TableRow>
187    ///             <TableRow>
188    ///                 <TableData>{ "Seven" }</TableData>
189    ///                 <TableData>{ "Eight" }</TableData>
190    ///             </TableRow>
191    ///         </Table>
192    ///     }
193    /// }
194    /// ```
195    ///
196    /// [bd]: https://bulma.io/documentation/elements/table/#modifiers
197    #[prop_or_default]
198    pub narrow: bool,
199    /// Whether or not the [Bulma table element][bd] should be hoverable.
200    ///
201    /// Whether or not the [Bulma table element][bd], which will receive these
202    /// properties, will be hoverable.
203    ///
204    /// # Examples
205    ///
206    /// ```rust
207    /// use yew::prelude::*;
208    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
209    ///
210    /// #[function_component(App)]
211    /// fn app() -> Html {
212    ///     html! {
213    ///         <Table hoverable=true>
214    ///             <TableHeader>{"One"}</TableHeader>
215    ///             <TableHeader>{"Two"}</TableHeader>
216    ///
217    ///             <TableRow>
218    ///                 <TableData>{ "Three" }</TableData>
219    ///                 <TableData>{ "Four" }</TableData>
220    ///             </TableRow>
221    ///             <TableRow>
222    ///                 <TableData>{ "Five" }</TableData>
223    ///                 <TableData>{ "Six" }</TableData>
224    ///             </TableRow>
225    ///             <TableRow>
226    ///                 <TableData>{ "Seven" }</TableData>
227    ///                 <TableData>{ "Eight" }</TableData>
228    ///             </TableRow>
229    ///         </Table>
230    ///     }
231    /// }
232    /// ```
233    ///
234    /// [bd]: https://bulma.io/documentation/elements/table/#modifiers
235    #[prop_or_default]
236    pub hoverable: bool,
237    /// Whether or not the [Bulma table element][bd] should be full width.
238    ///
239    /// Whether or not the [Bulma table element][bd], which will receive these
240    /// properties, will be full width.
241    ///
242    /// # Examples
243    ///
244    /// ```rust
245    /// use yew::prelude::*;
246    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
247    ///
248    /// #[function_component(App)]
249    /// fn app() -> Html {
250    ///     html! {
251    ///         <Table full_width=true>
252    ///             <TableHeader>{"One"}</TableHeader>
253    ///             <TableHeader>{"Two"}</TableHeader>
254    ///
255    ///             <TableRow>
256    ///                 <TableData>{ "Three" }</TableData>
257    ///                 <TableData>{ "Four" }</TableData>
258    ///             </TableRow>
259    ///             <TableRow>
260    ///                 <TableData>{ "Five" }</TableData>
261    ///                 <TableData>{ "Six" }</TableData>
262    ///             </TableRow>
263    ///             <TableRow>
264    ///                 <TableData>{ "Seven" }</TableData>
265    ///                 <TableData>{ "Eight" }</TableData>
266    ///             </TableRow>
267    ///         </Table>
268    ///     }
269    /// }
270    /// ```
271    ///
272    /// [bd]: https://bulma.io/documentation/elements/table/#modifiers
273    #[prop_or_default]
274    pub full_width: bool,
275    /// The list of elements found inside the [table element][bd].
276    ///
277    /// Defines the elements that will be found inside the
278    /// [Bulma table element][bd] which will receive these properties.
279    ///
280    /// [bd]: https://bulma.io/documentation/elements/table/
281    pub children: ChildrenRenderer<TableItem>,
282}
283
284impl From<&TableProperties> for String {
285    fn from(value: &TableProperties) -> Self {
286        let mut modifier_classes = String::with_capacity(80);
287
288        modifier_classes.push_str("table");
289        if value.bordered {
290            modifier_classes.push_str(" is-bordered");
291        }
292        if value.striped {
293            modifier_classes.push_str(" is-striped");
294        }
295        if value.narrow {
296            modifier_classes.push_str(IS_NARROW);
297        }
298        if value.hoverable {
299            modifier_classes.push_str(" is-hoverable");
300        }
301        if value.full_width {
302            modifier_classes.push_str(" is-fullwidth");
303        }
304
305        modifier_classes
306    }
307}
308
309/// Defines the possible types of children from a [Bulma table element][bd].
310///
311/// Defines the possible types of children found inside a
312/// [Bulma table element][bd].
313///
314/// # Examples
315///
316/// ```rust
317/// use yew::prelude::*;
318/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
319///
320/// #[function_component(App)]
321/// fn app() -> Html {
322///     html! {
323///         <Table>
324///             <TableHeader>{"One"}</TableHeader>
325///             <TableHeader>{"Two"}</TableHeader>
326///
327///             <TableRow>
328///                 <TableData>{ "Three" }</TableData>
329///                 <TableData>{ "Four" }</TableData>
330///             </TableRow>
331///             <TableRow>
332///                 <TableData>{ "Five" }</TableData>
333///                 <TableData>{ "Six" }</TableData>
334///             </TableRow>
335///             <TableRow>
336///                 <TableData>{ "Seven" }</TableData>
337///                 <TableData>{ "Eight" }</TableData>
338///             </TableRow>
339///         </Table>
340///     }
341/// }
342/// ```
343///
344/// [bd]: https://bulma.io/documentation/elements/table/
345#[derive(Clone, PartialEq)]
346pub enum TableItem {
347    TableHeader(VChild<TableHeader>),
348    TableFooter(VChild<TableFooter>),
349    TableRow(VChild<TableRow>),
350    TableData(VChild<TableData>),
351}
352
353impl TableItem {
354    /// Determines if the table item is a [`crate::elements::table::TableHeader`].
355    pub fn is_header(&self) -> bool {
356        matches!(self, TableItem::TableHeader(_))
357    }
358
359    /// Determines if the table item is a [`crate::elements::table::TableFooter`].
360    pub fn is_footer(&self) -> bool {
361        matches!(self, TableItem::TableFooter(_))
362    }
363
364    /// Determines if the table item is a [`crate::elements::table::TableRow`].
365    pub fn is_row(&self) -> bool {
366        matches!(self, TableItem::TableRow(_))
367    }
368
369    /// Determines if the table item is a [`crate::elements::table::TableData`].
370    pub fn is_data(&self) -> bool {
371        matches!(self, TableItem::TableData(_))
372    }
373}
374
375impl From<VChild<TableHeader>> for TableItem {
376    fn from(value: VChild<TableHeader>) -> Self {
377        TableItem::TableHeader(value)
378    }
379}
380
381impl From<VChild<TableFooter>> for TableItem {
382    fn from(value: VChild<TableFooter>) -> Self {
383        TableItem::TableFooter(value)
384    }
385}
386
387impl From<VChild<TableRow>> for TableItem {
388    fn from(value: VChild<TableRow>) -> Self {
389        TableItem::TableRow(value)
390    }
391}
392
393impl From<VChild<TableData>> for TableItem {
394    fn from(value: VChild<TableData>) -> Self {
395        TableItem::TableData(value)
396    }
397}
398
399#[allow(clippy::from_over_into)]
400impl Into<Html> for TableItem {
401    fn into(self) -> Html {
402        match self {
403            TableItem::TableHeader(th) => th.into(),
404            TableItem::TableFooter(tf) => tf.into(),
405            TableItem::TableRow(tr) => tr.into(),
406            TableItem::TableData(td) => td.into(),
407        }
408    }
409}
410
411/// Yew implementation of the [Bulma table element][bd].
412///
413/// Yew implementation of the table element, based on the specification found
414/// in the [Bulma table element documentation][bd].
415///
416/// # Examples
417///
418/// ```rust
419/// use yew::prelude::*;
420/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
421///
422/// #[function_component(App)]
423/// fn app() -> Html {
424///     html! {
425///         <Table>
426///             <TableHeader>{"One"}</TableHeader>
427///             <TableHeader>{"Two"}</TableHeader>
428///
429///             <TableRow>
430///                 <TableData>{ "Three" }</TableData>
431///                 <TableData>{ "Four" }</TableData>
432///             </TableRow>
433///             <TableRow>
434///                 <TableData>{ "Five" }</TableData>
435///                 <TableData>{ "Six" }</TableData>
436///             </TableRow>
437///             <TableRow>
438///                 <TableData>{ "Seven" }</TableData>
439///                 <TableData>{ "Eight" }</TableData>
440///             </TableRow>
441///         </Table>
442///     }
443/// }
444/// ```
445///
446/// [bd]: https://bulma.io/documentation/elements/table/
447#[function_component(Table)]
448pub fn table(props: &TableProperties) -> Html {
449    let class = ClassBuilder::default()
450        .with_custom_class(&String::from(props))
451        .with_custom_class(
452            &props
453                .class
454                .as_ref()
455                .map(|c| c.to_string())
456                .unwrap_or("".to_owned()),
457        )
458        .build();
459    let headers: Vec<_> = props.children.iter().filter(|ti| ti.is_header()).collect();
460    let footers: Vec<_> = props.children.iter().filter(|ti| ti.is_footer()).collect();
461    let data: Vec<_> = props
462        .children
463        .iter()
464        .filter(|ti| ti.is_row() || ti.is_data())
465        .collect();
466
467    let table_html = html! {
468        <table id={props.id.clone()} {class}
469            onclick={props.onclick.clone()} onwheel={props.onwheel.clone()} onscroll={props.onscroll.clone()}
470            onmousedown={props.onmousedown.clone()} onmousemove={props.onmousemove.clone()} onmouseout={props.onmouseout.clone()} onmouseover={props.onmouseover.clone()} onmouseup={props.onmouseup.clone()}
471            ondrag={props.ondrag.clone()} ondragend={props.ondragend.clone()} ondragenter={props.ondragenter.clone()} ondragleave={props.ondragleave.clone()} ondragover={props.ondragover.clone()} ondragstart={props.ondragstart.clone()} ondrop={props.ondrop.clone()}
472            oncopy={props.oncopy.clone()} oncut={props.oncut.clone()} onpaste={props.onpaste.clone()}
473            onkeydown={props.onkeydown.clone()} onkeypress={props.onkeypress.clone()} onkeyup={props.onkeyup.clone()}
474            onblur={props.onblur.clone()} onchange={props.onchange.clone()} oncontextmenu={props.oncontextmenu.clone()} onfocus={props.onfocus.clone()} oninput={props.oninput.clone()} oninvalid={props.oninvalid.clone()} onreset={props.onreset.clone()} onselect={props.onselect.clone()} onsubmit={props.onsubmit.clone()}
475            onabort={props.onabort.clone()} oncanplay={props.oncanplay.clone()} oncanplaythrough={props.oncanplaythrough.clone()} oncuechange={props.oncuechange.clone()}
476            ondurationchange={props.ondurationchange.clone()} onemptied={props.onemptied.clone()} onended={props.onended.clone()} onerror={props.onerror.clone()}
477            onloadeddata={props.onloadeddata.clone()} onloadedmetadata={props.onloadedmetadata.clone()} onloadstart={props.onloadstart.clone()} onpause={props.onpause.clone()}
478            onplay={props.onplay.clone()} onplaying={props.onplaying.clone()} onprogress={props.onprogress.clone()} onratechange={props.onratechange.clone()}
479            onseeked={props.onseeked.clone()} onseeking={props.onseeking.clone()} onstalled={props.onstalled.clone()} onsuspend={props.onsuspend.clone()}
480            ontimeupdate={props.ontimeupdate.clone()} onvolumechange={props.onvolumechange.clone()} onwaiting={props.onwaiting.clone()}>
481            if !headers.is_empty() {
482                <thead>
483                    { for headers }
484                </thead>
485            }
486
487            if !footers.is_empty() {
488                <tfoot>
489                    { for footers }
490                </tfoot>
491            }
492
493            <tbody>
494                { for data }
495            </tbody>
496        </table>
497    };
498
499    if props.scrollable {
500        html! {
501            <div class="table-container">
502                {table_html}
503            </div>
504        }
505    } else {
506        table_html
507    }
508}
509
510/// Defines the properties of the [Bulma table header element][bd].
511///
512/// Defines the properties of the table header element, based on the
513/// specification found in the [Bulma table element documentation][bd].
514///
515/// # Examples
516///
517/// ```rust
518/// use yew::prelude::*;
519/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
520///
521/// #[function_component(App)]
522/// fn app() -> Html {
523///     html! {
524///         <Table>
525///             <TableHeader>{"One"}</TableHeader>
526///             <TableHeader>{"Two"}</TableHeader>
527///
528///             <TableRow>
529///                 <TableData>{ "Three" }</TableData>
530///                 <TableData>{ "Four" }</TableData>
531///             </TableRow>
532///             <TableRow>
533///                 <TableData>{ "Five" }</TableData>
534///                 <TableData>{ "Six" }</TableData>
535///             </TableRow>
536///             <TableRow>
537///                 <TableData>{ "Seven" }</TableData>
538///                 <TableData>{ "Eight" }</TableData>
539///             </TableRow>
540///         </Table>
541///     }
542/// }
543/// ```
544///
545/// [bd]: https://bulma.io/documentation/elements/table/
546#[base_component_properties]
547#[derive(Properties, PartialEq)]
548pub struct TableHeaderProperties {
549    /// Sets the abbreviation of [Bulma table header element][bd].
550    ///
551    /// Sets the abbreviation of the [Bulma table header element][bd] which will
552    /// receive these properties.
553    ///
554    /// # Examples
555    ///
556    /// ```rust
557    /// use yew::prelude::*;
558    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
559    ///
560    /// #[function_component(App)]
561    /// fn app() -> Html {
562    ///     html! {
563    ///         <Table>
564    ///             <TableHeader abbreviation={"1"}>{"One"}</TableHeader>
565    ///             <TableHeader abbreviation={"1"}>{"Two"}</TableHeader>
566    ///
567    ///             <TableRow>
568    ///                 <TableData>{ "Three" }</TableData>
569    ///                 <TableData>{ "Four" }</TableData>
570    ///             </TableRow>
571    ///             <TableRow>
572    ///                 <TableData>{ "Five" }</TableData>
573    ///                 <TableData>{ "Six" }</TableData>
574    ///             </TableRow>
575    ///             <TableRow>
576    ///                 <TableData>{ "Seven" }</TableData>
577    ///                 <TableData>{ "Eight" }</TableData>
578    ///             </TableRow>
579    ///         </Table>
580    ///     }
581    /// }
582    /// ```
583    ///
584    /// [bd]: https://bulma.io/documentation/elements/table/
585    #[prop_or_default]
586    pub abbreviation: Option<AttrValue>,
587    /// The list of elements found inside the [table header element][bd].
588    ///
589    /// Defines the elements that will be found inside the
590    /// [Bulma table header element][bd] which will receive these properties.
591    ///
592    /// [bd]: https://bulma.io/documentation/elements/table/
593    pub children: Children,
594}
595
596/// Yew implementation of the [Bulma table header element][bd].
597///
598/// Yew implementation of the table header element, based on the specification
599/// found in the [Bulma table element documentation][bd].
600///
601/// # Examples
602///
603/// ```rust
604/// use yew::prelude::*;
605/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
606///
607/// #[function_component(App)]
608/// fn app() -> Html {
609///     html! {
610///         <Table>
611///             <TableHeader>{"One"}</TableHeader>
612///             <TableHeader>{"Two"}</TableHeader>
613///
614///             <TableRow>
615///                 <TableData>{ "Three" }</TableData>
616///                 <TableData>{ "Four" }</TableData>
617///             </TableRow>
618///             <TableRow>
619///                 <TableData>{ "Five" }</TableData>
620///                 <TableData>{ "Six" }</TableData>
621///             </TableRow>
622///             <TableRow>
623///                 <TableData>{ "Seven" }</TableData>
624///                 <TableData>{ "Eight" }</TableData>
625///             </TableRow>
626///         </Table>
627///     }
628/// }
629/// ```
630///
631/// [bd]: https://bulma.io/documentation/elements/table/
632#[function_component(TableHeader)]
633pub fn table_header(props: &TableHeaderProperties) -> Html {
634    let class = ClassBuilder::default()
635        .with_custom_class(
636            &props
637                .class
638                .as_ref()
639                .map(|c| c.to_string())
640                .unwrap_or("".to_owned()),
641        )
642        .build();
643    let abbr = &props.abbreviation;
644
645    html! {
646        <th id={props.id.clone()} {class}
647            onclick={props.onclick.clone()} onwheel={props.onwheel.clone()} onscroll={props.onscroll.clone()}
648            onmousedown={props.onmousedown.clone()} onmousemove={props.onmousemove.clone()} onmouseout={props.onmouseout.clone()} onmouseover={props.onmouseover.clone()} onmouseup={props.onmouseup.clone()}
649            ondrag={props.ondrag.clone()} ondragend={props.ondragend.clone()} ondragenter={props.ondragenter.clone()} ondragleave={props.ondragleave.clone()} ondragover={props.ondragover.clone()} ondragstart={props.ondragstart.clone()} ondrop={props.ondrop.clone()}
650            oncopy={props.oncopy.clone()} oncut={props.oncut.clone()} onpaste={props.onpaste.clone()}
651            onkeydown={props.onkeydown.clone()} onkeypress={props.onkeypress.clone()} onkeyup={props.onkeyup.clone()}
652            onblur={props.onblur.clone()} onchange={props.onchange.clone()} oncontextmenu={props.oncontextmenu.clone()} onfocus={props.onfocus.clone()} oninput={props.oninput.clone()} oninvalid={props.oninvalid.clone()} onreset={props.onreset.clone()} onselect={props.onselect.clone()} onsubmit={props.onsubmit.clone()}
653            onabort={props.onabort.clone()} oncanplay={props.oncanplay.clone()} oncanplaythrough={props.oncanplaythrough.clone()} oncuechange={props.oncuechange.clone()}
654            ondurationchange={props.ondurationchange.clone()} onemptied={props.onemptied.clone()} onended={props.onended.clone()} onerror={props.onerror.clone()}
655            onloadeddata={props.onloadeddata.clone()} onloadedmetadata={props.onloadedmetadata.clone()} onloadstart={props.onloadstart.clone()} onpause={props.onpause.clone()}
656            onplay={props.onplay.clone()} onplaying={props.onplaying.clone()} onprogress={props.onprogress.clone()} onratechange={props.onratechange.clone()}
657            onseeked={props.onseeked.clone()} onseeking={props.onseeking.clone()} onstalled={props.onstalled.clone()} onsuspend={props.onsuspend.clone()}
658            ontimeupdate={props.ontimeupdate.clone()} onvolumechange={props.onvolumechange.clone()} onwaiting={props.onwaiting.clone()}>
659            if let Some(abbr) = &abbr {
660                <abbr {abbr}>{ for props.children.iter() }</abbr>
661            } else {
662                { for props.children.iter() }
663            }
664        </th>
665    }
666}
667
668/// Yew implementation of the [Bulma table footer element][bd].
669///
670/// Yew implementation of the table footer element, based on the specification
671/// found in the [Bulma table element documentation][bd]. Has the same
672/// properties as [`crate::elements::table::TableHeader`].
673///
674/// # Examples
675///
676/// ```rust
677/// use yew::prelude::*;
678/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
679///
680/// #[function_component(App)]
681/// fn app() -> Html {
682///     html! {
683///         <Table>
684///             <TableHeader>{"One"}</TableHeader>
685///             <TableHeader>{"Two"}</TableHeader>
686///
687///             <TableRow>
688///                 <TableData>{ "Three" }</TableData>
689///                 <TableData>{ "Four" }</TableData>
690///             </TableRow>
691///             <TableRow>
692///                 <TableData>{ "Five" }</TableData>
693///                 <TableData>{ "Six" }</TableData>
694///             </TableRow>
695///             <TableRow>
696///                 <TableData>{ "Seven" }</TableData>
697///                 <TableData>{ "Eight" }</TableData>
698///             </TableRow>
699///         </Table>
700///     }
701/// }
702/// ```
703///
704/// [bd]: https://bulma.io/documentation/elements/table/
705#[function_component(TableFooter)]
706pub fn table_footer(props: &TableHeaderProperties) -> Html {
707    let class = ClassBuilder::default()
708        .with_custom_class(
709            &props
710                .class
711                .as_ref()
712                .map(|c| c.to_string())
713                .unwrap_or("".to_owned()),
714        )
715        .build();
716    let abbr = &props.abbreviation;
717
718    html! {
719        <th id={props.id.clone()} {class}
720            onclick={props.onclick.clone()} onwheel={props.onwheel.clone()} onscroll={props.onscroll.clone()}
721            onmousedown={props.onmousedown.clone()} onmousemove={props.onmousemove.clone()} onmouseout={props.onmouseout.clone()} onmouseover={props.onmouseover.clone()} onmouseup={props.onmouseup.clone()}
722            ondrag={props.ondrag.clone()} ondragend={props.ondragend.clone()} ondragenter={props.ondragenter.clone()} ondragleave={props.ondragleave.clone()} ondragover={props.ondragover.clone()} ondragstart={props.ondragstart.clone()} ondrop={props.ondrop.clone()}
723            oncopy={props.oncopy.clone()} oncut={props.oncut.clone()} onpaste={props.onpaste.clone()}
724            onkeydown={props.onkeydown.clone()} onkeypress={props.onkeypress.clone()} onkeyup={props.onkeyup.clone()}
725            onblur={props.onblur.clone()} onchange={props.onchange.clone()} oncontextmenu={props.oncontextmenu.clone()} onfocus={props.onfocus.clone()} oninput={props.oninput.clone()} oninvalid={props.oninvalid.clone()} onreset={props.onreset.clone()} onselect={props.onselect.clone()} onsubmit={props.onsubmit.clone()}
726            onabort={props.onabort.clone()} oncanplay={props.oncanplay.clone()} oncanplaythrough={props.oncanplaythrough.clone()} oncuechange={props.oncuechange.clone()}
727            ondurationchange={props.ondurationchange.clone()} onemptied={props.onemptied.clone()} onended={props.onended.clone()} onerror={props.onerror.clone()}
728            onloadeddata={props.onloadeddata.clone()} onloadedmetadata={props.onloadedmetadata.clone()} onloadstart={props.onloadstart.clone()} onpause={props.onpause.clone()}
729            onplay={props.onplay.clone()} onplaying={props.onplaying.clone()} onprogress={props.onprogress.clone()} onratechange={props.onratechange.clone()}
730            onseeked={props.onseeked.clone()} onseeking={props.onseeking.clone()} onstalled={props.onstalled.clone()} onsuspend={props.onsuspend.clone()}
731            ontimeupdate={props.ontimeupdate.clone()} onvolumechange={props.onvolumechange.clone()} onwaiting={props.onwaiting.clone()}>
732            if let Some(abbr) = &abbr {
733                <abbr {abbr}>{ for props.children.iter() }</abbr>
734            } else {
735                { for props.children.iter() }
736            }
737        </th>
738    }
739}
740
741/// Defines the properties of the [Bulma table row element][bd].
742///
743/// Defines the properties of the table row element, based on the
744/// specification found in the [Bulma table element documentation][bd].
745///
746/// # Examples
747///
748/// ```rust
749/// use yew::prelude::*;
750/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
751///
752/// #[function_component(App)]
753/// fn app() -> Html {
754///     html! {
755///         <Table>
756///             <TableHeader>{"One"}</TableHeader>
757///             <TableHeader>{"Two"}</TableHeader>
758///
759///             <TableRow>
760///                 <TableData>{ "Three" }</TableData>
761///                 <TableData>{ "Four" }</TableData>
762///             </TableRow>
763///             <TableRow>
764///                 <TableData>{ "Five" }</TableData>
765///                 <TableData>{ "Six" }</TableData>
766///             </TableRow>
767///             <TableRow>
768///                 <TableData>{ "Seven" }</TableData>
769///                 <TableData>{ "Eight" }</TableData>
770///             </TableRow>
771///         </Table>
772///     }
773/// }
774/// ```
775///
776/// [bd]: https://bulma.io/documentation/elements/table/
777#[base_component_properties]
778#[derive(Properties, PartialEq)]
779pub struct TableRowProperties {
780    /// Whether or not the [Bulma table row element][bd] should be selected.
781    ///
782    /// Whether or not the [Bulma table row element][bd], which will receive these
783    /// properties, will be selected.
784    ///
785    /// # Examples
786    ///
787    /// ```rust
788    /// use yew::prelude::*;
789    /// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
790    ///
791    /// #[function_component(App)]
792    /// fn app() -> Html {
793    ///     html! {
794    ///         <Table>
795    ///             <TableHeader>{"One"}</TableHeader>
796    ///             <TableHeader>{"Two"}</TableHeader>
797    ///
798    ///             <TableRow>
799    ///                 <TableData>{ "Three" }</TableData>
800    ///                 <TableData>{ "Four" }</TableData>
801    ///             </TableRow>
802    ///             <TableRow selected=true>
803    ///                 <TableData>{ "Five" }</TableData>
804    ///                 <TableData>{ "Six" }</TableData>
805    ///             </TableRow>
806    ///             <TableRow>
807    ///                 <TableData>{ "Seven" }</TableData>
808    ///                 <TableData>{ "Eight" }</TableData>
809    ///             </TableRow>
810    ///         </Table>
811    ///     }
812    /// }
813    /// ```
814    ///
815    /// [bd]: https://bulma.io/documentation/elements/table/
816    #[prop_or_default]
817    pub selected: bool,
818    /// The list of elements found inside the [table row element][bd].
819    ///
820    /// Defines the elements that will be found inside the
821    /// [Bulma table row element][bd] which will receive these properties.
822    ///
823    /// [bd]: https://bulma.io/documentation/elements/table/
824    pub children: Children,
825}
826
827impl From<&TableRowProperties> for String {
828    fn from(value: &TableRowProperties) -> Self {
829        if value.selected {
830            "is-selected".to_owned()
831        } else {
832            String::new()
833        }
834    }
835}
836
837/// Yew implementation of the [Bulma table row element][bd].
838///
839/// Yew implementation of the table row element, based on the specification
840/// found in the [Bulma table element documentation][bd].
841///
842/// # Examples
843///
844/// ```rust
845/// use yew::prelude::*;
846/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
847///
848/// #[function_component(App)]
849/// fn app() -> Html {
850///     html! {
851///         <Table>
852///             <TableHeader>{"One"}</TableHeader>
853///             <TableHeader>{"Two"}</TableHeader>
854///
855///             <TableRow>
856///                 <TableData>{ "Three" }</TableData>
857///                 <TableData>{ "Four" }</TableData>
858///             </TableRow>
859///             <TableRow>
860///                 <TableData>{ "Five" }</TableData>
861///                 <TableData>{ "Six" }</TableData>
862///             </TableRow>
863///             <TableRow>
864///                 <TableData>{ "Seven" }</TableData>
865///                 <TableData>{ "Eight" }</TableData>
866///             </TableRow>
867///         </Table>
868///     }
869/// }
870/// ```
871///
872/// [bd]: https://bulma.io/documentation/elements/table/
873#[function_component(TableRow)]
874pub fn table_row(props: &TableRowProperties) -> Html {
875    let class = ClassBuilder::default()
876        .with_custom_class(&String::from(props))
877        .with_custom_class(
878            &props
879                .class
880                .as_ref()
881                .map(|c| c.to_string())
882                .unwrap_or("".to_owned()),
883        )
884        .build();
885
886    html! {
887        <tr id={props.id.clone()} {class}
888            onclick={props.onclick.clone()} onwheel={props.onwheel.clone()} onscroll={props.onscroll.clone()}
889            onmousedown={props.onmousedown.clone()} onmousemove={props.onmousemove.clone()} onmouseout={props.onmouseout.clone()} onmouseover={props.onmouseover.clone()} onmouseup={props.onmouseup.clone()}
890            ondrag={props.ondrag.clone()} ondragend={props.ondragend.clone()} ondragenter={props.ondragenter.clone()} ondragleave={props.ondragleave.clone()} ondragover={props.ondragover.clone()} ondragstart={props.ondragstart.clone()} ondrop={props.ondrop.clone()}
891            oncopy={props.oncopy.clone()} oncut={props.oncut.clone()} onpaste={props.onpaste.clone()}
892            onkeydown={props.onkeydown.clone()} onkeypress={props.onkeypress.clone()} onkeyup={props.onkeyup.clone()}
893            onblur={props.onblur.clone()} onchange={props.onchange.clone()} oncontextmenu={props.oncontextmenu.clone()} onfocus={props.onfocus.clone()} oninput={props.oninput.clone()} oninvalid={props.oninvalid.clone()} onreset={props.onreset.clone()} onselect={props.onselect.clone()} onsubmit={props.onsubmit.clone()}
894            onabort={props.onabort.clone()} oncanplay={props.oncanplay.clone()} oncanplaythrough={props.oncanplaythrough.clone()} oncuechange={props.oncuechange.clone()}
895            ondurationchange={props.ondurationchange.clone()} onemptied={props.onemptied.clone()} onended={props.onended.clone()} onerror={props.onerror.clone()}
896            onloadeddata={props.onloadeddata.clone()} onloadedmetadata={props.onloadedmetadata.clone()} onloadstart={props.onloadstart.clone()} onpause={props.onpause.clone()}
897            onplay={props.onplay.clone()} onplaying={props.onplaying.clone()} onprogress={props.onprogress.clone()} onratechange={props.onratechange.clone()}
898            onseeked={props.onseeked.clone()} onseeking={props.onseeking.clone()} onstalled={props.onstalled.clone()} onsuspend={props.onsuspend.clone()}
899            ontimeupdate={props.ontimeupdate.clone()} onvolumechange={props.onvolumechange.clone()} onwaiting={props.onwaiting.clone()}>
900            { for props.children.iter() }
901        </tr>
902    }
903}
904
905/// Defines the properties of the [Bulma table data element][bd].
906///
907/// Defines the properties of the table data element, based on the
908/// specification found in the [Bulma table element documentation][bd].
909///
910/// # Examples
911///
912/// ```rust
913/// use yew::prelude::*;
914/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
915///
916/// #[function_component(App)]
917/// fn app() -> Html {
918///     html! {
919///         <Table>
920///             <TableHeader>{"One"}</TableHeader>
921///             <TableHeader>{"Two"}</TableHeader>
922///
923///             <TableRow>
924///                 <TableData>{ "Three" }</TableData>
925///                 <TableData>{ "Four" }</TableData>
926///             </TableRow>
927///             <TableRow>
928///                 <TableData>{ "Five" }</TableData>
929///                 <TableData>{ "Six" }</TableData>
930///             </TableRow>
931///             <TableRow>
932///                 <TableData>{ "Seven" }</TableData>
933///                 <TableData>{ "Eight" }</TableData>
934///             </TableRow>
935///         </Table>
936///     }
937/// }
938/// ```
939///
940/// [bd]: https://bulma.io/documentation/elements/table/
941#[base_component_properties]
942#[derive(Properties, PartialEq)]
943pub struct TableDataProperties {
944    /// The list of elements found inside the [table data element][bd].
945    ///
946    /// Defines the elements that will be found inside the
947    /// [Bulma table data element][bd] which will receive these properties.
948    ///
949    /// [bd]: https://bulma.io/documentation/elements/table/
950    pub children: Children,
951}
952
953/// Yew implementation of the [Bulma table data element][bd].
954///
955/// Yew implementation of the table data element, based on the specification
956/// found in the [Bulma table element documentation][bd].
957///
958/// # Examples
959///
960/// ```rust
961/// use yew::prelude::*;
962/// use yew_and_bulma::elements::table::{Table, TableHeader, TableRow, TableData};
963///
964/// #[function_component(App)]
965/// fn app() -> Html {
966///     html! {
967///         <Table>
968///             <TableHeader>{"One"}</TableHeader>
969///             <TableHeader>{"Two"}</TableHeader>
970///
971///             <TableRow>
972///                 <TableData>{ "Three" }</TableData>
973///                 <TableData>{ "Four" }</TableData>
974///             </TableRow>
975///             <TableRow>
976///                 <TableData>{ "Five" }</TableData>
977///                 <TableData>{ "Six" }</TableData>
978///             </TableRow>
979///             <TableRow>
980///                 <TableData>{ "Seven" }</TableData>
981///                 <TableData>{ "Eight" }</TableData>
982///             </TableRow>
983///         </Table>
984///     }
985/// }
986/// ```
987///
988/// [bd]: https://bulma.io/documentation/elements/table/
989#[function_component(TableData)]
990pub fn table_data(props: &TableDataProperties) -> Html {
991    let class = ClassBuilder::default()
992        .with_custom_class(
993            &props
994                .class
995                .as_ref()
996                .map(|c| c.to_string())
997                .unwrap_or("".to_owned()),
998        )
999        .build();
1000
1001    html! {
1002        <td id={props.id.clone()} {class}
1003            onclick={props.onclick.clone()} onwheel={props.onwheel.clone()} onscroll={props.onscroll.clone()}
1004            onmousedown={props.onmousedown.clone()} onmousemove={props.onmousemove.clone()} onmouseout={props.onmouseout.clone()} onmouseover={props.onmouseover.clone()} onmouseup={props.onmouseup.clone()}
1005            ondrag={props.ondrag.clone()} ondragend={props.ondragend.clone()} ondragenter={props.ondragenter.clone()} ondragleave={props.ondragleave.clone()} ondragover={props.ondragover.clone()} ondragstart={props.ondragstart.clone()} ondrop={props.ondrop.clone()}
1006            oncopy={props.oncopy.clone()} oncut={props.oncut.clone()} onpaste={props.onpaste.clone()}
1007            onkeydown={props.onkeydown.clone()} onkeypress={props.onkeypress.clone()} onkeyup={props.onkeyup.clone()}
1008            onblur={props.onblur.clone()} onchange={props.onchange.clone()} oncontextmenu={props.oncontextmenu.clone()} onfocus={props.onfocus.clone()} oninput={props.oninput.clone()} oninvalid={props.oninvalid.clone()} onreset={props.onreset.clone()} onselect={props.onselect.clone()} onsubmit={props.onsubmit.clone()}
1009            onabort={props.onabort.clone()} oncanplay={props.oncanplay.clone()} oncanplaythrough={props.oncanplaythrough.clone()} oncuechange={props.oncuechange.clone()}
1010            ondurationchange={props.ondurationchange.clone()} onemptied={props.onemptied.clone()} onended={props.onended.clone()} onerror={props.onerror.clone()}
1011            onloadeddata={props.onloadeddata.clone()} onloadedmetadata={props.onloadedmetadata.clone()} onloadstart={props.onloadstart.clone()} onpause={props.onpause.clone()}
1012            onplay={props.onplay.clone()} onplaying={props.onplaying.clone()} onprogress={props.onprogress.clone()} onratechange={props.onratechange.clone()}
1013            onseeked={props.onseeked.clone()} onseeking={props.onseeking.clone()} onstalled={props.onstalled.clone()} onsuspend={props.onsuspend.clone()}
1014            ontimeupdate={props.ontimeupdate.clone()} onvolumechange={props.onvolumechange.clone()} onwaiting={props.onwaiting.clone()}>
1015            { for props.children.iter() }
1016        </td>
1017    }
1018}