@tuspe/components
Version:
A reusable SvelteKit component library for form elements, breadcrumbs, prices and images.
145 lines (144 loc) • 4.91 kB
JavaScript
import { get, writable } from 'svelte/store';
import Breadcrumbs from './Breadcrumbs.svelte';
import Button from './Button.svelte';
import ButtonArrow from './ButtonArrow.svelte';
import ButtonClose from './ButtonClose.svelte';
import ButtonMenu from './ButtonMenu.svelte';
import Checkbox from './Checkbox.svelte';
import Image from './Image.svelte';
import Input from './Input.svelte';
import Modal from './Modal.svelte';
import Select from './Select.svelte';
export { Breadcrumbs, Button, ButtonArrow, ButtonClose, ButtonMenu, Checkbox, Image, Input, Modal, Select };
export const loading = writable(0);
/**
* PRICES AND NUMBERS
*/
export const formatPrice = (value, comma = false, currency = '€') => {
if (!value) {
return '0.00 ' + currency;
}
let price = Number(value)
.toFixed(2) // Ensure two decimal places
.replace(/\B(?=(\d{3})+(?!\d))/g, ' '); // Add space as thousand separator
if (comma) {
price = price.replace('.', ','); // Replace dot with comma
}
if (currency) {
price += ' ' + currency;
}
return price;
};
export const fixNumber = (value) => {
if (typeof value === 'string') {
value = Number(value);
}
if (!value) {
return 0;
}
return Math.round((value + Number.EPSILON) * 100) / 100;
};
/**
* VAT CALCULATION
*/
const defaultVatPercentage = 25.5;
export const calculateTax = (value, vatPercentage = defaultVatPercentage) => fixNumber((vatPercentage * value) / (100 + vatPercentage));
export const calculatePreTax = (value, vatPercentage = defaultVatPercentage) => fixNumber(value - calculateTax(value, vatPercentage));
export const calculateWithTax = (value, vatPercentage = defaultVatPercentage) => fixNumber(value * (1 + vatPercentage / 100));
/**
* STRING VALIDATIONS
*/
export const slugify = (value) => {
if (!value) {
return '';
}
return value
.toLowerCase()
.replace(/[äå]/g, 'a') // Replace ä and å with a
.replace(/ö/g, 'o') // Replace ö with o
.replace(/['"]/g, '') // Remove ' and "
.replace(/[^a-z0-9]+/g, '-') // Replace any non-alphanumeric characters with -
.replace(/^-+|-+$/g, ''); // Trim leading and trailing hyphens
};
export const validateSlug = (value) => {
return value && slugify(value) === value ? true : false;
};
export const validateEmail = (email) => {
var re = /\S+@\S+\.\S+/;
return re.test(email);
};
export const validateString = (value) => {
return value && value.replace(/[^\w\s@!.:;,?+äÄöÖåÅ/%&()|-]/gi, '') === value ? true : false;
};
/**
* ARRAY VALIDATIONS
*/
export const validateArray = (value, items = 0) => {
return value && Array.isArray(value) && value.length > items ? true : false;
};
export const cacheValues = writable({});
export const handleCache = (key, value = undefined, ttl = 60) => {
if (!key) {
return null;
}
const cache = get(cacheValues), newKey = slugify(key), now = Date.now(), ttlMs = ttl * 1000;
if (value !== undefined) {
const newValues = {
...cache,
[newKey]: { date: now, value }
};
cacheValues.set(newValues);
}
else if (cache?.[newKey]) {
const cachedItem = cache[newKey];
if (now - cachedItem.date < ttlMs) {
return cachedItem.value;
}
else {
// Remove expired cache entry
const { [newKey]: _, ...rest } = cache;
cacheValues.set(rest);
}
}
return null;
};
/**
* PREVENT DEFAULT
*/
export const preventDefault = (fn) => {
return function (event) {
event.preventDefault();
fn.call(this, event);
};
};
/**
* SUMMARY
*/
export const summary = (text, num = 160) => {
if (!text || typeof text !== 'string') {
return '';
}
// Remove HTML tags
let sum = text.replace(/<[^>]*>/g, '').trim();
// If the summary is within the limit, return it directly.
if (sum.length <= num) {
return sum;
}
// Truncate the summary to the specified number of characters.
let truncatedSummary = sum.substring(0, num);
// Define end characters to find the last occurrence for truncation.
const endChars = ['.', '!', '?'];
// Variable to track if an end character is found.
let foundEndChar = false;
// Find the last occurrence of any end character within the truncated summary.
for (const char of endChars) {
const lastIndex = truncatedSummary.lastIndexOf(char);
if (lastIndex !== -1) {
truncatedSummary = truncatedSummary.substring(0, lastIndex + 1);
foundEndChar = true;
break; // Exit loop after finding the first end character.
}
}
// Return the summary. Append ellipsis only if no end character was found.
return truncatedSummary.trim() + (foundEndChar ? '' : '...');
};