@voyantjs/availability-ui 0.21.1

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,141 @@
1
+ import type { OnChangeFn, RowSelectionState } from "@tanstack/react-table";
2
+ import type { AvailabilityCloseoutRow, AvailabilityPickupPointRow, AvailabilityRuleRow, AvailabilitySlotRow, AvailabilityStartTimeRow, ProductOption } from "@voyantjs/availability-react";
3
+ import { type AvailabilityColumnsMessages } from "./availability-columns.js";
4
+ export interface AvailabilityTabMessages extends AvailabilityColumnsMessages {
5
+ nouns: {
6
+ slotSingular: string;
7
+ slotPlural: string;
8
+ ruleSingular: string;
9
+ rulePlural: string;
10
+ startTimeSingular: string;
11
+ startTimePlural: string;
12
+ closeoutSingular: string;
13
+ closeoutPlural: string;
14
+ pickupPointSingular: string;
15
+ pickupPointPlural: string;
16
+ };
17
+ tabs: {
18
+ slots: AvailabilitySlotTabMessages;
19
+ rules: AvailabilityToggleTabMessages;
20
+ startTimes: AvailabilityToggleTabMessages;
21
+ closeouts: AvailabilityDeleteOnlyTabMessages;
22
+ pickupPoints: AvailabilityToggleTabMessages;
23
+ };
24
+ verbOpened: string;
25
+ verbClosed: string;
26
+ verbActivated: string;
27
+ verbDeactivated: string;
28
+ }
29
+ interface AvailabilityBaseTabMessages {
30
+ title: string;
31
+ description: string;
32
+ actionLabel: string;
33
+ emptyMessage: string;
34
+ bulkDeleteButton: string;
35
+ bulkDeleteConfirm: string;
36
+ bulkDeleteTitle: string;
37
+ bulkDeleteDescription: string;
38
+ }
39
+ interface AvailabilitySlotTabMessages extends AvailabilityBaseTabMessages {
40
+ bulkOpenButton: string;
41
+ bulkOpenConfirm: string;
42
+ bulkOpenTitle: string;
43
+ bulkOpenDescription: string;
44
+ bulkCloseButton: string;
45
+ bulkCloseConfirm: string;
46
+ bulkCloseTitle: string;
47
+ bulkCloseDescription: string;
48
+ }
49
+ interface AvailabilityToggleTabMessages extends AvailabilityBaseTabMessages {
50
+ bulkActivateButton: string;
51
+ bulkActivateConfirm: string;
52
+ bulkActivateTitle: string;
53
+ bulkActivateDescription: string;
54
+ bulkDeactivateButton: string;
55
+ bulkDeactivateConfirm: string;
56
+ bulkDeactivateTitle: string;
57
+ bulkDeactivateDescription: string;
58
+ }
59
+ type AvailabilityDeleteOnlyTabMessages = AvailabilityBaseTabMessages;
60
+ export type AvailabilityBulkUpdateFn = (args: {
61
+ ids: string[];
62
+ endpoint: string;
63
+ target: string;
64
+ nounSingular: string;
65
+ nounPlural: string;
66
+ payload: Record<string, unknown>;
67
+ successVerb: string;
68
+ clearSelection: () => void;
69
+ }) => Promise<void>;
70
+ export type AvailabilityBulkDeleteFn = (args: {
71
+ ids: string[];
72
+ endpoint: string;
73
+ target: string;
74
+ nounSingular: string;
75
+ nounPlural: string;
76
+ clearSelection: () => void;
77
+ }) => Promise<void>;
78
+ export declare function AvailabilitySlotsTab(props: {
79
+ messages: AvailabilityTabMessages;
80
+ products: ProductOption[];
81
+ filteredSlots: AvailabilitySlotRow[];
82
+ slotSelection: RowSelectionState;
83
+ setSlotSelection: OnChangeFn<RowSelectionState>;
84
+ bulkActionTarget: string | null;
85
+ handleBulkUpdate: AvailabilityBulkUpdateFn;
86
+ handleBulkDelete: AvailabilityBulkDeleteFn;
87
+ onCreate: () => void;
88
+ onOpenRoute: (slotId: string) => void;
89
+ onEdit: (row: AvailabilitySlotRow) => void;
90
+ }): import("react/jsx-runtime").JSX.Element;
91
+ export declare function AvailabilityRulesTab(props: {
92
+ messages: AvailabilityTabMessages;
93
+ products: ProductOption[];
94
+ filteredRules: AvailabilityRuleRow[];
95
+ ruleSelection: RowSelectionState;
96
+ setRuleSelection: OnChangeFn<RowSelectionState>;
97
+ bulkActionTarget: string | null;
98
+ handleBulkUpdate: AvailabilityBulkUpdateFn;
99
+ handleBulkDelete: AvailabilityBulkDeleteFn;
100
+ onCreate: () => void;
101
+ onOpenRoute: (ruleId: string) => void;
102
+ onEdit: (row: AvailabilityRuleRow) => void;
103
+ }): import("react/jsx-runtime").JSX.Element;
104
+ export declare function AvailabilityStartTimesTab(props: {
105
+ messages: AvailabilityTabMessages;
106
+ products: ProductOption[];
107
+ filteredStartTimes: AvailabilityStartTimeRow[];
108
+ startTimeSelection: RowSelectionState;
109
+ setStartTimeSelection: OnChangeFn<RowSelectionState>;
110
+ bulkActionTarget: string | null;
111
+ handleBulkUpdate: AvailabilityBulkUpdateFn;
112
+ handleBulkDelete: AvailabilityBulkDeleteFn;
113
+ onCreate: () => void;
114
+ onOpenRoute: (startTimeId: string) => void;
115
+ onEdit: (row: AvailabilityStartTimeRow) => void;
116
+ }): import("react/jsx-runtime").JSX.Element;
117
+ export declare function AvailabilityCloseoutsTab(props: {
118
+ messages: AvailabilityTabMessages;
119
+ products: ProductOption[];
120
+ filteredCloseouts: AvailabilityCloseoutRow[];
121
+ closeoutSelection: RowSelectionState;
122
+ setCloseoutSelection: OnChangeFn<RowSelectionState>;
123
+ bulkActionTarget: string | null;
124
+ handleBulkDelete: AvailabilityBulkDeleteFn;
125
+ onCreate: () => void;
126
+ onEdit: (row: AvailabilityCloseoutRow) => void;
127
+ }): import("react/jsx-runtime").JSX.Element;
128
+ export declare function AvailabilityPickupPointsTab(props: {
129
+ messages: AvailabilityTabMessages;
130
+ products: ProductOption[];
131
+ filteredPickupPoints: AvailabilityPickupPointRow[];
132
+ pickupPointSelection: RowSelectionState;
133
+ setPickupPointSelection: OnChangeFn<RowSelectionState>;
134
+ bulkActionTarget: string | null;
135
+ handleBulkUpdate: AvailabilityBulkUpdateFn;
136
+ handleBulkDelete: AvailabilityBulkDeleteFn;
137
+ onCreate: () => void;
138
+ onEdit: (row: AvailabilityPickupPointRow) => void;
139
+ }): import("react/jsx-runtime").JSX.Element;
140
+ export {};
141
+ //# sourceMappingURL=availability-tabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"availability-tabs.d.ts","sourceRoot":"","sources":["../../src/components/availability-tabs.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ConfirmActionButton, SelectionActionBar } from "@voyantjs/ui/components";
4
+ import { DataTable } from "@voyantjs/ui/components/data-table";
5
+ import { TabsContent } from "@voyantjs/ui/components/tabs";
6
+ import { formatLocalizedSelectionLabel } from "../utils.js";
7
+ import { availabilityCloseoutColumns, availabilityPickupPointColumns, availabilityRuleColumns, availabilitySlotColumns, availabilityStartTimeColumns, } from "./availability-columns.js";
8
+ import { AvailabilitySectionHeader } from "./availability-section-header.js";
9
+ function formatTemplate(template, values) {
10
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
11
+ const value = values[key];
12
+ return value == null ? match : String(value);
13
+ });
14
+ }
15
+ export function AvailabilitySlotsTab(props) {
16
+ const selection = (count) => formatLocalizedSelectionLabel(count, props.messages.nouns.slotSingular, props.messages.nouns.slotPlural);
17
+ return (_jsxs(TabsContent, { value: "slots", className: "space-y-4", children: [_jsx(AvailabilitySectionHeader, { title: props.messages.tabs.slots.title, description: props.messages.tabs.slots.description, actionLabel: props.messages.tabs.slots.actionLabel, onAction: props.onCreate }), _jsx(DataTable, { columns: availabilitySlotColumns(props.products, props.onOpenRoute, props.messages), data: props.filteredSlots, emptyMessage: props.messages.tabs.slots.emptyMessage, enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.slotSelection, onRowSelectionChange: props.setSlotSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsxs(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: [_jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.slots.bulkOpenButton, confirmLabel: props.messages.tabs.slots.bulkOpenConfirm, title: formatTemplate(props.messages.tabs.slots.bulkOpenTitle, {
18
+ selection: selection(selectedRows.length),
19
+ }), description: props.messages.tabs.slots.bulkOpenDescription, disabled: props.bulkActionTarget === "slots-open", onConfirm: () => props.handleBulkUpdate({
20
+ ids: selectedRows.map((row) => row.original.id),
21
+ endpoint: "/v1/availability/slots",
22
+ target: "slots-open",
23
+ nounSingular: props.messages.nouns.slotSingular,
24
+ nounPlural: props.messages.nouns.slotPlural,
25
+ payload: { status: "open" },
26
+ successVerb: props.messages.verbOpened,
27
+ clearSelection,
28
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.slots.bulkCloseButton, confirmLabel: props.messages.tabs.slots.bulkCloseConfirm, title: formatTemplate(props.messages.tabs.slots.bulkCloseTitle, {
29
+ selection: selection(selectedRows.length),
30
+ }), description: props.messages.tabs.slots.bulkCloseDescription, disabled: props.bulkActionTarget === "slots-close", onConfirm: () => props.handleBulkUpdate({
31
+ ids: selectedRows.map((row) => row.original.id),
32
+ endpoint: "/v1/availability/slots",
33
+ target: "slots-close",
34
+ nounSingular: props.messages.nouns.slotSingular,
35
+ nounPlural: props.messages.nouns.slotPlural,
36
+ payload: { status: "closed" },
37
+ successVerb: props.messages.verbClosed,
38
+ clearSelection,
39
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.slots.bulkDeleteButton, confirmLabel: props.messages.tabs.slots.bulkDeleteConfirm, title: formatTemplate(props.messages.tabs.slots.bulkDeleteTitle, {
40
+ selection: selection(selectedRows.length),
41
+ }), description: props.messages.tabs.slots.bulkDeleteDescription, disabled: props.bulkActionTarget === "slots-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
42
+ ids: selectedRows.map((row) => row.original.id),
43
+ endpoint: "/v1/availability/slots",
44
+ target: "slots-delete",
45
+ nounSingular: props.messages.nouns.slotSingular,
46
+ nounPlural: props.messages.nouns.slotPlural,
47
+ clearSelection,
48
+ }) })] })), onRowClick: (row) => props.onEdit(row.original) })] }));
49
+ }
50
+ export function AvailabilityRulesTab(props) {
51
+ const selection = (count) => formatLocalizedSelectionLabel(count, props.messages.nouns.ruleSingular, props.messages.nouns.rulePlural);
52
+ return (_jsxs(TabsContent, { value: "rules", className: "space-y-4", children: [_jsx(AvailabilitySectionHeader, { title: props.messages.tabs.rules.title, description: props.messages.tabs.rules.description, actionLabel: props.messages.tabs.rules.actionLabel, onAction: props.onCreate }), _jsx(DataTable, { columns: availabilityRuleColumns(props.products, props.onOpenRoute, props.messages), data: props.filteredRules, emptyMessage: props.messages.tabs.rules.emptyMessage, enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.ruleSelection, onRowSelectionChange: props.setRuleSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsxs(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: [_jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.rules.bulkActivateButton, confirmLabel: props.messages.tabs.rules.bulkActivateConfirm, title: formatTemplate(props.messages.tabs.rules.bulkActivateTitle, {
53
+ selection: selection(selectedRows.length),
54
+ }), description: props.messages.tabs.rules.bulkActivateDescription, disabled: props.bulkActionTarget === "rules-activate", onConfirm: () => props.handleBulkUpdate({
55
+ ids: selectedRows.map((row) => row.original.id),
56
+ endpoint: "/v1/availability/rules",
57
+ target: "rules-activate",
58
+ nounSingular: props.messages.nouns.ruleSingular,
59
+ nounPlural: props.messages.nouns.rulePlural,
60
+ payload: { active: true },
61
+ successVerb: props.messages.verbActivated,
62
+ clearSelection,
63
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.rules.bulkDeactivateButton, confirmLabel: props.messages.tabs.rules.bulkDeactivateConfirm, title: formatTemplate(props.messages.tabs.rules.bulkDeactivateTitle, {
64
+ selection: selection(selectedRows.length),
65
+ }), description: props.messages.tabs.rules.bulkDeactivateDescription, disabled: props.bulkActionTarget === "rules-deactivate", onConfirm: () => props.handleBulkUpdate({
66
+ ids: selectedRows.map((row) => row.original.id),
67
+ endpoint: "/v1/availability/rules",
68
+ target: "rules-deactivate",
69
+ nounSingular: props.messages.nouns.ruleSingular,
70
+ nounPlural: props.messages.nouns.rulePlural,
71
+ payload: { active: false },
72
+ successVerb: props.messages.verbDeactivated,
73
+ clearSelection,
74
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.rules.bulkDeleteButton, confirmLabel: props.messages.tabs.rules.bulkDeleteConfirm, title: formatTemplate(props.messages.tabs.rules.bulkDeleteTitle, {
75
+ selection: selection(selectedRows.length),
76
+ }), description: props.messages.tabs.rules.bulkDeleteDescription, disabled: props.bulkActionTarget === "rules-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
77
+ ids: selectedRows.map((row) => row.original.id),
78
+ endpoint: "/v1/availability/rules",
79
+ target: "rules-delete",
80
+ nounSingular: props.messages.nouns.ruleSingular,
81
+ nounPlural: props.messages.nouns.rulePlural,
82
+ clearSelection,
83
+ }) })] })), onRowClick: (row) => props.onEdit(row.original) })] }));
84
+ }
85
+ export function AvailabilityStartTimesTab(props) {
86
+ const selection = (count) => formatLocalizedSelectionLabel(count, props.messages.nouns.startTimeSingular, props.messages.nouns.startTimePlural);
87
+ return (_jsxs(TabsContent, { value: "start-times", className: "space-y-4", children: [_jsx(AvailabilitySectionHeader, { title: props.messages.tabs.startTimes.title, description: props.messages.tabs.startTimes.description, actionLabel: props.messages.tabs.startTimes.actionLabel, onAction: props.onCreate }), _jsx(DataTable, { columns: availabilityStartTimeColumns(props.products, props.onOpenRoute, props.messages), data: props.filteredStartTimes, emptyMessage: props.messages.tabs.startTimes.emptyMessage, enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.startTimeSelection, onRowSelectionChange: props.setStartTimeSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsxs(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: [_jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.startTimes.bulkActivateButton, confirmLabel: props.messages.tabs.startTimes.bulkActivateConfirm, title: formatTemplate(props.messages.tabs.startTimes.bulkActivateTitle, {
88
+ selection: selection(selectedRows.length),
89
+ }), description: props.messages.tabs.startTimes.bulkActivateDescription, disabled: props.bulkActionTarget === "start-times-activate", onConfirm: () => props.handleBulkUpdate({
90
+ ids: selectedRows.map((row) => row.original.id),
91
+ endpoint: "/v1/availability/start-times",
92
+ target: "start-times-activate",
93
+ nounSingular: props.messages.nouns.startTimeSingular,
94
+ nounPlural: props.messages.nouns.startTimePlural,
95
+ payload: { active: true },
96
+ successVerb: props.messages.verbActivated,
97
+ clearSelection,
98
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.startTimes.bulkDeactivateButton, confirmLabel: props.messages.tabs.startTimes.bulkDeactivateConfirm, title: formatTemplate(props.messages.tabs.startTimes.bulkDeactivateTitle, {
99
+ selection: selection(selectedRows.length),
100
+ }), description: props.messages.tabs.startTimes.bulkDeactivateDescription, disabled: props.bulkActionTarget === "start-times-deactivate", onConfirm: () => props.handleBulkUpdate({
101
+ ids: selectedRows.map((row) => row.original.id),
102
+ endpoint: "/v1/availability/start-times",
103
+ target: "start-times-deactivate",
104
+ nounSingular: props.messages.nouns.startTimeSingular,
105
+ nounPlural: props.messages.nouns.startTimePlural,
106
+ payload: { active: false },
107
+ successVerb: props.messages.verbDeactivated,
108
+ clearSelection,
109
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.startTimes.bulkDeleteButton, confirmLabel: props.messages.tabs.startTimes.bulkDeleteConfirm, title: formatTemplate(props.messages.tabs.startTimes.bulkDeleteTitle, {
110
+ selection: selection(selectedRows.length),
111
+ }), description: props.messages.tabs.startTimes.bulkDeleteDescription, disabled: props.bulkActionTarget === "start-times-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
112
+ ids: selectedRows.map((row) => row.original.id),
113
+ endpoint: "/v1/availability/start-times",
114
+ target: "start-times-delete",
115
+ nounSingular: props.messages.nouns.startTimeSingular,
116
+ nounPlural: props.messages.nouns.startTimePlural,
117
+ clearSelection,
118
+ }) })] })), onRowClick: (row) => props.onEdit(row.original) })] }));
119
+ }
120
+ export function AvailabilityCloseoutsTab(props) {
121
+ const selection = (count) => formatLocalizedSelectionLabel(count, props.messages.nouns.closeoutSingular, props.messages.nouns.closeoutPlural);
122
+ return (_jsxs(TabsContent, { value: "closeouts", className: "space-y-4", children: [_jsx(AvailabilitySectionHeader, { title: props.messages.tabs.closeouts.title, description: props.messages.tabs.closeouts.description, actionLabel: props.messages.tabs.closeouts.actionLabel, onAction: props.onCreate }), _jsx(DataTable, { columns: availabilityCloseoutColumns(props.products, props.messages), data: props.filteredCloseouts, emptyMessage: props.messages.tabs.closeouts.emptyMessage, 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: props.messages.tabs.closeouts.bulkDeleteButton, confirmLabel: props.messages.tabs.closeouts.bulkDeleteConfirm, title: formatTemplate(props.messages.tabs.closeouts.bulkDeleteTitle, {
123
+ selection: selection(selectedRows.length),
124
+ }), description: props.messages.tabs.closeouts.bulkDeleteDescription, disabled: props.bulkActionTarget === "closeouts-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
125
+ ids: selectedRows.map((row) => row.original.id),
126
+ endpoint: "/v1/availability/closeouts",
127
+ target: "closeouts-delete",
128
+ nounSingular: props.messages.nouns.closeoutSingular,
129
+ nounPlural: props.messages.nouns.closeoutPlural,
130
+ clearSelection,
131
+ }) }) })), onRowClick: (row) => props.onEdit(row.original) })] }));
132
+ }
133
+ export function AvailabilityPickupPointsTab(props) {
134
+ const selection = (count) => formatLocalizedSelectionLabel(count, props.messages.nouns.pickupPointSingular, props.messages.nouns.pickupPointPlural);
135
+ return (_jsxs(TabsContent, { value: "pickup-points", className: "space-y-4", children: [_jsx(AvailabilitySectionHeader, { title: props.messages.tabs.pickupPoints.title, description: props.messages.tabs.pickupPoints.description, actionLabel: props.messages.tabs.pickupPoints.actionLabel, onAction: props.onCreate }), _jsx(DataTable, { columns: availabilityPickupPointColumns(props.products, props.messages), data: props.filteredPickupPoints, emptyMessage: props.messages.tabs.pickupPoints.emptyMessage, enableRowSelection: true, getRowId: (row) => row.id, rowSelection: props.pickupPointSelection, onRowSelectionChange: props.setPickupPointSelection, renderSelectionActions: ({ selectedRows, clearSelection }) => (_jsxs(SelectionActionBar, { selectedCount: selectedRows.length, onClear: clearSelection, children: [_jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.pickupPoints.bulkActivateButton, confirmLabel: props.messages.tabs.pickupPoints.bulkActivateConfirm, title: formatTemplate(props.messages.tabs.pickupPoints.bulkActivateTitle, {
136
+ selection: selection(selectedRows.length),
137
+ }), description: props.messages.tabs.pickupPoints.bulkActivateDescription, disabled: props.bulkActionTarget === "pickup-points-activate", onConfirm: () => props.handleBulkUpdate({
138
+ ids: selectedRows.map((row) => row.original.id),
139
+ endpoint: "/v1/availability/pickup-points",
140
+ target: "pickup-points-activate",
141
+ nounSingular: props.messages.nouns.pickupPointSingular,
142
+ nounPlural: props.messages.nouns.pickupPointPlural,
143
+ payload: { active: true },
144
+ successVerb: props.messages.verbActivated,
145
+ clearSelection,
146
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.pickupPoints.bulkDeactivateButton, confirmLabel: props.messages.tabs.pickupPoints.bulkDeactivateConfirm, title: formatTemplate(props.messages.tabs.pickupPoints.bulkDeactivateTitle, {
147
+ selection: selection(selectedRows.length),
148
+ }), description: props.messages.tabs.pickupPoints.bulkDeactivateDescription, disabled: props.bulkActionTarget === "pickup-points-deactivate", onConfirm: () => props.handleBulkUpdate({
149
+ ids: selectedRows.map((row) => row.original.id),
150
+ endpoint: "/v1/availability/pickup-points",
151
+ target: "pickup-points-deactivate",
152
+ nounSingular: props.messages.nouns.pickupPointSingular,
153
+ nounPlural: props.messages.nouns.pickupPointPlural,
154
+ payload: { active: false },
155
+ successVerb: props.messages.verbDeactivated,
156
+ clearSelection,
157
+ }) }), _jsx(ConfirmActionButton, { buttonLabel: props.messages.tabs.pickupPoints.bulkDeleteButton, confirmLabel: props.messages.tabs.pickupPoints.bulkDeleteConfirm, title: formatTemplate(props.messages.tabs.pickupPoints.bulkDeleteTitle, {
158
+ selection: selection(selectedRows.length),
159
+ }), description: props.messages.tabs.pickupPoints.bulkDeleteDescription, disabled: props.bulkActionTarget === "pickup-points-delete", variant: "destructive", confirmVariant: "destructive", onConfirm: () => props.handleBulkDelete({
160
+ ids: selectedRows.map((row) => row.original.id),
161
+ endpoint: "/v1/availability/pickup-points",
162
+ target: "pickup-points-delete",
163
+ nounSingular: props.messages.nouns.pickupPointSingular,
164
+ nounPlural: props.messages.nouns.pickupPointPlural,
165
+ clearSelection,
166
+ }) })] })), onRowClick: (row) => props.onEdit(row.original) })] }));
167
+ }
@@ -0,0 +1,4 @@
1
+ import type { FieldValues, Resolver } from "react-hook-form";
2
+ import type { z } from "zod/v4";
3
+ export declare function zodResolver<TSchema extends z.ZodType<FieldValues, FieldValues>>(schema: TSchema): Resolver<z.input<TSchema>, unknown, z.output<TSchema>>;
4
+ //# sourceMappingURL=form-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-resolver.d.ts","sourceRoot":"","sources":["../src/form-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,WAAW,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AACzE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AA+B/B,wBAAgB,WAAW,CAAC,OAAO,SAAS,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EAC7E,MAAM,EAAE,OAAO,GACd,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CA6BxD"}
@@ -0,0 +1,39 @@
1
+ function setFieldError(target, path, error) {
2
+ let current = target;
3
+ for (let index = 0; index < path.length; index += 1) {
4
+ const key = String(path[index] ?? "root");
5
+ if (index === path.length - 1) {
6
+ current[key] = error;
7
+ return;
8
+ }
9
+ const next = current[key];
10
+ if (typeof next !== "object" || next === null) {
11
+ current[key] = {};
12
+ }
13
+ current = current[key];
14
+ }
15
+ }
16
+ export function zodResolver(schema) {
17
+ return async (values) => {
18
+ const result = await schema.safeParseAsync(values);
19
+ if (result.success) {
20
+ return {
21
+ values: result.data,
22
+ errors: {},
23
+ };
24
+ }
25
+ const errors = {};
26
+ for (const issue of result.error.issues) {
27
+ const path = issue.path.filter((segment) => typeof segment !== "symbol");
28
+ const normalizedPath = path.length > 0 ? path : ["root"];
29
+ setFieldError(errors, normalizedPath, {
30
+ type: issue.code,
31
+ message: issue.message,
32
+ });
33
+ }
34
+ return {
35
+ values: {},
36
+ errors: errors,
37
+ };
38
+ };
39
+ }
@@ -0,0 +1,8 @@
1
+ export { type AvailabilityColumnsMessages, availabilityCloseoutColumns, availabilityPickupPointColumns, availabilityRuleColumns, availabilitySlotColumns, availabilityStartTimeColumns, getSlotStatusLabel, } from "./components/availability-columns.js";
2
+ export { AvailabilityCloseoutDialog, type AvailabilityCloseoutSubmitPayload, type AvailabilityDialogMessages, AvailabilityPickupPointDialog, type AvailabilityPickupPointSubmitPayload, AvailabilityRuleDialog, type AvailabilityRuleSubmitPayload, AvailabilitySlotDialog, type AvailabilitySlotSubmitPayload, AvailabilityStartTimeDialog, type AvailabilityStartTimeSubmitPayload, } from "./components/availability-dialogs.js";
3
+ export { AvailabilityOverview, type AvailabilityOverviewMessages, } from "./components/availability-overview.js";
4
+ export { AvailabilitySectionHeader, type AvailabilitySectionHeaderProps, } from "./components/availability-section-header.js";
5
+ export { AvailabilityBodySkeleton, AvailabilityPageSkeleton, AvailabilityRuleDetailSkeleton, AvailabilitySlotDetailSkeleton, AvailabilityStartTimeDetailSkeleton, } from "./components/availability-skeletons.js";
6
+ export { type AvailabilityBulkDeleteFn, type AvailabilityBulkUpdateFn, AvailabilityCloseoutsTab, AvailabilityPickupPointsTab, AvailabilityRulesTab, AvailabilitySlotsTab, AvailabilityStartTimesTab, type AvailabilityTabMessages, } from "./components/availability-tabs.js";
7
+ export { formatLocalizedSelectionLabel } from "./utils.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,2BAA2B,EAChC,2BAA2B,EAC3B,8BAA8B,EAC9B,uBAAuB,EACvB,uBAAuB,EACvB,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EACL,0BAA0B,EAC1B,KAAK,iCAAiC,EACtC,KAAK,0BAA0B,EAC/B,6BAA6B,EAC7B,KAAK,oCAAoC,EACzC,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,2BAA2B,EAC3B,KAAK,kCAAkC,GACxC,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EACL,oBAAoB,EACpB,KAAK,4BAA4B,GAClC,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EACL,yBAAyB,EACzB,KAAK,8BAA8B,GACpC,MAAM,6CAA6C,CAAA;AACpD,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,8BAA8B,EAC9B,8BAA8B,EAC9B,mCAAmC,GACpC,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,uBAAuB,GAC7B,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { availabilityCloseoutColumns, availabilityPickupPointColumns, availabilityRuleColumns, availabilitySlotColumns, availabilityStartTimeColumns, getSlotStatusLabel, } from "./components/availability-columns.js";
2
+ export { AvailabilityCloseoutDialog, AvailabilityPickupPointDialog, AvailabilityRuleDialog, AvailabilitySlotDialog, AvailabilityStartTimeDialog, } from "./components/availability-dialogs.js";
3
+ export { AvailabilityOverview, } from "./components/availability-overview.js";
4
+ export { AvailabilitySectionHeader, } from "./components/availability-section-header.js";
5
+ export { AvailabilityBodySkeleton, AvailabilityPageSkeleton, AvailabilityRuleDetailSkeleton, AvailabilitySlotDetailSkeleton, AvailabilityStartTimeDetailSkeleton, } from "./components/availability-skeletons.js";
6
+ export { AvailabilityCloseoutsTab, AvailabilityPickupPointsTab, AvailabilityRulesTab, AvailabilitySlotsTab, AvailabilityStartTimesTab, } from "./components/availability-tabs.js";
7
+ export { formatLocalizedSelectionLabel } from "./utils.js";
@@ -0,0 +1,2 @@
1
+ export declare function formatLocalizedSelectionLabel(count: number, singular: string, plural: string): string;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAE5F"}
package/dist/utils.js ADDED
@@ -0,0 +1,3 @@
1
+ export function formatLocalizedSelectionLabel(count, singular, plural) {
2
+ return `${count} ${count === 1 ? singular : plural}`;
3
+ }
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@voyantjs/availability-ui",
3
+ "version": "0.21.1",
4
+ "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/voyantjs/voyant.git",
8
+ "directory": "packages/availability-ui"
9
+ },
10
+ "type": "module",
11
+ "sideEffects": false,
12
+ "exports": {
13
+ ".": "./src/index.ts",
14
+ "./components/*": "./src/components/*.tsx",
15
+ "./utils": "./src/utils.ts"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.build.json",
19
+ "clean": "rm -rf dist",
20
+ "prepack": "pnpm run build",
21
+ "typecheck": "tsc --noEmit",
22
+ "lint": "biome check src/",
23
+ "test": "vitest run --passWithNoTests"
24
+ },
25
+ "peerDependencies": {
26
+ "@tanstack/react-table": "^8.21.3",
27
+ "@voyantjs/availability-react": "workspace:*",
28
+ "@voyantjs/ui": "workspace:*",
29
+ "lucide-react": "^0.475.0",
30
+ "react": "^19.0.0",
31
+ "react-dom": "^19.0.0",
32
+ "react-hook-form": "^7.72.1",
33
+ "zod": "^4.3.6"
34
+ },
35
+ "devDependencies": {
36
+ "@tanstack/react-table": "^8.21.3",
37
+ "@types/react": "^19.2.14",
38
+ "@types/react-dom": "^19.2.3",
39
+ "@voyantjs/availability-react": "workspace:*",
40
+ "@voyantjs/ui": "workspace:*",
41
+ "@voyantjs/voyant-typescript-config": "workspace:*",
42
+ "lucide-react": "^1.7.0",
43
+ "react": "^19.2.4",
44
+ "react-dom": "^19.2.4",
45
+ "react-hook-form": "^7.72.1",
46
+ "typescript": "^6.0.2",
47
+ "vitest": "^4.1.2",
48
+ "zod": "^4.3.6"
49
+ },
50
+ "files": [
51
+ "dist"
52
+ ],
53
+ "publishConfig": {
54
+ "access": "public",
55
+ "exports": {
56
+ ".": {
57
+ "types": "./dist/index.d.ts",
58
+ "import": "./dist/index.js",
59
+ "default": "./dist/index.js"
60
+ },
61
+ "./components/*": {
62
+ "types": "./dist/components/*.d.ts",
63
+ "import": "./dist/components/*.js",
64
+ "default": "./dist/components/*.js"
65
+ },
66
+ "./utils": {
67
+ "types": "./dist/utils.d.ts",
68
+ "import": "./dist/utils.js",
69
+ "default": "./dist/utils.js"
70
+ }
71
+ },
72
+ "main": "./dist/index.js",
73
+ "types": "./dist/index.d.ts"
74
+ }
75
+ }