react-better-html 1.1.20 → 1.1.21

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.
@@ -1,6 +1,7 @@
1
1
  import { BetterHtmlConfig } from "../types/config";
2
2
  import { AnyOtherString, DeepPartialRecord } from "../types/app";
3
3
  import { LoaderName } from "../types/loader";
4
+ import { BetterHtmlPlugin, PluginName } from "../types/plugin";
4
5
  export declare const useBetterHtmlContext: () => BetterHtmlConfig;
5
6
  export declare const useTheme: () => {
6
7
  colors: import("../types/theme").Colors;
@@ -11,10 +12,12 @@ export declare const useLoaderControls: () => {
11
12
  startLoading: (loaderName: LoaderName | AnyOtherString) => void;
12
13
  stopLoading: (loaderName: LoaderName | AnyOtherString) => void;
13
14
  };
15
+ export declare const usePlugin: (pluginName: PluginName) => BetterHtmlPlugin | undefined;
14
16
  type BetterHtmlProviderProps = {
15
17
  value?: DeepPartialRecord<BetterHtmlConfig>;
18
+ plugins?: BetterHtmlPlugin[];
16
19
  children?: React.ReactNode;
17
20
  };
18
- declare function BetterHtmlProvider({ value, children }: BetterHtmlProviderProps): import("react/jsx-runtime").JSX.Element;
21
+ declare function BetterHtmlProvider({ value, plugins: pluginsToUse, children }: BetterHtmlProviderProps): import("react/jsx-runtime").JSX.Element;
19
22
  declare const _default: import("react").MemoExoticComponent<typeof BetterHtmlProvider>;
20
23
  export default _default;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = void 0;
3
+ exports.usePlugin = 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
6
  const styled_components_1 = require("styled-components");
@@ -94,12 +94,21 @@ const useLoaderControls = () => {
94
94
  };
95
95
  };
96
96
  exports.useLoaderControls = useLoaderControls;
97
+ const usePlugin = (pluginName) => {
98
+ const context = (0, react_1.useContext)(betterHtmlContext);
99
+ if (context === undefined) {
100
+ throw new Error("`usePlugin()` must be used within a `<BetterHtmlProvider>`. Make sure to add one at the root of your component tree.");
101
+ }
102
+ return context.plugins.find((plugin) => plugin.name === pluginName);
103
+ };
104
+ exports.usePlugin = usePlugin;
97
105
  function BetterHtmlProviderContent({ children }) {
98
106
  const theme = (0, exports.useTheme)();
99
107
  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
108
  }
101
- function BetterHtmlProvider({ value, children }) {
109
+ function BetterHtmlProvider({ value, plugins: pluginsToUse, children }) {
102
110
  const [loaders, setLoaders] = (0, react_1.useState)(value?.loaders ?? {});
111
+ const [plugins] = (0, react_1.useState)(pluginsToUse ?? []);
103
112
  const readyValue = (0, react_1.useMemo)(() => ({
104
113
  app: {
105
114
  ...app_1.appConfig,
@@ -134,7 +143,13 @@ function BetterHtmlProvider({ value, children }) {
134
143
  components: {
135
144
  ...value?.components,
136
145
  },
137
- }), [value, loaders]);
146
+ plugins,
147
+ }), [value, loaders, plugins]);
148
+ (0, react_1.useEffect)(() => {
149
+ plugins.forEach((plugin) => {
150
+ plugin.initialize?.();
151
+ });
152
+ }, [plugins]);
138
153
  return ((0, jsx_runtime_1.jsx)(betterHtmlContext.Provider, { value: readyValue, children: (0, jsx_runtime_1.jsx)(BetterHtmlProviderContent, { children: children }) }));
139
154
  }
140
155
  exports.default = (0, react_1.memo)(BetterHtmlProvider);
@@ -0,0 +1,5 @@
1
+ type ExampleComponentProps = {
2
+ test?: string;
3
+ };
4
+ declare const _default: import("react").MemoExoticComponent<import("react").ComponentType<ExampleComponentProps>>;
5
+ export default _default;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const jsx_runtime_1 = require("react/jsx-runtime");
4
+ const react_1 = require("react");
5
+ const withPlugin_1 = require("../utils/withPlugin");
6
+ function ExampleComponent({ test, plugin }) {
7
+ const { Link } = plugin.components || {};
8
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("h1", { children: ["Example Component with Router Plugin: ", test] }), (0, jsx_runtime_1.jsx)(Link, { to: "/", children: "Go to Home Page" })] }));
9
+ }
10
+ exports.default = (0, react_1.memo)((0, withPlugin_1.withPlugin)("react-router-dom", ExampleComponent));
@@ -12,6 +12,8 @@ type ModalProps = {
12
12
  description?: string;
13
13
  descriptionColor?: string;
14
14
  headerBackgroundColor?: string;
15
+ /** @requires ReactRouterDomPlugin */
16
+ name?: string;
15
17
  overflow?: React.CSSProperties["overflow"];
16
18
  onOpen?: () => void;
17
19
  onClose?: () => void;
@@ -11,6 +11,7 @@ const Button_1 = __importDefault(require("./Button"));
11
11
  const Text_1 = __importDefault(require("./Text"));
12
12
  const Divider_1 = __importDefault(require("./Divider"));
13
13
  const BetterHtmlProvider_1 = require("./BetterHtmlProvider");
14
+ const hooks_1 = require("../utils/hooks");
14
15
  const DialogStylesElement = styled_components_1.default.dialog.withConfig({
15
16
  shouldForwardProp: (prop) => !["theme", "opacity"].includes(prop),
16
17
  }) `
@@ -50,7 +51,9 @@ const DialogStylesElement = styled_components_1.default.dialog.withConfig({
50
51
  }
51
52
  }
52
53
  `;
53
- const ModalComponent = (0, react_1.forwardRef)(function Modal({ maxWidth, title, titleColor, description, descriptionColor, headerBackgroundColor, overflow, onOpen, onClose, children, }, ref) {
54
+ const ModalComponent = (0, react_1.forwardRef)(function Modal({ maxWidth, title, titleColor, description, descriptionColor, headerBackgroundColor, name, overflow, onOpen, onClose, children, }, ref) {
55
+ const reactRouterDomPlugin = (0, BetterHtmlProvider_1.usePlugin)("react-router-dom");
56
+ const urlQuery = reactRouterDomPlugin ? (0, hooks_1.useUrlQuery)() : undefined;
54
57
  const theme = (0, BetterHtmlProvider_1.useTheme)();
55
58
  const { app } = (0, BetterHtmlProvider_1.useBetterHtmlContext)();
56
59
  const dialogRef = (0, react_1.useRef)(null);
@@ -60,16 +63,22 @@ const ModalComponent = (0, react_1.forwardRef)(function Modal({ maxWidth, title,
60
63
  dialogRef.current?.showModal();
61
64
  setIsOpened(true);
62
65
  setIsOpenedLate(true);
66
+ if (urlQuery && name)
67
+ urlQuery.setQuery({
68
+ [`${name}-modal`]: "opened",
69
+ }, false);
63
70
  onOpen?.();
64
- }, [onOpen]);
71
+ }, [onOpen, urlQuery, name]);
65
72
  const onClickClose = (0, react_1.useCallback)(() => {
66
73
  setIsOpened(false);
67
74
  onClose?.();
75
+ if (urlQuery && name)
76
+ urlQuery.removeQuery(`${name}-modal`, false);
68
77
  setTimeout(() => {
69
78
  dialogRef.current?.close();
70
79
  setIsOpenedLate(false);
71
80
  }, 0.2 * 1000);
72
- }, [onClose]);
81
+ }, [onClose, urlQuery, name]);
73
82
  (0, react_1.useImperativeHandle)(ref, () => {
74
83
  return {
75
84
  open: onClickOpen,
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ import Dropdown, { type DropdownOption } from "./components/Dropdown";
13
13
  import ToggleInput from "./components/ToggleInput";
14
14
  import Form from "./components/Form";
15
15
  import BetterHtmlProvider, { useBetterHtmlContext, useTheme, useLoader, useLoaderControls } from "./components/BetterHtmlProvider";
16
- import { usePageResize, useMediaQuery, useBooleanState, useDebounceState, useForm } from "./utils/hooks";
16
+ import { usePageResize, useMediaQuery, useBooleanState, useDebounceState, useForm, useUrlQuery } from "./utils/hooks";
17
17
  import { type OmitProps, type ExcludeOptions, type PickValue, type PartialRecord, type DeepPartialRecord, type PickAllRequired } from "./types/app";
18
18
  import { type AppConfig, type BetterHtmlConfig } from "./types/config";
19
19
  import { type AssetName, type AssetsConfig } from "./types/asset";
@@ -21,4 +21,5 @@ import { type IconName, type IconsConfig } from "./types/icon";
21
21
  import { type LoaderName, type LoaderConfig } from "./types/loader";
22
22
  import { type Color, type ColorName, type ColorTheme, type Colors, type Styles, type Theme, type ThemeConfig } from "./types/theme";
23
23
  import { isMobileDevice } from "./constants";
24
- export { BetterHtmlProvider, Div, Text, Loader, Icon, Image, Button, Divider, Modal, ModalRef, PageHolder, Chip, InputField, Dropdown, DropdownOption, ToggleInput, Form, useBetterHtmlContext, useTheme, useLoader, useLoaderControls, usePageResize, useMediaQuery, useBooleanState, useDebounceState, useForm, OmitProps, ExcludeOptions, PickValue, PartialRecord, DeepPartialRecord, PickAllRequired, AppConfig, BetterHtmlConfig, AssetName, AssetsConfig, IconName, IconsConfig, LoaderName, LoaderConfig, Color, ColorName, ColorTheme, Colors, Styles, Theme, ThemeConfig, isMobileDevice, };
24
+ export * from "./plugins";
25
+ export { BetterHtmlProvider, Div, Text, Loader, Icon, Image, Button, Divider, Modal, ModalRef, PageHolder, Chip, InputField, Dropdown, DropdownOption, ToggleInput, Form, useBetterHtmlContext, useTheme, useLoader, useLoaderControls, usePageResize, useMediaQuery, useBooleanState, useDebounceState, useForm, useUrlQuery, OmitProps, ExcludeOptions, PickValue, PartialRecord, DeepPartialRecord, PickAllRequired, AppConfig, BetterHtmlConfig, AssetName, AssetsConfig, IconName, IconsConfig, LoaderName, LoaderConfig, Color, ColorName, ColorTheme, Colors, Styles, Theme, ThemeConfig, isMobileDevice, };
package/dist/index.js CHANGED
@@ -32,11 +32,14 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
35
38
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
39
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
40
  };
38
41
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.isMobileDevice = exports.useForm = exports.useDebounceState = exports.useBooleanState = exports.useMediaQuery = exports.usePageResize = exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = exports.Form = exports.ToggleInput = exports.Dropdown = exports.InputField = exports.Chip = exports.PageHolder = exports.Modal = exports.Divider = exports.Button = exports.Image = exports.Icon = exports.Loader = exports.Text = exports.Div = exports.BetterHtmlProvider = void 0;
42
+ exports.isMobileDevice = exports.useUrlQuery = exports.useForm = exports.useDebounceState = exports.useBooleanState = exports.useMediaQuery = exports.usePageResize = exports.useLoaderControls = exports.useLoader = exports.useTheme = exports.useBetterHtmlContext = exports.Form = exports.ToggleInput = exports.Dropdown = exports.InputField = exports.Chip = exports.PageHolder = exports.Modal = exports.Divider = exports.Button = exports.Image = exports.Icon = exports.Loader = exports.Text = exports.Div = exports.BetterHtmlProvider = void 0;
40
43
  const Div_1 = __importDefault(require("./components/Div"));
41
44
  exports.Div = Div_1.default;
42
45
  const Text_1 = __importDefault(require("./components/Text"));
@@ -77,5 +80,7 @@ Object.defineProperty(exports, "useMediaQuery", { enumerable: true, get: functio
77
80
  Object.defineProperty(exports, "useBooleanState", { enumerable: true, get: function () { return hooks_1.useBooleanState; } });
78
81
  Object.defineProperty(exports, "useDebounceState", { enumerable: true, get: function () { return hooks_1.useDebounceState; } });
79
82
  Object.defineProperty(exports, "useForm", { enumerable: true, get: function () { return hooks_1.useForm; } });
83
+ Object.defineProperty(exports, "useUrlQuery", { enumerable: true, get: function () { return hooks_1.useUrlQuery; } });
80
84
  const constants_1 = require("./constants");
81
85
  Object.defineProperty(exports, "isMobileDevice", { enumerable: true, get: function () { return constants_1.isMobileDevice; } });
86
+ __exportStar(require("./plugins"), exports);
@@ -0,0 +1 @@
1
+ export * from "./react-router-dom";
@@ -0,0 +1,17 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./react-router-dom"), exports);
@@ -0,0 +1,2 @@
1
+ import { BetterHtmlPlugin } from "../types/plugin";
2
+ export declare const reactRouterDomPlugin: BetterHtmlPlugin;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reactRouterDomPlugin = void 0;
4
+ const react_router_dom_1 = require("react-router-dom");
5
+ exports.reactRouterDomPlugin = {
6
+ name: "react-router-dom",
7
+ components: {
8
+ Link: react_router_dom_1.Link,
9
+ NavLink: react_router_dom_1.NavLink,
10
+ },
11
+ initialize: () => {
12
+ console.log("react-router-dom plugin initialized");
13
+ },
14
+ };
@@ -1,3 +1,4 @@
1
+ import { BetterHtmlPlugin } from "./plugin";
1
2
  export type ComponentStyle = React.CSSProperties;
2
3
  export type ComponentHoverStyle = {
3
4
  [CSSProperty in keyof ComponentStyle as `${CSSProperty & string}Hover`]: ComponentStyle[CSSProperty];
@@ -7,3 +8,6 @@ export type ComponentPaddingProps = Pick<ComponentStyle, "padding" | "paddingTop
7
8
  export type ComponentPropWithRef<ComponentRef, ComponentProps> = ComponentProps & {
8
9
  ref?: React.Ref<ComponentRef>;
9
10
  };
11
+ export type ComponentPropWithPlugin<ComponentProps> = ComponentProps & {
12
+ plugin: BetterHtmlPlugin;
13
+ };
@@ -0,0 +1,7 @@
1
+ import { ComponentType } from "react";
2
+ export type PluginName = "react-router-dom";
3
+ export type BetterHtmlPlugin = {
4
+ name: PluginName;
5
+ components?: Record<string, ComponentType<any>>;
6
+ initialize?: () => void;
7
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -57,3 +57,8 @@ export declare function useForm<FormFields extends Record<string, string | numbe
57
57
  onSubmit: (event: React.FormEvent<HTMLFormElement>) => Promise<void>;
58
58
  reset: () => void;
59
59
  };
60
+ export declare function useUrlQuery(): {
61
+ setQuery: (query: Record<string, string>, keepHistory?: boolean) => void;
62
+ getQuery: (name: string) => string | null;
63
+ removeQuery: (name: string, keepHistory?: boolean) => void;
64
+ };
@@ -9,8 +9,11 @@ exports.useMediaQuery = useMediaQuery;
9
9
  exports.useBooleanState = useBooleanState;
10
10
  exports.useDebounceState = useDebounceState;
11
11
  exports.useForm = useForm;
12
+ exports.useUrlQuery = useUrlQuery;
12
13
  const react_1 = require("react");
14
+ const react_router_dom_1 = require("react-router-dom");
13
15
  const css_1 = require("../constants/css");
16
+ const BetterHtmlProvider_1 = require("../components/BetterHtmlProvider");
14
17
  const cssPropsToExclude = [
15
18
  "position",
16
19
  "top",
@@ -235,3 +238,39 @@ function useForm({ defaultValues, onSubmit, validate, }) {
235
238
  reset,
236
239
  };
237
240
  }
241
+ function useUrlQuery() {
242
+ const reactRouterDomPlugin = (0, BetterHtmlProvider_1.usePlugin)("react-router-dom");
243
+ if (!reactRouterDomPlugin) {
244
+ throw new Error("`useUrlQuery` hook requires the `react-router-dom` plugin to be added to the `plugins` prop in `<BetterHtmlProvider>`.");
245
+ }
246
+ const navigate = (0, react_router_dom_1.useNavigate)();
247
+ const [searchParams] = (0, react_router_dom_1.useSearchParams)();
248
+ const setQuery = (0, react_1.useCallback)((query, keepHistory = true) => {
249
+ const currentSearchParams = {};
250
+ searchParams.forEach((value, key) => {
251
+ currentSearchParams[key] = value;
252
+ });
253
+ navigate({
254
+ search: (0, react_router_dom_1.createSearchParams)({
255
+ ...currentSearchParams,
256
+ ...query,
257
+ }).toString(),
258
+ }, {
259
+ replace: !keepHistory,
260
+ });
261
+ }, [navigate, searchParams]);
262
+ const getQuery = (0, react_1.useCallback)((name) => searchParams.get(name), [searchParams]);
263
+ const removeQuery = (0, react_1.useCallback)((name, keepHistory = true) => {
264
+ searchParams.delete(name);
265
+ navigate({
266
+ search: searchParams.toString(),
267
+ }, {
268
+ replace: !keepHistory,
269
+ });
270
+ }, [navigate, searchParams]);
271
+ return {
272
+ setQuery,
273
+ getQuery,
274
+ removeQuery,
275
+ };
276
+ }
@@ -0,0 +1,4 @@
1
+ import { ComponentType } from "react";
2
+ import { PluginName } from "../types/plugin";
3
+ import { ComponentPropWithPlugin } from "../types/components";
4
+ export declare function withPlugin<ComponentProps extends object>(pluginName: PluginName, WrappedComponent: ComponentType<ComponentPropWithPlugin<ComponentProps>>): ComponentType<ComponentProps>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withPlugin = withPlugin;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const BetterHtmlProvider_1 = require("../components/BetterHtmlProvider");
6
+ function withPlugin(pluginName, WrappedComponent) {
7
+ const WithPlugin = (props) => {
8
+ const plugin = (0, BetterHtmlProvider_1.usePlugin)(pluginName);
9
+ if (!plugin)
10
+ throw new Error(`\`${pluginName}\` must be added to the \`plugins\` prop in \`<BetterHtmlProvider>\` for the component to work.`);
11
+ return (0, jsx_runtime_1.jsx)(WrappedComponent, { ...props, plugin: plugin });
12
+ };
13
+ WithPlugin.displayName = `WithPlugin(${pluginName})`;
14
+ return WithPlugin;
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-better-html",
3
- "version": "1.1.20",
3
+ "version": "1.1.21",
4
4
  "description": "A component library for react that is as close to plane html as possible",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -42,6 +42,7 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "react": "^19.0.0",
45
+ "react-router-dom": "^7.4.1",
45
46
  "styled-components": "^6.1.15"
46
47
  }
47
48
  }