@scaleflex/uploader 0.1.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 (96) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +50 -0
  3. package/README.md +123 -0
  4. package/dist/auth/auth.service.d.ts +25 -0
  5. package/dist/auth/auth.service.d.ts.map +1 -0
  6. package/dist/auth/auth.types.d.ts +24 -0
  7. package/dist/auth/auth.types.d.ts.map +1 -0
  8. package/dist/auth/index.d.ts +3 -0
  9. package/dist/auth/index.d.ts.map +1 -0
  10. package/dist/components/actions-bar.d.ts +17 -0
  11. package/dist/components/actions-bar.d.ts.map +1 -0
  12. package/dist/components/camera-dialog.d.ts +27 -0
  13. package/dist/components/camera-dialog.d.ts.map +1 -0
  14. package/dist/components/drop-zone.d.ts +28 -0
  15. package/dist/components/drop-zone.d.ts.map +1 -0
  16. package/dist/components/file-item.d.ts +12 -0
  17. package/dist/components/file-item.d.ts.map +1 -0
  18. package/dist/components/file-list.d.ts +8 -0
  19. package/dist/components/file-list.d.ts.map +1 -0
  20. package/dist/components/import-divider.d.ts +6 -0
  21. package/dist/components/import-divider.d.ts.map +1 -0
  22. package/dist/components/index.d.ts +9 -0
  23. package/dist/components/index.d.ts.map +1 -0
  24. package/dist/components/provider-browser.d.ts +48 -0
  25. package/dist/components/provider-browser.d.ts.map +1 -0
  26. package/dist/components/screen-cast-dialog.d.ts +29 -0
  27. package/dist/components/screen-cast-dialog.d.ts.map +1 -0
  28. package/dist/components/search-provider-browser.d.ts +36 -0
  29. package/dist/components/search-provider-browser.d.ts.map +1 -0
  30. package/dist/components/source-pills.d.ts +11 -0
  31. package/dist/components/source-pills.d.ts.map +1 -0
  32. package/dist/components/success-card.d.ts +10 -0
  33. package/dist/components/success-card.d.ts.map +1 -0
  34. package/dist/components/url-dialog.d.ts +25 -0
  35. package/dist/components/url-dialog.d.ts.map +1 -0
  36. package/dist/connectors/companion-client.d.ts +58 -0
  37. package/dist/connectors/companion-client.d.ts.map +1 -0
  38. package/dist/connectors/connector.types.d.ts +56 -0
  39. package/dist/connectors/connector.types.d.ts.map +1 -0
  40. package/dist/connectors/index.d.ts +5 -0
  41. package/dist/connectors/index.d.ts.map +1 -0
  42. package/dist/connectors/provider-registry.d.ts +8 -0
  43. package/dist/connectors/provider-registry.d.ts.map +1 -0
  44. package/dist/connectors/token-store.d.ts +10 -0
  45. package/dist/connectors/token-store.d.ts.map +1 -0
  46. package/dist/controllers/store.controller.d.ts +14 -0
  47. package/dist/controllers/store.controller.d.ts.map +1 -0
  48. package/dist/define.cjs +1 -0
  49. package/dist/define.d.ts +2 -0
  50. package/dist/define.d.ts.map +1 -0
  51. package/dist/define.js +15 -0
  52. package/dist/engine/companion-upload.d.ts +23 -0
  53. package/dist/engine/companion-upload.d.ts.map +1 -0
  54. package/dist/engine/index.d.ts +2 -0
  55. package/dist/engine/index.d.ts.map +1 -0
  56. package/dist/engine/upload-engine.d.ts +56 -0
  57. package/dist/engine/upload-engine.d.ts.map +1 -0
  58. package/dist/engine/xhr-upload.d.ts +25 -0
  59. package/dist/engine/xhr-upload.d.ts.map +1 -0
  60. package/dist/events/event-bus.d.ts +38 -0
  61. package/dist/events/event-bus.d.ts.map +1 -0
  62. package/dist/events/public-events.d.ts +23 -0
  63. package/dist/events/public-events.d.ts.map +1 -0
  64. package/dist/index.cjs +1 -0
  65. package/dist/index.d.ts +17 -0
  66. package/dist/index.d.ts.map +1 -0
  67. package/dist/index.js +21 -0
  68. package/dist/provider-browser-C-S_MPrC.js +832 -0
  69. package/dist/provider-browser-CmCwv0ph.cjs +581 -0
  70. package/dist/react.cjs +1 -0
  71. package/dist/react.d.ts +33 -0
  72. package/dist/react.d.ts.map +1 -0
  73. package/dist/react.js +125 -0
  74. package/dist/search-provider-browser-DxmLznEB.cjs +390 -0
  75. package/dist/search-provider-browser-jCOer2Y9.js +537 -0
  76. package/dist/sfx-uploader-BVDK-9xi.cjs +2029 -0
  77. package/dist/sfx-uploader-C2lWIRnU.js +3789 -0
  78. package/dist/sfx-uploader.d.ts +131 -0
  79. package/dist/sfx-uploader.d.ts.map +1 -0
  80. package/dist/store/helpers.d.ts +16 -0
  81. package/dist/store/helpers.d.ts.map +1 -0
  82. package/dist/store/index.d.ts +7 -0
  83. package/dist/store/index.d.ts.map +1 -0
  84. package/dist/store/store.d.ts +14 -0
  85. package/dist/store/store.d.ts.map +1 -0
  86. package/dist/store/store.types.d.ts +77 -0
  87. package/dist/store/store.types.d.ts.map +1 -0
  88. package/dist/test-utils.d.ts +5 -0
  89. package/dist/test-utils.d.ts.map +1 -0
  90. package/dist/types/source.types.d.ts +12 -0
  91. package/dist/types/source.types.d.ts.map +1 -0
  92. package/dist/utils/file-utils.d.ts +14 -0
  93. package/dist/utils/file-utils.d.ts.map +1 -0
  94. package/dist/utils/validate.d.ts +6 -0
  95. package/dist/utils/validate.d.ts.map +1 -0
  96. package/package.json +72 -0
@@ -0,0 +1,537 @@
1
+ import { LitElement as x, css as g, html as s, nothing as d } from "lit";
2
+ import { property as f, state as a } from "lit/decorators.js";
3
+ import { m as b, s as u } from "./sfx-uploader-C2lWIRnU.js";
4
+ var m = Object.defineProperty, n = (c, r, e, t) => {
5
+ for (var i = void 0, l = c.length - 1, h; l >= 0; l--)
6
+ (h = c[l]) && (i = h(r, e, i) || i);
7
+ return i && m(r, e, i), i;
8
+ };
9
+ const p = class p extends x {
10
+ constructor() {
11
+ super(...arguments), this.provider = "unsplash", this.companionUrl = "", this._loading = !1, this._loadingMore = !1, this._items = [], this._selectedIds = /* @__PURE__ */ new Set(), this._error = null, this._searchQuery = "", this._nextPageQuery = null, this._searched = !1, this._onResultsScroll = (r) => {
12
+ if (!this._nextPageQuery || this._loadingMore) return;
13
+ const e = r.target;
14
+ e.scrollHeight - e.scrollTop - e.clientHeight < 200 && this._onLoadMore();
15
+ }, this._onSearchInput = (r) => {
16
+ this._searchQuery = r.target.value;
17
+ }, this._onSearchKeydown = (r) => {
18
+ r.key === "Enter" && this._doSearch();
19
+ }, this._onAddSelected = () => {
20
+ const e = this._items.filter((t) => this._selectedIds.has(t.id)).map((t) => ({
21
+ companionUrl: this.companionUrl,
22
+ provider: this.provider,
23
+ token: "",
24
+ // Search providers don't use OAuth tokens
25
+ requestPath: t.requestPath,
26
+ fileId: t.id,
27
+ name: t.name || t.id,
28
+ mimeType: t.mimeType,
29
+ size: t.size,
30
+ thumbnail: t.thumbnail
31
+ }));
32
+ this.dispatchEvent(
33
+ new CustomEvent("connector-files-selected", {
34
+ detail: { files: e },
35
+ bubbles: !0,
36
+ composed: !0
37
+ })
38
+ );
39
+ }, this._onClose = () => {
40
+ this.dispatchEvent(
41
+ new CustomEvent("connector-close", {
42
+ bubbles: !0,
43
+ composed: !0
44
+ })
45
+ );
46
+ };
47
+ }
48
+ get _providerLabel() {
49
+ var e;
50
+ return ((e = b([this.provider])[0]) == null ? void 0 : e.label) ?? this.provider;
51
+ }
52
+ async _doSearch() {
53
+ const r = this._searchQuery.trim();
54
+ if (r) {
55
+ this._loading = !0, this._error = null, this._items = [], this._selectedIds = /* @__PURE__ */ new Set(), this._nextPageQuery = null, this._searched = !0;
56
+ try {
57
+ const e = await u(this.companionUrl, this.provider, r), t = /* @__PURE__ */ new Set();
58
+ this._items = e.items.filter((i) => t.has(i.id) ? !1 : (t.add(i.id), !0)), this._nextPageQuery = e.nextPageQuery;
59
+ } catch (e) {
60
+ this._error = e instanceof Error ? e.message : "Search failed";
61
+ } finally {
62
+ this._loading = !1;
63
+ }
64
+ }
65
+ }
66
+ async _onLoadMore() {
67
+ if (!(!this._nextPageQuery || this._loadingMore)) {
68
+ this._loadingMore = !0;
69
+ try {
70
+ const r = await u(
71
+ this.companionUrl,
72
+ this.provider,
73
+ this._searchQuery.trim(),
74
+ this._nextPageQuery
75
+ ), e = new Set(this._items.map((i) => i.id)), t = r.items.filter((i) => !e.has(i.id));
76
+ this._items = [...this._items, ...t], this._nextPageQuery = r.nextPageQuery;
77
+ } catch {
78
+ } finally {
79
+ this._loadingMore = !1;
80
+ }
81
+ }
82
+ }
83
+ // --- Selection ---
84
+ _toggleSelect(r) {
85
+ const e = new Set(this._selectedIds);
86
+ e.has(r.id) ? e.delete(r.id) : e.add(r.id), this._selectedIds = e;
87
+ }
88
+ // --- Render ---
89
+ render() {
90
+ return s`
91
+ ${this._renderHeader()}
92
+ ${this._renderSearchBar()}
93
+ ${this._loading ? this._renderLoading() : this._error ? this._renderError() : this._renderResults()}
94
+ `;
95
+ }
96
+ _renderHeader() {
97
+ return s`
98
+ <div class="browser-header">
99
+ <button class="back-btn" @click=${this._onClose}>
100
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
101
+ <polyline points="15 18 9 12 15 6" />
102
+ </svg>
103
+ </button>
104
+ <span class="browser-title">${this._providerLabel}</span>
105
+ </div>
106
+ `;
107
+ }
108
+ _renderSearchBar() {
109
+ return s`
110
+ <div class="search-bar">
111
+ <input
112
+ class="search-input"
113
+ type="text"
114
+ placeholder="Search for images..."
115
+ .value=${this._searchQuery}
116
+ @input=${this._onSearchInput}
117
+ @keydown=${this._onSearchKeydown}
118
+ />
119
+ <button
120
+ class="search-btn"
121
+ ?disabled=${!this._searchQuery.trim() || this._loading}
122
+ @click=${() => this._doSearch()}
123
+ >
124
+ Search
125
+ </button>
126
+ </div>
127
+ `;
128
+ }
129
+ _renderLoading() {
130
+ return s`
131
+ <div class="loading">
132
+ <div class="spinner"></div>
133
+ </div>
134
+ `;
135
+ }
136
+ _renderError() {
137
+ return s`
138
+ <div class="error-view">
139
+ <div class="error-text">${this._error}</div>
140
+ <button class="retry-btn" @click=${() => this._doSearch()}>Retry</button>
141
+ </div>
142
+ `;
143
+ }
144
+ _renderResults() {
145
+ const r = this._selectedIds.size;
146
+ return this._searched ? this._items.length === 0 ? s`
147
+ <div class="empty-state">
148
+ <div class="empty-text">No results found</div>
149
+ </div>
150
+ ` : s`
151
+ <div class="results" @scroll=${this._onResultsScroll}>
152
+ <div class="results-grid">
153
+ ${this._items.map(
154
+ (e) => {
155
+ var t;
156
+ return s`
157
+ <div
158
+ class="result-item ${this._selectedIds.has(e.id) ? "selected" : ""}"
159
+ @click=${() => this._toggleSelect(e)}
160
+ >
161
+ ${e.thumbnail ? s`<img src=${e.thumbnail} alt=${e.name} loading="lazy" referrerpolicy="no-referrer" />` : d}
162
+ <div class="check">
163
+ ${this._selectedIds.has(e.id) ? s`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><polyline points="20 6 9 17 4 12" /></svg>` : d}
164
+ </div>
165
+ ${(t = e.author) != null && t.name ? s`<div class="author">${e.author.name}</div>` : d}
166
+ </div>
167
+ `;
168
+ }
169
+ )}
170
+ </div>
171
+ ${this._loadingMore ? s`<div class="loading" style="padding:16px 0"><div class="spinner"></div></div>` : d}
172
+ </div>
173
+
174
+ ${this._items.length > 0 ? s`
175
+ <div class="browser-footer">
176
+ <span class="selected-count">
177
+ ${r > 0 ? `${r} image${r === 1 ? "" : "s"} selected` : "Select images to add"}
178
+ </span>
179
+ <button
180
+ class="add-btn"
181
+ ?disabled=${r === 0}
182
+ @click=${this._onAddSelected}
183
+ >
184
+ Add ${r > 0 ? r : ""} image${r === 1 ? "" : "s"}
185
+ </button>
186
+ </div>
187
+ ` : d}
188
+ ` : s`
189
+ <div class="empty-state">
190
+ <div class="empty-text">Enter text to search for images</div>
191
+ </div>
192
+ `;
193
+ }
194
+ };
195
+ p.styles = g`
196
+ :host {
197
+ display: flex;
198
+ flex-direction: column;
199
+ height: 100%;
200
+ min-height: 300px;
201
+ font-family: var(--sfx-up-font, 'Inter', system-ui, -apple-system, sans-serif);
202
+ color: var(--sfx-up-text, #1e293b);
203
+ }
204
+
205
+ .browser-header {
206
+ display: flex;
207
+ align-items: center;
208
+ gap: 10px;
209
+ padding: 14px 20px;
210
+ border-bottom: 1px solid var(--sfx-up-border-light, #f1f5f9);
211
+ flex-shrink: 0;
212
+ }
213
+
214
+ .back-btn {
215
+ width: 32px;
216
+ height: 32px;
217
+ border: none;
218
+ background: none;
219
+ border-radius: 8px;
220
+ cursor: pointer;
221
+ display: flex;
222
+ align-items: center;
223
+ justify-content: center;
224
+ color: var(--sfx-up-text-muted, #94a3b8);
225
+ transition: all 0.15s;
226
+ flex-shrink: 0;
227
+ }
228
+
229
+ .back-btn:hover {
230
+ background: #f1f5f9;
231
+ color: var(--sfx-up-text, #1e293b);
232
+ }
233
+
234
+ .back-btn svg {
235
+ width: 18px;
236
+ height: 18px;
237
+ }
238
+
239
+ .browser-title {
240
+ font-size: 14px;
241
+ font-weight: 600;
242
+ flex: 1;
243
+ }
244
+
245
+ /* --- Search bar --- */
246
+ .search-bar {
247
+ display: flex;
248
+ align-items: center;
249
+ gap: 8px;
250
+ padding: 12px 20px;
251
+ border-bottom: 1px solid var(--sfx-up-border-light, #f1f5f9);
252
+ flex-shrink: 0;
253
+ }
254
+
255
+ .search-input {
256
+ flex: 1;
257
+ height: 36px;
258
+ padding: 0 12px;
259
+ border: 1.5px solid var(--sfx-up-border, #e8edf5);
260
+ border-radius: 9px;
261
+ font-family: inherit;
262
+ font-size: 13px;
263
+ color: var(--sfx-up-text, #1e293b);
264
+ background: #fff;
265
+ outline: none;
266
+ transition: border-color 0.15s;
267
+ }
268
+
269
+ .search-input:focus {
270
+ border-color: var(--sfx-up-primary, #2563eb);
271
+ }
272
+
273
+ .search-input::placeholder {
274
+ color: var(--sfx-up-text-muted, #94a3b8);
275
+ }
276
+
277
+ .search-btn {
278
+ height: 36px;
279
+ padding: 0 16px;
280
+ border: none;
281
+ border-radius: 9px;
282
+ background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), var(--sfx-up-primary-mid, #3b82f6));
283
+ color: #fff;
284
+ font-family: inherit;
285
+ font-size: 13px;
286
+ font-weight: 600;
287
+ cursor: pointer;
288
+ transition: all 0.18s;
289
+ flex-shrink: 0;
290
+ }
291
+
292
+ .search-btn:hover:not(:disabled) {
293
+ transform: translateY(-1px);
294
+ }
295
+
296
+ .search-btn:disabled {
297
+ opacity: 0.5;
298
+ cursor: not-allowed;
299
+ }
300
+
301
+ /* --- Results grid --- */
302
+ .results {
303
+ flex: 1;
304
+ overflow-y: auto;
305
+ padding: 8px 12px;
306
+ min-height: 0;
307
+ }
308
+
309
+ .results-grid {
310
+ display: grid;
311
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
312
+ gap: 8px;
313
+ }
314
+
315
+ .result-item {
316
+ position: relative;
317
+ aspect-ratio: 1;
318
+ border-radius: 10px;
319
+ overflow: hidden;
320
+ cursor: pointer;
321
+ border: 2px solid transparent;
322
+ transition: border-color 0.15s;
323
+ }
324
+
325
+ .result-item.selected {
326
+ border-color: var(--sfx-up-primary, #2563eb);
327
+ }
328
+
329
+ .result-item img {
330
+ width: 100%;
331
+ height: 100%;
332
+ object-fit: cover;
333
+ display: block;
334
+ }
335
+
336
+ .result-item .check {
337
+ position: absolute;
338
+ top: 6px;
339
+ left: 6px;
340
+ width: 22px;
341
+ height: 22px;
342
+ border-radius: 6px;
343
+ background: rgba(255, 255, 255, 0.85);
344
+ display: flex;
345
+ align-items: center;
346
+ justify-content: center;
347
+ opacity: 0;
348
+ transition: opacity 0.15s;
349
+ }
350
+
351
+ .result-item:hover .check,
352
+ .result-item.selected .check {
353
+ opacity: 1;
354
+ }
355
+
356
+ .result-item.selected .check {
357
+ background: var(--sfx-up-primary, #2563eb);
358
+ color: #fff;
359
+ }
360
+
361
+ .check svg {
362
+ width: 14px;
363
+ height: 14px;
364
+ }
365
+
366
+ .result-item .author {
367
+ position: absolute;
368
+ bottom: 0;
369
+ left: 0;
370
+ right: 0;
371
+ padding: 4px 8px;
372
+ background: linear-gradient(transparent, rgba(0,0,0,0.5));
373
+ font-size: 10px;
374
+ color: #fff;
375
+ white-space: nowrap;
376
+ overflow: hidden;
377
+ text-overflow: ellipsis;
378
+ opacity: 0;
379
+ transition: opacity 0.15s;
380
+ }
381
+
382
+ .result-item:hover .author {
383
+ opacity: 1;
384
+ }
385
+
386
+ /* --- Footer --- */
387
+ .browser-footer {
388
+ display: flex;
389
+ align-items: center;
390
+ justify-content: space-between;
391
+ padding: 12px 20px;
392
+ border-top: 1px solid var(--sfx-up-border-light, #f1f5f9);
393
+ flex-shrink: 0;
394
+ }
395
+
396
+ .selected-count {
397
+ font-size: 13px;
398
+ color: var(--sfx-up-text-secondary, #475569);
399
+ font-weight: 500;
400
+ }
401
+
402
+ .add-btn {
403
+ height: 36px;
404
+ padding: 0 20px;
405
+ border: none;
406
+ border-radius: 9px;
407
+ background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), var(--sfx-up-primary-mid, #3b82f6));
408
+ color: #fff;
409
+ font-family: inherit;
410
+ font-size: 13px;
411
+ font-weight: 600;
412
+ cursor: pointer;
413
+ transition: all 0.18s;
414
+ box-shadow: 0 2px 10px rgba(37, 99, 235, 0.28);
415
+ }
416
+
417
+ .add-btn:hover:not(:disabled) {
418
+ transform: translateY(-1px);
419
+ box-shadow: 0 4px 16px rgba(37, 99, 235, 0.38);
420
+ }
421
+
422
+ .add-btn:disabled {
423
+ opacity: 0.5;
424
+ cursor: not-allowed;
425
+ }
426
+
427
+ /* --- States --- */
428
+ .loading, .error-view, .empty-state {
429
+ flex: 1;
430
+ display: flex;
431
+ flex-direction: column;
432
+ align-items: center;
433
+ justify-content: center;
434
+ gap: 12px;
435
+ padding: 40px 24px;
436
+ text-align: center;
437
+ }
438
+
439
+ .spinner {
440
+ width: 28px;
441
+ height: 28px;
442
+ border: 3px solid var(--sfx-up-border, #e8edf5);
443
+ border-top-color: var(--sfx-up-primary, #2563eb);
444
+ border-radius: 50%;
445
+ animation: spin 0.7s linear infinite;
446
+ }
447
+
448
+ .error-text {
449
+ font-size: 14px;
450
+ color: var(--sfx-up-error, #dc2626);
451
+ }
452
+
453
+ .retry-btn {
454
+ height: 34px;
455
+ padding: 0 16px;
456
+ border: 1.5px solid var(--sfx-up-border, #e8edf5);
457
+ background: none;
458
+ border-radius: 8px;
459
+ font-family: inherit;
460
+ font-size: 13px;
461
+ font-weight: 600;
462
+ cursor: pointer;
463
+ color: var(--sfx-up-text-secondary, #475569);
464
+ transition: all 0.15s;
465
+ }
466
+
467
+ .retry-btn:hover {
468
+ background: #f8faff;
469
+ border-color: #d1dff0;
470
+ }
471
+
472
+ .empty-text {
473
+ font-size: 14px;
474
+ color: var(--sfx-up-text-muted, #94a3b8);
475
+ }
476
+
477
+ .load-more-btn {
478
+ display: block;
479
+ margin: 12px auto;
480
+ padding: 8px 20px;
481
+ border: 1.5px solid var(--sfx-up-border, #e8edf5);
482
+ background: none;
483
+ border-radius: 8px;
484
+ font-family: inherit;
485
+ font-size: 13px;
486
+ font-weight: 500;
487
+ cursor: pointer;
488
+ color: var(--sfx-up-primary, #2563eb);
489
+ transition: all 0.15s;
490
+ }
491
+
492
+ .load-more-btn:hover {
493
+ background: var(--sfx-up-primary-bg, #eff6ff);
494
+ }
495
+
496
+ @keyframes spin {
497
+ to { transform: rotate(360deg); }
498
+ }
499
+
500
+ @media (prefers-reduced-motion: reduce) {
501
+ .spinner { animation: none; }
502
+ }
503
+ `;
504
+ let o = p;
505
+ n([
506
+ f({ type: String })
507
+ ], o.prototype, "provider");
508
+ n([
509
+ f({ type: String })
510
+ ], o.prototype, "companionUrl");
511
+ n([
512
+ a()
513
+ ], o.prototype, "_loading");
514
+ n([
515
+ a()
516
+ ], o.prototype, "_loadingMore");
517
+ n([
518
+ a()
519
+ ], o.prototype, "_items");
520
+ n([
521
+ a()
522
+ ], o.prototype, "_selectedIds");
523
+ n([
524
+ a()
525
+ ], o.prototype, "_error");
526
+ n([
527
+ a()
528
+ ], o.prototype, "_searchQuery");
529
+ n([
530
+ a()
531
+ ], o.prototype, "_nextPageQuery");
532
+ n([
533
+ a()
534
+ ], o.prototype, "_searched");
535
+ export {
536
+ o as SfxSearchProviderBrowser
537
+ };