@pipelex/mthds-form 0.12.0 → 0.13.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 +9 -0
- package/dist/{chunk-V7T4DM63.js → chunk-7KQXGG6J.js} +6 -4
- package/dist/chunk-7KQXGG6J.js.map +1 -0
- package/dist/{chunk-4KX6YTLW.js → chunk-D2EQVWGN.js} +113 -21
- package/dist/chunk-D2EQVWGN.js.map +1 -0
- package/dist/{chunk-4KGQ65TQ.js → chunk-G6SFMTL4.js} +3 -3
- package/dist/{chunk-4KGQ65TQ.js.map → chunk-G6SFMTL4.js.map} +1 -1
- package/dist/{chunk-IUWLOSAM.js → chunk-IR3OFSGD.js} +3 -3
- package/dist/{chunk-IUWLOSAM.js.map → chunk-IR3OFSGD.js.map} +1 -1
- package/dist/{chunk-PM55AHRO.js → chunk-MJQ7CXUB.js} +6 -3
- package/dist/chunk-MJQ7CXUB.js.map +1 -0
- package/dist/{chunk-VS5JMFUV.js → chunk-RRTI7AIR.js} +2 -2
- package/dist/chunk-RRTI7AIR.js.map +1 -0
- package/dist/core/gate.js +2 -2
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +5 -5
- package/dist/core/readiness.d.ts +9 -1
- package/dist/core/readiness.js +1 -1
- package/dist/core/save-plan.d.ts +13 -4
- package/dist/core/save-plan.js +2 -2
- package/dist/core/stuff-files.d.ts +7 -1
- package/dist/core/stuff-files.js +1 -1
- package/dist/core/values.js +2 -2
- package/dist/generative/index.js +4 -4
- package/dist/generative/index.js.map +1 -1
- package/dist/react/index.d.ts +58 -7
- package/dist/react/index.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-4KX6YTLW.js.map +0 -1
- package/dist/chunk-PM55AHRO.js.map +0 -1
- package/dist/chunk-V7T4DM63.js.map +0 -1
- package/dist/chunk-VS5JMFUV.js.map +0 -1
package/README.md
CHANGED
|
@@ -58,6 +58,14 @@ Submitting goes through the gate: `buildRunInputsSchema` → `prepareRunInputs`
|
|
|
58
58
|
|
|
59
59
|
A file field (`document` or `image`) carries `formats`, the formats its slot accepts, and the control's hint, file-picker filter and check all read that one list. A host whose upload path takes fewer types narrows the whole tree once with `narrowFileFormats(fields, mimeTypes)` and has its server check uploads against the same list. [docs/upload-seam.md](docs/upload-seam.md) is everything a file control and its host owe each other.
|
|
60
60
|
|
|
61
|
+
The controls' own copy comes through `FieldStringsProvider`: `locale` picks a language pack (`fr`, `fr-FR`, `en`…, English when unknown) and `strings` overrides single keys on top. The field labels, helper lines and enum choices come from the method's own names and descriptions, never from the host:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
<FieldStringsProvider locale="fr">{/* the form over buildRunFields(form, contract) */}</FieldStringsProvider>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
[docs/i18n.md](docs/i18n.md) has the language packs and the locale switch.
|
|
68
|
+
|
|
61
69
|
## Theming
|
|
62
70
|
|
|
63
71
|
The controls carry Tailwind classes over the standard shadcn/ui semantic tokens (`--background`, `--input`, `--border`, `--primary`, …). A host that already defines those tokens gets controls that match its product with no configuration. A host with no Tailwind build loads the prebuilt `@pipelex/mthds-form/styles.css`. Both paths, and the exact token list, are in [docs/theming.md](docs/theming.md).
|
|
@@ -71,6 +79,7 @@ The controls carry Tailwind classes over the standard shadcn/ui semantic tokens
|
|
|
71
79
|
| [docs/theming.md](docs/theming.md) | the token contract and host setup |
|
|
72
80
|
| [docs/wire-correspondence.md](docs/wire-correspondence.md) | the name-for-name wire ↔ `RunField` mapping |
|
|
73
81
|
| [docs/upload-seam.md](docs/upload-seam.md) | what a file control and its host owe each other: accepted formats and narrowing them, write-back paths, previews, the file card |
|
|
82
|
+
| [docs/i18n.md](docs/i18n.md) | wording a form for its reader: the controls' strings, the French set and the locale switch |
|
|
74
83
|
| [docs/derivation-swap.md](docs/derivation-swap.md) | the record of the swap to the wire descriptor — what changed, what survived |
|
|
75
84
|
|
|
76
85
|
## Development
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { collectStuffFiles } from './chunk-
|
|
1
|
+
import { collectStuffFiles } from './chunk-RRTI7AIR.js';
|
|
2
2
|
import { viewableUrl, readDataUrl, dataUrlExtensions } from './chunk-CM4KVG53.js';
|
|
3
3
|
|
|
4
4
|
// src/core/save-plan.ts
|
|
@@ -85,7 +85,9 @@ function typeForName(name) {
|
|
|
85
85
|
}
|
|
86
86
|
function nameFor(file, base, allowed) {
|
|
87
87
|
const own = file.filename ? safeName(file.filename) : "";
|
|
88
|
-
const
|
|
88
|
+
const place = file.path.split(".").slice(1).join("-");
|
|
89
|
+
const named = safeName(base) || "result";
|
|
90
|
+
const stem = own || (place ? `${named}-${place}` : named);
|
|
89
91
|
const stated = own ? extensionOf(own) : "";
|
|
90
92
|
if (allowed) {
|
|
91
93
|
if (stated && allowed.includes(stated)) return stem;
|
|
@@ -121,5 +123,5 @@ function jsonCopy(value) {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
export { planFileSave, planStuffSave };
|
|
124
|
-
//# sourceMappingURL=chunk-
|
|
125
|
-
//# sourceMappingURL=chunk-
|
|
126
|
+
//# sourceMappingURL=chunk-7KQXGG6J.js.map
|
|
127
|
+
//# sourceMappingURL=chunk-7KQXGG6J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/save-plan.ts"],"names":["extension"],"mappings":"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","file":"chunk-7KQXGG6J.js","sourcesContent":["import { dataUrlExtensions, readDataUrl, viewableUrl } from './native-content';\nimport { collectStuffFiles, type StuffFile, type StuffFileKind } from './stuff-files';\nimport type { RunField } from './descriptor';\n\n/**\n * What saving a result MEANS, decided with no DOM: which files, what each is\n * called, what type it is, and where its bytes are.\n *\n * ## Why the plan is separate from the delivery\n *\n * Handing bytes to a reader is the part that depends on where the view runs.\n * An ordinary browser tab saves through an object URL and a clicked link; a\n * view inside a sandboxed frame is refused all of that and has to ask its host\n * to do it, typically by passing links and inline contents across a bridge that\n * fetches the links itself. What to save is the same answer in both places, so\n * it is computed once, here, and a delivery only has to carry it out. The\n * default browser delivery lives in `./react`; a host supplies its own through\n * `ResultEnvProvider`'s `saveFiles`. See docs/result-view.md § \"Saving a\n * result\".\n *\n * ## Why a planned file carries a URL rather than bytes\n *\n * A host's download bridge takes links and fetches them itself, which is also\n * what keeps a cross-origin fetch out of a frame that cannot make one. So a\n * stored file is planned as the URL the gate admitted, and only the default\n * browser delivery fetches it. Content the stuff carries inline (the JSON copy\n * of the data, an HTML page) is planned as its text.\n */\n\n/** What a planned file is: one of the stuff's own files, or the JSON copy of its data. */\nexport type SaveFileKind = StuffFileKind | 'data';\n\ninterface SaveFileCommon {\n /**\n * What to save it as: a bare file name, never a path. The file's own\n * `filename` when it states one, else the base name and the file's place\n * below the result's root (`report-figures-0-image.png`), or the base name\n * alone for a file that is the whole result (`output.png`). No two files in\n * one plan share a name, compared without case.\n */\n name: string;\n /**\n * The media type. For a `data:` URL it is the type the gate admitted; for any\n * other URL it is what the payload states, or what the name's extension\n * implies, or `application/octet-stream` when nothing says.\n */\n mimeType: string;\n kind: SaveFileKind;\n /** Where it sat in the result, dotted (`output.figures.0.image`); the root's name for the JSON copy. */\n path: string;\n}\n\n/**\n * One file to hand to the reader: exactly one of `url` and `text` is set.\n *\n * `url` is the string the URL gate returned, after the host's resolver was\n * asked first, so a delivery never acts on a member nothing judged. It may be a\n * root-relative path, which a planner with no document cannot resolve; the\n * result view makes one absolute against its own document before a delivery\n * sees it. `text` is content the result carries inline.\n */\nexport type SaveFile =\n | (SaveFileCommon & { url: string; text?: undefined })\n | (SaveFileCommon & { text: string; url?: undefined });\n\n/** A file the result holds that cannot be saved, because no URL the gate admits was found for it. */\nexport interface UnavailableFile {\n /** What it would have been saved as, so the reader can be told which one. */\n name: string;\n kind: StuffFileKind;\n path: string;\n}\n\n/** Everything saving a whole result involves. */\nexport interface SavePlan {\n /** What to deliver, in the order the result shows it, the JSON copy last. */\n files: SaveFile[];\n /**\n * What the result holds and cannot be delivered. The JSON copy still carries\n * each one's reference, so the reader keeps it even without the bytes.\n */\n unavailable: UnavailableFile[];\n}\n\n/** A file a delivery did not hand over, and why when it knows. */\nexport interface SaveFailure {\n file: SaveFile;\n reason?: string;\n}\n\n/**\n * What a delivery reports. Every planned file not listed in `failed` was\n * delivered, so an empty list means everything went out.\n */\nexport interface SaveResult {\n failed: SaveFailure[];\n}\n\n/**\n * How files reach the reader. The default saves them in the browser; a host\n * whose view runs in a sandboxed frame supplies one that asks the host to.\n *\n * It resolves rather than rejects when a file does not go out, and names that\n * file in `failed`, so the control that asked can tell the reader. A throw or\n * a rejection is read as every file having failed.\n */\nexport type SaveFiles = (files: readonly SaveFile[]) => Promise<SaveResult>;\n\nexport interface SavePlanOptions {\n /**\n * Names the whole stuff: the JSON copy is `<baseName>.json`, a file with no\n * name of its own below the root is `<baseName>-<place>`, and a file that is\n * the whole stuff is `<baseName>.<ext>`.\n */\n baseName: string;\n /** The same resolver the result view paints through, asked before the payload's own URLs. */\n resolveUrl?: (url: string) => string | undefined;\n}\n\n/**\n * Everything a stuff contains, planned for saving.\n *\n * The data goes down as JSON, and any image, document or HTML page inside it\n * goes down as ITSELF: a JSON file holding a URL to a picture is not the\n * picture, and a reader who saves a report with three attachments wants the\n * three attachments.\n *\n * The JSON copy is planned whenever the stuff is anything more than one file. A\n * result that IS one image has nothing left over once the image is saved, so\n * `{\"url\": …}` beside it would be a second file saying less than the first. That\n * holds only when the image can be saved: a bare file the gate refuses leaves\n * the JSON copy as the one thing the reader gets, because it still carries the\n * reference.\n */\nexport function planStuffSave(field: RunField, value: unknown, options: SavePlanOptions): SavePlan {\n const found = collectStuffFiles(field, value);\n const files: SaveFile[] = [];\n const unavailable: UnavailableFile[] = [];\n for (const file of found) {\n const planned = planFileSave(file, options);\n if (planned) files.push(planned);\n else\n unavailable.push({ name: nameFor(file, options.baseName), kind: file.kind, path: file.path });\n }\n\n // A stuff that is nothing BUT one file, read from the collector rather than\n // from `field.kind`: a `native.Html` node's kind is `object`, and the whole\n // stuff is still the page.\n const isBareFile = found.length === 1 && found[0]?.path === field.name;\n if (isBareFile && files.length === 1) return { files, unavailable };\n\n const jsonName = `${safeName(options.baseName) || 'result'}.json`;\n return {\n files: [\n ...distinctNames(files, jsonName),\n {\n name: jsonName,\n mimeType: 'application/json',\n kind: 'data',\n path: field.name,\n text: jsonCopy(value),\n },\n ],\n unavailable,\n };\n}\n\n/**\n * The plan's files with no two sharing a name, and none taking the JSON copy's.\n *\n * A name derived from a file's place is unique by construction, but a name the\n * payload states is not: two documents a method wrote as `scan.pdf`, or one it\n * called `report.json` beside the JSON copy of `report`. A browser suffixes a\n * duplicate download itself, but a host's delivery may write the names as given,\n * into a folder or an archive, where the second file silently replaces the\n * first. So the first file keeps its name and each later one gets a number\n * before its extension (`scan-2.pdf`), compared without case, as the file\n * systems readers mostly use compare them.\n *\n * That is the whole plan's concern: a file's own button saves one file, which\n * collides with nothing, under its own name.\n */\nfunction distinctNames(files: readonly SaveFile[], reserved: string): SaveFile[] {\n const taken = new Set([reserved.toLowerCase()]);\n return files.map((file) => {\n let name = file.name;\n for (let count = 2; taken.has(name.toLowerCase()); count += 1) {\n name = numbered(file.name, count);\n }\n taken.add(name.toLowerCase());\n return name === file.name ? file : { ...file, name };\n });\n}\n\n/** `scan.pdf` as `scan-2.pdf`: the number before the extension, so the type still reads. */\nfunction numbered(name: string, count: number): string {\n const extension = extensionOf(name);\n return extension\n ? `${name.slice(0, -(extension.length + 1))}-${count}.${name.slice(-extension.length)}`\n : `${name}-${count}`;\n}\n\n/**\n * One file, planned on its own — what a file's own download button saves.\n *\n * The file's `path` starts at the root's name, as `collectStuffFiles` builds\n * it: the name leaves that first segment out, because the base name already\n * stands for the root.\n *\n * `undefined` when the file cannot be saved: a stored reference the host's\n * resolver does not answer and no URL the gate admits beside it. The button is\n * not drawn then, so a reader is never offered a download that cannot happen.\n */\nexport function planFileSave(file: StuffFile, options: SavePlanOptions): SaveFile | undefined {\n const common = { kind: file.kind, path: file.path };\n if (file.text !== undefined) {\n return {\n ...common,\n name: nameFor(file, options.baseName),\n mimeType: 'text/html',\n text: file.text,\n };\n }\n // Judged by the same gate the result view paints through, in the same\n // durability order: the host's resolver over the durable reference first,\n // then `public_url`, then the reference itself. What the gate returns is what\n // is planned, never the raw member.\n const url =\n viewableUrl(options.resolveUrl?.(file.url ?? '')) ??\n viewableUrl(file.publicUrl) ??\n viewableUrl(file.url);\n if (!url) return undefined;\n const encoded = readDataUrl(url);\n if (encoded) {\n // A `data:` URL is its own file, and the gate admitted it for its declared\n // type alone. That type names it: the payload's `filename` and the tail of\n // the payload are both the payload's say, and a `data:image/png` URL saved\n // under `image.html` is a page that runs when the reader opens it.\n return {\n ...common,\n name: nameFor(file, options.baseName, dataUrlExtensions(encoded.mediaType)),\n mimeType: encoded.mediaType,\n url,\n };\n }\n const name = nameFor(file, options.baseName);\n return { ...common, name, mimeType: file.mimeType ?? typeForName(name), url };\n}\n\n/** The type a name's extension implies, for a stored file whose payload states none. */\nconst TYPE_FOR_EXTENSION: Readonly<Record<string, string>> = {\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n avif: 'image/avif',\n svg: 'image/svg+xml',\n pdf: 'application/pdf',\n html: 'text/html',\n};\n\nfunction typeForName(name: string): string {\n const extension = name.match(/\\.([A-Za-z0-9]{1,8})$/)?.[1]?.toLowerCase();\n return (extension && TYPE_FOR_EXTENSION[extension]) || 'application/octet-stream';\n}\n\n/**\n * What a saved file is called.\n *\n * The file's own `filename` wins when it has one: it is the name the producer\n * chose and the reader recognises. Otherwise the base name and the file's place\n * below the root name it (`report-attachments-2`), which is unlovely but\n * unambiguous, since two images from one result must not both land as\n * `image.png` and overwrite each other in the download folder.\n *\n * The path's first segment is left out because it is always the root's name,\n * and the base name already stands for the root, as it does in `<base>.json`:\n * keeping it would save the one image a pipe outputs as `output-output.png`. A\n * file that IS the root has no place below it and is named by the base name\n * alone. Every segment is a field's name or an index, neither of which holds a\n * dot, so splitting on dots recovers them.\n *\n * `allowed` is set for a `data:` URL, whose admitted type is the only thing\n * allowed to decide the extension: a name carrying one of those extensions\n * keeps it, and any other extension is replaced by the type's own.\n */\nfunction nameFor(file: StuffFile, base: string, allowed?: readonly string[]): string {\n const own = file.filename ? safeName(file.filename) : '';\n const place = file.path.split('.').slice(1).join('-');\n const named = safeName(base) || 'result';\n const stem = own || (place ? `${named}-${place}` : named);\n const stated = own ? extensionOf(own) : '';\n if (allowed) {\n if (stated && allowed.includes(stated)) return stem;\n const bare = stated ? stem.slice(0, -(stated.length + 1)) : stem;\n const extension = allowed[0];\n return extension ? `${bare}.${extension}` : bare;\n }\n if (own) return own;\n const extension = file.extension ?? extensionOf(pathOf(file.url ?? ''));\n return extension ? `${stem}.${extension}` : stem;\n}\n\n/** The extension a name ends in, lowercased, or none. Never guessed from the bytes. */\nfunction extensionOf(name: string): string {\n return name.match(/\\.([A-Za-z0-9]{1,8})$/)?.[1]?.toLowerCase() ?? '';\n}\n\n/** A URL without its query and fragment, so `x.png?sig=…` still ends in `.png`. */\nfunction pathOf(url: string): string {\n return url.split(/[?#]/)[0] ?? url;\n}\n\n/**\n * A name safe to hand a delivery: its last path segment, without control\n * characters, trimmed. A browser sanitises a download name itself, but a host's\n * bridge may write it to disk as given, and a payload's `filename` is the\n * payload's say. Empty when nothing is left.\n */\nfunction safeName(name: string): string {\n const printable = Array.from(name)\n .filter((character) => {\n const code = character.charCodeAt(0);\n return code > 0x1f && code !== 0x7f;\n })\n .join('');\n const trimmed = (printable.split(/[/\\\\]/).pop() ?? '').trim();\n return trimmed === '.' || trimmed === '..' ? '' : trimmed;\n}\n\n/**\n * The data as JSON, the way the JSON view shows it. A BigInt, which a JSON\n * parser configured to produce one can hand over, is written as its digits\n * rather than failing the whole save.\n */\nfunction jsonCopy(value: unknown): string {\n const text = JSON.stringify(\n value,\n (_key, member: unknown) => (typeof member === 'bigint' ? member.toString() : member),\n 2,\n );\n return text ?? 'null';\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { planStuffSave, planFileSave } from './chunk-
|
|
2
|
-
import { readStuffFile } from './chunk-
|
|
1
|
+
import { planStuffSave, planFileSave } from './chunk-7KQXGG6J.js';
|
|
2
|
+
import { readStuffFile } from './chunk-RRTI7AIR.js';
|
|
3
3
|
import { viewableUrl, isNativeDateNode, isNativeHtmlNode, readHtmlContent, isNativeCompositeNode, readCompositeContent, isNativeValueNode, readDateContent, formatDateContent, readImageContent, readDataUrl, readDocumentContent } from './chunk-CM4KVG53.js';
|
|
4
4
|
import { conceptCategory } from './chunk-FABY3DEY.js';
|
|
5
5
|
import { acceptLabel, acceptMap, isAcceptedFile, formatOfFilename, DOCUMENT_FORMATS, IMAGE_FORMATS } from './chunk-XCO6GTEC.js';
|
|
6
|
-
import { isFilled } from './chunk-
|
|
6
|
+
import { shownAsOptional, isFilled } from './chunk-MJQ7CXUB.js';
|
|
7
7
|
import { toStoredDateValue, toDateInputValue } from './chunk-GKV77RAS.js';
|
|
8
8
|
import { ownProp } from './chunk-V3OV2XQT.js';
|
|
9
9
|
import { clsx } from 'clsx';
|
|
@@ -181,12 +181,14 @@ function BooleanField({ field, value, onChange, id, disabled }) {
|
|
|
181
181
|
}
|
|
182
182
|
);
|
|
183
183
|
}
|
|
184
|
+
|
|
185
|
+
// src/react/locales/en.ts
|
|
184
186
|
function formatBytes(bytes) {
|
|
185
187
|
if (bytes < 1024) return bytes === 1 ? "1 byte" : `${bytes} bytes`;
|
|
186
188
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
187
189
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
188
190
|
}
|
|
189
|
-
var
|
|
191
|
+
var EN_FIELD_STRINGS = {
|
|
190
192
|
optionalBadge: "optional",
|
|
191
193
|
selectPlaceholder: "Select\u2026",
|
|
192
194
|
typeValuePlaceholder: "Type a value\u2026",
|
|
@@ -237,12 +239,100 @@ var DEFAULT_FIELD_STRINGS = {
|
|
|
237
239
|
optionalFieldsCount: (count) => count === 1 ? "1 optional field" : `${count} optional fields`,
|
|
238
240
|
optionalInputsCount: (count) => count === 1 ? "1 optional input" : `${count} optional inputs`
|
|
239
241
|
};
|
|
242
|
+
|
|
243
|
+
// src/react/locales/fr.ts
|
|
244
|
+
var PLURALS = new Intl.PluralRules("fr");
|
|
245
|
+
var BYTES = new Intl.NumberFormat("fr-FR", { style: "unit", unit: "byte", unitDisplay: "long" });
|
|
246
|
+
var KILOBYTES = new Intl.NumberFormat("fr-FR", {
|
|
247
|
+
style: "unit",
|
|
248
|
+
unit: "kilobyte",
|
|
249
|
+
unitDisplay: "short",
|
|
250
|
+
maximumFractionDigits: 0
|
|
251
|
+
});
|
|
252
|
+
var MEGABYTES = new Intl.NumberFormat("fr-FR", {
|
|
253
|
+
style: "unit",
|
|
254
|
+
unit: "megabyte",
|
|
255
|
+
unitDisplay: "short",
|
|
256
|
+
maximumFractionDigits: 1
|
|
257
|
+
});
|
|
258
|
+
function plural(count, one, other) {
|
|
259
|
+
return PLURALS.select(count) === "one" ? one : other;
|
|
260
|
+
}
|
|
261
|
+
function formatBytes2(bytes) {
|
|
262
|
+
if (bytes < 1024) return BYTES.format(bytes);
|
|
263
|
+
if (bytes < 1024 * 1024) return KILOBYTES.format(bytes / 1024);
|
|
264
|
+
return MEGABYTES.format(bytes / (1024 * 1024));
|
|
265
|
+
}
|
|
266
|
+
var FR_FIELD_STRINGS = {
|
|
267
|
+
optionalBadge: "facultatif",
|
|
268
|
+
selectPlaceholder: "Choisir\u2026",
|
|
269
|
+
typeValuePlaceholder: "Saisissez une valeur\u2026",
|
|
270
|
+
writeHerePlaceholder: "\xC9crivez ici\u2026",
|
|
271
|
+
jsonHint: "Saisissez cette valeur en JSON brut.",
|
|
272
|
+
decrease: "Diminuer",
|
|
273
|
+
increase: "Augmenter",
|
|
274
|
+
noItemsYet: "Aucun \xE9l\xE9ment pour le moment",
|
|
275
|
+
addItem: "Ajouter un \xE9l\xE9ment",
|
|
276
|
+
removeItemAria: (index) => `Supprimer l\u2019\xE9l\xE9ment ${index}`,
|
|
277
|
+
itemsCount: (count) => `${count} ${plural(count, "\xE9l\xE9ment", "\xE9l\xE9ments")}`,
|
|
278
|
+
itemsCountOf: (count, total) => `${count} sur ${total} ${plural(total, "\xE9l\xE9ment", "\xE9l\xE9ments")}`,
|
|
279
|
+
fieldsCount: (count) => `${count} ${plural(count, "champ", "champs")}`,
|
|
280
|
+
uploading: "Envoi en cours\u2026",
|
|
281
|
+
dropToUpload: "D\xE9posez pour envoyer",
|
|
282
|
+
dropOrBrowse: "D\xE9posez un fichier ou cliquez pour parcourir",
|
|
283
|
+
pasteUrlInstead: "coller un lien \xE0 la place",
|
|
284
|
+
uploadUnavailable: "Impossible d\u2019envoyer un fichier ici. Collez plut\xF4t un lien vers le fichier.",
|
|
285
|
+
urlPlaceholder: "https://\u2026",
|
|
286
|
+
fileUrlAria: (label) => label ? `Lien vers le fichier pour ${label}` : "Lien vers le fichier",
|
|
287
|
+
uploadedFile: "Fichier joint",
|
|
288
|
+
encodedFileSummary: (format, bytes) => `${format} \xB7 ${formatBytes2(bytes)}`,
|
|
289
|
+
preview: "Aper\xE7u",
|
|
290
|
+
removeFileAria: "Retirer le fichier",
|
|
291
|
+
previewUnavailablePdf: "Aper\xE7u indisponible - ouvrez le fichier pour le consulter.",
|
|
292
|
+
// U+002D HYPHEN-MINUS, as in the English defaults.
|
|
293
|
+
resultAbsent: "-",
|
|
294
|
+
resultAbsentDescription: "Non renseign\xE9",
|
|
295
|
+
resultUndescribed: "Aucun descripteur de sortie pour ce pipe \u2014 affichage de la valeur brute.",
|
|
296
|
+
toggleRowDetails: (index) => `Afficher ou masquer le d\xE9tail de la ligne ${index}`,
|
|
297
|
+
rowDetailsColumn: "D\xE9tail",
|
|
298
|
+
copyUrl: "Copier le lien",
|
|
299
|
+
copyText: "Copier le texte",
|
|
300
|
+
download: "T\xE9l\xE9charger",
|
|
301
|
+
downloading: "T\xE9l\xE9chargement\u2026",
|
|
302
|
+
downloadIncomplete: (names) => `${names.length <= 1 ? "Un fichier n\u2019a pas pu \xEAtre enregistr\xE9" : `${names.length} fichiers n\u2019ont pas pu \xEAtre enregistr\xE9s`}\xA0: ${names.join(", ")}`,
|
|
303
|
+
downloadFile: (name) => `T\xE9l\xE9charger ${name}`,
|
|
304
|
+
downloadFileFailed: "Le fichier n\u2019a pas pu \xEAtre enregistr\xE9",
|
|
305
|
+
viewRendered: "R\xE9sultat",
|
|
306
|
+
viewJson: "JSON",
|
|
307
|
+
copyJson: "Copier le JSON",
|
|
308
|
+
resultViewGroup: "Affichage du r\xE9sultat",
|
|
309
|
+
yes: "Oui",
|
|
310
|
+
no: "Non",
|
|
311
|
+
unsupportedFileType: (formats) => `Ce type de fichier n\u2019est pas pris en charge. Formats accept\xE9s\xA0: ${formats}.`,
|
|
312
|
+
hideOptionalFields: "Masquer les champs facultatifs",
|
|
313
|
+
hideOptionalInputs: "Masquer les entr\xE9es facultatives",
|
|
314
|
+
optionalFieldsCount: (count) => `${count} ${plural(count, "champ facultatif", "champs facultatifs")}`,
|
|
315
|
+
optionalInputsCount: (count) => `${count} ${plural(count, "entr\xE9e facultative", "entr\xE9es facultatives")}`
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// src/react/locales/index.ts
|
|
319
|
+
var FIELD_STRINGS_BY_LOCALE = {
|
|
320
|
+
en: EN_FIELD_STRINGS,
|
|
321
|
+
fr: FR_FIELD_STRINGS
|
|
322
|
+
};
|
|
323
|
+
var SUPPORTED_LOCALES = Object.keys(FIELD_STRINGS_BY_LOCALE);
|
|
324
|
+
function fieldStringsFor(locale) {
|
|
325
|
+
const language = (locale ?? "").trim().toLowerCase().split(/[-_]/)[0] ?? "";
|
|
326
|
+
return FIELD_STRINGS_BY_LOCALE[language] ?? EN_FIELD_STRINGS;
|
|
327
|
+
}
|
|
328
|
+
var DEFAULT_FIELD_STRINGS = EN_FIELD_STRINGS;
|
|
240
329
|
var FieldStringsContext = createContext(DEFAULT_FIELD_STRINGS);
|
|
241
330
|
function FieldStringsProvider({
|
|
331
|
+
locale,
|
|
242
332
|
strings,
|
|
243
333
|
children
|
|
244
334
|
}) {
|
|
245
|
-
const merged = useMemo(() => ({ ...
|
|
335
|
+
const merged = useMemo(() => ({ ...fieldStringsFor(locale), ...strings }), [locale, strings]);
|
|
246
336
|
return /* @__PURE__ */ jsx(FieldStringsContext.Provider, { value: merged, children });
|
|
247
337
|
}
|
|
248
338
|
function useFieldStrings() {
|
|
@@ -315,7 +405,7 @@ function DateField({ field, value, onChange, id, error, disabled }) {
|
|
|
315
405
|
conceptRef: field.conceptRef,
|
|
316
406
|
category: "date",
|
|
317
407
|
description: field.description,
|
|
318
|
-
required: field
|
|
408
|
+
required: !shownAsOptional(field),
|
|
319
409
|
error,
|
|
320
410
|
htmlFor: domId,
|
|
321
411
|
children: /* @__PURE__ */ jsx(
|
|
@@ -511,7 +601,7 @@ function FileField({
|
|
|
511
601
|
conceptRef: field.conceptRef,
|
|
512
602
|
category,
|
|
513
603
|
description: field.description,
|
|
514
|
-
required: field
|
|
604
|
+
required: !shownAsOptional(field),
|
|
515
605
|
error,
|
|
516
606
|
htmlFor: domId,
|
|
517
607
|
children: [
|
|
@@ -903,7 +993,7 @@ function EnumField({ field, value, onChange, id, error, disabled }) {
|
|
|
903
993
|
conceptRef: field.conceptRef,
|
|
904
994
|
category: "choice",
|
|
905
995
|
description: field.description,
|
|
906
|
-
required: field
|
|
996
|
+
required: !shownAsOptional(field),
|
|
907
997
|
error,
|
|
908
998
|
htmlFor: isSegmented ? void 0 : domId,
|
|
909
999
|
children: isSegmented ? (
|
|
@@ -972,7 +1062,7 @@ function NumberField({ field, value, onChange, id, error, disabled }) {
|
|
|
972
1062
|
conceptRef: field.conceptRef,
|
|
973
1063
|
category: "number",
|
|
974
1064
|
description: field.description ?? rangeHint,
|
|
975
|
-
required: field
|
|
1065
|
+
required: !shownAsOptional(field),
|
|
976
1066
|
error,
|
|
977
1067
|
htmlFor: domId,
|
|
978
1068
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-stretch gap-1.5", children: [
|
|
@@ -1034,7 +1124,7 @@ function TextField({ field, value, onChange, id, error, disabled }) {
|
|
|
1034
1124
|
conceptRef: field.conceptRef,
|
|
1035
1125
|
category: "text",
|
|
1036
1126
|
description: field.description,
|
|
1037
|
-
required: field
|
|
1127
|
+
required: !shownAsOptional(field),
|
|
1038
1128
|
error,
|
|
1039
1129
|
htmlFor: domId,
|
|
1040
1130
|
children: /* @__PURE__ */ jsx(
|
|
@@ -1064,7 +1154,7 @@ function ProseField({ field, value, onChange, id, error, disabled }) {
|
|
|
1064
1154
|
conceptRef: field.conceptRef,
|
|
1065
1155
|
category: "text",
|
|
1066
1156
|
description: field.description,
|
|
1067
|
-
required: field
|
|
1157
|
+
required: !shownAsOptional(field),
|
|
1068
1158
|
error,
|
|
1069
1159
|
htmlFor: domId,
|
|
1070
1160
|
children: /* @__PURE__ */ jsx(
|
|
@@ -1108,8 +1198,10 @@ function ObjectField({ field, value, onChange, id, error, env }) {
|
|
|
1108
1198
|
const isApp = presentation === "app";
|
|
1109
1199
|
const data = value ?? {};
|
|
1110
1200
|
const setChild = (name, childValue) => onChange({ ...data, [name]: childValue });
|
|
1111
|
-
const optionalEmpty = field.fields.filter(
|
|
1112
|
-
|
|
1201
|
+
const optionalEmpty = field.fields.filter(
|
|
1202
|
+
(f) => shownAsOptional(f) && !isFilled(ownProp(data, f.name))
|
|
1203
|
+
);
|
|
1204
|
+
const visible = showOptional ? field.fields : field.fields.filter((f) => !shownAsOptional(f) || isFilled(ownProp(data, f.name)));
|
|
1113
1205
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1114
1206
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
|
|
1115
1207
|
/* @__PURE__ */ jsx(
|
|
@@ -1123,7 +1215,7 @@ function ObjectField({ field, value, onChange, id, error, env }) {
|
|
|
1123
1215
|
}
|
|
1124
1216
|
),
|
|
1125
1217
|
!isApp && /* @__PURE__ */ jsx(ConceptPill, { conceptRef: field.conceptRef, category: "structured" }),
|
|
1126
|
-
|
|
1218
|
+
shownAsOptional(field) && /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-[10px] uppercase tracking-wider text-muted-foreground", children: s.optionalBadge })
|
|
1127
1219
|
] }),
|
|
1128
1220
|
field.description && /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-relaxed text-muted-foreground", children: field.description }),
|
|
1129
1221
|
/* @__PURE__ */ jsxs(
|
|
@@ -1223,7 +1315,7 @@ function ListField({ field, value, onChange, id, error, env }) {
|
|
|
1223
1315
|
),
|
|
1224
1316
|
!isApp && /* @__PURE__ */ jsx(ConceptPill, { conceptRef: field.conceptRef, category: "list" }),
|
|
1225
1317
|
/* @__PURE__ */ jsx("span", { className: "font-mono text-[10.5px] text-muted-foreground", children: field.itemCount !== void 0 && field.maxItemCount === field.itemCount ? s.itemsCountOf(items.length, field.itemCount) : s.itemsCount(items.length) }),
|
|
1226
|
-
|
|
1318
|
+
shownAsOptional(field) && /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-[10px] uppercase tracking-wider text-muted-foreground", children: s.optionalBadge })
|
|
1227
1319
|
] }),
|
|
1228
1320
|
field.description && /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-relaxed text-muted-foreground", children: field.description }),
|
|
1229
1321
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
@@ -1341,7 +1433,7 @@ function UnknownField({ field, value, onChange, id, error, disabled }) {
|
|
|
1341
1433
|
conceptRef: field.conceptRef,
|
|
1342
1434
|
category: "structured",
|
|
1343
1435
|
description: field.description ?? s.jsonHint,
|
|
1344
|
-
required: field
|
|
1436
|
+
required: !shownAsOptional(field),
|
|
1345
1437
|
error,
|
|
1346
1438
|
htmlFor: domId,
|
|
1347
1439
|
children: /* @__PURE__ */ jsx(
|
|
@@ -2243,9 +2335,9 @@ function FileDownloadButton({ file }) {
|
|
|
2243
2335
|
);
|
|
2244
2336
|
return () => window.clearTimeout(timer);
|
|
2245
2337
|
}, [attempt]);
|
|
2246
|
-
if (!shown) return null;
|
|
2338
|
+
if (!shown || !location) return null;
|
|
2247
2339
|
const planned = planFileSave(file, {
|
|
2248
|
-
baseName: location
|
|
2340
|
+
baseName: location.baseName,
|
|
2249
2341
|
...resolve ? { resolveUrl: resolve } : {}
|
|
2250
2342
|
});
|
|
2251
2343
|
if (!planned) return null;
|
|
@@ -3127,6 +3219,6 @@ function StuffPanel({
|
|
|
3127
3219
|
] });
|
|
3128
3220
|
}
|
|
3129
3221
|
|
|
3130
|
-
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EnumField, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, HtmlPreview, ImageField, JsonView, ListField, Markdown, NumberField, ObjectField, OptionalToggle, ProseField, ResultEnvProvider, ResultField, ResultRoot, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StuffViewer, Switch, TextField, ToggleGroup, ToggleGroupItem, UnknownField, cn, fieldControlClass, humanizeFieldName, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
|
|
3131
|
-
//# sourceMappingURL=chunk-
|
|
3132
|
-
//# sourceMappingURL=chunk-
|
|
3222
|
+
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EN_FIELD_STRINGS, EnumField, FIELD_STRINGS_BY_LOCALE, FR_FIELD_STRINGS, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, HtmlPreview, ImageField, JsonView, ListField, Markdown, NumberField, ObjectField, OptionalToggle, ProseField, ResultEnvProvider, ResultField, ResultRoot, SUPPORTED_LOCALES, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StuffViewer, Switch, TextField, ToggleGroup, ToggleGroupItem, UnknownField, cn, fieldControlClass, fieldStringsFor, humanizeFieldName, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
|
|
3223
|
+
//# sourceMappingURL=chunk-D2EQVWGN.js.map
|
|
3224
|
+
//# sourceMappingURL=chunk-D2EQVWGN.js.map
|