From 02421bb8b739a93aab6e77dbab04668b374e8a0f Mon Sep 17 00:00:00 2001 From: Josem1801 Date: Thu, 19 Jun 2025 15:41:17 -0600 Subject: [PATCH 1/2] feat(react): add Level component --- js/react/lib/components/level/index.ts | 1 + .../lib/components/level/level.component.tsx | 31 +++++++++++++++++++ js/react/lib/components/level/level.const.ts | 15 +++++++++ js/react/lib/index.ts | 1 + js/react/lib/styles.css | 2 ++ js/react/showcase/App.tsx | 21 +++++++++++++ 6 files changed, 71 insertions(+) create mode 100644 js/react/lib/components/level/index.ts create mode 100644 js/react/lib/components/level/level.component.tsx create mode 100644 js/react/lib/components/level/level.const.ts diff --git a/js/react/lib/components/level/index.ts b/js/react/lib/components/level/index.ts new file mode 100644 index 0000000..ce5d739 --- /dev/null +++ b/js/react/lib/components/level/index.ts @@ -0,0 +1 @@ +export * from "./level.component"; diff --git a/js/react/lib/components/level/level.component.tsx b/js/react/lib/components/level/level.component.tsx new file mode 100644 index 0000000..ffc546d --- /dev/null +++ b/js/react/lib/components/level/level.component.tsx @@ -0,0 +1,31 @@ +import { ComponentPropsWithoutRef } from "react"; +import { cn } from "../../utils/tw-merge"; +import { LEVEL_LABELS, LEVEL_VARIANTS, LevelVariants } from "./level.const"; + +type LevelProps = { + variant: LevelVariants; + className?: string; + as?: C; +} & Omit, "children">; + +export const Level = ({ + as, + variant, + className, + ...rest +}: LevelProps) => { + const Component = as || "span"; + return ( + + {LEVEL_LABELS[variant]} + + ); +}; diff --git a/js/react/lib/components/level/level.const.ts b/js/react/lib/components/level/level.const.ts new file mode 100644 index 0000000..92b6023 --- /dev/null +++ b/js/react/lib/components/level/level.const.ts @@ -0,0 +1,15 @@ +export const LEVEL_VARIANTS = { + n1: "bg-primary-100", + n2: "bg-primary-300", + n3: "bg-primary-500", + op: "bg-secondary-400", +}; + +export const LEVEL_LABELS = { + n1: "N1", + n2: "N2", + n3: "N3", + op: "Op", +}; + +export type LevelVariants = keyof typeof LEVEL_VARIANTS; diff --git a/js/react/lib/index.ts b/js/react/lib/index.ts index b6435d6..06b71c7 100644 --- a/js/react/lib/index.ts +++ b/js/react/lib/index.ts @@ -3,4 +3,5 @@ export * from "./components/button"; export * from "./components/chip"; export * from "./components/tag"; export * from "./components/flap"; +export * from "./components/level"; export * from "./icons"; diff --git a/js/react/lib/styles.css b/js/react/lib/styles.css index cc88d7e..ac0134d 100644 --- a/js/react/lib/styles.css +++ b/js/react/lib/styles.css @@ -83,7 +83,9 @@ --color-light: #fafafa; --color-dark: #2e2e2e; + /* Fonts */ + --text-xxs: 10px; --text-caption: 12px; --text-caption--font-weight: 400; --text-caption--letter-spacing: 0em; diff --git a/js/react/showcase/App.tsx b/js/react/showcase/App.tsx index d38752b..c0c874a 100644 --- a/js/react/showcase/App.tsx +++ b/js/react/showcase/App.tsx @@ -6,6 +6,7 @@ import { Telegram, Flap, Chip, + Level, } from "@rustlanges/react"; import { ShowComponent } from "./ShowComponent"; @@ -143,6 +144,26 @@ export function App() { }} component={Flap} /> + ); } From 77a4ceaf1635ef816896ac0211c8a0385d6fdb63 Mon Sep 17 00:00:00 2001 From: Josem1801 Date: Thu, 19 Jun 2025 15:49:23 -0600 Subject: [PATCH 2/2] refactor: create withAs HOC to support dynamic tag rendering --- .../lib/components/level/level.component.tsx | 45 +++++++++---------- js/react/lib/components/tag/index.ts | 2 +- js/react/lib/components/tag/tag.component.tsx | 40 +++++++++-------- js/react/lib/components/tag/tag.const.ts | 2 +- js/react/lib/utils/hoc/with-as.hoc.tsx | 12 +++++ 5 files changed, 55 insertions(+), 46 deletions(-) create mode 100644 js/react/lib/utils/hoc/with-as.hoc.tsx diff --git a/js/react/lib/components/level/level.component.tsx b/js/react/lib/components/level/level.component.tsx index ffc546d..8ec149d 100644 --- a/js/react/lib/components/level/level.component.tsx +++ b/js/react/lib/components/level/level.component.tsx @@ -1,31 +1,26 @@ -import { ComponentPropsWithoutRef } from "react"; +import { withAs } from "../../utils/hoc/with-as.hoc"; import { cn } from "../../utils/tw-merge"; import { LEVEL_LABELS, LEVEL_VARIANTS, LevelVariants } from "./level.const"; -type LevelProps = { +type LevelProps = { variant: LevelVariants; className?: string; - as?: C; -} & Omit, "children">; - -export const Level = ({ - as, - variant, - className, - ...rest -}: LevelProps) => { - const Component = as || "span"; - return ( - - {LEVEL_LABELS[variant]} - - ); }; + +export const Level = withAs( + (Component, { variant, className, ...rest }: LevelProps) => { + return ( + + {LEVEL_LABELS[variant]} + + ); + } +); diff --git a/js/react/lib/components/tag/index.ts b/js/react/lib/components/tag/index.ts index f13aa6a..cd95b7a 100644 --- a/js/react/lib/components/tag/index.ts +++ b/js/react/lib/components/tag/index.ts @@ -1 +1 @@ -export { Tag } from "./tag.component" \ No newline at end of file +export { Tag } from "./tag.component"; diff --git a/js/react/lib/components/tag/tag.component.tsx b/js/react/lib/components/tag/tag.component.tsx index 6b87ddb..df39941 100644 --- a/js/react/lib/components/tag/tag.component.tsx +++ b/js/react/lib/components/tag/tag.component.tsx @@ -1,24 +1,26 @@ -import { ComponentPropsWithoutRef, useMemo } from "react"; import { cn } from "../../utils/tw-merge"; import { TAG_VARIANTS } from "./tag.const"; +import { withAs } from "../../utils/hoc/with-as.hoc"; -type TagProps = { - as?: C; +type TagProps = { label?: string; -} & Omit, "children">; + selected?: boolean; + className?: string; +}; -export const Tag = ({ label, selected, className , as, ...rest }: TagProps) => { - const Component = useMemo(() => as || "span", [as]) - return ( - - {label} - - ); -}; \ No newline at end of file +export const Tag = withAs( + (Component, { label, selected, className, ...rest }: TagProps) => { + return ( + + {label} + + ); + } +); diff --git a/js/react/lib/components/tag/tag.const.ts b/js/react/lib/components/tag/tag.const.ts index 0ea1b63..a451ca0 100644 --- a/js/react/lib/components/tag/tag.const.ts +++ b/js/react/lib/components/tag/tag.const.ts @@ -7,4 +7,4 @@ export const TAG_VARIANTS = { "bg-secondary-100 border-secondary-600 text-secondary-600", "dark:bg-primary-950 dark:border-primary-500 dark:text-primary-500", ], -}; \ No newline at end of file +}; diff --git a/js/react/lib/utils/hoc/with-as.hoc.tsx b/js/react/lib/utils/hoc/with-as.hoc.tsx new file mode 100644 index 0000000..ffb431f --- /dev/null +++ b/js/react/lib/utils/hoc/with-as.hoc.tsx @@ -0,0 +1,12 @@ +import React, { ComponentPropsWithoutRef } from "react"; + +export function withAs

( + render: (Component: React.ElementType, props: P) => React.ReactNode +) { + return function WithAsComponent( + props: { as?: C } & Omit, keyof P> & P + ) { + const { as: Component = "div", ...rest } = props; + return render(Component, rest as P); + }; +}