@kirill.konshin/utils 0.0.8 → 0.0.10
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 +10 -0
- package/.storybook/main.ts +21 -0
- package/.storybook/preview.ts +17 -0
- package/.turbo/turbo-build.log +67 -0
- package/.turbo/turbo-test.log +118 -0
- package/CHANGELOG.md +12 -0
- package/README.md +59 -0
- package/builders/.swcrc +18 -0
- package/builders/build.config.ts +11 -0
- package/builders/bun.build.js +23 -0
- package/builders/package.json +209 -0
- package/builders/perf.mjs +63 -0
- package/builders/rollup.config.mjs +50 -0
- package/builders/rslib.config.ts +26 -0
- package/builders/tsconfig.json +21 -0
- package/builders/tsup.config.ts +20 -0
- package/builders/turbo.json +24 -0
- package/builders/vite.config.ts +37 -0
- package/demo/cache-demo.ts +2 -1
- package/package.json +166 -22
- package/src/bootstrap/adaptiveContainer.tsx +12 -0
- package/src/bootstrap/controls.stories.tsx +62 -0
- package/src/bootstrap/controls.tsx +119 -0
- package/src/bootstrap/error.stories.tsx +34 -0
- package/src/bootstrap/error.tsx +40 -0
- package/src/bootstrap/field.stories.tsx +42 -0
- package/src/bootstrap/field.tsx +35 -0
- package/src/bootstrap/footer.tsx +49 -0
- package/src/bootstrap/globalLoading.stories.tsx +25 -0
- package/src/bootstrap/globalLoading.tsx +17 -0
- package/src/bootstrap/index.ts +12 -0
- package/src/bootstrap/loading.stories.tsx +35 -0
- package/src/bootstrap/loading.tsx +22 -0
- package/src/bootstrap/main.scss +86 -0
- package/src/bootstrap/responsiveHelper.tsx +50 -0
- package/src/bootstrap/screen.stories.tsx +160 -0
- package/src/bootstrap/screen.tsx +144 -0
- package/src/bootstrap/toaster.stories.tsx +32 -0
- package/src/bootstrap/toaster.tsx +38 -0
- package/src/bootstrap/useModal.stories.tsx +51 -0
- package/src/bootstrap/useModal.tsx +88 -0
- package/src/bootstrap/useWrappedForm.ts +40 -0
- package/src/core/cache.test.ts +121 -0
- package/src/electron/README.md +13 -0
- package/src/electron/createWindow.ts +234 -0
- package/src/electron/index.ts +2 -0
- package/src/electron/updater.ts +54 -0
- package/src/electron-builder/builder.ts +150 -0
- package/src/electron-builder/images.ts +33 -0
- package/src/electron-builder/index.ts +2 -0
- package/src/mui/README.md +3 -0
- package/src/mui/formControlFieldset.stories.tsx +71 -0
- package/src/mui/formControlFieldset.tsx +26 -0
- package/src/mui/formLabelLegend.tsx +11 -0
- package/src/mui/genericControl.tsx +20 -0
- package/src/mui/index.ts +4 -0
- package/src/mui/readOnly.tsx +6 -0
- package/src/next/appLink.tsx +39 -0
- package/src/next/index.ts +5 -0
- package/src/next/measure.ts +7 -0
- package/src/next/noSSR.tsx +17 -0
- package/src/next/redirect.tsx +13 -0
- package/src/next/useIsInner.ts +13 -0
- package/src/react/apiCall.ts +25 -0
- package/src/react/form/client.tsx +62 -0
- package/src/react/form/form.tsx +109 -0
- package/src/react/form/index.ts +2 -0
- package/src/react/index.ts +4 -0
- package/src/react/useFetch.ts +29 -0
- package/src/react/useFetcher.ts +49 -0
- package/src/react-native/index.ts +3 -0
- package/src/react-native/share.ts +31 -0
- package/src/react-native/update.tsx +40 -0
- package/src/react-native/useAppState.ts +18 -0
- package/src/tailwind/fullpage.tsx +11 -0
- package/src/tailwind/index.ts +2 -0
- package/src/tailwind/responsiveHelper.tsx +16 -0
- package/src-todo/auth0.tsx +177 -0
- package/tsconfig.json +15 -18
- package/turbo.json +2 -11
- package/vite.config.ts +47 -0
- package/vite.exports.ts +121 -0
- package/build/cache.d.ts +0 -120
- package/build/cache.js +0 -191
- package/build/errors.d.ts +0 -1
- package/build/errors.js +0 -14
- package/build/index.d.ts +0 -5
- package/build/index.js +0 -5
- package/build/measure.d.ts +0 -34
- package/build/measure.js +0 -48
- package/build/mutex.d.ts +0 -5
- package/build/mutex.js +0 -23
- package/build/worker.d.ts +0 -83
- package/build/worker.js +0 -250
- package/tsconfig.tsbuildinfo +0 -1
- package/src/{cache.ts → core/cache.ts} +0 -0
- package/src/{errors.ts → core/errors.ts} +0 -0
- package/src/{index.ts → core/index.ts} +1 -1
- /package/src/{measure.ts → core/measure.ts} +0 -0
- /package/src/{mutex.ts → core/mutex.ts} +0 -0
- /package/src/{worker.ts → core/worker.ts} +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { globSync } from 'glob';
|
|
2
|
+
import dts from 'vite-plugin-dts';
|
|
3
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
4
|
+
import swc from '@rollup/plugin-swc';
|
|
5
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
6
|
+
import del from 'rollup-plugin-delete';
|
|
7
|
+
import multi from '@rollup/plugin-multi-entry';
|
|
8
|
+
import { fixExports, excludeGlob, includeGlob, entryGlob, entry, external } from './exports.mjs';
|
|
9
|
+
|
|
10
|
+
//FIXME https://github.com/rollup/rollup/issues/4629 watch spits all files
|
|
11
|
+
//FIXME https://github.com/rollup/rollup/issues/3150 watch spits all files
|
|
12
|
+
//FIXME Multi produces virtual files
|
|
13
|
+
|
|
14
|
+
const dir = 'dist-rollpup';
|
|
15
|
+
|
|
16
|
+
/** @type {import('rollup').RollupOptions} */
|
|
17
|
+
const config = {
|
|
18
|
+
// input: includeGlob, // multi
|
|
19
|
+
// input: entryGlob, // multi
|
|
20
|
+
input: entry, // glob array, seems to be a bit faster
|
|
21
|
+
// ignore: excludeGlob,
|
|
22
|
+
output: {
|
|
23
|
+
dir,
|
|
24
|
+
preserveModules: true,
|
|
25
|
+
preserveModulesRoot: 'src',
|
|
26
|
+
sourcemap: true,
|
|
27
|
+
format: 'es',
|
|
28
|
+
},
|
|
29
|
+
external,
|
|
30
|
+
onwarn(warning, warn) {
|
|
31
|
+
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') return;
|
|
32
|
+
warn(warning);
|
|
33
|
+
},
|
|
34
|
+
plugins: [
|
|
35
|
+
del({ targets: dir, runOnce: true }),
|
|
36
|
+
swc(),
|
|
37
|
+
commonjs(),
|
|
38
|
+
resolve({ extensions: ['.ts', '.tsx'] }),
|
|
39
|
+
dts({ outDir: dir }), // exclude: excludeGlob,
|
|
40
|
+
// multi({ preserveModules: true }),
|
|
41
|
+
{
|
|
42
|
+
name: 'Generate Exports',
|
|
43
|
+
async buildEnd() {
|
|
44
|
+
// await fixExports();
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default config;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineConfig } from '@rslib/core';
|
|
2
|
+
import type { RsbuildPlugin } from '@rsbuild/core';
|
|
3
|
+
import { fixExports, generateIndex, includeGlob } from './vite.exports';
|
|
4
|
+
|
|
5
|
+
//FIXME https://github.com/egoist/tsup/issues/945 dts is slow
|
|
6
|
+
//TODO https://api-extractor.com/pages/setup/invoking/ instead of dts
|
|
7
|
+
//TODO https://github.com/egoist/tsup/issues/615 incremental
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
lib: [{ bundle: false, format: 'esm', dts: { bundle: false } }],
|
|
11
|
+
source: { entry: { index: includeGlob } },
|
|
12
|
+
output: { sourceMap: true, cleanDistPath: true, distPath: { root: 'dist-rslib' } },
|
|
13
|
+
plugins: [
|
|
14
|
+
// {
|
|
15
|
+
// name: 'Generate Index & Exports',
|
|
16
|
+
// setup(api) {
|
|
17
|
+
// api.onBeforeBuild(async () => {
|
|
18
|
+
// await generateIndex();
|
|
19
|
+
// });
|
|
20
|
+
// api.onAfterBuild(async () => {
|
|
21
|
+
// await fixExports();
|
|
22
|
+
// });
|
|
23
|
+
// },
|
|
24
|
+
// } satisfies RsbuildPlugin,
|
|
25
|
+
],
|
|
26
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "src",
|
|
5
|
+
"outDir": "dist",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"declarationDir": "dist",
|
|
9
|
+
"incremental": false,
|
|
10
|
+
"allowJs": true,
|
|
11
|
+
/* Build-specific options */
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"moduleDetection": "force",
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx"
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"],
|
|
20
|
+
"exclude": ["**/*.test.ts", "**/*.stories.ts", "**/*.stories.tsx"]
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup';
|
|
2
|
+
import { fixExports, formats, includeGlob } from './exports.mjs';
|
|
3
|
+
|
|
4
|
+
//FIXME https://github.com/egoist/tsup/issues/945 dts is slow
|
|
5
|
+
//TODO https://api-extractor.com/pages/setup/invoking/ instead of dts
|
|
6
|
+
//TODO https://github.com/egoist/tsup/issues/615 incremental
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
outDir: 'dist-tsup',
|
|
10
|
+
entry: [includeGlob],
|
|
11
|
+
format: Object.keys(formats) as any,
|
|
12
|
+
bundle: false,
|
|
13
|
+
splitting: false,
|
|
14
|
+
sourcemap: true,
|
|
15
|
+
clean: true,
|
|
16
|
+
dts: true,
|
|
17
|
+
async onSuccess() {
|
|
18
|
+
// await fixExports();
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://turbo.build/schema.json",
|
|
3
|
+
"extends": ["//"],
|
|
4
|
+
"tasks": {
|
|
5
|
+
"build": {
|
|
6
|
+
"dependsOn": ["^build", "build:vite", "build:exports"]
|
|
7
|
+
},
|
|
8
|
+
"build:exports": {
|
|
9
|
+
"outputs": ["package.json"]
|
|
10
|
+
},
|
|
11
|
+
"build:index": {
|
|
12
|
+
"outputs": ["src/**/*/index.ts"]
|
|
13
|
+
},
|
|
14
|
+
"build:vite": {
|
|
15
|
+
"outputs": ["dist/**/*"],
|
|
16
|
+
"dependsOn": ["build:index"]
|
|
17
|
+
},
|
|
18
|
+
"start": {
|
|
19
|
+
"persistent": true,
|
|
20
|
+
"cache": false,
|
|
21
|
+
"dependsOn": ["build:index", "build:exports"]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import dts from 'vite-plugin-dts';
|
|
4
|
+
import { fixExports, formats, entry, external, distDir } from './exports.mjs';
|
|
5
|
+
|
|
6
|
+
// https://rbardini.com/how-to-build-ts-library-with-vite/
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
build: {
|
|
10
|
+
ssr: true,
|
|
11
|
+
sourcemap: true,
|
|
12
|
+
outDir: distDir,
|
|
13
|
+
emptyOutDir: true,
|
|
14
|
+
// target: 'esnext',
|
|
15
|
+
lib: {
|
|
16
|
+
entry,
|
|
17
|
+
formats: Object.keys(formats) as any,
|
|
18
|
+
},
|
|
19
|
+
rollupOptions: {
|
|
20
|
+
external,
|
|
21
|
+
output: {
|
|
22
|
+
preserveModules: true,
|
|
23
|
+
preserveModulesRoot: 'src',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
plugins: [
|
|
28
|
+
react(),
|
|
29
|
+
dts(),
|
|
30
|
+
{
|
|
31
|
+
name: 'Generate Exports',
|
|
32
|
+
async buildEnd() {
|
|
33
|
+
// await fixExports();
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
});
|
package/demo/cache-demo.ts
CHANGED
|
@@ -188,7 +188,8 @@ function create<
|
|
|
188
188
|
S extends ResSchemaFinal<ResSchema>,
|
|
189
189
|
M extends keyof S,
|
|
190
190
|
F extends (key: S[M][0], input: S[M][1]) => S[M][2],
|
|
191
|
-
>(schema: S, message: M, responder: F): F {
|
|
191
|
+
>(schema: S, message: M, responder: F): F {
|
|
192
|
+
// context: Context<S, M, 'response'>
|
|
192
193
|
return responder as any;
|
|
193
194
|
}
|
|
194
195
|
|
package/package.json
CHANGED
|
@@ -1,37 +1,181 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kirill.konshin/utils",
|
|
3
|
-
"
|
|
3
|
+
"description": "Utilities",
|
|
4
|
+
"version": "0.0.10",
|
|
4
5
|
"type": "module",
|
|
5
|
-
"main": "build/index.js",
|
|
6
|
-
"module": "build/index.js",
|
|
7
|
-
"types": "build/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": "./build/index.js",
|
|
10
|
-
"./cache": "./build/cache.js",
|
|
11
|
-
"./errors": "./build/errors.js",
|
|
12
|
-
"./measure": "./build/measure.js",
|
|
13
|
-
"./mutex": "./build/mutex.js",
|
|
14
|
-
"./worker": "./build/worker.js"
|
|
15
|
-
},
|
|
16
6
|
"scripts": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
7
|
+
"----- BUILD -----": "",
|
|
8
|
+
"clean": "rm -rf dist .tscache tsconfig.tsbuildinfo",
|
|
9
|
+
"build": "vite build",
|
|
10
|
+
"build:index": "cti create ./src/*",
|
|
11
|
+
"build:check-types": "attw --pack .",
|
|
12
|
+
"start": "yarn build --watch",
|
|
13
|
+
"wait": "wait-on ./dist/core/index.mjs",
|
|
14
|
+
"----- TEST -----": "",
|
|
15
|
+
"test": "vitest run --coverage",
|
|
16
|
+
"test:watch": "vitest watch --coverage",
|
|
17
|
+
"----- STORYBOOK -----": "",
|
|
18
|
+
"storybook:start": "storybook dev -p 6006",
|
|
19
|
+
"storybook:build": "storybook build"
|
|
21
20
|
},
|
|
22
21
|
"dependencies": {
|
|
22
|
+
"clsx": "^2.1.1",
|
|
23
23
|
"colors": "^1.4.0",
|
|
24
|
-
"
|
|
24
|
+
"expo-file-system": "^18.0.7",
|
|
25
|
+
"expo-sharing": "^13.0.1",
|
|
26
|
+
"expo-updates": "^0.26.13",
|
|
27
|
+
"many-keys-map": "^2.0.1",
|
|
28
|
+
"psd": "^3.4.0",
|
|
29
|
+
"react-hook-form": "^7.54.2",
|
|
30
|
+
"sharp": "^0.33.5"
|
|
25
31
|
},
|
|
26
32
|
"devDependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"
|
|
29
|
-
"
|
|
33
|
+
"@arethetypeswrong/cli": "^0.17.3",
|
|
34
|
+
"@chromatic-com/storybook": "^3.2.4",
|
|
35
|
+
"@emotion/react": "^11.14.0",
|
|
36
|
+
"@emotion/styled": "^11.14.0",
|
|
37
|
+
"@mui/material": "^6.4.2",
|
|
38
|
+
"@mui/styled-engine": "^6.4.2",
|
|
39
|
+
"@storybook/addon-essentials": "^8.5.2",
|
|
40
|
+
"@storybook/addon-interactions": "^8.5.2",
|
|
41
|
+
"@storybook/addon-onboarding": "^8.5.2",
|
|
42
|
+
"@storybook/blocks": "^8.5.2",
|
|
43
|
+
"@storybook/react": "^8.5.2",
|
|
44
|
+
"@storybook/react-vite": "^8.5.2",
|
|
45
|
+
"@storybook/test": "^8.5.2",
|
|
46
|
+
"@types/psd": "^3.4.3",
|
|
47
|
+
"@vitest/coverage-v8": "^3.0.4",
|
|
48
|
+
"bootstrap": "^5.3.3",
|
|
49
|
+
"bootstrap-icons": "^1.11.3",
|
|
50
|
+
"create-ts-index": "^1.14.0",
|
|
51
|
+
"electron": "^34.0.1",
|
|
52
|
+
"electron-builder": "^25.1.8",
|
|
53
|
+
"electron-default-menu": "^1.0.2",
|
|
54
|
+
"electron-store": "^10.0.1",
|
|
55
|
+
"electron-updater": "^6.4.0",
|
|
56
|
+
"glob": "^11.0.1",
|
|
57
|
+
"next": "^15.1.6",
|
|
58
|
+
"react-bootstrap": "^2.10.8",
|
|
59
|
+
"react-native": "^0.77.0",
|
|
60
|
+
"sass-embedded": "^1.83.4",
|
|
61
|
+
"storybook": "^8.5.2",
|
|
62
|
+
"tailwindcss": "^4.0.1",
|
|
63
|
+
"vite": "^6.0.11",
|
|
64
|
+
"vitest": "^3.0.4",
|
|
65
|
+
"zod": "^3.24.1"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"@mui/material": "^6",
|
|
69
|
+
"bootstrap": "^5",
|
|
70
|
+
"bootstrap-icons": "^1",
|
|
71
|
+
"electron": "^34",
|
|
72
|
+
"next": "^15",
|
|
73
|
+
"react": "^19",
|
|
74
|
+
"react-bootstrap": "^2",
|
|
75
|
+
"react-native": "^0.77",
|
|
76
|
+
"tailwindcss": "^4",
|
|
77
|
+
"zod": "^3"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"@mui/material": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"bootstrap": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"bootstrap-icons": {
|
|
87
|
+
"optional": true
|
|
88
|
+
},
|
|
89
|
+
"electron": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"next": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"react": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"react-bootstrap": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"react-native": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"tailwindcss": {
|
|
105
|
+
"optional": true
|
|
106
|
+
},
|
|
107
|
+
"zod": {
|
|
108
|
+
"optional": true
|
|
109
|
+
}
|
|
30
110
|
},
|
|
31
111
|
"publishConfig": {
|
|
32
112
|
"access": "public"
|
|
33
113
|
},
|
|
34
114
|
"author": "Kirill Konshin <kirill@konshin.org> (https://konshin.org)",
|
|
35
115
|
"license": "MIT",
|
|
36
|
-
"
|
|
37
|
-
|
|
116
|
+
"exports": {
|
|
117
|
+
"./tailwind": {
|
|
118
|
+
"import": {
|
|
119
|
+
"import": "./dist/tailwind/index.mjs",
|
|
120
|
+
"types": "./dist/tailwind/index.d.ts"
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"./react-native": {
|
|
124
|
+
"import": {
|
|
125
|
+
"import": "./dist/react-native/index.mjs",
|
|
126
|
+
"types": "./dist/react-native/index.d.ts"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"./react": {
|
|
130
|
+
"import": {
|
|
131
|
+
"import": "./dist/react/index.mjs",
|
|
132
|
+
"types": "./dist/react/index.d.ts"
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"./next": {
|
|
136
|
+
"import": {
|
|
137
|
+
"import": "./dist/next/index.mjs",
|
|
138
|
+
"types": "./dist/next/index.d.ts"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"./mui": {
|
|
142
|
+
"import": {
|
|
143
|
+
"import": "./dist/mui/index.mjs",
|
|
144
|
+
"types": "./dist/mui/index.d.ts"
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"./electron-builder": {
|
|
148
|
+
"import": {
|
|
149
|
+
"import": "./dist/electron-builder/index.mjs",
|
|
150
|
+
"types": "./dist/electron-builder/index.d.ts"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
"./electron": {
|
|
154
|
+
"import": {
|
|
155
|
+
"import": "./dist/electron/index.mjs",
|
|
156
|
+
"types": "./dist/electron/index.d.ts"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"./core": {
|
|
160
|
+
"import": {
|
|
161
|
+
"import": "./dist/core/index.mjs",
|
|
162
|
+
"types": "./dist/core/index.d.ts"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"./bootstrap": {
|
|
166
|
+
"import": {
|
|
167
|
+
"import": "./dist/bootstrap/index.mjs",
|
|
168
|
+
"types": "./dist/bootstrap/index.d.ts"
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
".": {
|
|
172
|
+
"import": {
|
|
173
|
+
"import": "./dist/core/index.mjs",
|
|
174
|
+
"types": "./dist/core/index.d.ts"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"main": "./dist/core/index.mjs",
|
|
179
|
+
"module": "./dist/core/index.mjs",
|
|
180
|
+
"types": "./dist/core/index.d.ts"
|
|
181
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Container, ContainerProps } from 'react-bootstrap';
|
|
3
|
+
import { useBreakpoint } from './responsiveHelper';
|
|
4
|
+
|
|
5
|
+
export function AdaptiveContainer({ children, ...props }: ContainerProps) {
|
|
6
|
+
const { isMobile } = useBreakpoint();
|
|
7
|
+
return (
|
|
8
|
+
<Container fluid={isMobile} {...props}>
|
|
9
|
+
{children}
|
|
10
|
+
</Container>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { cloneElement, useCallback, useState } from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { fn } from '@storybook/test';
|
|
4
|
+
|
|
5
|
+
import { Select, Control, Range, Checkbox } from './controls';
|
|
6
|
+
|
|
7
|
+
const defaultOptions = { num: 1, bool: false, select: 'bar' };
|
|
8
|
+
|
|
9
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
|
10
|
+
const meta = {
|
|
11
|
+
title: 'Bootstrap / Controls',
|
|
12
|
+
parameters: {
|
|
13
|
+
layout: 'centered',
|
|
14
|
+
},
|
|
15
|
+
tags: ['autodocs'],
|
|
16
|
+
argTypes: {},
|
|
17
|
+
args: { options: { ...defaultOptions }, setOptions: fn(), defaultOptions: { ...defaultOptions }, name: 'unused' },
|
|
18
|
+
render: function Demo(args) {
|
|
19
|
+
const [options, setOptionsRaw] = useState(args.options);
|
|
20
|
+
|
|
21
|
+
const setOptions = useCallback(
|
|
22
|
+
(options) =>
|
|
23
|
+
setOptionsRaw((currentOptions) => {
|
|
24
|
+
return { ...currentOptions, ...options };
|
|
25
|
+
}),
|
|
26
|
+
[],
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const controlProps = { options, setOptions, defaultOptions };
|
|
30
|
+
|
|
31
|
+
const { children, name, ...safeArgs } = args;
|
|
32
|
+
|
|
33
|
+
return <div style={{ width: '300px' }}>{cloneElement(children as any, { ...safeArgs, ...controlProps })}</div>;
|
|
34
|
+
},
|
|
35
|
+
} satisfies Meta<typeof Control>;
|
|
36
|
+
|
|
37
|
+
export default meta;
|
|
38
|
+
|
|
39
|
+
type Story = StoryObj<typeof meta>;
|
|
40
|
+
|
|
41
|
+
export const RangeControl: Story = {
|
|
42
|
+
args: {
|
|
43
|
+
children: <Range name="Num" min={0} max={1} />,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const CheckboxControl: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
children: <Checkbox name="Bool" />,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const SelectControl: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
children: (
|
|
56
|
+
<Select name="Select">
|
|
57
|
+
<option value="foo">Foo</option>
|
|
58
|
+
<option value="bar">Bar</option>
|
|
59
|
+
</Select>
|
|
60
|
+
),
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import React, { HTMLInputTypeAttribute, memo } from 'react';
|
|
2
|
+
|
|
3
|
+
const lcFirst = (str) => str[0].toLowerCase() + str.substring(1, str.length);
|
|
4
|
+
|
|
5
|
+
const toProperty = (str) => lcFirst(str).split(' ').join('');
|
|
6
|
+
|
|
7
|
+
interface ControlProps {
|
|
8
|
+
value?: any;
|
|
9
|
+
setValue?: (v: any) => void;
|
|
10
|
+
defaultValue?: any;
|
|
11
|
+
options?: { [key: string]: any };
|
|
12
|
+
setOptions?: (v: { [key: string]: any }) => void;
|
|
13
|
+
defaultOptions?: { [key: string]: any };
|
|
14
|
+
name: string;
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
inputProps?: {
|
|
17
|
+
type: HTMLInputTypeAttribute;
|
|
18
|
+
property?: string;
|
|
19
|
+
valueExtractor?: (e: any) => any;
|
|
20
|
+
className?: string;
|
|
21
|
+
} & any;
|
|
22
|
+
hideValue?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type LabelProps = Pick<ControlProps, 'name' | 'value' | 'defaultValue'> & { reset: () => void };
|
|
26
|
+
|
|
27
|
+
const Label = memo<LabelProps>(function Label({ name, reset, value, defaultValue }) {
|
|
28
|
+
return (
|
|
29
|
+
<label className="flex-grow-1 mb-0 d-flex align-items-center justify-content-start gap-2">
|
|
30
|
+
{name}
|
|
31
|
+
{value !== defaultValue && (
|
|
32
|
+
<>
|
|
33
|
+
<a href="javascript: void(0)" onClick={reset}>
|
|
34
|
+
<small>reset</small>
|
|
35
|
+
</a>
|
|
36
|
+
</>
|
|
37
|
+
)}
|
|
38
|
+
</label>
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const Control = memo<ControlProps>(function Control({
|
|
43
|
+
value = null,
|
|
44
|
+
setValue,
|
|
45
|
+
defaultValue = null,
|
|
46
|
+
options = {},
|
|
47
|
+
setOptions,
|
|
48
|
+
defaultOptions = {},
|
|
49
|
+
name,
|
|
50
|
+
inputProps: { Tag = 'input', property = 'value', valueExtractor = (e) => e.target.value, ...inputProps } = {},
|
|
51
|
+
hideValue = false,
|
|
52
|
+
children,
|
|
53
|
+
}) {
|
|
54
|
+
const prop = toProperty(name);
|
|
55
|
+
|
|
56
|
+
defaultValue = defaultValue || defaultOptions[prop];
|
|
57
|
+
value = value || options?.[prop];
|
|
58
|
+
setValue = setValue || ((v) => setOptions?.({ [prop]: v }));
|
|
59
|
+
|
|
60
|
+
const reset = () => setValue(defaultValue);
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div className="d-flex align-items-center gap-2">
|
|
64
|
+
<Label name={name} reset={reset} value={value} defaultValue={defaultValue} />
|
|
65
|
+
<Tag
|
|
66
|
+
{...inputProps}
|
|
67
|
+
{...{ [property]: value || '' }} // null is needed to make it always controlled
|
|
68
|
+
className={`${value === defaultValue ? 'opacity-75' : ''} ${inputProps.className}`}
|
|
69
|
+
onChange={(e) => setValue(valueExtractor(e))}
|
|
70
|
+
>
|
|
71
|
+
{children}
|
|
72
|
+
</Tag>
|
|
73
|
+
{!hideValue && (
|
|
74
|
+
<span onDoubleClick={reset} className="text-start" style={{ width: '20px' }}>
|
|
75
|
+
{value}
|
|
76
|
+
</span>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
export interface RangeProps extends ControlProps {
|
|
83
|
+
min: number;
|
|
84
|
+
max: number;
|
|
85
|
+
step?: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export const Range = memo<RangeProps>(function Range({ min, max, step = 0.1, ...props }) {
|
|
89
|
+
return (
|
|
90
|
+
<Control
|
|
91
|
+
inputProps={{
|
|
92
|
+
type: 'range',
|
|
93
|
+
min,
|
|
94
|
+
max,
|
|
95
|
+
step,
|
|
96
|
+
className: 'form-control-range',
|
|
97
|
+
valueExtractor: (e) => parseFloat(e.target.value),
|
|
98
|
+
}}
|
|
99
|
+
{...props}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export const Checkbox = memo<ControlProps>(function Checkbox(props) {
|
|
105
|
+
return (
|
|
106
|
+
<Control
|
|
107
|
+
inputProps={{ type: 'checkbox', property: 'checked', valueExtractor: (e) => e.target.checked }}
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export const Select = memo<ControlProps>(function Select({ children, ...props }) {
|
|
114
|
+
return (
|
|
115
|
+
<Control inputProps={{ Tag: 'select', className: 'form-select' }} {...props} hideValue={true}>
|
|
116
|
+
{children}
|
|
117
|
+
</Control>
|
|
118
|
+
);
|
|
119
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
3
|
+
|
|
4
|
+
import { ErrorAlert } from './error';
|
|
5
|
+
|
|
6
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Bootstrap / ErrorAlert',
|
|
9
|
+
component: ErrorAlert,
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: 'centered',
|
|
12
|
+
},
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
argTypes: {
|
|
15
|
+
// backgroundColor: { control: 'color' },
|
|
16
|
+
children: { control: 'text' },
|
|
17
|
+
},
|
|
18
|
+
args: { onRetry: fn() },
|
|
19
|
+
} satisfies Meta<typeof ErrorAlert>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof meta>;
|
|
23
|
+
|
|
24
|
+
export const String: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
children: 'An error occurred',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const ErrorObject: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
children: new Error('An error occurred'),
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Alert, AlertProps, Button, ButtonProps } from 'react-bootstrap';
|
|
5
|
+
|
|
6
|
+
//TODO Create MUI-specific?
|
|
7
|
+
export function ErrorAlert({
|
|
8
|
+
onRetry,
|
|
9
|
+
children,
|
|
10
|
+
buttonProps,
|
|
11
|
+
...props
|
|
12
|
+
}: {
|
|
13
|
+
children?: Error | string | any;
|
|
14
|
+
onRetry?: () => any;
|
|
15
|
+
buttonProps?: ButtonProps;
|
|
16
|
+
}) {
|
|
17
|
+
if (!children) return null;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Alert variant="danger" {...props}>
|
|
21
|
+
<div>{children.message || children.toString()}</div>
|
|
22
|
+
{onRetry && (
|
|
23
|
+
<div>
|
|
24
|
+
<Button
|
|
25
|
+
variant="link"
|
|
26
|
+
className="alert-link"
|
|
27
|
+
{...buttonProps}
|
|
28
|
+
onClick={(e) => {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
e.stopPropagation();
|
|
31
|
+
onRetry();
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
Retry
|
|
35
|
+
</Button>
|
|
36
|
+
</div>
|
|
37
|
+
)}
|
|
38
|
+
</Alert>
|
|
39
|
+
);
|
|
40
|
+
}
|