checkbox.rs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. use std::collections::HashMap;
  2. use dioxus::prelude::*;
  3. use dioxus_elements::input_data::keyboard_types::Key;
  4. use dioxus_html as dioxus_elements;
  5. use dioxus_html::FormData;
  6. #[derive(Props)]
  7. pub(crate) struct CheckBoxProps<'a> {
  8. #[props(!optional)]
  9. raw_oninput: Option<&'a EventHandler<'a, FormData>>,
  10. #[props(!optional)]
  11. value: Option<&'a str>,
  12. #[props(!optional)]
  13. width: Option<&'a str>,
  14. #[props(!optional)]
  15. height: Option<&'a str>,
  16. #[props(!optional)]
  17. checked: Option<&'a str>,
  18. }
  19. #[allow(non_snake_case)]
  20. pub(crate) fn CheckBox<'a>(cx: Scope<'a, CheckBoxProps>) -> Element<'a> {
  21. let state = use_state(cx, || cx.props.checked.filter(|&c| c == "true").is_some());
  22. let width = cx.props.width.unwrap_or("1px");
  23. let height = cx.props.height.unwrap_or("1px");
  24. let single_char = width == "1px" && height == "1px";
  25. let text = if single_char {
  26. if *state.get() {
  27. "☑"
  28. } else {
  29. "☐"
  30. }
  31. } else if *state.get() {
  32. "✓"
  33. } else {
  34. " "
  35. };
  36. let border_style = if width == "1px" || height == "1px" {
  37. "none"
  38. } else {
  39. "solid"
  40. };
  41. let update = move || {
  42. let new_state = !state.get();
  43. if let Some(callback) = cx.props.raw_oninput {
  44. callback.call(FormData {
  45. value: if let Some(value) = &cx.props.value {
  46. if new_state {
  47. value.to_string()
  48. } else {
  49. String::new()
  50. }
  51. } else {
  52. "on".to_string()
  53. },
  54. values: HashMap::new(),
  55. files: None,
  56. });
  57. }
  58. state.set(new_state);
  59. };
  60. cx.render(rsx! {
  61. div {
  62. width: "{width}",
  63. height: "{height}",
  64. border_style: "{border_style}",
  65. align_items: "center",
  66. justify_content: "center",
  67. onclick: move |_| {
  68. update();
  69. },
  70. onkeydown: move |evt| {
  71. if !evt.is_auto_repeating() && match evt.key(){ Key::Character(c) if c == " " =>true, Key::Enter=>true, _=>false } {
  72. update();
  73. }
  74. },
  75. "{text}"
  76. }
  77. })
  78. }