create-principles-disciple 1.120.0 → 1.120.2

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.
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import { Check, X, CheckCheck, XCircle } from "lucide-react";
5
+ import { formatDate } from "../../utils/format-date.js";
5
6
  import { Badge } from "../../components/ui/badge.js";
6
7
  import { Tooltip, TooltipContent, TooltipTrigger, } from "../../components/ui/tooltip.js";
7
8
  // ── Helpers ─────────────────────────────────────────────────────────────────
@@ -31,5 +32,5 @@ export function PendingTermsSection({ terms, onConfirm, onIgnore, onConfirmAll,
31
32
  };
32
33
  return (_jsxs("section", { children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-[15px] font-semibold text-ink", children: t("pages.signalKeywords.pendingTerms.title") }), _jsx("p", { className: "mt-0.5 text-[12px] text-ink-4 leading-[1.5]", children: t("pages.signalKeywords.pendingTerms.subtitle") })] }), _jsx("span", { className: "text-[12px] text-ink-4 tabular-nums", children: t("pages.signalKeywords.nTerms", { count: terms.length }) })] }), terms.length > 0 && hasBatchOps && (_jsxs("div", { className: "flex items-center justify-between mb-3 px-3 py-2 bg-surface border border-line rounded-[4px]", children: [_jsx("span", { className: "text-[12px] text-ink-4", children: selected.size > 0
33
34
  ? t("pages.signalKeywords.selectedNOfTotal", { selected: selected.size, total: terms.length })
34
- : t("pages.signalKeywords.nTermsPendingReview", { count: terms.length }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", onClick: () => onConfirmAll?.(), disabled: true, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[12px] font-medium text-green bg-green/10 rounded-[3px] disabled:opacity-30 disabled:cursor-not-allowed hover:bg-green/20 transition-colors", children: [_jsx(CheckCheck, { className: "h-3.5 w-3.5" }), t("pages.signalKeywords.pendingTerms.confirmBatch")] }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", onClick: () => onIgnoreAll?.(), disabled: true, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[12px] font-medium text-ink-4 bg-surface border border-line rounded-[3px] disabled:opacity-30 disabled:cursor-not-allowed hover:text-danger hover:border-danger/30 transition-colors", children: [_jsx(XCircle, { className: "h-3.5 w-3.5" }), t("pages.signalKeywords.pendingTerms.ignoreBatch")] }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] })] })] })), terms.length === 0 ? (_jsxs("div", { className: "px-4 py-12 text-center text-[13px] text-ink-4 border border-dashed border-line-2 rounded-[4px]", children: [_jsx("p", { children: t("pages.signalKeywords.pendingTerms.empty") }), _jsx("p", { className: "mt-2 text-[12px]", children: t("pages.signalKeywords.pendingTerms.emptyDescription") })] })) : (_jsxs("div", { className: "border border-line rounded-[4px] overflow-hidden", children: [_jsxs("div", { className: "grid grid-cols-[24px_1fr_100px_90px_1fr_100px] gap-3 px-4 py-2.5 bg-surface text-[11px] font-medium text-ink-4 uppercase tracking-[var(--tracking-wide)] border-b border-line items-center", children: [_jsx("span", {}), _jsx("span", { children: t("pages.signalKeywords.colTerm") }), _jsx("span", { children: t("pages.signalKeywords.colCategory") }), _jsx("span", { children: t("pages.signalKeywords.colPrecision") }), _jsx("span", { children: t("pages.signalKeywords.colReason") }), hasRowOps && _jsx("span", { className: "text-right", children: t("pages.signalKeywords.colActions") })] }), terms.map((term) => (_jsxs("div", { className: "grid grid-cols-[24px_1fr_100px_90px_1fr_100px] gap-3 px-4 py-3 items-start border-b border-line last:border-b-0 hover:bg-surface/50 transition-colors", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("input", { type: "checkbox", checked: selected.has(term.term), onChange: () => toggleSelected(term.term), disabled: true, className: "mt-0.5 h-3.5 w-3.5 rounded border-line text-gov disabled:opacity-30 disabled:cursor-not-allowed" }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }), _jsxs("div", { className: "min-w-0", children: [_jsx("span", { className: "text-[13px] text-ink font-medium block truncate", children: term.term }), _jsx("span", { className: "text-[11px] text-ink-4 mt-0.5 block", children: new Date(term.discoveredAt).toLocaleDateString(i18n.language) })] }), _jsx(Badge, { variant: term.suggestedCategory === "correction" ? "default" : "amber", children: categoryLabel[term.suggestedCategory] ?? term.suggestedCategory }), _jsx("span", { className: "text-[12px] text-ink-3", children: term.suggestedPrecision === "high" ? (_jsx("span", { className: "text-green", children: t("pages.signalKeywords.precisionHigh") })) : (_jsx("span", { className: "text-amber", children: t("pages.signalKeywords.precisionAmbiguous") })) }), _jsx("span", { className: "text-[12px] text-ink-3 leading-[1.5] line-clamp-2", children: term.reason }), hasRowOps && (_jsxs("div", { className: "flex items-center justify-end gap-1", children: [onConfirm && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => onConfirm(term), disabled: true, className: "p-1.5 text-ink-4 hover:text-green disabled:opacity-30 disabled:cursor-not-allowed transition-colors", "aria-label": t("pages.signalKeywords.pendingTerms.confirm"), children: _jsx(Check, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] })), onIgnore && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => onIgnore(term.term), disabled: true, className: "p-1.5 text-ink-4 hover:text-danger disabled:opacity-30 disabled:cursor-not-allowed transition-colors", "aria-label": t("pages.signalKeywords.pendingTerms.ignore"), children: _jsx(X, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }))] }))] }, term.term)))] }))] }));
35
+ : t("pages.signalKeywords.nTermsPendingReview", { count: terms.length }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", onClick: () => onConfirmAll?.(), disabled: true, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[12px] font-medium text-green bg-green/10 rounded-[3px] disabled:opacity-30 disabled:cursor-not-allowed hover:bg-green/20 transition-colors", children: [_jsx(CheckCheck, { className: "h-3.5 w-3.5" }), t("pages.signalKeywords.pendingTerms.confirmBatch")] }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", onClick: () => onIgnoreAll?.(), disabled: true, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[12px] font-medium text-ink-4 bg-surface border border-line rounded-[3px] disabled:opacity-30 disabled:cursor-not-allowed hover:text-danger hover:border-danger/30 transition-colors", children: [_jsx(XCircle, { className: "h-3.5 w-3.5" }), t("pages.signalKeywords.pendingTerms.ignoreBatch")] }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] })] })] })), terms.length === 0 ? (_jsxs("div", { className: "px-4 py-12 text-center text-[13px] text-ink-4 border border-dashed border-line-2 rounded-[4px]", children: [_jsx("p", { children: t("pages.signalKeywords.pendingTerms.empty") }), _jsx("p", { className: "mt-2 text-[12px]", children: t("pages.signalKeywords.pendingTerms.emptyDescription") })] })) : (_jsxs("div", { className: "border border-line rounded-[4px] overflow-hidden", children: [_jsxs("div", { className: "grid grid-cols-[24px_1fr_100px_90px_1fr_100px] gap-3 px-4 py-2.5 bg-surface text-[11px] font-medium text-ink-4 uppercase tracking-[var(--tracking-wide)] border-b border-line items-center", children: [_jsx("span", {}), _jsx("span", { children: t("pages.signalKeywords.colTerm") }), _jsx("span", { children: t("pages.signalKeywords.colCategory") }), _jsx("span", { children: t("pages.signalKeywords.colPrecision") }), _jsx("span", { children: t("pages.signalKeywords.colReason") }), hasRowOps && _jsx("span", { className: "text-right", children: t("pages.signalKeywords.colActions") })] }), terms.map((term) => (_jsxs("div", { className: "grid grid-cols-[24px_1fr_100px_90px_1fr_100px] gap-3 px-4 py-3 items-start border-b border-line last:border-b-0 hover:bg-surface/50 transition-colors", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("input", { type: "checkbox", checked: selected.has(term.term), onChange: () => toggleSelected(term.term), disabled: true, className: "mt-0.5 h-3.5 w-3.5 rounded border-line text-gov disabled:opacity-30 disabled:cursor-not-allowed" }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }), _jsxs("div", { className: "min-w-0", children: [_jsx("span", { className: "text-[13px] text-ink font-medium block truncate", children: term.term }), _jsx("span", { className: "text-[11px] text-ink-4 mt-0.5 block", children: formatDate(term.discoveredAt, i18n.language) })] }), _jsx(Badge, { variant: term.suggestedCategory === "correction" ? "default" : "amber", children: categoryLabel[term.suggestedCategory] ?? term.suggestedCategory }), _jsx("span", { className: "text-[12px] text-ink-3", children: term.suggestedPrecision === "high" ? (_jsx("span", { className: "text-green", children: t("pages.signalKeywords.precisionHigh") })) : (_jsx("span", { className: "text-amber", children: t("pages.signalKeywords.precisionAmbiguous") })) }), _jsx("span", { className: "text-[12px] text-ink-3 leading-[1.5] line-clamp-2", children: term.reason }), hasRowOps && (_jsxs("div", { className: "flex items-center justify-end gap-1", children: [onConfirm && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => onConfirm(term), disabled: true, className: "p-1.5 text-ink-4 hover:text-green disabled:opacity-30 disabled:cursor-not-allowed transition-colors", "aria-label": t("pages.signalKeywords.pendingTerms.confirm"), children: _jsx(Check, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] })), onIgnore && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => onIgnore(term.term), disabled: true, className: "p-1.5 text-ink-4 hover:text-danger disabled:opacity-30 disabled:cursor-not-allowed transition-colors", "aria-label": t("pages.signalKeywords.pendingTerms.ignore"), children: _jsx(X, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }))] }))] }, term.term)))] }))] }));
35
36
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Format an ISO timestamp following the UI language, not the browser/OS locale.
3
+ *
4
+ * PD is bilingual (zh-CN / en): a user running an English OS while viewing the
5
+ * zh-CN UI must still see zh-CN dates (and vice versa), so the locale always
6
+ * comes from i18n.language instead of the ambient environment.
7
+ *
8
+ * Invalid or missing input returns the raw string unchanged — Intl would
9
+ * render "Invalid Date" for NaN dates, which must never reach the screen.
10
+ */
11
+ export declare function formatDate(iso: string, language?: string, options?: Intl.DateTimeFormatOptions): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Format an ISO timestamp following the UI language, not the browser/OS locale.
3
+ *
4
+ * PD is bilingual (zh-CN / en): a user running an English OS while viewing the
5
+ * zh-CN UI must still see zh-CN dates (and vice versa), so the locale always
6
+ * comes from i18n.language instead of the ambient environment.
7
+ *
8
+ * Invalid or missing input returns the raw string unchanged — Intl would
9
+ * render "Invalid Date" for NaN dates, which must never reach the screen.
10
+ */
11
+ export function formatDate(iso, language, options) {
12
+ const date = new Date(iso);
13
+ if (Number.isNaN(date.getTime()))
14
+ return iso;
15
+ const locale = language && language !== "unknown" ? language : undefined;
16
+ return new Intl.DateTimeFormat(locale, options).format(date);
17
+ }
@@ -310,6 +310,9 @@
310
310
  .top-1\/2 {
311
311
  top: calc(1 / 2 * 100%);
312
312
  }
313
+ .top-3 {
314
+ top: calc(var(--spacing) * 3);
315
+ }
313
316
  .top-4 {
314
317
  top: calc(var(--spacing) * 4);
315
318
  }
@@ -337,9 +340,15 @@
337
340
  .bottom-0 {
338
341
  bottom: 0px;
339
342
  }
343
+ .bottom-3 {
344
+ bottom: calc(var(--spacing) * 3);
345
+ }
340
346
  .bottom-4 {
341
347
  bottom: calc(var(--spacing) * 4);
342
348
  }
349
+ .-left-\[19px\] {
350
+ left: calc(19px * -1);
351
+ }
343
352
  .left-0 {
344
353
  left: 0px;
345
354
  }
@@ -349,6 +358,9 @@
349
358
  .left-3 {
350
359
  left: calc(var(--spacing) * 3);
351
360
  }
361
+ .left-\[12\.5px\] {
362
+ left: 12.5px;
363
+ }
352
364
  .left-\[50\%\] {
353
365
  left: 50%;
354
366
  }
@@ -664,6 +676,9 @@
664
676
  .w-2 {
665
677
  width: calc(var(--spacing) * 2);
666
678
  }
679
+ .w-2\.5 {
680
+ width: calc(var(--spacing) * 2.5);
681
+ }
667
682
  .w-3 {
668
683
  width: calc(var(--spacing) * 3);
669
684
  }
@@ -746,6 +761,9 @@
746
761
  .w-full {
747
762
  width: 100%;
748
763
  }
764
+ .w-px {
765
+ width: 1px;
766
+ }
749
767
  .max-w-\[32ch\] {
750
768
  max-width: 32ch;
751
769
  }
@@ -797,6 +815,9 @@
797
815
  .min-w-\[80px\] {
798
816
  min-width: 80px;
799
817
  }
818
+ .min-w-\[120px\] {
819
+ min-width: 120px;
820
+ }
800
821
  .min-w-\[140px\] {
801
822
  min-width: 140px;
802
823
  }
@@ -1350,6 +1371,15 @@
1350
1371
  border-color: color-mix(in oklab, var(--color-line) 50%, transparent);
1351
1372
  }
1352
1373
  }
1374
+ .border-line\/60 {
1375
+ border-color: color-mix(in srgb, #d7d1c4 60%, transparent);
1376
+ @supports (color: color-mix(in lab, red, red)) {
1377
+ border-color: color-mix(in oklab, var(--color-line) 60%, transparent);
1378
+ }
1379
+ }
1380
+ .border-paper {
1381
+ border-color: var(--color-paper);
1382
+ }
1353
1383
  .border-red-200 {
1354
1384
  border-color: var(--color-red-200);
1355
1385
  }
@@ -1818,6 +1848,9 @@
1818
1848
  .pl-4 {
1819
1849
  padding-left: calc(var(--spacing) * 4);
1820
1850
  }
1851
+ .pl-6 {
1852
+ padding-left: calc(var(--spacing) * 6);
1853
+ }
1821
1854
  .pl-7 {
1822
1855
  padding-left: calc(var(--spacing) * 7);
1823
1856
  }
@@ -2389,6 +2422,10 @@
2389
2422
  --tw-content: '';
2390
2423
  content: var(--tw-content);
2391
2424
  }
2425
+ .last\:border-r-0:last-child {
2426
+ border-right-style: var(--tw-border-style);
2427
+ border-right-width: 0px;
2428
+ }
2392
2429
  .last\:border-b-0:last-child {
2393
2430
  border-bottom-style: var(--tw-border-style);
2394
2431
  border-bottom-width: 0px;