-
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.
* 🚚 chore(workflow): create issue branch가 생성하는 브랜치 prefix 변경 * 🚚 chore(workflow): component plop에 vitest import 문 추가 및 jest 주석 삭제 * ♻️ refactor(component): bandAxis 분리 및 방향 추가 * ✨ feat(css): labelHide, lineHide 추가 및 관련 스토리 추가 * ✨ feat(util): getAxisOrientConfig 함수 추가 * ♻️ refactor(component): getAxisOrientConfig 함수 적용 및 direction을 orient로 props 이름 변경 * ♻️ refactor(component): barChart에 기존 BandAxis 제거 및 BandAxis 컴포넌트 적용 * 🚚 chore(type): axisOrient 타입 export * ✅ test(util): getAxisOrientConfig 테스트 코드 추가 * 💄 style(css): bandAxisVariants 삭제 * ✅ test(component): bandAxis 테스트 코드 추가 * 💄 style(css): bandAxisVariants에 base만 있도록 수정 * ✅ test(component): bandAxis 테스트 코드 추가 * 🐛 fix(type): lineHide type 빠져있는 문제 수정 ISSUES CLOSED: #31 * 🐛 fix(component): lineHide 시 path와 line이 렌더링되는 문제 수정
- Loading branch information
Showing
12 changed files
with
294 additions
and
44 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
2 changes: 1 addition & 1 deletion
2
plop_templates/component/__test__/{{upperCamel name}}.test.tsx.hbs
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
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,66 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import { scaleBand } from "d3"; | ||
import BandAxis from "./BandAxis"; | ||
|
||
const meta = { | ||
title: "charts/BandAxis", | ||
component: BandAxis, | ||
parameters: { | ||
layout: "centered", | ||
}, | ||
tags: ["autodocs"], | ||
} satisfies Meta<typeof BandAxis>; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof BandAxis>; | ||
|
||
const data = [ | ||
{ label: 2019, value: 151.8 }, | ||
{ label: 2020, value: 242.2 }, | ||
{ label: 2021, value: 121.3 }, | ||
{ label: 2022, value: 200.7 }, | ||
{ label: 2023, value: null }, // 값이 아직 없는 경우 | ||
]; | ||
|
||
const length = 256; | ||
|
||
const xScale = scaleBand() | ||
.domain(data.map((d) => d.label.toString())) | ||
.range([0, length]); | ||
|
||
export const Default: Story = { | ||
render: () => ( | ||
<svg width={256} height={256}> | ||
<BandAxis axisScale={xScale} transform="translate(0, 128)" /> | ||
</svg> | ||
), | ||
}; | ||
|
||
export const Direction: Story = { | ||
render: () => ( | ||
<svg width={512} height={256}> | ||
<g transform="translate(128, 0)"> | ||
<BandAxis axisScale={xScale} orient="DOWN" transform="translate(0, 5)" /> | ||
<BandAxis axisScale={xScale} orient="UP" transform="translate(0, 245)" /> | ||
<BandAxis axisScale={xScale} orient="RIGHT" transform="translate(280, 0)" /> | ||
<BandAxis axisScale={xScale} orient="LEFT" transform="translate(-24, 0)" /> | ||
</g> | ||
</svg> | ||
), | ||
}; | ||
|
||
export const LabelHide: Story = { | ||
render: () => ( | ||
<svg width={256} height={256}> | ||
<BandAxis axisScale={xScale} transform="translate(0, 128)" labelHide /> | ||
</svg> | ||
), | ||
}; | ||
|
||
export const LineHide: Story = { | ||
render: () => ( | ||
<svg width={256} height={256}> | ||
<BandAxis axisScale={xScale} transform="translate(0, 128)" lineHide /> | ||
</svg> | ||
), | ||
}; |
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,5 @@ | ||
import { tv } from "@utils/customTV"; | ||
|
||
export const BandAxisVariants = tv({ | ||
base: "stroke-black", | ||
}); |
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,56 @@ | ||
import { getAxisOrientConfig } from "@utils/getAxisOrientConfig"; | ||
import { isEven } from "@utils/isEven"; | ||
import { BandAxisVariants } from "./BandAxis.styles"; | ||
import { BandAxisProps } from "./BandAxis.types"; | ||
|
||
const BandAxis = ({ | ||
orient = "DOWN", | ||
axisScale, | ||
outerTickLength = 6, | ||
innerTickLength = 6, | ||
lineHide, | ||
labelHide, | ||
className, | ||
...props | ||
}: BandAxisProps) => { | ||
const [startPoint, endPoint] = axisScale.range(); | ||
const tickCount = axisScale.domain().length; | ||
const isVertical = orient === "LEFT" || orient === "RIGHT"; | ||
|
||
const tickStartPoint = | ||
(endPoint - startPoint) / 2 - | ||
axisScale.step() * (isEven(tickCount) ? tickCount / 2 - 0.5 : Math.floor(tickCount / 2)); | ||
|
||
const [textdX, textdY, path] = getAxisOrientConfig({ orient, startPoint, endPoint, outerTickLength }); | ||
|
||
return ( | ||
<g className={BandAxisVariants({ className })} textAnchor="middle" {...props}> | ||
{!lineHide && <path fill="none" d={path} />} | ||
{axisScale.domain().map((label, i) => ( | ||
<g | ||
key={`tick-${i}`} | ||
transform={ | ||
isVertical | ||
? `translate(0, ${tickStartPoint + axisScale.step() * i})` | ||
: `translate(${tickStartPoint + axisScale.step() * i}, 0)` | ||
} | ||
> | ||
{!lineHide && ( | ||
<line | ||
x2={isVertical ? innerTickLength : undefined} | ||
y2={isVertical ? undefined : innerTickLength} | ||
fill="none" | ||
/> | ||
)} | ||
{!labelHide && ( | ||
<text dx={textdX} dy={textdY} stroke="none"> | ||
{label} | ||
</text> | ||
)} | ||
</g> | ||
))} | ||
</g> | ||
); | ||
}; | ||
|
||
export default BandAxis; |
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 ScaleBand } from "d3"; | ||
import type { VariantProps } from "tailwind-variants"; | ||
import type { ComponentPropsWithInnerRef } from "@customTypes/utilType"; | ||
import { BandAxisVariants } from "./BandAxis.styles"; | ||
|
||
export type AxisOrient = "UP" | "DOWN" | "RIGHT" | "LEFT"; | ||
|
||
type BandAxisBaseProps = { | ||
axisScale: ScaleBand<string>; | ||
outerTickLength?: number; | ||
innerTickLength?: number; | ||
orient?: AxisOrient; | ||
labelHide?: boolean; | ||
lineHide?: boolean; | ||
}; | ||
|
||
export type BandAxisProps = Omit<ComponentPropsWithInnerRef<"g">, "textAnchor"> & | ||
VariantProps<typeof BandAxisVariants> & | ||
BandAxisBaseProps; |
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,83 @@ | ||
/* eslint-disable testing-library/no-node-access */ | ||
|
||
/* eslint-disable testing-library/no-container */ | ||
import { render } from "@testing-library/react"; | ||
import { scaleBand } from "d3-scale"; | ||
import { describe, expect, it } from "vitest"; | ||
import BandAxis from "../BandAxis"; | ||
import type { AxisOrient } from "../BandAxis.types"; | ||
|
||
const createScale = () => scaleBand().domain(["A", "B", "C", "D"]).range([0, 100]); | ||
|
||
describe("BandAxis", () => { | ||
const defaultProps = { | ||
axisScale: createScale(), | ||
orient: "DOWN" as AxisOrient, | ||
outerTickLength: 6, | ||
innerTickLength: 6, | ||
lineHide: false, | ||
labelHide: false, | ||
className: "", | ||
}; | ||
|
||
it("에러 없이 렌더링", () => { | ||
render(<BandAxis {...defaultProps} />); | ||
}); | ||
|
||
it("data에 맞는 tick 개수", () => { | ||
const { container } = render(<BandAxis {...defaultProps} />); | ||
const ticks = container.querySelectorAll("g > g"); | ||
expect(ticks.length).toBe(4); | ||
}); | ||
|
||
it("lineHide일 때 path, line 태그 없음", () => { | ||
const { container } = render(<BandAxis {...defaultProps} lineHide />); | ||
const path = container.querySelector("path"); | ||
const line = container.querySelector("line"); | ||
|
||
expect(path).toBe(null); | ||
expect(line).toBe(null); | ||
}); | ||
|
||
it("labelHide일 때 text 태그 없음", () => { | ||
const { container } = render(<BandAxis {...defaultProps} labelHide />); | ||
const texts = container.querySelectorAll("text"); | ||
expect(texts.length).toBe(0); | ||
}); | ||
|
||
it("orient가 UP | DOWN 일 경우, transform 속성", () => { | ||
const regex = /^translate\([\d.]+,\s*0\)$/; | ||
["UP", "DOWN"].forEach((orient) => { | ||
const { container } = render(<BandAxis {...defaultProps} orient={orient as AxisOrient} />); | ||
const tick = container.querySelector("g > g"); | ||
expect(tick).toHaveAttribute("transform", expect.stringMatching(regex)); | ||
}); | ||
}); | ||
|
||
it("orient가 UP | DOWN 일 경우, line의 y2 존재 및 x2 속성 없음", () => { | ||
["UP", "DOWN"].forEach((orient) => { | ||
const { container } = render(<BandAxis {...defaultProps} orient={orient as AxisOrient} />); | ||
const line = container.querySelector("line"); | ||
expect(line).toHaveAttribute("y2"); | ||
expect(line).not.toHaveAttribute("x2"); | ||
}); | ||
}); | ||
|
||
it("orient가 LEFT | RIGHT 일 경우, transform 속성", () => { | ||
const regex = /^translate\(0,\s*[\d.]+\)$/; | ||
["LEFT", "RIGHT"].forEach((orient) => { | ||
const { container } = render(<BandAxis {...defaultProps} orient={orient as AxisOrient} />); | ||
const tick = container.querySelector("g > g"); | ||
expect(tick).toHaveAttribute("transform", expect.stringMatching(regex)); | ||
}); | ||
}); | ||
|
||
it("orient가 LEFT | RIGHT 일 경우, line의 x2 존재 및 y2 속성 없음", () => { | ||
["LEFT", "RIGHT"].forEach((orient) => { | ||
const { container } = render(<BandAxis {...defaultProps} orient={orient as AxisOrient} />); | ||
const line = container.querySelector("line"); | ||
expect(line).toHaveAttribute("x2"); | ||
expect(line).not.toHaveAttribute("y2"); | ||
}); | ||
}); | ||
}); |
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,9 @@ | ||
import BandAxis from "./BandAxis"; | ||
import { BandAxisVariants } from "./BandAxis.styles"; | ||
import type { AxisOrient, BandAxisProps } from "./BandAxis.types"; | ||
|
||
export type { BandAxisProps, AxisOrient }; | ||
|
||
export { BandAxisVariants }; | ||
|
||
export default BandAxis; |
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
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
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 { describe, expect, test } from "vitest"; | ||
import { getAxisOrientConfig } from "@utils/getAxisOrientConfig"; | ||
|
||
describe("getAxisOrientConfig", () => { | ||
const startPoint = 0; | ||
const endPoint = 100; | ||
const outerTickLength = 10; | ||
|
||
test("returns correct config for UP orientation", () => { | ||
const result = getAxisOrientConfig({ orient: "UP", startPoint, endPoint, outerTickLength }); | ||
expect(result).toEqual([0, -6, "M0.5,0V10H99.5V0"]); | ||
}); | ||
|
||
test("returns correct config for DOWN orientation", () => { | ||
const result = getAxisOrientConfig({ orient: "DOWN", startPoint, endPoint, outerTickLength }); | ||
expect(result).toEqual([0, 24, "M0.5,10V0H99.5V10"]); | ||
}); | ||
|
||
test("returns correct config for LEFT orientation", () => { | ||
const result = getAxisOrientConfig({ orient: "LEFT", startPoint, endPoint, outerTickLength }); | ||
expect(result).toEqual([-24, 6, "M0,0.5H10V99.5H0"]); | ||
}); | ||
|
||
test("returns correct config for RIGHT orientation", () => { | ||
const result = getAxisOrientConfig({ orient: "RIGHT", startPoint, endPoint, outerTickLength }); | ||
expect(result).toEqual([28, 6, "M10,0.5H0V99.5H10"]); | ||
}); | ||
}); |
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 { AxisOrient } from "@charts/BandAxis/BandAxis.types"; | ||
|
||
type getAxisOrientConfigParams = { | ||
orient: AxisOrient; | ||
startPoint: number; | ||
endPoint: number; | ||
outerTickLength: number; | ||
}; | ||
|
||
export const getAxisOrientConfig = ({ orient, startPoint, endPoint, outerTickLength }: getAxisOrientConfigParams) => { | ||
const pathConfig: { [key: string]: [number, number, string] } = { | ||
UP: [0, -6, `M${startPoint + 0.5},0V${outerTickLength}H${endPoint - 0.5}V0`], | ||
DOWN: [0, 24, `M${startPoint + 0.5},${outerTickLength}V0H${endPoint - 0.5}V${outerTickLength}`], | ||
LEFT: [-24, 6, `M0,${startPoint + 0.5}H${outerTickLength}V${endPoint - 0.5}H0`], | ||
RIGHT: [28, 6, `M${outerTickLength},${startPoint + 0.5}H0V${endPoint - 0.5}H${outerTickLength}`], | ||
}; | ||
|
||
return pathConfig[orient]; | ||
}; |