@parallelworks/ui 0.34.0 → 0.35.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.
- package/README.md +201 -0
- package/dist/ai/components/ChatEmptyState.js +71 -86
- package/dist/ai/components/ChatInput.d.ts +11 -3
- package/dist/ai/components/ChatInput.js +19 -11
- package/dist/ai/components/ChatSidebar.js +12 -130
- package/dist/ai/components/ChatStage.d.ts +11 -0
- package/dist/ai/components/ChatStage.js +26 -0
- package/dist/ai/components/ComposerChrome.d.ts +3 -0
- package/dist/ai/components/ComposerChrome.js +21 -2
- package/dist/ai/components/conversationActions.d.ts +23 -0
- package/dist/ai/components/conversationActions.js +108 -0
- package/dist/ai/index.d.ts +4 -3
- package/dist/ai/index.js +6 -5
- package/dist/ai/strings.d.ts +1 -0
- package/dist/ai/strings.js +2 -1
- package/dist/ai/ui/ConversationSidebar.d.ts +3 -2
- package/dist/ai/ui/ConversationSidebar.js +2 -1
- package/dist/ai/ui/sidebar.d.ts +6 -0
- package/dist/ai/ui/sidebar.js +10 -1
- package/dist/components/Dropdown.js +3 -1
- package/dist/components/FilterPill.js +1 -0
- package/dist/components/Provider.d.ts +14 -0
- package/dist/components/Provider.js +14 -3
- package/dist/components/SegmentedControl.d.ts +24 -0
- package/dist/components/SegmentedControl.js +69 -0
- package/dist/editing.d.ts +32 -0
- package/dist/editor/FormCodePanel.js +1 -1
- package/dist/engine.d.ts +3 -0
- package/dist/form/FieldWrapper.js +1 -1
- package/dist/form/Fields/CheckboxGroupField.d.ts +3 -3
- package/dist/form/Fields/CheckboxGroupField.js +10 -4
- package/dist/form/Fields/RadioField.d.ts +5 -3
- package/dist/form/Fields/RadioField.js +25 -17
- package/dist/form/Fields/fieldOption.d.ts +12 -0
- package/dist/form/Fields/fieldOption.js +17 -0
- package/dist/form/Form.d.ts +4 -2
- package/dist/form/Form.js +170 -68
- package/dist/form/FormLayout.d.ts +7 -0
- package/dist/form/FormLayout.js +144 -0
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +1 -1
- package/dist/form/SpecialTypes/FormikCustomInput.js +7 -0
- package/dist/form/Wizard/WizardContainer.d.ts +1 -1
- package/dist/form/Wizard/WizardContainer.js +244 -49
- package/dist/form/Wizard/WizardNavigation.js +4 -4
- package/dist/form/Wizard/WizardStepContent.d.ts +1 -1
- package/dist/form/Wizard/WizardStepContent.js +19 -10
- package/dist/form/Wizard/WizardStepIndicator.js +35 -7
- package/dist/form/Wizard/types.d.ts +19 -6
- package/dist/form/Wizard/useWizardState.d.ts +1 -0
- package/dist/form/Wizard/useWizardState.js +5 -1
- package/dist/form/Wizard/utils.d.ts +7 -0
- package/dist/form/Wizard/utils.js +18 -1
- package/dist/form/index.d.ts +2 -0
- package/dist/form/index.js +4 -2
- package/dist/form/layout.d.ts +50 -0
- package/dist/form/layout.js +125 -0
- package/dist/form/layoutCSS.d.ts +10 -0
- package/dist/form/layoutCSS.js +234 -0
- package/dist/form/lib.d.ts +2 -0
- package/dist/form/lib.js +17 -2
- package/dist/form/types/fieldTypes.d.ts +8 -23
- package/dist/graph/DependencyGraph.d.ts +20 -1
- package/dist/graph/DependencyGraph.js +437 -142
- package/dist/graph/MatrixGroup.d.ts +3 -1
- package/dist/graph/MatrixGroup.js +31 -28
- package/dist/graph/TreeView.js +6 -6
- package/dist/graph/gridSpacing.d.ts +7 -0
- package/dist/graph/gridSpacing.js +10 -0
- package/dist/graph/util.d.ts +2 -0
- package/dist/graph/util.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/list/ListViewControls.d.ts +15 -0
- package/dist/list/ListViewControls.js +9 -3
- package/dist/list/index.d.ts +1 -1
- package/dist/list/index.js +2 -2
- package/dist/styles/base.css +3 -1
- package/dist/styles/theme.css +5 -0
- package/dist/styles.css +1 -1
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.js +3 -2
- package/package.json +4 -2
- package/dist/ai/components/ComposerFrame.d.ts +0 -16
- package/dist/ai/components/ComposerFrame.js +0 -33
|
@@ -102,8 +102,15 @@ var DEFAULTS = {
|
|
|
102
102
|
status: "Status",
|
|
103
103
|
runtime: "Runtime",
|
|
104
104
|
submitted: "Submitted",
|
|
105
|
-
expandAll: "Expand
|
|
106
|
-
collapseAll: "Collapse
|
|
105
|
+
expandAll: "Expand All",
|
|
106
|
+
collapseAll: "Collapse All",
|
|
107
|
+
zoomIn: "Zoom in",
|
|
108
|
+
zoomOut: "Zoom out",
|
|
109
|
+
resetView: "Reset View",
|
|
110
|
+
previousGraph: "Back to the previous graph",
|
|
111
|
+
nextGraph: "Forward to the next graph",
|
|
112
|
+
matrixOf: (name) => `Matrix: ${name}`,
|
|
113
|
+
jobCount: (count) => count === 1 ? "1 job" : `${count} jobs`,
|
|
107
114
|
loadingLogs: "Loading logs",
|
|
108
115
|
noLogFound: "No log found",
|
|
109
116
|
logLoadFailed: "Log could not be loaded",
|
|
@@ -322,7 +329,11 @@ var DEFAULTS = {
|
|
|
322
329
|
form: {
|
|
323
330
|
invalidDuration: "Enter a duration as DD-HH:MM:SS or HH:MM:SS.",
|
|
324
331
|
durationOutOfRange: (min, max) => `Must be between ${min} and ${max}.`,
|
|
325
|
-
durationBelowMin: (min) => `Must be at least ${min}
|
|
332
|
+
durationBelowMin: (min) => `Must be at least ${min}.`,
|
|
333
|
+
copyTitle: (title, number) => `${title} ${number}`,
|
|
334
|
+
addCopy: (title) => `+ Add ${title}`,
|
|
335
|
+
removeCopy: (title) => `Remove ${title}`,
|
|
336
|
+
steps: "Steps"
|
|
326
337
|
},
|
|
327
338
|
time: {
|
|
328
339
|
now: "now",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface SegmentedOption<T extends string> {
|
|
3
|
+
value: T;
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
/** Beside the label, or in the corner when only the icon shows. */
|
|
7
|
+
badge?: ReactNode;
|
|
8
|
+
/** Navigates instead of calling `onChange`, for segments that are pages. */
|
|
9
|
+
to?: string;
|
|
10
|
+
testId?: string;
|
|
11
|
+
}
|
|
12
|
+
/** A few mutually exclusive choices side by side, one always current. With
|
|
13
|
+
* `iconOnly` the segments stack as icons with their labels in tooltips, for
|
|
14
|
+
* a collapsed rail. */
|
|
15
|
+
export declare function SegmentedControl<T extends string>({ label, options, value, onChange, fill, iconOnly, testId, }: {
|
|
16
|
+
label: string;
|
|
17
|
+
options: SegmentedOption<T>[];
|
|
18
|
+
value: T;
|
|
19
|
+
onChange?: (value: T) => void;
|
|
20
|
+
/** Segments share the container's width equally. */
|
|
21
|
+
fill?: boolean;
|
|
22
|
+
iconOnly?: boolean;
|
|
23
|
+
testId?: string;
|
|
24
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useLink } from "./Provider.js";
|
|
2
|
+
import { TOOLTIP_ID } from "./Tooltip.js";
|
|
3
|
+
import cx from "classnames";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/SegmentedControl.tsx
|
|
6
|
+
var itemBase = "relative flex min-w-0 items-center justify-center rounded-md font-medium transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-(--theme-link)";
|
|
7
|
+
var itemCurrent = "bg-(--theme-panel-bg) theme-text shadow-sm ring-1 ring-(--theme-border)";
|
|
8
|
+
var itemIdle = "theme-muted-text hover:theme-text hover:bg-(--theme-hover)";
|
|
9
|
+
/** A few mutually exclusive choices side by side, one always current. With
|
|
10
|
+
* `iconOnly` the segments stack as icons with their labels in tooltips, for
|
|
11
|
+
* a collapsed rail. */
|
|
12
|
+
function SegmentedControl({ label, options, value, onChange, fill = false, iconOnly = false, testId }) {
|
|
13
|
+
const Link = useLink();
|
|
14
|
+
const links = options.some((o) => o.to);
|
|
15
|
+
const items = options.map((option) => {
|
|
16
|
+
const current = option.value === value;
|
|
17
|
+
const className = cx(itemBase, current ? itemCurrent : itemIdle, iconOnly ? "h-8 w-8" : cx("h-7 gap-1.5 text-[13px]", fill ? "px-1.5" : "px-2.5"));
|
|
18
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
19
|
+
option.icon,
|
|
20
|
+
iconOnly ? /* @__PURE__ */ jsx("span", {
|
|
21
|
+
className: "sr-only",
|
|
22
|
+
children: option.label
|
|
23
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
24
|
+
className: "truncate",
|
|
25
|
+
children: option.label
|
|
26
|
+
}),
|
|
27
|
+
option.badge && (iconOnly ? /* @__PURE__ */ jsx("span", {
|
|
28
|
+
className: "absolute top-1 right-1 inline-flex",
|
|
29
|
+
children: option.badge
|
|
30
|
+
}) : option.badge)
|
|
31
|
+
] });
|
|
32
|
+
const tooltip = iconOnly ? {
|
|
33
|
+
"data-tooltip-id": TOOLTIP_ID,
|
|
34
|
+
"data-tooltip-content": option.label,
|
|
35
|
+
"data-tooltip-place": "right"
|
|
36
|
+
} : {};
|
|
37
|
+
return option.to ? /* @__PURE__ */ jsx(Link, {
|
|
38
|
+
to: option.to,
|
|
39
|
+
"aria-current": current ? "page" : void 0,
|
|
40
|
+
"data-testid": option.testId,
|
|
41
|
+
className,
|
|
42
|
+
...tooltip,
|
|
43
|
+
children: content
|
|
44
|
+
}, option.value) : /* @__PURE__ */ jsx("button", {
|
|
45
|
+
type: "button",
|
|
46
|
+
"aria-pressed": current,
|
|
47
|
+
"data-testid": option.testId,
|
|
48
|
+
onClick: () => onChange?.(option.value),
|
|
49
|
+
className,
|
|
50
|
+
...tooltip,
|
|
51
|
+
children: content
|
|
52
|
+
}, option.value);
|
|
53
|
+
});
|
|
54
|
+
const groupClassName = cx("gap-0.5", iconOnly ? "flex flex-col items-center" : cx("rounded-lg theme-muted-panel p-0.5", fill ? "grid auto-cols-fr grid-flow-col" : "inline-flex"));
|
|
55
|
+
return links ? /* @__PURE__ */ jsx("nav", {
|
|
56
|
+
"aria-label": label,
|
|
57
|
+
"data-testid": testId,
|
|
58
|
+
className: groupClassName,
|
|
59
|
+
children: items
|
|
60
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
61
|
+
role: "group",
|
|
62
|
+
"aria-label": label,
|
|
63
|
+
"data-testid": testId,
|
|
64
|
+
className: groupClassName,
|
|
65
|
+
children: items
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { SegmentedControl };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** A job's slot on the dependency graph's column/row grid. */
|
|
2
|
+
export interface GraphPosition {
|
|
3
|
+
column: number;
|
|
4
|
+
row: number;
|
|
5
|
+
}
|
|
6
|
+
/** Job name to grid slot, as stored on a workflow. */
|
|
7
|
+
export type GraphLayout = Record<string, GraphPosition>;
|
|
8
|
+
/** One column's boxes, top to bottom, the row each box sits in, and the column's number. */
|
|
9
|
+
export interface LaidOutColumn {
|
|
10
|
+
boxes: string[][];
|
|
11
|
+
rows: number[];
|
|
12
|
+
column: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The workflow editing the visual editor defers to: reading and rewriting the workflow's YAML,
|
|
16
|
+
* its graph layout and its checks. A host built on a workflow package can pass that package's
|
|
17
|
+
* functions of the same names.
|
|
18
|
+
*/
|
|
19
|
+
export interface WorkflowEditing {
|
|
20
|
+
/** The job a `needs` entry points at, without a matrix's wait-for-any suffix. */
|
|
21
|
+
needTarget: (need: string) => string;
|
|
22
|
+
/** Jobs whose matrix runs more than once as `<job>-<n>` members, the way a run lists them. */
|
|
23
|
+
expandMatrixJobs: <T>(jobs: Record<string, T>) => Record<string, T>;
|
|
24
|
+
hasLayout: (layout: GraphLayout | undefined) => boolean;
|
|
25
|
+
layoutPosition: (layout: GraphLayout | undefined, job: string) => GraphPosition | undefined;
|
|
26
|
+
mapLayout: (layout: GraphLayout, fn: (position: GraphPosition, job: string) => GraphPosition | undefined) => GraphLayout;
|
|
27
|
+
/** Boxes and rows from a stored layout; jobs without a slot go below, grouped when `together` says. */
|
|
28
|
+
boxesFromLayout: (jobNames: string[], deps: Record<string, string[]>, layout: GraphLayout, rules: {
|
|
29
|
+
together: (a: string, b: string) => boolean;
|
|
30
|
+
alone: (job: string) => boolean;
|
|
31
|
+
}) => LaidOutColumn[];
|
|
32
|
+
}
|
|
@@ -4,8 +4,8 @@ import { FiCopy } from "../icons/fi/FiCopy.js";
|
|
|
4
4
|
import { LuEye } from "../icons/lu/LuEye.js";
|
|
5
5
|
import { LuEyeOff } from "../icons/lu/LuEyeOff.js";
|
|
6
6
|
import SwitchToggleSmall from "../components/SwitchToggleSmall.js";
|
|
7
|
-
import Editor from "./Editor.js";
|
|
8
7
|
import { flattenGroups, impureSetValueFromPath } from "../form/lib.js";
|
|
8
|
+
import Editor from "./Editor.js";
|
|
9
9
|
import cx from "classnames";
|
|
10
10
|
import { useId, useRef, useState } from "react";
|
|
11
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { WorkflowEditing } from './editing.js';
|
|
1
2
|
export type RunStatus = 'started' | 'running' | 'completed' | 'error' | 'failed' | 'canceled' | 'skipped' | 'faulted' | 'canceling' | 'skipped-failed' | '' | undefined;
|
|
2
3
|
export interface MatrixGroup {
|
|
3
4
|
originaljob: string;
|
|
@@ -95,4 +96,6 @@ export interface WorkflowEngine {
|
|
|
95
96
|
segments: LogSegment[];
|
|
96
97
|
}[], rawLines: string[]): ProcessedLogLine[];
|
|
97
98
|
toYaml(value: unknown): string;
|
|
99
|
+
/** What the visual editor and stored graph layouts need; without it, graphs lay themselves out. */
|
|
100
|
+
editing?: WorkflowEditing | undefined;
|
|
98
101
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RequiredMark } from "../components/RequiredMark.js";
|
|
2
|
-
import { FieldProvider } from "./fieldContext.js";
|
|
3
2
|
import { resolvedFlag } from "./lib.js";
|
|
3
|
+
import { FieldProvider } from "./fieldContext.js";
|
|
4
4
|
import cx from "classnames";
|
|
5
5
|
import { useId, useMemo } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -2,9 +2,9 @@ import type { FieldComponentProps } from '../types/fieldComponentTypes.js';
|
|
|
2
2
|
import type { BaseField } from '../types/fieldTypes.js';
|
|
3
3
|
export interface ICheckboxGroupField extends BaseField {
|
|
4
4
|
type: 'checkbox-group';
|
|
5
|
-
options?: Array<{
|
|
6
|
-
label
|
|
7
|
-
value: string;
|
|
5
|
+
options?: Array<string | number | {
|
|
6
|
+
label?: string;
|
|
7
|
+
value: string | number;
|
|
8
8
|
description?: string;
|
|
9
9
|
}>;
|
|
10
10
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FieldWrapper } from "../FieldWrapper.js";
|
|
2
|
+
import { fieldOption } from "./fieldOption.js";
|
|
2
3
|
import cx from "classnames";
|
|
3
4
|
import { useState } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -17,8 +18,12 @@ function CheckboxGroupField({ field, label, labelPosition, missing, disabled, on
|
|
|
17
18
|
const [fieldState] = useField(fieldName);
|
|
18
19
|
const { setFieldValue, setFieldTouched } = useFormikContext();
|
|
19
20
|
const implies = field.implies;
|
|
21
|
+
const rawOf = new Map((field.options ?? []).map((choice) => {
|
|
22
|
+
const option = fieldOption(choice);
|
|
23
|
+
return [option.value, option.raw];
|
|
24
|
+
}));
|
|
20
25
|
const [manual, setManual] = useState(() => {
|
|
21
|
-
const saved = fieldState.value || [];
|
|
26
|
+
const saved = (fieldState.value || []).map(String);
|
|
22
27
|
const impliedBySaved = impliedFrom(saved, implies);
|
|
23
28
|
return saved.filter((v) => !impliedBySaved.has(v));
|
|
24
29
|
});
|
|
@@ -26,7 +31,7 @@ function CheckboxGroupField({ field, label, labelPosition, missing, disabled, on
|
|
|
26
31
|
const handleToggle = (value) => {
|
|
27
32
|
if (disabled) return;
|
|
28
33
|
const nextManual = manual.includes(value) ? manual.filter((v) => v !== value) : [...manual, value];
|
|
29
|
-
const next = union(nextManual, impliedFrom(nextManual, implies));
|
|
34
|
+
const next = union(nextManual, impliedFrom(nextManual, implies)).map((v) => rawOf.get(v) ?? v);
|
|
30
35
|
setManual(nextManual);
|
|
31
36
|
setFieldTouched(fieldName, true);
|
|
32
37
|
setFieldValue(fieldName, next);
|
|
@@ -43,7 +48,8 @@ function CheckboxGroupField({ field, label, labelPosition, missing, disabled, on
|
|
|
43
48
|
"aria-labelledby": labelId,
|
|
44
49
|
"aria-describedby": describedBy,
|
|
45
50
|
className: "flex min-w-0 max-w-lg flex-col gap-1",
|
|
46
|
-
children: field.options?.map((
|
|
51
|
+
children: field.options?.map((raw) => {
|
|
52
|
+
const option = fieldOption(raw);
|
|
47
53
|
const locked = forced.has(option.value);
|
|
48
54
|
const optionDisabled = disabled || locked;
|
|
49
55
|
return /* @__PURE__ */ jsxs("label", {
|
|
@@ -53,7 +59,7 @@ function CheckboxGroupField({ field, label, labelPosition, missing, disabled, on
|
|
|
53
59
|
checked: manual.includes(option.value) || locked,
|
|
54
60
|
disabled: optionDisabled,
|
|
55
61
|
onChange: () => handleToggle(option.value),
|
|
56
|
-
className: cx("
|
|
62
|
+
className: cx("h-4 min-h-0 w-4 rounded accent-(--theme-link)", optionDisabled ? "cursor-not-allowed" : "cursor-pointer", missing && "invalid")
|
|
57
63
|
}), /* @__PURE__ */ jsxs("div", {
|
|
58
64
|
className: "flex min-w-0 flex-col",
|
|
59
65
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type React from 'react';
|
|
2
1
|
import type { FieldComponentProps } from '../types/fieldComponentTypes.js';
|
|
3
2
|
import type { BaseField } from '../types/fieldTypes.js';
|
|
4
3
|
export interface IRadioField extends BaseField {
|
|
5
4
|
type: 'radio';
|
|
6
|
-
options?: string
|
|
5
|
+
options?: Array<string | number | {
|
|
6
|
+
label?: string;
|
|
7
|
+
value: string | number;
|
|
8
|
+
}>;
|
|
7
9
|
optionLabelPosition?: 'left' | 'top';
|
|
8
10
|
}
|
|
9
|
-
export default function RadioField(props: FieldComponentProps<IRadioField>):
|
|
11
|
+
export default function RadioField(props: FieldComponentProps<IRadioField>): import("react").JSX.Element;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { FieldWrapper } from "../FieldWrapper.js";
|
|
2
|
+
import { fieldOption } from "./fieldOption.js";
|
|
2
3
|
import cx from "classnames";
|
|
3
4
|
import { useId } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
6
|
+
import { useField, useFormikContext } from "formik";
|
|
6
7
|
//#region src/form/Fields/RadioField.tsx
|
|
7
8
|
function RadioField(props) {
|
|
8
9
|
const { field, label, labelPosition, missing, disabled, onChange, tooltipComponent, spaceCompact, setFormDirty } = props;
|
|
9
10
|
const fieldName = field.name ?? "";
|
|
10
11
|
const uid = useId();
|
|
12
|
+
const [fieldState] = useField(fieldName);
|
|
11
13
|
const { setFieldValue, setFieldTouched } = useFormikContext();
|
|
12
14
|
const handleChange = (val) => {
|
|
13
15
|
if (disabled) return;
|
|
@@ -27,22 +29,28 @@ function RadioField(props) {
|
|
|
27
29
|
"aria-labelledby": labelId,
|
|
28
30
|
"aria-describedby": describedBy,
|
|
29
31
|
"aria-required": field.optional ? void 0 : true,
|
|
30
|
-
className: cx("flex", field.optionLabelPosition === "top" ? "flex-col" : "flex-row"),
|
|
31
|
-
children: field.options?.map((
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
className: cx("
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
className: cx("flex py-1.5", field.optionLabelPosition === "top" ? "flex-col gap-2" : "flex-row flex-wrap gap-x-5 gap-y-2"),
|
|
33
|
+
children: field.options?.map((raw) => {
|
|
34
|
+
const option = fieldOption(raw);
|
|
35
|
+
const unlabelled = typeof raw !== "object" || raw.label === void 0;
|
|
36
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
37
|
+
htmlFor: `${uid}-${option.value}`,
|
|
38
|
+
className: cx("flex items-center gap-2", disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer"),
|
|
39
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
40
|
+
id: `${uid}-${option.value}`,
|
|
41
|
+
className: cx("h-4 w-4", disabled ? "cursor-not-allowed" : "cursor-pointer", missing && "invalid"),
|
|
42
|
+
name: field.name,
|
|
43
|
+
type: "radio",
|
|
44
|
+
value: option.value,
|
|
45
|
+
checked: fieldState.value !== void 0 && fieldState.value !== null && String(fieldState.value) === option.value,
|
|
46
|
+
disabled,
|
|
47
|
+
onChange: () => handleChange(option.raw)
|
|
48
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
49
|
+
className: cx("theme-text", unlabelled && "capitalize"),
|
|
50
|
+
children: option.label
|
|
51
|
+
})]
|
|
52
|
+
}, field.name + option.value);
|
|
53
|
+
})
|
|
46
54
|
})
|
|
47
55
|
});
|
|
48
56
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** A choice as `{ label, value }`, its value as text so a numeric option or default still matches, and
|
|
2
|
+
* `raw` as written, so a picked number is stored as one. */
|
|
3
|
+
export declare function fieldOption(option: string | number | {
|
|
4
|
+
label?: string;
|
|
5
|
+
value: string | number;
|
|
6
|
+
description?: string;
|
|
7
|
+
}): {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string;
|
|
10
|
+
raw: string | number;
|
|
11
|
+
description?: string | undefined;
|
|
12
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/form/Fields/fieldOption.ts
|
|
2
|
+
/** A choice as `{ label, value }`, its value as text so a numeric option or default still matches, and
|
|
3
|
+
* `raw` as written, so a picked number is stored as one. */
|
|
4
|
+
function fieldOption(option) {
|
|
5
|
+
return typeof option === "object" && option !== null ? {
|
|
6
|
+
...option,
|
|
7
|
+
label: option.label ?? String(option.value),
|
|
8
|
+
value: String(option.value),
|
|
9
|
+
raw: option.value
|
|
10
|
+
} : {
|
|
11
|
+
label: String(option),
|
|
12
|
+
value: String(option),
|
|
13
|
+
raw: option
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { fieldOption };
|
package/dist/form/Form.d.ts
CHANGED
|
@@ -75,8 +75,10 @@ export declare function FieldsFromOptions({ options, values, setFormDirty, setFi
|
|
|
75
75
|
spaceCompact?: boolean;
|
|
76
76
|
/** Prevents deletion of hidden+ignored field values (workflow forms filter at submit time) */
|
|
77
77
|
workflowForm?: boolean | undefined;
|
|
78
|
-
}): React.JSX.Element
|
|
78
|
+
}): React.JSX.Element;
|
|
79
79
|
export interface DynamicFormProps {
|
|
80
|
+
/** Enables validated layout-only CSS declarations on authored layout nodes. */
|
|
81
|
+
allowLayoutCSS?: boolean;
|
|
80
82
|
formJSONs: Record<string, unknown>;
|
|
81
83
|
reinitialize?: boolean;
|
|
82
84
|
setFormDirty?: (dirty: boolean) => void;
|
|
@@ -104,5 +106,5 @@ export interface DynamicFormProps {
|
|
|
104
106
|
/** Host-supplied field components, merged over the core registry by type. */
|
|
105
107
|
fields?: Record<string, FieldComponent>;
|
|
106
108
|
}
|
|
107
|
-
export declare function DynamicForm({ formJSONs: options, reinitialize, initialValues, setValues, setFormDirty, formikRef, labelPosition, missingFields, spaceCompact, organizationVariables, remoteVars, needsOrganizationVariables, onSubmit, submitLabel, className, workflowForm, contextKey, skipValueParse, fields, }: DynamicFormProps): React.JSX.Element;
|
|
109
|
+
export declare function DynamicForm({ formJSONs: options, reinitialize, initialValues, setValues, setFormDirty, formikRef, labelPosition, missingFields, spaceCompact, organizationVariables, remoteVars, needsOrganizationVariables, onSubmit, submitLabel, className, workflowForm, contextKey, skipValueParse, fields, allowLayoutCSS, }: DynamicFormProps): React.JSX.Element;
|
|
108
110
|
export {};
|