@bildvitta/quasar-ui-asteroid 3.17.0 → 3.18.0-beta.1

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 (65) hide show
  1. package/package.json +1 -1
  2. package/src/components/actions-menu/QasActionsMenu.vue +3 -3
  3. package/src/components/alert/QasAlert.vue +187 -60
  4. package/src/components/alert/QasAlert.yml +27 -5
  5. package/src/components/app-bar/QasAppBar.vue +2 -0
  6. package/src/components/app-menu/QasAppMenu.vue +127 -68
  7. package/src/components/app-menu/QasAppMenu.yml +10 -0
  8. package/src/components/app-user/QasAppUser.vue +12 -8
  9. package/src/components/app-user/QasAppUser.yml +5 -0
  10. package/src/components/badge/QasBadge.vue +1 -1
  11. package/src/components/checkbox/QasCheckbox.vue +97 -32
  12. package/src/components/date-time-input/QasDateTimeInput.vue +2 -2
  13. package/src/components/error-message/QasErrorMessage.vue +23 -0
  14. package/src/components/error-message/QasErrorMessage.yml +9 -0
  15. package/src/components/expansion-item/QasExpansionItem.vue +14 -16
  16. package/src/components/filters/QasFilters.vue +51 -30
  17. package/src/components/filters/QasFilters.yml +9 -0
  18. package/src/components/gallery/QasGallery.vue +2 -3
  19. package/src/components/gallery-card/QasGalleryCard.vue +43 -12
  20. package/src/components/gallery-card/QasGalleryCard.yml +22 -6
  21. package/src/components/input/QasInput.vue +3 -3
  22. package/src/components/label/QasLabel.vue +1 -1
  23. package/src/components/list-view/QasListView.vue +6 -1
  24. package/src/components/list-view/QasListView.yml +5 -0
  25. package/src/components/nested-fields/QasNestedFields.vue +10 -2
  26. package/src/components/nested-fields/QasNestedFields.yml +18 -3
  27. package/src/components/password-input/QasPasswordInput.vue +6 -2
  28. package/src/components/radio/QasRadio.vue +56 -10
  29. package/src/components/radio/QasRadio.yml +8 -1
  30. package/src/components/search-input/QasSearchInput.vue +14 -29
  31. package/src/components/select/QasSelect.vue +31 -21
  32. package/src/components/select-filter/QasSelectFilter.vue +33 -6
  33. package/src/components/select-filter/QasSelectFilter.yml +5 -0
  34. package/src/components/select-list/QasSelectList.vue +6 -6
  35. package/src/components/select-list/private/PvSelectListCheckbox.vue +1 -1
  36. package/src/components/table-generator/QasTableGenerator.vue +10 -5
  37. package/src/components/table-generator/QasTableGenerator.yml +9 -4
  38. package/src/components/toggle/QasToggle.vue +26 -1
  39. package/src/components/toggle-visibility/QasToggleVisibility.vue +15 -6
  40. package/src/components/tree-generator/QasTreeGenerator.vue +10 -2
  41. package/src/components/uploader/QasUploader.vue +7 -14
  42. package/src/components/uploader/private/PvUploaderGalleryCard.vue +2 -2
  43. package/src/composables/private/index.js +3 -2
  44. package/src/composables/private/use-error-message.js +28 -0
  45. package/src/composables/use-default-filters.js +47 -15
  46. package/src/css/components/field.scss +69 -2
  47. package/src/css/components/index.scss +1 -3
  48. package/src/css/components/item.scss +3 -2
  49. package/src/css/components/menu.scss +21 -0
  50. package/src/css/mixins/index.scss +1 -0
  51. package/src/css/mixins/set-error-message.scss +8 -0
  52. package/src/css/plugins/notify.scss +37 -37
  53. package/src/css/variables/scrollbar.scss +1 -1
  54. package/src/enums/Status.js +3 -3
  55. package/src/helpers/colors.js +137 -0
  56. package/src/helpers/index.js +1 -0
  57. package/src/helpers/set-scroll-gradient.js +261 -0
  58. package/src/plugins/notify-error/NotifyError.js +2 -1
  59. package/src/plugins/notify-success/NotifySuccess.js +2 -1
  60. package/src/vue-plugin.js +3 -3
  61. package/src/components/info/QasInfo.vue +0 -155
  62. package/src/components/info/QasInfo.yml +0 -34
  63. package/src/css/components/checkbox.scss +0 -14
  64. package/src/css/components/radio.scss +0 -18
  65. package/src/css/components/toggle.scss +0 -13
@@ -1,4 +1,5 @@
1
- export { default as useView } from './use-view'
1
+ export { default as useAuthUser } from './use-auth-user'
2
+ export { default as useErrorMessage } from './use-error-message'
2
3
  export { default as useGenerator } from './use-generator'
3
4
  export { default as useToggleVisibility } from './use-toggle-visibility'
4
- export { default as useAuthUser } from './use-auth-user'
5
+ export { default as useView } from './use-view'
@@ -0,0 +1,28 @@
1
+ import { computed } from 'vue'
2
+
3
+ export const baseErrorProps = {
4
+ errorMessage: {
5
+ type: String,
6
+ default: ''
7
+ },
8
+
9
+ error: {
10
+ type: Boolean
11
+ }
12
+ }
13
+
14
+ /**
15
+ * Composable para lidar com mensagens de erro
16
+ *
17
+ * @param {baseErrorProps} props
18
+ */
19
+ export default function useErrorMessage (props) {
20
+ const labelClasses = computed(() => ({ 'text-negative': props.error }))
21
+
22
+ const color = computed(() => (props.error ? 'negative' : 'grey-10'))
23
+
24
+ return {
25
+ labelClasses,
26
+ color
27
+ }
28
+ }
@@ -15,10 +15,25 @@ const defaultFiltersHooks = {
15
15
  * 2 - Se o filtro já estiver na query, então utiliza ele.
16
16
  * 3 - Se o filtro já estiver salvo no LocalStorage, então utiliza ele.
17
17
  *
18
- * @param {Object} to - Rota de destino.
19
- * @param {Object} _from - Rota de origem.
20
- * @param {Function} next - Função de redirecionamento.
21
- * @param {Array} queryList='company' - Lista de filtros a serem aplicados.
18
+ * Comportamento entre mesma entidade variando telas com multiple: true|false:
19
+ * 1 - Se minha tela atual for de múltiplos registros e a próxima for de um único registro,
20
+ * então o filtro será aplicado apenas no primeiro item.
21
+ * 2 - Se minha tela atual for de um único registro e a próxima for de múltiplos registros,
22
+ * então o filtro será aplicado em todos os registros.
23
+ * 3 - Se minha tela atual e a próxima forem de múltiplos registros, então o filtro será aplicado
24
+ * em todos os registros.
25
+ *
26
+ * @param {object} to - Rota de destino.
27
+ * @param {object} _from - Rota de origem.
28
+ * @param {function} next - Função de redirecionamento.
29
+ * @param {array|object} queryList='company' - Lista de filtros a serem aplicados.
30
+ *
31
+ * @example
32
+ * ```js
33
+ * setDefaultFiltersBeforeEnter(to, from, next)
34
+ * setDefaultFiltersBeforeEnter(to, from, next, ['company', 'properties'])
35
+ * setDefaultFiltersBeforeEnter(to, from, next, { company: false, properties: true // multiple })
36
+ * ```
22
37
  */
23
38
  export function setDefaultFiltersBeforeEnter (to, _from, next, queryList = ['company']) {
24
39
  const { getDefaultFiltersFromStorage, setFilterQuery } = useDefaultFilters()
@@ -26,31 +41,48 @@ export function setDefaultFiltersBeforeEnter (to, _from, next, queryList = ['com
26
41
  const { query } = to
27
42
  const newQuery = { ...query }
28
43
 
44
+ const isQueryListArray = Array.isArray(queryList)
45
+ const normalizedQueryList = isQueryListArray ? {} : queryList
46
+
47
+ // normaliza sempre o queryList para um objeto
48
+ if (isQueryListArray) {
49
+ queryList.forEach(name => { normalizedQueryList[name] = false })
50
+ }
51
+
29
52
  // recupera os filtros padrão do LocalStorage
30
53
  const defaultFiltersFromStorage = getDefaultFiltersFromStorage()
31
54
 
32
- queryList.forEach(name => {
55
+ for (const key in normalizedQueryList) {
56
+ const filterQueryValue = filterQuery.value[key]
57
+
33
58
  // 1. se o filtro já estiver salvo no estado, então utiliza ele
34
- if (filterQuery.value[name]) {
35
- newQuery[name] = filterQuery.value[name]
36
- return
59
+ if (filterQueryValue) {
60
+ // se normalizedQueryList[key] for "true" (multiple) então utiliza o filtro completo
61
+ if (normalizedQueryList[key]) {
62
+ newQuery[key] = filterQueryValue
63
+ continue
64
+ }
65
+
66
+ // filterQueryValue é um array, então pega o primeiro item
67
+ newQuery[key] = Array.isArray(filterQueryValue) ? filterQueryValue?.at(0) : filterQueryValue
68
+ continue
37
69
  }
38
70
 
39
71
  // 2. se o filtro já estiver na query, então utiliza ele
40
- if (query[name]) {
41
- setFilterQuery(query[name], name)
72
+ if (query[key]) {
73
+ setFilterQuery(query[key], key)
42
74
 
43
- return
75
+ continue
44
76
  }
45
77
 
46
- const storedFilter = defaultFiltersFromStorage[name]
78
+ const storedFilter = defaultFiltersFromStorage[key]
47
79
 
48
80
  // 3. se o filtro já estiver salvo no LocalStorage, então utiliza ele
49
81
  if (storedFilter) {
50
- setFilterQuery(storedFilter, name)
51
- newQuery[name] = storedFilter
82
+ setFilterQuery(storedFilter, key)
83
+ newQuery[key] = storedFilter
52
84
  }
53
- })
85
+ }
54
86
 
55
87
  /**
56
88
  * Verifica se houve mudanças na query antes de redirecionar, sem essa validação
@@ -7,8 +7,21 @@
7
7
  transition: transform var(--qas-generic-transition);
8
8
  }
9
9
 
10
+ &--standard &__control:hover::before {
11
+ border-color: var(--q-primary-contrast) !important;
12
+ }
13
+
14
+ &--standard &__control::after {
15
+ height: 1px;
16
+ }
17
+
18
+ &--outlined &__control::after,
19
+ &--outlined.q-field--highlighted &__control::after {
20
+ border-width: 1px !important;
21
+ }
22
+
10
23
  .q-field__label {
11
- will-change: transform;
24
+ will-change: transform, font-size;
12
25
  }
13
26
 
14
27
  &__label,
@@ -16,6 +29,22 @@
16
29
  @include set-typography($body2);
17
30
  }
18
31
 
32
+ // pega o ícone imediato dos append e prepend, não os do q-chip por exemplo.
33
+ &--error {
34
+ .q-field__input,
35
+ .q-field__label,
36
+ .q-field__native,
37
+ .q-field__marginal > .q-icon,
38
+ .q-field__marginal > .qas-btn .q-icon,
39
+ .q-field__marginal > button.q-icon {
40
+ color: $negative !important;
41
+ }
42
+
43
+ .q-field__bottom {
44
+ @include set-error-message;
45
+ }
46
+ }
47
+
19
48
  &--dense {
20
49
  .q-textarea {
21
50
  height: 100%;
@@ -42,9 +71,10 @@
42
71
  // Somente fields com label
43
72
  &--float.q-field--labeled,
44
73
  &--focused.q-field--labeled {
74
+ will-change: transform, font-size;
45
75
  transition: transform var(--qas-generic-transition), font-size var(--qas-generic-transition);
46
76
 
47
- &:not(&.qas-select--filter):not(&.qas-select--has-icon) .q-field__label {
77
+ &:not(&.qas-select--filter):not(&.qas-select--has-icon):not(&.qas-input--has-icon) .q-field__label {
48
78
  transform: translateY(-10px) scale(0.85) !important;
49
79
  }
50
80
 
@@ -60,6 +90,7 @@
60
90
  }
61
91
 
62
92
  .q-field__label {
93
+ color: $grey-8;
63
94
  transition: transform var(--qas-generic-transition), font-size var(--qas-generic-transition);
64
95
  }
65
96
 
@@ -85,4 +116,40 @@
85
116
  background-color: white;
86
117
  border-radius: $generic-border-radius;
87
118
  }
119
+
120
+ // logica referente ao modo filtro
121
+ &.qas-search-input,
122
+ &.qas-select--filter {
123
+ .q-field__control::before {
124
+ transition: border var(--qas-generic-transition);
125
+ }
126
+
127
+ &:not(&.q-field--error):not(&.q-field--highlighted):hover {
128
+ .q-field__control::after {
129
+ border-color: var(--q-primary-contrast);
130
+ }
131
+ }
132
+
133
+ .q-field__control {
134
+ border-radius: $generic-border-radius;
135
+ }
136
+
137
+ .q-field__control::before {
138
+ border: 0;
139
+ }
140
+ }
141
+
142
+ &.qas-search-input--shadow,
143
+ &.qas-select--filter-shadow {
144
+ .q-field__control {
145
+ box-shadow: $shadow-2;
146
+ }
147
+ }
148
+
149
+ &.qas-search-input--border,
150
+ &.qas-select--filter-border {
151
+ .q-field__control {
152
+ @extend .bordered;
153
+ }
154
+ }
88
155
  }
@@ -1,10 +1,8 @@
1
1
  @import './base';
2
2
  @import './button';
3
- @import './checkbox';
4
3
  @import './editor';
5
4
  @import './field';
6
5
  @import './item';
7
- @import './radio';
6
+ @import './menu.scss';
8
7
  @import './scrollbar';
9
8
  @import './tabs';
10
- @import './toggle';
@@ -1,5 +1,6 @@
1
1
  .q-item {
2
2
  font-size: 16px;
3
+ min-height: 36px;
3
4
 
4
5
  &:not(.disabled) {
5
6
  font-weight: 600;
@@ -26,11 +27,11 @@
26
27
  }
27
28
 
28
29
  &--clickable:not(&--active) {
29
- color: $grey-10;
30
+ color: $grey-10 !important;
30
31
  transition: var(--qas-generic-transition);
31
32
 
32
33
  &:not(&.q-router-link--active):hover {
33
- color: var(--q-primary-contrast);
34
+ color: var(--q-primary-contrast) !important;
34
35
  }
35
36
  }
36
37
 
@@ -0,0 +1,21 @@
1
+ .qas-menu {
2
+ border-radius: $generic-border-radius;
3
+
4
+ .q-list {
5
+ padding: var(--qas-spacing-sm) var(--qas-spacing-md);
6
+
7
+ .q-item {
8
+ padding-left: 0;
9
+ padding-right: 0;
10
+ min-height: 36px !important;
11
+
12
+ .q-icon {
13
+ font-size: 18px !important;
14
+ }
15
+ }
16
+
17
+ .q-item + .q-item {
18
+ border-top: 1px solid $border-grey;
19
+ }
20
+ }
21
+ }
@@ -1,3 +1,4 @@
1
1
  @import './set-button';
2
2
  @import './set-brand';
3
3
  @import './set-typography';
4
+ @import './set-error-message';
@@ -0,0 +1,8 @@
1
+ @import '../variables/typography.scss';
2
+
3
+ @mixin set-error-message ($important: false) {
4
+ @include set-typography($caption, $important);
5
+
6
+ padding-top: if($important, var(--qas-spacing-sm) !important, var(--qas-spacing-sm));
7
+ color: if($important, $negative !important, $negative);
8
+ }
@@ -1,54 +1,40 @@
1
1
  .q-notification {
2
+ $root: &;
3
+
2
4
  &:not(.boot-notification).qas-notification {
3
5
  margin-top: 80px;
4
- max-width: 560px;
6
+ max-width: 740px;
5
7
  }
6
8
 
9
+
7
10
  &.qas-notification {
8
- &--error::before,
9
- &--success::before {
10
- border-radius: var(--qas-generic-border-radius) 0 0 var(--qas-generic-border-radius);
11
- bottom: 0;
12
- content: '';
13
- left: calc(var(--qas-spacing-md) * -1);
14
- position: relative;
15
- top: 0;
16
- width: 4px;
17
- }
11
+ box-shadow: none;
18
12
 
19
- &--error::before {
20
- background-color: var(--q-negative);
13
+ &--error #{$root}__progress {
14
+ background-color: $negative;
21
15
  }
22
16
 
23
- &--success::before {
24
- background-color: var(--q-positive);
17
+ &--success #{$root}__progress {
18
+ background-color: $positive;
25
19
  }
26
20
 
27
21
  .q-notification__actions {
28
- align-self: start;
22
+ align-self: self-start;
29
23
  padding-top: var(--qas-spacing-xs);
24
+ }
30
25
 
31
- .q-btn {
32
- color: white !important;
33
- height: var(--qas-spacing-md);
34
- min-height: auto;
35
- min-width: auto;
36
- padding: 0;
37
- text-align: center;
38
- text-transform: none;
39
- width: var(--qas-spacing-md);
40
-
41
- &__content {
42
- height: var(--qas-spacing-md);
43
-
44
- span {
45
- align-self: center;
46
- height: var(--qas-spacing-md);
47
- line-height: 0.9;
48
- width: var(--qas-spacing-md);
49
- }
50
- }
51
- }
26
+ .q-notification__badge {
27
+ @include set-typography($caption);
28
+
29
+ box-shadow: none;
30
+ }
31
+
32
+ .q-btn {
33
+ @include set-button(tertiary, true, true, 'white');
34
+
35
+ // o quasar não usa um ícone, mas sim um label "x", por isto o font-size e font-weight.
36
+ font-size: 24px;
37
+ font-weight: 400;
52
38
  }
53
39
 
54
40
  .q-notification__content {
@@ -56,6 +42,20 @@
56
42
  margin-right: var(--qas-spacing-sm);
57
43
  }
58
44
  }
45
+
46
+ .q-notification__progress {
47
+ border-radius: 0 0 var(--qas-generic-border-radius) var(--qas-generic-border-radius);
48
+ left: calc(var(--qas-spacing-md) * -1);
49
+ right: calc(var(--qas-spacing-md) * -1);
50
+ opacity: 1;
51
+ }
52
+
53
+ .q-notification__message {
54
+ @include set-typography($body1);
55
+
56
+ padding-top: var(--qas-spacing-md);
57
+ padding-bottom: var(--qas-spacing-md);
58
+ }
59
59
  }
60
60
 
61
61
  &.boot-notification {
@@ -1,6 +1,6 @@
1
1
  :root {
2
2
  --qas-scrollbar-size: 9px;
3
- --qas-scrollbar-background: #E0E0E0;
3
+ --qas-scrollbar-background: transparent;
4
4
  --qas-scrollbar-thumb-background: var(--q-primary);
5
5
  --qas-scrollbar-thumb-background-hover: var(--q-primary-contrast);
6
6
  --qas-scrollbar-border-radius: calc(var(--qas-generic-border-radius) * 2);
@@ -7,12 +7,12 @@
7
7
  * @enum
8
8
  * @type {{
9
9
  * Info: 'yellow-14',
10
- * Error: 'red-14'
10
+ * Error: 'negative'
11
11
  * }}
12
12
  */
13
13
  export const StatusColor = {
14
- Info: 'yellow-14',
15
- Error: 'red-14'
14
+ Info: 'primary',
15
+ Error: 'negative'
16
16
  }
17
17
 
18
18
  /**
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Converte uma cor RGBA para RGB, mesclando com um fundo.
3
+ *
4
+ * @param {string} rgba - Cor em formato rgba, por exemplo, "rgba(15, 83, 175, 0.03)".
5
+ * @param {object} background - Objeto com as propriedades r, g e b para a cor de fundo (default: branco).
6
+ *
7
+ * @example
8
+ * ```js
9
+ * convertRgbaToRgb('rgba(15, 83, 175, 0.03)') // { r: 15, g: 83, b: 175 }
10
+ * ```
11
+ */
12
+ export function convertRgbaToRgb (rgba, background = { r: 255, g: 255, b: 255 }) {
13
+ // Extrai os valores com uma expressão regular
14
+ const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/)
15
+
16
+ if (!match) return background
17
+
18
+ const r = parseInt(match[1], 10)
19
+ const g = parseInt(match[2], 10)
20
+ const b = parseInt(match[3], 10)
21
+ const a = parseFloat(match[4])
22
+
23
+ return {
24
+ r: Math.round(r * a + background.r * (1 - a)),
25
+ g: Math.round(g * a + background.g * (1 - a)),
26
+ b: Math.round(b * a + background.b * (1 - a))
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Função que converte uma cor hexadecimal para um objeto RGB.
32
+ *
33
+ * @param {string} hex - A cor em formato hexadecimal, por exemplo, "#ff0000" ou "ff0000".
34
+ *
35
+ * @example
36
+ * ```js
37
+ * convertHexToRgb('#ff0000') // { r: 255, g: 0, b: 0 }
38
+ * convertHexToRgb('ff0000') // { r: 255, g: 0, b: 0 }
39
+ * ```
40
+ */
41
+ export function convertHexToRgb (hex) {
42
+ // Remove o '#' se existir
43
+ let cleanHex = hex.startsWith('#') ? hex.slice(1) : hex
44
+
45
+ // Se for o formato curto, expande para 6 dígitos
46
+ if (cleanHex.length === 3) {
47
+ cleanHex = cleanHex.split('').map(item => item + item).join('')
48
+ }
49
+
50
+ // Converte o hexadecimal para inteiro
51
+ const bigint = parseInt(cleanHex, 16)
52
+
53
+ // Extrai os valores de r, g, b
54
+ const r = (bigint >> 16) & 255
55
+ const g = (bigint >> 8) & 255
56
+ const b = bigint & 255
57
+
58
+ return { r, g, b }
59
+ }
60
+
61
+ /**
62
+ * converte um rgb em string para objeto rgb
63
+ *
64
+ * @param {string} color - A cor em formato rgb, por exemplo, "rgb(255, 0, 0)".
65
+ *
66
+ * @example
67
+ * ```js
68
+ * getRgb('rgb(255, 0, 0)') // { r: 255, g: 0, b: 0 }
69
+ * ```
70
+ */
71
+ function getRgb (color) {
72
+ // Extrai os valores com uma expressão regular
73
+ const match = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/)
74
+
75
+ if (!match) return {}
76
+
77
+ const r = parseInt(match[1], 10)
78
+ const g = parseInt(match[2], 10)
79
+ const b = parseInt(match[3], 10)
80
+
81
+ return { r, g, b }
82
+ }
83
+
84
+ /**
85
+ * função que recebe uma cor como parâmetro string, e retorna sempre um rgb,
86
+ * os possíveis formatos de entrada são:
87
+ * - rgb
88
+ * - rgba
89
+ * - hex
90
+ *
91
+ * @example
92
+ *
93
+ * ```js
94
+ * convertToRgb('#ff0000') // { r: 255, g: 0, b: 0 }
95
+ * convertToRgb('rgba(255, 0, 0, 0.5)') // { r: 255, g: 0, b: 0 }
96
+ * convertToRgb('rgb(255, 0, 0)') // { r: 255, g: 0, b: 0 }
97
+ * ```
98
+ *
99
+ */
100
+ export function convertToRgb (color) {
101
+ if (!color) return {}
102
+
103
+ // Verifica se a cor está no formato hex
104
+ if (isHex(color)) return convertHexToRgb(color)
105
+
106
+ // Verifica se a cor está no formato rgba
107
+ if (isRgba(color)) return convertRgbaToRgb(color)
108
+
109
+ // Se não for nenhum dos formatos conhecidos, retorna a cor original
110
+ return getRgb(color)
111
+ }
112
+
113
+ export function isRgba (color) {
114
+ return color.startsWith('rgba')
115
+ }
116
+
117
+ export function isHex (color) {
118
+ return color.startsWith('#')
119
+ }
120
+
121
+ export function isRgb (color) {
122
+ return color.startsWith('rgb') && !isRgba(color)
123
+ }
124
+
125
+ /**
126
+ * função para retornar css vars do asteroid
127
+ *
128
+ * @param {string} name - nome da variável css
129
+ *
130
+ * @example
131
+ * ```js
132
+ * getCssVar('background-color') // #ff0000
133
+ * ```
134
+ */
135
+ export function getCssVar (name) {
136
+ return getComputedStyle(document.documentElement).getPropertyValue(`--qas-${name}`)
137
+ }
@@ -19,6 +19,7 @@ export { default as isLocalDevelopment } from './is-local-development.js'
19
19
  export { default as promiseHandler } from './promise-handler.js'
20
20
  export { default as setScrollOnGrab } from './set-scroll-on-grab.js'
21
21
  export { default as getPlaceholder } from './get-placeholder.js'
22
+ export { default as setScrollGradient } from './set-scroll-gradient.js'
22
23
 
23
24
  export * from './filters.js'
24
25
  export * from './images.js'