@semiont/react-ui 0.5.25 → 0.5.26
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/dist/PdfAnnotationCanvas.client-6ZSF6ZTJ.js +677 -0
- package/dist/PdfAnnotationCanvas.client-6ZSF6ZTJ.js.map +1 -0
- package/dist/PdfAnnotationCanvas.client-JCJMXWWJ.css +180 -0
- package/dist/PdfAnnotationCanvas.client-JCJMXWWJ.css.map +1 -0
- package/dist/{ar-CULRHLNG.js → ar-YTUUGK2O.js} +13 -1
- package/dist/ar-YTUUGK2O.js.map +1 -0
- package/dist/{bn-HYR7CEL2.js → bn-ASGNGPMD.js} +13 -1
- package/dist/bn-ASGNGPMD.js.map +1 -0
- package/dist/{chunk-TG2XQEC4.js → chunk-BTUG3VJJ.js} +18 -298
- package/dist/chunk-BTUG3VJJ.js.map +1 -0
- package/dist/{chunk-NH6L2GIL.js → chunk-L3WKRWP3.js} +13 -1
- package/dist/chunk-L3WKRWP3.js.map +1 -0
- package/dist/chunk-OBQOZCJE.js +287 -0
- package/dist/chunk-OBQOZCJE.js.map +1 -0
- package/dist/{cs-YBRWY7NH.js → cs-WMYVAOZY.js} +13 -1
- package/dist/cs-WMYVAOZY.js.map +1 -0
- package/dist/{da-PHDEOBV3.js → da-FSHHN4D6.js} +13 -1
- package/dist/da-FSHHN4D6.js.map +1 -0
- package/dist/{de-O4UCCVLJ.js → de-FJFO3TPT.js} +13 -1
- package/dist/de-FJFO3TPT.js.map +1 -0
- package/dist/{el-MVGO6WZV.js → el-XOH4QIAG.js} +13 -1
- package/dist/el-XOH4QIAG.js.map +1 -0
- package/dist/{en-2KQILFKQ.js → en-3FCBW3YD.js} +4 -2
- package/dist/{es-USSLXQY7.js → es-HDX4QI7E.js} +13 -1
- package/dist/es-HDX4QI7E.js.map +1 -0
- package/dist/{fa-WMAREFWY.js → fa-DJ6WTFTJ.js} +13 -1
- package/dist/fa-DJ6WTFTJ.js.map +1 -0
- package/dist/{fi-B3NBNOTS.js → fi-4S7H7W7U.js} +13 -1
- package/dist/fi-4S7H7W7U.js.map +1 -0
- package/dist/{fr-TXYK5T5W.js → fr-6UJSYHXC.js} +13 -1
- package/dist/fr-6UJSYHXC.js.map +1 -0
- package/dist/{he-JCJACW5D.js → he-ZZJOHJX2.js} +13 -1
- package/dist/he-ZZJOHJX2.js.map +1 -0
- package/dist/{hi-VOQLZNJU.js → hi-HZJTAW7U.js} +13 -1
- package/dist/hi-HZJTAW7U.js.map +1 -0
- package/dist/{id-BFN5RZNZ.js → id-E3I6ILEM.js} +13 -1
- package/dist/id-E3I6ILEM.js.map +1 -0
- package/dist/index.css +140 -58
- package/dist/index.css.map +1 -1
- package/dist/index.js +67 -55
- package/dist/index.js.map +1 -1
- package/dist/{it-TWWDHKKM.js → it-ULAPAD7U.js} +13 -1
- package/dist/it-ULAPAD7U.js.map +1 -0
- package/dist/{ja-YRQLEBFM.js → ja-SAHZQ4CZ.js} +13 -1
- package/dist/ja-SAHZQ4CZ.js.map +1 -0
- package/dist/{ko-PG6B3CRB.js → ko-DFU2ADQ4.js} +13 -1
- package/dist/ko-DFU2ADQ4.js.map +1 -0
- package/dist/{ms-7EZECVKM.js → ms-NWL76XNT.js} +13 -1
- package/dist/ms-NWL76XNT.js.map +1 -0
- package/dist/{nl-HP753YAP.js → nl-ATCM76WN.js} +13 -1
- package/dist/nl-ATCM76WN.js.map +1 -0
- package/dist/{no-JUD5WX3N.js → no-UIAQ5RJF.js} +13 -1
- package/dist/no-UIAQ5RJF.js.map +1 -0
- package/dist/{pl-RVUL4CBM.js → pl-NOECQDXD.js} +13 -1
- package/dist/pl-NOECQDXD.js.map +1 -0
- package/dist/{pt-RPOVD4QM.js → pt-SVWIIUPC.js} +13 -1
- package/dist/pt-SVWIIUPC.js.map +1 -0
- package/dist/{ro-DMYWQTRD.js → ro-NR2DRTZG.js} +13 -1
- package/dist/ro-NR2DRTZG.js.map +1 -0
- package/dist/{sv-DMZ4FGXD.js → sv-STVJ37JP.js} +13 -1
- package/dist/sv-STVJ37JP.js.map +1 -0
- package/dist/test-utils.js +5 -3
- package/dist/test-utils.js.map +1 -1
- package/dist/{th-4HVBJBQ2.js → th-UWQR4K54.js} +13 -1
- package/dist/th-UWQR4K54.js.map +1 -0
- package/dist/{tr-6BDPU5ML.js → tr-WNXZSD27.js} +13 -1
- package/dist/tr-WNXZSD27.js.map +1 -0
- package/dist/{uk-TBZBT2TL.js → uk-SJRMB47Y.js} +13 -1
- package/dist/uk-SJRMB47Y.js.map +1 -0
- package/dist/{vi-UMKZKZL3.js → vi-TMRQFES2.js} +13 -1
- package/dist/vi-TMRQFES2.js.map +1 -0
- package/dist/{zh-YBJWJJYB.js → zh-QOL3LYEM.js} +13 -1
- package/dist/zh-QOL3LYEM.js.map +1 -0
- package/package.json +4 -4
- package/src/components/StatusDisplay.css +35 -35
- package/src/components/annotation/annotations.css +1 -1
- package/src/components/modals/SearchModal.css +5 -5
- package/src/components/pdf-annotation/PdfAnnotationCanvas.css +143 -6
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +622 -231
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +761 -2
- package/src/components/pdf-annotation/__tests__/estimate-slot-height.test.ts +53 -0
- package/src/components/pdf-annotation/estimate-slot-height.ts +31 -0
- package/src/components/resource/__tests__/browse-renderers.dispatch.test.tsx +33 -0
- package/src/components/resource/annotate-renderers.tsx +10 -1
- package/src/components/resource/browse-renderers.tsx +10 -1
- package/src/features/auth/auth.css +10 -10
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +26 -0
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +1 -1
- package/src/styles/core/inputs.css +1 -1
- package/src/styles/features/compose.css +1 -1
- package/src/styles/features/resource-viewer.css +1 -1
- package/src/styles/features/static-pages.css +11 -11
- package/src/styles/motivations/motivation-comment.css +2 -2
- package/src/styles/motivations/motivation-reference.css +2 -2
- package/src/styles/patterns/panels-base.css +4 -4
- package/src/styles/utilities/motion.css +15 -15
- package/src/styles/variables.css +29 -1
- package/translations/ar.json +10 -0
- package/translations/bn.json +10 -0
- package/translations/cs.json +10 -0
- package/translations/da.json +10 -0
- package/translations/de.json +10 -0
- package/translations/el.json +10 -0
- package/translations/en.json +10 -0
- package/translations/es.json +10 -0
- package/translations/fa.json +10 -0
- package/translations/fi.json +10 -0
- package/translations/fr.json +10 -0
- package/translations/he.json +10 -0
- package/translations/hi.json +10 -0
- package/translations/id.json +10 -0
- package/translations/it.json +10 -0
- package/translations/ja.json +10 -0
- package/translations/ko.json +10 -0
- package/translations/ms.json +10 -0
- package/translations/nl.json +10 -0
- package/translations/no.json +10 -0
- package/translations/pl.json +10 -0
- package/translations/pt.json +10 -0
- package/translations/ro.json +10 -0
- package/translations/sv.json +10 -0
- package/translations/th.json +10 -0
- package/translations/tr.json +10 -0
- package/translations/uk.json +10 -0
- package/translations/vi.json +10 -0
- package/translations/zh.json +10 -0
- package/dist/PdfAnnotationCanvas.client-EHQWF6BR.js +0 -462
- package/dist/PdfAnnotationCanvas.client-EHQWF6BR.js.map +0 -1
- package/dist/PdfAnnotationCanvas.client-SU5KNT7G.css +0 -98
- package/dist/PdfAnnotationCanvas.client-SU5KNT7G.css.map +0 -1
- package/dist/ar-CULRHLNG.js.map +0 -1
- package/dist/bn-HYR7CEL2.js.map +0 -1
- package/dist/chunk-NH6L2GIL.js.map +0 -1
- package/dist/chunk-TG2XQEC4.js.map +0 -1
- package/dist/cs-YBRWY7NH.js.map +0 -1
- package/dist/da-PHDEOBV3.js.map +0 -1
- package/dist/de-O4UCCVLJ.js.map +0 -1
- package/dist/el-MVGO6WZV.js.map +0 -1
- package/dist/es-USSLXQY7.js.map +0 -1
- package/dist/fa-WMAREFWY.js.map +0 -1
- package/dist/fi-B3NBNOTS.js.map +0 -1
- package/dist/fr-TXYK5T5W.js.map +0 -1
- package/dist/he-JCJACW5D.js.map +0 -1
- package/dist/hi-VOQLZNJU.js.map +0 -1
- package/dist/id-BFN5RZNZ.js.map +0 -1
- package/dist/it-TWWDHKKM.js.map +0 -1
- package/dist/ja-YRQLEBFM.js.map +0 -1
- package/dist/ko-PG6B3CRB.js.map +0 -1
- package/dist/ms-7EZECVKM.js.map +0 -1
- package/dist/nl-HP753YAP.js.map +0 -1
- package/dist/no-JUD5WX3N.js.map +0 -1
- package/dist/pl-RVUL4CBM.js.map +0 -1
- package/dist/pt-RPOVD4QM.js.map +0 -1
- package/dist/ro-DMYWQTRD.js.map +0 -1
- package/dist/sv-DMZ4FGXD.js.map +0 -1
- package/dist/th-4HVBJBQ2.js.map +0 -1
- package/dist/tr-6BDPU5ML.js.map +0 -1
- package/dist/uk-TBZBT2TL.js.map +0 -1
- package/dist/vi-UMKZKZL3.js.map +0 -1
- package/dist/zh-YBJWJJYB.js.map +0 -1
- /package/dist/{en-2KQILFKQ.js.map → en-3FCBW3YD.js.map} +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDF-CONTINUOUS-SCROLL S1b.
|
|
3
|
+
*
|
|
4
|
+
* The scroll column reserves space for unmounted pages. If the reservation is
|
|
5
|
+
* wrong, every mount and unmount changes the column's height and the scrollbar
|
|
6
|
+
* jumps — which is what S1 shipped, by reserving the raster height rather than
|
|
7
|
+
* the displayed one.
|
|
8
|
+
*
|
|
9
|
+
* These pins hold the estimate to the CSS the image is actually under:
|
|
10
|
+
* `max-width: 100%; height: auto`.
|
|
11
|
+
*/
|
|
12
|
+
import { describe, it, expect } from 'vitest';
|
|
13
|
+
import { estimateSlotHeight } from '../estimate-slot-height';
|
|
14
|
+
|
|
15
|
+
// US Letter at scale 1.5: 918 × 1188 raster, aspect 792/612.
|
|
16
|
+
const ASPECT = 792 / 612;
|
|
17
|
+
const RASTER_W = 918;
|
|
18
|
+
|
|
19
|
+
describe('estimateSlotHeight', () => {
|
|
20
|
+
it('scales to the column when the column is narrower than the raster', () => {
|
|
21
|
+
// The common case: `max-width: 100%` shrinks the image to the column.
|
|
22
|
+
expect(estimateSlotHeight(600, RASTER_W, ASPECT)).toBe(Math.round(600 * ASPECT));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('never upscales past the raster — max-width shrinks only', () => {
|
|
26
|
+
// A column wider than the raster leaves the image at natural size, so the
|
|
27
|
+
// height stops growing. Reserving columnWidth * aspect here would over-
|
|
28
|
+
// reserve and leave a gap under every page.
|
|
29
|
+
expect(estimateSlotHeight(1600, RASTER_W, ASPECT)).toBe(Math.round(RASTER_W * ASPECT));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('is exactly the raster height when the column matches the raster', () => {
|
|
33
|
+
expect(estimateSlotHeight(RASTER_W, RASTER_W, ASPECT)).toBe(Math.round(RASTER_W * ASPECT));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('does NOT use the raster height as a width-independent constant', () => {
|
|
37
|
+
// The S1 defect, stated as a pin: the raster is 1188px tall, but in a
|
|
38
|
+
// 600px column the page occupies ~776px. Reserving 1188 is what made the
|
|
39
|
+
// column's height lurch on every mount.
|
|
40
|
+
const rasterHeight = Math.round(RASTER_W * ASPECT); // 1188
|
|
41
|
+
expect(estimateSlotHeight(600, RASTER_W, ASPECT)).not.toBe(rasterHeight);
|
|
42
|
+
expect(estimateSlotHeight(600, RASTER_W, ASPECT)).toBeLessThan(rasterHeight);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('answers null until every measurement is in, rather than guessing', () => {
|
|
46
|
+
// A wrong reservation is worse than none: an unsized slot is stable, a
|
|
47
|
+
// mis-sized one moves when the page lands.
|
|
48
|
+
expect(estimateSlotHeight(null, RASTER_W, ASPECT)).toBeNull();
|
|
49
|
+
expect(estimateSlotHeight(600, null, ASPECT)).toBeNull();
|
|
50
|
+
expect(estimateSlotHeight(600, RASTER_W, null)).toBeNull();
|
|
51
|
+
expect(estimateSlotHeight(0, RASTER_W, ASPECT)).toBeNull();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The height a page will occupy once rendered, computed BEFORE rendering it.
|
|
3
|
+
*
|
|
4
|
+
* The scrolling column reserves space for pages it has not mounted. If the
|
|
5
|
+
* reserved height differs from the height the page actually takes, every mount
|
|
6
|
+
* and unmount changes the column's total height and the scrollbar jumps under
|
|
7
|
+
* the reader's cursor — the defect S1 shipped by reserving the *raster* height
|
|
8
|
+
* (`getViewport({ scale }).height`) instead of the *displayed* one.
|
|
9
|
+
*
|
|
10
|
+
* This models the CSS the image is under exactly:
|
|
11
|
+
*
|
|
12
|
+
* .semiont-pdf-annotation-canvas__image { max-width: 100%; height: auto; }
|
|
13
|
+
*
|
|
14
|
+
* `max-width` shrinks but never upscales, so the displayed width is
|
|
15
|
+
* `min(columnWidth, rasterWidth)` and the height follows the page's aspect
|
|
16
|
+
* ratio. Aspect is scale-invariant, so it can come from any viewport.
|
|
17
|
+
*
|
|
18
|
+
* @param columnWidth Measured inner width of the scroll column, in CSS px.
|
|
19
|
+
* @param rasterWidth Width of the rendered raster, in px (`viewport(scale).width`).
|
|
20
|
+
* @param aspect Page height ÷ width, from any viewport scale.
|
|
21
|
+
* @returns Reserved height in CSS px, or null when a measurement is not in yet.
|
|
22
|
+
*/
|
|
23
|
+
export function estimateSlotHeight(
|
|
24
|
+
columnWidth: number | null,
|
|
25
|
+
rasterWidth: number | null,
|
|
26
|
+
aspect: number | null,
|
|
27
|
+
): number | null {
|
|
28
|
+
if (!columnWidth || !rasterWidth || !aspect) return null;
|
|
29
|
+
if (columnWidth <= 0 || rasterWidth <= 0 || aspect <= 0) return null;
|
|
30
|
+
return Math.round(Math.min(columnWidth, rasterWidth) * aspect);
|
|
31
|
+
}
|
|
@@ -109,5 +109,38 @@ describe('browse-renderers — annotation + session forwarding (dispatch contrac
|
|
|
109
109
|
expect(props.existingAnnotations).toEqual([shapeAnnotation()]); // pinned — worked before
|
|
110
110
|
expect(props.drawingMode).toBeNull();
|
|
111
111
|
expect(props.session).toBe(session); // NEW — was a session-less no-op
|
|
112
|
+
// PDF-CONTINUOUS-SCROLL S1: browse asks for the scrolling column.
|
|
113
|
+
expect(props.pageLayout).toBe('scroll');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// S2. Annotate is the mode people actually work in
|
|
117
|
+
// (.plans/PDF-CONTINUOUS-SCROLL.md D3, second correction), so it gets the
|
|
118
|
+
// column too — leaving it on Previous/Next made the feature invisible to
|
|
119
|
+
// its primary audience.
|
|
120
|
+
it('the annotate registry asks for the column as well, with the live tool', async () => {
|
|
121
|
+
const session = fakeSession();
|
|
122
|
+
const { AnnotateView } = await import('../AnnotateView');
|
|
123
|
+
const { container } = render(
|
|
124
|
+
<AnnotateView
|
|
125
|
+
content="blob:pdf-url"
|
|
126
|
+
mimeType="application/pdf"
|
|
127
|
+
resourceUri="res-1"
|
|
128
|
+
annotations={emptyAnnotations}
|
|
129
|
+
uiState={{
|
|
130
|
+
selectedMotivation: 'highlighting',
|
|
131
|
+
selectedClick: 'detail',
|
|
132
|
+
selectedShape: 'rectangle',
|
|
133
|
+
hoveredAnnotationId: null,
|
|
134
|
+
scrollToAnnotationId: null,
|
|
135
|
+
}}
|
|
136
|
+
annotateMode
|
|
137
|
+
session={session}
|
|
138
|
+
/>,
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
await within(container).findByText('pdf-canvas-mock');
|
|
142
|
+
const props = captured.pdf.at(-1)!;
|
|
143
|
+
expect(props.pageLayout).toBe('scroll');
|
|
144
|
+
expect(props.drawingMode).toBe('rectangle'); // the tool still reaches the pages
|
|
112
145
|
});
|
|
113
146
|
});
|
|
@@ -7,10 +7,18 @@ import { SvgDrawingCanvas } from '../image-annotation/SvgDrawingCanvas';
|
|
|
7
7
|
import { CodeMirrorRenderer } from '../CodeMirrorRenderer';
|
|
8
8
|
import { segmentTextWithAnnotations } from '../../lib/text-segmentation';
|
|
9
9
|
import type { SelectionMotivation, ShapeType } from '../annotation/AnnotateToolbar';
|
|
10
|
+
import { useTranslations } from '../../contexts/TranslationContext';
|
|
10
11
|
|
|
11
12
|
// Lazy-load the PDF component to avoid SSR issues with browser PDF.js loading.
|
|
12
13
|
// Kept lazy here deliberately: hoisting it to a static import would make it
|
|
13
14
|
// eager again and reintroduce the SSR problem this indirection exists for.
|
|
15
|
+
/** The lazy chunk's fallback needs its own component: a hook cannot run
|
|
16
|
+
* inside a `fallback` prop expression. */
|
|
17
|
+
function PdfViewerLoading() {
|
|
18
|
+
const t = useTranslations('PdfViewer');
|
|
19
|
+
return <>{t('viewerLoading')}</>;
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
const PdfAnnotationCanvas = lazy(() =>
|
|
15
23
|
import('../pdf-annotation/PdfAnnotationCanvas.client').then((mod) => ({ default: mod.PdfAnnotationCanvas })),
|
|
16
24
|
);
|
|
@@ -127,7 +135,7 @@ export function PdfAnnotateRenderer({
|
|
|
127
135
|
}: AnnotateMediaRendererProps) {
|
|
128
136
|
if (!content) return null;
|
|
129
137
|
return (
|
|
130
|
-
<Suspense fallback={<div className="semiont-annotate-view__loading"
|
|
138
|
+
<Suspense fallback={<div className="semiont-annotate-view__loading"><PdfViewerLoading /></div>}>
|
|
131
139
|
<PdfAnnotationCanvas
|
|
132
140
|
pdfUrl={content}
|
|
133
141
|
resourceUri={resourceUri}
|
|
@@ -137,6 +145,7 @@ export function PdfAnnotateRenderer({
|
|
|
137
145
|
session={session}
|
|
138
146
|
hoveredAnnotationId={hoveredAnnotationId || null}
|
|
139
147
|
hoverDelayMs={hoverDelayMs}
|
|
148
|
+
pageLayout="scroll"
|
|
140
149
|
/>
|
|
141
150
|
</Suspense>
|
|
142
151
|
);
|
|
@@ -6,8 +6,16 @@ import remarkGfm from 'remark-gfm';
|
|
|
6
6
|
import type { Annotation } from '@semiont/core';
|
|
7
7
|
import type { SemiontSession } from '@semiont/sdk';
|
|
8
8
|
import { SvgDrawingCanvas } from '../image-annotation/SvgDrawingCanvas';
|
|
9
|
+
import { useTranslations } from '../../contexts/TranslationContext';
|
|
9
10
|
|
|
10
11
|
// Lazy-load the PDF component to avoid SSR issues with browser PDF.js loading.
|
|
12
|
+
/** The lazy chunk's fallback needs its own component: a hook cannot run
|
|
13
|
+
* inside a `fallback` prop expression. */
|
|
14
|
+
function PdfViewerLoading() {
|
|
15
|
+
const t = useTranslations('PdfViewer');
|
|
16
|
+
return <>{t('viewerLoading')}</>;
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
const PdfAnnotationCanvas = lazy(() => import('../pdf-annotation/PdfAnnotationCanvas.client').then(mod => ({ default: mod.PdfAnnotationCanvas })));
|
|
12
20
|
|
|
13
21
|
/**
|
|
@@ -60,7 +68,7 @@ export function ImageBrowseRenderer({ content, resourceUri, annotations, session
|
|
|
60
68
|
|
|
61
69
|
export function PdfBrowseRenderer({ content, resourceUri, annotations, session }: MediaRendererProps) {
|
|
62
70
|
return (
|
|
63
|
-
<Suspense fallback={<div className="semiont-browse-view__loading"
|
|
71
|
+
<Suspense fallback={<div className="semiont-browse-view__loading"><PdfViewerLoading /></div>}>
|
|
64
72
|
<PdfAnnotationCanvas
|
|
65
73
|
pdfUrl={content}
|
|
66
74
|
resourceUri={resourceUri}
|
|
@@ -68,6 +76,7 @@ export function PdfBrowseRenderer({ content, resourceUri, annotations, session }
|
|
|
68
76
|
drawingMode={null}
|
|
69
77
|
selectedMotivation={null}
|
|
70
78
|
session={session}
|
|
79
|
+
pageLayout="scroll"
|
|
71
80
|
/>
|
|
72
81
|
</Suspense>
|
|
73
82
|
);
|
|
@@ -316,12 +316,12 @@
|
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
.semiont-form__input-row:focus-visible {
|
|
319
|
-
outline: 2px solid var(--semiont-focus-ring
|
|
319
|
+
outline: 2px solid var(--semiont-focus-ring);
|
|
320
320
|
outline-offset: 2px;
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
[data-theme="dark"] .semiont-form__input-row:focus-visible {
|
|
324
|
-
outline-color: var(--semiont-focus-ring
|
|
324
|
+
outline-color: var(--semiont-focus-ring);
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
.semiont-form__input-row .semiont-input {
|
|
@@ -329,12 +329,12 @@
|
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
.semiont-form__input-row .semiont-input:focus-visible {
|
|
332
|
-
outline: 2px solid var(--semiont-focus-ring
|
|
332
|
+
outline: 2px solid var(--semiont-focus-ring);
|
|
333
333
|
outline-offset: 2px;
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
[data-theme="dark"] .semiont-form__input-row .semiont-input:focus-visible {
|
|
337
|
-
outline-color: var(--semiont-focus-ring
|
|
337
|
+
outline-color: var(--semiont-focus-ring);
|
|
338
338
|
}
|
|
339
339
|
|
|
340
340
|
.semiont-form__url-status {
|
|
@@ -345,27 +345,27 @@
|
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
.semiont-form__url-status--checking {
|
|
348
|
-
color: var(--semiont-text-
|
|
348
|
+
color: var(--semiont-text-tertiary);
|
|
349
349
|
animation: spin 1s linear infinite;
|
|
350
350
|
display: inline-block;
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
[data-theme="dark"] .semiont-form__url-status--checking {
|
|
354
|
-
color: var(--semiont-text-
|
|
354
|
+
color: var(--semiont-text-tertiary);
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
.semiont-form__url-status--ok {
|
|
358
|
-
color: var(--semiont-success
|
|
358
|
+
color: var(--semiont-color-success);
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
[data-theme="dark"] .semiont-form__url-status--ok {
|
|
362
|
-
color: var(--semiont-success
|
|
362
|
+
color: var(--semiont-color-success);
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
.semiont-form__url-status--error {
|
|
366
|
-
color: var(--semiont-error
|
|
366
|
+
color: var(--semiont-color-error);
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
[data-theme="dark"] .semiont-form__url-status--error {
|
|
370
|
-
color: var(--semiont-error
|
|
370
|
+
color: var(--semiont-color-error);
|
|
371
371
|
}
|
|
@@ -123,6 +123,15 @@ vi.mock('../../../contexts/ResourceAnnotationsContext', () => ({
|
|
|
123
123
|
ResourceAnnotationsProvider: ({ children }: any) => children,
|
|
124
124
|
}));
|
|
125
125
|
|
|
126
|
+
// Capture what ResourceViewerPage passes to useOutcomeToasts. The real hook is a
|
|
127
|
+
// pure event subscription, so standing it in costs the other specs nothing.
|
|
128
|
+
const outcomeToastsCalls = vi.hoisted(() => [] as unknown[]);
|
|
129
|
+
vi.mock('../../../hooks/useOutcomeToasts', () => ({
|
|
130
|
+
useOutcomeToasts: (resourceId: unknown) => {
|
|
131
|
+
outcomeToastsCalls.push(resourceId);
|
|
132
|
+
},
|
|
133
|
+
}));
|
|
134
|
+
|
|
126
135
|
// Mock useEventSubscription at the direct path used by ResourceViewerPage
|
|
127
136
|
// (the barrel export mock doesn't intercept direct context imports)
|
|
128
137
|
const mockUseEventSubscriptions = vi.fn();
|
|
@@ -180,6 +189,23 @@ const renderWithProviders = (ui: React.ReactElement) => {
|
|
|
180
189
|
);
|
|
181
190
|
};
|
|
182
191
|
|
|
192
|
+
describe('ResourceViewerPage — outcome toasts reach the user', () => {
|
|
193
|
+
// The decline/success toast was dropped for EVERY resource:
|
|
194
|
+
// `useOutcomeToasts(resource.id as string)` read a property
|
|
195
|
+
// `ResourceDescriptor` does not declare (it carries `@id`). The descriptor's
|
|
196
|
+
// open index signature made the access legal and the `as string` silenced its
|
|
197
|
+
// `unknown` type, so the hook's `event.resourceId !== resourceId` guard
|
|
198
|
+
// compared a real id against `undefined` and returned early every time.
|
|
199
|
+
it('subscribes with the resource id, not a property the descriptor lacks', () => {
|
|
200
|
+
outcomeToastsCalls.length = 0;
|
|
201
|
+
renderWithProviders(<ResourceViewerPage {...createMockProps()} />);
|
|
202
|
+
|
|
203
|
+
expect(outcomeToastsCalls).not.toHaveLength(0);
|
|
204
|
+
// Must be the resource's identity — `undefined` here silences every toast.
|
|
205
|
+
expect(outcomeToastsCalls[0]).toBe('test-123');
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
183
209
|
describe('ResourceViewerPage', () => {
|
|
184
210
|
beforeEach(() => {
|
|
185
211
|
});
|
|
@@ -396,7 +396,7 @@ export function ResourceViewerPage({
|
|
|
396
396
|
// assist timed-out) live in useOutcomeToasts — they need only the resource id
|
|
397
397
|
// and the toast surface. The registration below keeps the handlers that need
|
|
398
398
|
// page-local dependencies (SDK actions, sparkles, settings, navigation).
|
|
399
|
-
useOutcomeToasts(
|
|
399
|
+
useOutcomeToasts(rUri);
|
|
400
400
|
|
|
401
401
|
// Single useEventSubscriptions call per file (enforced by
|
|
402
402
|
// scripts/compliance/audit-hooks-ordering.ts); hooks like useOutcomeToasts
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
align-items: center;
|
|
138
138
|
padding: 0.5rem 0.5rem 0.5rem 0.75rem;
|
|
139
139
|
font-size: var(--semiont-text-sm);
|
|
140
|
-
font-family: var(--semiont-font-mono
|
|
140
|
+
font-family: var(--semiont-font-mono);
|
|
141
141
|
color: var(--semiont-text-tertiary);
|
|
142
142
|
background-color: var(--semiont-color-gray-50);
|
|
143
143
|
border-right: 1px solid var(--semiont-color-gray-300);
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
highlight while a drag hovers. */
|
|
119
119
|
.semiont-form__upload-dropzone[data-drag-over="true"] {
|
|
120
120
|
border-color: var(--semiont-color-primary-500);
|
|
121
|
-
background: var(--semiont-color-primary-50
|
|
121
|
+
background: var(--semiont-color-primary-50);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
/* Dark mode needs its own tint: primary-50 is a near-white wash that would
|
|
@@ -324,7 +324,7 @@
|
|
|
324
324
|
}
|
|
325
325
|
|
|
326
326
|
[data-theme="dark"] .semiont-browse-view__content tr:nth-child(even) td {
|
|
327
|
-
background: var(--semiont-color-gray-
|
|
327
|
+
background: var(--semiont-color-gray-800);
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
/* GFM task list checkboxes */
|
|
@@ -412,8 +412,8 @@
|
|
|
412
412
|
}
|
|
413
413
|
|
|
414
414
|
.semiont-static-warning-box {
|
|
415
|
-
background: var(--semiont-color-
|
|
416
|
-
border-left: 4px solid var(--semiont-color-
|
|
415
|
+
background: var(--semiont-color-amber-50);
|
|
416
|
+
border-left: 4px solid var(--semiont-color-amber-500);
|
|
417
417
|
border-radius: 0.375rem;
|
|
418
418
|
padding: 1rem 1.25rem;
|
|
419
419
|
margin: 1.5rem 0;
|
|
@@ -427,7 +427,7 @@
|
|
|
427
427
|
|
|
428
428
|
[data-theme="dark"] .semiont-static-warning-box {
|
|
429
429
|
background: rgba(251, 146, 60, 0.1);
|
|
430
|
-
border-left-color: var(--semiont-color-
|
|
430
|
+
border-left-color: var(--semiont-color-amber-400);
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
/* ========================================
|
|
@@ -447,27 +447,27 @@
|
|
|
447
447
|
|
|
448
448
|
.semiont-static-badge-planned {
|
|
449
449
|
background: rgba(251, 146, 60, 0.1);
|
|
450
|
-
color: var(--semiont-color-
|
|
451
|
-
border: 1px solid var(--semiont-color-
|
|
450
|
+
color: var(--semiont-color-amber-700);
|
|
451
|
+
border: 1px solid var(--semiont-color-amber-200);
|
|
452
452
|
}
|
|
453
453
|
|
|
454
454
|
.semiont-static-badge-active {
|
|
455
455
|
background: rgba(34, 197, 94, 0.1);
|
|
456
|
-
color: var(--semiont-color-
|
|
457
|
-
border: 1px solid var(--semiont-color-
|
|
456
|
+
color: var(--semiont-color-green-700);
|
|
457
|
+
border: 1px solid var(--semiont-color-green-200);
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
/* Dark mode */
|
|
461
461
|
[data-theme="dark"] .semiont-static-badge-planned {
|
|
462
462
|
background: rgba(251, 146, 60, 0.15);
|
|
463
|
-
color: var(--semiont-color-
|
|
464
|
-
border-color: var(--semiont-color-
|
|
463
|
+
color: var(--semiont-color-amber-400);
|
|
464
|
+
border-color: var(--semiont-color-amber-600);
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
[data-theme="dark"] .semiont-static-badge-active {
|
|
468
468
|
background: rgba(34, 197, 94, 0.15);
|
|
469
|
-
color: var(--semiont-color-
|
|
470
|
-
border-color: var(--semiont-color-
|
|
469
|
+
color: var(--semiont-color-green-400);
|
|
470
|
+
border-color: var(--semiont-color-green-600);
|
|
471
471
|
}
|
|
472
472
|
|
|
473
473
|
/* ========================================
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
--semiont-motivation-comment-panel-bg-dark: rgba(55, 65, 81, 0.2);
|
|
34
34
|
|
|
35
35
|
/* Button gradients */
|
|
36
|
-
--semiont-motivation-comment-button-bg: linear-gradient(to right, var(--semiont-color-purple-600), var(--semiont-color-
|
|
37
|
-
--semiont-motivation-comment-button-bg-hover: linear-gradient(to right, var(--semiont-color-purple-700), var(--semiont-color-
|
|
36
|
+
--semiont-motivation-comment-button-bg: linear-gradient(to right, var(--semiont-color-purple-600), var(--semiont-color-blue-600));
|
|
37
|
+
--semiont-motivation-comment-button-bg-hover: linear-gradient(to right, var(--semiont-color-purple-700), var(--semiont-color-blue-700));
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/* ============================================
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
/* Light theme colors */
|
|
15
15
|
--semiont-motivation-reference-primary: var(--semiont-color-cyan-600);
|
|
16
16
|
--semiont-motivation-reference-secondary: var(--semiont-color-blue-600);
|
|
17
|
-
--semiont-motivation-reference-bg: linear-gradient(to right, var(--semiont-color-cyan-200
|
|
18
|
-
--semiont-motivation-reference-bg-hover: linear-gradient(to right, var(--semiont-color-cyan-300
|
|
17
|
+
--semiont-motivation-reference-bg: linear-gradient(to right, var(--semiont-color-cyan-200), var(--semiont-color-blue-200));
|
|
18
|
+
--semiont-motivation-reference-bg-hover: linear-gradient(to right, var(--semiont-color-cyan-300), var(--semiont-color-blue-300));
|
|
19
19
|
--semiont-motivation-reference-border: rgba(6, 182, 212, 0.3);
|
|
20
20
|
--semiont-motivation-reference-border-hover: rgba(6, 182, 212, 0.5);
|
|
21
21
|
--semiont-motivation-reference-text: var(--semiont-color-gray-900);
|
|
@@ -405,12 +405,12 @@
|
|
|
405
405
|
|
|
406
406
|
/* Login form pulsing border for first-launch nudge */
|
|
407
407
|
@keyframes semiont-pulse-border {
|
|
408
|
-
0%, 100% { border-color: var(--semiont-color-primary-300
|
|
409
|
-
50% { border-color: var(--semiont-color-primary-600
|
|
408
|
+
0%, 100% { border-color: var(--semiont-color-primary-300); }
|
|
409
|
+
50% { border-color: var(--semiont-color-primary-600); }
|
|
410
410
|
}
|
|
411
411
|
|
|
412
412
|
.semiont-panel__login-form--pulsing {
|
|
413
|
-
border: 2px solid var(--semiont-color-primary-400
|
|
414
|
-
border-radius: var(--semiont-panel-border-radius
|
|
413
|
+
border: 2px solid var(--semiont-color-primary-400);
|
|
414
|
+
border-radius: var(--semiont-panel-border-radius);
|
|
415
415
|
animation: semiont-pulse-border 2s ease-in-out infinite;
|
|
416
416
|
}
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
.semiont-transition {
|
|
125
125
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
|
126
126
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
127
|
-
transition-duration: var(--semiont-duration-base
|
|
127
|
+
transition-duration: var(--semiont-duration-base);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
.semiont-transition-none {
|
|
@@ -134,58 +134,58 @@
|
|
|
134
134
|
.semiont-transition-all {
|
|
135
135
|
transition-property: all;
|
|
136
136
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
137
|
-
transition-duration: var(--semiont-duration-base
|
|
137
|
+
transition-duration: var(--semiont-duration-base);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
.semiont-transition-colors {
|
|
141
141
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
142
142
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
143
|
-
transition-duration: var(--semiont-duration-base
|
|
143
|
+
transition-duration: var(--semiont-duration-base);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
.semiont-transition-opacity {
|
|
147
147
|
transition-property: opacity;
|
|
148
148
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
149
|
-
transition-duration: var(--semiont-duration-base
|
|
149
|
+
transition-duration: var(--semiont-duration-base);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
.semiont-transition-transform {
|
|
153
153
|
transition-property: transform;
|
|
154
154
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
155
|
-
transition-duration: var(--semiont-duration-base
|
|
155
|
+
transition-duration: var(--semiont-duration-base);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
/* Animation classes */
|
|
159
159
|
.semiont-animate-fade-in {
|
|
160
|
-
animation: fadeIn var(--semiont-duration-base
|
|
160
|
+
animation: fadeIn var(--semiont-duration-base) ease-in-out;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
.semiont-animate-fade-out {
|
|
164
|
-
animation: fadeOut var(--semiont-duration-base
|
|
164
|
+
animation: fadeOut var(--semiont-duration-base) ease-in-out;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
.semiont-animate-slide-in-up {
|
|
168
|
-
animation: slideInUp var(--semiont-duration-
|
|
168
|
+
animation: slideInUp var(--semiont-duration-base) ease-out;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
.semiont-animate-slide-in-down {
|
|
172
|
-
animation: slideInDown var(--semiont-duration-
|
|
172
|
+
animation: slideInDown var(--semiont-duration-base) ease-out;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
.semiont-animate-slide-in-left {
|
|
176
|
-
animation: slideInLeft var(--semiont-duration-
|
|
176
|
+
animation: slideInLeft var(--semiont-duration-base) ease-out;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
.semiont-animate-slide-in-right {
|
|
180
|
-
animation: slideInRight var(--semiont-duration-
|
|
180
|
+
animation: slideInRight var(--semiont-duration-base) ease-out;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
.semiont-animate-scale-in {
|
|
184
|
-
animation: scaleIn var(--semiont-duration-base
|
|
184
|
+
animation: scaleIn var(--semiont-duration-base) ease-out;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
.semiont-animate-scale-out {
|
|
188
|
-
animation: scaleOut var(--semiont-duration-base
|
|
188
|
+
animation: scaleOut var(--semiont-duration-base) ease-in;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
.semiont-animate-spin {
|
|
@@ -299,13 +299,13 @@
|
|
|
299
299
|
.semiont-motion-safe-transition-all {
|
|
300
300
|
transition-property: all;
|
|
301
301
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
302
|
-
transition-duration: var(--semiont-duration-base
|
|
302
|
+
transition-duration: var(--semiont-duration-base);
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
.semiont-motion-safe-transition-transform {
|
|
306
306
|
transition-property: transform;
|
|
307
307
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
308
|
-
transition-duration: var(--semiont-duration-base
|
|
308
|
+
transition-duration: var(--semiont-duration-base);
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
|
package/src/styles/variables.css
CHANGED
|
@@ -177,6 +177,14 @@
|
|
|
177
177
|
--semiont-bg-tertiary: var(--semiont-color-neutral-100);
|
|
178
178
|
--semiont-bg-inverse: var(--semiont-color-neutral-900);
|
|
179
179
|
|
|
180
|
+
/* Borders — the panel/card border every pattern file reaches for. */
|
|
181
|
+
--semiont-border-primary: var(--semiont-color-neutral-200);
|
|
182
|
+
--semiont-border-secondary: var(--semiont-color-neutral-100);
|
|
183
|
+
|
|
184
|
+
/* Interaction */
|
|
185
|
+
--semiont-bg-hover: var(--semiont-color-neutral-100);
|
|
186
|
+
--semiont-focus-ring: var(--semiont-color-blue-500);
|
|
187
|
+
|
|
180
188
|
/* Text Colors */
|
|
181
189
|
--semiont-text-primary: var(--semiont-color-neutral-900);
|
|
182
190
|
--semiont-text-secondary: var(--semiont-color-neutral-600);
|
|
@@ -186,6 +194,8 @@
|
|
|
186
194
|
|
|
187
195
|
/* Spacing */
|
|
188
196
|
--semiont-spacing-0: 0;
|
|
197
|
+
--semiont-panel-gap-xs: 0.25rem;
|
|
198
|
+
--semiont-text-2xs: 0.625rem;
|
|
189
199
|
--semiont-spacing-xs: 0.25rem;
|
|
190
200
|
--semiont-spacing-sm: 0.5rem;
|
|
191
201
|
--semiont-spacing-md: 1rem;
|
|
@@ -322,6 +332,11 @@
|
|
|
322
332
|
--semiont-text-tertiary: var(--semiont-color-neutral-400);
|
|
323
333
|
--semiont-text-disabled: var(--semiont-color-neutral-600);
|
|
324
334
|
--semiont-text-inverse: var(--semiont-color-neutral-900);
|
|
335
|
+
|
|
336
|
+
--semiont-border-primary: var(--semiont-color-neutral-700);
|
|
337
|
+
--semiont-border-secondary: var(--semiont-color-neutral-800);
|
|
338
|
+
--semiont-bg-hover: var(--semiont-color-neutral-800);
|
|
339
|
+
--semiont-focus-ring: var(--semiont-color-blue-400);
|
|
325
340
|
}
|
|
326
341
|
}
|
|
327
342
|
|
|
@@ -337,6 +352,14 @@
|
|
|
337
352
|
--semiont-text-tertiary: var(--semiont-color-neutral-500);
|
|
338
353
|
--semiont-text-disabled: var(--semiont-color-neutral-400);
|
|
339
354
|
--semiont-text-inverse: var(--semiont-color-neutral-0);
|
|
355
|
+
|
|
356
|
+
/* Borders — the panel/card border every pattern file reaches for. */
|
|
357
|
+
--semiont-border-primary: var(--semiont-color-neutral-200);
|
|
358
|
+
--semiont-border-secondary: var(--semiont-color-neutral-100);
|
|
359
|
+
|
|
360
|
+
/* Interaction */
|
|
361
|
+
--semiont-bg-hover: var(--semiont-color-neutral-100);
|
|
362
|
+
--semiont-focus-ring: var(--semiont-color-blue-500);
|
|
340
363
|
}
|
|
341
364
|
|
|
342
365
|
/* Allow manual dark mode override */
|
|
@@ -351,4 +374,9 @@
|
|
|
351
374
|
--semiont-text-tertiary: var(--semiont-color-neutral-400);
|
|
352
375
|
--semiont-text-disabled: var(--semiont-color-neutral-600);
|
|
353
376
|
--semiont-text-inverse: var(--semiont-color-neutral-900);
|
|
354
|
-
|
|
377
|
+
|
|
378
|
+
--semiont-border-primary: var(--semiont-color-neutral-700);
|
|
379
|
+
--semiont-border-secondary: var(--semiont-color-neutral-800);
|
|
380
|
+
--semiont-bg-hover: var(--semiont-color-neutral-800);
|
|
381
|
+
--semiont-focus-ring: var(--semiont-color-blue-400);
|
|
382
|
+
}
|
package/translations/ar.json
CHANGED
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
"paramsTitle": "معاملات الطلب:",
|
|
5
5
|
"processing": "الحالي: {{label}}"
|
|
6
6
|
},
|
|
7
|
+
"PdfViewer": {
|
|
8
|
+
"loadFailed": "فشل تحميل ملف PDF",
|
|
9
|
+
"loading": "جارٍ تحميل PDF...",
|
|
10
|
+
"next": "التالي",
|
|
11
|
+
"pageLoadFailed": "فشل تحميل الصفحة",
|
|
12
|
+
"pageOf": "صفحة {{page}} من {{total}}",
|
|
13
|
+
"pagination": "ترقيم الصفحات",
|
|
14
|
+
"previous": "السابق",
|
|
15
|
+
"viewerLoading": "جارٍ تحميل عارض PDF..."
|
|
16
|
+
},
|
|
7
17
|
"Toolbar": {
|
|
8
18
|
"annotations": "التعليقات التوضيحية",
|
|
9
19
|
"history": "السجل",
|
package/translations/bn.json
CHANGED
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
"paramsTitle": "অনুরোধের প্যারামিটার:",
|
|
5
5
|
"processing": "বর্তমান: {{label}}"
|
|
6
6
|
},
|
|
7
|
+
"PdfViewer": {
|
|
8
|
+
"loadFailed": "PDF লোড করা যায়নি",
|
|
9
|
+
"loading": "PDF লোড হচ্ছে...",
|
|
10
|
+
"next": "পরবর্তী",
|
|
11
|
+
"pageLoadFailed": "পৃষ্ঠা লোড করা যায়নি",
|
|
12
|
+
"pageOf": "পৃষ্ঠা {{page}} / {{total}}",
|
|
13
|
+
"pagination": "পৃষ্ঠা নেভিগেশন",
|
|
14
|
+
"previous": "পূর্ববর্তী",
|
|
15
|
+
"viewerLoading": "PDF ভিউয়ার লোড হচ্ছে..."
|
|
16
|
+
},
|
|
7
17
|
"Toolbar": {
|
|
8
18
|
"annotations": "টীকাসমূহ",
|
|
9
19
|
"history": "ইতিহাস",
|
package/translations/cs.json
CHANGED
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
"paramsTitle": "Parametry požadavku:",
|
|
5
5
|
"processing": "Aktuální: {{label}}"
|
|
6
6
|
},
|
|
7
|
+
"PdfViewer": {
|
|
8
|
+
"loadFailed": "Nepodařilo se načíst PDF",
|
|
9
|
+
"loading": "Načítání PDF...",
|
|
10
|
+
"next": "Další",
|
|
11
|
+
"pageLoadFailed": "Nepodařilo se načíst stránku",
|
|
12
|
+
"pageOf": "Strana {{page}} z {{total}}",
|
|
13
|
+
"pagination": "Stránkování",
|
|
14
|
+
"previous": "Předchozí",
|
|
15
|
+
"viewerLoading": "Načítání prohlížeče PDF..."
|
|
16
|
+
},
|
|
7
17
|
"Toolbar": {
|
|
8
18
|
"annotations": "Anotace",
|
|
9
19
|
"history": "Historie",
|