@voyantjs/products-ui 0.19.0 → 0.21.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.
@@ -0,0 +1,14 @@
1
+ import type { CatalogSearchHit } from "@voyantjs/catalog-react";
2
+ export interface ProductCatalogCardProps {
3
+ hit: CatalogSearchHit;
4
+ /** Click handler — usually a router push to the product detail page. */
5
+ onClick?: (hit: CatalogSearchHit) => void;
6
+ className?: string;
7
+ }
8
+ /**
9
+ * Search-result card for a product hit. Reads `name`, `status`,
10
+ * `productTypeId`, `bookingMode`, `sellAmountCents`, `sellCurrency`,
11
+ * `tags` from the resolved indexer document.
12
+ */
13
+ export declare function ProductCatalogCard({ hit, onClick, className }: ProductCatalogCardProps): import("react/jsx-runtime").JSX.Element;
14
+ //# sourceMappingURL=product-catalog-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product-catalog-card.d.ts","sourceRoot":"","sources":["../../src/components/product-catalog-card.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAK/D,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,gBAAgB,CAAA;IACrB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,uBAAuB,2CAoDtF"}
@@ -0,0 +1,44 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Badge } from "@voyantjs/ui/components/badge";
4
+ import { Card, CardContent } from "@voyantjs/ui/components/card";
5
+ import { cn } from "@voyantjs/ui/lib/utils";
6
+ /**
7
+ * Search-result card for a product hit. Reads `name`, `status`,
8
+ * `productTypeId`, `bookingMode`, `sellAmountCents`, `sellCurrency`,
9
+ * `tags` from the resolved indexer document.
10
+ */
11
+ export function ProductCatalogCard({ hit, onClick, className }) {
12
+ const fields = hit.document.fields;
13
+ const name = stringOr(fields.name, "Untitled product");
14
+ const status = stringOr(fields.status, null);
15
+ const bookingMode = stringOr(fields.bookingMode, null);
16
+ const sellAmount = numberOr(fields.sellAmountCents, null);
17
+ const sellCurrency = stringOr(fields.sellCurrency, null);
18
+ const tags = stringArray(fields.tags);
19
+ const price = sellAmount != null && sellCurrency
20
+ ? new Intl.NumberFormat(undefined, {
21
+ style: "currency",
22
+ currency: sellCurrency,
23
+ maximumFractionDigits: 0,
24
+ }).format(sellAmount / 100)
25
+ : null;
26
+ return (_jsx(Card, { className: cn("h-full cursor-pointer transition-colors hover:border-primary/40", onClick == null && "cursor-default", className), onClick: onClick ? () => onClick(hit) : undefined, children: _jsxs(CardContent, { className: "flex h-full flex-col gap-2 p-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsx("h3", { className: "line-clamp-2 font-medium text-sm", children: name }), status && (_jsx(Badge, { variant: status === "active" ? "default" : "secondary", className: "shrink-0", children: status }))] }), _jsxs("div", { className: "flex items-center gap-2 text-muted-foreground text-xs", children: [bookingMode && _jsx("span", { children: bookingMode }), price && _jsx("span", { className: "ml-auto font-medium text-foreground", children: price })] }), tags.length > 0 && (_jsx("div", { className: "mt-auto flex flex-wrap gap-1", children: tags.slice(0, 4).map((tag) => (_jsx(Badge, { variant: "outline", className: "text-[10px]", children: tag }, tag))) }))] }) }));
27
+ }
28
+ function stringOr(value, fallback) {
29
+ return typeof value === "string" && value.length > 0 ? value : fallback;
30
+ }
31
+ function numberOr(value, fallback) {
32
+ if (typeof value === "number")
33
+ return value;
34
+ if (typeof value === "string") {
35
+ const n = Number(value);
36
+ return Number.isFinite(n) ? n : fallback;
37
+ }
38
+ return fallback;
39
+ }
40
+ function stringArray(value) {
41
+ if (!Array.isArray(value))
42
+ return [];
43
+ return value.filter((v) => typeof v === "string" && v.length > 0);
44
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"product-category-form.d.ts","sourceRoot":"","sources":["../../src/components/product-category-form.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,0BAA0B,CAAA;AAYjC,KAAK,IAAI,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,qBAAqB,CAAA;CAAE,CAAA;AAElF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACrD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AA6CD,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,wBAAwB,2CAkI1F"}
1
+ {"version":3,"file":"product-category-form.d.ts","sourceRoot":"","sources":["../../src/components/product-category-form.tsx"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,qBAAqB,EAE3B,MAAM,0BAA0B,CAAA;AAYjC,KAAK,IAAI,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,qBAAqB,CAAA;CAAE,CAAA;AAElF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACrD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAmDD,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,wBAAwB,2CAqJ1F"}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { PaymentPolicyForm, PaymentPolicyPreview } from "@voyantjs/finance-ui";
3
4
  import { useProductCategoryMutation, } from "@voyantjs/products-react";
4
5
  import { Button } from "@voyantjs/ui/components/button";
5
6
  import { Input } from "@voyantjs/ui/components/input";
@@ -20,6 +21,7 @@ function initialState(mode) {
20
21
  description: category.description ?? "",
21
22
  sortOrder: String(category.sortOrder),
22
23
  active: category.active,
24
+ customerPaymentPolicy: category.customerPaymentPolicy ?? null,
23
25
  };
24
26
  }
25
27
  return {
@@ -29,6 +31,7 @@ function initialState(mode) {
29
31
  description: "",
30
32
  sortOrder: "0",
31
33
  active: true,
34
+ customerPaymentPolicy: null,
32
35
  };
33
36
  }
34
37
  function toPayload(state) {
@@ -39,6 +42,7 @@ function toPayload(state) {
39
42
  description: state.description.trim() || null,
40
43
  sortOrder: Number(state.sortOrder) || 0,
41
44
  active: state.active,
45
+ customerPaymentPolicy: state.customerPaymentPolicy ?? null,
42
46
  };
43
47
  }
44
48
  export function ProductCategoryForm({ mode, onSuccess, onCancel }) {
@@ -72,7 +76,7 @@ export function ProductCategoryForm({ mode, onSuccess, onCancel }) {
72
76
  setError(err instanceof Error ? err.message : messages.productCategoryForm.validation.saveFailed);
73
77
  }
74
78
  };
75
- return (_jsxs("form", { "data-slot": "product-category-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-name", children: messages.productCategoryForm.fields.name }), _jsx(Input, { id: "product-category-name", required: true, autoFocus: true, value: state.name, onChange: (event) => setState((prev) => ({ ...prev, name: event.target.value })), placeholder: messages.productCategoryForm.placeholders.name })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-slug", children: messages.productCategoryForm.fields.slug }), _jsx(Input, { id: "product-category-slug", required: true, value: state.slug, onChange: (event) => setState((prev) => ({ ...prev, slug: event.target.value })), placeholder: messages.productCategoryForm.placeholders.slug })] })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { children: messages.productCategoryForm.fields.parentCategory }), _jsx(ProductCategoryCombobox, { value: state.parentId === "__none__" ? null : state.parentId, onChange: (value) => setState((prev) => ({ ...prev, parentId: value ?? "__none__" })), excludeId: mode.kind === "edit" ? mode.category.id : null, placeholder: messages.productCategoryForm.placeholders.parentCategory })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-description", children: messages.productCategoryForm.fields.description }), _jsx(Textarea, { id: "product-category-description", value: state.description, onChange: (event) => setState((prev) => ({ ...prev, description: event.target.value })), placeholder: messages.productCategoryForm.placeholders.description })] }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-sort-order", children: messages.productCategoryForm.fields.sortOrder }), _jsx(Input, { id: "product-category-sort-order", type: "number", value: state.sortOrder, onChange: (event) => setState((prev) => ({ ...prev, sortOrder: event.target.value })) })] }), _jsxs("div", { className: "flex items-center gap-2 pt-7", children: [_jsx(Switch, { checked: state.active, onCheckedChange: (active) => setState((prev) => ({ ...prev, active })) }), _jsx(Label, { children: messages.productCategoryForm.fields.active })] })] }), error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null, _jsxs("div", { className: "flex items-center justify-end gap-2", children: [onCancel ? (_jsx(Button, { type: "button", variant: "ghost", onClick: onCancel, children: messages.common.cancel })) : null, _jsxs(Button, { type: "submit", disabled: isSubmitting, children: [isSubmitting ? (_jsx(Loader2, { className: "mr-2 size-4 animate-spin", "aria-hidden": "true" })) : null, mode.kind === "edit"
79
+ return (_jsxs("form", { "data-slot": "product-category-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-name", children: messages.productCategoryForm.fields.name }), _jsx(Input, { id: "product-category-name", required: true, autoFocus: true, value: state.name, onChange: (event) => setState((prev) => ({ ...prev, name: event.target.value })), placeholder: messages.productCategoryForm.placeholders.name })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-slug", children: messages.productCategoryForm.fields.slug }), _jsx(Input, { id: "product-category-slug", required: true, value: state.slug, onChange: (event) => setState((prev) => ({ ...prev, slug: event.target.value })), placeholder: messages.productCategoryForm.placeholders.slug })] })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { children: messages.productCategoryForm.fields.parentCategory }), _jsx(ProductCategoryCombobox, { value: state.parentId === "__none__" ? null : state.parentId, onChange: (value) => setState((prev) => ({ ...prev, parentId: value ?? "__none__" })), excludeId: mode.kind === "edit" ? mode.category.id : null, placeholder: messages.productCategoryForm.placeholders.parentCategory })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-description", children: messages.productCategoryForm.fields.description }), _jsx(Textarea, { id: "product-category-description", value: state.description, onChange: (event) => setState((prev) => ({ ...prev, description: event.target.value })), placeholder: messages.productCategoryForm.placeholders.description })] }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "product-category-sort-order", children: messages.productCategoryForm.fields.sortOrder }), _jsx(Input, { id: "product-category-sort-order", type: "number", value: state.sortOrder, onChange: (event) => setState((prev) => ({ ...prev, sortOrder: event.target.value })) })] }), _jsxs("div", { className: "flex items-center gap-2 pt-7", children: [_jsx(Switch, { checked: state.active, onCheckedChange: (active) => setState((prev) => ({ ...prev, active })) }), _jsx(Label, { children: messages.productCategoryForm.fields.active })] })] }), _jsxs("div", { className: "flex flex-col gap-3 rounded-md border bg-muted/10 p-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-medium", children: "Customer payment policy" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "When set, products in this category inherit these terms unless the listing or booking sets its own override. Wins over the supplier-level policy." })] }), _jsxs("div", { className: "grid gap-4 lg:grid-cols-[2fr_1fr]", children: [_jsx(PaymentPolicyForm, { value: state.customerPaymentPolicy, onChange: (next) => setState((prev) => ({ ...prev, customerPaymentPolicy: next })), inheritable: true, disabled: isSubmitting }), _jsx(PaymentPolicyPreview, { policy: state.customerPaymentPolicy })] })] }), error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null, _jsxs("div", { className: "flex items-center justify-end gap-2", children: [onCancel ? (_jsx(Button, { type: "button", variant: "ghost", onClick: onCancel, children: messages.common.cancel })) : null, _jsxs(Button, { type: "submit", disabled: isSubmitting, children: [isSubmitting ? (_jsx(Loader2, { className: "mr-2 size-4 animate-spin", "aria-hidden": "true" })) : null, mode.kind === "edit"
76
80
  ? messages.common.saveChanges
77
81
  : messages.productCategoryForm.actions.createCategory] })] })] }));
78
82
  }
@@ -3,9 +3,11 @@ export interface ProductDayDialogProps {
3
3
  open: boolean;
4
4
  onOpenChange: (open: boolean) => void;
5
5
  productId: string;
6
+ /** Optional. When set, new days are created against this itinerary. */
7
+ itineraryId?: string;
6
8
  day?: ProductDayRecord;
7
9
  nextDayNumber?: number;
8
10
  onSuccess?: (day: ProductDayRecord) => void;
9
11
  }
10
- export declare function ProductDayDialog({ open, onOpenChange, productId, day, nextDayNumber, onSuccess, }: ProductDayDialogProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function ProductDayDialog({ open, onOpenChange, productId, itineraryId, day, nextDayNumber, onSuccess, }: ProductDayDialogProps): import("react/jsx-runtime").JSX.Element;
11
13
  //# sourceMappingURL=product-day-dialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"product-day-dialog.d.ts","sourceRoot":"","sources":["../../src/components/product-day-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAahE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,gBAAgB,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAA;CAC5C;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,GAAG,EACH,aAAa,EACb,SAAS,GACV,EAAE,qBAAqB,2CAgCvB"}
1
+ {"version":3,"file":"product-day-dialog.d.ts","sourceRoot":"","sources":["../../src/components/product-day-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAahE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,GAAG,CAAC,EAAE,gBAAgB,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAA;CAC5C;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,WAAW,EACX,GAAG,EACH,aAAa,EACb,SAAS,GACV,EAAE,qBAAqB,2CAkCvB"}
@@ -3,14 +3,16 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@voyantjs/ui/components/dialog";
4
4
  import { useProductsUiMessagesOrDefault } from "../i18n/provider";
5
5
  import { ProductDayForm } from "./product-day-form";
6
- export function ProductDayDialog({ open, onOpenChange, productId, day, nextDayNumber, onSuccess, }) {
6
+ export function ProductDayDialog({ open, onOpenChange, productId, itineraryId, day, nextDayNumber, onSuccess, }) {
7
7
  const isEdit = Boolean(day);
8
8
  const messages = useProductsUiMessagesOrDefault();
9
9
  return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { "data-slot": "product-day-dialog", className: "sm:max-w-[640px]", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: isEdit
10
10
  ? messages.productDayDialog.titles.edit
11
11
  : messages.productDayDialog.titles.create }), _jsx(DialogDescription, { children: isEdit
12
12
  ? messages.productDayDialog.descriptions.edit
13
- : messages.productDayDialog.descriptions.create })] }), _jsx(ProductDayForm, { mode: day ? { kind: "edit", productId, day } : { kind: "create", productId, nextDayNumber }, onSuccess: (savedDay) => {
13
+ : messages.productDayDialog.descriptions.create })] }), _jsx(ProductDayForm, { mode: day
14
+ ? { kind: "edit", productId, day }
15
+ : { kind: "create", productId, itineraryId, nextDayNumber }, onSuccess: (savedDay) => {
14
16
  onSuccess?.(savedDay);
15
17
  onOpenChange(false);
16
18
  }, onCancel: () => onOpenChange(false) })] }) }));
@@ -2,6 +2,7 @@ import { type ProductDayRecord } from "@voyantjs/products-react";
2
2
  type Mode = {
3
3
  kind: "create";
4
4
  productId: string;
5
+ itineraryId?: string;
5
6
  nextDayNumber?: number;
6
7
  } | {
7
8
  kind: "edit";
@@ -1 +1 @@
1
- {"version":3,"file":"product-day-form.d.ts","sourceRoot":"","sources":["../../src/components/product-day-form.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,gBAAgB,EAAyB,MAAM,0BAA0B,CAAA;AAUvF,KAAK,IAAI,GACL;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,gBAAgB,CAAA;CAAE,CAAA;AAE9D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AA2BD,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CA0HhF"}
1
+ {"version":3,"file":"product-day-form.d.ts","sourceRoot":"","sources":["../../src/components/product-day-form.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,gBAAgB,EAAyB,MAAM,0BAA0B,CAAA;AAUvF,KAAK,IAAI,GACL;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,gBAAgB,CAAA;CAAE,CAAA;AAE9D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AA2BD,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CA8HhF"}
@@ -53,7 +53,11 @@ export function ProductDayForm({ mode, onSuccess, onCancel }) {
53
53
  };
54
54
  try {
55
55
  const day = mode.kind === "create"
56
- ? await create.mutateAsync({ productId: mode.productId, ...payload })
56
+ ? await create.mutateAsync({
57
+ productId: mode.productId,
58
+ itineraryId: mode.itineraryId,
59
+ ...payload,
60
+ })
57
61
  : await update.mutateAsync({
58
62
  productId: mode.productId,
59
63
  dayId: mode.day.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/products-ui",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,6 +15,9 @@
15
15
  "import": "./dist/index.js",
16
16
  "default": "./dist/index.js"
17
17
  },
18
+ "./styles.css": {
19
+ "default": "./src/styles.css"
20
+ },
18
21
  "./i18n": {
19
22
  "types": "./dist/i18n/index.d.ts",
20
23
  "import": "./dist/i18n/index.js",
@@ -40,14 +43,17 @@
40
43
  "@tanstack/react-query": "^5.0.0",
41
44
  "react": "^19.0.0",
42
45
  "react-dom": "^19.0.0",
43
- "@voyantjs/availability-react": "0.19.0",
44
- "@voyantjs/pricing-react": "0.19.0",
45
- "@voyantjs/products-react": "0.19.0",
46
- "@voyantjs/suppliers-react": "0.19.0",
47
- "@voyantjs/ui": "0.19.0"
46
+ "@voyantjs/availability-react": "0.21.0",
47
+ "@voyantjs/catalog-react": "0.21.0",
48
+ "@voyantjs/finance": "0.21.0",
49
+ "@voyantjs/finance-ui": "0.21.0",
50
+ "@voyantjs/pricing-react": "0.21.0",
51
+ "@voyantjs/products-react": "0.21.0",
52
+ "@voyantjs/suppliers-react": "0.21.0",
53
+ "@voyantjs/ui": "0.21.0"
48
54
  },
49
55
  "dependencies": {
50
- "@voyantjs/i18n": "0.19.0"
56
+ "@voyantjs/i18n": "0.21.0"
51
57
  },
52
58
  "devDependencies": {
53
59
  "@tanstack/react-query": "^5.96.2",
@@ -58,16 +64,20 @@
58
64
  "react-dom": "^19.2.4",
59
65
  "typescript": "^6.0.2",
60
66
  "vitest": "^4.1.2",
61
- "@voyantjs/availability-react": "0.19.0",
62
- "@voyantjs/i18n": "0.19.0",
63
- "@voyantjs/pricing-react": "0.19.0",
64
- "@voyantjs/products-react": "0.19.0",
65
- "@voyantjs/suppliers-react": "0.19.0",
67
+ "@voyantjs/availability-react": "0.21.0",
68
+ "@voyantjs/catalog-react": "0.21.0",
69
+ "@voyantjs/finance": "0.21.0",
70
+ "@voyantjs/finance-ui": "0.21.0",
71
+ "@voyantjs/i18n": "0.21.0",
72
+ "@voyantjs/pricing-react": "0.21.0",
73
+ "@voyantjs/products-react": "0.21.0",
74
+ "@voyantjs/suppliers-react": "0.21.0",
66
75
  "@voyantjs/voyant-typescript-config": "0.1.0",
67
- "@voyantjs/ui": "0.19.0"
76
+ "@voyantjs/ui": "0.21.0"
68
77
  },
69
78
  "files": [
70
- "dist"
79
+ "dist",
80
+ "src/styles.css"
71
81
  ],
72
82
  "publishConfig": {
73
83
  "access": "public"
package/src/styles.css ADDED
@@ -0,0 +1,11 @@
1
+ /* Tailwind v4 source-detection helper.
2
+ *
3
+ * Templates that consume this package should `@import` this CSS so Tailwind
4
+ * scans these component files for utility classes:
5
+ *
6
+ * @import "@voyantjs/<domain>-ui/styles.css";
7
+ *
8
+ * Without it, classes that only appear inside this package (e.g. data-attr
9
+ * variants on primitives) won't be compiled into the final bundle.
10
+ */
11
+ @source "./components/**/*.{ts,tsx}";