@almadar/ui 5.8.1 → 5.9.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/avl/index.cjs +314 -0
- package/dist/avl/index.js +314 -0
- package/dist/components/atoms/AnimatedGraphic.d.ts +2 -0
- package/dist/components/atoms/AnimatedReveal.d.ts +2 -0
- package/dist/components/atoms/Badge.d.ts +2 -0
- package/dist/components/atoms/Box.d.ts +2 -0
- package/dist/components/atoms/Button.d.ts +2 -0
- package/dist/components/atoms/Card.d.ts +2 -0
- package/dist/components/atoms/Checkbox.d.ts +2 -0
- package/dist/components/atoms/FilterPill.d.ts +2 -0
- package/dist/components/atoms/Input.d.ts +2 -0
- package/dist/components/atoms/Label.d.ts +2 -0
- package/dist/components/atoms/Radio.d.ts +2 -0
- package/dist/components/atoms/RangeSlider.d.ts +2 -0
- package/dist/components/atoms/Select.d.ts +2 -0
- package/dist/components/atoms/Spinner.d.ts +2 -0
- package/dist/components/atoms/StatusDot.d.ts +2 -0
- package/dist/components/atoms/Textarea.d.ts +2 -0
- package/dist/components/atoms/TrendIndicator.d.ts +2 -0
- package/dist/components/index.cjs +318 -2
- package/dist/components/index.js +318 -3
- package/dist/components/molecules/TableView.d.ts +107 -0
- package/dist/components/molecules/index.d.ts +1 -0
- package/dist/docs/index.d.cts +8 -0
- package/dist/marketing/index.d.cts +12 -0
- package/dist/providers/index.cjs +314 -0
- package/dist/providers/index.js +314 -0
- package/dist/runtime/index.cjs +314 -0
- package/dist/runtime/index.js +314 -0
- package/package.json +1 -1
package/dist/providers/index.cjs
CHANGED
|
@@ -29236,6 +29236,318 @@ var init_Lightbox = __esm({
|
|
|
29236
29236
|
Lightbox.displayName = "Lightbox";
|
|
29237
29237
|
}
|
|
29238
29238
|
});
|
|
29239
|
+
function columnLabel(col) {
|
|
29240
|
+
return col.header ?? col.label ?? col.key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
29241
|
+
}
|
|
29242
|
+
function statusVariant4(value) {
|
|
29243
|
+
const v = value.toLowerCase();
|
|
29244
|
+
if (["active", "completed", "done", "approved", "published", "resolved", "open", "online", "ok"].includes(v)) return "success";
|
|
29245
|
+
if (["pending", "in_progress", "in-progress", "review", "draft", "processing", "warn", "warning"].includes(v)) return "warning";
|
|
29246
|
+
if (["inactive", "deleted", "rejected", "failed", "error", "blocked", "closed", "offline"].includes(v)) return "error";
|
|
29247
|
+
if (["new", "created", "scheduled", "queued", "info"].includes(v)) return "info";
|
|
29248
|
+
return "default";
|
|
29249
|
+
}
|
|
29250
|
+
function formatCell(value, format) {
|
|
29251
|
+
if (value === void 0 || value === null) return "";
|
|
29252
|
+
switch (format) {
|
|
29253
|
+
case "date": {
|
|
29254
|
+
const d = new Date(String(value));
|
|
29255
|
+
return isNaN(d.getTime()) ? String(value) : d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
29256
|
+
}
|
|
29257
|
+
case "currency":
|
|
29258
|
+
return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
|
|
29259
|
+
case "number":
|
|
29260
|
+
return typeof value === "number" ? value.toLocaleString() : String(value);
|
|
29261
|
+
case "percent":
|
|
29262
|
+
return typeof value === "number" ? `${Math.round(value)}%` : String(value);
|
|
29263
|
+
case "boolean":
|
|
29264
|
+
return value ? "Yes" : "No";
|
|
29265
|
+
default:
|
|
29266
|
+
return String(value);
|
|
29267
|
+
}
|
|
29268
|
+
}
|
|
29269
|
+
function groupData2(items, field) {
|
|
29270
|
+
const groups = /* @__PURE__ */ new Map();
|
|
29271
|
+
for (const item of items) {
|
|
29272
|
+
const key = String(getNestedValue(item, field) ?? "");
|
|
29273
|
+
const group = groups.get(key);
|
|
29274
|
+
if (group) group.push(item);
|
|
29275
|
+
else groups.set(key, [item]);
|
|
29276
|
+
}
|
|
29277
|
+
return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
29278
|
+
}
|
|
29279
|
+
function TableView({
|
|
29280
|
+
entity,
|
|
29281
|
+
columns,
|
|
29282
|
+
fields,
|
|
29283
|
+
itemActions,
|
|
29284
|
+
selectable = false,
|
|
29285
|
+
selectEvent,
|
|
29286
|
+
selectedIds,
|
|
29287
|
+
sortEvent,
|
|
29288
|
+
sortColumn,
|
|
29289
|
+
sortDirection,
|
|
29290
|
+
className,
|
|
29291
|
+
emptyMessage,
|
|
29292
|
+
isLoading = false,
|
|
29293
|
+
error = null,
|
|
29294
|
+
groupBy,
|
|
29295
|
+
pageSize = 0,
|
|
29296
|
+
children,
|
|
29297
|
+
renderItem: _schemaRenderItem,
|
|
29298
|
+
look = "dense",
|
|
29299
|
+
// DnD props consumed by useDataDnd.
|
|
29300
|
+
dragGroup,
|
|
29301
|
+
accepts,
|
|
29302
|
+
sortable,
|
|
29303
|
+
dropEvent,
|
|
29304
|
+
reorderEvent,
|
|
29305
|
+
positionEvent,
|
|
29306
|
+
dndItemIdField,
|
|
29307
|
+
dndRoot
|
|
29308
|
+
}) {
|
|
29309
|
+
const eventBus = useEventBus();
|
|
29310
|
+
const { t } = useTranslate();
|
|
29311
|
+
const [visibleCount, setVisibleCount] = React86__namespace.default.useState(pageSize > 0 ? pageSize : Infinity);
|
|
29312
|
+
const [localSelected, setLocalSelected] = React86__namespace.default.useState(/* @__PURE__ */ new Set());
|
|
29313
|
+
const colDefs = columns ?? fields ?? [];
|
|
29314
|
+
const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
29315
|
+
const dnd = useDataDnd({
|
|
29316
|
+
items: allDataRaw,
|
|
29317
|
+
layout: "list",
|
|
29318
|
+
dragGroup,
|
|
29319
|
+
accepts,
|
|
29320
|
+
sortable,
|
|
29321
|
+
dropEvent,
|
|
29322
|
+
reorderEvent,
|
|
29323
|
+
positionEvent,
|
|
29324
|
+
dndItemIdField,
|
|
29325
|
+
dndRoot
|
|
29326
|
+
});
|
|
29327
|
+
const ordered = dnd.orderedItems;
|
|
29328
|
+
const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
|
|
29329
|
+
const hasMore = pageSize > 0 && visibleCount < ordered.length;
|
|
29330
|
+
const hasRenderProp = typeof children === "function";
|
|
29331
|
+
const idField = dndItemIdField ?? "id";
|
|
29332
|
+
const selected = selectedIds ? new Set(selectedIds) : localSelected;
|
|
29333
|
+
const emitSelection = (next) => {
|
|
29334
|
+
if (!selectedIds) setLocalSelected(next);
|
|
29335
|
+
if (selectEvent) {
|
|
29336
|
+
const payload = { selectedIds: Array.from(next) };
|
|
29337
|
+
eventBus.emit(`UI:${selectEvent}`, payload);
|
|
29338
|
+
}
|
|
29339
|
+
};
|
|
29340
|
+
const allSelected = selectable && data.length > 0 && data.every((r, i) => selected.has(String(r[idField] ?? i)));
|
|
29341
|
+
const toggleAll = () => {
|
|
29342
|
+
if (allSelected) emitSelection(/* @__PURE__ */ new Set());
|
|
29343
|
+
else emitSelection(new Set(data.map((r, i) => String(r[idField] ?? i))));
|
|
29344
|
+
};
|
|
29345
|
+
const toggleRow = (id) => {
|
|
29346
|
+
const next = new Set(selected);
|
|
29347
|
+
if (next.has(id)) next.delete(id);
|
|
29348
|
+
else next.add(id);
|
|
29349
|
+
emitSelection(next);
|
|
29350
|
+
};
|
|
29351
|
+
const handleSort = (col) => {
|
|
29352
|
+
if (!col.sortable || !sortEvent) return;
|
|
29353
|
+
const dir = sortColumn === (col.field ?? col.key) && sortDirection === "asc" ? "desc" : "asc";
|
|
29354
|
+
eventBus.emit(`UI:${sortEvent}`, { column: col.field ?? col.key, direction: dir });
|
|
29355
|
+
};
|
|
29356
|
+
const handleActionClick = (action, row) => (e) => {
|
|
29357
|
+
e.stopPropagation();
|
|
29358
|
+
const payload = {
|
|
29359
|
+
id: row.id,
|
|
29360
|
+
row
|
|
29361
|
+
};
|
|
29362
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
29363
|
+
};
|
|
29364
|
+
if (isLoading) {
|
|
29365
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading\u2026" }) });
|
|
29366
|
+
}
|
|
29367
|
+
if (error) {
|
|
29368
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
29369
|
+
}
|
|
29370
|
+
if (data.length === 0) {
|
|
29371
|
+
const emptyNode = /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: emptyMessage || t("empty.noItems") || "No records" }) });
|
|
29372
|
+
return dnd.enabled ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: dnd.wrapContainer(emptyNode) }) : emptyNode;
|
|
29373
|
+
}
|
|
29374
|
+
const lk = LOOKS[look];
|
|
29375
|
+
const hasActions = Boolean(itemActions && itemActions.length > 0);
|
|
29376
|
+
const gridTemplateColumns = [
|
|
29377
|
+
selectable ? "auto" : null,
|
|
29378
|
+
...colDefs.map((c) => c.width ?? "minmax(0, 1fr)"),
|
|
29379
|
+
hasActions ? "auto" : null
|
|
29380
|
+
].filter(Boolean).join(" ");
|
|
29381
|
+
const header = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29382
|
+
Box,
|
|
29383
|
+
{
|
|
29384
|
+
role: "row",
|
|
29385
|
+
style: { gridTemplateColumns },
|
|
29386
|
+
className: cn(
|
|
29387
|
+
"grid items-center gap-3 sticky top-0 z-10",
|
|
29388
|
+
"bg-[var(--color-surface-subtle)] border-b border-[var(--color-border)]",
|
|
29389
|
+
"text-[var(--color-text-muted)] uppercase text-xs font-semibold tracking-wide",
|
|
29390
|
+
lk.headPad
|
|
29391
|
+
),
|
|
29392
|
+
children: [
|
|
29393
|
+
selectable && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { checked: allSelected, onChange: toggleAll, "aria-label": "Select all rows" }) }),
|
|
29394
|
+
colDefs.map((col) => {
|
|
29395
|
+
const active = sortColumn === (col.field ?? col.key);
|
|
29396
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29397
|
+
Box,
|
|
29398
|
+
{
|
|
29399
|
+
role: "columnheader",
|
|
29400
|
+
onClick: () => handleSort(col),
|
|
29401
|
+
className: cn(
|
|
29402
|
+
"flex items-center gap-1 min-w-0",
|
|
29403
|
+
alignClass[col.align ?? "left"],
|
|
29404
|
+
col.sortable && sortEvent && "cursor-pointer select-none hover:text-foreground"
|
|
29405
|
+
),
|
|
29406
|
+
children: [
|
|
29407
|
+
col.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: col.icon, size: "xs" }),
|
|
29408
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: columnLabel(col) }),
|
|
29409
|
+
col.sortable && sortEvent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29410
|
+
Icon,
|
|
29411
|
+
{
|
|
29412
|
+
name: active ? sortDirection === "asc" ? "chevron-up" : "chevron-down" : "chevrons-up-down",
|
|
29413
|
+
size: "xs",
|
|
29414
|
+
className: cn("flex-shrink-0", active ? "text-foreground" : "opacity-40")
|
|
29415
|
+
}
|
|
29416
|
+
)
|
|
29417
|
+
]
|
|
29418
|
+
},
|
|
29419
|
+
col.key
|
|
29420
|
+
);
|
|
29421
|
+
}),
|
|
29422
|
+
hasActions && /* @__PURE__ */ jsxRuntime.jsx(Box, { "aria-hidden": true })
|
|
29423
|
+
]
|
|
29424
|
+
}
|
|
29425
|
+
);
|
|
29426
|
+
const renderRow = (row, index) => {
|
|
29427
|
+
const id = String(row[idField] ?? index);
|
|
29428
|
+
const rowInner = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29429
|
+
Box,
|
|
29430
|
+
{
|
|
29431
|
+
role: "row",
|
|
29432
|
+
"data-entity-row": true,
|
|
29433
|
+
"data-entity-id": id,
|
|
29434
|
+
style: !hasRenderProp ? { gridTemplateColumns } : void 0,
|
|
29435
|
+
className: cn(
|
|
29436
|
+
"group items-center gap-3 transition-colors duration-fast",
|
|
29437
|
+
hasRenderProp ? "flex" : "grid",
|
|
29438
|
+
lk.rowPad,
|
|
29439
|
+
lk.divider && "border-b border-[var(--color-border)]",
|
|
29440
|
+
lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
|
|
29441
|
+
"hover:bg-[var(--color-surface-subtle)]",
|
|
29442
|
+
look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
|
|
29443
|
+
),
|
|
29444
|
+
children: [
|
|
29445
|
+
selectable && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29446
|
+
Checkbox,
|
|
29447
|
+
{
|
|
29448
|
+
checked: selected.has(id),
|
|
29449
|
+
onChange: () => toggleRow(id),
|
|
29450
|
+
"aria-label": `Select row ${id}`
|
|
29451
|
+
}
|
|
29452
|
+
) }),
|
|
29453
|
+
hasRenderProp ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 min-w-0", children: children(row, index) }) : colDefs.map((col) => {
|
|
29454
|
+
const raw = getNestedValue(row, col.field ?? col.key);
|
|
29455
|
+
const cellBase = cn(
|
|
29456
|
+
"flex items-center min-w-0",
|
|
29457
|
+
alignClass[col.align ?? "left"],
|
|
29458
|
+
weightClass[col.weight ?? "normal"],
|
|
29459
|
+
col.className
|
|
29460
|
+
);
|
|
29461
|
+
if (col.format === "badge" && raw != null && raw !== "") {
|
|
29462
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: statusVariant4(String(raw)), size: "sm", children: String(raw) }) }, col.key);
|
|
29463
|
+
}
|
|
29464
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
|
|
29465
|
+
}),
|
|
29466
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", className: "flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: itemActions.map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29467
|
+
Button,
|
|
29468
|
+
{
|
|
29469
|
+
variant: action.variant ?? "ghost",
|
|
29470
|
+
size: "sm",
|
|
29471
|
+
onClick: handleActionClick(action, row),
|
|
29472
|
+
"data-testid": `action-${action.event}`,
|
|
29473
|
+
"data-row-id": String(row.id),
|
|
29474
|
+
className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
|
|
29475
|
+
children: [
|
|
29476
|
+
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
29477
|
+
action.label
|
|
29478
|
+
]
|
|
29479
|
+
},
|
|
29480
|
+
i
|
|
29481
|
+
)) })
|
|
29482
|
+
]
|
|
29483
|
+
}
|
|
29484
|
+
);
|
|
29485
|
+
return dnd.isZone ? /* @__PURE__ */ jsxRuntime.jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsxRuntime.jsx(React86__namespace.default.Fragment, { children: rowInner }, id);
|
|
29486
|
+
};
|
|
29487
|
+
const items = data.map((row) => row);
|
|
29488
|
+
const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
|
|
29489
|
+
let runningIndex = 0;
|
|
29490
|
+
const body = /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React86__namespace.default.Fragment, { children: [
|
|
29491
|
+
group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
|
|
29492
|
+
group.items.map((row) => renderRow(row, runningIndex++))
|
|
29493
|
+
] }, gi)) });
|
|
29494
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29495
|
+
Box,
|
|
29496
|
+
{
|
|
29497
|
+
role: "table",
|
|
29498
|
+
className: cn("w-full text-sm", className),
|
|
29499
|
+
children: [
|
|
29500
|
+
header,
|
|
29501
|
+
dnd.wrapContainer(body),
|
|
29502
|
+
hasMore && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setVisibleCount((p2) => p2 + (pageSize || 5)), children: [
|
|
29503
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
29504
|
+
t("common.showMore"),
|
|
29505
|
+
" (",
|
|
29506
|
+
ordered.length - visibleCount,
|
|
29507
|
+
" remaining)"
|
|
29508
|
+
] }) })
|
|
29509
|
+
]
|
|
29510
|
+
}
|
|
29511
|
+
);
|
|
29512
|
+
}
|
|
29513
|
+
var alignClass, weightClass, LOOKS;
|
|
29514
|
+
var init_TableView = __esm({
|
|
29515
|
+
"components/molecules/TableView.tsx"() {
|
|
29516
|
+
"use client";
|
|
29517
|
+
init_cn();
|
|
29518
|
+
init_getNestedValue();
|
|
29519
|
+
init_useEventBus();
|
|
29520
|
+
init_useTranslate();
|
|
29521
|
+
init_Box();
|
|
29522
|
+
init_Stack();
|
|
29523
|
+
init_Typography();
|
|
29524
|
+
init_Badge();
|
|
29525
|
+
init_Button();
|
|
29526
|
+
init_Icon();
|
|
29527
|
+
init_Checkbox();
|
|
29528
|
+
init_Divider();
|
|
29529
|
+
init_useDataDnd();
|
|
29530
|
+
logger.createLogger("almadar:ui:table-view");
|
|
29531
|
+
alignClass = {
|
|
29532
|
+
left: "justify-start text-left",
|
|
29533
|
+
center: "justify-center text-center",
|
|
29534
|
+
right: "justify-end text-right"
|
|
29535
|
+
};
|
|
29536
|
+
weightClass = {
|
|
29537
|
+
normal: "",
|
|
29538
|
+
medium: "font-medium",
|
|
29539
|
+
semibold: "font-semibold"
|
|
29540
|
+
};
|
|
29541
|
+
LOOKS = {
|
|
29542
|
+
dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
|
|
29543
|
+
spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
|
|
29544
|
+
striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
|
|
29545
|
+
borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
|
|
29546
|
+
bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
|
|
29547
|
+
};
|
|
29548
|
+
TableView.displayName = "TableView";
|
|
29549
|
+
}
|
|
29550
|
+
});
|
|
29239
29551
|
function formatNumber(value, format) {
|
|
29240
29552
|
if (value == null) return "0";
|
|
29241
29553
|
const v = typeof value === "number" ? value : value;
|
|
@@ -46293,6 +46605,7 @@ var init_component_registry_generated = __esm({
|
|
|
46293
46605
|
init_Switch();
|
|
46294
46606
|
init_TabbedContainer();
|
|
46295
46607
|
init_Table();
|
|
46608
|
+
init_TableView();
|
|
46296
46609
|
init_Tabs();
|
|
46297
46610
|
init_TagCloud();
|
|
46298
46611
|
init_TagInput();
|
|
@@ -46610,6 +46923,7 @@ var init_component_registry_generated = __esm({
|
|
|
46610
46923
|
"Switch": Switch,
|
|
46611
46924
|
"TabbedContainer": TabbedContainer,
|
|
46612
46925
|
"Table": Table,
|
|
46926
|
+
"TableView": TableView,
|
|
46613
46927
|
"Tabs": Tabs,
|
|
46614
46928
|
"TagCloud": TagCloud,
|
|
46615
46929
|
"TagInput": TagInput,
|
package/dist/providers/index.js
CHANGED
|
@@ -29187,6 +29187,318 @@ var init_Lightbox = __esm({
|
|
|
29187
29187
|
Lightbox.displayName = "Lightbox";
|
|
29188
29188
|
}
|
|
29189
29189
|
});
|
|
29190
|
+
function columnLabel(col) {
|
|
29191
|
+
return col.header ?? col.label ?? col.key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
29192
|
+
}
|
|
29193
|
+
function statusVariant4(value) {
|
|
29194
|
+
const v = value.toLowerCase();
|
|
29195
|
+
if (["active", "completed", "done", "approved", "published", "resolved", "open", "online", "ok"].includes(v)) return "success";
|
|
29196
|
+
if (["pending", "in_progress", "in-progress", "review", "draft", "processing", "warn", "warning"].includes(v)) return "warning";
|
|
29197
|
+
if (["inactive", "deleted", "rejected", "failed", "error", "blocked", "closed", "offline"].includes(v)) return "error";
|
|
29198
|
+
if (["new", "created", "scheduled", "queued", "info"].includes(v)) return "info";
|
|
29199
|
+
return "default";
|
|
29200
|
+
}
|
|
29201
|
+
function formatCell(value, format) {
|
|
29202
|
+
if (value === void 0 || value === null) return "";
|
|
29203
|
+
switch (format) {
|
|
29204
|
+
case "date": {
|
|
29205
|
+
const d = new Date(String(value));
|
|
29206
|
+
return isNaN(d.getTime()) ? String(value) : d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
29207
|
+
}
|
|
29208
|
+
case "currency":
|
|
29209
|
+
return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
|
|
29210
|
+
case "number":
|
|
29211
|
+
return typeof value === "number" ? value.toLocaleString() : String(value);
|
|
29212
|
+
case "percent":
|
|
29213
|
+
return typeof value === "number" ? `${Math.round(value)}%` : String(value);
|
|
29214
|
+
case "boolean":
|
|
29215
|
+
return value ? "Yes" : "No";
|
|
29216
|
+
default:
|
|
29217
|
+
return String(value);
|
|
29218
|
+
}
|
|
29219
|
+
}
|
|
29220
|
+
function groupData2(items, field) {
|
|
29221
|
+
const groups = /* @__PURE__ */ new Map();
|
|
29222
|
+
for (const item of items) {
|
|
29223
|
+
const key = String(getNestedValue(item, field) ?? "");
|
|
29224
|
+
const group = groups.get(key);
|
|
29225
|
+
if (group) group.push(item);
|
|
29226
|
+
else groups.set(key, [item]);
|
|
29227
|
+
}
|
|
29228
|
+
return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
29229
|
+
}
|
|
29230
|
+
function TableView({
|
|
29231
|
+
entity,
|
|
29232
|
+
columns,
|
|
29233
|
+
fields,
|
|
29234
|
+
itemActions,
|
|
29235
|
+
selectable = false,
|
|
29236
|
+
selectEvent,
|
|
29237
|
+
selectedIds,
|
|
29238
|
+
sortEvent,
|
|
29239
|
+
sortColumn,
|
|
29240
|
+
sortDirection,
|
|
29241
|
+
className,
|
|
29242
|
+
emptyMessage,
|
|
29243
|
+
isLoading = false,
|
|
29244
|
+
error = null,
|
|
29245
|
+
groupBy,
|
|
29246
|
+
pageSize = 0,
|
|
29247
|
+
children,
|
|
29248
|
+
renderItem: _schemaRenderItem,
|
|
29249
|
+
look = "dense",
|
|
29250
|
+
// DnD props consumed by useDataDnd.
|
|
29251
|
+
dragGroup,
|
|
29252
|
+
accepts,
|
|
29253
|
+
sortable,
|
|
29254
|
+
dropEvent,
|
|
29255
|
+
reorderEvent,
|
|
29256
|
+
positionEvent,
|
|
29257
|
+
dndItemIdField,
|
|
29258
|
+
dndRoot
|
|
29259
|
+
}) {
|
|
29260
|
+
const eventBus = useEventBus();
|
|
29261
|
+
const { t } = useTranslate();
|
|
29262
|
+
const [visibleCount, setVisibleCount] = React86__default.useState(pageSize > 0 ? pageSize : Infinity);
|
|
29263
|
+
const [localSelected, setLocalSelected] = React86__default.useState(/* @__PURE__ */ new Set());
|
|
29264
|
+
const colDefs = columns ?? fields ?? [];
|
|
29265
|
+
const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
29266
|
+
const dnd = useDataDnd({
|
|
29267
|
+
items: allDataRaw,
|
|
29268
|
+
layout: "list",
|
|
29269
|
+
dragGroup,
|
|
29270
|
+
accepts,
|
|
29271
|
+
sortable,
|
|
29272
|
+
dropEvent,
|
|
29273
|
+
reorderEvent,
|
|
29274
|
+
positionEvent,
|
|
29275
|
+
dndItemIdField,
|
|
29276
|
+
dndRoot
|
|
29277
|
+
});
|
|
29278
|
+
const ordered = dnd.orderedItems;
|
|
29279
|
+
const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
|
|
29280
|
+
const hasMore = pageSize > 0 && visibleCount < ordered.length;
|
|
29281
|
+
const hasRenderProp = typeof children === "function";
|
|
29282
|
+
const idField = dndItemIdField ?? "id";
|
|
29283
|
+
const selected = selectedIds ? new Set(selectedIds) : localSelected;
|
|
29284
|
+
const emitSelection = (next) => {
|
|
29285
|
+
if (!selectedIds) setLocalSelected(next);
|
|
29286
|
+
if (selectEvent) {
|
|
29287
|
+
const payload = { selectedIds: Array.from(next) };
|
|
29288
|
+
eventBus.emit(`UI:${selectEvent}`, payload);
|
|
29289
|
+
}
|
|
29290
|
+
};
|
|
29291
|
+
const allSelected = selectable && data.length > 0 && data.every((r, i) => selected.has(String(r[idField] ?? i)));
|
|
29292
|
+
const toggleAll = () => {
|
|
29293
|
+
if (allSelected) emitSelection(/* @__PURE__ */ new Set());
|
|
29294
|
+
else emitSelection(new Set(data.map((r, i) => String(r[idField] ?? i))));
|
|
29295
|
+
};
|
|
29296
|
+
const toggleRow = (id) => {
|
|
29297
|
+
const next = new Set(selected);
|
|
29298
|
+
if (next.has(id)) next.delete(id);
|
|
29299
|
+
else next.add(id);
|
|
29300
|
+
emitSelection(next);
|
|
29301
|
+
};
|
|
29302
|
+
const handleSort = (col) => {
|
|
29303
|
+
if (!col.sortable || !sortEvent) return;
|
|
29304
|
+
const dir = sortColumn === (col.field ?? col.key) && sortDirection === "asc" ? "desc" : "asc";
|
|
29305
|
+
eventBus.emit(`UI:${sortEvent}`, { column: col.field ?? col.key, direction: dir });
|
|
29306
|
+
};
|
|
29307
|
+
const handleActionClick = (action, row) => (e) => {
|
|
29308
|
+
e.stopPropagation();
|
|
29309
|
+
const payload = {
|
|
29310
|
+
id: row.id,
|
|
29311
|
+
row
|
|
29312
|
+
};
|
|
29313
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
29314
|
+
};
|
|
29315
|
+
if (isLoading) {
|
|
29316
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading\u2026" }) });
|
|
29317
|
+
}
|
|
29318
|
+
if (error) {
|
|
29319
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
29320
|
+
}
|
|
29321
|
+
if (data.length === 0) {
|
|
29322
|
+
const emptyNode = /* @__PURE__ */ jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: emptyMessage || t("empty.noItems") || "No records" }) });
|
|
29323
|
+
return dnd.enabled ? /* @__PURE__ */ jsx(Fragment, { children: dnd.wrapContainer(emptyNode) }) : emptyNode;
|
|
29324
|
+
}
|
|
29325
|
+
const lk = LOOKS[look];
|
|
29326
|
+
const hasActions = Boolean(itemActions && itemActions.length > 0);
|
|
29327
|
+
const gridTemplateColumns = [
|
|
29328
|
+
selectable ? "auto" : null,
|
|
29329
|
+
...colDefs.map((c) => c.width ?? "minmax(0, 1fr)"),
|
|
29330
|
+
hasActions ? "auto" : null
|
|
29331
|
+
].filter(Boolean).join(" ");
|
|
29332
|
+
const header = /* @__PURE__ */ jsxs(
|
|
29333
|
+
Box,
|
|
29334
|
+
{
|
|
29335
|
+
role: "row",
|
|
29336
|
+
style: { gridTemplateColumns },
|
|
29337
|
+
className: cn(
|
|
29338
|
+
"grid items-center gap-3 sticky top-0 z-10",
|
|
29339
|
+
"bg-[var(--color-surface-subtle)] border-b border-[var(--color-border)]",
|
|
29340
|
+
"text-[var(--color-text-muted)] uppercase text-xs font-semibold tracking-wide",
|
|
29341
|
+
lk.headPad
|
|
29342
|
+
),
|
|
29343
|
+
children: [
|
|
29344
|
+
selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(Checkbox, { checked: allSelected, onChange: toggleAll, "aria-label": "Select all rows" }) }),
|
|
29345
|
+
colDefs.map((col) => {
|
|
29346
|
+
const active = sortColumn === (col.field ?? col.key);
|
|
29347
|
+
return /* @__PURE__ */ jsxs(
|
|
29348
|
+
Box,
|
|
29349
|
+
{
|
|
29350
|
+
role: "columnheader",
|
|
29351
|
+
onClick: () => handleSort(col),
|
|
29352
|
+
className: cn(
|
|
29353
|
+
"flex items-center gap-1 min-w-0",
|
|
29354
|
+
alignClass[col.align ?? "left"],
|
|
29355
|
+
col.sortable && sortEvent && "cursor-pointer select-none hover:text-foreground"
|
|
29356
|
+
),
|
|
29357
|
+
children: [
|
|
29358
|
+
col.icon && /* @__PURE__ */ jsx(Icon, { name: col.icon, size: "xs" }),
|
|
29359
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: columnLabel(col) }),
|
|
29360
|
+
col.sortable && sortEvent && /* @__PURE__ */ jsx(
|
|
29361
|
+
Icon,
|
|
29362
|
+
{
|
|
29363
|
+
name: active ? sortDirection === "asc" ? "chevron-up" : "chevron-down" : "chevrons-up-down",
|
|
29364
|
+
size: "xs",
|
|
29365
|
+
className: cn("flex-shrink-0", active ? "text-foreground" : "opacity-40")
|
|
29366
|
+
}
|
|
29367
|
+
)
|
|
29368
|
+
]
|
|
29369
|
+
},
|
|
29370
|
+
col.key
|
|
29371
|
+
);
|
|
29372
|
+
}),
|
|
29373
|
+
hasActions && /* @__PURE__ */ jsx(Box, { "aria-hidden": true })
|
|
29374
|
+
]
|
|
29375
|
+
}
|
|
29376
|
+
);
|
|
29377
|
+
const renderRow = (row, index) => {
|
|
29378
|
+
const id = String(row[idField] ?? index);
|
|
29379
|
+
const rowInner = /* @__PURE__ */ jsxs(
|
|
29380
|
+
Box,
|
|
29381
|
+
{
|
|
29382
|
+
role: "row",
|
|
29383
|
+
"data-entity-row": true,
|
|
29384
|
+
"data-entity-id": id,
|
|
29385
|
+
style: !hasRenderProp ? { gridTemplateColumns } : void 0,
|
|
29386
|
+
className: cn(
|
|
29387
|
+
"group items-center gap-3 transition-colors duration-fast",
|
|
29388
|
+
hasRenderProp ? "flex" : "grid",
|
|
29389
|
+
lk.rowPad,
|
|
29390
|
+
lk.divider && "border-b border-[var(--color-border)]",
|
|
29391
|
+
lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
|
|
29392
|
+
"hover:bg-[var(--color-surface-subtle)]",
|
|
29393
|
+
look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
|
|
29394
|
+
),
|
|
29395
|
+
children: [
|
|
29396
|
+
selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(
|
|
29397
|
+
Checkbox,
|
|
29398
|
+
{
|
|
29399
|
+
checked: selected.has(id),
|
|
29400
|
+
onChange: () => toggleRow(id),
|
|
29401
|
+
"aria-label": `Select row ${id}`
|
|
29402
|
+
}
|
|
29403
|
+
) }),
|
|
29404
|
+
hasRenderProp ? /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(row, index) }) : colDefs.map((col) => {
|
|
29405
|
+
const raw = getNestedValue(row, col.field ?? col.key);
|
|
29406
|
+
const cellBase = cn(
|
|
29407
|
+
"flex items-center min-w-0",
|
|
29408
|
+
alignClass[col.align ?? "left"],
|
|
29409
|
+
weightClass[col.weight ?? "normal"],
|
|
29410
|
+
col.className
|
|
29411
|
+
);
|
|
29412
|
+
if (col.format === "badge" && raw != null && raw !== "") {
|
|
29413
|
+
return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx(Badge, { variant: statusVariant4(String(raw)), size: "sm", children: String(raw) }) }, col.key);
|
|
29414
|
+
}
|
|
29415
|
+
return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
|
|
29416
|
+
}),
|
|
29417
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: itemActions.map((action, i) => /* @__PURE__ */ jsxs(
|
|
29418
|
+
Button,
|
|
29419
|
+
{
|
|
29420
|
+
variant: action.variant ?? "ghost",
|
|
29421
|
+
size: "sm",
|
|
29422
|
+
onClick: handleActionClick(action, row),
|
|
29423
|
+
"data-testid": `action-${action.event}`,
|
|
29424
|
+
"data-row-id": String(row.id),
|
|
29425
|
+
className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
|
|
29426
|
+
children: [
|
|
29427
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
29428
|
+
action.label
|
|
29429
|
+
]
|
|
29430
|
+
},
|
|
29431
|
+
i
|
|
29432
|
+
)) })
|
|
29433
|
+
]
|
|
29434
|
+
}
|
|
29435
|
+
);
|
|
29436
|
+
return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React86__default.Fragment, { children: rowInner }, id);
|
|
29437
|
+
};
|
|
29438
|
+
const items = data.map((row) => row);
|
|
29439
|
+
const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
|
|
29440
|
+
let runningIndex = 0;
|
|
29441
|
+
const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
|
|
29442
|
+
group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
|
|
29443
|
+
group.items.map((row) => renderRow(row, runningIndex++))
|
|
29444
|
+
] }, gi)) });
|
|
29445
|
+
return /* @__PURE__ */ jsxs(
|
|
29446
|
+
Box,
|
|
29447
|
+
{
|
|
29448
|
+
role: "table",
|
|
29449
|
+
className: cn("w-full text-sm", className),
|
|
29450
|
+
children: [
|
|
29451
|
+
header,
|
|
29452
|
+
dnd.wrapContainer(body),
|
|
29453
|
+
hasMore && /* @__PURE__ */ jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setVisibleCount((p2) => p2 + (pageSize || 5)), children: [
|
|
29454
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
29455
|
+
t("common.showMore"),
|
|
29456
|
+
" (",
|
|
29457
|
+
ordered.length - visibleCount,
|
|
29458
|
+
" remaining)"
|
|
29459
|
+
] }) })
|
|
29460
|
+
]
|
|
29461
|
+
}
|
|
29462
|
+
);
|
|
29463
|
+
}
|
|
29464
|
+
var alignClass, weightClass, LOOKS;
|
|
29465
|
+
var init_TableView = __esm({
|
|
29466
|
+
"components/molecules/TableView.tsx"() {
|
|
29467
|
+
"use client";
|
|
29468
|
+
init_cn();
|
|
29469
|
+
init_getNestedValue();
|
|
29470
|
+
init_useEventBus();
|
|
29471
|
+
init_useTranslate();
|
|
29472
|
+
init_Box();
|
|
29473
|
+
init_Stack();
|
|
29474
|
+
init_Typography();
|
|
29475
|
+
init_Badge();
|
|
29476
|
+
init_Button();
|
|
29477
|
+
init_Icon();
|
|
29478
|
+
init_Checkbox();
|
|
29479
|
+
init_Divider();
|
|
29480
|
+
init_useDataDnd();
|
|
29481
|
+
createLogger("almadar:ui:table-view");
|
|
29482
|
+
alignClass = {
|
|
29483
|
+
left: "justify-start text-left",
|
|
29484
|
+
center: "justify-center text-center",
|
|
29485
|
+
right: "justify-end text-right"
|
|
29486
|
+
};
|
|
29487
|
+
weightClass = {
|
|
29488
|
+
normal: "",
|
|
29489
|
+
medium: "font-medium",
|
|
29490
|
+
semibold: "font-semibold"
|
|
29491
|
+
};
|
|
29492
|
+
LOOKS = {
|
|
29493
|
+
dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
|
|
29494
|
+
spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
|
|
29495
|
+
striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
|
|
29496
|
+
borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
|
|
29497
|
+
bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
|
|
29498
|
+
};
|
|
29499
|
+
TableView.displayName = "TableView";
|
|
29500
|
+
}
|
|
29501
|
+
});
|
|
29190
29502
|
function formatNumber(value, format) {
|
|
29191
29503
|
if (value == null) return "0";
|
|
29192
29504
|
const v = typeof value === "number" ? value : value;
|
|
@@ -46244,6 +46556,7 @@ var init_component_registry_generated = __esm({
|
|
|
46244
46556
|
init_Switch();
|
|
46245
46557
|
init_TabbedContainer();
|
|
46246
46558
|
init_Table();
|
|
46559
|
+
init_TableView();
|
|
46247
46560
|
init_Tabs();
|
|
46248
46561
|
init_TagCloud();
|
|
46249
46562
|
init_TagInput();
|
|
@@ -46561,6 +46874,7 @@ var init_component_registry_generated = __esm({
|
|
|
46561
46874
|
"Switch": Switch,
|
|
46562
46875
|
"TabbedContainer": TabbedContainer,
|
|
46563
46876
|
"Table": Table,
|
|
46877
|
+
"TableView": TableView,
|
|
46564
46878
|
"Tabs": Tabs,
|
|
46565
46879
|
"TagCloud": TagCloud,
|
|
46566
46880
|
"TagInput": TagInput,
|