create-prisma-php-app 3.3.11 → 3.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,190 +6,390 @@ namespace Lib\PHPX;
6
6
 
7
7
  class TwMerge
8
8
  {
9
- private static $classGroupPatterns = [
10
- // **General Padding classes**
11
- "p" => "/^p-/",
12
- // **Specific Padding classes**
13
- "pt" => "/^pt-/",
14
- "pr" => "/^pr-/",
15
- "pb" => "/^pb-/",
16
- "pl" => "/^pl-/",
17
- "px" => "/^px-/",
18
- "py" => "/^py-/",
19
- // **Margin classes**
20
- "m" => "/^m-/",
21
- "mt" => "/^mt-/",
22
- "mr" => "/^mr-/",
23
- "mb" => "/^mb-/",
24
- "ml" => "/^ml-/",
25
- "mx" => "/^mx-/",
26
- "my" => "/^my-/",
27
- // **Background color classes**
28
- "bg" => "/^bg-/",
29
- // **Text size classes**
30
- "text-size" => '/^text-(xs|sm|base|lg|xl|[2-9]xl)$/',
31
- // **Text alignment classes**
32
- "text-alignment" => '/^text-(left|center|right|justify)$/',
33
- // **Text color classes**
34
- "text-color" => '/^text-(?!xs$|sm$|base$|lg$|xl$|[2-9]xl$).+$/',
35
- // **Text transform classes**
36
- "text-transform" => '/^text-(uppercase|lowercase|capitalize|normal-case)$/',
37
- // **Text decoration classes**
38
- "text-decoration" => '/^text-(underline|line-through|no-underline)$/',
39
- // **Border width classes**
40
- "border-width" => '/^border(-[0-9]+)?$/',
41
- // **Border color classes**
42
- "border-color" => "/^border-(?![0-9])/",
43
- // **Border radius classes**
44
- "rounded" => '/^rounded(-.*)?$/',
45
- // **Font weight classes**
46
- "font" => '/^font-(thin|extralight|light|normal|medium|semibold|bold|extrabold|black)$/',
47
- // **Hover background color classes**
48
- "hover:bg" => "/^hover:bg-/",
49
- // **Hover text color classes**
50
- "hover:text" => "/^hover:text-/",
51
- // **Transition classes**
52
- "transition" => '/^transition(-[a-z]+)?$/',
53
- // **Opacity classes**
54
- "opacity" => '/^opacity(-[0-9]+)?$/',
55
- // **Flexbox alignment classes**
56
- "justify" => "/^justify-(start|end|center|between|around|evenly)$/",
57
- // **Flexbox alignment classes**
58
- "items" => "/^items-(start|end|center|baseline|stretch)$/",
59
- // **Width classes**
60
- "w" => "/^w-(full|[0-9]+|\\[.+\\])$/",
61
- // **Max-width classes**
62
- "max-w" => '/^max-w-(full|[0-9]+|\\[.+\\]|[a-zA-Z]+)$/',
63
- // **Other utility classes can be added here**
9
+ private const IMPORTANT_MODIFIER = '!';
10
+
11
+ private static array $classGroups = [
12
+ // Layout
13
+ 'aspect' => ['aspect-auto', 'aspect-square', 'aspect-video', '/^aspect-\[.+\]$/'],
14
+ 'container' => ['container'],
15
+ 'columns' => ['/^columns-(\d+|auto|\[.+\])$/'],
16
+ 'break-after' => ['/^break-after-(auto|avoid|all|avoid-page|page|left|right|column)$/'],
17
+ 'break-before' => ['/^break-before-(auto|avoid|all|avoid-page|page|left|right|column)$/'],
18
+ 'break-inside' => ['/^break-inside-(auto|avoid|avoid-page|avoid-column)$/'],
19
+ 'box-decoration' => ['/^box-decoration-(clone|slice)$/'],
20
+ 'box' => ['/^box-(border|content)$/'],
21
+ 'display' => ['block', 'inline-block', 'inline', 'flex', 'inline-flex', 'table', 'inline-table', 'table-caption', 'table-cell', 'table-column', 'table-column-group', 'table-footer-group', 'table-header-group', 'table-row-group', 'table-row', 'flow-root', 'grid', 'inline-grid', 'contents', 'list-item', 'hidden'],
22
+ 'float' => ['/^float-(right|left|none)$/'],
23
+ 'clear' => ['/^clear-(left|right|both|none)$/'],
24
+ 'isolation' => ['isolate', 'isolation-auto'],
25
+ 'object-fit' => ['/^object-(contain|cover|fill|none|scale-down)$/'],
26
+ 'object-position' => ['/^object-(bottom|center|left|left-bottom|left-top|right|right-bottom|right-top|top|\[.+\])$/'],
27
+ 'overflow' => ['/^overflow-(auto|hidden|clip|visible|scroll)$/'],
28
+ 'overflow-x' => ['/^overflow-x-(auto|hidden|clip|visible|scroll)$/'],
29
+ 'overflow-y' => ['/^overflow-y-(auto|hidden|clip|visible|scroll)$/'],
30
+ 'overscroll' => ['/^overscroll-(auto|contain|none)$/'],
31
+ 'overscroll-x' => ['/^overscroll-x-(auto|contain|none)$/'],
32
+ 'overscroll-y' => ['/^overscroll-y-(auto|contain|none)$/'],
33
+ 'position' => ['static', 'fixed', 'absolute', 'relative', 'sticky'],
34
+ 'inset' => ['/^inset-(\d+(\.\d+)?|auto|\[.+\]|px|full)$/', '/^-inset-(\d+(\.\d+)?|\[.+\])$/'],
35
+ 'inset-x' => ['/^inset-x-(\d+(\.\d+)?|auto|\[.+\]|px|full)$/', '/^-inset-x-(\d+(\.\d+)?|\[.+\])$/'],
36
+ 'inset-y' => ['/^inset-y-(\d+(\.\d+)?|auto|\[.+\]|px|full)$/', '/^-inset-y-(\d+(\.\d+)?|\[.+\])$/'],
37
+ 'top' => ['/^top-(\d+(\.\d+)?|auto|\[.+\]|px|full)$/', '/^-top-(\d+(\.\d+)?|\[.+\])$/'],
38
+ 'right' => ['/^right-(\d+(\.\d+)?|auto|\[.+\]|px|full)$/', '/^-right-(\d+(\.\d+)?|\[.+\])$/'],
39
+ 'bottom' => ['/^bottom-(\d+(\.\d+)?|auto|\[.+\]|px|full)$/', '/^-bottom-(\d+(\.\d+)?|\[.+\])$/'],
40
+ 'left' => ['/^left-(\d+(\.\d+)?|auto|\[.+\]|px|full)$/', '/^-left-(\d+(\.\d+)?|\[.+\])$/'],
41
+ 'visibility' => ['visible', 'invisible', 'collapse'],
42
+ 'z' => ['/^z-(\d+|auto|\[.+\])$/', '/^-z-(\d+|\[.+\])$/'],
43
+
44
+ // Flexbox & Grid
45
+ 'flex-basis' => ['/^basis-(\d+(\.\d+)?\/\d+|\d+(\.\d+)?|auto|px|full|\[.+\])$/'],
46
+ 'flex-direction' => ['/^flex-(row|row-reverse|col|col-reverse)$/'],
47
+ 'flex-wrap' => ['/^flex-(wrap|wrap-reverse|nowrap)$/'],
48
+ 'flex' => ['/^flex-(1|auto|initial|none|\[.+\])$/'],
49
+ 'flex-grow' => ['/^grow(-0|\[.+\])?$/'],
50
+ 'flex-shrink' => ['/^shrink(-0|\[.+\])?$/'],
51
+ 'order' => ['/^order-(\d+|first|last|none|\[.+\])$/'],
52
+ 'grid-template-columns' => ['/^grid-cols-(\d+|none|subgrid|\[.+\])$/'],
53
+ 'grid-column' => ['/^col-(auto|span-(\d+|full)|\[.+\])$/'],
54
+ 'grid-column-start' => ['/^col-start-(\d+|auto|\[.+\])$/'],
55
+ 'grid-column-end' => ['/^col-end-(\d+|auto|\[.+\])$/'],
56
+ 'grid-template-rows' => ['/^grid-rows-(\d+|none|subgrid|\[.+\])$/'],
57
+ 'grid-row' => ['/^row-(auto|span-(\d+|full)|\[.+\])$/'],
58
+ 'grid-row-start' => ['/^row-start-(\d+|auto|\[.+\])$/'],
59
+ 'grid-row-end' => ['/^row-end-(\d+|auto|\[.+\])$/'],
60
+ 'grid-auto-flow' => ['/^grid-flow-(row|col|dense|row-dense|col-dense)$/'],
61
+ 'grid-auto-columns' => ['/^auto-cols-(auto|min|max|fr|\[.+\])$/'],
62
+ 'grid-auto-rows' => ['/^auto-rows-(auto|min|max|fr|\[.+\])$/'],
63
+ 'gap' => ['/^gap-(\d+(\.\d+)?|px|\[.+\])$/'],
64
+ 'gap-x' => ['/^gap-x-(\d+(\.\d+)?|px|\[.+\])$/'],
65
+ 'gap-y' => ['/^gap-y-(\d+(\.\d+)?|px|\[.+\])$/'],
66
+ 'justify-content' => ['/^justify-(start|end|center|between|around|evenly)$/'],
67
+ 'justify-items' => ['/^justify-items-(start|end|center|stretch)$/'],
68
+ 'justify-self' => ['/^justify-self-(auto|start|end|center|stretch)$/'],
69
+ 'align-content' => ['/^content-(center|start|end|between|around|evenly|baseline|stretch)$/'],
70
+ 'align-items' => ['/^items-(start|end|center|baseline|stretch)$/'],
71
+ 'align-self' => ['/^self-(auto|start|end|center|stretch|baseline)$/'],
72
+ 'place-content' => ['/^place-content-(center|start|end|between|around|evenly|baseline|stretch)$/'],
73
+ 'place-items' => ['/^place-items-(start|end|center|baseline|stretch)$/'],
74
+ 'place-self' => ['/^place-self-(auto|start|end|center|stretch)$/'],
75
+
76
+ // Spacing
77
+ 'p' => ['/^p-(\d+(\.\d+)?|px|\[.+\])$/'],
78
+ 'px' => ['/^px-(\d+(\.\d+)?|px|\[.+\])$/'],
79
+ 'py' => ['/^py-(\d+(\.\d+)?|px|\[.+\])$/'],
80
+ 'pt' => ['/^pt-(\d+(\.\d+)?|px|\[.+\])$/'],
81
+ 'pr' => ['/^pr-(\d+(\.\d+)?|px|\[.+\])$/'],
82
+ 'pb' => ['/^pb-(\d+(\.\d+)?|px|\[.+\])$/'],
83
+ 'pl' => ['/^pl-(\d+(\.\d+)?|px|\[.+\])$/'],
84
+ 'm' => ['/^-?m-(\d+(\.\d+)?|px|auto|\[.+\])$/'],
85
+ 'mx' => ['/^-?mx-(\d+(\.\d+)?|px|auto|\[.+\])$/'],
86
+ 'my' => ['/^-?my-(\d+(\.\d+)?|px|auto|\[.+\])$/'],
87
+ 'mt' => ['/^-?mt-(\d+(\.\d+)?|px|auto|\[.+\])$/'],
88
+ 'mr' => ['/^-?mr-(\d+(\.\d+)?|px|auto|\[.+\])$/'],
89
+ 'mb' => ['/^-?mb-(\d+(\.\d+)?|px|auto|\[.+\])$/'],
90
+ 'ml' => ['/^-?ml-(\d+(\.\d+)?|px|auto|\[.+\])$/'],
91
+ 'space-x' => ['/^-?space-x-(\d+(\.\d+)?|px|reverse|\[.+\])$/'],
92
+ 'space-y' => ['/^-?space-y-(\d+(\.\d+)?|px|reverse|\[.+\])$/'],
93
+
94
+ // Sizing
95
+ 'w' => ['/^w-(\d+(\.\d+)?\/\d+|\d+(\.\d+)?|auto|px|full|screen|svw|lvw|dvw|min|max|fit|\[.+\])$/'],
96
+ 'min-w' => ['/^min-w-(\d+|px|full|min|max|fit|\[.+\])$/'],
97
+ 'max-w' => ['/^max-w-(\d+|px|full|min|max|fit|prose|screen-\w+|\[.+\])$/'],
98
+ 'h' => ['/^h-(\d+(\.\d+)?\/\d+|\d+(\.\d+)?|auto|px|full|screen|svh|lvh|dvh|min|max|fit|\[.+\])$/'],
99
+ 'min-h' => ['/^min-h-(\d+|px|full|screen|svh|lvh|dvh|min|max|fit|\[.+\])$/'],
100
+ 'max-h' => ['/^max-h-(\d+|px|full|screen|svh|lvh|dvh|min|max|fit|\[.+\])$/'],
101
+ 'size' => ['/^size-(\d+(\.\d+)?|auto|px|full|\[.+\])$/'],
102
+
103
+ // Typography
104
+ 'font-family' => ['/^font-(sans|serif|mono|\[.+\])$/'],
105
+ 'font-size' => ['/^text-(xs|sm|base|lg|xl|[2-9]xl|\[.+\])$/'],
106
+ 'font-smoothing' => ['antialiased', 'subpixel-antialiased'],
107
+ 'font-style' => ['italic', 'not-italic'],
108
+ 'font-weight' => ['/^font-(thin|extralight|light|normal|medium|semibold|bold|extrabold|black|\[.+\])$/'],
109
+ 'font-variant-numeric' => ['/^(normal-nums|ordinal|slashed-zero|lining-nums|oldstyle-nums|proportional-nums|tabular-nums|diagonal-fractions|stacked-fractions)$/'],
110
+ 'letter-spacing' => ['/^tracking-(tighter|tight|normal|wide|wider|widest|\[.+\])$/'],
111
+ 'line-clamp' => ['/^line-clamp-(\d+|none)$/'],
112
+ 'line-height' => ['/^leading-(\d+(\.\d+)?|none|tight|snug|normal|relaxed|loose|\[.+\])$/'],
113
+ 'list-image' => ['/^list-image-(none|\[.+\])$/'],
114
+ 'list-style-position' => ['/^list-(inside|outside)$/'],
115
+ 'list-style-type' => ['/^list-(none|disc|decimal|\[.+\])$/'],
116
+ 'text-align' => ['/^text-(left|center|right|justify|start|end)$/'],
117
+ 'text-color' => ['/^text-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
118
+ 'text-decoration' => ['underline', 'overline', 'line-through', 'no-underline'],
119
+ 'text-decoration-color' => ['/^decoration-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
120
+ 'text-decoration-style' => ['/^decoration-(solid|double|dotted|dashed|wavy)$/'],
121
+ 'text-decoration-thickness' => ['/^decoration-(auto|from-font|\d+|px|\[.+\])$/'],
122
+ 'text-underline-offset' => ['/^underline-offset-(auto|\d+|px|\[.+\])$/'],
123
+ 'text-transform' => ['uppercase', 'lowercase', 'capitalize', 'normal-case'],
124
+ 'text-overflow' => ['truncate', 'text-ellipsis', 'text-clip'],
125
+ 'text-wrap' => ['/^text-(wrap|nowrap|balance|pretty)$/'],
126
+ 'text-indent' => ['/^indent-(\d+(\.\d+)?|px|\[.+\])$/'],
127
+ 'vertical-align' => ['/^align-(baseline|top|middle|bottom|text-top|text-bottom|sub|super|\[.+\])$/'],
128
+ 'whitespace' => ['/^whitespace-(normal|nowrap|pre|pre-line|pre-wrap|break-spaces)$/'],
129
+ 'word-break' => ['/^break-(normal|words|all|keep)$/'],
130
+ 'hyphens' => ['/^hyphens-(none|manual|auto)$/'],
131
+
132
+ // Backgrounds
133
+ 'bg-attachment' => ['/^bg-(fixed|local|scroll)$/'],
134
+ 'bg-clip' => ['/^bg-clip-(border|padding|content|text)$/'],
135
+ 'bg-color' => ['/^bg-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
136
+ 'bg-origin' => ['/^bg-origin-(border|padding|content)$/'],
137
+ 'bg-position' => ['/^bg-(bottom|center|left|left-bottom|left-top|right|right-bottom|right-top|top|\[.+\])$/'],
138
+ 'bg-repeat' => ['/^bg-(no-repeat|repeat|repeat-x|repeat-y|repeat-round|repeat-space)$/'],
139
+ 'bg-size' => ['/^bg-(auto|cover|contain|\[.+\])$/'],
140
+ 'bg-image' => ['/^bg-(none|gradient-to-(t|tr|r|br|b|bl|l|tl)|\[.+\])$/'],
141
+ 'gradient-from' => ['/^from-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
142
+ 'gradient-via' => ['/^via-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
143
+ 'gradient-to' => ['/^to-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
144
+
145
+ // Borders
146
+ 'rounded' => ['/^rounded(-(\w+))?(-(\d+(\.\d+)?|px|full|\[.+\]))?$/'],
147
+ 'border-w-all' => ['/^border(-(\d+|px|\[.+\]))?$/', '/^border-0$/'],
148
+ 'border-w-x' => ['/^border-x(-(\d+|px|\[.+\]))?$/'],
149
+ 'border-w-y' => ['/^border-y(-(\d+|px|\[.+\]))?$/'],
150
+ 'border-w-t' => ['/^border-t(-(\d+|px|\[.+\]))?$/'],
151
+ 'border-w-r' => ['/^border-r(-(\d+|px|\[.+\]))?$/'],
152
+ 'border-w-b' => ['/^border-b(-(\d+|px|\[.+\]))?$/'],
153
+ 'border-w-l' => ['/^border-l(-(\d+|px|\[.+\]))?$/'],
154
+ 'border-color' => ['/^border(-[trbl])?-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|primary|secondary|accent|muted|card|popover|border|input|ring|background|foreground|destructive|success|warning|info|\[.+\])$/'],
155
+ 'border-style' => ['/^border-(solid|dashed|dotted|double|hidden|none)$/'],
156
+ 'divide-x' => ['/^divide-x(-(\d+|px|reverse|\[.+\]))?$/'],
157
+ 'divide-y' => ['/^divide-y(-(\d+|px|reverse|\[.+\]))?$/'],
158
+ 'divide-color' => ['/^divide-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|primary|secondary|accent|muted|card|popover|border|input|ring|background|foreground|destructive|success|warning|info|\[.+\])$/'],
159
+ 'divide-style' => ['/^divide-(solid|dashed|dotted|double|none)$/'],
160
+ 'outline-w' => ['/^outline(-(\d+|px|\[.+\]))?$/'],
161
+ 'outline-color' => ['/^outline-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|primary|secondary|accent|muted|card|popover|border|input|ring|background|foreground|destructive|success|warning|info|\[.+\])$/'],
162
+ 'outline-style' => ['/^outline-(none|solid|dashed|dotted|double)$/'],
163
+ 'outline-offset' => ['/^outline-offset-(\d+|px|\[.+\])$/'],
164
+ 'ring-w' => ['/^ring(-(\d+|px|inset|\[.+\]))?$/'],
165
+ 'ring-color' => ['/^ring-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|primary|secondary|accent|muted|card|popover|border|input|ring|background|foreground|destructive|success|warning|info|\[.+\])$/'],
166
+ 'ring-offset-w' => ['/^ring-offset-(\d+|px|\[.+\])$/'],
167
+ 'ring-offset-color' => ['/^ring-offset-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|primary|secondary|accent|muted|card|popover|border|input|ring|background|foreground|destructive|success|warning|info|\[.+\])$/'],
168
+
169
+ // Effects
170
+ 'shadow' => ['/^shadow(-(\w+|\[.+\]))?$/'],
171
+ 'shadow-color' => ['/^shadow-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
172
+ 'opacity' => ['/^opacity-(\d+|\[.+\])$/'],
173
+ 'mix-blend' => ['/^mix-blend-(normal|multiply|screen|overlay|darken|lighten|color-dodge|color-burn|hard-light|soft-light|difference|exclusion|hue|saturation|color|luminosity|plus-lighter)$/'],
174
+ 'bg-blend' => ['/^bg-blend-(normal|multiply|screen|overlay|darken|lighten|color-dodge|color-burn|hard-light|soft-light|difference|exclusion|hue|saturation|color|luminosity)$/'],
175
+
176
+ // Filters
177
+ 'blur' => ['/^blur(-(\w+|\[.+\]))?$/'],
178
+ 'brightness' => ['/^brightness-(\d+|\[.+\])$/'],
179
+ 'contrast' => ['/^contrast-(\d+|\[.+\])$/'],
180
+ 'drop-shadow' => ['/^drop-shadow(-(\w+|\[.+\]))?$/'],
181
+ 'grayscale' => ['/^grayscale(-(\d+|\[.+\]))?$/'],
182
+ 'hue-rotate' => ['/^hue-rotate-(\d+|\[.+\])$/'],
183
+ 'invert' => ['/^invert(-(\d+|\[.+\]))?$/'],
184
+ 'saturate' => ['/^saturate-(\d+|\[.+\])$/'],
185
+ 'sepia' => ['/^sepia(-(\d+|\[.+\]))?$/'],
186
+ 'backdrop-blur' => ['/^backdrop-blur(-(\w+|\[.+\]))?$/'],
187
+ 'backdrop-brightness' => ['/^backdrop-brightness-(\d+|\[.+\])$/'],
188
+ 'backdrop-contrast' => ['/^backdrop-contrast-(\d+|\[.+\])$/'],
189
+ 'backdrop-grayscale' => ['/^backdrop-grayscale(-(\d+|\[.+\]))?$/'],
190
+ 'backdrop-hue-rotate' => ['/^backdrop-hue-rotate-(\d+|\[.+\])$/'],
191
+ 'backdrop-invert' => ['/^backdrop-invert(-(\d+|\[.+\]))?$/'],
192
+ 'backdrop-opacity' => ['/^backdrop-opacity-(\d+|\[.+\])$/'],
193
+ 'backdrop-saturate' => ['/^backdrop-saturate-(\d+|\[.+\])$/'],
194
+ 'backdrop-sepia' => ['/^backdrop-sepia(-(\d+|\[.+\]))?$/'],
195
+
196
+ // Transitions & Animation
197
+ 'transition-property' => ['/^transition(-(\w+|\[.+\]))?$/'],
198
+ 'transition-duration' => ['/^duration-(\d+|\[.+\])$/'],
199
+ 'transition-timing' => ['/^ease-(linear|in|out|in-out|\[.+\])$/'],
200
+ 'transition-delay' => ['/^delay-(\d+|\[.+\])$/'],
201
+ 'animate' => ['/^animate-(none|spin|ping|pulse|bounce|\[.+\])$/'],
202
+
203
+ // Transforms
204
+ 'scale' => ['/^scale(-[xy])?-(\d+|\[.+\])$/'],
205
+ 'rotate' => ['/^-?rotate-(\d+|\[.+\])$/'],
206
+ 'translate-x' => ['/^-?translate-x-(\d+(\.\d+)?\/\d+|\d+(\.\d+)?|px|full|\[.+\])$/'],
207
+ 'translate-y' => ['/^-?translate-y-(\d+(\.\d+)?\/\d+|\d+(\.\d+)?|px|full|\[.+\])$/'],
208
+ 'skew-x' => ['/^-?skew-x-(\d+|\[.+\])$/'],
209
+ 'skew-y' => ['/^-?skew-y-(\d+|\[.+\])$/'],
210
+ 'transform-origin' => ['/^origin-(center|top|top-right|right|bottom-right|bottom|bottom-left|left|top-left|\[.+\])$/'],
211
+
212
+ // Interactivity
213
+ 'accent' => ['/^accent-(auto|inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
214
+ 'appearance' => ['/^appearance-(none|auto)$/'],
215
+ 'cursor' => ['/^cursor-(auto|default|pointer|wait|text|move|help|not-allowed|none|context-menu|progress|cell|crosshair|vertical-text|alias|copy|no-drop|grab|grabbing|all-scroll|col-resize|row-resize|n-resize|e-resize|s-resize|w-resize|ne-resize|nw-resize|se-resize|sw-resize|ew-resize|ns-resize|nesw-resize|nwse-resize|zoom-in|zoom-out|\[.+\])$/'],
216
+ 'caret-color' => ['/^caret-(inherit|current|transparent|black|white|slate-\d+|gray-\d+|zinc-\d+|neutral-\d+|stone-\d+|red-\d+|orange-\d+|amber-\d+|yellow-\d+|lime-\d+|green-\d+|emerald-\d+|teal-\d+|cyan-\d+|sky-\d+|blue-\d+|indigo-\d+|violet-\d+|purple-\d+|fuchsia-\d+|pink-\d+|rose-\d+|\[.+\])$/'],
217
+ 'pointer-events' => ['/^pointer-events-(none|auto)$/'],
218
+ 'resize' => ['/^resize(-none|-y|-x)?$/'],
219
+ 'scroll-behavior' => ['/^scroll-(auto|smooth)$/'],
220
+ 'scroll-m' => ['/^scroll-m[trbl]?x?y?-(\d+(\.\d+)?|px|\[.+\])$/'],
221
+ 'scroll-p' => ['/^scroll-p[trbl]?x?y?-(\d+(\.\d+)?|px|\[.+\])$/'],
222
+ 'scroll-snap-align' => ['/^snap-(start|end|center|align-none)$/'],
223
+ 'scroll-snap-stop' => ['/^snap-(normal|always)$/'],
224
+ 'scroll-snap-type' => ['/^snap-(none|x|y|both|mandatory|proximity)$/'],
225
+ 'touch' => ['/^touch-(auto|none|pan-x|pan-left|pan-right|pan-y|pan-up|pan-down|pinch-zoom|manipulation)$/'],
226
+ 'user-select' => ['/^select-(none|text|all|auto)$/'],
227
+ 'will-change' => ['/^will-change-(auto|scroll|contents|transform|\[.+\])$/'],
64
228
  ];
65
229
 
66
- private static $conflictGroups = [
67
- // **Padding conflict groups**
68
- "p" => ["p", "px", "py", "pt", "pr", "pb", "pl"],
69
- "px" => ["px", "pl", "pr"],
70
- "py" => ["py", "pt", "pb"],
71
- "pt" => ["pt"],
72
- "pr" => ["pr"],
73
- "pb" => ["pb"],
74
- "pl" => ["pl"],
75
- // **Margin conflict groups**
76
- "m" => ["m", "mx", "my", "mt", "mr", "mb", "ml"],
77
- "mx" => ["mx", "ml", "mr"],
78
- "my" => ["my", "mt", "mb"],
79
- "mt" => ["mt"],
80
- "mr" => ["mr"],
81
- "mb" => ["mb"],
82
- "ml" => ["ml"],
83
- // **Border width conflict group**
84
- "border-width" => ["border-width"],
85
- // **Border color conflict group**
86
- "border-color" => ["border-color"],
87
- // **Text size conflict group**
88
- "text-size" => ["text-size"],
89
- // **Text color conflict group**
90
- "text-color" => ["text-color"],
91
- // **Text alignment conflict group**
92
- "text-alignment" => ["text-alignment"],
93
- // **Text transform conflict group**
94
- "text-transform" => ["text-transform"],
95
- // **Text decoration conflict group**
96
- "text-decoration" => ["text-decoration"],
97
- // **Opacity conflict group**
98
- "opacity" => ["opacity"],
99
- // **Flexbox alignment conflict groups**
100
- "justify" => ["justify"],
101
- // **Flexbox alignment conflict group**
102
- "items" => ["items"],
103
- // **Width conflict group**
104
- "w" => ["w"],
105
- // **Max-width conflict group**
106
- "max-w" => ["max-w"],
107
- // **Add other conflict groups as needed**
230
+ private static array $conflictingClassGroups = [
231
+ 'overflow' => ['overflow-x', 'overflow-y'],
232
+ 'overscroll' => ['overscroll-x', 'overscroll-y'],
233
+ 'inset' => ['inset-x', 'inset-y', 'top', 'right', 'bottom', 'left'],
234
+ 'inset-x' => ['right', 'left'],
235
+ 'inset-y' => ['top', 'bottom'],
236
+ 'flex' => ['basis', 'grow', 'shrink'],
237
+ 'gap' => ['gap-x', 'gap-y'],
238
+ 'p' => ['px', 'py', 'pt', 'pr', 'pb', 'pl'],
239
+ 'px' => ['pr', 'pl'],
240
+ 'py' => ['pt', 'pb'],
241
+ 'm' => ['mx', 'my', 'mt', 'mr', 'mb', 'ml'],
242
+ 'mx' => ['mr', 'ml'],
243
+ 'my' => ['mt', 'mb'],
244
+ 'font-size' => ['line-height'],
245
+ 'fvn-normal' => ['fvn-ordinal', 'fvn-slashed-zero', 'fvn-figure', 'fvn-spacing', 'fvn-fraction'],
246
+ 'rounded' => ['rounded-s', 'rounded-e', 'rounded-t', 'rounded-r', 'rounded-b', 'rounded-l', 'rounded-ss', 'rounded-se', 'rounded-ee', 'rounded-es', 'rounded-tl', 'rounded-tr', 'rounded-br', 'rounded-bl'],
247
+ 'rounded-s' => ['rounded-ss', 'rounded-es'],
248
+ 'rounded-e' => ['rounded-se', 'rounded-ee'],
249
+ 'rounded-t' => ['rounded-tl', 'rounded-tr'],
250
+ 'rounded-r' => ['rounded-tr', 'rounded-br'],
251
+ 'rounded-b' => ['rounded-br', 'rounded-bl'],
252
+ 'rounded-l' => ['rounded-tl', 'rounded-bl'],
253
+ 'border-spacing' => ['border-spacing-x', 'border-spacing-y'],
254
+ 'border-w-all' => [],
255
+ 'border-w-x' => ['border-w-all'],
256
+ 'border-w-y' => ['border-w-all'],
257
+ 'border-w-t' => ['border-w-all', 'border-w-y'],
258
+ 'border-w-r' => ['border-w-all', 'border-w-x'],
259
+ 'border-w-b' => ['border-w-all', 'border-w-y'],
260
+ 'border-w-l' => ['border-w-all', 'border-w-x'],
261
+ 'border-color' => ['border-color-t', 'border-color-r', 'border-color-b', 'border-color-l'],
262
+ 'border-color-x' => ['border-color-r', 'border-color-l'],
263
+ 'border-color-y' => ['border-color-t', 'border-color-b'],
264
+ 'scroll-m' => ['scroll-mx', 'scroll-my', 'scroll-mt', 'scroll-mr', 'scroll-mb', 'scroll-ml'],
265
+ 'scroll-mx' => ['scroll-mr', 'scroll-ml'],
266
+ 'scroll-my' => ['scroll-mt', 'scroll-mb'],
267
+ 'scroll-p' => ['scroll-px', 'scroll-py', 'scroll-pt', 'scroll-pr', 'scroll-pb', 'scroll-pl'],
268
+ 'scroll-px' => ['scroll-pr', 'scroll-pl'],
269
+ 'scroll-py' => ['scroll-pt', 'scroll-pb'],
108
270
  ];
109
271
 
110
- /**
111
- * Merges multiple CSS class strings or arrays of CSS class strings into a single, optimized CSS class string.
112
- *
113
- * @param string|array ...$classes The CSS classes to be merged.
114
- * @return string A single CSS class string with duplicates and conflicts resolved.
115
- */
116
- public static function mergeClasses(string|array ...$classes): string
272
+ public static function merge(string ...$inputs): string
117
273
  {
118
- $classArray = [];
119
-
120
- foreach ($classes as $class) {
121
- // Handle arrays by flattening them into strings.
122
- $classList = is_array($class) ? $class : [$class];
123
- foreach ($classList as $item) {
124
- if (!empty(trim($item))) {
125
- // Split the classes by any whitespace characters.
126
- $splitClasses = preg_split("/\s+/", $item);
127
- foreach ($splitClasses as $individualClass) {
128
- $classKey = self::getClassGroup($individualClass);
129
-
130
- // If the class is non-responsive (no colon), remove any responsive variants for the same base.
131
- if (strpos($classKey, ':') === false) {
132
- $baseGroup = $classKey;
133
- foreach ($classArray as $existingKey => $existingClass) {
134
-
135
- if (
136
- is_string($existingKey) // make sure we have a string
137
- && $existingKey !== $baseGroup
138
- && substr($existingKey, -strlen($baseGroup)) === $baseGroup
139
- ) {
140
- unset($classArray[$existingKey]);
141
- }
142
- }
143
- }
144
-
145
- // Remove conflicting classes based on the conflict groups.
146
- $conflictingKeys = self::getConflictingKeys($classKey);
147
- foreach ($conflictingKeys as $key) {
148
- unset($classArray[$key]);
149
- }
150
-
151
- // Update the array, prioritizing the last occurrence.
152
- $classArray[$classKey] = $individualClass;
153
- }
274
+ return self::twMerge(...$inputs);
275
+ }
276
+
277
+ public static function twMerge(string|array ...$inputs): string
278
+ {
279
+ $allClasses = [];
280
+
281
+ foreach ($inputs as $input) {
282
+ if (is_array($input)) {
283
+ $allClasses = array_merge($allClasses, $input);
284
+ } else {
285
+ $classes = preg_split('/\s+/', trim($input));
286
+ $allClasses = array_merge($allClasses, array_filter($classes));
287
+ }
288
+ }
289
+
290
+ return self::mergeClassList($allClasses);
291
+ }
292
+
293
+ private static function mergeClassList(array $classes): string
294
+ {
295
+ $classGroupsInConflict = [];
296
+ $result = [];
297
+
298
+ foreach ($classes as $originalClass) {
299
+ if (empty(trim($originalClass))) {
300
+ continue;
301
+ }
302
+
303
+ $modifiersAndClass = self::parseClass($originalClass);
304
+ $modifiers = $modifiersAndClass['modifiers'];
305
+ $baseClass = $modifiersAndClass['baseClass'];
306
+ $hasImportantModifier = $modifiersAndClass['hasImportantModifier'];
307
+
308
+ $classGroup = self::getClassGroup($baseClass);
309
+ if (!$classGroup) {
310
+ $result[] = $originalClass;
311
+ continue;
312
+ }
313
+
314
+ $variantModifier = implode(':', $modifiers);
315
+ $modifierId = $hasImportantModifier ? $variantModifier . self::IMPORTANT_MODIFIER : $variantModifier;
316
+ $classGroupId = $modifierId . ':' . $classGroup;
317
+
318
+ $conflictGroups = self::getConflictingClassGroups($classGroup);
319
+
320
+ foreach ($conflictGroups as $group) {
321
+ $groupId = $modifierId . ':' . $group;
322
+ if (isset($classGroupsInConflict[$groupId])) {
323
+ unset($result[array_search($classGroupsInConflict[$groupId], $result)]);
154
324
  }
325
+ unset($classGroupsInConflict[$groupId]);
155
326
  }
327
+
328
+ $classGroupsInConflict[$classGroupId] = $originalClass;
329
+ $result[] = $originalClass;
330
+ }
331
+
332
+ return implode(' ', array_values($result));
333
+ }
334
+
335
+ private static function parseClass(string $className): array
336
+ {
337
+ $modifiers = [];
338
+ $hasImportantModifier = false;
339
+ $baseClass = $className;
340
+
341
+ if (str_starts_with($className, '!')) {
342
+ $hasImportantModifier = true;
343
+ $baseClass = substr($className, 1);
344
+ }
345
+
346
+ $parts = explode(':', $baseClass);
347
+ if (count($parts) > 1) {
348
+ $baseClass = array_pop($parts);
349
+ $modifiers = $parts;
156
350
  }
157
351
 
158
- // Combine the final classes into a single string.
159
- return implode(" ", array_values($classArray));
352
+ return [
353
+ 'modifiers' => $modifiers,
354
+ 'baseClass' => $baseClass,
355
+ 'hasImportantModifier' => $hasImportantModifier
356
+ ];
160
357
  }
161
358
 
162
- private static function getClassGroup($class)
359
+ private static function getClassGroup(string $className): ?string
163
360
  {
164
- // Match optional prefixes (responsive and variants).
165
- $pattern = '/^((?:[^:]+:)*)([^:]+)$/';
166
- if (preg_match($pattern, $class, $matches)) {
167
- $prefixes = $matches[1];
168
- $utilityClass = $matches[2];
169
-
170
- // Match the utilityClass against patterns.
171
- foreach (self::$classGroupPatterns as $groupKey => $regex) {
172
- if (preg_match($regex, $utilityClass)) {
173
- return $prefixes . $groupKey;
361
+ foreach (self::$classGroups as $groupName => $patterns) {
362
+ foreach ($patterns as $pattern) {
363
+ if (is_string($pattern) && str_starts_with($pattern, '/')) {
364
+ if (preg_match($pattern, $className)) {
365
+ return $groupName;
366
+ }
367
+ } else {
368
+ if ($pattern === $className) {
369
+ return $groupName;
370
+ }
174
371
  }
175
372
  }
176
- // If no match, use the full class.
177
- return $prefixes . $utilityClass;
178
373
  }
179
- // For classes without a recognizable prefix, return the class itself.
180
- return $class;
374
+ return null;
181
375
  }
182
376
 
183
- private static function getConflictingKeys($classKey)
377
+ private static function getConflictingClassGroups(string $classGroup): array
184
378
  {
185
- // Remove any responsive or variant prefixes.
186
- $baseClassKey = preg_replace("/^(?:[^:]+:)+/", "", $classKey);
187
- if (isset(self::$conflictGroups[$baseClassKey])) {
188
- $prefix = preg_replace("/" . preg_quote($baseClassKey, "/") . '$/', "", $classKey);
189
- return array_map(function ($conflict) use ($prefix) {
190
- return $prefix . $conflict;
191
- }, self::$conflictGroups[$baseClassKey]);
379
+ $conflicts = self::$conflictingClassGroups[$classGroup] ?? [];
380
+ $allConflicts = [$classGroup];
381
+
382
+ foreach ($conflicts as $conflict) {
383
+ $allConflicts[] = $conflict;
384
+ $nestedConflicts = self::getConflictingClassGroups($conflict);
385
+ $allConflicts = array_merge($allConflicts, $nestedConflicts);
192
386
  }
193
- return [$classKey];
387
+
388
+ return array_unique($allConflicts);
389
+ }
390
+
391
+ public static function mergeClasses(string|array ...$classes): string
392
+ {
393
+ return self::twMerge(...$classes);
194
394
  }
195
395
  }
@@ -193,8 +193,10 @@ class Request
193
193
  public static string $requestedWith = '';
194
194
 
195
195
  /**
196
- * Initialize the request by setting all static properties.
196
+ * @var string $remoteAddr Holds the remote address of the request.
197
197
  */
198
+ public static string $remoteAddr = '';
199
+
198
200
  public static function init(): void
199
201
  {
200
202
  self::$params = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
@@ -222,6 +224,7 @@ class Request
222
224
  self::$localStorage = self::getLocalStorage();
223
225
  self::$protocol = self::getProtocol();
224
226
  self::$documentUrl = self::$protocol . self::$domainName . self::$scriptName;
227
+ self::$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? 'Unknown';
225
228
  }
226
229
 
227
230
  /**