@rojaostudio/ds 1.0.0

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.
Files changed (291) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/brand/rojao-black-on-white.png +0 -0
  4. package/brand/rojao-black.png +0 -0
  5. package/brand/rojao-white-on-black.png +0 -0
  6. package/brand/rojao-white.png +0 -0
  7. package/dist/chunk-ORMEWXMH.js +37 -0
  8. package/dist/compat/generate.d.ts +6 -0
  9. package/dist/compat/generate.js +1 -0
  10. package/dist/compat/recipes.d.ts +1 -0
  11. package/dist/compat/recipes.js +1 -0
  12. package/dist/compat/themes.d.ts +1 -0
  13. package/dist/compat/themes.js +1 -0
  14. package/dist/compat/tokens.d.ts +1 -0
  15. package/dist/compat/tokens.js +1 -0
  16. package/dist/components/accordion.d.ts +35 -0
  17. package/dist/components/accordion.js +95 -0
  18. package/dist/components/alert.d.ts +24 -0
  19. package/dist/components/alert.js +72 -0
  20. package/dist/components/avatar.d.ts +45 -0
  21. package/dist/components/avatar.js +97 -0
  22. package/dist/components/badge.d.ts +45 -0
  23. package/dist/components/badge.js +114 -0
  24. package/dist/components/blocker-card.d.ts +42 -0
  25. package/dist/components/blocker-card.js +45 -0
  26. package/dist/components/bottom-sheet.d.ts +31 -0
  27. package/dist/components/bottom-sheet.js +120 -0
  28. package/dist/components/breadcrumb.d.ts +28 -0
  29. package/dist/components/breadcrumb.js +52 -0
  30. package/dist/components/button.d.ts +27 -0
  31. package/dist/components/button.js +124 -0
  32. package/dist/components/card.d.ts +27 -0
  33. package/dist/components/card.js +52 -0
  34. package/dist/components/chat-bubble.d.ts +16 -0
  35. package/dist/components/chat-bubble.js +55 -0
  36. package/dist/components/checkbox.d.ts +14 -0
  37. package/dist/components/checkbox.js +78 -0
  38. package/dist/components/chip-input.d.ts +26 -0
  39. package/dist/components/chip-input.js +182 -0
  40. package/dist/components/chips.d.ts +22 -0
  41. package/dist/components/chips.js +94 -0
  42. package/dist/components/choice-card.d.ts +16 -0
  43. package/dist/components/choice-card.js +60 -0
  44. package/dist/components/choice-carousel.d.ts +16 -0
  45. package/dist/components/choice-carousel.js +154 -0
  46. package/dist/components/choice-preview-card.d.ts +37 -0
  47. package/dist/components/choice-preview-card.js +39 -0
  48. package/dist/components/color-input.d.ts +20 -0
  49. package/dist/components/color-input.js +79 -0
  50. package/dist/components/combobox.d.ts +70 -0
  51. package/dist/components/combobox.js +213 -0
  52. package/dist/components/context-menu.d.ts +33 -0
  53. package/dist/components/context-menu.js +70 -0
  54. package/dist/components/copilot-hint.d.ts +18 -0
  55. package/dist/components/copilot-hint.js +63 -0
  56. package/dist/components/copy-field.d.ts +16 -0
  57. package/dist/components/copy-field.js +41 -0
  58. package/dist/components/currency-input.d.ts +32 -0
  59. package/dist/components/currency-input.js +138 -0
  60. package/dist/components/danger-zone.d.ts +20 -0
  61. package/dist/components/danger-zone.js +21 -0
  62. package/dist/components/data-table-header.d.ts +43 -0
  63. package/dist/components/data-table-header.js +205 -0
  64. package/dist/components/date-picker.d.ts +40 -0
  65. package/dist/components/date-picker.js +252 -0
  66. package/dist/components/divider.d.ts +20 -0
  67. package/dist/components/divider.js +47 -0
  68. package/dist/components/drawer.d.ts +26 -0
  69. package/dist/components/drawer.js +82 -0
  70. package/dist/components/dropzone.d.ts +19 -0
  71. package/dist/components/dropzone.js +65 -0
  72. package/dist/components/empty-state.d.ts +48 -0
  73. package/dist/components/empty-state.js +91 -0
  74. package/dist/components/fab.d.ts +38 -0
  75. package/dist/components/fab.js +100 -0
  76. package/dist/components/filter-chip.d.ts +54 -0
  77. package/dist/components/filter-chip.js +66 -0
  78. package/dist/components/floating-stepper.d.ts +44 -0
  79. package/dist/components/floating-stepper.js +53 -0
  80. package/dist/components/form-card-header.d.ts +13 -0
  81. package/dist/components/form-card-header.js +8 -0
  82. package/dist/components/icon-button.d.ts +17 -0
  83. package/dist/components/icon-button.js +80 -0
  84. package/dist/components/image-crop-modal.d.ts +59 -0
  85. package/dist/components/image-crop-modal.js +240 -0
  86. package/dist/components/image-upload.d.ts +72 -0
  87. package/dist/components/image-upload.js +271 -0
  88. package/dist/components/index.d.ts +85 -0
  89. package/dist/components/index.js +200 -0
  90. package/dist/components/input.d.ts +25 -0
  91. package/dist/components/input.js +136 -0
  92. package/dist/components/insight-card.d.ts +19 -0
  93. package/dist/components/insight-card.js +27 -0
  94. package/dist/components/label.d.ts +16 -0
  95. package/dist/components/label.js +43 -0
  96. package/dist/components/media-tile.d.ts +24 -0
  97. package/dist/components/media-tile.js +28 -0
  98. package/dist/components/menu.d.ts +50 -0
  99. package/dist/components/menu.js +80 -0
  100. package/dist/components/modal.d.ts +25 -0
  101. package/dist/components/modal.js +71 -0
  102. package/dist/components/notice.d.ts +50 -0
  103. package/dist/components/notice.js +103 -0
  104. package/dist/components/option-tile.d.ts +60 -0
  105. package/dist/components/option-tile.js +144 -0
  106. package/dist/components/page-shell.d.ts +29 -0
  107. package/dist/components/page-shell.js +36 -0
  108. package/dist/components/page-skeleton.d.ts +35 -0
  109. package/dist/components/page-skeleton.js +12 -0
  110. package/dist/components/page-tabs.d.ts +35 -0
  111. package/dist/components/page-tabs.js +55 -0
  112. package/dist/components/pagination.d.ts +31 -0
  113. package/dist/components/pagination.js +80 -0
  114. package/dist/components/paywall-banner.d.ts +37 -0
  115. package/dist/components/paywall-banner.js +42 -0
  116. package/dist/components/paywall.d.ts +44 -0
  117. package/dist/components/paywall.js +55 -0
  118. package/dist/components/phone-frame.d.ts +9 -0
  119. package/dist/components/phone-frame.js +18 -0
  120. package/dist/components/phone-input.d.ts +24 -0
  121. package/dist/components/phone-input.js +92 -0
  122. package/dist/components/pix-icon.d.ts +8 -0
  123. package/dist/components/pix-icon.js +24 -0
  124. package/dist/components/popover.d.ts +44 -0
  125. package/dist/components/popover.js +140 -0
  126. package/dist/components/pricing-card.d.ts +42 -0
  127. package/dist/components/pricing-card.js +29 -0
  128. package/dist/components/qr-display.d.ts +19 -0
  129. package/dist/components/qr-display.js +24 -0
  130. package/dist/components/radio.d.ts +33 -0
  131. package/dist/components/radio.js +97 -0
  132. package/dist/components/row-actions.d.ts +24 -0
  133. package/dist/components/row-actions.js +76 -0
  134. package/dist/components/saving-bar-context.d.ts +40 -0
  135. package/dist/components/saving-bar-context.js +125 -0
  136. package/dist/components/saving-bar.d.ts +18 -0
  137. package/dist/components/saving-bar.js +72 -0
  138. package/dist/components/search.d.ts +30 -0
  139. package/dist/components/search.js +81 -0
  140. package/dist/components/section-card.d.ts +14 -0
  141. package/dist/components/section-card.js +49 -0
  142. package/dist/components/section-header.d.ts +29 -0
  143. package/dist/components/section-header.js +7 -0
  144. package/dist/components/select.d.ts +21 -0
  145. package/dist/components/select.js +140 -0
  146. package/dist/components/selectable-card.d.ts +35 -0
  147. package/dist/components/selectable-card.js +27 -0
  148. package/dist/components/setting-row.d.ts +33 -0
  149. package/dist/components/setting-row.js +19 -0
  150. package/dist/components/settings-list.d.ts +25 -0
  151. package/dist/components/settings-list.js +22 -0
  152. package/dist/components/skeleton.d.ts +24 -0
  153. package/dist/components/skeleton.js +49 -0
  154. package/dist/components/slider.d.ts +32 -0
  155. package/dist/components/slider.js +79 -0
  156. package/dist/components/spinner.d.ts +14 -0
  157. package/dist/components/spinner.js +36 -0
  158. package/dist/components/step-progress.d.ts +12 -0
  159. package/dist/components/step-progress.js +24 -0
  160. package/dist/components/summary-bar.d.ts +31 -0
  161. package/dist/components/summary-bar.js +54 -0
  162. package/dist/components/table.d.ts +23 -0
  163. package/dist/components/table.js +80 -0
  164. package/dist/components/textarea.d.ts +21 -0
  165. package/dist/components/textarea.js +95 -0
  166. package/dist/components/themed.d.ts +36 -0
  167. package/dist/components/themed.js +22 -0
  168. package/dist/components/time-picker.d.ts +34 -0
  169. package/dist/components/time-picker.js +213 -0
  170. package/dist/components/toaster.d.ts +84 -0
  171. package/dist/components/toaster.js +284 -0
  172. package/dist/components/toggle-card-compact.d.ts +21 -0
  173. package/dist/components/toggle-card-compact.js +99 -0
  174. package/dist/components/toggle-card.d.ts +15 -0
  175. package/dist/components/toggle-card.js +76 -0
  176. package/dist/components/toggle-group.d.ts +67 -0
  177. package/dist/components/toggle-group.js +80 -0
  178. package/dist/components/toggle.d.ts +13 -0
  179. package/dist/components/toggle.js +64 -0
  180. package/dist/components/tooltip.d.ts +17 -0
  181. package/dist/components/tooltip.js +89 -0
  182. package/dist/components/typing-indicator.d.ts +8 -0
  183. package/dist/components/typing-indicator.js +27 -0
  184. package/dist/components/use-dismiss.d.ts +9 -0
  185. package/dist/components/use-dismiss.js +28 -0
  186. package/dist/components/use-focus-trap.d.ts +5 -0
  187. package/dist/components/use-focus-trap.js +54 -0
  188. package/dist/icons/index.d.ts +1 -0
  189. package/dist/icons/index.js +89 -0
  190. package/dist/targets/native/components/accordion.d.ts +18 -0
  191. package/dist/targets/native/components/accordion.js +122 -0
  192. package/dist/targets/native/components/alert.d.ts +16 -0
  193. package/dist/targets/native/components/alert.js +58 -0
  194. package/dist/targets/native/components/avatar.d.ts +25 -0
  195. package/dist/targets/native/components/avatar.js +88 -0
  196. package/dist/targets/native/components/badge.d.ts +27 -0
  197. package/dist/targets/native/components/badge.js +59 -0
  198. package/dist/targets/native/components/button.d.ts +18 -0
  199. package/dist/targets/native/components/button.js +84 -0
  200. package/dist/targets/native/components/card.d.ts +6 -0
  201. package/dist/targets/native/components/card.js +36 -0
  202. package/dist/targets/native/components/checkbox.d.ts +12 -0
  203. package/dist/targets/native/components/checkbox.js +59 -0
  204. package/dist/targets/native/components/chips.d.ts +17 -0
  205. package/dist/targets/native/components/chips.js +77 -0
  206. package/dist/targets/native/components/choice-card.d.ts +11 -0
  207. package/dist/targets/native/components/choice-card.js +52 -0
  208. package/dist/targets/native/components/context-menu.d.ts +11 -0
  209. package/dist/targets/native/components/context-menu.js +19 -0
  210. package/dist/targets/native/components/currency-input.d.ts +22 -0
  211. package/dist/targets/native/components/currency-input.js +105 -0
  212. package/dist/targets/native/components/danger-zone.d.ts +13 -0
  213. package/dist/targets/native/components/danger-zone.js +27 -0
  214. package/dist/targets/native/components/date-picker.d.ts +13 -0
  215. package/dist/targets/native/components/date-picker.js +185 -0
  216. package/dist/targets/native/components/divider.d.ts +9 -0
  217. package/dist/targets/native/components/divider.js +36 -0
  218. package/dist/targets/native/components/empty-state.d.ts +13 -0
  219. package/dist/targets/native/components/empty-state.js +10 -0
  220. package/dist/targets/native/components/fab.d.ts +25 -0
  221. package/dist/targets/native/components/fab.js +112 -0
  222. package/dist/targets/native/components/filter-chip.d.ts +22 -0
  223. package/dist/targets/native/components/filter-chip.js +70 -0
  224. package/dist/targets/native/components/form-field.d.ts +13 -0
  225. package/dist/targets/native/components/form-field.js +29 -0
  226. package/dist/targets/native/components/form-screen.d.ts +19 -0
  227. package/dist/targets/native/components/form-screen.js +88 -0
  228. package/dist/targets/native/components/google-icon.d.ts +8 -0
  229. package/dist/targets/native/components/google-icon.js +32 -0
  230. package/dist/targets/native/components/icon-button.d.ts +18 -0
  231. package/dist/targets/native/components/icon-button.js +80 -0
  232. package/dist/targets/native/components/icon.d.ts +11 -0
  233. package/dist/targets/native/components/icon.js +9 -0
  234. package/dist/targets/native/components/image-upload.d.ts +12 -0
  235. package/dist/targets/native/components/image-upload.js +95 -0
  236. package/dist/targets/native/components/index.d.ts +45 -0
  237. package/dist/targets/native/components/index.js +100 -0
  238. package/dist/targets/native/components/input.d.ts +17 -0
  239. package/dist/targets/native/components/input.js +103 -0
  240. package/dist/targets/native/components/list-item.d.ts +20 -0
  241. package/dist/targets/native/components/list-item.js +71 -0
  242. package/dist/targets/native/components/menu.d.ts +24 -0
  243. package/dist/targets/native/components/menu.js +71 -0
  244. package/dist/targets/native/components/modal.d.ts +15 -0
  245. package/dist/targets/native/components/modal.js +110 -0
  246. package/dist/targets/native/components/paywall-banner.d.ts +11 -0
  247. package/dist/targets/native/components/paywall-banner.js +46 -0
  248. package/dist/targets/native/components/paywall.d.ts +18 -0
  249. package/dist/targets/native/components/paywall.js +61 -0
  250. package/dist/targets/native/components/radio.d.ts +20 -0
  251. package/dist/targets/native/components/radio.js +71 -0
  252. package/dist/targets/native/components/search.d.ts +22 -0
  253. package/dist/targets/native/components/search.js +92 -0
  254. package/dist/targets/native/components/select.d.ts +17 -0
  255. package/dist/targets/native/components/select.js +86 -0
  256. package/dist/targets/native/components/sheet.d.ts +11 -0
  257. package/dist/targets/native/components/sheet.js +51 -0
  258. package/dist/targets/native/components/skeleton.d.ts +18 -0
  259. package/dist/targets/native/components/skeleton.js +52 -0
  260. package/dist/targets/native/components/slider.d.ts +18 -0
  261. package/dist/targets/native/components/slider.js +153 -0
  262. package/dist/targets/native/components/spinner.d.ts +7 -0
  263. package/dist/targets/native/components/spinner.js +10 -0
  264. package/dist/targets/native/components/stepper.d.ts +10 -0
  265. package/dist/targets/native/components/stepper.js +33 -0
  266. package/dist/targets/native/components/switch.d.ts +20 -0
  267. package/dist/targets/native/components/switch.js +68 -0
  268. package/dist/targets/native/components/text.d.ts +12 -0
  269. package/dist/targets/native/components/text.js +31 -0
  270. package/dist/targets/native/components/textarea.d.ts +13 -0
  271. package/dist/targets/native/components/textarea.js +92 -0
  272. package/dist/targets/native/components/theme.d.ts +18 -0
  273. package/dist/targets/native/components/theme.js +20 -0
  274. package/dist/targets/native/components/toaster.d.ts +35 -0
  275. package/dist/targets/native/components/toaster.js +159 -0
  276. package/dist/targets/native/fonts.d.ts +9 -0
  277. package/dist/targets/native/fonts.js +10 -0
  278. package/dist/targets/native/icons.d.ts +1 -0
  279. package/dist/targets/native/icons.js +1 -0
  280. package/dist/targets/native/index.d.ts +3 -0
  281. package/dist/targets/native/index.js +11 -0
  282. package/dist/targets/native/preset.cjs +69 -0
  283. package/dist/targets/native/resolve.d.ts +22 -0
  284. package/dist/targets/native/resolve.js +85 -0
  285. package/dist/targets/native/theme.css +118 -0
  286. package/dist/targets/native/theme.d.ts +117 -0
  287. package/dist/targets/native/theme.js +118 -0
  288. package/package.json +194 -0
  289. package/styles/_primitives.generated.css +284 -0
  290. package/styles/base.css +950 -0
  291. package/styles/themes/rojao.css +107 -0
@@ -0,0 +1,42 @@
1
+ import "../chunk-ORMEWXMH.js";
2
+ import { Lock, AlertTriangle } from "lucide-react";
3
+ const STYLES = {
4
+ warn: {
5
+ container: "border-warning-border bg-warning-soft",
6
+ title: "text-warning-text",
7
+ desc: "text-warning-text/85",
8
+ cta: "bg-surface-default border border-warning-border hover:bg-warning-soft text-warning-text",
9
+ Icon: AlertTriangle,
10
+ iconColor: "text-warning-text"
11
+ },
12
+ blocked: {
13
+ container: "border-danger-border bg-danger-soft",
14
+ title: "text-danger-text",
15
+ desc: "text-danger-text/85",
16
+ cta: "bg-danger text-fg-inverse hover:bg-danger-text",
17
+ Icon: Lock,
18
+ iconColor: "text-danger-text"
19
+ }
20
+ };
21
+ function DefaultLink({ href, className, children }) {
22
+ return /* @__PURE__ */ React.createElement("a", { href, className }, children);
23
+ }
24
+ function PaywallBanner({
25
+ variant,
26
+ title,
27
+ description,
28
+ ctaLabel = "Ver planos",
29
+ ctaHref,
30
+ onCta,
31
+ linkAs: LinkAs = DefaultLink,
32
+ className = ""
33
+ }) {
34
+ const s = STYLES[variant];
35
+ const Icon = s.Icon;
36
+ const ctaClass = ["text-caption font-semibold px-3 py-1.5 rounded-(--radius-card) shrink-0 transition-colors", s.cta].join(" ");
37
+ const cta = ctaHref ? /* @__PURE__ */ React.createElement(LinkAs, { href: ctaHref, className: ctaClass }, ctaLabel, " \u2192") : onCta ? /* @__PURE__ */ React.createElement("button", { type: "button", onClick: onCta, className: ctaClass }, ctaLabel, " \u2192") : null;
38
+ return /* @__PURE__ */ React.createElement("div", { className: ["rounded-(--radius-card) border px-4 py-3 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2", s.container, className].join(" ") }, /* @__PURE__ */ React.createElement("div", { className: "flex items-start gap-2.5 min-w-0" }, /* @__PURE__ */ React.createElement(Icon, { size: 18, className: ["shrink-0 mt-0.5", s.iconColor].join(" ") }), /* @__PURE__ */ React.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React.createElement("p", { className: ["text-label font-semibold", s.title].join(" ") }, title), /* @__PURE__ */ React.createElement("div", { className: ["text-caption mt-0.5", s.desc].join(" ") }, description))), cta);
39
+ }
40
+ export {
41
+ PaywallBanner
42
+ };
@@ -0,0 +1,44 @@
1
+ import * as react from 'react';
2
+ import { ComponentType, ReactNode } from 'react';
3
+ import { EmptyStateIcon } from './empty-state.js';
4
+ import 'lucide-react';
5
+
6
+ type PaywallReason = 'feature' | 'limit' | 'trial_value';
7
+ type LinkComponent = ComponentType<{
8
+ href: string;
9
+ className?: string;
10
+ onClick?: () => void;
11
+ children: ReactNode;
12
+ }>;
13
+ interface PaywallContentProps {
14
+ /** Ícone por categoria da feature (catalog/channels/commercial/operation/
15
+ * intelligence/billing). Default: lock. */
16
+ icon?: EmptyStateIcon;
17
+ title: string;
18
+ description?: string;
19
+ /** 'feature' → "Disponível no {planLabel}"; 'limit' → "Limite atingido".
20
+ * Sem cor de alerta — friendly, não erro. */
21
+ reason?: PaywallReason;
22
+ /** Rótulo do plano mínimo (ex.: "Essencial") — usado quando reason='feature'. */
23
+ planLabel?: string;
24
+ ctaLabel?: string;
25
+ ctaHref?: string;
26
+ onCta?: () => void;
27
+ /** Componente de link do app (next/link). Sem ele → âncora nativa <a>. */
28
+ linkAs?: LinkComponent;
29
+ }
30
+ /** Visual puro do paywall — compartilhado por PaywallState e PaywallModal. */
31
+ declare function PaywallContent({ icon, title, description, reason, planLabel, ctaLabel, ctaHref, onCta, linkAs: Link, }: PaywallContentProps): react.JSX.Element;
32
+ interface PaywallStateProps extends PaywallContentProps {
33
+ className?: string;
34
+ }
35
+ /** Estado-de-página: ocupa a altura disponível, mesmo visual do modal. */
36
+ declare function PaywallState({ className, ...content }: PaywallStateProps): react.JSX.Element;
37
+ interface PaywallModalProps extends PaywallContentProps {
38
+ open: boolean;
39
+ onClose: () => void;
40
+ }
41
+ /** Modal compacto: o controle de ação fica visível na tela; ao clicar, abre isto. */
42
+ declare function PaywallModal({ open, onClose, ...content }: PaywallModalProps): react.JSX.Element;
43
+
44
+ export { PaywallContent, type PaywallContentProps, PaywallModal, type PaywallModalProps, type PaywallReason, PaywallState, type PaywallStateProps };
@@ -0,0 +1,55 @@
1
+ "use client";
2
+ import {
3
+ __objRest,
4
+ __spreadProps,
5
+ __spreadValues
6
+ } from "../chunk-ORMEWXMH.js";
7
+ import { Lock, Sparkles } from "lucide-react";
8
+ import { ICON_MAP } from "./empty-state.js";
9
+ import { Modal } from "./modal.js";
10
+ const CTA_CLASS = "inline-flex items-center justify-center w-full rounded-(--radius-control) px-4 py-3 text-label font-semibold bg-brand-primary text-brand-on-primary hover:bg-brand-hover transition-colors";
11
+ function planLineText(reason, planLabel) {
12
+ if (reason === "trial_value") return "Incluso no seu teste Pro";
13
+ if (reason === "limit") return "Limite atingido";
14
+ return planLabel ? `Dispon\xEDvel no ${planLabel}` : "Fa\xE7a upgrade";
15
+ }
16
+ function PaywallContent({
17
+ icon = "lock",
18
+ title,
19
+ description,
20
+ reason = "feature",
21
+ planLabel,
22
+ ctaLabel = "Ver planos",
23
+ ctaHref,
24
+ onCta,
25
+ linkAs: Link
26
+ }) {
27
+ var _a;
28
+ const Icon = (_a = ICON_MAP[icon]) != null ? _a : Lock;
29
+ const isTrial = reason === "trial_value";
30
+ const cta = ctaHref && Link ? /* @__PURE__ */ React.createElement(Link, { href: ctaHref, className: CTA_CLASS, onClick: onCta }, ctaLabel) : ctaHref ? /* @__PURE__ */ React.createElement("a", { href: ctaHref, className: CTA_CLASS, onClick: onCta }, ctaLabel) : /* @__PURE__ */ React.createElement("button", { type: "button", className: CTA_CLASS, onClick: onCta }, ctaLabel);
31
+ return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col items-center text-center px-2" }, /* @__PURE__ */ React.createElement("div", { className: "relative mb-4 text-fg-secondary" }, /* @__PURE__ */ React.createElement(Icon, { size: 52, strokeWidth: 1.25 }), /* @__PURE__ */ React.createElement("span", { className: `absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full ${isTrial ? "bg-amber-500 text-white" : "bg-brand-primary text-brand-on-primary"}` }, isTrial ? /* @__PURE__ */ React.createElement(Sparkles, { size: 12, strokeWidth: 2.5 }) : /* @__PURE__ */ React.createElement(Lock, { size: 12, strokeWidth: 2.5 }))), /* @__PURE__ */ React.createElement("span", { className: `inline-flex items-center rounded-full px-2.5 py-1 text-caption font-medium ${isTrial ? "bg-amber-100 text-amber-900" : "bg-surface-raised text-fg-secondary"}` }, planLineText(reason, planLabel)), /* @__PURE__ */ React.createElement("p", { className: "text-body font-semibold text-fg-primary mt-3 mb-1.5" }, title), description && /* @__PURE__ */ React.createElement("p", { className: "text-label text-fg-muted max-w-sm leading-relaxed mb-5" }, description), /* @__PURE__ */ React.createElement("div", { className: "w-full max-w-xs" }, cta));
32
+ }
33
+ function PaywallState(_a) {
34
+ var _b = _a, { className = "" } = _b, content = __objRest(_b, ["className"]);
35
+ return /* @__PURE__ */ React.createElement(
36
+ "div",
37
+ {
38
+ className: ["flex flex-col items-center justify-center min-h-[320px] flex-1 py-10", className].filter(Boolean).join(" ")
39
+ },
40
+ /* @__PURE__ */ React.createElement(PaywallContent, __spreadValues({}, content))
41
+ );
42
+ }
43
+ function PaywallModal(_c) {
44
+ var _d = _c, { open, onClose } = _d, content = __objRest(_d, ["open", "onClose"]);
45
+ return /* @__PURE__ */ React.createElement(Modal, { open, onClose, size: "sm" }, /* @__PURE__ */ React.createElement("div", { className: "py-2" }, /* @__PURE__ */ React.createElement(PaywallContent, __spreadProps(__spreadValues({}, content), { onCta: () => {
46
+ var _a;
47
+ (_a = content.onCta) == null ? void 0 : _a.call(content);
48
+ onClose();
49
+ } }))));
50
+ }
51
+ export {
52
+ PaywallContent,
53
+ PaywallModal,
54
+ PaywallState
55
+ };
@@ -0,0 +1,9 @@
1
+ import * as react from 'react';
2
+
3
+ interface PhoneFrameProps {
4
+ children: React.ReactNode;
5
+ className?: string;
6
+ }
7
+ declare function PhoneFrame({ children, className }: PhoneFrameProps): react.JSX.Element;
8
+
9
+ export { PhoneFrame, type PhoneFrameProps };
@@ -0,0 +1,18 @@
1
+ import "../chunk-ORMEWXMH.js";
2
+ function PhoneFrame({ children, className = "" }) {
3
+ return /* @__PURE__ */ React.createElement(
4
+ "div",
5
+ {
6
+ className: [
7
+ // rojao-detect-disable over-rounding
8
+ "relative rounded-[2.5rem] border-[6px] border-(--text-primary)",
9
+ "bg-white overflow-hidden shadow-2xl",
10
+ className
11
+ ].filter(Boolean).join(" ")
12
+ },
13
+ /* @__PURE__ */ React.createElement("div", { className: "h-full overflow-y-auto overflow-x-hidden scrollbar-none" }, children)
14
+ );
15
+ }
16
+ export {
17
+ PhoneFrame
18
+ };
@@ -0,0 +1,24 @@
1
+ import * as react from 'react';
2
+ import { InputHTMLAttributes } from 'react';
3
+
4
+ interface PhoneInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value' | 'defaultValue' | 'size'> {
5
+ label?: string;
6
+ helper?: string;
7
+ error?: string;
8
+ required?: boolean;
9
+ optional?: boolean;
10
+ value?: string;
11
+ defaultValue?: string;
12
+ onChange?: (value: string) => void;
13
+ }
14
+ /**
15
+ * PhoneInput — telefone internacional com seletor de país BUSCÁVEL.
16
+ *
17
+ * Seletor de país = Combobox do DS (busca por nome/código + bandeira), em vez do
18
+ * dropdown nativo do react-international-phone (que não tem busca e estourava a tela).
19
+ * A mecânica de máscara/parse/E.164 vem do hook `usePhoneInput` da lib.
20
+ * Submete E.164 via input hidden (prop `name`); onChange entrega E.164.
21
+ */
22
+ declare function PhoneInput({ label, helper, error, required, optional, value, defaultValue, placeholder, name, onChange, id, }: PhoneInputProps): react.JSX.Element;
23
+
24
+ export { PhoneInput, type PhoneInputProps };
@@ -0,0 +1,92 @@
1
+ "use client";
2
+ import "../chunk-ORMEWXMH.js";
3
+ import { useId, useMemo, useState } from "react";
4
+ import { usePhoneInput, defaultCountries, parseCountry, FlagImage } from "react-international-phone";
5
+ import { Combobox } from "./combobox.js";
6
+ function normalizeToE164(raw) {
7
+ if (!raw) return "";
8
+ const digits = raw.replace(/\D/g, "");
9
+ if (raw.startsWith("+")) return raw;
10
+ if (digits.length >= 12) return `+${digits}`;
11
+ return `+55${digits}`;
12
+ }
13
+ function PhoneInput({
14
+ label,
15
+ helper,
16
+ error,
17
+ required,
18
+ optional,
19
+ value,
20
+ defaultValue = "",
21
+ placeholder,
22
+ name,
23
+ onChange,
24
+ id
25
+ }) {
26
+ const generatedId = useId();
27
+ const inputId = id != null ? id : generatedId;
28
+ const controlled = value !== void 0;
29
+ const [internalValue, setInternalValue] = useState(() => normalizeToE164(defaultValue));
30
+ const displayValue = controlled ? value : internalValue;
31
+ const { inputValue, country, setCountry, handlePhoneValueChange, inputRef } = usePhoneInput({
32
+ defaultCountry: "br",
33
+ value: displayValue,
34
+ countries: defaultCountries,
35
+ // DDI nunca é editável pelo campo: o input mostra só o número nacional e o
36
+ // código do país vira prefixo estático — troca de país SÓ pelo seletor.
37
+ // data.phone JÁ vem em E.164 completo (a flag afeta apenas o display);
38
+ // recompor aqui duplicaria o DDI e criaria feedback loop.
39
+ disableDialCodeAndPrefix: true,
40
+ onChange: (data) => {
41
+ const v = data.phone === `+${data.country.dialCode}` ? "" : data.phone;
42
+ if (!controlled) setInternalValue(v);
43
+ onChange == null ? void 0 : onChange(v);
44
+ }
45
+ });
46
+ const countryOptions = useMemo(
47
+ () => defaultCountries.map((c) => {
48
+ const p = parseCountry(c);
49
+ return {
50
+ value: p.iso2,
51
+ label: p.name,
52
+ description: `+${p.dialCode}`,
53
+ icon: /* @__PURE__ */ React.createElement(FlagImage, { iso2: p.iso2, size: "18px" })
54
+ };
55
+ }),
56
+ []
57
+ );
58
+ const errorBorder = error ? "border-danger focus-within:border-danger focus-within:ring-2 focus-within:ring-danger/20" : "border-stroke-control focus-within:border-stroke-focus focus-within:ring-2 focus-within:ring-stroke-focus/20";
59
+ return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1.5 w-full" }, label && /* @__PURE__ */ React.createElement("label", { htmlFor: inputId, className: "inline-flex items-center gap-1 text-label font-medium text-fg-primary" }, /* @__PURE__ */ React.createElement("span", null, label), required && /* @__PURE__ */ React.createElement("span", { className: "text-danger", "aria-label": "obrigat\xF3rio" }, "*"), optional && !required && /* @__PURE__ */ React.createElement("span", { className: "text-fg-muted font-normal" }, "(opcional)")), /* @__PURE__ */ React.createElement("div", { className: "flex items-stretch gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "shrink-0" }, /* @__PURE__ */ React.createElement(
60
+ Combobox,
61
+ {
62
+ width: "hug",
63
+ options: countryOptions,
64
+ value: country.iso2,
65
+ onChange: (iso2) => {
66
+ if (iso2) setCountry(iso2);
67
+ },
68
+ placeholder: "Pa\xEDs",
69
+ "aria-label": "Pa\xEDs",
70
+ dropdownMinWidth: 272,
71
+ triggerContent: (sel) => {
72
+ var _a;
73
+ return /* @__PURE__ */ React.createElement("span", { className: "inline-flex items-center [&_svg]:size-4 [&_img]:rounded-(--radius-sm)" }, (_a = sel == null ? void 0 : sel.icon) != null ? _a : /* @__PURE__ */ React.createElement("span", { className: "text-fg-placeholder" }, "Pa\xEDs"));
74
+ }
75
+ }
76
+ )), /* @__PURE__ */ React.createElement("div", { className: ["flex-1 min-w-0 flex items-center rounded-(--radius-control) border bg-surface-default h-10 transition-colors", errorBorder].join(" ") }, /* @__PURE__ */ React.createElement("span", { className: "pl-3 pr-1.5 text-label text-fg-muted select-none shrink-0", "aria-hidden": true }, "+", country.dialCode), /* @__PURE__ */ React.createElement(
77
+ "input",
78
+ {
79
+ id: inputId,
80
+ ref: inputRef,
81
+ type: "tel",
82
+ value: inputValue,
83
+ onChange: handlePhoneValueChange,
84
+ placeholder,
85
+ "aria-invalid": error ? true : void 0,
86
+ className: "flex-1 min-w-0 bg-transparent pr-3 h-full text-label text-fg-primary placeholder:text-fg-placeholder outline-none"
87
+ }
88
+ ))), name && /* @__PURE__ */ React.createElement("input", { type: "hidden", name, value: displayValue }), (error || helper) && /* @__PURE__ */ React.createElement("p", { className: ["text-caption", error ? "text-danger-text" : "text-fg-muted"].join(" ") }, error != null ? error : helper));
89
+ }
90
+ export {
91
+ PhoneInput
92
+ };
@@ -0,0 +1,8 @@
1
+ import * as react from 'react';
2
+ import { SVGProps } from 'react';
3
+
4
+ declare function PixIcon({ size, ...props }: {
5
+ size?: number;
6
+ } & SVGProps<SVGSVGElement>): react.JSX.Element;
7
+
8
+ export { PixIcon };
@@ -0,0 +1,24 @@
1
+ import {
2
+ __objRest,
3
+ __spreadValues
4
+ } from "../chunk-ORMEWXMH.js";
5
+ function PixIcon(_a) {
6
+ var _b = _a, { size = 16 } = _b, props = __objRest(_b, ["size"]);
7
+ return /* @__PURE__ */ React.createElement(
8
+ "svg",
9
+ __spreadValues({
10
+ width: size,
11
+ height: size,
12
+ viewBox: "0 0 512 512",
13
+ fill: "currentColor",
14
+ xmlns: "http://www.w3.org/2000/svg",
15
+ "aria-hidden": "true"
16
+ }, props),
17
+ /* @__PURE__ */ React.createElement("path", { d: "M242.4 292.5c5.4-5.4 14.7-5.4 20.1 0l77 77c14.2 14.2 33.1 22 53.1 22h15.1l-97.1 97.1c-30.3 30.3-79.5 30.3-109.8 0L103.3 391.2h9.3c20 0 38.9-7.8 53.1-22l76.7-76.7z" }),
18
+ /* @__PURE__ */ React.createElement("path", { d: "M262.5 218.9c-5.4 5.4-14.7 5.4-20.1 0l-76.7-76.7c-14.2-14.2-33.1-22-53.1-22h-9.3l97.4-97.4c30.3-30.3 79.5-30.3 109.8 0l97.1 97.1h-15.1c-20 0-38.9 7.8-53.1 22l-77 77z" }),
19
+ /* @__PURE__ */ React.createElement("path", { d: "M112.6 142.7c13.8 0 27.4 5.6 37.2 15.4l76.7 76.7c7.3 7.3 17 10.9 26.6 10.9s19.3-3.6 26.6-10.9l77-77c9.8-9.8 23.4-15.4 37.2-15.4h37.2l58.4 58.4c30.3 30.3 30.3 79.5 0 109.8l-58.4 58.4h-37.2c-13.8 0-27.4-5.6-37.2-15.4l-77-77c-14.2-14.2-39-14.2-53.2 0l-76.7 76.7c-9.8 9.8-23.4 15.4-37.2 15.4H75.4L17 310.7c-30.3-30.3-30.3-79.5 0-109.8l58.4-58.4h37.2z" })
20
+ );
21
+ }
22
+ export {
23
+ PixIcon
24
+ };
@@ -0,0 +1,44 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Popover — overlay flutuante ancorado num trigger. Base genérica de Menu,
6
+ * HoverCard, custom dropdowns. Não tem opinião sobre conteúdo.
7
+ *
8
+ * Uso:
9
+ * <Popover
10
+ * trigger={<Button>Abrir</Button>}
11
+ * placement="bottom-start"
12
+ * >
13
+ * <div className="p-3 bg-surface-default rounded-md shadow-lg">
14
+ * Conteúdo aqui
15
+ * </div>
16
+ * </Popover>
17
+ *
18
+ * Recursos: clique fora fecha, ESC fecha, focus trap opcional, posicionamento
19
+ * com flip automático quando não cabe (top → bottom, etc).
20
+ */
21
+ type PopoverPlacement = 'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end' | 'left-start' | 'left' | 'left-end' | 'right-start' | 'right' | 'right-end';
22
+ interface PopoverProps {
23
+ trigger: ReactNode;
24
+ children: ReactNode | ((api: {
25
+ close: () => void;
26
+ }) => ReactNode);
27
+ /** Posição preferida. flip automático quando não cabe na viewport. */
28
+ placement?: PopoverPlacement;
29
+ /** Distância em px entre trigger e popover. default = 4. */
30
+ offset?: number;
31
+ /** Controla externamente. Se omitido, gerencia interno. */
32
+ open?: boolean;
33
+ onOpenChange?: (open: boolean) => void;
34
+ /** Fecha ao clicar fora. default = true. */
35
+ closeOnOutsideClick?: boolean;
36
+ /** Fecha ao apertar ESC. default = true. */
37
+ closeOnEsc?: boolean;
38
+ className?: string;
39
+ /** Classe CSS do wrapper do trigger. default = "inline-block". */
40
+ triggerClassName?: string;
41
+ }
42
+ declare function Popover({ trigger, children, placement, offset, open: openProp, onOpenChange, closeOnOutsideClick, closeOnEsc, className, triggerClassName, }: PopoverProps): react.JSX.Element;
43
+
44
+ export { Popover, type PopoverPlacement, type PopoverProps };
@@ -0,0 +1,140 @@
1
+ "use client";
2
+ import "../chunk-ORMEWXMH.js";
3
+ import { useEffect, useRef, useState, useId } from "react";
4
+ import { createPortal } from "react-dom";
5
+ function calcPosition(triggerRect, popRect, placement, offset) {
6
+ const { innerWidth: vw, innerHeight: vh } = window;
7
+ let [side, cross = "center"] = placement.split("-");
8
+ let top = 0, left = 0;
9
+ const place = (s, c) => {
10
+ if (s === "bottom") top = triggerRect.bottom + offset;
11
+ else if (s === "top") top = triggerRect.top - popRect.height - offset;
12
+ else if (s === "left") {
13
+ left = triggerRect.left - popRect.width - offset;
14
+ } else if (s === "right") {
15
+ left = triggerRect.right + offset;
16
+ }
17
+ if (s === "top" || s === "bottom") {
18
+ if (c === "start") left = triggerRect.left;
19
+ else if (c === "end") left = triggerRect.right - popRect.width;
20
+ else left = triggerRect.left + (triggerRect.width - popRect.width) / 2;
21
+ } else {
22
+ if (c === "start") top = triggerRect.top;
23
+ else if (c === "end") top = triggerRect.bottom - popRect.height;
24
+ else top = triggerRect.top + (triggerRect.height - popRect.height) / 2;
25
+ }
26
+ };
27
+ place(side, cross);
28
+ if (side === "bottom" && top + popRect.height > vh) {
29
+ side = "top";
30
+ place(side, cross);
31
+ } else if (side === "top" && top < 0) {
32
+ side = "bottom";
33
+ place(side, cross);
34
+ }
35
+ if (side === "right" && left + popRect.width > vw) {
36
+ side = "left";
37
+ place(side, cross);
38
+ } else if (side === "left" && left < 0) {
39
+ side = "right";
40
+ place(side, cross);
41
+ }
42
+ left = Math.max(8, Math.min(left, vw - popRect.width - 8));
43
+ top = Math.max(8, Math.min(top, vh - popRect.height - 8));
44
+ return { top, left, placement: `${side}${cross !== "center" ? `-${cross}` : ""}` };
45
+ }
46
+ function Popover({
47
+ trigger,
48
+ children,
49
+ placement = "bottom-start",
50
+ offset = 4,
51
+ open: openProp,
52
+ onOpenChange,
53
+ closeOnOutsideClick = true,
54
+ closeOnEsc = true,
55
+ className = "",
56
+ triggerClassName
57
+ }) {
58
+ var _a, _b;
59
+ const [internalOpen, setInternalOpen] = useState(false);
60
+ const [position, setPosition] = useState(null);
61
+ const [mounted, setMounted] = useState(false);
62
+ const triggerRef = useRef(null);
63
+ const popRef = useRef(null);
64
+ const id = useId();
65
+ const isControlled = openProp !== void 0;
66
+ const open = isControlled ? openProp : internalOpen;
67
+ const setOpen = (next) => {
68
+ if (!isControlled) setInternalOpen(next);
69
+ onOpenChange == null ? void 0 : onOpenChange(next);
70
+ };
71
+ useEffect(() => {
72
+ setMounted(true);
73
+ }, []);
74
+ useEffect(() => {
75
+ if (!open || !triggerRef.current || !popRef.current) return;
76
+ const update = () => {
77
+ if (!triggerRef.current || !popRef.current) return;
78
+ const trig = triggerRef.current.getBoundingClientRect();
79
+ const pop = popRef.current.getBoundingClientRect();
80
+ setPosition(calcPosition(trig, pop, placement, offset));
81
+ };
82
+ update();
83
+ window.addEventListener("scroll", update, true);
84
+ window.addEventListener("resize", update);
85
+ return () => {
86
+ window.removeEventListener("scroll", update, true);
87
+ window.removeEventListener("resize", update);
88
+ };
89
+ }, [open, placement, offset]);
90
+ useEffect(() => {
91
+ if (!open) return;
92
+ const handleClick = (e) => {
93
+ var _a2, _b2;
94
+ if (!closeOnOutsideClick) return;
95
+ const t = e.target;
96
+ if (((_a2 = popRef.current) == null ? void 0 : _a2.contains(t)) || ((_b2 = triggerRef.current) == null ? void 0 : _b2.contains(t))) return;
97
+ setOpen(false);
98
+ };
99
+ const handleKey = (e) => {
100
+ if (closeOnEsc && e.key === "Escape") setOpen(false);
101
+ };
102
+ document.addEventListener("mousedown", handleClick);
103
+ document.addEventListener("keydown", handleKey);
104
+ return () => {
105
+ document.removeEventListener("mousedown", handleClick);
106
+ document.removeEventListener("keydown", handleKey);
107
+ };
108
+ }, [open, closeOnOutsideClick, closeOnEsc]);
109
+ const close = () => setOpen(false);
110
+ const toggle = () => setOpen(!open);
111
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
112
+ "div",
113
+ {
114
+ ref: triggerRef,
115
+ onClick: toggle,
116
+ role: "none",
117
+ className: triggerClassName != null ? triggerClassName : "inline-block"
118
+ },
119
+ trigger
120
+ ), mounted && open && createPortal(
121
+ /* @__PURE__ */ React.createElement(
122
+ "div",
123
+ {
124
+ ref: popRef,
125
+ id,
126
+ className: ["fixed z-[1000]", className].join(" "),
127
+ style: {
128
+ top: (_a = position == null ? void 0 : position.top) != null ? _a : -9999,
129
+ left: (_b = position == null ? void 0 : position.left) != null ? _b : -9999,
130
+ visibility: position ? "visible" : "hidden"
131
+ }
132
+ },
133
+ typeof children === "function" ? children({ close }) : children
134
+ ),
135
+ document.body
136
+ ));
137
+ }
138
+ export {
139
+ Popover
140
+ };
@@ -0,0 +1,42 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * PricingCard — cartão de plano para páginas de preço (marketing + billing).
6
+ *
7
+ * Props-based para casar com o shape de um catálogo (`/api/public/plans`):
8
+ * nome, preço já formatado, lista de features e um slot de CTA (o consumidor
9
+ * injeta o próprio link/botão — o DS não conhece roteamento nem analytics).
10
+ *
11
+ * `recommended` inverte a superfície (destaque) e mostra o selo de recomendação.
12
+ * `badge` é um acento independente (ex.: "14 dias grátis") em outline.
13
+ *
14
+ * <PricingCard
15
+ * name="Essencial" price="R$49,90" period="/mês"
16
+ * description="Para quem vende todo dia."
17
+ * features={['Produtos ilimitados', 'Controle de estoque']}
18
+ * recommended
19
+ * cta={<a href="/register">Começar</a>}
20
+ * />
21
+ */
22
+ interface PricingCardProps {
23
+ name: string;
24
+ /** Preço já formatado pelo consumidor (ex.: "R$49,90", "R$0", "Grátis"). */
25
+ price: string;
26
+ /** Sufixo do preço (ex.: "/mês"). Omitido em planos sem recorrência. */
27
+ period?: string;
28
+ description?: string;
29
+ features: string[];
30
+ /** Plano em destaque: superfície invertida + selo de recomendação. */
31
+ recommended?: boolean;
32
+ /** Texto do selo de recomendação. default = "Recomendado". */
33
+ recommendedLabel?: string;
34
+ /** Selo de acento independente do destaque (ex.: trial). Renderiza em outline. */
35
+ badge?: string;
36
+ /** Slot do CTA — o consumidor injeta <a>/<Link>/<button> já estilizado ou nu. */
37
+ cta: ReactNode;
38
+ className?: string;
39
+ }
40
+ declare function PricingCard({ name, price, period, description, features, recommended, recommendedLabel, badge, cta, className, }: PricingCardProps): react.JSX.Element;
41
+
42
+ export { PricingCard, type PricingCardProps };
@@ -0,0 +1,29 @@
1
+ import "../chunk-ORMEWXMH.js";
2
+ import { Check } from "lucide-react";
3
+ const CHECK_TONE = {
4
+ recommended: "text-brand-on-accent",
5
+ default: "text-brand-accent"
6
+ };
7
+ function PricingCard({
8
+ name,
9
+ price,
10
+ period,
11
+ description,
12
+ features,
13
+ recommended = false,
14
+ recommendedLabel = "Recomendado",
15
+ badge,
16
+ cta,
17
+ className = ""
18
+ }) {
19
+ const surface = recommended ? "bg-surface-invert text-fg-inverse border border-transparent" : "bg-surface-default text-fg-primary border border-stroke-default";
20
+ const nameTone = recommended ? "text-fg-inverse/70" : "text-fg-muted";
21
+ const descTone = recommended ? "text-fg-inverse/70" : "text-fg-muted";
22
+ const periodTone = recommended ? "text-fg-inverse/60" : "text-fg-muted";
23
+ const featTone = recommended ? "text-fg-inverse/85" : "text-fg-secondary";
24
+ const check = recommended ? CHECK_TONE.recommended : CHECK_TONE.default;
25
+ return /* @__PURE__ */ React.createElement("div", { className: `relative flex flex-col rounded-(--radius-card) p-6 ${surface} ${className}` }, recommended && /* @__PURE__ */ React.createElement("span", { className: "absolute -top-3 left-1/2 -translate-x-1/2 whitespace-nowrap rounded-(--radius-badge) bg-brand-accent px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-brand-on-accent" }, recommendedLabel), badge && /* @__PURE__ */ React.createElement("span", { className: "absolute -top-3 right-4 whitespace-nowrap rounded-(--radius-badge) border border-brand-accent bg-surface-default px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-brand-accent" }, badge), /* @__PURE__ */ React.createElement("p", { className: `text-caption font-semibold uppercase tracking-widest ${nameTone}` }, name), /* @__PURE__ */ React.createElement("div", { className: "mt-3 mb-1 flex items-baseline gap-1" }, /* @__PURE__ */ React.createElement("span", { className: "text-4xl font-bold leading-none tracking-tight tabular-nums" }, price), period && /* @__PURE__ */ React.createElement("span", { className: `text-caption ${periodTone}` }, period)), description && /* @__PURE__ */ React.createElement("p", { className: `mb-5 min-h-10 text-caption ${descTone}` }, description), /* @__PURE__ */ React.createElement("div", { className: "mt-1" }, cta), /* @__PURE__ */ React.createElement("ul", { className: "mt-5 space-y-2" }, features.map((f) => /* @__PURE__ */ React.createElement("li", { key: f, className: `flex items-start gap-2 text-caption ${featTone}` }, /* @__PURE__ */ React.createElement(Check, { size: 14, className: `mt-0.5 shrink-0 ${check}`, "aria-hidden": "true" }), /* @__PURE__ */ React.createElement("span", null, f)))));
26
+ }
27
+ export {
28
+ PricingCard
29
+ };
@@ -0,0 +1,19 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ interface QRDisplayProps {
5
+ /** Imagem do QR — dataURL (PNG) ou URL. Gerada por quem chama (o DS não gera QR). */
6
+ src: string;
7
+ /** Texto alternativo — inclua o contexto/valor pra leitor de tela (a11y). */
8
+ alt?: string;
9
+ /** Lado do QR em px. Renderize 1:1 com o tamanho gerado pra não borrar. */
10
+ size?: number;
11
+ /** Conteúdo abaixo do QR (ex.: instrução curta). */
12
+ caption?: ReactNode;
13
+ /** Slot entre o QR e a caption (ex.: <CopyField/>). */
14
+ children?: ReactNode;
15
+ className?: string;
16
+ }
17
+ declare function QRDisplay({ src, alt, size, caption, children, className, }: QRDisplayProps): react.JSX.Element;
18
+
19
+ export { QRDisplay, type QRDisplayProps };
@@ -0,0 +1,24 @@
1
+ import "../chunk-ORMEWXMH.js";
2
+ function QRDisplay({
3
+ src,
4
+ alt = "QR Code",
5
+ size = 240,
6
+ caption,
7
+ children,
8
+ className = ""
9
+ }) {
10
+ return /* @__PURE__ */ React.createElement("div", { className: ["flex flex-col items-center gap-4", className].join(" ") }, /* @__PURE__ */ React.createElement("div", { className: "rounded-(--radius-card) bg-white p-4 shadow-sm" }, /* @__PURE__ */ React.createElement(
11
+ "img",
12
+ {
13
+ src,
14
+ alt,
15
+ width: size,
16
+ height: size,
17
+ style: { width: size, height: size },
18
+ className: "block"
19
+ }
20
+ )), children, caption && /* @__PURE__ */ React.createElement("div", { className: "max-w-xs text-center text-sm text-fg-secondary leading-snug" }, caption));
21
+ }
22
+ export {
23
+ QRDisplay
24
+ };