@stackoverflow/stacks 3.0.0-beta.3 → 3.0.0-beta.30
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/controllers.d.ts +0 -2
- package/dist/css/stacks.css +14245 -15086
- package/dist/css/stacks.min.css +1 -1
- package/dist/js/stacks.js +0 -364
- package/dist/js/stacks.min.js +1 -1
- package/lib/atomic/backgrounds.less +67 -0
- package/lib/atomic/border-radius.less +38 -0
- package/lib/atomic/borders.less +73 -0
- package/lib/atomic/box-shadow.less +29 -0
- package/lib/atomic/box-sizing.less +3 -0
- package/lib/atomic/current-color.less +2 -0
- package/lib/atomic/cursors.less +8 -0
- package/lib/atomic/display.less +15 -0
- package/lib/atomic/flex.less +6 -34
- package/lib/atomic/floats.less +20 -0
- package/lib/atomic/gap.less +2 -0
- package/lib/atomic/grid.less +2 -0
- package/lib/atomic/height.less +22 -0
- package/lib/atomic/interactivity.less +45 -0
- package/lib/atomic/lists.less +29 -0
- package/lib/atomic/margin.less +48 -0
- package/lib/atomic/object-fit.less +9 -0
- package/lib/atomic/opacity.less +54 -0
- package/lib/atomic/outline.less +11 -0
- package/lib/atomic/overflow.less +17 -0
- package/lib/atomic/padding.less +12 -0
- package/lib/atomic/positioning.less +41 -0
- package/lib/atomic/sizing.less +51 -0
- package/lib/atomic/transitions.less +20 -0
- package/lib/atomic/truncation.less +58 -0
- package/lib/atomic/typography.less +71 -137
- package/lib/atomic/vertical-alignment.less +9 -0
- package/lib/atomic/visibility.less +18 -0
- package/lib/atomic/width.less +27 -0
- package/lib/atomic/z-index.less +12 -0
- package/lib/base/body.less +2 -4
- package/lib/base/configuration-static.less +3 -3
- package/lib/base/internal.less +3 -5
- package/lib/base/reset-normalize.less +3 -3
- package/lib/components/activity-indicator/activity-indicator.less +4 -20
- package/lib/components/anchor/anchor.less +28 -39
- package/lib/components/avatar/avatar.less +20 -19
- package/lib/components/badge/badge.less +227 -167
- package/lib/components/banner/banner.less +12 -11
- package/lib/components/bling/bling.less +47 -10
- package/lib/components/button/button.less +300 -380
- package/lib/components/checkbox_radio/checkbox_radio.less +195 -113
- package/lib/components/code-block/code-block.fixtures.ts +2 -2
- package/lib/components/code-block/code-block.less +2 -3
- package/lib/components/description/description.less +17 -2
- package/lib/components/empty-state/empty-state.less +17 -6
- package/lib/components/form-group/form-group.less +38 -0
- package/lib/components/input-fill/input-fill.less +3 -3
- package/lib/components/input-icon/input-icon.less +3 -3
- package/lib/components/input-message/input-message.less +1 -0
- package/lib/components/input_textarea/input_textarea.less +71 -58
- package/lib/components/label/label.less +12 -56
- package/lib/components/link/link.less +44 -98
- package/lib/components/loader/loader.less +88 -0
- package/lib/components/menu/menu.less +89 -19
- package/lib/components/modal/modal.less +10 -10
- package/lib/components/navigation/navigation.less +77 -42
- package/lib/components/notice/notice.less +90 -75
- package/lib/components/pagination/pagination.less +50 -42
- package/lib/components/popover/popover.less +9 -11
- package/lib/components/post-summary/post-summary.less +225 -385
- package/lib/components/prose/prose.less +49 -35
- package/lib/components/select/select.less +46 -41
- package/lib/components/sidebar-widget/sidebar-widget.less +26 -196
- package/lib/components/table/table.less +48 -22
- package/lib/components/tag/tag.less +25 -6
- package/lib/components/toast/toast.less +4 -2
- package/lib/components/toggle-switch/toggle-switch.less +15 -19
- package/lib/components/user-card/user-card.less +129 -92
- package/lib/components/vote/vote.less +134 -0
- package/lib/controllers.ts +0 -2
- package/lib/exports/color-sets.less +108 -81
- package/lib/exports/constants-helpers.less +9 -13
- package/lib/exports/constants-type.less +18 -36
- package/lib/exports/mixins.less +92 -272
- package/lib/index.ts +0 -4
- package/lib/stacks-static.less +44 -30
- package/lib/test/visual-test-utils.ts +42 -10
- package/lib/tsconfig.json +1 -1
- package/package.json +1 -1
- package/dist/components/expandable/expandable.d.ts +0 -17
- package/dist/components/uploader/uploader.d.ts +0 -48
- package/lib/atomic/border.less +0 -121
- package/lib/atomic/misc.less +0 -374
- package/lib/atomic/spacing.less +0 -98
- package/lib/atomic/width-height.less +0 -194
- package/lib/components/block-link/block-link.less +0 -82
- package/lib/components/breadcrumbs/breadcrumbs.less +0 -41
- package/lib/components/button-group/button-group.less +0 -81
- package/lib/components/card/card.less +0 -37
- package/lib/components/check-control/check-control.less +0 -17
- package/lib/components/check-group/check-group.less +0 -19
- package/lib/components/expandable/expandable.less +0 -119
- package/lib/components/expandable/expandable.ts +0 -238
- package/lib/components/link-preview/link-preview.less +0 -148
- package/lib/components/page-title/page-title.less +0 -51
- package/lib/components/progress-bar/progress-bar.less +0 -292
- package/lib/components/skeleton/skeleton.less +0 -73
- package/lib/components/spinner/spinner.less +0 -103
- package/lib/components/topbar/topbar.less +0 -553
- package/lib/components/uploader/uploader.less +0 -205
- package/lib/components/uploader/uploader.ts +0 -207
- package/lib/exports/spacing-mixins.less +0 -67
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
.s-uploader {
|
|
2
|
-
// COMPONENT-SPECIFIC CONSTANTS
|
|
3
|
-
--_up-bg-b-image: url("data:image/svg+xml;,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='5' ry='5' stroke='%23000000' stroke-width='8' stroke-dasharray='7%2c 22' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e"); // Keeping this a custom property to save a few bytes
|
|
4
|
-
// COMPONENT-SPECIFIC CUSTOM PROPERTIES
|
|
5
|
-
--_up-bg: var(--black-100);
|
|
6
|
-
--_up-bg-focus: var(--black-150);
|
|
7
|
-
--_up-bg-bc: var(--black-250);
|
|
8
|
-
--_up-focus-ring-color: var(--focus-ring);
|
|
9
|
-
|
|
10
|
-
// CONTEXTUAL STYLES
|
|
11
|
-
.highcontrast-mode({
|
|
12
|
-
--_up-bg-bc-hc: var(--black-400);
|
|
13
|
-
&.has-error {
|
|
14
|
-
--_up-bg-bc-hc-state: var(--red-500);
|
|
15
|
-
}
|
|
16
|
-
&.has-success {
|
|
17
|
-
--_up-bg-bc-hc-state: var(--green-400);
|
|
18
|
-
}
|
|
19
|
-
&.has-warning {
|
|
20
|
-
--_up-bg-bc-hc-state: var(--yellow-500);
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// STATES
|
|
25
|
-
&.has-error,
|
|
26
|
-
&.has-success,
|
|
27
|
-
&.has-warning {
|
|
28
|
-
.s-link {
|
|
29
|
-
color: var(--_up-link-fc);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
&.has-error {
|
|
34
|
-
--_up-bg: var(--red-100);
|
|
35
|
-
--_up-bg-focus: var(--red-200);
|
|
36
|
-
--_up-bg-bc: var(--red-300);
|
|
37
|
-
--_up-focus-ring-color: var(--focus-ring-error);
|
|
38
|
-
--_up-link-fc: var(--red-500);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
&.has-success {
|
|
42
|
-
--_up-bg: var(--green-100);
|
|
43
|
-
--_up-bg-focus: var(--green-200);
|
|
44
|
-
--_up-bg-bc: var(--green-300);
|
|
45
|
-
--_up-focus-ring-color: var(--focus-ring-success);
|
|
46
|
-
--_up-link-fc: var(--green-400);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
&.has-warning {
|
|
50
|
-
--_up-bg: var(--yellow-100);
|
|
51
|
-
--_up-bg-focus: var(--yellow-200);
|
|
52
|
-
--_up-bg-bc: var(--yellow-300);
|
|
53
|
-
--_up-focus-ring-color: var(--focus-ring-warning);
|
|
54
|
-
--_up-link-fc: var(--yellow-500);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
&.is-active {
|
|
58
|
-
--_up-bg: var(--black-150);
|
|
59
|
-
--_up-bg-bc: var(--black-300);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
&.is-disabled {
|
|
63
|
-
opacity: var(--_o-disabled-static);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// CHILD ELEMENTS
|
|
67
|
-
& &--container {
|
|
68
|
-
&:before { // Add the dashed border as an SVG background mask
|
|
69
|
-
-webkit-mask-image: var(--_up-bg-b-image);
|
|
70
|
-
mask-image: var(--_up-bg-b-image);
|
|
71
|
-
background-color: var(--_up-bg-bc-hc-state, var(--_up-bg-bc-hc, var(--_up-bg-bc)));
|
|
72
|
-
border-radius: var(--br-md);
|
|
73
|
-
content: '';
|
|
74
|
-
display: block;
|
|
75
|
-
inset: 0;
|
|
76
|
-
position: absolute;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
align-items: center;
|
|
80
|
-
background-color: var(--_up-bg);
|
|
81
|
-
border-radius: var(--br-md);
|
|
82
|
-
display: flex;
|
|
83
|
-
flex-direction: column;
|
|
84
|
-
justify-content: center;
|
|
85
|
-
min-height: var(--su-static128);
|
|
86
|
-
padding: var(--su8) var(--su16);
|
|
87
|
-
position: relative;
|
|
88
|
-
text-align: center;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
& &--input {
|
|
92
|
-
&:focus:focus-visible + .s-uploader--container {
|
|
93
|
-
.focus-styles();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
&:focus:focus-visible + .s-uploader--container,
|
|
97
|
-
.s-uploader--container.focus {
|
|
98
|
-
background-color: var(--_up-bg-focus);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
cursor: pointer;
|
|
102
|
-
height: 100%;
|
|
103
|
-
inset: 0;
|
|
104
|
-
opacity: 0;
|
|
105
|
-
position: absolute;
|
|
106
|
-
width: 100%;
|
|
107
|
-
z-index: var(--zi-selected);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
& &--preview {
|
|
111
|
-
max-width: 100%;
|
|
112
|
-
pointer-events: none;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
& &--preview-thumbnail {
|
|
116
|
-
.highcontrast-mode({
|
|
117
|
-
border: var(--su-static1) solid var(--black);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
&:is(img) {
|
|
121
|
-
object-fit: scale-down;
|
|
122
|
-
object-position: center;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
&:not(img) {
|
|
126
|
-
padding: var(--su16);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
background-color: var(--white);
|
|
130
|
-
border-radius: var(--br-md);
|
|
131
|
-
box-shadow: var(--bs-md);
|
|
132
|
-
max-height: var(--su-static128);
|
|
133
|
-
max-width: 100%;
|
|
134
|
-
overflow: hidden;
|
|
135
|
-
text-overflow: ellipsis;
|
|
136
|
-
white-space: nowrap;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
& &--previews {
|
|
140
|
-
&.has-multiple {
|
|
141
|
-
display: block;
|
|
142
|
-
height: auto;
|
|
143
|
-
padding: var(--su8) var(--su2);
|
|
144
|
-
width: 100%;
|
|
145
|
-
|
|
146
|
-
.s-uploader--preview {
|
|
147
|
-
&:after {
|
|
148
|
-
content: attr(data-filename);
|
|
149
|
-
display: block;
|
|
150
|
-
margin-left: var(--su12);
|
|
151
|
-
max-width: 100%;
|
|
152
|
-
overflow: hidden;
|
|
153
|
-
text-overflow: ellipsis;
|
|
154
|
-
white-space: nowrap;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
align-items: center;
|
|
158
|
-
display: flex;
|
|
159
|
-
padding: var(--su6) 0;
|
|
160
|
-
width: 100%;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.s-uploader--preview-thumbnail {
|
|
164
|
-
&:is(img) {
|
|
165
|
-
object-fit: cover;
|
|
166
|
-
}
|
|
167
|
-
&:not(img) {
|
|
168
|
-
background-image: url("data:image/svg+xml;,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' fill='%23535A60' width='18' height='18' viewBox='0 0 18 18'%3E%3Cpath d='M3 3a2 2 0 012-2h6l4 4v10a2 2 0 01-2 2H5a2 2 0 01-2-2V3zm7-1.5V6h4.5L10 1.5z'%3E%3C/path%3E%3C/svg%3E");
|
|
169
|
-
background-position: center;
|
|
170
|
-
background-repeat: no-repeat;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
color: transparent;
|
|
174
|
-
height: var(--su-static32);
|
|
175
|
-
flex-shrink: 0;
|
|
176
|
-
width: var(--su-static32);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
max-width: 100%;
|
|
181
|
-
text-align: left;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
& &--previews-heading {
|
|
185
|
-
color: var(--black-600);
|
|
186
|
-
font-size: var(--fs-body2);
|
|
187
|
-
font-weight: 700;
|
|
188
|
-
padding-bottom: var(--su8);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
& &--reset {
|
|
192
|
-
position: absolute;
|
|
193
|
-
right: var(--su8);
|
|
194
|
-
top: var(--su8);
|
|
195
|
-
z-index: var(--zi-active);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// This is for safari shadow DOM
|
|
199
|
-
// see https://github.com/StackExchange/Stacks/pull/690#issuecomment-861028193
|
|
200
|
-
input[type="file"]::file-selector-button {
|
|
201
|
-
cursor: pointer;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
position: relative;
|
|
205
|
-
}
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import * as Stacks from "../../stacks";
|
|
2
|
-
|
|
3
|
-
interface FilePreview {
|
|
4
|
-
data?: string | ArrayBuffer;
|
|
5
|
-
name: string;
|
|
6
|
-
type: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class UploaderController extends Stacks.StacksController {
|
|
10
|
-
static targets = ["input", "previews", "uploader"];
|
|
11
|
-
|
|
12
|
-
declare readonly inputTarget: HTMLInputElement;
|
|
13
|
-
declare readonly previewsTarget: HTMLElement;
|
|
14
|
-
declare readonly uploaderTarget: HTMLElement;
|
|
15
|
-
|
|
16
|
-
private boundDragEnter!: () => void;
|
|
17
|
-
private boundDragLeave!: () => void;
|
|
18
|
-
|
|
19
|
-
private static readonly FILE_DISPLAY_LIMIT = 10;
|
|
20
|
-
private static readonly MAX_FILE_SIZE = 1024 * 1024 * 10; // 10 MB
|
|
21
|
-
|
|
22
|
-
connect() {
|
|
23
|
-
super.connect();
|
|
24
|
-
this.boundDragEnter = this.handleUploaderActive.bind(this, true);
|
|
25
|
-
this.boundDragLeave = this.handleUploaderActive.bind(this, false);
|
|
26
|
-
|
|
27
|
-
this.inputTarget.addEventListener("dragenter", this.boundDragEnter);
|
|
28
|
-
this.inputTarget.addEventListener("dragleave", this.boundDragLeave);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
disconnect() {
|
|
32
|
-
this.inputTarget.removeEventListener("dragenter", this.boundDragEnter);
|
|
33
|
-
this.inputTarget.removeEventListener("dragleave", this.boundDragLeave);
|
|
34
|
-
super.disconnect();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Handles rendering the file preview state on input change
|
|
39
|
-
*/
|
|
40
|
-
handleInput() {
|
|
41
|
-
this.previewsTarget.innerHTML = "";
|
|
42
|
-
|
|
43
|
-
if (!this.inputTarget.files) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const count = this.inputTarget.files.length;
|
|
48
|
-
this.getDataURLs(
|
|
49
|
-
this.inputTarget.files,
|
|
50
|
-
UploaderController.FILE_DISPLAY_LIMIT
|
|
51
|
-
)
|
|
52
|
-
.then((res: FilePreview[]) => {
|
|
53
|
-
this.handleVisible(true);
|
|
54
|
-
const hasMultipleFiles = res.length > 1;
|
|
55
|
-
|
|
56
|
-
if (hasMultipleFiles) {
|
|
57
|
-
const headingElement = document.createElement("div");
|
|
58
|
-
headingElement.classList.add(
|
|
59
|
-
"s-uploader--previews-heading"
|
|
60
|
-
);
|
|
61
|
-
headingElement.innerText =
|
|
62
|
-
res.length < count
|
|
63
|
-
? `Showing ${res.length} of ${count} files`
|
|
64
|
-
: `${count} items`;
|
|
65
|
-
this.previewsTarget.appendChild(headingElement);
|
|
66
|
-
this.previewsTarget.classList.add("has-multiple");
|
|
67
|
-
} else {
|
|
68
|
-
this.previewsTarget.classList.remove("has-multiple");
|
|
69
|
-
}
|
|
70
|
-
res.forEach((file) => this.addFilePreview(file));
|
|
71
|
-
this.handleUploaderActive(true);
|
|
72
|
-
})
|
|
73
|
-
// TODO consider rendering an error message
|
|
74
|
-
.catch(() => null);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Resets the Uploader to initial state
|
|
79
|
-
*/
|
|
80
|
-
reset() {
|
|
81
|
-
this.inputTarget.value = "";
|
|
82
|
-
this.previewsTarget.innerHTML = "";
|
|
83
|
-
this.handleVisible(false);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Set hide/show and disabled state on elements depending on preview state
|
|
88
|
-
* @param {boolean} shouldPreview - Uploader is entering a preview state
|
|
89
|
-
*/
|
|
90
|
-
private handleVisible(shouldPreview: boolean) {
|
|
91
|
-
const { scope } = this.targets;
|
|
92
|
-
const hideElements = scope.findAllElements(
|
|
93
|
-
"[data-s-uploader-hide-on-input]"
|
|
94
|
-
);
|
|
95
|
-
const showElements = scope.findAllElements(
|
|
96
|
-
"[data-s-uploader-show-on-input]"
|
|
97
|
-
);
|
|
98
|
-
const enableElements = scope.findAllElements(
|
|
99
|
-
"[data-s-uploader-enable-on-input]"
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
if (shouldPreview) {
|
|
103
|
-
hideElements.forEach((el) => {
|
|
104
|
-
el.classList.add("d-none");
|
|
105
|
-
});
|
|
106
|
-
showElements.forEach((el) => {
|
|
107
|
-
el.classList.remove("d-none");
|
|
108
|
-
});
|
|
109
|
-
enableElements.forEach((el) => {
|
|
110
|
-
el.removeAttribute("disabled");
|
|
111
|
-
});
|
|
112
|
-
} else {
|
|
113
|
-
hideElements.forEach((el) => {
|
|
114
|
-
el.classList.remove("d-none");
|
|
115
|
-
});
|
|
116
|
-
showElements.forEach((el) => {
|
|
117
|
-
el.classList.add("d-none");
|
|
118
|
-
});
|
|
119
|
-
enableElements.forEach((el) => {
|
|
120
|
-
el.setAttribute("disabled", "true");
|
|
121
|
-
});
|
|
122
|
-
this.handleUploaderActive(false);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Adds a DOM element to preview a selected file
|
|
128
|
-
* @param {FilePreview} file
|
|
129
|
-
*/
|
|
130
|
-
private addFilePreview(file: FilePreview) {
|
|
131
|
-
if (!file) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const previewElement = document.createElement("div");
|
|
136
|
-
let thumbElement;
|
|
137
|
-
|
|
138
|
-
if (file.type.match("image/*") && file.data) {
|
|
139
|
-
thumbElement = document.createElement("img");
|
|
140
|
-
|
|
141
|
-
thumbElement.src = file.data.toString();
|
|
142
|
-
thumbElement.alt = file.name;
|
|
143
|
-
} else {
|
|
144
|
-
thumbElement = document.createElement("div");
|
|
145
|
-
thumbElement.innerText = file.name;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
thumbElement.classList.add("s-uploader--preview-thumbnail");
|
|
149
|
-
previewElement.appendChild(thumbElement);
|
|
150
|
-
previewElement.classList.add("s-uploader--preview");
|
|
151
|
-
previewElement.setAttribute("data-filename", file.name);
|
|
152
|
-
this.previewsTarget.appendChild(previewElement);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Toggles display and disabled state for select elements on valid input
|
|
157
|
-
* @param {boolean} active - Uploader is in active state (typically on 'dragenter')
|
|
158
|
-
*/
|
|
159
|
-
private handleUploaderActive(active: boolean) {
|
|
160
|
-
this.uploaderTarget.classList.toggle("is-active", active);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Converts the file data into a data URL
|
|
165
|
-
* @param {File} file
|
|
166
|
-
* @returns an object containing a FilePreview object
|
|
167
|
-
*/
|
|
168
|
-
private fileToDataURL(file: File): Promise<FilePreview> {
|
|
169
|
-
const reader = new FileReader();
|
|
170
|
-
const { name, size, type } = file;
|
|
171
|
-
|
|
172
|
-
if (
|
|
173
|
-
size < UploaderController.MAX_FILE_SIZE &&
|
|
174
|
-
type.indexOf("image") > -1
|
|
175
|
-
) {
|
|
176
|
-
return new Promise((resolve, reject) => {
|
|
177
|
-
reader.onload = (evt) => {
|
|
178
|
-
const res = evt?.target?.result;
|
|
179
|
-
if (res) {
|
|
180
|
-
resolve({ data: res, name, type });
|
|
181
|
-
} else {
|
|
182
|
-
reject();
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
reader.readAsDataURL(file);
|
|
186
|
-
});
|
|
187
|
-
} else {
|
|
188
|
-
return Promise.resolve({ name, type });
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Gets an array of FilePreviews from a FileList
|
|
194
|
-
* @param {FileList|[]} files
|
|
195
|
-
* @returns an array of FilePreview objects from a FileList
|
|
196
|
-
*/
|
|
197
|
-
private getDataURLs(
|
|
198
|
-
files: FileList,
|
|
199
|
-
limit: number
|
|
200
|
-
): Promise<FilePreview[]> {
|
|
201
|
-
const promises = Array.from(files)
|
|
202
|
-
.slice(0, Math.min(limit, files.length))
|
|
203
|
-
.map((f) => this.fileToDataURL(f));
|
|
204
|
-
|
|
205
|
-
return Promise.all(promises);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate base and responsive atomic spacing classes.
|
|
3
|
-
*
|
|
4
|
-
* Usage example:
|
|
5
|
-
* .generate-spacing('.m', margin, true);
|
|
6
|
-
* .generate-spacing('.ml', margin-left, true, percent);
|
|
7
|
-
* .generate-spacing('.mx'; margin-left, margin-right; true);
|
|
8
|
-
* .generate-spacing('.pr', padding-right);
|
|
9
|
-
*
|
|
10
|
-
* @prefix - (required) What prefix to generate (e.g. `.m`, `.pr`, etc).
|
|
11
|
-
* @properties - (required) What CSS properties to generate (e.g. `margin`, `margin-right, margin-left`, etc).
|
|
12
|
-
* @includeNegative: bool - Boolean to include generation of negative value classes.
|
|
13
|
-
* @type: px | percent - What set of value to generate.
|
|
14
|
-
*/
|
|
15
|
-
.generate-spacing(@prefix, @properties, @includeNegative: false, @type: px) {
|
|
16
|
-
& when (@type = px) {
|
|
17
|
-
#stacks-internals #build-classes(
|
|
18
|
-
responsive,
|
|
19
|
-
@prefix,
|
|
20
|
-
{ .template(@value) {
|
|
21
|
-
each(@properties, #(@prop) {
|
|
22
|
-
@{prop}: var(~"--su@{value}") !important;
|
|
23
|
-
})
|
|
24
|
-
} },
|
|
25
|
-
0 1 2 4 6 8 12 16 24 32 48 64 96 128
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
& when (@includeNegative = true) {
|
|
29
|
-
#stacks-internals #build-classes(
|
|
30
|
-
responsive,
|
|
31
|
-
~"@{prefix}n",
|
|
32
|
-
{ .template(@value) {
|
|
33
|
-
each(@properties, #(@prop) {
|
|
34
|
-
@{prop}: calc(var(~"--su@{value}") * -1) !important;
|
|
35
|
-
})
|
|
36
|
-
} },
|
|
37
|
-
1 2 4 6 8 12 16 24 32 48 64 96 128
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
& when (@type = percent) {
|
|
43
|
-
#stacks-internals #build-classes(
|
|
44
|
-
responsive,
|
|
45
|
-
@prefix,
|
|
46
|
-
{ .template(@value) {
|
|
47
|
-
each(@properties, #(@prop) {
|
|
48
|
-
@{prop}: @value !important;
|
|
49
|
-
})
|
|
50
|
-
} },
|
|
51
|
-
50% 100%
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
& when (@includeNegative = true) {
|
|
55
|
-
#stacks-internals #build-classes(
|
|
56
|
-
responsive,
|
|
57
|
-
~"@{prefix}n",
|
|
58
|
-
{ .template(@value) {
|
|
59
|
-
each(@properties, #(@prop) {
|
|
60
|
-
@{prop}: -@value !important;
|
|
61
|
-
})
|
|
62
|
-
} },
|
|
63
|
-
50% 100%
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|