tailwind_fuse/core/merge/
mod.rs

1pub(crate) mod config;
2pub(crate) mod get_collision_id;
3pub(crate) mod get_collisions;
4pub(crate) mod merge_impl;
5pub(crate) mod validators;
6
7pub use config::*;
8pub use merge_impl::tw_merge_override;
9
10/// Merges all the Tailwind classes, resolving conflicts.
11///
12/// Items can be anything that implements [`crate::AsTailwindClass`].
13///
14/// If you DON'T want to handle conflicts use [`crate::tw_join!`].
15///
16/// If you want to set global options use [`crate::merge::set_merge_options`].
17///
18/// If you want a custom type to be used with this macro, implement the [`crate::MaybeIntoTailwindClass`] trait.
19#[macro_export]
20macro_rules! tw_merge {
21    ($($item:expr),+ $(,)?) => {{
22        let joined = $crate::tw_join!($($item),+);
23        $crate::merge::tw_merge(joined.as_str())
24    }};
25}
26
27/// Merges all the Tailwind classes in the string, resolving conflicts.
28///
29/// If you need custom options use [`tw_merge_options`].
30#[inline]
31pub fn tw_merge(class: impl AsRef<str>) -> String {
32    tw_merge_slice_options(&[class.as_ref()], Default::default())
33}
34
35/// Merges all the Tailwind classes in the provided strings, resolving conflicts.
36/// Useful to avoid collecting all the strings into a single string.
37///
38/// If you need custom options use [`tw_merge_slice_options`].
39#[inline]
40pub fn tw_merge_slice(class: &[&str]) -> String {
41    tw_merge_slice_options(class, Default::default())
42}
43
44/// Merges all the Tailwind classes, resolving conflicts, with the provided options.
45///
46/// ## Example: With Tailwind Prefix
47///
48/// ```
49/// # use tailwind_fuse::merge::*;
50/// const OPTIONS: MergeOptions = MergeOptions {
51///   prefix: "tw-",
52///   separator: ":",
53/// };
54///
55/// pub fn my_custom_tw_merge(class: impl AsRef<str>) -> String {
56///    tw_merge_options(class, OPTIONS)
57/// }
58/// ```
59#[inline]
60pub fn tw_merge_options(class: impl AsRef<str>, options: MergeOptions) -> String {
61    merge_impl::tw_merge_override(
62        &[class.as_ref()],
63        options,
64        |_: &[&str], _: Option<&str>| None,
65        |_: &str| None,
66    )
67}
68
69/// Merges all the Tailwind classes in the provided strings, resolving conflicts.
70/// Useful to avoid collecting all the strings into a single string.
71///
72/// If you don't need custom options use [`tw_merge_slice`].
73///
74/// ## Example: With Tailwind Prefix
75///
76/// ```
77/// # use tailwind_fuse::merge::*;
78/// const OPTIONS: MergeOptions = MergeOptions {
79///   prefix: "tw-",
80///   separator: ":",
81/// };
82///
83/// pub fn my_custom_tw_merge(class: &[&str]) -> String {
84///    tw_merge_slice_options(class, OPTIONS)
85/// }
86/// ```
87#[inline]
88pub fn tw_merge_slice_options(class: &[&str], options: MergeOptions) -> String {
89    merge_impl::tw_merge_override(
90        class,
91        options,
92        |_: &[&str], _: Option<&str>| None,
93        |_: &str| None,
94    )
95}
96
97/// Return a ConflictId for a given Tailwind Class.
98pub trait CollisionIdFn {
99    /// elements: parts of the Tailwind class separated by `-`.
100    ///
101    /// (e.g. `bg-red-500` would be `["bg", "red", "500"]`)
102    ///
103    /// arbitrary: the arbitrary value at the end of the Tailwind class
104    ///
105    /// <https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values>
106    fn apply(&self, elements: &[&str], arbitrary: Option<&str>) -> Option<&'static str>;
107}
108
109impl<F> CollisionIdFn for F
110where
111    F: Fn(&[&str], Option<&str>) -> Option<&'static str> + 'static,
112{
113    fn apply(&self, elements: &[&str], arbitrary: Option<&str>) -> Option<&'static str> {
114        self(elements, arbitrary)
115    }
116}
117
118/// Return list of CollisionIds that collide with the given CollisionId.
119///
120/// The list does not need to contain the given CollisionId.
121///
122/// e.g. "flex-row" should probably collide with "flex-col"
123pub trait GetCollisionsFn {
124    /// Return list of CollisionIds that collide with the given CollisionId.
125    fn apply(&self, collision_id: &str) -> Option<Vec<&'static str>>;
126}
127
128impl<F> GetCollisionsFn for F
129where
130    F: Fn(&str) -> Option<Vec<&'static str>>,
131{
132    fn apply(&self, collision_id: &str) -> Option<Vec<&'static str>> {
133        self(collision_id)
134    }
135}