@multiplatform.one/frappe-ui 6.3.0 → 6.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/FrappeDashboard.cjs +12 -2
- package/dist/cjs/FrappeDashboard.native.js +12 -2
- package/dist/cjs/FrappeDashboard.native.js.map +1 -1
- package/dist/cjs/FrappeLikedBy.cjs +2 -1
- package/dist/cjs/FrappeLikedBy.native.js +3 -1
- package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
- package/dist/cjs/FrappeListView.cjs +10 -1
- package/dist/cjs/FrappeListView.native.js +10 -1
- package/dist/cjs/FrappeListView.native.js.map +1 -1
- package/dist/cjs/fieldRegistry.cjs +1 -1
- package/dist/cjs/fieldRegistry.native.js +1 -1
- package/dist/cjs/fieldRegistry.native.js.map +1 -1
- package/dist/cjs/fields/MarkdownEditor/index.cjs +33 -108
- package/dist/cjs/fields/MarkdownEditor/index.native.js +3 -3
- package/dist/cjs/fields/MarkdownEditor/index.native.js.map +1 -1
- package/dist/esm/FrappeDashboard.mjs +13 -3
- package/dist/esm/FrappeDashboard.mjs.map +1 -1
- package/dist/esm/FrappeDashboard.native.js +13 -3
- package/dist/esm/FrappeDashboard.native.js.map +1 -1
- package/dist/esm/FrappeLikedBy.mjs +3 -2
- package/dist/esm/FrappeLikedBy.mjs.map +1 -1
- package/dist/esm/FrappeLikedBy.native.js +4 -2
- package/dist/esm/FrappeLikedBy.native.js.map +1 -1
- package/dist/esm/FrappeListView.mjs +11 -2
- package/dist/esm/FrappeListView.mjs.map +1 -1
- package/dist/esm/FrappeListView.native.js +11 -2
- package/dist/esm/FrappeListView.native.js.map +1 -1
- package/dist/esm/fieldRegistry.mjs +1 -1
- package/dist/esm/fieldRegistry.mjs.map +1 -1
- package/dist/esm/fieldRegistry.native.js +1 -1
- package/dist/esm/fieldRegistry.native.js.map +1 -1
- package/dist/esm/fields/MarkdownEditor/index.mjs +36 -100
- package/dist/esm/fields/MarkdownEditor/index.mjs.map +1 -1
- package/dist/esm/fields/MarkdownEditor/index.native.js.map +1 -1
- package/dist/jsx/FrappeDashboard.mjs +13 -3
- package/dist/jsx/FrappeDashboard.mjs.map +1 -1
- package/dist/jsx/FrappeDashboard.native.js +12 -2
- package/dist/jsx/FrappeDashboard.native.js.map +1 -1
- package/dist/jsx/FrappeLikedBy.mjs +3 -2
- package/dist/jsx/FrappeLikedBy.mjs.map +1 -1
- package/dist/jsx/FrappeLikedBy.native.js +3 -1
- package/dist/jsx/FrappeLikedBy.native.js.map +1 -1
- package/dist/jsx/FrappeListView.mjs +11 -2
- package/dist/jsx/FrappeListView.mjs.map +1 -1
- package/dist/jsx/FrappeListView.native.js +10 -1
- package/dist/jsx/FrappeListView.native.js.map +1 -1
- package/dist/jsx/fieldRegistry.mjs +1 -1
- package/dist/jsx/fieldRegistry.mjs.map +1 -1
- package/dist/jsx/fieldRegistry.native.js +1 -1
- package/dist/jsx/fieldRegistry.native.js.map +1 -1
- package/dist/jsx/fields/MarkdownEditor/index.mjs +36 -100
- package/dist/jsx/fields/MarkdownEditor/index.mjs.map +1 -1
- package/dist/jsx/fields/MarkdownEditor/index.native.js +3 -3
- package/dist/jsx/fields/MarkdownEditor/index.native.js.map +1 -1
- package/package.json +22 -15
- package/src/FrappeDashboard.stories.tsx +3 -1
- package/src/FrappeDashboard.tsx +21 -1
- package/src/FrappeLikedBy.tsx +13 -2
- package/src/FrappeListView.tsx +21 -1
- package/src/FrappeTable.stories.tsx +91 -12
- package/src/fieldRegistry.ts +1 -1
- package/src/fields/Date/index.tsx +47 -3
- package/src/fields/MarkdownEditor/MarkdownEditor.spec.tsx +56 -32
- package/src/fields/MarkdownEditor/MarkdownEditor.stories.tsx +5 -5
- package/src/fields/MarkdownEditor/index.native.tsx +292 -0
- package/src/fields/MarkdownEditor/index.tsx +64 -139
- package/types/FrappeDashboard.d.ts.map +1 -1
- package/types/FrappeLikedBy.d.ts.map +1 -1
- package/types/FrappeListView.d.ts.map +1 -1
- package/types/fieldRegistry.d.ts.map +1 -1
- package/types/fields/MarkdownEditor/index.d.ts +11 -5
- package/types/fields/MarkdownEditor/index.d.ts.map +1 -1
- package/types/fields/MarkdownEditor/index.native.d.ts +47 -0
- package/types/fields/MarkdownEditor/index.native.d.ts.map +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["index_native_exports","__export","MarkdownEditorField","module","exports","__toCommonJS","import_jsx_runtime","require","import_forms","import_react","import_react_i18next","import_tamagui","import_theme","import_EditorPreviewPanes","markdownRendererCache","useMarkdownRenderer","enabled","renderer","setRenderer","useState","useEffect","cancelled","then","mod","Markdown","catch","MarkdownPreview","param","value","compact","t","useTranslation","knobProps","useResolvedKnobs","Renderer","textSize","sizeToken","jsx","PreviewSurface","children","Paragraph","color","formCommonColors","muted","size","whiteSpace","name","form","formProp","validators","label","labelProps","helperText","error","required","disabled","readOnly","skeleton","id","idProp","defaultValue","onChange","onBlur","placeholder","minRows","maxRows","ariaLabel","_ref","_ref1","resolvedForm","useFormField","resolvedValidators","useResolvedValidators","inTableCell","useIsInTableCell","internalValue","setInternalValue","accessibleName","jsxs","YStack","gap","width","Skeleton","variant","height","renderSource","renderSource2","textValue","handleChange","hasError","TextArea","onChangeText","text","textAreaProps","fontFamily","autoCapitalize","autoCorrect","spellCheck","renderControl","renderControl2","EditorPreviewPanes","editor","preview","editTabLabel","previewTabLabel","defaultPreview","FieldLayout","Field","field","resolvedError","getFieldError","fieldValue","state","handleChange2","mergeFieldHandler"],"sources":["../../../../src/fields/MarkdownEditor/index.native.tsx"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/frappe-ui",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.4.1",
|
|
4
4
|
"description": "Pre-wired Tamagui components for Frappe doctypes with live data",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cross-platform",
|
|
@@ -52,6 +52,13 @@
|
|
|
52
52
|
"import": "./dist/esm/index.mjs",
|
|
53
53
|
"require": "./dist/cjs/index.cjs",
|
|
54
54
|
"default": "./dist/esm/index.mjs"
|
|
55
|
+
},
|
|
56
|
+
"./dependsOn": {
|
|
57
|
+
"source": "./src/dependsOn.ts",
|
|
58
|
+
"types": "./types/dependsOn.d.ts",
|
|
59
|
+
"import": "./dist/esm/dependsOn.mjs",
|
|
60
|
+
"require": "./dist/cjs/dependsOn.cjs",
|
|
61
|
+
"default": "./src/dependsOn.ts"
|
|
55
62
|
}
|
|
56
63
|
},
|
|
57
64
|
"publishConfig": {
|
|
@@ -71,17 +78,17 @@
|
|
|
71
78
|
"html5-qrcode": "^2.3.8",
|
|
72
79
|
"signature_pad": "^5.1.3",
|
|
73
80
|
"tamagui": "2.0.0-rc.41",
|
|
74
|
-
"@multiplatform.one/components": "6.
|
|
75
|
-
"@multiplatform.one/desktop": "6.
|
|
76
|
-
"@multiplatform.one/forms": "6.
|
|
77
|
-
"@multiplatform.one/frappe": "6.
|
|
78
|
-
"@multiplatform.one/i18n": "6.
|
|
79
|
-
"@multiplatform.one/platform": "6.
|
|
80
|
-
"@multiplatform.one/rich-text": "6.
|
|
81
|
-
"@multiplatform.one/
|
|
82
|
-
"@multiplatform.one/theme": "6.
|
|
83
|
-
"@multiplatform.one/
|
|
84
|
-
"@multiplatform.one/
|
|
81
|
+
"@multiplatform.one/components": "6.4.1",
|
|
82
|
+
"@multiplatform.one/desktop": "6.4.1",
|
|
83
|
+
"@multiplatform.one/forms": "6.4.1",
|
|
84
|
+
"@multiplatform.one/frappe": "6.4.1",
|
|
85
|
+
"@multiplatform.one/i18n": "6.4.1",
|
|
86
|
+
"@multiplatform.one/platform": "6.4.1",
|
|
87
|
+
"@multiplatform.one/rich-text": "6.4.1",
|
|
88
|
+
"@multiplatform.one/store": "6.4.1",
|
|
89
|
+
"@multiplatform.one/theme": "6.4.1",
|
|
90
|
+
"@multiplatform.one/table": "6.4.1",
|
|
91
|
+
"@multiplatform.one/router": "6.4.1"
|
|
85
92
|
},
|
|
86
93
|
"devDependencies": {
|
|
87
94
|
"@tamagui/build": "2.0.0-rc.41",
|
|
@@ -94,9 +101,9 @@
|
|
|
94
101
|
"react-dom": "19.2.5",
|
|
95
102
|
"react-i18next": "^16.6.6",
|
|
96
103
|
"vitest": "^4.1.5",
|
|
97
|
-
"@multiplatform.one/
|
|
98
|
-
"@multiplatform.one/
|
|
99
|
-
"@multiplatform.one/
|
|
104
|
+
"@multiplatform.one/storybook": "6.4.1",
|
|
105
|
+
"@multiplatform.one/config": "6.4.1",
|
|
106
|
+
"@multiplatform.one/test-utils": "6.4.1"
|
|
100
107
|
},
|
|
101
108
|
"peerDependencies": {
|
|
102
109
|
"@react-native-community/datetimepicker": "^8.0.1",
|
|
@@ -31,7 +31,9 @@ export const KPICardDefault = () => (
|
|
|
31
31
|
/>
|
|
32
32
|
);
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
// Not "Main": SalesDashboard below owns that name; two stories sharing one
|
|
35
|
+
// name collide to a single lost-pixel shot file, silently untesting one.
|
|
36
|
+
KPICardDefault.storyName = "KPI Card";
|
|
35
37
|
// Chart Card Stories
|
|
36
38
|
export const BarChart = () => (
|
|
37
39
|
<ChartCard
|
package/src/FrappeDashboard.tsx
CHANGED
|
@@ -15,7 +15,25 @@ import React, { useMemo, useCallback, useState, useEffect, useRef } from "react"
|
|
|
15
15
|
import { useTranslation } from "react-i18next";
|
|
16
16
|
import { Spinner } from "@multiplatform.one/forms";
|
|
17
17
|
import { Button, Text, XStack, YStack, type YStackProps, H3 } from "tamagui";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
MIN_PRESS_TARGET,
|
|
20
|
+
pressTargetHitSlop,
|
|
21
|
+
pressTargetStyle,
|
|
22
|
+
useResolvedKnobs,
|
|
23
|
+
} from "@multiplatform.one/theme";
|
|
24
|
+
|
|
25
|
+
// DG-LAY-04 / D-02 press-floor: the chromeless $2 refresh button paints
|
|
26
|
+
// ~28×28; the press box is floored at 44 via the house pressTarget* channel
|
|
27
|
+
// (grown transparent box + negative outset + hitSlop). Layout stays put; the
|
|
28
|
+
// only adjacent node is non-interactive text, so no target overlap.
|
|
29
|
+
const REFRESH_VISUAL = 28;
|
|
30
|
+
const REFRESH_OUTSET = Math.ceil((MIN_PRESS_TARGET - REFRESH_VISUAL) / 2);
|
|
31
|
+
const refreshPressFloorProps = {
|
|
32
|
+
...pressTargetStyle(),
|
|
33
|
+
marginVertical: -REFRESH_OUTSET,
|
|
34
|
+
marginHorizontal: -REFRESH_OUTSET,
|
|
35
|
+
hitSlop: pressTargetHitSlop(REFRESH_VISUAL),
|
|
36
|
+
} as const;
|
|
19
37
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
20
38
|
|
|
21
39
|
/**
|
|
@@ -209,6 +227,7 @@ function LiveDashboardContent<TDoc extends { name: string; doctype: string }>({
|
|
|
209
227
|
disabled={isRefreshing || isLiveLoading}
|
|
210
228
|
chromeless
|
|
211
229
|
aria-label={t("Refresh")}
|
|
230
|
+
{...refreshPressFloorProps}
|
|
212
231
|
/>
|
|
213
232
|
</XStack>
|
|
214
233
|
)}
|
|
@@ -319,6 +338,7 @@ export function FrappeDashboard<TDoc extends { name: string; doctype: string }>(
|
|
|
319
338
|
disabled={isRefreshing}
|
|
320
339
|
chromeless
|
|
321
340
|
aria-label={t("Refresh")}
|
|
341
|
+
{...refreshPressFloorProps}
|
|
322
342
|
/>
|
|
323
343
|
</XStack>
|
|
324
344
|
</XStack>
|
package/src/FrappeLikedBy.tsx
CHANGED
|
@@ -17,7 +17,7 @@ import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
|
17
17
|
import { HeartIcon } from "@phosphor-icons/react";
|
|
18
18
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
19
19
|
import { useTranslation } from "react-i18next";
|
|
20
|
-
import { Button, Text, XStack, YStack, type YStackProps } from "tamagui";
|
|
20
|
+
import { Button, Text, XStack, YStack, isWeb, useTheme, type YStackProps } from "tamagui";
|
|
21
21
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
22
22
|
import { FrappeReconnectIndicator } from "./FrappeReconnectIndicator";
|
|
23
23
|
import { useFrappeUsers } from "./frappeUsers";
|
|
@@ -108,6 +108,9 @@ function FrappeLikedByBody({
|
|
|
108
108
|
const config = useFrappeConfig();
|
|
109
109
|
const { t } = useTranslation();
|
|
110
110
|
const { knobProps } = useResolvedKnobs();
|
|
111
|
+
// Native SVG can't parse CSS color strings (`var(--red10)` / `currentColor`)
|
|
112
|
+
// — resolve concrete theme values there; web keeps the CSS vars.
|
|
113
|
+
const theme = useTheme();
|
|
111
114
|
const [pending, setPending] = useState(false);
|
|
112
115
|
const [actionError, setActionError] = useState<string | null>(null);
|
|
113
116
|
// Optimistic flip for the live (toggle_like) path — reverted on failure,
|
|
@@ -282,7 +285,15 @@ function FrappeLikedByBody({
|
|
|
282
285
|
<HeartIcon
|
|
283
286
|
size={16}
|
|
284
287
|
weight={liked ? "fill" : "regular"}
|
|
285
|
-
color={
|
|
288
|
+
color={
|
|
289
|
+
liked
|
|
290
|
+
? isWeb
|
|
291
|
+
? "var(--red10)"
|
|
292
|
+
: theme.red10?.val
|
|
293
|
+
: isWeb
|
|
294
|
+
? "currentColor"
|
|
295
|
+
: theme.color?.val
|
|
296
|
+
}
|
|
286
297
|
/>
|
|
287
298
|
}
|
|
288
299
|
/>
|
package/src/FrappeListView.tsx
CHANGED
|
@@ -17,12 +17,31 @@ import {
|
|
|
17
17
|
} from "tamagui";
|
|
18
18
|
import { SavedFilterDropdown, useSavedFilters, type ParsedFilter } from "@multiplatform.one/table";
|
|
19
19
|
import { ViewSwitcher } from "@multiplatform.one/components";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
MIN_PRESS_TARGET,
|
|
22
|
+
pressTargetHitSlop,
|
|
23
|
+
pressTargetStyle,
|
|
24
|
+
useResolvedKnobs,
|
|
25
|
+
} from "@multiplatform.one/theme";
|
|
21
26
|
import { storage } from "@multiplatform.one/store";
|
|
22
27
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
23
28
|
import { FrappeList } from "./FrappeList";
|
|
24
29
|
import { FrappeTable } from "./FrappeTable";
|
|
25
30
|
|
|
31
|
+
// DG-LAY-04 / D-02 press-floor: the chromeless $2 refresh button paints
|
|
32
|
+
// ~28×28; the press box is floored at 44 via the house pressTarget* channel
|
|
33
|
+
// (grown transparent box + negative outset + hitSlop). The horizontal outset
|
|
34
|
+
// (8px) stays under the toolbar gap, so the enlarged target never reaches the
|
|
35
|
+
// adjacent Add button's box.
|
|
36
|
+
const REFRESH_VISUAL = 28;
|
|
37
|
+
const REFRESH_OUTSET = Math.ceil((MIN_PRESS_TARGET - REFRESH_VISUAL) / 2);
|
|
38
|
+
const refreshPressFloorProps = {
|
|
39
|
+
...pressTargetStyle(),
|
|
40
|
+
marginVertical: -REFRESH_OUTSET,
|
|
41
|
+
marginHorizontal: -REFRESH_OUTSET,
|
|
42
|
+
hitSlop: pressTargetHitSlop(REFRESH_VISUAL),
|
|
43
|
+
} as const;
|
|
44
|
+
|
|
26
45
|
interface ListFieldConfig {
|
|
27
46
|
key: string;
|
|
28
47
|
label?: string;
|
|
@@ -481,6 +500,7 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
481
500
|
icon={ArrowsClockwiseIcon}
|
|
482
501
|
onPress={handleRefresh}
|
|
483
502
|
aria-label={t("Refresh")}
|
|
503
|
+
{...refreshPressFloorProps}
|
|
484
504
|
/>
|
|
485
505
|
{onAdd && (
|
|
486
506
|
<Button size="$3" theme="accent" icon={PlusIcon} onPress={onAdd}>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { InMemoryFixtureProvider } from "@multiplatform.one/frappe";
|
|
2
2
|
import { action } from "@multiplatform.one/storybook";
|
|
3
3
|
import type { DataTableColumn } from "@multiplatform.one/table";
|
|
4
|
-
|
|
4
|
+
// Catalog Text (G-15 story honesty / D-05).
|
|
5
|
+
import { Text } from "@multiplatform.one/components";
|
|
5
6
|
import { FrappeTable } from "./FrappeTable";
|
|
6
7
|
import { FrappeProvider } from "./FrappeProvider";
|
|
7
8
|
import { FrappeStoryProvider } from "./frappeStoryTarget";
|
|
@@ -14,12 +15,88 @@ export default {
|
|
|
14
15
|
docs: {
|
|
15
16
|
description: {
|
|
16
17
|
component:
|
|
17
|
-
"Table over useFrappeCollection / useLiveQuery (client) or Frappe REST (serverSide).
|
|
18
|
+
"Table over useFrappeCollection / useLiveQuery (client) or Frappe REST (serverSide). Fixture stories are network-hermetic (G-15/D-05): documents come from InMemoryFixtureProvider and DocType meta from an in-story fetch mock, so nothing leaves the machine. The separately-named Live and ServerSide stories are the live-bench arm — they target STORYBOOK_FRAPPE_URL when reachable and fall back to fixtures otherwise.",
|
|
18
19
|
},
|
|
19
20
|
},
|
|
20
21
|
},
|
|
21
22
|
};
|
|
22
23
|
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Hermetic story host (G-15 story honesty / D-05, closes UX-P18).
|
|
26
|
+
//
|
|
27
|
+
// Fixture-backed stories previously pointed at https://demo.frappe.cloud. The
|
|
28
|
+
// fixture provider serves the *collection*, but FrappeTable still resolves
|
|
29
|
+
// DocType meta over HTTP — so every one of those stories fired a real
|
|
30
|
+
// cross-origin request that the browser rejected with a CORS error, poisoning
|
|
31
|
+
// the console for every automated probe. MOCK_HOST keeps the same code path
|
|
32
|
+
// (real fetch, real meta shape) without leaving the machine; ERR_HOST is the
|
|
33
|
+
// deliberate failure host for the error-state story.
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
const MOCK_HOST = "https://frappetable.mock.test";
|
|
37
|
+
const ERR_HOST = "https://forbidden.frappetable.mock.test";
|
|
38
|
+
|
|
39
|
+
function customerMetaRaw(name: string) {
|
|
40
|
+
return {
|
|
41
|
+
name,
|
|
42
|
+
module: "Selling",
|
|
43
|
+
title_field: "customer_name",
|
|
44
|
+
fields: [
|
|
45
|
+
{ fieldname: "customer_name", fieldtype: "Data", label: "Customer Name", in_list_view: 1 },
|
|
46
|
+
{
|
|
47
|
+
fieldname: "customer_type",
|
|
48
|
+
fieldtype: "Select",
|
|
49
|
+
label: "Customer Type",
|
|
50
|
+
options: "Company\nIndividual",
|
|
51
|
+
in_list_view: 1,
|
|
52
|
+
in_standard_filter: 1,
|
|
53
|
+
},
|
|
54
|
+
{ fieldname: "territory", fieldtype: "Data", label: "Territory", in_list_view: 1 },
|
|
55
|
+
{
|
|
56
|
+
fieldname: "status",
|
|
57
|
+
fieldtype: "Select",
|
|
58
|
+
label: "Status",
|
|
59
|
+
options: "Active\nInactive\nLead",
|
|
60
|
+
in_list_view: 1,
|
|
61
|
+
in_standard_filter: 1,
|
|
62
|
+
},
|
|
63
|
+
{ fieldname: "creation", fieldtype: "Date", label: "Created On" },
|
|
64
|
+
],
|
|
65
|
+
permissions: [{ role: "All", read: 1, write: 1, create: 1 }],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function jsonResponse(body: unknown, status = 200): Response {
|
|
70
|
+
return new Response(JSON.stringify(body), {
|
|
71
|
+
status,
|
|
72
|
+
headers: { "Content-Type": "application/json" },
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
(() => {
|
|
77
|
+
if (typeof window === "undefined") return;
|
|
78
|
+
const w = window as unknown as Record<string, unknown>;
|
|
79
|
+
if (w.__frappeTableMockFetch) return;
|
|
80
|
+
w.__frappeTableMockFetch = true;
|
|
81
|
+
const realFetch = window.fetch.bind(window);
|
|
82
|
+
window.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
|
|
83
|
+
const urlStr =
|
|
84
|
+
typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
85
|
+
if (urlStr.startsWith(ERR_HOST)) return jsonResponse({ message: "Not permitted" }, 403);
|
|
86
|
+
if (urlStr.startsWith(MOCK_HOST)) {
|
|
87
|
+
const url = new URL(urlStr);
|
|
88
|
+
const metaMatch = url.pathname.match(/^\/api\/resource\/DocType\/(.+)$/);
|
|
89
|
+
if (metaMatch) return jsonResponse({ data: customerMetaRaw(decodeURIComponent(metaMatch[1])) });
|
|
90
|
+
if (url.pathname === "/api/resource/DocType") {
|
|
91
|
+
return jsonResponse({ data: [{ name: "Customer", module: "Selling" }] });
|
|
92
|
+
}
|
|
93
|
+
// Everything else (guest field-peek, counts): empty, never the network.
|
|
94
|
+
return jsonResponse({ data: [] });
|
|
95
|
+
}
|
|
96
|
+
return realFetch(input as RequestInfo, init);
|
|
97
|
+
};
|
|
98
|
+
})();
|
|
99
|
+
|
|
23
100
|
interface Customer {
|
|
24
101
|
name: string;
|
|
25
102
|
doctype: string;
|
|
@@ -135,7 +212,7 @@ const customerColumns: DataTableColumn<Partial<Customer>>[] = [
|
|
|
135
212
|
|
|
136
213
|
export const Default = () => (
|
|
137
214
|
<FrappeProvider
|
|
138
|
-
baseURL=
|
|
215
|
+
baseURL={MOCK_HOST}
|
|
139
216
|
fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
|
|
140
217
|
>
|
|
141
218
|
<FrappeTable<Customer>
|
|
@@ -159,7 +236,7 @@ Default.parameters = {
|
|
|
159
236
|
Default.storyName = "Main";
|
|
160
237
|
export const WithPagination = () => (
|
|
161
238
|
<FrappeProvider
|
|
162
|
-
baseURL=
|
|
239
|
+
baseURL={MOCK_HOST}
|
|
163
240
|
fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
|
|
164
241
|
>
|
|
165
242
|
<FrappeTable<Customer>
|
|
@@ -181,7 +258,7 @@ WithPagination.parameters = {
|
|
|
181
258
|
|
|
182
259
|
export const WithSavedFilters = () => (
|
|
183
260
|
<FrappeProvider
|
|
184
|
-
baseURL=
|
|
261
|
+
baseURL={MOCK_HOST}
|
|
185
262
|
fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
|
|
186
263
|
>
|
|
187
264
|
<FrappeTable<Customer>
|
|
@@ -298,7 +375,7 @@ class PendingFixtureProvider extends InMemoryFixtureProvider {
|
|
|
298
375
|
|
|
299
376
|
/** Collection stuck syncing: the built-in loading panel renders (W9 / DG-ST-02). */
|
|
300
377
|
export const Loading = () => (
|
|
301
|
-
<FrappeProvider baseURL=
|
|
378
|
+
<FrappeProvider baseURL={MOCK_HOST} fixtures={new PendingFixtureProvider()}>
|
|
302
379
|
<FrappeTable<Customer> doctype="Customer" columns={customerColumns} />
|
|
303
380
|
</FrappeProvider>
|
|
304
381
|
);
|
|
@@ -306,7 +383,7 @@ export const Loading = () => (
|
|
|
306
383
|
/** Zero documents, no filters, no failure — "No Customer records found" (empty ≠ error). */
|
|
307
384
|
export const Empty = () => (
|
|
308
385
|
<FrappeProvider
|
|
309
|
-
baseURL=
|
|
386
|
+
baseURL={MOCK_HOST}
|
|
310
387
|
fixtures={new InMemoryFixtureProvider({ Customer: [] })}
|
|
311
388
|
>
|
|
312
389
|
<FrappeTable<Customer> doctype="Customer" columns={customerColumns} />
|
|
@@ -320,7 +397,7 @@ export const Empty = () => (
|
|
|
320
397
|
*/
|
|
321
398
|
export const NoResults = () => (
|
|
322
399
|
<FrappeProvider
|
|
323
|
-
baseURL=
|
|
400
|
+
baseURL={MOCK_HOST}
|
|
324
401
|
fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
|
|
325
402
|
>
|
|
326
403
|
<FrappeTable<Customer>
|
|
@@ -341,13 +418,15 @@ export const NoResults = () => (
|
|
|
341
418
|
);
|
|
342
419
|
|
|
343
420
|
/**
|
|
344
|
-
*
|
|
345
|
-
*
|
|
421
|
+
* Collection that fails with no fixtures: the built-in error panel renders
|
|
422
|
+
* instead of empty chrome (DG-ST-01). The failure is served hermetically —
|
|
423
|
+
* the in-story mock answers ERR_HOST with 403, so the error state is
|
|
424
|
+
* reproducible offline instead of depending on a DNS miss. Note: no retry
|
|
346
425
|
* affordance exists on this panel — tracked as a component gap in
|
|
347
426
|
* p-results/state-triplet-coverage.md.
|
|
348
427
|
*/
|
|
349
428
|
export const LoadError = () => (
|
|
350
|
-
<FrappeProvider baseURL=
|
|
429
|
+
<FrappeProvider baseURL={ERR_HOST}>
|
|
351
430
|
<FrappeTable<Customer> doctype="Customer" columns={customerColumns} />
|
|
352
431
|
</FrappeProvider>
|
|
353
432
|
);
|
|
@@ -402,7 +481,7 @@ const customerFilterFields = [
|
|
|
402
481
|
*/
|
|
403
482
|
export const HiddenFieldFilters = () => (
|
|
404
483
|
<FrappeProvider
|
|
405
|
-
baseURL=
|
|
484
|
+
baseURL={MOCK_HOST}
|
|
406
485
|
fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
|
|
407
486
|
>
|
|
408
487
|
<FrappeTable<Customer>
|
package/src/fieldRegistry.ts
CHANGED
|
@@ -1064,7 +1064,7 @@ export function fieldtypeToTableField(
|
|
|
1064
1064
|
onChange: onCellChange,
|
|
1065
1065
|
doctype: rowDoctype,
|
|
1066
1066
|
compact: true,
|
|
1067
|
-
disabled: !rowDoctype || context?.disabled,
|
|
1067
|
+
disabled: Boolean(!rowDoctype || context?.disabled),
|
|
1068
1068
|
// D-18.4: read-only cells block commits, so the combobox must
|
|
1069
1069
|
// render its non-interactive representation.
|
|
1070
1070
|
readOnly: context?.readOnly,
|
|
@@ -40,6 +40,31 @@ export type DateProps<
|
|
|
40
40
|
inputProps?: Record<string, unknown>;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
const pad2 = (n: number) => String(n).padStart(2, "0");
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Format a picked Date back into the Frappe wire shape for the fieldtype:
|
|
47
|
+
* `YYYY-MM-DD` (Date), `YYYY-MM-DD HH:mm:ss` (Datetime — the picker edits
|
|
48
|
+
* only the date part, so an existing time part on the previous value is
|
|
49
|
+
* preserved), `HH:mm:ss` (Time). Local date parts — Frappe date strings are
|
|
50
|
+
* timezone-naive (same contract as FrappeCalendar's toFrappeFieldValue).
|
|
51
|
+
*/
|
|
52
|
+
function toFrappeDateValue(
|
|
53
|
+
date: globalThis.Date,
|
|
54
|
+
type: "date" | "datetime" | "time",
|
|
55
|
+
previousValue: string | undefined,
|
|
56
|
+
): string {
|
|
57
|
+
const datePart = `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
|
|
58
|
+
if (type === "time") {
|
|
59
|
+
return `${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;
|
|
60
|
+
}
|
|
61
|
+
if (type === "datetime") {
|
|
62
|
+
const previousTime = previousValue?.trim().split(/[ T]/)[1];
|
|
63
|
+
return `${datePart} ${previousTime ?? "00:00:00"}`;
|
|
64
|
+
}
|
|
65
|
+
return datePart;
|
|
66
|
+
}
|
|
67
|
+
|
|
43
68
|
export function Date<
|
|
44
69
|
TData extends Record<string, unknown> = Record<string, unknown>,
|
|
45
70
|
TName extends string = string,
|
|
@@ -51,11 +76,11 @@ export function Date<
|
|
|
51
76
|
mode,
|
|
52
77
|
name,
|
|
53
78
|
onBlur,
|
|
54
|
-
onChange
|
|
79
|
+
onChange,
|
|
55
80
|
preserveValue,
|
|
56
81
|
validators,
|
|
57
82
|
disabled,
|
|
58
|
-
value
|
|
83
|
+
value,
|
|
59
84
|
type = "date",
|
|
60
85
|
...fieldProps
|
|
61
86
|
} = useProps(props) as DateProps<TData, TName> & Record<string, unknown>;
|
|
@@ -65,7 +90,26 @@ export function Date<
|
|
|
65
90
|
name={name}
|
|
66
91
|
form={form}
|
|
67
92
|
validators={validators}
|
|
68
|
-
|
|
93
|
+
// Controlled pass-through: folding `value` into `defaultValue` was
|
|
94
|
+
// mount-only, so a value arriving after first paint (create-mode
|
|
95
|
+
// engine seeding) never displayed — and `onChange` was dropped, so
|
|
96
|
+
// picks never reached the consumer doc. `undefined` stays undefined so
|
|
97
|
+
// uncontrolled (defaultValue-only) use keeps its semantics.
|
|
98
|
+
value={value as string | undefined}
|
|
99
|
+
onChange={(date) => {
|
|
100
|
+
const emit = onChange as ((v: string) => void) | undefined;
|
|
101
|
+
if (!emit) return;
|
|
102
|
+
emit(
|
|
103
|
+
date
|
|
104
|
+
? toFrappeDateValue(
|
|
105
|
+
date,
|
|
106
|
+
type as "date" | "datetime" | "time",
|
|
107
|
+
value as string | undefined,
|
|
108
|
+
)
|
|
109
|
+
: "",
|
|
110
|
+
);
|
|
111
|
+
}}
|
|
112
|
+
defaultValue={defaultValue as string}
|
|
69
113
|
label={fieldProps.label}
|
|
70
114
|
labelProps={fieldProps.labelProps}
|
|
71
115
|
error={fieldProps.error}
|