@pipelex/mthds-form 0.1.0 → 0.2.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/dist/{chunk-DAP47OGP.js → chunk-YWMUM7BC.js} +2 -2
- package/dist/{chunk-DAP47OGP.js.map → chunk-YWMUM7BC.js.map} +1 -1
- package/dist/core/index.d.ts +8 -8
- package/dist/core/index.js +1 -1
- package/dist/react/index.d.ts +31 -1
- package/dist/react/index.js +65 -14
- package/dist/react/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/core/index.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ interface Readiness {
|
|
|
109
109
|
* a plural slot is never "absent" in MTHDS, its empty form IS the empty list,
|
|
110
110
|
* and no method can declare "at least one item".
|
|
111
111
|
*
|
|
112
|
-
* **For a field
|
|
112
|
+
* **For a field this package built, the answer comes from `inputMustBeFilled`**
|
|
113
113
|
* (`contracts.ts`) - the SAME predicate the method viewer's Run button, its ajv
|
|
114
114
|
* `required` list and its missing-inputs toast all read. `buildRunFields`
|
|
115
115
|
* stamps it onto `gating`. This used to be re-derived here as
|
|
@@ -121,8 +121,8 @@ interface Readiness {
|
|
|
121
121
|
*
|
|
122
122
|
* The shape heuristic survives only as the fallback for a **hand-authored**
|
|
123
123
|
* `RunField` - story fixtures and unit tests, which have no contract to consult
|
|
124
|
-
* and therefore nothing to disagree with. Every field
|
|
125
|
-
* `buildRunFields` and carries `gating`, so
|
|
124
|
+
* and therefore nothing to disagree with. Every field a host renders comes from
|
|
125
|
+
* `buildRunFields` and carries `gating`, so a host is on the contract's answer
|
|
126
126
|
* alone.
|
|
127
127
|
*/
|
|
128
128
|
declare function mustBeFilled(field: RunField): boolean;
|
|
@@ -130,10 +130,10 @@ declare function mustBeFilled(field: RunField): boolean;
|
|
|
130
130
|
declare function computeReadiness(fields: RunField[], values: Record<string, unknown>): Readiness;
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
|
-
* One validation error, in the shape
|
|
133
|
+
* One validation error, in the shape hosts read (`property`, `message`,
|
|
134
134
|
* `name`, `stack`, `params.format`). Structurally a superset-compatible twin of
|
|
135
|
-
* RJSF's `RJSFValidationError`, so
|
|
136
|
-
*
|
|
135
|
+
* RJSF's `RJSFValidationError`, so a host surface still holding RJSF form errors
|
|
136
|
+
* (an RJSF-based inputs panel) can hand them to the same message renderer.
|
|
137
137
|
*/
|
|
138
138
|
interface RunInputError {
|
|
139
139
|
/** The ajv keyword that failed (`required`, `format`, `type`, …). */
|
|
@@ -218,7 +218,7 @@ declare function validateRunInputs(preparedData: Dict$1, inputs: Record<string,
|
|
|
218
218
|
declare function apiInputsFromSchemaData(preparedData: Dict$1, inputs: Record<string, PipeInputContract>): Dict$1;
|
|
219
219
|
|
|
220
220
|
/**
|
|
221
|
-
* Bridges the `MethodRunner`'s field values to the rest of the
|
|
221
|
+
* Bridges the `MethodRunner`'s field values to the rest of the host.
|
|
222
222
|
*
|
|
223
223
|
* The method-store keeps inputs in the *simplified* format and runs send the
|
|
224
224
|
* *full* RJSF form shape - both already handled by `inflate/deflateAllInputs`.
|
|
@@ -477,7 +477,7 @@ declare function toDateInputValue(value: string | undefined): string;
|
|
|
477
477
|
declare function toStoredDateValue(day: string, datetime: boolean): string | undefined;
|
|
478
478
|
|
|
479
479
|
/** The message keys this module renders, relative to the caller's namespace
|
|
480
|
-
* (
|
|
480
|
+
* (a host passes its own translator for that namespace). */
|
|
481
481
|
type ValidationMessageKey = 'inputPanel.aDateField' | 'inputPanel.pickValidDate' | 'inputPanel.pickValidDateEmpty' | 'inputPanel.dateCarriesTime' | 'inputPanel.invalidValue' | 'inputPanel.invalidValueWithData';
|
|
482
482
|
/**
|
|
483
483
|
* The translate function the caller injects. Typed on the EXACT keys this
|
package/dist/core/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { apiInputsFromRunValues, apiInputsFromSchemaData, asCalendarDate, buildPipeRef, buildRunFields, buildRunInputsSchema, collapseNullable, collectSchemaDefs, computeReadiness, conceptCategory, dayWithinDateTime, deflateAllInputs, deflateInput, derefSchema, describeValidationError, displayValue, fieldFilled, fieldsForContract, flattenAnyOf, getPipeIOContract, healStringWrappers, hoistDefsToRoot, inflateAllInputs, inflateInput, inputDataFromWorkingMemory, inputMustBeFilled, isAcceptableDate, isAcceptableDateTime, isFilled, isPluralInput, mustBeFilled, normalizeSchemaForRjsf, outputsFromPipeOutput, prepareRunInputs, prepareSchemaForRjsf, pruneEmptyOptionals, resolveConceptCode, resolveSchemaIndirection, rjsfDataFromRunValues, runValuesFromStore, schemaTypeOf, setValueAtPath, storeInputDataFromRunValues, toDateInputValue, toStoredDateValue, validateRunInputs, validateRunInputsSchema, valueAtProperty } from '../chunk-
|
|
1
|
+
export { apiInputsFromRunValues, apiInputsFromSchemaData, asCalendarDate, buildPipeRef, buildRunFields, buildRunInputsSchema, collapseNullable, collectSchemaDefs, computeReadiness, conceptCategory, dayWithinDateTime, deflateAllInputs, deflateInput, derefSchema, describeValidationError, displayValue, fieldFilled, fieldsForContract, flattenAnyOf, getPipeIOContract, healStringWrappers, hoistDefsToRoot, inflateAllInputs, inflateInput, inputDataFromWorkingMemory, inputMustBeFilled, isAcceptableDate, isAcceptableDateTime, isFilled, isPluralInput, mustBeFilled, normalizeSchemaForRjsf, outputsFromPipeOutput, prepareRunInputs, prepareSchemaForRjsf, pruneEmptyOptionals, resolveConceptCode, resolveSchemaIndirection, rjsfDataFromRunValues, runValuesFromStore, schemaTypeOf, setValueAtPath, storeInputDataFromRunValues, toDateInputValue, toStoredDateValue, validateRunInputs, validateRunInputsSchema, valueAtProperty } from '../chunk-YWMUM7BC.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/react/index.d.ts
CHANGED
|
@@ -273,4 +273,34 @@ declare function FieldStringsProvider({ strings, children, }: {
|
|
|
273
273
|
/** The strings the nearest provider supplies (English defaults when none does). */
|
|
274
274
|
declare function useFieldStrings(): FieldStrings;
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
/**
|
|
277
|
+
* How a field's LABEL chrome should read. The control itself never changes.
|
|
278
|
+
*
|
|
279
|
+
* - `studio` (default): the field's name verbatim in mono, with its concept
|
|
280
|
+
* pill. The name IS the identifier a builder writes in the `.mthds` file, so
|
|
281
|
+
* showing it exactly - and typed - is the point.
|
|
282
|
+
* - `app`: the field's name as a human question in sans, no concept pill. Inside
|
|
283
|
+
* a method app, `full_name` and `native.Text` are implementation detail; the
|
|
284
|
+
* person filling the form has never seen the method's source.
|
|
285
|
+
*
|
|
286
|
+
* Deliberately a context rather than a prop or a `FieldEnv` flag: only the
|
|
287
|
+
* components that own label chrome read it - `FieldShell`, `ObjectField`,
|
|
288
|
+
* `BooleanField` and `ListField` - and threading a prop would have meant
|
|
289
|
+
* editing every field control and both recursive containers.
|
|
290
|
+
*/
|
|
291
|
+
type FieldPresentation = 'studio' | 'app';
|
|
292
|
+
declare function FieldPresentationProvider({ presentation, children, }: {
|
|
293
|
+
presentation: FieldPresentation;
|
|
294
|
+
children: ReactNode;
|
|
295
|
+
}): react.JSX.Element;
|
|
296
|
+
declare function useFieldPresentation(): FieldPresentation;
|
|
297
|
+
/**
|
|
298
|
+
* `full_name` → `Full name`. Only the first word is capitalised: these are
|
|
299
|
+
* labels, not titles, and Title Case on every word reads as a form from 2009.
|
|
300
|
+
* Takes IDENTIFIERS only - snake_case or kebab-case names, where a separator
|
|
301
|
+
* is structure. An authored `title` never goes through here: it is already
|
|
302
|
+
* human-facing, and its hyphens are spelling (`E-mail address`), not structure.
|
|
303
|
+
*/
|
|
304
|
+
declare function humanizeFieldName(name: string): string;
|
|
305
|
+
|
|
306
|
+
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EnumField, type FieldEnv, type FieldPresentation, FieldPresentationProvider, FieldRenderer, type FieldRendererProps, FieldShell, type FieldStrings, FieldStringsProvider, type FileValue, ImageField, ListField, NumberField, ObjectField, OptionalToggle, ProseField, TextField, UnknownField, fieldControlClass, humanizeFieldName, useFieldPresentation, useFieldStrings };
|
package/dist/react/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { toStoredDateValue, toDateInputValue, isFilled } from '../chunk-
|
|
2
|
+
import { toStoredDateValue, toDateInputValue, isFilled } from '../chunk-YWMUM7BC.js';
|
|
3
3
|
import { clsx } from 'clsx';
|
|
4
4
|
import { twMerge } from 'tailwind-merge';
|
|
5
5
|
import { ChevronDown, ChevronUp, Check, List, Braces, ListChecks, ToggleLeft, Hash, Image, FileText, CalendarDays, Type, Loader2, Upload, Link2, ImageOff, EyeOff, Eye, X, Minus, Plus, Trash2 } from 'lucide-react';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
import * as React2 from 'react';
|
|
8
|
-
import { createContext, useMemo, useContext, useState, useRef, useCallback, useEffect } from 'react';
|
|
8
|
+
import { createContext, use, useMemo, useContext, useState, useRef, useCallback, useEffect } from 'react';
|
|
9
9
|
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
10
10
|
import { useDropzone } from 'react-dropzone';
|
|
11
11
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
@@ -44,6 +44,25 @@ function ConceptPill({ conceptRef, category, className }) {
|
|
|
44
44
|
}
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
+
var FieldPresentationContext = createContext("studio");
|
|
48
|
+
function FieldPresentationProvider({
|
|
49
|
+
presentation,
|
|
50
|
+
children
|
|
51
|
+
}) {
|
|
52
|
+
return /* @__PURE__ */ jsx(FieldPresentationContext, { value: presentation, children });
|
|
53
|
+
}
|
|
54
|
+
function useFieldPresentation() {
|
|
55
|
+
return use(FieldPresentationContext);
|
|
56
|
+
}
|
|
57
|
+
function humanizeFieldName(name) {
|
|
58
|
+
const words = name.replace(/[_-]+/g, " ").trim();
|
|
59
|
+
if (words === "") return name;
|
|
60
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
61
|
+
}
|
|
62
|
+
function fieldLabel(title, name, presentation) {
|
|
63
|
+
if (title !== void 0) return title;
|
|
64
|
+
return presentation === "app" ? humanizeFieldName(name) : name;
|
|
65
|
+
}
|
|
47
66
|
var Switch = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
48
67
|
SwitchPrimitives.Root,
|
|
49
68
|
{
|
|
@@ -65,6 +84,8 @@ var Switch = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
65
84
|
));
|
|
66
85
|
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
67
86
|
function BooleanField({ field, value, onChange, id, disabled }) {
|
|
87
|
+
const presentation = useFieldPresentation();
|
|
88
|
+
const isApp = presentation === "app";
|
|
68
89
|
return /* @__PURE__ */ jsxs(
|
|
69
90
|
"div",
|
|
70
91
|
{
|
|
@@ -79,11 +100,14 @@ function BooleanField({ field, value, onChange, id, disabled }) {
|
|
|
79
100
|
"label",
|
|
80
101
|
{
|
|
81
102
|
htmlFor: id,
|
|
82
|
-
className:
|
|
83
|
-
|
|
103
|
+
className: cn(
|
|
104
|
+
"text-[13px] font-medium leading-none text-foreground",
|
|
105
|
+
isApp ? "text-[13.5px]" : "font-mono"
|
|
106
|
+
),
|
|
107
|
+
children: fieldLabel(field.title, field.name, presentation)
|
|
84
108
|
}
|
|
85
109
|
),
|
|
86
|
-
/* @__PURE__ */ jsx(ConceptPill, { conceptRef: field.conceptRef, category: "boolean" })
|
|
110
|
+
!isApp && /* @__PURE__ */ jsx(ConceptPill, { conceptRef: field.conceptRef, category: "boolean" })
|
|
87
111
|
] }),
|
|
88
112
|
field.description && /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-relaxed text-muted-foreground", children: field.description })
|
|
89
113
|
] }),
|
|
@@ -151,8 +175,10 @@ function FieldShell({
|
|
|
151
175
|
className
|
|
152
176
|
}) {
|
|
153
177
|
const s = useFieldStrings();
|
|
178
|
+
const presentation = useFieldPresentation();
|
|
179
|
+
const isApp = presentation === "app";
|
|
154
180
|
const Label2 = htmlFor ? "label" : "div";
|
|
155
|
-
const labelText = title
|
|
181
|
+
const labelText = fieldLabel(title, name, presentation);
|
|
156
182
|
const showLabel = labelText.trim() !== "";
|
|
157
183
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
|
|
158
184
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
|
|
@@ -160,15 +186,18 @@ function FieldShell({
|
|
|
160
186
|
Label2,
|
|
161
187
|
{
|
|
162
188
|
...htmlFor ? { htmlFor } : {},
|
|
163
|
-
className:
|
|
189
|
+
className: cn(
|
|
190
|
+
"text-[13px] font-medium leading-none text-foreground",
|
|
191
|
+
isApp ? "text-[13.5px]" : "font-mono"
|
|
192
|
+
),
|
|
164
193
|
children: labelText
|
|
165
194
|
}
|
|
166
195
|
),
|
|
167
|
-
/* @__PURE__ */ jsx(ConceptPill, { conceptRef, category }),
|
|
196
|
+
!isApp && /* @__PURE__ */ jsx(ConceptPill, { conceptRef, category }),
|
|
168
197
|
!required && /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-[10px] uppercase tracking-wider text-muted-foreground/70", children: s.optionalBadge })
|
|
169
198
|
] }),
|
|
170
199
|
description && /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-relaxed text-muted-foreground", children: description }),
|
|
171
|
-
children,
|
|
200
|
+
isApp && error ? /* @__PURE__ */ jsx("div", { className: "rounded-lg ring-1 ring-destructive/70 ring-offset-4 ring-offset-background", children }) : children,
|
|
172
201
|
error && /* @__PURE__ */ jsx("p", { className: "flex items-center gap-1 text-[11px] text-destructive", role: "alert", children: error })
|
|
173
202
|
] });
|
|
174
203
|
}
|
|
@@ -809,14 +838,25 @@ function OptionalToggle({ count, expanded, onToggle, noun = "field" }) {
|
|
|
809
838
|
function ObjectField({ field, value, onChange, id, error, env }) {
|
|
810
839
|
const s = useFieldStrings();
|
|
811
840
|
const [showOptional, setShowOptional] = useState(false);
|
|
841
|
+
const presentation = useFieldPresentation();
|
|
842
|
+
const isApp = presentation === "app";
|
|
812
843
|
const data = value ?? {};
|
|
813
844
|
const setChild = (name, childValue) => onChange({ ...data, [name]: childValue });
|
|
814
845
|
const optionalEmpty = field.fields.filter((f) => !f.required && !isFilled(data[f.name]));
|
|
815
846
|
const visible = showOptional ? field.fields : field.fields.filter((f) => f.required || isFilled(data[f.name]));
|
|
816
847
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
817
848
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
|
|
818
|
-
/* @__PURE__ */ jsx(
|
|
819
|
-
|
|
849
|
+
/* @__PURE__ */ jsx(
|
|
850
|
+
"span",
|
|
851
|
+
{
|
|
852
|
+
className: cn(
|
|
853
|
+
"text-[13px] font-medium leading-none text-foreground",
|
|
854
|
+
isApp ? "text-[13.5px]" : "font-mono"
|
|
855
|
+
),
|
|
856
|
+
children: fieldLabel(field.title, field.name, presentation)
|
|
857
|
+
}
|
|
858
|
+
),
|
|
859
|
+
!isApp && /* @__PURE__ */ jsx(ConceptPill, { conceptRef: field.conceptRef, category: "structured" }),
|
|
820
860
|
!field.required && /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-[10px] uppercase tracking-wider text-muted-foreground/70", children: s.optionalBadge })
|
|
821
861
|
] }),
|
|
822
862
|
field.description && /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-relaxed text-muted-foreground", children: field.description }),
|
|
@@ -856,6 +896,8 @@ function ObjectField({ field, value, onChange, id, error, env }) {
|
|
|
856
896
|
}
|
|
857
897
|
function ListField({ field, value, onChange, id, error, env }) {
|
|
858
898
|
const s = useFieldStrings();
|
|
899
|
+
const presentation = useFieldPresentation();
|
|
900
|
+
const isApp = presentation === "app";
|
|
859
901
|
const items = value ?? [];
|
|
860
902
|
const setItem = (index, itemValue) => {
|
|
861
903
|
const next = items.slice();
|
|
@@ -866,8 +908,17 @@ function ListField({ field, value, onChange, id, error, env }) {
|
|
|
866
908
|
const addItem = () => onChange([...items, emptyValue(field.item)]);
|
|
867
909
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
868
910
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
|
|
869
|
-
/* @__PURE__ */ jsx(
|
|
870
|
-
|
|
911
|
+
/* @__PURE__ */ jsx(
|
|
912
|
+
"span",
|
|
913
|
+
{
|
|
914
|
+
className: cn(
|
|
915
|
+
"text-[13px] font-medium leading-none text-foreground",
|
|
916
|
+
isApp ? "text-[13.5px]" : "font-mono"
|
|
917
|
+
),
|
|
918
|
+
children: fieldLabel(field.title, field.name, presentation)
|
|
919
|
+
}
|
|
920
|
+
),
|
|
921
|
+
!isApp && /* @__PURE__ */ jsx(ConceptPill, { conceptRef: field.conceptRef, category: "list" }),
|
|
871
922
|
/* @__PURE__ */ jsx("span", { className: "font-mono text-[10.5px] text-muted-foreground", children: s.itemsCount(items.length) }),
|
|
872
923
|
!field.required && /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-[10px] uppercase tracking-wider text-muted-foreground/70", children: s.optionalBadge })
|
|
873
924
|
] }),
|
|
@@ -1113,6 +1164,6 @@ function FieldRenderer({ field, value, onChange, id, error, env }) {
|
|
|
1113
1164
|
}
|
|
1114
1165
|
}
|
|
1115
1166
|
|
|
1116
|
-
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EnumField, FieldRenderer, FieldShell, FieldStringsProvider, ImageField, ListField, NumberField, ObjectField, OptionalToggle, ProseField, TextField, UnknownField, fieldControlClass, useFieldStrings };
|
|
1167
|
+
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EnumField, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, ImageField, ListField, NumberField, ObjectField, OptionalToggle, ProseField, TextField, UnknownField, fieldControlClass, humanizeFieldName, useFieldPresentation, useFieldStrings };
|
|
1117
1168
|
//# sourceMappingURL=index.js.map
|
|
1118
1169
|
//# sourceMappingURL=index.js.map
|