vyrn 1.0.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/.eslintrc.js ADDED
@@ -0,0 +1,25 @@
1
+ module.exports = {
2
+ parser: '@typescript-eslint/parser',
3
+ extends: [
4
+ 'plugin:react/recommended',
5
+ 'plugin:@typescript-eslint/recommended',
6
+ 'prettier',
7
+ 'plugin:react-hooks/recommended',
8
+ ],
9
+ parserOptions: {
10
+ ecmaVersion: 2020,
11
+ sourceType: 'module',
12
+ ecmaFeatures: {
13
+ jsx: true,
14
+ },
15
+ },
16
+ rules: {
17
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
18
+ },
19
+ settings: {
20
+ react: {
21
+ version: 'detect',
22
+ },
23
+ },
24
+ };
25
+
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "all",
4
+ "singleQuote": true,
5
+ "printWidth": 100,
6
+ "tabWidth": 2
7
+ }
8
+
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # Vyrn Toast
2
+
3
+ Vyrn is a modern, customizable toast library for React and Next.js applications. It provides an easy-to-use API for displaying toast notifications with various styles and animations.
4
+
5
+ ## Features
6
+
7
+ - 🚀 Easy to use
8
+ - 🎨 Customizable styles
9
+ - ♿ Accessible
10
+ - 🔧 TypeScript support
11
+ - âš¡ Lightweight
12
+ - 🔄 Smooth animations
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install vyrn
18
+ # or
19
+ yarn add vyrn
20
+
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { ToastProps } from '../types';
3
+ export declare const Toast: React.FC<ToastProps>;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { ToastProps } from '../types';
3
+ interface ToastContainerProps {
4
+ toasts: ToastProps[];
5
+ }
6
+ export declare const ToastContainer: React.FC<ToastContainerProps>;
7
+ export {};
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const ToastProvider: React.FC<React.PropsWithChildren<{}>>;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { ToastContextValue } from '../types';
3
+ export declare const ToastContext: React.Context<ToastContextValue | undefined>;
4
+ export declare const useToastContext: () => ToastContextValue;
@@ -0,0 +1,8 @@
1
+ import { ToastType } from '../types';
2
+ export declare const useToast: () => {
3
+ toast: (message: string, type?: ToastType, duration?: number) => void;
4
+ info: (message: string, duration?: number) => void;
5
+ success: (message: string, duration?: number) => void;
6
+ warning: (message: string, duration?: number) => void;
7
+ error: (message: string, duration?: number) => void;
8
+ };
@@ -0,0 +1,3 @@
1
+ export { ToastProvider } from './components/ToastProvider';
2
+ export { useToast } from './hooks/useToast';
3
+ export type { ToastProps, ToastType } from './types';
@@ -0,0 +1,2 @@
1
+ import t,{createContext as r,useContext as e,useEffect as n,useState as o,useCallback as a}from"react";var i=function(){return i=Object.assign||function(t){for(var r,e=1,n=arguments.length;e<n;e++)for(var o in r=arguments[e])Object.prototype.hasOwnProperty.call(r,o)&&(t[o]=r[o]);return t},i.apply(this,arguments)};function u(t,r,e){if(e||2===arguments.length)for(var n,o=0,a=r.length;o<a;o++)!n&&o in r||(n||(n=Array.prototype.slice.call(r,0,o)),n[o]=r[o]);return t.concat(n||Array.prototype.slice.call(r))}"function"==typeof SuppressedError&&SuppressedError;var c=r(void 0),s=function(){var t=e(c);if(!t)throw new Error("useToastContext must be used within a ToastProvider");return t},l=function(r){var e=r.id,o=r.message,a=r.type,i=r.duration,u=void 0===i?3e3:i,c=s().removeToast;return n((function(){var t=setTimeout((function(){c(e)}),u);return function(){return clearTimeout(t)}}),[e,u,c]),t.createElement("div",{className:"vyrn-toast vyrn-toast-".concat(a),role:"alert"},t.createElement("div",{className:"vyrn-toast-message"},o),t.createElement("button",{className:"vyrn-toast-close",onClick:function(){return c(e)},"aria-label":"Close"},"×"))},f=function(r){var e=r.toasts;return t.createElement("div",{className:"vyrn-toast-container","aria-live":"polite","aria-atomic":"true"},e.map((function(r){return t.createElement(l,i({key:r.id},r))})))},v=function(r){var e=r.children,s=o([]),l=s[0],v=s[1],m=o([]),d=m[0],p=m[1],y=a((function(t){var r=Math.random().toString(36).substr(2,9);l.length<5?v((function(e){return u(u([],e,!0),[i(i({},t),{id:r})],!1)})):p((function(r){return u(u([],r,!0),[t],!1)}))}),[l]),g=a((function(t){v((function(r){return r.filter((function(r){return r.id!==t}))}))}),[]);return n((function(){if(l.length<5&&d.length>0){var t=d[0],r=d.slice(1);y(t),p(r)}}),[l,d,y]),t.createElement(c.Provider,{value:{addToast:y,removeToast:g}},e,t.createElement(f,{toasts:l}))},m=function(){var t=s().addToast,r=a((function(r,e,n){void 0===e&&(e="info"),t({message:r,type:e,duration:n})}),[t]);return{toast:r,info:function(t,e){return r(t,"info",e)},success:function(t,e){return r(t,"success",e)},warning:function(t,e){return r(t,"warning",e)},error:function(t,e){return r(t,"error",e)}}};export{v as ToastProvider,m as useToast};
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var r=e(t),n=function(){return n=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var a in e=arguments[r])Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a]);return t},n.apply(this,arguments)};function a(t,e,r){if(r||2===arguments.length)for(var n,a=0,o=e.length;a<o;a++)!n&&a in e||(n||(n=Array.prototype.slice.call(e,0,a)),n[a]=e[a]);return t.concat(n||Array.prototype.slice.call(e))}"function"==typeof SuppressedError&&SuppressedError;var o=t.createContext(void 0),u=function(){var e=t.useContext(o);if(!e)throw new Error("useToastContext must be used within a ToastProvider");return e},i=function(e){var n=e.id,a=e.message,o=e.type,i=e.duration,s=void 0===i?3e3:i,c=u().removeToast;return t.useEffect((function(){var t=setTimeout((function(){c(n)}),s);return function(){return clearTimeout(t)}}),[n,s,c]),r.default.createElement("div",{className:"vyrn-toast vyrn-toast-".concat(o),role:"alert"},r.default.createElement("div",{className:"vyrn-toast-message"},a),r.default.createElement("button",{className:"vyrn-toast-close",onClick:function(){return c(n)},"aria-label":"Close"},"×"))},s=function(t){var e=t.toasts;return r.default.createElement("div",{className:"vyrn-toast-container","aria-live":"polite","aria-atomic":"true"},e.map((function(t){return r.default.createElement(i,n({key:t.id},t))})))};exports.ToastProvider=function(e){var u=e.children,i=t.useState([]),c=i[0],l=i[1],f=t.useState([]),d=f[0],v=f[1],p=t.useCallback((function(t){var e=Math.random().toString(36).substr(2,9);c.length<5?l((function(r){return a(a([],r,!0),[n(n({},t),{id:e})],!1)})):v((function(e){return a(a([],e,!0),[t],!1)}))}),[c]),m=t.useCallback((function(t){l((function(e){return e.filter((function(e){return e.id!==t}))}))}),[]);return t.useEffect((function(){if(c.length<5&&d.length>0){var t=d[0],e=d.slice(1);p(t),v(e)}}),[c,d,p]),r.default.createElement(o.Provider,{value:{addToast:p,removeToast:m}},u,r.default.createElement(s,{toasts:c}))},exports.useToast=function(){var e=u().addToast,r=t.useCallback((function(t,r,n){void 0===r&&(r="info"),e({message:t,type:r,duration:n})}),[e]);return{toast:r,info:function(t,e){return r(t,"info",e)},success:function(t,e){return r(t,"success",e)},warning:function(t,e){return r(t,"warning",e)},error:function(t,e){return r(t,"error",e)}}};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ export type ToastType = 'info' | 'success' | 'warning' | 'error';
2
+ export interface ToastProps {
3
+ id: string;
4
+ message: string;
5
+ type: ToastType;
6
+ duration?: number;
7
+ }
8
+ export interface ToastContextValue {
9
+ addToast: (toast: Omit<ToastProps, 'id'>) => void;
10
+ removeToast: (id: string) => void;
11
+ }
@@ -0,0 +1,2 @@
1
+ export declare const fadeIn = "\n @keyframes vyrnFadeIn {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n }\n";
2
+ export declare const fadeOut = "\n @keyframes vyrnFadeOut {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(-20px); }\n }\n";
@@ -0,0 +1,3 @@
1
+ export declare const TOAST_TYPES: readonly ["info", "success", "warning", "error"];
2
+ export declare const DEFAULT_DURATION = 3000;
3
+ export declare const MAX_TOASTS = 5;
package/jest.config.js ADDED
@@ -0,0 +1,9 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'jsdom',
4
+ setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
5
+ moduleNameMapper: {
6
+ '\\.(css|less|sass|scss)$': '<rootDir>/tests/__mocks__/styleMock.js',
7
+ },
8
+ };
9
+
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "vyrn",
3
+ "version": "1.0.0",
4
+ "description": "A modern, customizable toast library for React and Next.js",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "rollup -c",
10
+ "test": "jest",
11
+ "lint": "eslint 'src/**/*.{js,ts,tsx}'",
12
+ "lint:fix": "eslint 'src/**/*.{js,ts,tsx}' --fix",
13
+ "format": "prettier --write 'src/**/*.{js,ts,tsx}'",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "react",
18
+ "nextjs",
19
+ "toast",
20
+ "notification"
21
+ ],
22
+ "author": "Your Name",
23
+ "license": "MIT",
24
+ "peerDependencies": {
25
+ "react": "^17.0.0 || ^18.0.0",
26
+ "react-dom": "^17.0.0 || ^18.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "@testing-library/jest-dom": "^6.6.3",
30
+ "@testing-library/react": "^13.0.0",
31
+ "@testing-library/react-hooks": "^7.0.2",
32
+ "@types/jest": "^27.4.1",
33
+ "@types/react": "^18.0.0",
34
+ "@types/react-dom": "^18.0.0",
35
+ "@typescript-eslint/eslint-plugin": "^5.13.0",
36
+ "@typescript-eslint/parser": "^5.13.0",
37
+ "eslint": "^8.10.0",
38
+ "eslint-config-prettier": "^8.5.0",
39
+ "eslint-plugin-react": "^7.29.3",
40
+ "eslint-plugin-react-hooks": "^4.3.0",
41
+ "jest": "^27.5.1",
42
+ "postcss": "^8.4.49",
43
+ "prettier": "^2.5.1",
44
+ "rollup": "^2.70.0",
45
+ "rollup-plugin-postcss": "^4.0.0",
46
+ "rollup-plugin-terser": "^7.0.2",
47
+ "rollup-plugin-typescript2": "^0.31.0",
48
+ "ts-jest": "^27.1.3",
49
+ "typescript": "^4.5.0"
50
+ }
51
+ }
@@ -0,0 +1,38 @@
1
+ import typescript from 'rollup-plugin-typescript2';
2
+ import postcss from 'rollup-plugin-postcss';
3
+ import { terser } from 'rollup-plugin-terser';
4
+ import pkg from './package.json';
5
+
6
+ export default {
7
+ input: 'src/index.ts',
8
+ output: [
9
+ {
10
+ file: pkg.main,
11
+ format: 'cjs',
12
+ exports: 'named',
13
+ sourcemap: true,
14
+ },
15
+ {
16
+ file: pkg.module,
17
+ format: 'es',
18
+ exports: 'named',
19
+ sourcemap: true,
20
+ },
21
+ ],
22
+ plugins: [
23
+ typescript({
24
+ tsconfig: 'tsconfig.json',
25
+ clean: true,
26
+ }),
27
+ postcss({
28
+ extensions: ['.css'],
29
+ minimize: true,
30
+ inject: {
31
+ insertAt: 'top',
32
+ },
33
+ }),
34
+ terser(),
35
+ ],
36
+ external: [...Object.keys(pkg.peerDependencies || {})],
37
+ };
38
+
@@ -0,0 +1,26 @@
1
+ import React, { useEffect } from 'react';
2
+ import { ToastProps } from '../types';
3
+ import { useToastContext } from '../context/ToastContext';
4
+ import { DEFAULT_DURATION } from '../utils/constants';
5
+
6
+ export const Toast: React.FC<ToastProps> = ({ id, message, type, duration = DEFAULT_DURATION }) => {
7
+ const { removeToast } = useToastContext();
8
+
9
+ useEffect(() => {
10
+ const timer = setTimeout(() => {
11
+ removeToast(id);
12
+ }, duration);
13
+
14
+ return () => clearTimeout(timer);
15
+ }, [id, duration, removeToast]);
16
+
17
+ return (
18
+ <div className={`vyrn-toast vyrn-toast-${type}`} role="alert">
19
+ <div className="vyrn-toast-message">{message}</div>
20
+ <button className="vyrn-toast-close" onClick={() => removeToast(id)} aria-label="Close">
21
+ &times;
22
+ </button>
23
+ </div>
24
+ );
25
+ };
26
+
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { Toast } from './Toast';
3
+ import { ToastProps } from '../types';
4
+
5
+ interface ToastContainerProps {
6
+ toasts: ToastProps[];
7
+ }
8
+
9
+ export const ToastContainer: React.FC<ToastContainerProps> = ({ toasts }) => {
10
+ return (
11
+ <div className="vyrn-toast-container" aria-live="polite" aria-atomic="true">
12
+ {toasts.map((toast) => (
13
+ <Toast key={toast.id} {...toast} />
14
+ ))}
15
+ </div>
16
+ );
17
+ };
18
+
@@ -0,0 +1,39 @@
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
+ import { ToastContext } from '../context/ToastContext';
3
+ import { ToastContainer } from './ToastContainer';
4
+ import { ToastProps } from '../types';
5
+ import { MAX_TOASTS } from '../utils/constants';
6
+
7
+ export const ToastProvider: React.FC<React.PropsWithChildren<{}>> = ({ children }) => {
8
+ const [toasts, setToasts] = useState<ToastProps[]>([]);
9
+ const [queue, setQueue] = useState<Omit<ToastProps, 'id'>[]>([]);
10
+
11
+ const addToast = useCallback((toast: Omit<ToastProps, 'id'>) => {
12
+ const id = Math.random().toString(36).substr(2, 9);
13
+ if (toasts.length < MAX_TOASTS) {
14
+ setToasts((prevToasts) => [...prevToasts, { ...toast, id }]);
15
+ } else {
16
+ setQueue((prevQueue) => [...prevQueue, toast]);
17
+ }
18
+ }, [toasts]);
19
+
20
+ const removeToast = useCallback((id: string) => {
21
+ setToasts((prevToasts) => prevToasts.filter((toast) => toast.id !== id));
22
+ }, []);
23
+
24
+ useEffect(() => {
25
+ if (toasts.length < MAX_TOASTS && queue.length > 0) {
26
+ const [nextToast, ...restQueue] = queue;
27
+ addToast(nextToast);
28
+ setQueue(restQueue);
29
+ }
30
+ }, [toasts, queue, addToast]);
31
+
32
+ return (
33
+ <ToastContext.Provider value={{ addToast, removeToast }}>
34
+ {children}
35
+ <ToastContainer toasts={toasts} />
36
+ </ToastContext.Provider>
37
+ );
38
+ };
39
+
@@ -0,0 +1,13 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import { ToastContextValue } from '../types';
3
+
4
+ export const ToastContext = createContext<ToastContextValue | undefined>(undefined);
5
+
6
+ export const useToastContext = () => {
7
+ const context = useContext(ToastContext);
8
+ if (!context) {
9
+ throw new Error('useToastContext must be used within a ToastProvider');
10
+ }
11
+ return context;
12
+ };
13
+
@@ -0,0 +1,23 @@
1
+ import { useCallback } from 'react';
2
+ import { useToastContext } from '../context/ToastContext';
3
+ import { ToastType } from '../types';
4
+
5
+ export const useToast = () => {
6
+ const { addToast } = useToastContext();
7
+
8
+ const toast = useCallback(
9
+ (message: string, type: ToastType = 'info', duration?: number) => {
10
+ addToast({ message, type, duration });
11
+ },
12
+ [addToast]
13
+ );
14
+
15
+ return {
16
+ toast,
17
+ info: (message: string, duration?: number) => toast(message, 'info', duration),
18
+ success: (message: string, duration?: number) => toast(message, 'success', duration),
19
+ warning: (message: string, duration?: number) => toast(message, 'warning', duration),
20
+ error: (message: string, duration?: number) => toast(message, 'error', duration),
21
+ };
22
+ };
23
+
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { ToastProvider } from './components/ToastProvider';
2
+ export { useToast } from './hooks/useToast';
3
+ export type { ToastProps, ToastType } from './types';
4
+
@@ -0,0 +1,71 @@
1
+ .vyrn-toast-container {
2
+ position: fixed;
3
+ top: 1rem;
4
+ right: 1rem;
5
+ z-index: 9999;
6
+ }
7
+
8
+ .vyrn-toast {
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: space-between;
12
+ padding: 0.75rem 1rem;
13
+ border-radius: 4px;
14
+ margin-bottom: 0.5rem;
15
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
16
+ animation: vyrnFadeIn 0.3s ease-out;
17
+ }
18
+
19
+ .vyrn-toast-info {
20
+ background-color: #3498db;
21
+ color: #fff;
22
+ }
23
+
24
+ .vyrn-toast-success {
25
+ background-color: #2ecc71;
26
+ color: #fff;
27
+ }
28
+
29
+ .vyrn-toast-warning {
30
+ background-color: #f39c12;
31
+ color: #fff;
32
+ }
33
+
34
+ .vyrn-toast-error {
35
+ background-color: #e74c3c;
36
+ color: #fff;
37
+ }
38
+
39
+ .vyrn-toast-message {
40
+ flex-grow: 1;
41
+ margin-right: 1rem;
42
+ }
43
+
44
+ .vyrn-toast-close {
45
+ background: none;
46
+ border: none;
47
+ color: inherit;
48
+ font-size: 1.2rem;
49
+ cursor: pointer;
50
+ opacity: 0.7;
51
+ transition: opacity 0.2s;
52
+ }
53
+
54
+ .vyrn-toast-close:hover {
55
+ opacity: 1;
56
+ }
57
+
58
+ @keyframes vyrnFadeIn {
59
+ from { opacity: 0; transform: translateY(20px); }
60
+ to { opacity: 1; transform: translateY(0); }
61
+ }
62
+
63
+ @keyframes vyrnFadeOut {
64
+ from { opacity: 1; transform: translateY(0); }
65
+ to { opacity: 0; transform: translateY(-20px); }
66
+ }
67
+
68
+ .vyrn-toast-exit {
69
+ animation: vyrnFadeOut 0.3s ease-in forwards;
70
+ }
71
+
@@ -0,0 +1,14 @@
1
+ export type ToastType = 'info' | 'success' | 'warning' | 'error';
2
+
3
+ export interface ToastProps {
4
+ id: string;
5
+ message: string;
6
+ type: ToastType;
7
+ duration?: number;
8
+ }
9
+
10
+ export interface ToastContextValue {
11
+ addToast: (toast: Omit<ToastProps, 'id'>) => void;
12
+ removeToast: (id: string) => void;
13
+ }
14
+
@@ -0,0 +1,14 @@
1
+ export const fadeIn = `
2
+ @keyframes vyrnFadeIn {
3
+ from { opacity: 0; transform: translateY(20px); }
4
+ to { opacity: 1; transform: translateY(0); }
5
+ }
6
+ `;
7
+
8
+ export const fadeOut = `
9
+ @keyframes vyrnFadeOut {
10
+ from { opacity: 1; transform: translateY(0); }
11
+ to { opacity: 0; transform: translateY(-20px); }
12
+ }
13
+ `;
14
+
@@ -0,0 +1,4 @@
1
+ export const TOAST_TYPES = ['info', 'success', 'warning', 'error'] as const;
2
+ export const DEFAULT_DURATION = 3000;
3
+ export const MAX_TOASTS = 5;
4
+
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Toast } from '../src/components/Toast';
4
+ import { ToastContext } from '../src/context/ToastContext';
5
+
6
+ const mockRemoveToast = jest.fn();
7
+
8
+ const renderToast = (props: any) =>
9
+ render(
10
+ <ToastContext.Provider value={{ removeToast: mockRemoveToast } as any}>
11
+ <Toast {...props} />
12
+ </ToastContext.Provider>
13
+ );
14
+
15
+ describe('Toast', () => {
16
+ it('renders the message', () => {
17
+ renderToast({ id: '1', message: 'Test message', type: 'info' });
18
+ expect(screen.getByText('Test message')).toBeInTheDocument();
19
+ });
20
+
21
+ it('applies the correct CSS class based on type', () => {
22
+ renderToast({ id: '1', message: 'Test message', type: 'success' });
23
+ expect(screen.getByRole('alert')).toHaveClass('vyrn-toast-success');
24
+ });
25
+
26
+ it('calls removeToast when close button is clicked', () => {
27
+ renderToast({ id: '1', message: 'Test message', type: 'info' });
28
+ screen.getByRole('button').click();
29
+ expect(mockRemoveToast).toHaveBeenCalledWith('1');
30
+ });
31
+ });
32
+
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es5",
4
+ "module": "esnext",
5
+ "lib": ["dom", "esnext"],
6
+ "jsx": "react",
7
+ "declaration": true,
8
+ "declarationDir": "dist",
9
+ "strict": true,
10
+ "moduleResolution": "node",
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "outDir": "dist",
15
+ "rootDir": "src"
16
+ },
17
+ "include": ["src"],
18
+ "exclude": ["node_modules", "dist", "tests"]
19
+ }
20
+