@designbasekorea/figma-ui 0.7.0 → 0.7.1
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 +149 -37
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +148 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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,16 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
53
53
|
'form.submit': '제출',
|
|
54
54
|
'form.verifying': '확인 중...',
|
|
55
55
|
'license.youtube_membership': 'YouTube 멤버십',
|
|
56
|
+
'license.current_plan': '현재 플랜',
|
|
57
|
+
'license.pro_plan': '프로 플랜',
|
|
58
|
+
'license.membership': '멤버십',
|
|
56
59
|
'license.pro_account': '프로 계정',
|
|
57
60
|
'license.upgrade_to_pro': '프로로 업그레이드',
|
|
58
61
|
'license.all_features_available': '모든 기능을 사용할 수 있습니다.',
|
|
59
62
|
'license.youtube_membership_description': 'YouTube 멤버십에 가입하면 Designbase 플러그인을 무제한으로 사용할 수 있습니다.',
|
|
60
63
|
'license.purchase_for_unlimited': '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.',
|
|
61
64
|
'license.usage_unlimited': '사용 횟수 제한 없음',
|
|
65
|
+
'license.active_until_expiry': '만료일까지 모든 기능을 제한 없이 사용할 수 있습니다.',
|
|
62
66
|
'license.usage_daily': '오늘 남은 횟수 {{remaining}}/{{limit}}',
|
|
63
67
|
'license.usage_weekly': '이번 주 남은 횟수 {{remaining}}/{{limit}}',
|
|
64
68
|
'license.usage_monthly': '이번 달 남은 횟수 {{remaining}}/{{limit}}',
|
|
@@ -68,6 +72,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
68
72
|
'license.spots_remaining': '자리 남음',
|
|
69
73
|
'license.deactivating': '비활성화 중...',
|
|
70
74
|
'license.deactivate': '라이선스 비활성화',
|
|
75
|
+
'license.deactivate_hint': '이 기기에서 라이선스 연결을 해제합니다.',
|
|
71
76
|
'license.designbase_account': '디자인베이스 계정',
|
|
72
77
|
'license.designbase_account_hint': 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.',
|
|
73
78
|
'license.authenticating': '인증 중...',
|
|
@@ -186,12 +191,16 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
186
191
|
'form.submit': 'Activate',
|
|
187
192
|
'form.verifying': 'Verifying...',
|
|
188
193
|
'license.youtube_membership': 'YouTube Membership',
|
|
194
|
+
'license.current_plan': 'Current plan',
|
|
195
|
+
'license.pro_plan': 'Pro plan',
|
|
196
|
+
'license.membership': 'Membership',
|
|
189
197
|
'license.pro_account': 'Pro account',
|
|
190
198
|
'license.upgrade_to_pro': 'Upgrade to Pro',
|
|
191
199
|
'license.all_features_available': 'All features are available.',
|
|
192
200
|
'license.youtube_membership_description': 'Join YouTube Membership to use Designbase plugins without limits.',
|
|
193
201
|
'license.purchase_for_unlimited': 'Get unlimited access with a Designbase membership or license.',
|
|
194
202
|
'license.usage_unlimited': 'Unlimited usage',
|
|
203
|
+
'license.active_until_expiry': 'All features remain available without limits until expiration.',
|
|
195
204
|
'license.usage_daily': '{{remaining}}/{{limit}} remaining today',
|
|
196
205
|
'license.usage_weekly': '{{remaining}}/{{limit}} remaining this week',
|
|
197
206
|
'license.usage_monthly': '{{remaining}}/{{limit}} remaining this month',
|
|
@@ -201,6 +210,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
201
210
|
'license.spots_remaining': 'spots remaining',
|
|
202
211
|
'license.deactivating': 'Deactivating...',
|
|
203
212
|
'license.deactivate': 'Deactivate license',
|
|
213
|
+
'license.deactivate_hint': 'Disconnects this license from the current device.',
|
|
204
214
|
'license.designbase_account': 'Designbase account',
|
|
205
215
|
'license.designbase_account_hint': 'Sign in with your WordPress account or purchase a membership to activate the plugin automatically.',
|
|
206
216
|
'license.authenticating': 'Authenticating...',
|
|
@@ -319,12 +329,16 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
319
329
|
'form.submit': '有効化',
|
|
320
330
|
'form.verifying': '確認中...',
|
|
321
331
|
'license.youtube_membership': 'YouTubeメンバーシップ',
|
|
332
|
+
'license.current_plan': '現在のプラン',
|
|
333
|
+
'license.pro_plan': 'Proプラン',
|
|
334
|
+
'license.membership': 'メンバーシップ',
|
|
322
335
|
'license.pro_account': 'Proアカウント',
|
|
323
336
|
'license.upgrade_to_pro': 'Proにアップグレード',
|
|
324
337
|
'license.all_features_available': 'すべての機能を使用できます。',
|
|
325
338
|
'license.youtube_membership_description': 'YouTubeメンバーシップに参加すると、Designbaseプラグインを無制限で使用できます。',
|
|
326
339
|
'license.purchase_for_unlimited': 'Designbaseのメンバーシップまたはライセンスで無制限に利用できます。',
|
|
327
340
|
'license.usage_unlimited': '使用回数の制限なし',
|
|
341
|
+
'license.active_until_expiry': '有効期限まで、すべての機能を制限なく使用できます。',
|
|
328
342
|
'license.usage_daily': '今日の残り {{remaining}}/{{limit}}回',
|
|
329
343
|
'license.usage_weekly': '今週の残り {{remaining}}/{{limit}}回',
|
|
330
344
|
'license.usage_monthly': '今月の残り {{remaining}}/{{limit}}回',
|
|
@@ -334,6 +348,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
334
348
|
'license.spots_remaining': '枠残り',
|
|
335
349
|
'license.deactivating': '無効化中...',
|
|
336
350
|
'license.deactivate': 'ライセンスを無効化',
|
|
351
|
+
'license.deactivate_hint': 'このデバイスからライセンスの接続を解除します。',
|
|
337
352
|
'license.designbase_account': 'Designbaseアカウント',
|
|
338
353
|
'license.designbase_account_hint': 'WordPressアカウントでサインインするか、メンバーシップを購入するとプラグインが自動的に有効化されます。',
|
|
339
354
|
'license.authenticating': '認証中...',
|
|
@@ -982,7 +997,7 @@ const fallbackText = (t, key, fallback) => {
|
|
|
982
997
|
const translated = t?.(key);
|
|
983
998
|
return translated && translated !== key ? translated : fallback;
|
|
984
999
|
};
|
|
985
|
-
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, t, locale, className, }) => {
|
|
1000
|
+
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, licenseSource, accessScope, expiresAt, lastVerifiedAt, t, locale, className, }) => {
|
|
986
1001
|
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
987
1002
|
const [isOpen, setIsOpen] = useState(false);
|
|
988
1003
|
const rootRef = useRef(null);
|
|
@@ -1005,9 +1020,12 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1005
1020
|
: paymentStatus === 'TRIAL'
|
|
1006
1021
|
? fallbackText(translate, 'trialPlan', '체험판')
|
|
1007
1022
|
: fallbackText(translate, 'free', '무료');
|
|
1008
|
-
const
|
|
1023
|
+
const planSuffix = fallbackText(translate, 'planSuffix', '플랜');
|
|
1024
|
+
const normalizedPlanLabel = planLabel.toLocaleLowerCase();
|
|
1025
|
+
const normalizedPlanSuffix = planSuffix.toLocaleLowerCase();
|
|
1026
|
+
const planTitle = isBeta || normalizedPlanLabel.includes(normalizedPlanSuffix)
|
|
1009
1027
|
? planLabel
|
|
1010
|
-
: `${planLabel} ${
|
|
1028
|
+
: `${planLabel} ${planSuffix}`;
|
|
1011
1029
|
const triggerLabel = isPaid
|
|
1012
1030
|
? `${planLabel}, ${fallbackText(translate, 'unlimitedUsage', '무제한 사용 가능')}`
|
|
1013
1031
|
: isBeta
|
|
@@ -1018,6 +1036,41 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1018
1036
|
const upgradeLabel = isPaid
|
|
1019
1037
|
? fallbackText(translate, 'managePlan', '플랜 관리')
|
|
1020
1038
|
: fallbackText(translate, 'upgradePlan', '플랜 업그레이드');
|
|
1039
|
+
const resolvedLocale = locale || 'ko';
|
|
1040
|
+
const formatDate = (value) => {
|
|
1041
|
+
if (!value)
|
|
1042
|
+
return undefined;
|
|
1043
|
+
const date = new Date(value);
|
|
1044
|
+
if (Number.isNaN(date.getTime()))
|
|
1045
|
+
return value;
|
|
1046
|
+
return new Intl.DateTimeFormat(resolvedLocale, { dateStyle: 'medium' }).format(date);
|
|
1047
|
+
};
|
|
1048
|
+
const formattedSource = licenseSource === 'youtube_membership' || licenseSource === 'membership'
|
|
1049
|
+
? fallbackText(translate, 'license.source_youtube_membership', 'YouTube 멤버십')
|
|
1050
|
+
: licenseSource === 'lemonsqueezy'
|
|
1051
|
+
? fallbackText(translate, 'license.source_purchase', '구매 라이선스')
|
|
1052
|
+
: licenseSource;
|
|
1053
|
+
const formattedScope = accessScope === 'all-products' || accessScope === 'all_products'
|
|
1054
|
+
? fallbackText(translate, 'license.all_plugins', '모든 플러그인')
|
|
1055
|
+
: accessScope;
|
|
1056
|
+
const paidMetadata = [
|
|
1057
|
+
formattedSource && {
|
|
1058
|
+
label: fallbackText(translate, 'license.membership', '멤버십'),
|
|
1059
|
+
value: formattedSource,
|
|
1060
|
+
},
|
|
1061
|
+
expiresAt && {
|
|
1062
|
+
label: fallbackText(translate, 'license.expires', '만료일'),
|
|
1063
|
+
value: formatDate(expiresAt),
|
|
1064
|
+
},
|
|
1065
|
+
formattedScope && {
|
|
1066
|
+
label: fallbackText(translate, 'license.access', '접근 범위'),
|
|
1067
|
+
value: formattedScope,
|
|
1068
|
+
},
|
|
1069
|
+
lastVerifiedAt && {
|
|
1070
|
+
label: fallbackText(translate, 'license.last_checked', '최근 확인'),
|
|
1071
|
+
value: formatDate(lastVerifiedAt),
|
|
1072
|
+
},
|
|
1073
|
+
].filter(Boolean);
|
|
1021
1074
|
useEffect(() => {
|
|
1022
1075
|
if (!isOpen)
|
|
1023
1076
|
return undefined;
|
|
@@ -1052,7 +1105,10 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1052
1105
|
'designbase-figma-usage-status--loading': isLoading,
|
|
1053
1106
|
}, className) },
|
|
1054
1107
|
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(
|
|
1108
|
+
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,
|
|
1109
|
+
React.createElement("span", { className: "designbase-figma-usage-status__mini-progress", "aria-hidden": "true" },
|
|
1110
|
+
React.createElement("span", { style: { width: '100%' } })),
|
|
1111
|
+
React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E"))) : hasDailyLimit ? (React.createElement(React.Fragment, null,
|
|
1056
1112
|
React.createElement("span", { className: "designbase-figma-usage-status__mini-progress", "aria-hidden": "true" },
|
|
1057
1113
|
React.createElement("span", { style: { width: `${remainingPercent}%` } })),
|
|
1058
1114
|
React.createElement("span", { className: "designbase-figma-usage-status__usage-value" },
|
|
@@ -1063,11 +1119,19 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1063
1119
|
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
1120
|
isOpen && (React.createElement("div", { id: popoverId, className: "designbase-figma-usage-status__popover", role: "dialog", "aria-label": fallbackText(translate, 'usageDetails', '사용량 상세') },
|
|
1065
1121
|
React.createElement("div", { className: "designbase-figma-usage-status__popover-header" },
|
|
1066
|
-
React.createElement("span", { className: "designbase-figma-usage-status__plan-
|
|
1122
|
+
React.createElement("span", { className: "designbase-figma-usage-status__plan-heading" },
|
|
1123
|
+
React.createElement("span", null, fallbackText(translate, 'license.current_plan', '현재 플랜')),
|
|
1124
|
+
React.createElement("strong", null, planTitle)),
|
|
1067
1125
|
!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
|
-
|
|
1126
|
+
isPaid ? (React.createElement(React.Fragment, null,
|
|
1127
|
+
React.createElement("div", { className: "designbase-figma-usage-status__unlimited-copy" },
|
|
1128
|
+
React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E"),
|
|
1129
|
+
React.createElement("span", null,
|
|
1130
|
+
React.createElement("strong", null, fallbackText(translate, 'unlimitedUsage', '무제한 사용')),
|
|
1131
|
+
React.createElement("small", null, fallbackText(translate, 'unlimitedUsageTooltip', '모든 기능을 제한 없이 사용할 수 있습니다')))),
|
|
1132
|
+
paidMetadata.length > 0 && (React.createElement("dl", { className: "designbase-figma-usage-status__license-meta" }, paidMetadata.map((item) => (React.createElement("div", { key: item.label },
|
|
1133
|
+
React.createElement("dt", null, item.label),
|
|
1134
|
+
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
1135
|
React.createElement("div", { className: "designbase-figma-usage-status__usage-summary" },
|
|
1072
1136
|
React.createElement("strong", { className: "designbase-figma-usage-status__usage-count" },
|
|
1073
1137
|
remaining,
|
|
@@ -1169,7 +1233,7 @@ FigmaToastProvider.displayName = 'FigmaToastProvider';
|
|
|
1169
1233
|
FigmaToast.displayName = 'FigmaToast';
|
|
1170
1234
|
|
|
1171
1235
|
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, }) => {
|
|
1236
|
+
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
1237
|
const { t: translate } = useFigmaUiI18n(currentLanguage, t);
|
|
1174
1238
|
const { showToast, toastComponent } = useFigmaToast();
|
|
1175
1239
|
const [liveUsage, setLiveUsage] = useState({});
|
|
@@ -1179,12 +1243,17 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1179
1243
|
const effectiveUsageCount = liveUsage.usageCount ?? usageCount;
|
|
1180
1244
|
const effectiveRemainingUsage = liveUsage.remainingUsage ?? remainingUsage;
|
|
1181
1245
|
const effectiveMaxDailyUsage = liveUsage.maxDailyUsage ?? maxDailyUsage;
|
|
1246
|
+
const effectiveLicenseSource = liveUsage.licenseSource ?? licenseSource;
|
|
1247
|
+
const effectiveAccessScope = liveUsage.accessScope ?? accessScope;
|
|
1248
|
+
const effectiveExpiresAt = liveUsage.expiresAt ?? expiresAt;
|
|
1249
|
+
const effectiveLastVerifiedAt = liveUsage.lastVerifiedAt ?? lastVerifiedAt;
|
|
1182
1250
|
const limit = Math.max(1, Math.round(effectiveMaxDailyUsage));
|
|
1183
1251
|
const resolvedRemaining = typeof effectiveRemainingUsage === 'number' && Number.isFinite(effectiveRemainingUsage)
|
|
1184
1252
|
? Math.min(limit, Math.max(0, Math.round(effectiveRemainingUsage)))
|
|
1185
1253
|
: Math.max(0, limit - Math.min(limit, Math.max(0, Math.round(effectiveUsageCount))));
|
|
1186
1254
|
const remainingPercent = Math.round((resolvedRemaining / limit) * 100);
|
|
1187
|
-
const resolvedShowUsageInfo = showPaymentStatus
|
|
1255
|
+
const resolvedShowUsageInfo = showPaymentStatus
|
|
1256
|
+
&& (showUsageInfo || effectivePaymentStatus === 'FREE' || effectivePaymentStatus === 'PAID');
|
|
1188
1257
|
const resolvedShowPaymentBadge = showPaymentStatus && showPaymentBadge;
|
|
1189
1258
|
const resolvedLicensePageClick = effectivePaymentStatus === 'BETA' ? undefined : onLicensePageClick;
|
|
1190
1259
|
const hasChildren = React.Children.count(children) > 0;
|
|
@@ -1210,10 +1279,31 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1210
1279
|
: message.paymentStatus === 'FREE' || message.paymentStatus === 'UNPAID'
|
|
1211
1280
|
? 'FREE'
|
|
1212
1281
|
: undefined;
|
|
1282
|
+
const nextLicenseSource = typeof message.licenseSource === 'string' ? message.licenseSource : undefined;
|
|
1283
|
+
const nextAccessScope = typeof message.accessScope === 'string' ? message.accessScope : undefined;
|
|
1284
|
+
const nextExpiresAt = typeof message.expiresAt === 'string' ? message.expiresAt : undefined;
|
|
1285
|
+
const rawLastVerifiedAt = message.lastVerifiedAt;
|
|
1286
|
+
const numericLastVerifiedAt = typeof rawLastVerifiedAt === 'number' && Number.isFinite(rawLastVerifiedAt)
|
|
1287
|
+
? rawLastVerifiedAt < 1000000000000
|
|
1288
|
+
? rawLastVerifiedAt * 1000
|
|
1289
|
+
: rawLastVerifiedAt
|
|
1290
|
+
: undefined;
|
|
1291
|
+
const parsedLastVerifiedAt = numericLastVerifiedAt === undefined
|
|
1292
|
+
? undefined
|
|
1293
|
+
: new Date(numericLastVerifiedAt);
|
|
1294
|
+
const nextLastVerifiedAt = typeof rawLastVerifiedAt === 'string'
|
|
1295
|
+
? rawLastVerifiedAt
|
|
1296
|
+
: parsedLastVerifiedAt && !Number.isNaN(parsedLastVerifiedAt.getTime())
|
|
1297
|
+
? parsedLastVerifiedAt.toISOString()
|
|
1298
|
+
: undefined;
|
|
1213
1299
|
if (nextPaymentStatus === undefined
|
|
1214
1300
|
&& nextLimit === undefined
|
|
1215
1301
|
&& nextUsed === undefined
|
|
1216
|
-
&& nextRemaining === undefined
|
|
1302
|
+
&& nextRemaining === undefined
|
|
1303
|
+
&& nextLicenseSource === undefined
|
|
1304
|
+
&& nextAccessScope === undefined
|
|
1305
|
+
&& nextExpiresAt === undefined
|
|
1306
|
+
&& nextLastVerifiedAt === undefined) {
|
|
1217
1307
|
return;
|
|
1218
1308
|
}
|
|
1219
1309
|
setLiveUsage((previous) => ({
|
|
@@ -1222,6 +1312,10 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1222
1312
|
...(typeof nextLimit === 'number' ? { maxDailyUsage: nextLimit } : {}),
|
|
1223
1313
|
...(typeof nextUsed === 'number' ? { usageCount: nextUsed } : {}),
|
|
1224
1314
|
...(typeof nextRemaining === 'number' ? { remainingUsage: nextRemaining } : {}),
|
|
1315
|
+
...(nextLicenseSource ? { licenseSource: nextLicenseSource } : {}),
|
|
1316
|
+
...(nextAccessScope ? { accessScope: nextAccessScope } : {}),
|
|
1317
|
+
...(nextExpiresAt ? { expiresAt: nextExpiresAt } : {}),
|
|
1318
|
+
...(nextLastVerifiedAt ? { lastVerifiedAt: nextLastVerifiedAt } : {}),
|
|
1225
1319
|
}));
|
|
1226
1320
|
};
|
|
1227
1321
|
window.addEventListener('message', handleUsageMessage);
|
|
@@ -1280,7 +1374,7 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1280
1374
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
1281
1375
|
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, languages: languages, currentLanguage: currentLanguage, showLanguageSelector: showLanguageSelector, onLanguageChange: onLanguageChange, t: translate })),
|
|
1282
1376
|
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 })),
|
|
1377
|
+
(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
1378
|
showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t: translate })))),
|
|
1285
1379
|
children,
|
|
1286
1380
|
toastComponent));
|
|
@@ -1293,9 +1387,15 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
1293
1387
|
useEffect(() => {
|
|
1294
1388
|
setInputValue(value);
|
|
1295
1389
|
}, [value]);
|
|
1390
|
+
const submitLicense = async () => {
|
|
1391
|
+
const normalizedValue = inputValue.trim();
|
|
1392
|
+
if (!normalizedValue || disabled || isSubmitting)
|
|
1393
|
+
return;
|
|
1394
|
+
await onLicenseSubmit(normalizedValue);
|
|
1395
|
+
};
|
|
1296
1396
|
const handleSubmit = async (e) => {
|
|
1297
1397
|
e.preventDefault();
|
|
1298
|
-
await
|
|
1398
|
+
await submitLicense();
|
|
1299
1399
|
};
|
|
1300
1400
|
const handleChange = (value) => {
|
|
1301
1401
|
setInputValue(value);
|
|
@@ -1315,7 +1415,9 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
1315
1415
|
handleChange(value);
|
|
1316
1416
|
}
|
|
1317
1417
|
}, placeholder: displayPlaceholder, helperText: displayHelperText, disabled: disabled || isSubmitting, size: "m" })),
|
|
1318
|
-
React.createElement(Button, { type: "
|
|
1418
|
+
React.createElement(Button, { type: "button", variant: "primary", size: "m", loading: isSubmitting, disabled: !inputValue.trim() || isSubmitting || disabled, fullWidth: true, onPress: () => {
|
|
1419
|
+
void submitLicense();
|
|
1420
|
+
} }, isSubmitting ? displaySubmittingText : displaySubmitText)));
|
|
1319
1421
|
};
|
|
1320
1422
|
FormWithSubmit.displayName = 'FormWithSubmit';
|
|
1321
1423
|
|
|
@@ -1438,7 +1540,7 @@ function formatSource(value, t) {
|
|
|
1438
1540
|
}
|
|
1439
1541
|
return value;
|
|
1440
1542
|
}
|
|
1441
|
-
const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSource, accessScope, expiresAt, lastVerifiedAt, validationMessage, allowRevealKey = false, t, locale, className, }) => {
|
|
1543
|
+
const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSource, accessScope, expiresAt, lastVerifiedAt, validationMessage, showHeader = true, allowRevealKey = false, t, locale, className, }) => {
|
|
1442
1544
|
const { locale: resolvedLocale, t: translate } = useFigmaUiI18n(locale, t);
|
|
1443
1545
|
const [isKeyRevealed, setIsKeyRevealed] = useState(false);
|
|
1444
1546
|
const normalizedLicenseStatus = licenseStatus?.toLowerCase();
|
|
@@ -1449,13 +1551,15 @@ const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSour
|
|
|
1449
1551
|
: resolveText(translate, { key: 'license.status_inactive' }, 'License check failed');
|
|
1450
1552
|
const statusClass = isActive ? 'active' : 'inactive';
|
|
1451
1553
|
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" },
|
|
1554
|
+
showHeader && (React.createElement("div", { className: "designbase-figma-license-status-card__header" },
|
|
1453
1555
|
React.createElement("div", null,
|
|
1454
1556
|
React.createElement("div", { className: "designbase-figma-license-status-card__eyebrow" }, isActive
|
|
1455
1557
|
? resolveText(translate, { key: 'license.activated' }, '라이선스 활성화됨')
|
|
1456
1558
|
: resolveText(translate, { key: 'license.status_label' }, '라이선스 상태')),
|
|
1457
1559
|
React.createElement("h3", null, statusText)),
|
|
1458
|
-
React.createElement("span", { className: "designbase-figma-license-status-card__badge" },
|
|
1560
|
+
React.createElement("span", { className: "designbase-figma-license-status-card__badge" }, isActive
|
|
1561
|
+
? resolveText(translate, { key: 'license.status_active' }, '활성')
|
|
1562
|
+
: resolveText(translate, { key: 'license.status_inactive' }, '비활성')))),
|
|
1459
1563
|
validationMessage && !isActive && (React.createElement("p", { className: "designbase-figma-license-status-card__message" }, validationMessage)),
|
|
1460
1564
|
licenseKey && (React.createElement("div", { className: "designbase-figma-license-status-card__key-row" },
|
|
1461
1565
|
React.createElement("span", null, resolveText(translate, { key: 'license.key_label' }, '라이선스 키')),
|
|
@@ -1850,7 +1954,7 @@ function formatUsageLabel(state, t) {
|
|
|
1850
1954
|
}
|
|
1851
1955
|
return resolveText(t, { key: 'license.usage_generic', values: { remaining, limit } }, `남은 횟수 ${remaining}/${limit}`) ?? `남은 횟수 ${remaining}/${limit}`;
|
|
1852
1956
|
}
|
|
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, }) => {
|
|
1957
|
+
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
1958
|
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1855
1959
|
const links = useMemo(() => ({
|
|
1856
1960
|
purchaseUrl: wordpressLinks?.purchaseUrl ?? paymentPageUrl,
|
|
@@ -1863,13 +1967,21 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1863
1967
|
initialState: {
|
|
1864
1968
|
paymentStatus: initialStatus,
|
|
1865
1969
|
licenseKey: initialLicenseKey,
|
|
1970
|
+
hasLicenseKey: Boolean(initialLicenseKey),
|
|
1971
|
+
isLicenseRegistered: initialStatus === 'PAID',
|
|
1972
|
+
planTier: initialStatus === 'PAID' ? 'PRO' : 'FREE',
|
|
1973
|
+
usageLimit: initialStatus === 'PAID' ? 'unlimited' : 0,
|
|
1974
|
+
licenseStatus: initialLicenseStatus,
|
|
1975
|
+
licenseSource: initialLicenseSource,
|
|
1976
|
+
accessScope: initialAccessScope,
|
|
1977
|
+
expiresAt: initialExpiresAt,
|
|
1978
|
+
lastVerifiedAt: initialLastVerifiedAt,
|
|
1866
1979
|
usageCount: initialUsageCount,
|
|
1867
1980
|
},
|
|
1868
1981
|
onStateChange,
|
|
1869
1982
|
onPaymentStatusChange: setPaymentStatus,
|
|
1870
1983
|
onUsageCountChange: setUsageCount,
|
|
1871
1984
|
});
|
|
1872
|
-
const [showDetails, setShowDetails] = useState(false);
|
|
1873
1985
|
const [licenseKeyDraft, setLicenseKeyDraft] = useState(initialLicenseKey);
|
|
1874
1986
|
const isPaid = state.isLicenseRegistered && state.paymentStatus === 'PAID';
|
|
1875
1987
|
const isMembershipMode = mode === 'youtube-membership';
|
|
@@ -1894,7 +2006,7 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1894
2006
|
: isPaid
|
|
1895
2007
|
? resolveText(translate, { key: 'license.pro_account' }, '프로 계정')
|
|
1896
2008
|
: resolveText(translate, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
|
|
1897
|
-
|
|
2009
|
+
isPaid && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, resolveText(translate, { key: 'license.pro_plan' }, '프로 플랜')))),
|
|
1898
2010
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
1899
2011
|
? resolveText(translate, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
1900
2012
|
: isMembershipMode
|
|
@@ -1902,16 +2014,16 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1902
2014
|
: resolveText(translate, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
|
|
1903
2015
|
!isPaid && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
1904
2016
|
!isMembershipMode && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: translate })),
|
|
1905
|
-
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)),
|
|
1906
|
-
isPaid && (React.createElement("div", { className: "designbase-figma-page-
|
|
1907
|
-
React.createElement("div", { className: "designbase-figma-page-
|
|
1908
|
-
React.createElement("
|
|
1909
|
-
React.createElement(
|
|
1910
|
-
React.createElement(
|
|
1911
|
-
|
|
1912
|
-
React.createElement(
|
|
1913
|
-
|
|
1914
|
-
React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
2017
|
+
state.lastMessage && state.lastErrorCode && !state.deactivateMessage && (React.createElement("p", { className: `designbase-figma-page-license__feedback ${state.lastErrorCode ? 'designbase-figma-page-license__feedback--error' : ''}`, "aria-live": "polite" }, state.lastMessage)),
|
|
2018
|
+
isPaid && (React.createElement("div", { className: "designbase-figma-page-license__paid-summary" },
|
|
2019
|
+
React.createElement("div", { className: "designbase-figma-page-license__paid-hero" },
|
|
2020
|
+
React.createElement("span", { "aria-hidden": "true" }, "\u221E"),
|
|
2021
|
+
React.createElement("div", null,
|
|
2022
|
+
React.createElement("strong", null, resolveText(translate, { key: 'license.usage_unlimited' }, '무제한 사용')),
|
|
2023
|
+
React.createElement("p", null, resolveText(translate, { key: 'license.active_until_expiry' }, '만료일까지 모든 기능을 제한 없이 사용할 수 있습니다.')))),
|
|
2024
|
+
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 }),
|
|
2025
|
+
React.createElement("div", { className: "designbase-figma-page-license__paid-actions" },
|
|
2026
|
+
state.activationLimit > 0 && (React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
1915
2027
|
React.createElement("div", { className: "designbase-figma-page-license__remaining" },
|
|
1916
2028
|
Math.max(0, state.activationLimit - state.activationUsage),
|
|
1917
2029
|
' ',
|
|
@@ -1921,12 +2033,12 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
1921
2033
|
React.createElement("div", { className: "designbase-figma-page-license__usage-count" },
|
|
1922
2034
|
state.activationUsage,
|
|
1923
2035
|
"/",
|
|
1924
|
-
state.activationLimit)),
|
|
1925
|
-
React.createElement(
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
2036
|
+
state.activationLimit))),
|
|
2037
|
+
React.createElement(Button, { onPress: deactivateLicense, variant: "secondary", size: "m", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
2038
|
+
? resolveText(translate, { key: 'license.deactivating' }, '비활성화 중...')
|
|
2039
|
+
: resolveText(translate, { key: 'license.deactivate' }, '라이선스 비활성화')),
|
|
2040
|
+
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)),
|
|
2041
|
+
React.createElement("p", { className: "designbase-figma-page-license__deactivate-hint" }, resolveText(translate, { key: 'license.deactivate_hint' }, '이 기기에서 라이선스 연결을 해제합니다.'))))),
|
|
1930
2042
|
!isPaid && (React.createElement(React.Fragment, null,
|
|
1931
2043
|
isMembershipMode && (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t: translate })),
|
|
1932
2044
|
!isMembershipMode && (enableAccountAuth || links.purchaseUrl || links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|