negodesign 0.0.39 → 0.0.40

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.
@@ -2,7 +2,6 @@
2
2
  import * as Carousel from "../../../../ui/carousel/index.js";
3
3
  import type { CarouselBadgeProps } from "../../types.js";
4
4
  import { HugeiconsIcon } from "@hugeicons/svelte";
5
- import CarouselSlot from "../../../panel/CarouselSlot.svelte";
6
5
  import Skeleton from "../../../../ui/skeleton/skeleton.svelte";
7
6
  import { useDevice } from "../../../../../hooks/responsive.svelte";
8
7
 
@@ -11,72 +10,72 @@
11
10
  imageClass,
12
11
  iconClass,
13
12
  labelClass,
14
- activeClass,
15
- valueActive,
13
+ activeClass = "bg-gradient text-white rounded-sm px-3",
16
14
  isLoading = false,
17
- itemCarouselClass,
18
15
  orientation = "horizontal",
19
- isBorderItem = false,
20
- isBorderBottom = false,
21
- isButtonPreviousAndNext = true,
22
- buttonPreviousAndNextClass = "",
16
+ onClick,
23
17
  }: CarouselBadgeProps = $props();
24
18
 
25
19
  const DEFAULT_IMG_OR_ICON_CLASS = "size-3";
20
+ const NAV_BUTTON_CLASS =
21
+ "absolute top-1/2 -translate-y-1/2 mt-0.5 md:mr-0 z-50 bg-blue-700! text-white! cursor-pointer!";
22
+
26
23
  const responsive = useDevice();
24
+ const skeletonCount = $derived(responsive.isMobile ? 2 : 8);
25
+
26
+ let selectedValue = $state<unknown>(undefined);
27
+
28
+ function isSelected(item: (typeof items)[number]) {
29
+ return item.value !== undefined && item.value === selectedValue;
30
+ }
31
+
32
+ function selectItem(item: (typeof items)[number]) {
33
+ selectedValue = item.value;
34
+ item.onClick?.(item.value);
35
+ onClick?.(item.value);
36
+ }
27
37
  </script>
28
38
 
29
- <CarouselSlot
30
- {isBorderBottom}
31
- {isButtonPreviousAndNext}
32
- {buttonPreviousAndNextClass}
33
- >
34
- {#if isLoading}
35
- <div class="flex items-center justify-between w-full gap-1 md:gap-2">
36
- {#each Array.from({ length: responsive.isMobile ? 2 : 10 }) as _, i (`skeleton-${i}`)}
37
- <Skeleton class="h-4 w-25 bg-black/20" />
38
- {/each}
39
- </div>
40
- {:else}
41
- {#each (items ?? []) as item, i (`badge-${i}-${item.value ?? item.label ?? i}`)}
42
- <Carousel.Item
43
- onclick={() => item.onClick?.(item.value)}
44
- class={`
45
- flex cursor-pointer items-center justify-center gap-1 basis-auto mx-3 pl-0
46
- ${isBorderItem ? "border border-solid border-gray-300 rounded-lg" : ""}
47
- ${item.value === valueActive ? activeClass : ""}
48
- ${itemCarouselClass}`}
49
- >
50
- <div
51
- class={`
52
- flex gap-1 mx-2 p-0.5 justify-center items-center
53
- ${orientation === "horizontal" ? "flex-row" : "flex-col"}
54
- `}
55
- >
56
- {#if item.image}
57
- <img
58
- src={item.image}
59
- alt={item.label}
60
- class={imageClass || DEFAULT_IMG_OR_ICON_CLASS}
61
- />
62
- {:else if item.icon}
63
- {#if typeof item.icon === "string"}
64
- <div>
65
- <i
66
- class={`${item.icon} ${iconClass || DEFAULT_IMG_OR_ICON_CLASS}`}
67
- >
68
- </i>
69
- </div>
70
- {:else}
71
- <HugeiconsIcon
72
- icon={item.icon}
73
- class={iconClass || DEFAULT_IMG_OR_ICON_CLASS}
74
- />
75
- {/if}
76
- {/if}
77
- <div class={`${labelClass}`}>{item.label}</div>
78
- </div>
79
- </Carousel.Item>
80
- {/each}
39
+ {#snippet itemVisual(item: (typeof items)[number])}
40
+ {#if item.image}
41
+ <img
42
+ src={item.image}
43
+ alt={item.label}
44
+ class={imageClass || DEFAULT_IMG_OR_ICON_CLASS}
45
+ />
46
+ {:else if typeof item.icon === "string"}
47
+ <i class={`${item.icon} ${iconClass || DEFAULT_IMG_OR_ICON_CLASS}`}></i>
48
+ {:else if item.icon}
49
+ <HugeiconsIcon
50
+ icon={item.icon}
51
+ class={iconClass || DEFAULT_IMG_OR_ICON_CLASS}
52
+ />
81
53
  {/if}
82
- </CarouselSlot>
54
+ {/snippet}
55
+
56
+ <Carousel.Root>
57
+ <Carousel.Content>
58
+ {#if isLoading}
59
+ <div class="flex items-center justify-between w-full gap-1 md:gap-2">
60
+ {#each Array.from({ length: skeletonCount }) as _, i (`skeleton-${i}`)}
61
+ <Skeleton class="h-4 w-25 bg-gray-900/90" />
62
+ {/each}
63
+ </div>
64
+ {:else}
65
+ {#each items as item, i (`badge-${i}-${item.value ?? item.label ?? i}`)}
66
+ <Carousel.Item class="basis-auto" onclick={() => selectItem(item)}>
67
+ <div
68
+ class="flex gap-1 mx-2 p-0.5 justify-center items-center cursor-pointer
69
+ {orientation === 'horizontal' ? 'flex-row' : 'flex-col'}
70
+ {isSelected(item) ? activeClass : ''}"
71
+ >
72
+ {@render itemVisual(item)}
73
+ <div class={labelClass}>{item.label}</div>
74
+ </div>
75
+ </Carousel.Item>
76
+ {/each}
77
+ {/if}
78
+ </Carousel.Content>
79
+ <Carousel.Previous class="-left-8 {NAV_BUTTON_CLASS}" />
80
+ <Carousel.Next class="-right-8 {NAV_BUTTON_CLASS}" />
81
+ </Carousel.Root>
@@ -59,20 +59,9 @@ export interface CarouselBadgeProps {
59
59
  labelClass?: string;
60
60
  /** Classe CSS personalizada para o estado ativo */
61
61
  activeClass?: string;
62
- /** Valor do item ativo por padrão */
63
- valueActive?: string;
64
62
  /** Estado de carregamento (skeleton) */
65
63
  isLoading?: boolean;
66
- /** Exibe borda em cada item */
67
- isBorderItem?: boolean;
68
- /** Exibe borda inferior no container */
69
- isBorderBottom?: boolean;
70
- /** Classe CSS adicional para cada item do carousel */
71
- itemCarouselClass?: string;
72
- /** Exibe botões anterior/próximo */
73
- isButtonPreviousAndNext?: boolean;
74
- /** Classe CSS personalizada para botões anterior/próximo */
75
- buttonPreviousAndNextClass?: string;
64
+ onClick?: (value: string | number) => void;
76
65
  }
77
66
  /**
78
67
  * Item individual do CarouselHero — slide com imagem,
package/dist/globals.css CHANGED
@@ -17,7 +17,6 @@
17
17
  --color-blue-400: oklch(70.7% 0.165 254.624);
18
18
  --color-blue-500: oklch(62.3% 0.214 259.815);
19
19
  --color-blue-700: oklch(48.8% 0.243 264.376);
20
- --color-blue-900: oklch(37.9% 0.146 265.522);
21
20
  --color-indigo-600: oklch(51.1% 0.262 276.966);
22
21
  --color-slate-400: oklch(70.4% 0.04 256.788);
23
22
  --color-slate-500: oklch(55.4% 0.046 257.417);
@@ -462,9 +461,6 @@
462
461
  .mx-2 {
463
462
  margin-inline: calc(var(--spacing) * 2);
464
463
  }
465
- .mx-3 {
466
- margin-inline: calc(var(--spacing) * 3);
467
- }
468
464
  .mx-3\.5 {
469
465
  margin-inline: calc(var(--spacing) * 3.5);
470
466
  }
@@ -1528,10 +1524,6 @@
1528
1524
  --tw-border-style: none;
1529
1525
  border-style: none;
1530
1526
  }
1531
- .border-solid {
1532
- --tw-border-style: solid;
1533
- border-style: solid;
1534
- }
1535
1527
  .border-\(--color-border\) {
1536
1528
  border-color: var(--color-border);
1537
1529
  }
@@ -1691,9 +1683,6 @@
1691
1683
  .bg-blue-700\! {
1692
1684
  background-color: var(--color-blue-700) !important;
1693
1685
  }
1694
- .bg-blue-900 {
1695
- background-color: var(--color-blue-900);
1696
- }
1697
1686
  .bg-border {
1698
1687
  background-color: var(--border);
1699
1688
  }
@@ -1763,6 +1752,12 @@
1763
1752
  background-color: color-mix(in oklab, var(--color-gray-800) 50%, transparent);
1764
1753
  }
1765
1754
  }
1755
+ .bg-gray-900\/90 {
1756
+ background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 90%, transparent);
1757
+ @supports (color: color-mix(in lab, red, red)) {
1758
+ background-color: color-mix(in oklab, var(--color-gray-900) 90%, transparent);
1759
+ }
1760
+ }
1766
1761
  .bg-green-500 {
1767
1762
  background-color: var(--color-green-500);
1768
1763
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "negodesign",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "sideEffects": [