@widgetic/design-system 0.5.21 → 0.5.23
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/README.md +2 -0
- package/dist/components/CopyableHeader.svelte +260 -448
- package/dist/components/CopyableHeader.svelte.d.ts +8 -5
- package/dist/components/EmptyState.svelte +100 -128
- package/dist/components/EmptyState.svelte.d.ts +16 -19
- package/dist/components/GenerateLoader.svelte +17 -10
- package/dist/components/PasswordInput.svelte +41 -44
- package/dist/components/PasswordInput.svelte.d.ts +2 -0
- package/dist/components/ThumbHashImage.svelte +117 -119
- package/dist/components/WScrollArea.svelte +47 -41
- package/dist/components/chat/ActivityRow.svelte +115 -0
- package/dist/components/chat/ActivityRow.svelte.d.ts +18 -0
- package/dist/components/chat/ChatHeader.svelte +114 -0
- package/dist/components/chat/ChatHeader.svelte.d.ts +26 -0
- package/dist/components/chat/Composer.svelte +172 -0
- package/dist/components/chat/Composer.svelte.d.ts +27 -0
- package/dist/components/chat/Message.svelte +158 -0
- package/dist/components/chat/Message.svelte.d.ts +28 -0
- package/dist/components/chat/OptionRow.svelte +59 -0
- package/dist/components/chat/OptionRow.svelte.d.ts +14 -0
- package/dist/components/chat/PlanCard.svelte +220 -0
- package/dist/components/chat/PlanCard.svelte.d.ts +34 -0
- package/dist/components/chat/QuestionCard.svelte +265 -0
- package/dist/components/chat/QuestionCard.svelte.d.ts +38 -0
- package/dist/components/chat/ScrollToBottom.svelte +51 -0
- package/dist/components/chat/ScrollToBottom.svelte.d.ts +11 -0
- package/dist/components/chat/SuggestionCard.svelte +79 -0
- package/dist/components/chat/SuggestionCard.svelte.d.ts +20 -0
- package/dist/components/chat/TaskRow.svelte +59 -0
- package/dist/components/chat/TaskRow.svelte.d.ts +11 -0
- package/dist/components/chat/composerLogic.d.ts +16 -0
- package/dist/components/chat/composerLogic.js +29 -0
- package/dist/components/chat/index.d.ts +16 -0
- package/dist/components/chat/index.js +16 -0
- package/dist/components/chat/questionCardLogic.d.ts +11 -0
- package/dist/components/chat/questionCardLogic.js +39 -0
- package/dist/components/index.d.ts +10 -1
- package/dist/components/index.js +10 -0
- package/dist/components/modals/ActionModal.svelte +186 -180
- package/dist/components/modals/BaseModal.svelte +404 -395
- package/dist/components/modals/BaseModal.svelte.d.ts +3 -0
- package/dist/components/modals/NewItemDialog.svelte +200 -243
- package/dist/components/modals/Portal.svelte +107 -105
- package/dist/components/modals/README.md +16 -2
- package/dist/components/modals/RenameDialog.svelte +234 -292
- package/dist/components/navigation/Breadcrumbs.svelte +415 -377
- package/dist/components/navigation/Breadcrumbs.svelte.d.ts +3 -2
- package/dist/components/navigation/types.d.ts +2 -0
- package/dist/components/pdf/PDFViewer.svelte +54 -1
- package/dist/components/search-input/SearchInput.svelte +51 -104
- package/dist/components/search-input/SearchInput.svelte.d.ts +9 -27
- package/dist/components/shad-editor/editor.css +1 -1
- package/dist/components/shad-editor/i18n/messages.d.ts +1 -1
- package/dist/components/shad-editor/i18n/messages.js +1 -1
- package/dist/components/shell/AppShell.svelte +52 -0
- package/dist/components/shell/AppShell.svelte.d.ts +13 -0
- package/dist/components/shell/Banner.svelte +90 -0
- package/dist/components/shell/Banner.svelte.d.ts +61 -0
- package/dist/components/shell/ErrorState.svelte +60 -0
- package/dist/components/shell/ErrorState.svelte.d.ts +13 -0
- package/dist/components/shell/Link.svelte +63 -0
- package/dist/components/shell/Link.svelte.d.ts +53 -0
- package/dist/components/shell/NavDrawer.svelte +117 -0
- package/dist/components/shell/NavDrawer.svelte.d.ts +10 -0
- package/dist/components/shell/NavRow.svelte +128 -0
- package/dist/components/shell/NavRow.svelte.d.ts +65 -0
- package/dist/components/shell/NavSectionLabel.svelte +27 -0
- package/dist/components/shell/NavSectionLabel.svelte.d.ts +9 -0
- package/dist/components/shell/NotificationRow.svelte +76 -0
- package/dist/components/shell/NotificationRow.svelte.d.ts +16 -0
- package/dist/components/shell/PageHeader.svelte +42 -0
- package/dist/components/shell/PageHeader.svelte.d.ts +12 -0
- package/dist/components/shell/ProfileRow.svelte +95 -0
- package/dist/components/shell/ProfileRow.svelte.d.ts +54 -0
- package/dist/components/shell/SettingsDialog.svelte +118 -0
- package/dist/components/shell/SettingsDialog.svelte.d.ts +19 -0
- package/dist/components/shell/SettingsNav.svelte +46 -0
- package/dist/components/shell/SettingsNav.svelte.d.ts +11 -0
- package/dist/components/shell/Sidebar.svelte +82 -0
- package/dist/components/shell/Sidebar.svelte.d.ts +25 -0
- package/dist/components/shell/Stat.svelte +63 -0
- package/dist/components/shell/Stat.svelte.d.ts +58 -0
- package/dist/components/shell/TopBar.svelte +37 -0
- package/dist/components/shell/TopBar.svelte.d.ts +11 -0
- package/dist/components/shell/WidgetRow.svelte +126 -0
- package/dist/components/shell/WidgetRow.svelte.d.ts +78 -0
- package/dist/components/shell/error-state-messages.d.ts +7 -0
- package/dist/components/shell/error-state-messages.js +9 -0
- package/dist/components/shell/index.d.ts +22 -0
- package/dist/components/shell/index.js +25 -0
- package/dist/components/shell/link-external.d.ts +2 -0
- package/dist/components/shell/link-external.js +7 -0
- package/dist/components/shell/messages.d.ts +7 -0
- package/dist/components/shell/messages.js +5 -0
- package/dist/components/shell/settings-nav-types.d.ts +12 -0
- package/dist/components/shell/settings-nav-types.js +3 -0
- package/dist/components/shell/shell-utils.d.ts +7 -0
- package/dist/components/shell/shell-utils.js +27 -0
- package/dist/components/shell/stat-tone.d.ts +3 -0
- package/dist/components/shell/stat-tone.js +11 -0
- package/dist/components/toast/ToasterModal.svelte +102 -168
- package/dist/components/toast/ToasterModal.svelte.d.ts +2 -12
- package/dist/components/ui/accordion/accordion-content.svelte +3 -2
- package/dist/components/ui/accordion/accordion-item.svelte +10 -1
- package/dist/components/ui/accordion/accordion-trigger.svelte +4 -3
- package/dist/components/ui/alert/alert-description.svelte +5 -1
- package/dist/components/ui/alert/alert-title.svelte +2 -1
- package/dist/components/ui/alert/index.d.ts +13 -11
- package/dist/components/ui/alert/index.js +4 -4
- package/dist/components/ui/avatar/avatar-utils.d.ts +2 -0
- package/dist/components/ui/avatar/avatar-utils.js +9 -0
- package/dist/components/ui/avatar/avatar.svelte +63 -0
- package/dist/components/ui/avatar/avatar.svelte.d.ts +80 -0
- package/dist/components/ui/avatar/index.d.ts +4 -0
- package/dist/components/ui/avatar/index.js +4 -0
- package/dist/components/ui/badge/badge.svelte +22 -10
- package/dist/components/ui/badge/badge.svelte.d.ts +14 -15
- package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
- package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +1 -1
- package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +1 -1
- package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +2 -2
- package/dist/components/ui/button/button-padding.d.ts +9 -0
- package/dist/components/ui/button/button-padding.js +15 -0
- package/dist/components/ui/button/button.svelte +81 -31
- package/dist/components/ui/button/button.svelte.d.ts +48 -29
- package/dist/components/ui/calendar/calendar-cell.svelte +1 -1
- package/dist/components/ui/calendar/calendar-head-cell.svelte +1 -1
- package/dist/components/ui/calendar/calendar-next-button.svelte +2 -2
- package/dist/components/ui/calendar/calendar-prev-button.svelte +2 -2
- package/dist/components/ui/card/card-description.svelte +1 -1
- package/dist/components/ui/card/card-title.svelte +1 -1
- package/dist/components/ui/card/card.svelte +1 -1
- package/dist/components/ui/checkbox/checkbox.svelte +9 -5
- package/dist/components/ui/chip/chip.svelte +48 -0
- package/dist/components/ui/chip/chip.svelte.d.ts +13 -0
- package/dist/components/ui/chip/index.d.ts +2 -0
- package/dist/components/ui/chip/index.js +2 -0
- package/dist/components/ui/command/command-dialog.svelte +1 -1
- package/dist/components/ui/command/command-input.svelte +4 -4
- package/dist/components/ui/command/command-item.svelte +1 -1
- package/dist/components/ui/command/command.svelte +1 -1
- package/dist/components/ui/dialog/dialog-content.svelte +4 -4
- package/dist/components/ui/dialog/dialog-description.svelte +1 -1
- package/dist/components/ui/dialog/dialog-overlay.svelte +1 -1
- package/dist/components/ui/dialog/dialog-title.svelte +1 -1
- package/dist/components/ui/drawer/drawer-content.svelte +1 -1
- package/dist/components/ui/drawer/drawer-overlay.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +5 -5
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +20 -2
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +5 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +3 -3
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +3 -3
- package/dist/components/ui/field/field-ids.d.ts +7 -0
- package/dist/components/ui/field/field-ids.js +15 -0
- package/dist/components/ui/field/field.svelte +62 -0
- package/dist/components/ui/field/field.svelte.d.ts +21 -0
- package/dist/components/ui/field/index.d.ts +3 -0
- package/dist/components/ui/field/index.js +3 -0
- package/dist/components/ui/hover-card/hover-card-content.svelte +1 -1
- package/dist/components/ui/icon-button/icon-button.svelte +72 -0
- package/dist/components/ui/icon-button/icon-button.svelte.d.ts +90 -0
- package/dist/components/ui/icon-button/index.d.ts +2 -0
- package/dist/components/ui/icon-button/index.js +4 -0
- package/dist/components/ui/input/index.d.ts +1 -0
- package/dist/components/ui/input/input.svelte +11 -4
- package/dist/components/ui/input/input.svelte.d.ts +4 -1
- package/dist/components/ui/input-otp/input-otp-separator.svelte +2 -2
- package/dist/components/ui/input-otp/input-otp-slot.svelte +5 -4
- package/dist/components/ui/input-otp/input-otp-slot.svelte.d.ts +1 -1
- package/dist/components/ui/input-otp/input-otp.svelte +1 -1
- package/dist/components/ui/label/label.svelte +3 -2
- package/dist/components/ui/popover/popover-content.svelte +1 -1
- package/dist/components/ui/progress/progress.svelte +19 -5
- package/dist/components/ui/progress/progress.svelte.d.ts +4 -2
- package/dist/components/ui/radio-group/radio-group-item.svelte +4 -4
- package/dist/components/ui/range-calendar/range-calendar-head-cell.svelte +1 -1
- package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +2 -2
- package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +2 -2
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +4 -1
- package/dist/components/ui/scroll-area/scroll-area.svelte +1 -1
- package/dist/components/ui/select/select-content.svelte +1 -3
- package/dist/components/ui/select/select-item.svelte +5 -4
- package/dist/components/ui/select/select-scroll-down-button.svelte +2 -2
- package/dist/components/ui/select/select-scroll-up-button.svelte +2 -2
- package/dist/components/ui/select/select-trigger.svelte +4 -3
- package/dist/components/ui/skeleton/index.d.ts +2 -0
- package/dist/components/ui/skeleton/index.js +2 -0
- package/dist/components/ui/skeleton/skeleton.svelte +24 -0
- package/dist/components/ui/skeleton/skeleton.svelte.d.ts +8 -0
- package/dist/components/ui/slider/slider.svelte +5 -10
- package/dist/components/ui/sonner/sonner.svelte +19 -13
- package/dist/components/ui/stepper-button/index.d.ts +3 -0
- package/dist/components/ui/stepper-button/index.js +2 -0
- package/dist/components/ui/stepper-button/stepper-button.svelte +37 -0
- package/dist/components/ui/stepper-button/stepper-button.svelte.d.ts +9 -0
- package/dist/components/ui/switch/switch.svelte +8 -3
- package/dist/components/ui/table/table-cell.svelte +1 -1
- package/dist/components/ui/table/table-head.svelte +1 -1
- package/dist/components/ui/table/table-row.svelte +1 -1
- package/dist/components/ui/tabs/tabs-list.svelte +1 -1
- package/dist/components/ui/tabs/tabs-trigger.svelte +1 -1
- package/dist/components/ui/tag/index.d.ts +2 -0
- package/dist/components/ui/tag/index.js +2 -0
- package/dist/components/ui/tag/tag.svelte +42 -0
- package/dist/components/ui/tag/tag.svelte.d.ts +11 -0
- package/dist/components/ui/textarea/textarea.svelte +4 -3
- package/dist/components/ui/textarea/textarea.svelte.d.ts +2 -2
- package/dist/components/ui/toggle/toggle.svelte +9 -9
- package/dist/components/ui/toggle/toggle.svelte.d.ts +14 -21
- package/dist/components/ui/tooltip/tooltip-content.svelte +1 -1
- package/dist/fonts/Inter/Inter-Black.woff2 +0 -0
- package/dist/fonts/Inter/Inter-BlackItalic.woff2 +0 -0
- package/dist/fonts/Inter/Inter-Bold.woff2 +0 -0
- package/dist/fonts/Inter/Inter-BoldItalic.woff2 +0 -0
- package/dist/fonts/Inter/Inter-ExtraBold.woff2 +0 -0
- package/dist/fonts/Inter/Inter-ExtraBoldItalic.woff2 +0 -0
- package/dist/fonts/Inter/Inter-ExtraLight-BETA.woff2 +0 -0
- package/dist/fonts/Inter/Inter-ExtraLightItalic-BETA.woff2 +0 -0
- package/dist/fonts/Inter/Inter-Italic.woff2 +0 -0
- package/dist/fonts/Inter/Inter-Light-BETA.woff2 +0 -0
- package/dist/fonts/Inter/Inter-LightItalic-BETA.woff2 +0 -0
- package/dist/fonts/Inter/Inter-Medium.woff2 +0 -0
- package/dist/fonts/Inter/Inter-MediumItalic.woff2 +0 -0
- package/dist/fonts/Inter/Inter-Regular.woff2 +0 -0
- package/dist/fonts/Inter/Inter-SemiBold.woff2 +0 -0
- package/dist/fonts/Inter/Inter-SemiBoldItalic.woff2 +0 -0
- package/dist/fonts/Inter/Inter-Thin-BETA.woff2 +0 -0
- package/dist/fonts/Inter/Inter-ThinItalic-BETA.woff2 +0 -0
- package/dist/fonts/Inter/Inter-italic.var.woff2 +0 -0
- package/dist/fonts/Inter/Inter-upright.var.woff2 +0 -0
- package/dist/fonts/Inter/Inter.var.woff2 +0 -0
- package/dist/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 +0 -0
- package/dist/i18n/audit/designSystemWords.d.ts +1 -1
- package/dist/i18n/audit/designSystemWords.js +1 -1
- package/dist/styles/fonts.css +18 -14
- package/dist/styles/global.css +7 -19
- package/dist/styles/tokens.css +332 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +33 -2
- package/package.json +2 -1
- package/tailwind.config.ts +7 -47
|
@@ -2,467 +2,279 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* CopyableHeader Component
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - Optional help icon with tooltip
|
|
8
|
-
* - Configurable header text and content
|
|
9
|
-
* - Consistent styling with the design system
|
|
5
|
+
* Figma: Embed Code Header (title row, code card, help row — no drag handle).
|
|
6
|
+
* Displays copyable content with icon or text copy control, loading/error card states, optional help link row.
|
|
10
7
|
*
|
|
11
8
|
* Usage:
|
|
12
9
|
* ```svelte
|
|
13
10
|
* <CopyableHeader
|
|
14
11
|
* headerText="Embed code"
|
|
15
12
|
* content="<widgetic id='123' width='350' height='50'></widgetic>"
|
|
16
|
-
*
|
|
13
|
+
* helpPrompt="Not sure how embedding works?"
|
|
14
|
+
* helpText="Learn more"
|
|
17
15
|
* helpUrl="/embed"
|
|
18
16
|
* />
|
|
19
17
|
* ```
|
|
20
18
|
*
|
|
21
|
-
*
|
|
22
|
-
* `copyFailedTitle`, `copyFailedDescription`), so a page in another language can give them. A page that shows its own pop-up
|
|
23
|
-
* on the `copy` and `copyError` events passes `showInternalToast={false}` instead.
|
|
19
|
+
* Toast copy strings are props (`copiedTitle`, `copiedDescription`, …). Pass `showInternalToast={false}` when the host shows toasts on `copy` / `copyError`.
|
|
24
20
|
*/
|
|
25
21
|
-->
|
|
26
22
|
<script lang="ts">
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
let
|
|
49
|
-
export
|
|
50
|
-
export let
|
|
51
|
-
export let
|
|
52
|
-
export let
|
|
53
|
-
export let
|
|
54
|
-
export let
|
|
55
|
-
export let
|
|
56
|
-
export let
|
|
57
|
-
export let
|
|
58
|
-
export let
|
|
59
|
-
|
|
60
|
-
export let
|
|
61
|
-
export let
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const range = document.createRange();
|
|
136
|
-
range.selectNodeContents(contentElement);
|
|
137
|
-
selection?.removeAllRanges();
|
|
138
|
-
selection?.addRange(range);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
await navigator.clipboard.writeText(content);
|
|
143
|
-
if (showInternalToast) {
|
|
144
|
-
showToast('success', copiedTitle, {
|
|
145
|
-
description: copiedDescription,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
dispatch('copy', { content });
|
|
149
|
-
} catch (err) {
|
|
150
|
-
if (showInternalToast) {
|
|
151
|
-
showToast('error', copyFailedTitle, {
|
|
152
|
-
description: copyFailedDescription,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
dispatch('copyError', { error: err });
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Toast helper function
|
|
160
|
-
let isToastVisible = false;
|
|
161
|
-
|
|
162
|
-
function showToast(type: 'success' | 'error', message: string, options = {}) {
|
|
163
|
-
if (isToastVisible) return;
|
|
164
|
-
|
|
165
|
-
isToastVisible = true;
|
|
166
|
-
toast[type](message, {
|
|
167
|
-
...options,
|
|
168
|
-
duration: 5000,
|
|
169
|
-
unstyled: true,
|
|
170
|
-
classes: {
|
|
171
|
-
toast: 'copyable-header-toast flex items-center gap-3',
|
|
172
|
-
title: 'copyable-header-toast-title',
|
|
173
|
-
description: 'copyable-header-toast-description',
|
|
174
|
-
closeButton: 'copyable-header-toast-close-button'
|
|
175
|
-
},
|
|
176
|
-
onAutoClose: () => {
|
|
177
|
-
isToastVisible = false;
|
|
178
|
-
},
|
|
179
|
-
onDismiss: () => {
|
|
180
|
-
isToastVisible = false;
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
}
|
|
23
|
+
import { createEventDispatcher, onDestroy } from 'svelte';
|
|
24
|
+
import { toast, Button, Tooltip, Portal, IconButton, Link, Skeleton } from './';
|
|
25
|
+
import { cn } from '../utils.js';
|
|
26
|
+
import { IconCopy, IconCheck, IconAlertTriangle } from '@tabler/icons-svelte';
|
|
27
|
+
import { sideAtStart, useTextDirection } from './textDirection.js';
|
|
28
|
+
|
|
29
|
+
const dispatch = createEventDispatcher();
|
|
30
|
+
const textDirection = useTextDirection();
|
|
31
|
+
type TriggerChildProps = { props: Record<string, unknown> & { class?: string } };
|
|
32
|
+
|
|
33
|
+
let className = '';
|
|
34
|
+
export { className as class };
|
|
35
|
+
export let style = '';
|
|
36
|
+
export let headerText = 'Copy content';
|
|
37
|
+
export let content = '';
|
|
38
|
+
export let helpText = 'Learn more';
|
|
39
|
+
export let helpUrl = '';
|
|
40
|
+
export let helpPrompt = '';
|
|
41
|
+
export let helpLinkAria = '';
|
|
42
|
+
export let showHelp = true;
|
|
43
|
+
export let monospaceContent = true;
|
|
44
|
+
export let showStandaloneCopyButton = false;
|
|
45
|
+
export let standaloneCopyButtonText = '';
|
|
46
|
+
export let copiedTitle = 'Copied to clipboard';
|
|
47
|
+
export let copiedDescription = 'Content copied successfully.';
|
|
48
|
+
export let copyFailedTitle = 'Copy failed';
|
|
49
|
+
export let copyFailedDescription = 'Please try manual selection';
|
|
50
|
+
export let showButtonText = true;
|
|
51
|
+
export let buttonClass = '';
|
|
52
|
+
export let showInternalToast = true;
|
|
53
|
+
export let headerTextClass = '';
|
|
54
|
+
export let headerBackgroundColor = '';
|
|
55
|
+
export let contentBorderColor = '';
|
|
56
|
+
export let loading = false;
|
|
57
|
+
export let errorTitle = '';
|
|
58
|
+
export let errorDetail = '';
|
|
59
|
+
|
|
60
|
+
let showCopyTooltip = false;
|
|
61
|
+
let tooltipDebounce = false;
|
|
62
|
+
let contentElement: HTMLDivElement | null = null;
|
|
63
|
+
let copied = false;
|
|
64
|
+
let copiedTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
65
|
+
let isToastVisible = false;
|
|
66
|
+
|
|
67
|
+
$: showHelpRow = showHelp && !!helpUrl && (!!helpPrompt || !!helpText);
|
|
68
|
+
|
|
69
|
+
onDestroy(() => {
|
|
70
|
+
if (copiedTimeout) clearTimeout(copiedTimeout);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
function setTooltipDebounce() {
|
|
74
|
+
tooltipDebounce = true;
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
tooltipDebounce = false;
|
|
77
|
+
}, 500);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function handleCopyButtonClick(e: MouseEvent) {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
e.stopPropagation();
|
|
83
|
+
showCopyTooltip = false;
|
|
84
|
+
setTooltipDebounce();
|
|
85
|
+
|
|
86
|
+
if (contentElement) {
|
|
87
|
+
const selection = window.getSelection();
|
|
88
|
+
const range = document.createRange();
|
|
89
|
+
range.selectNodeContents(contentElement);
|
|
90
|
+
selection?.removeAllRanges();
|
|
91
|
+
selection?.addRange(range);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
await navigator.clipboard.writeText(content);
|
|
96
|
+
copied = true;
|
|
97
|
+
if (copiedTimeout) clearTimeout(copiedTimeout);
|
|
98
|
+
copiedTimeout = setTimeout(() => {
|
|
99
|
+
copied = false;
|
|
100
|
+
}, 2000);
|
|
101
|
+
if (showInternalToast) {
|
|
102
|
+
showToast('success', copiedTitle, {
|
|
103
|
+
description: copiedDescription
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
dispatch('copy', { content });
|
|
107
|
+
} catch (err) {
|
|
108
|
+
if (showInternalToast) {
|
|
109
|
+
showToast('error', copyFailedTitle, {
|
|
110
|
+
description: copyFailedDescription
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
dispatch('copyError', { error: err });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function showToast(type: 'success' | 'error', message: string, options = {}) {
|
|
118
|
+
if (isToastVisible) return;
|
|
119
|
+
isToastVisible = true;
|
|
120
|
+
toast[type](message, {
|
|
121
|
+
...options,
|
|
122
|
+
duration: 5000,
|
|
123
|
+
onAutoClose: () => {
|
|
124
|
+
isToastVisible = false;
|
|
125
|
+
},
|
|
126
|
+
onDismiss: () => {
|
|
127
|
+
isToastVisible = false;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
184
131
|
</script>
|
|
185
132
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
max-height: 141px;
|
|
334
|
-
z-index: 101;
|
|
335
|
-
line-height: 1.5;
|
|
336
|
-
border: 1px solid {contentBorderColor || 'hsl(var(--grey2))'};
|
|
337
|
-
border-radius: var(--radius-small);
|
|
338
|
-
margin: 0 -2px -2px -2px;
|
|
339
|
-
width: calc(100% + 4px);
|
|
340
|
-
cursor: text;
|
|
341
|
-
white-space: pre-wrap;
|
|
342
|
-
word-break: break-all;
|
|
343
|
-
overflow-wrap: anywhere;
|
|
344
|
-
overflow-y: auto;
|
|
345
|
-
"
|
|
346
|
-
tabindex="0"
|
|
347
|
-
>
|
|
348
|
-
{content}
|
|
349
|
-
</div>
|
|
350
|
-
</div>
|
|
133
|
+
<div class={cn('copyable-header flex w-full flex-col gap-3', className)} {style}>
|
|
134
|
+
<!-- Title row: section label + copy control (Figma 32px). -->
|
|
135
|
+
<div class={cn('flex h-8 items-center justify-between gap-3', headerBackgroundColor)}>
|
|
136
|
+
<div class={cn('text-heading-section text-foreground min-w-0 truncate', headerTextClass)}>
|
|
137
|
+
{headerText}
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
{#if showStandaloneCopyButton}
|
|
141
|
+
<Tooltip.Provider>
|
|
142
|
+
<Tooltip.Root open={showCopyTooltip}>
|
|
143
|
+
<Tooltip.Trigger>
|
|
144
|
+
{#snippet child({ props }: TriggerChildProps)}
|
|
145
|
+
<Button
|
|
146
|
+
{...props}
|
|
147
|
+
variant="default"
|
|
148
|
+
class={cn(buttonClass, props.class)}
|
|
149
|
+
onclick={handleCopyButtonClick}
|
|
150
|
+
onmouseenter={() => {
|
|
151
|
+
if (!tooltipDebounce) showCopyTooltip = true;
|
|
152
|
+
}}
|
|
153
|
+
onmouseleave={() => {
|
|
154
|
+
showCopyTooltip = false;
|
|
155
|
+
}}
|
|
156
|
+
onmousedown={() => {
|
|
157
|
+
showCopyTooltip = false;
|
|
158
|
+
setTooltipDebounce();
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
{#if copied}
|
|
162
|
+
<IconCheck class="size-4 stroke-[1.333]" />
|
|
163
|
+
{:else}
|
|
164
|
+
<IconCopy class="size-4 stroke-[1.333]" />
|
|
165
|
+
{/if}
|
|
166
|
+
{#if showButtonText}
|
|
167
|
+
<span class="ms-2">{standaloneCopyButtonText}</span>
|
|
168
|
+
{/if}
|
|
169
|
+
</Button>
|
|
170
|
+
{/snippet}
|
|
171
|
+
</Tooltip.Trigger>
|
|
172
|
+
{#if showCopyTooltip}
|
|
173
|
+
<Portal target="editor-tooltips">
|
|
174
|
+
<Tooltip.Content side={sideAtStart($textDirection)} sideOffset={5}>
|
|
175
|
+
<p class="text-caption">{standaloneCopyButtonText}</p>
|
|
176
|
+
</Tooltip.Content>
|
|
177
|
+
</Portal>
|
|
178
|
+
{/if}
|
|
179
|
+
</Tooltip.Root>
|
|
180
|
+
</Tooltip.Provider>
|
|
181
|
+
{:else}
|
|
182
|
+
<Tooltip.Provider>
|
|
183
|
+
<Tooltip.Root open={showCopyTooltip}>
|
|
184
|
+
<Tooltip.Trigger>
|
|
185
|
+
{#snippet child({ props }: TriggerChildProps)}
|
|
186
|
+
<IconButton
|
|
187
|
+
{...props}
|
|
188
|
+
variant={copied ? 'accent' : 'ghost'}
|
|
189
|
+
label={standaloneCopyButtonText || 'Copy'}
|
|
190
|
+
class={cn(headerBackgroundColor, props.class)}
|
|
191
|
+
onclick={handleCopyButtonClick}
|
|
192
|
+
onmouseenter={() => {
|
|
193
|
+
if (!tooltipDebounce) showCopyTooltip = true;
|
|
194
|
+
}}
|
|
195
|
+
onmouseleave={() => {
|
|
196
|
+
showCopyTooltip = false;
|
|
197
|
+
}}
|
|
198
|
+
onmousedown={() => {
|
|
199
|
+
showCopyTooltip = false;
|
|
200
|
+
setTooltipDebounce();
|
|
201
|
+
}}
|
|
202
|
+
>
|
|
203
|
+
{#if copied}
|
|
204
|
+
<IconCheck class="size-4 stroke-[1.333]" />
|
|
205
|
+
{:else}
|
|
206
|
+
<IconCopy class="text-muted-foreground size-4 stroke-[1.333]" />
|
|
207
|
+
{/if}
|
|
208
|
+
</IconButton>
|
|
209
|
+
{/snippet}
|
|
210
|
+
</Tooltip.Trigger>
|
|
211
|
+
{#if showCopyTooltip && standaloneCopyButtonText}
|
|
212
|
+
<Portal target="editor-tooltips">
|
|
213
|
+
<Tooltip.Content side={sideAtStart($textDirection)} sideOffset={5}>
|
|
214
|
+
<p class="text-caption">{standaloneCopyButtonText}</p>
|
|
215
|
+
</Tooltip.Content>
|
|
216
|
+
</Portal>
|
|
217
|
+
{/if}
|
|
218
|
+
</Tooltip.Root>
|
|
219
|
+
</Tooltip.Provider>
|
|
220
|
+
{/if}
|
|
221
|
+
</div>
|
|
222
|
+
|
|
223
|
+
<!-- Code card: accent surface; loading skeleton, error, or selectable snippet. -->
|
|
224
|
+
<div
|
|
225
|
+
class={cn(
|
|
226
|
+
'bg-accent flex flex-col gap-2 rounded-xl p-3',
|
|
227
|
+
contentBorderColor && 'border-border border'
|
|
228
|
+
)}
|
|
229
|
+
style={contentBorderColor && !contentBorderColor.startsWith('border')
|
|
230
|
+
? `border-color: ${contentBorderColor};`
|
|
231
|
+
: undefined}
|
|
232
|
+
>
|
|
233
|
+
{#if loading}
|
|
234
|
+
<div class="flex flex-col gap-2" aria-busy="true">
|
|
235
|
+
<Skeleton class="bg-border h-4 w-full" />
|
|
236
|
+
<Skeleton class="bg-border h-4 w-full" />
|
|
237
|
+
<Skeleton class="bg-border h-4 w-40" />
|
|
238
|
+
</div>
|
|
239
|
+
{:else if errorTitle}
|
|
240
|
+
<div class="flex flex-col items-center gap-2 py-2 text-center">
|
|
241
|
+
<div class="bg-destructive/10 flex size-10 items-center justify-center rounded-lg">
|
|
242
|
+
<IconAlertTriangle class="text-destructive size-4 stroke-[1.333]" aria-hidden="true" />
|
|
243
|
+
</div>
|
|
244
|
+
<p class="text-body-medium text-foreground">{errorTitle}</p>
|
|
245
|
+
{#if errorDetail}
|
|
246
|
+
<p class="text-caption text-muted-foreground font-mono">{errorDetail}</p>
|
|
247
|
+
{/if}
|
|
248
|
+
</div>
|
|
249
|
+
{:else}
|
|
250
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
251
|
+
<div
|
|
252
|
+
bind:this={contentElement}
|
|
253
|
+
class={cn(
|
|
254
|
+
'text-code text-foreground max-h-36 w-full cursor-text overflow-y-auto text-start break-all whitespace-pre-wrap',
|
|
255
|
+
monospaceContent ? '' : 'text-body'
|
|
256
|
+
)}
|
|
257
|
+
tabindex="0"
|
|
258
|
+
>
|
|
259
|
+
{content}
|
|
260
|
+
</div>
|
|
261
|
+
{/if}
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
{#if showHelpRow}
|
|
265
|
+
<div class="flex flex-wrap items-center gap-1">
|
|
266
|
+
{#if helpPrompt}
|
|
267
|
+
<span class="text-caption text-muted-foreground">{helpPrompt}</span>
|
|
268
|
+
{/if}
|
|
269
|
+
<Link
|
|
270
|
+
href={helpUrl}
|
|
271
|
+
label={helpText}
|
|
272
|
+
size="small"
|
|
273
|
+
class="underline"
|
|
274
|
+
aria-label={helpLinkAria || helpText}
|
|
275
|
+
target="_blank"
|
|
276
|
+
rel="noopener noreferrer"
|
|
277
|
+
/>
|
|
278
|
+
</div>
|
|
279
|
+
{/if}
|
|
351
280
|
</div>
|
|
352
|
-
|
|
353
|
-
<style>
|
|
354
|
-
/* Style for the content area */
|
|
355
|
-
.copyable-content-area {
|
|
356
|
-
-webkit-user-select: text !important;
|
|
357
|
-
-moz-user-select: text !important;
|
|
358
|
-
-ms-user-select: text !important;
|
|
359
|
-
user-select: text !important;
|
|
360
|
-
overflow-y: auto !important;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
.copyable-content-area::selection {
|
|
364
|
-
background-color: rgba(59, 130, 246, 0.2) !important;
|
|
365
|
-
color: inherit !important;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
.copyable-content-area::-moz-selection {
|
|
369
|
-
background-color: rgba(59, 130, 246, 0.2) !important;
|
|
370
|
-
color: inherit !important;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/* Help icon hover styles */
|
|
374
|
-
:global(.copyable-header-container .w-6.h-6) {
|
|
375
|
-
display: flex !important;
|
|
376
|
-
align-items: center !important;
|
|
377
|
-
justify-content: center !important;
|
|
378
|
-
border-radius: 50% !important;
|
|
379
|
-
transition: background-color 0.2s ease !important;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/* Removed the hover background effect for the help icon */
|
|
383
|
-
/* :global(.copyable-header-container .w-6.h-6:hover) {
|
|
384
|
-
background-color: rgba(255, 255, 255, 0.5) !important;
|
|
385
|
-
} */
|
|
386
|
-
|
|
387
|
-
/* Button Press Effect */
|
|
388
|
-
:global(.copyable-header button) {
|
|
389
|
-
transition: transform 0.15s ease, background-color 0.1s ease;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/* Add hover styles for the standalone copy button */
|
|
393
|
-
:global(.copyable-header-container button[variant="default"]:hover) {
|
|
394
|
-
background-color: white !important;
|
|
395
|
-
color: hsl(var(--grey7)) !important;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/* Prevent hover background change for buttons with custom header background */
|
|
399
|
-
:global(.copyable-header-container button[class*="bg-"]:hover) {
|
|
400
|
-
background-color: inherit !important;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/* Add active scale effect for all buttons */
|
|
404
|
-
:global(.copyable-header button:active) {
|
|
405
|
-
transform: scale(0.95);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/** TOASTER STYLES **/
|
|
409
|
-
/* Toaster Positioning */
|
|
410
|
-
:global(.copyable-header-toast) {
|
|
411
|
-
position: fixed !important;
|
|
412
|
-
bottom: 20px !important;
|
|
413
|
-
inset-inline-end: 20px !important;
|
|
414
|
-
top: auto !important;
|
|
415
|
-
display: flex !important;
|
|
416
|
-
align-items: center !important;
|
|
417
|
-
gap: 12px !important;
|
|
418
|
-
padding: 16px 24px !important;
|
|
419
|
-
background: white !important;
|
|
420
|
-
border-radius: var(--radius-small) !important;
|
|
421
|
-
box-shadow: 0px 0px 15px 3px rgba(0, 0, 0, 0.1) !important;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/* Icon container */
|
|
425
|
-
:global(.copyable-header-toast [data-icon]) {
|
|
426
|
-
order: -1 !important;
|
|
427
|
-
display: flex !important;
|
|
428
|
-
align-items: center !important;
|
|
429
|
-
justify-content: center !important;
|
|
430
|
-
margin: 0 !important;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/* Text container */
|
|
434
|
-
:global(.copyable-header-toast [data-content]) {
|
|
435
|
-
display: flex !important;
|
|
436
|
-
flex-direction: column !important;
|
|
437
|
-
gap: 4px !important;
|
|
438
|
-
margin: 0 !important;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/* Toaster title */
|
|
442
|
-
.copyable-header-toast-title {
|
|
443
|
-
font-size: var(--h6) !important;
|
|
444
|
-
color: hsl(var(--forest)) !important;
|
|
445
|
-
font-weight: 600 !important;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
/* Toaster description */
|
|
449
|
-
.copyable-header-toast-description {
|
|
450
|
-
font-size: var(--caption) !important;
|
|
451
|
-
color: hsl(var(--grey3)) !important;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
/* Toaster close button */
|
|
455
|
-
:global(.copyable-header-toast-close-button) {
|
|
456
|
-
background: hsl(var(--grey7)) !important;
|
|
457
|
-
border: 1px solid hsl(var(--grey5)) !important;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
:global(.copyable-header-toast-close-button:hover) {
|
|
461
|
-
background: hsl(var(--dark)) !important;
|
|
462
|
-
border: 1px solid hsl(var(--grey5)) !important;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
:global(.copyable-header-toast-close-button svg) {
|
|
466
|
-
color: white !important;
|
|
467
|
-
}
|
|
468
|
-
</style>
|