impact-nova 0.1.6 → 0.1.9

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Impact Analytics
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -18,6 +18,8 @@ export interface HeaderSearchInputProps {
18
18
  onSelectSearchChange?: (value: string) => void;
19
19
  onSelectOpen?: () => void;
20
20
  isLoadingSelect?: boolean;
21
+ enableSpaceSplitting?: boolean;
22
+ enableBooleanParsing?: boolean;
21
23
  }
22
24
  /**
23
25
  * HeaderSearchInput - A single instance input for column filtering.
@@ -25,5 +27,5 @@ export interface HeaderSearchInputProps {
25
27
  * ZERO HOOKS SYNC: This component reads its state directly from AG Grid on mount.
26
28
  * It does not use useEffect to sync with external state, as the Grid API is the source of truth.
27
29
  */
28
- export declare const HeaderSearchInput: ({ column, api, onClose, handleInlineSearch, handleClearSearchInline, onAdvanceSearchClick, toggleAdvanceSearch, advanceSearchEnabled, selectOptions, isMultiSelect, onSelectScrollToBottom, onSelectSearchChange, onSelectOpen, isLoadingSelect, }: HeaderSearchInputProps) => import("react/jsx-runtime").JSX.Element;
30
+ export declare const HeaderSearchInput: ({ column, api, onClose, handleInlineSearch, handleClearSearchInline, onAdvanceSearchClick, toggleAdvanceSearch, advanceSearchEnabled, selectOptions, isMultiSelect, onSelectScrollToBottom, onSelectSearchChange, onSelectOpen, isLoadingSelect, enableSpaceSplitting, enableBooleanParsing, }: HeaderSearchInputProps) => import("react/jsx-runtime").JSX.Element;
29
31
  export default HeaderSearchInput;
@@ -1,16 +1,16 @@
1
1
  import { jsxs as y, jsx as i } from "react/jsx-runtime";
2
- import { useRef as Ce, useState as I, useEffect as Te, useCallback as be } from "react";
3
- import { Filter as De } from "lucide-react";
4
- import { cn as Ne } from "../../../../lib/utils.js";
2
+ import { useRef as be, useState as I, useEffect as De, useCallback as Ne } from "react";
3
+ import { Filter as Ae } from "lucide-react";
4
+ import { cn as Se } from "../../../../lib/utils.js";
5
5
  import { DatePicker as oe } from "../../date-picker/date-picker.js";
6
6
  import { Input as ie } from "../../input.js";
7
7
  import se from "../../select/select.js";
8
- import { Popover as Ae, PopoverTrigger as Se, PopoverContent as we, PopoverHeader as Ie, PopoverTitle as Pe, PopoverBody as qe } from "../../popover.js";
8
+ import { Popover as we, PopoverTrigger as Ie, PopoverContent as Pe, PopoverHeader as qe, PopoverTitle as ze, PopoverBody as Be } from "../../popover.js";
9
9
  import { Cross as ae } from "../../../../icons/index.js";
10
- import { useGridHeader as ze } from "./context/grid-header-context.js";
11
- import { getMultiFilterIndices as C, getDisplayStringFromFilterModel as P, parseInputPattern as Be } from "./utils/filter-utils.js";
10
+ import { useGridHeader as Ee } from "./context/grid-header-context.js";
11
+ import { getMultiFilterIndices as C, getDisplayStringFromFilterModel as P, parseInputPattern as He } from "./utils/filter-utils.js";
12
12
  import { deserializeDate as M, serializeDate as ce } from "./utils/date-utils.js";
13
- const Ee = {
13
+ const ke = {
14
14
  contains: "contains",
15
15
  notContains: "notContains",
16
16
  equals: "equals",
@@ -24,7 +24,7 @@ const Ee = {
24
24
  inRange: "inRange",
25
25
  empty: "blank",
26
26
  notEmpty: "notBlank"
27
- }, Ue = ({
27
+ }, Ye = ({
28
28
  column: D,
29
29
  api: d,
30
30
  onClose: W,
@@ -38,9 +38,11 @@ const Ee = {
38
38
  onSelectScrollToBottom: fe,
39
39
  onSelectSearchChange: ue,
40
40
  onSelectOpen: V,
41
- isLoadingSelect: J
41
+ isLoadingSelect: J,
42
+ enableSpaceSplitting: he = !1,
43
+ enableBooleanParsing: me = !1
42
44
  }) => {
43
- const c = D.getColDef(), o = D.getColId(), z = c?.filter || "agTextColumnFilter", p = z === "agDateColumnFilter", B = z === "agSetColumnFilter" || q && q.length > 0 || c?.cellDataType === "boolean", K = ze(), E = Ce(null), [H, k] = I(() => {
45
+ const c = D.getColDef(), o = D.getColId(), z = c?.filter || "agTextColumnFilter", p = z === "agDateColumnFilter", B = z === "agSetColumnFilter" || q && q.length > 0 || c?.cellDataType === "boolean", K = Ee(), E = be(null), [H, k] = I(() => {
44
46
  const t = d.getFilterModel()[o];
45
47
  if (!t) return "";
46
48
  if (t.filterType === "multi" && t.filterModels) {
@@ -52,7 +54,7 @@ const Ee = {
52
54
  return "";
53
55
  }
54
56
  return p ? "" : P(o, t);
55
- }), [he, u] = I(!1), [Q, R] = I(() => {
57
+ }), [pe, u] = I(!1), [Q, R] = I(() => {
56
58
  const t = d.getFilterModel()[o];
57
59
  if (t) {
58
60
  if (t.filterType === "multi" && t.filterModels) {
@@ -72,7 +74,7 @@ const Ee = {
72
74
  }
73
75
  return null;
74
76
  });
75
- Te(() => {
77
+ De(() => {
76
78
  const e = () => {
77
79
  const l = d.getFilterModel()[o];
78
80
  let r = "";
@@ -84,7 +86,7 @@ const Ee = {
84
86
  r = f ? P(o, f) : "";
85
87
  }
86
88
  } else p || (r = P(o, l));
87
- he || k((n) => n !== r ? r : n);
89
+ pe || k((n) => n !== r ? r : n);
88
90
  let m = null;
89
91
  if (l)
90
92
  if (l.filterType === "multi" && l.filterModels) {
@@ -102,14 +104,14 @@ const Ee = {
102
104
  }, [d, o, p]);
103
105
  const U = (e, t) => {
104
106
  const r = { ...d.getFilterModel() }, m = (n, a) => {
105
- const f = Be(n);
107
+ const f = He(n, he, me);
106
108
  if (console.log("[HeaderSearchInput] Pattern Debug:", {
107
109
  input: n,
108
110
  filterType: a,
109
111
  parsed: f
110
112
  }), f.conditions.length === 0) return null;
111
113
  const b = (s) => {
112
- let F = Ee[s.operator] || "contains";
114
+ let F = ke[s.operator] || "contains";
113
115
  if (a === "number") {
114
116
  const ne = parseFloat(s.value);
115
117
  return ["contains", "notContains", "startsWith", "endsWith"].includes(F) && (F = F === "notContains" ? "notEqual" : "equals"), s.operator === "inRange" ? {
@@ -181,11 +183,11 @@ const Ee = {
181
183
  k(t), O(t);
182
184
  }, Y = (e) => {
183
185
  R(e), O(e);
184
- }, me = () => {
186
+ }, ge = () => {
185
187
  k(""), R(null), O(""), G && G();
186
188
  }, A = (e) => {
187
189
  U(e, "set");
188
- }, S = q || (c?.cellDataType === "boolean" ? [{ label: "True", value: "true" }, { label: "False", value: "false" }] : []), Z = be(() => {
190
+ }, S = q || (c?.cellDataType === "boolean" ? [{ label: "True", value: "true" }, { label: "False", value: "false" }] : []), Z = Ne(() => {
189
191
  const e = d.getFilterModel()[o];
190
192
  if (!e) return [];
191
193
  if ("filterType" in e && e.filterType === "multi" && e.filterModels) {
@@ -211,9 +213,9 @@ const Ee = {
211
213
  return;
212
214
  }
213
215
  N(t);
214
- }, pe = () => {
216
+ }, xe = () => {
215
217
  A([]), N([]);
216
- }, ge = (e) => {
218
+ }, ye = (e) => {
217
219
  if (v) {
218
220
  if (e !== void 0) {
219
221
  let t = [];
@@ -222,14 +224,14 @@ const Ee = {
222
224
  }
223
225
  w !== null && (A(w), N(null));
224
226
  }
225
- }, xe = () => {
227
+ }, Fe = () => {
226
228
  N(Z()), V && V();
227
- }, ye = () => de ? /* @__PURE__ */ i("svg", { className: "cursor-pointer text-[#7a8294] hover:text-[#3649C6] shrink-0", fill: "currentColor", focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", width: "18", height: "18", onClick: (e) => {
229
+ }, Me = () => de ? /* @__PURE__ */ i("svg", { className: "cursor-pointer text-[#7a8294] hover:text-[#3649C6] shrink-0", fill: "currentColor", focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", width: "18", height: "18", onClick: (e) => {
228
230
  e.stopPropagation(), E.current && E.current.blur(), L ? L(D) : _ ? _(o) : K && K.openAdvancedFilter(o);
229
- }, children: /* @__PURE__ */ i("path", { d: "M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z" }) }) : null, Fe = () => /* @__PURE__ */ i("button", { onClick: W, className: "cursor-pointer shrink-0 text-[#4259ee] hover:text-[#0f1c76]", children: /* @__PURE__ */ i(ae, { size: 12 }) }), T = c.filter === "agMultiColumnFilter", g = C(c);
231
+ }, children: /* @__PURE__ */ i("path", { d: "M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z" }) }) : null, ve = () => /* @__PURE__ */ i("button", { onClick: W, className: "cursor-pointer shrink-0 text-[#4259ee] hover:text-[#0f1c76]", children: /* @__PURE__ */ i(ae, { size: 12 }) }), T = c.filter === "agMultiColumnFilter", g = C(c);
230
232
  let x = "text";
231
233
  T ? x = g.set !== -1 ? "set" : g.date !== -1 ? "date" : "text" : B ? x = "set" : p && (x = "date");
232
- const Me = T ? g.text !== -1 || g.number !== -1 : !p && !B, te = T ? g.set !== -1 : B, le = T ? g.date !== -1 : p, ve = d.getFilterModel()[o], re = T && ve?.filterModels?.some((e, t) => {
234
+ const Ce = T ? g.text !== -1 || g.number !== -1 : !p && !B, te = T ? g.set !== -1 : B, le = T ? g.date !== -1 : p, Te = d.getFilterModel()[o], re = T && Te?.filterModels?.some((e, t) => {
233
235
  const l = t === g.text || t === g.number ? "text" : t === g.set ? "set" : "date";
234
236
  return e !== null && l !== x;
235
237
  });
@@ -247,11 +249,11 @@ const Ee = {
247
249
  menuWidth: "200px",
248
250
  menuPortalTarget: document.body,
249
251
  autoFocus: !0,
250
- onMenuOpen: xe,
251
- onMenuClose: ge,
252
+ onMenuOpen: Fe,
253
+ onMenuClose: ye,
252
254
  onMenuScrollToBottom: fe,
253
255
  onInputChange: ue,
254
- onClearAll: pe,
256
+ onClearAll: xe,
255
257
  isLoading: J,
256
258
  onFocus: () => u(!0),
257
259
  onBlur: () => u(!1)
@@ -282,20 +284,20 @@ const Ee = {
282
284
  onFocus: () => u(!0),
283
285
  onBlur: () => u(!1),
284
286
  suffix: H && /* @__PURE__ */ i("button", { onClick: (e) => {
285
- e.stopPropagation(), me();
287
+ e.stopPropagation(), ge();
286
288
  }, className: "cursor-pointer text-[#7a8294] hover:text-[#3649C6]", children: /* @__PURE__ */ i(ae, { size: 10 }) })
287
289
  }
288
290
  ),
289
291
  /* @__PURE__ */ y("div", { className: "flex items-center gap-1.5 shrink-0", children: [
290
- T && /* @__PURE__ */ y(Ae, { children: [
291
- /* @__PURE__ */ i(Se, { asChild: !0, children: /* @__PURE__ */ y("div", { className: "relative group p-1 hover:bg-[#dbe0fb] rounded-md transition-colors cursor-pointer", children: [
292
- /* @__PURE__ */ i(De, { size: 16, className: Ne("text-[#60697D] group-hover:text-[#3649C6]", re && "text-[#3649C6]") }),
292
+ T && /* @__PURE__ */ y(we, { children: [
293
+ /* @__PURE__ */ i(Ie, { asChild: !0, children: /* @__PURE__ */ y("div", { className: "relative group p-1 hover:bg-[#dbe0fb] rounded-md transition-colors cursor-pointer", children: [
294
+ /* @__PURE__ */ i(Ae, { size: 16, className: Se("text-[#60697D] group-hover:text-[#3649C6]", re && "text-[#3649C6]") }),
293
295
  re && /* @__PURE__ */ i("span", { className: "absolute top-0.5 right-0.5 w-2 h-2 rounded-full bg-[#4259ee] border border-white shadow-sm" })
294
296
  ] }) }),
295
- /* @__PURE__ */ y(we, { align: "end", className: "w-[300px]", children: [
296
- /* @__PURE__ */ i(Ie, { children: /* @__PURE__ */ i(Pe, { children: "Active Filters" }) }),
297
- /* @__PURE__ */ y(qe, { className: "flex flex-col gap-4", children: [
298
- x !== "text" && Me && /* @__PURE__ */ y("div", { className: "flex flex-col gap-1.5", children: [
297
+ /* @__PURE__ */ y(Pe, { align: "end", className: "w-[300px]", children: [
298
+ /* @__PURE__ */ i(qe, { children: /* @__PURE__ */ i(ze, { children: "Active Filters" }) }),
299
+ /* @__PURE__ */ y(Be, { className: "flex flex-col gap-4", children: [
300
+ x !== "text" && Ce && /* @__PURE__ */ y("div", { className: "flex flex-col gap-1.5", children: [
299
301
  /* @__PURE__ */ i("span", { className: "text-xs font-semibold text-[#60697D]", children: "Text Search" }),
300
302
  /* @__PURE__ */ i(
301
303
  ie,
@@ -342,11 +344,11 @@ const Ee = {
342
344
  ] })
343
345
  ] })
344
346
  ] }),
345
- ye(),
346
- Fe()
347
+ Me(),
348
+ ve()
347
349
  ] })
348
350
  ] });
349
351
  };
350
352
  export {
351
- Ue as HeaderSearchInput
353
+ Ye as HeaderSearchInput
352
354
  };
@@ -42,9 +42,12 @@ export declare function getMultiFilterIndices(colDef: ColDef | undefined): {
42
42
  * - Multiple patterns with AND: `fo+ au` or `fo +au` (plus separated)
43
43
  * - Match all: `*` alone
44
44
  *
45
+ * @param input - The search input string
46
+ * @param enableSpaceSplitting - If true, spaces split terms into multiple OR conditions. If false (default), preserves phrases like "Pratik Kumar"
47
+ * @param enableBooleanParsing - If true, boolean keywords parsed globally (e.g., "yes" → true). If false (default), only with '=' prefix (e.g., "=yes" → true)
45
48
  * @returns ParsedInput with conditions array and logic
46
49
  */
47
- export declare function parseInputPattern(input: string): ParsedInput;
50
+ export declare function parseInputPattern(input: string, enableSpaceSplitting?: boolean, enableBooleanParsing?: boolean): ParsedInput;
48
51
  /**
49
52
  * Convert ParsedInput to AdvancedFilterRule array for a specific column.
50
53
  * Used to sync inline search input with the advanced filter modal.
@@ -1,5 +1,5 @@
1
1
  import { getTodayStr as R, getYesterdayStr as b, getMonthRange as S, getYearRange as W } from "./date-utils.js";
2
- const E = {
2
+ const T = {
3
3
  yes: !0,
4
4
  true: !0,
5
5
  "[x]": !0,
@@ -11,7 +11,7 @@ const E = {
11
11
  "[ ]": !1,
12
12
  inactive: !1,
13
13
  disabled: !1
14
- }, $ = {
14
+ }, C = {
15
15
  jan: 1,
16
16
  january: 1,
17
17
  feb: 2,
@@ -36,20 +36,20 @@ const E = {
36
36
  dec: 12,
37
37
  december: 12
38
38
  };
39
- function I(n) {
40
- const t = n?.filterParams?.filters || [];
39
+ function w(n) {
40
+ const e = n?.filterParams?.filters || [];
41
41
  return {
42
- text: t.findIndex((r) => (typeof r == "string" ? r : r.filter) === "agTextColumnFilter"),
43
- number: t.findIndex((r) => (typeof r == "string" ? r : r.filter) === "agNumberColumnFilter"),
44
- set: t.findIndex((r) => (typeof r == "string" ? r : r.filter) === "agSetColumnFilter"),
45
- date: t.findIndex((r) => (typeof r == "string" ? r : r.filter) === "agDateColumnFilter")
42
+ text: e.findIndex((t) => (typeof t == "string" ? t : t.filter) === "agTextColumnFilter"),
43
+ number: e.findIndex((t) => (typeof t == "string" ? t : t.filter) === "agNumberColumnFilter"),
44
+ set: e.findIndex((t) => (typeof t == "string" ? t : t.filter) === "agSetColumnFilter"),
45
+ date: e.findIndex((t) => (typeof t == "string" ? t : t.filter) === "agDateColumnFilter")
46
46
  };
47
47
  }
48
48
  function p(n) {
49
- const t = n.toLowerCase().trim();
50
- return t === "today" ? R() : t === "yesterday" ? b() : n;
49
+ const e = n.toLowerCase().trim();
50
+ return e === "today" ? R() : e === "yesterday" ? b() : n;
51
51
  }
52
- function T(n) {
52
+ function v(n, e = !1) {
53
53
  const t = n.trim();
54
54
  if (!t)
55
55
  return { operator: "contains", value: "" };
@@ -59,8 +59,10 @@ function T(n) {
59
59
  return { operator: "notEqual", value: p(t.slice(2)) };
60
60
  if (t.startsWith("=="))
61
61
  return { operator: "equals", value: p(t.slice(2)) };
62
- if (t.startsWith("="))
63
- return { operator: "equals", value: p(t.slice(1)) };
62
+ if (t.startsWith("=")) {
63
+ const r = t.slice(1).trim(), l = r.toLowerCase();
64
+ return T[l] !== void 0 ? { operator: "equals", value: String(T[l]) } : { operator: "equals", value: p(r) };
65
+ }
64
66
  if (t.startsWith("!"))
65
67
  return { operator: "notContains", value: p(t.slice(1)) };
66
68
  if (t.startsWith(">="))
@@ -75,97 +77,99 @@ function T(n) {
75
77
  return { operator: "endsWith", value: t.slice(1).trim() };
76
78
  if (t.endsWith("*") && t.length > 1 && !t.startsWith("*"))
77
79
  return { operator: "startsWith", value: t.slice(0, -1).trim() };
78
- const r = t.match(/^(\d+(?:\.\d+)?)\s*-\s*(\d+(?:\.\d+)?)$/);
79
- if (r)
80
- return { operator: "inRange", value: r[1], valueTo: r[2] };
81
- const o = t.match(/^(\d{4}-\d{2}-\d{2})\s*-\s*(\d{4}-\d{2}-\d{2})$/);
82
- if (o)
83
- return { operator: "inRange", value: o[1], valueTo: o[2] };
84
- const a = t.toLowerCase();
85
- if (E[a] !== void 0)
86
- return { operator: "equals", value: String(E[a]) };
87
- if (a === "today") return { operator: "equals", value: R() };
88
- if (a === "yesterday") return { operator: "equals", value: b() };
80
+ const a = t.match(/^(\d+(?:\.\d+)?)\s*-\s*(\d+(?:\.\d+)?)$/);
81
+ if (a)
82
+ return { operator: "inRange", value: a[1], valueTo: a[2] };
83
+ const i = t.match(/^(\d{4}-\d{2}-\d{2})\s*-\s*(\d{4}-\d{2}-\d{2})$/);
84
+ if (i)
85
+ return { operator: "inRange", value: i[1], valueTo: i[2] };
86
+ const f = t.toLowerCase();
87
+ if (e && T[f] !== void 0)
88
+ return { operator: "equals", value: String(T[f]) };
89
+ if (f === "today") return { operator: "equals", value: R() };
90
+ if (f === "yesterday") return { operator: "equals", value: b() };
89
91
  if (/^\d{4}$/.test(t)) {
90
- const l = W(Number(t));
91
- return { operator: "inRange", value: l.from, valueTo: l.to };
92
+ const r = W(Number(t));
93
+ return { operator: "inRange", value: r.from, valueTo: r.to };
92
94
  }
93
- const f = t.match(/^([a-zA-Z]+)\s*(\d{4})$/);
94
- if (f) {
95
- const l = $[f[1].toLowerCase()];
96
- if (l) {
97
- const e = S(l, Number(f[2]));
98
- return { operator: "inRange", value: e.from, valueTo: e.to };
95
+ const u = t.match(/^([a-zA-Z]+)\s*(\d{4})$/);
96
+ if (u) {
97
+ const r = C[u[1].toLowerCase()];
98
+ if (r) {
99
+ const l = S(r, Number(u[2]));
100
+ return { operator: "inRange", value: l.from, valueTo: l.to };
99
101
  }
100
102
  }
101
103
  return { operator: "contains", value: t };
102
104
  }
103
- function j(n) {
105
+ function I(n, e = !1, t = !1) {
104
106
  if (!n || n.trim() === "")
105
107
  return { conditions: [], logic: "OR" };
106
- const t = n.trim();
107
- if (t === "*")
108
+ const a = n.trim();
109
+ if (a === "*")
108
110
  return { conditions: [], logic: "OR", matchAll: !0 };
109
- const r = t.includes("+") || t.includes("&"), o = t.includes(",") || t.includes(";");
110
- if (r)
111
- return { conditions: t.split(/\s*[+&]\s*/).filter((s) => !!s.trim()).map((s) => T(s)).filter((s) => !!s.value), logic: "AND" };
112
- if (o)
113
- return { conditions: t.split(/\s*[,;]\s*/).filter((s) => !!s.trim()).map((s) => T(s)).filter((s) => !!s.value), logic: "OR" };
114
- const a = t.split(/\s+/).filter((l) => !!l.trim());
115
- if (a.length > 1) {
116
- const l = a.map((e) => T(e)).filter((e) => !!e.value);
117
- if (l.length > 1)
118
- return { conditions: l, logic: "OR" };
111
+ const i = a.includes("+") || a.includes("&"), f = a.includes(",") || a.includes(";");
112
+ if (i)
113
+ return { conditions: a.split(/\s*[+&]\s*/).filter((o) => !!o.trim()).map((o) => v(o, t)).filter((o) => !!o.value), logic: "AND" };
114
+ if (f)
115
+ return { conditions: a.split(/\s*[,;]\s*/).filter((o) => !!o.trim()).map((o) => v(o, t)).filter((o) => !!o.value), logic: "OR" };
116
+ if (e) {
117
+ const r = a.split(/\s+/).filter((l) => !!l.trim());
118
+ if (r.length > 1) {
119
+ const l = r.map((o) => v(o, t)).filter((o) => !!o.value);
120
+ if (l.length > 1)
121
+ return { conditions: l, logic: "OR" };
122
+ }
119
123
  }
120
- const f = T(t);
121
- return !f.value && f.operator === "contains" ? { conditions: [], logic: "OR" } : { conditions: [f], logic: "OR" };
124
+ const u = v(a, t);
125
+ return !u.value && u.operator === "contains" ? { conditions: [], logic: "OR" } : { conditions: [u], logic: "OR" };
122
126
  }
123
127
  function m(n) {
124
128
  if (!n) return "";
125
129
  if (Array.isArray(n))
126
- return n.map((t) => m(t)).join(", ");
130
+ return n.map((e) => m(e)).join(", ");
127
131
  if (/^\d{4}-\d{2}-\d{2}/.test(n))
128
132
  try {
129
- const t = new Date(n);
130
- if (!isNaN(t.getTime())) {
131
- const r = String(t.getMonth() + 1).padStart(2, "0"), o = String(t.getDate()).padStart(2, "0");
132
- return `${r}/${o}`;
133
+ const e = new Date(n);
134
+ if (!isNaN(e.getTime())) {
135
+ const t = String(e.getMonth() + 1).padStart(2, "0"), a = String(e.getDate()).padStart(2, "0");
136
+ return `${t}/${a}`;
133
137
  }
134
138
  } catch {
135
139
  }
136
140
  return n;
137
141
  }
138
- function C(n) {
139
- const t = m(n.value), r = m(n.valueTo || "");
142
+ function $(n) {
143
+ const e = m(n.value), t = m(n.valueTo || "");
140
144
  switch (n.operator) {
141
145
  case "contains":
142
- return t;
146
+ return e;
143
147
  case "notContains":
144
- return `!${t}`;
148
+ return `!${e}`;
145
149
  case "equals":
146
- return n.columnType === "number" || n.columnType === "date" || n.columnType === "select" ? t : `=${t}`;
150
+ return n.columnType === "number" || n.columnType === "date" || n.columnType === "select" ? e : `=${e}`;
147
151
  case "notEqual":
148
- return `!=${t}`;
152
+ return `!=${e}`;
149
153
  case "startsWith":
150
- return `${t}*`;
154
+ return `${e}*`;
151
155
  case "endsWith":
152
- return `*${t}`;
156
+ return `*${e}`;
153
157
  case "greaterThan":
154
- return `>${t}`;
158
+ return `>${e}`;
155
159
  case "greaterThanOrEqual":
156
- return `≥${t}`;
160
+ return `≥${e}`;
157
161
  case "lessThan":
158
- return `<${t}`;
162
+ return `<${e}`;
159
163
  case "lessThanOrEqual":
160
- return `≤${t}`;
164
+ return `≤${e}`;
161
165
  case "inRange":
162
- return `${t}–${r}`;
166
+ return `${e}–${t}`;
163
167
  case "empty":
164
168
  return "∅";
165
169
  case "notEmpty":
166
170
  return "≠∅";
167
171
  default:
168
- return t;
172
+ return e;
169
173
  }
170
174
  }
171
175
  const M = {
@@ -190,42 +194,42 @@ const M = {
190
194
  lt: "lessThan",
191
195
  lte: "lessThanOrEqual"
192
196
  };
193
- function A(n, t) {
194
- if (!t) return "";
195
- if ("filterType" in t && t.filterType === "multi" && t.filterModels)
196
- return t.filterModels.map((o) => A(n, o)).filter((o) => !!o).join(", ");
197
- if ("filterType" in t && t.filterType === "set" && t.values) {
198
- const a = t.values || [];
199
- return a.length === 0 ? "" : a.length === 1 ? m(a[0]) : `${m(a[0])} (+${a.length - 1})`;
197
+ function A(n, e) {
198
+ if (!e) return "";
199
+ if ("filterType" in e && e.filterType === "multi" && e.filterModels)
200
+ return e.filterModels.map((a) => A(n, a)).filter((a) => !!a).join(", ");
201
+ if ("filterType" in e && e.filterType === "set" && e.values) {
202
+ const i = e.values || [];
203
+ return i.length === 0 ? "" : i.length === 1 ? m(i[0]) : `${m(i[0])} (+${i.length - 1})`;
200
204
  }
201
- if ("conditions" in t && t.conditions && t.operator) {
202
- const o = t.operator === "AND" ? " + " : ", ";
203
- return t.conditions.map((a) => A(n, a)).filter((a) => !!a).join(o);
205
+ if ("conditions" in e && e.conditions && e.operator) {
206
+ const a = e.operator === "AND" ? " + " : ", ";
207
+ return e.conditions.map((i) => A(n, i)).filter((i) => !!i).join(a);
204
208
  }
205
- const r = t;
206
- if ("type" in r && r.type) {
207
- const o = r.type, a = M[o] || o, f = r.filter !== void 0 ? String(r.filter) : r.dateFrom !== void 0 ? String(r.dateFrom) : "", l = r.filterTo !== void 0 ? String(r.filterTo) : r.dateTo !== void 0 ? String(r.dateTo) : void 0;
208
- return C({
209
- operator: a,
209
+ const t = e;
210
+ if ("type" in t && t.type) {
211
+ const a = t.type, i = M[a] || a, f = t.filter !== void 0 ? String(t.filter) : t.dateFrom !== void 0 ? String(t.dateFrom) : "", u = t.filterTo !== void 0 ? String(t.filterTo) : t.dateTo !== void 0 ? String(t.dateTo) : void 0;
212
+ return $({
213
+ operator: i,
210
214
  value: f,
211
- valueTo: l,
215
+ valueTo: u,
212
216
  // Optimization: determine type roughly for '=' vs contains logic
213
- columnType: r.filterType === "number" ? "number" : r.filterType === "date" ? "date" : "text"
217
+ columnType: t.filterType === "number" ? "number" : t.filterType === "date" ? "date" : "text"
214
218
  });
215
219
  }
216
220
  return "";
217
221
  }
218
- function q() {
222
+ function E() {
219
223
  return Math.random().toString(36).substring(2, 11);
220
224
  }
221
- function D(n = "", t) {
222
- const r = t === "number" || t === "date" || t === "select" ? "equals" : "contains";
225
+ function j(n = "", e) {
226
+ const t = e === "number" || e === "date" || e === "select" ? "equals" : "contains";
223
227
  return {
224
- id: q(),
228
+ id: E(),
225
229
  columnId: n,
226
- operator: r,
230
+ operator: t,
227
231
  value: "",
228
- columnType: t
232
+ columnType: e
229
233
  // Store for proper filterType in AG Grid conversion
230
234
  };
231
235
  }
@@ -261,174 +265,174 @@ function h(n) {
261
265
  return "contains";
262
266
  }
263
267
  }
264
- function O(n, t, r) {
265
- return r === "number" ? "number" : r === "date" ? "date" : r === "select" || r === "set" || Array.isArray(t) ? n === "notEqual" || n === "notContains" ? "text" : "set" : typeof t == "string" && /^\d{4}-\d{2}-\d{2}/.test(t) ? "date" : ["greaterThan", "greaterThanOrEqual", "lessThan", "lessThanOrEqual", "inRange"].includes(n) && t && !x(t) && !isNaN(Number(t)) || typeof t == "string" && t && /^-?\d+(\.\d+)?$/.test(t.trim()) ? "number" : "text";
268
+ function O(n, e, t) {
269
+ return t === "number" ? "number" : t === "date" ? "date" : t === "select" || t === "set" || Array.isArray(e) ? n === "notEqual" || n === "notContains" ? "text" : "set" : typeof e == "string" && /^\d{4}-\d{2}-\d{2}/.test(e) ? "date" : ["greaterThan", "greaterThanOrEqual", "lessThan", "lessThanOrEqual", "inRange"].includes(n) && e && !x(e) && !isNaN(Number(e)) || typeof e == "string" && e && /^-?\d+(\.\d+)?$/.test(e.trim()) ? "number" : "text";
266
270
  }
267
271
  function x(n) {
268
272
  return Array.isArray(n);
269
273
  }
270
- function w(n) {
274
+ function D(n) {
271
275
  if (console.log("[AdvancedFilter] convertToAgGridFilterModel input:", n), !n || !n.rules || n.rules.length === 0)
272
276
  return console.log("[AdvancedFilter] No model or empty rules, returning empty"), {};
273
- const t = {}, r = {}, o = (a) => {
274
- "logic" in a ? (a.conditions || []).forEach(o) : a.columnId && (a.value || a.operator === "empty" || a.operator === "notEmpty") && (r[a.columnId] || (r[a.columnId] = []), r[a.columnId].push(a));
277
+ const e = {}, t = {}, a = (i) => {
278
+ "logic" in i ? (i.conditions || []).forEach(a) : i.columnId && (i.value || i.operator === "empty" || i.operator === "notEmpty") && (t[i.columnId] || (t[i.columnId] = []), t[i.columnId].push(i));
275
279
  };
276
- n.rules.forEach(o), console.log("[AdvancedFilter] Rules by column:", r);
277
- for (const [a, f] of Object.entries(r)) {
280
+ n.rules.forEach(a), console.log("[AdvancedFilter] Rules by column:", t);
281
+ for (const [i, f] of Object.entries(t)) {
278
282
  if (f.length === 0) continue;
279
283
  if (f[0].columnType === "multi") {
280
- const e = (i) => i.operator !== "equals" ? !1 : !!(Array.isArray(i.value) || ["select", "multi"].includes(i.columnType)), s = f.filter(e), c = f.filter((i) => !e(i)), u = [null, null];
281
- if (c.length > 0) {
282
- const i = v(c, "text", n.logic);
283
- i && (u[0] = i);
284
+ const r = (s) => s.operator !== "equals" ? !1 : !!(Array.isArray(s.value) || ["select", "multi"].includes(s.columnType)), l = f.filter(r), o = f.filter((s) => !r(s)), c = [null, null];
285
+ if (o.length > 0) {
286
+ const s = q(o, "text", n.logic);
287
+ s && (c[0] = s);
284
288
  }
285
- if (s.length > 0) {
286
- const i = v(s, "set", n.logic);
287
- i && (u[1] = i);
289
+ if (l.length > 0) {
290
+ const s = q(l, "set", n.logic);
291
+ s && (c[1] = s);
288
292
  }
289
- (u[0] || u[1]) && (t[a] = {
293
+ (c[0] || c[1]) && (e[i] = {
290
294
  filterType: "multi",
291
- filterModels: u
295
+ filterModels: c
292
296
  });
293
297
  } else {
294
- const e = v(f, f[0].columnType, n.logic);
295
- e && (t[a] = e);
298
+ const r = q(f, f[0].columnType, n.logic);
299
+ r && (e[i] = r);
296
300
  }
297
301
  }
298
- return console.log("[AdvancedFilter] Converted AG Grid filter model:", t), t;
302
+ return console.log("[AdvancedFilter] Converted AG Grid filter model:", e), e;
299
303
  }
300
- function v(n, t, r = "OR") {
304
+ function q(n, e, t = "OR") {
301
305
  if (n.length === 0) return null;
302
- const o = [];
303
- n.forEach((e) => {
304
- Array.isArray(e.value) && (e.operator === "notEqual" || e.operator === "notContains") ? e.value.forEach((s) => {
305
- o.push({
306
- ...e,
307
- value: s,
308
- id: q()
306
+ const a = [];
307
+ n.forEach((r) => {
308
+ Array.isArray(r.value) && (r.operator === "notEqual" || r.operator === "notContains") ? r.value.forEach((l) => {
309
+ a.push({
310
+ ...r,
311
+ value: l,
312
+ id: E()
309
313
  // Unique ID for each condition
310
314
  });
311
- }) : o.push(e);
315
+ }) : a.push(r);
312
316
  });
313
- const a = o.some((e) => e.operator === "notEqual" || e.operator === "notContains");
314
- if (t === "set" || o.some((e) => Array.isArray(e.value) || e.columnType === "select") && !a) {
315
- const e = /* @__PURE__ */ new Set();
316
- return o.forEach((s) => {
317
- Array.isArray(s.value) ? s.value.forEach((c) => e.add(c)) : s.value && e.add(s.value);
317
+ const i = a.some((r) => r.operator === "notEqual" || r.operator === "notContains");
318
+ if (e === "set" || a.some((r) => Array.isArray(r.value) || r.columnType === "select") && !i) {
319
+ const r = /* @__PURE__ */ new Set();
320
+ return a.forEach((l) => {
321
+ Array.isArray(l.value) ? l.value.forEach((o) => r.add(o)) : l.value && r.add(l.value);
318
322
  }), {
319
323
  filterType: "set",
320
- values: Array.from(e)
324
+ values: Array.from(r)
321
325
  };
322
326
  }
323
- const l = o;
324
- if (l.length === 1) {
325
- const e = l[0], s = O(e.operator, e.value, e.columnType);
326
- if (s === "date" && typeof e.value == "string") {
327
- const u = (i) => {
328
- if (!i || Array.isArray(i)) return null;
329
- if (/^\d{4}-\d{2}-\d{2}$/.test(i)) return i;
327
+ const u = a;
328
+ if (u.length === 1) {
329
+ const r = u[0], l = O(r.operator, r.value, r.columnType);
330
+ if (l === "date" && typeof r.value == "string") {
331
+ const c = (s) => {
332
+ if (!s || Array.isArray(s)) return null;
333
+ if (/^\d{4}-\d{2}-\d{2}$/.test(s)) return s;
330
334
  try {
331
- const d = new Date(i), y = d.getFullYear(), g = String(d.getMonth() + 1).padStart(2, "0"), F = String(d.getDate()).padStart(2, "0");
335
+ const d = new Date(s), y = d.getFullYear(), g = String(d.getMonth() + 1).padStart(2, "0"), F = String(d.getDate()).padStart(2, "0");
332
336
  return `${y}-${g}-${F}`;
333
337
  } catch {
334
- return i;
338
+ return s;
335
339
  }
336
340
  };
337
- return e.operator === "inRange" ? {
341
+ return r.operator === "inRange" ? {
338
342
  type: "inRange",
339
- dateFrom: u(e.value),
340
- dateTo: u(e.valueTo || ""),
343
+ dateFrom: c(r.value),
344
+ dateTo: c(r.valueTo || ""),
341
345
  filterType: "date"
342
346
  } : {
343
- type: h(e.operator),
344
- dateFrom: u(e.value),
347
+ type: h(r.operator),
348
+ dateFrom: c(r.value),
345
349
  filterType: "date"
346
350
  };
347
351
  }
348
- const c = (u) => {
349
- if (Array.isArray(u)) return u;
350
- const i = e.columnType === "number";
351
- return (s === "number" || i) && parseFloat(u) || u;
352
+ const o = (c) => {
353
+ if (Array.isArray(c)) return c;
354
+ const s = r.columnType === "number";
355
+ return (l === "number" || s) && parseFloat(c) || c;
352
356
  };
353
- return e.operator === "inRange" ? {
354
- type: h(e.operator),
355
- filter: c(e.value),
356
- filterTo: c(e.valueTo || ""),
357
- filterType: s
358
- } : e.operator === "empty" || e.operator === "notEmpty" ? {
359
- type: h(e.operator),
357
+ return r.operator === "inRange" ? {
358
+ type: h(r.operator),
359
+ filter: o(r.value),
360
+ filterTo: o(r.valueTo || ""),
361
+ filterType: l
362
+ } : r.operator === "empty" || r.operator === "notEmpty" ? {
363
+ type: h(r.operator),
360
364
  filterType: "text"
361
365
  // Empty checks usually run on text filter or generic
362
366
  } : {
363
- type: h(e.operator),
364
- filter: c(e.value),
365
- filterType: s
367
+ type: h(r.operator),
368
+ filter: o(r.value),
369
+ filterType: l
366
370
  };
367
371
  } else {
368
- let e = "text";
369
- const s = n.map((c) => {
370
- const u = h(c.operator), i = O(c.operator, c.value, c.columnType);
371
- e === "text" && i !== "text" && i !== "set" && (e = i);
372
- const d = (g) => Array.isArray(g) ? g : i === "number" && parseFloat(g) || g;
373
- let y = u;
374
- return i === "number" && (["contains", "startsWith", "endsWith"].includes(u) ? y = "equals" : u === "notContains" && (y = "notEqual")), c.operator === "inRange" ? {
375
- type: u,
376
- filter: d(c.value),
377
- filterTo: d(c.valueTo || ""),
378
- filterType: i
379
- } : c.operator === "empty" || c.operator === "notEmpty" ? {
380
- type: u,
372
+ let r = "text";
373
+ const l = n.map((o) => {
374
+ const c = h(o.operator), s = O(o.operator, o.value, o.columnType);
375
+ r === "text" && s !== "text" && s !== "set" && (r = s);
376
+ const d = (g) => Array.isArray(g) ? g : s === "number" && parseFloat(g) || g;
377
+ let y = c;
378
+ return s === "number" && (["contains", "startsWith", "endsWith"].includes(c) ? y = "equals" : c === "notContains" && (y = "notEqual")), o.operator === "inRange" ? {
379
+ type: c,
380
+ filter: d(o.value),
381
+ filterTo: d(o.valueTo || ""),
382
+ filterType: s
383
+ } : o.operator === "empty" || o.operator === "notEmpty" ? {
384
+ type: c,
381
385
  filterType: "text"
382
386
  } : {
383
387
  type: y,
384
- filter: d(c.value),
385
- filterType: i
388
+ filter: d(o.value),
389
+ filterType: s
386
390
  };
387
391
  });
388
392
  return {
389
- filterType: e,
390
- operator: r,
391
- conditions: s
393
+ filterType: r,
394
+ operator: t,
395
+ conditions: l
392
396
  };
393
397
  }
394
398
  }
395
399
  function k(n) {
396
400
  if (!n || Object.keys(n).length === 0) return null;
397
- const t = [];
398
- for (const [r, o] of Object.entries(n)) {
399
- if (!o) continue;
400
- const a = (l) => {
401
- if (!l) return [];
402
- if ("conditions" in l && l.conditions && l.operator)
403
- return l.conditions.flatMap((i) => a(i));
404
- if ("filterType" in l && l.filterType === "multi" && l.filterModels)
405
- return l.filterModels.flatMap((i) => i ? a(i) : []);
406
- const e = l, s = "type" in e ? e.type : "equals", c = e.filterType === "set" ? "equals" : M[s] || "contains", u = e.filter !== void 0 ? String(e.filter) : e.dateFrom !== void 0 ? String(e.dateFrom) : e.values ? e.values : "";
401
+ const e = [];
402
+ for (const [t, a] of Object.entries(n)) {
403
+ if (!a) continue;
404
+ const i = (u) => {
405
+ if (!u) return [];
406
+ if ("conditions" in u && u.conditions && u.operator)
407
+ return u.conditions.flatMap((s) => i(s));
408
+ if ("filterType" in u && u.filterType === "multi" && u.filterModels)
409
+ return u.filterModels.flatMap((s) => s ? i(s) : []);
410
+ const r = u, l = "type" in r ? r.type : "equals", o = r.filterType === "set" ? "equals" : M[l] || "contains", c = r.filter !== void 0 ? String(r.filter) : r.dateFrom !== void 0 ? String(r.dateFrom) : r.values ? r.values : "";
407
411
  return [{
408
- id: q(),
409
- columnId: r,
410
- operator: c,
411
- value: u,
412
- valueTo: e.filterTo || e.dateTo,
413
- columnType: e.filterType
412
+ id: E(),
413
+ columnId: t,
414
+ operator: o,
415
+ value: c,
416
+ valueTo: r.filterTo || r.dateTo,
417
+ columnType: r.filterType
414
418
  }];
415
- }, f = a(o);
416
- t.push(...f);
419
+ }, f = i(a);
420
+ e.push(...f);
417
421
  }
418
- return t.length === 0 ? null : {
422
+ return e.length === 0 ? null : {
419
423
  logic: "AND",
420
424
  // Default top-level logic
421
- rules: t
425
+ rules: e
422
426
  };
423
427
  }
424
428
  export {
425
429
  k as convertFromAgGridFilterModel,
426
- w as convertToAgGridFilterModel,
427
- D as createEmptyRule,
428
- C as formatRuleForDisplay,
429
- q as generateFilterId,
430
+ D as convertToAgGridFilterModel,
431
+ j as createEmptyRule,
432
+ $ as formatRuleForDisplay,
433
+ E as generateFilterId,
430
434
  A as getDisplayStringFromFilterModel,
431
- I as getMultiFilterIndices,
435
+ w as getMultiFilterIndices,
432
436
  h as mapOperatorToAgGrid,
433
- j as parseInputPattern
437
+ I as parseInputPattern
434
438
  };
package/package.json CHANGED
@@ -1,11 +1,62 @@
1
1
 
2
2
  {
3
3
  "name": "impact-nova",
4
- "version": "0.1.6",
4
+ "version": "0.1.9",
5
+ "description": "Enterprise-grade React design system built with React 19, Vite, Tailwind CSS, and Radix UI. Comprehensive UI component library for scalable, accessible, and performant applications.",
5
6
  "type": "module",
6
7
  "main": "./dist/index.js",
7
8
  "module": "./dist/index.js",
8
9
  "types": "./dist/index.d.ts",
10
+ "license": "MIT",
11
+ "author": "Impact Analytics",
12
+ "keywords": [
13
+ "react",
14
+ "react-19",
15
+ "design-system",
16
+ "component-library",
17
+ "ui-library",
18
+ "tailwind",
19
+ "tailwindcss",
20
+ "radix-ui",
21
+ "typescript",
22
+ "vite",
23
+ "enterprise",
24
+ "accessibility",
25
+ "a11y",
26
+ "ui-components",
27
+ "react-components",
28
+ "shadcn",
29
+ "headless-ui",
30
+ "ag-grid",
31
+ "data-table",
32
+ "charts",
33
+ "highcharts",
34
+ "forms",
35
+ "navigation",
36
+ "modal",
37
+ "dialog",
38
+ "toast",
39
+ "dropdown",
40
+ "select",
41
+ "input",
42
+ "button",
43
+ "card",
44
+ "accordion",
45
+ "tabs",
46
+ "date-picker",
47
+ "icons",
48
+ "theme",
49
+ "design-tokens",
50
+ "impact-nova"
51
+ ],
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/insideinsight/impact-nova.git"
55
+ },
56
+ "bugs": {
57
+ "url": "https://impactanalytics.atlassian.net/jira/software/c/projects/DES/issues"
58
+ },
59
+ "homepage": "https://github.com/insideinsight/impact-nova#readme",
9
60
  "sideEffects": [
10
61
  "*.css",
11
62
  "*.scss"
@@ -13,7 +64,9 @@
13
64
  "files": [
14
65
  "dist",
15
66
  "tailwind.config.js",
16
- "tailwind.config.d.ts"
67
+ "tailwind.config.d.ts",
68
+ "LICENSE",
69
+ "README.md"
17
70
  ],
18
71
  "exports": {
19
72
  ".": {