griffincss-ui 0.26.1 → 0.27.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.
- package/dist/griffincss-ui-scoped.css +1 -1
- package/dist/griffincss-ui.css +1 -1
- package/dist/griffincss-ui.js +1 -1
- package/dist/griffinjs-core.js +1 -1
- package/dist/griffinjs-dialog.js +1 -1
- package/dist/griffinjs-dialog.js.map +1 -1
- package/dist/griffinjs-lightbox.js +1 -1
- package/dist/griffinjs-lightbox.js.map +1 -1
- package/dist/griffinjs.css +1 -1
- package/dist/griffinjs.js +1 -1
- package/dist/griffinjs.js.map +1 -1
- package/package.json +2 -2
- package/scss/_choice.scss +45 -6
- package/scss/_pagination.scss +8 -1
- package/scss/_prose.scss +116 -0
- package/scss/_steps.scss +81 -38
- package/scss/_table.scss +17 -6
- package/scss/griffincss-ui-scoped.scss +1 -0
- package/scss/griffincss-ui.scss +1 -0
- package/scss/griffinjs/_track.scss +10 -0
- package/scss/griffinjs/griffinjs.scss +1 -1
- package/src/griffincss-ui.js +2 -2
- package/src/griffinjs/core/griffinjs-core.js +2 -2
- package/src/griffinjs/core/track.js +1 -1
- package/src/griffinjs/widgets/dialog.js +15 -5
- package/src/griffinjs/widgets/gallery.js +1 -1
- package/src/griffinjs/widgets/lightbox.js +16 -10
package/scss/_prose.scss
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Griffincss UI — Prose
|
|
2
|
+
// Форматированный текст, у детей которого нет классов: HTML из редактора,
|
|
3
|
+
// описание товара, запись блога. Класс ставится на обёртку, а ритм,
|
|
4
|
+
// подзаголовки, списки, цитата, ссылки, разделитель и таблица оформляются
|
|
5
|
+
// по тегам.
|
|
6
|
+
//
|
|
7
|
+
// <div class="gr-prose">{{ description }}</div>
|
|
8
|
+
//
|
|
9
|
+
// Правила детей записаны целиком под :where(): вес у них нулевой, и любой
|
|
10
|
+
// класс на ребёнке сильнее прозы — утилита (.gr-mt-0), компонент (.gr-btn,
|
|
11
|
+
// .gr-alert). Списки и ссылки оформляются только без класса: у .gr-menu,
|
|
12
|
+
// .gr-steps и ссылки-кнопки свой вид. Поля проза ставит сама, а не берёт
|
|
13
|
+
// у ресета: ресет подключают не все, и без него у абзаца поля браузера,
|
|
14
|
+
// с ним — ноль.
|
|
15
|
+
//
|
|
16
|
+
// Меры строки в классе нет: ширину решает место — колонка, карточка, окно.
|
|
17
|
+
// Мера текста — утилита .gr-max-w-prose. Вид таблицы — в _table.scss:
|
|
18
|
+
// <table> в прозе оформлен теми же правилами, что .gr-table.
|
|
19
|
+
|
|
20
|
+
// Длинная ссылка или слово без пробелов не выталкивают колонку вбок:
|
|
21
|
+
// текст в редакторе пишет кто угодно.
|
|
22
|
+
.gr-prose {
|
|
23
|
+
overflow-wrap: break-word;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// --- Ритм -------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
// Поле — только между соседями: у прямых детей прозы и у детей цитаты
|
|
29
|
+
// и пункта списка (редактор кладёт абзацы и туда). У крайних детей полей
|
|
30
|
+
// нет — блок не спорит с отступами вокруг себя.
|
|
31
|
+
:where(.gr-prose, .gr-prose blockquote, .gr-prose li) > * {
|
|
32
|
+
margin-block: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:where(.gr-prose, .gr-prose blockquote, .gr-prose li) > * + * {
|
|
36
|
+
margin-block-start: var(--gr-gap);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Подзаголовок ближе к своему тексту, чем к предыдущему, а разделитель
|
|
40
|
+
// отбивает разделы — поле вокруг него крупнее абзацного.
|
|
41
|
+
:where(.gr-prose > * + :is(h1, h2, h3, h4, h5, h6), .gr-prose > * + hr, .gr-prose > hr + *) {
|
|
42
|
+
margin-block-start: var(--gr-gap-lg);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:where(.gr-prose > :is(h1, h2, h3, h4, h5, h6) + *) {
|
|
46
|
+
margin-block-start: var(--gr-gap-sm);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// --- Списки -----------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
// Маркеры — браузера: ресет снимает их только со списков с role="list".
|
|
52
|
+
// Отступ теснее браузерных 40px — на узком экране они съедали строку.
|
|
53
|
+
// Пункты и вложенный список теснее абзацев.
|
|
54
|
+
:where(.gr-prose :is(ul, ol):not([class])) {
|
|
55
|
+
padding-inline-start: 1.5em;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
:where(.gr-prose :is(ul, ol):not([class]) > li + li, .gr-prose li > :is(ul, ol)) {
|
|
59
|
+
margin-block-start: var(--gr-gap-sm);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
:where(.gr-prose :is(ul, ol):not([class]) > li)::marker {
|
|
63
|
+
color: var(--gr-color-text-secondary);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// --- Цитата, разделитель, медиа, код -----------------------------------------
|
|
67
|
+
|
|
68
|
+
// Цитата — линией у начала строки, как в рецепте «Цитата с цветной линией».
|
|
69
|
+
// Поля браузера по бокам (40px у цитаты и у figure) сняты.
|
|
70
|
+
:where(.gr-prose :is(blockquote, figure)) {
|
|
71
|
+
margin-inline: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
:where(.gr-prose blockquote) {
|
|
75
|
+
padding-inline-start: 1em;
|
|
76
|
+
border-inline-start: 0.25rem solid var(--gr-color-accent);
|
|
77
|
+
font-style: italic;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:where(.gr-prose hr) {
|
|
81
|
+
block-size: 0;
|
|
82
|
+
border: 0;
|
|
83
|
+
border-block-start: var(--gr-border-width) solid var(--gr-color-border);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Картинка и видео не шире колонки и при сужении не сплющиваются.
|
|
87
|
+
:where(.gr-prose :is(img, video)) {
|
|
88
|
+
max-inline-size: 100%;
|
|
89
|
+
block-size: auto;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Длинная строка кода прокручивается внутри блока, а не всей страницей.
|
|
93
|
+
:where(.gr-prose pre) {
|
|
94
|
+
overflow-x: auto;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// --- Ссылки -----------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
// Ссылка без класса — как .gr-link: цвет ссылки и подчёркивание, которых
|
|
100
|
+
// ресет лишает <a>. Порядок LVHA — как у .gr-link.
|
|
101
|
+
:where(.gr-prose a:not([class])) {
|
|
102
|
+
color: var(--gr-color-link);
|
|
103
|
+
text-decoration-line: underline;
|
|
104
|
+
text-decoration-thickness: from-font;
|
|
105
|
+
text-underline-offset: 0.2em;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
:where(.gr-prose a:not([class]):visited) {
|
|
109
|
+
color: var(--gr-color-link-visited);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@media (hover: hover) {
|
|
113
|
+
:where(.gr-prose a:not([class]):hover) {
|
|
114
|
+
color: var(--gr-color-link-hover);
|
|
115
|
+
}
|
|
116
|
+
}
|
package/scss/_steps.scss
CHANGED
|
@@ -18,12 +18,17 @@
|
|
|
18
18
|
// Состояний три: пройденный (.gr-step-done), текущий (aria-current="step")
|
|
19
19
|
// и ожидающий — он же состояние по умолчанию. Текущий находится по тому же
|
|
20
20
|
// признаку, по которому его находит программа чтения с экрана; класса
|
|
21
|
-
// для него нет намеренно.
|
|
21
|
+
// для него нет намеренно. Перечню этапов без хода — «Этапы работы»
|
|
22
|
+
// лендинга — состояния не нужны: .gr-steps-plain делает все шаги
|
|
23
|
+
// равноправными.
|
|
22
24
|
//
|
|
23
25
|
// Знак в маркере кладут в разметку: галочка у пройденного шага и номер
|
|
24
26
|
// у остальных — это содержимое, а не оформление. Цвет остаётся вторым
|
|
25
27
|
// признаком поверх знака и позиции, а не единственным.
|
|
26
28
|
|
|
29
|
+
@use 'griffincss-core/scss/breakpoints' as bp;
|
|
30
|
+
@use 'griffincss-core/scss/container-mixins' as cq;
|
|
31
|
+
|
|
27
32
|
.gr-steps {
|
|
28
33
|
--gr-step-marker-size: 2rem;
|
|
29
34
|
|
|
@@ -125,6 +130,26 @@
|
|
|
125
130
|
line-height: 1.35;
|
|
126
131
|
}
|
|
127
132
|
|
|
133
|
+
// Подпись и пояснение одним блоком: в колонке он встаёт справа от маркера,
|
|
134
|
+
// в ряду — под ним, и там ведёт себя как её отсутствие: строки друг под
|
|
135
|
+
// другом с тем же зазором, что у шага. Нужен разметке, которая бывает
|
|
136
|
+
// и тем и другим (.gr-steps-stack-*).
|
|
137
|
+
.gr-step-body {
|
|
138
|
+
display: flex;
|
|
139
|
+
flex-direction: column;
|
|
140
|
+
gap: calc(var(--gr-ui-gap) * 0.5);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// --- Равноправный список ----------------------------------------------------
|
|
144
|
+
|
|
145
|
+
// Перечень этапов без хода процесса: подпись цвета текста, маркер
|
|
146
|
+
// акцентный, линия нейтральная. Вес — как у .gr-step, и стоит до состояний:
|
|
147
|
+
// пройденный и текущий шаг в таком списке по-прежнему сильнее.
|
|
148
|
+
:where(.gr-steps-plain) .gr-step {
|
|
149
|
+
--gr-step-color: var(--gr-color-text);
|
|
150
|
+
--gr-step-marker-fg: var(--gr-color-accent);
|
|
151
|
+
}
|
|
152
|
+
|
|
128
153
|
// --- Состояния --------------------------------------------------------------
|
|
129
154
|
|
|
130
155
|
// Пройденный: его хвост залит акцентом — путь от него дальше проделан.
|
|
@@ -157,41 +182,59 @@
|
|
|
157
182
|
|
|
158
183
|
// Колонка: маркер слева, подпись справа. На узком экране это единственный
|
|
159
184
|
// работающий вариант — горизонтальный ряд из четырёх шагов там нечитаем.
|
|
160
|
-
.gr-steps-vertical
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
185
|
+
// Правила колонки описаны один раз: .gr-steps-vertical — всегда,
|
|
186
|
+
// .gr-steps-stack-{bp} и -c{bp} — ниже порога (см. ниже).
|
|
187
|
+
@mixin gr-steps-vertical($s) {
|
|
188
|
+
#{$s} {
|
|
189
|
+
flex-direction: column;
|
|
190
|
+
gap: var(--gr-gap);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
#{$s} > :where(li) {
|
|
194
|
+
flex: none;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
#{$s} .gr-step {
|
|
198
|
+
flex: none;
|
|
199
|
+
flex-direction: row;
|
|
200
|
+
align-items: flex-start;
|
|
201
|
+
gap: var(--gr-ui-gap);
|
|
202
|
+
text-align: start;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// В колонке хвост идёт вниз от маркера до маркера следующего шага. Длину
|
|
206
|
+
// задают оба вылета сразу, а block-size: auto считает её из них: сколько бы
|
|
207
|
+
// текста ни висело под маркером, линия дотянется — это и есть довод
|
|
208
|
+
// в пользу хвоста, а не отрезка фиксированной длины.
|
|
209
|
+
#{$s} .gr-step::after {
|
|
210
|
+
inset-block: var(--gr-step-marker-size) calc(var(--gr-gap) * -1);
|
|
211
|
+
inset-inline: calc(var(--gr-step-marker-size) / 2) auto;
|
|
212
|
+
inline-size: var(--gr-border-width);
|
|
213
|
+
block-size: auto;
|
|
214
|
+
margin-block-start: 0;
|
|
215
|
+
margin-inline-start: calc(var(--gr-border-width) * -0.5);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Подпись и пояснение встают в колонку рядом с маркером (сама колонка —
|
|
219
|
+
// у .gr-step-body всегда); первая строка — по центру маркера.
|
|
220
|
+
#{$s} .gr-step-body {
|
|
221
|
+
gap: calc(var(--gr-ui-gap) * 0.25);
|
|
222
|
+
padding-block-start: calc((var(--gr-step-marker-size) - 1.3em) / 2);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@include gr-steps-vertical('.gr-steps-vertical');
|
|
227
|
+
|
|
228
|
+
// Столбиком ниже порога, рядом — от порога: суффикс называет порог,
|
|
229
|
+
// как у .gr-table-stack-md. -md — колонка, пока окно уже 768px;
|
|
230
|
+
// -cmd — пока уже 768px ближайший предок с .gr-cq. Разметка одна на оба
|
|
231
|
+
// вида: подпись и пояснение — в .gr-step-body.
|
|
232
|
+
@each $bp-name, $bp-value in bp.$gr-breakpoints {
|
|
233
|
+
@media (width < $bp-value) {
|
|
234
|
+
@include gr-steps-vertical('.gr-steps-stack-#{$bp-name}');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@include cq.gr-container-below($bp-name) {
|
|
238
|
+
@include gr-steps-vertical('.gr-steps-stack-c#{$bp-name}');
|
|
239
|
+
}
|
|
197
240
|
}
|
package/scss/_table.scss
CHANGED
|
@@ -6,12 +6,18 @@
|
|
|
6
6
|
//
|
|
7
7
|
// Ресет опционален, поэтому border-collapse задаётся здесь: без него
|
|
8
8
|
// у ячеек остались бы двойные линии и зазоры border-spacing.
|
|
9
|
+
//
|
|
10
|
+
// Таблица внутри .gr-prose оформлена теми же правилами: класс на <table>
|
|
11
|
+
// редактор не поставит. Селекторы прозы — под :where(), с нулевым весом:
|
|
12
|
+
// варианты (.gr-table-compact и другие) на такой таблице по-прежнему
|
|
13
|
+
// сильнее базы.
|
|
9
14
|
|
|
10
15
|
@use 'sass:string';
|
|
11
16
|
@use 'griffincss-core/scss/breakpoints' as bp;
|
|
12
17
|
@use 'griffincss-core/scss/container-mixins' as cq;
|
|
13
18
|
|
|
14
|
-
.gr-table
|
|
19
|
+
.gr-table,
|
|
20
|
+
:where(.gr-prose table) {
|
|
15
21
|
inline-size: 100%;
|
|
16
22
|
border-collapse: collapse;
|
|
17
23
|
color: var(--gr-color-text);
|
|
@@ -19,7 +25,8 @@
|
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
.gr-table th,
|
|
22
|
-
.gr-table td
|
|
28
|
+
.gr-table td,
|
|
29
|
+
:where(.gr-prose table :is(th, td)) {
|
|
23
30
|
padding-block: calc(var(--gr-gap) * 0.5);
|
|
24
31
|
padding-inline: calc(var(--gr-gap) * 0.75);
|
|
25
32
|
border-block-end: var(--gr-border-width) solid var(--gr-color-border);
|
|
@@ -27,24 +34,28 @@
|
|
|
27
34
|
vertical-align: top;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
|
-
.gr-table th
|
|
37
|
+
.gr-table th,
|
|
38
|
+
:where(.gr-prose table th) {
|
|
31
39
|
color: var(--gr-color-text-secondary);
|
|
32
40
|
font-size: 0.875rem;
|
|
33
41
|
font-weight: 600;
|
|
34
42
|
white-space: nowrap;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
|
-
.gr-table thead th
|
|
45
|
+
.gr-table thead th,
|
|
46
|
+
:where(.gr-prose table thead th) {
|
|
38
47
|
border-block-end: calc(var(--gr-border-width) * 2) solid var(--gr-color-border-strong);
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
.gr-table tfoot td
|
|
50
|
+
.gr-table tfoot td,
|
|
51
|
+
:where(.gr-prose table tfoot td) {
|
|
42
52
|
border-block-end: 0;
|
|
43
53
|
color: var(--gr-color-text-secondary);
|
|
44
54
|
font-size: 0.875rem;
|
|
45
55
|
}
|
|
46
56
|
|
|
47
|
-
.gr-table caption
|
|
57
|
+
.gr-table caption,
|
|
58
|
+
:where(.gr-prose table caption) {
|
|
48
59
|
padding-block-end: calc(var(--gr-gap) * 0.5);
|
|
49
60
|
color: var(--gr-color-text-secondary);
|
|
50
61
|
font-size: 0.875rem;
|
package/scss/griffincss-ui.scss
CHANGED
|
@@ -46,6 +46,16 @@
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// Слайды своей ширины: лента историй, полоса тегов, ряд логотипов. Ширину
|
|
50
|
+
// даёт содержимое — аватар, атрибуты width/height картинки, текст кнопки;
|
|
51
|
+
// утилита ширины на слайде доли 100% не перебьёт, основа здесь — flex-basis.
|
|
52
|
+
// Не сжимаются (flex-shrink: 0 базового правила): лишнее уходит в прокрутку.
|
|
53
|
+
// Стоит до суффиксных долей: .gr-track-auto .gr-track-3-lg — своя ширина
|
|
54
|
+
// на узком окне и три в ряд на широком.
|
|
55
|
+
.gr-track-auto > * {
|
|
56
|
+
flex-basis: auto;
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
// Доля слайда описана один раз: без суффикса — база, с суффиксом
|
|
50
60
|
// брейкпоинта — от ширины окна, с буквой c — от ширины ближайшего предка
|
|
51
61
|
// с .gr-cq (Этап 47d): виджет в слоте меряется слотом. Виджету дорожки
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// griffinjs.css подключается всегда ПОВЕРХ griffincss-ui.css, где он есть.
|
|
9
9
|
//
|
|
10
10
|
// Оформление привязывается к состояниям, а не к классам, которые JS
|
|
11
|
-
// добавляет: [data-gr-state="open"], .gr-
|
|
11
|
+
// добавляет: [data-gr-state="open"], .gr-track > [aria-current],
|
|
12
12
|
// var(--gr-progress). Движение — здесь, в CSS; JS transform и opacity
|
|
13
13
|
// не пишет никогда (инварианты слоя — docs/griffinjs-architecture.html).
|
|
14
14
|
//
|
package/src/griffincss-ui.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Griffincss UI — Runtime v0.
|
|
2
|
+
* Griffincss UI — Runtime v0.27.0
|
|
3
3
|
* Опциональный рантайм пакета компонентов. Делает ровно то, чего платформа
|
|
4
4
|
* не даёт вовсе; всё, что умеют <details>, <dialog> и Popover API, остаётся
|
|
5
5
|
* за ними. Без этого файла компоненты работают — просто без перечисленного.
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
})(function () {
|
|
51
51
|
'use strict';
|
|
52
52
|
|
|
53
|
-
var VERSION = '0.
|
|
53
|
+
var VERSION = '0.27.0';
|
|
54
54
|
|
|
55
55
|
var OVERLAY_ATTR = 'data-gr-overlay-close';
|
|
56
56
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* GriffinJS — Core v0.
|
|
2
|
+
* GriffinJS — Core v0.27.0
|
|
3
3
|
* Опциональный слой виджетов с состоянием поверх Griffincss: слайдер,
|
|
4
4
|
* галерея, лайтбокс, параллакс, мегаменю. Подключается одной строкой
|
|
5
5
|
* и одним файлом; страница без него — законное и рабочее состояние.
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
})(function () {
|
|
46
46
|
'use strict';
|
|
47
47
|
|
|
48
|
-
var VERSION = '0.
|
|
48
|
+
var VERSION = '0.27.0';
|
|
49
49
|
|
|
50
50
|
// Реестры. Модуль зовёт defineEngine/defineWidget; ядро — единственное
|
|
51
51
|
// место, которое знает, как их применить.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* состояние, только physical.
|
|
21
21
|
*
|
|
22
22
|
* JS пишет только aria-*, inert, --gr-progress и --gr-snap (снап-точки
|
|
23
|
-
* по страницам); оформление активного слайда — .gr-
|
|
23
|
+
* по страницам); оформление активного слайда — .gr-track > [aria-current] в CSS.
|
|
24
24
|
*/
|
|
25
25
|
(function (G) {
|
|
26
26
|
'use strict';
|
|
@@ -205,11 +205,14 @@
|
|
|
205
205
|
|
|
206
206
|
// --- Рост окна ----------------------------------------------------------
|
|
207
207
|
|
|
208
|
-
// Пока идёт анимация, наблюдение молчит: промежуточные высоты — её же.
|
|
209
208
|
// Открытие и закрытие (0 ↔ высота) — не рост; мелочь до порога — тоже.
|
|
209
|
+
// Анимация меняет размер самого окна, поэтому на её время окно снято
|
|
210
|
+
// с наблюдения: начатая здесь при живом наблюдении, она давала на window
|
|
211
|
+
// «ResizeObserver loop completed with undelivered notifications».
|
|
212
|
+
// Промежуточные высоты — её же, слушать их незачем. Вернувшись,
|
|
213
|
+
// наблюдение первым сообщает текущую высоту: если за время анимации
|
|
214
|
+
// пришло ещё содержимое, окно дорастёт следующей.
|
|
210
215
|
function onResize() {
|
|
211
|
-
if (growing) return;
|
|
212
|
-
|
|
213
216
|
var next = el.getBoundingClientRect().height;
|
|
214
217
|
var prev = known;
|
|
215
218
|
|
|
@@ -221,8 +224,15 @@
|
|
|
221
224
|
|
|
222
225
|
if (!ms || typeof el.animate !== 'function') return;
|
|
223
226
|
|
|
227
|
+
grow.unobserve(el);
|
|
224
228
|
growing = el.animate([{ blockSize: prev + 'px' }, { blockSize: next + 'px' }], { duration: ms, easing: 'ease' });
|
|
225
|
-
growing.onfinish = growing.oncancel =
|
|
229
|
+
growing.onfinish = growing.oncancel = settle;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// После destroy() наблюдателя нет: отмена приходит позже и не вернёт его.
|
|
233
|
+
function settle() {
|
|
234
|
+
growing = null;
|
|
235
|
+
if (grow) grow.observe(el);
|
|
226
236
|
}
|
|
227
237
|
|
|
228
238
|
// --- Hash ---------------------------------------------------------------
|
|
@@ -300,7 +310,7 @@
|
|
|
300
310
|
var at = stack.indexOf(record);
|
|
301
311
|
if (at !== -1) stack.splice(at, 1);
|
|
302
312
|
|
|
303
|
-
if (grow) grow.disconnect();
|
|
313
|
+
if (grow) { grow.disconnect(); grow = null; }
|
|
304
314
|
if (growing) growing.cancel();
|
|
305
315
|
relock();
|
|
306
316
|
restoreMedia();
|
|
@@ -2,23 +2,28 @@
|
|
|
2
2
|
* GriffinJS — лайтбокс: <dialog> + дорожка.
|
|
3
3
|
*
|
|
4
4
|
* <a href="large.jpg" data-gr-lightbox="promo" data-gr-caption="Подпись"><img src="thumb.jpg" alt="…"></a>
|
|
5
|
+
* <a href="https://rutube.ru/video/…/" data-gr-src="https://rutube.ru/play/embed/…" data-gr-lightbox>…</a>
|
|
5
6
|
*
|
|
6
7
|
* Значение атрибута — группа: элементы с одним значением листаются в одном
|
|
7
8
|
* окне; пустое значение — окно на один элемент, и дорожка вырождается
|
|
8
|
-
* в один кадр без кнопок.
|
|
9
|
-
*
|
|
9
|
+
* в один кадр без кнопок. Адрес кадра — data-gr-src, без него — href:
|
|
10
|
+
* у видео это разные адреса — во фрейм встаёт только плеер, страницу ролика
|
|
11
|
+
* хостинги во фрейме не показывают, а ссылка без скрипта ведёт именно на неё.
|
|
12
|
+
* Тип — по адресу кадра (картинка, видео, iframe для плееров YouTube, Vimeo,
|
|
13
|
+
* Rutube и VK Видео) или явно: data-gr-type="iframe".
|
|
10
14
|
*
|
|
11
|
-
* База без JS — ссылка на большое
|
|
12
|
-
* и уничтожается при закрытии: так видео
|
|
13
|
-
* а в документе не копится по <dialog>
|
|
14
|
-
* ловушка фокуса, Esc, возврат фокуса —
|
|
15
|
+
* База без JS — ссылка на большое изображение или на страницу ролика.
|
|
16
|
+
* Окно строится при открытии и уничтожается при закрытии: так видео
|
|
17
|
+
* гарантированно останавливается, а в документе не копится по <dialog>
|
|
18
|
+
* на каждую группу. Верхний слой, ловушка фокуса, Esc, возврат фокуса —
|
|
19
|
+
* от <dialog>.
|
|
15
20
|
*/
|
|
16
21
|
(function (G) {
|
|
17
22
|
'use strict';
|
|
18
23
|
|
|
19
24
|
var ATTR = 'data-gr-lightbox';
|
|
20
25
|
var VIDEO = /\.(mp4|webm|ogv|mov)(\?|#|$)/i;
|
|
21
|
-
var EMBED = /youtube\.com|youtu\.be|vimeo\.com/i;
|
|
26
|
+
var EMBED = /youtube\.com|youtu\.be|vimeo\.com|rutube\.ru|vkvideo\.ru|vk\.com\/video/i;
|
|
22
27
|
|
|
23
28
|
var dialog = null;
|
|
24
29
|
var track = null;
|
|
@@ -36,9 +41,10 @@
|
|
|
36
41
|
return 'image';
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
// Элемент разметки → описание кадра.
|
|
44
|
+
// Элемент разметки → описание кадра. data-gr-src старше href: у видео
|
|
45
|
+
// href — страница ролика для перехода без скрипта, а кадр — плеер.
|
|
40
46
|
function itemOf(node) {
|
|
41
|
-
var src = node.getAttribute('
|
|
47
|
+
var src = node.getAttribute('data-gr-src') || node.getAttribute('href') || '';
|
|
42
48
|
var img = node.querySelector ? node.querySelector('img') : null;
|
|
43
49
|
|
|
44
50
|
return {
|
|
@@ -105,7 +111,7 @@
|
|
|
105
111
|
var trackEl = element('div', 'gr-track gr-lightbox-track', { tabindex: '0' });
|
|
106
112
|
|
|
107
113
|
for (var i = 0; i < n; i++) {
|
|
108
|
-
var figure = element('figure', 'gr-
|
|
114
|
+
var figure = element('figure', 'gr-lightbox-item');
|
|
109
115
|
|
|
110
116
|
figure.appendChild(media(items[i]));
|
|
111
117
|
|