@community-release/nx-ui 0.0.49 → 0.0.50

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/module.d.mts CHANGED
@@ -43,6 +43,7 @@ var defaultStyle = {
43
43
  "color-bg": "#fff",
44
44
  "color-bg-text": "#fff",
45
45
  "color-text-on-bg": "var(--color-text)",
46
+ "color-overlay": "var(--color-overlay)",
46
47
  "color-border": "#e8e8e8",
47
48
  "color-border-bolder": "#e0e0e0",
48
49
  // Text
@@ -59,6 +60,7 @@ var defaultStyle = {
59
60
  "font-icons": "FontAwesome",
60
61
  "font-mono": "Consolas, SF Mono",
61
62
  // Font weight
63
+ "font-weight-bold": "700",
62
64
  "font-weight-medium": "600",
63
65
  // Padding
64
66
  "space-extra-large": "100px",
package/dist/module.d.ts CHANGED
@@ -43,6 +43,7 @@ var defaultStyle = {
43
43
  "color-bg": "#fff",
44
44
  "color-bg-text": "#fff",
45
45
  "color-text-on-bg": "var(--color-text)",
46
+ "color-overlay": "var(--color-overlay)",
46
47
  "color-border": "#e8e8e8",
47
48
  "color-border-bolder": "#e0e0e0",
48
49
  // Text
@@ -59,6 +60,7 @@ var defaultStyle = {
59
60
  "font-icons": "FontAwesome",
60
61
  "font-mono": "Consolas, SF Mono",
61
62
  // Font weight
63
+ "font-weight-bold": "700",
62
64
  "font-weight-medium": "600",
63
65
  // Padding
64
66
  "space-extra-large": "100px",
package/dist/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "ui",
3
3
  "configKey": "ui",
4
- "version": "0.0.49"
4
+ "version": "0.0.50"
5
5
  }
package/dist/module.mjs CHANGED
@@ -43,6 +43,7 @@ const defaultStyle = {
43
43
  "color-bg": "#fff",
44
44
  "color-bg-text": "#fff",
45
45
  "color-text-on-bg": "var(--color-text)",
46
+ "color-overlay": "var(--color-overlay)",
46
47
  "color-border": "#e8e8e8",
47
48
  "color-border-bolder": "#e0e0e0",
48
49
  // Text
@@ -59,6 +60,7 @@ const defaultStyle = {
59
60
  "font-icons": "FontAwesome",
60
61
  "font-mono": "Consolas, SF Mono",
61
62
  // Font weight
63
+ "font-weight-bold": "700",
62
64
  "font-weight-medium": "600",
63
65
  // Padding
64
66
  "space-extra-large": "100px",
@@ -119,7 +119,6 @@
119
119
  padding: 0 0 0 30px;
120
120
 
121
121
  height: @com-input-height;
122
- line-height: @com-input-height;
123
122
  font-size: @com-text-default;
124
123
  font-weight: 500;
125
124
 
@@ -0,0 +1,426 @@
1
+ <template>
2
+ <div class="component-ui-file-input" :class="classes">
3
+
4
+ <!-- Input -->
5
+ <div class="block-input">
6
+ <ui-button class="btn-add" @click="openFileDialogue" color="surface" shape="square">
7
+ <template #prepend>
8
+ <i class="icon-file ic ic-paperclip" aria-hidden="true"></i>
9
+ </template>
10
+ <template #default>
11
+ {{ dictionary['select-file'] }}
12
+ </template>
13
+ </ui-button>
14
+
15
+ <div class="status">
16
+ <span class="status-text">{{ filesList.length ? '' : dictionary['no-files'] }}</span>
17
+ <ui-button v-if="filesList.length" @click="filesList = []" class="btn-delete" variant="flat">
18
+ <template #default>
19
+ {{ dictionary['delete-all'] }} ({{ filesList.length }})
20
+ </template>
21
+ </ui-button>
22
+ </div>
23
+ </div>
24
+
25
+ <!-- Filelist -->
26
+ <div class="block-filelist" ref="refDropZone">
27
+ <ul v-if="filesList.length" class="list">
28
+ <li v-for="item of filesList" :key="item.id" class="item">
29
+ <div class="preview" :class="{'tag-image': item.image}">
30
+ <div class="file" @click="item.image ? imagePreview = item.image : ''">
31
+ <img v-if="item.image" :src="item.image" alt="" />
32
+ <span v-else>{{ item.type }}</span>
33
+ </div>
34
+ </div>
35
+ <div class="details">
36
+ <div class="details-inner-wrapper">
37
+ <span class="name">{{ item.file.name }}</span>
38
+ <em class="size">{{ item.size }} KB</em>
39
+ </div>
40
+ </div>
41
+ <span class="delete">
42
+ <ui-button @click="deleteFile(item.id)" variant="flat" shape="round-square">
43
+ {{ dictionary['delete'] }}
44
+ </ui-button>
45
+ </span>
46
+ </li>
47
+ </ul>
48
+ <div class="drag-and-drop" @click="openFileDialogue">
49
+ {{ dictionary['drag-and-drop'] }}
50
+ </div>
51
+ </div>
52
+
53
+ <ui-file-input-preview v-model="imagePreview" />
54
+ </div>
55
+ </template>
56
+
57
+ <script setup>
58
+ // Imports
59
+ import { ref, watch, computed } from 'vue';
60
+ import { useFileDialog, useDropZone } from '@vueuse/core';
61
+ import UiFileInputPreview from './preview.vue';
62
+
63
+ // Data
64
+ const emit = defineEmits(['update:modelValue']);
65
+ const props = defineProps({
66
+ modelValue: {
67
+ required: true
68
+ },
69
+ dictionary: {
70
+ type: Object,
71
+ default() {
72
+ return {
73
+ "select-file": "Attach file(s)",
74
+ "no-files": "No files selected",
75
+ "delete": "Delete",
76
+ "delete-all": "Delete all file(s) ({n})",
77
+ "drag-and-drop": "Or drag and drop file to upload."
78
+ };
79
+ }
80
+ }
81
+ });
82
+
83
+ const filesList = ref([]);
84
+ watch(filesList, e => {
85
+ emit('update:modelValue', e);
86
+ });
87
+
88
+ const imagePreview = ref();
89
+
90
+ const allowedTypes = ['image/jpeg', 'image/gif', 'image/png', 'application/pdf', 'applicaion/pdf'];
91
+
92
+ // Handle button select (file input)
93
+ const { files, open: openFileDialogue, reset, onCancel, onChange: inputOnChange } = useFileDialog({
94
+ //accept: 'image/*', // Set to accept only image files
95
+ accept: allowedTypes, // Set to accept only image files
96
+ multiple: true,
97
+ });
98
+ inputOnChange(e => { filesList.value.push( ...createFileInputFiles(e) ); });
99
+
100
+ // Handle drag and drop zone
101
+ const refDropZone = ref();
102
+ const { isOverDropZone } = useDropZone(refDropZone, {
103
+ onDrop(e) {
104
+ filesList.value.push( ...createFileInputFiles(e) );
105
+ },
106
+ // specify the types of data to be received.
107
+ dataTypes: allowedTypes,
108
+ // control multi-file drop
109
+ multiple: true,
110
+ // whether to prevent default behavior for unhandled events
111
+ preventDefaultForUnhandled: false,
112
+ });
113
+
114
+ const classes = computed(() => {
115
+ const result = [];
116
+
117
+ if (isOverDropZone.value) result.push('tag-drag-over');
118
+ if (!filesList.value.length) result.push('tag-empty');
119
+
120
+ return result;
121
+ });
122
+
123
+ // Methods
124
+ function deleteFile(computedId) {
125
+ for (let i=0; i < filesList.value.length; i++) {
126
+ const item = filesList.value[i];
127
+ if (item.id === computedId) {
128
+ filesList.value.splice(i--, 1);
129
+ }
130
+ }
131
+ }
132
+
133
+ function getType(mime) {
134
+ const ar = mime.split('/');
135
+
136
+ if (ar.length) {
137
+ if (ar[0] === 'image')
138
+ return 'image';
139
+ else
140
+ return ar[1];
141
+ }
142
+
143
+ return 'file';
144
+ }
145
+
146
+ function createFileInputFiles(arFiles) {
147
+ const result = [];
148
+
149
+ for (let file of arFiles) {
150
+ const id = `${file.name}-${file.size}`;
151
+
152
+ // Skip, if file already exists in list
153
+ if (filesList.value.filter(v => v.id === id).length) continue;
154
+
155
+ const o ={
156
+ id,
157
+ file,
158
+ type: getType(file.type),
159
+ size: Math.round(file.size / 1024)
160
+ };
161
+
162
+ if (o.type == 'image')
163
+ o.image = URL.createObjectURL(file);
164
+
165
+ result.push(o);
166
+ }
167
+
168
+ return result;
169
+ }
170
+
171
+ // Hooks
172
+
173
+ </script>
174
+
175
+ <style lang="less">
176
+ .component-ui-file-input {
177
+ @com-color-primary-text: var(--ui-color-primary-text);
178
+ @com-color-surface: var(--ui-color-surface);
179
+ @com-color-border-bolder: var(--ui-color-border-bolder);
180
+ @com-color-border: var(--ui-color-border);
181
+ @com-color-header-text:var(--ui-color-header-text);
182
+
183
+ @com-border-radius-m: var(--ui-border-radius-default);
184
+
185
+ @com-space-default: var(--ui-space-default);
186
+ @com-space-mini: var(--ui-space-mini);
187
+ @com-space-small: var(--ui-space-small);
188
+
189
+ @com-text-large: var(--ui-text-large);
190
+ @com-text-default: var(--ui-text-default);
191
+ @com-text-small: var(--ui-text-small);
192
+
193
+ @com-font-weight-bold: var(--ui-font-weight-bold);
194
+
195
+
196
+ .block-input {
197
+ display: grid;
198
+ grid-template-columns: auto 1fr;
199
+ border-radius: @com-border-radius-m;
200
+ border: 1px solid @com-color-border;
201
+
202
+ .btn-add {
203
+ border-radius: @com-border-radius-m 0 0 @com-border-radius-m;
204
+
205
+ .ic {
206
+ font-size: @com-text-large;
207
+ }
208
+ }
209
+
210
+ .btn-delete {
211
+ border-radius: 0 @com-border-radius-m @com-border-radius-m 0;
212
+
213
+ .ic {
214
+ padding-left: @com-space-mini;
215
+ font-size: @com-text-default;
216
+ }
217
+ }
218
+
219
+
220
+ .status {
221
+ display: flex;
222
+ justify-content: end;
223
+ align-items: center;
224
+ }
225
+
226
+ .status-text {
227
+ padding-right: @com-space-default;
228
+ }
229
+ }
230
+
231
+ .block-filelist {
232
+ position: relative;
233
+ margin-top: @com-space-mini;
234
+ border-radius: @com-border-radius-m;
235
+ border: 1px dashed @com-color-border-bolder;
236
+
237
+ .item {
238
+ display: grid;
239
+ grid-template-columns: 80px 1fr 80px;
240
+
241
+ .preview {
242
+ padding: @com-space-mini;
243
+
244
+ .file {
245
+ overflow: hidden;
246
+ position: relative;
247
+ display: grid;
248
+ place-items: center;
249
+ height: 70px;
250
+
251
+ text-transform: uppercase;
252
+ font-size: @com-text-small;
253
+ font-weight: @com-font-weight-bold;
254
+ border-radius: @com-border-radius-m;
255
+ background-color: @com-color-surface;
256
+ border: 1px solid @com-color-surface;
257
+ }
258
+
259
+ img {
260
+ object-fit: contain;
261
+ }
262
+
263
+ img, span {
264
+ pointer-events: none;
265
+ }
266
+
267
+ &.tag-image {
268
+ cursor: pointer;
269
+ }
270
+ }
271
+
272
+ .details-inner-wrapper {
273
+ width: 100%;
274
+ }
275
+
276
+ .details {
277
+ display: flex;
278
+ justify-content: start;
279
+ align-items: center;
280
+ overflow: hidden;
281
+
282
+ .name {
283
+ .mix-text-overflow;
284
+
285
+ display: block;
286
+ font-weight: @com-font-weight-bold;
287
+ color: @com-color-header-text;
288
+ }
289
+
290
+ .size {
291
+ font-style: italic;
292
+ font-size: @com-text-small;
293
+ }
294
+ }
295
+
296
+ .delete {
297
+ display: flex;
298
+ justify-content: end;
299
+ align-items: center;
300
+
301
+ .component-ui-button {
302
+ font-size: @com-text-small;
303
+ height: 100%;
304
+ }
305
+ }
306
+ }
307
+ }
308
+
309
+ .drag-and-drop {
310
+ position: absolute;
311
+ inset: 0;
312
+
313
+ display: none;
314
+ place-items: center;
315
+ padding: @com-space-small;
316
+ text-align: center;
317
+ cursor: pointer;
318
+ }
319
+
320
+ // Empty
321
+ &.tag-empty {
322
+ .block-filelist {
323
+ min-height: 150px;
324
+ }
325
+
326
+ .drag-and-drop {
327
+ display: grid;
328
+ }
329
+ }
330
+
331
+ // Drag over
332
+ &.tag-drag-over {
333
+ .block-filelist {
334
+ border-color: @com-color-primary-text;
335
+ background: @com-color-surface;
336
+
337
+ .list {
338
+ opacity: 0.1;
339
+ }
340
+ }
341
+
342
+ .drag-and-drop {
343
+ display: grid;
344
+ }
345
+ }
346
+ }
347
+
348
+ @media (max-width: 640px) {
349
+ .component-ui-file-input {
350
+ @com-color-primary-text: var(--ui-color-primary-text);
351
+ @com-color-surface: var(--ui-color-surface);
352
+ @com-color-border-bolder: var(--ui-color-border-bolder);
353
+ @com-color-border: var(--ui-color-border);
354
+ @com-color-header-text:var(--ui-color-header-text);
355
+
356
+ @com-border-radius-m: var(--ui-border-radius-default);
357
+
358
+ @com-space-mini: var(--ui-space-mini);
359
+ @com-space-small: var(--ui-space-small);
360
+
361
+ @com-text-large: var(--ui-text-large);
362
+ @com-text-default: var(--ui-text-default);
363
+ @com-text-small: var(--ui-text-small);
364
+
365
+ @com-font-weight-bold: var(--ui-font-weight-bold);
366
+
367
+ .block-input {
368
+ grid-template-columns: 1fr;
369
+
370
+ .btn-add {
371
+ border-radius: @com-border-radius-m;
372
+ }
373
+
374
+ .status {
375
+ display: none;
376
+ }
377
+ }
378
+ }
379
+ }
380
+
381
+ @media (max-width: 520px) {
382
+ .component-ui-file-input {
383
+ @com-color-primary-text: var(--ui-color-primary-text);
384
+ @com-color-surface: var(--ui-color-surface);
385
+ @com-color-border-bolder: var(--ui-color-border-bolder);
386
+ @com-color-border: var(--ui-color-border);
387
+ @com-color-header-text:var(--ui-color-header-text);
388
+
389
+ @com-border-radius-m: var(--ui-border-radius-default);
390
+
391
+ @com-space-mini: var(--ui-space-mini);
392
+ @com-space-small: var(--ui-space-small);
393
+
394
+ @com-text-large: var(--ui-text-large);
395
+ @com-text-default: var(--ui-text-default);
396
+ @com-text-small: var(--ui-text-small);
397
+
398
+ @com-font-weight-bold: var(--ui-font-weight-bold);
399
+
400
+ .block-input {
401
+ .component-ui-button {
402
+ font-size: @com-text-small;
403
+ }
404
+ }
405
+
406
+ .block-filelist {
407
+ .item {
408
+ display: grid;
409
+ grid-template-columns: 70px 1fr 70px;
410
+
411
+ .preview {
412
+
413
+ }
414
+
415
+ .details {
416
+ font-size: @com-text-small;
417
+ }
418
+ }
419
+ }
420
+
421
+ .drag-and-drop {
422
+ font-size: @com-text-small;
423
+ }
424
+ }
425
+ }
426
+ </style>
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <div class="component-ui-file-input-preview" @click="close" :class="classes">
3
+ <img :src="modelValue" />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ // Imports
9
+ import { computed } from 'vue';
10
+
11
+ // Data
12
+ const emit = defineEmits(['update:modelValue']);
13
+ const props = defineProps({
14
+ modelValue: {
15
+ required: true
16
+ }
17
+ });
18
+
19
+ const classes = computed(() => {
20
+ const result = [];
21
+
22
+ if (props.modelValue) {
23
+ result.push('tag-active');
24
+ }
25
+
26
+ return result;
27
+ });
28
+
29
+ // Methods
30
+ function close() {
31
+ emit('update:modelValue', null);
32
+ }
33
+ </script>
34
+
35
+ <style lang="less">
36
+ .component-ui-file-input-preview {
37
+ // Colors
38
+ @com-color-overlay: var(--ui-color-overlay);
39
+
40
+ z-index: 5000;
41
+
42
+ display: none;
43
+ position: fixed;
44
+ inset: 0;
45
+ place-items: center;
46
+
47
+ background: @com-color-overlay;
48
+
49
+ &.tag-active {
50
+ display: grid;
51
+ }
52
+ }
53
+ </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@community-release/nx-ui",
3
- "version": "0.0.49",
3
+ "version": "0.0.50",
4
4
  "packageManager": "pnpm@10.14.0",
5
5
  "description": "nx-ui - Nuxt UI library",
6
6
  "repository": {
@@ -37,6 +37,8 @@
37
37
  "@vue/test-utils": "^2.4.6",
38
38
  "@vuedoc/md": "^4.0.0-beta8",
39
39
  "@vuedoc/parser": "^4.0.0-beta14",
40
+ "@vueuse/core": "^13.6.0",
41
+ "@vueuse/nuxt": "^13.6.0",
40
42
  "changelogen": "^0.5.5",
41
43
  "cross-env": "^7.0.3",
42
44
  "happy-dom": "^14.12.0",