Skip to content

Commit ce80d04

Browse files
init
0 parents  commit ce80d04

File tree

10 files changed

+234
-0
lines changed

10 files changed

+234
-0
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Qwik Utilities
2+
3+
This package provides utility functions for Qwik framework, including CSV export, date formatting, JSON helpers, and more.
4+
5+
## Installation
6+
7+
```bash
8+
npm install qwik-utilities
9+
```
10+
11+
### Usage
12+
13+
CSV Export
14+
```
15+
import { downloadCSV } from 'qwik-utilities';
16+
const data = [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }];
17+
downloadCSV(data);
18+
```
19+
20+
Date Formatting
21+
```
22+
import { formatDate, formatDateToMonthShort } from 'qwik-utilities';
23+
formatDate('2025-08-14');
24+
formatDateToMonthShort('2025-08-14');
25+
```
26+
JSON and Object Helpers
27+
```
28+
import { removeFalsy, duplicateObj, doesObjsMatch } from 'qwik-utilities';
29+
removeFalsy({ a: '', b: 0, c: null });
30+
duplicateObj({ a: 1 });
31+
doesObjsMatch({ a: 1 }, { a: 1 });
32+
```

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "qwik-utilities",
3+
"version": "1.0.0",
4+
"description": "A collection of utility functions and hooks for Qwik framework.",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"scripts": {
8+
"build": "tsc",
9+
"test": "echo No tests specified && exit 0"
10+
},
11+
"keywords": ["qwik", "utilities", "hooks", "debounce", "csv", "date", "helpers"],
12+
"author": "Your Name",
13+
"license": "MIT",
14+
"devDependencies": {
15+
"typescript": "^5.1.6"
16+
},
17+
"dependencies": {
18+
"@builder.io/qwik": "^0.23.0"
19+
}
20+
}

src/components/DarkModeSwitch.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// DarkModeSwitch component here
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// ToastNotification component here

src/hooks/useDebounce.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// src/hooks/useDebounce.ts
2+
import { useSignal, useTask$ } from '@builder.io/qwik';
3+
4+
/**
5+
6+
Custom Qwik hook to debounce a value.
7+
8+
@param value The value to debounce
9+
10+
@param delay Delay in milliseconds
11+
*/
12+
export function useDebounce(value: any, delay: number) {
13+
const debouncedValue = useSignal(value);
14+
15+
useTask$((options: { track: (fn: () => any) => void; cleanup: (fn: () => void) => void }) => {
16+
const { track, cleanup } = options;
17+
18+
track(() => value);
19+
20+
const timeout = setTimeout(() => {
21+
debouncedValue.value = value;
22+
}, delay);
23+
24+
cleanup(() => clearTimeout(timeout));
25+
26+
});
27+
28+
return debouncedValue;
29+
}
30+

src/hooks/useLocalStorage.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { useStore } from "@builder.io/qwik";
2+
3+
export function useLocalStorage<T>(key: string, initialValue: T) {
4+
const state = useStore({ value: initialValue });
5+
6+
const saved = localStorage.getItem(key);
7+
if (saved !== null) {
8+
state.value = JSON.parse(saved);
9+
}
10+
11+
const setValue = (val: T) => {
12+
state.value = val;
13+
localStorage.setItem(key, JSON.stringify(val));
14+
};
15+
16+
return [state, setValue] as const;
17+
}

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './utils/csvExporter';
2+
export * from './utils/generalUtils';
3+
export * from "./hooks/useLocalStorage";

src/utils/csvExporter.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export function convertArrayOfObjectsToCSV(array: any[]) {
2+
let result: string;
3+
const columnDelimiter = ',';
4+
const lineDelimiter = '\n';
5+
const keys = Object.keys(array[0]);
6+
7+
result = '';
8+
result += keys.join(columnDelimiter);
9+
result += lineDelimiter;
10+
11+
array.forEach(item => {
12+
let ctr = 0;
13+
keys.forEach(key => {
14+
if (ctr > 0) result += columnDelimiter;
15+
result += item[key];
16+
ctr++;
17+
});
18+
result += lineDelimiter;
19+
});
20+
21+
return result;
22+
}
23+
24+
export function downloadCSV(array: any[]) {
25+
const link = document.createElement('a');
26+
let csv = convertArrayOfObjectsToCSV(array);
27+
if (csv === null) return;
28+
29+
const filename = 'export.csv';
30+
31+
if (!csv.match(/^data:text\/csv/i)) {
32+
csv = `data:text/csv;charset=utf-8,${csv}`;
33+
}
34+
35+
link.setAttribute('href', encodeURI(csv));
36+
link.setAttribute('download', filename);
37+
link.click();
38+
}

src/utils/generalUtils.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
export const formatDate = (
2+
value: string | Date,
3+
formatting: Intl.DateTimeFormatOptions = { month: "short", day: "numeric", year: "numeric" }
4+
) => {
5+
if (!value) return value;
6+
return new Intl.DateTimeFormat("en-US", formatting).format(new Date(value));
7+
};
8+
9+
export const formatDateToMonthShort = (value: string | Date, toTimeForCurrentDay = true) => {
10+
const date = new Date(value);
11+
let formatting: Intl.DateTimeFormatOptions = { month: "short", day: "numeric" };
12+
if (toTimeForCurrentDay && date.toDateString() === new Date().toDateString()) {
13+
formatting = { hour: "numeric", minute: "numeric" };
14+
}
15+
return new Intl.DateTimeFormat("en-US", formatting).format(new Date(value));
16+
};
17+
18+
export const getFileExt = (uri: string) => uri.includes('.') ? uri.split('.').pop() : '';
19+
20+
export const getYearOptions = (from = 1950, to = new Date().getFullYear()) => {
21+
let result = [];
22+
for (let i = to; i >= from; i--) {
23+
result.push({ label: i, value: i });
24+
}
25+
return result;
26+
};
27+
28+
export const removeFalsy = (obj: any) => {
29+
let newObj: any = {};
30+
Object.keys(obj).forEach(props => {
31+
if (obj[props] || obj[props] === '0' || obj[props] === 0 || obj[props] !== '') {
32+
newObj[props] = obj[props];
33+
}
34+
});
35+
return newObj;
36+
};
37+
38+
export const getNumberWithOrdinal = (n: number) => {
39+
const s = ["th", "st", "nd", "rd"], v = n % 100;
40+
return n + (s[(v - 20) % 10] || s[v] || s[0]);
41+
};
42+
43+
export const handleGetDirection = (lat = '', lng = '') => {
44+
window.open(`https://www.google.com/maps/search/?api=1&query=${lat},${lng}`, '_blank');
45+
};
46+
47+
export const convertTimeFormat = (time = '') => {
48+
if (!time) return '';
49+
let [hr, min] = time.split(':');
50+
let hour = parseInt(hr);
51+
if (hour < 12) return `${hour}:${min} AM`;
52+
return `${hour - 12 < 10 ? `0${hour-12}` : hour-12}:${min} PM`;
53+
};
54+
55+
export const isJsonParsable = (str: string) => {
56+
try { JSON.parse(str); } catch { return false; }
57+
return true;
58+
};
59+
60+
export const duplicateObj = (obj: any) => JSON.parse(JSON.stringify(obj));
61+
62+
export const makeTwoDigit = (num: number) => num < 10 ? `0${num}` : num.toString();
63+
64+
export const doesObjsMatch = (obj1: any, obj2: any) => JSON.stringify(obj1) === JSON.stringify(obj2);
65+
66+
export const onlyAllowNumber = (evt: KeyboardEvent) => {
67+
const charCode = evt.which ? evt.which : evt.keyCode;
68+
if (charCode > 31 && (charCode < 48 || charCode > 57) && charCode !== 46) evt.preventDefault();
69+
};
70+
71+
export const createDateObj = (date: string, time: string) => {
72+
try {
73+
const [y, m, d] = date.split('-');
74+
const [hr, min] = time.split(':');
75+
return new Date(parseInt(y), parseInt(m)-1, parseInt(d), parseInt(hr), parseInt(min));
76+
} catch (e) { console.log('Error createDateObj', e); return null; }
77+
};
78+
79+
export const getYoutubeVideoId = (link: string) => {
80+
try { let url = new URL(link); return url.searchParams.get('v') || ''; } catch { return ''; }
81+
};

tsconfig.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES6",
4+
"module": "ESNext",
5+
"jsx": "react-jsx",
6+
"moduleResolution": "node",
7+
"esModuleInterop": true,
8+
"strict": true
9+
},
10+
"include": ["src"]
11+
}

0 commit comments

Comments
 (0)