@designbasekorea/figma-ui 0.6.9 → 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 +672 -269
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +812 -402
- 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, { useRef, useState, useLayoutEffect, useEffect, useCallback, useId
|
|
1
|
+
import React, { createContext, useMemo, useContext, useRef, useState, useLayoutEffect, useEffect, useCallback, useId } from 'react';
|
|
2
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,54 +838,30 @@ 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
|
-
languageSettingsDescription: '플러그인에 표시할 언어를 선택하세요.',
|
|
414
|
-
'language.korean': '한국어',
|
|
415
|
-
'language.english': 'English',
|
|
416
|
-
'language.japanese': '日本語',
|
|
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 resolvedCurrentLanguage = currentLanguage || i18n?.language || languages[0]?.code;
|
|
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;
|
|
423
849
|
const [pendingLanguage, setPendingLanguage] = useState(resolvedCurrentLanguage);
|
|
424
850
|
useEffect(() => {
|
|
425
851
|
if (isOpen) {
|
|
426
852
|
setPendingLanguage(resolvedCurrentLanguage);
|
|
427
853
|
}
|
|
428
854
|
}, [isOpen, resolvedCurrentLanguage]);
|
|
429
|
-
const translate = (key, fallback) => {
|
|
430
|
-
const translated = t(key);
|
|
431
|
-
return translated && translated !== key ? translated : fallback;
|
|
432
|
-
};
|
|
433
855
|
const handleSelect = useCallback((languageCode) => {
|
|
434
856
|
setPendingLanguage(languageCode);
|
|
435
|
-
if (i18n) {
|
|
436
|
-
i18n.changeLanguage(languageCode);
|
|
437
|
-
}
|
|
438
857
|
onLanguageChange?.(languageCode);
|
|
439
858
|
onClose();
|
|
440
|
-
}, [
|
|
441
|
-
return (React.createElement(Modal, { isOpen: isOpen, onClose: onClose, title: title || translate('languageSettings'
|
|
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) },
|
|
442
861
|
React.createElement(ModalBody, { className: "designbase-figma-language-settings-modal__content" },
|
|
443
|
-
React.createElement("p", { className: "designbase-figma-language-settings-modal__description" }, description || translate('languageSettingsDescription'
|
|
444
|
-
React.createElement("ul", { className: "designbase-figma-language-settings-modal__list", role: "listbox", "aria-label": translate('languageSettings'
|
|
445
|
-
const label = resolveText(
|
|
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());
|
|
446
865
|
const isActive = language.code === pendingLanguage;
|
|
447
866
|
return (React.createElement("li", { key: language.code, role: "presentation" },
|
|
448
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) },
|
|
@@ -452,13 +871,6 @@ const LanguageSettingsModal = ({ isOpen, onClose, languages = DEFAULT_LANGUAGES$
|
|
|
452
871
|
};
|
|
453
872
|
LanguageSettingsModal.displayName = 'LanguageSettingsModal';
|
|
454
873
|
|
|
455
|
-
let useTranslation$1 = null;
|
|
456
|
-
try {
|
|
457
|
-
const reactI18next = require('react-i18next');
|
|
458
|
-
useTranslation$1 = reactI18next.useTranslation;
|
|
459
|
-
}
|
|
460
|
-
catch (e) {
|
|
461
|
-
}
|
|
462
874
|
const defaultLinks = [
|
|
463
875
|
{
|
|
464
876
|
name: 'officialWebsite',
|
|
@@ -486,33 +898,20 @@ const defaultLinks = [
|
|
|
486
898
|
icon: React.createElement(MailIcon, { size: 20 }),
|
|
487
899
|
},
|
|
488
900
|
];
|
|
489
|
-
const defaultTranslations$1 = {
|
|
490
|
-
officialWebsite: '공식 웹사이트',
|
|
491
|
-
youtube: '유튜브',
|
|
492
|
-
instagram: '인스타그램',
|
|
493
|
-
figmaCommunity: '피그마 커뮤니티',
|
|
494
|
-
contact: '문의하기',
|
|
495
|
-
languageSettings: '언어 설정',
|
|
496
|
-
};
|
|
497
|
-
const defaultT$1 = (key) => defaultTranslations$1[key] || key;
|
|
498
901
|
const defaultLanguages = [
|
|
499
|
-
{ code: 'ko', label: '
|
|
500
|
-
{ code: 'en', label: '
|
|
501
|
-
{ code: 'ja', label: '
|
|
902
|
+
{ code: 'ko', label: { key: 'language.korean' } },
|
|
903
|
+
{ code: 'en', label: { key: 'language.english' } },
|
|
904
|
+
{ code: 'ja', label: { key: 'language.japanese' } },
|
|
502
905
|
];
|
|
503
|
-
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, }) => {
|
|
504
907
|
const [isOpen, setIsOpen] = useState(false);
|
|
505
908
|
const [isLanguageModalOpen, setIsLanguageModalOpen] = useState(false);
|
|
506
909
|
const [internalLanguage, setInternalLanguage] = useState();
|
|
507
|
-
const
|
|
910
|
+
const { t: translate } = useFigmaUiI18n(currentLanguage ?? internalLanguage, t);
|
|
508
911
|
const rootRef = useRef(null);
|
|
509
912
|
const triggerRef = useRef(null);
|
|
510
913
|
const menuId = `designbase-figma-logo-menu-${useId().replace(/:/g, '')}`;
|
|
511
|
-
const activeLanguage = currentLanguage ?? internalLanguage ??
|
|
512
|
-
const translate = (key, fallback) => {
|
|
513
|
-
const translated = t(key);
|
|
514
|
-
return translated && translated !== key ? translated : fallback;
|
|
515
|
-
};
|
|
914
|
+
const activeLanguage = currentLanguage ?? internalLanguage ?? languages[0]?.code;
|
|
516
915
|
useEffect(() => {
|
|
517
916
|
if (!isOpen) {
|
|
518
917
|
return undefined;
|
|
@@ -551,9 +950,6 @@ const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase'
|
|
|
551
950
|
if (currentLanguage === undefined) {
|
|
552
951
|
setInternalLanguage(languageCode);
|
|
553
952
|
}
|
|
554
|
-
if (i18n) {
|
|
555
|
-
i18n.changeLanguage(languageCode);
|
|
556
|
-
}
|
|
557
953
|
onLanguageChange?.(languageCode);
|
|
558
954
|
};
|
|
559
955
|
const classes = clsx('designbase-figma-logo-dropdown', `designbase-figma-logo-dropdown--${position}`, {
|
|
@@ -568,14 +964,14 @@ const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase'
|
|
|
568
964
|
links.map((link, index) => (React.createElement("li", { key: index, className: "designbase-figma-logo-dropdown__item", role: "none" },
|
|
569
965
|
React.createElement("button", { type: "button", className: "designbase-figma-logo-dropdown__link", role: "menuitem", onClick: () => handleLinkClick(link.url) },
|
|
570
966
|
link.icon && (React.createElement("span", { className: "designbase-figma-logo-dropdown__icon" }, link.icon)),
|
|
571
|
-
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" },
|
|
967
|
+
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" }, translate(link.name)),
|
|
572
968
|
React.createElement(ExternalLinkIcon, { size: 16, className: "designbase-figma-logo-dropdown__arrow" }))))),
|
|
573
969
|
showLanguageSelector && (React.createElement("li", { className: "designbase-figma-logo-dropdown__item designbase-figma-logo-dropdown__language-item", role: "none" },
|
|
574
970
|
React.createElement("button", { type: "button", className: "designbase-figma-logo-dropdown__link", role: "menuitem", onClick: handleLanguageSettingsClick },
|
|
575
971
|
React.createElement("span", { className: "designbase-figma-logo-dropdown__icon" },
|
|
576
972
|
React.createElement(TranslateIcon, { size: 20, "aria-hidden": "true" })),
|
|
577
|
-
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" }, translate('languageSettings'
|
|
578
|
-
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 }))));
|
|
579
975
|
};
|
|
580
976
|
LogoDropdown.displayName = 'LogoDropdown';
|
|
581
977
|
|
|
@@ -583,7 +979,8 @@ const fallbackText = (t, key, fallback) => {
|
|
|
583
979
|
const translated = t?.(key);
|
|
584
980
|
return translated && translated !== key ? translated : fallback;
|
|
585
981
|
};
|
|
586
|
-
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);
|
|
587
984
|
const [isOpen, setIsOpen] = useState(false);
|
|
588
985
|
const rootRef = useRef(null);
|
|
589
986
|
const triggerRef = useRef(null);
|
|
@@ -597,25 +994,25 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20,
|
|
|
597
994
|
const usedPercent = hasDailyLimit ? Math.round((used / limit) * 100) : 0;
|
|
598
995
|
const hasControl = showUsage || showPlan;
|
|
599
996
|
const planLabel = isPaid
|
|
600
|
-
? fallbackText(
|
|
997
|
+
? fallbackText(translate, 'proUser', '프로')
|
|
601
998
|
: isBeta
|
|
602
|
-
? fallbackText(
|
|
999
|
+
? fallbackText(translate, 'betaStatus', 'BETA')
|
|
603
1000
|
: paymentStatus === 'TRIAL'
|
|
604
|
-
? fallbackText(
|
|
605
|
-
: fallbackText(
|
|
1001
|
+
? fallbackText(translate, 'trialPlan', '체험판')
|
|
1002
|
+
: fallbackText(translate, 'free', '무료');
|
|
606
1003
|
const planTitle = isBeta
|
|
607
1004
|
? planLabel
|
|
608
|
-
: `${planLabel} ${fallbackText(
|
|
1005
|
+
: `${planLabel} ${fallbackText(translate, 'planSuffix', '플랜')}`;
|
|
609
1006
|
const triggerLabel = isPaid
|
|
610
|
-
? `${planLabel}, ${fallbackText(
|
|
1007
|
+
? `${planLabel}, ${fallbackText(translate, 'unlimitedUsage', '무제한 사용 가능')}`
|
|
611
1008
|
: isBeta
|
|
612
1009
|
? planLabel
|
|
613
1010
|
: hasDailyLimit
|
|
614
|
-
? `${remaining}/${limit} ${fallbackText(
|
|
1011
|
+
? `${remaining}/${limit} ${fallbackText(translate, 'remainingShort', '남음')}`
|
|
615
1012
|
: planLabel;
|
|
616
1013
|
const upgradeLabel = isPaid
|
|
617
|
-
? fallbackText(
|
|
618
|
-
: fallbackText(
|
|
1014
|
+
? fallbackText(translate, 'managePlan', '플랜 관리')
|
|
1015
|
+
: fallbackText(translate, 'upgradePlan', '플랜 업그레이드');
|
|
619
1016
|
useEffect(() => {
|
|
620
1017
|
if (!isOpen)
|
|
621
1018
|
return undefined;
|
|
@@ -650,7 +1047,7 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20,
|
|
|
650
1047
|
'designbase-figma-usage-status--loading': isLoading,
|
|
651
1048
|
}, className) },
|
|
652
1049
|
React.createElement("div", { className: "designbase-figma-usage-status__control" },
|
|
653
|
-
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,
|
|
654
1051
|
React.createElement("span", { className: "designbase-figma-usage-status__mini-progress", "aria-hidden": "true" },
|
|
655
1052
|
React.createElement("span", { style: { width: `${usedPercent}%` } })),
|
|
656
1053
|
React.createElement("span", { className: "designbase-figma-usage-status__usage-value" },
|
|
@@ -659,53 +1056,27 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20,
|
|
|
659
1056
|
"/",
|
|
660
1057
|
limit)))) : (React.createElement("span", { className: "designbase-figma-usage-status__plan-label" }, planLabel)))),
|
|
661
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))),
|
|
662
|
-
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', '사용량 상세') },
|
|
663
1060
|
React.createElement("div", { className: "designbase-figma-usage-status__popover-header" },
|
|
664
1061
|
React.createElement("span", { className: "designbase-figma-usage-status__plan-title" }, planTitle),
|
|
665
1062
|
!isBeta && (React.createElement(Button, { className: "designbase-figma-usage-status__upgrade", variant: isPaid ? 'secondary' : 'primary', size: "s", endIcon: "chevron-right", onPress: handleManageClick }, upgradeLabel))),
|
|
666
1063
|
isPaid ? (React.createElement("div", { className: "designbase-figma-usage-status__unlimited-copy" },
|
|
667
1064
|
React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E"),
|
|
668
|
-
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" },
|
|
669
1066
|
React.createElement("div", { className: "designbase-figma-usage-status__usage-summary" },
|
|
670
1067
|
React.createElement("strong", { className: "designbase-figma-usage-status__usage-count" },
|
|
671
1068
|
used,
|
|
672
1069
|
React.createElement("span", { className: "designbase-figma-usage-status__usage-divider" }, "/"),
|
|
673
1070
|
limit),
|
|
674
|
-
React.createElement("span", { className: "designbase-figma-usage-status__usage-caption" }, fallbackText(
|
|
675
|
-
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}` },
|
|
676
1073
|
React.createElement("span", { style: { width: `${usedPercent}%` } })),
|
|
677
|
-
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', '사용량 제한이 없습니다')))))));
|
|
678
1075
|
};
|
|
679
1076
|
UsageStatusPopover.displayName = 'UsageStatusPopover';
|
|
680
1077
|
|
|
681
|
-
const
|
|
682
|
-
|
|
683
|
-
proUser: '프로',
|
|
684
|
-
free: '무료',
|
|
685
|
-
trialPlan: '체험판',
|
|
686
|
-
planSuffix: '플랜',
|
|
687
|
-
usageDetails: '사용량 상세',
|
|
688
|
-
dailyUsage: '오늘 사용량',
|
|
689
|
-
usedToday: '오늘 사용',
|
|
690
|
-
remainingToday: '오늘 남은 사용량',
|
|
691
|
-
remainingUsage: '오늘 남은 사용량',
|
|
692
|
-
managePlan: '플랜 관리',
|
|
693
|
-
upgradePlan: '플랜 업그레이드',
|
|
694
|
-
remainingShort: '남음',
|
|
695
|
-
usageCountCaption: '오늘 사용',
|
|
696
|
-
remainingCopy: '{{count}}회 남음 · 매일 리셋',
|
|
697
|
-
usageUnavailable: '사용량 제한이 없습니다',
|
|
698
|
-
betaUsageDescription: '베타 기간에는 사용량 제한이 적용되지 않습니다',
|
|
699
|
-
perDay: '일',
|
|
700
|
-
resetsDaily: '매일 리셋',
|
|
701
|
-
donationPrompt: '이 플러그인이 유용했나요?',
|
|
702
|
-
betaStatus: 'BETA',
|
|
703
|
-
};
|
|
704
|
-
const defaultT = (key, values) => {
|
|
705
|
-
const template = defaultTranslations[key] || key;
|
|
706
|
-
return interpolateText(template, values);
|
|
707
|
-
};
|
|
708
|
-
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);
|
|
709
1080
|
const resolvedShowUsageInfo = showPaymentStatus && showUsageInfo;
|
|
710
1081
|
const resolvedShowPaymentBadge = showPaymentStatus && showPaymentBadge;
|
|
711
1082
|
const resolvedLicensePageClick = paymentStatus === 'BETA' ? undefined : onLicensePageClick;
|
|
@@ -716,10 +1087,10 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
716
1087
|
return (React.createElement("footer", { className: classes },
|
|
717
1088
|
React.createElement("div", { className: "designbase-figma-footer__wrap" },
|
|
718
1089
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
719
|
-
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 })),
|
|
720
1091
|
React.createElement("div", { className: "designbase-figma-footer__right" },
|
|
721
|
-
(resolvedShowUsageInfo || resolvedShowPaymentBadge) && (React.createElement(UsageStatusPopover, { paymentStatus: paymentStatus, usageCount: usageCount, maxDailyUsage: maxDailyUsage, showUsage: resolvedShowUsageInfo, showPlan: resolvedShowPaymentBadge, isLoading: isLoading, onLicensePageClick: resolvedLicensePageClick, t:
|
|
722
|
-
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 })))),
|
|
723
1094
|
children));
|
|
724
1095
|
};
|
|
725
1096
|
FigmaFooter.displayName = 'FigmaFooter';
|
|
@@ -795,7 +1166,8 @@ const useFigmaToast = () => {
|
|
|
795
1166
|
FigmaToastProvider.displayName = 'FigmaToastProvider';
|
|
796
1167
|
FigmaToast.displayName = 'FigmaToast';
|
|
797
1168
|
|
|
798
|
-
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);
|
|
799
1171
|
const [inputValue, setInputValue] = useState(value);
|
|
800
1172
|
useEffect(() => {
|
|
801
1173
|
setInputValue(value);
|
|
@@ -808,11 +1180,11 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
808
1180
|
setInputValue(value);
|
|
809
1181
|
onValueChange?.(value);
|
|
810
1182
|
};
|
|
811
|
-
const displayLabel = resolveText(
|
|
812
|
-
const displayPlaceholder = resolveText(
|
|
813
|
-
const displaySubmitText = resolveText(
|
|
814
|
-
const displaySubmittingText = resolveText(
|
|
815
|
-
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;
|
|
816
1188
|
return (React.createElement("form", { className: `designbase-figma-form-with-submit ${className || ''}`, onSubmit: handleSubmit },
|
|
817
1189
|
React.createElement("div", { className: "designbase-figma-form-with-submit__field" },
|
|
818
1190
|
React.createElement("label", { className: "designbase-figma-form-with-submit__label" }, displayLabel),
|
|
@@ -826,7 +1198,8 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
826
1198
|
};
|
|
827
1199
|
FormWithSubmit.displayName = 'FormWithSubmit';
|
|
828
1200
|
|
|
829
|
-
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);
|
|
830
1203
|
const feedbackClasses = clsx('designbase-figma-interaction', `designbase-figma-interaction--${status}`, {
|
|
831
1204
|
'designbase-figma-interaction--visible': visible,
|
|
832
1205
|
}, className);
|
|
@@ -835,38 +1208,28 @@ const InteractionFeedback = ({ status = 'default', message, statusMessage, leftC
|
|
|
835
1208
|
return (React.createElement("div", { className: feedbackClasses },
|
|
836
1209
|
React.createElement("div", { className: "designbase-figma-interaction__content" },
|
|
837
1210
|
React.createElement("div", { className: "designbase-figma-interaction__left" }, leftContent || (React.createElement("div", { className: "designbase-figma-interaction__message" },
|
|
838
|
-
status === 'loading' && (React.createElement(Spinner, { size: "s", type: "circular", label:
|
|
839
|
-
(message || status === 'loading') && (React.createElement("span", { className: "designbase-figma-interaction__text" }, resolveText(
|
|
840
|
-
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)))))),
|
|
841
1214
|
rightAction && (React.createElement("div", { className: "designbase-figma-interaction__right" }, rightAction)))));
|
|
842
1215
|
};
|
|
843
1216
|
InteractionFeedback.displayName = 'InteractionFeedback';
|
|
844
1217
|
|
|
845
|
-
let useTranslation = null;
|
|
846
|
-
try {
|
|
847
|
-
const reactI18next = require('react-i18next');
|
|
848
|
-
useTranslation = reactI18next.useTranslation;
|
|
849
|
-
}
|
|
850
|
-
catch (e) {
|
|
851
|
-
}
|
|
852
1218
|
const DEFAULT_LANGUAGES = [
|
|
853
1219
|
{ code: 'ko', label: 'KO' },
|
|
854
1220
|
{ code: 'en', label: 'EN' },
|
|
855
1221
|
];
|
|
856
1222
|
const LanguageSelector = ({ currentLanguage, languages = DEFAULT_LANGUAGES, onLanguageChange, size = 's', className, t }) => {
|
|
857
|
-
const
|
|
858
|
-
const activeLanguage = currentLanguage ||
|
|
1223
|
+
const { locale, t: translate } = useFigmaUiI18n(currentLanguage, t);
|
|
1224
|
+
const activeLanguage = currentLanguage || locale;
|
|
859
1225
|
const handleLanguageChange = (languageCode) => {
|
|
860
|
-
if (i18n) {
|
|
861
|
-
i18n.changeLanguage(languageCode);
|
|
862
|
-
}
|
|
863
1226
|
if (onLanguageChange) {
|
|
864
1227
|
onLanguageChange(languageCode);
|
|
865
1228
|
}
|
|
866
1229
|
};
|
|
867
1230
|
const segmentOptions = languages.map((language) => ({
|
|
868
1231
|
value: language.code,
|
|
869
|
-
label: resolveText(
|
|
1232
|
+
label: resolveText(translate, language.label, language.code.toUpperCase()),
|
|
870
1233
|
disabled: false,
|
|
871
1234
|
}));
|
|
872
1235
|
return (React.createElement("div", { className: `designbase-figma-language-selector ${className || ''}` },
|
|
@@ -898,25 +1261,26 @@ function openExternalUrl(url) {
|
|
|
898
1261
|
}
|
|
899
1262
|
}
|
|
900
1263
|
|
|
901
|
-
const LicenseOffer = ({ joinUrl, guideUrl, membershipUrl, t, className, }) => {
|
|
1264
|
+
const LicenseOffer = ({ joinUrl, guideUrl, membershipUrl, t, locale, className, }) => {
|
|
1265
|
+
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
902
1266
|
const titleId = `designbase-license-offer-title-${useId().replace(/:/g, '')}`;
|
|
903
1267
|
const resolvedJoinUrl = joinUrl || membershipUrl;
|
|
904
1268
|
const steps = [
|
|
905
|
-
resolveText(
|
|
906
|
-
resolveText(
|
|
907
|
-
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' }, '아래 입력창에 키를 붙여 넣고 활성화합니다.'),
|
|
908
1272
|
];
|
|
909
1273
|
return (React.createElement("section", { className: `designbase-figma-license-offer ${className || ''}`, "aria-labelledby": titleId },
|
|
910
|
-
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' }, '이용 방법')),
|
|
911
1275
|
React.createElement("ol", { className: "designbase-figma-license-offer__steps" }, steps.map((step, index) => (React.createElement("li", { key: index },
|
|
912
1276
|
React.createElement("span", { className: "designbase-figma-license-offer__step-index", "aria-hidden": "true" },
|
|
913
1277
|
index + 1,
|
|
914
1278
|
"."),
|
|
915
1279
|
React.createElement("span", null, step))))),
|
|
916
1280
|
(resolvedJoinUrl || guideUrl) && (React.createElement("div", { className: "designbase-figma-license-offer__actions" },
|
|
917
|
-
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' }, '멤버십 가입'))),
|
|
918
1282
|
guideUrl && (React.createElement(Button, { onPress: () => openExternalUrl(guideUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
919
|
-
React.createElement("span", null, resolveText(
|
|
1283
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.youtube_membership_guide' }, '안내보기')),
|
|
920
1284
|
React.createElement(ExternalLinkIcon, { size: 16, "aria-hidden": "true" })))))));
|
|
921
1285
|
};
|
|
922
1286
|
LicenseOffer.displayName = 'LicenseOffer';
|
|
@@ -926,13 +1290,13 @@ function maskLicenseKey(value) {
|
|
|
926
1290
|
return '••••••••';
|
|
927
1291
|
return `${value.slice(0, 4)}••••${value.slice(-4)}`;
|
|
928
1292
|
}
|
|
929
|
-
function formatDate(value) {
|
|
1293
|
+
function formatDate(value, locale) {
|
|
930
1294
|
if (!value)
|
|
931
1295
|
return undefined;
|
|
932
1296
|
const date = new Date(value);
|
|
933
1297
|
if (Number.isNaN(date.getTime()))
|
|
934
1298
|
return value;
|
|
935
|
-
return new Intl.DateTimeFormat(
|
|
1299
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(date);
|
|
936
1300
|
}
|
|
937
1301
|
function formatScope(value, t) {
|
|
938
1302
|
if (!value)
|
|
@@ -953,43 +1317,44 @@ function formatSource(value, t) {
|
|
|
953
1317
|
}
|
|
954
1318
|
return value;
|
|
955
1319
|
}
|
|
956
|
-
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);
|
|
957
1322
|
const [isKeyRevealed, setIsKeyRevealed] = useState(false);
|
|
958
1323
|
const normalizedLicenseStatus = licenseStatus?.toLowerCase();
|
|
959
1324
|
const isInactiveStatus = ['expired', 'revoked', 'invalid', 'inactive'].includes(normalizedLicenseStatus || '');
|
|
960
1325
|
const isActive = status === 'PAID' && !isInactiveStatus;
|
|
961
1326
|
const statusText = isActive
|
|
962
|
-
? resolveText(
|
|
963
|
-
: resolveText(
|
|
1327
|
+
? resolveText(translate, { key: 'license.status_active' }, 'Active')
|
|
1328
|
+
: resolveText(translate, { key: 'license.status_inactive' }, 'License check failed');
|
|
964
1329
|
const statusClass = isActive ? 'active' : 'inactive';
|
|
965
1330
|
return (React.createElement("section", { className: `designbase-figma-license-status-card designbase-figma-license-status-card--${statusClass} ${className || ''}`, "aria-label": statusText },
|
|
966
1331
|
React.createElement("div", { className: "designbase-figma-license-status-card__header" },
|
|
967
1332
|
React.createElement("div", null,
|
|
968
1333
|
React.createElement("div", { className: "designbase-figma-license-status-card__eyebrow" }, isActive
|
|
969
|
-
? resolveText(
|
|
970
|
-
: resolveText(
|
|
1334
|
+
? resolveText(translate, { key: 'license.activated' }, '라이선스 활성화됨')
|
|
1335
|
+
: resolveText(translate, { key: 'license.status_label' }, '라이선스 상태')),
|
|
971
1336
|
React.createElement("h3", null, statusText)),
|
|
972
1337
|
React.createElement("span", { className: "designbase-figma-license-status-card__badge" }, licenseStatus || (isActive ? 'active' : 'inactive'))),
|
|
973
1338
|
validationMessage && !isActive && (React.createElement("p", { className: "designbase-figma-license-status-card__message" }, validationMessage)),
|
|
974
1339
|
licenseKey && (React.createElement("div", { className: "designbase-figma-license-status-card__key-row" },
|
|
975
|
-
React.createElement("span", null, resolveText(
|
|
1340
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.key_label' }, '라이선스 키')),
|
|
976
1341
|
React.createElement("code", null, allowRevealKey && isKeyRevealed ? licenseKey : maskLicenseKey(licenseKey)),
|
|
977
1342
|
allowRevealKey && (React.createElement(Button, { type: "button", onPress: () => setIsKeyRevealed((value) => !value), variant: "tertiary", size: "s" }, isKeyRevealed
|
|
978
|
-
? resolveText(
|
|
979
|
-
: resolveText(
|
|
1343
|
+
? resolveText(translate, { key: 'license.hide_key' }, '숨기기')
|
|
1344
|
+
: resolveText(translate, { key: 'license.reveal_key' }, '보기'))))),
|
|
980
1345
|
(licenseSource || accessScope || expiresAt || lastVerifiedAt) && (React.createElement("dl", { className: "designbase-figma-license-status-card__meta" },
|
|
981
|
-
formatSource(licenseSource,
|
|
982
|
-
React.createElement("dt", null, resolveText(
|
|
983
|
-
React.createElement("dd", null, formatSource(licenseSource,
|
|
984
|
-
formatScope(accessScope,
|
|
985
|
-
React.createElement("dt", null, resolveText(
|
|
986
|
-
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))),
|
|
987
1352
|
expiresAt && React.createElement(React.Fragment, null,
|
|
988
|
-
React.createElement("dt", null, resolveText(
|
|
989
|
-
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)),
|
|
990
1355
|
lastVerifiedAt && React.createElement(React.Fragment, null,
|
|
991
|
-
React.createElement("dt", null, resolveText(
|
|
992
|
-
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))))));
|
|
993
1358
|
};
|
|
994
1359
|
LicenseStatusCard.displayName = 'LicenseStatusCard';
|
|
995
1360
|
|
|
@@ -1010,15 +1375,16 @@ function resolvePaymentFeedbackVariant(errorCode, explicitVariant) {
|
|
|
1010
1375
|
}
|
|
1011
1376
|
return 'error';
|
|
1012
1377
|
}
|
|
1013
|
-
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);
|
|
1014
1380
|
const remainingActivations = Math.max(0, activationLimit - activationUsage);
|
|
1015
|
-
const resolvedActionMessage = actionMessage ? resolveText(
|
|
1381
|
+
const resolvedActionMessage = actionMessage ? resolveText(translate, actionMessage) : undefined;
|
|
1016
1382
|
const feedbackVariant = resolvedActionMessage
|
|
1017
1383
|
? resolvePaymentFeedbackVariant(errorCode, actionMessageVariant)
|
|
1018
1384
|
: undefined;
|
|
1019
1385
|
return (React.createElement("div", { className: clsx('designbase-figma-payment-status', className) },
|
|
1020
1386
|
React.createElement("div", { className: "designbase-figma-payment-status__license-key" },
|
|
1021
|
-
resolveText(
|
|
1387
|
+
resolveText(translate, { key: 'payment.license_key_label' }, '라이선스 키'),
|
|
1022
1388
|
": ",
|
|
1023
1389
|
React.createElement("span", null, licenseKey)),
|
|
1024
1390
|
showDetails && (React.createElement("div", { className: "designbase-figma-payment-status__details" },
|
|
@@ -1026,41 +1392,60 @@ const PaymentStatusSection = ({ activationLimit, activationUsage, licenseKey, on
|
|
|
1026
1392
|
React.createElement("div", { className: "designbase-figma-payment-status__remaining" },
|
|
1027
1393
|
remainingActivations,
|
|
1028
1394
|
' ',
|
|
1029
|
-
resolveText(
|
|
1395
|
+
resolveText(translate, { key: 'payment.activations_remaining' }, '활성'),
|
|
1030
1396
|
' ',
|
|
1031
|
-
resolveText(
|
|
1397
|
+
resolveText(translate, { key: 'payment.spots_remaining' }, '자리 남음')),
|
|
1032
1398
|
React.createElement("div", { className: "designbase-figma-payment-status__usage" },
|
|
1033
1399
|
activationUsage,
|
|
1034
1400
|
"/",
|
|
1035
1401
|
activationLimit)),
|
|
1036
1402
|
React.createElement("div", { className: "designbase-figma-payment-status__action" },
|
|
1037
1403
|
React.createElement(Button, { onPress: onDeactivate, variant: "secondary", size: "s", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
1038
|
-
? resolveText(
|
|
1039
|
-
: resolveText(
|
|
1404
|
+
? resolveText(translate, { key: 'payment.deactivating' }, '비활성화중...')
|
|
1405
|
+
: resolveText(translate, { key: 'payment.deactivate_license' }, '라이선스 비활성화')),
|
|
1040
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)))))));
|
|
1041
1407
|
};
|
|
1042
1408
|
PaymentStatusSection.displayName = 'PaymentStatusSection';
|
|
1043
1409
|
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
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
|
+
};
|
|
1051
1433
|
const defaultPricing = {
|
|
1052
1434
|
monthly: 2,
|
|
1053
1435
|
yearly: 21.6,
|
|
1054
1436
|
lifetime: 50,
|
|
1055
1437
|
};
|
|
1056
|
-
const PricingComparison = ({ features
|
|
1438
|
+
const PricingComparison = ({ features, pricing = defaultPricing, paymentType = 'subscription', t, locale, className, }) => {
|
|
1439
|
+
const { locale: resolvedLocale, t: translate } = useFigmaUiI18n(locale, t);
|
|
1057
1440
|
const [isYearly, setIsYearly] = useState(false);
|
|
1441
|
+
const resolvedFeatures = features ?? defaultFeaturesByLocale[resolvedLocale];
|
|
1442
|
+
const resolveFeatureValue = (value) => typeof value === 'boolean' ? (value ? '✓' : '✗') : value;
|
|
1058
1443
|
const getPrice = () => {
|
|
1059
1444
|
if (paymentType === 'lifetime') {
|
|
1060
|
-
return `$${pricing.lifetime?.toLocaleString()} - ${
|
|
1445
|
+
return `$${pricing.lifetime?.toLocaleString()} - ${translate('lifetimeAccess')}`;
|
|
1061
1446
|
}
|
|
1062
1447
|
const price = isYearly ? pricing.yearly : pricing.monthly;
|
|
1063
|
-
return `$${price?.toLocaleString()} / ${isYearly ?
|
|
1448
|
+
return `$${price?.toLocaleString()} / ${isYearly ? translate('perYear') : translate('perMonth')}`;
|
|
1064
1449
|
};
|
|
1065
1450
|
const getDiscountPercentage = () => {
|
|
1066
1451
|
if (paymentType === 'lifetime') {
|
|
@@ -1083,46 +1468,34 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
1083
1468
|
}, options: [
|
|
1084
1469
|
{
|
|
1085
1470
|
value: 'monthly',
|
|
1086
|
-
label:
|
|
1471
|
+
label: translate('monthlyBilling'),
|
|
1087
1472
|
},
|
|
1088
1473
|
{
|
|
1089
1474
|
value: 'yearly',
|
|
1090
|
-
label: `${
|
|
1475
|
+
label: `${translate('yearlyBilling')} (${getDiscountPercentage()}% ${translate('pricing.discount_suffix')})`,
|
|
1091
1476
|
},
|
|
1092
1477
|
], size: "s" }))),
|
|
1093
1478
|
paymentType === 'lifetime' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__lifetime-info" },
|
|
1094
|
-
React.createElement("p", { className: "designbase-figma-pricing-comparison__lifetime-text" },
|
|
1479
|
+
React.createElement("p", { className: "designbase-figma-pricing-comparison__lifetime-text" }, translate('oneTimePaymentLifetime')))),
|
|
1095
1480
|
React.createElement("table", { className: "designbase-figma-pricing-comparison__table" },
|
|
1096
1481
|
React.createElement("thead", null,
|
|
1097
1482
|
React.createElement("tr", null,
|
|
1098
|
-
React.createElement("th", null,
|
|
1483
|
+
React.createElement("th", null, translate('feature')),
|
|
1099
1484
|
React.createElement("th", null,
|
|
1100
|
-
React.createElement("div", { className: "designbase-figma-pricing-comparison__plan-name" },
|
|
1101
|
-
React.createElement("div", null,
|
|
1485
|
+
React.createElement("div", { className: "designbase-figma-pricing-comparison__plan-name" }, translate('free')),
|
|
1486
|
+
React.createElement("div", null, translate('freePrice'))),
|
|
1102
1487
|
React.createElement("th", { className: "designbase-figma-pricing-comparison__recommended" },
|
|
1103
1488
|
React.createElement("div", { className: "designbase-figma-pricing-comparison__plan-name" },
|
|
1104
|
-
|
|
1105
|
-
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'))),
|
|
1106
1491
|
React.createElement("div", null, getPrice())))),
|
|
1107
|
-
React.createElement("tbody", null,
|
|
1492
|
+
React.createElement("tbody", null, resolvedFeatures.map((feature, index) => (React.createElement("tr", { key: index },
|
|
1108
1493
|
React.createElement("td", null, feature.name),
|
|
1109
|
-
React.createElement("td", null,
|
|
1110
|
-
|
|
1111
|
-
: feature.free),
|
|
1112
|
-
React.createElement("td", null, typeof feature.pro === 'boolean'
|
|
1113
|
-
? (feature.pro ? '✓' : '✗')
|
|
1114
|
-
: feature.pro))))))));
|
|
1494
|
+
React.createElement("td", null, resolveFeatureValue(feature.free)),
|
|
1495
|
+
React.createElement("td", null, resolveFeatureValue(feature.pro)))))))));
|
|
1115
1496
|
};
|
|
1116
1497
|
PricingComparison.displayName = 'PricingComparison';
|
|
1117
1498
|
|
|
1118
|
-
const DEFAULT_LICENSE_MESSAGE_TYPES = {
|
|
1119
|
-
initialize: 'initialize',
|
|
1120
|
-
verifyLicense: 'verify-license',
|
|
1121
|
-
deactivateLicense: 'deactivate-license',
|
|
1122
|
-
updateStatus: 'update-plugin-status',
|
|
1123
|
-
verifyResult: 'license-verification-result',
|
|
1124
|
-
deactivateResult: 'license-deactivation-result',
|
|
1125
|
-
};
|
|
1126
1499
|
const START_DESIGNBASE_AUTH_MESSAGE = 'start-designbase-auth';
|
|
1127
1500
|
const INITIAL_LICENSE_PAGE_STATE = {
|
|
1128
1501
|
paymentStatus: 'FREE',
|
|
@@ -1277,6 +1650,9 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1277
1650
|
applyPatch({ lastMessage: payload.message });
|
|
1278
1651
|
}
|
|
1279
1652
|
}
|
|
1653
|
+
if (type === messageTypes.featureAccessResult || type === messageTypes.usageConsumeResult) {
|
|
1654
|
+
applyPatch(parseLicenseMessage(payload));
|
|
1655
|
+
}
|
|
1280
1656
|
};
|
|
1281
1657
|
window.addEventListener('message', handleMessage);
|
|
1282
1658
|
postPluginMessage({ type: messageTypes.initialize });
|
|
@@ -1301,6 +1677,20 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1301
1677
|
setIsStartingAuth(true);
|
|
1302
1678
|
postPluginMessage({ type: START_DESIGNBASE_AUTH_MESSAGE });
|
|
1303
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]);
|
|
1304
1694
|
return {
|
|
1305
1695
|
state,
|
|
1306
1696
|
isVerifying,
|
|
@@ -1309,6 +1699,8 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1309
1699
|
verifyLicense,
|
|
1310
1700
|
deactivateLicense,
|
|
1311
1701
|
startDesignbaseAuth,
|
|
1702
|
+
checkFeatureAccess,
|
|
1703
|
+
consumeUsage,
|
|
1312
1704
|
setLicenseKeyInput: (licenseKey) => applyPatch({ licenseKey }),
|
|
1313
1705
|
};
|
|
1314
1706
|
}
|
|
@@ -1322,17 +1714,23 @@ function formatUsageLabel(state, t) {
|
|
|
1322
1714
|
const remaining = remainingUsage ?? Math.max(0, limit - usageUsed);
|
|
1323
1715
|
if (usageReset === 'daily') {
|
|
1324
1716
|
const fallback = `오늘 남은 횟수 ${remaining}/${limit}`;
|
|
1325
|
-
const translated = resolveText(t, { key: 'license.usage_daily' }, fallback) ?? fallback;
|
|
1717
|
+
const translated = resolveText(t, { key: 'license.usage_daily', values: { remaining, limit } }, fallback) ?? fallback;
|
|
1326
1718
|
return translated.includes(String(remaining)) ? translated : fallback;
|
|
1327
1719
|
}
|
|
1328
1720
|
if (usageReset === 'monthly') {
|
|
1329
1721
|
const fallback = `이번 달 남은 횟수 ${remaining}/${limit}`;
|
|
1330
|
-
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;
|
|
1331
1728
|
return translated.includes(String(remaining)) ? translated : fallback;
|
|
1332
1729
|
}
|
|
1333
|
-
return `남은 횟수 ${remaining}/${limit}`;
|
|
1730
|
+
return resolveText(t, { key: 'license.usage_generic', values: { remaining, limit } }, `남은 횟수 ${remaining}/${limit}`) ?? `남은 횟수 ${remaining}/${limit}`;
|
|
1334
1731
|
}
|
|
1335
|
-
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);
|
|
1336
1734
|
const links = useMemo(() => ({
|
|
1337
1735
|
purchaseUrl: wordpressLinks?.purchaseUrl ?? paymentPageUrl,
|
|
1338
1736
|
membershipUrl: membershipUrl ?? wordpressLinks?.membershipUrl,
|
|
@@ -1354,7 +1752,7 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1354
1752
|
const [licenseKeyDraft, setLicenseKeyDraft] = useState(initialLicenseKey);
|
|
1355
1753
|
const isPaid = state.isLicenseRegistered && state.paymentStatus === 'PAID';
|
|
1356
1754
|
const isMembershipMode = mode === 'youtube-membership';
|
|
1357
|
-
const usageLabel = formatUsageLabel(state,
|
|
1755
|
+
const usageLabel = formatUsageLabel(state, translate);
|
|
1358
1756
|
const handleLicenseSubmit = async (submittedLicenseKey) => {
|
|
1359
1757
|
if (onLicenseSubmit) {
|
|
1360
1758
|
await onLicenseSubmit(submittedLicenseKey);
|
|
@@ -1371,79 +1769,80 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1371
1769
|
React.createElement("div", { className: "designbase-figma-page-license__header" },
|
|
1372
1770
|
React.createElement("div", { className: "designbase-figma-page-license__title" },
|
|
1373
1771
|
React.createElement("h2", null, isMembershipMode
|
|
1374
|
-
? resolveText(
|
|
1772
|
+
? resolveText(translate, { key: 'license.youtube_membership' }, 'YouTube 멤버십')
|
|
1375
1773
|
: isPaid
|
|
1376
|
-
? resolveText(
|
|
1377
|
-
: resolveText(
|
|
1774
|
+
? resolveText(translate, { key: 'license.pro_account' }, '프로 계정')
|
|
1775
|
+
: resolveText(translate, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
|
|
1378
1776
|
state.planTier && state.planTier !== 'FREE' && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, state.planTier))),
|
|
1379
1777
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
1380
|
-
? resolveText(
|
|
1778
|
+
? resolveText(translate, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
1381
1779
|
: isMembershipMode
|
|
1382
|
-
? resolveText(
|
|
1383
|
-
: resolveText(
|
|
1780
|
+
? resolveText(translate, { key: 'license.youtube_membership_description' }, 'YouTube 멤버십에 가입하면 Designbase 플러그인을 무제한으로 사용할 수 있습니다.')
|
|
1781
|
+
: resolveText(translate, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
|
|
1384
1782
|
!isPaid && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
1385
|
-
!isMembershipMode && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t:
|
|
1783
|
+
!isMembershipMode && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: translate })),
|
|
1386
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)),
|
|
1387
1785
|
isPaid && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1388
1786
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1389
|
-
React.createElement("h3", null, resolveText(
|
|
1787
|
+
React.createElement("h3", null, resolveText(translate, { key: 'license.activated' }, '라이선스 활성화됨')),
|
|
1390
1788
|
React.createElement(Button, { onPress: () => setShowDetails(!showDetails), variant: "tertiary", size: "s", iconOnly: true },
|
|
1391
1789
|
React.createElement(MoreHorizontalIcon, { size: 16 }))),
|
|
1392
|
-
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 }),
|
|
1393
1791
|
React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel),
|
|
1394
1792
|
showDetails && (React.createElement("div", { className: "designbase-figma-page-license__details" },
|
|
1395
1793
|
React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
1396
1794
|
React.createElement("div", { className: "designbase-figma-page-license__remaining" },
|
|
1397
1795
|
Math.max(0, state.activationLimit - state.activationUsage),
|
|
1398
1796
|
' ',
|
|
1399
|
-
resolveText(
|
|
1797
|
+
resolveText(translate, { key: 'license.activations_remaining' }, '활성'),
|
|
1400
1798
|
' ',
|
|
1401
|
-
resolveText(
|
|
1799
|
+
resolveText(translate, { key: 'license.spots_remaining' }, '자리 남음')),
|
|
1402
1800
|
React.createElement("div", { className: "designbase-figma-page-license__usage-count" },
|
|
1403
1801
|
state.activationUsage,
|
|
1404
1802
|
"/",
|
|
1405
1803
|
state.activationLimit)),
|
|
1406
1804
|
React.createElement("div", { className: "designbase-figma-page-license__action" },
|
|
1407
1805
|
React.createElement(Button, { onPress: deactivateLicense, variant: "secondary", size: "s", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
1408
|
-
? resolveText(
|
|
1409
|
-
: resolveText(
|
|
1806
|
+
? resolveText(translate, { key: 'license.deactivating' }, '비활성화 중...')
|
|
1807
|
+
: resolveText(translate, { key: 'license.deactivate' }, '라이선스 비활성화')),
|
|
1410
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))))))),
|
|
1411
1809
|
!isPaid && (React.createElement(React.Fragment, null,
|
|
1412
|
-
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 })),
|
|
1413
1811
|
!isMembershipMode && (enableAccountAuth || links.purchaseUrl || links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1414
1812
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1415
|
-
React.createElement("h3", null, resolveText(
|
|
1416
|
-
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 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.')),
|
|
1417
1815
|
React.createElement("div", { className: "designbase-figma-page-license__actions" },
|
|
1418
1816
|
enableAccountAuth && (React.createElement(Button, { onPress: startDesignbaseAuth, variant: "primary", size: "m", disabled: isStartingAuth || isVerifying, fullWidth: true }, isStartingAuth
|
|
1419
|
-
? resolveText(
|
|
1420
|
-
: resolveText(
|
|
1817
|
+
? resolveText(translate, { key: 'license.authenticating' }, '인증 중...')
|
|
1818
|
+
: resolveText(translate, { key: 'license.login_with_designbase' }, '디자인베이스로 로그인'))),
|
|
1421
1819
|
links.purchaseUrl && (React.createElement(Button, { onPress: () => openExternalUrl(links.purchaseUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
1422
|
-
React.createElement("span", null, resolveText(
|
|
1820
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.purchase_membership' }, '멤버십 안내')),
|
|
1423
1821
|
React.createElement(ExternalLinkIcon, { size: 16 }))),
|
|
1424
1822
|
links.accountUrl && (React.createElement(Button, { onPress: () => openExternalUrl(links.accountUrl), variant: "tertiary", size: "s", fullWidth: true },
|
|
1425
|
-
React.createElement("span", null, resolveText(
|
|
1823
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.manage_account' }, '계정·멤버십 관리')),
|
|
1426
1824
|
React.createElement(ExternalLinkIcon, { size: 16 })))))),
|
|
1427
1825
|
showLicenseKeyInput && (React.createElement("div", { className: isMembershipMode
|
|
1428
1826
|
? 'designbase-figma-page-license__key-form'
|
|
1429
1827
|
: 'designbase-figma-page-license__section' },
|
|
1430
1828
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1431
|
-
React.createElement("h3", null, resolveText(
|
|
1432
|
-
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 }))))),
|
|
1433
1831
|
links.helpUrl && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
1434
|
-
React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(
|
|
1435
|
-
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') },
|
|
1436
1834
|
React.createElement(CloseIcon, { size: 16 }))));
|
|
1437
1835
|
};
|
|
1438
1836
|
PageLicense.displayName = 'PageLicense';
|
|
1439
1837
|
|
|
1440
|
-
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);
|
|
1441
1840
|
const getBadgeText = () => {
|
|
1442
1841
|
if (text)
|
|
1443
1842
|
return text;
|
|
1444
1843
|
return isActive
|
|
1445
|
-
? (
|
|
1446
|
-
: (
|
|
1844
|
+
? translate('proUser')
|
|
1845
|
+
: translate('usingFree');
|
|
1447
1846
|
};
|
|
1448
1847
|
const getBadgeVariant = () => {
|
|
1449
1848
|
return isActive ? 'success' : 'secondary';
|
|
@@ -1452,7 +1851,8 @@ const PaymentBadge = ({ isActive, onClick, isLoading = false, text, t = (key) =>
|
|
|
1452
1851
|
};
|
|
1453
1852
|
PaymentBadge.displayName = 'PaymentBadge';
|
|
1454
1853
|
|
|
1455
|
-
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);
|
|
1456
1856
|
const [isCompleted, setIsCompleted] = useState(false);
|
|
1457
1857
|
const completeFiredRef = useRef(false);
|
|
1458
1858
|
const { processedNodes, totalNodes } = progress;
|
|
@@ -1482,11 +1882,11 @@ const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.wor
|
|
|
1482
1882
|
onClose();
|
|
1483
1883
|
};
|
|
1484
1884
|
const modalClasses = clsx('designbase-figma-progress-modal', className);
|
|
1485
|
-
const displayTitle = resolveText(
|
|
1486
|
-
const displayMessage = resolveText(
|
|
1487
|
-
const displayStopText = resolveText(
|
|
1488
|
-
const displayConfirmText = resolveText(
|
|
1489
|
-
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);
|
|
1490
1890
|
return (React.createElement(Modal, { isOpen: isOpen, onClose: isCompleted ? onClose : undefined, title: displayTitle, size: "s", className: modalClasses, showCloseButton: false },
|
|
1491
1891
|
React.createElement("div", { className: "designbase-figma-progress-modal__content" },
|
|
1492
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" },
|
|
@@ -1540,7 +1940,8 @@ const ResizablePlugin = ({ children, minWidth = 360, maxWidth = 460, minHeight =
|
|
|
1540
1940
|
};
|
|
1541
1941
|
ResizablePlugin.displayName = 'ResizablePlugin';
|
|
1542
1942
|
|
|
1543
|
-
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);
|
|
1544
1945
|
const [tempCategories, setTempCategories] = useState(initialCategories);
|
|
1545
1946
|
const [draggedIndex, setDraggedIndex] = useState(null);
|
|
1546
1947
|
useEffect(() => {
|
|
@@ -1633,8 +2034,8 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1633
2034
|
}
|
|
1634
2035
|
};
|
|
1635
2036
|
const modalClasses = clsx('designbase-figma-settings-modal', className);
|
|
1636
|
-
const displayTitle = resolveText(
|
|
1637
|
-
const displayDescription = resolveText(
|
|
2037
|
+
const displayTitle = resolveText(translate, title, '목록 변경');
|
|
2038
|
+
const displayDescription = resolveText(translate, description, '드래그하여 순서를 변경하거나, 토글하여 카테고리를 숨길 수 있습니다.');
|
|
1638
2039
|
return (React.createElement(Modal, { isOpen: isOpen, onClose: onClose, title: displayTitle, size: "m", className: modalClasses },
|
|
1639
2040
|
React.createElement("div", { className: "designbase-figma-settings-modal__content" },
|
|
1640
2041
|
displayDescription && (React.createElement("p", { className: "designbase-figma-settings-modal__description" }, displayDescription)),
|
|
@@ -1646,32 +2047,33 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1646
2047
|
React.createElement("span", { className: "designbase-figma-settings-modal__drag-handle" },
|
|
1647
2048
|
React.createElement(GripVerticalIcon, { size: 16 })),
|
|
1648
2049
|
category.icon && (React.createElement("span", { className: "designbase-figma-settings-modal__category-icon" }, category.icon)),
|
|
1649
|
-
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))),
|
|
1650
2051
|
React.createElement(Toggle, { checked: category.enabled, onChange: () => handleToggle(category.id), size: "s" })))))),
|
|
1651
2052
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer" },
|
|
1652
|
-
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' }, '초기화'))),
|
|
1653
2054
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer-right" },
|
|
1654
|
-
React.createElement(Button, { onPress: handleCancel, variant: "tertiary", size: "s" }, resolveText(
|
|
1655
|
-
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' }, '저장'))))));
|
|
1656
2057
|
};
|
|
1657
2058
|
SettingsModal.displayName = 'SettingsModal';
|
|
1658
2059
|
|
|
1659
|
-
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);
|
|
1660
2062
|
const classes = [
|
|
1661
2063
|
'designbase-figma-title-description',
|
|
1662
2064
|
className,
|
|
1663
2065
|
]
|
|
1664
2066
|
.filter(Boolean)
|
|
1665
2067
|
.join(' ');
|
|
1666
|
-
const displayTitle = resolveText(
|
|
1667
|
-
const displayDescription = resolveText(
|
|
2068
|
+
const displayTitle = resolveText(translate, title);
|
|
2069
|
+
const displayDescription = resolveText(translate, description);
|
|
1668
2070
|
return (React.createElement("div", { className: classes },
|
|
1669
2071
|
iconSrc && (React.createElement("img", { className: "designbase-figma-title-description__icon", src: iconSrc, alt: iconAlt })),
|
|
1670
2072
|
React.createElement("h5", { className: "designbase-figma-title-description__title" }, displayTitle),
|
|
1671
2073
|
React.createElement("p", { className: "designbase-figma-title-description__description" }, displayDescription),
|
|
1672
2074
|
button && React.createElement("div", { className: "designbase-figma-title-description__button" }, button),
|
|
1673
2075
|
features && features.length > 0 && (React.createElement("ul", { className: "designbase-figma-title-description__features" }, features.map((feature, index) => {
|
|
1674
|
-
const displayFeature = resolveText(
|
|
2076
|
+
const displayFeature = resolveText(translate, feature);
|
|
1675
2077
|
return (React.createElement("li", { key: index, className: "designbase-figma-title-description__feature-item" },
|
|
1676
2078
|
React.createElement("span", { className: "designbase-figma-title-description__check-icon" },
|
|
1677
2079
|
React.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
|
|
@@ -1682,10 +2084,11 @@ const TitleDescription = ({ iconSrc, iconAlt = 'Icon', title, description, butto
|
|
|
1682
2084
|
};
|
|
1683
2085
|
TitleDescription.displayName = 'TitleDescription';
|
|
1684
2086
|
|
|
1685
|
-
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 }) => {
|
|
1686
|
-
const
|
|
1687
|
-
const
|
|
1688
|
-
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, '지금 업그레이드');
|
|
1689
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) => {
|
|
1690
2093
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
1691
2094
|
e.preventDefault();
|
|
@@ -1701,5 +2104,5 @@ const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title =
|
|
|
1701
2104
|
};
|
|
1702
2105
|
UpgradeBanner.displayName = 'UpgradeBanner';
|
|
1703
2106
|
|
|
1704
|
-
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 };
|
|
1705
2108
|
//# sourceMappingURL=index.esm.js.map
|