pam-grid 1.1.0 → 1.2.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/index.mjs CHANGED
@@ -2,298 +2,664 @@
2
2
  import React2, { useEffect as useEffect5, useRef as useRef2, useState as useState5 } from "react";
3
3
 
4
4
  // src/components/AdvanceFilter.tsx
5
- import { useState, useEffect } from "react";
6
- import { jsx, jsxs } from "react/jsx-runtime";
7
- var OPERATORS = {
8
- number: [
9
- { key: "eq", label: "Equals" },
10
- { key: "neq", label: "Not Equal" },
11
- { key: "gt", label: "Greater Than" },
12
- { key: "gte", label: "Greater or Equal" },
13
- { key: "lt", label: "Less Than" },
14
- { key: "lte", label: "Less or Equal" },
15
- { key: "between", label: "Between" }
16
- ],
17
- text: [
18
- { key: "contains", label: "Contains" },
19
- { key: "starts", label: "Starts With" },
20
- { key: "ends", label: "Ends With" },
21
- { key: "eq", label: "Equals" }
22
- ],
23
- date: [
24
- { key: "before", label: "Before" },
25
- { key: "after", label: "After" },
26
- { key: "between", label: "Between" }
27
- ]
28
- };
29
- function AdvanceFilter({
30
- type = "number",
31
- value,
32
- onApply,
33
- onClear
5
+ import { useState as useState2, useEffect as useEffect2 } from "react";
6
+
7
+ // src/components/dropdown/PamDropdown.tsx
8
+ import {
9
+ useEffect,
10
+ useLayoutEffect,
11
+ useMemo,
12
+ useRef,
13
+ useState
14
+ } from "react";
15
+ import { createPortal } from "react-dom";
16
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
+ function PamDropdown({
18
+ trigger,
19
+ items,
20
+ title,
21
+ placement = "bottom-start",
22
+ offset = 6,
23
+ disabled = false,
24
+ closeOnItemClick = true,
25
+ className = ""
34
26
  }) {
35
- const [operation, setOperation] = useState("");
36
- const [v1, setV1] = useState("");
37
- const [v2, setV2] = useState("");
38
- useEffect(() => {
39
- if (!value) {
40
- setOperation("");
41
- setV1("");
42
- setV2("");
43
- return;
27
+ const triggerRef = useRef(null);
28
+ const menuRef = useRef(null);
29
+ const [open, setOpen] = useState(false);
30
+ const [pos, setPos] = useState({ top: 0, left: 0 });
31
+ const [openSubKeys, setOpenSubKeys] = useState({});
32
+ const portalRoot = useMemo(() => {
33
+ const el = document.getElementById("pam-portal-root");
34
+ if (el) return el;
35
+ const created = document.createElement("div");
36
+ created.id = "pam-portal-root";
37
+ document.body.appendChild(created);
38
+ return created;
39
+ }, []);
40
+ function close() {
41
+ setOpen(false);
42
+ setOpenSubKeys({});
43
+ }
44
+ function toggle() {
45
+ if (disabled) return;
46
+ setOpen((v) => {
47
+ const next = !v;
48
+ if (!next) setOpenSubKeys({});
49
+ return next;
50
+ });
51
+ }
52
+ function getDropdownPosition(triggerEl, menuEl) {
53
+ const rect = triggerEl.getBoundingClientRect();
54
+ const menuRect = menuEl.getBoundingClientRect();
55
+ let top = rect.bottom + offset + window.scrollY;
56
+ let left = rect.left + window.scrollX;
57
+ if (placement.startsWith("top")) {
58
+ top = rect.top - menuRect.height - offset + window.scrollY;
44
59
  }
45
- setOperation(value.operation);
46
- setV1(value.value ?? value.from ?? "");
47
- setV2(value.to ?? "");
48
- }, [value]);
49
- const apply = () => {
50
- if (!operation) return;
51
- onApply(
52
- operation === "between" ? { operation, from: v1, to: v2 } : { operation, value: v1 }
53
- );
54
- };
55
- if (!type) return null;
56
- return /* @__PURE__ */ jsxs("div", { style: { width: 270 }, onClick: (e) => e.stopPropagation(), children: [
57
- /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
58
- /* @__PURE__ */ jsx("label", { className: "form-label", children: "Condition" }),
60
+ if (placement.endsWith("end")) {
61
+ left = rect.right - menuRect.width + window.scrollX;
62
+ }
63
+ const minLeft = 8 + window.scrollX;
64
+ const maxLeft = window.innerWidth - menuRect.width - 8 + window.scrollX;
65
+ left = Math.max(minLeft, Math.min(left, maxLeft));
66
+ const minTop = 8 + window.scrollY;
67
+ const maxTop = window.innerHeight - menuRect.height - 8 + window.scrollY;
68
+ top = Math.max(minTop, Math.min(top, maxTop));
69
+ const bottomOverflow = top + menuRect.height > window.innerHeight + window.scrollY;
70
+ const topOverflow = top < window.scrollY;
71
+ if (bottomOverflow && rect.top > menuRect.height) {
72
+ top = rect.top - menuRect.height - offset + window.scrollY;
73
+ } else if (topOverflow && window.innerHeight - rect.bottom > menuRect.height) {
74
+ top = rect.bottom + offset + window.scrollY;
75
+ }
76
+ return { top, left };
77
+ }
78
+ function updatePosition() {
79
+ const t = triggerRef.current;
80
+ const m = menuRef.current;
81
+ if (!t || !m) return;
82
+ setPos(getDropdownPosition(t, m));
83
+ }
84
+ useLayoutEffect(() => {
85
+ if (!open) return;
86
+ updatePosition();
87
+ }, [open, placement]);
88
+ useEffect(() => {
89
+ if (!open) return;
90
+ const onDown = (e) => {
91
+ const t = triggerRef.current;
92
+ const m = menuRef.current;
93
+ if (!t || !m) return;
94
+ const target = e.target;
95
+ if (t.contains(target)) return;
96
+ if (m.contains(target)) return;
97
+ close();
98
+ };
99
+ const onKey = (e) => {
100
+ if (e.key === "Escape") close();
101
+ };
102
+ document.addEventListener("mousedown", onDown);
103
+ document.addEventListener("keydown", onKey);
104
+ return () => {
105
+ document.removeEventListener("mousedown", onDown);
106
+ document.removeEventListener("keydown", onKey);
107
+ };
108
+ }, [open]);
109
+ useEffect(() => {
110
+ if (!open) return;
111
+ const handler = () => updatePosition();
112
+ window.addEventListener("scroll", handler, true);
113
+ window.addEventListener("resize", handler);
114
+ return () => {
115
+ window.removeEventListener("scroll", handler, true);
116
+ window.removeEventListener("resize", handler);
117
+ };
118
+ }, [open]);
119
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
120
+ /* @__PURE__ */ jsx("span", { ref: triggerRef, className: `pam-dropdown-trigger ${className}`, children: /* @__PURE__ */ jsx("span", { onClick: toggle, style: { display: "inline-flex" }, children: trigger }) }),
121
+ open && createPortal(
59
122
  /* @__PURE__ */ jsxs(
60
- "select",
123
+ "div",
61
124
  {
62
- className: "form-select form-select-sm",
63
- value: operation,
64
- onChange: (e) => setOperation(e.target.value),
125
+ ref: menuRef,
126
+ className: "pam-dropdown-menu",
127
+ style: {
128
+ top: pos.top,
129
+ left: pos.left
130
+ },
65
131
  children: [
66
- /* @__PURE__ */ jsx("option", { value: "", children: "Select" }),
67
- OPERATORS[type].map((o) => /* @__PURE__ */ jsx("option", { value: o.key, children: o.label }, o.key))
132
+ title && /* @__PURE__ */ jsx("div", { className: "pam-dropdown-title", children: title }),
133
+ /* @__PURE__ */ jsx("div", { className: "pam-list-wrapper", children: /* @__PURE__ */ jsx(
134
+ PamDropdownList,
135
+ {
136
+ items,
137
+ closeOnItemClick,
138
+ onClose: close,
139
+ openSubKeys,
140
+ setOpenSubKeys,
141
+ level: 0
142
+ }
143
+ ) })
68
144
  ]
69
145
  }
70
- )
71
- ] }),
72
- operation && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
73
- /* @__PURE__ */ jsx("label", { className: "form-label", children: "Value" }),
74
- operation !== "between" ? /* @__PURE__ */ jsx(
75
- "input",
76
- {
77
- type,
78
- className: "form-control form-control-sm",
79
- value: v1,
80
- onChange: (e) => setV1(e.target.value)
81
- }
82
- ) : /* @__PURE__ */ jsxs("div", { className: "d-flex gap-2", children: [
83
- /* @__PURE__ */ jsx(
84
- "input",
85
- {
86
- type,
87
- className: "form-control form-control-sm",
88
- placeholder: "From",
89
- value: v1,
90
- onChange: (e) => setV1(e.target.value)
91
- }
92
- ),
93
- /* @__PURE__ */ jsx(
94
- "input",
95
- {
96
- type,
97
- className: "form-control form-control-sm",
98
- placeholder: "To",
99
- value: v2,
100
- onChange: (e) => setV2(e.target.value)
101
- }
102
- )
103
- ] })
104
- ] }),
105
- /* @__PURE__ */ jsxs("div", { className: "d-flex justify-content-between mt-3", children: [
106
- /* @__PURE__ */ jsx("button", { className: "btn btn-label-secondary btn-xs", onClick: onClear, children: "Clear" }),
107
- /* @__PURE__ */ jsx("button", { className: "btn btn-primary btn-xs", onClick: apply, children: "Apply" })
108
- ] })
146
+ ),
147
+ portalRoot
148
+ )
109
149
  ] });
110
150
  }
111
-
112
- // src/core/utils.ts
113
- import { useEffect as useEffect2, useState as useState2 } from "react";
114
- var EDGE_SIZE = 8;
115
- var getResizeSide = (e, index) => {
116
- const rect = e.currentTarget.getBoundingClientRect();
117
- const nearRight = rect.right - e.clientX < EDGE_SIZE;
118
- const nearLeft = e.clientX - rect.left < EDGE_SIZE;
119
- if (nearRight) return "right";
120
- if (nearLeft && index > 0) return "left";
121
- return null;
122
- };
123
- function getAdvancedFilterType(column) {
124
- const f = column.enableAdvancedFilter;
125
- if (!f) return null;
126
- if (f === true) {
127
- return "number";
128
- }
129
- return f.type;
130
- }
131
- function getLeftOffset(colState, key) {
132
- let offset = 0;
133
- const leftCols = colState.filter((c) => c.visible && c.pinned === "left").sort((a, b) => a.order - b.order);
134
- for (const c of leftCols) {
135
- if (c.key === key) return offset;
136
- offset += c.width ?? 120;
137
- }
138
- return offset;
139
- }
140
- function getRightOffset(colState, key) {
141
- let offset = 0;
142
- const rightCols = colState.filter((c) => c.visible && c.pinned === "right").sort((a, b) => b.order - a.order);
143
- for (const c of rightCols) {
144
- if (c.key === key) return offset;
145
- offset += c.width ?? 120;
146
- }
147
- return offset;
151
+ function PamDropdownList({
152
+ items,
153
+ onClose,
154
+ closeOnItemClick,
155
+ openSubKeys,
156
+ setOpenSubKeys,
157
+ level
158
+ }) {
159
+ return /* @__PURE__ */ jsx("ul", { className: "pam-dropdown-list", children: items.map((item, index) => /* @__PURE__ */ jsx(
160
+ PamDropdownNode,
161
+ {
162
+ item,
163
+ onClose,
164
+ closeOnItemClick,
165
+ openSubKeys,
166
+ setOpenSubKeys,
167
+ level,
168
+ index
169
+ },
170
+ item.key ?? `${level}-${index}`
171
+ )) });
148
172
  }
149
- var getNestedValue = (obj, path) => {
150
- return path.split(".").reduce((acc, key) => acc?.[key], obj);
151
- };
152
- function useLocalStorageState(key, initialValue) {
153
- const getValue = () => {
154
- try {
155
- const stored = localStorage.getItem(key);
156
- return stored ? JSON.parse(stored) : initialValue;
157
- } catch {
158
- return initialValue;
159
- }
160
- };
161
- const [value, setValue] = useState2(getValue);
162
- const updateValue = (newValue) => {
163
- setValue(newValue);
164
- localStorage.setItem(key, JSON.stringify(newValue));
165
- window.dispatchEvent(
166
- new CustomEvent("pam-localstorage", {
167
- detail: { key, value: newValue }
168
- })
169
- );
170
- };
171
- useEffect2(() => {
172
- const sync = (e) => {
173
- if (e?.detail?.key === key) {
174
- setValue(e.detail.value);
175
- return;
176
- }
177
- if (e?.key === key) {
178
- setValue(getValue());
173
+ function PamDropdownNode({
174
+ item,
175
+ onClose,
176
+ closeOnItemClick,
177
+ openSubKeys,
178
+ setOpenSubKeys,
179
+ level,
180
+ index
181
+ }) {
182
+ const liRef = useRef(null);
183
+ const submenuRef = useRef(null);
184
+ const hasChildren = !!item.children?.length;
185
+ const nodeKey = item.key ?? `${level}-${index}`;
186
+ const submenuOpen = !!openSubKeys[nodeKey];
187
+ useLayoutEffect(() => {
188
+ if (!submenuOpen) return;
189
+ const li = liRef.current;
190
+ const menu = submenuRef.current;
191
+ if (!li || !menu) return;
192
+ const rect = li.getBoundingClientRect();
193
+ menu.style.left = "0px";
194
+ menu.style.top = "0px";
195
+ menu.style.maxHeight = "";
196
+ menu.style.overflowY = "";
197
+ const menuRect = menu.getBoundingClientRect();
198
+ const gap = 6;
199
+ const spaceRight = window.innerWidth - rect.right;
200
+ const spaceLeft = rect.left;
201
+ const spaceBottom = window.innerHeight - rect.bottom;
202
+ const spaceTop = rect.top;
203
+ let left = rect.right + gap;
204
+ let top = rect.top;
205
+ let mode = "right";
206
+ if (spaceRight >= menuRect.width) {
207
+ mode = "right";
208
+ left = rect.right + gap;
209
+ top = rect.top;
210
+ } else if (spaceLeft >= menuRect.width) {
211
+ mode = "left";
212
+ left = rect.left - menuRect.width - gap;
213
+ top = rect.top;
214
+ } else {
215
+ if (spaceBottom >= menuRect.height) {
216
+ mode = "bottom";
217
+ left = rect.left;
218
+ top = rect.bottom + gap;
219
+ } else if (spaceTop >= menuRect.height) {
220
+ mode = "top";
221
+ left = rect.left;
222
+ top = rect.top - menuRect.height - gap;
223
+ } else {
224
+ mode = "bottom";
225
+ left = rect.left;
226
+ top = rect.bottom + gap;
179
227
  }
180
- };
181
- window.addEventListener("pam-localstorage", sync);
182
- window.addEventListener("storage", sync);
183
- return () => {
184
- window.removeEventListener("pam-localstorage", sync);
185
- window.removeEventListener("storage", sync);
186
- };
187
- }, [key]);
188
- return [value, updateValue];
228
+ }
229
+ const minLeft = 8;
230
+ const maxLeft = window.innerWidth - menuRect.width - 8;
231
+ left = Math.max(minLeft, Math.min(left, maxLeft));
232
+ const minTop = 8;
233
+ const maxTop = window.innerHeight - menuRect.height - 8;
234
+ top = Math.max(minTop, Math.min(top, maxTop));
235
+ const maxHeight = window.innerHeight - 16;
236
+ menu.style.maxHeight = `${maxHeight}px`;
237
+ menu.style.overflowY = "auto";
238
+ menu.style.left = `${left}px`;
239
+ menu.style.top = `${top}px`;
240
+ menu.setAttribute("data-placement", mode);
241
+ }, [submenuOpen]);
242
+ const handleClick = (e) => {
243
+ e.stopPropagation();
244
+ if (item.disabled) return;
245
+ if (hasChildren) {
246
+ setOpenSubKeys((prev) => {
247
+ const next = {};
248
+ Object.keys(prev).forEach((k) => {
249
+ const lvl = Number(k.split("-")[0]);
250
+ if (lvl < level) next[k] = prev[k];
251
+ });
252
+ next[nodeKey] = !prev[nodeKey];
253
+ return next;
254
+ });
255
+ return;
256
+ }
257
+ item.onClick?.();
258
+ if (item.keepOpenOnClick) return;
259
+ if (closeOnItemClick) onClose();
260
+ };
261
+ return /* @__PURE__ */ jsxs(
262
+ "li",
263
+ {
264
+ ref: liRef,
265
+ className: [
266
+ !item.custome ? "pam-dropdown-item" : "",
267
+ item.danger ? "danger" : "",
268
+ item.disabled ? "disabled" : "",
269
+ hasChildren ? "has-children" : "",
270
+ submenuOpen ? "open" : ""
271
+ ].join(" "),
272
+ onClick: handleClick,
273
+ children: [
274
+ /* @__PURE__ */ jsxs(
275
+ "div",
276
+ {
277
+ className: `${item.rightSlot ? "pam-dropdown-item-inner-rightSlot" : "pam-dropdown-item-inner"} `,
278
+ children: [
279
+ /* @__PURE__ */ jsxs("div", { className: "pam-left", children: [
280
+ item.icon && /* @__PURE__ */ jsx("i", { className: `${item.icon} pam-icon` }),
281
+ /* @__PURE__ */ jsx("span", { className: "pam-label", children: item.label })
282
+ ] }),
283
+ /* @__PURE__ */ jsxs("div", { className: "pam-right", children: [
284
+ item.rightSlot && /* @__PURE__ */ jsx(
285
+ "span",
286
+ {
287
+ className: "pam-rightslot",
288
+ onClick: (e) => e.stopPropagation(),
289
+ children: item.rightSlot
290
+ }
291
+ ),
292
+ hasChildren && /* @__PURE__ */ jsx("i", { className: "bx bx-chevron-right pam-arrow" })
293
+ ] })
294
+ ]
295
+ }
296
+ ),
297
+ hasChildren && submenuOpen && /* @__PURE__ */ jsx("div", { ref: submenuRef, className: "pam-submenu", children: /* @__PURE__ */ jsx(
298
+ PamDropdownList,
299
+ {
300
+ items: item.children,
301
+ onClose,
302
+ closeOnItemClick,
303
+ openSubKeys,
304
+ setOpenSubKeys,
305
+ level: level + 1
306
+ }
307
+ ) })
308
+ ]
309
+ }
310
+ );
189
311
  }
190
- var resolveValue = (value, row) => {
191
- return typeof value === "function" ? value(row) : value;
192
- };
193
312
 
194
- // src/components/FacetFilter.tsx
195
- import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
313
+ // src/components/AdvanceFilter.tsx
196
314
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
197
- var FacetFilter = ({
198
- columnKey,
199
- grid
200
- }) => {
201
- const {
202
- facetItems,
203
- facetFilters,
204
- toggleFacetFilter,
205
- loadFacets,
206
- facetLoading,
207
- clearFacetFilters
208
- } = grid;
209
- const [search, setSearch] = useState3("");
210
- const items = facetItems?.[columnKey] || [];
211
- const selected = facetFilters?.[columnKey] || [];
212
- useEffect3(() => {
213
- loadFacets(columnKey);
214
- }, [columnKey]);
215
- const filteredItems = useMemo(() => {
216
- if (!search) return items;
217
- const q = search.toLowerCase();
218
- return items.filter((i) => i.name.toLowerCase().includes(q));
219
- }, [items, search]);
220
- if (facetLoading?.[columnKey]) {
221
- return /* @__PURE__ */ jsx2("div", { className: "p-3 text-center", children: /* @__PURE__ */ jsx2("p", { className: "text-secondary", children: "Loading..." }) });
222
- }
223
- return /* @__PURE__ */ jsxs2("div", { className: "pam-grid-facet-filter", style: { width: 240 }, children: [
224
- /* @__PURE__ */ jsx2("div", { className: "mb-2", children: /* @__PURE__ */ jsx2(
225
- "input",
226
- {
227
- type: "search",
228
- className: "form-control form-control-sm",
229
- placeholder: "Search...",
230
- value: search,
231
- onChange: (e) => setSearch(e.target.value)
232
- }
233
- ) }),
234
- /* @__PURE__ */ jsxs2(
235
- "div",
236
- {
237
- className: "list-group list-group-flush text-truncate",
238
- style: {
239
- maxHeight: 220,
240
- overflowY: "auto"
241
- },
242
- children: [
243
- filteredItems.map((item) => {
244
- const checked = selected.some((s) => s.id === item.id);
245
- return /* @__PURE__ */ jsxs2(
246
- "label",
315
+ var OPERATORS = {
316
+ number: [
317
+ { key: "eq", label: "Equals" },
318
+ { key: "neq", label: "Not Equal" },
319
+ { key: "gt", label: "Greater Than" },
320
+ { key: "gte", label: "Greater or Equal" },
321
+ { key: "lt", label: "Less Than" },
322
+ { key: "lte", label: "Less or Equal" },
323
+ { key: "between", label: "Between" }
324
+ ],
325
+ text: [
326
+ { key: "contains", label: "Contains" },
327
+ { key: "starts", label: "Starts With" },
328
+ { key: "ends", label: "Ends With" },
329
+ { key: "eq", label: "Equals" }
330
+ ],
331
+ date: [
332
+ { key: "before", label: "Before" },
333
+ { key: "after", label: "After" },
334
+ { key: "between", label: "Between" }
335
+ ]
336
+ };
337
+ function AdvanceFilter({
338
+ type = "number",
339
+ value,
340
+ onApply,
341
+ onClear
342
+ }) {
343
+ const [operation, setOperation] = useState2("");
344
+ const [v1, setV1] = useState2("");
345
+ const [v2, setV2] = useState2("");
346
+ useEffect2(() => {
347
+ if (!value) {
348
+ setOperation("");
349
+ setV1("");
350
+ setV2("");
351
+ return;
352
+ }
353
+ setOperation(value.operation);
354
+ setV1(value.value ?? value.from ?? "");
355
+ setV2(value.to ?? "");
356
+ }, [value]);
357
+ const apply = () => {
358
+ if (!operation) return;
359
+ onApply(
360
+ operation === "between" ? { type, operation, from: v1, to: v2 } : { type, operation, value: v1 }
361
+ );
362
+ };
363
+ if (!type) return null;
364
+ const isApplyDisabled = !operation || (operation === "between" ? !v1 || !v2 : !v1);
365
+ const selectedOpLabel = OPERATORS[type].find((o) => o.key === operation)?.label || "Select condition...";
366
+ const opItems = OPERATORS[type].map((o) => ({
367
+ key: o.key,
368
+ label: o.label,
369
+ onClick: () => setOperation(o.key)
370
+ }));
371
+ return /* @__PURE__ */ jsxs2(
372
+ "div",
373
+ {
374
+ className: "advance-filter-panel",
375
+ style: { width: 260, minWidth: 260 },
376
+ onClick: (e) => e.stopPropagation(),
377
+ onMouseDown: (e) => e.stopPropagation(),
378
+ children: [
379
+ /* @__PURE__ */ jsxs2("div", { className: "d-flex align-items-center mb-3", children: [
380
+ /* @__PURE__ */ jsx2("i", { className: "bx bx-filter text-secondary me-2" }),
381
+ /* @__PURE__ */ jsx2("span", { className: "text-secondary", children: "Filter by Column" })
382
+ ] }),
383
+ /* @__PURE__ */ jsx2("div", { className: "mb-3", children: /* @__PURE__ */ jsx2(
384
+ PamDropdown,
385
+ {
386
+ trigger: /* @__PURE__ */ jsxs2(
387
+ "button",
247
388
  {
248
- className: "list-group-item list-group-item-action d-flex align-items-center gap-2 py-2",
389
+ type: "button",
390
+ className: "btn d-flex align-items-center gap-2 px-2 py-1 bg-light-secondary-hover rounded",
249
391
  children: [
250
- /* @__PURE__ */ jsx2(
251
- "input",
252
- {
253
- type: "checkbox",
254
- className: "form-check-input mt-0",
255
- checked,
256
- onChange: () => toggleFacetFilter(columnKey, item)
257
- }
258
- ),
259
- /* @__PURE__ */ jsx2("span", { className: "flex-grow-1", children: item.name }),
260
- checked && /* @__PURE__ */ jsx2("i", { className: "bx bx-check text-primary" })
392
+ /* @__PURE__ */ jsx2("span", { className: "text-truncate", style: { maxWidth: 140 }, children: selectedOpLabel }),
393
+ /* @__PURE__ */ jsx2("i", { className: "bx bx-xs bx-expand-vertical" })
261
394
  ]
262
- },
263
- item.id
264
- );
265
- }),
266
- !filteredItems.length && /* @__PURE__ */ jsx2("div", { className: "text-center text-muted py-3 small", children: "No results" })
267
- ]
268
- }
269
- ),
270
- selected.length > 0 && /* @__PURE__ */ jsx2("div", { className: "pt-2 border-top mt-2 d-flex justify-content-end", children: /* @__PURE__ */ jsx2(
271
- "button",
272
- {
273
- className: "btn btn-sm btn-label-secondary",
274
- onClick: clearFacetFilters,
275
- children: "Clear"
276
- }
277
- ) })
278
- ] });
279
- };
280
- var FacetFilter_default = FacetFilter;
281
-
282
- // src/components/PamHeaderOption.tsx
283
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
284
- var PamHeaderOptions = ({
285
- currentColumn,
286
- gridFetaures,
287
- grid
288
- }) => {
289
- const items = [];
290
- const { advanceFilters, setColumnAdvanceFilter, colState, updateColumn } = grid;
291
- const { key: columnKey } = currentColumn;
292
- const pinColumn = (key, side) => {
293
- const col = colState.find((c) => c.key === key);
294
- if (!col) return;
295
- const newPinned = col.pinned === side ? null : side;
296
- updateColumn(key, { pinned: newPinned });
395
+ }
396
+ ),
397
+ items: opItems,
398
+ placement: "bottom-start"
399
+ }
400
+ ) }),
401
+ operation && /* @__PURE__ */ jsx2("div", { className: "mb-3", children: operation !== "between" ? /* @__PURE__ */ jsx2(
402
+ "input",
403
+ {
404
+ type: type === "date" ? "date" : type === "number" ? "number" : "text",
405
+ className: "form-control form-control-sm",
406
+ placeholder: "Value...",
407
+ value: v1,
408
+ onChange: (e) => setV1(e.target.value),
409
+ autoFocus: true
410
+ }
411
+ ) : /* @__PURE__ */ jsxs2("div", { className: "d-flex flex-column gap-2", children: [
412
+ /* @__PURE__ */ jsx2(
413
+ "input",
414
+ {
415
+ type: type === "date" ? "date" : type === "number" ? "number" : "text",
416
+ className: "form-control form-control-sm",
417
+ placeholder: "From",
418
+ value: v1,
419
+ onChange: (e) => setV1(e.target.value)
420
+ }
421
+ ),
422
+ /* @__PURE__ */ jsx2(
423
+ "input",
424
+ {
425
+ type: type === "date" ? "date" : type === "number" ? "number" : "text",
426
+ className: "form-control form-control-sm",
427
+ placeholder: "To",
428
+ value: v2,
429
+ onChange: (e) => setV2(e.target.value)
430
+ }
431
+ )
432
+ ] }) }),
433
+ /* @__PURE__ */ jsxs2("div", { className: "d-flex align-items-center justify-content-between gap-2 mt-3 pt-2 border-top", children: [
434
+ /* @__PURE__ */ jsx2(
435
+ "button",
436
+ {
437
+ className: "btn btn-sm btn-label-secondary border-0",
438
+ onClick: onClear,
439
+ style: { fontSize: "0.75rem", padding: "4px 8px" },
440
+ children: "Clear"
441
+ }
442
+ ),
443
+ /* @__PURE__ */ jsx2(
444
+ "button",
445
+ {
446
+ className: "btn btn-sm btn-primary",
447
+ onClick: apply,
448
+ disabled: isApplyDisabled,
449
+ style: { fontSize: "0.75rem", padding: "4px 16px", borderRadius: "4px" },
450
+ children: "Apply"
451
+ }
452
+ )
453
+ ] }),
454
+ /* @__PURE__ */ jsx2("style", { children: `
455
+ .dropdown-item-custom:hover {
456
+ background-color: #f5f5f9;
457
+ color: #696cff;
458
+ }
459
+ .advance-filter-panel .form-control:focus {
460
+ border-color: #696cff;
461
+ box-shadow: 0 0 0 0.1rem rgba(105, 108, 255, 0.1);
462
+ }
463
+ ` })
464
+ ]
465
+ }
466
+ );
467
+ }
468
+
469
+ // src/core/utils.ts
470
+ import { useEffect as useEffect3, useState as useState3 } from "react";
471
+ var EDGE_SIZE = 8;
472
+ var getResizeSide = (e, index) => {
473
+ const rect = e.currentTarget.getBoundingClientRect();
474
+ const nearRight = rect.right - e.clientX < EDGE_SIZE;
475
+ const nearLeft = e.clientX - rect.left < EDGE_SIZE;
476
+ if (nearRight) return "right";
477
+ if (nearLeft && index > 0) return "left";
478
+ return null;
479
+ };
480
+ function getAdvancedFilterType(column) {
481
+ const f = column.enableAdvancedFilter;
482
+ if (!f) return null;
483
+ if (f === true) {
484
+ return "number";
485
+ }
486
+ return f.type;
487
+ }
488
+ function getLeftOffset(colState, key) {
489
+ let offset = 0;
490
+ const leftCols = colState.filter((c) => c.visible && c.pinned === "left").sort((a, b) => a.order - b.order);
491
+ for (const c of leftCols) {
492
+ if (c.key === key) return offset;
493
+ offset += c.width ?? 120;
494
+ }
495
+ return offset;
496
+ }
497
+ function getRightOffset(colState, key) {
498
+ let offset = 0;
499
+ const rightCols = colState.filter((c) => c.visible && c.pinned === "right").sort((a, b) => b.order - a.order);
500
+ for (const c of rightCols) {
501
+ if (c.key === key) return offset;
502
+ offset += c.width ?? 120;
503
+ }
504
+ return offset;
505
+ }
506
+ var getNestedValue = (obj, path) => {
507
+ return path.split(".").reduce((acc, key) => acc?.[key], obj);
508
+ };
509
+ function useLocalStorageState(key, initialValue) {
510
+ const getValue = () => {
511
+ try {
512
+ const stored = localStorage.getItem(key);
513
+ return stored ? JSON.parse(stored) : initialValue;
514
+ } catch {
515
+ return initialValue;
516
+ }
517
+ };
518
+ const [value, setValue] = useState3(getValue);
519
+ const updateValue = (newValue) => {
520
+ setValue(newValue);
521
+ localStorage.setItem(key, JSON.stringify(newValue));
522
+ window.dispatchEvent(
523
+ new CustomEvent("pam-localstorage", {
524
+ detail: { key, value: newValue }
525
+ })
526
+ );
527
+ };
528
+ useEffect3(() => {
529
+ const sync = (e) => {
530
+ if (e?.detail?.key === key) {
531
+ setValue(e.detail.value);
532
+ return;
533
+ }
534
+ if (e?.key === key) {
535
+ setValue(getValue());
536
+ }
537
+ };
538
+ window.addEventListener("pam-localstorage", sync);
539
+ window.addEventListener("storage", sync);
540
+ return () => {
541
+ window.removeEventListener("pam-localstorage", sync);
542
+ window.removeEventListener("storage", sync);
543
+ };
544
+ }, [key]);
545
+ return [value, updateValue];
546
+ }
547
+ var resolveValue = (value, row) => {
548
+ return typeof value === "function" ? value(row) : value;
549
+ };
550
+
551
+ // src/components/FacetFilter.tsx
552
+ import { useEffect as useEffect4, useMemo as useMemo2, useState as useState4 } from "react";
553
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
554
+ var FacetFilter = ({
555
+ columnKey,
556
+ grid
557
+ }) => {
558
+ const {
559
+ facetItems,
560
+ facetFilters,
561
+ toggleFacetFilter,
562
+ loadFacets,
563
+ facetLoading,
564
+ clearFacetFilters
565
+ } = grid;
566
+ const [search, setSearch] = useState4("");
567
+ const items = facetItems?.[columnKey] || [];
568
+ const selected = facetFilters?.[columnKey] || [];
569
+ useEffect4(() => {
570
+ loadFacets(columnKey);
571
+ }, [columnKey]);
572
+ const filteredItems = useMemo2(() => {
573
+ if (!search) return items;
574
+ const q = search.toLowerCase();
575
+ return items.filter((i) => i.name.toLowerCase().includes(q));
576
+ }, [items, search]);
577
+ if (facetLoading?.[columnKey]) {
578
+ return /* @__PURE__ */ jsx3("div", { className: "p-3 text-center", children: /* @__PURE__ */ jsx3("p", { className: "text-secondary", children: "Loading..." }) });
579
+ }
580
+ return /* @__PURE__ */ jsxs3(
581
+ "div",
582
+ {
583
+ className: "pam-grid-facet-filter",
584
+ style: { width: 240 },
585
+ onClick: (e) => e.stopPropagation(),
586
+ onMouseDown: (e) => e.stopPropagation(),
587
+ children: [
588
+ /* @__PURE__ */ jsx3("div", { className: "mb-2", children: /* @__PURE__ */ jsx3(
589
+ "input",
590
+ {
591
+ type: "search",
592
+ className: "form-control form-control-sm",
593
+ placeholder: "Search...",
594
+ value: search,
595
+ onChange: (e) => setSearch(e.target.value)
596
+ }
597
+ ) }),
598
+ /* @__PURE__ */ jsxs3(
599
+ "div",
600
+ {
601
+ className: "list-group list-group-flush text-truncate",
602
+ style: {
603
+ maxHeight: 220,
604
+ overflowY: "auto"
605
+ },
606
+ children: [
607
+ filteredItems.map((item) => {
608
+ const checked = selected.some((s) => s.id === item.id);
609
+ return /* @__PURE__ */ jsxs3(
610
+ "label",
611
+ {
612
+ className: "list-group-item list-group-item-action d-flex align-items-center gap-2 py-2",
613
+ children: [
614
+ /* @__PURE__ */ jsx3(
615
+ "input",
616
+ {
617
+ type: "checkbox",
618
+ className: "form-check-input mt-0",
619
+ checked,
620
+ onChange: () => toggleFacetFilter(columnKey, item)
621
+ }
622
+ ),
623
+ /* @__PURE__ */ jsx3("span", { className: "flex-grow-1", children: item.name }),
624
+ checked && /* @__PURE__ */ jsx3("i", { className: "bx bx-check text-primary" })
625
+ ]
626
+ },
627
+ item.id
628
+ );
629
+ }),
630
+ !filteredItems.length && /* @__PURE__ */ jsx3("div", { className: "text-center text-muted py-3 small", children: "No results" })
631
+ ]
632
+ }
633
+ ),
634
+ selected.length > 0 && /* @__PURE__ */ jsx3("div", { className: "pt-2 border-top mt-2 d-flex justify-content-end", children: /* @__PURE__ */ jsx3(
635
+ "button",
636
+ {
637
+ className: "btn btn-sm btn-label-secondary",
638
+ onClick: clearFacetFilters,
639
+ children: "Clear"
640
+ }
641
+ ) })
642
+ ]
643
+ }
644
+ );
645
+ };
646
+ var FacetFilter_default = FacetFilter;
647
+
648
+ // src/components/PamHeaderOption.tsx
649
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
650
+ var PamHeaderOptions = ({
651
+ currentColumn,
652
+ gridFetaures,
653
+ grid
654
+ }) => {
655
+ const items = [];
656
+ const { advanceFilters, setColumnAdvanceFilter, colState, updateColumn } = grid;
657
+ const { key: columnKey } = currentColumn;
658
+ const pinColumn = (key, side) => {
659
+ const col = colState.find((c) => c.key === key);
660
+ if (!col) return;
661
+ const newPinned = col.pinned === side ? null : side;
662
+ updateColumn(key, { pinned: newPinned });
297
663
  };
298
664
  const unpinColumn = (key) => {
299
665
  updateColumn(key, { pinned: null });
@@ -336,7 +702,7 @@ var PamHeaderOptions = ({
336
702
  key: `advance-filter-${String(currentColumn.key)}-apply`,
337
703
  keepOpenOnClick: true,
338
704
  custome: true,
339
- label: /* @__PURE__ */ jsx3(
705
+ label: /* @__PURE__ */ jsx4(
340
706
  AdvanceFilter,
341
707
  {
342
708
  type: getAdvancedFilterType(currentColumn),
@@ -359,17 +725,17 @@ var PamHeaderOptions = ({
359
725
  key: `facet-filter-${String(currentColumn.key)}-items`,
360
726
  keepOpenOnClick: true,
361
727
  custome: true,
362
- label: /* @__PURE__ */ jsx3(FacetFilter_default, { columnKey: String(columnKey), grid })
728
+ label: /* @__PURE__ */ jsx4(FacetFilter_default, { columnKey: String(columnKey), grid })
363
729
  }
364
730
  ]
365
731
  });
366
732
  }
367
- return /* @__PURE__ */ jsx3(
733
+ return /* @__PURE__ */ jsx4(
368
734
  PamDropdown,
369
735
  {
370
- trigger: /* @__PURE__ */ jsxs3(Fragment, { children: [
371
- /* @__PURE__ */ jsx3("i", { className: "bx bx-sm bx-dots-vertical-rounded cursor-pointer" }),
372
- advanceFilters[String(columnKey)] && /* @__PURE__ */ jsx3("span", { className: "badge rounded-pill bg-info badge-dot badge-notifications" })
736
+ trigger: /* @__PURE__ */ jsxs4(Fragment2, { children: [
737
+ /* @__PURE__ */ jsx4("i", { className: "bx bx-sm bx-dots-vertical-rounded cursor-pointer" }),
738
+ advanceFilters[String(columnKey)] && /* @__PURE__ */ jsx4("span", { className: "badge rounded-pill bg-info badge-dot badge-notifications" })
373
739
  ] }),
374
740
  items
375
741
  }
@@ -378,7 +744,7 @@ var PamHeaderOptions = ({
378
744
  var PamHeaderOption_default = PamHeaderOptions;
379
745
 
380
746
  // src/components/FilterApplied.tsx
381
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
747
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
382
748
  var FilterApplied = ({
383
749
  groupBy,
384
750
  removeGroupby,
@@ -422,12 +788,12 @@ var FilterApplied = ({
422
788
  };
423
789
  const facetFilters = grid.facetFilters || {};
424
790
  const removeFacetFilter = grid.removeFacetFilter;
425
- return /* @__PURE__ */ jsxs4("div", { className: "d-flex flex-row flex-wrap gap-1 py-1 px-3", children: [
426
- groupBy && /* @__PURE__ */ jsxs4("span", { className: "badge bg-label-primary text-capitalize", children: [
791
+ return /* @__PURE__ */ jsxs5("div", { className: "d-flex flex-row flex-wrap gap-1 py-1 px-3", children: [
792
+ groupBy && /* @__PURE__ */ jsxs5("span", { className: "badge bg-label-primary text-capitalize", children: [
427
793
  "GroupBy : ",
428
794
  groupBy.label,
429
795
  " ",
430
- /* @__PURE__ */ jsx4(
796
+ /* @__PURE__ */ jsx5(
431
797
  "i",
432
798
  {
433
799
  className: "bx bx-x bx-xs cursor-pointer",
@@ -435,13 +801,13 @@ var FilterApplied = ({
435
801
  }
436
802
  )
437
803
  ] }),
438
- appliedFilters.map((item) => /* @__PURE__ */ jsxs4(
804
+ appliedFilters.map((item) => /* @__PURE__ */ jsxs5(
439
805
  "span",
440
806
  {
441
807
  className: "badge bg-label-info text-capitalize me-2",
442
808
  children: [
443
809
  item.type === "date" && item.operation === "between" ? `${item.column} ${item.from} ${getOperatinName(item.operation)} ${item.to}` : `${item.column} ${getOperatinName(item.operation)} ${item.value}`,
444
- /* @__PURE__ */ jsx4(
810
+ /* @__PURE__ */ jsx5(
445
811
  "i",
446
812
  {
447
813
  className: "bx bx-x bx-xs cursor-pointer ms-1",
@@ -453,7 +819,7 @@ var FilterApplied = ({
453
819
  item.column
454
820
  )),
455
821
  Object.entries(facetFilters).map(
456
- ([column, items]) => items.map((item) => /* @__PURE__ */ jsxs4(
822
+ ([column, items]) => items.map((item) => /* @__PURE__ */ jsxs5(
457
823
  "span",
458
824
  {
459
825
  className: "badge bg-label-success text-capitalize me-2",
@@ -461,7 +827,7 @@ var FilterApplied = ({
461
827
  getColumnLabel(column),
462
828
  ": ",
463
829
  item.name,
464
- /* @__PURE__ */ jsx4(
830
+ /* @__PURE__ */ jsx5(
465
831
  "i",
466
832
  {
467
833
  className: "bx bx-x bx-xs cursor-pointer ms-1",
@@ -476,13 +842,13 @@ var FilterApplied = ({
476
842
  switchFiltersConfig !== void 0 && switchFiltersConfig?.length > 0 && switchFiltersConfig.map((swicth) => {
477
843
  return Object.entries(switchQuery).map(([key, value]) => {
478
844
  if (swicth.queryParam === key && swicth.defaultValue !== value) {
479
- return /* @__PURE__ */ jsxs4(
845
+ return /* @__PURE__ */ jsxs5(
480
846
  "span",
481
847
  {
482
848
  className: "badge bg-label-warning text-capitalize",
483
849
  children: [
484
850
  swicth.label,
485
- /* @__PURE__ */ jsx4(
851
+ /* @__PURE__ */ jsx5(
486
852
  "i",
487
853
  {
488
854
  className: "bx bx-x bx-xs cursor-pointer",
@@ -502,9 +868,9 @@ var FilterApplied = ({
502
868
  var FilterApplied_default = FilterApplied;
503
869
 
504
870
  // src/components/icons/Minimize.tsx
505
- import { jsx as jsx5 } from "react/jsx-runtime";
871
+ import { jsx as jsx6 } from "react/jsx-runtime";
506
872
  var Minimize = ({ onClick }) => {
507
- return /* @__PURE__ */ jsx5(
873
+ return /* @__PURE__ */ jsx6(
508
874
  "svg",
509
875
  {
510
876
  className: "w-6 h-6 text-gray-800 dark:text-white cursor-pointer",
@@ -515,7 +881,7 @@ var Minimize = ({ onClick }) => {
515
881
  fill: "none",
516
882
  viewBox: "0 0 24 24",
517
883
  onClick,
518
- children: /* @__PURE__ */ jsx5(
884
+ children: /* @__PURE__ */ jsx6(
519
885
  "path",
520
886
  {
521
887
  stroke: "currentColor",
@@ -531,9 +897,9 @@ var Minimize = ({ onClick }) => {
531
897
  var Minimize_default = Minimize;
532
898
 
533
899
  // src/components/icons/Compress.tsx
534
- import { jsx as jsx6 } from "react/jsx-runtime";
900
+ import { jsx as jsx7 } from "react/jsx-runtime";
535
901
  var Compress = ({ onClick }) => {
536
- return /* @__PURE__ */ jsx6(
902
+ return /* @__PURE__ */ jsx7(
537
903
  "svg",
538
904
  {
539
905
  className: "w-6 h-6 text-gray-800 dark:text-white cursor-pointer",
@@ -544,7 +910,7 @@ var Compress = ({ onClick }) => {
544
910
  fill: "none",
545
911
  viewBox: "0 0 24 24",
546
912
  onClick,
547
- children: /* @__PURE__ */ jsx6(
913
+ children: /* @__PURE__ */ jsx7(
548
914
  "path",
549
915
  {
550
916
  stroke: "currentColor",
@@ -563,16 +929,16 @@ var Compress_default = Compress;
563
929
  var Box_default = 'data:image/svg+xml,<svg width="250" height="200" viewBox="0 0 250 200" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">%0D%0A<rect width="250" height="200" fill="url(%23pattern0_249_513)"/>%0D%0A<defs>%0D%0A<pattern id="pattern0_249_513" patternContentUnits="objectBoundingBox" width="1" height="1">%0D%0A<use xlink:href="%23image0_249_513" transform="scale(0.004 0.005)"/>%0D%0A</pattern>%0D%0A<image id="image0_249_513" width="250" height="200" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAADICAYAAADBXvybAAAAAXNSR0IArs4c6QAAIABJREFUeF7tfQl4VNXZ/+/OPpOdnWwgCGRh30FRUEShn621KPbf2vpZqxbbz727WK39tK7VqrSubb/aCtrF2kIFrBvIvsoSAgISNhMSSDKZfeb+n/fcuZObm9kzE25yz30eH58hdznnPed33v19BVEURfCLU4BToFdTQOBA79XryyfHKcAowIHONwKngA4owIGug0XmU+QU4EDne4BTQAcU4EDXwSLzKXIKcKDzPcApoAMKcKDrYJH5FDkFOND5HuAU0AEFONB1sMh8ipwCHOh8D3AK6IACHOg6WGQ+RU4BDnS+BzgFdEABDnQdLDKfIqcABzrfA5wCOqAAB7oOFplPkVOAA53vAU4BHVCAA10Hi8ynyCnAgc73AKeADijAga6DReZT5BTgQOd7gFNABxTgQNfBIvMpcgpwoPM9wCmgAwpwoOtgkfkUOQU40Pke4BTQAQU40HWwyHyKnAIc6HwPcArogAIc6DpYZD5FTgEOdL4HOAV0QAEOdB0sMp8ipwAHOt8DnAI6oAAHug4WmU+RU4ADne8BTgEdUIADXQeLzKfIKcCBzvcAp4AOKMCBroNF5lPkFOBA53uAU0AHFOBA18Ei8ylyCnCg63QPnG4F3tgg4uQZwOMHyvsCX5sloChHpwTp5dPmQO/lCxxtegTyJ/4hIhj+45lWIMcOFDiAO+YLKMrVIVF6+ZQ50Hv5Akeb3qvvi9h3HJg8TMAXJwNuH7B6l4j1tUBJH+CeKwUdUqV3T5kDvXevb9TZff81kf37j65qF9UJ7P/ziojBfYAHr+VA723bggO9t61oEvNZ8oaIU03AMzcKsJmlB860Ab/4mwiDADz6NQ70JMjYo27hQO9Ry5WZwT76lojjZ4ELRgKXjRVgtwBvbRGx9RBQVSLghtmZ+Q5/i3YowIGunbXotpEQ935qhYhWF9DcBvTNBwQBMBmAu74goF9+tw2Ff6ibKMCB3k2E1tpnCOx//BA42ijCbgWKCwVcOwPowy3uWluqjIyHAz0jZOQv4RTQNgU40LW9Pnx0nAIZoQAHekbIyF/CKaBtCnCga3t9+Og4BTJCAQ70jJCRv4RTQNsU4EDX9vrw0XEKZIQCHOgZISN/CaeAtinAga7t9Uk4uhNngLe3ivj0c8AgAtfPFlBdmvAxfoPOKMCB3oMXnIJefrNaZHHqZ51ggS9WM3DrXAHDBnZtYpSjToku8fLT6ZApLurad/jT3UMBDvTuoXNWvrKnDqCUUwpjzbUDZhPgDwDTzxew6IL0P0kHx8N/F+HzAwunC7iwouO76BBYukrEvmPA1dMEXDE+/W/xJ7uHAhzo3UPnrHxlyyHgxdVSCKvFDPgCQJsb+K/JAr40Of1PEif/0Z9EuLxAQQ5w3UwBk4ZJ75NBvvszID8HuGS0gCsnpf8t/mT3UIADvXvonJWvtHmBn/9FREgE/EHA5QbyHMBPru56Sah1NcDft4gs2aWlDbjxEgFjhwBLV4uoqQMcNmDGSCk+nl/apwAHuvbXKO4IScx+9X1g31ERVeUC5o1DxoxxlLb64hoRFhNgswKFDuDw50CODZg5ioO8J20dDvSetFrnYKybDgBvbhIhilJKK6kJF3CQn4OV6NonOdC7Rr9e/zTp5E/+S8ThU+0Gv2unC5g8vNdPvVdNkAO9Vy1nZifDDG+rReyrk8R1suoHgkCzE1h8RbuBLrNf5W/LBgU40LNB1V7wTqULzWGVdPKh/SWdvShPmuA10wVM4Zy9R6w2B3qPWKbuH+RT/xIhu9CU1nUy0C1bL/nY3V7gB1d1PTin+2envy9yoGtszf+yQWQusnljO1ZiXf2JiFAIuHxc9iu0kiX/+/8nsiCcaC60TQeBl9aIKMgFLqrkfnSNbaGow+FA19Aq7T8BPL9KZGGsFKCyaIYE6uXrpeYKVMzxh18WMKgQkCqzAzLsyZdOPu9Yv8lqTn+niz2r/E3/oHp2xxGg1Q1cXAXmp6cy0PJFvw+cBGpOABdVAIW57d9VfofuVz/bYRxRvqueg/K74dvZMBLNN9XvdviOgjbqOdD4lbQishiNgNXUTl8NbanIUDjQNbQqFJH22zUiKIacDF4XVwMmIxjInW6gohS4Za6QFMjVwJR/0z6lzRr5HQVsce+lfS4fGKpnOx0mioOIAQTAhzUiNh4AWlzA9JHAf02UXhYXmEkcarHmq353tAMi5nyTOBDlZ4kmFG9gNmpoQymGwoGusXUhsD/2loimNimslazcxMlHlQA3zBYYt1dycjWHSQiYBJw8HmCUHFXNuZXjUEsb8t9W7ZJATr3eKLKO5nJxpYBZlR2lkXgHRiJOnqrkEo+TpyJ9yNuIGmLQ4ay1iwNdaysCKWuMkkqcHkl8JlH99gWdQR6PO0XjkspDINEBEU1cjyUFRAO9zPWV43j0HyI+PysB3GaRCO/1AQ99VYioHKmCPFlOnsn5xqMNzdth0Z4Yz4GuQaDLOjlFovXJl8Ts0WXAl6e2AyIRZ0uooypE8HgbN5GOmgqAliwT4QsC5K6ji2LoSb//6dWS+N7pwFCL/nFsEKkcTGrapfLdRPOleZAIT/9p6eJA19JqKAxvxM0rSqSd/lk94PUDF1UBX5osRDVEdUUEjafPq412Sk6diphM9763B1i7XxLsKX+eAD+rUsDl4zqCPBlDY6bmm8oclAeE2tah3EY0Nvkw08r24kDXykoAOPQ58Ow7IhPXRxVLOjltxOffEeH0SuLgTXME1vFUNoKrOUw8MToRN0okBahBrrQ+x9Nnld99ZyfwwR4ptZZcc2TVT1VcV1rmuzLfVJ+N5xFQb6Ncm4Y2FvELUZTtodoamB5HQ7r5K/+R3DULp0u6LNNj/dQEEWhqAW69PHMutHT1WzVAEh0QatddLMAkw8njPpuCoTHeHFI9ENXzpzXjQNcjgtOYM+WaM1Ex/Gwqhrdz7UKL5X5L6BFIEBeQ7MGULRcaHQBE2w5GSYWtQ15mg0EyyGnp4hxdS6uhGAtVi6H/6EoE8lRF0LgutDhcsZMLTRWEQ3+PZ5lXc3al/5rmGUsdSWg8S8DJuyLqy892OjyZ9TC6dZ186bI0ppXtxYGulZVQjYM2FpVyCoY6R6WlG8WVSet6PNE3kUcgVZ08WU7eFZE7ka0jkXoiSzHcvaZRQGl5WFQeirLIkhXfOxnEzoELLRpgYhntwkwx6TDeVF1ocS3zcSSIVA4M9b3EybUYHcc5upaRDqmqK/me1Zw9XXE9kQgaD6hRdf8EIbExLfNhuqdziLEDIk3DW6I4/7jqSdhaGM0GQf9G8e5ajIpjahG3umsc6WEdnfR14miUwdbsElF73I/NB304djKAUaVmzJ1kQ0lfIwNAPA6aSARVPrtxjxfv7fPB6QlhUKEBU8+3YGqFFO2SiHPH06tTta6ne6ipD4REB0Q82sWar1GQwE1cXOl+1Nqu4kAPb1oSk4lzyhkjiTayMu470QZKaExKYIgiEbTmWACbajxYvdmDg01BtHpEiD4RIV8Ixhwjivsa8fNF+ZhaZY0aTiob9WIGx6gOiF+/0YKl7zphMBsgBkQE2oIw55uQ5xAwaagZU0ZaMa3CiopSUyfQZxLkxPEJSBRppmUgaQ3Y6vHoHuiUNEJ+6lAKOps6uYOJRmEZNGULueq78ntaXCLWbHJja50f//nEgxZnCIHWIEwFRgiCANEvIuAKonyoFSebggi2BSGYBfzo/xXi+tmODtlgqYrcv/jDGby2zg2DxYAcK+AIAA3kARDADpaQV4QpT8rcGGgFpo62YVqlFVNHWDCoyNghpTVThjcir9kMWDSYMKJ1kOtedJeNXfFys+MZZhJy/QRitPLAIHF8ywEfE8cJ2EeP+GCwGWAwC4yjBttCMOYbUNzHhIuqrRje14hLJtkZh31tTRteWuWEi04rUcQtc3PxvavC9Z5UKaDxdNRWt4jFT5zGtmN+CGYDBhca8etbi1DWz4iTZ4LYXxfAe1vd2HkiwH7TwSNYBBitBrbX6XfVCCsT7y8dY8XIEjMKcsJx7CqdPJHBK5a4rtXsMK2DXbccnTaSyyfpvPECPGJGYqkMM6m4lGRrswzs9VuJcwdgsAhMdQi0BGB0GBmHzrUIGDvIiGnj7bh4jJVxzGCw3ehDRjoa46cnA7j31bOoOyodEN/9Uh4Wz89NuvDDiaYgFj95GrWnQ+xwGTHYhIe/WchALqsmNEejhGnsO+rHwWN+fFTrw7aDPpyp98NgN0oHU1A6mIjrTxlpwZwqCyrKLJg6SooiSST1JHIDkpTBxfjUjhbdAp3cVmTgSifAI5FOHotbnWgMYs12N9ZsdeNAYwitrhACTglYBE7ixvaAiFHnWTGlyoIJwywYd54lYsmls4UOJhlsMshpDvS3Yw1BfPe5RpxyikwKmF1pxcPfLkK+vXNxB+UYCeTXP9SAk20hJq6TxPCTawpQmNueVRYUAVMY5DQGuigCTB7T9oNebD8SwNYDPmza5oK5kJRqSNKIKwhTngl5dgETio24bLoDlWUWpt+nAnp5zGTd1lp2WGqw6/67dQt0CjFlGycJC3I8nTwaqGUpoKVNxJodHmw77MO7uzxobgkh5JY2PYEg4AzCYBIwapgFk4ZbcGGVFaOKTcjPMUQARGAiuCUCOYGPAH/qbBDf+XUT6ur8MOYZUFFuxjM3FaG4D+n2nee7/3gAX3+onon9gsWARbMcuP3KvMhhQvNTcnJ2uIRBzsT1oAR4+bChcbi8IrZ96pNUkV1uHG6RYnnl+bJDjfR7MzBtnB2XTrAx0BcXtY8x3mGqxeyw7odual/ULdApDTQtkKtzohWGuLNtImpP+PGfXV5s3u/Fnv1emHKNgIGMWCJCHkmcJc42c4QFU0ZYMHuiHXk2gfnJCYhKwMggJ6AR4GJxcnqW3Dz0PN3X3BbCD/9wFtsP+SH6QxiUY8Affty/k/vtrQ1uPPTqGbQJApMqbpqXgxvn5jLgssNFDfIwqOUDg0BOY2LfVUkbymdJn9+0z4ftB7zYcSys37cEYHAYYCAxIUhW/RCqK6zMmn9JtRVTRlniqlT59tQ2ut7v1jXQExrTFBZxNYeRRU7iWptqfdi4w43axiCc/rC46g7BlCOBPMcCnF9oxCUzHLh4tBUDmOU8OqjV4KLfSrE56oGgALny3if+1orXVrYwtxhx9Fe+W4SS/iYG4udXOPHMG83MLkDi+h1fzMO1FzhY5hybqwK4zGofdkvIBxHZCdScXD6IlHOQ36Ocb81nfmw/6GP6fW2dD2dPk5RDjmgwl2HQG2IHJB2EF1dYMK3ahspSqZKDrL9rLTtM6weJfoEeFt1jVk2NUtiQNitZpv/6QRu2HPFjyyGfpGe3hmCwKyzkrhCmjLdj8vlmSc8eZonot3KEm5ILEnjk3wQgApvMUel+OdpKCXLaWB3epeK+MtheXePEi6vamNhckGfE/95UhP3H/HhmeTMMVgEF+Ub88oZCjB9mSVpcl0Eei5PLh000kMsqhnK+Ow/78OEeL2qO+pmoTwcTm1/YZWiwGpjUM6HEhHnTHbh6pl1z2WEc6BqlgDI7LBUX2uKnTuO9vT4Yw3pm0Cm5mEoGmnHRaCsuHGVFZbmZub2icmOlfqsUucMcNJZOHgjr4LLxkH5HxHXVs7KoL7/rt2+3MvcbAYZZ9VuDMNgFlAww49EbCjF8sCl5kEdRMaJxcvkgUurzUQ85lQ1C1u//s9WNgycDOHg6yHQIf0sQprAnYu4YK176nyKN7ixtDku3HF3ODmMWZJXeHc8SX33LCQkwAC4fY8OUkWbMnmBHrk3oYBGPasQKi+uxjFjJGN5icXK1Pk+/nR4Rm/eRNdyPlVvdTBqhCDcaP+nkg/IMGFduxiVT7Jh0vgW5VqlMlfyuThKEQkePp5NHQB5nvsyukIShUdbvV252YXtdgLnucgDsfWWwNhGl0VHpFui0HtGyw2JlPMlc/8ZnmrC51svE9YrhFjx+c1En3zaBgIncYXdUNL1aqbMq/eKJDoh44jpZ+WtOBECiMFm9SQwmts+kD+LkBPKwTq4Ma2W6sV9koJ86xsY8AOPPk8rbKF1oahVDVimUkksscV0934h6ksBlSAfx52eD+P7vzqL2Mz+CrhCum5+Lx/+7QKOQ0uawdA10BvZwdlinwJkYWVnEFb/xywbsPxWMcMVnv9MHZQPCgSVJgFwJGKazJsHZYnFyCpTZdsiH97e5UXPIB7c5HKUWdt2RK4v022FFRhT3N2LlLi8D9TXT7Dh0NsSeZR4BMoCFw1pJn88vMGJKpRUTCfTlFowsN3XwCMQV19WGRoUNItn5ygcGgXzx0jM40RBgQTjzL3LgiRsLke/IfmsqbUI2vVHpHuiyNZ10djIiEXftVOMsSiz7T//YjL9/7EKoLYTScjOW3taHcfZYAS1qcVbeyMm40JioH9bJnV4RH+zwYNNeDz4+5JeSW/whBN0i85tTHDwBdTIlnJxnYVb+YYPMKHAIzN1267ONDDAv3NMPk0Za0OoSUXPUh4/2S1LAvhqPFHprkQ4MP0Xp2Y0oGWDCxKFmjBtiYcE8ZMVXSx9qO0I8l2G8uAB5vnSI3ba0CS1OiuUXcfPVeVhyXX56O13nT3Ggd2EDPPlmC55Z6ZJcaGbguVv7oHKIJPKq9Vvmc5at6fR3RRgrE/WjhLUS5ycg1xzx46MaL7NMnzgdYOCzFEnfEX0hBFwhlJ9nZaAePsiE2aOtLOhGPY6t+3349mMNMBeYsHRxEfMIKINh6JAinZiMYB/u9mLjTjc+D0fLKcNa6SAcMcCI8UMtLN5+RIkJDosQcRlGs0EoVZlkQP7vrR786q0WtLRJyTy3X1eIxV/IZXNShsjGSy1V36v8zaQqA2BLISuOvkXqHq0lHWqkjpBBlKQbrWfXcaB3Aej06K/+4cRTf22V0jgLTLjzqjxcc4GDibnputCI824/JMWQb9rpZjo2xb1LyS2UwWZi4ji5xCaUmpgxbTDFwCss4p0kCBHYUuvDd184wySW528t6uBSU0e8yS40Av3+4378Z6MLu06F02PDmXOSG0wKdplcbcOc8TaMHGxi7sR0XIbyAfDy6ja8vNoppcc6g/jpjX1w/RxHJJIxVm5CvEw5OQpS/SyNM5meaSzLMdAeRKTOgZDBrsXqMrQXONC7CHR6fPn7Lnz/jy2RMM+br8zHLWHuE88NFtFDm0P48BMPNn3ixva6IFwBqdwocW7ZpURW/WH5Bkwda8OkEVIcvNJCLnsPZGNiB7E57GPfcdiPxUubmE7+3OKiSBGJTiCP40LbetCHzXu82Hlcsg2ow1qJ+xb0MWLyKCsuqrSyWP3SAcaoYbxKUV82YL6ypg0vr5JAbg+KeP6evpg6sr3YhRKoysQWJWfvlKGXoLEkPWu3xK4OQ1ycUpllNS9e+WqtZtdxoGcA6PSKvXUBLLy/nkXGkY5707xc3HhpDhMP1WGt5PZ6f7sHW/Z7se6gj4nnLDjEJERcdwSgSoqBJ8BUWzFssBmFOVJLJrWfPG4gTViNII6z/VM/bnm6keWUv3B3P3ZgdMWFRiG/22u92HHUDzoA9u1v1+9J1A+5QjDkGFDc14QJQ8yYVW1FxRAz0++jjfmh5S1YscXNXGgDrQKev6svKsrCKoqqdFQskMtgVP49GVGf7o/WM03OcpTtEUT/WLUHGOfkvdcyhCgNv+ZYYxDXPd6EYw0B5n67cpYDdy8sYFUtyO21dq8HWz/1SW6icNw7cW7K7hKMAgoKjbhojA3jysyYM07Ss9VBN6yclCKTLK64rtL9t9T4cMtTp5l1fel3ijD+PCltNFMuNLKQk8qx9YCfqRz1flEqkkEqB4UEk1VfBIYXGTCxyopLxtkxYbgZzW0ibvtNE7MNkEdgoE3AH5f0ZwdCMjp5rDiIVJ81m6S6b8qLODlx9ERpyMpneO81DYM0U0MjsC/82WmcbA1F8skDLUG4rWSskjZ9pCyTXcDwfiZmRJszyRbRsyP6Lfm+Q+1VRdVW7kTiujLunZ7dfMCH75GODuDZW4qYv5xAzvT5oGScUkof6brQ5GCYgycCjNO/u9GFw80hFrAjH2pyWi6l6RYUGdFG+m9QxPmFBvzfT/pHMvho3MmkEqdaRSeaEY/mq+6ZRjULSD+PVZcgmgShxew6LrpnCuGK97z5sRv3vNosZWU5pcowBHISmceXmjF1nI1FopH+KgeS0OMd9PlwMoscPZaSuB7m+uosNFlHp8IWv727H9OjZZCzexNkocljpI0c1RYQIxRXPjA21/rw4S4PDjYEmSuP2SDsUoENMRCCPQS89YsBKOknsdUOxrUo1Xo6FMFMoRRYvJp26mSZFndnkCtBrxyjcitpLemGAz3DQCeOvuDB02hupaISQZgp95wC01jkmQlXXZyLicPNHTLYGNjCsewy2IiLyBZcufprvOSWDpFniqg8pehPHHXOnScBs4C3HxwgSRBdDGuN5zKMFlPQ5hXx4SdevLvBhY8O+iIVaVg9vHwTvjzDjoe+XpDQhZauuB6v0AWdJXmq5oitnuTr6nOgZxhMWn2drKPXfR5gIB9bbcO+Y4FOOiqJr8UDTJhcaZN83wNNKOknpa6qdfJkQmIjII+RwabMYz91JsjEYpYDnwDk6iy0dFyGdLhQWuqHFHN/2IcDx/2SlGM1sGQguR4eFb1kXNwn4tbLc/C9q6XAmHipxOG6IR1bOaVZqJPeRfOjMlXKi7rlyHaRWBV01fuR917TKkIzNC4yxK3f42WRZ/d8LR93fCkPBP51O73Y/JkfG2p9OEJFH6l0VDiTTHahjRxixsShFlwoF12IUvghVZ28Ux67InMuWtRaprLQyF+/44ifxQHsq/WgjQ4UNl8RfuLcdiMKCgyYPsqCKeVmXDHNhoIcI+bfV4/PjgdgzDXgmZv74JIxVBwuek+2aDq5DNZEB0QntSC8/lRhVt0zjSImqexYrByIaDo6772WIUBp8TW/etuJX/2NAmdCWDQvB098qzDqMPcc8WPjp36s2u7Brr1etJHPOlxQURJfjRAMAiaUmzCryoYpVVaMLDZFdUd1CEpRZoOpdPSuuNCiRfipC058fjaED/d4sKXGiy27PXBTNo8AsBRe+VADMHWICdOrrJhZbWUgV1919QF84aFGtLhFOMQQ/vbAQFYVJxpwOzWiSEFHjxZYwwxols5FJ+neNl97vf94DTBonNy9pkV0ZmhMr7zrwgOvNSPoDGHoMAtWLOmXdNLFhv0+rNrhxc49Hmw9SYH2pM9LYa0UaUdXfytQMcSCORPtnfR7JuorilOoy051KuSoEtfVmXOJikbQRiY9+4OdHuw74mdxABQ2q3ahUVxA6UAT5s9wYN54K6rKzEnRZNV2L7712GkWW1pWbMabP+zH1Ix0dfJ4tQYYrcMHRLyeaWQvIa6eCOT0Pt57LUOg0tprKFBm/v0NIBfa0OEWLLu3L0rDJZJTHSs1bSDg/3u9C5vqAjh2OsjSMpkObg+nmjqDKBkk6fcXVVkxfriFBdLIXC9eIcd0XWgs8YX07FovmMuM0nSpEERhuJlE2GXYd5AZ8ybYMH2khYFbjrdPlQ4UUvz0yjaGwollRvz+B/0jkXWd3G1xer8l0zGGOHkyPdNIhCd/uhxKqw7CISknmfekSotM3c+t7l2gJOnfix4+jc+OBpgLbeX9/VFVpoq46ML76xqC2LDPi9W7vSzy7sghX3vJqnDtdNJnJ42wYkR/I2aNpUIYkkisrM4q/06mkCO7NyTViafglw92e1lGWxvp95QCGy7kSJlyBTkGVJaYcVm1GTPH2FFVnrm5k3vyzytaWbupb1yWgx9+JT/CfWOJ8vGi1tTiOh2epJOn0jON3kHx7iRByYCnE4jeQe9SRuN1Ydmz8mivAboys0gWX2OFKiaqJR7Pf6s8yef9tB5H6/yskOGSr+bjxrmOrCyS/NK9ZNA76MeqrR58tNklifbhohFBT7h2uk3AeYUGzJniwOQRFkm/T8K63tAcwge7Pdhb68FHtX64JC0Cgeb2ZhIU0DKl1IQLJ9kxvcKStDieDlEoa+3aR5pQc0ryWtz7xTzcMF/KXpNFbuKgdHjJtop0vqOXZ3oF0JWZRbRwiWKb09X3lAfEI8tb8OrbLawX2p1fzMMdX2zfhN21eZh+v92LtVtcqG2WnE0UXy5S6iSJ+gAGWMAyyyg4ZsIwMwYWGhk4KL5+a42XRcutq/XhZFMAQZcIgQrXhptJUBhveQlZxe1MHCcDWncWfGAS0yONOPKZjxWMJH29sszEimWqQ1W7i+Y99Ts9HugdijyGV0GuPRLNEBMvqikRJ5effe7tVlC3URLXq8vNzPh2ri8CBVn039nkxqajkn7PikBapXLOUseUECpHWZHnMGDrPi+C3iBMuR2bSRT2MWLeeBsqi02YN8GKsgGZE8fTodGew3584ReNTHIZnGvAsh/1RXm4mk8679PrMz0a6MrMInXwBOO+6QZPxAm3fHeHB7c91ch8vWX9TXj9nj5pG9+yuemYfl/jxepPvNiwz4em+kCkmYQMekoyyc8RUDHAiHnjbBg9QuLaWrteWRP2arhDGFtpxev39u1WyUJr9EhnPD0a6HJmkayzJcvJ1W6SeKK+Ulw/3hDA9Q+fRr0fbKOtuK+fJkEebSPc/OxZrNrpYaG4rBdavgnTR5nxwm19egRo7v/dWfx+ndRe5+pJNjx5a/Q4hXRAoIdnejTQKbOILKB0xWrEkMj3mQjkckQUGYe+9OPPUR+gLC+BVSFdOLNn9AUiP/+Dr7cwkA9yCDjvPAuL0qMw3buvzcedX25vsazlTU+Rh2u3ullK792L8nHHld1vF9EyfeKNrUcDnRIOUultrs40SlYnJwLe9qtGvH/Ax0BOG+xcGN/S2WSRJJuz1IMN+MuDA5DvMGDej+pBXVTJ8PbC4iKmj2v9anaGMP++BpwXIAeQAAAS2klEQVRwSorab28pxOWTVVkoWp/EORpfjwd6PE6ebA5xouipv65zYcmfWlgWGgGCgNETrkiSzakAgu4g3nxgQEQHlw8ACtJxBEJY9djAHqGGUDwBZQdSqm1hHxN2Lx3UE5binI+xRwNdziyKl+FEFE5XJ5ef/dP7Ljzy1xZWGIEs12OrKFbbirmjLRh9Xve6nFLZMQQIsloHnAHce31RJymEhZs+chqCVUB5seQ96E73WTJzoYNozyEfNnzqx8YDPhY5yGLoacyDzFj7SP9kXqP7e3o00Mm1xor2qVsZqzKe1PXFYlURjRUySamWVz/UgLpj/kjXT1YUMZywQT7mSyvMGDPKyvzNWrgeXNaKl1c4mQvt5qsKsOS66Hr4U2+14ul/tjH329QhZrzxs3PvKiSuTTYElvizz4NWP1haK13MZWgTUFhgxJJF+T3GTnKu90SPBjrLLPK2k7CrEW+JfOzUInnzQR827vGwQJNIqmlrAEabkbU7yrMImDLEhAUXOhjo041778rGoEw6iheXpY8V97eDlzhkiyvUYVx3v3wWy1a1MZfht+blMAB150VjWrXDw1J8V653sX7tZAuhw5QKZsoNLSeVmjBmuAVXTLFlNSqvO+feXd/q0UBnJ7wisygRUONx8rj5xlFSIJ1ukYF99WY39p8IoLZeCtWkzSmnmlIWWnGeARdMtEvJHiPMaSd6JLshiBMu+t9GVnxyyFALlin8/KSXX/iDelb4Ye8rxRExnTwKix5vkopk+EXctygPNynCTZP9drL3MXH8sA/vbPNgzV4fC+5hbj+5YCZV3HGFWDGOuVMdqCg1Yc4YGxuv3Ry7LHOy39fjfT0e6LRocv80OdFAbV1P1oVG71InP8QrTtjBx94UxIbdXmz7zM+4/nFmAAuxEFl2IJGobxQwmoWSWjG32oKZozNr6SYgX/twI4u/7zPI1MnPv77Gh2t+1sA4JEWYKYNj1OGmJAVkMkHn491ebDokFd8gzi0XyCS1S9n77ZKxVkweZmFFJ0rDUXlqSS1atVY9gjeVOfcKoMsA7ZRZlKDAYLw0xk6gV0XLJVITKr55XIqeG2DCmYYAWn1ie812RWjq9PPNuHSMFReMIXE0/XBT4pJX3NeAo8d8MOWZWI8ydZINgY180WRboIg+dRQchdBS4QcWbmoD3ri/f9qqBx0clGe/apukZzupJp7ZwAyaTOqhqDyHAZVlZjQ3BrC/SQqI+OQZyYqeSPpiHVaIu4er2Kay6fV4b68ButYWb+i3T7Eh3f6FXNx5VS6zFtPG333Aiw2k34fjz1kByXAWWnG+AVWlpkgSSSr6/befbmL6LcWuk48/mp+fuOl1jzUxsL1+T1/MqOpsOKRw0yUvn2GHwejzLey+ZCzxsp69boeHhd06A1KMg7pV87AiA6aOt7P+cCMGmzGg0IBX1jhZayuypu99tSRm8FO0yjDkXpWr0lLRBy2nip7LPcqBniXqE9CpysodV+Wx6DPlJReYWPFxG7bUBVldOdJRmThbKHH1kDuEqqFmjB5ORRyomENs/f7Jv7biyWXNjJPPmxjbz0/fpSIZwdYg3vj5AJT1l9QK9UXVcl59382A+uVJVjz1nc5xA7Lb653tXmw67GP58jRfQh3LnKPKN84g8gqMmDPJjonDzLig0oai3PYiGVTNptAh4MVVTjxJkXsCsO+lYjacRLENcmUY5b3J9lHL0pJr+rUc6FlantKvHofBJOCuaxOHahLQP/7EizV7vYzzUwIKhXnKqabMpWQRMHOsDZWDKavMFuHGL6104me/O8tAThJApnzhxPnXbpEaPN65MI9FA9LYSCqg/+855MeZxgAzPNJFBTEpxZW6zYwoMePCCgtmj7GyGu3RKtvKJauop9xv3moBeQroW7t/PShq5dcOLtI49eFIpaLab3Jp7Cwtb497LQd6lpas/BsnmE7OxOgUY7IjBSa2e7B2swuGsOsu0ro414j8XAEk6u+uJZ3cyECeyUy65rYQFtx/GsebQ1KgUGsQxnDhSmq2QP3K5cYUU4eZMbrUhCnVNkwcLvVzS7ZwZY5VwIvvSL58unY9M6hDV5ROYcsJQC6Xvo5W6DFLS90jXsuBnqVliujoC3K6nDQi6/drt7lRe5pQJDWEYO4oAn0OGdf6JmXMI46cZ6M8+sSGP6lUViOOHJUOE/Jtk8twsF3Agtm5kaKP1MTBKSWWdahWm0zhyhybwHR0CtwJtYU66OjpgFwOieaW+Y4bmwM9i0AnQ9tdX8nHXQszlx1G4Nt7NIC129045RZR2s+EGy91JGUdp2cvuKee2QJWPzEoqYOByEOhsnuP+VHaVypKoTTOEfc+3SolmURr1ZyoVjy9i3T0x19rZurJ3hfadfRUxHV1cwWyxqv7qGVpqXvEaznQs7RMpdcdZ9Vd7lqYWEfP0hA6vXb9Xi+ueUDqpvr6vZ3da+mMg0BOAFc2l5B1crlvnFpHV/ZjZzr631vw9L+cTNUhHT2Vmu3xXKRa63+WDn0z9QwHeqYoqXpP+TdPMBdaOjp6lobEjGjXPdrERP9ofvRUv0v13UlkV3d9kbupkhitBr26IQTT0Vc58fTbTmYL2P3c4A4usmjW9WRrD3Cgt68oB3qquzvJ+0lHp5DY/1mQg7uv6d7Y8VhDZH70R5tYhZllP+7Xpcg8WWTvBPJgu8Vb7lkmB7Uom0nIoj41Z3iZdPRwbH7N70siw+8A8vC/JgtyEvvVfdSSXLpeeRsHepaWdch/n2S68L1fL9RMkQri6Nc80MBcd8t/2i/t+nDEpRudIih7UNngUd2PPW4zCWpFJQD5dgEvrHDiidebmWFx93NSZFwqnDxaQRGLqXMftSwtdY94LQd6lpapdJEUAnvnVZIPWgsXC4F9tJHpwl0R3alUdKs7eReakuu3uCQjmdy/jXT03/6zFc+saGMqBfOjJ+FCU9YHVKchy91MeZQcF92zjruhN51iMeOa0tHDIbA0+XSBTj3ImtpEFqZKlm4CpbKXO/1mveDCMeiNrcDheuD4GaCuEag/C1wyBphdJT2bY5FEdwqBJVVn99LBHdsgx6k1EKseoFb7n2V908X5AOfoWaI+09H9YR1dFQKbpU8mfK2so5Pb7437+mFGdWrZc7JeLgMsWsSbLK43u4HXPgBOO4GccFm35jZJnJ40DLh8vGSpJ/faS6uceOovrSzbT9bRE4XARqsaRFZ+Lfc/S7hAWbyBAz1LxB1yw0lm9LpHQzr6+v0+LFxSD6PdiOWqNNVkyHCmTYz0Co8X1krvWrsPeH8vYA+fJV4fUF0GDB8MnD9Q4vgUpkqi+wv/bMUTy6VY/d3Pdg6BTZRlSN8jnTyVPmrJzLc33cOBnqXVpFh3o0NjOvoeL8tei5WmGo8UTo/kSiO9VxbPI37ysLgu/ybOT4a6DQeAAgcwuBAYWNgu6hMnl0NkmY7+r7COLgBHXuTFHrOxJTnQs0FVALKOfnsGQmAzNcRImmpAZAEzM6qSE90JuI2tIgM4A3mSLjS6l0AdscyHfyuj5ciPznT0t1oRaAvh2J/b3WuZmjd/D8CBnqVdQDo6udeoOYKW/OjUtJBKJf/l5wMwvTI5oJMrjQxuakMbie/JuNCIu+8/AdSeBM60AZOHAROGsg7MkTTVx//czGLp6/4ohcDyK7MU4EDPLD0jbyP3GguBvUZbIbAL729gqaXLvt+xlFQsMsjRbzJ3JteVHPHWCeSCJJKTZf5oA1DXJFnbTzUB5FYryJHcaiV9gGumSy2PWQjs38IhsDYDF92ztB850LNE2LLrT7D8ak2512p8WPRYI+OcybjXZCt7Ihcaief1LcCJM8DBU0DtCUlct1kkMV8GORnmCORTh0v/p4tEd7K6Uz46XVxHz86G5EDPDl0RSVOdn4M7r85c9lpXhhvR0X1hHT1BcUpKWAmEOvrFo4nrFDzz8nvSyMiFZrdI9dxI3C9yANXlQHk/oLSvpLPLOjodJHl2AS+vDuvozhCOvc519K6scaxnOdCzQVUyxpGO3hpkFWbu0hDQKb+cSim/+UA/TK+IraOTyE697ZTBL7Gy0PxB4KV3gfpmoF8BMLoMKO0DFPdpjzdX6/f0XqtJACWeLP23E0+81gzBZsDR3w3O0oro+7Uc6Fla/9JFx1gDw/LBZtx+ZS6mj7CgbED0Gm1ZGkKn136814trf3YaxjxDXB2dgEsGuA5ZaGGLuayjq7PQKAKO9POiXMlop3Shyb/Jb242CsznTRVgqAPOm+vdeH1lK2rqgyw0l4vu2dkNHOjZoSsW/bIRGw/6pfLGLUGYCo2oLjdj2nAzFl6Yg+ohiSu8ZHpoLE318Sb22lg6OgG4KZywItddi5eFFs2FpnS/keXOYhRYJhkFtFBN902H/VL9uRovgq0h1keNQE7lrqnmHb8yTwEO9MzTlL2Rqrk89ZYT67a5cdIjQhAEFstNYrNc421KuQmLLs1JO4ss1aHLOjqNgSLjZkTR0ZtdIpze9lj1ZF1octw7cXKLSYDNLEWreXwiq05DVWpeX+NEqzvEIvPoojp0gtWAwkIDFs50JF0pJ9V58/u5H71b9gCVQqaGgSvWtqG2SWT+KbmyK3EyiveeXGrCgguy26+NgE6dWqif2fKfdE5TdfvIzy0yF1hUF1oQEAySiE4XGdtYNBxxbZMAqtNGLZPaPCLe2eLGsvdcqG0MosUtSvOlppQ2KduFDjmKtZ9ZTZ1ptdGYsls2wzn6COfo3Ux44vQkvi7/wIXNR6nLAZhob7AbGBBI1CcQLJiVw5o0dqV7i3pqlKZKKgW5/dSiO4ns9S1iBMRq45myVBS9l8R5u0VgSSTEvY81BLD6E6kDKs2P4vwpdp0das4gCvKMGDPSwkpVL5xhT6opRDcvTa/+HAf6OVxe1sihxot3tniw8bAfdZ8HGOeLNGkMihjsABbMkiqudpXzyaJ7NB1djn6jv3UKcw1J/0Zcm7LPCNwkltP7aOwr17lwirraUhw8azQZgLmAGk4IuGyMFfPGWjFjdMeikueQ7Lr8NAe6hpadOCG1M1q104s6atLoCjELOen3FE5bPsiEmWNs4c4tFgakVC4Z6HSYKNNUXT6pkAQDOXVYEdt1dLKSk1GOjGkkkv97gxsbP/Nj9Q4PmlupvrtUclouQT3YIWDBRTmYN6HrB1Mqc+P3xqcAB7pGd0hdfRCrdxLoPcygR+WfZP2WdWalzi1jbPjKNGrXZEXZwMSuO7J0UwgsheYu/7Gko7OEFafIAM6SVkTKGZfaE5NILrvASCTfuduDNhFS37gQNXWQDIvTKyWR/LKxFpT1735vgkaXUFPD4kDX1HJEHwz1DyduTGBbu80Dp1/qzMqs+NSaOdeIqnIT5lZbcflke0zXHUkMpKMrS0lR9BvTt80Ci2azGIGNB3xYt92DTUf8zEVI6CfpQrBIdgSq8za5xMjsCOo67z2AnLocIgd6D1x24sxvfuzG2s1unPSKUgcVAj2J0QVG1mhhyhATFs3JwfSKdou2Ok2VstcoOMbjDWHvsQDr9vrmxy40NQSYJd3oaO/tXphnxLWXErCtqCozc2NaD9s3HOg9bMHUw2Wuux0erPioDfsbQwz0csNDEvXJdTel2IQrZjmYy+zul88yg9+rP+iHFi+5wSTVwEUlX8IWcsEEGG1GJtpPO5/+M3epNHQPJ3GvGD4Heq9YRmkSzHW314s3PnRh0xHJdUetjMlvzkR9itKjfuz5ktuLSQHOIEzh/uzU0biy3IT5MxzcBdaL9gVNhQO9ly2oPB1y3a3fR647NwM9c92pQE6/+xabmZ7N3HcjyZIfLt/aS+mi12lxoOtk5YnTr95F/c29aHaGMLfCgvkUicej0nSxAzjQdbHMfJJ6pwAHut53AJ+/LijAga6LZeaT1DsFOND1vgP4/HVBAQ50XSwzn6TeKcCBrvcdwOevCwpwoOtimfkk9U4BDnS97wA+f11QgANdF8vMJ6l3CnCg630H8PnrggIc6LpYZj5JvVOAA13vO4DPXxcU4EDXxTLzSeqdAhzoet8BfP66oAAHui6WmU9S7xTgQNf7DuDz1wUFONB1scx8knqnAAe63ncAn78uKMCBrotl5pPUOwU40PW+A/j8dUEBDnRdLDOfpN4pwIGu9x3A568LCnCg62KZ+ST1TgEOdL3vAD5/XVCAA10Xy8wnqXcKcKDrfQfw+euCAhzoulhmPkm9U4ADXe87gM9fFxTgQNfFMvNJ6p0CHOh63wF8/rqgAAe6LpaZT1LvFOBA1/sO4PPXBQU40HWxzHySeqcAB7redwCfvy4owIGui2Xmk9Q7BTjQ9b4D+Px1QQEOdF0sM5+k3inAga73HcDnrwsKcKDrYpn5JPVOAQ50ve8APn9dUIADXRfLzCepdwpwoOt9B/D564ICHOi6WGY+Sb1TgANd7zuAz18XFPj/WsGwXGrMaOEAAAAASUVORK5CYII="/>%0D%0A</defs>%0D%0A</svg>%0D%0A';
564
930
 
565
931
  // src/components/EmptyState.tsx
566
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
932
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
567
933
  var EmptyState = ({
568
934
  title = "No data available",
569
935
  description = "There is nothing to display here.",
570
936
  imgSrc = Box_default
571
937
  }) => {
572
- return /* @__PURE__ */ jsxs5("div", { className: "empty-state", children: [
573
- /* @__PURE__ */ jsx7("div", { className: "empty-image-wrapper", children: /* @__PURE__ */ jsx7("img", { src: imgSrc, alt: "Empty" }) }),
574
- /* @__PURE__ */ jsx7("h6", { children: title }),
575
- /* @__PURE__ */ jsx7("p", { className: "text-muted mb-0", children: description })
938
+ return /* @__PURE__ */ jsxs6("div", { className: "empty-state", children: [
939
+ /* @__PURE__ */ jsx8("div", { className: "empty-image-wrapper", children: /* @__PURE__ */ jsx8("img", { src: imgSrc, alt: "Empty" }) }),
940
+ /* @__PURE__ */ jsx8("h6", { children: title }),
941
+ /* @__PURE__ */ jsx8("p", { className: "text-muted mb-0", children: description })
576
942
  ] });
577
943
  };
578
944
  var EmptyState_default = EmptyState;
@@ -581,9 +947,9 @@ var EmptyState_default = EmptyState;
581
947
  var NoSearchResult_default = 'data:image/svg+xml,<svg width="250" height="200" viewBox="0 0 250 200" fill="none" xmlns="http://www.w3.org/2000/svg">%0D%0A<rect width="250" height="200" fill="white"/>%0D%0A<path fill-rule="evenodd" clip-rule="evenodd" d="M207 65C210.866 65 214 68.134 214 72C214 75.866 210.866 79 207 79H167C170.866 79 174 82.134 174 86C174 89.866 170.866 93 167 93H189C192.866 93 196 96.134 196 100C196 103.866 192.866 107 189 107H178.826C173.952 107 170 110.134 170 114C170 116.577 172 118.911 176 121C179.866 121 183 124.134 183 128C183 131.866 179.866 135 176 135H93C89.134 135 86 131.866 86 128C86 124.134 89.134 121 93 121H54C50.134 121 47 117.866 47 114C47 110.134 50.134 107 54 107H94C97.866 107 101 103.866 101 100C101 96.134 97.866 93 94 93H69C65.134 93 62 89.866 62 86C62 82.134 65.134 79 69 79H109C105.134 79 102 75.866 102 72C102 68.134 105.134 65 109 65H207ZM207 93C210.866 93 214 96.134 214 100C214 103.866 210.866 107 207 107C203.134 107 200 103.866 200 100C200 96.134 203.134 93 207 93Z" fill="%23F3F7FF"/>%0D%0A<path d="M120.5 133C139.002 133 154 118.002 154 99.5C154 80.9985 139.002 66 120.5 66C101.998 66 87 80.9985 87 99.5C87 118.002 101.998 133 120.5 133Z" fill="%23F3F7FF" stroke="%231F64E7" stroke-width="2.5"/>%0D%0A<path fill-rule="evenodd" clip-rule="evenodd" d="M115.132 125.494C116.891 125.819 118.68 125.987 120.5 126C135.136 126 147 114.136 147 99.5C147 84.8645 135.136 73 120.5 73C116.74 73 113.164 73.7829 109.924 75.1946C104.294 77.6479 99.6816 81.9999 96.896 87.4419C95.0445 91.0589 94 95.1575 94 99.5C94 103.44 94.8599 107.179 96.4021 110.54C97.5032 112.94 98.9521 115.146 100.684 117.096" fill="white"/>%0D%0A<path d="M115.132 125.494C116.891 125.819 118.68 125.987 120.5 126C135.136 126 147 114.136 147 99.5C147 84.8645 135.136 73 120.5 73C116.74 73 113.164 73.7829 109.924 75.1946C104.294 77.6479 99.6816 81.9999 96.896 87.4419C95.0445 91.0589 94 95.1575 94 99.5C94 103.44 94.8599 107.179 96.4021 110.54C97.5032 112.94 98.9521 115.146 100.684 117.096" stroke="%231F64E7" stroke-width="2.5" stroke-linecap="round"/>%0D%0A<path d="M103.797 120.075C105.945 121.821 108.372 123.237 111.001 124.247" stroke="%231F64E7" stroke-width="2.5" stroke-linecap="round"/>%0D%0A<path d="M148 126L154 132" stroke="%231F64E7" stroke-width="2.5"/>%0D%0A<path fill-rule="evenodd" clip-rule="evenodd" d="M153.03 131.03C151.138 132.923 151.138 135.992 153.03 137.884L164.116 148.97C166.008 150.862 169.077 150.862 170.97 148.97C172.863 147.077 172.863 144.008 170.97 142.116L159.885 131.03C157.992 129.138 154.923 129.138 153.03 131.03Z" fill="%23E8F0FE" stroke="%231F64E7" stroke-width="2.5"/>%0D%0A<path d="M158 133L169 144" stroke="white" stroke-width="2.5" stroke-linecap="round"/>%0D%0A<path fill-rule="evenodd" clip-rule="evenodd" d="M114 88C114 99.598 123.402 109 135 109C137.278 109 139.472 108.637 141.526 107.966C138.173 116.287 130.023 122.161 120.5 122.161C107.985 122.161 97.8394 112.015 97.8394 99.5C97.8394 88.1596 106.17 78.7648 117.045 77.1011C115.113 80.2793 114 84.0097 114 88Z" fill="%23E8F0FE"/>%0D%0A<path d="M121 81C119.727 81 118.482 81.1253 117.279 81.3642M113.645 82.4761C106.804 85.3508 102 92.1144 102 100" stroke="%2375A4FE" stroke-width="2.5" stroke-linecap="round"/>%0D%0A<path d="M174.176 99.7773H166M180.5 92H163.324H180.5ZM187.5 92H185.279H187.5Z" stroke="%2375A4FE" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>%0D%0A<path d="M84.1758 121.777H76M79.5 113H62.3242H79.5ZM56.5 113H52.2788H56.5Z" stroke="%2375A4FE" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>%0D%0A</svg>%0D%0A';
582
948
 
583
949
  // src/components/icons/ArrowFromBottonToRight.tsx
584
- import { jsx as jsx8 } from "react/jsx-runtime";
950
+ import { jsx as jsx9 } from "react/jsx-runtime";
585
951
  var ArrowFromBottonToRight = () => {
586
- return /* @__PURE__ */ jsx8(
952
+ return /* @__PURE__ */ jsx9(
587
953
  "svg",
588
954
  {
589
955
  className: "w-[18px] h-[18px] text-gray-800 dark:text-white cursor-pointer",
@@ -593,7 +959,7 @@ var ArrowFromBottonToRight = () => {
593
959
  height: "18",
594
960
  fill: "none",
595
961
  viewBox: "0 0 24 24",
596
- children: /* @__PURE__ */ jsx8(
962
+ children: /* @__PURE__ */ jsx9(
597
963
  "path",
598
964
  {
599
965
  d: "M4 20V18.6C4 15.2397 4 13.5595 4.65396 12.2761C5.2292 11.1471 6.14708 10.2292 7.27606 9.65396C8.55953 9 10.2397 9 13.6 9H20M20 9L15 14M20 9L15 4",
@@ -640,421 +1006,119 @@ var getPosition = (x, y, el) => {
640
1006
  }
641
1007
  if (top + rect.height > innerHeight) {
642
1008
  top = y - rect.height - OFFSET;
643
- }
644
- if (top < 0) {
645
- top = OFFSET;
646
- }
647
- return { left, top };
648
- };
649
- var showTooltip = (text, x, y) => {
650
- const el = getToolTip();
651
- el.textContent = text;
652
- el.style.opacity = "1";
653
- el.style.left = "0px";
654
- el.style.top = "0px";
655
- const { left, top } = getPosition(x, y, el);
656
- el.style.left = `${left}px`;
657
- el.style.top = `${top}px`;
658
- };
659
- var hideTooltip = () => {
660
- if (!tooltipEl) return;
661
- tooltipEl.style.opacity = "0";
662
- };
663
-
664
- // src/components/BulkAction.tsx
665
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
666
- function BulkAction({ records, actions }) {
667
- return /* @__PURE__ */ jsxs6("div", { className: "d-flex flex-row gap-1 align-items-center py-1 ps-4", children: [
668
- /* @__PURE__ */ jsx9(ArrowFromBottonToRight_default, {}),
669
- /* @__PURE__ */ jsx9("span", { children: `(${records.size}) ${records.size > 1 ? "Records" : "Record"}` }),
670
- " ",
671
- actions.length > 0 && actions?.filter((act) => act.isVisible)?.map((action, index) => /* @__PURE__ */ jsx9(
672
- "i",
673
- {
674
- className: `${action.icon}`,
675
- onClick: (e) => {
676
- e.stopPropagation();
677
- action.onBulkClick && action.onBulkClick(records);
678
- },
679
- onMouseEnter: (e) => showTooltip(action.label, e.clientX, e.clientY),
680
- onMouseMove: (e) => showTooltip(action.label, e.clientX, e.clientY),
681
- onMouseLeave: hideTooltip
682
- },
683
- `${action.label}_${index}`
684
- ))
685
- ] });
686
- }
687
- var BulkAction_default = BulkAction;
688
-
689
- // src/components/Paginantion.tsx
690
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
691
- var getPaginationRange = (currentPage, totalPages, delta = 1) => {
692
- const range = [];
693
- const rangeWithDots = [];
694
- let last;
695
- for (let i = 1; i <= totalPages; i++) {
696
- if (i === 1 || i === totalPages || i >= currentPage - delta && i <= currentPage + delta) {
697
- range.push(i);
698
- }
699
- }
700
- for (const page of range) {
701
- if (last !== void 0) {
702
- if (page - last === 2) {
703
- rangeWithDots.push(last + 1);
704
- } else if (page - last > 2) {
705
- rangeWithDots.push("...");
706
- }
707
- }
708
- rangeWithDots.push(page);
709
- last = page;
710
- }
711
- return rangeWithDots;
712
- };
713
- var Pagination = ({
714
- currentPage,
715
- totalPages,
716
- onPageChange
717
- }) => {
718
- if (totalPages <= 1) return null;
719
- const paginationRange = getPaginationRange(currentPage, totalPages);
720
- return /* @__PURE__ */ jsx10("nav", { "aria-label": "Page navigation", children: /* @__PURE__ */ jsxs7("ul", { className: "pagination pagination-sm justify-content-end py-1 mx-1", children: [
721
- /* @__PURE__ */ jsx10("li", { className: `page-item ${currentPage === 1 ? "disabled" : ""}`, children: /* @__PURE__ */ jsx10(
722
- "button",
723
- {
724
- className: "page-link",
725
- onClick: () => onPageChange(currentPage - 1),
726
- disabled: currentPage === 1,
727
- children: "\xAB"
728
- }
729
- ) }),
730
- paginationRange.map((item, index) => /* @__PURE__ */ jsx10(
731
- "li",
732
- {
733
- className: `page-item ${item === currentPage ? "active" : ""} ${item === "..." ? "disabled" : ""}`,
734
- children: item === "..." ? /* @__PURE__ */ jsx10("span", { className: "page-link", children: "\u2026" }) : /* @__PURE__ */ jsx10("button", { className: "page-link", onClick: () => onPageChange(item), children: item })
735
- },
736
- index
737
- )),
738
- /* @__PURE__ */ jsx10(
739
- "li",
740
- {
741
- className: `page-item ${currentPage === totalPages ? "disabled" : ""}`,
742
- children: /* @__PURE__ */ jsx10(
743
- "button",
744
- {
745
- className: "page-link",
746
- onClick: () => onPageChange(currentPage + 1),
747
- disabled: currentPage === totalPages,
748
- children: "\xBB"
749
- }
750
- )
751
- }
752
- )
753
- ] }) });
754
- };
755
- var Paginantion_default = Pagination;
756
-
757
- // src/components/dropdown/PamDropdown.tsx
758
- import {
759
- useEffect as useEffect4,
760
- useLayoutEffect,
761
- useMemo as useMemo2,
762
- useRef,
763
- useState as useState4
764
- } from "react";
765
- import { createPortal } from "react-dom";
766
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
767
- function PamDropdown({
768
- trigger,
769
- items,
770
- placement = "bottom-start",
771
- offset = 6,
772
- disabled = false,
773
- closeOnItemClick = true,
774
- className = ""
775
- }) {
776
- const triggerRef = useRef(null);
777
- const menuRef = useRef(null);
778
- const [open, setOpen] = useState4(false);
779
- const [pos, setPos] = useState4({ top: 0, left: 0 });
780
- const [openSubKeys, setOpenSubKeys] = useState4({});
781
- const portalRoot = useMemo2(() => {
782
- const el = document.getElementById("pam-portal-root");
783
- if (el) return el;
784
- const created = document.createElement("div");
785
- created.id = "pam-portal-root";
786
- document.body.appendChild(created);
787
- return created;
788
- }, []);
789
- function close() {
790
- setOpen(false);
791
- setOpenSubKeys({});
792
- }
793
- function toggle() {
794
- if (disabled) return;
795
- setOpen((v) => {
796
- const next = !v;
797
- if (!next) setOpenSubKeys({});
798
- return next;
799
- });
800
- }
801
- function getDropdownPosition(triggerEl, menuEl) {
802
- const rect = triggerEl.getBoundingClientRect();
803
- const menuRect = menuEl.getBoundingClientRect();
804
- let top = rect.bottom + offset + window.scrollY;
805
- let left = rect.left + window.scrollX;
806
- if (placement.startsWith("top")) {
807
- top = rect.top - menuRect.height - offset + window.scrollY;
808
- }
809
- if (placement.endsWith("end")) {
810
- left = rect.right - menuRect.width + window.scrollX;
811
- }
812
- const minLeft = 8 + window.scrollX;
813
- const maxLeft = window.innerWidth - menuRect.width - 8 + window.scrollX;
814
- left = Math.max(minLeft, Math.min(left, maxLeft));
815
- const minTop = 8 + window.scrollY;
816
- const maxTop = window.innerHeight - menuRect.height - 8 + window.scrollY;
817
- top = Math.max(minTop, Math.min(top, maxTop));
818
- const bottomOverflow = top + menuRect.height > window.innerHeight + window.scrollY;
819
- const topOverflow = top < window.scrollY;
820
- if (bottomOverflow && rect.top > menuRect.height) {
821
- top = rect.top - menuRect.height - offset + window.scrollY;
822
- } else if (topOverflow && window.innerHeight - rect.bottom > menuRect.height) {
823
- top = rect.bottom + offset + window.scrollY;
824
- }
825
- return { top, left };
826
- }
827
- function updatePosition() {
828
- const t = triggerRef.current;
829
- const m = menuRef.current;
830
- if (!t || !m) return;
831
- setPos(getDropdownPosition(t, m));
832
- }
833
- useLayoutEffect(() => {
834
- if (!open) return;
835
- updatePosition();
836
- }, [open, placement]);
837
- useEffect4(() => {
838
- if (!open) return;
839
- const onDown = (e) => {
840
- const t = triggerRef.current;
841
- const m = menuRef.current;
842
- if (!t || !m) return;
843
- const target = e.target;
844
- if (t.contains(target)) return;
845
- if (m.contains(target)) return;
846
- close();
847
- };
848
- const onKey = (e) => {
849
- if (e.key === "Escape") close();
850
- };
851
- document.addEventListener("mousedown", onDown);
852
- document.addEventListener("keydown", onKey);
853
- return () => {
854
- document.removeEventListener("mousedown", onDown);
855
- document.removeEventListener("keydown", onKey);
856
- };
857
- }, [open]);
858
- useEffect4(() => {
859
- if (!open) return;
860
- const handler = () => updatePosition();
861
- window.addEventListener("scroll", handler, true);
862
- window.addEventListener("resize", handler);
863
- return () => {
864
- window.removeEventListener("scroll", handler, true);
865
- window.removeEventListener("resize", handler);
866
- };
867
- }, [open]);
868
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
869
- /* @__PURE__ */ jsx11("span", { ref: triggerRef, className: `pam-dropdown-trigger ${className}`, children: /* @__PURE__ */ jsx11("span", { onClick: toggle, style: { display: "inline-flex" }, children: trigger }) }),
870
- open && createPortal(
871
- /* @__PURE__ */ jsx11(
872
- "div",
873
- {
874
- ref: menuRef,
875
- className: "pam-dropdown-menu",
876
- style: {
877
- top: pos.top,
878
- left: pos.left
879
- },
880
- children: /* @__PURE__ */ jsx11(
881
- PamDropdownList,
882
- {
883
- items,
884
- closeOnItemClick,
885
- onClose: close,
886
- openSubKeys,
887
- setOpenSubKeys,
888
- level: 0
889
- }
890
- )
891
- }
892
- ),
893
- portalRoot
894
- )
895
- ] });
896
- }
897
- function PamDropdownList({
898
- items,
899
- onClose,
900
- closeOnItemClick,
901
- openSubKeys,
902
- setOpenSubKeys,
903
- level
904
- }) {
905
- return /* @__PURE__ */ jsx11("ul", { className: "pam-dropdown-list", children: items.map((item, index) => /* @__PURE__ */ jsx11(
906
- PamDropdownNode,
907
- {
908
- item,
909
- onClose,
910
- closeOnItemClick,
911
- openSubKeys,
912
- setOpenSubKeys,
913
- level,
914
- index
915
- },
916
- item.key ?? `${level}-${index}`
917
- )) });
918
- }
919
- function PamDropdownNode({
920
- item,
921
- onClose,
922
- closeOnItemClick,
923
- openSubKeys,
924
- setOpenSubKeys,
925
- level,
926
- index
927
- }) {
928
- const liRef = useRef(null);
929
- const submenuRef = useRef(null);
930
- const hasChildren = !!item.children?.length;
931
- const nodeKey = item.key ?? `${level}-${index}`;
932
- const submenuOpen = !!openSubKeys[nodeKey];
933
- useLayoutEffect(() => {
934
- if (!submenuOpen) return;
935
- const li = liRef.current;
936
- const menu = submenuRef.current;
937
- if (!li || !menu) return;
938
- const rect = li.getBoundingClientRect();
939
- menu.style.left = "0px";
940
- menu.style.top = "0px";
941
- menu.style.maxHeight = "";
942
- menu.style.overflowY = "";
943
- const menuRect = menu.getBoundingClientRect();
944
- const gap = 6;
945
- const spaceRight = window.innerWidth - rect.right;
946
- const spaceLeft = rect.left;
947
- const spaceBottom = window.innerHeight - rect.bottom;
948
- const spaceTop = rect.top;
949
- let left = rect.right + gap;
950
- let top = rect.top;
951
- let mode = "right";
952
- if (spaceRight >= menuRect.width) {
953
- mode = "right";
954
- left = rect.right + gap;
955
- top = rect.top;
956
- } else if (spaceLeft >= menuRect.width) {
957
- mode = "left";
958
- left = rect.left - menuRect.width - gap;
959
- top = rect.top;
960
- } else {
961
- if (spaceBottom >= menuRect.height) {
962
- mode = "bottom";
963
- left = rect.left;
964
- top = rect.bottom + gap;
965
- } else if (spaceTop >= menuRect.height) {
966
- mode = "top";
967
- left = rect.left;
968
- top = rect.top - menuRect.height - gap;
969
- } else {
970
- mode = "bottom";
971
- left = rect.left;
972
- top = rect.bottom + gap;
973
- }
1009
+ }
1010
+ if (top < 0) {
1011
+ top = OFFSET;
1012
+ }
1013
+ return { left, top };
1014
+ };
1015
+ var showTooltip = (text, x, y) => {
1016
+ const el = getToolTip();
1017
+ el.textContent = text;
1018
+ el.style.opacity = "1";
1019
+ el.style.left = "0px";
1020
+ el.style.top = "0px";
1021
+ const { left, top } = getPosition(x, y, el);
1022
+ el.style.left = `${left}px`;
1023
+ el.style.top = `${top}px`;
1024
+ };
1025
+ var hideTooltip = () => {
1026
+ if (!tooltipEl) return;
1027
+ tooltipEl.style.opacity = "0";
1028
+ };
1029
+
1030
+ // src/components/BulkAction.tsx
1031
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1032
+ function BulkAction({ records, actions }) {
1033
+ return /* @__PURE__ */ jsxs7("div", { className: "d-flex flex-row gap-1 align-items-center py-1 ps-4", children: [
1034
+ /* @__PURE__ */ jsx10(ArrowFromBottonToRight_default, {}),
1035
+ /* @__PURE__ */ jsx10("span", { children: `(${records.size}) ${records.size > 1 ? "Records" : "Record"}` }),
1036
+ " ",
1037
+ actions.length > 0 && actions?.filter((act) => act.isVisible)?.map((action, index) => /* @__PURE__ */ jsx10(
1038
+ "i",
1039
+ {
1040
+ className: `${action.icon}`,
1041
+ onClick: (e) => {
1042
+ e.stopPropagation();
1043
+ action.onBulkClick && action.onBulkClick(records);
1044
+ },
1045
+ onMouseEnter: (e) => showTooltip(action.label, e.clientX, e.clientY),
1046
+ onMouseMove: (e) => showTooltip(action.label, e.clientX, e.clientY),
1047
+ onMouseLeave: hideTooltip
1048
+ },
1049
+ `${action.label}_${index}`
1050
+ ))
1051
+ ] });
1052
+ }
1053
+ var BulkAction_default = BulkAction;
1054
+
1055
+ // src/components/Paginantion.tsx
1056
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1057
+ var getPaginationRange = (currentPage, totalPages, delta = 1) => {
1058
+ const range = [];
1059
+ const rangeWithDots = [];
1060
+ let last;
1061
+ for (let i = 1; i <= totalPages; i++) {
1062
+ if (i === 1 || i === totalPages || i >= currentPage - delta && i <= currentPage + delta) {
1063
+ range.push(i);
974
1064
  }
975
- const minLeft = 8;
976
- const maxLeft = window.innerWidth - menuRect.width - 8;
977
- left = Math.max(minLeft, Math.min(left, maxLeft));
978
- const minTop = 8;
979
- const maxTop = window.innerHeight - menuRect.height - 8;
980
- top = Math.max(minTop, Math.min(top, maxTop));
981
- const maxHeight = window.innerHeight - 16;
982
- menu.style.maxHeight = `${maxHeight}px`;
983
- menu.style.overflowY = "auto";
984
- menu.style.left = `${left}px`;
985
- menu.style.top = `${top}px`;
986
- menu.setAttribute("data-placement", mode);
987
- }, [submenuOpen]);
988
- const handleClick = (e) => {
989
- e.stopPropagation();
990
- if (item.disabled) return;
991
- if (hasChildren) {
992
- setOpenSubKeys((prev) => {
993
- const next = {};
994
- Object.keys(prev).forEach((k) => {
995
- const lvl = Number(k.split("-")[0]);
996
- if (lvl < level) next[k] = prev[k];
997
- });
998
- next[nodeKey] = !prev[nodeKey];
999
- return next;
1000
- });
1001
- return;
1065
+ }
1066
+ for (const page of range) {
1067
+ if (last !== void 0) {
1068
+ if (page - last === 2) {
1069
+ rangeWithDots.push(last + 1);
1070
+ } else if (page - last > 2) {
1071
+ rangeWithDots.push("...");
1072
+ }
1002
1073
  }
1003
- item.onClick?.();
1004
- if (item.keepOpenOnClick) return;
1005
- if (closeOnItemClick) onClose();
1006
- };
1007
- return /* @__PURE__ */ jsxs8(
1008
- "li",
1009
- {
1010
- ref: liRef,
1011
- className: [
1012
- !item.custome ? "pam-dropdown-item" : "",
1013
- item.danger ? "danger" : "",
1014
- item.disabled ? "disabled" : "",
1015
- hasChildren ? "has-children" : "",
1016
- submenuOpen ? "open" : ""
1017
- ].join(" "),
1018
- onClick: handleClick,
1019
- children: [
1020
- /* @__PURE__ */ jsxs8(
1021
- "div",
1022
- {
1023
- className: `${item.rightSlot ? "pam-dropdown-item-inner-rightSlot" : "pam-dropdown-item-inner"} `,
1024
- children: [
1025
- /* @__PURE__ */ jsxs8("div", { className: "pam-left", children: [
1026
- item.icon && /* @__PURE__ */ jsx11("i", { className: `${item.icon} pam-icon` }),
1027
- /* @__PURE__ */ jsx11("span", { className: "pam-label", children: item.label })
1028
- ] }),
1029
- /* @__PURE__ */ jsxs8("div", { className: "pam-right", children: [
1030
- item.rightSlot && /* @__PURE__ */ jsx11(
1031
- "span",
1032
- {
1033
- className: "pam-rightslot",
1034
- onClick: (e) => e.stopPropagation(),
1035
- children: item.rightSlot
1036
- }
1037
- ),
1038
- hasChildren && /* @__PURE__ */ jsx11("i", { className: "bx bx-chevron-right pam-arrow" })
1039
- ] })
1040
- ]
1041
- }
1042
- ),
1043
- hasChildren && submenuOpen && /* @__PURE__ */ jsx11("div", { ref: submenuRef, className: "pam-submenu", children: /* @__PURE__ */ jsx11(
1044
- PamDropdownList,
1074
+ rangeWithDots.push(page);
1075
+ last = page;
1076
+ }
1077
+ return rangeWithDots;
1078
+ };
1079
+ var Pagination = ({
1080
+ currentPage,
1081
+ totalPages,
1082
+ onPageChange
1083
+ }) => {
1084
+ if (totalPages <= 1) return null;
1085
+ const paginationRange = getPaginationRange(currentPage, totalPages);
1086
+ return /* @__PURE__ */ jsx11("nav", { "aria-label": "Page navigation", children: /* @__PURE__ */ jsxs8("ul", { className: "pagination pagination-sm justify-content-end py-1 mx-1", children: [
1087
+ /* @__PURE__ */ jsx11("li", { className: `page-item ${currentPage === 1 ? "disabled" : ""}`, children: /* @__PURE__ */ jsx11(
1088
+ "button",
1089
+ {
1090
+ className: "page-link",
1091
+ onClick: () => onPageChange(currentPage - 1),
1092
+ disabled: currentPage === 1,
1093
+ children: "\xAB"
1094
+ }
1095
+ ) }),
1096
+ paginationRange.map((item, index) => /* @__PURE__ */ jsx11(
1097
+ "li",
1098
+ {
1099
+ className: `page-item ${item === currentPage ? "active" : ""} ${item === "..." ? "disabled" : ""}`,
1100
+ children: item === "..." ? /* @__PURE__ */ jsx11("span", { className: "page-link", children: "\u2026" }) : /* @__PURE__ */ jsx11("button", { className: "page-link", onClick: () => onPageChange(item), children: item })
1101
+ },
1102
+ index
1103
+ )),
1104
+ /* @__PURE__ */ jsx11(
1105
+ "li",
1106
+ {
1107
+ className: `page-item ${currentPage === totalPages ? "disabled" : ""}`,
1108
+ children: /* @__PURE__ */ jsx11(
1109
+ "button",
1045
1110
  {
1046
- items: item.children,
1047
- onClose,
1048
- closeOnItemClick,
1049
- openSubKeys,
1050
- setOpenSubKeys,
1051
- level: level + 1
1111
+ className: "page-link",
1112
+ onClick: () => onPageChange(currentPage + 1),
1113
+ disabled: currentPage === totalPages,
1114
+ children: "\xBB"
1052
1115
  }
1053
- ) })
1054
- ]
1055
- }
1056
- );
1057
- }
1116
+ )
1117
+ }
1118
+ )
1119
+ ] }) });
1120
+ };
1121
+ var Paginantion_default = Pagination;
1058
1122
 
1059
1123
  // src/components/MainFilter.tsx
1060
1124
  import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
@@ -1289,12 +1353,14 @@ var PamGrid = ({
1289
1353
  "bulk-data-toggle",
1290
1354
  false
1291
1355
  );
1356
+ const [editingCell, setEditingCell] = useState5(null);
1292
1357
  const wrapperRef = useRef2(null);
1293
1358
  const dragState = useRef2({ from: null });
1294
1359
  const {
1295
1360
  rows,
1296
1361
  page,
1297
1362
  totalPages,
1363
+ totalRecord,
1298
1364
  pageSize,
1299
1365
  setPage,
1300
1366
  setPageSize,
@@ -1445,7 +1511,13 @@ var PamGrid = ({
1445
1511
  ]
1446
1512
  }
1447
1513
  ),
1448
- /* @__PURE__ */ jsx13("div", { className: `flex-shrink-0 ${features.fullScreen ? "" : "d-none"}`, children: isFullScreen ? /* @__PURE__ */ jsx13(Minimize_default, { onClick: () => setFullScreen(!isFullScreen) }) : /* @__PURE__ */ jsx13(Compress_default, { onClick: () => setFullScreen(!isFullScreen) }) })
1514
+ /* @__PURE__ */ jsx13(
1515
+ "div",
1516
+ {
1517
+ className: `flex-shrink-0 ${features.fullScreen ? "" : "d-none"}`,
1518
+ children: isFullScreen ? /* @__PURE__ */ jsx13(Minimize_default, { onClick: () => setFullScreen(!isFullScreen) }) : /* @__PURE__ */ jsx13(Compress_default, { onClick: () => setFullScreen(!isFullScreen) })
1519
+ }
1520
+ )
1449
1521
  ] }) })
1450
1522
  ] }),
1451
1523
  customeDiv && customeDiv,
@@ -1462,7 +1534,7 @@ var PamGrid = ({
1462
1534
  }
1463
1535
  )
1464
1536
  ] }),
1465
- /* @__PURE__ */ jsx13(
1537
+ /* @__PURE__ */ jsxs10(
1466
1538
  "div",
1467
1539
  {
1468
1540
  ref: wrapperRef,
@@ -1470,197 +1542,211 @@ var PamGrid = ({
1470
1542
  style: {
1471
1543
  height: gridHeight
1472
1544
  },
1473
- children: /* @__PURE__ */ jsxs10(
1474
- "table",
1475
- {
1476
- className: "table table-sm rounded mb-0 position-relative",
1477
- style: { width: "max-content", minWidth: "100%" },
1478
- children: [
1479
- /* @__PURE__ */ jsx13(
1480
- "thead",
1481
- {
1482
- className: "bg-light-secondary border p-2 bg-light rounded",
1483
- style: { position: "sticky", top: 0, zIndex: 10 },
1484
- children: /* @__PURE__ */ jsxs10("tr", { className: "p-2", children: [
1485
- features.IsNumbering && /* @__PURE__ */ jsx13("th", { className: "text-center", children: "#" }),
1486
- features.expand && /* @__PURE__ */ jsx13("th", { className: "text-center ticky-action-column", children: /* @__PURE__ */ jsx13("i", { className: "bx bx-collapse-vertical d-none" }) }),
1487
- isBulkAction && /* @__PURE__ */ jsx13(
1488
- "th",
1489
- {
1490
- style: { width: 32, position: "sticky", top: 0, zIndex: 10 },
1491
- className: "text-center ticky-action-column",
1492
- children: /* @__PURE__ */ jsx13(
1493
- "input",
1494
- {
1495
- type: "checkbox",
1496
- className: "form-check-input mx-3",
1497
- checked: currentRows.length > 0 && currentRows.every((r) => selected.has(String(r[rowKey]))),
1498
- onChange: (e) => e.target.checked ? selectAllOnPage(currentRows) : deselectAllOnPage(currentRows),
1499
- disabled: isFetching
1500
- }
1501
- )
1502
- }
1503
- ),
1504
- visibleColumns.map((col, index) => {
1505
- const style = {
1506
- minWidth: col.width || 120,
1507
- width: col.width,
1508
- ...col.pinned && { position: "sticky" },
1509
- ...col.pinned === "left" && {
1510
- left: `${getLeftOffset(colState, col.key)}px`
1511
- },
1512
- ...col.pinned === "right" && {
1513
- right: `${getRightOffset(colState, col.key)}px`
1514
- }
1515
- };
1516
- return /* @__PURE__ */ jsx13(
1545
+ children: [
1546
+ /* @__PURE__ */ jsxs10(
1547
+ "table",
1548
+ {
1549
+ className: "table table-sm rounded mb-0 position-relative",
1550
+ style: { width: "max-content", minWidth: "100%" },
1551
+ children: [
1552
+ /* @__PURE__ */ jsx13(
1553
+ "thead",
1554
+ {
1555
+ className: "bg-light-secondary border p-2 bg-light rounded",
1556
+ style: { position: "sticky", top: 0, zIndex: 10 },
1557
+ children: /* @__PURE__ */ jsxs10("tr", { className: "p-2", children: [
1558
+ features.IsNumbering && /* @__PURE__ */ jsx13("th", { className: "text-center", children: "#" }),
1559
+ features.expand && /* @__PURE__ */ jsx13("th", { className: "text-center ticky-action-column", children: /* @__PURE__ */ jsx13("i", { className: "bx bx-collapse-vertical d-none" }) }),
1560
+ isBulkAction && /* @__PURE__ */ jsx13(
1517
1561
  "th",
1518
1562
  {
1519
- draggable: features.reorder,
1520
- onDragStart: (e) => {
1521
- setDraggingCol(String(col.key));
1522
- onDragStart(e, String(col.key));
1523
- },
1524
- onDragEnd: () => setDraggingCol(null),
1525
- onDragOver: (e) => e.preventDefault(),
1526
- onDrop: (e) => onDrop(e, col.key),
1527
- onMouseMove: (e) => {
1528
- const side = getResizeSide(e, index);
1529
- if (side) {
1530
- e.currentTarget.style.cursor = "col-resize";
1531
- } else if (draggingCol === col.key) {
1532
- e.currentTarget.style.cursor = "grabbing";
1533
- } else if (features.reorder) {
1534
- e.currentTarget.style.cursor = "grab";
1535
- } else {
1536
- e.currentTarget.style.cursor = "default";
1563
+ style: { width: 32, position: "sticky", top: 0, zIndex: 10 },
1564
+ className: "text-center ticky-action-column",
1565
+ children: /* @__PURE__ */ jsx13(
1566
+ "input",
1567
+ {
1568
+ type: "checkbox",
1569
+ className: "form-check-input mx-3",
1570
+ checked: currentRows.length > 0 && currentRows.every((r) => selected.has(String(r[rowKey]))),
1571
+ onChange: (e) => e.target.checked ? selectAllOnPage(currentRows) : deselectAllOnPage(currentRows),
1572
+ disabled: isFetching
1537
1573
  }
1574
+ )
1575
+ }
1576
+ ),
1577
+ visibleColumns.map((col, index) => {
1578
+ const style = {
1579
+ minWidth: col.width || 120,
1580
+ width: col.width,
1581
+ ...col.pinned && { position: "sticky" },
1582
+ ...col.pinned === "left" && {
1583
+ left: `${getLeftOffset(colState, col.key)}px`
1538
1584
  },
1539
- onMouseLeave: (e) => {
1540
- e.currentTarget.style.cursor = "default";
1541
- },
1542
- onMouseDown: (e) => {
1543
- const side = getResizeSide(e, index);
1544
- if (!side) return;
1545
- e.stopPropagation();
1546
- onResizeMouseDown(e, col.key, side);
1547
- },
1548
- className: `pms-col-header vs-th
1585
+ ...col.pinned === "right" && {
1586
+ right: `${getRightOffset(colState, col.key)}px`
1587
+ }
1588
+ };
1589
+ return /* @__PURE__ */ jsx13(
1590
+ "th",
1591
+ {
1592
+ draggable: features.reorder,
1593
+ onDragStart: (e) => {
1594
+ setDraggingCol(String(col.key));
1595
+ onDragStart(e, String(col.key));
1596
+ },
1597
+ onDragEnd: () => setDraggingCol(null),
1598
+ onDragOver: (e) => e.preventDefault(),
1599
+ onDrop: (e) => onDrop(e, col.key),
1600
+ onMouseMove: (e) => {
1601
+ const side = getResizeSide(e, index);
1602
+ if (side) {
1603
+ e.currentTarget.style.cursor = "col-resize";
1604
+ } else if (draggingCol === col.key) {
1605
+ e.currentTarget.style.cursor = "grabbing";
1606
+ } else if (features.reorder) {
1607
+ e.currentTarget.style.cursor = "grab";
1608
+ } else {
1609
+ e.currentTarget.style.cursor = "default";
1610
+ }
1611
+ },
1612
+ onMouseLeave: (e) => {
1613
+ e.currentTarget.style.cursor = "default";
1614
+ },
1615
+ onMouseDown: (e) => {
1616
+ const side = getResizeSide(e, index);
1617
+ if (!side) return;
1618
+ e.stopPropagation();
1619
+ onResizeMouseDown(e, col.key, side);
1620
+ },
1621
+ className: `pms-col-header vs-th
1549
1622
  ${col.pinned ? `pinned pinned-${col.pinned}` : ""}
1550
1623
  `,
1551
- style,
1552
- children: /* @__PURE__ */ jsxs10("div", { className: "d-flex align-items-center w-100 px-1", children: [
1553
- /* @__PURE__ */ jsx13(
1554
- "div",
1555
- {
1556
- className: `flex-grow-1 d-flex align-items-center
1624
+ style,
1625
+ children: /* @__PURE__ */ jsxs10("div", { className: "d-flex align-items-center w-100 px-1", children: [
1626
+ /* @__PURE__ */ jsx13(
1627
+ "div",
1628
+ {
1629
+ className: `flex-grow-1 d-flex align-items-center
1557
1630
  ${col.align === "center" ? "justify-content-center" : ""}
1558
1631
  ${col.align === "end" ? "justify-content-end" : ""}
1559
1632
  ${!col.align || col.align === "start" ? "justify-content-start" : ""}
1560
1633
  `,
1561
- children: /* @__PURE__ */ jsxs10(
1562
- "div",
1563
- {
1564
- onClick: () => col.sortable && changeSort(String(col.key)),
1565
- className: col.sortable ? "cursor-pointer" : "",
1566
- children: [
1567
- /* @__PURE__ */ jsx13("small", { children: col.title }),
1568
- sortBy.key === col.key && /* @__PURE__ */ jsx13(
1569
- "i",
1570
- {
1571
- className: `bx bx-sm ${sortBy.dir === "asc" ? "bxs-chevron-up" : "bxs-chevron-down"}`
1572
- }
1573
- )
1574
- ]
1575
- }
1576
- )
1577
- }
1578
- ),
1579
- /* @__PURE__ */ jsx13("div", { className: "d-flex align-items-center gap-1 flex-shrink-0", children: features.pinning && /* @__PURE__ */ jsx13(
1580
- PamHeaderOption_default,
1581
- {
1582
- currentColumn: col,
1583
- gridFetaures: features,
1584
- grid
1585
- }
1586
- ) })
1587
- ] })
1588
- },
1589
- String(col.key)
1590
- );
1591
- }),
1592
- features.actions && /* @__PURE__ */ jsx13(
1593
- "th",
1634
+ children: /* @__PURE__ */ jsxs10(
1635
+ "div",
1636
+ {
1637
+ onClick: () => col.sortable && changeSort(String(col.key)),
1638
+ className: col.sortable ? "cursor-pointer" : "",
1639
+ children: [
1640
+ /* @__PURE__ */ jsx13("small", { children: col.title }),
1641
+ sortBy.key === col.key && /* @__PURE__ */ jsx13(
1642
+ "i",
1643
+ {
1644
+ className: `bx bx-sm ${sortBy.dir === "asc" ? "bxs-chevron-up" : "bxs-chevron-down"}`
1645
+ }
1646
+ )
1647
+ ]
1648
+ }
1649
+ )
1650
+ }
1651
+ ),
1652
+ /* @__PURE__ */ jsx13("div", { className: "d-flex align-items-center gap-1 flex-shrink-0", children: features.pinning && /* @__PURE__ */ jsx13(
1653
+ PamHeaderOption_default,
1654
+ {
1655
+ currentColumn: col,
1656
+ gridFetaures: features,
1657
+ grid
1658
+ }
1659
+ ) })
1660
+ ] })
1661
+ },
1662
+ String(col.key)
1663
+ );
1664
+ }),
1665
+ features.actions && /* @__PURE__ */ jsx13(
1666
+ "th",
1667
+ {
1668
+ className: "text-center sticky-action-column vs-th bg-white th-lastChild",
1669
+ style: { position: "sticky", right: 0, zIndex: 10 },
1670
+ children: "Action"
1671
+ }
1672
+ )
1673
+ ] })
1674
+ }
1675
+ ),
1676
+ /* @__PURE__ */ jsx13("tbody", { children: loading || rows.length === 0 ? Array.from({ length: 1 }).map((_, index) => /* @__PURE__ */ jsx13("tr", { className: "", children: /* @__PURE__ */ jsx13(
1677
+ "td",
1678
+ {
1679
+ colSpan: visibleColumns.length + (features.IsNumbering ? 1 : 0) + (features.selection ? 1 : 0) + (features.actions ? 1 : 0),
1680
+ className: "text-center py-4 ",
1681
+ children: /* @__PURE__ */ jsx13("div", { className: " d-flex justify-content-center align-items-center vh-50", children: /* @__PURE__ */ jsx13("div", { children: loading ? /* @__PURE__ */ jsx13("p", { children: "Loading..." }) : !loading && search ? /* @__PURE__ */ jsx13(
1682
+ EmptyState_default,
1594
1683
  {
1595
- className: "text-center sticky-action-column vs-th bg-white th-lastChild",
1596
- style: { position: "sticky", right: 0, zIndex: 10 },
1597
- children: "Action"
1684
+ title: emptyState.title,
1685
+ description: `No results found for "${search}"`,
1686
+ imgSrc: NoSearchResult_default
1598
1687
  }
1599
- )
1600
- ] })
1601
- }
1602
- ),
1603
- /* @__PURE__ */ jsx13("tbody", { children: loading || rows.length === 0 ? Array.from({ length: 1 }).map((_, index) => /* @__PURE__ */ jsx13("tr", { className: "", children: /* @__PURE__ */ jsx13(
1604
- "td",
1605
- {
1606
- colSpan: visibleColumns.length + (features.IsNumbering ? 1 : 0) + (features.selection ? 1 : 0) + (features.actions ? 1 : 0),
1607
- className: "text-center py-4 ",
1608
- children: /* @__PURE__ */ jsx13("div", { className: " d-flex justify-content-center align-items-center vh-50", children: /* @__PURE__ */ jsx13("div", { children: loading ? /* @__PURE__ */ jsx13("p", { children: "Loading..." }) : !loading && search ? /* @__PURE__ */ jsx13(
1609
- EmptyState_default,
1610
- {
1611
- title: emptyState.title,
1612
- description: `No results found for "${search}"`,
1613
- imgSrc: NoSearchResult_default
1614
- }
1615
- ) : /* @__PURE__ */ jsx13(
1616
- EmptyState_default,
1688
+ ) : /* @__PURE__ */ jsx13(
1689
+ EmptyState_default,
1690
+ {
1691
+ title: emptyState.title,
1692
+ imgSrc: Box_default,
1693
+ description: emptyState.description
1694
+ }
1695
+ ) }) })
1696
+ },
1697
+ index
1698
+ ) }, `row-${index}`)) : !loading && groupBy && groupedRows && groupedRows.length > 0 ? groupedRows.map((g, indG) => /* @__PURE__ */ jsxs10(React2.Fragment, { children: [
1699
+ /* @__PURE__ */ jsx13("tr", { className: "pam-bg-light-primary", children: /* @__PURE__ */ jsxs10(
1700
+ "td",
1617
1701
  {
1618
- title: emptyState.title,
1619
- imgSrc: Box_default,
1620
- description: emptyState.description
1702
+ colSpan: visibleColumns.length + (features.selection ? 1 : 0) + (features.actions ? columns.length : 0),
1703
+ className: "text-start pinned pinned-left tr-group",
1704
+ children: [
1705
+ /* @__PURE__ */ jsx13("strong", { children: g.displayLabel }),
1706
+ features.aggregation && Object.keys(g.aggregates).length > 0 && /* @__PURE__ */ jsx13("small", { className: "ms-3 text-secondary text-capitalize ", children: Object.entries(g.aggregates).map(([k, v]) => `${k}: ${v}`).join(" | ") })
1707
+ ]
1621
1708
  }
1622
- ) }) })
1623
- },
1624
- index
1625
- ) }, `row-${index}`)) : !loading && groupBy && groupedRows && groupedRows.length > 0 ? groupedRows.map((g, indG) => /* @__PURE__ */ jsxs10(React2.Fragment, { children: [
1626
- /* @__PURE__ */ jsx13("tr", { className: "pam-bg-light-primary", children: /* @__PURE__ */ jsxs10(
1627
- "td",
1628
- {
1629
- colSpan: visibleColumns.length + (features.selection ? 1 : 0) + (features.actions ? columns.length : 0),
1630
- className: "text-start pinned pinned-left tr-group",
1631
- children: [
1632
- /* @__PURE__ */ jsx13("strong", { children: g.displayLabel }),
1633
- features.aggregation && Object.keys(g.aggregates).length > 0 && /* @__PURE__ */ jsx13("small", { className: "ms-3 text-secondary text-capitalize ", children: Object.entries(g.aggregates).map(([k, v]) => `${k}: ${v}`).join(" | ") })
1634
- ]
1635
- }
1636
- ) }),
1637
- g.items.map((row, indG2) => renderRow(row, indG2))
1638
- ] }, g.key)) : currentRows.map((row, ind) => renderRow(row, ind)) }),
1639
- isFetching && /* @__PURE__ */ jsx13("div", { className: "pam-overlay show d-flex justify-content-center align-items-center", children: /* @__PURE__ */ jsxs10("div", { className: "p-3 bg-light rounded", children: [
1640
- /* @__PURE__ */ jsx13("div", { className: "spinner-border spinner-border-sm text-white" }),
1641
- /* @__PURE__ */ jsx13("span", { className: "ms-2 te text-white fw-2 text-light fw-bolder", children: "Loading...." })
1642
- ] }) })
1643
- ]
1644
- }
1645
- )
1709
+ ) }),
1710
+ g.items.map((row, indG2) => renderRow(row, indG2))
1711
+ ] }, g.key)) : currentRows.map((row, ind) => renderRow(row, ind)) })
1712
+ ]
1713
+ }
1714
+ ),
1715
+ isFetching && /* @__PURE__ */ jsx13("div", { className: "pam-overlay show d-flex justify-content-center align-items-center", children: /* @__PURE__ */ jsxs10("div", { className: "p-3 bg-light rounded", children: [
1716
+ /* @__PURE__ */ jsx13("div", { className: "spinner-border spinner-border-sm text-white" }),
1717
+ /* @__PURE__ */ jsx13("span", { className: "ms-2 te text-white fw-2 text-light fw-bolder", children: "Loading...." })
1718
+ ] }) })
1719
+ ]
1646
1720
  }
1647
1721
  ),
1648
1722
  features.pagination && /* @__PURE__ */ jsxs10("div", { className: "d-flex justify-content-between align-items-center mt-2", children: [
1649
1723
  /* @__PURE__ */ jsxs10("div", { className: "d-flex flex-row align-items-center gap-2", children: [
1650
- features.pageSizeSelector && /* @__PURE__ */ jsx13(
1651
- "select",
1652
- {
1653
- className: "form-select form-select-sm",
1654
- style: { width: "80px" },
1655
- value: pageSize,
1656
- onChange: (e) => setPageSize(Number(e.target.value)),
1657
- children: [20, 50, 100].map((n) => /* @__PURE__ */ jsx13("option", { value: n, children: n }, n))
1658
- }
1659
- ),
1660
- " ",
1661
- /* @__PURE__ */ jsxs10("small", { children: [
1662
- rows.length,
1663
- " Record"
1724
+ /* @__PURE__ */ jsxs10("small", { className: "text-secondary", children: [
1725
+ "Showing ",
1726
+ rows.length === 0 ? 0 : (page - 1) * pageSize + 1,
1727
+ " - ",
1728
+ (page - 1) * pageSize + rows.length,
1729
+ " of ",
1730
+ totalRecord
1731
+ ] }),
1732
+ features.pageSizeSelector && /* @__PURE__ */ jsxs10("div", { className: "d-flex align-items-center gap-2 ms-2", children: [
1733
+ /* @__PURE__ */ jsx13(
1734
+ PamDropdown,
1735
+ {
1736
+ placement: "top-start",
1737
+ trigger: /* @__PURE__ */ jsxs10("button", { className: "btn btn-sm border bg-white d-flex align-items-center gap-1", children: [
1738
+ pageSize,
1739
+ " ",
1740
+ /* @__PURE__ */ jsx13("i", { className: "bx bx-chevron-down text-muted" })
1741
+ ] }),
1742
+ items: [20, 50, 100].map((n) => ({
1743
+ key: String(n),
1744
+ label: String(n),
1745
+ onClick: () => setPageSize(n)
1746
+ }))
1747
+ }
1748
+ ),
1749
+ /* @__PURE__ */ jsx13("small", { className: "text-secondary", children: "per page" })
1664
1750
  ] })
1665
1751
  ] }),
1666
1752
  /* @__PURE__ */ jsx13("div", { children: /* @__PURE__ */ jsx13(
@@ -1722,6 +1808,27 @@ var PamGrid = ({
1722
1808
  if (col.pinned === "right")
1723
1809
  style.right = `${getRightOffset(colState, col.key)}px`;
1724
1810
  const isActive = activeCell?.row[rowKey] === row[rowKey] && activeCell?.column.key === col.key;
1811
+ const isEditing = editingCell?.rowId === row[rowKey] && editingCell?.columnKey === col.key;
1812
+ const handleEditStart = () => {
1813
+ if (features.editable && col.editable) {
1814
+ setEditingCell({
1815
+ rowId: row[rowKey],
1816
+ columnKey: String(col.key),
1817
+ value: row[col.key]
1818
+ });
1819
+ }
1820
+ };
1821
+ const handleEditSave = () => {
1822
+ if (editingCell) {
1823
+ grid.updateRow(editingCell.rowId, {
1824
+ [editingCell.columnKey]: editingCell.value
1825
+ });
1826
+ setEditingCell(null);
1827
+ }
1828
+ };
1829
+ const handleEditCancel = () => {
1830
+ setEditingCell(null);
1831
+ };
1725
1832
  return /* @__PURE__ */ jsx13(
1726
1833
  "td",
1727
1834
  {
@@ -1733,9 +1840,62 @@ var PamGrid = ({
1733
1840
  column: col
1734
1841
  });
1735
1842
  col.onCellClick && col.onCellClick(row, col);
1843
+ handleEditStart();
1736
1844
  },
1737
- className: `${col.className ?? ""} ${col.pinned ? "pinned-left px-3 bg-white pms-grid td pinned" : "px-3"} ${isActive ? "grid-cell-active" : ""} cursor-pointer`,
1738
- children: col.render ? col.render(row) : String(row[col.key]) ?? ""
1845
+ className: `${col.className ?? ""} ${col.pinned ? "pinned-left px-3 bg-white pms-grid td pinned" : "px-3"} ${isActive ? "grid-cell-active" : ""} ${isEditing ? "p-0" : ""} cursor-pointer`,
1846
+ children: isEditing ? /* @__PURE__ */ jsx13("div", { className: "w-100 h-100 d-flex align-items-center p-0", children: col.editType === "select" ? /* @__PURE__ */ jsx13("div", { className: "w-100 h-100", children: /* @__PURE__ */ jsx13(
1847
+ PamDropdown,
1848
+ {
1849
+ placement: "bottom-start",
1850
+ className: "w-100 h-100",
1851
+ trigger: /* @__PURE__ */ jsxs10("div", { className: "border-0 rounded-0 h-100 d-flex align-items-center justify-content-between bg-white px-2", children: [
1852
+ /* @__PURE__ */ jsxs10("div", { className: "d-flex align-items-center gap-2", children: [
1853
+ col.editOptions?.find(
1854
+ (o) => String(o.value) === String(editingCell.value)
1855
+ )?.icon && /* @__PURE__ */ jsx13(
1856
+ "i",
1857
+ {
1858
+ className: `${col.editOptions?.find(
1859
+ (o) => String(o.value) === String(editingCell.value)
1860
+ )?.icon} text-secondary`
1861
+ }
1862
+ ),
1863
+ /* @__PURE__ */ jsx13("span", { children: col.editOptions?.find(
1864
+ (o) => String(o.value) === String(editingCell.value)
1865
+ )?.label ?? "Select..." })
1866
+ ] }),
1867
+ /* @__PURE__ */ jsx13("i", { className: "bx bx-chevron-down text-muted" })
1868
+ ] }),
1869
+ items: col.editOptions?.map((opt) => ({
1870
+ key: String(opt.value),
1871
+ label: opt.label,
1872
+ icon: opt.icon,
1873
+ onClick: () => {
1874
+ grid.updateRow(editingCell.rowId, {
1875
+ [editingCell.columnKey]: opt.value
1876
+ });
1877
+ setEditingCell(null);
1878
+ }
1879
+ })) || []
1880
+ }
1881
+ ) }) : /* @__PURE__ */ jsx13(
1882
+ "input",
1883
+ {
1884
+ type: col.editType === "number" ? "number" : col.editType === "date" ? "date" : "text",
1885
+ className: "form-control form-control-sm border-0 rounded-0 p-0 m-0",
1886
+ autoFocus: true,
1887
+ value: editingCell.value ?? "",
1888
+ onChange: (e) => setEditingCell({
1889
+ ...editingCell,
1890
+ value: e.target.value
1891
+ }),
1892
+ onBlur: handleEditSave,
1893
+ onKeyDown: (e) => {
1894
+ if (e.key === "Enter") handleEditSave();
1895
+ if (e.key === "Escape") handleEditCancel();
1896
+ }
1897
+ }
1898
+ ) }) : col.render ? col.render(row) : String(row[col.key]) ?? ""
1739
1899
  },
1740
1900
  String(col.key)
1741
1901
  );
@@ -1899,10 +2059,12 @@ function useGridCore({
1899
2059
  rowKey = "id",
1900
2060
  initialPageSize = 20,
1901
2061
  addNewRecord,
1902
- switchFiltersConfig
2062
+ switchFiltersConfig,
2063
+ onRowUpdate
1903
2064
  }) {
1904
2065
  const [page, setPage] = useState6(1);
1905
2066
  const [pageSize, setPageSize] = useState6(initialPageSize);
2067
+ const [totalRecord, setTotalRecord] = useState6(0);
1906
2068
  const [search, setSearch] = useState6("");
1907
2069
  const [debouncedSearch, setDebouncedSearch] = useState6("");
1908
2070
  const [groupBy, setGroupBy] = useState6(null);
@@ -1928,6 +2090,14 @@ function useGridCore({
1928
2090
  const [serverRows, setServerRows] = useState6([]);
1929
2091
  const [serverTotal, setServerTotal] = useState6(0);
1930
2092
  const [serverTotalPages, setServerTotalPages] = useState6(1);
2093
+ const [editedData, setEditedData] = useState6({});
2094
+ const mergedData = useMemo3(() => {
2095
+ if (Object.keys(editedData).length === 0) return data;
2096
+ return data.map((row) => {
2097
+ const id = String(row[rowKey]);
2098
+ return editedData[id] ? { ...row, ...editedData[id] } : row;
2099
+ });
2100
+ }, [data, editedData, rowKey]);
1931
2101
  const [colState, setColState] = useState6(
1932
2102
  () => columns.map((c, i) => ({
1933
2103
  ...c,
@@ -1944,7 +2114,7 @@ function useGridCore({
1944
2114
  }, [search]);
1945
2115
  const filteredData = useMemo3(() => {
1946
2116
  if (serverMode) return [];
1947
- let filtered = [...data];
2117
+ let filtered = [...mergedData];
1948
2118
  if (debouncedSearch) {
1949
2119
  const q = debouncedSearch.toLowerCase();
1950
2120
  filtered = filtered.filter(
@@ -1953,18 +2123,87 @@ function useGridCore({
1953
2123
  )
1954
2124
  );
1955
2125
  }
2126
+ Object.values(advanceFilters).forEach((f) => {
2127
+ const { column, operation, value, from, to, type } = f;
2128
+ if (!column || !operation) return;
2129
+ filtered = filtered.filter((row) => {
2130
+ const rawValue = getNestedValue(row, column);
2131
+ if (rawValue === void 0 || rawValue === null) return false;
2132
+ const val = type === "number" ? Number(rawValue) : rawValue;
2133
+ const compareValue = type === "number" ? Number(value) : value;
2134
+ const compareFrom = type === "number" ? Number(from) : from;
2135
+ const compareTo = type === "number" ? Number(to) : to;
2136
+ const toDate = (v) => {
2137
+ const d = new Date(v);
2138
+ return isNaN(d.getTime()) ? null : d;
2139
+ };
2140
+ switch (operation) {
2141
+ // Text & Generic
2142
+ case "eq":
2143
+ return String(val).toLowerCase() === String(compareValue).toLowerCase();
2144
+ case "neq":
2145
+ return String(val).toLowerCase() !== String(compareValue).toLowerCase();
2146
+ case "contains":
2147
+ return String(val).toLowerCase().includes(String(compareValue).toLowerCase());
2148
+ case "starts":
2149
+ return String(val).toLowerCase().startsWith(String(compareValue).toLowerCase());
2150
+ case "ends":
2151
+ return String(val).toLowerCase().endsWith(String(compareValue).toLowerCase());
2152
+ // Numbers & Generic comparison
2153
+ case "gt":
2154
+ return val > compareValue;
2155
+ case "gte":
2156
+ return val >= compareValue;
2157
+ case "lt":
2158
+ return val < compareValue;
2159
+ case "lte":
2160
+ return val <= compareValue;
2161
+ case "between":
2162
+ if (type === "date") {
2163
+ const dVal = toDate(val);
2164
+ const dFrom = toDate(compareFrom);
2165
+ const dTo = toDate(compareTo);
2166
+ if (!dVal || !dFrom || !dTo) return false;
2167
+ return dVal >= dFrom && dVal <= dTo;
2168
+ }
2169
+ return val >= compareFrom && val <= compareTo;
2170
+ // Dates specific
2171
+ case "before": {
2172
+ const dVal = toDate(val);
2173
+ const dComp = toDate(compareValue);
2174
+ return dVal && dComp ? dVal < dComp : false;
2175
+ }
2176
+ case "after": {
2177
+ const dVal = toDate(val);
2178
+ const dComp = toDate(compareValue);
2179
+ return dVal && dComp ? dVal > dComp : false;
2180
+ }
2181
+ default:
2182
+ return true;
2183
+ }
2184
+ });
2185
+ });
2186
+ Object.entries(facetFilters).forEach(([column, items]) => {
2187
+ if (!items || items.length === 0) return;
2188
+ const allowedIds = new Set(items.map((i) => String(i.id)));
2189
+ filtered = filtered.filter((row) => {
2190
+ const val = getNestedValue(row, column);
2191
+ return allowedIds.has(String(val ?? ""));
2192
+ });
2193
+ });
1956
2194
  if (sortBy.key) {
1957
2195
  const dir = sortBy.dir === "asc" ? 1 : -1;
1958
- filtered.sort(
1959
- (a, b) => String(a?.[sortBy.key] ?? "").localeCompare(
1960
- String(b?.[sortBy.key] ?? ""),
1961
- void 0,
1962
- { numeric: true, sensitivity: "base" }
1963
- ) * dir
1964
- );
2196
+ filtered.sort((a, b) => {
2197
+ const vA = a?.[sortBy.key] ?? "";
2198
+ const vB = b?.[sortBy.key] ?? "";
2199
+ return String(vA).localeCompare(String(vB), void 0, {
2200
+ numeric: true,
2201
+ sensitivity: "base"
2202
+ }) * dir;
2203
+ });
1965
2204
  }
1966
2205
  return filtered;
1967
- }, [data, debouncedSearch, sortBy, serverMode]);
2206
+ }, [mergedData, debouncedSearch, sortBy, serverMode, advanceFilters, facetFilters]);
1968
2207
  const pagedClientRows = useMemo3(() => {
1969
2208
  if (serverMode) return [];
1970
2209
  const start = (page - 1) * pageSize;
@@ -2119,6 +2358,16 @@ function useGridCore({
2119
2358
  },
2120
2359
  []
2121
2360
  );
2361
+ const updateRow = useCallback((id, patch) => {
2362
+ setEditedData((prev) => ({
2363
+ ...prev,
2364
+ [String(id)]: { ...prev[String(id)] || {}, ...patch }
2365
+ }));
2366
+ if (onRowUpdate) onRowUpdate(id, patch);
2367
+ }, [onRowUpdate]);
2368
+ const clearEdits = useCallback(() => {
2369
+ setEditedData({});
2370
+ }, []);
2122
2371
  const toggleExpand = useCallback((id) => {
2123
2372
  setExpanded((prev) => {
2124
2373
  const s = new Set(prev);
@@ -2134,6 +2383,8 @@ function useGridCore({
2134
2383
  setPageSize,
2135
2384
  totalRows,
2136
2385
  totalPages,
2386
+ totalRecord,
2387
+ setTotalRecord,
2137
2388
  // search
2138
2389
  search,
2139
2390
  setSearch,
@@ -2188,7 +2439,9 @@ function useGridCore({
2188
2439
  loadFacets,
2189
2440
  facetLoading,
2190
2441
  removeFacetFilter,
2191
- clearFacetFilters
2442
+ clearFacetFilters,
2443
+ updateRow,
2444
+ clearEdits
2192
2445
  };
2193
2446
  }
2194
2447
  export {