react-better-html 1.1.9 → 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.
Files changed (41) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +56 -0
  3. package/dist/components/BetterHtmlProvider.d.ts +13 -3
  4. package/dist/components/BetterHtmlProvider.js +103 -24
  5. package/dist/components/Button.d.ts +63 -0
  6. package/dist/components/Button.js +157 -0
  7. package/dist/components/Div.d.ts +9 -17
  8. package/dist/components/Div.js +2 -2
  9. package/dist/components/Divider.d.ts +21 -0
  10. package/dist/components/Divider.js +20 -0
  11. package/dist/components/Icon.d.ts +13 -0
  12. package/dist/components/Icon.js +36 -0
  13. package/dist/components/Image.d.ts +18 -0
  14. package/dist/components/Image.js +44 -0
  15. package/dist/components/Loader.d.ts +16 -1
  16. package/dist/components/Loader.js +11 -0
  17. package/dist/components/Modal.d.ts +41 -0
  18. package/dist/components/Modal.js +93 -0
  19. package/dist/components/PageHolder.d.ts +8 -0
  20. package/dist/components/PageHolder.js +15 -0
  21. package/dist/components/Text.d.ts +5 -11
  22. package/dist/constants/app.d.ts +2 -0
  23. package/dist/constants/app.js +6 -0
  24. package/dist/constants/assets.d.ts +2 -0
  25. package/dist/constants/assets.js +10 -0
  26. package/dist/constants/icons.d.ts +2 -0
  27. package/dist/constants/icons.js +35 -0
  28. package/dist/constants/theme.d.ts +2 -0
  29. package/dist/constants/theme.js +46 -0
  30. package/dist/index.d.ts +9 -1
  31. package/dist/index.js +21 -1
  32. package/dist/types/app.d.ts +1 -0
  33. package/dist/types/asset.d.ts +4 -2
  34. package/dist/types/components.d.ts +3 -0
  35. package/dist/types/config.d.ts +8 -7
  36. package/dist/types/icon.d.ts +6 -3
  37. package/dist/types/loader.d.ts +3 -0
  38. package/dist/types/theme.d.ts +7 -5
  39. package/dist/utils/hooks.d.ts +20 -0
  40. package/dist/utils/hooks.js +40 -0
  41. package/package.json +4 -4
package/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 krissvv
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 CHANGED
@@ -1,3 +1,59 @@
1
1
  # react-better-html
2
2
 
3
3
  A component library for react that is as close to plane html as possible
4
+
5
+ ![NPM Version](https://img.shields.io/npm/v/react-better-html)
6
+ ![GitHub Repo stars](https://img.shields.io/github/stars/krissvv/react-better-html?style=flat)
7
+ ![GitHub package.json version](https://img.shields.io/github/package-json/v/krissvv/react-better-html)
8
+ ![NPM Type Definitions](https://img.shields.io/npm/types/react-better-html)<br/>
9
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/krissvv/react-better-html/deploy.yml)
10
+ ![GitHub last commit](https://img.shields.io/github/last-commit/krissvv/react-better-html)
11
+ ![NPM Downloads](https://img.shields.io/npm/dm/react-better-html)<br/>
12
+ ![NPM License](https://img.shields.io/npm/l/react-better-html)<br/>
13
+ ![React dep](https://img.shields.io/badge/React-v19-9b6499)
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
+
23
+ ## Requirements
24
+
25
+ - [React](https://react.dev) version 19.0 or above.
26
+
27
+ The library uses [styles-components](https://styled-components.com) under the hood to create all of the components in the library. `styles-components` is a peer dependency and will be installed automatically when downloading the `react-better-html`.
28
+
29
+ ## Installation
30
+
31
+ To install `react-better-html` run the following command in your project directory:
32
+
33
+ ```bash
34
+ npm install react-better-html
35
+ ```
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
+
57
+ ## Problems?
58
+
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, PartialBetterHtmlConfig } from "../types/config";
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: () => import("../types/theme").Theme;
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?: PartialBetterHtmlConfig;
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
- return context;
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
- return context.theme;
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
- space: 16,
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
- textPrimary: "#111111",
34
- textSecondary: "#777777",
35
- label: "#111111",
36
- primary: "#6d466b",
37
- secondary: "#412234",
38
- success: "#28a745",
39
- info: "#17a2b8",
40
- warn: "#ffc107",
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
- }), [value]);
56
- return (0, jsx_runtime_1.jsx)(betterHtmlContext.Provider, { value: readyValue, children: children });
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;
@@ -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
- ref?: React.Ref<HTMLDivElement>;
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
- ref?: React.Ref<HTMLDivElement>;
18
- }) => React.ReactElement;
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
- ref?: React.Ref<HTMLDivElement>;
22
- }) => React.ReactElement;
23
- grid: <Value>(props: OmitProps<DivProps<Value>, "display" | "flexDirection"> & {
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 & {
@@ -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 DivStylesComponent = styled_components_1.default.div.withConfig({
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)(DivStylesComponent, { 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 }));
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;