@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/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
- import React, { useRef, useState, useEffect, createContext, useContext, useCallback } from 'react';
2
- import { HeartFilledIcon, CoffeeFilledIcon, ChevronLeftIcon, MoreHorizontalIcon, ChevronDownIcon, AppWindowIcon, YoutubeIcon, InstagramIcon, FigmaIcon, MailIcon, ExternalLinkIcon, CloseIcon, CircleCheckFilledIcon, ResizableIcon, GripVerticalIcon, ChevronRightIcon } from '@designbasekorea/icons';
3
- import { Button, Dropdown, Badge, Toggle, Spinner, SegmentControl, Logo, ToastContainer, Toast, Input, Modal, Progressbar, RandomGradient } from '@designbasekorea/ui';
4
- export * from '@designbasekorea/ui';
1
+ import React, { useRef, useState, useLayoutEffect, useEffect, createContext, useContext, useCallback, useMemo } from 'react';
2
+ import { Button, Dropdown, Badge, Toggle, Spinner, SegmentControl, Logo, Toast, Input, Modal, Progressbar, RandomGradient } from '@designbasekorea/ui-wc/react';
3
+ export * from '@designbasekorea/ui-wc/react';
4
+ import { ChevronDownIcon, AppWindowIcon, YoutubeIcon, InstagramIcon, FigmaIcon, MailIcon, ExternalLinkIcon, MoreHorizontalIcon, CloseIcon, CircleCheckFilledIcon, ResizableIcon, GripVerticalIcon, ChevronRightIcon } from '@designbasekorea/icons';
5
5
 
6
6
  function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
7
7
 
@@ -11,10 +11,20 @@ function resolveText(t, input, fallback) {
11
11
  if (typeof input === 'string') {
12
12
  return input;
13
13
  }
14
- return t ? t(input.key, input.values) : input.key;
14
+ if (t) {
15
+ const translated = t(input.key, input.values);
16
+ if (translated && translated !== input.key) {
17
+ return translated;
18
+ }
19
+ }
20
+ return fallback ?? input.key;
15
21
  }
16
22
 
17
- const DonationBadge = ({ donationUrl = 'https://buymeacoffee.com/designbase', text = { key: 'donation.buy_me_a_coffee' }, iconType = 'heart', size = 's', variant = 'tertiary', fullWidth = false, disabled = false, showPrompt = false, promptText = { key: 'donation.prompt' }, className, onClick, t }) => {
23
+ const DONATION_ICON_NAMES = {
24
+ heart: 'star-filled',
25
+ coffee: 'cart',
26
+ };
27
+ 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 }) => {
18
28
  const handleClick = () => {
19
29
  if (onClick) {
20
30
  onClick();
@@ -23,15 +33,12 @@ const DonationBadge = ({ donationUrl = 'https://buymeacoffee.com/designbase', te
23
33
  window.open(donationUrl, '_blank', 'noopener,noreferrer');
24
34
  }
25
35
  };
26
- const Icon = iconType === 'heart' ? HeartFilledIcon : CoffeeFilledIcon;
27
36
  const displayText = resolveText(t, text, 'Buy me a coffee');
28
37
  const displayPromptText = resolveText(t, promptText, '도움이 되었다면 커피 한 잔 사주세요!');
29
38
  const buttonSize = size;
30
39
  return (React.createElement("div", { className: clsx('designbase-figma-donation-badge-container', className) },
31
- showPrompt && (React.createElement("div", { className: "designbase-figma-donation-badge__prompt" }, displayPromptText)),
32
- React.createElement(Button, { variant: variant, size: buttonSize, fullWidth: fullWidth, disabled: disabled, onPress: handleClick, startIcon: Icon, className: clsx('designbase-figma-donation-badge', `designbase-figma-donation-badge--${iconType}`), "aria-label": displayText, style: {
33
- '--designbase-figma-donation-badge-icon-color': 'var(--db-brand-primary)'
34
- } }, displayText)));
40
+ showPrompt && !iconOnly && (React.createElement("div", { className: "designbase-figma-donation-badge__prompt" }, displayPromptText)),
41
+ React.createElement(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)));
35
42
  };
36
43
  DonationBadge.displayName = 'DonationBadge';
37
44
 
@@ -69,10 +76,11 @@ const FigmaHeader = ({ children, actions = [], searchBar, sticky = true, classNa
69
76
  'designbase-figma-header--with-search': !!searchBar,
70
77
  'designbase-figma-header--with-actions': actions.length > 0,
71
78
  }, className);
79
+ const hasToolbar = !!children || actions.length > 0;
72
80
  return (React.createElement("header", { className: classes },
73
- React.createElement("div", { className: "designbase-figma-header__container" },
81
+ hasToolbar && (React.createElement("div", { className: "designbase-figma-header__container" },
74
82
  children && (React.createElement("div", { className: "designbase-figma-header__center" }, children)),
75
- actions.length > 0 && (React.createElement("div", { className: "designbase-figma-header__right" }, actions.map((action, index) => (React.createElement(Button, { key: index, variant: "tertiary", size: "s", iconOnly: true, "aria-label": `액션 ${index + 1}` }, action)))))),
83
+ actions.length > 0 && (React.createElement("div", { className: "designbase-figma-header__right" }, actions.map((action, index) => (React.createElement(Button, { key: `${action.startIcon}-${index}`, variant: "tertiary", size: "s", iconOnly: true, startIcon: action.startIcon, "aria-label": action.ariaLabel, onPress: action.onPress }))))))),
76
84
  searchBar && (React.createElement("div", { className: "designbase-figma-header__search-container" }, searchBar))));
77
85
  };
78
86
  FigmaHeader.displayName = 'FigmaHeader';
@@ -81,22 +89,24 @@ const FigmaPageHead = ({ onBack, title, description, actions = [], moreActions =
81
89
  const classes = clsx('designbase-figma-page-head', className);
82
90
  const displayTitle = resolveText(t, title);
83
91
  const displayDescription = description ? resolveText(t, description) : undefined;
84
- const dropdownItems = moreActions.map(action => ({
92
+ const dropdownItems = moreActions.map((action) => ({
85
93
  id: action.id,
86
94
  label: resolveText(t, action.label),
87
- onClick: action.onClick
88
95
  }));
96
+ const handleDropdownChange = (event) => {
97
+ const actionId = event.detail?.id ?? event.detail?.value;
98
+ const action = moreActions.find((item) => item.id === actionId);
99
+ action?.onClick();
100
+ };
89
101
  return (React.createElement("div", { className: classes },
90
102
  React.createElement("div", { className: "designbase-figma-page-head__left" },
91
- React.createElement(Button, { variant: "tertiary", size: "s", iconOnly: true, onPress: onBack, "aria-label": "\uB4A4\uB85C\uAC00\uAE30" },
92
- React.createElement(ChevronLeftIcon, { size: 14 })),
103
+ React.createElement(Button, { variant: "tertiary", size: "s", iconOnly: true, startIcon: "chevron-left", onPress: onBack, "aria-label": "\uB4A4\uB85C\uAC00\uAE30" }),
93
104
  React.createElement("div", { className: "designbase-figma-page-head__titles" },
94
105
  React.createElement("h2", null, displayTitle),
95
106
  displayDescription && React.createElement("p", null, displayDescription))),
96
107
  React.createElement("div", { className: "designbase-figma-page-head__actions" },
97
108
  actions.map((action, index) => (React.createElement(React.Fragment, { key: index }, action))),
98
- moreActions.length > 0 && (React.createElement(Dropdown, { trigger: React.createElement("button", { type: "button", className: "designbase-figma-page-head__more-button", "aria-label": "\uB354\uBCF4\uAE30" },
99
- React.createElement(MoreHorizontalIcon, { size: 16 })), items: dropdownItems, placement: "bottom-right", size: "s" })))));
109
+ moreActions.length > 0 && (React.createElement(Dropdown, { items: dropdownItems, triggerIcon: "more-horizontal", iconOnly: true, triggerVariant: "tertiary", placement: "bottom-right", size: "s", onChange: handleDropdownChange })))));
100
110
  };
101
111
  FigmaPageHead.displayName = 'FigmaPageHead';
102
112
 
@@ -105,7 +115,9 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
105
115
  const clipRef = useRef(null);
106
116
  const innerRef = useRef(null);
107
117
  const animatingRef = useRef(false);
118
+ const isInitialMountRef = useRef(true);
108
119
  const [collapsed, setCollapsed] = useState(defaultCollapsed);
120
+ const [contentHidden, setContentHidden] = useState(defaultCollapsed);
109
121
  const sectionStyle = marginBottom ? { marginBottom: `${marginBottom}px` } : undefined;
110
122
  const classes = [
111
123
  'designbase-figma-section',
@@ -118,38 +130,42 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
118
130
  const toggle = () => {
119
131
  if (!collapsible)
120
132
  return;
121
- setCollapsed(v => {
122
- const next = !v;
133
+ setCollapsed((prev) => {
134
+ const next = !prev;
123
135
  onCollapseChange?.(next, dataCategory);
124
- animate(next);
125
136
  return next;
126
137
  });
127
138
  };
128
- const animate = (toCollapsed) => {
139
+ const animate = (toCollapsed, onComplete) => {
129
140
  const clip = clipRef.current;
130
141
  const inner = innerRef.current;
131
142
  if (!clip || !inner)
132
143
  return;
133
144
  const transitionMs = 250;
134
- const setH = (h) => { clip.style.height = h; };
145
+ const setH = (h) => {
146
+ clip.style.height = h;
147
+ };
135
148
  if (animatingRef.current) {
136
149
  const current = `${clip.getBoundingClientRect().height}px`;
137
150
  clip.style.transition = 'none';
138
151
  setH(current);
139
- clip.offsetHeight;
152
+ void clip.offsetHeight;
140
153
  clip.style.transition = '';
141
154
  }
142
155
  animatingRef.current = true;
143
156
  if (toCollapsed) {
157
+ inner.classList.remove('is-collapsed');
144
158
  const start = `${inner.scrollHeight}px`;
145
159
  setH(start);
146
- clip.offsetHeight;
160
+ void clip.offsetHeight;
147
161
  setH('0px');
148
162
  }
149
163
  else {
164
+ inner.classList.remove('is-collapsed');
165
+ const targetHeight = inner.scrollHeight;
150
166
  setH('0px');
151
- clip.offsetHeight;
152
- setH(`${inner.scrollHeight}px`);
167
+ void clip.offsetHeight;
168
+ setH(`${targetHeight}px`);
153
169
  }
154
170
  const onEnd = (e) => {
155
171
  if (e.propertyName !== 'height')
@@ -159,6 +175,7 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
159
175
  setH('auto');
160
176
  }
161
177
  animatingRef.current = false;
178
+ onComplete?.();
162
179
  };
163
180
  clip.addEventListener('transitionend', onEnd);
164
181
  window.setTimeout(() => {
@@ -167,15 +184,29 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
167
184
  if (!toCollapsed)
168
185
  setH('auto');
169
186
  animatingRef.current = false;
187
+ onComplete?.();
170
188
  }, transitionMs + 50);
171
189
  };
172
- useEffect(() => {
173
- const clip = clipRef.current;
174
- const inner = innerRef.current;
175
- if (!clip || !inner)
190
+ useLayoutEffect(() => {
191
+ if (!collapsible)
176
192
  return;
177
- clip.style.height = collapsed ? '0px' : 'auto';
178
- }, []);
193
+ if (isInitialMountRef.current) {
194
+ isInitialMountRef.current = false;
195
+ const clip = clipRef.current;
196
+ if (clip) {
197
+ clip.style.height = collapsed ? '0px' : 'auto';
198
+ }
199
+ setContentHidden(collapsed);
200
+ return;
201
+ }
202
+ if (collapsed) {
203
+ animate(true, () => setContentHidden(true));
204
+ }
205
+ else {
206
+ setContentHidden(false);
207
+ animate(false);
208
+ }
209
+ }, [collapsed, collapsible]);
179
210
  useEffect(() => {
180
211
  if (collapsed)
181
212
  return;
@@ -202,14 +233,14 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
202
233
  ? resolveText(t, title)
203
234
  : title,
204
235
  badge && (React.createElement(Badge, { variant: "secondary", size: "s" }, badge)))),
205
- React.createElement("div", { className: "designbase-figma-section__controls" },
236
+ React.createElement("div", { className: "designbase-figma-section__controls", onClick: (e) => e.stopPropagation() },
206
237
  iconButton,
207
238
  collapsible && (React.createElement("span", { className: `designbase-figma-section__collapse-icon ${collapsed ? 'designbase-figma-section__collapse-icon--collapsed' : ''}` },
208
239
  React.createElement(ChevronDownIcon, { size: 16 }))),
209
240
  onToggle && (React.createElement(Toggle, { checked: isEnabled, onChange: () => onToggle(dataCategory), size: "s" }))))),
210
241
  React.createElement("div", { className: `designbase-figma-section__content ${!isEnabled ? 'designbase-figma-section__content--hidden' : ''}` },
211
242
  React.createElement("div", { ref: clipRef, className: "designbase-figma-section__content-clip" },
212
- React.createElement("div", { ref: innerRef, className: `designbase-figma-section__content-inner ${collapsible && collapsed ? 'is-collapsed' : ''}` }, children)))));
243
+ React.createElement("div", { ref: innerRef, className: `designbase-figma-section__content-inner ${collapsible && contentHidden ? 'is-collapsed' : ''}` }, children)))));
213
244
  };
214
245
  FigmaSection.displayName = 'FigmaSection';
215
246
  const scrollToSection = (category, headerHeight = 94) => {
@@ -392,10 +423,15 @@ const LanguageSelector = ({ currentLanguage, languages = DEFAULT_LANGUAGES, onLa
392
423
  const segmentOptions = languages.map((language) => ({
393
424
  value: language.code,
394
425
  label: resolveText(t, language.label),
395
- disabled: false
426
+ disabled: false,
396
427
  }));
397
428
  return (React.createElement("div", { className: `designbase-figma-language-selector ${className || ''}` },
398
- React.createElement(SegmentControl, { options: segmentOptions, value: activeLanguage, onChange: handleLanguageChange, size: size, className: "designbase-figma-language-selector__segment" })));
429
+ React.createElement(SegmentControl, { options: segmentOptions, value: activeLanguage, onChange: (event) => {
430
+ const value = event.detail?.value;
431
+ if (value) {
432
+ handleLanguageChange(value);
433
+ }
434
+ }, size: size, className: "designbase-figma-language-selector__segment" })));
399
435
  };
400
436
  LanguageSelector.displayName = 'LanguageSelector';
401
437
 
@@ -485,22 +521,29 @@ const FigmaFooter = ({ onLicensePageClick, paymentStatus = 'FREE', usageCount =
485
521
  React.createElement("div", { className: "designbase-figma-footer__left" },
486
522
  React.createElement(LogoDropdown, { logoSrc: logoSrc, logoAlt: logoAlt, logoType: logoType, logoSize: logoSize, links: logoLinks, t: t }),
487
523
  showLanguageSelector && (React.createElement(LanguageSelector, { currentLanguage: currentLanguage, languages: languages, onLanguageChange: onLanguageChange, size: "s" }))),
488
- showPaymentStatus && (React.createElement("div", { className: "designbase-figma-footer__payment-states" },
489
- 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(React.Fragment, null,
490
- React.createElement("span", { className: "designbase-figma-footer__usage-info designbase-figma-footer__usage-info--tooltip", title: t('resetsDaily') },
491
- React.createElement("span", { className: "designbase-figma-footer__usage-count" }, usageCount),
492
- React.createElement("span", { className: "designbase-figma-footer__max-daily-usage" },
493
- "/",
494
- maxDailyUsage,
495
- " ",
496
- t('perDay'))))))),
497
- resolvedShowPaymentBadge && (React.createElement(PaymentBadge, { isActive: isActive, onClick: isBeta ? undefined : onLicensePageClick, isLoading: isLoading, text: isBeta ? (t('betaStatus') || 'BETA') : undefined, t: t })))),
498
- showDonation && (React.createElement("div", { className: "designbase-figma-footer__donation" },
499
- React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", showPrompt: showDonationText && !isActive, promptText: donationPromptText, t: t })))),
524
+ React.createElement("div", { className: "designbase-figma-footer__right" },
525
+ 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') },
526
+ React.createElement("span", { className: "designbase-figma-footer__usage-count" }, usageCount),
527
+ React.createElement("span", { className: "designbase-figma-footer__max-daily-usage" },
528
+ "/",
529
+ maxDailyUsage,
530
+ " ",
531
+ t('perDay')))))),
532
+ showPaymentStatus && resolvedShowPaymentBadge && (React.createElement(PaymentBadge, { isActive: isActive, onClick: isBeta ? undefined : onLicensePageClick, isLoading: isLoading, text: isBeta ? (t('betaStatus') || 'BETA') : undefined, t: t })),
533
+ showDonation && (React.createElement(DonationBadge, { donationUrl: donationUrl, text: donationText, iconType: "heart", size: "s", iconOnly: true, showPrompt: false, t: t })))),
500
534
  children));
501
535
  };
502
536
  FigmaFooter.displayName = 'FigmaFooter';
503
537
 
538
+ const FigmaToastStack = ({ toasts, position, maxToasts, onRemoveToast, }) => {
539
+ const visibleToasts = [...toasts]
540
+ .sort((a, b) => b.createdAt - a.createdAt)
541
+ .slice(0, maxToasts);
542
+ if (visibleToasts.length === 0)
543
+ return null;
544
+ 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" },
545
+ React.createElement(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) }))))));
546
+ };
504
547
  const ToastContext = createContext(null);
505
548
  const useToast = () => {
506
549
  const context = useContext(ToastContext);
@@ -518,13 +561,13 @@ const FigmaToastProvider = ({ children, position = 'top-right', maxToasts = 5, }
518
561
  id,
519
562
  createdAt: Date.now(),
520
563
  };
521
- setToasts(prev => {
564
+ setToasts((prev) => {
522
565
  const updated = [newToast, ...prev];
523
566
  return updated.slice(0, maxToasts);
524
567
  });
525
568
  }, [maxToasts]);
526
569
  const removeToast = useCallback((id) => {
527
- setToasts(prev => prev.filter(toast => toast.id !== id));
570
+ setToasts((prev) => prev.filter((toast) => toast.id !== id));
528
571
  }, []);
529
572
  const showToast = useCallback((message, options = {}) => {
530
573
  addToast({
@@ -543,17 +586,17 @@ const FigmaToastProvider = ({ children, position = 'top-right', maxToasts = 5, }
543
586
  };
544
587
  return (React.createElement(ToastContext.Provider, { value: contextValue },
545
588
  children,
546
- React.createElement(ToastContainer, { toasts: toasts, onRemoveToast: removeToast, position: position, maxToasts: maxToasts })));
589
+ React.createElement(FigmaToastStack, { toasts: toasts, onRemoveToast: removeToast, position: position, maxToasts: maxToasts })));
547
590
  };
548
591
  const FigmaToast = ({ message, isVisible, onClose, type = 'info', duration = 3000, className, }) => {
549
592
  if (!isVisible)
550
593
  return null;
551
594
  return (React.createElement("div", { className: `figma-toast-fixed-wrap ${className || ''}` },
552
- React.createElement(Toast, { id: "figma-toast-simple", title: message, status: type, duration: duration, showProgress: false, showCloseButton: true, onClose: onClose, position: "top-right" })));
595
+ React.createElement(Toast, { toastId: "figma-toast-simple", title: message, status: type, duration: duration, showProgress: false, showClose: true, onClose: onClose })));
553
596
  };
554
597
  const useFigmaToast = () => {
555
598
  const [toast, setToast] = useState({ message: '', isVisible: false });
556
- const showToast = useCallback((message, type = 'info') => {
599
+ const showToast = useCallback((message, _type = 'info') => {
557
600
  setToast({ message, isVisible: true });
558
601
  setTimeout(() => setToast({ message: '', isVisible: false }), 5000);
559
602
  }, []);
@@ -584,7 +627,12 @@ const FormWithSubmit = ({ onLicenseSubmit, disabled = false, isSubmitting = fals
584
627
  return (React.createElement("form", { className: `designbase-figma-form-with-submit ${className || ''}`, onSubmit: handleSubmit },
585
628
  React.createElement("div", { className: "designbase-figma-form-with-submit__field" },
586
629
  React.createElement("label", { className: "designbase-figma-form-with-submit__label" }, displayLabel),
587
- React.createElement(Input, { value: inputValue, onChange: handleChange, placeholder: displayPlaceholder, helperText: displayHelperText, disabled: disabled || isSubmitting, size: "m" })),
630
+ React.createElement(Input, { value: inputValue, onChange: (event) => {
631
+ const value = event.detail?.value;
632
+ if (value !== undefined) {
633
+ handleChange(value);
634
+ }
635
+ }, placeholder: displayPlaceholder, helperText: displayHelperText, disabled: disabled || isSubmitting, size: "m" })),
588
636
  React.createElement(Button, { type: "submit", variant: "primary", size: "m", loading: isSubmitting, disabled: !inputValue.trim() || isSubmitting || disabled, fullWidth: true }, isSubmitting ? displaySubmittingText : displaySubmitText)));
589
637
  };
590
638
  FormWithSubmit.displayName = 'FormWithSubmit';
@@ -637,18 +685,17 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
637
685
  };
638
686
  return (React.createElement("div", { className: `designbase-figma-pricing-comparison ${className || ''}` },
639
687
  paymentType === 'subscription' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__billing-toggle" },
640
- React.createElement(SegmentControl, { value: isYearly ? 'yearly' : 'monthly', onChange: (value) => setIsYearly(value === 'yearly'), options: [
688
+ React.createElement(SegmentControl, { value: isYearly ? 'yearly' : 'monthly', onChange: (event) => {
689
+ const value = event.detail?.value;
690
+ setIsYearly(value === 'yearly');
691
+ }, options: [
641
692
  {
642
693
  value: 'monthly',
643
694
  label: t('monthlyBilling') || '월간 결제',
644
695
  },
645
696
  {
646
697
  value: 'yearly',
647
- label: (React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
648
- t('yearlyBilling') || '연간 결제',
649
- React.createElement("span", { className: "designbase-figma-pricing-comparison__discount-badge" },
650
- getDiscountPercentage(),
651
- "% \uC808\uC57D"))),
698
+ label: `${t('yearlyBilling') || '연간 결제'} (${getDiscountPercentage()}% 절약)`,
652
699
  },
653
700
  ], size: "s" }))),
654
701
  paymentType === 'lifetime' && (React.createElement("div", { className: "designbase-figma-pricing-comparison__lifetime-info" },
@@ -676,123 +723,306 @@ const PricingComparison = ({ features = defaultFeatures, pricing = defaultPricin
676
723
  };
677
724
  PricingComparison.displayName = 'PricingComparison';
678
725
 
679
- const PageLicense = ({ status: initialStatus, onClose, usageCount: initialUsageCount = 0, onLicenseSubmit, licenseKey: initialLicenseKey = '', setPaymentStatus, setUsageCount, setShowLicensePage, paymentPageUrl, pricingFeatures, pricing, paymentType = 'subscription', t, className, }) => {
680
- const [isSubmitting, setIsSubmitting] = useState(false);
726
+ function postPluginMessage(message) {
727
+ if (typeof parent === 'undefined') {
728
+ return;
729
+ }
730
+ parent.postMessage({ pluginMessage: message }, '*');
731
+ }
732
+ function openExternalUrl(url) {
733
+ if (!url)
734
+ return;
735
+ postPluginMessage({ type: 'open-external-url', url });
736
+ if (typeof window !== 'undefined') {
737
+ window.open(url, '_blank', 'noopener,noreferrer');
738
+ }
739
+ }
740
+
741
+ const DEFAULT_LICENSE_MESSAGE_TYPES = {
742
+ initialize: 'initialize',
743
+ verifyLicense: 'verify-license',
744
+ deactivateLicense: 'deactivate-license',
745
+ updateStatus: 'update-plugin-status',
746
+ verifyResult: 'license-verification-result',
747
+ deactivateResult: 'license-deactivation-result',
748
+ };
749
+ const START_DESIGNBASE_AUTH_MESSAGE = 'start-designbase-auth';
750
+ const INITIAL_LICENSE_PAGE_STATE = {
751
+ paymentStatus: 'FREE',
752
+ licenseKey: '',
753
+ planTier: 'FREE',
754
+ hasLicenseKey: false,
755
+ isLicenseRegistered: false,
756
+ activationLimit: 0,
757
+ activationUsage: 0,
758
+ usageCount: 0,
759
+ remainingUsage: 0,
760
+ usageUsed: 0,
761
+ usageLimit: 0,
762
+ usageReset: 'none',
763
+ canUseFeature: true,
764
+ };
765
+
766
+ function readString(data, keys) {
767
+ for (const key of keys) {
768
+ const value = data[key];
769
+ if (typeof value === 'string') {
770
+ return value;
771
+ }
772
+ }
773
+ return '';
774
+ }
775
+ function readNumber(data, keys) {
776
+ for (const key of keys) {
777
+ const value = data[key];
778
+ if (typeof value === 'number' && Number.isFinite(value)) {
779
+ return value;
780
+ }
781
+ }
782
+ return undefined;
783
+ }
784
+ function readBoolean(data, keys) {
785
+ for (const key of keys) {
786
+ const value = data[key];
787
+ if (typeof value === 'boolean') {
788
+ return value;
789
+ }
790
+ }
791
+ return undefined;
792
+ }
793
+ function parseLicenseMessage(data) {
794
+ const paymentStatus = readString(data, ['paymentStatus', 'status']);
795
+ const usageLimitRaw = data.usageLimit;
796
+ return {
797
+ ...(paymentStatus ? { paymentStatus } : {}),
798
+ licenseKey: readString(data, ['licenseKey']) || undefined,
799
+ planTier: readString(data, ['planTier']) || undefined,
800
+ hasLicenseKey: readBoolean(data, ['hasLicenseKey']),
801
+ isLicenseRegistered: readBoolean(data, ['isLicenseRegistered']),
802
+ activationLimit: readNumber(data, ['activationLimit']),
803
+ activationUsage: readNumber(data, ['activationUsage']),
804
+ usageCount: readNumber(data, ['usageCount']),
805
+ remainingUsage: readNumber(data, ['remainingUsage']),
806
+ usageUsed: readNumber(data, ['usageUsed']),
807
+ usageLimit: usageLimitRaw === 'unlimited' ? 'unlimited' : readNumber(data, ['usageLimit']),
808
+ usageReset: readString(data, ['usageReset']) || undefined,
809
+ canUseFeature: readBoolean(data, ['canUseFeature']),
810
+ usageReason: readString(data, ['usageReason']) || undefined,
811
+ lastMessage: readString(data, ['message']) || undefined,
812
+ lastErrorCode: readString(data, ['errorCode']) || undefined,
813
+ };
814
+ }
815
+ function useFigmaLicenseBridge(options = {}) {
816
+ const messageTypes = useMemo(() => ({ ...DEFAULT_LICENSE_MESSAGE_TYPES, ...options.messageTypes }), [options.messageTypes]);
817
+ const [state, setState] = useState({
818
+ ...INITIAL_LICENSE_PAGE_STATE,
819
+ ...options.initialState,
820
+ });
821
+ const [isVerifying, setIsVerifying] = useState(false);
681
822
  const [isDeactivating, setIsDeactivating] = useState(false);
682
- const [licenseKey, setLicenseKey] = useState(initialLicenseKey);
683
- const [status, setStatus] = useState(initialStatus);
684
- const [usageCount, setLocalUsageCount] = useState(initialUsageCount);
685
- const [activationLimit, setActivationLimit] = useState(0);
686
- const [activationUsage, setActivationUsage] = useState(0);
687
- const [showDetails, setShowDetails] = useState(false);
823
+ const [isStartingAuth, setIsStartingAuth] = useState(false);
824
+ const optionsRef = useRef(options);
825
+ optionsRef.current = options;
826
+ const applyPatch = useCallback((patch) => {
827
+ setState((prev) => {
828
+ const next = {
829
+ ...prev,
830
+ ...Object.fromEntries(Object.entries(patch).filter(([, value]) => value !== undefined)),
831
+ };
832
+ optionsRef.current.onStateChange?.(next);
833
+ if (patch.paymentStatus) {
834
+ optionsRef.current.onPaymentStatusChange?.(patch.paymentStatus);
835
+ }
836
+ if (patch.usageCount !== undefined) {
837
+ optionsRef.current.onUsageCountChange?.(patch.usageCount);
838
+ }
839
+ return next;
840
+ });
841
+ }, []);
688
842
  useEffect(() => {
689
843
  const handleMessage = (event) => {
690
- const { type, paymentStatus, licenseKey, activationLimit, activationUsage, success, message, usageCount } = event.data.pluginMessage || {};
691
- if (type === 'update-plugin-status' || type === 'license-verification-result') {
692
- if (paymentStatus)
693
- setStatus(paymentStatus);
694
- if (licenseKey)
695
- setLicenseKey(licenseKey);
696
- if (activationLimit !== undefined)
697
- setActivationLimit(activationLimit);
698
- if (activationUsage !== undefined)
699
- setActivationUsage(activationUsage);
700
- if (paymentStatus)
701
- setPaymentStatus(paymentStatus);
702
- if (usageCount !== undefined) {
703
- setLocalUsageCount(usageCount);
704
- setUsageCount(usageCount);
705
- }
844
+ const data = event.data?.pluginMessage;
845
+ if (!data || typeof data !== 'object')
846
+ return;
847
+ const payload = data;
848
+ const type = typeof payload.type === 'string' ? payload.type : '';
849
+ if (type === messageTypes.updateStatus) {
850
+ applyPatch(parseLicenseMessage(payload));
706
851
  }
707
- if (type === 'license-verification-result') {
708
- setIsSubmitting(false);
709
- if (message)
710
- console.log('License verification:', message);
711
- if (success) {
712
- setStatus('PAID');
713
- setPaymentStatus('PAID');
852
+ if (type === messageTypes.verifyResult) {
853
+ setIsVerifying(false);
854
+ setIsStartingAuth(false);
855
+ applyPatch(parseLicenseMessage(payload));
856
+ if (payload.success === true) {
857
+ applyPatch({ paymentStatus: 'PAID', isLicenseRegistered: true });
714
858
  }
715
859
  }
716
- if (type === 'license-deactivation-result') {
860
+ if (type === messageTypes.deactivateResult) {
717
861
  setIsDeactivating(false);
718
- if (message)
719
- console.log('License deactivation:', message);
720
- if (success) {
721
- setStatus('UNPAID');
722
- setPaymentStatus('UNPAID');
723
- setLicenseKey('');
724
- setLocalUsageCount(20);
725
- setActivationLimit(0);
726
- setActivationUsage(0);
862
+ applyPatch(parseLicenseMessage(payload));
863
+ if (payload.success === true) {
864
+ applyPatch({
865
+ paymentStatus: 'UNPAID',
866
+ licenseKey: '',
867
+ hasLicenseKey: false,
868
+ isLicenseRegistered: false,
869
+ activationLimit: 0,
870
+ activationUsage: 0,
871
+ });
872
+ }
873
+ }
874
+ if (type === 'designbase-auth-result') {
875
+ setIsStartingAuth(false);
876
+ if (payload.success === true) {
877
+ applyPatch(parseLicenseMessage(payload));
878
+ }
879
+ else if (typeof payload.message === 'string') {
880
+ applyPatch({ lastMessage: payload.message });
727
881
  }
728
882
  }
729
883
  };
730
884
  window.addEventListener('message', handleMessage);
731
- if (typeof parent !== 'undefined') {
732
- parent.postMessage({ pluginMessage: { type: 'initialize' } }, '*');
733
- }
885
+ postPluginMessage({ type: messageTypes.initialize });
734
886
  return () => window.removeEventListener('message', handleMessage);
735
- }, [setPaymentStatus, setUsageCount]);
887
+ }, [applyPatch, messageTypes]);
888
+ const verifyLicense = useCallback((licenseKey) => {
889
+ setIsVerifying(true);
890
+ postPluginMessage({
891
+ type: messageTypes.verifyLicense,
892
+ licenseKey,
893
+ });
894
+ }, [messageTypes.verifyLicense]);
895
+ const deactivateLicense = useCallback(() => {
896
+ setIsDeactivating(true);
897
+ postPluginMessage({ type: messageTypes.deactivateLicense });
898
+ }, [messageTypes.deactivateLicense]);
899
+ const startDesignbaseAuth = useCallback(() => {
900
+ setIsStartingAuth(true);
901
+ postPluginMessage({ type: START_DESIGNBASE_AUTH_MESSAGE });
902
+ }, []);
903
+ return {
904
+ state,
905
+ isVerifying,
906
+ isDeactivating,
907
+ isStartingAuth,
908
+ verifyLicense,
909
+ deactivateLicense,
910
+ startDesignbaseAuth,
911
+ setLicenseKeyInput: (licenseKey) => applyPatch({ licenseKey }),
912
+ };
913
+ }
914
+
915
+ function formatUsageLabel(state, t) {
916
+ const { remainingUsage, usageUsed, usageLimit, usageReset } = state;
917
+ if (usageLimit === 'unlimited') {
918
+ return resolveText(t, { key: 'license.usage_unlimited' }, '사용 횟수 제한 없음');
919
+ }
920
+ const limit = typeof usageLimit === 'number' ? usageLimit : remainingUsage + usageUsed;
921
+ const remaining = remainingUsage ?? Math.max(0, limit - usageUsed);
922
+ if (usageReset === 'daily') {
923
+ const fallback = `오늘 남은 횟수 ${remaining}/${limit}`;
924
+ const translated = resolveText(t, { key: 'license.usage_daily' }, fallback);
925
+ return translated.includes(String(remaining)) ? translated : fallback;
926
+ }
927
+ if (usageReset === 'monthly') {
928
+ const fallback = `이번 달 남은 횟수 ${remaining}/${limit}`;
929
+ const translated = resolveText(t, { key: 'license.usage_monthly' }, fallback);
930
+ return translated.includes(String(remaining)) ? translated : fallback;
931
+ }
932
+ return `남은 횟수 ${remaining}/${limit}`;
933
+ }
934
+ const PageLicense = ({ status: initialStatus, onClose, licenseKey: initialLicenseKey = '', wordpressLinks, paymentPageUrl, enableAccountAuth = true, showLicenseKeyInput = true, pricingFeatures, pricing, paymentType = 'subscription', messageTypes, onStateChange, setPaymentStatus, setUsageCount, onLicenseSubmit, usageCount: initialUsageCount = 0, t, className, }) => {
935
+ const links = useMemo(() => ({
936
+ purchaseUrl: wordpressLinks?.purchaseUrl ?? paymentPageUrl,
937
+ accountUrl: wordpressLinks?.accountUrl,
938
+ helpUrl: wordpressLinks?.helpUrl,
939
+ }), [wordpressLinks, paymentPageUrl]);
940
+ const { state, isVerifying, isDeactivating, isStartingAuth, verifyLicense, deactivateLicense, startDesignbaseAuth, setLicenseKeyInput, } = useFigmaLicenseBridge({
941
+ messageTypes,
942
+ initialState: {
943
+ paymentStatus: initialStatus,
944
+ licenseKey: initialLicenseKey,
945
+ usageCount: initialUsageCount,
946
+ },
947
+ onStateChange,
948
+ onPaymentStatusChange: setPaymentStatus,
949
+ onUsageCountChange: setUsageCount,
950
+ });
951
+ const [showDetails, setShowDetails] = useState(false);
952
+ const [licenseKeyDraft, setLicenseKeyDraft] = useState(initialLicenseKey);
953
+ const isPaid = state.isLicenseRegistered || state.paymentStatus === 'PAID';
954
+ const usageLabel = formatUsageLabel(state, t);
736
955
  const handleLicenseSubmit = async (submittedLicenseKey) => {
737
- setIsSubmitting(true);
738
- if (typeof parent !== 'undefined') {
739
- parent.postMessage({
740
- pluginMessage: {
741
- type: 'verify-license',
742
- licenseKey: submittedLicenseKey
743
- }
744
- }, '*');
956
+ if (onLicenseSubmit) {
957
+ await onLicenseSubmit(submittedLicenseKey);
958
+ return;
745
959
  }
960
+ verifyLicense(submittedLicenseKey);
746
961
  };
747
- const handleDeactivateLicense = () => {
748
- setIsDeactivating(true);
749
- if (typeof parent !== 'undefined') {
750
- parent.postMessage({
751
- pluginMessage: { type: 'deactivate-license' }
752
- }, '*');
753
- }
962
+ const handleLicenseKeyChange = (value) => {
963
+ setLicenseKeyDraft(value);
964
+ setLicenseKeyInput(value);
754
965
  };
755
- const isPaid = status === 'PAID';
756
966
  return (React.createElement("div", { className: `designbase-figma-page-license ${className || ''}` },
757
967
  React.createElement("div", { className: "designbase-figma-page-license__content" },
758
968
  React.createElement("div", { className: "designbase-figma-page-license__header" },
759
969
  React.createElement("div", { className: "designbase-figma-page-license__title" },
760
- React.createElement("h2", null, isPaid ? resolveText(t, { key: 'license.pro_account' }, '프로 계정') : resolveText(t, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드'))),
970
+ React.createElement("h2", null, isPaid
971
+ ? resolveText(t, { key: 'license.pro_account' }, '프로 계정')
972
+ : resolveText(t, { key: 'license.upgrade_to_pro' }, '프로로 업그레이드')),
973
+ state.planTier && state.planTier !== 'FREE' && (React.createElement("span", { className: "designbase-figma-page-license__tier" }, state.planTier))),
761
974
  React.createElement("p", { className: "designbase-figma-page-license__description" }, isPaid
762
975
  ? resolveText(t, { key: 'license.all_features_available' }, '모든 기능을 사용할 수 있습니다.')
763
- : resolveText(t, { key: 'license.purchase_for_unlimited' }, '라이선스 구매 무제한 접근이 가능합니다.'))),
976
+ : resolveText(t, { key: 'license.purchase_for_unlimited' }, '디자인베이스 멤버십 또는 라이선스로 무제한 이용이 가능합니다.')),
977
+ !isPaid && (React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel))),
764
978
  React.createElement(PricingComparison, { features: pricingFeatures, pricing: pricing, paymentType: paymentType, t: t }),
979
+ state.lastMessage && (React.createElement("p", { className: `designbase-figma-page-license__feedback ${state.lastErrorCode ? 'designbase-figma-page-license__feedback--error' : ''}` }, state.lastMessage)),
765
980
  isPaid && (React.createElement("div", { className: "designbase-figma-page-license__section" },
766
981
  React.createElement("div", { className: "designbase-figma-page-license__section-header" },
767
982
  React.createElement("h3", null, resolveText(t, { key: 'license.activated' }, '라이선스 활성화됨')),
768
983
  React.createElement(Button, { onClick: () => setShowDetails(!showDetails), variant: "tertiary", size: "s", iconOnly: true },
769
984
  React.createElement(MoreHorizontalIcon, { size: 16 }))),
770
- React.createElement("div", { className: "designbase-figma-page-license__license-key" },
985
+ state.licenseKey && (React.createElement("div", { className: "designbase-figma-page-license__license-key" },
771
986
  resolveText(t, { key: 'license.key_label' }, '라이선스 키'),
772
987
  ": ",
773
- React.createElement("span", null, licenseKey)),
988
+ React.createElement("span", null, state.licenseKey))),
989
+ React.createElement("p", { className: "designbase-figma-page-license__usage" }, usageLabel),
774
990
  showDetails && (React.createElement("div", { className: "designbase-figma-page-license__details" },
775
991
  React.createElement("div", { className: "designbase-figma-page-license__activation-info" },
776
992
  React.createElement("div", { className: "designbase-figma-page-license__remaining" },
777
- activationLimit - activationUsage,
778
- " ",
993
+ Math.max(0, state.activationLimit - state.activationUsage),
994
+ ' ',
779
995
  resolveText(t, { key: 'license.activations_remaining' }, '활성'),
780
- " ",
996
+ ' ',
781
997
  resolveText(t, { key: 'license.spots_remaining' }, '자리 남음')),
782
- React.createElement("div", { className: "designbase-figma-page-license__usage" },
783
- activationUsage,
998
+ React.createElement("div", { className: "designbase-figma-page-license__usage-count" },
999
+ state.activationUsage,
784
1000
  "/",
785
- activationLimit)),
786
- React.createElement(Button, { onClick: handleDeactivateLicense, variant: "tertiary", size: "s", disabled: isDeactivating }, isDeactivating
787
- ? resolveText(t, { key: 'license.deactivating' }, '비활성화중...')
1001
+ state.activationLimit)),
1002
+ React.createElement(Button, { onClick: deactivateLicense, variant: "tertiary", size: "s", disabled: isDeactivating }, isDeactivating
1003
+ ? resolveText(t, { key: 'license.deactivating' }, '비활성화 중...')
788
1004
  : resolveText(t, { key: 'license.deactivate' }, '라이선스 비활성화')))))),
789
- !isPaid && (React.createElement("div", { className: "designbase-figma-page-license__section" },
790
- React.createElement("div", { className: "designbase-figma-page-license__section-header" },
791
- React.createElement("h3", null, resolveText(t, { key: 'license.enter_key' }, '라이선스 키 입력')),
792
- paymentPageUrl && (React.createElement(Button, { onClick: () => window.open(paymentPageUrl, '_blank'), variant: "primary", size: "s" },
793
- React.createElement("span", null, resolveText(t, { key: 'license.purchase' }, '라이선스 구매')),
794
- React.createElement(ExternalLinkIcon, { size: 16 })))),
795
- React.createElement(FormWithSubmit, { onLicenseSubmit: handleLicenseSubmit, disabled: false, isSubmitting: isSubmitting, value: licenseKey, onValueChange: setLicenseKey, label: { key: 'license.key' }, submitText: { key: 'license.submit' }, submittingText: { key: 'license.verifying' }, helperText: { key: 'license.enter_from_email' }, t: t })))),
1005
+ !isPaid && (React.createElement(React.Fragment, null,
1006
+ (enableAccountAuth || links.purchaseUrl || links.accountUrl) && (React.createElement("div", { className: "designbase-figma-page-license__section" },
1007
+ React.createElement("div", { className: "designbase-figma-page-license__section-header" },
1008
+ React.createElement("h3", null, resolveText(t, { key: 'license.designbase_account' }, '디자인베이스 계정'))),
1009
+ React.createElement("p", { className: "designbase-figma-page-license__hint" }, resolveText(t, { key: 'license.designbase_account_hint' }, 'WordPress 계정으로 로그인하거나 멤버십을 구매하면 플러그인이 자동으로 활성화됩니다.')),
1010
+ React.createElement("div", { className: "designbase-figma-page-license__actions" },
1011
+ enableAccountAuth && (React.createElement(Button, { onClick: startDesignbaseAuth, variant: "primary", size: "m", disabled: isStartingAuth || isVerifying, fullWidth: true }, isStartingAuth
1012
+ ? resolveText(t, { key: 'license.authenticating' }, '인증 중...')
1013
+ : resolveText(t, { key: 'license.login_with_designbase' }, '디자인베이스로 로그인'))),
1014
+ links.purchaseUrl && (React.createElement(Button, { onClick: () => openExternalUrl(links.purchaseUrl), variant: "secondary", size: "m", fullWidth: true },
1015
+ React.createElement("span", null, resolveText(t, { key: 'license.purchase_membership' }, '멤버십 구매')),
1016
+ React.createElement(ExternalLinkIcon, { size: 16 }))),
1017
+ links.accountUrl && (React.createElement(Button, { onClick: () => openExternalUrl(links.accountUrl), variant: "tertiary", size: "s", fullWidth: true },
1018
+ React.createElement("span", null, resolveText(t, { key: 'license.manage_account' }, '계정·멤버십 관리')),
1019
+ React.createElement(ExternalLinkIcon, { size: 16 })))))),
1020
+ showLicenseKeyInput && (React.createElement("div", { className: "designbase-figma-page-license__section" },
1021
+ React.createElement("div", { className: "designbase-figma-page-license__section-header" },
1022
+ React.createElement("h3", null, resolveText(t, { key: 'license.enter_key' }, '라이선스 키 입력'))),
1023
+ React.createElement(FormWithSubmit, { onLicenseSubmit: handleLicenseSubmit, disabled: false, isSubmitting: isVerifying, value: licenseKeyDraft, onValueChange: handleLicenseKeyChange, label: { key: 'license.key' }, submitText: { key: 'license.submit' }, submittingText: { key: 'license.verifying' }, helperText: { key: 'license.enter_from_email' }, t: t }))))),
1024
+ links.helpUrl && (React.createElement("p", { className: "designbase-figma-page-license__disclaimer" },
1025
+ React.createElement("button", { type: "button", className: "designbase-figma-page-license__link", onClick: () => openExternalUrl(links.helpUrl) }, resolveText(t, { key: 'license.help_link' }, '라이선스·결제 도움말'))))),
796
1026
  React.createElement(Button, { className: "designbase-figma-page-license__close", onPress: onClose, variant: "tertiary", size: "s", "aria-label": "Close" },
797
1027
  React.createElement(CloseIcon, { size: 20 }))));
798
1028
  };
@@ -1066,11 +1296,11 @@ const UpgradeBanner = ({ onClick, variant = 'button', isLoading = false, title =
1066
1296
  React.createElement("div", { className: "designbase-figma-upgrade-banner__text-wrap" },
1067
1297
  React.createElement("h3", { className: "designbase-figma-upgrade-banner__title" }, displayTitle),
1068
1298
  React.createElement("p", { className: "designbase-figma-upgrade-banner__text" }, displayDescription)),
1069
- variant === 'button' ? (React.createElement(Button, { onClick: onClick, variant: "primary", size: "m", disabled: isLoading }, displayButtonText)) : (React.createElement("div", { className: "designbase-figma-upgrade-banner__icon" },
1299
+ variant === 'button' ? (React.createElement(Button, { onPress: onClick, variant: "primary", size: "m", disabled: isLoading }, displayButtonText)) : (React.createElement("div", { className: "designbase-figma-upgrade-banner__icon" },
1070
1300
  React.createElement(ChevronRightIcon, { size: 20 })))));
1071
1301
  return (React.createElement("div", { className: `designbase-figma-upgrade-banner designbase-figma-upgrade-banner--${variant} ${className || ''}` }, useGradient ? (React.createElement(RandomGradient, { scheme: gradientScheme, tone: gradientTone, animated: gradientAnimated, height: "100%", width: "100%", className: "designbase-figma-upgrade-banner__gradient-bg" }, bannerContent)) : (bannerContent)));
1072
1302
  };
1073
1303
  UpgradeBanner.displayName = 'UpgradeBanner';
1074
1304
 
1075
- export { DonationBadge, FigmaContainer, FigmaFooter, FigmaHeader, FigmaPageHead, FigmaSection, FigmaSidebar, FigmaToast, FigmaToastProvider, FormWithSubmit, InteractionFeedback, LanguageSelector, LogoDropdown, PageLicense, PaymentBadge, PaymentStatusSection, PricingComparison, ProgressModal, ResizablePlugin, SettingsModal, TitleDescription, UpgradeBanner, getActiveSection, resolveText, scrollToSection, useFigmaToast, useToast };
1305
+ export { DEFAULT_LICENSE_MESSAGE_TYPES, DonationBadge, FigmaContainer, FigmaFooter, FigmaHeader, FigmaPageHead, FigmaSection, FigmaSidebar, FigmaToast, FigmaToastProvider, FormWithSubmit, InteractionFeedback, LanguageSelector, LogoDropdown, PageLicense, PaymentBadge, PaymentStatusSection, PricingComparison, ProgressModal, ResizablePlugin, START_DESIGNBASE_AUTH_MESSAGE, SettingsModal, TitleDescription, UpgradeBanner, getActiveSection, resolveText, scrollToSection, useFigmaLicenseBridge, useFigmaToast, useToast };
1076
1306
  //# sourceMappingURL=index.esm.js.map