@almadar/ui 5.8.0 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +308 -1
- package/dist/avl/index.js +308 -1
- 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 +312 -3
- package/dist/components/index.js +312 -4
- package/dist/components/molecules/TableView.d.ts +105 -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 +308 -1
- package/dist/providers/index.js +308 -1
- package/dist/runtime/index.cjs +308 -1
- package/dist/runtime/index.js +308 -1
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -32824,6 +32824,311 @@ var init_Lightbox = __esm({
|
|
|
32824
32824
|
Lightbox.displayName = "Lightbox";
|
|
32825
32825
|
}
|
|
32826
32826
|
});
|
|
32827
|
+
function columnLabel(col) {
|
|
32828
|
+
return col.header ?? col.label ?? col.key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
32829
|
+
}
|
|
32830
|
+
function statusVariant4(value) {
|
|
32831
|
+
const v = value.toLowerCase();
|
|
32832
|
+
if (["active", "completed", "done", "approved", "published", "resolved", "open", "online", "ok"].includes(v)) return "success";
|
|
32833
|
+
if (["pending", "in_progress", "in-progress", "review", "draft", "processing", "warn", "warning"].includes(v)) return "warning";
|
|
32834
|
+
if (["inactive", "deleted", "rejected", "failed", "error", "blocked", "closed", "offline"].includes(v)) return "error";
|
|
32835
|
+
if (["new", "created", "scheduled", "queued", "info"].includes(v)) return "info";
|
|
32836
|
+
return "default";
|
|
32837
|
+
}
|
|
32838
|
+
function formatCell(value, format) {
|
|
32839
|
+
if (value === void 0 || value === null) return "";
|
|
32840
|
+
switch (format) {
|
|
32841
|
+
case "date": {
|
|
32842
|
+
const d = new Date(String(value));
|
|
32843
|
+
return isNaN(d.getTime()) ? String(value) : d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
32844
|
+
}
|
|
32845
|
+
case "currency":
|
|
32846
|
+
return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
|
|
32847
|
+
case "number":
|
|
32848
|
+
return typeof value === "number" ? value.toLocaleString() : String(value);
|
|
32849
|
+
case "percent":
|
|
32850
|
+
return typeof value === "number" ? `${Math.round(value)}%` : String(value);
|
|
32851
|
+
case "boolean":
|
|
32852
|
+
return value ? "Yes" : "No";
|
|
32853
|
+
default:
|
|
32854
|
+
return String(value);
|
|
32855
|
+
}
|
|
32856
|
+
}
|
|
32857
|
+
function groupData2(items, field) {
|
|
32858
|
+
const groups = /* @__PURE__ */ new Map();
|
|
32859
|
+
for (const item of items) {
|
|
32860
|
+
const key = String(getNestedValue(item, field) ?? "");
|
|
32861
|
+
const group = groups.get(key);
|
|
32862
|
+
if (group) group.push(item);
|
|
32863
|
+
else groups.set(key, [item]);
|
|
32864
|
+
}
|
|
32865
|
+
return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
32866
|
+
}
|
|
32867
|
+
function TableView({
|
|
32868
|
+
entity,
|
|
32869
|
+
columns,
|
|
32870
|
+
fields,
|
|
32871
|
+
itemActions,
|
|
32872
|
+
selectable = false,
|
|
32873
|
+
selectEvent,
|
|
32874
|
+
selectedIds,
|
|
32875
|
+
sortEvent,
|
|
32876
|
+
sortColumn,
|
|
32877
|
+
sortDirection,
|
|
32878
|
+
className,
|
|
32879
|
+
emptyMessage,
|
|
32880
|
+
isLoading = false,
|
|
32881
|
+
error = null,
|
|
32882
|
+
groupBy,
|
|
32883
|
+
pageSize = 0,
|
|
32884
|
+
children,
|
|
32885
|
+
renderItem: _schemaRenderItem,
|
|
32886
|
+
look = "dense",
|
|
32887
|
+
// DnD props consumed by useDataDnd.
|
|
32888
|
+
dragGroup,
|
|
32889
|
+
accepts,
|
|
32890
|
+
sortable,
|
|
32891
|
+
dropEvent,
|
|
32892
|
+
reorderEvent,
|
|
32893
|
+
positionEvent,
|
|
32894
|
+
dndItemIdField,
|
|
32895
|
+
dndRoot
|
|
32896
|
+
}) {
|
|
32897
|
+
const eventBus = useEventBus();
|
|
32898
|
+
const { t } = useTranslate();
|
|
32899
|
+
const [visibleCount, setVisibleCount] = React98__namespace.default.useState(pageSize > 0 ? pageSize : Infinity);
|
|
32900
|
+
const [localSelected, setLocalSelected] = React98__namespace.default.useState(/* @__PURE__ */ new Set());
|
|
32901
|
+
const colDefs = columns ?? fields ?? [];
|
|
32902
|
+
const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
32903
|
+
const dnd = useDataDnd({
|
|
32904
|
+
items: allDataRaw,
|
|
32905
|
+
layout: "list",
|
|
32906
|
+
dragGroup,
|
|
32907
|
+
accepts,
|
|
32908
|
+
sortable,
|
|
32909
|
+
dropEvent,
|
|
32910
|
+
reorderEvent,
|
|
32911
|
+
positionEvent,
|
|
32912
|
+
dndItemIdField,
|
|
32913
|
+
dndRoot
|
|
32914
|
+
});
|
|
32915
|
+
const ordered = dnd.orderedItems;
|
|
32916
|
+
const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
|
|
32917
|
+
const hasMore = pageSize > 0 && visibleCount < ordered.length;
|
|
32918
|
+
const hasRenderProp = typeof children === "function";
|
|
32919
|
+
const idField = dndItemIdField ?? "id";
|
|
32920
|
+
const selected = selectedIds ? new Set(selectedIds) : localSelected;
|
|
32921
|
+
const emitSelection = (next) => {
|
|
32922
|
+
if (!selectedIds) setLocalSelected(next);
|
|
32923
|
+
if (selectEvent) {
|
|
32924
|
+
const payload = { selectedIds: Array.from(next) };
|
|
32925
|
+
eventBus.emit(`UI:${selectEvent}`, payload);
|
|
32926
|
+
}
|
|
32927
|
+
};
|
|
32928
|
+
const allSelected = selectable && data.length > 0 && data.every((r2, i) => selected.has(String(r2[idField] ?? i)));
|
|
32929
|
+
const toggleAll = () => {
|
|
32930
|
+
if (allSelected) emitSelection(/* @__PURE__ */ new Set());
|
|
32931
|
+
else emitSelection(new Set(data.map((r2, i) => String(r2[idField] ?? i))));
|
|
32932
|
+
};
|
|
32933
|
+
const toggleRow = (id) => {
|
|
32934
|
+
const next = new Set(selected);
|
|
32935
|
+
if (next.has(id)) next.delete(id);
|
|
32936
|
+
else next.add(id);
|
|
32937
|
+
emitSelection(next);
|
|
32938
|
+
};
|
|
32939
|
+
const handleSort = (col) => {
|
|
32940
|
+
if (!col.sortable || !sortEvent) return;
|
|
32941
|
+
const dir = sortColumn === (col.field ?? col.key) && sortDirection === "asc" ? "desc" : "asc";
|
|
32942
|
+
eventBus.emit(`UI:${sortEvent}`, { column: col.field ?? col.key, direction: dir });
|
|
32943
|
+
};
|
|
32944
|
+
const handleActionClick = (action, row) => (e) => {
|
|
32945
|
+
e.stopPropagation();
|
|
32946
|
+
const payload = {
|
|
32947
|
+
id: row.id,
|
|
32948
|
+
row
|
|
32949
|
+
};
|
|
32950
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
32951
|
+
};
|
|
32952
|
+
if (isLoading) {
|
|
32953
|
+
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" }) });
|
|
32954
|
+
}
|
|
32955
|
+
if (error) {
|
|
32956
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
32957
|
+
}
|
|
32958
|
+
if (data.length === 0) {
|
|
32959
|
+
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" }) });
|
|
32960
|
+
return dnd.enabled ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: dnd.wrapContainer(emptyNode) }) : emptyNode;
|
|
32961
|
+
}
|
|
32962
|
+
const lk = LOOKS[look];
|
|
32963
|
+
const header = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
32964
|
+
Box,
|
|
32965
|
+
{
|
|
32966
|
+
role: "row",
|
|
32967
|
+
className: cn(
|
|
32968
|
+
"flex items-center gap-3 sticky top-0 z-10",
|
|
32969
|
+
"bg-[var(--color-surface-subtle)] border-b border-[var(--color-table-border)]",
|
|
32970
|
+
"text-[var(--color-text-muted)] uppercase text-xs font-semibold tracking-wide",
|
|
32971
|
+
lk.headPad
|
|
32972
|
+
),
|
|
32973
|
+
children: [
|
|
32974
|
+
selectable && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-8 flex-shrink-0 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { checked: allSelected, onChange: toggleAll, "aria-label": "Select all rows" }) }),
|
|
32975
|
+
colDefs.map((col) => {
|
|
32976
|
+
const active = sortColumn === (col.field ?? col.key);
|
|
32977
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
32978
|
+
Box,
|
|
32979
|
+
{
|
|
32980
|
+
role: "columnheader",
|
|
32981
|
+
onClick: () => handleSort(col),
|
|
32982
|
+
className: cn(
|
|
32983
|
+
"flex items-center gap-1 min-w-0",
|
|
32984
|
+
col.width ?? "flex-1",
|
|
32985
|
+
alignClass[col.align ?? "left"],
|
|
32986
|
+
col.sortable && sortEvent && "cursor-pointer select-none hover:text-foreground"
|
|
32987
|
+
),
|
|
32988
|
+
children: [
|
|
32989
|
+
col.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: col.icon, size: "xs" }),
|
|
32990
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: columnLabel(col) }),
|
|
32991
|
+
col.sortable && sortEvent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
32992
|
+
Icon,
|
|
32993
|
+
{
|
|
32994
|
+
name: active ? sortDirection === "asc" ? "chevron-up" : "chevron-down" : "chevrons-up-down",
|
|
32995
|
+
size: "xs",
|
|
32996
|
+
className: cn("flex-shrink-0", active ? "text-foreground" : "opacity-40")
|
|
32997
|
+
}
|
|
32998
|
+
)
|
|
32999
|
+
]
|
|
33000
|
+
},
|
|
33001
|
+
col.key
|
|
33002
|
+
);
|
|
33003
|
+
}),
|
|
33004
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-px flex-shrink-0", "aria-hidden": true })
|
|
33005
|
+
]
|
|
33006
|
+
}
|
|
33007
|
+
);
|
|
33008
|
+
const renderRow = (row, index) => {
|
|
33009
|
+
const id = String(row[idField] ?? index);
|
|
33010
|
+
const rowInner = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
33011
|
+
Box,
|
|
33012
|
+
{
|
|
33013
|
+
role: "row",
|
|
33014
|
+
"data-entity-row": true,
|
|
33015
|
+
"data-entity-id": id,
|
|
33016
|
+
className: cn(
|
|
33017
|
+
"group flex items-center gap-3 transition-colors duration-fast",
|
|
33018
|
+
lk.rowPad,
|
|
33019
|
+
lk.divider && "border-b border-[var(--color-table-border)]",
|
|
33020
|
+
lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
|
|
33021
|
+
"hover:bg-[var(--color-surface-subtle)]",
|
|
33022
|
+
look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-table-border)] [&>*:last-child]:border-r-0"
|
|
33023
|
+
),
|
|
33024
|
+
children: [
|
|
33025
|
+
selectable && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-8 flex-shrink-0 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
33026
|
+
Checkbox,
|
|
33027
|
+
{
|
|
33028
|
+
checked: selected.has(id),
|
|
33029
|
+
onChange: () => toggleRow(id),
|
|
33030
|
+
"aria-label": `Select row ${id}`
|
|
33031
|
+
}
|
|
33032
|
+
) }),
|
|
33033
|
+
hasRenderProp ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 min-w-0", children: children(row, index) }) : colDefs.map((col) => {
|
|
33034
|
+
const raw = getNestedValue(row, col.field ?? col.key);
|
|
33035
|
+
const cellBase = cn(
|
|
33036
|
+
"flex items-center min-w-0",
|
|
33037
|
+
col.width ?? "flex-1",
|
|
33038
|
+
alignClass[col.align ?? "left"],
|
|
33039
|
+
weightClass[col.weight ?? "normal"],
|
|
33040
|
+
col.className
|
|
33041
|
+
);
|
|
33042
|
+
if (col.format === "badge" && raw != null && raw !== "") {
|
|
33043
|
+
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);
|
|
33044
|
+
}
|
|
33045
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "cell", className: cn(cellBase, "truncate block"), children: formatCell(raw, col.format) }, col.key);
|
|
33046
|
+
}),
|
|
33047
|
+
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(
|
|
33048
|
+
Button,
|
|
33049
|
+
{
|
|
33050
|
+
variant: action.variant ?? "ghost",
|
|
33051
|
+
size: "sm",
|
|
33052
|
+
onClick: handleActionClick(action, row),
|
|
33053
|
+
"data-testid": `action-${action.event}`,
|
|
33054
|
+
"data-row-id": String(row.id),
|
|
33055
|
+
className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
|
|
33056
|
+
children: [
|
|
33057
|
+
action.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
33058
|
+
action.label
|
|
33059
|
+
]
|
|
33060
|
+
},
|
|
33061
|
+
i
|
|
33062
|
+
)) })
|
|
33063
|
+
]
|
|
33064
|
+
}
|
|
33065
|
+
);
|
|
33066
|
+
return dnd.isZone ? /* @__PURE__ */ jsxRuntime.jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsxRuntime.jsx(React98__namespace.default.Fragment, { children: rowInner }, id);
|
|
33067
|
+
};
|
|
33068
|
+
const items = data.map((row) => row);
|
|
33069
|
+
const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
|
|
33070
|
+
let runningIndex = 0;
|
|
33071
|
+
const body = /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React98__namespace.default.Fragment, { children: [
|
|
33072
|
+
group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
|
|
33073
|
+
group.items.map((row) => renderRow(row, runningIndex++))
|
|
33074
|
+
] }, gi)) });
|
|
33075
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
33076
|
+
Box,
|
|
33077
|
+
{
|
|
33078
|
+
role: "table",
|
|
33079
|
+
className: cn("w-full text-sm", className),
|
|
33080
|
+
children: [
|
|
33081
|
+
header,
|
|
33082
|
+
dnd.wrapContainer(body),
|
|
33083
|
+
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: [
|
|
33084
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
33085
|
+
t("common.showMore"),
|
|
33086
|
+
" (",
|
|
33087
|
+
ordered.length - visibleCount,
|
|
33088
|
+
" remaining)"
|
|
33089
|
+
] }) })
|
|
33090
|
+
]
|
|
33091
|
+
}
|
|
33092
|
+
);
|
|
33093
|
+
}
|
|
33094
|
+
var alignClass, weightClass, LOOKS;
|
|
33095
|
+
var init_TableView = __esm({
|
|
33096
|
+
"components/molecules/TableView.tsx"() {
|
|
33097
|
+
"use client";
|
|
33098
|
+
init_cn();
|
|
33099
|
+
init_getNestedValue();
|
|
33100
|
+
init_useEventBus();
|
|
33101
|
+
init_useTranslate();
|
|
33102
|
+
init_Box();
|
|
33103
|
+
init_Stack();
|
|
33104
|
+
init_Typography();
|
|
33105
|
+
init_Badge();
|
|
33106
|
+
init_Button();
|
|
33107
|
+
init_Icon();
|
|
33108
|
+
init_Checkbox();
|
|
33109
|
+
init_Divider();
|
|
33110
|
+
init_useDataDnd();
|
|
33111
|
+
logger.createLogger("almadar:ui:table-view");
|
|
33112
|
+
alignClass = {
|
|
33113
|
+
left: "justify-start text-left",
|
|
33114
|
+
center: "justify-center text-center",
|
|
33115
|
+
right: "justify-end text-right"
|
|
33116
|
+
};
|
|
33117
|
+
weightClass = {
|
|
33118
|
+
normal: "",
|
|
33119
|
+
medium: "font-medium",
|
|
33120
|
+
semibold: "font-semibold"
|
|
33121
|
+
};
|
|
33122
|
+
LOOKS = {
|
|
33123
|
+
dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
|
|
33124
|
+
spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
|
|
33125
|
+
striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
|
|
33126
|
+
borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
|
|
33127
|
+
bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
|
|
33128
|
+
};
|
|
33129
|
+
TableView.displayName = "TableView";
|
|
33130
|
+
}
|
|
33131
|
+
});
|
|
32827
33132
|
function formatNumber(value, format) {
|
|
32828
33133
|
if (value == null) return "0";
|
|
32829
33134
|
const v = typeof value === "number" ? value : value;
|
|
@@ -45258,7 +45563,7 @@ function VerifyModePanel({
|
|
|
45258
45563
|
}
|
|
45259
45564
|
prevCountRef.current = transitions.length;
|
|
45260
45565
|
}, [transitions.length, expanded]);
|
|
45261
|
-
const hudBottom = typeof document !== "undefined" ? document.getElementById("runtime-debugger-portal")
|
|
45566
|
+
const hudBottom = typeof document !== "undefined" ? document.getElementById("runtime-debugger-portal") : null;
|
|
45262
45567
|
const panel = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
45263
45568
|
"div",
|
|
45264
45569
|
{
|
|
@@ -54986,6 +55291,7 @@ var init_component_registry_generated = __esm({
|
|
|
54986
55291
|
init_Switch();
|
|
54987
55292
|
init_TabbedContainer();
|
|
54988
55293
|
init_Table();
|
|
55294
|
+
init_TableView();
|
|
54989
55295
|
init_Tabs();
|
|
54990
55296
|
init_TagCloud();
|
|
54991
55297
|
init_TagInput();
|
|
@@ -55303,6 +55609,7 @@ var init_component_registry_generated = __esm({
|
|
|
55303
55609
|
"Switch": Switch,
|
|
55304
55610
|
"TabbedContainer": TabbedContainer,
|
|
55305
55611
|
"Table": Table,
|
|
55612
|
+
"TableView": TableView,
|
|
55306
55613
|
"Tabs": Tabs,
|
|
55307
55614
|
"TagCloud": TagCloud,
|
|
55308
55615
|
"TagInput": TagInput,
|
package/dist/avl/index.js
CHANGED
|
@@ -32775,6 +32775,311 @@ var init_Lightbox = __esm({
|
|
|
32775
32775
|
Lightbox.displayName = "Lightbox";
|
|
32776
32776
|
}
|
|
32777
32777
|
});
|
|
32778
|
+
function columnLabel(col) {
|
|
32779
|
+
return col.header ?? col.label ?? col.key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
32780
|
+
}
|
|
32781
|
+
function statusVariant4(value) {
|
|
32782
|
+
const v = value.toLowerCase();
|
|
32783
|
+
if (["active", "completed", "done", "approved", "published", "resolved", "open", "online", "ok"].includes(v)) return "success";
|
|
32784
|
+
if (["pending", "in_progress", "in-progress", "review", "draft", "processing", "warn", "warning"].includes(v)) return "warning";
|
|
32785
|
+
if (["inactive", "deleted", "rejected", "failed", "error", "blocked", "closed", "offline"].includes(v)) return "error";
|
|
32786
|
+
if (["new", "created", "scheduled", "queued", "info"].includes(v)) return "info";
|
|
32787
|
+
return "default";
|
|
32788
|
+
}
|
|
32789
|
+
function formatCell(value, format) {
|
|
32790
|
+
if (value === void 0 || value === null) return "";
|
|
32791
|
+
switch (format) {
|
|
32792
|
+
case "date": {
|
|
32793
|
+
const d = new Date(String(value));
|
|
32794
|
+
return isNaN(d.getTime()) ? String(value) : d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
32795
|
+
}
|
|
32796
|
+
case "currency":
|
|
32797
|
+
return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
|
|
32798
|
+
case "number":
|
|
32799
|
+
return typeof value === "number" ? value.toLocaleString() : String(value);
|
|
32800
|
+
case "percent":
|
|
32801
|
+
return typeof value === "number" ? `${Math.round(value)}%` : String(value);
|
|
32802
|
+
case "boolean":
|
|
32803
|
+
return value ? "Yes" : "No";
|
|
32804
|
+
default:
|
|
32805
|
+
return String(value);
|
|
32806
|
+
}
|
|
32807
|
+
}
|
|
32808
|
+
function groupData2(items, field) {
|
|
32809
|
+
const groups = /* @__PURE__ */ new Map();
|
|
32810
|
+
for (const item of items) {
|
|
32811
|
+
const key = String(getNestedValue(item, field) ?? "");
|
|
32812
|
+
const group = groups.get(key);
|
|
32813
|
+
if (group) group.push(item);
|
|
32814
|
+
else groups.set(key, [item]);
|
|
32815
|
+
}
|
|
32816
|
+
return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
32817
|
+
}
|
|
32818
|
+
function TableView({
|
|
32819
|
+
entity,
|
|
32820
|
+
columns,
|
|
32821
|
+
fields,
|
|
32822
|
+
itemActions,
|
|
32823
|
+
selectable = false,
|
|
32824
|
+
selectEvent,
|
|
32825
|
+
selectedIds,
|
|
32826
|
+
sortEvent,
|
|
32827
|
+
sortColumn,
|
|
32828
|
+
sortDirection,
|
|
32829
|
+
className,
|
|
32830
|
+
emptyMessage,
|
|
32831
|
+
isLoading = false,
|
|
32832
|
+
error = null,
|
|
32833
|
+
groupBy,
|
|
32834
|
+
pageSize = 0,
|
|
32835
|
+
children,
|
|
32836
|
+
renderItem: _schemaRenderItem,
|
|
32837
|
+
look = "dense",
|
|
32838
|
+
// DnD props consumed by useDataDnd.
|
|
32839
|
+
dragGroup,
|
|
32840
|
+
accepts,
|
|
32841
|
+
sortable,
|
|
32842
|
+
dropEvent,
|
|
32843
|
+
reorderEvent,
|
|
32844
|
+
positionEvent,
|
|
32845
|
+
dndItemIdField,
|
|
32846
|
+
dndRoot
|
|
32847
|
+
}) {
|
|
32848
|
+
const eventBus = useEventBus();
|
|
32849
|
+
const { t } = useTranslate();
|
|
32850
|
+
const [visibleCount, setVisibleCount] = React98__default.useState(pageSize > 0 ? pageSize : Infinity);
|
|
32851
|
+
const [localSelected, setLocalSelected] = React98__default.useState(/* @__PURE__ */ new Set());
|
|
32852
|
+
const colDefs = columns ?? fields ?? [];
|
|
32853
|
+
const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
32854
|
+
const dnd = useDataDnd({
|
|
32855
|
+
items: allDataRaw,
|
|
32856
|
+
layout: "list",
|
|
32857
|
+
dragGroup,
|
|
32858
|
+
accepts,
|
|
32859
|
+
sortable,
|
|
32860
|
+
dropEvent,
|
|
32861
|
+
reorderEvent,
|
|
32862
|
+
positionEvent,
|
|
32863
|
+
dndItemIdField,
|
|
32864
|
+
dndRoot
|
|
32865
|
+
});
|
|
32866
|
+
const ordered = dnd.orderedItems;
|
|
32867
|
+
const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
|
|
32868
|
+
const hasMore = pageSize > 0 && visibleCount < ordered.length;
|
|
32869
|
+
const hasRenderProp = typeof children === "function";
|
|
32870
|
+
const idField = dndItemIdField ?? "id";
|
|
32871
|
+
const selected = selectedIds ? new Set(selectedIds) : localSelected;
|
|
32872
|
+
const emitSelection = (next) => {
|
|
32873
|
+
if (!selectedIds) setLocalSelected(next);
|
|
32874
|
+
if (selectEvent) {
|
|
32875
|
+
const payload = { selectedIds: Array.from(next) };
|
|
32876
|
+
eventBus.emit(`UI:${selectEvent}`, payload);
|
|
32877
|
+
}
|
|
32878
|
+
};
|
|
32879
|
+
const allSelected = selectable && data.length > 0 && data.every((r2, i) => selected.has(String(r2[idField] ?? i)));
|
|
32880
|
+
const toggleAll = () => {
|
|
32881
|
+
if (allSelected) emitSelection(/* @__PURE__ */ new Set());
|
|
32882
|
+
else emitSelection(new Set(data.map((r2, i) => String(r2[idField] ?? i))));
|
|
32883
|
+
};
|
|
32884
|
+
const toggleRow = (id) => {
|
|
32885
|
+
const next = new Set(selected);
|
|
32886
|
+
if (next.has(id)) next.delete(id);
|
|
32887
|
+
else next.add(id);
|
|
32888
|
+
emitSelection(next);
|
|
32889
|
+
};
|
|
32890
|
+
const handleSort = (col) => {
|
|
32891
|
+
if (!col.sortable || !sortEvent) return;
|
|
32892
|
+
const dir = sortColumn === (col.field ?? col.key) && sortDirection === "asc" ? "desc" : "asc";
|
|
32893
|
+
eventBus.emit(`UI:${sortEvent}`, { column: col.field ?? col.key, direction: dir });
|
|
32894
|
+
};
|
|
32895
|
+
const handleActionClick = (action, row) => (e) => {
|
|
32896
|
+
e.stopPropagation();
|
|
32897
|
+
const payload = {
|
|
32898
|
+
id: row.id,
|
|
32899
|
+
row
|
|
32900
|
+
};
|
|
32901
|
+
eventBus.emit(`UI:${action.event}`, payload);
|
|
32902
|
+
};
|
|
32903
|
+
if (isLoading) {
|
|
32904
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading\u2026" }) });
|
|
32905
|
+
}
|
|
32906
|
+
if (error) {
|
|
32907
|
+
return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
|
|
32908
|
+
}
|
|
32909
|
+
if (data.length === 0) {
|
|
32910
|
+
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" }) });
|
|
32911
|
+
return dnd.enabled ? /* @__PURE__ */ jsx(Fragment, { children: dnd.wrapContainer(emptyNode) }) : emptyNode;
|
|
32912
|
+
}
|
|
32913
|
+
const lk = LOOKS[look];
|
|
32914
|
+
const header = /* @__PURE__ */ jsxs(
|
|
32915
|
+
Box,
|
|
32916
|
+
{
|
|
32917
|
+
role: "row",
|
|
32918
|
+
className: cn(
|
|
32919
|
+
"flex items-center gap-3 sticky top-0 z-10",
|
|
32920
|
+
"bg-[var(--color-surface-subtle)] border-b border-[var(--color-table-border)]",
|
|
32921
|
+
"text-[var(--color-text-muted)] uppercase text-xs font-semibold tracking-wide",
|
|
32922
|
+
lk.headPad
|
|
32923
|
+
),
|
|
32924
|
+
children: [
|
|
32925
|
+
selectable && /* @__PURE__ */ jsx(Box, { className: "w-8 flex-shrink-0 flex items-center", children: /* @__PURE__ */ jsx(Checkbox, { checked: allSelected, onChange: toggleAll, "aria-label": "Select all rows" }) }),
|
|
32926
|
+
colDefs.map((col) => {
|
|
32927
|
+
const active = sortColumn === (col.field ?? col.key);
|
|
32928
|
+
return /* @__PURE__ */ jsxs(
|
|
32929
|
+
Box,
|
|
32930
|
+
{
|
|
32931
|
+
role: "columnheader",
|
|
32932
|
+
onClick: () => handleSort(col),
|
|
32933
|
+
className: cn(
|
|
32934
|
+
"flex items-center gap-1 min-w-0",
|
|
32935
|
+
col.width ?? "flex-1",
|
|
32936
|
+
alignClass[col.align ?? "left"],
|
|
32937
|
+
col.sortable && sortEvent && "cursor-pointer select-none hover:text-foreground"
|
|
32938
|
+
),
|
|
32939
|
+
children: [
|
|
32940
|
+
col.icon && /* @__PURE__ */ jsx(Icon, { name: col.icon, size: "xs" }),
|
|
32941
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: columnLabel(col) }),
|
|
32942
|
+
col.sortable && sortEvent && /* @__PURE__ */ jsx(
|
|
32943
|
+
Icon,
|
|
32944
|
+
{
|
|
32945
|
+
name: active ? sortDirection === "asc" ? "chevron-up" : "chevron-down" : "chevrons-up-down",
|
|
32946
|
+
size: "xs",
|
|
32947
|
+
className: cn("flex-shrink-0", active ? "text-foreground" : "opacity-40")
|
|
32948
|
+
}
|
|
32949
|
+
)
|
|
32950
|
+
]
|
|
32951
|
+
},
|
|
32952
|
+
col.key
|
|
32953
|
+
);
|
|
32954
|
+
}),
|
|
32955
|
+
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "w-px flex-shrink-0", "aria-hidden": true })
|
|
32956
|
+
]
|
|
32957
|
+
}
|
|
32958
|
+
);
|
|
32959
|
+
const renderRow = (row, index) => {
|
|
32960
|
+
const id = String(row[idField] ?? index);
|
|
32961
|
+
const rowInner = /* @__PURE__ */ jsxs(
|
|
32962
|
+
Box,
|
|
32963
|
+
{
|
|
32964
|
+
role: "row",
|
|
32965
|
+
"data-entity-row": true,
|
|
32966
|
+
"data-entity-id": id,
|
|
32967
|
+
className: cn(
|
|
32968
|
+
"group flex items-center gap-3 transition-colors duration-fast",
|
|
32969
|
+
lk.rowPad,
|
|
32970
|
+
lk.divider && "border-b border-[var(--color-table-border)]",
|
|
32971
|
+
lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
|
|
32972
|
+
"hover:bg-[var(--color-surface-subtle)]",
|
|
32973
|
+
look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-table-border)] [&>*:last-child]:border-r-0"
|
|
32974
|
+
),
|
|
32975
|
+
children: [
|
|
32976
|
+
selectable && /* @__PURE__ */ jsx(Box, { className: "w-8 flex-shrink-0 flex items-center", children: /* @__PURE__ */ jsx(
|
|
32977
|
+
Checkbox,
|
|
32978
|
+
{
|
|
32979
|
+
checked: selected.has(id),
|
|
32980
|
+
onChange: () => toggleRow(id),
|
|
32981
|
+
"aria-label": `Select row ${id}`
|
|
32982
|
+
}
|
|
32983
|
+
) }),
|
|
32984
|
+
hasRenderProp ? /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(row, index) }) : colDefs.map((col) => {
|
|
32985
|
+
const raw = getNestedValue(row, col.field ?? col.key);
|
|
32986
|
+
const cellBase = cn(
|
|
32987
|
+
"flex items-center min-w-0",
|
|
32988
|
+
col.width ?? "flex-1",
|
|
32989
|
+
alignClass[col.align ?? "left"],
|
|
32990
|
+
weightClass[col.weight ?? "normal"],
|
|
32991
|
+
col.className
|
|
32992
|
+
);
|
|
32993
|
+
if (col.format === "badge" && raw != null && raw !== "") {
|
|
32994
|
+
return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx(Badge, { variant: statusVariant4(String(raw)), size: "sm", children: String(raw) }) }, col.key);
|
|
32995
|
+
}
|
|
32996
|
+
return /* @__PURE__ */ jsx(Box, { role: "cell", className: cn(cellBase, "truncate block"), children: formatCell(raw, col.format) }, col.key);
|
|
32997
|
+
}),
|
|
32998
|
+
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(
|
|
32999
|
+
Button,
|
|
33000
|
+
{
|
|
33001
|
+
variant: action.variant ?? "ghost",
|
|
33002
|
+
size: "sm",
|
|
33003
|
+
onClick: handleActionClick(action, row),
|
|
33004
|
+
"data-testid": `action-${action.event}`,
|
|
33005
|
+
"data-row-id": String(row.id),
|
|
33006
|
+
className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
|
|
33007
|
+
children: [
|
|
33008
|
+
action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
|
|
33009
|
+
action.label
|
|
33010
|
+
]
|
|
33011
|
+
},
|
|
33012
|
+
i
|
|
33013
|
+
)) })
|
|
33014
|
+
]
|
|
33015
|
+
}
|
|
33016
|
+
);
|
|
33017
|
+
return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React98__default.Fragment, { children: rowInner }, id);
|
|
33018
|
+
};
|
|
33019
|
+
const items = data.map((row) => row);
|
|
33020
|
+
const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
|
|
33021
|
+
let runningIndex = 0;
|
|
33022
|
+
const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
|
|
33023
|
+
group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
|
|
33024
|
+
group.items.map((row) => renderRow(row, runningIndex++))
|
|
33025
|
+
] }, gi)) });
|
|
33026
|
+
return /* @__PURE__ */ jsxs(
|
|
33027
|
+
Box,
|
|
33028
|
+
{
|
|
33029
|
+
role: "table",
|
|
33030
|
+
className: cn("w-full text-sm", className),
|
|
33031
|
+
children: [
|
|
33032
|
+
header,
|
|
33033
|
+
dnd.wrapContainer(body),
|
|
33034
|
+
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: [
|
|
33035
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
33036
|
+
t("common.showMore"),
|
|
33037
|
+
" (",
|
|
33038
|
+
ordered.length - visibleCount,
|
|
33039
|
+
" remaining)"
|
|
33040
|
+
] }) })
|
|
33041
|
+
]
|
|
33042
|
+
}
|
|
33043
|
+
);
|
|
33044
|
+
}
|
|
33045
|
+
var alignClass, weightClass, LOOKS;
|
|
33046
|
+
var init_TableView = __esm({
|
|
33047
|
+
"components/molecules/TableView.tsx"() {
|
|
33048
|
+
"use client";
|
|
33049
|
+
init_cn();
|
|
33050
|
+
init_getNestedValue();
|
|
33051
|
+
init_useEventBus();
|
|
33052
|
+
init_useTranslate();
|
|
33053
|
+
init_Box();
|
|
33054
|
+
init_Stack();
|
|
33055
|
+
init_Typography();
|
|
33056
|
+
init_Badge();
|
|
33057
|
+
init_Button();
|
|
33058
|
+
init_Icon();
|
|
33059
|
+
init_Checkbox();
|
|
33060
|
+
init_Divider();
|
|
33061
|
+
init_useDataDnd();
|
|
33062
|
+
createLogger("almadar:ui:table-view");
|
|
33063
|
+
alignClass = {
|
|
33064
|
+
left: "justify-start text-left",
|
|
33065
|
+
center: "justify-center text-center",
|
|
33066
|
+
right: "justify-end text-right"
|
|
33067
|
+
};
|
|
33068
|
+
weightClass = {
|
|
33069
|
+
normal: "",
|
|
33070
|
+
medium: "font-medium",
|
|
33071
|
+
semibold: "font-semibold"
|
|
33072
|
+
};
|
|
33073
|
+
LOOKS = {
|
|
33074
|
+
dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
|
|
33075
|
+
spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
|
|
33076
|
+
striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
|
|
33077
|
+
borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
|
|
33078
|
+
bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
|
|
33079
|
+
};
|
|
33080
|
+
TableView.displayName = "TableView";
|
|
33081
|
+
}
|
|
33082
|
+
});
|
|
32778
33083
|
function formatNumber(value, format) {
|
|
32779
33084
|
if (value == null) return "0";
|
|
32780
33085
|
const v = typeof value === "number" ? value : value;
|
|
@@ -45209,7 +45514,7 @@ function VerifyModePanel({
|
|
|
45209
45514
|
}
|
|
45210
45515
|
prevCountRef.current = transitions.length;
|
|
45211
45516
|
}, [transitions.length, expanded]);
|
|
45212
|
-
const hudBottom = typeof document !== "undefined" ? document.getElementById("runtime-debugger-portal")
|
|
45517
|
+
const hudBottom = typeof document !== "undefined" ? document.getElementById("runtime-debugger-portal") : null;
|
|
45213
45518
|
const panel = /* @__PURE__ */ jsxs(
|
|
45214
45519
|
"div",
|
|
45215
45520
|
{
|
|
@@ -54937,6 +55242,7 @@ var init_component_registry_generated = __esm({
|
|
|
54937
55242
|
init_Switch();
|
|
54938
55243
|
init_TabbedContainer();
|
|
54939
55244
|
init_Table();
|
|
55245
|
+
init_TableView();
|
|
54940
55246
|
init_Tabs();
|
|
54941
55247
|
init_TagCloud();
|
|
54942
55248
|
init_TagInput();
|
|
@@ -55254,6 +55560,7 @@ var init_component_registry_generated = __esm({
|
|
|
55254
55560
|
"Switch": Switch,
|
|
55255
55561
|
"TabbedContainer": TabbedContainer,
|
|
55256
55562
|
"Table": Table,
|
|
55563
|
+
"TableView": TableView,
|
|
55257
55564
|
"Tabs": Tabs,
|
|
55258
55565
|
"TagCloud": TagCloud,
|
|
55259
55566
|
"TagInput": TagInput,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export type GraphicAnimation = 'draw' | 'fill' | 'pulse' | 'morph';
|
|
3
3
|
export interface AnimatedGraphicProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** Additional CSS classes applied to the root element. */
|
|
5
|
+
className?: string;
|
|
4
6
|
/** URL to an SVG file. Fetched and inlined to enable stroke/fill animations. */
|
|
5
7
|
src?: string;
|
|
6
8
|
/** Inline SVG string. Takes precedence over src if both provided. */
|