@andreyshpigunov/x 0.3.72

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 (60) hide show
  1. package/.editorconfig +12 -0
  2. package/.github/workflows/publish.yml +28 -0
  3. package/README.md +37 -0
  4. package/assets/alpha.png +0 -0
  5. package/assets/apple-touch-icon.png +0 -0
  6. package/assets/github-mark-white.png +0 -0
  7. package/assets/github-mark.png +0 -0
  8. package/assets/logo-inverse.png +0 -0
  9. package/assets/logo.png +0 -0
  10. package/assets/logo.svg +9 -0
  11. package/babel.config.cjs +4 -0
  12. package/dist/app.css +167 -0
  13. package/dist/app.js +1 -0
  14. package/dist/x.css +167 -0
  15. package/dist/x.js +1 -0
  16. package/favicon.ico +0 -0
  17. package/favicon.svg +9 -0
  18. package/index.html +2214 -0
  19. package/index.js +1 -0
  20. package/jest.config.mjs +7 -0
  21. package/jsdoc.json +11 -0
  22. package/package.json +50 -0
  23. package/src/components/x/animate.js +296 -0
  24. package/src/components/x/appear.js +158 -0
  25. package/src/components/x/autocomplete.js +150 -0
  26. package/src/components/x/buttons.css +265 -0
  27. package/src/components/x/colors.css +64 -0
  28. package/src/components/x/debug.css +55 -0
  29. package/src/components/x/device.js +265 -0
  30. package/src/components/x/dropdown.css +164 -0
  31. package/src/components/x/dropdown.js +463 -0
  32. package/src/components/x/flex.css +163 -0
  33. package/src/components/x/flow.css +52 -0
  34. package/src/components/x/form.css +138 -0
  35. package/src/components/x/form.js +180 -0
  36. package/src/components/x/grid.css +109 -0
  37. package/src/components/x/helpers.css +928 -0
  38. package/src/components/x/hover.js +93 -0
  39. package/src/components/x/icons.css +58 -0
  40. package/src/components/x/lazyload.js +153 -0
  41. package/src/components/x/lib.js +679 -0
  42. package/src/components/x/links.css +114 -0
  43. package/src/components/x/loadmore.js +191 -0
  44. package/src/components/x/modal.css +286 -0
  45. package/src/components/x/modal.js +346 -0
  46. package/src/components/x/reset.css +213 -0
  47. package/src/components/x/scroll.css +100 -0
  48. package/src/components/x/scroll.js +301 -0
  49. package/src/components/x/sheets.css +15 -0
  50. package/src/components/x/sheets.js +147 -0
  51. package/src/components/x/slider.css +83 -0
  52. package/src/components/x/slider.js +330 -0
  53. package/src/components/x/space.css +56 -0
  54. package/src/components/x/sticky.css +28 -0
  55. package/src/components/x/sticky.js +156 -0
  56. package/src/components/x/typo.css +318 -0
  57. package/src/css/app.css +407 -0
  58. package/src/css/x.css +252 -0
  59. package/src/js/app.js +47 -0
  60. package/src/js/x.js +81 -0
@@ -0,0 +1,163 @@
1
+ /*----------------------------------------
2
+ flex.css / x
3
+ Flexbox
4
+
5
+ Created by Andrey Shpigunov at 20.03.2025
6
+ All right reserved.
7
+ ----------------------------------------*/
8
+
9
+
10
+ /*
11
+ .flex
12
+
13
+ .flex.fr (m,l,xl) - flex row
14
+ .flex.fc (m,l,xl) - flex column
15
+ .flex.fw (m,l,xl) - flex wrap
16
+ .flex.fnw (m,l,xl) - flex nowrap
17
+
18
+ .flex.ais (m,l,xl) - stretch
19
+ .flex.aifs (m,l,xl) - flex start
20
+ .flex.aic (m,l,xl) - center
21
+ .flex.aife (m,l,xl) - flex end
22
+
23
+ .flex.jcfs (m,l,xl) - flex start
24
+ .flex.jcc (m,l,xl) - center
25
+ .flex.jcfe (m,l,xl) - flex end
26
+ .flex.jcsb (m,l,xl) - space between
27
+ .flex.jcsa (m,l,xl) - space around
28
+ .flex.jcse (m,l,xl) - space evenly
29
+
30
+ .flex > .c[1-12]/[1-12] (m,l,xl) - column width "column/columns"
31
+ */
32
+
33
+
34
+ .flex {
35
+ display: flex;
36
+
37
+ &.fr { flex-direction: row }
38
+ &.fc { flex-direction: column }
39
+ &.fw { flex-wrap: wrap }
40
+ &.fnw { flex-wrap: nowrap }
41
+
42
+ &.ais { align-items: stretch }
43
+ &.aifs { align-items: flex-start }
44
+ &.aic { align-items: center }
45
+ &.aife { align-items: flex-end }
46
+
47
+ &.jcfs { justify-content: flex-start }
48
+ &.jcc { justify-content: center }
49
+ &.jcfe { justify-content: flex-end }
50
+ &.jcsb { justify-content: space-between }
51
+ &.jcsa { justify-content: space-around }
52
+ &.jcse { justify-content: space-evenly }
53
+
54
+ & > .noshrink { flex-shrink: 0 }
55
+ & > .nogrow { flex-grow: 0 }
56
+
57
+ /* Columns */
58
+ @for $cols from 1 to 12 {
59
+ @for $col from 1 to $cols {
60
+ & > .c$(col)\/$(cols) {
61
+ flex-basis: calc($(col) / $(cols) * 100%);
62
+ max-width: calc($(col) / $(cols) * 100%);
63
+ }
64
+ }
65
+ }
66
+
67
+ @media (--medium) {
68
+
69
+ &.m\:fr { flex-direction: row }
70
+ &.m\:fc { flex-direction: column }
71
+ &.m\:fw { flex-wrap: wrap }
72
+ &.m\:fnw { flex-wrap: nowrap }
73
+
74
+ &.m\:ais { align-items: stretch }
75
+ &.m\:aifs { align-items: flex-start }
76
+ &.m\:aic { align-items: center }
77
+ &.m\:aife { align-items: flex-end }
78
+
79
+ &.m\:jcfs { justify-content: flex-start }
80
+ &.m\:jcc { justify-content: center }
81
+ &.m\:jcfe { justify-content: flex-end }
82
+ &.m\:jcsb { justify-content: space-between }
83
+ &.m\:jcsa { justify-content: space-around }
84
+ &.m\:jcse { justify-content: space-evenly }
85
+
86
+ & > .m\:noshrink { flex-shrink: 0 }
87
+ & > .m\:nogrow { flex-grow: 0 }
88
+
89
+ @for $cols from 1 to 12 {
90
+ @for $col from 1 to $cols {
91
+ & > .m\:c$(col)\/$(cols) {
92
+ flex-basis: calc($(col) / $(cols) * 100%);
93
+ max-width: calc($(col) / $(cols) * 100%);
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ @media (--large) {
100
+
101
+ &.l\:fr { flex-direction: row }
102
+ &.l\:fc { flex-direction: column }
103
+ &.l\:fw { flex-wrap: wrap }
104
+ &.l\:fnw { flex-wrap: nowrap }
105
+
106
+ &.l\:ais { align-items: stretch }
107
+ &.l\:aifs { align-items: flex-start }
108
+ &.l\:aic { align-items: center }
109
+ &.l\:aife { align-items: flex-end }
110
+
111
+ &.l\:jcfs { justify-content: flex-start }
112
+ &.l\:jcc { justify-content: center }
113
+ &.l\:jcfe { justify-content: flex-end }
114
+ &.l\:jcsb { justify-content: space-between }
115
+ &.l\:jcsa { justify-content: space-around }
116
+ &.l\:jcse { justify-content: space-evenly }
117
+
118
+ & > .l\:noshrink { flex-shrink: 0 }
119
+ & > .l\:nogrow { flex-grow: 0 }
120
+
121
+ @for $cols from 1 to 12 {
122
+ @for $col from 1 to $cols {
123
+ & > .l\:c$(col)\/$(cols) {
124
+ flex-basis: calc($(col) / $(cols) * 100%);
125
+ max-width: calc($(col) / $(cols) * 100%);
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ @media (--xlarge) {
132
+
133
+ &.xl\:fr { flex-direction: row }
134
+ &.xl\:fc { flex-direction: column }
135
+ &.xl\:fw { flex-wrap: wrap }
136
+ &.xl\:fnw { flex-wrap: nowrap }
137
+
138
+ &.xl\:ais { align-items: stretch }
139
+ &.xl\:aifs { align-items: flex-start }
140
+ &.xl\:aic { align-items: center }
141
+ &.xl\:aife { align-items: flex-end }
142
+
143
+ &.xl\:jcfs { justify-content: flex-start }
144
+ &.xl\:jcc { justify-content: center }
145
+ &.xl\:jcfe { justify-content: flex-end }
146
+ &.xl\:jcsb { justify-content: space-between }
147
+ &.xl\:jcsa { justify-content: space-around }
148
+ &.xl\:jcse { justify-content: space-evenly }
149
+
150
+ & > .xl\:noshrink { flex-shrink: 0 }
151
+ & > .xl\:nogrow { flex-grow: 0 }
152
+
153
+ @for $cols from 1 to 12 {
154
+ @for $col from 1 to $cols {
155
+ & > .xl\:c$(col)\/$(cols) {
156
+ flex-basis: calc($(col) / $(cols) * 100%);
157
+ max-width: calc($(col) / $(cols) * 100%);
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ }
@@ -0,0 +1,52 @@
1
+ /*----------------------------------------
2
+ flow.css / x
3
+ Flow — vertical flow of elements with margin-bottom space
4
+
5
+ Created by Andrey Shpigunov at 20.03.2025
6
+ All right reserved.
7
+ ----------------------------------------*/
8
+
9
+
10
+ /*
11
+ .flow
12
+ .flow.s[0-12] (m,l,xl) - vertical space
13
+ */
14
+
15
+
16
+ .flow {
17
+
18
+
19
+ & > * { margin: 0 }
20
+
21
+ @for $i from 0 to 12 {
22
+ &.s$(i) > * {
23
+ margin-bottom: var(--space-$(i));
24
+ }
25
+ }
26
+
27
+ @media(--medium){
28
+ @for $i from 0 to 12 {
29
+ &.m\:s$(i) > * {
30
+ margin-bottom: var(--space-$(i));
31
+ }
32
+ }
33
+ }
34
+
35
+ @media(--large){
36
+ @for $i from 0 to 12 {
37
+ &.l\:s$(i) > * {
38
+ margin-bottom: var(--space-$(i));
39
+ }
40
+ }
41
+ }
42
+
43
+ @media(--xlarge){
44
+ @for $i from 0 to 12 {
45
+ &.xl\:s$(i) > * {
46
+ margin-bottom: var(--space-$(i));
47
+ }
48
+ }
49
+ }
50
+
51
+ & > *:last-child { margin-bottom: 0 }
52
+ }
@@ -0,0 +1,138 @@
1
+ /*----------------------------------------
2
+ form.css / x
3
+ Form default styles
4
+
5
+ Created by Andrey Shpigunov at 20.03.2025
6
+ All right reserved.
7
+ ----------------------------------------*/
8
+
9
+
10
+ :root {
11
+ --form-width: 40rem;
12
+ --form-height-coeff: 2.5;
13
+ --form-side-padding: 1rem;
14
+
15
+ --form-font-size: var(--font-size);
16
+ --form-font-color: #000;
17
+ --form-font-color-readonly: #000;
18
+ --form-font-color-disabled: #666;
19
+ --form-font-color-placeholder: #ccc;
20
+
21
+ --form-border-width: 0.1rem;
22
+ --form-border-radius: 0.8rem;
23
+ --form-border-color: #d4d4d4;
24
+ --form-border-color-focused: #8cf;
25
+ --form-border-color-error: #f00;
26
+ --form-border-color-readonly: #ddd;
27
+ --form-border-color-disabled: #ddd;
28
+
29
+ --form-background-color: #fff;
30
+ --form-background-color-readonly: #fafafa;
31
+ --form-background-color-disabled: #f6f6f6;
32
+
33
+ /*
34
+ Additional variables and their default values:
35
+ --form-height: 4rem;
36
+ */
37
+ }
38
+
39
+ input[type="color"],
40
+ input[type="date"],
41
+ input[type="datetime"],
42
+ input[type="tel"],
43
+ input[type="email"],
44
+ input[type="month"],
45
+ input[type="number"],
46
+ input[type="password"],
47
+ input[type="search"],
48
+ input[type="text"],
49
+ input[type="time"],
50
+ input[type="url"],
51
+ input[type="week"],
52
+ input:not([type]),
53
+ textarea,
54
+ select {
55
+ position: relative;
56
+ width: 100%;
57
+ height: var(--form-height);
58
+ height: var(--form-height, calc(var(--form-font-size) * var(--form-height-coeff)));
59
+ margin: 0;
60
+ padding: 0 var(--form-side-padding);
61
+ font-size: var(--form-font-size);
62
+ color: var(--form-font-color);
63
+ outline: none;
64
+ border-width: var(--form-border-width);
65
+ border-style: solid;
66
+ border-color: var(--form-border-color);
67
+ border-radius: var(--form-border-radius);
68
+ background-color: var(--form-background-color);
69
+ appearance: none;
70
+
71
+ &[readonly],
72
+ &[readonly]:focus {
73
+ color: var(--form-font-color-readonly);
74
+ border-color: var(--form-border-color-readonly);
75
+ background-color: var(--form-background-color-readonly);
76
+ box-shadow: none;
77
+ }
78
+ &[disabled],
79
+ &[disabled]:focus {
80
+ color: var(--form-font-color-disabled);
81
+ border-color: var(--form-border-color-disabled);
82
+ background-color: var(--form-background-color-disabled);
83
+ cursor: not-allowed !important;
84
+ box-shadow: none;
85
+ }
86
+
87
+ &:focus {
88
+ border-color: var(--form-border-color-focused);
89
+ box-shadow: 0 0 0 1px var(--form-border-color-focused);
90
+ }
91
+ &.error,
92
+ &.error:focus,
93
+ &[pattern]:invalid,
94
+ &[pattern]:invalid:focus {
95
+ border-color: var(--form-border-color-error);
96
+ box-shadow: 0 0 0 1px var(--form-border-color-error);
97
+ }
98
+ }
99
+
100
+ select {
101
+ padding-right: calc(var(--form-side-padding) * 2.6);
102
+ background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#888" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevrons-up-down-icon lucide-chevrons-up-down"%3E%3Cpath d="m7 15 5 5 5-5"/%3E%3Cpath d="m7 9 5-5 5 5"/%3E%3C/svg%3E');
103
+ background-repeat: no-repeat;
104
+ background-position: right calc(var(--form-side-padding) - 4px) top 52%, 0 0;
105
+ background-size: 1.6rem;
106
+ }
107
+
108
+ ::placeholder {
109
+ color: var(--form-font-color-placeholder);
110
+ }
111
+
112
+ input[placeholder],
113
+ input::-moz-placeholder,
114
+ input:-moz-placeholder,
115
+ input:-ms-input-placeholder {
116
+ text-overflow: ellipsis;
117
+ }
118
+
119
+ input,
120
+ textarea,
121
+ select,
122
+ button {
123
+ max-width: var(--form-width);
124
+ font-family: inherit;
125
+ font-size: var(--font-size);
126
+ box-sizing: border-box;
127
+ box-shadow: none;
128
+ }
129
+
130
+ textarea {
131
+ height: auto;
132
+ padding-top: calc(var(--form-side-padding) / 2);
133
+ padding-bottom: calc(var(--form-side-padding) / 2);
134
+ }
135
+
136
+ ::-webkit-file-upload-button {
137
+ cursor:pointer;
138
+ }
@@ -0,0 +1,180 @@
1
+ /**
2
+ * @fileoverview Additional form utilities for inputs, checkboxes, selects, and contenteditable elements.
3
+ *
4
+ * Provides methods for setting values, managing checkboxes, attaching/removing event listeners,
5
+ * and manually dispatching events.
6
+ *
7
+ * Exported singleton: `form`
8
+ *
9
+ * Public API:
10
+ *
11
+ * - `form.setChecked(selector, checked)` – Set checked state of checkboxes/radios.
12
+ * - `form.setValue(selector, value)` – Set value of form elements or contenteditable.
13
+ * - `form.onUpdate(selector, callback)` – Attach listener for input/change events.
14
+ * - `form.offUpdate(selector)` – Remove previously added listeners (partial, due to anonymous functions).
15
+ * - `form.update(selector)` – Manually dispatch input/change event.
16
+ *
17
+ * Example usage:
18
+ *
19
+ * form.setValue('.name', 'John');
20
+ * form.setChecked('#agree', true);
21
+ * form.onUpdate('input', el => console.log(el.value));
22
+ *
23
+ * @author Andrey Shpigunov
24
+ * @version 0.2
25
+ * @since 2025-07-17
26
+ */
27
+
28
+ import { lib } from './lib';
29
+
30
+ class Form {
31
+ /**
32
+ * Creates a Form utility instance.
33
+ * Stores internal references to event listeners.
34
+ */
35
+ constructor() {
36
+ /**
37
+ * Stores event listener references to avoid duplicates.
38
+ *
39
+ * @readonly
40
+ * @type {{update: Set<HTMLElement>}}
41
+ */
42
+ this.listen = Object.freeze({
43
+ update: new Set(),
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Determines the appropriate event type for an element.
49
+ *
50
+ * @param {HTMLElement} el - Target element.
51
+ * @returns {string} 'input' or 'change' depending on the element type.
52
+ * @throws {Error} If the element is unsupported.
53
+ */
54
+ getEventType(el) {
55
+ if (el.isContentEditable) return 'input';
56
+
57
+ const tag = el.tagName.toLowerCase();
58
+ if (tag === 'input' || tag === 'textarea') return 'input';
59
+ if (tag === 'select') return 'change';
60
+
61
+ throw new Error(`Unsupported element <${tag}>`);
62
+ }
63
+
64
+ /**
65
+ * Sets the checked state of checkboxes or radios and dispatches 'input' event if changed.
66
+ *
67
+ * @param {string} selector - CSS selector for checkboxes or radios.
68
+ * @param {boolean} [checked=false] - Desired checked state.
69
+ */
70
+ setChecked(selector, checked = false) {
71
+ for (const el of lib.qsa(selector)) {
72
+ if (!el?.type || (el.type !== 'checkbox' && el.type !== 'radio')) {
73
+ console.error('setChecked: Not a checkbox/radio', el);
74
+ continue;
75
+ }
76
+
77
+ if (el.checked !== checked) {
78
+ el.checked = checked;
79
+ el.dispatchEvent(new Event('input', { bubbles: true }));
80
+ }
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Sets the value of inputs, textareas, selects, or contenteditable elements and dispatches event.
86
+ *
87
+ * @param {string} selector - CSS selector for elements.
88
+ * @param {string|boolean|number} value - Value to set.
89
+ * @throws {Error} If element type is unsupported.
90
+ */
91
+ setValue(selector, value) {
92
+ for (const el of lib.qsa(selector)) {
93
+ if (!el) {
94
+ console.error('setValue: Element not found', el);
95
+ continue;
96
+ }
97
+
98
+ if (el.isContentEditable) {
99
+ el.innerText = value;
100
+ } else {
101
+ const tag = el.tagName.toLowerCase();
102
+ const type = el.type;
103
+
104
+ if (tag === 'input') {
105
+ if (type === 'checkbox' || type === 'radio') {
106
+ el.checked = !!value;
107
+ } else {
108
+ el.value = value;
109
+ }
110
+ } else if (tag === 'textarea' || tag === 'select') {
111
+ el.value = value;
112
+ } else {
113
+ throw new Error(`setValue: Unsupported element <${tag}>`);
114
+ }
115
+ }
116
+
117
+ el.dispatchEvent(new Event(this.getEventType(el), { bubbles: true }));
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Attaches input/change listeners to elements, preventing duplicates.
123
+ *
124
+ * @param {string} selector - CSS selector for elements.
125
+ * @param {Function} callback - Function to call when input or change event fires.
126
+ */
127
+ onUpdate(selector, callback) {
128
+ for (const el of lib.qsa(selector)) {
129
+ if (!el) {
130
+ console.error('onUpdate: Element not found', el);
131
+ continue;
132
+ }
133
+
134
+ if (this.listen.update.has(el)) continue;
135
+
136
+ el.addEventListener(this.getEventType(el), () => callback(el));
137
+ this.listen.update.add(el);
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Removes references to update listeners added by `onUpdate`.
143
+ *
144
+ * Note: Actual event listeners are not removed because they were added as anonymous functions.
145
+ * This method only cleans the internal tracking set.
146
+ *
147
+ * @param {string} selector - CSS selector for elements.
148
+ */
149
+ offUpdate(selector) {
150
+ for (const el of lib.qsa(selector)) {
151
+ if (!el) continue;
152
+ if (!this.listen.update.has(el)) continue;
153
+
154
+ console.warn('offUpdate: Cannot fully remove listener because anonymous functions were used.');
155
+ this.listen.update.delete(el);
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Manually dispatches 'input' or 'change' events on the selected elements.
161
+ *
162
+ * @param {string} selector - CSS selector for elements.
163
+ */
164
+ update(selector) {
165
+ for (const el of lib.qsa(selector)) {
166
+ if (!el) {
167
+ console.error('update: Element not found', el);
168
+ continue;
169
+ }
170
+
171
+ el.dispatchEvent(new Event(this.getEventType(el), { bubbles: true }));
172
+ }
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Singleton export of the Form utility.
178
+ * @type {Form}
179
+ */
180
+ export const form = new Form();
@@ -0,0 +1,109 @@
1
+ /*----------------------------------------
2
+ grid.css / x
3
+ Grid prototype
4
+
5
+ Created by Andrey Shpigunov at 20.03.2025
6
+ All right reserved.
7
+ ----------------------------------------*/
8
+
9
+
10
+ /*
11
+ .grid
12
+ .grid.g[1-12] (m,l,xl) - columns limit in grid
13
+ .grid > .c[1-12] (m,l,xl) - column width
14
+ .grid > .c[1-12]/[1-12] (m,l,xl) - columns range for content
15
+ */
16
+
17
+
18
+ .grid {
19
+ display: grid;
20
+ width: 100%;
21
+ grid-template-columns: repeat(12, 1fr);
22
+ grid-auto-flow: dense;
23
+
24
+ @for $i from 1 to 12 {
25
+ &.g$(i) { grid-template-columns: repeat($(i), 1fr) }
26
+ & > .c$(i) { grid-column: span $(i) }
27
+
28
+ @for $m from 12 to $i {
29
+ & > .c$(i)\/$(m) {
30
+ grid-column: $(i) / calc($(m) + 1)
31
+ }
32
+ }
33
+ }
34
+
35
+ & .jss { justify-self: start }
36
+ & .jse { justify-self: end }
37
+ & .jsc { justify-self: center }
38
+ & .jsstr { justify-self: stretch }
39
+ & .ass { align-self: start }
40
+ & .ase { align-self: end }
41
+ & .asc { align-self: center }
42
+ & .asstr { align-self: stretch }
43
+
44
+ @media (--medium) {
45
+ @for $i from 1 to 12 {
46
+ &.m\:g$(i) { grid-template-columns: repeat($(i), 1fr) }
47
+ & > .m\:c$(i) { grid-column: span $(i) }
48
+
49
+ @for $m from 12 to $i {
50
+ & > .m\:c$(i)\/$(m) {
51
+ grid-column: $(i) / calc($(m) + 1)
52
+ }
53
+ }
54
+ }
55
+
56
+ & .m\:jss { justify-self: start }
57
+ & .m\:jse { justify-self: end }
58
+ & .m\:jsc { justify-self: center }
59
+ & .m\:jsstr { justify-self: stretch }
60
+ & .m\:ass { align-self: start }
61
+ & .m\:ase { align-self: end }
62
+ & .m\:asc { align-self: center }
63
+ & .m\:asstr { align-self: stretch }
64
+ }
65
+
66
+ @media (--large) {
67
+ @for $i from 1 to 12 {
68
+ &.l\:g$(i) { grid-template-columns: repeat($(i), 1fr) }
69
+ & > .l\:c$(i) { grid-column: span $(i) }
70
+
71
+ @for $m from 12 to $i {
72
+ & > .l\:c$(i)\/$(m) {
73
+ grid-column: $(i) / calc($(m) + 1)
74
+ }
75
+ }
76
+ }
77
+
78
+ & .l\:jss { justify-self: start }
79
+ & .l\:jse { justify-self: end }
80
+ & .l\:jsc { justify-self: center }
81
+ & .l\:jsstr { justify-self: stretch }
82
+ & .l\:ass { align-self: start }
83
+ & .l\:ase { align-self: end }
84
+ & .l\:asc { align-self: center }
85
+ & .l\:asstr { align-self: stretch }
86
+ }
87
+
88
+ @media (--xlarge) {
89
+ @for $i from 1 to 12 {
90
+ &.xl\:g$(i) { grid-template-columns: repeat($(i), 1fr) }
91
+ & > .xl\:c$(i) { grid-column: span $(i) }
92
+
93
+ @for $m from 12 to $i {
94
+ & > .xl\:c$(i)\/$(m) {
95
+ grid-column: $(i) / calc($(m) + 1)
96
+ }
97
+ }
98
+ }
99
+
100
+ & .xl\:jss { justify-self: start }
101
+ & .xl\:jse { justify-self: end }
102
+ & .xl\:jsc { justify-self: center }
103
+ & .xl\:jsstr { justify-self: stretch }
104
+ & .xl\:ass { align-self: start }
105
+ & .xl\:ase { align-self: end }
106
+ & .xl\:asc { align-self: center }
107
+ & .xl\:asstr { align-self: stretch }
108
+ }
109
+ }