@makolabs/ripple 0.4.1-0 → 0.5.0

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 (59) hide show
  1. package/README.md +165 -205
  2. package/dist/adapters/ai/OpenAIAdapter.d.ts +115 -0
  3. package/dist/adapters/ai/OpenAIAdapter.js +568 -0
  4. package/dist/adapters/ai/index.d.ts +3 -0
  5. package/dist/adapters/ai/index.js +3 -0
  6. package/dist/adapters/ai/types.d.ts +108 -0
  7. package/dist/adapters/ai/types.js +31 -0
  8. package/dist/adapters/storage/BaseAdapter.js +31 -31
  9. package/dist/ai/AIChatInterface.svelte +435 -0
  10. package/dist/ai/AIChatInterface.svelte.d.ts +18 -0
  11. package/dist/ai/ChatInput.svelte +211 -0
  12. package/dist/ai/ChatInput.svelte.d.ts +18 -0
  13. package/dist/ai/CodeRenderer.svelte +174 -0
  14. package/dist/ai/CodeRenderer.svelte.d.ts +8 -0
  15. package/dist/ai/ComposeDropdown.svelte +171 -0
  16. package/dist/ai/ComposeDropdown.svelte.d.ts +9 -0
  17. package/dist/ai/MermaidRenderer.svelte +89 -0
  18. package/dist/ai/MermaidRenderer.svelte.d.ts +7 -0
  19. package/dist/ai/MessageBox.svelte +403 -0
  20. package/dist/ai/MessageBox.svelte.d.ts +12 -0
  21. package/dist/ai/ThinkingDisplay.svelte +275 -0
  22. package/dist/ai/ThinkingDisplay.svelte.d.ts +9 -0
  23. package/dist/ai/ai-chat-interface.d.ts +161 -0
  24. package/dist/ai/ai-chat-interface.js +63 -0
  25. package/dist/ai/content-detector.d.ts +41 -0
  26. package/dist/ai/content-detector.js +153 -0
  27. package/dist/config/ai.d.ts +13 -0
  28. package/dist/config/ai.js +43 -0
  29. package/dist/elements/accordion/accordion.js +1 -1
  30. package/dist/elements/badge/Badge.svelte +14 -3
  31. package/dist/elements/dropdown/Dropdown.svelte +2 -2
  32. package/dist/elements/dropdown/Select.svelte +1 -1
  33. package/dist/elements/progress/Progress.svelte +7 -10
  34. package/dist/file-browser/FileBrowser.svelte +1 -1
  35. package/dist/forms/DateRange.svelte +18 -16
  36. package/dist/forms/NumberInput.svelte +1 -1
  37. package/dist/forms/RadioInputs.svelte +1 -1
  38. package/dist/forms/RadioPill.svelte +1 -1
  39. package/dist/forms/Tags.svelte +2 -2
  40. package/dist/helper/date.d.ts +1 -0
  41. package/dist/helper/date.js +6 -0
  42. package/dist/index.d.ts +65 -1
  43. package/dist/index.js +11 -0
  44. package/dist/layout/activity-list/ActivityList.svelte +94 -0
  45. package/dist/layout/activity-list/ActivityList.svelte.d.ts +4 -0
  46. package/dist/layout/activity-list/activity-list.d.ts +152 -0
  47. package/dist/layout/activity-list/activity-list.js +59 -0
  48. package/dist/layout/card/Card.svelte +1 -5
  49. package/dist/layout/card/metric-card.d.ts +18 -18
  50. package/dist/layout/table/Cells.svelte +1 -7
  51. package/dist/layout/table/Cells.svelte.d.ts +1 -1
  52. package/dist/modal/Modal.svelte +4 -2
  53. package/dist/modal/Modal.svelte.d.ts +1 -1
  54. package/dist/modal/modal.d.ts +19 -18
  55. package/dist/modal/modal.js +7 -6
  56. package/dist/sonner/sonner.svelte +1 -7
  57. package/dist/types/markdown.d.ts +14 -0
  58. package/dist/utils/Portal.svelte +1 -1
  59. package/package.json +128 -121
@@ -0,0 +1,161 @@
1
+ export declare const aiChatInterface: import("tailwind-variants").TVReturnType<{
2
+ color: {
3
+ default: {
4
+ userMessage: string;
5
+ sendButton: string;
6
+ background: string;
7
+ };
8
+ primary: {
9
+ userMessage: string;
10
+ sendButton: string;
11
+ background: string;
12
+ };
13
+ secondary: {
14
+ userMessage: string;
15
+ sendButton: string;
16
+ background: string;
17
+ };
18
+ success: {
19
+ userMessage: string;
20
+ sendButton: string;
21
+ background: string;
22
+ };
23
+ warning: {
24
+ userMessage: string;
25
+ sendButton: string;
26
+ background: string;
27
+ };
28
+ danger: {
29
+ userMessage: string;
30
+ sendButton: string;
31
+ background: string;
32
+ };
33
+ info: {
34
+ userMessage: string;
35
+ sendButton: string;
36
+ background: string;
37
+ };
38
+ };
39
+ loading: {
40
+ true: {
41
+ sendButton: string;
42
+ };
43
+ };
44
+ disabled: {
45
+ true: {
46
+ sendButton: string;
47
+ };
48
+ };
49
+ }, {
50
+ userMessage: string;
51
+ aiMessage: string;
52
+ sendButton: string;
53
+ background: string;
54
+ }, undefined, {
55
+ color: {
56
+ default: {
57
+ userMessage: string;
58
+ sendButton: string;
59
+ background: string;
60
+ };
61
+ primary: {
62
+ userMessage: string;
63
+ sendButton: string;
64
+ background: string;
65
+ };
66
+ secondary: {
67
+ userMessage: string;
68
+ sendButton: string;
69
+ background: string;
70
+ };
71
+ success: {
72
+ userMessage: string;
73
+ sendButton: string;
74
+ background: string;
75
+ };
76
+ warning: {
77
+ userMessage: string;
78
+ sendButton: string;
79
+ background: string;
80
+ };
81
+ danger: {
82
+ userMessage: string;
83
+ sendButton: string;
84
+ background: string;
85
+ };
86
+ info: {
87
+ userMessage: string;
88
+ sendButton: string;
89
+ background: string;
90
+ };
91
+ };
92
+ loading: {
93
+ true: {
94
+ sendButton: string;
95
+ };
96
+ };
97
+ disabled: {
98
+ true: {
99
+ sendButton: string;
100
+ };
101
+ };
102
+ }, {
103
+ userMessage: string;
104
+ aiMessage: string;
105
+ sendButton: string;
106
+ background: string;
107
+ }, import("tailwind-variants").TVReturnType<{
108
+ color: {
109
+ default: {
110
+ userMessage: string;
111
+ sendButton: string;
112
+ background: string;
113
+ };
114
+ primary: {
115
+ userMessage: string;
116
+ sendButton: string;
117
+ background: string;
118
+ };
119
+ secondary: {
120
+ userMessage: string;
121
+ sendButton: string;
122
+ background: string;
123
+ };
124
+ success: {
125
+ userMessage: string;
126
+ sendButton: string;
127
+ background: string;
128
+ };
129
+ warning: {
130
+ userMessage: string;
131
+ sendButton: string;
132
+ background: string;
133
+ };
134
+ danger: {
135
+ userMessage: string;
136
+ sendButton: string;
137
+ background: string;
138
+ };
139
+ info: {
140
+ userMessage: string;
141
+ sendButton: string;
142
+ background: string;
143
+ };
144
+ };
145
+ loading: {
146
+ true: {
147
+ sendButton: string;
148
+ };
149
+ };
150
+ disabled: {
151
+ true: {
152
+ sendButton: string;
153
+ };
154
+ };
155
+ }, {
156
+ userMessage: string;
157
+ aiMessage: string;
158
+ sendButton: string;
159
+ background: string;
160
+ }, undefined, unknown, unknown, undefined>>;
161
+ export type AIChatInterfaceVariants = Parameters<typeof aiChatInterface>[0];
@@ -0,0 +1,63 @@
1
+ import { tv } from 'tailwind-variants';
2
+ export const aiChatInterface = tv({
3
+ slots: {
4
+ userMessage: 'max-w-[70%] ml-auto px-4 py-3 rounded-3xl text-sm leading-relaxed shadow-lg',
5
+ aiMessage: 'max-w-[80%] mr-auto px-4 py-3 rounded-3xl text-sm leading-relaxed bg-white border border-default-200 text-default-900 shadow-sm',
6
+ sendButton: 'flex-shrink-0 w-11 h-11 rounded-full flex items-center justify-center transition-all duration-200 shadow-sm hover:shadow-md',
7
+ background: ''
8
+ },
9
+ variants: {
10
+ color: {
11
+ default: {
12
+ userMessage: 'bg-default-900 text-white',
13
+ sendButton: 'bg-default-900 hover:bg-default-800 text-white disabled:bg-default-300 disabled:text-default-500',
14
+ background: 'bg-gray-50'
15
+ },
16
+ primary: {
17
+ userMessage: 'bg-primary-600 text-white',
18
+ sendButton: 'bg-primary-600 hover:bg-primary-700 text-white disabled:bg-primary-300 disabled:text-primary-100',
19
+ background: 'bg-blue-50'
20
+ },
21
+ secondary: {
22
+ userMessage: 'bg-secondary-600 text-white',
23
+ sendButton: 'bg-secondary-600 hover:bg-secondary-700 text-white disabled:bg-secondary-300 disabled:text-secondary-100',
24
+ background: 'bg-purple-50'
25
+ },
26
+ success: {
27
+ userMessage: 'bg-success-600 text-white',
28
+ sendButton: 'bg-success-600 hover:bg-success-700 text-white disabled:bg-success-300 disabled:text-success-100',
29
+ background: 'bg-green-50'
30
+ },
31
+ warning: {
32
+ userMessage: 'bg-warning-600 text-white',
33
+ sendButton: 'bg-warning-600 hover:bg-warning-700 text-white disabled:bg-warning-300 disabled:text-warning-100',
34
+ background: 'bg-yellow-50'
35
+ },
36
+ danger: {
37
+ userMessage: 'bg-danger-600 text-white',
38
+ sendButton: 'bg-danger-600 hover:bg-danger-700 text-white disabled:bg-danger-300 disabled:text-danger-100',
39
+ background: 'bg-red-50'
40
+ },
41
+ info: {
42
+ userMessage: 'bg-info-600 text-white',
43
+ sendButton: 'bg-info-600 hover:bg-info-700 text-white disabled:bg-info-300 disabled:text-info-100',
44
+ background: 'bg-cyan-50'
45
+ }
46
+ },
47
+ loading: {
48
+ true: {
49
+ sendButton: 'cursor-not-allowed'
50
+ }
51
+ },
52
+ disabled: {
53
+ true: {
54
+ sendButton: 'cursor-not-allowed opacity-50'
55
+ }
56
+ }
57
+ },
58
+ defaultVariants: {
59
+ color: 'primary',
60
+ loading: false,
61
+ disabled: false
62
+ }
63
+ });
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Content detection utilities for AI chat messages
3
+ */
4
+ export interface CodeBlock {
5
+ language: string;
6
+ code: string;
7
+ startIndex: number;
8
+ endIndex: number;
9
+ }
10
+ export interface MermaidBlock {
11
+ diagram: string;
12
+ startIndex: number;
13
+ endIndex: number;
14
+ }
15
+ export interface ContentSegment {
16
+ type: 'text' | 'code' | 'mermaid';
17
+ content: string;
18
+ language?: string;
19
+ startIndex: number;
20
+ endIndex: number;
21
+ }
22
+ /**
23
+ * Detects if content contains Mermaid diagram syntax
24
+ */
25
+ export declare function detectMermaidDiagrams(content: string): MermaidBlock[];
26
+ /**
27
+ * Detects code blocks in content
28
+ */
29
+ export declare function detectCodeBlocks(content: string): CodeBlock[];
30
+ /**
31
+ * Parses content into segments (text, code, mermaid)
32
+ */
33
+ export declare function parseContentSegments(content: string): ContentSegment[];
34
+ /**
35
+ * Simple check if content contains any Mermaid diagrams
36
+ */
37
+ export declare function hasMermaidDiagrams(content: string): boolean;
38
+ /**
39
+ * Simple check if content contains any code blocks
40
+ */
41
+ export declare function hasCodeBlocks(content: string): boolean;
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Content detection utilities for AI chat messages
3
+ */
4
+ /**
5
+ * Detects if content contains Mermaid diagram syntax
6
+ */
7
+ export function detectMermaidDiagrams(content) {
8
+ const mermaidBlocks = [];
9
+ // Pattern to match mermaid code blocks
10
+ // Handles various Mermaid diagram types and whitespace scenarios
11
+ const mermaidRegex = /```(?:mermaid|graph|flowchart|sequenceDiagram|classDiagram|stateDiagram|stateDiagram-v2|erDiagram|journey|gantt|pie|gitgraph|mindmap)\s*\r?\n([\s\S]*?)\r?\n```/gi;
12
+ let match;
13
+ while ((match = mermaidRegex.exec(content)) !== null) {
14
+ mermaidBlocks.push({
15
+ diagram: match[1].trim(),
16
+ startIndex: match.index,
17
+ endIndex: match.index + match[0].length
18
+ });
19
+ }
20
+ return mermaidBlocks;
21
+ }
22
+ /**
23
+ * Detects code blocks in content
24
+ */
25
+ export function detectCodeBlocks(content) {
26
+ const codeBlocks = [];
27
+ // Pattern to match code blocks with language specification
28
+ // Handles: ```language, ```, and various whitespace scenarios
29
+ const codeRegex = /```(\w+)?\s*\r?\n([\s\S]*?)\r?\n```/gi;
30
+ let match;
31
+ while ((match = codeRegex.exec(content)) !== null) {
32
+ const language = match[1] || 'text';
33
+ const code = match[2].trim();
34
+ // Skip empty code blocks
35
+ if (!code) {
36
+ continue;
37
+ }
38
+ // Skip if it's a mermaid diagram (handled separately)
39
+ if (!isMermaidLanguage(language)) {
40
+ codeBlocks.push({
41
+ language,
42
+ code,
43
+ startIndex: match.index,
44
+ endIndex: match.index + match[0].length
45
+ });
46
+ }
47
+ }
48
+ return codeBlocks;
49
+ }
50
+ /**
51
+ * Checks if a language identifier is for Mermaid diagrams
52
+ */
53
+ function isMermaidLanguage(language) {
54
+ const mermaidLanguages = [
55
+ 'mermaid',
56
+ 'graph',
57
+ 'flowchart',
58
+ 'sequenceDiagram',
59
+ 'classDiagram',
60
+ 'stateDiagram',
61
+ 'stateDiagram-v2',
62
+ 'erDiagram',
63
+ 'journey',
64
+ 'gantt',
65
+ 'pie',
66
+ 'gitgraph',
67
+ 'mindmap'
68
+ ];
69
+ return mermaidLanguages.includes(language.toLowerCase());
70
+ }
71
+ /**
72
+ * Parses content into segments (text, code, mermaid)
73
+ */
74
+ export function parseContentSegments(content) {
75
+ console.log('parseContentSegments', content);
76
+ const segments = [];
77
+ const mermaidBlocks = detectMermaidDiagrams(content);
78
+ const codeBlocks = detectCodeBlocks(content);
79
+ // Combine all blocks and sort by position
80
+ const allBlocks = [
81
+ ...mermaidBlocks.map(block => ({ ...block, type: 'mermaid' })),
82
+ ...codeBlocks.map(block => ({ ...block, type: 'code' }))
83
+ ].sort((a, b) => a.startIndex - b.startIndex);
84
+ let currentIndex = 0;
85
+ for (const block of allBlocks) {
86
+ // Add text segment before this block
87
+ if (currentIndex < block.startIndex) {
88
+ const textContent = content.slice(currentIndex, block.startIndex).trim();
89
+ if (textContent) {
90
+ segments.push({
91
+ type: 'text',
92
+ content: textContent,
93
+ startIndex: currentIndex,
94
+ endIndex: block.startIndex
95
+ });
96
+ }
97
+ }
98
+ // Add the block segment
99
+ if (block.type === 'mermaid') {
100
+ segments.push({
101
+ type: 'mermaid',
102
+ content: block.diagram,
103
+ startIndex: block.startIndex,
104
+ endIndex: block.endIndex
105
+ });
106
+ }
107
+ else {
108
+ const codeBlock = block;
109
+ segments.push({
110
+ type: 'code',
111
+ content: codeBlock.code,
112
+ language: codeBlock.language,
113
+ startIndex: block.startIndex,
114
+ endIndex: block.endIndex
115
+ });
116
+ }
117
+ currentIndex = block.endIndex;
118
+ }
119
+ // Add remaining text after last block
120
+ if (currentIndex < content.length) {
121
+ const textContent = content.slice(currentIndex).trim();
122
+ if (textContent) {
123
+ segments.push({
124
+ type: 'text',
125
+ content: textContent,
126
+ startIndex: currentIndex,
127
+ endIndex: content.length
128
+ });
129
+ }
130
+ }
131
+ // If no blocks found, return entire content as text
132
+ if (segments.length === 0) {
133
+ segments.push({
134
+ type: 'text',
135
+ content: content,
136
+ startIndex: 0,
137
+ endIndex: content.length
138
+ });
139
+ }
140
+ return segments;
141
+ }
142
+ /**
143
+ * Simple check if content contains any Mermaid diagrams
144
+ */
145
+ export function hasMermaidDiagrams(content) {
146
+ return detectMermaidDiagrams(content).length > 0;
147
+ }
148
+ /**
149
+ * Simple check if content contains any code blocks
150
+ */
151
+ export function hasCodeBlocks(content) {
152
+ return detectCodeBlocks(content).length > 0;
153
+ }
@@ -0,0 +1,13 @@
1
+ export interface AIConfig {
2
+ provider: 'openai' | 'anthropic' | 'ollama';
3
+ apiKey?: string;
4
+ model?: string;
5
+ baseUrl?: string;
6
+ }
7
+ export declare function getAIConfig(): AIConfig;
8
+ export declare function validateAIConfig(config: AIConfig): boolean;
9
+ export declare const ENV_GUIDE: {
10
+ openai: string[];
11
+ anthropic: string[];
12
+ ollama: string[];
13
+ };
@@ -0,0 +1,43 @@
1
+ import { browser } from '$app/environment';
2
+ import { dev } from '$app/environment';
3
+ export function getAIConfig() {
4
+ if (!browser) {
5
+ return {
6
+ provider: 'openai'
7
+ };
8
+ }
9
+ const config = {
10
+ provider: import.meta.env.VITE_AI_PROVIDER || 'openai',
11
+ apiKey: import.meta.env.VITE_OPENAI_API_KEY,
12
+ model: import.meta.env.VITE_OPENAI_MODEL || 'gpt-4-turbo-preview',
13
+ baseUrl: import.meta.env.VITE_OPENAI_BASE_URL || 'https://api.openai.com/v1'
14
+ };
15
+ // In development, provide helpful warnings
16
+ if (dev && !config.apiKey && config.provider === 'openai') {
17
+ console.warn('⚠️ OpenAI API key not found. Set VITE_OPENAI_API_KEY in your .env file');
18
+ console.warn('💡 Create a .env file with: VITE_OPENAI_API_KEY=sk-your-key-here');
19
+ }
20
+ return config;
21
+ }
22
+ export function validateAIConfig(config) {
23
+ switch (config.provider) {
24
+ case 'openai':
25
+ return !!config.apiKey;
26
+ case 'anthropic':
27
+ return !!config.apiKey;
28
+ case 'ollama':
29
+ return !!config.baseUrl;
30
+ default:
31
+ return false;
32
+ }
33
+ }
34
+ // Environment variables guide
35
+ export const ENV_GUIDE = {
36
+ openai: [
37
+ 'VITE_OPENAI_API_KEY=sk-your-openai-key',
38
+ 'VITE_OPENAI_MODEL=gpt-4-turbo-preview (optional)',
39
+ 'VITE_OPENAI_BASE_URL=https://api.openai.com/v1 (optional)'
40
+ ],
41
+ anthropic: ['VITE_ANTHROPIC_API_KEY=your-anthropic-key', 'VITE_AI_PROVIDER=anthropic'],
42
+ ollama: ['VITE_OLLAMA_BASE_URL=http://localhost:11434', 'VITE_AI_PROVIDER=ollama']
43
+ };
@@ -5,7 +5,7 @@ export const accordion = tv({
5
5
  base: 'w-full relative overflow-hidden rounded-xl transition-all duration-200 bg-white border border-default-200',
6
6
  header: 'w-full flex cursor-pointer items-center justify-between p-4 transition-colors duration-200',
7
7
  title: 'flex text-default-900 text-lg font-medium leading-tight',
8
- body: 'w-full border-t border-default-200 p-4 pt-3 transition-all',
8
+ body: 'w-full border-t border-default-200 p-4 pt-3 transition-all'
9
9
  },
10
10
  variants: {
11
11
  color: {
@@ -30,9 +30,20 @@
30
30
  {@render children()}
31
31
  {#if onClose}
32
32
  <button
33
- onclick={handleOnClose} class="cursor-pointer h-full flex items-center" aria-label="Close" title="Close"
34
- tabindex="0" type="button">
35
- <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" class="size-2">
33
+ onclick={handleOnClose}
34
+ class="flex h-full cursor-pointer items-center"
35
+ aria-label="Close"
36
+ title="Close"
37
+ tabindex="0"
38
+ type="button"
39
+ >
40
+ <svg
41
+ xmlns="http://www.w3.org/2000/svg"
42
+ width="32"
43
+ height="32"
44
+ viewBox="0 0 32 32"
45
+ class="size-2"
46
+ >
36
47
  <path
37
48
  fill="currentColor"
38
49
  d="M26.113 4.116a1.25 1.25 0 0 1 1.768 1.768L17.766 15.999l10.115 10.114a1.25 1.25 0 1 1-1.768 1.768L16 17.766L5.884 27.881a1.25 1.25 0 1 1-1.768-1.768L14.231 16L4.116 5.884a1.25 1.25 0 1 1 1.768-1.768l10.115 10.115z"
@@ -116,9 +116,9 @@
116
116
  function handleClickOutside(event: MouseEvent) {
117
117
  // Only handle if this specific dropdown is open
118
118
  if (!isOpen) return;
119
-
119
+
120
120
  const target = event.target as Node;
121
-
121
+
122
122
  // Check if click is outside both the dropdown and trigger
123
123
  if (
124
124
  dropdownRef &&
@@ -208,7 +208,7 @@
208
208
  {disabled}
209
209
  aria-expanded={open}
210
210
  onclick={handleToggle}
211
- class="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
211
+ class="absolute inset-0 h-full w-full cursor-pointer opacity-0"
212
212
  tabindex={disabled ? -1 : 0}
213
213
  ></button>
214
214
  <span class="flex min-h-[1.5rem] flex-1 flex-wrap items-center gap-1 overflow-hidden">
@@ -45,7 +45,7 @@
45
45
  // Derived values
46
46
  const percentage = $derived(segments ? 100 : calculatePercentage(value, max));
47
47
  const segmentPercentages = $derived(
48
- segments?.map(segment => ({
48
+ segments?.map((segment) => ({
49
49
  ...segment,
50
50
  percentage: calculatePercentage(segment.value, max)
51
51
  })) || []
@@ -78,11 +78,7 @@
78
78
  );
79
79
 
80
80
  const fillClass = $derived(
81
- cn(
82
- 'h-full rounded-full transition-all',
83
- segments ? '' : getColorClass(color),
84
- barClass
85
- )
81
+ cn('h-full rounded-full transition-all', segments ? '' : getColorClass(color), barClass)
86
82
  );
87
83
 
88
84
  const labelTextClass = $derived(
@@ -110,7 +106,7 @@
110
106
  {#if segments}
111
107
  {#each segmentPercentages as segment}
112
108
  {#if segment.percentage > 0}
113
- <div
109
+ <div
114
110
  class={cn(getColorClass(segment.color), barClass)}
115
111
  style="width: {segment.percentage}%"
116
112
  title={segment.label || `${segment.value} (${segment.percentage}%)`}
@@ -121,9 +117,9 @@
121
117
  <div class={fillClass} style="width: {percentage}%"></div>
122
118
  {/if}
123
119
  </div>
124
-
120
+
125
121
  {#if segments && (showLabels || showValues)}
126
- <div class="flex justify-between mt-1">
122
+ <div class="mt-1 flex justify-between">
127
123
  {#each segmentPercentages as segment}
128
124
  {#if segment.percentage > 0}
129
125
  <div class={labelTextClass}>
@@ -131,7 +127,8 @@
131
127
  {segment.label}
132
128
  {/if}
133
129
  {#if showValues}
134
- {#if showLabels && segment.label} ({/if}
130
+ {#if showLabels && segment.label}
131
+ ({/if}
135
132
  {segment.percentage}%
136
133
  {#if showLabels && segment.label}){/if}
137
134
  {/if}
@@ -9,7 +9,7 @@
9
9
  Breadcrumb,
10
10
  FileAction,
11
11
  FileActionBatch,
12
- FileActionSingle,
12
+ FileActionSingle
13
13
  } from '../adapters/storage/index.js';
14
14
 
15
15
  let {