@pipelex/mthds-form 0.23.1 → 0.23.2

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.
@@ -1,6 +1,6 @@
1
1
  export { planFileSave, planStuffSave } from '../chunk-ICUEHNEH.js';
2
2
  export { closeOptionalStructures, openOptionalStructures, seedInputs, seedObjectValue } from '../chunk-VH5CDQDR.js';
3
- export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue } from '../chunk-EQJBM3NS.js';
3
+ export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue } from '../chunk-O2VIVDHO.js';
4
4
  export { collectStuffFiles } from '../chunk-RRTI7AIR.js';
5
5
  export { describeValidationError, displayValue, valueAtProperty } from '../chunk-RPA7DNSK.js';
6
6
  export { apiInputsFromRunValues, fieldsForContract, inputDataFromWorkingMemory, outputsFromPipeOutput, rjsfDataFromRunValues, runValuesFromInputs, runValuesFromStore, sameRunValues, setValueAtPath, storeInputDataFromRunValues } from '../chunk-ZX52CQJ4.js';
@@ -11,7 +11,10 @@
11
11
  *
12
12
  * Shapes and pure functions only, so a host's server can import the types it
13
13
  * answers with, and the rules that write an answer into a value are tested in
14
- * node. No React, no fetch.
14
+ * node. No React, no fetch. What a row SAYS is data here (`SourceFile`'s
15
+ * `typeLabel` and `origin` are the host's words); how a row DRAWS is a
16
+ * rendering, so the glyph a host draws on a row is `./react`'s
17
+ * (`FilePickerSource.renderGlyph`), never a field of these shapes.
15
18
  */
16
19
  /** Whose files a file source lists: the person's own, or the whole team's. */
17
20
  type FileSourceScope = 'mine' | 'everyone';
@@ -45,8 +48,19 @@ interface SourceFile {
45
48
  url: string;
46
49
  /** The file's name, shown on the row and written into the field as its `filename`. */
47
50
  name: string;
48
- /** The file's MIME type, which names its format on the row. */
51
+ /**
52
+ * The file's MIME type, which picks the field's format the row's file is:
53
+ * the row names that format's label ("PNG") unless `typeLabel` words the
54
+ * type, and draws an image's glyph or a document's from it unless the
55
+ * host draws its own.
56
+ */
49
57
  mediaType?: string;
58
+ /**
59
+ * The file's type in the host's own words ("Picture", "PDF document"), said
60
+ * on the row's second line in place of the format's label, so a row reads
61
+ * as the host's own list of files does. An empty string counts as none.
62
+ */
63
+ typeLabel?: string;
50
64
  /** The file's size in bytes. */
51
65
  size?: number;
52
66
  /** How the file came to be. A `test` file is marked "Test file" at the head of its row's second line. */
@@ -144,11 +158,6 @@ declare function sourceFileValue(file: SourceFile): {
144
158
  * a new array and leaves `held` as it was.
145
159
  */
146
160
  declare function addChosenFiles(held: readonly unknown[] | undefined, chosen: readonly SourceFile[]): unknown[];
147
- /**
148
- * How many files a list may still take from a source: its bound less the files
149
- * it holds, since `addChosenFiles` writes into its empty rows before adding
150
- * any. `undefined` when the list has no bound.
151
- */
152
161
  /**
153
162
  * How many files `addChosenFiles` writes for `chosen` into `held`: the choices
154
163
  * whose address the list does not hold yet, each address once. This is what a
@@ -156,6 +165,11 @@ declare function addChosenFiles(held: readonly unknown[] | undefined, chosen: re
156
165
  * second row naming a chosen file, takes no room.
157
166
  */
158
167
  declare function chosenFilesAdded(held: readonly unknown[] | undefined, chosen: readonly SourceFile[]): number;
168
+ /**
169
+ * How many files a list may still take from a source: its bound less the files
170
+ * it holds, since `addChosenFiles` writes into its empty rows before adding
171
+ * any. `undefined` when the list has no bound.
172
+ */
159
173
  declare function roomForChosenFiles(held: readonly unknown[] | undefined, maxItemCount: number | undefined): number | undefined;
160
174
 
161
175
  export { type ExampleSource, type ExampleSourcePage, type ExampleSourceQuery, type FileSource, type FileSourcePage, type FileSourceQuery, type FileSourceScope, type FormExample, type SourceFile, addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue };
@@ -1,3 +1,3 @@
1
- export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue } from '../chunk-EQJBM3NS.js';
1
+ export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue } from '../chunk-O2VIVDHO.js';
2
2
  //# sourceMappingURL=sources.js.map
3
3
  //# sourceMappingURL=sources.js.map
@@ -1,6 +1,111 @@
1
1
  import * as react from 'react';
2
+ import { ReactNode, RefObject, Ref } from 'react';
2
3
  import { FileRunField, RunField } from './core/descriptor.js';
3
- import { FileSource } from './core/sources.js';
4
+ import { FileFormat } from './core/file-formats.js';
5
+ import { SourceFile, FileSource, FileSourceQuery, FileSourcePage } from './core/sources.js';
6
+
7
+ /**
8
+ * A file source as the control set takes it: the kernel's `FileSource`, which
9
+ * lists the files, and how a row draws, which only a renderer can say. Every
10
+ * `FileSource` is one, so a host that draws nothing passes its source as it is.
11
+ *
12
+ * `F` is the host's own row: a host may carry its own fields on the rows its
13
+ * `list` answers with (the format key its glyphs are chosen by, for instance)
14
+ * and read them back in `renderGlyph`, which receives each row exactly as
15
+ * `list` returned it. A source typed over its own row is accepted wherever a
16
+ * `FilePickerSource` is, because `renderGlyph` is declared as a method, whose
17
+ * parameter TypeScript compares both ways. Declared as a function-typed
18
+ * property it would be compared strictly, and a host's typed source would
19
+ * stop being accepted by `useMethodForm`, `FieldEnv` and `FilePicker`.
20
+ */
21
+ interface FilePickerSource<F extends SourceFile = SourceFile> extends FileSource {
22
+ list: (query: FileSourceQuery) => Promise<FileSourcePage & {
23
+ files: readonly F[];
24
+ }>;
25
+ /**
26
+ * Draws a row's glyph in place of the kernel's own, a 24px document or
27
+ * picture outline. What it returns sits at the row's start at its own size
28
+ * (the row is at least 64px tall and grows with a larger glyph), and is
29
+ * hidden from assistive technology, since the row's second line says the
30
+ * type. A row it returns what React renders nothing for keeps the kernel's
31
+ * glyph: `null`, `undefined`, `true`, `false` or `''`, so a
32
+ * `cond && <Tile />` whose condition is false falls back as it reads. A
33
+ * number is drawn, `0` included, because React draws it as text, so a
34
+ * condition that is a count is the host's to turn into a boolean.
35
+ */
36
+ renderGlyph?(file: F): ReactNode;
37
+ }
38
+ interface FilePickerEntryProps {
39
+ /** Opens the sheet. */
40
+ onOpen: () => void;
41
+ /** The field's label as the form shows it, which names the row for assistive technology. */
42
+ label: string;
43
+ disabled?: boolean;
44
+ /** The row's button, which the sheet hands focus back to (`FilePicker`'s `returnFocusTo`). */
45
+ ref?: Ref<HTMLButtonElement>;
46
+ /** The button's id, for a field whose label names this row, when it is the field's only way in. */
47
+ id?: string;
48
+ }
49
+ /**
50
+ * "Choose from your team's files": a full-width row with a folder icon, under
51
+ * the field's own controls.
52
+ */
53
+ declare function FilePickerEntry({ onOpen, label, disabled, ref, id }: FilePickerEntryProps): react.JSX.Element;
54
+ interface FilePickerProps {
55
+ /** The host's list, and how its rows draw. */
56
+ source: FilePickerSource;
57
+ /** What the field accepts: the list is narrowed to these types, and the sheet names them. */
58
+ formats: readonly FileFormat[];
59
+ /** A list field's picker: several rows may be chosen. One otherwise. */
60
+ multiple?: boolean;
61
+ /**
62
+ * The most files a choice may add, a list's remaining room; unbounded when
63
+ * absent. Counted as `chosenFilesAdded` counts them, against `held`.
64
+ */
65
+ maxChoices?: number;
66
+ /**
67
+ * The list's items. A chosen file whose address they hold adds nothing to
68
+ * the list, nor does a second row naming a chosen file, so neither takes
69
+ * any of `maxChoices`.
70
+ */
71
+ held?: readonly unknown[];
72
+ open: boolean;
73
+ onOpenChange: (open: boolean) => void;
74
+ /** What was chosen, in the order it was chosen. The sheet closes after. */
75
+ onUse: (files: SourceFile[]) => void;
76
+ /**
77
+ * Offered as "Upload a file" when the person holds no file of the field's
78
+ * formats: the sheet closes, and this starts the field's own upload.
79
+ */
80
+ onUpload?: () => void;
81
+ /**
82
+ * What focus goes back to when the sheet closes: the row that opened it, as
83
+ * a rule. Without it, focus goes back to whatever held it as the sheet
84
+ * opened, which a browser that does not focus a clicked button leaves unset.
85
+ */
86
+ returnFocusTo?: RefObject<HTMLElement | null>;
87
+ /**
88
+ * Runs as the sheet closes, before focus goes back: `preventDefault()` on the
89
+ * event and focus something else, as a field does with the file it now holds.
90
+ */
91
+ onCloseAutoFocus?: (event: Event) => void;
92
+ /**
93
+ * Holds the sheet shut, as the field is while it is disabled or a file is
94
+ * arriving: an open sheet closes, writing nothing, and `onOpenChange` is
95
+ * told so.
96
+ */
97
+ disabled?: boolean;
98
+ }
99
+ /**
100
+ * "Your team's files": a bottom sheet below 1280px and a dialog from 1280px,
101
+ * with the field's formats named under its title, the search, the Mine and
102
+ * Everyone switch, the rows newest first, and one primary button at the foot.
103
+ *
104
+ * Closing it, by its close button, Escape, the backdrop or a swipe down, leaves
105
+ * the field as it was: only Use writes. The sheet's state lives in its body,
106
+ * which mounts when it opens, so it always opens on a fresh choice.
107
+ */
108
+ declare function FilePicker({ open, onOpenChange, returnFocusTo, onCloseAutoFocus, disabled, ...props }: FilePickerProps): react.JSX.Element;
4
109
 
5
110
  /** The serializable value of a file field. URL is what the runner sends. */
6
111
  interface FileValue {
@@ -56,7 +161,7 @@ interface FileFieldProps {
56
161
  * and the chosen file is written through `onChange` as `{ url, filename }`,
57
162
  * the value an upload writes. See docs/sources.md.
58
163
  */
59
- fileSource?: FileSource;
164
+ fileSource?: FilePickerSource;
60
165
  error?: string;
61
166
  disabled?: boolean;
62
167
  }
@@ -192,9 +297,10 @@ interface FieldEnv {
192
297
  * is the capability, as `onDropFile`'s is: every empty file field then
193
298
  * offers "Choose from your team's files", and a list of files offers it for
194
299
  * several at once. The choice is written as `{ url, filename }`, exactly as
195
- * an upload's result is. See docs/sources.md.
300
+ * an upload's result is. Its `renderGlyph`, when given, draws each row's
301
+ * glyph in the sheet. See docs/sources.md.
196
302
  */
197
- fileSource?: FileSource;
303
+ fileSource?: FilePickerSource;
198
304
  }
199
305
  interface FieldRendererProps {
200
306
  field: RunField;
@@ -212,4 +318,4 @@ interface FieldRendererProps {
212
318
  */
213
319
  declare function FieldRenderer({ field, value, onChange, id, error, env }: FieldRendererProps): react.JSX.Element;
214
320
 
215
- export { DocumentField as D, type FieldEnv as F, ImageField as I, type RowMove as R, type UploadedFile as U, FieldRenderer as a, type FieldRendererProps as b, type FileValue as c };
321
+ export { DocumentField as D, type FieldEnv as F, ImageField as I, type RowMove as R, type UploadedFile as U, type FilePickerSource as a, FieldRenderer as b, type FieldRendererProps as c, FilePicker as d, FilePickerEntry as e, type FilePickerEntryProps as f, type FilePickerProps as g, type FileValue as h };
@@ -9,7 +9,7 @@ import { Components, Renderer } from '@json-render/react';
9
9
  import { B as BrandManifest } from '../manifest-DUeAWeqa.js';
10
10
  export { b as brandManifestSchema } from '../manifest-DUeAWeqa.js';
11
11
  import * as zod_v4_core from 'zod/v4/core';
12
- import { F as FieldEnv } from '../field-renderer-lNhtw-Cz.js';
12
+ import { F as FieldEnv } from '../field-renderer-CH-biG8C.js';
13
13
  export { seedInputs } from '../core/seed.js';
14
14
  import '../core/contracts.js';
15
15
  import 'mthds/protocol';
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { cn, checkedAccentClass, focusOutlineClass, linkTextClass, selectedBorderClass, selectedFillClass, fieldControlClass, ResultRoot, ResultField, FieldRenderer, ToggleGroup, ToggleGroupItem, selectedFillStrongClass, Switch, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../chunk-NOSHTDID.js';
2
+ import { cn, checkedAccentClass, focusOutlineClass, linkTextClass, selectedBorderClass, selectedFillClass, fieldControlClass, ResultRoot, ResultField, FieldRenderer, ToggleGroup, ToggleGroupItem, selectedFillStrongClass, Switch, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../chunk-W5MYXDLO.js';
3
3
  import '../chunk-ICUEHNEH.js';
4
4
  export { seedInputs } from '../chunk-VH5CDQDR.js';
5
- import '../chunk-EQJBM3NS.js';
5
+ import '../chunk-O2VIVDHO.js';
6
6
  import '../chunk-RRTI7AIR.js';
7
7
  import '../chunk-ZX52CQJ4.js';
8
8
  import { isNativeValueNode, readDateContent, formatDateContent, isNativeHtmlNode, isNativeDateNode, isNativeCompositeNode } from '../chunk-CM4KVG53.js';
@@ -1,16 +1,16 @@
1
- import { F as FieldEnv, R as RowMove, U as UploadedFile } from '../field-renderer-lNhtw-Cz.js';
2
- export { D as DocumentField, a as FieldRenderer, b as FieldRendererProps, c as FileValue, I as ImageField } from '../field-renderer-lNhtw-Cz.js';
1
+ import { F as FieldEnv, R as RowMove, a as FilePickerSource, U as UploadedFile } from '../field-renderer-CH-biG8C.js';
2
+ export { D as DocumentField, b as FieldRenderer, c as FieldRendererProps, d as FilePicker, e as FilePickerEntry, f as FilePickerEntryProps, g as FilePickerProps, h as FileValue, I as ImageField } from '../field-renderer-CH-biG8C.js';
3
3
  import * as react from 'react';
4
- import { ReactNode, RefObject, Ref } from 'react';
4
+ import { ReactNode } from 'react';
5
5
  import { BooleanRunField, DateRunField, EnumRunField, ListRunField, NumberRunField, ObjectRunField, ProseRunField, TextRunField, UnknownRunField, RunField, ConceptCategory } from '../core/descriptor.js';
6
6
  import { PipeInputFormDescriptor, PipeIOContract } from 'mthds/protocol';
7
7
  import { Readiness } from '../core/readiness.js';
8
- import { FileSource, ExampleSource, SourceFile, FormExample } from '../core/sources.js';
9
- export { ExampleSourcePage, ExampleSourceQuery, FileSourcePage, FileSourceQuery, FileSourceScope } from '../core/sources.js';
10
- import { FileFormat } from '../core/file-formats.js';
8
+ import { ExampleSource, FormExample } from '../core/sources.js';
9
+ export { ExampleSourcePage, ExampleSourceQuery, FileSource, FileSourcePage, FileSourceQuery, FileSourceScope, SourceFile } from '../core/sources.js';
11
10
  import { SaveFiles, SaveFile, SaveResult } from '../core/save-plan.js';
12
11
  import { StuffFileKind } from '../core/stuff-files.js';
13
12
  import { HtmlContentView } from '../core/native-content.js';
13
+ import '../core/file-formats.js';
14
14
  import '../core/contracts.js';
15
15
 
16
16
  interface BooleanFieldProps {
@@ -556,9 +556,10 @@ interface UseMethodFormOptions {
556
556
  * is the capability, as `uploadFile`'s is: every empty file field then offers
557
557
  * "Choose from your team's files", and a list of files offers it for several
558
558
  * at once. The choice is written as `{ url, filename }`, as an upload's
559
- * result is. See docs/sources.md.
559
+ * result is. Its `renderGlyph`, when given, draws each row's glyph in the
560
+ * sheet. See docs/sources.md.
560
561
  */
561
- fileSource?: FileSource;
562
+ fileSource?: FilePickerSource;
562
563
  /**
563
564
  * Where the form can take a saved example of the method. When given,
564
565
  * `MethodForm` offers "Fill with an example" above the fields, which sets
@@ -686,7 +687,7 @@ interface MethodFormController extends MethodFormState {
686
687
  filename: string;
687
688
  }>) | undefined;
688
689
  /** The host's file source, which `MethodForm` hands its file fields. */
689
- fileSource: FileSource | undefined;
690
+ fileSource: FilePickerSource | undefined;
690
691
  /** The host's example source, which `MethodForm` offers above the fields. */
691
692
  exampleSource: ExampleSource | undefined;
692
693
  }
@@ -741,78 +742,6 @@ interface MethodFormProps {
741
742
  */
742
743
  declare function MethodForm({ locale, strings, presentation, ...props }: MethodFormProps): react.ReactElement<unknown, string | react.JSXElementConstructor<any>>;
743
744
 
744
- interface FilePickerEntryProps {
745
- /** Opens the sheet. */
746
- onOpen: () => void;
747
- /** The field's label as the form shows it, which names the row for assistive technology. */
748
- label: string;
749
- disabled?: boolean;
750
- /** The row's button, which the sheet hands focus back to (`FilePicker`'s `returnFocusTo`). */
751
- ref?: Ref<HTMLButtonElement>;
752
- /** The button's id, for a field whose label names this row, when it is the field's only way in. */
753
- id?: string;
754
- }
755
- /**
756
- * "Choose from your team's files": a full-width row with a folder icon, under
757
- * the field's own controls.
758
- */
759
- declare function FilePickerEntry({ onOpen, label, disabled, ref, id }: FilePickerEntryProps): react.JSX.Element;
760
- interface FilePickerProps {
761
- /** The host's list. */
762
- source: FileSource;
763
- /** What the field accepts: the list is narrowed to these types, and the sheet names them. */
764
- formats: readonly FileFormat[];
765
- /** A list field's picker: several rows may be chosen. One otherwise. */
766
- multiple?: boolean;
767
- /**
768
- * The most files a choice may add, a list's remaining room; unbounded when
769
- * absent. Counted as `chosenFilesAdded` counts them, against `held`.
770
- */
771
- maxChoices?: number;
772
- /**
773
- * The list's items. A chosen file whose address they hold adds nothing to
774
- * the list, nor does a second row naming a chosen file, so neither takes
775
- * any of `maxChoices`.
776
- */
777
- held?: readonly unknown[];
778
- open: boolean;
779
- onOpenChange: (open: boolean) => void;
780
- /** What was chosen, in the order it was chosen. The sheet closes after. */
781
- onUse: (files: SourceFile[]) => void;
782
- /**
783
- * Offered as "Upload a file" when the person holds no file of the field's
784
- * formats: the sheet closes, and this starts the field's own upload.
785
- */
786
- onUpload?: () => void;
787
- /**
788
- * What focus goes back to when the sheet closes: the row that opened it, as
789
- * a rule. Without it, focus goes back to whatever held it as the sheet
790
- * opened, which a browser that does not focus a clicked button leaves unset.
791
- */
792
- returnFocusTo?: RefObject<HTMLElement | null>;
793
- /**
794
- * Runs as the sheet closes, before focus goes back: `preventDefault()` on the
795
- * event and focus something else, as a field does with the file it now holds.
796
- */
797
- onCloseAutoFocus?: (event: Event) => void;
798
- /**
799
- * Holds the sheet shut, as the field is while it is disabled or a file is
800
- * arriving: an open sheet closes, writing nothing, and `onOpenChange` is
801
- * told so.
802
- */
803
- disabled?: boolean;
804
- }
805
- /**
806
- * "Your team's files": a bottom sheet below 1280px and a dialog from 1280px,
807
- * with the field's formats named under its title, the search, the Mine and
808
- * Everyone switch, the rows newest first, and one primary button at the foot.
809
- *
810
- * Closing it, by its close button, Escape, the backdrop or a swipe down, leaves
811
- * the field as it was: only Use writes. The sheet's state lives in its body,
812
- * which mounts when it opens, so it always opens on a fresh choice.
813
- */
814
- declare function FilePicker({ open, onOpenChange, returnFocusTo, onCloseAutoFocus, disabled, ...props }: FilePickerProps): react.JSX.Element;
815
-
816
745
  interface FillWithExampleProps {
817
746
  /** The host's examples of this method. */
818
747
  source: ExampleSource;
@@ -1648,4 +1577,4 @@ declare function FieldDomIdProvider({ prefix, children, }: {
1648
1577
  */
1649
1578
  declare function useFieldDomId(path: string): string;
1650
1579
 
1651
- export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, type DownloadDisplay, EN_FIELD_STRINGS, EnumField, ExampleSource, FIELD_STRINGS_BY_LOCALE, FR_FIELD_STRINGS, FieldDomIdProvider, FieldEnv, type FieldPresentation, FieldPresentationProvider, FieldShell, type FieldStrings, FieldStringsProvider, FilePicker, FilePickerEntry, type FilePickerEntryProps, type FilePickerProps, FileSource, FillWithExample, type FillWithExampleProps, FormExample, type HtmlPdf, type HtmlPdfOptions, HtmlPreview, type HtmlPreviewProps, JsonView, ListField, Markdown, type MarkdownProps, type MarkupResolvers, MethodForm, type MethodFormController, type MethodFormProps, type MethodFormState, type MethodFormUploadContext, type MethodFormValues, NumberField, ObjectField, OptionalToggle, PdfDownloadButton, type PdfDownloadButtonProps, type PdfPage, ProseField, type ProseImages, type RenderPdf, type ResolveShareUrl, type ResolveUrl, type ResolveUrls, ResultEnvProvider, ResultField, type ResultFieldProps, RowMove, SUPPORTED_LOCALES, SourceFile, StuffViewer, type StuffViewerProps, type StuffViewerView, type TableLayout, TextField, UnknownField, UploadedFile, type UseMethodFormOptions, fieldControlClass, fieldStringsFor, humanizeFieldName, renderHtmlPdf, resolveHtmlStorageUrls, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useMethodForm, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
1580
+ export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, type DownloadDisplay, EN_FIELD_STRINGS, EnumField, ExampleSource, FIELD_STRINGS_BY_LOCALE, FR_FIELD_STRINGS, FieldDomIdProvider, FieldEnv, type FieldPresentation, FieldPresentationProvider, FieldShell, type FieldStrings, FieldStringsProvider, FilePickerSource, FillWithExample, type FillWithExampleProps, FormExample, type HtmlPdf, type HtmlPdfOptions, HtmlPreview, type HtmlPreviewProps, JsonView, ListField, Markdown, type MarkdownProps, type MarkupResolvers, MethodForm, type MethodFormController, type MethodFormProps, type MethodFormState, type MethodFormUploadContext, type MethodFormValues, NumberField, ObjectField, OptionalToggle, PdfDownloadButton, type PdfDownloadButtonProps, type PdfPage, ProseField, type ProseImages, type RenderPdf, type ResolveShareUrl, type ResolveUrl, type ResolveUrls, ResultEnvProvider, ResultField, type ResultFieldProps, RowMove, SUPPORTED_LOCALES, StuffViewer, type StuffViewerProps, type StuffViewerView, type TableLayout, TextField, UnknownField, UploadedFile, type UseMethodFormOptions, fieldControlClass, fieldStringsFor, humanizeFieldName, renderHtmlPdf, resolveHtmlStorageUrls, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useMethodForm, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EN_FIELD_STRINGS, EnumField, FIELD_STRINGS_BY_LOCALE, FR_FIELD_STRINGS, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, FilePicker, FilePickerEntry, FillWithExample, HtmlPreview, ImageField, JsonView, ListField, Markdown, MethodForm, NumberField, ObjectField, OptionalToggle, PdfDownloadButton, ProseField, ResultEnvProvider, ResultField, SUPPORTED_LOCALES, StuffViewer, TextField, UnknownField, fieldControlClass, fieldStringsFor, humanizeFieldName, renderHtmlPdf, resolveHtmlStorageUrls, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useMethodForm, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl } from '../chunk-NOSHTDID.js';
2
+ export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EN_FIELD_STRINGS, EnumField, FIELD_STRINGS_BY_LOCALE, FR_FIELD_STRINGS, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, FilePicker, FilePickerEntry, FillWithExample, HtmlPreview, ImageField, JsonView, ListField, Markdown, MethodForm, NumberField, ObjectField, OptionalToggle, PdfDownloadButton, ProseField, ResultEnvProvider, ResultField, SUPPORTED_LOCALES, StuffViewer, TextField, UnknownField, fieldControlClass, fieldStringsFor, humanizeFieldName, renderHtmlPdf, resolveHtmlStorageUrls, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useMethodForm, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl } from '../chunk-W5MYXDLO.js';
3
3
  import '../chunk-ICUEHNEH.js';
4
4
  import '../chunk-VH5CDQDR.js';
5
- import '../chunk-EQJBM3NS.js';
5
+ import '../chunk-O2VIVDHO.js';
6
6
  import '../chunk-RRTI7AIR.js';
7
7
  import '../chunk-ZX52CQJ4.js';
8
8
  import '../chunk-CM4KVG53.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipelex/mthds-form",
3
- "version": "0.23.1",
3
+ "version": "0.23.2",
4
4
  "description": "Headless form kernel and control set for MTHDS method inputs",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/sources.ts"],"names":[],"mappings":";AA+IO,SAAS,gBAAgB,IAAA,EAAqD;AACnF,EAAA,OAAO,EAAE,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,QAAA,EAAU,KAAK,IAAA,EAAK;AAC9C;AAGA,SAAS,QAAQ,IAAA,EAAmC;AAClD,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,UAAU,OAAO,MAAA;AAC9C,EAAA,MAAM,MAAO,IAAA,CAA2B,GAAA;AACxC,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,KAAK,GAAA,GAAM,MAAA;AACvD;AAGA,SAAS,SAAS,KAAA,EAAwC;AACxD,EAAA,OAAO,IAAI,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAuB,GAAA,KAAQ,MAAS,CAAC,CAAA;AACrF;AAUO,SAAS,cAAA,CACd,MACA,MAAA,EACW;AACX,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAI,IAAA,IAAQ,EAAG,CAAA;AAC9B,EAAA,MAAM,IAAA,GAAO,SAAS,KAAK,CAAA;AAC3B,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,MAAW,QAAQ,MAAA,EAAQ;AACzB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,EAAG;AACxB,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,GAAG,CAAA;AACjB,IAAA,OAAO,IAAA,GAAO,MAAM,MAAA,IAAU,OAAA,CAAQ,MAAM,IAAI,CAAC,CAAA,KAAM,MAAA,EAAW,IAAA,IAAQ,CAAA;AAC1E,IAAA,IAAI,OAAO,KAAA,CAAM,MAAA,QAAc,IAAI,CAAA,GAAI,gBAAgB,IAAI,CAAA;AAAA,SACtD,KAAA,CAAM,IAAA,CAAK,eAAA,CAAgB,IAAI,CAAC,CAAA;AACrC,IAAA,IAAA,IAAQ,CAAA;AAAA,EACV;AACA,EAAA,OAAO,KAAA;AACT;AAaO,SAAS,gBAAA,CACd,MACA,MAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,IAAA,IAAQ,EAAE,CAAA;AAChC,EAAA,MAAM,SAAS,IAAA,CAAK,IAAA;AACpB,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,KAAK,GAAG,CAAA;AAC5C,EAAA,OAAO,KAAK,IAAA,GAAO,MAAA;AACrB;AAEO,SAAS,kBAAA,CACd,MACA,YAAA,EACoB;AACpB,EAAA,IAAI,YAAA,KAAiB,QAAW,OAAO,MAAA;AACvC,EAAA,MAAM,KAAA,GAAA,CAAS,IAAA,IAAQ,EAAC,EAAG,MAAA,CAAO,CAAC,IAAA,KAAS,OAAA,CAAQ,IAAI,CAAA,KAAM,MAAS,CAAA,CAAE,MAAA;AACzE,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,YAAA,GAAe,KAAK,CAAA;AACzC","file":"chunk-EQJBM3NS.js","sourcesContent":["/**\n * The two optional host seams beside the upload: a **file source**, which lets\n * a file field take a file the host already stores, and an **example source**,\n * which lets a whole form take a set of values someone saved for the method.\n *\n * The kernel states the shapes and applies the answers; the host answers. It\n * knows nothing of any platform's routes, records or permissions: a host maps\n * its own list onto these shapes, and a host that gives neither seam gets the\n * form it had before. The controls that use them are `./react`'s\n * (`FilePicker`, `FillWithExample`), and docs/sources.md is the contract.\n *\n * Shapes and pure functions only, so a host's server can import the types it\n * answers with, and the rules that write an answer into a value are tested in\n * node. No React, no fetch.\n */\n\n/** Whose files a file source lists: the person's own, or the whole team's. */\nexport type FileSourceScope = 'mine' | 'everyone';\n\n/** One page of a file source's list, as the picker asks for it. */\nexport interface FileSourceQuery {\n /** What the person searched for, trimmed; empty when they searched for nothing. */\n search: string;\n /** Whose files to list. */\n scope: FileSourceScope;\n /**\n * The MIME types the field accepts, after any narrowing a host applied\n * (`narrowFileFormats`), in the field's own order. The list must hold only\n * files of these types: the picker writes what is chosen straight into the\n * field, and a field that refuses a dropped file of another type must not\n * be handed one this way.\n */\n mediaTypes: readonly string[];\n /** Where to continue: absent for the first page, else the previous page's `nextCursor`. */\n cursor?: string;\n /** Aborted when the answer is no longer wanted: a newer search, a closed picker. */\n signal: AbortSignal;\n}\n\n/** One row of a file source's list: a file the host already stores. */\nexport interface SourceFile {\n /** The row's identity in the host's list, which a choice is kept by. */\n id: string;\n /**\n * The stored file's address, written into the field as its `url`, exactly as\n * an upload's result is. Several rows may share one address.\n */\n url: string;\n /** The file's name, shown on the row and written into the field as its `filename`. */\n name: string;\n /** The file's MIME type, which names its format on the row. */\n mediaType?: string;\n /** The file's size in bytes. */\n size?: number;\n /** How the file came to be. A `test` file is marked \"Test file\" at the head of its row's second line. */\n kind?: 'uploaded' | 'generated' | 'test';\n /** When the file was stored, as an ISO 8601 timestamp; the row says it as a date. */\n createdAt?: string;\n /**\n * Where the file came from, in the host's own words (\"Uploaded by Ana\",\n * \"Made by Invoice extraction\"), shown on the row's second line as it is.\n */\n origin?: string;\n}\n\n/** One page of a file source's answer. */\nexport interface FileSourcePage {\n /** The page's files, newest first. A page may be empty and still carry a cursor. */\n files: readonly SourceFile[];\n /** Where the next page starts, or nothing when this page is the last. */\n nextCursor?: string | null;\n}\n\n/**\n * Where a file field can take a file the host already stores. When a form has\n * one, every file field offers \"Choose from your team's files\", and a list of\n * files offers it for several at once.\n */\nexport interface FileSource {\n /** Lists one page of files for a query. Rejecting shows the failure with Try again. */\n list: (query: FileSourceQuery) => Promise<FileSourcePage>;\n /** Which of Mine and Everyone the picker opens on. */\n initialScope: FileSourceScope;\n}\n\n/** One example of a method: a name and the inputs a run of it sends. */\nexport interface FormExample {\n /** The example's identity in the host's list. */\n id: string;\n /** The example's name, shown on its row. */\n name: string;\n /**\n * The inputs as a run takes them: each input `{ concept, content }`, an\n * optional input left out, an empty plural input a bare `[]`. It is the\n * shape `apiInputsFromRunValues` produces, so a host saves an example from\n * `form.inputs` and hands it back as it is.\n */\n inputs: Readonly<Record<string, unknown>>;\n}\n\n/** One page of an example source's list. */\nexport interface ExampleSourceQuery {\n /** Where to continue: absent for the first page, else the previous page's `nextCursor`. */\n cursor?: string;\n /** Aborted when the answer is no longer wanted. */\n signal: AbortSignal;\n}\n\n/** One page of an example source's answer. */\nexport interface ExampleSourcePage {\n /** The page's examples, in the order the list shows them. */\n examples: readonly FormExample[];\n /** Where the next page starts, or nothing when this page is the last. */\n nextCursor?: string | null;\n}\n\n/**\n * Where a form can take a whole set of values. When a form has one, it offers\n * \"Fill with an example\". `rename` and `delete` are capabilities: each is\n * offered on a row's menu only when given, so a host gives them only to a\n * person allowed to change examples.\n */\nexport interface ExampleSource {\n /** Lists one page of the method's examples. Rejecting shows the failure with Try again. */\n list: (query: ExampleSourceQuery) => Promise<ExampleSourcePage>;\n /**\n * Renames an example. Resolving to the example as stored replaces the row;\n * resolving to nothing keeps the row under the new name.\n */\n rename?: (example: FormExample, name: string) => Promise<FormExample | void>;\n /** Deletes an example. Asked for only after the person confirmed it. */\n delete?: (example: FormExample) => Promise<void>;\n /**\n * Whether \"Fill with an example\" is left out while the method has no\n * example. `false` by default, when the empty list says how to make one.\n * A host sets it for a person who cannot save an example, to whom an empty\n * list has nothing to offer; the form then asks for the first page as it\n * mounts, to know whether to offer the control.\n */\n hideWhenEmpty?: boolean;\n}\n\n/** What a chosen file writes into its field: the same `{ url, filename }` an upload writes. */\nexport function sourceFileValue(file: SourceFile): { url: string; filename: string } {\n return { url: file.url, filename: file.name };\n}\n\n/** The `url` a list item holds, when it is a file value holding one. */\nfunction heldUrl(item: unknown): string | undefined {\n if (!item || typeof item !== 'object') return undefined;\n const url = (item as { url?: unknown }).url;\n return typeof url === 'string' && url !== '' ? url : undefined;\n}\n\n/** The addresses a list's items hold, each once. */\nfunction heldUrls(items: readonly unknown[]): Set<string> {\n return new Set(items.map(heldUrl).filter((url): url is string => url !== undefined));\n}\n\n/**\n * A list of files with the chosen files written into it, in the order they\n * were chosen: first into the rows that hold no file yet (a row the person\n * added and left empty), then as new rows after the last. A file whose address\n * the list already holds is not written again, and neither is a second choice\n * of one address: two rows of a source may name the same stored file. Returns\n * a new array and leaves `held` as it was.\n */\nexport function addChosenFiles(\n held: readonly unknown[] | undefined,\n chosen: readonly SourceFile[],\n): unknown[] {\n const items = [...(held ?? [])];\n const urls = heldUrls(items);\n let free = 0;\n for (const file of chosen) {\n if (urls.has(file.url)) continue;\n urls.add(file.url);\n while (free < items.length && heldUrl(items[free]) !== undefined) free += 1;\n if (free < items.length) items[free] = sourceFileValue(file);\n else items.push(sourceFileValue(file));\n free += 1;\n }\n return items;\n}\n\n/**\n * How many files a list may still take from a source: its bound less the files\n * it holds, since `addChosenFiles` writes into its empty rows before adding\n * any. `undefined` when the list has no bound.\n */\n/**\n * How many files `addChosenFiles` writes for `chosen` into `held`: the choices\n * whose address the list does not hold yet, each address once. This is what a\n * choice spends of `roomForChosenFiles`, so a held file chosen again, or a\n * second row naming a chosen file, takes no room.\n */\nexport function chosenFilesAdded(\n held: readonly unknown[] | undefined,\n chosen: readonly SourceFile[],\n): number {\n const urls = heldUrls(held ?? []);\n const before = urls.size;\n for (const file of chosen) urls.add(file.url);\n return urls.size - before;\n}\n\nexport function roomForChosenFiles(\n held: readonly unknown[] | undefined,\n maxItemCount: number | undefined,\n): number | undefined {\n if (maxItemCount === undefined) return undefined;\n const files = (held ?? []).filter((item) => heldUrl(item) !== undefined).length;\n return Math.max(0, maxItemCount - files);\n}\n"]}