@mshuja288/aksuicore 0.4.0 → 0.4.1

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 CHANGED
@@ -849,6 +849,21 @@ function useIsClient2() {
849
849
  () => false
850
850
  );
851
851
  }
852
+ function useHoverTooltipsEnabled() {
853
+ return react.useSyncExternalStore(
854
+ (onStoreChange) => {
855
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
856
+ return () => {
857
+ };
858
+ }
859
+ const media = window.matchMedia("(hover: hover) and (pointer: fine)");
860
+ media.addEventListener("change", onStoreChange);
861
+ return () => media.removeEventListener("change", onStoreChange);
862
+ },
863
+ () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(hover: hover) and (pointer: fine)").matches,
864
+ () => false
865
+ );
866
+ }
852
867
  var EXPORT_FORMAT_OPTIONS = [
853
868
  { format: "csv", label: "CSV" },
854
869
  { format: "xlsx", label: "Excel" },
@@ -944,6 +959,19 @@ function MoreIcon() {
944
959
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15.5", cy: "10", r: "1.5", fill: "currentColor" })
945
960
  ] });
946
961
  }
962
+ function ToolsIcon() {
963
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
964
+ "path",
965
+ {
966
+ d: "M11.5 3.5h5v5M16.2 3.8 10 10M8.2 5.2H3.8v11h11V12",
967
+ fill: "none",
968
+ stroke: "currentColor",
969
+ strokeWidth: "1.6",
970
+ strokeLinecap: "round",
971
+ strokeLinejoin: "round"
972
+ }
973
+ ) });
974
+ }
947
975
  function DetailList({ lines }) {
948
976
  return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "record-detail-list", children: lines.map((line) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "record-detail-row", children: [
949
977
  /* @__PURE__ */ jsxRuntime.jsx("dt", { children: line.label }),
@@ -987,6 +1015,7 @@ function RecordWorkspace({
987
1015
  const [filters, setFilters] = react.useState({});
988
1016
  const [sort, setSort] = react.useState(null);
989
1017
  const [sideOpen, setSideOpen] = react.useState(false);
1018
+ const [toolsDrawerOpen, setToolsDrawerOpen] = react.useState(false);
990
1019
  const [downloadOpen, setDownloadOpen] = react.useState(false);
991
1020
  const [columnsOpen, setColumnsOpen] = react.useState(false);
992
1021
  const [previewEnabled, setPreviewEnabled] = react.useState(false);
@@ -994,9 +1023,10 @@ function RecordWorkspace({
994
1023
  const [tooltip, setTooltip] = react.useState(null);
995
1024
  const [pageSize, setPageSize] = react.useState("15");
996
1025
  const [page, setPage] = react.useState(1);
997
- const [actionsMenuKey, setActionsMenuKey] = react.useState(null);
1026
+ const [actionsMenu, setActionsMenu] = react.useState(null);
998
1027
  const actionsMenuRef = react.useRef(null);
999
1028
  const isClient = useIsClient2();
1029
+ const hoverTooltipsEnabled = useHoverTooltipsEnabled();
1000
1030
  react.useEffect(() => {
1001
1031
  if (isControlled) {
1002
1032
  return;
@@ -1073,6 +1103,7 @@ function RecordWorkspace({
1073
1103
  [filterableColumns, filters]
1074
1104
  );
1075
1105
  const hiddenColumnCount = columns.length - visibleColumns.length;
1106
+ const toolsBadgeCount = activeFilterCount + (hiddenColumnCount > 0 ? 1 : 0) + (previewEnabled ? 1 : 0);
1076
1107
  const showAll = pageSize === "all";
1077
1108
  const numericPageSize = showAll ? Math.max(sorted.length, 1) : Number(pageSize);
1078
1109
  const pageCount = showAll ? 1 : Math.max(1, Math.ceil(sorted.length / numericPageSize));
@@ -1088,18 +1119,36 @@ function RecordWorkspace({
1088
1119
  key: column.exportKey ?? column.key,
1089
1120
  header: column.header
1090
1121
  }));
1122
+ const canShowTooltip = hoverTooltipsEnabled && !previewEnabled && actionsMenu === null;
1091
1123
  react.useEffect(() => {
1092
- if (actionsMenuKey === null) {
1124
+ if (actionsMenu === null) {
1093
1125
  return;
1094
1126
  }
1095
1127
  function onPointerDown(event) {
1096
1128
  if (actionsMenuRef.current && !actionsMenuRef.current.contains(event.target)) {
1097
- setActionsMenuKey(null);
1129
+ setActionsMenu(null);
1098
1130
  }
1099
1131
  }
1100
1132
  document.addEventListener("mousedown", onPointerDown);
1101
1133
  return () => document.removeEventListener("mousedown", onPointerDown);
1102
- }, [actionsMenuKey]);
1134
+ }, [actionsMenu]);
1135
+ react.useEffect(() => {
1136
+ if (!toolsDrawerOpen) {
1137
+ return;
1138
+ }
1139
+ function onKeyDown(event) {
1140
+ if (event.key === "Escape") {
1141
+ setToolsDrawerOpen(false);
1142
+ }
1143
+ }
1144
+ document.addEventListener("keydown", onKeyDown);
1145
+ const previousOverflow = document.body.style.overflow;
1146
+ document.body.style.overflow = "hidden";
1147
+ return () => {
1148
+ document.removeEventListener("keydown", onKeyDown);
1149
+ document.body.style.overflow = previousOverflow;
1150
+ };
1151
+ }, [toolsDrawerOpen]);
1103
1152
  function requestDownload(format) {
1104
1153
  if (!onDownload || downloadBusy) {
1105
1154
  return;
@@ -1154,13 +1203,244 @@ function RecordWorkspace({
1154
1203
  }
1155
1204
  }
1156
1205
  function showTooltip(item, event) {
1206
+ if (!canShowTooltip) {
1207
+ return;
1208
+ }
1157
1209
  const padding = 16;
1158
1210
  const width = 280;
1159
1211
  const x = Math.min(event.clientX + 14, window.innerWidth - width - padding);
1160
1212
  const y = Math.min(event.clientY + 14, window.innerHeight - padding - 24);
1161
1213
  setTooltip({ x, y, lines: detailLines(item) });
1162
1214
  }
1215
+ function openRowActions(item, event) {
1216
+ event.stopPropagation();
1217
+ setTooltip(null);
1218
+ const key = rowKey(item);
1219
+ if (actionsMenu?.key === key) {
1220
+ setActionsMenu(null);
1221
+ return;
1222
+ }
1223
+ const rect = event.currentTarget.getBoundingClientRect();
1224
+ const menuWidth = 168;
1225
+ const menuHeight = 148;
1226
+ const x = Math.min(Math.max(8, rect.right - menuWidth), window.innerWidth - menuWidth - 8);
1227
+ const y = Math.min(rect.bottom + 6, window.innerHeight - menuHeight - 8);
1228
+ setActionsMenu({ key, item, x, y });
1229
+ }
1163
1230
  const summary = sorted.length === 0 ? "0 records" : showAll ? `1\u2013${sorted.length} of ${sorted.length}` : `${start + 1}\u2013${Math.min(start + numericPageSize, sorted.length)} of ${sorted.length}`;
1231
+ function renderToolsBody({ compactIcons }) {
1232
+ if (compactIcons) {
1233
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-icons", children: [
1234
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-icon preview-check-icon", title: "Preview", children: [
1235
+ /* @__PURE__ */ jsxRuntime.jsx(
1236
+ "input",
1237
+ {
1238
+ type: "checkbox",
1239
+ checked: previewEnabled,
1240
+ onChange: (event) => setPreviewEnabledValue(event.target.checked),
1241
+ "aria-label": "Preview"
1242
+ }
1243
+ ),
1244
+ /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, {})
1245
+ ] }),
1246
+ showAdd ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost side-rail-icon", title: addLabel, "aria-label": addLabel, onClick: onAdd, children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}) }) : null,
1247
+ showColumns ? /* @__PURE__ */ jsxRuntime.jsxs(
1248
+ "button",
1249
+ {
1250
+ type: "button",
1251
+ className: "ghost side-rail-icon",
1252
+ title: "Columns",
1253
+ "aria-label": "Columns",
1254
+ onClick: () => {
1255
+ setSideOpen(true);
1256
+ setColumnsOpen(true);
1257
+ },
1258
+ children: [
1259
+ /* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {}),
1260
+ hiddenColumnCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "filter-badge", children: hiddenColumnCount }) : null
1261
+ ]
1262
+ }
1263
+ ) : null,
1264
+ showDownload ? /* @__PURE__ */ jsxRuntime.jsx(
1265
+ "button",
1266
+ {
1267
+ type: "button",
1268
+ className: "ghost side-rail-icon",
1269
+ title: "Download",
1270
+ "aria-label": "Download",
1271
+ disabled: downloadBusy,
1272
+ onClick: () => {
1273
+ setSideOpen(true);
1274
+ setDownloadOpen(true);
1275
+ },
1276
+ children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {})
1277
+ }
1278
+ ) : null,
1279
+ showFilters ? /* @__PURE__ */ jsxRuntime.jsxs(
1280
+ "button",
1281
+ {
1282
+ type: "button",
1283
+ className: "ghost side-rail-icon",
1284
+ title: "Show filters",
1285
+ "aria-label": "Show filters",
1286
+ onClick: () => setSideOpen(true),
1287
+ children: [
1288
+ /* @__PURE__ */ jsxRuntime.jsx(FilterIcon, {}),
1289
+ activeFilterCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "filter-badge", children: activeFilterCount }) : null
1290
+ ]
1291
+ }
1292
+ ) : null,
1293
+ showFilters ? /* @__PURE__ */ jsxRuntime.jsx(
1294
+ "button",
1295
+ {
1296
+ type: "button",
1297
+ className: "ghost side-rail-icon",
1298
+ title: "Reset filters",
1299
+ "aria-label": "Reset filters",
1300
+ disabled: activeFilterCount === 0,
1301
+ onClick: clearFilters,
1302
+ children: /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, {})
1303
+ }
1304
+ ) : null
1305
+ ] });
1306
+ }
1307
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-body", children: [
1308
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "preview-check", children: [
1309
+ /* @__PURE__ */ jsxRuntime.jsx(
1310
+ "input",
1311
+ {
1312
+ type: "checkbox",
1313
+ checked: previewEnabled,
1314
+ onChange: (event) => setPreviewEnabledValue(event.target.checked),
1315
+ "aria-label": "Preview"
1316
+ }
1317
+ ),
1318
+ /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, {}),
1319
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "Preview" })
1320
+ ] }),
1321
+ showAdd ? /* @__PURE__ */ jsxRuntime.jsxs(
1322
+ "button",
1323
+ {
1324
+ type: "button",
1325
+ className: "side-rail-add",
1326
+ onClick: () => {
1327
+ setToolsDrawerOpen(false);
1328
+ onAdd?.();
1329
+ },
1330
+ children: [
1331
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
1332
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: addLabel })
1333
+ ]
1334
+ }
1335
+ ) : null,
1336
+ showColumns ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns", children: [
1337
+ /* @__PURE__ */ jsxRuntime.jsxs(
1338
+ "button",
1339
+ {
1340
+ type: "button",
1341
+ className: "ghost side-rail-columns-toggle",
1342
+ "aria-expanded": columnsOpen,
1343
+ onClick: () => setColumnsOpen((open) => !open),
1344
+ children: [
1345
+ /* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {}),
1346
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1347
+ "Columns",
1348
+ hiddenColumnCount > 0 ? ` (${visibleColumns.length}/${columns.length})` : ""
1349
+ ] })
1350
+ ]
1351
+ }
1352
+ ),
1353
+ columnsOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns-panel", role: "group", "aria-label": "Visible columns", children: [
1354
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns-actions", children: [
1355
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", onClick: selectAllColumns, children: "Select all" }),
1356
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", onClick: resetColumns, children: "Reset" })
1357
+ ] }),
1358
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "side-rail-columns-list", children: columns.map((column) => {
1359
+ const checked = resolvedVisibleKeys.includes(column.key);
1360
+ const disableUncheck = checked && resolvedVisibleKeys.length <= 1;
1361
+ return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-column-option", children: [
1362
+ /* @__PURE__ */ jsxRuntime.jsx(
1363
+ "input",
1364
+ {
1365
+ type: "checkbox",
1366
+ checked,
1367
+ disabled: disableUncheck,
1368
+ onChange: (event) => toggleColumnVisible(column.key, event.target.checked)
1369
+ }
1370
+ ),
1371
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: column.header })
1372
+ ] }, column.key);
1373
+ }) })
1374
+ ] }) : null
1375
+ ] }) : null,
1376
+ showDownload ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-download", children: [
1377
+ /* @__PURE__ */ jsxRuntime.jsxs(
1378
+ "button",
1379
+ {
1380
+ type: "button",
1381
+ className: "ghost side-rail-download-toggle",
1382
+ "aria-expanded": downloadOpen,
1383
+ disabled: downloadBusy,
1384
+ onClick: () => setDownloadOpen((open) => !open),
1385
+ children: [
1386
+ /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {}),
1387
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: downloadBusy ? "Downloading\u2026" : "Download" })
1388
+ ]
1389
+ }
1390
+ ),
1391
+ downloadOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "side-rail-download-formats", role: "group", "aria-label": "Download format", children: EXPORT_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
1392
+ "button",
1393
+ {
1394
+ type: "button",
1395
+ className: "ghost side-rail-download-format",
1396
+ disabled: downloadBusy,
1397
+ onClick: () => requestDownload(option.format),
1398
+ children: option.label
1399
+ },
1400
+ option.format
1401
+ )) }) : null
1402
+ ] }) : null,
1403
+ showFilters ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-filters", children: [
1404
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "filter-panel-head", children: [
1405
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Filters" }),
1406
+ /* @__PURE__ */ jsxRuntime.jsxs(
1407
+ "button",
1408
+ {
1409
+ type: "button",
1410
+ className: "ghost filter-clear",
1411
+ title: "Reset filters",
1412
+ "aria-label": "Reset filters",
1413
+ disabled: activeFilterCount === 0,
1414
+ onClick: clearFilters,
1415
+ children: [
1416
+ /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, {}),
1417
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Reset" })
1418
+ ]
1419
+ }
1420
+ )
1421
+ ] }),
1422
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "filter-panel-stack", children: filterableColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
1423
+ column.header,
1424
+ column.filterOptions ? /* @__PURE__ */ jsxRuntime.jsx(
1425
+ Select,
1426
+ {
1427
+ value: filters[column.key] ?? "",
1428
+ options: [{ value: "", label: column.filterPlaceholder ?? "All" }, ...column.filterOptions],
1429
+ onChange: (value) => changeFilter(column.key, value),
1430
+ placeholder: column.filterPlaceholder ?? "All"
1431
+ }
1432
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1433
+ "input",
1434
+ {
1435
+ value: filters[column.key] ?? "",
1436
+ onChange: (event) => changeFilter(column.key, event.target.value),
1437
+ placeholder: `Filter ${column.header.toLowerCase()}`
1438
+ }
1439
+ )
1440
+ ] }, column.key)) })
1441
+ ] }) : null
1442
+ ] });
1443
+ }
1164
1444
  function renderRowActions(item) {
1165
1445
  const key = rowKey(item);
1166
1446
  const updateAllowed = canUpdate ? canUpdate(item) : Boolean(onUpdate);
@@ -1195,66 +1475,45 @@ function RecordWorkspace({
1195
1475
  }
1196
1476
  ) : null
1197
1477
  ] }),
1198
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "row-actions row-actions-mobile", ref: actionsMenuKey === key ? actionsMenuRef : void 0, children: [
1199
- /* @__PURE__ */ jsxRuntime.jsx(
1200
- "button",
1201
- {
1202
- type: "button",
1203
- className: "ghost row-action-menu-trigger",
1204
- "aria-haspopup": "menu",
1205
- "aria-expanded": actionsMenuKey === key,
1206
- "aria-label": "Row actions",
1207
- onClick: () => setActionsMenuKey((current) => current === key ? null : key),
1208
- children: /* @__PURE__ */ jsxRuntime.jsx(MoreIcon, {})
1209
- }
1210
- ),
1211
- actionsMenuKey === key ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "row-action-menu", role: "menu", children: [
1212
- onView ? /* @__PURE__ */ jsxRuntime.jsx(
1213
- "button",
1214
- {
1215
- type: "button",
1216
- role: "menuitem",
1217
- className: "ghost",
1218
- onClick: () => {
1219
- setActionsMenuKey(null);
1220
- onView(item);
1221
- },
1222
- children: "View"
1223
- }
1224
- ) : null,
1225
- onUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
1226
- "button",
1227
- {
1228
- type: "button",
1229
- role: "menuitem",
1230
- className: "ghost",
1231
- disabled: !updateAllowed,
1232
- onClick: () => {
1233
- setActionsMenuKey(null);
1234
- onUpdate(item);
1235
- },
1236
- children: "Update"
1237
- }
1238
- ) : null,
1239
- onDelete ? /* @__PURE__ */ jsxRuntime.jsx(
1240
- "button",
1241
- {
1242
- type: "button",
1243
- role: "menuitem",
1244
- className: "ghost danger",
1245
- disabled: !deleteAllowed,
1246
- onClick: () => {
1247
- setActionsMenuKey(null);
1248
- onDelete(item);
1249
- },
1250
- children: "Delete"
1251
- }
1252
- ) : null
1253
- ] }) : null
1254
- ] })
1478
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "row-actions row-actions-mobile", children: /* @__PURE__ */ jsxRuntime.jsx(
1479
+ "button",
1480
+ {
1481
+ type: "button",
1482
+ className: actionsMenu?.key === key ? "ghost row-action-menu-trigger open" : "ghost row-action-menu-trigger",
1483
+ "aria-haspopup": "menu",
1484
+ "aria-expanded": actionsMenu?.key === key,
1485
+ "aria-label": "Row actions",
1486
+ onClick: (event) => openRowActions(item, event),
1487
+ children: /* @__PURE__ */ jsxRuntime.jsx(MoreIcon, {})
1488
+ }
1489
+ ) })
1255
1490
  ] });
1256
1491
  }
1257
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "list-workspace", "aria-label": title, children: [
1492
+ const actionsMenuItem = actionsMenu?.item;
1493
+ const actionsUpdateAllowed = actionsMenuItem ? canUpdate ? canUpdate(actionsMenuItem) : Boolean(onUpdate) : false;
1494
+ const actionsDeleteAllowed = actionsMenuItem ? canDelete ? canDelete(actionsMenuItem) : Boolean(onDelete) : false;
1495
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: toolsDrawerOpen ? "list-workspace tools-drawer-open" : "list-workspace", "aria-label": title, children: [
1496
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tools-mobile-bar", children: [
1497
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tools-mobile-bar-start", children: showAdd ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "tools-mobile-add", onClick: onAdd, children: [
1498
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
1499
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: addLabel })
1500
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "tools-mobile-title", children: title }) }),
1501
+ /* @__PURE__ */ jsxRuntime.jsxs(
1502
+ "button",
1503
+ {
1504
+ type: "button",
1505
+ className: "ghost tools-mobile-toggle",
1506
+ "aria-expanded": toolsDrawerOpen,
1507
+ "aria-controls": "aksui-tools-drawer",
1508
+ onClick: () => setToolsDrawerOpen(true),
1509
+ children: [
1510
+ /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, {}),
1511
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Tools" }),
1512
+ toolsBadgeCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "filter-badge", children: toolsBadgeCount }) : null
1513
+ ]
1514
+ }
1515
+ )
1516
+ ] }),
1258
1517
  /* @__PURE__ */ jsxRuntime.jsxs(
1259
1518
  "div",
1260
1519
  {
@@ -1297,16 +1556,10 @@ function RecordWorkspace({
1297
1556
  {
1298
1557
  className: selected ? "data-row selected" : "data-row",
1299
1558
  onMouseEnter: (event) => {
1300
- if (!previewEnabled) {
1301
- showTooltip(item, event);
1302
- }
1559
+ showTooltip(item, event);
1303
1560
  focusRecord(item);
1304
1561
  },
1305
- onMouseMove: (event) => {
1306
- if (!previewEnabled) {
1307
- showTooltip(item, event);
1308
- }
1309
- },
1562
+ onMouseMove: (event) => showTooltip(item, event),
1310
1563
  onMouseLeave: () => setTooltip(null),
1311
1564
  onClick: () => focusRecord(item),
1312
1565
  children: [
@@ -1338,7 +1591,7 @@ function RecordWorkspace({
1338
1591
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "preview-kicker", children: "Preview" }),
1339
1592
  /* @__PURE__ */ jsxRuntime.jsx("h3", { children: previewTitle ?? "No record selected" })
1340
1593
  ] }) }),
1341
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "preview-panel-body", children: previewItem ? /* @__PURE__ */ jsxRuntime.jsx(DetailList, { lines: detailLines(previewItem) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "preview-empty", children: "Hover or click a row to preview its details here." }) })
1594
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "preview-panel-body", children: previewItem ? /* @__PURE__ */ jsxRuntime.jsx(DetailList, { lines: detailLines(previewItem) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "preview-empty", children: "Select a row to preview its details here." }) })
1342
1595
  ] }) : null,
1343
1596
  /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: sideOpen ? "side-rail open" : "side-rail", "aria-label": "Actions and filters", children: [
1344
1597
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1355,210 +1608,102 @@ function RecordWorkspace({
1355
1608
  ]
1356
1609
  }
1357
1610
  ),
1358
- sideOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-body", children: [
1359
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "preview-check", children: [
1360
- /* @__PURE__ */ jsxRuntime.jsx(
1361
- "input",
1362
- {
1363
- type: "checkbox",
1364
- checked: previewEnabled,
1365
- onChange: (event) => setPreviewEnabledValue(event.target.checked),
1366
- "aria-label": "Preview"
1367
- }
1368
- ),
1369
- /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, {}),
1370
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "Preview" })
1371
- ] }),
1372
- showAdd ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "side-rail-add", onClick: onAdd, children: [
1373
- /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
1374
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: addLabel })
1375
- ] }) : null,
1376
- showColumns ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns", children: [
1377
- /* @__PURE__ */ jsxRuntime.jsxs(
1378
- "button",
1379
- {
1380
- type: "button",
1381
- className: "ghost side-rail-columns-toggle",
1382
- "aria-expanded": columnsOpen,
1383
- onClick: () => setColumnsOpen((open) => !open),
1384
- children: [
1385
- /* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {}),
1386
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1387
- "Columns",
1388
- hiddenColumnCount > 0 ? ` (${visibleColumns.length}/${columns.length})` : ""
1389
- ] })
1390
- ]
1391
- }
1392
- ),
1393
- columnsOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns-panel", role: "group", "aria-label": "Visible columns", children: [
1394
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-columns-actions", children: [
1395
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", onClick: selectAllColumns, children: "Select all" }),
1396
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", onClick: resetColumns, children: "Reset" })
1397
- ] }),
1398
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "side-rail-columns-list", children: columns.map((column) => {
1399
- const checked = resolvedVisibleKeys.includes(column.key);
1400
- const disableUncheck = checked && resolvedVisibleKeys.length <= 1;
1401
- return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-column-option", children: [
1402
- /* @__PURE__ */ jsxRuntime.jsx(
1403
- "input",
1404
- {
1405
- type: "checkbox",
1406
- checked,
1407
- disabled: disableUncheck,
1408
- onChange: (event) => toggleColumnVisible(column.key, event.target.checked)
1409
- }
1410
- ),
1411
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: column.header })
1412
- ] }, column.key);
1413
- }) })
1414
- ] }) : null
1415
- ] }) : null,
1416
- showDownload ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-download", children: [
1417
- /* @__PURE__ */ jsxRuntime.jsxs(
1418
- "button",
1419
- {
1420
- type: "button",
1421
- className: "ghost side-rail-download-toggle",
1422
- "aria-expanded": downloadOpen,
1423
- disabled: downloadBusy,
1424
- onClick: () => setDownloadOpen((open) => !open),
1425
- children: [
1426
- /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {}),
1427
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: downloadBusy ? "Downloading\u2026" : "Download" })
1428
- ]
1429
- }
1430
- ),
1431
- downloadOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "side-rail-download-formats", role: "group", "aria-label": "Download format", children: EXPORT_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
1432
- "button",
1433
- {
1434
- type: "button",
1435
- className: "ghost side-rail-download-format",
1436
- disabled: downloadBusy,
1437
- onClick: () => requestDownload(option.format),
1438
- children: option.label
1439
- },
1440
- option.format
1441
- )) }) : null
1442
- ] }) : null,
1443
- showFilters ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-filters", children: [
1444
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "filter-panel-head", children: [
1445
- /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Filters" }),
1446
- /* @__PURE__ */ jsxRuntime.jsxs(
1447
- "button",
1448
- {
1449
- type: "button",
1450
- className: "ghost filter-clear",
1451
- title: "Reset filters",
1452
- "aria-label": "Reset filters",
1453
- disabled: activeFilterCount === 0,
1454
- onClick: clearFilters,
1455
- children: [
1456
- /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, {}),
1457
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Reset" })
1458
- ]
1459
- }
1460
- )
1461
- ] }),
1462
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "filter-panel-stack", children: filterableColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
1463
- column.header,
1464
- column.filterOptions ? /* @__PURE__ */ jsxRuntime.jsx(
1465
- Select,
1466
- {
1467
- value: filters[column.key] ?? "",
1468
- options: [{ value: "", label: column.filterPlaceholder ?? "All" }, ...column.filterOptions],
1469
- onChange: (value) => changeFilter(column.key, value),
1470
- placeholder: column.filterPlaceholder ?? "All"
1471
- }
1472
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1473
- "input",
1474
- {
1475
- value: filters[column.key] ?? "",
1476
- onChange: (event) => changeFilter(column.key, event.target.value),
1477
- placeholder: `Filter ${column.header.toLowerCase()}`
1478
- }
1479
- )
1480
- ] }, column.key)) })
1481
- ] }) : null
1482
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-icons", children: [
1483
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-icon preview-check-icon", title: "Preview", children: [
1484
- /* @__PURE__ */ jsxRuntime.jsx(
1485
- "input",
1486
- {
1487
- type: "checkbox",
1488
- checked: previewEnabled,
1489
- onChange: (event) => setPreviewEnabledValue(event.target.checked),
1490
- "aria-label": "Preview"
1491
- }
1492
- ),
1493
- /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, {})
1494
- ] }),
1495
- showAdd ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost side-rail-icon", title: addLabel, "aria-label": addLabel, onClick: onAdd, children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}) }) : null,
1496
- showColumns ? /* @__PURE__ */ jsxRuntime.jsxs(
1497
- "button",
1498
- {
1499
- type: "button",
1500
- className: "ghost side-rail-icon",
1501
- title: "Columns",
1502
- "aria-label": "Columns",
1503
- onClick: () => {
1504
- setSideOpen(true);
1505
- setColumnsOpen(true);
1506
- },
1507
- children: [
1508
- /* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {}),
1509
- hiddenColumnCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "filter-badge", children: hiddenColumnCount }) : null
1510
- ]
1511
- }
1512
- ) : null,
1513
- showDownload ? /* @__PURE__ */ jsxRuntime.jsx(
1514
- "button",
1515
- {
1516
- type: "button",
1517
- className: "ghost side-rail-icon",
1518
- title: "Download",
1519
- "aria-label": "Download",
1520
- "aria-expanded": downloadOpen,
1521
- disabled: downloadBusy,
1522
- onClick: () => {
1523
- setSideOpen(true);
1524
- setDownloadOpen(true);
1525
- },
1526
- children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {})
1527
- }
1528
- ) : null,
1529
- showFilters ? /* @__PURE__ */ jsxRuntime.jsxs(
1530
- "button",
1531
- {
1532
- type: "button",
1533
- className: "ghost side-rail-icon",
1534
- title: "Show filters",
1535
- "aria-label": "Show filters",
1536
- onClick: () => setSideOpen(true),
1537
- children: [
1538
- /* @__PURE__ */ jsxRuntime.jsx(FilterIcon, {}),
1539
- activeFilterCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "filter-badge", children: activeFilterCount }) : null
1540
- ]
1541
- }
1542
- ) : null,
1543
- showFilters ? /* @__PURE__ */ jsxRuntime.jsx(
1544
- "button",
1545
- {
1546
- type: "button",
1547
- className: "ghost side-rail-icon",
1548
- title: "Reset filters",
1549
- "aria-label": "Reset filters",
1550
- disabled: activeFilterCount === 0,
1551
- onClick: clearFilters,
1552
- children: /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, {})
1553
- }
1554
- ) : null
1555
- ] })
1611
+ sideOpen ? renderToolsBody({ compactIcons: false }) : renderToolsBody({ compactIcons: true })
1556
1612
  ] })
1557
1613
  ]
1558
1614
  }
1559
1615
  ),
1616
+ isClient ? reactDom.createPortal(
1617
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1618
+ /* @__PURE__ */ jsxRuntime.jsx(
1619
+ "button",
1620
+ {
1621
+ type: "button",
1622
+ className: toolsDrawerOpen ? "tools-drawer-backdrop open" : "tools-drawer-backdrop",
1623
+ "aria-label": "Close tools",
1624
+ tabIndex: toolsDrawerOpen ? 0 : -1,
1625
+ onClick: () => setToolsDrawerOpen(false)
1626
+ }
1627
+ ),
1628
+ /* @__PURE__ */ jsxRuntime.jsxs(
1629
+ "aside",
1630
+ {
1631
+ id: "aksui-tools-drawer",
1632
+ className: toolsDrawerOpen ? "tools-drawer open" : "tools-drawer",
1633
+ "aria-label": "Workspace tools",
1634
+ "aria-hidden": !toolsDrawerOpen,
1635
+ children: [
1636
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tools-drawer-head", children: [
1637
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1638
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "tools-drawer-kicker", children: "Workspace" }),
1639
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Tools" })
1640
+ ] }),
1641
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost tools-drawer-close", onClick: () => setToolsDrawerOpen(false), children: "Close" })
1642
+ ] }),
1643
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tools-drawer-body", children: renderToolsBody({ compactIcons: false }) })
1644
+ ]
1645
+ }
1646
+ )
1647
+ ] }),
1648
+ document.body
1649
+ ) : null,
1560
1650
  form,
1561
- isClient && tooltip && !previewEnabled ? reactDom.createPortal(
1651
+ isClient && actionsMenu && actionsMenuItem ? reactDom.createPortal(
1652
+ /* @__PURE__ */ jsxRuntime.jsxs(
1653
+ "div",
1654
+ {
1655
+ ref: actionsMenuRef,
1656
+ className: "row-action-menu row-action-menu-portal",
1657
+ role: "menu",
1658
+ style: { left: actionsMenu.x, top: actionsMenu.y },
1659
+ children: [
1660
+ onView ? /* @__PURE__ */ jsxRuntime.jsx(
1661
+ "button",
1662
+ {
1663
+ type: "button",
1664
+ role: "menuitem",
1665
+ className: "ghost",
1666
+ onClick: () => {
1667
+ setActionsMenu(null);
1668
+ onView(actionsMenuItem);
1669
+ },
1670
+ children: "View"
1671
+ }
1672
+ ) : null,
1673
+ onUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
1674
+ "button",
1675
+ {
1676
+ type: "button",
1677
+ role: "menuitem",
1678
+ className: "ghost",
1679
+ disabled: !actionsUpdateAllowed,
1680
+ onClick: () => {
1681
+ setActionsMenu(null);
1682
+ onUpdate(actionsMenuItem);
1683
+ },
1684
+ children: "Update"
1685
+ }
1686
+ ) : null,
1687
+ onDelete ? /* @__PURE__ */ jsxRuntime.jsx(
1688
+ "button",
1689
+ {
1690
+ type: "button",
1691
+ role: "menuitem",
1692
+ className: "ghost danger",
1693
+ disabled: !actionsDeleteAllowed,
1694
+ onClick: () => {
1695
+ setActionsMenu(null);
1696
+ onDelete(actionsMenuItem);
1697
+ },
1698
+ children: "Delete"
1699
+ }
1700
+ ) : null
1701
+ ]
1702
+ }
1703
+ ),
1704
+ document.body
1705
+ ) : null,
1706
+ isClient && tooltip && canShowTooltip ? reactDom.createPortal(
1562
1707
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "record-tooltip", style: { left: tooltip.x, top: tooltip.y }, role: "tooltip", children: [
1563
1708
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "record-tooltip-title", children: title }),
1564
1709
  /* @__PURE__ */ jsxRuntime.jsx(DetailList, { lines: tooltip.lines })