@nubitio/crud 0.5.15 → 0.5.16
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/dist/index.cjs +29 -134
- package/dist/index.mjs +30 -135
- package/dist/style.css +0 -465
- package/package.json +3 -6
package/dist/index.cjs
CHANGED
|
@@ -28,7 +28,6 @@ let react_dom = require("react-dom");
|
|
|
28
28
|
let _nubitio_ui = require("@nubitio/ui");
|
|
29
29
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
30
30
|
let _nubitio_core = require("@nubitio/core");
|
|
31
|
-
let react_dropzone = require("react-dropzone");
|
|
32
31
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
33
32
|
//#region packages/crud/crud/defineResource.ts
|
|
34
33
|
const stringResourceCache = /* @__PURE__ */ new Map();
|
|
@@ -1243,9 +1242,6 @@ const enumTypeModule = {
|
|
|
1243
1242
|
};
|
|
1244
1243
|
//#endregion
|
|
1245
1244
|
//#region packages/crud/form/FileUploadField.tsx
|
|
1246
|
-
function cx$1(...values) {
|
|
1247
|
-
return values.filter(Boolean).join(" ");
|
|
1248
|
-
}
|
|
1249
1245
|
function resolveMediaPath(media) {
|
|
1250
1246
|
if (!media) return null;
|
|
1251
1247
|
const path = media["path"];
|
|
@@ -1271,27 +1267,6 @@ function resolveMediaIri(uploadUrl, media) {
|
|
|
1271
1267
|
function isImageMimeType(mimeType) {
|
|
1272
1268
|
return !!mimeType && mimeType.startsWith("image/");
|
|
1273
1269
|
}
|
|
1274
|
-
function buildDropzoneAccept(accept) {
|
|
1275
|
-
if (!accept || accept === "*/*" || accept === "*") return void 0;
|
|
1276
|
-
if (accept === "image/*") return {
|
|
1277
|
-
"image/png": [".png"],
|
|
1278
|
-
"image/jpeg": [".jpg", ".jpeg"],
|
|
1279
|
-
"image/webp": [".webp"],
|
|
1280
|
-
"image/gif": [".gif"]
|
|
1281
|
-
};
|
|
1282
|
-
if (accept.includes(",")) return accept.split(",").reduce((acc, token) => {
|
|
1283
|
-
const trimmed = token.trim();
|
|
1284
|
-
if (!trimmed) return acc;
|
|
1285
|
-
if (trimmed.startsWith(".")) {
|
|
1286
|
-
acc["application/octet-stream"] = [...acc["application/octet-stream"] ?? [], trimmed];
|
|
1287
|
-
return acc;
|
|
1288
|
-
}
|
|
1289
|
-
acc[trimmed] = [];
|
|
1290
|
-
return acc;
|
|
1291
|
-
}, {});
|
|
1292
|
-
if (accept.startsWith(".")) return { "application/octet-stream": [accept] };
|
|
1293
|
-
return { [accept]: [] };
|
|
1294
|
-
}
|
|
1295
1270
|
async function uploadMediaFile(file, uploadUrl, httpClient) {
|
|
1296
1271
|
const body = new FormData();
|
|
1297
1272
|
body.append("file", file);
|
|
@@ -1371,17 +1346,6 @@ function FileUploadField({ field, disabled = false, readOnly = false, invalid =
|
|
|
1371
1346
|
t,
|
|
1372
1347
|
uploadUrl
|
|
1373
1348
|
]);
|
|
1374
|
-
const { getRootProps, getInputProps, isDragActive, open } = (0, react_dropzone.useDropzone)({
|
|
1375
|
-
accept: buildDropzoneAccept(field.accept),
|
|
1376
|
-
disabled: disabled || readOnly || status === "uploading",
|
|
1377
|
-
multiple: false,
|
|
1378
|
-
noClick: !!(previewUrl || fileName),
|
|
1379
|
-
noKeyboard: !!(previewUrl || fileName),
|
|
1380
|
-
onDrop: (acceptedFiles) => {
|
|
1381
|
-
const file = acceptedFiles[0];
|
|
1382
|
-
if (file) uploadFile(file);
|
|
1383
|
-
}
|
|
1384
|
-
});
|
|
1385
1349
|
const handleClear = () => {
|
|
1386
1350
|
revokeLocalPreview();
|
|
1387
1351
|
setPreviewUrl(null);
|
|
@@ -1391,104 +1355,35 @@ function FileUploadField({ field, disabled = false, readOnly = false, invalid =
|
|
|
1391
1355
|
setErrorMessage(null);
|
|
1392
1356
|
onCleared(field.name);
|
|
1393
1357
|
};
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
className: "nb-form__file-upload-file-link",
|
|
1424
|
-
href: fileUrl,
|
|
1425
|
-
target: "_blank",
|
|
1426
|
-
rel: "noreferrer",
|
|
1427
|
-
onClick: (event) => event.stopPropagation(),
|
|
1428
|
-
children: t("form.fileUploadOpen")
|
|
1429
|
-
})]
|
|
1430
|
-
})]
|
|
1431
|
-
}),
|
|
1432
|
-
status === "uploading" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1433
|
-
className: "nb-form__file-upload-overlay",
|
|
1434
|
-
"aria-live": "polite",
|
|
1435
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1436
|
-
className: "nb-form__file-upload-spinner",
|
|
1437
|
-
"aria-hidden": "true"
|
|
1438
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("form.fileUploading") })]
|
|
1439
|
-
}),
|
|
1440
|
-
isInteractive && status !== "uploading" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1441
|
-
className: "nb-form__file-upload-actions",
|
|
1442
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1443
|
-
type: "button",
|
|
1444
|
-
className: "nb-form__file-upload-action",
|
|
1445
|
-
onClick: (event) => {
|
|
1446
|
-
event.stopPropagation();
|
|
1447
|
-
open();
|
|
1448
|
-
},
|
|
1449
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
1450
|
-
className: "ph ph-arrows-clockwise",
|
|
1451
|
-
"aria-hidden": "true"
|
|
1452
|
-
}), t("form.fileUploadReplace")]
|
|
1453
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1454
|
-
type: "button",
|
|
1455
|
-
className: "nb-form__file-upload-action nb-form__file-upload-action--danger",
|
|
1456
|
-
onClick: (event) => {
|
|
1457
|
-
event.stopPropagation();
|
|
1458
|
-
handleClear();
|
|
1459
|
-
},
|
|
1460
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
1461
|
-
className: "ph ph-trash",
|
|
1462
|
-
"aria-hidden": "true"
|
|
1463
|
-
}), t("form.fileUploadRemove")]
|
|
1464
|
-
})]
|
|
1465
|
-
})
|
|
1466
|
-
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1467
|
-
className: "nb-form__file-upload-placeholder",
|
|
1468
|
-
children: [
|
|
1469
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1470
|
-
className: "nb-form__file-upload-icon",
|
|
1471
|
-
"aria-hidden": "true",
|
|
1472
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", { className: `ph ${placeholderIcon}` })
|
|
1473
|
-
}),
|
|
1474
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1475
|
-
className: "nb-form__file-upload-title",
|
|
1476
|
-
children: placeholderTitle
|
|
1477
|
-
}),
|
|
1478
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1479
|
-
className: "nb-form__file-upload-hint",
|
|
1480
|
-
children: placeholderHint
|
|
1481
|
-
})
|
|
1482
|
-
]
|
|
1483
|
-
})]
|
|
1484
|
-
}), errorMessage && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1485
|
-
className: "nb-form__file-upload-error",
|
|
1486
|
-
role: "alert",
|
|
1487
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
1488
|
-
className: "ph ph-warning-circle",
|
|
1489
|
-
"aria-hidden": "true"
|
|
1490
|
-
}), errorMessage]
|
|
1491
|
-
})]
|
|
1358
|
+
const value = {
|
|
1359
|
+
fileName,
|
|
1360
|
+
fileUrl,
|
|
1361
|
+
previewUrl
|
|
1362
|
+
};
|
|
1363
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_nubitio_ui.FileDropzone, {
|
|
1364
|
+
accept: field.accept,
|
|
1365
|
+
disabled,
|
|
1366
|
+
readOnly,
|
|
1367
|
+
invalid,
|
|
1368
|
+
image: imageMode,
|
|
1369
|
+
value,
|
|
1370
|
+
uploading: status === "uploading",
|
|
1371
|
+
error: errorMessage,
|
|
1372
|
+
inputId: `nb-form-${field.name}`,
|
|
1373
|
+
inputLabel: field.label,
|
|
1374
|
+
labels: {
|
|
1375
|
+
dropPrompt: t("form.fileUploadDrop"),
|
|
1376
|
+
prompt: t("form.fileUploadPrompt"),
|
|
1377
|
+
imagePrompt: t("form.imageUploadPrompt"),
|
|
1378
|
+
hint: t("form.fileUploadHint"),
|
|
1379
|
+
imageHint: t("form.imageUploadHint"),
|
|
1380
|
+
uploading: t("form.fileUploading"),
|
|
1381
|
+
replace: t("form.fileUploadReplace"),
|
|
1382
|
+
remove: t("form.fileUploadRemove"),
|
|
1383
|
+
open: t("form.fileUploadOpen")
|
|
1384
|
+
},
|
|
1385
|
+
onFileSelect: (file) => void uploadFile(file),
|
|
1386
|
+
onClear: handleClear
|
|
1492
1387
|
});
|
|
1493
1388
|
}
|
|
1494
1389
|
function isImageFileField(field) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React, { createContext, forwardRef, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
2
2
|
import { Route, useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
|
-
import { AppDialog, AppDropdown, Badge, Button, ConfirmDialog, DatePicker, DateRangePicker, Drawer, EmptyState, IconButton, Skeleton, Timeline, TimelineItem } from "@nubitio/ui";
|
|
4
|
+
import { AppDialog, AppDropdown, Badge, Button, ConfirmDialog, DatePicker, DateRangePicker, Drawer, EmptyState, FileDropzone, IconButton, Skeleton, Timeline, TimelineItem } from "@nubitio/ui";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { createCrudEvents, createScopedEventBus, getCoreCurrency, getCoreLocale, getCoreTimezone, useCoreHttpClient, useCoreRuntime, useCoreTranslation, useEvents, useMercureSubscription } from "@nubitio/core";
|
|
7
|
-
import { useDropzone } from "react-dropzone";
|
|
8
7
|
import { useQueryClient } from "@tanstack/react-query";
|
|
9
8
|
//#region packages/crud/crud/defineResource.ts
|
|
10
9
|
const stringResourceCache = /* @__PURE__ */ new Map();
|
|
@@ -1219,9 +1218,6 @@ const enumTypeModule = {
|
|
|
1219
1218
|
};
|
|
1220
1219
|
//#endregion
|
|
1221
1220
|
//#region packages/crud/form/FileUploadField.tsx
|
|
1222
|
-
function cx$1(...values) {
|
|
1223
|
-
return values.filter(Boolean).join(" ");
|
|
1224
|
-
}
|
|
1225
1221
|
function resolveMediaPath(media) {
|
|
1226
1222
|
if (!media) return null;
|
|
1227
1223
|
const path = media["path"];
|
|
@@ -1247,27 +1243,6 @@ function resolveMediaIri(uploadUrl, media) {
|
|
|
1247
1243
|
function isImageMimeType(mimeType) {
|
|
1248
1244
|
return !!mimeType && mimeType.startsWith("image/");
|
|
1249
1245
|
}
|
|
1250
|
-
function buildDropzoneAccept(accept) {
|
|
1251
|
-
if (!accept || accept === "*/*" || accept === "*") return void 0;
|
|
1252
|
-
if (accept === "image/*") return {
|
|
1253
|
-
"image/png": [".png"],
|
|
1254
|
-
"image/jpeg": [".jpg", ".jpeg"],
|
|
1255
|
-
"image/webp": [".webp"],
|
|
1256
|
-
"image/gif": [".gif"]
|
|
1257
|
-
};
|
|
1258
|
-
if (accept.includes(",")) return accept.split(",").reduce((acc, token) => {
|
|
1259
|
-
const trimmed = token.trim();
|
|
1260
|
-
if (!trimmed) return acc;
|
|
1261
|
-
if (trimmed.startsWith(".")) {
|
|
1262
|
-
acc["application/octet-stream"] = [...acc["application/octet-stream"] ?? [], trimmed];
|
|
1263
|
-
return acc;
|
|
1264
|
-
}
|
|
1265
|
-
acc[trimmed] = [];
|
|
1266
|
-
return acc;
|
|
1267
|
-
}, {});
|
|
1268
|
-
if (accept.startsWith(".")) return { "application/octet-stream": [accept] };
|
|
1269
|
-
return { [accept]: [] };
|
|
1270
|
-
}
|
|
1271
1246
|
async function uploadMediaFile(file, uploadUrl, httpClient) {
|
|
1272
1247
|
const body = new FormData();
|
|
1273
1248
|
body.append("file", file);
|
|
@@ -1347,17 +1322,6 @@ function FileUploadField({ field, disabled = false, readOnly = false, invalid =
|
|
|
1347
1322
|
t,
|
|
1348
1323
|
uploadUrl
|
|
1349
1324
|
]);
|
|
1350
|
-
const { getRootProps, getInputProps, isDragActive, open } = useDropzone({
|
|
1351
|
-
accept: buildDropzoneAccept(field.accept),
|
|
1352
|
-
disabled: disabled || readOnly || status === "uploading",
|
|
1353
|
-
multiple: false,
|
|
1354
|
-
noClick: !!(previewUrl || fileName),
|
|
1355
|
-
noKeyboard: !!(previewUrl || fileName),
|
|
1356
|
-
onDrop: (acceptedFiles) => {
|
|
1357
|
-
const file = acceptedFiles[0];
|
|
1358
|
-
if (file) uploadFile(file);
|
|
1359
|
-
}
|
|
1360
|
-
});
|
|
1361
1325
|
const handleClear = () => {
|
|
1362
1326
|
revokeLocalPreview();
|
|
1363
1327
|
setPreviewUrl(null);
|
|
@@ -1367,104 +1331,35 @@ function FileUploadField({ field, disabled = false, readOnly = false, invalid =
|
|
|
1367
1331
|
setErrorMessage(null);
|
|
1368
1332
|
onCleared(field.name);
|
|
1369
1333
|
};
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
return /* @__PURE__ */
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
className: "nb-form__file-upload-file-link",
|
|
1400
|
-
href: fileUrl,
|
|
1401
|
-
target: "_blank",
|
|
1402
|
-
rel: "noreferrer",
|
|
1403
|
-
onClick: (event) => event.stopPropagation(),
|
|
1404
|
-
children: t("form.fileUploadOpen")
|
|
1405
|
-
})]
|
|
1406
|
-
})]
|
|
1407
|
-
}),
|
|
1408
|
-
status === "uploading" && /* @__PURE__ */ jsxs("div", {
|
|
1409
|
-
className: "nb-form__file-upload-overlay",
|
|
1410
|
-
"aria-live": "polite",
|
|
1411
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
1412
|
-
className: "nb-form__file-upload-spinner",
|
|
1413
|
-
"aria-hidden": "true"
|
|
1414
|
-
}), /* @__PURE__ */ jsx("span", { children: t("form.fileUploading") })]
|
|
1415
|
-
}),
|
|
1416
|
-
isInteractive && status !== "uploading" && /* @__PURE__ */ jsxs("div", {
|
|
1417
|
-
className: "nb-form__file-upload-actions",
|
|
1418
|
-
children: [/* @__PURE__ */ jsxs("button", {
|
|
1419
|
-
type: "button",
|
|
1420
|
-
className: "nb-form__file-upload-action",
|
|
1421
|
-
onClick: (event) => {
|
|
1422
|
-
event.stopPropagation();
|
|
1423
|
-
open();
|
|
1424
|
-
},
|
|
1425
|
-
children: [/* @__PURE__ */ jsx("i", {
|
|
1426
|
-
className: "ph ph-arrows-clockwise",
|
|
1427
|
-
"aria-hidden": "true"
|
|
1428
|
-
}), t("form.fileUploadReplace")]
|
|
1429
|
-
}), /* @__PURE__ */ jsxs("button", {
|
|
1430
|
-
type: "button",
|
|
1431
|
-
className: "nb-form__file-upload-action nb-form__file-upload-action--danger",
|
|
1432
|
-
onClick: (event) => {
|
|
1433
|
-
event.stopPropagation();
|
|
1434
|
-
handleClear();
|
|
1435
|
-
},
|
|
1436
|
-
children: [/* @__PURE__ */ jsx("i", {
|
|
1437
|
-
className: "ph ph-trash",
|
|
1438
|
-
"aria-hidden": "true"
|
|
1439
|
-
}), t("form.fileUploadRemove")]
|
|
1440
|
-
})]
|
|
1441
|
-
})
|
|
1442
|
-
] }) : /* @__PURE__ */ jsxs("div", {
|
|
1443
|
-
className: "nb-form__file-upload-placeholder",
|
|
1444
|
-
children: [
|
|
1445
|
-
/* @__PURE__ */ jsx("span", {
|
|
1446
|
-
className: "nb-form__file-upload-icon",
|
|
1447
|
-
"aria-hidden": "true",
|
|
1448
|
-
children: /* @__PURE__ */ jsx("i", { className: `ph ${placeholderIcon}` })
|
|
1449
|
-
}),
|
|
1450
|
-
/* @__PURE__ */ jsx("span", {
|
|
1451
|
-
className: "nb-form__file-upload-title",
|
|
1452
|
-
children: placeholderTitle
|
|
1453
|
-
}),
|
|
1454
|
-
/* @__PURE__ */ jsx("span", {
|
|
1455
|
-
className: "nb-form__file-upload-hint",
|
|
1456
|
-
children: placeholderHint
|
|
1457
|
-
})
|
|
1458
|
-
]
|
|
1459
|
-
})]
|
|
1460
|
-
}), errorMessage && /* @__PURE__ */ jsxs("span", {
|
|
1461
|
-
className: "nb-form__file-upload-error",
|
|
1462
|
-
role: "alert",
|
|
1463
|
-
children: [/* @__PURE__ */ jsx("i", {
|
|
1464
|
-
className: "ph ph-warning-circle",
|
|
1465
|
-
"aria-hidden": "true"
|
|
1466
|
-
}), errorMessage]
|
|
1467
|
-
})]
|
|
1334
|
+
const value = {
|
|
1335
|
+
fileName,
|
|
1336
|
+
fileUrl,
|
|
1337
|
+
previewUrl
|
|
1338
|
+
};
|
|
1339
|
+
return /* @__PURE__ */ jsx(FileDropzone, {
|
|
1340
|
+
accept: field.accept,
|
|
1341
|
+
disabled,
|
|
1342
|
+
readOnly,
|
|
1343
|
+
invalid,
|
|
1344
|
+
image: imageMode,
|
|
1345
|
+
value,
|
|
1346
|
+
uploading: status === "uploading",
|
|
1347
|
+
error: errorMessage,
|
|
1348
|
+
inputId: `nb-form-${field.name}`,
|
|
1349
|
+
inputLabel: field.label,
|
|
1350
|
+
labels: {
|
|
1351
|
+
dropPrompt: t("form.fileUploadDrop"),
|
|
1352
|
+
prompt: t("form.fileUploadPrompt"),
|
|
1353
|
+
imagePrompt: t("form.imageUploadPrompt"),
|
|
1354
|
+
hint: t("form.fileUploadHint"),
|
|
1355
|
+
imageHint: t("form.imageUploadHint"),
|
|
1356
|
+
uploading: t("form.fileUploading"),
|
|
1357
|
+
replace: t("form.fileUploadReplace"),
|
|
1358
|
+
remove: t("form.fileUploadRemove"),
|
|
1359
|
+
open: t("form.fileUploadOpen")
|
|
1360
|
+
},
|
|
1361
|
+
onFileSelect: (file) => void uploadFile(file),
|
|
1362
|
+
onClear: handleClear
|
|
1468
1363
|
});
|
|
1469
1364
|
}
|
|
1470
1365
|
function isImageFileField(field) {
|
package/dist/style.css
CHANGED
|
@@ -1705,471 +1705,6 @@ html[data-density=compact] .nb-datagrid .nb-badge {
|
|
|
1705
1705
|
box-shadow: none;
|
|
1706
1706
|
}
|
|
1707
1707
|
}
|
|
1708
|
-
.nb-form__file-upload {
|
|
1709
|
-
display: flex;
|
|
1710
|
-
flex-direction: column;
|
|
1711
|
-
gap: var(--space-1);
|
|
1712
|
-
width: 100%;
|
|
1713
|
-
}
|
|
1714
|
-
|
|
1715
|
-
.nb-form__file-upload-zone {
|
|
1716
|
-
align-items: center;
|
|
1717
|
-
background: var(--surface-1);
|
|
1718
|
-
border: 1px dashed var(--border-color);
|
|
1719
|
-
border-radius: var(--radius-lg);
|
|
1720
|
-
box-sizing: border-box;
|
|
1721
|
-
cursor: pointer;
|
|
1722
|
-
display: flex;
|
|
1723
|
-
justify-content: center;
|
|
1724
|
-
min-height: 112px;
|
|
1725
|
-
overflow: hidden;
|
|
1726
|
-
position: relative;
|
|
1727
|
-
transition: border-color var(--transition-base), background var(--transition-base), box-shadow var(--transition-base);
|
|
1728
|
-
width: 100%;
|
|
1729
|
-
}
|
|
1730
|
-
.nb-form__file-upload-zone:hover:not(.nb-form__file-upload-zone--disabled):not(.nb-form__file-upload-zone--filled) {
|
|
1731
|
-
background: color-mix(in srgb, var(--accent-color) 4%, var(--surface-1));
|
|
1732
|
-
border-color: var(--accent-color);
|
|
1733
|
-
}
|
|
1734
|
-
.nb-form__file-upload-zone--active {
|
|
1735
|
-
background: color-mix(in srgb, var(--accent-color) 8%, var(--surface-1));
|
|
1736
|
-
border-color: var(--accent-color);
|
|
1737
|
-
}
|
|
1738
|
-
.nb-form__file-upload-zone--filled {
|
|
1739
|
-
border-style: solid;
|
|
1740
|
-
cursor: default;
|
|
1741
|
-
min-height: 88px;
|
|
1742
|
-
}
|
|
1743
|
-
.nb-form__file-upload-zone--uploading {
|
|
1744
|
-
pointer-events: none;
|
|
1745
|
-
}
|
|
1746
|
-
.nb-form__file-upload-zone--disabled {
|
|
1747
|
-
cursor: not-allowed;
|
|
1748
|
-
opacity: 0.72;
|
|
1749
|
-
}
|
|
1750
|
-
.nb-form__file-upload-zone:focus-visible {
|
|
1751
|
-
box-shadow: 0 0 0 3px var(--focus-ring-color);
|
|
1752
|
-
outline: none;
|
|
1753
|
-
}
|
|
1754
|
-
|
|
1755
|
-
.nb-form__file-upload--image .nb-form__file-upload-zone {
|
|
1756
|
-
min-height: 168px;
|
|
1757
|
-
}
|
|
1758
|
-
|
|
1759
|
-
.nb-form__file-upload--image .nb-form__file-upload-zone--filled {
|
|
1760
|
-
min-height: 180px;
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
.nb-form__file-upload--invalid .nb-form__file-upload-zone {
|
|
1764
|
-
border-color: var(--error-color);
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
.nb-form__file-upload-placeholder {
|
|
1768
|
-
align-items: center;
|
|
1769
|
-
display: flex;
|
|
1770
|
-
flex-direction: column;
|
|
1771
|
-
gap: var(--space-2);
|
|
1772
|
-
max-width: 320px;
|
|
1773
|
-
padding: var(--space-4);
|
|
1774
|
-
text-align: center;
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
.nb-form__file-upload-icon {
|
|
1778
|
-
align-items: center;
|
|
1779
|
-
background: color-mix(in srgb, var(--accent-color) 10%, transparent);
|
|
1780
|
-
border-radius: 999px;
|
|
1781
|
-
color: var(--accent-color);
|
|
1782
|
-
display: inline-flex;
|
|
1783
|
-
font-size: 24px;
|
|
1784
|
-
height: 48px;
|
|
1785
|
-
justify-content: center;
|
|
1786
|
-
width: 48px;
|
|
1787
|
-
}
|
|
1788
|
-
|
|
1789
|
-
.nb-form__file-upload-title {
|
|
1790
|
-
color: var(--text-primary);
|
|
1791
|
-
font-size: var(--font-size-sm);
|
|
1792
|
-
font-weight: var(--font-weight-semibold);
|
|
1793
|
-
}
|
|
1794
|
-
|
|
1795
|
-
.nb-form__file-upload-hint {
|
|
1796
|
-
color: var(--text-tertiary);
|
|
1797
|
-
font-size: var(--font-size-xs);
|
|
1798
|
-
line-height: var(--line-height-tight);
|
|
1799
|
-
}
|
|
1800
|
-
|
|
1801
|
-
.nb-form__file-upload-preview {
|
|
1802
|
-
display: block;
|
|
1803
|
-
height: 100%;
|
|
1804
|
-
max-height: 220px;
|
|
1805
|
-
object-fit: contain;
|
|
1806
|
-
width: 100%;
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
|
-
.nb-form__file-upload-file {
|
|
1810
|
-
align-items: center;
|
|
1811
|
-
display: flex;
|
|
1812
|
-
gap: var(--space-3);
|
|
1813
|
-
max-width: 100%;
|
|
1814
|
-
padding: var(--space-3) var(--space-4);
|
|
1815
|
-
width: 100%;
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
.nb-form__file-upload-file-icon {
|
|
1819
|
-
align-items: center;
|
|
1820
|
-
background: var(--surface-0);
|
|
1821
|
-
border: 1px solid var(--border-subtle);
|
|
1822
|
-
border-radius: var(--radius-md);
|
|
1823
|
-
color: var(--accent-color);
|
|
1824
|
-
display: inline-flex;
|
|
1825
|
-
flex: 0 0 auto;
|
|
1826
|
-
font-size: 22px;
|
|
1827
|
-
height: 44px;
|
|
1828
|
-
justify-content: center;
|
|
1829
|
-
width: 44px;
|
|
1830
|
-
}
|
|
1831
|
-
|
|
1832
|
-
.nb-form__file-upload-file-meta {
|
|
1833
|
-
display: flex;
|
|
1834
|
-
flex: 1 1 auto;
|
|
1835
|
-
flex-direction: column;
|
|
1836
|
-
gap: 2px;
|
|
1837
|
-
min-width: 0;
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
.nb-form__file-upload-file-name {
|
|
1841
|
-
color: var(--text-primary);
|
|
1842
|
-
font-size: var(--font-size-sm);
|
|
1843
|
-
font-weight: var(--font-weight-medium);
|
|
1844
|
-
overflow: hidden;
|
|
1845
|
-
text-overflow: ellipsis;
|
|
1846
|
-
white-space: nowrap;
|
|
1847
|
-
}
|
|
1848
|
-
|
|
1849
|
-
.nb-form__file-upload-file-link {
|
|
1850
|
-
color: var(--accent-color);
|
|
1851
|
-
font-size: var(--font-size-xs);
|
|
1852
|
-
text-decoration: none;
|
|
1853
|
-
}
|
|
1854
|
-
.nb-form__file-upload-file-link:hover {
|
|
1855
|
-
text-decoration: underline;
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
.nb-form__file-upload-overlay {
|
|
1859
|
-
align-items: center;
|
|
1860
|
-
background: rgba(0, 0, 0, 0.42);
|
|
1861
|
-
color: #fff;
|
|
1862
|
-
display: flex;
|
|
1863
|
-
flex-direction: column;
|
|
1864
|
-
font-size: var(--font-size-sm);
|
|
1865
|
-
gap: var(--space-2);
|
|
1866
|
-
inset: 0;
|
|
1867
|
-
justify-content: center;
|
|
1868
|
-
position: absolute;
|
|
1869
|
-
}
|
|
1870
|
-
|
|
1871
|
-
.nb-form__file-upload-spinner {
|
|
1872
|
-
animation: nb-form-file-spin 700ms linear infinite;
|
|
1873
|
-
border: 2px solid rgba(255, 255, 255, 0.35);
|
|
1874
|
-
border-radius: 999px;
|
|
1875
|
-
border-top-color: #fff;
|
|
1876
|
-
height: 24px;
|
|
1877
|
-
width: 24px;
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
@keyframes nb-form-file-spin {
|
|
1881
|
-
to {
|
|
1882
|
-
transform: rotate(360deg);
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
.nb-form__file-upload-actions {
|
|
1886
|
-
align-items: center;
|
|
1887
|
-
background: linear-gradient(to top, rgba(0, 0, 0, 0.58), transparent);
|
|
1888
|
-
bottom: 0;
|
|
1889
|
-
display: flex;
|
|
1890
|
-
gap: var(--space-2);
|
|
1891
|
-
inset-inline: 0;
|
|
1892
|
-
justify-content: center;
|
|
1893
|
-
opacity: 0;
|
|
1894
|
-
padding: var(--space-3);
|
|
1895
|
-
position: absolute;
|
|
1896
|
-
transition: opacity var(--transition-base);
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
.nb-form__file-upload-zone--filled:hover .nb-form__file-upload-actions,
|
|
1900
|
-
.nb-form__file-upload-zone--filled:focus-within .nb-form__file-upload-actions {
|
|
1901
|
-
opacity: 1;
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
.nb-form__file-upload-action {
|
|
1905
|
-
align-items: center;
|
|
1906
|
-
background: var(--surface-1);
|
|
1907
|
-
border: 1px solid var(--border-subtle);
|
|
1908
|
-
border-radius: var(--radius-md);
|
|
1909
|
-
color: var(--text-primary);
|
|
1910
|
-
cursor: pointer;
|
|
1911
|
-
display: inline-flex;
|
|
1912
|
-
font: inherit;
|
|
1913
|
-
font-size: var(--font-size-xs);
|
|
1914
|
-
font-weight: var(--font-weight-medium);
|
|
1915
|
-
gap: var(--space-1);
|
|
1916
|
-
min-height: 28px;
|
|
1917
|
-
padding: 0 var(--space-2);
|
|
1918
|
-
transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
|
|
1919
|
-
}
|
|
1920
|
-
.nb-form__file-upload-action:hover {
|
|
1921
|
-
border-color: var(--accent-color);
|
|
1922
|
-
color: var(--accent-color);
|
|
1923
|
-
}
|
|
1924
|
-
.nb-form__file-upload-action--danger:hover {
|
|
1925
|
-
border-color: var(--error-color);
|
|
1926
|
-
color: var(--error-color);
|
|
1927
|
-
}
|
|
1928
|
-
.nb-form__file-upload-action:focus-visible {
|
|
1929
|
-
box-shadow: 0 0 0 2px var(--focus-ring-color);
|
|
1930
|
-
outline: none;
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
|
-
.nb-form__file-upload-error {
|
|
1934
|
-
align-items: center;
|
|
1935
|
-
color: var(--error-color);
|
|
1936
|
-
display: inline-flex;
|
|
1937
|
-
font-size: var(--font-size-xs);
|
|
1938
|
-
gap: var(--space-1);
|
|
1939
|
-
}
|
|
1940
|
-
.nb-form__file-upload {
|
|
1941
|
-
display: flex;
|
|
1942
|
-
flex-direction: column;
|
|
1943
|
-
gap: var(--space-1);
|
|
1944
|
-
width: 100%;
|
|
1945
|
-
}
|
|
1946
|
-
|
|
1947
|
-
.nb-form__file-upload-zone {
|
|
1948
|
-
align-items: center;
|
|
1949
|
-
background: var(--surface-1);
|
|
1950
|
-
border: 1px dashed var(--border-color);
|
|
1951
|
-
border-radius: var(--radius-lg);
|
|
1952
|
-
box-sizing: border-box;
|
|
1953
|
-
cursor: pointer;
|
|
1954
|
-
display: flex;
|
|
1955
|
-
justify-content: center;
|
|
1956
|
-
min-height: 112px;
|
|
1957
|
-
overflow: hidden;
|
|
1958
|
-
position: relative;
|
|
1959
|
-
transition: border-color var(--transition-base), background var(--transition-base), box-shadow var(--transition-base);
|
|
1960
|
-
width: 100%;
|
|
1961
|
-
}
|
|
1962
|
-
.nb-form__file-upload-zone:hover:not(.nb-form__file-upload-zone--disabled):not(.nb-form__file-upload-zone--filled) {
|
|
1963
|
-
background: color-mix(in srgb, var(--accent-color) 4%, var(--surface-1));
|
|
1964
|
-
border-color: var(--accent-color);
|
|
1965
|
-
}
|
|
1966
|
-
.nb-form__file-upload-zone--active {
|
|
1967
|
-
background: color-mix(in srgb, var(--accent-color) 8%, var(--surface-1));
|
|
1968
|
-
border-color: var(--accent-color);
|
|
1969
|
-
}
|
|
1970
|
-
.nb-form__file-upload-zone--filled {
|
|
1971
|
-
border-style: solid;
|
|
1972
|
-
cursor: default;
|
|
1973
|
-
min-height: 88px;
|
|
1974
|
-
}
|
|
1975
|
-
.nb-form__file-upload-zone--uploading {
|
|
1976
|
-
pointer-events: none;
|
|
1977
|
-
}
|
|
1978
|
-
.nb-form__file-upload-zone--disabled {
|
|
1979
|
-
cursor: not-allowed;
|
|
1980
|
-
opacity: 0.72;
|
|
1981
|
-
}
|
|
1982
|
-
.nb-form__file-upload-zone:focus-visible {
|
|
1983
|
-
box-shadow: 0 0 0 3px var(--focus-ring-color);
|
|
1984
|
-
outline: none;
|
|
1985
|
-
}
|
|
1986
|
-
|
|
1987
|
-
.nb-form__file-upload--image .nb-form__file-upload-zone {
|
|
1988
|
-
min-height: 168px;
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
.nb-form__file-upload--image .nb-form__file-upload-zone--filled {
|
|
1992
|
-
min-height: 180px;
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
|
-
.nb-form__file-upload--invalid .nb-form__file-upload-zone {
|
|
1996
|
-
border-color: var(--error-color);
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
.nb-form__file-upload-placeholder {
|
|
2000
|
-
align-items: center;
|
|
2001
|
-
display: flex;
|
|
2002
|
-
flex-direction: column;
|
|
2003
|
-
gap: var(--space-2);
|
|
2004
|
-
max-width: 320px;
|
|
2005
|
-
padding: var(--space-4);
|
|
2006
|
-
text-align: center;
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
.nb-form__file-upload-icon {
|
|
2010
|
-
align-items: center;
|
|
2011
|
-
background: color-mix(in srgb, var(--accent-color) 10%, transparent);
|
|
2012
|
-
border-radius: 999px;
|
|
2013
|
-
color: var(--accent-color);
|
|
2014
|
-
display: inline-flex;
|
|
2015
|
-
font-size: 24px;
|
|
2016
|
-
height: 48px;
|
|
2017
|
-
justify-content: center;
|
|
2018
|
-
width: 48px;
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
|
-
.nb-form__file-upload-title {
|
|
2022
|
-
color: var(--text-primary);
|
|
2023
|
-
font-size: var(--font-size-sm);
|
|
2024
|
-
font-weight: var(--font-weight-semibold);
|
|
2025
|
-
}
|
|
2026
|
-
|
|
2027
|
-
.nb-form__file-upload-hint {
|
|
2028
|
-
color: var(--text-tertiary);
|
|
2029
|
-
font-size: var(--font-size-xs);
|
|
2030
|
-
line-height: var(--line-height-tight);
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
.nb-form__file-upload-preview {
|
|
2034
|
-
display: block;
|
|
2035
|
-
height: 100%;
|
|
2036
|
-
max-height: 220px;
|
|
2037
|
-
object-fit: contain;
|
|
2038
|
-
width: 100%;
|
|
2039
|
-
}
|
|
2040
|
-
|
|
2041
|
-
.nb-form__file-upload-file {
|
|
2042
|
-
align-items: center;
|
|
2043
|
-
display: flex;
|
|
2044
|
-
gap: var(--space-3);
|
|
2045
|
-
max-width: 100%;
|
|
2046
|
-
padding: var(--space-3) var(--space-4);
|
|
2047
|
-
width: 100%;
|
|
2048
|
-
}
|
|
2049
|
-
|
|
2050
|
-
.nb-form__file-upload-file-icon {
|
|
2051
|
-
align-items: center;
|
|
2052
|
-
background: var(--surface-0);
|
|
2053
|
-
border: 1px solid var(--border-subtle);
|
|
2054
|
-
border-radius: var(--radius-md);
|
|
2055
|
-
color: var(--accent-color);
|
|
2056
|
-
display: inline-flex;
|
|
2057
|
-
flex: 0 0 auto;
|
|
2058
|
-
font-size: 22px;
|
|
2059
|
-
height: 44px;
|
|
2060
|
-
justify-content: center;
|
|
2061
|
-
width: 44px;
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
.nb-form__file-upload-file-meta {
|
|
2065
|
-
display: flex;
|
|
2066
|
-
flex: 1 1 auto;
|
|
2067
|
-
flex-direction: column;
|
|
2068
|
-
gap: 2px;
|
|
2069
|
-
min-width: 0;
|
|
2070
|
-
}
|
|
2071
|
-
|
|
2072
|
-
.nb-form__file-upload-file-name {
|
|
2073
|
-
color: var(--text-primary);
|
|
2074
|
-
font-size: var(--font-size-sm);
|
|
2075
|
-
font-weight: var(--font-weight-medium);
|
|
2076
|
-
overflow: hidden;
|
|
2077
|
-
text-overflow: ellipsis;
|
|
2078
|
-
white-space: nowrap;
|
|
2079
|
-
}
|
|
2080
|
-
|
|
2081
|
-
.nb-form__file-upload-file-link {
|
|
2082
|
-
color: var(--accent-color);
|
|
2083
|
-
font-size: var(--font-size-xs);
|
|
2084
|
-
text-decoration: none;
|
|
2085
|
-
}
|
|
2086
|
-
.nb-form__file-upload-file-link:hover {
|
|
2087
|
-
text-decoration: underline;
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
|
-
.nb-form__file-upload-overlay {
|
|
2091
|
-
align-items: center;
|
|
2092
|
-
background: rgba(0, 0, 0, 0.42);
|
|
2093
|
-
color: #fff;
|
|
2094
|
-
display: flex;
|
|
2095
|
-
flex-direction: column;
|
|
2096
|
-
font-size: var(--font-size-sm);
|
|
2097
|
-
gap: var(--space-2);
|
|
2098
|
-
inset: 0;
|
|
2099
|
-
justify-content: center;
|
|
2100
|
-
position: absolute;
|
|
2101
|
-
}
|
|
2102
|
-
|
|
2103
|
-
.nb-form__file-upload-spinner {
|
|
2104
|
-
animation: nb-form-file-spin 700ms linear infinite;
|
|
2105
|
-
border: 2px solid rgba(255, 255, 255, 0.35);
|
|
2106
|
-
border-radius: 999px;
|
|
2107
|
-
border-top-color: #fff;
|
|
2108
|
-
height: 24px;
|
|
2109
|
-
width: 24px;
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
|
-
@keyframes nb-form-file-spin {
|
|
2113
|
-
to {
|
|
2114
|
-
transform: rotate(360deg);
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
.nb-form__file-upload-actions {
|
|
2118
|
-
align-items: center;
|
|
2119
|
-
background: linear-gradient(to top, rgba(0, 0, 0, 0.58), transparent);
|
|
2120
|
-
bottom: 0;
|
|
2121
|
-
display: flex;
|
|
2122
|
-
gap: var(--space-2);
|
|
2123
|
-
inset-inline: 0;
|
|
2124
|
-
justify-content: center;
|
|
2125
|
-
opacity: 0;
|
|
2126
|
-
padding: var(--space-3);
|
|
2127
|
-
position: absolute;
|
|
2128
|
-
transition: opacity var(--transition-base);
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
.nb-form__file-upload-zone--filled:hover .nb-form__file-upload-actions,
|
|
2132
|
-
.nb-form__file-upload-zone--filled:focus-within .nb-form__file-upload-actions {
|
|
2133
|
-
opacity: 1;
|
|
2134
|
-
}
|
|
2135
|
-
|
|
2136
|
-
.nb-form__file-upload-action {
|
|
2137
|
-
align-items: center;
|
|
2138
|
-
background: var(--surface-1);
|
|
2139
|
-
border: 1px solid var(--border-subtle);
|
|
2140
|
-
border-radius: var(--radius-md);
|
|
2141
|
-
color: var(--text-primary);
|
|
2142
|
-
cursor: pointer;
|
|
2143
|
-
display: inline-flex;
|
|
2144
|
-
font: inherit;
|
|
2145
|
-
font-size: var(--font-size-xs);
|
|
2146
|
-
font-weight: var(--font-weight-medium);
|
|
2147
|
-
gap: var(--space-1);
|
|
2148
|
-
min-height: 28px;
|
|
2149
|
-
padding: 0 var(--space-2);
|
|
2150
|
-
transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
|
|
2151
|
-
}
|
|
2152
|
-
.nb-form__file-upload-action:hover {
|
|
2153
|
-
border-color: var(--accent-color);
|
|
2154
|
-
color: var(--accent-color);
|
|
2155
|
-
}
|
|
2156
|
-
.nb-form__file-upload-action--danger:hover {
|
|
2157
|
-
border-color: var(--error-color);
|
|
2158
|
-
color: var(--error-color);
|
|
2159
|
-
}
|
|
2160
|
-
.nb-form__file-upload-action:focus-visible {
|
|
2161
|
-
box-shadow: 0 0 0 2px var(--focus-ring-color);
|
|
2162
|
-
outline: none;
|
|
2163
|
-
}
|
|
2164
|
-
|
|
2165
|
-
.nb-form__file-upload-error {
|
|
2166
|
-
align-items: center;
|
|
2167
|
-
color: var(--error-color);
|
|
2168
|
-
display: inline-flex;
|
|
2169
|
-
font-size: var(--font-size-xs);
|
|
2170
|
-
gap: var(--space-1);
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
1708
|
.nb-form {
|
|
2174
1709
|
color: var(--text-primary);
|
|
2175
1710
|
display: flex;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nubitio/crud",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Declarative CRUD engine with field DSL, forms, datagrids, RBAC, conditional logic and pluggable adapters (Hydra/REST).",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,10 +56,7 @@
|
|
|
56
56
|
"react-dom": "^19.0.0",
|
|
57
57
|
"react-i18next": "^14.0.0",
|
|
58
58
|
"react-router-dom": "^6.0.0",
|
|
59
|
-
"@nubitio/core": "^0.5.
|
|
60
|
-
"@nubitio/ui": "^0.5.
|
|
61
|
-
},
|
|
62
|
-
"dependencies": {
|
|
63
|
-
"react-dropzone": "^15.0.0"
|
|
59
|
+
"@nubitio/core": "^0.5.16",
|
|
60
|
+
"@nubitio/ui": "^0.5.16"
|
|
64
61
|
}
|
|
65
62
|
}
|