@foxui/social 0.4.4 → 0.4.6

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.
@@ -1,13 +1,42 @@
1
+ <script lang="ts" module>
2
+ import { isEmojiSupported } from 'is-emoji-supported';
3
+
4
+ import Database from 'emoji-picker-element/database';
5
+
6
+ export let emojiDatabase: {
7
+ db: Database | undefined;
8
+ } = $state({
9
+ db: undefined
10
+ });
11
+
12
+ export function loadEmojis() {
13
+ if(emojiDatabase.db) return;
14
+
15
+ import('emoji-picker-element').then(({ Database }) => {
16
+ emojiDatabase.db = new Database();
17
+
18
+ // go through all groups and check if the emoji is supported (will be cached)
19
+ // so that things appear faster when we select a group
20
+ for (const group of allGroups) {
21
+ emojiDatabase.db.getEmojiByGroup(group.id).then((emojis) => {
22
+ for (const emoji of emojis) {
23
+ isEmojiSupported(emoji.unicode);
24
+ }
25
+ });
26
+ }
27
+ });
28
+ console.log('emojis loaded');
29
+ }
30
+ </script>
31
+
1
32
  <script lang="ts">
2
33
  import { cn, ScrollArea } from '@foxui/core';
3
- import { isEmojiSupported } from 'is-emoji-supported';
4
34
  import { allGroups } from './emoji';
5
- import Database from 'emoji-picker-element/database';
6
35
  import type { NativeEmoji } from 'emoji-picker-element/shared';
7
36
  import { fade } from 'svelte/transition';
37
+ import { onMount } from 'svelte';
8
38
 
9
39
  let currentGroup = $state(allGroups[0].id);
10
- let db: Database | undefined = $state();
11
40
 
12
41
  let {
13
42
  onpicked,
@@ -23,22 +52,9 @@
23
52
  class?: string;
24
53
  } = $props();
25
54
 
26
- $effect(() => {
27
- if (db) return;
28
- import('emoji-picker-element').then(({ Database }) => {
29
- db = new Database();
30
-
31
- // go through all groups and check if the emoji is supported (will be cached)
32
- // so that things appear faster when we select a group
33
- for (const group of allGroups) {
34
- db.getEmojiByGroup(group.id).then((emojis) => {
35
- for (const emoji of emojis) {
36
- isEmojiSupported(emoji.unicode);
37
- }
38
- });
39
- }
40
- });
41
- });
55
+ onMount(() => {
56
+ loadEmojis();
57
+ })
42
58
  </script>
43
59
 
44
60
  <div class={cn('flex flex-col', className)} style="height: {height}px; width: {width}px;">
@@ -46,7 +62,7 @@
46
62
  class="grid w-full select-none space-y-0 px-2"
47
63
  style="height: {height}px; grid-template-columns: repeat({columns}, minmax(0, 1fr));"
48
64
  >
49
- {#await db?.getEmojiByGroup(currentGroup) then emojis}
65
+ {#await emojiDatabase.db?.getEmojiByGroup(currentGroup) then emojis}
50
66
  {#if emojis}
51
67
  {#each emojis as emoji}
52
68
  {#if isEmojiSupported(emoji.unicode)}
@@ -70,12 +86,12 @@
70
86
  <button
71
87
  onclick={() => (currentGroup = group.id)}
72
88
  class={cn(
73
- '[&>svg]:size-4.5 relative cursor-pointer [&>svg]:transition-all [&>svg]:duration-100 [&>svg]:hover:scale-105 py-2',
89
+ '[&>svg]:size-4.5 relative cursor-pointer py-2 [&>svg]:transition-all [&>svg]:duration-100 [&>svg]:hover:scale-105',
74
90
  group.id === currentGroup
75
91
  ? 'text-accent-600 dark:text-accent-400'
76
92
  : 'hover:text-accent-700 dark:hover:text-accent-300'
77
93
  )}
78
- >
94
+ >
79
95
  {@html group.svg}
80
96
  <span class="sr-only">{group.name}</span>
81
97
 
@@ -1,3 +1,8 @@
1
+ import Database from 'emoji-picker-element/database';
2
+ export declare let emojiDatabase: {
3
+ db: Database | undefined;
4
+ };
5
+ export declare function loadEmojis(): void;
1
6
  import type { NativeEmoji } from 'emoji-picker-element/shared';
2
7
  type $$ComponentProps = {
3
8
  onpicked?: (emoji: NativeEmoji) => void;
@@ -1,2 +1,3 @@
1
1
  export { default as EmojiPicker } from './EmojiPicker.svelte';
2
2
  export { default as PopoverEmojiPicker } from './PopoverEmojiPicker.svelte';
3
+ export { loadEmojis } from './EmojiPicker.svelte';
@@ -1,2 +1,3 @@
1
1
  export { default as EmojiPicker } from './EmojiPicker.svelte';
2
2
  export { default as PopoverEmojiPicker } from './PopoverEmojiPicker.svelte';
3
+ export { loadEmojis } from './EmojiPicker.svelte';
@@ -9,4 +9,5 @@ export * from './chat';
9
9
  export * from './emoji-picker';
10
10
  export * from './bluesky-post';
11
11
  export * from './nested-comments';
12
+ export * from './link-card';
12
13
  export declare function numberToHumanReadable(number: number): string | number;
@@ -9,6 +9,7 @@ export * from './chat';
9
9
  export * from './emoji-picker';
10
10
  export * from './bluesky-post';
11
11
  export * from './nested-comments';
12
+ export * from './link-card';
12
13
  export function numberToHumanReadable(number) {
13
14
  if (number < 1000) {
14
15
  return number;
@@ -0,0 +1,104 @@
1
+ <script lang="ts" module>
2
+ import type { WithElementRef } from 'bits-ui';
3
+ import type { HTMLAnchorAttributes, HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '@foxui/core';
5
+
6
+ export type LinkCardProps = WithElementRef<HTMLAttributes<HTMLDivElement>> &
7
+ WithElementRef<HTMLAnchorAttributes> & {
8
+ showMedia?: boolean;
9
+ showDescription?: boolean;
10
+ showTitle?: boolean;
11
+ showDomain?: boolean;
12
+ showGradient?: boolean;
13
+
14
+ meta: {
15
+ title: string;
16
+ description?: string;
17
+
18
+ image?: string;
19
+ imageAlt?: string;
20
+
21
+ video?: string;
22
+ videoType?: string;
23
+ };
24
+ };
25
+ </script>
26
+
27
+ <script lang="ts">
28
+ let {
29
+ class: className,
30
+ ref = $bindable(null),
31
+ href,
32
+
33
+ target = '_blank',
34
+
35
+ showMedia = true,
36
+ showDescription = false,
37
+ showTitle = true,
38
+ showDomain = true,
39
+ showGradient = true,
40
+
41
+ meta,
42
+
43
+ children,
44
+ ...restProps
45
+ }: LinkCardProps = $props();
46
+ </script>
47
+
48
+ <div
49
+ bind:this={ref}
50
+ class={cn(
51
+ 'not-prose group border-base-300 dark:border-base-900 bg-base-200/50 dark:bg-base-950/50 group relative isolate my-6 flex aspect-[1200/630] max-w-lg flex-col justify-end overflow-hidden rounded-2xl border p-4',
52
+ 'focus-within:outline-accent-500 focus-within:outline-2 focus-within:outline-offset-2',
53
+ className
54
+ )}
55
+ {...restProps}
56
+ >
57
+ {#if showMedia}
58
+ {#if meta.video && meta.videoType}
59
+ <video
60
+ autoplay
61
+ loop
62
+ muted
63
+ preload="metadata"
64
+ width="1200"
65
+ height="630"
66
+ class="absolute inset-0 -z-10 h-full w-full rounded-2xl object-cover"
67
+ >
68
+ <source src={meta.video} type={meta.videoType} />
69
+ </video>
70
+ {:else if meta.image}
71
+ <img
72
+ src={meta.image}
73
+ alt={meta.imageAlt || ''}
74
+ width="1200"
75
+ height="630"
76
+ class="absolute inset-0 -z-10 h-full w-full rounded-2xl object-cover group-hover:scale-102 transition-all duration-300 ease-in-out"
77
+ />
78
+ {/if}
79
+ {/if}
80
+
81
+ {#if showGradient}
82
+ <div
83
+ class="from-base-200/90 to-base-200/40 dark:from-base-950 dark:to-base-950/60 absolute inset-0 -z-10 rounded-xl bg-gradient-to-t"
84
+ ></div>
85
+ {/if}
86
+
87
+ {#if showDomain}
88
+ <div class="dark:text-accent-400 text-accent-600 text-xs font-semibold">
89
+ {href ? new URL(href).hostname.replace('www.', '') : ''}
90
+ </div>
91
+ {/if}
92
+
93
+ <div class="text-base-950 dark:text-base-50 mt-2 text-lg font-semibold">
94
+ <a {href} {target} class="focus:outline-none">
95
+ <span class="absolute inset-0"></span>
96
+ <div class={showTitle ? '' : 'sr-only'}>{meta?.title ?? href}</div>
97
+ </a>
98
+ </div>
99
+ {#if showDescription}
100
+ <div class="dark:text-base-400 text-base-700 mt-1 line-clamp-2 text-xs/5">
101
+ {meta?.description ?? ''}
102
+ </div>
103
+ {/if}
104
+ </div>
@@ -0,0 +1,20 @@
1
+ import type { WithElementRef } from 'bits-ui';
2
+ import type { HTMLAnchorAttributes, HTMLAttributes } from 'svelte/elements';
3
+ export type LinkCardProps = WithElementRef<HTMLAttributes<HTMLDivElement>> & WithElementRef<HTMLAnchorAttributes> & {
4
+ showMedia?: boolean;
5
+ showDescription?: boolean;
6
+ showTitle?: boolean;
7
+ showDomain?: boolean;
8
+ showGradient?: boolean;
9
+ meta: {
10
+ title: string;
11
+ description?: string;
12
+ image?: string;
13
+ imageAlt?: string;
14
+ video?: string;
15
+ videoType?: string;
16
+ };
17
+ };
18
+ declare const LinkCard: import("svelte").Component<LinkCardProps, {}, "ref">;
19
+ type LinkCard = ReturnType<typeof LinkCard>;
20
+ export default LinkCard;
@@ -0,0 +1 @@
1
+ export { default as LinkCard } from './LinkCard.svelte';
@@ -0,0 +1 @@
1
+ export { default as LinkCard } from './LinkCard.svelte';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@foxui/social",
3
3
  "private": false,
4
- "version": "0.4.4",
4
+ "version": "0.4.6",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -50,8 +50,8 @@
50
50
  "hls.js": "^1.6.2",
51
51
  "is-emoji-supported": "^0.0.5",
52
52
  "plyr": "^3.7.8",
53
- "@foxui/core": "0.4.4",
54
- "@foxui/time": "0.4.4"
53
+ "@foxui/core": "0.4.6",
54
+ "@foxui/time": "0.4.6"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "svelte": ">=5",