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