@bagelink/vue 0.0.360 → 0.0.374

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 (31) hide show
  1. package/dist/components/Alert.vue.d.ts.map +1 -1
  2. package/dist/components/Card.vue.d.ts +2 -0
  3. package/dist/components/Card.vue.d.ts.map +1 -1
  4. package/dist/components/RouterWrapper.vue.d.ts.map +1 -1
  5. package/dist/components/form/BglField.vue.d.ts.map +1 -1
  6. package/dist/components/form/BglForm.vue.d.ts +3 -0
  7. package/dist/components/form/BglForm.vue.d.ts.map +1 -1
  8. package/dist/components/form/inputs/DatePicker.vue.d.ts +4 -2
  9. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/RichText.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/TextInput.vue.d.ts.map +1 -1
  12. package/dist/components/layout/SidebarMenu.vue.d.ts.map +1 -1
  13. package/dist/index.cjs +154 -127
  14. package/dist/index.mjs +154 -127
  15. package/dist/style.css +105 -53
  16. package/dist/utils/BagelFormUtils.d.ts +10 -0
  17. package/dist/utils/BagelFormUtils.d.ts.map +1 -1
  18. package/package.json +1 -1
  19. package/src/components/Alert.vue +1 -1
  20. package/src/components/Card.vue +51 -23
  21. package/src/components/RouterWrapper.vue +4 -6
  22. package/src/components/form/BglField.vue +65 -36
  23. package/src/components/form/BglForm.vue +64 -60
  24. package/src/components/form/inputs/DatePicker.vue +15 -18
  25. package/src/components/form/inputs/RichText.vue +68 -41
  26. package/src/components/form/inputs/SelectInput.vue +1 -1
  27. package/src/components/form/inputs/TextInput.vue +4 -0
  28. package/src/components/layout/SidebarMenu.vue +39 -20
  29. package/src/styles/text.css +1 -1
  30. package/src/styles/theme.css +1 -0
  31. package/src/utils/BagelFormUtils.ts +14 -0
@@ -1,21 +1,30 @@
1
1
  <template>
2
- <template v-if="id">
3
- <BglField v-for="(field, i) in schema" :key="field.id || `${i}p`" :field="field" v-model="data" />
4
- </template>
5
- <form v-else-if="(!slots.success || formStatus !== 'success')" ref="form" @submit.prevent="runSubmit">
6
- <Title tag="h4" :label="label" v-if="label" />
7
- <BglField v-for="(field, i) in schema" :key="field.id || `${i}p`" :field="field" v-model="data" />
8
- <slot name="submit" />
9
- </form>
10
- <slot v-if="formStatus === 'success'" name="success" />
11
- <slot v-if="formStatus === 'error'" name="error" />
2
+ <template v-if="id">
3
+ <BglField
4
+ v-for="(field, i) in schema"
5
+ :key="field.id || `${i}p`"
6
+ :field="field"
7
+ v-model="data" />
8
+ </template>
9
+ <form
10
+ v-else-if="!slots.success || status !== 'success'"
11
+ ref="form"
12
+ @submit.prevent="runSubmit">
13
+ <Title tag="h4" :label="label" v-if="label" />
14
+ <BglField
15
+ v-for="(field, i) in schema"
16
+ :key="field.id || `${i}p`"
17
+ :field="field"
18
+ v-model="data" />
19
+ <slot name="submit" />
20
+ </form>
21
+ <slot v-if="status === 'success'" name="success" />
22
+ <slot v-if="status === 'error'" name="error" />
12
23
  </template>
13
24
 
14
25
  <script lang="ts" setup>
15
26
  import { useSlots } from 'vue';
16
- import {
17
- useModal, BglField, Title,
18
- } from '@bagelink/vue';
27
+ import { useModal, BglField, Title } from '@bagelink/vue';
19
28
 
20
29
  import { type BglFormSchemaT } from '@bagelink/vue';
21
30
 
@@ -24,17 +33,18 @@ const slots = useSlots();
24
33
  const { showModal } = useModal();
25
34
 
26
35
  const props = withDefaults(
27
- defineProps<{
28
- label?: string;
29
- id?: string;
30
- schema: BglFormSchemaT<any>;
31
- modelValue?: Record<string, any>;
32
- onDelete?: ((id: string) => void);
33
- onSubmit?: ((data: any) => void);
34
- }>(),
35
- {
36
- modelValue: () => ({}),
37
- },
36
+ defineProps<{
37
+ label?: string;
38
+ id?: string;
39
+ schema: BglFormSchemaT<any>;
40
+ modelValue?: Record<string, any>;
41
+ onDelete?: (id: string) => void;
42
+ onSubmit?: (data: any) => void;
43
+ status?: FormStatus;
44
+ }>(),
45
+ {
46
+ modelValue: () => ({}),
47
+ }
38
48
  );
39
49
 
40
50
  const instAt = new Date();
@@ -43,15 +53,15 @@ let formData = $ref(props.modelValue);
43
53
  const emit = defineEmits(['update:modelValue', 'submit', 'dirty']);
44
54
  let isDirty = $ref(false);
45
55
  const data = $computed({
46
- set: (val: any) => {
47
- if (timeSinceInst() > 100) {
48
- emit('dirty');
49
- isDirty = true;
50
- }
51
- formData = val;
52
- emit('update:modelValue', val);
53
- },
54
- get: () => props.modelValue || formData,
56
+ set: (val: any) => {
57
+ if (timeSinceInst() > 100) {
58
+ emit('dirty');
59
+ isDirty = true;
60
+ }
61
+ formData = val;
62
+ emit('update:modelValue', val);
63
+ },
64
+ get: () => props.modelValue || formData,
55
65
  });
56
66
  const form = $ref<HTMLFormElement>();
57
67
 
@@ -61,38 +71,32 @@ const clearForm = () => Object.assign(data, {});
61
71
 
62
72
  type FormStatus = 'idle' | 'loading' | 'success' | 'error';
63
73
 
64
- let formStatus = $ref<FormStatus>('idle');
65
-
66
74
  const runSubmit = () => {
67
- try {
68
- validateForm();
69
- props.onSubmit?.(data);
70
- // emit('submit', data);
71
- clearForm();
72
- formStatus = 'success';
73
- } catch (e) {
74
- formStatus = 'error';
75
- }
75
+ const isValid = validateForm();
76
+ if (!isValid) return;
77
+ props.onSubmit?.(data);
78
+ // emit('submit', data);
79
+ clearForm();
76
80
  };
77
81
 
78
82
  const i18nT = (val: string) => val;
79
83
 
80
84
  const deleteItem = () => {
81
- showModal(
82
- {
83
- class: 'small-modal',
84
- title: i18nT('Are you sure?'),
85
- actions: [
86
- {
87
- value: 'Confirm',
88
- color: 'red',
89
- onClick: () => props.onDelete?.(data.value.id),
90
- },
91
- { value: 'Cancel', color: 'gray' },
92
- ],
93
- },
94
- { default: i18nT('form.deleteMessage') },
95
- );
85
+ showModal(
86
+ {
87
+ class: 'small-modal',
88
+ title: i18nT('Are you sure?'),
89
+ actions: [
90
+ {
91
+ value: 'Confirm',
92
+ color: 'red',
93
+ onClick: () => props.onDelete?.(data.value.id),
94
+ },
95
+ { value: 'Cancel', color: 'gray' },
96
+ ],
97
+ },
98
+ { default: i18nT('form.deleteMessage') }
99
+ );
96
100
  };
97
101
 
98
102
  defineExpose({ validateForm, deleteItem, isDirty });
@@ -100,6 +104,6 @@ defineExpose({ validateForm, deleteItem, isDirty });
100
104
 
101
105
  <style>
102
106
  .del-top {
103
- transform: translateY(-2.6rem);
107
+ transform: translateY(-2.6rem);
104
108
  }
105
109
  </style>
@@ -8,28 +8,20 @@
8
8
  :highlight-week-days="[6]"
9
9
  :enable-time-picker="false"
10
10
  :month-change-on-scroll="false"
11
- v-bind="options"
12
- >
11
+ v-bind="options">
13
12
  <template #action-buttons />
14
13
  <template #action-preview />
15
14
  </VDatepicker>
16
15
  </div>
17
- <div
18
- class="time-wrap"
19
- v-if="showTimeWrap"
20
- >
21
- <template
22
- v-for="hr in hours"
23
- :key="hr"
24
- >
16
+ <div class="time-wrap" v-if="showTimeWrap">
17
+ <template v-for="hr in hours" :key="hr">
25
18
  <input
26
19
  type="radio"
27
- :id="`${hr}_${name}`"
28
- :name="name"
20
+ :id="`${hr}_${id}`"
21
+ :name="label"
29
22
  :value="hr"
30
- v-model="selectedHour"
31
- >
32
- <label :for="`${hr}_${name}`">{{ hr }}</label>
23
+ v-model="selectedHour" />
24
+ <label :for="`${hr}_${id}`">{{ hr }}</label>
33
25
  </template>
34
26
  </div>
35
27
  </div>
@@ -39,7 +31,12 @@
39
31
  import VDatepicker from '@vuepic/vue-datepicker';
40
32
  import '@vuepic/vue-datepicker/dist/main.css';
41
33
 
42
- defineProps<{ name: string, options?: Record<string, any>, showTimeWrap?: boolean }>();
34
+ defineProps<{
35
+ label?: string;
36
+ id?: string;
37
+ options?: Record<string, any>;
38
+ showTimeWrap?: boolean;
39
+ }>();
43
40
  const selectedDate = $ref(null);
44
41
  const selectedHour = $ref();
45
42
 
@@ -80,7 +77,7 @@ const hours = Array.from({ length: 18 }, (_, index) => {
80
77
  border: 1px solid var(--bgl-primary);
81
78
  }
82
79
 
83
- .time-wrap input[type="radio"]:checked+label {
80
+ .time-wrap input[type='radio']:checked + label {
84
81
  background: var(--bgl-primary);
85
82
  color: var(--bgl-white);
86
83
  }
@@ -130,7 +127,7 @@ const hours = Array.from({ length: 18 }, (_, index) => {
130
127
  margin-bottom: -10px;
131
128
  }
132
129
 
133
- .dp__calendar_row>div:last-child {
130
+ .dp__calendar_row > div:last-child {
134
131
  pointer-events: none;
135
132
  }
136
133
 
@@ -1,16 +1,18 @@
1
1
  <template>
2
- <div v-if="editor">
3
- <Btn
4
- :flat="!editor.isActive(item.name, item.option)"
5
- @click="item.command"
6
- thin
7
- v-for="item in config"
8
- v-tooltip="item.name"
9
- :key="item.name"
10
- :icon="item.icon"
11
- :disabled="item.disabled?.()" />
2
+ <div class="RichText">
3
+ <div class="RichText-tools" v-if="editor">
4
+ <Btn
5
+ :flat="!editor.isActive(item.name, item.option)"
6
+ @click="item.command"
7
+ thin
8
+ v-for="item in config"
9
+ v-tooltip="item.name"
10
+ :key="item.name"
11
+ :icon="item.icon"
12
+ :disabled="item.disabled?.()" />
13
+ </div>
14
+ <editor-content :editor="editor" />
12
15
  </div>
13
- <editor-content :editor="editor" />
14
16
  </template>
15
17
 
16
18
  <script setup lang="ts">
@@ -37,117 +39,117 @@ const config: {
37
39
  disabled?: () => boolean;
38
40
  }[] = [
39
41
  {
40
- name: 'bold',
42
+ name: 'Bold',
41
43
  command: () => focus()?.toggleBold().run(),
42
44
  icon: 'format_bold',
43
45
  disabled: () => !editor?.can().chain().focus().toggleBold().run(),
44
46
  },
45
47
  {
46
- name: 'italic',
48
+ name: 'Italic',
47
49
  command: () => focus().toggleItalic().run(),
48
50
  icon: 'format_italic',
49
51
  disabled: () => !editor?.can().chain().focus().toggleItalic().run(),
50
52
  },
51
53
  {
52
- name: 'strike',
54
+ name: 'Strike',
53
55
  command: () => focus().toggleStrike().run(),
54
56
  icon: 'format_strikethrough',
55
57
  disabled: () => !editor?.can().chain().focus().toggleStrike().run(),
56
58
  },
57
59
  {
58
- name: 'code',
60
+ name: 'Code Text',
59
61
  command: () => focus().toggleCode().run(),
60
62
  icon: 'code',
61
63
  },
64
+ // {
65
+ // name: 'clearMarks',
66
+ // command: () => focus().unsetAllMarks(),
67
+ // icon: 'clear',
68
+ // },
62
69
  {
63
- name: 'clearMarks',
64
- command: () => focus().unsetAllMarks(),
65
- icon: 'clear',
66
- },
67
- {
68
- name: 'clearNodes',
70
+ name: 'Clear',
69
71
  command: () => focus().clearNodes().run(),
70
- icon: 'clear',
72
+ icon: 'format_clear',
71
73
  },
72
74
  {
73
- name: 'paragraph',
75
+ name: 'Paragraph',
74
76
  command: () => focus().setParagraph().run(),
75
77
  icon: 'format_paragraph',
76
78
  },
77
79
  {
78
- name: 'heading',
80
+ name: 'Heading',
79
81
  command: () => focus().toggleHeading({ level: 1 }).run(),
80
82
  icon: 'format_h1',
81
83
  option: { level: 1 },
82
84
  },
83
85
  {
84
- name: 'heading',
86
+ name: 'Heading',
85
87
  command: () => focus().toggleHeading({ level: 2 }).run(),
86
88
  icon: 'format_h2',
87
89
  option: { level: 2 },
88
90
  },
89
91
  {
90
- name: 'heading',
92
+ name: 'Heading',
91
93
  command: () => focus().toggleHeading({ level: 3 }).run(),
92
94
  icon: 'format_h3',
93
95
  option: { level: 3 },
94
96
  },
95
97
  {
96
- name: 'heading',
98
+ name: 'Heading',
97
99
  command: () => focus().toggleHeading({ level: 4 }).run(),
98
100
  icon: 'format_h4',
99
101
  option: { level: 4 },
100
102
  },
101
103
  {
102
- name: 'heading',
104
+ name: 'Heading',
103
105
  command: () => focus().toggleHeading({ level: 5 }).run(),
104
106
  icon: 'format_h5',
105
107
  option: { level: 5 },
106
108
  },
107
109
  {
108
- name: 'heading',
110
+ name: 'Heading',
109
111
  command: () => focus().toggleHeading({ level: 6 }).run(),
110
112
  icon: 'format_h6',
111
113
  option: { level: 6 },
112
114
  },
113
115
  {
114
- name: 'bulletList',
116
+ name: 'Bullet List',
115
117
  command: () => focus().toggleBulletList().run(),
116
118
  icon: 'format_list_bulleted',
117
119
  },
118
120
  {
119
- name: 'orderedList',
121
+ name: 'Ordered List',
120
122
  command: () => focus().toggleOrderedList().run(),
121
123
  icon: 'format_list_numbered',
122
124
  },
123
125
  {
124
- name: 'codeBlock',
126
+ name: 'Code Block',
125
127
  command: () => focus().toggleCodeBlock().run(),
126
- icon: 'code',
128
+ icon: 'code_blocks',
127
129
  },
128
130
  {
129
- name: 'blockquote',
131
+ name: 'Blockquote',
130
132
  command: () => focus().toggleBlockquote().run(),
131
133
  icon: 'format_quote',
132
134
  },
133
135
  {
134
- name: 'horizontalRule',
136
+ name: 'Horizontal Rule',
135
137
  command: () => focus().setHorizontalRule().run(),
136
138
  icon: 'horizontal_rule',
137
139
  },
138
140
  {
139
- name: 'hardBreak',
141
+ name: 'Hard Break',
140
142
  command: () => focus().setHardBreak().run(),
141
143
  icon: 'keyboard_return',
142
144
  },
143
145
  {
144
- name: 'undo',
146
+ name: 'Undo',
145
147
  command: () => focus().undo().run(),
146
148
  icon: 'undo',
147
149
  disabled: () => !editor?.can().chain().focus().undo().run(),
148
150
  },
149
151
  {
150
- name: 'redo',
152
+ name: 'Redo',
151
153
  command: () => focus().redo().run(),
152
154
  icon: 'redo',
153
155
  disabled: () => !editor?.can().chain().focus().redo().run(),
@@ -166,7 +168,10 @@ function initEditor() {
166
168
 
167
169
  watch(
168
170
  () => props.modelValue,
169
- (value) => editor?.commands.setContent(value),
171
+ (value) => {
172
+ if (editor?.getHTML() === value) return;
173
+ editor?.commands.setContent(value, false);
174
+ },
170
175
  { immediate: true }
171
176
  );
172
177
 
@@ -187,12 +192,17 @@ onBeforeUnmount(() => editor?.destroy());
187
192
  }
188
193
 
189
194
  .tiptap h1,
190
- .tiptap h2,
195
+ .tiptap h2 {
196
+ line-height: 1;
197
+ margin-top: 0;
198
+ }
199
+
191
200
  .tiptap h3,
192
201
  .tiptap h4,
193
202
  .tiptap h5,
194
203
  .tiptap h6 {
195
204
  line-height: 1.1;
205
+ margin-top: 0;
196
206
  }
197
207
 
198
208
  .tiptap code {
@@ -228,7 +238,7 @@ onBeforeUnmount(() => editor?.destroy());
228
238
  .tiptap hr {
229
239
  border: none;
230
240
  border-top: 2px solid rgba(13, 13, 13, 0.1);
231
- margin: 2rem 0;
241
+ margin: 1rem 0;
232
242
  }
233
243
 
234
244
  .tiptap {
@@ -236,5 +246,22 @@ onBeforeUnmount(() => editor?.destroy());
236
246
  background: var(--input-bg);
237
247
  overflow: auto;
238
248
  max-height: 600px;
249
+ padding: 0.7rem;
250
+ color: var(--input-color);
251
+ border-radius: var(--input-border-radius);
252
+ font-size: var(--input-font-size);
253
+ line-height: 1.5;
254
+ }
255
+ .tiptap.ProseMirror-focused {
256
+ outline: none;
257
+ box-shadow: inset 0 0 10px #00000012;
258
+ }
259
+ .RichText {
260
+ margin-bottom: 0.5rem;
261
+ }
262
+ .RichText-tools {
263
+ background: var(--input-bg);
264
+ margin-bottom: 0.125rem;
265
+ border-radius: var(--input-border-radius);
239
266
  }
240
267
  </style>
@@ -266,7 +266,7 @@ watch(
266
266
 
267
267
  .v-popper--theme-dropdown .v-popper__inner {
268
268
  border: none;
269
- background: transparent;
269
+ /* background: transparent; if anyone is changing this please talk to me first*/
270
270
  border-radius: var(--card-border-radius);
271
271
  color: var(--input-color);
272
272
  }
@@ -180,6 +180,10 @@ onMounted(() => {
180
180
  background: var(--bgl-black) !important;
181
181
  color: var(--bgl-white) !important;
182
182
  }
183
+ .code textarea::placeholder{
184
+ color: var(--bgl-white) !important;
185
+ opacity: 0.3;
186
+ }
183
187
 
184
188
  .bagel-input.toggleEdit:hover {
185
189
  background-color: var(--input-bg);
@@ -1,22 +1,24 @@
1
1
  <template>
2
- <Card class="flex column gap-05 pt-1 bgl_sidebar" :class="{ 'wideNav': isOpen }">
3
- <div class="w-100 px-075">
4
- <Btn thin color="light" class="toggleNav mb-05" icon="keyboard_arrow_right" @click="toggleMenu" />
5
- </div>
6
- <slot v-if="!isOpen || !slots['brand-open']" name="brand" />
7
- <slot v-if="isOpen" name="brand-open" />
8
- <slot v-if="!navLinks" />
9
- <Btn v-for="(nav, i) in navLinks" :key="i" :to="nav.to" class="nav-button px-075"
10
- v-tooltip.right="{ content: nav.label, disabled: open, class: ['nav-tooltip'] }">
11
- <template #default>
12
- <Icon :icon="nav.icon" :size="1.4" />
13
- <p v-if="open">
14
- {{ nav.label }}
15
- </p>
16
- </template>
17
- </Btn>
18
- <slot name="footer" />
19
- </Card>
2
+ <Card class="flex column gap-05 pt-1 bgl_sidebar" :class="{ 'wideNav': isOpen }">
3
+ <div class="w-100 px-075">
4
+ <Btn thin color="light" class="toggleNav mb-05" icon="keyboard_arrow_right" @click="toggleMenu" />
5
+ </div>
6
+ <slot v-if="!isOpen || !slots['brand-open']" name="brand" />
7
+ <slot v-if="isOpen" name="brand-open" />
8
+ <slot v-if="!navLinks" />
9
+ <Btn
10
+ v-for="(nav, i) in navLinks" :key="i" :to="nav.to" class="nav-button px-075"
11
+ v-tooltip.right="{ content: nav.label, disabled: open, class: ['nav-tooltip'] }"
12
+ >
13
+ <template #default>
14
+ <Icon :icon="nav.icon" :size="1.4" />
15
+ <p v-if="open">
16
+ {{ nav.label }}
17
+ </p>
18
+ </template>
19
+ </Btn>
20
+ <slot name="footer" />
21
+ </Card>
20
22
  </template>
21
23
 
22
24
  <script lang="ts" setup>
@@ -32,8 +34,8 @@ let isOpen = $ref(props.open);
32
34
 
33
35
  const emit = defineEmits(['update:open']);
34
36
  function toggleMenu() {
35
- isOpen = !isOpen;
36
- emit('update:open', isOpen);
37
+ isOpen = !isOpen;
38
+ emit('update:open', isOpen);
37
39
  }
38
40
  </script>
39
41
 
@@ -67,6 +69,15 @@ function toggleMenu() {
67
69
  padding: 0.5rem;
68
70
  overflow-y: auto;
69
71
  }
72
+ .toggleNav{
73
+ height: 22px !important;
74
+ width: 22px !important;
75
+ opacity: 0.4;
76
+ transition: var(--bgl-transition);
77
+ }
78
+ .toggleNav:hover{
79
+ opacity: 1;
80
+ }
70
81
 
71
82
  .wideNav .toggleNav {
72
83
  transform: rotate(180deg);
@@ -77,6 +88,14 @@ function toggleMenu() {
77
88
  width: 100%;
78
89
  }
79
90
 
91
+ [dir="rtl"] .toggleNav {
92
+ transform: rotate(180deg);
93
+ }
94
+
95
+ [dir="rtl"] .wideNav .toggleNav {
96
+ transform: rotate(0deg);
97
+ }
98
+
80
99
  .nav-button.bgl_btn-icon {
81
100
  border-radius: var(--btn-border-radius) !important;
82
101
  }
@@ -228,7 +228,7 @@
228
228
  }
229
229
 
230
230
  .bgl_icon-font {
231
- font-family: "Material Symbols Outlined", serif;
231
+ font-family: "Material Symbols Outlined", serif !important;
232
232
  }
233
233
 
234
234
  .nowrap {
@@ -142,6 +142,7 @@
142
142
  color: var(--bgl-primary);
143
143
  border-bottom: 2px solid var(--bgl-primary);
144
144
  }
145
+
145
146
  .router-tab:hover {
146
147
  color: var(--bgl-primary);
147
148
  }
@@ -25,6 +25,20 @@ interface NumFieldOptions extends InputOptions {
25
25
  step?: number;
26
26
  }
27
27
 
28
+ type RichTextOptions = InputOptions
29
+
30
+ export function richText(id: string, label?: string, options?: RichTextOptions) {
31
+ return {
32
+ $el: 'richtext',
33
+ class: options?.class,
34
+ required: options?.required,
35
+ id,
36
+ label,
37
+ placeholder: options?.placeholder,
38
+ attrs: {},
39
+ };
40
+ }
41
+
28
42
  export function txtField(id: string, label?: string, options?: TextInputOptions): Field {
29
43
  return {
30
44
  $el: 'text',