@designbasekorea/figma-ui 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +83 -14
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +336 -127
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +356 -144
- package/dist/index.js.map +1 -1
- package/package.json +13 -6
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
|
+
var react = require('@designbasekorea/ui-wc/react');
|
|
4
5
|
var icons = require('@designbasekorea/icons');
|
|
5
|
-
var ui = require('@designbasekorea/ui');
|
|
6
6
|
|
|
7
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}
|
|
8
8
|
|
|
@@ -12,10 +12,20 @@ function resolveText(t, input, fallback) {
|
|
|
12
12
|
if (typeof input === 'string') {
|
|
13
13
|
return input;
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
if (t) {
|
|
16
|
+
const translated = t(input.key, input.values);
|
|
17
|
+
if (translated && translated !== input.key) {
|
|
18
|
+
return translated;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return fallback ?? input.key;
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
const
|
|
24
|
+
const DONATION_ICON_NAMES = {
|
|
25
|
+
heart: 'star-filled',
|
|
26
|
+
coffee: 'cart',
|
|
27
|
+
};
|
|
28
|
+
const DonationBadge = ({ donationUrl = 'https://buymeacoffee.com/designbase', text = { key: 'donation.buy_me_a_coffee' }, iconType = 'heart', size = 's', variant = 'tertiary', fullWidth = false, iconOnly = false, disabled = false, showPrompt = false, promptText = { key: 'donation.prompt' }, className, onClick, t }) => {
|
|
19
29
|
const handleClick = () => {
|
|
20
30
|
if (onClick) {
|
|
21
31
|
onClick();
|
|
@@ -24,15 +34,12 @@ const DonationBadge = ({ donationUrl = 'https://buymeacoffee.com/designbase', te
|
|
|
24
34
|
window.open(donationUrl, '_blank', 'noopener,noreferrer');
|
|
25
35
|
}
|
|
26
36
|
};
|
|
27
|
-
const Icon = iconType === 'heart' ? icons.HeartFilledIcon : icons.CoffeeFilledIcon;
|
|
28
37
|
const displayText = resolveText(t, text, 'Buy me a coffee');
|
|
29
38
|
const displayPromptText = resolveText(t, promptText, '도움이 되었다면 커피 한 잔 사주세요!');
|
|
30
39
|
const buttonSize = size;
|
|
31
40
|
return (React.createElement("div", { className: clsx('designbase-figma-donation-badge-container', className) },
|
|
32
|
-
showPrompt && (React.createElement("div", { className: "designbase-figma-donation-badge__prompt" }, displayPromptText)),
|
|
33
|
-
React.createElement(
|
|
34
|
-
'--designbase-figma-donation-badge-icon-color': 'var(--db-brand-primary)'
|
|
35
|
-
} }, displayText)));
|
|
41
|
+
showPrompt && !iconOnly && (React.createElement("div", { className: "designbase-figma-donation-badge__prompt" }, displayPromptText)),
|
|
42
|
+
React.createElement(react.Button, { variant: variant, size: buttonSize, fullWidth: fullWidth, disabled: disabled, onPress: handleClick, iconOnly: iconOnly, startIcon: DONATION_ICON_NAMES[iconType], className: clsx('designbase-figma-donation-badge', `designbase-figma-donation-badge--${iconType}`), "aria-label": displayText }, iconOnly ? undefined : displayText)));
|
|
36
43
|
};
|
|
37
44
|
DonationBadge.displayName = 'DonationBadge';
|
|
38
45
|
|
|
@@ -70,10 +77,11 @@ const FigmaHeader = ({ children, actions = [], searchBar, sticky = true, classNa
|
|
|
70
77
|
'designbase-figma-header--with-search': !!searchBar,
|
|
71
78
|
'designbase-figma-header--with-actions': actions.length > 0,
|
|
72
79
|
}, className);
|
|
80
|
+
const hasToolbar = !!children || actions.length > 0;
|
|
73
81
|
return (React.createElement("header", { className: classes },
|
|
74
|
-
React.createElement("div", { className: "designbase-figma-header__container" },
|
|
82
|
+
hasToolbar && (React.createElement("div", { className: "designbase-figma-header__container" },
|
|
75
83
|
children && (React.createElement("div", { className: "designbase-figma-header__center" }, children)),
|
|
76
|
-
actions.length > 0 && (React.createElement("div", { className: "designbase-figma-header__right" }, actions.map((action, index) => (React.createElement(
|
|
84
|
+
actions.length > 0 && (React.createElement("div", { className: "designbase-figma-header__right" }, actions.map((action, index) => (React.createElement(react.Button, { key: `${action.startIcon}-${index}`, variant: "tertiary", size: "s", iconOnly: true, startIcon: action.startIcon, "aria-label": action.ariaLabel, onPress: action.onPress }))))))),
|
|
77
85
|
searchBar && (React.createElement("div", { className: "designbase-figma-header__search-container" }, searchBar))));
|
|
78
86
|
};
|
|
79
87
|
FigmaHeader.displayName = 'FigmaHeader';
|
|
@@ -82,22 +90,24 @@ const FigmaPageHead = ({ onBack, title, description, actions = [], moreActions =
|
|
|
82
90
|
const classes = clsx('designbase-figma-page-head', className);
|
|
83
91
|
const displayTitle = resolveText(t, title);
|
|
84
92
|
const displayDescription = description ? resolveText(t, description) : undefined;
|
|
85
|
-
const dropdownItems = moreActions.map(action => ({
|
|
93
|
+
const dropdownItems = moreActions.map((action) => ({
|
|
86
94
|
id: action.id,
|
|
87
95
|
label: resolveText(t, action.label),
|
|
88
|
-
onClick: action.onClick
|
|
89
96
|
}));
|
|
97
|
+
const handleDropdownChange = (event) => {
|
|
98
|
+
const actionId = event.detail?.id ?? event.detail?.value;
|
|
99
|
+
const action = moreActions.find((item) => item.id === actionId);
|
|
100
|
+
action?.onClick();
|
|
101
|
+
};
|
|
90
102
|
return (React.createElement("div", { className: classes },
|
|
91
103
|
React.createElement("div", { className: "designbase-figma-page-head__left" },
|
|
92
|
-
React.createElement(
|
|
93
|
-
React.createElement(icons.ChevronLeftIcon, { size: 14 })),
|
|
104
|
+
React.createElement(react.Button, { variant: "tertiary", size: "s", iconOnly: true, startIcon: "chevron-left", onPress: onBack, "aria-label": "\uB4A4\uB85C\uAC00\uAE30" }),
|
|
94
105
|
React.createElement("div", { className: "designbase-figma-page-head__titles" },
|
|
95
106
|
React.createElement("h2", null, displayTitle),
|
|
96
107
|
displayDescription && React.createElement("p", null, displayDescription))),
|
|
97
108
|
React.createElement("div", { className: "designbase-figma-page-head__actions" },
|
|
98
109
|
actions.map((action, index) => (React.createElement(React.Fragment, { key: index }, action))),
|
|
99
|
-
moreActions.length > 0 && (React.createElement(
|
|
100
|
-
React.createElement(icons.MoreHorizontalIcon, { size: 16 })), items: dropdownItems, placement: "bottom-right", size: "s" })))));
|
|
110
|
+
moreActions.length > 0 && (React.createElement(react.Dropdown, { items: dropdownItems, triggerIcon: "more-horizontal", iconOnly: true, triggerVariant: "tertiary", placement: "bottom-right", size: "s", onChange: handleDropdownChange })))));
|
|
101
111
|
};
|
|
102
112
|
FigmaPageHead.displayName = 'FigmaPageHead';
|
|
103
113
|
|
|
@@ -223,12 +233,12 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
|
|
|
223
233
|
typeof title === 'string' || (typeof title === 'object' && 'key' in title)
|
|
224
234
|
? resolveText(t, title)
|
|
225
235
|
: title,
|
|
226
|
-
badge && (React.createElement(
|
|
236
|
+
badge && (React.createElement(react.Badge, { variant: "secondary", size: "s" }, badge)))),
|
|
227
237
|
React.createElement("div", { className: "designbase-figma-section__controls", onClick: (e) => e.stopPropagation() },
|
|
228
238
|
iconButton,
|
|
229
239
|
collapsible && (React.createElement("span", { className: `designbase-figma-section__collapse-icon ${collapsed ? 'designbase-figma-section__collapse-icon--collapsed' : ''}` },
|
|
230
240
|
React.createElement(icons.ChevronDownIcon, { size: 16 }))),
|
|
231
|
-
onToggle && (React.createElement(
|
|
241
|
+
onToggle && (React.createElement(react.Toggle, { checked: isEnabled, onChange: () => onToggle(dataCategory), size: "s" }))))),
|
|
232
242
|
React.createElement("div", { className: `designbase-figma-section__content ${!isEnabled ? 'designbase-figma-section__content--hidden' : ''}` },
|
|
233
243
|
React.createElement("div", { ref: clipRef, className: "designbase-figma-section__content-clip" },
|
|
234
244
|
React.createElement("div", { ref: innerRef, className: `designbase-figma-section__content-inner ${collapsible && contentHidden ? 'is-collapsed' : ''}` }, children)))));
|
|
@@ -385,7 +395,7 @@ const PaymentBadge = ({ isActive, onClick, isLoading = false, text, t = (key) =>
|
|
|
385
395
|
const getBadgeVariant = () => {
|
|
386
396
|
return isActive ? 'success' : 'secondary';
|
|
387
397
|
};
|
|
388
|
-
return (React.createElement("div", { className: `designbase-figma-payment-badge ${className || ''} ${isActive ? 'active' : 'free'}`, onClick: onClick, style: { cursor: onClick ? 'pointer' : 'default' } }, isLoading ? (React.createElement(
|
|
398
|
+
return (React.createElement("div", { className: `designbase-figma-payment-badge ${className || ''} ${isActive ? 'active' : 'free'}`, onClick: onClick, style: { cursor: onClick ? 'pointer' : 'default' } }, isLoading ? (React.createElement(react.Spinner, { size: "s" })) : (React.createElement(react.Badge, { variant: getBadgeVariant(), size: "s", className: "designbase-figma-payment-badge__badge" }, getBadgeText()))));
|
|
389
399
|
};
|
|
390
400
|
PaymentBadge.displayName = 'PaymentBadge';
|
|
391
401
|
|
|
@@ -414,10 +424,15 @@ const LanguageSelector = ({ currentLanguage, languages = DEFAULT_LANGUAGES, onLa
|
|
|
414
424
|
const segmentOptions = languages.map((language) => ({
|
|
415
425
|
value: language.code,
|
|
416
426
|
label: resolveText(t, language.label),
|
|
417
|
-
disabled: false
|
|
427
|
+
disabled: false,
|
|
418
428
|
}));
|
|
419
429
|
return (React.createElement("div", { className: `designbase-figma-language-selector ${className || ''}` },
|
|
420
|
-
React.createElement(
|
|
430
|
+
React.createElement(react.SegmentControl, { options: segmentOptions, value: activeLanguage, onChange: (event) => {
|
|
431
|
+
const value = event.detail?.value;
|
|
432
|
+
if (value) {
|
|
433
|
+
handleLanguageChange(value);
|
|
434
|
+
}
|
|
435
|
+
}, size: size, className: "designbase-figma-language-selector__segment" })));
|
|
421
436
|
};
|
|
422
437
|
LanguageSelector.displayName = 'LanguageSelector';
|
|
423
438
|
|
|
@@ -473,7 +488,7 @@ const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase'
|
|
|
473
488
|
return (React.createElement("img", { className: "designbase-figma-logo-dropdown__logo", src: logoSrc, alt: logoAlt, onClick: toggleDropdown }));
|
|
474
489
|
}
|
|
475
490
|
return (React.createElement("div", { className: "designbase-figma-logo-dropdown__logo", onClick: toggleDropdown },
|
|
476
|
-
React.createElement(
|
|
491
|
+
React.createElement(react.Logo, { type: logoType, size: logoSize, variant: "default" })));
|
|
477
492
|
};
|
|
478
493
|
return (React.createElement("div", { className: classes },
|
|
479
494
|
renderLogo(),
|
|
@@ -507,22 +522,29 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
507
522
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
508
523
|
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, t: t }),
|
|
509
524
|
showLanguageSelector && (React.createElement(LanguageSelector, { currentLanguage: currentLanguage, languages: languages, onLanguageChange: onLanguageChange, size: "s" }))),
|
|
510
|
-
|
|
511
|
-
resolvedShowUsageInfo && (React.createElement("div", { className: "designbase-figma-footer__usage-info" }, isActive ? (React.createElement("span", { className: "designbase-figma-footer__unlimited-usage designbase-figma-footer__unlimited-usage--tooltip", title: t('unlimitedUsageTooltip') }, t('unlimitedUsage'))) : (React.createElement(
|
|
512
|
-
React.createElement("span", { className: "designbase-figma-footer__usage-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
showDonation && (React.createElement("div", { className: "designbase-figma-footer__donation" },
|
|
521
|
-
React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", showPrompt: showDonationText && !isActive, promptText: donationPromptText, t: t })))),
|
|
525
|
+
React.createElement("div", { className: "designbase-figma-footer__right" },
|
|
526
|
+
showPaymentStatus && resolvedShowUsageInfo && (React.createElement("div", { className: "designbase-figma-footer__usage-info" }, isActive ? (React.createElement("span", { className: "designbase-figma-footer__unlimited-usage designbase-figma-footer__unlimited-usage--tooltip", title: t('unlimitedUsageTooltip') }, t('unlimitedUsage'))) : (React.createElement("span", { className: "designbase-figma-footer__usage-info designbase-figma-footer__usage-info--tooltip", title: t('resetsDaily') },
|
|
527
|
+
React.createElement("span", { className: "designbase-figma-footer__usage-count" }, usageCount),
|
|
528
|
+
React.createElement("span", { className: "designbase-figma-footer__max-daily-usage" },
|
|
529
|
+
"/",
|
|
530
|
+
maxDailyUsage,
|
|
531
|
+
" ",
|
|
532
|
+
t('perDay')))))),
|
|
533
|
+
showPaymentStatus && resolvedShowPaymentBadge && (React.createElement(PaymentBadge, { isActive: isActive, onClick: isBeta ? undefined : onLicensePageClick, isLoading: isLoading, text: isBeta ? (t('betaStatus') || 'BETA') : undefined, t: t })),
|
|
534
|
+
showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t: t })))),
|
|
522
535
|
children));
|
|
523
536
|
};
|
|
524
537
|
FigmaFooter.displayName = 'FigmaFooter';
|
|
525
538
|
|
|
539
|
+
const FigmaToastStack = ({ toasts, position, maxToasts, onRemoveToast, }) => {
|
|
540
|
+
const visibleToasts = [...toasts]
|
|
541
|
+
.sort((a, b) => b.createdAt - a.createdAt)
|
|
542
|
+
.slice(0, maxToasts);
|
|
543
|
+
if (visibleToasts.length === 0)
|
|
544
|
+
return null;
|
|
545
|
+
return (React.createElement("div", { className: `figma-toast-container figma-toast-container--${position}` }, visibleToasts.map((toast) => (React.createElement("div", { key: toast.id, className: "figma-toast-container__item" },
|
|
546
|
+
React.createElement(react.Toast, { toastId: toast.id, title: toast.title, description: toast.description, status: toast.status, duration: toast.duration, showProgress: toast.showProgress, showClose: toast.showCloseButton, onClose: () => onRemoveToast(toast.id) }))))));
|
|
547
|
+
};
|
|
526
548
|
const ToastContext = React.createContext(null);
|
|
527
549
|
const useToast = () => {
|
|
528
550
|
const context = React.useContext(ToastContext);
|
|
@@ -540,13 +562,13 @@ const FigmaToastProvider = ({ children, position = 'top-right', maxToasts = 5, }
|
|
|
540
562
|
id,
|
|
541
563
|
createdAt: Date.now(),
|
|
542
564
|
};
|
|
543
|
-
setToasts(prev => {
|
|
565
|
+
setToasts((prev) => {
|
|
544
566
|
const updated = [newToast, ...prev];
|
|
545
567
|
return updated.slice(0, maxToasts);
|
|
546
568
|
});
|
|
547
569
|
}, [maxToasts]);
|
|
548
570
|
const removeToast = React.useCallback((id) => {
|
|
549
|
-
setToasts(prev => prev.filter(toast => toast.id !== id));
|
|
571
|
+
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
|
550
572
|
}, []);
|
|
551
573
|
const showToast = React.useCallback((message, options = {}) => {
|
|
552
574
|
addToast({
|
|
@@ -565,17 +587,17 @@ const FigmaToastProvider = ({ children, position = 'top-right', maxToasts = 5, }
|
|
|
565
587
|
};
|
|
566
588
|
return (React.createElement(ToastContext.Provider, { value: contextValue },
|
|
567
589
|
children,
|
|
568
|
-
React.createElement(
|
|
590
|
+
React.createElement(FigmaToastStack, { toasts: toasts, onRemoveToast: removeToast, position: position, maxToasts: maxToasts })));
|
|
569
591
|
};
|
|
570
592
|
const FigmaToast = ({ message, isVisible, onClose, type = 'info', duration = 3000, className, }) => {
|
|
571
593
|
if (!isVisible)
|
|
572
594
|
return null;
|
|
573
595
|
return (React.createElement("div", { className: `figma-toast-fixed-wrap ${className || ''}` },
|
|
574
|
-
React.createElement(
|
|
596
|
+
React.createElement(react.Toast, { toastId: "figma-toast-simple", title: message, status: type, duration: duration, showProgress: false, showClose: true, onClose: onClose })));
|
|
575
597
|
};
|
|
576
598
|
const useFigmaToast = () => {
|
|
577
599
|
const [toast, setToast] = React.useState({ message: '', isVisible: false });
|
|
578
|
-
const showToast = React.useCallback((message,
|
|
600
|
+
const showToast = React.useCallback((message, _type = 'info') => {
|
|
579
601
|
setToast({ message, isVisible: true });
|
|
580
602
|
setTimeout(() => setToast({ message: '', isVisible: false }), 5000);
|
|
581
603
|
}, []);
|
|
@@ -606,8 +628,13 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
606
628
|
return (React.createElement("form", { className: `designbase-figma-form-with-submit ${className || ''}`, onSubmit: handleSubmit },
|
|
607
629
|
React.createElement("div", { className: "designbase-figma-form-with-submit__field" },
|
|
608
630
|
React.createElement("label", { className: "designbase-figma-form-with-submit__label" }, displayLabel),
|
|
609
|
-
React.createElement(
|
|
610
|
-
|
|
631
|
+
React.createElement(react.Input, { value: inputValue, onChange: (event) => {
|
|
632
|
+
const value = event.detail?.value;
|
|
633
|
+
if (value !== undefined) {
|
|
634
|
+
handleChange(value);
|
|
635
|
+
}
|
|
636
|
+
}, placeholder: displayPlaceholder, helperText: displayHelperText, disabled: disabled || isSubmitting, size: "m" })),
|
|
637
|
+
React.createElement(react.Button, { type: "submit", variant: "primary", size: "m", loading: isSubmitting, disabled: !inputValue.trim() || isSubmitting || disabled, fullWidth: true }, isSubmitting ? displaySubmittingText : displaySubmitText)));
|
|
611
638
|
};
|
|
612
639
|
FormWithSubmit.displayName = 'FormWithSubmit';
|
|
613
640
|
|
|
@@ -620,7 +647,7 @@ const InteractionFeedback = ({ status = 'default', message, statusMessage, leftC
|
|
|
620
647
|
return (React.createElement("div", { className: feedbackClasses },
|
|
621
648
|
React.createElement("div", { className: "designbase-figma-interaction__content" },
|
|
622
649
|
React.createElement("div", { className: "designbase-figma-interaction__left" }, leftContent || (React.createElement("div", { className: "designbase-figma-interaction__message" },
|
|
623
|
-
status === 'loading' && (React.createElement(
|
|
650
|
+
status === 'loading' && (React.createElement(react.Spinner, { size: "s", type: "circular", label: "\uBD88\uB7EC\uC624\uB294 \uC911\uC785\uB2C8\uB2E4...", showLabel: false })),
|
|
624
651
|
(message || status === 'loading') && (React.createElement("span", { className: "designbase-figma-interaction__text" }, resolveText(t, message || '불러오는 중입니다...'))),
|
|
625
652
|
statusMessage && (React.createElement("span", { className: "designbase-figma-interaction__status-text" }, resolveText(t, statusMessage)))))),
|
|
626
653
|
rightAction && (React.createElement("div", { className: "designbase-figma-interaction__right" }, rightAction)))));
|
|
@@ -659,18 +686,17 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
659
686
|
};
|
|
660
687
|
return (React.createElement("div", { className: `designbase-figma-pricing-comparison ${className || ''}` },
|
|
661
688
|
paymentType === 'subscription' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__billing-toggle" },
|
|
662
|
-
React.createElement(
|
|
689
|
+
React.createElement(react.SegmentControl, { value: isYearly ? 'yearly' : 'monthly', onChange: (event) => {
|
|
690
|
+
const value = event.detail?.value;
|
|
691
|
+
setIsYearly(value === 'yearly');
|
|
692
|
+
}, options: [
|
|
663
693
|
{
|
|
664
694
|
value: 'monthly',
|
|
665
695
|
label: t('monthlyBilling') || '월간 결제',
|
|
666
696
|
},
|
|
667
697
|
{
|
|
668
698
|
value: 'yearly',
|
|
669
|
-
label: (
|
|
670
|
-
t('yearlyBilling') || '연간 결제',
|
|
671
|
-
React.createElement("span", { className: "designbase-figma-pricing-comparison__discount-badge" },
|
|
672
|
-
getDiscountPercentage(),
|
|
673
|
-
"% \uC808\uC57D"))),
|
|
699
|
+
label: `${t('yearlyBilling') || '연간 결제'} (${getDiscountPercentage()}% 절약)`,
|
|
674
700
|
},
|
|
675
701
|
], size: "s" }))),
|
|
676
702
|
paymentType === 'lifetime' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__lifetime-info" },
|
|
@@ -698,124 +724,307 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
698
724
|
};
|
|
699
725
|
PricingComparison.displayName = 'PricingComparison';
|
|
700
726
|
|
|
701
|
-
|
|
702
|
-
|
|
727
|
+
function postPluginMessage(message) {
|
|
728
|
+
if (typeof parent === 'undefined') {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
parent.postMessage({ pluginMessage: message }, '*');
|
|
732
|
+
}
|
|
733
|
+
function openExternalUrl(url) {
|
|
734
|
+
if (!url)
|
|
735
|
+
return;
|
|
736
|
+
postPluginMessage({ type: 'open-external-url', url });
|
|
737
|
+
if (typeof window !== 'undefined') {
|
|
738
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
const DEFAULT_LICENSE_MESSAGE_TYPES = {
|
|
743
|
+
initialize: 'initialize',
|
|
744
|
+
verifyLicense: 'verify-license',
|
|
745
|
+
deactivateLicense: 'deactivate-license',
|
|
746
|
+
updateStatus: 'update-plugin-status',
|
|
747
|
+
verifyResult: 'license-verification-result',
|
|
748
|
+
deactivateResult: 'license-deactivation-result',
|
|
749
|
+
};
|
|
750
|
+
const START_DESIGNBASE_AUTH_MESSAGE = 'start-designbase-auth';
|
|
751
|
+
const INITIAL_LICENSE_PAGE_STATE = {
|
|
752
|
+
paymentStatus: 'FREE',
|
|
753
|
+
licenseKey: '',
|
|
754
|
+
planTier: 'FREE',
|
|
755
|
+
hasLicenseKey: false,
|
|
756
|
+
isLicenseRegistered: false,
|
|
757
|
+
activationLimit: 0,
|
|
758
|
+
activationUsage: 0,
|
|
759
|
+
usageCount: 0,
|
|
760
|
+
remainingUsage: 0,
|
|
761
|
+
usageUsed: 0,
|
|
762
|
+
usageLimit: 0,
|
|
763
|
+
usageReset: 'none',
|
|
764
|
+
canUseFeature: true,
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
function readString(data, keys) {
|
|
768
|
+
for (const key of keys) {
|
|
769
|
+
const value = data[key];
|
|
770
|
+
if (typeof value === 'string') {
|
|
771
|
+
return value;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
return '';
|
|
775
|
+
}
|
|
776
|
+
function readNumber(data, keys) {
|
|
777
|
+
for (const key of keys) {
|
|
778
|
+
const value = data[key];
|
|
779
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
780
|
+
return value;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return undefined;
|
|
784
|
+
}
|
|
785
|
+
function readBoolean(data, keys) {
|
|
786
|
+
for (const key of keys) {
|
|
787
|
+
const value = data[key];
|
|
788
|
+
if (typeof value === 'boolean') {
|
|
789
|
+
return value;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return undefined;
|
|
793
|
+
}
|
|
794
|
+
function parseLicenseMessage(data) {
|
|
795
|
+
const paymentStatus = readString(data, ['paymentStatus', 'status']);
|
|
796
|
+
const usageLimitRaw = data.usageLimit;
|
|
797
|
+
return {
|
|
798
|
+
...(paymentStatus ? { paymentStatus } : {}),
|
|
799
|
+
licenseKey: readString(data, ['licenseKey']) || undefined,
|
|
800
|
+
planTier: readString(data, ['planTier']) || undefined,
|
|
801
|
+
hasLicenseKey: readBoolean(data, ['hasLicenseKey']),
|
|
802
|
+
isLicenseRegistered: readBoolean(data, ['isLicenseRegistered']),
|
|
803
|
+
activationLimit: readNumber(data, ['activationLimit']),
|
|
804
|
+
activationUsage: readNumber(data, ['activationUsage']),
|
|
805
|
+
usageCount: readNumber(data, ['usageCount']),
|
|
806
|
+
remainingUsage: readNumber(data, ['remainingUsage']),
|
|
807
|
+
usageUsed: readNumber(data, ['usageUsed']),
|
|
808
|
+
usageLimit: usageLimitRaw === 'unlimited' ? 'unlimited' : readNumber(data, ['usageLimit']),
|
|
809
|
+
usageReset: readString(data, ['usageReset']) || undefined,
|
|
810
|
+
canUseFeature: readBoolean(data, ['canUseFeature']),
|
|
811
|
+
usageReason: readString(data, ['usageReason']) || undefined,
|
|
812
|
+
lastMessage: readString(data, ['message']) || undefined,
|
|
813
|
+
lastErrorCode: readString(data, ['errorCode']) || undefined,
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
function useFigmaLicenseBridge(options = {}) {
|
|
817
|
+
const messageTypes = React.useMemo(() => ({ ...DEFAULT_LICENSE_MESSAGE_TYPES, ...options.messageTypes }), [options.messageTypes]);
|
|
818
|
+
const [state, setState] = React.useState({
|
|
819
|
+
...INITIAL_LICENSE_PAGE_STATE,
|
|
820
|
+
...options.initialState,
|
|
821
|
+
});
|
|
822
|
+
const [isVerifying, setIsVerifying] = React.useState(false);
|
|
703
823
|
const [isDeactivating, setIsDeactivating] = React.useState(false);
|
|
704
|
-
const [
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
824
|
+
const [isStartingAuth, setIsStartingAuth] = React.useState(false);
|
|
825
|
+
const optionsRef = React.useRef(options);
|
|
826
|
+
optionsRef.current = options;
|
|
827
|
+
const applyPatch = React.useCallback((patch) => {
|
|
828
|
+
setState((prev) => {
|
|
829
|
+
const next = {
|
|
830
|
+
...prev,
|
|
831
|
+
...Object.fromEntries(Object.entries(patch).filter(([, value]) => value !== undefined)),
|
|
832
|
+
};
|
|
833
|
+
optionsRef.current.onStateChange?.(next);
|
|
834
|
+
if (patch.paymentStatus) {
|
|
835
|
+
optionsRef.current.onPaymentStatusChange?.(patch.paymentStatus);
|
|
836
|
+
}
|
|
837
|
+
if (patch.usageCount !== undefined) {
|
|
838
|
+
optionsRef.current.onUsageCountChange?.(patch.usageCount);
|
|
839
|
+
}
|
|
840
|
+
return next;
|
|
841
|
+
});
|
|
842
|
+
}, []);
|
|
710
843
|
React.useEffect(() => {
|
|
711
844
|
const handleMessage = (event) => {
|
|
712
|
-
const
|
|
713
|
-
if (
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
setActivationLimit(activationLimit);
|
|
720
|
-
if (activationUsage !== undefined)
|
|
721
|
-
setActivationUsage(activationUsage);
|
|
722
|
-
if (paymentStatus)
|
|
723
|
-
setPaymentStatus(paymentStatus);
|
|
724
|
-
if (usageCount !== undefined) {
|
|
725
|
-
setLocalUsageCount(usageCount);
|
|
726
|
-
setUsageCount(usageCount);
|
|
727
|
-
}
|
|
845
|
+
const data = event.data?.pluginMessage;
|
|
846
|
+
if (!data || typeof data !== 'object')
|
|
847
|
+
return;
|
|
848
|
+
const payload = data;
|
|
849
|
+
const type = typeof payload.type === 'string' ? payload.type : '';
|
|
850
|
+
if (type === messageTypes.updateStatus) {
|
|
851
|
+
applyPatch(parseLicenseMessage(payload));
|
|
728
852
|
}
|
|
729
|
-
if (type ===
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (success) {
|
|
734
|
-
|
|
735
|
-
setPaymentStatus('PAID');
|
|
853
|
+
if (type === messageTypes.verifyResult) {
|
|
854
|
+
setIsVerifying(false);
|
|
855
|
+
setIsStartingAuth(false);
|
|
856
|
+
applyPatch(parseLicenseMessage(payload));
|
|
857
|
+
if (payload.success === true) {
|
|
858
|
+
applyPatch({ paymentStatus: 'PAID', isLicenseRegistered: true });
|
|
736
859
|
}
|
|
737
860
|
}
|
|
738
|
-
if (type ===
|
|
861
|
+
if (type === messageTypes.deactivateResult) {
|
|
739
862
|
setIsDeactivating(false);
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
863
|
+
applyPatch(parseLicenseMessage(payload));
|
|
864
|
+
if (payload.success === true) {
|
|
865
|
+
applyPatch({
|
|
866
|
+
paymentStatus: 'UNPAID',
|
|
867
|
+
licenseKey: '',
|
|
868
|
+
hasLicenseKey: false,
|
|
869
|
+
isLicenseRegistered: false,
|
|
870
|
+
activationLimit: 0,
|
|
871
|
+
activationUsage: 0,
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
if (type === 'designbase-auth-result') {
|
|
876
|
+
setIsStartingAuth(false);
|
|
877
|
+
if (payload.success === true) {
|
|
878
|
+
applyPatch(parseLicenseMessage(payload));
|
|
879
|
+
}
|
|
880
|
+
else if (typeof payload.message === 'string') {
|
|
881
|
+
applyPatch({ lastMessage: payload.message });
|
|
749
882
|
}
|
|
750
883
|
}
|
|
751
884
|
};
|
|
752
885
|
window.addEventListener('message', handleMessage);
|
|
753
|
-
|
|
754
|
-
parent.postMessage({ pluginMessage: { type: 'initialize' } }, '*');
|
|
755
|
-
}
|
|
886
|
+
postPluginMessage({ type: messageTypes.initialize });
|
|
756
887
|
return () => window.removeEventListener('message', handleMessage);
|
|
757
|
-
}, [
|
|
888
|
+
}, [applyPatch, messageTypes]);
|
|
889
|
+
const verifyLicense = React.useCallback((licenseKey) => {
|
|
890
|
+
setIsVerifying(true);
|
|
891
|
+
postPluginMessage({
|
|
892
|
+
type: messageTypes.verifyLicense,
|
|
893
|
+
licenseKey,
|
|
894
|
+
});
|
|
895
|
+
}, [messageTypes.verifyLicense]);
|
|
896
|
+
const deactivateLicense = React.useCallback(() => {
|
|
897
|
+
setIsDeactivating(true);
|
|
898
|
+
postPluginMessage({ type: messageTypes.deactivateLicense });
|
|
899
|
+
}, [messageTypes.deactivateLicense]);
|
|
900
|
+
const startDesignbaseAuth = React.useCallback(() => {
|
|
901
|
+
setIsStartingAuth(true);
|
|
902
|
+
postPluginMessage({ type: START_DESIGNBASE_AUTH_MESSAGE });
|
|
903
|
+
}, []);
|
|
904
|
+
return {
|
|
905
|
+
state,
|
|
906
|
+
isVerifying,
|
|
907
|
+
isDeactivating,
|
|
908
|
+
isStartingAuth,
|
|
909
|
+
verifyLicense,
|
|
910
|
+
deactivateLicense,
|
|
911
|
+
startDesignbaseAuth,
|
|
912
|
+
setLicenseKeyInput: (licenseKey) => applyPatch({ licenseKey }),
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
function formatUsageLabel(state, t) {
|
|
917
|
+
const { remainingUsage, usageUsed, usageLimit, usageReset } = state;
|
|
918
|
+
if (usageLimit === 'unlimited') {
|
|
919
|
+
return resolveText(t, { key: 'license.usage_unlimited' }, '사용 횟수 제한 없음');
|
|
920
|
+
}
|
|
921
|
+
const limit = typeof usageLimit === 'number' ? usageLimit : remainingUsage + usageUsed;
|
|
922
|
+
const remaining = remainingUsage ?? Math.max(0, limit - usageUsed);
|
|
923
|
+
if (usageReset === 'daily') {
|
|
924
|
+
const fallback = `오늘 남은 횟수 ${remaining}/${limit}`;
|
|
925
|
+
const translated = resolveText(t, { key: 'license.usage_daily' }, fallback);
|
|
926
|
+
return translated.includes(String(remaining)) ? translated : fallback;
|
|
927
|
+
}
|
|
928
|
+
if (usageReset === 'monthly') {
|
|
929
|
+
const fallback = `이번 달 남은 횟수 ${remaining}/${limit}`;
|
|
930
|
+
const translated = resolveText(t, { key: 'license.usage_monthly' }, fallback);
|
|
931
|
+
return translated.includes(String(remaining)) ? translated : fallback;
|
|
932
|
+
}
|
|
933
|
+
return `남은 횟수 ${remaining}/${limit}`;
|
|
934
|
+
}
|
|
935
|
+
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, }) => {
|
|
936
|
+
const links = React.useMemo(() => ({
|
|
937
|
+
purchaseUrl: wordpressLinks?.purchaseUrl ?? paymentPageUrl,
|
|
938
|
+
accountUrl: wordpressLinks?.accountUrl,
|
|
939
|
+
helpUrl: wordpressLinks?.helpUrl,
|
|
940
|
+
}), [wordpressLinks, paymentPageUrl]);
|
|
941
|
+
const { state, isVerifying, isDeactivating, isStartingAuth, verifyLicense, deactivateLicense, startDesignbaseAuth, setLicenseKeyInput, } = useFigmaLicenseBridge({
|
|
942
|
+
messageTypes,
|
|
943
|
+
initialState: {
|
|
944
|
+
paymentStatus: initialStatus,
|
|
945
|
+
licenseKey: initialLicenseKey,
|
|
946
|
+
usageCount: initialUsageCount,
|
|
947
|
+
},
|
|
948
|
+
onStateChange,
|
|
949
|
+
onPaymentStatusChange: setPaymentStatus,
|
|
950
|
+
onUsageCountChange: setUsageCount,
|
|
951
|
+
});
|
|
952
|
+
const [showDetails, setShowDetails] = React.useState(false);
|
|
953
|
+
const [licenseKeyDraft, setLicenseKeyDraft] = React.useState(initialLicenseKey);
|
|
954
|
+
const isPaid = state.isLicenseRegistered || state.paymentStatus === 'PAID';
|
|
955
|
+
const usageLabel = formatUsageLabel(state, t);
|
|
758
956
|
const handleLicenseSubmit = async (submittedLicenseKey) => {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
pluginMessage: {
|
|
763
|
-
type: 'verify-license',
|
|
764
|
-
licenseKey: submittedLicenseKey
|
|
765
|
-
}
|
|
766
|
-
}, '*');
|
|
957
|
+
if (onLicenseSubmit) {
|
|
958
|
+
await onLicenseSubmit(submittedLicenseKey);
|
|
959
|
+
return;
|
|
767
960
|
}
|
|
961
|
+
verifyLicense(submittedLicenseKey);
|
|
768
962
|
};
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
parent.postMessage({
|
|
773
|
-
pluginMessage: { type: 'deactivate-license' }
|
|
774
|
-
}, '*');
|
|
775
|
-
}
|
|
963
|
+
const handleLicenseKeyChange = (value) => {
|
|
964
|
+
setLicenseKeyDraft(value);
|
|
965
|
+
setLicenseKeyInput(value);
|
|
776
966
|
};
|
|
777
|
-
const isPaid = status === 'PAID';
|
|
778
967
|
return (React.createElement("div", { className: `designbase-figma-page-license ${className || ''}` },
|
|
779
968
|
React.createElement("div", { className: "designbase-figma-page-license__content" },
|
|
780
969
|
React.createElement("div", { className: "designbase-figma-page-license__header" },
|
|
781
970
|
React.createElement("div", { className: "designbase-figma-page-license__title" },
|
|
782
|
-
React.createElement("h2", null, isPaid
|
|
971
|
+
React.createElement("h2", null, isPaid
|
|
972
|
+
? resolveText(t, { key: 'license.pro_account' }, '프로 계정')
|
|
973
|
+
: resolveText(t, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
|
|
974
|
+
state.planTier && state.planTier !== 'FREE' && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, state.planTier))),
|
|
783
975
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
784
976
|
? resolveText(t, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
785
|
-
: resolveText(t, { key: 'license.purchase_for_unlimited' }, '
|
|
977
|
+
: resolveText(t, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
|
|
978
|
+
!isPaid && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
|
|
786
979
|
React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: t }),
|
|
980
|
+
state.lastMessage && (React.createElement("p", { className: `designbase-figma-page-license__feedback ${state.lastErrorCode ? 'designbase-figma-page-license__feedback--error' : ''}` }, state.lastMessage)),
|
|
787
981
|
isPaid && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
788
982
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
789
983
|
React.createElement("h3", null, resolveText(t, { key: 'license.activated' }, '라이선스 활성화됨')),
|
|
790
|
-
React.createElement(
|
|
984
|
+
React.createElement(react.Button, { onClick: () => setShowDetails(!showDetails), variant: "tertiary", size: "s", iconOnly: true },
|
|
791
985
|
React.createElement(icons.MoreHorizontalIcon, { size: 16 }))),
|
|
792
|
-
React.createElement("div", { className: "designbase-figma-page-license__license-key" },
|
|
986
|
+
state.licenseKey && (React.createElement("div", { className: "designbase-figma-page-license__license-key" },
|
|
793
987
|
resolveText(t, { key: 'license.key_label' }, '라이선스 키'),
|
|
794
988
|
": ",
|
|
795
|
-
React.createElement("span", null, licenseKey)),
|
|
989
|
+
React.createElement("span", null, state.licenseKey))),
|
|
990
|
+
React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel),
|
|
796
991
|
showDetails && (React.createElement("div", { className: "designbase-figma-page-license__details" },
|
|
797
992
|
React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
798
993
|
React.createElement("div", { className: "designbase-figma-page-license__remaining" },
|
|
799
|
-
activationLimit - activationUsage,
|
|
800
|
-
|
|
994
|
+
Math.max(0, state.activationLimit - state.activationUsage),
|
|
995
|
+
' ',
|
|
801
996
|
resolveText(t, { key: 'license.activations_remaining' }, '활성'),
|
|
802
|
-
|
|
997
|
+
' ',
|
|
803
998
|
resolveText(t, { key: 'license.spots_remaining' }, '자리 남음')),
|
|
804
|
-
React.createElement("div", { className: "designbase-figma-page-license__usage" },
|
|
805
|
-
activationUsage,
|
|
999
|
+
React.createElement("div", { className: "designbase-figma-page-license__usage-count" },
|
|
1000
|
+
state.activationUsage,
|
|
806
1001
|
"/",
|
|
807
|
-
activationLimit)),
|
|
808
|
-
React.createElement(
|
|
809
|
-
? resolveText(t, { key: 'license.deactivating' }, '
|
|
1002
|
+
state.activationLimit)),
|
|
1003
|
+
React.createElement(react.Button, { onClick: deactivateLicense, variant: "tertiary", size: "s", disabled: isDeactivating }, isDeactivating
|
|
1004
|
+
? resolveText(t, { key: 'license.deactivating' }, '비활성화 중...')
|
|
810
1005
|
: resolveText(t, { key: 'license.deactivate' }, '라이선스 비활성화')))))),
|
|
811
|
-
!isPaid && (React.createElement(
|
|
812
|
-
React.createElement("div", { className: "designbase-figma-page-license__section
|
|
813
|
-
React.createElement("
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
1006
|
+
!isPaid && (React.createElement(React.Fragment, null,
|
|
1007
|
+
(enableAccountAuth || links.purchaseUrl || links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1008
|
+
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1009
|
+
React.createElement("h3", null, resolveText(t, { key: 'license.designbase_account' }, '디자인베이스 계정'))),
|
|
1010
|
+
React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(t, { key: 'license.designbase_account_hint' }, 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.')),
|
|
1011
|
+
React.createElement("div", { className: "designbase-figma-page-license__actions" },
|
|
1012
|
+
enableAccountAuth && (React.createElement(react.Button, { onClick: startDesignbaseAuth, variant: "primary", size: "m", disabled: isStartingAuth || isVerifying, fullWidth: true }, isStartingAuth
|
|
1013
|
+
? resolveText(t, { key: 'license.authenticating' }, '인증 중...')
|
|
1014
|
+
: resolveText(t, { key: 'license.login_with_designbase' }, '디자인베이스로 로그인'))),
|
|
1015
|
+
links.purchaseUrl && (React.createElement(react.Button, { onClick: () => openExternalUrl(links.purchaseUrl), variant: "secondary", size: "m", fullWidth: true },
|
|
1016
|
+
React.createElement("span", null, resolveText(t, { key: 'license.purchase_membership' }, '멤버십 구매')),
|
|
1017
|
+
React.createElement(icons.ExternalLinkIcon, { size: 16 }))),
|
|
1018
|
+
links.accountUrl && (React.createElement(react.Button, { onClick: () => openExternalUrl(links.accountUrl), variant: "tertiary", size: "s", fullWidth: true },
|
|
1019
|
+
React.createElement("span", null, resolveText(t, { key: 'license.manage_account' }, '계정·멤버십 관리')),
|
|
1020
|
+
React.createElement(icons.ExternalLinkIcon, { size: 16 })))))),
|
|
1021
|
+
showLicenseKeyInput && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
1022
|
+
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
1023
|
+
React.createElement("h3", null, resolveText(t, { key: 'license.enter_key' }, '라이선스 키 입력'))),
|
|
1024
|
+
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 }))))),
|
|
1025
|
+
links.helpUrl && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
|
|
1026
|
+
React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(t, { key: 'license.help_link' }, '라이선스·결제 도움말'))))),
|
|
1027
|
+
React.createElement(react.Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", "aria-label": "Close" },
|
|
819
1028
|
React.createElement(icons.CloseIcon, { size: 20 }))));
|
|
820
1029
|
};
|
|
821
1030
|
PageLicense.displayName = 'PageLicense';
|
|
@@ -839,7 +1048,7 @@ const PaymentStatusSection = ({ status, usageCount, activationLimit, activationU
|
|
|
839
1048
|
activationUsage,
|
|
840
1049
|
"/",
|
|
841
1050
|
activationLimit)),
|
|
842
|
-
React.createElement(
|
|
1051
|
+
React.createElement(react.Button, { onClick: onDeactivate, variant: "tertiary", size: "s", disabled: isDeactivating }, isDeactivating
|
|
843
1052
|
? resolveText(t, { key: 'payment.deactivating' }, '비활성화중...')
|
|
844
1053
|
: resolveText(t, { key: 'payment.deactivate_license' }, '라이선스 비활성화'))))));
|
|
845
1054
|
};
|
|
@@ -880,16 +1089,16 @@ const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.wor
|
|
|
880
1089
|
const displayStopText = resolveText(t, stopButtonText, '중지');
|
|
881
1090
|
const displayConfirmText = resolveText(t, confirmButtonText, '확인');
|
|
882
1091
|
const displayHelpText = resolveText(t, helpText);
|
|
883
|
-
return (React.createElement(
|
|
1092
|
+
return (React.createElement(react.Modal, { isOpen: isOpen, onClose: isCompleted ? onClose : undefined, title: displayTitle, size: "s", className: modalClasses, showCloseButton: false },
|
|
884
1093
|
React.createElement("div", { className: "designbase-figma-progress-modal__content" },
|
|
885
1094
|
React.createElement("div", { className: "designbase-figma-progress-modal__icon", "aria-hidden": "true" }, isCompleted ? (completeIcon || (React.createElement("div", { className: "designbase-figma-progress-modal__icon-success" },
|
|
886
1095
|
React.createElement(icons.CircleCheckFilledIcon, null)))) : (loadingIcon || (React.createElement("div", { className: "designbase-figma-progress-modal__icon-loading" },
|
|
887
|
-
React.createElement(
|
|
1096
|
+
React.createElement(react.Spinner, { size: "m" }))))),
|
|
888
1097
|
React.createElement("p", { className: "designbase-figma-progress-modal__message" }, displayMessage),
|
|
889
1098
|
React.createElement("div", { className: "designbase-figma-progress-modal__status" }, `${processedNodes} / ${totalNodes} (${progressPercentage.toFixed(1)}%)`),
|
|
890
|
-
React.createElement(
|
|
1099
|
+
React.createElement(react.Progressbar, { value: progressPercentage, size: "m", variant: isCompleted ? 'success' : 'primary', style: "animated", fullWidth: true }),
|
|
891
1100
|
displayHelpText && !isCompleted && (React.createElement("p", { className: "designbase-figma-progress-modal__help-text" }, displayHelpText)),
|
|
892
|
-
React.createElement("div", { className: "designbase-figma-progress-modal__actions" }, isCompleted ? (React.createElement(
|
|
1101
|
+
React.createElement("div", { className: "designbase-figma-progress-modal__actions" }, isCompleted ? (React.createElement(react.Button, { onPress: handleConfirm, variant: "primary", size: "m", fullWidth: true }, displayConfirmText)) : (React.createElement(react.Button, { onPress: handleStop, variant: "secondary", size: "m", fullWidth: true }, displayStopText))))));
|
|
893
1102
|
};
|
|
894
1103
|
ProgressModal.displayName = 'ProgressModal';
|
|
895
1104
|
|
|
@@ -1028,7 +1237,7 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1028
1237
|
const modalClasses = clsx('designbase-figma-settings-modal', className);
|
|
1029
1238
|
const displayTitle = resolveText(t, title, '목록 변경');
|
|
1030
1239
|
const displayDescription = resolveText(t, description, '드래그하여 순서를 변경하거나, 토글하여 카테고리를 숨길 수 있습니다.');
|
|
1031
|
-
return (React.createElement(
|
|
1240
|
+
return (React.createElement(react.Modal, { isOpen: isOpen, onClose: onClose, title: displayTitle, size: "m", className: modalClasses },
|
|
1032
1241
|
React.createElement("div", { className: "designbase-figma-settings-modal__content" },
|
|
1033
1242
|
displayDescription && (React.createElement("p", { className: "designbase-figma-settings-modal__description" }, displayDescription)),
|
|
1034
1243
|
React.createElement("ul", { className: "designbase-figma-settings-modal__list" }, tempCategories.map((category, index) => (React.createElement("li", { key: category.id, draggable: true, onDragStart: (e) => handleDragStart(e, index), onDragOver: handleDragOver, onDrop: (e) => handleDrop(e, index), onDragEnd: handleDragEnd, className: clsx('designbase-figma-settings-modal__item', {
|
|
@@ -1040,12 +1249,12 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1040
1249
|
React.createElement(icons.GripVerticalIcon, { size: 16 })),
|
|
1041
1250
|
category.icon && (React.createElement("span", { className: "designbase-figma-settings-modal__category-icon" }, category.icon)),
|
|
1042
1251
|
React.createElement("span", { className: "designbase-figma-settings-modal__category-title" }, resolveText(t, category.title))),
|
|
1043
|
-
React.createElement(
|
|
1252
|
+
React.createElement(react.Toggle, { checked: category.enabled, onChange: () => handleToggle(category.id), size: "s" })))))),
|
|
1044
1253
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer" },
|
|
1045
|
-
onReset && (React.createElement(
|
|
1254
|
+
onReset && (React.createElement(react.Button, { onPress: handleReset, variant: "tertiary", size: "s" }, resolveText(t, { key: 'settings.reset' }, '초기화'))),
|
|
1046
1255
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer-right" },
|
|
1047
|
-
React.createElement(
|
|
1048
|
-
React.createElement(
|
|
1256
|
+
React.createElement(react.Button, { onPress: handleCancel, variant: "tertiary", size: "s" }, resolveText(t, { key: 'settings.cancel' }, '취소')),
|
|
1257
|
+
React.createElement(react.Button, { onPress: handleSave, variant: "primary", size: "s" }, resolveText(t, { key: 'settings.save' }, '저장'))))));
|
|
1049
1258
|
};
|
|
1050
1259
|
SettingsModal.displayName = 'SettingsModal';
|
|
1051
1260
|
|
|
@@ -1088,12 +1297,13 @@ const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title =
|
|
|
1088
1297
|
React.createElement("div", { className: "designbase-figma-upgrade-banner__text-wrap" },
|
|
1089
1298
|
React.createElement("h3", { className: "designbase-figma-upgrade-banner__title" }, displayTitle),
|
|
1090
1299
|
React.createElement("p", { className: "designbase-figma-upgrade-banner__text" }, displayDescription)),
|
|
1091
|
-
variant === 'button' ? (React.createElement(
|
|
1300
|
+
variant === 'button' ? (React.createElement(react.Button, { onPress: onClick, variant: "primary", size: "m", disabled: isLoading }, displayButtonText)) : (React.createElement("div", { className: "designbase-figma-upgrade-banner__icon" },
|
|
1092
1301
|
React.createElement(icons.ChevronRightIcon, { size: 20 })))));
|
|
1093
|
-
return (React.createElement("div", { className: `designbase-figma-upgrade-banner designbase-figma-upgrade-banner--${variant} ${className || ''}` }, useGradient ? (React.createElement(
|
|
1302
|
+
return (React.createElement("div", { className: `designbase-figma-upgrade-banner designbase-figma-upgrade-banner--${variant} ${className || ''}` }, useGradient ? (React.createElement(react.RandomGradient, { scheme: gradientScheme, tone: gradientTone, animated: gradientAnimated, height: "100%", width: "100%", className: "designbase-figma-upgrade-banner__gradient-bg" }, bannerContent)) : (bannerContent)));
|
|
1094
1303
|
};
|
|
1095
1304
|
UpgradeBanner.displayName = 'UpgradeBanner';
|
|
1096
1305
|
|
|
1306
|
+
exports.DEFAULT_LICENSE_MESSAGE_TYPES = DEFAULT_LICENSE_MESSAGE_TYPES;
|
|
1097
1307
|
exports.DonationBadge = DonationBadge;
|
|
1098
1308
|
exports.FigmaContainer = FigmaContainer;
|
|
1099
1309
|
exports.FigmaFooter = FigmaFooter;
|
|
@@ -1113,18 +1323,20 @@ exports.PaymentStatusSection = PaymentStatusSection;
|
|
|
1113
1323
|
exports.PricingComparison = PricingComparison;
|
|
1114
1324
|
exports.ProgressModal = ProgressModal;
|
|
1115
1325
|
exports.ResizablePlugin = ResizablePlugin;
|
|
1326
|
+
exports.START_DESIGNBASE_AUTH_MESSAGE = START_DESIGNBASE_AUTH_MESSAGE;
|
|
1116
1327
|
exports.SettingsModal = SettingsModal;
|
|
1117
1328
|
exports.TitleDescription = TitleDescription;
|
|
1118
1329
|
exports.UpgradeBanner = UpgradeBanner;
|
|
1119
1330
|
exports.getActiveSection = getActiveSection;
|
|
1120
1331
|
exports.resolveText = resolveText;
|
|
1121
1332
|
exports.scrollToSection = scrollToSection;
|
|
1333
|
+
exports.useFigmaLicenseBridge = useFigmaLicenseBridge;
|
|
1122
1334
|
exports.useFigmaToast = useFigmaToast;
|
|
1123
1335
|
exports.useToast = useToast;
|
|
1124
|
-
Object.keys(
|
|
1336
|
+
Object.keys(react).forEach(function (k) {
|
|
1125
1337
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
1126
1338
|
enumerable: true,
|
|
1127
|
-
get: function () { return
|
|
1339
|
+
get: function () { return react[k]; }
|
|
1128
1340
|
});
|
|
1129
1341
|
});
|
|
1130
1342
|
//# sourceMappingURL=index.js.map
|