@designbasekorea/figma-ui 0.6.8 → 0.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -2
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +41 -5
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +686 -272
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +825 -404
- package/dist/index.js.map +1 -1
- package/package.json +9 -6
package/dist/index.esm.js
CHANGED
|
@@ -1,11 +1,429 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { Button, Dropdown, Badge, Toggle, Modal, Logo, Toast, Input, Spinner, SegmentControl, Progressbar, RandomGradient } from '@designbasekorea/ui-wc/react';
|
|
1
|
+
import React, { createContext, useMemo, useContext, useRef, useState, useLayoutEffect, useEffect, useCallback, useId } from 'react';
|
|
2
|
+
import { Button, Dropdown, Badge, Toggle, Modal, ModalBody, Logo, Toast, Input, Spinner, SegmentControl, Progressbar, RandomGradient } from '@designbasekorea/ui-wc/react';
|
|
3
3
|
export * from '@designbasekorea/ui-wc/react';
|
|
4
4
|
export { Accordion, ActivityHeatmap, AdBanner, AiChat, AiChatList, Alert, AnimationBackground, AnimationText, AppBadge, AudioPlayer, Avatar, Backdrop, Badge, Banner, BottomNavigation, BottomSheet, Breadcrumbs, Button, Calendar, Card, Carousel, ChatComposer, ChatList, ChatMessage, ChatOrb, ChatRoom, ChatSuggestions, ChatTyping, ChatWelcome, ChatWidget, Checkbox, Chip, CodeBlock, ColorPicker, ColorSwatch, Confirm, Container, ContextMenu, CookieBanner, Countdown, CursorFollower, DatePicker, Divider, DownloadProgress, Drawer, Dropdown, Dropzone, EmailVerify, EmptyState, FileUploader, FloatingActionButton, Footer, Form, Gantt, Gradient, Grid, GridBackground, GridItem, Image, ImageList, ImagePlaceholder, Indicator, Input, Kanban, Label, Lightbox, List, Logo, MarkdownEditor, Marquee, Masonry, MenuItem, Modal, ModalBody, ModalFooter, ModalHeader, Navbar, OnboardingModal, OtpInput, PageHeader, Pagination, PhoneVerify, Popover, Progress, ProgressStep, Progressbar, Radio, RandomGradient, RangeSlider, Rating, Reorder, ResizablePanels, ScrollArea, SearchBar, Section, SectionAppDownload, SectionContact, SectionCta, SectionFaq, SectionFeature, SectionFeatureGrid, SectionHero, SectionLogoCloud, SectionPricing, SectionStats, SectionTestimonials, SegmentControl, Select, Share, Sidebar, Signature, Skeleton, Spinner, SplitView, Stack, Stat, Stepper, Table, Tabs, Testimonial, Textarea, TimePicker, Timeline, Toast, Toggle, Toolbar, Tooltip, TopBanner, Tutorial, TwoFactor, VideoPlayer, YouTubePlayer, useContextMenu } from '@designbasekorea/ui-wc/react';
|
|
5
5
|
import { ChevronDownIcon, AppWindowIcon, YoutubeIcon, InstagramIcon, FigmaIcon, MailIcon, ExternalLinkIcon, TranslateIcon, MoreHorizontalIcon, CloseIcon, CircleCheckFilledIcon, ResizableIcon, GripVerticalIcon, ChevronRightIcon } from '@designbasekorea/icons';
|
|
6
|
+
import { DEFAULT_LICENSE_MESSAGE_TYPES } from '@designbasekorea/figma-license-core';
|
|
7
|
+
export { DEFAULT_LICENSE_MESSAGE_TYPES } from '@designbasekorea/figma-license-core';
|
|
6
8
|
|
|
7
9
|
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
|
|
8
10
|
|
|
11
|
+
const FIGMA_UI_TRANSLATIONS = {
|
|
12
|
+
ko: {
|
|
13
|
+
close: '닫기',
|
|
14
|
+
back: '뒤로가기',
|
|
15
|
+
officialWebsite: '공식 웹사이트',
|
|
16
|
+
youtube: '유튜브',
|
|
17
|
+
instagram: '인스타그램',
|
|
18
|
+
figmaCommunity: '피그마 커뮤니티',
|
|
19
|
+
contact: '문의하기',
|
|
20
|
+
languageSettings: '언어 설정',
|
|
21
|
+
languageSettingsDescription: '플러그인에 표시할 언어를 선택하세요.',
|
|
22
|
+
'language.korean': '한국어',
|
|
23
|
+
'language.english': 'English',
|
|
24
|
+
'language.japanese': '日本語',
|
|
25
|
+
unlimitedUsage: '무제한 사용',
|
|
26
|
+
proUser: '프로',
|
|
27
|
+
usingFree: '무료 사용',
|
|
28
|
+
free: '무료',
|
|
29
|
+
trialPlan: '체험판',
|
|
30
|
+
planSuffix: '플랜',
|
|
31
|
+
usageDetails: '사용량 상세',
|
|
32
|
+
dailyUsage: '오늘 사용량',
|
|
33
|
+
usedToday: '오늘 사용',
|
|
34
|
+
remainingToday: '오늘 남은 사용량',
|
|
35
|
+
remainingUsage: '오늘 남은 사용량',
|
|
36
|
+
managePlan: '플랜 관리',
|
|
37
|
+
upgradePlan: '플랜 업그레이드',
|
|
38
|
+
remainingShort: '남음',
|
|
39
|
+
usageCountCaption: '오늘 사용',
|
|
40
|
+
remainingCopy: '{{count}}회 남음 · 매일 리셋',
|
|
41
|
+
usageUnavailable: '사용량 제한이 없습니다',
|
|
42
|
+
unlimitedUsageTooltip: '모든 기능을 제한 없이 사용할 수 있습니다',
|
|
43
|
+
betaUsageDescription: '베타 기간에는 사용량 제한이 적용되지 않습니다',
|
|
44
|
+
perDay: '일',
|
|
45
|
+
resetsDaily: '매일 리셋',
|
|
46
|
+
donationPrompt: '이 플러그인이 유용했나요?',
|
|
47
|
+
betaStatus: 'BETA',
|
|
48
|
+
'donation.buy_me_a_coffee': '커피 한 잔 사기',
|
|
49
|
+
'donation.prompt': '도움이 되었다면 커피 한 잔 사주세요!',
|
|
50
|
+
'form.license_key': '라이선스 키',
|
|
51
|
+
'form.license_placeholder': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
52
|
+
'form.submit': '제출',
|
|
53
|
+
'form.verifying': '확인 중...',
|
|
54
|
+
'license.youtube_membership': 'YouTube 멤버십',
|
|
55
|
+
'license.pro_account': '프로 계정',
|
|
56
|
+
'license.upgrade_to_pro': '프로로 업그레이드',
|
|
57
|
+
'license.all_features_available': '모든 기능을 사용할 수 있습니다.',
|
|
58
|
+
'license.youtube_membership_description': 'YouTube 멤버십에 가입하면 Designbase 플러그인을 무제한으로 사용할 수 있습니다.',
|
|
59
|
+
'license.purchase_for_unlimited': '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.',
|
|
60
|
+
'license.usage_unlimited': '사용 횟수 제한 없음',
|
|
61
|
+
'license.usage_daily': '오늘 남은 횟수 {{remaining}}/{{limit}}',
|
|
62
|
+
'license.usage_weekly': '이번 주 남은 횟수 {{remaining}}/{{limit}}',
|
|
63
|
+
'license.usage_monthly': '이번 달 남은 횟수 {{remaining}}/{{limit}}',
|
|
64
|
+
'license.usage_generic': '남은 횟수 {{remaining}}/{{limit}}',
|
|
65
|
+
'license.activated': '라이선스 활성화됨',
|
|
66
|
+
'license.activations_remaining': '활성',
|
|
67
|
+
'license.spots_remaining': '자리 남음',
|
|
68
|
+
'license.deactivating': '비활성화 중...',
|
|
69
|
+
'license.deactivate': '라이선스 비활성화',
|
|
70
|
+
'license.designbase_account': '디자인베이스 계정',
|
|
71
|
+
'license.designbase_account_hint': 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.',
|
|
72
|
+
'license.authenticating': '인증 중...',
|
|
73
|
+
'license.login_with_designbase': '디자인베이스로 로그인',
|
|
74
|
+
'license.purchase_membership': '멤버십 안내',
|
|
75
|
+
'license.manage_account': '계정·멤버십 관리',
|
|
76
|
+
'license.enter_key': '라이선스 키 입력',
|
|
77
|
+
'license.key': '라이선스 키',
|
|
78
|
+
'license.submit': '활성화',
|
|
79
|
+
'license.verifying': '확인 중...',
|
|
80
|
+
'license.enter_from_email': '이메일로 받은 라이선스 키를 입력하세요.',
|
|
81
|
+
'license.enter_from_youtube': '멤버 전용 커뮤니티에서 받은 키를 입력하세요.',
|
|
82
|
+
'license.help_link': '라이선스·결제 도움말',
|
|
83
|
+
'license.youtube_membership_howto': '이용 방법',
|
|
84
|
+
'license.youtube_membership_step_1': 'Designbase YouTube 채널 멤버십에 가입합니다.',
|
|
85
|
+
'license.youtube_membership_step_2': '멤버 전용 커뮤니티에서 이번 달 키를 복사합니다.',
|
|
86
|
+
'license.youtube_membership_step_3': '아래 입력창에 키를 붙여 넣고 활성화합니다.',
|
|
87
|
+
'license.youtube_membership_join': '멤버십 가입',
|
|
88
|
+
'license.youtube_membership_guide': '안내보기',
|
|
89
|
+
'license.all_plugins': '모든 플러그인',
|
|
90
|
+
'license.source_youtube_membership': 'YouTube 멤버십',
|
|
91
|
+
'license.source_purchase': '구매 라이선스',
|
|
92
|
+
'license.status_active': '활성',
|
|
93
|
+
'license.status_inactive': '라이선스 확인 실패',
|
|
94
|
+
'license.status_label': '라이선스 상태',
|
|
95
|
+
'license.key_label': '라이선스 키',
|
|
96
|
+
'license.hide_key': '숨기기',
|
|
97
|
+
'license.reveal_key': '보기',
|
|
98
|
+
'license.source': '출처',
|
|
99
|
+
'license.access': '접근 범위',
|
|
100
|
+
'license.expires': '만료일',
|
|
101
|
+
'license.last_checked': '최근 확인',
|
|
102
|
+
'payment.license_key_label': '라이선스 키',
|
|
103
|
+
'payment.activations_remaining': '활성',
|
|
104
|
+
'payment.spots_remaining': '자리 남음',
|
|
105
|
+
'payment.deactivating': '비활성화 중...',
|
|
106
|
+
'payment.deactivate_license': '라이선스 비활성화',
|
|
107
|
+
lifetimeAccess: '평생 이용',
|
|
108
|
+
perYear: '년',
|
|
109
|
+
perMonth: '월',
|
|
110
|
+
monthlyBilling: '월간 결제',
|
|
111
|
+
yearlyBilling: '연간 결제',
|
|
112
|
+
oneTimePaymentLifetime: '평생 이용을 위한 일회성 결제입니다.',
|
|
113
|
+
feature: '기능',
|
|
114
|
+
freePrice: '$0',
|
|
115
|
+
pro: '프로',
|
|
116
|
+
recommended: '추천',
|
|
117
|
+
'pricing.usage_limit': '사용 제한',
|
|
118
|
+
'pricing.daily_limit': '일일 제한',
|
|
119
|
+
'pricing.unlimited': '무제한',
|
|
120
|
+
'pricing.all_topics': '모든 주제 사용',
|
|
121
|
+
'pricing.max_selection': '최대 선택 제한',
|
|
122
|
+
'pricing.max_selection_free': '최대 5개',
|
|
123
|
+
'pricing.max_selection_pro': '최대 30개',
|
|
124
|
+
'pricing.dummy_count': '더미 개수',
|
|
125
|
+
'pricing.dummy_count_free': '1,400개',
|
|
126
|
+
'pricing.dummy_count_pro': '4,400개 이상',
|
|
127
|
+
'pricing.custom_number': '커스텀 숫자 사용',
|
|
128
|
+
'pricing.discount_suffix': '절약',
|
|
129
|
+
'settings.modal_title': '목록 변경',
|
|
130
|
+
'settings.modal_description': '드래그하여 순서를 변경하거나, 토글하여 카테고리를 숨길 수 있습니다.',
|
|
131
|
+
'settings.reset': '초기화',
|
|
132
|
+
'settings.cancel': '취소',
|
|
133
|
+
'settings.save': '저장',
|
|
134
|
+
'progress.working': '작업 중',
|
|
135
|
+
'progress.processing': '처리 중...',
|
|
136
|
+
'progress.completed': '완료되었습니다',
|
|
137
|
+
'progress.stop': '중지',
|
|
138
|
+
'progress.confirm': '확인',
|
|
139
|
+
'banner.upgrade_title': '프로로 업그레이드하세요',
|
|
140
|
+
'banner.upgrade_description': '무제한 기능을 사용하고 더 많은 혜택을 누리세요.',
|
|
141
|
+
'banner.upgrade_button': '지금 업그레이드',
|
|
142
|
+
loading: '불러오는 중',
|
|
143
|
+
},
|
|
144
|
+
en: {
|
|
145
|
+
close: 'Close',
|
|
146
|
+
back: 'Back',
|
|
147
|
+
officialWebsite: 'Official website',
|
|
148
|
+
youtube: 'YouTube',
|
|
149
|
+
instagram: 'Instagram',
|
|
150
|
+
figmaCommunity: 'Figma Community',
|
|
151
|
+
contact: 'Contact',
|
|
152
|
+
languageSettings: 'Language settings',
|
|
153
|
+
languageSettingsDescription: 'Choose the language to display in the plugin.',
|
|
154
|
+
'language.korean': 'Korean',
|
|
155
|
+
'language.english': 'English',
|
|
156
|
+
'language.japanese': 'Japanese',
|
|
157
|
+
unlimitedUsage: 'Unlimited use',
|
|
158
|
+
proUser: 'Pro',
|
|
159
|
+
usingFree: 'Free use',
|
|
160
|
+
free: 'Free',
|
|
161
|
+
trialPlan: 'Trial',
|
|
162
|
+
planSuffix: 'plan',
|
|
163
|
+
usageDetails: 'Usage details',
|
|
164
|
+
dailyUsage: "Today's usage",
|
|
165
|
+
usedToday: 'Used today',
|
|
166
|
+
remainingToday: 'Remaining today',
|
|
167
|
+
remainingUsage: 'Remaining today',
|
|
168
|
+
managePlan: 'Manage plan',
|
|
169
|
+
upgradePlan: 'Upgrade plan',
|
|
170
|
+
remainingShort: 'left',
|
|
171
|
+
usageCountCaption: 'Used today',
|
|
172
|
+
remainingCopy: '{{count}} remaining · resets daily',
|
|
173
|
+
usageUnavailable: 'No usage limit',
|
|
174
|
+
unlimitedUsageTooltip: 'Use every feature without limits',
|
|
175
|
+
betaUsageDescription: 'Usage limits are not applied during the beta period',
|
|
176
|
+
perDay: 'day',
|
|
177
|
+
resetsDaily: 'Resets daily',
|
|
178
|
+
donationPrompt: 'Is this plugin useful?',
|
|
179
|
+
betaStatus: 'BETA',
|
|
180
|
+
'donation.buy_me_a_coffee': 'Buy me a coffee',
|
|
181
|
+
'donation.prompt': 'If this helped, buy me a coffee!',
|
|
182
|
+
'form.license_key': 'License key',
|
|
183
|
+
'form.license_placeholder': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
184
|
+
'form.submit': 'Activate',
|
|
185
|
+
'form.verifying': 'Verifying...',
|
|
186
|
+
'license.youtube_membership': 'YouTube Membership',
|
|
187
|
+
'license.pro_account': 'Pro account',
|
|
188
|
+
'license.upgrade_to_pro': 'Upgrade to Pro',
|
|
189
|
+
'license.all_features_available': 'All features are available.',
|
|
190
|
+
'license.youtube_membership_description': 'Join YouTube Membership to use Designbase plugins without limits.',
|
|
191
|
+
'license.purchase_for_unlimited': 'Get unlimited access with a Designbase membership or license.',
|
|
192
|
+
'license.usage_unlimited': 'Unlimited usage',
|
|
193
|
+
'license.usage_daily': '{{remaining}}/{{limit}} remaining today',
|
|
194
|
+
'license.usage_weekly': '{{remaining}}/{{limit}} remaining this week',
|
|
195
|
+
'license.usage_monthly': '{{remaining}}/{{limit}} remaining this month',
|
|
196
|
+
'license.usage_generic': '{{remaining}}/{{limit}} remaining',
|
|
197
|
+
'license.activated': 'License activated',
|
|
198
|
+
'license.activations_remaining': 'activations',
|
|
199
|
+
'license.spots_remaining': 'spots remaining',
|
|
200
|
+
'license.deactivating': 'Deactivating...',
|
|
201
|
+
'license.deactivate': 'Deactivate license',
|
|
202
|
+
'license.designbase_account': 'Designbase account',
|
|
203
|
+
'license.designbase_account_hint': 'Sign in with your WordPress account or purchase a membership to activate the plugin automatically.',
|
|
204
|
+
'license.authenticating': 'Authenticating...',
|
|
205
|
+
'license.login_with_designbase': 'Sign in with Designbase',
|
|
206
|
+
'license.purchase_membership': 'Membership details',
|
|
207
|
+
'license.manage_account': 'Manage account · membership',
|
|
208
|
+
'license.enter_key': 'Enter license key',
|
|
209
|
+
'license.key': 'License key',
|
|
210
|
+
'license.submit': 'Activate',
|
|
211
|
+
'license.verifying': 'Verifying...',
|
|
212
|
+
'license.enter_from_email': 'Enter the license key you received by email.',
|
|
213
|
+
'license.enter_from_youtube': 'Enter the key from the members-only community.',
|
|
214
|
+
'license.help_link': 'License · payment help',
|
|
215
|
+
'license.youtube_membership_howto': 'How to use',
|
|
216
|
+
'license.youtube_membership_step_1': 'Join the Designbase YouTube channel membership.',
|
|
217
|
+
'license.youtube_membership_step_2': 'Copy this month’s key from the members-only community.',
|
|
218
|
+
'license.youtube_membership_step_3': 'Paste the key below and activate it.',
|
|
219
|
+
'license.youtube_membership_join': 'Join membership',
|
|
220
|
+
'license.youtube_membership_guide': 'View guide',
|
|
221
|
+
'license.all_plugins': 'All plugins',
|
|
222
|
+
'license.source_youtube_membership': 'YouTube Membership',
|
|
223
|
+
'license.source_purchase': 'Purchased license',
|
|
224
|
+
'license.status_active': 'Active',
|
|
225
|
+
'license.status_inactive': 'License check failed',
|
|
226
|
+
'license.status_label': 'License status',
|
|
227
|
+
'license.key_label': 'License key',
|
|
228
|
+
'license.hide_key': 'Hide',
|
|
229
|
+
'license.reveal_key': 'Show',
|
|
230
|
+
'license.source': 'Source',
|
|
231
|
+
'license.access': 'Access',
|
|
232
|
+
'license.expires': 'Expires',
|
|
233
|
+
'license.last_checked': 'Last checked',
|
|
234
|
+
'payment.license_key_label': 'License key',
|
|
235
|
+
'payment.activations_remaining': 'activations',
|
|
236
|
+
'payment.spots_remaining': 'spots remaining',
|
|
237
|
+
'payment.deactivating': 'Deactivating...',
|
|
238
|
+
'payment.deactivate_license': 'Deactivate license',
|
|
239
|
+
lifetimeAccess: 'Lifetime access',
|
|
240
|
+
perYear: 'year',
|
|
241
|
+
perMonth: 'month',
|
|
242
|
+
monthlyBilling: 'Monthly billing',
|
|
243
|
+
yearlyBilling: 'Yearly billing',
|
|
244
|
+
oneTimePaymentLifetime: 'One-time payment for lifetime access.',
|
|
245
|
+
feature: 'Feature',
|
|
246
|
+
freePrice: '$0',
|
|
247
|
+
pro: 'Pro',
|
|
248
|
+
recommended: 'Recommended',
|
|
249
|
+
'pricing.usage_limit': 'Usage limit',
|
|
250
|
+
'pricing.daily_limit': 'Daily limit',
|
|
251
|
+
'pricing.unlimited': 'Unlimited',
|
|
252
|
+
'pricing.all_topics': 'All topics',
|
|
253
|
+
'pricing.max_selection': 'Selection limit',
|
|
254
|
+
'pricing.max_selection_free': 'Up to 5',
|
|
255
|
+
'pricing.max_selection_pro': 'Up to 30',
|
|
256
|
+
'pricing.dummy_count': 'Dummy count',
|
|
257
|
+
'pricing.dummy_count_free': '1,400',
|
|
258
|
+
'pricing.dummy_count_pro': '4,400+',
|
|
259
|
+
'pricing.custom_number': 'Custom numbers',
|
|
260
|
+
'pricing.discount_suffix': 'saved',
|
|
261
|
+
'settings.modal_title': 'Change list',
|
|
262
|
+
'settings.modal_description': 'Drag to reorder or toggle a category to hide it.',
|
|
263
|
+
'settings.reset': 'Reset',
|
|
264
|
+
'settings.cancel': 'Cancel',
|
|
265
|
+
'settings.save': 'Save',
|
|
266
|
+
'progress.working': 'Working',
|
|
267
|
+
'progress.processing': 'Processing...',
|
|
268
|
+
'progress.completed': 'Completed',
|
|
269
|
+
'progress.stop': 'Stop',
|
|
270
|
+
'progress.confirm': 'Done',
|
|
271
|
+
'banner.upgrade_title': 'Upgrade to Pro',
|
|
272
|
+
'banner.upgrade_description': 'Unlock unlimited features and more benefits.',
|
|
273
|
+
'banner.upgrade_button': 'Upgrade now',
|
|
274
|
+
loading: 'Loading',
|
|
275
|
+
},
|
|
276
|
+
ja: {
|
|
277
|
+
close: '閉じる',
|
|
278
|
+
back: '戻る',
|
|
279
|
+
officialWebsite: '公式ウェブサイト',
|
|
280
|
+
youtube: 'YouTube',
|
|
281
|
+
instagram: 'Instagram',
|
|
282
|
+
figmaCommunity: 'Figmaコミュニティ',
|
|
283
|
+
contact: 'お問い合わせ',
|
|
284
|
+
languageSettings: '言語設定',
|
|
285
|
+
languageSettingsDescription: 'プラグインに表示する言語を選択してください。',
|
|
286
|
+
'language.korean': '韓国語',
|
|
287
|
+
'language.english': '英語',
|
|
288
|
+
'language.japanese': '日本語',
|
|
289
|
+
unlimitedUsage: '無制限で使用',
|
|
290
|
+
proUser: 'Pro',
|
|
291
|
+
usingFree: '無料で使用中',
|
|
292
|
+
free: '無料',
|
|
293
|
+
trialPlan: 'トライアル',
|
|
294
|
+
planSuffix: 'プラン',
|
|
295
|
+
usageDetails: '使用量の詳細',
|
|
296
|
+
dailyUsage: '今日の使用量',
|
|
297
|
+
usedToday: '今日の使用',
|
|
298
|
+
remainingToday: '今日の残り使用量',
|
|
299
|
+
remainingUsage: '今日の残り使用量',
|
|
300
|
+
managePlan: 'プランを管理',
|
|
301
|
+
upgradePlan: 'プランをアップグレード',
|
|
302
|
+
remainingShort: '残り',
|
|
303
|
+
usageCountCaption: '今日の使用',
|
|
304
|
+
remainingCopy: '{{count}}回残り · 毎日リセット',
|
|
305
|
+
usageUnavailable: '使用制限はありません',
|
|
306
|
+
unlimitedUsageTooltip: 'すべての機能を無制限で使用できます',
|
|
307
|
+
betaUsageDescription: 'ベータ期間中は使用制限がありません',
|
|
308
|
+
perDay: '日',
|
|
309
|
+
resetsDaily: '毎日リセット',
|
|
310
|
+
donationPrompt: 'このプラグインは役に立ちましたか?',
|
|
311
|
+
betaStatus: 'BETA',
|
|
312
|
+
'donation.buy_me_a_coffee': 'コーヒーを一杯おごる',
|
|
313
|
+
'donation.prompt': '役に立ったらコーヒーを一杯おごってください!',
|
|
314
|
+
'form.license_key': 'ライセンスキー',
|
|
315
|
+
'form.license_placeholder': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
316
|
+
'form.submit': '有効化',
|
|
317
|
+
'form.verifying': '確認中...',
|
|
318
|
+
'license.youtube_membership': 'YouTubeメンバーシップ',
|
|
319
|
+
'license.pro_account': 'Proアカウント',
|
|
320
|
+
'license.upgrade_to_pro': 'Proにアップグレード',
|
|
321
|
+
'license.all_features_available': 'すべての機能を使用できます。',
|
|
322
|
+
'license.youtube_membership_description': 'YouTubeメンバーシップに参加すると、Designbaseプラグインを無制限で使用できます。',
|
|
323
|
+
'license.purchase_for_unlimited': 'Designbaseのメンバーシップまたはライセンスで無制限に利用できます。',
|
|
324
|
+
'license.usage_unlimited': '使用回数の制限なし',
|
|
325
|
+
'license.usage_daily': '今日の残り {{remaining}}/{{limit}}回',
|
|
326
|
+
'license.usage_weekly': '今週の残り {{remaining}}/{{limit}}回',
|
|
327
|
+
'license.usage_monthly': '今月の残り {{remaining}}/{{limit}}回',
|
|
328
|
+
'license.usage_generic': '残り {{remaining}}/{{limit}}回',
|
|
329
|
+
'license.activated': 'ライセンス有効化済み',
|
|
330
|
+
'license.activations_remaining': '有効化',
|
|
331
|
+
'license.spots_remaining': '枠残り',
|
|
332
|
+
'license.deactivating': '無効化中...',
|
|
333
|
+
'license.deactivate': 'ライセンスを無効化',
|
|
334
|
+
'license.designbase_account': 'Designbaseアカウント',
|
|
335
|
+
'license.designbase_account_hint': 'WordPressアカウントでサインインするか、メンバーシップを購入するとプラグインが自動的に有効化されます。',
|
|
336
|
+
'license.authenticating': '認証中...',
|
|
337
|
+
'license.login_with_designbase': 'Designbaseでサインイン',
|
|
338
|
+
'license.purchase_membership': 'メンバーシップの詳細',
|
|
339
|
+
'license.manage_account': 'アカウント・メンバーシップを管理',
|
|
340
|
+
'license.enter_key': 'ライセンスキーを入力',
|
|
341
|
+
'license.key': 'ライセンスキー',
|
|
342
|
+
'license.submit': '有効化',
|
|
343
|
+
'license.verifying': '確認中...',
|
|
344
|
+
'license.enter_from_email': 'メールで受け取ったライセンスキーを入力してください。',
|
|
345
|
+
'license.enter_from_youtube': 'メンバー限定コミュニティのキーを入力してください。',
|
|
346
|
+
'license.help_link': 'ライセンス・支払いヘルプ',
|
|
347
|
+
'license.youtube_membership_howto': '利用方法',
|
|
348
|
+
'license.youtube_membership_step_1': 'Designbase YouTubeチャンネルのメンバーシップに参加します。',
|
|
349
|
+
'license.youtube_membership_step_2': 'メンバー限定コミュニティから今月のキーをコピーします。',
|
|
350
|
+
'license.youtube_membership_step_3': '下の入力欄にキーを貼り付けて有効化します。',
|
|
351
|
+
'license.youtube_membership_join': 'メンバーシップに参加',
|
|
352
|
+
'license.youtube_membership_guide': 'ガイドを見る',
|
|
353
|
+
'license.all_plugins': 'すべてのプラグイン',
|
|
354
|
+
'license.source_youtube_membership': 'YouTubeメンバーシップ',
|
|
355
|
+
'license.source_purchase': '購入ライセンス',
|
|
356
|
+
'license.status_active': '有効',
|
|
357
|
+
'license.status_inactive': 'ライセンス確認に失敗しました',
|
|
358
|
+
'license.status_label': 'ライセンス状態',
|
|
359
|
+
'license.key_label': 'ライセンスキー',
|
|
360
|
+
'license.hide_key': '隠す',
|
|
361
|
+
'license.reveal_key': '表示',
|
|
362
|
+
'license.source': '取得元',
|
|
363
|
+
'license.access': 'アクセス範囲',
|
|
364
|
+
'license.expires': '有効期限',
|
|
365
|
+
'license.last_checked': '最終確認',
|
|
366
|
+
'payment.license_key_label': 'ライセンスキー',
|
|
367
|
+
'payment.activations_remaining': '有効化',
|
|
368
|
+
'payment.spots_remaining': '枠残り',
|
|
369
|
+
'payment.deactivating': '無効化中...',
|
|
370
|
+
'payment.deactivate_license': 'ライセンスを無効化',
|
|
371
|
+
lifetimeAccess: '生涯利用',
|
|
372
|
+
perYear: '年',
|
|
373
|
+
perMonth: '月',
|
|
374
|
+
monthlyBilling: '月払い',
|
|
375
|
+
yearlyBilling: '年払い',
|
|
376
|
+
oneTimePaymentLifetime: '生涯利用のための一括払いです。',
|
|
377
|
+
feature: '機能',
|
|
378
|
+
freePrice: '$0',
|
|
379
|
+
pro: 'Pro',
|
|
380
|
+
recommended: 'おすすめ',
|
|
381
|
+
'pricing.usage_limit': '使用制限',
|
|
382
|
+
'pricing.daily_limit': '1日の制限',
|
|
383
|
+
'pricing.unlimited': '無制限',
|
|
384
|
+
'pricing.all_topics': 'すべてのトピック',
|
|
385
|
+
'pricing.max_selection': '選択上限',
|
|
386
|
+
'pricing.max_selection_free': '最大5個',
|
|
387
|
+
'pricing.max_selection_pro': '最大30個',
|
|
388
|
+
'pricing.dummy_count': 'ダミー数',
|
|
389
|
+
'pricing.dummy_count_free': '1,400個',
|
|
390
|
+
'pricing.dummy_count_pro': '4,400個以上',
|
|
391
|
+
'pricing.custom_number': 'カスタム数値',
|
|
392
|
+
'pricing.discount_suffix': '割引',
|
|
393
|
+
'settings.modal_title': 'リストを変更',
|
|
394
|
+
'settings.modal_description': 'ドラッグして並べ替えるか、トグルでカテゴリを非表示にできます。',
|
|
395
|
+
'settings.reset': 'リセット',
|
|
396
|
+
'settings.cancel': 'キャンセル',
|
|
397
|
+
'settings.save': '保存',
|
|
398
|
+
'progress.working': '処理中',
|
|
399
|
+
'progress.processing': '処理しています...',
|
|
400
|
+
'progress.completed': '完了しました',
|
|
401
|
+
'progress.stop': '停止',
|
|
402
|
+
'progress.confirm': '完了',
|
|
403
|
+
'banner.upgrade_title': 'Proにアップグレード',
|
|
404
|
+
'banner.upgrade_description': '無制限の機能とさらに多くの特典を利用できます。',
|
|
405
|
+
'banner.upgrade_button': '今すぐアップグレード',
|
|
406
|
+
loading: '読み込み中',
|
|
407
|
+
},
|
|
408
|
+
};
|
|
409
|
+
function normalizeFigmaUiLocale(locale) {
|
|
410
|
+
const normalized = (locale || '').toLowerCase().split(/[-_]/)[0];
|
|
411
|
+
if (normalized === 'en' || normalized === 'ja')
|
|
412
|
+
return normalized;
|
|
413
|
+
return 'ko';
|
|
414
|
+
}
|
|
415
|
+
function createFigmaUiTranslator(locale = 'ko', parentT) {
|
|
416
|
+
const normalizedLocale = normalizeFigmaUiLocale(locale);
|
|
417
|
+
const translations = FIGMA_UI_TRANSLATIONS[normalizedLocale];
|
|
418
|
+
return (key, values) => {
|
|
419
|
+
const parentValue = parentT?.(key, values);
|
|
420
|
+
if (parentValue && parentValue !== key) {
|
|
421
|
+
return interpolateText(parentValue, values);
|
|
422
|
+
}
|
|
423
|
+
const value = translations[key] ?? FIGMA_UI_TRANSLATIONS.ko[key] ?? key;
|
|
424
|
+
return interpolateText(value, values);
|
|
425
|
+
};
|
|
426
|
+
}
|
|
9
427
|
function interpolateText(template, values) {
|
|
10
428
|
if (!values)
|
|
11
429
|
return template;
|
|
@@ -32,11 +450,34 @@ function resolveText(t, input, fallback) {
|
|
|
32
450
|
return input.key;
|
|
33
451
|
}
|
|
34
452
|
|
|
453
|
+
const defaultContextValue = {
|
|
454
|
+
locale: 'ko',
|
|
455
|
+
t: createFigmaUiTranslator('ko'),
|
|
456
|
+
};
|
|
457
|
+
const FigmaUiI18nContext = createContext(defaultContextValue);
|
|
458
|
+
const FigmaUiI18nProvider = ({ locale = 'ko', t: parentT, children, }) => {
|
|
459
|
+
const normalizedLocale = normalizeFigmaUiLocale(locale);
|
|
460
|
+
const value = useMemo(() => ({
|
|
461
|
+
locale: normalizedLocale,
|
|
462
|
+
parentT,
|
|
463
|
+
t: createFigmaUiTranslator(normalizedLocale, parentT),
|
|
464
|
+
}), [normalizedLocale, parentT]);
|
|
465
|
+
return React.createElement(FigmaUiI18nContext.Provider, { value: value }, children);
|
|
466
|
+
};
|
|
467
|
+
function useFigmaUiI18n(localeOverride, tOverride) {
|
|
468
|
+
const context = useContext(FigmaUiI18nContext);
|
|
469
|
+
const locale = normalizeFigmaUiLocale(localeOverride ?? context.locale);
|
|
470
|
+
const parentT = tOverride ?? context.parentT;
|
|
471
|
+
const t = useMemo(() => createFigmaUiTranslator(locale, parentT), [locale, parentT]);
|
|
472
|
+
return { locale, parentT, t };
|
|
473
|
+
}
|
|
474
|
+
|
|
35
475
|
const DONATION_ICON_NAMES = {
|
|
36
476
|
heart: 'star-filled',
|
|
37
477
|
coffee: 'cart',
|
|
38
478
|
};
|
|
39
|
-
const DonationBadge = ({ donationUrl = 'https://buymeacoffee.com/designbase', text = { key: 'donation.buy_me_a_coffee' }, iconType = 'heart', size = 's', variant = 'tertiary', fullWidth = false, iconOnly = false, disabled = false, showPrompt = false, promptText = { key: 'donation.prompt' }, className, onClick, t }) => {
|
|
479
|
+
const DonationBadge = ({ donationUrl = 'https://buymeacoffee.com/designbase', text = { key: 'donation.buy_me_a_coffee' }, iconType = 'heart', size = 's', variant = 'tertiary', fullWidth = false, iconOnly = false, disabled = false, showPrompt = false, promptText = { key: 'donation.prompt' }, className, onClick, t, locale, }) => {
|
|
480
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
40
481
|
const handleClick = () => {
|
|
41
482
|
if (onClick) {
|
|
42
483
|
onClick();
|
|
@@ -45,8 +486,8 @@ const DonationBadge = ({ donationUrl = 'https://buymeacoffee.com/designbase', te
|
|
|
45
486
|
window.open(donationUrl, '_blank', 'noopener,noreferrer');
|
|
46
487
|
}
|
|
47
488
|
};
|
|
48
|
-
const displayText = resolveText(
|
|
49
|
-
const displayPromptText = resolveText(
|
|
489
|
+
const displayText = resolveText(translate, text, 'Buy me a coffee');
|
|
490
|
+
const displayPromptText = resolveText(translate, promptText, '도움이 되었다면 커피 한 잔 사주세요!');
|
|
50
491
|
const buttonSize = size;
|
|
51
492
|
return (React.createElement("div", { className: clsx('designbase-figma-donation-badge-container', className) },
|
|
52
493
|
showPrompt && !iconOnly && (React.createElement("div", { className: "designbase-figma-donation-badge__prompt" }, displayPromptText)),
|
|
@@ -97,13 +538,14 @@ const FigmaHeader = ({ children, actions = [], searchBar, sticky = true, classNa
|
|
|
97
538
|
};
|
|
98
539
|
FigmaHeader.displayName = 'FigmaHeader';
|
|
99
540
|
|
|
100
|
-
const FigmaPageHead = ({ onBack, title, description, actions = [], moreActions = [], className, t }) => {
|
|
541
|
+
const FigmaPageHead = ({ onBack, title, description, actions = [], moreActions = [], className, t, locale, }) => {
|
|
542
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
101
543
|
const classes = clsx('designbase-figma-page-head', className);
|
|
102
|
-
const displayTitle = resolveText(
|
|
103
|
-
const displayDescription = description ? resolveText(
|
|
544
|
+
const displayTitle = resolveText(translate, title);
|
|
545
|
+
const displayDescription = description ? resolveText(translate, description) : undefined;
|
|
104
546
|
const dropdownItems = moreActions.map((action) => ({
|
|
105
547
|
id: action.id,
|
|
106
|
-
label: resolveText(
|
|
548
|
+
label: resolveText(translate, action.label),
|
|
107
549
|
}));
|
|
108
550
|
const handleDropdownChange = (event) => {
|
|
109
551
|
const actionId = event.detail?.id ?? event.detail?.value;
|
|
@@ -112,7 +554,7 @@ const FigmaPageHead = ({ onBack, title, description, actions = [], moreActions =
|
|
|
112
554
|
};
|
|
113
555
|
return (React.createElement("div", { className: classes },
|
|
114
556
|
React.createElement("div", { className: "designbase-figma-page-head__left" },
|
|
115
|
-
React.createElement(Button, { variant: "tertiary", size: "s", iconOnly: true, startIcon: "chevron-left", onPress: onBack, "aria-label":
|
|
557
|
+
React.createElement(Button, { variant: "tertiary", size: "s", iconOnly: true, startIcon: "chevron-left", onPress: onBack, "aria-label": translate('back') }),
|
|
116
558
|
React.createElement("div", { className: "designbase-figma-page-head__titles" },
|
|
117
559
|
React.createElement("h2", null, displayTitle),
|
|
118
560
|
displayDescription && React.createElement("p", null, displayDescription))),
|
|
@@ -122,7 +564,8 @@ const FigmaPageHead = ({ onBack, title, description, actions = [], moreActions =
|
|
|
122
564
|
};
|
|
123
565
|
FigmaPageHead.displayName = 'FigmaPageHead';
|
|
124
566
|
|
|
125
|
-
const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom, isEnabled = true, onToggle, className, enableScrollNavigation = false, headerHeight = 94, onActiveSectionChange, t, collapsible = false, defaultCollapsed = false, onCollapseChange, badge, overflowVisible = false, }) => {
|
|
567
|
+
const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom, isEnabled = true, onToggle, className, enableScrollNavigation = false, headerHeight = 94, onActiveSectionChange, t, locale, collapsible = false, defaultCollapsed = false, onCollapseChange, badge, overflowVisible = false, }) => {
|
|
568
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
126
569
|
const sectionRef = useRef(null);
|
|
127
570
|
const clipRef = useRef(null);
|
|
128
571
|
const innerRef = useRef(null);
|
|
@@ -242,7 +685,7 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
|
|
|
242
685
|
React.createElement("div", { className: "designbase-figma-section__title-area" },
|
|
243
686
|
React.createElement("h2", { className: "designbase-figma-section__title" },
|
|
244
687
|
typeof title === 'string' || (typeof title === 'object' && 'key' in title)
|
|
245
|
-
? resolveText(
|
|
688
|
+
? resolveText(translate, title)
|
|
246
689
|
: title,
|
|
247
690
|
badge && (React.createElement(Badge, { variant: "secondary", size: "s" }, badge)))),
|
|
248
691
|
React.createElement("div", { className: "designbase-figma-section__controls", onClick: (e) => e.stopPropagation() },
|
|
@@ -395,63 +838,39 @@ const FigmaSidebar = ({ categories, categoryGroups = {}, categoryLabels = {}, ac
|
|
|
395
838
|
};
|
|
396
839
|
FigmaSidebar.displayName = 'FigmaSidebar';
|
|
397
840
|
|
|
398
|
-
let useTranslation$2 = null;
|
|
399
|
-
try {
|
|
400
|
-
const reactI18next = require('react-i18next');
|
|
401
|
-
useTranslation$2 = reactI18next.useTranslation;
|
|
402
|
-
}
|
|
403
|
-
catch (e) {
|
|
404
|
-
}
|
|
405
841
|
const DEFAULT_LANGUAGES$1 = [
|
|
406
|
-
{ code: 'ko', label: '
|
|
407
|
-
{ code: 'en', label: '
|
|
408
|
-
{ code: 'ja', label: '
|
|
842
|
+
{ code: 'ko', label: { key: 'language.korean' } },
|
|
843
|
+
{ code: 'en', label: { key: 'language.english' } },
|
|
844
|
+
{ code: 'ja', label: { key: 'language.japanese' } },
|
|
409
845
|
];
|
|
410
|
-
const
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
};
|
|
418
|
-
return translations[key] || key;
|
|
419
|
-
};
|
|
420
|
-
const LanguageSettingsModal = ({ isOpen, onClose, languages = DEFAULT_LANGUAGES$1, currentLanguage, onLanguageChange, title, description, className, t = defaultT$2, }) => {
|
|
421
|
-
const i18n = useTranslation$2 ? useTranslation$2().i18n : null;
|
|
422
|
-
const activeLanguage = currentLanguage || i18n?.language || languages[0]?.code;
|
|
423
|
-
const translate = (key, fallback) => {
|
|
424
|
-
const translated = t(key);
|
|
425
|
-
return translated && translated !== key ? translated : fallback;
|
|
426
|
-
};
|
|
427
|
-
const handleSelect = (languageCode) => {
|
|
428
|
-
if (i18n) {
|
|
429
|
-
i18n.changeLanguage(languageCode);
|
|
846
|
+
const LanguageSettingsModal = ({ isOpen, onClose, languages = DEFAULT_LANGUAGES$1, currentLanguage, onLanguageChange, title, description, className, t, }) => {
|
|
847
|
+
const { t: translate } = useFigmaUiI18n(currentLanguage, t);
|
|
848
|
+
const resolvedCurrentLanguage = currentLanguage || languages[0]?.code;
|
|
849
|
+
const [pendingLanguage, setPendingLanguage] = useState(resolvedCurrentLanguage);
|
|
850
|
+
useEffect(() => {
|
|
851
|
+
if (isOpen) {
|
|
852
|
+
setPendingLanguage(resolvedCurrentLanguage);
|
|
430
853
|
}
|
|
854
|
+
}, [isOpen, resolvedCurrentLanguage]);
|
|
855
|
+
const handleSelect = useCallback((languageCode) => {
|
|
856
|
+
setPendingLanguage(languageCode);
|
|
431
857
|
onLanguageChange?.(languageCode);
|
|
432
858
|
onClose();
|
|
433
|
-
};
|
|
434
|
-
return (React.createElement(Modal, { isOpen: isOpen, onClose: onClose, title: title || translate('languageSettings'
|
|
435
|
-
React.createElement(
|
|
436
|
-
React.createElement("p", { className: "designbase-figma-language-settings-modal__description" }, description || translate('languageSettingsDescription'
|
|
437
|
-
React.createElement("ul", { className: "designbase-figma-language-settings-modal__list", role: "listbox", "aria-label": translate('languageSettings'
|
|
438
|
-
const label = resolveText(
|
|
439
|
-
const isActive = language.code ===
|
|
859
|
+
}, [onClose, onLanguageChange]);
|
|
860
|
+
return (React.createElement(Modal, { isOpen: isOpen, onClose: onClose, title: title || translate('languageSettings'), size: "s", className: clsx('designbase-figma-language-settings-modal', className) },
|
|
861
|
+
React.createElement(ModalBody, { className: "designbase-figma-language-settings-modal__content" },
|
|
862
|
+
React.createElement("p", { className: "designbase-figma-language-settings-modal__description" }, description || translate('languageSettingsDescription')),
|
|
863
|
+
React.createElement("ul", { className: "designbase-figma-language-settings-modal__list", role: "listbox", "aria-label": translate('languageSettings') }, languages.map((language) => {
|
|
864
|
+
const label = resolveText(translate, language.label, language.code.toUpperCase());
|
|
865
|
+
const isActive = language.code === pendingLanguage;
|
|
440
866
|
return (React.createElement("li", { key: language.code, role: "presentation" },
|
|
441
|
-
React.createElement(
|
|
867
|
+
React.createElement(Button, { type: "button", variant: "tertiary", size: "m", fullWidth: true, className: clsx('designbase-figma-language-settings-modal__option', { 'designbase-figma-language-settings-modal__option--active': isActive }), role: "option", "aria-selected": isActive, onPress: () => handleSelect(language.code) },
|
|
442
868
|
React.createElement("span", { className: "designbase-figma-language-settings-modal__option-label" }, label),
|
|
443
869
|
React.createElement("span", { className: "designbase-figma-language-settings-modal__option-indicator", "aria-hidden": "true" }))));
|
|
444
870
|
})))));
|
|
445
871
|
};
|
|
446
872
|
LanguageSettingsModal.displayName = 'LanguageSettingsModal';
|
|
447
873
|
|
|
448
|
-
let useTranslation$1 = null;
|
|
449
|
-
try {
|
|
450
|
-
const reactI18next = require('react-i18next');
|
|
451
|
-
useTranslation$1 = reactI18next.useTranslation;
|
|
452
|
-
}
|
|
453
|
-
catch (e) {
|
|
454
|
-
}
|
|
455
874
|
const defaultLinks = [
|
|
456
875
|
{
|
|
457
876
|
name: 'officialWebsite',
|
|
@@ -479,32 +898,20 @@ const defaultLinks = [
|
|
|
479
898
|
icon: React.createElement(MailIcon, { size: 20 }),
|
|
480
899
|
},
|
|
481
900
|
];
|
|
482
|
-
const defaultTranslations$1 = {
|
|
483
|
-
officialWebsite: '공식 웹사이트',
|
|
484
|
-
youtube: '유튜브',
|
|
485
|
-
instagram: '인스타그램',
|
|
486
|
-
figmaCommunity: '피그마 커뮤니티',
|
|
487
|
-
contact: '문의하기',
|
|
488
|
-
languageSettings: '언어 설정',
|
|
489
|
-
};
|
|
490
|
-
const defaultT$1 = (key) => defaultTranslations$1[key] || key;
|
|
491
901
|
const defaultLanguages = [
|
|
492
|
-
{ code: 'ko', label: '
|
|
493
|
-
{ code: 'en', label: '
|
|
494
|
-
{ code: 'ja', label: '
|
|
902
|
+
{ code: 'ko', label: { key: 'language.korean' } },
|
|
903
|
+
{ code: 'en', label: { key: 'language.english' } },
|
|
904
|
+
{ code: 'ja', label: { key: 'language.japanese' } },
|
|
495
905
|
];
|
|
496
|
-
const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase', logoSize = 'xs', links = defaultLinks, position = 'top-left', className, t
|
|
906
|
+
const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase', logoSize = 'xs', links = defaultLinks, position = 'top-left', className, t, showLanguageSelector = true, languages = defaultLanguages, currentLanguage, onLanguageChange, }) => {
|
|
497
907
|
const [isOpen, setIsOpen] = useState(false);
|
|
498
908
|
const [isLanguageModalOpen, setIsLanguageModalOpen] = useState(false);
|
|
499
|
-
const
|
|
909
|
+
const [internalLanguage, setInternalLanguage] = useState();
|
|
910
|
+
const { t: translate } = useFigmaUiI18n(currentLanguage ?? internalLanguage, t);
|
|
500
911
|
const rootRef = useRef(null);
|
|
501
912
|
const triggerRef = useRef(null);
|
|
502
913
|
const menuId = `designbase-figma-logo-menu-${useId().replace(/:/g, '')}`;
|
|
503
|
-
const activeLanguage = currentLanguage
|
|
504
|
-
const translate = (key, fallback) => {
|
|
505
|
-
const translated = t(key);
|
|
506
|
-
return translated && translated !== key ? translated : fallback;
|
|
507
|
-
};
|
|
914
|
+
const activeLanguage = currentLanguage ?? internalLanguage ?? languages[0]?.code;
|
|
508
915
|
useEffect(() => {
|
|
509
916
|
if (!isOpen) {
|
|
510
917
|
return undefined;
|
|
@@ -540,8 +947,8 @@ const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase'
|
|
|
540
947
|
setIsLanguageModalOpen(true);
|
|
541
948
|
};
|
|
542
949
|
const handleLanguageChange = (languageCode) => {
|
|
543
|
-
if (
|
|
544
|
-
|
|
950
|
+
if (currentLanguage === undefined) {
|
|
951
|
+
setInternalLanguage(languageCode);
|
|
545
952
|
}
|
|
546
953
|
onLanguageChange?.(languageCode);
|
|
547
954
|
};
|
|
@@ -557,14 +964,14 @@ const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase'
|
|
|
557
964
|
links.map((link, index) => (React.createElement("li", { key: index, className: "designbase-figma-logo-dropdown__item", role: "none" },
|
|
558
965
|
React.createElement("button", { type: "button", className: "designbase-figma-logo-dropdown__link", role: "menuitem", onClick: () => handleLinkClick(link.url) },
|
|
559
966
|
link.icon && (React.createElement("span", { className: "designbase-figma-logo-dropdown__icon" }, link.icon)),
|
|
560
|
-
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" },
|
|
967
|
+
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" }, translate(link.name)),
|
|
561
968
|
React.createElement(ExternalLinkIcon, { size: 16, className: "designbase-figma-logo-dropdown__arrow" }))))),
|
|
562
969
|
showLanguageSelector && (React.createElement("li", { className: "designbase-figma-logo-dropdown__item designbase-figma-logo-dropdown__language-item", role: "none" },
|
|
563
970
|
React.createElement("button", { type: "button", className: "designbase-figma-logo-dropdown__link", role: "menuitem", onClick: handleLanguageSettingsClick },
|
|
564
971
|
React.createElement("span", { className: "designbase-figma-logo-dropdown__icon" },
|
|
565
972
|
React.createElement(TranslateIcon, { size: 20, "aria-hidden": "true" })),
|
|
566
|
-
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" }, translate('languageSettings'
|
|
567
|
-
showLanguageSelector && (React.createElement(LanguageSettingsModal, { isOpen: isLanguageModalOpen, onClose: () => setIsLanguageModalOpen(false), languages: languages, currentLanguage: activeLanguage, onLanguageChange: handleLanguageChange, t:
|
|
973
|
+
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" }, translate('languageSettings'))))))),
|
|
974
|
+
showLanguageSelector && (React.createElement(LanguageSettingsModal, { isOpen: isLanguageModalOpen, onClose: () => setIsLanguageModalOpen(false), languages: languages, currentLanguage: activeLanguage, onLanguageChange: handleLanguageChange, t: translate }))));
|
|
568
975
|
};
|
|
569
976
|
LogoDropdown.displayName = 'LogoDropdown';
|
|
570
977
|
|
|
@@ -572,7 +979,8 @@ const fallbackText = (t, key, fallback) => {
|
|
|
572
979
|
const translated = t?.(key);
|
|
573
980
|
return translated && translated !== key ? translated : fallback;
|
|
574
981
|
};
|
|
575
|
-
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, t, className, }) => {
|
|
982
|
+
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, t, locale, className, }) => {
|
|
983
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
576
984
|
const [isOpen, setIsOpen] = useState(false);
|
|
577
985
|
const rootRef = useRef(null);
|
|
578
986
|
const triggerRef = useRef(null);
|
|
@@ -586,25 +994,25 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20,
|
|
|
586
994
|
const usedPercent = hasDailyLimit ? Math.round((used / limit) * 100) : 0;
|
|
587
995
|
const hasControl = showUsage || showPlan;
|
|
588
996
|
const planLabel = isPaid
|
|
589
|
-
? fallbackText(
|
|
997
|
+
? fallbackText(translate, 'proUser', '프로')
|
|
590
998
|
: isBeta
|
|
591
|
-
? fallbackText(
|
|
999
|
+
? fallbackText(translate, 'betaStatus', 'BETA')
|
|
592
1000
|
: paymentStatus === 'TRIAL'
|
|
593
|
-
? fallbackText(
|
|
594
|
-
: fallbackText(
|
|
1001
|
+
? fallbackText(translate, 'trialPlan', '체험판')
|
|
1002
|
+
: fallbackText(translate, 'free', '무료');
|
|
595
1003
|
const planTitle = isBeta
|
|
596
1004
|
? planLabel
|
|
597
|
-
: `${planLabel} ${fallbackText(
|
|
1005
|
+
: `${planLabel} ${fallbackText(translate, 'planSuffix', '플랜')}`;
|
|
598
1006
|
const triggerLabel = isPaid
|
|
599
|
-
? `${planLabel}, ${fallbackText(
|
|
1007
|
+
? `${planLabel}, ${fallbackText(translate, 'unlimitedUsage', '무제한 사용 가능')}`
|
|
600
1008
|
: isBeta
|
|
601
1009
|
? planLabel
|
|
602
1010
|
: hasDailyLimit
|
|
603
|
-
? `${remaining}/${limit} ${fallbackText(
|
|
1011
|
+
? `${remaining}/${limit} ${fallbackText(translate, 'remainingShort', '남음')}`
|
|
604
1012
|
: planLabel;
|
|
605
1013
|
const upgradeLabel = isPaid
|
|
606
|
-
? fallbackText(
|
|
607
|
-
: fallbackText(
|
|
1014
|
+
? fallbackText(translate, 'managePlan', '플랜 관리')
|
|
1015
|
+
: fallbackText(translate, 'upgradePlan', '플랜 업그레이드');
|
|
608
1016
|
useEffect(() => {
|
|
609
1017
|
if (!isOpen)
|
|
610
1018
|
return undefined;
|
|
@@ -639,7 +1047,7 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20,
|
|
|
639
1047
|
'designbase-figma-usage-status--loading': isLoading,
|
|
640
1048
|
}, className) },
|
|
641
1049
|
React.createElement("div", { className: "designbase-figma-usage-status__control" },
|
|
642
|
-
showUsage && (React.createElement("button", { ref: triggerRef, type: "button", className: "designbase-figma-usage-status__trigger", "aria-expanded": isOpen, "aria-controls": popoverId, "aria-haspopup": "dialog", "aria-label": isLoading ? fallbackText(
|
|
1050
|
+
showUsage && (React.createElement("button", { ref: triggerRef, type: "button", className: "designbase-figma-usage-status__trigger", "aria-expanded": isOpen, "aria-controls": popoverId, "aria-haspopup": "dialog", "aria-label": isLoading ? fallbackText(translate, 'loading', '불러오는 중') : triggerLabel, disabled: isLoading, onClick: togglePopover }, isLoading ? (React.createElement("span", { className: "designbase-figma-usage-status__skeleton", "aria-hidden": "true" })) : isPaid ? (React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E")) : hasDailyLimit ? (React.createElement(React.Fragment, null,
|
|
643
1051
|
React.createElement("span", { className: "designbase-figma-usage-status__mini-progress", "aria-hidden": "true" },
|
|
644
1052
|
React.createElement("span", { style: { width: `${usedPercent}%` } })),
|
|
645
1053
|
React.createElement("span", { className: "designbase-figma-usage-status__usage-value" },
|
|
@@ -648,53 +1056,27 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20,
|
|
|
648
1056
|
"/",
|
|
649
1057
|
limit)))) : (React.createElement("span", { className: "designbase-figma-usage-status__plan-label" }, planLabel)))),
|
|
650
1058
|
showPlan && !isLoading && (React.createElement("button", { type: "button", className: "designbase-figma-usage-status__plan-badge", "aria-expanded": isOpen, "aria-controls": popoverId, "aria-haspopup": "dialog", "aria-label": planTitle, onClick: togglePopover }, planLabel))),
|
|
651
|
-
isOpen && (React.createElement("div", { id: popoverId, className: "designbase-figma-usage-status__popover", role: "dialog", "aria-label": fallbackText(
|
|
1059
|
+
isOpen && (React.createElement("div", { id: popoverId, className: "designbase-figma-usage-status__popover", role: "dialog", "aria-label": fallbackText(translate, 'usageDetails', '사용량 상세') },
|
|
652
1060
|
React.createElement("div", { className: "designbase-figma-usage-status__popover-header" },
|
|
653
1061
|
React.createElement("span", { className: "designbase-figma-usage-status__plan-title" }, planTitle),
|
|
654
1062
|
!isBeta && (React.createElement(Button, { className: "designbase-figma-usage-status__upgrade", variant: isPaid ? 'secondary' : 'primary', size: "s", endIcon: "chevron-right", onPress: handleManageClick }, upgradeLabel))),
|
|
655
1063
|
isPaid ? (React.createElement("div", { className: "designbase-figma-usage-status__unlimited-copy" },
|
|
656
1064
|
React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E"),
|
|
657
|
-
React.createElement("span", null, fallbackText(
|
|
1065
|
+
React.createElement("span", null, fallbackText(translate, 'unlimitedUsageTooltip', '모든 기능을 제한 없이 사용할 수 있습니다')))) : isBeta ? (React.createElement("p", { className: "designbase-figma-usage-status__note" }, fallbackText(translate, 'betaUsageDescription', '베타 기간에는 사용량 제한이 적용되지 않습니다'))) : hasDailyLimit ? (React.createElement("div", { className: "designbase-figma-usage-status__usage-detail" },
|
|
658
1066
|
React.createElement("div", { className: "designbase-figma-usage-status__usage-summary" },
|
|
659
1067
|
React.createElement("strong", { className: "designbase-figma-usage-status__usage-count" },
|
|
660
1068
|
used,
|
|
661
1069
|
React.createElement("span", { className: "designbase-figma-usage-status__usage-divider" }, "/"),
|
|
662
1070
|
limit),
|
|
663
|
-
React.createElement("span", { className: "designbase-figma-usage-status__usage-caption" }, fallbackText(
|
|
664
|
-
React.createElement("div", { className: "designbase-figma-usage-status__progress", role: "progressbar", "aria-label": fallbackText(
|
|
1071
|
+
React.createElement("span", { className: "designbase-figma-usage-status__usage-caption" }, fallbackText(translate, 'usageCountCaption', '오늘 사용'))),
|
|
1072
|
+
React.createElement("div", { className: "designbase-figma-usage-status__progress", role: "progressbar", "aria-label": fallbackText(translate, 'usageCountCaption', '오늘 사용'), "aria-valuemin": 0, "aria-valuemax": limit, "aria-valuenow": used, "aria-valuetext": `${used} / ${limit}` },
|
|
665
1073
|
React.createElement("span", { style: { width: `${usedPercent}%` } })),
|
|
666
|
-
React.createElement("p", { className: "designbase-figma-usage-status__remaining-copy" }, resolveText(
|
|
1074
|
+
React.createElement("p", { className: "designbase-figma-usage-status__remaining-copy" }, resolveText(translate, { key: 'remainingCopy', values: { count: remaining } }, `${remaining}회 남음 · 매일 리셋`)))) : (React.createElement("p", { className: "designbase-figma-usage-status__note" }, fallbackText(translate, 'usageUnavailable', '사용량 제한이 없습니다')))))));
|
|
667
1075
|
};
|
|
668
1076
|
UsageStatusPopover.displayName = 'UsageStatusPopover';
|
|
669
1077
|
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
proUser: '프로',
|
|
673
|
-
free: '무료',
|
|
674
|
-
trialPlan: '체험판',
|
|
675
|
-
planSuffix: '플랜',
|
|
676
|
-
usageDetails: '사용량 상세',
|
|
677
|
-
dailyUsage: '오늘 사용량',
|
|
678
|
-
usedToday: '오늘 사용',
|
|
679
|
-
remainingToday: '오늘 남은 사용량',
|
|
680
|
-
remainingUsage: '오늘 남은 사용량',
|
|
681
|
-
managePlan: '플랜 관리',
|
|
682
|
-
upgradePlan: '플랜 업그레이드',
|
|
683
|
-
remainingShort: '남음',
|
|
684
|
-
usageCountCaption: '오늘 사용',
|
|
685
|
-
remainingCopy: '{{count}}회 남음 · 매일 리셋',
|
|
686
|
-
usageUnavailable: '사용량 제한이 없습니다',
|
|
687
|
-
betaUsageDescription: '베타 기간에는 사용량 제한이 적용되지 않습니다',
|
|
688
|
-
perDay: '일',
|
|
689
|
-
resetsDaily: '매일 리셋',
|
|
690
|
-
donationPrompt: '이 플러그인이 유용했나요?',
|
|
691
|
-
betaStatus: 'BETA',
|
|
692
|
-
};
|
|
693
|
-
const defaultT = (key, values) => {
|
|
694
|
-
const template = defaultTranslations[key] || key;
|
|
695
|
-
return interpolateText(template, values);
|
|
696
|
-
};
|
|
697
|
-
const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount = 0, isLoading = false, showPaymentStatus = true, showUsageInfo = true, maxDailyUsage = 20, showPaymentBadge = true, showDonation = true, donationUrl = 'https://buymeacoffee.com/designbase', donationText = 'Buy me a coffee', showDonationText = true, donationPromptText, showLanguageSelector = true, currentLanguage = 'ko', languages, onLanguageChange, logoSrc, logoAlt = 'DesignBase', logoType = 'designbase', logoSize = 'xs', logoLinks, className, t = defaultT, children, }) => {
|
|
1078
|
+
const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount = 0, isLoading = false, showPaymentStatus = true, showUsageInfo = true, maxDailyUsage = 20, showPaymentBadge = true, showDonation = true, donationUrl = 'https://buymeacoffee.com/designbase', donationText = { key: 'donation.buy_me_a_coffee' }, showDonationText = true, donationPromptText, showLanguageSelector = true, currentLanguage = 'ko', languages, onLanguageChange, logoSrc, logoAlt = 'DesignBase', logoType = 'designbase', logoSize = 'xs', logoLinks, className, t, children, }) => {
|
|
1079
|
+
const { t: translate } = useFigmaUiI18n(currentLanguage, t);
|
|
698
1080
|
const resolvedShowUsageInfo = showPaymentStatus && showUsageInfo;
|
|
699
1081
|
const resolvedShowPaymentBadge = showPaymentStatus && showPaymentBadge;
|
|
700
1082
|
const resolvedLicensePageClick = paymentStatus === 'BETA' ? undefined : onLicensePageClick;
|
|
@@ -705,10 +1087,10 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
705
1087
|
return (React.createElement("footer", { className: classes },
|
|
706
1088
|
React.createElement("div", { className: "designbase-figma-footer__wrap" },
|
|
707
1089
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
708
|
-
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, languages: languages, currentLanguage: currentLanguage, showLanguageSelector: showLanguageSelector, onLanguageChange: onLanguageChange, t:
|
|
1090
|
+
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, languages: languages, currentLanguage: currentLanguage, showLanguageSelector: showLanguageSelector, onLanguageChange: onLanguageChange, t: translate })),
|
|
709
1091
|
React.createElement("div", { className: "designbase-figma-footer__right" },
|
|
710
|
-
(resolvedShowUsageInfo || resolvedShowPaymentBadge) && (React.createElement(UsageStatusPopover, { paymentStatus: paymentStatus, usageCount: usageCount, maxDailyUsage: maxDailyUsage, showUsage: resolvedShowUsageInfo, showPlan: resolvedShowPaymentBadge, isLoading: isLoading, onLicensePageClick: resolvedLicensePageClick, t:
|
|
711
|
-
showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t:
|
|
1092
|
+
(resolvedShowUsageInfo || resolvedShowPaymentBadge) && (React.createElement(UsageStatusPopover, { paymentStatus: paymentStatus, usageCount: usageCount, maxDailyUsage: maxDailyUsage, showUsage: resolvedShowUsageInfo, showPlan: resolvedShowPaymentBadge, isLoading: isLoading, onLicensePageClick: resolvedLicensePageClick, t: translate })),
|
|
1093
|
+
showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t: translate })))),
|
|
712
1094
|
children));
|
|
713
1095
|
};
|
|
714
1096
|
FigmaFooter.displayName = 'FigmaFooter';
|
|
@@ -784,7 +1166,8 @@ const useFigmaToast = () => {
|
|
|
784
1166
|
FigmaToastProvider.displayName = 'FigmaToastProvider';
|
|
785
1167
|
FigmaToast.displayName = 'FigmaToast';
|
|
786
1168
|
|
|
787
|
-
const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = false, value = '', onValueChange, label = { key: 'form.license_key' }, placeholder = { key: 'form.license_placeholder' }, submitText = { key: 'form.submit' }, submittingText = { key: 'form.verifying' }, helperText, className, t }) => {
|
|
1169
|
+
const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = false, value = '', onValueChange, label = { key: 'form.license_key' }, placeholder = { key: 'form.license_placeholder' }, submitText = { key: 'form.submit' }, submittingText = { key: 'form.verifying' }, helperText, className, t, locale, }) => {
|
|
1170
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
788
1171
|
const [inputValue, setInputValue] = useState(value);
|
|
789
1172
|
useEffect(() => {
|
|
790
1173
|
setInputValue(value);
|
|
@@ -797,11 +1180,11 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
797
1180
|
setInputValue(value);
|
|
798
1181
|
onValueChange?.(value);
|
|
799
1182
|
};
|
|
800
|
-
const displayLabel = resolveText(
|
|
801
|
-
const displayPlaceholder = resolveText(
|
|
802
|
-
const displaySubmitText = resolveText(
|
|
803
|
-
const displaySubmittingText = resolveText(
|
|
804
|
-
const displayHelperText = helperText ? resolveText(
|
|
1183
|
+
const displayLabel = resolveText(translate, label, 'License Key');
|
|
1184
|
+
const displayPlaceholder = resolveText(translate, placeholder, 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
|
|
1185
|
+
const displaySubmitText = resolveText(translate, submitText, 'Submit');
|
|
1186
|
+
const displaySubmittingText = resolveText(translate, submittingText, 'Verifying...');
|
|
1187
|
+
const displayHelperText = helperText ? resolveText(translate, helperText, '') : undefined;
|
|
805
1188
|
return (React.createElement("form", { className: `designbase-figma-form-with-submit ${className || ''}`, onSubmit: handleSubmit },
|
|
806
1189
|
React.createElement("div", { className: "designbase-figma-form-with-submit__field" },
|
|
807
1190
|
React.createElement("label", { className: "designbase-figma-form-with-submit__label" }, displayLabel),
|
|
@@ -815,7 +1198,8 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
815
1198
|
};
|
|
816
1199
|
FormWithSubmit.displayName = 'FormWithSubmit';
|
|
817
1200
|
|
|
818
|
-
const InteractionFeedback = ({ status = 'default', message, statusMessage, leftContent, rightAction, visible = true, className, t }) => {
|
|
1201
|
+
const InteractionFeedback = ({ status = 'default', message, statusMessage, leftContent, rightAction, visible = true, className, t, locale, }) => {
|
|
1202
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
819
1203
|
const feedbackClasses = clsx('designbase-figma-interaction', `designbase-figma-interaction--${status}`, {
|
|
820
1204
|
'designbase-figma-interaction--visible': visible,
|
|
821
1205
|
}, className);
|
|
@@ -824,38 +1208,28 @@ const InteractionFeedback = ({ status = 'default', message, statusMessage, leftC
|
|
|
824
1208
|
return (React.createElement("div", { className: feedbackClasses },
|
|
825
1209
|
React.createElement("div", { className: "designbase-figma-interaction__content" },
|
|
826
1210
|
React.createElement("div", { className: "designbase-figma-interaction__left" }, leftContent || (React.createElement("div", { className: "designbase-figma-interaction__message" },
|
|
827
|
-
status === 'loading' && (React.createElement(Spinner, { size: "s", type: "circular", label:
|
|
828
|
-
(message || status === 'loading') && (React.createElement("span", { className: "designbase-figma-interaction__text" }, resolveText(
|
|
829
|
-
statusMessage && (React.createElement("span", { className: "designbase-figma-interaction__status-text" }, resolveText(
|
|
1211
|
+
status === 'loading' && (React.createElement(Spinner, { size: "s", type: "circular", label: translate('loading'), showLabel: false })),
|
|
1212
|
+
(message || status === 'loading') && (React.createElement("span", { className: "designbase-figma-interaction__text" }, resolveText(translate, message || { key: 'loading' }))),
|
|
1213
|
+
statusMessage && (React.createElement("span", { className: "designbase-figma-interaction__status-text" }, resolveText(translate, statusMessage)))))),
|
|
830
1214
|
rightAction && (React.createElement("div", { className: "designbase-figma-interaction__right" }, rightAction)))));
|
|
831
1215
|
};
|
|
832
1216
|
InteractionFeedback.displayName = 'InteractionFeedback';
|
|
833
1217
|
|
|
834
|
-
let useTranslation = null;
|
|
835
|
-
try {
|
|
836
|
-
const reactI18next = require('react-i18next');
|
|
837
|
-
useTranslation = reactI18next.useTranslation;
|
|
838
|
-
}
|
|
839
|
-
catch (e) {
|
|
840
|
-
}
|
|
841
1218
|
const DEFAULT_LANGUAGES = [
|
|
842
1219
|
{ code: 'ko', label: 'KO' },
|
|
843
1220
|
{ code: 'en', label: 'EN' },
|
|
844
1221
|
];
|
|
845
1222
|
const LanguageSelector = ({ currentLanguage, languages = DEFAULT_LANGUAGES, onLanguageChange, size = 's', className, t }) => {
|
|
846
|
-
const
|
|
847
|
-
const activeLanguage = currentLanguage ||
|
|
1223
|
+
const { locale, t: translate } = useFigmaUiI18n(currentLanguage, t);
|
|
1224
|
+
const activeLanguage = currentLanguage || locale;
|
|
848
1225
|
const handleLanguageChange = (languageCode) => {
|
|
849
|
-
if (i18n) {
|
|
850
|
-
i18n.changeLanguage(languageCode);
|
|
851
|
-
}
|
|
852
1226
|
if (onLanguageChange) {
|
|
853
1227
|
onLanguageChange(languageCode);
|
|
854
1228
|
}
|
|
855
1229
|
};
|
|
856
1230
|
const segmentOptions = languages.map((language) => ({
|
|
857
1231
|
value: language.code,
|
|
858
|
-
label: resolveText(
|
|
1232
|
+
label: resolveText(translate, language.label, language.code.toUpperCase()),
|
|
859
1233
|
disabled: false,
|
|
860
1234
|
}));
|
|
861
1235
|
return (React.createElement("div", { className: `designbase-figma-language-selector ${className || ''}` },
|
|
@@ -887,25 +1261,26 @@ function openExternalUrl(url) {
|
|
|
887
1261
|
}
|
|
888
1262
|
}
|
|
889
1263
|
|
|
890
|
-
const LicenseOffer = ({ joinUrl, guideUrl, membershipUrl, t, className, }) => {
|
|
1264
|
+
const LicenseOffer = ({ joinUrl, guideUrl, membershipUrl, t, locale, className, }) => {
|
|
1265
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
891
1266
|
const titleId = `designbase-license-offer-title-${useId().replace(/:/g, '')}`;
|
|
892
1267
|
const resolvedJoinUrl = joinUrl || membershipUrl;
|
|
893
1268
|
const steps = [
|
|
894
|
-
resolveText(
|
|
895
|
-
resolveText(
|
|
896
|
-
resolveText(
|
|
1269
|
+
resolveText(translate, { key: 'license.youtube_membership_step_1' }, 'Designbase YouTube 채널 멤버십에 가입합니다.'),
|
|
1270
|
+
resolveText(translate, { key: 'license.youtube_membership_step_2' }, '멤버 전용 커뮤니티에서 이번 달 키를 복사합니다.'),
|
|
1271
|
+
resolveText(translate, { key: 'license.youtube_membership_step_3' }, '아래 입력창에 키를 붙여 넣고 활성화합니다.'),
|
|
897
1272
|
];
|
|
898
1273
|
return (React.createElement("section", { className: `designbase-figma-license-offer ${className || ''}`, "aria-labelledby": titleId },
|
|
899
|
-
React.createElement("h3", { id: titleId, className: "designbase-figma-license-offer__title" }, resolveText(
|
|
1274
|
+
React.createElement("h3", { id: titleId, className: "designbase-figma-license-offer__title" }, resolveText(translate, { key: 'license.youtube_membership_howto' }, '이용 방법')),
|
|
900
1275
|
React.createElement("ol", { className: "designbase-figma-license-offer__steps" }, steps.map((step, index) => (React.createElement("li", { key: index },
|
|
901
1276
|
React.createElement("span", { className: "designbase-figma-license-offer__step-index", "aria-hidden": "true" },
|
|
902
1277
|
index + 1,
|
|
903
1278
|
"."),
|
|
904
1279
|
React.createElement("span", null, step))))),
|
|
905
1280
|
(resolvedJoinUrl || guideUrl) && (React.createElement("div", { className: "designbase-figma-license-offer__actions" },
|
|
906
|
-
resolvedJoinUrl && (React.createElement(Button, { onPress: () => openExternalUrl(resolvedJoinUrl), variant: "primary", size: "m", fullWidth: true }, resolveText(
|
|
1281
|
+
resolvedJoinUrl && (React.createElement(Button, { onPress: () => openExternalUrl(resolvedJoinUrl), variant: "primary", size: "m", fullWidth: true }, resolveText(translate, { key: 'license.youtube_membership_join' }, '멤버십 가입'))),
|
|
907
1282
|
guideUrl && (React.createElement(Button, { onPress: () => openExternalUrl(guideUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
908
|
-
React.createElement("span", null, resolveText(
|
|
1283
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.youtube_membership_guide' }, '안내보기')),
|
|
909
1284
|
React.createElement(ExternalLinkIcon, { size: 16, "aria-hidden": "true" })))))));
|
|
910
1285
|
};
|
|
911
1286
|
LicenseOffer.displayName = 'LicenseOffer';
|
|
@@ -915,13 +1290,13 @@ function maskLicenseKey(value) {
|
|
|
915
1290
|
return '••••••••';
|
|
916
1291
|
return `${value.slice(0, 4)}••••${value.slice(-4)}`;
|
|
917
1292
|
}
|
|
918
|
-
function formatDate(value) {
|
|
1293
|
+
function formatDate(value, locale) {
|
|
919
1294
|
if (!value)
|
|
920
1295
|
return undefined;
|
|
921
1296
|
const date = new Date(value);
|
|
922
1297
|
if (Number.isNaN(date.getTime()))
|
|
923
1298
|
return value;
|
|
924
|
-
return new Intl.DateTimeFormat(
|
|
1299
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(date);
|
|
925
1300
|
}
|
|
926
1301
|
function formatScope(value, t) {
|
|
927
1302
|
if (!value)
|
|
@@ -942,43 +1317,44 @@ function formatSource(value, t) {
|
|
|
942
1317
|
}
|
|
943
1318
|
return value;
|
|
944
1319
|
}
|
|
945
|
-
const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSource, accessScope, expiresAt, lastVerifiedAt, validationMessage, allowRevealKey = false, t, className, }) => {
|
|
1320
|
+
const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSource, accessScope, expiresAt, lastVerifiedAt, validationMessage, allowRevealKey = false, t, locale, className, }) => {
|
|
1321
|
+
const { locale: resolvedLocale, t: translate } = useFigmaUiI18n(locale, t);
|
|
946
1322
|
const [isKeyRevealed, setIsKeyRevealed] = useState(false);
|
|
947
1323
|
const normalizedLicenseStatus = licenseStatus?.toLowerCase();
|
|
948
1324
|
const isInactiveStatus = ['expired', 'revoked', 'invalid', 'inactive'].includes(normalizedLicenseStatus || '');
|
|
949
1325
|
const isActive = status === 'PAID' && !isInactiveStatus;
|
|
950
1326
|
const statusText = isActive
|
|
951
|
-
? resolveText(
|
|
952
|
-
: resolveText(
|
|
1327
|
+
? resolveText(translate, { key: 'license.status_active' }, 'Active')
|
|
1328
|
+
: resolveText(translate, { key: 'license.status_inactive' }, 'License check failed');
|
|
953
1329
|
const statusClass = isActive ? 'active' : 'inactive';
|
|
954
1330
|
return (React.createElement("section", { className: `designbase-figma-license-status-card designbase-figma-license-status-card--${statusClass} ${className || ''}`, "aria-label": statusText },
|
|
955
1331
|
React.createElement("div", { className: "designbase-figma-license-status-card__header" },
|
|
956
1332
|
React.createElement("div", null,
|
|
957
1333
|
React.createElement("div", { className: "designbase-figma-license-status-card__eyebrow" }, isActive
|
|
958
|
-
? resolveText(
|
|
959
|
-
: resolveText(
|
|
1334
|
+
? resolveText(translate, { key: 'license.activated' }, '라이선스 활성화됨')
|
|
1335
|
+
: resolveText(translate, { key: 'license.status_label' }, '라이선스 상태')),
|
|
960
1336
|
React.createElement("h3", null, statusText)),
|
|
961
1337
|
React.createElement("span", { className: "designbase-figma-license-status-card__badge" }, licenseStatus || (isActive ? 'active' : 'inactive'))),
|
|
962
1338
|
validationMessage && !isActive && (React.createElement("p", { className: "designbase-figma-license-status-card__message" }, validationMessage)),
|
|
963
1339
|
licenseKey && (React.createElement("div", { className: "designbase-figma-license-status-card__key-row" },
|
|
964
|
-
React.createElement("span", null, resolveText(
|
|
1340
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.key_label' }, '라이선스 키')),
|
|
965
1341
|
React.createElement("code", null, allowRevealKey && isKeyRevealed ? licenseKey : maskLicenseKey(licenseKey)),
|
|
966
1342
|
allowRevealKey && (React.createElement(Button, { type: "button", onPress: () => setIsKeyRevealed((value) => !value), variant: "tertiary", size: "s" }, isKeyRevealed
|
|
967
|
-
? resolveText(
|
|
968
|
-
: resolveText(
|
|
1343
|
+
? resolveText(translate, { key: 'license.hide_key' }, '숨기기')
|
|
1344
|
+
: resolveText(translate, { key: 'license.reveal_key' }, '보기'))))),
|
|
969
1345
|
(licenseSource || accessScope || expiresAt || lastVerifiedAt) && (React.createElement("dl", { className: "designbase-figma-license-status-card__meta" },
|
|
970
|
-
formatSource(licenseSource,
|
|
971
|
-
React.createElement("dt", null, resolveText(
|
|
972
|
-
React.createElement("dd", null, formatSource(licenseSource,
|
|
973
|
-
formatScope(accessScope,
|
|
974
|
-
React.createElement("dt", null, resolveText(
|
|
975
|
-
React.createElement("dd", null, formatScope(accessScope,
|
|
1346
|
+
formatSource(licenseSource, translate) && React.createElement(React.Fragment, null,
|
|
1347
|
+
React.createElement("dt", null, resolveText(translate, { key: 'license.source' }, '출처')),
|
|
1348
|
+
React.createElement("dd", null, formatSource(licenseSource, translate))),
|
|
1349
|
+
formatScope(accessScope, translate) && React.createElement(React.Fragment, null,
|
|
1350
|
+
React.createElement("dt", null, resolveText(translate, { key: 'license.access' }, '접근 범위')),
|
|
1351
|
+
React.createElement("dd", null, formatScope(accessScope, translate))),
|
|
976
1352
|
expiresAt && React.createElement(React.Fragment, null,
|
|
977
|
-
React.createElement("dt", null, resolveText(
|
|
978
|
-
React.createElement("dd", null, formatDate(expiresAt) || expiresAt)),
|
|
1353
|
+
React.createElement("dt", null, resolveText(translate, { key: 'license.expires' }, '만료일')),
|
|
1354
|
+
React.createElement("dd", null, formatDate(expiresAt, resolvedLocale) || expiresAt)),
|
|
979
1355
|
lastVerifiedAt && React.createElement(React.Fragment, null,
|
|
980
|
-
React.createElement("dt", null, resolveText(
|
|
981
|
-
React.createElement("dd", null, formatDate(lastVerifiedAt) || lastVerifiedAt))))));
|
|
1356
|
+
React.createElement("dt", null, resolveText(translate, { key: 'license.last_checked' }, '최근 확인')),
|
|
1357
|
+
React.createElement("dd", null, formatDate(lastVerifiedAt, resolvedLocale) || lastVerifiedAt))))));
|
|
982
1358
|
};
|
|
983
1359
|
LicenseStatusCard.displayName = 'LicenseStatusCard';
|
|
984
1360
|
|
|
@@ -999,15 +1375,16 @@ function resolvePaymentFeedbackVariant(errorCode, explicitVariant) {
|
|
|
999
1375
|
}
|
|
1000
1376
|
return 'error';
|
|
1001
1377
|
}
|
|
1002
|
-
const PaymentStatusSection = ({ activationLimit, activationUsage, licenseKey, onDeactivate, isDeactivating = false, showDetails = false, actionMessage, actionMessageVariant, errorCode, className, t, }) => {
|
|
1378
|
+
const PaymentStatusSection = ({ activationLimit, activationUsage, licenseKey, onDeactivate, isDeactivating = false, showDetails = false, actionMessage, actionMessageVariant, errorCode, className, t, locale, }) => {
|
|
1379
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1003
1380
|
const remainingActivations = Math.max(0, activationLimit - activationUsage);
|
|
1004
|
-
const resolvedActionMessage = actionMessage ? resolveText(
|
|
1381
|
+
const resolvedActionMessage = actionMessage ? resolveText(translate, actionMessage) : undefined;
|
|
1005
1382
|
const feedbackVariant = resolvedActionMessage
|
|
1006
1383
|
? resolvePaymentFeedbackVariant(errorCode, actionMessageVariant)
|
|
1007
1384
|
: undefined;
|
|
1008
1385
|
return (React.createElement("div", { className: clsx('designbase-figma-payment-status', className) },
|
|
1009
1386
|
React.createElement("div", { className: "designbase-figma-payment-status__license-key" },
|
|
1010
|
-
resolveText(
|
|
1387
|
+
resolveText(translate, { key: 'payment.license_key_label' }, '라이선스 키'),
|
|
1011
1388
|
": ",
|
|
1012
1389
|
React.createElement("span", null, licenseKey)),
|
|
1013
1390
|
showDetails && (React.createElement("div", { className: "designbase-figma-payment-status__details" },
|
|
@@ -1015,41 +1392,60 @@ const PaymentStatusSection = ({ activationLimit, activationUsage, licenseKey, on
|
|
|
1015
1392
|
React.createElement("div", { className: "designbase-figma-payment-status__remaining" },
|
|
1016
1393
|
remainingActivations,
|
|
1017
1394
|
' ',
|
|
1018
|
-
resolveText(
|
|
1395
|
+
resolveText(translate, { key: 'payment.activations_remaining' }, '활성'),
|
|
1019
1396
|
' ',
|
|
1020
|
-
resolveText(
|
|
1397
|
+
resolveText(translate, { key: 'payment.spots_remaining' }, '자리 남음')),
|
|
1021
1398
|
React.createElement("div", { className: "designbase-figma-payment-status__usage" },
|
|
1022
1399
|
activationUsage,
|
|
1023
1400
|
"/",
|
|
1024
1401
|
activationLimit)),
|
|
1025
1402
|
React.createElement("div", { className: "designbase-figma-payment-status__action" },
|
|
1026
1403
|
React.createElement(Button, { onPress: onDeactivate, variant: "secondary", size: "s", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
1027
|
-
? resolveText(
|
|
1028
|
-
: resolveText(
|
|
1404
|
+
? resolveText(translate, { key: 'payment.deactivating' }, '비활성화중...')
|
|
1405
|
+
: resolveText(translate, { key: 'payment.deactivate_license' }, '라이선스 비활성화')),
|
|
1029
1406
|
resolvedActionMessage && feedbackVariant && (React.createElement("p", { className: clsx('designbase-figma-payment-status__feedback', `designbase-figma-payment-status__feedback--${feedbackVariant}`), role: feedbackVariant === 'error' ? 'alert' : 'status', "aria-live": "polite" }, resolvedActionMessage)))))));
|
|
1030
1407
|
};
|
|
1031
1408
|
PaymentStatusSection.displayName = 'PaymentStatusSection';
|
|
1032
1409
|
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1410
|
+
const defaultFeaturesByLocale = {
|
|
1411
|
+
ko: [
|
|
1412
|
+
{ name: '사용 제한', free: '일일 제한', pro: '무제한' },
|
|
1413
|
+
{ name: '모든 주제 사용', free: false, pro: true },
|
|
1414
|
+
{ name: '최대 선택 제한', free: '최대 5개', pro: '최대 30개' },
|
|
1415
|
+
{ name: '더미 개수', free: '1,400개', pro: '4,400개 이상' },
|
|
1416
|
+
{ name: '커스텀 숫자 사용', free: false, pro: true },
|
|
1417
|
+
],
|
|
1418
|
+
en: [
|
|
1419
|
+
{ name: 'Usage limit', free: 'Daily limit', pro: 'Unlimited' },
|
|
1420
|
+
{ name: 'All topics', free: false, pro: true },
|
|
1421
|
+
{ name: 'Selection limit', free: 'Up to 5', pro: 'Up to 30' },
|
|
1422
|
+
{ name: 'Dummy count', free: '1,400', pro: '4,400+' },
|
|
1423
|
+
{ name: 'Custom numbers', free: false, pro: true },
|
|
1424
|
+
],
|
|
1425
|
+
ja: [
|
|
1426
|
+
{ name: '使用制限', free: '1日の制限', pro: '無制限' },
|
|
1427
|
+
{ name: 'すべてのトピック', free: false, pro: true },
|
|
1428
|
+
{ name: '選択上限', free: '最大5個', pro: '最大30個' },
|
|
1429
|
+
{ name: 'ダミー数', free: '1,400個', pro: '4,400個以上' },
|
|
1430
|
+
{ name: 'カスタム数値', free: false, pro: true },
|
|
1431
|
+
],
|
|
1432
|
+
};
|
|
1040
1433
|
const defaultPricing = {
|
|
1041
1434
|
monthly: 2,
|
|
1042
1435
|
yearly: 21.6,
|
|
1043
1436
|
lifetime: 50,
|
|
1044
1437
|
};
|
|
1045
|
-
const PricingComparison = ({ features
|
|
1438
|
+
const PricingComparison = ({ features, pricing = defaultPricing, paymentType = 'subscription', t, locale, className, }) => {
|
|
1439
|
+
const { locale: resolvedLocale, t: translate } = useFigmaUiI18n(locale, t);
|
|
1046
1440
|
const [isYearly, setIsYearly] = useState(false);
|
|
1441
|
+
const resolvedFeatures = features ?? defaultFeaturesByLocale[resolvedLocale];
|
|
1442
|
+
const resolveFeatureValue = (value) => typeof value === 'boolean' ? (value ? '✓' : '✗') : value;
|
|
1047
1443
|
const getPrice = () => {
|
|
1048
1444
|
if (paymentType === 'lifetime') {
|
|
1049
|
-
return `$${pricing.lifetime?.toLocaleString()} - ${
|
|
1445
|
+
return `$${pricing.lifetime?.toLocaleString()} - ${translate('lifetimeAccess')}`;
|
|
1050
1446
|
}
|
|
1051
1447
|
const price = isYearly ? pricing.yearly : pricing.monthly;
|
|
1052
|
-
return `$${price?.toLocaleString()} / ${isYearly ?
|
|
1448
|
+
return `$${price?.toLocaleString()} / ${isYearly ? translate('perYear') : translate('perMonth')}`;
|
|
1053
1449
|
};
|
|
1054
1450
|
const getDiscountPercentage = () => {
|
|
1055
1451
|
if (paymentType === 'lifetime') {
|
|
@@ -1072,46 +1468,34 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
1072
1468
|
}, options: [
|
|
1073
1469
|
{
|
|
1074
1470
|
value: 'monthly',
|
|
1075
|
-
label:
|
|
1471
|
+
label: translate('monthlyBilling'),
|
|
1076
1472
|
},
|
|
1077
1473
|
{
|
|
1078
1474
|
value: 'yearly',
|
|
1079
|
-
label: `${
|
|
1475
|
+
label: `${translate('yearlyBilling')} (${getDiscountPercentage()}% ${translate('pricing.discount_suffix')})`,
|
|
1080
1476
|
},
|
|
1081
1477
|
], size: "s" }))),
|
|
1082
1478
|
paymentType === 'lifetime' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__lifetime-info" },
|
|
1083
|
-
React.createElement("p", { className: "designbase-figma-pricing-comparison__lifetime-text" },
|
|
1479
|
+
React.createElement("p", { className: "designbase-figma-pricing-comparison__lifetime-text" }, translate('oneTimePaymentLifetime')))),
|
|
1084
1480
|
React.createElement("table", { className: "designbase-figma-pricing-comparison__table" },
|
|
1085
1481
|
React.createElement("thead", null,
|
|
1086
1482
|
React.createElement("tr", null,
|
|
1087
|
-
React.createElement("th", null,
|
|
1483
|
+
React.createElement("th", null, translate('feature')),
|
|
1088
1484
|
React.createElement("th", null,
|
|
1089
|
-
React.createElement("div", { className: "designbase-figma-pricing-comparison__plan-name" },
|
|
1090
|
-
React.createElement("div", null,
|
|
1485
|
+
React.createElement("div", { className: "designbase-figma-pricing-comparison__plan-name" }, translate('free')),
|
|
1486
|
+
React.createElement("div", null, translate('freePrice'))),
|
|
1091
1487
|
React.createElement("th", { className: "designbase-figma-pricing-comparison__recommended" },
|
|
1092
1488
|
React.createElement("div", { className: "designbase-figma-pricing-comparison__plan-name" },
|
|
1093
|
-
|
|
1094
|
-
React.createElement("span", { className: "designbase-figma-pricing-comparison__recommended-badge" },
|
|
1489
|
+
translate('pro'),
|
|
1490
|
+
React.createElement("span", { className: "designbase-figma-pricing-comparison__recommended-badge" }, translate('recommended'))),
|
|
1095
1491
|
React.createElement("div", null, getPrice())))),
|
|
1096
|
-
React.createElement("tbody", null,
|
|
1492
|
+
React.createElement("tbody", null, resolvedFeatures.map((feature, index) => (React.createElement("tr", { key: index },
|
|
1097
1493
|
React.createElement("td", null, feature.name),
|
|
1098
|
-
React.createElement("td", null,
|
|
1099
|
-
|
|
1100
|
-
: feature.free),
|
|
1101
|
-
React.createElement("td", null, typeof feature.pro === 'boolean'
|
|
1102
|
-
? (feature.pro ? '✓' : '✗')
|
|
1103
|
-
: feature.pro))))))));
|
|
1494
|
+
React.createElement("td", null, resolveFeatureValue(feature.free)),
|
|
1495
|
+
React.createElement("td", null, resolveFeatureValue(feature.pro)))))))));
|
|
1104
1496
|
};
|
|
1105
1497
|
PricingComparison.displayName = 'PricingComparison';
|
|
1106
1498
|
|
|
1107
|
-
const DEFAULT_LICENSE_MESSAGE_TYPES = {
|
|
1108
|
-
initialize: 'initialize',
|
|
1109
|
-
verifyLicense: 'verify-license',
|
|
1110
|
-
deactivateLicense: 'deactivate-license',
|
|
1111
|
-
updateStatus: 'update-plugin-status',
|
|
1112
|
-
verifyResult: 'license-verification-result',
|
|
1113
|
-
deactivateResult: 'license-deactivation-result',
|
|
1114
|
-
};
|
|
1115
1499
|
const START_DESIGNBASE_AUTH_MESSAGE = 'start-designbase-auth';
|
|
1116
1500
|
const INITIAL_LICENSE_PAGE_STATE = {
|
|
1117
1501
|
paymentStatus: 'FREE',
|
|
@@ -1266,6 +1650,9 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1266
1650
|
applyPatch({ lastMessage: payload.message });
|
|
1267
1651
|
}
|
|
1268
1652
|
}
|
|
1653
|
+
if (type === messageTypes.featureAccessResult || type === messageTypes.usageConsumeResult) {
|
|
1654
|
+
applyPatch(parseLicenseMessage(payload));
|
|
1655
|
+
}
|
|
1269
1656
|
};
|
|
1270
1657
|
window.addEventListener('message', handleMessage);
|
|
1271
1658
|
postPluginMessage({ type: messageTypes.initialize });
|
|
@@ -1290,6 +1677,20 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1290
1677
|
setIsStartingAuth(true);
|
|
1291
1678
|
postPluginMessage({ type: START_DESIGNBASE_AUTH_MESSAGE });
|
|
1292
1679
|
}, []);
|
|
1680
|
+
const checkFeatureAccess = useCallback((featureKey, amount = 1) => {
|
|
1681
|
+
postPluginMessage({
|
|
1682
|
+
type: messageTypes.checkFeatureAccess,
|
|
1683
|
+
...(featureKey ? { featureKey } : {}),
|
|
1684
|
+
amount,
|
|
1685
|
+
});
|
|
1686
|
+
}, [messageTypes.checkFeatureAccess]);
|
|
1687
|
+
const consumeUsage = useCallback((amount = 1, featureKey) => {
|
|
1688
|
+
postPluginMessage({
|
|
1689
|
+
type: messageTypes.consumeUsage,
|
|
1690
|
+
amount,
|
|
1691
|
+
...(featureKey ? { featureKey } : {}),
|
|
1692
|
+
});
|
|
1693
|
+
}, [messageTypes.consumeUsage]);
|
|
1293
1694
|
return {
|
|
1294
1695
|
state,
|
|
1295
1696
|
isVerifying,
|
|
@@ -1298,6 +1699,8 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1298
1699
|
verifyLicense,
|
|
1299
1700
|
deactivateLicense,
|
|
1300
1701
|
startDesignbaseAuth,
|
|
1702
|
+
checkFeatureAccess,
|
|
1703
|
+
consumeUsage,
|
|
1301
1704
|
setLicenseKeyInput: (licenseKey) => applyPatch({ licenseKey }),
|
|
1302
1705
|
};
|
|
1303
1706
|
}
|
|
@@ -1311,17 +1714,23 @@ function formatUsageLabel(state, t) {
|
|
|
1311
1714
|
const remaining = remainingUsage ?? Math.max(0, limit - usageUsed);
|
|
1312
1715
|
if (usageReset === 'daily') {
|
|
1313
1716
|
const fallback = `오늘 남은 횟수 ${remaining}/${limit}`;
|
|
1314
|
-
const translated = resolveText(t, { key: 'license.usage_daily' }, fallback) ?? fallback;
|
|
1717
|
+
const translated = resolveText(t, { key: 'license.usage_daily', values: { remaining, limit } }, fallback) ?? fallback;
|
|
1315
1718
|
return translated.includes(String(remaining)) ? translated : fallback;
|
|
1316
1719
|
}
|
|
1317
1720
|
if (usageReset === 'monthly') {
|
|
1318
1721
|
const fallback = `이번 달 남은 횟수 ${remaining}/${limit}`;
|
|
1319
|
-
const translated = resolveText(t, { key: 'license.usage_monthly' }, fallback) ?? fallback;
|
|
1722
|
+
const translated = resolveText(t, { key: 'license.usage_monthly', values: { remaining, limit } }, fallback) ?? fallback;
|
|
1723
|
+
return translated.includes(String(remaining)) ? translated : fallback;
|
|
1724
|
+
}
|
|
1725
|
+
if (usageReset === 'weekly') {
|
|
1726
|
+
const fallback = `이번 주 남은 횟수 ${remaining}/${limit}`;
|
|
1727
|
+
const translated = resolveText(t, { key: 'license.usage_weekly', values: { remaining, limit } }, fallback) ?? fallback;
|
|
1320
1728
|
return translated.includes(String(remaining)) ? translated : fallback;
|
|
1321
1729
|
}
|
|
1322
|
-
return `남은 횟수 ${remaining}/${limit}`;
|
|
1730
|
+
return resolveText(t, { key: 'license.usage_generic', values: { remaining, limit } }, `남은 횟수 ${remaining}/${limit}`) ?? `남은 횟수 ${remaining}/${limit}`;
|
|
1323
1731
|
}
|
|
1324
|
-
const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicenseKey = '', wordpressLinks, paymentPageUrl, mode = 'pricing', membershipUrl, enableAccountAuth = true, showLicenseKeyInput = true, pricingFeatures, pricing, paymentType = 'subscription', messageTypes, onStateChange, setPaymentStatus, setUsageCount, onLicenseSubmit, usageCount: initialUsageCount = 0, t, className, }) => {
|
|
1732
|
+
const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicenseKey = '', wordpressLinks, paymentPageUrl, mode = 'pricing', membershipUrl, enableAccountAuth = true, showLicenseKeyInput = true, pricingFeatures, pricing, paymentType = 'subscription', messageTypes, onStateChange, setPaymentStatus, setUsageCount, onLicenseSubmit, usageCount: initialUsageCount = 0, t, locale, className, }) => {
|
|
1733
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1325
1734
|
const links = useMemo(() => ({
|
|
1326
1735
|
purchaseUrl: wordpressLinks?.purchaseUrl ?? paymentPageUrl,
|
|
1327
1736
|
membershipUrl: membershipUrl ?? wordpressLinks?.membershipUrl,
|
|
@@ -1343,7 +1752,7 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1343
1752
|
const [licenseKeyDraft, setLicenseKeyDraft] = useState(initialLicenseKey);
|
|
1344
1753
|
const isPaid = state.isLicenseRegistered && state.paymentStatus === 'PAID';
|
|
1345
1754
|
const isMembershipMode = mode === 'youtube-membership';
|
|
1346
|
-
const usageLabel = formatUsageLabel(state,
|
|
1755
|
+
const usageLabel = formatUsageLabel(state, translate);
|
|
1347
1756
|
const handleLicenseSubmit = async (submittedLicenseKey) => {
|
|
1348
1757
|
if (onLicenseSubmit) {
|
|
1349
1758
|
await onLicenseSubmit(submittedLicenseKey);
|
|
@@ -1360,79 +1769,80 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1360
1769
|
React.createElement("div", { className: "designbase-figma-page-license__header" },
|
|
1361
1770
|
React.createElement("div", { className: "designbase-figma-page-license__title" },
|
|
1362
1771
|
React.createElement("h2", null, isMembershipMode
|
|
1363
|
-
? resolveText(
|
|
1772
|
+
? resolveText(translate, { key: 'license.youtube_membership' }, 'YouTube 멤버십')
|
|
1364
1773
|
: isPaid
|
|
1365
|
-
? resolveText(
|
|
1366
|
-
: resolveText(
|
|
1774
|
+
? resolveText(translate, { key: 'license.pro_account' }, '프로 계정')
|
|
1775
|
+
: resolveText(translate, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
|
|
1367
1776
|
state.planTier && state.planTier !== 'FREE' && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, state.planTier))),
|
|
1368
1777
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
1369
|
-
? resolveText(
|
|
1778
|
+
? resolveText(translate, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
1370
1779
|
: isMembershipMode
|
|
1371
|
-
? resolveText(
|
|
1372
|
-
: resolveText(
|
|
1780
|
+
? resolveText(translate, { key: 'license.youtube_membership_description' }, 'YouTube 멤버십에 가입하면 Designbase 플러그인을 무제한으로 사용할 수 있습니다.')
|
|
1781
|
+
: resolveText(translate, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
|
|
1373
1782
|
!isPaid && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
1374
|
-
!isMembershipMode && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t:
|
|
1783
|
+
!isMembershipMode && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: translate })),
|
|
1375
1784
|
state.lastMessage && !state.deactivateMessage && (React.createElement("p", { className: `designbase-figma-page-license__feedback ${state.lastErrorCode ? 'designbase-figma-page-license__feedback--error' : ''}`, "aria-live": "polite" }, state.lastMessage)),
|
|
1376
1785
|
isPaid && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1377
1786
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1378
|
-
React.createElement("h3", null, resolveText(
|
|
1787
|
+
React.createElement("h3", null, resolveText(translate, { key: 'license.activated' }, '라이선스 활성화됨')),
|
|
1379
1788
|
React.createElement(Button, { onPress: () => setShowDetails(!showDetails), variant: "tertiary", size: "s", iconOnly: true },
|
|
1380
1789
|
React.createElement(MoreHorizontalIcon, { size: 16 }))),
|
|
1381
|
-
React.createElement(LicenseStatusCard, { status: state.paymentStatus, licenseKey: state.licenseKey, licenseStatus: state.licenseStatus, licenseSource: state.licenseSource, accessScope: state.accessScope, expiresAt: state.expiresAt, lastVerifiedAt: state.lastVerifiedAt, validationMessage: state.validationMessage, allowRevealKey: false, t:
|
|
1790
|
+
React.createElement(LicenseStatusCard, { status: state.paymentStatus, licenseKey: state.licenseKey, licenseStatus: state.licenseStatus, licenseSource: state.licenseSource, accessScope: state.accessScope, expiresAt: state.expiresAt, lastVerifiedAt: state.lastVerifiedAt, validationMessage: state.validationMessage, allowRevealKey: false, t: translate }),
|
|
1382
1791
|
React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel),
|
|
1383
1792
|
showDetails && (React.createElement("div", { className: "designbase-figma-page-license__details" },
|
|
1384
1793
|
React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
1385
1794
|
React.createElement("div", { className: "designbase-figma-page-license__remaining" },
|
|
1386
1795
|
Math.max(0, state.activationLimit - state.activationUsage),
|
|
1387
1796
|
' ',
|
|
1388
|
-
resolveText(
|
|
1797
|
+
resolveText(translate, { key: 'license.activations_remaining' }, '활성'),
|
|
1389
1798
|
' ',
|
|
1390
|
-
resolveText(
|
|
1799
|
+
resolveText(translate, { key: 'license.spots_remaining' }, '자리 남음')),
|
|
1391
1800
|
React.createElement("div", { className: "designbase-figma-page-license__usage-count" },
|
|
1392
1801
|
state.activationUsage,
|
|
1393
1802
|
"/",
|
|
1394
1803
|
state.activationLimit)),
|
|
1395
1804
|
React.createElement("div", { className: "designbase-figma-page-license__action" },
|
|
1396
1805
|
React.createElement(Button, { onPress: deactivateLicense, variant: "secondary", size: "s", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
1397
|
-
? resolveText(
|
|
1398
|
-
: resolveText(
|
|
1806
|
+
? resolveText(translate, { key: 'license.deactivating' }, '비활성화 중...')
|
|
1807
|
+
: resolveText(translate, { key: 'license.deactivate' }, '라이선스 비활성화')),
|
|
1399
1808
|
state.deactivateMessage && (React.createElement("p", { className: `designbase-figma-page-license__action-feedback designbase-figma-page-license__action-feedback--${resolvePaymentFeedbackVariant(state.deactivateErrorCode)}`, role: state.deactivateErrorCode ? 'alert' : 'status', "aria-live": "polite" }, state.deactivateMessage))))))),
|
|
1400
1809
|
!isPaid && (React.createElement(React.Fragment, null,
|
|
1401
|
-
isMembershipMode && (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t:
|
|
1810
|
+
isMembershipMode && (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t: translate })),
|
|
1402
1811
|
!isMembershipMode && (enableAccountAuth || links.purchaseUrl || links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1403
1812
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1404
|
-
React.createElement("h3", null, resolveText(
|
|
1405
|
-
React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(
|
|
1813
|
+
React.createElement("h3", null, resolveText(translate, { key: 'license.designbase_account' }, '디자인베이스 계정'))),
|
|
1814
|
+
React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(translate, { key: 'license.designbase_account_hint' }, 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.')),
|
|
1406
1815
|
React.createElement("div", { className: "designbase-figma-page-license__actions" },
|
|
1407
1816
|
enableAccountAuth && (React.createElement(Button, { onPress: startDesignbaseAuth, variant: "primary", size: "m", disabled: isStartingAuth || isVerifying, fullWidth: true }, isStartingAuth
|
|
1408
|
-
? resolveText(
|
|
1409
|
-
: resolveText(
|
|
1817
|
+
? resolveText(translate, { key: 'license.authenticating' }, '인증 중...')
|
|
1818
|
+
: resolveText(translate, { key: 'license.login_with_designbase' }, '디자인베이스로 로그인'))),
|
|
1410
1819
|
links.purchaseUrl && (React.createElement(Button, { onPress: () => openExternalUrl(links.purchaseUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
1411
|
-
React.createElement("span", null, resolveText(
|
|
1820
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.purchase_membership' }, '멤버십 안내')),
|
|
1412
1821
|
React.createElement(ExternalLinkIcon, { size: 16 }))),
|
|
1413
1822
|
links.accountUrl && (React.createElement(Button, { onPress: () => openExternalUrl(links.accountUrl), variant: "tertiary", size: "s", fullWidth: true },
|
|
1414
|
-
React.createElement("span", null, resolveText(
|
|
1823
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.manage_account' }, '계정·멤버십 관리')),
|
|
1415
1824
|
React.createElement(ExternalLinkIcon, { size: 16 })))))),
|
|
1416
1825
|
showLicenseKeyInput && (React.createElement("div", { className: isMembershipMode
|
|
1417
1826
|
? 'designbase-figma-page-license__key-form'
|
|
1418
1827
|
: 'designbase-figma-page-license__section' },
|
|
1419
1828
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1420
|
-
React.createElement("h3", null, resolveText(
|
|
1421
|
-
React.createElement(FormWithSubmit, { onLicenseSubmit: handleLicenseSubmit, disabled: false, isSubmitting: isVerifying, value: licenseKeyDraft, onValueChange: handleLicenseKeyChange, label: { key: 'license.key' }, submitText: { key: 'license.submit' }, submittingText: { key: 'license.verifying' }, helperText: { key: isMembershipMode ? 'license.enter_from_youtube' : 'license.enter_from_email' }, t:
|
|
1829
|
+
React.createElement("h3", null, resolveText(translate, { key: 'license.enter_key' }, '라이선스 키 입력'))),
|
|
1830
|
+
React.createElement(FormWithSubmit, { onLicenseSubmit: handleLicenseSubmit, disabled: false, isSubmitting: isVerifying, value: licenseKeyDraft, onValueChange: handleLicenseKeyChange, label: { key: 'license.key' }, submitText: { key: 'license.submit' }, submittingText: { key: 'license.verifying' }, helperText: { key: isMembershipMode ? 'license.enter_from_youtube' : 'license.enter_from_email' }, t: translate }))))),
|
|
1422
1831
|
links.helpUrl && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
1423
|
-
React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(
|
|
1424
|
-
React.createElement(Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", iconOnly: true, "aria-label":
|
|
1832
|
+
React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(translate, { key: 'license.help_link' }, '라이선스·결제 도움말'))))),
|
|
1833
|
+
React.createElement(Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", iconOnly: true, "aria-label": translate('close') },
|
|
1425
1834
|
React.createElement(CloseIcon, { size: 16 }))));
|
|
1426
1835
|
};
|
|
1427
1836
|
PageLicense.displayName = 'PageLicense';
|
|
1428
1837
|
|
|
1429
|
-
const PaymentBadge = ({ isActive, onClick, isLoading = false, text, t
|
|
1838
|
+
const PaymentBadge = ({ isActive, onClick, isLoading = false, text, t, locale, className, }) => {
|
|
1839
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1430
1840
|
const getBadgeText = () => {
|
|
1431
1841
|
if (text)
|
|
1432
1842
|
return text;
|
|
1433
1843
|
return isActive
|
|
1434
|
-
? (
|
|
1435
|
-
: (
|
|
1844
|
+
? translate('proUser')
|
|
1845
|
+
: translate('usingFree');
|
|
1436
1846
|
};
|
|
1437
1847
|
const getBadgeVariant = () => {
|
|
1438
1848
|
return isActive ? 'success' : 'secondary';
|
|
@@ -1441,7 +1851,8 @@ const PaymentBadge = ({ isActive, onClick, isLoading = false, text, t = (key) =>
|
|
|
1441
1851
|
};
|
|
1442
1852
|
PaymentBadge.displayName = 'PaymentBadge';
|
|
1443
1853
|
|
|
1444
|
-
const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.working' }, completedMessage = { key: 'progress.completed' }, processingMessage = { key: 'progress.processing' }, stopButtonText = { key: 'progress.stop' }, confirmButtonText = { key: 'progress.confirm' }, helpText, onStop, onComplete, loadingIcon, completeIcon, className, t, autoComplete = true, autoCloseOnComplete = false }) => {
|
|
1854
|
+
const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.working' }, completedMessage = { key: 'progress.completed' }, processingMessage = { key: 'progress.processing' }, stopButtonText = { key: 'progress.stop' }, confirmButtonText = { key: 'progress.confirm' }, helpText, onStop, onComplete, loadingIcon, completeIcon, className, t, locale, autoComplete = true, autoCloseOnComplete = false }) => {
|
|
1855
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1445
1856
|
const [isCompleted, setIsCompleted] = useState(false);
|
|
1446
1857
|
const completeFiredRef = useRef(false);
|
|
1447
1858
|
const { processedNodes, totalNodes } = progress;
|
|
@@ -1471,11 +1882,11 @@ const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.wor
|
|
|
1471
1882
|
onClose();
|
|
1472
1883
|
};
|
|
1473
1884
|
const modalClasses = clsx('designbase-figma-progress-modal', className);
|
|
1474
|
-
const displayTitle = resolveText(
|
|
1475
|
-
const displayMessage = resolveText(
|
|
1476
|
-
const displayStopText = resolveText(
|
|
1477
|
-
const displayConfirmText = resolveText(
|
|
1478
|
-
const displayHelpText = resolveText(
|
|
1885
|
+
const displayTitle = resolveText(translate, isCompleted ? completedMessage : title, isCompleted ? '완료되었습니다' : '작업 중');
|
|
1886
|
+
const displayMessage = resolveText(translate, isCompleted ? completedMessage : processingMessage, isCompleted ? '완료되었습니다' : '처리 중...');
|
|
1887
|
+
const displayStopText = resolveText(translate, stopButtonText, '중지');
|
|
1888
|
+
const displayConfirmText = resolveText(translate, confirmButtonText, '확인');
|
|
1889
|
+
const displayHelpText = resolveText(translate, helpText);
|
|
1479
1890
|
return (React.createElement(Modal, { isOpen: isOpen, onClose: isCompleted ? onClose : undefined, title: displayTitle, size: "s", className: modalClasses, showCloseButton: false },
|
|
1480
1891
|
React.createElement("div", { className: "designbase-figma-progress-modal__content" },
|
|
1481
1892
|
React.createElement("div", { className: "designbase-figma-progress-modal__icon", "aria-hidden": "true" }, isCompleted ? (completeIcon || (React.createElement("div", { className: "designbase-figma-progress-modal__icon-success" },
|
|
@@ -1529,7 +1940,8 @@ const ResizablePlugin = ({ children, minWidth = 360, maxWidth = 460, minHeight =
|
|
|
1529
1940
|
};
|
|
1530
1941
|
ResizablePlugin.displayName = 'ResizablePlugin';
|
|
1531
1942
|
|
|
1532
|
-
const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categoryGroups, onSave, onReset, title = { key: 'settings.modal_title' }, description = { key: 'settings.modal_description' }, className, t }) => {
|
|
1943
|
+
const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categoryGroups, onSave, onReset, title = { key: 'settings.modal_title' }, description = { key: 'settings.modal_description' }, className, t, locale, }) => {
|
|
1944
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1533
1945
|
const [tempCategories, setTempCategories] = useState(initialCategories);
|
|
1534
1946
|
const [draggedIndex, setDraggedIndex] = useState(null);
|
|
1535
1947
|
useEffect(() => {
|
|
@@ -1622,8 +2034,8 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1622
2034
|
}
|
|
1623
2035
|
};
|
|
1624
2036
|
const modalClasses = clsx('designbase-figma-settings-modal', className);
|
|
1625
|
-
const displayTitle = resolveText(
|
|
1626
|
-
const displayDescription = resolveText(
|
|
2037
|
+
const displayTitle = resolveText(translate, title, '목록 변경');
|
|
2038
|
+
const displayDescription = resolveText(translate, description, '드래그하여 순서를 변경하거나, 토글하여 카테고리를 숨길 수 있습니다.');
|
|
1627
2039
|
return (React.createElement(Modal, { isOpen: isOpen, onClose: onClose, title: displayTitle, size: "m", className: modalClasses },
|
|
1628
2040
|
React.createElement("div", { className: "designbase-figma-settings-modal__content" },
|
|
1629
2041
|
displayDescription && (React.createElement("p", { className: "designbase-figma-settings-modal__description" }, displayDescription)),
|
|
@@ -1635,32 +2047,33 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1635
2047
|
React.createElement("span", { className: "designbase-figma-settings-modal__drag-handle" },
|
|
1636
2048
|
React.createElement(GripVerticalIcon, { size: 16 })),
|
|
1637
2049
|
category.icon && (React.createElement("span", { className: "designbase-figma-settings-modal__category-icon" }, category.icon)),
|
|
1638
|
-
React.createElement("span", { className: "designbase-figma-settings-modal__category-title" }, resolveText(
|
|
2050
|
+
React.createElement("span", { className: "designbase-figma-settings-modal__category-title" }, resolveText(translate, category.title))),
|
|
1639
2051
|
React.createElement(Toggle, { checked: category.enabled, onChange: () => handleToggle(category.id), size: "s" })))))),
|
|
1640
2052
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer" },
|
|
1641
|
-
onReset && (React.createElement(Button, { onPress: handleReset, variant: "tertiary", size: "s" }, resolveText(
|
|
2053
|
+
onReset && (React.createElement(Button, { onPress: handleReset, variant: "tertiary", size: "s" }, resolveText(translate, { key: 'settings.reset' }, '초기화'))),
|
|
1642
2054
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer-right" },
|
|
1643
|
-
React.createElement(Button, { onPress: handleCancel, variant: "tertiary", size: "s" }, resolveText(
|
|
1644
|
-
React.createElement(Button, { onPress: handleSave, variant: "primary", size: "s" }, resolveText(
|
|
2055
|
+
React.createElement(Button, { onPress: handleCancel, variant: "tertiary", size: "s" }, resolveText(translate, { key: 'settings.cancel' }, '취소')),
|
|
2056
|
+
React.createElement(Button, { onPress: handleSave, variant: "primary", size: "s" }, resolveText(translate, { key: 'settings.save' }, '저장'))))));
|
|
1645
2057
|
};
|
|
1646
2058
|
SettingsModal.displayName = 'SettingsModal';
|
|
1647
2059
|
|
|
1648
|
-
const TitleDescription = ({ iconSrc, iconAlt = 'Icon', title, description, button, features, className, t }) => {
|
|
2060
|
+
const TitleDescription = ({ iconSrc, iconAlt = 'Icon', title, description, button, features, className, t, locale, }) => {
|
|
2061
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1649
2062
|
const classes = [
|
|
1650
2063
|
'designbase-figma-title-description',
|
|
1651
2064
|
className,
|
|
1652
2065
|
]
|
|
1653
2066
|
.filter(Boolean)
|
|
1654
2067
|
.join(' ');
|
|
1655
|
-
const displayTitle = resolveText(
|
|
1656
|
-
const displayDescription = resolveText(
|
|
2068
|
+
const displayTitle = resolveText(translate, title);
|
|
2069
|
+
const displayDescription = resolveText(translate, description);
|
|
1657
2070
|
return (React.createElement("div", { className: classes },
|
|
1658
2071
|
iconSrc && (React.createElement("img", { className: "designbase-figma-title-description__icon", src: iconSrc, alt: iconAlt })),
|
|
1659
2072
|
React.createElement("h5", { className: "designbase-figma-title-description__title" }, displayTitle),
|
|
1660
2073
|
React.createElement("p", { className: "designbase-figma-title-description__description" }, displayDescription),
|
|
1661
2074
|
button && React.createElement("div", { className: "designbase-figma-title-description__button" }, button),
|
|
1662
2075
|
features && features.length > 0 && (React.createElement("ul", { className: "designbase-figma-title-description__features" }, features.map((feature, index) => {
|
|
1663
|
-
const displayFeature = resolveText(
|
|
2076
|
+
const displayFeature = resolveText(translate, feature);
|
|
1664
2077
|
return (React.createElement("li", { key: index, className: "designbase-figma-title-description__feature-item" },
|
|
1665
2078
|
React.createElement("span", { className: "designbase-figma-title-description__check-icon" },
|
|
1666
2079
|
React.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
|
|
@@ -1671,10 +2084,11 @@ const TitleDescription = ({ iconSrc, iconAlt = 'Icon', title, description, butto
|
|
|
1671
2084
|
};
|
|
1672
2085
|
TitleDescription.displayName = 'TitleDescription';
|
|
1673
2086
|
|
|
1674
|
-
const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title = { key: 'banner.upgrade_title' }, description = { key: 'banner.upgrade_description' }, buttonText = { key: 'banner.upgrade_button' }, useGradient = false, gradientScheme = 'primary', gradientTone = 'light', gradientAnimated = true, className, t }) => {
|
|
1675
|
-
const
|
|
1676
|
-
const
|
|
1677
|
-
const
|
|
2087
|
+
const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title = { key: 'banner.upgrade_title' }, description = { key: 'banner.upgrade_description' }, buttonText = { key: 'banner.upgrade_button' }, useGradient = false, gradientScheme = 'primary', gradientTone = 'light', gradientAnimated = true, className, t, locale, }) => {
|
|
2088
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
2089
|
+
const displayTitle = resolveText(translate, title, '프로로 업그레이드하세요');
|
|
2090
|
+
const displayDescription = resolveText(translate, description, '무제한 기능을 사용하고 더 많은 혜택을 누리세요.');
|
|
2091
|
+
const displayButtonText = resolveText(translate, buttonText, '지금 업그레이드');
|
|
1678
2092
|
const bannerContent = (React.createElement("div", { className: `designbase-figma-upgrade-banner__content designbase-figma-upgrade-banner__content--${variant}`, onClick: variant === 'clickable' ? onClick : undefined, role: variant === 'clickable' ? 'button' : undefined, tabIndex: variant === 'clickable' ? 0 : undefined, onKeyDown: variant === 'clickable' ? (e) => {
|
|
1679
2093
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
1680
2094
|
e.preventDefault();
|
|
@@ -1690,5 +2104,5 @@ const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title =
|
|
|
1690
2104
|
};
|
|
1691
2105
|
UpgradeBanner.displayName = 'UpgradeBanner';
|
|
1692
2106
|
|
|
1693
|
-
export {
|
|
2107
|
+
export { DonationBadge, FIGMA_UI_TRANSLATIONS, FigmaContainer, FigmaFooter, FigmaHeader, FigmaPageHead, FigmaSection, FigmaSidebar, FigmaToast, FigmaToastProvider, FigmaUiI18nProvider, FormWithSubmit, InteractionFeedback, LanguageSelector, LanguageSettingsModal, LicenseOffer, LicenseStatusCard, LogoDropdown, PageLicense, PaymentBadge, PaymentStatusSection, PricingComparison, ProgressModal, ResizablePlugin, START_DESIGNBASE_AUTH_MESSAGE, SettingsModal, TitleDescription, UpgradeBanner, UsageStatusPopover, createFigmaUiTranslator, getActiveSection, interpolateText, normalizeFigmaUiLocale, resolvePaymentFeedbackVariant, resolveText, scrollToSection, useFigmaLicenseBridge, useFigmaToast, useFigmaUiI18n, useToast };
|
|
1694
2108
|
//# sourceMappingURL=index.esm.js.map
|