fulldev-ui 0.9.2 → 0.9.3
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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/public/r/beta-repo-setup.json +1 -7
- package/public/r/components.json +1 -0
- package/public/r/gradient.json +17 -0
- package/public/r/icon.json +1 -1
- package/public/r/marquee.json +1 -1
- package/public/r/registry.json +15 -5
- package/registry.json +15 -5
- package/src/components/ui/gradient/gradient.astro +45 -0
- package/src/components/ui/gradient/index.ts +1 -0
- package/src/components/ui/icon/icon.astro +7 -1
- package/src/components/ui/marquee/marquee.astro +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Fulldev UI
|
|
2
2
|
|
|
3
|
+
## 0.9.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`e641911`](https://github.com/fulldotdev/ui/commit/e64191143efe448a46999d63ca7ed6d8bd320d1e) Thanks [@silveltman](https://github.com/silveltman)! - Add the gradient component to the registry, keep Lucide icons unfilled, and fix marquee spacing during looping animations.
|
|
8
|
+
|
|
3
9
|
## 0.9.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -12,12 +12,6 @@
|
|
|
12
12
|
"type": "registry:file",
|
|
13
13
|
"target": "src/content.config.ts"
|
|
14
14
|
},
|
|
15
|
-
{
|
|
16
|
-
"path": "src/components/layout-renderer.astro",
|
|
17
|
-
"content": "---\n// Keep this renderer generic and stable. New page types should be wired by\n// adding a matching schema and src/layouts/<type>.astro file, not by adding\n// layout-specific branches here.\nimport { getEntry, render, type CollectionEntry } from \"astro:content\"\n\ntype Props = CollectionEntry<\"pages\">\n\nconst page = Astro.props\nconst pageData = page.data\nconst { Content, headings } = await render(page)\nconst global = await getEntry(\"globals\", Astro.currentLocale || \"en\")\nif (!global) throw new Error(\"Add a global to content/globals\")\nconst globalData = global.data\n\nconst layoutImports = import.meta.glob(\"../layouts/*.astro\", { eager: true })\nconst layoutPath = `../layouts/${pageData.type}.astro`\nconst layoutImport = layoutImports[layoutPath] as { default?: any } | undefined\nconst Layout = layoutImport?.default\n\nif (!Layout) throw new Error(`Add a layout for page type \"${pageData.type}\"`)\n---\n\n<Layout global={globalData} page={pageData} headings={headings}>\n <Content />\n</Layout>\n",
|
|
18
|
-
"type": "registry:file",
|
|
19
|
-
"target": "src/components/layout-renderer.astro"
|
|
20
|
-
},
|
|
21
15
|
{
|
|
22
16
|
"path": "src/lib/pages.ts",
|
|
23
17
|
"content": "import { getCollection, type CollectionEntry } from \"astro:content\"\n\ntype Page = CollectionEntry<\"pages\">\n\nexport type PageSearchItem = {\n label: string\n href: string\n title: string\n path: string\n description: string\n group: string\n}\n\nexport type PageBreadcrumbItem = {\n label: string\n href: string\n}\n\nexport const normalizePath = (path: string) => {\n if (path === \"/\") return path\n\n return path.replace(/\\/$/, \"\")\n}\n\nexport const getPageHref = (page: Page) =>\n page.id === \"index\" ? \"/\" : `/${page.id}/`\n\nexport const formatSlug = (slug: string) =>\n slug\n .split(\"-\")\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \")\n\nconst getPageSearchGroup = (href: string) => {\n const [slug] = href.split(\"/\").filter(Boolean)\n\n return slug ? formatSlug(slug) : \"Overview\"\n}\n\nexport const getPageSearchItems = async (): Promise<PageSearchItem[]> => {\n const pages = await getCollection(\"pages\")\n\n return pages\n .map((page) => ({\n label: page.data.title,\n href: getPageHref(page),\n title: page.data.title,\n path: getPageHref(page),\n description: page.data.description,\n group: getPageSearchGroup(getPageHref(page)),\n }))\n .sort((a, b) => a.label.localeCompare(b.label))\n}\n\nexport const getPageBreadcrumbItems = async (\n pathname: string\n): Promise<PageBreadcrumbItem[]> => {\n const currentPath = normalizePath(pathname)\n const pages = await getCollection(\"pages\")\n const pageTitlesByHref = new Map(\n pages.map((page) => [getPageHref(page), page.data.title])\n )\n const homeLink = {\n label: pageTitlesByHref.get(\"/\") ?? \"Home\",\n href: \"/\",\n }\n\n if (currentPath === \"/\") return [homeLink]\n\n return [\n homeLink,\n ...currentPath\n .split(\"/\")\n .filter(Boolean)\n .map((slug, index, slugs) => {\n const href = `/${slugs.slice(0, index + 1).join(\"/\")}/`\n\n return {\n label: pageTitlesByHref.get(href) ?? formatSlug(slug),\n href,\n }\n }),\n ]\n}\n",
|
|
@@ -26,7 +20,7 @@
|
|
|
26
20
|
},
|
|
27
21
|
{
|
|
28
22
|
"path": "src/pages/[...page].astro",
|
|
29
|
-
"content": "---\nimport { getCollection } from \"astro:content\"\n\
|
|
23
|
+
"content": "---\nimport { getCollection, getEntry, render } from \"astro:content\"\n\nexport const prerender = true\n\nexport async function getStaticPaths() {\n const pages = await getCollection(\"pages\")\n return pages.map((page) => {\n return {\n params: {\n page: page.id === \"index\" ? undefined : page.id,\n },\n props: page,\n }\n })\n}\n\nconst page = Astro.props\nconst pageData = page.data\nconst { Content, headings } = await render(page)\nconst global = await getEntry(\"globals\", Astro.currentLocale || \"en\")\nif (!global) throw new Error(\"Add a global to content/globals\")\nconst globalData = global.data\n\nconst layoutImports = import.meta.glob(\"../layouts/*.astro\", { eager: true })\nconst layoutPath = `../layouts/${pageData.type}.astro`\nconst layoutImport = layoutImports[layoutPath] as { default?: any } | undefined\nconst Layout = layoutImport?.default\n\nif (!Layout) throw new Error(`Add a layout for page type \"${pageData.type}\"`)\n---\n\n<Layout global={globalData} page={pageData} headings={headings}>\n <Content />\n</Layout>\n",
|
|
30
24
|
"type": "registry:file",
|
|
31
25
|
"target": "src/pages/[...page].astro"
|
|
32
26
|
},
|
package/public/r/components.json
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "gradient",
|
|
4
|
+
"files": [
|
|
5
|
+
{
|
|
6
|
+
"path": "src/components/ui/gradient/gradient.astro",
|
|
7
|
+
"content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst gradientVariants = cva(\n \"bg-primary pointer-events-none absolute inset-0 opacity-50 [--gradient-stops:black,transparent]\",\n {\n variants: {\n variant: {\n radial:\n \"[mask-image:radial-gradient(ellipse_at_var(--gradient-position),var(--gradient-stops))] [-webkit-mask-image:radial-gradient(ellipse_at_var(--gradient-position),var(--gradient-stops))]\",\n linear:\n \"[mask-image:linear-gradient(var(--gradient-direction),var(--gradient-stops))] [-webkit-mask-image:linear-gradient(var(--gradient-direction),var(--gradient-stops))]\",\n },\n direction: {\n left: \"[--gradient-direction:to_left] [--gradient-position:0%_50%]\",\n right: \"[--gradient-direction:to_right] [--gradient-position:100%_50%]\",\n top: \"[--gradient-direction:to_top] [--gradient-position:50%_0%]\",\n bottom:\n \"[--gradient-direction:to_bottom] [--gradient-position:50%_100%]\",\n center:\n \"[--gradient-direction:to_bottom] [--gradient-position:50%_50%]\",\n },\n },\n defaultVariants: {\n variant: \"radial\",\n direction: \"bottom\",\n },\n }\n)\n\ntype Props = HTMLAttributes<\"div\"> & VariantProps<typeof gradientVariants>\n\nconst { class: className, variant, direction, ...props } = Astro.props\n---\n\n<div\n data-slot=\"gradient\"\n aria-hidden=\"true\"\n class={cn(gradientVariants({ variant, direction }), className)}\n {...props}\n>\n</div>\n",
|
|
8
|
+
"type": "registry:ui"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "src/components/ui/gradient/index.ts",
|
|
12
|
+
"content": "export { default as Gradient } from \"./gradient.astro\"\n",
|
|
13
|
+
"type": "registry:ui"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"type": "registry:ui"
|
|
17
|
+
}
|
package/public/r/icon.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "src/components/ui/icon/icon.astro",
|
|
11
|
-
"content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = Omit<HTMLAttributes<\"svg\">, \"name\" | \"href\"> & {\n href?: HTMLAttributes<\"a\">[\"href\"]\n name?: string | number | null\n}\n\nconst { name, href, ...props } = Astro.props\n\nconst hrefMap = {\n \"x.com\": \"x\",\n twitter: \"twitter\",\n facebook: \"facebook\",\n instagram: \"instagram\",\n pinterest: \"pinterest\",\n youtube: \"youtube\",\n tiktok: \"tiktok\",\n snapchat: \"snapchat\",\n reddit: \"reddit\",\n tumblr: \"tumblr\",\n \"wa.me\": \"whatsapp\",\n telegram: \"telegram\",\n discord: \"discord\",\n vimeo: \"vimeo\",\n flickr: \"flickr\",\n yelp: \"yelp\",\n spotify: \"spotify\",\n behance: \"behance\",\n dribbble: \"dribbble\",\n soundcloud: \"soundcloud\",\n github: \"github\",\n twitch: \"twitch\",\n \"tel:\": \"phone\",\n \"mailto:\": \"mail\",\n \"maps.app.goo.gl\": \"map-pin\",\n linkedin: \"linkedin\",\n} as const\n\nconst icons = import.meta.glob(\n [\n \"/node_modules/lucide-static/icons/*.svg\",\n \"/node_modules/simple-icons/icons/*.svg\",\n ],\n { eager: true }\n) as Record<string, { default: any }>\n\nconst foundPath = () => {\n let foundPath: string | undefined = undefined\n\n // For x.com, use the Simple Icons X instead of Lucide's X icon.\n if (name === \"x.com\") {\n foundPath = \"/node_modules/simple-icons/icons/x.svg\"\n } else if (name) {\n foundPath = Object.keys(icons).find((key) => key.includes(`/${name}.svg`))\n } else if (href) {\n const hrefKey = Object.keys(hrefMap).find((key) =>\n href.toString().includes(key)\n )\n const hrefValue = hrefMap[hrefKey as keyof typeof hrefMap]\n foundPath = Object.keys(icons)\n .reverse()\n .find((key) => key.includes(`/${hrefValue}.svg`))\n }\n\n return foundPath\n}\n\nconst iconPath = foundPath()\nconst module = iconPath ? icons[iconPath] : undefined\nconst Comp = module?.default\n---\n\n{\n Comp && foundPath()?.includes(\"simple-icons\") && (\n <Comp\n height={24}\n width={24}\n fill=\"currentColor\"\n class=\"size-[1em] text-base\"\n {...props}\n />\n )\n}\n\n{\n Comp && foundPath()?.includes(\"lucide-static\") && (\n <Comp
|
|
11
|
+
"content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = Omit<HTMLAttributes<\"svg\">, \"name\" | \"href\"> & {\n href?: HTMLAttributes<\"a\">[\"href\"]\n name?: string | number | null\n}\n\nconst { name, href, ...props } = Astro.props\n\nconst hrefMap = {\n \"x.com\": \"x\",\n twitter: \"twitter\",\n facebook: \"facebook\",\n instagram: \"instagram\",\n pinterest: \"pinterest\",\n youtube: \"youtube\",\n tiktok: \"tiktok\",\n snapchat: \"snapchat\",\n reddit: \"reddit\",\n tumblr: \"tumblr\",\n \"wa.me\": \"whatsapp\",\n telegram: \"telegram\",\n discord: \"discord\",\n vimeo: \"vimeo\",\n flickr: \"flickr\",\n yelp: \"yelp\",\n spotify: \"spotify\",\n behance: \"behance\",\n dribbble: \"dribbble\",\n soundcloud: \"soundcloud\",\n github: \"github\",\n twitch: \"twitch\",\n \"tel:\": \"phone\",\n \"mailto:\": \"mail\",\n \"maps.app.goo.gl\": \"map-pin\",\n linkedin: \"linkedin\",\n} as const\n\nconst icons = import.meta.glob(\n [\n \"/node_modules/lucide-static/icons/*.svg\",\n \"/node_modules/simple-icons/icons/*.svg\",\n ],\n { eager: true }\n) as Record<string, { default: any }>\n\nconst foundPath = () => {\n let foundPath: string | undefined = undefined\n\n // For x.com, use the Simple Icons X instead of Lucide's X icon.\n if (name === \"x.com\") {\n foundPath = \"/node_modules/simple-icons/icons/x.svg\"\n } else if (name) {\n foundPath = Object.keys(icons).find((key) => key.includes(`/${name}.svg`))\n } else if (href) {\n const hrefKey = Object.keys(hrefMap).find((key) =>\n href.toString().includes(key)\n )\n const hrefValue = hrefMap[hrefKey as keyof typeof hrefMap]\n foundPath = Object.keys(icons)\n .reverse()\n .find((key) => key.includes(`/${hrefValue}.svg`))\n }\n\n return foundPath\n}\n\nconst iconPath = foundPath()\nconst module = iconPath ? icons[iconPath] : undefined\nconst Comp = module?.default\n---\n\n{\n Comp && foundPath()?.includes(\"simple-icons\") && (\n <Comp\n height={24}\n width={24}\n fill=\"currentColor\"\n class=\"size-[1em] text-base\"\n {...props}\n />\n )\n}\n\n{\n Comp && foundPath()?.includes(\"lucide-static\") && (\n <Comp\n height={24}\n width={24}\n fill=\"none\"\n class=\"size-[1em] text-base\"\n {...props}\n />\n )\n}\n",
|
|
12
12
|
"type": "registry:ui"
|
|
13
13
|
},
|
|
14
14
|
{
|
package/public/r/marquee.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"files": [
|
|
5
5
|
{
|
|
6
6
|
"path": "src/components/ui/marquee/marquee.astro",
|
|
7
|
-
"content": "---\nimport { cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = {\n direction?: \"left\" | \"right\" | \"top\" | \"bottom\"\n duration?: number | string\n gap?: string\n infinite?: boolean\n pauseOnHover?: boolean\n time?: number | string\n variant?: \"gradient\" | \"solid\"\n class?: string\n style?: string\n}\n\nconst {\n class: className = \"\",\n direction = \"left\",\n duration,\n gap = \"1rem\",\n infinite = true,\n pauseOnHover = false,\n style,\n time = 30,\n variant = \"gradient\",\n ...props\n} = Astro.props\n\nconst resolvedDuration = duration ?? time\nconst styleValue = `--duration:${\n typeof resolvedDuration === \"number\"\n ? `${resolvedDuration}s`\n : resolvedDuration\n}; --gap:${gap}; ${style ?? \"\"}`\nconst contentClass = cn(\n \"marquee-content flex min-w-full shrink-0 justify-around gap-[var(--gap)] will-change-transform group-data-[direction=bottom]:[animation-direction:reverse] group-data-[direction=right]:[animation-direction:reverse] data-[direction=bottom]:min-h-full data-[direction=bottom]:flex-col data-[direction=top]:min-h-full data-[direction=top]:flex-col motion-reduce:[animation-play-state:paused]\",\n infinite &&\n \"animate-[marquee-x_var(--duration,20s)_linear_infinite] group-data-[direction=bottom]:animate-[marquee-y_var(--duration,20s)_linear_infinite] group-data-[direction=top]:animate-[marquee-y_var(--duration,20s)_linear_infinite]\",\n direction === \"top\" && \"flex-col\",\n direction === \"bottom\" && \"flex-col\"\n)\n\nconst marqueeVariants = cva(\"relative w-full\", {\n variants: {\n variant: {\n gradient:\n \"[mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)] [-webkit-mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)] [&[data-direction=bottom]]:[mask-image:linear-gradient(to_top,transparent,black_10%,black_90%,transparent)] [&[data-direction=bottom]]:[-webkit-mask-image:linear-gradient(to_top,transparent,black_10%,black_90%,transparent)] [&[data-direction=top]]:[mask-image:linear-gradient(to_bottom,transparent,black_10%,black_90%,transparent)] [&[data-direction=top]]:[-webkit-mask-image:linear-gradient(to_bottom,transparent,black_10%,black_90%,transparent)]\",\n solid: \"\",\n },\n },\n defaultVariants: {\n variant: \"gradient\",\n },\n})\n---\n\n<div\n data-marquee\n data-direction={direction}\n data-pause-on-hover={pauseOnHover ? \"true\" : undefined}\n class={cn(\n \"\",\n // container utilities\n \"group flex w-full overflow-hidden data-[direction=bottom]:flex-col data-[direction=top]:flex-col\",\n marqueeVariants({ variant }),\n className\n )}\n style={styleValue}\n {...props}\n>\n <div class={contentClass}>\n <slot />\n </div>\n {\n infinite && (\n <div class={contentClass} aria-hidden=\"true\">\n <slot />\n </div>\n )\n }\n</div>\n\n<style>\n @keyframes marquee-x {\n from {\n transform: translateX(0);\n }\n to {\n transform: translateX(-100%);\n }\n }\n @keyframes marquee-y {\n from {\n transform: translateY(0);\n }\n to {\n transform: translateY(-100%);\n }\n }\n\n [data-marquee][data-pause-on-hover=\"true\"]:hover .marquee-content {\n animation-play-state: paused;\n }\n</style>\n",
|
|
7
|
+
"content": "---\nimport { cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = {\n direction?: \"left\" | \"right\" | \"top\" | \"bottom\"\n duration?: number | string\n gap?: string\n infinite?: boolean\n pauseOnHover?: boolean\n time?: number | string\n variant?: \"gradient\" | \"solid\"\n class?: string\n style?: string\n}\n\nconst {\n class: className = \"\",\n direction = \"left\",\n duration,\n gap = \"1rem\",\n infinite = true,\n pauseOnHover = false,\n style,\n time = 30,\n variant = \"gradient\",\n ...props\n} = Astro.props\n\nconst resolvedDuration = duration ?? time\nconst styleValue = `--duration:${\n typeof resolvedDuration === \"number\"\n ? `${resolvedDuration}s`\n : resolvedDuration\n}; --gap:${gap}; ${style ?? \"\"}`\nconst contentClass = cn(\n \"marquee-content flex min-w-full shrink-0 justify-around gap-[var(--gap)] will-change-transform group-data-[direction=bottom]:[animation-direction:reverse] group-data-[direction=right]:[animation-direction:reverse] data-[direction=bottom]:min-h-full data-[direction=bottom]:flex-col data-[direction=top]:min-h-full data-[direction=top]:flex-col motion-reduce:[animation-play-state:paused]\",\n infinite &&\n \"animate-[marquee-x_var(--duration,20s)_linear_infinite] group-data-[direction=bottom]:animate-[marquee-y_var(--duration,20s)_linear_infinite] group-data-[direction=top]:animate-[marquee-y_var(--duration,20s)_linear_infinite]\",\n direction === \"top\" && \"flex-col\",\n direction === \"bottom\" && \"flex-col\"\n)\n\nconst marqueeVariants = cva(\"relative w-full\", {\n variants: {\n variant: {\n gradient:\n \"[mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)] [-webkit-mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)] [&[data-direction=bottom]]:[mask-image:linear-gradient(to_top,transparent,black_10%,black_90%,transparent)] [&[data-direction=bottom]]:[-webkit-mask-image:linear-gradient(to_top,transparent,black_10%,black_90%,transparent)] [&[data-direction=top]]:[mask-image:linear-gradient(to_bottom,transparent,black_10%,black_90%,transparent)] [&[data-direction=top]]:[-webkit-mask-image:linear-gradient(to_bottom,transparent,black_10%,black_90%,transparent)]\",\n solid: \"\",\n },\n },\n defaultVariants: {\n variant: \"gradient\",\n },\n})\n---\n\n<div\n data-marquee\n data-direction={direction}\n data-pause-on-hover={pauseOnHover ? \"true\" : undefined}\n class={cn(\n \"\",\n // container utilities\n \"group flex w-full gap-[var(--gap)] overflow-hidden data-[direction=bottom]:flex-col data-[direction=top]:flex-col\",\n marqueeVariants({ variant }),\n className\n )}\n style={styleValue}\n {...props}\n>\n <div class={contentClass}>\n <slot />\n </div>\n {\n infinite && (\n <div class={contentClass} aria-hidden=\"true\">\n <slot />\n </div>\n )\n }\n</div>\n\n<style>\n @keyframes marquee-x {\n from {\n transform: translateX(0);\n }\n to {\n transform: translateX(calc(-100% - var(--gap)));\n }\n }\n @keyframes marquee-y {\n from {\n transform: translateY(0);\n }\n to {\n transform: translateY(calc(-100% - var(--gap)));\n }\n }\n\n [data-marquee][data-pause-on-hover=\"true\"]:hover .marquee-content {\n animation-play-state: paused;\n }\n</style>\n",
|
|
8
8
|
"type": "registry:ui"
|
|
9
9
|
},
|
|
10
10
|
{
|
package/public/r/registry.json
CHANGED
|
@@ -651,6 +651,20 @@
|
|
|
651
651
|
}
|
|
652
652
|
]
|
|
653
653
|
},
|
|
654
|
+
{
|
|
655
|
+
"name": "gradient",
|
|
656
|
+
"type": "registry:ui",
|
|
657
|
+
"files": [
|
|
658
|
+
{
|
|
659
|
+
"path": "src/components/ui/gradient/gradient.astro",
|
|
660
|
+
"type": "registry:ui"
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
"path": "src/components/ui/gradient/index.ts",
|
|
664
|
+
"type": "registry:ui"
|
|
665
|
+
}
|
|
666
|
+
]
|
|
667
|
+
},
|
|
654
668
|
{
|
|
655
669
|
"name": "header",
|
|
656
670
|
"type": "registry:ui",
|
|
@@ -1686,6 +1700,7 @@
|
|
|
1686
1700
|
"@fulldev/dropdown-menu",
|
|
1687
1701
|
"@fulldev/empty",
|
|
1688
1702
|
"@fulldev/field",
|
|
1703
|
+
"@fulldev/gradient",
|
|
1689
1704
|
"@fulldev/header",
|
|
1690
1705
|
"@fulldev/hover-card",
|
|
1691
1706
|
"@fulldev/input",
|
|
@@ -1848,11 +1863,6 @@
|
|
|
1848
1863
|
"type": "registry:file",
|
|
1849
1864
|
"target": "src/content.config.ts"
|
|
1850
1865
|
},
|
|
1851
|
-
{
|
|
1852
|
-
"path": "src/components/layout-renderer.astro",
|
|
1853
|
-
"type": "registry:file",
|
|
1854
|
-
"target": "src/components/layout-renderer.astro"
|
|
1855
|
-
},
|
|
1856
1866
|
{
|
|
1857
1867
|
"path": "src/lib/pages.ts",
|
|
1858
1868
|
"type": "registry:file",
|
package/registry.json
CHANGED
|
@@ -651,6 +651,20 @@
|
|
|
651
651
|
}
|
|
652
652
|
]
|
|
653
653
|
},
|
|
654
|
+
{
|
|
655
|
+
"name": "gradient",
|
|
656
|
+
"type": "registry:ui",
|
|
657
|
+
"files": [
|
|
658
|
+
{
|
|
659
|
+
"path": "src/components/ui/gradient/gradient.astro",
|
|
660
|
+
"type": "registry:ui"
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
"path": "src/components/ui/gradient/index.ts",
|
|
664
|
+
"type": "registry:ui"
|
|
665
|
+
}
|
|
666
|
+
]
|
|
667
|
+
},
|
|
654
668
|
{
|
|
655
669
|
"name": "header",
|
|
656
670
|
"type": "registry:ui",
|
|
@@ -1686,6 +1700,7 @@
|
|
|
1686
1700
|
"@fulldev/dropdown-menu",
|
|
1687
1701
|
"@fulldev/empty",
|
|
1688
1702
|
"@fulldev/field",
|
|
1703
|
+
"@fulldev/gradient",
|
|
1689
1704
|
"@fulldev/header",
|
|
1690
1705
|
"@fulldev/hover-card",
|
|
1691
1706
|
"@fulldev/input",
|
|
@@ -1848,11 +1863,6 @@
|
|
|
1848
1863
|
"type": "registry:file",
|
|
1849
1864
|
"target": "src/content.config.ts"
|
|
1850
1865
|
},
|
|
1851
|
-
{
|
|
1852
|
-
"path": "src/components/layout-renderer.astro",
|
|
1853
|
-
"type": "registry:file",
|
|
1854
|
-
"target": "src/components/layout-renderer.astro"
|
|
1855
|
-
},
|
|
1856
1866
|
{
|
|
1857
1867
|
"path": "src/lib/pages.ts",
|
|
1858
1868
|
"type": "registry:file",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types"
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const gradientVariants = cva(
|
|
8
|
+
"bg-primary pointer-events-none absolute inset-0 opacity-50 [--gradient-stops:black,transparent]",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
radial:
|
|
13
|
+
"[mask-image:radial-gradient(ellipse_at_var(--gradient-position),var(--gradient-stops))] [-webkit-mask-image:radial-gradient(ellipse_at_var(--gradient-position),var(--gradient-stops))]",
|
|
14
|
+
linear:
|
|
15
|
+
"[mask-image:linear-gradient(var(--gradient-direction),var(--gradient-stops))] [-webkit-mask-image:linear-gradient(var(--gradient-direction),var(--gradient-stops))]",
|
|
16
|
+
},
|
|
17
|
+
direction: {
|
|
18
|
+
left: "[--gradient-direction:to_left] [--gradient-position:0%_50%]",
|
|
19
|
+
right: "[--gradient-direction:to_right] [--gradient-position:100%_50%]",
|
|
20
|
+
top: "[--gradient-direction:to_top] [--gradient-position:50%_0%]",
|
|
21
|
+
bottom:
|
|
22
|
+
"[--gradient-direction:to_bottom] [--gradient-position:50%_100%]",
|
|
23
|
+
center:
|
|
24
|
+
"[--gradient-direction:to_bottom] [--gradient-position:50%_50%]",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: {
|
|
28
|
+
variant: "radial",
|
|
29
|
+
direction: "bottom",
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
type Props = HTMLAttributes<"div"> & VariantProps<typeof gradientVariants>
|
|
35
|
+
|
|
36
|
+
const { class: className, variant, direction, ...props } = Astro.props
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
<div
|
|
40
|
+
data-slot="gradient"
|
|
41
|
+
aria-hidden="true"
|
|
42
|
+
class={cn(gradientVariants({ variant, direction }), className)}
|
|
43
|
+
{...props}
|
|
44
|
+
>
|
|
45
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Gradient } from "./gradient.astro"
|
|
@@ -85,6 +85,12 @@ const Comp = module?.default
|
|
|
85
85
|
|
|
86
86
|
{
|
|
87
87
|
Comp && foundPath()?.includes("lucide-static") && (
|
|
88
|
-
<Comp
|
|
88
|
+
<Comp
|
|
89
|
+
height={24}
|
|
90
|
+
width={24}
|
|
91
|
+
fill="none"
|
|
92
|
+
class="size-[1em] text-base"
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
89
95
|
)
|
|
90
96
|
}
|
|
@@ -63,7 +63,7 @@ const marqueeVariants = cva("relative w-full", {
|
|
|
63
63
|
class={cn(
|
|
64
64
|
"",
|
|
65
65
|
// container utilities
|
|
66
|
-
"group flex w-full overflow-hidden data-[direction=bottom]:flex-col data-[direction=top]:flex-col",
|
|
66
|
+
"group flex w-full gap-[var(--gap)] overflow-hidden data-[direction=bottom]:flex-col data-[direction=top]:flex-col",
|
|
67
67
|
marqueeVariants({ variant }),
|
|
68
68
|
className
|
|
69
69
|
)}
|
|
@@ -88,7 +88,7 @@ const marqueeVariants = cva("relative w-full", {
|
|
|
88
88
|
transform: translateX(0);
|
|
89
89
|
}
|
|
90
90
|
to {
|
|
91
|
-
transform: translateX(-100%);
|
|
91
|
+
transform: translateX(calc(-100% - var(--gap)));
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
@keyframes marquee-y {
|
|
@@ -96,7 +96,7 @@ const marqueeVariants = cva("relative w-full", {
|
|
|
96
96
|
transform: translateY(0);
|
|
97
97
|
}
|
|
98
98
|
to {
|
|
99
|
-
transform: translateY(-100%);
|
|
99
|
+
transform: translateY(calc(-100% - var(--gap)));
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|