1use floem_renderer::text::{LineHeightValue, Weight};
132use imbl::hashmap::Entry;
133use peniko::color::palette;
134use peniko::kurbo::{self, Affine, RoundedRect, Vec2};
135use peniko::{Brush, Color};
136use smallvec::SmallVec;
137use std::any::Any;
138use std::collections::HashMap;
139use std::fmt::{self, Debug};
140use std::rc::Rc;
141use taffy::GridTemplateComponent;
142
143pub use taffy::style::{
144 AlignContent, AlignItems, BoxSizing, Dimension, Display, FlexDirection, FlexWrap,
145 JustifyContent, JustifyItems, Position,
146};
147use taffy::{
148 geometry::{MinMax, Size},
149 prelude::{GridPlacement, Line, Rect},
150 style::{
151 LengthPercentage, MaxTrackSizingFunction, MinTrackSizingFunction, Overflow,
152 Style as TaffyStyle,
153 },
154};
155
156use crate::layout::responsive::{ScreenSize, ScreenSizeBp};
157
158use crate::{prop, prop_extractor};
160
161mod cache;
162mod components;
163mod custom;
164mod cx;
165mod props;
166pub mod recalc;
167mod selectors;
168#[cfg(test)]
169mod tests;
170pub mod theme;
171mod transition;
172pub mod unit;
173mod values;
174
175pub use components::{
176 Border, BorderColor, BorderRadius, BoxShadow, CursorStyle, Margin, Padding, PointerEvents,
177 TextOverflow,
178};
179pub use custom::{CustomStylable, CustomStyle};
180pub use cx::{InheritedInteractionCx, InteractionState, StyleCx};
181pub use props::{
182 ExtractorField, StyleClass, StyleClassInfo, StyleClassRef, StyleKey, StyleKeyInfo, StyleProp,
183 StylePropInfo, StylePropReader, StylePropRef,
184};
185pub use selectors::{StyleSelector, StyleSelectors};
186pub use theme::{DesignSystem, StyleThemeExt};
187pub use transition::{DirectTransition, Transition, TransitionState};
188pub use unit::{AnchorAbout, Angle, Auto, DurationUnitExt, Pct, Px, PxPct, PxPctAuto, UnitExt};
189pub use values::{CombineResult, StrokeWrap, StyleMapValue, StylePropValue, StyleValue};
190
191pub use cache::{StyleCache, StyleCacheKey};
192pub use recalc::{InheritedChanges, InheritedGroups, Propagate, RecalcFlags, StyleRecalcChange};
193
194pub(crate) use props::{CONTEXT_MAPPINGS_INFO, ImHashMap, style_key_selector};
195
196type ContextMapFn = Rc<dyn Fn(Style, &Style) -> Style>;
198
199#[derive(Clone)]
205pub(crate) struct ContextMappings(pub Rc<Vec<ContextMapFn>>);
206
207style_key_selector!(selector_xs, StyleSelectors::new().responsive());
208style_key_selector!(selector_sm, StyleSelectors::new().responsive());
209style_key_selector!(selector_md, StyleSelectors::new().responsive());
210style_key_selector!(selector_lg, StyleSelectors::new().responsive());
211style_key_selector!(selector_xl, StyleSelectors::new().responsive());
212style_key_selector!(selector_xxl, StyleSelectors::new().responsive());
213
214pub(crate) fn screen_size_bp_to_key(breakpoint: ScreenSizeBp) -> StyleKey {
215 match breakpoint {
216 ScreenSizeBp::Xs => selector_xs(),
217 ScreenSizeBp::Sm => selector_sm(),
218 ScreenSizeBp::Md => selector_md(),
219 ScreenSizeBp::Lg => selector_lg(),
220 ScreenSizeBp::Xl => selector_xl(),
221 ScreenSizeBp::Xxl => selector_xxl(),
222 }
223}
224
225pub fn resolve_nested_maps(
227 style: Style,
228 interact_state: &InteractionState,
229 screen_size_bp: ScreenSizeBp,
230 classes: &[StyleClassRef],
231 inherited_context: &Style,
232 class_context: &Style,
233) -> (Style, bool) {
234 let mut classes_applied = false;
235
236 let (class_style, mut class_context_mappings) = resolve_classes_collecting_mappings(
238 classes,
239 interact_state,
240 screen_size_bp,
241 class_context,
242 &mut classes_applied,
243 );
244
245 let (view_style, mut view_context_mappings) =
247 resolve_style_collecting_mappings(style, interact_state, screen_size_bp);
248
249 let mut context_result = class_style.clone();
252 let mut i = 0;
253 while i < class_context_mappings.len() {
254 let mapping = class_context_mappings[i].clone();
255 let combined_context = inherited_context
256 .clone()
257 .apply(view_style.clone())
258 .apply(context_result.clone());
259 let mapped = mapping(context_result.clone(), &combined_context);
260 let (resolved, new_mappings) =
261 resolve_selectors_collecting_mappings(mapped, interact_state, screen_size_bp);
262 context_result.apply_mut_no_mappings(resolved);
263 class_context_mappings.splice(i + 1..i + 1, new_mappings);
264 i += 1;
265 }
266
267 let mut result = context_result.apply(view_style);
269
270 let mut i = 0;
272 while i < view_context_mappings.len() {
273 let mapping = view_context_mappings[i].clone();
274 let combined_context = inherited_context.clone().apply(result.clone());
275 let mapped = mapping(result.clone(), &combined_context);
276 let (resolved, new_mappings) =
277 resolve_selectors_collecting_mappings(mapped, interact_state, screen_size_bp);
278 result.apply_mut_no_mappings(resolved);
279 view_context_mappings.splice(i + 1..i + 1, new_mappings);
280 i += 1;
281 }
282
283 (result, classes_applied)
284}
285
286fn resolve_classes_collecting_mappings(
287 classes: &[StyleClassRef],
288 interact_state: &InteractionState,
289 screen_size_bp: ScreenSizeBp,
290 class_context: &Style,
291 classes_applied: &mut bool,
292) -> (Style, Vec<ContextMapFn>) {
293 let mut result = Style::new();
294 let mut mappings = Vec::new();
295
296 for class in classes {
297 if let Some(map) = class_context.get_nested_map(class.key) {
298 *classes_applied = true;
299 let (resolved, class_mappings) =
300 resolve_style_collecting_mappings(map.clone(), interact_state, screen_size_bp);
301 result.apply_mut(resolved);
302 mappings.extend(class_mappings);
303 }
304 }
305
306 (result, mappings)
307}
308
309fn resolve_style_collecting_mappings(
310 style: Style,
311 interact_state: &InteractionState,
312 screen_size_bp: ScreenSizeBp,
313) -> (Style, Vec<ContextMapFn>) {
314 let mut mappings = Vec::new();
315
316 if let Some(style_mappings) = extract_context_mappings(&style) {
318 mappings.extend(style_mappings);
319 }
320
321 let (resolved, selector_mappings) =
323 resolve_selectors_collecting_mappings(style, interact_state, screen_size_bp);
324 mappings.extend(selector_mappings);
325
326 (resolved, mappings)
327}
328
329fn resolve_selectors_collecting_mappings(
330 mut style: Style,
331 interact_state: &InteractionState,
332 screen_size_bp: ScreenSizeBp,
333) -> (Style, Vec<ContextMapFn>) {
334 const MAX_DEPTH: u32 = 20;
335 let mut depth = 0;
336 let mut all_mappings = Vec::new();
337
338 loop {
339 if depth >= MAX_DEPTH {
340 break;
341 }
342 depth += 1;
343
344 let mut changed = false;
345
346 let mut apply_nested = |style: &mut Style, key: StyleKey| -> bool {
348 if let Some(map) = style.get_nested_map(key) {
349 if let Some(mappings) = extract_context_mappings(&map) {
351 all_mappings.extend(mappings);
352 }
353 style.apply_mut_no_mappings(map);
354 style.remove_nested_map(key);
355 true
356 } else {
357 false
358 }
359 };
360
361 if apply_nested(&mut style, screen_size_bp_to_key(screen_size_bp)) {
363 changed = true;
364 }
365
366 if interact_state.is_dark_mode && apply_nested(&mut style, StyleSelector::DarkMode.to_key())
368 {
369 changed = true;
370 }
371
372 if interact_state.is_disabled || style.get(Disabled) {
374 if apply_nested(&mut style, StyleSelector::Disabled.to_key()) {
375 changed = true;
376 }
377 } else {
378 if (interact_state.is_selected || style.get(Selected))
380 && apply_nested(&mut style, StyleSelector::Selected.to_key())
381 {
382 changed = true;
383 }
384
385 if interact_state.is_hovered && apply_nested(&mut style, StyleSelector::Hover.to_key())
387 {
388 changed = true;
389 }
390
391 if interact_state.is_file_hover
393 && apply_nested(&mut style, StyleSelector::FileHover.to_key())
394 {
395 changed = true;
396 }
397
398 if interact_state.is_focused {
400 if apply_nested(&mut style, StyleSelector::Focus.to_key()) {
401 changed = true;
402 }
403
404 if interact_state.using_keyboard_navigation {
405 if apply_nested(&mut style, StyleSelector::FocusVisible.to_key()) {
406 changed = true;
407 }
408
409 if interact_state.is_clicking
410 && apply_nested(&mut style, StyleSelector::Active.to_key())
411 {
412 changed = true;
413 }
414 }
415 }
416
417 if interact_state.is_clicking
419 && !interact_state.using_keyboard_navigation
420 && apply_nested(&mut style, StyleSelector::Active.to_key())
421 {
422 changed = true;
423 }
424 }
425
426 if !changed {
427 break;
428 }
429 }
430
431 (style, all_mappings)
432}
433
434fn extract_context_mappings(style: &Style) -> Option<Vec<ContextMapFn>> {
435 let key = StyleKey {
436 info: &CONTEXT_MAPPINGS_INFO,
437 };
438 style.map.get(&key).map(|rc| {
439 let mappings = rc.downcast_ref::<ContextMappings>().unwrap();
440 mappings.0.iter().cloned().collect()
441 })
442}
443
444#[derive(Default, Clone)]
445pub struct Style {
446 pub(crate) map: ImHashMap<StyleKey, Rc<dyn Any>>,
447 has_class_maps: bool,
451 has_inherited: bool,
455}
456
457impl Style {
458 pub fn new() -> Self {
459 Self::default()
460 }
461
462 pub fn apply_only_inherited(to: &mut Rc<Style>, from: &Style) {
469 if from.any_inherited() {
470 let mut new_style = (**to).clone();
471 let inherited = from.map.iter().filter(|(p, _)| p.inherited());
473 new_style.apply_iter(inherited);
474 *to = Rc::new(new_style);
475 }
476 }
477
478 pub fn apply_inherited_and_class_maps(to: &mut Rc<Style>, from: &Style) {
484 let has_inherited = from.any_inherited();
485 let has_class_maps = from.has_class_maps;
487
488 if has_inherited || has_class_maps {
489 let mut new_style = (**to).clone();
490
491 if has_inherited {
493 let inherited = from.map.iter().filter(|(p, _)| p.inherited());
494 new_style.apply_iter(inherited);
495 }
496
497 if has_class_maps {
499 let class_maps = from
500 .map
501 .iter()
502 .filter(|(k, _)| matches!(k.info, StyleKeyInfo::Class(..)));
503 new_style.apply_iter(class_maps);
504 }
505
506 *to = Rc::new(new_style);
507 }
508 }
509
510 pub fn apply_only_class_maps(to: &mut Rc<Style>, from: &Style) {
515 if !from.has_class_maps {
517 return;
518 }
519 let mut new_style = (**to).clone();
520 let class_maps = from
521 .map
522 .iter()
523 .filter(|(k, _)| matches!(k.info, StyleKeyInfo::Class(..)));
524 new_style.apply_iter(class_maps);
525 *to = Rc::new(new_style);
526 }
527
528 pub(crate) fn get_transition<P: StyleProp>(&self) -> Option<Transition> {
529 self.map
530 .get(&P::prop_ref().info().transition_key)
531 .map(|v| v.downcast_ref::<Transition>().unwrap().clone())
532 }
533
534 pub(crate) fn get_prop_or_default<P: StyleProp>(&self) -> P::Type {
535 self.get_prop::<P>().unwrap_or_else(|| P::default_value())
536 }
537
538 pub(crate) fn get_prop<P: StyleProp>(&self) -> Option<P::Type> {
539 self.map.get(&P::key()).and_then(|v| {
540 v.downcast_ref::<StyleMapValue<P::Type>>()
541 .unwrap()
542 .as_ref()
543 .cloned()
544 })
545 }
546
547 pub(crate) fn get_prop_style_value<P: StyleProp>(&self) -> StyleValue<P::Type> {
548 self.map
549 .get(&P::key())
550 .map(
551 |v| match v.downcast_ref::<StyleMapValue<P::Type>>().unwrap() {
552 StyleMapValue::Val(v) => StyleValue::Val(v.clone()),
553 StyleMapValue::Animated(v) => StyleValue::Animated(v.clone()),
554 StyleMapValue::Unset => StyleValue::Unset,
555 },
556 )
557 .unwrap_or(StyleValue::Base)
558 }
559
560 pub(crate) fn style_props(&self) -> impl Iterator<Item = StylePropRef> + '_ {
561 self.map.keys().filter_map(|p| match p.info {
562 StyleKeyInfo::Prop(..) => Some(StylePropRef { key: *p }),
563 _ => None,
564 })
565 }
566
567 pub(crate) fn selectors(&self) -> StyleSelectors {
568 let mut result = StyleSelectors::new();
569
570 for (k, v) in &self.map {
572 if let StyleKeyInfo::Selector(selector) = k.info {
573 result = result
574 .union(*selector)
575 .union(v.downcast_ref::<Style>().unwrap().selectors());
576 }
577 }
578 result
579 }
580
581 pub fn apply_classes_from_context(
596 self,
597 classes: &[StyleClassRef],
598 class_context: &std::rc::Rc<Style>,
599 ) -> (Style, bool) {
600 if classes.is_empty() || !class_context.has_class_maps {
602 return (self, false);
603 }
604
605 let has_matching_classes = classes
607 .iter()
608 .any(|class| class_context.get_nested_map(class.key).is_some());
609 if !has_matching_classes {
610 return (self, false);
611 }
612
613 let mut changed = false;
614
615 let context_mappings_key = StyleKey {
616 info: &CONTEXT_MAPPINGS_INFO,
617 };
618
619 let view_style = self;
630 let view_ctx_mappings = view_style.map.get(&context_mappings_key).cloned();
631
632 let mut result = Style::new();
634 let mut all_class_mappings: Vec<ContextMapFn> = Vec::new();
635
636 for class in classes {
637 if let Some(map) = class_context.get_nested_map(class.key) {
638 let mut class_style = map.clone();
639 if let Some(class_mappings_rc) = class_style.map.remove(&context_mappings_key) {
641 let class_mappings =
642 class_mappings_rc.downcast_ref::<ContextMappings>().unwrap();
643 all_class_mappings.extend(class_mappings.0.iter().cloned());
644 }
645 result.apply_mut(class_style);
647 changed = true;
648 }
649 }
650
651 result.apply_mut(view_style.clone());
654
655 if !all_class_mappings.is_empty() {
658 let view_selector_keys: Vec<_> = view_style
663 .map
664 .keys()
665 .filter(|k| matches!(k.info, StyleKeyInfo::Selector(..)))
666 .cloned()
667 .collect();
668
669 if !view_selector_keys.is_empty() {
670 let view_selectors: HashMap<StyleKey, Rc<dyn Any>> = view_selector_keys
671 .iter()
672 .filter_map(|k| view_style.map.get(k).map(|v| (*k, v.clone())))
673 .collect();
674
675 let restore_selectors: ContextMapFn = Rc::new(move |mut s: Style, _ctx: &Style| {
677 for (k, v) in view_selectors.iter() {
678 s.apply_iter(std::iter::once((k, v)));
679 }
680 s
681 });
682 all_class_mappings.push(restore_selectors);
683 }
684
685 if let Some(view_mappings_rc) = view_ctx_mappings {
687 let view_mappings = view_mappings_rc.downcast_ref::<ContextMappings>().unwrap();
688 all_class_mappings.extend(view_mappings.0.iter().cloned());
689 }
690 result.map.insert(
691 context_mappings_key,
692 Rc::new(ContextMappings(Rc::new(all_class_mappings))),
693 );
694 } else if let Some(view_mappings_rc) = view_ctx_mappings {
695 result.map.insert(context_mappings_key, view_mappings_rc);
697 }
698
699 (result, changed)
700 }
701
702 pub fn apply_class<C: StyleClass>(mut self, _class: C) -> Style {
703 if let Some(map) = self.map.get(&C::key()) {
704 self.apply_mut(map.downcast_ref::<Style>().unwrap().clone());
705 }
706 self
707 }
708
709 pub fn apply_selectors(mut self, selectors: &[StyleSelector]) -> Style {
710 for selector in selectors {
711 if let Some(map) = self.get_nested_map(selector.to_key()) {
712 self.apply_mut(map.apply_selectors(selectors));
713 }
714 }
715 if self.get(Selected) {
716 if let Some(map) = self.get_nested_map(StyleSelector::Selected.to_key()) {
717 self.apply_mut(map.apply_selectors(&[StyleSelector::Selected]));
718 }
719 }
720 self
721 }
722
723 pub fn with_context<P: StyleProp>(self, f: impl Fn(Self, &P::Type) -> Self + 'static) -> Self {
731 let default_value = P::default_value();
734 let result = f(self.clone(), &default_value);
735
736 let mapper: ContextMapFn = Rc::new(move |style: Style, context: &Style| {
739 let value = style.get_prop::<P>().or_else(|| {
741 let prop_key = P::key();
742 if let StyleKeyInfo::Prop(_) = prop_key.info {
743 context.get_prop::<P>()
744 } else {
745 None
746 }
747 });
748
749 if let Some(value) = value {
750 f(style, &value)
751 } else {
752 f(style, &P::default_value())
753 }
754 });
755
756 let key = StyleKey {
758 info: &CONTEXT_MAPPINGS_INFO,
759 };
760
761 let mut mappings_vec = result
763 .map
764 .get(&key)
765 .and_then(|v| v.downcast_ref::<ContextMappings>())
766 .map(|cm| (*cm.0).clone())
767 .unwrap_or_default();
768 mappings_vec.push(mapper);
769
770 let mut final_result = result;
773 final_result
774 .map
775 .insert(key, Rc::new(ContextMappings(Rc::new(mappings_vec))));
776 final_result
777 }
778
779 pub fn with_context_opt<P: StyleProp<Type = Option<T>>, T: 'static + Default>(
784 self,
785 f: impl Fn(Self, T) -> Self + 'static,
786 ) -> Self {
787 let result = f(self.clone(), T::default());
789
790 let mapper: ContextMapFn = Rc::new(move |style: Style, context: &Style| {
792 let value = style.get_prop::<P>().or_else(|| {
793 let prop_key = P::key();
794 if let StyleKeyInfo::Prop(_) = prop_key.info {
795 context.get_prop::<P>()
796 } else {
797 None
798 }
799 });
800
801 match value {
802 Some(Some(value)) => f(style, value),
803 _ => style,
804 }
805 });
806
807 let key = StyleKey {
809 info: &CONTEXT_MAPPINGS_INFO,
810 };
811
812 let mut mappings_vec = result
814 .map
815 .get(&key)
816 .and_then(|v| v.downcast_ref::<ContextMappings>())
817 .map(|cm| (*cm.0).clone())
818 .unwrap_or_default();
819 mappings_vec.push(mapper);
820
821 let mut final_result = result;
822 final_result
823 .map
824 .insert(key, Rc::new(ContextMappings(Rc::new(mappings_vec))));
825 final_result
826 }
827
828 pub(crate) fn get_nested_map(&self, key: StyleKey) -> Option<Style> {
829 self.map
830 .get(&key)
831 .map(|map| map.downcast_ref::<Style>().unwrap().clone())
832 }
833
834 pub(crate) fn remove_nested_map(&mut self, key: StyleKey) -> Option<Style> {
835 self.map
836 .remove(&key)
837 .map(|map| map.downcast_ref::<Style>().unwrap().clone())
838 }
839
840 pub(crate) fn any_inherited(&self) -> bool {
844 self.has_inherited
845 }
846
847 pub(crate) fn inherited(&self) -> Style {
848 let mut new = Style::new();
849 if self.any_inherited() {
850 let inherited = self.map.iter().filter(|(p, _)| p.inherited());
851
852 new.apply_iter(inherited);
853 }
854 new
855 }
856
857 fn set_selector(&mut self, selector: StyleSelector, map: Style) {
858 self.set_map_selector(selector.to_key(), map)
859 }
860
861 fn set_map_selector(&mut self, key: StyleKey, map: Style) {
862 match self.map.entry(key) {
863 Entry::Occupied(mut e) => {
864 let mut current = e.get_mut().downcast_ref::<Style>().unwrap().clone();
865 current.apply_mut(map);
866 *e.get_mut() = Rc::new(current);
867 }
868 Entry::Vacant(e) => {
869 e.insert(Rc::new(map));
870 }
871 }
872 }
873
874 fn set_breakpoint(&mut self, breakpoint: ScreenSizeBp, map: Style) {
875 self.set_map_selector(screen_size_bp_to_key(breakpoint), map)
876 }
877
878 fn set_class(&mut self, class: StyleClassRef, map: Style) {
879 self.has_class_maps = true;
880 self.set_map_selector(class.key, map)
881 }
882
883 pub fn builtin(&self) -> BuiltinStyle<'_> {
884 BuiltinStyle { style: self }
885 }
886
887 pub(crate) fn apply_iter<'a>(
888 &mut self,
889 iter: impl Iterator<Item = (&'a StyleKey, &'a Rc<dyn Any>)>,
890 ) {
891 for (k, v) in iter {
892 match k.info {
893 StyleKeyInfo::Class(..) | StyleKeyInfo::Selector(..) => {
894 if matches!(k.info, StyleKeyInfo::Class(..)) {
896 self.has_class_maps = true;
897 }
898 match self.map.entry(*k) {
899 Entry::Occupied(mut e) => {
900 let v = v.downcast_ref::<Style>().unwrap();
903 match Rc::get_mut(e.get_mut()) {
904 Some(current) => {
905 current
906 .downcast_mut::<Style>()
907 .unwrap()
908 .apply_mut(v.clone());
909 }
910 None => {
911 let mut current =
912 e.get_mut().downcast_ref::<Style>().unwrap().clone();
913 current.apply_mut(v.clone());
914 *e.get_mut() = Rc::new(current);
915 }
916 }
917 }
918 Entry::Vacant(e) => {
919 e.insert(v.clone());
920 }
921 }
922 }
923 StyleKeyInfo::ContextMappings => match self.map.entry(*k) {
924 Entry::Occupied(mut e) => {
925 let new_ctx = v.downcast_ref::<ContextMappings>().unwrap();
927 let current = e.get().downcast_ref::<ContextMappings>().unwrap();
928 let mut merged: Vec<_> = (*current.0).clone();
930 merged.extend(new_ctx.0.iter().cloned());
931 *e.get_mut() = Rc::new(ContextMappings(Rc::new(merged)));
932 }
933 Entry::Vacant(e) => {
934 e.insert(v.clone());
935 }
936 },
937 StyleKeyInfo::Transition => {
938 self.map.insert(*k, v.clone());
939 }
940 StyleKeyInfo::Prop(info) => {
941 if info.inherited {
943 self.has_inherited = true;
944 }
945 match self.map.entry(*k) {
946 Entry::Occupied(mut e) => {
947 e.insert((info.combine)(e.get().clone(), v.clone()));
949 }
950 Entry::Vacant(e) => {
951 e.insert(v.clone());
952 }
953 }
954 }
955 }
956 }
957 }
958
959 pub(crate) fn apply_iter_no_mappings<'a>(
960 &mut self,
961 iter: impl Iterator<Item = (&'a StyleKey, &'a Rc<dyn Any>)>,
962 ) {
963 for (k, v) in iter {
964 match k.info {
965 StyleKeyInfo::Class(..) | StyleKeyInfo::Selector(..) => {
966 if matches!(k.info, StyleKeyInfo::Class(..)) {
968 self.has_class_maps = true;
969 }
970 match self.map.entry(*k) {
971 Entry::Occupied(mut e) => {
972 let v = v.downcast_ref::<Style>().unwrap();
975 match Rc::get_mut(e.get_mut()) {
976 Some(current) => {
977 current
978 .downcast_mut::<Style>()
979 .unwrap()
980 .apply_mut(v.clone());
981 }
982 None => {
983 let mut current =
984 e.get_mut().downcast_ref::<Style>().unwrap().clone();
985 current.apply_mut(v.clone());
986 *e.get_mut() = Rc::new(current);
987 }
988 }
989 }
990 Entry::Vacant(e) => {
991 e.insert(v.clone());
992 }
993 }
994 }
995 StyleKeyInfo::Transition => {
996 self.map.insert(*k, v.clone());
997 }
998 StyleKeyInfo::Prop(info) => {
999 if info.inherited {
1001 self.has_inherited = true;
1002 }
1003 match self.map.entry(*k) {
1004 Entry::Occupied(mut e) => {
1005 e.insert((info.combine)(e.get().clone(), v.clone()));
1007 }
1008 Entry::Vacant(e) => {
1009 e.insert(v.clone());
1010 }
1011 }
1012 }
1013 _ => {}
1014 }
1015 }
1016 }
1017
1018 pub(crate) fn apply_mut(&mut self, over: Style) {
1019 self.apply_iter(over.map.iter());
1020 }
1021
1022 pub(crate) fn apply_mut_no_mappings(&mut self, over: Style) {
1023 self.apply_iter_no_mappings(over.map.iter());
1024 }
1025
1026 pub fn apply(mut self, over: Style) -> Style {
1033 self.apply_mut(over);
1034 self
1035 }
1036
1037 pub fn map(self, over: impl FnOnce(Self) -> Self) -> Self {
1038 over(self)
1039 }
1040
1041 pub fn apply_overriding_styles(self, overrides: impl Iterator<Item = Style>) -> Style {
1044 overrides.fold(self, |acc, x| acc.apply(x))
1045 }
1046
1047 }
1080
1081impl Debug for Style {
1082 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1083 f.debug_struct("Style")
1084 .field(
1085 "map",
1086 &self
1087 .map
1088 .iter()
1089 .map(|(p, v)| (*p, (p.debug_any(&**v))))
1090 .collect::<HashMap<StyleKey, String>>(),
1091 )
1092 .finish()
1093 }
1094}
1095
1096style_key_selector!(hover, StyleSelectors::new().set(StyleSelector::Hover, true));
1097style_key_selector!(
1098 file_hover,
1099 StyleSelectors::new().set(StyleSelector::FileHover, true)
1100);
1101style_key_selector!(focus, StyleSelectors::new().set(StyleSelector::Focus, true));
1102style_key_selector!(
1103 focus_visible,
1104 StyleSelectors::new().set(StyleSelector::FocusVisible, true)
1105);
1106style_key_selector!(
1107 disabled,
1108 StyleSelectors::new().set(StyleSelector::Disabled, true)
1109);
1110style_key_selector!(
1111 active,
1112 StyleSelectors::new().set(StyleSelector::Active, true)
1113);
1114style_key_selector!(
1115 dragging,
1116 StyleSelectors::new().set(StyleSelector::Dragging, true)
1117);
1118style_key_selector!(
1119 selected,
1120 StyleSelectors::new().set(StyleSelector::Selected, true)
1121);
1122style_key_selector!(
1123 darkmode,
1124 StyleSelectors::new().set(StyleSelector::DarkMode, true)
1125);
1126
1127impl StyleSelector {
1128 fn to_key(self) -> StyleKey {
1129 match self {
1130 StyleSelector::Hover => hover(),
1131 StyleSelector::Focus => focus(),
1132 StyleSelector::FocusVisible => focus_visible(),
1133 StyleSelector::Disabled => disabled(),
1134 StyleSelector::Active => active(),
1135 StyleSelector::Dragging => dragging(),
1136 StyleSelector::Selected => selected(),
1137 StyleSelector::DarkMode => darkmode(),
1138 StyleSelector::FileHover => file_hover(),
1139 }
1140 }
1141}
1142
1143macro_rules! define_builtin_props {
1155 (
1156 $(
1157 $(#[$meta:meta])*
1158 $type_name:ident $name:ident $({ $($flags:ident),* })? :
1159 $typ:ty { $($options:tt)* } = $val:expr
1160 ),*
1161 $(,)?
1162 ) => {
1163 $(
1164 prop!($(#[$meta])* pub $type_name: $typ { $($options)* } = $val);
1165 )*
1166 impl Style {
1167 $(
1168 define_builtin_props!(decl: $(#[$meta])* $type_name $name $({ $($flags),* })?: $typ = $val);
1169 )*
1170 $(
1171 define_builtin_props!(unset: $(#[$meta])* $type_name $name);
1172 )*
1173 $(
1174 define_builtin_props!(transition: $(#[$meta])* $type_name $name $({ $($flags),* })?);
1175 )*
1176 }
1177 impl BuiltinStyle<'_> {
1178 $(
1179 $(#[$meta])*
1180 pub fn $name(&self) -> $typ {
1181 self.style.get($type_name)
1182 }
1183 )*
1184 }
1185 };
1186
1187 (decl: $(#[$meta:meta])* $type_name:ident $name:ident { $($flags:ident),* }: $typ:ty = $val:expr) => {
1189 define_builtin_props!(@check_nocb $(#[$meta])* $type_name $name [$($flags)*]: $typ);
1190 };
1191
1192 (decl: $(#[$meta:meta])* $type_name:ident $name:ident: $typ:ty = $val:expr) => {
1194 $(#[$meta])*
1195 pub fn $name(self, v: impl Into<$typ>) -> Self {
1196 self.set($type_name, v.into())
1197 }
1198 };
1199
1200 (@check_nocb $(#[$meta:meta])* $type_name:ident $name:ident [nocb $($rest:ident)*]: $typ:ty) => {};
1202 (@check_nocb $(#[$meta:meta])* $type_name:ident $name:ident [$first:ident $($rest:ident)*]: $typ:ty) => {
1203 define_builtin_props!(@check_nocb $(#[$meta])* $type_name $name [$($rest)*]: $typ);
1204 };
1205 (@check_nocb $(#[$meta:meta])* $type_name:ident $name:ident []: $typ:ty) => {
1206 $(#[$meta])*
1208 pub fn $name(self, v: impl Into<$typ>) -> Self {
1209 self.set($type_name, v.into())
1210 }
1211 };
1212
1213 (unset: $(#[$meta:meta])* $type_name:ident $name:ident) => {
1215 paste::paste! {
1216 #[doc = "Unsets the `" $name "` property."]
1217 pub fn [<unset_ $name>](self) -> Self {
1218 self.set_style_value($type_name, $crate::style::StyleValue::Unset)
1219 }
1220 }
1221 };
1222
1223 (transition: $(#[$meta:meta])* $type_name:ident $name:ident { $($flags:ident),* }) => {
1225 define_builtin_props!(@check_tr $(#[$meta])* $type_name $name [$($flags)*]);
1226 };
1227
1228 (transition: $(#[$meta:meta])* $type_name:ident $name:ident) => {};
1230
1231 (@check_tr $(#[$meta:meta])* $type_name:ident $name:ident [tr $($rest:ident)*]) => {
1233 paste::paste! {
1234 #[doc = "Sets a transition for the `" $name "` property."]
1235 $(#[$meta])*
1236 pub fn [<transition_ $name>](self, transition: impl Into<Transition>) -> Self {
1237 self.transition($type_name, transition.into())
1238 }
1239 }
1240 };
1241 (@check_tr $(#[$meta:meta])* $type_name:ident $name:ident [$first:ident $($rest:ident)*]) => {
1242 define_builtin_props!(@check_tr $(#[$meta])* $type_name $name [$($rest)*]);
1243 };
1244 (@check_tr $(#[$meta:meta])* $type_name:ident $name:ident []) => {
1245 };
1247}
1248
1249pub struct BuiltinStyle<'a> {
1250 style: &'a Style,
1251}
1252
1253define_builtin_props!(
1254 DisplayProp display {}: Display {} = Display::Flex,
1258
1259 PositionProp position {}: Position {} = Position::Relative,
1263
1264 IsFixed is_fixed {}: bool {} = false,
1274
1275 Width width {tr}: PxPctAuto {} = PxPctAuto::Auto,
1279
1280 Height height {tr}: PxPctAuto {} = PxPctAuto::Auto,
1284
1285 MinWidth min_width {tr}: PxPctAuto {} = PxPctAuto::Auto,
1289
1290 MinHeight min_height {tr}: PxPctAuto {} = PxPctAuto::Auto,
1294
1295 MaxWidth max_width {tr}: PxPctAuto {} = PxPctAuto::Auto,
1299
1300 MaxHeight max_height {tr}: PxPctAuto {} = PxPctAuto::Auto,
1304
1305 FlexDirectionProp flex_direction {}: FlexDirection {} = FlexDirection::Row,
1309
1310 FlexWrapProp flex_wrap {}: FlexWrap {} = FlexWrap::NoWrap,
1314
1315 FlexGrow flex_grow {}: f32 {} = 0.0,
1319
1320 FlexShrink flex_shrink {}: f32 {} = 1.0,
1324
1325 FlexBasis flex_basis {tr}: PxPctAuto {} = PxPctAuto::Auto,
1329
1330 JustifyContentProp justify_content {}: Option<JustifyContent> {} = None,
1334
1335 JustifyItemsProp justify_items {}: Option<JustifyItems> {} = None,
1339
1340 BoxSizingProp box_sizing {}: Option<BoxSizing> {} = None,
1344
1345 JustifySelf justify_self {}: Option<AlignItems> {} = None,
1349
1350 AlignItemsProp align_items {}: Option<AlignItems> {} = None,
1354
1355 AlignContentProp align_content {}: Option<AlignContent> {} = None,
1359
1360 GridTemplateRows grid_template_rows {}: Vec<GridTemplateComponent<String>> {} = Vec::new(),
1364
1365 GridTemplateColumns grid_template_columns {}: Vec<GridTemplateComponent<String>> {} = Vec::new(),
1369
1370 GridAutoRows grid_auto_rows {}: Vec<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>> {} = Vec::new(),
1374
1375 GridAutoColumns grid_auto_columns {}: Vec<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>> {} = Vec::new(),
1379
1380 GridAutoFlow grid_auto_flow {}: taffy::GridAutoFlow {} = taffy::GridAutoFlow::Row,
1384
1385 GridRow grid_row {}: Line<GridPlacement> {} = Line::default(),
1389
1390 GridColumn grid_column {}: Line<GridPlacement> {} = Line::default(),
1394
1395 AlignSelf align_self {}: Option<AlignItems> {} = None,
1399
1400 OutlineColor outline_color {tr}: Brush {} = Brush::Solid(palette::css::TRANSPARENT),
1404
1405 Outline outline {nocb, tr}: StrokeWrap {} = StrokeWrap::new(0.),
1409
1410 OutlineProgress outline_progress {tr}: Pct {} = Pct(100.),
1414
1415 BorderProgress border_progress {tr}: Pct {} = Pct(100.),
1419
1420 BorderProp border_combined {nocb, tr}: Border {} = Border::default(),
1424
1425 BorderColorProp border_color_combined { nocb, tr }: BorderColor {} = BorderColor::default(),
1429
1430 BorderRadiusProp border_radius_combined { nocb, tr }: BorderRadius {} = BorderRadius::default(),
1434
1435 PaddingProp padding_combined { nocb, tr }: Padding {} = Padding::default(),
1439
1440 MarginProp margin_combined { nocb, tr }: Margin {} = Margin::default(),
1444
1445 InsetLeft inset_left {tr}: PxPctAuto {} = PxPctAuto::Auto,
1447
1448 InsetTop inset_top {tr}: PxPctAuto {} = PxPctAuto::Auto,
1450
1451 InsetRight inset_right {tr}: PxPctAuto {} = PxPctAuto::Auto,
1453
1454 InsetBottom inset_bottom {tr}: PxPctAuto {} = PxPctAuto::Auto,
1456
1457 PointerEventsProp pointer_events {}: Option<PointerEvents> { inherited } = None,
1461
1462 ZIndex z_index { nocb, tr }: Option<i32> {} = None,
1466
1467 Cursor cursor { nocb }: Option<CursorStyle> {} = None,
1471
1472 TextColor color { nocb, tr }: Option<Color> { inherited } = None,
1476
1477 Background background { nocb, tr }: Option<Brush> {} = None,
1481
1482 Foreground foreground { nocb, tr }: Option<Brush> {} = None,
1486
1487 BoxShadowProp box_shadow { nocb, tr }: SmallVec<[BoxShadow; 3]> {} = SmallVec::new(),
1491
1492 FontSize font_size { nocb, tr }: Option<f32> { inherited } = None,
1496
1497 FontFamily font_family { nocb }: Option<String> { inherited } = None,
1501
1502 FontWeight font_weight { nocb }: Option<Weight> { inherited } = None,
1506
1507 FontStyle font_style { nocb }: Option<crate::text::Style> { inherited } = None,
1511
1512 CursorColor cursor_color { nocb, tr }: Brush {} = Brush::Solid(palette::css::BLACK.with_alpha(0.3)),
1516
1517 SelectionCornerRadius selection_corer_radius { nocb, tr }: f64 {} = 1.,
1521
1522 Selectable selectable {}: bool { inherited } = true,
1526
1527 TextOverflowProp text_overflow {}: TextOverflow {} = TextOverflow::Wrap,
1531
1532 TextAlignProp text_align {}: Option<crate::text::Align> {} = None,
1536
1537 LineHeight line_height { nocb, tr }: Option<LineHeightValue> { inherited } = None,
1541
1542 AspectRatio aspect_ratio {tr}: Option<f32> {} = None,
1546
1547 ColGap col_gap { nocb, tr }: PxPct {} = PxPct::Px(0.),
1551
1552 RowGap row_gap { nocb, tr }: PxPct {} = PxPct::Px(0.),
1556
1557 ScaleX scale_x {tr}: Pct {} = Pct(100.),
1561
1562 ScaleY scale_y {tr}: Pct {} = Pct(100.),
1566
1567 TranslateX translate_x {tr}: PxPct {} = PxPct::Px(0.),
1571
1572 TranslateY translate_y {tr}: PxPct {} = PxPct::Px(0.),
1576
1577 Rotation rotate {tr}: Angle {} = Angle::Rad(0.0),
1582
1583 RotateAbout rotate_about {}: AnchorAbout {} = AnchorAbout::CENTER,
1588
1589 ScaleAbout scale_about {tr}: AnchorAbout {} = AnchorAbout::CENTER,
1594
1595 Opacity opacity {tr}: f32 {} = 1.0,
1600
1601 Selected set_selected {}: bool { inherited } = false,
1605
1606 Disabled set_disabled {}: bool { inherited } = false,
1610
1611 Focusable focusable {}: bool { } = false,
1615
1616 Draggable draggable {}: bool { } = false,
1620);
1621
1622impl BuiltinStyle<'_> {
1623 pub fn padding_left(&self) -> PxPct {
1625 self.style.get(PaddingProp).left.unwrap_or(PxPct::Px(0.0))
1626 }
1627 pub fn padding_top(&self) -> PxPct {
1628 self.style.get(PaddingProp).top.unwrap_or(PxPct::Px(0.0))
1629 }
1630 pub fn padding_right(&self) -> PxPct {
1631 self.style.get(PaddingProp).right.unwrap_or(PxPct::Px(0.0))
1632 }
1633 pub fn padding_bottom(&self) -> PxPct {
1634 self.style.get(PaddingProp).bottom.unwrap_or(PxPct::Px(0.0))
1635 }
1636
1637 pub fn margin_left(&self) -> PxPctAuto {
1639 self.style
1640 .get(MarginProp)
1641 .left
1642 .unwrap_or(PxPctAuto::Px(0.0))
1643 }
1644 pub fn margin_top(&self) -> PxPctAuto {
1645 self.style.get(MarginProp).top.unwrap_or(PxPctAuto::Px(0.0))
1646 }
1647 pub fn margin_right(&self) -> PxPctAuto {
1648 self.style
1649 .get(MarginProp)
1650 .right
1651 .unwrap_or(PxPctAuto::Px(0.0))
1652 }
1653 pub fn margin_bottom(&self) -> PxPctAuto {
1654 self.style
1655 .get(MarginProp)
1656 .bottom
1657 .unwrap_or(PxPctAuto::Px(0.0))
1658 }
1659}
1660
1661prop!(
1662 pub OverflowX: Overflow {} = Overflow::default()
1664);
1665
1666prop!(
1667 pub OverflowY: Overflow {} = Overflow::default()
1669);
1670
1671prop_extractor! {
1672 pub FontProps {
1673 pub size: FontSize,
1674 pub family: FontFamily,
1675 pub weight: FontWeight,
1676 pub style: FontStyle,
1677 }
1678}
1679
1680prop_extractor! {
1681 pub(crate) LayoutProps {
1682 pub border: BorderProp,
1683 pub padding: PaddingProp,
1684 pub margin: MarginProp,
1685
1686 pub width: Width,
1687 pub height: Height,
1688
1689 pub min_width: MinWidth,
1690 pub min_height: MinHeight,
1691
1692 pub max_width: MaxWidth,
1693 pub max_height: MaxHeight,
1694
1695 pub flex_grow: FlexGrow,
1696 pub flex_shrink: FlexShrink,
1697 pub flex_basis: FlexBasis ,
1698
1699 pub inset_left: InsetLeft,
1700 pub inset_top: InsetTop,
1701 pub inset_right: InsetRight,
1702 pub inset_bottom: InsetBottom,
1703
1704 pub row_gap: RowGap,
1705 pub col_gap: ColGap,
1706 }
1707}
1708
1709prop_extractor! {
1710 pub TransformProps {
1711 pub scale_x: ScaleX,
1712 pub scale_y: ScaleY,
1713
1714 pub translate_x: TranslateX,
1715 pub translate_y: TranslateY,
1716
1717 pub rotation: Rotation,
1718 pub rotate_about: RotateAbout,
1719 pub scale_about: ScaleAbout,
1720 }
1721}
1722impl TransformProps {
1723 pub fn affine(&self, size: kurbo::Size) -> Affine {
1724 let mut transform = Affine::IDENTITY;
1725
1726 let transform_x = match self.translate_x() {
1727 crate::unit::PxPct::Px(px) => px,
1728 crate::unit::PxPct::Pct(pct) => pct / 100.,
1729 };
1730 let transform_y = match self.translate_y() {
1731 crate::unit::PxPct::Px(px) => px,
1732 crate::unit::PxPct::Pct(pct) => pct / 100.,
1733 };
1734 transform *= Affine::translate(Vec2 {
1735 x: transform_x,
1736 y: transform_y,
1737 });
1738
1739 let scale_x = self.scale_x().0 / 100.;
1740 let scale_y = self.scale_y().0 / 100.;
1741 let rotation = self.rotation().to_radians();
1742
1743 let rotate_about = self.rotate_about();
1745 let scale_about = self.scale_about();
1746
1747 let (rotate_x_frac, rotate_y_frac) = rotate_about.as_fractions();
1749 let (scale_x_frac, scale_y_frac) = scale_about.as_fractions();
1750
1751 let rotate_point = Vec2 {
1752 x: rotate_x_frac * size.width,
1753 y: rotate_y_frac * size.height,
1754 };
1755
1756 let scale_point = Vec2 {
1757 x: scale_x_frac * size.width,
1758 y: scale_y_frac * size.height,
1759 };
1760
1761 if scale_x != 1.0 || scale_y != 1.0 {
1763 let scale_center = scale_point;
1765 transform = transform
1766 .then_translate(-scale_center)
1767 .then_scale_non_uniform(scale_x, scale_y)
1768 .then_translate(scale_center);
1769 }
1770 if rotation != 0.0 {
1771 let rotate_center = rotate_point;
1773 transform = transform
1774 .then_translate(-rotate_center)
1775 .then_rotate(rotation)
1776 .then_translate(rotate_center);
1777 }
1778
1779 transform
1780 }
1781}
1782
1783prop_extractor! {
1784 pub BoxTreeProps {
1785 pub scale_about: ScaleAbout,
1786 pub z_index: ZIndex,
1787 pub pointer_events: PointerEventsProp,
1788 pub focusable: Focusable,
1789 pub disabled: Disabled,
1790 pub display: DisplayProp,
1791 pub overflow_x: OverflowX,
1792 pub overflow_y: OverflowY,
1793 pub border_radius: BorderRadiusProp,
1794 }
1795}
1796impl BoxTreeProps {
1797 pub fn pickable(&self) -> bool {
1798 self.pointer_events() != Some(PointerEvents::None)
1799 }
1800
1801 pub fn clip_rect(&self, mut rect: kurbo::Rect) -> Option<RoundedRect> {
1822 use Overflow::*;
1823
1824 let (overflow_x, overflow_y) = (self.overflow_x(), self.overflow_y());
1825
1826 if overflow_x == Visible && overflow_y == Visible {
1828 return None;
1829 }
1830
1831 let border_radius = self
1832 .border_radius()
1833 .resolve_border_radii(rect.size().min_side());
1834
1835 if overflow_x == Visible {
1837 rect.x0 = f64::NEG_INFINITY;
1838 rect.x1 = f64::INFINITY;
1839 }
1840 if overflow_y == Visible {
1841 rect.y0 = f64::NEG_INFINITY;
1842 rect.y1 = f64::INFINITY;
1843 }
1844
1845 Some(RoundedRect::from_rect(rect, border_radius))
1846 }
1847}
1848
1849impl LayoutProps {
1850 pub fn to_style(&self) -> Style {
1851 let border = self.border();
1852 let padding = self.padding();
1853 let margin = self.margin();
1854 Style::new()
1855 .width(self.width())
1856 .height(self.height())
1857 .apply_border(border)
1858 .apply_padding(padding)
1859 .min_width(self.min_width())
1860 .min_height(self.min_height())
1861 .max_width(self.max_width())
1862 .max_height(self.max_height())
1863 .flex_grow(self.flex_grow())
1864 .flex_shrink(self.flex_shrink())
1865 .flex_basis(self.flex_basis())
1866 .inset_left(self.inset_left())
1867 .inset_top(self.inset_top())
1868 .inset_right(self.inset_right())
1869 .inset_bottom(self.inset_bottom())
1870 .apply_margin(margin)
1871 .col_gap(self.col_gap())
1872 .row_gap(self.row_gap())
1873 }
1874}
1875
1876prop_extractor! {
1877 pub SelectionStyle {
1878 pub corner_radius: SelectionCornerRadius,
1879 pub selection_color: CursorColor,
1880 }
1881}
1882
1883impl Style {
1884 pub fn get<P: StyleProp>(&self, _prop: P) -> P::Type {
1886 self.get_prop_or_default::<P>()
1887 }
1888
1889 pub fn get_style_value<P: StyleProp>(&self, _prop: P) -> StyleValue<P::Type> {
1891 self.get_prop_style_value::<P>()
1892 }
1893
1894 pub fn set<P: StyleProp>(self, prop: P, value: impl Into<P::Type>) -> Self {
1896 self.set_style_value(prop, StyleValue::Val(value.into()))
1897 }
1898
1899 pub fn set_style_value<P: StyleProp>(mut self, _prop: P, value: StyleValue<P::Type>) -> Self {
1900 let insert = match value {
1901 StyleValue::Val(value) => StyleMapValue::Val(value),
1902 StyleValue::Animated(value) => StyleMapValue::Animated(value),
1903 StyleValue::Unset => StyleMapValue::Unset,
1904 StyleValue::Base => {
1905 self.map.remove(&P::key());
1906 return self;
1907 }
1908 };
1909 if P::prop_ref().info().inherited {
1911 self.has_inherited = true;
1912 }
1913 self.map.insert(P::key(), Rc::new(insert));
1914 self
1915 }
1916
1917 pub fn transition<P: StyleProp>(mut self, _prop: P, transition: Transition) -> Self {
1919 self.map
1920 .insert(P::prop_ref().info().transition_key, Rc::new(transition));
1921 self
1922 }
1923
1924 fn selector(mut self, selector: StyleSelector, style: impl FnOnce(Style) -> Style) -> Self {
1925 let over = style(Style::default());
1926 self.set_selector(selector, over);
1927 self
1928 }
1929
1930 pub fn hover(self, style: impl FnOnce(Style) -> Style) -> Self {
1932 self.selector(StyleSelector::Hover, style)
1933 }
1934
1935 pub fn focus(self, style: impl FnOnce(Style) -> Style) -> Self {
1937 self.selector(StyleSelector::Focus, style)
1938 }
1939
1940 pub fn focus_visible(self, style: impl FnOnce(Style) -> Style) -> Self {
1942 self.selector(StyleSelector::FocusVisible, style)
1943 }
1944
1945 pub fn selected(self, style: impl FnOnce(Style) -> Style) -> Self {
1947 self.selector(StyleSelector::Selected, style)
1948 }
1949
1950 pub fn drag(self, style: impl FnOnce(Style) -> Style) -> Self {
1952 self.selector(StyleSelector::Dragging, style)
1953 }
1954
1955 pub fn disabled(self, style: impl FnOnce(Style) -> Style) -> Self {
1957 self.selector(StyleSelector::Disabled, style)
1958 }
1959
1960 pub fn dark_mode(self, style: impl FnOnce(Style) -> Style) -> Self {
1962 self.selector(StyleSelector::DarkMode, style)
1963 }
1964
1965 pub fn file_hover(self, style: impl FnOnce(Style) -> Style) -> Self {
1967 self.selector(StyleSelector::FileHover, style)
1968 }
1969
1970 pub fn active(self, style: impl FnOnce(Style) -> Style) -> Self {
1972 self.selector(StyleSelector::Active, style)
1973 }
1974
1975 pub fn responsive(mut self, size: ScreenSize, style: impl FnOnce(Style) -> Style) -> Self {
1977 let over = style(Style::default());
1978 for breakpoint in size.breakpoints() {
1979 self.set_breakpoint(breakpoint, over.clone());
1980 }
1981 self
1982 }
1983
1984 pub fn class<C: StyleClass>(mut self, _class: C, style: impl FnOnce(Style) -> Style) -> Self {
1986 let over = style(Style::default());
1987 self.set_class(C::class_ref(), over);
1988 self
1989 }
1990
1991 pub fn custom_style_class<CS: CustomStyle>(mut self, style: impl FnOnce(CS) -> CS) -> Self {
2010 let over = style(CS::default());
2011 self.set_class(CS::StyleClass::class_ref(), over.into());
2012 self
2013 }
2014
2015 pub fn width_full(self) -> Self {
2017 self.width_pct(100.0)
2018 }
2019
2020 pub fn width_pct(self, width: f64) -> Self {
2022 self.width(width.pct())
2023 }
2024
2025 pub fn height_full(self) -> Self {
2027 self.height_pct(100.0)
2028 }
2029
2030 pub fn height_pct(self, height: f64) -> Self {
2032 self.height(height.pct())
2033 }
2034
2035 pub fn col_gap(self, width: impl Into<PxPct>) -> Self {
2037 self.set(ColGap, width.into())
2038 }
2039
2040 pub fn row_gap(self, height: impl Into<PxPct>) -> Self {
2042 self.set(RowGap, height.into())
2043 }
2044
2045 pub fn row_col_gap(self, width: impl Into<PxPct>, height: impl Into<PxPct>) -> Self {
2047 self.col_gap(width).row_gap(height)
2048 }
2049
2050 pub fn gap(self, gap: impl Into<PxPct>) -> Self {
2052 let gap = gap.into();
2053 self.col_gap(gap).row_gap(gap)
2054 }
2055
2056 pub fn size(self, width: impl Into<PxPctAuto>, height: impl Into<PxPctAuto>) -> Self {
2058 self.width(width).height(height)
2059 }
2060
2061 pub fn size_full(self) -> Self {
2063 self.size_pct(100.0, 100.0)
2064 }
2065
2066 pub fn size_pct(self, width: f64, height: f64) -> Self {
2068 self.width(width.pct()).height(height.pct())
2069 }
2070
2071 pub fn min_width_full(self) -> Self {
2073 self.min_width_pct(100.0)
2074 }
2075
2076 pub fn min_width_pct(self, min_width: f64) -> Self {
2078 self.min_width(min_width.pct())
2079 }
2080
2081 pub fn min_height_full(self) -> Self {
2083 self.min_height_pct(100.0)
2084 }
2085
2086 pub fn min_height_pct(self, min_height: f64) -> Self {
2088 self.min_height(min_height.pct())
2089 }
2090
2091 pub fn min_size_full(self) -> Self {
2093 self.min_size_pct(100.0, 100.0)
2094 }
2095
2096 pub fn min_size(
2098 self,
2099 min_width: impl Into<PxPctAuto>,
2100 min_height: impl Into<PxPctAuto>,
2101 ) -> Self {
2102 self.min_width(min_width).min_height(min_height)
2103 }
2104
2105 pub fn min_size_pct(self, min_width: f64, min_height: f64) -> Self {
2107 self.min_size(min_width.pct(), min_height.pct())
2108 }
2109
2110 pub fn max_width_full(self) -> Self {
2112 self.max_width_pct(100.0)
2113 }
2114
2115 pub fn max_width_pct(self, max_width: f64) -> Self {
2117 self.max_width(max_width.pct())
2118 }
2119
2120 pub fn max_height_full(self) -> Self {
2122 self.max_height_pct(100.0)
2123 }
2124
2125 pub fn max_height_pct(self, max_height: f64) -> Self {
2127 self.max_height(max_height.pct())
2128 }
2129
2130 pub fn max_size(
2132 self,
2133 max_width: impl Into<PxPctAuto>,
2134 max_height: impl Into<PxPctAuto>,
2135 ) -> Self {
2136 self.max_width(max_width).max_height(max_height)
2137 }
2138
2139 pub fn max_size_full(self) -> Self {
2141 self.max_size_pct(100.0, 100.0)
2142 }
2143
2144 pub fn max_size_pct(self, max_width: f64, max_height: f64) -> Self {
2146 self.max_size(max_width.pct(), max_height.pct())
2147 }
2148
2149 pub fn border_color(self, color: impl Into<Brush>) -> Self {
2151 self.set(BorderColorProp, BorderColor::all(color))
2152 }
2153
2154 pub fn border(self, border: impl Into<StrokeWrap>) -> Self {
2156 self.set(BorderProp, Border::all(border))
2157 }
2158
2159 pub fn outline(self, outline: impl Into<StrokeWrap>) -> Self {
2161 self.set_style_value(Outline, StyleValue::Val(outline.into()))
2162 }
2163
2164 pub fn border_horiz(self, border: impl Into<StrokeWrap>) -> Self {
2166 let mut current = self.get(BorderProp);
2167 let border = border.into();
2168 current.left = Some(border.clone());
2169 current.right = Some(border);
2170 self.set(BorderProp, current)
2171 }
2172
2173 pub fn border_vert(self, border: impl Into<StrokeWrap>) -> Self {
2175 let mut current = self.get(BorderProp);
2176 let border = border.into();
2177 current.top = Some(border.clone());
2178 current.bottom = Some(border);
2179 self.set(BorderProp, current)
2180 }
2181
2182 pub fn padding_left_pct(self, padding: f64) -> Self {
2184 self.padding_left(padding.pct())
2185 }
2186
2187 pub fn padding_right_pct(self, padding: f64) -> Self {
2189 self.padding_right(padding.pct())
2190 }
2191
2192 pub fn padding_top_pct(self, padding: f64) -> Self {
2194 self.padding_top(padding.pct())
2195 }
2196
2197 pub fn padding_bottom_pct(self, padding: f64) -> Self {
2199 self.padding_bottom(padding.pct())
2200 }
2201
2202 pub fn padding(self, padding: impl Into<PxPct>) -> Self {
2204 self.set(PaddingProp, Padding::all(padding))
2205 }
2206
2207 pub fn padding_pct(self, padding: f64) -> Self {
2209 self.set(PaddingProp, Padding::all(padding.pct()))
2210 }
2211
2212 pub fn padding_horiz(self, padding: impl Into<PxPct>) -> Self {
2214 let mut current = self.get(PaddingProp);
2215 let padding = padding.into();
2216 current.left = Some(padding);
2217 current.right = Some(padding);
2218 self.set(PaddingProp, current)
2219 }
2220
2221 pub fn padding_horiz_pct(self, padding: f64) -> Self {
2223 self.padding_horiz(padding.pct())
2224 }
2225
2226 pub fn padding_vert(self, padding: impl Into<PxPct>) -> Self {
2228 let mut current = self.get(PaddingProp);
2229 let padding = padding.into();
2230 current.top = Some(padding);
2231 current.bottom = Some(padding);
2232 self.set(PaddingProp, current)
2233 }
2234
2235 pub fn padding_vert_pct(self, padding: f64) -> Self {
2237 self.padding_vert(padding.pct())
2238 }
2239
2240 pub fn margin_left_pct(self, margin: f64) -> Self {
2242 self.margin_left(margin.pct())
2243 }
2244
2245 pub fn margin_right_pct(self, margin: f64) -> Self {
2247 self.margin_right(margin.pct())
2248 }
2249
2250 pub fn margin_top_pct(self, margin: f64) -> Self {
2252 self.margin_top(margin.pct())
2253 }
2254
2255 pub fn margin_bottom_pct(self, margin: f64) -> Self {
2257 self.margin_bottom(margin.pct())
2258 }
2259
2260 pub fn margin(self, margin: impl Into<PxPctAuto>) -> Self {
2262 self.set(MarginProp, Margin::all(margin))
2263 }
2264
2265 pub fn margin_pct(self, margin: f64) -> Self {
2267 self.set(MarginProp, Margin::all(margin.pct()))
2268 }
2269
2270 pub fn margin_horiz(self, margin: impl Into<PxPctAuto>) -> Self {
2272 let mut current = self.get(MarginProp);
2273 let margin = margin.into();
2274 current.left = Some(margin);
2275 current.right = Some(margin);
2276 self.set(MarginProp, current)
2277 }
2278
2279 pub fn margin_horiz_pct(self, margin: f64) -> Self {
2281 self.margin_horiz(margin.pct())
2282 }
2283
2284 pub fn margin_vert(self, margin: impl Into<PxPctAuto>) -> Self {
2286 let mut current = self.get(MarginProp);
2287 let margin = margin.into();
2288 current.top = Some(margin);
2289 current.bottom = Some(margin);
2290 self.set(MarginProp, current)
2291 }
2292
2293 pub fn margin_vert_pct(self, margin: f64) -> Self {
2295 self.margin_vert(margin.pct())
2296 }
2297
2298 pub fn padding_left(self, padding: impl Into<PxPct>) -> Self {
2300 let mut current = self.get(PaddingProp);
2301 current.left = Some(padding.into());
2302 self.set(PaddingProp, current)
2303 }
2304 pub fn padding_right(self, padding: impl Into<PxPct>) -> Self {
2306 let mut current = self.get(PaddingProp);
2307 current.right = Some(padding.into());
2308 self.set(PaddingProp, current)
2309 }
2310 pub fn padding_top(self, padding: impl Into<PxPct>) -> Self {
2312 let mut current = self.get(PaddingProp);
2313 current.top = Some(padding.into());
2314 self.set(PaddingProp, current)
2315 }
2316 pub fn padding_bottom(self, padding: impl Into<PxPct>) -> Self {
2318 let mut current = self.get(PaddingProp);
2319 current.bottom = Some(padding.into());
2320 self.set(PaddingProp, current)
2321 }
2322
2323 pub fn margin_left(self, margin: impl Into<PxPctAuto>) -> Self {
2325 let mut current = self.get(MarginProp);
2326 current.left = Some(margin.into());
2327 self.set(MarginProp, current)
2328 }
2329 pub fn margin_right(self, margin: impl Into<PxPctAuto>) -> Self {
2331 let mut current = self.get(MarginProp);
2332 current.right = Some(margin.into());
2333 self.set(MarginProp, current)
2334 }
2335 pub fn margin_top(self, margin: impl Into<PxPctAuto>) -> Self {
2337 let mut current = self.get(MarginProp);
2338 current.top = Some(margin.into());
2339 self.set(MarginProp, current)
2340 }
2341 pub fn margin_bottom(self, margin: impl Into<PxPctAuto>) -> Self {
2343 let mut current = self.get(MarginProp);
2344 current.bottom = Some(margin.into());
2345 self.set(MarginProp, current)
2346 }
2347
2348 pub fn apply_padding(self, padding: Padding) -> Self {
2350 self.set(PaddingProp, padding)
2351 }
2352 pub fn apply_margin(self, margin: Margin) -> Self {
2354 self.set(MarginProp, margin)
2355 }
2356
2357 pub fn border_radius(self, radius: impl Into<PxPct>) -> Self {
2359 self.set(BorderRadiusProp, BorderRadius::all(radius))
2360 }
2361
2362 pub fn border_left(self, border: impl Into<StrokeWrap>) -> Self {
2364 let mut current = self.get(BorderProp);
2365 current.left = Some(border.into());
2366 self.set(BorderProp, current)
2367 }
2368 pub fn border_right(self, border: impl Into<StrokeWrap>) -> Self {
2370 let mut current = self.get(BorderProp);
2371 current.right = Some(border.into());
2372 self.set(BorderProp, current)
2373 }
2374 pub fn border_top(self, border: impl Into<StrokeWrap>) -> Self {
2376 let mut current = self.get(BorderProp);
2377 current.top = Some(border.into());
2378 self.set(BorderProp, current)
2379 }
2380 pub fn border_bottom(self, border: impl Into<StrokeWrap>) -> Self {
2382 let mut current = self.get(BorderProp);
2383 current.bottom = Some(border.into());
2384 self.set(BorderProp, current)
2385 }
2386
2387 pub fn border_left_color(self, color: impl Into<Brush>) -> Self {
2389 let mut current = self.get(BorderColorProp);
2390 current.left = Some(color.into());
2391 self.set(BorderColorProp, current)
2392 }
2393 pub fn border_right_color(self, color: impl Into<Brush>) -> Self {
2395 let mut current = self.get(BorderColorProp);
2396 current.right = Some(color.into());
2397 self.set(BorderColorProp, current)
2398 }
2399 pub fn border_top_color(self, color: impl Into<Brush>) -> Self {
2401 let mut current = self.get(BorderColorProp);
2402 current.top = Some(color.into());
2403 self.set(BorderColorProp, current)
2404 }
2405 pub fn border_bottom_color(self, color: impl Into<Brush>) -> Self {
2407 let mut current = self.get(BorderColorProp);
2408 current.bottom = Some(color.into());
2409 self.set(BorderColorProp, current)
2410 }
2411
2412 pub fn border_top_left_radius(self, radius: impl Into<PxPct>) -> Self {
2414 let mut current = self.get(BorderRadiusProp);
2415 current.top_left = Some(radius.into());
2416 self.set(BorderRadiusProp, current)
2417 }
2418 pub fn border_top_right_radius(self, radius: impl Into<PxPct>) -> Self {
2420 let mut current = self.get(BorderRadiusProp);
2421 current.top_right = Some(radius.into());
2422 self.set(BorderRadiusProp, current)
2423 }
2424 pub fn border_bottom_left_radius(self, radius: impl Into<PxPct>) -> Self {
2426 let mut current = self.get(BorderRadiusProp);
2427 current.bottom_left = Some(radius.into());
2428 self.set(BorderRadiusProp, current)
2429 }
2430 pub fn border_bottom_right_radius(self, radius: impl Into<PxPct>) -> Self {
2432 let mut current = self.get(BorderRadiusProp);
2433 current.bottom_right = Some(radius.into());
2434 self.set(BorderRadiusProp, current)
2435 }
2436
2437 pub fn apply_border(self, border: Border) -> Self {
2439 self.set(BorderProp, border)
2440 }
2441 pub fn apply_border_color(self, border_color: BorderColor) -> Self {
2443 self.set(BorderColorProp, border_color)
2444 }
2445 pub fn apply_border_radius(self, border_radius: BorderRadius) -> Self {
2447 self.set(BorderRadiusProp, border_radius)
2448 }
2449
2450 pub fn inset_left_pct(self, inset: f64) -> Self {
2452 self.inset_left(inset.pct())
2453 }
2454
2455 pub fn inset_right_pct(self, inset: f64) -> Self {
2457 self.inset_right(inset.pct())
2458 }
2459
2460 pub fn inset_top_pct(self, inset: f64) -> Self {
2462 self.inset_top(inset.pct())
2463 }
2464
2465 pub fn inset_bottom_pct(self, inset: f64) -> Self {
2467 self.inset_bottom(inset.pct())
2468 }
2469
2470 pub fn inset(self, inset: impl Into<PxPctAuto>) -> Self {
2472 let inset = inset.into();
2473 self.inset_left(inset)
2474 .inset_top(inset)
2475 .inset_right(inset)
2476 .inset_bottom(inset)
2477 }
2478
2479 pub fn inset_pct(self, inset: f64) -> Self {
2481 let inset = inset.pct();
2482 self.inset_left(inset)
2483 .inset_top(inset)
2484 .inset_right(inset)
2485 .inset_bottom(inset)
2486 }
2487
2488 pub fn cursor(self, cursor: impl Into<StyleValue<CursorStyle>>) -> Self {
2490 self.set_style_value(Cursor, cursor.into().map(Some))
2491 }
2492
2493 pub fn color(self, color: impl Into<StyleValue<Color>>) -> Self {
2495 self.set_style_value(TextColor, color.into().map(Some))
2496 }
2497
2498 pub fn background(self, color: impl Into<Brush>) -> Self {
2500 let brush = StyleValue::Val(Some(color.into()));
2501 self.set_style_value(Background, brush)
2502 }
2503
2504 pub fn box_shadow_blur(self, blur_radius: impl Into<PxPct>) -> Self {
2507 let mut value = self.get(BoxShadowProp);
2508 if let Some(v) = value.first_mut() {
2509 v.blur_radius = blur_radius.into();
2510 } else {
2511 value.push(BoxShadow {
2512 blur_radius: blur_radius.into(),
2513 ..Default::default()
2514 });
2515 }
2516 self.set(BoxShadowProp, value)
2517 }
2518
2519 pub fn box_shadow_color(self, color: Color) -> Self {
2521 let mut value = self.get(BoxShadowProp);
2522 if let Some(v) = value.first_mut() {
2523 v.color = color;
2524 } else {
2525 value.push(BoxShadow {
2526 color,
2527 ..Default::default()
2528 });
2529 }
2530 self.set(BoxShadowProp, value)
2531 }
2532
2533 pub fn box_shadow_spread(self, spread: impl Into<PxPct>) -> Self {
2536 let mut value = self.get(BoxShadowProp);
2537 if let Some(v) = value.first_mut() {
2538 v.spread = spread.into();
2539 } else {
2540 value.push(BoxShadow {
2541 spread: spread.into(),
2542 ..Default::default()
2543 });
2544 }
2545 self.set(BoxShadowProp, value)
2546 }
2547
2548 pub fn apply_box_shadows(self, shadow: impl Into<SmallVec<[BoxShadow; 3]>>) -> Self {
2581 self.set(BoxShadowProp, shadow.into())
2582 }
2583
2584 pub fn box_shadow_h_offset(self, h_offset: impl Into<PxPct>) -> Self {
2587 let mut value = self.get(BoxShadowProp);
2588 let offset = h_offset.into();
2589 if let Some(v) = value.first_mut() {
2590 v.left_offset = -offset;
2591 v.right_offset = offset;
2592 } else {
2593 value.push(BoxShadow {
2594 left_offset: -offset,
2595 right_offset: offset,
2596 ..Default::default()
2597 });
2598 }
2599 self.set(BoxShadowProp, value)
2600 }
2601
2602 pub fn box_shadow_v_offset(self, v_offset: impl Into<PxPct>) -> Self {
2605 let mut value = self.get(BoxShadowProp);
2606 let offset = v_offset.into();
2607 if let Some(v) = value.first_mut() {
2608 v.top_offset = -offset;
2609 v.bottom_offset = offset;
2610 } else {
2611 value.push(BoxShadow {
2612 top_offset: -offset,
2613 bottom_offset: offset,
2614 ..Default::default()
2615 });
2616 }
2617 self.set(BoxShadowProp, value)
2618 }
2619
2620 pub fn box_shadow_left_offset(self, left_offset: impl Into<PxPct>) -> Self {
2622 let mut value = self.get(BoxShadowProp);
2623 if let Some(v) = value.first_mut() {
2624 v.left_offset = left_offset.into();
2625 } else {
2626 value.push(BoxShadow {
2627 left_offset: left_offset.into(),
2628 ..Default::default()
2629 });
2630 }
2631 self.set(BoxShadowProp, value)
2632 }
2633
2634 pub fn box_shadow_right_offset(self, right_offset: impl Into<PxPct>) -> Self {
2636 let mut value = self.get(BoxShadowProp);
2637 if let Some(v) = value.first_mut() {
2638 v.right_offset = right_offset.into();
2639 } else {
2640 value.push(BoxShadow {
2641 right_offset: right_offset.into(),
2642 ..Default::default()
2643 });
2644 }
2645 self.set(BoxShadowProp, value)
2646 }
2647
2648 pub fn box_shadow_top_offset(self, top_offset: impl Into<PxPct>) -> Self {
2650 let mut value = self.get(BoxShadowProp);
2651 if let Some(v) = value.first_mut() {
2652 v.top_offset = top_offset.into();
2653 } else {
2654 value.push(BoxShadow {
2655 top_offset: top_offset.into(),
2656 ..Default::default()
2657 });
2658 }
2659 self.set(BoxShadowProp, value)
2660 }
2661
2662 pub fn box_shadow_bottom_offset(self, bottom_offset: impl Into<PxPct>) -> Self {
2664 let mut value = self.get(BoxShadowProp);
2665 if let Some(v) = value.first_mut() {
2666 v.bottom_offset = bottom_offset.into();
2667 } else {
2668 value.push(BoxShadow {
2669 bottom_offset: bottom_offset.into(),
2670 ..Default::default()
2671 });
2672 }
2673 self.set(BoxShadowProp, value)
2674 }
2675
2676 pub fn font_size(self, size: impl Into<Px>) -> Self {
2678 let px = size.into();
2679 self.set_style_value(FontSize, StyleValue::Val(Some(px.0 as f32)))
2680 }
2681
2682 pub fn font_family(self, family: impl Into<StyleValue<String>>) -> Self {
2684 self.set_style_value(FontFamily, family.into().map(Some))
2685 }
2686
2687 pub fn font_weight(self, weight: impl Into<StyleValue<Weight>>) -> Self {
2689 self.set_style_value(FontWeight, weight.into().map(Some))
2690 }
2691
2692 pub fn font_bold(self) -> Self {
2694 self.font_weight(Weight::BOLD)
2695 }
2696
2697 pub fn font_style(self, style: impl Into<StyleValue<crate::text::Style>>) -> Self {
2699 self.set_style_value(FontStyle, style.into().map(Some))
2700 }
2701
2702 pub fn cursor_color(self, color: impl Into<Brush>) -> Self {
2704 let brush = StyleValue::Val(color.into());
2705 self.set_style_value(CursorColor, brush)
2706 }
2707
2708 pub fn line_height(self, normal: f32) -> Self {
2710 self.set(LineHeight, Some(LineHeightValue::Normal(normal)))
2711 }
2712
2713 pub fn pointer_events_auto(self) -> Self {
2715 self.pointer_events(PointerEvents::Auto)
2716 }
2717
2718 pub fn pointer_events_none(self) -> Self {
2720 self.pointer_events(PointerEvents::None)
2721 }
2722
2723 pub fn text_ellipsis(self) -> Self {
2725 self.text_overflow(TextOverflow::Ellipsis)
2726 }
2727
2728 pub fn text_clip(self) -> Self {
2730 self.text_overflow(TextOverflow::Clip)
2731 }
2732
2733 pub fn absolute(self) -> Self {
2735 self.position(taffy::style::Position::Absolute)
2736 }
2737
2738 pub fn fixed(self) -> Self {
2754 self.position(taffy::style::Position::Absolute)
2755 .is_fixed(true)
2756 }
2757
2758 pub fn items_stretch(self) -> Self {
2760 self.align_items(Some(taffy::style::AlignItems::Stretch))
2761 }
2762
2763 pub fn items_start(self) -> Self {
2765 self.align_items(Some(taffy::style::AlignItems::FlexStart))
2766 }
2767
2768 pub fn items_center(self) -> Self {
2770 self.align_items(Some(taffy::style::AlignItems::Center))
2771 }
2772
2773 pub fn items_end(self) -> Self {
2775 self.align_items(Some(taffy::style::AlignItems::FlexEnd))
2776 }
2777
2778 pub fn items_baseline(self) -> Self {
2780 self.align_items(Some(taffy::style::AlignItems::Baseline))
2781 }
2782
2783 pub fn justify_start(self) -> Self {
2785 self.justify_content(Some(taffy::style::JustifyContent::FlexStart))
2786 }
2787
2788 pub fn justify_end(self) -> Self {
2790 self.justify_content(Some(taffy::style::JustifyContent::FlexEnd))
2791 }
2792
2793 pub fn justify_center(self) -> Self {
2795 self.justify_content(Some(taffy::style::JustifyContent::Center))
2796 }
2797
2798 pub fn justify_between(self) -> Self {
2800 self.justify_content(Some(taffy::style::JustifyContent::SpaceBetween))
2801 }
2802
2803 pub fn justify_around(self) -> Self {
2805 self.justify_content(Some(taffy::style::JustifyContent::SpaceAround))
2806 }
2807
2808 pub fn justify_evenly(self) -> Self {
2810 self.justify_content(Some(taffy::style::JustifyContent::SpaceEvenly))
2811 }
2812
2813 pub fn hide(self) -> Self {
2815 self.set(DisplayProp, Display::None)
2816 }
2817
2818 pub fn flex(self) -> Self {
2820 self.display(taffy::style::Display::Flex)
2821 }
2822
2823 pub fn grid(self) -> Self {
2825 self.display(taffy::style::Display::Grid)
2826 }
2827
2828 pub fn flex_row(self) -> Self {
2830 self.flex_direction(taffy::style::FlexDirection::Row)
2831 }
2832
2833 pub fn flex_col(self) -> Self {
2835 self.flex_direction(taffy::style::FlexDirection::Column)
2836 }
2837
2838 pub fn z_index(self, z_index: i32) -> Self {
2840 self.set(ZIndex, Some(z_index))
2841 }
2842
2843 pub fn scale(self, scale: impl Into<Pct>) -> Self {
2845 let val = scale.into();
2846 self.scale_x(val).scale_y(val)
2847 }
2848
2849 pub fn apply_opt<T>(self, opt: Option<T>, f: impl FnOnce(Self, T) -> Self) -> Self {
2861 if let Some(t) = opt { f(self, t) } else { self }
2862 }
2863
2864 pub fn apply_if(self, cond: bool, f: impl FnOnce(Self) -> Self) -> Self {
2873 if cond { f(self) } else { self }
2874 }
2875
2876 pub fn custom<CS: CustomStyle>(self, custom: impl FnOnce(CS) -> CS) -> Self {
2886 self.apply(custom(CS::default()).into())
2887 }
2888
2889 pub fn apply_custom<CS: Into<Style>>(self, custom_style: CS) -> Self {
2899 self.apply(custom_style.into())
2900 }
2901}
2902
2903impl Style {
2904 pub fn to_taffy_style(&self) -> TaffyStyle {
2905 let style = self.builtin();
2906 TaffyStyle {
2907 display: style.display(),
2908 overflow: taffy::Point {
2909 x: self.get(OverflowX),
2910 y: self.get(OverflowY),
2911 },
2912 position: style.position(),
2913 size: taffy::prelude::Size {
2914 width: style.width().into(),
2915 height: style.height().into(),
2916 },
2917 min_size: taffy::prelude::Size {
2918 width: style.min_width().into(),
2919 height: style.min_height().into(),
2920 },
2921 max_size: taffy::prelude::Size {
2922 width: style.max_width().into(),
2923 height: style.max_height().into(),
2924 },
2925 flex_direction: style.flex_direction(),
2926 flex_grow: style.flex_grow(),
2927 flex_shrink: style.flex_shrink(),
2928 flex_basis: style.flex_basis().into(),
2929 flex_wrap: style.flex_wrap(),
2930 justify_content: style.justify_content(),
2931 justify_self: style.justify_self(),
2932 justify_items: style.justify_items(),
2933 align_items: style.align_items(),
2934 align_content: style.align_content(),
2935 align_self: style.align_self(),
2936 aspect_ratio: style.aspect_ratio(),
2937 border: {
2938 let border = style.style.get(BorderProp);
2939 Rect {
2940 left: LengthPercentage::length(border.left.map_or(0.0, |b| b.0.width) as f32),
2941 top: LengthPercentage::length(border.top.map_or(0.0, |b| b.0.width) as f32),
2942 right: LengthPercentage::length(border.right.map_or(0.0, |b| b.0.width) as f32),
2943 bottom: LengthPercentage::length(
2944 border.bottom.map_or(0.0, |b| b.0.width) as f32
2945 ),
2946 }
2947 },
2948 padding: {
2949 let padding = style.style.get(PaddingProp);
2950 Rect {
2951 left: padding.left.unwrap_or(PxPct::Px(0.0)).into(),
2952 top: padding.top.unwrap_or(PxPct::Px(0.0)).into(),
2953 right: padding.right.unwrap_or(PxPct::Px(0.0)).into(),
2954 bottom: padding.bottom.unwrap_or(PxPct::Px(0.0)).into(),
2955 }
2956 },
2957 margin: {
2958 let margin = style.style.get(MarginProp);
2959 Rect {
2960 left: margin.left.unwrap_or(PxPctAuto::Px(0.0)).into(),
2961 top: margin.top.unwrap_or(PxPctAuto::Px(0.0)).into(),
2962 right: margin.right.unwrap_or(PxPctAuto::Px(0.0)).into(),
2963 bottom: margin.bottom.unwrap_or(PxPctAuto::Px(0.0)).into(),
2964 }
2965 },
2966 inset: Rect {
2967 left: style.inset_left().into(),
2968 top: style.inset_top().into(),
2969 right: style.inset_right().into(),
2970 bottom: style.inset_bottom().into(),
2971 },
2972 gap: Size {
2973 width: style.col_gap().into(),
2974 height: style.row_gap().into(),
2975 },
2976 grid_template_rows: style.grid_template_rows(),
2977 grid_template_columns: style.grid_template_columns(),
2978 grid_row: style.grid_row(),
2979 grid_column: style.grid_column(),
2980 grid_auto_rows: style.grid_auto_rows(),
2981 grid_auto_columns: style.grid_auto_columns(),
2982 grid_auto_flow: style.grid_auto_flow(),
2983 ..Default::default()
2984 }
2985 }
2986}