@king26/wk-react-tools 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/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/react/forEach.d.ts +12 -0
- package/dist/react/forEach.d.ts.map +1 -0
- package/dist/react/forEach.js +20 -0
- package/dist/react/forEach.js.map +1 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +9 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/switch.d.ts +20 -0
- package/dist/react/switch.d.ts.map +1 -0
- package/dist/react/switch.js +35 -0
- package/dist/react/switch.js.map +1 -0
- package/dist/zustand/index.d.ts +24 -0
- package/dist/zustand/index.d.ts.map +1 -0
- package/dist/zustand/index.js +70 -0
- package/dist/zustand/index.js.map +1 -0
- package/package.json +50 -0
- package/src/index.ts +2 -0
- package/src/react/forEach.tsx +44 -0
- package/src/react/index.tsx +2 -0
- package/src/react/switch.tsx +56 -0
- package/src/zustand/index.ts +205 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./react"), exports);
|
|
18
|
+
__exportStar(require("./zustand"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,4CAA0B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
interface ForEachProps<T = unknown> {
|
|
4
|
+
of: T[];
|
|
5
|
+
children: (item: T, index: number) => ReactNode;
|
|
6
|
+
default?: ReactNode;
|
|
7
|
+
keyExtractor?: (item: T, index: number) => string | number;
|
|
8
|
+
}
|
|
9
|
+
export declare function ForEach<T = unknown>({ of: items, children: render, default: defaultChild, keyExtractor, }: ForEachProps<T>): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
export declare function forEachExample(): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=forEach.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forEach.d.ts","sourceRoot":"","sources":["../../src/react/forEach.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,UAAU,YAAY,CAAC,CAAC,GAAG,OAAO;IAChC,EAAE,EAAE,CAAC,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAChD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC;CAC5D;AAED,wBAAgB,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,EACnC,EAAE,EAAE,KAAK,EACT,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,EACrB,YAAkC,GACnC,EAAE,YAAY,CAAC,CAAC,CAAC,0GAcjB;AAED,wBAAgB,cAAc,4CAY7B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ForEach = ForEach;
|
|
7
|
+
exports.forEachExample = forEachExample;
|
|
8
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
9
|
+
const react_1 = __importDefault(require("react"));
|
|
10
|
+
function ForEach({ of: items, children: render, default: defaultChild, keyExtractor = (_, index) => index, }) {
|
|
11
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
12
|
+
return defaultChild ?? null;
|
|
13
|
+
}
|
|
14
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: render(item, index) }, keyExtractor(item, index)))) }));
|
|
15
|
+
}
|
|
16
|
+
function forEachExample() {
|
|
17
|
+
const items = ["Apple", "Banana", "Cherry"];
|
|
18
|
+
return ((0, jsx_runtime_1.jsx)(ForEach, { of: items, default: (0, jsx_runtime_1.jsx)("div", { children: "No items" }), children: (item, index) => ((0, jsx_runtime_1.jsxs)("div", { children: [index + 1, ". ", item] }, item)) }));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=forEach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forEach.js","sourceRoot":"","sources":["../../src/react/forEach.tsx"],"names":[],"mappings":";;;;;AAUA,0BAmBC;AAED,wCAYC;;AA3CD,kDAA0B;AAU1B,SAAgB,OAAO,CAAc,EACnC,EAAE,EAAE,KAAK,EACT,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,EACrB,YAAY,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAClB;IAChB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,YAAY,IAAI,IAAI,CAAC;IAC9B,CAAC;IAED,OAAO,CACL,2DACG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,uBAAC,eAAK,CAAC,QAAQ,cACZ,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IADD,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAE7B,CAClB,CAAC,GACD,CACJ,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc;IAC5B,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAE5C,OAAO,CACL,uBAAC,OAAO,IAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,uDAAmB,YAC7C,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAChB,4CACG,KAAK,GAAG,CAAC,QAAI,IAAI,KADV,IAAI,CAER,CACP,GACO,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ForEach = exports.Case = exports.Switch = void 0;
|
|
4
|
+
var switch_1 = require("./switch");
|
|
5
|
+
Object.defineProperty(exports, "Switch", { enumerable: true, get: function () { return switch_1.Switch; } });
|
|
6
|
+
Object.defineProperty(exports, "Case", { enumerable: true, get: function () { return switch_1.Case; } });
|
|
7
|
+
var forEach_1 = require("./forEach");
|
|
8
|
+
Object.defineProperty(exports, "ForEach", { enumerable: true, get: function () { return forEach_1.ForEach; } });
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":";;;AAAA,mCAAwC;AAA/B,gGAAA,MAAM,OAAA;AAAE,8FAAA,IAAI,OAAA;AACrB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
declare const CASE_TYPE: unique symbol;
|
|
4
|
+
interface SwitchProps {
|
|
5
|
+
condition: unknown;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
default?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
interface CaseProps {
|
|
10
|
+
when: unknown;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
interface CaseComponent extends React.FC<CaseProps> {
|
|
14
|
+
type: typeof CASE_TYPE;
|
|
15
|
+
}
|
|
16
|
+
export declare const Case: CaseComponent;
|
|
17
|
+
export declare function Switch({ condition, children, default: defaultChild }: SwitchProps): React.ReactNode;
|
|
18
|
+
export declare function example(): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=switch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../src/react/switch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,QAAA,MAAM,SAAS,eAA6B,CAAC;AAE7C,UAAU,WAAW;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,UAAU,SAAS;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACvB;AAED,UAAU,aAAc,SAAQ,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC;IAC/C,IAAI,EAAE,OAAO,SAAS,CAAC;CAC1B;AAED,eAAO,MAAM,IAAI,EAAE,aAA0C,CAAC;AAG9D,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,WAAW,mBAiBjF;AAED,wBAAgB,OAAO,4CAatB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Case = void 0;
|
|
7
|
+
exports.Switch = Switch;
|
|
8
|
+
exports.example = example;
|
|
9
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
10
|
+
const react_1 = __importDefault(require("react"));
|
|
11
|
+
const CASE_TYPE = Symbol.for('@switch/case');
|
|
12
|
+
const Case = ({ children }) => children;
|
|
13
|
+
exports.Case = Case;
|
|
14
|
+
exports.Case.type = CASE_TYPE;
|
|
15
|
+
function Switch({ condition, children, default: defaultChild }) {
|
|
16
|
+
const childrenArray = react_1.default.Children.toArray(children);
|
|
17
|
+
const matchedCase = childrenArray.find((child) => {
|
|
18
|
+
if (!react_1.default.isValidElement(child))
|
|
19
|
+
return false;
|
|
20
|
+
const elementType = child.type;
|
|
21
|
+
if (elementType.type !== CASE_TYPE)
|
|
22
|
+
return false;
|
|
23
|
+
const caseValue = child.props.when;
|
|
24
|
+
return caseValue === condition;
|
|
25
|
+
});
|
|
26
|
+
if (matchedCase) {
|
|
27
|
+
return matchedCase.props.children;
|
|
28
|
+
}
|
|
29
|
+
return defaultChild ?? null;
|
|
30
|
+
}
|
|
31
|
+
function example() {
|
|
32
|
+
const value = 5;
|
|
33
|
+
return ((0, jsx_runtime_1.jsxs)(Switch, { condition: value, default: (0, jsx_runtime_1.jsx)("div", { children: "Default case" }), children: [(0, jsx_runtime_1.jsx)(exports.Case, { when: 5, children: (0, jsx_runtime_1.jsx)("div", { children: "Case 1" }) }), (0, jsx_runtime_1.jsx)(exports.Case, { when: 4, children: (0, jsx_runtime_1.jsx)("div", { children: "Case 2" }) })] }));
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=switch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch.js","sourceRoot":"","sources":["../../src/react/switch.tsx"],"names":[],"mappings":";;;;;;AAuBA,wBAiBC;AAED,0BAaC;;AAvDD,kDAA0B;AAG1B,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAiBtC,MAAM,IAAI,GAAkB,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC;AAAjD,QAAA,IAAI,QAA6C;AAC9D,YAAI,CAAC,IAAI,GAAG,SAAS,CAAC;AAEtB,SAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAe;IAC9E,MAAM,aAAa,GAAG,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEvD,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QAC7C,IAAI,CAAC,eAAK,CAAC,cAAc,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,MAAM,WAAW,GAAG,KAAK,CAAC,IAAqB,CAAC;QAChD,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAEjD,MAAM,SAAS,GAAI,KAAuC,CAAC,KAAK,CAAC,IAAI,CAAC;QACtE,OAAO,SAAS,KAAK,SAAS,CAAC;IACnC,CAAC,CAA8C,CAAC;IAEhD,IAAI,WAAW,EAAE,CAAC;QACd,OAAO,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,OAAO,YAAY,IAAI,IAAI,CAAC;AAChC,CAAC;AAED,SAAgB,OAAO;IACnB,MAAM,KAAK,GAAG,CAAC,CAAC;IAEhB,OAAO,CACH,wBAAC,MAAM,IAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,2DAAuB,aACtD,uBAAC,YAAI,IAAC,IAAI,EAAE,CAAC,YACT,qDAAiB,GACd,EACP,uBAAC,YAAI,IAAC,IAAI,EAAE,CAAC,YACT,qDAAiB,GACd,IACF,CACZ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { StateCreator } from 'zustand';
|
|
2
|
+
import type { DevtoolsOptions, PersistOptions, PersistStorage } from 'zustand/middleware';
|
|
3
|
+
export declare function createBox<T extends object>(config: {
|
|
4
|
+
name: string;
|
|
5
|
+
storeCreator: StateCreator<T, [['zustand/immer', never]], [], T>;
|
|
6
|
+
/**
|
|
7
|
+
* Persist 配置
|
|
8
|
+
* - 如果为 false,则跳过持久化
|
|
9
|
+
* - 如果为字符串 'localStorage' 或 'sessionStorage',则使用对应的存储
|
|
10
|
+
* - 如果为对象,则使用完整的 persist 配置
|
|
11
|
+
* - storage 可以是 'localStorage' | 'sessionStorage' 或自定义的 PersistStorage 实现
|
|
12
|
+
* - partialize 的返回类型会自动推断为 PersistedState,无需手动指定第二个泛型参数
|
|
13
|
+
*/
|
|
14
|
+
persist?: false | 'localStorage' | 'sessionStorage' | (Omit<PersistOptions<T, unknown>, 'name' | 'storage'> & {
|
|
15
|
+
storage?: 'localStorage' | 'sessionStorage' | PersistStorage<any>;
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Devtools 配置
|
|
19
|
+
* 如果为 false,则禁用 devtools
|
|
20
|
+
* 如果为对象,则使用完整的 devtools 配置(name 会自动设置)
|
|
21
|
+
*/
|
|
22
|
+
devtools?: boolean | Omit<DevtoolsOptions, 'name'>;
|
|
23
|
+
}): import("zustand").UseBoundStore<import("zustand").StoreApi<T>>;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/zustand/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACf,MAAM,oBAAoB,CAAA;AA+G3B,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IAChE;;;;;;;OAOG;IACH,OAAO,CAAC,EACJ,KAAK,GACL,cAAc,GACd,gBAAgB,GAChB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG;QACtD,OAAO,CAAC,EAAE,cAAc,GAAG,gBAAgB,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;KAClE,CAAC,CAAA;IACN;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAA;CACnD,kEA6DA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBox = createBox;
|
|
4
|
+
const middleware_1 = require("zustand/middleware");
|
|
5
|
+
const immer_1 = require("zustand/middleware/immer");
|
|
6
|
+
const react_1 = require("zustand/react");
|
|
7
|
+
// 辅助函数:生成 storage key
|
|
8
|
+
function generateStorageKey(name) {
|
|
9
|
+
return name
|
|
10
|
+
.replace(/([A-Z])/g, '-$1')
|
|
11
|
+
.toLowerCase()
|
|
12
|
+
.replace(/^-/, '')
|
|
13
|
+
.concat('-storage');
|
|
14
|
+
}
|
|
15
|
+
// 辅助函数:创建 storage
|
|
16
|
+
function createStorage(storageType) {
|
|
17
|
+
if (typeof storageType === 'string') {
|
|
18
|
+
return (0, middleware_1.createJSONStorage)(() => storageType === 'localStorage' ? localStorage : sessionStorage);
|
|
19
|
+
}
|
|
20
|
+
if (storageType) {
|
|
21
|
+
return storageType;
|
|
22
|
+
}
|
|
23
|
+
// 默认使用 sessionStorage
|
|
24
|
+
return (0, middleware_1.createJSONStorage)(() => sessionStorage);
|
|
25
|
+
}
|
|
26
|
+
function createBox(config) {
|
|
27
|
+
const { name, storeCreator, persist: persistConfig, devtools: devtoolsConfig = true, } = config;
|
|
28
|
+
// 自动生成 storage key
|
|
29
|
+
const storageKey = generateStorageKey(name);
|
|
30
|
+
// 创建基础 store(应用 immer)
|
|
31
|
+
const baseStore = (0, immer_1.immer)(storeCreator);
|
|
32
|
+
// 应用 persist(如果启用)
|
|
33
|
+
// 注意:使用 any 是因为中间件组合会导致复杂的类型,这是 zustand 的类型系统限制
|
|
34
|
+
let storeWithPersist = baseStore;
|
|
35
|
+
if (persistConfig !== false && persistConfig !== undefined) {
|
|
36
|
+
let persistOptions;
|
|
37
|
+
if (typeof persistConfig === 'string') {
|
|
38
|
+
// 简化配置:使用字符串指定存储类型
|
|
39
|
+
const persistStorage = createStorage(persistConfig);
|
|
40
|
+
persistOptions = {
|
|
41
|
+
name: storageKey,
|
|
42
|
+
storage: persistStorage,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// 完整配置:处理 storage 选项
|
|
47
|
+
const { storage, ...restOptions } = persistConfig;
|
|
48
|
+
const persistStorage = createStorage(storage);
|
|
49
|
+
// 构建完整的 persist 配置
|
|
50
|
+
persistOptions = {
|
|
51
|
+
name: storageKey,
|
|
52
|
+
storage: persistStorage,
|
|
53
|
+
...restOptions,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
storeWithPersist = (0, middleware_1.persist)(baseStore, persistOptions);
|
|
57
|
+
}
|
|
58
|
+
// 应用 devtools(如果启用)
|
|
59
|
+
let finalStore = storeWithPersist;
|
|
60
|
+
if (devtoolsConfig !== false) {
|
|
61
|
+
const devtoolsOptions = {
|
|
62
|
+
name,
|
|
63
|
+
enabled: true,
|
|
64
|
+
...(typeof devtoolsConfig === 'object' && devtoolsConfig),
|
|
65
|
+
};
|
|
66
|
+
finalStore = (0, middleware_1.devtools)(storeWithPersist, devtoolsOptions);
|
|
67
|
+
}
|
|
68
|
+
return (0, react_1.create)()(finalStore);
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/zustand/index.ts"],"names":[],"mappings":";;AAuHA,8BAqFC;AA5MD,mDAAyE;AACzE,oDAAgD;AAChD,yCAAsC;AAwFtC,sBAAsB;AACtB,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,IAAI;SACR,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,WAAW,EAAE;SACb,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;SACjB,MAAM,CAAC,UAAU,CAAC,CAAA;AACvB,CAAC;AAED,kBAAkB;AAClB,SAAS,aAAa,CACpB,WAIa;IAEb,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,IAAA,8BAAiB,EAAC,GAAG,EAAE,CAC5B,WAAW,KAAK,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAC1C,CAAA;IACxB,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,WAAW,CAAA;IACpB,CAAC;IACD,sBAAsB;IACtB,OAAO,IAAA,8BAAiB,EAAC,GAAG,EAAE,CAAC,cAAc,CAAsB,CAAA;AACrE,CAAC;AAED,SAAgB,SAAS,CAAmB,MAwB3C;IACC,MAAM,EACJ,IAAI,EACJ,YAAY,EACZ,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,cAAc,GAAG,IAAI,GAChC,GAAG,MAAM,CAAA;IAEV,mBAAmB;IACnB,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAE3C,uBAAuB;IACvB,MAAM,SAAS,GAAG,IAAA,aAAK,EAAI,YAAY,CAAC,CAAA;IAExC,mBAAmB;IACnB,gDAAgD;IAChD,IAAI,gBAAgB,GAAQ,SAAS,CAAA;IACrC,IAAI,aAAa,KAAK,KAAK,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAI3D,IAAI,cAAyD,CAAA;QAE7D,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,mBAAmB;YACnB,MAAM,cAAc,GAClB,aAAa,CAAyB,aAAa,CAAC,CAAA;YACtD,cAAc,GAAG;gBACf,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,cAAc;aACxB,CAAA;QACH,CAAC;aAAM,CAAC;YACN,qBAAqB;YACrB,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,GAAG,aAAa,CAAA;YACjD,MAAM,cAAc,GAAG,aAAa,CAClC,OAAc,CACf,CAAA;YAED,mBAAmB;YACnB,cAAc,GAAG;gBACf,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,cAAc;gBACvB,GAAG,WAAW;aAC8B,CAAA;QAChD,CAAC;QAED,gBAAgB,GAAG,IAAA,oBAAO,EAAC,SAAS,EAAE,cAAc,CAAC,CAAA;IACvD,CAAC;IAED,oBAAoB;IACpB,IAAI,UAAU,GAAQ,gBAAgB,CAAA;IACtC,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,eAAe,GAAoB;YACvC,IAAI;YACJ,OAAO,EAAE,IAAI;YACb,GAAG,CAAC,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,CAAC;SAC1D,CAAA;QACD,UAAU,GAAG,IAAA,qBAAQ,EAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO,IAAA,cAAM,GAAK,CAAC,UAAU,CAAC,CAAA;AAChC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@king26/wk-react-tools",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React 简化工具包",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./react": {
|
|
15
|
+
"import": "./dist/react/index.js",
|
|
16
|
+
"require": "./dist/react/index.js",
|
|
17
|
+
"types": "./dist/react/index.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./zustand": {
|
|
20
|
+
"import": "./dist/zustand/index.js",
|
|
21
|
+
"require": "./dist/zustand/index.js",
|
|
22
|
+
"types": "./dist/zustand/index.d.ts"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"clean": "rm -rf dist",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"react",
|
|
32
|
+
"tools",
|
|
33
|
+
"zustand",
|
|
34
|
+
"switch"
|
|
35
|
+
],
|
|
36
|
+
"author": "zwking",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"src"
|
|
41
|
+
],
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"react": "^18.0.0",
|
|
44
|
+
"zustand": "^4.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/react": "^18.0.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
interface ForEachProps<T = unknown> {
|
|
5
|
+
of: T[];
|
|
6
|
+
children: (item: T, index: number) => ReactNode;
|
|
7
|
+
default?: ReactNode;
|
|
8
|
+
keyExtractor?: (item: T, index: number) => string | number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ForEach<T = unknown>({
|
|
12
|
+
of: items,
|
|
13
|
+
children: render,
|
|
14
|
+
default: defaultChild,
|
|
15
|
+
keyExtractor = (_, index) => index,
|
|
16
|
+
}: ForEachProps<T>) {
|
|
17
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
18
|
+
return defaultChild ?? null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
{items.map((item, index) => (
|
|
24
|
+
<React.Fragment key={keyExtractor(item, index)}>
|
|
25
|
+
{render(item, index)}
|
|
26
|
+
</React.Fragment>
|
|
27
|
+
))}
|
|
28
|
+
</>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function forEachExample() {
|
|
33
|
+
const items = ["Apple", "Banana", "Cherry"];
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<ForEach of={items} default={<div>No items</div>}>
|
|
37
|
+
{(item, index) => (
|
|
38
|
+
<div key={item}>
|
|
39
|
+
{index + 1}. {item}
|
|
40
|
+
</div>
|
|
41
|
+
)}
|
|
42
|
+
</ForEach>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type {ReactNode} from 'react';
|
|
3
|
+
|
|
4
|
+
const CASE_TYPE = Symbol.for('@switch/case');
|
|
5
|
+
|
|
6
|
+
interface SwitchProps {
|
|
7
|
+
condition: unknown;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
default?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface CaseProps {
|
|
13
|
+
when: unknown;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface CaseComponent extends React.FC<CaseProps> {
|
|
18
|
+
type: typeof CASE_TYPE;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const Case: CaseComponent = ({ children }) => children;
|
|
22
|
+
Case.type = CASE_TYPE;
|
|
23
|
+
|
|
24
|
+
export function Switch({ condition, children, default: defaultChild }: SwitchProps) {
|
|
25
|
+
const childrenArray = React.Children.toArray(children);
|
|
26
|
+
|
|
27
|
+
const matchedCase = childrenArray.find((child) => {
|
|
28
|
+
if (!React.isValidElement(child)) return false;
|
|
29
|
+
const elementType = child.type as CaseComponent;
|
|
30
|
+
if (elementType.type !== CASE_TYPE) return false;
|
|
31
|
+
|
|
32
|
+
const caseValue = (child as React.ReactElement<CaseProps>).props.when;
|
|
33
|
+
return caseValue === condition;
|
|
34
|
+
}) as React.ReactElement<CaseProps> | undefined;
|
|
35
|
+
|
|
36
|
+
if (matchedCase) {
|
|
37
|
+
return matchedCase.props.children;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return defaultChild ?? null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function example() {
|
|
44
|
+
const value = 5;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Switch condition={value} default={<div>Default case</div>}>
|
|
48
|
+
<Case when={5}>
|
|
49
|
+
<div>Case 1</div>
|
|
50
|
+
</Case>
|
|
51
|
+
<Case when={4}>
|
|
52
|
+
<div>Case 2</div>
|
|
53
|
+
</Case>
|
|
54
|
+
</Switch>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { createJSONStorage, devtools, persist } from 'zustand/middleware'
|
|
2
|
+
import { immer } from 'zustand/middleware/immer'
|
|
3
|
+
import { create } from 'zustand/react'
|
|
4
|
+
import type { StateCreator } from 'zustand'
|
|
5
|
+
import type {
|
|
6
|
+
DevtoolsOptions,
|
|
7
|
+
PersistOptions,
|
|
8
|
+
PersistStorage,
|
|
9
|
+
} from 'zustand/middleware'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 约定大于配置的 Store 创建函数
|
|
13
|
+
* 自动应用 immer、persist、devtools 中间件
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // 基础用法 - 只需提供 store 名称和初始状态
|
|
17
|
+
* const useStore = createBox<UserStore>({
|
|
18
|
+
* name: 'UserStore',
|
|
19
|
+
* storeCreator: (set, get) => ({
|
|
20
|
+
* name: '',
|
|
21
|
+
* setName: (name: string) => set({ name }),
|
|
22
|
+
* }),
|
|
23
|
+
* })
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // 简化配置 - 使用字符串指定存储类型
|
|
27
|
+
* const useStore = createBox<UserStore>({
|
|
28
|
+
* name: 'UserStore',
|
|
29
|
+
* storeCreator: (set, get) => ({
|
|
30
|
+
* name: '',
|
|
31
|
+
* setName: (name: string) => set({ name }),
|
|
32
|
+
* }),
|
|
33
|
+
* persist: 'localStorage', // 或 'sessionStorage' (默认)
|
|
34
|
+
* })
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // 完整配置 - 支持所有 persist 和 devtools 选项
|
|
38
|
+
* const useStore = createBox<UserStore>({
|
|
39
|
+
* name: 'UserStore',
|
|
40
|
+
* storeCreator: (set, get) => ({
|
|
41
|
+
* name: '',
|
|
42
|
+
* setName: (name: string) => set({ name }),
|
|
43
|
+
* }),
|
|
44
|
+
* persist: {
|
|
45
|
+
* storage: 'localStorage',
|
|
46
|
+
* partialize: (state) => ({ name: state.name }),
|
|
47
|
+
* version: 1,
|
|
48
|
+
* migrate: (persistedState, version) => ({ ...persistedState, version }),
|
|
49
|
+
* },
|
|
50
|
+
* devtools: {
|
|
51
|
+
* enabled: true,
|
|
52
|
+
* anonymousActionType: 'anonymous',
|
|
53
|
+
* },
|
|
54
|
+
* })
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // 自定义存储 - 使用自定义的 PersistStorage 实现
|
|
58
|
+
* const customStorage: PersistStorage<UserStore> = {
|
|
59
|
+
* getItem: (name) => {
|
|
60
|
+
* // 自定义获取逻辑
|
|
61
|
+
* const str = localStorage.getItem(name)
|
|
62
|
+
* return str ? JSON.parse(str) : null
|
|
63
|
+
* },
|
|
64
|
+
* setItem: (name, value) => {
|
|
65
|
+
* // 自定义存储逻辑
|
|
66
|
+
* localStorage.setItem(name, JSON.stringify(value))
|
|
67
|
+
* },
|
|
68
|
+
* removeItem: (name) => {
|
|
69
|
+
* localStorage.removeItem(name)
|
|
70
|
+
* },
|
|
71
|
+
* }
|
|
72
|
+
* const useStore = createBox<UserStore>({
|
|
73
|
+
* name: 'UserStore',
|
|
74
|
+
* storeCreator: (set, get) => ({
|
|
75
|
+
* name: '',
|
|
76
|
+
* setName: (name: string) => set({ name }),
|
|
77
|
+
* }),
|
|
78
|
+
* persist: {
|
|
79
|
+
* storage: customStorage, // 使用自定义存储
|
|
80
|
+
* },
|
|
81
|
+
* })
|
|
82
|
+
*/
|
|
83
|
+
// 辅助类型:从 persist 配置中提取 PersistedState
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
85
|
+
type ExtractPersistedState<T, P> = P extends {
|
|
86
|
+
partialize: (state: T) => infer PS
|
|
87
|
+
}
|
|
88
|
+
? PS
|
|
89
|
+
: T
|
|
90
|
+
|
|
91
|
+
// 辅助函数:生成 storage key
|
|
92
|
+
function generateStorageKey(name: string): string {
|
|
93
|
+
return name
|
|
94
|
+
.replace(/([A-Z])/g, '-$1')
|
|
95
|
+
.toLowerCase()
|
|
96
|
+
.replace(/^-/, '')
|
|
97
|
+
.concat('-storage')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 辅助函数:创建 storage
|
|
101
|
+
function createStorage<T>(
|
|
102
|
+
storageType:
|
|
103
|
+
| 'localStorage'
|
|
104
|
+
| 'sessionStorage'
|
|
105
|
+
| PersistStorage<T>
|
|
106
|
+
| undefined,
|
|
107
|
+
): PersistStorage<T> {
|
|
108
|
+
if (typeof storageType === 'string') {
|
|
109
|
+
return createJSONStorage(() =>
|
|
110
|
+
storageType === 'localStorage' ? localStorage : sessionStorage,
|
|
111
|
+
) as PersistStorage<T>
|
|
112
|
+
}
|
|
113
|
+
if (storageType) {
|
|
114
|
+
return storageType
|
|
115
|
+
}
|
|
116
|
+
// 默认使用 sessionStorage
|
|
117
|
+
return createJSONStorage(() => sessionStorage) as PersistStorage<T>
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function createBox<T extends object>(config: {
|
|
121
|
+
name: string
|
|
122
|
+
storeCreator: StateCreator<T, [['zustand/immer', never]], [], T>
|
|
123
|
+
/**
|
|
124
|
+
* Persist 配置
|
|
125
|
+
* - 如果为 false,则跳过持久化
|
|
126
|
+
* - 如果为字符串 'localStorage' 或 'sessionStorage',则使用对应的存储
|
|
127
|
+
* - 如果为对象,则使用完整的 persist 配置
|
|
128
|
+
* - storage 可以是 'localStorage' | 'sessionStorage' 或自定义的 PersistStorage 实现
|
|
129
|
+
* - partialize 的返回类型会自动推断为 PersistedState,无需手动指定第二个泛型参数
|
|
130
|
+
*/
|
|
131
|
+
persist?:
|
|
132
|
+
| false
|
|
133
|
+
| 'localStorage'
|
|
134
|
+
| 'sessionStorage'
|
|
135
|
+
| (Omit<PersistOptions<T, unknown>, 'name' | 'storage'> & {
|
|
136
|
+
storage?: 'localStorage' | 'sessionStorage' | PersistStorage<any>
|
|
137
|
+
})
|
|
138
|
+
/**
|
|
139
|
+
* Devtools 配置
|
|
140
|
+
* 如果为 false,则禁用 devtools
|
|
141
|
+
* 如果为对象,则使用完整的 devtools 配置(name 会自动设置)
|
|
142
|
+
*/
|
|
143
|
+
devtools?: boolean | Omit<DevtoolsOptions, 'name'>
|
|
144
|
+
}) {
|
|
145
|
+
const {
|
|
146
|
+
name,
|
|
147
|
+
storeCreator,
|
|
148
|
+
persist: persistConfig,
|
|
149
|
+
devtools: devtoolsConfig = true,
|
|
150
|
+
} = config
|
|
151
|
+
|
|
152
|
+
// 自动生成 storage key
|
|
153
|
+
const storageKey = generateStorageKey(name)
|
|
154
|
+
|
|
155
|
+
// 创建基础 store(应用 immer)
|
|
156
|
+
const baseStore = immer<T>(storeCreator)
|
|
157
|
+
|
|
158
|
+
// 应用 persist(如果启用)
|
|
159
|
+
// 注意:使用 any 是因为中间件组合会导致复杂的类型,这是 zustand 的类型系统限制
|
|
160
|
+
let storeWithPersist: any = baseStore
|
|
161
|
+
if (persistConfig !== false && persistConfig !== undefined) {
|
|
162
|
+
// 从配置中推断 PersistedState
|
|
163
|
+
type InferredPersistedState = ExtractPersistedState<T, typeof persistConfig>
|
|
164
|
+
|
|
165
|
+
let persistOptions: PersistOptions<T, InferredPersistedState>
|
|
166
|
+
|
|
167
|
+
if (typeof persistConfig === 'string') {
|
|
168
|
+
// 简化配置:使用字符串指定存储类型
|
|
169
|
+
const persistStorage =
|
|
170
|
+
createStorage<InferredPersistedState>(persistConfig)
|
|
171
|
+
persistOptions = {
|
|
172
|
+
name: storageKey,
|
|
173
|
+
storage: persistStorage,
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
// 完整配置:处理 storage 选项
|
|
177
|
+
const { storage, ...restOptions } = persistConfig
|
|
178
|
+
const persistStorage = createStorage<InferredPersistedState>(
|
|
179
|
+
storage as any,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
// 构建完整的 persist 配置
|
|
183
|
+
persistOptions = {
|
|
184
|
+
name: storageKey,
|
|
185
|
+
storage: persistStorage,
|
|
186
|
+
...restOptions,
|
|
187
|
+
} as PersistOptions<T, InferredPersistedState>
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
storeWithPersist = persist(baseStore, persistOptions)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 应用 devtools(如果启用)
|
|
194
|
+
let finalStore: any = storeWithPersist
|
|
195
|
+
if (devtoolsConfig !== false) {
|
|
196
|
+
const devtoolsOptions: DevtoolsOptions = {
|
|
197
|
+
name,
|
|
198
|
+
enabled: true,
|
|
199
|
+
...(typeof devtoolsConfig === 'object' && devtoolsConfig),
|
|
200
|
+
}
|
|
201
|
+
finalStore = devtools(storeWithPersist, devtoolsOptions)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return create<T>()(finalStore)
|
|
205
|
+
}
|