@designbasekorea/figma-ui 0.8.0 → 0.8.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/README.md +4 -0
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +103 -44
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +103 -44
- package/dist/index.js.map +1 -1
- package/package.json +100 -100
package/dist/index.esm.js
CHANGED
|
@@ -38,6 +38,15 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
38
38
|
remainingShort: '남음',
|
|
39
39
|
usageCountCaption: '오늘 사용',
|
|
40
40
|
remainingCopy: '{{count}}회 남음 · 매일 리셋',
|
|
41
|
+
'usage.caption.none': '남은 무료 사용량',
|
|
42
|
+
'usage.caption.weekly': '이번 주 남은 사용량',
|
|
43
|
+
'usage.caption.monthly': '이번 달 남은 사용량',
|
|
44
|
+
'usage.remaining.none': '{{count}}회 남음 · 자동 초기화 없음',
|
|
45
|
+
'usage.remaining.weekly': '{{count}}회 남음 · 매주 초기화',
|
|
46
|
+
'usage.remaining.monthly': '{{count}}회 남음 · 매월 초기화',
|
|
47
|
+
'license.this_plugin': '현재 플러그인',
|
|
48
|
+
'license.purchase_or_membership_description': '구매한 상품의 라이선스 키 또는 YouTube 멤버십 키를 등록하세요. 이용 범위는 키에 부여된 권한에 따라 달라집니다.',
|
|
49
|
+
'license.purchase_benefit_title': '구매한 플러그인의 프로 기능 사용',
|
|
41
50
|
lowUsageWarning: '무료 사용량이 {{count}}회({{percent}}%) 남았습니다. 멤버십으로 무제한 이용해보세요.',
|
|
42
51
|
usageUnavailable: '사용량 제한이 없습니다',
|
|
43
52
|
unlimitedUsageTooltip: '모든 기능을 제한 없이 사용할 수 있습니다',
|
|
@@ -98,6 +107,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
98
107
|
'license.authenticating': '인증 중...',
|
|
99
108
|
'license.login_with_designbase': '디자인베이스로 로그인',
|
|
100
109
|
'license.purchase_membership': '멤버십 안내',
|
|
110
|
+
'license.purchase_license': '라이선스 구매하기',
|
|
101
111
|
'license.manage_account': '계정·멤버십 관리',
|
|
102
112
|
'license.enter_key': '라이선스 키 입력',
|
|
103
113
|
'license.key': '라이선스 키',
|
|
@@ -196,6 +206,15 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
196
206
|
remainingShort: 'left',
|
|
197
207
|
usageCountCaption: 'Used today',
|
|
198
208
|
remainingCopy: '{{count}} remaining · resets daily',
|
|
209
|
+
'usage.caption.none': 'Remaining free uses',
|
|
210
|
+
'usage.caption.weekly': 'Remaining uses this week',
|
|
211
|
+
'usage.caption.monthly': 'Remaining uses this month',
|
|
212
|
+
'usage.remaining.none': '{{count}} uses left · No automatic reset',
|
|
213
|
+
'usage.remaining.weekly': '{{count}} uses left · Resets weekly',
|
|
214
|
+
'usage.remaining.monthly': '{{count}} uses left · Resets monthly',
|
|
215
|
+
'license.this_plugin': 'This plugin',
|
|
216
|
+
'license.purchase_or_membership_description': 'Enter a purchased product license or a YouTube membership key. Access depends on the permissions attached to your key.',
|
|
217
|
+
'license.purchase_benefit_title': 'Unlock Pro for your purchased plugin',
|
|
199
218
|
lowUsageWarning: 'Only {{count}} free uses ({{percent}}%) remain. Upgrade for unlimited access.',
|
|
200
219
|
usageUnavailable: 'No usage limit',
|
|
201
220
|
unlimitedUsageTooltip: 'Use every feature without limits',
|
|
@@ -256,6 +275,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
256
275
|
'license.authenticating': 'Authenticating...',
|
|
257
276
|
'license.login_with_designbase': 'Sign in with Designbase',
|
|
258
277
|
'license.purchase_membership': 'Membership details',
|
|
278
|
+
'license.purchase_license': 'Buy a license',
|
|
259
279
|
'license.manage_account': 'Manage account · membership',
|
|
260
280
|
'license.enter_key': 'Enter license key',
|
|
261
281
|
'license.key': 'License key',
|
|
@@ -354,6 +374,15 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
354
374
|
remainingShort: '残り',
|
|
355
375
|
usageCountCaption: '今日の使用',
|
|
356
376
|
remainingCopy: '{{count}}回残り · 毎日リセット',
|
|
377
|
+
'usage.caption.none': '無料利用の残り回数',
|
|
378
|
+
'usage.caption.weekly': '今週の残り回数',
|
|
379
|
+
'usage.caption.monthly': '今月の残り回数',
|
|
380
|
+
'usage.remaining.none': '残り{{count}}回 · 自動リセットなし',
|
|
381
|
+
'usage.remaining.weekly': '残り{{count}}回 · 毎週リセット',
|
|
382
|
+
'usage.remaining.monthly': '残り{{count}}回 · 毎月リセット',
|
|
383
|
+
'license.this_plugin': 'このプラグイン',
|
|
384
|
+
'license.purchase_or_membership_description': '購入ライセンスまたはYouTubeメンバーシップキーを登録してください。利用範囲はキーの権限によって異なります。',
|
|
385
|
+
'license.purchase_benefit_title': '購入したプラグインのPro機能を利用',
|
|
357
386
|
lowUsageWarning: '無料使用回数は残り{{count}}回({{percent}}%)です。無制限利用にアップグレードできます。',
|
|
358
387
|
usageUnavailable: '使用制限はありません',
|
|
359
388
|
unlimitedUsageTooltip: 'すべての機能を無制限で使用できます',
|
|
@@ -414,6 +443,7 @@ const FIGMA_UI_TRANSLATIONS = {
|
|
|
414
443
|
'license.authenticating': '認証中...',
|
|
415
444
|
'license.login_with_designbase': 'Designbaseでサインイン',
|
|
416
445
|
'license.purchase_membership': 'メンバーシップの詳細',
|
|
446
|
+
'license.purchase_license': 'ライセンスを購入',
|
|
417
447
|
'license.manage_account': 'アカウント・メンバーシップを管理',
|
|
418
448
|
'license.enter_key': 'ライセンスキーを入力',
|
|
419
449
|
'license.key': 'ライセンスキー',
|
|
@@ -1057,7 +1087,7 @@ const fallbackText = (t, key, fallback) => {
|
|
|
1057
1087
|
const translated = t?.(key);
|
|
1058
1088
|
return translated && translated !== key ? translated : fallback;
|
|
1059
1089
|
};
|
|
1060
|
-
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, licenseSource, accessScope, expiresAt, lastVerifiedAt, t, locale, className, }) => {
|
|
1090
|
+
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, maxDailyUsage = 20, usageReset = 'daily', showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, licenseSource, accessScope, expiresAt, lastVerifiedAt, t, locale, className, }) => {
|
|
1061
1091
|
const { t: translate } = useFigmaUiI18n(locale, t);
|
|
1062
1092
|
const [isOpen, setIsOpen] = useState(false);
|
|
1063
1093
|
const rootRef = useRef(null);
|
|
@@ -1107,15 +1137,15 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1107
1137
|
};
|
|
1108
1138
|
const formattedSource = licenseSource === 'youtube_membership' || licenseSource === 'membership'
|
|
1109
1139
|
? fallbackText(translate, 'license.source_youtube_membership', 'YouTube 멤버십')
|
|
1110
|
-
: licenseSource
|
|
1140
|
+
: ['lemonsqueezy', 'lemon_squeezy', 'lemon-squeezy', 'order'].includes(licenseSource || '')
|
|
1111
1141
|
? fallbackText(translate, 'license.source_purchase', '구매 라이선스')
|
|
1112
1142
|
: licenseSource;
|
|
1113
1143
|
const formattedScope = accessScope === 'all-products' || accessScope === 'all_products'
|
|
1114
1144
|
? fallbackText(translate, 'license.all_plugins', '모든 플러그인')
|
|
1115
|
-
: accessScope;
|
|
1145
|
+
: accessScope === 'product' ? fallbackText(translate, 'license.this_plugin', '현재 플러그인') : accessScope;
|
|
1116
1146
|
const paidMetadata = [
|
|
1117
1147
|
formattedSource && {
|
|
1118
|
-
label: fallbackText(translate, 'license.
|
|
1148
|
+
label: fallbackText(translate, 'license.source', '출처'),
|
|
1119
1149
|
value: formattedSource,
|
|
1120
1150
|
},
|
|
1121
1151
|
expiresAt && {
|
|
@@ -1197,13 +1227,13 @@ const UsageStatusPopover = ({ paymentStatus, usageCount = 0, remainingUsage, max
|
|
|
1197
1227
|
remaining,
|
|
1198
1228
|
React.createElement("span", { className: "designbase-figma-usage-status__usage-divider" }, "/"),
|
|
1199
1229
|
limit),
|
|
1200
|
-
React.createElement("span", { className: "designbase-figma-usage-status__usage-caption" }, fallbackText(translate, 'remainingToday', '오늘 남은 사용량')),
|
|
1230
|
+
React.createElement("span", { className: "designbase-figma-usage-status__usage-caption" }, usageReset === 'daily' ? fallbackText(translate, 'remainingToday', '오늘 남은 사용량') : translate(`usage.caption.${usageReset}`)),
|
|
1201
1231
|
React.createElement("strong", { className: "designbase-figma-usage-status__usage-percent" },
|
|
1202
1232
|
remainingPercent,
|
|
1203
1233
|
"%")),
|
|
1204
|
-
React.createElement("div", { className: "designbase-figma-usage-status__progress", role: "progressbar", "aria-label": fallbackText(translate, 'remainingToday', '오늘 남은 사용량'), "aria-valuemin": 0, "aria-valuemax": limit, "aria-valuenow": remaining, "aria-valuetext": `${remaining} / ${limit}, ${remainingPercent}%` },
|
|
1234
|
+
React.createElement("div", { className: "designbase-figma-usage-status__progress", role: "progressbar", "aria-label": usageReset === 'daily' ? fallbackText(translate, 'remainingToday', '오늘 남은 사용량') : translate(`usage.caption.${usageReset}`), "aria-valuemin": 0, "aria-valuemax": limit, "aria-valuenow": remaining, "aria-valuetext": `${remaining} / ${limit}, ${remainingPercent}%` },
|
|
1205
1235
|
React.createElement("span", { style: { width: `${remainingPercent}%` } })),
|
|
1206
|
-
React.createElement("p", { className: "designbase-figma-usage-status__remaining-copy" }, resolveText(translate, { key: 'remainingCopy'
|
|
1236
|
+
React.createElement("p", { className: "designbase-figma-usage-status__remaining-copy" }, resolveText(translate, { key: usageReset === 'daily' ? 'remainingCopy' : `usage.remaining.${usageReset}`, values: { count: remaining } }, `${remaining}회 남음 · 매일 리셋`)))) : (React.createElement("p", { className: "designbase-figma-usage-status__note" }, fallbackText(translate, 'usageUnavailable', '사용량 제한이 없습니다')))))));
|
|
1207
1237
|
};
|
|
1208
1238
|
UsageStatusPopover.displayName = 'UsageStatusPopover';
|
|
1209
1239
|
|
|
@@ -1293,7 +1323,7 @@ FigmaToastProvider.displayName = 'FigmaToastProvider';
|
|
|
1293
1323
|
FigmaToast.displayName = 'FigmaToast';
|
|
1294
1324
|
|
|
1295
1325
|
const DEFAULT_LOW_USAGE_WARNING = { key: 'lowUsageWarning' };
|
|
1296
|
-
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, }) => {
|
|
1326
|
+
const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount = 0, remainingUsage, listenForUsageMessages = true, isLoading = false, showPaymentStatus = true, showUsageInfo = true, maxDailyUsage = 20, usageReset = 'daily', 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, }) => {
|
|
1297
1327
|
const { t: translate } = useFigmaUiI18n(currentLanguage, t);
|
|
1298
1328
|
const { showToast, toastComponent } = useFigmaToast();
|
|
1299
1329
|
const [liveUsage, setLiveUsage] = useState({});
|
|
@@ -1303,6 +1333,7 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1303
1333
|
const effectiveUsageCount = liveUsage.usageCount ?? usageCount;
|
|
1304
1334
|
const effectiveRemainingUsage = liveUsage.remainingUsage ?? remainingUsage;
|
|
1305
1335
|
const effectiveMaxDailyUsage = liveUsage.maxDailyUsage ?? maxDailyUsage;
|
|
1336
|
+
const effectiveUsageReset = liveUsage.usageReset ?? usageReset;
|
|
1306
1337
|
const effectiveLicenseSource = liveUsage.licenseSource ?? licenseSource;
|
|
1307
1338
|
const effectiveAccessScope = liveUsage.accessScope ?? accessScope;
|
|
1308
1339
|
const effectiveExpiresAt = liveUsage.expiresAt ?? expiresAt;
|
|
@@ -1327,6 +1358,8 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1327
1358
|
}
|
|
1328
1359
|
const nextLimit = [message.usageLimit, message.freeDailyLimit, message.maxDailyUsage]
|
|
1329
1360
|
.find((value) => typeof value === 'number' && Number.isFinite(value) && value > 0);
|
|
1361
|
+
const nextReset = ['none', 'daily', 'weekly', 'monthly'].includes(message.usageReset)
|
|
1362
|
+
? message.usageReset : undefined;
|
|
1330
1363
|
const nextUsed = [message.usageUsed, message.dailyUsage]
|
|
1331
1364
|
.find((value) => typeof value === 'number' && Number.isFinite(value) && value >= 0);
|
|
1332
1365
|
const nextRemaining = typeof message.remainingUsage === 'number' && Number.isFinite(message.remainingUsage)
|
|
@@ -1358,6 +1391,7 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1358
1391
|
: undefined;
|
|
1359
1392
|
if (nextPaymentStatus === undefined
|
|
1360
1393
|
&& nextLimit === undefined
|
|
1394
|
+
&& nextReset === undefined
|
|
1361
1395
|
&& nextUsed === undefined
|
|
1362
1396
|
&& nextRemaining === undefined
|
|
1363
1397
|
&& nextLicenseSource === undefined
|
|
@@ -1370,12 +1404,17 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1370
1404
|
...previous,
|
|
1371
1405
|
...(nextPaymentStatus ? { paymentStatus: nextPaymentStatus } : {}),
|
|
1372
1406
|
...(typeof nextLimit === 'number' ? { maxDailyUsage: nextLimit } : {}),
|
|
1407
|
+
...(nextReset !== undefined ? { usageReset: nextReset } : {}),
|
|
1373
1408
|
...(typeof nextUsed === 'number' ? { usageCount: nextUsed } : {}),
|
|
1374
1409
|
...(typeof nextRemaining === 'number' ? { remainingUsage: nextRemaining } : {}),
|
|
1375
1410
|
...(nextLicenseSource ? { licenseSource: nextLicenseSource } : {}),
|
|
1376
1411
|
...(nextAccessScope ? { accessScope: nextAccessScope } : {}),
|
|
1377
1412
|
...(nextExpiresAt ? { expiresAt: nextExpiresAt } : {}),
|
|
1378
1413
|
...(nextLastVerifiedAt ? { lastVerifiedAt: nextLastVerifiedAt } : {}),
|
|
1414
|
+
...((nextPaymentStatus === 'FREE' || nextLicenseSource !== undefined || nextAccessScope !== undefined) ? {
|
|
1415
|
+
licenseSource: nextLicenseSource || '', accessScope: nextAccessScope || '',
|
|
1416
|
+
expiresAt: nextExpiresAt || '', lastVerifiedAt: nextLastVerifiedAt || '',
|
|
1417
|
+
} : {}),
|
|
1379
1418
|
}));
|
|
1380
1419
|
};
|
|
1381
1420
|
window.addEventListener('message', handleUsageMessage);
|
|
@@ -1434,7 +1473,7 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
1434
1473
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
1435
1474
|
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, languages: languages, currentLanguage: currentLanguage, showLanguageSelector: showLanguageSelector, onLanguageChange: onLanguageChange, t: translate })),
|
|
1436
1475
|
React.createElement("div", { className: "designbase-figma-footer__right" },
|
|
1437
|
-
(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 })),
|
|
1476
|
+
(resolvedShowUsageInfo || resolvedShowPaymentBadge) && (React.createElement(UsageStatusPopover, { paymentStatus: effectivePaymentStatus, usageCount: effectiveUsageCount, remainingUsage: effectiveRemainingUsage, maxDailyUsage: effectiveMaxDailyUsage, usageReset: effectiveUsageReset, showUsage: resolvedShowUsageInfo, showPlan: resolvedShowPaymentBadge, isLoading: isLoading, onLicensePageClick: resolvedLicensePageClick, licenseSource: effectiveLicenseSource, accessScope: effectiveAccessScope, expiresAt: effectiveExpiresAt, lastVerifiedAt: effectiveLastVerifiedAt, locale: currentLanguage, t: translate })),
|
|
1438
1477
|
showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t: translate })))),
|
|
1439
1478
|
children,
|
|
1440
1479
|
toastComponent));
|
|
@@ -1597,6 +1636,8 @@ function formatScope(value, t) {
|
|
|
1597
1636
|
if (value === 'all-products' || value === 'all_products') {
|
|
1598
1637
|
return resolveText(t, { key: 'license.all_plugins' }, '모든 플러그인');
|
|
1599
1638
|
}
|
|
1639
|
+
if (value === 'product')
|
|
1640
|
+
return resolveText(t, { key: 'license.this_plugin' }, '현재 플러그인');
|
|
1600
1641
|
return value;
|
|
1601
1642
|
}
|
|
1602
1643
|
function formatSource(value, t) {
|
|
@@ -1605,7 +1646,7 @@ function formatSource(value, t) {
|
|
|
1605
1646
|
if (value === 'youtube_membership' || value === 'membership') {
|
|
1606
1647
|
return resolveText(t, { key: 'license.source_youtube_membership' }, 'YouTube 멤버십');
|
|
1607
1648
|
}
|
|
1608
|
-
if (
|
|
1649
|
+
if (['lemonsqueezy', 'lemon_squeezy', 'lemon-squeezy', 'order'].includes(value)) {
|
|
1609
1650
|
return resolveText(t, { key: 'license.source_purchase' }, '구매 라이선스');
|
|
1610
1651
|
}
|
|
1611
1652
|
return value;
|
|
@@ -1835,12 +1876,21 @@ function readBoolean(data, keys) {
|
|
|
1835
1876
|
}
|
|
1836
1877
|
return undefined;
|
|
1837
1878
|
}
|
|
1879
|
+
function readOptionalText(data, keys) {
|
|
1880
|
+
for (const key of keys) {
|
|
1881
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1882
|
+
return typeof data[key] === 'string' ? data[key] : '';
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
return undefined;
|
|
1886
|
+
}
|
|
1838
1887
|
function parseLicenseMessage(data) {
|
|
1839
|
-
const
|
|
1888
|
+
const status = readString(data, ['paymentStatus', 'status']);
|
|
1889
|
+
const paymentStatus = ['PAID', 'FREE', 'UNPAID'].includes(status) ? status : '';
|
|
1840
1890
|
const usageLimitRaw = data.usageLimit;
|
|
1841
1891
|
return {
|
|
1842
1892
|
...(paymentStatus ? { paymentStatus } : {}),
|
|
1843
|
-
licenseKey:
|
|
1893
|
+
licenseKey: readOptionalText(data, ['licenseKey']),
|
|
1844
1894
|
planTier: readString(data, ['planTier']) || undefined,
|
|
1845
1895
|
hasLicenseKey: readBoolean(data, ['hasLicenseKey']),
|
|
1846
1896
|
isLicenseRegistered: readBoolean(data, ['isLicenseRegistered']),
|
|
@@ -1855,12 +1905,12 @@ function parseLicenseMessage(data) {
|
|
|
1855
1905
|
usageReason: readString(data, ['usageReason']) || undefined,
|
|
1856
1906
|
lastMessage: readString(data, ['message']) || undefined,
|
|
1857
1907
|
lastErrorCode: readString(data, ['errorCode']) || undefined,
|
|
1858
|
-
licenseStatus:
|
|
1859
|
-
licenseSource:
|
|
1860
|
-
accessScope:
|
|
1861
|
-
expiresAt:
|
|
1862
|
-
lastVerifiedAt:
|
|
1863
|
-
validationMessage:
|
|
1908
|
+
licenseStatus: readOptionalText(data, ['licenseStatus', 'license_status']),
|
|
1909
|
+
licenseSource: readOptionalText(data, ['licenseSource', 'license_source', 'source']),
|
|
1910
|
+
accessScope: readOptionalText(data, ['accessScope', 'access_scope', 'scope']),
|
|
1911
|
+
expiresAt: readOptionalText(data, ['expiresAt', 'expires_at']),
|
|
1912
|
+
lastVerifiedAt: readOptionalText(data, ['lastVerifiedAt', 'last_verified_at']),
|
|
1913
|
+
validationMessage: readOptionalText(data, ['validationMessage', 'validation_message']),
|
|
1864
1914
|
};
|
|
1865
1915
|
}
|
|
1866
1916
|
function useFigmaLicenseBridge(options = {}) {
|
|
@@ -1931,8 +1981,16 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
1931
1981
|
isLicenseRegistered: false,
|
|
1932
1982
|
activationLimit: 0,
|
|
1933
1983
|
activationUsage: 0,
|
|
1984
|
+
licenseStatus: '',
|
|
1985
|
+
licenseSource: '',
|
|
1986
|
+
accessScope: '',
|
|
1987
|
+
expiresAt: '',
|
|
1988
|
+
lastVerifiedAt: '',
|
|
1989
|
+
validationMessage: '',
|
|
1990
|
+
lastMessage: '',
|
|
1991
|
+
lastErrorCode: '',
|
|
1934
1992
|
deactivateMessage: parsed.lastMessage || '라이선스가 비활성화되었습니다.',
|
|
1935
|
-
deactivateErrorCode:
|
|
1993
|
+
deactivateErrorCode: '',
|
|
1936
1994
|
});
|
|
1937
1995
|
}
|
|
1938
1996
|
}
|
|
@@ -2058,6 +2116,7 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
2058
2116
|
const [activeLicenseMode, setActiveLicenseMode] = useState(mode);
|
|
2059
2117
|
const isPaid = state.isLicenseRegistered && state.paymentStatus === 'PAID';
|
|
2060
2118
|
const isMembershipMode = activeLicenseMode === 'youtube-membership';
|
|
2119
|
+
const hasSourceTabs = showYoutubeMembershipTab && !isPaid;
|
|
2061
2120
|
const usageLabel = formatUsageLabel(state, translate);
|
|
2062
2121
|
const handleLicenseSubmit = async (submittedLicenseKey) => {
|
|
2063
2122
|
if (onLicenseSubmit) {
|
|
@@ -2070,36 +2129,33 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
2070
2129
|
setLicenseKeyDraft(value);
|
|
2071
2130
|
setLicenseKeyInput(value);
|
|
2072
2131
|
};
|
|
2073
|
-
return (React.createElement("div", { className: `designbase-figma-page-license designbase-figma-page-license--${activeLicenseMode} ${className || ''}`, "data-license-mode": activeLicenseMode },
|
|
2132
|
+
return (React.createElement("div", { className: `designbase-figma-page-license designbase-figma-page-license--${activeLicenseMode} ${hasSourceTabs ? 'designbase-figma-page-license--source-switching' : ''} ${className || ''}`, "data-license-mode": activeLicenseMode },
|
|
2074
2133
|
React.createElement("div", { className: "designbase-figma-page-license__content" },
|
|
2075
|
-
showYoutubeMembershipTab && (React.createElement("div", { className: "designbase-figma-page-license__source-tabs", role: "tablist", "aria-label": resolveText(translate, { key: 'license.source_tabs_label' }, 'License type') },
|
|
2076
|
-
React.createElement("button", { type: "button", role: "tab", "aria-selected": !isMembershipMode, onClick: () => setActiveLicenseMode('pricing') }, resolveText(translate, { key: 'license.source_lemon_squeezy' }, 'Lemon Squeezy license')),
|
|
2077
|
-
React.createElement("button", { type: "button", role: "tab", "aria-selected": isMembershipMode, onClick: () => setActiveLicenseMode('youtube-membership') }, resolveText(translate, { key: 'license.source_youtube_membership' }, 'YouTube membership')))),
|
|
2078
|
-
showYoutubeMembershipTab && (React.createElement("p", { className: "designbase-figma-page-license__source-hint" }, isMembershipMode
|
|
2079
|
-
? resolveText(translate, { key: 'license.source_youtube_hint' }, 'Enter the key provided to YouTube channel members.')
|
|
2080
|
-
: resolveText(translate, { key: 'license.source_lemon_hint' }, 'Enter the license key from your Lemon Squeezy purchase.'))),
|
|
2081
2134
|
React.createElement("div", { className: "designbase-figma-page-license__header" },
|
|
2082
2135
|
React.createElement("div", { className: "designbase-figma-page-license__title" },
|
|
2083
2136
|
React.createElement("h2", null, isPaid
|
|
2084
2137
|
? resolveText(translate, { key: 'license.pro_account' }, '프로 계정')
|
|
2085
|
-
: isMembershipMode
|
|
2086
|
-
? resolveText(translate, { key: 'license.unlock_unlimited' }, '
|
|
2138
|
+
: (showYoutubeMembershipTab || isMembershipMode)
|
|
2139
|
+
? resolveText(translate, { key: 'license.unlock_unlimited' }, 'Unlock Unlimited Access')
|
|
2087
2140
|
: resolveText(translate, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
|
|
2088
2141
|
isPaid && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, resolveText(translate, { key: 'license.pro_plan' }, '프로 플랜')))),
|
|
2089
2142
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
2090
2143
|
? resolveText(translate, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
2091
|
-
: isMembershipMode
|
|
2144
|
+
: (showYoutubeMembershipTab || isMembershipMode)
|
|
2092
2145
|
? resolveText(translate, {
|
|
2093
|
-
key: 'license.unlock_unlimited_description',
|
|
2094
|
-
}, '
|
|
2146
|
+
key: isMembershipMode ? 'license.unlock_unlimited_description' : 'license.purchase_or_membership_description',
|
|
2147
|
+
}, 'Add a license key to unlock Pro features and unlimited use across Designbase plugins.')
|
|
2095
2148
|
: resolveText(translate, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
|
|
2096
|
-
!isPaid && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
2097
|
-
!isPaid && isMembershipMode && (React.createElement("div", { className: "designbase-figma-page-license__benefit" },
|
|
2149
|
+
!isPaid && !showYoutubeMembershipTab && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
2150
|
+
!isPaid && (showYoutubeMembershipTab || isMembershipMode) && (React.createElement("div", { className: "designbase-figma-page-license__benefit" },
|
|
2098
2151
|
React.createElement("span", { className: "designbase-figma-page-license__benefit-icon", "aria-hidden": "true" }, "\u221E"),
|
|
2099
2152
|
React.createElement("div", null,
|
|
2100
|
-
React.createElement("strong", null, resolveText(translate, { key: 'license.unlimited_benefit_title' }, '모든 플러그인 무제한 사용')),
|
|
2153
|
+
React.createElement("strong", null, resolveText(translate, { key: isMembershipMode ? 'license.unlimited_benefit_title' : 'license.purchase_benefit_title' }, '모든 플러그인 무제한 사용')),
|
|
2101
2154
|
React.createElement("p", null, resolveText(translate, { key: 'license.unlimited_benefit_description' }, '사용 횟수 제한 없이 프로 기능과 프리미엄 콘텐츠를 이용할 수 있습니다.'))))),
|
|
2102
|
-
|
|
2155
|
+
hasSourceTabs && (React.createElement("div", { className: "designbase-figma-page-license__source-tabs", role: "tablist", "aria-label": resolveText(translate, { key: 'license.source_tabs_label' }, 'License type') },
|
|
2156
|
+
React.createElement("button", { type: "button", role: "tab", "aria-selected": !isMembershipMode, onClick: () => setActiveLicenseMode('pricing') }, resolveText(translate, { key: 'license.source_lemon_squeezy' }, 'Lemon Squeezy license')),
|
|
2157
|
+
React.createElement("button", { type: "button", role: "tab", "aria-selected": isMembershipMode, onClick: () => setActiveLicenseMode('youtube-membership') }, resolveText(translate, { key: 'license.source_youtube_membership' }, 'YouTube membership')))),
|
|
2158
|
+
!isMembershipMode && !showYoutubeMembershipTab && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: translate })),
|
|
2103
2159
|
state.lastMessage &&
|
|
2104
2160
|
state.lastErrorCode &&
|
|
2105
2161
|
!state.deactivateMessage && (React.createElement("p", { className: `designbase-figma-page-license__feedback ${state.lastErrorCode ? 'designbase-figma-page-license__feedback--error' : ''}`, "aria-live": "polite" }, state.lastMessage)),
|
|
@@ -2132,8 +2188,8 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
2132
2188
|
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)),
|
|
2133
2189
|
React.createElement("p", { className: "designbase-figma-page-license__deactivate-hint" }, resolveText(translate, { key: 'license.deactivate_hint' }, '이 기기에서 라이선스 연결을 해제합니다.'))))),
|
|
2134
2190
|
!isPaid && (React.createElement(React.Fragment, null,
|
|
2135
|
-
isMembershipMode && (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t: translate })),
|
|
2136
|
-
!isMembershipMode &&
|
|
2191
|
+
isMembershipMode && !showYoutubeMembershipTab && (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t: translate })),
|
|
2192
|
+
!isMembershipMode && !showYoutubeMembershipTab &&
|
|
2137
2193
|
(enableAccountAuth ||
|
|
2138
2194
|
links.purchaseUrl ||
|
|
2139
2195
|
links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
@@ -2163,20 +2219,23 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
2163
2219
|
key: 'license.manage_account',
|
|
2164
2220
|
}, '계정·멤버십 관리')),
|
|
2165
2221
|
React.createElement(ExternalLinkIcon, { size: 16 })))))),
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2222
|
+
showYoutubeMembershipTab && (React.createElement("div", { "aria-live": "polite" }, isMembershipMode ? (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t: translate })) : (React.createElement(React.Fragment, null,
|
|
2223
|
+
React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: translate }),
|
|
2224
|
+
links.purchaseUrl && (React.createElement(Button, { onPress: () => openExternalUrl(links.purchaseUrl), variant: "primary", size: "m", fullWidth: true },
|
|
2225
|
+
React.createElement("span", null, resolveText(translate, { key: 'license.purchase_license' }, 'Buy a license')),
|
|
2226
|
+
React.createElement(ExternalLinkIcon, { size: 16, "aria-hidden": "true" }))))))),
|
|
2227
|
+
showLicenseKeyInput && (React.createElement("div", { className: isMembershipMode && !showYoutubeMembershipTab ? 'designbase-figma-page-license__key-form' : 'designbase-figma-page-license__section' },
|
|
2169
2228
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
2170
|
-
React.createElement("h3", null, isMembershipMode
|
|
2229
|
+
React.createElement("h3", null, isMembershipMode || showYoutubeMembershipTab
|
|
2171
2230
|
? resolveText(translate, {
|
|
2172
2231
|
key: 'license.activate_key_title',
|
|
2173
2232
|
}, '라이선스 키 등록')
|
|
2174
2233
|
: resolveText(translate, { key: 'license.enter_key' }, '라이선스 키 입력'))),
|
|
2175
|
-
isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(translate, {
|
|
2234
|
+
(isMembershipMode || showYoutubeMembershipTab) && (React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(translate, {
|
|
2176
2235
|
key: 'license.activate_key_description',
|
|
2177
2236
|
}, '이미 키가 있다면 아래에 붙여 넣어 프로 기능을 활성화하세요.'))),
|
|
2178
2237
|
React.createElement(FormWithSubmit, { onLicenseSubmit: handleLicenseSubmit, disabled: false, isSubmitting: isVerifying, value: licenseKeyDraft, onValueChange: handleLicenseKeyChange, label: { key: 'license.key' }, submitText: {
|
|
2179
|
-
key: isMembershipMode
|
|
2238
|
+
key: isMembershipMode || showYoutubeMembershipTab
|
|
2180
2239
|
? 'license.unlock_pro_features'
|
|
2181
2240
|
: 'license.submit',
|
|
2182
2241
|
}, submittingText: {
|
|
@@ -2186,7 +2245,7 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
2186
2245
|
? 'license.enter_from_youtube'
|
|
2187
2246
|
: 'license.enter_from_email',
|
|
2188
2247
|
}, t: translate }))))),
|
|
2189
|
-
links.helpUrl && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
2248
|
+
links.helpUrl && (!isMembershipMode || showYoutubeMembershipTab) && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
2190
2249
|
React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(translate, { key: 'license.help_link' }, '라이선스·결제 도움말'))))),
|
|
2191
2250
|
React.createElement(Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", iconOnly: true, "aria-label": translate('close') },
|
|
2192
2251
|
React.createElement(CloseIcon, { size: 16 }))));
|