react-better-html 1.1.10 → 1.1.11
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 +28 -1
- package/dist/components/BetterHtmlProvider.d.ts +13 -3
- package/dist/components/BetterHtmlProvider.js +103 -24
- package/dist/components/Button.d.ts +63 -0
- package/dist/components/Button.js +157 -0
- package/dist/components/Div.d.ts +9 -17
- package/dist/components/Div.js +2 -2
- package/dist/components/Divider.d.ts +21 -0
- package/dist/components/Divider.js +20 -0
- package/dist/components/Icon.d.ts +13 -0
- package/dist/components/Icon.js +36 -0
- package/dist/components/Image.d.ts +18 -0
- package/dist/components/Image.js +44 -0
- package/dist/components/Loader.d.ts +16 -1
- package/dist/components/Loader.js +11 -0
- package/dist/components/Modal.d.ts +41 -0
- package/dist/components/Modal.js +93 -0
- package/dist/components/PageHolder.d.ts +8 -0
- package/dist/components/PageHolder.js +15 -0
- package/dist/components/Text.d.ts +5 -11
- package/dist/constants/app.d.ts +2 -0
- package/dist/constants/app.js +6 -0
- package/dist/constants/assets.d.ts +2 -0
- package/dist/constants/assets.js +10 -0
- package/dist/constants/icons.d.ts +2 -0
- package/dist/constants/icons.js +35 -0
- package/dist/constants/theme.d.ts +2 -0
- package/dist/constants/theme.js +46 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +21 -1
- package/dist/types/app.d.ts +1 -0
- package/dist/types/asset.d.ts +4 -2
- package/dist/types/components.d.ts +3 -0
- package/dist/types/config.d.ts +8 -7
- package/dist/types/icon.d.ts +6 -3
- package/dist/types/loader.d.ts +3 -0
- package/dist/types/theme.d.ts +7 -5
- package/dist/utils/hooks.d.ts +20 -0
- package/dist/utils/hooks.js +40 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
A component library for react that is as close to plane html as possible
|
|
4
4
|
|
|
5
|
-

|
|
6
5
|

|
|
7
6
|

|
|
8
7
|

|
|
@@ -13,6 +12,14 @@ A component library for react that is as close to plane html as possible
|
|
|
13
12
|
<br/>
|
|
14
13
|

|
|
15
14
|
|
|
15
|
+
# 🚧 Work in progress 🚧
|
|
16
|
+
|
|
17
|
+
🔴 The library is not yet ready for use - development is actively in progress 🔴
|
|
18
|
+
|
|
19
|
+
## Documentation
|
|
20
|
+
|
|
21
|
+
You can fined the full documentation on the home page of the official [Docs](https://krissvv.github.io/react-better-html) website.
|
|
22
|
+
|
|
16
23
|
## Requirements
|
|
17
24
|
|
|
18
25
|
- [React](https://react.dev) version 19.0 or above.
|
|
@@ -27,6 +34,26 @@ To install `react-better-html` run the following command in your project directo
|
|
|
27
34
|
npm install react-better-html
|
|
28
35
|
```
|
|
29
36
|
|
|
37
|
+
## Configuration
|
|
38
|
+
|
|
39
|
+
The `<BetterHtmlProvider>` component should wrap your application's root component to apply the configuration.
|
|
40
|
+
|
|
41
|
+
```jsx
|
|
42
|
+
import { createRoot } from "react-dom/client";
|
|
43
|
+
import { BetterHtmlProvider } from "react-better-html";
|
|
44
|
+
|
|
45
|
+
import App from "./App";
|
|
46
|
+
|
|
47
|
+
const root = document.getElementById("root");
|
|
48
|
+
createRoot(root).render(
|
|
49
|
+
<BetterHtmlProvider>
|
|
50
|
+
<App />
|
|
51
|
+
</BetterHtmlProvider>,
|
|
52
|
+
);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This is enough for the components to work with the default configurations that the library comes with. They can be overridden when passing `value` prop to the `<BetterHtmlProvider>` tag.
|
|
56
|
+
|
|
30
57
|
## Problems?
|
|
31
58
|
|
|
32
59
|
Ask for help on [Stack Overflow](https://stackoverflow.com/questions/ask), on our [GitHub repository](https://github.com/krissvv/react-better-html/issues/new) or contact the contributors.
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import { BetterHtmlConfig
|
|
1
|
+
import { BetterHtmlConfig } from "../types/config";
|
|
2
|
+
import { AnyOtherString, DeepPartialRecord } from "../types/app";
|
|
3
|
+
import { LoaderName } from "../types/loader";
|
|
2
4
|
export declare const useBetterHtmlContext: () => BetterHtmlConfig;
|
|
3
|
-
export declare const useTheme: () =>
|
|
5
|
+
export declare const useTheme: () => {
|
|
6
|
+
colors: import("../types/theme").Colors;
|
|
7
|
+
styles: import("../types/theme").Styles;
|
|
8
|
+
};
|
|
9
|
+
export declare const useLoader: (loaderName?: LoaderName | AnyOtherString) => boolean;
|
|
10
|
+
export declare const useLoaderControls: () => {
|
|
11
|
+
startLoading: (loaderName: LoaderName | AnyOtherString) => void;
|
|
12
|
+
stopLoading: (loaderName: LoaderName | AnyOtherString) => void;
|
|
13
|
+
};
|
|
4
14
|
type BetterHtmlProviderProps = {
|
|
5
|
-
value?:
|
|
15
|
+
value?: DeepPartialRecord<BetterHtmlConfig>;
|
|
6
16
|
children?: React.ReactNode;
|
|
7
17
|
};
|
|
8
18
|
declare function BetterHtmlProvider({ value, children }: BetterHtmlProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,58 +1,137 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useTheme = exports.useBetterHtmlContext = void 0;
|
|
3
|
+
exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
+
const styled_components_1 = require("styled-components");
|
|
7
|
+
const theme_1 = require("../constants/theme");
|
|
8
|
+
const icons_1 = require("../constants/icons");
|
|
9
|
+
const assets_1 = require("../constants/assets");
|
|
10
|
+
const app_1 = require("../constants/app");
|
|
11
|
+
const GlobalStyle = (0, styled_components_1.createGlobalStyle) `
|
|
12
|
+
body {
|
|
13
|
+
font-family: ${(props) => props.fontFamily};
|
|
14
|
+
color: ${(props) => props.color};
|
|
15
|
+
background-color: ${(props) => props.backgroundColor};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
* {
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: 0;
|
|
22
|
+
-webkit-tap-highlight-color: transparent;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
a {
|
|
26
|
+
text-decoration: none;
|
|
27
|
+
color: inherit;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
6
30
|
const betterHtmlContext = (0, react_1.createContext)(undefined);
|
|
7
31
|
const useBetterHtmlContext = () => {
|
|
8
32
|
const context = (0, react_1.useContext)(betterHtmlContext);
|
|
9
33
|
if (context === undefined)
|
|
10
34
|
throw new Error("`useBetterHtmlContext()` must be used within a `<BetterHtmlProvider>`. Make sure to add one at the root of your component tree.");
|
|
11
|
-
|
|
35
|
+
const { setLoaders, ...rest } = context;
|
|
36
|
+
return rest;
|
|
12
37
|
};
|
|
13
38
|
exports.useBetterHtmlContext = useBetterHtmlContext;
|
|
14
39
|
const useTheme = () => {
|
|
15
40
|
const context = (0, react_1.useContext)(betterHtmlContext);
|
|
41
|
+
const [currentTheme, setCurrentTheme] = (0, react_1.useState)("light");
|
|
16
42
|
if (context === undefined)
|
|
17
43
|
throw new Error("`useTheme()` must be used within a `<BetterHtmlProvider>`. Make sure to add one at the root of your component tree.");
|
|
18
|
-
|
|
44
|
+
(0, react_1.useEffect)(() => {
|
|
45
|
+
const html = document.querySelector("html");
|
|
46
|
+
if (!html)
|
|
47
|
+
return;
|
|
48
|
+
const observer = new MutationObserver((mutations) => {
|
|
49
|
+
mutations.forEach((mutation) => {
|
|
50
|
+
if (mutation.type === "attributes") {
|
|
51
|
+
setCurrentTheme(html.getAttribute("data-theme"));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
observer.observe(html, {
|
|
56
|
+
attributes: true,
|
|
57
|
+
});
|
|
58
|
+
return () => {
|
|
59
|
+
observer.disconnect();
|
|
60
|
+
};
|
|
61
|
+
}, []);
|
|
62
|
+
return {
|
|
63
|
+
...context.theme,
|
|
64
|
+
colors: context.theme.colors[currentTheme] ?? context.theme.colors.light,
|
|
65
|
+
};
|
|
19
66
|
};
|
|
20
67
|
exports.useTheme = useTheme;
|
|
68
|
+
const useLoader = (loaderName) => {
|
|
69
|
+
const context = (0, react_1.useContext)(betterHtmlContext);
|
|
70
|
+
if (context === undefined)
|
|
71
|
+
throw new Error("`useLoader()` must be used within a `<BetterHtmlProvider>`. Make sure to add one at the root of your component tree.");
|
|
72
|
+
return loaderName ? context.loaders[loaderName.toString()] ?? false : false;
|
|
73
|
+
};
|
|
74
|
+
exports.useLoader = useLoader;
|
|
75
|
+
const useLoaderControls = () => {
|
|
76
|
+
const context = (0, react_1.useContext)(betterHtmlContext);
|
|
77
|
+
if (context === undefined)
|
|
78
|
+
throw new Error("`useLoaderControls()` must be used within a `<BetterHtmlProvider>`. Make sure to add one at the root of your component tree.");
|
|
79
|
+
const startLoading = (0, react_1.useCallback)((loaderName) => {
|
|
80
|
+
context.setLoaders((oldValue) => ({
|
|
81
|
+
...oldValue,
|
|
82
|
+
[loaderName.toString()]: true,
|
|
83
|
+
}));
|
|
84
|
+
}, []);
|
|
85
|
+
const stopLoading = (0, react_1.useCallback)((loaderName) => {
|
|
86
|
+
context.setLoaders((oldValue) => ({
|
|
87
|
+
...oldValue,
|
|
88
|
+
[loaderName.toString()]: false,
|
|
89
|
+
}));
|
|
90
|
+
}, []);
|
|
91
|
+
return {
|
|
92
|
+
startLoading,
|
|
93
|
+
stopLoading,
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
exports.useLoaderControls = useLoaderControls;
|
|
97
|
+
function BetterHtmlProviderContent({ children }) {
|
|
98
|
+
const theme = (0, exports.useTheme)();
|
|
99
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(GlobalStyle, { fontFamily: theme.styles.fontFamily, color: theme.colors.textPrimary, backgroundColor: theme.colors.backgroundBase }), children] }));
|
|
100
|
+
}
|
|
21
101
|
function BetterHtmlProvider({ value, children }) {
|
|
102
|
+
const [loaders, setLoaders] = (0, react_1.useState)(value?.loaders ?? {});
|
|
22
103
|
const readyValue = (0, react_1.useMemo)(() => ({
|
|
104
|
+
app: {
|
|
105
|
+
...app_1.appConfig,
|
|
106
|
+
...value?.app,
|
|
107
|
+
},
|
|
23
108
|
theme: {
|
|
24
109
|
styles: {
|
|
25
|
-
|
|
26
|
-
gap: 8,
|
|
27
|
-
borderRadius: 10,
|
|
28
|
-
fontFamily: "Arial, sans-serif",
|
|
29
|
-
transition: "ease 0.2s",
|
|
110
|
+
...theme_1.theme.styles,
|
|
30
111
|
...value?.theme?.styles,
|
|
31
112
|
},
|
|
32
113
|
colors: {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
error: "#dc3545",
|
|
42
|
-
backgroundBase: "#f8f8f8",
|
|
43
|
-
backgroundSecondary: "#e8e8e8",
|
|
44
|
-
backgroundContent: "#ffffff",
|
|
45
|
-
border: "#ced4da",
|
|
46
|
-
...value?.theme?.colors,
|
|
114
|
+
light: {
|
|
115
|
+
...theme_1.theme.colors.light,
|
|
116
|
+
...value?.theme?.colors?.light,
|
|
117
|
+
},
|
|
118
|
+
dark: {
|
|
119
|
+
...theme_1.theme.colors.dark,
|
|
120
|
+
...value?.theme?.colors?.dark,
|
|
121
|
+
},
|
|
47
122
|
},
|
|
48
123
|
},
|
|
49
124
|
icons: {
|
|
125
|
+
...icons_1.icons,
|
|
50
126
|
...value?.icons,
|
|
51
127
|
},
|
|
52
128
|
assets: {
|
|
129
|
+
...assets_1.assets,
|
|
53
130
|
...value?.assets,
|
|
54
131
|
},
|
|
55
|
-
|
|
56
|
-
|
|
132
|
+
loaders,
|
|
133
|
+
setLoaders,
|
|
134
|
+
}), [value, loaders]);
|
|
135
|
+
return ((0, jsx_runtime_1.jsx)(betterHtmlContext.Provider, { value: readyValue, children: (0, jsx_runtime_1.jsx)(BetterHtmlProviderContent, { children: children }) }));
|
|
57
136
|
}
|
|
58
137
|
exports.default = (0, react_1.memo)(BetterHtmlProvider);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ComponentProps } from "react";
|
|
2
|
+
import { IconName } from "../types/icon";
|
|
3
|
+
import { AssetName } from "../types/asset";
|
|
4
|
+
import { LoaderName } from "../types/loader";
|
|
5
|
+
import { AnyOtherString, OmitProps } from "../types/app";
|
|
6
|
+
import { ComponentHoverStyle, ComponentStyle } from "../types/components";
|
|
7
|
+
type ButtonProps<Value> = {
|
|
8
|
+
href?: string;
|
|
9
|
+
text?: string;
|
|
10
|
+
value?: Value;
|
|
11
|
+
icon?: IconName;
|
|
12
|
+
/** @default "left" */
|
|
13
|
+
iconPosition?: "left" | "right";
|
|
14
|
+
/** @default Same as text color */
|
|
15
|
+
iconColor?: string;
|
|
16
|
+
/** @default 16 */
|
|
17
|
+
iconSize?: number;
|
|
18
|
+
image?: AssetName;
|
|
19
|
+
/** @default "left" */
|
|
20
|
+
imagePosition?: "left" | "right";
|
|
21
|
+
/** @default 16 */
|
|
22
|
+
imageWidth?: number;
|
|
23
|
+
/** @default undefined */
|
|
24
|
+
imageHeight?: number;
|
|
25
|
+
loaderName?: LoaderName | AnyOtherString;
|
|
26
|
+
/** @default 16 */
|
|
27
|
+
loaderSize?: number;
|
|
28
|
+
/** @default false */
|
|
29
|
+
isLoading?: boolean;
|
|
30
|
+
/** @default false */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** @default false */
|
|
33
|
+
isSmall?: boolean;
|
|
34
|
+
/** @default false */
|
|
35
|
+
isSubmit?: boolean;
|
|
36
|
+
onClickWithValue?: (value: Value) => void;
|
|
37
|
+
} & OmitProps<React.ComponentProps<"button">, "style" | "defaultValue"> & ComponentStyle & ComponentHoverStyle;
|
|
38
|
+
type ButtonComponent = {
|
|
39
|
+
<Value>(props: ButtonProps<Value>): React.ReactElement;
|
|
40
|
+
secondary: <Value>(props: ButtonProps<Value>) => React.ReactElement;
|
|
41
|
+
destructive: <Value>(props: ButtonProps<Value>) => React.ReactElement;
|
|
42
|
+
icon: <Value>(props: OmitProps<ButtonProps<Value>, "icon" | "width" | "height" | "isSmall"> & {
|
|
43
|
+
icon: IconName;
|
|
44
|
+
/** @default 16 */
|
|
45
|
+
size?: number;
|
|
46
|
+
/** @default "#000000" */
|
|
47
|
+
backgroundButtonColor?: string;
|
|
48
|
+
}) => React.ReactElement;
|
|
49
|
+
upload: <Value>(props: OmitProps<ButtonProps<Value>, "onClick"> & {
|
|
50
|
+
accept?: ComponentProps<"input">["accept"];
|
|
51
|
+
/** @default false */
|
|
52
|
+
multiple?: boolean;
|
|
53
|
+
onUpload?: (files: FileList | null) => void;
|
|
54
|
+
}) => React.ReactElement;
|
|
55
|
+
};
|
|
56
|
+
declare const ButtonComponent: ButtonComponent;
|
|
57
|
+
declare const Button: typeof ButtonComponent & {
|
|
58
|
+
secondary: typeof ButtonComponent.secondary;
|
|
59
|
+
destructive: typeof ButtonComponent.destructive;
|
|
60
|
+
icon: typeof ButtonComponent.icon;
|
|
61
|
+
upload: typeof ButtonComponent.upload;
|
|
62
|
+
};
|
|
63
|
+
export default Button;
|
|
@@ -0,0 +1,157 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
40
|
+
const react_1 = require("react");
|
|
41
|
+
const styled_components_1 = __importStar(require("styled-components"));
|
|
42
|
+
const hooks_1 = require("../utils/hooks");
|
|
43
|
+
const Div_1 = __importDefault(require("./Div"));
|
|
44
|
+
const Icon_1 = __importDefault(require("./Icon"));
|
|
45
|
+
const Loader_1 = __importDefault(require("./Loader"));
|
|
46
|
+
const Image_1 = __importDefault(require("./Image"));
|
|
47
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
48
|
+
const ButtonElement = styled_components_1.default.button.withConfig({
|
|
49
|
+
shouldForwardProp: (prop) => !["theme", "normalStyle", "hoverStyle", "isSmall", "withText", "isLoading"].includes(prop),
|
|
50
|
+
}) `
|
|
51
|
+
position: relative;
|
|
52
|
+
width: fit-content;
|
|
53
|
+
min-width: max-content;
|
|
54
|
+
font-family: ${(props) => props.theme.styles.fontFamily};
|
|
55
|
+
font-size: 16px;
|
|
56
|
+
line-height: 20px;
|
|
57
|
+
text-decoration: none;
|
|
58
|
+
color: ${(props) => props.theme.colors.base};
|
|
59
|
+
background-color: ${(props) => props.theme.colors.primary};
|
|
60
|
+
border: none;
|
|
61
|
+
border-radius: ${(props) => props.theme.styles.borderRadius}px;
|
|
62
|
+
padding: ${(props) => props.isSmall
|
|
63
|
+
? `${props.theme.styles.gap + 1}px ${props.theme.styles.space}px`
|
|
64
|
+
: `${(props.theme.styles.gap + props.theme.styles.space) / 2 + 1}px ${props.theme.styles.space + (props.withText ? props.theme.styles.gap : 0)}px`};
|
|
65
|
+
user-select: none;
|
|
66
|
+
flex-shrink: 0;
|
|
67
|
+
transition: ${(props) => props.theme.styles.transition};
|
|
68
|
+
|
|
69
|
+
${(props) => props.disabled
|
|
70
|
+
? (0, styled_components_1.css) `
|
|
71
|
+
opacity: 0.6;
|
|
72
|
+
cursor: not-allowed;
|
|
73
|
+
|
|
74
|
+
&.secondary.disabled {
|
|
75
|
+
opacity: 0.4;
|
|
76
|
+
}
|
|
77
|
+
`
|
|
78
|
+
: !props.isLoading
|
|
79
|
+
? (0, styled_components_1.css) `
|
|
80
|
+
cursor: pointer;
|
|
81
|
+
|
|
82
|
+
&:not(.secondary):hover {
|
|
83
|
+
filter: brightness(0.9);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&.secondary:hover {
|
|
87
|
+
border-color: ${props.theme.colors.primary};
|
|
88
|
+
}
|
|
89
|
+
`
|
|
90
|
+
: ""}
|
|
91
|
+
|
|
92
|
+
&.secondary {
|
|
93
|
+
padding-block: ${(props) => props.isSmall ? props.theme.styles.gap : (props.theme.styles.space + props.theme.styles.gap) / 2}px;
|
|
94
|
+
border: solid 1px ${(props) => props.theme.colors.border};
|
|
95
|
+
background-color: ${(props) => props.theme.colors.backgroundContent};
|
|
96
|
+
background-image: none;
|
|
97
|
+
|
|
98
|
+
${(props) => props.normalStyle}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
${(props) => props.normalStyle}
|
|
102
|
+
|
|
103
|
+
&:hover {
|
|
104
|
+
${(props) => props.hoverStyle}
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
const ButtonComponent = function Button({ href, text, value, icon, iconPosition = "left", iconColor, iconSize, image, imagePosition = "left", imageWidth, imageHeight, loaderName, loaderSize, isLoading, disabled, isSmall, isSubmit, onClick, onClickWithValue, ...props }) {
|
|
108
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
109
|
+
const isLoadingHook = (0, BetterHtmlProvider_1.useLoader)(loaderName);
|
|
110
|
+
const isLoadingElement = isLoading ?? isLoadingHook;
|
|
111
|
+
const styledComponentStyles = (0, hooks_1.useStyledComponentStyles)(props, theme);
|
|
112
|
+
const dataProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "data");
|
|
113
|
+
const ariaProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "aria");
|
|
114
|
+
const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
|
|
115
|
+
const onClickElement = (0, react_1.useCallback)((event) => {
|
|
116
|
+
onClick?.(event);
|
|
117
|
+
onClickWithValue?.(value);
|
|
118
|
+
}, [onClick, onClickWithValue, value]);
|
|
119
|
+
const iconComponent = icon ? ((0, jsx_runtime_1.jsx)(Div_1.default.row, { height: 20, alignItems: "center", justifyContent: "center", children: (0, jsx_runtime_1.jsx)(Icon_1.default, { name: icon, color: iconColor ?? props.color ?? theme.colors.base, size: iconSize ?? parseInt(styledComponentStyles.normalStyle.fontSize?.toString() ?? "16") }) })) : undefined;
|
|
120
|
+
const imageComponent = image ? ((0, jsx_runtime_1.jsx)(Image_1.default, { name: image, color: iconColor ?? props.color ?? theme.colors.base, width: imageWidth ?? parseInt(styledComponentStyles.normalStyle.fontSize?.toString() ?? "16"), height: imageHeight })) : undefined;
|
|
121
|
+
return ((0, jsx_runtime_1.jsxs)(ButtonElement, { as: href ? "a" : "button", theme: theme, isSmall: isSmall, withText: text !== undefined, isLoading: isLoadingElement, disabled: disabled, href: href, type: isSubmit && !isLoadingElement ? "submit" : "button", onClick: !disabled && !isLoadingElement ? onClickElement : undefined, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps, children: [(0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", justifyContent: "center", gap: 10, pointerEvents: "none", opacity: isLoadingElement ? 0 : 1, transition: theme.styles.transition, children: [iconPosition === "left" && iconComponent, imagePosition === "left" && imageComponent, text, iconPosition === "right" && iconComponent, imagePosition === "right" && imageComponent] }), (0, jsx_runtime_1.jsx)(Div_1.default.row, { position: "absolute", width: "100%", height: "100%", top: 0, left: 0, pointerEvents: "none", alignItems: "center", justifyContent: "center", opacity: isLoadingElement ? 1 : 0, transition: theme.styles.transition, children: (0, jsx_runtime_1.jsx)(Loader_1.default, { color: props.color ?? theme.colors.base, size: loaderSize, disabled: !isLoadingElement }) })] }));
|
|
122
|
+
};
|
|
123
|
+
ButtonComponent.secondary = function Secondary({ className, ...props }) {
|
|
124
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
125
|
+
return ((0, jsx_runtime_1.jsx)(ButtonComponent, { className: `secondary${className ? ` ${className}` : ""}`, color: theme.colors.textPrimary, ...props }));
|
|
126
|
+
};
|
|
127
|
+
ButtonComponent.destructive = function Destructive(props) {
|
|
128
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
129
|
+
return (0, jsx_runtime_1.jsx)(ButtonComponent, { backgroundColor: theme.colors.error, color: theme.colors.base, ...props });
|
|
130
|
+
};
|
|
131
|
+
ButtonComponent.icon = function Icon({ size = 16, backgroundButtonColor, ...props }) {
|
|
132
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
133
|
+
const buttonSize = size + theme.styles.space;
|
|
134
|
+
const backgroundButtonColorReady = backgroundButtonColor ?? theme.colors.textPrimary;
|
|
135
|
+
return ((0, jsx_runtime_1.jsx)(ButtonComponent, { width: buttonSize, height: buttonSize, color: theme.colors.textPrimary, backgroundColor: backgroundButtonColorReady + "00", backgroundImage: "none", backgroundColorHover: backgroundButtonColorReady + "20", borderRadius: 999, iconSize: size, loaderSize: 12, border: "none", padding: 0, filterHover: "none !important", ...props }));
|
|
136
|
+
};
|
|
137
|
+
ButtonComponent.upload = function Upload({ accept, multiple, onUpload, ...props }) {
|
|
138
|
+
const onClickElement = (0, react_1.useCallback)(() => {
|
|
139
|
+
const input = document.createElement("input");
|
|
140
|
+
input.setAttribute("type", "file");
|
|
141
|
+
if (accept)
|
|
142
|
+
input.setAttribute("accept", accept);
|
|
143
|
+
if (multiple)
|
|
144
|
+
input.setAttribute("multiple", "true");
|
|
145
|
+
input.addEventListener("change", () => {
|
|
146
|
+
onUpload?.(input.files);
|
|
147
|
+
});
|
|
148
|
+
input.click();
|
|
149
|
+
}, [accept]);
|
|
150
|
+
return (0, jsx_runtime_1.jsx)(ButtonComponent, { text: "Upload", icon: "uploadCloud", onClick: onClickElement, ...props });
|
|
151
|
+
};
|
|
152
|
+
const Button = (0, react_1.memo)(ButtonComponent);
|
|
153
|
+
Button.secondary = ButtonComponent.secondary;
|
|
154
|
+
Button.destructive = ButtonComponent.destructive;
|
|
155
|
+
Button.icon = ButtonComponent.icon;
|
|
156
|
+
Button.upload = ButtonComponent.upload;
|
|
157
|
+
exports.default = Button;
|
package/dist/components/Div.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JSX } from "react";
|
|
2
|
-
import { ComponentHoverStyle, ComponentStyle } from "../types/components";
|
|
2
|
+
import { ComponentHoverStyle, ComponentPropWithRef, ComponentStyle } from "../types/components";
|
|
3
3
|
import { OmitProps } from "../types/app";
|
|
4
4
|
export type DivProps<Value> = {
|
|
5
5
|
value?: Value;
|
|
@@ -7,25 +7,17 @@ export type DivProps<Value> = {
|
|
|
7
7
|
as?: keyof JSX.IntrinsicElements;
|
|
8
8
|
isTabAccessed?: boolean;
|
|
9
9
|
onClickWithValue?: (value: Value) => void;
|
|
10
|
-
} & OmitProps<React.ComponentProps<"div">, "style"> & ComponentStyle & ComponentHoverStyle;
|
|
10
|
+
} & OmitProps<React.ComponentProps<"div">, "style" | "defaultValue"> & ComponentStyle & ComponentHoverStyle;
|
|
11
11
|
type DivComponentType = {
|
|
12
|
-
<Value>(props: DivProps<Value
|
|
13
|
-
|
|
14
|
-
}): React.ReactElement;
|
|
15
|
-
row: <Value>(props: OmitProps<DivProps<Value>, "display" | "flexDirection"> & {
|
|
12
|
+
<Value>(props: ComponentPropWithRef<HTMLDivElement, DivProps<Value>>): React.ReactElement;
|
|
13
|
+
row: <Value>(props: ComponentPropWithRef<HTMLDivElement, OmitProps<DivProps<Value>, "display" | "flexDirection"> & {
|
|
16
14
|
invertFlexDirection?: boolean;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
column: <Value>(props: OmitProps<DivProps<Value>, "display" | "flexDirection"> & {
|
|
15
|
+
}>) => React.ReactElement;
|
|
16
|
+
column: <Value>(props: ComponentPropWithRef<HTMLDivElement, OmitProps<DivProps<Value>, "display" | "flexDirection"> & {
|
|
20
17
|
invertFlexDirection?: boolean;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
ref?: React.Ref<HTMLDivElement>;
|
|
25
|
-
}) => React.ReactElement;
|
|
26
|
-
box: <Value>(props: DivProps<Value> & {
|
|
27
|
-
ref?: React.Ref<HTMLDivElement>;
|
|
28
|
-
}) => React.ReactElement;
|
|
18
|
+
}>) => React.ReactElement;
|
|
19
|
+
grid: <Value>(props: ComponentPropWithRef<HTMLDivElement, OmitProps<DivProps<Value>, "display">>) => React.ReactElement;
|
|
20
|
+
box: <Value>(props: ComponentPropWithRef<HTMLDivElement, DivProps<Value>>) => React.ReactElement;
|
|
29
21
|
};
|
|
30
22
|
declare const DivComponent: DivComponentType;
|
|
31
23
|
declare const Div: typeof DivComponent & {
|
package/dist/components/Div.js
CHANGED
|
@@ -9,7 +9,7 @@ const styled_components_1 = __importDefault(require("styled-components"));
|
|
|
9
9
|
const constants_1 = require("../constants");
|
|
10
10
|
const hooks_1 = require("../utils/hooks");
|
|
11
11
|
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
12
|
-
const
|
|
12
|
+
const DivStyledComponent = styled_components_1.default.div.withConfig({
|
|
13
13
|
shouldForwardProp: (prop) => !["normalStyle", "hoverStyle"].includes(prop),
|
|
14
14
|
}) `
|
|
15
15
|
${(props) => props.normalStyle}
|
|
@@ -37,7 +37,7 @@ const DivComponent = (0, react_1.forwardRef)(function Div({ value, as, isTabAcce
|
|
|
37
37
|
event.currentTarget.click();
|
|
38
38
|
}
|
|
39
39
|
}, [onKeyDown, isTabAccessed]);
|
|
40
|
-
return ((0, jsx_runtime_1.jsx)(
|
|
40
|
+
return ((0, jsx_runtime_1.jsx)(DivStyledComponent, { as: as, tabIndex: isTabAccessed && !constants_1.isMobileDevice ? 0 : undefined, role: role ?? (onClick ? "button" : undefined), onClick: onClickElement, onKeyDown: onKeyDownElement, ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps, ref: ref, children: children }));
|
|
41
41
|
});
|
|
42
42
|
DivComponent.row = (0, react_1.forwardRef)(function Row(props, ref) {
|
|
43
43
|
return ((0, jsx_runtime_1.jsx)(DivComponent, { display: "flex", flexDirection: props.invertFlexDirection ? "column" : "row", ref: ref, ...props }));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type DividerProps = {
|
|
2
|
+
/** @default 1 */
|
|
3
|
+
width?: number;
|
|
4
|
+
/** @default border */
|
|
5
|
+
backgroundColor?: string;
|
|
6
|
+
paddingBlock?: number;
|
|
7
|
+
};
|
|
8
|
+
type VerticalDividerProps = DividerProps & {
|
|
9
|
+
/** @default "100%" */
|
|
10
|
+
height?: number;
|
|
11
|
+
};
|
|
12
|
+
type HorizontalDividerProps = DividerProps & {
|
|
13
|
+
text?: string;
|
|
14
|
+
/** @default textSecondary */
|
|
15
|
+
textColor?: string;
|
|
16
|
+
};
|
|
17
|
+
declare const _default: {
|
|
18
|
+
vertical: import("react").NamedExoticComponent<VerticalDividerProps>;
|
|
19
|
+
horizontal: import("react").NamedExoticComponent<HorizontalDividerProps>;
|
|
20
|
+
};
|
|
21
|
+
export default _default;
|
|
@@ -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
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const Div_1 = __importDefault(require("./Div"));
|
|
9
|
+
const Text_1 = __importDefault(require("./Text"));
|
|
10
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
11
|
+
exports.default = {
|
|
12
|
+
vertical: (0, react_1.memo)(function Divider({ width = 1, backgroundColor, paddingBlock, height }) {
|
|
13
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
14
|
+
return ((0, jsx_runtime_1.jsx)(Div_1.default, { width: width, height: height ?? "100%", flexShrink: 0, backgroundColor: backgroundColor ?? theme.colors.border, paddingBlock: paddingBlock }));
|
|
15
|
+
}),
|
|
16
|
+
horizontal: (0, react_1.memo)(function Divider({ width = 1, backgroundColor, paddingBlock, text, textColor, }) {
|
|
17
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
18
|
+
return ((0, jsx_runtime_1.jsxs)(Div_1.default.row, { alignItems: "center", gap: text ? theme.styles.space : undefined, paddingBlock: paddingBlock, children: [(0, jsx_runtime_1.jsx)(Div_1.default, { flex: 1, height: width, flexShrink: 0, backgroundColor: backgroundColor ?? theme.colors.border }), text && (0, jsx_runtime_1.jsx)(Text_1.default, { color: textColor ?? theme.colors.textSecondary, children: text }), (0, jsx_runtime_1.jsx)(Div_1.default, { flex: 1, height: width, flexShrink: 0, backgroundColor: backgroundColor ?? theme.colors.border })] }));
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AnyOtherString, OmitProps } from "../types/app";
|
|
2
|
+
import { ComponentHoverStyle, ComponentPropWithRef, ComponentStyle } from "../types/components";
|
|
3
|
+
import { IconName } from "../types/icon";
|
|
4
|
+
type IconProps = {
|
|
5
|
+
name: IconName | AnyOtherString;
|
|
6
|
+
/** @default 16 */
|
|
7
|
+
size?: number;
|
|
8
|
+
} & OmitProps<React.ComponentProps<"svg">, "style" | "width" | "height" | "viewBox" | "fill" | "xmlns"> & ComponentStyle & ComponentHoverStyle;
|
|
9
|
+
type IconComponent = {
|
|
10
|
+
(props: ComponentPropWithRef<SVGSVGElement, IconProps>): React.ReactElement;
|
|
11
|
+
};
|
|
12
|
+
declare const _default: IconComponent;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const react_2 = require("react");
|
|
9
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
10
|
+
const hooks_1 = require("../utils/hooks");
|
|
11
|
+
const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
|
|
12
|
+
const IconElement = styled_components_1.default.svg.withConfig({
|
|
13
|
+
shouldForwardProp: (prop) => !["normalStyle", "hoverStyle"].includes(prop),
|
|
14
|
+
}) `
|
|
15
|
+
${(props) => props.normalStyle}
|
|
16
|
+
|
|
17
|
+
&:hover {
|
|
18
|
+
${(props) => props.hoverStyle}
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
const Icon = (0, react_2.forwardRef)(function Icon({ name, size = 16, ...props }, ref) {
|
|
22
|
+
const theme = (0, BetterHtmlProvider_1.useTheme)();
|
|
23
|
+
const { icons } = (0, BetterHtmlProvider_1.useBetterHtmlContext)();
|
|
24
|
+
const styledComponentStyles = (0, hooks_1.useStyledComponentStyles)(props, theme);
|
|
25
|
+
const dataProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "data");
|
|
26
|
+
const ariaProps = (0, hooks_1.useComponentPropsWithPrefix)(props, "aria");
|
|
27
|
+
const restProps = (0, hooks_1.useComponentPropsWithoutStyle)(props);
|
|
28
|
+
const svgColor = props.color ?? theme.colors.textPrimary;
|
|
29
|
+
(0, react_2.useEffect)(() => {
|
|
30
|
+
if (!icons[name])
|
|
31
|
+
console.warn(`The icon \`${name}\` you are trying to use does not exist. Make sure to add it to the \`icons\` object in \`<BetterHtmlProvider>\` config value prop.`);
|
|
32
|
+
}, [icons, name]);
|
|
33
|
+
return ((0, jsx_runtime_1.jsx)(IconElement, { width: size, height: size, viewBox: `0 0 ${icons[name]?.width ?? 0} ${icons[name]?.height ?? 0}`, fill: "none", xmlns: "http://www.w3.org/2000/svg", ...styledComponentStyles, ...dataProps, ...ariaProps, ...restProps, ref: ref, children: icons[name]?.paths.map((path) => ((0, react_1.createElement)("path", { ...path, fill: path.type === "fill" ? svgColor : undefined, stroke: path.type === "stroke" ? svgColor : undefined, key: path.d }))) }));
|
|
34
|
+
});
|
|
35
|
+
const MemoizedIcon = (0, react_2.memo)(Icon);
|
|
36
|
+
exports.default = { Icon: MemoizedIcon }.Icon;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AnyOtherString, OmitProps } from "../types/app";
|
|
2
|
+
import { ComponentHoverStyle, ComponentPropWithRef, ComponentStyle } from "../types/components";
|
|
3
|
+
import { AssetName } from "../types/asset";
|
|
4
|
+
type ImageProps = {
|
|
5
|
+
name?: AssetName | AnyOtherString;
|
|
6
|
+
} & OmitProps<React.ComponentProps<"img">, "style"> & ComponentStyle & ComponentHoverStyle;
|
|
7
|
+
type ImageComponent = {
|
|
8
|
+
(props: ComponentPropWithRef<HTMLImageElement, ImageProps>): React.ReactElement;
|
|
9
|
+
profileImage: (props: ComponentPropWithRef<HTMLImageElement, OmitProps<ImageProps, "width" | "height"> & {
|
|
10
|
+
/** @default 40 */
|
|
11
|
+
size?: number;
|
|
12
|
+
}>) => React.ReactElement;
|
|
13
|
+
};
|
|
14
|
+
declare const Image: ImageComponent;
|
|
15
|
+
declare const _default: ImageComponent & {
|
|
16
|
+
profileImage: typeof Image.profileImage;
|
|
17
|
+
};
|
|
18
|
+
export default _default;
|