Package detail

grunfeld

ilokesto22MIT0.0.11

  • πŸš€ κ°„λ‹¨ν•œ API: λ³΅μž‘ν•œ μƒνƒœ 관리 없이 λͺ‡ μ€„μ˜ μ½”λ“œλ‘œ λŒ€ν™”μƒμžλ₯Ό 관리할 수 μžˆμŠ΅λ‹ˆλ‹€ - 🎯 동기/비동기 지원: 일반적인 μ•Œλ¦ΌλΆ€ν„° μ‚¬μš©μž 응닡이 ν•„μš”ν•œ 확인 λŒ€ν™”μƒμžκΉŒμ§€ λͺ¨λ“  μ‹œλ‚˜λ¦¬μ˜€λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€ - πŸ“± μœ μ—°ν•œ μœ„μΉ˜ μ„€μ •: 쀑앙 λͺ¨λ‹¬, ν•˜λ‹¨ μ‹œνŠΈ λ“± λ‹€μ–‘ν•œ UI νŒ¨ν„΄μ— 맞좰 μœ„μΉ˜λ₯Ό μ‘°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€ - πŸ”„ μŠ€λ§ˆνŠΈν•œ μŠ€νƒ 관리: μ—¬λŸ¬ λŒ€ν™”μƒμžκ°€ 열릴 λ•Œ 논리적인 LIFO(Last In First Out) μˆœμ„œλ‘œ

readme

Grunfeld

νŠΉμ§•

  • πŸš€ κ°„λ‹¨ν•œ API: λ³΅μž‘ν•œ μƒνƒœ 관리 없이 λͺ‡ μ€„μ˜ μ½”λ“œλ‘œ λŒ€ν™”μƒμžλ₯Ό 관리할 수 μžˆμŠ΅λ‹ˆλ‹€
  • 🎯 동기/비동기 지원: 일반적인 μ•Œλ¦ΌλΆ€ν„° μ‚¬μš©μž 응닡이 ν•„μš”ν•œ 확인 λŒ€ν™”μƒμžκΉŒμ§€ λͺ¨λ“  μ‹œλ‚˜λ¦¬μ˜€λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€
  • πŸ“± μœ μ—°ν•œ μœ„μΉ˜ μ„€μ •: 쀑앙 λͺ¨λ‹¬, ν•˜λ‹¨ μ‹œνŠΈ λ“± λ‹€μ–‘ν•œ UI νŒ¨ν„΄μ— 맞좰 μœ„μΉ˜λ₯Ό μ‘°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€
  • πŸ”„ μŠ€λ§ˆνŠΈν•œ μŠ€νƒ 관리: μ—¬λŸ¬ λŒ€ν™”μƒμžκ°€ 열릴 λ•Œ 논리적인 LIFO(Last In First Out) μˆœμ„œλ‘œ κ΄€λ¦¬λ©λ‹ˆλ‹€
  • 🎨 μ»€μŠ€ν…€ μŠ€νƒ€μΌλ§: λ°±λ“œλ‘­ μŠ€νƒ€μΌλΆ€ν„° κ°œλ³„ λŒ€ν™”μƒμž μŠ€νƒ€μΌκΉŒμ§€ 자유둭게 μ»€μŠ€ν„°λ§ˆμ΄μ§• κ°€λŠ₯ν•©λ‹ˆλ‹€
  • πŸ‘† 직관적인 UX: λ°°κ²½ 클릭으둜 λ‹«κΈ°, μžλ™ 포컀슀 관리 λ“± μ‚¬μš©μž κ²½ν—˜μ„ κ³ λ €ν•œ κΈ°λŠ₯듀을 μ œκ³΅ν•©λ‹ˆλ‹€λŠ” React μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μœ„ν•œ κ°„λ‹¨ν•˜κ³  κ°€λ²Όμš΄ λŒ€ν™”μƒμž(dialog) 관리 λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€.

μ„€μΉ˜

npm install grunfeld
# λ˜λŠ”
yarn add grunfeld

νŠΉμ§•

  • πŸš€ κ°„λ‹¨ν•œ API둜 λŒ€ν™”μƒμž 관리
  • οΏ½ 동기/비동기 λŒ€ν™”μƒμž 지원
  • πŸ“± μœ„μΉ˜ μ„€μ • κ°€λŠ₯ ('center' λ˜λŠ” 'bottom')
  • πŸ”„ 닀쀑 λŒ€ν™”μƒμž μŠ€νƒ 지원
  • 🎨 μ»€μŠ€ν…€ μŠ€νƒ€μΌλ§ 지원
  • πŸ‘† Light dismiss (λ°°κ²½ 클릭으둜 λ‹«κΈ°) μ˜΅μ…˜

μ‚¬μš©λ²•

κΈ°λ³Έ μ„€μ •

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ΅œμƒμœ„ λ ˆλ²¨μ— GrunfeldProviderλ₯Ό μΆ”κ°€ν•˜μ„Έμš”. 이 μ»΄ν¬λ„ŒνŠΈλŠ” λͺ¨λ“  λŒ€ν™”μƒμžλ₯Ό λ Œλ”λ§ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” μ»¨ν…μŠ€νŠΈλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€:

import { GrunfeldProvider } from "grunfeld";

function App() {
  return (
    <GrunfeldProvider
      options={{
        defaultPosition: "center",
        defaultDismiss: true,
        backdropStyle: {
          /* μ»€μŠ€ν…€ λ°±λ“œλ‘­ μŠ€νƒ€μΌ */
        },
      }}
    >
      {/* μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ‚΄μš© */}
    </GrunfeldProvider>
  );
}

κΈ°λ³Έ λŒ€ν™”μƒμž ν‘œμ‹œ

κ°€μž₯ 기본적인 ν˜•νƒœμ˜ λŒ€ν™”μƒμžμž…λ‹ˆλ‹€. μ‚¬μš©μžμ—κ²Œ 정보λ₯Ό λ³΄μ—¬μ£Όκ±°λ‚˜ κ°„λ‹¨ν•œ μƒν˜Έμž‘μš©μ΄ ν•„μš”ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€:

import { grunfeld } from "grunfeld";

function YourComponent() {
  const showDialog = () => {
    grunfeld.add({
      element: <div>μ•ˆλ…•ν•˜μ„Έμš”!</div>,
      position: "center",
      lightDismiss: true,
    });
  };

  return <button onClick={showDialog}>λŒ€ν™”μƒμž μ—΄κΈ°</button>;
}

비동기 λŒ€ν™”μƒμž (μ‚¬μš©μž 응닡 λŒ€κΈ°)

μ‚¬μš©μžμ˜ μ„ νƒμ΄λ‚˜ μž…λ ₯을 κΈ°λ‹€λ €μ•Ό ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€. Promiseλ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ async/await νŒ¨ν„΄μœΌλ‘œ μ‚¬μš©μžμ˜ 응닡을 μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

import { grunfeld } from "grunfeld";

function YourComponent() {
  const showConfirmDialog = async () => {
    const result = await grunfeld.addAsync((removeWith) => ({
      element: (
        <div>
          <p>정말 μ‚­μ œν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?</p>
          <button onClick={() => removeWith(true)}>확인</button>
          <button onClick={() => removeWith(false)}>μ·¨μ†Œ</button>
        </div>
      ),
      position: "center",
    }));

    if (result) {
      console.log("μ‚¬μš©μžκ°€ 확인을 ν΄λ¦­ν–ˆμŠ΅λ‹ˆλ‹€");
    } else {
      console.log("μ‚¬μš©μžκ°€ μ·¨μ†Œλ₯Ό ν΄λ¦­ν–ˆμŠ΅λ‹ˆλ‹€");
    }
  };

  return <button onClick={showConfirmDialog}>확인 λŒ€ν™”μƒμž</button>;
}

κ°„λ‹¨ν•œ λŒ€ν™”μƒμž (ReactNode만 전달)

λ³΅μž‘ν•œ μ„€μ • 없이 JSX μš”μ†Œλ‚˜ λ¬Έμžμ—΄μ„ 직접 μ „λ‹¬ν•˜μ—¬ λΉ λ₯΄κ²Œ λŒ€ν™”μƒμžλ₯Ό ν‘œμ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€:

import { grunfeld } from "grunfeld";

function YourComponent() {
  const showSimpleDialog = () => {
    // ReactNodeλ₯Ό 직접 전달할 수 μžˆμŠ΅λ‹ˆλ‹€
    grunfeld.add(<div>κ°„λ‹¨ν•œ λ©”μ‹œμ§€</div>);
  };

  return <button onClick={showSimpleDialog}>κ°„λ‹¨ν•œ λŒ€ν™”μƒμž</button>;
}

λŒ€ν™”μƒμž 제거

GrunfeldλŠ” λŒ€ν™”μƒμžλ“€μ„ μŠ€νƒ(Stack) ꡬ쑰둜 κ΄€λ¦¬ν•©λ‹ˆλ‹€. μ΄λŠ” λŒ€ν™”μƒμžλ“€ κ°„μ˜ λ§₯락적 관계λ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•¨μž…λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, A λŒ€ν™”μƒμžμ—μ„œ B λŒ€ν™”μƒμžλ₯Ό μ—΄μ—ˆλ‹€λ©΄, Bκ°€ A의 결과둜 μƒμ„±λœ κ²ƒμ΄λ―€λ‘œ Bκ°€ λ¨Όμ € λ‹«ν˜€μ•Ό λ…Όλ¦¬μ μœΌλ‘œ μ˜¬λ°”λ¦…λ‹ˆλ‹€. μ΄λŸ¬ν•œ 원칙에 따라 remove()λŠ” 항상 κ°€μž₯ μ΅œκ·Όμ— μ—΄λ¦° λŒ€ν™”μƒμžλΆ€ν„° μ œκ±°ν•©λ‹ˆλ‹€.

import { grunfeld } from "grunfeld";

// κ°€μž₯ 졜근 λŒ€ν™”μƒμž 제거
grunfeld.remove();

// λͺ¨λ“  λŒ€ν™”μƒμž 제거
grunfeld.clear();

API μ°Έμ‘°

GrunfeldProvider

속성 νƒ€μž… κΈ°λ³Έκ°’ μ„€λͺ…
children ReactNode ν•„μˆ˜ μžμ‹ μ»΄ν¬λ„ŒνŠΈ
options GrunfeldProviderOptions - κΈ°λ³Έ μ„€μ • μ˜΅μ…˜

GrunfeldProviderOptions

속성 νƒ€μž… κΈ°λ³Έκ°’ μ„€λͺ…
defaultPosition 'center' \ 'bottom' 'center' λŒ€ν™”μƒμžμ˜ κΈ°λ³Έ μœ„μΉ˜
defaultDismiss boolean true κΈ°λ³Έ light dismiss μ„€μ •
backdropStyle CSSProperties - λ°±λ“œλ‘­ μ»€μŠ€ν…€ μŠ€νƒ€μΌ

grunfeld 객체

grunfeld.add(dialog)

μƒˆλ‘œμš΄ λŒ€ν™”μƒμžλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

λ§€κ°œλ³€μˆ˜:

  • dialog: GrunfeldProps - λŒ€ν™”μƒμž μ„€μ •

GrunfeldProps:

type GrunfeldProps =
  | {
      element: React.ReactNode;
      position?: "center" | "bottom";
      lightDismiss?: boolean;
      dismissCallback?: () => unknown;
    }
  | React.ReactNode;

grunfeld.addAsync<T>(dialog)

비동기 λŒ€ν™”μƒμžλ₯Ό μΆ”κ°€ν•˜κ³  μ‚¬μš©μž 응닡을 κΈ°λ‹€λ¦½λ‹ˆλ‹€.

λ§€κ°œλ³€μˆ˜:

  • dialog: (removeWith: (data: T) => T) => GrunfeldProps - λŒ€ν™”μƒμž νŒ©ν† λ¦¬ ν•¨μˆ˜

λ°˜ν™˜κ°’:

  • Promise<T> - μ‚¬μš©μžκ°€ removeWithλ₯Ό ν˜ΈμΆœν•  λ•Œ μ „λ‹¬ν•œ 데이터

grunfeld.remove()

κ°€μž₯ μ΅œκ·Όμ— μΆ”κ°€λœ λŒ€ν™”μƒμžλ₯Ό μ œκ±°ν•©λ‹ˆλ‹€.

이 λ©”μ„œλ“œλŠ” LIFO(Last In First Out) 원칙을 λ”°λ¦…λ‹ˆλ‹€. μ—¬λŸ¬ λŒ€ν™”μƒμžκ°€ μ—΄λ €μžˆμ„ λ•Œ, κ°€μž₯ λ§ˆμ§€λ§‰μ— μ—΄λ¦° λŒ€ν™”μƒμžλΆ€ν„° μˆœμ„œλŒ€λ‘œ λ‹«νž™λ‹ˆλ‹€. μ΄λŠ” λŒ€ν™”μƒμžλ“€ κ°„μ˜ λ§₯락적 관계λ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ μ„€κ³„μž…λ‹ˆλ‹€.

// μ˜ˆμ‹œ: A β†’ B β†’ C μˆœμ„œλ‘œ μ—΄λ¦° 경우
grunfeld.remove(); // Cκ°€ λ‹«νž˜
grunfeld.remove(); // Bκ°€ λ‹«νž˜
grunfeld.remove(); // Aκ°€ λ‹«νž˜

grunfeld.clear()

λͺ¨λ“  λŒ€ν™”μƒμžλ₯Ό ν•œ λ²ˆμ— μ œκ±°ν•©λ‹ˆλ‹€.

κΈ΄κΈ‰ν•œ μƒν™©μ΄λ‚˜ νŽ˜μ΄μ§€ μ „ν™˜ μ‹œ λͺ¨λ“  λŒ€ν™”μƒμžλ₯Ό 정리해야 ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€. 각 λŒ€ν™”μƒμžμ˜ dismissCallback이 μžˆλ‹€λ©΄ λͺ¨λ‘ μ‹€ν–‰λœ ν›„ μ œκ±°λ©λ‹ˆλ‹€.

κ³ κΈ‰ μ‚¬μš©λ²•

μ»€μŠ€ν…€ dismiss 콜백

λŒ€ν™”μƒμžκ°€ λ‹«νž λ•Œ νŠΉμ • λ‘œμ§μ„ μ‹€ν–‰ν•΄μ•Ό ν•˜λŠ” 경우 dismissCallback을 μ‚¬μš©ν•©λ‹ˆλ‹€. μ΄λŠ” 정리 μž‘μ—…, μƒνƒœ μ—…λ°μ΄νŠΈ, 뢄석 이벀트 전솑 등에 μœ μš©ν•©λ‹ˆλ‹€:

grunfeld.add({
  element: <MyDialog />,
  dismissCallback: () => {
    console.log("λŒ€ν™”μƒμžκ°€ λ‹«ν˜”μŠ΅λ‹ˆλ‹€");
    // 정리 μž‘μ—… μˆ˜ν–‰
  },
});

μœ„μΉ˜λ³„ λŒ€ν™”μƒμž

λ‹€μ–‘ν•œ UI νŒ¨ν„΄μ— 맞좰 λŒ€ν™”μƒμžμ˜ μœ„μΉ˜λ₯Ό μ‘°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 각 μœ„μΉ˜λŠ” μ„œλ‘œ λ‹€λ₯Έ μ‚¬μš©μž κ²½ν—˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€:

// 쀑앙에 ν‘œμ‹œ
grunfeld.add({
  element: <CenterDialog />,
  position: "center",
});

// ν•˜λ‹¨μ— ν‘œμ‹œ (λ°”ν…€ μ‹œνŠΈ μŠ€νƒ€μΌ)
grunfeld.add({
  element: <BottomSheet />,
  position: "bottom",
});