{"version":"0.0.0-beta0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^18.2.0","react-dom":"^18.2.0","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"08a4941d9c84653af4f84d9224ff852fda91a538","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.0.0-beta0","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-K5FtUfz43eJwHqZxjsvW5TUWPfsg48juUeyxsO8ECH92avVISIIBzwqwXOUfo0Y7+2Aj36emYuhMNltilxQ6kw==","shasum":"eedbaf8908996ae5b305ec1a7047ec5540ca7b1d","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.0.0-beta0.tgz","fileCount":115,"unpackedSize":108740,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF6o5FQCw18duCL9bKVskuXhiKvOAAxsKE3NnvT48wtsAiEAk1wLS/Lqf7+mS4dNe8rYPQ6cABfZa9zhRmVnaSgfR+g="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.0.0-beta0_1683703085527_0.22808449884598048"},"_hasShrinkwrap":false}