@mshuja288/aksuicore 0.4.1 → 0.4.2
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/aksui.css +75 -1
- package/dist/index.cjs +133 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -2
- package/dist/index.d.ts +20 -2
- package/dist/index.js +133 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
- package/src/patterns/RecordWorkspace.tsx +157 -1
- package/src/patterns/index.ts +3 -0
- package/src/theme/patterns.css +75 -1
package/dist/aksui.css
CHANGED
|
@@ -1222,7 +1222,8 @@ button.side-rail-add:hover {
|
|
|
1222
1222
|
}
|
|
1223
1223
|
|
|
1224
1224
|
.side-rail-columns,
|
|
1225
|
-
.side-rail-download
|
|
1225
|
+
.side-rail-download,
|
|
1226
|
+
.side-rail-bulk {
|
|
1226
1227
|
display: grid;
|
|
1227
1228
|
gap: 8px;
|
|
1228
1229
|
}
|
|
@@ -1350,6 +1351,79 @@ button.side-rail-download-format:disabled {
|
|
|
1350
1351
|
cursor: default;
|
|
1351
1352
|
}
|
|
1352
1353
|
|
|
1354
|
+
button.side-rail-bulk-toggle {
|
|
1355
|
+
display: inline-flex;
|
|
1356
|
+
align-items: center;
|
|
1357
|
+
justify-content: center;
|
|
1358
|
+
gap: 8px;
|
|
1359
|
+
width: 100%;
|
|
1360
|
+
padding: 10px 12px;
|
|
1361
|
+
border: 1px solid var(--aks-border, #d7dde5);
|
|
1362
|
+
border-radius: var(--aks-radius);
|
|
1363
|
+
background: #fff;
|
|
1364
|
+
color: var(--aks-brand);
|
|
1365
|
+
box-shadow: none;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
button.side-rail-bulk-toggle svg {
|
|
1369
|
+
width: 18px;
|
|
1370
|
+
height: 18px;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
button.side-rail-bulk-toggle:hover:not(:disabled) {
|
|
1374
|
+
background: #f5f7fa;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
button.side-rail-bulk-toggle:disabled {
|
|
1378
|
+
opacity: 0.55;
|
|
1379
|
+
cursor: default;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
.side-rail-bulk-panel {
|
|
1383
|
+
display: grid;
|
|
1384
|
+
gap: 10px;
|
|
1385
|
+
padding: 8px;
|
|
1386
|
+
border: 1px solid var(--aks-line);
|
|
1387
|
+
border-radius: var(--aks-radius);
|
|
1388
|
+
background: #faf9f7;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
label.side-rail-bulk-mode,
|
|
1392
|
+
label.side-rail-bulk-file {
|
|
1393
|
+
display: grid;
|
|
1394
|
+
gap: 6px;
|
|
1395
|
+
margin: 0;
|
|
1396
|
+
font-size: 13px;
|
|
1397
|
+
font-weight: 600;
|
|
1398
|
+
color: var(--aks-brand);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
button.side-rail-bulk-submit {
|
|
1402
|
+
width: 100%;
|
|
1403
|
+
padding: 10px 12px;
|
|
1404
|
+
border: none;
|
|
1405
|
+
border-radius: var(--aks-radius);
|
|
1406
|
+
background: var(--aks-accent, #c45c26);
|
|
1407
|
+
color: #fff;
|
|
1408
|
+
font-weight: 600;
|
|
1409
|
+
box-shadow: none;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
button.side-rail-bulk-submit:disabled {
|
|
1413
|
+
opacity: 0.5;
|
|
1414
|
+
cursor: default;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
.side-rail-bulk-report {
|
|
1418
|
+
font-size: 12px;
|
|
1419
|
+
color: var(--aks-brand);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
.side-rail-bulk-errors {
|
|
1423
|
+
margin: 6px 0 0;
|
|
1424
|
+
padding-left: 18px;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1353
1427
|
.side-rail-filters {
|
|
1354
1428
|
display: grid;
|
|
1355
1429
|
gap: 12px;
|
package/dist/index.cjs
CHANGED
|
@@ -869,6 +869,11 @@ var EXPORT_FORMAT_OPTIONS = [
|
|
|
869
869
|
{ format: "xlsx", label: "Excel" },
|
|
870
870
|
{ format: "json", label: "JSON" }
|
|
871
871
|
];
|
|
872
|
+
var BULK_IMPORT_MODE_OPTIONS = [
|
|
873
|
+
{ mode: "insert", label: "Insert" },
|
|
874
|
+
{ mode: "update", label: "Update" },
|
|
875
|
+
{ mode: "upsert", label: "Upsert" }
|
|
876
|
+
];
|
|
872
877
|
function defaultVisibleKeys(columns) {
|
|
873
878
|
return columns.filter((column) => column.defaultVisible !== false).map((column) => column.key);
|
|
874
879
|
}
|
|
@@ -945,6 +950,13 @@ function PreviewIcon() {
|
|
|
945
950
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "2.4", fill: "none", stroke: "currentColor", strokeWidth: "1.6" })
|
|
946
951
|
] });
|
|
947
952
|
}
|
|
953
|
+
function UploadIcon() {
|
|
954
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
|
|
955
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 16.5V7.3", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
956
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.5 10.8 10 7.2l3.5 3.6", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
957
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4.5h12", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
|
|
958
|
+
] });
|
|
959
|
+
}
|
|
948
960
|
function DownloadIcon() {
|
|
949
961
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
|
|
950
962
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3.5v8.2", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
@@ -994,7 +1006,11 @@ function RecordWorkspace({
|
|
|
994
1006
|
canDelete,
|
|
995
1007
|
onDownload,
|
|
996
1008
|
canDownload = true,
|
|
1009
|
+
canExport,
|
|
997
1010
|
downloadBusy = false,
|
|
1011
|
+
onBulkImport,
|
|
1012
|
+
canImport = true,
|
|
1013
|
+
importBusy = false,
|
|
998
1014
|
showColumnPicker = true,
|
|
999
1015
|
columnPrefsKey,
|
|
1000
1016
|
visibleColumnKeys,
|
|
@@ -1017,6 +1033,11 @@ function RecordWorkspace({
|
|
|
1017
1033
|
const [sideOpen, setSideOpen] = react.useState(false);
|
|
1018
1034
|
const [toolsDrawerOpen, setToolsDrawerOpen] = react.useState(false);
|
|
1019
1035
|
const [downloadOpen, setDownloadOpen] = react.useState(false);
|
|
1036
|
+
const [bulkOpen, setBulkOpen] = react.useState(false);
|
|
1037
|
+
const [bulkMode, setBulkMode] = react.useState("upsert");
|
|
1038
|
+
const [bulkFile, setBulkFile] = react.useState(null);
|
|
1039
|
+
const [bulkReport, setBulkReport] = react.useState(null);
|
|
1040
|
+
const bulkFileInputRef = react.useRef(null);
|
|
1020
1041
|
const [columnsOpen, setColumnsOpen] = react.useState(false);
|
|
1021
1042
|
const [previewEnabled, setPreviewEnabled] = react.useState(false);
|
|
1022
1043
|
const [previewKey, setPreviewKey] = react.useState(null);
|
|
@@ -1111,7 +1132,9 @@ function RecordWorkspace({
|
|
|
1111
1132
|
const start = showAll ? 0 : (currentPage - 1) * numericPageSize;
|
|
1112
1133
|
const pageItems = showAll ? sorted : sorted.slice(start, start + numericPageSize);
|
|
1113
1134
|
const showAdd = canAdd && Boolean(onAdd);
|
|
1114
|
-
const
|
|
1135
|
+
const exportAllowed = (canExport ?? true) && canDownload;
|
|
1136
|
+
const showDownload = Boolean(onDownload) && exportAllowed;
|
|
1137
|
+
const showBulkImport = Boolean(onBulkImport) && canImport;
|
|
1115
1138
|
const showFilters = filterableColumns.length > 0;
|
|
1116
1139
|
const showColumns = showColumnPicker && columns.length > 0;
|
|
1117
1140
|
const previewItem = previewKey === null ? null : sorted.find((item) => rowKey(item) === previewKey) ?? null;
|
|
@@ -1156,6 +1179,29 @@ function RecordWorkspace({
|
|
|
1156
1179
|
onDownload(format, exportColumns);
|
|
1157
1180
|
setDownloadOpen(false);
|
|
1158
1181
|
}
|
|
1182
|
+
async function submitBulkImport() {
|
|
1183
|
+
if (!onBulkImport || importBusy || !bulkFile) {
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
setBulkReport(null);
|
|
1187
|
+
try {
|
|
1188
|
+
const report = await onBulkImport(bulkMode, bulkFile);
|
|
1189
|
+
setBulkReport(report);
|
|
1190
|
+
if (report.applied) {
|
|
1191
|
+
setBulkFile(null);
|
|
1192
|
+
if (bulkFileInputRef.current) {
|
|
1193
|
+
bulkFileInputRef.current.value = "";
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
} catch {
|
|
1197
|
+
setBulkReport({
|
|
1198
|
+
totalRows: 0,
|
|
1199
|
+
failed: 1,
|
|
1200
|
+
applied: false,
|
|
1201
|
+
errors: [{ row: 0, code: "ImportFailed", message: "Import request failed." }]
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1159
1205
|
function cellText(column, item) {
|
|
1160
1206
|
const raw = column.display ? column.display(item) : column.value(item);
|
|
1161
1207
|
return raw === null || raw === void 0 || raw === "" ? "\u2014" : String(raw);
|
|
@@ -1276,6 +1322,21 @@ function RecordWorkspace({
|
|
|
1276
1322
|
children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {})
|
|
1277
1323
|
}
|
|
1278
1324
|
) : null,
|
|
1325
|
+
showBulkImport ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1326
|
+
"button",
|
|
1327
|
+
{
|
|
1328
|
+
type: "button",
|
|
1329
|
+
className: "ghost side-rail-icon",
|
|
1330
|
+
title: "Bulk entry",
|
|
1331
|
+
"aria-label": "Bulk entry",
|
|
1332
|
+
disabled: importBusy,
|
|
1333
|
+
onClick: () => {
|
|
1334
|
+
setSideOpen(true);
|
|
1335
|
+
setBulkOpen(true);
|
|
1336
|
+
},
|
|
1337
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(UploadIcon, {})
|
|
1338
|
+
}
|
|
1339
|
+
) : null,
|
|
1279
1340
|
showFilters ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1280
1341
|
"button",
|
|
1281
1342
|
{
|
|
@@ -1400,6 +1461,77 @@ function RecordWorkspace({
|
|
|
1400
1461
|
option.format
|
|
1401
1462
|
)) }) : null
|
|
1402
1463
|
] }) : null,
|
|
1464
|
+
showBulkImport ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-bulk", children: [
|
|
1465
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1466
|
+
"button",
|
|
1467
|
+
{
|
|
1468
|
+
type: "button",
|
|
1469
|
+
className: "ghost side-rail-bulk-toggle",
|
|
1470
|
+
"aria-expanded": bulkOpen,
|
|
1471
|
+
disabled: importBusy,
|
|
1472
|
+
onClick: () => setBulkOpen((open) => !open),
|
|
1473
|
+
children: [
|
|
1474
|
+
/* @__PURE__ */ jsxRuntime.jsx(UploadIcon, {}),
|
|
1475
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: importBusy ? "Importing\u2026" : "Bulk entry" })
|
|
1476
|
+
]
|
|
1477
|
+
}
|
|
1478
|
+
),
|
|
1479
|
+
bulkOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-bulk-panel", role: "group", "aria-label": "Bulk entry", children: [
|
|
1480
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-bulk-mode", children: [
|
|
1481
|
+
"Mode",
|
|
1482
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1483
|
+
Select,
|
|
1484
|
+
{
|
|
1485
|
+
value: bulkMode,
|
|
1486
|
+
options: BULK_IMPORT_MODE_OPTIONS.map((option) => ({ value: option.mode, label: option.label })),
|
|
1487
|
+
onChange: (value) => setBulkMode(value)
|
|
1488
|
+
}
|
|
1489
|
+
)
|
|
1490
|
+
] }),
|
|
1491
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-bulk-file", children: [
|
|
1492
|
+
"File",
|
|
1493
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1494
|
+
"input",
|
|
1495
|
+
{
|
|
1496
|
+
ref: bulkFileInputRef,
|
|
1497
|
+
type: "file",
|
|
1498
|
+
accept: ".csv,.xlsx,.json",
|
|
1499
|
+
disabled: importBusy,
|
|
1500
|
+
onChange: (event) => {
|
|
1501
|
+
setBulkFile(event.target.files?.[0] ?? null);
|
|
1502
|
+
setBulkReport(null);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
)
|
|
1506
|
+
] }),
|
|
1507
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1508
|
+
"button",
|
|
1509
|
+
{
|
|
1510
|
+
type: "button",
|
|
1511
|
+
className: "side-rail-bulk-submit",
|
|
1512
|
+
disabled: importBusy || !bulkFile,
|
|
1513
|
+
onClick: () => void submitBulkImport(),
|
|
1514
|
+
children: importBusy ? "Importing\u2026" : "Import"
|
|
1515
|
+
}
|
|
1516
|
+
),
|
|
1517
|
+
bulkReport ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-bulk-report", role: "status", children: [
|
|
1518
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: bulkReport.applied ? `Applied ${bulkReport.totalRows} row(s).` : `${bulkReport.failed} error(s) in ${bulkReport.totalRows} row(s).` }),
|
|
1519
|
+
bulkReport.errors.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "side-rail-bulk-errors", children: [
|
|
1520
|
+
bulkReport.errors.slice(0, 8).map((error, index) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
1521
|
+
"Row ",
|
|
1522
|
+
error.row,
|
|
1523
|
+
": ",
|
|
1524
|
+
error.message
|
|
1525
|
+
] }, `${error.row}-${error.code}-${index}`)),
|
|
1526
|
+
bulkReport.errors.length > 8 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
1527
|
+
"\u2026and ",
|
|
1528
|
+
bulkReport.errors.length - 8,
|
|
1529
|
+
" more"
|
|
1530
|
+
] }) : null
|
|
1531
|
+
] }) : null
|
|
1532
|
+
] }) : null
|
|
1533
|
+
] }) : null
|
|
1534
|
+
] }) : null,
|
|
1403
1535
|
showFilters ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-filters", children: [
|
|
1404
1536
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "filter-panel-head", children: [
|
|
1405
1537
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Filters" }),
|