@dynect/base 0.2.0 → 0.3.0

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynect/base",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Reusable Nuxt base module — components, composables, utils, plugins and i18n from the Dynect design system.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,3 +1,5 @@
1
+ import { computed, onMounted, onUnmounted, readonly, ref } from 'vue';
2
+
1
3
  export type ViewportDeviceType = 'mobile' | 'tablet' | 'laptop' | 'desktop';
2
4
  export type OS = 'windows' | 'macos' | 'linux' | 'ios' | 'android' | 'unknown';
3
5
  export type Browser = 'chrome' | 'firefox' | 'safari' | 'edge' | 'opera' | 'samsung' | 'unknown';
@@ -80,40 +82,29 @@ export const useDevices = () => {
80
82
  });
81
83
 
82
84
  return {
83
- // State
84
85
  viewportWidth: readonly(viewportWidth),
85
86
  viewportHeight: readonly(viewportHeight),
86
87
  isOnline: readonly(isOnline),
87
88
  ua: readonly(ua),
88
-
89
- // Derived
90
89
  os,
91
90
  browser,
92
91
  deviceType,
93
92
  orientation,
94
-
95
- // Booleans
96
93
  isMobile,
97
94
  isTablet,
98
95
  isLaptop,
99
96
  isDesktop,
100
97
  isTouch,
101
-
102
- // OS shorthands
103
98
  isWindows: computed(() => os.value === 'windows'),
104
99
  isMacOS: computed(() => os.value === 'macos'),
105
100
  isLinux: computed(() => os.value === 'linux'),
106
101
  isIOS: computed(() => os.value === 'ios'),
107
102
  isAndroid: computed(() => os.value === 'android'),
108
-
109
- // Browser shorthands
110
103
  isChrome: computed(() => browser.value === 'chrome'),
111
104
  isFirefox: computed(() => browser.value === 'firefox'),
112
105
  isSafari: computed(() => browser.value === 'safari'),
113
106
  isEdge: computed(() => browser.value === 'edge'),
114
107
  isOpera: computed(() => browser.value === 'opera'),
115
-
116
- // Orientation
117
108
  isPortrait: computed(() => orientation.value === 'portrait'),
118
109
  isLandscape: computed(() => orientation.value === 'landscape'),
119
110
  };
@@ -1,3 +1,6 @@
1
+ import { ref, type Ref } from 'vue';
2
+ import { useNuxtApp } from 'nuxt/app';
3
+
1
4
  interface DropzoneConfig {
2
5
  allowedExt?: string[];
3
6
  maxSizeLimit?: number;
@@ -9,14 +12,10 @@ export const useDropzone = (config: DropzoneConfig = {}) => {
9
12
  const dragActive = ref(false);
10
13
  const droppedFile = ref<File[]>([]);
11
14
 
12
- // Use config values with defaults
13
15
  const maxSizeLimit = config.maxSizeLimit ?? 8;
14
16
  const maxFileLimit = config.maxFileLimit ?? 3;
15
17
  const allowedExt = config.allowedExt ?? ['pdf', 'doc', 'docx', 'jpeg', 'jpg', 'png', 'xls', 'xlsx', 'mp4', 'mov', 'avi', 'mpeg', 'mpg', 'zip'];
16
18
 
17
- /**
18
- * Converts dropped files to FormData entries
19
- */
20
19
  const uploadFiles = () => {
21
20
  const formData = new FormData();
22
21
  droppedFile.value.forEach((file) => {
@@ -25,73 +24,53 @@ export const useDropzone = (config: DropzoneConfig = {}) => {
25
24
  return [...formData.entries()] as [string, File][];
26
25
  };
27
26
 
28
- /**
29
- * Toggle drag active state
30
- */
31
27
  const toggleActive = () => {
32
28
  dragActive.value = !dragActive.value;
33
29
  };
34
30
 
35
- /**
36
- * Validate file extension
37
- */
38
31
  const validateFileExtension = (fileName: string): boolean => {
39
32
  const extension = fileName.split('.').pop()?.toLowerCase();
40
33
  return extension ? allowedExt.includes(extension) : false;
41
34
  };
42
35
 
43
- /**
44
- * Validate file size
45
- */
46
36
  const validateFileSize = (fileSize: number): boolean => {
47
37
  const sizeInMB = fileSize / (1024 * 1024);
48
38
  return sizeInMB < maxSizeLimit;
49
39
  };
50
40
 
51
- /**
52
- * Handle file selection from drop or file input
53
- */
54
41
  const selectedFile = (event: DragEvent | Event, type: 'drop' | 'select', fileInputRef: Ref<HTMLInputElement | null>) => {
55
42
  const files = type === 'drop' ? Array.from((event as DragEvent).dataTransfer?.files ?? []) : Array.from((event.target as HTMLInputElement).files ?? []);
56
43
 
57
44
  if (files.length === 0) return;
58
45
 
59
- // Check file count limit
60
46
  const totalFiles = droppedFile.value.length + files.length;
61
47
  if (totalFiles > maxFileLimit) {
62
- $toast.error(`Maximum ${maxFileLimit} file${maxFileLimit > 1 ? 's' : ''} allowed. You currently have ${droppedFile.value.length} file(s) and tried to add ${files.length} more.`, { position: 'top-center' });
48
+ ($toast as any).error(`Maximum ${maxFileLimit} file${maxFileLimit > 1 ? 's' : ''} allowed. You currently have ${droppedFile.value.length} file(s) and tried to add ${files.length} more.`, { position: 'top-center' });
63
49
  return;
64
50
  }
65
51
 
66
- // Validate file extensions
67
52
  const invalidFiles = files.filter((file) => !validateFileExtension(file.name));
68
53
  if (invalidFiles.length > 0) {
69
54
  const fileNames = invalidFiles.map((f) => f.name).join(', ');
70
- $toast.error(`Invalid file format: ${fileNames}. Supported formats: ${allowedExt.join(', ')}`, { position: 'top-center' });
55
+ ($toast as any).error(`Invalid file format: ${fileNames}. Supported formats: ${allowedExt.join(', ')}`, { position: 'top-center' });
71
56
  return;
72
57
  }
73
58
 
74
- // Validate file sizes
75
59
  const oversizedFiles = files.filter((file) => !validateFileSize(file.size));
76
60
  if (oversizedFiles.length > 0) {
77
61
  const fileNames = oversizedFiles.map((f) => f.name).join(', ');
78
- $toast.error(`File size exceeds ${maxSizeLimit} MB limit: ${fileNames}`, { position: 'top-center' });
62
+ ($toast as any).error(`File size exceeds ${maxSizeLimit} MB limit: ${fileNames}`, { position: 'top-center' });
79
63
  return;
80
64
  }
81
65
 
82
- // Add valid files
83
66
  droppedFile.value.push(...files);
84
67
  dragActive.value = droppedFile.value.length > 0;
85
68
 
86
- // Reset input value to allow re-uploading the same file
87
69
  if (fileInputRef.value) {
88
70
  fileInputRef.value.value = '';
89
71
  }
90
72
  };
91
73
 
92
- /**
93
- * Remove file by index
94
- */
95
74
  const deleteFile = (index: number) => {
96
75
  if (index >= 0 && index < droppedFile.value.length) {
97
76
  droppedFile.value.splice(index, 1);
@@ -99,9 +78,6 @@ export const useDropzone = (config: DropzoneConfig = {}) => {
99
78
  }
100
79
  };
101
80
 
102
- /**
103
- * Clear all files
104
- */
105
81
  const clearFiles = () => {
106
82
  droppedFile.value = [];
107
83
  dragActive.value = false;
@@ -1,3 +1,14 @@
1
+ import { inject, provide, type InjectionKey, type Ref } from 'vue';
2
+ import {
3
+ differenceInDays,
4
+ differenceInMonths,
5
+ differenceInWeeks,
6
+ getDaysInMonth,
7
+ startOfDay,
8
+ startOfMonth,
9
+ startOfWeek,
10
+ } from '../utils/date';
11
+
1
12
  export type GanttRange = 'daily' | 'weekly' | 'monthly';
2
13
 
3
14
  export interface GanttFeature {
@@ -59,7 +70,6 @@ export function useGantt() {
59
70
  return context;
60
71
  }
61
72
 
62
- // Helper functions for date calculations
63
73
  export function getDifferenceIn(range: GanttRange) {
64
74
  switch (range) {
65
75
  case 'daily':
@@ -78,7 +88,7 @@ export function getStartOf(range: GanttRange) {
78
88
  case 'daily':
79
89
  return startOfDay;
80
90
  case 'weekly':
81
- return (date: Date) => startOfWeek(date, { weekStartsOn: 1 }); // Assuming week starts on Monday
91
+ return (date: Date) => startOfWeek(date, { weekStartsOn: 1 });
82
92
  case 'monthly':
83
93
  return startOfMonth;
84
94
  default:
@@ -118,7 +128,6 @@ export function getOffset(date: Date, timelineStartDate: Date, context: { zoom:
118
128
  return offset * context.columnWidth * (context.zoom / 100) + innerOffset;
119
129
  }
120
130
 
121
- // Generate timeline data
122
131
  export function generateTimelineData(startYear: number, yearCount: number): TimelineData {
123
132
  const data: TimelineData = [];
124
133
 
@@ -1,3 +1,5 @@
1
+ import { inject, provide, type InjectionKey, type Ref } from 'vue';
2
+
1
3
  export type KanbanItemProps = {
2
4
  id: string;
3
5
  name: string;
@@ -1,3 +1,6 @@
1
+ import { computed } from 'vue';
2
+ import { useState } from 'nuxt/app';
3
+
1
4
  export interface AppNotification {
2
5
  id: string;
3
6
  type: string;
@@ -17,14 +20,6 @@ export interface AppAnnouncement {
17
20
  read: boolean;
18
21
  }
19
22
 
20
- // {
21
- // id: 'sample-1',
22
- // type: 'info',
23
- // title: 'Leave request approved',
24
- // message: 'Your annual leave request for 25-27 Apr has been approved.',
25
- // createdAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(),
26
- // read: false,
27
- // },
28
23
  export function useServerSideEvent() {
29
24
  const connected = useState<boolean>('sse:connected', () => false);
30
25
  const notifications = useState<AppNotification[]>('sse:notifications', () => []);
@@ -1,3 +1,4 @@
1
+ import { defineNuxtPlugin } from 'nuxt/app';
1
2
  import { provideSSRWidth } from '@vueuse/core';
2
3
 
3
4
  export default defineNuxtPlugin((nuxtApp) => {
@@ -1,3 +1,4 @@
1
+ import { defineNuxtPlugin } from 'nuxt/app';
1
2
  import { toast } from '../components/base/toast/state';
2
3
 
3
4
  export default defineNuxtPlugin(() => {