@vizel/svelte 0.0.1-alpha.1

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 (101) hide show
  1. package/README.md +83 -0
  2. package/dist/components/Vizel.svelte +158 -0
  3. package/dist/components/Vizel.svelte.d.ts +82 -0
  4. package/dist/components/Vizel.svelte.d.ts.map +1 -0
  5. package/dist/components/VizelBubbleMenu.svelte +96 -0
  6. package/dist/components/VizelBubbleMenu.svelte.d.ts +28 -0
  7. package/dist/components/VizelBubbleMenu.svelte.d.ts.map +1 -0
  8. package/dist/components/VizelBubbleMenuButton.svelte +45 -0
  9. package/dist/components/VizelBubbleMenuButton.svelte.d.ts +21 -0
  10. package/dist/components/VizelBubbleMenuButton.svelte.d.ts.map +1 -0
  11. package/dist/components/VizelBubbleMenuColorPicker.svelte +135 -0
  12. package/dist/components/VizelBubbleMenuColorPicker.svelte.d.ts +19 -0
  13. package/dist/components/VizelBubbleMenuColorPicker.svelte.d.ts.map +1 -0
  14. package/dist/components/VizelBubbleMenuDefault.svelte +111 -0
  15. package/dist/components/VizelBubbleMenuDefault.svelte.d.ts +13 -0
  16. package/dist/components/VizelBubbleMenuDefault.svelte.d.ts.map +1 -0
  17. package/dist/components/VizelBubbleMenuDivider.svelte +12 -0
  18. package/dist/components/VizelBubbleMenuDivider.svelte.d.ts +8 -0
  19. package/dist/components/VizelBubbleMenuDivider.svelte.d.ts.map +1 -0
  20. package/dist/components/VizelColorPicker.svelte +269 -0
  21. package/dist/components/VizelColorPicker.svelte.d.ts +25 -0
  22. package/dist/components/VizelColorPicker.svelte.d.ts.map +1 -0
  23. package/dist/components/VizelContext.d.ts +27 -0
  24. package/dist/components/VizelContext.d.ts.map +1 -0
  25. package/dist/components/VizelContext.js +34 -0
  26. package/dist/components/VizelEditor.svelte +61 -0
  27. package/dist/components/VizelEditor.svelte.d.ts +17 -0
  28. package/dist/components/VizelEditor.svelte.d.ts.map +1 -0
  29. package/dist/components/VizelEmbedView.svelte +162 -0
  30. package/dist/components/VizelEmbedView.svelte.d.ts +13 -0
  31. package/dist/components/VizelEmbedView.svelte.d.ts.map +1 -0
  32. package/dist/components/VizelIcon.svelte +54 -0
  33. package/dist/components/VizelIcon.svelte.d.ts +32 -0
  34. package/dist/components/VizelIcon.svelte.d.ts.map +1 -0
  35. package/dist/components/VizelIconContext.d.ts +27 -0
  36. package/dist/components/VizelIconContext.d.ts.map +1 -0
  37. package/dist/components/VizelIconContext.js +31 -0
  38. package/dist/components/VizelIconProvider.svelte +43 -0
  39. package/dist/components/VizelIconProvider.svelte.d.ts +31 -0
  40. package/dist/components/VizelIconProvider.svelte.d.ts.map +1 -0
  41. package/dist/components/VizelLinkEditor.svelte +143 -0
  42. package/dist/components/VizelLinkEditor.svelte.d.ts +15 -0
  43. package/dist/components/VizelLinkEditor.svelte.d.ts.map +1 -0
  44. package/dist/components/VizelNodeSelector.svelte +172 -0
  45. package/dist/components/VizelNodeSelector.svelte.d.ts +13 -0
  46. package/dist/components/VizelNodeSelector.svelte.d.ts.map +1 -0
  47. package/dist/components/VizelPortal.svelte +70 -0
  48. package/dist/components/VizelPortal.svelte.d.ts +19 -0
  49. package/dist/components/VizelPortal.svelte.d.ts.map +1 -0
  50. package/dist/components/VizelProvider.svelte +26 -0
  51. package/dist/components/VizelProvider.svelte.d.ts +14 -0
  52. package/dist/components/VizelProvider.svelte.d.ts.map +1 -0
  53. package/dist/components/VizelSaveIndicator.svelte +94 -0
  54. package/dist/components/VizelSaveIndicator.svelte.d.ts +15 -0
  55. package/dist/components/VizelSaveIndicator.svelte.d.ts.map +1 -0
  56. package/dist/components/VizelSlashMenu.svelte +211 -0
  57. package/dist/components/VizelSlashMenu.svelte.d.ts +31 -0
  58. package/dist/components/VizelSlashMenu.svelte.d.ts.map +1 -0
  59. package/dist/components/VizelSlashMenuEmpty.svelte +22 -0
  60. package/dist/components/VizelSlashMenuEmpty.svelte.d.ts +11 -0
  61. package/dist/components/VizelSlashMenuEmpty.svelte.d.ts.map +1 -0
  62. package/dist/components/VizelSlashMenuItem.svelte +57 -0
  63. package/dist/components/VizelSlashMenuItem.svelte.d.ts +17 -0
  64. package/dist/components/VizelSlashMenuItem.svelte.d.ts.map +1 -0
  65. package/dist/components/VizelThemeProvider.svelte +79 -0
  66. package/dist/components/VizelThemeProvider.svelte.d.ts +11 -0
  67. package/dist/components/VizelThemeProvider.svelte.d.ts.map +1 -0
  68. package/dist/components/index.d.ts +23 -0
  69. package/dist/components/index.d.ts.map +1 -0
  70. package/dist/components/index.js +64 -0
  71. package/dist/iconRenderer.d.ts +6 -0
  72. package/dist/iconRenderer.d.ts.map +1 -0
  73. package/dist/iconRenderer.js +7 -0
  74. package/dist/index.d.ts +9 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +31 -0
  77. package/dist/runes/createVizelAutoSave.svelte.d.ts +44 -0
  78. package/dist/runes/createVizelAutoSave.svelte.d.ts.map +1 -0
  79. package/dist/runes/createVizelAutoSave.svelte.js +91 -0
  80. package/dist/runes/createVizelEditor.svelte.d.ts +43 -0
  81. package/dist/runes/createVizelEditor.svelte.d.ts.map +1 -0
  82. package/dist/runes/createVizelEditor.svelte.js +65 -0
  83. package/dist/runes/createVizelEditorState.svelte.d.ts +27 -0
  84. package/dist/runes/createVizelEditorState.svelte.d.ts.map +1 -0
  85. package/dist/runes/createVizelEditorState.svelte.js +35 -0
  86. package/dist/runes/createVizelMarkdown.svelte.d.ts +68 -0
  87. package/dist/runes/createVizelMarkdown.svelte.d.ts.map +1 -0
  88. package/dist/runes/createVizelMarkdown.svelte.js +123 -0
  89. package/dist/runes/createVizelSlashMenuRenderer.d.ts +22 -0
  90. package/dist/runes/createVizelSlashMenuRenderer.d.ts.map +1 -0
  91. package/dist/runes/createVizelSlashMenuRenderer.js +84 -0
  92. package/dist/runes/createVizelState.svelte.d.ts +22 -0
  93. package/dist/runes/createVizelState.svelte.d.ts.map +1 -0
  94. package/dist/runes/createVizelState.svelte.js +50 -0
  95. package/dist/runes/getVizelTheme.svelte.d.ts +23 -0
  96. package/dist/runes/getVizelTheme.svelte.d.ts.map +1 -0
  97. package/dist/runes/getVizelTheme.svelte.js +31 -0
  98. package/dist/runes/index.d.ts +8 -0
  99. package/dist/runes/index.d.ts.map +1 -0
  100. package/dist/runes/index.js +7 -0
  101. package/package.json +64 -0
@@ -0,0 +1,162 @@
1
+ <script lang="ts" module>
2
+ import type { VizelEmbedData } from "@vizel/core";
3
+
4
+ export interface VizelEmbedViewProps {
5
+ /** Embed data */
6
+ data: VizelEmbedData;
7
+ /** Additional class name */
8
+ class?: string;
9
+ /** Whether the embed is selected */
10
+ selected?: boolean;
11
+ }
12
+ </script>
13
+
14
+ <script lang="ts">
15
+ import VizelIcon from "./VizelIcon.svelte";
16
+
17
+ let { data, class: className, selected = false }: VizelEmbedViewProps = $props();
18
+
19
+ let containerRef: HTMLDivElement | null = $state(null);
20
+
21
+ const baseClass = $derived(
22
+ `vizel-embed ${data.loading ? "is-loading" : ""} ${selected ? "ProseMirror-selectednode" : ""} ${className ?? ""}`
23
+ );
24
+
25
+ const isVideo = $derived(
26
+ ["youtube", "vimeo", "loom", "tiktok"].includes(data.provider ?? "")
27
+ );
28
+
29
+ const hasImage = $derived(Boolean(data.image));
30
+
31
+ const hostname = $derived.by(() => {
32
+ try {
33
+ return new URL(data.url).hostname;
34
+ } catch {
35
+ return data.url;
36
+ }
37
+ });
38
+
39
+ // Handle oEmbed scripts
40
+ function loadScripts() {
41
+ if (data.type === "oembed" && data.html && containerRef) {
42
+ const scripts = containerRef.querySelectorAll("script");
43
+ for (const script of scripts) {
44
+ const newScript = document.createElement("script");
45
+ if (script.src) {
46
+ newScript.src = script.src;
47
+ } else {
48
+ newScript.textContent = script.textContent;
49
+ }
50
+ script.parentNode?.replaceChild(newScript, script);
51
+ }
52
+
53
+ // Load Twitter widgets if present
54
+ if (data.provider === "twitter" && "twttr" in window) {
55
+ (window as { twttr?: { widgets?: { load?: () => void } } }).twttr?.widgets?.load?.();
56
+ }
57
+ }
58
+ }
59
+
60
+ // Load scripts on mount and when data changes
61
+ $effect(() => {
62
+ loadScripts();
63
+ });
64
+ </script>
65
+
66
+ {#if data.loading}
67
+ <!-- Loading state -->
68
+ <div
69
+ class={baseClass}
70
+ data-embed-type="loading"
71
+ data-embed-provider={data.provider}
72
+ >
73
+ <div class="vizel-embed-loading">
74
+ <div class="vizel-embed-loading-spinner"></div>
75
+ <span>Loading embed...</span>
76
+ </div>
77
+ </div>
78
+ {:else if data.type === "oembed" && data.html}
79
+ <!-- oEmbed (rich embed) -->
80
+ <div
81
+ bind:this={containerRef}
82
+ class={baseClass}
83
+ data-embed-type="oembed"
84
+ data-embed-provider={data.provider}
85
+ >
86
+ <div
87
+ class={isVideo ? "vizel-embed-video" : "vizel-embed-oembed"}
88
+ >
89
+ {@html data.html}
90
+ </div>
91
+ </div>
92
+ {:else if data.type === "ogp"}
93
+ <!-- OGP card -->
94
+ <div
95
+ class={baseClass}
96
+ data-embed-type="ogp"
97
+ data-embed-provider={data.provider}
98
+ >
99
+ <a
100
+ href={data.url}
101
+ target="_blank"
102
+ rel="noopener noreferrer"
103
+ class="vizel-embed-card {hasImage ? 'vizel-embed-card-horizontal' : ''}"
104
+ >
105
+ {#if hasImage}
106
+ <img
107
+ src={data.image}
108
+ alt=""
109
+ class="vizel-embed-card-image"
110
+ loading="lazy"
111
+ />
112
+ {/if}
113
+ <div class="vizel-embed-card-content">
114
+ {#if data.siteName || data.favicon}
115
+ <div class="vizel-embed-card-site">
116
+ {#if data.favicon}
117
+ <img
118
+ src={data.favicon}
119
+ alt=""
120
+ class="vizel-embed-card-favicon"
121
+ />
122
+ {/if}
123
+ {#if data.siteName}
124
+ <span>{data.siteName}</span>
125
+ {/if}
126
+ </div>
127
+ {/if}
128
+ {#if data.title}
129
+ <div class="vizel-embed-card-title">{data.title}</div>
130
+ {/if}
131
+ {#if data.description}
132
+ <div class="vizel-embed-card-description">{data.description}</div>
133
+ {/if}
134
+ <div class="vizel-embed-card-url">{hostname}</div>
135
+ </div>
136
+ </a>
137
+ </div>
138
+ {:else if data.type === "title" && data.title}
139
+ <!-- Title link -->
140
+ <div
141
+ class={baseClass}
142
+ data-embed-type="title"
143
+ data-embed-provider={data.provider}
144
+ >
145
+ <a href={data.url} target="_blank" rel="noopener noreferrer" class="vizel-embed-link">
146
+ <span class="vizel-embed-link-icon"><VizelIcon name="link" /></span>
147
+ <span class="vizel-embed-link-text">{data.title}</span>
148
+ </a>
149
+ </div>
150
+ {:else}
151
+ <!-- Plain link (fallback) -->
152
+ <div
153
+ class={baseClass}
154
+ data-embed-type="link"
155
+ data-embed-provider={data.provider}
156
+ >
157
+ <a href={data.url} target="_blank" rel="noopener noreferrer" class="vizel-embed-link">
158
+ <span class="vizel-embed-link-icon"><VizelIcon name="link" /></span>
159
+ <span class="vizel-embed-link-text">{data.url}</span>
160
+ </a>
161
+ </div>
162
+ {/if}
@@ -0,0 +1,13 @@
1
+ import type { VizelEmbedData } from "@vizel/core";
2
+ export interface VizelEmbedViewProps {
3
+ /** Embed data */
4
+ data: VizelEmbedData;
5
+ /** Additional class name */
6
+ class?: string;
7
+ /** Whether the embed is selected */
8
+ selected?: boolean;
9
+ }
10
+ declare const VizelEmbedView: import("svelte").Component<VizelEmbedViewProps, {}, "">;
11
+ type VizelEmbedView = ReturnType<typeof VizelEmbedView>;
12
+ export default VizelEmbedView;
13
+ //# sourceMappingURL=VizelEmbedView.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelEmbedView.svelte.d.ts","sourceRoot":"","sources":["../../src/components/VizelEmbedView.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,iBAAiB;IACjB,IAAI,EAAE,cAAc,CAAC;IACrB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA0HD,QAAA,MAAM,cAAc,yDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -0,0 +1,54 @@
1
+ <script lang="ts" module>
2
+ import type { CustomIconMap, VizelIconName } from "@vizel/core";
3
+
4
+ export interface VizelIconProps {
5
+ /**
6
+ * The semantic icon name from Vizel's icon system.
7
+ */
8
+ name: VizelIconName;
9
+ /**
10
+ * Custom icon mappings to override default Iconify icon IDs.
11
+ * If provided, will take precedence over context icons.
12
+ */
13
+ customIcons?: CustomIconMap;
14
+ /**
15
+ * Icon width in pixels or CSS value.
16
+ */
17
+ width?: string | number;
18
+ /**
19
+ * Icon height in pixels or CSS value.
20
+ */
21
+ height?: string | number;
22
+ /**
23
+ * Icon color.
24
+ */
25
+ color?: string;
26
+ /**
27
+ * Additional CSS class.
28
+ */
29
+ class?: string;
30
+ }
31
+ </script>
32
+
33
+ <script lang="ts">
34
+ import type { IconifyIconProps } from "@iconify/svelte";
35
+ import Icon from "@iconify/svelte";
36
+ import { vizelDefaultIconIds } from "@vizel/core";
37
+ import { getVizelIconContext } from "./VizelIconContext";
38
+
39
+ const { name, customIcons, width, height, color, class: className }: VizelIconProps = $props();
40
+ const { customIcons: contextIcons } = getVizelIconContext();
41
+
42
+ const iconId = $derived(customIcons?.[name] ?? contextIcons?.[name] ?? vizelDefaultIconIds[name]);
43
+
44
+ // Build props object excluding undefined values to satisfy exactOptionalPropertyTypes
45
+ const iconProps = $derived.by(() => {
46
+ const props: IconifyIconProps = { icon: iconId };
47
+ if (width !== undefined) props.width = width;
48
+ if (height !== undefined) props.height = height;
49
+ if (color !== undefined) props.color = color;
50
+ return props;
51
+ });
52
+ </script>
53
+
54
+ <Icon {...iconProps} class={className} style="pointer-events: none;" />
@@ -0,0 +1,32 @@
1
+ import type { CustomIconMap, VizelIconName } from "@vizel/core";
2
+ export interface VizelIconProps {
3
+ /**
4
+ * The semantic icon name from Vizel's icon system.
5
+ */
6
+ name: VizelIconName;
7
+ /**
8
+ * Custom icon mappings to override default Iconify icon IDs.
9
+ * If provided, will take precedence over context icons.
10
+ */
11
+ customIcons?: CustomIconMap;
12
+ /**
13
+ * Icon width in pixels or CSS value.
14
+ */
15
+ width?: string | number;
16
+ /**
17
+ * Icon height in pixels or CSS value.
18
+ */
19
+ height?: string | number;
20
+ /**
21
+ * Icon color.
22
+ */
23
+ color?: string;
24
+ /**
25
+ * Additional CSS class.
26
+ */
27
+ class?: string;
28
+ }
29
+ declare const VizelIcon: import("svelte").Component<VizelIconProps, {}, "">;
30
+ type VizelIcon = ReturnType<typeof VizelIcon>;
31
+ export default VizelIcon;
32
+ //# sourceMappingURL=VizelIcon.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelIcon.svelte.d.ts","sourceRoot":"","sources":["../../src/components/VizelIcon.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmCD,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { CustomIconMap, VizelIconContextValue } from "@vizel/core";
2
+ /**
3
+ * Set custom icon mappings for child components.
4
+ * Call this in a parent component to customize icons for all descendants.
5
+ *
6
+ * @example
7
+ * ```svelte
8
+ * <script lang="ts">
9
+ * import { setVizelIcons } from "@vizel/svelte";
10
+ *
11
+ * // Use Phosphor icons
12
+ * setVizelIcons({
13
+ * heading1: "ph:text-h-one",
14
+ * heading2: "ph:text-h-two",
15
+ * bold: "ph:text-b-bold",
16
+ * italic: "ph:text-italic",
17
+ * });
18
+ * </script>
19
+ * ```
20
+ */
21
+ export declare function setVizelIcons(customIcons?: CustomIconMap): void;
22
+ /**
23
+ * Get custom icon mappings from parent context.
24
+ * Returns an empty object if no context is set.
25
+ */
26
+ export declare function getVizelIconContext(): VizelIconContextValue;
27
+ //# sourceMappingURL=VizelIconContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelIconContext.d.ts","sourceRoot":"","sources":["../../src/components/VizelIconContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAKxE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,WAAW,CAAC,EAAE,aAAa,GAAG,IAAI,CAE/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,qBAAqB,CAE3D"}
@@ -0,0 +1,31 @@
1
+ import { getContext, setContext } from "svelte";
2
+ const VIZEL_ICON_CONTEXT_KEY = Symbol("vizel-icon-context");
3
+ /**
4
+ * Set custom icon mappings for child components.
5
+ * Call this in a parent component to customize icons for all descendants.
6
+ *
7
+ * @example
8
+ * ```svelte
9
+ * <script lang="ts">
10
+ * import { setVizelIcons } from "@vizel/svelte";
11
+ *
12
+ * // Use Phosphor icons
13
+ * setVizelIcons({
14
+ * heading1: "ph:text-h-one",
15
+ * heading2: "ph:text-h-two",
16
+ * bold: "ph:text-b-bold",
17
+ * italic: "ph:text-italic",
18
+ * });
19
+ * </script>
20
+ * ```
21
+ */
22
+ export function setVizelIcons(customIcons) {
23
+ setContext(VIZEL_ICON_CONTEXT_KEY, { customIcons });
24
+ }
25
+ /**
26
+ * Get custom icon mappings from parent context.
27
+ * Returns an empty object if no context is set.
28
+ */
29
+ export function getVizelIconContext() {
30
+ return getContext(VIZEL_ICON_CONTEXT_KEY) ?? {};
31
+ }
@@ -0,0 +1,43 @@
1
+ <script lang="ts" module>
2
+ import type { CustomIconMap } from "@vizel/core";
3
+ import type { Snippet } from "svelte";
4
+
5
+ /**
6
+ * Props for VizelIconProvider component.
7
+ */
8
+ export interface VizelIconProviderProps {
9
+ /**
10
+ * Custom icon mappings to override default Lucide icons.
11
+ * Any icon not specified will fall back to the default Lucide icon.
12
+ *
13
+ * @example
14
+ * ```svelte
15
+ * <VizelIconProvider icons={{ bold: "mdi:format-bold", italic: "mdi:format-italic" }}>
16
+ * <App />
17
+ * </VizelIconProvider>
18
+ *
19
+ * <VizelIconProvider icons={{ check: "heroicons:check", warning: "heroicons:exclamation-triangle" }}>
20
+ * <App />
21
+ * </VizelIconProvider>
22
+ * ```
23
+ */
24
+ icons?: CustomIconMap;
25
+ /**
26
+ * Child content to render inside the provider.
27
+ */
28
+ children?: Snippet;
29
+ }
30
+ </script>
31
+
32
+ <script lang="ts">
33
+ import { setVizelIcons } from "./VizelIconContext.ts";
34
+
35
+ const { icons, children }: VizelIconProviderProps = $props();
36
+
37
+ // Set icons in context for all descendants
38
+ setVizelIcons(icons);
39
+ </script>
40
+
41
+ {#if children}
42
+ {@render children()}
43
+ {/if}
@@ -0,0 +1,31 @@
1
+ import type { CustomIconMap } from "@vizel/core";
2
+ import type { Snippet } from "svelte";
3
+ /**
4
+ * Props for VizelIconProvider component.
5
+ */
6
+ export interface VizelIconProviderProps {
7
+ /**
8
+ * Custom icon mappings to override default Lucide icons.
9
+ * Any icon not specified will fall back to the default Lucide icon.
10
+ *
11
+ * @example
12
+ * ```svelte
13
+ * <VizelIconProvider icons={{ bold: "mdi:format-bold", italic: "mdi:format-italic" }}>
14
+ * <App />
15
+ * </VizelIconProvider>
16
+ *
17
+ * <VizelIconProvider icons={{ check: "heroicons:check", warning: "heroicons:exclamation-triangle" }}>
18
+ * <App />
19
+ * </VizelIconProvider>
20
+ * ```
21
+ */
22
+ icons?: CustomIconMap;
23
+ /**
24
+ * Child content to render inside the provider.
25
+ */
26
+ children?: Snippet;
27
+ }
28
+ declare const VizelIconProvider: import("svelte").Component<VizelIconProviderProps, {}, "">;
29
+ type VizelIconProvider = ReturnType<typeof VizelIconProvider>;
30
+ export default VizelIconProvider;
31
+ //# sourceMappingURL=VizelIconProvider.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelIconProvider.svelte.d.ts","sourceRoot":"","sources":["../../src/components/VizelIconProvider.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsBD,QAAA,MAAM,iBAAiB,4DAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,143 @@
1
+ <script lang="ts" module>
2
+ import type { Editor } from "@vizel/core";
3
+
4
+ export interface VizelLinkEditorProps {
5
+ /** The editor instance */
6
+ editor: Editor;
7
+ /** Custom class name */
8
+ class?: string;
9
+ /** Close handler */
10
+ onclose?: () => void;
11
+ /** Enable embed option (requires Embed extension) */
12
+ enableEmbed?: boolean;
13
+ }
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import { detectVizelEmbedProvider } from "@vizel/core";
18
+ import { untrack } from "svelte";
19
+ import VizelIcon from "./VizelIcon.svelte";
20
+
21
+ let {
22
+ editor,
23
+ class: className,
24
+ onclose,
25
+ enableEmbed = false,
26
+ }: VizelLinkEditorProps = $props();
27
+
28
+ let formElement: HTMLFormElement;
29
+ let inputElement: HTMLInputElement;
30
+ let currentHref = $derived(editor.getAttributes("link").href || "");
31
+ let url = $state(untrack(() => editor.getAttributes("link").href || ""));
32
+ let asEmbed = $state(false);
33
+
34
+ // Check if embed extension is available
35
+ const canEmbed = $derived.by(() => {
36
+ if (!enableEmbed) return false;
37
+ // Check if embed extension is loaded
38
+ const extensionManager = editor.extensionManager;
39
+ return extensionManager.extensions.some((ext) => ext.name === "embed");
40
+ });
41
+
42
+ // Check if URL is a known embed provider
43
+ const isEmbedProvider = $derived.by(() => {
44
+ if (!url.trim()) return false;
45
+ return detectVizelEmbedProvider(url.trim()) !== null;
46
+ });
47
+
48
+ // Handle click outside to close
49
+ function handleClickOutside(event: MouseEvent) {
50
+ if (formElement && !formElement.contains(event.target as Node)) {
51
+ onclose?.();
52
+ }
53
+ }
54
+
55
+ // Handle Escape key to close
56
+ function handleKeyDown(event: KeyboardEvent) {
57
+ if (event.key === "Escape") {
58
+ event.preventDefault();
59
+ event.stopImmediatePropagation();
60
+ onclose?.();
61
+ }
62
+ }
63
+
64
+ $effect(() => {
65
+ inputElement?.focus();
66
+
67
+ // Use setTimeout to avoid immediate trigger from the click that opened the editor
68
+ const timeoutId = setTimeout(() => {
69
+ document.addEventListener("mousedown", handleClickOutside);
70
+ }, 0);
71
+ // Use capture phase so this handler runs before BubbleMenu's handler
72
+ document.addEventListener("keydown", handleKeyDown, true);
73
+
74
+ return () => {
75
+ clearTimeout(timeoutId);
76
+ document.removeEventListener("mousedown", handleClickOutside);
77
+ document.removeEventListener("keydown", handleKeyDown, true);
78
+ };
79
+ });
80
+
81
+ function handleSubmit(e: Event) {
82
+ e.preventDefault();
83
+ const trimmedUrl = url.trim();
84
+
85
+ if (!trimmedUrl) {
86
+ editor.chain().focus().unsetLink().run();
87
+ onclose?.();
88
+ return;
89
+ }
90
+
91
+ if (asEmbed && canEmbed) {
92
+ // Remove the link first, then insert embed
93
+ editor.chain().focus().unsetLink().setEmbed({ url: trimmedUrl }).run();
94
+ } else {
95
+ editor.chain().focus().setLink({ href: trimmedUrl }).run();
96
+ }
97
+ onclose?.();
98
+ }
99
+
100
+ function handleRemove() {
101
+ editor.chain().focus().unsetLink().run();
102
+ onclose?.();
103
+ }
104
+ </script>
105
+
106
+ <form
107
+ bind:this={formElement}
108
+ class="vizel-link-editor {className ?? ''}"
109
+ onsubmit={handleSubmit}
110
+ >
111
+ <div class="vizel-link-editor-row">
112
+ <input
113
+ bind:this={inputElement}
114
+ bind:value={url}
115
+ type="url"
116
+ placeholder="Enter URL..."
117
+ class="vizel-link-input"
118
+ />
119
+ <button type="submit" class="vizel-link-button" title="Apply">
120
+ <VizelIcon name="check" />
121
+ </button>
122
+ {#if currentHref}
123
+ <button
124
+ type="button"
125
+ class="vizel-link-button vizel-link-remove"
126
+ title="Remove link"
127
+ onclick={handleRemove}
128
+ >
129
+ <VizelIcon name="x" />
130
+ </button>
131
+ {/if}
132
+ </div>
133
+ {#if canEmbed && isEmbedProvider}
134
+ <div class="vizel-link-editor-embed-toggle">
135
+ <input
136
+ id="vizel-embed-toggle"
137
+ type="checkbox"
138
+ bind:checked={asEmbed}
139
+ />
140
+ <label for="vizel-embed-toggle">Embed as rich content</label>
141
+ </div>
142
+ {/if}
143
+ </form>
@@ -0,0 +1,15 @@
1
+ import type { Editor } from "@vizel/core";
2
+ export interface VizelLinkEditorProps {
3
+ /** The editor instance */
4
+ editor: Editor;
5
+ /** Custom class name */
6
+ class?: string;
7
+ /** Close handler */
8
+ onclose?: () => void;
9
+ /** Enable embed option (requires Embed extension) */
10
+ enableEmbed?: boolean;
11
+ }
12
+ declare const VizelLinkEditor: import("svelte").Component<VizelLinkEditorProps, {}, "">;
13
+ type VizelLinkEditor = ReturnType<typeof VizelLinkEditor>;
14
+ export default VizelLinkEditor;
15
+ //# sourceMappingURL=VizelLinkEditor.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VizelLinkEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/components/VizelLinkEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAyHD,QAAA,MAAM,eAAe,0DAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}