adnbn-ui 0.0.1 → 0.0.2

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 (145) hide show
  1. package/.prettierignore +3 -0
  2. package/.prettierrc +28 -0
  3. package/.storybook/main.ts +22 -0
  4. package/.storybook/preview.tsx +100 -0
  5. package/.storybook/styles/custom.scss +59 -0
  6. package/.storybook/styles/preview.css +58 -0
  7. package/.storybook/vitest.setup.ts +9 -0
  8. package/eslint.config.js +39 -0
  9. package/package.json +77 -2
  10. package/src/components/Avatar/Avatar.stories.tsx +118 -0
  11. package/src/components/Avatar/Avatar.tsx +65 -0
  12. package/src/components/Avatar/avatar.module.scss +77 -0
  13. package/src/components/Avatar/index.ts +2 -0
  14. package/src/components/BaseButton/BaseButton.tsx +36 -0
  15. package/src/components/BaseButton/base-button.module.scss +24 -0
  16. package/src/components/BaseButton/index.ts +2 -0
  17. package/src/components/Button/Button.stories.tsx +148 -0
  18. package/src/components/Button/Button.tsx +73 -0
  19. package/src/components/Button/button.module.scss +140 -0
  20. package/src/components/Button/index.ts +2 -0
  21. package/src/components/Checkbox/Checkbox.stories.tsx +180 -0
  22. package/src/components/Checkbox/Checkbox.tsx +71 -0
  23. package/src/components/Checkbox/checkbox.module.scss +82 -0
  24. package/src/components/Checkbox/index.ts +2 -0
  25. package/src/components/Dialog/Dialog.tsx +125 -0
  26. package/src/components/Dialog/dialog.module.scss +55 -0
  27. package/src/components/Dialog/index.ts +2 -0
  28. package/src/components/Drawer/Drawer.stories.tsx +89 -0
  29. package/src/components/Drawer/Drawer.tsx +57 -0
  30. package/src/components/Drawer/drawer.module.scss +170 -0
  31. package/src/components/Drawer/index.ts +2 -0
  32. package/src/components/Footer/Footer.stories.tsx +118 -0
  33. package/src/components/Footer/Footer.tsx +58 -0
  34. package/src/components/Footer/footer.module.scss +44 -0
  35. package/src/components/Footer/index.ts +2 -0
  36. package/src/components/Header/Header.stories.tsx +49 -0
  37. package/src/components/Header/Header.tsx +73 -0
  38. package/src/components/Header/header.module.scss +56 -0
  39. package/src/components/Header/index.ts +2 -0
  40. package/src/components/Highlight/Highlight.stories.tsx +83 -0
  41. package/src/components/Highlight/Highlight.tsx +40 -0
  42. package/src/components/Highlight/highlight.module.scss +47 -0
  43. package/src/components/Highlight/index.ts +2 -0
  44. package/src/components/Icon/Icon.tsx +46 -0
  45. package/src/components/Icon/icon.module.scss +17 -0
  46. package/src/components/Icon/index.ts +2 -0
  47. package/src/components/IconButton/IconButton.stories.tsx +179 -0
  48. package/src/components/IconButton/IconButton.tsx +65 -0
  49. package/src/components/IconButton/icon-button.module.scss +86 -0
  50. package/src/components/IconButton/index.ts +2 -0
  51. package/src/components/Layout/Layout.stories.tsx +88 -0
  52. package/src/components/Layout/Provider.tsx +47 -0
  53. package/src/components/Layout/context.ts +24 -0
  54. package/src/components/Layout/index.ts +2 -0
  55. package/src/components/Layout/layout.module.scss +17 -0
  56. package/src/components/List/List.stories.tsx +81 -0
  57. package/src/components/List/List.tsx +24 -0
  58. package/src/components/List/index.ts +2 -0
  59. package/src/components/List/list.module.scss +8 -0
  60. package/src/components/ListItem/ListItem.tsx +75 -0
  61. package/src/components/ListItem/index.ts +2 -0
  62. package/src/components/ListItem/list-item.module.scss +36 -0
  63. package/src/components/Modal/Modal.stories.tsx +95 -0
  64. package/src/components/Modal/Modal.tsx +94 -0
  65. package/src/components/Modal/index.ts +2 -0
  66. package/src/components/Modal/modal.module.scss +97 -0
  67. package/src/components/Odometer/Odometer.stories.tsx +66 -0
  68. package/src/components/Odometer/Odometer.tsx +45 -0
  69. package/src/components/Odometer/hooks/useOdometer.tsx +24 -0
  70. package/src/components/Odometer/index.ts +3 -0
  71. package/src/components/Odometer/odometer.module.scss +81 -0
  72. package/src/components/Odometer/odometr.d.ts +9 -0
  73. package/src/components/ScrollArea/ScrollArea.stories.tsx +58 -0
  74. package/src/components/ScrollArea/ScrollArea.tsx +63 -0
  75. package/src/components/ScrollArea/index.ts +2 -0
  76. package/src/components/ScrollArea/scroll-area.module.scss +54 -0
  77. package/src/components/SvgSprite/SvgSprite.tsx +21 -0
  78. package/src/components/SvgSprite/index.ts +2 -0
  79. package/src/components/Switch/Switch.stories.tsx +25 -0
  80. package/src/components/Switch/Switch.tsx +23 -0
  81. package/src/components/Switch/index.ts +2 -0
  82. package/src/components/Switch/switch.module.scss +65 -0
  83. package/src/components/Tag/Tag.stories.tsx +157 -0
  84. package/src/components/Tag/Tag.tsx +71 -0
  85. package/src/components/Tag/index.ts +2 -0
  86. package/src/components/Tag/tag.module.scss +118 -0
  87. package/src/components/TextArea/TextArea.stories.tsx +145 -0
  88. package/src/components/TextArea/TextArea.tsx +143 -0
  89. package/src/components/TextArea/index.ts +2 -0
  90. package/src/components/TextArea/text-area.module.scss +88 -0
  91. package/src/components/TextField/TextField.stories.tsx +177 -0
  92. package/src/components/TextField/TextField.tsx +162 -0
  93. package/src/components/TextField/index.ts +2 -0
  94. package/src/components/TextField/text-field.module.scss +129 -0
  95. package/src/components/Toast/Toast.stories.tsx +209 -0
  96. package/src/components/Toast/Toast.tsx +142 -0
  97. package/src/components/Toast/index.ts +2 -0
  98. package/src/components/Toast/toast.module.scss +267 -0
  99. package/src/components/Tooltip/Tooltip.stories.tsx +80 -0
  100. package/src/components/Tooltip/Tooltip.tsx +79 -0
  101. package/src/components/Tooltip/index.ts +2 -0
  102. package/src/components/Tooltip/tooltip.module.scss +93 -0
  103. package/src/components/View/View.stories.tsx +47 -0
  104. package/src/components/View/View.tsx +68 -0
  105. package/src/components/View/index.ts +2 -0
  106. package/src/components/View/view.module.scss +38 -0
  107. package/src/components/ViewDrawer/ViewDrawer.stories.tsx +75 -0
  108. package/src/components/ViewDrawer/ViewDrawer.tsx +24 -0
  109. package/src/components/ViewDrawer/index.ts +2 -0
  110. package/src/components/ViewModal/ViewModal.stories.tsx +68 -0
  111. package/src/components/ViewModal/ViewModal.tsx +24 -0
  112. package/src/components/ViewModal/index.ts +2 -0
  113. package/src/components/index.ts +29 -0
  114. package/src/components/types.ts +65 -0
  115. package/src/config/default.ts +3 -0
  116. package/src/config/index.ts +26 -0
  117. package/src/declaration.d.ts +8 -0
  118. package/src/index.ts +3 -0
  119. package/src/plugin/builder/ConfigBuilder.ts +32 -0
  120. package/src/plugin/builder/StyleBuilder.ts +34 -0
  121. package/src/plugin/builder/virtual.config.ts +7 -0
  122. package/src/plugin/finder/ConfigFinder.ts +26 -0
  123. package/src/plugin/finder/Finder.ts +76 -0
  124. package/src/plugin/finder/StyleFinder.ts +23 -0
  125. package/src/plugin/index.ts +70 -0
  126. package/src/plugin/types.ts +8 -0
  127. package/src/providers/UIProvider.tsx +26 -0
  128. package/src/providers/icons/IconsProvider.tsx +34 -0
  129. package/src/providers/icons/context.ts +22 -0
  130. package/src/providers/icons/index.ts +3 -0
  131. package/src/providers/index.ts +3 -0
  132. package/src/providers/theme/ThemeProvider.tsx +39 -0
  133. package/src/providers/theme/context.ts +30 -0
  134. package/src/providers/theme/index.ts +2 -0
  135. package/src/providers/theme/styles/default.scss +95 -0
  136. package/src/providers/theme/styles/reset.css +111 -0
  137. package/src/styles/mixins.scss +23 -0
  138. package/src/types/theme.ts +4 -0
  139. package/src/utils/index.ts +2 -0
  140. package/src/utils/react.ts +21 -0
  141. package/src/utils/utils.ts +12 -0
  142. package/tsconfig.json +18 -0
  143. package/vite.config.ts +11 -0
  144. package/vitest.workspace.ts +19 -0
  145. package/components/Button/index.ts +0 -0
@@ -0,0 +1,75 @@
1
+ import {useState} from "react";
2
+ import {Meta} from "@storybook/react";
3
+
4
+ import {hideInTable} from "../../utils";
5
+
6
+ import {Button, DrawerSide} from "../index";
7
+
8
+ import ViewDrawerComponent, {ViewDrawerProps} from "./ViewDrawer";
9
+
10
+ const sides: DrawerSide[] = [DrawerSide.Left, DrawerSide.Top, DrawerSide.Bottom, DrawerSide.Right];
11
+
12
+ const meta: Meta<typeof ViewDrawerComponent> = {
13
+ title: "Components/ViewDrawer",
14
+ component: ViewDrawerComponent,
15
+ tags: ["autodocs"],
16
+ argTypes: {
17
+ side: {
18
+ options: sides,
19
+ control: {type: "select"},
20
+ },
21
+ title: {
22
+ type: "string",
23
+ },
24
+ subtitle: {
25
+ type: "string",
26
+ },
27
+ after: {
28
+ type: "string",
29
+ },
30
+ before: {
31
+ type: "string",
32
+ },
33
+ fullscreen: {
34
+ type: "boolean",
35
+ },
36
+ speed: {
37
+ type: "number",
38
+ },
39
+ children: hideInTable,
40
+ className: hideInTable,
41
+ wrapClassName: hideInTable,
42
+ titleClassName: hideInTable,
43
+ bodyClassName: hideInTable,
44
+ headerClassName: hideInTable,
45
+ beforeClassName: hideInTable,
46
+ afterClassName: hideInTable,
47
+ subtitleClassName: hideInTable,
48
+ childrenClassName: hideInTable,
49
+ },
50
+ };
51
+
52
+ export default meta;
53
+
54
+ export const ViewDrawer = (props: ViewDrawerProps) => {
55
+ const [open, setOpen] = useState(false);
56
+ return (
57
+ <div>
58
+ <Button onClick={() => setOpen(true)}>Open</Button>
59
+ <ViewDrawerComponent
60
+ open={open}
61
+ onOpenChange={setOpen}
62
+ title="Volume Up Plus"
63
+ side={DrawerSide.Right}
64
+ fullscreen={false}
65
+ subtitle="Adjust the current tab's volume with the slider. Switch to any audio tab in one click."
66
+ after="❤️"
67
+ {...props}
68
+ >
69
+ <Button style={{margin: "50px auto", maxWidth: "max-content"}} onClick={() => setOpen(false)}>
70
+ Close ViewDrawer
71
+ </Button>
72
+ </ViewDrawerComponent>
73
+ </div>
74
+ );
75
+ };
@@ -0,0 +1,24 @@
1
+ import React, {FC, memo} from "react";
2
+
3
+ import {splitProps} from "../../utils";
4
+ import {useComponentProps} from "../../providers";
5
+
6
+ import {Drawer, DrawerProps, drawerPropsKeys} from "../Drawer";
7
+ import {View, ViewProps, viewPropsKeys} from "../View";
8
+
9
+ export type ViewDrawerProps = Omit<DrawerProps, "title"> & ViewProps;
10
+
11
+ const ViewDrawer: FC<ViewDrawerProps> = props => {
12
+ const mergedProps = {...useComponentProps("viewDrawer"), ...props};
13
+
14
+ const drawerProps = splitProps<DrawerProps>(mergedProps, drawerPropsKeys);
15
+ const viewProps = splitProps<ViewProps>(mergedProps, viewPropsKeys);
16
+
17
+ return (
18
+ <Drawer {...drawerProps}>
19
+ <View {...viewProps} />
20
+ </Drawer>
21
+ );
22
+ };
23
+
24
+ export default memo(ViewDrawer);
@@ -0,0 +1,2 @@
1
+ export {default as ViewDrawer} from "./ViewDrawer";
2
+ export type {ViewDrawerProps} from "./ViewDrawer";
@@ -0,0 +1,68 @@
1
+ import {useState} from "react";
2
+ import {Meta} from "@storybook/react";
3
+
4
+ import {hideInTable} from "../../utils";
5
+
6
+ import {Button} from "../index";
7
+
8
+ import ViewModalComponent, {ViewModalProps} from "./ViewModal";
9
+
10
+ const meta: Meta<typeof ViewModalComponent> = {
11
+ title: "Components/ViewModal",
12
+ component: ViewModalComponent,
13
+ tags: ["autodocs"],
14
+ argTypes: {
15
+ title: {
16
+ type: "string",
17
+ },
18
+ subtitle: {
19
+ type: "string",
20
+ },
21
+ after: {
22
+ type: "string",
23
+ },
24
+ before: {
25
+ type: "string",
26
+ },
27
+ fullscreen: {
28
+ type: "boolean",
29
+ },
30
+ speed: {
31
+ type: "number",
32
+ },
33
+ children: hideInTable,
34
+ className: hideInTable,
35
+ wrapClassName: hideInTable,
36
+ titleClassName: hideInTable,
37
+ bodyClassName: hideInTable,
38
+ headerClassName: hideInTable,
39
+ beforeClassName: hideInTable,
40
+ afterClassName: hideInTable,
41
+ subtitleClassName: hideInTable,
42
+ childrenClassName: hideInTable,
43
+ },
44
+ };
45
+
46
+ export default meta;
47
+
48
+ export const ViewModal = (props: ViewModalProps) => {
49
+ const [open, setOpen] = useState(false);
50
+ return (
51
+ <div>
52
+ <Button onClick={() => setOpen(true)}>Open</Button>
53
+ <ViewModalComponent
54
+ open={open}
55
+ onOpenChange={setOpen}
56
+ title="Volume Up Plus"
57
+ fullscreen={false}
58
+ subtitle="Adjust the current tab's volume with the slider. Switch to any audio tab in one click."
59
+ after="❤️"
60
+ {...props}
61
+ >
62
+ <Button style={{margin: "50px auto", maxWidth: "max-content"}} onClick={() => setOpen(false)}>
63
+ Close ViewModal
64
+ </Button>
65
+ </ViewModalComponent>
66
+ </div>
67
+ );
68
+ };
@@ -0,0 +1,24 @@
1
+ import React, {FC, memo} from "react";
2
+
3
+ import {splitProps} from "../../utils";
4
+ import {useComponentProps} from "../../providers";
5
+
6
+ import {Modal, ModalProps, modalPropsKeys} from "../Modal";
7
+ import {View, ViewProps, viewPropsKeys} from "../View";
8
+
9
+ export type ViewModalProps = Omit<ModalProps, "title"> & ViewProps;
10
+
11
+ const ViewModal: FC<ViewModalProps> = props => {
12
+ const mergedProps = {...useComponentProps("viewModal"), ...props};
13
+
14
+ const modalProps = splitProps<ModalProps>(mergedProps, modalPropsKeys);
15
+ const viewProps = splitProps<ViewProps>(mergedProps, viewPropsKeys);
16
+
17
+ return (
18
+ <Modal {...modalProps}>
19
+ <View {...viewProps} />
20
+ </Modal>
21
+ );
22
+ };
23
+
24
+ export default memo(ViewModal);
@@ -0,0 +1,2 @@
1
+ export {default as ViewModal} from "./ViewModal";
2
+ export type {ViewModalProps} from "./ViewModal";
@@ -0,0 +1,29 @@
1
+ export * from "./Avatar";
2
+ export * from "./BaseButton";
3
+ export * from "./Button";
4
+ export * from "./Checkbox";
5
+ export * from "./Dialog";
6
+ export * from "./Drawer";
7
+ export * from "./Footer";
8
+ export * from "./Header";
9
+ export * from "./Highlight";
10
+ export * from "./Icon";
11
+ export * from "./IconButton";
12
+ export * from "./Layout";
13
+ export * from "./List";
14
+ export * from "./ListItem";
15
+ export * from "./Modal";
16
+ export * from "./Odometer";
17
+ export * from "./ScrollArea";
18
+ export * from "./SvgSprite";
19
+ export * from "./Switch";
20
+ export * from "./Tag";
21
+ export * from "./TextArea";
22
+ export * from "./TextField";
23
+ export * from "./Toast";
24
+ export * from "./Tooltip";
25
+ export * from "./View";
26
+ export * from "./ViewDrawer";
27
+ export * from "./ViewModal";
28
+
29
+ export type {ComponentsProps} from "./types";
@@ -0,0 +1,65 @@
1
+ import type {
2
+ AvatarProps,
3
+ ButtonProps,
4
+ CheckboxProps,
5
+ DialogProps,
6
+ DrawerProps,
7
+ FooterProps,
8
+ HeaderProps,
9
+ HighlightProps,
10
+ IconProps,
11
+ IconButtonProps,
12
+ ListProps,
13
+ ListItemProps,
14
+ ModalProps,
15
+ OdometerProps,
16
+ ScrollAreaProps,
17
+ SwitchProps,
18
+ TagProps,
19
+ TextAreaProps,
20
+ TextFieldProps,
21
+ ToastProps,
22
+ TooltipProps,
23
+ ViewProps,
24
+ ViewDrawerProps,
25
+ ViewModalProps,
26
+ } from "../components";
27
+
28
+ export interface ComponentsProps {
29
+ avatar?: Pick<AvatarProps, "size" | "radius" | "cursorPointer" | "delayMs">;
30
+ button?: Pick<ButtonProps, "variant" | "color" | "size" | "radius">;
31
+ checkbox?: Pick<CheckboxProps, "variant" | "size" | "radius" | "checkedIcon" | "indeterminateIcon">;
32
+ dialog?: DialogProps;
33
+ drawer?: DrawerProps;
34
+ footer?: FooterProps;
35
+ header?: Pick<HeaderProps, "alignCenter" | "before" | "after">;
36
+ highlight?: HighlightProps;
37
+ icon?: Omit<IconProps, "name">;
38
+ iconButton?: Pick<IconButtonProps, "variant" | "size" | "radius">;
39
+ list?: ListProps;
40
+ listItem?: ListItemProps;
41
+ modal?: ModalProps;
42
+ odometer?: Pick<OdometerProps, "auto" | "format" | "duration">;
43
+ scrollArea?: ScrollAreaProps;
44
+ switch?: SwitchProps;
45
+ tag?: Pick<TagProps, "variant" | "size" | "color" | "radius" | "clickable">;
46
+ textArea?: TextAreaProps;
47
+ textField?: TextFieldProps;
48
+ toast?: Pick<
49
+ ToastProps,
50
+ | "side"
51
+ | "duration"
52
+ | "swipeDirection"
53
+ | "swipeThreshold"
54
+ | "closeProps"
55
+ | "closeIcon"
56
+ | "fullWidth"
57
+ | "sticky"
58
+ | "radius"
59
+ | "color"
60
+ >;
61
+ tooltip?: Pick<TooltipProps, "side" | "align" | "delayDuration" | "arrowHeight" | "arrowWidth">;
62
+ view?: ViewProps;
63
+ viewDrawer?: ViewDrawerProps;
64
+ viewModal?: ViewModalProps;
65
+ }
@@ -0,0 +1,3 @@
1
+ import {Config} from "./index";
2
+
3
+ export default {} as Config;
@@ -0,0 +1,26 @@
1
+ import type {ComponentsProps} from "../components";
2
+ import type {Icons} from "../providers";
3
+
4
+ export {AvatarSize, AvatarRadius} from "../components/Avatar";
5
+ export {ButtonColor, ButtonSize, ButtonRadius, ButtonVariant} from "../components/Button";
6
+ export {CheckboxVariant, CheckboxRadius, CheckboxSize} from "../components/Checkbox";
7
+ export {DrawerSide} from "../components/Drawer";
8
+ export {HighlightColor} from "../components/Highlight";
9
+ export {IconButtonSize, IconButtonVariant, IconButtonRadius} from "../components/IconButton";
10
+ export {ModalRadius} from "../components/Modal";
11
+ export {TagVariant, TagColor, TagRadius, TagSize} from "../components/Tag";
12
+ export {TextAreaSize, TextAreaVariant} from "../components/TextArea";
13
+ export {TextFieldAccent, TextFieldSize, TextFieldVariant} from "../components/TextField";
14
+ export {ToastColor, ToastRadius, ToastSide} from "../components/Toast";
15
+
16
+ export type {ComponentsProps} from "../components";
17
+
18
+ export interface Config {
19
+ props: ComponentsProps;
20
+ icons: Icons;
21
+ }
22
+
23
+ export const defineConfig = (config: Partial<Config>): Config => {
24
+ const {props = {}, icons = {}} = config;
25
+ return {props, icons};
26
+ };
@@ -0,0 +1,8 @@
1
+ declare module "*.module.css" {
2
+ const classes: CSSModuleClasses;
3
+ export default classes;
4
+ }
5
+ declare module "*.module.scss" {
6
+ const classes: CSSModuleClasses;
7
+ export default classes;
8
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./components";
2
+ export * from "./providers";
3
+ export {Theme} from "./types/theme";
@@ -0,0 +1,32 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import Finder from "../finder/Finder";
4
+
5
+ import type {BuilderContract} from "../types";
6
+
7
+ export default class ConfigBuilder implements BuilderContract {
8
+ protected template: string;
9
+
10
+ public constructor(protected finder: Finder) {
11
+ this.template = fs.readFileSync(path.resolve(__dirname, "virtual.config.ts"), "utf8");
12
+ }
13
+
14
+ public build(): string {
15
+ const files = this.finder.getFiles();
16
+
17
+ const imports = files.map(file => {
18
+ return file.name ? `import ${file.name} from "${file.import}"` : `import "${file.import}"`;
19
+ });
20
+
21
+ // Elements must be reversed for correct merging of configs by priority
22
+ const names = files
23
+ .map(file => file.name)
24
+ .filter(Boolean)
25
+ .reverse();
26
+
27
+ // prettier-ignore
28
+ return this.template
29
+ .replace("//configs imports", imports.join("\n"))
30
+ .replace("{}", names.join(", "));
31
+ }
32
+ }
@@ -0,0 +1,34 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import Finder from "../finder/Finder";
4
+
5
+ import type {BuilderContract} from "../types";
6
+
7
+ export default class StyleBuilder implements BuilderContract {
8
+ public constructor(protected finder: Finder) {}
9
+
10
+ public build(): string {
11
+ const files = this.finder.getFiles();
12
+
13
+ const usesLines = new Set<string>();
14
+ const stylesLines: string[] = [];
15
+
16
+ const lines = files
17
+ .map(file => file.import)
18
+ .reduce((lines, filePath) => {
19
+ return lines + "\n" + fs.readFileSync(path.resolve(filePath), "utf8");
20
+ }, "")
21
+ .split("\n");
22
+
23
+ for (const line of lines) {
24
+ const trimmed = line.trim();
25
+ if (trimmed.startsWith("@use")) {
26
+ usesLines.add(trimmed);
27
+ } else {
28
+ stylesLines.push(line);
29
+ }
30
+ }
31
+
32
+ return [...usesLines].join("\n") + "\n" + stylesLines.join("\n");
33
+ }
34
+ }
@@ -0,0 +1,7 @@
1
+ import {merge} from "ts-deepmerge";
2
+
3
+ //configs imports;
4
+
5
+ import "adnbn-ui-style.scss";
6
+
7
+ export default merge({});
@@ -0,0 +1,26 @@
1
+ import path from "path";
2
+ import Finder from "./Finder";
3
+
4
+ import type {ReadonlyConfig} from "adnbn";
5
+ import type {FileImportInfo} from "../types";
6
+
7
+ export default class ConfigFinder extends Finder {
8
+ protected getAllowedExtensions(): string[] {
9
+ return ["tsx", "ts"];
10
+ }
11
+
12
+ constructor(fileName: string, config: ReadonlyConfig) {
13
+ super(fileName, config);
14
+ }
15
+
16
+ protected getFile(dirPath: string): FileImportInfo | undefined {
17
+ const filePath = this.resolveFileWithExtensions(dirPath, this.fileName);
18
+
19
+ if (!filePath) return;
20
+
21
+ return {
22
+ name: dirPath.replaceAll(path.sep, "").replaceAll("-", ""),
23
+ import: this.toImportPath(filePath),
24
+ };
25
+ }
26
+ }
@@ -0,0 +1,76 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ import type {ReadonlyConfig} from "adnbn";
5
+
6
+ import type {FileImportInfo} from "../types";
7
+
8
+ export interface FinderOptions {
9
+ searchDirs: string[];
10
+ fileName: string;
11
+ canMerge: boolean;
12
+ }
13
+
14
+ export default abstract class Finder {
15
+ protected abstract getAllowedExtensions(): string[];
16
+
17
+ protected abstract getFile(dirPath: string): FileImportInfo | undefined;
18
+
19
+ protected searchDirs: string[] = [];
20
+ protected canMerge: boolean = true;
21
+
22
+ protected constructor(
23
+ protected readonly fileName: string,
24
+ protected readonly config: ReadonlyConfig
25
+ ) {}
26
+
27
+ public setCanMerge(canMerge: boolean): this {
28
+ this.canMerge = canMerge;
29
+ return this;
30
+ }
31
+
32
+ public setSearchDirs(searchDirs: string[]): this {
33
+ this.searchDirs = searchDirs;
34
+ return this;
35
+ }
36
+
37
+ public getFiles(): FileImportInfo[] {
38
+ const files: FileImportInfo[] = [];
39
+
40
+ let isFound = false;
41
+
42
+ this.searchDirs.forEach(dirPath => {
43
+ const file = this.getFile(dirPath);
44
+
45
+ if (file && (this.canMerge || !isFound)) {
46
+ files.push(file);
47
+ isFound = true;
48
+ }
49
+ });
50
+
51
+ return files;
52
+ }
53
+
54
+ protected resolveFileWithExtensions(basePath: string, fileName: string): string | undefined {
55
+ const extname = path.extname(fileName);
56
+
57
+ const baseName = this.getAllowedExtensions().includes(extname.slice(1))
58
+ ? path.basename(fileName, extname)
59
+ : fileName;
60
+
61
+ for (const ext of this.getAllowedExtensions()) {
62
+ const fullPath = path.resolve(basePath, `${baseName}.${ext}`);
63
+ if (fs.existsSync(fullPath)) {
64
+ return fullPath;
65
+ }
66
+ }
67
+
68
+ return undefined;
69
+ }
70
+
71
+ protected toImportPath(fullPath: string, withExt: boolean = false): string {
72
+ const importPath = path.relative(this.config.inputDir, fullPath).split(path.sep).join("/");
73
+
74
+ return withExt ? importPath : importPath.replace(path.extname(importPath), "");
75
+ }
76
+ }
@@ -0,0 +1,23 @@
1
+ import type {ReadonlyConfig} from "adnbn";
2
+
3
+ import Finder from "./Finder";
4
+
5
+ import type {FileImportInfo} from "../types";
6
+
7
+ export default class StyleFinder extends Finder {
8
+ protected getAllowedExtensions(): string[] {
9
+ return ["scss", "css"];
10
+ }
11
+
12
+ constructor(fileName: string, config: ReadonlyConfig) {
13
+ super(fileName, config);
14
+ }
15
+
16
+ protected getFile(dirPath: string): FileImportInfo | undefined {
17
+ const filePath = this.resolveFileWithExtensions(dirPath, this.fileName);
18
+
19
+ if (!filePath) return;
20
+
21
+ return {name: "", import: this.toImportPath(filePath, true)};
22
+ }
23
+ }
@@ -0,0 +1,70 @@
1
+ import path from "path";
2
+ import {definePlugin} from "adnbn";
3
+ import {Configuration as Rspack} from "@rspack/core";
4
+ import {RspackVirtualModulePlugin} from "rspack-plugin-virtual-module";
5
+
6
+ import StyleBuilder from "./builder/StyleBuilder";
7
+ import ConfigBuilder from "./builder/ConfigBuilder";
8
+
9
+ import Finder from "./finder/Finder";
10
+ import StyleFinder from "./finder/StyleFinder";
11
+ import ConfigFinder from "./finder/ConfigFinder";
12
+
13
+ import type {BuilderContract} from "./types";
14
+
15
+ export interface PluginOptions {
16
+ themeDir?: string;
17
+ configFileName?: string;
18
+ styleFileName?: string;
19
+ mergeConfig?: boolean;
20
+ mergeStyles?: boolean;
21
+ }
22
+
23
+ export default definePlugin((options: PluginOptions = {}) => {
24
+ const {
25
+ themeDir = ".",
26
+ configFileName = "ui.config",
27
+ styleFileName = "ui.style",
28
+ mergeConfig = true,
29
+ mergeStyles = true,
30
+ } = options;
31
+
32
+ let configFinder: Finder;
33
+ let styleFinder: Finder;
34
+
35
+ let configBuilder: BuilderContract;
36
+ let styleBuilder: BuilderContract;
37
+
38
+ return {
39
+ name: "adnbn-ui",
40
+ startup: ({config}) => {
41
+ const {srcDir, appsDir, sharedDir, app, appSrcDir} = config;
42
+ const normalizeThemeDir = path.normalize(themeDir).split(path.sep);
43
+
44
+ // Elements should be arranged in descending order of priority
45
+ const searchDirs = [
46
+ path.join(srcDir, appsDir, app, appSrcDir, ...normalizeThemeDir),
47
+ path.join(srcDir, sharedDir, ...normalizeThemeDir),
48
+ ];
49
+
50
+ configFinder = new ConfigFinder(configFileName, config).setCanMerge(mergeConfig).setSearchDirs(searchDirs);
51
+ styleFinder = new StyleFinder(styleFileName, config).setCanMerge(mergeStyles).setSearchDirs(searchDirs);
52
+
53
+ configBuilder = new ConfigBuilder(configFinder);
54
+ styleBuilder = new StyleBuilder(styleFinder);
55
+ },
56
+ bundler: () => {
57
+ return {
58
+ plugins: [
59
+ new RspackVirtualModulePlugin(
60
+ {
61
+ "adnbn-ui-config": configBuilder.build(),
62
+ "adnbn-ui-style.scss": styleBuilder.build(),
63
+ },
64
+ "adnbn-ui-virtual"
65
+ ),
66
+ ],
67
+ } satisfies Rspack;
68
+ },
69
+ };
70
+ });
@@ -0,0 +1,8 @@
1
+ export interface FileImportInfo {
2
+ name: string;
3
+ import: string;
4
+ }
5
+
6
+ export interface BuilderContract {
7
+ build(): string;
8
+ }
@@ -0,0 +1,26 @@
1
+ import React, {PropsWithChildren, useMemo} from "react";
2
+ import {merge} from "ts-deepmerge";
3
+
4
+ import ThemeProvider from "./theme/ThemeProvider";
5
+ import {IconsProvider, Icons} from "./icons";
6
+ import {ComponentsProps} from "../components";
7
+
8
+ import config from "adnbn-ui-config";
9
+
10
+ import type {Config} from "../config";
11
+
12
+ const UIProvider = ({children, props = {}, icons = {}}: PropsWithChildren<Partial<Config>>) => {
13
+ const componentsProps: ComponentsProps = useMemo(() => merge(config.props || {}, props), [props]);
14
+
15
+ const svgIcons: Icons = useMemo(() => merge(config.icons || {}, icons), [icons]);
16
+
17
+ return (
18
+ <ThemeProvider {...componentsProps}>
19
+ <IconsProvider icons={svgIcons}>{children}</IconsProvider>
20
+ </ThemeProvider>
21
+ );
22
+ };
23
+
24
+ UIProvider.displayName = "UIProvider";
25
+
26
+ export default UIProvider;