@planetaexo/design-system 0.48.2 → 0.49.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.
package/dist/index.d.cts CHANGED
@@ -50,6 +50,12 @@ interface OfferOptionalItem {
50
50
  decreaseQuantityLabel?: string;
51
51
  /** aria-label para o botão de incrementar quantidade. Default: "Increase quantity". */
52
52
  increaseQuantityLabel?: string;
53
+ /**
54
+ * Descrição multilinha do opcional. Quando truthy, exibe ícone "info" ao lado
55
+ * do label que abre um Dialog com o texto integral. Texto plano — preservar
56
+ * `\n` via `whitespace-pre-wrap` no render.
57
+ */
58
+ description?: string;
53
59
  }
54
60
  interface OfferAdventureItem {
55
61
  id: string;
@@ -150,6 +156,15 @@ interface OfferLabels {
150
156
  scheduleCallLabel?: string;
151
157
  atCompanyLabel?: string;
152
158
  };
159
+ /** Labels do modal de descrição do opcional. */
160
+ optionalInfo?: {
161
+ /** aria-label do botão-ícone gatilho. Default EN: "More info". */
162
+ triggerAriaLabel?: string;
163
+ /** Label do botão de fechar do Dialog. Default EN: "Close". */
164
+ closeLabel?: string;
165
+ /** Label da seção "Descrição" dentro do modal. Default EN: "Description". */
166
+ descriptionLabel?: string;
167
+ };
153
168
  /**
154
169
  * Strings do BookingWizard interno (renderizado quando `checkoutSlot` é
155
170
  * undefined — em produção do bookings esse caminho é ofuscado, mas
package/dist/index.d.ts CHANGED
@@ -50,6 +50,12 @@ interface OfferOptionalItem {
50
50
  decreaseQuantityLabel?: string;
51
51
  /** aria-label para o botão de incrementar quantidade. Default: "Increase quantity". */
52
52
  increaseQuantityLabel?: string;
53
+ /**
54
+ * Descrição multilinha do opcional. Quando truthy, exibe ícone "info" ao lado
55
+ * do label que abre um Dialog com o texto integral. Texto plano — preservar
56
+ * `\n` via `whitespace-pre-wrap` no render.
57
+ */
58
+ description?: string;
53
59
  }
54
60
  interface OfferAdventureItem {
55
61
  id: string;
@@ -150,6 +156,15 @@ interface OfferLabels {
150
156
  scheduleCallLabel?: string;
151
157
  atCompanyLabel?: string;
152
158
  };
159
+ /** Labels do modal de descrição do opcional. */
160
+ optionalInfo?: {
161
+ /** aria-label do botão-ícone gatilho. Default EN: "More info". */
162
+ triggerAriaLabel?: string;
163
+ /** Label do botão de fechar do Dialog. Default EN: "Close". */
164
+ closeLabel?: string;
165
+ /** Label da seção "Descrição" dentro do modal. Default EN: "Description". */
166
+ descriptionLabel?: string;
167
+ };
153
168
  /**
154
169
  * Strings do BookingWizard interno (renderizado quando `checkoutSlot` é
155
170
  * undefined — em produção do bookings esse caminho é ofuscado, mas
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { cva } from 'class-variance-authority';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { XIcon, ChevronDownIcon, CalendarIcon, SearchIcon, ChevronRightIcon, ArrowLeftIcon, CheckCircle2Icon, MapIcon, LogOutIcon, UsersIcon, CreditCardIcon, AlertCircleIcon, MinusIcon, PlusIcon, CircleCheckIcon, SlidersHorizontalIcon, ChevronLeftIcon, HomeIcon, SailboatIcon, CarIcon, WavesIcon, FootprintsIcon, InfoIcon, ClockIcon, CheckIcon, ChevronUpIcon, MenuIcon, UserIcon, SunIcon, MoonIcon, MapPinIcon, PackageIcon, BedDoubleIcon, UtensilsIcon, CompassIcon, BackpackIcon, CherryIcon, ReceiptIcon, Loader2Icon, SendIcon, CheckCircleIcon, MailIcon, PhoneIcon, MessageCircleIcon, UserPlusIcon, ExternalLinkIcon, CopyIcon, PencilIcon, Trash2Icon, UserMinusIcon, AlertTriangleIcon, ZoomInIcon, StarIcon, TwitterIcon, YoutubeIcon, LinkedinIcon, InstagramIcon, FacebookIcon, ArrowRightIcon, LayoutGridIcon } from 'lucide-react';
7
+ import { XIcon, ChevronDownIcon, CalendarIcon, SearchIcon, ChevronRightIcon, ArrowLeftIcon, CheckCircle2Icon, MapIcon, LogOutIcon, UsersIcon, CreditCardIcon, AlertCircleIcon, MinusIcon, PlusIcon, CircleCheckIcon, SlidersHorizontalIcon, ChevronLeftIcon, HomeIcon, SailboatIcon, CarIcon, WavesIcon, FootprintsIcon, InfoIcon, ClockIcon, CheckIcon, ChevronUpIcon, MenuIcon, UserIcon, SunIcon, MoonIcon, MapPinIcon, PackageIcon, BedDoubleIcon, UtensilsIcon, CompassIcon, BackpackIcon, CherryIcon, ReceiptIcon, Loader2Icon, SendIcon, CheckCircleIcon, Info, MailIcon, PhoneIcon, MessageCircleIcon, UserPlusIcon, ExternalLinkIcon, CopyIcon, PencilIcon, Trash2Icon, UserMinusIcon, AlertTriangleIcon, ZoomInIcon, StarIcon, TwitterIcon, YoutubeIcon, LinkedinIcon, InstagramIcon, FacebookIcon, ArrowRightIcon, LayoutGridIcon } from 'lucide-react';
8
8
  import { Separator as Separator$1 } from '@base-ui/react/separator';
9
9
  import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
10
10
  import { Button as Button$1 } from '@base-ui/react/button';
@@ -227,7 +227,7 @@ function DialogContent(_a) {
227
227
  Button2,
228
228
  {
229
229
  variant: "ghost",
230
- className: "absolute top-2 right-2",
230
+ className: "absolute top-2 right-2 cursor-pointer",
231
231
  size: "icon-sm"
232
232
  }
233
233
  ),
@@ -1274,11 +1274,13 @@ function AdventureCard({
1274
1274
  labels,
1275
1275
  interactionsDisabled
1276
1276
  }) {
1277
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1277
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
1278
1278
  const isControlled = (_b = (_a = adventure.optionals) == null ? void 0 : _a.some((o) => o.onCheckedChange !== void 0)) != null ? _b : false;
1279
1279
  const [checkedInternal, setCheckedInternal] = React28.useState(
1280
1280
  new Set((_d = (_c = adventure.optionals) == null ? void 0 : _c.filter((o) => o.defaultChecked).map((o) => o.id)) != null ? _d : [])
1281
1281
  );
1282
+ const [openDescriptionId, setOpenDescriptionId] = React28.useState(null);
1283
+ const openDescriptionOptional = openDescriptionId ? (_e = adventure.optionals) == null ? void 0 : _e.find((o) => o.id === openDescriptionId) : void 0;
1282
1284
  const isChecked = (opt) => {
1283
1285
  var _a2;
1284
1286
  return isControlled ? (_a2 = opt.checked) != null ? _a2 : false : checkedInternal.has(opt.id);
@@ -1300,7 +1302,7 @@ function AdventureCard({
1300
1302
  "img",
1301
1303
  {
1302
1304
  src: adventure.image,
1303
- alt: (_e = adventure.imageAlt) != null ? _e : adventure.title,
1305
+ alt: (_f = adventure.imageAlt) != null ? _f : adventure.title,
1304
1306
  className: "w-full h-full object-cover"
1305
1307
  }
1306
1308
  ) }),
@@ -1315,7 +1317,7 @@ function AdventureCard({
1315
1317
  className: "flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-xs text-muted-foreground font-ui hover:border-destructive hover:text-destructive transition-colors",
1316
1318
  children: [
1317
1319
  /* @__PURE__ */ jsx(XIcon, { className: "w-3 h-3" }),
1318
- (_f = labels == null ? void 0 : labels.remove) != null ? _f : "Remove"
1320
+ (_g = labels == null ? void 0 : labels.remove) != null ? _g : "Remove"
1319
1321
  ]
1320
1322
  }
1321
1323
  )
@@ -1332,9 +1334,9 @@ function AdventureCard({
1332
1334
  adventure.location
1333
1335
  ] }),
1334
1336
  adventure.optionals && adventure.optionals.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded-xl border border-border bg-muted/30 p-4 flex flex-col gap-3", children: [
1335
- /* @__PURE__ */ jsx("p", { className: "text-[10px] font-bold text-muted-foreground font-heading uppercase tracking-widest", children: (_g = labels == null ? void 0 : labels.availableOptionals) != null ? _g : "Available optionals" }),
1337
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] font-bold text-muted-foreground font-heading uppercase tracking-widest", children: (_h = labels == null ? void 0 : labels.availableOptionals) != null ? _h : "Available optionals" }),
1336
1338
  /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: adventure.optionals.map((opt) => {
1337
- var _a2, _b2, _c2, _d2, _e2;
1339
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
1338
1340
  const checked = isChecked(opt);
1339
1341
  const minQty = (_a2 = opt.minQuantity) != null ? _a2 : 1;
1340
1342
  const maxQty = (_b2 = opt.maxQuantity) != null ? _b2 : 50;
@@ -1342,6 +1344,7 @@ function AdventureCard({
1342
1344
  const currentQty = (_c2 = opt.quantity) != null ? _c2 : minQty;
1343
1345
  const canDec = currentQty > minQty;
1344
1346
  const canInc = currentQty < maxQty;
1347
+ const hasDescription = !!((_d2 = opt.description) == null ? void 0 : _d2.trim());
1345
1348
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-center gap-x-3 gap-y-1.5", interactionsDisabled && "opacity-60"), children: [
1346
1349
  /* @__PURE__ */ jsxs("label", { className: cn("flex items-center gap-3 group", interactionsDisabled ? "cursor-not-allowed" : "cursor-pointer"), children: [
1347
1350
  /* @__PURE__ */ jsx(
@@ -1367,6 +1370,19 @@ function AdventureCard({
1367
1370
  ] })
1368
1371
  ] })
1369
1372
  ] }),
1373
+ hasDescription && /* @__PURE__ */ jsx(
1374
+ "button",
1375
+ {
1376
+ type: "button",
1377
+ onClick: (e) => {
1378
+ e.stopPropagation();
1379
+ setOpenDescriptionId(opt.id);
1380
+ },
1381
+ "aria-label": (_f2 = (_e2 = labels == null ? void 0 : labels.optionalInfo) == null ? void 0 : _e2.triggerAriaLabel) != null ? _f2 : "More info",
1382
+ className: "inline-flex cursor-pointer items-center justify-center text-muted-foreground hover:text-primary transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded",
1383
+ children: /* @__PURE__ */ jsx(Info, { className: "w-4 h-4" })
1384
+ }
1385
+ ),
1370
1386
  showStepper && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 ml-auto", children: [
1371
1387
  /* @__PURE__ */ jsx(
1372
1388
  "button",
@@ -1377,7 +1393,7 @@ function AdventureCard({
1377
1393
  return !interactionsDisabled && canDec && ((_a3 = opt.onQuantityChange) == null ? void 0 : _a3.call(opt, opt.id, currentQty - 1));
1378
1394
  },
1379
1395
  disabled: interactionsDisabled || !canDec,
1380
- "aria-label": (_d2 = opt.decreaseQuantityLabel) != null ? _d2 : "Decrease quantity",
1396
+ "aria-label": (_g2 = opt.decreaseQuantityLabel) != null ? _g2 : "Decrease quantity",
1381
1397
  className: cn(
1382
1398
  "h-7 w-7 rounded border border-border flex items-center justify-center text-sm font-semibold",
1383
1399
  "transition-colors",
@@ -1396,7 +1412,7 @@ function AdventureCard({
1396
1412
  return !interactionsDisabled && canInc && ((_a3 = opt.onQuantityChange) == null ? void 0 : _a3.call(opt, opt.id, currentQty + 1));
1397
1413
  },
1398
1414
  disabled: interactionsDisabled || !canInc,
1399
- "aria-label": (_e2 = opt.increaseQuantityLabel) != null ? _e2 : "Increase quantity",
1415
+ "aria-label": (_h2 = opt.increaseQuantityLabel) != null ? _h2 : "Increase quantity",
1400
1416
  className: cn(
1401
1417
  "h-7 w-7 rounded border border-border flex items-center justify-center text-sm font-semibold",
1402
1418
  "transition-colors",
@@ -1411,12 +1427,31 @@ function AdventureCard({
1411
1427
  opt.scheduledAtLabel
1412
1428
  ] })
1413
1429
  ] }, opt.id);
1414
- }) })
1430
+ }) }),
1431
+ /* @__PURE__ */ jsx(
1432
+ Dialog,
1433
+ {
1434
+ open: openDescriptionId !== null,
1435
+ onOpenChange: (open) => !open && setOpenDescriptionId(null),
1436
+ children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-lg max-h-[85vh] overflow-y-auto p-6 sm:max-w-lg", children: [
1437
+ /* @__PURE__ */ jsxs(DialogHeader, { className: "gap-3 pr-8", children: [
1438
+ /* @__PURE__ */ jsx(DialogTitle, { className: "font-heading text-xl font-bold text-foreground leading-snug", children: (_i = openDescriptionOptional == null ? void 0 : openDescriptionOptional.label) != null ? _i : "" }),
1439
+ (openDescriptionOptional == null ? void 0 : openDescriptionOptional.pricePerPerson) && /* @__PURE__ */ jsx("span", { className: "inline-flex w-fit items-center rounded-full bg-primary/10 px-3 py-1 text-sm font-semibold text-primary font-heading", children: openDescriptionOptional.pricePerPerson })
1440
+ ] }),
1441
+ /* @__PURE__ */ jsx(Separator, {}),
1442
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
1443
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] font-bold text-muted-foreground font-heading uppercase tracking-widest", children: (_k = (_j = labels == null ? void 0 : labels.optionalInfo) == null ? void 0 : _j.descriptionLabel) != null ? _k : "Description" }),
1444
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-sans text-foreground leading-relaxed whitespace-pre-wrap", children: (_l = openDescriptionOptional == null ? void 0 : openDescriptionOptional.description) != null ? _l : "" })
1445
+ ] }),
1446
+ /* @__PURE__ */ jsx("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsx(DialogClose, { className: "cursor-pointer px-4 py-2 rounded-lg bg-primary text-primary-foreground text-sm font-heading font-semibold hover:bg-primary/90 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: (_n = (_m = labels == null ? void 0 : labels.optionalInfo) == null ? void 0 : _m.closeLabel) != null ? _n : "Close" }) })
1447
+ ] })
1448
+ }
1449
+ )
1415
1450
  ] }),
1416
1451
  (adventure.description || adventure.detailsSlot) && /* @__PURE__ */ jsxs(Fragment, { children: [
1417
1452
  /* @__PURE__ */ jsx(Separator, { className: "my-1" }),
1418
1453
  /* @__PURE__ */ jsxs("div", { children: [
1419
- /* @__PURE__ */ jsx("p", { className: "text-[10px] font-bold text-muted-foreground font-heading uppercase tracking-widest mb-3", children: (_h = adventure.itineraryLabel) != null ? _h : "Details" }),
1454
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] font-bold text-muted-foreground font-heading uppercase tracking-widest mb-3", children: (_o = adventure.itineraryLabel) != null ? _o : "Details" }),
1420
1455
  adventure.description && !adventure.detailsSlot && /* @__PURE__ */ jsx("p", { className: "text-base text-foreground/80 leading-snug font-sans", children: adventure.description }),
1421
1456
  adventure.detailsSlot && /* @__PURE__ */ jsx("div", { className: cn(
1422
1457
  "text-foreground",
@@ -1442,21 +1477,21 @@ function AdventureCard({
1442
1477
  ] })
1443
1478
  ] }),
1444
1479
  adventure.included && adventure.included.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 mt-1", children: [
1445
- /* @__PURE__ */ jsx("h4", { className: "text-base font-bold text-foreground font-heading", children: (_i = adventure.includedLabel) != null ? _i : "What's included" }),
1480
+ /* @__PURE__ */ jsx("h4", { className: "text-base font-bold text-foreground font-heading", children: (_p = adventure.includedLabel) != null ? _p : "What's included" }),
1446
1481
  /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: adventure.included.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-base text-foreground/80 font-sans", children: [
1447
1482
  /* @__PURE__ */ jsx(CheckIcon, { className: "w-4 h-4 text-primary shrink-0 mt-1" }),
1448
1483
  item
1449
1484
  ] }, i)) })
1450
1485
  ] }),
1451
1486
  adventure.notIncluded && adventure.notIncluded.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 mt-1", children: [
1452
- /* @__PURE__ */ jsx("h4", { className: "text-base font-bold text-foreground font-heading", children: (_j = adventure.notIncludedLabel) != null ? _j : "What's not included" }),
1487
+ /* @__PURE__ */ jsx("h4", { className: "text-base font-bold text-foreground font-heading", children: (_q = adventure.notIncludedLabel) != null ? _q : "What's not included" }),
1453
1488
  /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: adventure.notIncluded.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-base text-foreground/80 font-sans", children: [
1454
1489
  /* @__PURE__ */ jsx(XIcon, { className: "w-4 h-4 text-destructive shrink-0 mt-1" }),
1455
1490
  item
1456
1491
  ] }, i)) })
1457
1492
  ] }),
1458
1493
  adventure.cancellationPolicy && adventure.cancellationPolicy.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 mt-1", children: [
1459
- /* @__PURE__ */ jsx("h4", { className: "text-base font-bold text-foreground font-heading", children: (_k = adventure.cancellationPolicyLabel) != null ? _k : "Cancellation policy" }),
1494
+ /* @__PURE__ */ jsx("h4", { className: "text-base font-bold text-foreground font-heading", children: (_r = adventure.cancellationPolicyLabel) != null ? _r : "Cancellation policy" }),
1460
1495
  /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: adventure.cancellationPolicy.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-base text-muted-foreground font-sans", children: [
1461
1496
  /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-primary shrink-0 mt-2.5" }),
1462
1497
  item