@bagelink/vue 1.4.161 → 1.4.165

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.4.161",
4
+ "version": "1.4.165",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -61,7 +61,6 @@ const maxWidth = $computed(() => {
61
61
  const isOverlay = $computed(() => props.closePlacement === 'overlay' || props.closePlacement === 'overlay-end')
62
62
  const isHeader = $computed(() => props.closePlacement === 'header' || props.closePlacement === 'header-end')
63
63
  const isFooter = $computed(() => props.closePlacement === 'footer')
64
- const isNone = $computed(() => props.closePlacement === 'none')
65
64
 
66
65
  const overlayCloseClass = $computed(() => {
67
66
  if (props.closePlacement === 'overlay-end') return 'top-1 end-1'
@@ -75,7 +74,7 @@ function closeModal() {
75
74
 
76
75
  defineExpose({ closeModal })
77
76
 
78
- const escapeKeyClose = (e: KeyboardEvent) => {
77
+ function escapeKeyClose(e: KeyboardEvent) {
79
78
  if (props.dismissable && e.key === 'Escape') {
80
79
  closeModal()
81
80
  }
@@ -93,45 +92,80 @@ onUnmounted(() => {
93
92
  </script>
94
93
 
95
94
  <template>
96
- <div class="bg-dark" :style="{ zIndex }" :class="{ 'is-side': side, 'is-active': isVisible, 'bg-lignt': false }" @click="() => (dismissable ? closeModal() : '')" @keydown.esc="closeModal">
97
- <!-- Overlay close button -->
98
- <Btn v-if="dismissable && isOverlay" icon="close" icon-mobile-size="1.4" class="fixed" :class="overlayCloseClass" @click="closeModal" />
99
-
100
- <Card class="modal m_pt-0" :style="{ ...maxWidth, '--bgl-box-bg': 'var(--bgl-popup-bg)' }" :thin="thin" @click.stop
101
- :class="{ 'pt-0': thin, 'pt-1': !thin, 'm_mt-5': isOverlay, 'display-flex column': side }">
102
- <header v-if="slots.toolbar || title" class="tool-bar w-100p flex space-between sticky z-3 py-1">
103
- <!-- Header close button -->
104
- <Btn v-if="dismissable && isHeader && closePlacement === 'header'" :style="{ float: side ? '' : '' }" flat icon="close" thin icon-mobile-size="1.4" @click="closeModal" />
105
- <slot name="toolbar" />
106
- <Title v-if="title" class="modal-title txt-center txt20 medium my-0 w-100p ellipsis-1" tag="h3" :label="title"
107
- :class="{ 'me-1-5': isHeader && dismissable && closePlacement === 'header', 'ms-1-5': isHeader && dismissable && closePlacement === 'header-end' }" />
108
- <!-- Header-end close button -->
109
- <Btn v-if="dismissable && isHeader && closePlacement === 'header-end'" :style="{ float: side ? '' : '' }" flat icon="close" thin icon-mobile-size="1.4" @click="closeModal" />
95
+ <div
96
+ class="bg-dark" :style="{ zIndex }" :class="{ 'is-side': side, 'is-active': isVisible, 'bg-lignt': false }"
97
+ @click="() => (dismissable ? closeModal() : '')" @keydown.esc="closeModal"
98
+ >
99
+ <!-- Overlay close button -->
100
+ <Btn
101
+ v-if="dismissable && isOverlay" icon="close" icon-mobile-size="1.4" class="fixed"
102
+ :class="overlayCloseClass" @click="closeModal"
103
+ />
104
+
105
+ <Card
106
+ class="modal m_pt-0" :style="{ ...maxWidth, '--bgl-box-bg': 'var(--bgl-popup-bg)' }" :thin="thin"
107
+ :class="{ 'pt-0': thin, 'pt-1': !thin, 'm_mt-5': isOverlay, 'display-flex column': side }" @click.stop
108
+ >
109
+ <header v-if="slots.toolbar || title" class="tool-bar w-100p flex space-between sticky z-3 py-1">
110
+ <!-- Header close button -->
111
+ <Btn
112
+ v-if="dismissable && isHeader && closePlacement === 'header'" :style="{ float: side ? '' : '' }"
113
+ flat icon="close" thin icon-mobile-size="1.4" @click="closeModal"
114
+ />
115
+ <slot name="toolbar" />
116
+ <Title
117
+ v-if="title" class="modal-title txt-center txt20 medium my-0 w-100p ellipsis-1" tag="h3"
118
+ :label="title"
119
+ :class="{ 'me-1-5': isHeader && dismissable && closePlacement === 'header', 'ms-1-5': isHeader && dismissable && closePlacement === 'header-end' }"
120
+ />
121
+ <!-- Header-end close button -->
122
+ <Btn
123
+ v-if="dismissable && isHeader && closePlacement === 'header-end'"
124
+ :style="{ float: side ? '' : '' }" flat icon="close" thin icon-mobile-size="1.4"
125
+ @click="closeModal"
126
+ />
110
127
  </header>
111
-
112
- <header v-else class="tool-bar w-100p flex space-between sticky z-3" :class="{ 'py-1': !isOverlay, 'pt-1': isOverlay }">
128
+
129
+ <header
130
+ v-else class="tool-bar w-100p flex space-between sticky z-3"
131
+ :class="{ 'py-1': !isOverlay, 'pt-1': isOverlay }"
132
+ >
113
133
  <!-- Header close button (no title) -->
114
- <Btn v-if="dismissable && isHeader && closePlacement === 'header'" :style="{ float: side ? '' : '' }" flat icon="close" thin icon-mobile-size="1.4" @click="closeModal" />
134
+ <Btn
135
+ v-if="dismissable && isHeader && closePlacement === 'header'" :style="{ float: side ? '' : '' }"
136
+ flat icon="close" thin icon-mobile-size="1.4" @click="closeModal"
137
+ />
115
138
  <slot name="toolbar" />
116
139
  <!-- Header-end close button (no title) -->
117
- <Btn v-if="dismissable && isHeader && closePlacement === 'header-end'" :style="{ float: side ? '' : '' }" flat icon="close" thin icon-mobile-size="1.4" class="ms-auto" @click="closeModal" />
140
+ <Btn
141
+ v-if="dismissable && isHeader && closePlacement === 'header-end'"
142
+ :style="{ float: side ? '' : '' }" flat icon="close" thin icon-mobile-size="1.4" class="ms-auto"
143
+ @click="closeModal"
144
+ />
118
145
  </header>
119
-
146
+
120
147
  <slot />
121
- <footer v-if="slots.footer || actions?.length" class="modal-footer gap-1 flex space-between" :class="{ 'mt-1': !side, 'mt-auto': side }">
148
+ <footer
149
+ v-if="slots.footer || actions?.length" class="modal-footer gap-1 flex space-between"
150
+ :class="{ 'mt-1': !side, 'mt-auto': side }"
151
+ >
122
152
  <Btn v-for="(action, i) in actions" :key="i" color="gray" v-bind="action" @click="closeModal" />
123
153
  <slot name="footer" />
124
154
  <!-- Footer close button -->
125
155
  </footer>
126
- <Btn v-if="dismissable && isFooter" icon="close" label="Close" class="mx-auto absolute start-0 end-0 modalFooterBtn" @click="closeModal" />
127
- </Card>
128
- </div>
156
+ <Btn
157
+ v-if="dismissable && isFooter" icon="close" label="Close"
158
+ class="mx-auto absolute start-0 end-0 modalFooterBtn" @click="closeModal"
159
+ />
160
+ </Card>
161
+ </div>
129
162
  </template>
130
163
 
131
164
  <style>
132
165
  .modal {
133
166
  color: var(--bgl-popup-text);
134
167
  }
168
+
135
169
  .modal .bgl_btn.bgl_btn_flat {
136
170
  color: var(--bgl-popup-text) !important;
137
171
  }
@@ -210,7 +210,7 @@ function formatTooltip(item: any): string {
210
210
  </span>
211
211
  </div>
212
212
  </div>
213
- <div class="flex w-100p align-items-end mt-auto gap-075 ltr overflow justify-content-start">
213
+ <div class="flex w-100p align-items-end mt-auto gap-075 overflow justify-content-start" :class="[rtl ? 'rtl' : 'ltr']">
214
214
  <div
215
215
  v-for="(bar, index) in chartData"
216
216
  :key="index"
@@ -232,7 +232,8 @@ function formatTooltip(item: any): string {
232
232
  />
233
233
  <span
234
234
  v-if="chartData.length <= 15 || index % Math.ceil(chartData.length / 8) === 0"
235
- class="txt-9 block line-height-1 -bottom-075 white-space color-gray absolute rtl"
235
+ class="txt-9 block line-height-1 -bottom-075 white-space color-gray absolute"
236
+ :class="rtl ? 'rtl' : 'ltr'"
236
237
  >
237
238
  {{ bar.displayLabel }}
238
239
  </span>
@@ -147,8 +147,8 @@ onMounted(() => { emit('ready', state.value) })
147
147
  @event-click="handleEventClick" @event-create="handleEventCreate" @event-update="handleEventUpdate"
148
148
  @event-delete="handleEventDelete" @date-change="handleDateChange" @open-popover="openPopover"
149
149
  >
150
- <template #eventContent="{ event }">
151
- <slot name="eventContent" :event="event" />
150
+ <template #eventContent="{ event, close }">
151
+ <slot name="eventContent" :event="event" :close="close" />
152
152
  </template>
153
153
  </component>
154
154
 
@@ -157,8 +157,8 @@ onMounted(() => { emit('ready', state.value) })
157
157
  :event="activeEvent" :position="popoverPosition" :show="showPopover"
158
158
  :has-event-content-slot="!!$slots.eventContent" @close="closePopover" @event-click="handleEventClick"
159
159
  >
160
- <template #eventContent="{ event }">
161
- <slot name="eventContent" :event="event" />
160
+ <template #eventContent="{ event, close }">
161
+ <slot name="eventContent" :event="event" :close="close" />
162
162
  </template>
163
163
  </CalendarPopover>
164
164
  </div>
@@ -0,0 +1,72 @@
1
+ <script setup lang="ts">
2
+ import { Btn, Icon } from '@bagelink/vue'
3
+
4
+ interface Option {
5
+ label: string
6
+ value: string | number
7
+ icon?: string
8
+ }
9
+
10
+ interface Props {
11
+ options: Option[]
12
+ thin?: boolean
13
+ outline?: boolean
14
+ multiselect?: boolean
15
+ }
16
+
17
+ const props = withDefaults(defineProps<Props>(), { multiselect: false })
18
+
19
+ // When multiselect is true: array, when false: single value or null
20
+ const selected = defineModel<string | number | (string | number)[] | null>('modelValue', { default: null })
21
+
22
+ function toggleOption(value: string | number) {
23
+ if (props.multiselect) {
24
+ // Multiselect mode - work with arrays
25
+ const currentValue = Array.isArray(selected.value) ? selected.value : []
26
+ const index = currentValue.indexOf(value)
27
+ if (index > -1) {
28
+ selected.value = currentValue.filter(v => v !== value)
29
+ } else {
30
+ selected.value = [...currentValue, value]
31
+ }
32
+ } else {
33
+ // Single select mode - work with single values
34
+ if (selected.value === value) {
35
+ selected.value = null
36
+ } else {
37
+ selected.value = value
38
+ }
39
+ }
40
+ }
41
+
42
+ function isSelected(value: string | number) {
43
+ if (Array.isArray(selected.value)) {
44
+ return selected.value.includes(value)
45
+ }
46
+ return selected.value === value
47
+ }
48
+ </script>
49
+
50
+ <template>
51
+ <div class="flex flex-wrap gap-05 SelectBtn">
52
+ <Btn
53
+ v-for="option in options"
54
+ :key="option.value"
55
+ :thin="thin"
56
+ :outline="outline"
57
+ :class="isSelected(option.value) ? 'primary' : 'bg-transparent color-black'"
58
+ type="button"
59
+ class="border px-075 radius-2"
60
+ @click="toggleOption(option.value)"
61
+ >
62
+ <Icon v-if="option.icon" :name="option.icon" weight="300" />
63
+ <p>{{ option.label }}</p>
64
+ </Btn>
65
+ </div>
66
+ </template>
67
+
68
+ <style scoped>
69
+ .SelectBtn {
70
+ --btn-height: 30px;
71
+ }
72
+ </style>
@@ -5,10 +5,12 @@ import { watch, ref } from 'vue'
5
5
 
6
6
  import { useFileUpload } from './useFileUpload'
7
7
 
8
- const props = withDefaults(defineProps<UploadInputProps>(), {
8
+ const props = withDefaults(defineProps<UploadInputProps & { showIcon?: boolean; icon?: string }>(), {
9
9
  height: '215px',
10
10
  theme: 'dropzone',
11
11
  accept: '*',
12
+ showIcon: true,
13
+ icon: 'upload_2',
12
14
  })
13
15
 
14
16
  const emit = defineEmits(['update:modelValue', 'addFileStart'])
@@ -160,7 +162,7 @@ function fileName(pathKey: string) {
160
162
 
161
163
  <slot v-if="(!pathKeys.length && !fileQueue.length) || multiple" name="placeholder" :files="pathKeys" :fileQueue :browse>
162
164
  <p class="p-1 flex column hover fileUploadPlaceHolder justify-content-center mb-05 ">
163
- <Icon icon="upload_2" class="user-select-none" />
165
+ <Icon v-if="showIcon" :name="icon" class="user-select-none" />
164
166
  <span class=" pretty balance user-select-none ">
165
167
  {{ dropPlaceholder || 'Drag and Drop files here or click to upload' }}
166
168
  </span>
@@ -13,6 +13,7 @@ export { default as RadioGroup } from './RadioGroup.vue'
13
13
  export { default as RadioPillsInput } from './RadioPillsInput.vue'
14
14
  export { default as RangeInput } from './RangeInput.vue'
15
15
  export { default as RichText } from './RichText/index.vue'
16
+ export { default as SelectBtn } from './SelectBtn.vue'
16
17
  export { default as SelectInput } from './SelectInput.vue'
17
18
  export { default as SignaturePad } from './SignaturePad.vue'
18
19
  export { default as TableField } from './TableField.vue'
@@ -1,8 +1,8 @@
1
1
  <script lang="ts" setup>
2
+ import type { NavLink } from '@bagelink/vue'
3
+ import { Btn, Icon } from '@bagelink/vue'
2
4
  import { inject, computed, ref, watch } from 'vue'
3
5
  import { useRoute } from 'vue-router'
4
- import { Btn, Icon } from '@bagelink/vue'
5
- import type { NavLink } from '@bagelink/vue'
6
6
 
7
7
  // Extended interface for footer links that can have actions
8
8
  interface FooterLink extends NavLink {
@@ -82,47 +82,38 @@ function logout() {
82
82
 
83
83
  <template>
84
84
  <aside
85
- class="app-sidebar transition-400 fixed inset h-100vh z-99"
86
- :class="{
85
+ class="app-sidebar transition-400 fixed start top bottom h-100vh z-99" :class="{
87
86
  'sidebar-mobile-open': menuState.isMobile.value && menuState.isOpen.value,
88
- 'sidebar-mobile-closed':
89
- menuState.isMobile.value && !menuState.isOpen.value,
90
- transitioning: isTransitioning,
91
- 'p-05': props.card,
92
- 'sidebar-collapsed': !menuState.isMobile.value && !menuState.isOpen.value,
93
- }"
94
- :style="sidebarStyles"
87
+ 'sidebar-mobile-closed':
88
+ menuState.isMobile.value && !menuState.isOpen.value,
89
+ 'transitioning': isTransitioning,
90
+ 'p-05': props.card,
91
+ 'sidebar-collapsed': !menuState.isMobile.value && !menuState.isOpen.value,
92
+ }" :style="sidebarStyles"
95
93
  >
96
94
  <div
97
95
  :style="{
98
96
  backgroundColor: props.bgColor,
99
97
  color: props.textColor,
100
- ...(props.card && { borderRadius: 'var(--card-border-radius)' }),
101
- }"
102
- :class="{
103
- 'card cardWrapSide': props.card,
104
- 'ps-05': !menuState.isOpen.value,
98
+ ...(props.card && { borderRadius: 'var(--card-border-radius)' }),
99
+ }" :class="{
100
+ 'card cardWrapSide': props.card,
101
+ 'ps-05': !menuState.isOpen.value,
105
102
  'scrollbar-gutter-both': menuState.isOpen.value,
106
- aside_frame: props.frame,
107
- }"
108
- class="overflow-hidden flex column flex-stretch gap-1 w100p pt-1 pb-05 h-100p"
103
+ 'aside_frame': props.frame,
104
+ }" class="overflow-hidden flex column flex-stretch gap-1 w100p pt-1 pb-05 h-100p"
109
105
  >
110
106
  <!-- Logo/Brand -->
111
107
  <router-link
112
- to="/"
113
- class="decoration-none flex px-05"
114
- :class="{
115
- 'gap-05': menuState.isOpen.value,
108
+ to="/" class="decoration-none flex px-05" :class="{
109
+ 'gap-05': menuState.isOpen.value,
116
110
  'gap-0': !menuState.isOpen.value,
117
111
  }"
118
112
  >
119
113
  <img
120
- v-if="props.logo"
121
- :src="props.logo"
122
- :alt="props.logoAlt"
123
- class="contain"
114
+ v-if="props.logo" :src="props.logo" :alt="props.logoAlt" class="contain"
124
115
  :style="{ height: props.logoHeight }"
125
- />
116
+ >
126
117
  <span class="nav-text">
127
118
  {{ props.name }}
128
119
  </span>
@@ -130,43 +121,52 @@ function logout() {
130
121
 
131
122
  <!-- Navigation Links -->
132
123
  <nav class="sidebar-nav flex column flex-stretch gap-025 align-items-start scrollbar-gutter-stable">
133
- <Btn v-for="link in props.navLinks" :key="link.to" :title="!menuState.isOpen.value && !menuState.isMobile.value
134
- ? link.label
135
- : ''
136
- " fullWidth alignTxt="start" class="flex-shrink-0 px-1" :class="{ 'nav-btn-active': route.path === link.to }" :style="{
137
- backgroundColor:
138
- route.path === link.to ? props.activeColor : props.bgColor,
139
- color: route.path === link.to ? 'white' : props.textColor,
140
- }" :to="link.to || '/'">
124
+ <Btn
125
+ v-for="link in props.navLinks" :key="link.to" :title="!menuState.isOpen.value && !menuState.isMobile.value
126
+ ? link.label
127
+ : ''
128
+ " fullWidth alignTxt="start" class="flex-shrink-0 px-1" :class="{ 'nav-btn-active': route.path === link.to }"
129
+ :style="{
130
+ backgroundColor:
131
+ route.path === link.to ? props.activeColor : props.bgColor,
132
+ color: route.path === link.to ? 'white' : props.textColor,
133
+ }" :to="link.to || '/'"
134
+ >
141
135
  <Icon :name="link.icon" size="1.2" />
142
136
  <span class="nav-text">
143
137
  {{ link.label }}
144
138
  </span>
145
139
  </Btn>
146
- </nav>
147
- <!-- Footer -->
148
- <div class="sidebar-footer flex column flex-stretch gap-025 align-items-start mt-auto scrollbar-gutter-stable">
149
- <!-- Footer Links -->
150
- <Btn v-for="link in props.footerLinks" :key="link.to || link.label" :title="!menuState.isOpen.value && !menuState.isMobile.value
140
+ </nav>
141
+ <!-- Footer -->
142
+ <div
143
+ class="sidebar-footer flex column flex-stretch gap-025 align-items-start mt-auto scrollbar-gutter-stable"
144
+ >
145
+ <!-- Footer Links -->
146
+ <Btn
147
+ v-for="link in props.footerLinks" :key="link.to || link.label" :title="!menuState.isOpen.value && !menuState.isMobile.value
151
148
  ? link.label
152
149
  : ''
153
- " alignTxt="start" fullWidth flat :icon="link.icon" class="flex-shrink-0 px-1" :to="link.to" @click="link.action">
154
- <span class="nav-text">
155
- {{ link.label }}
156
- </span>
157
- </Btn>
158
-
159
- <!-- Default Logout Button if no footer links provided -->
160
- <Btn v-if="props.footerLinks.length === 0" :title="!menuState.isOpen.value && !menuState.isMobile.value ? 'Logout' : ''
161
- " alignTxt="start" fullWidth flat icon="logout" class="flex-shrink-0 px-1" @click="logout">
162
- <span class="nav-text"> Logout </span>
163
- </Btn>
164
-
165
- <!-- Custom Footer Content Slot -->
166
- <slot name="footer" />
167
- </div>
168
- </div>
169
- </aside>
150
+ " alignTxt="start" fullWidth flat :icon="link.icon" class="flex-shrink-0 px-1" :to="link.to" @click="link.action"
151
+ >
152
+ <span class="nav-text">
153
+ {{ link.label }}
154
+ </span>
155
+ </Btn>
156
+
157
+ <!-- Default Logout Button if no footer links provided -->
158
+ <Btn
159
+ v-if="props.footerLinks.length === 0" :title="!menuState.isOpen.value && !menuState.isMobile.value ? 'Logout' : ''
160
+ " alignTxt="start" fullWidth flat icon="logout" class="flex-shrink-0 px-1" @click="logout"
161
+ >
162
+ <span class="nav-text"> Logout </span>
163
+ </Btn>
164
+
165
+ <!-- Custom Footer Content Slot -->
166
+ <slot name="footer" />
167
+ </div>
168
+ </div>
169
+ </aside>
170
170
  </template>
171
171
 
172
172
  <style>
@@ -189,7 +189,6 @@ function logout() {
189
189
  overflow-y: auto;
190
190
  flex: 1;
191
191
  }
192
-
193
192
  /* הסתרת גלילה בזמן שינוי גודל */
194
193
  .app-sidebar.transitioning .sidebar-nav {
195
194
  scrollbar-width: none;
@@ -267,8 +266,10 @@ function logout() {
267
266
  .sidebar-mobile-closed {
268
267
  transform: translateX(-100%);
269
268
  }
270
- [dir="rtl"] .sidebar-mobile-closed {
271
- transform: translateX(100%);
272
- }
269
+
270
+ [dir="rtl"] .sidebar-mobile-closed,
271
+ .rtl .sidebar-mobile-closed {
272
+ transform: translateX(100%);
273
+ }
273
274
  }
274
275
  </style>