Appearance
UI API
POS 플러그인에서 제공하는 UI 컴포넌트 API예요. 바코드 스캔 팝업과 입력·안내 모달을 제공해요.
import 방식
ui는 posPluginSdk의 프로퍼티가 아닌 독립 export예요.
ts
import { ui } from '@tossplace/pos-plugin-sdk';Types
ModalPageRequest
openModal에 전달하는 모달 구성이에요.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
title | string | O | 모달 제목 |
step | string | O | 모달을 구분하는 ID |
description | string | X | 제목 아래에 표시할 설명 |
cta.submit | ModalCta | O | 제출 버튼 |
cta.cancel | ModalCta | X | 취소 버튼 |
elements | Array<ModalInputElement|ModalDescriptionElement> | O | 모달에 표시할 요소. 배열 순서대로 표시돼요 |
onSubmit | (form: ModalForm) => Promise<T> | X | 제출 버튼을 누르면 실행돼요. 반환값이 ModalOpenResponse의 form으로 전달돼요. 에러가 발생하면 Alert이 표시되고 모달이 유지돼요. 생략하면 사용자가 입력한 값이 그대로 form으로 전달돼요. 자세한 동작은 onSubmit 동작을 참고해주세요 |
ModalForm은 Record<string, string | string[] | number | undefined>예요.
ModalCta
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
text | string | O | 버튼 문구 |
type | 'primary' | 'danger' | 'dark' | O | 버튼 스타일 |
ModalInputElement
사용자 입력을 받는 요소예요. 모든 입력 요소에 category: 'input'과 id를 넣어요.
agreement를 제외한 입력 요소는 아래 공통 필드를 가져요.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
label | string | O | 입력 요소 이름 |
required | boolean | O | 필수 입력 여부 |
errorMessage | string | X | 값을 넣으면 해당 입력 요소가 오류 상태로 표시돼요 |
text
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | 'text' | O | |
default | string | O | 기본값 |
placeholder | string | X | 입력 전 안내 문구 |
suffix | string | X | 입력값 뒤에 붙는 단위 문구 |
number
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | 'number' | O | |
default | number | O | 기본값 |
placeholder | string | X | 입력 전 안내 문구 |
suffix | string | X | 입력값 뒤에 붙는 단위 문구 |
password
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | 'password' | O | |
default | string | O | 기본값 |
placeholder | string | X | 입력 전 안내 문구 |
radio
하나를 선택해요. 선택된 항목의 values[].id가 string으로 반환돼요.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | 'radio' | O | |
default | string | O | 기본으로 선택할 values[].id |
values | { id: string; title: string; description?: string }[] | O | 선택지 |
checkbox
여러 개를 선택해요. 선택된 항목의 values[].id가 string[]로 반환돼요.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | 'checkbox' | O | |
default | string[] | O | 기본으로 선택할 values[].id 배열 |
values | { id: string; title: string; description?: string }[] | O | 선택지 |
agreement
약관 동의를 받아요. 동의한 약관의 agreements[].id가 string[]로 반환돼요. 공통 필드(label, required, errorMessage)가 없어요.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | 'agreement' | O | |
default | string[] | O | 기본으로 동의 처리할 agreements[].id 배열 |
agreements[].id | string | O | 약관 ID |
agreements[].title | string | O | 약관 제목 |
agreements[].required | boolean | O | 필수 약관 여부 |
agreements[].contents | string[] | O | 약관 본문 |
ModalDescriptionElement
안내를 표시하는 요소예요. 모든 설명 요소에 category: 'description'과 id를 넣어요.
type | 추가 필드 | 설명 |
|---|---|---|
'image' | url: string | 이미지를 표시해요 |
'text' | text: string, style: { weight: 'regular' | 'medium' | 'bold'; size: number } | 텍스트를 표시해요 |
'ordered-text' | text: string, subText: string, index: 1 ~ 9 | 번호가 붙은 텍스트를 표시해요 |
'qna' | question: string, answer: string | 질문과 답변을 표시해요 |
'horizontal-divider' | - | 가로 구분선을 표시해요 |
ModalOpenResponse
ts
{
event: 'SUBMITTED';
form: T; // onSubmit의 반환값. onSubmit이 없으면 입력값
} | {
event: 'CANCELLED' | 'CLOSED';
}| 필드 | 타입 | 설명 |
|---|---|---|
event | 'SUBMITTED' | 'CANCELLED' | 'CLOSED' | 모달 종료 결과. 사용자가 취소하거나 닫으면 'CANCELLED' 또는 'CLOSED'예요 |
form | T | onSubmit의 반환값이에요. onSubmit이 없으면 사용자가 입력한 값(ModalForm)이에요. event가 'SUBMITTED'일 때만 있어요 |
Methods
openBarcode
바코드 스캔 팝업을 표시해요.
ts
import { ui } from '@tossplace/pos-plugin-sdk';
const result = await ui.openBarcode({
productName: '토스 POS 플러그인', // 팝업 왼쪽 상단에 표시
});
if (result.result === 'SUCCESS') {
console.log('스캔된 바코드:', result.barcode);
} else {
console.log('사용자가 취소했어요');
}Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
productName | string | O | 팝업 왼쪽 상단에 표시할 이름 |
Response
ts
{
barcode: string; // 스캔된 바코드 값
result: 'SUCCESS';
} | {
result: 'CANCELLED'; // 사용자 취소
}| 필드 | 타입 | 설명 |
|---|---|---|
result | 'SUCCESS' | 'CANCELLED' | 스캔 결과. 사용자가 취소하면 'CANCELLED'예요 |
barcode | string | 스캔된 바코드 값. result가 'SUCCESS'일 때만 있어요 |
openModal
입력 요소와 안내 요소로 구성한 모달을 표시해요. 제출 버튼을 누르면 onSubmit이 실행되고, 성공하면 반환값과 함께 모달이 닫혀요. onSubmit에서 에러가 발생하면 Alert이 표시되고 모달은 닫히지 않아서, 사용자가 값을 고쳐 다시 제출할 수 있어요.
ts
import { ui } from '@tossplace/pos-plugin-sdk';
const result = await ui.openModal({
title: '회원 정보 입력',
step: 'member-info',
description: '포인트를 적립할 회원의 휴대폰 번호를 입력해주세요',
cta: {
cancel: { text: '취소', type: 'dark' },
submit: { text: '확인', type: 'primary' },
},
elements: [
{
category: 'input',
id: 'phone',
type: 'text',
label: '휴대폰 번호',
required: true,
default: '',
placeholder: '01012345678',
},
{
category: 'input',
id: 'terms',
type: 'agreement',
default: [],
agreements: [
{
id: 'privacy',
title: '개인정보 수집·이용 동의',
required: true,
contents: ['포인트 적립을 위해 휴대폰 번호를 수집해요.'],
},
],
},
],
onSubmit: async (form) => {
const phone = String(form.phone);
if (!/^01\d{8,9}$/.test(phone)) {
throw new Error('휴대폰 번호를 확인해주세요'); // Alert이 표시되고 모달은 닫히지 않아요
}
return { phone };
},
});
if (result.event === 'SUBMITTED') {
console.log('입력된 휴대폰 번호:', result.form.phone);
} else {
console.log('사용자가 모달을 닫았어요');
}onSubmit 동작
제출 버튼을 누르면 onSubmit이 입력값(form)을 받아 실행돼요. 결과에 따라 아래처럼 동작해요.
| 경우 | 모달 | openModal 응답 |
|---|---|---|
onSubmit이 값을 반환 | 닫혀요 | { event: 'SUBMITTED', form: 반환값 } |
onSubmit에서 에러 발생 | 닫히지 않아요. 에러 메시지가 Alert으로 표시돼요 | 아직 반환하지 않아요 |
onSubmit 생략 | 닫혀요 | { event: 'SUBMITTED', form: 입력값 } |
에러가 발생하면
위 예시에서 휴대폰 번호 형식이 맞지 않으면 throw new Error('휴대폰 번호를 확인해주세요')가 실행돼요. 이때 다음 순서로 동작해요.
- 에러의
message인 "휴대폰 번호를 확인해주세요"가 Alert으로 표시돼요. - 모달은 닫히지 않아요.
openModal도 응답을 반환하지 않고 기다려요. - 사용자가 값을 고쳐 제출 버튼을 다시 누르면
onSubmit이 다시 실행돼요. 이번에 값을 반환하면 모달이 닫히고openModal이SUBMITTED를 반환해요. - 사용자가 다시 제출하지 않고 취소하거나 닫으면
openModal이CANCELLED또는CLOSED를 반환해요.
입력값 검증이나 서버 저장처럼 실패했을 때 사용자가 다시 시도해야 하는 작업은 onSubmit 안에서 처리하고, 실패하면 사용자에게 보여줄 메시지와 함께 에러를 던지세요.
onSubmit이 없으면
onSubmit은 선택 항목이에요. 넣지 않거나 undefined를 넣으면 아래처럼 동작해요.
- 제출 버튼을 누르면 실행할 핸들러 없이 바로 모달이 닫혀요.
openModal은{ event: 'SUBMITTED', form: 입력값 }을 반환해요. 사용자가 입력한 값이ModalForm형태로 그대로 전달돼요.- 핸들러가 없으니 에러가 발생할 일도 없고, 제출 버튼을 누르면 항상 모달이 닫혀요.
별도 검증 없이 입력값만 받으면 되는 모달이라면 onSubmit 없이 쓸 수 있어요.
ts
import { ui } from '@tossplace/pos-plugin-sdk';
const result = await ui.openModal({
title: '메모 입력',
step: 'memo',
cta: {
submit: { text: '확인', type: 'primary' },
},
elements: [
{
category: 'input',
id: 'memo',
type: 'text',
label: '메모',
required: false,
default: '',
},
],
});
if (result.event === 'SUBMITTED') {
console.log('입력된 메모:', result.form.memo);
}모달마다 다른 step을 사용해주세요
onSubmit은 step 값을 기준으로 등록돼요. 같은 step으로 openModal을 다시 호출하면 이전에 등록한 onSubmit을 덮어쓰니, 모달마다 서로 다른 step을 넣어주세요.
Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
page | ModalPageRequest | O | 표시할 모달 구성 |
Response
Promise<ModalOpenResponse>를 반환해요.
openInputModal은 deprecated 됐어요
0.0.30부터 openInputModal은 deprecated 됐어요. 입력 모달이 필요하면 openModal을 사용해주세요.