flex-image-viewer 1.0.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 (67) hide show
  1. package/README.md +160 -0
  2. package/dist/FlexImageViewer/Content/index.js +193 -0
  3. package/dist/FlexImageViewer/Footer/Actions.js +115 -0
  4. package/dist/FlexImageViewer/Footer/index.js +56 -0
  5. package/dist/FlexImageViewer/Header/Actions.js +80 -0
  6. package/dist/FlexImageViewer/Header/index.js +42 -0
  7. package/dist/FlexImageViewer/Info/index.js +52 -0
  8. package/dist/FlexImageViewer/Thumbnail/index.js +90 -0
  9. package/dist/FlexImageViewer/index.css +582 -0
  10. package/dist/FlexImageViewer/index.js +117 -0
  11. package/dist/components/ActionItem.js +10 -0
  12. package/dist/components/BaseActions.js +69 -0
  13. package/dist/components/Icon/index.js +48 -0
  14. package/dist/components/Icon/svg/arrow-left.js +15 -0
  15. package/dist/components/Icon/svg/arrow-right.js +15 -0
  16. package/dist/components/Icon/svg/caret-right.js +15 -0
  17. package/dist/components/Icon/svg/check.js +15 -0
  18. package/dist/components/Icon/svg/clear.js +15 -0
  19. package/dist/components/Icon/svg/close.js +16 -0
  20. package/dist/components/Icon/svg/default-image.js +17 -0
  21. package/dist/components/Icon/svg/down.js +15 -0
  22. package/dist/components/Icon/svg/info-circle.js +20 -0
  23. package/dist/components/Icon/svg/rotate-left.js +20 -0
  24. package/dist/components/Icon/svg/rotate-right.js +20 -0
  25. package/dist/components/Icon/svg/save.js +15 -0
  26. package/dist/components/Icon/svg/size.js +19 -0
  27. package/dist/components/Icon/svg/thumbnail.js +19 -0
  28. package/dist/components/Icon/svg/zoom-adapt.js +24 -0
  29. package/dist/components/Icon/svg/zoom-in.js +15 -0
  30. package/dist/components/Icon/svg/zoom-out.js +15 -0
  31. package/dist/components/Image.js +148 -0
  32. package/dist/components/Modal.js +98 -0
  33. package/dist/components/PercentSelect.js +160 -0
  34. package/dist/components/ThumbnailIamge.js +65 -0
  35. package/dist/components/index.js +6 -0
  36. package/dist/context/ViewerContext.js +208 -0
  37. package/dist/hooks/useImageOperations.js +113 -0
  38. package/dist/hooks/useImageSource.js +52 -0
  39. package/dist/index.js +2 -0
  40. package/dist/rspress.config.d.ts +2 -0
  41. package/dist/src/FlexImageViewer/Content/index.d.ts +11 -0
  42. package/dist/src/FlexImageViewer/Footer/Actions.d.ts +13 -0
  43. package/dist/src/FlexImageViewer/Footer/index.d.ts +8 -0
  44. package/dist/src/FlexImageViewer/Header/Actions.d.ts +15 -0
  45. package/dist/src/FlexImageViewer/Header/index.d.ts +11 -0
  46. package/dist/src/FlexImageViewer/Info/index.d.ts +5 -0
  47. package/dist/src/FlexImageViewer/Thumbnail/index.d.ts +5 -0
  48. package/dist/src/FlexImageViewer/index.d.ts +21 -0
  49. package/dist/src/components/ActionItem.d.ts +6 -0
  50. package/dist/src/components/BaseActions.d.ts +17 -0
  51. package/dist/src/components/Icon/index.d.ts +6 -0
  52. package/dist/src/components/Image.d.ts +18 -0
  53. package/dist/src/components/Modal.d.ts +9 -0
  54. package/dist/src/components/PercentSelect.d.ts +17 -0
  55. package/dist/src/components/ThumbnailIamge.d.ts +8 -0
  56. package/dist/src/components/index.d.ts +13 -0
  57. package/dist/src/context/ViewerContext.d.ts +13 -0
  58. package/dist/src/hooks/useImageOperations.d.ts +12 -0
  59. package/dist/src/hooks/useImageSource.d.ts +7 -0
  60. package/dist/src/index.d.ts +6 -0
  61. package/dist/src/utils/dict.d.ts +1 -0
  62. package/dist/src/utils/exif.d.ts +2 -0
  63. package/dist/src/utils/source.d.ts +1 -0
  64. package/dist/utils/dict.js +16 -0
  65. package/dist/utils/exif.js +17 -0
  66. package/dist/utils/source.js +2 -0
  67. package/package.json +74 -0
@@ -0,0 +1,90 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { useInViewport } from "ahooks";
4
+ import { useViewerDispatch, useViewerState } from "../../context/ViewerContext.js";
5
+ import ThumbnailIamge from "../../components/ThumbnailIamge.js";
6
+ function ThumbnailItem(props) {
7
+ const { file, idx, currentIdx, angle, getThumbnail, onClick, onRef } = props;
8
+ const ref = useRef(null);
9
+ const [inViewport] = useInViewport(ref, {
10
+ threshold: 0
11
+ });
12
+ const [rendered, setRendered] = useState(idx === currentIdx);
13
+ useEffect(()=>{
14
+ onRef(ref.current, idx);
15
+ return ()=>onRef(null, idx);
16
+ }, [
17
+ idx,
18
+ onRef
19
+ ]);
20
+ useEffect(()=>{
21
+ if ((inViewport || idx === currentIdx) && !rendered) setRendered(true);
22
+ }, [
23
+ inViewport,
24
+ idx,
25
+ currentIdx,
26
+ rendered
27
+ ]);
28
+ return /*#__PURE__*/ jsx("li", {
29
+ ref: ref,
30
+ className: currentIdx === idx ? 'flex-image-viewer-thumbnail-active' : '',
31
+ onClick: onClick,
32
+ "aria-label": `缩略图 ${idx + 1}`,
33
+ role: "button",
34
+ tabIndex: 0,
35
+ children: rendered && /*#__PURE__*/ jsx(ThumbnailIamge, {
36
+ file: file,
37
+ angle: angle,
38
+ getThumbnail: getThumbnail
39
+ })
40
+ }, idx);
41
+ }
42
+ function Thumbnail(props) {
43
+ const { getThumbnail } = props;
44
+ const state = useViewerState();
45
+ const dispatch = useViewerDispatch();
46
+ const thumbnails = state.files;
47
+ const imageOptions = state.imageOptions;
48
+ const visible = state.thumbnailVisible;
49
+ const current = state.currentIndex;
50
+ const itemRefs = useRef(new Map());
51
+ const handleRef = useCallback((el, idx)=>{
52
+ if (el) itemRefs.current.set(idx, el);
53
+ else itemRefs.current.delete(idx);
54
+ }, []);
55
+ useEffect(()=>{
56
+ if (!thumbnails || 0 === thumbnails.length) return;
57
+ const index = current - 1;
58
+ const targetElement = itemRefs.current.get(index);
59
+ if (targetElement) targetElement.scrollIntoView({
60
+ behavior: 'smooth',
61
+ block: 'nearest',
62
+ inline: 'nearest'
63
+ });
64
+ }, [
65
+ current,
66
+ thumbnails
67
+ ]);
68
+ const index = current - 1;
69
+ return /*#__PURE__*/ jsx("nav", {
70
+ className: `flex-image-viewer-thumbnail ${visible ? 'visible' : ''}`,
71
+ "aria-label": "缩略图导航",
72
+ children: /*#__PURE__*/ jsx("div", {
73
+ children: /*#__PURE__*/ jsx("ul", {
74
+ children: thumbnails?.map((item, idx)=>/*#__PURE__*/ jsx(ThumbnailItem, {
75
+ file: item,
76
+ idx: idx,
77
+ currentIdx: index,
78
+ angle: imageOptions?.[idx]?.angle,
79
+ getThumbnail: getThumbnail,
80
+ onClick: ()=>dispatch({
81
+ type: 'SET_CURRENT_INDEX',
82
+ payload: idx + 1
83
+ }),
84
+ onRef: handleRef
85
+ }, idx))
86
+ })
87
+ })
88
+ });
89
+ }
90
+ export default Thumbnail;
@@ -0,0 +1,582 @@
1
+ :root {
2
+ --fiv-color-primary: #1890ff;
3
+ --fiv-color-bg-overlay: #00000080;
4
+ --fiv-color-bg-panel: #202020;
5
+ --fiv-color-bg-dark: #515151e6;
6
+ --fiv-color-bg-dark-hover: #51515180;
7
+ --fiv-color-bg-light: #fff;
8
+ --fiv-color-bg-disabled: #f5f5f5;
9
+ --fiv-color-bg-thumbnail: #0000001a;
10
+ --fiv-color-bg-selected: #e6f7ff;
11
+ --fiv-color-bg-hover: #f5f5f5;
12
+ --fiv-color-text-primary: #333;
13
+ --fiv-color-text-inverse: #fff;
14
+ --fiv-color-text-muted: #ffffffd9;
15
+ --fiv-color-text-disabled: #00000040;
16
+ --fiv-color-border: #d9d9d9;
17
+ --fiv-color-border-hover: #40a9ff;
18
+ --fiv-color-border-active: var(--fiv-color-primary);
19
+ --fiv-shadow-focus: 0 0 0 2px #1890ff33;
20
+ --fiv-shadow-dropdown: 0 2px 8px #00000026;
21
+ --fiv-spacing-xs: 2px;
22
+ --fiv-spacing-sm: 4px;
23
+ --fiv-spacing-md: 6px;
24
+ --fiv-spacing-lg: 8px;
25
+ --fiv-spacing-xl: 10px;
26
+ --fiv-spacing-2xl: 12px;
27
+ --fiv-spacing-3xl: 16px;
28
+ --fiv-spacing-4xl: 20px;
29
+ --fiv-size-tool: 30px;
30
+ --fiv-size-icon-sm: 12px;
31
+ --fiv-size-icon-md: 20px;
32
+ --fiv-size-icon-lg: 24px;
33
+ --fiv-size-thumbnail-width: 90px;
34
+ --fiv-size-thumbnail-height: 68px;
35
+ --fiv-size-info-panel-width: 300px;
36
+ --fiv-size-header-height: 36px;
37
+ --fiv-size-footer-height: 36px;
38
+ --fiv-size-footer-with-thumbnail: 160.88px;
39
+ --fiv-size-info-toggle: 16px;
40
+ --fiv-size-info-toggle-height: 30px;
41
+ --fiv-size-percent-input: 30px;
42
+ --fiv-size-percent-control-height: 24px;
43
+ --fiv-size-percent-dropdown-max: 200px;
44
+ --fiv-border-radius-sm: 3px;
45
+ --fiv-border-radius-md: 4px;
46
+ --fiv-animation-duration-fast: .3s;
47
+ --fiv-animation-ease: ease;
48
+ --fiv-z-index-modal: 1000;
49
+ --fiv-scrollbar-size: 6px;
50
+ --fiv-scrollbar-track: #0000001a;
51
+ --fiv-scrollbar-thumb: #ffffff4d;
52
+ --fiv-scrollbar-thumb-hover: #ffffff80;
53
+ }
54
+
55
+ @media (prefers-color-scheme: dark) {
56
+ :root {
57
+ --fiv-color-bg-light: #1f1f1f;
58
+ --fiv-color-bg-disabled: #2c2c2c;
59
+ --fiv-color-bg-selected: #1890ff33;
60
+ --fiv-color-bg-hover: #ffffff14;
61
+ --fiv-color-text-primary: #ffffffd9;
62
+ --fiv-color-text-disabled: #ffffff4d;
63
+ --fiv-color-border: #434343;
64
+ --fiv-color-border-hover: var(--fiv-color-primary);
65
+ --fiv-shadow-dropdown: 0 2px 8px #00000073;
66
+ }
67
+ }
68
+
69
+ .flex-image-viewer {
70
+ --fiv-layout-footer-offset: calc(var(--fiv-size-header-height) + var(--fiv-size-footer-height));
71
+ --fiv-layout-info-offset: 0px;
72
+ flex-direction: column;
73
+ justify-content: flex-start;
74
+ width: 100%;
75
+ height: 100%;
76
+ display: flex;
77
+ }
78
+
79
+ .flex-image-viewer.with-thumbnail {
80
+ --fiv-layout-footer-offset: var(--fiv-size-footer-with-thumbnail);
81
+ }
82
+
83
+ .flex-image-viewer.with-info {
84
+ --fiv-layout-info-offset: var(--fiv-size-info-panel-width);
85
+ }
86
+
87
+ .flex-image-viewer-main {
88
+ height: calc(100% - var(--fiv-layout-footer-offset));
89
+ flex: 1;
90
+ justify-content: flex-start;
91
+ align-items: center;
92
+ display: flex;
93
+ }
94
+
95
+ .flex-image-viewer-content {
96
+ width: calc(100% - var(--fiv-layout-info-offset));
97
+ }
98
+
99
+ div.rc-tooltip-inner {
100
+ min-height: auto;
101
+ }
102
+
103
+ .flex-image-viewer-container {
104
+ justify-content: center;
105
+ align-items: center;
106
+ width: 100%;
107
+ height: 100%;
108
+ display: flex;
109
+ overflow: hidden;
110
+ }
111
+
112
+ .flex-image-viewer-image {
113
+ transform-origin: center;
114
+ }
115
+
116
+ .flex-image-viewer-modal {
117
+ background-color: var(--fiv-color-bg-overlay);
118
+ z-index: var(--fiv-z-index-modal);
119
+ justify-content: center;
120
+ align-items: center;
121
+ display: flex;
122
+ position: fixed;
123
+ inset: 0;
124
+ }
125
+
126
+ .flex-image-viewer-percent-select {
127
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif;
128
+ display: inline-block;
129
+ position: relative;
130
+ }
131
+
132
+ .flex-image-viewer-percent-select-control {
133
+ border: 1px solid var(--fiv-color-border);
134
+ border-radius: var(--fiv-border-radius-md);
135
+ padding: 0 var(--fiv-spacing-lg);
136
+ cursor: pointer;
137
+ transition: all var(--fiv-animation-duration-fast);
138
+ color: var(--fiv-color-text-inverse);
139
+ height: var(--fiv-size-percent-control-height);
140
+ line-height: var(--fiv-size-percent-control-height);
141
+ align-items: center;
142
+ display: flex;
143
+ }
144
+
145
+ .flex-image-viewer-percent-select:hover .flex-image-viewer-percent-select-control {
146
+ border-color: var(--fiv-color-border-hover);
147
+ }
148
+
149
+ .flex-image-viewer-percent-select-open .flex-image-viewer-percent-select-control {
150
+ border-color: var(--fiv-color-border-hover);
151
+ box-shadow: var(--fiv-shadow-focus);
152
+ }
153
+
154
+ .flex-image-viewer-percent-select-input {
155
+ color: var(--fiv-color-text-inverse);
156
+ width: var(--fiv-size-percent-input);
157
+ text-align: right;
158
+ cursor: pointer;
159
+ background: none;
160
+ border: none;
161
+ outline: none;
162
+ font-size: 14px;
163
+ }
164
+
165
+ .flex-image-viewer-percent-select-input[readonly] {
166
+ cursor: pointer;
167
+ color: var(--fiv-color-text-inverse);
168
+ background-color: #0000;
169
+ }
170
+
171
+ .flex-image-viewer-percent-select-input-editing {
172
+ cursor: text;
173
+ }
174
+
175
+ .flex-image-viewer-percent-select-suffix {
176
+ color: var(--fiv-color-text-inverse);
177
+ pointer-events: none;
178
+ padding: 0 var(--fiv-spacing-xs);
179
+ font-size: 14px;
180
+ }
181
+
182
+ .flex-image-viewer-percent-select-arrow {
183
+ color: var(--fiv-color-text-inverse);
184
+ transition: transform var(--fiv-animation-duration-fast);
185
+ padding: 0 var(--fiv-spacing-sm);
186
+ }
187
+
188
+ div.flex-image-viewer-percent-select-arrow .flex-image-viewer-percent-select-arrow-icon {
189
+ font-size: var(--fiv-size-icon-sm);
190
+ }
191
+
192
+ .flex-image-viewer-percent-select-arrow-open {
193
+ transform: rotate(180deg);
194
+ }
195
+
196
+ .flex-image-viewer-percent-select-dropdown {
197
+ width: 100%;
198
+ margin-bottom: var(--fiv-spacing-sm);
199
+ background: var(--fiv-color-bg-light);
200
+ border: 1px solid var(--fiv-color-border);
201
+ border-radius: var(--fiv-border-radius-md);
202
+ box-shadow: var(--fiv-shadow-dropdown);
203
+ z-index: var(--fiv-z-index-modal);
204
+ max-height: var(--fiv-size-percent-dropdown-max);
205
+ position: absolute;
206
+ bottom: 100%;
207
+ left: 0;
208
+ overflow-y: auto;
209
+ }
210
+
211
+ .flex-image-viewer-percent-select-options {
212
+ padding: var(--fiv-spacing-sm) 0;
213
+ }
214
+
215
+ .flex-image-viewer-percent-select-option {
216
+ padding: 5px var(--fiv-spacing-2xl);
217
+ color: var(--fiv-color-text-primary);
218
+ cursor: pointer;
219
+ transition: background-color var(--fiv-animation-duration-fast);
220
+ justify-content: space-between;
221
+ align-items: center;
222
+ font-size: 14px;
223
+ display: flex;
224
+ }
225
+
226
+ .flex-image-viewer-percent-select-option:hover {
227
+ background-color: var(--fiv-color-bg-hover);
228
+ }
229
+
230
+ .flex-image-viewer-percent-select-option-selected {
231
+ background-color: var(--fiv-color-bg-selected);
232
+ color: var(--fiv-color-primary);
233
+ font-weight: 500;
234
+ }
235
+
236
+ .flex-image-viewer-percent-select-check {
237
+ color: var(--fiv-color-primary);
238
+ font-weight: bold;
239
+ }
240
+
241
+ div.flex-image-viewer-percent-select-check .flex-image-viewer-percent-select-check-icon {
242
+ font-size: 8px;
243
+ }
244
+
245
+ .flex-image-viewer-percent-select-disabled .flex-image-viewer-percent-select-control {
246
+ background-color: var(--fiv-color-bg-disabled);
247
+ border-color: var(--fiv-color-border);
248
+ cursor: not-allowed;
249
+ }
250
+
251
+ .flex-image-viewer-percent-select-disabled .flex-image-viewer-percent-select-input {
252
+ cursor: not-allowed;
253
+ color: var(--fiv-color-text-disabled);
254
+ }
255
+
256
+ .flex-image-viewer-content {
257
+ flex: 1;
258
+ justify-content: space-between;
259
+ align-items: center;
260
+ height: 100%;
261
+ display: flex;
262
+ position: relative;
263
+ }
264
+
265
+ .flex-image-viewer-content-tool-left, .flex-image-viewer-content-tool-right {
266
+ width: var(--fiv-size-tool);
267
+ padding: 0 var(--fiv-spacing-md);
268
+ z-index: 1;
269
+ justify-content: center;
270
+ align-items: center;
271
+ display: flex;
272
+ position: absolute;
273
+ top: 0;
274
+ bottom: 0;
275
+ }
276
+
277
+ .flex-image-viewer-content-tool-left > span, .flex-image-viewer-content-tool-right > span {
278
+ width: var(--fiv-size-tool);
279
+ height: var(--fiv-size-tool);
280
+ border-radius: var(--fiv-border-radius-md);
281
+ background-color: var(--fiv-color-bg-dark);
282
+ cursor: pointer;
283
+ justify-content: center;
284
+ align-items: center;
285
+ display: none;
286
+ }
287
+
288
+ .flex-image-viewer-content-tool-left:hover > span, .flex-image-viewer-content-tool-right:hover > span {
289
+ display: flex;
290
+ }
291
+
292
+ .flex-image-viewer-content-tool-left > span:hover, .flex-image-viewer-content-tool-right > span:hover {
293
+ background-color: var(--fiv-color-bg-dark-hover);
294
+ }
295
+
296
+ .flex-image-viewer-content-tool-left svg, .flex-image-viewer-content-tool-right svg {
297
+ font-size: var(--fiv-size-icon-md);
298
+ color: var(--fiv-color-text-inverse);
299
+ }
300
+
301
+ .flex-image-viewer-content-tool-left {
302
+ left: 0;
303
+ }
304
+
305
+ .flex-image-viewer-content-tool-right {
306
+ right: 0;
307
+ }
308
+
309
+ .flex-image-viewer-content-image {
310
+ justify-content: center;
311
+ align-items: center;
312
+ width: 100%;
313
+ height: 100%;
314
+ display: flex;
315
+ overflow: hidden;
316
+ }
317
+
318
+ .flex-image-viewer-header {
319
+ background-color: var(--fiv-color-bg-overlay);
320
+ padding: var(--fiv-spacing-md) var(--fiv-spacing-xl) var(--fiv-spacing-md) var(--fiv-spacing-4xl);
321
+ color: var(--fiv-color-text-muted);
322
+ justify-content: space-between;
323
+ align-items: center;
324
+ display: flex;
325
+ }
326
+
327
+ .flex-image-viewer-header-title {
328
+ justify-content: flex-start;
329
+ align-items: center;
330
+ display: flex;
331
+ }
332
+
333
+ .flex-image-viewer-header-count {
334
+ letter-spacing: var(--fiv-spacing-sm);
335
+ }
336
+
337
+ .flex-image-viewer-header-name {
338
+ padding: 0 var(--fiv-spacing-xl);
339
+ }
340
+
341
+ .flex-image-viewer-footer {
342
+ background-color: var(--fiv-color-bg-overlay);
343
+ padding: var(--fiv-spacing-md) var(--fiv-spacing-xl) var(--fiv-spacing-md) var(--fiv-spacing-4xl);
344
+ color: var(--fiv-color-text-muted);
345
+ justify-content: space-between;
346
+ align-items: center;
347
+ display: flex;
348
+ }
349
+
350
+ .flex-image-viewer-footer-title {
351
+ justify-content: flex-start;
352
+ align-items: center;
353
+ display: flex;
354
+ }
355
+
356
+ .flex-image-viewer-footer-size {
357
+ margin-right: var(--fiv-spacing-xl);
358
+ }
359
+
360
+ .flex-image-viewer-footer-size, .flex-image-viewer-footer-memory {
361
+ justify-content: flex-start;
362
+ align-items: center;
363
+ display: flex;
364
+ }
365
+
366
+ .flex-image-viewer-footer-size svg, .flex-image-viewer-footer-memory svg {
367
+ margin-right: var(--fiv-spacing-sm);
368
+ }
369
+
370
+ .flex-image-viewer-actions {
371
+ justify-content: end;
372
+ align-items: center;
373
+ margin: 0;
374
+ padding: 0;
375
+ display: flex;
376
+ }
377
+
378
+ .flex-image-viewer-actions .flex-image-viewer-action-item {
379
+ padding: 0 var(--fiv-spacing-xl);
380
+ height: var(--fiv-size-percent-control-height);
381
+ list-style: none;
382
+ }
383
+
384
+ .flex-image-viewer-actions .flex-image-viewer-action-item .flex-image-viewer-icon {
385
+ font-size: var(--fiv-size-icon-lg);
386
+ cursor: pointer;
387
+ }
388
+
389
+ .flex-image-viewer-actions .flex-image-viewer-action-item .flex-image-viewer-icon:hover {
390
+ color: var(--fiv-color-text-inverse);
391
+ }
392
+
393
+ .flex-image-viewer-info {
394
+ background-color: var(--fiv-color-bg-panel);
395
+ opacity: 0;
396
+ visibility: hidden;
397
+ width: 0;
398
+ height: 100%;
399
+ transition: width var(--fiv-animation-duration-fast) var(--fiv-animation-ease),
400
+ opacity var(--fiv-animation-duration-fast) var(--fiv-animation-ease),
401
+ visibility var(--fiv-animation-duration-fast) var(--fiv-animation-ease);
402
+ justify-content: flex-start;
403
+ align-items: center;
404
+ display: flex;
405
+ overflow: hidden;
406
+ }
407
+
408
+ .flex-image-viewer-info.visible {
409
+ width: var(--fiv-size-info-panel-width);
410
+ opacity: 1;
411
+ visibility: visible;
412
+ width: auto;
413
+ }
414
+
415
+ .flex-image-viewer-info-tool {
416
+ justify-content: center;
417
+ align-items: center;
418
+ height: 100%;
419
+ display: flex;
420
+ }
421
+
422
+ .flex-image-viewer-info-tool span {
423
+ width: var(--fiv-size-info-toggle);
424
+ height: var(--fiv-size-info-toggle-height);
425
+ background-color: var(--fiv-color-bg-dark);
426
+ cursor: pointer;
427
+ color: var(--fiv-color-text-inverse);
428
+ border-top-right-radius: var(--fiv-border-radius-md);
429
+ border-bottom-right-radius: var(--fiv-border-radius-md);
430
+ justify-content: center;
431
+ align-items: center;
432
+ display: flex;
433
+ }
434
+
435
+ .flex-image-viewer-info-tool span:hover {
436
+ background-color: var(--fiv-color-bg-dark-hover);
437
+ }
438
+
439
+ .flex-image-viewer-info ul {
440
+ height: 100%;
441
+ padding: var(--fiv-spacing-xl) var(--fiv-spacing-xl) var(--fiv-spacing-xl) 0;
442
+ box-sizing: border-box;
443
+ flex: 1;
444
+ margin: 0;
445
+ }
446
+
447
+ .flex-image-viewer-info ul li {
448
+ color: var(--fiv-color-text-inverse);
449
+ padding: var(--fiv-spacing-sm) 0;
450
+ justify-content: flex-start;
451
+ font-size: 14px;
452
+ list-style: none;
453
+ display: flex;
454
+ }
455
+
456
+ .flex-image-viewer-info ul li span {
457
+ min-width: 60px;
458
+ }
459
+
460
+ .flex-image-viewer-info ul li p {
461
+ flex: 1;
462
+ margin: 0;
463
+ }
464
+
465
+ .flex-image-viewer-thumbnail {
466
+ background-color: var(--fiv-color-bg-thumbnail);
467
+ opacity: 0;
468
+ visibility: hidden;
469
+ height: 0;
470
+ transition: height var(--fiv-animation-duration-fast) var(--fiv-animation-ease),
471
+ opacity var(--fiv-animation-duration-fast) var(--fiv-animation-ease),
472
+ visibility var(--fiv-animation-duration-fast) var(--fiv-animation-ease);
473
+ justify-content: center;
474
+ align-items: center;
475
+ display: flex;
476
+ overflow: hidden;
477
+ }
478
+
479
+ .flex-image-viewer-thumbnail.visible {
480
+ opacity: 1;
481
+ visibility: visible;
482
+ height: auto;
483
+ }
484
+
485
+ .flex-image-viewer-thumbnail ul {
486
+ padding: var(--fiv-spacing-md);
487
+ flex-wrap: nowrap;
488
+ justify-content: flex-start;
489
+ align-items: center;
490
+ margin: 0;
491
+ display: flex;
492
+ }
493
+
494
+ .flex-image-viewer-thumbnail > div {
495
+ scroll-behavior: smooth;
496
+ overflow-x: auto;
497
+ }
498
+
499
+ .flex-image-viewer-thumbnail > div::-webkit-scrollbar {
500
+ height: var(--fiv-scrollbar-size);
501
+ }
502
+
503
+ .flex-image-viewer-thumbnail > div::-webkit-scrollbar-track {
504
+ background: var(--fiv-scrollbar-track);
505
+ }
506
+
507
+ .flex-image-viewer-thumbnail > div::-webkit-scrollbar-thumb {
508
+ background: var(--fiv-scrollbar-thumb);
509
+ border-radius: var(--fiv-border-radius-sm);
510
+ }
511
+
512
+ .flex-image-viewer-thumbnail > div::-webkit-scrollbar-thumb:hover {
513
+ background: var(--fiv-scrollbar-thumb-hover);
514
+ }
515
+
516
+ .flex-image-viewer-thumbnail ul li {
517
+ width: var(--fiv-size-thumbnail-width);
518
+ height: var(--fiv-size-thumbnail-height);
519
+ border-radius: var(--fiv-border-radius-md);
520
+ background-color: var(--fiv-color-bg-dark);
521
+ cursor: pointer;
522
+ margin: 0 var(--fiv-spacing-md);
523
+ border: 2px solid var(--fiv-color-bg-dark);
524
+ flex: none;
525
+ list-style: none;
526
+ overflow: hidden;
527
+ }
528
+
529
+ .flex-image-viewer-thumbnail ul li.flex-image-viewer-thumbnail-active {
530
+ border-color: var(--fiv-color-border-active);
531
+ }
532
+
533
+ .flex-image-viewer-thumbnail ul li:hover {
534
+ background-color: var(--fiv-color-bg-dark-hover);
535
+ }
536
+
537
+ .flex-image-viewer-thumbnail-container {
538
+ justify-content: center;
539
+ align-items: center;
540
+ width: 100%;
541
+ height: 100%;
542
+ display: flex;
543
+ position: relative;
544
+ overflow: hidden;
545
+ }
546
+
547
+ .flex-image-viewer-thumbnail-image {
548
+ transform-origin: center;
549
+ }
550
+
551
+ .flex-image-viewer-error {
552
+ background-color: var(--fiv-color-bg-dark);
553
+ color: var(--fiv-color-text-muted);
554
+ justify-content: center;
555
+ align-items: center;
556
+ font-size: 14px;
557
+ display: flex;
558
+ position: absolute;
559
+ inset: 0;
560
+ }
561
+
562
+ .flex-image-viewer-error:before {
563
+ content: "图片加载失败";
564
+ }
565
+
566
+ .flex-image-viewer-loading {
567
+ z-index: 2;
568
+ border: 3px solid #fff3;
569
+ border-top-color: var(--fiv-color-primary);
570
+ border-radius: 50%;
571
+ width: 32px;
572
+ height: 32px;
573
+ animation: 1s linear infinite flex-image-viewer-spin;
574
+ position: absolute;
575
+ }
576
+
577
+ @keyframes flex-image-viewer-spin {
578
+ to {
579
+ transform: rotate(360deg);
580
+ }
581
+ }
582
+