react-polymorphic 1.0.0 → 1.0.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 +55 -55
- package/package.json +79 -82
package/README.md
CHANGED
|
@@ -12,11 +12,11 @@ A single component factory function for polymorphic React components. Built for
|
|
|
12
12
|
import { createPolymorph } from 'react-polymorphic';
|
|
13
13
|
|
|
14
14
|
const Button = createPolymorph<'button'>(({ as: Tag = 'button', ...rest }) => {
|
|
15
|
-
|
|
15
|
+
return <Tag {...rest} />
|
|
16
16
|
})
|
|
17
17
|
|
|
18
18
|
const App = () => {
|
|
19
|
-
|
|
19
|
+
return <Button as="a" href="/">Home</Button>
|
|
20
20
|
}
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -70,7 +70,7 @@ Polymorphic components let you keep one consistent API while swapping the render
|
|
|
70
70
|
`InferPolymorphElement`, `InferPolymorphProps`, and `InferPolymorphConfig` for advanced typing workflows.
|
|
71
71
|
|
|
72
72
|
- **TypeScript 7 Ready**
|
|
73
|
-
|
|
73
|
+
Compatible with TypeScript 5.4+ and optimized for TypeScript 7.
|
|
74
74
|
|
|
75
75
|
- **Built for React 19+**
|
|
76
76
|
Leverages React 19's handling of `ref`, eliminating `forwardRef` and convoluted type gymnastics.
|
|
@@ -96,23 +96,23 @@ Most polymorphic components are simple wrappers that combine custom props with i
|
|
|
96
96
|
import { createPolymorph } from 'react-polymorphic';
|
|
97
97
|
|
|
98
98
|
type Props = {
|
|
99
|
-
|
|
99
|
+
variant: 'primary' | 'secondary';
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
const Pane = createPolymorph<'div', Props>((props) => {
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
const { as: Tag = 'div', variant, className, ...rest } = props;
|
|
104
|
+
const variantClasses = variant === 'primary' ? 'bg-white' : 'bg-blue-50';
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
return <Tag className={`p-4 ${variantClasses} ${className}`} {...rest} />
|
|
107
107
|
})
|
|
108
108
|
|
|
109
109
|
const App = () => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
110
|
+
return (
|
|
111
|
+
<>
|
|
112
|
+
<Pane as="section" variant="primary" aria-label="...">...</Pane>
|
|
113
|
+
<Pane as="aside" variant="secondary" aria-label="...">...</Pane>
|
|
114
|
+
</>
|
|
115
|
+
)
|
|
116
116
|
}
|
|
117
117
|
```
|
|
118
118
|
|
|
@@ -127,20 +127,20 @@ import { useRef } from 'react';
|
|
|
127
127
|
import { createPolymorph } from 'react-polymorphic';
|
|
128
128
|
|
|
129
129
|
const Component = createPolymorph<'div'>((props) => {
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
const { as: Tag = 'div', ...rest } = props;
|
|
131
|
+
return <Tag {...rest} />
|
|
132
132
|
})
|
|
133
133
|
|
|
134
134
|
const App = () => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
135
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
136
|
+
const aRef = useRef<HTMLAnchorElement>(null);
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<>
|
|
140
|
+
<Component ref={ref} />
|
|
141
|
+
<Component as="a" ref={aRef} />
|
|
142
|
+
</>
|
|
143
|
+
)
|
|
144
144
|
}
|
|
145
145
|
```
|
|
146
146
|
|
|
@@ -155,34 +155,34 @@ import { createPolymorph } from 'react-polymorphic';
|
|
|
155
155
|
import type { PolymorphicConfig, Unset, Inherit } from 'react-polymorphic';
|
|
156
156
|
|
|
157
157
|
type Props = {
|
|
158
|
-
|
|
158
|
+
loading: boolean;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
type Config = PolymorphicConfig<'button', {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
'aria-loading': Unset;
|
|
163
|
+
children: string;
|
|
164
|
+
href: string;
|
|
165
|
+
target?: '_blank';
|
|
166
|
+
type: Inherit;
|
|
167
167
|
}>;
|
|
168
168
|
|
|
169
169
|
const Button = createPolymorph<'button', Props, Config>((props) => {
|
|
170
|
-
|
|
170
|
+
const { as: Tag = 'button', children, loading, ...rest } = props;
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
return (
|
|
173
|
+
<Tag aria-loading={loading} {...rest}>
|
|
174
|
+
{loading ? 'Loading...' : children}
|
|
175
|
+
</Tag>
|
|
176
|
+
)
|
|
177
177
|
})
|
|
178
178
|
|
|
179
179
|
const App = () => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
return (
|
|
181
|
+
<>
|
|
182
|
+
<Button type="button">Calculate</Button>
|
|
183
|
+
<Button as="a" href="/">Back to home</Button>
|
|
184
|
+
</>
|
|
185
|
+
)
|
|
186
186
|
}
|
|
187
187
|
```
|
|
188
188
|
|
|
@@ -201,12 +201,12 @@ import { createPolymorph } from 'react-polymorphic';
|
|
|
201
201
|
const OtherComponent = createPolymorph<'div'>(...);
|
|
202
202
|
|
|
203
203
|
const Component = createPolymorph<'div'>((props) => {
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
const { as: Tag = 'div', ...rest } = props;
|
|
205
|
+
return <Tag {...rest} />
|
|
206
206
|
});
|
|
207
207
|
|
|
208
208
|
const App = () => {
|
|
209
|
-
|
|
209
|
+
return <Component as={OtherComponent} root="section" />
|
|
210
210
|
}
|
|
211
211
|
```
|
|
212
212
|
|
|
@@ -219,9 +219,9 @@ You can extract generics from existing polymorphic components and reuse them whe
|
|
|
219
219
|
```tsx
|
|
220
220
|
import { createPolymorph } from 'react-polymorphic';
|
|
221
221
|
import type {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
InferPolymorphElement,
|
|
223
|
+
InferPolymorphProps,
|
|
224
|
+
InferPolymorphConfig
|
|
225
225
|
} from 'react-polymorphic';
|
|
226
226
|
import { TheirButton } from 'some-library';
|
|
227
227
|
|
|
@@ -237,8 +237,8 @@ type TheirConfig = InferPolymorphConfig<typeof TheirButton>;
|
|
|
237
237
|
type Props = { ... }
|
|
238
238
|
|
|
239
239
|
const OurButton = createPolymorph<typeof TheirButton, Props>((props) => {
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
const { as: Tag = TheirButton, ...rest } = props;
|
|
241
|
+
return <Tag {...rest} />
|
|
242
242
|
})
|
|
243
243
|
```
|
|
244
244
|
|
|
@@ -248,14 +248,14 @@ If swapping out the base would break core behavior, preserve the base and expose
|
|
|
248
248
|
|
|
249
249
|
```tsx
|
|
250
250
|
const OurButton = createPolymorph<TheirElement, Props & TheirProps, TheirConfig>(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
(props) => {
|
|
252
|
+
const { as = 'button', ...rest } = props;
|
|
253
|
+
return <TheirButton as={as} {...rest} />
|
|
254
|
+
}
|
|
255
255
|
)
|
|
256
256
|
|
|
257
257
|
const App = () => {
|
|
258
|
-
|
|
258
|
+
return <OurButton as="a" />
|
|
259
259
|
}
|
|
260
260
|
```
|
|
261
261
|
|
package/package.json
CHANGED
|
@@ -1,83 +1,80 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"typescript": ">=5.4.0"
|
|
82
|
-
}
|
|
83
|
-
}
|
|
2
|
+
"name": "react-polymorphic",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Create polymorphic React 19+ components with strong TypeScript inference.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"typescript",
|
|
8
|
+
"polymorphic",
|
|
9
|
+
"component-library",
|
|
10
|
+
"design-system",
|
|
11
|
+
"as-prop",
|
|
12
|
+
"headless-ui",
|
|
13
|
+
"ui"
|
|
14
|
+
],
|
|
15
|
+
"author": "Dashice",
|
|
16
|
+
"license": "Apache-2.0",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/Dashice/react-polymorphic.git"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/Dashice/react-polymorphic#readme",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/Dashice/react-polymorphic/issues"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"NOTICE"
|
|
32
|
+
],
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22.0.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@biomejs/biome": "^2.5.6",
|
|
44
|
+
"@changesets/cli": "^2.31.1",
|
|
45
|
+
"@testing-library/dom": "^10.4.1",
|
|
46
|
+
"@testing-library/react": "^16.3.2",
|
|
47
|
+
"@types/node": "^24.0.0",
|
|
48
|
+
"@types/react": "^19.2.18",
|
|
49
|
+
"happy-dom": "^20.11.1",
|
|
50
|
+
"husky": "^9.1.7",
|
|
51
|
+
"lint-staged": "^17.3.0",
|
|
52
|
+
"react": "^19.2.8",
|
|
53
|
+
"react-dom": "^19.2.8",
|
|
54
|
+
"tsup": "^8.5.1",
|
|
55
|
+
"typescript": "^7.0.2",
|
|
56
|
+
"vite": "^8.2.0",
|
|
57
|
+
"vitest": "^4.1.10"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"react": ">=19.0.0",
|
|
61
|
+
"react-dom": ">=19.0.0",
|
|
62
|
+
"typescript": ">=5.4.0"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"clean": "rm -rf dist",
|
|
66
|
+
"build": "pnpm clean && tsup && tsc -p tsconfig.build.json",
|
|
67
|
+
"format": "biome format . --write",
|
|
68
|
+
"format:check": "biome format .",
|
|
69
|
+
"lint": "biome lint .",
|
|
70
|
+
"lint:fix": "biome lint . --write",
|
|
71
|
+
"check": "biome check . --write",
|
|
72
|
+
"test": "vitest",
|
|
73
|
+
"test:run": "vitest run",
|
|
74
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
75
|
+
"lint:staged": "lint-staged",
|
|
76
|
+
"changeset": "changeset",
|
|
77
|
+
"version:packages": "changeset version",
|
|
78
|
+
"release": "changeset publish"
|
|
79
|
+
}
|
|
80
|
+
}
|