@omnibase/shadcn 0.1.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 +73 -0
- package/dist/index.cjs +787 -0
- package/dist/index.css +119 -0
- package/dist/index.d.cts +52 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +748 -0
- package/package.json +75 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,787 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
CustomFlowForm: () => CustomFlowForm,
|
|
34
|
+
PricingTable: () => PricingTable,
|
|
35
|
+
SwitchActiveTenant: () => SwitchActiveTenant
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/components/ui/card.tsx
|
|
40
|
+
var React = require("react");
|
|
41
|
+
|
|
42
|
+
// src/lib/utils.ts
|
|
43
|
+
var import_clsx = require("clsx");
|
|
44
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
45
|
+
function cn(...inputs) {
|
|
46
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/components/ui/card.tsx
|
|
50
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
51
|
+
function Card({ className, ...props }) {
|
|
52
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
53
|
+
"div",
|
|
54
|
+
{
|
|
55
|
+
"data-slot": "card",
|
|
56
|
+
className: cn(
|
|
57
|
+
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
58
|
+
className
|
|
59
|
+
),
|
|
60
|
+
...props
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
function CardHeader({ className, ...props }) {
|
|
65
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
"data-slot": "card-header",
|
|
69
|
+
className: cn(
|
|
70
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
71
|
+
className
|
|
72
|
+
),
|
|
73
|
+
...props
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
function CardTitle({ className, ...props }) {
|
|
78
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
79
|
+
"div",
|
|
80
|
+
{
|
|
81
|
+
"data-slot": "card-title",
|
|
82
|
+
className: cn("leading-none font-semibold", className),
|
|
83
|
+
...props
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
function CardDescription({ className, ...props }) {
|
|
88
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
89
|
+
"div",
|
|
90
|
+
{
|
|
91
|
+
"data-slot": "card-description",
|
|
92
|
+
className: cn("text-muted-foreground text-sm", className),
|
|
93
|
+
...props
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
function CardContent({ className, ...props }) {
|
|
98
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
99
|
+
"div",
|
|
100
|
+
{
|
|
101
|
+
"data-slot": "card-content",
|
|
102
|
+
className: cn("px-6", className),
|
|
103
|
+
...props
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
function CardFooter({ className, ...props }) {
|
|
108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
109
|
+
"div",
|
|
110
|
+
{
|
|
111
|
+
"data-slot": "card-footer",
|
|
112
|
+
className: cn("flex items-center px-6 [.border-t]:pt-6", className),
|
|
113
|
+
...props
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/components/ui/button.tsx
|
|
119
|
+
var React2 = require("react");
|
|
120
|
+
var import_react_slot = require("@radix-ui/react-slot");
|
|
121
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
122
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
123
|
+
var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
124
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
125
|
+
{
|
|
126
|
+
variants: {
|
|
127
|
+
variant: {
|
|
128
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
129
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
130
|
+
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
131
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
132
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
133
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
134
|
+
},
|
|
135
|
+
size: {
|
|
136
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
137
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
138
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
139
|
+
icon: "size-9"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
defaultVariants: {
|
|
143
|
+
variant: "default",
|
|
144
|
+
size: "default"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
function Button({
|
|
149
|
+
className,
|
|
150
|
+
variant,
|
|
151
|
+
size,
|
|
152
|
+
asChild = false,
|
|
153
|
+
...props
|
|
154
|
+
}) {
|
|
155
|
+
const Comp = asChild ? import_react_slot.Slot : "button";
|
|
156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
157
|
+
Comp,
|
|
158
|
+
{
|
|
159
|
+
"data-slot": "button",
|
|
160
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
161
|
+
...props
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/components/ui/input.tsx
|
|
167
|
+
var React3 = require("react");
|
|
168
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
169
|
+
function Input({ className, type, ...props }) {
|
|
170
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
171
|
+
"input",
|
|
172
|
+
{
|
|
173
|
+
type,
|
|
174
|
+
"data-slot": "input",
|
|
175
|
+
className: cn(
|
|
176
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
177
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
178
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
179
|
+
className
|
|
180
|
+
),
|
|
181
|
+
...props
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// src/components/ui/label.tsx
|
|
187
|
+
var React4 = require("react");
|
|
188
|
+
var LabelPrimitive = __toESM(require("@radix-ui/react-label"), 1);
|
|
189
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
190
|
+
function Label({
|
|
191
|
+
className,
|
|
192
|
+
...props
|
|
193
|
+
}) {
|
|
194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
195
|
+
LabelPrimitive.Root,
|
|
196
|
+
{
|
|
197
|
+
"data-slot": "label",
|
|
198
|
+
className: cn(
|
|
199
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
200
|
+
className
|
|
201
|
+
),
|
|
202
|
+
...props
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/form/index.tsx
|
|
208
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
209
|
+
function isUiNodeInputAttributes(attributes) {
|
|
210
|
+
return attributes && typeof attributes === "object" && "name" in attributes && "type" in attributes;
|
|
211
|
+
}
|
|
212
|
+
function CustomFlowForm({ flow, Header }) {
|
|
213
|
+
const hasSubmitButton = flow.ui.nodes.some(
|
|
214
|
+
(node) => isUiNodeInputAttributes(node.attributes) && node.attributes.type === "submit"
|
|
215
|
+
);
|
|
216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Card, { className: "w-full max-w-md mx-auto", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { action: flow.ui.action, method: flow.ui.method, children: [
|
|
217
|
+
Header && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CardTitle, { className: "text-center pb-4", children: Header }) }),
|
|
218
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(CardContent, { className: "space-y-4", children: [
|
|
219
|
+
flow.ui.nodes.map((node) => {
|
|
220
|
+
if (isUiNodeInputAttributes(node.attributes)) {
|
|
221
|
+
const isSubmitButton = node.attributes.type === "submit";
|
|
222
|
+
const isHiddenField = node.attributes.type === "hidden";
|
|
223
|
+
const isVisibleField = !isHiddenField && !isSubmitButton;
|
|
224
|
+
if (isHiddenField) {
|
|
225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
226
|
+
"input",
|
|
227
|
+
{
|
|
228
|
+
name: node.attributes.name,
|
|
229
|
+
type: "hidden",
|
|
230
|
+
value: node.attributes.value || "",
|
|
231
|
+
readOnly: true
|
|
232
|
+
},
|
|
233
|
+
node.attributes.name
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (isSubmitButton) {
|
|
237
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
238
|
+
Button,
|
|
239
|
+
{
|
|
240
|
+
type: "submit",
|
|
241
|
+
name: node.attributes.name,
|
|
242
|
+
value: node.attributes.value || "",
|
|
243
|
+
className: "w-full mt-2",
|
|
244
|
+
children: node.meta.label?.text || node.attributes.value || "Submit"
|
|
245
|
+
},
|
|
246
|
+
node.attributes.name
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
if (isVisibleField && [
|
|
250
|
+
"default",
|
|
251
|
+
"password",
|
|
252
|
+
"code",
|
|
253
|
+
"webauthn",
|
|
254
|
+
"passkey",
|
|
255
|
+
"totp",
|
|
256
|
+
"lookup_secret"
|
|
257
|
+
].includes(node.group)) {
|
|
258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
259
|
+
"div",
|
|
260
|
+
{
|
|
261
|
+
className: "space-y-2",
|
|
262
|
+
children: [
|
|
263
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Label, { htmlFor: node.attributes.name, children: [
|
|
264
|
+
node.meta.label?.text,
|
|
265
|
+
node.attributes.required && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
266
|
+
] }),
|
|
267
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
268
|
+
Input,
|
|
269
|
+
{
|
|
270
|
+
id: node.attributes.name,
|
|
271
|
+
name: node.attributes.name,
|
|
272
|
+
type: node.attributes.type,
|
|
273
|
+
defaultValue: node.attributes.value || "",
|
|
274
|
+
required: node.attributes.required,
|
|
275
|
+
placeholder: `Enter your ${node.meta.label?.text?.toLowerCase() || node.attributes.name}`
|
|
276
|
+
}
|
|
277
|
+
)
|
|
278
|
+
]
|
|
279
|
+
},
|
|
280
|
+
node.meta.label?.id || node.attributes.name
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}),
|
|
286
|
+
!hasSubmitButton && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { type: "submit", className: "w-full", children: "Submit" })
|
|
287
|
+
] })
|
|
288
|
+
] }) }) });
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/tenant-switcher/index.tsx
|
|
292
|
+
var React6 = __toESM(require("react"), 1);
|
|
293
|
+
|
|
294
|
+
// src/components/ui/select.tsx
|
|
295
|
+
var React5 = __toESM(require("react"), 1);
|
|
296
|
+
var SelectPrimitive = __toESM(require("@radix-ui/react-select"), 1);
|
|
297
|
+
var import_lucide_react = require("lucide-react");
|
|
298
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
299
|
+
var Select = SelectPrimitive.Root;
|
|
300
|
+
var SelectValue = SelectPrimitive.Value;
|
|
301
|
+
var SelectTrigger = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
302
|
+
SelectPrimitive.Trigger,
|
|
303
|
+
{
|
|
304
|
+
ref,
|
|
305
|
+
className: cn(
|
|
306
|
+
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
307
|
+
className
|
|
308
|
+
),
|
|
309
|
+
...props,
|
|
310
|
+
children: [
|
|
311
|
+
children,
|
|
312
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.ChevronDown, { className: "h-4 w-4 opacity-50" }) })
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
));
|
|
316
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
317
|
+
var SelectScrollUpButton = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
318
|
+
SelectPrimitive.ScrollUpButton,
|
|
319
|
+
{
|
|
320
|
+
ref,
|
|
321
|
+
className: cn(
|
|
322
|
+
"flex cursor-default items-center justify-center py-1",
|
|
323
|
+
className
|
|
324
|
+
),
|
|
325
|
+
...props,
|
|
326
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.ChevronUp, { className: "h-4 w-4" })
|
|
327
|
+
}
|
|
328
|
+
));
|
|
329
|
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
330
|
+
var SelectScrollDownButton = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
331
|
+
SelectPrimitive.ScrollDownButton,
|
|
332
|
+
{
|
|
333
|
+
ref,
|
|
334
|
+
className: cn(
|
|
335
|
+
"flex cursor-default items-center justify-center py-1",
|
|
336
|
+
className
|
|
337
|
+
),
|
|
338
|
+
...props,
|
|
339
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.ChevronDown, { className: "h-4 w-4" })
|
|
340
|
+
}
|
|
341
|
+
));
|
|
342
|
+
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
343
|
+
var SelectContent = React5.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
344
|
+
SelectPrimitive.Content,
|
|
345
|
+
{
|
|
346
|
+
ref,
|
|
347
|
+
className: cn(
|
|
348
|
+
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
349
|
+
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
350
|
+
className
|
|
351
|
+
),
|
|
352
|
+
position,
|
|
353
|
+
...props,
|
|
354
|
+
children: [
|
|
355
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectScrollUpButton, {}),
|
|
356
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
357
|
+
SelectPrimitive.Viewport,
|
|
358
|
+
{
|
|
359
|
+
className: cn(
|
|
360
|
+
"p-1",
|
|
361
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
362
|
+
),
|
|
363
|
+
children
|
|
364
|
+
}
|
|
365
|
+
),
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectScrollDownButton, {})
|
|
367
|
+
]
|
|
368
|
+
}
|
|
369
|
+
) }));
|
|
370
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
371
|
+
var SelectLabel = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
372
|
+
SelectPrimitive.Label,
|
|
373
|
+
{
|
|
374
|
+
ref,
|
|
375
|
+
className: cn("px-2 py-1.5 text-sm font-semibold", className),
|
|
376
|
+
...props
|
|
377
|
+
}
|
|
378
|
+
));
|
|
379
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
380
|
+
var SelectItem = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
381
|
+
SelectPrimitive.Item,
|
|
382
|
+
{
|
|
383
|
+
ref,
|
|
384
|
+
className: cn(
|
|
385
|
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
386
|
+
className
|
|
387
|
+
),
|
|
388
|
+
...props,
|
|
389
|
+
children: [
|
|
390
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Check, { className: "h-4 w-4" }) }) }),
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectPrimitive.ItemText, { children })
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
));
|
|
395
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
396
|
+
var SelectSeparator = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
397
|
+
SelectPrimitive.Separator,
|
|
398
|
+
{
|
|
399
|
+
ref,
|
|
400
|
+
className: cn("-mx-1 my-1 h-px bg-muted", className),
|
|
401
|
+
...props
|
|
402
|
+
}
|
|
403
|
+
));
|
|
404
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
405
|
+
|
|
406
|
+
// src/tenant-switcher/index.tsx
|
|
407
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
408
|
+
function SwitchActiveTenant({
|
|
409
|
+
tenants,
|
|
410
|
+
currentTenantId,
|
|
411
|
+
formAction,
|
|
412
|
+
placeholder = "Select tenant...",
|
|
413
|
+
className,
|
|
414
|
+
onTenantChange
|
|
415
|
+
}) {
|
|
416
|
+
const [isLoading, setIsLoading] = React6.useState(false);
|
|
417
|
+
const handleTenantChange = async (tenantId) => {
|
|
418
|
+
if (tenantId === currentTenantId) return;
|
|
419
|
+
setIsLoading(true);
|
|
420
|
+
try {
|
|
421
|
+
onTenantChange?.(tenantId);
|
|
422
|
+
if (formAction) {
|
|
423
|
+
const formData = new FormData();
|
|
424
|
+
formData.append("tenant_id", tenantId);
|
|
425
|
+
await formAction(formData);
|
|
426
|
+
}
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error("Failed to switch tenant:", error);
|
|
429
|
+
} finally {
|
|
430
|
+
setIsLoading(false);
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
const currentTenant = tenants.find((tenant) => tenant.id === currentTenantId);
|
|
434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
435
|
+
Select,
|
|
436
|
+
{
|
|
437
|
+
value: currentTenantId,
|
|
438
|
+
onValueChange: handleTenantChange,
|
|
439
|
+
disabled: isLoading,
|
|
440
|
+
children: [
|
|
441
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectTrigger, { className: cn("max-w-64", className), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectValue, { placeholder, children: currentTenant ? currentTenant.name : placeholder }) }),
|
|
442
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectContent, { children: tenants.map((tenant) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectItem, { value: tenant.id, children: tenant.name }, tenant.id)) })
|
|
443
|
+
]
|
|
444
|
+
}
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// src/pricing-table/index.tsx
|
|
449
|
+
var React7 = __toESM(require("react"), 1);
|
|
450
|
+
var import_lucide_react2 = require("lucide-react");
|
|
451
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
452
|
+
var getCurrencySymbol = (currency) => {
|
|
453
|
+
const symbols = {
|
|
454
|
+
USD: "$",
|
|
455
|
+
EUR: "\u20AC",
|
|
456
|
+
GBP: "\xA3",
|
|
457
|
+
JPY: "\xA5",
|
|
458
|
+
CAD: "C$",
|
|
459
|
+
AUD: "A$"
|
|
460
|
+
};
|
|
461
|
+
return symbols[currency] || currency;
|
|
462
|
+
};
|
|
463
|
+
var formatPrice = (price) => {
|
|
464
|
+
const priceUI = price.ui || {};
|
|
465
|
+
if (priceUI.price_display?.custom_text)
|
|
466
|
+
return priceUI.price_display.custom_text;
|
|
467
|
+
if (!price.amount || price.amount === 0) return "Free";
|
|
468
|
+
const amount = price.amount / 100;
|
|
469
|
+
const currency = price.currency.toUpperCase();
|
|
470
|
+
let formattedPrice = priceUI.price_display?.show_currency !== false ? `${getCurrencySymbol(currency)}${amount.toFixed(2)}` : amount.toFixed(2);
|
|
471
|
+
if (priceUI.price_display?.suffix)
|
|
472
|
+
formattedPrice += ` ${priceUI.price_display.suffix}`;
|
|
473
|
+
return formattedPrice;
|
|
474
|
+
};
|
|
475
|
+
var formatBillingPeriod = (price) => {
|
|
476
|
+
const priceUI = price.ui || {};
|
|
477
|
+
if (priceUI.billing_period) return priceUI.billing_period;
|
|
478
|
+
if (price.interval) {
|
|
479
|
+
const count = price.interval_count || 1;
|
|
480
|
+
return `per ${count === 1 ? price.interval : `${count} ${price.interval}s`}`;
|
|
481
|
+
}
|
|
482
|
+
return "one-time";
|
|
483
|
+
};
|
|
484
|
+
function PricingCard({
|
|
485
|
+
product,
|
|
486
|
+
isSelected,
|
|
487
|
+
onPriceSelect,
|
|
488
|
+
displayedPrice
|
|
489
|
+
}) {
|
|
490
|
+
const ui = product.ui || {};
|
|
491
|
+
const isHighlighted = ui.highlighted;
|
|
492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
493
|
+
"div",
|
|
494
|
+
{
|
|
495
|
+
className: cn(
|
|
496
|
+
"flex flex-col h-full pb-6",
|
|
497
|
+
isHighlighted ? "relative" : ""
|
|
498
|
+
),
|
|
499
|
+
children: [
|
|
500
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "h-4 flex-shrink-0 relative", children: ui.badge && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "absolute top-0 left-1/2 transform -translate-x-1/2 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "bg-primary text-primary-foreground px-3 py-1 rounded-full text-sm font-medium flex items-center gap-1 whitespace-nowrap shadow-md", children: [
|
|
501
|
+
ui.badge === "Most Popular" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Star, { className: "w-3 h-3" }),
|
|
502
|
+
ui.badge
|
|
503
|
+
] }) }) }),
|
|
504
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
505
|
+
Card,
|
|
506
|
+
{
|
|
507
|
+
className: cn(
|
|
508
|
+
"flex flex-col flex-1 w-full transition-all duration-200 hover:shadow-lg",
|
|
509
|
+
isHighlighted && "border-primary shadow-lg",
|
|
510
|
+
isSelected && "ring-2 ring-primary"
|
|
511
|
+
),
|
|
512
|
+
children: [
|
|
513
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(CardHeader, { className: "text-center", children: [
|
|
514
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardTitle, { className: "text-xl font-bold", children: ui.display_name || product.name }),
|
|
515
|
+
ui.tagline && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardDescription, { className: "text-base", children: ui.tagline })
|
|
516
|
+
] }),
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(CardContent, { className: "flex-1 space-y-6", children: [
|
|
518
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "text-center", children: [
|
|
519
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "text-3xl font-bold", children: formatPrice(displayedPrice) }),
|
|
520
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "text-sm text-muted-foreground", children: formatBillingPeriod(displayedPrice) })
|
|
521
|
+
] }),
|
|
522
|
+
(ui.features && ui.features.length > 0 || displayedPrice.ui?.features?.length > 0 || displayedPrice.ui?.limits?.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-4", children: [
|
|
523
|
+
ui.features && ui.features.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-2", children: [
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { className: "font-medium text-sm text-muted-foreground uppercase tracking-wide", children: "Features" }),
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: "space-y-2", children: ui.features.map((feature, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
526
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Check, { className: "w-4 h-4 text-green-500 mt-0.5 flex-shrink-0" }),
|
|
527
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm", children: feature })
|
|
528
|
+
] }, index)) })
|
|
529
|
+
] }),
|
|
530
|
+
displayedPrice.ui?.features && displayedPrice.ui.features.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-2", children: [
|
|
531
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { className: "font-medium text-sm text-muted-foreground uppercase tracking-wide", children: "This Plan" }),
|
|
532
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: "space-y-2", children: displayedPrice.ui.features.map(
|
|
533
|
+
(feature, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
534
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Check, { className: "w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0" }),
|
|
535
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm", children: feature })
|
|
536
|
+
] }, index)
|
|
537
|
+
) })
|
|
538
|
+
] }),
|
|
539
|
+
displayedPrice.ui?.limits && displayedPrice.ui.limits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-2", children: [
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { className: "font-medium text-sm text-muted-foreground uppercase tracking-wide", children: "Usage Limits" }),
|
|
541
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: "space-y-1", children: displayedPrice.ui.limits.map(
|
|
542
|
+
(limit, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
543
|
+
"li",
|
|
544
|
+
{
|
|
545
|
+
className: "text-sm text-muted-foreground",
|
|
546
|
+
children: limit.text
|
|
547
|
+
},
|
|
548
|
+
index
|
|
549
|
+
)
|
|
550
|
+
) })
|
|
551
|
+
] })
|
|
552
|
+
] })
|
|
553
|
+
] }),
|
|
554
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardFooter, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
555
|
+
Button,
|
|
556
|
+
{
|
|
557
|
+
className: "w-full",
|
|
558
|
+
variant: isHighlighted ? "default" : "outline",
|
|
559
|
+
size: "lg",
|
|
560
|
+
onClick: () => onPriceSelect?.(displayedPrice.id, product.id),
|
|
561
|
+
children: ui.cta_text || "Choose Plan"
|
|
562
|
+
}
|
|
563
|
+
) })
|
|
564
|
+
]
|
|
565
|
+
}
|
|
566
|
+
)
|
|
567
|
+
]
|
|
568
|
+
}
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
var CARD_WIDTH = 320;
|
|
572
|
+
var GAP = 24;
|
|
573
|
+
function PricingTable({
|
|
574
|
+
products,
|
|
575
|
+
selectedPriceId,
|
|
576
|
+
onPriceSelect,
|
|
577
|
+
className,
|
|
578
|
+
showPricingToggle = false,
|
|
579
|
+
defaultInterval = "month"
|
|
580
|
+
}) {
|
|
581
|
+
const [selectedInterval, setSelectedInterval] = React7.useState(defaultInterval);
|
|
582
|
+
const [carouselIndex, setCarouselIndex] = React7.useState(0);
|
|
583
|
+
const sortedProducts = React7.useMemo(
|
|
584
|
+
() => [...products].sort(
|
|
585
|
+
(a, b) => (a.ui?.sort_order ?? 999) - (b.ui?.sort_order ?? 999)
|
|
586
|
+
),
|
|
587
|
+
[products]
|
|
588
|
+
);
|
|
589
|
+
const hasMultipleIntervals = React7.useMemo(
|
|
590
|
+
() => products.some(
|
|
591
|
+
(p) => new Set(p.prices.map((price) => price.interval)).size > 1
|
|
592
|
+
),
|
|
593
|
+
[products]
|
|
594
|
+
);
|
|
595
|
+
const getDisplayedPrice = (product) => product.prices.find((p) => p.interval === selectedInterval) || product.prices[0];
|
|
596
|
+
const renderCard = (product) => {
|
|
597
|
+
const displayedPrice = getDisplayedPrice(product);
|
|
598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
599
|
+
PricingCard,
|
|
600
|
+
{
|
|
601
|
+
product,
|
|
602
|
+
displayedPrice,
|
|
603
|
+
isSelected: selectedPriceId === displayedPrice.id,
|
|
604
|
+
onPriceSelect
|
|
605
|
+
}
|
|
606
|
+
);
|
|
607
|
+
};
|
|
608
|
+
const desktopCarousel = /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "relative max-w-7xl mx-auto", children: [
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
610
|
+
Button,
|
|
611
|
+
{
|
|
612
|
+
variant: "ghost",
|
|
613
|
+
size: "icon",
|
|
614
|
+
className: "absolute left-0 top-1/2 transform -translate-y-1/2 -translate-x-4 z-10 bg-white shadow-lg border hover:bg-gray-50 disabled:opacity-50",
|
|
615
|
+
onClick: () => setCarouselIndex(Math.max(0, carouselIndex - 1)),
|
|
616
|
+
disabled: carouselIndex === 0,
|
|
617
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.ChevronLeft, { className: "w-4 h-4" })
|
|
618
|
+
}
|
|
619
|
+
),
|
|
620
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
621
|
+
"div",
|
|
622
|
+
{
|
|
623
|
+
className: "overflow-hidden mx-auto",
|
|
624
|
+
style: { width: `${3 * CARD_WIDTH + 2 * GAP}px` },
|
|
625
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
626
|
+
"div",
|
|
627
|
+
{
|
|
628
|
+
className: "flex items-stretch transition-transform duration-300 ease-in-out",
|
|
629
|
+
style: {
|
|
630
|
+
transform: `translateX(-${carouselIndex * (CARD_WIDTH + GAP)}px)`,
|
|
631
|
+
gap: `${GAP}px`
|
|
632
|
+
},
|
|
633
|
+
children: sortedProducts.map((p) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
634
|
+
"div",
|
|
635
|
+
{
|
|
636
|
+
style: { width: `${CARD_WIDTH}px` },
|
|
637
|
+
className: "flex-shrink-0",
|
|
638
|
+
children: renderCard(p)
|
|
639
|
+
},
|
|
640
|
+
p.id
|
|
641
|
+
))
|
|
642
|
+
}
|
|
643
|
+
)
|
|
644
|
+
}
|
|
645
|
+
),
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
647
|
+
Button,
|
|
648
|
+
{
|
|
649
|
+
variant: "ghost",
|
|
650
|
+
size: "icon",
|
|
651
|
+
className: "absolute right-0 top-1/2 transform -translate-y-1/2 translate-x-4 z-10 bg-white shadow-lg border hover:bg-gray-50 disabled:opacity-50",
|
|
652
|
+
onClick: () => setCarouselIndex(
|
|
653
|
+
Math.min(sortedProducts.length - 3, carouselIndex + 1)
|
|
654
|
+
),
|
|
655
|
+
disabled: carouselIndex >= sortedProducts.length - 3,
|
|
656
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.ChevronRight, { className: "w-4 h-4" })
|
|
657
|
+
}
|
|
658
|
+
),
|
|
659
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex justify-center mt-6 space-x-2", children: Array.from(
|
|
660
|
+
{ length: Math.max(1, sortedProducts.length - 2) },
|
|
661
|
+
(_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
662
|
+
"button",
|
|
663
|
+
{
|
|
664
|
+
onClick: () => setCarouselIndex(i),
|
|
665
|
+
className: cn(
|
|
666
|
+
"w-2 h-2 rounded-full transition-colors",
|
|
667
|
+
i === carouselIndex ? "bg-primary" : "bg-gray-300"
|
|
668
|
+
),
|
|
669
|
+
"aria-label": `Go to slide ${i + 1}`
|
|
670
|
+
},
|
|
671
|
+
i
|
|
672
|
+
)
|
|
673
|
+
) })
|
|
674
|
+
] });
|
|
675
|
+
const staticLayout = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
676
|
+
"div",
|
|
677
|
+
{
|
|
678
|
+
className: "flex flex-row items-stretch justify-center",
|
|
679
|
+
style: { gap: `${GAP}px` },
|
|
680
|
+
children: sortedProducts.map((p) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
681
|
+
"div",
|
|
682
|
+
{
|
|
683
|
+
style: { width: `${CARD_WIDTH}px` },
|
|
684
|
+
className: "flex-shrink-0",
|
|
685
|
+
children: renderCard(p)
|
|
686
|
+
},
|
|
687
|
+
p.id
|
|
688
|
+
))
|
|
689
|
+
}
|
|
690
|
+
);
|
|
691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("w-full", className), children: [
|
|
692
|
+
showPricingToggle && hasMultipleIntervals && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex bg-gray-100 p-1 rounded-lg", children: [
|
|
693
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
694
|
+
Button,
|
|
695
|
+
{
|
|
696
|
+
variant: selectedInterval === "month" ? "default" : "ghost",
|
|
697
|
+
size: "sm",
|
|
698
|
+
onClick: () => setSelectedInterval("month"),
|
|
699
|
+
className: "rounded-md",
|
|
700
|
+
children: "Monthly"
|
|
701
|
+
}
|
|
702
|
+
),
|
|
703
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
704
|
+
Button,
|
|
705
|
+
{
|
|
706
|
+
variant: selectedInterval === "year" ? "default" : "ghost",
|
|
707
|
+
size: "sm",
|
|
708
|
+
onClick: () => setSelectedInterval("year"),
|
|
709
|
+
className: "rounded-md",
|
|
710
|
+
children: "Yearly"
|
|
711
|
+
}
|
|
712
|
+
)
|
|
713
|
+
] }) }),
|
|
714
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "lg:hidden relative", children: [
|
|
715
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
716
|
+
"div",
|
|
717
|
+
{
|
|
718
|
+
className: "overflow-hidden mx-auto",
|
|
719
|
+
style: { width: `${CARD_WIDTH}px` },
|
|
720
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
721
|
+
"div",
|
|
722
|
+
{
|
|
723
|
+
className: "flex transition-transform duration-300 ease-in-out items-stretch",
|
|
724
|
+
style: {
|
|
725
|
+
transform: `translateX(-${carouselIndex * CARD_WIDTH}px)`
|
|
726
|
+
},
|
|
727
|
+
children: sortedProducts.map((product) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
728
|
+
"div",
|
|
729
|
+
{
|
|
730
|
+
className: "flex-shrink-0",
|
|
731
|
+
style: { width: `${CARD_WIDTH}px` },
|
|
732
|
+
children: renderCard(product)
|
|
733
|
+
},
|
|
734
|
+
product.id
|
|
735
|
+
))
|
|
736
|
+
}
|
|
737
|
+
)
|
|
738
|
+
}
|
|
739
|
+
),
|
|
740
|
+
sortedProducts.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
741
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
742
|
+
Button,
|
|
743
|
+
{
|
|
744
|
+
variant: "ghost",
|
|
745
|
+
size: "icon",
|
|
746
|
+
className: "absolute left-0 top-1/2 -translate-y-1/2 -translate-x-2 z-10 bg-white shadow-lg border hover:bg-gray-50 disabled:opacity-50",
|
|
747
|
+
onClick: () => setCarouselIndex((prev) => Math.max(0, prev - 1)),
|
|
748
|
+
disabled: carouselIndex === 0,
|
|
749
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.ChevronLeft, { className: "w-5 h-5" })
|
|
750
|
+
}
|
|
751
|
+
),
|
|
752
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
753
|
+
Button,
|
|
754
|
+
{
|
|
755
|
+
variant: "ghost",
|
|
756
|
+
size: "icon",
|
|
757
|
+
className: "absolute right-0 top-1/2 -translate-y-1/2 translate-x-2 z-10 bg-white shadow-lg border hover:bg-gray-50 disabled:opacity-50",
|
|
758
|
+
onClick: () => setCarouselIndex(
|
|
759
|
+
(prev) => Math.min(sortedProducts.length - 1, prev + 1)
|
|
760
|
+
),
|
|
761
|
+
disabled: carouselIndex >= sortedProducts.length - 1,
|
|
762
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.ChevronRight, { className: "w-5 h-5" })
|
|
763
|
+
}
|
|
764
|
+
),
|
|
765
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex justify-center mt-6 space-x-2", children: Array.from({ length: sortedProducts.length }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
766
|
+
"button",
|
|
767
|
+
{
|
|
768
|
+
onClick: () => setCarouselIndex(i),
|
|
769
|
+
className: cn(
|
|
770
|
+
"w-2 h-2 rounded-full transition-colors",
|
|
771
|
+
i === carouselIndex ? "bg-primary" : "bg-gray-300"
|
|
772
|
+
),
|
|
773
|
+
"aria-label": `Go to slide ${i + 1}`
|
|
774
|
+
},
|
|
775
|
+
i
|
|
776
|
+
)) })
|
|
777
|
+
] })
|
|
778
|
+
] }),
|
|
779
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hidden lg:block", children: sortedProducts.length <= 3 ? staticLayout : desktopCarousel })
|
|
780
|
+
] });
|
|
781
|
+
}
|
|
782
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
783
|
+
0 && (module.exports = {
|
|
784
|
+
CustomFlowForm,
|
|
785
|
+
PricingTable,
|
|
786
|
+
SwitchActiveTenant
|
|
787
|
+
});
|