@shelamkoff/rector 1.0.1 → 1.0.3

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 (63) hide show
  1. package/README.md +25 -24
  2. package/dist/core/clipboard/Clipboard.d.ts +2 -0
  3. package/dist/core/clipboard/Clipboard.js +52 -24
  4. package/dist/core/index.js +195 -194
  5. package/dist/core/locale/en.d.ts +1 -0
  6. package/dist/core/locale/en.js +1 -0
  7. package/dist/core/locale/ru.d.ts +1 -0
  8. package/dist/core/locale/ru.js +1 -0
  9. package/dist/core/themes/light.css +1 -1
  10. package/dist/core/themes/variables.css +72 -10
  11. package/dist/locale/en.d.ts +41 -0
  12. package/dist/locale/ru.d.ts +41 -0
  13. package/dist/plugins/attaches/attaches.css +16 -14
  14. package/dist/plugins/attaches/index.js +997 -920
  15. package/dist/plugins/attaches/locale/en.d.ts +9 -0
  16. package/dist/plugins/attaches/locale/en.js +11 -2
  17. package/dist/plugins/attaches/locale/ru.d.ts +9 -0
  18. package/dist/plugins/attaches/locale/ru.js +11 -2
  19. package/dist/plugins/carousel/carousel.css +213 -49
  20. package/dist/plugins/carousel/index.js +918 -858
  21. package/dist/plugins/carousel/locale/en.d.ts +15 -0
  22. package/dist/plugins/carousel/locale/en.js +18 -3
  23. package/dist/plugins/carousel/locale/ru.d.ts +15 -0
  24. package/dist/plugins/carousel/locale/ru.js +18 -3
  25. package/dist/plugins/gallery/README.md +92 -92
  26. package/dist/plugins/gallery/README.ru.md +17 -17
  27. package/dist/plugins/gallery/gallery.css +44 -19
  28. package/dist/plugins/gallery/index.js +375 -354
  29. package/dist/plugins/gallery/locale/en.d.ts +8 -0
  30. package/dist/plugins/gallery/locale/en.js +11 -3
  31. package/dist/plugins/gallery/locale/ru.d.ts +8 -0
  32. package/dist/plugins/gallery/locale/ru.js +11 -3
  33. package/dist/plugins/gallery/settings.js +15 -10
  34. package/dist/plugins/gallery/view-empty.d.ts +2 -0
  35. package/dist/plugins/gallery/view-empty.js +21 -15
  36. package/dist/plugins/gallery/view-filled.d.ts +2 -2
  37. package/dist/plugins/gallery/view-filled.js +84 -72
  38. package/dist/plugins/image/image.css +7 -2
  39. package/dist/plugins/image/index.js +365 -345
  40. package/dist/plugins/image/locale/en.d.ts +8 -0
  41. package/dist/plugins/image/locale/en.js +11 -3
  42. package/dist/plugins/image/locale/ru.d.ts +8 -0
  43. package/dist/plugins/image/locale/ru.js +11 -3
  44. package/dist/plugins/image/view-empty.d.ts +2 -0
  45. package/dist/plugins/image/view-empty.js +21 -15
  46. package/dist/plugins/image/view-filled.d.ts +2 -2
  47. package/dist/plugins/image/view-filled.js +77 -72
  48. package/dist/plugins/shared/dropzone.d.ts +6 -0
  49. package/dist/plugins/shared/dropzone.js +47 -36
  50. package/dist/plugins/shared/layer.d.ts +13 -0
  51. package/dist/plugins/shared/layer.js +45 -0
  52. package/dist/plugins/shared/sourceEditor.css +165 -0
  53. package/dist/plugins/shared/sourceEditor.d.ts +97 -0
  54. package/dist/plugins/shared/sourceEditor.js +260 -0
  55. package/dist/renderer/renderers/carousel/index.js +24 -23
  56. package/dist/renderer/renderers/carousel/styles.css +8 -2
  57. package/dist/renderer/renderers/gallery/README.md +41 -41
  58. package/dist/renderer/renderers/gallery/README.ru.md +41 -41
  59. package/dist/renderer/renderers/gallery/index.js +100 -85
  60. package/dist/renderer/renderers/gallery/styles.css +417 -401
  61. package/dist/shared/galleryMasonry.d.ts +34 -0
  62. package/dist/shared/galleryMasonry.js +152 -0
  63. package/package.json +29 -28
@@ -7,10 +7,25 @@ declare const _default: {
7
7
  'plugin.carousel.upload': string;
8
8
  'plugin.carousel.back': string;
9
9
  'plugin.carousel.dropzoneText': string;
10
+ 'plugin.carousel.dropzoneUrlPrefix': string;
11
+ 'plugin.carousel.dropzoneUrl': string;
12
+ 'plugin.carousel.dropzoneHtmlPrefix': string;
13
+ 'plugin.carousel.dropzoneHtml': string;
14
+ 'plugin.carousel.urlEditorTitle': string;
15
+ 'plugin.carousel.urlEditorLabel': string;
16
+ 'plugin.carousel.urlEditorPlaceholder': string;
17
+ 'plugin.carousel.htmlEditorTitle': string;
18
+ 'plugin.carousel.htmlEditorLabel': string;
19
+ 'plugin.carousel.htmlEditorPlaceholder': string;
20
+ 'plugin.carousel.sourceSubmit': string;
21
+ 'plugin.carousel.sourceCancel': string;
22
+ 'plugin.carousel.invalidUrl': string;
23
+ 'plugin.carousel.invalidHtml': string;
10
24
  'plugin.carousel.empty': string;
11
25
  'plugin.carousel.emptyReadonly': string;
12
26
  'plugin.carousel.html': string;
13
27
  'plugin.carousel.source': string;
28
+ 'plugin.carousel.embeddedSource': string;
14
29
  'plugin.carousel.alt': string;
15
30
  'plugin.carousel.poster': string;
16
31
  'plugin.carousel.caption': string;
@@ -7,10 +7,25 @@ export default {
7
7
  'plugin.carousel.upload': 'Upload',
8
8
  'plugin.carousel.back': 'Back',
9
9
  'plugin.carousel.dropzoneText': 'images or videos from your device or drag and drop them here',
10
+ 'plugin.carousel.dropzoneUrlPrefix': 'or',
11
+ 'plugin.carousel.dropzoneUrl': 'insert by URL',
12
+ 'plugin.carousel.dropzoneHtmlPrefix': 'or',
13
+ 'plugin.carousel.dropzoneHtml': 'insert HTML',
14
+ 'plugin.carousel.urlEditorTitle': 'Add media by URL',
15
+ 'plugin.carousel.urlEditorLabel': 'Media URL',
16
+ 'plugin.carousel.urlEditorPlaceholder': 'https://example.com/image.jpg',
17
+ 'plugin.carousel.htmlEditorTitle': 'Add HTML slide',
18
+ 'plugin.carousel.htmlEditorLabel': 'Slide HTML',
19
+ 'plugin.carousel.htmlEditorPlaceholder': '<article>...</article>',
20
+ 'plugin.carousel.sourceSubmit': 'Add',
21
+ 'plugin.carousel.sourceCancel': 'Cancel',
22
+ 'plugin.carousel.invalidUrl': 'Enter a valid media URL.',
23
+ 'plugin.carousel.invalidHtml': 'Enter valid slide HTML.',
10
24
  'plugin.carousel.empty': 'Add the first slide',
11
25
  'plugin.carousel.emptyReadonly': 'No slides',
12
26
  'plugin.carousel.html': 'HTML',
13
27
  'plugin.carousel.source': 'Source URL',
28
+ 'plugin.carousel.embeddedSource': 'Local file — paste a URL to replace it',
14
29
  'plugin.carousel.alt': 'Alternative text',
15
30
  'plugin.carousel.poster': 'Poster URL',
16
31
  'plugin.carousel.caption': 'Caption',
@@ -22,9 +37,9 @@ export default {
22
37
  'plugin.carousel.movePreviousShort': 'Earlier',
23
38
  'plugin.carousel.moveNextShort': 'Later',
24
39
  'plugin.carousel.remove': 'Remove',
25
- 'plugin.carousel.removeSlide': 'Remove slide',
26
- 'plugin.carousel.deleteAll': 'Remove all slides',
27
- 'plugin.carousel.video': 'Video slide',
40
+ 'plugin.carousel.removeSlide': 'Remove slide',
41
+ 'plugin.carousel.deleteAll': 'Remove all slides',
42
+ 'plugin.carousel.video': 'Video slide',
28
43
  'plugin.carousel.settings': 'Settings',
29
44
  'plugin.carousel.currentSlide': 'Current slide',
30
45
  'plugin.carousel.behavior': 'Behavior',
@@ -7,10 +7,25 @@ declare const _default: {
7
7
  'plugin.carousel.upload': string;
8
8
  'plugin.carousel.back': string;
9
9
  'plugin.carousel.dropzoneText': string;
10
+ 'plugin.carousel.dropzoneUrlPrefix': string;
11
+ 'plugin.carousel.dropzoneUrl': string;
12
+ 'plugin.carousel.dropzoneHtmlPrefix': string;
13
+ 'plugin.carousel.dropzoneHtml': string;
14
+ 'plugin.carousel.urlEditorTitle': string;
15
+ 'plugin.carousel.urlEditorLabel': string;
16
+ 'plugin.carousel.urlEditorPlaceholder': string;
17
+ 'plugin.carousel.htmlEditorTitle': string;
18
+ 'plugin.carousel.htmlEditorLabel': string;
19
+ 'plugin.carousel.htmlEditorPlaceholder': string;
20
+ 'plugin.carousel.sourceSubmit': string;
21
+ 'plugin.carousel.sourceCancel': string;
22
+ 'plugin.carousel.invalidUrl': string;
23
+ 'plugin.carousel.invalidHtml': string;
10
24
  'plugin.carousel.empty': string;
11
25
  'plugin.carousel.emptyReadonly': string;
12
26
  'plugin.carousel.html': string;
13
27
  'plugin.carousel.source': string;
28
+ 'plugin.carousel.embeddedSource': string;
14
29
  'plugin.carousel.alt': string;
15
30
  'plugin.carousel.poster': string;
16
31
  'plugin.carousel.caption': string;
@@ -7,10 +7,25 @@ export default {
7
7
  'plugin.carousel.upload': 'Загрузить',
8
8
  'plugin.carousel.back': 'Назад',
9
9
  'plugin.carousel.dropzoneText': 'изображения или видео с устройства либо перетащите их сюда',
10
+ 'plugin.carousel.dropzoneUrlPrefix': 'или',
11
+ 'plugin.carousel.dropzoneUrl': 'вставьте по URL',
12
+ 'plugin.carousel.dropzoneHtmlPrefix': 'или',
13
+ 'plugin.carousel.dropzoneHtml': 'вставьте HTML',
14
+ 'plugin.carousel.urlEditorTitle': 'Добавление медиафайла по URL',
15
+ 'plugin.carousel.urlEditorLabel': 'URL медиафайла',
16
+ 'plugin.carousel.urlEditorPlaceholder': 'https://example.com/image.jpg',
17
+ 'plugin.carousel.htmlEditorTitle': 'Добавление HTML-слайда',
18
+ 'plugin.carousel.htmlEditorLabel': 'HTML-код слайда',
19
+ 'plugin.carousel.htmlEditorPlaceholder': '<article>...</article>',
20
+ 'plugin.carousel.sourceSubmit': 'Добавить',
21
+ 'plugin.carousel.sourceCancel': 'Отмена',
22
+ 'plugin.carousel.invalidUrl': 'Введите корректный URL медиафайла.',
23
+ 'plugin.carousel.invalidHtml': 'Введите корректный HTML-код слайда.',
10
24
  'plugin.carousel.empty': 'Добавьте первый слайд',
11
25
  'plugin.carousel.emptyReadonly': 'Слайдов нет',
12
26
  'plugin.carousel.html': 'HTML',
13
27
  'plugin.carousel.source': 'URL источника',
28
+ 'plugin.carousel.embeddedSource': 'Локальный файл — вставьте URL для замены',
14
29
  'plugin.carousel.alt': 'Альтернативный текст',
15
30
  'plugin.carousel.poster': 'URL постера',
16
31
  'plugin.carousel.caption': 'Подпись',
@@ -22,9 +37,9 @@ export default {
22
37
  'plugin.carousel.movePreviousShort': 'Раньше',
23
38
  'plugin.carousel.moveNextShort': 'Позже',
24
39
  'plugin.carousel.remove': 'Удалить',
25
- 'plugin.carousel.removeSlide': 'Удалить слайд',
26
- 'plugin.carousel.deleteAll': 'Удалить все слайды',
27
- 'plugin.carousel.video': 'Видеослайд',
40
+ 'plugin.carousel.removeSlide': 'Удалить слайд',
41
+ 'plugin.carousel.deleteAll': 'Удалить все слайды',
42
+ 'plugin.carousel.video': 'Видеослайд',
28
43
  'plugin.carousel.settings': 'Настройки',
29
44
  'plugin.carousel.currentSlide': 'Текущий слайд',
30
45
  'plugin.carousel.behavior': 'Поведение',
@@ -1,92 +1,92 @@
1
- # Gallery block plugin
2
-
3
- Multi-image gallery with layouts, captions, appearance settings, reordering, and viewer options.
4
-
5
- ## Install and register
6
-
7
- ```bash
8
- npm install @shelamkoff/rector
9
- ```
10
-
11
- ```js
12
- import { createEditor } from '@shelamkoff/rector'
13
- import { Gallery } from '@shelamkoff/rector/plugins/gallery'
14
- import '@shelamkoff/rector/styles/editor.css'
15
-
16
- const editor = createEditor({
17
- holder: document.querySelector('#editor'),
18
- plugins: [new Gallery()],
19
- })
20
- ```
21
-
22
- The registered block type is `gallery`. The class is also exported by the complete `@shelamkoff/rector/plugins` preset and can be loaded through `@shelamkoff/rector/plugins/async`.
23
-
24
- ## Data
25
-
26
- ```json
27
- {
28
- "images": [{ "url": "https://cdn.example/a.jpg", "caption": "A" }],
29
- "layout": "auto",
30
- "styles": { "gap": "8px", "borderRadius": "8px", "height": "420px" },
31
- "options": { "loop": true, "zoom": true, "navigation": true, "captions": true, "thumbnails": true, "fullscreen": true, "autoplayInterval": 3000 }
32
- }
33
- ```
34
-
35
- ### Field reference
36
-
37
- | Field | Required | Meaning and constraints |
38
- | --- | --- | --- |
39
- | `images` | yes | Non-empty array. Every item requires a media-policy `url`; `caption` is an optional string. |
40
- | `layout` | yes | One of `auto`, `1`, `2`, `3a`, `3b`, `3c`, `4a`, `4b`, `4c`, `5a`, `5b`, `5c`, `6a`, `6b`, `6c`, `triptych`, `masonry`, `poly-5`, `poly-3arch`, `poly-5flat`, or `poly-3steps`. |
41
- | `styles` | no | String-valued map. The built-in settings UI uses `gap`, `borderRadius`, and `height`. |
42
- | `options.loop` | no | Wraps viewer navigation from the last image to the first. The new-block default is `true`. |
43
- | `options.zoom`, `navigation`, `captions`, `fullscreen` | no | Boolean viewer controls; new-block defaults are `true`. |
44
- | `options.thumbnails` | no | Shows viewer thumbnails; the new-block default is `false`. |
45
- | `options.autoplayInterval` | no | Positive finite interval in milliseconds. Omit it to disable autoplay. `0` is not valid persisted data. |
46
-
47
- Without `uploadFile`, local files become data URLs. Callback results are accepted only when `url` passes the shared media URL policy. The viewer requires `@shelamkoff/expose`.
48
-
49
- ## Configuration
50
-
51
- Every built-in block plugin accepts two style ownership options: `injectStyles?: boolean` defaults to `true`; set it to `false` when the host bundles that plugin's CSS. `css?: string` adds one host-provided stylesheet URL after the plugin default, or acts as the replacement URL when default injection is disabled.
52
-
53
- `uploadFile?: (file: File, context: { signal: AbortSignal }) => Promise<{ url: string; alt?: string }>` uploads each file. `actions?: Array<{ icon?; label; handler(context: { signal: AbortSignal }): Promise<Array<{ url: string; alt?: string }> | null> }>` adds application media sources. Both callbacks must stop work when the supplied signal is aborted.
54
-
55
- ## Application file sources
56
-
57
- Use `uploadFile` for browser `File` objects and `actions` for existing assets selected from a media library, cloud drive, or another application-owned catalog. An action may return several images; the complete selection becomes one undo/redo step.
58
-
59
- ```js
60
- const gallery = new Gallery({
61
- actions: [{
62
- label: 'Media library',
63
- async handler({ signal }) {
64
- const assets = await openMediaLibrary({
65
- accept: ['image/*'],
66
- multiple: true,
67
- signal,
68
- })
69
- return assets?.map(asset => ({
70
- url: asset.url,
71
- alt: asset.alt,
72
- })) ?? null
73
- },
74
- }],
75
- })
76
- ```
77
-
78
- Return `null` when selection is cancelled. The optional `alt` value initializes the image caption. Multiple independent sources may be added as separate `actions` entries. See [File sources and media libraries](https://shelamkoff.github.io/editor/guide/file-sources) for upload, cancellation, validation, and reusable adapter guidance.
79
-
80
- ## Capabilities
81
-
82
- Multi-file upload; image-file paste with an async transaction; layout/style controls; drag reordering; custom media actions.
83
-
84
- ## Undo, lifecycle, and styles
85
-
86
- User actions exposed by the plugin enter the command pipeline through the supplied `context.mutate()` capability, so each completed action is one undo/redo step. The editor reference-counts the plugin's declared stylesheet URLs. Removing a block calls its cleanup hook; removing the editor calls `destroy()` for every remaining block and then releases shared plugin resources.
87
-
88
- Do not remove the editor holder without first calling `editor.destroy()`.
89
-
90
- ## Document output
91
-
92
- Use the matching renderer from `@shelamkoff/rector/renderer/renderers/gallery`. The VitePress guide documents configuration, commands and history, extension contracts, document migrations, styling, security, and lifecycle in a sequential form.
1
+ # Gallery block plugin
2
+
3
+ Multi-image gallery with layouts, captions, appearance settings, reordering, and viewer options.
4
+
5
+ ## Install and register
6
+
7
+ ```bash
8
+ npm install @shelamkoff/rector
9
+ ```
10
+
11
+ ```js
12
+ import { createEditor } from '@shelamkoff/rector'
13
+ import { Gallery } from '@shelamkoff/rector/plugins/gallery'
14
+ import '@shelamkoff/rector/styles/editor.css'
15
+
16
+ const editor = createEditor({
17
+ holder: document.querySelector('#editor'),
18
+ plugins: [new Gallery()],
19
+ })
20
+ ```
21
+
22
+ The registered block type is `gallery`. The class is also exported by the complete `@shelamkoff/rector/plugins` preset and can be loaded through `@shelamkoff/rector/plugins/async`.
23
+
24
+ ## Data
25
+
26
+ ```json
27
+ {
28
+ "images": [{ "url": "https://cdn.example/a.jpg", "caption": "A" }],
29
+ "layout": "auto",
30
+ "styles": { "gap": "8px", "borderRadius": "8px", "height": "420px" },
31
+ "options": { "loop": true, "zoom": true, "navigation": true, "captions": true, "thumbnails": true, "fullscreen": true, "autoplayInterval": 3000 }
32
+ }
33
+ ```
34
+
35
+ ### Field reference
36
+
37
+ | Field | Required | Meaning and constraints |
38
+ | --- | --- | --- |
39
+ | `images` | yes | Non-empty array. Every item requires a media-policy `url`; `caption` is an optional string. |
40
+ | `layout` | yes | One of `auto`, `1`, `2`, `3a`, `3b`, `3c`, `4a`, `4b`, `4c`, `5a`, `5b`, `5c`, `6a`, `6b`, `6c`, `triptych`, `masonry`, `poly-5`, `poly-3arch`, `poly-5flat`, or `poly-3steps`. |
41
+ | `styles` | no | String-valued map. The built-in settings UI uses `gap`, `borderRadius`, and `height`. |
42
+ | `options.loop` | no | Wraps viewer navigation from the last image to the first. The new-block default is `true`. |
43
+ | `options.zoom`, `navigation`, `captions`, `fullscreen` | no | Boolean viewer controls; new-block defaults are `true`. |
44
+ | `options.thumbnails` | no | Shows viewer thumbnails; the new-block default is `false`. |
45
+ | `options.autoplayInterval` | no | Positive finite interval in milliseconds. Omit it to disable autoplay. `0` is not valid persisted data. |
46
+
47
+ Without `uploadFile`, local files become data URLs. Callback results are accepted only when `url` passes the shared media URL policy. The viewer requires `@shelamkoff/expose`. The `masonry` layout is measured and positioned by `@shelamkoff/masonry`; it is not a CSS-columns approximation.
48
+
49
+ ## Configuration
50
+
51
+ Every built-in block plugin accepts two style ownership options: `injectStyles?: boolean` defaults to `true`; set it to `false` when the host bundles that plugin's CSS. `css?: string` adds one host-provided stylesheet URL after the plugin default, or acts as the replacement URL when default injection is disabled.
52
+
53
+ `uploadFile?: (file: File, context: { signal: AbortSignal }) => Promise<{ url: string; alt?: string }>` uploads each file. `actions?: Array<{ icon?; label; handler(context: { signal: AbortSignal }): Promise<Array<{ url: string; alt?: string }> | null> }>` adds application media sources. Both callbacks must stop work when the supplied signal is aborted.
54
+
55
+ ## Application file sources
56
+
57
+ Use `uploadFile` for browser `File` objects and `actions` for existing assets selected from a media library, cloud drive, or another application-owned catalog. An action may return several images; the complete selection becomes one undo/redo step.
58
+
59
+ ```js
60
+ const gallery = new Gallery({
61
+ actions: [{
62
+ label: 'Media library',
63
+ async handler({ signal }) {
64
+ const assets = await openMediaLibrary({
65
+ accept: ['image/*'],
66
+ multiple: true,
67
+ signal,
68
+ })
69
+ return assets?.map(asset => ({
70
+ url: asset.url,
71
+ alt: asset.alt,
72
+ })) ?? null
73
+ },
74
+ }],
75
+ })
76
+ ```
77
+
78
+ Return `null` when selection is cancelled. The optional `alt` value initializes the image caption. Multiple independent sources may be added as separate `actions` entries. See [File sources and media libraries](https://shelamkoff.github.io/editor/guide/file-sources) for upload, cancellation, validation, and reusable adapter guidance.
79
+
80
+ ## Capabilities
81
+
82
+ Multi-file upload; image-file paste with an async transaction; layout/style controls; drag reordering; custom media actions.
83
+
84
+ ## Undo, lifecycle, and styles
85
+
86
+ User actions exposed by the plugin enter the command pipeline through the supplied `context.mutate()` capability, so each completed action is one undo/redo step. The editor reference-counts the plugin's declared stylesheet URLs. Removing a block calls its cleanup hook; removing the editor calls `destroy()` for every remaining block and then releases shared plugin resources.
87
+
88
+ Do not remove the editor holder without first calling `editor.destroy()`.
89
+
90
+ ## Document output
91
+
92
+ Use the matching renderer from `@shelamkoff/rector/renderer/renderers/gallery`. The VitePress guide documents configuration, commands and history, extension contracts, document migrations, styling, security, and lifecycle in a sequential form.
@@ -28,23 +28,23 @@ const editor = createEditor({
28
28
  "images": [{ "url": "https://cdn.example/a.jpg", "caption": "A" }],
29
29
  "layout": "auto",
30
30
  "styles": { "gap": "8px", "borderRadius": "8px", "height": "420px" },
31
- "options": { "loop": true, "zoom": true, "navigation": true, "captions": true, "thumbnails": true, "fullscreen": true, "autoplayInterval": 3000 }
32
- }
33
- ```
34
-
35
- ### Поля данных
36
-
37
- | Поле | Обязательное | Назначение и ограничения |
38
- | --- | --- | --- |
39
- | `images` | да | Непустой массив. Каждому элементу нужен разрешённый политикой медиафайлов `url`; `caption` — необязательная строка. |
40
- | `layout` | да | Одно из значений `auto`, `1`, `2`, `3a`, `3b`, `3c`, `4a`, `4b`, `4c`, `5a`, `5b`, `5c`, `6a`, `6b`, `6c`, `triptych`, `masonry`, `poly-5`, `poly-3arch`, `poly-5flat` или `poly-3steps`. |
41
- | `styles` | нет | Карта строковых значений. Встроенная панель настроек использует `gap`, `borderRadius` и `height`. |
42
- | `options.loop` | нет | После последнего изображения переходит к первому; для нового блока по умолчанию `true`. |
43
- | `options.zoom`, `navigation`, `captions`, `fullscreen` | нет | Логические параметры просмотра; для нового блока по умолчанию `true`. |
44
- | `options.thumbnails` | нет | Показывает миниатюры; для нового блока по умолчанию `false`. |
45
- | `options.autoplayInterval` | нет | Положительный конечный интервал в миллисекундах. Отсутствие поля отключает автовоспроизведение. Значение `0` недопустимо в сохранённых данных. |
46
-
47
- Без `uploadFile` файлы сохраняются как URL со встроенными данными. Для полноэкранного просмотра нужен `@shelamkoff/expose`.
31
+ "options": { "loop": true, "zoom": true, "navigation": true, "captions": true, "thumbnails": true, "fullscreen": true, "autoplayInterval": 3000 }
32
+ }
33
+ ```
34
+
35
+ ### Поля данных
36
+
37
+ | Поле | Обязательное | Назначение и ограничения |
38
+ | --- | --- | --- |
39
+ | `images` | да | Непустой массив. Каждому элементу нужен разрешённый политикой медиафайлов `url`; `caption` — необязательная строка. |
40
+ | `layout` | да | Одно из значений `auto`, `1`, `2`, `3a`, `3b`, `3c`, `4a`, `4b`, `4c`, `5a`, `5b`, `5c`, `6a`, `6b`, `6c`, `triptych`, `masonry`, `poly-5`, `poly-3arch`, `poly-5flat` или `poly-3steps`. |
41
+ | `styles` | нет | Карта строковых значений. Встроенная панель настроек использует `gap`, `borderRadius` и `height`. |
42
+ | `options.loop` | нет | После последнего изображения переходит к первому; для нового блока по умолчанию `true`. |
43
+ | `options.zoom`, `navigation`, `captions`, `fullscreen` | нет | Логические параметры просмотра; для нового блока по умолчанию `true`. |
44
+ | `options.thumbnails` | нет | Показывает миниатюры; для нового блока по умолчанию `false`. |
45
+ | `options.autoplayInterval` | нет | Положительный конечный интервал в миллисекундах. Отсутствие поля отключает автовоспроизведение. Значение `0` недопустимо в сохранённых данных. |
46
+
47
+ Без `uploadFile` файлы сохраняются как URL со встроенными данными. Для полноэкранного просмотра нужен `@shelamkoff/expose`. Раскладка `masonry` измеряется и позиционируется библиотекой `@shelamkoff/masonry`, а не имитацией через CSS columns.
48
48
 
49
49
  ## Конфигурация
50
50
 
@@ -1,4 +1,5 @@
1
1
  .oe-gallery {
2
+ position: relative;
2
3
  border-radius: 0.5rem;
3
4
  overflow-anchor: none;
4
5
  text-align: center;
@@ -433,19 +434,40 @@
433
434
  aspect-ratio: 3 / 1.5;
434
435
  }
435
436
 
436
- /* Masonry: CSS columns */
437
- .eg--masonry {
438
- column-count: 3;
439
- column-gap: 0.25rem;
440
- }
441
- .eg--masonry .oe-gallery__slot {
442
- break-inside: avoid;
443
- margin-bottom: 0.25rem;
444
- }
445
- .eg--masonry .oe-gallery__slot-img {
446
- height: auto;
447
- }
448
-
437
+ /* Masonry: layout is calculated by @shelamkoff/masonry. */
438
+ .eg--masonry {
439
+ position: relative;
440
+ width: 100%;
441
+ gap: 0.25rem;
442
+ }
443
+
444
+ .eg--masonry.masonry-container > .masonry-item {
445
+ position: absolute;
446
+ top: 0;
447
+ left: 0;
448
+ will-change: transform;
449
+ opacity: 0;
450
+ }
451
+
452
+ .eg--masonry.masonry-container > .masonry-item--visible {
453
+ opacity: 1;
454
+ }
455
+
456
+ .eg--masonry .oe-gallery__slot {
457
+ width: 100%;
458
+ margin: 0;
459
+ }
460
+
461
+ .eg--masonry .oe-gallery__slot-img {
462
+ height: auto;
463
+ }
464
+
465
+ .eg--masonry-fallback {
466
+ display: grid;
467
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
468
+ height: auto !important;
469
+ }
470
+
449
471
  /* ── Polyptych templates ── */
450
472
 
451
473
  /* poly-5: Classic 5-panel pyramid, center tallest */
@@ -510,11 +532,10 @@
510
532
  .eg--6b {
511
533
  grid-template-columns: repeat(3, 1fr);
512
534
  grid-template-rows: 1fr 1fr;
513
- }
514
- .eg--6b .oe-gallery__slot:nth-child(1) { grid-column: 1 / -1; grid-row: auto; }
515
- .eg--6b .oe-gallery__slot:nth-child(n+2) { grid-column: auto; }
516
- .eg--masonry { column-count: 2; }
517
- }
535
+ }
536
+ .eg--6b .oe-gallery__slot:nth-child(1) { grid-column: 1 / -1; grid-row: auto; }
537
+ .eg--6b .oe-gallery__slot:nth-child(n+2) { grid-column: auto; }
538
+ }
518
539
 
519
540
  /* ── Action bar ───────────────────────────────────────────────────────────── */
520
541
 
@@ -615,7 +636,7 @@
615
636
  border-radius: 8px;
616
637
  box-shadow: var(--oe-toolbar-shadow, 0 8px 24px rgba(0, 0, 0, 0.4));
617
638
  padding: 10px;
618
- z-index: 100;
639
+ z-index: var(--oe-plugin-panel-z-index, 1100);
619
640
  }
620
641
 
621
642
  .oe-gallery__dropdown--open .oe-gallery__dropdown-panel {
@@ -805,6 +826,10 @@
805
826
  color: var(--oe-text-1, #1a1a1a);
806
827
  }
807
828
 
829
+ .oe-theme-light .oe-gallery__action-btn:hover {
830
+ color: var(--oe-text-on-accent, #fff);
831
+ }
832
+
808
833
  .oe-theme-light .oe-gallery__action-btn--active {
809
834
  color: var(--oe-accent, #4357b4);
810
835
  }