@miozu/jera 0.0.2 → 0.4.2

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 (82) hide show
  1. package/CLAUDE.md +734 -0
  2. package/README.md +219 -1
  3. package/llms.txt +97 -0
  4. package/package.json +54 -14
  5. package/src/actions/index.js +375 -0
  6. package/src/components/docs/CodeBlock.svelte +203 -0
  7. package/src/components/docs/DocSection.svelte +120 -0
  8. package/src/components/docs/PropsTable.svelte +136 -0
  9. package/src/components/docs/SplitPane.svelte +98 -0
  10. package/src/components/docs/index.js +14 -0
  11. package/src/components/feedback/Alert.svelte +234 -0
  12. package/src/components/feedback/EmptyState.svelte +179 -0
  13. package/src/components/feedback/ProgressBar.svelte +116 -0
  14. package/src/components/feedback/Skeleton.svelte +107 -0
  15. package/src/components/feedback/Spinner.svelte +77 -0
  16. package/src/components/feedback/Toast.svelte +261 -0
  17. package/src/components/forms/Checkbox.svelte +147 -0
  18. package/src/components/forms/Dropzone.svelte +248 -0
  19. package/src/components/forms/FileUpload.svelte +266 -0
  20. package/src/components/forms/IconInput.svelte +184 -0
  21. package/src/components/forms/Input.svelte +121 -0
  22. package/src/components/forms/NumberInput.svelte +225 -0
  23. package/src/components/forms/PinInput.svelte +169 -0
  24. package/src/components/forms/Radio.svelte +143 -0
  25. package/src/components/forms/RadioGroup.svelte +62 -0
  26. package/src/components/forms/RangeSlider.svelte +212 -0
  27. package/src/components/forms/SearchInput.svelte +175 -0
  28. package/src/components/forms/Select.svelte +324 -0
  29. package/src/components/forms/Switch.svelte +159 -0
  30. package/src/components/forms/Textarea.svelte +122 -0
  31. package/src/components/navigation/Accordion.svelte +65 -0
  32. package/src/components/navigation/AccordionItem.svelte +146 -0
  33. package/src/components/navigation/NavigationContainer.svelte +344 -0
  34. package/src/components/navigation/Sidebar.svelte +334 -0
  35. package/src/components/navigation/SidebarAccountGroup.svelte +495 -0
  36. package/src/components/navigation/SidebarAccountItem.svelte +492 -0
  37. package/src/components/navigation/SidebarGroup.svelte +230 -0
  38. package/src/components/navigation/SidebarGroupSwitcher.svelte +262 -0
  39. package/src/components/navigation/SidebarItem.svelte +210 -0
  40. package/src/components/navigation/SidebarNavigationItem.svelte +470 -0
  41. package/src/components/navigation/SidebarPopover.svelte +145 -0
  42. package/src/components/navigation/SidebarSearch.svelte +236 -0
  43. package/src/components/navigation/SidebarSection.svelte +158 -0
  44. package/src/components/navigation/SidebarToggle.svelte +86 -0
  45. package/src/components/navigation/Tabs.svelte +239 -0
  46. package/src/components/navigation/WorkspaceMenu.svelte +416 -0
  47. package/src/components/navigation/blocks/NavigationAccountGroup.svelte +396 -0
  48. package/src/components/navigation/blocks/NavigationCustomBlock.svelte +74 -0
  49. package/src/components/navigation/blocks/NavigationGroupSwitcher.svelte +277 -0
  50. package/src/components/navigation/blocks/NavigationSearch.svelte +300 -0
  51. package/src/components/navigation/blocks/NavigationSection.svelte +230 -0
  52. package/src/components/navigation/index.js +22 -0
  53. package/src/components/overlays/ConfirmDialog.svelte +272 -0
  54. package/src/components/overlays/Dropdown.svelte +153 -0
  55. package/src/components/overlays/DropdownDivider.svelte +23 -0
  56. package/src/components/overlays/DropdownItem.svelte +97 -0
  57. package/src/components/overlays/Modal.svelte +232 -0
  58. package/src/components/overlays/Popover.svelte +206 -0
  59. package/src/components/primitives/Avatar.svelte +132 -0
  60. package/src/components/primitives/Badge.svelte +118 -0
  61. package/src/components/primitives/Button.svelte +214 -0
  62. package/src/components/primitives/Card.svelte +104 -0
  63. package/src/components/primitives/Divider.svelte +105 -0
  64. package/src/components/primitives/LazyImage.svelte +104 -0
  65. package/src/components/primitives/Link.svelte +122 -0
  66. package/src/components/primitives/Stat.svelte +197 -0
  67. package/src/components/primitives/StatusBadge.svelte +122 -0
  68. package/src/index.js +183 -0
  69. package/src/tokens/colors.css +157 -0
  70. package/src/tokens/effects.css +128 -0
  71. package/src/tokens/index.css +81 -0
  72. package/src/tokens/spacing.css +49 -0
  73. package/src/tokens/typography.css +79 -0
  74. package/src/utils/cn.svelte.js +175 -0
  75. package/src/utils/highlighter.js +124 -0
  76. package/src/utils/index.js +22 -0
  77. package/src/utils/navigation.svelte.js +423 -0
  78. package/src/utils/reactive.svelte.js +328 -0
  79. package/src/utils/sidebar.svelte.js +211 -0
  80. package/jera.js +0 -135
  81. package/www/components/jera/Input/Input.svelte +0 -63
  82. package/www/components/jera/Input/index.js +0 -1
@@ -0,0 +1,495 @@
1
+ <!--
2
+ @component SidebarAccountGroup
3
+
4
+ Connected accounts group with expandable accounts and subroutes.
5
+ Matches dash.selify.ai connected accounts functionality.
6
+
7
+ @example
8
+ <SidebarAccountGroup
9
+ accounts={connectedAccounts}
10
+ expanded={accountsExpanded}
11
+ expandedAccounts={expandedAccountsObj}
12
+ onAccountClick={(account) => toggleAccount(account)}
13
+ onSubrouteClick={(subroute) => navigateTo(subroute.path)}
14
+ onConnectAccount={() => showConnectModal = true}
15
+ />
16
+ -->
17
+ <script>
18
+ import { getContext } from 'svelte';
19
+ import { fade, fly, slide } from 'svelte/transition';
20
+ import { cubicOut } from 'svelte/easing';
21
+ import { SIDEBAR_CONTEXT_KEY } from '../../utils/sidebar.svelte.js';
22
+ import SidebarAccountItem from './SidebarAccountItem.svelte';
23
+
24
+ let {
25
+ accounts = [],
26
+ expanded = $bindable(false),
27
+ expandedAccounts = $bindable({}),
28
+ onAccountClick = null,
29
+ onSubrouteClick = null,
30
+ onConnectAccount = null,
31
+ searchQuery = '',
32
+ class: className = ''
33
+ } = $props();
34
+
35
+ const sidebar = getContext(SIDEBAR_CONTEXT_KEY);
36
+ const isCollapsed = $derived(sidebar?.collapsed ?? false);
37
+
38
+ // Filter accounts based on search
39
+ const filteredAccounts = $derived(
40
+ accounts.filter(account =>
41
+ !searchQuery ||
42
+ account.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
43
+ account.platform?.toLowerCase().includes(searchQuery.toLowerCase())
44
+ )
45
+ );
46
+
47
+ function toggleExpanded() {
48
+ expanded = !expanded;
49
+ }
50
+
51
+ function handleAccountClick(account) {
52
+ // Toggle expanded state
53
+ expandedAccounts[account.id] = !expandedAccounts[account.id];
54
+
55
+ if (onAccountClick) {
56
+ onAccountClick(account);
57
+ }
58
+ }
59
+
60
+ function handleSubrouteClick(subroute) {
61
+ if (onSubrouteClick) {
62
+ onSubrouteClick(subroute);
63
+ }
64
+ // Close mobile overlay if in mobile mode
65
+ if (sidebar?.closeMobileOverlay) {
66
+ sidebar.closeMobileOverlay();
67
+ }
68
+ }
69
+
70
+ function handleConnectAccount() {
71
+ if (onConnectAccount) {
72
+ onConnectAccount();
73
+ }
74
+ }
75
+
76
+ // Get default subroutes for an account
77
+ function getAccountSubroutes(account) {
78
+ return [
79
+ {
80
+ id: 'overview',
81
+ label: 'Overview',
82
+ path: `/account/${account.id}`,
83
+ icon: 'Eye',
84
+ active: false
85
+ },
86
+ {
87
+ id: 'chat',
88
+ label: 'Chat',
89
+ path: `/account/${account.id}/chat`,
90
+ icon: 'MessageSquare',
91
+ active: false
92
+ },
93
+ {
94
+ id: 'settings',
95
+ label: 'Settings',
96
+ path: `/account/${account.id}/settings`,
97
+ icon: 'Settings',
98
+ active: false
99
+ }
100
+ ];
101
+ }
102
+ </script>
103
+
104
+ <div class="sidebar-section {className}">
105
+ <button
106
+ class="section-header"
107
+ onclick={toggleExpanded}
108
+ aria-expanded={expanded}
109
+ >
110
+ <span class="section-title">Connected Accounts</span>
111
+ {#if accounts.length > 0}
112
+ <span class="section-count">{accounts.length}</span>
113
+ {/if}
114
+ <svg
115
+ class="section-chevron {expanded ? 'rotate-180' : ''}"
116
+ xmlns="http://www.w3.org/2000/svg"
117
+ width="14"
118
+ height="14"
119
+ viewBox="0 0 24 24"
120
+ fill="none"
121
+ stroke="currentColor"
122
+ stroke-width="2"
123
+ stroke-linecap="round"
124
+ stroke-linejoin="round"
125
+ >
126
+ <polyline points="6 9 12 15 18 9"></polyline>
127
+ </svg>
128
+ </button>
129
+
130
+ {#if expanded}
131
+ <div class="accounts-list" transition:slide={{ duration: 200, easing: cubicOut }}>
132
+ {#each filteredAccounts as account}
133
+ <div class="account-wrapper">
134
+ <!-- Main account item -->
135
+ <button
136
+ class="account-item {expandedAccounts[account.id] ? 'expanded' : ''}"
137
+ onclick={() => handleAccountClick(account)}
138
+ title={account.name}
139
+ >
140
+ <div class="account-avatar-container">
141
+ {#if account.avatar_url}
142
+ <div class="account-avatar-wrapper">
143
+ <img
144
+ src={account.avatar_url}
145
+ alt={account.name}
146
+ class="account-avatar-img"
147
+ />
148
+ </div>
149
+ {:else}
150
+ <div class="account-avatar {account.platform}">
151
+ {account.name?.charAt(0)?.toUpperCase() || 'A'}
152
+ </div>
153
+ {/if}
154
+ <div class="platform-badge {account.platform}">
155
+ {#if account.platform === 'instagram'}
156
+ <svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
157
+ <rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect>
158
+ <path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path>
159
+ <line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line>
160
+ </svg>
161
+ {:else if account.platform === 'shopify'}
162
+ <svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
163
+ <path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path>
164
+ <line x1="3" y1="6" x2="21" y2="6"></line>
165
+ <path d="M16 10a4 4 0 0 1-8 0"></path>
166
+ </svg>
167
+ {/if}
168
+ </div>
169
+ </div>
170
+
171
+ {#if !isCollapsed}
172
+ <div class="account-info">
173
+ <span class="account-name">{account.name}</span>
174
+ </div>
175
+ <svg
176
+ class="account-chevron {expandedAccounts[account.id] ? 'rotate-180' : ''}"
177
+ xmlns="http://www.w3.org/2000/svg"
178
+ width="14"
179
+ height="14"
180
+ viewBox="0 0 24 24"
181
+ fill="none"
182
+ stroke="currentColor"
183
+ stroke-width="2"
184
+ stroke-linecap="round"
185
+ stroke-linejoin="round"
186
+ >
187
+ <polyline points="6 9 12 15 18 9"></polyline>
188
+ </svg>
189
+ {/if}
190
+ </button>
191
+
192
+ <!-- Account subroutes -->
193
+ {#if expandedAccounts[account.id] && !isCollapsed}
194
+ <div class="account-subroutes" transition:slide={{ duration: 200, easing: cubicOut }}>
195
+ {#each getAccountSubroutes(account) as subroute}
196
+ <button
197
+ class="subroute-item {subroute.active ? 'active' : ''}"
198
+ onclick={() => handleSubrouteClick(subroute)}
199
+ title={subroute.label}
200
+ >
201
+ {#if subroute.icon === 'Eye'}
202
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
203
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
204
+ <circle cx="12" cy="12" r="3"></circle>
205
+ </svg>
206
+ {:else if subroute.icon === 'MessageSquare'}
207
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
208
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
209
+ </svg>
210
+ {:else if subroute.icon === 'Settings'}
211
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
212
+ <circle cx="12" cy="12" r="3"></circle>
213
+ <path d="m12 1 1.414 1.414-1.414 1.414v2.828l1.414 1.414h2.828l1.414-1.414L23 12l-1.414 1.414-1.414-1.414h-2.828l-1.414 1.414v2.828l1.414 1.414L12 23l-1.414-1.414 1.414-1.414v-2.828l-1.414-1.414H6.758l-1.414 1.414L1 12l1.414-1.414 1.414 1.414h2.828l1.414-1.414V8.172L5.656 6.758 12 1z"></path>
214
+ </svg>
215
+ {/if}
216
+ <span>{subroute.label}</span>
217
+ </button>
218
+ {/each}
219
+ </div>
220
+ {/if}
221
+ </div>
222
+ {/each}
223
+
224
+ <!-- Connect Account Button -->
225
+ <button class="add-account-btn" onclick={handleConnectAccount} title="Connect new account">
226
+ <svg
227
+ xmlns="http://www.w3.org/2000/svg"
228
+ width="16"
229
+ height="16"
230
+ viewBox="0 0 24 24"
231
+ fill="none"
232
+ stroke="currentColor"
233
+ stroke-width="2"
234
+ stroke-linecap="round"
235
+ stroke-linejoin="round"
236
+ >
237
+ <circle cx="12" cy="12" r="10"></circle>
238
+ <line x1="12" y1="8" x2="12" y2="16"></line>
239
+ <line x1="8" y1="12" x2="16" y2="12"></line>
240
+ </svg>
241
+ <span>Connect account</span>
242
+ </button>
243
+ </div>
244
+ {/if}
245
+ </div>
246
+
247
+ <style>
248
+ .sidebar-section {
249
+ padding: 0.125rem 0;
250
+ }
251
+
252
+ .section-header {
253
+ width: 100%;
254
+ display: flex;
255
+ align-items: center;
256
+ gap: 0.5rem;
257
+ padding: 0.5rem 0.75rem;
258
+ font-size: 0.75rem;
259
+ font-weight: 600;
260
+ color: var(--color-text-muted, var(--color-base04, #737E99));
261
+ text-transform: uppercase;
262
+ letter-spacing: 0.05em;
263
+ cursor: pointer;
264
+ transition: all 200ms ease;
265
+ border: none;
266
+ background: transparent;
267
+ font-family: inherit;
268
+ justify-content: flex-start;
269
+ }
270
+
271
+ .section-header:hover {
272
+ color: var(--color-text, var(--color-base05, #D0D2DB));
273
+ }
274
+
275
+ .section-title {
276
+ flex: 1;
277
+ text-align: left;
278
+ }
279
+
280
+ .section-count {
281
+ padding: 0.125rem 0.375rem;
282
+ font-size: 0.625rem;
283
+ background-color: var(--color-surface-alt, var(--color-base02, #3E4359));
284
+ color: var(--color-text-muted, var(--color-base05, #D0D2DB));
285
+ border-radius: 9999px;
286
+ flex-shrink: 0;
287
+ }
288
+
289
+ .section-chevron {
290
+ color: var(--color-text-muted, var(--color-base04, #737E99));
291
+ transition: all 200ms ease;
292
+ flex-shrink: 0;
293
+ }
294
+
295
+ .section-chevron.rotate-180 {
296
+ transform: rotate(180deg);
297
+ }
298
+
299
+ .accounts-list {
300
+ display: flex;
301
+ flex-direction: column;
302
+ gap: 0.125rem;
303
+ padding: 0 0.5rem;
304
+ }
305
+
306
+ .account-wrapper {
307
+ display: flex;
308
+ flex-direction: column;
309
+ }
310
+
311
+ .account-item {
312
+ width: 100%;
313
+ padding: 0.5rem 0.75rem;
314
+ display: flex;
315
+ align-items: center;
316
+ gap: 0.75rem;
317
+ font-size: 0.875rem;
318
+ color: var(--color-text, var(--color-base06, #F3F4F7));
319
+ cursor: pointer;
320
+ border-radius: 0.375rem;
321
+ transition: all 200ms ease;
322
+ overflow: hidden;
323
+ border: none;
324
+ background: transparent;
325
+ font-family: inherit;
326
+ text-align: left;
327
+ }
328
+
329
+ .account-item:hover {
330
+ color: var(--color-primary, var(--color-base0D, #83D2FC));
331
+ background-color: color-mix(in srgb, var(--color-primary, var(--color-base0D, #83D2FC)) 10%, transparent);
332
+ }
333
+
334
+ .account-item.expanded {
335
+ background-color: color-mix(in srgb, var(--color-primary, var(--color-base0D, #83D2FC)) 10%, transparent);
336
+ color: var(--color-primary, var(--color-base0D, #83D2FC));
337
+ }
338
+
339
+ /* Account avatar styles */
340
+ .account-avatar-container {
341
+ position: relative;
342
+ flex-shrink: 0;
343
+ width: 2rem;
344
+ height: 2rem;
345
+ }
346
+
347
+ .account-avatar-wrapper {
348
+ width: 2rem;
349
+ height: 2rem;
350
+ border-radius: 0.375rem;
351
+ overflow: hidden;
352
+ background: linear-gradient(to bottom right, rgba(131, 210, 252, 0.2), rgba(201, 116, 230, 0.2));
353
+ display: flex;
354
+ align-items: center;
355
+ justify-content: center;
356
+ }
357
+
358
+ .account-avatar-img {
359
+ width: 100%;
360
+ height: 100%;
361
+ object-fit: cover;
362
+ }
363
+
364
+ .account-avatar {
365
+ width: 2rem;
366
+ height: 2rem;
367
+ border-radius: 0.375rem;
368
+ display: flex;
369
+ align-items: center;
370
+ justify-content: center;
371
+ font-size: 0.75rem;
372
+ font-weight: 600;
373
+ color: white;
374
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
375
+ }
376
+
377
+ .account-avatar.instagram {
378
+ background: linear-gradient(to bottom right, rgb(168, 85, 247), rgb(236, 72, 153));
379
+ }
380
+
381
+ .account-avatar.shopify {
382
+ background: linear-gradient(to bottom right, rgb(34, 197, 94), rgb(16, 185, 129));
383
+ }
384
+
385
+ .platform-badge {
386
+ position: absolute;
387
+ bottom: -2px;
388
+ right: -2px;
389
+ width: 1rem;
390
+ height: 1rem;
391
+ border-radius: 9999px;
392
+ display: flex;
393
+ align-items: center;
394
+ justify-content: center;
395
+ color: white;
396
+ border: 1px solid var(--color-bg, var(--color-base00, #232733));
397
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
398
+ z-index: 10;
399
+ }
400
+
401
+ .platform-badge.instagram {
402
+ background: linear-gradient(135deg, #833ab4, #fd1d1d, #fcb045);
403
+ }
404
+
405
+ .platform-badge.shopify {
406
+ background-color: var(--color-success, var(--color-base0B, #6DD672));
407
+ }
408
+
409
+ .account-info {
410
+ flex: 1;
411
+ min-width: 0;
412
+ display: flex;
413
+ flex-direction: column;
414
+ }
415
+
416
+ .account-name {
417
+ white-space: nowrap;
418
+ overflow: hidden;
419
+ text-overflow: ellipsis;
420
+ font-weight: 500;
421
+ }
422
+
423
+ .account-chevron {
424
+ color: var(--color-text-muted, var(--color-base05, #D0D2DB));
425
+ transition: all 200ms ease;
426
+ flex-shrink: 0;
427
+ }
428
+
429
+ .account-chevron.rotate-180 {
430
+ transform: rotate(180deg);
431
+ }
432
+
433
+ /* Account subroutes */
434
+ .account-subroutes {
435
+ margin-left: 2.5rem;
436
+ padding-left: 0.5rem;
437
+ border-left: 2px solid color-mix(in srgb, var(--color-base03, #565E78) 30%, transparent);
438
+ display: flex;
439
+ flex-direction: column;
440
+ gap: 0.125rem;
441
+ }
442
+
443
+ .subroute-item {
444
+ padding: 0.375rem 0.75rem;
445
+ display: flex;
446
+ align-items: center;
447
+ gap: 0.5rem;
448
+ font-size: 0.875rem;
449
+ color: var(--color-text-muted, var(--color-base05, #D0D2DB));
450
+ cursor: pointer;
451
+ border-radius: 0.375rem;
452
+ transition: all 200ms ease;
453
+ overflow: hidden;
454
+ border: none;
455
+ background: transparent;
456
+ font-family: inherit;
457
+ text-align: left;
458
+ width: 100%;
459
+ }
460
+
461
+ .subroute-item:hover {
462
+ color: var(--color-primary, var(--color-base0D, #83D2FC));
463
+ background-color: color-mix(in srgb, var(--color-primary, var(--color-base0D, #83D2FC)) 5%, transparent);
464
+ }
465
+
466
+ .subroute-item.active {
467
+ color: var(--color-primary, var(--color-base0D, #83D2FC));
468
+ background-color: color-mix(in srgb, var(--color-primary, var(--color-base0D, #83D2FC)) 10%, transparent);
469
+ font-weight: 500;
470
+ }
471
+
472
+ .add-account-btn {
473
+ width: 100%;
474
+ padding: 0.5rem 0.75rem;
475
+ margin-top: 0.25rem;
476
+ display: flex;
477
+ align-items: center;
478
+ gap: 0.5rem;
479
+ justify-content: center;
480
+ font-size: 0.875rem;
481
+ color: var(--color-text-muted, var(--color-base05, #D0D2DB));
482
+ cursor: pointer;
483
+ border-radius: 0.375rem;
484
+ transition: all 200ms ease;
485
+ border: 1px solid color-mix(in srgb, var(--color-base03, #565E78) 30%, transparent);
486
+ background: transparent;
487
+ font-family: inherit;
488
+ }
489
+
490
+ .add-account-btn:hover {
491
+ color: var(--color-primary, var(--color-base0D, #83D2FC));
492
+ background-color: color-mix(in srgb, var(--color-primary, var(--color-base0D, #83D2FC)) 5%, transparent);
493
+ border-color: var(--color-primary, var(--color-base0D, #83D2FC));
494
+ }
495
+ </style>