@foxui/visual 0.4.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.
Files changed (34) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +20 -0
  3. package/dist/components/confetti/index.d.ts +1 -0
  4. package/dist/components/confetti/index.js +50 -0
  5. package/dist/components/excalidraw/Excalidraw.svelte +70 -0
  6. package/dist/components/excalidraw/Excalidraw.svelte.d.ts +11 -0
  7. package/dist/components/excalidraw/index.d.ts +1 -0
  8. package/dist/components/excalidraw/index.js +1 -0
  9. package/dist/components/gradient/Gradient.svelte +8 -0
  10. package/dist/components/gradient/Gradient.svelte.d.ts +26 -0
  11. package/dist/components/gradient/index.d.ts +1 -0
  12. package/dist/components/gradient/index.js +1 -0
  13. package/dist/components/image-masonry/ImageMasonry.svelte +94 -0
  14. package/dist/components/image-masonry/ImageMasonry.svelte.d.ts +18 -0
  15. package/dist/components/image-masonry/index.d.ts +1 -0
  16. package/dist/components/image-masonry/index.js +1 -0
  17. package/dist/components/index.d.ts +7 -0
  18. package/dist/components/index.js +7 -0
  19. package/dist/components/phone/Phone.svelte +30 -0
  20. package/dist/components/phone/Phone.svelte.d.ts +8 -0
  21. package/dist/components/phone/index.d.ts +1 -0
  22. package/dist/components/phone/index.js +1 -0
  23. package/dist/components/quote/Quote.svelte +69 -0
  24. package/dist/components/quote/Quote.svelte.d.ts +19 -0
  25. package/dist/components/quote/index.d.ts +1 -0
  26. package/dist/components/quote/index.js +1 -0
  27. package/dist/components/undraw/Undraw.svelte +92 -0
  28. package/dist/components/undraw/Undraw.svelte.d.ts +13 -0
  29. package/dist/components/undraw/index.d.ts +1 -0
  30. package/dist/components/undraw/index.js +1 -0
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.js +1 -0
  33. package/dist/types.d.ts +1 -0
  34. package/package.json +76 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License Copyright (c) 2025 flo-bit
2
+
3
+ Permission is hereby granted, free of
4
+ charge, to any person obtaining a copy of this software and associated
5
+ documentation files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use, copy, modify, merge,
7
+ publish, distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice
12
+ (including the next paragraph) shall be included in all copies or substantial
13
+ portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
18
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # 🦊 fox ui
2
+
3
+ svelte 5 + tailwind 4 ui kit, visual components
4
+
5
+ - [Confetti](https://flo-bit.dev/ui-kit/components/visual/confetti)
6
+ - [Excalidraw](https://flo-bit.dev/ui-kit/components/visual/excalidraw)
7
+ - [Image Masonry](https://flo-bit.dev/ui-kit/components/visual/image-masonry)
8
+ - [Phone](https://flo-bit.dev/ui-kit/components/visual/phone)
9
+ - [Quote](https://flo-bit.dev/ui-kit/components/visual/quote)
10
+ - [Undraw](https://flo-bit.dev/ui-kit/components/visual/undraw)
11
+
12
+ > **This is a public alpha release. Expect bugs and breaking changes.**
13
+
14
+ [See all components here](https://flo-bit.dev/ui-kit)
15
+
16
+ For a guide on how to use this ui kit, see the [Quickstart Guide](https://flo-bit.dev/ui-kit/docs/quick-start).
17
+
18
+ Read more about [the philosophy/aim of this project here](https://flo-bit.dev/ui-kit/docs/philosophy).
19
+
20
+ For more information about development, contributing and the like, see the main [README](https://github.com/flo-bit/ui-kit/blob/main/README.md).
@@ -0,0 +1 @@
1
+ export declare const launchConfetti: (color?: string, brightnesses?: (50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950)[]) => void;
@@ -0,0 +1,50 @@
1
+ import confetti from 'canvas-confetti';
2
+ import { convertCSSToHex } from '@foxui/colors';
3
+ function getCSSVar(variable) {
4
+ return getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
5
+ }
6
+ export const launchConfetti = (color = 'accent', brightnesses = [
7
+ 300, 400, 500, 800
8
+ ]) => {
9
+ const count = 200;
10
+ const defaults = {
11
+ origin: { y: 0.7 }
12
+ };
13
+ const colors = [];
14
+ for (const b of brightnesses) {
15
+ const c = getCSSVar(`--color-${color}-${b}`);
16
+ if (c) {
17
+ colors.push(convertCSSToHex(c));
18
+ }
19
+ }
20
+ function fire(particleRatio, opts) {
21
+ confetti({
22
+ ...defaults,
23
+ ...opts,
24
+ particleCount: Math.floor(count * particleRatio),
25
+ colors
26
+ });
27
+ }
28
+ fire(0.25, {
29
+ spread: 26,
30
+ startVelocity: 55
31
+ });
32
+ fire(0.2, {
33
+ spread: 60
34
+ });
35
+ fire(0.35, {
36
+ spread: 100,
37
+ decay: 0.91,
38
+ scalar: 0.8
39
+ });
40
+ fire(0.1, {
41
+ spread: 120,
42
+ startVelocity: 25,
43
+ decay: 0.92,
44
+ scalar: 1.2
45
+ });
46
+ fire(0.1, {
47
+ spread: 120,
48
+ startVelocity: 45
49
+ });
50
+ };
@@ -0,0 +1,70 @@
1
+ <script lang="ts">
2
+ import type { WithElementRef, WithoutChildrenOrChild } from 'bits-ui';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '@foxui/core';
5
+
6
+ import { load } from 'cheerio';
7
+
8
+ let {
9
+ ref = $bindable(null),
10
+ svg,
11
+ alt,
12
+ caption,
13
+ class: className,
14
+ captionClass,
15
+ ...restProps
16
+ }: WithElementRef<WithoutChildrenOrChild<HTMLAttributes<HTMLElement>>> & {
17
+ svg: string;
18
+ alt: string;
19
+ caption?: string;
20
+ captionClass?: string;
21
+ } = $props();
22
+
23
+ function modifySvg(svgString: string): string {
24
+ const loadedSvg = load(svgString, { xmlMode: true });
25
+
26
+ const svg = loadedSvg('svg');
27
+ svg.attr('width', '100%');
28
+ svg.attr('height', '100%');
29
+ svg.addClass('w-full h-auto');
30
+ svg.removeAttr('filter');
31
+
32
+ loadedSvg('text').each((_, el) => {
33
+ loadedSvg(el).removeAttr('fill');
34
+ loadedSvg(el).addClass('fill-base-800 dark:fill-base-100');
35
+ });
36
+
37
+ loadedSvg('rect').each((_, el) => {
38
+ loadedSvg(el).removeAttr('fill');
39
+ loadedSvg(el).addClass('fill-accent-600 dark:fill-accent-500');
40
+ });
41
+
42
+ loadedSvg('path').each((_, el) => {
43
+ loadedSvg(el).removeAttr('stroke');
44
+ loadedSvg(el).addClass('stroke-accent-600 dark:stroke-accent-500');
45
+ if (loadedSvg(el).attr('fill') !== 'none') {
46
+ loadedSvg(el).addClass('fill-accent-600 dark:fill-accent-500');
47
+ loadedSvg(el).removeAttr('fill');
48
+ }
49
+ });
50
+
51
+ return loadedSvg.html();
52
+ }
53
+ </script>
54
+
55
+ <figure
56
+ bind:this={ref}
57
+ class={cn('excalidraw-container mx-auto w-full max-w-full overflow-hidden', className)}
58
+ {...restProps}
59
+ >
60
+ <div class="excalidraw-svg w-full" aria-label={alt}>
61
+ {@html modifySvg(svg)}
62
+ </div>
63
+ {#if caption}
64
+ <figcaption
65
+ class={cn('text-base-700 dark:text-base-300 mt-4 text-center text-xs', captionClass)}
66
+ >
67
+ {caption}
68
+ </figcaption>
69
+ {/if}
70
+ </figure>
@@ -0,0 +1,11 @@
1
+ import type { WithElementRef, WithoutChildrenOrChild } from 'bits-ui';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = WithElementRef<WithoutChildrenOrChild<HTMLAttributes<HTMLElement>>> & {
4
+ svg: string;
5
+ alt: string;
6
+ caption?: string;
7
+ captionClass?: string;
8
+ };
9
+ declare const Excalidraw: import("svelte").Component<$$ComponentProps, {}, "ref">;
10
+ type Excalidraw = ReturnType<typeof Excalidraw>;
11
+ export default Excalidraw;
@@ -0,0 +1 @@
1
+ export { default as Excalidraw } from './Excalidraw.svelte';
@@ -0,0 +1 @@
1
+ export { default as Excalidraw } from './Excalidraw.svelte';
@@ -0,0 +1,8 @@
1
+ <div
2
+ class="absolute right-0 bottom-0 left-0 flex translate-y-100 items-center justify-center"
3
+ aria-hidden="true"
4
+ >
5
+ <div
6
+ class="from-accent-500/50 via-accent-300/0 dark:via-accent-800/0 size-[75rem] shrink-0 translate-y-100 bg-radial"
7
+ ></div>
8
+ </div>
@@ -0,0 +1,26 @@
1
+ export default Gradient;
2
+ type Gradient = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const Gradient: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -0,0 +1 @@
1
+ export { default as Gradient } from './Gradient.svelte';
@@ -0,0 +1 @@
1
+ export { default as Gradient } from './Gradient.svelte';
@@ -0,0 +1,94 @@
1
+ <script lang="ts">
2
+ import { Badge, cn } from '@foxui/core';
3
+
4
+ type Props = {
5
+ images: {
6
+ src: string;
7
+
8
+ name: string;
9
+ href?: string;
10
+ width?: number;
11
+ height?: number;
12
+ onclick?: () => void;
13
+ alt?: string;
14
+ }[];
15
+ interactive?: boolean;
16
+ maxColumns?: number;
17
+ showNames?: boolean;
18
+ class?: string;
19
+ };
20
+
21
+ const { images, interactive = true, maxColumns = 4, showNames = true, class: className }: Props = $props();
22
+ </script>
23
+
24
+ {#snippet backgroundTitle(name?: string)}
25
+ {#if showNames}
26
+ <div
27
+ class={cn(
28
+ 'from-base-950/80 absolute inset-0 z-10 h-full w-full bg-gradient-to-t via-transparent opacity-80',
29
+ interactive
30
+ ? 'transition-opacity duration-200 group-hover:opacity-90 group-focus:opacity-100 [@media(pointer:fine)]:opacity-0'
31
+ : ''
32
+ )}
33
+ ></div>
34
+
35
+ <div
36
+ class={cn(
37
+ 'pointer-events-none absolute inset-0 z-20 flex h-full w-full items-end overflow-hidden px-3 py-2 text-xl font-semibold leading-6 tracking-tight text-white md:px-4 md:py-3',
38
+ interactive
39
+ ? 'transition-translation duration-200 group-hover:translate-y-0 [@media(pointer:fine)]:translate-y-20'
40
+ : ''
41
+ )}
42
+ >
43
+ <div class="mt-1 text-sm sm:text-lg">{name}</div>
44
+ </div>
45
+ {:else}
46
+ <div class="absolute inset-0 z-10 h-full w-full"></div>
47
+ <span class="sr-only">{name}</span>
48
+ {/if}
49
+ {/snippet}
50
+
51
+ <div
52
+ class={cn(
53
+ 'not-prose gap-x-4',
54
+ maxColumns === 2 ? 'columns-2' : '',
55
+ maxColumns === 3 ? 'columns-2 sm:columns-3' : '',
56
+ maxColumns === 4 ? 'columns-2 sm:columns-3 md:columns-4' : '',
57
+ className
58
+ )}
59
+ >
60
+ {#each images as image}
61
+ <div
62
+ class="group relative mb-4 w-full break-inside-avoid-column overflow-hidden rounded-2xl border border-white/15"
63
+ style={`aspect-ratio: ${image.width ?? 1} / ${image.height ?? 1}`}
64
+ >
65
+ <img
66
+ src={image.src}
67
+ alt={image.alt}
68
+ class={cn(
69
+ 'absolute inset-0 h-full w-full rounded-2xl object-cover',
70
+ image.onclick || image.href ? 'transition-all duration-300 group-hover:scale-105' : ''
71
+ )}
72
+ loading="lazy"
73
+ width="270"
74
+ />
75
+
76
+ {#if image.href}
77
+ <a href={image.href} class="z-20">
78
+ {@render backgroundTitle(image.name)}
79
+ </a>
80
+ {:else if image.onclick}
81
+ <button
82
+ class="z-20 cursor-pointer"
83
+ onclick={() => {
84
+ image.onclick?.();
85
+ }}
86
+ >
87
+ {@render backgroundTitle(image.name)}
88
+ </button>
89
+ {:else}
90
+ {@render backgroundTitle(image.name)}
91
+ {/if}
92
+ </div>
93
+ {/each}
94
+ </div>
@@ -0,0 +1,18 @@
1
+ type Props = {
2
+ images: {
3
+ src: string;
4
+ name: string;
5
+ href?: string;
6
+ width?: number;
7
+ height?: number;
8
+ onclick?: () => void;
9
+ alt?: string;
10
+ }[];
11
+ interactive?: boolean;
12
+ maxColumns?: number;
13
+ showNames?: boolean;
14
+ class?: string;
15
+ };
16
+ declare const ImageMasonry: import("svelte").Component<Props, {}, "">;
17
+ type ImageMasonry = ReturnType<typeof ImageMasonry>;
18
+ export default ImageMasonry;
@@ -0,0 +1 @@
1
+ export { default as ImageMasonry } from './ImageMasonry.svelte';
@@ -0,0 +1 @@
1
+ export { default as ImageMasonry } from './ImageMasonry.svelte';
@@ -0,0 +1,7 @@
1
+ export * from './excalidraw';
2
+ export * from './gradient';
3
+ export * from './phone';
4
+ export * from './quote';
5
+ export * from './undraw';
6
+ export * from './image-masonry';
7
+ export * from './confetti';
@@ -0,0 +1,7 @@
1
+ export * from './excalidraw';
2
+ export * from './gradient';
3
+ export * from './phone';
4
+ export * from './quote';
5
+ export * from './undraw';
6
+ export * from './image-masonry';
7
+ export * from './confetti';
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ import { cn } from '@foxui/core';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ const { children, class: className }: { children: Snippet; class?: string } = $props();
6
+ </script>
7
+
8
+ <div
9
+ class={cn(
10
+ 'bg-accent-500 relative isolate aspect-[350/712] h-[712px] w-[350px] max-w-full rounded-[60px]',
11
+ className
12
+ )}
13
+ >
14
+ <div class="bg-accent-500 absolute top-20 -left-0.5 h-8 w-3 rounded-xs"></div>
15
+ <div class="bg-accent-500 absolute top-[140px] -left-[3px] h-14 w-3 rounded-xs"></div>
16
+ <div class="bg-accent-500 absolute top-[210px] -left-[3px] h-14 w-3 rounded-xs"></div>
17
+ <div class="bg-accent-500 absolute top-[180px] -right-[3px] h-20 w-3 rounded-xs"></div>
18
+
19
+ <div class="absolute top-[18px] z-10 flex w-full justify-center">
20
+ <div class="h-7 w-24 rounded-full bg-black"></div>
21
+ </div>
22
+
23
+ <div class="bg-accent-500 absolute top-[180px] -right-[3px] h-20 w-3 rounded-xs"></div>
24
+
25
+ <div class="absolute inset-0 h-full w-full p-3">
26
+ <div class="bg-accent-200 relative h-full w-full overflow-hidden rounded-[50px]">
27
+ {@render children?.()}
28
+ </div>
29
+ </div>
30
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ children: Snippet;
4
+ class?: string;
5
+ };
6
+ declare const Phone: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Phone = ReturnType<typeof Phone>;
8
+ export default Phone;
@@ -0,0 +1 @@
1
+ export { default as Phone } from './Phone.svelte';
@@ -0,0 +1 @@
1
+ export { default as Phone } from './Phone.svelte';
@@ -0,0 +1,69 @@
1
+ <script lang="ts">
2
+ import {
3
+ type WithElementRef,
4
+ type WithoutChildrenOrChild
5
+ } from 'bits-ui';
6
+ import type { HTMLAttributes } from 'svelte/elements';
7
+ import { cn, Avatar } from '@foxui/core';
8
+
9
+ let {
10
+ quote,
11
+ author,
12
+ role,
13
+
14
+ ref = $bindable(null),
15
+
16
+ useThemeColor = false,
17
+
18
+ class: className,
19
+ ...restProps
20
+ }: WithoutChildrenOrChild<WithElementRef<HTMLAttributes<HTMLDivElement>>> & {
21
+ quote?: string;
22
+ author?: {
23
+ src?: string;
24
+ alt?: string;
25
+ fallback?: string;
26
+
27
+ role?: string;
28
+ name?: string;
29
+
30
+ avatarClass?: string;
31
+ fallbackClass?: string;
32
+ imageClass?: string;
33
+ };
34
+
35
+ useThemeColor?: boolean;
36
+ } = $props();
37
+ </script>
38
+
39
+ <div
40
+ class={cn(
41
+ 'flex flex-col items-start justify-between gap-4 md:flex-row md:items-center md:gap-6',
42
+ className
43
+ )}
44
+ bind:this={ref}
45
+ {...restProps}
46
+ >
47
+ <div class="h-24 w-24 shrink-0 md:h-32 md:w-32">
48
+ <Avatar
49
+ {useThemeColor}
50
+ fallback={author?.fallback}
51
+ src={author?.src}
52
+ alt={author?.alt}
53
+ class="size-24 rounded-2xl object-cover text-3xl md:size-32"
54
+ />
55
+ </div>
56
+ <div class="flex flex-col gap-2">
57
+ <blockquote class="text-base-900 dark:text-base-50 text-lg font-medium">
58
+ <p>
59
+ "{quote}"
60
+ </p>
61
+ </blockquote>
62
+
63
+ <div class="flex items-center gap-2 text-sm">
64
+ <div class="text-accent-600 dark:text-accent-500 font-medium">{author?.name}</div>
65
+
66
+ <div class="text-base-600 dark:text-base-400">{author?.role}</div>
67
+ </div>
68
+ </div>
69
+ </div>
@@ -0,0 +1,19 @@
1
+ import { type WithElementRef, type WithoutChildrenOrChild } from 'bits-ui';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = WithoutChildrenOrChild<WithElementRef<HTMLAttributes<HTMLDivElement>>> & {
4
+ quote?: string;
5
+ author?: {
6
+ src?: string;
7
+ alt?: string;
8
+ fallback?: string;
9
+ role?: string;
10
+ name?: string;
11
+ avatarClass?: string;
12
+ fallbackClass?: string;
13
+ imageClass?: string;
14
+ };
15
+ useThemeColor?: boolean;
16
+ };
17
+ declare const Quote: import("svelte").Component<$$ComponentProps, {}, "ref">;
18
+ type Quote = ReturnType<typeof Quote>;
19
+ export default Quote;
@@ -0,0 +1 @@
1
+ export { default as Quote } from './Quote.svelte';
@@ -0,0 +1 @@
1
+ export { default as Quote } from './Quote.svelte';
@@ -0,0 +1,92 @@
1
+ <script lang="ts">
2
+ import type { WithElementRef, WithoutChildrenOrChild } from 'bits-ui';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '@foxui/core';
5
+
6
+ import { load, type CheerioAPI } from 'cheerio';
7
+
8
+ let {
9
+ ref = $bindable(null),
10
+ svg,
11
+ alt,
12
+ caption,
13
+ class: className,
14
+ captionClass,
15
+ autoInvert = false,
16
+ colorMap = {},
17
+ ...restProps
18
+ }: WithElementRef<WithoutChildrenOrChild<HTMLAttributes<HTMLElement>>> & {
19
+ svg: string;
20
+ alt: string;
21
+ caption?: string;
22
+ captionClass?: string;
23
+ autoInvert?: boolean;
24
+ colorMap?: Record<string, string>;
25
+ } = $props();
26
+
27
+ function applyClasses(loadedSvg: CheerioAPI, el: any) {
28
+ let fill = loadedSvg(el).attr('fill');
29
+ if (!fill) return;
30
+
31
+ if (fill === '#6c63ff') {
32
+ loadedSvg(el).removeAttr('fill');
33
+ loadedSvg(el).addClass('fill-accent-600 dark:fill-accent-500');
34
+ } else if (fill.startsWith('#') && !fill.includes('url') && autoInvert) {
35
+ loadedSvg(el).addClass('dark:invert dark:hue-rotate-180');
36
+ } else if (colorMap[fill]) {
37
+ loadedSvg(el).removeAttr('fill');
38
+ loadedSvg(el).addClass(colorMap[fill]);
39
+ }
40
+ }
41
+
42
+ function modifySvg(svgString: string): string {
43
+ const loadedSvg = load(svgString, { xmlMode: true });
44
+
45
+ const svg = loadedSvg('svg');
46
+ svg.attr('width', '100%');
47
+ svg.attr('height', '100%');
48
+ svg.addClass('w-full h-auto');
49
+ svg.removeAttr('filter');
50
+
51
+ loadedSvg('path').each((_, el) => {
52
+ applyClasses(loadedSvg, el);
53
+ });
54
+ loadedSvg('text').each((_, el) => {
55
+ applyClasses(loadedSvg, el);
56
+ });
57
+ loadedSvg('rect').each((_, el) => {
58
+ applyClasses(loadedSvg, el);
59
+ });
60
+ loadedSvg('circle').each((_, el) => {
61
+ applyClasses(loadedSvg, el);
62
+ });
63
+ loadedSvg('ellipse').each((_, el) => {
64
+ applyClasses(loadedSvg, el);
65
+ });
66
+ loadedSvg('polygon').each((_, el) => {
67
+ applyClasses(loadedSvg, el);
68
+ });
69
+ loadedSvg('line').each((_, el) => {
70
+ applyClasses(loadedSvg, el);
71
+ });
72
+
73
+ return loadedSvg.html();
74
+ }
75
+ </script>
76
+
77
+ <figure
78
+ bind:this={ref}
79
+ class={cn('excalidraw-container mx-auto w-full max-w-full overflow-hidden', className)}
80
+ {...restProps}
81
+ >
82
+ <div class="excalidraw-svg w-full" aria-label={alt}>
83
+ {@html modifySvg(svg)}
84
+ </div>
85
+ {#if caption}
86
+ <figcaption
87
+ class={cn('text-base-700 dark:text-base-300 mt-4 text-center text-xs', captionClass)}
88
+ >
89
+ {caption}
90
+ </figcaption>
91
+ {/if}
92
+ </figure>
@@ -0,0 +1,13 @@
1
+ import type { WithElementRef, WithoutChildrenOrChild } from 'bits-ui';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = WithElementRef<WithoutChildrenOrChild<HTMLAttributes<HTMLElement>>> & {
4
+ svg: string;
5
+ alt: string;
6
+ caption?: string;
7
+ captionClass?: string;
8
+ autoInvert?: boolean;
9
+ colorMap?: Record<string, string>;
10
+ };
11
+ declare const Undraw: import("svelte").Component<$$ComponentProps, {}, "ref">;
12
+ type Undraw = ReturnType<typeof Undraw>;
13
+ export default Undraw;
@@ -0,0 +1 @@
1
+ export { default as Undraw } from './Undraw.svelte';
@@ -0,0 +1 @@
1
+ export { default as Undraw } from './Undraw.svelte';
@@ -0,0 +1 @@
1
+ export * from './components';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './components';
@@ -0,0 +1 @@
1
+ export * from './index';
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@foxui/visual",
3
+ "private": false,
4
+ "version": "0.4.0",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "sideEffects": [
10
+ "**/*.css"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/types.d.ts",
15
+ "svelte": "./dist/index.js"
16
+ }
17
+ },
18
+ "types": "./dist/types.d.ts",
19
+ "svelte": "./dist/index.js",
20
+ "devDependencies": {
21
+ "@eslint/compat": "^1.2.5",
22
+ "@eslint/js": "^9.18.0",
23
+ "@sveltejs/adapter-auto": "^6.0.0",
24
+ "@sveltejs/adapter-static": "^3.0.8",
25
+ "@sveltejs/kit": "^2.16.0",
26
+ "@sveltejs/package": "^2.3.11",
27
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
28
+ "@tailwindcss/forms": "^0.5.9",
29
+ "@tailwindcss/typography": "^0.5.15",
30
+ "@tailwindcss/vite": "^4.1.5",
31
+ "@types/canvas-confetti": "^1.9.0",
32
+ "eslint": "^9.18.0",
33
+ "eslint-config-prettier": "^10.0.1",
34
+ "eslint-plugin-svelte": "^3.0.0",
35
+ "globals": "^16.0.0",
36
+ "prettier": "^3.4.2",
37
+ "prettier-plugin-svelte": "^3.3.3",
38
+ "prettier-plugin-tailwindcss": "^0.6.11",
39
+ "svelte": "^5.0.0",
40
+ "svelte-check": "^4.0.0",
41
+ "tailwindcss": "^4.1.5",
42
+ "typescript": "^5.0.0",
43
+ "typescript-eslint": "^8.20.0",
44
+ "vite": "^6.2.6"
45
+ },
46
+ "dependencies": {
47
+ "bits-ui": "^1.4.3",
48
+ "canvas-confetti": "^1.9.3",
49
+ "cheerio": "^1.0.0",
50
+ "@foxui/core": "0.4.0",
51
+ "@foxui/colors": "0.4.0"
52
+ },
53
+ "peerDependencies": {
54
+ "svelte": ">=5",
55
+ "tailwindcss": ">=3"
56
+ },
57
+ "description": "ui kit - svelte 5 + tailwind 4 - visual components",
58
+ "homepage": "https://flo-bit.dev/ui-kit",
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/flo-bit/ui-kit.git"
62
+ },
63
+ "author": "flo-bit (http://flo-bit.dev/)",
64
+ "bugs": "https://github.com/flo-bit/ui-kit/issues",
65
+ "license": "MIT",
66
+ "scripts": {
67
+ "dev": "vite dev",
68
+ "build": "vite build && npm run prepack",
69
+ "build:package": "vite build && npm run prepack",
70
+ "preview": "vite preview",
71
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
72
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
73
+ "format": "prettier --write .",
74
+ "lint": "prettier --check . && eslint ."
75
+ }
76
+ }