@bagelink/vue 0.0.211 → 0.0.216

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.
@@ -1,51 +1,53 @@
1
1
  <template>
2
- <div :class="{ open: isOpen, closed: !isOpen }">
3
- <slot name="top" />
4
- <div
5
- class="nav-expend"
6
- @click="isOpen = !isOpen"
7
- @keypress.enter="isOpen = !isOpen"
8
- role="button"
9
- aria-label="Toggle Navigation"
10
- tabindex="0"
11
- >
12
- <div class="icon-font top-arrow">chevron_right</div>
13
- </div>
14
-
15
- <div class="full-nav">
16
- <div class="nav-scroll">
17
- <div class="nav-links-wrapper">
18
- <RouterLink
19
- v-for="link in links?.()"
20
- class="nav-button"
21
- :to="link.to"
22
- :key="link.label"
23
- >
24
- <div class="icon-font">
25
- {{ link.materialIcon }}
26
- </div>
27
- <div class="tooltip">
28
- {{ link.localized ? link.localized : link.label }}
29
- </div>
30
- </RouterLink>
31
- </div>
32
- </div>
33
-
34
- <div class="bot-buttons-wrapper">
35
- <slot name="floor" />
36
- </div>
37
- </div>
38
- </div>
2
+ <div :class="{ open: isOpen, closed: !isOpen }">
3
+ <slot name="top" />
4
+ <div
5
+ class="nav-expend"
6
+ @click="isOpen = !isOpen"
7
+ @keypress.enter="isOpen = !isOpen"
8
+ role="button"
9
+ aria-label="Toggle Navigation"
10
+ tabindex="0"
11
+ >
12
+ <div class="icon-font top-arrow">
13
+ chevron_right
14
+ </div>
15
+ </div>
16
+
17
+ <div class="full-nav">
18
+ <div class="nav-scroll">
19
+ <div class="nav-links-wrapper">
20
+ <RouterLink
21
+ v-for="link in links?.()"
22
+ class="nav-button"
23
+ :to="link.to"
24
+ :key="link.label"
25
+ >
26
+ <div class="icon-font">
27
+ {{ link.materialIcon }}
28
+ </div>
29
+ <div class="tooltip">
30
+ {{ link.localized ? link.localized : link.label }}
31
+ </div>
32
+ </RouterLink>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="bot-buttons-wrapper">
37
+ <slot name="floor" />
38
+ </div>
39
+ </div>
40
+ </div>
39
41
  </template>
40
42
 
41
43
  <script lang="ts" setup>
42
44
  // import LangText from "../translation/LangText.vue"s
43
- import type { MaterialIcons } from "@bagelink/vue";
45
+ import type { MaterialIcons } from '@bagelink/vue';
44
46
 
45
47
  const isOpen = $ref(true);
46
48
 
47
49
  withDefaults(
48
- defineProps<{
50
+ defineProps<{
49
51
  links?: () => {
50
52
  label: string;
51
53
  to: string;
@@ -56,15 +58,15 @@ withDefaults(
56
58
  homeLabel?: string;
57
59
  homeTo?: string;
58
60
  }>(),
59
- {
60
- homeIcon: "home",
61
- homeLabel: "Home",
62
- homeTo: "/",
63
- }
61
+ {
62
+ homeIcon: 'home',
63
+ homeLabel: 'Home',
64
+ homeTo: '/',
65
+ },
64
66
  );
65
67
  </script>
66
68
 
67
- <style>
69
+ <style scoped>
68
70
  [dir="rtl"] .top-arrow {
69
71
  transform: rotate(180deg);
70
72
  }
@@ -2,6 +2,7 @@
2
2
  <component
3
3
  :required="field.required"
4
4
  v-bind="bindAttrs(field?.attrs||{}, props.modelValue[field.id || ''], props.modelValue,)"
5
+ v-if="vIf"
5
6
  :is="field.$el || 'div'"
6
7
  :label="field.label"
7
8
  :id="field.id"
@@ -26,5 +27,13 @@ const props = defineProps<{
26
27
  field: Field
27
28
  }>();
28
29
 
30
+ const vIf = $computed(() => {
31
+ if (props.field['v-if'] === undefined) return true;
32
+ if (typeof props.field['v-if'] === 'boolean') return props.field['v-if'];
33
+ if (typeof props.field['v-if'] === 'string') return !!props.modelValue[props.field['v-if']];
34
+ if (typeof props.field['v-if'] === 'function') return props.field['v-if']!(props.modelValue[props.field.id || ''], props.modelValue);
35
+ return true;
36
+ });
37
+
29
38
  const emits = defineEmits(['update:modelValue']);
30
39
  </script>
@@ -1,11 +1,11 @@
1
1
  <template>
2
- <form @submit.prevent="runSubmit">
2
+ <form ref="form" @submit.prevent="runSubmit">
3
3
  <BglField
4
4
  v-for="(field, i) in schema" :key="field.id || `${i }p`" :field="field" :modelValue="data"
5
- @update:modelValue="($event: any) => field.id ? data[field.id] = $event : ''"
5
+ @update:modelValue="($event)=>updateModelValue($event, field?.id || '')"
6
6
  />
7
7
  <Btn
8
- class="del-top" v-if="modelValue?.id && onDelete" @click="runDelete" value="Delete" flat icon="delete"
8
+ class="del-top" v-if="data?.id && onDelete" @click="runDelete" value="Delete" flat icon="delete"
9
9
  color="red" thin
10
10
  />
11
11
  <Btn v-if="!$slots.submit && onSubmit" value="Submit" type="submit" thin />
@@ -16,39 +16,41 @@
16
16
  </template>
17
17
 
18
18
  <script lang="ts" setup>
19
- import { watch } from 'vue';
20
19
  import { Btn, useModal, BglField } from '@bagelink/vue';
21
20
  import { type BglFormSchemaT } from '@bagelink/vue';
22
21
 
23
22
  const { showModal } = useModal();
24
23
 
24
+ const data = defineModel<Record<string, any>>('modelValue', { default: {} });
25
+
25
26
  const props = defineProps<{
26
- modelValue?: any;
27
27
  schema: BglFormSchemaT;
28
28
  onDelete?: ((id: string) => void);
29
29
  onSubmit?: ((data: any) => void);
30
30
  }>();
31
31
 
32
- const emits = defineEmits(['update:modelValue', 'submit']);
33
- const handleEmit = (val: any) => emits('update:modelValue', val);
34
- let data = $ref({
35
- ...props.modelValue,
36
- });
32
+ const form = $ref<HTMLFormElement>();
33
+
34
+ const validateForm = () => form?.reportValidity?.();
35
+
36
+ const updateModelValue = (val: any, fieldID: string) => {
37
+ if (!fieldID || !data.value) return;
38
+ data.value[fieldID] = val;
39
+ };
40
+
41
+ defineExpose({ validateForm });
42
+
43
+ const clearForm = () => Object.assign(data, {});
44
+ const emits = defineEmits(['submit']);
45
+
37
46
  const runSubmit = () => {
47
+ validateForm();
38
48
  emits('submit', data);
39
49
  clearForm();
40
50
  };
41
51
 
42
- const clearForm = () => data = {};
43
-
44
52
  const i18nT = (val: string) => val;
45
53
 
46
- watch(
47
- () => data,
48
- () => handleEmit,
49
- { immediate: true },
50
- );
51
-
52
54
  const runDelete = () => {
53
55
  showModal(
54
56
  {
@@ -58,7 +60,7 @@ const runDelete = () => {
58
60
  {
59
61
  value: 'Confirm',
60
62
  color: 'red',
61
- onClick: () => props.onDelete?.(data.id),
63
+ onClick: () => props.onDelete?.(data.value.id),
62
64
  },
63
65
  { value: 'Cancel', color: 'gray' },
64
66
  ],
@@ -1,143 +1,101 @@
1
1
  <template>
2
- <div
3
- class="bagel-input checkbox"
4
- :title="field.description"
5
- :class="{ small: small, 'no-edit': !editMode }"
6
- >
7
- <label :for="field.id">
8
- {{ field.label }}
9
- </label>
10
- <label class="switch">
11
- <input
12
- :id="field.id"
13
- type="checkbox"
14
- v-model="inputVal"
15
- :class="{ 'no-edit': !editMode }"
16
- />
17
- <span class="slider round" />
18
- </label>
19
- </div>
2
+ <div
3
+ class="bagel-input bgl-checkbox"
4
+ :title="title"
5
+ :class="{ small: small, 'no-edit': !editMode }"
6
+ >
7
+ <input
8
+ :id="id"
9
+ type="checkbox"
10
+ v-model="inputVal"
11
+ :class="{ 'no-edit': !editMode }"
12
+ >
13
+ <svg
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ height="24" viewBox="0 -960 960 960"
16
+ width="24"
17
+ >
18
+ <path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"/></svg>
19
+ <label :for="id">
20
+ {{ label }}
21
+ </label>
22
+ </div>
20
23
  </template>
21
24
 
22
25
  <script setup lang="ts">
23
- import { watch, ref, onMounted } from "vue";
24
- import { BagelField } from "@bagelink/vue";
25
-
26
- const emits = defineEmits(["update:modelValue"]);
27
- const props = withDefaults(
28
- defineProps<{
29
- field: BagelField;
30
- modelValue: any;
26
+ withDefaults(
27
+ defineProps<{
28
+ label: string;
29
+ id?: string;
30
+ title?: string;
31
31
  editMode?: boolean;
32
32
  small?: boolean;
33
33
  }>(),
34
- {
35
- editMode: true,
36
- }
34
+ {
35
+ editMode: true,
36
+ id: Math.random().toString(36).substring(7),
37
+ },
37
38
  );
38
39
 
39
- const inputVal = ref(false);
40
- watch(inputVal, (newVal) => {
41
- if (newVal === undefined) return;
42
- emits("update:modelValue", newVal);
43
- });
44
- watch(
45
- () => props.modelValue,
46
- (newVal) => {
47
- if (inputVal.value !== newVal) inputVal.value = newVal;
48
- }
49
- );
50
- onMounted(() => (inputVal.value = !!props.modelValue));
40
+ const inputVal = defineModel<boolean>('modelValue', { default: false });
51
41
  </script>
42
+ <style>
43
+ :root {
44
+ --bgl-white: #fff;
45
+ --input-height: 40px;
46
+ --input-border-radius: 7px;
47
+ --bgl-transition: all 200ms ease;
48
+ --bgl-primary: #19b8ea;
52
49
 
50
+ }
51
+ </style>
53
52
  <style scoped>
54
- .no-edit {
55
- pointer-events: none;
53
+ .bgl-checkbox{
54
+ position: relative;
56
55
  }
57
-
58
- .radio-wrap p {
59
- display: inline-block;
60
- color: var(--input-bg);
61
- font-size: var(--input-font-size);
62
- margin-inline-end: 10px;
56
+ .bgl-checkbox input[type=checkbox]{
57
+ display: none;
63
58
  }
64
-
65
- .radio-wrap label {
66
- padding: 3px 5px;
67
- display: inline-block;
68
- border-radius: var(--input-border-radius);
69
- font-size: var(--input-font-size);
70
- background: var(--input-bg);
71
- color: var(--bgl-black);
72
- text-align: center;
73
- margin: 8px 5px;
59
+ .bgl-checkbox label{
60
+ padding-inline-start: calc(var(--input-height) / 2 + 0.25rem);
61
+ transition: var(--bgl-transition);
74
62
  cursor: pointer;
75
63
  user-select: none;
76
64
  }
77
-
78
- .bagel-input .radio-wrap label::after {
79
- background: transparent;
65
+ .bgl-checkbox:hover{
66
+ filter: brightness(90%);
80
67
  }
81
-
82
- .radio-wrap input {
83
- display: none;
68
+ .bgl-checkbox:active{
69
+ filter: var(--bgl-active-filter);
84
70
  }
85
-
86
- .radio-wrap input:checked:checked + label {
87
- background: var(--bgl-primary);
88
- color: var(--bgl-white);
89
- }
90
-
91
- .checkbox {
92
- position: relative;
93
- }
94
-
95
- .switch {
96
- position: relative;
97
- display: inline-block;
98
- height: calc(var(--input-height) / 2);
99
- width: var(--input-height);
100
- border-radius: var(--input-height);
101
- }
102
-
103
- .switch input {
104
- opacity: 0;
105
- width: 0;
106
- height: 0;
107
- }
108
-
109
- .slider {
110
- position: absolute;
111
- cursor: pointer;
112
- top: 0;
113
- left: 0;
114
- right: 0;
115
- bottom: 0;
116
- background: var(--input-bg);
117
- -webkit-transition: 0.4s;
118
- transition: 0.4s;
119
- border-radius: calc(var(--input-height) / 2);
120
- box-shadow: inset 0 0 10px #00000020;
121
- }
122
-
123
- .slider:before {
124
- position: absolute;
71
+ .bgl-checkbox label::before{
125
72
  content: "";
126
- height: calc(var(--input-height) / 2 - 4px);
127
- width: calc(var(--input-height) / 2 - 4px);
128
- left: 2px;
129
- bottom: 2px;
130
- border-radius: 50%;
73
+ width: calc(var(--input-height) / 2.5);
74
+ height: calc(var(--input-height) / 2.5);
131
75
  background: var(--bgl-white);
132
- -webkit-transition: 0.4s;
133
- transition: 0.4s;
76
+ display: inline-block;
77
+ position: absolute;
78
+ margin-top: 0.25rem;
79
+ inset-inline-start: 0;
80
+ border-radius: calc(var(--input-border-radius) / 2) ;
81
+ border: var(--bgl-primary) 1px solid;
134
82
  }
135
83
 
136
- input:checked + .slider {
84
+ input:checked ~ label::before{
137
85
  background: var(--bgl-primary);
138
86
  }
139
-
140
- input:checked + .slider:before {
141
- transform: translateX(calc(var(--input-height) / 2));
87
+ .bgl-checkbox svg{
88
+ width: calc(var(--input-height) / 2.5);
89
+ height: calc(var(--input-height) / 2.5);
90
+ position: absolute;
91
+ inset-inline-start: 0.05rem;
92
+ margin-top: 0.3rem;
93
+ z-index: 2;
94
+ fill: var(--bgl-white);
95
+ opacity: 0;
96
+ pointer-events: none;
97
+ }
98
+ input:checked ~ svg{
99
+ opacity: 1;
142
100
  }
143
101
  </style>
@@ -3,16 +3,17 @@
3
3
  <label>
4
4
  {{ label }}
5
5
  </label>
6
- <div @click="browse" @dragover="dragenter" @drop="drop" @dragleave="dragleave" class="fileUploadWrap" :class="{fileDropZone: !files.length, dragover: isDragOver}">
6
+ <div @click="browse" @dragover="dragover" @drop="drop" @dragleave="dragleave" class="fileUploadWrap"
7
+ :class="{ fileDropZone: !files.length, dragover: isDragOver }">
7
8
  <div v-if="files.length && !multiple">
8
9
  <div class="imagePreviewWrap">
9
- <img class="preview" :src="fileToUrl(files[0])" alt="" >
10
+ <img class="preview" :src="fileToUrl(files[0])" alt="">
10
11
  </div>
11
12
  <div class="previewName">
12
13
  <p class="no-margin">
13
- {{files[0].name}}
14
+ {{ files[0].name }}
14
15
  </p>
15
- <Btn thin @click.stop="removeFile(files[0])" flat icon="delete" color="red"/>
16
+ <Btn thin @click.stop="removeFile(files[0])" flat icon="delete" color="red" />
16
17
  </div>
17
18
  </div>
18
19
  </div>
@@ -22,7 +23,7 @@
22
23
  <script setup lang="ts">
23
24
  import { Btn } from '@bagelink/vue';
24
25
 
25
- const props = defineProps<{label:string, multiple?: boolean}>();
26
+ const props = defineProps<{ label: string, multiple?: boolean }>();
26
27
  const files = $ref<File[]>([]);
27
28
  const fileQueue = $ref<File[]>([]);
28
29
  let isDragOver = $ref(false);
@@ -33,14 +34,13 @@ const preventDefault = (e: Event) => {
33
34
  };
34
35
 
35
36
  const fileToUrl = (file: File) => URL.createObjectURL(file);
36
- const removeFile = (file:File) => {
37
+ const removeFile = (file: File) => {
37
38
  const index = files.indexOf(file);
38
39
  files.splice(index, 1);
39
40
  };
40
41
  const flushQueue = () => {
41
- fileQueue.forEach((file:File, i) => {
42
+ fileQueue.forEach((file: File, i) => {
42
43
  if (props.multiple) { if (!files.includes(file)) files.push(file); } else files.splice(0, 1, file);
43
- console.log(files);
44
44
  fileQueue.splice(i, 1);
45
45
  });
46
46
  };
@@ -63,7 +63,7 @@ const dragleave = (e: DragEvent) => {
63
63
  else isDragOver = false;
64
64
  };
65
65
 
66
- const dragenter = (e: DragEvent) => {
66
+ const dragover = (e: DragEvent) => {
67
67
  preventDefault(e);
68
68
  if (e.dataTransfer) isDragOver = true;
69
69
  else isDragOver = false;
@@ -79,52 +79,59 @@ const drop = (e: DragEvent) => {
79
79
 
80
80
  <style scoped>
81
81
  .bagel-input .fileUploadWrap {
82
- outline: 1px solid var(--border-color);
83
- border-radius: var(--input-border-radius);
84
- text-align: center;
85
- cursor: pointer;
86
- transition: var(--bgl-transition);
87
- position: relative;
88
- height: 132px;
89
- font-size: var(--input-font-size);
82
+ outline: 1px solid var(--border-color);
83
+ border-radius: var(--input-border-radius);
84
+ text-align: center;
85
+ cursor: pointer;
86
+ transition: var(--bgl-transition);
87
+ position: relative;
88
+ height: 132px;
89
+ font-size: var(--input-font-size);
90
90
  }
91
- .previewName{
92
- padding: 0.5rem;
93
- text-align: start;
94
- color: var(--input-color);
95
- display: grid;
96
- grid-template-columns: 1fr 22px;
97
- align-items: center;
91
+
92
+ .previewName {
93
+ padding: 0.5rem;
94
+ text-align: start;
95
+ color: var(--input-color);
96
+ display: grid;
97
+ grid-template-columns: 1fr 22px;
98
+ align-items: center;
98
99
 
99
100
  }
100
- .previewName p{
101
- overflow: hidden;
102
- text-overflow: ellipsis;
103
- white-space: nowrap;
101
+
102
+ .previewName p {
103
+ overflow: hidden;
104
+ text-overflow: ellipsis;
105
+ white-space: nowrap;
104
106
  }
105
- .imagePreviewWrap{
106
- background: var(--input-bg);
107
- border-radius: var(--input-border-radius);
108
- height: 90px;
109
- padding: 5px;
107
+
108
+ .imagePreviewWrap {
109
+ background: var(--input-bg);
110
+ border-radius: var(--input-border-radius);
111
+ height: 90px;
112
+ padding: 5px;
110
113
  }
111
114
 
112
115
  img.preview {
113
- height: 80px;
114
- border-radius: var(--input-border-radius);
115
- object-fit: contain;
116
+ height: 80px;
117
+ border-radius: var(--input-border-radius);
118
+ object-fit: contain;
116
119
  }
117
- .fileUploadWrap.dragover, .fileUploadWrap:hover{
118
- box-shadow: inset 0 0 10px #00000012;
120
+
121
+ .fileUploadWrap.dragover,
122
+ .fileUploadWrap:hover {
123
+ box-shadow: inset 0 0 10px #00000012;
119
124
  }
120
- .bagel-input .fileUploadWrap.fileDropZone{
121
- background: var(--input-bg);
122
- display: flex;
123
- align-items: center;
124
- justify-content: center;
125
- color:var(--bgl-gray);
125
+
126
+ .bagel-input .fileUploadWrap.fileDropZone {
127
+ background: var(--input-bg);
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ color: var(--bgl-gray);
126
132
  }
133
+
127
134
  .bagel-input .fileUploadWrap.fileDropZone:after {
128
- content: "Drop files here or click to upload";
135
+ content: "Drop files here or click to upload";
129
136
  }
130
137
  </style>