@evotecit/canopyx 0.2.2 → 0.3.3

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.
Files changed (34) hide show
  1. package/CanopyX.Html/Assets/canopyx-editing.css +1 -6
  2. package/CanopyX.Html/Assets/canopyx-editing.js +4 -39
  3. package/CanopyX.Html/Assets/canopyx-export.js +2 -2
  4. package/CanopyX.Html/Assets/canopyx-flow-entry.css +178 -0
  5. package/CanopyX.Html/Assets/canopyx-flow-entry.js +78 -0
  6. package/CanopyX.Html/Assets/canopyx-flow-module.mjs +80 -0
  7. package/CanopyX.Html/Assets/canopyx-flow.css +180 -0
  8. package/CanopyX.Html/Assets/canopyx-flow.js +214 -0
  9. package/CanopyX.Html/Assets/canopyx-forms.css +8 -0
  10. package/CanopyX.Html/Assets/canopyx-forms.js +39 -0
  11. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +18 -14
  12. package/CanopyX.Html/Assets/canopyx-grid.css +2 -0
  13. package/CanopyX.Html/Assets/canopyx-grid.js +18 -14
  14. package/CanopyX.Html/Assets/canopyx-interactive.js +10 -9
  15. package/CanopyX.Html/Assets/canopyx-labels-de.js +72 -0
  16. package/CanopyX.Html/Assets/canopyx-labels-es.js +72 -0
  17. package/CanopyX.Html/Assets/canopyx-labels-fr.js +72 -0
  18. package/CanopyX.Html/Assets/canopyx-labels-it.js +72 -0
  19. package/CanopyX.Html/Assets/canopyx-labels-pl.js +72 -0
  20. package/CanopyX.Html/Assets/canopyx-module.mjs +10 -9
  21. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +18 -14
  22. package/CanopyX.Html/Assets/canopyx-reporting.css +2 -0
  23. package/CanopyX.Html/Assets/canopyx-reporting.js +18 -14
  24. package/CanopyX.Html/Assets/canopyx.js +10 -9
  25. package/JavaScript/flow.d.ts +232 -0
  26. package/JavaScript/grid.d.ts +8 -5
  27. package/JavaScript/hosts.d.ts +3 -1
  28. package/JavaScript/locales/de.mjs +72 -0
  29. package/JavaScript/locales/es.mjs +72 -0
  30. package/JavaScript/locales/fr.mjs +72 -0
  31. package/JavaScript/locales/it.mjs +72 -0
  32. package/JavaScript/locales/pl.mjs +72 -0
  33. package/README.md +3 -2
  34. package/package.json +20 -1
@@ -0,0 +1,232 @@
1
+ // Flows (docs/flow.md): guided forms with steps, typed fields, conditions as data, validation, a review page and one
2
+ // proposal to the host. The flow entry point (@evotecit/canopyx/flow) and the grid entry points create them.
3
+ import type { CanopyPlugin } from "./plugins.js";
4
+
5
+ /** A value a field holds: text, a number, a boolean, a list of values, or nothing. Secrets never have one. */
6
+ export type FlowValue = string | number | boolean | null | readonly (string | number | boolean)[];
7
+
8
+ /** The field types: the shared grid editors, the types flows add, and custom editors. */
9
+ export type FlowFieldType = "text" | "number" | "date" | "datetime" | "time" | "select" | "toggle" | "lookup" | "choice" | "multiChoice"
10
+ | "textarea" | "list" | "secret" | "duration" | "custom";
11
+
12
+ /** A condition operator, from the filter builder's grammar. */
13
+ export type FlowOperator = "eq" | "ne" | "gt" | "ge" | "lt" | "le" | "contains" | "notContains" | "startsWith" | "endsWith" | "matches" | "notMatches"
14
+ | "in" | "notIn" | "between" | "isNull" | "isNotNull";
15
+
16
+ /** A condition as data: groups of predicates joined by and, or and none. At most eight levels, 64 groups and 64 predicates. */
17
+ export interface FlowCondition {
18
+ operator: "and" | "or" | "none";
19
+ filters?: readonly { field: string; operator: FlowOperator; values?: readonly (string | number | boolean)[] }[];
20
+ groups?: readonly FlowCondition[];
21
+ }
22
+
23
+ /** A choice: a value, and how readers see it. */
24
+ export interface FlowOption {
25
+ value: string | number | boolean;
26
+ label?: string;
27
+ description?: string;
28
+ badge?: string;
29
+ /** Shown beside a choice that cannot be picked. */
30
+ disabledReason?: string;
31
+ /** Multiple choice: the heading the option sits under. */
32
+ group?: string;
33
+ }
34
+
35
+ /** A field's checks: lengths and patterns for text, ranges for numbers, moments and durations, counts and item rules for lists. */
36
+ export interface FlowValidation {
37
+ min?: number | string;
38
+ max?: number | string;
39
+ minLength?: number;
40
+ maxLength?: number;
41
+ pattern?: string;
42
+ message?: string;
43
+ minItems?: number;
44
+ maxItems?: number;
45
+ item?: "email" | "host" | "ip" | "cidr" | "url";
46
+ itemPattern?: string;
47
+ }
48
+
49
+ /** A field of a flow step. */
50
+ export interface FlowField {
51
+ id: string;
52
+ type: FlowFieldType;
53
+ label: string;
54
+ help?: string;
55
+ placeholder?: string;
56
+ required?: boolean;
57
+ readOnly?: boolean;
58
+ default?: FlowValue;
59
+ when?: FlowCondition;
60
+ width?: "full" | "half";
61
+ parameter?: string;
62
+ /** The setting it writes, as dot-separated names; the host prepares parent objects before applying the JSON patch. */
63
+ path?: string;
64
+ sensitive?: boolean;
65
+ validation?: FlowValidation;
66
+ options?: readonly FlowOption[];
67
+ /** Choice fields: cards (default up to five options) or a list. */
68
+ display?: "cards" | "list";
69
+ onText?: string;
70
+ offText?: string;
71
+ rows?: number;
72
+ step?: number;
73
+ /** Secrets: a blank answer keeps the stored value. */
74
+ keepWhenBlank?: boolean;
75
+ /** Secrets: false hides the reveal button. */
76
+ reveal?: boolean;
77
+ units?: readonly ("seconds" | "minutes" | "hours" | "days")[];
78
+ /** Custom fields: the registered editor's name. */
79
+ editor?: string;
80
+ }
81
+
82
+ /** A section of a step: a heading over some of its fields. */
83
+ export interface FlowSection { id: string; label: string; description?: string; fields: readonly FlowField[]; when?: FlowCondition }
84
+
85
+ /** A step: a form, a page of text, or the review page (which comes last). */
86
+ export interface FlowStep {
87
+ id: string;
88
+ title?: string;
89
+ description?: string;
90
+ type?: "form" | "info" | "review";
91
+ fields?: readonly FlowField[];
92
+ sections?: readonly FlowSection[];
93
+ when?: FlowCondition;
94
+ optional?: boolean;
95
+ /** Review steps: the text above the submit button. */
96
+ declaration?: string;
97
+ /** Review steps in edit mode: whether only changed answers show first (default true). */
98
+ changesOnly?: boolean;
99
+ }
100
+
101
+ /** A flow document, the contract C# writes with CanopyFlow and any host can map. */
102
+ export interface FlowDocument {
103
+ kind: "flow";
104
+ version: 1;
105
+ id: string;
106
+ title: string;
107
+ description?: string;
108
+ mode?: "linear" | "free";
109
+ layout?: { orientation?: "auto" | "horizontal" | "vertical" };
110
+ density?: "compact" | "normal" | "comfortable";
111
+ timeZone?: "utc" | "local";
112
+ steps: readonly FlowStep[];
113
+ /** Edit mode: the values the flow edits. */
114
+ initial?: Readonly<Record<string, FlowValue>>;
115
+ /** Edit mode: the secret fields that already have a stored value. */
116
+ storedSecrets?: readonly string[];
117
+ baseline?: string;
118
+ submit?: { label?: string };
119
+ labels?: Readonly<Record<string, string>>;
120
+ }
121
+
122
+ /** The proposal flowSubmit carries: visible answers, secret states, the changes and a JSON patch. Never a secret value. */
123
+ export interface FlowSubmission {
124
+ kind: "flowSubmission";
125
+ flow: string;
126
+ version: 1;
127
+ mode: "create" | "edit";
128
+ baseline?: string;
129
+ values: Record<string, FlowValue>;
130
+ secrets: Record<string, { state: "set" | "keep" }>;
131
+ changes: { field: string; path?: string; from: FlowValue; to: FlowValue }[];
132
+ patch: ({ op: "add" | "replace"; path: string; value: FlowValue } | { op: "remove"; path: string })[];
133
+ }
134
+
135
+ /** The submit event's detail: the proposal, how to answer it, and each secret once. */
136
+ export interface FlowSubmitDetail extends Readonly<FlowSubmission> {
137
+ respondWith(answer: FlowAnswer | Promise<FlowAnswer>): void;
138
+ /** A secret's value, once per field, until the answer settles; null afterwards. */
139
+ secret(fieldId: string): string | null;
140
+ }
141
+
142
+ /** The host's answer to a proposal. */
143
+ export interface FlowAnswer {
144
+ status: "saved" | "accepted" | "error" | "conflict";
145
+ message?: string;
146
+ fieldErrors?: Record<string, string>;
147
+ stepErrors?: Record<string, string>;
148
+ /** Saved: rows the result panel shows; once rows get Copy and leave the page with the panel. */
149
+ result?: { label: string; value: string | number | boolean; once?: boolean }[];
150
+ links?: { label: string; href: string }[];
151
+ }
152
+
153
+ /** What a step or flow rule answers: a message, or buckets of messages. */
154
+ export type FlowRuleResult = string | null | undefined | { errors?: string[]; warnings?: string[]; fieldErrors?: Record<string, string> };
155
+
156
+ /** The host's hooks; each runs isolated, and a failure becomes a message in place and an error event. */
157
+ export interface FlowHooks {
158
+ validators?: Record<string, (value: FlowValue, values: Record<string, FlowValue>) => string | null | undefined | Promise<string | null | undefined>>;
159
+ validateStep?(stepId: string, values: Record<string, FlowValue>): FlowRuleResult | Promise<FlowRuleResult>;
160
+ validateFlow?(values: Record<string, FlowValue>): FlowRuleResult | Promise<FlowRuleResult>;
161
+ submit?(detail: FlowSubmitDetail): FlowAnswer | Promise<FlowAnswer>;
162
+ }
163
+
164
+ /** Options of createFlow and CanopyX.configure for a flow fragment. */
165
+ export interface FlowOptions {
166
+ flow: FlowDocument;
167
+ /** Starting answers on top of the defaults or the edited values. */
168
+ values?: Record<string, FlowValue>;
169
+ labels?: Record<string, string>;
170
+ hooks?: FlowHooks;
171
+ /** Editors for custom fields, as grid editing's (docs/editing.md#custom-editors). */
172
+ editors?: CanopyPlugin["editors"];
173
+ onReady?(detail: { flow: string; step: string }): void;
174
+ onStepChange?(detail: { from: string; to: string }): void;
175
+ onValueChange?(detail: { field: string; value?: FlowValue; previous?: FlowValue; source: string }): void;
176
+ onSubmit?(detail: FlowSubmitDetail): FlowAnswer | Promise<FlowAnswer> | void;
177
+ onSubmitted?(answer: FlowAnswer): void;
178
+ onReload?(detail: { baseline: string | null }): void;
179
+ }
180
+
181
+ /** A validation result: the errors and warnings of a step or the whole flow. */
182
+ export interface FlowValidationResult {
183
+ valid: boolean;
184
+ errors: { field?: string; step?: string; message: string }[];
185
+ warnings: { step?: string; message: string }[];
186
+ }
187
+
188
+ /** A flow's state: the current step, the answers (never secrets) and the completed steps. */
189
+ export interface FlowState { step: string; values: Record<string, FlowValue>; completed: string[] }
190
+
191
+ /**
192
+ * The flow's API. Async methods wait for ready; synchronous methods throw a not-ready error until the implementation loads.
193
+ * After destroy, synchronous calls throw a destroyed error and async calls reject with it. Calls still waiting for ready also reject.
194
+ */
195
+ export interface FlowApi {
196
+ readonly element: HTMLElement;
197
+ readonly flow: FlowDocument;
198
+ /** Resolves after the first step is painted; rejects on mount failure or destruction before readiness. */
199
+ readonly ready: Promise<FlowApi>;
200
+ next(): Promise<boolean>;
201
+ back(): Promise<boolean>;
202
+ goTo(stepId: string): Promise<boolean>;
203
+ getStep(): string;
204
+ getValues(): Record<string, FlowValue>;
205
+ setValues(values: Record<string, FlowValue>): void;
206
+ getState(): FlowState;
207
+ setState(state: Partial<FlowState>): Promise<boolean>;
208
+ isDirty(): boolean;
209
+ reset(): boolean;
210
+ validate(stepId?: string): Promise<FlowValidationResult>;
211
+ setFieldError(fieldId: string, message: string | null): void;
212
+ submit(): Promise<FlowAnswer | null>;
213
+ setProgress(progress: { done?: number; total?: number; message?: string }): boolean;
214
+ complete(answer: FlowAnswer): boolean;
215
+ /** Releases the flow and its host's mount state, even before ready or after mount failure. Repeated calls do nothing. */
216
+ destroy(): void;
217
+ }
218
+
219
+ /** Creates a flow in a host element; the forms and flow parts load on first use. */
220
+ export declare function createFlow(host: HTMLElement, options: FlowOptions): FlowApi;
221
+ /** Registers options for a flow fragment before it mounts; returns a disposer. */
222
+ export declare function configure(flowId: string, options: Partial<Omit<FlowOptions, "flow">>): () => void;
223
+ export declare function unconfigure(flowId: string): boolean;
224
+ /** Mounts the flow fragments under root, or root itself. */
225
+ export declare function mount(root?: ParentNode): FlowApi[];
226
+ /** Registers a plugin's editors for the flows created afterwards; returns a disposer. */
227
+ export declare function use(plugin: Pick<CanopyPlugin, "name" | "editors">): () => void;
228
+ export declare function registerPart(name: string, part: { version: string; requires?: string[]; install(context: object): void }): void;
229
+ export declare function setNonce(nonce: string): void;
230
+ declare const CanopyX: { createFlow: typeof createFlow; configure: typeof configure; unconfigure: typeof unconfigure; mount: typeof mount;
231
+ use: typeof use; registerPart: typeof registerPart; setNonce: typeof setNonce };
232
+ export default CanopyX;
@@ -931,14 +931,17 @@ export function createDataGrid<Row extends GridRow = GridRow>(host: HTMLElement,
931
931
  export function createDataGrid<Row extends GridRow = GridRow>(host: HTMLElement, options: CursorGridOptions<GridNamedRow<Row>>): DataGrid<GridCursorQuery, Row>;
932
932
  /** A calendar from a list of events, with no grid schema to write: a preset (basic by default) and options over it (calendar.d.ts). */
933
933
  export function createCalendar(host: HTMLElement, options?: CalendarOptions): DataGrid<GridQuery, GridRow>;
934
- /** Registers options before either a tree or flat-grid fragment mounts. */
935
- export function configure(viewId: string, options: HostOptions | GridHostOptions | GridHostOptions<GridCursorQuery>): () => void;
934
+ /** Registers options before a tree, flat-grid or flow fragment mounts. */
935
+ export function configure(viewId: string, options: HostOptions | GridHostOptions | GridHostOptions<GridCursorQuery> | Partial<Omit<FlowOptions, "flow">>): () => void;
936
936
  /**
937
- * Mounts tree and flat-grid fragments below root, or root itself when it is a fragment. Fragments marked
937
+ * Mounts tree, flat-grid and flow fragments below root, or root itself when it is a fragment. Fragments marked
938
938
  * `data-cx-mount="visible"` below root wait until they come near the viewport; passing such a fragment as root mounts it at once.
939
939
  * Narrow a controller before using view-specific methods.
940
940
  */
941
- export function mount(root?: ParentNode): Array<TreeGrid | DataGrid<AcceptedGridQuery>>;
941
+ export function mount(root?: ParentNode): Array<TreeGrid | DataGrid<AcceptedGridQuery> | FlowApi>;
942
942
 
943
- declare const gridRuntime: Omit<typeof CanopyX, "configure" | "mount"> & { createDataGrid: typeof createDataGrid; createCalendar: typeof createCalendar; enhance: typeof enhance; grid: typeof grid; configure: typeof configure; mount: typeof mount };
943
+ import type { createFlow, FlowApi, FlowOptions } from "./flow.js";
944
+ export { createFlow } from "./flow.js";
945
+ export type { FlowDocument, FlowField, FlowStep, FlowSection, FlowOption, FlowCondition, FlowValidation, FlowValue, FlowSubmission, FlowSubmitDetail, FlowAnswer, FlowHooks, FlowOptions, FlowApi, FlowState, FlowValidationResult } from "./flow.js";
946
+ declare const gridRuntime: Omit<typeof CanopyX, "configure" | "mount"> & { createDataGrid: typeof createDataGrid; createCalendar: typeof createCalendar; createFlow: typeof createFlow; enhance: typeof enhance; grid: typeof grid; configure: typeof configure; mount: typeof mount };
944
947
  export default gridRuntime;
@@ -102,6 +102,8 @@ export interface ExportFormat<C extends ExportCapture = ExportCapture> {
102
102
  readonly extension: string;
103
103
  /** The Blob type for bytes a writer returns; default application/octet-stream. */
104
104
  readonly mime?: string;
105
+ /** False omits this writer from the Export menu; exportAs still runs it. Default true. */
106
+ readonly showInMenu?: boolean;
105
107
  /** Returns the file: a Blob (a File names the download itself), or bytes typed with mime. */
106
108
  write(capture: C, context: ExportFormatContext): Blob | ArrayBuffer | ArrayBufferView | PromiseLike<Blob | ArrayBuffer | ArrayBufferView>;
107
109
  }
@@ -281,4 +283,4 @@ export interface LinkedView {
281
283
  getHighlight(): string[];
282
284
  /** Starts canopyx:linkchange on a view created without linkEvents (for hosts that link views after they mount). */
283
285
  startLinkEvents(): Promise<void>;
284
- }
286
+ }
@@ -516,6 +516,78 @@ const labels = Object.freeze({
516
516
  calendarOutsideRange: "Außerhalb des Zeitraums dieses Kalenders",
517
517
  calendarClose: "Schließen",
518
518
  calendarDetailsOf: "Details zu {title}",
519
+ flowSteps: "Schritte",
520
+ flowStepOf: "Schritt {current} von {count}",
521
+ flowStepAnnounce: "Schritt {current} von {count}, {title}",
522
+ flowNext: "Weiter",
523
+ flowBack: "Zurück",
524
+ flowSubmit: "Senden",
525
+ flowSubmitting: "Wird gesendet…",
526
+ flowReviewTitle: "Angaben prüfen",
527
+ flowChange: "Ändern",
528
+ flowChangeField: "{field} ändern",
529
+ flowNotProvided: "Nicht angegeben",
530
+ flowOptional: "(optional)",
531
+ flowStepOptional: "Optional",
532
+ flowStepComplete: "Erledigt",
533
+ flowStepCurrent: "Aktueller Schritt",
534
+ flowStepErrors: "Fehler: {count}",
535
+ flowStepLocked: "Zuerst die vorherigen Schritte abschließen",
536
+ flowStepNotStarted: "Nicht begonnen",
537
+ flowErrorSummary: "Bitte korrigieren Sie diese Angaben, bevor Sie fortfahren",
538
+ flowReady: "Bereit zum Senden",
539
+ flowNotReady: "Zu korrigierende Fehler: {count}",
540
+ flowWarnings: "Warnungen: {count}",
541
+ flowChangesOnly: "Nur Änderungen anzeigen",
542
+ flowNoChanges: "Keine Angabe wurde geändert.",
543
+ flowWas: "Vorher: {value}",
544
+ flowChangedCount: "Geänderte Angaben: {count}",
545
+ flowSecretSet: "Festgelegt",
546
+ flowSecretKept: "Unverändert",
547
+ flowSecretNotSet: "Nicht festgelegt",
548
+ flowSecretHint: "Ein Wert ist gespeichert. Leer lassen, um ihn zu behalten.",
549
+ flowSecretShow: "Anzeigen",
550
+ flowSecretHide: "Verbergen",
551
+ flowSecretReveal: "{field} anzeigen",
552
+ flowOn: "Ein",
553
+ flowOff: "Aus",
554
+ flowAdd: "Hinzufügen",
555
+ flowAddItem: "Zu {field} hinzufügen",
556
+ flowRemoveItem: "{item} entfernen",
557
+ flowItemLabel: "{field}, Eintrag {index}",
558
+ flowSelectAll: "Alle auswählen",
559
+ flowSelectNone: "Leeren",
560
+ flowSelectedCount: "{count} von {total} ausgewählt",
561
+ flowUnit: "Einheit",
562
+ flowUnitSeconds: "Sekunden",
563
+ flowUnitMinutes: "Minuten",
564
+ flowUnitHours: "Stunden",
565
+ flowUnitDays: "Tage",
566
+ flowSeconds: "[one]{count} Sekunde[other]{count} Sekunden",
567
+ flowMinutes: "[one]{count} Minute[other]{count} Minuten",
568
+ flowHours: "[one]{count} Stunde[other]{count} Stunden",
569
+ flowDays: "[one]{count} Tag[other]{count} Tage",
570
+ flowDurationInvalid: "{field} muss eine ganze Zahl sein.",
571
+ flowItemsMin: "{field} braucht mindestens {min}.",
572
+ flowItemsMax: "{field} erlaubt höchstens {max}.",
573
+ flowItemEmail: "„{item}“ ist keine E-Mail-Adresse.",
574
+ flowItemHost: "„{item}“ ist kein Hostname.",
575
+ flowItemIp: "„{item}“ ist keine IP-Adresse.",
576
+ flowItemCidr: "„{item}“ ist kein Netzwerkbereich.",
577
+ flowItemUrl: "„{item}“ ist keine Webadresse.",
578
+ flowItemPattern: "„{item}“ hat nicht das erwartete Format.",
579
+ flowSaved: "Gespeichert",
580
+ flowAccepted: "In Bearbeitung",
581
+ flowProgress: "{done} von {total}",
582
+ flowConflict: "Diese Einstellungen wurden während Ihrer Bearbeitung geändert.",
583
+ flowReload: "Aktuelle Einstellungen neu laden",
584
+ flowNotSubmitted: "Die Angaben wurden nicht gesendet.",
585
+ flowNoHost: "Kein Host hat die Angaben empfangen.",
586
+ flowStartAgain: "Neu beginnen",
587
+ flowCopy: "Kopieren",
588
+ flowCopied: "Kopiert",
589
+ flowSavedIt: "Ich habe es gespeichert",
590
+ flowShownOnce: "Wird nur einmal angezeigt. Jetzt kopieren.",
519
591
  });
520
592
  const staticLabels = Object.freeze({
521
593
  overflowNote: "{shown} Zeilen angezeigt. Gesamtzahl: {total}.",
@@ -516,6 +516,78 @@ const labels = Object.freeze({
516
516
  calendarOutsideRange: "Fuera de las fechas que muestra este calendario",
517
517
  calendarClose: "Cerrar",
518
518
  calendarDetailsOf: "Detalles de {title}",
519
+ flowSteps: "Pasos",
520
+ flowStepOf: "Paso {current} de {count}",
521
+ flowStepAnnounce: "Paso {current} de {count}, {title}",
522
+ flowNext: "Siguiente",
523
+ flowBack: "Atrás",
524
+ flowSubmit: "Enviar",
525
+ flowSubmitting: "Enviando…",
526
+ flowReviewTitle: "Revise sus respuestas",
527
+ flowChange: "Cambiar",
528
+ flowChangeField: "Cambiar {field}",
529
+ flowNotProvided: "No indicado",
530
+ flowOptional: "(opcional)",
531
+ flowStepOptional: "Opcional",
532
+ flowStepComplete: "Completado",
533
+ flowStepCurrent: "Paso actual",
534
+ flowStepErrors: "Errores: {count}",
535
+ flowStepLocked: "Complete primero los pasos anteriores",
536
+ flowStepNotStarted: "Sin empezar",
537
+ flowErrorSummary: "Corrija esto antes de continuar",
538
+ flowReady: "Listo para enviar",
539
+ flowNotReady: "Errores por corregir: {count}",
540
+ flowWarnings: "Advertencias: {count}",
541
+ flowChangesOnly: "Mostrar solo los cambios",
542
+ flowNoChanges: "No ha cambiado ninguna respuesta.",
543
+ flowWas: "Antes: {value}",
544
+ flowChangedCount: "Respuestas cambiadas: {count}",
545
+ flowSecretSet: "Establecido",
546
+ flowSecretKept: "Sin cambios",
547
+ flowSecretNotSet: "Sin establecer",
548
+ flowSecretHint: "Hay un valor guardado. Déjelo en blanco para conservarlo.",
549
+ flowSecretShow: "Mostrar",
550
+ flowSecretHide: "Ocultar",
551
+ flowSecretReveal: "Mostrar {field}",
552
+ flowOn: "Activado",
553
+ flowOff: "Desactivado",
554
+ flowAdd: "Añadir",
555
+ flowAddItem: "Añadir a {field}",
556
+ flowRemoveItem: "Quitar {item}",
557
+ flowItemLabel: "{field}, elemento {index}",
558
+ flowSelectAll: "Seleccionar todo",
559
+ flowSelectNone: "Borrar",
560
+ flowSelectedCount: "{count} de {total} seleccionados",
561
+ flowUnit: "Unidad",
562
+ flowUnitSeconds: "segundos",
563
+ flowUnitMinutes: "minutos",
564
+ flowUnitHours: "horas",
565
+ flowUnitDays: "días",
566
+ flowSeconds: "[one]{count} segundo[other]{count} segundos",
567
+ flowMinutes: "[one]{count} minuto[other]{count} minutos",
568
+ flowHours: "[one]{count} hora[other]{count} horas",
569
+ flowDays: "[one]{count} día[other]{count} días",
570
+ flowDurationInvalid: "{field} debe ser un número entero.",
571
+ flowItemsMin: "{field} necesita al menos {min}.",
572
+ flowItemsMax: "{field} admite como máximo {max}.",
573
+ flowItemEmail: "«{item}» no es una dirección de correo.",
574
+ flowItemHost: "«{item}» no es un nombre de host.",
575
+ flowItemIp: "«{item}» no es una dirección IP.",
576
+ flowItemCidr: "«{item}» no es un rango de red.",
577
+ flowItemUrl: "«{item}» no es una dirección web.",
578
+ flowItemPattern: "«{item}» no tiene el formato esperado.",
579
+ flowSaved: "Guardado",
580
+ flowAccepted: "En curso",
581
+ flowProgress: "{done} de {total}",
582
+ flowConflict: "Esta configuración cambió mientras la editaba.",
583
+ flowReload: "Volver a cargar la configuración actual",
584
+ flowNotSubmitted: "Las respuestas no se enviaron.",
585
+ flowNoHost: "Ningún host recibió las respuestas.",
586
+ flowStartAgain: "Empezar otro",
587
+ flowCopy: "Copiar",
588
+ flowCopied: "Copiado",
589
+ flowSavedIt: "Lo he guardado",
590
+ flowShownOnce: "Se muestra solo una vez. Cópielo ahora.",
519
591
  });
520
592
  const staticLabels = Object.freeze({
521
593
  overflowNote: "Filas mostradas: {shown}. Total: {total}.",
@@ -516,6 +516,78 @@ const labels = Object.freeze({
516
516
  calendarOutsideRange: "En dehors des dates de ce calendrier",
517
517
  calendarClose: "Fermer",
518
518
  calendarDetailsOf: "Détails de {title}",
519
+ flowSteps: "Étapes",
520
+ flowStepOf: "Étape {current} sur {count}",
521
+ flowStepAnnounce: "Étape {current} sur {count}, {title}",
522
+ flowNext: "Suivant",
523
+ flowBack: "Retour",
524
+ flowSubmit: "Envoyer",
525
+ flowSubmitting: "Envoi…",
526
+ flowReviewTitle: "Vérifiez vos réponses",
527
+ flowChange: "Modifier",
528
+ flowChangeField: "Modifier {field}",
529
+ flowNotProvided: "Non renseigné",
530
+ flowOptional: "(facultatif)",
531
+ flowStepOptional: "Facultative",
532
+ flowStepComplete: "Terminée",
533
+ flowStepCurrent: "Étape actuelle",
534
+ flowStepErrors: "Erreurs : {count}",
535
+ flowStepLocked: "Terminez d'abord les étapes précédentes",
536
+ flowStepNotStarted: "Non commencée",
537
+ flowErrorSummary: "Corrigez ces points avant de continuer",
538
+ flowReady: "Prêt à envoyer",
539
+ flowNotReady: "Erreurs à corriger : {count}",
540
+ flowWarnings: "Avertissements : {count}",
541
+ flowChangesOnly: "Afficher uniquement les modifications",
542
+ flowNoChanges: "Aucune réponse n'a changé.",
543
+ flowWas: "Avant : {value}",
544
+ flowChangedCount: "Réponses modifiées : {count}",
545
+ flowSecretSet: "Défini",
546
+ flowSecretKept: "Inchangé",
547
+ flowSecretNotSet: "Non défini",
548
+ flowSecretHint: "Une valeur est enregistrée. Laissez vide pour la conserver.",
549
+ flowSecretShow: "Afficher",
550
+ flowSecretHide: "Masquer",
551
+ flowSecretReveal: "Afficher {field}",
552
+ flowOn: "Activé",
553
+ flowOff: "Désactivé",
554
+ flowAdd: "Ajouter",
555
+ flowAddItem: "Ajouter à {field}",
556
+ flowRemoveItem: "Retirer {item}",
557
+ flowItemLabel: "{field}, élément {index}",
558
+ flowSelectAll: "Tout sélectionner",
559
+ flowSelectNone: "Effacer",
560
+ flowSelectedCount: "{count} sur {total} sélectionnés",
561
+ flowUnit: "Unité",
562
+ flowUnitSeconds: "secondes",
563
+ flowUnitMinutes: "minutes",
564
+ flowUnitHours: "heures",
565
+ flowUnitDays: "jours",
566
+ flowSeconds: "[one]{count} seconde[other]{count} secondes",
567
+ flowMinutes: "[one]{count} minute[other]{count} minutes",
568
+ flowHours: "[one]{count} heure[other]{count} heures",
569
+ flowDays: "[one]{count} jour[other]{count} jours",
570
+ flowDurationInvalid: "{field} doit être un nombre entier.",
571
+ flowItemsMin: "{field} : au moins {min}.",
572
+ flowItemsMax: "{field} : au plus {max}.",
573
+ flowItemEmail: "« {item} » n'est pas une adresse e-mail.",
574
+ flowItemHost: "« {item} » n'est pas un nom d'hôte.",
575
+ flowItemIp: "« {item} » n'est pas une adresse IP.",
576
+ flowItemCidr: "« {item} » n'est pas une plage réseau.",
577
+ flowItemUrl: "« {item} » n'est pas une adresse web.",
578
+ flowItemPattern: "« {item} » n'a pas le format attendu.",
579
+ flowSaved: "Enregistré",
580
+ flowAccepted: "En cours",
581
+ flowProgress: "{done} sur {total}",
582
+ flowConflict: "Ces paramètres ont changé pendant que vous les modifiiez.",
583
+ flowReload: "Recharger les paramètres actuels",
584
+ flowNotSubmitted: "Les réponses n'ont pas été envoyées.",
585
+ flowNoHost: "Aucun hôte n'a reçu les réponses.",
586
+ flowStartAgain: "Recommencer",
587
+ flowCopy: "Copier",
588
+ flowCopied: "Copié",
589
+ flowSavedIt: "Je l'ai enregistré",
590
+ flowShownOnce: "Affiché une seule fois. Copiez-le maintenant.",
519
591
  });
520
592
  const staticLabels = Object.freeze({
521
593
  overflowNote: "{shown} lignes affichées sur {total}.",
@@ -516,6 +516,78 @@ const labels = Object.freeze({
516
516
  calendarOutsideRange: "Al di fuori delle date di questo calendario",
517
517
  calendarClose: "Chiudi",
518
518
  calendarDetailsOf: "Dettagli di {title}",
519
+ flowSteps: "Passaggi",
520
+ flowStepOf: "Passaggio {current} di {count}",
521
+ flowStepAnnounce: "Passaggio {current} di {count}, {title}",
522
+ flowNext: "Avanti",
523
+ flowBack: "Indietro",
524
+ flowSubmit: "Invia",
525
+ flowSubmitting: "Invio in corso…",
526
+ flowReviewTitle: "Controlla le risposte",
527
+ flowChange: "Modifica",
528
+ flowChangeField: "Modifica {field}",
529
+ flowNotProvided: "Non indicato",
530
+ flowOptional: "(facoltativo)",
531
+ flowStepOptional: "Facoltativo",
532
+ flowStepComplete: "Completato",
533
+ flowStepCurrent: "Passaggio corrente",
534
+ flowStepErrors: "Errori: {count}",
535
+ flowStepLocked: "Completa prima i passaggi precedenti",
536
+ flowStepNotStarted: "Non iniziato",
537
+ flowErrorSummary: "Correggi questi punti prima di continuare",
538
+ flowReady: "Pronto per l'invio",
539
+ flowNotReady: "Errori da correggere: {count}",
540
+ flowWarnings: "Avvisi: {count}",
541
+ flowChangesOnly: "Mostra solo le modifiche",
542
+ flowNoChanges: "Nessuna risposta è cambiata.",
543
+ flowWas: "Prima: {value}",
544
+ flowChangedCount: "Risposte modificate: {count}",
545
+ flowSecretSet: "Impostato",
546
+ flowSecretKept: "Invariato",
547
+ flowSecretNotSet: "Non impostato",
548
+ flowSecretHint: "È salvato un valore. Lascia vuoto per mantenerlo.",
549
+ flowSecretShow: "Mostra",
550
+ flowSecretHide: "Nascondi",
551
+ flowSecretReveal: "Mostra {field}",
552
+ flowOn: "Attivo",
553
+ flowOff: "Disattivo",
554
+ flowAdd: "Aggiungi",
555
+ flowAddItem: "Aggiungi a {field}",
556
+ flowRemoveItem: "Rimuovi {item}",
557
+ flowItemLabel: "{field}, elemento {index}",
558
+ flowSelectAll: "Seleziona tutto",
559
+ flowSelectNone: "Cancella",
560
+ flowSelectedCount: "{count} di {total} selezionati",
561
+ flowUnit: "Unità",
562
+ flowUnitSeconds: "secondi",
563
+ flowUnitMinutes: "minuti",
564
+ flowUnitHours: "ore",
565
+ flowUnitDays: "giorni",
566
+ flowSeconds: "[one]{count} secondo[other]{count} secondi",
567
+ flowMinutes: "[one]{count} minuto[other]{count} minuti",
568
+ flowHours: "[one]{count} ora[other]{count} ore",
569
+ flowDays: "[one]{count} giorno[other]{count} giorni",
570
+ flowDurationInvalid: "{field} deve essere un numero intero.",
571
+ flowItemsMin: "{field} richiede almeno {min}.",
572
+ flowItemsMax: "{field} ne consente al massimo {max}.",
573
+ flowItemEmail: "«{item}» non è un indirizzo email.",
574
+ flowItemHost: "«{item}» non è un nome host.",
575
+ flowItemIp: "«{item}» non è un indirizzo IP.",
576
+ flowItemCidr: "«{item}» non è un intervallo di rete.",
577
+ flowItemUrl: "«{item}» non è un indirizzo web.",
578
+ flowItemPattern: "«{item}» non ha il formato previsto.",
579
+ flowSaved: "Salvato",
580
+ flowAccepted: "In corso",
581
+ flowProgress: "{done} di {total}",
582
+ flowConflict: "Queste impostazioni sono cambiate durante la modifica.",
583
+ flowReload: "Ricarica le impostazioni correnti",
584
+ flowNotSubmitted: "Le risposte non sono state inviate.",
585
+ flowNoHost: "Nessun host ha ricevuto le risposte.",
586
+ flowStartAgain: "Ricomincia",
587
+ flowCopy: "Copia",
588
+ flowCopied: "Copiato",
589
+ flowSavedIt: "L'ho salvato",
590
+ flowShownOnce: "Mostrato una sola volta. Copialo ora.",
519
591
  });
520
592
  const staticLabels = Object.freeze({
521
593
  overflowNote: "Righe mostrate: {shown} su {total}.",
@@ -516,6 +516,78 @@ const labels = Object.freeze({
516
516
  calendarOutsideRange: "Poza datami, które pokazuje ten kalendarz",
517
517
  calendarClose: "Zamknij",
518
518
  calendarDetailsOf: "Szczegóły: {title}",
519
+ flowSteps: "Kroki",
520
+ flowStepOf: "Krok {current} z {count}",
521
+ flowStepAnnounce: "Krok {current} z {count}: {title}",
522
+ flowNext: "Dalej",
523
+ flowBack: "Wstecz",
524
+ flowSubmit: "Wyślij",
525
+ flowSubmitting: "Wysyłanie…",
526
+ flowReviewTitle: "Sprawdź odpowiedzi",
527
+ flowChange: "Zmień",
528
+ flowChangeField: "Zmień: {field}",
529
+ flowNotProvided: "Nie podano",
530
+ flowOptional: "(opcjonalnie)",
531
+ flowStepOptional: "Opcjonalny",
532
+ flowStepComplete: "Ukończono",
533
+ flowStepCurrent: "Bieżący krok",
534
+ flowStepErrors: "Błędy: {count}",
535
+ flowStepLocked: "Najpierw ukończ wcześniejsze kroki",
536
+ flowStepNotStarted: "Nierozpoczęty",
537
+ flowErrorSummary: "Popraw te pola, zanim przejdziesz dalej",
538
+ flowReady: "Gotowe do wysłania",
539
+ flowNotReady: "Błędy do poprawienia: {count}",
540
+ flowWarnings: "Ostrzeżenia: {count}",
541
+ flowChangesOnly: "Pokaż tylko zmiany",
542
+ flowNoChanges: "Żadna odpowiedź się nie zmieniła.",
543
+ flowWas: "Było: {value}",
544
+ flowChangedCount: "Zmienione odpowiedzi: {count}",
545
+ flowSecretSet: "Ustawiono",
546
+ flowSecretKept: "Bez zmian",
547
+ flowSecretNotSet: "Nie ustawiono",
548
+ flowSecretHint: "Wartość jest zapisana. Zostaw puste, aby ją zachować.",
549
+ flowSecretShow: "Pokaż",
550
+ flowSecretHide: "Ukryj",
551
+ flowSecretReveal: "Pokaż: {field}",
552
+ flowOn: "Włączone",
553
+ flowOff: "Wyłączone",
554
+ flowAdd: "Dodaj",
555
+ flowAddItem: "Dodaj do: {field}",
556
+ flowRemoveItem: "Usuń: {item}",
557
+ flowItemLabel: "{field}, pozycja {index}",
558
+ flowSelectAll: "Zaznacz wszystko",
559
+ flowSelectNone: "Wyczyść",
560
+ flowSelectedCount: "Zaznaczono {count} z {total}",
561
+ flowUnit: "Jednostka",
562
+ flowUnitSeconds: "sekundy",
563
+ flowUnitMinutes: "minuty",
564
+ flowUnitHours: "godziny",
565
+ flowUnitDays: "dni",
566
+ flowSeconds: "[one]{count} sekunda[few]{count} sekundy[many]{count} sekund[other]{count} sekundy",
567
+ flowMinutes: "[one]{count} minuta[few]{count} minuty[many]{count} minut[other]{count} minuty",
568
+ flowHours: "[one]{count} godzina[few]{count} godziny[many]{count} godzin[other]{count} godziny",
569
+ flowDays: "[one]{count} dzień[few]{count} dni[many]{count} dni[other]{count} dnia",
570
+ flowDurationInvalid: "{field}: wpisz liczbę całkowitą.",
571
+ flowItemsMin: "{field}: wymagane co najmniej {min}.",
572
+ flowItemsMax: "{field}: dozwolone najwyżej {max}.",
573
+ flowItemEmail: "„{item}” nie jest adresem e-mail.",
574
+ flowItemHost: "„{item}” nie jest nazwą hosta.",
575
+ flowItemIp: "„{item}” nie jest adresem IP.",
576
+ flowItemCidr: "„{item}” nie jest zakresem sieci.",
577
+ flowItemUrl: "„{item}” nie jest adresem internetowym.",
578
+ flowItemPattern: "„{item}” ma nieoczekiwany format.",
579
+ flowSaved: "Zapisano",
580
+ flowAccepted: "W toku",
581
+ flowProgress: "{done} z {total}",
582
+ flowConflict: "Te ustawienia zmieniły się podczas edycji.",
583
+ flowReload: "Wczytaj bieżące ustawienia",
584
+ flowNotSubmitted: "Odpowiedzi nie zostały wysłane.",
585
+ flowNoHost: "Żaden host nie odebrał odpowiedzi.",
586
+ flowStartAgain: "Zacznij od nowa",
587
+ flowCopy: "Kopiuj",
588
+ flowCopied: "Skopiowano",
589
+ flowSavedIt: "Mam to zapisane",
590
+ flowShownOnce: "Widoczne tylko raz. Skopiuj teraz.",
519
591
  });
520
592
  const staticLabels = Object.freeze({
521
593
  overflowNote: "Pokazano {shown} z {total} wierszy.",