chordia-ui 3.2.2 → 3.2.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.
@@ -0,0 +1,255 @@
1
+ import { useState } from 'react';
2
+ import { Upload, CircleUser, Compass, Link2 } from 'lucide-react';
3
+
4
+ const FF = 'var(--font-sans)';
5
+
6
+ // ─── Styles ───
7
+
8
+ const containerStyle = {
9
+ padding: '40px 48px',
10
+ fontFamily: FF,
11
+ minHeight: '100vh',
12
+ background: 'var(--grey-white)',
13
+ boxSizing: 'border-box',
14
+ };
15
+
16
+ const headingStyle = {
17
+ fontSize: 'var(--text-4xl)',
18
+ fontWeight: 'var(--font-bold)',
19
+ fontFamily: FF,
20
+ color: 'var(--text-ink)',
21
+ margin: 0,
22
+ letterSpacing: 'var(--tracking-tight)',
23
+ lineHeight: 'var(--leading-tight)',
24
+ };
25
+
26
+ const subtitleStyle = {
27
+ fontSize: 14,
28
+ fontStyle: 'normal',
29
+ fontWeight: 400,
30
+ lineHeight: '140%',
31
+ color: 'var(--color-text-secondary)',
32
+ margin: '8px 0 0',
33
+ fontFamily: FF,
34
+ };
35
+
36
+ const gridStyle = {
37
+ display: 'grid',
38
+ gridTemplateColumns: '1fr 1fr',
39
+ gap: 12,
40
+ marginTop: '36px',
41
+ };
42
+
43
+ const cardStyle = {
44
+ display: 'flex',
45
+ height: 160,
46
+ padding: 24,
47
+ flexDirection: 'column',
48
+ justifyContent: 'space-between',
49
+ alignItems: 'flex-start',
50
+ borderRadius: 12,
51
+ border: '1px solid var(--grey-absent)',
52
+ background: 'var(--grey-white)',
53
+ boxSizing: 'border-box',
54
+ transition: 'var(--transition)',
55
+ cursor: 'default',
56
+ gap: 8
57
+ };
58
+
59
+ const cardHoverStyle = {
60
+ ...cardStyle,
61
+ boxShadow: 'var(--shadow-sm)',
62
+ };
63
+
64
+ const iconWrapperStyle = {
65
+ width: 40,
66
+ height: 40,
67
+ borderRadius: 'var(--radius)',
68
+ background: 'var(--paper-secondary)',
69
+ display: 'flex',
70
+ alignItems: 'center',
71
+ justifyContent: 'center',
72
+ color: 'var(--text-base)',
73
+ };
74
+
75
+ const cardTitleStyle = {
76
+ color: 'var(--grey-strong)',
77
+ fontSize: 20,
78
+ fontStyle: 'normal',
79
+ fontWeight: 600,
80
+ lineHeight: 'normal',
81
+ fontFamily: FF,
82
+ margin: 0,
83
+ };
84
+
85
+ const cardDescStyle = {
86
+ fontSize: 13,
87
+ fontStyle: 'normal',
88
+ fontWeight: 400,
89
+ lineHeight: '140%',
90
+ color: 'var(--text-base)',
91
+ margin: 0,
92
+ fontFamily: FF,
93
+ flex: '1 0 0',
94
+ };
95
+
96
+ const btnStyle = {
97
+ display: 'flex',
98
+ height: 28,
99
+ padding: 10,
100
+ justifyContent: 'center',
101
+ alignItems: 'center',
102
+ gap: 10,
103
+ borderRadius: 10,
104
+ background: 'var(--grey-strong)',
105
+ fontSize: 14,
106
+ fontStyle: 'normal',
107
+ fontWeight: 600,
108
+ lineHeight: 1,
109
+ fontFamily: FF,
110
+ color: 'var(--grey-white)',
111
+ border: 'none',
112
+ cursor: 'pointer',
113
+ transition: 'var(--transition-fast)',
114
+ outline: 'none',
115
+ boxSizing: 'border-box',
116
+ };
117
+
118
+ const progressBarBg = {
119
+ flex: 1,
120
+ height: 8,
121
+ borderRadius: 4,
122
+ background: 'var(--border)',
123
+ overflow: 'hidden',
124
+ };
125
+
126
+ const progressBarFill = (pct) => ({
127
+ width: `${pct}%`,
128
+ height: '100%',
129
+ borderRadius: 4,
130
+ background: 'var(--color-green)',
131
+ transition: 'width 0.4s ease-out',
132
+ });
133
+
134
+ const recommendedBadge = {
135
+ display: 'inline-flex',
136
+ alignItems: 'center',
137
+ gap: 4,
138
+ fontSize: 'var(--text-xs)',
139
+ fontWeight: 'var(--font-semibold)',
140
+ color: 'var(--rail-compliance)',
141
+ fontFamily: FF,
142
+ marginLeft: 12,
143
+ };
144
+
145
+ // ─── Card Component ───
146
+
147
+ function OnboardingCard({ icon, title, description, buttonLabel, onAction, recommended, children }) {
148
+ const [hovered, setHovered] = useState(false);
149
+
150
+ return (
151
+ <div
152
+ style={hovered ? cardHoverStyle : cardStyle}
153
+ onMouseEnter={() => setHovered(true)}
154
+ onMouseLeave={() => setHovered(false)}
155
+ >
156
+ <div>
157
+ <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
158
+ <div style={iconWrapperStyle}>{icon}</div>
159
+ <h3 style={cardTitleStyle}>{title}</h3>
160
+ </div>
161
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginLeft: 52, marginTop: 4 }}>
162
+ {description && <p style={cardDescStyle}>{description}</p>}
163
+ {children}
164
+ </div>
165
+ </div>
166
+ <div style={{ display: 'flex', alignItems: 'center', marginLeft: 52 }}>
167
+ <button
168
+ style={btnStyle}
169
+ onClick={onAction}
170
+ onMouseEnter={(e) => { e.currentTarget.style.opacity = '0.85'; }}
171
+ onMouseLeave={(e) => { e.currentTarget.style.opacity = '1'; }}
172
+ >
173
+ {buttonLabel}
174
+ </button>
175
+ {recommended && (
176
+ <span style={recommendedBadge}>
177
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" /></svg>
178
+ Recommended
179
+ </span>
180
+ )}
181
+ </div>
182
+ </div>
183
+ );
184
+ }
185
+
186
+ // ─── Main Component ───
187
+
188
+ const UploadEvaluate = ({
189
+ userName = 'Will',
190
+ stepsCompleted = 4,
191
+ totalSteps = 6,
192
+ onUpload,
193
+ onContinue,
194
+ onExplore,
195
+ onConnect,
196
+ }) => {
197
+ const progressPct = (stepsCompleted / totalSteps) * 100;
198
+
199
+ return (
200
+ <div style={containerStyle}>
201
+ <h1 style={headingStyle}>Welcome {userName}</h1>
202
+ <p style={subtitleStyle}>Get started with your project or explore new features</p>
203
+
204
+ <div style={gridStyle}>
205
+ {/* Upload and Evaluate Audio */}
206
+ <OnboardingCard
207
+ icon={<Upload size={24} />}
208
+ title="Upload and Evaluate Audio"
209
+ description="Upload Audio Files to Run Evaluations: MP3, WMA or WAV (up to 50 files, max 325MB total)"
210
+ buttonLabel="Upload"
211
+ onAction={onUpload}
212
+ />
213
+
214
+ {/* Getting started with Chordia */}
215
+ <OnboardingCard
216
+ icon={<CircleUser size={24} />}
217
+ title="Getting started with Chordia"
218
+ description="Complete these steps to get the most out of Chordia."
219
+ buttonLabel="Continue"
220
+ onAction={onContinue}
221
+ >
222
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, width: '100%' }}>
223
+ <div style={progressBarBg}>
224
+ <div style={progressBarFill(progressPct)} />
225
+ </div>
226
+ <span style={{ fontSize: 12, color: 'var(--text-muted)', fontFamily: FF, whiteSpace: 'nowrap' }}>
227
+ <strong style={{ color: 'var(--text-base)', fontWeight: 600 }}>{stepsCompleted}</strong> of {totalSteps} steps completed
228
+ </span>
229
+ </div>
230
+ </OnboardingCard>
231
+
232
+ {/* Explore Demo Projects */}
233
+ <OnboardingCard
234
+ icon={<Compass size={24} />}
235
+ title="Explore Demo Projects"
236
+ description="Explore how Chordia Compass transforms real data into insights with plans, dashboards, and evaluations."
237
+ buttonLabel="Explore"
238
+ onAction={onExplore}
239
+ recommended
240
+ />
241
+
242
+ {/* Connect Data Source */}
243
+ <OnboardingCard
244
+ icon={<Link2 size={24} />}
245
+ title="Connect Data Source"
246
+ description="Connect and integrate third-party tools with your external data sources."
247
+ buttonLabel="Connect"
248
+ onAction={onConnect}
249
+ />
250
+ </div>
251
+ </div>
252
+ );
253
+ };
254
+
255
+ export default UploadEvaluate;
@@ -0,0 +1,186 @@
1
+ import { useState, useRef } from 'react';
2
+ import { CloudUpload } from 'lucide-react';
3
+
4
+ const FF = 'var(--font-sans)';
5
+
6
+ // ─── Styles ───
7
+
8
+ const containerStyle = {
9
+ fontFamily: FF,
10
+ };
11
+
12
+ const sectionTitleStyle = {
13
+ fontSize: 20,
14
+ fontWeight: 600,
15
+ fontStyle: 'normal',
16
+ fontFamily: FF,
17
+ color: 'var(--grey-strong)',
18
+ margin: 0,
19
+ lineHeight: 'normal',
20
+ };
21
+
22
+ const sectionSubtitleStyle = {
23
+ fontSize: 13,
24
+ fontWeight: 400,
25
+ fontStyle: 'normal',
26
+ color: 'var(--color-text-secondary)',
27
+ fontFamily: FF,
28
+ margin: '4px 0 0',
29
+ lineHeight: '140%',
30
+ };
31
+
32
+ const dropzoneStyle = {
33
+ display: 'flex',
34
+ flexDirection: 'column',
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ width: '100%',
38
+ minHeight: 320,
39
+ borderRadius: 16,
40
+ border: '2px dashed var(--color-input-border)',
41
+ background: 'var(--grey-white)',
42
+ boxSizing: 'border-box',
43
+ cursor: 'pointer',
44
+ transition: 'var(--transition-fast)',
45
+ marginTop: 24,
46
+ padding: '48px 24px',
47
+ };
48
+
49
+ const dropzoneHoverStyle = {
50
+ ...dropzoneStyle,
51
+ borderColor: 'var(--color-green)',
52
+ background: 'var(--color-green-ring)',
53
+ };
54
+
55
+ const dropzoneIconWrap = {
56
+ width: 80,
57
+ height: 80,
58
+ borderRadius: 9999,
59
+ background: 'var(--focus-2)',
60
+ display: 'flex',
61
+ alignItems: 'center',
62
+ justifyContent: 'center',
63
+ flexShrink: 0,
64
+ marginBottom: 20,
65
+ };
66
+
67
+ const dropzoneTextStyle = {
68
+ fontSize: 18,
69
+ fontWeight: 600,
70
+ fontFamily: FF,
71
+ color: 'var(--grey-strong)',
72
+ textAlign: 'center',
73
+ lineHeight: '28px',
74
+ margin: 0,
75
+ };
76
+
77
+ const browseButtonStyle = {
78
+ display: 'flex',
79
+ height: 32,
80
+ padding: 16,
81
+ justifyContent: 'center',
82
+ alignItems: 'center',
83
+ gap: 10,
84
+ borderRadius: 10,
85
+ border: '1px solid var(--grey-absent)',
86
+ background: 'var(--grey-white)',
87
+ fontSize: 15,
88
+ fontWeight: 400,
89
+ fontFamily: FF,
90
+ color: 'var(--grey-strong)',
91
+ cursor: 'pointer',
92
+ transition: 'var(--transition-fast)',
93
+ outline: 'none',
94
+ marginTop: 16,
95
+ boxSizing: 'border-box',
96
+ };
97
+
98
+ const dropzoneHintStyle = {
99
+ fontSize: 14,
100
+ fontWeight: 400,
101
+ fontFamily: FF,
102
+ color: 'var(--grey-muted)',
103
+ textAlign: 'center',
104
+ marginTop: 16,
105
+ lineHeight: '140%',
106
+ };
107
+
108
+ // ─── Component ───
109
+
110
+ const UploadInteraction = ({ onFileSelect }) => {
111
+ const [dragOver, setDragOver] = useState(false);
112
+ const fileInputRef = useRef(null);
113
+
114
+ const handleDragOver = (e) => {
115
+ e.preventDefault();
116
+ setDragOver(true);
117
+ };
118
+
119
+ const handleDragLeave = () => {
120
+ setDragOver(false);
121
+ };
122
+
123
+ const handleDrop = (e) => {
124
+ e.preventDefault();
125
+ setDragOver(false);
126
+ const files = e.dataTransfer?.files;
127
+ if (files?.length) {
128
+ onFileSelect?.(files);
129
+ }
130
+ };
131
+
132
+ const handleBrowseClick = () => {
133
+ fileInputRef.current?.click();
134
+ };
135
+
136
+ const handleFileChange = (e) => {
137
+ const files = e.target.files;
138
+ if (files?.length) {
139
+ onFileSelect?.(files);
140
+ }
141
+ e.target.value = '';
142
+ };
143
+
144
+ return (
145
+ <div style={containerStyle}>
146
+ <h2 style={sectionTitleStyle}>Evaluate Interaction</h2>
147
+ <p style={sectionSubtitleStyle}>
148
+ Upload another interaction to compare results and identify patterns across multiple evaluations.
149
+ </p>
150
+
151
+ <input
152
+ ref={fileInputRef}
153
+ type="file"
154
+ accept=".mp3,.wma,.wav"
155
+ multiple
156
+ style={{ display: 'none' }}
157
+ onChange={handleFileChange}
158
+ />
159
+
160
+ <div
161
+ style={dragOver ? dropzoneHoverStyle : dropzoneStyle}
162
+ onDragOver={handleDragOver}
163
+ onDragLeave={handleDragLeave}
164
+ onDrop={handleDrop}
165
+ onClick={handleBrowseClick}
166
+ >
167
+ <div style={dropzoneIconWrap}>
168
+ <CloudUpload size={32} color="var(--grey-strong)" />
169
+ </div>
170
+ <p style={dropzoneTextStyle}>Drop your file here, or</p>
171
+ <button
172
+ type="button"
173
+ style={browseButtonStyle}
174
+ onClick={(e) => { e.stopPropagation(); handleBrowseClick(); }}
175
+ onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--hover-warm-subtle)'; }}
176
+ onMouseLeave={(e) => { e.currentTarget.style.background = 'var(--grey-white)'; }}
177
+ >
178
+ Browse files
179
+ </button>
180
+ <p style={dropzoneHintStyle}>Supports: MP3, WMA or WAV</p>
181
+ </div>
182
+ </div>
183
+ );
184
+ };
185
+
186
+ export default UploadInteraction;
@@ -187,6 +187,19 @@
187
187
  --color-error-ring: rgba(237, 128, 119, 0.12);
188
188
  --color-error-bg: #F3F7F7;
189
189
 
190
+ /* ============================================
191
+ GREY SCALE (Figma Chordia Colors)
192
+ ============================================ */
193
+ --grey-white: #FFFFFF;
194
+ --grey-absent: #D9D9D9;
195
+ --grey-muted: #BDBDBD;
196
+ --grey-strong: var(--color-text);
197
+
198
+ /* ============================================
199
+ FOCUS / WARM SURFACES
200
+ ============================================ */
201
+ --focus-2: #FAF5E9;
202
+
190
203
  /* ============================================
191
204
  GRADIENTS
192
205
  ============================================ */