impact-nova 2.5.4 → 2.5.5

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.
@@ -1,30 +1,30 @@
1
1
  import { jsxs as ye, jsx as F } from "react/jsx-runtime";
2
2
  import { lazy as be, useRef as L, useState as O, useId as xe, useEffect as q, useCallback as m, useMemo as f, Suspense as Se } from "react";
3
- import { ModuleRegistry as Fe, AllCommunityModule as Ae, ValidationModule as Ee } from "ag-grid-community";
4
- import { AllEnterpriseModule as Ge } from "ag-grid-enterprise";
5
- import { AgGridReact as Me } from "ag-grid-react";
6
- import { customAgGridTheme as Re } from "./theme.js";
7
- import { syncAgGridThemeMode as Te } from "./sync-ag-grid-theme-mode.js";
8
- import { CustomHeader as we } from "./headers/custom-header.js";
3
+ import { ModuleRegistry as Fe, AllCommunityModule as Ae } from "ag-grid-community";
4
+ import { AllEnterpriseModule as Ee } from "ag-grid-enterprise";
5
+ import { AgGridReact as Ge } from "ag-grid-react";
6
+ import { customAgGridTheme as Me } from "./theme.js";
7
+ import { syncAgGridThemeMode as Re } from "./sync-ag-grid-theme-mode.js";
8
+ import { CustomHeader as Te } from "./headers/custom-header.js";
9
9
  import { CustomHeaderGroup as z } from "./headers/custom-inner-header-group.js";
10
- import { mergeColumnGroupDefsWithDefault as ke } from "./merge-column-group-defs.js";
11
- import { DefaultTextCellRenderer as Ie } from "./cell-renderers/default-text-cell-renderer.js";
12
- import { GridHeaderContext as je } from "./headers/context/grid-header-context.js";
13
- import { convertToAgGridFilterModel as Pe, getMultiFilterIndices as De, convertFromAgGridFilterModel as Le } from "./headers/utils/filter-utils.js";
14
- import { AG_GRID_VALUE_FORMATTERS as Oe } from "./value-formatters.js";
15
- import { useGridAutoSizeStrategyOnResize as He } from "./useGridAutoSizeStrategyOnResize.js";
16
- import { subscribeGridApiEvent as ct, subscribeGridApiEvents as ut } from "./grid-api-event-subscription.js";
10
+ import { mergeColumnGroupDefsWithDefault as we } from "./merge-column-group-defs.js";
11
+ import { DefaultTextCellRenderer as ke } from "./cell-renderers/default-text-cell-renderer.js";
12
+ import { GridHeaderContext as Ie } from "./headers/context/grid-header-context.js";
13
+ import { convertToAgGridFilterModel as je, getMultiFilterIndices as Pe, convertFromAgGridFilterModel as De } from "./headers/utils/filter-utils.js";
14
+ import { AG_GRID_VALUE_FORMATTERS as Le } from "./value-formatters.js";
15
+ import { useGridAutoSizeStrategyOnResize as Oe } from "./useGridAutoSizeStrategyOnResize.js";
16
+ import { subscribeGridApiEvent as ct, subscribeGridApiEvents as at } from "./grid-api-event-subscription.js";
17
17
  import { notifyColumnIndicatorSync as R } from "./notify-column-indicator-sync.js";
18
- import { setActiveSearchColumnId as H, clearHeaderSearchActiveState as Ne } from "./headers/header-search-active-state.js";
18
+ import { setActiveSearchColumnId as H, clearHeaderSearchActiveState as He } from "./headers/header-search-active-state.js";
19
19
  /* empty css */
20
- import { useAgGridTruncationTooltip as pt } from "./use-ag-grid-truncation-tooltip.js";
21
- import { isAgGridHeaderLabelTooltipOverflowing as ft, isAgGridTextOverflowing as gt } from "./ag-grid-tooltip-overflow.js";
22
- const We = be(
20
+ import { useAgGridTruncationTooltip as dt } from "./use-ag-grid-truncation-tooltip.js";
21
+ import { isAgGridHeaderLabelTooltipOverflowing as mt, isAgGridTextOverflowing as ft } from "./ag-grid-tooltip-overflow.js";
22
+ const Ne = be(
23
23
  () => import("./headers/advanced-filter/advanced-filter-dialog.js").then((s) => ({
24
24
  default: s.AdvancedFilterDialog
25
25
  }))
26
26
  );
27
- Fe.registerModules([Ae, Ge, Ee]);
27
+ Fe.registerModules([Ae, Ee]);
28
28
  const S = "", N = "", J = (s) => {
29
29
  if (!s) return;
30
30
  const o = s.cellRendererParams?.splits;
@@ -39,18 +39,18 @@ const S = "", N = "", J = (s) => {
39
39
  l.push("");
40
40
  continue;
41
41
  }
42
- const c = s[g];
43
- if (c == null) {
42
+ const a = s[g];
43
+ if (a == null) {
44
44
  l.push("");
45
45
  continue;
46
46
  }
47
- if (typeof c == "object" && "value" in c) {
48
- const u = c.value;
47
+ if (typeof a == "object" && "value" in a) {
48
+ const u = a.value;
49
49
  l.push(u == null ? "" : String(u));
50
50
  continue;
51
51
  }
52
- if (typeof c != "object") {
53
- l.push(String(c));
52
+ if (typeof a != "object") {
53
+ l.push(String(a));
54
54
  continue;
55
55
  }
56
56
  l.push("");
@@ -72,13 +72,13 @@ const S = "", N = "", J = (s) => {
72
72
  document.body.removeChild(o);
73
73
  }
74
74
  };
75
- function it({
75
+ function lt({
76
76
  children: s,
77
77
  defaultColDef: o,
78
78
  defaultColGroupDef: l,
79
79
  columnDefs: y,
80
80
  valueFormatters: g,
81
- onGridReady: c,
81
+ onGridReady: a,
82
82
  onGridPreDestroyed: u,
83
83
  onFilterChanged: b,
84
84
  onSelectionChanged: h,
@@ -92,10 +92,10 @@ function it({
92
92
  themeOverride: ee,
93
93
  ...C
94
94
  }) {
95
- const a = L(null), j = L(null), [W, _] = O(null), K = xe(), v = L(K);
96
- v.current = K, He(W, j, w), q(() => {
95
+ const c = L(null), j = L(null), [W, _] = O(null), K = xe(), v = L(K);
96
+ v.current = K, Oe(W, j, w), q(() => {
97
97
  const e = document.documentElement, t = () => {
98
- Te(e.classList.contains("dark") ? "dark" : "light", e);
98
+ Re(e.classList.contains("dark") ? "dark" : "light", e);
99
99
  };
100
100
  t();
101
101
  const n = new MutationObserver(t);
@@ -125,14 +125,14 @@ function it({
125
125
  }), []), P = f(() => ({
126
126
  gridScopeId: v.current,
127
127
  openSearch: (e) => {
128
- if (!a.current) return;
129
- const t = a.current.getGridOption("context") || {};
130
- a.current.setGridOption("context", { ...t, activeSearchColumnId: e }), H(v.current, e), R(a.current);
128
+ if (!c.current) return;
129
+ const t = c.current.getGridOption("context") || {};
130
+ c.current.setGridOption("context", { ...t, activeSearchColumnId: e }), H(v.current, e), R(c.current);
131
131
  },
132
132
  closeSearch: () => {
133
- if (!a.current) return;
134
- const e = a.current.getGridOption("context") || {};
135
- a.current.setGridOption("context", { ...e, activeSearchColumnId: null }), H(v.current, null), R(a.current);
133
+ if (!c.current) return;
134
+ const e = c.current.getGridOption("context") || {};
135
+ c.current.setGridOption("context", { ...e, activeSearchColumnId: null }), H(v.current, null), R(c.current);
136
136
  },
137
137
  openAdvancedFilter: (e) => {
138
138
  V(e || null), U(!0);
@@ -141,21 +141,21 @@ function it({
141
141
  U(!1), V(null);
142
142
  },
143
143
  applyAdvancedFilter: (e) => {
144
- if (!a.current) return;
145
- const t = Pe(e);
146
- a.current.setFilterModel(t), a.current.onFilterChanged(), R(a.current);
144
+ if (!c.current) return;
145
+ const t = je(e);
146
+ c.current.setFilterModel(t), c.current.onFilterChanged(), R(c.current);
147
147
  }
148
148
  }), []), le = m((e) => {
149
- a.current = e.api, _(e.api);
149
+ c.current = e.api, _(e.api);
150
150
  const t = e.api.getGridOption("context") || {};
151
151
  e.api.setGridOption("context", {
152
152
  ...t,
153
153
  activeSearchColumnId: null,
154
154
  headerSearchScopeId: v.current
155
- }), H(v.current, null), c && c(e);
156
- }, [c]), ie = m(
155
+ }), H(v.current, null), a && a(e);
156
+ }, [a]), ie = m(
157
157
  (e) => {
158
- Ne(v.current), a.current = null, _(null), u?.(e);
158
+ He(v.current), c.current = null, _(null), u?.(e);
159
159
  },
160
160
  [u]
161
161
  ), se = m(
@@ -163,12 +163,12 @@ function it({
163
163
  R(e.api), b?.(e);
164
164
  },
165
165
  [b]
166
- ), ae = m(
166
+ ), ce = m(
167
167
  (e) => {
168
168
  h?.(e);
169
169
  },
170
170
  [h]
171
- ), ce = m(
171
+ ), ae = m(
172
172
  (e) => {
173
173
  A?.(e);
174
174
  },
@@ -189,11 +189,11 @@ function it({
189
189
  return e.addEventListener("keydown", t, !0), () => e.removeEventListener("keydown", t, !0);
190
190
  }, []);
191
191
  const ue = f(() => ({
192
- headerComponent: we,
192
+ headerComponent: Te,
193
193
  // Default cell renderer wraps text in a span so display:flex centering
194
194
  // and text-overflow:ellipsis both work (ellipsis doesn't work on
195
195
  // anonymous flex text nodes, but works on flex child elements).
196
- cellRenderer: Ie,
196
+ cellRenderer: ke,
197
197
  ...o,
198
198
  suppressHeaderKeyboardEvent: (e) => {
199
199
  const { event: t } = e, n = t.target;
@@ -219,10 +219,10 @@ function it({
219
219
  innerHeaderGroupComponent: l?.headerGroupComponentParams?.innerHeaderGroupComponent ?? "CustomInnerHeaderGroup"
220
220
  }
221
221
  }), [l]), de = f(
222
- () => ke(y ?? void 0, D),
222
+ () => we(y ?? void 0, D),
223
223
  [y, D]
224
224
  ), pe = f(() => ({
225
- ...Oe,
225
+ ...Le,
226
226
  // Always available - value formatters
227
227
  CustomInnerHeaderGroup: z,
228
228
  CustomHeaderGroup: z,
@@ -310,11 +310,11 @@ function it({
310
310
  processCellCallback: E,
311
311
  ...C.defaultExcelExportParams ?? {}
312
312
  }), [E, C.defaultExcelExportParams]);
313
- return /* @__PURE__ */ ye(je.Provider, { value: P, children: [
313
+ return /* @__PURE__ */ ye(Ie.Provider, { value: P, children: [
314
314
  /* @__PURE__ */ F("div", { ref: j, "data-component": "ag-grid-react", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ F(
315
- Me,
315
+ Ge,
316
316
  {
317
- theme: ee ?? Re,
317
+ theme: ee ?? Me,
318
318
  defaultColDef: ue,
319
319
  columnDefs: de,
320
320
  cellSelection: !0,
@@ -322,8 +322,8 @@ function it({
322
322
  onGridReady: le,
323
323
  onGridPreDestroyed: ie,
324
324
  onFilterChanged: se,
325
- onSelectionChanged: ae,
326
- onModelUpdated: ce,
325
+ onSelectionChanged: ce,
326
+ onModelUpdated: ae,
327
327
  tooltipShowMode: k,
328
328
  tooltipShowDelay: I,
329
329
  tooltipHideDelay: Y,
@@ -348,7 +348,7 @@ function it({
348
348
  ) }),
349
349
  s,
350
350
  /* @__PURE__ */ F(
351
- _e,
351
+ We,
352
352
  {
353
353
  isOpen: te,
354
354
  columnId: re,
@@ -359,7 +359,7 @@ function it({
359
359
  )
360
360
  ] });
361
361
  }
362
- function _e({
362
+ function We({
363
363
  isOpen: s,
364
364
  columnId: o,
365
365
  gridApi: l,
@@ -367,11 +367,11 @@ function _e({
367
367
  onApply: g
368
368
  }) {
369
369
  if (!s || !o || !l) return null;
370
- const c = l.getColumn(o);
371
- if (!c) return null;
372
- const u = c.getColDef(), b = u.headerComponentParams, h = De(u), A = h.text !== -1 || h.number !== -1 || h.date !== -1, T = h.set !== -1, k = u.filter === "agMultiColumnFilter" && (A || T) ? "multi" : u.filter === "agNumberColumnFilter" ? "number" : u.filter === "agDateColumnFilter" ? "date" : u.filter === "agSetColumnFilter" || b?.selectOptions ? "select" : "text", I = Le(l.getFilterModel());
370
+ const a = l.getColumn(o);
371
+ if (!a) return null;
372
+ const u = a.getColDef(), b = u.headerComponentParams, h = Pe(u), A = h.text !== -1 || h.number !== -1 || h.date !== -1, T = h.set !== -1, k = u.filter === "agMultiColumnFilter" && (A || T) ? "multi" : u.filter === "agNumberColumnFilter" ? "number" : u.filter === "agDateColumnFilter" ? "date" : u.filter === "agSetColumnFilter" || b?.selectOptions ? "select" : "text", I = De(l.getFilterModel());
373
373
  return /* @__PURE__ */ F(Se, { fallback: null, children: /* @__PURE__ */ F(
374
- We,
374
+ Ne,
375
375
  {
376
376
  isOpen: s,
377
377
  onClose: y,
@@ -387,10 +387,10 @@ function _e({
387
387
  ) });
388
388
  }
389
389
  export {
390
- it as AgGridWrapper,
391
- ft as isAgGridHeaderLabelTooltipOverflowing,
392
- gt as isAgGridTextOverflowing,
390
+ lt as AgGridWrapper,
391
+ mt as isAgGridHeaderLabelTooltipOverflowing,
392
+ ft as isAgGridTextOverflowing,
393
393
  ct as subscribeGridApiEvent,
394
- ut as subscribeGridApiEvents,
395
- pt as useAgGridTruncationTooltip
394
+ at as subscribeGridApiEvents,
395
+ dt as useAgGridTruncationTooltip
396
396
  };
@@ -10,6 +10,13 @@ import { ColumnState } from 'ag-grid-community';
10
10
  * receives a complete ordered array — as intended for `applyColumnState`, without relying
11
11
  * on incidental merge behaviour inside the grid.
12
12
  *
13
+ * **Managed columns** (ids present in `partial`): order and overridden fields come from
14
+ * `partial`; other fields are preserved from `prevState`.
15
+ *
16
+ * **Non-managed columns** (e.g. AG Grid service columns excluded from the picker tree):
17
+ * keep their relative anchor position in `prevState` — columns before the first managed
18
+ * column stay before the managed block; columns after stay after.
19
+ *
13
20
  * Complexity: O(N) time, O(N) extra map/set memory for one pass over `prevState` and
14
21
  * `partial` (unavoidable when applying global order for N columns).
15
22
  */
@@ -1,29 +1,54 @@
1
- function f(e, t) {
2
- if (t.length === 0)
3
- return e;
4
- const c = /* @__PURE__ */ new Map();
5
- for (let n = 0; n < e.length; n++) {
6
- const o = e[n];
7
- c.set(o.colId, o);
1
+ function u(n, l) {
2
+ if (l.length === 0)
3
+ return n;
4
+ const i = /* @__PURE__ */ new Map();
5
+ for (let e = 0; e < n.length; e++) {
6
+ const t = n[e];
7
+ i.set(t.colId, t);
8
8
  }
9
- const l = /* @__PURE__ */ new Set();
10
- for (let n = 0; n < t.length; n++)
11
- l.add(t[n].colId);
12
- let d = 0;
13
- for (let n = 0; n < e.length; n++)
14
- l.has(e[n].colId) || d++;
15
- const s = new Array(t.length + d);
16
- let g = 0;
17
- for (let n = 0; n < t.length; n++) {
18
- const o = t[n], i = c.get(o.colId);
19
- s[g++] = i !== void 0 ? Object.assign({}, i, o) : Object.assign({}, o);
9
+ const s = /* @__PURE__ */ new Set();
10
+ for (let e = 0; e < l.length; e++)
11
+ s.add(l[e].colId);
12
+ const c = new Array(l.length);
13
+ for (let e = 0; e < l.length; e++) {
14
+ const t = l[e], h = i.get(t.colId);
15
+ c[e] = h !== void 0 ? Object.assign({}, h, t) : Object.assign({}, t);
20
16
  }
21
- for (let n = 0; n < e.length; n++) {
22
- const o = e[n];
23
- l.has(o.colId) || (s[g++] = o);
17
+ let o = !1, d = 0, g = 0;
18
+ for (let e = 0; e < n.length; e++) {
19
+ const t = n[e];
20
+ if (s.has(t.colId)) {
21
+ o = !0;
22
+ continue;
23
+ }
24
+ o ? g++ : d++;
24
25
  }
25
- return s;
26
+ const r = new Array(
27
+ d + c.length + g
28
+ );
29
+ let f = 0;
30
+ o = !1;
31
+ for (let e = 0; e < n.length; e++) {
32
+ const t = n[e];
33
+ if (s.has(t.colId)) {
34
+ o = !0;
35
+ continue;
36
+ }
37
+ o || (r[f++] = t);
38
+ }
39
+ for (let e = 0; e < c.length; e++)
40
+ r[f++] = c[e];
41
+ o = !1;
42
+ for (let e = 0; e < n.length; e++) {
43
+ const t = n[e];
44
+ if (s.has(t.colId)) {
45
+ o = !0;
46
+ continue;
47
+ }
48
+ o && (r[f++] = t);
49
+ }
50
+ return r;
26
51
  }
27
52
  export {
28
- f as mergePartialOrderedColumnState
53
+ u as mergePartialOrderedColumnState
29
54
  };
@@ -1 +1 @@
1
- export default "# Install and configure Impact Nova\n\nUse these steps to add Impact Nova to an existing project. Run the commands in your project root and apply the code changes to your entry file and layout.\n\n## 0. Scaffold a new app (recommended)\n\n**`create-impact-nova@^1.4.7`** is on npm. Scaffold auto-detects dependency mode:\n\n| Where you run | `impact-nova` dependency |\n|---------------|--------------------------|\n| Published CLI / MCP (outside monorepo) | `impact-nova@^2.5.4` from npm (`latest` tag) |\n| Inside impact-nova monorepo | `file:` link to repo root |\n\n```bash\nnpx create-impact-nova my-dashboard\ncd my-dashboard\nnpm run dev\n```\n\nMCP: **`scaffold_impact_nova_app`** with `projectName` and optional `modules[]` from the user prompt.\n\n**Overrides:** CLI `--from-npm` · `--link-monorepo` · MCP `usePublishedPackages: true | false`\n\n```bash\nnpx create-impact-nova my-dashboard --from-npm\n```\n\nBase template is shell-only (Home + shared primitives). Feature pages come from recipes — see `create-impact-nova/recipes/README.md`.\n\n**Local link in an existing app** (manual):\n\n```bash\nnpm install impact-nova@file:../path-to-impact-nova-repo\n```\n\nRun `npm run build` in the impact-nova repo after design-system changes.\n\n## 1. Install the package and peer dependencies\n\n```bash\nnpm install impact-nova impact-nova-icons\nnpm install react@^19 react-dom@^19\n```\n\n**Required peers:** `react@^19`, `react-dom@^19`, `impact-nova-icons@^0.1.1`\n\n**Optional peers** (install when you use these features):\n\n| Package | Version | When needed |\n|---------|---------|-------------|\n| `ag-grid-community` | `36.0.1` | AG Grid types/API (pin with react + enterprise) |\n| `ag-grid-react` | `36.0.1` | DataTable / AG Grid |\n| `ag-grid-enterprise` | `36.0.1` | Enterprise grid features |\n| `highcharts` | `^12` | Chart component |\n| `highcharts-react-official` | `^3` | Chart component |\n| `highcharts-border-radius` | `^0.0.4` | Rounded chart corners |\n\nIf you use AG Grid or Highcharts in your app, also install:\n\n```bash\nnpm install ag-grid-community@36.0.1 ag-grid-react@36.0.1 ag-grid-enterprise@36.0.1\n# Optional, for charts:\nnpm install highcharts@^12 highcharts-react-official@^3 highcharts-border-radius@^0.0.4\n```\n\n## 2. Import styles in your root entry\n\nIn your app root (e.g. `main.tsx`, `App.tsx`, or `layout.tsx`), **import the CSS before your app component**:\n\n```tsx\nimport 'impact-nova/dist/impact-nova.css';\nimport App from './App';\n// ... rest of your bootstrap\n```\n\n## 3. Add Manrope font (recommended)\n\nIn your `index.html` or layout:\n\n```html\n<link href=\"https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap\" rel=\"stylesheet\" />\n```\n\nIn your global CSS or Tailwind base:\n\n```css\n@layer base {\n body {\n font-family: 'Manrope', sans-serif;\n }\n}\n```\n\n## 4. Wrap your app with providers (recommended)\n\nMount **`ImpactNovaProviders`** once at the app root. It bundles i18n (`ImpactNovaI18nProvider`) and `TooltipProvider` (required for tooltips since v2.0.8):\n\n```tsx\nimport { ImpactNovaProviders } from 'impact-nova/form';\n\nfunction Root() {\n return (\n <ImpactNovaProviders locale=\"en\">\n <App />\n </ImpactNovaProviders>\n );\n}\n```\n\nFor another locale, pass a locale pack:\n\n```tsx\nimport { ImpactNovaProviders } from 'impact-nova/form';\nimport { de } from 'impact-nova/locale/de';\n\n<ImpactNovaProviders locale=\"de\" messages={de}>\n <App />\n</ImpactNovaProviders>\n```\n\n**Barrel exception:** locale packs may use `import { de } from 'impact-nova'`. All UI components still use subpaths (see §5).\n\n## 5. Subpath imports (recommended)\n\nPrefer subpath imports in feature code for tree-shaking:\n\n```tsx\nimport { Button } from 'impact-nova/button';\nimport { Card, CardContent } from 'impact-nova/card';\nimport { DataTable, DataTableContent, useDataTable } from 'impact-nova/data-table';\nimport { CheckCircle } from 'impact-nova-icons';\n```\n\nThe barrel `import { Button } from 'impact-nova'` still works but pulls a larger module graph. **Use subpaths for all UI components**; reserve the barrel for locale packs at app root only. Use `ImpactNovaProviders` from `impact-nova/form` for app setup.\n\n## 6. Using Impact Nova with CSS or SCSS (no Tailwind)\n\nIf your app uses **plain CSS or SCSS** and does **not** use Tailwind, you can still use Impact Nova. Tailwind is optional. Impact Nova ships a single built CSS file (no SCSS source).\n\n- **Import the library CSS** in your app root (e.g. `main.tsx`, `App.tsx`):\n ```tsx\n import 'impact-nova/dist/impact-nova.css';\n ```\n **CSS split exports** (optional, for layered theming): `impact-nova/impact-nova-tokens.scss`, `impact-nova/impact-nova-base.scss`, `impact-nova/impact-nova-components.css`\n Or from your main stylesheet: `@import 'impact-nova/dist/impact-nova.css';` in your main.css or main.scss.\n- **Component styling** comes from Impact Nova's CSS. Use each component's `variant` and `size` props; no Tailwind classes are required.\n- **Your layout and spacing** stay in your CSS or SCSS (margins, padding, flexbox, grid). Use your usual class names; the design system does not require Tailwind utilities.\n- **Manrope font:** Add the font link in `index.html` and in your CSS/SCSS set `body { font-family: 'Manrope', sans-serif; }` (see section 3).\n- **Summary:** No Tailwind, no Tailwind config. Load `impact-nova.css` once; use components with their props; use your existing CSS/SCSS for the rest.\n\n## 6b. Theming in consumer apps\n\n| Surface | What ships |\n|---------|------------|\n| **npm / consumer apps** | **Impact Light** only — `import 'impact-nova/dist/impact-nova.css'` (from `src/theme/tokens/light.json`) |\n| **Storybook / dev** | 10 curated **theme presets** (Impact Dark, Midnight, Ocean, …) — preview switcher only |\n\n**Do not** copy Storybook preset JSON or `theme-presets.ts` into consumer apps. Presets are not in the published package.\n\n**Custom branding:** override CSS variables on `:root` or a scoped class (e.g. `.my-brand`). Use Storybook **Theme Builder** / **Token Catalog** to explore tokens, then export CSS/JSON for your overrides.\n\n## 7. Using Impact Nova with Webpack\n\nIf your app is built with **Webpack** (including Create React App, which uses Webpack):\n\n- **CSS import:** Webpack will bundle the library CSS as long as you have a rule for `.css`. Ensure your config includes something like:\n ```js\n module: {\n rules: [\n {\n test: /\\.css$/,\n use: ['style-loader', 'css-loader'],\n // or with MiniCssExtractPlugin:\n // use: [MiniCssExtractPlugin.loader, 'css-loader'],\n },\n // ... other rules (e.g. for .tsx, .js)\n ],\n },\n ```\n Then in your root component or entry:\n ```tsx\n import 'impact-nova/dist/impact-nova.css';\n ```\n- **Create React App (CRA):** No extra config. Add `import 'impact-nova/dist/impact-nova.css';` in `index.tsx` or `App.tsx`.\n- **Dedupe React / AG Grid:** If you see “multiple copies of React” or AG Grid issues, use Webpack’s `resolve.alias` so the app uses a single version:\n ```js\n resolve: {\n alias: {\n react: path.resolve(__dirname, 'node_modules/react'),\n 'react-dom': path.resolve(__dirname, 'node_modules/react-dom'),\n // If using AG Grid:\n 'ag-grid-react': path.resolve(__dirname, 'node_modules/ag-grid-react'),\n 'ag-grid-community': path.resolve(__dirname, 'node_modules/ag-grid-community'),\n 'ag-grid-enterprise': path.resolve(__dirname, 'node_modules/ag-grid-enterprise'),\n },\n },\n ```\n- **Tailwind + Webpack:** If you use Tailwind, add the Impact Nova preset and include the package in `content` (see section 7 below).\n\n## 8. Optional: extend Tailwind with Impact Nova preset\n\nIf your project uses Tailwind and you want the same theme (colors, radius), extend your `tailwind.config.js` with the preset from the package:\n\n```js\n// tailwind.config.js\nimport impactNovaPreset from 'impact-nova/tailwind.config.js';\n// → dist/tailwind.config.js (bundled theme; no package src/ required)\n\nexport default {\n presets: [impactNovaPreset],\n content: [\n './index.html',\n './src/**/*.{js,ts,jsx,tsx}',\n './node_modules/impact-nova/dist/**/*.js',\n ],\n // ... rest of your config\n};\n```\n\n## Summary checklist\n\n- [ ] `npm install impact-nova impact-nova-icons` (and react, react-dom; optional: ag-grid, highcharts)\n- [ ] `import 'impact-nova/dist/impact-nova.css'` in root entry (or @import in main.css/main.scss if using CSS or SCSS without Tailwind; see §6)\n- [ ] Add Manrope font link and body font-family\n- [ ] Wrap app with `<ImpactNovaProviders locale=\"en\">` from `impact-nova/form`\n- [ ] Use subpath imports in feature code (see §5)\n- [ ] (Optional) Add Tailwind preset and content path for impact-nova\n- [ ] **Webpack:** Ensure a CSS rule (style-loader + css-loader) and, if needed, resolve.alias for React/AG Grid\n\nAfter this, import components via subpaths: `import { Button } from 'impact-nova/button';`\n\n## 9. Dashboard app shell (optional)\n\nTo scaffold a full dashboard (sidebar, header, breadcrumb, filters), read resource **`impact-nova://layout`** or call `get_real_world_patterns` with `topic: \"layout\"`. Use `Layout` from `impact-nova/layout` — not `DynamicLayout` (grid/flex utility only).\n";
1
+ export default "# Install and configure Impact Nova\n\nUse these steps to add Impact Nova to an existing project. Run the commands in your project root and apply the code changes to your entry file and layout.\n\n## 0. Scaffold a new app (recommended)\n\n**`create-impact-nova@^1.4.7`** is on npm. Scaffold auto-detects dependency mode:\n\n| Where you run | `impact-nova` dependency |\n|---------------|--------------------------|\n| Published CLI / MCP (outside monorepo) | `impact-nova@^2.5.5` from npm (`latest` tag) |\n| Inside impact-nova monorepo | `file:` link to repo root |\n\n```bash\nnpx create-impact-nova my-dashboard\ncd my-dashboard\nnpm run dev\n```\n\nMCP: **`scaffold_impact_nova_app`** with `projectName` and optional `modules[]` from the user prompt.\n\n**Overrides:** CLI `--from-npm` · `--link-monorepo` · MCP `usePublishedPackages: true | false`\n\n```bash\nnpx create-impact-nova my-dashboard --from-npm\n```\n\nBase template is shell-only (Home + shared primitives). Feature pages come from recipes — see `create-impact-nova/recipes/README.md`.\n\n**Local link in an existing app** (manual):\n\n```bash\nnpm install impact-nova@file:../path-to-impact-nova-repo\n```\n\nRun `npm run build` in the impact-nova repo after design-system changes.\n\n## 1. Install the package and peer dependencies\n\n```bash\nnpm install impact-nova impact-nova-icons\nnpm install react@^19 react-dom@^19\n```\n\n**Required peers:** `react@^19`, `react-dom@^19`, `impact-nova-icons@^0.1.1`\n\n**Optional peers** (install when you use these features):\n\n| Package | Version | When needed |\n|---------|---------|-------------|\n| `ag-grid-community` | `36.0.1` | AG Grid types/API (pin with react + enterprise) |\n| `ag-grid-react` | `36.0.1` | DataTable / AG Grid |\n| `ag-grid-enterprise` | `36.0.1` | Enterprise grid features |\n| `highcharts` | `^12` | Chart component |\n| `highcharts-react-official` | `^3` | Chart component |\n| `highcharts-border-radius` | `^0.0.4` | Rounded chart corners |\n\nIf you use AG Grid or Highcharts in your app, also install:\n\n```bash\nnpm install ag-grid-community@36.0.1 ag-grid-react@36.0.1 ag-grid-enterprise@36.0.1\n# Optional, for charts:\nnpm install highcharts@^12 highcharts-react-official@^3 highcharts-border-radius@^0.0.4\n```\n\n## 2. Import styles in your root entry\n\nIn your app root (e.g. `main.tsx`, `App.tsx`, or `layout.tsx`), **import the CSS before your app component**:\n\n```tsx\nimport 'impact-nova/dist/impact-nova.css';\nimport App from './App';\n// ... rest of your bootstrap\n```\n\n## 3. Add Manrope font (recommended)\n\nIn your `index.html` or layout:\n\n```html\n<link href=\"https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap\" rel=\"stylesheet\" />\n```\n\nIn your global CSS or Tailwind base:\n\n```css\n@layer base {\n body {\n font-family: 'Manrope', sans-serif;\n }\n}\n```\n\n## 4. Wrap your app with providers (recommended)\n\nMount **`ImpactNovaProviders`** once at the app root. It bundles i18n (`ImpactNovaI18nProvider`) and `TooltipProvider` (required for tooltips since v2.0.8):\n\n```tsx\nimport { ImpactNovaProviders } from 'impact-nova/form';\n\nfunction Root() {\n return (\n <ImpactNovaProviders locale=\"en\">\n <App />\n </ImpactNovaProviders>\n );\n}\n```\n\nFor another locale, pass a locale pack:\n\n```tsx\nimport { ImpactNovaProviders } from 'impact-nova/form';\nimport { de } from 'impact-nova/locale/de';\n\n<ImpactNovaProviders locale=\"de\" messages={de}>\n <App />\n</ImpactNovaProviders>\n```\n\n**Barrel exception:** locale packs may use `import { de } from 'impact-nova'`. All UI components still use subpaths (see §5).\n\n## 5. Subpath imports (recommended)\n\nPrefer subpath imports in feature code for tree-shaking:\n\n```tsx\nimport { Button } from 'impact-nova/button';\nimport { Card, CardContent } from 'impact-nova/card';\nimport { DataTable, DataTableContent, useDataTable } from 'impact-nova/data-table';\nimport { CheckCircle } from 'impact-nova-icons';\n```\n\nThe barrel `import { Button } from 'impact-nova'` still works but pulls a larger module graph. **Use subpaths for all UI components**; reserve the barrel for locale packs at app root only. Use `ImpactNovaProviders` from `impact-nova/form` for app setup.\n\n## 6. Using Impact Nova with CSS or SCSS (no Tailwind)\n\nIf your app uses **plain CSS or SCSS** and does **not** use Tailwind, you can still use Impact Nova. Tailwind is optional. Impact Nova ships a single built CSS file (no SCSS source).\n\n- **Import the library CSS** in your app root (e.g. `main.tsx`, `App.tsx`):\n ```tsx\n import 'impact-nova/dist/impact-nova.css';\n ```\n **CSS split exports** (optional, for layered theming): `impact-nova/impact-nova-tokens.scss`, `impact-nova/impact-nova-base.scss`, `impact-nova/impact-nova-components.css`\n Or from your main stylesheet: `@import 'impact-nova/dist/impact-nova.css';` in your main.css or main.scss.\n- **Component styling** comes from Impact Nova's CSS. Use each component's `variant` and `size` props; no Tailwind classes are required.\n- **Your layout and spacing** stay in your CSS or SCSS (margins, padding, flexbox, grid). Use your usual class names; the design system does not require Tailwind utilities.\n- **Manrope font:** Add the font link in `index.html` and in your CSS/SCSS set `body { font-family: 'Manrope', sans-serif; }` (see section 3).\n- **Summary:** No Tailwind, no Tailwind config. Load `impact-nova.css` once; use components with their props; use your existing CSS/SCSS for the rest.\n\n## 6b. Theming in consumer apps\n\n| Surface | What ships |\n|---------|------------|\n| **npm / consumer apps** | **Impact Light** only — `import 'impact-nova/dist/impact-nova.css'` (from `src/theme/tokens/light.json`) |\n| **Storybook / dev** | 10 curated **theme presets** (Impact Dark, Midnight, Ocean, …) — preview switcher only |\n\n**Do not** copy Storybook preset JSON or `theme-presets.ts` into consumer apps. Presets are not in the published package.\n\n**Custom branding:** override CSS variables on `:root` or a scoped class (e.g. `.my-brand`). Use Storybook **Theme Builder** / **Token Catalog** to explore tokens, then export CSS/JSON for your overrides.\n\n## 7. Using Impact Nova with Webpack\n\nIf your app is built with **Webpack** (including Create React App, which uses Webpack):\n\n- **CSS import:** Webpack will bundle the library CSS as long as you have a rule for `.css`. Ensure your config includes something like:\n ```js\n module: {\n rules: [\n {\n test: /\\.css$/,\n use: ['style-loader', 'css-loader'],\n // or with MiniCssExtractPlugin:\n // use: [MiniCssExtractPlugin.loader, 'css-loader'],\n },\n // ... other rules (e.g. for .tsx, .js)\n ],\n },\n ```\n Then in your root component or entry:\n ```tsx\n import 'impact-nova/dist/impact-nova.css';\n ```\n- **Create React App (CRA):** No extra config. Add `import 'impact-nova/dist/impact-nova.css';` in `index.tsx` or `App.tsx`.\n- **Dedupe React / AG Grid:** If you see “multiple copies of React” or AG Grid issues, use Webpack’s `resolve.alias` so the app uses a single version:\n ```js\n resolve: {\n alias: {\n react: path.resolve(__dirname, 'node_modules/react'),\n 'react-dom': path.resolve(__dirname, 'node_modules/react-dom'),\n // If using AG Grid:\n 'ag-grid-react': path.resolve(__dirname, 'node_modules/ag-grid-react'),\n 'ag-grid-community': path.resolve(__dirname, 'node_modules/ag-grid-community'),\n 'ag-grid-enterprise': path.resolve(__dirname, 'node_modules/ag-grid-enterprise'),\n },\n },\n ```\n- **Tailwind + Webpack:** If you use Tailwind, add the Impact Nova preset and include the package in `content` (see section 7 below).\n\n## 8. Optional: extend Tailwind with Impact Nova preset\n\nIf your project uses Tailwind and you want the same theme (colors, radius), extend your `tailwind.config.js` with the preset from the package:\n\n```js\n// tailwind.config.js\nimport impactNovaPreset from 'impact-nova/tailwind.config.js';\n// → dist/tailwind.config.js (bundled theme; no package src/ required)\n\nexport default {\n presets: [impactNovaPreset],\n content: [\n './index.html',\n './src/**/*.{js,ts,jsx,tsx}',\n './node_modules/impact-nova/dist/**/*.js',\n ],\n // ... rest of your config\n};\n```\n\n## Summary checklist\n\n- [ ] `npm install impact-nova impact-nova-icons` (and react, react-dom; optional: ag-grid, highcharts)\n- [ ] `import 'impact-nova/dist/impact-nova.css'` in root entry (or @import in main.css/main.scss if using CSS or SCSS without Tailwind; see §6)\n- [ ] Add Manrope font link and body font-family\n- [ ] Wrap app with `<ImpactNovaProviders locale=\"en\">` from `impact-nova/form`\n- [ ] Use subpath imports in feature code (see §5)\n- [ ] (Optional) Add Tailwind preset and content path for impact-nova\n- [ ] **Webpack:** Ensure a CSS rule (style-loader + css-loader) and, if needed, resolve.alias for React/AG Grid\n\nAfter this, import components via subpaths: `import { Button } from 'impact-nova/button';`\n\n## 9. Dashboard app shell (optional)\n\nTo scaffold a full dashboard (sidebar, header, breadcrumb, filters), read resource **`impact-nova://layout`** or call `get_real_world_patterns` with `topic: \"layout\"`. Use `Layout` from `impact-nova/layout` — not `DynamicLayout` (grid/flex utility only).\n";
@@ -1 +1 @@
1
- export default "# Impact Nova — baseline\n\nUse **Impact Nova** design-system components and tokens. Prefer subpath imports (e.g. `impact-nova/button`) when you only need a few modules. For live component lists, specs, and codegen, use the **impact-nova-mcp** MCP server (see npm `impact-nova-mcp`). Browse **Storybook**: https://impact-nova.iaproducts.ai/\n\n## Peer dependency summary\n\n```json\n{\n \"impactNova\": {\n \"package\": \"impact-nova\",\n \"recommendedVersion\": \"2.5.4\",\n \"recommendedDistTag\": \"latest\",\n \"description\": \"Design system package — ESM with 90+ subpath exports. Install: npm install impact-nova@latest\"\n },\n \"createImpactNova\": {\n \"package\": \"create-impact-nova\",\n \"recommendedVersion\": \"^1.4.7\",\n \"description\": \"Vite + React scaffold with recipe-based modules\"\n },\n \"localDevelopment\": {\n \"defaultScaffoldDependency\": \"auto\",\n \"description\": \"create-impact-nova auto-detects: file: link when run inside the impact-nova monorepo; npm (impact-nova@^2.5.4) otherwise. CLI: --from-npm or --link-monorepo to override. Rebuild impact-nova (npm run build) after DS changes when using file: link.\",\n \"cliFlagForNpm\": \"--from-npm\",\n \"cliFlagForMonorepo\": \"--link-monorepo\",\n \"mcpScaffoldFlag\": \"usePublishedPackages: true | false (omit for auto-detect)\"\n },\n \"mandatoryRules\": {\n \"componentsOnly\": \"Use Impact Nova components only — never create new custom UI components\",\n \"tables\": \"Any table/grid/spreadsheet → DataTable from impact-nova/data-table (not HTML table, not raw ag-grid-react)\",\n \"validateBeforeDone\": \"Call validate_snippet on generated UI code\",\n \"resource\": \"impact-nova://design-system-mandate\"\n },\n \"requiredPeers\": [\n {\n \"package\": \"react\",\n \"recommendedVersion\": \"^19.0.0\",\n \"description\": \"React 19 required\"\n },\n {\n \"package\": \"react-dom\",\n \"recommendedVersion\": \"^19.0.0\",\n \"description\": \"React DOM 19 required\"\n },\n {\n \"package\": \"impact-nova-icons\",\n \"recommendedVersion\": \">=0.1.0\",\n \"description\": \"Icons peer — not bundled in impact-nova; 0.1.x and 0.2.x supported\"\n }\n ],\n \"optionalPeers\": [\n {\n \"package\": \"ag-grid-community\",\n \"recommendedVersion\": \"36.0.1\",\n \"description\": \"AG Grid community types/API; pin to the same version as ag-grid-react\"\n },\n {\n \"package\": \"ag-grid-react\",\n \"recommendedVersion\": \"36.0.1\",\n \"description\": \"For DataTable and grid components; use exact version to match Impact Nova\"\n },\n {\n \"package\": \"ag-grid-enterprise\",\n \"recommendedVersion\": \"36.0.1\",\n \"description\": \"Required if using ag-grid-react with enterprise features\"\n },\n {\n \"package\": \"highcharts\",\n \"recommendedVersion\": \"^12.0.0\",\n \"description\": \"For Chart component\"\n },\n {\n \"package\": \"highcharts-react-official\",\n \"recommendedVersion\": \"^3.0.0\",\n \"description\": \"For Chart component\"\n },\n {\n \"package\": \"highcharts-border-radius\",\n \"recommendedVersion\": \"^0.0.4\",\n \"description\": \"Optional Highcharts plugin for rounded corners\"\n }\n ]\n}\n```\n";
1
+ export default "# Impact Nova — baseline\n\nUse **Impact Nova** design-system components and tokens. Prefer subpath imports (e.g. `impact-nova/button`) when you only need a few modules. For live component lists, specs, and codegen, use the **impact-nova-mcp** MCP server (see npm `impact-nova-mcp`). Browse **Storybook**: https://impact-nova.iaproducts.ai/\n\n## Peer dependency summary\n\n```json\n{\n \"impactNova\": {\n \"package\": \"impact-nova\",\n \"recommendedVersion\": \"2.5.5\",\n \"recommendedDistTag\": \"latest\",\n \"description\": \"Design system package — ESM with 90+ subpath exports. Install: npm install impact-nova@latest\"\n },\n \"createImpactNova\": {\n \"package\": \"create-impact-nova\",\n \"recommendedVersion\": \"^1.4.7\",\n \"description\": \"Vite + React scaffold with recipe-based modules\"\n },\n \"localDevelopment\": {\n \"defaultScaffoldDependency\": \"auto\",\n \"description\": \"create-impact-nova auto-detects: file: link when run inside the impact-nova monorepo; npm (impact-nova@^2.5.5) otherwise. CLI: --from-npm or --link-monorepo to override. Rebuild impact-nova (npm run build) after DS changes when using file: link.\",\n \"cliFlagForNpm\": \"--from-npm\",\n \"cliFlagForMonorepo\": \"--link-monorepo\",\n \"mcpScaffoldFlag\": \"usePublishedPackages: true | false (omit for auto-detect)\"\n },\n \"mandatoryRules\": {\n \"componentsOnly\": \"Use Impact Nova components only — never create new custom UI components\",\n \"tables\": \"Any table/grid/spreadsheet → DataTable from impact-nova/data-table (not HTML table, not raw ag-grid-react)\",\n \"validateBeforeDone\": \"Call validate_snippet on generated UI code\",\n \"resource\": \"impact-nova://design-system-mandate\"\n },\n \"requiredPeers\": [\n {\n \"package\": \"react\",\n \"recommendedVersion\": \"^19.0.0\",\n \"description\": \"React 19 required\"\n },\n {\n \"package\": \"react-dom\",\n \"recommendedVersion\": \"^19.0.0\",\n \"description\": \"React DOM 19 required\"\n },\n {\n \"package\": \"impact-nova-icons\",\n \"recommendedVersion\": \">=0.1.0\",\n \"description\": \"Icons peer — not bundled in impact-nova; 0.1.x and 0.2.x supported\"\n }\n ],\n \"optionalPeers\": [\n {\n \"package\": \"ag-grid-community\",\n \"recommendedVersion\": \"36.0.1\",\n \"description\": \"AG Grid community types/API; pin to the same version as ag-grid-react\"\n },\n {\n \"package\": \"ag-grid-react\",\n \"recommendedVersion\": \"36.0.1\",\n \"description\": \"For DataTable and grid components; use exact version to match Impact Nova\"\n },\n {\n \"package\": \"ag-grid-enterprise\",\n \"recommendedVersion\": \"36.0.1\",\n \"description\": \"Required if using ag-grid-react with enterprise features\"\n },\n {\n \"package\": \"highcharts\",\n \"recommendedVersion\": \"^12.0.0\",\n \"description\": \"For Chart component\"\n },\n {\n \"package\": \"highcharts-react-official\",\n \"recommendedVersion\": \"^3.0.0\",\n \"description\": \"For Chart component\"\n },\n {\n \"package\": \"highcharts-border-radius\",\n \"recommendedVersion\": \"^0.0.4\",\n \"description\": \"Optional Highcharts plugin for rounded corners\"\n }\n ]\n}\n```\n";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impact-nova",
3
- "version": "2.5.4",
3
+ "version": "2.5.5",
4
4
  "description": "Enterprise-grade React design system built with React 19, Vite, Tailwind CSS, and Radix UI. Built-in internationalization (i18n) and comprehensive UI component library for scalable, accessible, and performant applications.",
5
5
  "type": "module",
6
6
  "workspaces": [