impact-nova 2.2.4 → 2.2.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.
@@ -4,5 +4,6 @@ export interface ExpandableListItemAttributesProps {
4
4
  title?: string;
5
5
  maxVisibleTags?: number;
6
6
  formatOverflow?: ExpandableListItemAttributesSection["formatOverflow"];
7
+ externalCopyFunction?: ExpandableListItemAttributesSection["externalCopyFunction"];
7
8
  }
8
- export declare function ExpandableListItemAttributes({ tags, title, maxVisibleTags, formatOverflow, }: ExpandableListItemAttributesProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function ExpandableListItemAttributes({ tags, title, maxVisibleTags, formatOverflow, externalCopyFunction, }: ExpandableListItemAttributesProps): import("react/jsx-runtime").JSX.Element;
@@ -1,64 +1,67 @@
1
1
  import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
- import { Badge as p } from "../../data-display/badge/badge.js";
3
- import { FilterPopoverContent as h } from "../../flows/filter-strip/filter-tag-list.js";
4
- import { Popover as u, PopoverTrigger as f } from "../../feedback/popover/popover.js";
5
- import { Tag as x } from "../../primitives/tag/tag.js";
6
- import { Tooltip as b, TooltipTrigger as g, TooltipContent as v } from "../../feedback/tooltip/tooltip.js";
2
+ import { Badge as s } from "../../data-display/badge/badge.js";
3
+ import { FilterPopoverContent as u } from "../../flows/filter-strip/filter-tag-list.js";
4
+ import { Popover as b, PopoverTrigger as f } from "../../feedback/popover/popover.js";
5
+ import { Tooltip as g, TooltipTrigger as v, TooltipContent as x } from "../../feedback/tooltip/tooltip.js";
6
+ import "react";
7
7
  function I({
8
- tags: n,
9
- title: i = "Attributes",
10
- maxVisibleTags: a = 4,
11
- formatOverflow: s
8
+ tags: o,
9
+ title: l = "Attributes",
10
+ maxVisibleTags: n = 4,
11
+ formatOverflow: c,
12
+ externalCopyFunction: m
12
13
  }) {
13
- const c = n.slice(0, a), t = n.slice(a), o = t.length, d = s?.(o) ?? (o > 0 ? `+${o}` : null);
14
+ const p = o.slice(0, n), t = o.slice(n), i = t.length, d = c?.(i) ?? (i > 0 ? `+${i}` : null);
14
15
  return /* @__PURE__ */ r(
15
16
  "div",
16
17
  {
17
18
  className: "px-4 py-4 pt-0 sm:px-5",
18
19
  "data-component": "expandable-list-item-attributes",
19
20
  children: [
20
- /* @__PURE__ */ e("p", { className: "text-xs font-semibold leading-5 text-content-heading", children: i }),
21
+ /* @__PURE__ */ e("p", { className: "text-xs font-semibold leading-5 text-content-heading", children: l }),
21
22
  /* @__PURE__ */ r("div", { className: "mt-2 flex flex-wrap gap-1.5", children: [
22
- c.map((l, m) => /* @__PURE__ */ e(
23
- p,
23
+ p.map((a, h) => /* @__PURE__ */ e(
24
+ s,
24
25
  {
25
26
  variant: "subtle",
26
27
  color: "neutral",
27
28
  size: "sm",
28
29
  shape: "circle",
29
30
  className: "max-w-full",
30
- children: l
31
+ children: a
31
32
  },
32
- `${m}-${l}`
33
+ `${h}-${a}`
33
34
  )),
34
- t.length > 0 ? /* @__PURE__ */ r(u, { children: [
35
- /* @__PURE__ */ r(b, { children: [
36
- /* @__PURE__ */ e(g, { asChild: !0, children: /* @__PURE__ */ e(f, { asChild: !0, children: /* @__PURE__ */ e(
37
- x,
35
+ t.length > 0 ? /* @__PURE__ */ r(b, { children: [
36
+ /* @__PURE__ */ r(g, { children: [
37
+ /* @__PURE__ */ e(v, { asChild: !0, children: /* @__PURE__ */ e(f, { asChild: !0, children: /* @__PURE__ */ e(
38
+ s,
38
39
  {
39
- variant: "secondary",
40
- size: "md",
41
- shape: "rounded",
42
- className: "h-6 cursor-pointer whitespace-nowrap border-0 bg-accent px-2 font-['Manrope'] text-xs font-medium text-accent-foreground hover:bg-accent/80",
40
+ variant: "subtle",
41
+ color: "primary",
42
+ size: "sm",
43
+ shape: "circle",
44
+ className: "cursor-pointer hover:bg-accent/80",
43
45
  tabIndex: 0,
44
46
  role: "button",
45
- "aria-label": `${t.length} more attributes for ${i}`,
47
+ "aria-label": `${t.length} more attributes for ${l}`,
46
48
  children: d
47
49
  }
48
50
  ) }) }),
49
- /* @__PURE__ */ r(v, { variant: "tertiary", side: "top", children: [
51
+ /* @__PURE__ */ r(x, { variant: "tertiary", side: "top", children: [
50
52
  t.length,
51
53
  " more"
52
54
  ] })
53
55
  ] }),
54
56
  /* @__PURE__ */ e(
55
- h,
57
+ u,
56
58
  {
57
59
  remainingValues: t,
58
60
  onItemRemove: () => {
59
61
  },
60
62
  isRemovable: !1,
61
- isCopyable: !0
63
+ isCopyable: !0,
64
+ externalCopyFunction: m
62
65
  }
63
66
  )
64
67
  ] }) : null
@@ -21,7 +21,7 @@ export declare const ExpandableListItemTrigger: React.ForwardRefExoticComponent<
21
21
  rightActions?: React.ReactNode;
22
22
  headingLevel?: import('../../..').AccordionHeadingLevel;
23
23
  variant?: "default" | "plain";
24
- renderChevronTooltip?: import('../../..').InfoTooltipRender;
24
+ renderChevronTooltip?: import('../../feedback/tooltip').InfoTooltipRender;
25
25
  } & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
26
26
  export declare const ExpandableListItemTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
27
27
  export declare const ExpandableListItemDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
@@ -1,83 +1,121 @@
1
- import { jsx as n, jsxs as v } from "react/jsx-runtime";
2
- import * as i from "react";
3
- import { ChevronRight as y } from "impact-nova-icons";
4
- import { AccordionContent as R, Accordion as A, AccordionItem as k, AccordionTrigger as T } from "../../primitives/accordion/accordion.js";
5
- import { Checkbox as P } from "../../forms/checkbox/checkbox.js";
6
- import { createCompoundPart as I } from "../../../lib/primitives/create-compound.js";
7
- import { cn as r } from "../../../lib/utils.js";
8
- import { useExpandableListItemContext as x, ExpandableListItemProvider as E, EXPANDABLE_LIST_ITEM_ACCORDION_VALUE as c } from "./expandable-list-item-context.js";
9
- function N(e, t) {
10
- return r(
1
+ import { jsx as n, jsxs as h } from "react/jsx-runtime";
2
+ import * as s from "react";
3
+ import { ChevronRight as R } from "impact-nova-icons";
4
+ import { AccordionContent as A, Accordion as O, AccordionItem as P, AccordionTrigger as V } from "../../primitives/accordion/accordion.js";
5
+ import { Checkbox as D } from "../../forms/checkbox/checkbox.js";
6
+ import { Tooltip as M, TooltipTrigger as S, TooltipContent as _ } from "../../feedback/tooltip/tooltip.js";
7
+ import { createCompoundPart as y } from "../../../lib/primitives/create-compound.js";
8
+ import { cn as d } from "../../../lib/utils.js";
9
+ import { useExpandableListItemContext as I, ExpandableListItemProvider as w, EXPANDABLE_LIST_ITEM_ACCORDION_VALUE as u } from "./expandable-list-item-context.js";
10
+ const g = s.forwardRef(
11
+ ({ text: e, componentName: t, className: o, ...r }, a) => {
12
+ const l = s.useRef(null), [c, x] = s.useState(!1), p = s.useCallback(
13
+ (i) => {
14
+ l.current = i, typeof a == "function" ? a(i) : a && (a.current = i);
15
+ },
16
+ [a]
17
+ ), m = s.useCallback(() => {
18
+ const i = l.current;
19
+ i && x(i.scrollWidth > i.clientWidth);
20
+ }, []);
21
+ s.useLayoutEffect(() => {
22
+ const i = l.current;
23
+ if (!i) return;
24
+ m();
25
+ const v = i.parentElement, f = new ResizeObserver(m);
26
+ return f.observe(i), v && f.observe(v), () => {
27
+ f.disconnect();
28
+ };
29
+ }, [e, m]);
30
+ const b = /* @__PURE__ */ n(
31
+ "span",
32
+ {
33
+ ref: p,
34
+ "data-component": t,
35
+ className: o,
36
+ ...r,
37
+ children: e
38
+ }
39
+ );
40
+ return /* @__PURE__ */ h(M, { open: c ? void 0 : !1, children: [
41
+ /* @__PURE__ */ n(S, { asChild: !0, children: b }),
42
+ /* @__PURE__ */ n(_, { side: "top", variant: "tertiary", children: e })
43
+ ] });
44
+ }
45
+ );
46
+ g.displayName = "TruncatedTooltipText";
47
+ function C(e, t) {
48
+ return d(
11
49
  "rounded-xl transition-[background-color,border-color,box-shadow] duration-200",
12
50
  e ? "border-stroke-accent/40 bg-canvas-accent shadow-sm" : "border-stroke bg-canvas-elevated",
13
51
  t
14
52
  );
15
53
  }
16
- function V(e) {
17
- return i.isValidElement(e) && e.type.displayName === "ExpandableListItemContent";
54
+ function z(e) {
55
+ return s.isValidElement(e) && e.type.displayName === "ExpandableListItemContent";
18
56
  }
19
- const D = i.forwardRef(
57
+ const j = s.forwardRef(
20
58
  ({
21
59
  className: e,
22
60
  selected: t,
23
- expanded: a,
24
- defaultExpanded: o = !1,
25
- onExpandedChange: s,
61
+ expanded: o,
62
+ defaultExpanded: r = !1,
63
+ onExpandedChange: a,
26
64
  disabled: l,
27
- expandAriaLabel: m = "Expand details",
28
- collapseAriaLabel: b = "Collapse details",
65
+ expandAriaLabel: c = "Expand details",
66
+ collapseAriaLabel: x = "Collapse details",
29
67
  children: p,
30
- ...f
31
- }, h) => {
32
- const d = !!t, L = i.Children.toArray(p).find(V) != null, u = i.useMemo(
68
+ ...m
69
+ }, b) => {
70
+ const i = !!t, L = s.Children.toArray(p).find(z) != null, E = s.useMemo(
33
71
  () => ({
34
- showSelectionChrome: d,
72
+ showSelectionChrome: i,
35
73
  disabled: l,
36
- expandAriaLabel: m,
37
- collapseAriaLabel: b
74
+ expandAriaLabel: c,
75
+ collapseAriaLabel: x
38
76
  }),
39
- [d, l, m, b]
77
+ [i, l, c, x]
40
78
  );
41
79
  if (!L)
42
- return /* @__PURE__ */ n(E, { value: u, children: /* @__PURE__ */ n(
80
+ return /* @__PURE__ */ n(w, { value: E, children: /* @__PURE__ */ n(
43
81
  "div",
44
82
  {
45
- ref: h,
83
+ ref: b,
46
84
  "data-component": "expandable-list-item-row",
47
85
  "data-expandable": "false",
48
86
  "data-selected": t ? "" : void 0,
49
- "data-selection-chrome": d ? "" : void 0,
50
- className: N(d, e),
51
- ...f,
87
+ "data-selection-chrome": i ? "" : void 0,
88
+ className: C(i, e),
89
+ ...m,
52
90
  children: p
53
91
  }
54
92
  ) });
55
- const g = a !== void 0, C = g ? a ? c : "" : void 0;
56
- return /* @__PURE__ */ n(E, { value: u, children: /* @__PURE__ */ n(
93
+ const N = o !== void 0, T = N ? o ? u : "" : void 0;
94
+ return /* @__PURE__ */ n(w, { value: E, children: /* @__PURE__ */ n(
57
95
  "div",
58
96
  {
59
- ref: h,
97
+ ref: b,
60
98
  "data-component": "expandable-list-item",
61
99
  "data-expandable": "true",
62
- "data-expanded": a ?? void 0,
100
+ "data-expanded": o ?? void 0,
63
101
  "data-selected": t ? "" : void 0,
64
- "data-selection-chrome": d ? "" : void 0,
65
- className: N(d, e),
66
- ...f,
102
+ "data-selection-chrome": i ? "" : void 0,
103
+ className: C(i, e),
104
+ ...m,
67
105
  children: /* @__PURE__ */ n(
68
- A,
106
+ O,
69
107
  {
70
108
  type: "single",
71
109
  collapsible: !0,
72
110
  disabled: l,
73
- ...g ? { value: C } : {
74
- defaultValue: o ? c : void 0
111
+ ...N ? { value: T } : {
112
+ defaultValue: r ? u : void 0
75
113
  },
76
- onValueChange: (w) => s?.(w === c),
114
+ onValueChange: (k) => a?.(k === u),
77
115
  children: /* @__PURE__ */ n(
78
- k,
116
+ P,
79
117
  {
80
- value: c,
118
+ value: u,
81
119
  className: "overflow-visible rounded-none border-0 bg-transparent p-0 shadow-none",
82
120
  children: p
83
121
  }
@@ -88,146 +126,169 @@ const D = i.forwardRef(
88
126
  ) });
89
127
  }
90
128
  );
91
- D.displayName = "ExpandableListItemRoot";
92
- const W = I("expandable-list-item", {
129
+ j.displayName = "ExpandableListItemRoot";
130
+ const te = y("expandable-list-item", {
93
131
  part: "row",
94
132
  displayName: "ExpandableListItemRow",
95
- className: "flex items-start gap-3 px-3 py-3"
96
- }), M = i.forwardRef(({ className: e, onCheckedChange: t, ...a }, o) => /* @__PURE__ */ n(
133
+ className: "flex items-start gap-2 px-3 py-3"
134
+ }), B = s.forwardRef(({ className: e, onCheckedChange: t, ...o }, r) => /* @__PURE__ */ n(
97
135
  "div",
98
136
  {
99
- className: r("pt-0.5", e),
137
+ className: d("mt-1 shrink-0", e),
100
138
  "data-component": "expandable-list-item-checkbox",
101
- onClick: (s) => s.stopPropagation(),
102
- onKeyDown: (s) => s.stopPropagation(),
139
+ onClick: (a) => a.stopPropagation(),
140
+ onKeyDown: (a) => a.stopPropagation(),
103
141
  children: /* @__PURE__ */ n(
104
- P,
142
+ D,
105
143
  {
106
- ref: o,
107
- onCheckedChange: (s) => t?.(s === !0),
108
- ...a
144
+ ref: r,
145
+ onCheckedChange: (a) => t?.(a === !0),
146
+ ...o
109
147
  }
110
148
  )
111
149
  }
112
150
  ));
113
- M.displayName = "ExpandableListItemCheckbox";
114
- const S = i.forwardRef(({ className: e, children: t, ...a }, o) => {
115
- const { disabled: s, expandAriaLabel: l, collapseAriaLabel: m } = x();
116
- return /* @__PURE__ */ v(
117
- T,
151
+ B.displayName = "ExpandableListItemCheckbox";
152
+ const F = s.forwardRef(({ className: e, children: t, ...o }, r) => {
153
+ const { disabled: a, expandAriaLabel: l, collapseAriaLabel: c } = I();
154
+ return /* @__PURE__ */ h(
155
+ V,
118
156
  {
119
- ref: o,
157
+ ref: r,
120
158
  variant: "plain",
121
159
  "data-component": "expandable-list-item-trigger",
122
- className: r(
123
- "min-w-0 items-center gap-2 text-left",
124
- s && "pointer-events-none opacity-50",
160
+ className: d(
161
+ "min-w-0 flex-1 overflow-hidden items-start gap-1 text-left",
162
+ a && "pointer-events-none opacity-50",
125
163
  e
126
164
  ),
127
- disabled: s,
128
- ...a,
165
+ disabled: a,
166
+ ...o,
129
167
  children: [
130
168
  t,
131
169
  /* @__PURE__ */ n(
132
170
  "span",
133
171
  {
134
- className: "mt-0.5 inline-flex shrink-0 text-content-icon transition-transform duration-200 motion-reduce:transition-none group-data-[state=open]:rotate-180",
172
+ className: "mt-1 inline-flex shrink-0 text-content-icon transition-transform duration-200 motion-reduce:transition-none group-data-[state=open]:rotate-180",
135
173
  "aria-hidden": !0,
136
- children: /* @__PURE__ */ n(y, { className: "size-4 rotate-90" })
174
+ children: /* @__PURE__ */ n(R, { className: "size-4 rotate-90" })
137
175
  }
138
176
  ),
139
- /* @__PURE__ */ v("span", { className: "sr-only", children: [
177
+ /* @__PURE__ */ h("span", { className: "sr-only", children: [
140
178
  l,
141
179
  " / ",
142
- m
180
+ c
143
181
  ] })
144
182
  ]
145
183
  }
146
184
  );
147
185
  });
148
- S.displayName = "ExpandableListItemTrigger";
149
- const _ = i.forwardRef(({ className: e, ...t }, a) => {
150
- const { showSelectionChrome: o } = x();
151
- return /* @__PURE__ */ n(
186
+ F.displayName = "ExpandableListItemTrigger";
187
+ const H = s.forwardRef(({ className: e, children: t, ...o }, r) => {
188
+ const a = d(
189
+ "block min-w-0 w-0 flex-1 truncate text-sm font-semibold leading-6 tracking-tight text-content",
190
+ e
191
+ );
192
+ return typeof t != "string" ? /* @__PURE__ */ n(
152
193
  "span",
153
194
  {
154
- ref: a,
195
+ ref: r,
155
196
  "data-component": "expandable-list-item-title",
156
- className: r(
157
- "text-sm font-semibold leading-6 text-content",
158
- o && "tracking-tight",
159
- e
160
- ),
161
- ...t
197
+ className: a,
198
+ ...o,
199
+ children: t
200
+ }
201
+ ) : /* @__PURE__ */ n(
202
+ g,
203
+ {
204
+ ref: r,
205
+ text: t,
206
+ componentName: "expandable-list-item-title",
207
+ className: a,
208
+ ...o
162
209
  }
163
210
  );
164
211
  });
165
- _.displayName = "ExpandableListItemTitle";
166
- const j = i.forwardRef(({ className: e, ...t }, a) => /* @__PURE__ */ n(
167
- "div",
168
- {
169
- ref: a,
170
- "data-component": "expandable-list-item-description",
171
- className: r("mt-0.5 text-xs font-medium leading-4 text-secondary-foreground", e),
172
- ...t
173
- }
174
- ));
175
- j.displayName = "ExpandableListItemDescription";
176
- const B = i.forwardRef(({ className: e, ...t }, a) => /* @__PURE__ */ n(
212
+ H.displayName = "ExpandableListItemTitle";
213
+ const W = s.forwardRef(({ className: e, children: t, ...o }, r) => {
214
+ const a = d(
215
+ "mt-1 block min-w-0 w-full truncate text-xs font-medium leading-4 text-secondary-foreground",
216
+ e
217
+ );
218
+ return typeof t == "string" ? /* @__PURE__ */ n(
219
+ g,
220
+ {
221
+ text: t,
222
+ componentName: "expandable-list-item-description",
223
+ className: a
224
+ }
225
+ ) : /* @__PURE__ */ n(
226
+ "div",
227
+ {
228
+ ref: r,
229
+ "data-component": "expandable-list-item-description",
230
+ className: a,
231
+ ...o,
232
+ children: t
233
+ }
234
+ );
235
+ });
236
+ W.displayName = "ExpandableListItemDescription";
237
+ const K = s.forwardRef(({ className: e, ...t }, o) => /* @__PURE__ */ n(
177
238
  "div",
178
239
  {
179
- ref: a,
240
+ ref: o,
180
241
  "data-component": "expandable-list-item-media",
181
- className: r("flex flex-wrap items-center gap-2", e),
242
+ className: d("flex min-w-0 flex-1 flex-nowrap items-center gap-2 overflow-hidden", e),
182
243
  ...t
183
244
  }
184
245
  ));
185
- B.displayName = "ExpandableListItemMedia";
186
- const F = i.forwardRef(({ className: e, ...t }, a) => {
187
- const { disabled: o } = x();
246
+ K.displayName = "ExpandableListItemMedia";
247
+ const U = s.forwardRef(({ className: e, ...t }, o) => {
248
+ const { disabled: r } = I();
188
249
  return /* @__PURE__ */ n(
189
250
  "div",
190
251
  {
191
- ref: a,
252
+ ref: o,
192
253
  "data-component": "expandable-list-item-header",
193
- className: r(
194
- "min-w-0 flex-1",
195
- o && "pointer-events-none opacity-50",
254
+ className: d(
255
+ "min-w-0 w-full flex-1 overflow-hidden",
256
+ r && "pointer-events-none opacity-50",
196
257
  e
197
258
  ),
198
259
  ...t
199
260
  }
200
261
  );
201
262
  });
202
- F.displayName = "ExpandableListItemHeader";
203
- const H = i.forwardRef(({ className: e, children: t, ...a }, o) => /* @__PURE__ */ n(R, { className: "border-0 bg-transparent p-0 pb-[0.01rem]", children: /* @__PURE__ */ n(
263
+ U.displayName = "ExpandableListItemHeader";
264
+ const X = s.forwardRef(({ className: e, children: t, ...o }, r) => /* @__PURE__ */ n(A, { className: "border-0 bg-transparent p-0 pb-[0.01rem]", children: /* @__PURE__ */ n(
204
265
  "div",
205
266
  {
206
- ref: o,
267
+ ref: r,
207
268
  "data-component": "expandable-list-item-content",
208
- className: r(
269
+ className: d(
209
270
  "mx-2 mb-2 overflow-hidden rounded-lg bg-canvas-subtle pt-2",
210
271
  e
211
272
  ),
212
- ...a,
273
+ ...o,
213
274
  children: t
214
275
  }
215
276
  ) }));
216
- H.displayName = "ExpandableListItemContent";
217
- const Y = I("expandable-list-item", {
277
+ X.displayName = "ExpandableListItemContent";
278
+ const ae = y("expandable-list-item", {
218
279
  part: "footer",
219
280
  displayName: "ExpandableListItemFooter",
220
281
  className: "px-4 py-3 sm:px-5"
221
282
  });
222
283
  export {
223
- M as ExpandableListItemCheckbox,
224
- H as ExpandableListItemContent,
225
- j as ExpandableListItemDescription,
226
- Y as ExpandableListItemFooter,
227
- F as ExpandableListItemHeader,
228
- B as ExpandableListItemMedia,
229
- D as ExpandableListItemRoot,
230
- W as ExpandableListItemRow,
231
- _ as ExpandableListItemTitle,
232
- S as ExpandableListItemTrigger
284
+ B as ExpandableListItemCheckbox,
285
+ X as ExpandableListItemContent,
286
+ W as ExpandableListItemDescription,
287
+ ae as ExpandableListItemFooter,
288
+ U as ExpandableListItemHeader,
289
+ K as ExpandableListItemMedia,
290
+ j as ExpandableListItemRoot,
291
+ te as ExpandableListItemRow,
292
+ H as ExpandableListItemTitle,
293
+ F as ExpandableListItemTrigger
233
294
  };
@@ -1,13 +1,13 @@
1
1
  import { jsx as l, jsxs as d } from "react/jsx-runtime";
2
- import * as R from "react";
3
- import { ExpandableListItemAttributes as T } from "./expandable-list-item-attributes.js";
4
- import { ExpandableListItemMetrics as v } from "./expandable-list-item-metrics.js";
5
- import { ExpandableListItemRoot as f, ExpandableListItemRow as o, ExpandableListItemCheckbox as C, ExpandableListItemHeader as E, ExpandableListItemMedia as I, ExpandableListItemTitle as k, ExpandableListItemDescription as L, ExpandableListItemTrigger as y, ExpandableListItemContent as j, ExpandableListItemFooter as M } from "./expandable-list-item-parts.js";
2
+ import * as P from "react";
3
+ import { ExpandableListItemAttributes as R } from "./expandable-list-item-attributes.js";
4
+ import { ExpandableListItemMetrics as T } from "./expandable-list-item-metrics.js";
5
+ import { ExpandableListItemRoot as o, ExpandableListItemRow as f, ExpandableListItemCheckbox as C, ExpandableListItemHeader as E, ExpandableListItemMedia as I, ExpandableListItemTitle as k, ExpandableListItemDescription as L, ExpandableListItemTrigger as v, ExpandableListItemContent as j, ExpandableListItemFooter as M } from "./expandable-list-item-parts.js";
6
6
  function O(e) {
7
7
  switch (e.type) {
8
8
  case "metrics":
9
9
  return /* @__PURE__ */ l(
10
- v,
10
+ T,
11
11
  {
12
12
  sectionId: e.id,
13
13
  columns: e.columns
@@ -16,12 +16,13 @@ function O(e) {
16
16
  );
17
17
  case "attributes":
18
18
  return /* @__PURE__ */ l(
19
- T,
19
+ R,
20
20
  {
21
21
  title: e.title,
22
22
  tags: e.tags,
23
23
  maxVisibleTags: e.maxVisibleTags,
24
- formatOverflow: e.formatOverflow
24
+ formatOverflow: e.formatOverflow,
25
+ externalCopyFunction: e.externalCopyFunction
25
26
  },
26
27
  e.id
27
28
  );
@@ -34,7 +35,7 @@ function O(e) {
34
35
  function V({ section: e }) {
35
36
  return /* @__PURE__ */ l("div", { className: "px-4 py-4 sm:px-5", children: e.content });
36
37
  }
37
- const $ = R.forwardRef(
38
+ const $ = P.forwardRef(
38
39
  ({
39
40
  className: e,
40
41
  title: t,
@@ -43,31 +44,31 @@ const $ = R.forwardRef(
43
44
  selection: a,
44
45
  selected: g,
45
46
  expanded: w,
46
- defaultExpanded: S = !1,
47
- onExpandedChange: P,
47
+ defaultExpanded: y = !1,
48
+ onExpandedChange: S,
48
49
  disabled: c,
49
50
  sections: i,
50
51
  panelFooter: h,
51
- expandAriaLabel: s = "Expand details",
52
- collapseAriaLabel: u = "Collapse details",
53
- ...b
54
- }, p) => {
52
+ expandAriaLabel: u = "Expand details",
53
+ collapseAriaLabel: s = "Collapse details",
54
+ ...p
55
+ }, b) => {
55
56
  const x = !!(g || a?.checked);
56
57
  return i != null && i.length > 0 || h != null ? /* @__PURE__ */ d(
57
- f,
58
+ o,
58
59
  {
59
- ref: p,
60
+ ref: b,
60
61
  className: e,
61
62
  selected: x,
62
63
  expanded: w,
63
- defaultExpanded: S,
64
- onExpandedChange: P,
64
+ defaultExpanded: y,
65
+ onExpandedChange: S,
65
66
  disabled: c,
66
- expandAriaLabel: s,
67
- collapseAriaLabel: u,
68
- ...b,
67
+ expandAriaLabel: u,
68
+ collapseAriaLabel: s,
69
+ ...p,
69
70
  children: [
70
- /* @__PURE__ */ d(o, { children: [
71
+ /* @__PURE__ */ d(f, { children: [
71
72
  a ? /* @__PURE__ */ l(
72
73
  C,
73
74
  {
@@ -79,7 +80,7 @@ const $ = R.forwardRef(
79
80
  "aria-label": a["aria-label"] ?? `Select ${t}`
80
81
  }
81
82
  ) : null,
82
- /* @__PURE__ */ l(y, { children: /* @__PURE__ */ d(E, { children: [
83
+ /* @__PURE__ */ l(v, { children: /* @__PURE__ */ d(E, { children: [
83
84
  /* @__PURE__ */ d(I, { children: [
84
85
  /* @__PURE__ */ l(k, { children: t }),
85
86
  m
@@ -94,16 +95,16 @@ const $ = R.forwardRef(
94
95
  ]
95
96
  }
96
97
  ) : /* @__PURE__ */ l(
97
- f,
98
+ o,
98
99
  {
99
- ref: p,
100
+ ref: b,
100
101
  className: e,
101
102
  selected: x,
102
103
  disabled: c,
103
- expandAriaLabel: s,
104
- collapseAriaLabel: u,
105
- ...b,
106
- children: /* @__PURE__ */ d(o, { children: [
104
+ expandAriaLabel: u,
105
+ collapseAriaLabel: s,
106
+ ...p,
107
+ children: /* @__PURE__ */ d(f, { children: [
107
108
  a ? /* @__PURE__ */ l(
108
109
  C,
109
110
  {
@@ -1,4 +1,9 @@
1
- import { ReactNode } from 'react';
1
+ import { default as React, ReactNode } from 'react';
2
+ export interface ExternalCopyFunctionProps {
3
+ e: React.MouseEvent<HTMLButtonElement>;
4
+ val: string | number;
5
+ index: number;
6
+ }
2
7
  export type ExpandableListItemMetricColumn = {
3
8
  label: string;
4
9
  value: string;
@@ -19,6 +24,8 @@ export type ExpandableListItemAttributesSection = {
19
24
  maxVisibleTags?: number;
20
25
  /** Default: `(n) => \`+\${n}\``. */
21
26
  formatOverflow?: (hiddenCount: number) => string;
27
+ /** Override the default clipboard copy inside the overflow popover. */
28
+ externalCopyFunction?: (props: ExternalCopyFunctionProps) => void;
22
29
  };
23
30
  /** Arbitrary block inside the expanded panel. */
24
31
  export type ExpandableListItemCustomSection = {
@@ -2,4 +2,4 @@ export { ExpandableListItem, type ExpandableListItemProps, } from './expandable-
2
2
  export { ExpandableListItemRoot, ExpandableListItemRow, ExpandableListItemCheckbox, ExpandableListItemTrigger, ExpandableListItemTitle, ExpandableListItemDescription, ExpandableListItemMedia, ExpandableListItemHeader, ExpandableListItemContent, ExpandableListItemFooter, type ExpandableListItemRootProps, type ExpandableListItemCheckboxProps, } from './expandable-list-item-parts';
3
3
  export { ExpandableListItemMetrics, type ExpandableListItemMetricsProps } from './expandable-list-item-metrics';
4
4
  export { ExpandableListItemAttributes, type ExpandableListItemAttributesProps, } from './expandable-list-item-attributes';
5
- export type { ExpandableListItemAttributesSection, ExpandableListItemCustomSection, ExpandableListItemMetricColumn, ExpandableListItemMetricsSection, ExpandableListItemSelection, ExpandableListItemSection, } from './expandable-list-item.types';
5
+ export type { ExternalCopyFunctionProps, ExpandableListItemAttributesSection, ExpandableListItemCustomSection, ExpandableListItemMetricColumn, ExpandableListItemMetricsSection, ExpandableListItemSelection, ExpandableListItemSection, } from './expandable-list-item.types';
@@ -1,6 +1,7 @@
1
1
  import { jsxs as t, jsx as e } from "react/jsx-runtime";
2
2
  import { Tooltip as l, TooltipTrigger as n, TooltipContent as o } from "./tooltip.js";
3
- const d = (i, r, a) => /* @__PURE__ */ t(l, { children: [
3
+ import "react";
4
+ const p = (i, r, a) => /* @__PURE__ */ t(l, { children: [
4
5
  /* @__PURE__ */ e(n, { asChild: !0, children: /* @__PURE__ */ e("span", { className: "inline-flex items-center justify-center h-full w-full", children: i }) }),
5
6
  /* @__PURE__ */ e(o, { variant: "tertiary", className: a, children: r })
6
7
  ] }), h = (i, r) => /* @__PURE__ */ t(l, { children: [
@@ -9,5 +10,5 @@ const d = (i, r, a) => /* @__PURE__ */ t(l, { children: [
9
10
  ] });
10
11
  export {
11
12
  h as defaultAccordionTooltipRender,
12
- d as defaultTabTooltipRender
13
+ p as defaultTabTooltipRender
13
14
  };
@@ -7,18 +7,18 @@ import { Tooltip as b, TooltipTrigger as w, TooltipContent as y } from "../../fe
7
7
  import { PopoverContent as $, Popover as O, PopoverTrigger as j } from "../../feedback/popover/popover.js";
8
8
  import { Button as P } from "../../primitives/button/button.js";
9
9
  import { Checkmark as A, Copy as R, Cross as F } from "impact-nova-icons";
10
- const T = "whitespace-nowrap bg-accent text-accent-foreground hover:bg-accent/80 border-0 px-2 text-xs font-medium font-['Manrope'] cursor-pointer focus:!ring-inset focus:!ring-offset-0 focus:!ring-brand data-[state=open]:!ring-inset data-[state=open]:!ring-offset-0 data-[state=open]:!ring-brand", I = ({
10
+ const T = "whitespace-nowrap bg-accent text-brand hover:bg-accent/80 border-0 px-2 text-xs font-medium font-['Manrope'] cursor-pointer focus:!ring-inset focus:!ring-offset-0 focus:!ring-brand data-[state=open]:!ring-inset data-[state=open]:!ring-offset-0 data-[state=open]:!ring-brand", I = ({
11
11
  remainingValues: s,
12
12
  viewAllTrigger: c = "expand",
13
13
  onViewAll: h,
14
14
  onItemRemove: u,
15
15
  isRemovable: N,
16
- isCopyable: o = !1,
16
+ isCopyable: t = !1,
17
17
  externalCopyFunction: m
18
18
  }) => {
19
- const [i, f] = C.useState(!1), [n, d] = C.useState(null), g = (t, l, a) => {
20
- navigator.clipboard.writeText(String(l)), d(a), t.currentTarget.blur(), setTimeout(() => d(null), 1500);
21
- }, v = i ? s : s.slice(0, 3), x = s.length > 3, p = () => {
19
+ const [i, f] = C.useState(!1), [n, d] = C.useState(null), v = (o, l, a) => {
20
+ navigator.clipboard.writeText(String(l)), d(a), o.currentTarget.blur(), setTimeout(() => d(null), 1500);
21
+ }, g = i ? s : s.slice(0, 3), x = s.length > 3, p = () => {
22
22
  c === "custom" ? h?.() : f(!0);
23
23
  };
24
24
  return /* @__PURE__ */ e(
@@ -27,29 +27,29 @@ const T = "whitespace-nowrap bg-accent text-accent-foreground hover:bg-accent/80
27
27
  className: "w-[200px] p-0 rounded-[8px] bg-canvas-elevated shadow-elevation-floating border-none",
28
28
  align: "start",
29
29
  sideOffset: 8,
30
- onOpenAutoFocus: (t) => t.preventDefault(),
30
+ onOpenAutoFocus: (o) => o.preventDefault(),
31
31
  children: /* @__PURE__ */ r("div", { className: "flex flex-col py-2 px-[6px]", children: [
32
32
  /* @__PURE__ */ e(
33
33
  "div",
34
34
  {
35
35
  className: `flex flex-col gap-1 mb-2 ${i ? "max-h-[180px] overflow-y-auto" : ""}`,
36
- children: v.map((t, l) => /* @__PURE__ */ r(
36
+ children: g.map((o, l) => /* @__PURE__ */ r(
37
37
  "div",
38
38
  {
39
39
  className: "flex items-center justify-between text-[14px] font-medium leading-[20px] text-foreground px-3 py-2 overflow-hidden hover:bg-secondary rounded group shrink-0",
40
40
  children: [
41
41
  /* @__PURE__ */ r(b, { children: [
42
- /* @__PURE__ */ e(w, { asChild: !0, children: /* @__PURE__ */ e("span", { className: "truncate", children: String(t) }) }),
43
- /* @__PURE__ */ e(y, { variant: "tertiary", side: "right", children: String(t) })
42
+ /* @__PURE__ */ e(w, { asChild: !0, children: /* @__PURE__ */ e("span", { className: "truncate", children: String(o) }) }),
43
+ /* @__PURE__ */ e(y, { variant: "tertiary", side: "right", children: String(o) })
44
44
  ] }),
45
45
  /* @__PURE__ */ r("div", { className: "flex items-center shrink-0", children: [
46
- o && /* @__PURE__ */ e(
46
+ t && /* @__PURE__ */ e(
47
47
  "button",
48
48
  {
49
49
  onClick: (a) => {
50
- a.stopPropagation(), m ? m({ e: a, val: t, index: l }) : g(a, t, l);
50
+ a.stopPropagation(), m ? m({ e: a, val: o, index: l }) : v(a, o, l);
51
51
  },
52
- "aria-label": `Copy ${String(t)}`,
52
+ "aria-label": `Copy ${String(o)}`,
53
53
  className: "ms-2 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-content-icon hover:bg-scrim-hover hover:text-content-secondary opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity",
54
54
  children: n === l ? /* @__PURE__ */ e(A, { size: 12, className: "text-success" }) : /* @__PURE__ */ e(R, { size: 12 })
55
55
  }
@@ -58,9 +58,9 @@ const T = "whitespace-nowrap bg-accent text-accent-foreground hover:bg-accent/80
58
58
  "button",
59
59
  {
60
60
  onClick: (a) => {
61
- a.stopPropagation(), u(t);
61
+ a.stopPropagation(), u(o);
62
62
  },
63
- "aria-label": `Remove ${String(t)}`,
63
+ "aria-label": `Remove ${String(o)}`,
64
64
  className: "ms-2 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-content-icon hover:bg-scrim-hover hover:text-content-secondary opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity",
65
65
  children: /* @__PURE__ */ e(F, { size: 12 })
66
66
  }
@@ -97,27 +97,27 @@ const T = "whitespace-nowrap bg-accent text-accent-foreground hover:bg-accent/80
97
97
  S,
98
98
  {
99
99
  items: s,
100
- renderItem: (o, m) => {
101
- const i = Array.isArray(o.value) ? o.value : [o.value], f = i.slice(0, 2), n = i.slice(2), d = !!o.overflow, g = o.overflow?.label ? o.overflow.label : o.overflow?.count ? `+${o.overflow.count}` : null, v = n.length > 0, x = d || v, p = `+${n.length}`;
100
+ renderItem: (t, m) => {
101
+ const i = Array.isArray(t.value) ? t.value : [t.value], f = i.slice(0, 2), n = i.slice(2), d = !!t.overflow, v = t.overflow?.label ? t.overflow.label : t.overflow?.count ? `+${t.overflow.count}` : null, g = n.length > 0, x = d || g, p = `+${n.length}`;
102
102
  return /* @__PURE__ */ r("div", { className: "flex items-center px-1", children: [
103
103
  m > 0 && /* @__PURE__ */ e("div", { className: "mx-3 h-4 w-px bg-stroke-hairline shrink-0" }),
104
104
  /* @__PURE__ */ r("div", { className: "flex items-center gap-2", children: [
105
105
  /* @__PURE__ */ r("span", { className: "text-xs font-medium leading-[21px] text-secondary-foreground whitespace-nowrap", children: [
106
- o.label,
107
- o.required && /* @__PURE__ */ e("span", { className: "text-validation ms-0.5", children: "*" })
106
+ t.label,
107
+ t.required && /* @__PURE__ */ e("span", { className: "text-validation ms-0.5", children: "*" })
108
108
  ] }),
109
109
  /* @__PURE__ */ r("div", { className: "flex items-center gap-1", children: [
110
110
  /* @__PURE__ */ e(
111
111
  z,
112
112
  {
113
113
  spacing: "sm",
114
- tags: f.map((t) => ({
115
- label: String(t),
114
+ tags: f.map((o) => ({
115
+ label: String(o),
116
116
  variant: "secondary",
117
117
  size: "md",
118
118
  shape: "rounded",
119
- removable: o.removable,
120
- onRemove: () => c(o.id, t)
119
+ removable: t.removable,
120
+ onRemove: () => c(t.id, o)
121
121
  }))
122
122
  }
123
123
  ),
@@ -130,13 +130,13 @@ const T = "whitespace-nowrap bg-accent text-accent-foreground hover:bg-accent/80
130
130
  size: "md",
131
131
  shape: "rounded",
132
132
  className: T,
133
- "aria-label": `${o.overflow?.count || n.length} more filters for ${o.label}`,
134
- onClick: () => h?.(o.id),
135
- children: g || p
133
+ "aria-label": `${t.overflow?.count || n.length} more filters for ${t.label}`,
134
+ onClick: () => h?.(t.id),
135
+ children: v || p
136
136
  }
137
137
  ) }),
138
138
  /* @__PURE__ */ r(y, { variant: "tertiary", side: "top", children: [
139
- o.overflow?.count || n.length,
139
+ t.overflow?.count || n.length,
140
140
  " more filters"
141
141
  ] })
142
142
  ] }) : /* @__PURE__ */ r(O, { children: [
@@ -161,11 +161,11 @@ const T = "whitespace-nowrap bg-accent text-accent-foreground hover:bg-accent/80
161
161
  I,
162
162
  {
163
163
  remainingValues: n,
164
- viewAllTrigger: o.viewAllTrigger,
164
+ viewAllTrigger: t.viewAllTrigger,
165
165
  onViewAll: u,
166
- onItemRemove: (t) => c(o.id, t),
167
- isRemovable: o.removable,
168
- isCopyable: o.copyable
166
+ onItemRemove: (o) => c(t.id, o),
167
+ isRemovable: t.removable,
168
+ isCopyable: t.copyable
169
169
  }
170
170
  )
171
171
  ] }))
@@ -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.3`** 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.2.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.3`** 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.2.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.2.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.3\",\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.2.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.2.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.3\",\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.2.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.2.4",
3
+ "version": "2.2.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": [