@designbasekorea/figma-ui 0.7.0 → 0.7.2

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