@ansiversa/components 0.0.87 → 0.0.88
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/package.json +1 -1
- package/src/AvTable.astro +78 -2
- package/src/styles/global.css +31 -0
package/package.json
CHANGED
package/src/AvTable.astro
CHANGED
|
@@ -5,14 +5,90 @@ interface Props {
|
|
|
5
5
|
dense?: boolean;
|
|
6
6
|
stickyHeader?: boolean;
|
|
7
7
|
scroll?: boolean; // enable x-scroll container
|
|
8
|
+
sortKey?: string;
|
|
9
|
+
sortDir?: "asc" | "desc";
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
caption,
|
|
14
|
+
className = "",
|
|
15
|
+
dense = false,
|
|
16
|
+
stickyHeader = false,
|
|
17
|
+
scroll = true,
|
|
18
|
+
sortKey,
|
|
19
|
+
sortDir,
|
|
20
|
+
} = Astro.props as Props;
|
|
21
|
+
|
|
22
|
+
const normalizedSortDir = sortDir === "asc" || sortDir === "desc" ? sortDir : undefined;
|
|
11
23
|
---
|
|
12
24
|
|
|
13
|
-
<div
|
|
25
|
+
<div
|
|
26
|
+
class={`av-table ${scroll ? "av-table--scroll" : ""} ${dense ? "av-table--dense" : ""} ${stickyHeader ? "av-table--sticky" : ""} ${className}`}
|
|
27
|
+
data-sort-key={sortKey}
|
|
28
|
+
data-sort-dir={normalizedSortDir}
|
|
29
|
+
>
|
|
14
30
|
<table class="av-table__table">
|
|
15
31
|
{caption ? <caption class="av-table__caption">{caption}</caption> : null}
|
|
16
32
|
<slot />
|
|
17
33
|
</table>
|
|
18
34
|
</div>
|
|
35
|
+
|
|
36
|
+
<script define:vars={{ initialSortKey: sortKey ?? "", initialSortDir: normalizedSortDir ?? "" }}>
|
|
37
|
+
(() => {
|
|
38
|
+
const root = document.currentScript?.closest(".av-table");
|
|
39
|
+
if (!root) return;
|
|
40
|
+
|
|
41
|
+
const controls = Array.from(root.querySelectorAll("[data-av-sort]"));
|
|
42
|
+
if (!controls.length) return;
|
|
43
|
+
|
|
44
|
+
function applySortState(key, dir) {
|
|
45
|
+
root.dataset.sortKey = key || "";
|
|
46
|
+
root.dataset.sortDir = dir || "";
|
|
47
|
+
|
|
48
|
+
controls.forEach((control) => {
|
|
49
|
+
const sortKey = control.getAttribute("data-av-sort") || "";
|
|
50
|
+
const th = control.closest("th");
|
|
51
|
+
const isActive = sortKey && sortKey === key;
|
|
52
|
+
|
|
53
|
+
if (th) {
|
|
54
|
+
th.setAttribute(
|
|
55
|
+
"aria-sort",
|
|
56
|
+
isActive ? (dir === "desc" ? "descending" : "ascending") : "none"
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
control.classList.toggle("av-table__sort--active", isActive);
|
|
61
|
+
control.classList.toggle("av-table__sort--asc", isActive && dir === "asc");
|
|
62
|
+
control.classList.toggle("av-table__sort--desc", isActive && dir === "desc");
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const startKey = root.dataset.sortKey || initialSortKey;
|
|
67
|
+
const startDir = root.dataset.sortDir || initialSortDir;
|
|
68
|
+
if (startKey && startDir) {
|
|
69
|
+
applySortState(startKey, startDir);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
controls.forEach((control) => {
|
|
73
|
+
control.addEventListener("click", (event) => {
|
|
74
|
+
const key = control.getAttribute("data-av-sort") || "";
|
|
75
|
+
if (!key) return;
|
|
76
|
+
|
|
77
|
+
const defaultDir =
|
|
78
|
+
(control.getAttribute("data-av-sort-default") || "asc").toLowerCase() === "desc"
|
|
79
|
+
? "desc"
|
|
80
|
+
: "asc";
|
|
81
|
+
const currentKey = root.dataset.sortKey || "";
|
|
82
|
+
const currentDir = root.dataset.sortDir || "";
|
|
83
|
+
const nextDir = key === currentKey ? (currentDir === "desc" ? "asc" : "desc") : defaultDir;
|
|
84
|
+
|
|
85
|
+
applySortState(key, nextDir);
|
|
86
|
+
root.dispatchEvent(new CustomEvent("av-sort", { bubbles: true, detail: { key, dir: nextDir } }));
|
|
87
|
+
|
|
88
|
+
if (control.tagName === "BUTTON") {
|
|
89
|
+
event.preventDefault();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
})();
|
|
94
|
+
</script>
|
package/src/styles/global.css
CHANGED
|
@@ -1126,6 +1126,37 @@
|
|
|
1126
1126
|
white-space: nowrap;
|
|
1127
1127
|
}
|
|
1128
1128
|
|
|
1129
|
+
.av-table__sort {
|
|
1130
|
+
display: inline-flex;
|
|
1131
|
+
align-items: center;
|
|
1132
|
+
gap: 0.35rem;
|
|
1133
|
+
color: inherit;
|
|
1134
|
+
background: none;
|
|
1135
|
+
border: 0;
|
|
1136
|
+
padding: 0;
|
|
1137
|
+
font: inherit;
|
|
1138
|
+
cursor: pointer;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
.av-table__sort::after {
|
|
1142
|
+
content: "";
|
|
1143
|
+
display: inline-block;
|
|
1144
|
+
width: 0;
|
|
1145
|
+
height: 0;
|
|
1146
|
+
border-left: 4px solid transparent;
|
|
1147
|
+
border-right: 4px solid transparent;
|
|
1148
|
+
border-top: 6px solid var(--ans-muted);
|
|
1149
|
+
transform: translateY(1px);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
.av-table__sort--active::after {
|
|
1153
|
+
border-top-color: var(--ans-text);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
.av-table__sort--asc::after {
|
|
1157
|
+
transform: rotate(180deg);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1129
1160
|
.av-table--sticky thead th {
|
|
1130
1161
|
position: sticky;
|
|
1131
1162
|
top: 0;
|