@wwog/react 1.0.0 → 1.1.1
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/README.md +17 -17
- package/dist/index.d.mts +106 -2
- package/dist/index.js +181 -3
- package/package.json +3 -2
- package/src/ProcessControl/If.tsx +3 -3
- package/src/index.ts +3 -3
- package/src/index copy.ts +0 -3
package/README.md
CHANGED
|
@@ -30,25 +30,25 @@ pnpm add @wwog/react
|
|
|
30
30
|
|
|
31
31
|
### 流程控制组件
|
|
32
32
|
|
|
33
|
-
#### `<If
|
|
33
|
+
#### `<If>`
|
|
34
34
|
|
|
35
35
|
声明式的条件渲染组件,类似于 if-else 语句,但在 JSX 中使用。
|
|
36
36
|
|
|
37
37
|
```tsx
|
|
38
|
-
import { If
|
|
38
|
+
import { If } from '@wwog/react';
|
|
39
39
|
|
|
40
40
|
function Example({ count }) {
|
|
41
41
|
return (
|
|
42
42
|
<If condition={count > 10}>
|
|
43
|
-
<Then>
|
|
43
|
+
<If.Then>
|
|
44
44
|
<p>Count is greater than 10</p>
|
|
45
|
-
</Then>
|
|
46
|
-
<ElseIf condition={count > 5}>
|
|
45
|
+
</If.Then>
|
|
46
|
+
<If.ElseIf condition={count > 5}>
|
|
47
47
|
<p>Count is greater than 5</p>
|
|
48
|
-
</ElseIf>
|
|
49
|
-
<Else>
|
|
48
|
+
</If.ElseIf>
|
|
49
|
+
<If.Else>
|
|
50
50
|
<p>Count is 5 or less</p>
|
|
51
|
-
</Else>
|
|
51
|
+
</If.Else>
|
|
52
52
|
</If>
|
|
53
53
|
);
|
|
54
54
|
}
|
|
@@ -59,23 +59,23 @@ function Example({ count }) {
|
|
|
59
59
|
类似于 JavaScript 的 switch 语句,但更具声明性和类型安全性。
|
|
60
60
|
|
|
61
61
|
```tsx
|
|
62
|
-
import { Switch
|
|
62
|
+
import { Switch } from '@wwog/react';
|
|
63
63
|
|
|
64
64
|
function Example({ status }) {
|
|
65
65
|
return (
|
|
66
66
|
<Switch value={status}>
|
|
67
|
-
<Case value="loading">
|
|
67
|
+
<Switch.Case value="loading">
|
|
68
68
|
<Loading />
|
|
69
|
-
</Case>
|
|
70
|
-
<Case value="success">
|
|
69
|
+
</Switch.Case>
|
|
70
|
+
<Switch.Case value="success">
|
|
71
71
|
<Success />
|
|
72
|
-
</Case>
|
|
73
|
-
<Case value="error">
|
|
72
|
+
</Switch.Case>
|
|
73
|
+
<Switch.Case value="error">
|
|
74
74
|
<Error />
|
|
75
|
-
</Case>
|
|
76
|
-
<Default>
|
|
75
|
+
</Switch.Case>
|
|
76
|
+
<Switch.Default>
|
|
77
77
|
<p>Unknown status</p>
|
|
78
|
-
</Default>
|
|
78
|
+
</Switch.Default>
|
|
79
79
|
</Switch>
|
|
80
80
|
);
|
|
81
81
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,107 @@
|
|
|
1
|
-
|
|
1
|
+
import React$1, { FC as FC$1, ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
interface SwitchProps<T> {
|
|
4
|
+
value: T;
|
|
5
|
+
/**
|
|
6
|
+
* @description 可选的比对函数,默认() => a===b
|
|
7
|
+
* @description_en optional compare function, default to () => a === b
|
|
8
|
+
**/
|
|
9
|
+
compare?: (a: T, b: T) => boolean;
|
|
10
|
+
children?: React$1.ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* @description 是否严格模式,默认 false.建议跟随开发环境变化,严格模式下,会循环所有节点来提供更多的错误提示
|
|
13
|
+
* @description_en strict mode, default to false. It is recommended to follow the development environment changes. In strict mode, all nodes will be looped to provide more error prompts
|
|
14
|
+
* @extra
|
|
15
|
+
* 1.严格模式下,无论什么情况都会循环所有节点,以确保所有的 case 和 default 都能被检查到
|
|
16
|
+
* 2.非严格模式下,如果有一个 case 匹配成功,就不会继续循环
|
|
17
|
+
* @extra_en
|
|
18
|
+
* 1. In strict mode, all nodes will be looped regardless of the situation to ensure that all cases and defaults can be checked
|
|
19
|
+
* 2. In non-strict mode, if a case matches successfully, it will not continue to loop
|
|
20
|
+
*/
|
|
21
|
+
strict?: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface SwitchCaseProps<T> {
|
|
24
|
+
value: T;
|
|
25
|
+
children?: React$1.ReactNode;
|
|
26
|
+
}
|
|
27
|
+
interface SwitchDefaultProps {
|
|
28
|
+
children?: React$1.ReactNode;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* @description Switch 组件用于根据传入的 value 渲染不同的子组件
|
|
32
|
+
* @description_en The Switch component is used to render different child components based on the passed value
|
|
33
|
+
*/
|
|
34
|
+
declare const Switch: {
|
|
35
|
+
<T>(props: SwitchProps<T>): React$1.ReactElement | null;
|
|
36
|
+
displayName: string;
|
|
37
|
+
Case: {
|
|
38
|
+
<T>(props: SwitchCaseProps<T>): React$1.ReactElement;
|
|
39
|
+
displayName: string;
|
|
40
|
+
};
|
|
41
|
+
Default: {
|
|
42
|
+
(props: SwitchDefaultProps): React$1.ReactElement;
|
|
43
|
+
displayName: string;
|
|
44
|
+
};
|
|
45
|
+
createTyped<T>(): {
|
|
46
|
+
Switch: (props: SwitchProps<T>) => React$1.ReactElement | null;
|
|
47
|
+
Case: (props: SwitchCaseProps<T>) => React$1.ReactElement;
|
|
48
|
+
Default: (props: SwitchDefaultProps) => React$1.ReactElement;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
interface IfProps {
|
|
53
|
+
condition: boolean;
|
|
54
|
+
children?: React$1.ReactNode;
|
|
55
|
+
}
|
|
56
|
+
interface ThenProps {
|
|
57
|
+
children?: React$1.ReactNode;
|
|
58
|
+
}
|
|
59
|
+
interface ElseProps {
|
|
60
|
+
children?: React$1.ReactNode;
|
|
61
|
+
}
|
|
62
|
+
interface ElseIfProps {
|
|
63
|
+
condition: boolean;
|
|
64
|
+
children?: React$1.ReactNode;
|
|
65
|
+
}
|
|
66
|
+
declare const If: {
|
|
67
|
+
({ condition, children, }: IfProps): React$1.ReactElement | null;
|
|
68
|
+
displayName: string;
|
|
69
|
+
Then: FC<ThenProps>;
|
|
70
|
+
ElseIf: FC<ElseIfProps>;
|
|
71
|
+
Else: FC<ElseProps>;
|
|
72
|
+
createTyped(): {
|
|
73
|
+
If: (props: IfProps) => React$1.ReactElement | null;
|
|
74
|
+
Then: (props: ThenProps) => React$1.ReactElement;
|
|
75
|
+
ElseIf: (props: ElseIfProps) => React$1.ReactElement;
|
|
76
|
+
Else: (props: ElseProps) => React$1.ReactElement;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
interface SizeBoxProps {
|
|
81
|
+
size?: number | string;
|
|
82
|
+
height?: number | string;
|
|
83
|
+
width?: number | string;
|
|
84
|
+
h?: number | string;
|
|
85
|
+
w?: number | string;
|
|
86
|
+
children?: ReactNode;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* @description SizeBox 组件用于设置一个固定大小的盒子
|
|
90
|
+
*/
|
|
91
|
+
declare const SizeBox: FC$1<SizeBoxProps>;
|
|
92
|
+
|
|
93
|
+
interface ArrayRenderProps<T> {
|
|
94
|
+
items: T[];
|
|
95
|
+
renderItem: (item: T, index: number) => React.ReactNode;
|
|
96
|
+
filter?: (item: T) => boolean;
|
|
97
|
+
}
|
|
98
|
+
declare function ArrayRender<T>(props: ArrayRenderProps<T>): ReactNode;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @description 性能优化,替代 React.Children.forEach, 回调可以返回 false 来中断循环
|
|
102
|
+
* @description_en Replace React.Children.forEach, the callback can return false to interrupt the loop
|
|
103
|
+
*/
|
|
104
|
+
declare function childrenLoop(children: React$1.ReactNode | undefined, callback: (child: React$1.ReactNode, index: number) => boolean | void): void;
|
|
105
|
+
|
|
106
|
+
export { ArrayRender, If, SizeBox, Switch, childrenLoop };
|
|
107
|
+
export type { ArrayRenderProps, ElseIfProps, ElseProps, IfProps, SwitchCaseProps, SwitchDefaultProps, SwitchProps, ThenProps };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,183 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import React$1, { Fragment } from 'react';
|
|
2
|
+
|
|
3
|
+
function childrenLoop(children, callback) {
|
|
4
|
+
if (children === void 0) return;
|
|
5
|
+
let index = 0;
|
|
6
|
+
if (Array.isArray(children)) {
|
|
7
|
+
for (const child of children) {
|
|
8
|
+
const shouldContinue = callback(child, index++);
|
|
9
|
+
if (shouldContinue === false) {
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
} else {
|
|
14
|
+
callback(children, index);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const defaultCompare = (a, b) => {
|
|
19
|
+
return a === b;
|
|
20
|
+
};
|
|
21
|
+
const Case = (props) => {
|
|
22
|
+
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, props.children);
|
|
23
|
+
};
|
|
24
|
+
Case.displayName = "Switch_Case";
|
|
25
|
+
const Default = (props) => {
|
|
26
|
+
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, props.children);
|
|
27
|
+
};
|
|
28
|
+
Default.displayName = "Switch_Default";
|
|
29
|
+
const Switch = (props) => {
|
|
30
|
+
const { value, compare = defaultCompare, children, strict = false } = props;
|
|
31
|
+
const seenValues = /* @__PURE__ */ new Set();
|
|
32
|
+
let matchedChildren = null;
|
|
33
|
+
let defaultChild = null;
|
|
34
|
+
let hasDefault = false;
|
|
35
|
+
childrenLoop(children, (child, index) => {
|
|
36
|
+
if (!React$1.isValidElement(child)) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Switch Children only accepts valid React elements at index ${index}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const type = child.type;
|
|
42
|
+
if (type.displayName === Case.displayName) {
|
|
43
|
+
const caseProps = child.props;
|
|
44
|
+
if (seenValues.has(caseProps.value)) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Switch found duplicate Case value at index ${index}: ${JSON.stringify(
|
|
47
|
+
caseProps.value
|
|
48
|
+
)}${strict ? " (detected in strict mode)" : ""}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
seenValues.add(caseProps.value);
|
|
52
|
+
if (!matchedChildren && compare(value, caseProps.value)) {
|
|
53
|
+
matchedChildren = caseProps.children;
|
|
54
|
+
if (strict === false) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} else if (type.displayName === Default.displayName) {
|
|
59
|
+
if (hasDefault) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Switch can only have one Default child at index ${index}`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
hasDefault = true;
|
|
65
|
+
defaultChild = child.props.children;
|
|
66
|
+
if (!strict && matchedChildren) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(
|
|
72
|
+
type.displayName || type.name || type
|
|
73
|
+
)} at index ${index}`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, matchedChildren ?? defaultChild);
|
|
78
|
+
};
|
|
79
|
+
Switch.displayName = "Switch";
|
|
80
|
+
Switch.Case = Case;
|
|
81
|
+
Switch.Default = Default;
|
|
82
|
+
Switch.createTyped = function() {
|
|
83
|
+
return {
|
|
84
|
+
Switch,
|
|
85
|
+
Case,
|
|
86
|
+
Default
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const Then = (props) => {
|
|
91
|
+
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, props.children);
|
|
92
|
+
};
|
|
93
|
+
const Else = ({ children }) => {
|
|
94
|
+
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, children);
|
|
95
|
+
};
|
|
96
|
+
const ElseIf = (props) => {
|
|
97
|
+
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, props.children);
|
|
98
|
+
};
|
|
99
|
+
Then.displayName = "If_Then";
|
|
100
|
+
Else.displayName = "If_Else";
|
|
101
|
+
ElseIf.displayName = "If_ElseIf";
|
|
102
|
+
const If = ({
|
|
103
|
+
condition,
|
|
104
|
+
children
|
|
105
|
+
}) => {
|
|
106
|
+
let thenChild = null;
|
|
107
|
+
let elseChild = null;
|
|
108
|
+
const elseIfChildren = [];
|
|
109
|
+
React$1.Children.forEach(children, (child) => {
|
|
110
|
+
if (!React$1.isValidElement(child)) {
|
|
111
|
+
throw new Error("If component only accepts valid React elements");
|
|
112
|
+
}
|
|
113
|
+
const type = child.type;
|
|
114
|
+
if (type.displayName === Then.displayName) {
|
|
115
|
+
if (thenChild) {
|
|
116
|
+
throw new Error("If component can only have one Then child");
|
|
117
|
+
}
|
|
118
|
+
thenChild = child;
|
|
119
|
+
} else if (type.displayName === ElseIf.displayName) {
|
|
120
|
+
elseIfChildren.push(child);
|
|
121
|
+
} else if (type.displayName === Else.displayName) {
|
|
122
|
+
if (elseChild) {
|
|
123
|
+
throw new Error("If component can only have one Else child");
|
|
124
|
+
}
|
|
125
|
+
elseChild = child;
|
|
126
|
+
} else {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String(
|
|
129
|
+
type.displayName || type.name || type
|
|
130
|
+
)}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
if (condition) {
|
|
135
|
+
return thenChild ? /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, thenChild.props.children) : null;
|
|
136
|
+
}
|
|
137
|
+
const matchedElseIf = elseIfChildren.find((child) => {
|
|
138
|
+
const elseIfProps = child.props;
|
|
139
|
+
return elseIfProps.condition;
|
|
140
|
+
});
|
|
141
|
+
if (matchedElseIf) {
|
|
142
|
+
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, matchedElseIf.props.children);
|
|
143
|
+
}
|
|
144
|
+
if (elseChild) {
|
|
145
|
+
return elseChild ? /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, elseChild.props.children) : null;
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
};
|
|
149
|
+
If.displayName = "If";
|
|
150
|
+
If.Then = Then;
|
|
151
|
+
If.ElseIf = ElseIf;
|
|
152
|
+
If.Else = Else;
|
|
153
|
+
If.createTyped = function() {
|
|
154
|
+
return {
|
|
155
|
+
If,
|
|
156
|
+
Then,
|
|
157
|
+
ElseIf,
|
|
158
|
+
Else
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const SizeBox = (props) => {
|
|
163
|
+
const { children, h, w, size, height, width } = props;
|
|
164
|
+
const widthValue = size || w || width;
|
|
165
|
+
const heightValue = size || h || height;
|
|
166
|
+
return /* @__PURE__ */ React.createElement("div", { style: { width: widthValue, height: heightValue } }, children);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
function ArrayRender(props) {
|
|
170
|
+
const { items, renderItem, filter } = props;
|
|
171
|
+
if (!items) {
|
|
172
|
+
console.error("ArrayRender: items is null");
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
return /* @__PURE__ */ React.createElement(Fragment, null, items.map((item, index) => {
|
|
176
|
+
if (filter && !filter(item)) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
return renderItem(item, index);
|
|
180
|
+
}));
|
|
3
181
|
}
|
|
4
182
|
|
|
5
|
-
export {
|
|
183
|
+
export { ArrayRender, If, SizeBox, Switch, childrenLoop };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wwog/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "wwog",
|
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">= 20.0.0",
|
|
34
34
|
"pnpm": ">=8.15.0"
|
|
35
|
-
}
|
|
35
|
+
},
|
|
36
|
+
"packageManager": "pnpm@9.15.1+sha512.1acb565e6193efbebda772702950469150cf12bcc764262e7587e71d19dc98a423dff9536e57ea44c49bdf790ff694e83c27be5faa23d67e0c033b583be4bfcf"
|
|
36
37
|
}
|
|
@@ -18,13 +18,13 @@ export interface ElseIfProps {
|
|
|
18
18
|
children?: React.ReactNode;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
const Then: FC<ThenProps> = (props) => {
|
|
22
22
|
return <>{props.children}</>;
|
|
23
23
|
};
|
|
24
|
-
|
|
24
|
+
const Else: FC<ElseProps> = ({ children }) => {
|
|
25
25
|
return <>{children}</>;
|
|
26
26
|
};
|
|
27
|
-
|
|
27
|
+
const ElseIf: FC<ElseIfProps> = (props) => {
|
|
28
28
|
return <>{props.children}</>;
|
|
29
29
|
};
|
|
30
30
|
Then.displayName = "If_Then";
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export * from "./ProcessControl";
|
|
2
|
+
export * from "./Common";
|
|
3
|
+
export * from "./utils";
|
package/src/index copy.ts
DELETED