@makolabs/ripple 1.2.3 → 1.2.8

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 (114) hide show
  1. package/README.md +77 -0
  2. package/dist/adapters/ai/OpenAIAdapter.js +16 -11
  3. package/dist/adapters/ai/types.d.ts +3 -3
  4. package/dist/adapters/storage/BaseAdapter.d.ts +1 -1
  5. package/dist/adapters/storage/BaseAdapter.js +1 -1
  6. package/dist/adapters/storage/S3Adapter.js +2 -2
  7. package/dist/ai/AIChatInterface.svelte +32 -34
  8. package/dist/ai/AIChatInterface.svelte.d.ts +0 -1
  9. package/dist/ai/AIChatInterfaceTestWrapper.svelte +26 -0
  10. package/dist/ai/AIChatInterfaceTestWrapper.svelte.d.ts +17 -0
  11. package/dist/ai/ChatInput.svelte +7 -15
  12. package/dist/ai/ChatInput.svelte.d.ts +0 -2
  13. package/dist/ai/CodeRenderer.svelte +25 -12
  14. package/dist/ai/ComposeDropdown.svelte +17 -14
  15. package/dist/ai/MermaidRenderer.svelte +21 -17
  16. package/dist/ai/MermaidRenderer.svelte.d.ts +0 -1
  17. package/dist/ai/MessageBox.svelte +10 -7
  18. package/dist/ai/ThinkingDisplay.svelte +67 -43
  19. package/dist/ai/ai-chat-interface.d.ts +22 -21
  20. package/dist/ai/ai-chat-interface.js +8 -7
  21. package/dist/ai/content-detector.js +2 -2
  22. package/dist/button/ButtonTestWrapper.svelte +10 -0
  23. package/dist/button/ButtonTestWrapper.svelte.d.ts +7 -0
  24. package/dist/charts/Chart.svelte +6 -1
  25. package/dist/config/ai.js +1 -0
  26. package/dist/drawer/DrawerTestWrapper.svelte +19 -0
  27. package/dist/drawer/DrawerTestWrapper.svelte.d.ts +9 -0
  28. package/dist/drawer/drawer.d.ts +19 -18
  29. package/dist/drawer/drawer.js +7 -6
  30. package/dist/elements/accordion/Accordion.svelte +1 -1
  31. package/dist/elements/accordion/Accordion.svelte.d.ts +1 -1
  32. package/dist/elements/accordion/AccordionTestWrapper.svelte +21 -0
  33. package/dist/elements/accordion/AccordionTestWrapper.svelte.d.ts +10 -0
  34. package/dist/elements/badge/Badge.svelte +5 -4
  35. package/dist/elements/badge/BadgeTestWrapper.svelte +14 -0
  36. package/dist/elements/badge/BadgeTestWrapper.svelte.d.ts +9 -0
  37. package/dist/elements/badge/badge.d.ts +40 -39
  38. package/dist/elements/badge/badge.js +14 -13
  39. package/dist/elements/dropdown/Dropdown.svelte +0 -1
  40. package/dist/elements/pagination/Pagination.svelte +20 -26
  41. package/dist/elements/progress/Progress.svelte +3 -3
  42. package/dist/elements/timeline/Timeline.svelte +1 -1
  43. package/dist/file-browser/FileBrowser.svelte +7 -10
  44. package/dist/filters/CompactFilters.svelte +3 -3
  45. package/dist/forms/Checkbox.svelte +0 -1
  46. package/dist/forms/CheckboxTestWrapper.svelte +8 -0
  47. package/dist/forms/CheckboxTestWrapper.svelte.d.ts +4 -0
  48. package/dist/forms/DateRange.svelte +186 -198
  49. package/dist/forms/Form.svelte +1 -0
  50. package/dist/forms/Input.svelte +14 -5
  51. package/dist/forms/InputTestWrapper.svelte +8 -0
  52. package/dist/forms/InputTestWrapper.svelte.d.ts +4 -0
  53. package/dist/forms/NumberInput.svelte +2 -2
  54. package/dist/forms/RadioInputs.svelte +1 -1
  55. package/dist/forms/RadioPill.svelte +1 -1
  56. package/dist/forms/Slider.svelte +2 -2
  57. package/dist/forms/Tags.svelte +3 -3
  58. package/dist/forms/ToggleTestWrapper.svelte +8 -0
  59. package/dist/forms/ToggleTestWrapper.svelte.d.ts +7 -0
  60. package/dist/forms/slider.js +1 -1
  61. package/dist/header/PageHeader.svelte +2 -1
  62. package/dist/header/breadcrumbs.d.ts +47 -33
  63. package/dist/header/breadcrumbs.js +12 -11
  64. package/dist/index.d.ts +3 -2
  65. package/dist/index.js +2 -0
  66. package/dist/layout/activity-list/ActivityList.svelte +9 -11
  67. package/dist/layout/card/CardTestWrapper.svelte +15 -0
  68. package/dist/layout/card/CardTestWrapper.svelte.d.ts +7 -0
  69. package/dist/layout/card/RankedCard.svelte +2 -3
  70. package/dist/layout/navbar/navbar.d.ts +19 -18
  71. package/dist/layout/navbar/navbar.js +7 -6
  72. package/dist/layout/sidebar/NavGroup.svelte +1 -0
  73. package/dist/layout/table/Cells.svelte +5 -5
  74. package/dist/layout/table/Table.svelte +8 -8
  75. package/dist/layout/table/table.d.ts +28 -24
  76. package/dist/layout/table/table.js +14 -13
  77. package/dist/modal/Modal.svelte +1 -1
  78. package/dist/modal/ModalTestWrapper.svelte +20 -0
  79. package/dist/modal/ModalTestWrapper.svelte.d.ts +8 -0
  80. package/dist/modal/modal.d.ts +1 -20
  81. package/dist/pipeline/Pipeline.svelte +29 -17
  82. package/dist/user-management/README.md +417 -0
  83. package/dist/user-management/UserManagement.svelte +245 -0
  84. package/dist/user-management/UserManagement.svelte.d.ts +4 -0
  85. package/dist/user-management/UserManagementTestWrapper.svelte +33 -0
  86. package/dist/user-management/UserManagementTestWrapper.svelte.d.ts +13 -0
  87. package/dist/user-management/UserModal.svelte +285 -0
  88. package/dist/user-management/UserModal.svelte.d.ts +4 -0
  89. package/dist/user-management/UserModalTestWrapper.svelte +22 -0
  90. package/dist/user-management/UserModalTestWrapper.svelte.d.ts +7 -0
  91. package/dist/user-management/UserTable.svelte +219 -0
  92. package/dist/user-management/UserTable.svelte.d.ts +4 -0
  93. package/dist/user-management/UserTableTestWrapper.svelte +41 -0
  94. package/dist/user-management/UserTableTestWrapper.svelte.d.ts +7 -0
  95. package/dist/user-management/UserViewModal.svelte +276 -0
  96. package/dist/user-management/UserViewModal.svelte.d.ts +4 -0
  97. package/dist/user-management/UserViewModalTestWrapper.svelte +22 -0
  98. package/dist/user-management/UserViewModalTestWrapper.svelte.d.ts +7 -0
  99. package/dist/user-management/adapters/UserManagement.remote.d.ts +68 -0
  100. package/dist/user-management/adapters/UserManagement.remote.js +487 -0
  101. package/dist/user-management/adapters/index.d.ts +10 -0
  102. package/dist/user-management/adapters/index.js +12 -0
  103. package/dist/user-management/adapters/mockUserManagement.d.ts +70 -0
  104. package/dist/user-management/adapters/mockUserManagement.js +187 -0
  105. package/dist/user-management/adapters/types.d.ts +24 -0
  106. package/dist/user-management/adapters/types.js +7 -0
  107. package/dist/user-management/index.d.ts +12 -0
  108. package/dist/user-management/index.js +11 -0
  109. package/dist/user-management/user-management.d.ts +126 -0
  110. package/dist/user-management/user-management.js +42 -0
  111. package/package.json +4 -1
  112. package/dist/types/markdown.d.ts +0 -14
  113. package/dist/types/variants.d.ts +0 -1
  114. package/dist/types/variants.js +0 -1
@@ -0,0 +1,276 @@
1
+ <script lang="ts">
2
+ import { Modal, Button, TabGroup, TabContent, type TabItem, cn } from '../index.js';
3
+ import type { UserViewModalProps } from './user-management.js';
4
+ import { getUserDisplayName } from './user-management.js';
5
+ import { SvelteDate } from 'svelte/reactivity';
6
+
7
+ let {
8
+ open = $bindable(),
9
+ user = $bindable(),
10
+ onEdit,
11
+ onClose,
12
+ class: className
13
+ }: UserViewModalProps = $props();
14
+
15
+ // Local state
16
+ let activeTab = $state<'profile' | 'permissions'>('profile');
17
+
18
+ // Define tabs
19
+ const tabs: TabItem[] = [
20
+ {
21
+ value: 'profile',
22
+ label: 'Profile',
23
+ disabled: false
24
+ },
25
+ {
26
+ value: 'permissions',
27
+ label: 'Permissions',
28
+ disabled: false
29
+ }
30
+ ];
31
+
32
+ function handleClose() {
33
+ open = false;
34
+ activeTab = 'profile';
35
+ if (onClose) onClose();
36
+ }
37
+
38
+ function handleEdit() {
39
+ if (onEdit && user) {
40
+ onEdit(user);
41
+ }
42
+ }
43
+
44
+ function getModalTitle() {
45
+ return getUserDisplayName(user);
46
+ }
47
+
48
+ function formatDate(timestamp?: number) {
49
+ if (!timestamp) return 'Never';
50
+ return new SvelteDate(timestamp).toLocaleDateString('en-US', {
51
+ year: 'numeric',
52
+ month: 'short',
53
+ day: 'numeric'
54
+ });
55
+ }
56
+ </script>
57
+
58
+ {#snippet MailIcon()}
59
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
60
+ <path
61
+ stroke-linecap="round"
62
+ stroke-linejoin="round"
63
+ stroke-width="2"
64
+ d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
65
+ ></path>
66
+ </svg>
67
+ {/snippet}
68
+
69
+ {#snippet PhoneIcon()}
70
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
71
+ <path
72
+ stroke-linecap="round"
73
+ stroke-linejoin="round"
74
+ stroke-width="2"
75
+ d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"
76
+ ></path>
77
+ </svg>
78
+ {/snippet}
79
+
80
+ {#snippet ProfileIcon()}
81
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
82
+ <path
83
+ stroke-linecap="round"
84
+ stroke-linejoin="round"
85
+ stroke-width="2"
86
+ d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
87
+ ></path>
88
+ </svg>
89
+ {/snippet}
90
+
91
+ {#snippet ShieldIcon()}
92
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
93
+ <path
94
+ stroke-linecap="round"
95
+ stroke-linejoin="round"
96
+ stroke-width="2"
97
+ d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
98
+ ></path>
99
+ </svg>
100
+ {/snippet}
101
+
102
+ <Modal
103
+ {open}
104
+ onclose={handleClose}
105
+ title={getModalTitle()}
106
+ contentclass="max-w-4xl"
107
+ bodyclass="flex flex-col min-h-[500px]"
108
+ class={cn(className)}
109
+ >
110
+ <div class="flex h-full grow flex-col space-y-6">
111
+ <!-- Tab Navigation -->
112
+ <TabGroup {tabs} bind:selected={activeTab}>
113
+ <TabContent value="profile" persisted>
114
+ <!-- Profile Information -->
115
+ <div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
116
+ <!-- Basic Info -->
117
+ <div class="space-y-4">
118
+ <div class="rounded-lg bg-gray-50 p-4">
119
+ <div class="mb-3 flex items-center gap-2">
120
+ <span class="inline-flex">{@render ProfileIcon()}</span>
121
+ <h4 class="text-sm font-medium text-gray-700">Basic Information</h4>
122
+ </div>
123
+ <div class="space-y-3">
124
+ <div>
125
+ <span class="text-xs text-gray-500">Name</span>
126
+ <p class="text-sm font-medium">
127
+ {getUserDisplayName(user)}
128
+ </p>
129
+ </div>
130
+ <div>
131
+ <span class="text-xs text-gray-500">User ID</span>
132
+ <p class="font-mono text-xs break-all">{user?.id || 'N/A'}</p>
133
+ </div>
134
+ {#if user?.role}
135
+ <div>
136
+ <span class="text-xs text-gray-500">Role</span>
137
+ <p class="text-sm">
138
+ <span
139
+ class="inline-flex items-center rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-800"
140
+ >
141
+ {user.role}
142
+ </span>
143
+ </p>
144
+ </div>
145
+ {/if}
146
+ </div>
147
+ </div>
148
+
149
+ <!-- Contact Info -->
150
+ <div class="rounded-lg bg-gray-50 p-4">
151
+ <h4 class="mb-3 text-sm font-medium text-gray-700">Contact</h4>
152
+ <div class="space-y-2">
153
+ {#if user?.email_addresses?.[0]?.email_address}
154
+ <div class="flex items-center gap-2">
155
+ <span class="inline-flex text-gray-400">{@render MailIcon()}</span>
156
+ <span class="text-sm">{user.email_addresses[0].email_address}</span>
157
+ </div>
158
+ {/if}
159
+ {#if user?.phone_numbers?.[0]?.phone_number}
160
+ <div class="flex items-center gap-2">
161
+ <span class="inline-flex text-gray-400">{@render PhoneIcon()}</span>
162
+ <span class="text-sm">{user.phone_numbers[0].phone_number}</span>
163
+ </div>
164
+ {/if}
165
+ </div>
166
+ </div>
167
+ </div>
168
+
169
+ <!-- Account Status & Metadata -->
170
+ <div class="space-y-4">
171
+ <div class="rounded-lg bg-gray-50 p-4">
172
+ <h4 class="mb-3 text-sm font-medium text-gray-700">Account Status</h4>
173
+ <div class="space-y-3">
174
+ <div>
175
+ <span class="text-xs text-gray-500">Status</span>
176
+ <p class="text-sm">
177
+ <span
178
+ class="inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800"
179
+ >
180
+ Active
181
+ </span>
182
+ </p>
183
+ </div>
184
+ <div>
185
+ <span class="text-xs text-gray-500">Created</span>
186
+ <p class="text-sm">{formatDate(user?.created_at)}</p>
187
+ </div>
188
+ <div>
189
+ <span class="text-xs text-gray-500">Last Sign In</span>
190
+ <p class="text-sm">{formatDate(user?.last_sign_in_at)}</p>
191
+ </div>
192
+ </div>
193
+ </div>
194
+
195
+ <!-- Additional Metadata -->
196
+ {#if user?.private_metadata && Object.keys(user.private_metadata).length > 0}
197
+ <div class="rounded-lg bg-gray-50 p-4">
198
+ <h4 class="mb-3 text-sm font-medium text-gray-700">Additional Information</h4>
199
+ <div class="space-y-2">
200
+ {#each Object.entries(user.private_metadata ?? {}) as [key, value] (key + value)}
201
+ <div>
202
+ <span class="text-xs text-gray-500">{key}</span>
203
+ <p class="font-mono text-sm text-gray-700">
204
+ {typeof value === 'string' && value.length > 50
205
+ ? `${value.slice(0, 50)}...`
206
+ : String(value)}
207
+ </p>
208
+ </div>
209
+ {/each}
210
+ </div>
211
+ </div>
212
+ {/if}
213
+ </div>
214
+ </div>
215
+ </TabContent>
216
+
217
+ <TabContent value="permissions" persisted>
218
+ <!-- Permissions Information -->
219
+ <div class="space-y-6">
220
+ <!-- Current Role -->
221
+ {#if user?.role}
222
+ <div class="rounded-lg bg-gray-50 p-4">
223
+ <div class="mb-3 flex items-center gap-2">
224
+ <span class="inline-flex text-blue-600">{@render ShieldIcon()}</span>
225
+ <h4 class="text-sm font-medium text-gray-700">Current Role</h4>
226
+ </div>
227
+ <div class="flex items-center justify-between">
228
+ <div>
229
+ <p class="text-sm font-medium text-blue-600">{user.role}</p>
230
+ {#if user.permissions}
231
+ <p class="mt-1 text-xs text-gray-600">
232
+ {user.permissions.length} permission{user.permissions.length === 1 ? '' : 's'}
233
+ </p>
234
+ {/if}
235
+ </div>
236
+ </div>
237
+ </div>
238
+ {/if}
239
+
240
+ <!-- Permissions List -->
241
+ <div>
242
+ <h4 class="mb-3 text-sm font-medium text-gray-700">Assigned Permissions</h4>
243
+ {#if user?.permissions && user.permissions.length > 0}
244
+ <div class="max-h-80 overflow-y-auto rounded-lg border border-gray-200 bg-white">
245
+ <div class="divide-y divide-gray-100">
246
+ {#each user.permissions as permission (permission)}
247
+ <div class="px-4 py-3">
248
+ <div class="flex items-center gap-2 text-sm">
249
+ <div class="h-1.5 w-1.5 shrink-0 rounded-full bg-green-500"></div>
250
+ <span class="font-mono text-gray-700">{permission}</span>
251
+ </div>
252
+ </div>
253
+ {/each}
254
+ </div>
255
+ </div>
256
+ {:else}
257
+ <div class="rounded-lg bg-gray-50 p-6 text-center">
258
+ <p class="text-sm text-gray-500">No permissions assigned</p>
259
+ </div>
260
+ {/if}
261
+ </div>
262
+ </div>
263
+ </TabContent>
264
+ </TabGroup>
265
+ </div>
266
+
267
+ <!-- View Mode Actions -->
268
+ {#snippet footer()}
269
+ <div class="flex justify-end gap-3">
270
+ <Button variant="outline" onclick={handleClose}>Close</Button>
271
+ {#if onEdit}
272
+ <Button color="primary" onclick={handleEdit}>Edit User</Button>
273
+ {/if}
274
+ </div>
275
+ {/snippet}
276
+ </Modal>
@@ -0,0 +1,4 @@
1
+ import type { UserViewModalProps } from './user-management.js';
2
+ declare const UserViewModal: import("svelte").Component<UserViewModalProps, {}, "open" | "user">;
3
+ type UserViewModal = ReturnType<typeof UserViewModal>;
4
+ export default UserViewModal;
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import UserViewModal from './UserViewModal.svelte';
3
+ import type { UserViewModalProps } from './user-management.js';
4
+
5
+ interface Props extends UserViewModalProps {
6
+ testId?: string;
7
+ }
8
+
9
+ let {
10
+ open = $bindable(),
11
+ user = $bindable(),
12
+ permissions = [],
13
+ onEdit,
14
+ onClose = () => {},
15
+ testId,
16
+ ...rest
17
+ }: Props = $props();
18
+ </script>
19
+
20
+ <div data-testid={testId}>
21
+ <UserViewModal bind:open bind:user {permissions} {onEdit} {onClose} {...rest} />
22
+ </div>
@@ -0,0 +1,7 @@
1
+ import type { UserViewModalProps } from './user-management.js';
2
+ interface Props extends UserViewModalProps {
3
+ testId?: string;
4
+ }
5
+ declare const UserViewModalTestWrapper: import("svelte").Component<Props, {}, "open" | "user">;
6
+ type UserViewModalTestWrapper = ReturnType<typeof UserViewModalTestWrapper>;
7
+ export default UserViewModalTestWrapper;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * User Management Remote Functions
3
+ *
4
+ * Complete implementation template for user management remote functions.
5
+ * This follows the same pattern as users.remote.ts and is designed to be
6
+ * used as-is in SvelteKit applications like sharkfin-frontend.
7
+ *
8
+ * Configuration:
9
+ * - Set environment variables: CLERK_SECRET_KEY, ADMIN_API_KEY, PRIVATE_BASE_AUTH_URL, ALLOWED_ORG_ID
10
+ * - Configure CLIENT_ID via ADMIN_CONFIG or env variable (CLIENT_ID)
11
+ * - Adjust permission prefix filter via PERMISSION_PREFIX env variable
12
+ *
13
+ * @see https://svelte.dev/docs/kit/remote-functions
14
+ *
15
+ * Usage in your app:
16
+ * ```svelte
17
+ * <script>
18
+ * import { UserManagement } from '@makolabs/ripple';
19
+ * import * as adapter from '../UserManagement.remote';
20
+ * </script>
21
+ *
22
+ * <UserManagement adapter={adapter} />
23
+ * ```
24
+ */
25
+ import type { User } from '../user-management.js';
26
+ import type { GetUsersOptions, GetUsersResult } from './types.js';
27
+ /**
28
+ * Get users with pagination and sorting
29
+ *
30
+ * Transforms adapter options to Clerk API format
31
+ */
32
+ export declare const getUsers: import("@sveltejs/kit").RemoteQueryFunction<GetUsersOptions, GetUsersResult>;
33
+ /**
34
+ * Create a new user
35
+ *
36
+ * Creates user in Clerk, optionally adds to organization, and creates admin key with permissions
37
+ */
38
+ export declare const createUser: import("@sveltejs/kit").RemoteCommand<Partial<User>, Promise<User>>;
39
+ /**
40
+ * Update an existing user
41
+ */
42
+ export declare const updateUser: import("@sveltejs/kit").RemoteCommand<{
43
+ userId: string;
44
+ userData: Partial<User>;
45
+ }, Promise<User>>;
46
+ /**
47
+ * Delete a single user
48
+ */
49
+ export declare const deleteUser: import("@sveltejs/kit").RemoteCommand<string, Promise<void>>;
50
+ /**
51
+ * Delete multiple users
52
+ */
53
+ export declare const deleteUsers: import("@sveltejs/kit").RemoteCommand<string[], Promise<void>>;
54
+ /**
55
+ * Get permissions for a specific user
56
+ *
57
+ * Uses 'sub' (userId) parameter in admin API calls
58
+ */
59
+ export declare const getUserPermissions: import("@sveltejs/kit").RemoteQueryFunction<string, string[]>;
60
+ /**
61
+ * Update permissions for a specific user
62
+ *
63
+ * Uses 'sub' (userId) parameter in admin API calls
64
+ */
65
+ export declare const updateUserPermissions: import("@sveltejs/kit").RemoteCommand<{
66
+ userId: string;
67
+ permissions: string[];
68
+ }, Promise<void>>;