@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.
Files changed (246) hide show
  1. package/README.md +2 -0
  2. package/dist/components/CopyableHeader.svelte +260 -448
  3. package/dist/components/CopyableHeader.svelte.d.ts +8 -5
  4. package/dist/components/EmptyState.svelte +100 -128
  5. package/dist/components/EmptyState.svelte.d.ts +16 -19
  6. package/dist/components/GenerateLoader.svelte +17 -10
  7. package/dist/components/PasswordInput.svelte +41 -44
  8. package/dist/components/PasswordInput.svelte.d.ts +2 -0
  9. package/dist/components/ThumbHashImage.svelte +117 -119
  10. package/dist/components/WScrollArea.svelte +47 -41
  11. package/dist/components/chat/ActivityRow.svelte +115 -0
  12. package/dist/components/chat/ActivityRow.svelte.d.ts +18 -0
  13. package/dist/components/chat/ChatHeader.svelte +114 -0
  14. package/dist/components/chat/ChatHeader.svelte.d.ts +26 -0
  15. package/dist/components/chat/Composer.svelte +172 -0
  16. package/dist/components/chat/Composer.svelte.d.ts +27 -0
  17. package/dist/components/chat/Message.svelte +158 -0
  18. package/dist/components/chat/Message.svelte.d.ts +28 -0
  19. package/dist/components/chat/OptionRow.svelte +59 -0
  20. package/dist/components/chat/OptionRow.svelte.d.ts +14 -0
  21. package/dist/components/chat/PlanCard.svelte +220 -0
  22. package/dist/components/chat/PlanCard.svelte.d.ts +34 -0
  23. package/dist/components/chat/QuestionCard.svelte +265 -0
  24. package/dist/components/chat/QuestionCard.svelte.d.ts +38 -0
  25. package/dist/components/chat/ScrollToBottom.svelte +51 -0
  26. package/dist/components/chat/ScrollToBottom.svelte.d.ts +11 -0
  27. package/dist/components/chat/SuggestionCard.svelte +79 -0
  28. package/dist/components/chat/SuggestionCard.svelte.d.ts +20 -0
  29. package/dist/components/chat/TaskRow.svelte +59 -0
  30. package/dist/components/chat/TaskRow.svelte.d.ts +11 -0
  31. package/dist/components/chat/composerLogic.d.ts +16 -0
  32. package/dist/components/chat/composerLogic.js +29 -0
  33. package/dist/components/chat/index.d.ts +16 -0
  34. package/dist/components/chat/index.js +16 -0
  35. package/dist/components/chat/questionCardLogic.d.ts +11 -0
  36. package/dist/components/chat/questionCardLogic.js +39 -0
  37. package/dist/components/index.d.ts +10 -1
  38. package/dist/components/index.js +10 -0
  39. package/dist/components/modals/ActionModal.svelte +186 -180
  40. package/dist/components/modals/BaseModal.svelte +404 -395
  41. package/dist/components/modals/BaseModal.svelte.d.ts +3 -0
  42. package/dist/components/modals/NewItemDialog.svelte +200 -243
  43. package/dist/components/modals/Portal.svelte +107 -105
  44. package/dist/components/modals/README.md +16 -2
  45. package/dist/components/modals/RenameDialog.svelte +234 -292
  46. package/dist/components/navigation/Breadcrumbs.svelte +415 -377
  47. package/dist/components/navigation/Breadcrumbs.svelte.d.ts +3 -2
  48. package/dist/components/navigation/types.d.ts +2 -0
  49. package/dist/components/pdf/PDFViewer.svelte +54 -1
  50. package/dist/components/search-input/SearchInput.svelte +51 -104
  51. package/dist/components/search-input/SearchInput.svelte.d.ts +9 -27
  52. package/dist/components/shad-editor/editor.css +1 -1
  53. package/dist/components/shad-editor/i18n/messages.d.ts +1 -1
  54. package/dist/components/shad-editor/i18n/messages.js +1 -1
  55. package/dist/components/shell/AppShell.svelte +52 -0
  56. package/dist/components/shell/AppShell.svelte.d.ts +13 -0
  57. package/dist/components/shell/Banner.svelte +90 -0
  58. package/dist/components/shell/Banner.svelte.d.ts +61 -0
  59. package/dist/components/shell/ErrorState.svelte +60 -0
  60. package/dist/components/shell/ErrorState.svelte.d.ts +13 -0
  61. package/dist/components/shell/Link.svelte +63 -0
  62. package/dist/components/shell/Link.svelte.d.ts +53 -0
  63. package/dist/components/shell/NavDrawer.svelte +117 -0
  64. package/dist/components/shell/NavDrawer.svelte.d.ts +10 -0
  65. package/dist/components/shell/NavRow.svelte +128 -0
  66. package/dist/components/shell/NavRow.svelte.d.ts +65 -0
  67. package/dist/components/shell/NavSectionLabel.svelte +27 -0
  68. package/dist/components/shell/NavSectionLabel.svelte.d.ts +9 -0
  69. package/dist/components/shell/NotificationRow.svelte +76 -0
  70. package/dist/components/shell/NotificationRow.svelte.d.ts +16 -0
  71. package/dist/components/shell/PageHeader.svelte +42 -0
  72. package/dist/components/shell/PageHeader.svelte.d.ts +12 -0
  73. package/dist/components/shell/ProfileRow.svelte +95 -0
  74. package/dist/components/shell/ProfileRow.svelte.d.ts +54 -0
  75. package/dist/components/shell/SettingsDialog.svelte +118 -0
  76. package/dist/components/shell/SettingsDialog.svelte.d.ts +19 -0
  77. package/dist/components/shell/SettingsNav.svelte +46 -0
  78. package/dist/components/shell/SettingsNav.svelte.d.ts +11 -0
  79. package/dist/components/shell/Sidebar.svelte +82 -0
  80. package/dist/components/shell/Sidebar.svelte.d.ts +25 -0
  81. package/dist/components/shell/Stat.svelte +63 -0
  82. package/dist/components/shell/Stat.svelte.d.ts +58 -0
  83. package/dist/components/shell/TopBar.svelte +37 -0
  84. package/dist/components/shell/TopBar.svelte.d.ts +11 -0
  85. package/dist/components/shell/WidgetRow.svelte +126 -0
  86. package/dist/components/shell/WidgetRow.svelte.d.ts +78 -0
  87. package/dist/components/shell/error-state-messages.d.ts +7 -0
  88. package/dist/components/shell/error-state-messages.js +9 -0
  89. package/dist/components/shell/index.d.ts +22 -0
  90. package/dist/components/shell/index.js +25 -0
  91. package/dist/components/shell/link-external.d.ts +2 -0
  92. package/dist/components/shell/link-external.js +7 -0
  93. package/dist/components/shell/messages.d.ts +7 -0
  94. package/dist/components/shell/messages.js +5 -0
  95. package/dist/components/shell/settings-nav-types.d.ts +12 -0
  96. package/dist/components/shell/settings-nav-types.js +3 -0
  97. package/dist/components/shell/shell-utils.d.ts +7 -0
  98. package/dist/components/shell/shell-utils.js +27 -0
  99. package/dist/components/shell/stat-tone.d.ts +3 -0
  100. package/dist/components/shell/stat-tone.js +11 -0
  101. package/dist/components/toast/ToasterModal.svelte +102 -168
  102. package/dist/components/toast/ToasterModal.svelte.d.ts +2 -12
  103. package/dist/components/ui/accordion/accordion-content.svelte +3 -2
  104. package/dist/components/ui/accordion/accordion-item.svelte +10 -1
  105. package/dist/components/ui/accordion/accordion-trigger.svelte +4 -3
  106. package/dist/components/ui/alert/alert-description.svelte +5 -1
  107. package/dist/components/ui/alert/alert-title.svelte +2 -1
  108. package/dist/components/ui/alert/index.d.ts +13 -11
  109. package/dist/components/ui/alert/index.js +4 -4
  110. package/dist/components/ui/avatar/avatar-utils.d.ts +2 -0
  111. package/dist/components/ui/avatar/avatar-utils.js +9 -0
  112. package/dist/components/ui/avatar/avatar.svelte +63 -0
  113. package/dist/components/ui/avatar/avatar.svelte.d.ts +80 -0
  114. package/dist/components/ui/avatar/index.d.ts +4 -0
  115. package/dist/components/ui/avatar/index.js +4 -0
  116. package/dist/components/ui/badge/badge.svelte +22 -10
  117. package/dist/components/ui/badge/badge.svelte.d.ts +14 -15
  118. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
  119. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +1 -1
  120. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +1 -1
  121. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +2 -2
  122. package/dist/components/ui/button/button-padding.d.ts +9 -0
  123. package/dist/components/ui/button/button-padding.js +15 -0
  124. package/dist/components/ui/button/button.svelte +81 -31
  125. package/dist/components/ui/button/button.svelte.d.ts +48 -29
  126. package/dist/components/ui/calendar/calendar-cell.svelte +1 -1
  127. package/dist/components/ui/calendar/calendar-head-cell.svelte +1 -1
  128. package/dist/components/ui/calendar/calendar-next-button.svelte +2 -2
  129. package/dist/components/ui/calendar/calendar-prev-button.svelte +2 -2
  130. package/dist/components/ui/card/card-description.svelte +1 -1
  131. package/dist/components/ui/card/card-title.svelte +1 -1
  132. package/dist/components/ui/card/card.svelte +1 -1
  133. package/dist/components/ui/checkbox/checkbox.svelte +9 -5
  134. package/dist/components/ui/chip/chip.svelte +48 -0
  135. package/dist/components/ui/chip/chip.svelte.d.ts +13 -0
  136. package/dist/components/ui/chip/index.d.ts +2 -0
  137. package/dist/components/ui/chip/index.js +2 -0
  138. package/dist/components/ui/command/command-dialog.svelte +1 -1
  139. package/dist/components/ui/command/command-input.svelte +4 -4
  140. package/dist/components/ui/command/command-item.svelte +1 -1
  141. package/dist/components/ui/command/command.svelte +1 -1
  142. package/dist/components/ui/dialog/dialog-content.svelte +4 -4
  143. package/dist/components/ui/dialog/dialog-description.svelte +1 -1
  144. package/dist/components/ui/dialog/dialog-overlay.svelte +1 -1
  145. package/dist/components/ui/dialog/dialog-title.svelte +1 -1
  146. package/dist/components/ui/drawer/drawer-content.svelte +1 -1
  147. package/dist/components/ui/drawer/drawer-overlay.svelte +1 -1
  148. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +5 -5
  149. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
  150. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
  151. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +20 -2
  152. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +4 -0
  153. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +5 -1
  154. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +3 -3
  155. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -1
  156. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  157. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +3 -3
  158. package/dist/components/ui/field/field-ids.d.ts +7 -0
  159. package/dist/components/ui/field/field-ids.js +15 -0
  160. package/dist/components/ui/field/field.svelte +62 -0
  161. package/dist/components/ui/field/field.svelte.d.ts +21 -0
  162. package/dist/components/ui/field/index.d.ts +3 -0
  163. package/dist/components/ui/field/index.js +3 -0
  164. package/dist/components/ui/hover-card/hover-card-content.svelte +1 -1
  165. package/dist/components/ui/icon-button/icon-button.svelte +72 -0
  166. package/dist/components/ui/icon-button/icon-button.svelte.d.ts +90 -0
  167. package/dist/components/ui/icon-button/index.d.ts +2 -0
  168. package/dist/components/ui/icon-button/index.js +4 -0
  169. package/dist/components/ui/input/index.d.ts +1 -0
  170. package/dist/components/ui/input/input.svelte +11 -4
  171. package/dist/components/ui/input/input.svelte.d.ts +4 -1
  172. package/dist/components/ui/input-otp/input-otp-separator.svelte +2 -2
  173. package/dist/components/ui/input-otp/input-otp-slot.svelte +5 -4
  174. package/dist/components/ui/input-otp/input-otp-slot.svelte.d.ts +1 -1
  175. package/dist/components/ui/input-otp/input-otp.svelte +1 -1
  176. package/dist/components/ui/label/label.svelte +3 -2
  177. package/dist/components/ui/popover/popover-content.svelte +1 -1
  178. package/dist/components/ui/progress/progress.svelte +19 -5
  179. package/dist/components/ui/progress/progress.svelte.d.ts +4 -2
  180. package/dist/components/ui/radio-group/radio-group-item.svelte +4 -4
  181. package/dist/components/ui/range-calendar/range-calendar-head-cell.svelte +1 -1
  182. package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +2 -2
  183. package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +2 -2
  184. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +4 -1
  185. package/dist/components/ui/scroll-area/scroll-area.svelte +1 -1
  186. package/dist/components/ui/select/select-content.svelte +1 -3
  187. package/dist/components/ui/select/select-item.svelte +5 -4
  188. package/dist/components/ui/select/select-scroll-down-button.svelte +2 -2
  189. package/dist/components/ui/select/select-scroll-up-button.svelte +2 -2
  190. package/dist/components/ui/select/select-trigger.svelte +4 -3
  191. package/dist/components/ui/skeleton/index.d.ts +2 -0
  192. package/dist/components/ui/skeleton/index.js +2 -0
  193. package/dist/components/ui/skeleton/skeleton.svelte +24 -0
  194. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +8 -0
  195. package/dist/components/ui/slider/slider.svelte +5 -10
  196. package/dist/components/ui/sonner/sonner.svelte +19 -13
  197. package/dist/components/ui/stepper-button/index.d.ts +3 -0
  198. package/dist/components/ui/stepper-button/index.js +2 -0
  199. package/dist/components/ui/stepper-button/stepper-button.svelte +37 -0
  200. package/dist/components/ui/stepper-button/stepper-button.svelte.d.ts +9 -0
  201. package/dist/components/ui/switch/switch.svelte +8 -3
  202. package/dist/components/ui/table/table-cell.svelte +1 -1
  203. package/dist/components/ui/table/table-head.svelte +1 -1
  204. package/dist/components/ui/table/table-row.svelte +1 -1
  205. package/dist/components/ui/tabs/tabs-list.svelte +1 -1
  206. package/dist/components/ui/tabs/tabs-trigger.svelte +1 -1
  207. package/dist/components/ui/tag/index.d.ts +2 -0
  208. package/dist/components/ui/tag/index.js +2 -0
  209. package/dist/components/ui/tag/tag.svelte +42 -0
  210. package/dist/components/ui/tag/tag.svelte.d.ts +11 -0
  211. package/dist/components/ui/textarea/textarea.svelte +4 -3
  212. package/dist/components/ui/textarea/textarea.svelte.d.ts +2 -2
  213. package/dist/components/ui/toggle/toggle.svelte +9 -9
  214. package/dist/components/ui/toggle/toggle.svelte.d.ts +14 -21
  215. package/dist/components/ui/tooltip/tooltip-content.svelte +1 -1
  216. package/dist/fonts/Inter/Inter-Black.woff2 +0 -0
  217. package/dist/fonts/Inter/Inter-BlackItalic.woff2 +0 -0
  218. package/dist/fonts/Inter/Inter-Bold.woff2 +0 -0
  219. package/dist/fonts/Inter/Inter-BoldItalic.woff2 +0 -0
  220. package/dist/fonts/Inter/Inter-ExtraBold.woff2 +0 -0
  221. package/dist/fonts/Inter/Inter-ExtraBoldItalic.woff2 +0 -0
  222. package/dist/fonts/Inter/Inter-ExtraLight-BETA.woff2 +0 -0
  223. package/dist/fonts/Inter/Inter-ExtraLightItalic-BETA.woff2 +0 -0
  224. package/dist/fonts/Inter/Inter-Italic.woff2 +0 -0
  225. package/dist/fonts/Inter/Inter-Light-BETA.woff2 +0 -0
  226. package/dist/fonts/Inter/Inter-LightItalic-BETA.woff2 +0 -0
  227. package/dist/fonts/Inter/Inter-Medium.woff2 +0 -0
  228. package/dist/fonts/Inter/Inter-MediumItalic.woff2 +0 -0
  229. package/dist/fonts/Inter/Inter-Regular.woff2 +0 -0
  230. package/dist/fonts/Inter/Inter-SemiBold.woff2 +0 -0
  231. package/dist/fonts/Inter/Inter-SemiBoldItalic.woff2 +0 -0
  232. package/dist/fonts/Inter/Inter-Thin-BETA.woff2 +0 -0
  233. package/dist/fonts/Inter/Inter-ThinItalic-BETA.woff2 +0 -0
  234. package/dist/fonts/Inter/Inter-italic.var.woff2 +0 -0
  235. package/dist/fonts/Inter/Inter-upright.var.woff2 +0 -0
  236. package/dist/fonts/Inter/Inter.var.woff2 +0 -0
  237. package/dist/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 +0 -0
  238. package/dist/i18n/audit/designSystemWords.d.ts +1 -1
  239. package/dist/i18n/audit/designSystemWords.js +1 -1
  240. package/dist/styles/fonts.css +18 -14
  241. package/dist/styles/global.css +7 -19
  242. package/dist/styles/tokens.css +332 -0
  243. package/dist/utils.d.ts +27 -0
  244. package/dist/utils.js +33 -2
  245. package/package.json +2 -1
  246. package/tailwind.config.ts +7 -47
@@ -1,297 +1,239 @@
1
1
  <script lang="ts">
2
- // Svelte imports
3
- import { createEventDispatcher, tick } from 'svelte';
4
-
5
- // Local imports
6
- import { Button } from '../ui/button';
7
- // import { toast } from '../ui/sonner';
8
- import { showToast } from '../toast';
9
- import BaseModal from './BaseModal.svelte';
10
- // Words of the dialog and the helper that puts values into them
11
- import type { RenameDialogMessages } from './messages';
12
- import { fillMessage } from '../../utils/fillMessage';
13
-
14
- // Props
15
- let className = '';
16
- export { className as class };
17
- export let style: string = '';
18
- //
19
- export let isOpen = false;
20
- export let itemName = '';
21
- export let itemType = 'item'; // 'item', 'folder', 'file', 'key', etc.
22
- export let itemId = '';
23
- export let title = '';
24
- export let placeholder = '';
25
- export let confirmLabel = 'Rename';
26
- export let cancelLabel = 'Cancel';
27
- // The words a screen reader says for the close button (see BaseModal)
28
- export let closeLabel = 'Close modal';
29
- // The words of the errors and toasts; a key that is left out keeps its English text (see ./messages)
30
- export let messages: Partial<RenameDialogMessages> = {};
31
- export let width = '410px';
32
- export let height = '168px';
33
- export let target: string = 'rename-dialog'; // target for Portal
34
- export let maxLength = 50; // Reduced for better UX
35
- export let shouldUseCustomRenameFunction = false; // If true, parent component handles the rename
36
-
37
- // For backwards compatibility with specific implementations
38
- export let modalType: string = 'rename';
39
- export let modalData: any = null;
40
-
41
- let inputValue = '';
42
- let inputElement: HTMLInputElement;
43
- let hasAttemptedSubmit = false; // Track if user has attempted to submit
44
- let isValid = false; // Track if input is valid
45
-
46
- // Initialize modalData with our current props if not provided externally
47
- $: if (modalData === null) {
48
- modalData = {
49
- itemName,
50
- itemType,
51
- itemId,
52
- title,
53
- placeholder,
54
- confirmLabel,
55
- cancelLabel
56
- };
57
- }
58
-
59
- // Update validation state whenever inputValue changes
60
- $: {
61
- isValid = inputValue.trim().length > 0 &&
62
- inputValue.length <= maxLength &&
63
- inputValue !== itemName;
64
- }
65
-
66
- // Computed placeholder based on itemType
67
- $: computedPlaceholder = placeholder || `${itemType} name...`;
68
-
69
- // The words of the errors and toasts: the page's own, or English
70
- $: text = {
71
- invalidTitle: messages.invalidTitle ?? 'Invalid name',
72
- enterName: messages.enterName ?? 'Please enter a name',
73
- enterDifferentName: messages.enterDifferentName ?? 'Please enter a different name',
74
- enterValidName: messages.enterValidName ?? 'Please enter a valid name',
75
- tooShort: messages.tooShort ?? 'Name must be at least 1 character long',
76
- tooLong: fillMessage(messages.tooLong ?? 'Name must be {max} characters or less', { max: maxLength }),
77
- renamed: messages.renamed ?? 'Successfully renamed to {name}',
78
- failed: messages.failed ?? 'Failed to rename item'
79
- };
80
-
81
- // Function to focus and select the input text
82
- async function focusAndSelectInput() {
83
- // Wait for the DOM to update
84
- await tick();
85
-
86
- if (!inputElement) return;
87
-
88
- // Focus the input
89
- inputElement.focus();
90
-
91
- // Select all text
92
- inputElement.setSelectionRange(0, inputElement.value.length);
93
- }
94
-
95
- // Simple function to handle input initialization
96
- function handleInput(event: Event) {
97
- const input = event.target as HTMLInputElement;
98
- inputValue = input.value.slice(0, maxLength);
99
- }
100
-
101
- // When the modal opens, set the input value and focus the input
102
- $: if (isOpen) {
103
- inputValue = itemName;
104
- hasAttemptedSubmit = false; // Reset submission state
105
- // Schedule focus after a short delay
106
- setTimeout(focusAndSelectInput, 50);
107
- }
108
-
109
- const dispatch = createEventDispatcher();
110
-
111
- async function handleRename() {
112
- hasAttemptedSubmit = true;
113
-
114
- try {
115
- // Validate input
116
- if (!inputValue.trim() || inputValue.length < 1) {
117
- showToast('error', text.invalidTitle, { description: text.tooShort });
118
- return;
119
- }
120
-
121
- if (inputValue.length > maxLength) {
122
- showToast('error', text.invalidTitle, { description: text.tooLong });
123
- return;
124
- }
125
-
126
- if (inputValue === itemName) {
127
- showToast('error', text.invalidTitle, { description: text.enterDifferentName });
128
- return;
129
- }
130
-
131
- // console.log('Attempting rename:', {
132
- // from: itemName,
133
- // to: inputValue,
134
- // itemId
135
- // });
136
-
137
- // If parent component handles rename, dispatch event
138
- if (shouldUseCustomRenameFunction) {
139
- dispatch('rename', { itemId, newName: inputValue, oldName: itemName });
140
- isOpen = false;
141
- } else {
142
- // For file browser compatibility - in a real implementation, this would be replaced
143
- // with a more generic approach
144
- try {
145
- // Simulate success
146
- showToast('success', fillMessage(text.renamed, { name: inputValue }));
147
- dispatch('rename', { itemId, newName: inputValue, oldName: itemName });
148
- isOpen = false;
149
- } catch (error) {
150
- console.error('Error during rename:', error);
151
- showToast('error', text.failed);
152
- }
153
- }
154
- } catch (error) {
155
- console.error('Error during rename:', error);
156
- showToast('error', text.failed);
157
- }
158
- }
159
-
160
- function handleClose() {
161
- isOpen = false;
162
- hasAttemptedSubmit = false;
163
- dispatch('cancel');
164
- }
165
-
166
- // Support for restoring modal state
167
- function handleRestore(event: CustomEvent) {
168
- if (event.detail) {
169
- itemName = event.detail.itemName || '';
170
- itemType = event.detail.itemType || 'item';
171
- itemId = event.detail.itemId || '';
172
- if (event.detail.title) title = event.detail.title;
173
- if (event.detail.placeholder) placeholder = event.detail.placeholder;
174
- if (event.detail.confirmLabel) confirmLabel = event.detail.confirmLabel;
175
- if (event.detail.cancelLabel) cancelLabel = event.detail.cancelLabel;
176
-
177
- // Reset input value on restore
178
- inputValue = itemName;
179
-
180
- // Focus and select text when modal is restored
181
- setTimeout(focusAndSelectInput, 50);
182
- }
183
- }
2
+ // Svelte imports
3
+ import { createEventDispatcher, tick } from 'svelte';
4
+
5
+ // Local imports
6
+ import { Button } from '../ui/button';
7
+ import { Input } from '../ui/input';
8
+ import { showToast } from '../toast';
9
+ import BaseModal from './BaseModal.svelte';
10
+ // Words of the dialog and the helper that puts values into them
11
+ import type { RenameDialogMessages } from './messages';
12
+ import { fillMessage } from '../../utils/fillMessage';
13
+
14
+ // Props
15
+ let className = '';
16
+ export { className as class };
17
+ export let style: string = '';
18
+ //
19
+ export let isOpen = false;
20
+ export let itemName = '';
21
+ export let itemType = 'item'; // 'item', 'folder', 'file', 'key', etc.
22
+ export let itemId = '';
23
+ export let title = '';
24
+ export let placeholder = '';
25
+ export let confirmLabel = 'Rename';
26
+ export let cancelLabel = 'Cancel';
27
+ // The words a screen reader says for the close button (see BaseModal)
28
+ export let closeLabel = 'Close modal';
29
+ // The words of the errors and toasts; a key that is left out keeps its English text (see ./messages)
30
+ export let messages: Partial<RenameDialogMessages> = {};
31
+ export let width = '400px';
32
+ export let height = 'auto';
33
+ export let target: string = 'rename-dialog'; // target for Portal
34
+ export let maxLength = 50; // Reduced for better UX
35
+ export let shouldUseCustomRenameFunction = false; // If true, parent component handles the rename
36
+
37
+ // For backwards compatibility with specific implementations
38
+ export let modalType: string = 'rename';
39
+ export let modalData: any = null;
40
+
41
+ let inputValue = '';
42
+ // The Input binds its element to this: it starts as null (an undefined value cannot be bound)
43
+ let inputElement: HTMLInputElement | null = null;
44
+ let hasAttemptedSubmit = false; // Track if user has attempted to submit
45
+ let isValid = false; // Track if input is valid
46
+
47
+ // Initialize modalData with our current props if not provided externally
48
+ $: if (modalData === null) {
49
+ modalData = {
50
+ itemName,
51
+ itemType,
52
+ itemId,
53
+ title,
54
+ placeholder,
55
+ confirmLabel,
56
+ cancelLabel
57
+ };
58
+ }
59
+
60
+ // Update validation state whenever inputValue changes
61
+ $: {
62
+ isValid =
63
+ inputValue.trim().length > 0 && inputValue.length <= maxLength && inputValue !== itemName;
64
+ }
65
+
66
+ // Computed placeholder based on itemType
67
+ $: computedPlaceholder = placeholder || `${itemType} name…`;
68
+
69
+ // The words of the errors and toasts: the page's own, or English
70
+ $: text = {
71
+ invalidTitle: messages.invalidTitle ?? 'Invalid name',
72
+ enterName: messages.enterName ?? 'Please enter a name',
73
+ enterDifferentName: messages.enterDifferentName ?? 'Please enter a different name',
74
+ enterValidName: messages.enterValidName ?? 'Please enter a valid name',
75
+ tooShort: messages.tooShort ?? 'Name must be at least 1 character long',
76
+ tooLong: fillMessage(messages.tooLong ?? 'Name must be {max} characters or less', {
77
+ max: maxLength
78
+ }),
79
+ renamed: messages.renamed ?? 'Successfully renamed to {name}',
80
+ failed: messages.failed ?? 'Failed to rename item'
81
+ };
82
+
83
+ // Function to focus and select the input text
84
+ async function focusAndSelectInput() {
85
+ // Wait for the DOM to update
86
+ await tick();
87
+
88
+ if (!inputElement) return;
89
+
90
+ // Focus the input
91
+ inputElement.focus();
92
+
93
+ // Select all text
94
+ inputElement.setSelectionRange(0, inputElement.value.length);
95
+ }
96
+
97
+ // Simple function to handle input initialization
98
+ function handleInput(event: Event) {
99
+ const input = event.target as HTMLInputElement;
100
+ inputValue = input.value.slice(0, maxLength);
101
+ }
102
+
103
+ // When the modal opens, set the input value and focus the input
104
+ $: if (isOpen) {
105
+ inputValue = itemName;
106
+ hasAttemptedSubmit = false; // Reset submission state
107
+ // Schedule focus after a short delay
108
+ setTimeout(focusAndSelectInput, 50);
109
+ }
110
+
111
+ const dispatch = createEventDispatcher();
112
+
113
+ async function handleRename() {
114
+ hasAttemptedSubmit = true;
115
+
116
+ try {
117
+ // Validate input
118
+ if (!inputValue.trim() || inputValue.length < 1) {
119
+ showToast('error', text.invalidTitle, { description: text.tooShort });
120
+ return;
121
+ }
122
+
123
+ if (inputValue.length > maxLength) {
124
+ showToast('error', text.invalidTitle, { description: text.tooLong });
125
+ return;
126
+ }
127
+
128
+ if (inputValue === itemName) {
129
+ showToast('error', text.invalidTitle, { description: text.enterDifferentName });
130
+ return;
131
+ }
132
+
133
+ // If parent component handles rename, dispatch event
134
+ if (shouldUseCustomRenameFunction) {
135
+ dispatch('rename', { itemId, newName: inputValue, oldName: itemName });
136
+ isOpen = false;
137
+ } else {
138
+ try {
139
+ showToast('success', fillMessage(text.renamed, { name: inputValue }));
140
+ dispatch('rename', { itemId, newName: inputValue, oldName: itemName });
141
+ isOpen = false;
142
+ } catch (error) {
143
+ console.error('Error during rename:', error);
144
+ showToast('error', text.failed);
145
+ }
146
+ }
147
+ } catch (error) {
148
+ console.error('Error during rename:', error);
149
+ showToast('error', text.failed);
150
+ }
151
+ }
152
+
153
+ function handleClose() {
154
+ isOpen = false;
155
+ hasAttemptedSubmit = false;
156
+ dispatch('cancel');
157
+ }
158
+
159
+ // Support for restoring modal state
160
+ function handleRestore(event: CustomEvent) {
161
+ if (event.detail) {
162
+ itemName = event.detail.itemName || '';
163
+ itemType = event.detail.itemType || 'item';
164
+ itemId = event.detail.itemId || '';
165
+ if (event.detail.title) title = event.detail.title;
166
+ if (event.detail.placeholder) placeholder = event.detail.placeholder;
167
+ if (event.detail.confirmLabel) confirmLabel = event.detail.confirmLabel;
168
+ if (event.detail.cancelLabel) cancelLabel = event.detail.cancelLabel;
169
+
170
+ inputValue = itemName;
171
+ setTimeout(focusAndSelectInput, 50);
172
+ }
173
+ }
174
+
175
+ $: displayTitle = title || 'Rename';
176
+ $: validationMessage =
177
+ !isValid && hasAttemptedSubmit
178
+ ? inputValue.trim().length === 0
179
+ ? text.enterName
180
+ : inputValue === itemName
181
+ ? text.enterDifferentName
182
+ : text.enterValidName
183
+ : '';
184
184
  </script>
185
185
 
186
- <BaseModal
187
- bind:open={isOpen}
188
- on:close={handleClose}
189
- {target}
190
- title={title || undefined}
191
- width={width}
192
- height={height}
193
- titlePadding="small"
194
- {closeLabel}
195
- {modalType}
196
- {modalData}
197
- on:restore={handleRestore}
186
+ <BaseModal
187
+ bind:open={isOpen}
188
+ on:close={handleClose}
189
+ {target}
190
+ title={displayTitle}
191
+ {width}
192
+ {height}
193
+ {closeLabel}
194
+ {modalType}
195
+ {modalData}
196
+ on:restore={handleRestore}
198
197
  >
199
- <div class="{className ? `${className} ` : ''}rename-dialog-container h-full flex flex-col gap-4 min-h-[136px] justify-between" style={style}>
200
-
201
- <!-- Input Container -->
202
- <div class="input-container flex flex-col items-center pt-6">
203
- <!-- Simple native input with minimal event handlers -->
204
- <input
205
- type="text"
206
- bind:value={inputValue}
207
- bind:this={inputElement}
208
- oninput={handleInput}
209
- onkeydown={(e) => {
210
- if (e.key === 'Escape') {
211
- handleClose();
212
- } else {
213
- e.stopPropagation(); // Stop all keyboard events except Escape from bubbling up
214
- if (e.key === 'Enter') {
215
- e.preventDefault();
216
- handleRename();
217
- }
218
- }
219
- }}
220
- onfocus={(e) => {
221
- const target = e.target as HTMLInputElement;
222
- target.placeholder = "";
223
-
224
- // Select all text
225
- setTimeout(() => {
226
- if (target) {
227
- target.setSelectionRange(0, target.value.length);
228
- }
229
- }, 0);
230
- }}
231
- onblur={(e) => {
232
- const target = e.target as HTMLInputElement;
233
- target.placeholder = computedPlaceholder;
234
- }}
235
- required
236
- class="w-full h5 text-[24px] text-[hsl(var(--grey7))] text-center
237
- bg-transparent border-none focus:outline-hidden focus:ring-0
238
- placeholder:text-[24px] placeholder:text-[hsl(var(--grey3))]
239
- text-ellipsis-input
240
- {!isValid && hasAttemptedSubmit ? 'input-error' : ''}"
241
- maxlength={maxLength}
242
- data-min-length="1"
243
- placeholder={computedPlaceholder}
244
- />
245
- {#if !isValid && hasAttemptedSubmit}
246
- <div class="text-xs text-[hsl(var(--error))] mt-1">
247
- {inputValue.trim().length === 0 ? text.enterName :
248
- inputValue === itemName ? text.enterDifferentName :
249
- text.enterValidName}
250
- </div>
251
- {/if}
252
- </div>
253
-
254
- <!-- Buttons Container -->
255
- <div class="buttons-container flex justify-center gap-4">
256
- <!-- Cancel Button -->
257
- <!-- svelte-ignore a11y-no-static-element-interactions -->
258
- <Button
259
- class="modal-btn-secondary !h-[34px]"
260
- onclick={handleClose}
261
- >
262
- {cancelLabel}
263
- </Button>
264
-
265
- <!-- Confirm Button -->
266
- <Button
267
- class="modal-btn-primary !h-[34px]"
268
- onclick={handleRename}
269
- disabled={!isValid}
270
- >
271
- {confirmLabel}
272
- </Button>
273
- </div>
274
- </div>
198
+ <div
199
+ class="{className ? `${className} ` : ''}rename-dialog-container flex flex-col gap-4"
200
+ {style}
201
+ >
202
+ <div class="flex flex-col gap-1.5">
203
+ <Input
204
+ bind:ref={inputElement}
205
+ bind:value={inputValue}
206
+ placeholder={computedPlaceholder}
207
+ maxlength={maxLength}
208
+ aria-invalid={Boolean(validationMessage)}
209
+ class={validationMessage ? 'border-destructive' : ''}
210
+ oninput={handleInput}
211
+ onkeydown={(e) => {
212
+ if (e.key === 'Escape') {
213
+ handleClose();
214
+ } else {
215
+ e.stopPropagation();
216
+ if (e.key === 'Enter') {
217
+ e.preventDefault();
218
+ handleRename();
219
+ }
220
+ }
221
+ }}
222
+ onfocus={(e) => {
223
+ const target = e.currentTarget;
224
+ setTimeout(() => {
225
+ target.setSelectionRange(0, target.value.length);
226
+ }, 0);
227
+ }}
228
+ />
229
+ {#if validationMessage}
230
+ <p class="text-caption text-destructive">{validationMessage}</p>
231
+ {/if}
232
+ </div>
233
+
234
+ <div class="flex justify-end gap-2">
235
+ <Button variant="outline" onclick={handleClose}>{cancelLabel}</Button>
236
+ <Button onclick={handleRename} disabled={!isValid}>{confirmLabel}</Button>
237
+ </div>
238
+ </div>
275
239
  </BaseModal>
276
-
277
- <style>
278
- :global(.input-error) {
279
- animation: shake 0.4s ease-in-out;
280
- border-bottom: 1px solid hsl(var(--error)) !important;
281
- }
282
-
283
- :global(.text-ellipsis-input) {
284
- overflow: hidden;
285
- text-overflow: ellipsis;
286
- white-space: nowrap;
287
- max-width: 100%;
288
- padding: 0 16px; /* Add padding to prevent text from touching edges */
289
- box-sizing: border-box;
290
- }
291
-
292
- @keyframes shake {
293
- 0%, 100% { transform: translateX(0); }
294
- 25% { transform: translateX(-5px); }
295
- 75% { transform: translateX(5px); }
296
- }
297
- </style>