@xeplr/ui-utils 1.0.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.
@@ -0,0 +1,296 @@
1
+ {
2
+ "STATES": {
3
+ "IN": [
4
+ {
5
+ "code": "AN",
6
+ "name": "Andaman and Nicobar Islands"
7
+ },
8
+ {
9
+ "code": "AP",
10
+ "name": "Andhra Pradesh"
11
+ },
12
+ {
13
+ "code": "AR",
14
+ "name": "Arunachal Pradesh"
15
+ },
16
+ {
17
+ "code": "AS",
18
+ "name": "Assam"
19
+ },
20
+ {
21
+ "code": "BR",
22
+ "name": "Bihar"
23
+ },
24
+ {
25
+ "code": "CH",
26
+ "name": "Chandigarh"
27
+ },
28
+ {
29
+ "code": "CT",
30
+ "name": "Chhattisgarh"
31
+ },
32
+ {
33
+ "code": "DN",
34
+ "name": "Dadra and Nagar Haveli and Daman and Diu"
35
+ },
36
+ {
37
+ "code": "DL",
38
+ "name": "Delhi"
39
+ },
40
+ {
41
+ "code": "GA",
42
+ "name": "Goa"
43
+ },
44
+ {
45
+ "code": "GJ",
46
+ "name": "Gujarat"
47
+ },
48
+ {
49
+ "code": "HR",
50
+ "name": "Haryana"
51
+ },
52
+ {
53
+ "code": "HP",
54
+ "name": "Himachal Pradesh"
55
+ },
56
+ {
57
+ "code": "JK",
58
+ "name": "Jammu and Kashmir"
59
+ },
60
+ {
61
+ "code": "JH",
62
+ "name": "Jharkhand"
63
+ },
64
+ {
65
+ "code": "KA",
66
+ "name": "Karnataka"
67
+ },
68
+ {
69
+ "code": "KL",
70
+ "name": "Kerala"
71
+ },
72
+ {
73
+ "code": "LA",
74
+ "name": "Ladakh"
75
+ },
76
+ {
77
+ "code": "LD",
78
+ "name": "Lakshadweep"
79
+ },
80
+ {
81
+ "code": "MP",
82
+ "name": "Madhya Pradesh"
83
+ },
84
+ {
85
+ "code": "MH",
86
+ "name": "Maharashtra"
87
+ },
88
+ {
89
+ "code": "MN",
90
+ "name": "Manipur"
91
+ },
92
+ {
93
+ "code": "ML",
94
+ "name": "Meghalaya"
95
+ },
96
+ {
97
+ "code": "MZ",
98
+ "name": "Mizoram"
99
+ },
100
+ {
101
+ "code": "NL",
102
+ "name": "Nagaland"
103
+ },
104
+ {
105
+ "code": "OR",
106
+ "name": "Odisha"
107
+ },
108
+ {
109
+ "code": "PY",
110
+ "name": "Puducherry"
111
+ },
112
+ {
113
+ "code": "PB",
114
+ "name": "Punjab"
115
+ },
116
+ {
117
+ "code": "RJ",
118
+ "name": "Rajasthan"
119
+ },
120
+ {
121
+ "code": "SK",
122
+ "name": "Sikkim"
123
+ },
124
+ {
125
+ "code": "TN",
126
+ "name": "Tamil Nadu"
127
+ },
128
+ {
129
+ "code": "TG",
130
+ "name": "Telangana"
131
+ },
132
+ {
133
+ "code": "TR",
134
+ "name": "Tripura"
135
+ },
136
+ {
137
+ "code": "UP",
138
+ "name": "Uttar Pradesh"
139
+ },
140
+ {
141
+ "code": "UT",
142
+ "name": "Uttarakhand"
143
+ },
144
+ {
145
+ "code": "WB",
146
+ "name": "West Bengal"
147
+ }
148
+ ]
149
+ },
150
+ "STATES_IN": [
151
+ {
152
+ "code": "AN",
153
+ "name": "Andaman and Nicobar Islands"
154
+ },
155
+ {
156
+ "code": "AP",
157
+ "name": "Andhra Pradesh"
158
+ },
159
+ {
160
+ "code": "AR",
161
+ "name": "Arunachal Pradesh"
162
+ },
163
+ {
164
+ "code": "AS",
165
+ "name": "Assam"
166
+ },
167
+ {
168
+ "code": "BR",
169
+ "name": "Bihar"
170
+ },
171
+ {
172
+ "code": "CH",
173
+ "name": "Chandigarh"
174
+ },
175
+ {
176
+ "code": "CT",
177
+ "name": "Chhattisgarh"
178
+ },
179
+ {
180
+ "code": "DN",
181
+ "name": "Dadra and Nagar Haveli and Daman and Diu"
182
+ },
183
+ {
184
+ "code": "DL",
185
+ "name": "Delhi"
186
+ },
187
+ {
188
+ "code": "GA",
189
+ "name": "Goa"
190
+ },
191
+ {
192
+ "code": "GJ",
193
+ "name": "Gujarat"
194
+ },
195
+ {
196
+ "code": "HR",
197
+ "name": "Haryana"
198
+ },
199
+ {
200
+ "code": "HP",
201
+ "name": "Himachal Pradesh"
202
+ },
203
+ {
204
+ "code": "JK",
205
+ "name": "Jammu and Kashmir"
206
+ },
207
+ {
208
+ "code": "JH",
209
+ "name": "Jharkhand"
210
+ },
211
+ {
212
+ "code": "KA",
213
+ "name": "Karnataka"
214
+ },
215
+ {
216
+ "code": "KL",
217
+ "name": "Kerala"
218
+ },
219
+ {
220
+ "code": "LA",
221
+ "name": "Ladakh"
222
+ },
223
+ {
224
+ "code": "LD",
225
+ "name": "Lakshadweep"
226
+ },
227
+ {
228
+ "code": "MP",
229
+ "name": "Madhya Pradesh"
230
+ },
231
+ {
232
+ "code": "MH",
233
+ "name": "Maharashtra"
234
+ },
235
+ {
236
+ "code": "MN",
237
+ "name": "Manipur"
238
+ },
239
+ {
240
+ "code": "ML",
241
+ "name": "Meghalaya"
242
+ },
243
+ {
244
+ "code": "MZ",
245
+ "name": "Mizoram"
246
+ },
247
+ {
248
+ "code": "NL",
249
+ "name": "Nagaland"
250
+ },
251
+ {
252
+ "code": "OR",
253
+ "name": "Odisha"
254
+ },
255
+ {
256
+ "code": "PY",
257
+ "name": "Puducherry"
258
+ },
259
+ {
260
+ "code": "PB",
261
+ "name": "Punjab"
262
+ },
263
+ {
264
+ "code": "RJ",
265
+ "name": "Rajasthan"
266
+ },
267
+ {
268
+ "code": "SK",
269
+ "name": "Sikkim"
270
+ },
271
+ {
272
+ "code": "TN",
273
+ "name": "Tamil Nadu"
274
+ },
275
+ {
276
+ "code": "TG",
277
+ "name": "Telangana"
278
+ },
279
+ {
280
+ "code": "TR",
281
+ "name": "Tripura"
282
+ },
283
+ {
284
+ "code": "UP",
285
+ "name": "Uttar Pradesh"
286
+ },
287
+ {
288
+ "code": "UT",
289
+ "name": "Uttarakhand"
290
+ },
291
+ {
292
+ "code": "WB",
293
+ "name": "West Bengal"
294
+ }
295
+ ]
296
+ }
@@ -0,0 +1,77 @@
1
+ import './fileUpload.css';
2
+
3
+ function formatSize(bytes) {
4
+ if (bytes < 1024) return bytes + ' B';
5
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
6
+ return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
7
+ }
8
+
9
+ export default function FileUploadSample({
10
+ files, uploading, progress, error, result, dragOver, inputRef,
11
+ handleChange, handleDragOver, handleDragLeave, handleDrop,
12
+ handleUpload, openFilePicker, removeFile, clear,
13
+ allowedTypes, maxSize, maxFiles
14
+ }) {
15
+ return (
16
+ <div className="xeplr-upload-container">
17
+ <div
18
+ className={'xeplr-upload-dropzone' + (dragOver ? ' xeplr-upload-dragover' : '')}
19
+ onDragOver={handleDragOver}
20
+ onDragLeave={handleDragLeave}
21
+ onDrop={handleDrop}
22
+ onClick={openFilePicker}
23
+ >
24
+ <input
25
+ ref={inputRef}
26
+ type="file"
27
+ onChange={handleChange}
28
+ multiple={maxFiles > 1}
29
+ accept={allowedTypes.join(',')}
30
+ className="xeplr-upload-input"
31
+ />
32
+ <div className="xeplr-upload-dropzone-text">
33
+ <p>Drag & drop files here or click to browse</p>
34
+ <p className="xeplr-upload-hint">
35
+ Max {formatSize(maxSize)} per file
36
+ {maxFiles > 1 ? ' · Up to ' + maxFiles + ' files' : ''}
37
+ </p>
38
+ </div>
39
+ </div>
40
+
41
+ {error && <div className="xeplr-upload-alert xeplr-upload-alert-error">{error}</div>}
42
+ {result && <div className="xeplr-upload-alert xeplr-upload-alert-success">Upload complete</div>}
43
+
44
+ {files.length > 0 && (
45
+ <div className="xeplr-upload-file-list">
46
+ {files.map(function(file, i) {
47
+ return (
48
+ <div key={i} className="xeplr-upload-file-item">
49
+ <span className="xeplr-upload-file-name">{file.name}</span>
50
+ <span className="xeplr-upload-file-size">{formatSize(file.size)}</span>
51
+ {!uploading && (
52
+ <button type="button" className="xeplr-upload-file-remove" onClick={function() { removeFile(i); }}>×</button>
53
+ )}
54
+ </div>
55
+ );
56
+ })}
57
+ </div>
58
+ )}
59
+
60
+ {uploading && (
61
+ <div className="xeplr-upload-progress">
62
+ <div className="xeplr-upload-progress-bar" style={{ width: progress + '%' }}></div>
63
+ <span className="xeplr-upload-progress-text">{progress}%</span>
64
+ </div>
65
+ )}
66
+
67
+ <div className="xeplr-upload-actions">
68
+ <button type="button" onClick={handleUpload} disabled={uploading || files.length === 0} className="xeplr-upload-btn xeplr-upload-btn-primary">
69
+ {uploading ? 'Uploading...' : 'Upload'}
70
+ </button>
71
+ <button type="button" onClick={clear} disabled={uploading} className="xeplr-upload-btn xeplr-upload-btn-secondary">
72
+ Clear
73
+ </button>
74
+ </div>
75
+ </div>
76
+ );
77
+ }
@@ -0,0 +1,161 @@
1
+ .xeplr-upload-container {
2
+ max-width: 500px;
3
+ margin: 20px auto;
4
+ font-family: system-ui, -apple-system, sans-serif;
5
+ color: #e0e0e0;
6
+ }
7
+
8
+ .xeplr-upload-dropzone {
9
+ border: 2px dashed #444;
10
+ border-radius: 8px;
11
+ padding: 40px 20px;
12
+ text-align: center;
13
+ cursor: pointer;
14
+ background: #1a1a1a;
15
+ transition: border-color 0.2s, background 0.2s;
16
+ }
17
+
18
+ .xeplr-upload-dropzone:hover {
19
+ border-color: #646cff;
20
+ }
21
+
22
+ .xeplr-upload-dragover {
23
+ border-color: #646cff;
24
+ background: #252540;
25
+ }
26
+
27
+ .xeplr-upload-input {
28
+ display: none;
29
+ }
30
+
31
+ .xeplr-upload-dropzone-text p {
32
+ margin: 5px 0;
33
+ }
34
+
35
+ .xeplr-upload-hint {
36
+ font-size: 12px;
37
+ color: #888;
38
+ }
39
+
40
+ .xeplr-upload-alert {
41
+ margin-top: 10px;
42
+ padding: 8px 12px;
43
+ border-radius: 4px;
44
+ font-size: 14px;
45
+ }
46
+
47
+ .xeplr-upload-alert-error {
48
+ background: #3a1a1a;
49
+ color: #ff6b6b;
50
+ border: 1px solid #5a2a2a;
51
+ }
52
+
53
+ .xeplr-upload-alert-success {
54
+ background: #1a3a1a;
55
+ color: #6bff6b;
56
+ border: 1px solid #2a5a2a;
57
+ }
58
+
59
+ .xeplr-upload-file-list {
60
+ margin-top: 12px;
61
+ }
62
+
63
+ .xeplr-upload-file-item {
64
+ display: flex;
65
+ align-items: center;
66
+ padding: 8px 10px;
67
+ background: #2a2a2a;
68
+ border-radius: 4px;
69
+ margin-bottom: 6px;
70
+ }
71
+
72
+ .xeplr-upload-file-name {
73
+ flex: 1;
74
+ overflow: hidden;
75
+ text-overflow: ellipsis;
76
+ white-space: nowrap;
77
+ font-size: 14px;
78
+ }
79
+
80
+ .xeplr-upload-file-size {
81
+ font-size: 12px;
82
+ color: #888;
83
+ margin: 0 10px;
84
+ }
85
+
86
+ .xeplr-upload-file-remove {
87
+ background: none;
88
+ border: none;
89
+ color: #ff6b6b;
90
+ font-size: 18px;
91
+ cursor: pointer;
92
+ padding: 0 4px;
93
+ line-height: 1;
94
+ }
95
+
96
+ .xeplr-upload-file-remove:hover {
97
+ color: #ff4444;
98
+ }
99
+
100
+ .xeplr-upload-progress {
101
+ margin-top: 12px;
102
+ background: #2a2a2a;
103
+ border-radius: 4px;
104
+ height: 24px;
105
+ position: relative;
106
+ overflow: hidden;
107
+ }
108
+
109
+ .xeplr-upload-progress-bar {
110
+ height: 100%;
111
+ background: #646cff;
112
+ border-radius: 4px;
113
+ transition: width 0.3s;
114
+ }
115
+
116
+ .xeplr-upload-progress-text {
117
+ position: absolute;
118
+ top: 50%;
119
+ left: 50%;
120
+ transform: translate(-50%, -50%);
121
+ font-size: 12px;
122
+ font-weight: 600;
123
+ }
124
+
125
+ .xeplr-upload-actions {
126
+ margin-top: 12px;
127
+ display: flex;
128
+ gap: 8px;
129
+ }
130
+
131
+ .xeplr-upload-btn {
132
+ padding: 8px 20px;
133
+ border: none;
134
+ border-radius: 4px;
135
+ font-size: 14px;
136
+ cursor: pointer;
137
+ }
138
+
139
+ .xeplr-upload-btn:disabled {
140
+ opacity: 0.6;
141
+ cursor: not-allowed;
142
+ }
143
+
144
+ .xeplr-upload-btn-primary {
145
+ background: #646cff;
146
+ color: #fff;
147
+ flex: 1;
148
+ }
149
+
150
+ .xeplr-upload-btn-primary:hover:not(:disabled) {
151
+ background: #535bf2;
152
+ }
153
+
154
+ .xeplr-upload-btn-secondary {
155
+ background: #333;
156
+ color: #e0e0e0;
157
+ }
158
+
159
+ .xeplr-upload-btn-secondary:hover:not(:disabled) {
160
+ background: #444;
161
+ }
@@ -0,0 +1 @@
1
+ export { default as FileUploadSample } from './FileUploadSample.jsx';
@@ -0,0 +1,9 @@
1
+ import { useFileUploadController } from './useFileUploadController.js';
2
+ import FileUploadSample from './designs/FileUploadSample.jsx';
3
+ import { useDesignValidator, FILE_UPLOAD_RULES } from './validateDesign.js';
4
+
5
+ export function FileUploadPage(props) {
6
+ var controller = useFileUploadController(props);
7
+ var ref = useDesignValidator('FileUploadPage', FILE_UPLOAD_RULES);
8
+ return <div ref={ref}><FileUploadSample {...controller} /></div>;
9
+ }
@@ -0,0 +1,76 @@
1
+ var _config = {
2
+ url: '/internal/upload',
3
+ headers: {}
4
+ };
5
+
6
+ export function configureUpload(config = {}) {
7
+ if (config.url) _config.url = config.url;
8
+ if (config.headers) _config.headers = config.headers;
9
+ if (config.getHeaders) _config.getHeaders = config.getHeaders;
10
+ }
11
+
12
+ /**
13
+ * Upload files to the server.
14
+ * @param {File[]} files - Files to upload
15
+ * @param {object} [options]
16
+ * @param {string} [options.url] - Override upload URL
17
+ * @param {string} [options.fieldName='file'] - Form field name
18
+ * @param {object} [options.extraData] - Additional form fields
19
+ * @param {function} [options.onProgress] - Progress callback: (percent, loaded, total)
20
+ * @returns {Promise<object>} Server response
21
+ */
22
+ export function uploadFile(files, options = {}) {
23
+ return new Promise(function(resolve, reject) {
24
+ var url = options.url || _config.url;
25
+ var fieldName = options.fieldName || 'file';
26
+ var formData = new FormData();
27
+
28
+ var fileList = Array.isArray(files) ? files : [files];
29
+ fileList.forEach(function(file) {
30
+ formData.append(fieldName, file);
31
+ });
32
+
33
+ if (options.extraData) {
34
+ Object.keys(options.extraData).forEach(function(key) {
35
+ formData.append(key, options.extraData[key]);
36
+ });
37
+ }
38
+
39
+ var xhr = new XMLHttpRequest();
40
+ xhr.open('POST', url);
41
+
42
+ // Apply headers
43
+ var headers = _config.getHeaders ? _config.getHeaders() : _config.headers;
44
+ Object.keys(headers).forEach(function(key) {
45
+ xhr.setRequestHeader(key, headers[key]);
46
+ });
47
+
48
+ if (options.onProgress) {
49
+ xhr.upload.onprogress = function(e) {
50
+ if (e.lengthComputable) {
51
+ var percent = Math.round((e.loaded / e.total) * 100);
52
+ options.onProgress(percent, e.loaded, e.total);
53
+ }
54
+ };
55
+ }
56
+
57
+ xhr.onload = function() {
58
+ try {
59
+ var response = JSON.parse(xhr.responseText);
60
+ if (xhr.status >= 200 && xhr.status < 300) {
61
+ resolve(response);
62
+ } else {
63
+ reject(new Error(response.error || 'Upload failed'));
64
+ }
65
+ } catch (e) {
66
+ reject(new Error('Upload failed: ' + xhr.statusText));
67
+ }
68
+ };
69
+
70
+ xhr.onerror = function() {
71
+ reject(new Error('Upload failed: network error'));
72
+ };
73
+
74
+ xhr.send(formData);
75
+ });
76
+ }