@eifi1/ui-kit 0.22.0 → 0.24.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 +42 -25
- package/dist/chart.d.ts +8 -7
- package/dist/components/amount-input.d.ts +34 -7
- package/dist/components/amount-input.js +14 -10
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.d.ts +26 -0
- package/dist/components/autocomplete.js +164 -137
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/button-group.d.ts +8 -7
- package/dist/components/calculator.d.ts +8 -7
- package/dist/components/column-mapper.d.ts +235 -0
- package/dist/components/column-mapper.js +411 -0
- package/dist/components/column-mapper.js.map +1 -0
- package/dist/components/combobox-core.d.ts +39 -2
- package/dist/components/combobox-core.js +29 -6
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +113 -3
- package/dist/components/combobox.js +456 -313
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +8 -7
- package/dist/components/confirm-dialog.js +7 -8
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-button.d.ts +5 -4
- package/dist/components/country-select.d.ts +50 -7
- package/dist/components/country-select.js +65 -9
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +8 -7
- package/dist/components/danger-confirm.js +64 -7
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/date-picker.d.ts +41 -0
- package/dist/components/date-picker.js +269 -8
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +48 -2
- package/dist/components/entity-combobox.js +159 -114
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/facing-pair.d.ts +8 -7
- package/dist/components/field-parts.d.ts +116 -6
- package/dist/components/field-parts.js +84 -0
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-strip.d.ts +105 -0
- package/dist/components/field-strip.js +46 -0
- package/dist/components/field-strip.js.map +1 -0
- package/dist/components/file-button.d.ts +8 -7
- package/dist/components/file-dropzone.d.ts +8 -7
- package/dist/components/form-actions.d.ts +8 -7
- package/dist/components/form-actions.js +23 -3
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/iban-input.d.ts +8 -7
- package/dist/components/icon-picker.d.ts +10 -1
- package/dist/components/icon-picker.js +12 -4
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/language-select.d.ts +8 -7
- package/dist/components/money-field.d.ts +11 -7
- package/dist/components/money-field.js.map +1 -1
- package/dist/components/month-picker.js +2 -1
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.d.ts +31 -2
- package/dist/components/multi-entity-combobox.js +152 -103
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/number-field.d.ts +8 -7
- package/dist/components/number-input.d.ts +8 -7
- package/dist/components/numpad-sheet.d.ts +8 -7
- package/dist/components/phone-input.d.ts +8 -7
- package/dist/components/reauth-dialog.d.ts +2 -2
- package/dist/components/reauth-dialog.js +6 -8
- package/dist/components/reauth-dialog.js.map +1 -1
- package/dist/components/series-chart.d.ts +8 -7
- package/dist/components/settings-fields.d.ts +8 -7
- package/dist/components/share-card.d.ts +8 -7
- package/dist/components/swatch-picker.d.ts +17 -1
- package/dist/components/swatch-picker.js +10 -4
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/text-link.d.ts +8 -7
- package/dist/components/tile-radio.d.ts +20 -0
- package/dist/components/tile-radio.js +25 -8
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +8 -7
- package/dist/components/toggle-group.js +2 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/trigger-aria.d.ts +3 -0
- package/dist/components/trigger-aria.js +3 -1
- package/dist/components/trigger-aria.js.map +1 -1
- package/dist/components/ui.d.ts +5 -4
- package/dist/components/ui.js +60 -28
- package/dist/components/ui.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +66 -1
- package/dist/feedback/feedback-attachment.js +185 -65
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-dialog.d.ts +66 -1
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +67 -252
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +66 -287
- package/dist/feedback/feedback-thread.js +16 -3
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/{kit-labels-R8mIAc9N.d.ts → feedback-DOwPu-Il.d.ts} +1273 -30
- package/dist/feedback.d.ts +65 -3
- package/dist/hooks/use-file-drop.d.ts +8 -7
- package/dist/i18n/defaults.d.ts +8 -7
- package/dist/i18n/defaults.js +3 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +8 -7
- package/dist/i18n/german.js +36 -2
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +5 -4
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +8 -7
- package/dist/i18n/locales/de-CH.d.ts +8 -7
- package/dist/i18n/locales/en.d.ts +8 -7
- package/dist/i18n/locales/en.js +7 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +8 -7
- package/dist/i18n/locales/es.js +37 -2
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +8 -7
- package/dist/i18n/locales/fr.js +36 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +8 -7
- package/dist/i18n/locales/hu.js +38 -2
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +8 -7
- package/dist/i18n/locales/it.js +37 -2
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +8 -7
- package/dist/i18n/locales/zh.js +34 -2
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +8 -7
- package/dist/i18n/review.js +20 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/column-mapping.d.ts +81 -0
- package/dist/lib/column-mapping.js +108 -0
- package/dist/lib/column-mapping.js.map +1 -0
- package/dist/lib/strip-fade.d.ts +2 -2
- package/dist/lib/strip-fade.js.map +1 -1
- package/dist/lib/table-text.d.ts +109 -1
- package/dist/lib/table-text.js +122 -1
- package/dist/lib/table-text.js.map +1 -1
- package/dist/rhf/fields.d.ts +142 -13
- package/dist/rhf/fields.js +185 -3
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +8 -7
- package/dist/rhf.d.ts +9 -8
- package/dist/rhf.js.map +1 -1
- package/dist/shell/app-shell.d.ts +8 -7
- package/dist/shell/top-bar-brand.d.ts +8 -7
- package/dist/shell/topbar-action-menu.d.ts +36 -3
- package/dist/shell/topbar-action-menu.js +74 -33
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell.d.ts +8 -7
- package/dist/table-text.d.ts +1 -1
- package/dist/wizard/stepper-nav.d.ts +38 -9
- package/dist/wizard/stepper-nav.js +4 -0
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard.d.ts +8 -7
- package/package.json +1 -1
- package/src/components/amount-input.tsx +50 -14
- package/src/components/autocomplete.tsx +188 -116
- package/src/components/column-mapper.tsx +768 -0
- package/src/components/combobox-core.tsx +82 -9
- package/src/components/combobox.tsx +655 -335
- package/src/components/confirm-dialog.tsx +12 -8
- package/src/components/country-select.tsx +135 -22
- package/src/components/danger-confirm.tsx +274 -24
- package/src/components/date-picker.tsx +423 -10
- package/src/components/entity-combobox.tsx +243 -129
- package/src/components/field-parts.tsx +224 -5
- package/src/components/field-strip.tsx +149 -0
- package/src/components/form-actions.tsx +52 -5
- package/src/components/icon-picker.tsx +23 -4
- package/src/components/money-field.tsx +3 -0
- package/src/components/month-picker.tsx +2 -1
- package/src/components/multi-entity-combobox.tsx +221 -121
- package/src/components/reauth-dialog.tsx +17 -18
- package/src/components/swatch-picker.tsx +29 -5
- package/src/components/tile-radio.tsx +74 -13
- package/src/components/toggle-group.tsx +2 -2
- package/src/components/trigger-aria.ts +5 -0
- package/src/components/ui.tsx +114 -33
- package/src/feedback/feedback-attachment.tsx +372 -72
- package/src/feedback/feedback-dialog.tsx +7 -3
- package/src/feedback/feedback-inbox.tsx +3 -2
- package/src/feedback/feedback-thread.tsx +112 -9
- package/src/i18n/defaults.ts +2 -0
- package/src/i18n/german.ts +42 -0
- package/src/i18n/kit-labels.tsx +4 -0
- package/src/i18n/locales/en.ts +27 -5
- package/src/i18n/locales/es.ts +41 -0
- package/src/i18n/locales/fr.ts +42 -0
- package/src/i18n/locales/hu.ts +37 -0
- package/src/i18n/locales/it.ts +41 -0
- package/src/i18n/locales/zh.ts +32 -0
- package/src/i18n/review.ts +19 -0
- package/src/index.ts +18 -0
- package/src/lib/column-mapping.ts +234 -0
- package/src/lib/strip-fade.ts +2 -2
- package/src/lib/table-text.ts +271 -0
- package/src/rhf/fields.tsx +421 -6
- package/src/rhf.ts +2 -1
- package/src/shell/topbar-action-menu.tsx +134 -38
- package/src/wizard/stepper-nav.tsx +35 -1
- package/dist/components/field-anatomy.d.ts +0 -95
- package/dist/components/field-anatomy.js +0 -84
- package/dist/components/field-anatomy.js.map +0 -1
- package/dist/feedback-attachment-NhUm7Zga.d.ts +0 -367
- package/src/components/field-anatomy.tsx +0 -190
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
DEFAULT_MAX_ATTACHMENT_BYTES,
|
|
11
11
|
FeedbackAttachmentField,
|
|
12
12
|
type FeedbackAttachmentError,
|
|
13
|
+
type FeedbackAttachmentErrorInfo,
|
|
13
14
|
} from "./feedback-attachment";
|
|
14
15
|
|
|
15
16
|
export interface FeedbackCategoryOption {
|
|
@@ -157,7 +158,9 @@ interface FeedbackDialogBaseProps {
|
|
|
157
158
|
export interface FeedbackDialogSingleProps extends FeedbackDialogBaseProps {
|
|
158
159
|
attachments?: "single";
|
|
159
160
|
onSubmit: (data: FeedbackSubmission) => void | Promise<void>;
|
|
160
|
-
|
|
161
|
+
/** `info` (0.23.0) names the refused file and the limit — see
|
|
162
|
+
* {@link FeedbackAttachmentErrorInfo}. */
|
|
163
|
+
onAttachmentError?: (kind: "type" | "size", info: FeedbackAttachmentErrorInfo) => void;
|
|
161
164
|
/** Multiple mode only — refused here rather than silently ignored. */
|
|
162
165
|
maxAttachments?: never;
|
|
163
166
|
}
|
|
@@ -172,8 +175,9 @@ export interface FeedbackDialogMultipleProps extends FeedbackDialogBaseProps {
|
|
|
172
175
|
/** Default `DEFAULT_MAX_ATTACHMENTS` (5). The screenshot does not count. */
|
|
173
176
|
maxAttachments?: number;
|
|
174
177
|
onSubmit: (data: FeedbackMultipleSubmission) => void | Promise<void>;
|
|
175
|
-
/** `"count"`: more files arrived at once than there was room for; the surplus was
|
|
176
|
-
|
|
178
|
+
/** `"count"`: more files arrived at once than there was room for; the surplus was
|
|
179
|
+
* dropped. `info` (0.23.0) names the refused file(s) and the limit. */
|
|
180
|
+
onAttachmentError?: (kind: FeedbackAttachmentError, info: FeedbackAttachmentErrorInfo) => void;
|
|
177
181
|
}
|
|
178
182
|
|
|
179
183
|
export type FeedbackDialogProps = FeedbackDialogSingleProps | FeedbackDialogMultipleProps;
|
|
@@ -18,7 +18,7 @@ import type { LucideIcon } from "lucide-react";
|
|
|
18
18
|
import { cn } from "../lib/cn";
|
|
19
19
|
import { Button, Textarea } from "../components/ui";
|
|
20
20
|
import { Tooltip } from "../components/tooltip";
|
|
21
|
-
import { FeedbackAttachmentField } from "./feedback-attachment";
|
|
21
|
+
import { FeedbackAttachmentField, type FeedbackAttachmentErrorInfo } from "./feedback-attachment";
|
|
22
22
|
import type { FeedbackAttachmentLabels } from "./feedback-dialog";
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -566,7 +566,8 @@ export interface FeedbackNoteAttachment {
|
|
|
566
566
|
labels: FeedbackAttachmentLabels;
|
|
567
567
|
accept?: string[];
|
|
568
568
|
maxBytes?: number;
|
|
569
|
-
|
|
569
|
+
/** `info` (0.23.0) names the refused file and the limit. */
|
|
570
|
+
onError?: (kind: "type" | "size", info: FeedbackAttachmentErrorInfo) => void;
|
|
570
571
|
onCaptureScreenshot?: () => Promise<File | null>;
|
|
571
572
|
}
|
|
572
573
|
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { useEffect, useId, useImperativeHandle, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
2
|
-
import type { ReactNode, Ref } from "react";
|
|
2
|
+
import type { ReactNode, Ref, RefObject } from "react";
|
|
3
3
|
import { ImageIcon, ImageOff, Paperclip, Send } from "lucide-react";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
5
|
import { formatDate, formatRelativeTime } from "../lib/format";
|
|
6
6
|
import { Button, EmptyState, Spinner, Textarea } from "../components/ui";
|
|
7
|
+
import type { CharacterCountLabels } from "../components/ui";
|
|
7
8
|
import { Skeleton } from "../components/skeleton";
|
|
8
9
|
import { Tooltip } from "../components/tooltip";
|
|
9
10
|
import { useKitFileLabels, useKitLabels, useKitLocale } from "../i18n/kit-labels";
|
|
10
11
|
import { FeedbackAttachmentField } from "./feedback-attachment";
|
|
12
|
+
import type { FeedbackAttachmentFieldSingleProps } from "./feedback-attachment";
|
|
11
13
|
import type { FeedbackNoteAttachment } from "./feedback-inbox";
|
|
12
14
|
import type { FeedbackAttachmentLabels } from "./feedback-dialog";
|
|
13
15
|
|
|
@@ -463,10 +465,48 @@ function toDate(value: Date | string | number): Date | null {
|
|
|
463
465
|
/* ── Composer ─────────────────────────────────────────────────────────────── */
|
|
464
466
|
|
|
465
467
|
/** What the composer's attach control takes — {@link FeedbackNoteAttachment} with the
|
|
466
|
-
* labels optional, since the field reads `feedbackAttachment` from the provider
|
|
467
|
-
|
|
468
|
+
* labels optional, since the field reads `feedbackAttachment` from the provider, and
|
|
469
|
+
* `onError` the field's own (0.23.0): it is handed the refused file and the limit too
|
|
470
|
+
* (`FeedbackAttachmentErrorInfo`), and a `(kind) => …` handler still fits. Since
|
|
471
|
+
* 0.24.0 also the field's `buttonVariant` / `buttonSize`, for a composer whose row
|
|
472
|
+
* wants smaller or quieter attach buttons than the bordered `md` default. */
|
|
473
|
+
export type FeedbackComposerAttachment = Omit<FeedbackNoteAttachment, "labels" | "onError"> & {
|
|
468
474
|
labels?: Partial<FeedbackAttachmentLabels>;
|
|
469
|
-
|
|
475
|
+
onError?: FeedbackAttachmentFieldSingleProps["onError"];
|
|
476
|
+
} & Pick<FeedbackAttachmentFieldSingleProps, "buttonVariant" | "buttonSize">;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* What a render-prop {@link FeedbackComposerProps.attachmentSlot} is handed (0.24.0,
|
|
480
|
+
* keksdose).
|
|
481
|
+
*
|
|
482
|
+
* keksdose's support chat put `<FeedbackAttachmentField refs>` in the slot and a
|
|
483
|
+
* screenshot pasted into the reply box never reached it: the box is the field's
|
|
484
|
+
* sibling, so the paste bubbles to their common parent — the composer's root — and the
|
|
485
|
+
* field hears it only through `pasteFrom`, which needs that root. The composer kept it
|
|
486
|
+
* to itself, so keksdose wrapped the whole composer in a ref'd `<div>` of its own just
|
|
487
|
+
* to have an element to hand over.
|
|
488
|
+
*/
|
|
489
|
+
export interface FeedbackComposerSlotContext {
|
|
490
|
+
/**
|
|
491
|
+
* The composer's root, round the text box and this slot — the field's `pasteFrom`,
|
|
492
|
+
* as it is: `pasteFrom={slot.root}`.
|
|
493
|
+
*
|
|
494
|
+
* A ref, not the element, because `pasteFrom` is one: the field reads `.current` in
|
|
495
|
+
* an effect, and the slot renders INSIDE this root, so the two are committed together
|
|
496
|
+
* and React attaches the root before any effect of the slot's runs — the first paste
|
|
497
|
+
* after the first paint already lands. The element itself would be `null` on the
|
|
498
|
+
* first render (it does not exist yet) and could only arrive by a second render
|
|
499
|
+
* through state; the ref is the same object every render, so the field's listener is
|
|
500
|
+
* added once and never re-added.
|
|
501
|
+
*
|
|
502
|
+
* With the built-in `attachment` on as well, it listens on this root too: hand the
|
|
503
|
+
* root to one field only, or an image pasted once is attached twice.
|
|
504
|
+
*/
|
|
505
|
+
root: RefObject<HTMLElement | null>;
|
|
506
|
+
/** The composer's `pending` — a send is in flight. For the field's `disabled`
|
|
507
|
+
* (keksdose G5b): the message carries the attachments as they were at the press. */
|
|
508
|
+
pending: boolean;
|
|
509
|
+
}
|
|
470
510
|
|
|
471
511
|
export interface FeedbackComposerProps {
|
|
472
512
|
/**
|
|
@@ -491,14 +531,27 @@ export interface FeedbackComposerProps {
|
|
|
491
531
|
* The slot is the host's picker plus the chips of what is uploaded; the upload, the
|
|
492
532
|
* refs and clearing them once `onSend` resolves stay with the host. Pair it with
|
|
493
533
|
* `canSend`.
|
|
534
|
+
*
|
|
535
|
+
* A node, or (0.24.0) a function of {@link FeedbackComposerSlotContext} that returns
|
|
536
|
+
* one — for a field that wants the composer's root as its `pasteFrom`, so a
|
|
537
|
+
* screenshot pasted into the box reaches it, and `pending` for its `disabled`:
|
|
538
|
+
*
|
|
539
|
+
* ```tsx
|
|
540
|
+
* attachmentSlot={({ root, pending }) => (
|
|
541
|
+
* <FeedbackAttachmentField refs pasteFrom={root} disabled={pending} … />
|
|
542
|
+
* )}
|
|
543
|
+
* ```
|
|
544
|
+
*
|
|
545
|
+
* Called once per render of the composer, and not at all while `disabledReason`
|
|
546
|
+
* stands in for it.
|
|
494
547
|
*/
|
|
495
|
-
attachmentSlot?: ReactNode;
|
|
548
|
+
attachmentSlot?: ReactNode | ((slot: FeedbackComposerSlotContext) => ReactNode);
|
|
496
549
|
/**
|
|
497
550
|
* Whether Send is enabled, over the composer's own rule (some text in the box) —
|
|
498
551
|
* for state the composer cannot see, i.e. `attachmentSlot`'s (keksdose G5): `true`
|
|
499
552
|
* with files ready makes an empty draft sendable (`onSend("", null)`), `false` while
|
|
500
553
|
* an upload is still running holds even a written reply back. Left out, the text
|
|
501
|
-
* decides. `pending` blocks a send either way
|
|
554
|
+
* decides. `pending` blocks a send either way, as does a draft past `maxLength`.
|
|
502
555
|
*/
|
|
503
556
|
canSend?: boolean;
|
|
504
557
|
/**
|
|
@@ -513,6 +566,31 @@ export interface FeedbackComposerProps {
|
|
|
513
566
|
* reader. */
|
|
514
567
|
disabledReason?: ReactNode;
|
|
515
568
|
rows?: number;
|
|
569
|
+
/**
|
|
570
|
+
* The longest draft the box takes, in UTF-16 code units as the browser counts — the
|
|
571
|
+
* server's limit, so a reply too long for it is cut off while it is typed rather than
|
|
572
|
+
* refused by a 422 after the press (keksdose G6: its support replies are capped at
|
|
573
|
+
* 4,000 on the server, and its other text fields already count against that with
|
|
574
|
+
* Textarea's `maxLength` + `showCount` since 0.22; the reply box, a composer, could
|
|
575
|
+
* not). The box's own `maxLength`, so typing and pasting stop at it.
|
|
576
|
+
*
|
|
577
|
+
* {@link FeedbackComposerHandle.insertText} is not stopped by it — the browser limits
|
|
578
|
+
* typing, not a script — and a canned reply is not cut mid-sentence to fit. A draft
|
|
579
|
+
* past the limit therefore holds Send back (whatever `canSend` says, as `pending`
|
|
580
|
+
* does) until it is trimmed; with `showCount` the counter, red at the limit, says by
|
|
581
|
+
* how much.
|
|
582
|
+
*/
|
|
583
|
+
maxLength?: number;
|
|
584
|
+
/**
|
|
585
|
+
* A live "12/4000" under the box, with `maxLength` — Textarea's `showCount`, the same
|
|
586
|
+
* counter (keksdose G6): the count is part of the box's description, read with it on
|
|
587
|
+
* focus, and a polite live region speaks only on entering the last stretch and at the
|
|
588
|
+
* limit, never per keystroke. Under `size="sm"` the hidden send hint stays the box's
|
|
589
|
+
* description too, before the count. Ignored without `maxLength`.
|
|
590
|
+
*/
|
|
591
|
+
showCount?: boolean;
|
|
592
|
+
/** The counter's words — the `characterCount` namespace, as on Textarea. */
|
|
593
|
+
countLabels?: Partial<CharacterCountLabels>;
|
|
516
594
|
/**
|
|
517
595
|
* The box's hint, over the `placeholder` label — keksdose F9: an admin answering a
|
|
518
596
|
* support ticket is asked something else ("Reply to Anna…") than a member adding to
|
|
@@ -594,6 +672,9 @@ export function FeedbackComposer({
|
|
|
594
672
|
sendOn = "mod-enter",
|
|
595
673
|
disabledReason,
|
|
596
674
|
rows = 3,
|
|
675
|
+
maxLength,
|
|
676
|
+
showCount,
|
|
677
|
+
countLabels,
|
|
597
678
|
placeholder,
|
|
598
679
|
value,
|
|
599
680
|
onValueChange,
|
|
@@ -668,7 +749,10 @@ export function FeedbackComposer({
|
|
|
668
749
|
);
|
|
669
750
|
}
|
|
670
751
|
|
|
671
|
-
|
|
752
|
+
// Longer than `maxLength` only through `insertText` or a controlled value (typing
|
|
753
|
+
// stops at it): the server would refuse it, so it does not go.
|
|
754
|
+
const tooLong = maxLength !== undefined && draft.length > maxLength;
|
|
755
|
+
const canSend = (canSendProp ?? draft.trim().length > 0) && !pending && !tooLong;
|
|
672
756
|
const send = () => {
|
|
673
757
|
if (!canSend) return;
|
|
674
758
|
const sentDraft = draft;
|
|
@@ -682,6 +766,14 @@ export function FeedbackComposer({
|
|
|
682
766
|
};
|
|
683
767
|
|
|
684
768
|
const config = attachment === true ? {} : attachment || null;
|
|
769
|
+
// The slot is handed the ref OBJECT, for a field's `pasteFrom`, which reads `.current`
|
|
770
|
+
// in an effect once the root is attached — nothing reads it during this render (see
|
|
771
|
+
// FeedbackComposerSlotContext.root).
|
|
772
|
+
const slot =
|
|
773
|
+
typeof attachmentSlot === "function"
|
|
774
|
+
? // eslint-disable-next-line react-hooks/refs -- handed on for an effect, not read here
|
|
775
|
+
attachmentSlot({ root, pending })
|
|
776
|
+
: attachmentSlot;
|
|
685
777
|
|
|
686
778
|
return (
|
|
687
779
|
<div {...rootAttributes} ref={root} className={cn("space-y-2", className)}>
|
|
@@ -689,7 +781,14 @@ export function FeedbackComposer({
|
|
|
689
781
|
rows={rows}
|
|
690
782
|
dir="auto"
|
|
691
783
|
aria-label={labels.field}
|
|
784
|
+
// Textarea puts the counter's description after this one, so under "sm" the box
|
|
785
|
+
// reads "Enter to send… 12 of 4000 characters".
|
|
692
786
|
aria-describedby={size === "sm" ? hintId : undefined}
|
|
787
|
+
maxLength={maxLength}
|
|
788
|
+
// Passed only when given: Textarea keeps a wrapper for a `showCount` it was
|
|
789
|
+
// handed at all, and a composer without one keeps the DOM it had.
|
|
790
|
+
{...(showCount !== undefined ? { showCount } : null)}
|
|
791
|
+
countLabels={countLabels}
|
|
693
792
|
ref={box}
|
|
694
793
|
placeholder={placeholder ?? labels.placeholder}
|
|
695
794
|
value={draft}
|
|
@@ -713,7 +812,7 @@ export function FeedbackComposer({
|
|
|
713
812
|
}}
|
|
714
813
|
/>
|
|
715
814
|
<div className="flex flex-wrap items-end justify-between gap-2">
|
|
716
|
-
{config ||
|
|
815
|
+
{config || slot != null ? (
|
|
717
816
|
<div className="flex min-w-0 flex-wrap items-end gap-2">
|
|
718
817
|
{config && (
|
|
719
818
|
<FeedbackAttachmentField
|
|
@@ -724,11 +823,13 @@ export function FeedbackComposer({
|
|
|
724
823
|
maxBytes={config.maxBytes}
|
|
725
824
|
onError={config.onError}
|
|
726
825
|
onCaptureScreenshot={config.onCaptureScreenshot}
|
|
826
|
+
buttonVariant={config.buttonVariant}
|
|
827
|
+
buttonSize={config.buttonSize}
|
|
727
828
|
// The box is this field's sibling; a paste in it bubbles to `root`.
|
|
728
829
|
pasteFrom={root}
|
|
729
830
|
/>
|
|
730
831
|
)}
|
|
731
|
-
{
|
|
832
|
+
{slot}
|
|
732
833
|
</div>
|
|
733
834
|
) : (
|
|
734
835
|
<span />
|
|
@@ -784,3 +885,5 @@ export type ChatComposerHandle = FeedbackComposerHandle;
|
|
|
784
885
|
/** {@link FeedbackComposerLabels}, for {@link ChatComposer} — still the `feedbackComposer`
|
|
785
886
|
* namespace of the provider. */
|
|
786
887
|
export type ChatComposerLabels = FeedbackComposerLabels;
|
|
888
|
+
/** {@link FeedbackComposerSlotContext}, for {@link ChatComposer}'s `attachmentSlot`. */
|
|
889
|
+
export type ChatComposerSlotContext = FeedbackComposerSlotContext;
|
package/src/i18n/defaults.ts
CHANGED
|
@@ -62,6 +62,7 @@ import { DEFAULT_INLINE_EDIT_LABELS } from "../components/inline-edit-field";
|
|
|
62
62
|
import { DEFAULT_IBAN_INPUT_LABELS } from "../components/iban-input";
|
|
63
63
|
import { DEFAULT_PHONE_INPUT_LABELS } from "../components/phone-input";
|
|
64
64
|
import { DEFAULT_SIGN_CHIP_LABELS } from "../components/sign-chip";
|
|
65
|
+
import { DEFAULT_COLUMN_MAPPER_LABELS } from "../components/column-mapper";
|
|
65
66
|
import {
|
|
66
67
|
DEFAULT_APP_SHELL_LABELS,
|
|
67
68
|
DEFAULT_CALCULATOR_LABELS,
|
|
@@ -157,4 +158,5 @@ export const DEFAULT_UI_KIT_LABELS: UiKitLabels = {
|
|
|
157
158
|
ibanInput: DEFAULT_IBAN_INPUT_LABELS,
|
|
158
159
|
phoneInput: DEFAULT_PHONE_INPUT_LABELS,
|
|
159
160
|
signChip: DEFAULT_SIGN_CHIP_LABELS,
|
|
161
|
+
columnMapper: DEFAULT_COLUMN_MAPPER_LABELS,
|
|
160
162
|
};
|
package/src/i18n/german.ts
CHANGED
|
@@ -29,6 +29,7 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
29
29
|
attachmentRemoveFile: (name) => `${name} entfernen`,
|
|
30
30
|
attachmentLimit: (max) => `Maximal ${n(max)} ${max === 1 ? "Anhang" : "Anhänge"} – zum Hinzufügen erst einen entfernen.`,
|
|
31
31
|
attachmentUploading: "Wird hochgeladen…",
|
|
32
|
+
attachmentUploadFailed: (name) => `„${name}“ konnte nicht hochgeladen werden`,
|
|
32
33
|
},
|
|
33
34
|
feedbackDialog: {
|
|
34
35
|
title: "Feedback senden",
|
|
@@ -340,6 +341,9 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
340
341
|
password: "Passwort",
|
|
341
342
|
phrase: (phrase) => `Geben Sie zur Bestätigung „${phrase}“ ein`,
|
|
342
343
|
acknowledge: "Ich habe gelesen, was dies bewirkt, und möchte fortfahren.",
|
|
344
|
+
needsPhrase: (phrase) => `Geben Sie zur Bestätigung „${phrase}“ ein`,
|
|
345
|
+
needsAcknowledge: "Setzen Sie zur Bestätigung das Häkchen",
|
|
346
|
+
needsPassword: "Geben Sie zur Bestätigung Ihr Passwort ein",
|
|
343
347
|
},
|
|
344
348
|
tabs: {
|
|
345
349
|
// "Tab" is what German UIs say; "Registerkarte" reads like a 1990s manual.
|
|
@@ -698,6 +702,44 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
698
702
|
inflow: "Einnahme",
|
|
699
703
|
direction: (current, next) => `Richtung: ${current} – zu ${next} wechseln`,
|
|
700
704
|
},
|
|
705
|
+
columnMapper: {
|
|
706
|
+
paste: "Tabelle einfügen",
|
|
707
|
+
pasteHint:
|
|
708
|
+
"Die Zeilen aus einer Tabellenkalkulation kopieren und hier einfügen – oder eine CSV- oder Textdatei hier ablegen.",
|
|
709
|
+
chooseFile: "Datei auswählen",
|
|
710
|
+
readError: (name) => `„${name}“ konnte nicht gelesen werden`,
|
|
711
|
+
headerRow: "Die erste Zeile enthält die Spaltennamen",
|
|
712
|
+
summary: (columns, rows) =>
|
|
713
|
+
`${n(columns)} ${columns === 1 ? "Spalte" : "Spalten"}, ${n(rows)} ${rows === 1 ? "Zeile" : "Zeilen"}`,
|
|
714
|
+
// Fragments of the summary line ("3 Spalten, 120 Zeilen · durch Semikolons getrennt").
|
|
715
|
+
separatorSemicolon: "durch Semikolons getrennt",
|
|
716
|
+
separatorComma: "durch Kommas getrennt",
|
|
717
|
+
separatorTab: "durch Tabulatoren getrennt",
|
|
718
|
+
separatorSpace: "durch Leerzeichen getrennt",
|
|
719
|
+
// The examples stay as written: they show the convention, not the reader's locale.
|
|
720
|
+
decimalComma: "Dezimalkomma (1,5)",
|
|
721
|
+
decimalPoint: "Dezimalpunkt (1.5)",
|
|
722
|
+
unreadCount: (count) =>
|
|
723
|
+
count === 1
|
|
724
|
+
? "1 Zeile konnte nicht gelesen werden"
|
|
725
|
+
: `${n(count)} Zeilen konnten nicht gelesen werden`,
|
|
726
|
+
// A line number is a position, not a count: unformatted, as `measuredGrid.lineError`.
|
|
727
|
+
unreadLine: (line) => `Zeile ${line} konnte nicht gelesen werden`,
|
|
728
|
+
unreadMore: (count) => `…und ${n(count)} weitere`,
|
|
729
|
+
noRows: "Keine Zeile dieses Textes lässt sich als Tabellenzeile lesen.",
|
|
730
|
+
table: "Spaltenzuordnung",
|
|
731
|
+
columnN: (column) => `Spalte ${column}`,
|
|
732
|
+
roleOf: (column) => `Was enthält die Spalte „${column}“?`,
|
|
733
|
+
ignore: "Ignorieren",
|
|
734
|
+
requiredRole: (role) => `${role} (erforderlich)`,
|
|
735
|
+
previewOf: (shown, total) =>
|
|
736
|
+
shown === 1
|
|
737
|
+
? `Die erste von ${n(total)} Zeilen`
|
|
738
|
+
: `Die ersten ${n(shown)} von ${n(total)} Zeilen`,
|
|
739
|
+
// `roles` arrives joined with "oder" ("Soll oder Haben").
|
|
740
|
+
oneOf: (roles) => `entweder ${roles}`,
|
|
741
|
+
missing: (roles) => `Noch erforderlich: ${roles}.`,
|
|
742
|
+
},
|
|
701
743
|
translationReview: {
|
|
702
744
|
statusMissing: "Fehlt",
|
|
703
745
|
statusUnreviewed: "Ungeprüft",
|
package/src/i18n/kit-labels.tsx
CHANGED
|
@@ -58,6 +58,7 @@ import type { InlineEditLabels } from "../components/inline-edit-field";
|
|
|
58
58
|
import type { IbanInputLabels } from "../components/iban-input";
|
|
59
59
|
import type { PhoneInputLabels } from "../components/phone-input";
|
|
60
60
|
import type { SignChipLabels } from "../components/sign-chip";
|
|
61
|
+
import type { ColumnMapperLabels } from "../components/column-mapper";
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
64
|
* EVERY string the kit renders, as one typed tree — and an optional provider that
|
|
@@ -311,6 +312,9 @@ export interface UiKitLabels {
|
|
|
311
312
|
phoneInput: PhoneInputLabels;
|
|
312
313
|
/** 0.22.0: `SignChip` — the outflow / inflow toggle beside an amount. */
|
|
313
314
|
signChip: SignChipLabels;
|
|
315
|
+
/** 0.23.0: `ColumnMapper` / `ColumnRoleTable` — a pasted or dropped table, a role per
|
|
316
|
+
* column. */
|
|
317
|
+
columnMapper: ColumnMapperLabels;
|
|
314
318
|
}
|
|
315
319
|
|
|
316
320
|
/**
|
package/src/i18n/locales/en.ts
CHANGED
|
@@ -33,7 +33,9 @@ export function uiKitLabelsEn(numberLocale = "en-US"): UiKitLabels {
|
|
|
33
33
|
...d.measuredGrid,
|
|
34
34
|
points: (count) => (count === 1 ? "1 point" : `${n(count)} points`),
|
|
35
35
|
problems: (count) =>
|
|
36
|
-
count === 1
|
|
36
|
+
count === 1
|
|
37
|
+
? "1 cell is not a number"
|
|
38
|
+
: `${n(count)} cells are not numbers`,
|
|
37
39
|
},
|
|
38
40
|
dataTable: {
|
|
39
41
|
...d.dataTable,
|
|
@@ -51,9 +53,12 @@ export function uiKitLabelsEn(numberLocale = "en-US"): UiKitLabels {
|
|
|
51
53
|
combobox: {
|
|
52
54
|
...d.combobox,
|
|
53
55
|
selectedCount: (count) => `${n(count)} selected`,
|
|
54
|
-
resultCount: (count) =>
|
|
56
|
+
resultCount: (count) =>
|
|
57
|
+
count === 1 ? "1 result" : `${n(count)} results`,
|
|
55
58
|
minChars: (count) =>
|
|
56
|
-
count === 1
|
|
59
|
+
count === 1
|
|
60
|
+
? "Type at least 1 character"
|
|
61
|
+
: `Type at least ${n(count)} characters`,
|
|
57
62
|
},
|
|
58
63
|
multiSelect: {
|
|
59
64
|
...d.multiSelect,
|
|
@@ -81,7 +86,9 @@ export function uiKitLabelsEn(numberLocale = "en-US"): UiKitLabels {
|
|
|
81
86
|
`“${name}” was not added: at most ${n(maxFiles)} ${maxFiles === 1 ? "file" : "files"}`,
|
|
82
87
|
rejectedMany: (count) => `${n(count)} files were not added`,
|
|
83
88
|
rejectedPick: (count) =>
|
|
84
|
-
count === 1
|
|
89
|
+
count === 1
|
|
90
|
+
? "The file was not added"
|
|
91
|
+
: `None of the ${n(count)} files were added`,
|
|
85
92
|
selected: (count, firstName) =>
|
|
86
93
|
count === 1 ? `“${firstName}” selected` : `${n(count)} files selected`,
|
|
87
94
|
},
|
|
@@ -123,12 +130,27 @@ export function uiKitLabelsEn(numberLocale = "en-US"): UiKitLabels {
|
|
|
123
130
|
characterCount: {
|
|
124
131
|
...d.characterCount,
|
|
125
132
|
count: (used, max) => `${n(used)} of ${n(max)} characters`,
|
|
126
|
-
remaining: (left) =>
|
|
133
|
+
remaining: (left) =>
|
|
134
|
+
left === 1 ? "1 character left" : `${n(left)} characters left`,
|
|
127
135
|
},
|
|
128
136
|
ibanInput: {
|
|
129
137
|
...d.ibanInput,
|
|
130
138
|
length: (actual, expected) =>
|
|
131
139
|
`An IBAN from this country has ${n(expected)} characters — this one has ${n(actual)}.`,
|
|
132
140
|
},
|
|
141
|
+
columnMapper: {
|
|
142
|
+
...d.columnMapper,
|
|
143
|
+
summary: (columns, rows) =>
|
|
144
|
+
`${n(columns)} ${columns === 1 ? "column" : "columns"}, ${n(rows)} ${rows === 1 ? "row" : "rows"}`,
|
|
145
|
+
unreadCount: (count) =>
|
|
146
|
+
count === 1
|
|
147
|
+
? "1 line could not be read"
|
|
148
|
+
: `${n(count)} lines could not be read`,
|
|
149
|
+
unreadMore: (count) => `…and ${n(count)} more`,
|
|
150
|
+
previewOf: (shown, total) =>
|
|
151
|
+
shown === 1
|
|
152
|
+
? `The first of ${n(total)} rows`
|
|
153
|
+
: `The first ${n(shown)} of ${n(total)} rows`,
|
|
154
|
+
},
|
|
133
155
|
};
|
|
134
156
|
}
|
package/src/i18n/locales/es.ts
CHANGED
|
@@ -26,6 +26,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
26
26
|
attachmentRemoveFile: (name) => `Quitar ${name}`,
|
|
27
27
|
attachmentLimit: (max) => `Máximo ${n(max)} ${max === 1 ? "adjunto" : "adjuntos"}: quite uno para añadir otro.`,
|
|
28
28
|
attachmentUploading: "Subiendo…",
|
|
29
|
+
attachmentUploadFailed: (name) => `No se ha podido subir «${name}»`,
|
|
29
30
|
},
|
|
30
31
|
feedbackDialog: {
|
|
31
32
|
title: "Enviar comentarios",
|
|
@@ -330,6 +331,9 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
330
331
|
password: "Contraseña",
|
|
331
332
|
phrase: (phrase) => `Escriba «${phrase}» para confirmar`,
|
|
332
333
|
acknowledge: "He leído lo que hace esta acción y deseo continuar.",
|
|
334
|
+
needsPhrase: (phrase) => `Escriba «${phrase}» para confirmar`,
|
|
335
|
+
needsAcknowledge: "Marque la casilla para confirmar",
|
|
336
|
+
needsPassword: "Introduzca su contraseña para confirmar",
|
|
333
337
|
},
|
|
334
338
|
tabs: {
|
|
335
339
|
add: "Añadir pestaña",
|
|
@@ -680,6 +684,43 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
680
684
|
inflow: "Entrada",
|
|
681
685
|
direction: (current, next) => `Dirección: ${current} — cambiar a ${next}`,
|
|
682
686
|
},
|
|
687
|
+
columnMapper: {
|
|
688
|
+
paste: "Pegar una tabla",
|
|
689
|
+
pasteHint:
|
|
690
|
+
"Copie las filas de una hoja de cálculo y péguelas aquí, o suelte un archivo CSV o de texto.",
|
|
691
|
+
chooseFile: "Elegir un archivo",
|
|
692
|
+
readError: (name) => `No se ha podido leer «${name}»`,
|
|
693
|
+
headerRow: "La primera línea contiene los nombres de las columnas",
|
|
694
|
+
summary: (columns, rows) =>
|
|
695
|
+
`${n(columns)} ${plural(columns, "columna", "columnas")}, ${n(rows)} ${plural(rows, "fila", "filas")}`,
|
|
696
|
+
// Fragments of the summary line. "Separado por…" would have to agree with a noun the
|
|
697
|
+
// line does not name, so the separator is stated as a value.
|
|
698
|
+
separatorSemicolon: "separador: punto y coma",
|
|
699
|
+
separatorComma: "separador: coma",
|
|
700
|
+
separatorTab: "separador: tabulación",
|
|
701
|
+
separatorSpace: "separador: espacio",
|
|
702
|
+
// The examples stay as written: they show the convention, not the reader's locale.
|
|
703
|
+
decimalComma: "coma decimal (1,5)",
|
|
704
|
+
decimalPoint: "punto decimal (1.5)",
|
|
705
|
+
unreadCount: (count) =>
|
|
706
|
+
count === 1 ? "No se ha podido leer 1 línea" : `No se han podido leer ${n(count)} líneas`,
|
|
707
|
+
unreadLine: (line) => `No se pudo leer la línea ${line}`,
|
|
708
|
+
unreadMore: (count) => `…y ${n(count)} más`,
|
|
709
|
+
noRows: "Ninguna línea de este texto se puede leer como una fila de la tabla.",
|
|
710
|
+
table: "Columnas y sus funciones",
|
|
711
|
+
columnN: (column) => `Columna ${column}`,
|
|
712
|
+
roleOf: (column) => `¿Qué contiene la columna «${column}»?`,
|
|
713
|
+
ignore: "Ignorar",
|
|
714
|
+
requiredRole: (role) => `${role} (obligatorio)`,
|
|
715
|
+
previewOf: (shown, total) =>
|
|
716
|
+
shown === 1
|
|
717
|
+
? `La primera de ${n(total)} filas`
|
|
718
|
+
: `Las primeras ${n(shown)} de ${n(total)} filas`,
|
|
719
|
+
// `roles` arrives joined with "o" ("Debe o Haber").
|
|
720
|
+
oneOf: (roles) => `${roles} (a elegir)`,
|
|
721
|
+
// "Falta" + infinitive: no verb to agree with however many roles follow.
|
|
722
|
+
missing: (roles) => `Falta asignar: ${roles}.`,
|
|
723
|
+
},
|
|
683
724
|
translationReview: {
|
|
684
725
|
statusMissing: "Falta",
|
|
685
726
|
statusUnreviewed: "Sin revisar",
|
package/src/i18n/locales/fr.ts
CHANGED
|
@@ -26,6 +26,7 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
26
26
|
attachmentRemoveFile: (name) => `Retirer ${name}`,
|
|
27
27
|
attachmentLimit: (max) => `${n(max)} ${max === 1 ? "pièce jointe" : "pièces jointes"} au maximum — retirez-en une pour en ajouter une autre.`,
|
|
28
28
|
attachmentUploading: "Envoi en cours…",
|
|
29
|
+
attachmentUploadFailed: (name) => `«\u202f${name}\u202f» n’a pas pu être envoyé`,
|
|
29
30
|
},
|
|
30
31
|
feedbackDialog: {
|
|
31
32
|
title: "Envoyer un retour",
|
|
@@ -339,6 +340,9 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
339
340
|
password: "Mot de passe",
|
|
340
341
|
phrase: (phrase) => `Saisissez «\u202f${phrase}\u202f» pour confirmer`,
|
|
341
342
|
acknowledge: "J’ai lu ce que fait cette action et je souhaite continuer.",
|
|
343
|
+
needsPhrase: (phrase) => `Saisissez «\u202f${phrase}\u202f» pour confirmer`,
|
|
344
|
+
needsAcknowledge: "Cochez la case pour confirmer",
|
|
345
|
+
needsPassword: "Saisissez votre mot de passe pour confirmer",
|
|
342
346
|
},
|
|
343
347
|
tabs: {
|
|
344
348
|
add: "Ajouter un onglet",
|
|
@@ -696,6 +700,44 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
696
700
|
inflow: "Entrée",
|
|
697
701
|
direction: (current, next) => `Sens\u00a0: ${current} — passer à ${next}`,
|
|
698
702
|
},
|
|
703
|
+
columnMapper: {
|
|
704
|
+
paste: "Coller un tableau",
|
|
705
|
+
pasteHint:
|
|
706
|
+
"Copiez les lignes d’un tableur et collez-les ici, ou déposez un fichier CSV ou texte.",
|
|
707
|
+
chooseFile: "Choisir un fichier",
|
|
708
|
+
readError: (name) => `«\u202f${name}\u202f» n’a pas pu être lu`,
|
|
709
|
+
headerRow: "La première ligne contient les noms des colonnes",
|
|
710
|
+
summary: (columns, rows) =>
|
|
711
|
+
`${n(columns)} ${plural(columns, "colonne", "colonnes")}, ${n(rows)} ${plural(rows, "ligne", "lignes")}`,
|
|
712
|
+
// Fragments of the summary line. "Séparé par…" would have to agree with a noun the
|
|
713
|
+
// line does not name, so the separator is stated as a value.
|
|
714
|
+
separatorSemicolon: "séparateur\u00a0: point-virgule",
|
|
715
|
+
separatorComma: "séparateur\u00a0: virgule",
|
|
716
|
+
separatorTab: "séparateur\u00a0: tabulation",
|
|
717
|
+
separatorSpace: "séparateur\u00a0: espace",
|
|
718
|
+
// The examples stay as written: they show the convention, not the reader's locale.
|
|
719
|
+
decimalComma: "virgule décimale (1,5)",
|
|
720
|
+
decimalPoint: "point décimal (1.5)",
|
|
721
|
+
unreadCount: (count) =>
|
|
722
|
+
count < 2
|
|
723
|
+
? `${n(count)} ligne n’a pas pu être lue`
|
|
724
|
+
: `${n(count)} lignes n’ont pas pu être lues`,
|
|
725
|
+
unreadLine: (line) => `La ligne ${line} n\u2019a pas pu être lue`,
|
|
726
|
+
unreadMore: (count) => `…et ${n(count)} ${plural(count, "autre", "autres")}`,
|
|
727
|
+
noRows: "Aucune ligne de ce texte ne se lit comme une ligne du tableau.",
|
|
728
|
+
table: "Colonnes et leurs rôles",
|
|
729
|
+
columnN: (column) => `Colonne ${column}`,
|
|
730
|
+
roleOf: (column) => `Que contient la colonne «\u202f${column}\u202f»\u202f?`,
|
|
731
|
+
ignore: "Ignorer",
|
|
732
|
+
requiredRole: (role) => `${role} (obligatoire)`,
|
|
733
|
+
previewOf: (shown, total) =>
|
|
734
|
+
shown < 2
|
|
735
|
+
? `La première ligne sur ${n(total)}`
|
|
736
|
+
: `Les ${n(shown)} premières lignes sur ${n(total)}`,
|
|
737
|
+
// `roles` arrives joined with "ou" ("Débit ou Crédit").
|
|
738
|
+
oneOf: (roles) => `${roles} (au choix)`,
|
|
739
|
+
missing: (roles) => `Il manque encore\u00a0: ${roles}.`,
|
|
740
|
+
},
|
|
699
741
|
translationReview: {
|
|
700
742
|
statusMissing: "Manquant",
|
|
701
743
|
statusUnreviewed: "Non relu",
|
package/src/i18n/locales/hu.ts
CHANGED
|
@@ -25,6 +25,8 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
25
25
|
attachmentRemoveFile: (name) => `${name} eltávolítása`,
|
|
26
26
|
attachmentLimit: (max) => `Legfeljebb ${n(max)} melléklet – egy újabbhoz távolítson el egyet.`,
|
|
27
27
|
attachmentUploading: "Feltöltés…",
|
|
28
|
+
// Opens with the quoted name, as `filePicker`'s refusals: no a/az has to agree with it.
|
|
29
|
+
attachmentUploadFailed: (name) => `„${name}”: a feltöltés nem sikerült`,
|
|
28
30
|
},
|
|
29
31
|
feedbackDialog: {
|
|
30
32
|
title: "Visszajelzés küldése",
|
|
@@ -330,6 +332,9 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
330
332
|
// Phrase after a colon, so no article has to agree with it.
|
|
331
333
|
phrase: (phrase) => `A megerősítéshez írja be: „${phrase}”`,
|
|
332
334
|
acknowledge: "Elolvastam, mit eredményez ez a művelet, és folytatni szeretném.",
|
|
335
|
+
needsPhrase: (phrase) => `A megerősítéshez írja be: „${phrase}”`,
|
|
336
|
+
needsAcknowledge: "A megerősítéshez jelölje be a négyzetet",
|
|
337
|
+
needsPassword: "A megerősítéshez adja meg a jelszavát",
|
|
333
338
|
},
|
|
334
339
|
tabs: {
|
|
335
340
|
add: "Lap hozzáadása",
|
|
@@ -686,6 +691,38 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
686
691
|
inflow: "Bevétel",
|
|
687
692
|
direction: (current, next) => `Irány: ${current} – váltás erre: ${next}`,
|
|
688
693
|
},
|
|
694
|
+
columnMapper: {
|
|
695
|
+
paste: "Táblázat beillesztése",
|
|
696
|
+
pasteHint:
|
|
697
|
+
"Másolja ki a sorokat egy táblázatkezelőből, és illessze be ide, vagy húzzon ide egy CSV- vagy szövegfájlt.",
|
|
698
|
+
chooseFile: "Fájl kiválasztása",
|
|
699
|
+
readError: (name) => `„${name}”: a fájl nem olvasható`,
|
|
700
|
+
headerRow: "Az első sor az oszlopok nevét tartalmazza",
|
|
701
|
+
// No plural after a numeral (convention 2).
|
|
702
|
+
summary: (columns, rows) => `${n(columns)} oszlop, ${n(rows)} sor`,
|
|
703
|
+
separatorSemicolon: "pontosvesszővel elválasztva",
|
|
704
|
+
separatorComma: "vesszővel elválasztva",
|
|
705
|
+
separatorTab: "tabulátorral elválasztva",
|
|
706
|
+
separatorSpace: "szóközzel elválasztva",
|
|
707
|
+
// The examples stay as written: they show the convention, not the reader's locale.
|
|
708
|
+
decimalComma: "tizedesvessző (1,5)",
|
|
709
|
+
decimalPoint: "tizedespont (1.5)",
|
|
710
|
+
unreadCount: (count) => `${n(count)} sor nem olvasható`,
|
|
711
|
+
unreadLine: (line) => `A(z) ${line}. sor nem olvasható`,
|
|
712
|
+
unreadMore: (count) => `…és még ${n(count)}`,
|
|
713
|
+
noRows: "A szöveg egyetlen sora sem olvasható a táblázat soraként.",
|
|
714
|
+
table: "Oszlopok és szerepük",
|
|
715
|
+
columnN: (column) => `${column}. oszlop`,
|
|
716
|
+
// The name after a colon, so no article or case ending has to agree with it.
|
|
717
|
+
roleOf: (column) => `Mit tartalmaz ez az oszlop: „${column}”?`,
|
|
718
|
+
ignore: "Kihagyás",
|
|
719
|
+
requiredRole: (role) => `${role} (kötelező)`,
|
|
720
|
+
// "(összesen N)", as `dataTable.pageChanged`: both numerals stay bare (convention 3).
|
|
721
|
+
previewOf: (shown, total) => `Az első ${n(shown)} sor (összesen ${n(total)})`,
|
|
722
|
+
// `roles` arrives joined with "vagy" ("Tartozik vagy Követel").
|
|
723
|
+
oneOf: (roles) => `${roles} (valamelyik)`,
|
|
724
|
+
missing: (roles) => `Még hiányzik: ${roles}.`,
|
|
725
|
+
},
|
|
689
726
|
translationReview: {
|
|
690
727
|
statusMissing: "Hiányzik",
|
|
691
728
|
statusUnreviewed: "Nincs ellenőrizve",
|