@multiplatform.one/frappe-ui 7.8.0 → 7.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/cjs/FormSidebar.cjs +7 -7
  2. package/dist/cjs/FormSidebar.native.js +7 -7
  3. package/dist/cjs/FormSidebar.native.js.map +1 -1
  4. package/dist/cjs/FrappeChartCard.cjs +29 -3
  5. package/dist/cjs/FrappeChartCard.native.js +29 -3
  6. package/dist/cjs/FrappeChartCard.native.js.map +1 -1
  7. package/dist/cjs/FrappeKPICard.cjs +6 -5
  8. package/dist/cjs/FrappeKPICard.native.js +6 -5
  9. package/dist/cjs/FrappeKPICard.native.js.map +1 -1
  10. package/dist/cjs/FrappeListView.cjs +6 -6
  11. package/dist/cjs/FrappeListView.native.js +6 -6
  12. package/dist/cjs/FrappeListView.native.js.map +1 -1
  13. package/dist/cjs/fields/DateRange/index.cjs +30 -2
  14. package/dist/cjs/fields/DateRange/index.native.js +34 -2
  15. package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
  16. package/dist/cjs/shared/devWarn.native.js.map +1 -1
  17. package/dist/esm/FormSidebar.mjs +7 -7
  18. package/dist/esm/FormSidebar.mjs.map +1 -1
  19. package/dist/esm/FormSidebar.native.js +7 -7
  20. package/dist/esm/FormSidebar.native.js.map +1 -1
  21. package/dist/esm/FrappeChartCard.mjs +30 -4
  22. package/dist/esm/FrappeChartCard.mjs.map +1 -1
  23. package/dist/esm/FrappeChartCard.native.js +30 -4
  24. package/dist/esm/FrappeChartCard.native.js.map +1 -1
  25. package/dist/esm/FrappeKPICard.mjs +6 -5
  26. package/dist/esm/FrappeKPICard.mjs.map +1 -1
  27. package/dist/esm/FrappeKPICard.native.js +6 -5
  28. package/dist/esm/FrappeKPICard.native.js.map +1 -1
  29. package/dist/esm/FrappeListView.mjs +6 -6
  30. package/dist/esm/FrappeListView.mjs.map +1 -1
  31. package/dist/esm/FrappeListView.native.js +6 -6
  32. package/dist/esm/FrappeListView.native.js.map +1 -1
  33. package/dist/esm/fields/DateRange/index.mjs +30 -2
  34. package/dist/esm/fields/DateRange/index.mjs.map +1 -1
  35. package/dist/esm/fields/DateRange/index.native.js +34 -2
  36. package/dist/esm/fields/DateRange/index.native.js.map +1 -1
  37. package/dist/esm/shared/devWarn.mjs.map +1 -1
  38. package/dist/esm/shared/devWarn.native.js.map +1 -1
  39. package/dist/jsx/FormSidebar.mjs +7 -7
  40. package/dist/jsx/FormSidebar.mjs.map +1 -1
  41. package/dist/jsx/FormSidebar.native.js +7 -7
  42. package/dist/jsx/FormSidebar.native.js.map +1 -1
  43. package/dist/jsx/FrappeChartCard.mjs +30 -4
  44. package/dist/jsx/FrappeChartCard.mjs.map +1 -1
  45. package/dist/jsx/FrappeChartCard.native.js +29 -3
  46. package/dist/jsx/FrappeChartCard.native.js.map +1 -1
  47. package/dist/jsx/FrappeKPICard.mjs +6 -5
  48. package/dist/jsx/FrappeKPICard.mjs.map +1 -1
  49. package/dist/jsx/FrappeKPICard.native.js +6 -5
  50. package/dist/jsx/FrappeKPICard.native.js.map +1 -1
  51. package/dist/jsx/FrappeListView.mjs +6 -6
  52. package/dist/jsx/FrappeListView.mjs.map +1 -1
  53. package/dist/jsx/FrappeListView.native.js +6 -6
  54. package/dist/jsx/FrappeListView.native.js.map +1 -1
  55. package/dist/jsx/fields/DateRange/index.mjs +30 -2
  56. package/dist/jsx/fields/DateRange/index.mjs.map +1 -1
  57. package/dist/jsx/fields/DateRange/index.native.js +34 -2
  58. package/dist/jsx/fields/DateRange/index.native.js.map +1 -1
  59. package/dist/jsx/shared/devWarn.mjs.map +1 -1
  60. package/dist/jsx/shared/devWarn.native.js.map +1 -1
  61. package/package.json +18 -18
  62. package/src/FormSidebar.tsx +7 -7
  63. package/src/FrappeChartCard.spec.tsx +179 -0
  64. package/src/FrappeChartCard.tsx +55 -6
  65. package/src/FrappeKPICard.spec.tsx +25 -0
  66. package/src/FrappeKPICard.tsx +17 -11
  67. package/src/FrappeListView.tsx +6 -6
  68. package/src/FrappeProvider.catchUp.spec.tsx +502 -0
  69. package/src/FrappeProvider.tsx +2 -2
  70. package/src/fields/Date/Date.spec.tsx +8 -1
  71. package/src/fields/Date/nativePresentation.spec.tsx +8 -1
  72. package/src/fields/Date/typeParity.spec.tsx +8 -1
  73. package/src/fields/DateRange/DateRange.spec.tsx +87 -15
  74. package/src/fields/DateRange/index.tsx +47 -3
  75. package/src/shared/devWarn.ts +3 -1
  76. package/types/FrappeChartCard.d.ts +17 -1
  77. package/types/FrappeChartCard.d.ts.map +1 -1
  78. package/types/FrappeKPICard.d.ts +11 -6
  79. package/types/FrappeKPICard.d.ts.map +1 -1
  80. package/types/FrappeProvider.d.ts +2 -2
  81. package/types/FrappeProvider.d.ts.map +1 -1
  82. package/types/fields/DateRange/index.d.ts.map +1 -1
  83. package/types/shared/devWarn.d.ts +1 -1
  84. package/types/shared/devWarn.d.ts.map +1 -1
@@ -2,19 +2,16 @@
2
2
  * DateRangeField contract specs. The `Date Range` fieldtype composes the forms
3
3
  * DateRangePicker, so the adapter's contract is which props survive the hop.
4
4
  *
5
- * One of them does not, and that is pinned here deliberately: `value` and
6
- * `onChange` are DECLARED on DateRangeFieldProps and then destructured away
7
- * (`value: _value`, `onChange: _onChange`) instead of being handed to
8
- * DateRangePicker. The registry feeds `props.value` straight into the adapter,
9
- * so a saved Date Range never paints and a picked range never emits. These
10
- * tests describe today's behaviour and will go red the moment someone wires it
11
- * up — which is the point: that is the signal to update them alongside the fix.
12
- * Reported on MPO-123.
5
+ * `value` and `onChange` used to be DECLARED on DateRangeFieldProps and then
6
+ * destructured away instead of being handed to the picker, so a saved range
7
+ * never painted and a picked one never emitted (MPO-137, found by the MPO-123
8
+ * spec pass). Both are now wired, and the range is carried as the two calendar
9
+ * dates comma-separated — the shape the registry feeds in and reads back.
13
10
  */
14
11
  import { renderWithProviders } from "@multiplatform.one/test-utils";
15
- import { cleanup } from "@testing-library/react";
12
+ import { act, cleanup, fireEvent, waitFor } from "@testing-library/react";
16
13
  import type React from "react";
17
- import { afterEach, describe, expect, it } from "vitest";
14
+ import { afterEach, describe, expect, it, vi } from "vitest";
18
15
  import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
19
16
  import { DateRangeField } from ".";
20
17
 
@@ -27,6 +24,24 @@ const trigger = (container: HTMLElement) =>
27
24
  const combobox = (container: HTMLElement) =>
28
25
  container.querySelector('[data-testid="date-picker-trigger"]');
29
26
 
27
+ /**
28
+ * An enabled day cell in the month the picker opened on. The panel is
29
+ * portaled, and the wide layout renders the previous month first, so the
30
+ * range's own month is the LAST calendar panel in the document.
31
+ */
32
+ function getDayButton(day: number): HTMLButtonElement | undefined {
33
+ const panels = document.body.querySelectorAll('[data-testid="date-picker-calendar"]');
34
+ const panel = panels[panels.length - 1];
35
+ if (!panel) return undefined;
36
+ return Array.from(panel.querySelectorAll('button, [role="button"]')).find((btn) => {
37
+ const disabled =
38
+ btn.hasAttribute("disabled") ||
39
+ btn.getAttribute("aria-disabled") === "true" ||
40
+ btn.hasAttribute("data-disabled");
41
+ return btn.textContent?.trim() === String(day) && !disabled;
42
+ }) as HTMLButtonElement | undefined;
43
+ }
44
+
30
45
  describe("DateRangeField composes the forms DateRangePicker", () => {
31
46
  it("renders a single range trigger, not two date inputs", () => {
32
47
  const result = renderWithProviders(<DateRangeField label="Period" />);
@@ -84,21 +99,77 @@ describe("DateRangeField composes the forms DateRangePicker", () => {
84
99
  });
85
100
  });
86
101
 
87
- describe("DateRangeField value gap (MPO-123)", () => {
102
+ describe("DateRangeField controlled value (MPO-137)", () => {
88
103
  it("declares value on its props type", () => {
89
104
  // Type-level promise: the adapter advertises a controlled value.
90
105
  const props: React.ComponentProps<typeof DateRangeField> = { value: "2026-01-01" };
91
106
  expect(props.value).toBe("2026-01-01");
92
107
  });
93
108
 
94
- it("but a controlled value does not reach the control — the trigger stays empty", () => {
109
+ it("paints a saved range on the trigger rather than the placeholder", () => {
110
+ const result = renderWithProviders(
111
+ <DateRangeField label="Period" placeholder="From – To" value="2026-01-01,2026-01-31" />,
112
+ );
113
+ expect(trigger(result.container)?.value).toBe("Jan 1, 2026 – Jan 31, 2026");
114
+ });
115
+
116
+ it("paints a range that arrives after mount, without emitting (LC-14)", async () => {
117
+ const onChange = vi.fn();
118
+ const result = renderWithProviders(
119
+ <DateRangeField label="Period" value="" onChange={onChange} />,
120
+ );
121
+ expect(trigger(result.container)?.value ?? "").toBe("");
122
+
123
+ // Late seed: the engine applies create defaults once meta loads.
124
+ result.rerender(
125
+ <DateRangeField label="Period" value="2026-01-01,2026-01-31" onChange={onChange} />,
126
+ );
127
+ await waitFor(() => {
128
+ expect(trigger(result.container)?.value).toBe("Jan 1, 2026 – Jan 31, 2026");
129
+ });
130
+ expect(onChange).not.toHaveBeenCalled();
131
+ });
132
+
133
+ it("emits the comma-separated wire string once a range is picked", async () => {
134
+ const onChange = vi.fn();
135
+ const result = renderWithProviders(
136
+ <DateRangeField label="Period" value="2026-03-05,2026-03-31" onChange={onChange} />,
137
+ );
138
+ await act(async () => {
139
+ fireEvent.click(trigger(result.container)!);
140
+ });
141
+ // The panel opens on the range's own month; in the wide (dual-calendar)
142
+ // layout that is the LAST panel, the previous month being the first.
143
+ await waitFor(() => {
144
+ expect(getDayButton(15)).toBeTruthy();
145
+ });
146
+ // A complete range restarts on the next click, so this one only re-anchors.
147
+ await act(async () => {
148
+ fireEvent.click(getDayButton(15)!);
149
+ });
150
+ expect(onChange).not.toHaveBeenCalled();
151
+
152
+ await act(async () => {
153
+ fireEvent.click(getDayButton(20)!);
154
+ });
155
+ expect(onChange).toHaveBeenCalledTimes(1);
156
+ expect(onChange).toHaveBeenCalledWith("2026-03-15,2026-03-20");
157
+ });
158
+
159
+ it("clearing the range emits the empty wire value", async () => {
160
+ const onChange = vi.fn();
95
161
  const result = renderWithProviders(
96
- <DateRangeField label="Period" value="2026-01-01,2026-01-31" />,
162
+ <DateRangeField label="Period" value="2026-03-05,2026-03-31" onChange={onChange} />,
97
163
  );
98
- expect(trigger(result.container)?.value).toBe("");
164
+ await act(async () => {
165
+ fireEvent.click(
166
+ result.container.querySelector('[data-testid="date-picker-clear"]') as HTMLElement,
167
+ );
168
+ });
169
+ expect(onChange).toHaveBeenCalledWith("");
99
170
  });
100
171
 
101
- it("and the registry hands that value straight to the adapter, so the drop is on this file", () => {
172
+ it("the registry hands value and onChange straight to the adapter", () => {
102
173
  const Component = getFieldComponent("Date Range")!;
103
174
  const element = (Component as Function)({
104
175
  value: "2026-01-01,2026-01-31",
@@ -106,6 +177,7 @@ describe("DateRangeField value gap (MPO-123)", () => {
106
177
  } as FieldRenderProps) as React.ReactElement<Record<string, any>>;
107
178
  expect(element.type).toBe(DateRangeField);
108
179
  expect(element.props.value).toBe("2026-01-01,2026-01-31");
180
+ expect(typeof element.props.onChange).toBe("function");
109
181
  });
110
182
  });
111
183
 
@@ -1,7 +1,9 @@
1
- import type { FormFieldProps, FieldComponentProps } from "@multiplatform.one/forms";
1
+ import type { DateRange, FormFieldProps, FieldComponentProps } from "@multiplatform.one/forms";
2
2
  import { DateRangePicker as FormsDateRangePicker } from "@multiplatform.one/forms";
3
3
  import type { DeepKeys } from "@tanstack/form-core";
4
+ import { useMemo } from "react";
4
5
  import { useProps } from "tamagui";
6
+ import { fromFrappeDateValue, toFrappeDateValue } from "../Date/wire";
5
7
 
6
8
  export type DateRangeFieldProps<
7
9
  TData extends Record<string, unknown> = Record<string, unknown>,
@@ -37,6 +39,39 @@ export type DateRangeFieldProps<
37
39
  placeholder?: string;
38
40
  };
39
41
 
42
+ /**
43
+ * A `Date Range` is stored as its two ends, comma-separated, and each end is
44
+ * the same bare `YYYY-MM-DD` a `Date` field writes — so both ends serialize
45
+ * through the Date field's shared wire body rather than a second local-midnight
46
+ * parse that could drift from it.
47
+ */
48
+ const rangeSeparator = ",";
49
+
50
+ function toPickerDate(value: string | undefined): Date | null {
51
+ if (!value) return null;
52
+ const date = fromFrappeDateValue(value, "date");
53
+ return Number.isNaN(date.getTime()) ? null : date;
54
+ }
55
+
56
+ /**
57
+ * `undefined` stays undefined so uncontrolled (`defaultValue`-only) and
58
+ * form-bound use keep their semantics: the picker adopts an external value
59
+ * only when `value` is not undefined.
60
+ */
61
+ function toPickerRange(value: string | undefined): DateRange | null | undefined {
62
+ if (value === undefined) return undefined;
63
+ if (!value) return null;
64
+ const [start, end] = value.split(rangeSeparator);
65
+ return { start: toPickerDate(start?.trim()), end: toPickerDate(end?.trim()) };
66
+ }
67
+
68
+ function toWireValue(range: DateRange | null): string {
69
+ if (!range?.start) return "";
70
+ const start = toFrappeDateValue(range.start, "date");
71
+ if (!range.end) return start;
72
+ return `${start}${rangeSeparator}${toFrappeDateValue(range.end, "date")}`;
73
+ }
74
+
40
75
  export function DateRangeField<
41
76
  TData extends Record<string, unknown> = Record<string, unknown>,
42
77
  TName extends string = string,
@@ -47,20 +82,29 @@ export function DateRangeField<
47
82
  mode: _mode,
48
83
  name,
49
84
  onBlur: _onBlur,
50
- onChange: _onChange,
85
+ onChange,
51
86
  preserveValue: _preserveValue,
52
87
  validators,
53
88
  disabled,
54
- value: _value,
89
+ value,
55
90
  placeholder,
56
91
  ...fieldProps
57
92
  } = useProps(props);
58
93
 
94
+ const wireValue = value as string | undefined;
95
+ const emit = onChange as ((value: string) => void) | undefined;
96
+ // Memoized so the Date identities are stable across renders: the picker
97
+ // re-seeds its display state from every new `value` identity, which would
98
+ // otherwise discard a half-picked range on an unrelated re-render.
99
+ const rangeValue = useMemo(() => toPickerRange(wireValue), [wireValue]);
100
+
59
101
  return (
60
102
  <FormsDateRangePicker
61
103
  name={name}
62
104
  form={form}
63
105
  validators={validators}
106
+ value={rangeValue}
107
+ onChange={(range) => emit?.(toWireValue(range))}
64
108
  defaultValue={defaultValue}
65
109
  label={fieldProps.label}
66
110
  labelProps={fieldProps.labelProps}
@@ -11,7 +11,9 @@
11
11
  * process so a re-render never repeats a line.
12
12
  */
13
13
 
14
- export type FrappeDevWarnCode = "kpi-datasource-without-baseurl";
14
+ export type FrappeDevWarnCode =
15
+ | "kpi-datasource-without-baseurl"
16
+ | "chart-datasource-without-baseurl";
15
17
 
16
18
  export type FrappeDevWarnDetail = {
17
19
  component?: string;
@@ -15,6 +15,14 @@
15
15
  * (permission failures called out), catalog empty state when the aggregate
16
16
  * returns no groups, and a subtle stale dim while a post-event refetch is
17
17
  * in flight.
18
+ *
19
+ * A `dataSource` with no data source in scope — no `baseURL` from the prop
20
+ * or a FrappeProvider, and no fixture corpus either — is a misconfiguration,
21
+ * not static mode: the caller asked for a computed series and there is
22
+ * nowhere to compute it. The card renders the not-configured surface and
23
+ * warns in dev. It never falls back to `config.data`, which would present
24
+ * an uncomputed shape as the series. A fixture corpus answers every read
25
+ * locally, so it stands in for a baseURL (MPO-228).
18
26
  */
19
27
  import { type ChartCardProps, type ChartConfig } from "@multiplatform.one/components";
20
28
  import { type FrappeAggregateOperation } from "./useFrappeAggregate";
@@ -34,12 +42,20 @@ export interface FrappeChartDataSource {
34
42
  formatLabel?: (label: string) => string;
35
43
  }
36
44
  export interface FrappeChartCardProps extends Omit<ChartCardProps, "config"> {
37
- /** Chart chrome (title, type, height…). In live mode `data` is overridden. */
45
+ /**
46
+ * Chart chrome (title, type, height…). In live mode `data` is overridden.
47
+ * With a `dataSource` and no data source in scope, `data` is not rendered
48
+ * at all.
49
+ */
38
50
  config: Omit<ChartConfig, "data"> & {
39
51
  data?: ChartConfig["data"];
40
52
  };
41
53
  /** When set, the chart series goes live against this doctype. */
42
54
  dataSource?: FrappeChartDataSource;
55
+ /**
56
+ * Falls back to the FrappeProvider's. Required whenever `dataSource` is
57
+ * set, unless the provider carries a fixture corpus.
58
+ */
43
59
  baseURL?: string;
44
60
  auth?: {
45
61
  useToken?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"FrappeChartCard.d.ts","sourceRoot":"","sources":["../src/FrappeChartCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAC;AAE9B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC;IAC1E,8EAA8E;IAC9E,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC;IACnE,iEAAiE;IACjE,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAuBD,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,WAAW,EACX,GAAG,cAAc,EAClB,EAAE,oBAAoB,2CA2FtB;AAED,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"FrappeChartCard.d.ts","sourceRoot":"","sources":["../src/FrappeChartCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAQvC,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAC;AAE9B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC;IAC1E;;;;OAIG;IACH,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC;IACnE,iEAAiE;IACjE,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAuBD,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,WAAW,EACX,GAAG,cAAc,EAClB,EAAE,oBAAoB,2CA2HtB;AAED,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
@@ -12,11 +12,13 @@
12
12
  * (the card dims while a post-event refetch is in flight), and "—" when the
13
13
  * aggregate has no result (e.g. avg over an empty set).
14
14
  *
15
- * A `dataSource` with no `baseURL` in scope (neither the prop nor a
16
- * FrappeProvider) is a misconfiguration, not static mode: the caller asked
17
- * for a computed figure and there is nowhere to compute it. The card renders
18
- * the not-configured surface and warns in dev. It never falls back to
19
- * `config.value`, which would present an uncomputed number as the KPI.
15
+ * A `dataSource` with no data source in scope — no `baseURL` from the prop
16
+ * or a FrappeProvider, and no fixture corpus either — is a misconfiguration,
17
+ * not static mode: the caller asked for a computed figure and there is
18
+ * nowhere to compute it. The card renders the not-configured surface and
19
+ * warns in dev. It never falls back to `config.value`, which would present
20
+ * an uncomputed number as the KPI. A fixture corpus answers every read
21
+ * locally, so it stands in for a baseURL (MPO-228).
20
22
  */
21
23
  import { type KPICardConfig } from "@multiplatform.one/components";
22
24
  import { type YStackProps } from "tamagui";
@@ -41,7 +43,10 @@ export interface FrappeKPICardProps extends Omit<YStackProps, "children"> {
41
43
  config: KPICardConfig;
42
44
  /** When set, the card's value goes live against this doctype. */
43
45
  dataSource?: FrappeKPIDataSource;
44
- /** Falls back to the FrappeProvider's. Required whenever `dataSource` is set. */
46
+ /**
47
+ * Falls back to the FrappeProvider's. Required whenever `dataSource` is
48
+ * set, unless the provider carries a fixture corpus.
49
+ */
45
50
  baseURL?: string;
46
51
  auth?: {
47
52
  useToken?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"FrappeKPICard.d.ts","sourceRoot":"","sources":["../src/FrappeKPICard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAC;AAE9B,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC;IACvE;;;;OAIG;IACH,MAAM,EAAE,aAAa,CAAC;IACtB,iEAAiE;IACjE,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAcD,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,WAAW,EACX,GAAG,UAAU,EACd,EAAE,kBAAkB,2CAiGpB;AAED,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"FrappeKPICard.d.ts","sourceRoot":"","sources":["../src/FrappeKPICard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAC;AAE9B,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC;IACvE;;;;OAIG;IACH,MAAM,EAAE,aAAa,CAAC;IACtB,iEAAiE;IACjE,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAcD,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,WAAW,EACX,GAAG,UAAU,EACd,EAAE,kBAAkB,2CAkGpB;AAED,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC"}
@@ -48,7 +48,7 @@ export interface FrappeConfig {
48
48
  type?: string;
49
49
  };
50
50
  /** Sync options for the live data engine */
51
- syncOptions?: any;
51
+ syncOptions?: UseFrappeCollectionConfig["syncOptions"];
52
52
  /**
53
53
  * Extra Socket.IO client options for the realtime connection — e.g.
54
54
  * `{ transports: ["polling", "websocket"] }` behind dev proxies that
@@ -89,7 +89,7 @@ export interface FrappeProviderProps {
89
89
  type?: string;
90
90
  };
91
91
  /** Sync options for the live data engine */
92
- syncOptions?: any;
92
+ syncOptions?: UseFrappeCollectionConfig["syncOptions"];
93
93
  /** Extra Socket.IO client options for the realtime connection. */
94
94
  socketOptions?: UseFrappeCollectionConfig["socketOptions"];
95
95
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"FrappeProvider.d.ts","sourceRoot":"","sources":["../src/FrappeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC5F,OAAO,KAAyC,MAAM,OAAO,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,IAAI,CAAC,EAAE;QACL,gDAAgD;QAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,sFAAsF;QACtF,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,8BAA8B;QAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,4CAA4C;IAC5C,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAID;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,uBAAuB;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,IAAI,CAAC,EAAE;QACL,gDAAgD;QAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,sFAAsF;QACtF,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,8BAA8B;QAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,4CAA4C;IAC5C,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,kEAAkE;IAClE,aAAa,CAAC,EAAE,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,UAAU,EACV,aAAa,EACb,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,aAAa,EACb,QAAQ,GACT,EAAE,mBAAmB,2CA2BrB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,SAAS,CAE1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,GAAG,SAAS,CAE3D"}
1
+ {"version":3,"file":"FrappeProvider.d.ts","sourceRoot":"","sources":["../src/FrappeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC5F,OAAO,KAAyC,MAAM,OAAO,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,IAAI,CAAC,EAAE;QACL,gDAAgD;QAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,sFAAsF;QACtF,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,8BAA8B;QAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,4CAA4C;IAC5C,WAAW,CAAC,EAAE,yBAAyB,CAAC,aAAa,CAAC,CAAC;IACvD;;;;OAIG;IACH,aAAa,CAAC,EAAE,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAID;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,uBAAuB;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,IAAI,CAAC,EAAE;QACL,gDAAgD;QAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,sFAAsF;QACtF,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,8BAA8B;QAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,4CAA4C;IAC5C,WAAW,CAAC,EAAE,yBAAyB,CAAC,aAAa,CAAC,CAAC;IACvD,kEAAkE;IAClE,aAAa,CAAC,EAAE,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,UAAU,EACV,aAAa,EACb,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,aAAa,EACb,QAAQ,GACT,EAAE,mBAAmB,2CA2BrB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,SAAS,CAE1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,GAAG,SAAS,CAE3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/DateRange/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,MAAM,MAAM,mBAAmB,CAC7B,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,KAAK,SAAS,MAAM,GAAG,MAAM,IAC3B,IAAI,CACN,cAAc,CACZ,KAAK,EACL,KAAK,SAAS,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EACvD,OAAO,EACP,OAAO,EACP,MAAM,CACP,EACD,UAAU,GAAG,OAAO,CACrB,GACC,OAAO,CACL,IAAI,CACF,mBAAmB,CACjB,KAAK,EACL,KAAK,SAAS,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EACvD,OAAO,EACP,OAAO,EACP,MAAM,CACP,EACD,UAAU,CACX,CACF,GAAG;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEJ,wBAAgB,cAAc,CAC5B,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,KAAK,EAAE,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,2CAoCzC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/DateRange/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAKpD,MAAM,MAAM,mBAAmB,CAC7B,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,KAAK,SAAS,MAAM,GAAG,MAAM,IAC3B,IAAI,CACN,cAAc,CACZ,KAAK,EACL,KAAK,SAAS,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EACvD,OAAO,EACP,OAAO,EACP,MAAM,CACP,EACD,UAAU,GAAG,OAAO,CACrB,GACC,OAAO,CACL,IAAI,CACF,mBAAmB,CACjB,KAAK,EACL,KAAK,SAAS,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EACvD,OAAO,EACP,OAAO,EACP,MAAM,CACP,EACD,UAAU,CACX,CACF,GAAG;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAmCJ,wBAAgB,cAAc,CAC5B,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,KAAK,EAAE,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,2CA6CzC"}
@@ -10,7 +10,7 @@
10
10
  * No-ops when `NODE_ENV === "production"`, and each key warns once per
11
11
  * process so a re-render never repeats a line.
12
12
  */
13
- export type FrappeDevWarnCode = "kpi-datasource-without-baseurl";
13
+ export type FrappeDevWarnCode = "kpi-datasource-without-baseurl" | "chart-datasource-without-baseurl";
14
14
  export type FrappeDevWarnDetail = {
15
15
  component?: string;
16
16
  id?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"devWarn.d.ts","sourceRoot":"","sources":["../../src/shared/devWarn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,iBAAiB,GAAG,gCAAgC,CAAC;AAEjE,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,GAAE,mBAAwB,GAAG,IAAI,CAY7F;AAED,4BAA4B;AAC5B,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
1
+ {"version":3,"file":"devWarn.d.ts","sourceRoot":"","sources":["../../src/shared/devWarn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,iBAAiB,GACzB,gCAAgC,GAChC,kCAAkC,CAAC;AAEvC,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,GAAE,mBAAwB,GAAG,IAAI,CAY7F;AAED,4BAA4B;AAC5B,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}