negodesign 0.0.68 → 0.0.70
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/banner/CtaCardImageBanner.svelte +109 -0
- package/dist/components/core/banner/CtaCardImageBanner.svelte.d.ts +4 -0
- package/dist/components/core/banner/types.d.ts +37 -0
- package/dist/components/core/carousel/grid/shared/ui/CarouselGridSlot.svelte +1 -1
- package/dist/components/core/carousel/shared/ui/CarouselHeader.svelte +3 -4
- package/dist/components/core/grid/data/types.d.ts +3 -0
- package/dist/components/core/grid/ui/01/Grid01.svelte +2 -1
- package/dist/components/core/grid/ui/02/Grid02.svelte +2 -1
- package/dist/components/core/grid/ui/ItemsPanel.svelte +26 -0
- package/dist/components/core/grid/ui/ItemsPanel.svelte.d.ts +7 -0
- package/dist/components/core/grid/ui/ItemsPanelCarousel.svelte +37 -0
- package/dist/components/core/grid/ui/ItemsPanelCarousel.svelte.d.ts +4 -0
- package/dist/components/core/grid/ui/{PanelGrid.svelte → ItemsPanelGrid.svelte} +11 -5
- package/dist/components/core/grid/ui/ItemsPanelGrid.svelte.d.ts +4 -0
- package/dist/components/core/grid/ui/ItemsSimpleGrid.svelte.d.ts +4 -0
- package/dist/components/core/nav/data/types.d.ts +15 -0
- package/dist/components/core/nav/ui/ComplexMenu.svelte +27 -9
- package/dist/components/core/nav/ui/shared/MenuListItem.svelte +7 -2
- package/dist/components/core/nav/ui/shared/MenuListItem.svelte.d.ts +5 -1
- package/dist/components/core/nav/ui/shared/navigation/NavDropdown.svelte +23 -14
- package/dist/components/core/nav/ui/shared/navigation/NavDropdown.svelte.d.ts +3 -1
- package/dist/components/core/nav/ui/shared/navigation/NavigationMenuItem.svelte +12 -9
- package/dist/components/core/nav/ui/shared/navigation/NavigationMenuItemCard.svelte +12 -7
- package/dist/components/core/nav/ui/shared/navigation/NavigationMenuItemGrid.svelte +9 -3
- package/dist/components/core/nav/ui/shared/navigation/NavigationMenuItemList.svelte +7 -4
- package/dist/components/core/nav/ui/shared/navigation/NavigationMenuItems.svelte +3 -3
- package/dist/components/core/panel/NotFoundEmpty.svelte +2 -15
- package/dist/components/core/panel/NotFoundEmpty.svelte.d.ts +2 -14
- package/dist/components/core/panel/type.d.ts +25 -0
- package/dist/globals.css +125 -11
- package/dist/index.d.ts +164 -16
- package/dist/index.js +164 -16
- package/dist/types/index.d.ts +14 -4
- package/package.json +1 -1
- package/dist/components/core/grid/ui/PanelGrid.svelte.d.ts +0 -4
- package/dist/components/core/grid/ui/SimpleGrid.svelte.d.ts +0 -4
- /package/dist/components/core/grid/ui/{SimpleGrid.svelte → ItemsSimpleGrid.svelte} +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { CtaCardImageBannerProps } from "./types";
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
title,
|
|
6
|
+
description,
|
|
7
|
+
primaryText,
|
|
8
|
+
secondaryText,
|
|
9
|
+
primaryHref,
|
|
10
|
+
secondaryHref,
|
|
11
|
+
onClickPrimary,
|
|
12
|
+
onClickSecondary,
|
|
13
|
+
imageSrc = "https://tailwindcss.com/plus-assets/img/component-images/dark-project-app-screenshot.png",
|
|
14
|
+
imageAlt = "Imagem de destaque",
|
|
15
|
+
imageWidth = 1824,
|
|
16
|
+
imageHeight = 1080,
|
|
17
|
+
class: className = "",
|
|
18
|
+
imageContainerClass = "",
|
|
19
|
+
}: CtaCardImageBannerProps = $props();
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<div class="bg-white">
|
|
23
|
+
<div class="mx-auto max-w-7xl py-24 sm:px-6 sm:py-32 lg:px-8">
|
|
24
|
+
<div
|
|
25
|
+
class="relative isolate overflow-hidden bg-gradient px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0 {className}"
|
|
26
|
+
>
|
|
27
|
+
<svg
|
|
28
|
+
viewBox="0 0 1024 1024"
|
|
29
|
+
aria-hidden="true"
|
|
30
|
+
class="absolute top-1/2 left-1/2 -z-10 size-256 -translate-y-1/2 mask-[radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0"
|
|
31
|
+
>
|
|
32
|
+
<circle
|
|
33
|
+
r="512"
|
|
34
|
+
cx="512"
|
|
35
|
+
cy="512"
|
|
36
|
+
fill="url(#759c1415-0410-454c-8f7c-9a820de03641)"
|
|
37
|
+
fill-opacity="0.7"
|
|
38
|
+
/>
|
|
39
|
+
<defs>
|
|
40
|
+
<radialGradient id="759c1415-0410-454c-8f7c-9a820de03641">
|
|
41
|
+
<stop stop-color="#7775D6" />
|
|
42
|
+
<stop offset="1" stop-color="#E935C1" />
|
|
43
|
+
</radialGradient>
|
|
44
|
+
</defs>
|
|
45
|
+
</svg>
|
|
46
|
+
|
|
47
|
+
{#snippet pill(
|
|
48
|
+
label: string,
|
|
49
|
+
href: string | undefined,
|
|
50
|
+
onClick: (() => void) | undefined,
|
|
51
|
+
style: "primary" | "secondary",
|
|
52
|
+
)}
|
|
53
|
+
{#if href}
|
|
54
|
+
<a
|
|
55
|
+
{href}
|
|
56
|
+
class={style === "primary"
|
|
57
|
+
? "rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-xs hover:bg-gray-100 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
|
|
58
|
+
: "text-sm/6 font-semibold text-white hover:text-gray-100"}
|
|
59
|
+
>
|
|
60
|
+
{label}
|
|
61
|
+
{#if style === "secondary"}<span aria-hidden="true">→</span>{/if}
|
|
62
|
+
</a>
|
|
63
|
+
{:else}
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
onclick={() => onClick?.()}
|
|
67
|
+
class={style === "primary"
|
|
68
|
+
? "rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-xs hover:bg-gray-100 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
|
|
69
|
+
: "text-sm/6 font-semibold text-white hover:text-gray-100"}
|
|
70
|
+
>
|
|
71
|
+
{label}
|
|
72
|
+
{#if style === "secondary"}<span aria-hidden="true">→</span>{/if}
|
|
73
|
+
</button>
|
|
74
|
+
{/if}
|
|
75
|
+
{/snippet}
|
|
76
|
+
|
|
77
|
+
<div
|
|
78
|
+
class="mx-auto max-w-md text-center lg:mx-0 lg:flex-auto lg:py-32 lg:text-left"
|
|
79
|
+
>
|
|
80
|
+
<h2
|
|
81
|
+
class="text-3xl font-semibold tracking-tight text-balance text-white sm:text-4xl"
|
|
82
|
+
>
|
|
83
|
+
{title}
|
|
84
|
+
</h2>
|
|
85
|
+
{#if description}
|
|
86
|
+
<p class="mt-6 text-lg/8 text-pretty text-gray-300">{description}</p>
|
|
87
|
+
{/if}
|
|
88
|
+
<div
|
|
89
|
+
class="mt-10 flex items-center justify-center gap-x-6 lg:justify-start"
|
|
90
|
+
>
|
|
91
|
+
{@render pill(primaryText, primaryHref, onClickPrimary, "primary")}
|
|
92
|
+
{#if secondaryText}
|
|
93
|
+
{@render pill(secondaryText, secondaryHref, onClickSecondary, "secondary")}
|
|
94
|
+
{/if}
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="relative mt-16 h-80 lg:mt-8 {imageContainerClass}">
|
|
98
|
+
<img
|
|
99
|
+
src={imageSrc}
|
|
100
|
+
alt={imageAlt}
|
|
101
|
+
width={imageWidth}
|
|
102
|
+
height={imageHeight}
|
|
103
|
+
loading="lazy"
|
|
104
|
+
class="absolute top-0 left-0 w-228 max-w-none rounded-md bg-white/5 ring-1 ring-white/10"
|
|
105
|
+
/>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
@@ -71,3 +71,40 @@ export type CtaCardBannerProps = {
|
|
|
71
71
|
color: string;
|
|
72
72
|
}>;
|
|
73
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* CTA banner com imagem de destaque em fundo gradiente.
|
|
76
|
+
* Título, descrição e até dois CTAs (primário e secundário), cada um com
|
|
77
|
+
* texto, href e/ou callback de clique, além da imagem e seus atributos.
|
|
78
|
+
* Usa `bg-gradient` como fundo padrão (customizável via `containerClass`).
|
|
79
|
+
* @component
|
|
80
|
+
*/
|
|
81
|
+
export type CtaCardImageBannerProps = {
|
|
82
|
+
/** Título principal do banner. */
|
|
83
|
+
title: string;
|
|
84
|
+
/** Texto de apoio / descrição. */
|
|
85
|
+
description?: string;
|
|
86
|
+
/** Texto do CTA primário. */
|
|
87
|
+
primaryText: string;
|
|
88
|
+
/** href do CTA primário (link). */
|
|
89
|
+
primaryHref?: string;
|
|
90
|
+
/** Chamado ao clicar no CTA primário. */
|
|
91
|
+
onClickPrimary?: () => void;
|
|
92
|
+
/** Texto do CTA secundário. */
|
|
93
|
+
secondaryText?: string;
|
|
94
|
+
/** href do CTA secundário (link). */
|
|
95
|
+
secondaryHref?: string;
|
|
96
|
+
/** Chamado ao clicar no CTA secundário. */
|
|
97
|
+
onClickSecondary?: () => void;
|
|
98
|
+
/** URL da imagem de destaque. */
|
|
99
|
+
imageSrc?: string;
|
|
100
|
+
/** Texto alternativo da imagem. */
|
|
101
|
+
imageAlt?: string;
|
|
102
|
+
/** Largura da imagem (atributo width). */
|
|
103
|
+
imageWidth?: number;
|
|
104
|
+
/** Altura da imagem (atributo height). */
|
|
105
|
+
imageHeight?: number;
|
|
106
|
+
/** Classe CSS adicional para o artigo (fundo). */
|
|
107
|
+
class?: string;
|
|
108
|
+
/** Classe CSS do container da imagem. */
|
|
109
|
+
imageContainerClass?: string;
|
|
110
|
+
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { useDevice } from "../../../../../../hooks/responsive.svelte";
|
|
6
6
|
import Autoplay from "embla-carousel-autoplay";
|
|
7
7
|
import type { GridProps } from "../../../../grid/data/types";
|
|
8
|
-
import SimpleGrid from "../../../../grid/ui/
|
|
8
|
+
import SimpleGrid from "../../../../grid/ui/ItemsSimpleGrid.svelte";
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
11
|
slotProps?: CarouselSlotProps;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
<div class="w-full flex justify-center">
|
|
26
26
|
<div
|
|
27
|
-
class="w-
|
|
27
|
+
class="w-full p-2 rounded-xl
|
|
28
28
|
{isBorder ? 'border border-gray-50 dark:border-gray-800' : ''}
|
|
29
29
|
{containerClass}"
|
|
30
30
|
>
|
|
@@ -43,9 +43,8 @@
|
|
|
43
43
|
{#if onButtonViewAll}
|
|
44
44
|
<div>
|
|
45
45
|
<Button
|
|
46
|
-
variant="
|
|
47
|
-
|
|
48
|
-
class="flex items-center gap-0.5"
|
|
46
|
+
variant="outline"
|
|
47
|
+
class="flex items-center gap-0.5 border"
|
|
49
48
|
onclick={onButtonViewAll}
|
|
50
49
|
>
|
|
51
50
|
{$t("label.view.full")}
|
|
@@ -6,14 +6,17 @@ export interface ItemGridProps {
|
|
|
6
6
|
description?: string;
|
|
7
7
|
iconClass?: string;
|
|
8
8
|
titleClass?: string;
|
|
9
|
+
itemClassName?: string;
|
|
9
10
|
descriptionClass?: string;
|
|
10
11
|
icon: string | IconSvgElement;
|
|
11
12
|
onClick?: (id: string | number) => void;
|
|
12
13
|
}
|
|
13
14
|
export interface GridProps {
|
|
14
15
|
items?: ItemGridProps[];
|
|
16
|
+
itemClassName?: string;
|
|
15
17
|
className?: string;
|
|
16
18
|
variant?: 1 | 2;
|
|
17
19
|
isLoading?: boolean;
|
|
20
|
+
selectedKey?: string | number;
|
|
18
21
|
onClick?: (id: string | number) => void;
|
|
19
22
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
iconClass,
|
|
13
13
|
titleClass,
|
|
14
14
|
description,
|
|
15
|
+
itemClassName,
|
|
15
16
|
descriptionClass,
|
|
16
17
|
onClick,
|
|
17
18
|
}: ItemGridProps = $props();
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
onclick={() => {
|
|
22
23
|
if (id && onClick) onClick(id);
|
|
23
24
|
}}
|
|
24
|
-
class="flex flex-col justify-center items-center gap-2
|
|
25
|
+
class="flex flex-col justify-center items-center gap-2 rounded-xl {itemClassName}"
|
|
25
26
|
>
|
|
26
27
|
<IconRenderGrid {icon} {iconClass} {isLoading} />
|
|
27
28
|
<TitleGrid {titleClass} {title} {isLoading} />
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
description,
|
|
13
13
|
iconClass,
|
|
14
14
|
titleClass,
|
|
15
|
+
itemClassName,
|
|
15
16
|
descriptionClass,
|
|
16
17
|
onClick,
|
|
17
18
|
}: ItemGridProps = $props();
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
onclick={() => {
|
|
22
23
|
if (id && onClick) onClick(id);
|
|
23
24
|
}}
|
|
24
|
-
class="flex flex-col justify-center items-center gap-2 border rounded-lg p-2 cursor-pointer
|
|
25
|
+
class="flex flex-col justify-center items-center gap-2 border rounded-lg p-2 cursor-pointer {itemClassName}"
|
|
25
26
|
>
|
|
26
27
|
<IconRenderGrid {icon} {iconClass} {isLoading} />
|
|
27
28
|
<TitleGrid {titleClass} {title} {isLoading} />
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { GridProps } from "../data/types";
|
|
3
|
+
import PanelCarousel from "./ItemsPanelCarousel.svelte";
|
|
4
|
+
import PanelGrid from "./ItemsPanelGrid.svelte";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
style = "grid",
|
|
8
|
+
onClick,
|
|
9
|
+
...restProps
|
|
10
|
+
}: GridProps & {
|
|
11
|
+
style?: "inline" | "grid";
|
|
12
|
+
} = $props();
|
|
13
|
+
|
|
14
|
+
let selectedKey = $state<string | number | undefined>("");
|
|
15
|
+
|
|
16
|
+
function selectItem(id: string | number) {
|
|
17
|
+
selectedKey = `${id}`;
|
|
18
|
+
onClick?.(id);
|
|
19
|
+
}
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
{#if style == "inline"}
|
|
23
|
+
<PanelCarousel {...restProps} {selectedKey} onClick={selectItem} />
|
|
24
|
+
{:else}
|
|
25
|
+
<PanelGrid {...restProps} {selectedKey} onClick={selectItem} />
|
|
26
|
+
{/if}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GridProps } from "../data/types";
|
|
2
|
+
type $$ComponentProps = GridProps & {
|
|
3
|
+
style?: "inline" | "grid";
|
|
4
|
+
};
|
|
5
|
+
declare const ItemsPanel: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type ItemsPanel = ReturnType<typeof ItemsPanel>;
|
|
7
|
+
export default ItemsPanel;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as Carousel from "../../../ui/carousel/index.js";
|
|
3
|
+
import type { GridProps } from "../data/types";
|
|
4
|
+
import Grid02 from "./02/Grid02.svelte";
|
|
5
|
+
import Grid01 from "./01/Grid01.svelte";
|
|
6
|
+
|
|
7
|
+
let { variant, isLoading, items, itemClassName, onClick }: GridProps =
|
|
8
|
+
$props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<Carousel.Root>
|
|
12
|
+
<Carousel.Content>
|
|
13
|
+
{#if isLoading}
|
|
14
|
+
<div class="flex items-center justify-between w-full gap-1 md:gap-2">
|
|
15
|
+
{#each Array.from({ length: 10 }) as _, i (`skeleton-${i}`)}
|
|
16
|
+
<Carousel.Item class="basis-auto relative">
|
|
17
|
+
{#if variant == 2}
|
|
18
|
+
<Grid02 title={`${i}`} description="" icon="" {isLoading} />
|
|
19
|
+
{:else}
|
|
20
|
+
<Grid01 title={`${i}`} description="" icon="" {isLoading} />
|
|
21
|
+
{/if}
|
|
22
|
+
</Carousel.Item>
|
|
23
|
+
{/each}
|
|
24
|
+
</div>
|
|
25
|
+
{:else}
|
|
26
|
+
{#each items as item, i (`panel-${i}`)}
|
|
27
|
+
<Carousel.Item class="basis-auto relative">
|
|
28
|
+
{#if variant == 2}
|
|
29
|
+
<Grid02 {...item} {onClick} {itemClassName} />
|
|
30
|
+
{:else}
|
|
31
|
+
<Grid01 {...item} {onClick} {itemClassName} />
|
|
32
|
+
{/if}
|
|
33
|
+
</Carousel.Item>
|
|
34
|
+
{/each}
|
|
35
|
+
{/if}
|
|
36
|
+
</Carousel.Content>
|
|
37
|
+
</Carousel.Root>
|
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
import Grid02 from "./02/Grid02.svelte";
|
|
5
5
|
import Grid01 from "./01/Grid01.svelte";
|
|
6
6
|
|
|
7
|
-
let {
|
|
7
|
+
let {
|
|
8
|
+
variant,
|
|
9
|
+
className,
|
|
10
|
+
isLoading,
|
|
11
|
+
items,
|
|
12
|
+
itemClassName,
|
|
13
|
+
onClick,
|
|
14
|
+
}: GridProps = $props();
|
|
8
15
|
|
|
9
16
|
const styleMobile = "flex justify-between overflow-x-auto no-scrollbar";
|
|
10
17
|
|
|
@@ -14,8 +21,7 @@
|
|
|
14
21
|
<div
|
|
15
22
|
class="gap-4 my-2 {responsive.isMobile
|
|
16
23
|
? styleMobile
|
|
17
|
-
: 'grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 max-h-237.5 overflow-y-auto'}
|
|
18
|
-
{className}"
|
|
24
|
+
: 'grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 max-h-237.5 overflow-y-auto'} {className}"
|
|
19
25
|
>
|
|
20
26
|
{#if isLoading}
|
|
21
27
|
{#each Array.from({ length: responsive.isMobile ? 3 : 10 }) as it, i (i)}
|
|
@@ -28,9 +34,9 @@
|
|
|
28
34
|
{:else}
|
|
29
35
|
{#each items as item, i (i)}
|
|
30
36
|
{#if variant == 2}
|
|
31
|
-
<Grid02 {...item} {onClick} />
|
|
37
|
+
<Grid02 {...item} {onClick} {itemClassName} />
|
|
32
38
|
{:else}
|
|
33
|
-
<Grid01 {...item} {onClick} />
|
|
39
|
+
<Grid01 {...item} {onClick} {itemClassName} />
|
|
34
40
|
{/if}
|
|
35
41
|
{/each}
|
|
36
42
|
{/if}
|
|
@@ -9,9 +9,14 @@ export type ListItemProps = HTMLAttributes<HTMLAnchorElement> & {
|
|
|
9
9
|
export type NavigationMenuItemProps = {
|
|
10
10
|
label: string;
|
|
11
11
|
href?: string;
|
|
12
|
+
textClass?: string;
|
|
13
|
+
hoverClass?: string;
|
|
12
14
|
};
|
|
13
15
|
export type NavigationMenuItemCardProps = {
|
|
14
16
|
label?: string;
|
|
17
|
+
textClass?: string;
|
|
18
|
+
subTextClass?: string;
|
|
19
|
+
hoverClass?: string;
|
|
15
20
|
header?: {
|
|
16
21
|
label: string;
|
|
17
22
|
description: string;
|
|
@@ -24,14 +29,22 @@ export type NavigationMenuItemCardProps = {
|
|
|
24
29
|
};
|
|
25
30
|
export type NavigationMenuItemGridProps = {
|
|
26
31
|
label: string;
|
|
32
|
+
textClass?: string;
|
|
33
|
+
hoverClass?: string;
|
|
34
|
+
subTextClass?: string;
|
|
27
35
|
grids?: ListItemProps[];
|
|
28
36
|
};
|
|
29
37
|
export type NavigationMenuItemListProps = {
|
|
30
38
|
label: string;
|
|
39
|
+
textClass?: string;
|
|
40
|
+
hoverClass?: string;
|
|
41
|
+
subTextClass?: string;
|
|
31
42
|
list?: ListItemProps[];
|
|
32
43
|
};
|
|
33
44
|
export type NavigationMenuItemsProps = {
|
|
34
45
|
label: string;
|
|
46
|
+
textClass?: string;
|
|
47
|
+
hoverClass?: string;
|
|
35
48
|
items?: {
|
|
36
49
|
title: string;
|
|
37
50
|
href: string;
|
|
@@ -40,6 +53,8 @@ export type NavigationMenuItemsProps = {
|
|
|
40
53
|
export type ComplexMenuProps = IMenuProps & {
|
|
41
54
|
menus: (NavigationMenuItemProps | NavigationMenuItemListProps | NavigationMenuItemCardProps | NavigationMenuItemGridProps | NavigationMenuItemsProps)[];
|
|
42
55
|
textClass?: string;
|
|
56
|
+
subTextClass?: string;
|
|
57
|
+
hoverClass?: string;
|
|
43
58
|
};
|
|
44
59
|
export type MenuVarientProps = ComplexMenuProps | SimpleMenuProps;
|
|
45
60
|
export type MenuProps = IMenuProps & {
|
|
@@ -13,21 +13,39 @@
|
|
|
13
13
|
import NavigationMenuItemList from "./shared/navigation/NavigationMenuItemList.svelte";
|
|
14
14
|
import NavigationMenuItems from "./shared/navigation/NavigationMenuItems.svelte";
|
|
15
15
|
|
|
16
|
-
let { menus
|
|
16
|
+
let { menus, textClass, subTextClass, hoverClass }: ComplexMenuProps =
|
|
17
|
+
$props();
|
|
17
18
|
</script>
|
|
18
19
|
|
|
19
|
-
<ul
|
|
20
|
-
|
|
20
|
+
<ul
|
|
21
|
+
class="flex list-none flex-1 flex-wrap items-center justify-center {textClass}"
|
|
22
|
+
>
|
|
23
|
+
{#each menus as link, i (i)}
|
|
21
24
|
{#if isCard(link)}
|
|
22
|
-
<NavigationMenuItemCard
|
|
25
|
+
<NavigationMenuItemCard
|
|
26
|
+
{...link}
|
|
27
|
+
{textClass}
|
|
28
|
+
{subTextClass}
|
|
29
|
+
{hoverClass}
|
|
30
|
+
/>
|
|
23
31
|
{:else if isGrid(link)}
|
|
24
|
-
<NavigationMenuItemGrid
|
|
32
|
+
<NavigationMenuItemGrid
|
|
33
|
+
{...link}
|
|
34
|
+
{textClass}
|
|
35
|
+
{subTextClass}
|
|
36
|
+
{hoverClass}
|
|
37
|
+
/>
|
|
25
38
|
{:else if isList(link)}
|
|
26
|
-
<NavigationMenuItemList
|
|
39
|
+
<NavigationMenuItemList
|
|
40
|
+
{...link}
|
|
41
|
+
{textClass}
|
|
42
|
+
{subTextClass}
|
|
43
|
+
{hoverClass}
|
|
44
|
+
/>
|
|
27
45
|
{:else if isItems(link)}
|
|
28
|
-
<NavigationMenuItems {...link} />
|
|
46
|
+
<NavigationMenuItems {...link} {textClass} {hoverClass} />
|
|
29
47
|
{:else if isItem(link)}
|
|
30
|
-
<NavigationMenuItem {...link} />
|
|
48
|
+
<NavigationMenuItem {...link} {textClass} {hoverClass} />
|
|
31
49
|
{/if}
|
|
32
50
|
{/each}
|
|
33
|
-
</ul>
|
|
51
|
+
</ul>
|
|
@@ -6,9 +6,14 @@
|
|
|
6
6
|
content,
|
|
7
7
|
href,
|
|
8
8
|
icon,
|
|
9
|
+
textClass,
|
|
10
|
+
subTextClass,
|
|
9
11
|
class: className,
|
|
10
12
|
...restProps
|
|
11
|
-
}: ListItemProps
|
|
13
|
+
}: ListItemProps & {
|
|
14
|
+
textClass?: string;
|
|
15
|
+
subTextClass?: string;
|
|
16
|
+
} = $props();
|
|
12
17
|
</script>
|
|
13
18
|
|
|
14
19
|
<li>
|
|
@@ -36,4 +41,4 @@
|
|
|
36
41
|
{content}
|
|
37
42
|
</p>
|
|
38
43
|
</a>
|
|
39
|
-
</li>
|
|
44
|
+
</li>
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { ListItemProps } from "../../data/types";
|
|
2
|
-
|
|
2
|
+
type $$ComponentProps = ListItemProps & {
|
|
3
|
+
textClass?: string;
|
|
4
|
+
subTextClass?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const MenuListItem: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
3
7
|
type MenuListItem = ReturnType<typeof MenuListItem>;
|
|
4
8
|
export default MenuListItem;
|
|
@@ -6,11 +6,15 @@
|
|
|
6
6
|
let {
|
|
7
7
|
label,
|
|
8
8
|
className = "",
|
|
9
|
+
hoverClass = "",
|
|
10
|
+
onClick,
|
|
9
11
|
children,
|
|
10
12
|
}: {
|
|
11
13
|
label: string;
|
|
12
14
|
className?: string;
|
|
13
|
-
|
|
15
|
+
hoverClass?: string;
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
onClick?: () => void;
|
|
14
18
|
} = $props();
|
|
15
19
|
|
|
16
20
|
let open = $state(false);
|
|
@@ -50,25 +54,30 @@
|
|
|
50
54
|
type="button"
|
|
51
55
|
aria-expanded={open}
|
|
52
56
|
onclick={() => {
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
if (children) {
|
|
58
|
+
clearTimeout(closeTimer);
|
|
59
|
+
open = !open;
|
|
60
|
+
}
|
|
61
|
+
if (onClick) onClick();
|
|
55
62
|
}}
|
|
56
|
-
class="inline-flex h-9 w-max items-center justify-center rounded-2xl px-4.5 py-2.5 text-sm font-medium transition-all outline-none select-none hover:
|
|
57
|
-
?
|
|
63
|
+
class="inline-flex h-9 w-max items-center justify-center rounded-2xl px-4.5 py-2.5 text-sm font-medium transition-all outline-none select-none hover:{hoverClass} focus:{hoverClass} focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 {open
|
|
64
|
+
? hoverClass
|
|
58
65
|
: ''}"
|
|
59
66
|
>
|
|
60
67
|
{label}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
{#if children}
|
|
69
|
+
<HugeiconsIcon
|
|
70
|
+
icon={ArrowDown01Icon}
|
|
71
|
+
strokeWidth={2}
|
|
72
|
+
class={`relative top-px ml-1 size-3 transition-transform duration-300 ${
|
|
73
|
+
open ? "rotate-180" : ""
|
|
74
|
+
}`}
|
|
75
|
+
aria-hidden="true"
|
|
76
|
+
/>
|
|
77
|
+
{/if}
|
|
69
78
|
</button>
|
|
70
79
|
|
|
71
|
-
{#if open}
|
|
80
|
+
{#if open && children}
|
|
72
81
|
<div
|
|
73
82
|
class="absolute left-0 top-full z-50 md:z-100 mt-1.5 w-max rounded-2xl bg-popover p-2.5 pr-3 overflow-hidden text-popover-foreground shadow-2xl ring-1 ring-foreground/5"
|
|
74
83
|
>
|
|
@@ -2,7 +2,9 @@ import type { Snippet } from "svelte";
|
|
|
2
2
|
type $$ComponentProps = {
|
|
3
3
|
label: string;
|
|
4
4
|
className?: string;
|
|
5
|
-
|
|
5
|
+
hoverClass?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
onClick?: () => void;
|
|
6
8
|
};
|
|
7
9
|
declare const NavDropdown: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
10
|
type NavDropdown = ReturnType<typeof NavDropdown>;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { goto } from "$app/navigation";
|
|
2
3
|
import type { NavigationMenuItemProps } from "../../../data/types";
|
|
4
|
+
import NavDropdown from "./NavDropdown.svelte";
|
|
3
5
|
|
|
4
|
-
let { label, href }: NavigationMenuItemProps =
|
|
6
|
+
let { label, href, textClass, hoverClass }: NavigationMenuItemProps =
|
|
7
|
+
$props();
|
|
5
8
|
</script>
|
|
6
9
|
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
<NavDropdown
|
|
11
|
+
{label}
|
|
12
|
+
className="hidden md:block"
|
|
13
|
+
{hoverClass}
|
|
14
|
+
onClick={() => {
|
|
15
|
+
if (href) goto(href);
|
|
16
|
+
}}
|
|
17
|
+
/>
|
|
@@ -3,11 +3,18 @@
|
|
|
3
3
|
import MenuListItem from "../MenuListItem.svelte";
|
|
4
4
|
import NavDropdown from "./NavDropdown.svelte";
|
|
5
5
|
|
|
6
|
-
let {
|
|
6
|
+
let {
|
|
7
|
+
label,
|
|
8
|
+
header,
|
|
9
|
+
cards: items,
|
|
10
|
+
hoverClass,
|
|
11
|
+
}: NavigationMenuItemCardProps = $props();
|
|
7
12
|
</script>
|
|
8
13
|
|
|
9
14
|
{#snippet headerSnippet(label: string, description: string)}
|
|
10
|
-
<div class="mt-4 mb-2 text-lg font-medium {header?.labelClass}">
|
|
15
|
+
<div class="mt-4 mb-2 text-lg font-medium {header?.labelClass}">
|
|
16
|
+
{label}
|
|
17
|
+
</div>
|
|
11
18
|
<p
|
|
12
19
|
class="text-sm leading-tight {header?.descriptionClass ||
|
|
13
20
|
'text-muted-foreground'}"
|
|
@@ -16,10 +23,8 @@
|
|
|
16
23
|
</p>
|
|
17
24
|
{/snippet}
|
|
18
25
|
|
|
19
|
-
<NavDropdown label={label ?? header?.label ?? ""}>
|
|
20
|
-
<ul
|
|
21
|
-
class="grid gap-2 p-2 w-100 lg:w-125 lg:grid-cols-[.75fr_1fr]"
|
|
22
|
-
>
|
|
26
|
+
<NavDropdown label={label ?? header?.label ?? ""} {hoverClass}>
|
|
27
|
+
<ul class="grid gap-2 p-2 w-100 lg:w-125 lg:grid-cols-[.75fr_1fr]">
|
|
23
28
|
{#if header}
|
|
24
29
|
<li
|
|
25
30
|
class="row-span-3 relative"
|
|
@@ -45,4 +50,4 @@
|
|
|
45
50
|
{/each}
|
|
46
51
|
{/if}
|
|
47
52
|
</ul>
|
|
48
|
-
</NavDropdown>
|
|
53
|
+
</NavDropdown>
|