@designbasekorea/figma-ui 0.6.4 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +76 -3
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +538 -150
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1071 -146
- package/dist/index.js.map +1 -1
- package/package.json +18 -18
package/dist/index.esm.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import React, { useRef, useState, useLayoutEffect, useEffect, createContext, useContext, useCallback, useMemo } from 'react';
|
|
2
|
-
import { Button, Dropdown, Badge, Toggle,
|
|
1
|
+
import React, { useRef, useState, useLayoutEffect, useEffect, useId, createContext, useContext, useCallback, useMemo } from 'react';
|
|
2
|
+
import { Button, Dropdown, Badge, Toggle, Modal, 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
6
|
|
|
6
7
|
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
|
|
7
8
|
|
|
9
|
+
function interpolateText(template, values) {
|
|
10
|
+
if (!values)
|
|
11
|
+
return template;
|
|
12
|
+
return Object.entries(values).reduce((result, [key, value]) => {
|
|
13
|
+
const replacement = value == null ? '' : String(value);
|
|
14
|
+
return result.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), replacement);
|
|
15
|
+
}, template);
|
|
16
|
+
}
|
|
8
17
|
function resolveText(t, input, fallback) {
|
|
9
18
|
if (input == null)
|
|
10
19
|
return fallback;
|
|
@@ -14,10 +23,13 @@ function resolveText(t, input, fallback) {
|
|
|
14
23
|
if (t) {
|
|
15
24
|
const translated = t(input.key, input.values);
|
|
16
25
|
if (translated && translated !== input.key) {
|
|
17
|
-
return translated;
|
|
26
|
+
return interpolateText(translated, input.values);
|
|
18
27
|
}
|
|
19
28
|
}
|
|
20
|
-
|
|
29
|
+
if (fallback) {
|
|
30
|
+
return interpolateText(fallback, input.values);
|
|
31
|
+
}
|
|
32
|
+
return input.key;
|
|
21
33
|
}
|
|
22
34
|
|
|
23
35
|
const DONATION_ICON_NAMES = {
|
|
@@ -383,58 +395,63 @@ const FigmaSidebar = ({ categories, categoryGroups = {}, categoryLabels = {}, ac
|
|
|
383
395
|
};
|
|
384
396
|
FigmaSidebar.displayName = 'FigmaSidebar';
|
|
385
397
|
|
|
386
|
-
|
|
387
|
-
const getBadgeText = () => {
|
|
388
|
-
if (text)
|
|
389
|
-
return text;
|
|
390
|
-
return isActive
|
|
391
|
-
? (t('proUser') || '프로 계정')
|
|
392
|
-
: (t('usingFree') || '무료 사용');
|
|
393
|
-
};
|
|
394
|
-
const getBadgeVariant = () => {
|
|
395
|
-
return isActive ? 'success' : 'secondary';
|
|
396
|
-
};
|
|
397
|
-
return (React.createElement("div", { className: `designbase-figma-payment-badge ${className || ''} ${isActive ? 'active' : 'free'}`, onClick: onClick, style: { cursor: onClick ? 'pointer' : 'default' } }, isLoading ? (React.createElement(Spinner, { size: "s" })) : (React.createElement(Badge, { variant: getBadgeVariant(), size: "s", className: "designbase-figma-payment-badge__badge" }, getBadgeText()))));
|
|
398
|
-
};
|
|
399
|
-
PaymentBadge.displayName = 'PaymentBadge';
|
|
400
|
-
|
|
401
|
-
let useTranslation = null;
|
|
398
|
+
let useTranslation$2 = null;
|
|
402
399
|
try {
|
|
403
400
|
const reactI18next = require('react-i18next');
|
|
404
|
-
useTranslation = reactI18next.useTranslation;
|
|
401
|
+
useTranslation$2 = reactI18next.useTranslation;
|
|
405
402
|
}
|
|
406
403
|
catch (e) {
|
|
407
404
|
}
|
|
408
|
-
const DEFAULT_LANGUAGES = [
|
|
409
|
-
{ code: 'ko', label: '
|
|
410
|
-
{ code: 'en', label: '
|
|
405
|
+
const DEFAULT_LANGUAGES$1 = [
|
|
406
|
+
{ code: 'ko', label: '한국어' },
|
|
407
|
+
{ code: 'en', label: 'English' },
|
|
408
|
+
{ code: 'ja', label: '日本語' },
|
|
411
409
|
];
|
|
412
|
-
const
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
410
|
+
const defaultT$2 = (key) => {
|
|
411
|
+
const translations = {
|
|
412
|
+
languageSettings: '언어 설정',
|
|
413
|
+
languageSettingsDescription: '플러그인에 표시할 언어를 선택하세요.',
|
|
414
|
+
'language.korean': '한국어',
|
|
415
|
+
'language.english': 'English',
|
|
416
|
+
'language.japanese': '日本語',
|
|
417
|
+
};
|
|
418
|
+
return translations[key] || key;
|
|
419
|
+
};
|
|
420
|
+
const LanguageSettingsModal = ({ isOpen, onClose, languages = DEFAULT_LANGUAGES$1, currentLanguage, onLanguageChange, title, description, className, t = defaultT$2, }) => {
|
|
421
|
+
const i18n = useTranslation$2 ? useTranslation$2().i18n : null;
|
|
422
|
+
const activeLanguage = currentLanguage || i18n?.language || languages[0]?.code;
|
|
423
|
+
const translate = (key, fallback) => {
|
|
424
|
+
const translated = t(key);
|
|
425
|
+
return translated && translated !== key ? translated : fallback;
|
|
426
|
+
};
|
|
427
|
+
const handleSelect = (languageCode) => {
|
|
416
428
|
if (i18n) {
|
|
417
429
|
i18n.changeLanguage(languageCode);
|
|
418
430
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
431
|
+
onLanguageChange?.(languageCode);
|
|
432
|
+
onClose();
|
|
422
433
|
};
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
}, size: size, className: "designbase-figma-language-selector__segment" })));
|
|
434
|
+
return (React.createElement(Modal, { isOpen: isOpen, onClose: onClose, title: title || translate('languageSettings', '언어 설정'), size: "s", className: clsx('designbase-figma-language-settings-modal', className) },
|
|
435
|
+
React.createElement("div", { className: "designbase-figma-language-settings-modal__content" },
|
|
436
|
+
React.createElement("p", { className: "designbase-figma-language-settings-modal__description" }, description || translate('languageSettingsDescription', '플러그인에 표시할 언어를 선택하세요.')),
|
|
437
|
+
React.createElement("ul", { className: "designbase-figma-language-settings-modal__list", role: "listbox", "aria-label": translate('languageSettings', '언어 설정') }, languages.map((language) => {
|
|
438
|
+
const label = resolveText(t, language.label, language.code.toUpperCase());
|
|
439
|
+
const isActive = language.code === activeLanguage;
|
|
440
|
+
return (React.createElement("li", { key: language.code, role: "presentation" },
|
|
441
|
+
React.createElement("button", { type: "button", className: clsx('designbase-figma-language-settings-modal__option', { 'designbase-figma-language-settings-modal__option--active': isActive }), role: "option", "aria-selected": isActive, onClick: () => handleSelect(language.code) },
|
|
442
|
+
React.createElement("span", { className: "designbase-figma-language-settings-modal__option-label" }, label),
|
|
443
|
+
React.createElement("span", { className: "designbase-figma-language-settings-modal__option-indicator", "aria-hidden": "true" }))));
|
|
444
|
+
})))));
|
|
435
445
|
};
|
|
436
|
-
|
|
446
|
+
LanguageSettingsModal.displayName = 'LanguageSettingsModal';
|
|
437
447
|
|
|
448
|
+
let useTranslation$1 = null;
|
|
449
|
+
try {
|
|
450
|
+
const reactI18next = require('react-i18next');
|
|
451
|
+
useTranslation$1 = reactI18next.useTranslation;
|
|
452
|
+
}
|
|
453
|
+
catch (e) {
|
|
454
|
+
}
|
|
438
455
|
const defaultLinks = [
|
|
439
456
|
{
|
|
440
457
|
name: 'officialWebsite',
|
|
@@ -468,50 +485,219 @@ const defaultTranslations$1 = {
|
|
|
468
485
|
instagram: '인스타그램',
|
|
469
486
|
figmaCommunity: '피그마 커뮤니티',
|
|
470
487
|
contact: '문의하기',
|
|
488
|
+
languageSettings: '언어 설정',
|
|
471
489
|
};
|
|
472
490
|
const defaultT$1 = (key) => defaultTranslations$1[key] || key;
|
|
473
|
-
const
|
|
491
|
+
const defaultLanguages = [
|
|
492
|
+
{ code: 'ko', label: '한국어' },
|
|
493
|
+
{ code: 'en', label: 'English' },
|
|
494
|
+
{ code: 'ja', label: '日本語' },
|
|
495
|
+
];
|
|
496
|
+
const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase', logoSize = 'xs', links = defaultLinks, position = 'top-left', className, t = defaultT$1, showLanguageSelector = true, languages = defaultLanguages, currentLanguage, onLanguageChange, }) => {
|
|
474
497
|
const [isOpen, setIsOpen] = useState(false);
|
|
475
|
-
const
|
|
498
|
+
const [isLanguageModalOpen, setIsLanguageModalOpen] = useState(false);
|
|
499
|
+
const i18n = useTranslation$1 ? useTranslation$1().i18n : null;
|
|
500
|
+
const rootRef = useRef(null);
|
|
501
|
+
const triggerRef = useRef(null);
|
|
502
|
+
const menuId = `designbase-figma-logo-menu-${useId().replace(/:/g, '')}`;
|
|
503
|
+
const activeLanguage = currentLanguage || i18n?.language || languages[0]?.code;
|
|
504
|
+
const translate = (key, fallback) => {
|
|
505
|
+
const translated = t(key);
|
|
506
|
+
return translated && translated !== key ? translated : fallback;
|
|
507
|
+
};
|
|
508
|
+
useEffect(() => {
|
|
509
|
+
if (!isOpen) {
|
|
510
|
+
return undefined;
|
|
511
|
+
}
|
|
512
|
+
const handlePointerDown = (event) => {
|
|
513
|
+
if (!rootRef.current?.contains(event.target)) {
|
|
514
|
+
setIsOpen(false);
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
const handleKeyDown = (event) => {
|
|
518
|
+
if (event.key === 'Escape') {
|
|
519
|
+
setIsOpen(false);
|
|
520
|
+
triggerRef.current?.focus();
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
document.addEventListener('mousedown', handlePointerDown);
|
|
524
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
525
|
+
return () => {
|
|
526
|
+
document.removeEventListener('mousedown', handlePointerDown);
|
|
527
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
528
|
+
};
|
|
529
|
+
}, [isOpen]);
|
|
530
|
+
const toggleDropdown = () => setIsOpen((value) => !value);
|
|
476
531
|
const handleLinkClick = (url) => {
|
|
532
|
+
setIsOpen(false);
|
|
477
533
|
if (url.startsWith('mailto:')) {
|
|
478
534
|
return;
|
|
479
535
|
}
|
|
480
536
|
window.open(url, '_blank', 'noopener,noreferrer');
|
|
481
537
|
};
|
|
538
|
+
const handleLanguageSettingsClick = () => {
|
|
539
|
+
setIsOpen(false);
|
|
540
|
+
setIsLanguageModalOpen(true);
|
|
541
|
+
};
|
|
542
|
+
const handleLanguageChange = (languageCode) => {
|
|
543
|
+
if (i18n) {
|
|
544
|
+
i18n.changeLanguage(languageCode);
|
|
545
|
+
}
|
|
546
|
+
onLanguageChange?.(languageCode);
|
|
547
|
+
};
|
|
482
548
|
const classes = clsx('designbase-figma-logo-dropdown', `designbase-figma-logo-dropdown--${position}`, {
|
|
483
549
|
'designbase-figma-logo-dropdown--open': isOpen,
|
|
484
550
|
}, className);
|
|
485
551
|
const renderLogo = () => {
|
|
486
|
-
|
|
487
|
-
return (React.createElement("img", { className: "designbase-figma-logo-dropdown__logo", src: logoSrc, alt: logoAlt, onClick: toggleDropdown }));
|
|
488
|
-
}
|
|
489
|
-
return (React.createElement("div", { className: "designbase-figma-logo-dropdown__logo", onClick: toggleDropdown },
|
|
490
|
-
React.createElement(Logo, { type: logoType, size: logoSize, variant: "default" })));
|
|
552
|
+
return (React.createElement("button", { ref: triggerRef, type: "button", className: "designbase-figma-logo-dropdown__logo", "aria-label": logoAlt, "aria-expanded": isOpen, "aria-controls": menuId, "aria-haspopup": "menu", onClick: toggleDropdown }, logoSrc ? (React.createElement("img", { src: logoSrc, alt: "" })) : (React.createElement(Logo, { type: logoType, size: logoSize, variant: "default" }))));
|
|
491
553
|
};
|
|
492
|
-
return (React.createElement("div", { className: classes },
|
|
554
|
+
return (React.createElement("div", { ref: rootRef, className: classes },
|
|
493
555
|
renderLogo(),
|
|
494
|
-
isOpen && (React.createElement("ul", { className: "designbase-figma-logo-dropdown__menu"
|
|
495
|
-
React.createElement("
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
556
|
+
isOpen && (React.createElement("ul", { id: menuId, className: "designbase-figma-logo-dropdown__menu", role: "menu" },
|
|
557
|
+
links.map((link, index) => (React.createElement("li", { key: index, className: "designbase-figma-logo-dropdown__item", role: "none" },
|
|
558
|
+
React.createElement("button", { type: "button", className: "designbase-figma-logo-dropdown__link", role: "menuitem", onClick: () => handleLinkClick(link.url) },
|
|
559
|
+
link.icon && (React.createElement("span", { className: "designbase-figma-logo-dropdown__icon" }, link.icon)),
|
|
560
|
+
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" }, t(link.name)),
|
|
561
|
+
React.createElement(ExternalLinkIcon, { size: 16, className: "designbase-figma-logo-dropdown__arrow" }))))),
|
|
562
|
+
showLanguageSelector && (React.createElement("li", { className: "designbase-figma-logo-dropdown__item designbase-figma-logo-dropdown__language-item", role: "none" },
|
|
563
|
+
React.createElement("button", { type: "button", className: "designbase-figma-logo-dropdown__link", role: "menuitem", onClick: handleLanguageSettingsClick },
|
|
564
|
+
React.createElement("span", { className: "designbase-figma-logo-dropdown__icon" },
|
|
565
|
+
React.createElement(TranslateIcon, { size: 20, "aria-hidden": "true" })),
|
|
566
|
+
React.createElement("span", { className: "designbase-figma-logo-dropdown__text" }, translate('languageSettings', '언어 설정'))))))),
|
|
567
|
+
showLanguageSelector && (React.createElement(LanguageSettingsModal, { isOpen: isLanguageModalOpen, onClose: () => setIsLanguageModalOpen(false), languages: languages, currentLanguage: activeLanguage, onLanguageChange: handleLanguageChange, t: t }))));
|
|
499
568
|
};
|
|
500
569
|
LogoDropdown.displayName = 'LogoDropdown';
|
|
501
570
|
|
|
571
|
+
const fallbackText = (t, key, fallback) => {
|
|
572
|
+
const translated = t?.(key);
|
|
573
|
+
return translated && translated !== key ? translated : fallback;
|
|
574
|
+
};
|
|
575
|
+
const UsageStatusPopover = ({ paymentStatus, usageCount = 0, maxDailyUsage = 20, showUsage = true, showPlan = true, isLoading = false, onLicensePageClick, t, className, }) => {
|
|
576
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
577
|
+
const rootRef = useRef(null);
|
|
578
|
+
const triggerRef = useRef(null);
|
|
579
|
+
const popoverId = `designbase-figma-usage-popover-${useId().replace(/:/g, '')}`;
|
|
580
|
+
const isPaid = paymentStatus === 'PAID';
|
|
581
|
+
const isBeta = paymentStatus === 'BETA';
|
|
582
|
+
const hasDailyLimit = !isPaid && maxDailyUsage > 0;
|
|
583
|
+
const limit = Math.max(1, Math.round(maxDailyUsage));
|
|
584
|
+
const used = Math.min(limit, Math.max(0, Math.round(usageCount)));
|
|
585
|
+
const remaining = Math.max(0, limit - used);
|
|
586
|
+
const usedPercent = hasDailyLimit ? Math.round((used / limit) * 100) : 0;
|
|
587
|
+
const hasControl = showUsage || showPlan;
|
|
588
|
+
const planLabel = isPaid
|
|
589
|
+
? fallbackText(t, 'proUser', '프로')
|
|
590
|
+
: isBeta
|
|
591
|
+
? fallbackText(t, 'betaStatus', 'BETA')
|
|
592
|
+
: paymentStatus === 'TRIAL'
|
|
593
|
+
? fallbackText(t, 'trialPlan', '체험판')
|
|
594
|
+
: fallbackText(t, 'free', '무료');
|
|
595
|
+
const planTitle = isBeta
|
|
596
|
+
? planLabel
|
|
597
|
+
: `${planLabel} ${fallbackText(t, 'planSuffix', '플랜')}`;
|
|
598
|
+
const triggerLabel = isPaid
|
|
599
|
+
? `${planLabel}, ${fallbackText(t, 'unlimitedUsage', '무제한 사용 가능')}`
|
|
600
|
+
: isBeta
|
|
601
|
+
? planLabel
|
|
602
|
+
: hasDailyLimit
|
|
603
|
+
? `${remaining}/${limit} ${fallbackText(t, 'remainingShort', '남음')}`
|
|
604
|
+
: planLabel;
|
|
605
|
+
const upgradeLabel = isPaid
|
|
606
|
+
? fallbackText(t, 'managePlan', '플랜 관리')
|
|
607
|
+
: fallbackText(t, 'upgradePlan', '플랜 업그레이드');
|
|
608
|
+
useEffect(() => {
|
|
609
|
+
if (!isOpen)
|
|
610
|
+
return undefined;
|
|
611
|
+
const handlePointerDown = (event) => {
|
|
612
|
+
if (!rootRef.current?.contains(event.target)) {
|
|
613
|
+
setIsOpen(false);
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
const handleKeyDown = (event) => {
|
|
617
|
+
if (event.key === 'Escape') {
|
|
618
|
+
setIsOpen(false);
|
|
619
|
+
triggerRef.current?.focus();
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
document.addEventListener('mousedown', handlePointerDown);
|
|
623
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
624
|
+
return () => {
|
|
625
|
+
document.removeEventListener('mousedown', handlePointerDown);
|
|
626
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
627
|
+
};
|
|
628
|
+
}, [isOpen]);
|
|
629
|
+
if (!hasControl)
|
|
630
|
+
return null;
|
|
631
|
+
const handleManageClick = () => {
|
|
632
|
+
setIsOpen(false);
|
|
633
|
+
onLicensePageClick?.();
|
|
634
|
+
};
|
|
635
|
+
const togglePopover = () => setIsOpen((value) => !value);
|
|
636
|
+
return (React.createElement("div", { ref: rootRef, className: clsx('designbase-figma-usage-status', {
|
|
637
|
+
'designbase-figma-usage-status--open': isOpen,
|
|
638
|
+
'designbase-figma-usage-status--unlimited': isPaid,
|
|
639
|
+
'designbase-figma-usage-status--loading': isLoading,
|
|
640
|
+
}, className) },
|
|
641
|
+
React.createElement("div", { className: "designbase-figma-usage-status__control" },
|
|
642
|
+
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(t, '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,
|
|
643
|
+
React.createElement("span", { className: "designbase-figma-usage-status__mini-progress", "aria-hidden": "true" },
|
|
644
|
+
React.createElement("span", { style: { width: `${usedPercent}%` } })),
|
|
645
|
+
React.createElement("span", { className: "designbase-figma-usage-status__usage-value" },
|
|
646
|
+
React.createElement("strong", null, remaining),
|
|
647
|
+
React.createElement("span", null,
|
|
648
|
+
"/",
|
|
649
|
+
limit)))) : (React.createElement("span", { className: "designbase-figma-usage-status__plan-label" }, planLabel)))),
|
|
650
|
+
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))),
|
|
651
|
+
isOpen && (React.createElement("div", { id: popoverId, className: "designbase-figma-usage-status__popover", role: "dialog", "aria-label": fallbackText(t, 'usageDetails', '사용량 상세') },
|
|
652
|
+
React.createElement("div", { className: "designbase-figma-usage-status__popover-header" },
|
|
653
|
+
React.createElement("span", { className: "designbase-figma-usage-status__plan-title" }, planTitle),
|
|
654
|
+
!isBeta && (React.createElement(Button, { className: "designbase-figma-usage-status__upgrade", variant: isPaid ? 'secondary' : 'primary', size: "s", endIcon: "chevron-right", onPress: handleManageClick }, upgradeLabel))),
|
|
655
|
+
isPaid ? (React.createElement("div", { className: "designbase-figma-usage-status__unlimited-copy" },
|
|
656
|
+
React.createElement("span", { className: "designbase-figma-usage-status__unlimited-mark", "aria-hidden": "true" }, "\u221E"),
|
|
657
|
+
React.createElement("span", null, fallbackText(t, 'unlimitedUsageTooltip', '모든 기능을 제한 없이 사용할 수 있습니다')))) : isBeta ? (React.createElement("p", { className: "designbase-figma-usage-status__note" }, fallbackText(t, 'betaUsageDescription', '베타 기간에는 사용량 제한이 적용되지 않습니다'))) : hasDailyLimit ? (React.createElement("div", { className: "designbase-figma-usage-status__usage-detail" },
|
|
658
|
+
React.createElement("div", { className: "designbase-figma-usage-status__usage-summary" },
|
|
659
|
+
React.createElement("strong", { className: "designbase-figma-usage-status__usage-count" },
|
|
660
|
+
used,
|
|
661
|
+
React.createElement("span", { className: "designbase-figma-usage-status__usage-divider" }, "/"),
|
|
662
|
+
limit),
|
|
663
|
+
React.createElement("span", { className: "designbase-figma-usage-status__usage-caption" }, fallbackText(t, 'usageCountCaption', '오늘 사용'))),
|
|
664
|
+
React.createElement("div", { className: "designbase-figma-usage-status__progress", role: "progressbar", "aria-label": fallbackText(t, 'usageCountCaption', '오늘 사용'), "aria-valuemin": 0, "aria-valuemax": limit, "aria-valuenow": used, "aria-valuetext": `${used} / ${limit}` },
|
|
665
|
+
React.createElement("span", { style: { width: `${usedPercent}%` } })),
|
|
666
|
+
React.createElement("p", { className: "designbase-figma-usage-status__remaining-copy" }, resolveText(t, { key: 'remainingCopy', values: { count: remaining } }, `${remaining}회 남음 · 매일 리셋`)))) : (React.createElement("p", { className: "designbase-figma-usage-status__note" }, fallbackText(t, 'usageUnavailable', '사용량 제한이 없습니다')))))));
|
|
667
|
+
};
|
|
668
|
+
UsageStatusPopover.displayName = 'UsageStatusPopover';
|
|
669
|
+
|
|
502
670
|
const defaultTranslations = {
|
|
503
671
|
unlimitedUsage: '무제한 사용',
|
|
672
|
+
proUser: '프로',
|
|
673
|
+
free: '무료',
|
|
674
|
+
trialPlan: '체험판',
|
|
675
|
+
planSuffix: '플랜',
|
|
676
|
+
usageDetails: '사용량 상세',
|
|
677
|
+
dailyUsage: '오늘 사용량',
|
|
678
|
+
usedToday: '오늘 사용',
|
|
679
|
+
remainingToday: '오늘 남은 사용량',
|
|
680
|
+
remainingUsage: '오늘 남은 사용량',
|
|
681
|
+
managePlan: '플랜 관리',
|
|
682
|
+
upgradePlan: '플랜 업그레이드',
|
|
683
|
+
remainingShort: '남음',
|
|
684
|
+
usageCountCaption: '오늘 사용',
|
|
685
|
+
remainingCopy: '{{count}}회 남음 · 매일 리셋',
|
|
686
|
+
usageUnavailable: '사용량 제한이 없습니다',
|
|
687
|
+
betaUsageDescription: '베타 기간에는 사용량 제한이 적용되지 않습니다',
|
|
504
688
|
perDay: '일',
|
|
505
689
|
resetsDaily: '매일 리셋',
|
|
506
690
|
donationPrompt: '이 플러그인이 유용했나요?',
|
|
507
691
|
betaStatus: 'BETA',
|
|
508
692
|
};
|
|
509
|
-
const defaultT = (key) =>
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
693
|
+
const defaultT = (key, values) => {
|
|
694
|
+
const template = defaultTranslations[key] || key;
|
|
695
|
+
return interpolateText(template, values);
|
|
696
|
+
};
|
|
697
|
+
const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount = 0, isLoading = false, showPaymentStatus = true, showUsageInfo = true, maxDailyUsage = 20, showPaymentBadge = true, showDonation = true, donationUrl = 'https://buymeacoffee.com/designbase', donationText = 'Buy me a coffee', showDonationText = true, donationPromptText, showLanguageSelector = true, currentLanguage = 'ko', languages, onLanguageChange, logoSrc, logoAlt = 'DesignBase', logoType = 'designbase', logoSize = 'xs', logoLinks, className, t = defaultT, children, }) => {
|
|
698
|
+
const resolvedShowUsageInfo = showPaymentStatus && showUsageInfo;
|
|
514
699
|
const resolvedShowPaymentBadge = showPaymentStatus && showPaymentBadge;
|
|
700
|
+
const resolvedLicensePageClick = paymentStatus === 'BETA' ? undefined : onLicensePageClick;
|
|
515
701
|
const hasChildren = React.Children.count(children) > 0;
|
|
516
702
|
const classes = clsx('designbase-figma-footer', {
|
|
517
703
|
'designbase-figma-footer--has-children': hasChildren,
|
|
@@ -519,17 +705,9 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
519
705
|
return (React.createElement("footer", { className: classes },
|
|
520
706
|
React.createElement("div", { className: "designbase-figma-footer__wrap" },
|
|
521
707
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
522
|
-
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, t: t }),
|
|
523
|
-
showLanguageSelector && (React.createElement(LanguageSelector, { currentLanguage: currentLanguage, languages: languages, onLanguageChange: onLanguageChange, size: "s" }))),
|
|
708
|
+
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, languages: languages, currentLanguage: currentLanguage, showLanguageSelector: showLanguageSelector, onLanguageChange: onLanguageChange, t: t })),
|
|
524
709
|
React.createElement("div", { className: "designbase-figma-footer__right" },
|
|
525
|
-
|
|
526
|
-
React.createElement("span", { className: "designbase-figma-footer__usage-count" }, usageCount),
|
|
527
|
-
React.createElement("span", { className: "designbase-figma-footer__max-daily-usage" },
|
|
528
|
-
"/",
|
|
529
|
-
maxDailyUsage,
|
|
530
|
-
" ",
|
|
531
|
-
t('perDay')))))),
|
|
532
|
-
showPaymentStatus && resolvedShowPaymentBadge && (React.createElement(PaymentBadge, { isActive: isActive, onClick: isBeta ? undefined : onLicensePageClick, isLoading: isLoading, text: isBeta ? (t('betaStatus') || 'BETA') : undefined, t: t })),
|
|
710
|
+
(resolvedShowUsageInfo || resolvedShowPaymentBadge) && (React.createElement(UsageStatusPopover, { paymentStatus: paymentStatus, usageCount: usageCount, maxDailyUsage: maxDailyUsage, showUsage: resolvedShowUsageInfo, showPlan: resolvedShowPaymentBadge, isLoading: isLoading, onLicensePageClick: resolvedLicensePageClick, t: t })),
|
|
533
711
|
showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t: t })))),
|
|
534
712
|
children));
|
|
535
713
|
};
|
|
@@ -653,6 +831,205 @@ const InteractionFeedback = ({ status = 'default', message, statusMessage, leftC
|
|
|
653
831
|
};
|
|
654
832
|
InteractionFeedback.displayName = 'InteractionFeedback';
|
|
655
833
|
|
|
834
|
+
let useTranslation = null;
|
|
835
|
+
try {
|
|
836
|
+
const reactI18next = require('react-i18next');
|
|
837
|
+
useTranslation = reactI18next.useTranslation;
|
|
838
|
+
}
|
|
839
|
+
catch (e) {
|
|
840
|
+
}
|
|
841
|
+
const DEFAULT_LANGUAGES = [
|
|
842
|
+
{ code: 'ko', label: 'KO' },
|
|
843
|
+
{ code: 'en', label: 'EN' },
|
|
844
|
+
];
|
|
845
|
+
const LanguageSelector = ({ currentLanguage, languages = DEFAULT_LANGUAGES, onLanguageChange, size = 's', className, t }) => {
|
|
846
|
+
const i18n = useTranslation ? useTranslation().i18n : null;
|
|
847
|
+
const activeLanguage = currentLanguage || (i18n?.language) || 'ko';
|
|
848
|
+
const handleLanguageChange = (languageCode) => {
|
|
849
|
+
if (i18n) {
|
|
850
|
+
i18n.changeLanguage(languageCode);
|
|
851
|
+
}
|
|
852
|
+
if (onLanguageChange) {
|
|
853
|
+
onLanguageChange(languageCode);
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
const segmentOptions = languages.map((language) => ({
|
|
857
|
+
value: language.code,
|
|
858
|
+
label: resolveText(t, language.label),
|
|
859
|
+
disabled: false,
|
|
860
|
+
}));
|
|
861
|
+
return (React.createElement("div", { className: `designbase-figma-language-selector ${className || ''}` },
|
|
862
|
+
React.createElement(SegmentControl, { options: segmentOptions, value: activeLanguage, onChange: (event) => {
|
|
863
|
+
const detail = event.detail;
|
|
864
|
+
const value = typeof detail === 'object' && detail !== null && 'value' in detail &&
|
|
865
|
+
typeof detail.value === 'string'
|
|
866
|
+
? detail.value
|
|
867
|
+
: undefined;
|
|
868
|
+
if (value) {
|
|
869
|
+
handleLanguageChange(value);
|
|
870
|
+
}
|
|
871
|
+
}, size: size, className: "designbase-figma-language-selector__segment" })));
|
|
872
|
+
};
|
|
873
|
+
LanguageSelector.displayName = 'LanguageSelector';
|
|
874
|
+
|
|
875
|
+
function postPluginMessage(message) {
|
|
876
|
+
if (typeof parent === 'undefined') {
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
parent.postMessage({ pluginMessage: message }, '*');
|
|
880
|
+
}
|
|
881
|
+
function openExternalUrl(url) {
|
|
882
|
+
if (!url)
|
|
883
|
+
return;
|
|
884
|
+
postPluginMessage({ type: 'open-external-url', url });
|
|
885
|
+
if (typeof window !== 'undefined') {
|
|
886
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
const LicenseOffer = ({ joinUrl, guideUrl, membershipUrl, t, className, }) => {
|
|
891
|
+
const titleId = `designbase-license-offer-title-${useId().replace(/:/g, '')}`;
|
|
892
|
+
const resolvedJoinUrl = joinUrl || membershipUrl;
|
|
893
|
+
const steps = [
|
|
894
|
+
resolveText(t, { key: 'license.youtube_membership_step_1' }, 'Designbase YouTube 채널 멤버십에 가입합니다.'),
|
|
895
|
+
resolveText(t, { key: 'license.youtube_membership_step_2' }, '멤버 전용 커뮤니티에서 이번 달 키를 복사합니다.'),
|
|
896
|
+
resolveText(t, { key: 'license.youtube_membership_step_3' }, '아래 입력창에 키를 붙여 넣고 활성화합니다.'),
|
|
897
|
+
];
|
|
898
|
+
return (React.createElement("section", { className: `designbase-figma-license-offer ${className || ''}`, "aria-labelledby": titleId },
|
|
899
|
+
React.createElement("h3", { id: titleId, className: "designbase-figma-license-offer__title" }, resolveText(t, { key: 'license.youtube_membership_howto' }, '이용 방법')),
|
|
900
|
+
React.createElement("ol", { className: "designbase-figma-license-offer__steps" }, steps.map((step, index) => (React.createElement("li", { key: index },
|
|
901
|
+
React.createElement("span", { className: "designbase-figma-license-offer__step-index", "aria-hidden": "true" },
|
|
902
|
+
index + 1,
|
|
903
|
+
"."),
|
|
904
|
+
React.createElement("span", null, step))))),
|
|
905
|
+
(resolvedJoinUrl || guideUrl) && (React.createElement("div", { className: "designbase-figma-license-offer__actions" },
|
|
906
|
+
resolvedJoinUrl && (React.createElement(Button, { onPress: () => openExternalUrl(resolvedJoinUrl), variant: "primary", size: "m", fullWidth: true }, resolveText(t, { key: 'license.youtube_membership_join' }, '멤버십 가입'))),
|
|
907
|
+
guideUrl && (React.createElement(Button, { onPress: () => openExternalUrl(guideUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
908
|
+
React.createElement("span", null, resolveText(t, { key: 'license.youtube_membership_guide' }, '안내보기')),
|
|
909
|
+
React.createElement(ExternalLinkIcon, { size: 16, "aria-hidden": "true" })))))));
|
|
910
|
+
};
|
|
911
|
+
LicenseOffer.displayName = 'LicenseOffer';
|
|
912
|
+
|
|
913
|
+
function maskLicenseKey(value) {
|
|
914
|
+
if (value.length <= 8)
|
|
915
|
+
return '••••••••';
|
|
916
|
+
return `${value.slice(0, 4)}••••${value.slice(-4)}`;
|
|
917
|
+
}
|
|
918
|
+
function formatDate(value) {
|
|
919
|
+
if (!value)
|
|
920
|
+
return undefined;
|
|
921
|
+
const date = new Date(value);
|
|
922
|
+
if (Number.isNaN(date.getTime()))
|
|
923
|
+
return value;
|
|
924
|
+
return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium' }).format(date);
|
|
925
|
+
}
|
|
926
|
+
function formatScope(value, t) {
|
|
927
|
+
if (!value)
|
|
928
|
+
return undefined;
|
|
929
|
+
if (value === 'all-products' || value === 'all_products') {
|
|
930
|
+
return resolveText(t, { key: 'license.all_plugins' }, '모든 플러그인');
|
|
931
|
+
}
|
|
932
|
+
return value;
|
|
933
|
+
}
|
|
934
|
+
function formatSource(value, t) {
|
|
935
|
+
if (!value)
|
|
936
|
+
return undefined;
|
|
937
|
+
if (value === 'youtube_membership' || value === 'membership') {
|
|
938
|
+
return resolveText(t, { key: 'license.source_youtube_membership' }, 'YouTube 멤버십');
|
|
939
|
+
}
|
|
940
|
+
if (value === 'lemonsqueezy') {
|
|
941
|
+
return resolveText(t, { key: 'license.source_purchase' }, '구매 라이선스');
|
|
942
|
+
}
|
|
943
|
+
return value;
|
|
944
|
+
}
|
|
945
|
+
const LicenseStatusCard = ({ status, licenseKey = '', licenseStatus, licenseSource, accessScope, expiresAt, lastVerifiedAt, validationMessage, allowRevealKey = false, t, className, }) => {
|
|
946
|
+
const [isKeyRevealed, setIsKeyRevealed] = useState(false);
|
|
947
|
+
const normalizedLicenseStatus = licenseStatus?.toLowerCase();
|
|
948
|
+
const isInactiveStatus = ['expired', 'revoked', 'invalid', 'inactive'].includes(normalizedLicenseStatus || '');
|
|
949
|
+
const isActive = status === 'PAID' && !isInactiveStatus;
|
|
950
|
+
const statusText = isActive
|
|
951
|
+
? resolveText(t, { key: 'license.status_active' }, 'Active')
|
|
952
|
+
: resolveText(t, { key: 'license.status_inactive' }, 'License check failed');
|
|
953
|
+
const statusClass = isActive ? 'active' : 'inactive';
|
|
954
|
+
return (React.createElement("section", { className: `designbase-figma-license-status-card designbase-figma-license-status-card--${statusClass} ${className || ''}`, "aria-label": statusText },
|
|
955
|
+
React.createElement("div", { className: "designbase-figma-license-status-card__header" },
|
|
956
|
+
React.createElement("div", null,
|
|
957
|
+
React.createElement("div", { className: "designbase-figma-license-status-card__eyebrow" }, isActive
|
|
958
|
+
? resolveText(t, { key: 'license.activated' }, '라이선스 활성화됨')
|
|
959
|
+
: resolveText(t, { key: 'license.status_label' }, '라이선스 상태')),
|
|
960
|
+
React.createElement("h3", null, statusText)),
|
|
961
|
+
React.createElement("span", { className: "designbase-figma-license-status-card__badge" }, licenseStatus || (isActive ? 'active' : 'inactive'))),
|
|
962
|
+
validationMessage && !isActive && (React.createElement("p", { className: "designbase-figma-license-status-card__message" }, validationMessage)),
|
|
963
|
+
licenseKey && (React.createElement("div", { className: "designbase-figma-license-status-card__key-row" },
|
|
964
|
+
React.createElement("span", null, resolveText(t, { key: 'license.key_label' }, '라이선스 키')),
|
|
965
|
+
React.createElement("code", null, allowRevealKey && isKeyRevealed ? licenseKey : maskLicenseKey(licenseKey)),
|
|
966
|
+
allowRevealKey && (React.createElement(Button, { type: "button", onPress: () => setIsKeyRevealed((value) => !value), variant: "tertiary", size: "s" }, isKeyRevealed
|
|
967
|
+
? resolveText(t, { key: 'license.hide_key' }, '숨기기')
|
|
968
|
+
: resolveText(t, { key: 'license.reveal_key' }, '보기'))))),
|
|
969
|
+
(licenseSource || accessScope || expiresAt || lastVerifiedAt) && (React.createElement("dl", { className: "designbase-figma-license-status-card__meta" },
|
|
970
|
+
formatSource(licenseSource, t) && React.createElement(React.Fragment, null,
|
|
971
|
+
React.createElement("dt", null, resolveText(t, { key: 'license.source' }, '출처')),
|
|
972
|
+
React.createElement("dd", null, formatSource(licenseSource, t))),
|
|
973
|
+
formatScope(accessScope, t) && React.createElement(React.Fragment, null,
|
|
974
|
+
React.createElement("dt", null, resolveText(t, { key: 'license.access' }, '접근 범위')),
|
|
975
|
+
React.createElement("dd", null, formatScope(accessScope, t))),
|
|
976
|
+
expiresAt && React.createElement(React.Fragment, null,
|
|
977
|
+
React.createElement("dt", null, resolveText(t, { key: 'license.expires' }, '만료일')),
|
|
978
|
+
React.createElement("dd", null, formatDate(expiresAt) || expiresAt)),
|
|
979
|
+
lastVerifiedAt && React.createElement(React.Fragment, null,
|
|
980
|
+
React.createElement("dt", null, resolveText(t, { key: 'license.last_checked' }, '최근 확인')),
|
|
981
|
+
React.createElement("dd", null, formatDate(lastVerifiedAt) || lastVerifiedAt))))));
|
|
982
|
+
};
|
|
983
|
+
LicenseStatusCard.displayName = 'LicenseStatusCard';
|
|
984
|
+
|
|
985
|
+
function resolvePaymentFeedbackVariant(errorCode, explicitVariant) {
|
|
986
|
+
if (explicitVariant)
|
|
987
|
+
return explicitVariant;
|
|
988
|
+
if (!errorCode)
|
|
989
|
+
return 'success';
|
|
990
|
+
const normalized = errorCode.toLowerCase();
|
|
991
|
+
if (normalized.includes('network')
|
|
992
|
+
|| normalized.includes('server')
|
|
993
|
+
|| normalized.includes('rate')
|
|
994
|
+
|| normalized.includes('timeout')) {
|
|
995
|
+
return 'warning';
|
|
996
|
+
}
|
|
997
|
+
if (normalized.includes('info')) {
|
|
998
|
+
return 'info';
|
|
999
|
+
}
|
|
1000
|
+
return 'error';
|
|
1001
|
+
}
|
|
1002
|
+
const PaymentStatusSection = ({ activationLimit, activationUsage, licenseKey, onDeactivate, isDeactivating = false, showDetails = false, actionMessage, actionMessageVariant, errorCode, className, t, }) => {
|
|
1003
|
+
const remainingActivations = Math.max(0, activationLimit - activationUsage);
|
|
1004
|
+
const resolvedActionMessage = actionMessage ? resolveText(t, actionMessage) : undefined;
|
|
1005
|
+
const feedbackVariant = resolvedActionMessage
|
|
1006
|
+
? resolvePaymentFeedbackVariant(errorCode, actionMessageVariant)
|
|
1007
|
+
: undefined;
|
|
1008
|
+
return (React.createElement("div", { className: clsx('designbase-figma-payment-status', className) },
|
|
1009
|
+
React.createElement("div", { className: "designbase-figma-payment-status__license-key" },
|
|
1010
|
+
resolveText(t, { key: 'payment.license_key_label' }, '라이선스 키'),
|
|
1011
|
+
": ",
|
|
1012
|
+
React.createElement("span", null, licenseKey)),
|
|
1013
|
+
showDetails && (React.createElement("div", { className: "designbase-figma-payment-status__details" },
|
|
1014
|
+
React.createElement("div", { className: "designbase-figma-payment-status__activation-info" },
|
|
1015
|
+
React.createElement("div", { className: "designbase-figma-payment-status__remaining" },
|
|
1016
|
+
remainingActivations,
|
|
1017
|
+
' ',
|
|
1018
|
+
resolveText(t, { key: 'payment.activations_remaining' }, '활성'),
|
|
1019
|
+
' ',
|
|
1020
|
+
resolveText(t, { key: 'payment.spots_remaining' }, '자리 남음')),
|
|
1021
|
+
React.createElement("div", { className: "designbase-figma-payment-status__usage" },
|
|
1022
|
+
activationUsage,
|
|
1023
|
+
"/",
|
|
1024
|
+
activationLimit)),
|
|
1025
|
+
React.createElement("div", { className: "designbase-figma-payment-status__action" },
|
|
1026
|
+
React.createElement(Button, { onPress: onDeactivate, variant: "secondary", size: "s", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
1027
|
+
? resolveText(t, { key: 'payment.deactivating' }, '비활성화중...')
|
|
1028
|
+
: resolveText(t, { key: 'payment.deactivate_license' }, '라이선스 비활성화')),
|
|
1029
|
+
resolvedActionMessage && feedbackVariant && (React.createElement("p", { className: clsx('designbase-figma-payment-status__feedback', `designbase-figma-payment-status__feedback--${feedbackVariant}`), role: feedbackVariant === 'error' ? 'alert' : 'status', "aria-live": "polite" }, resolvedActionMessage)))))));
|
|
1030
|
+
};
|
|
1031
|
+
PaymentStatusSection.displayName = 'PaymentStatusSection';
|
|
1032
|
+
|
|
656
1033
|
const defaultFeatures = [
|
|
657
1034
|
{ name: '사용 제한', free: '일일 제한', pro: '무제한' },
|
|
658
1035
|
{ name: '모든 주제 사용', free: false, pro: true },
|
|
@@ -686,7 +1063,11 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
686
1063
|
return (React.createElement("div", { className: `designbase-figma-pricing-comparison ${className || ''}` },
|
|
687
1064
|
paymentType === 'subscription' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__billing-toggle" },
|
|
688
1065
|
React.createElement(SegmentControl, { value: isYearly ? 'yearly' : 'monthly', onChange: (event) => {
|
|
689
|
-
const
|
|
1066
|
+
const detail = event.detail;
|
|
1067
|
+
const value = typeof detail === 'object' && detail !== null && 'value' in detail &&
|
|
1068
|
+
typeof detail.value === 'string'
|
|
1069
|
+
? detail.value
|
|
1070
|
+
: undefined;
|
|
690
1071
|
setIsYearly(value === 'yearly');
|
|
691
1072
|
}, options: [
|
|
692
1073
|
{
|
|
@@ -723,21 +1104,6 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
723
1104
|
};
|
|
724
1105
|
PricingComparison.displayName = 'PricingComparison';
|
|
725
1106
|
|
|
726
|
-
function postPluginMessage(message) {
|
|
727
|
-
if (typeof parent === 'undefined') {
|
|
728
|
-
return;
|
|
729
|
-
}
|
|
730
|
-
parent.postMessage({ pluginMessage: message }, '*');
|
|
731
|
-
}
|
|
732
|
-
function openExternalUrl(url) {
|
|
733
|
-
if (!url)
|
|
734
|
-
return;
|
|
735
|
-
postPluginMessage({ type: 'open-external-url', url });
|
|
736
|
-
if (typeof window !== 'undefined') {
|
|
737
|
-
window.open(url, '_blank', 'noopener,noreferrer');
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
|
|
741
1107
|
const DEFAULT_LICENSE_MESSAGE_TYPES = {
|
|
742
1108
|
initialize: 'initialize',
|
|
743
1109
|
verifyLicense: 'verify-license',
|
|
@@ -810,6 +1176,12 @@ function parseLicenseMessage(data) {
|
|
|
810
1176
|
usageReason: readString(data, ['usageReason']) || undefined,
|
|
811
1177
|
lastMessage: readString(data, ['message']) || undefined,
|
|
812
1178
|
lastErrorCode: readString(data, ['errorCode']) || undefined,
|
|
1179
|
+
licenseStatus: readString(data, ['licenseStatus', 'license_status']) || undefined,
|
|
1180
|
+
licenseSource: readString(data, ['licenseSource', 'license_source', 'source']) || undefined,
|
|
1181
|
+
accessScope: readString(data, ['accessScope', 'access_scope', 'scope']) || undefined,
|
|
1182
|
+
expiresAt: readString(data, ['expiresAt', 'expires_at']) || undefined,
|
|
1183
|
+
lastVerifiedAt: readString(data, ['lastVerifiedAt', 'last_verified_at']) || undefined,
|
|
1184
|
+
validationMessage: readString(data, ['validationMessage', 'validation_message']) || undefined,
|
|
813
1185
|
};
|
|
814
1186
|
}
|
|
815
1187
|
function useFigmaLicenseBridge(options = {}) {
|
|
@@ -852,15 +1224,27 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
852
1224
|
if (type === messageTypes.verifyResult) {
|
|
853
1225
|
setIsVerifying(false);
|
|
854
1226
|
setIsStartingAuth(false);
|
|
855
|
-
applyPatch(
|
|
1227
|
+
applyPatch({
|
|
1228
|
+
...parseLicenseMessage(payload),
|
|
1229
|
+
deactivateMessage: '',
|
|
1230
|
+
deactivateErrorCode: '',
|
|
1231
|
+
});
|
|
856
1232
|
if (payload.success === true) {
|
|
857
1233
|
applyPatch({ paymentStatus: 'PAID', isLicenseRegistered: true });
|
|
858
1234
|
}
|
|
859
1235
|
}
|
|
860
1236
|
if (type === messageTypes.deactivateResult) {
|
|
861
1237
|
setIsDeactivating(false);
|
|
862
|
-
|
|
863
|
-
|
|
1238
|
+
const parsed = parseLicenseMessage(payload);
|
|
1239
|
+
const isSuccess = payload.success === true;
|
|
1240
|
+
applyPatch({
|
|
1241
|
+
...parsed,
|
|
1242
|
+
deactivateMessage: parsed.lastMessage,
|
|
1243
|
+
deactivateErrorCode: isSuccess ? undefined : parsed.lastErrorCode,
|
|
1244
|
+
lastMessage: isSuccess ? undefined : parsed.lastMessage,
|
|
1245
|
+
lastErrorCode: isSuccess ? undefined : parsed.lastErrorCode,
|
|
1246
|
+
});
|
|
1247
|
+
if (isSuccess) {
|
|
864
1248
|
applyPatch({
|
|
865
1249
|
paymentStatus: 'UNPAID',
|
|
866
1250
|
licenseKey: '',
|
|
@@ -868,6 +1252,8 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
868
1252
|
isLicenseRegistered: false,
|
|
869
1253
|
activationLimit: 0,
|
|
870
1254
|
activationUsage: 0,
|
|
1255
|
+
deactivateMessage: parsed.lastMessage || '라이선스가 비활성화되었습니다.',
|
|
1256
|
+
deactivateErrorCode: undefined,
|
|
871
1257
|
});
|
|
872
1258
|
}
|
|
873
1259
|
}
|
|
@@ -894,8 +1280,12 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
894
1280
|
}, [messageTypes.verifyLicense]);
|
|
895
1281
|
const deactivateLicense = useCallback(() => {
|
|
896
1282
|
setIsDeactivating(true);
|
|
1283
|
+
applyPatch({
|
|
1284
|
+
deactivateMessage: '',
|
|
1285
|
+
deactivateErrorCode: '',
|
|
1286
|
+
});
|
|
897
1287
|
postPluginMessage({ type: messageTypes.deactivateLicense });
|
|
898
|
-
}, [messageTypes.deactivateLicense]);
|
|
1288
|
+
}, [applyPatch, messageTypes.deactivateLicense]);
|
|
899
1289
|
const startDesignbaseAuth = useCallback(() => {
|
|
900
1290
|
setIsStartingAuth(true);
|
|
901
1291
|
postPluginMessage({ type: START_DESIGNBASE_AUTH_MESSAGE });
|
|
@@ -915,28 +1305,29 @@ function useFigmaLicenseBridge(options = {}) {
|
|
|
915
1305
|
function formatUsageLabel(state, t) {
|
|
916
1306
|
const { remainingUsage, usageUsed, usageLimit, usageReset } = state;
|
|
917
1307
|
if (usageLimit === 'unlimited') {
|
|
918
|
-
return resolveText(t, { key: 'license.usage_unlimited' }, '사용 횟수 제한 없음');
|
|
1308
|
+
return resolveText(t, { key: 'license.usage_unlimited' }, '사용 횟수 제한 없음') ?? '사용 횟수 제한 없음';
|
|
919
1309
|
}
|
|
920
1310
|
const limit = typeof usageLimit === 'number' ? usageLimit : remainingUsage + usageUsed;
|
|
921
1311
|
const remaining = remainingUsage ?? Math.max(0, limit - usageUsed);
|
|
922
1312
|
if (usageReset === 'daily') {
|
|
923
1313
|
const fallback = `오늘 남은 횟수 ${remaining}/${limit}`;
|
|
924
|
-
const translated = resolveText(t, { key: 'license.usage_daily' }, fallback);
|
|
1314
|
+
const translated = resolveText(t, { key: 'license.usage_daily' }, fallback) ?? fallback;
|
|
925
1315
|
return translated.includes(String(remaining)) ? translated : fallback;
|
|
926
1316
|
}
|
|
927
1317
|
if (usageReset === 'monthly') {
|
|
928
1318
|
const fallback = `이번 달 남은 횟수 ${remaining}/${limit}`;
|
|
929
|
-
const translated = resolveText(t, { key: 'license.usage_monthly' }, fallback);
|
|
1319
|
+
const translated = resolveText(t, { key: 'license.usage_monthly' }, fallback) ?? fallback;
|
|
930
1320
|
return translated.includes(String(remaining)) ? translated : fallback;
|
|
931
1321
|
}
|
|
932
1322
|
return `남은 횟수 ${remaining}/${limit}`;
|
|
933
1323
|
}
|
|
934
|
-
const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicenseKey = '', wordpressLinks, paymentPageUrl, enableAccountAuth = true, showLicenseKeyInput = true, pricingFeatures, pricing, paymentType = 'subscription', messageTypes, onStateChange, setPaymentStatus, setUsageCount, onLicenseSubmit, usageCount: initialUsageCount = 0, t, className, }) => {
|
|
1324
|
+
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, className, }) => {
|
|
935
1325
|
const links = useMemo(() => ({
|
|
936
1326
|
purchaseUrl: wordpressLinks?.purchaseUrl ?? paymentPageUrl,
|
|
1327
|
+
membershipUrl: membershipUrl ?? wordpressLinks?.membershipUrl,
|
|
937
1328
|
accountUrl: wordpressLinks?.accountUrl,
|
|
938
1329
|
helpUrl: wordpressLinks?.helpUrl,
|
|
939
|
-
}), [wordpressLinks, paymentPageUrl]);
|
|
1330
|
+
}), [wordpressLinks, paymentPageUrl, membershipUrl]);
|
|
940
1331
|
const { state, isVerifying, isDeactivating, isStartingAuth, verifyLicense, deactivateLicense, startDesignbaseAuth, setLicenseKeyInput, } = useFigmaLicenseBridge({
|
|
941
1332
|
messageTypes,
|
|
942
1333
|
initialState: {
|
|
@@ -950,7 +1341,8 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
950
1341
|
});
|
|
951
1342
|
const [showDetails, setShowDetails] = useState(false);
|
|
952
1343
|
const [licenseKeyDraft, setLicenseKeyDraft] = useState(initialLicenseKey);
|
|
953
|
-
const isPaid = state.isLicenseRegistered
|
|
1344
|
+
const isPaid = state.isLicenseRegistered && state.paymentStatus === 'PAID';
|
|
1345
|
+
const isMembershipMode = mode === 'youtube-membership';
|
|
954
1346
|
const usageLabel = formatUsageLabel(state, t);
|
|
955
1347
|
const handleLicenseSubmit = async (submittedLicenseKey) => {
|
|
956
1348
|
if (onLicenseSubmit) {
|
|
@@ -963,29 +1355,30 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
963
1355
|
setLicenseKeyDraft(value);
|
|
964
1356
|
setLicenseKeyInput(value);
|
|
965
1357
|
};
|
|
966
|
-
return (React.createElement("div", { className: `designbase-figma-page-license ${className || ''}
|
|
1358
|
+
return (React.createElement("div", { className: `designbase-figma-page-license designbase-figma-page-license--${mode} ${className || ''}`, "data-license-mode": mode },
|
|
967
1359
|
React.createElement("div", { className: "designbase-figma-page-license__content" },
|
|
968
1360
|
React.createElement("div", { className: "designbase-figma-page-license__header" },
|
|
969
1361
|
React.createElement("div", { className: "designbase-figma-page-license__title" },
|
|
970
|
-
React.createElement("h2", null,
|
|
971
|
-
? resolveText(t, { key: 'license.
|
|
972
|
-
:
|
|
1362
|
+
React.createElement("h2", null, isMembershipMode
|
|
1363
|
+
? resolveText(t, { key: 'license.youtube_membership' }, 'YouTube 멤버십')
|
|
1364
|
+
: isPaid
|
|
1365
|
+
? resolveText(t, { key: 'license.pro_account' }, '프로 계정')
|
|
1366
|
+
: resolveText(t, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
|
|
973
1367
|
state.planTier && state.planTier !== 'FREE' && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, state.planTier))),
|
|
974
1368
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
975
1369
|
? resolveText(t, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
976
|
-
:
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1370
|
+
: isMembershipMode
|
|
1371
|
+
? resolveText(t, { key: 'license.youtube_membership_description' }, 'YouTube 멤버십에 가입하면 Designbase 플러그인을 무제한으로 사용할 수 있습니다.')
|
|
1372
|
+
: resolveText(t, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
|
|
1373
|
+
!isPaid && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
1374
|
+
!isMembershipMode && (React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: t })),
|
|
1375
|
+
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)),
|
|
980
1376
|
isPaid && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
981
1377
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
982
1378
|
React.createElement("h3", null, resolveText(t, { key: 'license.activated' }, '라이선스 활성화됨')),
|
|
983
|
-
React.createElement(Button, {
|
|
1379
|
+
React.createElement(Button, { onPress: () => setShowDetails(!showDetails), variant: "tertiary", size: "s", iconOnly: true },
|
|
984
1380
|
React.createElement(MoreHorizontalIcon, { size: 16 }))),
|
|
985
|
-
state.licenseKey
|
|
986
|
-
resolveText(t, { key: 'license.key_label' }, '라이선스 키'),
|
|
987
|
-
": ",
|
|
988
|
-
React.createElement("span", null, state.licenseKey))),
|
|
1381
|
+
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: t }),
|
|
989
1382
|
React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel),
|
|
990
1383
|
showDetails && (React.createElement("div", { className: "designbase-figma-page-license__details" },
|
|
991
1384
|
React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
@@ -999,59 +1392,54 @@ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicens
|
|
|
999
1392
|
state.activationUsage,
|
|
1000
1393
|
"/",
|
|
1001
1394
|
state.activationLimit)),
|
|
1002
|
-
React.createElement(
|
|
1003
|
-
|
|
1004
|
-
|
|
1395
|
+
React.createElement("div", { className: "designbase-figma-page-license__action" },
|
|
1396
|
+
React.createElement(Button, { onPress: deactivateLicense, variant: "secondary", size: "s", fullWidth: true, disabled: isDeactivating }, isDeactivating
|
|
1397
|
+
? resolveText(t, { key: 'license.deactivating' }, '비활성화 중...')
|
|
1398
|
+
: resolveText(t, { key: 'license.deactivate' }, '라이선스 비활성화')),
|
|
1399
|
+
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))))))),
|
|
1005
1400
|
!isPaid && (React.createElement(React.Fragment, null,
|
|
1006
|
-
(
|
|
1401
|
+
isMembershipMode && (React.createElement(LicenseOffer, { joinUrl: links.membershipUrl || links.purchaseUrl, guideUrl: links.helpUrl || links.purchaseUrl, t: t })),
|
|
1402
|
+
!isMembershipMode && (enableAccountAuth || links.purchaseUrl || links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1007
1403
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1008
1404
|
React.createElement("h3", null, resolveText(t, { key: 'license.designbase_account' }, '디자인베이스 계정'))),
|
|
1009
1405
|
React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(t, { key: 'license.designbase_account_hint' }, 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.')),
|
|
1010
1406
|
React.createElement("div", { className: "designbase-figma-page-license__actions" },
|
|
1011
|
-
enableAccountAuth && (React.createElement(Button, {
|
|
1407
|
+
enableAccountAuth && (React.createElement(Button, { onPress: startDesignbaseAuth, variant: "primary", size: "m", disabled: isStartingAuth || isVerifying, fullWidth: true }, isStartingAuth
|
|
1012
1408
|
? resolveText(t, { key: 'license.authenticating' }, '인증 중...')
|
|
1013
1409
|
: resolveText(t, { key: 'license.login_with_designbase' }, '디자인베이스로 로그인'))),
|
|
1014
|
-
links.purchaseUrl && (React.createElement(Button, {
|
|
1015
|
-
React.createElement("span", null, resolveText(t, { key: 'license.purchase_membership' }, '멤버십
|
|
1410
|
+
links.purchaseUrl && (React.createElement(Button, { onPress: () => openExternalUrl(links.purchaseUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
1411
|
+
React.createElement("span", null, resolveText(t, { key: 'license.purchase_membership' }, '멤버십 안내')),
|
|
1016
1412
|
React.createElement(ExternalLinkIcon, { size: 16 }))),
|
|
1017
|
-
links.accountUrl && (React.createElement(Button, {
|
|
1413
|
+
links.accountUrl && (React.createElement(Button, { onPress: () => openExternalUrl(links.accountUrl), variant: "tertiary", size: "s", fullWidth: true },
|
|
1018
1414
|
React.createElement("span", null, resolveText(t, { key: 'license.manage_account' }, '계정·멤버십 관리')),
|
|
1019
1415
|
React.createElement(ExternalLinkIcon, { size: 16 })))))),
|
|
1020
|
-
showLicenseKeyInput && (React.createElement("div", { className:
|
|
1416
|
+
showLicenseKeyInput && (React.createElement("div", { className: isMembershipMode
|
|
1417
|
+
? 'designbase-figma-page-license__key-form'
|
|
1418
|
+
: 'designbase-figma-page-license__section' },
|
|
1021
1419
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1022
1420
|
React.createElement("h3", null, resolveText(t, { key: 'license.enter_key' }, '라이선스 키 입력'))),
|
|
1023
|
-
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: 'license.enter_from_email' }, t: t }))))),
|
|
1024
|
-
links.helpUrl && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
1421
|
+
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: t }))))),
|
|
1422
|
+
links.helpUrl && !isMembershipMode && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
1025
1423
|
React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(t, { key: 'license.help_link' }, '라이선스·결제 도움말'))))),
|
|
1026
|
-
React.createElement(Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", "aria-label": "Close" },
|
|
1027
|
-
React.createElement(CloseIcon, { size:
|
|
1424
|
+
React.createElement(Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", iconOnly: true, "aria-label": "Close" },
|
|
1425
|
+
React.createElement(CloseIcon, { size: 16 }))));
|
|
1028
1426
|
};
|
|
1029
1427
|
PageLicense.displayName = 'PageLicense';
|
|
1030
1428
|
|
|
1031
|
-
const
|
|
1032
|
-
const
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
resolveText(t, { key: 'payment.activations_remaining' }, '활성'),
|
|
1044
|
-
" ",
|
|
1045
|
-
resolveText(t, { key: 'payment.spots_remaining' }, '자리 남음')),
|
|
1046
|
-
React.createElement("div", { className: "designbase-figma-payment-status__usage" },
|
|
1047
|
-
activationUsage,
|
|
1048
|
-
"/",
|
|
1049
|
-
activationLimit)),
|
|
1050
|
-
React.createElement(Button, { onClick: onDeactivate, variant: "tertiary", size: "s", disabled: isDeactivating }, isDeactivating
|
|
1051
|
-
? resolveText(t, { key: 'payment.deactivating' }, '비활성화중...')
|
|
1052
|
-
: resolveText(t, { key: 'payment.deactivate_license' }, '라이선스 비활성화'))))));
|
|
1429
|
+
const PaymentBadge = ({ isActive, onClick, isLoading = false, text, t = (key) => key, className, }) => {
|
|
1430
|
+
const getBadgeText = () => {
|
|
1431
|
+
if (text)
|
|
1432
|
+
return text;
|
|
1433
|
+
return isActive
|
|
1434
|
+
? (t('proUser') || '프로 계정')
|
|
1435
|
+
: (t('usingFree') || '무료 사용');
|
|
1436
|
+
};
|
|
1437
|
+
const getBadgeVariant = () => {
|
|
1438
|
+
return isActive ? 'success' : 'secondary';
|
|
1439
|
+
};
|
|
1440
|
+
return (React.createElement("div", { className: `designbase-figma-payment-badge ${className || ''} ${isActive ? 'active' : 'free'}`, onClick: onClick, style: { cursor: onClick ? 'pointer' : 'default' } }, isLoading ? (React.createElement(Spinner, { size: "s" })) : (React.createElement(Badge, { variant: getBadgeVariant(), size: "s", className: "designbase-figma-payment-badge__badge" }, getBadgeText()))));
|
|
1053
1441
|
};
|
|
1054
|
-
|
|
1442
|
+
PaymentBadge.displayName = 'PaymentBadge';
|
|
1055
1443
|
|
|
1056
1444
|
const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.working' }, completedMessage = { key: 'progress.completed' }, processingMessage = { key: 'progress.processing' }, stopButtonText = { key: 'progress.stop' }, confirmButtonText = { key: 'progress.confirm' }, helpText, onStop, onComplete, loadingIcon, completeIcon, className, t, autoComplete = true, autoCloseOnComplete = false }) => {
|
|
1057
1445
|
const [isCompleted, setIsCompleted] = useState(false);
|
|
@@ -1095,7 +1483,7 @@ const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.wor
|
|
|
1095
1483
|
React.createElement(Spinner, { size: "m" }))))),
|
|
1096
1484
|
React.createElement("p", { className: "designbase-figma-progress-modal__message" }, displayMessage),
|
|
1097
1485
|
React.createElement("div", { className: "designbase-figma-progress-modal__status" }, `${processedNodes} / ${totalNodes} (${progressPercentage.toFixed(1)}%)`),
|
|
1098
|
-
React.createElement(Progressbar, { value: progressPercentage, size: "m", variant: isCompleted ? 'success' : 'primary',
|
|
1486
|
+
React.createElement(Progressbar, { value: progressPercentage, size: "m", variant: isCompleted ? 'success' : 'primary', barStyle: "animated", fullWidth: true }),
|
|
1099
1487
|
displayHelpText && !isCompleted && (React.createElement("p", { className: "designbase-figma-progress-modal__help-text" }, displayHelpText)),
|
|
1100
1488
|
React.createElement("div", { className: "designbase-figma-progress-modal__actions" }, isCompleted ? (React.createElement(Button, { onPress: handleConfirm, variant: "primary", size: "m", fullWidth: true }, displayConfirmText)) : (React.createElement(Button, { onPress: handleStop, variant: "secondary", size: "m", fullWidth: true }, displayStopText))))));
|
|
1101
1489
|
};
|
|
@@ -1302,5 +1690,5 @@ const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title =
|
|
|
1302
1690
|
};
|
|
1303
1691
|
UpgradeBanner.displayName = 'UpgradeBanner';
|
|
1304
1692
|
|
|
1305
|
-
export { DEFAULT_LICENSE_MESSAGE_TYPES, DonationBadge, FigmaContainer, FigmaFooter, FigmaHeader, FigmaPageHead, FigmaSection, FigmaSidebar, FigmaToast, FigmaToastProvider, FormWithSubmit, InteractionFeedback, LanguageSelector, LogoDropdown, PageLicense, PaymentBadge, PaymentStatusSection, PricingComparison, ProgressModal, ResizablePlugin, START_DESIGNBASE_AUTH_MESSAGE, SettingsModal, TitleDescription, UpgradeBanner, getActiveSection, resolveText, scrollToSection, useFigmaLicenseBridge, useFigmaToast, useToast };
|
|
1693
|
+
export { DEFAULT_LICENSE_MESSAGE_TYPES, DonationBadge, FigmaContainer, FigmaFooter, FigmaHeader, FigmaPageHead, FigmaSection, FigmaSidebar, FigmaToast, FigmaToastProvider, FormWithSubmit, InteractionFeedback, LanguageSelector, LanguageSettingsModal, LicenseOffer, LicenseStatusCard, LogoDropdown, PageLicense, PaymentBadge, PaymentStatusSection, PricingComparison, ProgressModal, ResizablePlugin, START_DESIGNBASE_AUTH_MESSAGE, SettingsModal, TitleDescription, UpgradeBanner, UsageStatusPopover, getActiveSection, interpolateText, resolvePaymentFeedbackVariant, resolveText, scrollToSection, useFigmaLicenseBridge, useFigmaToast, useToast };
|
|
1306
1694
|
//# sourceMappingURL=index.esm.js.map
|