@vyriy/hoc 0.1.9
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/LICENSE +21 -0
- package/README.md +93 -0
- package/builder.d.ts +12 -0
- package/builder.js +16 -0
- package/compose.d.ts +2 -0
- package/compose.js +1 -0
- package/hocs/activity.d.ts +2 -0
- package/hocs/activity.js +3 -0
- package/hocs/profiler.d.ts +2 -0
- package/hocs/profiler.js +7 -0
- package/hocs/strict-mode.d.ts +2 -0
- package/hocs/strict-mode.js +3 -0
- package/hocs/suspense.d.ts +2 -0
- package/hocs/suspense.js +6 -0
- package/index.d.ts +9 -0
- package/index.js +8 -0
- package/package.json +110 -0
- package/react.d.ts +2 -0
- package/react.js +6 -0
- package/types.d.ts +6 -0
- package/wrapper.d.ts +10 -0
- package/wrapper.js +11 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vyriy contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @vyriy/hoc
|
|
2
|
+
|
|
3
|
+
React higher-order component utilities for Vyriy projects.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
This package is a home for reusable React HOC helpers such as strict rendering wrappers and other component decorators.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
With npm:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @vyriy/hoc
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
With Yarn:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
yarn add @vyriy/hoc
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Wrap a component with React `StrictMode`:
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { withStrictMode } from '@vyriy/hoc';
|
|
29
|
+
|
|
30
|
+
const App = () => <main />;
|
|
31
|
+
|
|
32
|
+
export default withStrictMode(App);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Wrap a component with the default React HOC stack:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { withReact } from '@vyriy/hoc';
|
|
39
|
+
|
|
40
|
+
const App = () => <main />;
|
|
41
|
+
|
|
42
|
+
export default withReact(App);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Compose your own HOC stack:
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { compose, withActivity, withProfiler, withStrictMode, withSuspense } from '@vyriy/hoc';
|
|
49
|
+
|
|
50
|
+
const withApp = compose(withStrictMode, withSuspense, withActivity, withProfiler);
|
|
51
|
+
|
|
52
|
+
export default withApp(App);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Create a custom HOC from a wrapper component:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { builder } from '@vyriy/hoc';
|
|
59
|
+
import type { PropsWithChildren } from 'react';
|
|
60
|
+
|
|
61
|
+
type LayoutProps = {
|
|
62
|
+
title: string;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const Layout = ({ children, title }: PropsWithChildren<LayoutProps>) => (
|
|
66
|
+
<section aria-label={title}>{children}</section>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
export const withLayout = builder(Layout, {
|
|
70
|
+
title: 'Application',
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Use the shared HOC type when declaring package-local helpers:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import type { Hoc } from '@vyriy/hoc';
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API
|
|
81
|
+
|
|
82
|
+
- `builder(WrapperComponent, wrapperProps?, childrenProps?)` creates a HOC from a wrapper component.
|
|
83
|
+
- `builder(WrapperComponent, wrapperProps, childrenProps, Component)` wraps a component immediately.
|
|
84
|
+
- `compose(...hocs)` composes HOCs from outermost to innermost.
|
|
85
|
+
- `wrapper(WrapperComponent, wrapperProps, childrenProps, Component)` wraps a component directly.
|
|
86
|
+
- `withActivity(Component)` wraps a component with React `Activity`.
|
|
87
|
+
- `withProfiler(Component)` wraps a component with React `Profiler` and default no-op profiling props.
|
|
88
|
+
- `withReact(Component)` wraps a component with `StrictMode`, `Suspense`, `Activity`, and `Profiler`.
|
|
89
|
+
- `withStrictMode(Component)` wraps a component with React `StrictMode`.
|
|
90
|
+
- `withSuspense(Component)` wraps a component with React `Suspense` and the default `<div>Loading...</div>` fallback.
|
|
91
|
+
- `Hoc<Props>` describes a React higher-order component that receives a component and returns a component with the same props.
|
|
92
|
+
- `ChildrenProps<Props, LocalProps>` maps render-prop wrapper values into wrapped component props.
|
|
93
|
+
- `WrapperComponent<WrapperProps, Children>` describes a component that accepts wrapper props and `children`.
|
package/builder.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import type { ChildrenProps, Hoc, WrapperComponent } from './types.js';
|
|
3
|
+
type RenderChildren<LocalProps extends unknown[]> = (...localProps: LocalProps) => ReactNode;
|
|
4
|
+
type Builder = {
|
|
5
|
+
<Props extends object, WrapperProps extends object = object, LocalProps extends unknown[] = unknown[]>(WrapperComponent: WrapperComponent<WrapperProps, RenderChildren<LocalProps>>, wrapperProps: WrapperProps | undefined, childrenProps: ChildrenProps<Props, LocalProps>, Component: ComponentType<Props>): ComponentType<Props>;
|
|
6
|
+
<Props extends object, WrapperProps extends object = object>(WrapperComponent: WrapperComponent<WrapperProps, ReactNode>, wrapperProps: WrapperProps | undefined, childrenProps: null | undefined, Component: ComponentType<Props>): ComponentType<Props>;
|
|
7
|
+
<Props extends object, WrapperProps extends object = object>(WrapperComponent: WrapperComponent<WrapperProps, ReactNode>, wrapperProps: WrapperProps, Component: ComponentType<Props>): ComponentType<Props>;
|
|
8
|
+
<Props extends object, WrapperProps extends object = object>(WrapperComponent: WrapperComponent<WrapperProps, ReactNode>, wrapperProps?: WrapperProps): Hoc<Props>;
|
|
9
|
+
<Props extends object = object, WrapperProps extends object = object, LocalProps extends unknown[] = unknown[]>(WrapperComponent: WrapperComponent<WrapperProps, RenderChildren<LocalProps>>, wrapperProps: WrapperProps | undefined, childrenProps: ChildrenProps<Props, LocalProps>): Hoc<Props>;
|
|
10
|
+
};
|
|
11
|
+
export declare const builder: Builder;
|
|
12
|
+
export {};
|
package/builder.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { wrapper } from './wrapper.js';
|
|
2
|
+
const createBuilder = (WrapperComponent, wrapperProps = {}, childrenProps = null, Component) => {
|
|
3
|
+
if (!WrapperComponent) {
|
|
4
|
+
throw new Error('WrapperComponent should be set!');
|
|
5
|
+
}
|
|
6
|
+
if (Component) {
|
|
7
|
+
return wrapper(WrapperComponent, wrapperProps, childrenProps, Component);
|
|
8
|
+
}
|
|
9
|
+
return (NewComponent) => {
|
|
10
|
+
if (!NewComponent) {
|
|
11
|
+
throw new Error('Component should be set!');
|
|
12
|
+
}
|
|
13
|
+
return wrapper(WrapperComponent, wrapperProps, childrenProps, NewComponent);
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export const builder = createBuilder;
|
package/compose.d.ts
ADDED
package/compose.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const compose = (...hocs) => (Component) => hocs.reduceRight((CurrentComponent, hoc) => hoc(CurrentComponent), Component);
|
package/hocs/activity.js
ADDED
package/hocs/profiler.js
ADDED
package/hocs/suspense.js
ADDED
package/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './builder.js';
|
|
2
|
+
export * from './compose.js';
|
|
3
|
+
export * from './hocs/activity.js';
|
|
4
|
+
export * from './hocs/profiler.js';
|
|
5
|
+
export * from './hocs/strict-mode.js';
|
|
6
|
+
export * from './hocs/suspense.js';
|
|
7
|
+
export * from './react.js';
|
|
8
|
+
export * from './wrapper.js';
|
|
9
|
+
export type * from './types.js';
|
package/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './builder.js';
|
|
2
|
+
export * from './compose.js';
|
|
3
|
+
export * from './hocs/activity.js';
|
|
4
|
+
export * from './hocs/profiler.js';
|
|
5
|
+
export * from './hocs/strict-mode.js';
|
|
6
|
+
export * from './hocs/suspense.js';
|
|
7
|
+
export * from './react.js';
|
|
8
|
+
export * from './wrapper.js';
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vyriy/hoc",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "React higher-order component utilities for Vyriy projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.js",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@types/react": "^19.2.14",
|
|
9
|
+
"react": "^19.2.6"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"types": "./index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./index.d.ts",
|
|
16
|
+
"import": "./index.js",
|
|
17
|
+
"default": "./index.js"
|
|
18
|
+
},
|
|
19
|
+
"./builder": {
|
|
20
|
+
"types": "./builder.d.ts",
|
|
21
|
+
"import": "./builder.js",
|
|
22
|
+
"default": "./builder.js"
|
|
23
|
+
},
|
|
24
|
+
"./builder.js": {
|
|
25
|
+
"types": "./builder.d.ts",
|
|
26
|
+
"import": "./builder.js",
|
|
27
|
+
"default": "./builder.js"
|
|
28
|
+
},
|
|
29
|
+
"./compose": {
|
|
30
|
+
"types": "./compose.d.ts",
|
|
31
|
+
"import": "./compose.js",
|
|
32
|
+
"default": "./compose.js"
|
|
33
|
+
},
|
|
34
|
+
"./compose.js": {
|
|
35
|
+
"types": "./compose.d.ts",
|
|
36
|
+
"import": "./compose.js",
|
|
37
|
+
"default": "./compose.js"
|
|
38
|
+
},
|
|
39
|
+
"./hocs/activity": {
|
|
40
|
+
"types": "./hocs/activity.d.ts",
|
|
41
|
+
"import": "./hocs/activity.js",
|
|
42
|
+
"default": "./hocs/activity.js"
|
|
43
|
+
},
|
|
44
|
+
"./hocs/activity.js": {
|
|
45
|
+
"types": "./hocs/activity.d.ts",
|
|
46
|
+
"import": "./hocs/activity.js",
|
|
47
|
+
"default": "./hocs/activity.js"
|
|
48
|
+
},
|
|
49
|
+
"./hocs/profiler": {
|
|
50
|
+
"types": "./hocs/profiler.d.ts",
|
|
51
|
+
"import": "./hocs/profiler.js",
|
|
52
|
+
"default": "./hocs/profiler.js"
|
|
53
|
+
},
|
|
54
|
+
"./hocs/profiler.js": {
|
|
55
|
+
"types": "./hocs/profiler.d.ts",
|
|
56
|
+
"import": "./hocs/profiler.js",
|
|
57
|
+
"default": "./hocs/profiler.js"
|
|
58
|
+
},
|
|
59
|
+
"./hocs/strict-mode": {
|
|
60
|
+
"types": "./hocs/strict-mode.d.ts",
|
|
61
|
+
"import": "./hocs/strict-mode.js",
|
|
62
|
+
"default": "./hocs/strict-mode.js"
|
|
63
|
+
},
|
|
64
|
+
"./hocs/strict-mode.js": {
|
|
65
|
+
"types": "./hocs/strict-mode.d.ts",
|
|
66
|
+
"import": "./hocs/strict-mode.js",
|
|
67
|
+
"default": "./hocs/strict-mode.js"
|
|
68
|
+
},
|
|
69
|
+
"./hocs/suspense": {
|
|
70
|
+
"types": "./hocs/suspense.d.ts",
|
|
71
|
+
"import": "./hocs/suspense.js",
|
|
72
|
+
"default": "./hocs/suspense.js"
|
|
73
|
+
},
|
|
74
|
+
"./hocs/suspense.js": {
|
|
75
|
+
"types": "./hocs/suspense.d.ts",
|
|
76
|
+
"import": "./hocs/suspense.js",
|
|
77
|
+
"default": "./hocs/suspense.js"
|
|
78
|
+
},
|
|
79
|
+
"./index": {
|
|
80
|
+
"types": "./index.d.ts",
|
|
81
|
+
"import": "./index.js",
|
|
82
|
+
"default": "./index.js"
|
|
83
|
+
},
|
|
84
|
+
"./index.js": {
|
|
85
|
+
"types": "./index.d.ts",
|
|
86
|
+
"import": "./index.js",
|
|
87
|
+
"default": "./index.js"
|
|
88
|
+
},
|
|
89
|
+
"./react": {
|
|
90
|
+
"types": "./react.d.ts",
|
|
91
|
+
"import": "./react.js",
|
|
92
|
+
"default": "./react.js"
|
|
93
|
+
},
|
|
94
|
+
"./react.js": {
|
|
95
|
+
"types": "./react.d.ts",
|
|
96
|
+
"import": "./react.js",
|
|
97
|
+
"default": "./react.js"
|
|
98
|
+
},
|
|
99
|
+
"./wrapper": {
|
|
100
|
+
"types": "./wrapper.d.ts",
|
|
101
|
+
"import": "./wrapper.js",
|
|
102
|
+
"default": "./wrapper.js"
|
|
103
|
+
},
|
|
104
|
+
"./wrapper.js": {
|
|
105
|
+
"types": "./wrapper.d.ts",
|
|
106
|
+
"import": "./wrapper.js",
|
|
107
|
+
"default": "./wrapper.js"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
package/react.d.ts
ADDED
package/react.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { compose } from './compose.js';
|
|
2
|
+
import { withActivity } from './hocs/activity.js';
|
|
3
|
+
import { withProfiler } from './hocs/profiler.js';
|
|
4
|
+
import { withStrictMode } from './hocs/strict-mode.js';
|
|
5
|
+
import { withSuspense } from './hocs/suspense.js';
|
|
6
|
+
export const withReact = (Component) => compose(withStrictMode, withSuspense, withActivity, withProfiler)(Component);
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ComponentType, JSXElementConstructor, ReactNode } from 'react';
|
|
2
|
+
export type Hoc<Props extends object = object> = (Component: ComponentType<Props>) => ComponentType<Props>;
|
|
3
|
+
export type ChildrenProps<Props extends object = object, LocalProps extends unknown[] = unknown[]> = (...localProps: LocalProps) => Partial<Props>;
|
|
4
|
+
export type WrapperComponent<WrapperProps extends object = object, Children = ReactNode> = JSXElementConstructor<WrapperProps & {
|
|
5
|
+
children: Children;
|
|
6
|
+
}>;
|
package/wrapper.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import type { ChildrenProps, WrapperComponent } from './types.js';
|
|
3
|
+
type RenderChildren<LocalProps extends unknown[]> = (...localProps: LocalProps) => ReactNode;
|
|
4
|
+
type Wrapper = {
|
|
5
|
+
<Props extends object, WrapperProps extends object = object, LocalProps extends unknown[] = unknown[]>(WrapperComponent: WrapperComponent<WrapperProps, RenderChildren<LocalProps>>, wrapperProps: WrapperProps, childrenProps: ChildrenProps<Props, LocalProps>, Component: ComponentType<Props>): ComponentType<Props>;
|
|
6
|
+
<Props extends object, WrapperProps extends object = object>(WrapperComponent: WrapperComponent<WrapperProps, ReactNode>, wrapperProps: WrapperProps, childrenProps: null, Component: ComponentType<Props>): ComponentType<Props>;
|
|
7
|
+
<Props extends object, WrapperProps extends object = object, LocalProps extends unknown[] = unknown[]>(WrapperComponent: WrapperComponent<WrapperProps, ReactNode | RenderChildren<LocalProps>>, wrapperProps: WrapperProps, childrenProps: ChildrenProps<Props, LocalProps> | null, Component: ComponentType<Props>): ComponentType<Props>;
|
|
8
|
+
};
|
|
9
|
+
export declare const wrapper: Wrapper;
|
|
10
|
+
export {};
|
package/wrapper.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const createWrapper = (WrapperComponent, wrapperProps = {}, childrenProps = null, Component) => {
|
|
3
|
+
const WrappedComponent = (props) => {
|
|
4
|
+
if (childrenProps) {
|
|
5
|
+
return (_jsx(WrapperComponent, { ...wrapperProps, ...props, children: (...localProps) => _jsx(Component, { ...props, ...childrenProps(...localProps) }) }));
|
|
6
|
+
}
|
|
7
|
+
return (_jsx(WrapperComponent, { ...wrapperProps, ...props, children: _jsx(Component, { ...props }) }));
|
|
8
|
+
};
|
|
9
|
+
return WrappedComponent;
|
|
10
|
+
};
|
|
11
|
+
export const wrapper = createWrapper;
|