@bagelink/vue 1.4.141 → 1.4.145

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 (70) hide show
  1. package/dist/components/Btn.vue.d.ts.map +1 -1
  2. package/dist/components/Carousel.vue.d.ts +1 -1
  3. package/dist/components/Modal.vue.d.ts +3 -0
  4. package/dist/components/Modal.vue.d.ts.map +1 -1
  5. package/dist/components/Slider.vue.d.ts +1 -1
  6. package/dist/components/Slider.vue.d.ts.map +1 -1
  7. package/dist/components/analytics/BarChart.vue.d.ts +11 -3
  8. package/dist/components/analytics/BarChart.vue.d.ts.map +1 -1
  9. package/dist/components/analytics/LineChart.vue.d.ts +9 -0
  10. package/dist/components/analytics/LineChart.vue.d.ts.map +1 -1
  11. package/dist/components/analytics/PieChart.vue.d.ts +30 -2
  12. package/dist/components/analytics/PieChart.vue.d.ts.map +1 -1
  13. package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts +8 -0
  14. package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
  15. package/dist/components/form/inputs/RichText/components/TableGridSelector.vue.d.ts +9 -0
  16. package/dist/components/form/inputs/RichText/components/TableGridSelector.vue.d.ts.map +1 -0
  17. package/dist/components/form/inputs/RichText/composables/useCommands.d.ts.map +1 -1
  18. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts +0 -14
  19. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
  20. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts.map +1 -1
  21. package/dist/components/form/inputs/RichText/config.d.ts.map +1 -1
  22. package/dist/components/form/inputs/RichText/index.vue.d.ts +15 -15
  23. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  24. package/dist/components/form/inputs/RichText/richTextTypes.d.ts +1 -3
  25. package/dist/components/form/inputs/RichText/richTextTypes.d.ts.map +1 -1
  26. package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
  27. package/dist/components/form/inputs/RichText/utils/media-clean.d.ts +2 -0
  28. package/dist/components/form/inputs/RichText/utils/media-clean.d.ts.map +1 -0
  29. package/dist/components/form/inputs/RichText/utils/media.d.ts +4 -4
  30. package/dist/components/form/inputs/RichText/utils/media.d.ts.map +1 -1
  31. package/dist/components/form/inputs/RichText/utils/selection.d.ts.map +1 -1
  32. package/dist/components/form/inputs/RichText/utils/table.d.ts +1 -1
  33. package/dist/components/form/inputs/RichText/utils/table.d.ts.map +1 -1
  34. package/dist/components/index.d.ts +1 -0
  35. package/dist/components/index.d.ts.map +1 -1
  36. package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
  37. package/dist/components/layout/AppLayout.vue.d.ts.map +1 -1
  38. package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
  39. package/dist/index.cjs +123 -22
  40. package/dist/index.mjs +123 -22
  41. package/dist/style.css +1 -1
  42. package/package.json +1 -1
  43. package/src/components/Btn.vue +50 -42
  44. package/src/components/Modal.vue +49 -50
  45. package/src/components/analytics/BarChart.vue +118 -7
  46. package/src/components/analytics/KpiCard.vue +2 -2
  47. package/src/components/analytics/LineChart.vue +189 -105
  48. package/src/components/analytics/PieChart.vue +392 -49
  49. package/src/components/form/inputs/RichText/CheckList.md +23 -0
  50. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +243 -38
  51. package/src/components/form/inputs/RichText/components/TableGridSelector.vue +94 -0
  52. package/src/components/form/inputs/RichText/composables/useCommands.ts +4 -1
  53. package/src/components/form/inputs/RichText/composables/useEditor.ts +6 -6
  54. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +1 -0
  55. package/src/components/form/inputs/RichText/config.ts +23 -11
  56. package/src/components/form/inputs/RichText/editor.css +300 -33
  57. package/src/components/form/inputs/RichText/index.vue +3014 -75
  58. package/src/components/form/inputs/RichText/richTextTypes.ts +2 -3
  59. package/src/components/form/inputs/RichText/utils/commands.ts +279 -50
  60. package/src/components/form/inputs/RichText/utils/media-clean.ts +0 -0
  61. package/src/components/form/inputs/RichText/utils/media.ts +133 -67
  62. package/src/components/form/inputs/RichText/utils/selection.ts +10 -2
  63. package/src/components/form/inputs/RichText/utils/table.ts +1 -1
  64. package/src/components/index.ts +1 -0
  65. package/src/components/layout/AppContent.vue +26 -26
  66. package/src/components/layout/AppLayout.vue +21 -3
  67. package/src/components/layout/AppSidebar.vue +5 -2
  68. package/src/styles/layout.css +267 -0
  69. package/src/styles/mobilLayout.css +266 -0
  70. package/src/styles/modal.css +3 -17
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
 
3
- import { computed, onMounted, ref } from 'vue'
3
+ import { computed, onMounted, onUnmounted, ref } from 'vue'
4
4
  import { Icon } from '@bagelink/vue'
5
5
 
6
6
  interface DataPoint {
@@ -17,6 +17,10 @@ interface Props {
17
17
  height?: number
18
18
  showPoints?: boolean
19
19
  currency?: boolean
20
+ animated?: boolean
21
+ animationDuration?: number
22
+ animationStartDelay?: number
23
+ percentageChange?: number
20
24
  }
21
25
 
22
26
  const props = withDefaults(defineProps<Props>(), {
@@ -25,13 +29,25 @@ const props = withDefaults(defineProps<Props>(), {
25
29
  color: 'var(--bgl-primary)',
26
30
  height: 200,
27
31
  showPoints: true,
28
- currency: false
32
+ currency: false,
33
+ animated: true,
34
+ animationDuration: 1500,
35
+ animationStartDelay: 0,
36
+ percentageChange: 0
29
37
  })
30
38
 
31
39
  const svgRef = ref<SVGElement>()
40
+ const chartRef = ref<HTMLElement>()
32
41
  const width = ref(600)
33
42
  const height = ref(props.height)
34
43
 
44
+ // Animation state
45
+ const animatedProgress = ref(0)
46
+ const isAnimating = ref(false)
47
+ const isInView = ref(false)
48
+
49
+ let observer: IntersectionObserver | null = null
50
+
35
51
  const padding = { top: 20, inline_end: 30, bottom: 25, inline_start: 60 }
36
52
  const chartWidth = computed(() => width.value - padding.inline_start - padding.inline_end)
37
53
  const chartHeight = computed(() => height.value - padding.top - padding.bottom)
@@ -79,13 +95,29 @@ const yScale = computed(() => {
79
95
  const pathData = computed(() => {
80
96
  if (props.data.length === 0) return ''
81
97
 
82
- const points = props.data.map((d, i) =>
98
+ // Calculate how many points to show based on animation progress
99
+ const totalPoints = props.data.length
100
+ const visiblePoints = props.animated ?
101
+ Math.ceil(totalPoints * animatedProgress.value) :
102
+ totalPoints
103
+
104
+ const dataToShow = props.data.slice(0, Math.max(1, visiblePoints))
105
+
106
+ const points = dataToShow.map((d, i) =>
83
107
  `${i === 0 ? 'M' : 'L'} ${paddingLeft.value + xScale.value(i)} ${padding.top + yScale.value(d.value)}`
84
108
  ).join(' ')
85
109
 
86
110
  return points
87
111
  })
88
112
 
113
+ const visiblePoints = computed(() => {
114
+ if (!props.animated) return props.data
115
+
116
+ const totalPoints = props.data.length
117
+ const pointsToShow = Math.ceil(totalPoints * animatedProgress.value)
118
+ return props.data.slice(0, Math.max(1, pointsToShow))
119
+ })
120
+
89
121
  const gridLines = computed(() => {
90
122
  const lines = []
91
123
  const step = chartHeight.value / 4
@@ -113,135 +145,170 @@ function formatDate(dateStr: string): string {
113
145
  return date.toLocaleDateString('he-IL', { month: 'short', day: 'numeric' })
114
146
  }
115
147
 
148
+ function formatTooltip(point: any): string {
149
+ const tooltipLines = [
150
+ `${formatDate(point.date)}`,
151
+ `<b>${formatValue(point.value)}</b>`
152
+ ]
153
+ if (point.label) {
154
+ tooltipLines.push(`<b>${point.label}</b>`)
155
+ }
156
+ return `<div class="lineTooltip">${tooltipLines.join('<p>')}</div>`
157
+ }
158
+
159
+ const setupIntersectionObserver = () => {
160
+ if (typeof window === 'undefined') return
161
+
162
+ observer = new IntersectionObserver(
163
+ (entries) => {
164
+ entries.forEach((entry) => {
165
+ if (entry.isIntersecting && !isInView.value) {
166
+ isInView.value = true
167
+ setTimeout(() => {
168
+ startAnimation()
169
+ }, 100 + props.animationStartDelay)
170
+ }
171
+ })
172
+ },
173
+ {
174
+ threshold: 0.3,
175
+ rootMargin: '50px'
176
+ }
177
+ )
178
+
179
+ if (chartRef.value) {
180
+ observer.observe(chartRef.value)
181
+ } else {
182
+ setTimeout(() => {
183
+ if (chartRef.value && observer) {
184
+ observer.observe(chartRef.value)
185
+ }
186
+ }, 100)
187
+ }
188
+ }
189
+
190
+ const startAnimation = () => {
191
+ console.log(`Starting LineChart animation for "${props.title}" (duration: ${props.animationDuration}ms, start delay: ${props.animationStartDelay}ms)`)
192
+ isAnimating.value = true
193
+ animatedProgress.value = 0
194
+
195
+ const startTime = Date.now()
196
+
197
+ const animate = () => {
198
+ const elapsed = Date.now() - startTime
199
+ const progress = Math.min(elapsed / props.animationDuration, 1)
200
+
201
+ animatedProgress.value = easeOutCubic(progress)
202
+
203
+ if (progress < 1) {
204
+ requestAnimationFrame(animate)
205
+ } else {
206
+ isAnimating.value = false
207
+ console.log(`LineChart animation completed for "${props.title}"`)
208
+ }
209
+ }
210
+
211
+ requestAnimationFrame(animate)
212
+ }
213
+
214
+ const easeOutCubic = (t: number): number => {
215
+ return 1 - Math.pow(1 - t, 3)
216
+ }
217
+
116
218
  onMounted(() => {
117
219
  if (svgRef.value) {
118
220
  width.value = svgRef.value.clientWidth || 600
119
221
  }
222
+
223
+ if (props.animated) {
224
+ setupIntersectionObserver()
225
+ } else {
226
+ animatedProgress.value = 1
227
+ }
228
+ })
229
+
230
+ onUnmounted(() => {
231
+ if (observer) {
232
+ observer.disconnect()
233
+ }
120
234
  })
121
235
  </script>
122
236
 
123
237
  <template>
124
- <div class="line-chart h-100p flex column flex-stretch">
125
- <div class="flex space-between">
126
- <div class="flex align-center gap-05 pb-1">
127
- <Icon :name="icon" size="1.2" :color="color" class="line-height-08" />
238
+ <div ref="chartRef" class="line-chart h-100p flex column flex-stretch">
239
+ <div class="flex space-between pb-1">
240
+ <div class="flex align-center gap-05">
241
+ <Icon :name="icon" size="1.2" :color="color" class="line-height-0" />
128
242
  <p class="white-space light m_txt14">
129
243
  {{ title }}
130
244
  </p>
131
245
  </div>
132
- </div>
133
- <div class="chart-container flex-grow w-100p relative">
134
- <svg
135
- ref="svgRef"
136
- :width="width"
137
- :height="height"
138
- class="chart-svg h-100p w-100p"
139
- >
140
- <!-- Grid lines -->
141
- <g class="grid">
142
- <line
143
- v-for="line in gridLines"
144
- :key="line.y"
145
- :x1="paddingLeft"
146
- :y1="padding.top + line.y"
147
- :x2="paddingLeft + chartWidth"
148
- :y2="padding.top + line.y"
149
- stroke="#e0e0e0"
150
- stroke-width="1"
151
- />
152
- <!-- Y-axis labels -->
153
- <text
154
- v-for="line in gridLines"
155
- :key="`label-${line.y}`"
156
- :x="labelXPosition"
157
- :y="padding.top + line.y + 4"
158
- class="grid-label"
159
- :text-anchor="labelTextAnchor"
160
- >
161
- {{ formatValue(line.value) }}
162
- </text>
163
- </g>
164
-
165
- <!-- X-axis -->
166
- <line
167
- :x1="paddingLeft"
168
- :y1="padding.top + chartHeight"
169
- :x2="paddingLeft + chartWidth"
170
- :y2="padding.top + chartHeight"
171
- stroke="#ccc"
172
- stroke-width="2"
173
- />
174
-
175
- <!-- Y-axis -->
176
- <line
177
- :x1="paddingLeft"
178
- :y1="padding.top"
179
- :x2="paddingLeft"
180
- :y2="padding.top + chartHeight"
181
- stroke="#ccc"
182
- stroke-width="2"
183
- />
184
-
185
- <!-- Line path -->
186
- <path
187
- :d="pathData"
188
- :stroke="color"
189
- stroke-width="3"
190
- fill="none"
191
- stroke-linecap="round"
192
- stroke-linejoin="round"
193
- />
194
-
195
- <!-- Data points -->
196
- <g v-if="showPoints">
197
- <circle
198
- v-for="(point, index) in data"
199
- :key="index"
200
- :cx="paddingLeft + xScale(index)"
201
- :cy="padding.top + yScale(point.value)"
202
- r="4"
203
- :fill="color"
204
- class="data-point"
205
- >
206
- <title>{{ formatDate(point.date) }}: {{ formatValue(point.value) }}</title>
207
- </circle>
208
- </g>
209
-
210
- <!-- X-axis labels -->
211
- <g class="x-labels">
212
- <text
213
- v-for="(point, index) in data.filter((_, i) => i % Math.ceil(data.length / 6) === 0)"
214
- :key="index"
215
- :x="paddingLeft + xScale(data.findIndex(d => d === point))"
216
- :y="padding.top + chartHeight + 15"
217
- class="axis-label"
218
- text-anchor="middle"
219
- >
220
- {{ formatDate(point.date) }}
221
- </text>
222
- </g>
223
- </svg>
224
- </div>
225
- </div>
246
+ <div v-if="percentageChange !== 0" class="flex align-center gap-025">
247
+ <Icon :name="percentageChange > 0 ? 'trending_up' : 'trending_down'" size="1" :class="percentageChange > 0 ? 'color-success' : 'color-danger'" />
248
+ <span class="txt12 bold" :class="percentageChange > 0 ? 'color-success' : 'color-danger'">
249
+ {{ Math.abs(percentageChange) }}%
250
+ </span>
251
+ </div>
252
+ </div>
253
+ <div class="chart-container flex-grow w-100p relative">
254
+ <svg ref="svgRef" :width="width" :height="height" class="chart-svg h-100p w-100p">
255
+ <!-- Grid lines -->
256
+ <g class="grid">
257
+ <line v-for="line in gridLines" :key="line.y" :x1="paddingLeft" :y1="padding.top + line.y" :x2="paddingLeft + chartWidth" :y2="padding.top + line.y" stroke="#e0e0e0" stroke-width="1" />
258
+ <!-- Y-axis labels -->
259
+ <text v-for="line in gridLines" :key="`label-${line.y}`" :x="labelXPosition" :y="padding.top + line.y + 4" class="grid-label" :text-anchor="labelTextAnchor">
260
+ {{ formatValue(line.value) }}
261
+ </text>
262
+ </g>
263
+
264
+ <!-- X-axis -->
265
+ <line :x1="paddingLeft" :y1="padding.top + chartHeight" :x2="paddingLeft + chartWidth" :y2="padding.top + chartHeight" stroke="#ccc" stroke-width="2" />
266
+
267
+ <!-- Y-axis -->
268
+ <line :x1="paddingLeft" :y1="padding.top" :x2="paddingLeft" :y2="padding.top + chartHeight" stroke="#ccc" stroke-width="2" />
269
+
270
+ <!-- Line path -->
271
+ <path :d="pathData" :stroke="color" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round" />
272
+
273
+ <!-- Data points -->
274
+ <g v-if="showPoints">
275
+ <circle v-for="(point, index) in visiblePoints" :key="index" v-tooltip="{ content: formatTooltip(point), html: true }" :cx="paddingLeft + xScale(index)"
276
+ :cy="padding.top + yScale(point.value)" r="4" :fill="color" class="data-point" />
277
+ </g>
278
+
279
+ <!-- X-axis labels -->
280
+ <g class="x-labels">
281
+ <text v-for="(point, index) in visiblePoints.filter((_, i) => i % Math.ceil(visiblePoints.length / 6) === 0)" :key="index"
282
+ :x="paddingLeft + xScale(visiblePoints.findIndex(d => d === point))" :y="padding.top + chartHeight + 15" class="axis-label" text-anchor="middle">
283
+ {{ formatDate(point.date) }}
284
+ </text>
285
+ </g>
286
+ </svg>
287
+ </div>
288
+ </div>
226
289
  </template>
227
290
 
228
291
  <style scoped>
229
- .line-chart, .chart-container {
292
+ .line-chart,
293
+ .chart-container {
230
294
  direction: inherit;
231
295
  }
232
296
 
233
297
  .chart-svg {
234
298
  transform-origin: center;
235
- display: block; /* Remove any inline spacing */
299
+ display: block;
300
+ /* Remove any inline spacing */
236
301
  }
237
302
 
238
303
  .chart-container {
239
- overflow: hidden; /* Prevent any overflow spacing */
304
+ overflow: hidden;
305
+ /* Prevent any overflow spacing */
240
306
  }
241
307
 
242
308
  .grid-label,
243
309
  .axis-label {
244
- fill: var(--bgl-gray) !important;;
310
+ fill: var(--bgl-gray) !important;
311
+ ;
245
312
  font-family: system-ui, -apple-system, sans-serif;
246
313
  font-size: 12px;
247
314
  margin: 1rem;
@@ -263,5 +330,22 @@ onMounted(() => {
263
330
  [dir="rtl"] .line-chart {
264
331
  text-align: right;
265
332
  }
333
+ </style>
334
+
335
+ <style>
336
+ .lineTooltip p {
337
+ font-weight: 300 !important;
338
+ font-size: 12px;
339
+ }
266
340
 
341
+ .lineTooltip {
342
+ font-weight: 700 !important;
343
+ }
344
+
345
+ .v-popper--theme-tooltip .v-popper__inner:has(.lineTooltip) {
346
+ background-color: var(--bgl-black) !important;
347
+ color: var(--bgl-white) !important;
348
+ border-radius: 0.5rem !important;
349
+ padding: 0.25rem 0.5rem !important;
350
+ }
267
351
  </style>