@voyantjs/booking-requirements-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 +17 -0
- package/dist/components/booking-requirements-contact-tab.d.ts +8 -0
- package/dist/components/booking-requirements-contact-tab.d.ts.map +1 -0
- package/dist/components/booking-requirements-contact-tab.js +6 -0
- package/dist/components/booking-requirements-questions-tab.d.ts +14 -0
- package/dist/components/booking-requirements-questions-tab.d.ts.map +1 -0
- package/dist/components/booking-requirements-questions-tab.js +13 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# @voyantjs/booking-requirements-ui
|
|
2
|
+
|
|
3
|
+
Importable React UI components for Voyant booking-requirements. Bundler-consumed (Vite, Next.js, webpack, etc.).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @voyantjs/booking-requirements-ui @voyantjs/booking-requirements-react @voyantjs/voyant-ui @tanstack/react-query react react-dom
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`@voyantjs/voyant-ui` provides the design-system primitives. `@voyantjs/booking-requirements-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.
|
|
14
|
+
|
|
15
|
+
## Not included (registry-only)
|
|
16
|
+
|
|
17
|
+
Some components couple to TanStack Router or template-local helpers and remain available only via the shadcn registry: `booking-question-dialog`, `contact-requirement-dialog`, `question-option-dialog`. Import via `npx shadcn add @voyant/<component>` and customize per-project.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ContactRequirement } from "@voyantjs/booking-requirements-react";
|
|
2
|
+
export declare function BookingRequirementsContactTab({ rows, onCreate, onEdit, onDelete, }: {
|
|
3
|
+
rows: ContactRequirement[];
|
|
4
|
+
onCreate: () => void;
|
|
5
|
+
onEdit: (row: ContactRequirement) => void;
|
|
6
|
+
onDelete: (row: ContactRequirement) => void;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=booking-requirements-contact-tab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-requirements-contact-tab.d.ts","sourceRoot":"","sources":["../../src/components/booking-requirements-contact-tab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAA;AAI9E,wBAAgB,6BAA6B,CAAC,EAC5C,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,kBAAkB,EAAE,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,MAAM,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAA;IACzC,QAAQ,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAA;CAC5C,2CAyFA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Badge, Button } from "@voyantjs/voyant-ui/components";
|
|
3
|
+
import { Pencil, Plus, Trash2 } from "lucide-react";
|
|
4
|
+
export function BookingRequirementsContactTab({ rows, onCreate, onEdit, onDelete, }) {
|
|
5
|
+
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold", children: "Contact Requirements" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Standard traveler fields collected at booking (name, email, passport, etc.)." })] }), _jsxs(Button, { size: "sm", onClick: onCreate, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Add Requirement"] })] }), rows.length === 0 ? (_jsx("div", { className: "rounded-md border border-dashed p-8 text-center", children: _jsx("p", { className: "text-sm text-muted-foreground", children: "No contact requirements yet. Add one to start collecting traveler data." }) })) : (_jsx("div", { className: "rounded-md border bg-background", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b text-muted-foreground", children: [_jsx("th", { className: "p-3 text-left font-medium", children: "Field" }), _jsx("th", { className: "p-3 text-left font-medium", children: "Scope" }), _jsx("th", { className: "p-3 text-left font-medium", children: "Required" }), _jsx("th", { className: "p-3 text-left font-medium", children: "Per Traveler" }), _jsx("th", { className: "p-3 text-left font-medium", children: "Sort" }), _jsx("th", { className: "p-3 text-left font-medium", children: "Status" }), _jsx("th", { className: "w-20 p-3" })] }) }), _jsx("tbody", { children: rows.map((row) => (_jsxs("tr", { className: "border-b last:border-b-0", children: [_jsx("td", { className: "p-3 font-medium capitalize", children: row.fieldKey.replace(/_/g, " ") }), _jsx("td", { className: "p-3 capitalize text-muted-foreground", children: row.scope.replace("_", " ") }), _jsx("td", { className: "p-3", children: row.isRequired ? (_jsx(Badge, { variant: "default", children: "Required" })) : (_jsx(Badge, { variant: "outline", children: "Optional" })) }), _jsx("td", { className: "p-3", children: row.perTraveler ? (_jsx(Badge, { variant: "secondary", children: "Yes" })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: "No" })) }), _jsx("td", { className: "p-3 font-mono text-xs", children: row.sortOrder }), _jsx("td", { className: "p-3", children: _jsx(Badge, { variant: row.active ? "default" : "outline", children: row.active ? "Active" : "Inactive" }) }), _jsx("td", { className: "p-3", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => onEdit(row), className: "text-muted-foreground hover:text-foreground", children: _jsx(Pencil, { className: "h-3.5 w-3.5" }) }), _jsx("button", { type: "button", onClick: () => onDelete(row), className: "text-muted-foreground hover:text-destructive", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] }) })] }, row.id))) })] }) }))] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type BookingQuestion, type BookingQuestionOption } from "@voyantjs/booking-requirements-react";
|
|
2
|
+
export declare function BookingRequirementsQuestionsTab({ rows, expandedIds, questionOptionsById, onToggle, onCreate, onEdit, onDelete, onCreateOption, onEditOption, onDeleteOption, }: {
|
|
3
|
+
rows: BookingQuestion[];
|
|
4
|
+
expandedIds: Set<string>;
|
|
5
|
+
questionOptionsById: Map<string, BookingQuestionOption[]>;
|
|
6
|
+
onToggle: (questionId: string) => void;
|
|
7
|
+
onCreate: () => void;
|
|
8
|
+
onEdit: (question: BookingQuestion) => void;
|
|
9
|
+
onDelete: (question: BookingQuestion) => void;
|
|
10
|
+
onCreateOption: (question: BookingQuestion, nextSort: number) => void;
|
|
11
|
+
onEditOption: (question: BookingQuestion, option: BookingQuestionOption) => void;
|
|
12
|
+
onDeleteOption: (option: BookingQuestionOption) => void;
|
|
13
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=booking-requirements-questions-tab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-requirements-questions-tab.d.ts","sourceRoot":"","sources":["../../src/components/booking-requirements-questions-tab.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAE3B,MAAM,sCAAsC,CAAA;AAI7C,wBAAgB,+BAA+B,CAAC,EAC9C,IAAI,EACJ,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,cAAc,GACf,EAAE;IACD,IAAI,EAAE,eAAe,EAAE,CAAA;IACvB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACxB,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAA;IACzD,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,MAAM,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAA;IAC3C,QAAQ,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAA;IAC7C,cAAc,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACrE,YAAY,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAA;IAChF,cAAc,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAA;CACxD,2CA0KA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { SELECT_TYPES, } from "@voyantjs/booking-requirements-react";
|
|
3
|
+
import { Badge, Button } from "@voyantjs/voyant-ui/components";
|
|
4
|
+
import { Pencil, Plus, Trash2 } from "lucide-react";
|
|
5
|
+
export function BookingRequirementsQuestionsTab({ rows, expandedIds, questionOptionsById, onToggle, onCreate, onEdit, onDelete, onCreateOption, onEditOption, onDeleteOption, }) {
|
|
6
|
+
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold", children: "Custom Questions" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Product-specific questions asked at booking (dietary needs, preferences, etc.)." })] }), _jsxs(Button, { size: "sm", onClick: onCreate, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Add Question"] })] }), rows.length === 0 ? (_jsx("div", { className: "rounded-md border border-dashed p-8 text-center", children: _jsx("p", { className: "text-sm text-muted-foreground", children: "No questions yet. Add one to collect custom data at booking." }) })) : (_jsx("div", { className: "flex flex-col gap-2", children: rows.map((question) => {
|
|
7
|
+
const expanded = expandedIds.has(question.id);
|
|
8
|
+
const options = (questionOptionsById.get(question.id) ?? []).slice();
|
|
9
|
+
const hasChoices = SELECT_TYPES.has(question.fieldType);
|
|
10
|
+
const nextSort = options.length > 0 ? Math.max(...options.map((option) => option.sortOrder)) + 1 : 0;
|
|
11
|
+
return (_jsxs("div", { className: "rounded-md border", children: [_jsxs("div", { className: "flex items-center gap-3 p-3", children: [_jsx("button", { type: "button", onClick: () => onToggle(question.id), className: "text-sm text-muted-foreground hover:text-foreground", children: expanded ? "Hide" : "Show" }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "text-sm font-medium", children: question.label }), question.code ? (_jsx("span", { className: "font-mono text-xs text-muted-foreground", children: question.code })) : null, _jsx(Badge, { variant: "outline", className: "capitalize", children: question.fieldType.replace("_", " ") }), _jsx(Badge, { variant: "secondary", className: "capitalize", children: question.target.replace("_", " ") }), question.isRequired ? _jsx(Badge, { variant: "default", children: "Required" }) : null, _jsx(Badge, { variant: question.active ? "default" : "outline", children: question.active ? "Active" : "Inactive" })] }), question.description ? (_jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: question.description })) : null] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: () => onEdit(question), children: _jsx(Pencil, { className: "h-3.5 w-3.5" }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => onDelete(question), children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] })] }), expanded ? (_jsxs("div", { className: "border-t bg-muted/30 p-3", children: [!hasChoices ? (_jsx("p", { className: "py-2 text-center text-xs text-muted-foreground", children: "Choice options only apply to single-select / multi-select field types." })) : null, hasChoices ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-2 flex items-center justify-between", children: [_jsx("p", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Choices" }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => onCreateOption(question, nextSort), children: [_jsx(Plus, { className: "mr-1 h-3 w-3" }), "Add Choice"] })] }), options.length === 0 ? (_jsx("p", { className: "py-2 text-center text-xs text-muted-foreground", children: "No choices yet." })) : (_jsx("div", { className: "rounded border bg-background", children: _jsxs("table", { className: "w-full text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b text-muted-foreground", children: [_jsx("th", { className: "p-2 text-left font-medium", children: "Sort" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Value" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Label" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Default" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Status" }), _jsx("th", { className: "w-16 p-2" })] }) }), _jsx("tbody", { children: options.map((option) => (_jsxs("tr", { className: "border-b last:border-b-0", children: [_jsx("td", { className: "p-2 font-mono", children: option.sortOrder }), _jsx("td", { className: "p-2 font-mono text-muted-foreground", children: option.value }), _jsx("td", { className: "p-2", children: option.label }), _jsx("td", { className: "p-2", children: option.isDefault ? (_jsx(Badge, { variant: "secondary", children: "Default" })) : (_jsx("span", { className: "text-muted-foreground", children: "-" })) }), _jsx("td", { className: "p-2", children: _jsx(Badge, { variant: option.active ? "default" : "outline", children: option.active ? "Active" : "Inactive" }) }), _jsx("td", { className: "p-2", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => onEditOption(question, option), className: "text-muted-foreground hover:text-foreground", children: _jsx(Pencil, { className: "h-3 w-3" }) }), _jsx("button", { type: "button", onClick: () => onDeleteOption(option), className: "text-muted-foreground hover:text-destructive", children: _jsx(Trash2, { className: "h-3 w-3" }) })] }) })] }, option.id))) })] }) }))] })) : null] })) : null] }, question.id));
|
|
12
|
+
}) }))] }));
|
|
13
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,+CAA+C,CAAA;AAC7F,OAAO,EAAE,+BAA+B,EAAE,MAAM,iDAAiD,CAAA"}
|
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@voyantjs/booking-requirements-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/booking-requirements-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
|
+
"@voyantjs/booking-requirements-react": "workspace:*",
|
|
27
|
+
"@voyantjs/voyant-ui": "workspace:*",
|
|
28
|
+
"react": "^19.0.0",
|
|
29
|
+
"react-dom": "^19.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@tanstack/react-query": "^5.96.2",
|
|
33
|
+
"@types/react": "^19.2.14",
|
|
34
|
+
"@types/react-dom": "^19.2.3",
|
|
35
|
+
"@voyantjs/booking-requirements-react": "workspace:*",
|
|
36
|
+
"@voyantjs/voyant-typescript-config": "workspace:*",
|
|
37
|
+
"@voyantjs/voyant-ui": "workspace:*",
|
|
38
|
+
"lucide-react": "^0.475.0",
|
|
39
|
+
"react": "^19.2.4",
|
|
40
|
+
"react-dom": "^19.2.4",
|
|
41
|
+
"typescript": "^6.0.2",
|
|
42
|
+
"vitest": "^4.1.2"
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"dist"
|
|
46
|
+
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public",
|
|
49
|
+
"exports": {
|
|
50
|
+
".": {
|
|
51
|
+
"types": "./dist/index.d.ts",
|
|
52
|
+
"import": "./dist/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./components/*": {
|
|
55
|
+
"types": "./dist/components/*.d.ts",
|
|
56
|
+
"import": "./dist/components/*.js"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"main": "./dist/index.js",
|
|
60
|
+
"types": "./dist/index.d.ts"
|
|
61
|
+
}
|
|
62
|
+
}
|