@designbasekorea/figma-ui 0.6.0 → 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 +374 -144
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +394 -161
- package/dist/index.js.map +1 -1
- package/package.json +14 -7
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
|
|
|
@@ -106,7 +116,9 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
|
|
|
106
116
|
const clipRef = React.useRef(null);
|
|
107
117
|
const innerRef = React.useRef(null);
|
|
108
118
|
const animatingRef = React.useRef(false);
|
|
119
|
+
const isInitialMountRef = React.useRef(true);
|
|
109
120
|
const [collapsed, setCollapsed] = React.useState(defaultCollapsed);
|
|
121
|
+
const [contentHidden, setContentHidden] = React.useState(defaultCollapsed);
|
|
110
122
|
const sectionStyle = marginBottom ? { marginBottom: `${marginBottom}px` } : undefined;
|
|
111
123
|
const classes = [
|
|
112
124
|
'designbase-figma-section',
|
|
@@ -119,38 +131,42 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
|
|
|
119
131
|
const toggle = () => {
|
|
120
132
|
if (!collapsible)
|
|
121
133
|
return;
|
|
122
|
-
setCollapsed(
|
|
123
|
-
const next = !
|
|
134
|
+
setCollapsed((prev) => {
|
|
135
|
+
const next = !prev;
|
|
124
136
|
onCollapseChange?.(next, dataCategory);
|
|
125
|
-
animate(next);
|
|
126
137
|
return next;
|
|
127
138
|
});
|
|
128
139
|
};
|
|
129
|
-
const animate = (toCollapsed) => {
|
|
140
|
+
const animate = (toCollapsed, onComplete) => {
|
|
130
141
|
const clip = clipRef.current;
|
|
131
142
|
const inner = innerRef.current;
|
|
132
143
|
if (!clip || !inner)
|
|
133
144
|
return;
|
|
134
145
|
const transitionMs = 250;
|
|
135
|
-
const setH = (h) => {
|
|
146
|
+
const setH = (h) => {
|
|
147
|
+
clip.style.height = h;
|
|
148
|
+
};
|
|
136
149
|
if (animatingRef.current) {
|
|
137
150
|
const current = `${clip.getBoundingClientRect().height}px`;
|
|
138
151
|
clip.style.transition = 'none';
|
|
139
152
|
setH(current);
|
|
140
|
-
clip.offsetHeight;
|
|
153
|
+
void clip.offsetHeight;
|
|
141
154
|
clip.style.transition = '';
|
|
142
155
|
}
|
|
143
156
|
animatingRef.current = true;
|
|
144
157
|
if (toCollapsed) {
|
|
158
|
+
inner.classList.remove('is-collapsed');
|
|
145
159
|
const start = `${inner.scrollHeight}px`;
|
|
146
160
|
setH(start);
|
|
147
|
-
clip.offsetHeight;
|
|
161
|
+
void clip.offsetHeight;
|
|
148
162
|
setH('0px');
|
|
149
163
|
}
|
|
150
164
|
else {
|
|
165
|
+
inner.classList.remove('is-collapsed');
|
|
166
|
+
const targetHeight = inner.scrollHeight;
|
|
151
167
|
setH('0px');
|
|
152
|
-
clip.offsetHeight;
|
|
153
|
-
setH(`${
|
|
168
|
+
void clip.offsetHeight;
|
|
169
|
+
setH(`${targetHeight}px`);
|
|
154
170
|
}
|
|
155
171
|
const onEnd = (e) => {
|
|
156
172
|
if (e.propertyName !== 'height')
|
|
@@ -160,6 +176,7 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
|
|
|
160
176
|
setH('auto');
|
|
161
177
|
}
|
|
162
178
|
animatingRef.current = false;
|
|
179
|
+
onComplete?.();
|
|
163
180
|
};
|
|
164
181
|
clip.addEventListener('transitionend', onEnd);
|
|
165
182
|
window.setTimeout(() => {
|
|
@@ -168,15 +185,29 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
|
|
|
168
185
|
if (!toCollapsed)
|
|
169
186
|
setH('auto');
|
|
170
187
|
animatingRef.current = false;
|
|
188
|
+
onComplete?.();
|
|
171
189
|
}, transitionMs + 50);
|
|
172
190
|
};
|
|
173
|
-
React.
|
|
174
|
-
|
|
175
|
-
const inner = innerRef.current;
|
|
176
|
-
if (!clip || !inner)
|
|
191
|
+
React.useLayoutEffect(() => {
|
|
192
|
+
if (!collapsible)
|
|
177
193
|
return;
|
|
178
|
-
|
|
179
|
-
|
|
194
|
+
if (isInitialMountRef.current) {
|
|
195
|
+
isInitialMountRef.current = false;
|
|
196
|
+
const clip = clipRef.current;
|
|
197
|
+
if (clip) {
|
|
198
|
+
clip.style.height = collapsed ? '0px' : 'auto';
|
|
199
|
+
}
|
|
200
|
+
setContentHidden(collapsed);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (collapsed) {
|
|
204
|
+
animate(true, () => setContentHidden(true));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
setContentHidden(false);
|
|
208
|
+
animate(false);
|
|
209
|
+
}
|
|
210
|
+
}, [collapsed, collapsible]);
|
|
180
211
|
React.useEffect(() => {
|
|
181
212
|
if (collapsed)
|
|
182
213
|
return;
|
|
@@ -202,15 +233,15 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
|
|
|
202
233
|
typeof title === 'string' || (typeof title === 'object' && 'key' in title)
|
|
203
234
|
? resolveText(t, title)
|
|
204
235
|
: title,
|
|
205
|
-
badge && (React.createElement(
|
|
206
|
-
React.createElement("div", { className: "designbase-figma-section__controls" },
|
|
236
|
+
badge && (React.createElement(react.Badge, { variant: "secondary", size: "s" }, badge)))),
|
|
237
|
+
React.createElement("div", { className: "designbase-figma-section__controls", onClick: (e) => e.stopPropagation() },
|
|
207
238
|
iconButton,
|
|
208
239
|
collapsible && (React.createElement("span", { className: `designbase-figma-section__collapse-icon ${collapsed ? 'designbase-figma-section__collapse-icon--collapsed' : ''}` },
|
|
209
240
|
React.createElement(icons.ChevronDownIcon, { size: 16 }))),
|
|
210
|
-
onToggle && (React.createElement(
|
|
241
|
+
onToggle && (React.createElement(react.Toggle, { checked: isEnabled, onChange: () => onToggle(dataCategory), size: "s" }))))),
|
|
211
242
|
React.createElement("div", { className: `designbase-figma-section__content ${!isEnabled ? 'designbase-figma-section__content--hidden' : ''}` },
|
|
212
243
|
React.createElement("div", { ref: clipRef, className: "designbase-figma-section__content-clip" },
|
|
213
|
-
React.createElement("div", { ref: innerRef, className: `designbase-figma-section__content-inner ${collapsible &&
|
|
244
|
+
React.createElement("div", { ref: innerRef, className: `designbase-figma-section__content-inner ${collapsible && contentHidden ? 'is-collapsed' : ''}` }, children)))));
|
|
214
245
|
};
|
|
215
246
|
FigmaSection.displayName = 'FigmaSection';
|
|
216
247
|
const scrollToSection = (category, headerHeight = 94) => {
|
|
@@ -364,7 +395,7 @@ const PaymentBadge = ({ isActive, onClick, isLoading = false, text, t = (key) =>
|
|
|
364
395
|
const getBadgeVariant = () => {
|
|
365
396
|
return isActive ? 'success' : 'secondary';
|
|
366
397
|
};
|
|
367
|
-
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()))));
|
|
368
399
|
};
|
|
369
400
|
PaymentBadge.displayName = 'PaymentBadge';
|
|
370
401
|
|
|
@@ -393,10 +424,15 @@ const LanguageSelector = ({ currentLanguage, languages = DEFAULT_LANGUAGES, onLa
|
|
|
393
424
|
const segmentOptions = languages.map((language) => ({
|
|
394
425
|
value: language.code,
|
|
395
426
|
label: resolveText(t, language.label),
|
|
396
|
-
disabled: false
|
|
427
|
+
disabled: false,
|
|
397
428
|
}));
|
|
398
429
|
return (React.createElement("div", { className: `designbase-figma-language-selector ${className || ''}` },
|
|
399
|
-
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" })));
|
|
400
436
|
};
|
|
401
437
|
LanguageSelector.displayName = 'LanguageSelector';
|
|
402
438
|
|
|
@@ -452,7 +488,7 @@ const LogoDropdown = ({ logoSrc, logoAlt = 'DesignBase', logoType = 'designbase'
|
|
|
452
488
|
return (React.createElement("img", { className: "designbase-figma-logo-dropdown__logo", src: logoSrc, alt: logoAlt, onClick: toggleDropdown }));
|
|
453
489
|
}
|
|
454
490
|
return (React.createElement("div", { className: "designbase-figma-logo-dropdown__logo", onClick: toggleDropdown },
|
|
455
|
-
React.createElement(
|
|
491
|
+
React.createElement(react.Logo, { type: logoType, size: logoSize, variant: "default" })));
|
|
456
492
|
};
|
|
457
493
|
return (React.createElement("div", { className: classes },
|
|
458
494
|
renderLogo(),
|
|
@@ -486,22 +522,29 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
|
|
|
486
522
|
React.createElement("div", { className: "designbase-figma-footer__left" },
|
|
487
523
|
React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, t: t }),
|
|
488
524
|
showLanguageSelector && (React.createElement(LanguageSelector, { currentLanguage: currentLanguage, languages: languages, onLanguageChange: onLanguageChange, size: "s" }))),
|
|
489
|
-
|
|
490
|
-
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(
|
|
491
|
-
React.createElement("span", { className: "designbase-figma-footer__usage-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
showDonation && (React.createElement("div", { className: "designbase-figma-footer__donation" },
|
|
500
|
-
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 })))),
|
|
501
535
|
children));
|
|
502
536
|
};
|
|
503
537
|
FigmaFooter.displayName = 'FigmaFooter';
|
|
504
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
|
+
};
|
|
505
548
|
const ToastContext = React.createContext(null);
|
|
506
549
|
const useToast = () => {
|
|
507
550
|
const context = React.useContext(ToastContext);
|
|
@@ -519,13 +562,13 @@ const FigmaToastProvider = ({ children, position = 'top-right', maxToasts = 5, }
|
|
|
519
562
|
id,
|
|
520
563
|
createdAt: Date.now(),
|
|
521
564
|
};
|
|
522
|
-
setToasts(prev => {
|
|
565
|
+
setToasts((prev) => {
|
|
523
566
|
const updated = [newToast, ...prev];
|
|
524
567
|
return updated.slice(0, maxToasts);
|
|
525
568
|
});
|
|
526
569
|
}, [maxToasts]);
|
|
527
570
|
const removeToast = React.useCallback((id) => {
|
|
528
|
-
setToasts(prev => prev.filter(toast => toast.id !== id));
|
|
571
|
+
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
|
529
572
|
}, []);
|
|
530
573
|
const showToast = React.useCallback((message, options = {}) => {
|
|
531
574
|
addToast({
|
|
@@ -544,17 +587,17 @@ const FigmaToastProvider = ({ children, position = 'top-right', maxToasts = 5, }
|
|
|
544
587
|
};
|
|
545
588
|
return (React.createElement(ToastContext.Provider, { value: contextValue },
|
|
546
589
|
children,
|
|
547
|
-
React.createElement(
|
|
590
|
+
React.createElement(FigmaToastStack, { toasts: toasts, onRemoveToast: removeToast, position: position, maxToasts: maxToasts })));
|
|
548
591
|
};
|
|
549
592
|
const FigmaToast = ({ message, isVisible, onClose, type = 'info', duration = 3000, className, }) => {
|
|
550
593
|
if (!isVisible)
|
|
551
594
|
return null;
|
|
552
595
|
return (React.createElement("div", { className: `figma-toast-fixed-wrap ${className || ''}` },
|
|
553
|
-
React.createElement(
|
|
596
|
+
React.createElement(react.Toast, { toastId: "figma-toast-simple", title: message, status: type, duration: duration, showProgress: false, showClose: true, onClose: onClose })));
|
|
554
597
|
};
|
|
555
598
|
const useFigmaToast = () => {
|
|
556
599
|
const [toast, setToast] = React.useState({ message: '', isVisible: false });
|
|
557
|
-
const showToast = React.useCallback((message,
|
|
600
|
+
const showToast = React.useCallback((message, _type = 'info') => {
|
|
558
601
|
setToast({ message, isVisible: true });
|
|
559
602
|
setTimeout(() => setToast({ message: '', isVisible: false }), 5000);
|
|
560
603
|
}, []);
|
|
@@ -585,8 +628,13 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
|
|
|
585
628
|
return (React.createElement("form", { className: `designbase-figma-form-with-submit ${className || ''}`, onSubmit: handleSubmit },
|
|
586
629
|
React.createElement("div", { className: "designbase-figma-form-with-submit__field" },
|
|
587
630
|
React.createElement("label", { className: "designbase-figma-form-with-submit__label" }, displayLabel),
|
|
588
|
-
React.createElement(
|
|
589
|
-
|
|
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)));
|
|
590
638
|
};
|
|
591
639
|
FormWithSubmit.displayName = 'FormWithSubmit';
|
|
592
640
|
|
|
@@ -599,7 +647,7 @@ const InteractionFeedback = ({ status = 'default', message, statusMessage, leftC
|
|
|
599
647
|
return (React.createElement("div", { className: feedbackClasses },
|
|
600
648
|
React.createElement("div", { className: "designbase-figma-interaction__content" },
|
|
601
649
|
React.createElement("div", { className: "designbase-figma-interaction__left" }, leftContent || (React.createElement("div", { className: "designbase-figma-interaction__message" },
|
|
602
|
-
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 })),
|
|
603
651
|
(message || status === 'loading') && (React.createElement("span", { className: "designbase-figma-interaction__text" }, resolveText(t, message || '불러오는 중입니다...'))),
|
|
604
652
|
statusMessage && (React.createElement("span", { className: "designbase-figma-interaction__status-text" }, resolveText(t, statusMessage)))))),
|
|
605
653
|
rightAction && (React.createElement("div", { className: "designbase-figma-interaction__right" }, rightAction)))));
|
|
@@ -638,18 +686,17 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
638
686
|
};
|
|
639
687
|
return (React.createElement("div", { className: `designbase-figma-pricing-comparison ${className || ''}` },
|
|
640
688
|
paymentType === 'subscription' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__billing-toggle" },
|
|
641
|
-
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: [
|
|
642
693
|
{
|
|
643
694
|
value: 'monthly',
|
|
644
695
|
label: t('monthlyBilling') || '월간 결제',
|
|
645
696
|
},
|
|
646
697
|
{
|
|
647
698
|
value: 'yearly',
|
|
648
|
-
label: (
|
|
649
|
-
t('yearlyBilling') || '연간 결제',
|
|
650
|
-
React.createElement("span", { className: "designbase-figma-pricing-comparison__discount-badge" },
|
|
651
|
-
getDiscountPercentage(),
|
|
652
|
-
"% \uC808\uC57D"))),
|
|
699
|
+
label: `${t('yearlyBilling') || '연간 결제'} (${getDiscountPercentage()}% 절약)`,
|
|
653
700
|
},
|
|
654
701
|
], size: "s" }))),
|
|
655
702
|
paymentType === 'lifetime' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__lifetime-info" },
|
|
@@ -677,124 +724,307 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
|
|
|
677
724
|
};
|
|
678
725
|
PricingComparison.displayName = 'PricingComparison';
|
|
679
726
|
|
|
680
|
-
|
|
681
|
-
|
|
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);
|
|
682
823
|
const [isDeactivating, setIsDeactivating] = React.useState(false);
|
|
683
|
-
const [
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
|
|
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
|
+
}, []);
|
|
689
843
|
React.useEffect(() => {
|
|
690
844
|
const handleMessage = (event) => {
|
|
691
|
-
const
|
|
692
|
-
if (
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
setActivationLimit(activationLimit);
|
|
699
|
-
if (activationUsage !== undefined)
|
|
700
|
-
setActivationUsage(activationUsage);
|
|
701
|
-
if (paymentStatus)
|
|
702
|
-
setPaymentStatus(paymentStatus);
|
|
703
|
-
if (usageCount !== undefined) {
|
|
704
|
-
setLocalUsageCount(usageCount);
|
|
705
|
-
setUsageCount(usageCount);
|
|
706
|
-
}
|
|
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));
|
|
707
852
|
}
|
|
708
|
-
if (type ===
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
if (success) {
|
|
713
|
-
|
|
714
|
-
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 });
|
|
715
859
|
}
|
|
716
860
|
}
|
|
717
|
-
if (type ===
|
|
861
|
+
if (type === messageTypes.deactivateResult) {
|
|
718
862
|
setIsDeactivating(false);
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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 });
|
|
728
882
|
}
|
|
729
883
|
}
|
|
730
884
|
};
|
|
731
885
|
window.addEventListener('message', handleMessage);
|
|
732
|
-
|
|
733
|
-
parent.postMessage({ pluginMessage: { type: 'initialize' } }, '*');
|
|
734
|
-
}
|
|
886
|
+
postPluginMessage({ type: messageTypes.initialize });
|
|
735
887
|
return () => window.removeEventListener('message', handleMessage);
|
|
736
|
-
}, [
|
|
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);
|
|
737
956
|
const handleLicenseSubmit = async (submittedLicenseKey) => {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
pluginMessage: {
|
|
742
|
-
type: 'verify-license',
|
|
743
|
-
licenseKey: submittedLicenseKey
|
|
744
|
-
}
|
|
745
|
-
}, '*');
|
|
957
|
+
if (onLicenseSubmit) {
|
|
958
|
+
await onLicenseSubmit(submittedLicenseKey);
|
|
959
|
+
return;
|
|
746
960
|
}
|
|
961
|
+
verifyLicense(submittedLicenseKey);
|
|
747
962
|
};
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
parent.postMessage({
|
|
752
|
-
pluginMessage: { type: 'deactivate-license' }
|
|
753
|
-
}, '*');
|
|
754
|
-
}
|
|
963
|
+
const handleLicenseKeyChange = (value) => {
|
|
964
|
+
setLicenseKeyDraft(value);
|
|
965
|
+
setLicenseKeyInput(value);
|
|
755
966
|
};
|
|
756
|
-
const isPaid = status === 'PAID';
|
|
757
967
|
return (React.createElement("div", { className: `designbase-figma-page-license ${className || ''}` },
|
|
758
968
|
React.createElement("div", { className: "designbase-figma-page-license__content" },
|
|
759
969
|
React.createElement("div", { className: "designbase-figma-page-license__header" },
|
|
760
970
|
React.createElement("div", { className: "designbase-figma-page-license__title" },
|
|
761
|
-
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))),
|
|
762
975
|
React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
|
|
763
976
|
? resolveText(t, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
|
|
764
|
-
: 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))),
|
|
765
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)),
|
|
766
981
|
isPaid && (React.createElement("div", { className: "designbase-figma-page-license__section" },
|
|
767
982
|
React.createElement("div", { className: "designbase-figma-page-license__section-header" },
|
|
768
983
|
React.createElement("h3", null, resolveText(t, { key: 'license.activated' }, '라이선스 활성화됨')),
|
|
769
|
-
React.createElement(
|
|
984
|
+
React.createElement(react.Button, { onClick: () => setShowDetails(!showDetails), variant: "tertiary", size: "s", iconOnly: true },
|
|
770
985
|
React.createElement(icons.MoreHorizontalIcon, { size: 16 }))),
|
|
771
|
-
React.createElement("div", { className: "designbase-figma-page-license__license-key" },
|
|
986
|
+
state.licenseKey && (React.createElement("div", { className: "designbase-figma-page-license__license-key" },
|
|
772
987
|
resolveText(t, { key: 'license.key_label' }, '라이선스 키'),
|
|
773
988
|
": ",
|
|
774
|
-
React.createElement("span", null, licenseKey)),
|
|
989
|
+
React.createElement("span", null, state.licenseKey))),
|
|
990
|
+
React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel),
|
|
775
991
|
showDetails && (React.createElement("div", { className: "designbase-figma-page-license__details" },
|
|
776
992
|
React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
|
|
777
993
|
React.createElement("div", { className: "designbase-figma-page-license__remaining" },
|
|
778
|
-
activationLimit - activationUsage,
|
|
779
|
-
|
|
994
|
+
Math.max(0, state.activationLimit - state.activationUsage),
|
|
995
|
+
' ',
|
|
780
996
|
resolveText(t, { key: 'license.activations_remaining' }, '활성'),
|
|
781
|
-
|
|
997
|
+
' ',
|
|
782
998
|
resolveText(t, { key: 'license.spots_remaining' }, '자리 남음')),
|
|
783
|
-
React.createElement("div", { className: "designbase-figma-page-license__usage" },
|
|
784
|
-
activationUsage,
|
|
999
|
+
React.createElement("div", { className: "designbase-figma-page-license__usage-count" },
|
|
1000
|
+
state.activationUsage,
|
|
785
1001
|
"/",
|
|
786
|
-
activationLimit)),
|
|
787
|
-
React.createElement(
|
|
788
|
-
? 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' }, '비활성화 중...')
|
|
789
1005
|
: resolveText(t, { key: 'license.deactivate' }, '라이선스 비활성화')))))),
|
|
790
|
-
!isPaid && (React.createElement(
|
|
791
|
-
React.createElement("div", { className: "designbase-figma-page-license__section
|
|
792
|
-
React.createElement("
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
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" },
|
|
798
1028
|
React.createElement(icons.CloseIcon, { size: 20 }))));
|
|
799
1029
|
};
|
|
800
1030
|
PageLicense.displayName = 'PageLicense';
|
|
@@ -818,7 +1048,7 @@ const PaymentStatusSection = ({ status, usageCount, activationLimit, activationU
|
|
|
818
1048
|
activationUsage,
|
|
819
1049
|
"/",
|
|
820
1050
|
activationLimit)),
|
|
821
|
-
React.createElement(
|
|
1051
|
+
React.createElement(react.Button, { onClick: onDeactivate, variant: "tertiary", size: "s", disabled: isDeactivating }, isDeactivating
|
|
822
1052
|
? resolveText(t, { key: 'payment.deactivating' }, '비활성화중...')
|
|
823
1053
|
: resolveText(t, { key: 'payment.deactivate_license' }, '라이선스 비활성화'))))));
|
|
824
1054
|
};
|
|
@@ -859,16 +1089,16 @@ const ProgressModal = ({ isOpen, onClose, progress, title = { key: 'progress.wor
|
|
|
859
1089
|
const displayStopText = resolveText(t, stopButtonText, '중지');
|
|
860
1090
|
const displayConfirmText = resolveText(t, confirmButtonText, '확인');
|
|
861
1091
|
const displayHelpText = resolveText(t, helpText);
|
|
862
|
-
return (React.createElement(
|
|
1092
|
+
return (React.createElement(react.Modal, { isOpen: isOpen, onClose: isCompleted ? onClose : undefined, title: displayTitle, size: "s", className: modalClasses, showCloseButton: false },
|
|
863
1093
|
React.createElement("div", { className: "designbase-figma-progress-modal__content" },
|
|
864
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" },
|
|
865
1095
|
React.createElement(icons.CircleCheckFilledIcon, null)))) : (loadingIcon || (React.createElement("div", { className: "designbase-figma-progress-modal__icon-loading" },
|
|
866
|
-
React.createElement(
|
|
1096
|
+
React.createElement(react.Spinner, { size: "m" }))))),
|
|
867
1097
|
React.createElement("p", { className: "designbase-figma-progress-modal__message" }, displayMessage),
|
|
868
1098
|
React.createElement("div", { className: "designbase-figma-progress-modal__status" }, `${processedNodes} / ${totalNodes} (${progressPercentage.toFixed(1)}%)`),
|
|
869
|
-
React.createElement(
|
|
1099
|
+
React.createElement(react.Progressbar, { value: progressPercentage, size: "m", variant: isCompleted ? 'success' : 'primary', style: "animated", fullWidth: true }),
|
|
870
1100
|
displayHelpText && !isCompleted && (React.createElement("p", { className: "designbase-figma-progress-modal__help-text" }, displayHelpText)),
|
|
871
|
-
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))))));
|
|
872
1102
|
};
|
|
873
1103
|
ProgressModal.displayName = 'ProgressModal';
|
|
874
1104
|
|
|
@@ -1007,7 +1237,7 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1007
1237
|
const modalClasses = clsx('designbase-figma-settings-modal', className);
|
|
1008
1238
|
const displayTitle = resolveText(t, title, '목록 변경');
|
|
1009
1239
|
const displayDescription = resolveText(t, description, '드래그하여 순서를 변경하거나, 토글하여 카테고리를 숨길 수 있습니다.');
|
|
1010
|
-
return (React.createElement(
|
|
1240
|
+
return (React.createElement(react.Modal, { isOpen: isOpen, onClose: onClose, title: displayTitle, size: "m", className: modalClasses },
|
|
1011
1241
|
React.createElement("div", { className: "designbase-figma-settings-modal__content" },
|
|
1012
1242
|
displayDescription && (React.createElement("p", { className: "designbase-figma-settings-modal__description" }, displayDescription)),
|
|
1013
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', {
|
|
@@ -1019,12 +1249,12 @@ const SettingsModal = ({ isOpen, onClose, categories: initialCategories, categor
|
|
|
1019
1249
|
React.createElement(icons.GripVerticalIcon, { size: 16 })),
|
|
1020
1250
|
category.icon && (React.createElement("span", { className: "designbase-figma-settings-modal__category-icon" }, category.icon)),
|
|
1021
1251
|
React.createElement("span", { className: "designbase-figma-settings-modal__category-title" }, resolveText(t, category.title))),
|
|
1022
|
-
React.createElement(
|
|
1252
|
+
React.createElement(react.Toggle, { checked: category.enabled, onChange: () => handleToggle(category.id), size: "s" })))))),
|
|
1023
1253
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer" },
|
|
1024
|
-
onReset && (React.createElement(
|
|
1254
|
+
onReset && (React.createElement(react.Button, { onPress: handleReset, variant: "tertiary", size: "s" }, resolveText(t, { key: 'settings.reset' }, '초기화'))),
|
|
1025
1255
|
React.createElement("div", { className: "designbase-figma-settings-modal__footer-right" },
|
|
1026
|
-
React.createElement(
|
|
1027
|
-
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' }, '저장'))))));
|
|
1028
1258
|
};
|
|
1029
1259
|
SettingsModal.displayName = 'SettingsModal';
|
|
1030
1260
|
|
|
@@ -1067,12 +1297,13 @@ const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title =
|
|
|
1067
1297
|
React.createElement("div", { className: "designbase-figma-upgrade-banner__text-wrap" },
|
|
1068
1298
|
React.createElement("h3", { className: "designbase-figma-upgrade-banner__title" }, displayTitle),
|
|
1069
1299
|
React.createElement("p", { className: "designbase-figma-upgrade-banner__text" }, displayDescription)),
|
|
1070
|
-
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" },
|
|
1071
1301
|
React.createElement(icons.ChevronRightIcon, { size: 20 })))));
|
|
1072
|
-
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)));
|
|
1073
1303
|
};
|
|
1074
1304
|
UpgradeBanner.displayName = 'UpgradeBanner';
|
|
1075
1305
|
|
|
1306
|
+
exports.DEFAULT_LICENSE_MESSAGE_TYPES = DEFAULT_LICENSE_MESSAGE_TYPES;
|
|
1076
1307
|
exports.DonationBadge = DonationBadge;
|
|
1077
1308
|
exports.FigmaContainer = FigmaContainer;
|
|
1078
1309
|
exports.FigmaFooter = FigmaFooter;
|
|
@@ -1092,18 +1323,20 @@ exports.PaymentStatusSection = PaymentStatusSection;
|
|
|
1092
1323
|
exports.PricingComparison = PricingComparison;
|
|
1093
1324
|
exports.ProgressModal = ProgressModal;
|
|
1094
1325
|
exports.ResizablePlugin = ResizablePlugin;
|
|
1326
|
+
exports.START_DESIGNBASE_AUTH_MESSAGE = START_DESIGNBASE_AUTH_MESSAGE;
|
|
1095
1327
|
exports.SettingsModal = SettingsModal;
|
|
1096
1328
|
exports.TitleDescription = TitleDescription;
|
|
1097
1329
|
exports.UpgradeBanner = UpgradeBanner;
|
|
1098
1330
|
exports.getActiveSection = getActiveSection;
|
|
1099
1331
|
exports.resolveText = resolveText;
|
|
1100
1332
|
exports.scrollToSection = scrollToSection;
|
|
1333
|
+
exports.useFigmaLicenseBridge = useFigmaLicenseBridge;
|
|
1101
1334
|
exports.useFigmaToast = useFigmaToast;
|
|
1102
1335
|
exports.useToast = useToast;
|
|
1103
|
-
Object.keys(
|
|
1336
|
+
Object.keys(react).forEach(function (k) {
|
|
1104
1337
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
1105
1338
|
enumerable: true,
|
|
1106
|
-
get: function () { return
|
|
1339
|
+
get: function () { return react[k]; }
|
|
1107
1340
|
});
|
|
1108
1341
|
});
|
|
1109
1342
|
//# sourceMappingURL=index.js.map
|