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.
@@ -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
- flex-direction: column;
162
- gap: var(--gr-gap);
163
- }
164
-
165
- .gr-steps-vertical > :where(li) {
166
- flex: none;
167
- }
168
-
169
- .gr-steps-vertical .gr-step {
170
- flex: none;
171
- flex-direction: row;
172
- align-items: flex-start;
173
- gap: var(--gr-ui-gap);
174
- text-align: start;
175
- }
176
-
177
- // В колонке хвост идёт вниз от маркера до маркера следующего шага. Длину
178
- // задают оба вылета сразу, а block-size: auto считает её из них: сколько бы
179
- // текста ни висело под маркером, линия дотянется — это и есть довод
180
- // в пользу хвоста, а не отрезка фиксированной длины.
181
- .gr-steps-vertical .gr-step::after {
182
- inset-block: var(--gr-step-marker-size) calc(var(--gr-gap) * -1);
183
- inset-inline: calc(var(--gr-step-marker-size) / 2) auto;
184
- inline-size: var(--gr-border-width);
185
- block-size: auto;
186
- margin-block-start: 0;
187
- margin-inline-start: calc(var(--gr-border-width) * -0.5);
188
- }
189
-
190
- // Подпись и пояснение встают в колонку: в строке они разъезжались бы
191
- // по базовой линии маркера.
192
- .gr-steps-vertical .gr-step-body {
193
- display: flex;
194
- flex-direction: column;
195
- gap: calc(var(--gr-ui-gap) * 0.25);
196
- padding-block-start: calc((var(--gr-step-marker-size) - 1.3em) / 2);
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;
@@ -64,6 +64,7 @@
64
64
  @include meta.load-css('nav');
65
65
  @include meta.load-css('pagination');
66
66
  @include meta.load-css('progress');
67
+ @include meta.load-css('prose');
67
68
  @include meta.load-css('range');
68
69
  @include meta.load-css('rating');
69
70
  @include meta.load-css('skeleton');
@@ -58,6 +58,7 @@
58
58
  @include meta.load-css('nav');
59
59
  @include meta.load-css('pagination');
60
60
  @include meta.load-css('progress');
61
+ @include meta.load-css('prose');
61
62
  @include meta.load-css('range');
62
63
  @include meta.load-css('rating');
63
64
  @include meta.load-css('skeleton');
@@ -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-slide[aria-current],
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
  //
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Griffincss UI — Runtime v0.26.1
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.26.1';
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.26.1
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.26.1';
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-slide[aria-current] в CSS.
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 = function () { growing = null; };
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();
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * GriffinJS — галерея: слайдер + полоса превью.
3
3
  *
4
- * <div class="gr-gallery" data-gr-gallery>
4
+ * <div data-gr-gallery>
5
5
  * <div class="gr-track">…большие кадры…</div>
6
6
  * <div class="gr-track gr-gallery-thumbs">
7
7
  * <button type="button"><img …></button> …
@@ -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
- * в один кадр без кнопок. Тип — по адресу (картинка, видео, iframe для
9
- * YouTube/Vimeo) или явно: data-gr-type="iframe".
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, возврат фокуса — от <dialog>.
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('href') || node.getAttribute('data-gr-src') || '';
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-slide gr-lightbox-item');
114
+ var figure = element('figure', 'gr-lightbox-item');
109
115
 
110
116
  figure.appendChild(media(items[i]));
111
117