-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Progress Development UI Packages (#27)
- Loading branch information
Showing
43 changed files
with
2,179 additions
and
774 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Xion Design System | ||
|
||
.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{ | ||
"name": "@xionwcfm/ui", | ||
"version": "0.0.1", | ||
"license": "MIT", | ||
"main": "./dist/index.js", | ||
"module": "./dist/index.mjs", | ||
"types": "./dist/index.d.ts", | ||
"style": "./dist/style.css", | ||
"exports": { | ||
"./package.json": "./package.json", | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.mts", | ||
"default": "./dist/index.mjs" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
} | ||
} | ||
}, | ||
"files": ["dist"], | ||
"scripts": { | ||
"build": "tsup && pnpm run build:css", | ||
"build:css": "tailwindcss -i ./style.css -o dist/style.css --minify --postcss", | ||
"build:no": "tailwindcss -i ./style.css -o dist/style.css --postcss", | ||
"test": "vitest", | ||
"test:ci": "vitest run" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"devDependencies": { | ||
"@testing-library/jest-dom": "^6.6.3", | ||
"@testing-library/react": "^16.1.0", | ||
"@testing-library/user-event": "^14.5.2", | ||
"@types/node": "catalog:", | ||
"@types/react": "catalog:react18", | ||
"@types/react-dom": "catalog:react18", | ||
"@vitejs/plugin-react": "^4.3.4", | ||
"@xionwcfm/typescript-config": "workspace:*", | ||
"autoprefixer": "catalog:", | ||
"happy-dom": "^15.11.7", | ||
"postcss": "catalog:", | ||
"react": "catalog:react18", | ||
"tailwindcss": "catalog:", | ||
"tsup": "catalog:", | ||
"typescript": "catalog:", | ||
"vite": "^6.0.5", | ||
"vite-tsconfig-paths": "^5.1.4", | ||
"vitest": "^2.1.8" | ||
}, | ||
"peerDependencies": { | ||
"react": ">=18", | ||
"react-dom": ">=18" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** @type {import('postcss-load-config').Config} */ | ||
const config = { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
// "postcss-variable-compress": {}, | ||
}, | ||
}; | ||
|
||
export default config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { render, screen } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
import { useRef } from "react"; | ||
import "@testing-library/jest-dom"; | ||
import { Box } from "./box"; | ||
|
||
describe("Box", () => { | ||
it("should render as default div element", () => { | ||
render(<Box>Content</Box>); | ||
const element = screen.getByText("Content"); | ||
expect(element.tagName).toBe("DIV"); | ||
}); | ||
|
||
it("should render as specified element", () => { | ||
render(<Box as="section">Content</Box>); | ||
const element = screen.getByText("Content"); | ||
expect(element.tagName).toBe("SECTION"); | ||
}); | ||
|
||
it("should apply custom className", () => { | ||
render(<Box className="custom-class">Content</Box>); | ||
const element = screen.getByText("Content"); | ||
expect(element).toHaveClass("custom-class"); | ||
}); | ||
|
||
it("should forward ref correctly", () => { | ||
function TestComponent() { | ||
const ref = useRef<HTMLDivElement>(null); | ||
return <Box ref={ref}>Content</Box>; | ||
} | ||
|
||
render(<TestComponent />); | ||
const element = screen.getByText("Content"); | ||
expect(element).toBeInTheDocument(); | ||
expect(element.tagName).toBe("DIV"); | ||
}); | ||
|
||
it("should handle click events", async () => { | ||
const handleClick = vi.fn(); | ||
render(<Box onClick={handleClick}>Clickable</Box>); | ||
|
||
await userEvent.click(screen.getByText("Clickable")); | ||
expect(handleClick).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it("should handle keyboard events", async () => { | ||
const handleKeyDown = vi.fn(); | ||
render( | ||
<Box tabIndex={0} onKeyDown={handleKeyDown}> | ||
Interactive | ||
</Box>, | ||
); | ||
|
||
const element = screen.getByText("Interactive"); | ||
await userEvent.tab(); | ||
expect(element).toHaveFocus(); | ||
|
||
await userEvent.keyboard("[Enter]"); | ||
expect(handleKeyDown).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it("should handle aria attributes", () => { | ||
render( | ||
<Box aria-label="Test label" aria-describedby="description"> | ||
Accessible Content | ||
</Box>, | ||
); | ||
|
||
const element = screen.getByLabelText("Test label"); | ||
expect(element).toHaveAttribute("aria-describedby", "description"); | ||
}); | ||
|
||
it("should handle data attributes", () => { | ||
render( | ||
<Box data-testid="test-box" data-custom="value"> | ||
Content | ||
</Box>, | ||
); | ||
|
||
const element = screen.getByTestId("test-box"); | ||
expect(element).toHaveAttribute("data-custom", "value"); | ||
}); | ||
|
||
it("should handle style prop", () => { | ||
render(<Box style={{ backgroundColor: "red" }}>Styled Content</Box>); | ||
|
||
const element = screen.getByText("Styled Content"); | ||
expect(element).toHaveStyle({ backgroundColor: "red" }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { type ElementType, type ReactNode, forwardRef } from "react"; | ||
import { type PolymorphicComponentProps, type PolymorphicRef } from "./polymorphics"; | ||
export type BoxProps<C extends ElementType> = PolymorphicComponentProps< | ||
C, | ||
{ | ||
className?: string; | ||
children?: ReactNode; | ||
} | ||
>; | ||
|
||
export type BoxRef<C extends ElementType> = PolymorphicRef<C>; | ||
|
||
export const Box = forwardRef(function Box<C extends ElementType = "div">( | ||
{ as, className, ...rest }: BoxProps<C>, | ||
ref?: BoxRef<C>, | ||
) { | ||
const Component = as ?? "div"; | ||
return <Component ref={ref} className={className} {...rest} />; | ||
}) as <C extends ElementType = "div">(props: BoxProps<C> & { ref?: BoxRef<C> }) => JSX.Element; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { type ElementType, forwardRef } from "react"; | ||
import { Box, type BoxRef } from "./box"; | ||
import type { BoxProps } from "./box"; | ||
|
||
export const CenterStack = forwardRef(function CenterStack<C extends ElementType = "div">( | ||
{ as, className, ...rest }: BoxProps<C>, | ||
ref?: BoxRef<C>, | ||
) { | ||
const typesRest = rest as BoxProps<C>; | ||
return ( | ||
<Box | ||
className={` @xui-flex @xui-flex-col @xui-justify-center @xui-items-center ${className}`} | ||
ref={ref} | ||
as={as} | ||
{...typesRest} | ||
/> | ||
); | ||
}) as <C extends ElementType = "div">(props: BoxProps<C> & { ref?: BoxRef<C> }) => JSX.Element; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { render, screen } from "@testing-library/react"; | ||
import "@testing-library/jest-dom"; | ||
import { Center } from "./center"; | ||
|
||
describe("Center", () => { | ||
it("should handle aria attributes", () => { | ||
render( | ||
<Center aria-label="Test label" aria-describedby="description"> | ||
Accessible Content | ||
</Center>, | ||
); | ||
|
||
const element = screen.getByLabelText("Test label"); | ||
expect(element).toHaveAttribute("aria-describedby", "description"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { type ElementType, forwardRef } from "react"; | ||
import { Box, type BoxRef } from "./box"; | ||
import type { BoxProps } from "./box"; | ||
|
||
export const Center = forwardRef(function Center<C extends ElementType = "div">( | ||
{ as, className, ...rest }: BoxProps<C>, | ||
ref?: BoxRef<C>, | ||
) { | ||
const typesRest = rest as BoxProps<C>; | ||
return ( | ||
<Box className={` @xui-flex @xui-justify-center @xui-items-center ${className}`} ref={ref} as={as} {...typesRest} /> | ||
); | ||
}) as <C extends ElementType = "div">(props: BoxProps<C> & { ref?: BoxRef<C> }) => JSX.Element; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { type ElementType, forwardRef } from "react"; | ||
import { Box, type BoxRef } from "./box"; | ||
import type { BoxProps } from "./box"; | ||
|
||
export const Flex = forwardRef(function Flex<C extends ElementType = "div">( | ||
{ as, className, ...rest }: BoxProps<C>, | ||
ref?: BoxRef<C>, | ||
) { | ||
const typesRest = rest as BoxProps<C>; | ||
return <Box className={` @xui-flex ${className}`} ref={ref} as={as} {...typesRest} />; | ||
}) as <C extends ElementType = "div">(props: BoxProps<C> & { ref?: BoxRef<C> }) => JSX.Element; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Box } from "./box"; | ||
import { Center } from "./center"; | ||
import { CenterStack } from "./center-stack"; | ||
import { Flex } from "./flex"; | ||
import { JustifyBetween } from "./justify-between"; | ||
import { JustifyEnd } from "./justify-end"; | ||
import { List } from "./list"; | ||
import { Row } from "./row"; | ||
import { Skeleton } from "./skeleton"; | ||
import { Spacing } from "./spacing"; | ||
import { Stack } from "./stack"; | ||
import { ToggleButton } from "./toggle-button"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const isString = (value: unknown): value is string => typeof value === "string"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Children, Fragment, type PropsWithChildren, type ReactNode, isValidElement } from "react"; | ||
|
||
interface Props extends PropsWithChildren { | ||
with: ReactNode; | ||
} | ||
|
||
export function Separated({ children, with: separator }: Props) { | ||
const childrenArray = Children.toArray(children).filter(isValidElement); | ||
const childrenLength = childrenArray.length; | ||
|
||
return ( | ||
<> | ||
{childrenArray.map((child, i) => ( | ||
<Fragment key={i}> | ||
{child} | ||
{i + 1 !== childrenLength ? separator : null} | ||
</Fragment> | ||
))} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { type ElementType, forwardRef } from "react"; | ||
import { Box, type BoxRef } from "./box"; | ||
import type { BoxProps } from "./box"; | ||
|
||
export const JustifyBetween = forwardRef(function JustifyBetween<C extends ElementType = "div">( | ||
{ as, className, ...rest }: BoxProps<C>, | ||
ref?: BoxRef<C>, | ||
) { | ||
const typesRest = rest as BoxProps<C>; | ||
return <Box className={` @xui-flex @xui-justify-between ${className}`} ref={ref} as={as} {...typesRest} />; | ||
}) as <C extends ElementType = "div">(props: BoxProps<C> & { ref?: BoxRef<C> }) => JSX.Element; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { type ElementType, forwardRef } from "react"; | ||
import { Box, type BoxRef } from "./box"; | ||
import type { BoxProps } from "./box"; | ||
|
||
export const JustifyEnd = forwardRef(function JustifyEnd<C extends ElementType = "div">( | ||
{ as, className, ...rest }: BoxProps<C>, | ||
ref?: BoxRef<C>, | ||
) { | ||
const typesRest = rest as BoxProps<C>; | ||
return <Box className={` @xui-flex @xui-justify-end ${className}`} ref={ref} as={as} {...typesRest} />; | ||
}) as <C extends ElementType = "div">(props: BoxProps<C> & { ref?: BoxRef<C> }) => JSX.Element; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Children, type ElementType, type ReactNode, forwardRef } from "react"; | ||
import { Box, type BoxRef } from "./box"; | ||
import type { BoxProps } from "./box"; | ||
import { Separated } from "./internal/separated"; | ||
|
||
type ListProps = { | ||
fallback?: ReactNode; | ||
with?: ReactNode; | ||
}; | ||
|
||
export const List = forwardRef(function List<C extends ElementType = "ul">( | ||
{ as, className, children, fallback, ...rest }: BoxProps<C> & ListProps, | ||
ref?: BoxRef<C>, | ||
) { | ||
const typesRest = rest as BoxProps<C>; | ||
const child = Children.toArray(children); | ||
const isEmpty = child.length === 0; | ||
|
||
if (isEmpty) { | ||
return <>{fallback}</>; | ||
} | ||
|
||
return ( | ||
<Box className={` @xui-flex @xui-flex-col @xui-break-words ${className}`} ref={ref} as={as} {...typesRest}> | ||
{rest.with ? <Separated with={rest.with}>{children}</Separated> : children} | ||
</Box> | ||
); | ||
}) as <C extends ElementType = "ul">(props: BoxProps<C> & ListProps & { ref?: BoxRef<C> }) => JSX.Element; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import type { ComponentPropsWithoutRef, ElementType } from "react"; | ||
|
||
export type AsProp<C extends ElementType> = { | ||
as?: C; | ||
}; | ||
|
||
export type KeyWithAs<C extends ElementType, Props> = keyof (AsProp<C> & Props); | ||
|
||
export type PolymorphicRef<C extends ElementType> = ComponentPropsWithoutRef<C>["ref"]; | ||
|
||
export type PolymorphicComponentProps<C extends ElementType, Props = object> = (Props & AsProp<C>) & | ||
Omit<ComponentPropsWithoutRef<C>, KeyWithAs<C, Props>>; | ||
|
||
export type PolymorphicComponentPropsWithRef<C extends ElementType, Props = object> = Props & { | ||
ref?: PolymorphicRef<C>; | ||
}; |
Oops, something went wrong.