mado-ui 0.2.2 → 0.3.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.
@@ -1,7 +1,9 @@
1
1
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
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, Textarea as Textarea$1, Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';
3
+ import * as React from 'react';
4
+ import { Children, isValidElement, Fragment, createContext, useContext, useSyncExternalStore, useRef, Suspense, useLayoutEffect, useState, useEffect, useCallback, cloneElement, useId } from 'react';
5
+ import { Button as Button$1, Disclosure, DisclosurePanel, DisclosureButton, Menu, MenuButton, MenuItem, MenuItems, MenuSection, MenuHeading, MenuSeparator, Fieldset as Fieldset$1, Legend, Field, Label, Input as Input$1, Description, Textarea as Textarea$1, Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';
6
+ import * as ReactDOM from 'react-dom';
5
7
  import { createPortal } from 'react-dom';
6
8
 
7
9
  const integerList = Array.from({ length: 100 }, (_, i) => `${i + 1}`);
@@ -308,7 +310,7 @@ function twSort(className) {
308
310
  return className;
309
311
  }
310
312
 
311
- function Anchor({ className, disabled, href, onClick, ref, target, rel, ...props }) {
313
+ function Anchor({ as, className, disabled, href, onClick, target, rel, ...props }) {
312
314
  const isExternal = `${href}`.startsWith('http'), hasHash = `${href}`.includes('#');
313
315
  const handleClick = e => {
314
316
  if (disabled)
@@ -316,7 +318,8 @@ function Anchor({ className, disabled, href, onClick, ref, target, rel, ...props
316
318
  onClick?.(e);
317
319
  setTimeout(() => history.replaceState({}, document.title, location.pathname), 100);
318
320
  };
319
- 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
321
+ const AnchorElement = as || 'a';
322
+ return (jsx(AnchorElement, { ...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
320
323
  ? rel === 'nofollow'
321
324
  ? `${rel} noreferrer noopener`
322
325
  : `${rel} prefetch`
@@ -345,68 +348,104 @@ const lineLiftClasses = twJoin([
345
348
  ]);
346
349
  const fillClasses = twJoin(baseClasses, '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 after:ease-exponential active:text-zinc-50 pointer-fine:hover:text-zinc-50');
347
350
  // Define theme-specific fill color transition classes
348
- const getFillColorTransitionClasses = (theme = 'blue') => {
351
+ const getFillColorTransitionClasses = (theme = 'blue', customTheme) => {
352
+ let fillColorTransitionClasses = twJoin(fillClasses, 'transition-transform after:bg-(--theme-color)');
349
353
  switch (theme) {
354
+ case 'blue':
355
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-blue)]');
356
+ break;
350
357
  case 'brown':
351
- return twJoin(fillClasses, 'after:bg-ui-brown after:transition-transform contrast-more:after:bg-ui-brown');
358
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-brow)]');
359
+ break;
352
360
  case 'green':
353
- return twJoin(fillClasses, 'after:bg-ui-green after:transition-transform contrast-more:after:bg-ui-green');
361
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-green)]');
362
+ break;
354
363
  case 'grey':
355
- return twJoin(fillClasses, 'after:bg-ui-grey after:transition-transform contrast-more:after:bg-ui-grey');
364
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-grey)]');
365
+ break;
356
366
  case 'sky-blue':
357
- return twJoin(fillClasses, 'after:bg-ui-sky-blue after:transition-transform contrast-more:after:bg-ui-sky-blue');
367
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-sky-blue)]');
368
+ break;
358
369
  case 'magenta':
359
- return twJoin(fillClasses, 'after:bg-ui-magenta after:transition-transform contrast-more:after:bg-ui-magenta');
360
- case 'neutral':
361
- 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');
370
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-magenta)]');
371
+ break;
362
372
  case 'orange':
363
- return twJoin(fillClasses, 'after:bg-ui-orange after:transition-transform contrast-more:after:bg-ui-orange');
373
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-orange)]');
374
+ break;
364
375
  case 'pink':
365
- return twJoin(fillClasses, 'after:bg-ui-pink after:transition-transform contrast-more:after:bg-ui-pink');
376
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-pink)]');
377
+ break;
366
378
  case 'purple':
367
- return twJoin(fillClasses, 'after:bg-ui-purple after:transition-transform contrast-more:after:bg-ui-purple');
379
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-purple)]');
380
+ break;
368
381
  case 'red':
369
- return twJoin(fillClasses, 'after:bg-ui-red after:transition-transform contrast-more:after:bg-ui-red');
382
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-red)]');
383
+ break;
370
384
  case 'violet':
371
- return twJoin(fillClasses, 'after:bg-ui-violet after:transition-transform contrast-more:after:bg-ui-violet');
385
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-violet)]');
386
+ break;
372
387
  case 'yellow':
373
- return twJoin(fillClasses, 'after:bg-ui-yellow after:transition-transform contrast-more:after:bg-ui-yellow');
374
- case 'blue':
375
- default:
376
- return twJoin(fillClasses, 'after:bg-ui-blue after:transition-transform contrast-more:after:bg-ui-blue');
388
+ fillColorTransitionClasses = twJoin(fillColorTransitionClasses, 'after:[--theme-color:var(--color-ui-yellow)]');
389
+ break;
390
+ case 'custom':
391
+ if (customTheme && customTheme.themeColor && !customTheme.themeColor.includes('after:[--theme-color:'))
392
+ throw new Error('`customTheme.themeColor` must modify the `--theme-color` variable on the ::after pseudo element. Otherwise, please use `customTheme.classes`.');
393
+ fillColorTransitionClasses = customTheme.themeColor
394
+ ? twMerge(fillColorTransitionClasses, customTheme.themeColor)
395
+ : twMerge(fillClasses, customTheme.classes);
396
+ break;
377
397
  }
398
+ return fillColorTransitionClasses;
378
399
  };
379
400
  // Define theme-specific fill center classes
380
- const getFillCenterClasses = (theme = 'blue') => {
401
+ const getFillCenterClasses = (theme = 'blue', customTheme) => {
402
+ let fillCenterColorClasses = twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-(--theme-color)/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 active:after:bg-(--theme-color) pointer-fine:hover:after:scale-x-100 pointer-fine:hover:after:scale-y-100 pointer-fine:hover:after:bg-(--theme-color)');
381
403
  switch (theme) {
404
+ case 'blue':
405
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-blue)]');
406
+ break;
382
407
  case 'brown':
383
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-brown/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
408
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-brown)]');
409
+ break;
384
410
  case 'green':
385
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-green/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
411
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-green)]');
412
+ break;
386
413
  case 'grey':
387
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-grey/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
414
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-grey)]');
415
+ break;
388
416
  case 'sky-blue':
389
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-sky-blue/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
417
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-sky-blue)]');
418
+ break;
390
419
  case 'magenta':
391
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-magenta/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
392
- case 'neutral':
393
- return twJoin(fillClasses, '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 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');
420
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-magenta)]');
421
+ break;
394
422
  case 'orange':
395
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-orange/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
423
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-orange)]');
424
+ break;
396
425
  case 'pink':
397
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-pink/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
426
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-pink)]');
427
+ break;
398
428
  case 'purple':
399
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-purple/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
429
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-purple)]');
430
+ break;
400
431
  case 'red':
401
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-red/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
432
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-red)]');
433
+ break;
402
434
  case 'violet':
403
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-violet/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
435
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-violet)]');
436
+ break;
404
437
  case 'yellow':
405
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-yellow/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
406
- case 'blue':
407
- default:
408
- return twJoin(fillClasses, 'after:scale-x-50 after:scale-y-[0.25] after:bg-ui-blue/0 after:transition-[transform_background-color] active:after:scale-x-100 active:after:scale-y-100 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');
438
+ fillCenterColorClasses = twJoin(fillCenterColorClasses, 'after:[--theme-color:var(--color-ui-yellow)]');
439
+ break;
440
+ case 'custom':
441
+ if (customTheme && customTheme.themeColor && !customTheme.themeColor.includes('after:[--theme-color:'))
442
+ throw new Error('`customTheme.themeColor` must modify the `--theme-color` variable on the ::after pseudo element. Otherwise, please use `customTheme.classes`.');
443
+ fillCenterColorClasses = customTheme.themeColor
444
+ ? twMerge(fillCenterColorClasses, customTheme.themeColor)
445
+ : twMerge(fillClasses, customTheme.classes);
446
+ break;
409
447
  }
448
+ return fillCenterColorClasses;
410
449
  };
411
450
  const multilineBaseClasses = twSort('bg-linear-to-r from-current to-current bg-no-repeat active:scale-95');
412
451
  const multilineLineStaticClasses = 'underline';
@@ -418,80 +457,115 @@ const multilineLineRtlClasses = twJoin([multilineXClasses, 'bg-[position:100%_10
418
457
  const multilineLineCenterClasses = twJoin([multilineXClasses, 'bg-[position:50%_100%]']);
419
458
  const multilineLineLiftClasses = twJoin(multilineLineClasses, 'bg-[size:auto_0px] focus-visible:bg-[size:auto_2px] active:bg-[size:auto_2px] pointer-fine:hover:bg-[size:auto_2px]');
420
459
  const multilineFillBaseClasses = twJoin(multilineBaseClasses, 'rounded px-0.5 py-0.75 focus-visible:text-zinc-50 active:text-zinc-50 pointer-fine:hover:text-zinc-50');
421
- const getMultilineFillColorClasses = (theme = 'blue') => {
460
+ const getMultilineFillColorClasses = (theme = 'blue', customTheme) => {
461
+ let multilineFillColorClasses = twJoin(multilineFillBaseClasses, 'from-(--theme-color) to-(--theme-color) transition-[background-size_color]');
422
462
  switch (theme) {
463
+ case 'blue':
464
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-blue)]');
465
+ break;
423
466
  case 'brown':
424
- return twJoin(multilineFillBaseClasses, 'from-ui-brown to-ui-brown transition-[background-size_color] contrast-more:from-ui-brown contrast-more:to-ui-brown');
467
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-brown)]');
468
+ break;
425
469
  case 'green':
426
- return twJoin(multilineFillBaseClasses, 'from-ui-green to-ui-green transition-[background-size_color] contrast-more:from-ui-green contrast-more:to-ui-green');
470
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-green)]');
471
+ break;
427
472
  case 'grey':
428
- return twJoin(multilineFillBaseClasses, 'from-ui-grey to-ui-grey transition-[background-size_color] contrast-more:from-ui-grey contrast-more:to-ui-grey');
473
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-grey)]');
474
+ break;
429
475
  case 'sky-blue':
430
- return twJoin(multilineFillBaseClasses, 'from-ui-sky-blue to-ui-sky-blue transition-[background-size_color] contrast-more:from-ui-sky-blue contrast-more:to-ui-sky-blue');
476
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-sky-blue)]');
477
+ break;
431
478
  case 'magenta':
432
- return twJoin(multilineFillBaseClasses, 'from-ui-magenta to-ui-magenta transition-[background-size_color] contrast-more:from-ui-magenta contrast-more:to-ui-magenta');
433
- case 'neutral':
434
- 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');
479
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-magenta)]');
480
+ break;
435
481
  case 'orange':
436
- return twJoin(multilineFillBaseClasses, 'from-ui-orange to-ui-orange transition-[background-size_color] contrast-more:from-ui-orange contrast-more:to-ui-orange');
482
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-orange)]');
483
+ break;
437
484
  case 'pink':
438
- return twJoin(multilineFillBaseClasses, 'from-ui-pink to-ui-pink transition-[background-size_color] contrast-more:from-ui-pink contrast-more:to-ui-pink');
485
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-pink)]');
486
+ break;
439
487
  case 'purple':
440
- return twJoin(multilineFillBaseClasses, 'from-ui-purple to-ui-purple transition-[background-size_color] contrast-more:from-ui-purple contrast-more:to-ui-purple');
488
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-purple)]');
489
+ break;
441
490
  case 'red':
442
- return twJoin(multilineFillBaseClasses, 'from-ui-red to-ui-red transition-[background-size_color] contrast-more:from-ui-red contrast-more:to-ui-red');
491
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-red)]');
492
+ break;
443
493
  case 'violet':
444
- return twJoin(multilineFillBaseClasses, 'from-ui-violet to-ui-violet transition-[background-size_color] contrast-more:from-ui-violet contrast-more:to-ui-violet');
494
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-violet)]');
495
+ break;
445
496
  case 'yellow':
446
- return twJoin(multilineFillBaseClasses, 'from-ui-yellow to-ui-yellow transition-[background-size_color] contrast-more:from-ui-yellow contrast-more:to-ui-yellow');
447
- case 'blue':
448
- default:
449
- return twJoin(multilineFillBaseClasses, 'from-ui-blue to-ui-blue transition-[background-size_color] contrast-more:from-ui-blue contrast-more:to-ui-blue');
497
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-yellow)]');
498
+ break;
499
+ case 'custom':
500
+ if (customTheme && customTheme.themeColor && !customTheme.themeColor.includes('[--theme-color:'))
501
+ throw new Error('`customTheme.themeColor` must modify the `--theme-color` variable. Otherwise, please use `customTheme.classes`.');
502
+ multilineFillColorClasses = customTheme.themeColor
503
+ ? twMerge(multilineFillColorClasses, customTheme.themeColor)
504
+ : twMerge(multilineFillBaseClasses, customTheme.classes);
505
+ break;
450
506
  }
507
+ return multilineFillColorClasses;
451
508
  };
452
- // Define theme-specific multiline fill classes
453
- const getMultilineFillClasses = (theme = 'blue') => {
509
+ const getMultilineFillClasses = (theme = 'blue', customTheme) => {
510
+ let multilineFillColorClasses = twJoin(multilineFillBaseClasses, 'from-(--theme-color)/0 to-(--theme-color)/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-(--theme-color) focus-visible:to-(--theme-color) focus-visible:bg-[size:100%_100%] active:from-(--theme-color) active:to-(--theme-color) active:bg-[size:100%_100%] contrast-more:from-(--theme-color)/0 pointer-fine:hover:from-(--theme-color) pointer-fine:hover:to-(--theme-color) pointer-fine:hover:bg-[size:100%_100%]');
454
511
  switch (theme) {
512
+ case 'blue':
513
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-blue)]');
514
+ break;
455
515
  case 'brown':
456
- return twJoin(multilineFillBaseClasses, 'from-ui-brown/0 to-ui-brown/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-brown focus-visible:to-ui-brown focus-visible:bg-[size:100%_100%] active:from-ui-brown active:to-ui-brown active:bg-[size:100%_100%] 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');
516
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-brown)]');
517
+ break;
457
518
  case 'green':
458
- return twJoin(multilineFillBaseClasses, 'from-ui-green/0 to-ui-green/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-green focus-visible:to-ui-green focus-visible:bg-[size:100%_100%] active:from-ui-green active:to-ui-green active:bg-[size:100%_100%] 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');
519
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-green)]');
520
+ break;
459
521
  case 'grey':
460
- return twJoin(multilineFillBaseClasses, 'from-ui-grey/0 to-ui-grey/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-grey focus-visible:to-ui-grey focus-visible:bg-[size:100%_100%] active:from-ui-grey active:to-ui-grey active:bg-[size:100%_100%] 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');
522
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-grey)]');
523
+ break;
461
524
  case 'sky-blue':
462
- return twJoin(multilineFillBaseClasses, 'from-ui-sky-blue/0 to-ui-sky-blue/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-sky-blue focus-visible:to-ui-sky-blue focus-visible:bg-[size:100%_100%] active:from-ui-sky-blue active:to-ui-sky-blue active:bg-[size:100%_100%] 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');
525
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-sky-blue)]');
526
+ break;
463
527
  case 'magenta':
464
- return twJoin(multilineFillBaseClasses, 'from-ui-magenta/0 to-ui-magenta/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-magenta focus-visible:to-ui-magenta focus-visible:bg-[size:100%_100%] active:from-ui-magenta active:to-ui-magenta active:bg-[size:100%_100%] 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');
465
- case 'neutral':
466
- return twJoin(multilineFillBaseClasses, '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 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');
528
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-magenta)]');
529
+ break;
467
530
  case 'orange':
468
- return twJoin(multilineFillBaseClasses, 'from-ui-orange/0 to-ui-orange/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-orange focus-visible:to-ui-orange focus-visible:bg-[size:100%_100%] active:from-ui-orange active:to-ui-orange active:bg-[size:100%_100%] 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');
531
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-orange)]');
532
+ break;
469
533
  case 'pink':
470
- return twJoin(multilineFillBaseClasses, 'from-ui-pink/0 to-ui-pink/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-pink focus-visible:to-ui-pink focus-visible:bg-[size:100%_100%] active:from-ui-pink active:to-ui-pink active:bg-[size:100%_100%] 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');
534
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-pink)]');
535
+ break;
471
536
  case 'purple':
472
- return twJoin(multilineFillBaseClasses, 'from-ui-purple/0 to-ui-purple/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-purple focus-visible:to-ui-purple focus-visible:bg-[size:100%_100%] active:from-ui-purple active:to-ui-purple active:bg-[size:100%_100%] 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');
537
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-purple)]');
538
+ break;
473
539
  case 'red':
474
- return twJoin(multilineFillBaseClasses, 'from-ui-red/0 to-ui-red/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-red focus-visible:to-ui-red focus-visible:bg-[size:100%_100%] active:from-ui-red active:to-ui-red active:bg-[size:100%_100%] 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');
540
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-red)]');
541
+ break;
475
542
  case 'violet':
476
- return twJoin(multilineFillBaseClasses, 'from-ui-violet/0 to-ui-violet/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-violet focus-visible:to-ui-violet focus-visible:bg-[size:100%_100%] active:from-ui-violet active:to-ui-violet active:bg-[size:100%_100%] 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');
543
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-violet)]');
544
+ break;
477
545
  case 'yellow':
478
- return twJoin(multilineFillBaseClasses, 'from-ui-yellow/0 to-ui-yellow/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-yellow focus-visible:to-ui-yellow focus-visible:bg-[size:100%_100%] active:from-ui-yellow active:to-ui-yellow active:bg-[size:100%_100%] 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');
479
- case 'blue':
480
- default:
481
- return twJoin(multilineFillBaseClasses, 'from-ui-blue/0 to-ui-blue/0 bg-[size:50%_0px] bg-[position:50%_50%] transition-[background-size_background-image_color] focus-visible:from-ui-blue focus-visible:to-ui-blue focus-visible:bg-[size:100%_100%] active:from-ui-blue active:to-ui-blue active:bg-[size:100%_100%] 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');
546
+ multilineFillColorClasses = twJoin(multilineFillColorClasses, '[--theme-color:var(--color-ui-yellow)]');
547
+ break;
548
+ case 'custom':
549
+ if (customTheme && customTheme.themeColor && !customTheme.themeColor.includes('[--theme-color:'))
550
+ throw new Error('`customTheme.themeColor` must modify the `--theme-color` variable. Otherwise, please use `customTheme.classes`.');
551
+ multilineFillColorClasses = customTheme.themeColor
552
+ ? twMerge(multilineFillColorClasses, customTheme.themeColor)
553
+ : twMerge(multilineFillBaseClasses, customTheme.classes);
554
+ break;
482
555
  }
556
+ return multilineFillColorClasses;
483
557
  };
484
- const getMultilineFillLiftClasses = (theme = 'blue') => {
485
- return twJoin(getMultilineFillColorClasses(theme), 'bg-[size:auto_0px] bg-[position:50%_100%] focus-visible:bg-[size:auto_100%] active:bg-[size:auto_100%] pointer-fine:hover:bg-[size:auto_100%]');
558
+ const getMultilineFillLiftClasses = (theme = 'blue', customTheme) => {
559
+ return twJoin(getMultilineFillColorClasses(theme, customTheme), 'bg-[size:auto_0px] bg-[position:50%_100%] focus-visible:bg-[size:auto_100%] active:bg-[size:auto_100%] pointer-fine:hover:bg-[size:auto_100%]');
486
560
  };
487
- const getMultilineFillXClasses = (theme = 'blue') => {
488
- return twJoin(getMultilineFillColorClasses(theme), 'bg-[size:0%_100%] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%] pointer-fine:hover:bg-[size:100%_100%]');
561
+ const getMultilineFillXClasses = (theme = 'blue', customTheme) => {
562
+ return twJoin(getMultilineFillColorClasses(theme, customTheme), 'bg-[size:0%_100%] focus-visible:bg-[size:100%_100%] active:bg-[size:100%_100%] pointer-fine:hover:bg-[size:100%_100%]');
489
563
  };
490
- const getMultilineFillRtlClasses = (theme = 'blue') => {
491
- return twJoin(getMultilineFillXClasses(theme), 'bg-[position:100%_auto]');
564
+ const getMultilineFillRtlClasses = (theme = 'blue', customTheme) => {
565
+ return twJoin(getMultilineFillXClasses(theme, customTheme), 'bg-[position:100%_auto]');
492
566
  };
493
- const getMultilineFillCenterClasses = (theme = 'blue') => {
494
- return twJoin(getMultilineFillXClasses(theme), 'bg-[position:50%_auto]');
567
+ const getMultilineFillCenterClasses = (theme = 'blue', customTheme) => {
568
+ return twJoin(getMultilineFillXClasses(theme, customTheme), 'bg-[position:50%_auto]');
495
569
  };
496
570
  /**
497
571
  * # Link
@@ -522,7 +596,7 @@ const getMultilineFillCenterClasses = (theme = 'blue') => {
522
596
  * @example
523
597
  * <Link href='/about' type='fill-ltr' theme='red' title='About Us'>Learn more about our company</Link>
524
598
  */
525
- function Link({ as, className, ref, theme = 'blue', type, ...props }) {
599
+ function Link({ as, className, customTheme, theme = 'blue', type, ...props }) {
526
600
  const getLinkClasses = () => {
527
601
  switch (type) {
528
602
  case 'static':
@@ -536,13 +610,13 @@ function Link({ as, className, ref, theme = 'blue', type, ...props }) {
536
610
  case 'lift':
537
611
  return lineLiftClasses;
538
612
  case 'fill':
539
- return getFillCenterClasses(theme);
613
+ return getFillCenterClasses(theme, customTheme);
540
614
  case 'fill-ltr':
541
- return twJoin([getFillColorTransitionClasses(theme), scaleXClasses, 'after:origin-left']);
615
+ return twJoin([getFillColorTransitionClasses(theme, customTheme), scaleXClasses, 'after:origin-left']);
542
616
  case 'fill-rtl':
543
- return twJoin([getFillColorTransitionClasses(theme), scaleXClasses, 'after:origin-right']);
617
+ return twJoin([getFillColorTransitionClasses(theme, customTheme), scaleXClasses, 'after:origin-right']);
544
618
  case 'fill-lift':
545
- return twJoin([getFillColorTransitionClasses(theme), scaleYClasses, 'after:origin-bottom']);
619
+ return twJoin([getFillColorTransitionClasses(theme, customTheme), scaleYClasses, 'after:origin-bottom']);
546
620
  case 'multiline':
547
621
  return multilineNormalClasses;
548
622
  case 'multiline-static':
@@ -556,29 +630,29 @@ function Link({ as, className, ref, theme = 'blue', type, ...props }) {
556
630
  case 'multiline-lift':
557
631
  return multilineLineLiftClasses;
558
632
  case 'multiline-fill':
559
- return getMultilineFillClasses(theme);
633
+ return getMultilineFillClasses(theme, customTheme);
560
634
  case 'multiline-fill-ltr':
561
- return getMultilineFillXClasses(theme);
635
+ return getMultilineFillXClasses(theme, customTheme);
562
636
  case 'multiline-fill-rtl':
563
- return getMultilineFillRtlClasses(theme);
637
+ return getMultilineFillRtlClasses(theme, customTheme);
564
638
  case 'multiline-fill-center':
565
- return getMultilineFillCenterClasses(theme);
639
+ return getMultilineFillCenterClasses(theme, customTheme);
566
640
  case 'multiline-fill-lift':
567
- return getMultilineFillLiftClasses(theme);
641
+ return getMultilineFillLiftClasses(theme, customTheme);
568
642
  default:
569
643
  return lineNormalClasses;
570
644
  }
571
645
  };
572
646
  const linkClasses = getLinkClasses();
573
647
  const LinkElement = as || Anchor;
574
- return jsx(LinkElement, { ...props, className: twMerge(linkClasses, className), ref: ref });
648
+ return jsx(LinkElement, { ...props, className: twMerge(linkClasses, className) });
575
649
  }
576
650
 
577
651
  /**
578
652
  * # Button
579
653
  * - A pre-styled button with utility props for easy customization depending on use case.
580
654
  */
581
- function Button({ className, padding = 'md', rounded = 'lg', theme = 'blue', ref, ...props }) {
655
+ function Button({ className, customTheme, gradient = false, padding = 'md', rounded = 'lg', theme = 'blue', ...props }) {
582
656
  const getPaddingClasses = () => {
583
657
  switch (padding) {
584
658
  case 'xs':
@@ -609,99 +683,115 @@ function Button({ className, padding = 'md', rounded = 'lg', theme = 'blue', ref
609
683
  return 'rounded-full';
610
684
  }
611
685
  };
612
- const getThemeClasses = () => {
613
- const classList = [];
686
+ const getThemeColorVariable = () => {
614
687
  switch (theme) {
615
688
  case 'blue':
616
- classList.push(twSort('text-white shadow-lg shadow-ui-blue/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-blue before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
617
- break;
618
- case 'blue-gradient':
619
- classList.push(twSort('bg-ui-blue text-white shadow-lg shadow-ui-blue/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
620
- break;
689
+ return twSort('text-white [--theme-color:var(--color-ui-blue)]');
621
690
  case 'brown':
622
- classList.push(twSort('text-white shadow-lg shadow-ui-brown/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-brown before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
623
- break;
624
- case 'brown-gradient':
625
- classList.push(twSort('bg-ui-brown text-white shadow-lg shadow-ui-brown/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
626
- break;
691
+ return twSort('text-white [--theme-color:var(--color-ui-brown)]');
627
692
  case 'green':
628
- classList.push(twSort('text-white shadow-lg shadow-ui-green/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-green before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
629
- break;
630
- case 'green-gradient':
631
- classList.push(twSort('bg-ui-green text-white shadow-lg shadow-ui-green/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
632
- break;
693
+ return twSort('text-white [--theme-color:var(--color-ui-green)]');
633
694
  case 'grey':
634
- classList.push(twSort('text-white shadow-lg shadow-ui-grey/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-grey before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
635
- break;
636
- case 'grey-gradient':
637
- classList.push(twSort('bg-ui-grey text-white shadow-lg shadow-ui-grey/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
638
- break;
639
- case 'sky-blue':
640
- classList.push(twSort('text-white shadow-lg shadow-ui-sky-blue/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-sky-blue before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
641
- break;
642
- case 'sky-blue-gradient':
643
- classList.push(twSort('bg-ui-sky-blue text-white shadow-lg shadow-ui-sky-blue/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
644
- break;
695
+ return twSort('text-white [--theme-color:var(--color-ui-grey)]');
645
696
  case 'magenta':
646
- classList.push(twSort('text-white shadow-lg shadow-ui-magenta/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-magenta before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
647
- break;
648
- case 'magenta-gradient':
649
- classList.push(twSort('bg-ui-magenta text-white shadow-lg shadow-ui-magenta/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
650
- break;
651
- case 'neutral':
652
- classList.push(twSort('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 before:ease-exponential active:before:brightness-90 dark:bg-zinc-800 pointer-fine:hover:before:brightness-110'));
653
- break;
654
- case 'neutral-gradient':
655
- classList.push(twSort('dark bg-linear-to-t from-zinc-300 via-zinc-200 to-zinc-100 text-black before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 dark:from-zinc-900 dark:via-zinc-800 dark:to-zinc-700 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
656
- break;
697
+ return twSort('text-white [--theme-color:var(--color-ui-magenta)]');
657
698
  case 'orange':
658
- classList.push(twSort('text-white shadow-lg shadow-ui-orange/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-orange before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
659
- break;
660
- case 'orange-gradient':
661
- classList.push(twSort('bg-ui-orange text-white shadow-lg shadow-ui-orange/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
662
- break;
699
+ return twSort('text-white [--theme-color:var(--color-ui-orange)]');
663
700
  case 'pink':
664
- classList.push(twSort('text-white shadow-lg shadow-ui-pink/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-pink before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
665
- break;
666
- case 'pink-gradient':
667
- classList.push(twSort('before:to-white/75/75 bg-ui-pink text-white shadow-lg shadow-ui-pink/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t before:from-black/75 before:via-transparent before:opacity-75 before:mix-blend-soft-light before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
668
- break;
701
+ return twSort('text-white [--theme-color:var(--color-ui-pink)]');
669
702
  case 'purple':
670
- classList.push(twSort('text-white shadow-lg shadow-ui-purple/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-purple before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
671
- break;
672
- case 'purple-gradient':
673
- classList.push(twSort('bg-ui-purple text-white shadow-lg shadow-ui-purple/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
674
- break;
703
+ return twSort('text-white [--theme-color:var(--color-ui-purple)]');
675
704
  case 'red':
676
- classList.push(twSort('text-white shadow-lg shadow-ui-red/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-red before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
677
- break;
678
- case 'red-gradient':
679
- classList.push(twSort('bg-ui-red text-white shadow-lg shadow-ui-red/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
680
- break;
705
+ return twSort('text-white [--theme-color:var(--color-ui-red)]');
706
+ case 'sky-blue':
707
+ return twSort('text-white [--theme-color:var(--color-ui-sky-blue)]');
681
708
  case 'violet':
682
- classList.push(twSort('text-white shadow-lg shadow-ui-violet/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-violet before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
683
- break;
684
- case 'violet-gradient':
685
- classList.push(twSort('bg-ui-violet text-white shadow-lg shadow-ui-violet/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
686
- break;
709
+ return twSort('text-white [--theme-color:var(--color-ui-violet)]');
687
710
  case 'yellow':
688
- classList.push(twSort('text-black shadow-lg shadow-ui-yellow/25 transition-transform before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-ui-yellow before:transition-[filter] before:duration-300 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
689
- break;
690
- case 'yellow-gradient':
691
- classList.push(twSort('bg-ui-yellow text-black shadow-lg shadow-ui-yellow/25 transition-transform before:absolute before:inset-0 before:rounded-[inherit] before:bg-linear-to-t 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 before:ease-exponential active:before:brightness-90 pointer-fine:hover:before:brightness-110 pointer-fine:active:before:brightness-90'));
692
- break;
711
+ return twSort('text-black [--theme-color:var(--color-ui-yellow)]');
712
+ case 'custom':
713
+ if (customTheme && customTheme.themeColor && !customTheme.themeColor.includes('[--theme-color:'))
714
+ throw new Error('`customTheme.themeColor` must modify the `--theme-color` variable. Otherwise, please use `customTheme.classes`.');
715
+ return customTheme.themeColor || customTheme.classes;
693
716
  }
694
- return classList.join(' ');
695
717
  };
696
- const paddingClasses = getPaddingClasses(), roundedClasses = getRoundedClasses(), themeClasses = getThemeClasses();
718
+ const paddingClasses = getPaddingClasses(), roundedClasses = getRoundedClasses(), themeColorVariable = getThemeColorVariable();
719
+ const themeClasses = customTheme && customTheme.classes
720
+ ? customTheme.classes
721
+ : [
722
+ gradient
723
+ ? twSort('bg-linear-to-t from-[color-mix(in_oklab,var(--theme-color),var(--color-black)_20%)] via-(--theme-color) to-[color-mix(in_oklab,var(--theme-color),var(--color-white)_20%)] bg-[size:100%_200%] transition-[scale,background-position-y] [background-position-y:50%] active:[background-position-y:100%] data-focus:[background-position-y:0%] pointer-fine:hover:[background-position-y:0%] pointer-fine:hover:active:[background-position-y:100%]')
724
+ : twSort('bg-(--theme-color) transition-[scale,background-color] active:bg-[color-mix(in_oklab,var(--theme-color),var(--color-black)_10%)] data-focus:bg-[color-mix(in_oklab,var(--theme-color),var(--color-white)_10%)] pointer-fine:hover:bg-[color-mix(in_oklab,var(--theme-color),var(--color-white)_10%)] pointer-fine:hover:active:bg-[color-mix(in_oklab,var(--theme-color),var(--color-black)_10%)]'),
725
+ 'shadow-(--theme-color)/25',
726
+ ].join(' ');
697
727
  const buttonClasses = twMerge([
698
- 'block w-fit min-w-fit text-center font-semibold duration-300 ease-exponential focus-visible:scale-101 active:scale-95 pointer-fine:hover:scale-101 pointer-fine:active:scale-99',
728
+ 'block w-fit min-w-fit text-center font-semibold shadow-lg duration-300 ease-exponential active:scale-99 data-focus:scale-101 pointer-fine:hover:scale-101 pointer-fine:hover:active:scale-99',
699
729
  paddingClasses,
700
730
  roundedClasses,
731
+ themeColorVariable,
701
732
  themeClasses,
702
733
  className,
703
734
  ]);
704
- return 'href' in props && typeof props.href === 'string' ? (jsx(Anchor, { ref: ref, ...props, className: buttonClasses })) : (jsx(Button$1, { ref: ref, ...props, className: buttonClasses }));
735
+ const ButtonElement = 'as' in props ? props.as : props.href ? Anchor : Button$1;
736
+ const { as, ...restProps } = 'as' in props ? props : { ...props, as: undefined };
737
+ return jsx(ButtonElement, { ...restProps, className: buttonClasses });
738
+ }
739
+
740
+ function ChevronDown(props) {
741
+ return (jsx("svg", { viewBox: '0 0 64 36', ...props, children: jsx("path", { d: 'M32,36c1,0,1.8-0.4,2.5-1.1L63,5.7c0.7-0.7,1-1.4,1-2.3c0-1-0.3-1.8-1-2.4c-0.6-0.7-1.4-1-2.3-1s-1.7,0.3-2.4,1L30,29.8H34 L5.7,1C5.1,0.3,4.3,0,3.4,0C2.4,0,1.6,0.3,1,1C0.3,1.6,0,2.4,0,3.4c0,0.9,0.3,1.7,1,2.3l28.5,29.2C30.3,35.7,31.1,36,32,36z' }) }));
742
+ }
743
+
744
+ function ExclamationmarkOctagon(props) {
745
+ return (jsxs("svg", { viewBox: '0 0 64 61.6', ...props, children: [jsx("path", { d: 'M61.4,16.8l-12.1-13.3C47.3,1.3,45.4,0,41.4,0h-18.9C18.6,0,16.7,1.3,14.7,3.5L2.6,16.8c-2,2.3-2.6,3.8-2.6,6.9v14.2c0,3.1.5,4.6,2.6,6.9l12.1,13.3c2,2.2,3.9,3.5,7.8,3.5h18.9c4,0,5.8-1.3,7.9-3.5l12.1-13.3c2.1-2.3,2.6-3.8,2.6-6.9v-14.2c0-3.1-.5-4.6-2.6-6.9ZM58.2,37.3c0,2.3-.3,3.1-1.5,4.4l-11.2,12.3c-1.7,1.9-2.6,2.5-5.8,2.5h-15.5c-3.1,0-4-.7-5.7-2.5l-11.2-12.3c-1.2-1.4-1.5-2.2-1.5-4.4v-13.1c0-2.3.3-3.1,1.5-4.4l11.2-12.3c1.7-1.9,2.6-2.5,5.7-2.5h15.5c3.1,0,4,.7,5.8,2.5l11.2,12.3c1.3,1.4,1.5,2.2,1.5,4.4v13.1Z' }), jsx("path", { d: 'M32,36.4c1.5,0,2.4-.9,2.4-2.5l.4-16.4c0-1.6-1.2-2.8-2.9-2.8s-2.9,1.1-2.8,2.7l.4,16.5c0,1.6.9,2.5,2.4,2.5Z' }), jsx("path", { d: 'M32,46.5c1.8,0,3.4-1.4,3.4-3.2s-1.5-3.2-3.4-3.2-3.3,1.4-3.3,3.2,1.5,3.2,3.3,3.2Z' })] }));
746
+ }
747
+
748
+ function xmark(props) {
749
+ 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' }) }));
750
+ }
751
+
752
+ function DetailsSummary({ arrow = true, as, children, className, ...props }) {
753
+ return (
754
+ // @ts-expect-error Button has some extra props
755
+ jsx(DisclosureButton, { ...props, as: as || (Button), className: twMerge('w-full', className, Boolean(arrow) && 'grid grid-cols-[1fr_1rem] gap-2'), role: 'summary', children: bag => (jsxs(Fragment$1, { children: [typeof children === 'function' ? children(bag) : children, arrow &&
756
+ (typeof arrow === 'boolean' ? (jsx(ChevronDown, { className: 'absolute top-1/2 right-3 block w-4 -translate-y-1/2' })) : (arrow))] })) }));
757
+ }
758
+ function DetailsBody({ children, className, ...props }) {
759
+ return (jsx(DisclosurePanel, { ...props, className: twMerge('grid grid-rows-1fr transition-rows duration-500 ease-exponential data-closed:grid-rows-0fr', className), transition: true, children: bag => (jsx("div", { className: 'overflow-y-hidden px-2 pt-3 pb-1', children: typeof children === 'function' ? children(bag) : children })) }));
760
+ }
761
+ function Details({ as = 'div', className, ...props }) {
762
+ return (jsx(Disclosure, { ...props, as: as, className: twMerge('rounded-2xl bg-neutral-50/20 p-2 backdrop-blur-md backdrop-brightness-150', className), role: 'details' }));
763
+ }
764
+
765
+ function DropDownButton({ arrow = true, as, children, className, ...props }) {
766
+ return (jsxs(MenuButton, { ...props, as: as || 'button', className: twJoin('group/button', className), children: [children, arrow &&
767
+ (typeof arrow === 'boolean' ? (jsx(ChevronDown, { className: '-top-px -mr-1 ml-2 w-4 animate-flip-again group-data-open/button:animate-flip' })) : (arrow))] }));
768
+ }
769
+ function DropDownItem({ as, ...props }) {
770
+ return jsx(MenuItem, { as: as || 'div', ...props });
771
+ }
772
+ function DropDownItems({ anchor, children, className, style, ...props }) {
773
+ const getAnchorProps = () => {
774
+ let initialAnchor = { gap: '1rem', padding: '1rem', to: 'bottom start' };
775
+ if (anchor) {
776
+ if (typeof anchor === 'string')
777
+ initialAnchor.to = anchor;
778
+ if (typeof anchor === 'object')
779
+ initialAnchor = { ...initialAnchor, ...anchor };
780
+ }
781
+ return initialAnchor;
782
+ };
783
+ const anchorProps = getAnchorProps();
784
+ return (jsx(MenuItems, { ...props, anchor: anchorProps, className: 'grid grid-rows-1fr rounded-xl shadow-xl transition-rows duration-500 ease-exponential data-closed:grid-rows-0fr', transition: true, style: { ...style, minWidth: 'var(--button-width)' }, children: bag => (jsx("div", { className: 'overflow-y-hidden', children: jsx("div", { className: twMerge('bg-neutral-50/20 px-6 py-5 backdrop-blur-md backdrop-brightness-150', className), children: typeof children === 'function' ? children(bag) : children }) })) }));
785
+ }
786
+ function DropDownSection({ children, label, labelProps, separatorAbove, separatorBelow, ...props }) {
787
+ const { labelClassName, ...restLabelProps } = { labelClassName: labelProps?.className || '', ...labelProps };
788
+ return (jsx(MenuSection, { ...props, children: sectionBag => (jsxs(Fragment$1, { children: [separatorAbove && jsx(DropDownSeparator, {}), jsx(MenuHeading, { ...restLabelProps, className: headingBag => twMerge('text-[size:larger] font-bold', typeof labelClassName === 'function' ? labelClassName(headingBag) : labelClassName), children: label }), typeof children === 'function' ? children(sectionBag) : children, separatorBelow && jsx(DropDownSeparator, {})] })) }));
789
+ }
790
+ function DropDownSeparator({ className, ...props }) {
791
+ return (jsx(MenuSeparator, { ...props, className: bag => twMerge('my-4 block h-px rounded-full bg-neutral-950/20', typeof className === 'function' ? className(bag) : className) }));
792
+ }
793
+ function DropDown(props) {
794
+ return jsx(Menu, { ...props });
705
795
  }
706
796
 
707
797
  function createFastContext(defaultInitialState) {
@@ -772,25 +862,2202 @@ function useFormStatus() {
772
862
  return useStore(store => store);
773
863
  }
774
864
 
775
- function validateField$1(value, { required, type }) {
776
- const noValue = !value || value === '';
777
- if (!required && noValue)
778
- return true;
779
- if (noValue)
865
+ function Fieldset({ children, className, legend, legendProps, ...props }) {
866
+ const { className: legendClassName, ...restLegendProps } = legendProps || {};
867
+ return (jsx(Fieldset$1, { ...props, className: bag => twMerge('contents', typeof className === 'function' ? className(bag) : className), children: bag => (jsxs(Fragment$1, { children: [jsx(Legend, { ...restLegendProps, className: twMerge('text-lg font-bold sm:text-xl', typeof legendClassName === 'function' ? legendClassName(bag) : legendClassName), children: legend }), typeof children === 'function' ? children(bag) : children] })) }));
868
+ }
869
+
870
+ /**
871
+ * Custom positioning reference element.
872
+ * @see https://floating-ui.com/docs/virtual-elements
873
+ */
874
+
875
+ const min = Math.min;
876
+ const max = Math.max;
877
+ const round = Math.round;
878
+ const floor = Math.floor;
879
+ const createCoords = v => ({
880
+ x: v,
881
+ y: v
882
+ });
883
+ const oppositeSideMap = {
884
+ left: 'right',
885
+ right: 'left',
886
+ bottom: 'top',
887
+ top: 'bottom'
888
+ };
889
+ const oppositeAlignmentMap = {
890
+ start: 'end',
891
+ end: 'start'
892
+ };
893
+ function clamp(start, value, end) {
894
+ return max(start, min(value, end));
895
+ }
896
+ function evaluate(value, param) {
897
+ return typeof value === 'function' ? value(param) : value;
898
+ }
899
+ function getSide(placement) {
900
+ return placement.split('-')[0];
901
+ }
902
+ function getAlignment(placement) {
903
+ return placement.split('-')[1];
904
+ }
905
+ function getOppositeAxis(axis) {
906
+ return axis === 'x' ? 'y' : 'x';
907
+ }
908
+ function getAxisLength(axis) {
909
+ return axis === 'y' ? 'height' : 'width';
910
+ }
911
+ const yAxisSides = /*#__PURE__*/new Set(['top', 'bottom']);
912
+ function getSideAxis(placement) {
913
+ return yAxisSides.has(getSide(placement)) ? 'y' : 'x';
914
+ }
915
+ function getAlignmentAxis(placement) {
916
+ return getOppositeAxis(getSideAxis(placement));
917
+ }
918
+ function getAlignmentSides(placement, rects, rtl) {
919
+ if (rtl === void 0) {
920
+ rtl = false;
921
+ }
922
+ const alignment = getAlignment(placement);
923
+ const alignmentAxis = getAlignmentAxis(placement);
924
+ const length = getAxisLength(alignmentAxis);
925
+ let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';
926
+ if (rects.reference[length] > rects.floating[length]) {
927
+ mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
928
+ }
929
+ return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
930
+ }
931
+ function getExpandedPlacements(placement) {
932
+ const oppositePlacement = getOppositePlacement(placement);
933
+ return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
934
+ }
935
+ function getOppositeAlignmentPlacement(placement) {
936
+ return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]);
937
+ }
938
+ const lrPlacement = ['left', 'right'];
939
+ const rlPlacement = ['right', 'left'];
940
+ const tbPlacement = ['top', 'bottom'];
941
+ const btPlacement = ['bottom', 'top'];
942
+ function getSideList(side, isStart, rtl) {
943
+ switch (side) {
944
+ case 'top':
945
+ case 'bottom':
946
+ if (rtl) return isStart ? rlPlacement : lrPlacement;
947
+ return isStart ? lrPlacement : rlPlacement;
948
+ case 'left':
949
+ case 'right':
950
+ return isStart ? tbPlacement : btPlacement;
951
+ default:
952
+ return [];
953
+ }
954
+ }
955
+ function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
956
+ const alignment = getAlignment(placement);
957
+ let list = getSideList(getSide(placement), direction === 'start', rtl);
958
+ if (alignment) {
959
+ list = list.map(side => side + "-" + alignment);
960
+ if (flipAlignment) {
961
+ list = list.concat(list.map(getOppositeAlignmentPlacement));
962
+ }
963
+ }
964
+ return list;
965
+ }
966
+ function getOppositePlacement(placement) {
967
+ return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]);
968
+ }
969
+ function expandPaddingObject(padding) {
970
+ return {
971
+ top: 0,
972
+ right: 0,
973
+ bottom: 0,
974
+ left: 0,
975
+ ...padding
976
+ };
977
+ }
978
+ function getPaddingObject(padding) {
979
+ return typeof padding !== 'number' ? expandPaddingObject(padding) : {
980
+ top: padding,
981
+ right: padding,
982
+ bottom: padding,
983
+ left: padding
984
+ };
985
+ }
986
+ function rectToClientRect(rect) {
987
+ const {
988
+ x,
989
+ y,
990
+ width,
991
+ height
992
+ } = rect;
993
+ return {
994
+ width,
995
+ height,
996
+ top: y,
997
+ left: x,
998
+ right: x + width,
999
+ bottom: y + height,
1000
+ x,
1001
+ y
1002
+ };
1003
+ }
1004
+
1005
+ function computeCoordsFromPlacement(_ref, placement, rtl) {
1006
+ let {
1007
+ reference,
1008
+ floating
1009
+ } = _ref;
1010
+ const sideAxis = getSideAxis(placement);
1011
+ const alignmentAxis = getAlignmentAxis(placement);
1012
+ const alignLength = getAxisLength(alignmentAxis);
1013
+ const side = getSide(placement);
1014
+ const isVertical = sideAxis === 'y';
1015
+ const commonX = reference.x + reference.width / 2 - floating.width / 2;
1016
+ const commonY = reference.y + reference.height / 2 - floating.height / 2;
1017
+ const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
1018
+ let coords;
1019
+ switch (side) {
1020
+ case 'top':
1021
+ coords = {
1022
+ x: commonX,
1023
+ y: reference.y - floating.height
1024
+ };
1025
+ break;
1026
+ case 'bottom':
1027
+ coords = {
1028
+ x: commonX,
1029
+ y: reference.y + reference.height
1030
+ };
1031
+ break;
1032
+ case 'right':
1033
+ coords = {
1034
+ x: reference.x + reference.width,
1035
+ y: commonY
1036
+ };
1037
+ break;
1038
+ case 'left':
1039
+ coords = {
1040
+ x: reference.x - floating.width,
1041
+ y: commonY
1042
+ };
1043
+ break;
1044
+ default:
1045
+ coords = {
1046
+ x: reference.x,
1047
+ y: reference.y
1048
+ };
1049
+ }
1050
+ switch (getAlignment(placement)) {
1051
+ case 'start':
1052
+ coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
1053
+ break;
1054
+ case 'end':
1055
+ coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
1056
+ break;
1057
+ }
1058
+ return coords;
1059
+ }
1060
+
1061
+ /**
1062
+ * Computes the `x` and `y` coordinates that will place the floating element
1063
+ * next to a given reference element.
1064
+ *
1065
+ * This export does not have any `platform` interface logic. You will need to
1066
+ * write one for the platform you are using Floating UI with.
1067
+ */
1068
+ const computePosition$1 = async (reference, floating, config) => {
1069
+ const {
1070
+ placement = 'bottom',
1071
+ strategy = 'absolute',
1072
+ middleware = [],
1073
+ platform
1074
+ } = config;
1075
+ const validMiddleware = middleware.filter(Boolean);
1076
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
1077
+ let rects = await platform.getElementRects({
1078
+ reference,
1079
+ floating,
1080
+ strategy
1081
+ });
1082
+ let {
1083
+ x,
1084
+ y
1085
+ } = computeCoordsFromPlacement(rects, placement, rtl);
1086
+ let statefulPlacement = placement;
1087
+ let middlewareData = {};
1088
+ let resetCount = 0;
1089
+ for (let i = 0; i < validMiddleware.length; i++) {
1090
+ const {
1091
+ name,
1092
+ fn
1093
+ } = validMiddleware[i];
1094
+ const {
1095
+ x: nextX,
1096
+ y: nextY,
1097
+ data,
1098
+ reset
1099
+ } = await fn({
1100
+ x,
1101
+ y,
1102
+ initialPlacement: placement,
1103
+ placement: statefulPlacement,
1104
+ strategy,
1105
+ middlewareData,
1106
+ rects,
1107
+ platform,
1108
+ elements: {
1109
+ reference,
1110
+ floating
1111
+ }
1112
+ });
1113
+ x = nextX != null ? nextX : x;
1114
+ y = nextY != null ? nextY : y;
1115
+ middlewareData = {
1116
+ ...middlewareData,
1117
+ [name]: {
1118
+ ...middlewareData[name],
1119
+ ...data
1120
+ }
1121
+ };
1122
+ if (reset && resetCount <= 50) {
1123
+ resetCount++;
1124
+ if (typeof reset === 'object') {
1125
+ if (reset.placement) {
1126
+ statefulPlacement = reset.placement;
1127
+ }
1128
+ if (reset.rects) {
1129
+ rects = reset.rects === true ? await platform.getElementRects({
1130
+ reference,
1131
+ floating,
1132
+ strategy
1133
+ }) : reset.rects;
1134
+ }
1135
+ ({
1136
+ x,
1137
+ y
1138
+ } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
1139
+ }
1140
+ i = -1;
1141
+ }
1142
+ }
1143
+ return {
1144
+ x,
1145
+ y,
1146
+ placement: statefulPlacement,
1147
+ strategy,
1148
+ middlewareData
1149
+ };
1150
+ };
1151
+
1152
+ /**
1153
+ * Resolves with an object of overflow side offsets that determine how much the
1154
+ * element is overflowing a given clipping boundary on each side.
1155
+ * - positive = overflowing the boundary by that number of pixels
1156
+ * - negative = how many pixels left before it will overflow
1157
+ * - 0 = lies flush with the boundary
1158
+ * @see https://floating-ui.com/docs/detectOverflow
1159
+ */
1160
+ async function detectOverflow(state, options) {
1161
+ var _await$platform$isEle;
1162
+ if (options === void 0) {
1163
+ options = {};
1164
+ }
1165
+ const {
1166
+ x,
1167
+ y,
1168
+ platform,
1169
+ rects,
1170
+ elements,
1171
+ strategy
1172
+ } = state;
1173
+ const {
1174
+ boundary = 'clippingAncestors',
1175
+ rootBoundary = 'viewport',
1176
+ elementContext = 'floating',
1177
+ altBoundary = false,
1178
+ padding = 0
1179
+ } = evaluate(options, state);
1180
+ const paddingObject = getPaddingObject(padding);
1181
+ const altContext = elementContext === 'floating' ? 'reference' : 'floating';
1182
+ const element = elements[altBoundary ? altContext : elementContext];
1183
+ const clippingClientRect = rectToClientRect(await platform.getClippingRect({
1184
+ element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
1185
+ boundary,
1186
+ rootBoundary,
1187
+ strategy
1188
+ }));
1189
+ const rect = elementContext === 'floating' ? {
1190
+ x,
1191
+ y,
1192
+ width: rects.floating.width,
1193
+ height: rects.floating.height
1194
+ } : rects.reference;
1195
+ const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
1196
+ const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
1197
+ x: 1,
1198
+ y: 1
1199
+ } : {
1200
+ x: 1,
1201
+ y: 1
1202
+ };
1203
+ const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
1204
+ elements,
1205
+ rect,
1206
+ offsetParent,
1207
+ strategy
1208
+ }) : rect);
1209
+ return {
1210
+ top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
1211
+ bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
1212
+ left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
1213
+ right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
1214
+ };
1215
+ }
1216
+
1217
+ /**
1218
+ * Provides data to position an inner element of the floating element so that it
1219
+ * appears centered to the reference element.
1220
+ * @see https://floating-ui.com/docs/arrow
1221
+ */
1222
+ const arrow$3 = options => ({
1223
+ name: 'arrow',
1224
+ options,
1225
+ async fn(state) {
1226
+ const {
1227
+ x,
1228
+ y,
1229
+ placement,
1230
+ rects,
1231
+ platform,
1232
+ elements,
1233
+ middlewareData
1234
+ } = state;
1235
+ // Since `element` is required, we don't Partial<> the type.
1236
+ const {
1237
+ element,
1238
+ padding = 0
1239
+ } = evaluate(options, state) || {};
1240
+ if (element == null) {
1241
+ return {};
1242
+ }
1243
+ const paddingObject = getPaddingObject(padding);
1244
+ const coords = {
1245
+ x,
1246
+ y
1247
+ };
1248
+ const axis = getAlignmentAxis(placement);
1249
+ const length = getAxisLength(axis);
1250
+ const arrowDimensions = await platform.getDimensions(element);
1251
+ const isYAxis = axis === 'y';
1252
+ const minProp = isYAxis ? 'top' : 'left';
1253
+ const maxProp = isYAxis ? 'bottom' : 'right';
1254
+ const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
1255
+ const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
1256
+ const startDiff = coords[axis] - rects.reference[axis];
1257
+ const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));
1258
+ let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;
1259
+
1260
+ // DOM platform can return `window` as the `offsetParent`.
1261
+ if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {
1262
+ clientSize = elements.floating[clientProp] || rects.floating[length];
1263
+ }
1264
+ const centerToReference = endDiff / 2 - startDiff / 2;
1265
+
1266
+ // If the padding is large enough that it causes the arrow to no longer be
1267
+ // centered, modify the padding so that it is centered.
1268
+ const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
1269
+ const minPadding = min(paddingObject[minProp], largestPossiblePadding);
1270
+ const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);
1271
+
1272
+ // Make sure the arrow doesn't overflow the floating element if the center
1273
+ // point is outside the floating element's bounds.
1274
+ const min$1 = minPadding;
1275
+ const max = clientSize - arrowDimensions[length] - maxPadding;
1276
+ const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
1277
+ const offset = clamp(min$1, center, max);
1278
+
1279
+ // If the reference is small enough that the arrow's padding causes it to
1280
+ // to point to nothing for an aligned placement, adjust the offset of the
1281
+ // floating element itself. To ensure `shift()` continues to take action,
1282
+ // a single reset is performed when this is true.
1283
+ const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
1284
+ const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;
1285
+ return {
1286
+ [axis]: coords[axis] + alignmentOffset,
1287
+ data: {
1288
+ [axis]: offset,
1289
+ centerOffset: center - offset - alignmentOffset,
1290
+ ...(shouldAddOffset && {
1291
+ alignmentOffset
1292
+ })
1293
+ },
1294
+ reset: shouldAddOffset
1295
+ };
1296
+ }
1297
+ });
1298
+
1299
+ /**
1300
+ * Optimizes the visibility of the floating element by flipping the `placement`
1301
+ * in order to keep it in view when the preferred placement(s) will overflow the
1302
+ * clipping boundary. Alternative to `autoPlacement`.
1303
+ * @see https://floating-ui.com/docs/flip
1304
+ */
1305
+ const flip$2 = function (options) {
1306
+ if (options === void 0) {
1307
+ options = {};
1308
+ }
1309
+ return {
1310
+ name: 'flip',
1311
+ options,
1312
+ async fn(state) {
1313
+ var _middlewareData$arrow, _middlewareData$flip;
1314
+ const {
1315
+ placement,
1316
+ middlewareData,
1317
+ rects,
1318
+ initialPlacement,
1319
+ platform,
1320
+ elements
1321
+ } = state;
1322
+ const {
1323
+ mainAxis: checkMainAxis = true,
1324
+ crossAxis: checkCrossAxis = true,
1325
+ fallbackPlacements: specifiedFallbackPlacements,
1326
+ fallbackStrategy = 'bestFit',
1327
+ fallbackAxisSideDirection = 'none',
1328
+ flipAlignment = true,
1329
+ ...detectOverflowOptions
1330
+ } = evaluate(options, state);
1331
+
1332
+ // If a reset by the arrow was caused due to an alignment offset being
1333
+ // added, we should skip any logic now since `flip()` has already done its
1334
+ // work.
1335
+ // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643
1336
+ if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
1337
+ return {};
1338
+ }
1339
+ const side = getSide(placement);
1340
+ const initialSideAxis = getSideAxis(initialPlacement);
1341
+ const isBasePlacement = getSide(initialPlacement) === initialPlacement;
1342
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
1343
+ const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
1344
+ const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';
1345
+ if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {
1346
+ fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
1347
+ }
1348
+ const placements = [initialPlacement, ...fallbackPlacements];
1349
+ const overflow = await detectOverflow(state, detectOverflowOptions);
1350
+ const overflows = [];
1351
+ let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
1352
+ if (checkMainAxis) {
1353
+ overflows.push(overflow[side]);
1354
+ }
1355
+ if (checkCrossAxis) {
1356
+ const sides = getAlignmentSides(placement, rects, rtl);
1357
+ overflows.push(overflow[sides[0]], overflow[sides[1]]);
1358
+ }
1359
+ overflowsData = [...overflowsData, {
1360
+ placement,
1361
+ overflows
1362
+ }];
1363
+
1364
+ // One or more sides is overflowing.
1365
+ if (!overflows.every(side => side <= 0)) {
1366
+ var _middlewareData$flip2, _overflowsData$filter;
1367
+ const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
1368
+ const nextPlacement = placements[nextIndex];
1369
+ if (nextPlacement) {
1370
+ const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== getSideAxis(nextPlacement) : false;
1371
+ if (!ignoreCrossAxisOverflow ||
1372
+ // We leave the current main axis only if every placement on that axis
1373
+ // overflows the main axis.
1374
+ overflowsData.every(d => d.overflows[0] > 0 && getSideAxis(d.placement) === initialSideAxis)) {
1375
+ // Try next placement and re-run the lifecycle.
1376
+ return {
1377
+ data: {
1378
+ index: nextIndex,
1379
+ overflows: overflowsData
1380
+ },
1381
+ reset: {
1382
+ placement: nextPlacement
1383
+ }
1384
+ };
1385
+ }
1386
+ }
1387
+
1388
+ // First, find the candidates that fit on the mainAxis side of overflow,
1389
+ // then find the placement that fits the best on the main crossAxis side.
1390
+ let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
1391
+
1392
+ // Otherwise fallback.
1393
+ if (!resetPlacement) {
1394
+ switch (fallbackStrategy) {
1395
+ case 'bestFit':
1396
+ {
1397
+ var _overflowsData$filter2;
1398
+ const placement = (_overflowsData$filter2 = overflowsData.filter(d => {
1399
+ if (hasFallbackAxisSideDirection) {
1400
+ const currentSideAxis = getSideAxis(d.placement);
1401
+ return currentSideAxis === initialSideAxis ||
1402
+ // Create a bias to the `y` side axis due to horizontal
1403
+ // reading directions favoring greater width.
1404
+ currentSideAxis === 'y';
1405
+ }
1406
+ return true;
1407
+ }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];
1408
+ if (placement) {
1409
+ resetPlacement = placement;
1410
+ }
1411
+ break;
1412
+ }
1413
+ case 'initialPlacement':
1414
+ resetPlacement = initialPlacement;
1415
+ break;
1416
+ }
1417
+ }
1418
+ if (placement !== resetPlacement) {
1419
+ return {
1420
+ reset: {
1421
+ placement: resetPlacement
1422
+ }
1423
+ };
1424
+ }
1425
+ }
1426
+ return {};
1427
+ }
1428
+ };
1429
+ };
1430
+
1431
+ const originSides = /*#__PURE__*/new Set(['left', 'top']);
1432
+
1433
+ // For type backwards-compatibility, the `OffsetOptions` type was also
1434
+ // Derivable.
1435
+
1436
+ async function convertValueToCoords(state, options) {
1437
+ const {
1438
+ placement,
1439
+ platform,
1440
+ elements
1441
+ } = state;
1442
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
1443
+ const side = getSide(placement);
1444
+ const alignment = getAlignment(placement);
1445
+ const isVertical = getSideAxis(placement) === 'y';
1446
+ const mainAxisMulti = originSides.has(side) ? -1 : 1;
1447
+ const crossAxisMulti = rtl && isVertical ? -1 : 1;
1448
+ const rawValue = evaluate(options, state);
1449
+
1450
+ // eslint-disable-next-line prefer-const
1451
+ let {
1452
+ mainAxis,
1453
+ crossAxis,
1454
+ alignmentAxis
1455
+ } = typeof rawValue === 'number' ? {
1456
+ mainAxis: rawValue,
1457
+ crossAxis: 0,
1458
+ alignmentAxis: null
1459
+ } : {
1460
+ mainAxis: rawValue.mainAxis || 0,
1461
+ crossAxis: rawValue.crossAxis || 0,
1462
+ alignmentAxis: rawValue.alignmentAxis
1463
+ };
1464
+ if (alignment && typeof alignmentAxis === 'number') {
1465
+ crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;
1466
+ }
1467
+ return isVertical ? {
1468
+ x: crossAxis * crossAxisMulti,
1469
+ y: mainAxis * mainAxisMulti
1470
+ } : {
1471
+ x: mainAxis * mainAxisMulti,
1472
+ y: crossAxis * crossAxisMulti
1473
+ };
1474
+ }
1475
+
1476
+ /**
1477
+ * Modifies the placement by translating the floating element along the
1478
+ * specified axes.
1479
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
1480
+ * object may be passed.
1481
+ * @see https://floating-ui.com/docs/offset
1482
+ */
1483
+ const offset$2 = function (options) {
1484
+ if (options === void 0) {
1485
+ options = 0;
1486
+ }
1487
+ return {
1488
+ name: 'offset',
1489
+ options,
1490
+ async fn(state) {
1491
+ var _middlewareData$offse, _middlewareData$arrow;
1492
+ const {
1493
+ x,
1494
+ y,
1495
+ placement,
1496
+ middlewareData
1497
+ } = state;
1498
+ const diffCoords = await convertValueToCoords(state, options);
1499
+
1500
+ // If the placement is the same and the arrow caused an alignment offset
1501
+ // then we don't need to change the positioning coordinates.
1502
+ if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
1503
+ return {};
1504
+ }
1505
+ return {
1506
+ x: x + diffCoords.x,
1507
+ y: y + diffCoords.y,
1508
+ data: {
1509
+ ...diffCoords,
1510
+ placement
1511
+ }
1512
+ };
1513
+ }
1514
+ };
1515
+ };
1516
+
1517
+ /**
1518
+ * Optimizes the visibility of the floating element by shifting it in order to
1519
+ * keep it in view when it will overflow the clipping boundary.
1520
+ * @see https://floating-ui.com/docs/shift
1521
+ */
1522
+ const shift$2 = function (options) {
1523
+ if (options === void 0) {
1524
+ options = {};
1525
+ }
1526
+ return {
1527
+ name: 'shift',
1528
+ options,
1529
+ async fn(state) {
1530
+ const {
1531
+ x,
1532
+ y,
1533
+ placement
1534
+ } = state;
1535
+ const {
1536
+ mainAxis: checkMainAxis = true,
1537
+ crossAxis: checkCrossAxis = false,
1538
+ limiter = {
1539
+ fn: _ref => {
1540
+ let {
1541
+ x,
1542
+ y
1543
+ } = _ref;
1544
+ return {
1545
+ x,
1546
+ y
1547
+ };
1548
+ }
1549
+ },
1550
+ ...detectOverflowOptions
1551
+ } = evaluate(options, state);
1552
+ const coords = {
1553
+ x,
1554
+ y
1555
+ };
1556
+ const overflow = await detectOverflow(state, detectOverflowOptions);
1557
+ const crossAxis = getSideAxis(getSide(placement));
1558
+ const mainAxis = getOppositeAxis(crossAxis);
1559
+ let mainAxisCoord = coords[mainAxis];
1560
+ let crossAxisCoord = coords[crossAxis];
1561
+ if (checkMainAxis) {
1562
+ const minSide = mainAxis === 'y' ? 'top' : 'left';
1563
+ const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
1564
+ const min = mainAxisCoord + overflow[minSide];
1565
+ const max = mainAxisCoord - overflow[maxSide];
1566
+ mainAxisCoord = clamp(min, mainAxisCoord, max);
1567
+ }
1568
+ if (checkCrossAxis) {
1569
+ const minSide = crossAxis === 'y' ? 'top' : 'left';
1570
+ const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
1571
+ const min = crossAxisCoord + overflow[minSide];
1572
+ const max = crossAxisCoord - overflow[maxSide];
1573
+ crossAxisCoord = clamp(min, crossAxisCoord, max);
1574
+ }
1575
+ const limitedCoords = limiter.fn({
1576
+ ...state,
1577
+ [mainAxis]: mainAxisCoord,
1578
+ [crossAxis]: crossAxisCoord
1579
+ });
1580
+ return {
1581
+ ...limitedCoords,
1582
+ data: {
1583
+ x: limitedCoords.x - x,
1584
+ y: limitedCoords.y - y,
1585
+ enabled: {
1586
+ [mainAxis]: checkMainAxis,
1587
+ [crossAxis]: checkCrossAxis
1588
+ }
1589
+ }
1590
+ };
1591
+ }
1592
+ };
1593
+ };
1594
+
1595
+ /**
1596
+ * Provides data that allows you to change the size of the floating element —
1597
+ * for instance, prevent it from overflowing the clipping boundary or match the
1598
+ * width of the reference element.
1599
+ * @see https://floating-ui.com/docs/size
1600
+ */
1601
+ const size$2 = function (options) {
1602
+ if (options === void 0) {
1603
+ options = {};
1604
+ }
1605
+ return {
1606
+ name: 'size',
1607
+ options,
1608
+ async fn(state) {
1609
+ var _state$middlewareData, _state$middlewareData2;
1610
+ const {
1611
+ placement,
1612
+ rects,
1613
+ platform,
1614
+ elements
1615
+ } = state;
1616
+ const {
1617
+ apply = () => {},
1618
+ ...detectOverflowOptions
1619
+ } = evaluate(options, state);
1620
+ const overflow = await detectOverflow(state, detectOverflowOptions);
1621
+ const side = getSide(placement);
1622
+ const alignment = getAlignment(placement);
1623
+ const isYAxis = getSideAxis(placement) === 'y';
1624
+ const {
1625
+ width,
1626
+ height
1627
+ } = rects.floating;
1628
+ let heightSide;
1629
+ let widthSide;
1630
+ if (side === 'top' || side === 'bottom') {
1631
+ heightSide = side;
1632
+ widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';
1633
+ } else {
1634
+ widthSide = side;
1635
+ heightSide = alignment === 'end' ? 'top' : 'bottom';
1636
+ }
1637
+ const maximumClippingHeight = height - overflow.top - overflow.bottom;
1638
+ const maximumClippingWidth = width - overflow.left - overflow.right;
1639
+ const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);
1640
+ const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);
1641
+ const noShift = !state.middlewareData.shift;
1642
+ let availableHeight = overflowAvailableHeight;
1643
+ let availableWidth = overflowAvailableWidth;
1644
+ if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {
1645
+ availableWidth = maximumClippingWidth;
1646
+ }
1647
+ if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {
1648
+ availableHeight = maximumClippingHeight;
1649
+ }
1650
+ if (noShift && !alignment) {
1651
+ const xMin = max(overflow.left, 0);
1652
+ const xMax = max(overflow.right, 0);
1653
+ const yMin = max(overflow.top, 0);
1654
+ const yMax = max(overflow.bottom, 0);
1655
+ if (isYAxis) {
1656
+ availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));
1657
+ } else {
1658
+ availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));
1659
+ }
1660
+ }
1661
+ await apply({
1662
+ ...state,
1663
+ availableWidth,
1664
+ availableHeight
1665
+ });
1666
+ const nextDimensions = await platform.getDimensions(elements.floating);
1667
+ if (width !== nextDimensions.width || height !== nextDimensions.height) {
1668
+ return {
1669
+ reset: {
1670
+ rects: true
1671
+ }
1672
+ };
1673
+ }
1674
+ return {};
1675
+ }
1676
+ };
1677
+ };
1678
+
1679
+ function hasWindow() {
1680
+ return typeof window !== 'undefined';
1681
+ }
1682
+ function getNodeName(node) {
1683
+ if (isNode(node)) {
1684
+ return (node.nodeName || '').toLowerCase();
1685
+ }
1686
+ // Mocked nodes in testing environments may not be instances of Node. By
1687
+ // returning `#document` an infinite loop won't occur.
1688
+ // https://github.com/floating-ui/floating-ui/issues/2317
1689
+ return '#document';
1690
+ }
1691
+ function getWindow(node) {
1692
+ var _node$ownerDocument;
1693
+ return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
1694
+ }
1695
+ function getDocumentElement(node) {
1696
+ var _ref;
1697
+ return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
1698
+ }
1699
+ function isNode(value) {
1700
+ if (!hasWindow()) {
1701
+ return false;
1702
+ }
1703
+ return value instanceof Node || value instanceof getWindow(value).Node;
1704
+ }
1705
+ function isElement(value) {
1706
+ if (!hasWindow()) {
1707
+ return false;
1708
+ }
1709
+ return value instanceof Element || value instanceof getWindow(value).Element;
1710
+ }
1711
+ function isHTMLElement(value) {
1712
+ if (!hasWindow()) {
1713
+ return false;
1714
+ }
1715
+ return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
1716
+ }
1717
+ function isShadowRoot(value) {
1718
+ if (!hasWindow() || typeof ShadowRoot === 'undefined') {
1719
+ return false;
1720
+ }
1721
+ return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
1722
+ }
1723
+ const invalidOverflowDisplayValues = /*#__PURE__*/new Set(['inline', 'contents']);
1724
+ function isOverflowElement(element) {
1725
+ const {
1726
+ overflow,
1727
+ overflowX,
1728
+ overflowY,
1729
+ display
1730
+ } = getComputedStyle(element);
1731
+ return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !invalidOverflowDisplayValues.has(display);
1732
+ }
1733
+ const tableElements = /*#__PURE__*/new Set(['table', 'td', 'th']);
1734
+ function isTableElement(element) {
1735
+ return tableElements.has(getNodeName(element));
1736
+ }
1737
+ const topLayerSelectors = [':popover-open', ':modal'];
1738
+ function isTopLayer(element) {
1739
+ return topLayerSelectors.some(selector => {
1740
+ try {
1741
+ return element.matches(selector);
1742
+ } catch (_e) {
1743
+ return false;
1744
+ }
1745
+ });
1746
+ }
1747
+ const transformProperties = ['transform', 'translate', 'scale', 'rotate', 'perspective'];
1748
+ const willChangeValues = ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter'];
1749
+ const containValues = ['paint', 'layout', 'strict', 'content'];
1750
+ function isContainingBlock(elementOrCss) {
1751
+ const webkit = isWebKit();
1752
+ const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;
1753
+
1754
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
1755
+ // https://drafts.csswg.org/css-transforms-2/#individual-transforms
1756
+ return transformProperties.some(value => css[value] ? css[value] !== 'none' : false) || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || willChangeValues.some(value => (css.willChange || '').includes(value)) || containValues.some(value => (css.contain || '').includes(value));
1757
+ }
1758
+ function getContainingBlock(element) {
1759
+ let currentNode = getParentNode(element);
1760
+ while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
1761
+ if (isContainingBlock(currentNode)) {
1762
+ return currentNode;
1763
+ } else if (isTopLayer(currentNode)) {
1764
+ return null;
1765
+ }
1766
+ currentNode = getParentNode(currentNode);
1767
+ }
1768
+ return null;
1769
+ }
1770
+ function isWebKit() {
1771
+ if (typeof CSS === 'undefined' || !CSS.supports) return false;
1772
+ return CSS.supports('-webkit-backdrop-filter', 'none');
1773
+ }
1774
+ const lastTraversableNodeNames = /*#__PURE__*/new Set(['html', 'body', '#document']);
1775
+ function isLastTraversableNode(node) {
1776
+ return lastTraversableNodeNames.has(getNodeName(node));
1777
+ }
1778
+ function getComputedStyle(element) {
1779
+ return getWindow(element).getComputedStyle(element);
1780
+ }
1781
+ function getNodeScroll(element) {
1782
+ if (isElement(element)) {
1783
+ return {
1784
+ scrollLeft: element.scrollLeft,
1785
+ scrollTop: element.scrollTop
1786
+ };
1787
+ }
1788
+ return {
1789
+ scrollLeft: element.scrollX,
1790
+ scrollTop: element.scrollY
1791
+ };
1792
+ }
1793
+ function getParentNode(node) {
1794
+ if (getNodeName(node) === 'html') {
1795
+ return node;
1796
+ }
1797
+ const result =
1798
+ // Step into the shadow DOM of the parent of a slotted node.
1799
+ node.assignedSlot ||
1800
+ // DOM Element detected.
1801
+ node.parentNode ||
1802
+ // ShadowRoot detected.
1803
+ isShadowRoot(node) && node.host ||
1804
+ // Fallback.
1805
+ getDocumentElement(node);
1806
+ return isShadowRoot(result) ? result.host : result;
1807
+ }
1808
+ function getNearestOverflowAncestor(node) {
1809
+ const parentNode = getParentNode(node);
1810
+ if (isLastTraversableNode(parentNode)) {
1811
+ return node.ownerDocument ? node.ownerDocument.body : node.body;
1812
+ }
1813
+ if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
1814
+ return parentNode;
1815
+ }
1816
+ return getNearestOverflowAncestor(parentNode);
1817
+ }
1818
+ function getOverflowAncestors(node, list, traverseIframes) {
1819
+ var _node$ownerDocument2;
1820
+ if (list === void 0) {
1821
+ list = [];
1822
+ }
1823
+ if (traverseIframes === void 0) {
1824
+ traverseIframes = true;
1825
+ }
1826
+ const scrollableAncestor = getNearestOverflowAncestor(node);
1827
+ const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
1828
+ const win = getWindow(scrollableAncestor);
1829
+ if (isBody) {
1830
+ const frameElement = getFrameElement(win);
1831
+ return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
1832
+ }
1833
+ return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
1834
+ }
1835
+ function getFrameElement(win) {
1836
+ return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
1837
+ }
1838
+
1839
+ function getCssDimensions(element) {
1840
+ const css = getComputedStyle(element);
1841
+ // In testing environments, the `width` and `height` properties are empty
1842
+ // strings for SVG elements, returning NaN. Fallback to `0` in this case.
1843
+ let width = parseFloat(css.width) || 0;
1844
+ let height = parseFloat(css.height) || 0;
1845
+ const hasOffset = isHTMLElement(element);
1846
+ const offsetWidth = hasOffset ? element.offsetWidth : width;
1847
+ const offsetHeight = hasOffset ? element.offsetHeight : height;
1848
+ const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
1849
+ if (shouldFallback) {
1850
+ width = offsetWidth;
1851
+ height = offsetHeight;
1852
+ }
1853
+ return {
1854
+ width,
1855
+ height,
1856
+ $: shouldFallback
1857
+ };
1858
+ }
1859
+
1860
+ function unwrapElement(element) {
1861
+ return !isElement(element) ? element.contextElement : element;
1862
+ }
1863
+
1864
+ function getScale(element) {
1865
+ const domElement = unwrapElement(element);
1866
+ if (!isHTMLElement(domElement)) {
1867
+ return createCoords(1);
1868
+ }
1869
+ const rect = domElement.getBoundingClientRect();
1870
+ const {
1871
+ width,
1872
+ height,
1873
+ $
1874
+ } = getCssDimensions(domElement);
1875
+ let x = ($ ? round(rect.width) : rect.width) / width;
1876
+ let y = ($ ? round(rect.height) : rect.height) / height;
1877
+
1878
+ // 0, NaN, or Infinity should always fallback to 1.
1879
+
1880
+ if (!x || !Number.isFinite(x)) {
1881
+ x = 1;
1882
+ }
1883
+ if (!y || !Number.isFinite(y)) {
1884
+ y = 1;
1885
+ }
1886
+ return {
1887
+ x,
1888
+ y
1889
+ };
1890
+ }
1891
+
1892
+ const noOffsets = /*#__PURE__*/createCoords(0);
1893
+ function getVisualOffsets(element) {
1894
+ const win = getWindow(element);
1895
+ if (!isWebKit() || !win.visualViewport) {
1896
+ return noOffsets;
1897
+ }
1898
+ return {
1899
+ x: win.visualViewport.offsetLeft,
1900
+ y: win.visualViewport.offsetTop
1901
+ };
1902
+ }
1903
+ function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
1904
+ if (isFixed === void 0) {
1905
+ isFixed = false;
1906
+ }
1907
+ if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
1908
+ return false;
1909
+ }
1910
+ return isFixed;
1911
+ }
1912
+
1913
+ function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
1914
+ if (includeScale === void 0) {
1915
+ includeScale = false;
1916
+ }
1917
+ if (isFixedStrategy === void 0) {
1918
+ isFixedStrategy = false;
1919
+ }
1920
+ const clientRect = element.getBoundingClientRect();
1921
+ const domElement = unwrapElement(element);
1922
+ let scale = createCoords(1);
1923
+ if (includeScale) {
1924
+ if (offsetParent) {
1925
+ if (isElement(offsetParent)) {
1926
+ scale = getScale(offsetParent);
1927
+ }
1928
+ } else {
1929
+ scale = getScale(element);
1930
+ }
1931
+ }
1932
+ const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
1933
+ let x = (clientRect.left + visualOffsets.x) / scale.x;
1934
+ let y = (clientRect.top + visualOffsets.y) / scale.y;
1935
+ let width = clientRect.width / scale.x;
1936
+ let height = clientRect.height / scale.y;
1937
+ if (domElement) {
1938
+ const win = getWindow(domElement);
1939
+ const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
1940
+ let currentWin = win;
1941
+ let currentIFrame = getFrameElement(currentWin);
1942
+ while (currentIFrame && offsetParent && offsetWin !== currentWin) {
1943
+ const iframeScale = getScale(currentIFrame);
1944
+ const iframeRect = currentIFrame.getBoundingClientRect();
1945
+ const css = getComputedStyle(currentIFrame);
1946
+ const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
1947
+ const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
1948
+ x *= iframeScale.x;
1949
+ y *= iframeScale.y;
1950
+ width *= iframeScale.x;
1951
+ height *= iframeScale.y;
1952
+ x += left;
1953
+ y += top;
1954
+ currentWin = getWindow(currentIFrame);
1955
+ currentIFrame = getFrameElement(currentWin);
1956
+ }
1957
+ }
1958
+ return rectToClientRect({
1959
+ width,
1960
+ height,
1961
+ x,
1962
+ y
1963
+ });
1964
+ }
1965
+
1966
+ // If <html> has a CSS width greater than the viewport, then this will be
1967
+ // incorrect for RTL.
1968
+ function getWindowScrollBarX(element, rect) {
1969
+ const leftScroll = getNodeScroll(element).scrollLeft;
1970
+ if (!rect) {
1971
+ return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;
1972
+ }
1973
+ return rect.left + leftScroll;
1974
+ }
1975
+
1976
+ function getHTMLOffset(documentElement, scroll, ignoreScrollbarX) {
1977
+ if (ignoreScrollbarX === void 0) {
1978
+ ignoreScrollbarX = false;
1979
+ }
1980
+ const htmlRect = documentElement.getBoundingClientRect();
1981
+ const x = htmlRect.left + scroll.scrollLeft - (ignoreScrollbarX ? 0 :
1982
+ // RTL <body> scrollbar.
1983
+ getWindowScrollBarX(documentElement, htmlRect));
1984
+ const y = htmlRect.top + scroll.scrollTop;
1985
+ return {
1986
+ x,
1987
+ y
1988
+ };
1989
+ }
1990
+
1991
+ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
1992
+ let {
1993
+ elements,
1994
+ rect,
1995
+ offsetParent,
1996
+ strategy
1997
+ } = _ref;
1998
+ const isFixed = strategy === 'fixed';
1999
+ const documentElement = getDocumentElement(offsetParent);
2000
+ const topLayer = elements ? isTopLayer(elements.floating) : false;
2001
+ if (offsetParent === documentElement || topLayer && isFixed) {
2002
+ return rect;
2003
+ }
2004
+ let scroll = {
2005
+ scrollLeft: 0,
2006
+ scrollTop: 0
2007
+ };
2008
+ let scale = createCoords(1);
2009
+ const offsets = createCoords(0);
2010
+ const isOffsetParentAnElement = isHTMLElement(offsetParent);
2011
+ if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
2012
+ if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
2013
+ scroll = getNodeScroll(offsetParent);
2014
+ }
2015
+ if (isHTMLElement(offsetParent)) {
2016
+ const offsetRect = getBoundingClientRect(offsetParent);
2017
+ scale = getScale(offsetParent);
2018
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
2019
+ offsets.y = offsetRect.y + offsetParent.clientTop;
2020
+ }
2021
+ }
2022
+ const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll, true) : createCoords(0);
2023
+ return {
2024
+ width: rect.width * scale.x,
2025
+ height: rect.height * scale.y,
2026
+ x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,
2027
+ y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y
2028
+ };
2029
+ }
2030
+
2031
+ function getClientRects(element) {
2032
+ return Array.from(element.getClientRects());
2033
+ }
2034
+
2035
+ // Gets the entire size of the scrollable document area, even extending outside
2036
+ // of the `<html>` and `<body>` rect bounds if horizontally scrollable.
2037
+ function getDocumentRect(element) {
2038
+ const html = getDocumentElement(element);
2039
+ const scroll = getNodeScroll(element);
2040
+ const body = element.ownerDocument.body;
2041
+ const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
2042
+ const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
2043
+ let x = -scroll.scrollLeft + getWindowScrollBarX(element);
2044
+ const y = -scroll.scrollTop;
2045
+ if (getComputedStyle(body).direction === 'rtl') {
2046
+ x += max(html.clientWidth, body.clientWidth) - width;
2047
+ }
2048
+ return {
2049
+ width,
2050
+ height,
2051
+ x,
2052
+ y
2053
+ };
2054
+ }
2055
+
2056
+ function getViewportRect(element, strategy) {
2057
+ const win = getWindow(element);
2058
+ const html = getDocumentElement(element);
2059
+ const visualViewport = win.visualViewport;
2060
+ let width = html.clientWidth;
2061
+ let height = html.clientHeight;
2062
+ let x = 0;
2063
+ let y = 0;
2064
+ if (visualViewport) {
2065
+ width = visualViewport.width;
2066
+ height = visualViewport.height;
2067
+ const visualViewportBased = isWebKit();
2068
+ if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
2069
+ x = visualViewport.offsetLeft;
2070
+ y = visualViewport.offsetTop;
2071
+ }
2072
+ }
2073
+ return {
2074
+ width,
2075
+ height,
2076
+ x,
2077
+ y
2078
+ };
2079
+ }
2080
+
2081
+ const absoluteOrFixed = /*#__PURE__*/new Set(['absolute', 'fixed']);
2082
+ // Returns the inner client rect, subtracting scrollbars if present.
2083
+ function getInnerBoundingClientRect(element, strategy) {
2084
+ const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
2085
+ const top = clientRect.top + element.clientTop;
2086
+ const left = clientRect.left + element.clientLeft;
2087
+ const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
2088
+ const width = element.clientWidth * scale.x;
2089
+ const height = element.clientHeight * scale.y;
2090
+ const x = left * scale.x;
2091
+ const y = top * scale.y;
2092
+ return {
2093
+ width,
2094
+ height,
2095
+ x,
2096
+ y
2097
+ };
2098
+ }
2099
+ function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
2100
+ let rect;
2101
+ if (clippingAncestor === 'viewport') {
2102
+ rect = getViewportRect(element, strategy);
2103
+ } else if (clippingAncestor === 'document') {
2104
+ rect = getDocumentRect(getDocumentElement(element));
2105
+ } else if (isElement(clippingAncestor)) {
2106
+ rect = getInnerBoundingClientRect(clippingAncestor, strategy);
2107
+ } else {
2108
+ const visualOffsets = getVisualOffsets(element);
2109
+ rect = {
2110
+ x: clippingAncestor.x - visualOffsets.x,
2111
+ y: clippingAncestor.y - visualOffsets.y,
2112
+ width: clippingAncestor.width,
2113
+ height: clippingAncestor.height
2114
+ };
2115
+ }
2116
+ return rectToClientRect(rect);
2117
+ }
2118
+ function hasFixedPositionAncestor(element, stopNode) {
2119
+ const parentNode = getParentNode(element);
2120
+ if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
2121
+ return false;
2122
+ }
2123
+ return getComputedStyle(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
2124
+ }
2125
+
2126
+ // A "clipping ancestor" is an `overflow` element with the characteristic of
2127
+ // clipping (or hiding) child elements. This returns all clipping ancestors
2128
+ // of the given element up the tree.
2129
+ function getClippingElementAncestors(element, cache) {
2130
+ const cachedResult = cache.get(element);
2131
+ if (cachedResult) {
2132
+ return cachedResult;
2133
+ }
2134
+ let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
2135
+ let currentContainingBlockComputedStyle = null;
2136
+ const elementIsFixed = getComputedStyle(element).position === 'fixed';
2137
+ let currentNode = elementIsFixed ? getParentNode(element) : element;
2138
+
2139
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
2140
+ while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
2141
+ const computedStyle = getComputedStyle(currentNode);
2142
+ const currentNodeIsContaining = isContainingBlock(currentNode);
2143
+ if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
2144
+ currentContainingBlockComputedStyle = null;
2145
+ }
2146
+ const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && absoluteOrFixed.has(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
2147
+ if (shouldDropCurrentNode) {
2148
+ // Drop non-containing blocks.
2149
+ result = result.filter(ancestor => ancestor !== currentNode);
2150
+ } else {
2151
+ // Record last containing block for next iteration.
2152
+ currentContainingBlockComputedStyle = computedStyle;
2153
+ }
2154
+ currentNode = getParentNode(currentNode);
2155
+ }
2156
+ cache.set(element, result);
2157
+ return result;
2158
+ }
2159
+
2160
+ // Gets the maximum area that the element is visible in due to any number of
2161
+ // clipping ancestors.
2162
+ function getClippingRect(_ref) {
2163
+ let {
2164
+ element,
2165
+ boundary,
2166
+ rootBoundary,
2167
+ strategy
2168
+ } = _ref;
2169
+ const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);
2170
+ const clippingAncestors = [...elementClippingAncestors, rootBoundary];
2171
+ const firstClippingAncestor = clippingAncestors[0];
2172
+ const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
2173
+ const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
2174
+ accRect.top = max(rect.top, accRect.top);
2175
+ accRect.right = min(rect.right, accRect.right);
2176
+ accRect.bottom = min(rect.bottom, accRect.bottom);
2177
+ accRect.left = max(rect.left, accRect.left);
2178
+ return accRect;
2179
+ }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
2180
+ return {
2181
+ width: clippingRect.right - clippingRect.left,
2182
+ height: clippingRect.bottom - clippingRect.top,
2183
+ x: clippingRect.left,
2184
+ y: clippingRect.top
2185
+ };
2186
+ }
2187
+
2188
+ function getDimensions(element) {
2189
+ const {
2190
+ width,
2191
+ height
2192
+ } = getCssDimensions(element);
2193
+ return {
2194
+ width,
2195
+ height
2196
+ };
2197
+ }
2198
+
2199
+ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
2200
+ const isOffsetParentAnElement = isHTMLElement(offsetParent);
2201
+ const documentElement = getDocumentElement(offsetParent);
2202
+ const isFixed = strategy === 'fixed';
2203
+ const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
2204
+ let scroll = {
2205
+ scrollLeft: 0,
2206
+ scrollTop: 0
2207
+ };
2208
+ const offsets = createCoords(0);
2209
+
2210
+ // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
2211
+ // Firefox with layout.scrollbar.side = 3 in about:config to test this.
2212
+ function setLeftRTLScrollbarOffset() {
2213
+ offsets.x = getWindowScrollBarX(documentElement);
2214
+ }
2215
+ if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
2216
+ if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
2217
+ scroll = getNodeScroll(offsetParent);
2218
+ }
2219
+ if (isOffsetParentAnElement) {
2220
+ const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
2221
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
2222
+ offsets.y = offsetRect.y + offsetParent.clientTop;
2223
+ } else if (documentElement) {
2224
+ setLeftRTLScrollbarOffset();
2225
+ }
2226
+ }
2227
+ if (isFixed && !isOffsetParentAnElement && documentElement) {
2228
+ setLeftRTLScrollbarOffset();
2229
+ }
2230
+ const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
2231
+ const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
2232
+ const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
2233
+ return {
2234
+ x,
2235
+ y,
2236
+ width: rect.width,
2237
+ height: rect.height
2238
+ };
2239
+ }
2240
+
2241
+ function isStaticPositioned(element) {
2242
+ return getComputedStyle(element).position === 'static';
2243
+ }
2244
+
2245
+ function getTrueOffsetParent(element, polyfill) {
2246
+ if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') {
2247
+ return null;
2248
+ }
2249
+ if (polyfill) {
2250
+ return polyfill(element);
2251
+ }
2252
+ let rawOffsetParent = element.offsetParent;
2253
+
2254
+ // Firefox returns the <html> element as the offsetParent if it's non-static,
2255
+ // while Chrome and Safari return the <body> element. The <body> element must
2256
+ // be used to perform the correct calculations even if the <html> element is
2257
+ // non-static.
2258
+ if (getDocumentElement(element) === rawOffsetParent) {
2259
+ rawOffsetParent = rawOffsetParent.ownerDocument.body;
2260
+ }
2261
+ return rawOffsetParent;
2262
+ }
2263
+
2264
+ // Gets the closest ancestor positioned element. Handles some edge cases,
2265
+ // such as table ancestors and cross browser bugs.
2266
+ function getOffsetParent(element, polyfill) {
2267
+ const win = getWindow(element);
2268
+ if (isTopLayer(element)) {
2269
+ return win;
2270
+ }
2271
+ if (!isHTMLElement(element)) {
2272
+ let svgOffsetParent = getParentNode(element);
2273
+ while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {
2274
+ if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {
2275
+ return svgOffsetParent;
2276
+ }
2277
+ svgOffsetParent = getParentNode(svgOffsetParent);
2278
+ }
2279
+ return win;
2280
+ }
2281
+ let offsetParent = getTrueOffsetParent(element, polyfill);
2282
+ while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {
2283
+ offsetParent = getTrueOffsetParent(offsetParent, polyfill);
2284
+ }
2285
+ if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {
2286
+ return win;
2287
+ }
2288
+ return offsetParent || getContainingBlock(element) || win;
2289
+ }
2290
+
2291
+ const getElementRects = async function (data) {
2292
+ const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
2293
+ const getDimensionsFn = this.getDimensions;
2294
+ const floatingDimensions = await getDimensionsFn(data.floating);
2295
+ return {
2296
+ reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
2297
+ floating: {
2298
+ x: 0,
2299
+ y: 0,
2300
+ width: floatingDimensions.width,
2301
+ height: floatingDimensions.height
2302
+ }
2303
+ };
2304
+ };
2305
+
2306
+ function isRTL(element) {
2307
+ return getComputedStyle(element).direction === 'rtl';
2308
+ }
2309
+
2310
+ const platform = {
2311
+ convertOffsetParentRelativeRectToViewportRelativeRect,
2312
+ getDocumentElement,
2313
+ getClippingRect,
2314
+ getOffsetParent,
2315
+ getElementRects,
2316
+ getClientRects,
2317
+ getDimensions,
2318
+ getScale,
2319
+ isElement,
2320
+ isRTL
2321
+ };
2322
+
2323
+ function rectsAreEqual(a, b) {
2324
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
2325
+ }
2326
+
2327
+ // https://samthor.au/2021/observing-dom/
2328
+ function observeMove(element, onMove) {
2329
+ let io = null;
2330
+ let timeoutId;
2331
+ const root = getDocumentElement(element);
2332
+ function cleanup() {
2333
+ var _io;
2334
+ clearTimeout(timeoutId);
2335
+ (_io = io) == null || _io.disconnect();
2336
+ io = null;
2337
+ }
2338
+ function refresh(skip, threshold) {
2339
+ if (skip === void 0) {
2340
+ skip = false;
2341
+ }
2342
+ if (threshold === void 0) {
2343
+ threshold = 1;
2344
+ }
2345
+ cleanup();
2346
+ const elementRectForRootMargin = element.getBoundingClientRect();
2347
+ const {
2348
+ left,
2349
+ top,
2350
+ width,
2351
+ height
2352
+ } = elementRectForRootMargin;
2353
+ if (!skip) {
2354
+ onMove();
2355
+ }
2356
+ if (!width || !height) {
2357
+ return;
2358
+ }
2359
+ const insetTop = floor(top);
2360
+ const insetRight = floor(root.clientWidth - (left + width));
2361
+ const insetBottom = floor(root.clientHeight - (top + height));
2362
+ const insetLeft = floor(left);
2363
+ const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
2364
+ const options = {
2365
+ rootMargin,
2366
+ threshold: max(0, min(1, threshold)) || 1
2367
+ };
2368
+ let isFirstUpdate = true;
2369
+ function handleObserve(entries) {
2370
+ const ratio = entries[0].intersectionRatio;
2371
+ if (ratio !== threshold) {
2372
+ if (!isFirstUpdate) {
2373
+ return refresh();
2374
+ }
2375
+ if (!ratio) {
2376
+ // If the reference is clipped, the ratio is 0. Throttle the refresh
2377
+ // to prevent an infinite loop of updates.
2378
+ timeoutId = setTimeout(() => {
2379
+ refresh(false, 1e-7);
2380
+ }, 1000);
2381
+ } else {
2382
+ refresh(false, ratio);
2383
+ }
2384
+ }
2385
+ if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
2386
+ // It's possible that even though the ratio is reported as 1, the
2387
+ // element is not actually fully within the IntersectionObserver's root
2388
+ // area anymore. This can happen under performance constraints. This may
2389
+ // be a bug in the browser's IntersectionObserver implementation. To
2390
+ // work around this, we compare the element's bounding rect now with
2391
+ // what it was at the time we created the IntersectionObserver. If they
2392
+ // are not equal then the element moved, so we refresh.
2393
+ refresh();
2394
+ }
2395
+ isFirstUpdate = false;
2396
+ }
2397
+
2398
+ // Older browsers don't support a `document` as the root and will throw an
2399
+ // error.
2400
+ try {
2401
+ io = new IntersectionObserver(handleObserve, {
2402
+ ...options,
2403
+ // Handle <iframe>s
2404
+ root: root.ownerDocument
2405
+ });
2406
+ } catch (_e) {
2407
+ io = new IntersectionObserver(handleObserve, options);
2408
+ }
2409
+ io.observe(element);
2410
+ }
2411
+ refresh(true);
2412
+ return cleanup;
2413
+ }
2414
+
2415
+ /**
2416
+ * Automatically updates the position of the floating element when necessary.
2417
+ * Should only be called when the floating element is mounted on the DOM or
2418
+ * visible on the screen.
2419
+ * @returns cleanup function that should be invoked when the floating element is
2420
+ * removed from the DOM or hidden from the screen.
2421
+ * @see https://floating-ui.com/docs/autoUpdate
2422
+ */
2423
+ function autoUpdate(reference, floating, update, options) {
2424
+ if (options === void 0) {
2425
+ options = {};
2426
+ }
2427
+ const {
2428
+ ancestorScroll = true,
2429
+ ancestorResize = true,
2430
+ elementResize = typeof ResizeObserver === 'function',
2431
+ layoutShift = typeof IntersectionObserver === 'function',
2432
+ animationFrame = false
2433
+ } = options;
2434
+ const referenceEl = unwrapElement(reference);
2435
+ const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...getOverflowAncestors(floating)] : [];
2436
+ ancestors.forEach(ancestor => {
2437
+ ancestorScroll && ancestor.addEventListener('scroll', update, {
2438
+ passive: true
2439
+ });
2440
+ ancestorResize && ancestor.addEventListener('resize', update);
2441
+ });
2442
+ const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
2443
+ let reobserveFrame = -1;
2444
+ let resizeObserver = null;
2445
+ if (elementResize) {
2446
+ resizeObserver = new ResizeObserver(_ref => {
2447
+ let [firstEntry] = _ref;
2448
+ if (firstEntry && firstEntry.target === referenceEl && resizeObserver) {
2449
+ // Prevent update loops when using the `size` middleware.
2450
+ // https://github.com/floating-ui/floating-ui/issues/1740
2451
+ resizeObserver.unobserve(floating);
2452
+ cancelAnimationFrame(reobserveFrame);
2453
+ reobserveFrame = requestAnimationFrame(() => {
2454
+ var _resizeObserver;
2455
+ (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
2456
+ });
2457
+ }
2458
+ update();
2459
+ });
2460
+ if (referenceEl && !animationFrame) {
2461
+ resizeObserver.observe(referenceEl);
2462
+ }
2463
+ resizeObserver.observe(floating);
2464
+ }
2465
+ let frameId;
2466
+ let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
2467
+ if (animationFrame) {
2468
+ frameLoop();
2469
+ }
2470
+ function frameLoop() {
2471
+ const nextRefRect = getBoundingClientRect(reference);
2472
+ if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
2473
+ update();
2474
+ }
2475
+ prevRefRect = nextRefRect;
2476
+ frameId = requestAnimationFrame(frameLoop);
2477
+ }
2478
+ update();
2479
+ return () => {
2480
+ var _resizeObserver2;
2481
+ ancestors.forEach(ancestor => {
2482
+ ancestorScroll && ancestor.removeEventListener('scroll', update);
2483
+ ancestorResize && ancestor.removeEventListener('resize', update);
2484
+ });
2485
+ cleanupIo == null || cleanupIo();
2486
+ (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
2487
+ resizeObserver = null;
2488
+ if (animationFrame) {
2489
+ cancelAnimationFrame(frameId);
2490
+ }
2491
+ };
2492
+ }
2493
+
2494
+ /**
2495
+ * Modifies the placement by translating the floating element along the
2496
+ * specified axes.
2497
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
2498
+ * object may be passed.
2499
+ * @see https://floating-ui.com/docs/offset
2500
+ */
2501
+ const offset$1 = offset$2;
2502
+
2503
+ /**
2504
+ * Optimizes the visibility of the floating element by shifting it in order to
2505
+ * keep it in view when it will overflow the clipping boundary.
2506
+ * @see https://floating-ui.com/docs/shift
2507
+ */
2508
+ const shift$1 = shift$2;
2509
+
2510
+ /**
2511
+ * Optimizes the visibility of the floating element by flipping the `placement`
2512
+ * in order to keep it in view when the preferred placement(s) will overflow the
2513
+ * clipping boundary. Alternative to `autoPlacement`.
2514
+ * @see https://floating-ui.com/docs/flip
2515
+ */
2516
+ const flip$1 = flip$2;
2517
+
2518
+ /**
2519
+ * Provides data that allows you to change the size of the floating element —
2520
+ * for instance, prevent it from overflowing the clipping boundary or match the
2521
+ * width of the reference element.
2522
+ * @see https://floating-ui.com/docs/size
2523
+ */
2524
+ const size$1 = size$2;
2525
+
2526
+ /**
2527
+ * Provides data to position an inner element of the floating element so that it
2528
+ * appears centered to the reference element.
2529
+ * @see https://floating-ui.com/docs/arrow
2530
+ */
2531
+ const arrow$2 = arrow$3;
2532
+
2533
+ /**
2534
+ * Computes the `x` and `y` coordinates that will place the floating element
2535
+ * next to a given reference element.
2536
+ */
2537
+ const computePosition = (reference, floating, options) => {
2538
+ // This caches the expensive `getClippingElementAncestors` function so that
2539
+ // multiple lifecycle resets re-use the same result. It only lives for a
2540
+ // single call. If other functions become expensive, we can add them as well.
2541
+ const cache = new Map();
2542
+ const mergedOptions = {
2543
+ platform,
2544
+ ...options
2545
+ };
2546
+ const platformWithCache = {
2547
+ ...mergedOptions.platform,
2548
+ _c: cache
2549
+ };
2550
+ return computePosition$1(reference, floating, {
2551
+ ...mergedOptions,
2552
+ platform: platformWithCache
2553
+ });
2554
+ };
2555
+
2556
+ var isClient = typeof document !== 'undefined';
2557
+
2558
+ var noop = function noop() {};
2559
+ var index = isClient ? useLayoutEffect : noop;
2560
+
2561
+ // Fork of `fast-deep-equal` that only does the comparisons we need and compares
2562
+ // functions
2563
+ function deepEqual(a, b) {
2564
+ if (a === b) {
2565
+ return true;
2566
+ }
2567
+ if (typeof a !== typeof b) {
2568
+ return false;
2569
+ }
2570
+ if (typeof a === 'function' && a.toString() === b.toString()) {
2571
+ return true;
2572
+ }
2573
+ let length;
2574
+ let i;
2575
+ let keys;
2576
+ if (a && b && typeof a === 'object') {
2577
+ if (Array.isArray(a)) {
2578
+ length = a.length;
2579
+ if (length !== b.length) return false;
2580
+ for (i = length; i-- !== 0;) {
2581
+ if (!deepEqual(a[i], b[i])) {
2582
+ return false;
2583
+ }
2584
+ }
2585
+ return true;
2586
+ }
2587
+ keys = Object.keys(a);
2588
+ length = keys.length;
2589
+ if (length !== Object.keys(b).length) {
2590
+ return false;
2591
+ }
2592
+ for (i = length; i-- !== 0;) {
2593
+ if (!{}.hasOwnProperty.call(b, keys[i])) {
780
2594
  return false;
781
- switch (type) {
782
- case 'email':
783
- return isEmail(value);
784
- case 'number':
785
- return !isNaN(Number(value));
786
- case 'tel':
787
- return isPhoneNumber(value);
788
- default:
789
- return true;
2595
+ }
2596
+ }
2597
+ for (i = length; i-- !== 0;) {
2598
+ const key = keys[i];
2599
+ if (key === '_owner' && a.$$typeof) {
2600
+ continue;
2601
+ }
2602
+ if (!deepEqual(a[key], b[key])) {
2603
+ return false;
2604
+ }
2605
+ }
2606
+ return true;
2607
+ }
2608
+ return a !== a && b !== b;
2609
+ }
2610
+
2611
+ function getDPR(element) {
2612
+ if (typeof window === 'undefined') {
2613
+ return 1;
2614
+ }
2615
+ const win = element.ownerDocument.defaultView || window;
2616
+ return win.devicePixelRatio || 1;
2617
+ }
2618
+
2619
+ function roundByDPR(element, value) {
2620
+ const dpr = getDPR(element);
2621
+ return Math.round(value * dpr) / dpr;
2622
+ }
2623
+
2624
+ function useLatestRef(value) {
2625
+ const ref = React.useRef(value);
2626
+ index(() => {
2627
+ ref.current = value;
2628
+ });
2629
+ return ref;
2630
+ }
2631
+
2632
+ /**
2633
+ * Provides data to position a floating element.
2634
+ * @see https://floating-ui.com/docs/useFloating
2635
+ */
2636
+ function useFloating(options) {
2637
+ if (options === void 0) {
2638
+ options = {};
2639
+ }
2640
+ const {
2641
+ placement = 'bottom',
2642
+ strategy = 'absolute',
2643
+ middleware = [],
2644
+ platform,
2645
+ elements: {
2646
+ reference: externalReference,
2647
+ floating: externalFloating
2648
+ } = {},
2649
+ transform = true,
2650
+ whileElementsMounted,
2651
+ open
2652
+ } = options;
2653
+ const [data, setData] = React.useState({
2654
+ x: 0,
2655
+ y: 0,
2656
+ strategy,
2657
+ placement,
2658
+ middlewareData: {},
2659
+ isPositioned: false
2660
+ });
2661
+ const [latestMiddleware, setLatestMiddleware] = React.useState(middleware);
2662
+ if (!deepEqual(latestMiddleware, middleware)) {
2663
+ setLatestMiddleware(middleware);
2664
+ }
2665
+ const [_reference, _setReference] = React.useState(null);
2666
+ const [_floating, _setFloating] = React.useState(null);
2667
+ const setReference = React.useCallback(node => {
2668
+ if (node !== referenceRef.current) {
2669
+ referenceRef.current = node;
2670
+ _setReference(node);
2671
+ }
2672
+ }, []);
2673
+ const setFloating = React.useCallback(node => {
2674
+ if (node !== floatingRef.current) {
2675
+ floatingRef.current = node;
2676
+ _setFloating(node);
2677
+ }
2678
+ }, []);
2679
+ const referenceEl = externalReference || _reference;
2680
+ const floatingEl = externalFloating || _floating;
2681
+ const referenceRef = React.useRef(null);
2682
+ const floatingRef = React.useRef(null);
2683
+ const dataRef = React.useRef(data);
2684
+ const hasWhileElementsMounted = whileElementsMounted != null;
2685
+ const whileElementsMountedRef = useLatestRef(whileElementsMounted);
2686
+ const platformRef = useLatestRef(platform);
2687
+ const openRef = useLatestRef(open);
2688
+ const update = React.useCallback(() => {
2689
+ if (!referenceRef.current || !floatingRef.current) {
2690
+ return;
2691
+ }
2692
+ const config = {
2693
+ placement,
2694
+ strategy,
2695
+ middleware: latestMiddleware
2696
+ };
2697
+ if (platformRef.current) {
2698
+ config.platform = platformRef.current;
2699
+ }
2700
+ computePosition(referenceRef.current, floatingRef.current, config).then(data => {
2701
+ const fullData = {
2702
+ ...data,
2703
+ // The floating element's position may be recomputed while it's closed
2704
+ // but still mounted (such as when transitioning out). To ensure
2705
+ // `isPositioned` will be `false` initially on the next open, avoid
2706
+ // setting it to `true` when `open === false` (must be specified).
2707
+ isPositioned: openRef.current !== false
2708
+ };
2709
+ if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {
2710
+ dataRef.current = fullData;
2711
+ ReactDOM.flushSync(() => {
2712
+ setData(fullData);
2713
+ });
2714
+ }
2715
+ });
2716
+ }, [latestMiddleware, placement, strategy, platformRef, openRef]);
2717
+ index(() => {
2718
+ if (open === false && dataRef.current.isPositioned) {
2719
+ dataRef.current.isPositioned = false;
2720
+ setData(data => ({
2721
+ ...data,
2722
+ isPositioned: false
2723
+ }));
2724
+ }
2725
+ }, [open]);
2726
+ const isMountedRef = React.useRef(false);
2727
+ index(() => {
2728
+ isMountedRef.current = true;
2729
+ return () => {
2730
+ isMountedRef.current = false;
2731
+ };
2732
+ }, []);
2733
+ index(() => {
2734
+ if (referenceEl) referenceRef.current = referenceEl;
2735
+ if (floatingEl) floatingRef.current = floatingEl;
2736
+ if (referenceEl && floatingEl) {
2737
+ if (whileElementsMountedRef.current) {
2738
+ return whileElementsMountedRef.current(referenceEl, floatingEl, update);
2739
+ }
2740
+ update();
2741
+ }
2742
+ }, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]);
2743
+ const refs = React.useMemo(() => ({
2744
+ reference: referenceRef,
2745
+ floating: floatingRef,
2746
+ setReference,
2747
+ setFloating
2748
+ }), [setReference, setFloating]);
2749
+ const elements = React.useMemo(() => ({
2750
+ reference: referenceEl,
2751
+ floating: floatingEl
2752
+ }), [referenceEl, floatingEl]);
2753
+ const floatingStyles = React.useMemo(() => {
2754
+ const initialStyles = {
2755
+ position: strategy,
2756
+ left: 0,
2757
+ top: 0
2758
+ };
2759
+ if (!elements.floating) {
2760
+ return initialStyles;
2761
+ }
2762
+ const x = roundByDPR(elements.floating, data.x);
2763
+ const y = roundByDPR(elements.floating, data.y);
2764
+ if (transform) {
2765
+ return {
2766
+ ...initialStyles,
2767
+ transform: "translate(" + x + "px, " + y + "px)",
2768
+ ...(getDPR(elements.floating) >= 1.5 && {
2769
+ willChange: 'transform'
2770
+ })
2771
+ };
2772
+ }
2773
+ return {
2774
+ position: strategy,
2775
+ left: x,
2776
+ top: y
2777
+ };
2778
+ }, [strategy, transform, elements.floating, data.x, data.y]);
2779
+ return React.useMemo(() => ({
2780
+ ...data,
2781
+ update,
2782
+ refs,
2783
+ elements,
2784
+ floatingStyles
2785
+ }), [data, update, refs, elements, floatingStyles]);
2786
+ }
2787
+
2788
+ /**
2789
+ * Provides data to position an inner element of the floating element so that it
2790
+ * appears centered to the reference element.
2791
+ * This wraps the core `arrow` middleware to allow React refs as the element.
2792
+ * @see https://floating-ui.com/docs/arrow
2793
+ */
2794
+ const arrow$1 = options => {
2795
+ function isRef(value) {
2796
+ return {}.hasOwnProperty.call(value, 'current');
2797
+ }
2798
+ return {
2799
+ name: 'arrow',
2800
+ options,
2801
+ fn(state) {
2802
+ const {
2803
+ element,
2804
+ padding
2805
+ } = typeof options === 'function' ? options(state) : options;
2806
+ if (element && isRef(element)) {
2807
+ if (element.current != null) {
2808
+ return arrow$2({
2809
+ element: element.current,
2810
+ padding
2811
+ }).fn(state);
2812
+ }
2813
+ return {};
2814
+ }
2815
+ if (element) {
2816
+ return arrow$2({
2817
+ element,
2818
+ padding
2819
+ }).fn(state);
2820
+ }
2821
+ return {};
2822
+ }
2823
+ };
2824
+ };
2825
+
2826
+ /**
2827
+ * Modifies the placement by translating the floating element along the
2828
+ * specified axes.
2829
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
2830
+ * object may be passed.
2831
+ * @see https://floating-ui.com/docs/offset
2832
+ */
2833
+ const offset = (options, deps) => ({
2834
+ ...offset$1(options),
2835
+ options: [options, deps]
2836
+ });
2837
+
2838
+ /**
2839
+ * Optimizes the visibility of the floating element by shifting it in order to
2840
+ * keep it in view when it will overflow the clipping boundary.
2841
+ * @see https://floating-ui.com/docs/shift
2842
+ */
2843
+ const shift = (options, deps) => ({
2844
+ ...shift$1(options),
2845
+ options: [options, deps]
2846
+ });
2847
+
2848
+ /**
2849
+ * Optimizes the visibility of the floating element by flipping the `placement`
2850
+ * in order to keep it in view when the preferred placement(s) will overflow the
2851
+ * clipping boundary. Alternative to `autoPlacement`.
2852
+ * @see https://floating-ui.com/docs/flip
2853
+ */
2854
+ const flip = (options, deps) => ({
2855
+ ...flip$1(options),
2856
+ options: [options, deps]
2857
+ });
2858
+
2859
+ /**
2860
+ * Provides data that allows you to change the size of the floating element —
2861
+ * for instance, prevent it from overflowing the clipping boundary or match the
2862
+ * width of the reference element.
2863
+ * @see https://floating-ui.com/docs/size
2864
+ */
2865
+ const size = (options, deps) => ({
2866
+ ...size$1(options),
2867
+ options: [options, deps]
2868
+ });
2869
+
2870
+ /**
2871
+ * Provides data to position an inner element of the floating element so that it
2872
+ * appears centered to the reference element.
2873
+ * This wraps the core `arrow` middleware to allow React refs as the element.
2874
+ * @see https://floating-ui.com/docs/arrow
2875
+ */
2876
+ const arrow = (options, deps) => ({
2877
+ ...arrow$1(options),
2878
+ options: [options, deps]
2879
+ });
2880
+
2881
+ function TooltipTrigger({ as, asChild = false, children, ...props }) {
2882
+ const TooltipTriggerElement = as || Button$1;
2883
+ if (asChild && isValidElement(children))
2884
+ return cloneElement(children, props);
2885
+ return jsx(TooltipTriggerElement, { ...props, children: children });
2886
+ }
2887
+ function TooltipPanel({ as, children, className, style, ...props }) {
2888
+ const TooltipPanelElement = as || 'div';
2889
+ return (jsx(TooltipPanelElement, { ...props, className: twMerge('absolute top-0 left-0 z-50 w-max rounded-md bg-neutral-50 px-2 py-1 text-sm text-neutral-950 opacity-0 shadow-lg outline-1 outline-neutral-400 data-portal:fixed data-ready:animate-fade-in dark:bg-neutral-800 dark:text-neutral-50 dark:shadow-none dark:-outline-offset-1 dark:outline-neutral-600', className), style: style, children: children }));
2890
+ }
2891
+ function Tooltip({ anchor = 'top', arrow: arrow$1, arrowClassName, children, delay = 500, offset: offset$1 = 8, onClose, onOpen, portal, }) {
2892
+ const [isOpen, setIsOpen] = useState(false), timeoutRef = useRef(undefined), arrowRef = useRef(null);
2893
+ const [bodyElement, setBodyElement] = useState(() => typeof window !== 'undefined' ? document.body : null);
2894
+ useEffect(() => {
2895
+ if (typeof window !== 'undefined' && !bodyElement) {
2896
+ const documentBody = document.body;
2897
+ setBodyElement(documentBody);
2898
+ }
2899
+ }, [bodyElement, portal]);
2900
+ const { refs, floatingStyles, isPositioned, placement, middlewareData } = useFloating({
2901
+ middleware: [
2902
+ offset(offset$1),
2903
+ flip({ padding: 20 }),
2904
+ shift({ padding: 20 }),
2905
+ size({
2906
+ apply({ availableHeight, availableWidth, elements }) {
2907
+ const height = `${Math.max(0, availableHeight) / 16}rem`, width = `${Math.min(418, availableWidth) / 16}rem`;
2908
+ elements.floating.style.maxHeight = height;
2909
+ elements.floating.style.maxWidth = width;
2910
+ },
2911
+ }),
2912
+ ...(arrowRef.current ? [arrow({ element: arrowRef.current })] : []),
2913
+ ],
2914
+ placement: anchor,
2915
+ strategy: portal ? 'fixed' : 'absolute',
2916
+ whileElementsMounted: autoUpdate,
2917
+ open: isOpen,
2918
+ });
2919
+ const openTooltip = useCallback(() => {
2920
+ clearTimeout(timeoutRef.current);
2921
+ if (delay > 0) {
2922
+ timeoutRef.current = setTimeout(() => {
2923
+ setIsOpen(true);
2924
+ onOpen?.();
2925
+ }, delay);
2926
+ }
2927
+ else {
2928
+ setIsOpen(true);
2929
+ onOpen?.();
2930
+ }
2931
+ }, [delay, onOpen]);
2932
+ const closeTooltip = useCallback(() => {
2933
+ clearTimeout(timeoutRef.current);
2934
+ setIsOpen(false);
2935
+ onClose?.();
2936
+ }, [onClose]);
2937
+ useEffect(() => {
2938
+ return () => {
2939
+ clearTimeout(timeoutRef.current);
2940
+ };
2941
+ }, []);
2942
+ const content = typeof children === 'function' ? children({ openTooltip, closeTooltip }) : children;
2943
+ const triggerElement = findComponentByType(content, TooltipTrigger), contentElement = findComponentByType(content, TooltipPanel);
2944
+ if (!contentElement)
2945
+ throw new Error('TooltipPanel must be defined in Tooltip children');
2946
+ if (!triggerElement && typeof children !== 'function')
2947
+ throw new Error('TooltipTrigger must be provided when not using render prop pattern');
2948
+ const arrowStyles = {};
2949
+ const reversedAnchor = {
2950
+ top: 'bottom',
2951
+ right: 'left',
2952
+ bottom: 'top',
2953
+ left: 'right',
2954
+ 'top-start': 'bottom left',
2955
+ 'top-end': 'bottom right',
2956
+ 'right-start': 'top left',
2957
+ 'right-end': 'bottom left',
2958
+ 'bottom-start': 'top left',
2959
+ 'bottom-end': 'top right',
2960
+ 'left-start': 'top right',
2961
+ 'left-end': 'bottom right',
2962
+ }[placement];
2963
+ if (middlewareData.arrow && arrow$1) {
2964
+ const { x, y } = middlewareData.arrow;
2965
+ const staticSide = {
2966
+ top: 'bottom',
2967
+ right: 'left',
2968
+ bottom: 'top',
2969
+ left: 'right',
2970
+ }[placement.split('-')[0]];
2971
+ if (staticSide) {
2972
+ arrowStyles[staticSide] = '-4px';
2973
+ if (x != null)
2974
+ arrowStyles.left = `${x}px`;
2975
+ if (y != null)
2976
+ arrowStyles.top = `${y}px`;
2977
+ }
790
2978
  }
2979
+ const getArrowLocationClasses = () => {
2980
+ switch (placement) {
2981
+ case 'bottom':
2982
+ case 'bottom-end':
2983
+ case 'bottom-start':
2984
+ return '-translate-y-1';
2985
+ case 'top':
2986
+ case 'top-end':
2987
+ case 'top-start':
2988
+ return 'rotate-180 translate-y-1';
2989
+ case 'left':
2990
+ case 'left-end':
2991
+ case 'left-start':
2992
+ return 'rotate-90 translate-x-2';
2993
+ case 'right':
2994
+ case 'right-end':
2995
+ case 'right-start':
2996
+ return '-rotate-90 -translate-x-2';
2997
+ }
2998
+ };
2999
+ const arrowLocationClasses = getArrowLocationClasses();
3000
+ const handleMouseEnter = e => {
3001
+ openTooltip();
3002
+ triggerElement?.props.onMouseEnter?.(e);
3003
+ };
3004
+ const handleMouseLeave = e => {
3005
+ triggerElement?.props.onMouseLeave?.(e);
3006
+ closeTooltip();
3007
+ };
3008
+ const handleTouchStart = e => {
3009
+ openTooltip();
3010
+ triggerElement?.props.onTouchStart?.(e);
3011
+ };
3012
+ const handleFocus = e => {
3013
+ triggerElement?.props.onFocus?.(e);
3014
+ openTooltip();
3015
+ };
3016
+ const handleBlur = e => {
3017
+ triggerElement?.props.onBlur?.(e);
3018
+ closeTooltip();
3019
+ };
3020
+ const tooltipContent = (jsx(Fragment$1, { children: isOpen &&
3021
+ contentElement &&
3022
+ cloneElement(contentElement, {
3023
+ children: (jsxs(Fragment$1, { children: [contentElement.props.children, arrow$1 && (jsx(ArrowSvg, { className: twMerge('absolute', arrowLocationClasses, arrowClassName), style: arrowStyles, "data-tooltip-arrow": true }))] })),
3024
+ ...(portal ? { 'data-portal': true } : {}),
3025
+ ...(isPositioned ? { 'data-ready': true } : {}),
3026
+ onMouseEnter: openTooltip,
3027
+ onMouseLeave: closeTooltip,
3028
+ onTouchStart: handleTouchStart,
3029
+ ref: (node) => {
3030
+ refs.setFloating(node);
3031
+ if (node && arrow$1) {
3032
+ const arrowElement = node.querySelector('[data-tooltip-arrow]');
3033
+ if (arrowElement)
3034
+ arrowRef.current = arrowElement;
3035
+ }
3036
+ },
3037
+ role: 'tooltip',
3038
+ style: {
3039
+ ...contentElement.props.style,
3040
+ ...floatingStyles,
3041
+ transformOrigin: reversedAnchor,
3042
+ pointerEvents: 'none',
3043
+ },
3044
+ }) }));
3045
+ return (jsxs(Fragment$1, { children: [triggerElement &&
3046
+ cloneElement(triggerElement, {
3047
+ ref: refs.setReference,
3048
+ onMouseEnter: handleMouseEnter,
3049
+ onMouseLeave: handleMouseLeave,
3050
+ onFocus: handleFocus,
3051
+ onBlur: handleBlur,
3052
+ 'aria-describedby': isOpen ? 'tooltip' : undefined,
3053
+ }), portal ? bodyElement && createPortal(tooltipContent, bodyElement) : tooltipContent] }));
3054
+ }
3055
+ function ArrowSvg({ className, ...props }) {
3056
+ return (jsxs("svg", { viewBox: '0 0 20 10', className: twMerge('h-2.5 w-5 fill-none', className), ...props, children: [jsx("path", { d: 'M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z', className: 'fill-neutral-50 dark:fill-neutral-800' }), jsx("path", { d: 'M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z', className: 'fill-neutral-400 dark:fill-none' }), jsx("path", { d: 'M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z', className: 'dark:fill-neutral-600' })] }));
791
3057
  }
3058
+
792
3059
  function Input({ checked, className, defaultValue, description, descriptionProps, disabled, fieldProps, invalid = true, label, labelProps, name, onBlur, onChange, placeholder, ref, required = true, type, value, ...props }) {
793
- const [formContext, setFormContext] = useFormContext();
3060
+ const [formContext, setFormContext] = useFormContext(), [errorMessage, setErrorMessage] = useState(undefined);
794
3061
  if (placeholder === '*')
795
3062
  placeholder = name + (required && !label ? '*' : '');
796
3063
  if (label === '*')
@@ -835,13 +3102,40 @@ function Input({ checked, className, defaultValue, description, descriptionProps
835
3102
  };
836
3103
  }, [setFormContext]);
837
3104
  const fieldContext = formContext?.find(({ id: fieldID }) => fieldID === initialFieldContext.id) || initialFieldContext;
838
- const debounceTimerRef = useRef(undefined);
3105
+ const validateField = (validValue) => {
3106
+ const noValue = !validValue || validValue === '';
3107
+ if (!required && noValue)
3108
+ return true;
3109
+ const errorMessageList = [];
3110
+ if (noValue) {
3111
+ errorMessageList.push('This field is required.');
3112
+ setErrorMessage(errorMessageList.join(' '));
3113
+ return false;
3114
+ }
3115
+ switch (type) {
3116
+ case 'email':
3117
+ if (!isEmail(validValue))
3118
+ errorMessageList.push('This is not a valid email.');
3119
+ break;
3120
+ case 'number':
3121
+ if (isNaN(Number(validValue)))
3122
+ errorMessageList.push('This is not a valid number.');
3123
+ break;
3124
+ case 'tel':
3125
+ if (!isPhoneNumber(validValue))
3126
+ errorMessageList.push('This is not a valid phone number.');
3127
+ break;
3128
+ }
3129
+ if (errorMessageList.length === 0)
3130
+ return true;
3131
+ setErrorMessage(errorMessageList.join(' '));
3132
+ return false;
3133
+ };
839
3134
  const handleChange = e => {
840
3135
  if (disabled) {
841
3136
  e.preventDefault();
842
3137
  return;
843
3138
  }
844
- clearTimeout(debounceTimerRef.current);
845
3139
  const { currentTarget } = e, { value: newValue } = currentTarget;
846
3140
  setFormContext?.(prevContext => {
847
3141
  if (!prevContext)
@@ -851,25 +3145,11 @@ function Input({ checked, className, defaultValue, description, descriptionProps
851
3145
  throw new Error(`Field with id "${initialFieldContext.id}" not found in form context.`);
852
3146
  const otherFields = prevContext.filter(({ id: fieldID }) => fieldID !== initialFieldContext.id);
853
3147
  const updatedField = { ...field, value: newValue };
3148
+ const invalidField = validateField(newValue) === false;
3149
+ if (invalidField !== field.invalid)
3150
+ updatedField.invalid = invalidField;
854
3151
  return [...otherFields, updatedField];
855
3152
  });
856
- debounceTimerRef.current = setTimeout(() => {
857
- const field = formContext?.find(({ id: fieldID }) => fieldID === initialFieldContext.id);
858
- if (!field)
859
- return;
860
- const invalid = validateField$1(newValue, field) === false;
861
- if (invalid !== field.invalid)
862
- setFormContext?.(prevContext => {
863
- if (!prevContext)
864
- return [];
865
- const field = prevContext.find(({ id: fieldID }) => fieldID === initialFieldContext.id);
866
- if (!field)
867
- throw new Error(`Field with id "${initialFieldContext.id}" not found in form context.`);
868
- const otherFields = prevContext.filter(({ id: fieldID }) => fieldID !== initialFieldContext.id);
869
- const updatedField = { ...field, invalid };
870
- return [...otherFields, updatedField];
871
- });
872
- }, 500);
873
3153
  onChange?.(e);
874
3154
  };
875
3155
  const handleBlur = e => {
@@ -878,6 +3158,8 @@ function Input({ checked, className, defaultValue, description, descriptionProps
878
3158
  return;
879
3159
  }
880
3160
  const { currentTarget } = e, { value: newValue } = currentTarget;
3161
+ if (required)
3162
+ validateField(newValue);
881
3163
  switch (type) {
882
3164
  case 'email':
883
3165
  setFormContext?.(prevContext => {
@@ -915,20 +3197,20 @@ function Input({ checked, className, defaultValue, description, descriptionProps
915
3197
  const restDescriptionProps = descriptionProps
916
3198
  ? Object.fromEntries(Object.entries(descriptionProps).filter(([key]) => key !== 'className'))
917
3199
  : {};
918
- 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(
919
- // Base styles
920
- 'rounded-xl border-1 border-neutral-500/50 bg-neutral-100 py-1 pl-2 text-neutral-950 outline-offset-1 outline-ui-sky-blue/95 transition-[background-color] duration-300 ease-exponential dark:bg-neutral-700 dark:text-neutral-50',
921
- // Pseudo styles
922
- 'focus-visible:bg-neutral-50 focus-visible:outline-3 active:bg-neutral-200 dark:focus-visible:bg-neutral-600 dark:active:bg-neutral-800 pointer-fine:hover:bg-neutral-50 pointer-fine:active:bg-neutral-200 dark:pointer-fine:hover:bg-neutral-600 dark:pointer-fine:active:bg-neutral-800',
923
- // user-invalid styles
924
- 'user-invalid:border-ui-red user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-100))] user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-800))] dark:user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))] user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-100))] user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))]',
925
- // Custom styles
926
- typeof className === 'function' ? className(bag) : className), id: fieldContext?.id, invalid: invalid, onBlur: handleBlur, onChange: handleChange, placeholder: placeholder, ref: ref, required: required, type: type, value: fieldContext?.value }), description && (jsx(Description, { ...restDescriptionProps, className: bag => twMerge('text-xs', typeof descriptionProps?.className === 'function'
3200
+ 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 })), jsxs("div", { children: [jsx(Input$1, { ...props, className: bag => twMerge(
3201
+ // Base styles
3202
+ 'w-full rounded-xl border-1 border-neutral-500/50 bg-neutral-100 py-1 pl-2 text-neutral-950 outline-offset-1 outline-ui-sky-blue/95 transition-[background-color] duration-300 ease-exponential dark:bg-neutral-700 dark:text-neutral-50',
3203
+ // Pseudo styles
3204
+ 'focus-visible:bg-neutral-50 focus-visible:outline-3 active:bg-neutral-200 dark:focus-visible:bg-neutral-600 dark:active:bg-neutral-800 pointer-fine:hover:bg-neutral-50 pointer-fine:active:bg-neutral-200 dark:pointer-fine:hover:bg-neutral-600 dark:pointer-fine:active:bg-neutral-800',
3205
+ // user-invalid styles
3206
+ 'user-invalid:border-ui-red user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-100))] user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-800))] dark:user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))] user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-100))] user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))]',
3207
+ // Custom styles
3208
+ typeof className === 'function' ? className(bag) : className), invalid: invalid, onBlur: handleBlur, onChange: handleChange, placeholder: placeholder, ref: ref, required: required, type: type, value: fieldContext?.value }), fieldContext.invalid && errorMessage && (jsxs(Tooltip, { anchor: 'top-end', arrow: true, portal: true, children: [jsx(TooltipTrigger, { as: Button, className: 'absolute top-1.25 right-1.25 z-10 size-6 min-w-0', padding: 'none', rounded: 'md', theme: 'red', children: jsx(ExclamationmarkOctagon, { className: 'absolute top-1/2 left-1/2 size-full -translate-x-1/2 -translate-y-1/2 scale-70' }) }), jsx(TooltipPanel, { children: errorMessage })] }))] }), description && (jsx(Description, { ...restDescriptionProps, className: bag => twMerge('text-xs', typeof descriptionProps?.className === 'function'
927
3209
  ? descriptionProps?.className(bag)
928
3210
  : descriptionProps?.className), children: description }))] }));
929
3211
  }
930
3212
 
931
- function SubmitButton({ children, className, error, incomplete, loading, success, theme, type = 'submit', ref, ...props }) {
3213
+ function SubmitButton({ children, className, customTheme, error, incomplete, loading, success, type = 'submit', ...props }) {
932
3214
  const [formStatus] = useFormStatus();
933
3215
  const getFormStatusButtonClasses = () => {
934
3216
  switch (formStatus) {
@@ -942,21 +3224,6 @@ function SubmitButton({ children, className, error, incomplete, loading, success
942
3224
  }
943
3225
  };
944
3226
  const formStatusButtonClasses = getFormStatusButtonClasses();
945
- const getFormStatusButtonTheme = () => {
946
- switch (formStatus) {
947
- case 'incomplete':
948
- return 'grey';
949
- case 'loading':
950
- return 'blue';
951
- case 'error':
952
- return 'red';
953
- case 'success':
954
- return 'green';
955
- default:
956
- return theme;
957
- }
958
- };
959
- const formStatusButtonTheme = getFormStatusButtonTheme();
960
3227
  const getButtonText = () => {
961
3228
  switch (formStatus) {
962
3229
  case 'incomplete':
@@ -972,19 +3239,32 @@ function SubmitButton({ children, className, error, incomplete, loading, success
972
3239
  }
973
3240
  };
974
3241
  const buttonText = getButtonText();
975
- return (jsx(Button, { ...props, className: twMerge([formStatusButtonClasses, 'w-full', className]), ref: ref, theme: formStatusButtonTheme, type: type, children: buttonText }));
3242
+ const getDataFormState = () => {
3243
+ switch (formStatus) {
3244
+ case 'error':
3245
+ return { 'data-error': true };
3246
+ case 'incomplete':
3247
+ return { 'data-incomplete': true };
3248
+ case 'loading':
3249
+ return { 'data-loading': true };
3250
+ case 'readonly':
3251
+ return { 'data-readonly': true };
3252
+ case 'ready':
3253
+ return { 'data-ready': true };
3254
+ case 'success':
3255
+ return { 'data-success': true };
3256
+ default:
3257
+ return {};
3258
+ }
3259
+ };
3260
+ const dataFormState = getDataFormState();
3261
+ return (jsx(Button, { ...props, ...dataFormState, as: 'button', className: twMerge([formStatusButtonClasses, 'w-full text-white data-loading:text-black', className]), customTheme: {
3262
+ themeColor: twMerge('data-error:[--theme-color:var(--color-ui-red)] data-incomplete:[--theme-color:var(--color-ui-grey)] data-loading:[--theme-color:var(--color-ui-yellow)] data-readonly:[--theme-color:var(--color-ui-grey)] data-ready:[--theme-color:var(--color-ui-blue)] data-success:[--theme-color:var(--color-ui-green)]', customTheme?.themeColor),
3263
+ }, theme: 'custom', type: type, children: buttonText }));
976
3264
  }
977
3265
 
978
- function validateField(value, { required }) {
979
- const noValue = !value || value === '';
980
- if (!required && noValue)
981
- return true;
982
- if (noValue)
983
- return false;
984
- return true;
985
- }
986
3266
  function Textarea({ className, defaultValue, description, descriptionProps, disabled, fieldProps, invalid = true, label, labelProps, name, onBlur, onChange, placeholder, ref, required = true, value, ...props }) {
987
- const [formContext, setFormContext] = useFormContext();
3267
+ const [formContext, setFormContext] = useFormContext(), [errorMessage, setErrorMessage] = useState(undefined);
988
3268
  if (placeholder === '*')
989
3269
  placeholder = name + (required && !label ? '*' : '');
990
3270
  if (label === '*')
@@ -1012,13 +3292,26 @@ function Textarea({ className, defaultValue, description, descriptionProps, disa
1012
3292
  };
1013
3293
  }, [setFormContext]);
1014
3294
  const fieldContext = formContext?.find(({ id: fieldID }) => fieldID === initialFieldContext.id) || initialFieldContext;
1015
- const debounceTimerRef = useRef(undefined);
3295
+ const validateField = (validValue) => {
3296
+ const noValue = !validValue || validValue === '';
3297
+ if (!required && noValue)
3298
+ return true;
3299
+ const errorMessageList = [];
3300
+ if (noValue) {
3301
+ errorMessageList.push('This field is required.');
3302
+ setErrorMessage(errorMessageList.join(' '));
3303
+ return false;
3304
+ }
3305
+ if (errorMessageList.length === 0)
3306
+ return true;
3307
+ setErrorMessage(errorMessageList.join(' '));
3308
+ return false;
3309
+ };
1016
3310
  const handleChange = e => {
1017
3311
  if (disabled) {
1018
3312
  e.preventDefault();
1019
3313
  return;
1020
3314
  }
1021
- clearTimeout(debounceTimerRef.current);
1022
3315
  const { currentTarget } = e, { value: newValue } = currentTarget;
1023
3316
  setFormContext?.(prevContext => {
1024
3317
  if (!prevContext)
@@ -1028,25 +3321,11 @@ function Textarea({ className, defaultValue, description, descriptionProps, disa
1028
3321
  throw new Error(`Field with id "${initialFieldContext.id}" not found in form context.`);
1029
3322
  const otherFields = prevContext.filter(({ id: fieldID }) => fieldID !== initialFieldContext.id);
1030
3323
  const updatedField = { ...field, value: newValue };
3324
+ const invalidField = validateField(newValue) === false;
3325
+ if (invalidField !== field.invalid)
3326
+ updatedField.invalid = invalidField;
1031
3327
  return [...otherFields, updatedField];
1032
3328
  });
1033
- debounceTimerRef.current = setTimeout(() => {
1034
- const field = formContext?.find(({ id: fieldID }) => fieldID === initialFieldContext.id);
1035
- if (!field)
1036
- return;
1037
- const invalid = validateField(newValue, field) === false;
1038
- if (invalid !== field.invalid)
1039
- setFormContext?.(prevContext => {
1040
- if (!prevContext)
1041
- return [];
1042
- const field = prevContext.find(({ id: fieldID }) => fieldID === initialFieldContext.id);
1043
- if (!field)
1044
- throw new Error(`Field with id "${initialFieldContext.id}" not found in form context.`);
1045
- const otherFields = prevContext.filter(({ id: fieldID }) => fieldID !== initialFieldContext.id);
1046
- const updatedField = { ...field, invalid };
1047
- return [...otherFields, updatedField];
1048
- });
1049
- }, 500);
1050
3329
  onChange?.(e);
1051
3330
  };
1052
3331
  const restFieldProps = fieldProps
@@ -1058,15 +3337,15 @@ function Textarea({ className, defaultValue, description, descriptionProps, disa
1058
3337
  const restDescriptionProps = descriptionProps
1059
3338
  ? Object.fromEntries(Object.entries(descriptionProps).filter(([key]) => key !== 'className'))
1060
3339
  : {};
1061
- 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(Textarea$1, { ...props, className: bag => twMerge(
1062
- // Base styles
1063
- 'field-sizing-content resize-none rounded-xl border-1 border-neutral-500/50 bg-neutral-100 py-1 pl-2 text-neutral-950 outline-offset-1 outline-ui-sky-blue/95 transition-[background-color] duration-300 ease-exponential dark:bg-neutral-700 dark:text-neutral-50',
1064
- // Pseudo styles
1065
- 'focus-visible:bg-neutral-50 focus-visible:outline-3 active:bg-neutral-200 dark:focus-visible:bg-neutral-600 dark:active:bg-neutral-800 pointer-fine:hover:bg-neutral-50 pointer-fine:active:bg-neutral-200 dark:pointer-fine:hover:bg-neutral-600 dark:pointer-fine:active:bg-neutral-800',
1066
- // user-invalid styles
1067
- 'user-invalid:border-ui-red user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-100))] user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-800))] dark:user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))] user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-100))] user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))]',
1068
- // Custom styles
1069
- typeof className === 'function' ? className(bag) : className), id: fieldContext?.id, invalid: invalid, onChange: handleChange, placeholder: placeholder, ref: ref, required: required, value: fieldContext?.value }), description && (jsx(Description, { ...restDescriptionProps, className: bag => twMerge('text-xs', typeof descriptionProps?.className === 'function'
3340
+ 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 })), jsxs("div", { className: 'z-10 -mb-1.5', children: [jsx(Textarea$1, { ...props, className: bag => twMerge(
3341
+ // Base styles
3342
+ 'field-sizing-content w-full resize-none rounded-xl border-1 border-neutral-500/50 bg-neutral-100 py-1 pl-2 text-neutral-950 outline-offset-1 outline-ui-sky-blue/95 transition-[background-color] duration-300 ease-exponential dark:bg-neutral-700 dark:text-neutral-50',
3343
+ // Pseudo styles
3344
+ 'focus-visible:bg-neutral-50 focus-visible:outline-3 active:bg-neutral-200 dark:focus-visible:bg-neutral-600 dark:active:bg-neutral-800 pointer-fine:hover:bg-neutral-50 pointer-fine:active:bg-neutral-200 dark:pointer-fine:hover:bg-neutral-600 dark:pointer-fine:active:bg-neutral-800',
3345
+ // user-invalid styles
3346
+ 'user-invalid:border-ui-red user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-100))] user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:bg-[color-mix(in_oklab,var(--color-ui-red)_20%,var(--color-neutral-800))] dark:user-invalid:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))] user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-100))] user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-100))] user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-100))] dark:user-invalid:pointer-fine:hover:bg-[color-mix(in_oklab,var(--color-ui-red)_10%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklab,var(--color-ui-red)_1%,var(--color-neutral-800))] dark:user-invalid:pointer-fine:active:bg-[color-mix(in_oklab,var(--color-ui-red)_25%,var(--color-neutral-800))]',
3347
+ // Custom styles
3348
+ typeof className === 'function' ? className(bag) : className), id: fieldContext?.id, invalid: invalid, onChange: handleChange, placeholder: placeholder, ref: ref, required: required, value: fieldContext?.value }), fieldContext.invalid && errorMessage && (jsxs(Tooltip, { anchor: 'top-end', arrow: true, portal: true, children: [jsx(TooltipTrigger, { as: Button, className: 'absolute top-1.25 right-1.25 z-10 size-6 min-w-0', padding: 'none', rounded: 'md', theme: 'red', children: jsx(ExclamationmarkOctagon, { className: 'absolute top-1/2 left-1/2 size-full -translate-x-1/2 -translate-y-1/2 scale-70' }) }), jsx(TooltipPanel, { children: errorMessage })] }))] }), description && (jsx(Description, { ...restDescriptionProps, className: bag => twMerge('text-xs', typeof descriptionProps?.className === 'function'
1070
3349
  ? descriptionProps?.className(bag)
1071
3350
  : descriptionProps?.className), children: description }))] }));
1072
3351
  }
@@ -1091,12 +3370,12 @@ function FormComponent({ as, children, className, handleSubmit, onError, onSubmi
1091
3370
  const response = await onSubmit?.({ event: e, formContext });
1092
3371
  if (response && ('error' in response || response.status === 'error')) {
1093
3372
  setFormStatus?.('error');
1094
- onError?.({ event: e, error: response.error || 'An error occurred when submitting the form.' });
3373
+ onError?.({ event: e, error: response.error || 'An error occurred when submitting the form.', formContext });
1095
3374
  return;
1096
3375
  }
1097
3376
  if ((response && response.status === 'success') || !response) {
1098
3377
  setFormStatus?.('success');
1099
- onSuccess?.({ event: e });
3378
+ onSuccess?.({ event: e, formContext });
1100
3379
  }
1101
3380
  });
1102
3381
  const FormElement = as || 'form';
@@ -1134,27 +3413,23 @@ function Heading({ as = 'h2', children, customize, className, id, ref, ...props
1134
3413
  const getBaseClasses = () => {
1135
3414
  switch (as) {
1136
3415
  case 'h1':
1137
- return customize?.h1 || twSort('pb-2.5 text-6xl font-black last:pb-0');
3416
+ return twMerge('pb-2.5 text-6xl font-black last:pb-0', customize?.h1);
1138
3417
  case 'h3':
1139
- return customize?.h3 || twSort('pb-2 text-4xl font-extralight last:pb-0');
3418
+ return twMerge('pb-2 text-4xl font-extralight last:pb-0', customize?.h3);
1140
3419
  case 'h4':
1141
- return customize?.h4 || twSort('pb-2 text-3xl font-extrabold last:pb-0');
3420
+ return twMerge('pb-2 text-3xl font-extrabold last:pb-0', customize?.h4);
1142
3421
  case 'h5':
1143
- return customize?.h5 || twSort('pb-1.5 text-2xl font-semibold last:pb-0');
3422
+ return twMerge('pb-1.5 text-2xl font-semibold last:pb-0', customize?.h5);
1144
3423
  case 'h6':
1145
- return customize?.h6 || twSort('pb-1 text-xl font-bold last:pb-0');
3424
+ return twMerge('pb-1 text-xl font-bold last:pb-0', customize?.h6);
1146
3425
  default:
1147
- return customize?.h2 || twSort('pb-2.5 text-5xl font-medium last:pb-0');
3426
+ return twMerge('pb-2.5 text-5xl font-medium last:pb-0', customize?.h2);
1148
3427
  }
1149
3428
  };
1150
3429
  const baseClasses = getBaseClasses();
1151
3430
  return (jsx(H, { ref: ref, id: targetableID, ...props, className: twMerge(baseClasses, className), children: children }));
1152
3431
  }
1153
3432
 
1154
- function xmark(props) {
1155
- 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' }) }));
1156
- }
1157
-
1158
3433
  function ModalTrigger({ as, ...props }) {
1159
3434
  const Element = as || Button$1;
1160
3435
  return jsx(Element, { ...props });
@@ -1174,12 +3449,14 @@ function Modal({ children, className, onClose, onOpen, place = 'bottom' }) {
1174
3449
  startDragCoords = useRef({ x: 0, y: 0 });
1175
3450
  const [allowDragClose, setAllowDragClose] = useState(false), [readyToClose, setReadyToClose] = useState(false);
1176
3451
  const openModal = () => {
1177
- console.log('open');
3452
+ if (isOpen)
3453
+ return;
1178
3454
  setIsOpen(true);
1179
3455
  onOpen?.();
1180
3456
  };
1181
3457
  const closeModal = () => {
1182
- console.log('close');
3458
+ if (!isOpen)
3459
+ return;
1183
3460
  setIsOpen(false);
1184
3461
  onClose?.();
1185
3462
  };
@@ -1254,23 +3531,23 @@ function Modal({ children, className, onClose, onOpen, place = 'bottom' }) {
1254
3531
  }
1255
3532
  return (jsxs(Fragment$1, { children: [allowDragClose &&
1256
3533
  bodyElement &&
1257
- 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 &&
3534
+ createPortal(jsx("div", { ref: dragMoveBoxRef, className: 'fixed inset-0 z-99 h-dvh w-screen bg-transparent active:cursor-grabbing pointer-coarse:hidden', onMouseMove: handleMouseMove, onMouseUp: disableMouseDragClose }), bodyElement), triggerElement &&
1258
3535
  cloneElement(triggerElement, { onClick: openModal }), jsxs(Dialog, { open: isOpen, onClose: closeModal, className: [
1259
3536
  'isolate z-50',
1260
3537
  place === 'bottom' &&
1261
3538
  'after:fixed after:inset-x-0 after:bottom-0 after:-z-10 after:h-16 after:bg-neutral-50 sm:after:hidden',
1262
3539
  ].join(' '), children: [jsx(DialogBackdrop, { transition: true, className: [
1263
- 'duration-750 ease-exponential data-closed:opacity-0 fixed inset-0 cursor-pointer transition-[opacity_background-color_backdrop-filter_-webkit-backdrop-filter] delay-100',
3540
+ 'fixed inset-0 cursor-pointer transition-[opacity_background-color_backdrop-filter_-webkit-backdrop-filter] delay-100 duration-750 ease-exponential data-closed:opacity-0',
1264
3541
  readyToClose
1265
3542
  ? 'bg-neutral-50/5 backdrop-blur-[1px] dark:bg-neutral-950/5'
1266
3543
  : 'bg-neutral-50/25 backdrop-blur-sm dark:bg-neutral-950/25',
1267
- ].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'
1268
- ? 'data-enter:translate-y-[calc(-50%+12rem)] data-leave:translate-y-[calc(-50%-8rem)] top-1/2 -translate-y-1/2 rounded-2xl'
1269
- : '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: [
1270
- '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',
3544
+ ].join(' '), children: jsx(Button, { theme: 'blue', padding: 'none', rounded: 'full', className: 'group/button fixed top-4 right-4 h-7 w-7 overflow-x-hidden transition-[scale_width_filter] pointer-fine:hover:w-20', children: jsxs("div", { className: 'absolute top-1 right-1 flex items-center gap-1 pt-px transition-transform duration-300 ease-exponential pointer-fine:group-hover/button:-translate-x-0.5', children: [jsxs("span", { className: 'block text-xs leading-none font-medium text-neutral-50 uppercase', children: ["Close", jsx("span", { className: 'sr-only', children: " Modal" })] }), jsx(xmark, { className: '-top-px block size-5 scale-75 rotate-90 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('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] duration-750 ease-exponential data-closed:scale-50 data-closed:opacity-0 sm:w-[calc(100vw-2rem)] sm:max-w-fit sm:p-6 sm:shadow-2xl lg:p-8 dark:bg-neutral-900', place === 'center'
3545
+ ? 'top-1/2 -translate-y-1/2 rounded-2xl data-enter:translate-y-[calc(-50%+12rem)] data-leave:translate-y-[calc(-50%-8rem)]'
3546
+ : 'bottom-0 h-fit max-h-[calc(100dvh-4rem)] translate-y-0 rounded-t-4xl data-enter:translate-y-full data-leave:translate-y-full sm:top-1/2 sm:bottom-auto sm:rounded-t-2xl sm:rounded-b-2xl sm:data-enter:translate-y-[calc(-50%+12rem)] sm:data-leave:translate-y-[calc(-50%-8rem)] sm:data-open:-translate-y-1/2 pointer-fine:top-1/2 pointer-fine:bottom-auto pointer-fine:-translate-y-1/2 pointer-fine:rounded-2xl', className), children: [jsx("button", { onTouchStart: enableTouchClose, onMouseDown: enableMouseClose, className: [
3547
+ '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 after:ease-exponential active:cursor-grabbing',
1271
3548
  readyToClose
1272
3549
  ? 'after:scale-x-200 after:scale-y-200 after:bg-ui-blue'
1273
- : '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',
3550
+ : 'after:bg-ui-grey/50 active:after:scale-x-150 active:after:scale-y-125 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',
1274
3551
  ].join(' '), children: jsx("span", { className: 'sr-only', children: "Drag down to close" }) }), dialogElement] })] })] }));
1275
3552
  }
1276
3553
 
@@ -1325,5 +3602,5 @@ function Time({ children, dateObject, dateTime, day, hours, milliseconds, minute
1325
3602
  return (jsx("time", { dateTime: dateAndTime, ref: ref, ...props, children: dateDisplay }));
1326
3603
  }
1327
3604
 
1328
- export { Anchor, Button, Form, Ghost, Heading, Input, Link, Modal, ModalDialog, ModalTrigger, SubmitButton, Textarea, Time };
3605
+ export { Anchor, Button, Details, DetailsBody, DetailsSummary, DropDown, DropDownButton, DropDownItem, DropDownItems, DropDownSection, DropDownSeparator, Fieldset, Form, Ghost, Heading, Input, Link, Modal, ModalDialog, ModalTrigger, SubmitButton, Textarea, Time, Tooltip, TooltipPanel, TooltipTrigger };
1329
3606
  //# sourceMappingURL=components.esm.js.map