@kirill.konshin/utils 0.0.18 → 0.0.20
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/.ctirc +19 -10
- package/.storybook/main.ts +1 -20
- package/.storybook/preview.ts +1 -16
- package/.turbo/turbo-build.log +9 -66
- package/CHANGELOG.md +27 -0
- package/README.md +6 -0
- package/dist/bootstrap/index.d.ts +1 -12
- package/dist/bootstrap/index.d.ts.map +1 -1
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -9
- package/dist/core/index.d.ts.map +1 -1
- package/dist/electron/index.d.ts +1 -2
- package/dist/electron/index.d.ts.map +1 -1
- package/dist/electron-builder/index.d.ts +1 -2
- package/dist/electron-builder/index.d.ts.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/mui/index.d.ts +1 -4
- package/dist/mui/index.d.ts.map +1 -1
- package/dist/next/index.d.ts +1 -5
- package/dist/next/index.d.ts.map +1 -1
- package/dist/node/index.d.ts +2 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/react/index.d.ts +1 -5
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react-native/index.d.ts +1 -3
- package/dist/react-native/index.d.ts.map +1 -1
- package/dist/tailwind/index.d.ts +1 -2
- package/dist/tailwind/index.d.ts.map +1 -1
- package/dist/worker/index.d.ts +2 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/package.json +41 -99
- package/src/bootstrap/index.ts +2 -12
- package/src/browser/index.ts +2 -0
- package/src/core/index.ts +2 -9
- package/src/electron/index.ts +2 -2
- package/src/electron-builder/index.ts +2 -2
- package/src/index.ts +12 -0
- package/src/mui/index.ts +2 -4
- package/src/next/index.ts +2 -5
- package/src/node/index.ts +2 -0
- package/src/react/index.ts +2 -5
- package/src/react-native/index.ts +2 -3
- package/src/tailwind/index.ts +2 -2
- package/src/worker/index.ts +2 -0
- package/tsconfig.json +2 -14
- package/vite.config.ts +2 -56
- package/.turbo/turbo-test.log +0 -171
- package/builders/.swcrc +0 -18
- package/builders/build.config.ts +0 -11
- package/builders/bun.build.js +0 -23
- package/builders/package.json +0 -209
- package/builders/perf.mjs +0 -63
- package/builders/rollup.config.mjs +0 -50
- package/builders/rslib.config.ts +0 -26
- package/builders/tsconfig.json +0 -21
- package/builders/tsup.config.ts +0 -20
- package/builders/turbo.json +0 -24
- package/builders/vite.config.ts +0 -37
- package/demo/worker-demo.ts +0 -73
- package/dist/bootstrap/adaptiveContainer.d.ts +0 -3
- package/dist/bootstrap/adaptiveContainer.d.ts.map +0 -1
- package/dist/bootstrap/adaptiveContainer.js +0 -11
- package/dist/bootstrap/adaptiveContainer.js.map +0 -1
- package/dist/bootstrap/controls.d.ts +0 -38
- package/dist/bootstrap/controls.d.ts.map +0 -1
- package/dist/bootstrap/controls.js +0 -78
- package/dist/bootstrap/controls.js.map +0 -1
- package/dist/bootstrap/controls.stories.d.ts +0 -9
- package/dist/bootstrap/controls.stories.d.ts.map +0 -1
- package/dist/bootstrap/error.d.ts +0 -7
- package/dist/bootstrap/error.d.ts.map +0 -1
- package/dist/bootstrap/error.js +0 -32
- package/dist/bootstrap/error.js.map +0 -1
- package/dist/bootstrap/error.stories.d.ts +0 -8
- package/dist/bootstrap/error.stories.d.ts.map +0 -1
- package/dist/bootstrap/field.d.ts +0 -9
- package/dist/bootstrap/field.d.ts.map +0 -1
- package/dist/bootstrap/field.js +0 -29
- package/dist/bootstrap/field.js.map +0 -1
- package/dist/bootstrap/field.stories.d.ts +0 -8
- package/dist/bootstrap/field.stories.d.ts.map +0 -1
- package/dist/bootstrap/footer.d.ts +0 -10
- package/dist/bootstrap/footer.d.ts.map +0 -1
- package/dist/bootstrap/footer.js +0 -40
- package/dist/bootstrap/footer.js.map +0 -1
- package/dist/bootstrap/globalLoading.d.ts +0 -4
- package/dist/bootstrap/globalLoading.d.ts.map +0 -1
- package/dist/bootstrap/globalLoading.js +0 -10
- package/dist/bootstrap/globalLoading.js.map +0 -1
- package/dist/bootstrap/globalLoading.stories.d.ts +0 -7
- package/dist/bootstrap/globalLoading.stories.d.ts.map +0 -1
- package/dist/bootstrap/index.js +0 -35
- package/dist/bootstrap/loading.d.ts +0 -8
- package/dist/bootstrap/loading.d.ts.map +0 -1
- package/dist/bootstrap/loading.js +0 -18
- package/dist/bootstrap/loading.js.map +0 -1
- package/dist/bootstrap/loading.stories.d.ts +0 -9
- package/dist/bootstrap/loading.stories.d.ts.map +0 -1
- package/dist/bootstrap/responsiveHelper.d.ts +0 -7
- package/dist/bootstrap/responsiveHelper.d.ts.map +0 -1
- package/dist/bootstrap/responsiveHelper.js +0 -46
- package/dist/bootstrap/responsiveHelper.js.map +0 -1
- package/dist/bootstrap/screen.d.ts +0 -20
- package/dist/bootstrap/screen.d.ts.map +0 -1
- package/dist/bootstrap/screen.js +0 -79
- package/dist/bootstrap/screen.js.map +0 -1
- package/dist/bootstrap/screen.stories.d.ts +0 -14
- package/dist/bootstrap/screen.stories.d.ts.map +0 -1
- package/dist/bootstrap/toaster.d.ts +0 -9
- package/dist/bootstrap/toaster.d.ts.map +0 -1
- package/dist/bootstrap/toaster.js +0 -37
- package/dist/bootstrap/toaster.js.map +0 -1
- package/dist/bootstrap/toaster.stories.d.ts +0 -8
- package/dist/bootstrap/toaster.stories.d.ts.map +0 -1
- package/dist/bootstrap/useModal.d.ts +0 -22
- package/dist/bootstrap/useModal.d.ts.map +0 -1
- package/dist/bootstrap/useModal.js +0 -50
- package/dist/bootstrap/useModal.js.map +0 -1
- package/dist/bootstrap/useModal.stories.d.ts +0 -9
- package/dist/bootstrap/useModal.stories.d.ts.map +0 -1
- package/dist/bootstrap/useWrappedForm.d.ts +0 -14
- package/dist/bootstrap/useWrappedForm.d.ts.map +0 -1
- package/dist/bootstrap/useWrappedForm.js +0 -32
- package/dist/bootstrap/useWrappedForm.js.map +0 -1
- package/dist/core/cache.d.ts +0 -120
- package/dist/core/cache.d.ts.map +0 -1
- package/dist/core/cache.js +0 -107
- package/dist/core/cache.js.map +0 -1
- package/dist/core/cache.test.d.ts +0 -2
- package/dist/core/cache.test.d.ts.map +0 -1
- package/dist/core/errors.d.ts +0 -2
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js +0 -15
- package/dist/core/errors.js.map +0 -1
- package/dist/core/files.d.ts +0 -3
- package/dist/core/files.d.ts.map +0 -1
- package/dist/core/files.js +0 -27
- package/dist/core/files.js.map +0 -1
- package/dist/core/index.js +0 -34
- package/dist/core/index.js.map +0 -1
- package/dist/core/ls.d.ts +0 -6
- package/dist/core/ls.d.ts.map +0 -1
- package/dist/core/ls.js +0 -12
- package/dist/core/ls.js.map +0 -1
- package/dist/core/measure.d.ts +0 -35
- package/dist/core/measure.d.ts.map +0 -1
- package/dist/core/measure.js +0 -56
- package/dist/core/measure.js.map +0 -1
- package/dist/core/mutex.d.ts +0 -6
- package/dist/core/mutex.d.ts.map +0 -1
- package/dist/core/mutex.js +0 -26
- package/dist/core/mutex.js.map +0 -1
- package/dist/core/worker.d.ts +0 -98
- package/dist/core/worker.d.ts.map +0 -1
- package/dist/core/worker.js +0 -240
- package/dist/core/worker.js.map +0 -1
- package/dist/core/worker.test.d.ts +0 -2
- package/dist/core/worker.test.d.ts.map +0 -1
- package/dist/core/workerUtils.d.ts +0 -3
- package/dist/core/workerUtils.d.ts.map +0 -1
- package/dist/core/workerUtils.js +0 -31
- package/dist/core/workerUtils.js.map +0 -1
- package/dist/core/wrpc.d.ts +0 -45
- package/dist/core/wrpc.d.ts.map +0 -1
- package/dist/core/wrpc.fixture.d.ts +0 -29
- package/dist/core/wrpc.fixture.d.ts.map +0 -1
- package/dist/core/wrpc.js +0 -242
- package/dist/core/wrpc.js.map +0 -1
- package/dist/core/wrpc.test.d.ts +0 -1
- package/dist/core/wrpc.test.d.ts.map +0 -1
- package/dist/electron/createWindow.d.ts +0 -23
- package/dist/electron/createWindow.d.ts.map +0 -1
- package/dist/electron/createWindow.js +0 -160
- package/dist/electron/createWindow.js.map +0 -1
- package/dist/electron/index.js +0 -9
- package/dist/electron/index.js.map +0 -1
- package/dist/electron/updater.d.ts +0 -2
- package/dist/electron/updater.d.ts.map +0 -1
- package/dist/electron/updater.js +0 -47
- package/dist/electron/updater.js.map +0 -1
- package/dist/electron-builder/builder.d.ts +0 -8
- package/dist/electron-builder/builder.d.ts.map +0 -1
- package/dist/electron-builder/builder.js +0 -130
- package/dist/electron-builder/builder.js.map +0 -1
- package/dist/electron-builder/images.d.ts +0 -7
- package/dist/electron-builder/images.d.ts.map +0 -1
- package/dist/electron-builder/images.js +0 -25
- package/dist/electron-builder/images.js.map +0 -1
- package/dist/electron-builder/index.js +0 -7
- package/dist/electron-builder/index.js.map +0 -1
- package/dist/mui/formControlFieldset.d.ts +0 -5
- package/dist/mui/formControlFieldset.d.ts.map +0 -1
- package/dist/mui/formControlFieldset.js +0 -28
- package/dist/mui/formControlFieldset.js.map +0 -1
- package/dist/mui/formControlFieldset.stories.d.ts +0 -7
- package/dist/mui/formControlFieldset.stories.d.ts.map +0 -1
- package/dist/mui/formLabelLegend.d.ts +0 -4
- package/dist/mui/formLabelLegend.d.ts.map +0 -1
- package/dist/mui/formLabelLegend.js +0 -12
- package/dist/mui/formLabelLegend.js.map +0 -1
- package/dist/mui/genericControl.d.ts +0 -7
- package/dist/mui/genericControl.d.ts.map +0 -1
- package/dist/mui/genericControl.js +0 -21
- package/dist/mui/genericControl.js.map +0 -1
- package/dist/mui/index.js +0 -11
- package/dist/mui/index.js.map +0 -1
- package/dist/mui/readOnly.d.ts +0 -6
- package/dist/mui/readOnly.d.ts.map +0 -1
- package/dist/mui/readOnly.js +0 -7
- package/dist/mui/readOnly.js.map +0 -1
- package/dist/next/appLink.d.ts +0 -8
- package/dist/next/appLink.d.ts.map +0 -1
- package/dist/next/appLink.js +0 -34
- package/dist/next/appLink.js.map +0 -1
- package/dist/next/index.js +0 -15
- package/dist/next/index.js.map +0 -1
- package/dist/next/measure.d.ts +0 -15
- package/dist/next/measure.d.ts.map +0 -1
- package/dist/next/measure.js +0 -9
- package/dist/next/measure.js.map +0 -1
- package/dist/next/noSSR.d.ts +0 -5
- package/dist/next/noSSR.d.ts.map +0 -1
- package/dist/next/noSSR.js +0 -15
- package/dist/next/noSSR.js.map +0 -1
- package/dist/next/redirect.d.ts +0 -6
- package/dist/next/redirect.d.ts.map +0 -1
- package/dist/next/useIsInner.d.ts +0 -3
- package/dist/next/useIsInner.d.ts.map +0 -1
- package/dist/next/useIsInner.js +0 -15
- package/dist/next/useIsInner.js.map +0 -1
- package/dist/react/apiCall.d.ts +0 -6
- package/dist/react/apiCall.d.ts.map +0 -1
- package/dist/react/apiCall.js +0 -24
- package/dist/react/apiCall.js.map +0 -1
- package/dist/react/form/client.d.ts +0 -7
- package/dist/react/form/client.d.ts.map +0 -1
- package/dist/react/form/client.js +0 -46
- package/dist/react/form/client.js.map +0 -1
- package/dist/react/form/form.d.ts +0 -45
- package/dist/react/form/form.d.ts.map +0 -1
- package/dist/react/form/form.js +0 -69
- package/dist/react/form/form.js.map +0 -1
- package/dist/react/form/index.d.ts +0 -3
- package/dist/react/form/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -25
- package/dist/react/index.js.map +0 -1
- package/dist/react/keyboard.d.ts +0 -11
- package/dist/react/keyboard.d.ts.map +0 -1
- package/dist/react/keyboard.js +0 -38
- package/dist/react/keyboard.js.map +0 -1
- package/dist/react/useFetch.d.ts +0 -2
- package/dist/react/useFetch.d.ts.map +0 -1
- package/dist/react/useFetch.js +0 -20
- package/dist/react/useFetch.js.map +0 -1
- package/dist/react/useFetcher.d.ts +0 -10
- package/dist/react/useFetcher.d.ts.map +0 -1
- package/dist/react/useFetcher.js +0 -43
- package/dist/react/useFetcher.js.map +0 -1
- package/dist/react-native/index.js +0 -9
- package/dist/react-native/index.js.map +0 -1
- package/dist/react-native/share.d.ts +0 -9
- package/dist/react-native/share.d.ts.map +0 -1
- package/dist/react-native/share.js +0 -23
- package/dist/react-native/share.js.map +0 -1
- package/dist/react-native/update.d.ts +0 -4
- package/dist/react-native/update.d.ts.map +0 -1
- package/dist/react-native/update.js +0 -40
- package/dist/react-native/update.js.map +0 -1
- package/dist/react-native/useAppState.d.ts +0 -2
- package/dist/react-native/useAppState.d.ts.map +0 -1
- package/dist/react-native/useAppState.js +0 -18
- package/dist/react-native/useAppState.js.map +0 -1
- package/dist/tailwind/fullpage.d.ts +0 -7
- package/dist/tailwind/fullpage.d.ts.map +0 -1
- package/dist/tailwind/fullpage.js +0 -14
- package/dist/tailwind/fullpage.js.map +0 -1
- package/dist/tailwind/index.js +0 -7
- package/dist/tailwind/index.js.map +0 -1
- package/dist/tailwind/responsiveHelper.d.ts +0 -2
- package/dist/tailwind/responsiveHelper.d.ts.map +0 -1
- package/dist/tailwind/responsiveHelper.js +0 -16
- package/dist/tailwind/responsiveHelper.js.map +0 -1
- package/src/bootstrap/adaptiveContainer.tsx +0 -12
- package/src/bootstrap/controls.stories.tsx +0 -62
- package/src/bootstrap/controls.tsx +0 -119
- package/src/bootstrap/error.stories.tsx +0 -34
- package/src/bootstrap/error.tsx +0 -40
- package/src/bootstrap/field.stories.tsx +0 -42
- package/src/bootstrap/field.tsx +0 -35
- package/src/bootstrap/footer.tsx +0 -49
- package/src/bootstrap/globalLoading.stories.tsx +0 -25
- package/src/bootstrap/globalLoading.tsx +0 -17
- package/src/bootstrap/loading.stories.tsx +0 -35
- package/src/bootstrap/loading.tsx +0 -22
- package/src/bootstrap/main.scss +0 -86
- package/src/bootstrap/responsiveHelper.tsx +0 -50
- package/src/bootstrap/screen.stories.tsx +0 -160
- package/src/bootstrap/screen.tsx +0 -144
- package/src/bootstrap/toaster.stories.tsx +0 -32
- package/src/bootstrap/toaster.tsx +0 -38
- package/src/bootstrap/useModal.stories.tsx +0 -51
- package/src/bootstrap/useModal.tsx +0 -88
- package/src/bootstrap/useWrappedForm.ts +0 -40
- package/src/core/README.md +0 -91
- package/src/core/cache.test.ts +0 -121
- package/src/core/cache.ts +0 -239
- package/src/core/errors.ts +0 -14
- package/src/core/files.ts +0 -25
- package/src/core/ls.ts +0 -11
- package/src/core/measure.ts +0 -61
- package/src/core/mutex.ts +0 -22
- package/src/core/worker.test.ts +0 -197
- package/src/core/worker.ts +0 -340
- package/src/core/workerUtils.ts +0 -32
- package/src/core/wrpc.fixture.ts +0 -72
- package/src/core/wrpc.test.ts +0 -225
- package/src/core/wrpc.ts +0 -359
- package/src/electron/README.md +0 -13
- package/src/electron/createWindow.ts +0 -234
- package/src/electron/updater.ts +0 -54
- package/src/electron-builder/builder.ts +0 -150
- package/src/electron-builder/images.ts +0 -33
- package/src/mui/README.md +0 -3
- package/src/mui/formControlFieldset.stories.tsx +0 -71
- package/src/mui/formControlFieldset.tsx +0 -26
- package/src/mui/formLabelLegend.tsx +0 -11
- package/src/mui/genericControl.tsx +0 -20
- package/src/mui/readOnly.tsx +0 -6
- package/src/next/appLink.tsx +0 -40
- package/src/next/measure.ts +0 -7
- package/src/next/noSSR.tsx +0 -17
- package/src/next/redirect.tsx +0 -13
- package/src/next/useIsInner.ts +0 -13
- package/src/react/apiCall.ts +0 -25
- package/src/react/form/client.tsx +0 -62
- package/src/react/form/form.tsx +0 -129
- package/src/react/form/index.ts +0 -2
- package/src/react/keyboard.tsx +0 -49
- package/src/react/useFetch.ts +0 -29
- package/src/react/useFetcher.ts +0 -49
- package/src/react-native/share.ts +0 -31
- package/src/react-native/update.tsx +0 -40
- package/src/react-native/useAppState.ts +0 -18
- package/src/tailwind/README.md +0 -8
- package/src/tailwind/fullpage.tsx +0 -11
- package/src/tailwind/responsiveHelper.tsx +0 -16
- package/src-todo/auth0.tsx +0 -177
- package/vite.exports.ts +0 -121
- /package/dist/{bootstrap/index.js.map → index.js.map} +0 -0
package/src/next/noSSR.tsx
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { useLayoutEffect, useState } from 'react';
|
|
4
|
-
|
|
5
|
-
const DefaultOnSSR = () => <span />;
|
|
6
|
-
|
|
7
|
-
// @see https://github.com/kadirahq/react-no-ssr/blob/master/src/index.js
|
|
8
|
-
// @see https://nextjs.org/docs/messages/react-hydration-error#solution-1-using-useeffect-to-run-on-the-client-only
|
|
9
|
-
export function NoSSR({ children, onSSR = <DefaultOnSSR /> }) {
|
|
10
|
-
const [canRender, setCanRender] = useState(false);
|
|
11
|
-
|
|
12
|
-
useLayoutEffect(() => {
|
|
13
|
-
setCanRender(true);
|
|
14
|
-
}, []);
|
|
15
|
-
|
|
16
|
-
return canRender ? children : onSSR;
|
|
17
|
-
}
|
package/src/next/redirect.tsx
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useRouter } from 'next/navigation';
|
|
4
|
-
import { useEffect } from 'react';
|
|
5
|
-
import type { LinkProps } from 'next/link';
|
|
6
|
-
|
|
7
|
-
export default function Redirect({ to, replace }: { to: LinkProps['href']; replace?: LinkProps['replace'] }) {
|
|
8
|
-
const router = useRouter();
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
router[replace ? 'replace' : 'push'](to.toString()); //TODO Test this
|
|
11
|
-
}, [replace, router, to]);
|
|
12
|
-
return null;
|
|
13
|
-
}
|
package/src/next/useIsInner.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useSelectedLayoutSegments } from 'next/navigation';
|
|
4
|
-
|
|
5
|
-
export const useIsInner = (): boolean => {
|
|
6
|
-
const pathname = useSelectedLayoutSegments();
|
|
7
|
-
return pathname.length > 0;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const useIsIndex = (): boolean => {
|
|
11
|
-
const pathname = useSelectedLayoutSegments();
|
|
12
|
-
return pathname.length === 0;
|
|
13
|
-
};
|
package/src/react/apiCall.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export const jsonContentType = 'application/json';
|
|
2
|
-
|
|
3
|
-
export type DataResponse<R> = Response & { data?: R };
|
|
4
|
-
|
|
5
|
-
export async function apiCall<R>(url: string, init?: RequestInit): Promise<DataResponse<R>> {
|
|
6
|
-
const useBodyAsIs = !init?.body || init?.body instanceof FormData || typeof init?.body === 'string';
|
|
7
|
-
|
|
8
|
-
const res: DataResponse<R> = await fetch(url, {
|
|
9
|
-
method: 'POST',
|
|
10
|
-
...init,
|
|
11
|
-
body: useBodyAsIs ? init?.body : JSON.stringify(init.body),
|
|
12
|
-
headers: {
|
|
13
|
-
...init?.headers,
|
|
14
|
-
...(useBodyAsIs ? {} : { 'Content-Type': jsonContentType }),
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
if (res.headers.get('Content-Type')?.includes(jsonContentType)) {
|
|
19
|
-
res.data = await res.json();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!res.ok) throw new Error(res.statusText, { cause: res });
|
|
23
|
-
|
|
24
|
-
return res;
|
|
25
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useActionState, useCallback, useState, useTransition } from 'react';
|
|
4
|
-
import { create, MaybeTypeOf, Validation } from './form';
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
|
|
7
|
-
const FORM_DEBUG = process.env.NEXT_PUBLIC_FORM_DEBUG === 'true';
|
|
8
|
-
|
|
9
|
-
export function createClient<S extends z.ZodObject<any>>(schema: S) {
|
|
10
|
-
const { validate } = create(schema);
|
|
11
|
-
|
|
12
|
-
function useValidationCallback(
|
|
13
|
-
actionFn: (data: FormData) => Promise<Validation<S>>,
|
|
14
|
-
): (formData: FormData) => Promise<Validation<S>> {
|
|
15
|
-
return useCallback(
|
|
16
|
-
async (formData: FormData) => {
|
|
17
|
-
const clientRes = validate(formData);
|
|
18
|
-
console.log('Client validation', FORM_DEBUG ? 'ignored' : 'active', clientRes);
|
|
19
|
-
if (!clientRes.success && !FORM_DEBUG) return clientRes;
|
|
20
|
-
|
|
21
|
-
const serverRes = await actionFn(formData);
|
|
22
|
-
console.log('Server validation', serverRes);
|
|
23
|
-
return serverRes;
|
|
24
|
-
},
|
|
25
|
-
[actionFn],
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function useValidation(
|
|
30
|
-
actionFn: (data: FormData) => Promise<Validation<S>>,
|
|
31
|
-
initialData: MaybeTypeOf<S> = {} as MaybeTypeOf<S>,
|
|
32
|
-
) {
|
|
33
|
-
const cb = useValidationCallback(actionFn);
|
|
34
|
-
|
|
35
|
-
return useActionState<Validation<S>, FormData>(async (_, data) => cb(data), {
|
|
36
|
-
success: false,
|
|
37
|
-
data: initialData,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function useValidationTransition(
|
|
42
|
-
actionFn: (data: FormData) => Promise<Validation<S>>,
|
|
43
|
-
initialData: MaybeTypeOf<S> = {} as MaybeTypeOf<S>,
|
|
44
|
-
): [Validation<S>, (formData: FormData) => Promise<Validation<S>>, boolean] {
|
|
45
|
-
const [isPending, startTransition] = useTransition();
|
|
46
|
-
const [state, setState] = useState<Validation<S>>({ success: false, data: initialData });
|
|
47
|
-
const cb = useValidationCallback(actionFn);
|
|
48
|
-
|
|
49
|
-
const wrappedCb = useCallback(
|
|
50
|
-
(formData: FormData) => {
|
|
51
|
-
const promise = cb(formData);
|
|
52
|
-
startTransition(() => promise.then(setState));
|
|
53
|
-
return promise;
|
|
54
|
-
},
|
|
55
|
-
[cb, startTransition],
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
return [state, wrappedCb, isPending];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return { useValidation, useValidationTransition };
|
|
62
|
-
}
|
package/src/react/form/form.tsx
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { typeToFlattenedError, z, SafeParseReturnType, TypeOf } from 'zod';
|
|
2
|
-
import { createContext, useContext, useMemo } from 'react';
|
|
3
|
-
import clsx from 'clsx';
|
|
4
|
-
|
|
5
|
-
const nonEmpty = 'This field cannot be empty';
|
|
6
|
-
|
|
7
|
-
export const stringRequired = () => z.string({ required_error: nonEmpty }).min(1, nonEmpty);
|
|
8
|
-
export const maxLength = (schema: z.ZodString): number => schema.maxLength || 0;
|
|
9
|
-
export const minLength = (schema: z.ZodString): number => schema.minLength || 0;
|
|
10
|
-
export const isRequired = (schema: z.ZodString): boolean => minLength(schema) > 0;
|
|
11
|
-
|
|
12
|
-
export type ZodObject = z.ZodObject<any> | z.ZodEffects<z.ZodObject<any>>; // z.ZodType<any, any, any>
|
|
13
|
-
export type MaybeTypeOf<S extends ZodObject> = Partial<TypeOf<S>>;
|
|
14
|
-
export type SafeTypeOf<S extends ZodObject> = SafeParseReturnType<TypeOf<S>, TypeOf<S>>['data'];
|
|
15
|
-
export type Errors<S extends ZodObject> = typeToFlattenedError<TypeOf<S>>['fieldErrors'];
|
|
16
|
-
export type Validation<S extends ZodObject> =
|
|
17
|
-
| {
|
|
18
|
-
success: true; // this is true only if form was validated successfully
|
|
19
|
-
data: SafeTypeOf<S>;
|
|
20
|
-
errors?: never;
|
|
21
|
-
}
|
|
22
|
-
| {
|
|
23
|
-
success: false;
|
|
24
|
-
data?: MaybeTypeOf<S>;
|
|
25
|
-
errors?: Errors<S>;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const FormContext = createContext<{
|
|
29
|
-
schema: ZodObject;
|
|
30
|
-
}>(null as never);
|
|
31
|
-
|
|
32
|
-
export const Form = <S extends ZodObject>({ schema, children }: { schema: S; children: any }) => {
|
|
33
|
-
const value = useMemo(() => ({ schema }), [schema]);
|
|
34
|
-
return <FormContext.Provider value={value}>{children}</FormContext.Provider>;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const getShape = <S extends ZodObject>(schema: S) =>
|
|
38
|
-
(schema as z.ZodObject<any>).shape || (schema as z.ZodEffects<z.ZodObject<any>>).sourceType().shape;
|
|
39
|
-
|
|
40
|
-
export function create<S extends ZodObject>(schema: S) {
|
|
41
|
-
if (!getShape(schema)) {
|
|
42
|
-
throw new Error('Invalid schema: only z.object() or z.object().refine() are supported');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function register(name: keyof TypeOf<S>, data?: MaybeTypeOf<S>, errors?: Errors<S>, mui: boolean = false) {
|
|
46
|
-
const field = getShape(schema)[name];
|
|
47
|
-
return {
|
|
48
|
-
name,
|
|
49
|
-
id: name,
|
|
50
|
-
required: isRequired(field),
|
|
51
|
-
maxLength: maxLength(field),
|
|
52
|
-
type: field.isEmail ? 'email' : (name as string).includes('password') ? 'password' : 'text',
|
|
53
|
-
defaultValue: data?.[name],
|
|
54
|
-
...(mui
|
|
55
|
-
? {
|
|
56
|
-
label: field.description,
|
|
57
|
-
helperText: errors?.[name]?.join(', '),
|
|
58
|
-
error: !!errors?.[name]?.length,
|
|
59
|
-
}
|
|
60
|
-
: {}),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function validationError(data: MaybeTypeOf<S>, errors: Errors<S>): Validation<S> {
|
|
65
|
-
return {
|
|
66
|
-
success: false,
|
|
67
|
-
data, // data is undefined if there are errors
|
|
68
|
-
errors, // Next.js will butcher error object, so we provide something more primitive
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function validate(formData: FormData): Validation<S> {
|
|
73
|
-
const rawData = Object.fromEntries(formData) as TypeOf<S>;
|
|
74
|
-
const { error, data } = schema.safeParse(rawData);
|
|
75
|
-
|
|
76
|
-
// console.log('Validate result', { error, data, rawData });
|
|
77
|
-
|
|
78
|
-
if (error) {
|
|
79
|
-
// data is undefined if there are errors
|
|
80
|
-
// Next.js will butcher error object, so we provide something more primitive
|
|
81
|
-
return validationError(rawData, error.flatten().fieldErrors as any);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return { success: true, data };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return { register, validate, validationError };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function Field<S extends ZodObject>({
|
|
91
|
-
children,
|
|
92
|
-
name,
|
|
93
|
-
errors,
|
|
94
|
-
hint,
|
|
95
|
-
className,
|
|
96
|
-
labelProps,
|
|
97
|
-
...props
|
|
98
|
-
}: {
|
|
99
|
-
children?: any;
|
|
100
|
-
name: keyof TypeOf<S>;
|
|
101
|
-
errors?: Validation<S>['errors'];
|
|
102
|
-
hint?: string;
|
|
103
|
-
className?: string;
|
|
104
|
-
labelProps?: any;
|
|
105
|
-
}) {
|
|
106
|
-
const { schema } = useContext(FormContext);
|
|
107
|
-
const { description } = getShape(schema)[name];
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<div {...props} className={clsx('form-row', className)}>
|
|
111
|
-
{description && (
|
|
112
|
-
<label {...labelProps} htmlFor={name}>
|
|
113
|
-
{description}
|
|
114
|
-
</label>
|
|
115
|
-
)}
|
|
116
|
-
{children}
|
|
117
|
-
{hint && <Hint>{hint}</Hint>}
|
|
118
|
-
{errors?.[name]?.map((e: string) => (
|
|
119
|
-
<Hint error key={e}>
|
|
120
|
-
{e}
|
|
121
|
-
</Hint>
|
|
122
|
-
))}
|
|
123
|
-
</div>
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function Hint({ children, error }: { children: any; error?: boolean }) {
|
|
128
|
-
return <div className={`hint ${error ? 'hint-error' : ''}`}>{children}</div>;
|
|
129
|
-
}
|
package/src/react/form/index.ts
DELETED
package/src/react/keyboard.tsx
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useEffect, createContext, useMemo, useState, Dispatch, SetStateAction, useContext } from 'react';
|
|
4
|
-
|
|
5
|
-
const isCtrlOrMeta = (e: KeyboardEvent) => e.metaKey || e.ctrlKey;
|
|
6
|
-
|
|
7
|
-
const EVENT = 'keydown';
|
|
8
|
-
|
|
9
|
-
export type Hotkeys = Record<KeyboardEvent['code'], (e: KeyboardEvent) => void>;
|
|
10
|
-
|
|
11
|
-
export const HotkeysContext = createContext<{
|
|
12
|
-
enabled: boolean;
|
|
13
|
-
setEnabled: Dispatch<SetStateAction<boolean>>;
|
|
14
|
-
}>(null as never);
|
|
15
|
-
|
|
16
|
-
export const HotkeysProvider = ({ children }) => {
|
|
17
|
-
const [enabled, setEnabled] = useState(true);
|
|
18
|
-
|
|
19
|
-
const control = useMemo(() => ({ enabled, setEnabled }), [enabled, setEnabled]);
|
|
20
|
-
|
|
21
|
-
return <HotkeysContext.Provider value={control}>{children}</HotkeysContext.Provider>;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const useHotkeys = (hotkeys: Hotkeys) => {
|
|
25
|
-
const { enabled } = useContext(HotkeysContext);
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (typeof document === 'undefined' || !enabled) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const listeners = (e: KeyboardEvent) => {
|
|
33
|
-
if (!isCtrlOrMeta(e)) return;
|
|
34
|
-
|
|
35
|
-
for (const [code, callback] of Object.entries(hotkeys)) {
|
|
36
|
-
if (e.code === code) {
|
|
37
|
-
callback(e);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
window.addEventListener(EVENT, listeners, true);
|
|
44
|
-
|
|
45
|
-
return () => {
|
|
46
|
-
window.removeEventListener(EVENT, listeners);
|
|
47
|
-
};
|
|
48
|
-
}, [hotkeys, enabled]);
|
|
49
|
-
};
|
package/src/react/useFetch.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useCallback, useState, useTransition } from 'react';
|
|
4
|
-
|
|
5
|
-
//TODO useFetch https://use-http.com
|
|
6
|
-
//TODO SWR?
|
|
7
|
-
//TODO Tanstack Query?
|
|
8
|
-
export function useFetch<R>(
|
|
9
|
-
fn: (...args: any[]) => Promise<R>,
|
|
10
|
-
defaultValue: R | null = null,
|
|
11
|
-
): [R | null, typeof fn, boolean, Error | undefined] {
|
|
12
|
-
// An async function was passed to useActionState, but it was dispatched outside of an action context.
|
|
13
|
-
// This is likely not what you intended. Either pass the dispatch function to an `action` prop, or dispatch manually inside `startTransition`
|
|
14
|
-
const [isPending, startTransition] = useTransition();
|
|
15
|
-
const [data, setData] = useState<R | null>(defaultValue);
|
|
16
|
-
const [error, setError] = useState<Error>();
|
|
17
|
-
|
|
18
|
-
const actionFn = useCallback(
|
|
19
|
-
(...args: Parameters<typeof fn>) => {
|
|
20
|
-
const promise = fn(...args);
|
|
21
|
-
// https://react.dev/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition
|
|
22
|
-
startTransition(() => promise.then(setData).catch(setError)); //FIXME sub-chain...
|
|
23
|
-
return promise;
|
|
24
|
-
},
|
|
25
|
-
[fn],
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
return [data, actionFn, isPending, error];
|
|
29
|
-
}
|
package/src/react/useFetcher.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
export function useFetcher<T = any>(
|
|
4
|
-
cb,
|
|
5
|
-
|
|
6
|
-
{ fetchOnMount = false, onError }: { fetchOnMount?: boolean; onError?: (e: Error) => void } = {},
|
|
7
|
-
) {
|
|
8
|
-
const [loading, setLoading] = useState(fetchOnMount);
|
|
9
|
-
const [error, setError] = useState<Error | null>(null);
|
|
10
|
-
const [data, setData] = useState<T | null>(null);
|
|
11
|
-
|
|
12
|
-
const isMounted = useRef(false);
|
|
13
|
-
|
|
14
|
-
const trigger = useCallback(
|
|
15
|
-
async (...args) => {
|
|
16
|
-
try {
|
|
17
|
-
setLoading(true);
|
|
18
|
-
setError(null);
|
|
19
|
-
const res = await cb(args);
|
|
20
|
-
if (!isMounted.current) return;
|
|
21
|
-
setData(res);
|
|
22
|
-
return res;
|
|
23
|
-
} catch (e) {
|
|
24
|
-
console.error('Fetch failed', e);
|
|
25
|
-
if (!isMounted.current) return;
|
|
26
|
-
setError(e);
|
|
27
|
-
(onError as any)?.(e);
|
|
28
|
-
} finally {
|
|
29
|
-
if (isMounted.current) setLoading(false);
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
[cb, onError],
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
if (fetchOnMount) {
|
|
37
|
-
trigger().catch((e) => console.error('Fetch on mount failed', e)); // catch actually will never happen
|
|
38
|
-
}
|
|
39
|
-
}, [fetchOnMount, cb, trigger]);
|
|
40
|
-
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
isMounted.current = true;
|
|
43
|
-
return () => {
|
|
44
|
-
isMounted.current = false;
|
|
45
|
-
};
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
return { loading, error, data, trigger };
|
|
49
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import * as FileSystem from 'expo-file-system';
|
|
2
|
-
import * as Sharing from 'expo-sharing';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* data:text/plain;base64,W29iamV
|
|
6
|
-
* @see https://stackoverflow.com/questions/69738812/problem-to-generate-pdf-from-a-blob-in-an-expo-app-using-filesystem
|
|
7
|
-
* @param base64
|
|
8
|
-
* @param fileName
|
|
9
|
-
* @returns {Promise<void>}
|
|
10
|
-
*/
|
|
11
|
-
export const shareDialog = async (base64, fileName) => {
|
|
12
|
-
const path = `${FileSystem.documentDirectory}/${fileName}`;
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
if (!(await Sharing.isAvailableAsync())) throw new Error('Sharing is not available');
|
|
16
|
-
|
|
17
|
-
const [header, buffer] = base64.split(',');
|
|
18
|
-
const [, mimeTypeStr] = header.split(':');
|
|
19
|
-
const [mimeType] = mimeTypeStr.split(';');
|
|
20
|
-
|
|
21
|
-
await FileSystem.writeAsStringAsync(`${path}`, buffer, {
|
|
22
|
-
encoding: FileSystem.EncodingType.Base64,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
await Sharing.shareAsync(path, { mimeType, UTI: fileName, dialogTitle: 'Save or share document' });
|
|
26
|
-
} catch (error) {
|
|
27
|
-
alert('Sharing failed: ' + error.message);
|
|
28
|
-
} finally {
|
|
29
|
-
await FileSystem.deleteAsync(path);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import * as Updates from 'expo-updates';
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
|
-
import { Text } from 'react-native';
|
|
4
|
-
|
|
5
|
-
export function Update({ children }) {
|
|
6
|
-
//FIXME useUpdates https://blog.expo.dev/feature-preview-updates-js-api-for-expo-updates-3b92beb40dab
|
|
7
|
-
const [updating, setUpdating] = useState(true);
|
|
8
|
-
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
(async () => {
|
|
11
|
-
try {
|
|
12
|
-
if (__DEV__) {
|
|
13
|
-
setUpdating(false);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const update = await Updates.checkForUpdateAsync();
|
|
18
|
-
|
|
19
|
-
if (!update.isAvailable) {
|
|
20
|
-
setUpdating(false);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
await Updates.fetchUpdateAsync();
|
|
25
|
-
alert('Update is available. App will reload.');
|
|
26
|
-
await Updates.reloadAsync();
|
|
27
|
-
} catch (error) {
|
|
28
|
-
// You can also add an alert() to see the error message in case of an error when fetching updates.
|
|
29
|
-
alert(`Error fetching latest Expo update: ${error}`);
|
|
30
|
-
setUpdating(false);
|
|
31
|
-
}
|
|
32
|
-
})();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
if (updating) {
|
|
36
|
-
return <Text>Checking for updates ({Updates.channel})...</Text>;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return children;
|
|
40
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import { AppState } from 'react-native';
|
|
3
|
-
|
|
4
|
-
export function useAppState() {
|
|
5
|
-
const [appState, setAppState] = useState(AppState.currentState);
|
|
6
|
-
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
const subscription = AppState.addEventListener('change', (nextAppState) => {
|
|
9
|
-
setAppState(nextAppState);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
return () => {
|
|
13
|
-
subscription.remove();
|
|
14
|
-
};
|
|
15
|
-
}, []);
|
|
16
|
-
|
|
17
|
-
return appState;
|
|
18
|
-
}
|
package/src/tailwind/README.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
export const Fullpage = ({ divRef = null, className = '', children, ...props }) => (
|
|
4
|
-
<div
|
|
5
|
-
ref={divRef}
|
|
6
|
-
{...props}
|
|
7
|
-
className={`container h-screen flex flex-col justify-center items-center ${className}`}
|
|
8
|
-
>
|
|
9
|
-
{children}
|
|
10
|
-
</div>
|
|
11
|
-
);
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
|
|
5
|
-
export function ResponsiveHelperTW() {
|
|
6
|
-
return (
|
|
7
|
-
<span className="fixed bottom-0 right-2 z-30 leading-none text-xs">
|
|
8
|
-
<small className="hidden xs:max-sm:block">XS</small>
|
|
9
|
-
<small className="hidden sm:max-md:block">SM</small>
|
|
10
|
-
<small className="hidden md:max-lg:block">MD</small>
|
|
11
|
-
<small className="hidden lg:max-xl:block">LG</small>
|
|
12
|
-
<small className="hidden xl:max-2xl:block">XL</small>
|
|
13
|
-
<small className="hidden 2xl:block">XXL</small>
|
|
14
|
-
</span>
|
|
15
|
-
);
|
|
16
|
-
}
|