@voyantjs/resources-ui 0.13.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/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # @voyantjs/resources-ui
2
+
3
+ Importable React UI components for Voyant resources. Bundler-consumed (Vite, Next.js, webpack, etc.).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @voyantjs/resources-ui @voyantjs/resources-react @voyantjs/voyant-ui @tanstack/react-query react react-dom
9
+ ```
10
+
11
+ `@voyantjs/voyant-ui` provides the design-system primitives. `@voyantjs/resources-react` provides the data-layer hooks. Both are required peers.
12
+
13
+ All components accept a `className` prop and merge it with `cn()`. Wrap or compose to extend; use the registry copy-paste path (`npx shadcn add @voyant/...`) for components you want to fork outright.
@@ -0,0 +1,22 @@
1
+ import type { BookingOption, ResourceCloseoutRow, ResourceRow, ResourceSlotAssignmentRow, SlotOption } from "@voyantjs/resources-react";
2
+ export declare function ResourcesOverview({ bookings, slots, closeouts, filteredResources, filteredPools, liveAssignments, resourcesWithoutSupplier, unassignedReservations, search, setSearch, kindFilter, setKindFilter, hasFilters, onClearFilters, onOpenAssignment, onOpenResource, }: {
3
+ bookings: BookingOption[];
4
+ slots: SlotOption[];
5
+ closeouts: ResourceCloseoutRow[];
6
+ filteredResources: ResourceRow[];
7
+ filteredPools: Array<{
8
+ active: boolean;
9
+ }>;
10
+ liveAssignments: ResourceSlotAssignmentRow[];
11
+ resourcesWithoutSupplier: ResourceRow[];
12
+ unassignedReservations: ResourceSlotAssignmentRow[];
13
+ search: string;
14
+ setSearch: (value: string) => void;
15
+ kindFilter: string;
16
+ setKindFilter: (value: string) => void;
17
+ hasFilters: boolean;
18
+ onClearFilters: () => void;
19
+ onOpenAssignment: (assignmentId: string) => void;
20
+ onOpenResource: (resourceId: string) => void;
21
+ }): import("react/jsx-runtime").JSX.Element;
22
+ //# sourceMappingURL=resources-overview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources-overview.d.ts","sourceRoot":"","sources":["../../src/components/resources-overview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,yBAAyB,EACzB,UAAU,EACX,MAAM,2BAA2B,CAAA;AAkBlC,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,KAAK,EACL,SAAS,EACT,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,wBAAwB,EACxB,sBAAsB,EACtB,MAAM,EACN,SAAS,EACT,UAAU,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,GACf,EAAE;IACD,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,SAAS,EAAE,mBAAmB,EAAE,CAAA;IAChC,iBAAiB,EAAE,WAAW,EAAE,CAAA;IAChC,aAAa,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACzC,eAAe,EAAE,yBAAyB,EAAE,CAAA;IAC5C,wBAAwB,EAAE,WAAW,EAAE,CAAA;IACvC,sBAAsB,EAAE,yBAAyB,EAAE,CAAA;IACnD,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,gBAAgB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IAChD,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7C,2CAgIA"}
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { labelById, resourceKindOptions, slotLabel } from "@voyantjs/resources-react";
3
+ import { Button, Card, CardContent, CardHeader, CardTitle, Input, OverviewMetric, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyantjs/voyant-ui/components";
4
+ import { CalendarDays, ExternalLink, Search, Users, Wrench } from "lucide-react";
5
+ export function ResourcesOverview({ bookings, slots, closeouts, filteredResources, filteredPools, liveAssignments, resourcesWithoutSupplier, unassignedReservations, search, setSearch, kindFilter, setKindFilter, hasFilters, onClearFilters, onOpenAssignment, onOpenResource, }) {
6
+ const activeResourcesCount = filteredResources.filter((resource) => resource.active).length;
7
+ const activePoolsCount = filteredPools.filter((pool) => pool.active).length;
8
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-2 xl:grid-cols-4", children: [_jsx(OverviewMetric, { title: "Active Resources", value: activeResourcesCount, description: "Assignable assets ready for use", icon: Wrench }), _jsx(OverviewMetric, { title: "Active Pools", value: activePoolsCount, description: "Shared-capacity pools live", icon: Users }), _jsx(OverviewMetric, { title: "Live Assignments", value: liveAssignments.length, description: "Reserved or assigned slot coverage", icon: CalendarDays }), _jsx(OverviewMetric, { title: "Closeouts", value: closeouts.length, description: "Active maintenance or conflict blocks", icon: ExternalLink })] }), _jsxs("div", { className: "grid gap-4 xl:grid-cols-2", children: [_jsxs(Card, { size: "sm", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Assignment Gaps" }) }), _jsx(CardContent, { className: "space-y-3 text-sm", children: unassignedReservations.length === 0 ? (_jsx("p", { className: "text-muted-foreground", children: "Every live reservation has a named resource." })) : (unassignedReservations.slice(0, 4).map((assignment) => (_jsxs("button", { type: "button", className: "block w-full rounded-md border p-3 text-left hover:bg-muted/40", onClick: () => onOpenAssignment(assignment.id), children: [_jsx("div", { className: "font-medium", children: slotLabel(slots.find((slot) => slot.id === assignment.slotId) ?? {
9
+ id: assignment.slotId,
10
+ productId: "",
11
+ dateLocal: assignment.slotId,
12
+ startsAt: assignment.slotId,
13
+ }) }), _jsxs("div", { className: "text-muted-foreground", children: ["Status: ", assignment.status, " \u00B7 Booking:", " ", labelById(bookings, assignment.bookingId)] })] }, assignment.id)))) })] }), _jsxs(Card, { size: "sm", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Ownership Gaps" }) }), _jsx(CardContent, { className: "space-y-3 text-sm", children: resourcesWithoutSupplier.length === 0 ? (_jsx("p", { className: "text-muted-foreground", children: "Every resource is linked to a supplier." })) : (resourcesWithoutSupplier.slice(0, 4).map((resource) => (_jsxs("button", { type: "button", className: "block w-full rounded-md border p-3 text-left hover:bg-muted/40", onClick: () => onOpenResource(resource.id), children: [_jsx("div", { className: "font-medium", children: resource.name }), _jsxs("div", { className: "text-muted-foreground capitalize", children: [resource.kind, " \u00B7 Capacity ", resource.capacity ?? "-", " \u00B7 No supplier assigned"] })] }, resource.id)))) })] })] }), _jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [_jsxs("div", { className: "flex flex-1 flex-col gap-3 md:flex-row md:items-center", children: [_jsxs("div", { className: "relative w-full max-w-sm", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { placeholder: "Search resources...", value: search, onChange: (event) => setSearch(event.target.value), className: "pl-9" })] }), _jsxs(Select, { value: kindFilter, onValueChange: (value) => setKindFilter(value ?? "all"), children: [_jsx(SelectTrigger, { className: "w-full md:w-56", children: _jsx(SelectValue, { placeholder: "All kinds" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "All kinds" }), resourceKindOptions.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value)))] })] })] }), hasFilters ? (_jsx(Button, { variant: "outline", onClick: onClearFilters, children: "Clear Filters" })) : null] })] }));
14
+ }
@@ -0,0 +1,7 @@
1
+ export declare function ResourcesSectionHeader({ title, description, actionLabel, onAction, }: {
2
+ title: string;
3
+ description: string;
4
+ actionLabel: string;
5
+ onAction: () => void;
6
+ }): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=resources-section-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources-section-header.d.ts","sourceRoot":"","sources":["../../src/components/resources-section-header.tsx"],"names":[],"mappings":"AAGA,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,WAAW,EACX,WAAW,EACX,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,2CAaA"}
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@voyantjs/voyant-ui/components";
3
+ import { Plus } from "lucide-react";
4
+ export function ResourcesSectionHeader({ title, description, actionLabel, onAction, }) {
5
+ return (_jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold", children: title }), _jsx("p", { className: "text-sm text-muted-foreground", children: description })] }), _jsxs(Button, { onClick: onAction, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), actionLabel] })] }));
6
+ }
@@ -0,0 +1,56 @@
1
+ import type { OnChangeFn, RowSelectionState } from "@tanstack/react-table";
2
+ import { type ProductOption, type ResourceAllocationRow, type ResourcePoolRow, type ResourceRow, type SupplierOption } from "@voyantjs/resources-react";
3
+ type BulkFn = (args: {
4
+ ids: string[];
5
+ endpoint: string;
6
+ target: string;
7
+ noun: string;
8
+ payload: Record<string, unknown>;
9
+ successVerb: string;
10
+ clearSelection: () => void;
11
+ }) => Promise<void>;
12
+ type DeleteFn = (args: {
13
+ ids: string[];
14
+ endpoint: string;
15
+ target: string;
16
+ noun: string;
17
+ clearSelection: () => void;
18
+ }) => Promise<void>;
19
+ export declare function ResourcesTab(props: {
20
+ suppliers: SupplierOption[];
21
+ filteredResources: ResourceRow[];
22
+ resourceSelection: RowSelectionState;
23
+ setResourceSelection: OnChangeFn<RowSelectionState>;
24
+ bulkActionTarget: string | null;
25
+ handleBulkUpdate: BulkFn;
26
+ handleBulkDelete: DeleteFn;
27
+ onCreate: () => void;
28
+ onOpenRoute: (resourceId: string) => void;
29
+ onEdit: (row: ResourceRow) => void;
30
+ }): import("react/jsx-runtime").JSX.Element;
31
+ export declare function PoolsTab(props: {
32
+ products: ProductOption[];
33
+ filteredPools: ResourcePoolRow[];
34
+ poolSelection: RowSelectionState;
35
+ setPoolSelection: OnChangeFn<RowSelectionState>;
36
+ bulkActionTarget: string | null;
37
+ handleBulkUpdate: BulkFn;
38
+ handleBulkDelete: DeleteFn;
39
+ onCreate: () => void;
40
+ onOpenRoute: (poolId: string) => void;
41
+ onEdit: (row: ResourcePoolRow) => void;
42
+ }): import("react/jsx-runtime").JSX.Element;
43
+ export declare function AllocationsTab(props: {
44
+ pools: ResourcePoolRow[];
45
+ products: ProductOption[];
46
+ filteredAllocations: ResourceAllocationRow[];
47
+ allocationSelection: RowSelectionState;
48
+ setAllocationSelection: OnChangeFn<RowSelectionState>;
49
+ bulkActionTarget: string | null;
50
+ handleBulkDelete: DeleteFn;
51
+ onCreate: () => void;
52
+ onOpenRoute: (allocationId: string) => void;
53
+ onEdit: (row: ResourceAllocationRow) => void;
54
+ }): import("react/jsx-runtime").JSX.Element;
55
+ export {};
56
+ //# sourceMappingURL=resources-tabs-primary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources-tabs-primary.d.ts","sourceRoot":"","sources":["../../src/components/resources-tabs-primary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,UAAU,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACrF,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAA;AAalC,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE;IACnB,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEnB,KAAK,QAAQ,GAAG,CAAC,IAAI,EAAE;IACrB,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AA0JnB,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,iBAAiB,EAAE,WAAW,EAAE,CAAA;IAChC,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,oBAAoB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACnD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,QAAQ,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,MAAM,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAA;CACnC,2CA+EA;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAC9B,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,aAAa,EAAE,eAAe,EAAE,CAAA;IAChC,aAAa,EAAE,iBAAiB,CAAA;IAChC,gBAAgB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAC/C,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,QAAQ,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,MAAM,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;CACvC,2CA+EA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,KAAK,EAAE,eAAe,EAAE,CAAA;IACxB,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,mBAAmB,EAAE,qBAAqB,EAAE,CAAA;IAC5C,mBAAmB,EAAE,iBAAiB,CAAA;IACtC,sBAAsB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACrD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,QAAQ,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,MAAM,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC7C,2CA2CA"}
@@ -0,0 +1,163 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { formatSelectionLabel, labelById, } from "@voyantjs/resources-react";
3
+ import { Badge, Button, ConfirmActionButton, SelectionActionBar, } from "@voyantjs/voyant-ui/components";
4
+ import { DataTable } from "@voyantjs/voyant-ui/components/data-table";
5
+ import { DataTableColumnHeader } from "@voyantjs/voyant-ui/components/data-table-column-header";
6
+ import { TabsContent } from "@voyantjs/voyant-ui/components/tabs";
7
+ import { ExternalLink } from "lucide-react";
8
+ import { ResourcesSectionHeader } from "./resources-section-header";
9
+ const resourceColumns = (suppliers, onView) => [
10
+ {
11
+ accessorKey: "name",
12
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Resource" }),
13
+ },
14
+ {
15
+ accessorKey: "kind",
16
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Kind" }),
17
+ cell: ({ row }) => (_jsx(Badge, { variant: "outline", className: "capitalize", children: row.original.kind })),
18
+ },
19
+ {
20
+ accessorKey: "supplierId",
21
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Supplier" }),
22
+ cell: ({ row }) => labelById(suppliers, row.original.supplierId),
23
+ },
24
+ {
25
+ accessorKey: "capacity",
26
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Capacity" }),
27
+ cell: ({ row }) => row.original.capacity ?? "-",
28
+ },
29
+ {
30
+ accessorKey: "active",
31
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Status" }),
32
+ cell: ({ row }) => (_jsx(Badge, { variant: row.original.active ? "default" : "secondary", children: row.original.active ? "Active" : "Inactive" })),
33
+ },
34
+ {
35
+ id: "view",
36
+ header: "View",
37
+ cell: ({ row }) => (_jsxs(Button, { variant: "ghost", size: "sm", onClick: (event) => {
38
+ event.stopPropagation();
39
+ onView(row.original.id);
40
+ }, children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), "Open"] })),
41
+ },
42
+ ];
43
+ const poolColumns = (products, onView) => [
44
+ {
45
+ accessorKey: "name",
46
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Pool" }),
47
+ },
48
+ {
49
+ accessorKey: "kind",
50
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Kind" }),
51
+ cell: ({ row }) => (_jsx(Badge, { variant: "outline", className: "capitalize", children: row.original.kind })),
52
+ },
53
+ {
54
+ accessorKey: "productId",
55
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Product" }),
56
+ cell: ({ row }) => labelById(products, row.original.productId),
57
+ },
58
+ {
59
+ accessorKey: "sharedCapacity",
60
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Shared Capacity" }),
61
+ cell: ({ row }) => row.original.sharedCapacity ?? "-",
62
+ },
63
+ {
64
+ id: "view",
65
+ header: "View",
66
+ cell: ({ row }) => (_jsxs(Button, { variant: "ghost", size: "sm", onClick: (event) => {
67
+ event.stopPropagation();
68
+ onView(row.original.id);
69
+ }, children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), "Open"] })),
70
+ },
71
+ ];
72
+ const allocationColumns = (pools, products, onView) => [
73
+ {
74
+ accessorKey: "poolId",
75
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Pool" }),
76
+ cell: ({ row }) => labelById(pools, row.original.poolId),
77
+ },
78
+ {
79
+ accessorKey: "productId",
80
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Product" }),
81
+ cell: ({ row }) => labelById(products, row.original.productId),
82
+ },
83
+ {
84
+ accessorKey: "allocationMode",
85
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Mode" }),
86
+ cell: ({ row }) => (_jsx(Badge, { variant: "outline", className: "capitalize", children: row.original.allocationMode })),
87
+ },
88
+ {
89
+ accessorKey: "quantityRequired",
90
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Qty Required" }),
91
+ },
92
+ {
93
+ accessorKey: "priority",
94
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Priority" }),
95
+ },
96
+ {
97
+ id: "view",
98
+ header: "View",
99
+ cell: ({ row }) => (_jsxs(Button, { variant: "ghost", size: "sm", onClick: (event) => {
100
+ event.stopPropagation();
101
+ onView(row.original.id);
102
+ }, children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), "Open"] })),
103
+ },
104
+ ];
105
+ export function ResourcesTab(props) {
106
+ return (_jsxs(TabsContent, { value: "resources", className: "space-y-4", children: [_jsx(ResourcesSectionHeader, { title: "Resources", description: "Guides, vehicles, rooms, and other assignable assets.", actionLabel: "New Resource", onAction: props.onCreate }), _jsx(DataTable, { columns: resourceColumns(props.suppliers, props.onOpenRoute), data: props.filteredResources, emptyMessage: "No resources match the current filters.", enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.resourceSelection, onRowSelectionChange: props.setResourceSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsxs(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: [_jsx(ConfirmActionButton, { buttonLabel: "Activate", confirmLabel: "Activate Resources", title: `Activate ${formatSelectionLabel(selectedRows.length, "resource")}?`, description: "This makes the selected resources available again for assignment and planning.", disabled: props.bulkActionTarget === "resources-activate", onConfirm: () => props.handleBulkUpdate({
107
+ ids: selectedRows.map((row) => row.original.id),
108
+ endpoint: "/v1/resources/resources",
109
+ target: "resources-activate",
110
+ noun: "resource",
111
+ payload: { active: true },
112
+ successVerb: "Activated",
113
+ clearSelection,
114
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: "Deactivate", confirmLabel: "Deactivate Resources", title: `Deactivate ${formatSelectionLabel(selectedRows.length, "resource")}?`, description: "This preserves the selected resources but removes them from active operational use.", disabled: props.bulkActionTarget === "resources-deactivate", onConfirm: () => props.handleBulkUpdate({
115
+ ids: selectedRows.map((row) => row.original.id),
116
+ endpoint: "/v1/resources/resources",
117
+ target: "resources-deactivate",
118
+ noun: "resource",
119
+ payload: { active: false },
120
+ successVerb: "Deactivated",
121
+ clearSelection,
122
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: "Delete Selected", confirmLabel: "Delete Resources", title: `Delete ${formatSelectionLabel(selectedRows.length, "resource")}?`, description: "This permanently removes the selected resources. Use Deactivate if you only need to take them out of rotation.", disabled: props.bulkActionTarget === "resources-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
123
+ ids: selectedRows.map((row) => row.original.id),
124
+ endpoint: "/v1/resources/resources",
125
+ target: "resources-delete",
126
+ noun: "resource",
127
+ clearSelection,
128
+ }) })] })), onRowClick: (row) => props.onEdit(row.original) })] }));
129
+ }
130
+ export function PoolsTab(props) {
131
+ return (_jsxs(TabsContent, { value: "pools", className: "space-y-4", children: [_jsx(ResourcesSectionHeader, { title: "Pools", description: "Shared capacity groups by product or operational need.", actionLabel: "New Pool", onAction: props.onCreate }), _jsx(DataTable, { columns: poolColumns(props.products, props.onOpenRoute), data: props.filteredPools, emptyMessage: "No pools match the current filters.", enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.poolSelection, onRowSelectionChange: props.setPoolSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsxs(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: [_jsx(ConfirmActionButton, { buttonLabel: "Activate", confirmLabel: "Activate Pools", title: `Activate ${formatSelectionLabel(selectedRows.length, "pool")}?`, description: "This re-enables the selected resource pools for live capacity planning.", disabled: props.bulkActionTarget === "pools-activate", onConfirm: () => props.handleBulkUpdate({
132
+ ids: selectedRows.map((row) => row.original.id),
133
+ endpoint: "/v1/resources/pools",
134
+ target: "pools-activate",
135
+ noun: "pool",
136
+ payload: { active: true },
137
+ successVerb: "Activated",
138
+ clearSelection,
139
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: "Deactivate", confirmLabel: "Deactivate Pools", title: `Deactivate ${formatSelectionLabel(selectedRows.length, "pool")}?`, description: "This keeps the selected pools for reference but removes them from active planning.", disabled: props.bulkActionTarget === "pools-deactivate", onConfirm: () => props.handleBulkUpdate({
140
+ ids: selectedRows.map((row) => row.original.id),
141
+ endpoint: "/v1/resources/pools",
142
+ target: "pools-deactivate",
143
+ noun: "pool",
144
+ payload: { active: false },
145
+ successVerb: "Deactivated",
146
+ clearSelection,
147
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: "Delete Selected", confirmLabel: "Delete Pools", title: `Delete ${formatSelectionLabel(selectedRows.length, "pool")}?`, description: "This permanently removes the selected pools and any pool-level grouping they provide.", disabled: props.bulkActionTarget === "pools-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
148
+ ids: selectedRows.map((row) => row.original.id),
149
+ endpoint: "/v1/resources/pools",
150
+ target: "pools-delete",
151
+ noun: "pool",
152
+ clearSelection,
153
+ }) })] })), onRowClick: (row) => props.onEdit(row.original) })] }));
154
+ }
155
+ export function AllocationsTab(props) {
156
+ return (_jsxs(TabsContent, { value: "allocations", className: "space-y-4", children: [_jsx(ResourcesSectionHeader, { title: "Allocations", description: "Attach pools to products, rules, and start times.", actionLabel: "New Allocation", onAction: props.onCreate }), _jsx(DataTable, { columns: allocationColumns(props.pools, props.products, props.onOpenRoute), data: props.filteredAllocations, emptyMessage: "No allocations match the current filters.", enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.allocationSelection, onRowSelectionChange: props.setAllocationSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsx(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: _jsx(ConfirmActionButton, { buttonLabel: "Delete Selected", confirmLabel: "Delete Allocations", title: `Delete ${formatSelectionLabel(selectedRows.length, "allocation")}?`, description: "This permanently removes the selected allocation rules from resource planning.", disabled: props.bulkActionTarget === "allocations-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
157
+ ids: selectedRows.map((row) => row.original.id),
158
+ endpoint: "/v1/resources/allocations",
159
+ target: "allocations-delete",
160
+ noun: "allocation",
161
+ clearSelection,
162
+ }) }) })), onRowClick: (row) => props.onEdit(row.original) })] }));
163
+ }
@@ -0,0 +1,44 @@
1
+ import type { OnChangeFn, RowSelectionState } from "@tanstack/react-table";
2
+ import { type BookingOption, type ResourceCloseoutRow, type ResourceRow, type ResourceSlotAssignmentRow, type SlotOption } from "@voyantjs/resources-react";
3
+ type BulkFn = (args: {
4
+ ids: string[];
5
+ endpoint: string;
6
+ target: string;
7
+ noun: string;
8
+ payload: Record<string, unknown>;
9
+ successVerb: string;
10
+ clearSelection: () => void;
11
+ }) => Promise<void>;
12
+ type DeleteFn = (args: {
13
+ ids: string[];
14
+ endpoint: string;
15
+ target: string;
16
+ noun: string;
17
+ clearSelection: () => void;
18
+ }) => Promise<void>;
19
+ export declare function AssignmentsTab(props: {
20
+ slots: SlotOption[];
21
+ resources: ResourceRow[];
22
+ bookings: BookingOption[];
23
+ filteredAssignments: ResourceSlotAssignmentRow[];
24
+ assignmentSelection: RowSelectionState;
25
+ setAssignmentSelection: OnChangeFn<RowSelectionState>;
26
+ bulkActionTarget: string | null;
27
+ handleBulkUpdate: BulkFn;
28
+ handleBulkDelete: DeleteFn;
29
+ onCreate: () => void;
30
+ onOpenRoute: (assignmentId: string) => void;
31
+ onEdit: (row: ResourceSlotAssignmentRow) => void;
32
+ }): import("react/jsx-runtime").JSX.Element;
33
+ export declare function CloseoutsTab(props: {
34
+ resources: ResourceRow[];
35
+ filteredCloseouts: ResourceCloseoutRow[];
36
+ closeoutSelection: RowSelectionState;
37
+ setCloseoutSelection: OnChangeFn<RowSelectionState>;
38
+ bulkActionTarget: string | null;
39
+ handleBulkDelete: DeleteFn;
40
+ onCreate: () => void;
41
+ onEdit: (row: ResourceCloseoutRow) => void;
42
+ }): import("react/jsx-runtime").JSX.Element;
43
+ export {};
44
+ //# sourceMappingURL=resources-tabs-secondary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources-tabs-secondary.d.ts","sourceRoot":"","sources":["../../src/components/resources-tabs-secondary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,UAAU,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACrF,OAAO,EACL,KAAK,aAAa,EAIlB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,yBAAyB,EAC9B,KAAK,UAAU,EAEhB,MAAM,2BAA2B,CAAA;AAalC,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE;IACnB,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEnB,KAAK,QAAQ,GAAG,CAAC,IAAI,EAAE;IACrB,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AA2FnB,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,SAAS,EAAE,WAAW,EAAE,CAAA;IACxB,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,mBAAmB,EAAE,yBAAyB,EAAE,CAAA;IAChD,mBAAmB,EAAE,iBAAiB,CAAA;IACtC,sBAAsB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACrD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,QAAQ,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,MAAM,EAAE,CAAC,GAAG,EAAE,yBAAyB,KAAK,IAAI,CAAA;CACjD,2CA+EA;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,SAAS,EAAE,WAAW,EAAE,CAAA;IACxB,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;IACxC,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,oBAAoB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACnD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,QAAQ,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,MAAM,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,CAAA;CAC3C,2CA2CA"}
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { formatDateTime, formatSelectionLabel, labelById, slotLabel, } from "@voyantjs/resources-react";
3
+ import { Badge, Button, ConfirmActionButton, SelectionActionBar, } from "@voyantjs/voyant-ui/components";
4
+ import { DataTable } from "@voyantjs/voyant-ui/components/data-table";
5
+ import { DataTableColumnHeader } from "@voyantjs/voyant-ui/components/data-table-column-header";
6
+ import { TabsContent } from "@voyantjs/voyant-ui/components/tabs";
7
+ import { ExternalLink } from "lucide-react";
8
+ import { ResourcesSectionHeader } from "./resources-section-header";
9
+ const assignmentColumns = (slots, resources, bookings, onView) => [
10
+ {
11
+ accessorKey: "slotId",
12
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Slot" }),
13
+ cell: ({ row }) => slotLabel(slots.find((slot) => slot.id === row.original.slotId) ?? {
14
+ id: row.original.slotId,
15
+ productId: "",
16
+ dateLocal: row.original.slotId,
17
+ startsAt: row.original.slotId,
18
+ }),
19
+ },
20
+ {
21
+ accessorKey: "resourceId",
22
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Resource" }),
23
+ cell: ({ row }) => labelById(resources, row.original.resourceId),
24
+ },
25
+ {
26
+ accessorKey: "bookingId",
27
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Booking" }),
28
+ cell: ({ row }) => labelById(bookings, row.original.bookingId),
29
+ },
30
+ {
31
+ accessorKey: "status",
32
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Status" }),
33
+ cell: ({ row }) => (_jsx(Badge, { variant: "outline", className: "capitalize", children: row.original.status })),
34
+ },
35
+ {
36
+ accessorKey: "releasedAt",
37
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Released" }),
38
+ cell: ({ row }) => formatDateTime(row.original.releasedAt),
39
+ },
40
+ {
41
+ id: "view",
42
+ header: "View",
43
+ cell: ({ row }) => (_jsxs(Button, { variant: "ghost", size: "sm", onClick: (event) => {
44
+ event.stopPropagation();
45
+ onView(row.original.id);
46
+ }, children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), "Open"] })),
47
+ },
48
+ ];
49
+ const closeoutColumns = (resources) => [
50
+ {
51
+ accessorKey: "resourceId",
52
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Resource" }),
53
+ cell: ({ row }) => labelById(resources, row.original.resourceId),
54
+ },
55
+ {
56
+ accessorKey: "dateLocal",
57
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Date" }),
58
+ },
59
+ {
60
+ accessorKey: "startsAt",
61
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Starts" }),
62
+ cell: ({ row }) => formatDateTime(row.original.startsAt),
63
+ },
64
+ {
65
+ accessorKey: "endsAt",
66
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Ends" }),
67
+ cell: ({ row }) => formatDateTime(row.original.endsAt),
68
+ },
69
+ {
70
+ accessorKey: "reason",
71
+ header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Reason" }),
72
+ cell: ({ row }) => row.original.reason ?? "-",
73
+ },
74
+ ];
75
+ export function AssignmentsTab(props) {
76
+ return (_jsxs(TabsContent, { value: "assignments", className: "space-y-4", children: [_jsx(ResourcesSectionHeader, { title: "Slot Assignments", description: "Reserve or assign specific resources against live slots and bookings.", actionLabel: "New Assignment", onAction: props.onCreate }), _jsx(DataTable, { columns: assignmentColumns(props.slots, props.resources, props.bookings, props.onOpenRoute), data: props.filteredAssignments, emptyMessage: "No assignments match the current filters.", enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.assignmentSelection, onRowSelectionChange: props.setAssignmentSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsxs(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: [_jsx(ConfirmActionButton, { buttonLabel: "Assign", confirmLabel: "Mark Assigned", title: `Mark ${formatSelectionLabel(selectedRows.length, "assignment")} as assigned?`, description: "This marks the selected reservations as actively assigned without deleting any linkage.", disabled: props.bulkActionTarget === "assignments-assigned", onConfirm: () => props.handleBulkUpdate({
77
+ ids: selectedRows.map((row) => row.original.id),
78
+ endpoint: "/v1/resources/slot-assignments",
79
+ target: "assignments-assigned",
80
+ noun: "assignment",
81
+ payload: { status: "assigned" },
82
+ successVerb: "Updated",
83
+ clearSelection,
84
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: "Release", confirmLabel: "Release Assignments", title: `Release ${formatSelectionLabel(selectedRows.length, "assignment")}?`, description: "This marks the selected reservations as released while keeping the assignment history intact.", disabled: props.bulkActionTarget === "assignments-released", onConfirm: () => props.handleBulkUpdate({
85
+ ids: selectedRows.map((row) => row.original.id),
86
+ endpoint: "/v1/resources/slot-assignments",
87
+ target: "assignments-released",
88
+ noun: "assignment",
89
+ payload: { status: "released" },
90
+ successVerb: "Released",
91
+ clearSelection,
92
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: "Delete Selected", confirmLabel: "Delete Assignments", title: `Delete ${formatSelectionLabel(selectedRows.length, "assignment")}?`, description: "This permanently removes the selected slot assignments. Use Release if you only need to free the resource.", disabled: props.bulkActionTarget === "assignments-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
93
+ ids: selectedRows.map((row) => row.original.id),
94
+ endpoint: "/v1/resources/slot-assignments",
95
+ target: "assignments-delete",
96
+ noun: "assignment",
97
+ clearSelection,
98
+ }) })] })), onRowClick: (row) => props.onEdit(row.original) })] }));
99
+ }
100
+ export function CloseoutsTab(props) {
101
+ return (_jsxs(TabsContent, { value: "closeouts", className: "space-y-4", children: [_jsx(ResourcesSectionHeader, { title: "Resource Closeouts", description: "Block assets for maintenance, charter use, or operational conflicts.", actionLabel: "New Closeout", onAction: props.onCreate }), _jsx(DataTable, { columns: closeoutColumns(props.resources), data: props.filteredCloseouts, emptyMessage: "No closeouts match the current filters.", enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.closeoutSelection, onRowSelectionChange: props.setCloseoutSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsx(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: _jsx(ConfirmActionButton, { buttonLabel: "Delete Selected", confirmLabel: "Delete Closeouts", title: `Delete ${formatSelectionLabel(selectedRows.length, "closeout")}?`, description: "This permanently removes the selected closeouts and may return the resources to operational use.", disabled: props.bulkActionTarget === "closeouts-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
102
+ ids: selectedRows.map((row) => row.original.id),
103
+ endpoint: "/v1/resources/closeouts",
104
+ target: "closeouts-delete",
105
+ noun: "closeout",
106
+ clearSelection,
107
+ }) }) })), onRowClick: (row) => props.onEdit(row.original) })] }));
108
+ }
@@ -0,0 +1,5 @@
1
+ export { ResourcesOverview } from "./components/resources-overview";
2
+ export { ResourcesSectionHeader } from "./components/resources-section-header";
3
+ export { AllocationsTab, PoolsTab, ResourcesTab } from "./components/resources-tabs-primary";
4
+ export { AssignmentsTab, CloseoutsTab } from "./components/resources-tabs-secondary";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAC5F,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { ResourcesOverview } from "./components/resources-overview";
2
+ export { ResourcesSectionHeader } from "./components/resources-section-header";
3
+ export { AllocationsTab, PoolsTab, ResourcesTab } from "./components/resources-tabs-primary";
4
+ export { AssignmentsTab, CloseoutsTab } from "./components/resources-tabs-secondary";
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@voyantjs/resources-ui",
3
+ "version": "0.13.0",
4
+ "license": "FSL-1.1-Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/voyantjs/voyant.git",
8
+ "directory": "packages/resources-ui"
9
+ },
10
+ "type": "module",
11
+ "sideEffects": false,
12
+ "exports": {
13
+ ".": "./src/index.ts",
14
+ "./components/*": "./src/components/*.tsx"
15
+ },
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.build.json",
18
+ "clean": "rm -rf dist",
19
+ "prepack": "pnpm run build",
20
+ "typecheck": "tsc --noEmit",
21
+ "lint": "biome check src/",
22
+ "test": "vitest run --passWithNoTests"
23
+ },
24
+ "peerDependencies": {
25
+ "@tanstack/react-query": "^5.0.0",
26
+ "@tanstack/react-table": "^8.0.0",
27
+ "@voyantjs/resources-react": "workspace:*",
28
+ "@voyantjs/voyant-ui": "workspace:*",
29
+ "react": "^19.0.0",
30
+ "react-dom": "^19.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@tanstack/react-query": "^5.96.2",
34
+ "@tanstack/react-table": "^8.21.3",
35
+ "@types/react": "^19.2.14",
36
+ "@types/react-dom": "^19.2.3",
37
+ "@voyantjs/resources-react": "workspace:*",
38
+ "@voyantjs/voyant-typescript-config": "workspace:*",
39
+ "@voyantjs/voyant-ui": "workspace:*",
40
+ "lucide-react": "^0.475.0",
41
+ "react": "^19.2.4",
42
+ "react-dom": "^19.2.4",
43
+ "typescript": "^6.0.2",
44
+ "vitest": "^4.1.2"
45
+ },
46
+ "files": [
47
+ "dist"
48
+ ],
49
+ "publishConfig": {
50
+ "access": "public",
51
+ "exports": {
52
+ ".": {
53
+ "types": "./dist/index.d.ts",
54
+ "import": "./dist/index.js"
55
+ },
56
+ "./components/*": {
57
+ "types": "./dist/components/*.d.ts",
58
+ "import": "./dist/components/*.js"
59
+ }
60
+ },
61
+ "main": "./dist/index.js",
62
+ "types": "./dist/index.d.ts"
63
+ }
64
+ }