@pdf-viewer/react 1.5.1 → 1.6.0-beta.10
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/RPDefaultLayout-4518b3d3.js +3059 -0
- package/dist/SearchCloseButton-959cc1ed.js +32 -0
- package/dist/assets/Container.css +1 -1
- package/dist/assets/PasswordModal.css +1 -0
- package/dist/assets/RPDefaultLayout.css +1 -1
- package/dist/assets/SearchCloseButton.css +1 -0
- package/dist/components/RPController.js +1 -1
- package/dist/components/RPPages.js +4 -2
- package/dist/components/RPProvider.js +13 -12
- package/dist/components/layout/Container.js +7 -6
- package/dist/components/layout/LayoutContainer.js +3 -2
- package/dist/components/layout/RPDefaultLayout.js +1 -1
- package/dist/components/layout/sidebar/RPSidebar.js +1 -1
- package/dist/components/layout/sidebar/Thumbnail.js +1 -1
- package/dist/components/layout/sidebar/Thumbnails.js +1 -1
- package/dist/components/layout/toolbar/DocumentDialog.js +3 -2
- package/dist/components/layout/toolbar/FileDownloadTool.js +1 -1
- package/dist/components/layout/toolbar/MenuItem.js +1 -1
- package/dist/components/layout/toolbar/MenuSeparator.js +1 -1
- package/dist/components/layout/toolbar/MostPageTool.js +4 -3
- package/dist/components/layout/toolbar/OtherTool.js +2 -2
- package/dist/components/layout/toolbar/Paginate.js +1 -1
- package/dist/components/layout/toolbar/PrintTool.js +1 -1
- package/dist/components/layout/toolbar/RPToolbar.js +1 -1
- package/dist/components/layout/toolbar/RPToolbarEnd.js +1 -1
- package/dist/components/layout/toolbar/RotateTool.js +1 -1
- package/dist/components/layout/toolbar/ScrollModeTool.js +1 -1
- package/dist/components/layout/toolbar/SearchCloseButton.js +9 -0
- package/dist/components/layout/toolbar/SearchResultNavigator.js +10 -0
- package/dist/components/layout/toolbar/SearchTool.js +5 -4
- package/dist/components/layout/toolbar/SelectionModeTool.js +1 -1
- package/dist/components/layout/toolbar/ViewModeTool.js +18 -19
- package/dist/components/layout/toolbar/ZoomTool.js +8 -27
- package/dist/components/page/AnnotationLayer.js +3 -2
- package/dist/components/page/CanvasLayer.js +3 -2
- package/dist/components/page/DualPage.js +1 -1
- package/dist/components/page/RPPage.js +3 -2
- package/dist/components/page/SinglePage.js +1 -1
- package/dist/components/page/TextHighlightLayer.js +3 -2
- package/dist/components/page/TextLayer.js +3 -2
- package/dist/components/ui/Checkbox.js +14 -13
- package/dist/components/ui/DropDown.js +1 -1
- package/dist/components/ui/LoadingIndicator.js +1 -1
- package/dist/components/ui/PasswordModal.js +58 -0
- package/dist/components/ui/RPTooltip.js +689 -331
- package/dist/contexts/DocumentPasswordContext.js +40 -0
- package/dist/contexts/PaginationContext.js +1 -1
- package/dist/contexts/PrintContext.js +1 -1
- package/dist/contexts/RPDocumentContext.js +11 -8
- package/dist/contexts/SearchContext.js +1 -1
- package/dist/contexts/SmoothScrollContext.js +8 -9
- package/dist/contexts/ThumbnailsContext.js +1 -1
- package/dist/contexts/ToolbarComponentContext.js +2 -2
- package/dist/contexts/ViewModeContext.js +16 -17
- package/dist/contexts/ZoomContext.js +17 -16
- package/dist/index-2e540713.js +23 -0
- package/dist/index-353ec0a6.js +172 -0
- package/dist/index-5ff5dbd0.js +1675 -0
- package/dist/index-71898eb9.js +139 -0
- package/dist/main.js +1 -1
- package/dist/types/components/layout/toolbar/SearchCloseButton.d.ts +7 -0
- package/dist/types/components/layout/toolbar/SearchResultNavigator.d.ts +1 -0
- package/dist/types/components/layout/toolbar/ViewModeTool.d.ts +1 -1
- package/dist/types/components/ui/PasswordModal.d.ts +3 -0
- package/dist/types/contexts/DocumentPasswordContext.d.ts +14 -0
- package/dist/types/contexts/SmoothScrollContext.d.ts +1 -3
- package/dist/types/utils/constants.d.ts +1 -0
- package/dist/types/utils/getScrollDistance.d.ts +1 -0
- package/dist/types/utils/getWordPositionInPage.d.ts +11 -0
- package/dist/types/utils/getZoomLevel.d.ts +2 -2
- package/dist/types/utils/hooks/useLoadPdf.d.ts +2 -0
- package/dist/types/utils/types.d.ts +20 -3
- package/dist/utils/constants.js +3 -2
- package/dist/utils/getScrollDistance.js +4 -0
- package/dist/utils/getWordPositionInPage.js +19 -0
- package/dist/utils/getZoomLevel.js +13 -9
- package/dist/utils/highlight.js +141 -126
- package/dist/utils/hooks/useFileDownload.js +3 -2
- package/dist/utils/hooks/useLicense.js +1 -1
- package/dist/utils/hooks/useLoadPdf.js +52 -40
- package/dist/utils/hooks/usePaginate.js +4 -2
- package/dist/utils/hooks/usePinch.js +68 -17
- package/dist/utils/hooks/usePresentPage.js +3 -2
- package/dist/utils/hooks/usePrint.js +3 -2
- package/dist/utils/hooks/useScrollToPage.js +4 -2
- package/dist/utils/hooks/useSearch.js +5 -3
- package/dist/utils/hooks/useThumbnail.js +3 -2
- package/dist/utils/hooks/useVirtualReactWindow.js +3 -2
- package/dist/utils/types.js +4 -4
- package/package.json +1 -1
- package/dist/RPDefaultLayout-ed089918.js +0 -2958
- package/dist/index-1cb41342.js +0 -307
- package/dist/index-7279fb4e.js +0 -1557
- package/dist/index-aa2d3884.js +0 -140
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import * as i from "react";
|
|
2
|
+
import { jsx as C } from "react/jsx-runtime";
|
|
3
|
+
function m(e, n) {
|
|
4
|
+
const t = i.createContext(n), r = (s) => {
|
|
5
|
+
const { children: o, ...c } = s, a = i.useMemo(() => c, Object.values(c));
|
|
6
|
+
return /* @__PURE__ */ C(t.Provider, { value: a, children: o });
|
|
7
|
+
};
|
|
8
|
+
r.displayName = e + "Provider";
|
|
9
|
+
function u(s) {
|
|
10
|
+
const o = i.useContext(t);
|
|
11
|
+
if (o)
|
|
12
|
+
return o;
|
|
13
|
+
if (n !== void 0)
|
|
14
|
+
return n;
|
|
15
|
+
throw new Error(`\`${s}\` must be used within \`${e}\``);
|
|
16
|
+
}
|
|
17
|
+
return [r, u];
|
|
18
|
+
}
|
|
19
|
+
function E(e, n = []) {
|
|
20
|
+
let t = [];
|
|
21
|
+
function r(s, o) {
|
|
22
|
+
const c = i.createContext(o), a = t.length;
|
|
23
|
+
t = [...t, o];
|
|
24
|
+
const f = (d) => {
|
|
25
|
+
var b;
|
|
26
|
+
const { scope: l, children: S, ...v } = d, h = ((b = l == null ? void 0 : l[e]) == null ? void 0 : b[a]) || c, z = i.useMemo(() => v, Object.values(v));
|
|
27
|
+
return /* @__PURE__ */ C(h.Provider, { value: z, children: S });
|
|
28
|
+
};
|
|
29
|
+
f.displayName = s + "Provider";
|
|
30
|
+
function x(d, l) {
|
|
31
|
+
var h;
|
|
32
|
+
const S = ((h = l == null ? void 0 : l[e]) == null ? void 0 : h[a]) || c, v = i.useContext(S);
|
|
33
|
+
if (v)
|
|
34
|
+
return v;
|
|
35
|
+
if (o !== void 0)
|
|
36
|
+
return o;
|
|
37
|
+
throw new Error(`\`${d}\` must be used within \`${s}\``);
|
|
38
|
+
}
|
|
39
|
+
return [f, x];
|
|
40
|
+
}
|
|
41
|
+
const u = () => {
|
|
42
|
+
const s = t.map((o) => i.createContext(o));
|
|
43
|
+
return function(c) {
|
|
44
|
+
const a = (c == null ? void 0 : c[e]) || s;
|
|
45
|
+
return i.useMemo(
|
|
46
|
+
() => ({ [`__scope${e}`]: { ...c, [e]: a } }),
|
|
47
|
+
[c, a]
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
return u.scopeName = e, [r, P(u, ...n)];
|
|
52
|
+
}
|
|
53
|
+
function P(...e) {
|
|
54
|
+
const n = e[0];
|
|
55
|
+
if (e.length === 1)
|
|
56
|
+
return n;
|
|
57
|
+
const t = () => {
|
|
58
|
+
const r = e.map((u) => ({
|
|
59
|
+
useScope: u(),
|
|
60
|
+
scopeName: u.scopeName
|
|
61
|
+
}));
|
|
62
|
+
return function(s) {
|
|
63
|
+
const o = r.reduce((c, { useScope: a, scopeName: f }) => {
|
|
64
|
+
const d = a(s)[`__scope${f}`];
|
|
65
|
+
return { ...c, ...d };
|
|
66
|
+
}, {});
|
|
67
|
+
return i.useMemo(() => ({ [`__scope${n.scopeName}`]: o }), [o]);
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
return t.scopeName = n.scopeName, t;
|
|
71
|
+
}
|
|
72
|
+
function y(e) {
|
|
73
|
+
const n = i.useRef(e);
|
|
74
|
+
return i.useEffect(() => {
|
|
75
|
+
n.current = e;
|
|
76
|
+
}), i.useMemo(() => (...t) => {
|
|
77
|
+
var r;
|
|
78
|
+
return (r = n.current) == null ? void 0 : r.call(n, ...t);
|
|
79
|
+
}, []);
|
|
80
|
+
}
|
|
81
|
+
var g = globalThis != null && globalThis.document ? i.useLayoutEffect : () => {
|
|
82
|
+
};
|
|
83
|
+
function $(e) {
|
|
84
|
+
const [n, t] = i.useState(void 0);
|
|
85
|
+
return g(() => {
|
|
86
|
+
if (e) {
|
|
87
|
+
t({ width: e.offsetWidth, height: e.offsetHeight });
|
|
88
|
+
const r = new ResizeObserver((u) => {
|
|
89
|
+
if (!Array.isArray(u) || !u.length)
|
|
90
|
+
return;
|
|
91
|
+
const s = u[0];
|
|
92
|
+
let o, c;
|
|
93
|
+
if ("borderBoxSize" in s) {
|
|
94
|
+
const a = s.borderBoxSize, f = Array.isArray(a) ? a[0] : a;
|
|
95
|
+
o = f.inlineSize, c = f.blockSize;
|
|
96
|
+
} else
|
|
97
|
+
o = e.offsetWidth, c = e.offsetHeight;
|
|
98
|
+
t({ width: o, height: c });
|
|
99
|
+
});
|
|
100
|
+
return r.observe(e, { box: "border-box" }), () => r.unobserve(e);
|
|
101
|
+
} else
|
|
102
|
+
t(void 0);
|
|
103
|
+
}, [e]), n;
|
|
104
|
+
}
|
|
105
|
+
function _({
|
|
106
|
+
prop: e,
|
|
107
|
+
defaultProp: n,
|
|
108
|
+
onChange: t = () => {
|
|
109
|
+
}
|
|
110
|
+
}) {
|
|
111
|
+
const [r, u] = p({ defaultProp: n, onChange: t }), s = e !== void 0, o = s ? e : r, c = y(t), a = i.useCallback(
|
|
112
|
+
(f) => {
|
|
113
|
+
if (s) {
|
|
114
|
+
const d = typeof f == "function" ? f(e) : f;
|
|
115
|
+
d !== e && c(d);
|
|
116
|
+
} else
|
|
117
|
+
u(f);
|
|
118
|
+
},
|
|
119
|
+
[s, e, u, c]
|
|
120
|
+
);
|
|
121
|
+
return [o, a];
|
|
122
|
+
}
|
|
123
|
+
function p({
|
|
124
|
+
defaultProp: e,
|
|
125
|
+
onChange: n
|
|
126
|
+
}) {
|
|
127
|
+
const t = i.useState(e), [r] = t, u = i.useRef(r), s = y(n);
|
|
128
|
+
return i.useEffect(() => {
|
|
129
|
+
u.current !== r && (s(r), u.current = r);
|
|
130
|
+
}, [r, u, s]), t;
|
|
131
|
+
}
|
|
132
|
+
export {
|
|
133
|
+
g as a,
|
|
134
|
+
_ as b,
|
|
135
|
+
E as c,
|
|
136
|
+
$ as d,
|
|
137
|
+
m as e,
|
|
138
|
+
y as u
|
|
139
|
+
};
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RPProvider as t } from "./components/RPProvider.js";
|
|
2
|
-
import { b as x, R as n, c as s, u as m, d as p, e as f } from "./RPDefaultLayout-
|
|
2
|
+
import { b as x, R as n, c as s, u as m, d as p, e as f } from "./RPDefaultLayout-4518b3d3.js";
|
|
3
3
|
import { RPConfig as a } from "./components/RPConfig.js";
|
|
4
4
|
import { RPController as l } from "./components/RPController.js";
|
|
5
5
|
import { RPTheme as P } from "./components/RPTheme.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SearchResultNavigator: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const ViewModeTool: () => import("react/jsx-runtime").JSX.Element
|
|
1
|
+
export declare const ViewModeTool: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
export interface DocumentPasswordContextType {
|
|
3
|
+
password?: string;
|
|
4
|
+
setPassword: React.Dispatch<React.SetStateAction<string | undefined>>;
|
|
5
|
+
passwordError?: string;
|
|
6
|
+
setPasswordError: React.Dispatch<React.SetStateAction<string | undefined>>;
|
|
7
|
+
passwordRequired?: boolean;
|
|
8
|
+
setPasswordRequired: React.Dispatch<React.SetStateAction<boolean | undefined>>;
|
|
9
|
+
invalidPassword?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare const DocumentPasswordContext: React.Context<DocumentPasswordContextType>;
|
|
12
|
+
export declare const DocumentPasswordProvider: FC<PropsWithChildren>;
|
|
13
|
+
export declare const useDocumentPasswordContext: () => DocumentPasswordContextType;
|
|
14
|
+
export default DocumentPasswordContext;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { ScrollPosition } from '../utils/types';
|
|
2
1
|
interface SmoothScrollContextType {
|
|
3
|
-
|
|
4
|
-
targetScrollPosition: React.MutableRefObject<ScrollPosition>;
|
|
2
|
+
targetScrollPage: React.MutableRefObject<number | undefined>;
|
|
5
3
|
}
|
|
6
4
|
export declare const SmoothScrollProvider: ({ children }: {
|
|
7
5
|
children: React.ReactNode;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getScrollDistance: (distanceList: number[], targetIndex: number) => number;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { WordPositionRect } from './types';
|
|
2
|
+
export declare const getWordPositionInPage: (matchPageDimension: {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
}, space: {
|
|
6
|
+
top: number;
|
|
7
|
+
left: number;
|
|
8
|
+
}, wordPosition: WordPositionRect, scale: number, rotation: number) => {
|
|
9
|
+
leftInPage: number;
|
|
10
|
+
topInPage: number;
|
|
11
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ZoomLevel } from './types';
|
|
2
|
-
export declare const getZoomLevel: (zoomLevel: number | ZoomLevel, clientWidth: number, clientHeight: number, pageWidth: number, pageHeight: number) => number;
|
|
1
|
+
import { ZoomLevel, ViewMode } from './types';
|
|
2
|
+
export declare const getZoomLevel: (zoomLevel: number | ZoomLevel, clientWidth: number, clientHeight: number, pageWidth: number, pageHeight: number, viewMode: ViewMode) => number;
|
|
@@ -140,6 +140,11 @@ export type Localization = {
|
|
|
140
140
|
propertiesPDFVersionLabel?: string;
|
|
141
141
|
propertiesPageCountLabel?: string;
|
|
142
142
|
thumbnailTooltip?: string;
|
|
143
|
+
passwordModalTitle?: string;
|
|
144
|
+
passwordModalMessage?: string;
|
|
145
|
+
passwordPlaceholder?: string;
|
|
146
|
+
passwordConfirmLabel?: string;
|
|
147
|
+
passwordError?: string;
|
|
143
148
|
dragDropFileMessage?: string;
|
|
144
149
|
};
|
|
145
150
|
interface Attachment {
|
|
@@ -324,7 +329,6 @@ export interface RPSlots {
|
|
|
324
329
|
dropFileZone?: boolean | React.ReactNode | React.ComponentType;
|
|
325
330
|
downloadTool?: boolean | FC<DownloadToolProps>;
|
|
326
331
|
zoomTool?: boolean | FC<ZoomProps>;
|
|
327
|
-
viewModeTool?: boolean;
|
|
328
332
|
scrollModeTool?: boolean;
|
|
329
333
|
thumbnailTool?: boolean | FC<ThumbnailToolProps>;
|
|
330
334
|
pageNavigationTool?: boolean | FC<PageNavigationToolProps>;
|
|
@@ -446,7 +450,13 @@ export declare enum ThemeVariables {
|
|
|
446
450
|
TEXT_LAYER_HIGHLIGHT_BORDER_RADIUS = "--rp-text-layer-highlight-border-radius",
|
|
447
451
|
CURRENT_HIGHLIGHT_BACKGROUND_COLOR = "--rp-current-highlight-background-color",
|
|
448
452
|
TOOLTIP_BACKGROUND_COLOR = "--rp-tooltip-background-color",
|
|
449
|
-
TOOLTIP_BORDER_RADIUS = "--rp-tooltip-border-radius"
|
|
453
|
+
TOOLTIP_BORDER_RADIUS = "--rp-tooltip-border-radius",
|
|
454
|
+
PASSWORD_MODAL_BACKGROUND = "--rp-password-background",
|
|
455
|
+
PASSWORD_MODAL_TITLE_COLOR = "--rp-password-title-color",
|
|
456
|
+
PASSWORD_MODAL_CONTENT_COLOR = "--rp-password-content-color",
|
|
457
|
+
CONTAINER_FOCUS_OUTLINE_WIDTH = "--rp-container-focus-outline-width",
|
|
458
|
+
CONTAINER_FOCUS_OUTLINE_COLOR = "--rp-container-focus-outline-color",
|
|
459
|
+
CONTAINER_FOCUS_OUTLINE_OFFSET = "--rp-container-focus-outline-offset"
|
|
450
460
|
}
|
|
451
461
|
export interface DarkModeProviderProps extends PropsWithChildren, Partial<Omit<DarkMode, 'setDarkMode'>> {
|
|
452
462
|
}
|
|
@@ -500,7 +510,7 @@ export interface ZoomContextType {
|
|
|
500
510
|
export type ZoomProps = Omit<ZoomContextType, 'currentZoom'>;
|
|
501
511
|
export type InitialStateContextType = {
|
|
502
512
|
instanceId: string;
|
|
503
|
-
} & ZoomProviderProps & PageProviderProps &
|
|
513
|
+
} & ZoomProviderProps & PageProviderProps & ScrollModeProps & RotateProviderProps;
|
|
504
514
|
export interface ZoomProviderProps {
|
|
505
515
|
initialScale?: number | ZoomLevel;
|
|
506
516
|
}
|
|
@@ -532,6 +542,12 @@ export interface ScrollModeContextType {
|
|
|
532
542
|
export interface ScrollModeProps {
|
|
533
543
|
initialScrollMode?: ScrollMode;
|
|
534
544
|
}
|
|
545
|
+
export interface WordPositionRect {
|
|
546
|
+
left: number;
|
|
547
|
+
top: number;
|
|
548
|
+
width: number;
|
|
549
|
+
height: number;
|
|
550
|
+
}
|
|
535
551
|
export interface Match {
|
|
536
552
|
start: {
|
|
537
553
|
idx: number;
|
|
@@ -544,6 +560,7 @@ export interface Match {
|
|
|
544
560
|
str: string;
|
|
545
561
|
oIndex: number;
|
|
546
562
|
pageIndex: number;
|
|
563
|
+
rect: WordPositionRect;
|
|
547
564
|
}
|
|
548
565
|
export interface MatchValue extends Match {
|
|
549
566
|
page: number;
|
package/dist/utils/constants.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const a = (n, c) => {
|
|
2
|
+
const t = c * (Math.PI / 180);
|
|
3
|
+
return {
|
|
4
|
+
x: n.x * Math.cos(t) - n.y * Math.sin(t),
|
|
5
|
+
y: n.x * Math.sin(t) + n.y * Math.cos(t)
|
|
6
|
+
};
|
|
7
|
+
}, W = (n, c, t, e, h) => {
|
|
8
|
+
const s = t.height * e, r = t.width * e, f = t.top * e, g = t.left * e, M = n.height - f, { x: p, y: i } = a(
|
|
9
|
+
{ x: r, y: s },
|
|
10
|
+
h
|
|
11
|
+
), d = c.left + Math.abs(p) / 2, x = c.top + Math.abs(i) / 2, { x: y, y: u } = a({ x: g, y: M }, h), o = {
|
|
12
|
+
left: y,
|
|
13
|
+
top: u
|
|
14
|
+
}, P = o.left - d, I = o.top - x;
|
|
15
|
+
return { leftInPage: P, topInPage: I };
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
W as getWordPositionInPage
|
|
19
|
+
};
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { SCROLL_BAR_WIDTH as s } from "./constants.js";
|
|
2
|
+
import { ZoomLevel as e, ViewMode as c } from "./types.js";
|
|
3
|
+
const Z = (o, t, m, r, a, u) => {
|
|
3
4
|
if (typeof o == "number")
|
|
4
5
|
return o;
|
|
5
6
|
switch (o) {
|
|
6
|
-
case
|
|
7
|
+
case e.ACTUAL:
|
|
7
8
|
return 100;
|
|
8
|
-
case
|
|
9
|
+
case e.PAGE_FIT:
|
|
9
10
|
let n = 0;
|
|
10
|
-
const
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const l = u === c.DUAL_PAGE ? 2 * r : r;
|
|
12
|
+
return n = Math.min(
|
|
13
|
+
(t - s) / l,
|
|
14
|
+
m / a
|
|
15
|
+
), Math.floor(n * 100);
|
|
16
|
+
case e.PAGE_WIDTH:
|
|
17
|
+
return Math.floor(t / r * 100);
|
|
14
18
|
default:
|
|
15
19
|
return 100;
|
|
16
20
|
}
|
|
17
21
|
};
|
|
18
22
|
export {
|
|
19
|
-
|
|
23
|
+
Z as getZoomLevel
|
|
20
24
|
};
|