@ibanzajoe/uploader 0.2.0 → 0.3.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.
- package/README.md +51 -0
- package/dist/index.cjs +45 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -3
- package/dist/index.d.ts +105 -3
- package/dist/index.js +44 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,57 @@ Inline drop zone that can be embedded in a form.
|
|
|
64
64
|
|
|
65
65
|
Headless hook — returns `{ open, uploading, files, errors }`.
|
|
66
66
|
|
|
67
|
+
## Theming
|
|
68
|
+
|
|
69
|
+
The picker is styled entirely from `--uploader-*` CSS custom properties, so a
|
|
70
|
+
third-party app can restyle it to match its own brand. There are two ways to do
|
|
71
|
+
it — pick whichever fits your stack.
|
|
72
|
+
|
|
73
|
+
### 1. The `theme` prop (scoped, per-instance)
|
|
74
|
+
|
|
75
|
+
Pass your design tokens as a plain object. They are applied as inline CSS
|
|
76
|
+
variables on that component's root, so the override is **scoped to that
|
|
77
|
+
instance** — two pickers on one page can carry different themes and nothing
|
|
78
|
+
leaks to the rest of your app. Only the keys you set change; everything else
|
|
79
|
+
falls back to the shipped defaults.
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { PickerOverlay } from '@uploader/react'
|
|
83
|
+
import '@uploader/react/styles.css'
|
|
84
|
+
|
|
85
|
+
<PickerOverlay
|
|
86
|
+
apikey="pk_…"
|
|
87
|
+
open={open}
|
|
88
|
+
onClose={() => setOpen(false)}
|
|
89
|
+
theme={{
|
|
90
|
+
accent: '#4f46e5', // your brand color
|
|
91
|
+
accentSoft: '#eef2ff', // tinted hover/icon background
|
|
92
|
+
accentRing: 'rgba(79,70,229,.28)',
|
|
93
|
+
radius: '12px',
|
|
94
|
+
font: "'Inter', sans-serif",
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`DropPane` takes the same `theme` prop. See the `UploaderTheme` type for the
|
|
100
|
+
full token list (accent set, surfaces, text, borders, semantic colors, shadows,
|
|
101
|
+
radius, font, transition). A `themeToVars(theme)` helper is also exported if you
|
|
102
|
+
want to apply the same variables to your own wrapper element.
|
|
103
|
+
|
|
104
|
+
### 2. CSS variables (global / page-level)
|
|
105
|
+
|
|
106
|
+
Override the variables in your own stylesheet to theme every instance at once:
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
:root {
|
|
110
|
+
--uploader-accent: #4f46e5;
|
|
111
|
+
--uploader-accent-soft: #eef2ff;
|
|
112
|
+
--uploader-radius: 12px;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Dark mode is handled automatically when any ancestor has `data-theme="dark"`.
|
|
117
|
+
|
|
67
118
|
## Camera capture
|
|
68
119
|
|
|
69
120
|
Both `<PickerOverlay>` and `<DropPane>` can capture a photo straight from the
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
resize: () => resize,
|
|
36
36
|
rotate: () => rotate,
|
|
37
37
|
shouldOfferCamera: () => shouldOfferCamera,
|
|
38
|
+
themeToVars: () => themeToVars,
|
|
38
39
|
transformUrl: () => transformUrl,
|
|
39
40
|
usePicker: () => usePicker
|
|
40
41
|
});
|
|
@@ -1405,6 +1406,43 @@ function FileQueueRow({ entry, onRemove, onRetry, onEdit }) {
|
|
|
1405
1406
|
] });
|
|
1406
1407
|
}
|
|
1407
1408
|
|
|
1409
|
+
// src/react/theme.ts
|
|
1410
|
+
var VAR_MAP = {
|
|
1411
|
+
accent: "--uploader-accent",
|
|
1412
|
+
accentHover: "--uploader-accent-hover",
|
|
1413
|
+
accentSoft: "--uploader-accent-soft",
|
|
1414
|
+
accentRing: "--uploader-accent-ring",
|
|
1415
|
+
radius: "--uploader-radius",
|
|
1416
|
+
background: "--uploader-bg",
|
|
1417
|
+
surface: "--uploader-surface",
|
|
1418
|
+
surfaceHover: "--uploader-surface-hover",
|
|
1419
|
+
border: "--uploader-border",
|
|
1420
|
+
borderSubtle: "--uploader-border-subtle",
|
|
1421
|
+
text: "--uploader-text",
|
|
1422
|
+
textMuted: "--uploader-text-muted",
|
|
1423
|
+
textXMuted: "--uploader-text-xmuted",
|
|
1424
|
+
error: "--uploader-error",
|
|
1425
|
+
errorSoft: "--uploader-error-soft",
|
|
1426
|
+
success: "--uploader-success",
|
|
1427
|
+
shadowSm: "--uploader-shadow-sm",
|
|
1428
|
+
shadow: "--uploader-shadow",
|
|
1429
|
+
shadowLg: "--uploader-shadow-lg",
|
|
1430
|
+
font: "--uploader-font",
|
|
1431
|
+
transition: "--uploader-transition",
|
|
1432
|
+
zBackdrop: "--uploader-z-backdrop",
|
|
1433
|
+
zPanel: "--uploader-z-panel"
|
|
1434
|
+
};
|
|
1435
|
+
function themeToVars(theme) {
|
|
1436
|
+
if (!theme) return {};
|
|
1437
|
+
const vars = {};
|
|
1438
|
+
for (const key of Object.keys(theme)) {
|
|
1439
|
+
const value = theme[key];
|
|
1440
|
+
if (value === void 0 || value === null) continue;
|
|
1441
|
+
vars[VAR_MAP[key]] = String(value);
|
|
1442
|
+
}
|
|
1443
|
+
return vars;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1408
1446
|
// src/react/PickerOverlay.tsx
|
|
1409
1447
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1410
1448
|
function dialogTitle(isUploading, isDone, totalFiles, doneCount, errorCount, editingId, cameraOpen) {
|
|
@@ -1426,6 +1464,7 @@ function PickerOverlay({
|
|
|
1426
1464
|
onFileUploadFinished,
|
|
1427
1465
|
onFileUploadFailed,
|
|
1428
1466
|
onCancel,
|
|
1467
|
+
theme,
|
|
1429
1468
|
className,
|
|
1430
1469
|
style
|
|
1431
1470
|
}) {
|
|
@@ -1539,6 +1578,7 @@ function PickerOverlay({
|
|
|
1539
1578
|
{
|
|
1540
1579
|
className: "uploader-backdrop",
|
|
1541
1580
|
"data-testid": "picker-backdrop",
|
|
1581
|
+
style: themeToVars(theme),
|
|
1542
1582
|
onClick: handleClose,
|
|
1543
1583
|
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1544
1584
|
"div",
|
|
@@ -1725,11 +1765,13 @@ function DropPane({
|
|
|
1725
1765
|
onFileUploadFailed,
|
|
1726
1766
|
onCancel,
|
|
1727
1767
|
hint = "or click to browse \xB7 max 50 MB",
|
|
1768
|
+
theme,
|
|
1728
1769
|
className,
|
|
1729
1770
|
style
|
|
1730
1771
|
}) {
|
|
1731
1772
|
const [isDragOver, setIsDragOver] = (0, import_react7.useState)(false);
|
|
1732
1773
|
const [cameraOpen, setCameraOpen] = (0, import_react7.useState)(false);
|
|
1774
|
+
const rootStyle = { ...themeToVars(theme), ...style };
|
|
1733
1775
|
const { files, addFiles, removeFile, retryFile, upload, progress, isUploading, isDone } = usePicker({
|
|
1734
1776
|
apikey,
|
|
1735
1777
|
apiUrl,
|
|
@@ -1775,7 +1817,7 @@ function DropPane({
|
|
|
1775
1817
|
{
|
|
1776
1818
|
className: ["uploader-drop-pane", className ?? ""].filter(Boolean).join(" "),
|
|
1777
1819
|
"data-testid": "drop-pane",
|
|
1778
|
-
style,
|
|
1820
|
+
style: rootStyle,
|
|
1779
1821
|
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1780
1822
|
CameraCapture,
|
|
1781
1823
|
{
|
|
@@ -1796,7 +1838,7 @@ function DropPane({
|
|
|
1796
1838
|
className: ["uploader-drop-pane", className ?? ""].filter(Boolean).join(" "),
|
|
1797
1839
|
"data-drag-over": isDragOver ? "true" : void 0,
|
|
1798
1840
|
"data-testid": "drop-pane",
|
|
1799
|
-
style,
|
|
1841
|
+
style: rootStyle,
|
|
1800
1842
|
children: [
|
|
1801
1843
|
files.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1802
1844
|
Dropzone,
|
|
@@ -1908,6 +1950,7 @@ function DropPane({
|
|
|
1908
1950
|
resize,
|
|
1909
1951
|
rotate,
|
|
1910
1952
|
shouldOfferCamera,
|
|
1953
|
+
themeToVars,
|
|
1911
1954
|
transformUrl,
|
|
1912
1955
|
usePicker
|
|
1913
1956
|
});
|