@bagelink/vue 0.0.339 → 0.0.346

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 (43) hide show
  1. package/dist/components/Card.vue.d.ts +2 -2
  2. package/dist/components/Modal.vue.d.ts +1 -0
  3. package/dist/components/RouterWrapper.vue.d.ts.map +1 -1
  4. package/dist/components/form/BglForm.vue.d.ts +7 -1
  5. package/dist/components/form/BglForm.vue.d.ts.map +1 -1
  6. package/dist/components/form/inputs/DateInput.vue.d.ts +1 -0
  7. package/dist/components/form/inputs/RichText.vue.d.ts +20 -0
  8. package/dist/components/form/inputs/RichText.vue.d.ts.map +1 -0
  9. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  10. package/dist/components/form/inputs/index.d.ts +1 -1
  11. package/dist/components/form/inputs/index.d.ts.map +1 -1
  12. package/dist/components/index.d.ts +0 -2
  13. package/dist/components/index.d.ts.map +1 -1
  14. package/dist/components/layout/BottomMenu.vue.d.ts +24 -0
  15. package/dist/components/layout/BottomMenu.vue.d.ts.map +1 -0
  16. package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
  17. package/dist/components/layout/index.d.ts +1 -0
  18. package/dist/components/layout/index.d.ts.map +1 -1
  19. package/dist/index.cjs +32865 -24539
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.mjs +32866 -24540
  22. package/dist/style.css +166 -225
  23. package/dist/types/materialIcons.d.ts +1 -1
  24. package/dist/types/materialIcons.d.ts.map +1 -1
  25. package/package.json +4 -8
  26. package/src/components/RouterWrapper.vue +6 -4
  27. package/src/components/form/inputs/RichText.vue +219 -0
  28. package/src/components/form/inputs/SelectInput.vue +123 -122
  29. package/src/components/form/inputs/index.ts +1 -1
  30. package/src/components/index.ts +0 -2
  31. package/src/components/layout/BottomMenu.vue +64 -0
  32. package/src/components/layout/SidebarMenu.vue +2 -1
  33. package/src/components/layout/Tabs.vue +4 -4
  34. package/src/components/layout/TabsNav.vue +36 -14
  35. package/src/components/layout/index.ts +1 -0
  36. package/src/styles/layout.css +11 -0
  37. package/src/styles/mobilLayout.css +10 -0
  38. package/src/styles/theme.css +0 -1
  39. package/src/styles/transitions.css +4 -0
  40. package/src/types/materialIcons.ts +2068 -6
  41. package/src/components/Comments.vue +0 -268
  42. package/src/components/RTXEditor.vue +0 -151
  43. package/src/components/form/inputs/RichTextEditor.vue +0 -56
@@ -0,0 +1,219 @@
1
+ <template>
2
+ <div v-if="editor">
3
+ <Btn :flat="!editor.isActive(item.name, item.option)" @click="item.command" thin v-for="item in config"
4
+ v-tooltip="item.name" :key="item.name" :icon="item.icon" :disabled="item.disabled?.()" />
5
+ </div>
6
+ <editor-content :editor="editor" />
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { Btn } from '@bagelink/vue';
11
+ import { onMounted, onBeforeUnmount } from 'vue';
12
+ import StarterKit from '@tiptap/starter-kit';
13
+ import { Editor, EditorContent } from '@tiptap/vue-3';
14
+ import type { MaterialIcons } from '@bagelink/vue';
15
+
16
+ let editor = $ref<Editor>();
17
+
18
+ const props = defineProps<{ modelValue: string }>();
19
+
20
+ const focus = () => {
21
+ if (!editor) throw new Error('editor is not defined');
22
+ return editor.chain().focus();
23
+ };
24
+
25
+ const config: { name: string, command: any, icon: MaterialIcons, option?: Record<string, any>, disabled?: () => boolean }[] = [
26
+ {
27
+ name: 'bold',
28
+ command: () => focus()?.toggleBold().run(),
29
+ icon: 'format_bold',
30
+ disabled: () => !editor?.can().chain().focus().toggleBold()
31
+ .run(),
32
+ },
33
+ {
34
+ name: 'italic',
35
+ command: () => focus().toggleItalic().run(),
36
+ icon: 'format_italic',
37
+ disabled: () => !editor?.can().chain().focus().toggleItalic()
38
+ .run(),
39
+ },
40
+ {
41
+ name: 'strike',
42
+ command: () => focus().toggleStrike().run(),
43
+ icon: 'format_strikethrough',
44
+ disabled: () => !editor?.can().chain().focus().toggleStrike()
45
+ .run(),
46
+ },
47
+ {
48
+ name: 'code',
49
+ command: () => focus().toggleCode().run(),
50
+ icon: 'code',
51
+ },
52
+ {
53
+ name: 'clearMarks',
54
+ command: () => focus().unsetAllMarks(),
55
+ icon: 'clear',
56
+
57
+ },
58
+ {
59
+ name: 'clearNodes',
60
+ command: () => focus().clearNodes().run(),
61
+ icon: 'clear',
62
+ },
63
+ {
64
+ name: 'paragraph',
65
+ command: () => focus().setParagraph().run(),
66
+ icon: 'format_paragraph',
67
+ },
68
+ {
69
+ name: 'heading',
70
+ command: () => focus().toggleHeading({ level: 1 }).run(),
71
+ icon: 'format_h1',
72
+ option: { level: 1 },
73
+ },
74
+ {
75
+ name: 'heading',
76
+ command: () => focus().toggleHeading({ level: 2 }).run(),
77
+ icon: 'format_h2',
78
+ option: { level: 2 },
79
+ },
80
+ {
81
+ name: 'heading',
82
+ command: () => focus().toggleHeading({ level: 3 }).run(),
83
+ icon: 'format_h3',
84
+ option: { level: 3 },
85
+ },
86
+ {
87
+ name: 'heading',
88
+ command: () => focus().toggleHeading({ level: 4 }).run(),
89
+ icon: 'format_h4',
90
+ option: { level: 4 },
91
+ },
92
+ {
93
+ name: 'heading',
94
+ command: () => focus().toggleHeading({ level: 5 }).run(),
95
+ icon: 'format_h5',
96
+ option: { level: 5 },
97
+ },
98
+ {
99
+ name: 'heading',
100
+ command: () => focus().toggleHeading({ level: 6 }).run(),
101
+ icon: 'format_h6',
102
+ option: { level: 6 },
103
+ },
104
+ {
105
+ name: 'bulletList',
106
+ command: () => focus().toggleBulletList().run(),
107
+ icon: 'format_list_bulleted',
108
+ },
109
+ {
110
+ name: 'orderedList',
111
+ command: () => focus().toggleOrderedList().run(),
112
+ icon: 'format_list_numbered',
113
+ },
114
+ {
115
+ name: 'codeBlock',
116
+ command: () => focus().toggleCodeBlock().run(),
117
+ icon: 'code',
118
+ },
119
+ {
120
+ name: 'blockquote',
121
+ command: () => focus().toggleBlockquote().run(),
122
+ icon: 'format_quote',
123
+ },
124
+ {
125
+ name: 'horizontalRule',
126
+ command: () => focus().setHorizontalRule().run(),
127
+ icon: 'horizontal_rule',
128
+ },
129
+ {
130
+ name: 'hardBreak',
131
+ command: () => focus().setHardBreak().run(),
132
+ icon: 'keyboard_return',
133
+
134
+ },
135
+ {
136
+ name: 'undo',
137
+ command: () => focus().undo().run(),
138
+ icon: 'undo',
139
+ disabled: () => !editor?.can().chain().focus().undo()
140
+ .run(),
141
+ },
142
+ {
143
+ name: 'redo',
144
+ command: () => focus().redo().run(),
145
+ icon: 'redo',
146
+ disabled: () => !editor?.can().chain().focus().redo()
147
+ .run(),
148
+ },
149
+ ];
150
+
151
+ const emit = defineEmits(['update:modelValue']);
152
+
153
+ onMounted(() => {
154
+ editor = new Editor({
155
+ extensions: [StarterKit],
156
+ content: props.modelValue,
157
+ onUpdate: ({ editor }) => emit('update:modelValue', editor.getHTML()),
158
+ });
159
+ });
160
+
161
+ onBeforeUnmount(() => editor?.destroy());
162
+ </script>
163
+
164
+ <style>
165
+ /* Basic editor styles */
166
+ .tiptap>*+* {
167
+ margin-top: 0.75em;
168
+ }
169
+
170
+ .tiptap ul,
171
+ .tiptap ol {
172
+ padding: 0 1rem;
173
+ }
174
+
175
+ .tiptap h1,
176
+ .tiptap h2,
177
+ .tiptap h3,
178
+ .tiptap h4,
179
+ .tiptap h5,
180
+ .tiptap h6 {
181
+ line-height: 1.1;
182
+ }
183
+
184
+ .tiptap code {
185
+ background-color: rgba(97, 97, 97, 0.1);
186
+ color: #616161;
187
+ }
188
+
189
+ .tiptap pre {
190
+ background: #0d0d0d;
191
+ color: #fff;
192
+ font-family: 'JetBrainsMono', monospace;
193
+ padding: 0.75rem 1rem;
194
+ border-radius: 0.5rem;
195
+ }
196
+
197
+ .tiptap pre code {
198
+ color: inherit;
199
+ padding: 0;
200
+ background: none;
201
+ font-size: 0.8rem;
202
+ }
203
+
204
+ .tiptap img {
205
+ max-width: 100%;
206
+ height: auto;
207
+ }
208
+
209
+ .tiptap blockquote {
210
+ padding-left: 1rem;
211
+ border-left: 2px solid rgba(13, 13, 13, 0.1);
212
+ }
213
+
214
+ .tiptap hr {
215
+ border: none;
216
+ border-top: 2px solid rgba(13, 13, 13, 0.1);
217
+ margin: 2rem 0;
218
+ }
219
+ </style>
@@ -1,29 +1,29 @@
1
1
  <template>
2
- <Dropdown ref="dropdown" placement="bottom-start" class="bagel-input selectinput">
3
- <label>
4
- {{ label }}
5
- <button :disabled="disabled" type="button" class="selectinput-btn">
6
- {{ selecteLabel }}
7
- <MaterialIcon v-bind="{ 'icon': open ? 'unfold_less' : 'unfold_more' }" />
8
- </button>
9
- <input style="width: 0; height: 0; position: absolute; opacity: 0; z-index: -1;" v-if="required"
10
- v-model="selectedItems" required>
11
- </label>
12
- <template #popper="{ hide }">
13
- <Card class="selectinput-options p-05" :style="{ width: fullWidth ? '100%' : 'auto' }">
14
- <TextInput v-if="searchable" ref="searchInput" dense :placeholder="'Search'" icon="search" v-model="search" />
15
- <div class="selectinput-option hover gap-1" v-for="(option, i) in filteredOptions" :key="`${option}${i}`"
16
- @click="select(option)" :class="{ selected: isSelected(option) }">
17
- <Icon v-if="isSelected(option)" icon="check" />
18
- <Icon class="opacity-3" v-if="!isSelected(option)" icon="fiber_manual_record" />
19
- <span>
20
- {{ getLabel(option) }}
21
- </span>
22
- </div>
23
- <slot name="last" />
24
- </Card>
25
- </template>
26
- </Dropdown>
2
+ <Dropdown @hide="updateOpen(false)" ref="dropdown" placement="bottom-start" class="bagel-input selectinput">
3
+ <label>
4
+ {{ label }}
5
+ <button @click="updateOpen(true)" :disabled="disabled" type="button" class="selectinput-btn">
6
+ {{ selecteLabel }}
7
+ <Icon v-bind="{ 'icon': open ? 'unfold_less' : 'unfold_more' }" />
8
+ </button>
9
+ <input style="width: 0; height: 0; position: absolute; opacity: 0; z-index: -1;" v-if="required"
10
+ v-model="selectedItems" required>
11
+ </label>
12
+ <template #popper="{ hide }">
13
+ <Card class="selectinput-options p-05" :style="{ width: fullWidth ? '100%' : 'auto' }">
14
+ <TextInput v-if="searchable" ref="searchInput" dense :placeholder="'Search'" icon="search" v-model="search" />
15
+ <div class="selectinput-option hover gap-1" v-for="(option, i) in filteredOptions" :key="`${option}${i}`"
16
+ @click="select(option)" :class="{ selected: isSelected(option) }">
17
+ <Icon v-if="isSelected(option)" icon="check" />
18
+ <Icon class="opacity-3" v-if="!isSelected(option)" icon="fiber_manual_record" />
19
+ <span>
20
+ {{ getLabel(option) }}
21
+ </span>
22
+ </div>
23
+ <slot name="last" />
24
+ </Card>
25
+ </template>
26
+ </Dropdown>
27
27
  </template>
28
28
 
29
29
  <script lang="ts" setup>
@@ -31,176 +31,177 @@ import { watch } from 'vue';
31
31
  import { Dropdown } from 'floating-vue';
32
32
  import 'floating-vue/style.css';
33
33
  import {
34
- TextInput, Card, Icon, MaterialIcon,
34
+ TextInput, Card, Icon,
35
35
  } from '@bagelink/vue';
36
36
 
37
37
  type Option = string | number | Record<string, any> | { label: string, value: string | number };
38
- let open = $ref(false);
39
38
 
40
39
  const searchInput = $ref<HTMLInputElement | null>(null);
41
40
 
42
41
  const props = defineProps<{
43
- options: Option[];
44
- placeholder?: string;
45
- disabled?: boolean;
46
- modelValue?: Option;
47
- searchable?: boolean;
48
- required?: boolean;
49
- label?: string;
50
- fullWidth?: boolean;
51
- multiselect?: boolean;
42
+ options: Option[];
43
+ placeholder?: string;
44
+ disabled?: boolean;
45
+ modelValue?: Option;
46
+ searchable?: boolean;
47
+ required?: boolean;
48
+ label?: string;
49
+ fullWidth?: boolean;
50
+ multiselect?: boolean;
52
51
  }>();
52
+
53
53
  const selectedItems = $ref<Option[]>([]);
54
54
  let search = $ref('');
55
55
 
56
56
  const dropdown = $ref<InstanceType<typeof Dropdown> | null>(null);
57
57
 
58
- const toggle = () => {
59
- dropdown?.hide();
60
- open = !open;
61
- if (!open) search = '';
62
- if (open) setTimeout(() => (searchInput as any)?.$el?.querySelector('input')?.focus(), 100);
63
- };
58
+ let open = $ref(false);
59
+
60
+ function updateOpen(visible: boolean) {
61
+ open = visible;
62
+ if (!open) search = '';
63
+ else setTimeout(() => (searchInput as any)?.$el?.querySelector('input')?.focus(), 100);
64
+ }
64
65
 
65
66
  const selecteLabel = $computed(() => {
66
- if (selectedItems.length === 0) return props.placeholder || 'Select';
67
- if (selectedItems.length > 4) {
68
- const str = selectedItems.slice(0, 4).map((item) => getLabel(item)).join(', ');
69
- return `${str}... +${selectedItems.length - 4}`;
70
- }
71
- return selectedItems.map((item) => getLabel(item)).join(', ');
67
+ if (selectedItems.length === 0) return props.placeholder || 'Select';
68
+ if (selectedItems.length > 4) {
69
+ const str = selectedItems.slice(0, 4).map((item) => getLabel(item)).join(', ');
70
+ return `${str}... +${selectedItems.length - 4}`;
71
+ }
72
+ return selectedItems.map((item) => getLabel(item)).join(', ');
72
73
  });
73
74
 
74
75
  const emit = defineEmits(['update:modelValue']);
75
76
 
76
77
  const getLabel = (option: Option) => {
77
- if (typeof option === 'string') return option;
78
- if (typeof option === 'number') return `${option}`;
79
- return option.label;
78
+ if (typeof option === 'string') return option;
79
+ if (typeof option === 'number') return `${option}`;
80
+ return option.label;
80
81
  };
81
82
 
82
83
  const getValue = (option: Option) => {
83
- if (typeof option === 'string') return option;
84
- if (typeof option === 'number') return option;
85
- return option.value;
84
+ if (typeof option === 'string') return option;
85
+ if (typeof option === 'number') return option;
86
+ return option.value;
86
87
  };
87
88
 
88
89
  const isSelected = (option: Option) => selectedItems.includes(getValue(option));
89
90
 
90
91
  const filteredOptions = $computed(() => props.options.filter((option) => {
91
- const searchTerm = new RegExp(search, 'gi');
92
- if (typeof option === 'string') return option.match(searchTerm);
93
- if (typeof option === 'number') return `${option}`.match(searchTerm);
94
- return option.label.match(searchTerm);
92
+ const searchTerm = new RegExp(search, 'gi');
93
+ if (typeof option === 'string') return option.match(searchTerm);
94
+ if (typeof option === 'number') return `${option}`.match(searchTerm);
95
+ return option.label.match(searchTerm);
95
96
  }));
96
97
 
97
98
  const select = (option: Option) => {
98
- const existingIndex = selectedItems.findIndex((item) => {
99
- if (typeof item === 'string' || typeof item === 'number') return item === option;
100
- return item.value === option;
101
- });
102
- if (existingIndex > -1) selectedItems.splice(existingIndex, 1);
103
- else if (props.multiselect) {
104
- selectedItems.push(getValue(option));
105
- } else {
106
- selectedItems.splice(0, selectedItems.length, getValue(option));
107
- toggle();
108
- }
109
- emitUpdate();
99
+ const existingIndex = selectedItems.findIndex((item) => {
100
+ if (typeof item === 'string' || typeof item === 'number') return item === option;
101
+ return item.value === option;
102
+ });
103
+ if (existingIndex > -1) selectedItems.splice(existingIndex, 1);
104
+ else if (props.multiselect) {
105
+ selectedItems.push(getValue(option));
106
+ } else {
107
+ selectedItems.splice(0, selectedItems.length, getValue(option));
108
+ dropdown?.hide();
109
+ }
110
+ emitUpdate();
110
111
  };
111
112
 
112
113
  function emitUpdate() {
113
- if (props.multiselect) {
114
- emit('update:modelValue', selectedItems);
115
- } else {
116
- selectedItems.splice(1, selectedItems.length);
117
- emit('update:modelValue', selectedItems[0]);
118
- }
114
+ if (props.multiselect) {
115
+ emit('update:modelValue', selectedItems);
116
+ } else {
117
+ selectedItems.splice(1, selectedItems.length);
118
+ emit('update:modelValue', selectedItems[0]);
119
+ }
119
120
  }
120
121
 
121
122
  function compareArrays(arr1: Option[], arr2: Option[]) {
122
- const isSame = arr1.every((item: Option) => arr2.map((a) => getValue(a)).includes(getValue(item)));
123
- return isSame;
123
+ const isSame = arr1.every((item: Option) => arr2.map((a) => getValue(a)).includes(getValue(item)));
124
+ return isSame;
124
125
  }
125
126
 
126
127
  watch(
127
- () => props.modelValue,
128
- (newVal: Option | Option[]) => {
129
- if (!newVal) return;
130
- if (!props.multiselect) {
131
- if (!isSelected(newVal)) selectedItems.splice(0, selectedItems.length, newVal);
132
- } else {
133
- const isSame = compareArrays([newVal].flat(), selectedItems);
134
- if (!isSame) selectedItems.splice(0, selectedItems.length, [newVal].flat());
135
- }
136
- },
137
- { immediate: true },
128
+ () => props.modelValue,
129
+ (newVal: Option | Option[]) => {
130
+ if (!newVal) return;
131
+ if (!props.multiselect) {
132
+ if (!isSelected(newVal)) selectedItems.splice(0, selectedItems.length, newVal);
133
+ } else {
134
+ const isSame = compareArrays([newVal].flat(), selectedItems);
135
+ if (!isSame) selectedItems.splice(0, selectedItems.length, [newVal].flat());
136
+ }
137
+ },
138
+ { immediate: true },
138
139
  );
139
140
  </script>
140
141
 
141
142
  <style scoped>
142
143
  .selectinput {
143
- width: 100%;
144
+ width: 100%;
144
145
  }
145
146
 
146
147
  .selectinput-option {
147
- padding: 6px 12px;
148
- cursor: pointer;
149
- border-radius: 5px;
150
- transition: all 0.2s;
151
- display: grid;
152
- grid-template-columns: 10px 1fr;
153
- justify-content: space-between;
154
- width: 100%;
155
- font-size: var(--input-font-size);
148
+ padding: 6px 12px;
149
+ cursor: pointer;
150
+ border-radius: 5px;
151
+ transition: all 0.2s;
152
+ display: grid;
153
+ grid-template-columns: 10px 1fr;
154
+ justify-content: space-between;
155
+ width: 100%;
156
+ font-size: var(--input-font-size);
156
157
  }
157
158
 
158
159
  .selectinput-options {
159
- max-height: 300px;
160
- overflow-y: auto;
160
+ max-height: 300px;
161
+ overflow-y: auto;
161
162
  }
162
163
 
163
164
  .selectinput-option:hover {
164
- background: var(--bgl-gray-20);
165
+ background: var(--bgl-gray-20);
165
166
  }
166
167
  </style>
167
168
 
168
169
  <style>
169
170
  .bagel-input label {
170
- font-size: var(--label-font-size);
171
+ font-size: var(--label-font-size);
171
172
  }
172
173
 
173
174
  .selectinput-btn {
174
- display: flex;
175
- justify-content: space-between;
176
- align-items: center;
177
- height: var(--input-height);
178
- border-radius: var(--input-border-radius);
179
- border: none;
180
- background: var(--input-bg);
181
- padding: 0.7rem;
182
- color: var(--input-color);
183
- width: 100%;
184
- font-family: inherit;
175
+ display: flex;
176
+ justify-content: space-between;
177
+ align-items: center;
178
+ height: var(--input-height);
179
+ border-radius: var(--input-border-radius);
180
+ border: none;
181
+ background: var(--input-bg);
182
+ padding: 0.7rem;
183
+ color: var(--input-color);
184
+ width: 100%;
185
+ font-family: inherit;
185
186
  }
186
187
 
187
188
  .selectinput-btn:disabled {
188
- background: var(--input-disabled-bg);
189
- color: var(--input-disabled-color);
189
+ background: var(--input-disabled-bg);
190
+ color: var(--input-disabled-color);
190
191
  }
191
192
 
192
193
  .selectinput-btn:focus {
193
- outline: none;
194
- box-shadow: inset 0 0 10px #00000012;
194
+ outline: none;
195
+ box-shadow: inset 0 0 10px #00000012;
195
196
  }
196
197
 
197
198
  .v-popper__arrow-container {
198
- display: none;
199
+ display: none;
199
200
  }
200
201
 
201
202
  .v-popper--theme-dropdown .v-popper__inner {
202
- border: none;
203
- background: transparent;
204
- border-radius: var(--card-border-radius);
203
+ border: none;
204
+ background: transparent;
205
+ border-radius: var(--card-border-radius);
205
206
  }
206
207
  </style>
@@ -2,7 +2,6 @@ export { default as CheckInput } from './CheckInput.vue';
2
2
  export { default as DateInput } from './DateInput.vue';
3
3
  export { default as JSONInput } from './JSONInput.vue';
4
4
  export { default as SelectInput } from './SelectInput.vue';
5
- export { default as RichTextEditor } from './RichTextEditor.vue';
6
5
  export { default as TableField } from './TableField.vue';
7
6
  export { default as TextInput } from './TextInput.vue';
8
7
  export { default as Checkbox } from './Checkbox.vue';
@@ -11,3 +10,4 @@ export { default as DatePicker } from './DatePicker.vue';
11
10
  export { default as RadioPillsInput } from './RadioPillsInput.vue';
12
11
  export { default as FileUpload } from './FileUpload.vue';
13
12
  export { default as ToggleInput } from './ToggleInput.vue';
13
+ export { default as RichText } from './RichText.vue';
@@ -1,4 +1,3 @@
1
- export { default as RTXEditor } from './RTXEditor.vue';
2
1
  export { default as MaterialIcon } from './MaterialIcon.vue';
3
2
  export { default as Icon } from './MaterialIcon.vue';
4
3
  export { default as NavBar } from './NavBar.vue';
@@ -8,7 +7,6 @@ export { default as ModalForm } from './ModalForm.vue';
8
7
  export { default as AccordionItem } from './AccordionItem.vue';
9
8
  export { default as ListView } from './ListView.vue';
10
9
  export { default as ListItem } from './ListItem.vue';
11
- export { default as Comments } from './Comments.vue';
12
10
  export { default as PageTitle } from './PageTitle.vue';
13
11
  export { default as TableSchema } from './TableSchema.vue';
14
12
  export { default as TopBar } from './TopBar.vue';
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <Card
3
+ class="hide m_grid gap-05 bgl_bottombar px-1 txt14 justify-content-start align-items-center
4
+ overflow-x"
5
+ >
6
+ <slot name="brand" />
7
+ <Btn @click="nav.onClick" :to="nav.to" v-for="(nav, i) in navLinks" :key="i"
8
+ class="m_h-auto">
9
+ <Icon :icon="nav.icon" :size="1.4" class="m-0" />
10
+ <p class="m-0 pb-025 txt14 line-height-1">
11
+ {{ nav.label }}
12
+ </p>
13
+ </Btn>
14
+ </Card>
15
+ </template>
16
+
17
+ <script lang="ts" setup>
18
+ import {
19
+ Icon, Btn, type NavLink, Card,
20
+ } from '@bagelink/vue';
21
+
22
+ defineProps<{
23
+ navLinks: NavLink[];
24
+ }>();
25
+ </script>
26
+
27
+ <style>
28
+ .bgl_bottombar .bgl_btn-flex{
29
+ flex-direction: column;
30
+ height: 60px;
31
+ gap: 0;
32
+ }
33
+
34
+ </style>
35
+ <style scoped>
36
+ .bgl_bottombar {
37
+ background-color: var(--bgl-primary);
38
+ color: var(--bgl-white);
39
+ grid-template-columns: repeat(auto-fill, var(--bgl_bottombar-btn-width));
40
+ grid-auto-flow: column;
41
+ border-radius: 0;
42
+ padding: 0;
43
+ --bgl_bottombar-btn-width: 62px;
44
+ }
45
+
46
+
47
+ .bgl_bottombar>* {
48
+ width: var(--bgl_bottombar-btn-width);
49
+ }
50
+
51
+ .bgl_bottombar::-webkit-scrollbar {
52
+ display: none;
53
+ }
54
+
55
+ .bgl_bottombar .nav-button {
56
+ border-radius: var(--card-border-radius);
57
+
58
+ }
59
+
60
+ .bgl_bottombar .router-link-active {
61
+ background: var(--bgl-white);
62
+ color: var(--bgl-primary) !important;
63
+ }
64
+ </style>
@@ -51,7 +51,8 @@ function toggleMenu() {
51
51
  }
52
52
 
53
53
  .nav-button.router-link-active {
54
- background-color: var(--bgl-primary-tint) !important;
54
+ background: var(--bgl-white) !important;
55
+ color: var(--bgl-primary);
55
56
  }
56
57
  </style>
57
58
 
@@ -1,8 +1,8 @@
1
1
  <template>
2
- <TabsNav :tabs="tabs" :group="group" />
3
- <div v-if="currentTab">
4
- <slot :name="currentTab" />
5
- </div>
2
+ <TabsNav :tabs="tabs" :group="group" class="mb-05" />
3
+ <div v-if="currentTab">
4
+ <slot :name="currentTab" />
5
+ </div>
6
6
  </template>
7
7
 
8
8
  <script setup lang="ts">