@eifi1/ui-kit 0.24.1 → 0.25.1
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 +6 -6
- package/dist/chart.d.ts +2 -2
- package/dist/components/account-chips.d.ts +1 -1
- package/dist/components/amount-input.d.ts +2 -2
- package/dist/components/button-group.d.ts +2 -2
- package/dist/components/calculator.d.ts +2 -2
- package/dist/components/column-mapper.d.ts +28 -9
- package/dist/components/column-mapper.js +63 -77
- package/dist/components/column-mapper.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +2 -2
- package/dist/components/copy-button.d.ts +2 -2
- package/dist/components/danger-confirm.d.ts +2 -2
- package/dist/components/data-table-cells.d.ts +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table-labels.d.ts +1 -1
- package/dist/components/data-table-pagination.d.ts +1 -1
- package/dist/components/data-table-pagination.js +6 -1
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +7 -1
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/facing-pair.d.ts +2 -2
- package/dist/components/file-button.d.ts +2 -2
- package/dist/components/file-dropzone.d.ts +2 -2
- package/dist/components/form-actions.d.ts +2 -2
- package/dist/components/iban-input.d.ts +2 -2
- package/dist/components/language-select.d.ts +2 -2
- package/dist/components/money-field.d.ts +2 -2
- package/dist/components/number-field.d.ts +2 -2
- package/dist/components/number-input.d.ts +2 -2
- package/dist/components/numpad-sheet.d.ts +2 -2
- package/dist/components/phone-input.d.ts +2 -2
- package/dist/components/series-chart.d.ts +2 -2
- package/dist/components/settings-fields.d.ts +2 -2
- package/dist/components/share-card.d.ts +2 -2
- package/dist/components/swipeable-row.js +1 -1
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/table.d.ts +35 -1
- package/dist/components/table.js +4 -0
- package/dist/components/table.js.map +1 -1
- package/dist/components/text-link.d.ts +2 -2
- package/dist/components/time-input.d.ts +2 -2
- package/dist/components/tooltip.d.ts +103 -14
- package/dist/components/tooltip.js +194 -57
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/translation-review-editor.d.ts +9 -1
- package/dist/components/translation-review-editor.js +11 -1
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review-labels.d.ts +10 -0
- package/dist/components/translation-review-labels.js +5 -1
- package/dist/components/translation-review-labels.js.map +1 -1
- package/dist/components/translation-review.d.ts +145 -8
- package/dist/components/translation-review.js +372 -91
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/ui.d.ts +2 -2
- package/dist/components/ui.js +55 -18
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/{data-table-labels-B7OdnM0S.d.ts → data-table-labels-Cdn1QS2k.d.ts} +21 -1
- package/dist/data-table.d.ts +1 -1
- package/dist/feedback/feedback-attachment.d.ts +2 -2
- package/dist/feedback/feedback-dialog.d.ts +2 -2
- package/dist/feedback/feedback-dialog.js +6 -1
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +2 -2
- package/dist/feedback/feedback-inbox.js +2 -0
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +2 -2
- package/dist/{feedback-DOwPu-Il.d.ts → feedback-BXKH-ToU.d.ts} +32 -3
- package/dist/feedback.d.ts +2 -2
- package/dist/hooks/use-body-scroll-lock.js +16 -0
- package/dist/hooks/use-body-scroll-lock.js.map +1 -1
- package/dist/hooks/use-file-drop.d.ts +2 -2
- package/dist/hooks/use-search-param-state.d.ts +58 -3
- package/dist/hooks/use-search-param-state.js +107 -35
- package/dist/hooks/use-search-param-state.js.map +1 -1
- package/dist/i18n/defaults.d.ts +2 -2
- package/dist/i18n/german.d.ts +2 -2
- package/dist/i18n/german.js +8 -1
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +2 -2
- package/dist/i18n/languages.d.ts +2 -2
- package/dist/i18n/locales/de-CH.d.ts +2 -2
- package/dist/i18n/locales/en.d.ts +2 -2
- package/dist/i18n/locales/en.js +5 -1
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +2 -2
- package/dist/i18n/locales/es.js +7 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +2 -2
- package/dist/i18n/locales/fr.js +6 -1
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +2 -2
- package/dist/i18n/locales/hu.js +9 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +2 -2
- package/dist/i18n/locales/it.js +6 -1
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +2 -2
- package/dist/i18n/locales/zh.js +6 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +2 -2
- package/dist/i18n/review.js +11 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/strip-fade.d.ts +84 -5
- package/dist/lib/strip-fade.js +109 -11
- package/dist/lib/strip-fade.js.map +1 -1
- package/dist/lib/translation-review.d.ts +45 -1
- package/dist/lib/translation-review.js +38 -1
- package/dist/lib/translation-review.js.map +1 -1
- package/dist/rhf/fields.d.ts +2 -2
- package/dist/rhf/form.d.ts +2 -2
- package/dist/rhf.d.ts +2 -2
- package/dist/shell/app-shell.d.ts +2 -2
- package/dist/shell/top-bar-brand.d.ts +2 -2
- package/dist/shell.d.ts +2 -2
- package/dist/wizard/stepper-nav.d.ts +2 -2
- package/dist/wizard.d.ts +2 -2
- package/package.json +1 -1
- package/src/components/column-mapper.tsx +120 -113
- package/src/components/data-table-pagination.tsx +10 -1
- package/src/components/data-table.tsx +34 -1
- package/src/components/swipeable-row.tsx +1 -1
- package/src/components/table.tsx +39 -0
- package/src/components/tooltip.tsx +487 -104
- package/src/components/translation-review-editor.tsx +21 -1
- package/src/components/translation-review-labels.ts +17 -0
- package/src/components/translation-review.tsx +657 -109
- package/src/components/ui.tsx +104 -4
- package/src/feedback/feedback-dialog.tsx +21 -0
- package/src/feedback/feedback-inbox.tsx +19 -2
- package/src/hooks/use-body-scroll-lock.ts +25 -0
- package/src/hooks/use-search-param-state.ts +283 -41
- package/src/i18n/german.ts +10 -0
- package/src/i18n/locales/en.ts +7 -0
- package/src/i18n/locales/es.ts +9 -0
- package/src/i18n/locales/fr.ts +9 -0
- package/src/i18n/locales/hu.ts +11 -0
- package/src/i18n/locales/it.ts +9 -0
- package/src/i18n/locales/zh.ts +8 -0
- package/src/i18n/review.ts +11 -0
- package/src/index.ts +12 -0
- package/src/lib/strip-fade.ts +220 -15
- package/src/lib/translation-review.ts +85 -0
|
@@ -27,6 +27,30 @@ import 'lucide-react';
|
|
|
27
27
|
* write to the server's batch limit is the app's; the panel sends one call per action.
|
|
28
28
|
*/
|
|
29
29
|
type MaybePromise = void | Promise<unknown>;
|
|
30
|
+
/** What asked for a write — see {@link TranslationReviewSaveInfo}. */
|
|
31
|
+
type TranslationReviewOrigin = "editor" | "row" | "swipe" | "group" | "selection" | "undo";
|
|
32
|
+
/**
|
|
33
|
+
* The second argument of `onSave` and `onClear` (0.25): where the write came from, and
|
|
34
|
+
* whether the panel answers it with a toast of its own.
|
|
35
|
+
*
|
|
36
|
+
* WHY THE APP IS TOLD. keksdose and kastlan toast "Saved" from their mutation on every
|
|
37
|
+
* save. With {@link TranslationReviewPanelProps.undo} on, an approval is answered by the
|
|
38
|
+
* kit's Undo toast instead — and a reviewer swiping through a list then read two toasts
|
|
39
|
+
* per card. The app skips its own where `toasted` is true:
|
|
40
|
+
*
|
|
41
|
+
* onSave={(writes, { toasted }) => save.mutateAsync({ items: writes.map(toApiWrite), quiet: toasted })}
|
|
42
|
+
*
|
|
43
|
+
* An app that ignores the argument keeps working; it only says "Saved" twice.
|
|
44
|
+
*/
|
|
45
|
+
interface TranslationReviewSaveInfo {
|
|
46
|
+
/** The open editor, a row's approve button, a swipe on a phone card, a group's
|
|
47
|
+
* "Approve unreviewed", the selection's bulk bar, or an Undo pressed on the toast. */
|
|
48
|
+
origin: TranslationReviewOrigin;
|
|
49
|
+
/** The panel shows its own toast for this write (an approval's Undo toast). */
|
|
50
|
+
toasted: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** How {@link TranslationReviewPanelProps.groupBy} names a row's group. */
|
|
53
|
+
type TranslationReviewGroupBy = "namespace" | "source" | ((row: TranslationRow) => string);
|
|
30
54
|
interface TranslationReviewPanelProps {
|
|
31
55
|
/** One locale's rows, from `translationRows`. */
|
|
32
56
|
rows: readonly TranslationRow[];
|
|
@@ -35,10 +59,12 @@ interface TranslationReviewPanelProps {
|
|
|
35
59
|
/** The reference language's own name — the reference column's header. */
|
|
36
60
|
referenceLabel: string;
|
|
37
61
|
/** Store verdicts: one for an editor or a row's approve button, many for a bulk
|
|
38
|
-
* approve. Left out (or `readOnly`): nothing can be changed.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
* approve. Left out (or `readOnly`): nothing can be changed. The second argument
|
|
63
|
+
* says where the write came from ({@link TranslationReviewSaveInfo}). */
|
|
64
|
+
onSave?: (writes: TranslationReviewWrite[], info: TranslationReviewSaveInfo) => MaybePromise;
|
|
65
|
+
/** Clear verdicts — back to unreviewed. Left out: no reset, and an approval of a row
|
|
66
|
+
* that had no verdict cannot be undone. */
|
|
67
|
+
onClear?: (keys: TranslationReviewKey[], info: TranslationReviewSaveInfo) => MaybePromise;
|
|
42
68
|
/** A locale the viewer may read but not review: the rows and their verdicts, no
|
|
43
69
|
* actions, and a line saying so. */
|
|
44
70
|
readOnly?: boolean;
|
|
@@ -58,9 +84,18 @@ interface TranslationReviewPanelProps {
|
|
|
58
84
|
sourceLabels?: Readonly<Record<string, string>>;
|
|
59
85
|
/**
|
|
60
86
|
* Controlled filters — for an app that keeps them in the URL (keksdose's `?status=`,
|
|
61
|
-
* `?
|
|
87
|
+
* `?ns=`, `?q=`). Whatever is left out is the panel's own. Pair with `onFilterChange`.
|
|
88
|
+
*
|
|
89
|
+
* A field passed here is the app's, and the control shows what the app says: one the app
|
|
90
|
+
* passes but does not write back from `onFilterChange` is a control that does nothing.
|
|
91
|
+
* A development build warns about that once per field (0.25.1, Kurvenschmiede); a field
|
|
92
|
+
* left out entirely is fine — the panel keeps it.
|
|
62
93
|
*/
|
|
63
94
|
filter?: Partial<TranslationReviewFilter>;
|
|
95
|
+
/** Every filter, on every change — write them in ONE update: `useSearchParamsState`'s
|
|
96
|
+
* setter takes this object as it is (`filter={filter} onFilterChange={setFilter}`).
|
|
97
|
+
* Single `useSearchParamState` setters compose since 0.25; before, four in a row
|
|
98
|
+
* clobbered each other (keksdose live #378). */
|
|
64
99
|
onFilterChange?: (filter: TranslationReviewFilter) => void;
|
|
65
100
|
/** The progress bar over the filters. Default true. */
|
|
66
101
|
progress?: boolean;
|
|
@@ -72,6 +107,101 @@ interface TranslationReviewPanelProps {
|
|
|
72
107
|
formatDate?: (iso: string) => string;
|
|
73
108
|
/** Turns a callback's rejection into words. Default {@link TranslationReviewLabels.failed}. */
|
|
74
109
|
formatError?: (error: unknown) => ReactNode;
|
|
110
|
+
/**
|
|
111
|
+
* Swipe the phone cards (0.25, keksdose live #377 — Marcel reviewing on a phone): toward
|
|
112
|
+
* the reading END to approve, toward the START for "Needs a change", which OPENS the
|
|
113
|
+
* editor with the cursor in the wording rather than sending the string back blind — a
|
|
114
|
+
* verdict without a note or a better wording tells whoever fixes it nothing. In a
|
|
115
|
+
* right-to-left page the two sides mirror with the reading direction.
|
|
116
|
+
*
|
|
117
|
+
* DataTable's swipe sides (`mobileSwipeActions`) on {@link SwipeableRow}: the same
|
|
118
|
+
* gesture, the same feedback, and the same keyboard path — every swipe is also a real
|
|
119
|
+
* button, read out and reachable by Tab, so the gesture is a shortcut and never the only
|
|
120
|
+
* way. A row has no swipe while the editor under it is open, while its own write is out,
|
|
121
|
+
* under a {@link WriteLockProvider} lock, in a `readOnly` locale, and toward "Approve"
|
|
122
|
+
* where there is nothing to approve (a missing string, an approved one). A reviewer
|
|
123
|
+
* limited to `areas` never sees a row outside them, so never swipes one.
|
|
124
|
+
*
|
|
125
|
+
* Off by default, so no existing page gains a gesture on the bump. Phones only; the
|
|
126
|
+
* desktop table keeps its approve button.
|
|
127
|
+
*/
|
|
128
|
+
swipe?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Answer every approval with the kit's Undo toast (`toast.undo`): a row's button, a
|
|
131
|
+
* swipe, the editor's Approve, a group's and the selection's bulk approve. Undo stores
|
|
132
|
+
* again what the rows said before ({@link reviewUndo}) — or clears them, for rows that
|
|
133
|
+
* had no verdict, which needs `onClear` (without it the toast reports and offers
|
|
134
|
+
* nothing). A batch has ONE Undo.
|
|
135
|
+
*
|
|
136
|
+
* Default: on with `swipe` or `groupBy` — the two ways to approve in one movement or many
|
|
137
|
+
* rows at once bring their way back — and off otherwise, so an existing page does not
|
|
138
|
+
* gain a toast on the bump. Needs the app's `<Toaster>`. Tell the app's own "Saved"
|
|
139
|
+
* toast apart with the `toasted` flag ({@link TranslationReviewSaveInfo}).
|
|
140
|
+
*/
|
|
141
|
+
undo?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Group the strings under a header per area (0.25, keksdose live #377: *"grouping to the
|
|
144
|
+
* translation review entries for faster reviewing"*): `"namespace"` — the row's
|
|
145
|
+
* `namespace`, which `translationRows` derives from the key (`budget`, `kit.dataTable`
|
|
146
|
+
* with keksdose's `namespaceOf`) — `"source"`, or a function of the row.
|
|
147
|
+
*
|
|
148
|
+
* Each group is a section with a heading ({@link groupHeadingAs}): its name, "n
|
|
149
|
+
* unreviewed / total", and "Approve unreviewed (n)", which approves the group's rows
|
|
150
|
+
* nobody has given a verdict ({@link unreviewedRows}) under the same rules as one
|
|
151
|
+
* approval — write lock, `readOnly`, one write at a time — with one Undo for the batch.
|
|
152
|
+
* A batch larger than `pageSize` asks first, inside the opened group: more than a page
|
|
153
|
+
* is more than the reviewer can have had on screen.
|
|
154
|
+
*
|
|
155
|
+
* WHAT IT MEANS FOR THE FILTERS, THE SORT AND THE PAGES. The filters narrow the rows
|
|
156
|
+
* first, then the rows are grouped: a header counts what the filters show in it (so
|
|
157
|
+
* "Approve unreviewed" never takes a row the reviewer filtered away), and an area with
|
|
158
|
+
* nothing left is not shown. Groups stand in the order their first string has in the
|
|
159
|
+
* reference; a column sort orders the rows INSIDE every group alike. Each group pages
|
|
160
|
+
* on its own, `pageSize` rows at a time — a header then always stands over its own
|
|
161
|
+
* rows, and paging one area does not move another — rather than one pager cutting
|
|
162
|
+
* through the headers. `storageKey` keeps persisting the ungrouped table only.
|
|
163
|
+
*
|
|
164
|
+
* Groups fold (each on its own, remembered while the panel lives), and a folded group's
|
|
165
|
+
* rows are not rendered at all — only its header. Which groups start open is
|
|
166
|
+
* {@link defaultGroupsOpen}: by default, on a phone they start folded when there are
|
|
167
|
+
* several — the headers are then the area list, and the reviewer opens the one to work
|
|
168
|
+
* through — and on a wide screen they start open while that is cheap (see there).
|
|
169
|
+
*/
|
|
170
|
+
groupBy?: TranslationReviewGroupBy;
|
|
171
|
+
/**
|
|
172
|
+
* Which groups start open under {@link groupBy} (0.25.1). A group the reviewer opens or
|
|
173
|
+
* folds keeps that; this is what every other group follows.
|
|
174
|
+
*
|
|
175
|
+
* - `"auto"` (default): on a phone, open when there is one group and folded when there
|
|
176
|
+
* are several, as in 0.25.0. On a wide screen, open while opening every group renders
|
|
177
|
+
* at most 100 rows (each group shows up to `pageSize` of them; the budget is one page
|
|
178
|
+
* where `pageSize` is larger) — and folded above that, the headers then being the area
|
|
179
|
+
* list, as on a phone.
|
|
180
|
+
* - `true`: every group starts open, on a phone too.
|
|
181
|
+
* - `false`: every group starts folded, on a wide screen too.
|
|
182
|
+
*
|
|
183
|
+
* WHY A BUDGET OF ROWS (keksdose, measured on 0.25.0): a wide screen opened EVERY group.
|
|
184
|
+
* keksdose's /translations has 122 areas and ~4700 strings — 122 tables and 2053 rows at
|
|
185
|
+
* once, ~46 000 elements, 5.2 s before the panel appeared and 2.5 s for a filter click
|
|
186
|
+
* to paint, against 50 rows and 0.34 s ungrouped; its page test went from 4 s to 146 s.
|
|
187
|
+
* kastlan (~31 areas, ~1300 rows open) and Kurvenschmiede (28, ~700) had the same page.
|
|
188
|
+
* What costs is the rows on screen, so the rule counts them rather than the groups:
|
|
189
|
+
* 100 rows is two of the panel's default pages — any one or two areas still open as
|
|
190
|
+
* before, however long, and so do a dozen small ones, or a search whose hits fall in
|
|
191
|
+
* many areas — while a whole catalogue starts as its list of areas: keksdose's shape
|
|
192
|
+
* in jsdom, 122 headers and ~2100 elements instead of ~44 000 (the ungrouped panel has
|
|
193
|
+
* ~1200). The rule follows the filters: narrow them and the groups open.
|
|
194
|
+
*
|
|
195
|
+
* A boolean rather than a controlled open state: the panel already keeps each group's
|
|
196
|
+
* own state, and an app that only wants "all open" or "all folded" should not have to
|
|
197
|
+
* keep a record of 122 flags to say it.
|
|
198
|
+
*/
|
|
199
|
+
defaultGroupsOpen?: boolean | "auto";
|
|
200
|
+
/** A group's name. Default: `sourceLabels` for `groupBy="source"`, else the key. */
|
|
201
|
+
groupLabel?: (group: string) => string;
|
|
202
|
+
/** The level of the group headings. Default `h2`: the panel is a page's body, under
|
|
203
|
+
* the page's `h1`. */
|
|
204
|
+
groupHeadingAs?: "h2" | "h3" | "h4";
|
|
75
205
|
className?: string;
|
|
76
206
|
labels?: Partial<TranslationReviewLabels>;
|
|
77
207
|
}
|
|
@@ -87,8 +217,15 @@ interface TranslationReviewPanelProps {
|
|
|
87
217
|
* Bulk approve takes the selected rows that are not approved yet and have a text:
|
|
88
218
|
* approving an absent string says nothing, and re-approving one says it again. On a
|
|
89
219
|
* phone the table has no checkboxes, so "Select all shown" selects what the filters
|
|
90
|
-
* show — filter to `Unreviewed` in one area, read, select, approve.
|
|
220
|
+
* show — filter to `Unreviewed` in one area, read, select, approve. With `groupBy`, a
|
|
221
|
+
* group's own "Approve unreviewed" is the shorter way, and with `swipe` a card is approved
|
|
222
|
+
* by a swipe.
|
|
223
|
+
*
|
|
224
|
+
* The panel's writes go out ONE AT A TIME, in the order they were asked for: two writes on
|
|
225
|
+
* one locale's verdicts can answer out of order, and an Undo must not overtake the
|
|
226
|
+
* approval it takes back. A swipe on the next card while one is out is queued rather than
|
|
227
|
+
* refused — a reviewer swiping down a list is faster than the server.
|
|
91
228
|
*/
|
|
92
|
-
declare function TranslationReviewPanel({ rows: rowsProp, localeLabel, referenceLabel, onSave, onClear, readOnly, areas, areaLabels, inArea, sourceLabels, filter: filterProp, onFilterChange, progress, pageSize, storageKey, formatDate, formatError, className, labels: labelsProp, }: TranslationReviewPanelProps): react.JSX.Element;
|
|
229
|
+
declare function TranslationReviewPanel({ rows: rowsProp, localeLabel, referenceLabel, onSave, onClear, readOnly, areas, areaLabels, inArea, sourceLabels, filter: filterProp, onFilterChange, progress, pageSize, storageKey, formatDate, formatError, swipe, undo: undoProp, groupBy, groupLabel, groupHeadingAs, defaultGroupsOpen, className, labels: labelsProp, }: TranslationReviewPanelProps): react.JSX.Element;
|
|
93
230
|
|
|
94
|
-
export { TranslationReviewLabels, TranslationReviewPanel, type TranslationReviewPanelProps };
|
|
231
|
+
export { type TranslationReviewGroupBy, TranslationReviewLabels, type TranslationReviewOrigin, TranslationReviewPanel, type TranslationReviewPanelProps, type TranslationReviewSaveInfo };
|