@designbasekorea/figma-ui 0.7.0 → 0.7.2
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/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +243 -59
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +242 -58
- package/dist/index.js.map +1 -1
- package/package.json +100 -100
package/dist/index.esm.js
CHANGED
|
@@ -2,7 +2,7 @@ import React, { createContext, useMemo, useContext, useRef, useState, useLayoutE
|
|
|
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
|
-
import { ChevronDownIcon, AppWindowIcon, YoutubeIcon, InstagramIcon, FigmaIcon, MailIcon, ExternalLinkIcon, TranslateIcon,
|
|
5
|
+
import { ChevronDownIcon, AppWindowIcon, YoutubeIcon, InstagramIcon, FigmaIcon, MailIcon, ExternalLinkIcon, TranslateIcon, CloseIcon, CircleCheckFilledIcon, ResizableIcon, GripVerticalIcon, ChevronRightIcon } from '@designbasekorea/icons';
|
|
6
6
|
import { DEFAULT_LICENSE_MESSAGE_TYPES } from '@designbasekorea/figma-license-core';
|
|
7
7
|
export { DEFAULT_LICENSE_MESSAGE_TYPES } from '@designbasekorea/figma-license-core';
|
|
8
8
|
|
|
@@ -53,12 +53,30 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
53
53
|
'form.submit': '제출',
|
|
54
54
|
'form.verifying': '확인 중...',
|
|
55
55
|
'license.youtube_membership': 'YouTube 멤버십',
|
|
56
|
+
'license.unlock_unlimited': '무제한 사용 활성화',
|
|
57
|
+
'license.unlock_unlimited_description': '라이선스 키를 등록하면 모든 Designbase 플러그인의 프로 기능과 무제한 사용을 이용할 수 있습니다.',
|
|
58
|
+
'license.get_key_title': '라이선스 키 받기',
|
|
59
|
+
'license.get_key_description': '멤버십 회원에게 매월 새 라이선스 키가 제공됩니다.',
|
|
60
|
+
'license.get_key_step_1_title': '멤버십 가입',
|
|
61
|
+
'license.get_key_step_1_description': 'Designbase YouTube 채널에서 멤버십에 가입합니다.',
|
|
62
|
+
'license.get_key_step_2_title': '이번 달 키 복사',
|
|
63
|
+
'license.get_key_step_2_description': '멤버 전용 커뮤니티 게시글에서 키를 확인합니다.',
|
|
64
|
+
'license.get_key_step_3_title': '키 등록',
|
|
65
|
+
'license.get_key_step_3_description': '아래 입력창에 붙여 넣으면 프로 기능이 열립니다.',
|
|
66
|
+
'license.get_key_cta': '멤버십 가입하고 키 받기',
|
|
67
|
+
'license.activate_key_title': '라이선스 키 등록',
|
|
68
|
+
'license.activate_key_description': '이미 키가 있다면 아래에 붙여 넣어 프로 기능을 활성화하세요.',
|
|
69
|
+
'license.unlock_pro_features': '프로 기능 활성화',
|
|
70
|
+
'license.current_plan': '현재 플랜',
|
|
71
|
+
'license.pro_plan': '프로 플랜',
|
|
72
|
+
'license.membership': '멤버십',
|
|
56
73
|
'license.pro_account': '프로 계정',
|
|
57
74
|
'license.upgrade_to_pro': '프로로 업그레이드',
|
|
58
75
|
'license.all_features_available': '모든 기능을 사용할 수 있습니다.',
|
|
59
76
|
'license.youtube_membership_description': 'YouTube 멤버십에 가입하면 Designbase 플러그인을 무제한으로 사용할 수 있습니다.',
|
|
60
77
|
'license.purchase_for_unlimited': '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.',
|
|
61
78
|
'license.usage_unlimited': '사용 횟수 제한 없음',
|
|
79
|
+
'license.active_until_expiry': '만료일까지 모든 기능을 제한 없이 사용할 수 있습니다.',
|
|
62
80
|
'license.usage_daily': '오늘 남은 횟수 {{remaining}}/{{limit}}',
|
|
63
81
|
'license.usage_weekly': '이번 주 남은 횟수 {{remaining}}/{{limit}}',
|
|
64
82
|
'license.usage_monthly': '이번 달 남은 횟수 {{remaining}}/{{limit}}',
|
|
@@ -68,6 +86,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
68
86
|
'license.spots_remaining': '자리 남음',
|
|
69
87
|
'license.deactivating': '비활성화 중...',
|
|
70
88
|
'license.deactivate': '라이선스 비활성화',
|
|
89
|
+
'license.deactivate_hint': '이 기기에서 라이선스 연결을 해제합니다.',
|
|
71
90
|
'license.designbase_account': '디자인베이스 계정',
|
|
72
91
|
'license.designbase_account_hint': 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.',
|
|
73
92
|
'license.authenticating': '인증 중...',
|
|
@@ -79,7 +98,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
79
98
|
'license.submit': '활성화',
|
|
80
99
|
'license.verifying': '확인 중...',
|
|
81
100
|
'license.enter_from_email': '이메일로 받은 라이선스 키를 입력하세요.',
|
|
82
|
-
'license.enter_from_youtube': '멤버 전용
|
|
101
|
+
'license.enter_from_youtube': '멤버 전용 게시글에서 복사한 이번 달 키를 입력하세요.',
|
|
83
102
|
'license.help_link': '라이선스·결제 도움말',
|
|
84
103
|
'license.youtube_membership_howto': '이용 방법',
|
|
85
104
|
'license.youtube_membership_step_1': 'Designbase YouTube 채널 멤버십에 가입합니다.',
|
|
@@ -186,12 +205,30 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
186
205
|
'form.submit': 'Activate',
|
|
187
206
|
'form.verifying': 'Verifying...',
|
|
188
207
|
'license.youtube_membership': 'YouTube Membership',
|
|
208
|
+
'license.unlock_unlimited': 'Unlock Unlimited Access',
|
|
209
|
+
'license.unlock_unlimited_description': 'Add a license key to unlock Pro features and unlimited use across Designbase plugins.',
|
|
210
|
+
'license.get_key_title': 'Get a license key',
|
|
211
|
+
'license.get_key_description': 'Members receive a new license key every month.',
|
|
212
|
+
'license.get_key_step_1_title': 'Join the membership',
|
|
213
|
+
'license.get_key_step_1_description': 'Join the Designbase YouTube channel membership.',
|
|
214
|
+
'license.get_key_step_2_title': 'Copy this month’s key',
|
|
215
|
+
'license.get_key_step_2_description': 'Find the key in the members-only community post.',
|
|
216
|
+
'license.get_key_step_3_title': 'Activate the key',
|
|
217
|
+
'license.get_key_step_3_description': 'Paste it below to unlock Pro features.',
|
|
218
|
+
'license.get_key_cta': 'Join and get a license key',
|
|
219
|
+
'license.activate_key_title': 'Activate your license key',
|
|
220
|
+
'license.activate_key_description': 'Already have a key? Paste it below to unlock Pro features.',
|
|
221
|
+
'license.unlock_pro_features': 'Unlock Pro features',
|
|
222
|
+
'license.current_plan': 'Current plan',
|
|
223
|
+
'license.pro_plan': 'Pro plan',
|
|
224
|
+
'license.membership': 'Membership',
|
|
189
225
|
'license.pro_account': 'Pro account',
|
|
190
226
|
'license.upgrade_to_pro': 'Upgrade to Pro',
|
|
191
227
|
'license.all_features_available': 'All features are available.',
|
|
192
228
|
'license.youtube_membership_description': 'Join YouTube Membership to use Designbase plugins without limits.',
|
|
193
229
|
'license.purchase_for_unlimited': 'Get unlimited access with a Designbase membership or license.',
|
|
194
230
|
'license.usage_unlimited': 'Unlimited usage',
|
|
231
|
+
'license.active_until_expiry': 'All features remain available without limits until expiration.',
|
|
195
232
|
'license.usage_daily': '{{remaining}}/{{limit}} remaining today',
|
|
196
233
|
'license.usage_weekly': '{{remaining}}/{{limit}} remaining this week',
|
|
197
234
|
'license.usage_monthly': '{{remaining}}/{{limit}} remaining this month',
|
|
@@ -201,6 +238,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
201
238
|
'license.spots_remaining': 'spots remaining',
|
|
202
239
|
'license.deactivating': 'Deactivating...',
|
|
203
240
|
'license.deactivate': 'Deactivate license',
|
|
241
|
+
'license.deactivate_hint': 'Disconnects this license from the current device.',
|
|
204
242
|
'license.designbase_account': 'Designbase account',
|
|
205
243
|
'license.designbase_account_hint': 'Sign in with your WordPress account or purchase a membership to activate the plugin automatically.',
|
|
206
244
|
'license.authenticating': 'Authenticating...',
|
|
@@ -212,7 +250,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
212
250
|
'license.submit': 'Activate',
|
|
213
251
|
'license.verifying': 'Verifying...',
|
|
214
252
|
'license.enter_from_email': 'Enter the license key you received by email.',
|
|
215
|
-
'license.enter_from_youtube': 'Enter
|
|
253
|
+
'license.enter_from_youtube': 'Enter this month’s key copied from the members-only post.',
|
|
216
254
|
'license.help_link': 'License · payment help',
|
|
217
255
|
'license.youtube_membership_howto': 'How to use',
|
|
218
256
|
'license.youtube_membership_step_1': 'Join the Designbase YouTube channel membership.',
|
|
@@ -319,12 +357,30 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
319
357
|
'form.submit': '有効化',
|
|
320
358
|
'form.verifying': '確認中...',
|
|
321
359
|
'license.youtube_membership': 'YouTubeメンバーシップ',
|
|
360
|
+
'license.unlock_unlimited': '無制限アクセスを有効化',
|
|
361
|
+
'license.unlock_unlimited_description': 'ライセンスキーを登録すると、DesignbaseプラグインのPro機能を無制限で利用できます。',
|
|
362
|
+
'license.get_key_title': 'ライセンスキーを取得',
|
|
363
|
+
'license.get_key_description': 'メンバーには毎月新しいライセンスキーが提供されます。',
|
|
364
|
+
'license.get_key_step_1_title': 'メンバーシップに参加',
|
|
365
|
+
'license.get_key_step_1_description': 'Designbase YouTubeチャンネルのメンバーシップに参加します。',
|
|
366
|
+
'license.get_key_step_2_title': '今月のキーをコピー',
|
|
367
|
+
'license.get_key_step_2_description': 'メンバー限定コミュニティの投稿でキーを確認します。',
|
|
368
|
+
'license.get_key_step_3_title': 'キーを登録',
|
|
369
|
+
'license.get_key_step_3_description': '下の入力欄に貼り付けるとPro機能が利用できます。',
|
|
370
|
+
'license.get_key_cta': '参加してライセンスキーを取得',
|
|
371
|
+
'license.activate_key_title': 'ライセンスキーを登録',
|
|
372
|
+
'license.activate_key_description': 'キーをお持ちの場合は、下に貼り付けてPro機能を有効化してください。',
|
|
373
|
+
'license.unlock_pro_features': 'Pro機能を有効化',
|
|
374
|
+
'license.current_plan': '現在のプラン',
|
|
375
|
+
'license.pro_plan': 'Proプラン',
|
|
376
|
+
'license.membership': 'メンバーシップ',
|
|
322
377
|
'license.pro_account': 'Proアカウント',
|
|
323
378
|
'license.upgrade_to_pro': 'Proにアップグレード',
|
|
324
379
|
'license.all_features_available': 'すべての機能を使用できます。',
|
|
325
380
|
'license.youtube_membership_description': 'YouTubeメンバーシップに参加すると、Designbaseプラグインを無制限で使用できます。',
|
|
326
381
|
'license.purchase_for_unlimited': 'Designbaseのメンバーシップまたはライセンスで無制限に利用できます。',
|
|
327
382
|
'license.usage_unlimited': '使用回数の制限なし',
|
|
383
|
+
'license.active_until_expiry': '有効期限まで、すべての機能を制限なく使用できます。',
|
|
328
384
|
'license.usage_daily': '今日の残り {{remaining}}/{{limit}}回',
|
|
329
385
|
'license.usage_weekly': '今週の残り {{remaining}}/{{limit}}回',
|
|
330
386
|
'license.usage_monthly': '今月の残り {{remaining}}/{{limit}}回',
|
|
@@ -334,6 +390,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
334
390
|
'license.spots_remaining': '枠残り',
|
|
335
391
|
'license.deactivating': '無効化中...',
|
|
336
392
|
'license.deactivate': 'ライセンスを無効化',
|
|
393
|
+
'license.deactivate_hint': 'このデバイスからライセンスの接続を解除します。',
|
|
337
394
|
'license.designbase_account': 'Designbaseアカウント',
|
|
338
395
|
'license.designbase_account_hint': 'WordPressアカウントでサインインするか、メンバーシップを購入するとプラグインが自動的に有効化されます。',
|
|
339
396
|
'license.authenticating': '認証中...',
|
|
@@ -345,7 +402,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
345
402
|
'license.submit': '有効化',
|
|
346
403
|
'license.verifying': '確認中...',
|
|
347
404
|
'license.enter_from_email': 'メールで受け取ったライセンスキーを入力してください。',
|
|
348
|
-
'license.enter_from_youtube': '
|
|
405
|
+
'license.enter_from_youtube': 'メンバー限定投稿からコピーした今月のキーを入力してください。',
|
|
349
406
|
'license.help_link': 'ライセンス・支払いヘルプ',
|
|
350
407
|
'license.youtube_membership_howto': '利用方法',
|
|
351
408
|
'license.youtube_membership_step_1': 'Designbase YouTubeチャンネルのメンバーシップに参加します。',
|
|
@@ -982,7 +1039,7 @@ const fallbackText = (t, key, fallback) => {
|
|
|
982
1039
|
const translated = t?.(key);
|
|
983
1040
|
return translated && translated !== key ? translated : fallback;
|
|
984
1041
|
};
|
|
985
|
-
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, t, locale, className, }) => {
|
|
1042
|
+
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, licenseSource, accessScope, expiresAt, lastVerifiedAt, t, locale, className, }) => {
|
|
986
1043
|
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
987
1044
|
const [isOpen, setIsOpen] = useState(false);
|
|
988
1045
|
const rootRef = useRef(null);
|
|
@@ -1005,9 +1062,12 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1005
1062
|
: paymentStatus === 'TRIAL'
|
|
1006
1063
|
? fallbackText(translate, 'trialPlan', '체험판')
|
|
1007
1064
|
: fallbackText(translate, 'free', '무료');
|
|
1008
|
-
const
|
|
1065
|
+
const planSuffix = fallbackText(translate, 'planSuffix', '플랜');
|
|
1066
|
+
const normalizedPlanLabel = planLabel.toLocaleLowerCase();
|
|
1067
|
+
const normalizedPlanSuffix = planSuffix.toLocaleLowerCase();
|
|
1068
|
+
const planTitle = isBeta || normalizedPlanLabel.includes(normalizedPlanSuffix)
|
|
1009
1069
|
? planLabel
|
|
1010
|
-
: `${planLabel} ${
|
|
1070
|
+
: `${planLabel} ${planSuffix}`;
|
|
1011
1071
|
const triggerLabel = isPaid
|
|
1012
1072
|
? `${planLabel}, ${fallbackText(translate, 'unlimitedUsage', '무제한 사용 가능')}`
|
|
1013
1073
|
: isBeta
|
|
@@ -1018,6 +1078,41 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1018
1078
|
const upgradeLabel = isPaid
|
|
1019
1079
|
? fallbackText(translate, 'managePlan', '플랜 관리')
|
|
1020
1080
|
: fallbackText(translate, 'upgradePlan', '플랜 업그레이드');
|
|
1081
|
+
const resolvedLocale = locale || 'ko';
|
|
1082
|
+
const formatDate = (value) => {
|
|
1083
|
+
if (!value)
|
|
1084
|
+
return undefined;
|
|
1085
|
+
const date = new Date(value);
|
|
1086
|
+
if (Number.isNaN(date.getTime()))
|
|
1087
|
+
return value;
|
|
1088
|
+
return new Intl.DateTimeFormat(resolvedLocale, { dateStyle: 'medium' }).format(date);
|
|
1089
|
+
};
|
|
1090
|
+
const formattedSource = licenseSource === 'youtube_membership' || licenseSource === 'membership'
|
|
1091
|
+
? fallbackText(translate, 'license.source_youtube_membership', 'YouTube 멤버십')
|
|
1092
|
+
: licenseSource === 'lemonsqueezy'
|
|
1093
|
+
? fallbackText(translate, 'license.source_purchase', '구매 라이선스')
|
|
1094
|
+
: licenseSource;
|
|
1095
|
+
const formattedScope = accessScope === 'all-products' || accessScope === 'all_products'
|
|
1096
|
+
? fallbackText(translate, 'license.all_plugins', '모든 플러그인')
|
|
1097
|
+
: accessScope;
|
|
1098
|
+
const paidMetadata = [
|
|
1099
|
+
formattedSource && {
|
|
1100
|
+
label: fallbackText(translate, 'license.membership', '멤버십'),
|
|
1101
|
+
value: formattedSource,
|
|
1102
|
+
},
|
|
1103
|
+
expiresAt && {
|
|
1104
|
+
label: fallbackText(translate, 'license.expires', '만료일'),
|
|
1105
|
+
value: formatDate(expiresAt),
|
|
1106
|
+
},
|
|
1107
|
+
formattedScope && {
|
|
1108
|
+
label: fallbackText(translate, 'license.access', '접근 범위'),
|
|
1109
|
+
value: formattedScope,
|
|
1110
|
+
},
|
|
1111
|
+
lastVerifiedAt && {
|
|
1112
|
+
label: fallbackText(translate, 'license.last_checked', '최근 확인'),
|
|
1113
|
+
value: formatDate(lastVerifiedAt),
|
|
1114
|
+
},
|
|
1115
|
+
].filter(Boolean);
|
|
1021
1116
|
useEffect(() => {
|
|
1022
1117
|
if (!isOpen)
|
|
1023
1118
|
return undefined;
|
|
@@ -1052,7 +1147,10 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1052
1147
|
'designbase-figma-usage-status--loading': isLoading,
|
|
1053
1148
|
}, className) },
|
|
1054
1149
|
React.createElement("div", { className: "designbase-figma-usage-status__control" },
|
|
1055
|
-
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(
|
|
1150
|
+
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(React.Fragment, null,
|
|
1151
|
+
React.createElement("span", { className: "designbase-figma-usage-status__mini-progress", "aria-hidden": "true" },
|
|
1152
|
+
React.createElement("span", { style: { width: '100%' } })),
|
|
1153
|
+
React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E"))) : hasDailyLimit ? (React.createElement(React.Fragment, null,
|
|
1056
1154
|
React.createElement("span", { className: "designbase-figma-usage-status__mini-progress", "aria-hidden": "true" },
|
|
1057
1155
|
React.createElement("span", { style: { width: `${remainingPercent}%` } })),
|
|
1058
1156
|
React.createElement("span", { className: "designbase-figma-usage-status__usage-value" },
|
|
@@ -1063,11 +1161,19 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1063
1161
|
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))),
|
|
1064
1162
|
isOpen && (React.createElement("div", { id: popoverId, className: "designbase-figma-usage-status__popover", role: "dialog", "aria-label": fallbackText(translate, 'usageDetails', '사용량 상세') },
|
|
1065
1163
|
React.createElement("div", { className: "designbase-figma-usage-status__popover-header" },
|
|
1066
|
-
React.createElement("span", { className: "designbase-figma-usage-status__plan-
|
|
1164
|
+
React.createElement("span", { className: "designbase-figma-usage-status__plan-heading" },
|
|
1165
|
+
React.createElement("span", null, fallbackText(translate, 'license.current_plan', '현재 플랜')),
|
|
1166
|
+
React.createElement("strong", null, planTitle)),
|
|
1067
1167
|
!isBeta && (React.createElement(Button, { className: "designbase-figma-usage-status__upgrade", variant: isPaid ? 'secondary' : 'primary', size: "s", endIcon: "chevron-right", onPress: handleManageClick }, upgradeLabel))),
|
|
1068
|
-
isPaid ? (React.createElement(
|
|
1069
|
-
React.createElement("
|
|
1070
|
-
|
|
1168
|
+
isPaid ? (React.createElement(React.Fragment, null,
|
|
1169
|
+
React.createElement("div", { className: "designbase-figma-usage-status__unlimited-copy" },
|
|
1170
|
+
React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E"),
|
|
1171
|
+
React.createElement("span", null,
|
|
1172
|
+
React.createElement("strong", null, fallbackText(translate, 'unlimitedUsage', '무제한 사용')),
|
|
1173
|
+
React.createElement("small", null, fallbackText(translate, 'unlimitedUsageTooltip', '모든 기능을 제한 없이 사용할 수 있습니다')))),
|
|
1174
|
+
paidMetadata.length > 0 && (React.createElement("dl", { className: "designbase-figma-usage-status__license-meta" }, paidMetadata.map((item) => (React.createElement("div", { key: item.label },
|
|
1175
|
+
React.createElement("dt", null, item.label),
|
|
1176
|
+
React.createElement("dd", null, item.value)))))))) : isBeta ? (React.createElement("p", { className: "designbase-figma-usage-status__note" }, fallbackText(translate, 'betaUsageDescription', '베타 기간에는 사용량 제한이 적용되지 않습니다'))) : hasDailyLimit ? (React.createElement("div", { className: "designbase-figma-usage-status__usage-detail" },
|
|
1071
1177
|
React.createElement("div", { className: "designbase-figma-usage-status__usage-summary" },
|
|
1072
1178
|
React.createElement("strong", { className: "designbase-figma-usage-status__usage-count" },
|
|
1073
1179
|
remaining,
|
|
@@ -1169,7 +1275,7 @@ FigmaToastProvider.displayName = 'FigmaToastProvider';
|
|
|
1169
1275
|
FigmaToast.displayName = 'FigmaToast';
|
|
1170
1276
|
|
|
1171
1277
|
const DEFAULT_LOW_USAGE_WARNING = { key: 'lowUsageWarning' };
|
|
1172
|
-
const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount = 0, remainingUsage, listenForUsageMessages = true, isLoading = false, showPaymentStatus = true, showUsageInfo = true, maxDailyUsage = 20, showLowUsageWarning = true, lowUsageThresholdPercent = 10, lowUsageWarningText = DEFAULT_LOW_USAGE_WARNING, onLowUsageWarning, 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, }) => {
|
|
1278
|
+
const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount = 0, remainingUsage, listenForUsageMessages = true, isLoading = false, showPaymentStatus = true, showUsageInfo = true, maxDailyUsage = 20, licenseSource, accessScope, expiresAt, lastVerifiedAt, showLowUsageWarning = true, lowUsageThresholdPercent = 10, lowUsageWarningText = DEFAULT_LOW_USAGE_WARNING, onLowUsageWarning, 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, }) => {
|
|
1173
1279
|
const { t: translate } = useFigmaUiI18n(currentLanguage, t);
|
|
1174
1280
|
const { showToast, toastComponent } = useFigmaToast();
|
|
1175
1281
|
const [liveUsage, setLiveUsage] = useState({});
|
|
@@ -1179,12 +1285,17 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1179
1285
|
const effectiveUsageCount = liveUsage.usageCount ?? usageCount;
|
|
1180
1286
|
const effectiveRemainingUsage = liveUsage.remainingUsage ?? remainingUsage;
|
|
1181
1287
|
const effectiveMaxDailyUsage = liveUsage.maxDailyUsage ?? maxDailyUsage;
|
|
1288
|
+
const effectiveLicenseSource = liveUsage.licenseSource ?? licenseSource;
|
|
1289
|
+
const effectiveAccessScope = liveUsage.accessScope ?? accessScope;
|
|
1290
|
+
const effectiveExpiresAt = liveUsage.expiresAt ?? expiresAt;
|
|
1291
|
+
const effectiveLastVerifiedAt = liveUsage.lastVerifiedAt ?? lastVerifiedAt;
|
|
1182
1292
|
const limit = Math.max(1, Math.round(effectiveMaxDailyUsage));
|
|
1183
1293
|
const resolvedRemaining = typeof effectiveRemainingUsage === 'number' && Number.isFinite(effectiveRemainingUsage)
|
|
1184
1294
|
? Math.min(limit, Math.max(0, Math.round(effectiveRemainingUsage)))
|
|
1185
1295
|
: Math.max(0, limit - Math.min(limit, Math.max(0, Math.round(effectiveUsageCount))));
|
|
1186
1296
|
const remainingPercent = Math.round((resolvedRemaining / limit) * 100);
|
|
1187
|
-
const resolvedShowUsageInfo = showPaymentStatus
|
|
1297
|
+
const resolvedShowUsageInfo = showPaymentStatus
|
|
1298
|
+
&& (showUsageInfo || effectivePaymentStatus === 'FREE' || effectivePaymentStatus === 'PAID');
|
|
1188
1299
|
const resolvedShowPaymentBadge = showPaymentStatus && showPaymentBadge;
|
|
1189
1300
|
const resolvedLicensePageClick = effectivePaymentStatus === 'BETA' ? undefined : onLicensePageClick;
|
|
1190
1301
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -1210,10 +1321,31 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1210
1321
|
: message.paymentStatus === 'FREE' || message.paymentStatus === 'UNPAID'
|
|
1211
1322
|
? 'FREE'
|
|
1212
1323
|
: undefined;
|
|
1324
|
+
const nextLicenseSource = typeof message.licenseSource === 'string' ? message.licenseSource : undefined;
|
|
1325
|
+
const nextAccessScope = typeof message.accessScope === 'string' ? message.accessScope : undefined;
|
|
1326
|
+
const nextExpiresAt = typeof message.expiresAt === 'string' ? message.expiresAt : undefined;
|
|
1327
|
+
const rawLastVerifiedAt = message.lastVerifiedAt;
|
|
1328
|
+
const numericLastVerifiedAt = typeof rawLastVerifiedAt === 'number' && Number.isFinite(rawLastVerifiedAt)
|
|
1329
|
+
? rawLastVerifiedAt < 1000000000000
|
|
1330
|
+
? rawLastVerifiedAt * 1000
|
|
1331
|
+
: rawLastVerifiedAt
|
|
1332
|
+
: undefined;
|
|
1333
|
+
const parsedLastVerifiedAt = numericLastVerifiedAt === undefined
|
|
1334
|
+
? undefined
|
|
1335
|
+
: new Date(numericLastVerifiedAt);
|
|
1336
|
+
const nextLastVerifiedAt = typeof rawLastVerifiedAt === 'string'
|
|
1337
|
+
? rawLastVerifiedAt
|
|
1338
|
+
: parsedLastVerifiedAt && !Number.isNaN(parsedLastVerifiedAt.getTime())
|
|
1339
|
+
? parsedLastVerifiedAt.toISOString()
|
|
1340
|
+
: undefined;
|
|
1213
1341
|
if (nextPaymentStatus === undefined
|
|
1214
1342
|
&& nextLimit === undefined
|
|
1215
1343
|
&& nextUsed === undefined
|
|
1216
|
-
&& nextRemaining === undefined
|
|
1344
|
+
&& nextRemaining === undefined
|
|
1345
|
+
&& nextLicenseSource === undefined
|
|
1346
|
+
&& nextAccessScope === undefined
|
|
1347
|
+
&& nextExpiresAt === undefined
|
|
1348
|
+
&& nextLastVerifiedAt === undefined) {
|
|
1217
1349
|
return;
|
|
1218
1350
|
}
|
|
1219
1351
|
setLiveUsage((previous) => ({
|
|
@@ -1222,6 +1354,10 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1222
1354
|
...(typeof nextLimit === 'number' ? { maxDailyUsage: nextLimit } : {}),
|
|
1223
1355
|
...(typeof nextUsed === 'number' ? { usageCount: nextUsed } : {}),
|
|
1224
1356
|
...(typeof nextRemaining === 'number' ? { remainingUsage: nextRemaining } : {}),
|
|
1357
|
+
...(nextLicenseSource ? { licenseSource: nextLicenseSource } : {}),
|
|
1358
|
+
...(nextAccessScope ? { accessScope: nextAccessScope } : {}),
|
|
1359
|
+
...(nextExpiresAt ? { expiresAt: nextExpiresAt } : {}),
|
|
1360
|
+
...(nextLastVerifiedAt ? { lastVerifiedAt: nextLastVerifiedAt } : {}),
|
|
1225
1361
|
}));
|
|
1226
1362
|
};
|
|
1227
1363
|
window.addEventListener('message', handleUsageMessage);
|
|
@@ -1280,7 +1416,7 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1280
1416
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
1281
1417
|
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, languages: languages, currentLanguage: currentLanguage, showLanguageSelector: showLanguageSelector, onLanguageChange: onLanguageChange, t: translate })),
|
|
1282
1418
|
React.createElement("div", { className: "designbase-figma-footer__right" },
|
|
1283
|
-
(resolvedShowUsageInfo || resolvedShowPaymentBadge) && (React.createElement(UsageStatusPopover, { paymentStatus: effectivePaymentStatus, usageCount: effectiveUsageCount, remainingUsage: effectiveRemainingUsage, maxDailyUsage: effectiveMaxDailyUsage, showUsage: resolvedShowUsageInfo, showPlan: resolvedShowPaymentBadge, isLoading: isLoading, onLicensePageClick: resolvedLicensePageClick, t: translate })),
|
|
1419
|
+
(resolvedShowUsageInfo || resolvedShowPaymentBadge) && (React.createElement(UsageStatusPopover, { paymentStatus: effectivePaymentStatus, usageCount: effectiveUsageCount, remainingUsage: effectiveRemainingUsage, maxDailyUsage: effectiveMaxDailyUsage, showUsage: resolvedShowUsageInfo, showPlan: resolvedShowPaymentBadge, isLoading: isLoading, onLicensePageClick: resolvedLicensePageClick, licenseSource: effectiveLicenseSource, accessScope: effectiveAccessScope, expiresAt: effectiveExpiresAt, lastVerifiedAt: effectiveLastVerifiedAt, locale: currentLanguage, t: translate })),
|
|
1284
1420
|
showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t: translate })))),
|
|
1285
1421
|
children,
|
|
1286
1422
|
toastComponent));
|
|
@@ -1293,9 +1429,15 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
1293
1429
|
useEffect(() => {
|
|
1294
1430
|
setInputValue(value);
|
|
1295
1431
|
}, [value]);
|
|
1432
|
+
const submitLicense = async () => {
|
|
1433
|
+
const normalizedValue = inputValue.trim();
|
|
1434
|
+
if (!normalizedValue || disabled || isSubmitting)
|
|
1435
|
+
return;
|
|
1436
|
+
await onLicenseSubmit(normalizedValue);
|
|
1437
|
+
};
|
|
1296
1438
|
const handleSubmit = async (e) => {
|
|
1297
1439
|
e.preventDefault();
|
|
1298
|
-
await
|
|
1440
|
+
await submitLicense();
|
|
1299
1441
|
};
|
|
1300
1442
|
const handleChange = (value) => {
|
|
1301
1443
|
setInputValue(value);
|
|
@@ -1315,7 +1457,9 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
1315
1457
|
handleChange(value);
|
|
1316
1458
|
}
|
|
1317
1459
|
}, placeholder: displayPlaceholder, helperText: displayHelperText, disabled: disabled || isSubmitting, size: "m" })),
|
|
1318
|
-
React.createElement(Button, { type: "
|
|
1460
|
+
React.createElement(Button, { type: "button", variant: "primary", size: "m", loading: isSubmitting, disabled: !inputValue.trim() || isSubmitting || disabled, fullWidth: true, onPress: () => {
|
|
1461
|
+
void submitLicense();
|
|
1462
|
+
} }, isSubmitting ? displaySubmittingText : displaySubmitText)));
|
|
1319
1463
|
};
|
|
1320
1464
|
FormWithSubmit.displayName = 'FormWithSubmit';
|
|
1321
1465
|
|
|
@@ -1387,19 +1531,34 @@ const LicenseOffer = ({ joinUrl, guideUrl, membershipUrl, t, locale, className,
|
|
|
1387
1531
|
const titleId = `designbase-license-offer-title-${useId().replace(/:/g, '')}`;
|
|
1388
1532
|
const resolvedJoinUrl = joinUrl || membershipUrl;
|
|
1389
1533
|
const steps = [
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1534
|
+
{
|
|
1535
|
+
title: resolveText(translate, { key: 'license.get_key_step_1_title' }, '멤버십 가입'),
|
|
1536
|
+
description: resolveText(translate, { key: 'license.get_key_step_1_description' }, 'Designbase YouTube 채널에서 멤버십에 가입합니다.'),
|
|
1537
|
+
},
|
|
1538
|
+
{
|
|
1539
|
+
title: resolveText(translate, { key: 'license.get_key_step_2_title' }, '이번 달 키 복사'),
|
|
1540
|
+
description: resolveText(translate, { key: 'license.get_key_step_2_description' }, '멤버 전용 커뮤니티 게시글에서 키를 확인합니다.'),
|
|
1541
|
+
},
|
|
1542
|
+
{
|
|
1543
|
+
title: resolveText(translate, { key: 'license.get_key_step_3_title' }, '키 등록'),
|
|
1544
|
+
description: resolveText(translate, { key: 'license.get_key_step_3_description' }, '아래 입력창에 붙여 넣으면 프로 기능이 열립니다.'),
|
|
1545
|
+
},
|
|
1393
1546
|
];
|
|
1394
1547
|
return (React.createElement("section", { className: `designbase-figma-license-offer ${className || ''}`, "aria-labelledby": titleId },
|
|
1395
|
-
React.createElement("
|
|
1548
|
+
React.createElement("header", { className: "designbase-figma-license-offer__header" },
|
|
1549
|
+
React.createElement("span", { className: "designbase-figma-license-offer__section-index", "aria-hidden": "true" }, "1"),
|
|
1550
|
+
React.createElement("div", null,
|
|
1551
|
+
React.createElement("h3", { id: titleId, className: "designbase-figma-license-offer__title" }, resolveText(translate, { key: 'license.get_key_title' }, '라이선스 키 받기')),
|
|
1552
|
+
React.createElement("p", { className: "designbase-figma-license-offer__description" }, resolveText(translate, { key: 'license.get_key_description' }, '멤버십 회원에게 매월 새 라이선스 키가 제공됩니다.')))),
|
|
1396
1553
|
React.createElement("ol", { className: "designbase-figma-license-offer__steps" }, steps.map((step, index) => (React.createElement("li", { key: index },
|
|
1397
|
-
React.createElement("span", { className: "designbase-figma-license-offer__step-index", "aria-hidden": "true" },
|
|
1398
|
-
|
|
1399
|
-
".
|
|
1400
|
-
|
|
1554
|
+
React.createElement("span", { className: "designbase-figma-license-offer__step-index", "aria-hidden": "true" }, index + 1),
|
|
1555
|
+
React.createElement("span", { className: "designbase-figma-license-offer__step-copy" },
|
|
1556
|
+
React.createElement("strong", null, step.title),
|
|
1557
|
+
React.createElement("span", null, step.description)))))),
|
|
1401
1558
|
(resolvedJoinUrl || guideUrl) && (React.createElement("div", { className: "designbase-figma-license-offer__actions" },
|
|
1402
|
-
resolvedJoinUrl && (React.createElement(Button, { onPress: () => openExternalUrl(resolvedJoinUrl), variant: "primary", size: "m", fullWidth: true },
|
|
1559
|
+
resolvedJoinUrl && (React.createElement(Button, { onPress: () => openExternalUrl(resolvedJoinUrl), variant: "primary", size: "m", fullWidth: true },
|
|
1560
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.get_key_cta' }, '멤버십 가입하고 키 받기')),
|
|
1561
|
+
React.createElement(ExternalLinkIcon, { size: 16, "aria-hidden": "true" }))),
|
|
1403
1562
|
guideUrl && (React.createElement(Button, { onPress: () => openExternalUrl(guideUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
1404
1563
|
React.createElement("span", null, resolveText(translate, { key: 'license.youtube_membership_guide' }, '안내보기')),
|
|
1405
1564
|
React.createElement(ExternalLinkIcon, { size: 16, "aria-hidden": "true" })))))));
|
|
@@ -1438,7 +1597,7 @@ function formatSource(value, t) {
|
|
|
1438
1597
|
}
|
|
1439
1598
|
return value;
|
|
1440
1599
|
}
|
|
1441
|
-
const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSource, accessScope, expiresAt, lastVerifiedAt, validationMessage, allowRevealKey = false, t, locale, className, }) => {
|
|
1600
|
+
const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSource, accessScope, expiresAt, lastVerifiedAt, validationMessage, showHeader = true, allowRevealKey = false, t, locale, className, }) => {
|
|
1442
1601
|
const { locale: resolvedLocale, t: translate } = useFigmaUiI18n(locale, t);
|
|
1443
1602
|
const [isKeyRevealed, setIsKeyRevealed] = useState(false);
|
|
1444
1603
|
const normalizedLicenseStatus = licenseStatus?.toLowerCase();
|
|
@@ -1449,13 +1608,15 @@ const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSour
|
|
|
1449
1608
|
: resolveText(translate, { key: 'license.status_inactive' }, 'License check failed');
|
|
1450
1609
|
const statusClass = isActive ? 'active' : 'inactive';
|
|
1451
1610
|
return (React.createElement("section", { className: `designbase-figma-license-status-card designbase-figma-license-status-card--${statusClass} ${className || ''}`, "aria-label": statusText },
|
|
1452
|
-
React.createElement("div", { className: "designbase-figma-license-status-card__header" },
|
|
1611
|
+
showHeader && (React.createElement("div", { className: "designbase-figma-license-status-card__header" },
|
|
1453
1612
|
React.createElement("div", null,
|
|
1454
1613
|
React.createElement("div", { className: "designbase-figma-license-status-card__eyebrow" }, isActive
|
|
1455
1614
|
? resolveText(translate, { key: 'license.activated' }, '라이선스 활성화됨')
|
|
1456
1615
|
: resolveText(translate, { key: 'license.status_label' }, '라이선스 상태')),
|
|
1457
1616
|
React.createElement("h3", null, statusText)),
|
|
1458
|
-
React.createElement("span", { className: "designbase-figma-license-status-card__badge" },
|
|
1617
|
+
React.createElement("span", { className: "designbase-figma-license-status-card__badge" }, isActive
|
|
1618
|
+
? resolveText(translate, { key: 'license.status_active' }, '활성')
|
|
1619
|
+
: resolveText(translate, { key: 'license.status_inactive' }, '비활성')))),
|
|
1459
1620
|
validationMessage && !isActive && (React.createElement("p", { className: "designbase-figma-license-status-card__message" }, validationMessage)),
|
|
1460
1621
|
licenseKey && (React.createElement("div", { className: "designbase-figma-license-status-card__key-row" },
|
|
1461
1622
|
React.createElement("span", null, resolveText(translate, { key: 'license.key_label' }, '라이선스 키')),
|
|
@@ -1829,7 +1990,7 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1829
1990
|
function formatUsageLabel(state, t) {
|
|
1830
1991
|
const { remainingUsage, usageUsed, usageLimit, usageReset } = state;
|
|
1831
1992
|
if (usageLimit === 'unlimited') {
|
|
1832
|
-
return resolveText(t, { key: 'license.usage_unlimited' }, '사용 횟수 제한 없음') ?? '사용 횟수 제한 없음';
|
|
1993
|
+
return (resolveText(t, { key: 'license.usage_unlimited' }, '사용 횟수 제한 없음') ?? '사용 횟수 제한 없음');
|
|
1833
1994
|
}
|
|
1834
1995
|
const limit = typeof usageLimit === 'number' ? usageLimit : remainingUsage + usageUsed;
|
|
1835
1996
|
const remaining = remainingUsage ?? Math.max(0, limit - usageUsed);
|
|
@@ -1848,9 +2009,9 @@ function formatUsageLabel(state, t) {
|
|
|
1848
2009
|
const translated = resolveText(t, { key: 'license.usage_weekly', values: { remaining, limit } }, fallback) ?? fallback;
|
|
1849
2010
|
return translated.includes(String(remaining)) ? translated : fallback;
|
|
1850
2011
|
}
|
|
1851
|
-
return resolveText(t, { key: 'license.usage_generic', values: { remaining, limit } }, `남은 횟수 ${remaining}/${limit}`) ?? `남은 횟수 ${remaining}/${limit}
|
|
2012
|
+
return (resolveText(t, { key: 'license.usage_generic', values: { remaining, limit } }, `남은 횟수 ${remaining}/${limit}`) ?? `남은 횟수 ${remaining}/${limit}`);
|
|
1852
2013
|
}
|
|
1853
|
-
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, }) => {
|
|
2014
|
+
const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicenseKey = '', licenseStatus: initialLicenseStatus, licenseSource: initialLicenseSource, accessScope: initialAccessScope, expiresAt: initialExpiresAt, lastVerifiedAt: initialLastVerifiedAt, wordpressLinks, paymentPageUrl, mode = 'pricing', membershipUrl, enableAccountAuth = true, showLicenseKeyInput = true, pricingFeatures, pricing, paymentType = 'subscription', messageTypes, onStateChange, setPaymentStatus, setUsageCount, onLicenseSubmit, usageCount: initialUsageCount = 0, t, locale, className, }) => {
|
|
1854
2015
|
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1855
2016
|
const links = useMemo(() => ({
|
|
1856
2017
|
purchaseUrl: wordpressLinks?.purchaseUrl ?? paymentPageUrl,
|
|
@@ -1863,13 +2024,21 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1863
2024
|
initialState: {
|
|
1864
2025
|
paymentStatus: initialStatus,
|
|
1865
2026
|
licenseKey: initialLicenseKey,
|
|
2027
|
+
hasLicenseKey: Boolean(initialLicenseKey),
|
|
2028
|
+
isLicenseRegistered: initialStatus === 'PAID',
|
|
2029
|
+
planTier: initialStatus === 'PAID' ? 'PRO' : 'FREE',
|
|
2030
|
+
usageLimit: initialStatus === 'PAID' ? 'unlimited' : 0,
|
|
2031
|
+
licenseStatus: initialLicenseStatus,
|
|
2032
|
+
licenseSource: initialLicenseSource,
|
|
2033
|
+
accessScope: initialAccessScope,
|
|
2034
|
+
expiresAt: initialExpiresAt,
|
|
2035
|
+
lastVerifiedAt: initialLastVerifiedAt,
|
|
1866
2036
|
usageCount: initialUsageCount,
|
|
1867
2037
|
},
|
|
1868
2038
|
onStateChange,
|
|
1869
2039
|
onPaymentStatusChange: setPaymentStatus,
|
|
1870
2040
|
onUsageCountChange: setUsageCount,
|
|
1871
2041
|
});
|
|
1872
|
-
const [showDetails, setShowDetails] = useState(false);
|
|
1873
2042
|
const [licenseKeyDraft, setLicenseKeyDraft] = useState(initialLicenseKey);
|
|
1874
2043
|
const isPaid = state.isLicenseRegistered && state.paymentStatus === 'PAID';
|
|
1875
2044
|
const isMembershipMode = mode === 'youtube-membership';
|
|
@@ -1889,29 +2058,31 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1889
2058
|
React.createElement("div", { className: "designbase-figma-page-license__content" },
|
|
1890
2059
|
React.createElement("div", { className: "designbase-figma-page-license__header" },
|
|
1891
2060
|
React.createElement("div", { className: "designbase-figma-page-license__title" },
|
|
1892
|
-
React.createElement("h2", null,
|
|
1893
|
-
? resolveText(translate, { key: 'license.
|
|
1894
|
-
:
|
|
1895
|
-
? resolveText(translate, { key: 'license.
|
|
2061
|
+
React.createElement("h2", null, isPaid
|
|
2062
|
+
? resolveText(translate, { key: 'license.pro_account' }, '프로 계정')
|
|
2063
|
+
: isMembershipMode
|
|
2064
|
+
? resolveText(translate, { key: 'license.unlock_unlimited' }, '무제한 사용 활성화')
|
|
1896
2065
|
: resolveText(translate, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
|
|
1897
|
-
|
|
2066
|
+
isPaid && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, resolveText(translate, { key: 'license.pro_plan' }, '프로 플랜')))),
|
|
1898
2067
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
1899
2068
|
? resolveText(translate, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
1900
2069
|
: isMembershipMode
|
|
1901
|
-
? resolveText(translate, { key: 'license.
|
|
2070
|
+
? resolveText(translate, { key: 'license.unlock_unlimited_description' }, '라이선스 키를 등록하면 모든 Designbase 플러그인의 프로 기능과 무제한 사용을 이용할 수 있습니다.')
|
|
1902
2071
|
: resolveText(translate, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
|
|
1903
2072
|
!isPaid && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
1904
2073
|
!isMembershipMode && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: translate })),
|
|
1905
|
-
state.lastMessage &&
|
|
1906
|
-
|
|
1907
|
-
React.createElement("
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2074
|
+
state.lastMessage &&
|
|
2075
|
+
state.lastErrorCode &&
|
|
2076
|
+
!state.deactivateMessage && (React.createElement("p", { className: `designbase-figma-page-license__feedback ${state.lastErrorCode ? 'designbase-figma-page-license__feedback--error' : ''}`, "aria-live": "polite" }, state.lastMessage)),
|
|
2077
|
+
isPaid && (React.createElement("div", { className: "designbase-figma-page-license__paid-summary" },
|
|
2078
|
+
React.createElement("div", { className: "designbase-figma-page-license__paid-hero" },
|
|
2079
|
+
React.createElement("span", { "aria-hidden": "true" }, "\u221E"),
|
|
2080
|
+
React.createElement("div", null,
|
|
2081
|
+
React.createElement("strong", null, resolveText(translate, { key: 'license.usage_unlimited' }, '무제한 사용')),
|
|
2082
|
+
React.createElement("p", null, resolveText(translate, { key: 'license.active_until_expiry' }, '만료일까지 모든 기능을 제한 없이 사용할 수 있습니다.')))),
|
|
2083
|
+
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, showHeader: false, t: translate }),
|
|
2084
|
+
React.createElement("div", { className: "designbase-figma-page-license__paid-actions" },
|
|
2085
|
+
state.activationLimit > 0 && (React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
1915
2086
|
React.createElement("div", { className: "designbase-figma-page-license__remaining" },
|
|
1916
2087
|
Math.max(0, state.activationLimit - state.activationUsage),
|
|
1917
2088
|
' ',
|
|
@@ -1921,15 +2092,16 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1921
2092
|
React.createElement("div", { className: "designbase-figma-page-license__usage-count" },
|
|
1922
2093
|
state.activationUsage,
|
|
1923
2094
|
"/",
|
|
1924
|
-
state.activationLimit)),
|
|
1925
|
-
React.createElement(
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
2095
|
+
state.activationLimit))),
|
|
2096
|
+
React.createElement(Button, { onPress: deactivateLicense, variant: "secondary", size: "m", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
2097
|
+
? resolveText(translate, { key: 'license.deactivating' }, '비활성화 중...')
|
|
2098
|
+
: resolveText(translate, { key: 'license.deactivate' }, '라이선스 비활성화')),
|
|
2099
|
+
state.deactivateMessage && state.deactivateErrorCode && (React.createElement("p", { className: `designbase-figma-page-license__action-feedback designbase-figma-page-license__action-feedback--${resolvePaymentFeedbackVariant(state.deactivateErrorCode)}`, role: "alert", "aria-live": "polite" }, state.deactivateMessage)),
|
|
2100
|
+
React.createElement("p", { className: "designbase-figma-page-license__deactivate-hint" }, resolveText(translate, { key: 'license.deactivate_hint' }, '이 기기에서 라이선스 연결을 해제합니다.'))))),
|
|
1930
2101
|
!isPaid && (React.createElement(React.Fragment, null,
|
|
1931
2102
|
isMembershipMode && (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t: translate })),
|
|
1932
|
-
!isMembershipMode &&
|
|
2103
|
+
!isMembershipMode &&
|
|
2104
|
+
(enableAccountAuth || links.purchaseUrl || links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1933
2105
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1934
2106
|
React.createElement("h3", null, resolveText(translate, { key: 'license.designbase_account' }, '디자인베이스 계정'))),
|
|
1935
2107
|
React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(translate, { key: 'license.designbase_account_hint' }, 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.')),
|
|
@@ -1947,8 +2119,20 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1947
2119
|
? 'designbase-figma-page-license__key-form'
|
|
1948
2120
|
: 'designbase-figma-page-license__section' },
|
|
1949
2121
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1950
|
-
React.createElement("
|
|
1951
|
-
|
|
2122
|
+
isMembershipMode && (React.createElement("span", { className: "designbase-figma-page-license__section-index", "aria-hidden": "true" }, "2")),
|
|
2123
|
+
React.createElement("h3", null, isMembershipMode
|
|
2124
|
+
? resolveText(translate, { key: 'license.activate_key_title' }, '라이선스 키 등록')
|
|
2125
|
+
: resolveText(translate, { key: 'license.enter_key' }, '라이선스 키 입력'))),
|
|
2126
|
+
isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(translate, { key: 'license.activate_key_description' }, '이미 키가 있다면 아래에 붙여 넣어 프로 기능을 활성화하세요.'))),
|
|
2127
|
+
React.createElement(FormWithSubmit, { onLicenseSubmit: handleLicenseSubmit, disabled: false, isSubmitting: isVerifying, value: licenseKeyDraft, onValueChange: handleLicenseKeyChange, label: { key: 'license.key' }, submitText: {
|
|
2128
|
+
key: isMembershipMode
|
|
2129
|
+
? 'license.unlock_pro_features'
|
|
2130
|
+
: 'license.submit',
|
|
2131
|
+
}, submittingText: { key: 'license.verifying' }, helperText: {
|
|
2132
|
+
key: isMembershipMode
|
|
2133
|
+
? 'license.enter_from_youtube'
|
|
2134
|
+
: 'license.enter_from_email',
|
|
2135
|
+
}, t: translate }))))),
|
|
1952
2136
|
links.helpUrl && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
1953
2137
|
React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(translate, { key: 'license.help_link' }, '라이선스·결제 도움말'))))),
|
|
1954
2138
|
React.createElement(Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", iconOnly: true, "aria-label": translate('close') },
|