bootstrap-italia 2.9.2 → 2.11.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.
@@ -3,7 +3,6 @@ import EventHandler from 'bootstrap/js/src/dom/event-handler'
3
3
  import SelectorEngine from 'bootstrap/js/src/dom/selector-engine'
4
4
  import Manipulator from 'bootstrap/js/src/dom/manipulator'
5
5
 
6
- //import Input from './input'
7
6
  import InputLabel from './input-label'
8
7
 
9
8
  const NAME = 'inputpassword'
@@ -12,38 +11,45 @@ const EVENT_KEY = `.${DATA_KEY}`
12
11
  const DATA_API_KEY = '.data-api'
13
12
 
14
13
  const Default = {
15
- shortPass: 'Password molto debole',
16
- badPass: 'Password debole',
17
- goodPass: 'Password sicura',
18
- strongPass: 'Password molto sicura',
19
- enterPass: 'Inserisci almeno 8 caratteri e una lettera maiuscola',
20
- alertCaps: 'CAPS LOCK inserito',
21
- showText: true,
22
- minimumLength: 4,
14
+ shortPass: 'Password troppo breve',
15
+ badPass: 'Password debole.',
16
+ goodPass: 'Password abbastanza sicura.',
17
+ strongPass: 'Password sicura.',
18
+ minimumLength: 8,
19
+ suggestionsLabel: 'Suggerimenti per una buona password:',
20
+ suggestionFollowed: 'suggerimenti seguito',
21
+ suggestionFollowedPlural: 'suggerimenti seguiti',
22
+ suggestionOf: 'di',
23
+ suggestionMetLabel: 'Soddisfatto: ',
24
+ suggestionMetIconPath: `
25
+ M9.6 16.9 4 11.4l.8-.7 4.8 4.8 8.5-8.4.7.7-9.2 9.1z
26
+ `,
27
+ suggestionLength: 'Almeno {minLength} caratteri.',
28
+ suggestionUppercase: 'Una o più maiuscole.',
29
+ suggestionLowercase: 'Una o più minuscole.',
30
+ suggestionNumber: 'Uno o più numeri.',
31
+ suggestionSpecial: 'Uno o più caratteri speciali.',
23
32
  }
24
33
 
25
34
  const EVENT_CLICK = `click${EVENT_KEY}`
26
35
  const EVENT_KEYUP = `keyup${EVENT_KEY}`
27
- const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
28
- const EVENT_KEYPRESS = `keypress${EVENT_KEY}`
29
36
  const EVENT_SCORE = `score${EVENT_KEY}`
30
37
  const EVENT_TEXT = `text${EVENT_KEY}`
38
+ const EVENT_SUGGS = `suggs${EVENT_KEY}`
31
39
 
32
40
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
33
41
  const EVENT_MOUSEDOWN_DATA_API = `mousedown${EVENT_KEY}${DATA_API_KEY}`
34
42
  const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`
35
43
 
36
44
  const CLASS_NAME_PASSWORD = 'input-password'
37
- //const CLASS_NAME_METER = 'input-password-strength-meter'
38
- const CLASS_NAME_SHOW = 'show'
39
45
 
40
46
  const SELECTOR_PASSWORD = 'input[data-bs-input][type="password"]'
41
47
  const SELECTOR_BTN_SHOW_PWD = '.password-icon'
42
48
  const SELECTOR_METER = '.password-strength-meter'
43
49
  const SELECTOR_METER_GRAYBAR = '.password-meter'
44
50
  const SELECTOR_METER_COLBAR = '.progress-bar'
45
- const SELECTOR_CAPS = '.password-caps'
46
- const SELECTOR_TEXT = '.form-text'
51
+ const SELECTOR_METER_TEXT = '.strength-meter-info'
52
+ const SELECTOR_METER_SUGGS = '.strenght-meter-suggestions'
47
53
 
48
54
  class InputPassword extends BaseComponent {
49
55
  constructor(element, config) {
@@ -52,31 +58,54 @@ class InputPassword extends BaseComponent {
52
58
  this._config = this._getConfig(config)
53
59
  this._isCustom = this._element.classList.contains(CLASS_NAME_PASSWORD)
54
60
  this._meter = this._element.parentNode.querySelector(SELECTOR_METER)
55
- this._isShiftPressed = false
56
- this._isCapsOn = false
57
61
 
58
62
  this._grayBarElement = null
59
63
  this._colorBarElement = null
60
64
  this._textElement = null
61
- this._capsElement = null
65
+ this._suggsElement = null
62
66
  this._showPwdElement = null
63
67
 
64
68
  this._text = {}
65
69
 
66
70
  this._label = new InputLabel(element)
67
71
 
72
+ this._suggestions = [
73
+ {
74
+ key: 'length',
75
+ text: (config) => config.suggestionLength.replace('{minLength}', config.minimumLength.toString()),
76
+ test: (password, config) => password.length >= config.minimumLength,
77
+ },
78
+ {
79
+ key: 'uppercase',
80
+ text: (config) => config.suggestionUppercase,
81
+ test: (password) => /[A-Z]/.test(password),
82
+ },
83
+ {
84
+ key: 'lowercase',
85
+ text: (config) => config.suggestionLowercase,
86
+ test: (password) => /[a-z]/.test(password),
87
+ },
88
+ {
89
+ key: 'number',
90
+ text: (config) => config.suggestionNumber,
91
+ test: (password) => /[0-9]/.test(password),
92
+ },
93
+ {
94
+ key: 'special',
95
+ text: (config) => config.suggestionSpecial,
96
+ test: (password) => /[^A-Za-z0-9]/.test(password),
97
+ },
98
+ ]
99
+
68
100
  this._init()
69
101
  this._bindEvents()
70
102
  }
71
103
 
72
104
  // Getters
73
-
74
105
  static get NAME() {
75
106
  return NAME
76
107
  }
77
108
 
78
- // Public
79
-
80
109
  // Private
81
110
  _getConfig(config) {
82
111
  config = {
@@ -88,118 +117,174 @@ class InputPassword extends BaseComponent {
88
117
  }
89
118
 
90
119
  _init() {
91
- if (this._meter) {
92
- this._grayBarElement = this._meter.querySelector(SELECTOR_METER_GRAYBAR)
93
- this._colorBarElement = this._meter.querySelector(SELECTOR_METER_COLBAR)
94
- this._textElement = this._meter.querySelector(SELECTOR_TEXT)
95
-
96
- if (this._textElement) {
97
- this._config = Object.assign({}, this._config, { ...Manipulator.getDataAttributes(this._textElement) }, { enterPass: this._textElement.innerText })
98
- }
99
- }
100
120
  if (this._isCustom) {
101
- this._capsElement = this._element.parentNode.querySelector(SELECTOR_CAPS)
121
+ this._handleAutofill()
122
+ this._showPwdElement = SelectorEngine.findOne(SELECTOR_BTN_SHOW_PWD, this._element.parentNode)
123
+ if (this._meter) {
124
+ this._grayBarElement = this._meter.querySelector(SELECTOR_METER_GRAYBAR)
125
+ this._colorBarElement = this._meter.querySelector(SELECTOR_METER_COLBAR)
126
+ this._textElement = this._meter.querySelector(SELECTOR_METER_TEXT)
127
+ this._suggsElement = this._meter.querySelector(SELECTOR_METER_SUGGS)
128
+ if (this._textElement) {
129
+ this._config = Object.assign({}, this._config, { ...Manipulator.getDataAttributes(this._textElement) })
130
+ }
131
+ if (this._suggsElement) {
132
+ this._createsuggestionsList()
133
+ }
134
+ }
102
135
  }
103
-
104
- this._showPwdElement = SelectorEngine.findOne(SELECTOR_BTN_SHOW_PWD, this._element.parentNode)
105
136
  }
106
137
 
107
138
  _bindEvents() {
108
- if (this._meter) {
109
- EventHandler.on(this._element, EVENT_KEYUP, () => this._checkPassword())
110
- }
111
-
112
139
  if (this._isCustom) {
113
- EventHandler.on(this._element, EVENT_KEYDOWN, (evt) => {
114
- if (evt.key === 'Shift') {
115
- this._isShiftPressed = true
116
- }
117
- })
118
- EventHandler.on(this._element, EVENT_KEYUP, (evt) => {
119
- if (evt.key === 'Shift') {
120
- this._isShiftPressed = false
121
- }
122
- if (evt.key === 'CapsLock') {
123
- this._isCapsOn = !this._isCapsOn
124
- if (this._isCapsOn) {
125
- this._showCapsMsg()
126
- } else {
127
- this._hideCapsMsg()
128
- }
129
- }
130
- })
131
- EventHandler.on(this._element, EVENT_KEYPRESS, (evt) => {
132
- const matches = evt.key.match(/[A-Z]$/) || []
133
- if (matches.length > 0 && !this._isShiftPressed) {
134
- this._isCapsOn = true
135
- this._showCapsMsg()
136
- } else if (this._isCapsOn) {
137
- this._isCapsOn = false
138
- this._hideCapsMsg()
139
- }
140
- })
141
- }
142
-
143
- if (this._showPwdElement) {
144
- EventHandler.on(this._showPwdElement, EVENT_CLICK, () => this._toggleShowPassword())
140
+ if (this._showPwdElement) {
141
+ EventHandler.on(this._showPwdElement, EVENT_CLICK, () => this._toggleShowPassword())
142
+ }
143
+ if (this._meter) {
144
+ EventHandler.on(this._element, EVENT_KEYUP, () => this._checkPassword())
145
+ EventHandler.on(this._element, 'input', () => this._checkPassword())
146
+ }
145
147
  }
146
148
  }
147
149
 
148
- _showCapsMsg() {
149
- if (this._capsElement) {
150
- this._capsElement.classList.add(CLASS_NAME_SHOW)
151
- }
152
- }
153
- _hideCapsMsg() {
154
- if (this._capsElement) {
155
- this._capsElement.classList.remove(CLASS_NAME_SHOW)
150
+ _handleAutofill() {
151
+ const checkAndActivate = () => {
152
+ if (this._element.value !== '') {
153
+ this._label._labelOut()
154
+ this._checkPassword()
155
+ }
156
156
  }
157
+ checkAndActivate()
158
+ setTimeout(checkAndActivate, 100)
159
+ EventHandler.on(this._element, 'animationstart', (event) => {
160
+ if (event.animationName === 'onAutoFillStart') {
161
+ checkAndActivate()
162
+ }
163
+ })
157
164
  }
158
165
 
159
166
  _toggleShowPassword() {
160
167
  const toShow = this._element.getAttribute('type') === 'password'
161
168
  SelectorEngine.find('[class^="password-icon"]', this._showPwdElement).forEach((icon) => icon.classList.toggle('d-none'))
162
- if (toShow) {
163
- this._element.setAttribute('type', 'text')
164
- } else {
165
- this._element.setAttribute('type', 'password')
166
- }
169
+ this._element.setAttribute('type', toShow ? 'text' : 'password')
170
+ this._showPwdElement.setAttribute('aria-checked', toShow.toString())
167
171
  }
168
172
 
169
173
  _checkPassword() {
170
- const score = this._calculateScore(this._element.value)
171
- const perc = score < 0 ? 0 : score
172
-
173
- this._colorBarElement.classList.forEach((className) => {
174
- if (className.match(/(^|\s)bg-\S+/g)) {
175
- this._colorBarElement.classList.remove(className)
176
- }
177
- })
178
- this._colorBarElement.classList.add('bg-' + this._scoreColor(score))
179
- this._colorBarElement.style.width = perc + '%'
180
- this._colorBarElement.setAttribute('aria-valuenow', perc)
174
+ const password = this._element.value
175
+ const score = this._calculateScore(password)
176
+ this._updateMeter(score)
177
+ this._updateText(score, password)
178
+ this._updateSuggestions(password)
179
+ }
181
180
 
181
+ _updateMeter(score) {
182
+ const perc = score < 0 ? 0 : score
183
+ if (this._colorBarElement) {
184
+ this._colorBarElement.classList.forEach((className) => {
185
+ if (className.match(/(^|\s)bg-\S+/g)) {
186
+ this._colorBarElement.classList.remove(className)
187
+ }
188
+ })
189
+ this._colorBarElement.classList.add(`bg-${this._scoreColor(score)}`)
190
+ this._colorBarElement.style.width = `${perc}%`
191
+ this._colorBarElement.setAttribute('aria-valuenow', perc)
192
+ }
182
193
  EventHandler.trigger(this._element, EVENT_SCORE)
194
+ }
183
195
 
196
+ _updateText(score, password) {
184
197
  if (this._textElement) {
185
198
  let text = this._scoreText(score)
186
- if (this._element.value.length === 0 && score <= 0) {
187
- text = this._config.enterPass
199
+ if (this._suggsElement) {
200
+ const { completedCount, totalCount } = this._getCompletedSuggestions(password)
201
+ const suggestionText = completedCount === 1 ? this._config.suggestionFollowed : this._config.suggestionFollowedPlural
202
+ text += ` ${completedCount} ${this._config.suggestionOf} ${totalCount} ${suggestionText}.`
188
203
  }
189
-
190
- if (this._textElement.innerHTML.search(text) === -1) {
191
- this._textElement.innerHTML = text
204
+ if (this._textElement.textContent !== text) {
205
+ this._textElement.textContent = text
192
206
  this._textElement.classList.forEach((className) => {
193
207
  if (className.match(/(^|\s)text-\S+/g)) {
194
208
  this._textElement.classList.remove(className)
195
209
  }
196
210
  })
197
- this._textElement.classList.add('text-' + this._scoreColor(score))
211
+ this._textElement.classList.add(`text-${this._scoreColor(score)}`)
198
212
  EventHandler.trigger(this._element, EVENT_TEXT)
199
213
  }
200
214
  }
201
215
  }
202
216
 
217
+ _updateSuggestions(password) {
218
+ if (this._suggsElement) {
219
+ this._updateSuggestionsList(password)
220
+ EventHandler.trigger(this._element, EVENT_SUGGS)
221
+ }
222
+ }
223
+
224
+ _getCompletedSuggestions(password) {
225
+ let completedCount = 0
226
+ const totalCount = this._suggestions.length
227
+ this._suggestions.forEach((sugg) => {
228
+ if (sugg.test(password, this._config)) completedCount++
229
+ })
230
+ return { completedCount, totalCount }
231
+ }
232
+
233
+ _createsuggestionsList() {
234
+ if (this._suggsElement.querySelector('.password-suggestions')) {
235
+ return
236
+ }
237
+ const suggLabel = document.createElement('label')
238
+ suggLabel.className = 'visually-hidden'
239
+ suggLabel.htmlFor = 'suggestions'
240
+ suggLabel.textContent = Default.suggestionsLabel
241
+ const suggContainer = document.createElement('div')
242
+ suggContainer.id = 'suggestions'
243
+ suggContainer.className = 'password-suggestions'
244
+
245
+ this._suggestions.forEach((sugg) => {
246
+ const suggElement = document.createElement('div')
247
+ suggElement.className = 'suggestion'
248
+ suggElement.dataset.suggestion = sugg.key
249
+ const checkIcon = this._createIconCheck()
250
+ const textSpan = document.createElement('span')
251
+ textSpan.textContent = sugg.text(this._config)
252
+ suggElement.appendChild(checkIcon)
253
+ suggElement.appendChild(textSpan)
254
+ suggContainer.appendChild(suggElement)
255
+ })
256
+
257
+ this._suggsElement.appendChild(suggLabel)
258
+ this._suggsElement.appendChild(suggContainer)
259
+ }
260
+
261
+ _createIconCheck() {
262
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
263
+ svg.setAttribute('class', `icon icon-xs me-1 d-none`)
264
+ svg.setAttribute('aria-label', this._config.suggestionMetLabel)
265
+ svg.setAttribute('viewBox', '0 0 24 24')
266
+ svg.style.width = '1em'
267
+ svg.style.height = '1em'
268
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
269
+ path.setAttribute('d', this._config.suggestionMetIconPath.trim())
270
+ svg.appendChild(path)
271
+ return svg
272
+ }
273
+
274
+ _updateSuggestionsList(password) {
275
+ if (!this._suggsElement) return
276
+ this._suggestions.forEach((sugg) => {
277
+ const suggElement = this._suggsElement.querySelector(`[data-suggestion="${sugg.key}"]`)
278
+ if (suggElement) {
279
+ const isMet = sugg.test(password, this._config)
280
+ const checkIcon = suggElement.querySelector('.icon')
281
+ if (checkIcon) {
282
+ checkIcon.classList.toggle('d-none', !isMet)
283
+ }
284
+ }
285
+ })
286
+ }
287
+
203
288
  /**
204
289
  * Returns strings based on the score given.
205
290
  *
@@ -211,10 +296,14 @@ class InputPassword extends BaseComponent {
211
296
  return this._config.shortPass
212
297
  }
213
298
 
299
+ if (score === -2) {
300
+ return ''
301
+ }
302
+
214
303
  score = score < 0 ? 0 : score
215
304
 
216
305
  if (score < 26) {
217
- return this._config.shortPass
306
+ return this._config.badPass
218
307
  }
219
308
  if (score < 51) {
220
309
  return this._config.badPass
@@ -227,16 +316,7 @@ class InputPassword extends BaseComponent {
227
316
  }
228
317
 
229
318
  _scoreColor(score) {
230
- if (score === -1) {
231
- return 'danger'
232
- }
233
- if (score === -2) {
234
- return 'muted'
235
- }
236
-
237
- score = score < 0 ? 0 : score
238
-
239
- if (score < 26) {
319
+ if (score === -1 || score === -2 || score < 26) {
240
320
  return 'danger'
241
321
  }
242
322
  if (score < 51) {
@@ -245,7 +325,6 @@ class InputPassword extends BaseComponent {
245
325
  if (score < 76) {
246
326
  return 'success'
247
327
  }
248
-
249
328
  return 'success'
250
329
  }
251
330
 
@@ -281,7 +360,7 @@ class InputPassword extends BaseComponent {
281
360
  score += 5
282
361
  }
283
362
 
284
- // password has at least 2 sybols
363
+ // password has at least 2 symbols
285
364
  var symbols = '.*[!,@,#,$,%,^,&,*,?,_,~]'
286
365
  symbols = new RegExp('(' + symbols + symbols + ')')
287
366
  if (password.match(symbols)) {
@@ -360,11 +439,6 @@ class InputPassword extends BaseComponent {
360
439
  * ------------------------------------------------------------------------
361
440
  */
362
441
 
363
- /*const inputs = SelectorEngine.find(SELECTOR_PASSWORD)
364
- inputs.forEach((input) => {
365
- InputPassword.getOrCreateInstance(input)
366
- })*/
367
-
368
442
  const createInput = (element) => {
369
443
  if (element && element.matches(SELECTOR_PASSWORD)) {
370
444
  return InputPassword.getOrCreateInstance(element)
@@ -372,6 +446,19 @@ const createInput = (element) => {
372
446
  return null
373
447
  }
374
448
 
449
+ const initInputPassword = () => {
450
+ const element = SelectorEngine.findOne(SELECTOR_PASSWORD)
451
+ if (element) {
452
+ InputPassword.getOrCreateInstance(element)
453
+ }
454
+ }
455
+
456
+ if (document.readyState !== 'loading') {
457
+ initInputPassword()
458
+ } else {
459
+ document.addEventListener('DOMContentLoaded', initInputPassword)
460
+ }
461
+
375
462
  EventHandler.on(document, EVENT_MOUSEDOWN_DATA_API, SELECTOR_PASSWORD + ', label', function () {
376
463
  const target = InputLabel.getInputFromLabel(this) || this
377
464
  createInput(target)
package/src/js/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // bootstrap italia version variable
2
2
  // useful to check for the current version
3
3
  // eslint-disable-next-line no-unused-vars
4
- const BOOTSTRAP_ITALIA_VERSION = '2.9.2'
4
+ const BOOTSTRAP_ITALIA_VERSION = '2.11.0'
5
5
  export default BOOTSTRAP_ITALIA_VERSION
@@ -268,7 +268,7 @@ $link-list-divider-height: 1px;
268
268
  $link-list-divider-distance: 8px;
269
269
  $link-list-h-pad: 24px;
270
270
  $link-list-v-pad: 0.25em;
271
- $link-list-paragraph-size: 0.75rem;
271
+ $link-list-paragraph-size: 0.875rem;
272
272
  $link-list-left-icon-space: 8px;
273
273
  $link-list-avatar-radius: 50px;
274
274
  $link-list-avatar-margin: 8px;
@@ -551,25 +551,24 @@ $crs-landcape-bottom: 5px;
551
551
  // Gridlist **************
552
552
  $grid-item-df-proportion: 66.81222707423581%;
553
553
  $grid-item-df-double-proportion: 33.4061135371179%;
554
- $grid-item-text-size: 1rem;
555
- $grid-item-text-size-mob: 0.8rem;
554
+ $grid-item-text-size: 0.75rem;
556
555
  $grid-item-text-color: $neutral-1 !default; // Missing in the UI kit - need more attention
557
556
  $grid-item-text-overlay-bg: $neutral-1-a10 !default; // Missing in the UI kit - need more attention
558
557
  $grid-list-default-gap: 2px;
559
558
  $grid-list-text-gap: $v-gap;
560
559
  $grid-item-sm-col: 50%;
561
560
  $grid-item-lg-col: 33.333333%;
562
- $grid-item-icon-mob-size: 24px;
563
- $grid-item-icon-size-desk: 32px;
561
+ $grid-item-icon-size: 24px;
562
+ $grid-item-overlay: hsla(210%, 54%, 20, 0.85);
564
563
 
565
564
  // list
566
565
  $list-font-size: 1rem;
567
566
  $list-text-padding: $v-gap * 2 0 $v-gap * 2 0;
568
567
  $list-border-color: $gray-border !default; // UI kit
569
568
  $list-metadata-color: $color-text-muted !default; // Missing in the UI kit but token applicable
570
- $list-metadata-size: 12px;
569
+ $list-metadata-size: 0.75rem;
571
570
  $list-metadata-space: 0.5px;
572
- $list-sub-size: 14px;
571
+ $list-sub-size: 0.875rem;
573
572
  $list-sub-color: $color-text-muted !default; // UI kit
574
573
 
575
574
  //chips
@@ -1,3 +1,3 @@
1
1
  .figure-caption {
2
- font-size: 90%;
2
+ font-size: 0.75rem;
3
3
  }
@@ -12,7 +12,7 @@
12
12
  }
13
13
  .password-meter {
14
14
  height: 4px;
15
- left: 10px;
15
+ left: 7px;
16
16
  bottom: -6px;
17
17
  width: 100%;
18
18
  max-width: 180px;
@@ -129,6 +129,7 @@ textarea {
129
129
  background-position: center right !important;
130
130
  background-repeat: no-repeat !important;
131
131
  background-size: 45px 45% !important;
132
+ border-radius: 0 !important;
132
133
  min-height: 2.5rem;
133
134
  &:disabled,
134
135
  &[readonly] {
@@ -1,41 +1,47 @@
1
1
  //mobile
2
2
  .it-grid-item-wrapper {
3
3
  position: relative;
4
+
4
5
  // img default proportion
5
6
  .img-responsive-wrapper {
6
7
  border-radius: $border-radius;
8
+
7
9
  .img-responsive {
8
10
  padding-bottom: $grid-item-df-proportion;
9
11
  }
10
12
  }
13
+
11
14
  // text
12
15
  .it-griditem-text-wrapper {
13
16
  display: flex;
14
17
  justify-content: space-between;
15
- padding: $v-gap;
16
18
  align-items: center;
19
+
17
20
  .it-griditem-text {
18
- font-size: $grid-item-text-size-mob;
19
- color: $grid-item-text-color;
20
- font-weight: 600;
21
+ font-size: $grid-item-text-size;
22
+ font-weight: $font-weight-semibold;
21
23
  }
24
+
22
25
  .icon {
23
26
  flex-shrink: 0;
24
27
  position: relative;
25
- right: -$v-gap;
26
28
  fill: $primary;
27
- width: $grid-item-icon-mob-size;
28
- height: $grid-item-icon-mob-size;
29
+ width: $grid-item-icon-size;
30
+ height: $grid-item-icon-size;
29
31
  }
30
32
  }
33
+
31
34
  // text overlay
32
35
  &.it-grid-item-overlay {
33
36
  position: relative;
37
+
34
38
  .img-responsive-wrapper {
39
+ position: relative;
40
+
35
41
  &:after {
36
42
  content: '';
37
43
  display: block;
38
- background: rgba(0, 0, 0, 0.5);
44
+ background: $grid-item-overlay;
39
45
  position: absolute;
40
46
  left: 0;
41
47
  top: 0;
@@ -43,6 +49,7 @@
43
49
  height: 100%;
44
50
  }
45
51
  }
52
+
46
53
  .it-griditem-text-wrapper {
47
54
  position: absolute;
48
55
  left: 0;
@@ -59,7 +66,18 @@
59
66
  fill: #fff;
60
67
  }
61
68
  }
69
+
70
+ .figure-img {
71
+ margin-bottom: 0;
72
+ }
73
+
74
+ .figure-caption {
75
+ position: absolute;
76
+ z-index: 10;
77
+ color: #fff;
78
+ }
62
79
  }
80
+
63
81
  a {
64
82
  display: block;
65
83
  text-decoration: none;
@@ -85,24 +103,29 @@
85
103
  .it-grid-list-wrapper {
86
104
  padding-left: $grid-list-default-gap * 2;
87
105
  padding-right: $grid-list-default-gap * 2;
106
+
88
107
  // grid changes
89
108
  div[class^='col-'] {
90
109
  padding: 0 $grid-list-default-gap $grid-list-default-gap * 2 $grid-list-default-gap;
91
110
  }
111
+
92
112
  .grid-row {
93
113
  display: flex;
94
114
  margin-left: -$grid-list-default-gap;
95
115
  margin-right: -$grid-list-default-gap;
96
116
  flex-wrap: wrap;
97
117
  }
118
+
98
119
  // grid with label
99
120
  &.it-image-label-grid {
100
121
  padding-left: $grid-list-text-gap * 2;
101
122
  padding-right: $grid-list-text-gap * 2;
123
+
102
124
  // grid changes
103
125
  div[class^='col-'] {
104
126
  padding: 0 $grid-list-text-gap $grid-list-text-gap * 2 $grid-list-text-gap;
105
127
  }
128
+
106
129
  .grid-row {
107
130
  margin-left: -(($grid-list-text-gap * 2) + ($grid-list-default-gap * 2));
108
131
  margin-right: -(($grid-list-text-gap * 2) + ($grid-list-default-gap * 2));
@@ -117,12 +140,14 @@
117
140
  .img-responsive {
118
141
  padding-bottom: initial;
119
142
  height: auto;
143
+
120
144
  .img-wrapper {
121
145
  position: inherit;
122
146
  left: initial;
123
147
  right: initial;
124
148
  width: initial;
125
149
  height: initial;
150
+
126
151
  img {
127
152
  height: auto;
128
153
  object-fit: initial;
@@ -139,20 +164,11 @@
139
164
  &.it-grid-item-overlay {
140
165
  .it-griditem-text-wrapper {
141
166
  padding: $v-gap * 2 $v-gap * 3;
167
+
142
168
  .it-griditem-text {
143
169
  font-size: $grid-item-text-size;
144
170
  }
145
171
  }
146
172
  }
147
- // text
148
- .it-griditem-text-wrapper {
149
- .it-griditem-text {
150
- font-size: $grid-item-text-size;
151
- }
152
- .icon {
153
- width: $grid-item-icon-size-desk;
154
- height: $grid-item-icon-size-desk;
155
- }
156
- }
157
173
  }
158
174
  }