npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@solapi/ui-kit

v1.0.4

Published

Solapi 공용 UI 컴포넌트 라이브러리. **Module Federation**(CDN) 우선 로드, CDN 장애 시 **npm 패키지**로 자동 fallback하는 구조입니다.

Readme

@solapi/ui-kit

Solapi 공용 UI 컴포넌트 라이브러리. Module Federation(CDN) 우선 로드, CDN 장애 시 npm 패키지로 자동 fallback하는 구조입니다.

설치

npm install @solapi/ui-kit

CSS 스타일 import

npm 패키지 사용 시 CSS를 별도로 import해야 합니다. (Module Federation은 CSS가 자동 포함되므로 불필요)

import '@solapi/ui-kit/styles'

주의: CSS를 import하지 않으면 Modal, Snackbar, Confirm 등 UI 컴포넌트가 렌더링되지만 화면에 보이지 않습니다.

Module Federation Exposes

| 모듈 | 경로 | 설명 | |------|------|------| | ./ui | src/export/index.ts | 전체 export (컴포넌트, 훅, Provider, 테마) | | ./provider | src/export/provider.ts | GlobalUIProvider, ThemeProvider | | ./hooks | src/export/hooks.ts | useSnackbar, useModal, useConfirm, useEnhancedMutation | | ./createMutationConfig | src/lib/createMutationConfig.ts | MFA 처리 포함 Mutation 설정 유틸 |

Quick Start (Federation + npm Fallback)

1. Remote 등록

// vite.remotes.config.js
const remoteApps = {
  '@solapi-frontend/ui-kit': '/ui-kit/stable/assets/remote.entry.js'
}

2. GlobalUIProvider 감싸기

// src/uiKit/safeProviderLoader.tsx
import { createSafeProviderLoader } from '@solapi/ui-kit/federation'

const UI_KIT_PROVIDER = async () => {
  try {
    return await import('@solapi-frontend/ui-kit/provider')
  } catch {
    // npm fallback 시 CSS 로드 (Federation은 CSS 자동 포함)
    await import('@solapi/ui-kit/styles')
    return await import('@solapi/ui-kit')
  }
}

const GlobalUIProvider = createSafeProviderLoader<{
  children?: React.ReactNode
  portalContainer?: () => HTMLElement | null
}>(
  UI_KIT_PROVIDER,
  'GlobalUIProvider',
  { warningMessage: 'UI Kit CDN을 로드할 수 없습니다. npm 패키지로 대체되었습니다.' }
)

export default function RemoteEntry() {
  return (
    <GlobalUIProvider portalContainer={() => document.getElementById('root')}>
      {/* 앱 컨텐츠 */}
    </GlobalUIProvider>
  )
}

3. 컴포넌트 로더 정의

// src/uiKit/safeCompLoader.tsx
import { createSafeComponentLoader } from '@solapi/ui-kit/federation'

const UI_KIT_COMP = async () => {
  try {
    return await import('@solapi-frontend/ui-kit/ui')
  } catch {
    return await import('@solapi/ui-kit')
  }
}

export const Tabs = createSafeComponentLoader(UI_KIT_COMP, 'Tabs')
export const TextInput = createSafeComponentLoader(UI_KIT_COMP, 'TextInput')
export const Button = createSafeComponentLoader(UI_KIT_COMP, 'Button')
export const Box = createSafeComponentLoader(UI_KIT_COMP, 'Box')
// ... 필요한 컴포넌트 추가

4. Hook 로더 정의

// src/uiKit/safeHookLoader.ts
import { createSafeHookLoader } from '@solapi/ui-kit/federation'

const UI_KIT_HOOKS = async () => {
  try {
    return await import('@solapi-frontend/ui-kit/hooks')
  } catch {
    return await import('@solapi/ui-kit')
  }
}

export const useSnackbar = createSafeHookLoader(UI_KIT_HOOKS, 'useSnackbar', {
  success: msg => console.log(`[snackbar] ${msg}`),
  error: msg => console.error(`[snackbar] ${msg}`),
  warning: msg => console.warn(`[snackbar] ${msg}`),
  info: msg => console.info(`[snackbar] ${msg}`)
})

export const useModal = createSafeHookLoader(UI_KIT_HOOKS, 'useModal', {
  modals: [],
  openModal: async () => false,
  closeModal: () => {},
  closeAllModals: () => {}
})

export const useConfirm = createSafeHookLoader(UI_KIT_HOOKS, 'useConfirm', {
  confirms: [],
  confirm: ({ message }) => Promise.resolve(window.confirm(message)),
  alert: ({ message }) => { window.alert(message); return Promise.resolve(true) },
  close: () => {}
})

5. MFA Mutation 설정

// src/uiKit/safeFunctionLoader.ts
const loadModule = async () => {
  try {
    return await import('@solapi-frontend/ui-kit/createMutationConfig')
  } catch {
    // 메인 entry에서 import하여 GlobalUIProvider와 동일한 store 인스턴스 공유
    return await import('@solapi/ui-kit')
  }
}

export const loadCreateMutationConfig = async () => {
  const mod = await loadModule()
  return mod?.createMutationConfig ?? null
}

export const loadConfigureMfa = async () => {
  const mod = await loadModule()
  return mod?.configureMfa ?? null
}

6. Error Boundary 감싸기 (선택)

Federation 모듈 로드 실패 시 앱 전체가 깨지는 것을 방지합니다.

// src/uiKit/FederationErrorBoundary.tsx
import { FederationErrorBoundary } from '@solapi/ui-kit/federation'

function App() {
  return (
    <FederationErrorBoundary
      onError={(error, errorInfo) => {
        // 에러 로깅 서비스로 전송
        console.error('Federation 모듈 로드 실패:', error)
      }}
      message="UI 모듈을 불러오지 못했습니다."
    >
      <GlobalUIProvider>
        {/* 앱 컨텐츠 */}
      </GlobalUIProvider>
    </FederationErrorBoundary>
  )
}

| Props | 타입 | 설명 | |-------|------|------| | fallback | React.ComponentType<{ error, onRetry, onReload }> | 커스텀 에러 UI | | onError | (error, errorInfo) => void | 에러 발생 시 콜백 | | onRetry | () => void | 재시도 버튼 클릭 시 콜백 | | showDetails | boolean | 에러 상세 정보 표시 여부 | | message | string | 커스텀 에러 메시지 |

7. 사용

import { Tabs, TextInput, Button, Box } from 'uiKit/safeCompLoader'
import { useSnackbar, useConfirm } from 'uiKit/safeHookLoader'

function MyPage() {
  const snackbar = useSnackbar()
  const { confirm } = useConfirm()

  const handleSave = async () => {
    const ok = await confirm({ title: '저장', message: '저장하시겠습니까?' })
    if (ok) snackbar.success('저장되었습니다!')
  }

  return (
    <Box padding={16}>
      <Tabs
        items={[{ label: 'Tab 1', value: '1' }, { label: 'Tab 2', value: '2' }]}
        value={tabValue}
        onChange={setTabValue}
      />
      <TextInput label="이름" placeholder="이름을 입력하세요" />
      <Button onClick={handleSave}>저장</Button>
    </Box>
  )
}

Federation이 정상이면 CDN에서 로드 (번들 크기 0), 장애 시 npm 패키지에서 자동 로드됩니다.

문서

| 문서 | 설명 | |------|------| | 시작하기 | 설치, 개발, 빌드 | | 아키텍처 | 패키지/모듈/프로젝트 구조, Provider 계층 | | 사용 가이드 | Federation + npm Fallback 상세 가이드, 마이그레이션 | | Federation API | createSafeProviderLoader, createSafeComponentLoader, createSafeHookLoader | | GlobalUIProvider | Props, Portal, MFA, 로컬 개발 설정 | | createMutationConfig | MFA 처리, Snackbar 연동, Federation 환경 사용법 | | 컴포넌트 추가 | 새 UI 컴포넌트/Hook 추가 가이드 | | 안티패턴 | 흔한 실수와 올바른 대안 |