impact-nova 2.5.19 → 2.5.20

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.
Files changed (25) hide show
  1. package/dist/components/data/expandable-list-item/expandable-list-item-attributes.js +2 -3
  2. package/dist/components/data/expandable-list-item/expandable-list-item-metrics.js +2 -3
  3. package/dist/components/data-display/calendar/calendar.js +194 -190
  4. package/dist/components/feedback/tooltip/tab-tooltip-render.js +2 -3
  5. package/dist/components/flows/command-palette/shortcut-settings.js +10 -10
  6. package/dist/components/flows/filter-panel/filter-panel.js +4 -4
  7. package/dist/components/forms/date-picker/fiscal-pass-through.d.ts +6 -6
  8. package/dist/components/forms/date-picker/fiscal-pass-through.js +7 -3
  9. package/dist/components/forms/date-picker/multi-week-picker.js +1 -1
  10. package/dist/components/forms/date-picker/week-picker.js +123 -123
  11. package/dist/components/forms/date-picker/week-range-picker.js +188 -188
  12. package/dist/components/forms/select/components/SelectTriggerValue.js +2 -3
  13. package/dist/components/forms/select/components/Submenu.js +2 -3
  14. package/dist/form-react/Fields/MultiWeekPickerField.js +16 -15
  15. package/dist/form-react/Fields/WeekRangePicker.js +18 -16
  16. package/dist/form-react/types/fields.types.d.ts +4 -0
  17. package/dist/form-react/utils/date.utils.d.ts +1 -0
  18. package/dist/form-react/utils/date.utils.js +38 -34
  19. package/dist/lib/fiscal-calendar/index.d.ts +2 -2
  20. package/dist/lib/fiscal-calendar/index.js +26 -24
  21. package/dist/lib/fiscal-calendar/week-selection.d.ts +5 -0
  22. package/dist/lib/fiscal-calendar/week-selection.js +56 -49
  23. package/dist/llms/rules/installation.js +1 -1
  24. package/dist/llms/rules/requirements.js +1 -1
  25. package/package.json +1 -1
@@ -1,28 +1,28 @@
1
1
  import { jsx as a } from "react/jsx-runtime";
2
- import { Controller as p } from "react-hook-form";
3
- import { MultiWeekPicker as g } from "../../components/forms/date-picker/multi-week-picker.js";
4
- import { fiscalCalendarPassThrough as k } from "../../components/forms/date-picker/fiscal-pass-through.js";
5
- import { getFieldTestId as M } from "../utils/fieldTestIds.js";
6
- import { resolveWeekRangeMinMax as f } from "../utils/date.utils.js";
7
- const y = ({
2
+ import { Controller as f } from "react-hook-form";
3
+ import { MultiWeekPicker as p } from "../../components/forms/date-picker/multi-week-picker.js";
4
+ import { fiscalCalendarPassThrough as g } from "../../components/forms/date-picker/fiscal-pass-through.js";
5
+ import { getFieldTestId as k } from "../utils/fieldTestIds.js";
6
+ import { resolveWeekRangeMinMax as M } from "../utils/date.utils.js";
7
+ const b = ({
8
8
  field: r,
9
9
  validationRules: l,
10
10
  isDisabled: s,
11
- formHelpers: u
11
+ formHelpers: c
12
12
  }) => {
13
- const c = u.form.control, e = r.fieldType === "multi_week_picker" ? r : null;
13
+ const u = c.form.control, e = r.fieldType === "multi_week_picker" ? r : null;
14
14
  if (!e) return null;
15
- const { minDate: d, maxDate: m } = f(e);
15
+ const { minDate: d, maxDate: m } = M(e);
16
16
  return /* @__PURE__ */ a(
17
- p,
17
+ f,
18
18
  {
19
19
  name: r.id,
20
- control: c,
20
+ control: u,
21
21
  rules: l,
22
22
  render: ({ field: o, fieldState: t }) => {
23
23
  const i = !!t.error, n = o.value;
24
- return /* @__PURE__ */ a("div", { "data-testid": M(r.id), children: /* @__PURE__ */ a(
25
- g,
24
+ return /* @__PURE__ */ a("div", { "data-testid": k(r.id), children: /* @__PURE__ */ a(
25
+ p,
26
26
  {
27
27
  label: r.label,
28
28
  value: Array.isArray(n) ? n : void 0,
@@ -36,13 +36,14 @@ const y = ({
36
36
  helperText: i ? t.error?.message : r.helpText,
37
37
  minDate: d,
38
38
  maxDate: m,
39
- ...k({
39
+ ...g({
40
40
  calendarKind: e.calendarKind,
41
41
  fiscalMode: e.fiscalMode,
42
42
  granularity: e.granularity,
43
43
  fiscalMonthPattern: e.fiscalMonthPattern,
44
44
  fiscalYearStartMonth: e.fiscalYearStartMonth,
45
45
  weekStartsOn: e.weekStartsOn,
46
+ fiscalConfig: e.fiscalConfig,
46
47
  showPeriodBoundaries: e.showPeriodBoundaries,
47
48
  autoNavigateToAvailable: e.autoNavigateToAvailable
48
49
  })
@@ -53,5 +54,5 @@ const y = ({
53
54
  );
54
55
  };
55
56
  export {
56
- y as MultiWeekPickerField
57
+ b as MultiWeekPickerField
57
58
  };
@@ -1,17 +1,18 @@
1
1
  import { jsx as c } from "react/jsx-runtime";
2
- import { Controller as b } from "react-hook-form";
3
- import { WeekRangePicker as x } from "../../components/forms/date-picker/week-range-picker.js";
4
- import { toLocalDate as f } from "../utils/calendar-boundary.js";
5
- import { resolveWeekSelection as Y } from "../../lib/fiscal-calendar/week-selection.js";
6
- import { resolveWeekRangeMinMax as $ } from "../utils/date.utils.js";
7
- const S = (e, a) => Y(e, {
2
+ import { Controller as T } from "react-hook-form";
3
+ import { WeekRangePicker as b } from "../../components/forms/date-picker/week-range-picker.js";
4
+ import { toLocalDate as M } from "../utils/calendar-boundary.js";
5
+ import { resolveWeekSelection as x } from "../../lib/fiscal-calendar/week-selection.js";
6
+ import { resolveWeekRangeMinMax as Y } from "../utils/date.utils.js";
7
+ const S = (e, a) => x(e, {
8
8
  calendarKind: a.calendarKind,
9
9
  fiscalMode: a.fiscalMode ?? "basic",
10
10
  granularity: a.granularity,
11
11
  fiscalMonthPattern: a.fiscalMonthPattern,
12
12
  fiscalYearStartMonth: a.fiscalYearStartMonth ?? 1,
13
- weekStartsOn: a.weekStartsOn ?? 1
14
- }), C = ({
13
+ weekStartsOn: a.weekStartsOn,
14
+ fiscalConfig: a.fiscalConfig
15
+ }), B = ({
15
16
  field: e,
16
17
  validationRules: a,
17
18
  isDisabled: p,
@@ -19,26 +20,26 @@ const S = (e, a) => Y(e, {
19
20
  }) => {
20
21
  const t = e.fieldType === "week_range" ? e : null;
21
22
  if (!t) return null;
22
- const { minDate: u, maxDate: m, startMonth: D, endMonth: k } = $(t), v = d.form.control;
23
+ const { minDate: u, maxDate: m, startMonth: D, endMonth: k } = Y(t), v = d.form.control;
23
24
  return /* @__PURE__ */ c(
24
- b,
25
+ T,
25
26
  {
26
27
  name: e.id,
27
28
  control: v,
28
29
  rules: a,
29
30
  render: ({ field: w, fieldState: h }) => {
30
- const g = !!h.error, r = w.value, s = r?.start ? f(r.start) ?? null : null, i = r?.end ? f(r.end) ?? null : null, F = !!(s && i);
31
+ const g = !!h.error, r = w.value, s = r?.start ? M(r.start) ?? null : null, i = r?.end ? M(r.end) ?? null : null, C = !!(s && i);
31
32
  return /* @__PURE__ */ c("div", { children: /* @__PURE__ */ c(
32
- x,
33
+ b,
33
34
  {
34
35
  label: e.label,
35
- value: F && s && i ? {
36
+ value: C && s && i ? {
36
37
  from: S(s, t),
37
38
  to: S(i, t)
38
39
  } : void 0,
39
40
  onChange: (o) => {
40
- const M = o?.from ? { from: o.from, to: o.to ?? o.from } : void 0, n = M?.from?.startDate, l = M?.to?.endDate, P = n ? `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, "0")}-${String(n.getDate()).padStart(2, "0")}` : null, T = l ? `${l.getFullYear()}-${String(l.getMonth() + 1).padStart(2, "0")}-${String(l.getDate()).padStart(2, "0")}` : null;
41
- d.setValue(e.id, { start: P, end: T });
41
+ const f = o?.from ? { from: o.from, to: o.to ?? o.from } : void 0, n = f?.from?.startDate, l = f?.to?.endDate, F = n ? `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, "0")}-${String(n.getDate()).padStart(2, "0")}` : null, P = l ? `${l.getFullYear()}-${String(l.getMonth() + 1).padStart(2, "0")}-${String(l.getDate()).padStart(2, "0")}` : null;
42
+ d.setValue(e.id, { start: F, end: P });
42
43
  },
43
44
  placeholder: t.placeholder,
44
45
  startMonth: u ?? D,
@@ -55,6 +56,7 @@ const S = (e, a) => Y(e, {
55
56
  granularity: t.granularity,
56
57
  fiscalMonthPattern: t.fiscalMonthPattern,
57
58
  fiscalYearStartMonth: t.fiscalYearStartMonth,
59
+ fiscalConfig: t.fiscalConfig,
58
60
  showFooter: t.showFooter,
59
61
  showPeriodBoundaries: t.showPeriodBoundaries,
60
62
  autoNavigateToAvailable: t.autoNavigateToAvailable,
@@ -66,5 +68,5 @@ const S = (e, a) => Y(e, {
66
68
  );
67
69
  };
68
70
  export {
69
- C as WeekRangeField
71
+ B as WeekRangeField
70
72
  };
@@ -1,6 +1,7 @@
1
1
  import { Option } from '../../components/forms/select';
2
2
  import { HTMLInputTypeAttribute } from 'react';
3
3
  import { FieldOutputValue } from './fieldsOutput.types';
4
+ import { FiscalCalendarConfig } from '../../lib/fiscal-calendar';
4
5
  export type ValidationRule = {
5
6
  /** Regex pattern string to test against */
6
7
  regex?: string;
@@ -219,6 +220,8 @@ export type WeekRangeField = BaseField & {
219
220
  granularity?: "day" | "week" | "period" | "quarter" | "year";
220
221
  fiscalMonthPattern?: number[];
221
222
  fiscalYearStartMonth?: number;
223
+ /** Canonical retail/NRF config. Wins over fiscalYearStartMonth and fiscalMonthPattern. */
224
+ fiscalConfig?: FiscalCalendarConfig;
222
225
  showFooter?: boolean;
223
226
  /** Draw `(` / `)` on fiscal period start/end days. Default false. */
224
227
  showPeriodBoundaries?: boolean;
@@ -253,6 +256,7 @@ export type MultiWeekRangeField = BaseField & {
253
256
  granularity?: "day" | "week" | "period" | "quarter" | "year";
254
257
  fiscalMonthPattern?: number[];
255
258
  fiscalYearStartMonth?: number;
259
+ fiscalConfig?: FiscalCalendarConfig;
256
260
  showPeriodBoundaries?: boolean;
257
261
  /** When true, open on the first enabled week. Navigate only. */
258
262
  autoNavigateToAvailable?: boolean;
@@ -36,6 +36,7 @@ type WeekRangeBoundsField = {
36
36
  fiscalMonthPattern?: WeekRangeField["fiscalMonthPattern"];
37
37
  fiscalYearStartMonth?: WeekRangeField["fiscalYearStartMonth"];
38
38
  weekStartsOn?: WeekRangeField["weekStartsOn"];
39
+ fiscalConfig?: WeekRangeField["fiscalConfig"];
39
40
  };
40
41
  export declare const handleMinMaxProp: (dateRangeField: DateRangeField) => {
41
42
  minDate: Date | undefined;
@@ -1,17 +1,17 @@
1
- import { format as W } from "date-fns";
1
+ import { format as C } from "date-fns";
2
2
  import { civilFromLocalDate as h, localDateFromCivil as x } from "../../lib/fiscal-calendar/civil-date.js";
3
3
  import { getFiscalYearForDate as O } from "../../lib/fiscal-calendar/lookup.js";
4
- import { resolveWeekSelection as p, toFiscalCalendarConfig as Y } from "../../lib/fiscal-calendar/week-selection.js";
4
+ import { resolveWeekSelection as p, toFiscalCalendarConfig as Y, resolveWeekStartsOn as W } from "../../lib/fiscal-calendar/week-selection.js";
5
5
  import { toLocalDate as o } from "./calendar-boundary.js";
6
6
  const M = "yyyy-MM-dd", l = /* @__PURE__ */ new Map();
7
- function T(t) {
7
+ function _(t) {
8
8
  const n = t?.trim();
9
9
  if (!n) return M;
10
10
  const a = n.replace(/D/g, "d").replace(/Y/g, "y");
11
11
  let r = l.get(a);
12
12
  if (r === void 0) {
13
13
  try {
14
- W(/* @__PURE__ */ new Date(), a), r = !0;
14
+ C(/* @__PURE__ */ new Date(), a), r = !0;
15
15
  } catch {
16
16
  r = !1;
17
17
  }
@@ -23,7 +23,7 @@ function f(t) {
23
23
  const n = new Date(t);
24
24
  return n.setHours(0, 0, 0, 0), n;
25
25
  }
26
- function i(t, n) {
26
+ function c(t, n) {
27
27
  const a = new Date(t);
28
28
  return a.setDate(a.getDate() + n), a;
29
29
  }
@@ -38,7 +38,11 @@ function S(t) {
38
38
  granularity: t.granularity,
39
39
  fiscalMonthPattern: t.fiscalMonthPattern,
40
40
  fiscalYearStartMonth: t.fiscalYearStartMonth ?? 1,
41
- weekStartsOn: t.weekStartsOn ?? 1
41
+ weekStartsOn: W({
42
+ weekStartsOn: t.weekStartsOn,
43
+ fiscalConfig: t.fiscalConfig
44
+ }),
45
+ fiscalConfig: t.fiscalConfig
42
46
  };
43
47
  }
44
48
  function D(t, n) {
@@ -55,12 +59,12 @@ function u(t, n) {
55
59
  );
56
60
  return f(a.endDate);
57
61
  }
58
- const _ = (t) => {
62
+ const V = (t) => {
59
63
  let n, a;
60
64
  const r = /* @__PURE__ */ new Date();
61
65
  if (t.minStartOffsetDays != null && t.minStartOffsetDays >= 0)
62
66
  n = f(
63
- i(r, t.minStartOffsetDays)
67
+ c(r, t.minStartOffsetDays)
64
68
  );
65
69
  else if (t.minDate) {
66
70
  const s = o(t.minDate);
@@ -75,24 +79,24 @@ const _ = (t) => {
75
79
  const s = o(t.startMonth);
76
80
  s && (e = f(s));
77
81
  } else t.minStartOffsetDays != null && n && (e = n);
78
- let c;
82
+ let i;
79
83
  if (t.endMonth) {
80
84
  const s = o(t.endMonth);
81
- s && (c = f(s));
85
+ s && (i = f(s));
82
86
  }
83
- return { minDate: n, maxDate: a, startMonth: e, endMonth: c };
84
- }, V = (t) => {
87
+ return { minDate: n, maxDate: a, startMonth: e, endMonth: i };
88
+ }, z = (t) => {
85
89
  let n, a;
86
90
  const r = /* @__PURE__ */ new Date();
87
91
  if (t.minWeeksOffset != null) {
88
- const s = i(
92
+ const s = c(
89
93
  r,
90
94
  -t.minWeeksOffset * 7
91
95
  );
92
96
  n = D(t, s);
93
97
  } else if (t.minStartOffsetDays != null && t.minStartOffsetDays >= 0)
94
98
  n = f(
95
- i(r, t.minStartOffsetDays)
99
+ c(r, t.minStartOffsetDays)
96
100
  );
97
101
  else if (t.disablePastWeeks)
98
102
  n = D(t, r);
@@ -101,7 +105,7 @@ const _ = (t) => {
101
105
  s && (n = D(t, s));
102
106
  }
103
107
  if (t.maxWeeksOffset != null) {
104
- const s = i(
108
+ const s = c(
105
109
  r,
106
110
  t.maxWeeksOffset * 7
107
111
  );
@@ -115,13 +119,13 @@ const _ = (t) => {
115
119
  const s = o(t.startMonth);
116
120
  s && (e = f(s));
117
121
  }
118
- let c;
122
+ let i;
119
123
  if (t.endMonth) {
120
124
  const s = o(t.endMonth);
121
- s && (c = f(s));
125
+ s && (i = f(s));
122
126
  }
123
- return { minDate: n, maxDate: a, startMonth: e, endMonth: c };
124
- }, z = (t) => {
127
+ return { minDate: n, maxDate: a, startMonth: e, endMonth: i };
128
+ }, H = (t) => {
125
129
  let n, a;
126
130
  const r = /* @__PURE__ */ new Date();
127
131
  if (t.minMonthsOffset != null)
@@ -157,12 +161,12 @@ const _ = (t) => {
157
161
  const s = o(t.startMonth);
158
162
  s && (e = f(s));
159
163
  } else (t.minMonthsOffset != null || t.disablePastMonths) && n && (e = n);
160
- let c;
164
+ let i;
161
165
  if (t.endMonth) {
162
166
  const s = o(t.endMonth);
163
- s && (c = f(s));
164
- } else t.maxMonthsOffset != null && a && (c = a);
165
- return { minDate: n, maxDate: a, startMonth: e, endMonth: c };
167
+ s && (i = f(s));
168
+ } else t.maxMonthsOffset != null && a && (i = a);
169
+ return { minDate: n, maxDate: a, startMonth: e, endMonth: i };
166
170
  };
167
171
  function v(t) {
168
172
  return {
@@ -201,7 +205,7 @@ function P(t, n) {
201
205
  }
202
206
  return f(new Date(n.getFullYear(), 11, 31));
203
207
  }
204
- const H = (t) => {
208
+ const I = (t) => {
205
209
  let n, a;
206
210
  const r = /* @__PURE__ */ new Date();
207
211
  if (t.minYearsOffset != null)
@@ -227,21 +231,21 @@ const H = (t) => {
227
231
  const s = o(t.startMonth);
228
232
  s && (e = f(s));
229
233
  } else t.minYearsOffset != null && n && (e = n);
230
- let c;
234
+ let i;
231
235
  if (t.endMonth) {
232
236
  const s = o(t.endMonth);
233
- s && (c = f(s));
234
- } else t.maxYearsOffset != null && a && (c = a);
235
- return { minDate: n, maxDate: a, startMonth: e, endMonth: c };
237
+ s && (i = f(s));
238
+ } else t.maxYearsOffset != null && a && (i = a);
239
+ return { minDate: n, maxDate: a, startMonth: e, endMonth: i };
236
240
  };
237
241
  export {
238
242
  M as DEFAULT_PICKER_DATE_FORMAT,
239
- i as addDaysDate,
243
+ c as addDaysDate,
240
244
  m as addYearsDate,
241
- T as handleDateFnsFormat,
242
- _ as resolveDateRangeMinMax,
243
- z as resolveMonthRangeMinMax,
244
- V as resolveWeekRangeMinMax,
245
- H as resolveYearRangeMinMax,
245
+ _ as handleDateFnsFormat,
246
+ V as resolveDateRangeMinMax,
247
+ H as resolveMonthRangeMinMax,
248
+ z as resolveWeekRangeMinMax,
249
+ I as resolveYearRangeMinMax,
246
250
  f as startOfDayDate
247
251
  };
@@ -1,4 +1,4 @@
1
- export type { CalendarInterval, CalendarKind, CalendarSelection, CalendarSelectionMode, CivilDate, DateCellMeta, FiscalCalendarConfig, FiscalMode, FiscalMonthPattern, FiscalPeriod, FiscalQuarter, FiscalWeek, FiscalYearModel, FyLabelStyle, Granularity, LeapWeekPolicy, RetailPatternId, WeekSelection, Weekday, } from './types';
1
+ export type { CalendarInterval, CalendarKind, CalendarSelection, CalendarSelectionMode, CivilDate, DateCellMeta, FiscalCalendarConfig, FiscalMode, FiscalMonthPattern, FiscalPeriod, FiscalQuarter, FiscalWeek, FiscalYearModel, FyAnchorRule, FyLabelStyle, Granularity, LeapWeekPolicy, RetailPatternId, WeekSelection, Weekday, } from './types';
2
2
  export { DEFAULT_FY_LABEL, DEFAULT_LEAP_WEEK_POLICY, FISCAL_PATTERNS, } from './types';
3
3
  export { addDays, civilFromLocalDate, compareCivil, diffDays, formatCivilRange, lastDayOfMonth, localDateFromCivil, parseCivilDate, toCivilDate, weekStart, weekday, } from './civil-date';
4
4
  export { buildFiscalYear, clearFiscalYearCache, formatFyLabel, resolvePattern, shiftedFyForDate, } from './build-year';
@@ -6,5 +6,5 @@ export { getCellMeta, getFiscalYearForDate, clearFiscalLookupCache } from './loo
6
6
  export { getFiscalPresets } from './presets';
7
7
  export type { FiscalPreset } from './presets';
8
8
  export { isSameInterval, nextIntervalSelection } from './selection';
9
- export { getCalendarWeekSelection, getFiscalWeekSelection, resolveWeekSelection, toFiscalCalendarConfig, } from './week-selection';
9
+ export { getCalendarWeekSelection, getFiscalWeekSelection, resolveWeekSelection, resolveWeekStartsOn, toFiscalCalendarConfig, weekStartsOnFromFiscalConfig, } from './week-selection';
10
10
  export type { ResolveWeekSelectionOptions } from './week-selection';
@@ -1,38 +1,40 @@
1
1
  import { DEFAULT_FY_LABEL as t, DEFAULT_LEAP_WEEK_POLICY as r, FISCAL_PATTERNS as o } from "./types.js";
2
- import { addDays as i, civilFromLocalDate as c, compareCivil as s, diffDays as F, formatCivilRange as f, lastDayOfMonth as m, localDateFromCivil as n, parseCivilDate as C, toCivilDate as D, weekStart as p, weekday as v } from "./civil-date.js";
3
- import { buildFiscalYear as d, clearFiscalYearCache as x, formatFyLabel as S, resolvePattern as g, shiftedFyForDate as E } from "./build-year.js";
2
+ import { addDays as i, civilFromLocalDate as s, compareCivil as c, diffDays as F, formatCivilRange as n, lastDayOfMonth as f, localDateFromCivil as m, parseCivilDate as C, toCivilDate as v, weekStart as D, weekday as p } from "./civil-date.js";
3
+ import { buildFiscalYear as S, clearFiscalYearCache as d, formatFyLabel as g, resolvePattern as k, shiftedFyForDate as x } from "./build-year.js";
4
4
  import { clearFiscalLookupCache as y, getCellMeta as A, getFiscalYearForDate as _ } from "./lookup.js";
5
- import { getFiscalPresets as Y } from "./presets.js";
6
- import { isSameInterval as I, nextIntervalSelection as T } from "./selection.js";
7
- import { getCalendarWeekSelection as b, getFiscalWeekSelection as u, resolveWeekSelection as w, toFiscalCalendarConfig as M } from "./week-selection.js";
5
+ import { getFiscalPresets as W } from "./presets.js";
6
+ import { isSameInterval as h, nextIntervalSelection as I } from "./selection.js";
7
+ import { getCalendarWeekSelection as T, getFiscalWeekSelection as w, resolveWeekSelection as b, resolveWeekStartsOn as u, toFiscalCalendarConfig as M, weekStartsOnFromFiscalConfig as R } from "./week-selection.js";
8
8
  export {
9
9
  t as DEFAULT_FY_LABEL,
10
10
  r as DEFAULT_LEAP_WEEK_POLICY,
11
11
  o as FISCAL_PATTERNS,
12
12
  i as addDays,
13
- d as buildFiscalYear,
14
- c as civilFromLocalDate,
13
+ S as buildFiscalYear,
14
+ s as civilFromLocalDate,
15
15
  y as clearFiscalLookupCache,
16
- x as clearFiscalYearCache,
17
- s as compareCivil,
16
+ d as clearFiscalYearCache,
17
+ c as compareCivil,
18
18
  F as diffDays,
19
- f as formatCivilRange,
20
- S as formatFyLabel,
21
- b as getCalendarWeekSelection,
19
+ n as formatCivilRange,
20
+ g as formatFyLabel,
21
+ T as getCalendarWeekSelection,
22
22
  A as getCellMeta,
23
- Y as getFiscalPresets,
24
- u as getFiscalWeekSelection,
23
+ W as getFiscalPresets,
24
+ w as getFiscalWeekSelection,
25
25
  _ as getFiscalYearForDate,
26
- I as isSameInterval,
27
- m as lastDayOfMonth,
28
- n as localDateFromCivil,
29
- T as nextIntervalSelection,
26
+ h as isSameInterval,
27
+ f as lastDayOfMonth,
28
+ m as localDateFromCivil,
29
+ I as nextIntervalSelection,
30
30
  C as parseCivilDate,
31
- g as resolvePattern,
32
- w as resolveWeekSelection,
33
- E as shiftedFyForDate,
34
- D as toCivilDate,
31
+ k as resolvePattern,
32
+ b as resolveWeekSelection,
33
+ u as resolveWeekStartsOn,
34
+ x as shiftedFyForDate,
35
+ v as toCivilDate,
35
36
  M as toFiscalCalendarConfig,
36
- p as weekStart,
37
- v as weekday
37
+ D as weekStart,
38
+ R as weekStartsOnFromFiscalConfig,
39
+ p as weekday
38
40
  };
@@ -1,5 +1,10 @@
1
1
  import { CalendarKind, FiscalMode, FiscalMonthPattern, Granularity, WeekSelection, FiscalCalendarConfig, Weekday } from './types';
2
2
  export type { FiscalMode, FiscalMonthPattern };
3
+ export declare function weekStartsOnFromFiscalConfig(fiscalConfig?: FiscalCalendarConfig): Weekday | undefined;
4
+ export declare function resolveWeekStartsOn(options: {
5
+ weekStartsOn?: Weekday;
6
+ fiscalConfig?: FiscalCalendarConfig;
7
+ }): Weekday;
3
8
  export declare function getFiscalWeekSelection(date: Date, weekStartsOn: Weekday): WeekSelection;
4
9
  export declare function getCalendarWeekSelection(date: Date, weekStartsOn: Weekday): WeekSelection;
5
10
  export interface ResolveWeekSelectionOptions {
@@ -1,80 +1,87 @@
1
- import { FISCAL_PATTERNS as y } from "./types.js";
1
+ import { FISCAL_PATTERNS as M } from "./types.js";
2
2
  import { buildFiscalYear as d } from "./build-year.js";
3
- import { civilFromLocalDate as m, parseCivilDate as w, localDateFromCivil as l } from "./civil-date.js";
4
- import { getCellMeta as k } from "./lookup.js";
5
- function D(t, n) {
6
- const e = new Date(t), r = (e.getDay() + 7 - n) % 7;
7
- return e.setDate(e.getDate() - r), e.setHours(0, 0, 0, 0), e;
3
+ import { civilFromLocalDate as k, parseCivilDate as w, localDateFromCivil as l } from "./civil-date.js";
4
+ import { getCellMeta as m } from "./lookup.js";
5
+ function O(t) {
6
+ if (t)
7
+ return t.kind === "retail", t.weekStartsOn;
8
+ }
9
+ function S(t) {
10
+ return t.weekStartsOn ?? O(t.fiscalConfig) ?? 1;
8
11
  }
9
- function h(t, n) {
12
+ function u(t, n) {
13
+ const e = new Date(t), a = (e.getDay() + 7 - n) % 7;
14
+ return e.setDate(e.getDate() - a), e.setHours(0, 0, 0, 0), e;
15
+ }
16
+ function D(t, n) {
10
17
  const e = new Date(t);
11
18
  return e.setDate(e.getDate() + n), e;
12
19
  }
13
- function c(t, n) {
14
- const e = D(t, n), a = h(e, 6), o = new Date(t.getFullYear(), t.getMonth(), 1).getDay(), i = e.getDate(), s = e.getMonth() === t.getMonth() ? i : 1, f = Math.ceil((s + o) / 7);
20
+ function f(t, n) {
21
+ const e = u(t, n), r = D(e, 6), i = new Date(t.getFullYear(), t.getMonth(), 1).getDay(), o = e.getDate(), s = e.getMonth() === t.getMonth() ? o : 1, c = Math.ceil((s + i) / 7);
15
22
  return {
16
23
  year: t.getFullYear(),
17
24
  month: t.getMonth(),
18
- weekOfMonth: Math.max(1, f),
25
+ weekOfMonth: Math.max(1, c),
19
26
  startDate: e,
20
- endDate: a
27
+ endDate: r
21
28
  };
22
29
  }
23
- function O(t, n) {
24
- const e = D(t, n), a = h(e, 6), r = new Date(t.getFullYear(), t.getMonth(), 1), o = new Date(t.getFullYear(), t.getMonth() + 1, 0), i = e < r ? new Date(r) : new Date(e), s = a > o ? new Date(o) : new Date(a), u = new Date(i.getFullYear(), i.getMonth(), 1).getDay(), g = i.getDate(), M = Math.ceil((g + u) / 7);
30
+ function F(t, n) {
31
+ const e = u(t, n), r = D(e, 6), a = new Date(t.getFullYear(), t.getMonth(), 1), i = new Date(t.getFullYear(), t.getMonth() + 1, 0), o = e < a ? new Date(a) : new Date(e), s = r > i ? new Date(i) : new Date(r), h = new Date(o.getFullYear(), o.getMonth(), 1).getDay(), g = o.getDate(), y = Math.ceil((g + h) / 7);
25
32
  return {
26
- year: i.getFullYear(),
27
- month: i.getMonth(),
28
- weekOfMonth: Math.max(1, M),
29
- startDate: i,
33
+ year: o.getFullYear(),
34
+ month: o.getMonth(),
35
+ weekOfMonth: Math.max(1, y),
36
+ startDate: o,
30
37
  endDate: s
31
38
  };
32
39
  }
33
- function F(t, n, e) {
34
- const a = k(t, m(n));
35
- if (a?.fy == null || a.fiscalPeriod == null)
36
- return c(n, e);
37
- const r = d(t, a.fy).periods.find(
38
- (i) => i.period === a.fiscalPeriod
40
+ function p(t, n, e) {
41
+ const r = m(t, k(n));
42
+ if (r?.fy == null || r.fiscalPeriod == null)
43
+ return f(n, e);
44
+ const a = d(t, r.fy).periods.find(
45
+ (o) => o.period === r.fiscalPeriod
39
46
  );
40
- if (!r) return c(n, e);
41
- const o = w(r.start);
47
+ if (!a) return f(n, e);
48
+ const i = w(a.start);
42
49
  return {
43
- year: o.y,
44
- month: o.m - 1,
45
- weekOfMonth: r.period,
46
- startDate: l(r.start),
47
- endDate: l(r.end)
50
+ year: i.y,
51
+ month: i.m - 1,
52
+ weekOfMonth: a.period,
53
+ startDate: l(a.start),
54
+ endDate: l(a.end)
48
55
  };
49
56
  }
50
- function v(t, n = {}) {
57
+ function P(t, n = {}) {
51
58
  const {
52
59
  calendarKind: e = "gregorian",
53
- fiscalMode: a = "basic",
54
- granularity: r,
55
- weekStartsOn: o = 1,
56
- fiscalConfig: i
57
- } = n;
58
- if (e !== "fiscal")
59
- return O(t, o);
60
- if (a === "basic" || r !== "period")
61
- return c(t, o);
62
- const s = i ?? S(n);
63
- return s ? F(s, t, o) : c(t, o);
60
+ fiscalMode: r = "basic",
61
+ granularity: a,
62
+ weekStartsOn: i,
63
+ fiscalConfig: o
64
+ } = n, s = o ?? W(n), c = S({
65
+ weekStartsOn: i,
66
+ fiscalConfig: s
67
+ });
68
+ return e !== "fiscal" ? F(t, c) : r === "basic" || a !== "period" || !s ? f(t, c) : p(s, t, c);
64
69
  }
65
- function S(t) {
70
+ function W(t) {
66
71
  if (t.calendarKind !== "fiscal") return;
67
72
  const n = t.weekStartsOn ?? 1, e = t.fiscalYearStartMonth ?? 1;
68
73
  return {
69
74
  kind: "retail",
70
- pattern: t.fiscalMonthPattern ?? y["4-5-4"],
75
+ pattern: t.fiscalMonthPattern ?? M["4-5-4"],
71
76
  weekStartsOn: n,
72
- fyAnchor: { month: e, day: 1, rule: "on-or-before" }
77
+ fyAnchor: { month: e, day: 1, rule: "closest-weekday" }
73
78
  };
74
79
  }
75
80
  export {
76
- O as getCalendarWeekSelection,
77
- c as getFiscalWeekSelection,
78
- v as resolveWeekSelection,
79
- S as toFiscalCalendarConfig
81
+ F as getCalendarWeekSelection,
82
+ f as getFiscalWeekSelection,
83
+ P as resolveWeekSelection,
84
+ S as resolveWeekStartsOn,
85
+ W as toFiscalCalendarConfig,
86
+ O as weekStartsOnFromFiscalConfig
80
87
  };
@@ -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.9`** 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.18` 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.9`** 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.19` 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";