@vaneui/ui 0.0.1

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.
@@ -0,0 +1,97 @@
1
+ import React from 'react';
2
+ import { componentBuilder } from "./utils";
3
+ import { TypographyComponentProps } from "./props";
4
+
5
+ export const PageTitle: React.FC<TypographyComponentProps> = (props) =>
6
+ componentBuilder(props, "h1")
7
+ .withSizes({
8
+ xs: "text-3xl",
9
+ sm: "text-4xl",
10
+ md: "text-5xl",
11
+ lg: "text-6xl",
12
+ xl: "text-7xl",
13
+ })
14
+ .withTypography({
15
+ fontWeight: { semibold: true }
16
+ })
17
+ .build();
18
+
19
+ export const SectionTitle: React.FC<TypographyComponentProps> = (props) =>
20
+ componentBuilder(props, "h2")
21
+ .withSizes({
22
+ xs: "text-2xl",
23
+ sm: "text-3xl",
24
+ md: "text-4xl",
25
+ lg: "text-5xl",
26
+ xl: "text-6xl",
27
+ })
28
+ .withTypography({
29
+ fontWeight: { semibold: true }
30
+ })
31
+ .build();
32
+
33
+ export const Title: React.FC<TypographyComponentProps> = (props) =>
34
+ componentBuilder(props, "h3")
35
+ .withSizes({
36
+ xs: "text-lg",
37
+ sm: "text-xl",
38
+ md: "text-2xl",
39
+ lg: "text-3xl",
40
+ xl: "text-4xl",
41
+ })
42
+ .withTypography({
43
+ fontWeight: { semibold: true }
44
+ })
45
+ .build();
46
+
47
+ export const Text: React.FC<TypographyComponentProps> = (props) =>
48
+ componentBuilder(props, "p", "p-0 m-0")
49
+ .withSizes({
50
+ xs: "text-xs",
51
+ sm: "text-sm",
52
+ md: "text-md",
53
+ lg: "text-lg",
54
+ xl: "text-xl",
55
+ })
56
+ .withTypography({
57
+ textAppearance: { secondary: true }
58
+ })
59
+ .build();
60
+
61
+ export const Link: React.FC<TypographyComponentProps> = (props) =>
62
+ componentBuilder(props, "a", "hover:underline")
63
+ .withSizes({
64
+ xs: "text-xs",
65
+ sm: "text-sm",
66
+ md: "text-md",
67
+ lg: "text-lg",
68
+ xl: "text-xl",
69
+ })
70
+ .withTypography({
71
+ textAppearance: { link: true }
72
+ })
73
+ .build();
74
+
75
+ export const ListItem: React.FC<TypographyComponentProps> = (props) =>
76
+ componentBuilder(props, "li")
77
+ .withSizes({
78
+ xs: "text-xs",
79
+ sm: "text-sm",
80
+ md: "text-md",
81
+ lg: "text-lg",
82
+ xl: "text-xl",
83
+ })
84
+ .withTypography({})
85
+ .build();
86
+
87
+ export const List: React.FC<TypographyComponentProps> = (props) =>
88
+ componentBuilder(props, "ul", "list-disc list-inside")
89
+ .withSizes({
90
+ xs: "text-xs",
91
+ sm: "text-sm",
92
+ md: "text-md",
93
+ lg: "text-lg",
94
+ xl: "text-xl",
95
+ })
96
+ .withTypography({})
97
+ .build();
@@ -0,0 +1,124 @@
1
+ import { twMerge } from "tailwind-merge";
2
+ import { BaseComponentProps, BreakpointProps, CenteredProps, CommonAppearanceProps, FontFamilyProps, FontStyleProps, FontWeightProps, GapProps, HideProps, PositionProps, ReverseProps, ColProps, RowProps, TextAppearanceProps, TextDecorationProps, TextTransformProps, SizeProps } from "./props";
3
+ import { fontFamilyClasses, fontStyleClasses, fontWeightClasses, textAppearanceClasses, textDecorationClasses, textTransformClasses } from "./commonValues";
4
+ import { CommonAppearanceSettings, FontFamilySettings, FontStyleSettings, FontWeightSettings, TextAppearanceSettings, TextDecorationSettings, TextTransformSettings, TypographySettings } from "./settings";
5
+
6
+ function getBooleanClass<T extends Record<string, boolean | undefined>>(
7
+ props: T,
8
+ classes?: Record<keyof T, string>,
9
+ fallbackKey?: keyof T
10
+ ): string {
11
+ if (!classes) return "";
12
+ for (const key in props) {
13
+ if (Object.prototype.hasOwnProperty.call(props, key) && props[key]) {
14
+ return classes[key] ?? "";
15
+ }
16
+ }
17
+ return fallbackKey ? classes[fallbackKey] ?? "" : "";
18
+ }
19
+
20
+ export function componentBuilder(
21
+ baseProps: BaseComponentProps,
22
+ defaultTag: string,
23
+ baseClasses?: string
24
+ ) {
25
+ const extraClasses: string[] = [];
26
+ const { className, children, tag, ...other } = baseProps;
27
+ const otherProps: (typeof other) & Partial<ReverseProps & CenteredProps & GapProps & RowProps & ColProps> = { ...other };
28
+ const propsToRemove: string[] = []
29
+
30
+ const registerKeys = (keys: string[]) => {
31
+ keys.forEach((key) => propsToRemove.push(key));
32
+ };
33
+
34
+ const withBooleanProps = <T extends Record<string, string>>(
35
+ propMap: Record<keyof T, string>,
36
+ fallbackKey?: keyof T,
37
+ settings?: { [key: string]: boolean }
38
+ ) => {
39
+ // Build a subset of props from otherProps for the keys in the map.
40
+ const propsSubset: Partial<Record<keyof T, boolean>> = {} as Partial<Record<keyof T, boolean>>;
41
+ const keys = Object.keys(propMap) as (keyof T)[];
42
+ keys.forEach((key) => {
43
+ if (key in otherProps) {
44
+ propsSubset[key] = otherProps[key as keyof typeof otherProps];
45
+ }
46
+ });
47
+
48
+ if (settings) {
49
+ const settingsClass = getBooleanClass(settings || {}, propMap);
50
+ extraClasses.push(settingsClass);
51
+ }
52
+
53
+ // Compute the class.
54
+ const newClass = getBooleanClass(propsSubset, propMap, fallbackKey);
55
+ extraClasses.push(newClass);
56
+
57
+ // Register all keys found in the map.
58
+ registerKeys(keys as string[]);
59
+ return builder;
60
+ };
61
+
62
+ function finalize(): React.ReactElement {
63
+ const Tag = tag || defaultTag;
64
+ const merged = twMerge(baseClasses, ...extraClasses, className);
65
+
66
+ propsToRemove.forEach(key => delete otherProps[key as keyof typeof otherProps])
67
+
68
+ return (
69
+ <Tag className={merged} {...otherProps}>
70
+ {children}
71
+ </Tag>
72
+ );
73
+ }
74
+
75
+ const builder = {
76
+ withBooleanProps,
77
+
78
+ withSizes: (sizeMap: Record<keyof SizeProps, string>) => withBooleanProps(sizeMap, "md"),
79
+ withBreakpoints: (breakpointMap: Record<keyof BreakpointProps, string>) => withBooleanProps(breakpointMap),
80
+ withReverse: (reverseMap: Record<keyof ReverseProps, string>) => withBooleanProps(reverseMap),
81
+ withCentered: (centeredMap: Record<keyof CenteredProps, string>) => withBooleanProps(centeredMap),
82
+ withHide: (hideMap: Record<keyof HideProps, string>) => withBooleanProps(hideMap),
83
+ withPosition: (positionMap: Record<keyof PositionProps, string>) => withBooleanProps(positionMap),
84
+ withFontWeight: (fontWeight: Record<keyof FontWeightProps, string>, settings: FontWeightSettings) => withBooleanProps(fontWeight, undefined, settings),
85
+ withFontStyle: (fontStyle: Record<keyof FontStyleProps, string>, settings: FontStyleSettings) => withBooleanProps(fontStyle, undefined, settings),
86
+ withFontFamily: (fontFamily: Record<keyof FontFamilyProps, string>, settings: FontFamilySettings) => withBooleanProps(fontFamily, undefined, settings),
87
+ withTextDecoration: (textDecoration: Record<keyof TextDecorationProps, string>, settings: TextDecorationSettings) => withBooleanProps(textDecoration, undefined, settings),
88
+ withTextTransform: (textTransform: Record<keyof TextTransformProps, string>, settings: TextTransformSettings) => withBooleanProps(textTransform, undefined, settings),
89
+ withTextAppearance: (appearance: Record<keyof TextAppearanceProps & CommonAppearanceProps, string>, settings: TextAppearanceSettings) => withBooleanProps(appearance, "default", settings),
90
+
91
+ withGaps: (gapMap: Record<keyof GapProps, string>, sizeMap: Record<keyof SizeProps, string>) =>
92
+ otherProps.noGap !== undefined && otherProps.noGap ? withBooleanProps(gapMap) : builder.withSizes(sizeMap),
93
+
94
+ withTypography: (settings: TypographySettings) => builder
95
+ .withFontFamily(fontFamilyClasses, settings?.fontFamily ?? {})
96
+ .withFontStyle(fontStyleClasses, settings?.fontStyle ?? {})
97
+ .withFontWeight(fontWeightClasses, settings?.fontWeight ?? {})
98
+ .withTextDecoration(textDecorationClasses, settings?.textDecoration ?? {})
99
+ .withTextTransform(textTransformClasses, settings?.textTransform ?? {})
100
+ .withTextAppearance(textAppearanceClasses, settings?.textAppearance ?? {}),
101
+
102
+ withAppearance: (appearance: Record<keyof CommonAppearanceProps, string>, settings: CommonAppearanceSettings) => withBooleanProps(appearance, "default", settings),
103
+
104
+ build() {
105
+ builder.withHide({
106
+ xsHide: "max-xs:hidden",
107
+ smHide: "max-sm:hidden",
108
+ mdHide: "max-md:hidden",
109
+ lgHide: "max-lg:hidden",
110
+ xlHide: "max-xl:hidden"
111
+ })
112
+ builder.withPosition({
113
+ relative: "relative",
114
+ absolute: "absolute",
115
+ fixed: "fixed",
116
+ sticky: "sticky",
117
+ static: "static"
118
+ })
119
+ return finalize();
120
+ },
121
+ };
122
+
123
+ return builder;
124
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { Button } from "./components/ui/button";
2
+ export { Badge } from "./components/ui/badge";
3
+ export { Divider } from "./components/ui/divider";
4
+ export { Chip } from "./components/ui/chip";
5
+ export { Section, Container, Col, Row, Grid3, Grid4 } from "./components/ui/layout";
6
+ export { Text, Title, Link, List, ListItem, SectionTitle, PageTitle } from "./components/ui/typography";
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2019",
4
+ "module": "ESNext",
5
+ "lib": ["DOM", "ESNext"],
6
+ "jsx": "react-jsx",
7
+ "declaration": true,
8
+ "outDir": "./dist",
9
+ "moduleResolution": "node",
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "strict": true
13
+ },
14
+ "include": ["src"]
15
+ }