feat(lib-core): biblioteca atomica @pulse-libs/core v1.0.0-beta.1
Esta commit conteudo a estrutura atomica completa:
- types: Result<T,E>, AsyncState<T>, Paginated<T>, SortConfig<T>
- utils: date, str, num, cn, debounce, throttle, storage, arr, obj
- validators: Zod schemas — email, password, uuid, url, phone, CPF/CNPJ, sanitizedStr, safeParse
- hooks: useToggle, useAsync, useDebounce, useLocalStorage, useMedia, useInterval, useOnClickOutside, useClipboard, useFetch
- components: Button, Input, Alert, Card, Spinner (atomic design pattern)
- build: tsup v8 ESM+CJS + DTS + sourcemaps — 0 erros
- tests: 57 testes 100% usuarios
- docker: multi-stage Dockerfile (node 20-alpine)
- config: vitest, tsup, tsconfig strict, .npmignore
Filosofia atomica:/utils ← /types ← /validators ← /hooks ← /components
Build: npm run build | Test: npm test | Publish: npm publish
🤖 Generated with Pulse (openclaw + nova-self-improver)
This commit is contained in:
+118
@@ -0,0 +1,118 @@
|
||||
// src/utils/index.ts
|
||||
var date = {
|
||||
now: () => (/* @__PURE__ */ new Date()).toISOString(),
|
||||
format: (d, fmt = "YYYY-MM-DD HH:mm") => {
|
||||
const date2 = typeof d === "number" ? new Date(d) : new Date(d);
|
||||
const map = {
|
||||
YYYY: String(date2.getFullYear()),
|
||||
MM: String(date2.getMonth() + 1).padStart(2, "0"),
|
||||
DD: String(date2.getDate()).padStart(2, "0"),
|
||||
HH: String(date2.getHours()).padStart(2, "0"),
|
||||
mm: String(date2.getMinutes()).padStart(2, "0"),
|
||||
ss: String(date2.getSeconds()).padStart(2, "0")
|
||||
};
|
||||
return fmt.replace(/YYYY|MM|DD|HH|mm|ss/g, (m) => map[m]);
|
||||
},
|
||||
isToday: (d) => {
|
||||
const date2 = new Date(d);
|
||||
const today = /* @__PURE__ */ new Date();
|
||||
return date2.toDateString() === today.toDateString();
|
||||
},
|
||||
daysBetween: (a, b) => Math.ceil((b.getTime() - a.getTime()) / 864e5)
|
||||
};
|
||||
var str = {
|
||||
capitalize: (s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase(),
|
||||
truncate: (s, max, suffix = "\u2026") => s.length <= max ? s : s.slice(0, max).trimEnd() + suffix,
|
||||
camelCase: (s) => s.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : ""),
|
||||
kebabCase: (s) => s.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
|
||||
slugify: (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""),
|
||||
removeAccents: (s) => s.normalize("NFD").replace(/[\u0300-\u036f]/g, ""),
|
||||
maskEmail: (email) => {
|
||||
const [user, domain] = email.split("@");
|
||||
return user.length <= 2 ? `${user[0]}*@${domain}` : `${user[0]}${"*".repeat(user.length - 2)}${user.at(-1)}@${domain}`;
|
||||
}
|
||||
};
|
||||
var num = {
|
||||
clamp: (value, min, max) => Math.min(Math.max(value, min), max),
|
||||
rand: (min, max) => Math.floor(Math.random() * (max - min + 1)) + min,
|
||||
format: (n) => n.toLocaleString("pt-BR"),
|
||||
percent: (part, total, decimals = 1) => {
|
||||
if (total === 0) return 0;
|
||||
return parseFloat((part / total * 100).toFixed(decimals));
|
||||
}
|
||||
};
|
||||
var CLEAN_CLASSES_REGEX = /\s+/g;
|
||||
function cn(...inputs) {
|
||||
return inputs.flat(2).filter(Boolean).join(" ").replace(CLEAN_CLASSES_REGEX, " ").trim();
|
||||
}
|
||||
function debounce(fn, ms) {
|
||||
let timer;
|
||||
return (...args) => {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => fn(...args), ms);
|
||||
};
|
||||
}
|
||||
function throttle(fn, ms) {
|
||||
let last = 0;
|
||||
return (...args) => {
|
||||
const now = Date.now();
|
||||
if (now - last >= ms) {
|
||||
last = now;
|
||||
fn(...args);
|
||||
}
|
||||
};
|
||||
}
|
||||
var storage = {
|
||||
get: (key, fallback) => {
|
||||
try {
|
||||
const v = typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
|
||||
return v ? JSON.parse(v) : fallback;
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
},
|
||||
set: (key, value) => {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
},
|
||||
remove: (key) => {
|
||||
try {
|
||||
localStorage.removeItem(key);
|
||||
} catch {
|
||||
}
|
||||
},
|
||||
clear: (prefix) => {
|
||||
if (prefix) Object.keys(localStorage).filter((k) => k.startsWith(prefix)).forEach((k) => localStorage.removeItem(k));
|
||||
else localStorage.clear();
|
||||
}
|
||||
};
|
||||
var arr = {
|
||||
unique: (items, key) => {
|
||||
if (!key) return [...new Set(items)];
|
||||
return items.filter((v, i, a) => a.findIndex((item) => item[key] === v[key]) === i);
|
||||
},
|
||||
chunk: (items, size) => {
|
||||
return Array.from({ length: Math.ceil(items.length / size) }, (_, i) => items.slice(i * size, i * size + size));
|
||||
},
|
||||
shuffle: (items) => [...items].sort(() => Math.random() - 0.5)
|
||||
};
|
||||
var obj = {
|
||||
pick: (o, keys) => keys.reduce((r, k) => {
|
||||
if (k in o) r[k] = o[k];
|
||||
return r;
|
||||
}, {}),
|
||||
omit: (o, keys) => Object.fromEntries(Object.entries(o).filter(([k]) => !keys.includes(k))),
|
||||
isEmpty: (o) => o == null || Object.keys(o).length === 0
|
||||
};
|
||||
|
||||
export {
|
||||
date,
|
||||
str,
|
||||
num,
|
||||
cn,
|
||||
debounce,
|
||||
throttle,
|
||||
storage,
|
||||
arr,
|
||||
obj
|
||||
};
|
||||
//# sourceMappingURL=chunk-RL4ANBQD.mjs.map
|
||||
Reference in New Issue
Block a user