@miozu/jera 0.3.0 → 0.4.3

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