mado-ui 0.1.0

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.
Files changed (140) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +274 -0
  3. package/css/index.css +5829 -0
  4. package/dist/components/button.d.ts +21 -0
  5. package/dist/components/form/index.d.ts +30 -0
  6. package/dist/components/form/input/index.d.ts +36 -0
  7. package/dist/components/form/submit-button.d.ts +20 -0
  8. package/dist/components/ghost.d.ts +4 -0
  9. package/dist/components/heading.d.ts +11 -0
  10. package/dist/components/index.d.ts +8 -0
  11. package/dist/components/link.d.ts +51 -0
  12. package/dist/components/mado-ui-provider.d.ts +1 -0
  13. package/dist/components/modal.d.ts +19 -0
  14. package/dist/components/time.d.ts +16 -0
  15. package/dist/hooks/create-fast-context.d.ts +7 -0
  16. package/dist/hooks/index.d.ts +4 -0
  17. package/dist/hooks/use-anime-scope.d.ts +15 -0
  18. package/dist/hooks/use-form-context.d.ts +30 -0
  19. package/dist/hooks/use-form-status.d.ts +7 -0
  20. package/dist/icons/3-people.d.ts +2 -0
  21. package/dist/icons/3-rectangles-desktop-fill.d.ts +2 -0
  22. package/dist/icons/3-rectangles-desktop.d.ts +2 -0
  23. package/dist/icons/airplane.d.ts +2 -0
  24. package/dist/icons/arrow-triangle-2-circlepath-circle-fill.d.ts +2 -0
  25. package/dist/icons/arrow-triangle-2-circlepath-circle.d.ts +2 -0
  26. package/dist/icons/bag-fill.d.ts +2 -0
  27. package/dist/icons/banknote.d.ts +2 -0
  28. package/dist/icons/bell-fill.d.ts +2 -0
  29. package/dist/icons/bolt-car.d.ts +2 -0
  30. package/dist/icons/bolt-fill.d.ts +2 -0
  31. package/dist/icons/bolt-ring-closed.d.ts +2 -0
  32. package/dist/icons/bolt-trianglebadge-exclamationmark.d.ts +2 -0
  33. package/dist/icons/book-fill.d.ts +2 -0
  34. package/dist/icons/bookmark-fill.d.ts +2 -0
  35. package/dist/icons/briefcase-fill.d.ts +2 -0
  36. package/dist/icons/bubble-left-fill.d.ts +2 -0
  37. package/dist/icons/building-2-fill.d.ts +2 -0
  38. package/dist/icons/calendar.d.ts +2 -0
  39. package/dist/icons/camera-fill.d.ts +2 -0
  40. package/dist/icons/car-fill.d.ts +2 -0
  41. package/dist/icons/cart-fill.d.ts +2 -0
  42. package/dist/icons/chart-bar-doc-horizontal.d.ts +2 -0
  43. package/dist/icons/checkmark-seal.d.ts +2 -0
  44. package/dist/icons/checkmark.d.ts +2 -0
  45. package/dist/icons/chevron-compact-down.d.ts +2 -0
  46. package/dist/icons/chevron-down.d.ts +2 -0
  47. package/dist/icons/chevron-left-forwardslash-chevron-right.d.ts +2 -0
  48. package/dist/icons/chevron-left.d.ts +2 -0
  49. package/dist/icons/chevron-right.d.ts +2 -0
  50. package/dist/icons/chevron-up-chevron-down.d.ts +2 -0
  51. package/dist/icons/circle-fill.d.ts +2 -0
  52. package/dist/icons/clock-badge-checkmark.d.ts +2 -0
  53. package/dist/icons/clock-fill.d.ts +2 -0
  54. package/dist/icons/cloud-fill.d.ts +2 -0
  55. package/dist/icons/cube-fill.d.ts +2 -0
  56. package/dist/icons/curve-point-left.d.ts +2 -0
  57. package/dist/icons/dial-high.d.ts +2 -0
  58. package/dist/icons/doc-fill.d.ts +2 -0
  59. package/dist/icons/doc-on-clipboard.d.ts +2 -0
  60. package/dist/icons/doc-on-doc-fill.d.ts +2 -0
  61. package/dist/icons/doc-on-doc.d.ts +2 -0
  62. package/dist/icons/doc-text-magnifyingglass.d.ts +2 -0
  63. package/dist/icons/dollar-sign.d.ts +2 -0
  64. package/dist/icons/ellipsis-circle-fill.d.ts +2 -0
  65. package/dist/icons/ellipsis-circle.d.ts +2 -0
  66. package/dist/icons/envelope-fill.d.ts +2 -0
  67. package/dist/icons/envelope.d.ts +2 -0
  68. package/dist/icons/exclamationmark-octagon.d.ts +2 -0
  69. package/dist/icons/eye.d.ts +2 -0
  70. package/dist/icons/figure-water-fitness.d.ts +2 -0
  71. package/dist/icons/flag-fill.d.ts +2 -0
  72. package/dist/icons/flame-fill.d.ts +2 -0
  73. package/dist/icons/folder-fill.d.ts +2 -0
  74. package/dist/icons/folder.d.ts +2 -0
  75. package/dist/icons/gearshape-fill.d.ts +2 -0
  76. package/dist/icons/gearshape.d.ts +2 -0
  77. package/dist/icons/gift-fill.d.ts +2 -0
  78. package/dist/icons/globe-americas-fill.d.ts +2 -0
  79. package/dist/icons/hare-fill.d.ts +2 -0
  80. package/dist/icons/house-deskclock.d.ts +2 -0
  81. package/dist/icons/house-fill.d.ts +2 -0
  82. package/dist/icons/house.d.ts +2 -0
  83. package/dist/icons/index.d.ts +104 -0
  84. package/dist/icons/iphone-house.d.ts +2 -0
  85. package/dist/icons/light-ribbon.d.ts +2 -0
  86. package/dist/icons/lightbulb-fill.d.ts +2 -0
  87. package/dist/icons/lightbulb-led.d.ts +2 -0
  88. package/dist/icons/list-bullet-clipboard-fill.d.ts +2 -0
  89. package/dist/icons/magnifyingglass.d.ts +2 -0
  90. package/dist/icons/map-pin-ellipse.d.ts +2 -0
  91. package/dist/icons/minus-plus-batterblock.d.ts +2 -0
  92. package/dist/icons/network-shield.d.ts +2 -0
  93. package/dist/icons/network.d.ts +2 -0
  94. package/dist/icons/newspaper-fill.d.ts +2 -0
  95. package/dist/icons/number.d.ts +2 -0
  96. package/dist/icons/paperplane-fill.d.ts +2 -0
  97. package/dist/icons/person-crop-square.d.ts +2 -0
  98. package/dist/icons/person-fill-questionmark.d.ts +2 -0
  99. package/dist/icons/person-fill.d.ts +2 -0
  100. package/dist/icons/person.d.ts +2 -0
  101. package/dist/icons/phone-arrow-up-right.d.ts +2 -0
  102. package/dist/icons/phone-fill.d.ts +2 -0
  103. package/dist/icons/phone.d.ts +2 -0
  104. package/dist/icons/play-rectangle-fill.d.ts +2 -0
  105. package/dist/icons/plus.d.ts +2 -0
  106. package/dist/icons/qrcode.d.ts +2 -0
  107. package/dist/icons/rectangle-portrait-and-arrow-left-fill.d.ts +2 -0
  108. package/dist/icons/rectangle-portrait-and-arrow-left.d.ts +2 -0
  109. package/dist/icons/sensor.d.ts +2 -0
  110. package/dist/icons/signature.d.ts +2 -0
  111. package/dist/icons/solar-panel.d.ts +2 -0
  112. package/dist/icons/square-and-arrow-down-fill.d.ts +2 -0
  113. package/dist/icons/square-and-arrow-down.d.ts +2 -0
  114. package/dist/icons/square-and-arrow-up-fill.d.ts +2 -0
  115. package/dist/icons/square-and-arrow-up.d.ts +2 -0
  116. package/dist/icons/square-and-pencil-fill.d.ts +2 -0
  117. package/dist/icons/square-and-pencil.d.ts +2 -0
  118. package/dist/icons/text-bubble.d.ts +2 -0
  119. package/dist/icons/trash-fill.d.ts +2 -0
  120. package/dist/icons/trash.d.ts +2 -0
  121. package/dist/icons/tree.d.ts +2 -0
  122. package/dist/icons/umbrella-fill.d.ts +2 -0
  123. package/dist/icons/xmark.d.ts +2 -0
  124. package/dist/index.d.ts +3 -0
  125. package/dist/index.esm.js +1168 -0
  126. package/dist/index.esm.js.map +1 -0
  127. package/dist/index.js +1186 -0
  128. package/dist/index.js.map +1 -0
  129. package/dist/types/index.d.ts +2 -0
  130. package/dist/types/utils.d.ts +18 -0
  131. package/dist/utils/class-management.d.ts +29 -0
  132. package/dist/utils/custom-tailwind-merge.d.ts +4 -0
  133. package/dist/utils/get-date.d.ts +153 -0
  134. package/dist/utils/helpers.d.ts +2 -0
  135. package/dist/utils/index.d.ts +9 -0
  136. package/dist/utils/math.d.ts +1 -0
  137. package/dist/utils/regex.d.ts +12 -0
  138. package/dist/utils/string-manipulation.d.ts +17 -0
  139. package/dist/utils/tw-sort.d.ts +1 -0
  140. package/package.json +63 -0
@@ -0,0 +1,1168 @@
1
+ import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
+ import { extendTailwindMerge, twJoin } from 'tailwind-merge';
3
+ import { Children, isValidElement, Fragment, createContext, useContext, useSyncExternalStore, useRef, Suspense, useId, useEffect, useState, cloneElement } from 'react';
4
+ import { Button as Button$1, Field, Label, Input as Input$1, Description, Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';
5
+ import { createPortal } from 'react-dom';
6
+
7
+ const integerList = Array.from({ length: 100 }, (_, i) => `${i + 1}`);
8
+ const twMerge = extendTailwindMerge({
9
+ extend: {
10
+ theme: {
11
+ color: [
12
+ {
13
+ ui: [
14
+ 'red',
15
+ 'orange',
16
+ 'yellow',
17
+ 'green',
18
+ 'sky-blue',
19
+ 'blue',
20
+ 'violet',
21
+ 'magenta',
22
+ 'purple',
23
+ 'brown',
24
+ 'grey',
25
+ 'pink',
26
+ ],
27
+ },
28
+ ],
29
+ },
30
+ classGroups: {
31
+ animate: [
32
+ {
33
+ animate: [
34
+ 'bounce',
35
+ 'double-spin',
36
+ 'drop-in',
37
+ 'flip',
38
+ 'flip-again',
39
+ 'grid-rows',
40
+ 'heartbeat',
41
+ 'ping',
42
+ 'pulse',
43
+ 'slide-up',
44
+ 'spin',
45
+ 'wave',
46
+ ],
47
+ },
48
+ ],
49
+ 'animation-direction': [
50
+ {
51
+ 'animation-direction': ['normal', 'reverse', 'alternate', 'alternate-reverse'],
52
+ },
53
+ ],
54
+ 'animation-fill': [
55
+ {
56
+ 'animation-fill': ['none', 'forwards', 'backwards', 'both'],
57
+ },
58
+ ],
59
+ 'animation-iteration': [
60
+ {
61
+ 'animation-iteration': [...integerList, 'infinite'],
62
+ },
63
+ ],
64
+ 'animation-state': [
65
+ {
66
+ 'animation-state': ['running', 'paused'],
67
+ },
68
+ ],
69
+ 'grid-cols': [
70
+ {
71
+ 'grid-cols': ['0fr', '1fr'],
72
+ },
73
+ ],
74
+ 'grid-rows': [
75
+ {
76
+ 'grid-rows': ['0fr', '1fr'],
77
+ },
78
+ ],
79
+ transition: ['transition-rows'],
80
+ },
81
+ },
82
+ });
83
+
84
+ /** The current date as a Date object */
85
+ const d = new Date();
86
+ /** The current minute of the current hour */
87
+ const minutes = d.getMinutes();
88
+ /** The current year */
89
+ d.getFullYear();
90
+ /** An array of the names of month in order */
91
+ const monthNamesList = [
92
+ 'January',
93
+ 'February',
94
+ 'March',
95
+ 'April',
96
+ 'May',
97
+ 'June',
98
+ 'July',
99
+ 'August',
100
+ 'September',
101
+ 'October',
102
+ 'November',
103
+ 'December',
104
+ ];
105
+ /** An array of the names of the days of the week in order */
106
+ const weekdayNamesList = [
107
+ 'Sunday',
108
+ 'Monday',
109
+ 'Tuesday',
110
+ 'Wednesday',
111
+ 'Thursday',
112
+ 'Friday',
113
+ 'Saturday',
114
+ ];
115
+ /** The name of the current month */
116
+ getMonthName();
117
+ /** The name of the current day of the week */
118
+ getWeekdayName();
119
+ /**
120
+ * ### Get Date
121
+ * - Returns the date with two digits
122
+ * @param {number|Date} date The date to get date
123
+ * @returns {string} The date with two digits
124
+ */
125
+ function getDate(date = d) {
126
+ if (typeof date !== 'number')
127
+ date = date.getDate();
128
+ let formattedDate = date.toString();
129
+ if (formattedDate.length === 1)
130
+ formattedDate = `0${formattedDate}`;
131
+ return formattedDate;
132
+ }
133
+ /**
134
+ * ### Get Hours
135
+ * - Returns the hours with two digits
136
+ * @param {number|Date} hours The date to get hours
137
+ * @returns {string} The hours with two digits
138
+ */
139
+ function getHours(hours = d) {
140
+ if (typeof hours !== 'number')
141
+ hours = hours.getHours();
142
+ let formattedHours = hours.toString();
143
+ if (formattedHours.length === 1)
144
+ formattedHours = `0${formattedHours}`;
145
+ return formattedHours;
146
+ }
147
+ /**
148
+ * ### Get Milliseconds
149
+ * - Returns the milliseconds with two digits
150
+ * @param {number|Date} milliseconds The date to get milliseconds
151
+ * @returns {string} The milliseconds with two digits
152
+ */
153
+ function getMilliseconds(milliseconds = d) {
154
+ if (typeof milliseconds !== 'number')
155
+ milliseconds = milliseconds.getMilliseconds();
156
+ let formattedMilliseconds = minutes.toString();
157
+ if (formattedMilliseconds.length === 1)
158
+ formattedMilliseconds = `0${formattedMilliseconds}`;
159
+ return formattedMilliseconds;
160
+ }
161
+ /**
162
+ * ### Get Minutes
163
+ * - Returns the minutes with two digits
164
+ * @param {number|Date} minutes The date to get minutes
165
+ * @returns {string} The minutes with two digits
166
+ */
167
+ function getMinutes(minutes = d) {
168
+ if (typeof minutes !== 'number')
169
+ minutes = minutes.getMinutes();
170
+ let formattedMinutes = minutes.toString();
171
+ if (formattedMinutes.length === 1)
172
+ formattedMinutes = `0${formattedMinutes}`;
173
+ return formattedMinutes;
174
+ }
175
+ /**
176
+ * ### Get Month
177
+ * - Returns the month with two digits
178
+ * @param {number|Date} month The date to get month
179
+ * @returns {string} The month with two digits
180
+ */
181
+ function getMonth(month = d) {
182
+ if (typeof month !== 'number')
183
+ month = month.getMonth() + 1;
184
+ let formattedMonth = month.toString();
185
+ if (formattedMonth.length === 1)
186
+ formattedMonth = `0${formattedMonth}`;
187
+ return formattedMonth;
188
+ }
189
+ /**
190
+ * ### Get Month Name
191
+ * - Returns the name of the specified month
192
+ * @param {Date} date A Date object representing the month to get the name of the month from. (Preset to the current date)
193
+ * @returns {MonthName} The name of the specified month
194
+ */
195
+ function getMonthName(date = d) {
196
+ if (typeof date === 'number')
197
+ return monthNamesList[date];
198
+ return monthNamesList[date.getMonth()];
199
+ }
200
+ /**
201
+ * ### Get Seconds
202
+ * - Returns the seconds with two digits
203
+ * @param {number|Date} seconds The date to get seconds
204
+ * @returns {string} The seconds with two digits
205
+ */
206
+ function getSeconds(seconds = d) {
207
+ if (typeof seconds !== 'number')
208
+ seconds = seconds.getSeconds();
209
+ let formattedSeconds = seconds.toString();
210
+ if (formattedSeconds.length === 1)
211
+ formattedSeconds = `0${formattedSeconds}`;
212
+ return formattedSeconds;
213
+ }
214
+ /**
215
+ * ### Get Weekday Name
216
+ * - Returns the weekday name of the specified day
217
+ * @param {number | Date} weekday A Date object or number representing the day to get the weekday name from. (Preset to the current date)
218
+ * @returns {WeekdayName} The name of the specified weekday
219
+ */
220
+ function getWeekdayName(weekday = d) {
221
+ if (typeof weekday === 'number')
222
+ return weekdayNamesList[weekday];
223
+ // Return the name of the day of the week
224
+ return weekdayNamesList[weekday.getDay()];
225
+ }
226
+
227
+ function findComponentByType(children, componentType) {
228
+ const childrenArray = Children.toArray(children);
229
+ for (const child of childrenArray) {
230
+ if (isValidElement(child) && child.type === componentType)
231
+ return child;
232
+ }
233
+ for (const child of childrenArray) {
234
+ if (isValidElement(child)) {
235
+ if (child.type === Fragment && child.props.children) {
236
+ const found = findComponentByType(child.props.children, componentType);
237
+ if (found)
238
+ return found;
239
+ }
240
+ else if (child.props.children) {
241
+ const found = findComponentByType(child.props.children, componentType);
242
+ if (found)
243
+ return found;
244
+ }
245
+ }
246
+ }
247
+ return null;
248
+ }
249
+
250
+ function easeOutExpo(time, start, end, duration) {
251
+ return time == duration ? start + end : end * (-Math.pow(2, (-10 * time) / duration) + 1) + start;
252
+ }
253
+
254
+ const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
255
+ /**
256
+ * # Is Email
257
+ * Checks whether the specified string is in email format
258
+ */
259
+ function isEmail(email) {
260
+ return emailRegex.test(email);
261
+ }
262
+ const telRegex = /(?:\+1\s|1\s|)?\d{3}\.\d{3}\.\d{4}|(?:\+1\s|1\s|)?\d{3}-\d{3}-\d{4}|(?:\+1\s|1\s|)?\(\d{3}\) \d{3}-\d{4}|(?:\+1\s|1\s|\+1|1|)?\d{10}/;
263
+ /**
264
+ * # Is Phone Number
265
+ * Checks whether the specified string is in phone number format
266
+ */
267
+ function isPhoneNumber(tel) {
268
+ return telRegex.test(tel);
269
+ }
270
+
271
+ /**
272
+ * # Format Phone Number
273
+ * Converts any string containing at least 10 numbers to a formatted phone number
274
+ * @param {string} string
275
+ * @returns {string} string formatted (000) 000-0000
276
+ */
277
+ /**
278
+ * # To Lower Case
279
+ * Converts a string to lowercase, and offers easy string replacements for creating snake case, kebab case, or your own.
280
+ * @param str - The string to convert to lowercase.
281
+ * @param options - Configuration options.
282
+ * @param options[0] - The delimiter to split the string. Defaults to space.
283
+ * @param options[1] - The string to join the parts back together. Defaults to space.
284
+ * @returns The lowercase version of the input string, with the replacements, if provided.
285
+ */
286
+ function toLowerCase(str, [delimiter, joiner]) {
287
+ return str.toLowerCase().replaceAll(delimiter || ' ', joiner || ' ');
288
+ }
289
+
290
+ function twSort(className) {
291
+ return className;
292
+ }
293
+
294
+ function Anchor({ className, disabled, href, onClick, ref, target, rel, ...props }) {
295
+ const isExternal = `${href}`.startsWith('http'), hasHash = `${href}`.includes('#');
296
+ const handleClick = e => {
297
+ if (disabled)
298
+ return e.preventDefault();
299
+ onClick?.(e);
300
+ setTimeout(() => history.replaceState({}, document.title, location.pathname), 100);
301
+ };
302
+ return (jsx("a", { ref: ref, ...props, "aria-disabled": disabled, className: twMerge(className, disabled && 'pointer-events-none'), href: href, target: target || (isExternal ? '_blank' : '_self'), onClick: hasHash ? handleClick : onClick, rel: rel !== undefined
303
+ ? rel === 'nofollow'
304
+ ? `${rel} noreferrer noopener`
305
+ : `${rel} prefetch`
306
+ : isExternal
307
+ ? 'nofollow noreferrer noopener'
308
+ : 'prefetch' }));
309
+ }
310
+ // * Styles
311
+ const baseClasses = twSort('ease-exponential isolate inline-block cursor-pointer duration-300 after:absolute after:left-1/2 after:-z-10 after:-translate-x-1/2 after:duration-500 active:scale-95 active:after:opacity-100');
312
+ const lineStaticClasses = twJoin(baseClasses, 'after:border-1 whitespace-nowrap after:-bottom-0.5 after:w-[calc(100%+0.15rem)] after:rounded-full after:border-current');
313
+ const lineClasses = twJoin(lineStaticClasses, 'after:ease-exponential whitespace-nowrap transition-transform after:transition-transform');
314
+ const scaleXClasses = 'after:scale-x-0 pointer-fine:hover:after:scale-x-100 active:after:scale-x-100';
315
+ const scaleYClasses = 'after:scale-y-0 pointer-fine:hover:after:scale-y-100 active:after:scale-y-100';
316
+ const lineNormalClasses = twJoin([
317
+ lineClasses,
318
+ scaleYClasses,
319
+ 'pointer-fine:hover:after:translate-y-0 after:origin-bottom after:translate-y-0.5 active:after:translate-y-0',
320
+ ]);
321
+ const lineLtrClasses = twJoin([lineClasses, scaleXClasses, 'after:origin-left']);
322
+ const lineRtlClasses = twJoin([lineClasses, scaleXClasses, 'after:origin-right']);
323
+ const lineCenterClasses = twJoin([lineClasses, scaleXClasses]);
324
+ const lineLiftClasses = twJoin([
325
+ lineClasses,
326
+ scaleYClasses,
327
+ 'pointer-fine:hover:after:translate-y-0 pointer-fine:hover:after:scale-x-100 after:origin-bottom after:translate-y-1 after:scale-x-75 active:after:translate-y-0 active:after:scale-x-100',
328
+ ]);
329
+ const fillClasses = twJoin(baseClasses, 'after:ease-exponential pointer-fine:hover:text-zinc-50 whitespace-nowrap transition-[transform_color] after:top-1/2 after:h-[calc(100%+0.05rem)] after:w-[calc(100%+0.25rem)] after:-translate-y-1/2 after:rounded active:text-zinc-50');
330
+ // Define theme-specific fill color transition classes
331
+ const getFillColorTransitionClasses = (theme = 'blue') => {
332
+ switch (theme) {
333
+ case 'brown':
334
+ return twJoin(fillClasses, 'after:bg-ui-brown contrast-more:after:bg-ui-brown after:transition-transform');
335
+ case 'green':
336
+ return twJoin(fillClasses, 'after:bg-ui-green contrast-more:after:bg-ui-green after:transition-transform');
337
+ case 'grey':
338
+ return twJoin(fillClasses, 'after:bg-ui-grey contrast-more:after:bg-ui-grey after:transition-transform');
339
+ case 'sky-blue':
340
+ return twJoin(fillClasses, 'after:bg-ui-sky-blue contrast-more:after:bg-ui-sky-blue after:transition-transform');
341
+ case 'magenta':
342
+ return twJoin(fillClasses, 'after:bg-ui-magenta contrast-more:after:bg-ui-magenta after:transition-transform');
343
+ case 'neutral':
344
+ return twJoin(fillClasses, 'after:bg-zinc-700 after:transition-transform contrast-more:after:bg-zinc-700 dark:after:bg-zinc-300 dark:contrast-more:after:bg-zinc-300');
345
+ case 'orange':
346
+ return twJoin(fillClasses, 'after:bg-ui-orange contrast-more:after:bg-ui-orange after:transition-transform');
347
+ case 'pink':
348
+ return twJoin(fillClasses, 'after:bg-ui-pink contrast-more:after:bg-ui-pink after:transition-transform');
349
+ case 'primary':
350
+ return twJoin(fillClasses, 'after:bg-primary-500 contrast-more:after:bg-primary-500 after:transition-transform');
351
+ case 'purple':
352
+ return twJoin(fillClasses, 'after:bg-ui-purple contrast-more:after:bg-ui-purple after:transition-transform');
353
+ case 'red':
354
+ return twJoin(fillClasses, 'after:bg-ui-red contrast-more:after:bg-ui-red after:transition-transform');
355
+ case 'violet':
356
+ return twJoin(fillClasses, 'after:bg-ui-violet contrast-more:after:bg-ui-violet after:transition-transform');
357
+ case 'yellow':
358
+ return twJoin(fillClasses, 'after:bg-ui-yellow contrast-more:after:bg-ui-yellow after:transition-transform');
359
+ case 'blue':
360
+ default:
361
+ return twJoin(fillClasses, 'after:bg-ui-blue contrast-more:after:bg-ui-blue after:transition-transform');
362
+ }
363
+ };
364
+ // Define theme-specific fill center classes
365
+ const getFillCenterClasses = (theme = 'blue') => {
366
+ switch (theme) {
367
+ case 'brown':
368
+ return twJoin(fillClasses, 'after:bg-ui-brown/0 active:after:bg-ui-brown pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-brown after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
369
+ case 'green':
370
+ return twJoin(fillClasses, 'after:bg-ui-green/0 active:after:bg-ui-green pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-green after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
371
+ case 'grey':
372
+ return twJoin(fillClasses, 'after:bg-ui-grey/0 active:after:bg-ui-grey pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-grey after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
373
+ case 'sky-blue':
374
+ return twJoin(fillClasses, 'after:bg-ui-sky-blue/0 active:after:bg-ui-sky-blue pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-sky-blue after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
375
+ case 'magenta':
376
+ return twJoin(fillClasses, 'after:bg-ui-magenta/0 active:after:bg-ui-magenta pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-magenta after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
377
+ case 'neutral':
378
+ return twJoin(fillClasses, 'pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-zinc-700 dark:pointer-fine:hover:after:bg-zinc-300 after:scale-x-50 after:scale-y-[0.25] after:bg-zinc-700/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 active:after:bg-zinc-700 dark:after:bg-zinc-300/0 dark:active:after:bg-zinc-300');
379
+ case 'orange':
380
+ return twJoin(fillClasses, 'after:bg-ui-orange/0 active:after:bg-ui-orange pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-orange after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
381
+ case 'pink':
382
+ return twJoin(fillClasses, 'after:bg-ui-pink/0 active:after:bg-ui-pink pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-pink after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
383
+ case 'primary':
384
+ return twJoin(fillClasses, 'after:bg-primary-500/0 active:after:bg-primary-500 pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-primary-500 after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
385
+ case 'purple':
386
+ return twJoin(fillClasses, 'after:bg-ui-purple/0 active:after:bg-ui-purple pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-purple after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
387
+ case 'red':
388
+ return twJoin(fillClasses, 'after:bg-ui-red/0 active:after:bg-ui-red pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-red after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
389
+ case 'violet':
390
+ return twJoin(fillClasses, 'after:bg-ui-violet/0 active:after:bg-ui-violet pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-violet after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
391
+ case 'yellow':
392
+ return twJoin(fillClasses, 'after:bg-ui-yellow/0 active:after:bg-ui-yellow pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-yellow after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
393
+ case 'blue':
394
+ default:
395
+ return twJoin(fillClasses, 'after:bg-ui-blue/0 active:after:bg-ui-blue pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-ui-blue after:scale-x-50 after:scale-y-[0.25] after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100');
396
+ }
397
+ };
398
+ const multilineBaseClasses = twSort('bg-linear-to-r from-current to-current bg-no-repeat active:scale-95');
399
+ const multilineLineStaticClasses = 'underline';
400
+ const multilineNormalClasses = twSort('pointer-fine:hover:underline underline-offset-1 active:underline');
401
+ const multilineClasses = twJoin(multilineBaseClasses, 'ease-exponential duration-500');
402
+ const multilineLineClasses = twJoin(multilineClasses, 'bg-[position:0%_100%] px-px pb-px transition-[background-size]');
403
+ const multilineXClasses = twJoin(multilineLineClasses, 'pointer-fine:hover:bg-[size:100%_2px] bg-[size:0%_2px] focus-visible:bg-[size:100%_2px] active:bg-[size:100%_2px]');
404
+ const multilineLineRtlClasses = twJoin([multilineXClasses, 'bg-[position:100%_100%]']);
405
+ const multilineLineCenterClasses = twJoin([multilineXClasses, 'bg-[position:50%_100%]']);
406
+ const multilineLineLiftClasses = twJoin(multilineLineClasses, 'pointer-fine:hover:bg-[size:auto_2px] bg-[size:auto_0px] focus-visible:bg-[size:auto_2px] active:bg-[size:auto_2px]');
407
+ const multilineFillBaseClasses = twJoin(multilineBaseClasses, 'py-0.75 pointer-fine:hover:text-zinc-50 rounded px-0.5 focus-visible:text-zinc-50 active:text-zinc-50');
408
+ // Define theme-specific multiline fill color classes
409
+ const getMultilineFillColorClasses = (theme = 'blue') => {
410
+ switch (theme) {
411
+ case 'brown':
412
+ return twJoin(multilineFillBaseClasses, 'from-ui-brown to-ui-brown contrast-more:from-ui-brown contrast-more:to-ui-brown transition-[background-size_color]');
413
+ case 'green':
414
+ return twJoin(multilineFillBaseClasses, 'from-ui-green to-ui-green contrast-more:from-ui-green contrast-more:to-ui-green transition-[background-size_color]');
415
+ case 'grey':
416
+ return twJoin(multilineFillBaseClasses, 'from-ui-grey to-ui-grey contrast-more:from-ui-grey contrast-more:to-ui-grey transition-[background-size_color]');
417
+ case 'sky-blue':
418
+ return twJoin(multilineFillBaseClasses, 'from-ui-sky-blue to-ui-sky-blue contrast-more:from-ui-sky-blue contrast-more:to-ui-sky-blue transition-[background-size_color]');
419
+ case 'magenta':
420
+ return twJoin(multilineFillBaseClasses, 'from-ui-magenta to-ui-magenta contrast-more:from-ui-magenta contrast-more:to-ui-magenta transition-[background-size_color]');
421
+ case 'neutral':
422
+ return twJoin(multilineFillBaseClasses, 'from-zinc-700 to-zinc-700 transition-[background-size_color] contrast-more:from-zinc-700 contrast-more:to-zinc-700 dark:from-zinc-300 dark:to-zinc-300 dark:contrast-more:from-zinc-300 dark:contrast-more:to-zinc-300');
423
+ case 'orange':
424
+ return twJoin(multilineFillBaseClasses, 'from-ui-orange to-ui-orange contrast-more:from-ui-orange contrast-more:to-ui-orange transition-[background-size_color]');
425
+ case 'pink':
426
+ return twJoin(multilineFillBaseClasses, 'from-ui-pink to-ui-pink contrast-more:from-ui-pink contrast-more:to-ui-pink transition-[background-size_color]');
427
+ case 'primary':
428
+ return twJoin(multilineFillBaseClasses, 'from-primary-500 to-primary-500 contrast-more:from-primary-500 contrast-more:to-primary-500 transition-[background-size_color]');
429
+ case 'purple':
430
+ return twJoin(multilineFillBaseClasses, 'from-ui-purple to-ui-purple contrast-more:from-ui-purple contrast-more:to-ui-purple transition-[background-size_color]');
431
+ case 'red':
432
+ return twJoin(multilineFillBaseClasses, 'from-ui-red to-ui-red contrast-more:from-ui-red contrast-more:to-ui-red transition-[background-size_color]');
433
+ case 'violet':
434
+ return twJoin(multilineFillBaseClasses, 'from-ui-violet to-ui-violet contrast-more:from-ui-violet contrast-more:to-ui-violet transition-[background-size_color]');
435
+ case 'yellow':
436
+ return twJoin(multilineFillBaseClasses, 'from-ui-yellow to-ui-yellow contrast-more:from-ui-yellow contrast-more:to-ui-yellow transition-[background-size_color]');
437
+ case 'blue':
438
+ default:
439
+ return twJoin(multilineFillBaseClasses, 'from-ui-blue to-ui-blue contrast-more:from-ui-blue contrast-more:to-ui-blue transition-[background-size_color]');
440
+ }
441
+ };
442
+ // Define theme-specific multiline fill classes
443
+ const getMultilineFillClasses = (theme = 'blue') => {
444
+ switch (theme) {
445
+ case 'brown':
446
+ return twJoin(multilineFillBaseClasses, 'from-ui-brown/0 to-ui-brown/0 focus-visible:from-ui-brown focus-visible:to-ui-brown active:from-ui-brown active:to-ui-brown contrast-more:from-ui-brown/0 contrast-more:to-ui-brown/0 focus-visible:contrast-more:from-ui-brown focus-visible:contrast-more:to-ui-brown active:contrast-more:from-ui-brown active:contrast-more:to-ui-brown pointer-fine:hover:from-ui-brown pointer-fine:hover:to-ui-brown pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-brown pointer-fine:hover:contrast-more:to-ui-brown bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
447
+ case 'green':
448
+ return twJoin(multilineFillBaseClasses, 'from-ui-green/0 to-ui-green/0 focus-visible:from-ui-green focus-visible:to-ui-green active:from-ui-green active:to-ui-green contrast-more:from-ui-green/0 contrast-more:to-ui-green/0 focus-visible:contrast-more:from-ui-green focus-visible:contrast-more:to-ui-green active:contrast-more:from-ui-green active:contrast-more:to-ui-green pointer-fine:hover:from-ui-green pointer-fine:hover:to-ui-green pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-green pointer-fine:hover:contrast-more:to-ui-green bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
449
+ case 'grey':
450
+ return twJoin(multilineFillBaseClasses, 'from-ui-grey/0 to-ui-grey/0 focus-visible:from-ui-grey focus-visible:to-ui-grey active:from-ui-grey active:to-ui-grey contrast-more:from-ui-grey/0 contrast-more:to-ui-grey/0 focus-visible:contrast-more:from-ui-grey focus-visible:contrast-more:to-ui-grey active:contrast-more:from-ui-grey active:contrast-more:to-ui-grey pointer-fine:hover:from-ui-grey pointer-fine:hover:to-ui-grey pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-grey pointer-fine:hover:contrast-more:to-ui-grey bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
451
+ case 'sky-blue':
452
+ return twJoin(multilineFillBaseClasses, 'from-ui-sky-blue/0 to-ui-sky-blue/0 focus-visible:from-ui-sky-blue focus-visible:to-ui-sky-blue active:from-ui-sky-blue active:to-ui-sky-blue contrast-more:from-ui-sky-blue/0 contrast-more:to-ui-sky-blue/0 focus-visible:contrast-more:from-ui-sky-blue focus-visible:contrast-more:to-ui-sky-blue active:contrast-more:from-ui-sky-blue active:contrast-more:to-ui-sky-blue pointer-fine:hover:from-ui-sky-blue pointer-fine:hover:to-ui-sky-blue pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-sky-blue pointer-fine:hover:contrast-more:to-ui-sky-blue bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
453
+ case 'magenta':
454
+ return twJoin(multilineFillBaseClasses, 'from-ui-magenta/0 to-ui-magenta/0 focus-visible:from-ui-magenta focus-visible:to-ui-magenta active:from-ui-magenta active:to-ui-magenta contrast-more:from-ui-magenta/0 contrast-more:to-ui-magenta/0 focus-visible:contrast-more:from-ui-magenta focus-visible:contrast-more:to-ui-magenta active:contrast-more:from-ui-magenta active:contrast-more:to-ui-magenta pointer-fine:hover:from-ui-magenta pointer-fine:hover:to-ui-magenta pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-magenta pointer-fine:hover:contrast-more:to-ui-magenta bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
455
+ case 'neutral':
456
+ return twJoin(multilineFillBaseClasses, 'pointer-fine:hover:from-zinc-700 pointer-fine:hover:to-zinc-700 pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-zinc-700 pointer-fine:hover:contrast-more:to-zinc-700 dark:pointer-fine:hover:from-zinc-300 dark:pointer-fine:hover:to-zinc-300 dark:pointer-fine:hover:contrast-more:from-zinc-300 dark:pointer-fine:hover:contrast-more:to-zinc-300 from-zinc-700/0 to-zinc-700/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-zinc-700 focus-visible:to-zinc-700 focus-visible:bg-[size:100%_100%] active:from-zinc-700 active:to-zinc-700 active:bg-[size:100%_100%] contrast-more:from-zinc-700/0 contrast-more:to-zinc-700/0 focus-visible:contrast-more:from-zinc-700 focus-visible:contrast-more:to-zinc-700 active:contrast-more:from-zinc-700 active:contrast-more:to-zinc-700 dark:from-zinc-300/0 dark:to-zinc-300/0 dark:focus-visible:from-zinc-300 dark:focus-visible:to-zinc-300 dark:active:from-zinc-300 dark:active:to-zinc-300 dark:contrast-more:from-zinc-300/0 dark:contrast-more:to-zinc-300/0 dark:focus-visible:contrast-more:from-zinc-300 dark:focus-visible:contrast-more:to-zinc-300 dark:active:contrast-more:from-zinc-300 dark:active:contrast-more:to-zinc-300');
457
+ case 'orange':
458
+ return twJoin(multilineFillBaseClasses, 'from-ui-orange/0 to-ui-orange/0 focus-visible:from-ui-orange focus-visible:to-ui-orange active:from-ui-orange active:to-ui-orange contrast-more:from-ui-orange/0 contrast-more:to-ui-orange/0 focus-visible:contrast-more:from-ui-orange focus-visible:contrast-more:to-ui-orange active:contrast-more:from-ui-orange active:contrast-more:to-ui-orange pointer-fine:hover:from-ui-orange pointer-fine:hover:to-ui-orange pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-orange pointer-fine:hover:contrast-more:to-ui-orange bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
459
+ case 'pink':
460
+ return twJoin(multilineFillBaseClasses, 'from-ui-pink/0 to-ui-pink/0 focus-visible:from-ui-pink focus-visible:to-ui-pink active:from-ui-pink active:to-ui-pink contrast-more:from-ui-pink/0 contrast-more:to-ui-pink/0 focus-visible:contrast-more:from-ui-pink focus-visible:contrast-more:to-ui-pink active:contrast-more:from-ui-pink active:contrast-more:to-ui-pink pointer-fine:hover:from-ui-pink pointer-fine:hover:to-ui-pink pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-pink pointer-fine:hover:contrast-more:to-ui-pink bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
461
+ case 'primary':
462
+ return twJoin(multilineFillBaseClasses, 'from-primary-500/0 to-primary-500/0 focus-visible:from-primary-500 focus-visible:to-primary-500 active:from-primary-500 active:to-primary-500 contrast-more:from-primary-500/0 contrast-more:to-primary-500/0 focus-visible:contrast-more:from-primary-500 focus-visible:contrast-more:to-primary-500 active:contrast-more:from-primary-500 active:contrast-more:to-primary-500 pointer-fine:hover:from-primary-500 pointer-fine:hover:to-primary-500 pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-primary-500 pointer-fine:hover:contrast-more:to-primary-500 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
463
+ case 'purple':
464
+ return twJoin(multilineFillBaseClasses, 'from-ui-purple/0 to-ui-purple/0 focus-visible:from-ui-purple focus-visible:to-ui-purple active:from-ui-purple active:to-ui-purple contrast-more:from-ui-purple/0 contrast-more:to-ui-purple/0 focus-visible:contrast-more:from-ui-purple focus-visible:contrast-more:to-ui-purple active:contrast-more:from-ui-purple active:contrast-more:to-ui-purple pointer-fine:hover:from-ui-purple pointer-fine:hover:to-ui-purple pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-purple pointer-fine:hover:contrast-more:to-ui-purple bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
465
+ case 'red':
466
+ return twJoin(multilineFillBaseClasses, 'from-ui-red/0 to-ui-red/0 focus-visible:from-ui-red focus-visible:to-ui-red active:from-ui-red active:to-ui-red contrast-more:from-ui-red/0 contrast-more:to-ui-red/0 focus-visible:contrast-more:from-ui-red focus-visible:contrast-more:to-ui-red active:contrast-more:from-ui-red active:contrast-more:to-ui-red pointer-fine:hover:from-ui-red pointer-fine:hover:to-ui-red pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-red pointer-fine:hover:contrast-more:to-ui-red bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
467
+ case 'violet':
468
+ return twJoin(multilineFillBaseClasses, 'from-ui-violet/0 to-ui-violet/0 focus-visible:from-ui-violet focus-visible:to-ui-violet active:from-ui-violet active:to-ui-violet contrast-more:from-ui-violet/0 contrast-more:to-ui-violet/0 focus-visible:contrast-more:from-ui-violet focus-visible:contrast-more:to-ui-violet active:contrast-more:from-ui-violet active:contrast-more:to-ui-violet pointer-fine:hover:from-ui-violet pointer-fine:hover:to-ui-violet pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-violet pointer-fine:hover:contrast-more:to-ui-violet bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
469
+ case 'yellow':
470
+ return twJoin(multilineFillBaseClasses, 'from-ui-yellow/0 to-ui-yellow/0 focus-visible:from-ui-yellow focus-visible:to-ui-yellow active:from-ui-yellow active:to-ui-yellow contrast-more:from-ui-yellow/0 contrast-more:to-ui-yellow/0 focus-visible:contrast-more:from-ui-yellow focus-visible:contrast-more:to-ui-yellow active:contrast-more:from-ui-yellow active:contrast-more:to-ui-yellow pointer-fine:hover:from-ui-yellow pointer-fine:hover:to-ui-yellow pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-yellow pointer-fine:hover:contrast-more:to-ui-yellow bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
471
+ case 'blue':
472
+ default:
473
+ return twJoin(multilineFillBaseClasses, 'from-ui-blue/0 to-ui-blue/0 focus-visible:from-ui-blue focus-visible:to-ui-blue active:from-ui-blue active:to-ui-blue contrast-more:from-ui-blue/0 contrast-more:to-ui-blue/0 focus-visible:contrast-more:from-ui-blue focus-visible:contrast-more:to-ui-blue active:contrast-more:from-ui-blue active:contrast-more:to-ui-blue pointer-fine:hover:from-ui-blue pointer-fine:hover:to-ui-blue pointer-fine:hover:bg-[size:100%_100%] pointer-fine:hover:contrast-more:from-ui-blue pointer-fine:hover:contrast-more:to-ui-blue bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
474
+ }
475
+ };
476
+ const getMultilineFillLiftClasses = (theme = 'blue') => {
477
+ return twJoin(getMultilineFillColorClasses(theme), 'pointer-fine:hover:bg-[size:auto_100%] bg-[size:auto_0px] bg-[position:auto_100%] focus-visible:bg-[size:auto_100%] active:bg-[size:auto_100%]');
478
+ };
479
+ const getMultilineFillXClasses = (theme = 'blue') => {
480
+ return twJoin(getMultilineFillColorClasses(theme), 'pointer-fine:hover:bg-[size:100%_100%] bg-[size:0%_100%] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%]');
481
+ };
482
+ const getMultilineFillRtlClasses = (theme = 'blue') => {
483
+ return twJoin(getMultilineFillXClasses(theme), 'bg-[position:100%_auto]');
484
+ };
485
+ const getMultilineFillCenterClasses = (theme = 'blue') => {
486
+ return twJoin(getMultilineFillXClasses(theme), 'bg-[position:50%_auto]');
487
+ };
488
+ /**
489
+ * # Link
490
+ *
491
+ * - A component for rendering links with various styles and options.
492
+ * - Utilizes the Next.js `Link` component and provides additional functionality.
493
+ *
494
+ * ---
495
+ *
496
+ * ## Styles
497
+ *
498
+ * This component includes various classes to style the link. The styles are divided into two types:
499
+ *
500
+ * - Line styles: These styles add a line underneath the link, and include variations for different positions and orientations.
501
+ * - Fill styles: These styles add a background color behind the link, and include variations for different positions and orientations.
502
+ * - Multiline styles: These styles seek to accomplish the same as the line and fill styles, while offering multiline support.
503
+ *
504
+ * ---
505
+ *
506
+ * ## Examples
507
+ *
508
+ * @example
509
+ * <Link href='/about' type='ltr' title='About Us'>Learn more about our company</Link>
510
+ *
511
+ * @example
512
+ * <Link href='/about' type='fill-ltr' title='About Us'>Learn more about our company</Link>
513
+ *
514
+ * @example
515
+ * <Link href='/about' type='fill-ltr' theme='red' title='About Us'>Learn more about our company</Link>
516
+ */
517
+ function Link({ type, theme = 'blue', className, ref, ...props }) {
518
+ const getLinkClasses = () => {
519
+ switch (type) {
520
+ case 'static':
521
+ return lineStaticClasses;
522
+ case 'ltr':
523
+ return lineLtrClasses;
524
+ case 'rtl':
525
+ return lineRtlClasses;
526
+ case 'center':
527
+ return lineCenterClasses;
528
+ case 'lift':
529
+ return lineLiftClasses;
530
+ case 'fill':
531
+ return getFillCenterClasses(theme);
532
+ case 'fill-ltr':
533
+ return twJoin([getFillColorTransitionClasses(theme), scaleXClasses, 'after:origin-left']);
534
+ case 'fill-rtl':
535
+ return twJoin([getFillColorTransitionClasses(theme), scaleXClasses, 'after:origin-right']);
536
+ case 'fill-lift':
537
+ return twJoin([getFillColorTransitionClasses(theme), scaleYClasses, 'after:origin-bottom']);
538
+ case 'multiline':
539
+ return multilineNormalClasses;
540
+ case 'multiline-static':
541
+ return multilineLineStaticClasses;
542
+ case 'multiline-ltr':
543
+ return multilineXClasses;
544
+ case 'multiline-rtl':
545
+ return multilineLineRtlClasses;
546
+ case 'multiline-center':
547
+ return multilineLineCenterClasses;
548
+ case 'multiline-lift':
549
+ return multilineLineLiftClasses;
550
+ case 'multiline-fill':
551
+ return getMultilineFillClasses(theme);
552
+ case 'multiline-fill-ltr':
553
+ return getMultilineFillXClasses(theme);
554
+ case 'multiline-fill-rtl':
555
+ return getMultilineFillRtlClasses(theme);
556
+ case 'multiline-fill-center':
557
+ return getMultilineFillCenterClasses(theme);
558
+ case 'multiline-fill-lift':
559
+ return getMultilineFillLiftClasses(theme);
560
+ default:
561
+ return lineNormalClasses;
562
+ }
563
+ };
564
+ const linkClasses = getLinkClasses();
565
+ return jsx(Anchor, { ref: ref, ...props, className: twMerge(linkClasses, className) });
566
+ }
567
+
568
+ /**
569
+ * # Button
570
+ * - A pre-styled button with utility props for easy customization depending on use case.
571
+ */
572
+ function Button({ className, padding = 'md', rounded = 'lg', theme = 'primary', ref, ...props }) {
573
+ const getPaddingClasses = () => {
574
+ switch (padding) {
575
+ case 'xs':
576
+ return 'px-2 py-0.5';
577
+ case 'sm':
578
+ return 'px-4 py-1';
579
+ case 'md':
580
+ return 'px-6 py-1.5';
581
+ case 'lg':
582
+ return 'px-8 py-2';
583
+ case 'xl':
584
+ return 'px-12 py-3';
585
+ }
586
+ };
587
+ const getRoundedClasses = () => {
588
+ switch (rounded) {
589
+ case 'xs':
590
+ return 'rounded-sm';
591
+ case 'sm':
592
+ return 'rounded-md';
593
+ case 'md':
594
+ return 'rounded-lg';
595
+ case 'lg':
596
+ return 'rounded-xl';
597
+ case 'xl':
598
+ return 'rounded-3xl';
599
+ case 'full':
600
+ return 'rounded-full';
601
+ }
602
+ };
603
+ const getThemeClasses = () => {
604
+ switch (theme) {
605
+ case 'blue':
606
+ return twSort('before:bg-ui-blue shadow-ui-blue/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
607
+ case 'blue-gradient':
608
+ return twSort('bg-ui-blue shadow-ui-blue/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
609
+ case 'brown':
610
+ return twSort('before:bg-ui-brown shadow-ui-brown/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
611
+ case 'brown-gradient':
612
+ return twSort('bg-ui-brown shadow-ui-brown/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
613
+ case 'green':
614
+ return twSort('before:bg-ui-green shadow-ui-green/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
615
+ case 'green-gradient':
616
+ return twSort('bg-ui-green shadow-ui-green/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
617
+ case 'grey':
618
+ return twSort('before:bg-ui-grey shadow-ui-grey/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
619
+ case 'grey-gradient':
620
+ return twSort('bg-ui-grey shadow-ui-grey/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
621
+ case 'sky-blue':
622
+ return twSort('before:bg-ui-sky-blue shadow-ui-sky-blue/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
623
+ case 'sky-blue-gradient':
624
+ return twSort('bg-ui-sky-blue shadow-text-white lg shadow-ui-sky-blue/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
625
+ case 'magenta':
626
+ return twSort('before:bg-ui-magenta shadow-ui-magenta/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
627
+ case 'magenta-gradient':
628
+ return twSort('bg-ui-magenta shadow-ui-magenta/25 before:bg-linear-to-t active:before transition-transform:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white mix-blend-soft-light shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:text-white before:opacity-75');
629
+ case 'neutral':
630
+ return twSort('before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90text-white dark bg-zinc-200 text-black before:absolute before:inset-0 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90 dark:bg-zinc-800');
631
+ case 'neutral-gradient':
632
+ return twSort('bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 dark from-zinc-300 via-zinc-200 to-zinc-100 text-black before:transition-[filter] before:duration-300 active:before:brightness-90 dark:from-zinc-900 dark:via-zinc-800 dark:to-zinc-700');
633
+ case 'orange':
634
+ return twSort('before:bg-ui-orange shadow-ui-orange/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
635
+ case 'orange-gradient':
636
+ return twSort('bg-ui-orange shadow-ui-orange/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
637
+ case 'pink':
638
+ return twSort('before:bg-ui-pink shadow-ui-pink/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
639
+ case 'pink-gradient':
640
+ return twSort('bg-ui-pink shadow-ui-pink/25 before:bg-linear-to-t before:to-white/75/75 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
641
+ case 'primary-light':
642
+ return twSort('bg-primary-50 text-primary-600 active:bg-primary-600 active:text-primary-50 pointer-fine:hover:bg-primary-600 pointer-fine:hover:text-primary-50 pointer-fine:active:bg-primary-700 transition-[transform_background-color_color_box-shadow]');
643
+ case 'primary-gradient':
644
+ return twSort('bg-linear-to-t from-primary-700 via-primary-500 to-primary-300 bg-size-y-[200%] shadow-primary-600/25 pointer-fine:hover:[background-position:50%_0%] transition-[transform_background-position] [background-position:50%_50%] active:[background-position:50%_75%]');
645
+ case 'purple':
646
+ return twSort('before:bg-ui-purple shadow-ui-purple/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
647
+ case 'purple-gradient':
648
+ return twSort('bg-ui-purple shadow-ui-purple/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
649
+ case 'red':
650
+ return twSort('before:bg-ui-red shadow-ui-red/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
651
+ case 'red-gradient':
652
+ return twSort('bg-ui-red shadow-ui-red/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
653
+ case 'violet':
654
+ return twSort('before:bg-ui-violet shadow-ui-violet/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
655
+ case 'violet-gradient':
656
+ return twSort('bg-ui-violet shadow-ui-violet/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-white shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black/75 before:via-transparent before:to-white/75 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
657
+ case 'yellow':
658
+ return twSort('before:bg-ui-yellow shadow-ui-yellow/25 before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-black shadow-lg transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:transition-[filter] before:duration-300 active:before:brightness-90');
659
+ case 'yellow-gradient':
660
+ return twSort('bg-ui-yellow shadow-ui-yellow/25 before:bg-linear-to-t before:ease-exponential pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90 text-black shadow-lg transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:from-black before:via-black/50 before:to-white/50 before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 active:before:brightness-90');
661
+ case 'primary':
662
+ default:
663
+ return twSort('bg-primary-500 shadow-primary-700/25 active:bg-primary-600 pointer-fine:hover:bg-primary-400 pointer-fine:active:bg-primary-600 text-white shadow-lg transition-[transform_background-color_box-shadow]');
664
+ }
665
+ };
666
+ const paddingClasses = getPaddingClasses(), roundedClasses = getRoundedClasses(), themeClasses = getThemeClasses();
667
+ const buttonClasses = twMerge([
668
+ 'ease-exponential focus-visible:scale-101 pointer-fine:hover:scale-101 pointer-fine:active:scale-99 block w-fit min-w-fit text-center font-semibold duration-300 active:scale-95',
669
+ paddingClasses,
670
+ roundedClasses,
671
+ themeClasses,
672
+ className,
673
+ ]);
674
+ return 'href' in props && typeof props.href === 'string' ? (jsx(Anchor, { ref: ref, ...props, className: buttonClasses })) : (jsx(Button$1, { ref: ref, ...props, className: buttonClasses }));
675
+ }
676
+
677
+ function createFastContext(defaultInitialState) {
678
+ function useStoreData(initialState = defaultInitialState) {
679
+ const store = useRef(initialState), get = () => store.current, subscribers = useRef(new Set());
680
+ const set = (value) => {
681
+ if (typeof value === 'function') {
682
+ store.current = value(store.current);
683
+ }
684
+ else {
685
+ store.current = value;
686
+ }
687
+ subscribers.current.forEach(callback => callback());
688
+ };
689
+ const subscribe = (callback) => {
690
+ subscribers.current.add(callback);
691
+ return () => subscribers.current.delete(callback);
692
+ };
693
+ return {
694
+ get,
695
+ set,
696
+ subscribe,
697
+ };
698
+ }
699
+ const StoreContext = createContext(null);
700
+ function Provider({ initialValue = defaultInitialState, ...props }) {
701
+ return jsx(StoreContext.Provider, { value: useStoreData(initialValue), ...props });
702
+ }
703
+ function useStore(selector, initialValue) {
704
+ const store = useContext(StoreContext);
705
+ if (!store) {
706
+ const localStoreValue = initialValue !== undefined ? initialValue : defaultInitialState;
707
+ const selectedValue = selector(localStoreValue);
708
+ const noOpSet = () => console.warn('Attempting to set store value outside of Provider');
709
+ return [selectedValue, noOpSet];
710
+ }
711
+ const state = useSyncExternalStore(store.subscribe, () => selector(store.get()), () => selector(initialValue !== undefined ? initialValue : defaultInitialState));
712
+ return [state, store.set];
713
+ }
714
+ return {
715
+ Provider,
716
+ useStore,
717
+ };
718
+ }
719
+
720
+ /**
721
+ * # Define Field
722
+ *
723
+ * This is a helper function to define a field in a form context with type safety.
724
+ */
725
+ function defineField(fieldDefinition) {
726
+ return fieldDefinition;
727
+ }
728
+ const { Provider: Provider$1, useStore: useStore$1 } = createFastContext([]);
729
+ function FormContextProvider({ children }) {
730
+ return jsx(Provider$1, { children: children });
731
+ }
732
+ function useFormContext() {
733
+ return useStore$1(store => store);
734
+ }
735
+
736
+ const DEFAULT_STATUS = 'incomplete';
737
+ const { Provider, useStore } = createFastContext(DEFAULT_STATUS);
738
+ function FormStatusProvider({ children, initialStatus = DEFAULT_STATUS, }) {
739
+ return (jsx(Suspense, { children: jsx(Provider, { initialValue: initialStatus, children: children }) }));
740
+ }
741
+ function useFormStatus() {
742
+ return useStore(store => store);
743
+ }
744
+
745
+ function validateField(value, { required, type }) {
746
+ const noValue = !value || value === '';
747
+ if (!required && noValue)
748
+ return true;
749
+ if (noValue)
750
+ return false;
751
+ switch (type) {
752
+ case 'email':
753
+ return isEmail(value);
754
+ case 'number':
755
+ return !isNaN(Number(value));
756
+ case 'tel':
757
+ return isPhoneNumber(value);
758
+ default:
759
+ return true;
760
+ }
761
+ }
762
+ function Input({ checked, className, defaultValue, description, descriptionProps, disabled, fieldProps, invalid = true, label, labelProps, name, onChange, placeholder, ref, required = true, type, value, ...props }) {
763
+ const [formContext, setFormContext] = useFormContext(), [, setFormStatus] = useFormStatus();
764
+ if (placeholder === '*')
765
+ placeholder = name + (required && !label ? '*' : '');
766
+ if (label === '*')
767
+ label = name;
768
+ const uniqueID = useId(), fieldContextID = toLowerCase(name, [, '_']) + '§' + uniqueID;
769
+ if (Boolean(formContext?.find(field => field.id === fieldContextID)?.invalid))
770
+ invalid = true;
771
+ const getFieldContextType = () => {
772
+ switch (type) {
773
+ case 'email':
774
+ return 'email';
775
+ case 'file':
776
+ return 'file';
777
+ case 'number':
778
+ return 'number';
779
+ case 'tel':
780
+ return 'tel';
781
+ case 'url':
782
+ return 'url';
783
+ default:
784
+ return 'string';
785
+ }
786
+ };
787
+ const fieldContextType = getFieldContextType();
788
+ const fieldContext = defineField({
789
+ type: fieldContextType,
790
+ id: fieldContextID,
791
+ invalid,
792
+ name,
793
+ required,
794
+ value: value ? `${value}` : defaultValue ? `${defaultValue}` : '',
795
+ });
796
+ useEffect(() => {
797
+ if (!setFormContext)
798
+ return;
799
+ setFormContext(prevContext => {
800
+ const otherFields = (prevContext || []).filter(field => field.id !== fieldContext.id);
801
+ return [...otherFields, fieldContext];
802
+ });
803
+ return () => {
804
+ setFormContext(prevContext => (prevContext || []).filter(field => field.id !== fieldContext.id));
805
+ };
806
+ }, [setFormContext]);
807
+ const debounceTimerRef = useRef(undefined);
808
+ const handleChange = e => {
809
+ if (disabled) {
810
+ e.preventDefault();
811
+ return;
812
+ }
813
+ clearTimeout(debounceTimerRef.current);
814
+ const { currentTarget } = e, { value: newValue } = currentTarget;
815
+ setFormContext?.(prevContext => {
816
+ if (!prevContext)
817
+ return [];
818
+ const field = prevContext.find(({ id: fieldID }) => fieldID === fieldContext.id);
819
+ if (!field)
820
+ throw new Error(`Field with id "${fieldContext.id}" not found in form context.`);
821
+ const otherFields = prevContext.filter(({ id: fieldID }) => fieldID !== fieldContext.id);
822
+ const updatedField = { ...field, value: newValue };
823
+ return [...otherFields, updatedField];
824
+ });
825
+ debounceTimerRef.current = setTimeout(() => {
826
+ const field = formContext?.find(({ id: fieldID }) => fieldID === fieldContext.id);
827
+ if (!field)
828
+ return;
829
+ const invalid = validateField(newValue, field) === false;
830
+ if (invalid !== field.invalid)
831
+ setFormContext?.(prevContext => {
832
+ if (!prevContext)
833
+ return [];
834
+ const field = prevContext.find(({ id: fieldID }) => fieldID === fieldContext.id);
835
+ if (!field)
836
+ throw new Error(`Field with id "${fieldContext.id}" not found in form context.`);
837
+ const otherFields = prevContext.filter(({ id: fieldID }) => fieldID !== fieldContext.id);
838
+ const updatedField = { ...field, invalid };
839
+ return [...otherFields, updatedField];
840
+ });
841
+ }, 500);
842
+ onChange?.(e);
843
+ };
844
+ const restFieldProps = fieldProps
845
+ ? Object.fromEntries(Object.entries(fieldProps).filter(([key]) => key !== 'className'))
846
+ : {};
847
+ const restLabelProps = labelProps
848
+ ? Object.fromEntries(Object.entries(labelProps).filter(([key]) => key !== 'className'))
849
+ : {};
850
+ const restDescriptionProps = descriptionProps
851
+ ? Object.fromEntries(Object.entries(descriptionProps).filter(([key]) => key !== 'className'))
852
+ : {};
853
+ return (jsxs(Field, { ...restFieldProps, className: bag => twMerge('grid gap-1', typeof fieldProps?.className === 'function' ? fieldProps?.className(bag) : fieldProps?.className), disabled: disabled, children: [label && (jsx(Label, { ...restLabelProps, className: bag => twMerge('text-sm font-medium', required ? 'after:text-ui-red after:content-["_*"]' : '', typeof labelProps?.className === 'function' ? labelProps?.className(bag) : labelProps?.className), children: label })), jsx(Input$1, { ...props, className: bag => twMerge('pointer-fine:hover:bg-neutral-50 dark:pointer-fine:hover:bg-neutral-600 pointer-fine:active:bg-neutral-200 dark:pointer-fine:active:bg-neutral-800 border-1 outline-ui-sky-blue/95 focus-visible:outline-3 ease-exponential rounded-xl border-neutral-500/50 bg-neutral-100 py-1 pl-2 text-neutral-950 outline-offset-1 transition-[background-color] duration-300 focus-visible:bg-neutral-50 active:bg-neutral-200 dark:bg-neutral-700 dark:text-neutral-50 dark:focus-visible:bg-neutral-600 dark:active:bg-neutral-800', typeof className === 'function' ? className(bag) : className), invalid: invalid, onChange: handleChange, placeholder: placeholder, ref: ref, type: type }), description && (jsx(Description, { ...restDescriptionProps, className: bag => twMerge('text-xs', typeof descriptionProps?.className === 'function'
854
+ ? descriptionProps?.className(bag)
855
+ : descriptionProps?.className), children: description }))] }));
856
+ }
857
+
858
+ function SubmitButton({ children, className, 'aria-disabled': ariaDisabled, error, incomplete, loading, success, theme, type = 'submit', ref, ...props }) {
859
+ const [formStatus] = useFormStatus();
860
+ const getDisabledStatus = () => {
861
+ if (ariaDisabled !== undefined)
862
+ return ariaDisabled;
863
+ if (formStatus !== 'ready')
864
+ return 'true';
865
+ return 'false';
866
+ };
867
+ const disabled = getDisabledStatus();
868
+ const getFormStatusButtonClasses = () => {
869
+ switch (formStatus) {
870
+ case 'loading':
871
+ return twSort('animate-pulse cursor-wait text-lg font-black leading-6 tracking-widest');
872
+ case 'error':
873
+ case 'success':
874
+ return 'cursor-not-allowed';
875
+ default:
876
+ return undefined;
877
+ }
878
+ };
879
+ const formStatusButtonClasses = getFormStatusButtonClasses();
880
+ const getFormStatusButtonTheme = () => {
881
+ switch (formStatus) {
882
+ case 'incomplete':
883
+ return 'grey';
884
+ case 'loading':
885
+ return 'blue';
886
+ case 'error':
887
+ return 'red';
888
+ case 'success':
889
+ return 'green';
890
+ default:
891
+ return theme;
892
+ }
893
+ };
894
+ const formStatusButtonTheme = getFormStatusButtonTheme();
895
+ const getButtonText = () => {
896
+ switch (formStatus) {
897
+ case 'incomplete':
898
+ return incomplete || 'Complete Form';
899
+ case 'loading':
900
+ return (loading || (jsxs(Fragment$1, { children: [jsx("span", { className: 'animate-wave animation-delay-300 inline-block', children: "\u2022" }), jsx("span", { className: 'animate-wave animation-delay-150 inline-block', children: "\u2022" }), jsx("span", { className: 'animate-wave inline-block', children: "\u2022" })] })));
901
+ case 'error':
902
+ return (jsxs(Fragment$1, { children: [error || 'Error', ' ', jsx("span", { className: 'absolute top-1/2 ml-1.5 translate-y-[calc(-50%-1.5px)] text-2xl', children: "\u00D7" })] }));
903
+ case 'success':
904
+ return success || 'Successfully Submitted';
905
+ default:
906
+ return children || 'Submit';
907
+ }
908
+ };
909
+ const buttonText = getButtonText();
910
+ return (jsx(Button, { ...props, ...(disabled === 'true' ? { 'aria-disabled': 'true', disabled: true } : {}), className: twMerge([formStatusButtonClasses, 'w-full', className]), ref: ref, theme: formStatusButtonTheme, type: type, children: buttonText }));
911
+ }
912
+
913
+ // import { findComponentByType } from '../../utils'
914
+ function FormComponent({ as, children, className, handleSubmit, onError, onSubmit, onSuccess, ...props }) {
915
+ const [formContext] = useFormContext(), [formStatus, setFormStatus] = useFormStatus();
916
+ // const submitButton = findComponentByType(children, SubmitButton)
917
+ useEffect(() => {
918
+ if (!formContext)
919
+ return;
920
+ if (formStatus !== 'incomplete' && formContext.find(({ invalid }) => invalid))
921
+ setFormStatus?.('incomplete');
922
+ if (formStatus !== 'ready' && formContext.every(({ invalid }) => !invalid))
923
+ setFormStatus?.('ready');
924
+ }, [formContext]);
925
+ const processSubmit = handleSubmit ||
926
+ (async (e) => {
927
+ e.preventDefault();
928
+ e.stopPropagation();
929
+ setFormStatus?.('loading');
930
+ const response = await onSubmit?.({ event: e, formContext });
931
+ if (response && ('error' in response || response.status === 'error')) {
932
+ setFormStatus?.('error');
933
+ onError?.({ event: e, error: response.error || 'An error occurred when submitting the form.' });
934
+ return;
935
+ }
936
+ if ((response && response.status === 'success') || !response) {
937
+ setFormStatus?.('success');
938
+ onSuccess?.({ event: e });
939
+ }
940
+ });
941
+ const FormElement = as || 'form';
942
+ return (jsxs(FormElement, { ...props, className: twMerge(className, 'grid gap-3'), onSubmit: processSubmit, children: [jsx("span", { className: 'block text-xl font-black', children: formStatus }), children] }));
943
+ }
944
+ function Form({ controlled = 'auto', initialStatus = 'incomplete', ...props }) {
945
+ const FormContextOrNotProvider = controlled === 'auto' ? FormContextProvider : Fragment;
946
+ return (jsx(FormStatusProvider, { initialStatus: initialStatus, children: jsx(FormContextOrNotProvider, { children: jsx(FormComponent, { ...props }) }) }));
947
+ }
948
+
949
+ function Ghost({ children, className, ...props }) {
950
+ return (jsx("div", { ...props, className: twMerge('block w-24 max-w-full animate-pulse rounded bg-white/50', className), children: children || jsx(Fragment$1, { children: "\u00A0" }) }));
951
+ }
952
+
953
+ function getTextFromChildren(children) {
954
+ let text = '';
955
+ Children.forEach(children, child => {
956
+ if (typeof child === 'string' || typeof child === 'number') {
957
+ text += child;
958
+ }
959
+ else if (isValidElement(child)) {
960
+ text += getTextFromChildren(child.props.children);
961
+ }
962
+ });
963
+ return text;
964
+ }
965
+ /**
966
+ * # Heading
967
+ * A heading component that renders HTML heading elements (h1-h6) with appropriate styling.
968
+ * Automatically generates an ID for the heading based on its content if none is provided.
969
+ */
970
+ function Heading({ as = 'h2', children, className, id, ref, ...props }) {
971
+ const H = as;
972
+ const targetableID = id || getTextFromChildren(children).replace(/\s+/g, '-').toLowerCase();
973
+ const getBaseClasses = () => {
974
+ switch (as) {
975
+ case 'h1':
976
+ return twSort('pb-2.5 text-6xl font-black last:pb-0');
977
+ case 'h3':
978
+ return twSort('pb-2 text-4xl font-extralight last:pb-0');
979
+ case 'h4':
980
+ return twSort('pb-2 text-3xl font-extrabold last:pb-0');
981
+ case 'h5':
982
+ return twSort('pb-1.5 text-2xl font-semibold last:pb-0');
983
+ case 'h6':
984
+ return twSort('pb-1 text-xl font-bold last:pb-0');
985
+ default:
986
+ return twSort('pb-2.5 text-5xl font-medium last:pb-0');
987
+ }
988
+ };
989
+ const baseClasses = getBaseClasses();
990
+ return (jsx(H, { ref: ref, id: targetableID, ...props, className: twMerge(baseClasses, className), children: children }));
991
+ }
992
+
993
+ function xmark(props) {
994
+ return (jsx("svg", { viewBox: '0 0 64 64', ...props, children: jsx("path", { d: 'M1,63c0.7,0.7,1.6,1,2.6,1s1.9-0.3,2.6-1L32,37.1L57.8,63c0.7,0.7,1.5,1,2.5,1c1,0,1.9-0.3,2.6-1c0.7-0.7,1-1.6,1-2.6 c0-1-0.3-1.8-1-2.5L37.1,32L63,6.2c0.7-0.7,1-1.6,1-2.6S63.7,1.7,63,1c-0.7-0.7-1.6-1-2.6-1c-1,0-1.8,0.3-2.5,1L32,26.9L6.2,1 C5.5,0.3,4.6,0,3.6,0C2.6,0,1.7,0.3,1,1C0.3,1.7,0,2.6,0,3.6c0,1,0.3,1.9,1,2.6L26.9,32L1,57.8c-0.7,0.7-1,1.5-1,2.6 C0,61.4,0.3,62.3,1,63z' }) }));
995
+ }
996
+
997
+ function ModalTrigger({ as, ...props }) {
998
+ const Element = as || Button$1;
999
+ return jsx(Element, { ...props });
1000
+ }
1001
+ function ModalDialog(props) {
1002
+ return jsx("div", { ...props });
1003
+ }
1004
+ function Modal({ children, className, onClose, onOpen, place = 'bottom' }) {
1005
+ const [bodyElement, setBodyElement] = useState(null);
1006
+ useEffect(() => {
1007
+ if (!bodyElement && typeof window !== 'undefined')
1008
+ setBodyElement(document.body);
1009
+ }, [bodyElement]);
1010
+ const [isOpen, setIsOpen] = useState(false);
1011
+ const dialogPanelRef = useRef(null), dragMoveBoxRef = useRef(null),
1012
+ // lastTouchYRef = useRef(0),
1013
+ startDragCoords = useRef({ x: 0, y: 0 });
1014
+ const [allowDragClose, setAllowDragClose] = useState(false), [readyToClose, setReadyToClose] = useState(false);
1015
+ const openModal = () => {
1016
+ console.log('open');
1017
+ setIsOpen(true);
1018
+ onOpen?.();
1019
+ };
1020
+ const closeModal = () => {
1021
+ console.log('close');
1022
+ setIsOpen(false);
1023
+ onClose?.();
1024
+ };
1025
+ const enableClose = (clientX, clientY) => {
1026
+ startDragCoords.current.x = clientX;
1027
+ startDragCoords.current.y = clientY;
1028
+ dialogPanelRef.current.style.transitionDuration = '0s';
1029
+ setAllowDragClose(true);
1030
+ };
1031
+ const enableTouchClose = e => {
1032
+ const { touches } = e, touch = touches[0], { clientY } = touch;
1033
+ enableClose(0, clientY);
1034
+ };
1035
+ const enableMouseClose = e => {
1036
+ const { clientX, clientY } = e;
1037
+ enableClose(clientX, clientY);
1038
+ };
1039
+ const handleMove = (clientX, clientY) => {
1040
+ if (!dialogPanelRef.current)
1041
+ return;
1042
+ let deltaX = clientX - startDragCoords.current.x, deltaY = clientY - startDragCoords.current.y;
1043
+ if (deltaX > 0)
1044
+ deltaX = easeOutExpo(Math.abs(deltaX), 0, 25, 5000);
1045
+ if (deltaX < 0)
1046
+ deltaX = -easeOutExpo(Math.abs(deltaX), 0, 25, 5000);
1047
+ if (deltaY < 0)
1048
+ deltaY = -easeOutExpo(Math.abs(deltaY), 0, 25, 2000);
1049
+ if (deltaY >= 100 && !readyToClose) {
1050
+ setReadyToClose(true);
1051
+ }
1052
+ else if (deltaY < 100 && readyToClose) {
1053
+ setReadyToClose(false);
1054
+ }
1055
+ const greaterThanMediaSmall = innerWidth > 640;
1056
+ dialogPanelRef.current.style.translate = `calc(-50% + ${deltaX}px) ${greaterThanMediaSmall ? `calc(-50% + ${deltaY}px)` : `${deltaY}px`}`;
1057
+ };
1058
+ const handleMouseMove = e => {
1059
+ if (!allowDragClose)
1060
+ return;
1061
+ const { clientX, clientY } = e;
1062
+ handleMove(clientX, clientY);
1063
+ };
1064
+ const disableDragClose = (clientY) => {
1065
+ const deltaY = clientY - startDragCoords.current.y;
1066
+ dialogPanelRef.current.style.transitionDuration = '';
1067
+ if (deltaY >= 100) {
1068
+ closeModal();
1069
+ setReadyToClose(false);
1070
+ }
1071
+ else {
1072
+ setTimeout(() => (dialogPanelRef.current.style.removeProperty('translate'), 50));
1073
+ }
1074
+ };
1075
+ const disableMouseDragClose = e => {
1076
+ if (allowDragClose)
1077
+ setAllowDragClose(false);
1078
+ const { clientY } = e;
1079
+ disableDragClose(clientY);
1080
+ };
1081
+ const content = typeof children === 'function' ? children({ openModal, closeModal }) : children;
1082
+ const dialogElement = findComponentByType(content, ModalDialog);
1083
+ if (!dialogElement)
1084
+ throw new Error('ModalDialog must be defined in Modal children');
1085
+ let triggerElement = null;
1086
+ if (typeof children !== 'function') {
1087
+ triggerElement = findComponentByType(content, ModalTrigger);
1088
+ if (!triggerElement)
1089
+ throw new Error('ModalTrigger must be provided when not using render prop pattern');
1090
+ }
1091
+ else {
1092
+ triggerElement = findComponentByType(content, ModalTrigger);
1093
+ }
1094
+ return (jsxs(Fragment$1, { children: [allowDragClose &&
1095
+ bodyElement &&
1096
+ createPortal(jsx("div", { ref: dragMoveBoxRef, className: 'z-99 pointer-coarse:hidden fixed inset-0 h-dvh w-screen bg-transparent active:cursor-grabbing', onMouseMove: handleMouseMove, onMouseUp: disableMouseDragClose }), bodyElement), triggerElement &&
1097
+ cloneElement(triggerElement, { onClick: openModal }), jsxs(Dialog, { open: isOpen, onClose: closeModal, className: [
1098
+ 'isolate z-50',
1099
+ place === 'bottom' &&
1100
+ 'after:fixed after:inset-x-0 after:bottom-0 after:-z-10 after:h-16 after:bg-neutral-50 sm:after:hidden',
1101
+ ].join(' '), children: [jsx(DialogBackdrop, { transition: true, className: [
1102
+ 'duration-750 ease-exponential data-closed:opacity-0 fixed inset-0 cursor-pointer transition-[opacity_background-color_backdrop-filter_-webkit-backdrop-filter] delay-100',
1103
+ readyToClose
1104
+ ? 'bg-neutral-50/5 backdrop-blur-[1px] dark:bg-neutral-950/5'
1105
+ : 'bg-neutral-50/25 backdrop-blur-sm dark:bg-neutral-950/25',
1106
+ ].join(' '), children: jsx(Button, { theme: 'blue', padding: 'none', rounded: 'full', className: 'group/button pointer-fine:hover:w-20 fixed right-4 top-4 h-7 w-7 overflow-x-hidden transition-[scale_width_filter]', children: jsxs("div", { className: 'pointer-fine:group-hover/button:-translate-x-0.5 ease-exponential absolute right-1 top-1 flex items-center gap-1 pt-px transition-transform duration-300', children: [jsxs("span", { className: 'block text-xs font-medium uppercase leading-none text-neutral-50', children: ["Close", jsx("span", { className: 'sr-only', children: " Modal" })] }), jsx(xmark, { className: '-top-px block size-5 rotate-90 scale-75 fill-white stroke-white stroke-1 transition-transform duration-300 ease-in-out group-hover/button:rotate-0' })] }) }) }), jsxs(DialogPanel, { ref: dialogPanelRef, transition: true, className: twMerge('duration-750 ease-exponential data-closed:opacity-0 data-closed:scale-50 fixed left-1/2 -translate-x-1/2 overflow-y-scroll bg-neutral-50 p-4 shadow-[0_-15px_50px_-12px] shadow-neutral-950/25 transition-[transform_translate_opacity] sm:w-[calc(100vw-2rem)] sm:max-w-fit sm:p-6 sm:shadow-2xl lg:p-8 dark:bg-neutral-900', place === 'center'
1107
+ ? 'data-enter:translate-y-[calc(-50%+12rem)] data-leave:translate-y-[calc(-50%-8rem)] top-1/2 -translate-y-1/2 rounded-2xl'
1108
+ : 'rounded-t-4xl pointer-fine:top-1/2 pointer-fine:bottom-auto pointer-fine:-translate-y-1/2 pointer-fine:rounded-2xl data-enter:translate-y-full sm:data-enter:translate-y-[calc(-50%+12rem)] data-leave:translate-y-full sm:data-leave:translate-y-[calc(-50%-8rem)] sm:data-open:-translate-y-1/2 bottom-0 h-fit max-h-[calc(100dvh-4rem)] translate-y-0 sm:bottom-auto sm:top-1/2 sm:rounded-b-2xl sm:rounded-t-2xl', className), children: [jsx("button", { onTouchStart: enableTouchClose, onMouseDown: enableMouseClose, className: [
1109
+ 'after:ease-exponential absolute inset-x-0 top-0 z-10 flex h-6 cursor-grab items-center justify-center after:h-1 after:w-8 after:rounded-full after:transition-[transform_background-color] after:duration-500 active:cursor-grabbing',
1110
+ readyToClose
1111
+ ? 'after:scale-x-200 after:scale-y-200 after:bg-ui-blue'
1112
+ : 'after:bg-ui-grey/50 active:after:bg-ui-grey pointer-fine:hover:after:scale-x-125 pointer-fine:hover:after:bg-neutral-500/75 pointer-fine:active:after:scale-x-150 pointer-fine:active:after:bg-ui-grey active:after:scale-x-150 active:after:scale-y-125',
1113
+ ].join(' '), children: jsx("span", { className: 'sr-only', children: "Drag down to close" }) }), dialogElement] })] })] }));
1114
+ }
1115
+
1116
+ function Time({ children, dateObject, dateTime, day, hours, milliseconds, minutes, month, seconds, year, ref, ...props }) {
1117
+ const [date, setDate] = useState(dateObject || undefined);
1118
+ const getDateAndTime = () => {
1119
+ if (dateTime)
1120
+ return dateTime;
1121
+ if (!date)
1122
+ return '';
1123
+ const currentYear = date.getFullYear(), currentMonth = getMonth(date), currentDay = getDate(date), currentHour = getHours(date), currentMinute = getMinutes(date), currentSecond = getSeconds(date), currentMillisecond = getMilliseconds(date);
1124
+ return [currentYear, currentMonth, currentDay, currentHour, currentMinute, currentSecond, currentMillisecond].join('-');
1125
+ };
1126
+ const dateAndTime = getDateAndTime();
1127
+ const getDateDisplay = () => {
1128
+ if (children)
1129
+ return children;
1130
+ if (dateAndTime === '')
1131
+ return '';
1132
+ const [dtYear, dtMonth, dtDay, dtHour, dtMinute, dtSecond, dtMillisecond] = dateAndTime.split('-').map(Number);
1133
+ return [
1134
+ day && dtDay,
1135
+ month && [getMonthName(Number(dtMonth) - 1), month && year && ','].filter(Boolean).join(''),
1136
+ year && dtYear,
1137
+ hours &&
1138
+ minutes &&
1139
+ [
1140
+ 'at',
1141
+ hours && dtHour,
1142
+ hours && minutes && ':',
1143
+ minutes && dtMinute,
1144
+ minutes && seconds && ':',
1145
+ seconds && dtSecond,
1146
+ seconds && milliseconds && '.',
1147
+ milliseconds && dtMillisecond,
1148
+ ]
1149
+ .filter(Boolean)
1150
+ .join(''),
1151
+ ]
1152
+ .filter(Boolean)
1153
+ .join(' ');
1154
+ };
1155
+ const dateDisplay = getDateDisplay();
1156
+ useEffect(() => {
1157
+ if (date === undefined &&
1158
+ dateObject === undefined &&
1159
+ dateTime === undefined &&
1160
+ typeof window !== 'undefined' &&
1161
+ (dateAndTime === '' || dateDisplay === ''))
1162
+ setDate(new Date());
1163
+ }, [date, setDate, dateAndTime, dateDisplay, dateObject, dateTime]);
1164
+ return (jsx("time", { dateTime: dateAndTime, ref: ref, ...props, children: dateDisplay }));
1165
+ }
1166
+
1167
+ export { Anchor, Button, Form, FormContextProvider, FormStatusProvider, Ghost, Heading, Input, Link, Modal, ModalDialog, ModalTrigger, SubmitButton, Time, defineField, useFormContext, useFormStatus };
1168
+ //# sourceMappingURL=index.esm.js.map