@eifi1/ui-kit 0.25.0 → 0.26.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 +3 -3
- package/dist/components/data-table.js +3 -2
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/swipeable-row.d.ts +5 -1
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/translation-review-labels.d.ts +4 -0
- package/dist/components/translation-review-labels.js +2 -1
- package/dist/components/translation-review-labels.js.map +1 -1
- package/dist/components/translation-review.d.ts +67 -7
- package/dist/components/translation-review.js +115 -29
- package/dist/components/translation-review.js.map +1 -1
- package/dist/hooks/use-search-param-state.d.ts +1 -1
- package/dist/hooks/use-search-param-state.js +8 -1
- package/dist/hooks/use-search-param-state.js.map +1 -1
- package/dist/i18n/german.js +1 -0
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/locales/en.js +1 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.js +1 -0
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +1 -0
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +1 -0
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +1 -0
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +1 -0
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +1 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/translation-review.d.ts +76 -1
- package/dist/lib/translation-review.js +30 -0
- package/dist/lib/translation-review.js.map +1 -1
- package/package.json +1 -1
- package/src/components/data-table.tsx +9 -2
- package/src/components/swipeable-row.tsx +5 -1
- package/src/components/translation-review-labels.ts +5 -0
- package/src/components/translation-review.tsx +275 -48
- package/src/hooks/use-search-param-state.ts +19 -4
- package/src/i18n/german.ts +1 -0
- package/src/i18n/locales/en.ts +1 -0
- package/src/i18n/locales/es.ts +1 -0
- package/src/i18n/locales/fr.ts +1 -0
- package/src/i18n/locales/hu.ts +1 -0
- package/src/i18n/locales/it.ts +1 -0
- package/src/i18n/locales/zh.ts +1 -0
- package/src/i18n/review.ts +1 -0
- package/src/index.ts +6 -0
- package/src/lib/translation-review.ts +109 -0
- package/tokens.css +4 -0
|
@@ -512,6 +512,115 @@ export function dropReviews<T extends TranslationReviewKey>(
|
|
|
512
512
|
return prev.filter((r) => !gone.has(`${r.locale}|${r.key}`));
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
+
// ── Swipe bindings ──────────────────────────────────────────────────────────────
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* What a phone card's swipe can be bound to in `TranslationReviewPanel`'s `swipe`
|
|
519
|
+
* (keksdose — Marcel's live #377 rework, 2026-10-03: *"Add the swipe options to be shown
|
|
520
|
+
* also to the settings /settings#interaction area where the other swipe options are
|
|
521
|
+
* defined"*). keksdose lets the user bind every list's swipes there — per side, a primary
|
|
522
|
+
* action at the first threshold and a secondary one at a longer drag — and lists each
|
|
523
|
+
* surface's ids in its `SWIPE_ACTIONS`; this is the translation list's, in the order a
|
|
524
|
+
* settings page offers them.
|
|
525
|
+
*
|
|
526
|
+
* - `approve` — the string is right as it stands. With the panel's Undo toast.
|
|
527
|
+
* - `edit` — open the editor with the cursor in the wording: "Needs a change" (or
|
|
528
|
+
* "Suggest translation" on a missing string). Writes nothing; the editor does.
|
|
529
|
+
* - `clear` — take the verdict back: unreviewed again. With the Undo toast, which stores
|
|
530
|
+
* the verdict again.
|
|
531
|
+
*
|
|
532
|
+
* THERE IS NO SEPARATE "needs a change". The editor has no verdict to preselect: Approve
|
|
533
|
+
* and "Needs a change" stand side by side in it, and "Needs a change" takes a note or a
|
|
534
|
+
* different wording — a verdict without either tells whoever fixes the string nothing, so
|
|
535
|
+
* a swipe never sends one blind (0.25). The one honest thing a "needs a change" swipe can
|
|
536
|
+
* do is therefore open the editor with the cursor in the wording — which is `edit`, and
|
|
537
|
+
* `edit` already says "Needs a change" on the card. A second id doing the same would arm
|
|
538
|
+
* a second threshold that does what the first already did: the duplicate keksdose's
|
|
539
|
+
* `resolveSwipePlan` drops for exactly that reason.
|
|
540
|
+
*/
|
|
541
|
+
export const TRANSLATION_REVIEW_SWIPE_ACTIONS = ["approve", "edit", "clear"] as const;
|
|
542
|
+
|
|
543
|
+
/** One of {@link TRANSLATION_REVIEW_SWIPE_ACTIONS}. */
|
|
544
|
+
export type TranslationReviewSwipeAction = (typeof TRANSLATION_REVIEW_SWIPE_ACTIONS)[number];
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Which swipe does what on a phone card — `TranslationReviewPanel`'s `swipe`. Each side is
|
|
548
|
+
* an ordered ladder, exactly as `SwipeableRow` and DataTable's `mobileSwipeActions` model
|
|
549
|
+
* one: index 0 commits at the first threshold, index 1 at the longer drag (and so on — the
|
|
550
|
+
* thresholds spread evenly over the card's width). A side left out, or empty, does not
|
|
551
|
+
* swipe.
|
|
552
|
+
*
|
|
553
|
+
* LOGICAL SIDES: `end` is a drag toward the reading end of the line — right in a
|
|
554
|
+
* left-to-right page, left in a right-to-left one — and `start` the other way, so one
|
|
555
|
+
* binding holds in both directions. An app whose settings store physical sides (keksdose's
|
|
556
|
+
* `right`/`left`) hands `right` as `end` for a left-to-right page.
|
|
557
|
+
*/
|
|
558
|
+
export interface TranslationReviewSwipeBinding {
|
|
559
|
+
/** A drag toward the reading START, nearest threshold first. */
|
|
560
|
+
start?: readonly TranslationReviewSwipeAction[];
|
|
561
|
+
/** A drag toward the reading END, nearest threshold first. */
|
|
562
|
+
end?: readonly TranslationReviewSwipeAction[];
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/** What `swipe={true}` means — 0.25's fixed mapping: approve toward the end, open the
|
|
566
|
+
* editor ("Needs a change") toward the start. A settings page's "reset" goes back here. */
|
|
567
|
+
export const DEFAULT_TRANSLATION_REVIEW_SWIPE: TranslationReviewSwipeBinding = Object.freeze({
|
|
568
|
+
start: Object.freeze(["edit"] as const),
|
|
569
|
+
end: Object.freeze(["approve"] as const),
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
/** The ladders one row actually offers, from a {@link TranslationReviewSwipeBinding}. */
|
|
573
|
+
export interface TranslationReviewSwipePlan {
|
|
574
|
+
start: TranslationReviewSwipeAction[];
|
|
575
|
+
end: TranslationReviewSwipeAction[];
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* The binding resolved against one row — keksdose's `resolveSwipePlan`, for this list.
|
|
580
|
+
* An id the row cannot offer DROPS OUT and the ladder closes up behind it, so the second
|
|
581
|
+
* stage becomes the first rather than the side going dead behind an unreachable first
|
|
582
|
+
* stage (or arming a threshold that does nothing):
|
|
583
|
+
*
|
|
584
|
+
* - `approve`: not on a missing string (nothing to approve) or an approved one (it would
|
|
585
|
+
* say it again) — the rows that have no approve button either;
|
|
586
|
+
* - `clear`: not without `canClear` (the app passed no `onClear`), and not on a row with
|
|
587
|
+
* no verdict to take back (unreviewed; missing with no suggestion);
|
|
588
|
+
* - `edit`: on every row;
|
|
589
|
+
* - an id named twice on one side: the second time (a longer drag to the same effect);
|
|
590
|
+
* - an id this version does not know (a binding stored by another version, an app's own
|
|
591
|
+
* "none" slot): dropped like one that does not apply.
|
|
592
|
+
*
|
|
593
|
+
* Only what the ROW decides. Whether the panel may write at all — `readOnly`, no
|
|
594
|
+
* `onSave`, a write lock, the row's own write still out — is the panel's, and then no
|
|
595
|
+
* side swipes.
|
|
596
|
+
*/
|
|
597
|
+
export function translationReviewSwipePlan(
|
|
598
|
+
binding: TranslationReviewSwipeBinding,
|
|
599
|
+
row: TranslationRow,
|
|
600
|
+
{ canClear = false }: { canClear?: boolean } = {},
|
|
601
|
+
): TranslationReviewSwipePlan {
|
|
602
|
+
const offers = (id: TranslationReviewSwipeAction): boolean => {
|
|
603
|
+
switch (id) {
|
|
604
|
+
case "approve":
|
|
605
|
+
return row.text !== "" && row.status !== "approved";
|
|
606
|
+
case "edit":
|
|
607
|
+
return true;
|
|
608
|
+
case "clear":
|
|
609
|
+
return canClear && row.review !== null;
|
|
610
|
+
default:
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
const side = (ids: readonly TranslationReviewSwipeAction[] | undefined): TranslationReviewSwipeAction[] => {
|
|
615
|
+
const out: TranslationReviewSwipeAction[] = [];
|
|
616
|
+
for (const id of ids ?? []) {
|
|
617
|
+
if (!out.includes(id) && offers(id)) out.push(id);
|
|
618
|
+
}
|
|
619
|
+
return out;
|
|
620
|
+
};
|
|
621
|
+
return { start: side(binding.start), end: side(binding.end) };
|
|
622
|
+
}
|
|
623
|
+
|
|
515
624
|
// ── Export ──────────────────────────────────────────────────────────────────────
|
|
516
625
|
|
|
517
626
|
/**
|
package/tokens.css
CHANGED
|
@@ -213,6 +213,9 @@
|
|
|
213
213
|
journey to the database, this one an ACTION's outcome. Emerald rather than the
|
|
214
214
|
money teal, so a "resolved" chip cannot be misread as an inflow. */
|
|
215
215
|
--success: #047857; /* emerald-700 */
|
|
216
|
+
/* Text on a `--success` fill (0.26: a swipe's approve panel) — white here, the
|
|
217
|
+
darkest emerald in dark mode, where the fill is a pastel and white text failed. */
|
|
218
|
+
--success-contrast: #ffffff;
|
|
216
219
|
--success-border: #6ee7b7; /* emerald-300 */
|
|
217
220
|
--success-bg: #d1fae5; /* emerald-100 */
|
|
218
221
|
}
|
|
@@ -237,6 +240,7 @@
|
|
|
237
240
|
--info-bg: rgba(12, 74, 110, 0.25);
|
|
238
241
|
|
|
239
242
|
--success: #6ee7b7; /* emerald-300 */
|
|
243
|
+
--success-contrast: #022c22; /* emerald-950 */
|
|
240
244
|
--success-border: rgba(4, 120, 87, 0.6);
|
|
241
245
|
--success-bg: rgba(6, 78, 59, 0.25);
|
|
242
246
|
}
|