@focus-reactive/payload-plugin-translator 0.7.2 → 0.8.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.
Files changed (139) hide show
  1. package/README.md +18 -3
  2. package/dist/client/entities/translation/api/mutations/useDismissStaleness.d.ts +12 -0
  3. package/dist/client/entities/translation/api/mutations/useDismissStaleness.js +40 -0
  4. package/dist/client/entities/translation/api/mutations/useQueueDocumentTranslation.js +6 -0
  5. package/dist/client/entities/translation/api/mutations/useRunDocumentTranslation.js +6 -0
  6. package/dist/client/entities/translation/api/queries/useDocumentStaleness.d.ts +17 -0
  7. package/dist/client/entities/translation/api/queries/useDocumentStaleness.js +35 -0
  8. package/dist/client/entities/translation/api/queries/useDocumentTranslation.js +23 -1
  9. package/dist/client/entities/translation/index.d.ts +12 -5
  10. package/dist/client/entities/translation/index.js +10 -5
  11. package/dist/client/entities/translation/model/panelStatus.d.ts +60 -0
  12. package/dist/client/entities/translation/model/panelStatus.js +101 -0
  13. package/dist/client/entities/translation/model/statusRows.d.ts +42 -0
  14. package/dist/client/entities/translation/model/statusRows.js +79 -0
  15. package/dist/client/entities/translation/model/types.d.ts +11 -0
  16. package/dist/client/entities/translation/model/types.js +1 -1
  17. package/dist/client/entities/translation/ui/ActionButton/ActionButton.d.ts +14 -0
  18. package/dist/client/entities/translation/ui/ActionButton/ActionButton.js +28 -0
  19. package/dist/client/entities/translation/ui/ActionButton/index.d.ts +1 -0
  20. package/dist/client/entities/translation/ui/ActionButton/index.js +3 -0
  21. package/dist/client/entities/translation/ui/ActionButton/styles.module.scss +11 -0
  22. package/dist/client/entities/translation/ui/PanelStatusMarker/PanelStatusMarker.d.ts +12 -0
  23. package/dist/client/entities/translation/ui/PanelStatusMarker/PanelStatusMarker.js +26 -0
  24. package/dist/client/entities/translation/ui/PanelStatusMarker/index.d.ts +1 -0
  25. package/dist/client/entities/translation/ui/PanelStatusMarker/index.js +3 -0
  26. package/dist/client/entities/translation/ui/PanelStatusMarker/styles.module.scss +12 -0
  27. package/dist/client/entities/translation/ui/TranslationDirection/styles.module.scss +2 -2
  28. package/dist/client/entities/translation/ui/TranslationStatusList/StatusBadge.d.ts +10 -0
  29. package/dist/client/entities/translation/ui/TranslationStatusList/StatusBadge.js +27 -0
  30. package/dist/client/entities/translation/ui/TranslationStatusList/TranslationStatusList.d.ts +14 -0
  31. package/dist/client/entities/translation/ui/TranslationStatusList/TranslationStatusList.js +194 -0
  32. package/dist/client/entities/translation/ui/TranslationStatusList/index.d.ts +1 -0
  33. package/dist/client/entities/translation/ui/TranslationStatusList/index.js +3 -0
  34. package/dist/client/entities/translation/ui/TranslationStatusList/styles.module.scss +72 -0
  35. package/dist/client/features/collection-translation-form/ui/CollectionTranslationForm.js +17 -21
  36. package/dist/client/features/collection-translation-form/ui/styles.module.scss +14 -14
  37. package/dist/client/features/collection-translation-popup/ui/CollectionTranslationPopup.d.ts +4 -2
  38. package/dist/client/features/collection-translation-popup/ui/CollectionTranslationPopup.js +9 -9
  39. package/dist/client/features/collection-translation-popup/ui/styles.module.scss +5 -3
  40. package/dist/client/features/collection-translation-progress/ui/CollectionTranslationProgress.d.ts +5 -1
  41. package/dist/client/features/collection-translation-progress/ui/CollectionTranslationProgress.js +100 -93
  42. package/dist/client/features/collection-translation-progress/ui/styles.module.scss +52 -3
  43. package/dist/client/features/open-document-translation-popup/ui/OpenDocumentTranslationPopup.d.ts +4 -1
  44. package/dist/client/features/open-document-translation-popup/ui/OpenDocumentTranslationPopup.js +16 -5
  45. package/dist/client/features/open-document-translation-popup/ui/styles.module.scss +5 -3
  46. package/dist/client/features/translate-document-form/ui/DocumentTranslationForm.js +5 -2
  47. package/dist/client/features/translate-document-form/ui/styles.module.scss +8 -2
  48. package/dist/client/shared/lib/assets/icons/AlertTriangleIcon.d.ts +1 -0
  49. package/dist/client/shared/lib/assets/icons/AlertTriangleIcon.js +14 -0
  50. package/dist/client/shared/lib/assets/icons/CheckIcon.d.ts +1 -0
  51. package/dist/client/shared/lib/assets/icons/CheckIcon.js +17 -0
  52. package/dist/client/shared/lib/assets/icons/CloseIcon.d.ts +1 -0
  53. package/dist/client/shared/lib/assets/icons/CloseIcon.js +16 -0
  54. package/dist/client/shared/ui/Button/Button.js +2 -1
  55. package/dist/client/shared/ui/ColorIndicator/ColorIndicator.d.ts +1 -1
  56. package/dist/client/shared/ui/ColorIndicator/styles.module.scss +4 -0
  57. package/dist/client/shared/ui/Label/Label.d.ts +2 -0
  58. package/dist/client/shared/ui/Label/Label.js +3 -2
  59. package/dist/client/shared/ui/Label/styles.module.scss +11 -0
  60. package/dist/client/shared/ui/Loading/Loading.d.ts +6 -2
  61. package/dist/client/shared/ui/Loading/Loading.js +4 -2
  62. package/dist/client/shared/ui/Loading/barCount.d.ts +3 -0
  63. package/dist/client/shared/ui/Loading/barCount.js +11 -0
  64. package/dist/client/shared/ui/Loading/styles.module.scss +20 -27
  65. package/dist/client/shared/ui/Popup/Popup.js +3 -0
  66. package/dist/client/shared/ui/Select/Select.js +1 -1
  67. package/dist/client/shared/ui/form/FormSelect/FormSelect.js +1 -0
  68. package/dist/client/widgets/bulk-translation-dashboard/ui/BulkTranslationDashboard.js +37 -17
  69. package/dist/client/widgets/bulk-translation-dashboard/ui/styles.module.scss +27 -0
  70. package/dist/client/widgets/translate-document/ui/TranslateDocument.js +53 -27
  71. package/dist/client/widgets/translate-document/ui/styles.module.scss +27 -0
  72. package/dist/composition/levels/useDocTranslationApi.d.ts +3 -2
  73. package/dist/composition/levels/useDocTranslationApi.js +6 -3
  74. package/dist/core/provenance/ProvenanceStore.interface.d.ts +18 -0
  75. package/dist/core/provenance/index.d.ts +1 -0
  76. package/dist/core/provenance/index.js +1 -1
  77. package/dist/core/provenance/staleness.d.ts +19 -0
  78. package/dist/core/provenance/staleness.js +21 -0
  79. package/dist/plugin.js +2 -1
  80. package/dist/server/features/_lib/sourceDocument.d.ts +9 -0
  81. package/dist/server/features/_lib/sourceDocument.js +16 -0
  82. package/dist/server/features/createTranslationRoutes.d.ts +12 -4
  83. package/dist/server/features/createTranslationRoutes.js +15 -5
  84. package/dist/server/features/get-document-status/model.js +7 -2
  85. package/dist/server/features/staleness/dismissStaleness.handler.d.ts +8 -0
  86. package/dist/server/features/staleness/dismissStaleness.handler.js +27 -0
  87. package/dist/server/features/staleness/getDocumentStaleness.handler.d.ts +12 -0
  88. package/dist/server/features/staleness/getDocumentStaleness.handler.js +43 -0
  89. package/dist/server/features/staleness/index.d.ts +2 -0
  90. package/dist/server/features/staleness/index.js +3 -0
  91. package/dist/server/features/staleness/model.d.ts +52 -0
  92. package/dist/server/features/staleness/model.js +17 -0
  93. package/dist/server/features/staleness/route.d.ts +7 -0
  94. package/dist/server/features/staleness/route.js +21 -0
  95. package/dist/server/features/staleness/service.d.ts +15 -0
  96. package/dist/server/features/staleness/service.js +78 -0
  97. package/dist/server/features/translate-document/handler.js +22 -8
  98. package/dist/server/modules/provenance/PayloadProvenanceStore.d.ts +2 -0
  99. package/dist/server/modules/provenance/PayloadProvenanceStore.js +37 -14
  100. package/dist/server/modules/translation-levels/PluginConfigBuilder.d.ts +3 -0
  101. package/dist/server/modules/translation-levels/PluginConfigBuilder.js +2 -0
  102. package/dist/server/modules/translation-levels/types.d.ts +3 -0
  103. package/dist/server/shared/http/index.d.ts +1 -0
  104. package/dist/server/shared/http/index.js +1 -0
  105. package/dist/server/shared/http/toClientErrorMessage.d.ts +15 -0
  106. package/dist/server/shared/http/toClientErrorMessage.js +26 -0
  107. package/dist/server/shared/index.d.ts +1 -1
  108. package/dist/server/shared/index.js +1 -1
  109. package/package.json +1 -1
  110. package/dist/client/entities/translation/ui/CompletedTranslationStatus/CompletedTranslationStatus.d.ts +0 -7
  111. package/dist/client/entities/translation/ui/CompletedTranslationStatus/CompletedTranslationStatus.js +0 -45
  112. package/dist/client/entities/translation/ui/CompletedTranslationStatus/index.d.ts +0 -1
  113. package/dist/client/entities/translation/ui/CompletedTranslationStatus/index.js +0 -3
  114. package/dist/client/entities/translation/ui/CompletedTranslationStatus/styles.module.scss +0 -3
  115. package/dist/client/entities/translation/ui/FailedTranslationStatus/FailedTranslationStatus.d.ts +0 -9
  116. package/dist/client/entities/translation/ui/FailedTranslationStatus/FailedTranslationStatus.js +0 -54
  117. package/dist/client/entities/translation/ui/FailedTranslationStatus/index.d.ts +0 -1
  118. package/dist/client/entities/translation/ui/FailedTranslationStatus/index.js +0 -3
  119. package/dist/client/entities/translation/ui/FailedTranslationStatus/styles.module.scss +0 -3
  120. package/dist/client/entities/translation/ui/PendingTranslationStatus/PendingTranslationStatus.d.ts +0 -11
  121. package/dist/client/entities/translation/ui/PendingTranslationStatus/PendingTranslationStatus.js +0 -83
  122. package/dist/client/entities/translation/ui/PendingTranslationStatus/index.d.ts +0 -1
  123. package/dist/client/entities/translation/ui/PendingTranslationStatus/index.js +0 -3
  124. package/dist/client/entities/translation/ui/RunningTranslationStatus/RunningTranslationStatus.d.ts +0 -10
  125. package/dist/client/entities/translation/ui/RunningTranslationStatus/RunningTranslationStatus.js +0 -66
  126. package/dist/client/entities/translation/ui/RunningTranslationStatus/index.d.ts +0 -1
  127. package/dist/client/entities/translation/ui/RunningTranslationStatus/index.js +0 -3
  128. package/dist/client/features/document-translation-progress-failed/index.d.ts +0 -1
  129. package/dist/client/features/document-translation-progress-failed/index.js +0 -3
  130. package/dist/client/features/document-translation-progress-failed/ui/DocumentTranslationProgressFailed.d.ts +0 -6
  131. package/dist/client/features/document-translation-progress-failed/ui/DocumentTranslationProgressFailed.js +0 -28
  132. package/dist/client/features/document-translation-progress-pending/index.d.ts +0 -1
  133. package/dist/client/features/document-translation-progress-pending/index.js +0 -3
  134. package/dist/client/features/document-translation-progress-pending/ui/DocumentTranslationProgressPending.d.ts +0 -6
  135. package/dist/client/features/document-translation-progress-pending/ui/DocumentTranslationProgressPending.js +0 -44
  136. package/dist/client/features/document-translation-progress-running/index.d.ts +0 -1
  137. package/dist/client/features/document-translation-progress-running/index.js +0 -3
  138. package/dist/client/features/document-translation-progress-running/ui/DocumentTranslationProgressRunning.d.ts +0 -6
  139. package/dist/client/features/document-translation-progress-running/ui/DocumentTranslationProgressRunning.js +0 -28
@@ -1,107 +1,114 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { ShimmerEffect } from "@payloadcms/ui";
4
4
  import { TrashIcon } from "@payloadcms/ui/icons/Trash";
5
- import { TranslationsApi } from "../../../entities/translation";
6
- import { LanguageTranslateIcon } from "../../../shared/lib/assets/icons/LanguageTranslateIcon";
7
- import Button from "../../../shared/ui/Button";
8
- import StatusIndicator from "../../../shared/ui/StatusIndicator";
9
- import Tooltip from "../../../shared/ui/Tooltip";
5
+ import { ActionButton, DocumentTranslationStatus, TranslationsApi } from "../../../entities/translation";
6
+ import ColorIndicator from "../../../shared/ui/ColorIndicator";
10
7
  import styles from "./styles.module.scss";
11
- export function CollectionTranslationProgress({ collection, data, isPending }) {
8
+ // Same colour + label vocabulary as the document status list (StatusBadge STATE_LABEL). Only the
9
+ // actively-processing group pulses — Queued is waiting, not working, so it stays static.
10
+ const ROWS = [
11
+ {
12
+ key: DocumentTranslationStatus.RUNNING,
13
+ label: "Translating",
14
+ color: "blue"
15
+ },
16
+ {
17
+ key: DocumentTranslationStatus.PENDING,
18
+ label: "Queued",
19
+ color: "gray"
20
+ },
21
+ {
22
+ key: DocumentTranslationStatus.COMPLETED,
23
+ label: "Translated",
24
+ color: "green"
25
+ },
26
+ {
27
+ key: DocumentTranslationStatus.FAILED,
28
+ label: "Failed",
29
+ color: "red"
30
+ }
31
+ ];
32
+ /**
33
+ * Collection status as a compact list of grouped counts — one `[dot] label … count` row per
34
+ * non-zero group, mirroring the document popup's per-locale list rhythm (dot vocabulary shared).
35
+ */ export function CollectionTranslationProgress({ collection, data, isPending }) {
12
36
  const cancelPendingTranslations = TranslationsApi.useCancelCollectionTranslations();
13
- return /*#__PURE__*/ _jsxs("div", {
14
- className: styles.container,
15
- children: [
16
- isPending && /*#__PURE__*/ _jsxs(_Fragment, {
37
+ if (isPending) {
38
+ return /*#__PURE__*/ _jsxs("div", {
39
+ className: styles["status-list"],
40
+ children: [
41
+ /*#__PURE__*/ _jsx(ShimmerEffect, {
42
+ width: "100%",
43
+ height: 20
44
+ }),
45
+ /*#__PURE__*/ _jsx(ShimmerEffect, {
46
+ width: "100%",
47
+ height: 20
48
+ }),
49
+ /*#__PURE__*/ _jsx(ShimmerEffect, {
50
+ width: "100%",
51
+ height: 20
52
+ })
53
+ ]
54
+ });
55
+ }
56
+ if (!data) {
57
+ return null;
58
+ }
59
+ return /*#__PURE__*/ _jsx("ul", {
60
+ className: styles["status-list"],
61
+ children: ROWS.map(({ key, label, color })=>{
62
+ const count = data[key].length;
63
+ if (count === 0) {
64
+ return null;
65
+ }
66
+ return /*#__PURE__*/ _jsxs("li", {
67
+ className: styles["status-row"],
17
68
  children: [
18
- /*#__PURE__*/ _jsx(ShimmerEffect, {
19
- width: "100%",
20
- height: 32
21
- }),
22
- /*#__PURE__*/ _jsx(ShimmerEffect, {
23
- width: "100%",
24
- height: 32
25
- }),
26
- /*#__PURE__*/ _jsx(ShimmerEffect, {
27
- width: "100%",
28
- height: 32
29
- }),
30
- /*#__PURE__*/ _jsx(ShimmerEffect, {
31
- width: "100%",
32
- height: 32
33
- })
34
- ]
35
- }),
36
- data && /*#__PURE__*/ _jsxs(_Fragment, {
37
- children: [
38
- /*#__PURE__*/ _jsxs(StatusIndicator, {
39
- className: styles["status-indicator"],
40
- title: "Completed",
41
- $color: "green",
42
- children: [
43
- /*#__PURE__*/ _jsx(LanguageTranslateIcon, {}),
44
- /*#__PURE__*/ _jsx("b", {
45
- children: data.completed.length
46
- })
47
- ]
48
- }, "completed"),
49
- /*#__PURE__*/ _jsxs(StatusIndicator, {
50
- className: styles["status-indicator"],
51
- title: "Failed",
52
- $color: "red",
69
+ /*#__PURE__*/ _jsxs("div", {
70
+ className: styles.top,
53
71
  children: [
54
- /*#__PURE__*/ _jsx(LanguageTranslateIcon, {}),
55
- /*#__PURE__*/ _jsx("b", {
56
- children: data.failed.length
57
- })
58
- ]
59
- }, "failed"),
60
- /*#__PURE__*/ _jsxs(StatusIndicator, {
61
- className: styles["status-indicator"],
62
- title: "In progress",
63
- $animated: data.running.length > 0,
64
- $color: "blue",
65
- children: [
66
- /*#__PURE__*/ _jsx(LanguageTranslateIcon, {}),
67
- /*#__PURE__*/ _jsx("b", {
68
- children: data.running.length
69
- })
70
- ]
71
- }, "running"),
72
- /*#__PURE__*/ _jsxs(StatusIndicator, {
73
- className: styles["status-indicator"],
74
- title: "Pending",
75
- $animated: data.pending.length > 0,
76
- $color: "gray",
77
- children: [
78
- /*#__PURE__*/ _jsx(LanguageTranslateIcon, {}),
79
- /*#__PURE__*/ _jsx("b", {
80
- children: data.pending.length
72
+ /*#__PURE__*/ _jsxs("span", {
73
+ className: styles.lead,
74
+ children: [
75
+ /*#__PURE__*/ _jsx(ColorIndicator, {
76
+ $color: color,
77
+ $animated: key === DocumentTranslationStatus.RUNNING
78
+ }),
79
+ /*#__PURE__*/ _jsx("span", {
80
+ className: styles.label,
81
+ children: label
82
+ })
83
+ ]
81
84
  }),
82
- /*#__PURE__*/ _jsx(Tooltip, {
83
- sideOffset: 12,
84
- side: "bottom",
85
- content: "Cancel translations",
86
- children: /*#__PURE__*/ _jsx(Button, {
87
- $variant: "light",
88
- $size: "sm",
89
- $isIconButton: true,
90
- "aria-label": "Cancel all queued translation",
91
- type: "button",
92
- onClick: ()=>cancelPendingTranslations.mutateAsync({
93
- collection
94
- }),
95
- disabled: cancelPendingTranslations.isPending || !data.pending.length,
96
- $isLoading: cancelPendingTranslations.isPending,
97
- children: /*#__PURE__*/ _jsx(TrashIcon, {})
98
- })
85
+ /*#__PURE__*/ _jsxs("span", {
86
+ className: styles.right,
87
+ children: [
88
+ /*#__PURE__*/ _jsx("span", {
89
+ className: styles.count,
90
+ children: count
91
+ }),
92
+ key === DocumentTranslationStatus.PENDING && /*#__PURE__*/ _jsx(ActionButton, {
93
+ icon: /*#__PURE__*/ _jsx(TrashIcon, {}),
94
+ title: "Cancel translations",
95
+ onClick: ()=>cancelPendingTranslations.mutateAsync({
96
+ collection
97
+ }),
98
+ disabled: cancelPendingTranslations.isPending,
99
+ loading: cancelPendingTranslations.isPending
100
+ })
101
+ ]
99
102
  })
100
103
  ]
101
- }, "pending")
104
+ }),
105
+ key === DocumentTranslationStatus.FAILED && /*#__PURE__*/ _jsx("p", {
106
+ className: styles.meta,
107
+ children: "Open a document to see why"
108
+ })
102
109
  ]
103
- })
104
- ]
110
+ }, key);
111
+ })
105
112
  });
106
113
  }
107
114
 
@@ -1,8 +1,57 @@
1
- .container {
1
+ .status-list {
2
2
  display: flex;
3
+ flex-direction: column;
3
4
  gap: 0.5rem;
5
+ margin: 0;
6
+ padding: 0;
7
+ list-style: none;
4
8
  }
5
9
 
6
- .status-indicator {
7
- flex-grow: 1;
10
+ .status-row {
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: 0.125rem;
14
+ font-size: 0.8125rem;
15
+ }
16
+
17
+ // The count line: [dot + label] left, count (+ action) right.
18
+ .top {
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: space-between;
22
+ gap: 0.5rem;
23
+ min-height: 1.5rem; // same first-line height as the document status row
24
+ }
25
+
26
+ // Hint under a failed group: no per-doc error data here, so point to where detail lives.
27
+ .meta {
28
+ margin: 0;
29
+ padding-left: calc(8px + 0.5rem); // align under the label, like the document meta line
30
+ font-size: 0.6875rem;
31
+ color: var(--theme-elevation-500, #8c8c8c);
32
+ }
33
+
34
+ // Dot + label share one flex line so the dot centres on the label.
35
+ .lead {
36
+ display: flex;
37
+ align-items: center;
38
+ gap: 0.5rem;
39
+ min-width: 0;
40
+ }
41
+
42
+ .label {
43
+ font-weight: 500;
44
+ color: var(--theme-text, #222);
45
+ }
46
+
47
+ .right {
48
+ display: inline-flex;
49
+ align-items: center;
50
+ gap: 0.25rem;
51
+ }
52
+
53
+ .count {
54
+ font-size: 0.8125rem;
55
+ font-weight: 600;
56
+ font-variant-numeric: tabular-nums;
8
57
  }
@@ -1,9 +1,12 @@
1
1
  import type { ReactNode } from "react";
2
+ import type { PanelStatus } from "../../../entities/translation";
2
3
  type OpenDocumentTranslationPopupProps = {
3
4
  isLoading?: boolean;
5
+ /** Aggregate translation state → the marker + tooltip on the trigger (detail lives in the popup). */
6
+ status?: PanelStatus;
4
7
  children: (props: {
5
8
  close: () => void;
6
9
  }) => ReactNode;
7
10
  };
8
- declare function OpenDocumentTranslationPopup({ children, isLoading }: OpenDocumentTranslationPopupProps): import("react/jsx-runtime").JSX.Element;
11
+ declare function OpenDocumentTranslationPopup({ children, isLoading, status, }: OpenDocumentTranslationPopupProps): import("react/jsx-runtime").JSX.Element;
9
12
  export default OpenDocumentTranslationPopup;
@@ -1,25 +1,36 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { describePanelStatus, PanelStatusMarker } from "../../../entities/translation";
3
4
  import { LanguageTranslateIcon } from "../../../shared/lib/assets/icons/LanguageTranslateIcon";
4
5
  import { useToggle } from "../../../shared/lib/utils/react/useToggle";
5
6
  import Button from "../../../shared/ui/Button";
6
7
  import Popup from "../../../shared/ui/Popup";
7
8
  import styles from "./styles.module.scss";
8
- function OpenDocumentTranslationPopup({ children, isLoading }) {
9
+ function OpenDocumentTranslationPopup({ children, isLoading, status }) {
9
10
  const [isPopupOpen, popupOpen] = useToggle();
11
+ const { tone, title } = describePanelStatus(status, "Translate this document");
10
12
  return /*#__PURE__*/ _jsx(Popup, {
11
13
  $align: "start",
12
14
  onOpenChange: popupOpen.setValue,
13
- $trigger: /*#__PURE__*/ _jsx(Button, {
15
+ $trigger: /*#__PURE__*/ _jsxs(Button, {
16
+ // Explicit: the control is injected into Payload's document `<form>`, so a bare button
17
+ // would default to type="submit" and save the whole page on click.
18
+ type: "button",
14
19
  $size: "md",
15
20
  $variant: "outlined-light",
16
21
  $isIconButton: true,
17
22
  className: styles["popup-trigger-button"],
18
- "aria-label": "Open translation options",
23
+ "aria-label": `Open translation options — ${title}`,
24
+ title: title,
19
25
  onClick: popupOpen.setTrue,
20
26
  disabled: isLoading,
21
27
  $isLoading: isLoading,
22
- children: /*#__PURE__*/ _jsx(LanguageTranslateIcon, {})
28
+ children: [
29
+ /*#__PURE__*/ _jsx(LanguageTranslateIcon, {}),
30
+ /*#__PURE__*/ _jsx(PanelStatusMarker, {
31
+ tone: tone
32
+ })
33
+ ]
23
34
  }),
24
35
  open: isPopupOpen,
25
36
  children: /*#__PURE__*/ _jsx("div", {
@@ -1,11 +1,13 @@
1
1
  .popup-content {
2
2
  display: flex;
3
3
  flex-direction: column;
4
- gap: 1rem;
5
- padding: 1.5rem 1rem;
6
- min-width: 270px;
4
+ gap: 0.75rem;
5
+ padding: 0.75rem;
6
+ width: 18rem; // ~288px — narrow; status rows wrap to 2 lines so the From/To two-up is the width floor
7
+ max-width: calc(100vw - 24px);
7
8
  }
8
9
 
9
10
  .popup-trigger-button {
10
11
  font-size: 1.3rem;
12
+ position: relative;
11
13
  }
@@ -17,16 +17,19 @@ export function DocumentTranslationForm({ form, onSubmit, hasDrafts }) {
17
17
  className: styles.row,
18
18
  children: [
19
19
  /*#__PURE__*/ _jsx(FormSelectLocale, {
20
+ size: "sm",
20
21
  label: "From",
21
22
  name: FORM_FIELDS.SOURCE_LNG
22
23
  }),
23
24
  /*#__PURE__*/ _jsx(FormSelectLocale, {
25
+ size: "sm",
24
26
  label: "To",
25
27
  name: FORM_FIELDS.TARGET_LNG
26
28
  })
27
29
  ]
28
30
  }),
29
31
  /*#__PURE__*/ _jsx(FormSelectStrategy, {
32
+ size: "sm",
30
33
  name: FORM_FIELDS.STRATEGY
31
34
  }),
32
35
  hasDrafts && /*#__PURE__*/ _jsx(FormCheckboxPublish, {
@@ -46,10 +49,10 @@ export function DocumentTranslationForm({ form, onSubmit, hasDrafts }) {
46
49
  className: styles["submit-button"],
47
50
  onClick: form.handleSubmit(onSubmit),
48
51
  type: "submit",
49
- $size: "lg",
52
+ $size: "sm",
50
53
  $isLoading: form.formState.isSubmitting,
51
54
  $startContent: /*#__PURE__*/ _jsx(SendIcon, {}),
52
- children: "Queue Translation"
55
+ children: "Queue translation"
53
56
  })
54
57
  ]
55
58
  })
@@ -1,7 +1,7 @@
1
1
  .fieldset {
2
2
  display: flex;
3
3
  flex-direction: column;
4
- gap: 1rem;
4
+ gap: 0.5rem;
5
5
  border-width: 0;
6
6
  margin: 0;
7
7
  padding: 0;
@@ -9,7 +9,13 @@
9
9
 
10
10
  .row {
11
11
  display: flex;
12
- gap: 1rem;
12
+ gap: 0.5rem;
13
+ }
14
+
15
+ // From / To share the row equally and are allowed to shrink with the narrower popup.
16
+ .row > * {
17
+ flex: 1 1 0;
18
+ min-width: 0;
13
19
  }
14
20
 
15
21
  .submit-button {
@@ -0,0 +1 @@
1
+ export declare const AlertTriangleIcon: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const AlertTriangleIcon = ()=>/*#__PURE__*/ _jsx("svg", {
3
+ width: "1em",
4
+ height: "1em",
5
+ viewBox: "0 0 16 16",
6
+ xmlns: "http://www.w3.org/2000/svg",
7
+ fill: "none",
8
+ children: /*#__PURE__*/ _jsx("path", {
9
+ fill: "currentColor",
10
+ d: "M7.14 1.86a1 1 0 011.72 0l6 10.5A1 1 0 0114 14H2a1 1 0 01-.86-1.5l6-10.64zM8 5.75a.75.75 0 00-.75.75v3a.75.75 0 001.5 0v-3A.75.75 0 008 5.75zm0 6.5a.9.9 0 100-1.8.9.9 0 000 1.8z"
11
+ })
12
+ });
13
+
14
+ //# sourceMappingURL=AlertTriangleIcon.js.map
@@ -0,0 +1 @@
1
+ export declare const CheckIcon: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const CheckIcon = ()=>/*#__PURE__*/ _jsx("svg", {
3
+ width: "1em",
4
+ height: "1em",
5
+ viewBox: "0 0 16 16",
6
+ xmlns: "http://www.w3.org/2000/svg",
7
+ fill: "none",
8
+ children: /*#__PURE__*/ _jsx("path", {
9
+ stroke: "currentColor",
10
+ strokeWidth: "1.75",
11
+ strokeLinecap: "round",
12
+ strokeLinejoin: "round",
13
+ d: "M3.5 8.5l3 3 6-7"
14
+ })
15
+ });
16
+
17
+ //# sourceMappingURL=CheckIcon.js.map
@@ -0,0 +1 @@
1
+ export declare const CloseIcon: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const CloseIcon = ()=>/*#__PURE__*/ _jsx("svg", {
3
+ width: "1em",
4
+ height: "1em",
5
+ viewBox: "0 0 16 16",
6
+ xmlns: "http://www.w3.org/2000/svg",
7
+ fill: "none",
8
+ children: /*#__PURE__*/ _jsx("path", {
9
+ stroke: "currentColor",
10
+ strokeWidth: "1.75",
11
+ strokeLinecap: "round",
12
+ d: "M4 4l8 8M12 4l-8 8"
13
+ })
14
+ });
15
+
16
+ //# sourceMappingURL=CloseIcon.js.map
@@ -37,7 +37,8 @@ const Button = /*#__PURE__*/ forwardRef(function Button({ className = "", childr
37
37
  children: $startContent
38
38
  }),
39
39
  $isLoading ? /*#__PURE__*/ _jsx(Loading, {
40
- size: $isIconButton ? "small" : "medium"
40
+ size: $size,
41
+ compact: $isIconButton
41
42
  }) : children
42
43
  ]
43
44
  });
@@ -1,5 +1,5 @@
1
1
  type ColorIndicatorProps = {
2
- $color: "red" | "green" | "blue" | "gray";
2
+ $color: "red" | "green" | "blue" | "gray" | "amber";
3
3
  $animated?: boolean;
4
4
  title?: string;
5
5
  className?: string;
@@ -21,6 +21,10 @@
21
21
  background-color: var(--color-base-250);
22
22
  }
23
23
 
24
+ .amber-indicator {
25
+ background-color: #b45309; // amber-700 — matches the panel trigger's out-of-date marker
26
+ }
27
+
24
28
  .animated {
25
29
  animation: pulse 2s ease-in-out infinite;
26
30
  }
@@ -1,6 +1,8 @@
1
1
  import type { ComponentPropsWithRef, ReactElement } from "react";
2
2
  type LabelProps = ComponentPropsWithRef<"label"> & {
3
3
  label: string | ReactElement;
4
+ /** Scales the label text to match the control it captions (e.g. a `sm` field gets a smaller label). */
5
+ $size?: "sm" | "md" | "lg";
4
6
  };
5
7
  declare const Label: import("react").ForwardRefExoticComponent<Omit<LabelProps, "ref"> & import("react").RefAttributes<HTMLLabelElement>>;
6
8
  export default Label;
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
3
  import styles from "./styles.module.scss";
4
- const Label = /*#__PURE__*/ forwardRef(function Label({ children, className = "", label, ...props }, ref) {
4
+ const Label = /*#__PURE__*/ forwardRef(function Label({ children, className = "", label, $size, ...props }, ref) {
5
+ const sizeClass = $size ? styles[`size-${$size}`] : "";
5
6
  return /*#__PURE__*/ _jsxs("label", {
6
7
  ref: ref,
7
- className: `${styles.label} ${className}`,
8
+ className: `${styles.label} ${sizeClass} ${className}`,
8
9
  ...props,
9
10
  children: [
10
11
  /*#__PURE__*/ _jsx("span", {
@@ -10,3 +10,14 @@
10
10
  padding-bottom: 5px;
11
11
  }
12
12
  }
13
+
14
+ // Scale the caption text to the control size so a small field doesn't get an oversized label.
15
+ .size-sm .label__text {
16
+ font-size: 0.75rem;
17
+ padding-bottom: 3px;
18
+ }
19
+
20
+ .size-lg .label__text {
21
+ font-size: 1.05rem;
22
+ padding-bottom: 6px;
23
+ }
@@ -1,7 +1,11 @@
1
+ import type { LoadingSize } from "./barCount";
1
2
  type LoadingProps = {
2
3
  text?: string;
3
4
  className?: string;
4
- size?: "small" | "medium";
5
+ /** Matches the host control's size; drives how many bars animate (sm → fewer, so it stays legible). */
6
+ size?: LoadingSize;
7
+ /** For square/narrow hosts (icon buttons): use the minimum bar count so they fit the width. */
8
+ compact?: boolean;
5
9
  };
6
- declare function Loading({ text, className, size }: LoadingProps): import("react/jsx-runtime").JSX.Element;
10
+ declare function Loading({ text, className, size, compact }: LoadingProps): import("react/jsx-runtime").JSX.Element;
7
11
  export default Loading;
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import classNames from "classnames";
3
+ import { getBarCount } from "./barCount";
3
4
  import styles from "./styles.module.scss";
4
- function Loading({ text, className, size = "medium" }) {
5
+ function Loading({ text, className, size = "md", compact }) {
6
+ const barCount = getBarCount(size, compact);
5
7
  return /*#__PURE__*/ _jsxs("div", {
6
8
  className: classNames(styles["loading-overlay"], styles["loading-overlay--entering"], className),
7
9
  style: {
@@ -10,7 +12,7 @@ function Loading({ text, className, size = "medium" }) {
10
12
  children: [
11
13
  /*#__PURE__*/ _jsx("div", {
12
14
  className: classNames(styles["loading-overlay__bars"], styles[`loading-overlay__bars_${size}`]),
13
- children: new Array(size === "small" ? 2 : 5).fill(null).map((_, index)=>/*#__PURE__*/ _jsx("div", {
15
+ children: new Array(barCount).fill(null).map((_, index)=>/*#__PURE__*/ _jsx("div", {
14
16
  className: classNames(styles["loading-overlay__bar"], styles[`loading-overlay__bar_size-${size}`])
15
17
  }, index))
16
18
  }),
@@ -0,0 +1,3 @@
1
+ export type LoadingSize = "sm" | "md" | "lg";
2
+ /** How many animated bars the loading indicator renders for a given host size. */
3
+ export declare function getBarCount(size: LoadingSize, compact?: boolean): number;
@@ -0,0 +1,11 @@
1
+ /** Bars per size — a small control with five bars reads as noise, so the count scales down. */ const BAR_COUNT = {
2
+ sm: 3,
3
+ md: 4,
4
+ lg: 5
5
+ };
6
+ /** Square/narrow hosts (icon buttons) always use the minimum so the bars fit the width. */ const COMPACT_BAR_COUNT = 2;
7
+ /** How many animated bars the loading indicator renders for a given host size. */ export function getBarCount(size, compact) {
8
+ return compact ? COMPACT_BAR_COUNT : BAR_COUNT[size];
9
+ }
10
+
11
+ //# sourceMappingURL=barCount.js.map