negodesign 0.0.39 → 0.0.41
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.
- package/dist/components/core/card/profile/01/CardProfile01.svelte +1 -1
- package/dist/components/core/card/profile/02/CardProfile02.svelte +1 -1
- package/dist/components/core/card/shared/TruncatableText.svelte +2 -1
- package/dist/components/core/carousel/badge/ui/CarouselBadge.svelte +63 -61
- package/dist/components/core/carousel/grid/product/ui/CarouselGridProduct.svelte +2 -2
- package/dist/components/core/carousel/grid/profile/ui/CarouselGridProfile.svelte +2 -2
- package/dist/components/core/carousel/grid/promotion/ui/CarouselGridPromotion.svelte +2 -2
- package/dist/components/core/carousel/types.d.ts +2 -12
- package/dist/components/core/panel/CarouselSlot.svelte +1 -1
- package/dist/globals.css +14 -16
- package/package.json +1 -1
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
$effect(() => {
|
|
19
19
|
if (!textEl) return;
|
|
20
20
|
const check = () =>
|
|
21
|
-
(isTruncated =
|
|
21
|
+
(isTruncated =
|
|
22
|
+
(textEl?.scrollHeight ?? 0) > (textEl?.clientHeight ?? 0) + 1);
|
|
22
23
|
// requestAnimationFrame garante que o layout com o clamp já foi aplicado
|
|
23
24
|
// antes de medirmos — medir no mesmo tick pode dar valores desatualizados.
|
|
24
25
|
requestAnimationFrame(check);
|
|
@@ -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,75 @@
|
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
isButtonPreviousAndNext = true,
|
|
22
|
-
buttonPreviousAndNextClass = "",
|
|
16
|
+
itemClass,
|
|
17
|
+
onClick,
|
|
23
18
|
}: CarouselBadgeProps = $props();
|
|
24
19
|
|
|
25
20
|
const DEFAULT_IMG_OR_ICON_CLASS = "size-3";
|
|
21
|
+
const NAV_BUTTON_CLASS =
|
|
22
|
+
"absolute top-1/2 -translate-y-1/2 mt-0.5 md:mr-0 z-50 bg-blue-700! text-white! cursor-pointer!";
|
|
23
|
+
|
|
26
24
|
const responsive = useDevice();
|
|
25
|
+
const skeletonCount = $derived(responsive.isMobile ? 2 : 8);
|
|
26
|
+
|
|
27
|
+
let selectedValue = $state<unknown>(undefined);
|
|
28
|
+
|
|
29
|
+
function isSelected(item: (typeof items)[number]) {
|
|
30
|
+
return item.value !== undefined && item.value === selectedValue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function selectItem(item: (typeof items)[number]) {
|
|
34
|
+
selectedValue = item.value;
|
|
35
|
+
item.onClick?.(item.value);
|
|
36
|
+
onClick?.(item.value);
|
|
37
|
+
}
|
|
27
38
|
</script>
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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}
|
|
40
|
+
{#snippet itemVisual(item: (typeof items)[number])}
|
|
41
|
+
{#if item.image}
|
|
42
|
+
<img
|
|
43
|
+
src={item.image}
|
|
44
|
+
alt={item.label}
|
|
45
|
+
class={imageClass || DEFAULT_IMG_OR_ICON_CLASS}
|
|
46
|
+
/>
|
|
47
|
+
{:else if typeof item.icon === "string"}
|
|
48
|
+
<i class={`${item.icon} ${iconClass || DEFAULT_IMG_OR_ICON_CLASS}`}></i>
|
|
49
|
+
{:else if item.icon}
|
|
50
|
+
<HugeiconsIcon
|
|
51
|
+
icon={item.icon}
|
|
52
|
+
class={iconClass || DEFAULT_IMG_OR_ICON_CLASS}
|
|
53
|
+
/>
|
|
81
54
|
{/if}
|
|
82
|
-
|
|
55
|
+
{/snippet}
|
|
56
|
+
|
|
57
|
+
<Carousel.Root>
|
|
58
|
+
<Carousel.Content>
|
|
59
|
+
{#if isLoading}
|
|
60
|
+
<div class="flex items-center justify-between w-full gap-1 md:gap-2">
|
|
61
|
+
{#each Array.from({ length: skeletonCount }) as _, i (`skeleton-${i}`)}
|
|
62
|
+
<Skeleton class="h-4 w-25 bg-gray-900/90" />
|
|
63
|
+
{/each}
|
|
64
|
+
</div>
|
|
65
|
+
{:else}
|
|
66
|
+
{#each items as item, i (`badge-${i}-${item.value ?? item.label ?? i}`)}
|
|
67
|
+
<Carousel.Item class="basis-auto" onclick={() => selectItem(item)}>
|
|
68
|
+
<div
|
|
69
|
+
class="flex gap-1 mx-2 p-0.5 justify-center items-center cursor-pointer
|
|
70
|
+
{orientation === 'horizontal' ? 'flex-row' : 'flex-col'}
|
|
71
|
+
{isSelected(item) ? activeClass : ''}
|
|
72
|
+
{itemClass}
|
|
73
|
+
"
|
|
74
|
+
>
|
|
75
|
+
{@render itemVisual(item)}
|
|
76
|
+
<div class={labelClass}>{item.label}</div>
|
|
77
|
+
</div>
|
|
78
|
+
</Carousel.Item>
|
|
79
|
+
{/each}
|
|
80
|
+
{/if}
|
|
81
|
+
</Carousel.Content>
|
|
82
|
+
<Carousel.Previous class="-left-8 {NAV_BUTTON_CLASS}" />
|
|
83
|
+
<Carousel.Next class="-right-8 {NAV_BUTTON_CLASS}" />
|
|
84
|
+
</Carousel.Root>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
{#if isLoading}
|
|
35
35
|
{#each Array.from( { length: responsive.isMobile ? 3 : 6 }, ) as _, i (`loading-${i}`)}
|
|
36
36
|
{#if responsive.isMobile}
|
|
37
|
-
<Carousel.Item class="pl-2 basis-auto">
|
|
37
|
+
<Carousel.Item class="pl-2 basis-auto w-[300px]">
|
|
38
38
|
<CardProduct id={i} {variant} isLoading />
|
|
39
39
|
</Carousel.Item>
|
|
40
40
|
{:else}
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
{:else}
|
|
47
47
|
{#each items as item, i (`product-${item.id ?? i}`)}
|
|
48
48
|
{#if responsive.isMobile}
|
|
49
|
-
<Carousel.Item class="pl-2 basis-auto">
|
|
49
|
+
<Carousel.Item class="pl-2 basis-auto w-[300px]">
|
|
50
50
|
<CardProduct
|
|
51
51
|
{...item}
|
|
52
52
|
{variant}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
{#if isLoading}
|
|
39
39
|
{#each Array.from( { length: responsive.isMobile ? 3 : 6 }, ) as _, i (`loading-${i}`)}
|
|
40
40
|
{#if responsive.isMobile}
|
|
41
|
-
<Carousel.Item class="pl-2 basis-auto">
|
|
41
|
+
<Carousel.Item class="pl-2 basis-auto w-[300px]">
|
|
42
42
|
<CardProfile id={i} {variant} isLoading />
|
|
43
43
|
</Carousel.Item>
|
|
44
44
|
{:else}
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
{:else}
|
|
51
51
|
{#each items as item, i (`profile-${item.id ?? i}`)}
|
|
52
52
|
{#if responsive.isMobile}
|
|
53
|
-
<Carousel.Item class="pl-2 basis-auto">
|
|
53
|
+
<Carousel.Item class="pl-2 basis-auto w-[300px]">
|
|
54
54
|
<CardProfile
|
|
55
55
|
{...item}
|
|
56
56
|
{variant}
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
{#if isLoading}
|
|
34
34
|
{#each Array.from( { length: responsive.isMobile ? 3 : 6 }, ) as _, i (`loading-${i}`)}
|
|
35
35
|
{#if responsive.isMobile}
|
|
36
|
-
<Carousel.Item class="pl-2 basis-auto">
|
|
36
|
+
<Carousel.Item class="pl-2 basis-auto w-[300px]">
|
|
37
37
|
<CardPromotion id={i} isLoading />
|
|
38
38
|
</Carousel.Item>
|
|
39
39
|
{:else}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
{:else}
|
|
46
46
|
{#each items as item, i (`promotion-${item.id ?? i}`)}
|
|
47
47
|
{#if responsive.isMobile}
|
|
48
|
-
<Carousel.Item class="pl-2 basis-auto">
|
|
48
|
+
<Carousel.Item class="pl-2 basis-auto w-[300px]">
|
|
49
49
|
<CardPromotion
|
|
50
50
|
{...item}
|
|
51
51
|
{isDescriptionIcon}
|
|
@@ -59,20 +59,10 @@ 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
|
-
|
|
67
|
-
|
|
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
|
+
itemClass?: string;
|
|
65
|
+
onClick?: (value: string | number) => void;
|
|
76
66
|
}
|
|
77
67
|
/**
|
|
78
68
|
* Item individual do CarouselHero — slide com imagem,
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
{#if positionButtonPreviousAndNext == "top_right" || responsive.isMobile}
|
|
43
43
|
{#if isButtonPreviousAndNext}
|
|
44
44
|
<div
|
|
45
|
-
class="absolute -top-
|
|
45
|
+
class="absolute -top-5 md:-top-10 right-8 md:right-10 lg:right-12 z-20"
|
|
46
46
|
>
|
|
47
47
|
<Carousel.Previous
|
|
48
48
|
class={`${styleTopCenter} ${buttonPreviousAndNextClass}`}
|
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);
|
|
@@ -297,12 +296,12 @@
|
|
|
297
296
|
.end-2 {
|
|
298
297
|
inset-inline-end: calc(var(--spacing) * 2);
|
|
299
298
|
}
|
|
299
|
+
.-top-5 {
|
|
300
|
+
top: calc(var(--spacing) * -5);
|
|
301
|
+
}
|
|
300
302
|
.-top-12 {
|
|
301
303
|
top: calc(var(--spacing) * -12);
|
|
302
304
|
}
|
|
303
|
-
.-top-16 {
|
|
304
|
-
top: calc(var(--spacing) * -16);
|
|
305
|
-
}
|
|
306
305
|
.top-0 {
|
|
307
306
|
top: 0px;
|
|
308
307
|
}
|
|
@@ -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
|
}
|
|
@@ -805,6 +801,9 @@
|
|
|
805
801
|
.h-32 {
|
|
806
802
|
height: calc(var(--spacing) * 32);
|
|
807
803
|
}
|
|
804
|
+
.h-32\.5 {
|
|
805
|
+
height: calc(var(--spacing) * 32.5);
|
|
806
|
+
}
|
|
808
807
|
.h-36 {
|
|
809
808
|
height: calc(var(--spacing) * 36);
|
|
810
809
|
}
|
|
@@ -1528,10 +1527,6 @@
|
|
|
1528
1527
|
--tw-border-style: none;
|
|
1529
1528
|
border-style: none;
|
|
1530
1529
|
}
|
|
1531
|
-
.border-solid {
|
|
1532
|
-
--tw-border-style: solid;
|
|
1533
|
-
border-style: solid;
|
|
1534
|
-
}
|
|
1535
1530
|
.border-\(--color-border\) {
|
|
1536
1531
|
border-color: var(--color-border);
|
|
1537
1532
|
}
|
|
@@ -1691,9 +1686,6 @@
|
|
|
1691
1686
|
.bg-blue-700\! {
|
|
1692
1687
|
background-color: var(--color-blue-700) !important;
|
|
1693
1688
|
}
|
|
1694
|
-
.bg-blue-900 {
|
|
1695
|
-
background-color: var(--color-blue-900);
|
|
1696
|
-
}
|
|
1697
1689
|
.bg-border {
|
|
1698
1690
|
background-color: var(--border);
|
|
1699
1691
|
}
|
|
@@ -1763,6 +1755,12 @@
|
|
|
1763
1755
|
background-color: color-mix(in oklab, var(--color-gray-800) 50%, transparent);
|
|
1764
1756
|
}
|
|
1765
1757
|
}
|
|
1758
|
+
.bg-gray-900\/90 {
|
|
1759
|
+
background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 90%, transparent);
|
|
1760
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1761
|
+
background-color: color-mix(in oklab, var(--color-gray-900) 90%, transparent);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1766
1764
|
.bg-green-500 {
|
|
1767
1765
|
background-color: var(--color-green-500);
|
|
1768
1766
|
}
|
|
@@ -4022,8 +4020,8 @@
|
|
|
4022
4020
|
.md\:h-25 {
|
|
4023
4021
|
height: calc(var(--spacing) * 25);
|
|
4024
4022
|
}
|
|
4025
|
-
.md\:h-
|
|
4026
|
-
height: calc(var(--spacing) *
|
|
4023
|
+
.md\:h-36 {
|
|
4024
|
+
height: calc(var(--spacing) * 36);
|
|
4027
4025
|
}
|
|
4028
4026
|
.md\:h-44 {
|
|
4029
4027
|
height: calc(var(--spacing) * 44);
|