@multiplatform.one/frappe-ui 7.6.3 → 7.7.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/ChartCard.cjs +52 -0
- package/dist/cjs/ChartCard.native.js +72 -0
- package/dist/cjs/ChartCard.native.js.map +1 -0
- package/dist/cjs/FileBrowser/AttachLibrary.cjs +2 -2
- package/dist/cjs/FileBrowser/AttachLibrary.native.js +8 -2
- package/dist/cjs/FileBrowser/AttachLibrary.native.js.map +1 -1
- package/dist/cjs/FrappeChartCard.cjs +3 -3
- package/dist/cjs/FrappeChartCard.native.js +3 -3
- package/dist/cjs/FrappeChartCard.native.js.map +1 -1
- package/dist/cjs/FrappeDashboard.cjs +6 -27
- package/dist/cjs/FrappeDashboard.native.js +6 -33
- package/dist/cjs/FrappeDashboard.native.js.map +1 -1
- package/dist/cjs/FrappeImageView.cjs +2 -8
- package/dist/cjs/FrappeImageView.native.js +2 -9
- package/dist/cjs/FrappeImageView.native.js.map +1 -1
- package/dist/cjs/fields/CodeEditor/index.cjs +4 -0
- package/dist/cjs/fields/CodeEditor/index.native.js +4 -0
- package/dist/cjs/fields/CodeEditor/index.native.js.map +1 -1
- package/dist/cjs/fields/LinkTree.cjs +5 -3
- package/dist/cjs/fields/LinkTree.native.js +9 -5
- package/dist/cjs/fields/LinkTree.native.js.map +1 -1
- package/dist/cjs/formEngine/createPrefill.cjs +37 -0
- package/dist/cjs/formEngine/createPrefill.native.js +40 -0
- package/dist/cjs/formEngine/createPrefill.native.js.map +1 -0
- package/dist/cjs/formEngine/dirtyTracking.cjs +55 -0
- package/dist/cjs/formEngine/dirtyTracking.native.js +77 -0
- package/dist/cjs/formEngine/dirtyTracking.native.js.map +1 -0
- package/dist/cjs/formEngine/doctypeMeta.cjs +18 -0
- package/dist/cjs/formEngine/doctypeMeta.native.js +21 -0
- package/dist/cjs/formEngine/doctypeMeta.native.js.map +1 -0
- package/dist/cjs/formEngine/fetchFrom.cjs +67 -0
- package/dist/cjs/formEngine/fetchFrom.native.js +110 -0
- package/dist/cjs/formEngine/fetchFrom.native.js.map +1 -0
- package/dist/cjs/formEngine/fieldPermissions.cjs +55 -0
- package/dist/cjs/formEngine/fieldPermissions.native.js +80 -0
- package/dist/cjs/formEngine/fieldPermissions.native.js.map +1 -0
- package/dist/cjs/formEngine/formActions.cjs +189 -0
- package/dist/cjs/formEngine/formActions.native.js +199 -0
- package/dist/cjs/formEngine/formActions.native.js.map +1 -0
- package/dist/cjs/formEngine/formLayout.cjs +245 -0
- package/dist/cjs/formEngine/formLayout.native.js +388 -0
- package/dist/cjs/formEngine/formLayout.native.js.map +1 -0
- package/dist/cjs/formEngine/index.cjs +48 -0
- package/dist/cjs/formEngine/index.native.js +51 -0
- package/dist/cjs/formEngine/index.native.js.map +1 -0
- package/dist/cjs/formEngine/useFormEngine.cjs +387 -0
- package/dist/cjs/formEngine/useFormEngine.native.js +476 -0
- package/dist/cjs/formEngine/useFormEngine.native.js.map +1 -0
- package/dist/cjs/frappeStoryTarget.cjs +4 -2
- package/dist/cjs/frappeStoryTarget.native.js +4 -3
- package/dist/cjs/frappeStoryTarget.native.js.map +1 -1
- package/dist/cjs/index.cjs +19 -1
- package/dist/cjs/index.native.js +19 -1
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/ChartCard.mjs +27 -0
- package/dist/esm/ChartCard.mjs.map +1 -0
- package/dist/esm/ChartCard.native.js +33 -0
- package/dist/esm/ChartCard.native.js.map +1 -0
- package/dist/esm/FileBrowser/AttachLibrary.mjs +2 -2
- package/dist/esm/FileBrowser/AttachLibrary.mjs.map +1 -1
- package/dist/esm/FileBrowser/AttachLibrary.native.js +8 -2
- package/dist/esm/FileBrowser/AttachLibrary.native.js.map +1 -1
- package/dist/esm/FrappeChartCard.mjs +1 -1
- package/dist/esm/FrappeChartCard.native.js +1 -1
- package/dist/esm/FrappeChartCard.native.js.map +1 -1
- package/dist/esm/FrappeDashboard.mjs +6 -27
- package/dist/esm/FrappeDashboard.mjs.map +1 -1
- package/dist/esm/FrappeDashboard.native.js +6 -33
- package/dist/esm/FrappeDashboard.native.js.map +1 -1
- package/dist/esm/FrappeImageView.mjs +2 -7
- package/dist/esm/FrappeImageView.mjs.map +1 -1
- package/dist/esm/FrappeImageView.native.js +2 -8
- package/dist/esm/FrappeImageView.native.js.map +1 -1
- package/dist/esm/fields/CodeEditor/index.mjs +4 -0
- package/dist/esm/fields/CodeEditor/index.mjs.map +1 -1
- package/dist/esm/fields/CodeEditor/index.native.js +4 -0
- package/dist/esm/fields/CodeEditor/index.native.js.map +1 -1
- package/dist/esm/fields/LinkTree.mjs +5 -3
- package/dist/esm/fields/LinkTree.mjs.map +1 -1
- package/dist/esm/fields/LinkTree.native.js +9 -5
- package/dist/esm/fields/LinkTree.native.js.map +1 -1
- package/dist/esm/formEngine/createPrefill.mjs +11 -0
- package/dist/esm/formEngine/createPrefill.mjs.map +1 -0
- package/dist/esm/formEngine/createPrefill.native.js +11 -0
- package/dist/esm/formEngine/createPrefill.native.js.map +1 -0
- package/dist/esm/formEngine/dirtyTracking.mjs +28 -0
- package/dist/esm/formEngine/dirtyTracking.mjs.map +1 -0
- package/dist/esm/formEngine/dirtyTracking.native.js +47 -0
- package/dist/esm/formEngine/dirtyTracking.native.js.map +1 -0
- package/dist/esm/formEngine/doctypeMeta.mjs +2 -0
- package/dist/esm/formEngine/doctypeMeta.mjs.map +1 -0
- package/dist/esm/formEngine/doctypeMeta.native.js +2 -0
- package/dist/esm/formEngine/doctypeMeta.native.js.map +1 -0
- package/dist/esm/formEngine/fetchFrom.mjs +40 -0
- package/dist/esm/formEngine/fetchFrom.mjs.map +1 -0
- package/dist/esm/formEngine/fetchFrom.native.js +80 -0
- package/dist/esm/formEngine/fetchFrom.native.js.map +1 -0
- package/dist/esm/formEngine/fieldPermissions.mjs +28 -0
- package/dist/esm/formEngine/fieldPermissions.mjs.map +1 -0
- package/dist/esm/formEngine/fieldPermissions.native.js +50 -0
- package/dist/esm/formEngine/fieldPermissions.native.js.map +1 -0
- package/dist/esm/formEngine/formActions.mjs +146 -0
- package/dist/esm/formEngine/formActions.mjs.map +1 -0
- package/dist/esm/formEngine/formActions.native.js +153 -0
- package/dist/esm/formEngine/formActions.native.js.map +1 -0
- package/dist/esm/formEngine/formLayout.mjs +217 -0
- package/dist/esm/formEngine/formLayout.mjs.map +1 -0
- package/dist/esm/formEngine/formLayout.native.js +357 -0
- package/dist/esm/formEngine/formLayout.native.js.map +1 -0
- package/dist/esm/formEngine/index.mjs +8 -0
- package/dist/esm/formEngine/index.mjs.map +1 -0
- package/dist/esm/formEngine/index.native.js +8 -0
- package/dist/esm/formEngine/index.native.js.map +1 -0
- package/dist/esm/formEngine/useFormEngine.mjs +362 -0
- package/dist/esm/formEngine/useFormEngine.mjs.map +1 -0
- package/dist/esm/formEngine/useFormEngine.native.js +448 -0
- package/dist/esm/formEngine/useFormEngine.native.js.map +1 -0
- package/dist/esm/frappeStoryTarget.mjs +4 -1
- package/dist/esm/frappeStoryTarget.mjs.map +1 -1
- package/dist/esm/frappeStoryTarget.native.js +4 -2
- package/dist/esm/frappeStoryTarget.native.js.map +1 -1
- package/dist/esm/index.mjs +4 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +4 -2
- package/dist/esm/index.native.js.map +1 -1
- package/dist/jsx/ChartCard.mjs +27 -0
- package/dist/jsx/ChartCard.mjs.map +1 -0
- package/dist/jsx/ChartCard.native.js +72 -0
- package/dist/jsx/ChartCard.native.js.map +1 -0
- package/dist/jsx/FileBrowser/AttachLibrary.mjs +2 -2
- package/dist/jsx/FileBrowser/AttachLibrary.mjs.map +1 -1
- package/dist/jsx/FileBrowser/AttachLibrary.native.js +8 -2
- package/dist/jsx/FileBrowser/AttachLibrary.native.js.map +1 -1
- package/dist/jsx/FrappeChartCard.mjs +1 -1
- package/dist/jsx/FrappeChartCard.native.js +3 -3
- package/dist/jsx/FrappeChartCard.native.js.map +1 -1
- package/dist/jsx/FrappeDashboard.mjs +6 -27
- package/dist/jsx/FrappeDashboard.mjs.map +1 -1
- package/dist/jsx/FrappeDashboard.native.js +6 -33
- package/dist/jsx/FrappeDashboard.native.js.map +1 -1
- package/dist/jsx/FrappeImageView.mjs +2 -7
- package/dist/jsx/FrappeImageView.mjs.map +1 -1
- package/dist/jsx/FrappeImageView.native.js +2 -9
- package/dist/jsx/FrappeImageView.native.js.map +1 -1
- package/dist/jsx/fields/CodeEditor/index.mjs +4 -0
- package/dist/jsx/fields/CodeEditor/index.mjs.map +1 -1
- package/dist/jsx/fields/CodeEditor/index.native.js +4 -0
- package/dist/jsx/fields/CodeEditor/index.native.js.map +1 -1
- package/dist/jsx/fields/LinkTree.mjs +5 -3
- package/dist/jsx/fields/LinkTree.mjs.map +1 -1
- package/dist/jsx/fields/LinkTree.native.js +9 -5
- package/dist/jsx/fields/LinkTree.native.js.map +1 -1
- package/dist/jsx/formEngine/createPrefill.mjs +11 -0
- package/dist/jsx/formEngine/createPrefill.mjs.map +1 -0
- package/dist/jsx/formEngine/createPrefill.native.js +40 -0
- package/dist/jsx/formEngine/createPrefill.native.js.map +1 -0
- package/dist/jsx/formEngine/dirtyTracking.mjs +28 -0
- package/dist/jsx/formEngine/dirtyTracking.mjs.map +1 -0
- package/dist/jsx/formEngine/dirtyTracking.native.js +77 -0
- package/dist/jsx/formEngine/dirtyTracking.native.js.map +1 -0
- package/dist/jsx/formEngine/doctypeMeta.mjs +2 -0
- package/dist/jsx/formEngine/doctypeMeta.mjs.map +1 -0
- package/dist/jsx/formEngine/doctypeMeta.native.js +21 -0
- package/dist/jsx/formEngine/doctypeMeta.native.js.map +1 -0
- package/dist/jsx/formEngine/fetchFrom.mjs +40 -0
- package/dist/jsx/formEngine/fetchFrom.mjs.map +1 -0
- package/dist/jsx/formEngine/fetchFrom.native.js +110 -0
- package/dist/jsx/formEngine/fetchFrom.native.js.map +1 -0
- package/dist/jsx/formEngine/fieldPermissions.mjs +28 -0
- package/dist/jsx/formEngine/fieldPermissions.mjs.map +1 -0
- package/dist/jsx/formEngine/fieldPermissions.native.js +80 -0
- package/dist/jsx/formEngine/fieldPermissions.native.js.map +1 -0
- package/dist/jsx/formEngine/formActions.mjs +146 -0
- package/dist/jsx/formEngine/formActions.mjs.map +1 -0
- package/dist/jsx/formEngine/formActions.native.js +199 -0
- package/dist/jsx/formEngine/formActions.native.js.map +1 -0
- package/dist/jsx/formEngine/formLayout.mjs +217 -0
- package/dist/jsx/formEngine/formLayout.mjs.map +1 -0
- package/dist/jsx/formEngine/formLayout.native.js +388 -0
- package/dist/jsx/formEngine/formLayout.native.js.map +1 -0
- package/dist/jsx/formEngine/index.mjs +8 -0
- package/dist/jsx/formEngine/index.mjs.map +1 -0
- package/dist/jsx/formEngine/index.native.js +51 -0
- package/dist/jsx/formEngine/index.native.js.map +1 -0
- package/dist/jsx/formEngine/useFormEngine.mjs +362 -0
- package/dist/jsx/formEngine/useFormEngine.mjs.map +1 -0
- package/dist/jsx/formEngine/useFormEngine.native.js +476 -0
- package/dist/jsx/formEngine/useFormEngine.native.js.map +1 -0
- package/dist/jsx/frappeStoryTarget.mjs +4 -1
- package/dist/jsx/frappeStoryTarget.mjs.map +1 -1
- package/dist/jsx/frappeStoryTarget.native.js +4 -3
- package/dist/jsx/frappeStoryTarget.native.js.map +1 -1
- package/dist/jsx/index.js +4 -2
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +4 -2
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +19 -1
- package/dist/jsx/index.native.js.map +1 -1
- package/package.json +23 -17
- package/src/ChartCard.tsx +31 -0
- package/src/FileBrowser/AttachLibrary.tsx +13 -1
- package/src/FileBrowser/FileBrowser.spec.tsx +16 -0
- package/src/FileBrowser/FileBrowser.stories.tsx +18 -1
- package/src/FileBrowser/folderTree.spec.tsx +68 -0
- package/src/FrappeCalendar.stories.tsx +1 -2
- package/src/FrappeChartCard.stories.tsx +1 -1
- package/src/FrappeChartCard.tsx +1 -1
- package/src/FrappeDashboard.stories.tsx +6 -5
- package/src/FrappeDashboard.tsx +6 -33
- package/src/FrappeGantt.stories.tsx +1 -2
- package/src/FrappeImageView.tsx +16 -15
- package/src/FrappeList.stories.tsx +3 -10
- package/src/classicScriptSafety.spec.ts +47 -0
- package/src/components/attachments.stories.tsx +9 -2
- package/src/dependsOn.ts +2 -2
- package/src/desk/DeskFormSidebar.stories.tsx +19 -1
- package/src/fields/CodeEditor/CodeEditor.spec.tsx +37 -0
- package/src/fields/CodeEditor/CodeEditor.stories.tsx +83 -66
- package/src/fields/CodeEditor/index.tsx +4 -0
- package/src/fields/DateRange/DateRange.spec.tsx +143 -0
- package/src/fields/FileUpload.spec.tsx +334 -0
- package/src/fields/FileUploadField/FileUploadField.spec.tsx +166 -0
- package/src/fields/HTML/Html.spec.tsx +179 -0
- package/src/fields/Icon/Icon.stories.tsx +138 -0
- package/src/fields/Link.stories.tsx +2 -0
- package/src/fields/LinkTree.tsx +18 -3
- package/src/fields/LongText/LongText.spec.tsx +217 -0
- package/src/fields/OTPInput/OTPInput.spec.tsx +167 -0
- package/src/fields/Password/Password.stories.tsx +21 -0
- package/src/fields/Phone/Phone.spec.tsx +151 -0
- package/src/fields/Progress/Progress.spec.tsx +160 -0
- package/src/fields/ReadOnly/ReadOnly.spec.tsx +229 -0
- package/src/fields/SmallText/SmallText.spec.tsx +175 -0
- package/src/fields/shared/EditorPreviewPanes.spec.tsx +122 -0
- package/src/formEngine/createPrefill.ts +28 -0
- package/src/formEngine/dirtyTracking.spec.ts +91 -0
- package/src/formEngine/dirtyTracking.ts +64 -0
- package/src/formEngine/doctypeMeta.ts +117 -0
- package/src/formEngine/fetchFrom.spec.ts +92 -0
- package/src/formEngine/fetchFrom.ts +111 -0
- package/src/formEngine/fieldPermissions.spec.ts +61 -0
- package/src/formEngine/fieldPermissions.ts +68 -0
- package/src/formEngine/formActions.ts +285 -0
- package/src/formEngine/formLayout.spec.ts +373 -0
- package/src/formEngine/formLayout.ts +392 -0
- package/src/formEngine/index.ts +33 -0
- package/src/formEngine/seam.spec.ts +148 -0
- package/src/formEngine/useFormEngine.ts +496 -0
- package/src/frappeRemainder.designLaw.spec.ts +9 -0
- package/src/frappeStoryTarget.tsx +25 -9
- package/src/frappeViews.designLaw.spec.ts +1 -0
- package/src/index.spec.ts +7 -3
- package/src/index.ts +51 -1
- package/src/schemaForm/SchemaForm.spec.tsx +4 -1
- package/types/ChartCard.d.ts +13 -0
- package/types/ChartCard.d.ts.map +1 -0
- package/types/FileBrowser/AttachLibrary.d.ts.map +1 -1
- package/types/FrappeDashboard.d.ts +2 -10
- package/types/FrappeDashboard.d.ts.map +1 -1
- package/types/FrappeImageView.d.ts.map +1 -1
- package/types/dependsOn.d.ts +2 -2
- package/types/fields/CodeEditor/index.d.ts.map +1 -1
- package/types/fields/LinkTree.d.ts.map +1 -1
- package/types/formEngine/createPrefill.d.ts +19 -0
- package/types/formEngine/createPrefill.d.ts.map +1 -0
- package/types/formEngine/dirtyTracking.d.ts +36 -0
- package/types/formEngine/dirtyTracking.d.ts.map +1 -0
- package/types/formEngine/doctypeMeta.d.ts +117 -0
- package/types/formEngine/doctypeMeta.d.ts.map +1 -0
- package/types/formEngine/fetchFrom.d.ts +43 -0
- package/types/formEngine/fetchFrom.d.ts.map +1 -0
- package/types/formEngine/fieldPermissions.d.ts +38 -0
- package/types/formEngine/fieldPermissions.d.ts.map +1 -0
- package/types/formEngine/formActions.d.ts +95 -0
- package/types/formEngine/formActions.d.ts.map +1 -0
- package/types/formEngine/formLayout.d.ts +91 -0
- package/types/formEngine/formLayout.d.ts.map +1 -0
- package/types/formEngine/index.d.ts +27 -0
- package/types/formEngine/index.d.ts.map +1 -0
- package/types/formEngine/useFormEngine.d.ts +61 -0
- package/types/formEngine/useFormEngine.d.ts.map +1 -0
- package/types/frappeStoryTarget.d.ts +2 -2
- package/types/frappeStoryTarget.d.ts.map +1 -1
- package/types/index.d.ts +4 -1
- package/types/index.d.ts.map +1 -1
package/src/FrappeDashboard.tsx
CHANGED
|
@@ -3,13 +3,7 @@ import {
|
|
|
3
3
|
useFrappeDoctypeEvents,
|
|
4
4
|
useLiveQuery,
|
|
5
5
|
} from "@multiplatform.one/frappe";
|
|
6
|
-
import {
|
|
7
|
-
ChartCard as BaseChartCard,
|
|
8
|
-
Dashboard,
|
|
9
|
-
type ChartCardProps,
|
|
10
|
-
type ChartDataPoint,
|
|
11
|
-
type DashboardWidget,
|
|
12
|
-
} from "@multiplatform.one/components";
|
|
6
|
+
import { Dashboard, type DashboardWidget } from "@multiplatform.one/components";
|
|
13
7
|
import { Button, Spinner, formCommonColors } from "@multiplatform.one/forms";
|
|
14
8
|
import { ArrowsClockwiseIcon } from "@phosphor-icons/react";
|
|
15
9
|
import React, { useMemo, useCallback, useState, useEffect, useRef } from "react";
|
|
@@ -168,7 +162,7 @@ function LiveDashboardContent<TDoc extends { name: string; doctype: string }>({
|
|
|
168
162
|
return (
|
|
169
163
|
<YStack {...knobProps.panelPadding} alignItems="center" {...stackProps}>
|
|
170
164
|
<Spinner size="large" />
|
|
171
|
-
<Text color={
|
|
165
|
+
<Text color={knobProps.textAccentColor} marginTop="$2" {...knobProps.body}>
|
|
172
166
|
{t("Loading dashboard...")}
|
|
173
167
|
</Text>
|
|
174
168
|
</YStack>
|
|
@@ -181,7 +175,7 @@ function LiveDashboardContent<TDoc extends { name: string; doctype: string }>({
|
|
|
181
175
|
return (
|
|
182
176
|
<YStack {...knobProps.panelPadding} alignItems="center" {...stackProps} {...knobProps.gap}>
|
|
183
177
|
<Text color={formCommonColors.error}>{t("Failed to load dashboard")}</Text>
|
|
184
|
-
<Text color={
|
|
178
|
+
<Text color={knobProps.textAccentColor} {...knobProps.body}>
|
|
185
179
|
{err.message}
|
|
186
180
|
</Text>
|
|
187
181
|
</YStack>
|
|
@@ -201,7 +195,7 @@ function LiveDashboardContent<TDoc extends { name: string; doctype: string }>({
|
|
|
201
195
|
{showRefresh && (
|
|
202
196
|
<XStack {...knobProps.gap} alignItems="center">
|
|
203
197
|
{isLiveStale && <Spinner size="small" aria-label={t("Updating")} />}
|
|
204
|
-
<Text color={
|
|
198
|
+
<Text color={knobProps.textAccentColor} {...knobProps.label}>
|
|
205
199
|
{t("Last updated: {{time}}", {
|
|
206
200
|
time: formatTimeOfDay(dataUpdatedAt ?? lastRefresh),
|
|
207
201
|
})}
|
|
@@ -321,7 +315,7 @@ export function FrappeDashboard<TDoc extends { name: string; doctype: string }>(
|
|
|
321
315
|
{title ? <H3 {...knobProps.heading}>{title}</H3> : <YStack flex={1} />}
|
|
322
316
|
<XStack {...knobProps.gap} alignItems="center">
|
|
323
317
|
{autoRefresh && (
|
|
324
|
-
<Text color={
|
|
318
|
+
<Text color={knobProps.textAccentColor} {...knobProps.label}>
|
|
325
319
|
{t("Last updated: {{time}}", { time: formatTimeOfDay(lastRefresh) })}
|
|
326
320
|
</Text>
|
|
327
321
|
)}
|
|
@@ -380,25 +374,4 @@ export function FrappeDashboard<TDoc extends { name: string; doctype: string }>(
|
|
|
380
374
|
);
|
|
381
375
|
}
|
|
382
376
|
|
|
383
|
-
|
|
384
|
-
* ChartCard bridge that sanitizes series rows before render: values are
|
|
385
|
-
* coerced to numbers and rows without a finite value (missing, NaN,
|
|
386
|
-
* non-numeric, Infinity) are dropped, so malformed series can't flood the
|
|
387
|
-
* SVG layer with invalid-length (`NaN`) attribute errors. Bar and pie
|
|
388
|
-
* renderers can't draw negative magnitudes (negative rect heights / arc
|
|
389
|
-
* angles are invalid SVG), so negatives clamp to the baseline there.
|
|
390
|
-
*/
|
|
391
|
-
export function ChartCard({ config, ...chartCardProps }: ChartCardProps) {
|
|
392
|
-
const clampNegatives = config.type === "bar" || config.type === "pie";
|
|
393
|
-
const data = useMemo(
|
|
394
|
-
() =>
|
|
395
|
-
(config.data ?? []).flatMap((point) => {
|
|
396
|
-
const value = Number((point as Partial<ChartDataPoint> | undefined)?.value);
|
|
397
|
-
if (!Number.isFinite(value)) return [];
|
|
398
|
-
return [{ ...point, value: clampNegatives && value < 0 ? 0 : value }];
|
|
399
|
-
}),
|
|
400
|
-
[config.data, clampNegatives],
|
|
401
|
-
);
|
|
402
|
-
const sanitizedConfig = useMemo(() => ({ ...config, data }), [config.data, data]);
|
|
403
|
-
return <BaseChartCard {...chartCardProps} config={sanitizedConfig} />;
|
|
404
|
-
}
|
|
377
|
+
export { ChartCard } from "./ChartCard";
|
|
@@ -77,8 +77,7 @@ function jsonResponse(body: unknown, status = 200): Response {
|
|
|
77
77
|
return jsonResponse({ docs: [taskMetaRaw(doctype)] });
|
|
78
78
|
}
|
|
79
79
|
const metaMatch = url.pathname.match(/^\/api\/resource\/DocType\/(.+)$/);
|
|
80
|
-
if (metaMatch)
|
|
81
|
-
return jsonResponse({ data: taskMetaRaw(decodeURIComponent(metaMatch[1])) });
|
|
80
|
+
if (metaMatch) return jsonResponse({ data: taskMetaRaw(decodeURIComponent(metaMatch[1])) });
|
|
82
81
|
if (url.pathname === "/api/resource/DocType") {
|
|
83
82
|
return jsonResponse({ data: [{ name: "Task", module: "Projects" }] });
|
|
84
83
|
}
|
package/src/FrappeImageView.tsx
CHANGED
|
@@ -5,25 +5,26 @@ import React, { useMemo } from "react";
|
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
6
|
import { Spinner, formCommonColors } from "@multiplatform.one/forms";
|
|
7
7
|
import { Image, Text, YStack, type YStackProps } from "tamagui";
|
|
8
|
+
import { isServer } from "@multiplatform.one/platform";
|
|
8
9
|
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
9
10
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
10
11
|
import { FrappeReconnectIndicator } from "./FrappeReconnectIndicator";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* True when this module is evaluated during web server rendering.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `
|
|
14
|
+
* True when this module is evaluated during web server rendering.
|
|
15
|
+
*
|
|
16
|
+
* This used to read `import.meta.env.SSR` behind a try/catch, which MPO-192
|
|
17
|
+
* ruled out: in a classic script — the vxrn/rolldown Hermes bundle, or any
|
|
18
|
+
* Metro bundle for platform=web, which is what an Expo DOM component
|
|
19
|
+
* (`'use dom'`) is — `import.meta` is a PARSE-time SyntaxError, so the catch
|
|
20
|
+
* never runs and the whole module fails to parse.
|
|
21
|
+
*
|
|
22
|
+
* `isServer` carries no `import.meta` and is split at the FILE level
|
|
23
|
+
* (@tamagui/constants ships a `.native` flavour hardcoding it false), so it
|
|
24
|
+
* answers correctly in all four places: true only under web server render,
|
|
25
|
+
* false in a browser, on native, and inside a DOM component's WebView.
|
|
19
26
|
*/
|
|
20
|
-
const IS_SSR: boolean =
|
|
21
|
-
try {
|
|
22
|
-
return (import.meta as ImportMeta & { env?: { SSR?: boolean } }).env?.SSR === true;
|
|
23
|
-
} catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
})();
|
|
27
|
+
const IS_SSR: boolean = isServer;
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Resolves an image field value to a full URL.
|
|
@@ -85,8 +86,8 @@ export function FrappeImageView<TDoc extends { name: string; doctype: string }>(
|
|
|
85
86
|
// when FrappeProvider already carries it.
|
|
86
87
|
const providerConfig = useFrappeConfig();
|
|
87
88
|
// Note: `typeof window` is unreliable because react-native-web polyfills
|
|
88
|
-
// `window` during SSR. Use the module-level
|
|
89
|
-
// (
|
|
89
|
+
// `window` during SSR. Use the module-level platform flag instead
|
|
90
|
+
// (see IS_SSR above).
|
|
90
91
|
if (IS_SSR) {
|
|
91
92
|
const {
|
|
92
93
|
doctype,
|
|
@@ -85,8 +85,7 @@ function jsonResponse(body: unknown, status = 200): Response {
|
|
|
85
85
|
return jsonResponse({ docs: [todoMetaRaw(doctype)] });
|
|
86
86
|
}
|
|
87
87
|
const metaMatch = url.pathname.match(/^\/api\/resource\/DocType\/(.+)$/);
|
|
88
|
-
if (metaMatch)
|
|
89
|
-
return jsonResponse({ data: todoMetaRaw(decodeURIComponent(metaMatch[1])) });
|
|
88
|
+
if (metaMatch) return jsonResponse({ data: todoMetaRaw(decodeURIComponent(metaMatch[1])) });
|
|
90
89
|
if (url.pathname === "/api/resource/DocType") {
|
|
91
90
|
return jsonResponse({ data: [{ name: "ToDo", module: "Desk" }] });
|
|
92
91
|
}
|
|
@@ -270,10 +269,7 @@ export const Loading = () => (
|
|
|
270
269
|
|
|
271
270
|
/** Zero documents, no failure — "No ToDo records found" (empty ≠ error). */
|
|
272
271
|
export const Empty = () => (
|
|
273
|
-
<FrappeProvider
|
|
274
|
-
baseURL={MOCK_HOST}
|
|
275
|
-
fixtures={new InMemoryFixtureProvider({ ToDo: [] })}
|
|
276
|
-
>
|
|
272
|
+
<FrappeProvider baseURL={MOCK_HOST} fixtures={new InMemoryFixtureProvider({ ToDo: [] })}>
|
|
277
273
|
<FrappeList<ToDo> doctype="ToDo" renderItem={renderTodo} height={400} />
|
|
278
274
|
</FrappeProvider>
|
|
279
275
|
);
|
|
@@ -286,10 +282,7 @@ export const Empty = () => (
|
|
|
286
282
|
* AsyncBoundary error panel.
|
|
287
283
|
*/
|
|
288
284
|
export const LoadError = () => (
|
|
289
|
-
<FrappeProvider
|
|
290
|
-
baseURL={MOCK_HOST}
|
|
291
|
-
fixtures={new InMemoryFixtureProvider({ ToDo: [] })}
|
|
292
|
-
>
|
|
285
|
+
<FrappeProvider baseURL={MOCK_HOST} fixtures={new InMemoryFixtureProvider({ ToDo: [] })}>
|
|
293
286
|
<FrappeList<ToDo>
|
|
294
287
|
doctype="ToDo"
|
|
295
288
|
renderItem={renderTodo}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { isServer } from "@multiplatform.one/platform";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MPO-204 / MPO-192. `import.meta` is a PARSE-time SyntaxError in a classic
|
|
8
|
+
* script, and two bundles execute mpo as one: the vxrn/rolldown native bundle
|
|
9
|
+
* for Hermes, and any Metro bundle for platform=web — which is what an Expo
|
|
10
|
+
* DOM component (`'use dom'`) is. A try/catch never runs, because the file
|
|
11
|
+
* never parses, so the token has to be ABSENT rather than guarded. Both files
|
|
12
|
+
* below are reachable from a DOM component through the frappe-ui surface.
|
|
13
|
+
*/
|
|
14
|
+
const src = (name: string) =>
|
|
15
|
+
readFileSync(resolve(process.cwd(), "src", name), "utf8").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
16
|
+
|
|
17
|
+
describe("frappeStoryTarget carries no import.meta (MPO-204)", () => {
|
|
18
|
+
const source = src("frappeStoryTarget.tsx");
|
|
19
|
+
|
|
20
|
+
it("contains no import.meta token", () => {
|
|
21
|
+
expect(source).not.toMatch(/import\.meta/);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("reads both Storybook keys as static process.env member expressions, the only spelling bundlers inline", () => {
|
|
25
|
+
expect(source).toMatch(/process\.env\.STORYBOOK_FRAPPE_LIVE\b/);
|
|
26
|
+
expect(source).toMatch(/process\.env\.STORYBOOK_FRAPPE_URL\b/);
|
|
27
|
+
// A computed read is never inlined, so it would always resolve undefined.
|
|
28
|
+
expect(source).not.toMatch(/process\.env\[/);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("FrappeImageView carries no import.meta (MPO-204)", () => {
|
|
33
|
+
const source = src("FrappeImageView.tsx");
|
|
34
|
+
|
|
35
|
+
it("contains no import.meta token", () => {
|
|
36
|
+
expect(source).not.toMatch(/import\.meta/);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("takes its SSR answer from the platform package, which is split by FILE and not by a bundler define", () => {
|
|
40
|
+
expect(source).toMatch(/import \{ isServer \} from "@multiplatform\.one\/platform";/);
|
|
41
|
+
expect(source).toMatch(/const IS_SSR: boolean = isServer;/);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("resolves isServer false in a browser-like environment, so the client branch renders", () => {
|
|
45
|
+
expect(isServer).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -91,6 +91,13 @@ function jsonResponse(body: unknown, status = 200): Response {
|
|
|
91
91
|
};
|
|
92
92
|
})();
|
|
93
93
|
|
|
94
|
+
// 1x1 PNG so the image thumbnail does not GET /files/diagram.png off the
|
|
95
|
+
// Storybook origin (that 404 was the recorded fuzz FAIL). file_type is the
|
|
96
|
+
// MIME the thumbnail recognises; file_name keeps the .png extension for the
|
|
97
|
+
// type well. Same byte string as FrappeFileUpload.stories.
|
|
98
|
+
const TINY_PNG =
|
|
99
|
+
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
|
|
100
|
+
|
|
94
101
|
const fileFixtures: FrappeFile[] = [
|
|
95
102
|
{
|
|
96
103
|
name: "FILE-001",
|
|
@@ -107,9 +114,9 @@ const fileFixtures: FrappeFile[] = [
|
|
|
107
114
|
name: "FILE-002",
|
|
108
115
|
doctype: "File",
|
|
109
116
|
file_name: "diagram.png",
|
|
110
|
-
file_url:
|
|
117
|
+
file_url: TINY_PNG,
|
|
111
118
|
file_size: 51200,
|
|
112
|
-
file_type: "
|
|
119
|
+
file_type: "image/png",
|
|
113
120
|
attached_to_doctype: "Task",
|
|
114
121
|
attached_to_name: "TASK-001",
|
|
115
122
|
attached_to_field: "design_attachment",
|
package/src/dependsOn.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Safe evaluator for Frappe `depends_on` / `mandatory_depends_on` /
|
|
3
3
|
* `read_only_depends_on` expressions — the ONE parser for every surface
|
|
4
|
-
* (SchemaForm here, the
|
|
5
|
-
*
|
|
4
|
+
* (SchemaForm here, and the desk form engine next door in ./formEngine;
|
|
5
|
+
* `@multiplatform.one/backoffice` re-exports it from its old path).
|
|
6
6
|
*
|
|
7
7
|
* Frappe's desk evaluates these with JS `eval`; Hermes (React Native), GJS,
|
|
8
8
|
* and CSP-restricted webviews cannot construct functions from strings, so
|
|
@@ -20,6 +20,24 @@ export default {
|
|
|
20
20
|
|
|
21
21
|
const MOCK_HOST = "https://deskformsidebar.mock.test";
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* The document image is an inline data: URI, not "/files/todo.png".
|
|
25
|
+
* `resolveFileUrl` prefixes a "/..." value with baseURL, so a path fixture
|
|
26
|
+
* makes the <img> fetch https://deskformsidebar.mock.test/files/todo.png for
|
|
27
|
+
* real — the story's window.fetch shim only intercepts fetch(), never an
|
|
28
|
+
* image load — and the story prints ERR_TUNNEL_CONNECTION_FAILED. A data: URI
|
|
29
|
+
* goes through resolveFileUrl untouched and paints without a request, which
|
|
30
|
+
* is what G-15 story honesty asks for (MPO-197).
|
|
31
|
+
*/
|
|
32
|
+
const storyImage =
|
|
33
|
+
"data:image/svg+xml;utf8," +
|
|
34
|
+
encodeURIComponent(
|
|
35
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240" viewBox="0 0 24 24">' +
|
|
36
|
+
'<rect width="24" height="24" rx="3" fill="#4c6ef5"/>' +
|
|
37
|
+
'<path d="M6 12.5l3.5 3.5L18 8" fill="none" stroke="#fff" stroke-width="2" ' +
|
|
38
|
+
'stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
|
39
|
+
);
|
|
40
|
+
|
|
23
41
|
function jsonResponse(body: unknown, status = 200): Response {
|
|
24
42
|
return new Response(JSON.stringify(body), {
|
|
25
43
|
status,
|
|
@@ -70,7 +88,7 @@ const todoDocs = [
|
|
|
70
88
|
owner: "jane@example.com",
|
|
71
89
|
modified_by: "john@example.com",
|
|
72
90
|
creation: "2026-02-01",
|
|
73
|
-
image:
|
|
91
|
+
image: storyImage,
|
|
74
92
|
_assign: JSON.stringify(["jane@example.com"]),
|
|
75
93
|
},
|
|
76
94
|
];
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* table-cell chromeless branch, and registry resolution for the
|
|
5
5
|
* "Code" and "JSON" fieldtypes.
|
|
6
6
|
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
7
10
|
import { TableCellContext } from "@multiplatform.one/forms";
|
|
8
11
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
9
12
|
import { act, cleanup, fireEvent } from "@testing-library/react";
|
|
@@ -12,6 +15,24 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
12
15
|
import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
|
|
13
16
|
import { CodeEditorField, frappeCodeLanguage } from ".";
|
|
14
17
|
|
|
18
|
+
function codeEditorDir() {
|
|
19
|
+
try {
|
|
20
|
+
const meta = import.meta.url;
|
|
21
|
+
if (meta.startsWith("file:")) return dirname(fileURLToPath(meta));
|
|
22
|
+
} catch {
|
|
23
|
+
/* vite-node may serve a non-file import.meta.url */
|
|
24
|
+
}
|
|
25
|
+
return join(process.cwd(), "src/fields/CodeEditor");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function readCodeEditorSource() {
|
|
29
|
+
return readFileSync(join(codeEditorDir(), "index.tsx"), "utf8");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readCodeEditorStories() {
|
|
33
|
+
return readFileSync(join(codeEditorDir(), "CodeEditor.stories.tsx"), "utf8");
|
|
34
|
+
}
|
|
35
|
+
|
|
15
36
|
afterEach(cleanup);
|
|
16
37
|
|
|
17
38
|
describe("frappeCodeLanguage (stock ControlCode language_map)", () => {
|
|
@@ -80,6 +101,22 @@ describe("CodeEditorField (standalone)", () => {
|
|
|
80
101
|
);
|
|
81
102
|
expect(result.getTextArea()).toBeNull();
|
|
82
103
|
});
|
|
104
|
+
|
|
105
|
+
it("ships CSF3 story objects so native gallery keeps args (KS blank-pane)", () => {
|
|
106
|
+
const stories = readCodeEditorStories();
|
|
107
|
+
expect(stories).toMatch(/export const Main = \{/);
|
|
108
|
+
expect(stories).not.toMatch(/Main\.args\s*=/);
|
|
109
|
+
expect(stories).toContain("value: PYTHON_FIXTURE");
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("forwards knob containerRadius onto the source textarea (F14)", () => {
|
|
113
|
+
const source = readCodeEditorSource();
|
|
114
|
+
expect(source).toContain("...knobProps.containerRadius");
|
|
115
|
+
const result = renderWithProviders(
|
|
116
|
+
<CodeEditorField label="Script" value="print(1)" language="python" onChange={() => {}} />,
|
|
117
|
+
);
|
|
118
|
+
expect(result.getTextArea()).toBeTruthy();
|
|
119
|
+
});
|
|
83
120
|
});
|
|
84
121
|
|
|
85
122
|
describe("registry resolution (Code / JSON fieldtypes)", () => {
|
|
@@ -30,11 +30,11 @@ export default {
|
|
|
30
30
|
title: "FrappeUI/CodeEditorField",
|
|
31
31
|
component: CodeEditorField,
|
|
32
32
|
parameters: {
|
|
33
|
-
status: { type: "
|
|
33
|
+
status: { type: "stable" },
|
|
34
34
|
docs: {
|
|
35
35
|
description: {
|
|
36
36
|
component:
|
|
37
|
-
"Frappe `Code` / `JSON` fieldtypes: monospace source pane + shiki-highlighted preview (unified components Highlighter). Language follows the stock df.options convention via `frappeCodeLanguage()`.",
|
|
37
|
+
"Frappe `Code` / `JSON` fieldtypes: monospace source pane + shiki-highlighted preview (unified components Highlighter). Language follows the stock df.options convention via `frappeCodeLanguage()`. Source textarea honours knob `containerRadius` (F14).",
|
|
38
38
|
},
|
|
39
39
|
},
|
|
40
40
|
},
|
|
@@ -74,76 +74,93 @@ function Controlled(props: Omit<StoryProps, "onChange">) {
|
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
export const Main = (args
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
} as Partial<StoryProps>;
|
|
77
|
+
// CSF3 objects (not `export const Main = (args) => …; Main.args = …`).
|
|
78
|
+
// Native Kitchen Sink `storyIndex.ts` treats a function export as
|
|
79
|
+
// `{ render: fn }` and drops `fn.args`, so CSF2 Main/Json/ReadOnly
|
|
80
|
+
// painted an empty Code pane on OTA (value/readOnly never arrived).
|
|
81
|
+
export const Main = {
|
|
82
|
+
name: "Main",
|
|
83
|
+
args: {
|
|
84
|
+
label: "Server script",
|
|
85
|
+
helperText: 'Language from df.options ("Python")',
|
|
86
|
+
value: PYTHON_FIXTURE,
|
|
87
|
+
language: frappeCodeLanguage("Python"),
|
|
88
|
+
} as Partial<StoryProps>,
|
|
89
|
+
render: (args: StoryProps) => <Controlled {...args} />,
|
|
90
|
+
};
|
|
92
91
|
|
|
93
|
-
export const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<YStack gap="$4">
|
|
101
|
-
<CodeEditorField
|
|
102
|
-
form={form as unknown as AnyFormApi}
|
|
103
|
-
name="script"
|
|
104
|
-
label="Script (form-integrated)"
|
|
105
|
-
language="python"
|
|
106
|
-
required
|
|
107
|
-
helperText="Bound to TanStack Form field state"
|
|
108
|
-
/>
|
|
109
|
-
</YStack>
|
|
110
|
-
</Form>
|
|
111
|
-
);
|
|
92
|
+
export const Json = {
|
|
93
|
+
args: {
|
|
94
|
+
label: "Filters (JSON fieldtype)",
|
|
95
|
+
value: JSON_FIXTURE,
|
|
96
|
+
language: "json",
|
|
97
|
+
} as Partial<StoryProps>,
|
|
98
|
+
render: (args: StoryProps) => <Controlled {...args} />,
|
|
112
99
|
};
|
|
113
100
|
|
|
114
|
-
export const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
101
|
+
export const FormIntegrated = {
|
|
102
|
+
name: "Form Integrated",
|
|
103
|
+
render: function FormIntegratedRender() {
|
|
104
|
+
const form = useForm({
|
|
105
|
+
defaultValues: { script: PYTHON_FIXTURE },
|
|
106
|
+
onSubmit: async ({ value }) => action("onSubmit")(value),
|
|
107
|
+
});
|
|
108
|
+
return (
|
|
109
|
+
<Form form={form}>
|
|
110
|
+
<YStack gap="$4">
|
|
111
|
+
<CodeEditorField
|
|
112
|
+
form={form as unknown as AnyFormApi}
|
|
113
|
+
name="script"
|
|
114
|
+
label="Script (form-integrated)"
|
|
115
|
+
language="python"
|
|
116
|
+
required
|
|
117
|
+
helperText="Bound to TanStack Form field state"
|
|
118
|
+
/>
|
|
119
|
+
</YStack>
|
|
120
|
+
</Form>
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
};
|
|
121
124
|
|
|
122
|
-
export const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
value: 'const answer = 42;\nconsole.log("state fixtures");',
|
|
132
|
-
language: "javascript",
|
|
133
|
-
} as Partial<StoryProps>;
|
|
125
|
+
export const ReadOnly = {
|
|
126
|
+
args: {
|
|
127
|
+
label: "Read-only script",
|
|
128
|
+
value: PYTHON_FIXTURE,
|
|
129
|
+
language: "python",
|
|
130
|
+
readOnly: true,
|
|
131
|
+
} as Partial<StoryProps>,
|
|
132
|
+
render: (args: StoryProps) => <Controlled {...args} />,
|
|
133
|
+
};
|
|
134
134
|
|
|
135
|
-
export const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
export const States = {
|
|
136
|
+
args: {
|
|
137
|
+
value: 'const answer = 42;\nconsole.log("state fixtures");',
|
|
138
|
+
language: "javascript",
|
|
139
|
+
} as Partial<StoryProps>,
|
|
140
|
+
render: (args: StoryProps) => (
|
|
141
|
+
<YStack gap="$5">
|
|
142
|
+
<Controlled {...args} label="Error" error="Script fails to parse at line 3" />
|
|
143
|
+
<Controlled {...args} label="Disabled" disabled />
|
|
144
|
+
<Controlled {...args} label="Compact" compact />
|
|
145
|
+
<CodeEditorField label="Skeleton" skeleton onChange={() => {}} />
|
|
139
146
|
</YStack>
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
),
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const DarkScheme = {
|
|
151
|
+
args: {
|
|
152
|
+
label: "Server script (dark)",
|
|
153
|
+
value: PYTHON_FIXTURE,
|
|
154
|
+
language: "python",
|
|
155
|
+
} as Partial<StoryProps>,
|
|
156
|
+
render: (args: StoryProps) => (
|
|
157
|
+
<Theme name="dark">
|
|
158
|
+
<YStack backgroundColor="$background" padding="$4">
|
|
159
|
+
<Controlled {...args} />
|
|
160
|
+
</YStack>
|
|
161
|
+
</Theme>
|
|
162
|
+
),
|
|
163
|
+
};
|
|
147
164
|
|
|
148
165
|
type CodeRow = { id: string; label: string; value: string };
|
|
149
166
|
|
|
@@ -213,6 +213,10 @@ export function CodeEditorField({
|
|
|
213
213
|
maxRows={maxRows}
|
|
214
214
|
textAreaProps={{
|
|
215
215
|
fontFamily: "$mono",
|
|
216
|
+
// F14: TextArea's inner <textarea> takes radius from `size` unless
|
|
217
|
+
// containerRadius lands after the size recipe. FieldLayout already
|
|
218
|
+
// gets knobProps; the measured source surface must too.
|
|
219
|
+
...knobProps.containerRadius,
|
|
216
220
|
autoCapitalize: "none",
|
|
217
221
|
autoCorrect: false,
|
|
218
222
|
spellCheck: false,
|