@omnibase/shadcn 0.4.2 → 0.5.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/dist/index.cjs +1261 -335
- package/dist/index.d.cts +79 -5
- package/dist/index.d.ts +79 -5
- package/dist/index.js +1250 -336
- package/package.json +19 -17
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
"use strict";
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
@@ -30,10 +31,23 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
31
|
// src/index.ts
|
|
31
32
|
var index_exports = {};
|
|
32
33
|
__export(index_exports, {
|
|
33
|
-
|
|
34
|
+
LoginForm: () => LoginForm,
|
|
34
35
|
PricingTable: () => PricingTable,
|
|
36
|
+
RecoveryForm: () => RecoveryForm,
|
|
37
|
+
RegistrationForm: () => RegistrationForm,
|
|
38
|
+
RoleCreator: () => RoleCreator,
|
|
39
|
+
SettingsForm: () => SettingsForm,
|
|
35
40
|
SwitchActiveTenant: () => SwitchActiveTenant,
|
|
36
|
-
TenantCreator: () => TenantCreator
|
|
41
|
+
TenantCreator: () => TenantCreator,
|
|
42
|
+
UserInvite: () => UserInvite,
|
|
43
|
+
VerificationForm: () => VerificationForm,
|
|
44
|
+
filterInputNodes: () => filterInputNodes,
|
|
45
|
+
findAnchorNode: () => findAnchorNode,
|
|
46
|
+
findCsrfToken: () => findCsrfToken,
|
|
47
|
+
findSubmitButton: () => findSubmitButton,
|
|
48
|
+
groupNodesByGroup: () => groupNodesByGroup,
|
|
49
|
+
isUiNodeInputAttributes: () => isUiNodeInputAttributes,
|
|
50
|
+
sortNodes: () => sortNodes
|
|
37
51
|
});
|
|
38
52
|
module.exports = __toCommonJS(index_exports);
|
|
39
53
|
|
|
@@ -116,12 +130,131 @@ function CardFooter({ className, ...props }) {
|
|
|
116
130
|
);
|
|
117
131
|
}
|
|
118
132
|
|
|
119
|
-
// src/components/ui/
|
|
120
|
-
var
|
|
121
|
-
|
|
133
|
+
// src/components/ui/messages.tsx
|
|
134
|
+
var React3 = __toESM(require("react"), 1);
|
|
135
|
+
|
|
136
|
+
// src/components/ui/alert.tsx
|
|
137
|
+
var React2 = __toESM(require("react"), 1);
|
|
122
138
|
var import_class_variance_authority = require("class-variance-authority");
|
|
123
139
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
124
|
-
var
|
|
140
|
+
var alertVariants = (0, import_class_variance_authority.cva)(
|
|
141
|
+
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
|
142
|
+
{
|
|
143
|
+
variants: {
|
|
144
|
+
variant: {
|
|
145
|
+
default: "bg-background text-foreground",
|
|
146
|
+
destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
|
147
|
+
warning: "border-yellow-500/50 text-yellow-700 bg-yellow-50 dark:border-yellow-500 dark:text-yellow-200 dark:bg-yellow-950/20 [&>svg]:text-yellow-600 dark:[&>svg]:text-yellow-200",
|
|
148
|
+
success: "border-green-500/50 text-green-700 bg-green-50 dark:border-green-500 dark:text-green-200 dark:bg-green-950/20 [&>svg]:text-green-600 dark:[&>svg]:text-green-200",
|
|
149
|
+
info: "border-blue-500/50 text-blue-700 bg-blue-50 dark:border-blue-500 dark:text-blue-200 dark:bg-blue-950/20 [&>svg]:text-blue-600 dark:[&>svg]:text-blue-200"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
defaultVariants: {
|
|
153
|
+
variant: "default"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
var Alert = React2.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
158
|
+
"div",
|
|
159
|
+
{
|
|
160
|
+
ref,
|
|
161
|
+
role: "alert",
|
|
162
|
+
className: cn(alertVariants({ variant }), className),
|
|
163
|
+
...props
|
|
164
|
+
}
|
|
165
|
+
));
|
|
166
|
+
Alert.displayName = "Alert";
|
|
167
|
+
var AlertTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
168
|
+
"h5",
|
|
169
|
+
{
|
|
170
|
+
ref,
|
|
171
|
+
className: cn("mb-1 font-medium leading-none tracking-tight", className),
|
|
172
|
+
...props
|
|
173
|
+
}
|
|
174
|
+
));
|
|
175
|
+
AlertTitle.displayName = "AlertTitle";
|
|
176
|
+
var AlertDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
177
|
+
"div",
|
|
178
|
+
{
|
|
179
|
+
ref,
|
|
180
|
+
className: cn("text-sm [&_p]:leading-relaxed", className),
|
|
181
|
+
...props
|
|
182
|
+
}
|
|
183
|
+
));
|
|
184
|
+
AlertDescription.displayName = "AlertDescription";
|
|
185
|
+
|
|
186
|
+
// src/components/ui/messages.tsx
|
|
187
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
188
|
+
var getMessageVariant = (type) => {
|
|
189
|
+
switch (type) {
|
|
190
|
+
case "error":
|
|
191
|
+
return "destructive";
|
|
192
|
+
case "success":
|
|
193
|
+
return "success";
|
|
194
|
+
case "info":
|
|
195
|
+
return "info";
|
|
196
|
+
case "11184809":
|
|
197
|
+
return "warning";
|
|
198
|
+
default:
|
|
199
|
+
return "default";
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
var Messages = React3.forwardRef(
|
|
203
|
+
({ flow, className, ...props }, ref) => {
|
|
204
|
+
if (!flow?.ui) return null;
|
|
205
|
+
const allMessages = [];
|
|
206
|
+
if (flow.ui.messages) {
|
|
207
|
+
allMessages.push(...flow.ui.messages);
|
|
208
|
+
}
|
|
209
|
+
if (flow.ui.nodes) {
|
|
210
|
+
flow.ui.nodes.forEach((node) => {
|
|
211
|
+
if (node.messages) {
|
|
212
|
+
allMessages.push(...node.messages);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
if (allMessages.length === 0) return null;
|
|
217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
218
|
+
"div",
|
|
219
|
+
{
|
|
220
|
+
ref,
|
|
221
|
+
className: cn("w-full max-w-md mx-auto space-y-2 mb-4", className),
|
|
222
|
+
...props,
|
|
223
|
+
children: allMessages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Alert, { variant: getMessageVariant(message.type), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AlertDescription, { children: message.text }) }, message.id))
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
Messages.displayName = "Messages";
|
|
229
|
+
|
|
230
|
+
// src/form/types.ts
|
|
231
|
+
function isUiNodeInputAttributes(attributes) {
|
|
232
|
+
return attributes && typeof attributes === "object" && "name" in attributes && "type" in attributes;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/form/components/HiddenInput.tsx
|
|
236
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
237
|
+
function HiddenInput({ node }) {
|
|
238
|
+
if (!isUiNodeInputAttributes(node.attributes)) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
242
|
+
"input",
|
|
243
|
+
{
|
|
244
|
+
name: node.attributes.name,
|
|
245
|
+
type: "hidden",
|
|
246
|
+
value: node.attributes.value || "",
|
|
247
|
+
readOnly: true
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/components/ui/button.tsx
|
|
253
|
+
var React4 = require("react");
|
|
254
|
+
var import_react_slot = require("@radix-ui/react-slot");
|
|
255
|
+
var import_class_variance_authority2 = require("class-variance-authority");
|
|
256
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
257
|
+
var buttonVariants = (0, import_class_variance_authority2.cva)(
|
|
125
258
|
"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",
|
|
126
259
|
{
|
|
127
260
|
variants: {
|
|
@@ -154,7 +287,7 @@ function Button({
|
|
|
154
287
|
...props
|
|
155
288
|
}) {
|
|
156
289
|
const Comp = asChild ? import_react_slot.Slot : "button";
|
|
157
|
-
return /* @__PURE__ */ (0,
|
|
290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
158
291
|
Comp,
|
|
159
292
|
{
|
|
160
293
|
"data-slot": "button",
|
|
@@ -164,11 +297,78 @@ function Button({
|
|
|
164
297
|
);
|
|
165
298
|
}
|
|
166
299
|
|
|
300
|
+
// src/form/components/SubmitButton.tsx
|
|
301
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
302
|
+
function SubmitButton({
|
|
303
|
+
node,
|
|
304
|
+
variant = "default",
|
|
305
|
+
className = "w-full"
|
|
306
|
+
}) {
|
|
307
|
+
if (!isUiNodeInputAttributes(node.attributes)) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
311
|
+
Button,
|
|
312
|
+
{
|
|
313
|
+
type: "submit",
|
|
314
|
+
name: node.attributes.name,
|
|
315
|
+
value: node.attributes.value || "",
|
|
316
|
+
variant,
|
|
317
|
+
className,
|
|
318
|
+
disabled: node.attributes.disabled,
|
|
319
|
+
children: node.meta.label?.text || node.attributes.value || "Submit"
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/form/components/Divider.tsx
|
|
325
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
326
|
+
function Divider({ withText = false }) {
|
|
327
|
+
if (withText) {
|
|
328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative my-6", children: [
|
|
329
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-full border-t border-border" }) }),
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "bg-background px-3 text-muted-foreground font-medium", children: "Or continue with" }) })
|
|
331
|
+
] });
|
|
332
|
+
}
|
|
333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "border-t border-border my-6" });
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// src/form/components/OidcGroup.tsx
|
|
337
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
338
|
+
function OidcGroup({
|
|
339
|
+
nodes,
|
|
340
|
+
flowAction,
|
|
341
|
+
flowMethod,
|
|
342
|
+
csrfToken,
|
|
343
|
+
groupIndex,
|
|
344
|
+
groupName
|
|
345
|
+
}) {
|
|
346
|
+
const submitButtons = nodes.filter(
|
|
347
|
+
(node) => isUiNodeInputAttributes(node.attributes) && node.attributes.type === "submit"
|
|
348
|
+
);
|
|
349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
350
|
+
groupIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Divider, { withText: true }),
|
|
351
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "space-y-3", children: submitButtons.map((node, btnIndex) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
352
|
+
"form",
|
|
353
|
+
{
|
|
354
|
+
action: flowAction,
|
|
355
|
+
method: flowMethod,
|
|
356
|
+
className: "w-full",
|
|
357
|
+
children: [
|
|
358
|
+
csrfToken && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(HiddenInput, { node: csrfToken }),
|
|
359
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SubmitButton, { node, variant: "outline" })
|
|
360
|
+
]
|
|
361
|
+
},
|
|
362
|
+
`${groupName}-${btnIndex}`
|
|
363
|
+
)) })
|
|
364
|
+
] });
|
|
365
|
+
}
|
|
366
|
+
|
|
167
367
|
// src/components/ui/input.tsx
|
|
168
|
-
var
|
|
169
|
-
var
|
|
368
|
+
var React5 = require("react");
|
|
369
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
170
370
|
function Input({ className, type, ...props }) {
|
|
171
|
-
return /* @__PURE__ */ (0,
|
|
371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
172
372
|
"input",
|
|
173
373
|
{
|
|
174
374
|
type,
|
|
@@ -185,14 +385,14 @@ function Input({ className, type, ...props }) {
|
|
|
185
385
|
}
|
|
186
386
|
|
|
187
387
|
// src/components/ui/label.tsx
|
|
188
|
-
var
|
|
388
|
+
var React6 = require("react");
|
|
189
389
|
var LabelPrimitive = __toESM(require("@radix-ui/react-label"), 1);
|
|
190
|
-
var
|
|
390
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
191
391
|
function Label({
|
|
192
392
|
className,
|
|
193
393
|
...props
|
|
194
394
|
}) {
|
|
195
|
-
return /* @__PURE__ */ (0,
|
|
395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
196
396
|
LabelPrimitive.Root,
|
|
197
397
|
{
|
|
198
398
|
"data-slot": "label",
|
|
@@ -205,109 +405,393 @@ function Label({
|
|
|
205
405
|
);
|
|
206
406
|
}
|
|
207
407
|
|
|
208
|
-
// src/components/
|
|
209
|
-
var
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
408
|
+
// src/form/components/FormInput.tsx
|
|
409
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
410
|
+
function FormInput({ node }) {
|
|
411
|
+
if (!isUiNodeInputAttributes(node.attributes)) {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "space-y-2", children: [
|
|
415
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Label, { htmlFor: node.attributes.name, children: [
|
|
416
|
+
node.meta.label?.text,
|
|
417
|
+
node.attributes.required && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
418
|
+
] }),
|
|
419
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
420
|
+
Input,
|
|
421
|
+
{
|
|
422
|
+
id: node.attributes.name,
|
|
423
|
+
name: node.attributes.name,
|
|
424
|
+
type: node.attributes.type,
|
|
425
|
+
defaultValue: node.attributes.value || "",
|
|
426
|
+
required: node.attributes.required,
|
|
427
|
+
disabled: node.attributes.disabled,
|
|
428
|
+
autoComplete: node.attributes.autocomplete,
|
|
429
|
+
placeholder: `Enter your ${node.meta.label?.text?.toLowerCase() || node.attributes.name}`
|
|
225
430
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
431
|
+
)
|
|
432
|
+
] });
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/form/utils.ts
|
|
436
|
+
var TYPE_ORDER = {
|
|
437
|
+
hidden: 0,
|
|
438
|
+
text: 1,
|
|
439
|
+
email: 1,
|
|
440
|
+
password: 1,
|
|
441
|
+
checkbox: 1,
|
|
442
|
+
submit: 2
|
|
443
|
+
};
|
|
444
|
+
function sortNodes(nodes) {
|
|
445
|
+
return [...nodes].sort((a, b) => {
|
|
446
|
+
const aIsInput = isUiNodeInputAttributes(a.attributes);
|
|
447
|
+
const bIsInput = isUiNodeInputAttributes(b.attributes);
|
|
448
|
+
if (!aIsInput && !bIsInput) return 0;
|
|
449
|
+
if (!aIsInput) return 1;
|
|
450
|
+
if (!bIsInput) return -1;
|
|
451
|
+
const aAttrs = a.attributes;
|
|
452
|
+
const bAttrs = b.attributes;
|
|
453
|
+
const aOrder = TYPE_ORDER[aAttrs.type] ?? 1;
|
|
454
|
+
const bOrder = TYPE_ORDER[bAttrs.type] ?? 1;
|
|
455
|
+
return aOrder - bOrder;
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
function findSubmitButton(nodes) {
|
|
459
|
+
return nodes.find(
|
|
460
|
+
(node) => isUiNodeInputAttributes(node.attributes) && node.attributes.type === "submit"
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
function findAnchorNode(nodes) {
|
|
464
|
+
return nodes.find((node) => node.type === "a");
|
|
465
|
+
}
|
|
466
|
+
function filterInputNodes(nodes) {
|
|
467
|
+
return nodes.filter(
|
|
468
|
+
(node) => isUiNodeInputAttributes(node.attributes) && node.attributes.type !== "submit" && node.attributes.type !== "hidden"
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
function findCsrfToken(nodes) {
|
|
472
|
+
return nodes.find(
|
|
473
|
+
(node) => isUiNodeInputAttributes(node.attributes) && node.attributes.name === "csrf_token"
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
function groupNodesByGroup(nodes) {
|
|
477
|
+
return nodes.reduce((groups, node) => {
|
|
478
|
+
const group = node.group || "default";
|
|
479
|
+
if (!groups[group]) {
|
|
480
|
+
groups[group] = [];
|
|
229
481
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
{
|
|
235
|
-
ref,
|
|
236
|
-
role: "alert",
|
|
237
|
-
className: cn(alertVariants({ variant }), className),
|
|
238
|
-
...props
|
|
239
|
-
}
|
|
240
|
-
));
|
|
241
|
-
Alert.displayName = "Alert";
|
|
242
|
-
var AlertTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
243
|
-
"h5",
|
|
244
|
-
{
|
|
245
|
-
ref,
|
|
246
|
-
className: cn("mb-1 font-medium leading-none tracking-tight", className),
|
|
247
|
-
...props
|
|
248
|
-
}
|
|
249
|
-
));
|
|
250
|
-
AlertTitle.displayName = "AlertTitle";
|
|
251
|
-
var AlertDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
252
|
-
"div",
|
|
253
|
-
{
|
|
254
|
-
ref,
|
|
255
|
-
className: cn("text-sm [&_p]:leading-relaxed", className),
|
|
256
|
-
...props
|
|
257
|
-
}
|
|
258
|
-
));
|
|
259
|
-
AlertDescription.displayName = "AlertDescription";
|
|
482
|
+
groups[group].push(node);
|
|
483
|
+
return groups;
|
|
484
|
+
}, {});
|
|
485
|
+
}
|
|
260
486
|
|
|
261
|
-
// src/
|
|
262
|
-
var
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
487
|
+
// src/form/login.tsx
|
|
488
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
489
|
+
function LoginForm({ flow, Header, register_url }) {
|
|
490
|
+
const nodesByGroup = groupNodesByGroup(flow.ui.nodes);
|
|
491
|
+
const csrfToken = findCsrfToken(flow.ui.nodes);
|
|
492
|
+
const oidcNodes = nodesByGroup.oidc || [];
|
|
493
|
+
const defaultNodes = nodesByGroup.default || [];
|
|
494
|
+
const passwordNodes = nodesByGroup.password || [];
|
|
495
|
+
const identifierNodes = filterInputNodes(sortNodes(defaultNodes));
|
|
496
|
+
const passwordInputNodes = filterInputNodes(sortNodes(passwordNodes));
|
|
497
|
+
const submitButton = findSubmitButton(sortNodes(passwordNodes));
|
|
498
|
+
const registerHref = register_url && flow.return_to ? `${register_url}?return_to=${encodeURIComponent(flow.return_to)}` : register_url;
|
|
499
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
500
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Messages, { flow }),
|
|
501
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Card, { className: "w-full max-w-md mx-auto", children: [
|
|
502
|
+
Header && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardTitle, { className: "text-center pb-1", children: Header }) }),
|
|
503
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(CardContent, { className: "space-y-6", children: [
|
|
504
|
+
oidcNodes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
505
|
+
OidcGroup,
|
|
506
|
+
{
|
|
507
|
+
nodes: sortNodes(oidcNodes),
|
|
508
|
+
flowAction: flow.ui.action,
|
|
509
|
+
flowMethod: flow.ui.method,
|
|
510
|
+
csrfToken,
|
|
511
|
+
groupIndex: 0,
|
|
512
|
+
groupName: "oidc"
|
|
513
|
+
}
|
|
514
|
+
),
|
|
515
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
516
|
+
oidcNodes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Divider, { withText: true }),
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("form", { action: flow.ui.action, method: flow.ui.method, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-4", children: [
|
|
518
|
+
csrfToken && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(HiddenInput, { node: csrfToken }),
|
|
519
|
+
identifierNodes.map((node, idx) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormInput, { node }, idx)),
|
|
520
|
+
passwordInputNodes.map((node, idx) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormInput, { node }, idx)),
|
|
521
|
+
submitButton && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SubmitButton, { node: submitButton })
|
|
522
|
+
] }) }),
|
|
523
|
+
register_url && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-4 text-center text-sm", children: [
|
|
524
|
+
"Don't have an account?",
|
|
525
|
+
" ",
|
|
526
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
527
|
+
"a",
|
|
528
|
+
{
|
|
529
|
+
href: registerHref,
|
|
530
|
+
className: "text-primary underline-offset-4 hover:underline",
|
|
531
|
+
children: "Go to Register"
|
|
532
|
+
}
|
|
533
|
+
)
|
|
534
|
+
] })
|
|
535
|
+
] })
|
|
536
|
+
] })
|
|
537
|
+
] })
|
|
538
|
+
] });
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/form/registration.tsx
|
|
542
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
543
|
+
function RegistrationForm({
|
|
544
|
+
flow,
|
|
545
|
+
Header,
|
|
546
|
+
login_url
|
|
547
|
+
}) {
|
|
548
|
+
const nodesByGroup = groupNodesByGroup(flow.ui.nodes);
|
|
549
|
+
const csrfToken = findCsrfToken(flow.ui.nodes);
|
|
550
|
+
const oidcNodes = nodesByGroup.oidc || [];
|
|
551
|
+
const defaultNodes = nodesByGroup.default || [];
|
|
552
|
+
const profileNodes = nodesByGroup.profile || [];
|
|
553
|
+
const passwordNodes = nodesByGroup.password || [];
|
|
554
|
+
const inputNodes = filterInputNodes(
|
|
555
|
+
sortNodes([...defaultNodes, ...passwordNodes])
|
|
556
|
+
);
|
|
557
|
+
const hiddenNodes = [...defaultNodes, ...passwordNodes].filter(
|
|
558
|
+
(node) => isUiNodeInputAttributes(node.attributes) && node.attributes.type === "hidden" && node.attributes.name !== "csrf_token"
|
|
559
|
+
);
|
|
560
|
+
const submitButton = findSubmitButton(sortNodes(passwordNodes)) || findSubmitButton(sortNodes(profileNodes));
|
|
561
|
+
const loginHref = login_url && flow.return_to ? `${login_url}?return_to=${encodeURIComponent(flow.return_to)}` : login_url;
|
|
562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
563
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Messages, { flow }),
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Card, { className: "w-full max-w-md mx-auto", children: [
|
|
565
|
+
Header && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardTitle, { className: "text-center pb-1", children: Header }) }),
|
|
566
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(CardContent, { className: "space-y-6", children: [
|
|
567
|
+
oidcNodes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
568
|
+
OidcGroup,
|
|
569
|
+
{
|
|
570
|
+
nodes: sortNodes(oidcNodes),
|
|
571
|
+
flowAction: flow.ui.action,
|
|
572
|
+
flowMethod: flow.ui.method,
|
|
573
|
+
csrfToken,
|
|
574
|
+
groupIndex: 0,
|
|
575
|
+
groupName: "oidc"
|
|
576
|
+
}
|
|
577
|
+
),
|
|
578
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
579
|
+
oidcNodes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Divider, { withText: true }),
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("form", { action: flow.ui.action, method: flow.ui.method, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-4", children: [
|
|
581
|
+
csrfToken && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(HiddenInput, { node: csrfToken }),
|
|
582
|
+
hiddenNodes.map((node, idx) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(HiddenInput, { node }, `hidden-${idx}`)),
|
|
583
|
+
inputNodes.map((node, idx) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FormInput, { node }, idx)),
|
|
584
|
+
submitButton && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SubmitButton, { node: submitButton })
|
|
585
|
+
] }) }),
|
|
586
|
+
login_url && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "mt-4 text-center text-sm", children: [
|
|
587
|
+
"Already have an account?",
|
|
588
|
+
" ",
|
|
589
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
590
|
+
"a",
|
|
591
|
+
{
|
|
592
|
+
href: loginHref,
|
|
593
|
+
className: "text-primary underline-offset-4 hover:underline",
|
|
594
|
+
children: "Go to Login"
|
|
595
|
+
}
|
|
596
|
+
)
|
|
597
|
+
] })
|
|
598
|
+
] })
|
|
599
|
+
] })
|
|
600
|
+
] })
|
|
601
|
+
] });
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/form/verification.tsx
|
|
605
|
+
var React8 = __toESM(require("react"), 1);
|
|
606
|
+
|
|
607
|
+
// src/form/components/PinInput.tsx
|
|
608
|
+
var React7 = __toESM(require("react"), 1);
|
|
609
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
610
|
+
function PinInput({
|
|
611
|
+
node,
|
|
612
|
+
length = 6,
|
|
613
|
+
initialValue = ""
|
|
614
|
+
}) {
|
|
615
|
+
if (!isUiNodeInputAttributes(node.attributes)) {
|
|
616
|
+
return null;
|
|
275
617
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
618
|
+
const [pins, setPins] = React7.useState(() => {
|
|
619
|
+
if (initialValue) {
|
|
620
|
+
const sanitized = initialValue.replace(/[^0-9]/g, "").slice(0, length);
|
|
621
|
+
const pinArray = Array(length).fill("");
|
|
622
|
+
for (let i = 0; i < sanitized.length; i++) {
|
|
623
|
+
pinArray[i] = sanitized[i];
|
|
624
|
+
}
|
|
625
|
+
return pinArray;
|
|
283
626
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
627
|
+
return Array(length).fill("");
|
|
628
|
+
});
|
|
629
|
+
const inputRefs = React7.useRef([]);
|
|
630
|
+
const handleChange = (index, value) => {
|
|
631
|
+
const sanitizedValue = value.replace(/[^0-9]/g, "").slice(0, 1);
|
|
632
|
+
const newPins = [...pins];
|
|
633
|
+
newPins[index] = sanitizedValue;
|
|
634
|
+
setPins(newPins);
|
|
635
|
+
if (sanitizedValue && index < length - 1) {
|
|
636
|
+
inputRefs.current[index + 1]?.focus();
|
|
290
637
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
638
|
+
};
|
|
639
|
+
const handleKeyDown = (index, e) => {
|
|
640
|
+
if (e.key === "Backspace" && !pins[index] && index > 0) {
|
|
641
|
+
inputRefs.current[index - 1]?.focus();
|
|
642
|
+
}
|
|
643
|
+
if (e.key === "ArrowLeft" && index > 0) {
|
|
644
|
+
inputRefs.current[index - 1]?.focus();
|
|
645
|
+
}
|
|
646
|
+
if (e.key === "ArrowRight" && index < length - 1) {
|
|
647
|
+
inputRefs.current[index + 1]?.focus();
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
const handlePaste = (e) => {
|
|
651
|
+
e.preventDefault();
|
|
652
|
+
const pastedData = e.clipboardData.getData("text").replace(/[^0-9]/g, "");
|
|
653
|
+
const newPins = [...pins];
|
|
654
|
+
for (let i = 0; i < Math.min(pastedData.length, length); i++) {
|
|
655
|
+
newPins[i] = pastedData[i];
|
|
656
|
+
}
|
|
657
|
+
setPins(newPins);
|
|
658
|
+
const nextEmptyIndex = newPins.findIndex((pin) => !pin);
|
|
659
|
+
const focusIndex = nextEmptyIndex === -1 ? length - 1 : nextEmptyIndex;
|
|
660
|
+
inputRefs.current[focusIndex]?.focus();
|
|
661
|
+
};
|
|
662
|
+
const combinedValue = pins.join("");
|
|
663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-2 mb-6", children: [
|
|
664
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex gap-2 justify-center", children: Array.from({ length }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
665
|
+
"input",
|
|
294
666
|
{
|
|
295
|
-
ref,
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
667
|
+
ref: (el) => inputRefs.current[index] = el,
|
|
668
|
+
type: "text",
|
|
669
|
+
inputMode: "numeric",
|
|
670
|
+
maxLength: 1,
|
|
671
|
+
value: pins[index],
|
|
672
|
+
onChange: (e) => handleChange(index, e.target.value),
|
|
673
|
+
onKeyDown: (e) => handleKeyDown(index, e),
|
|
674
|
+
onPaste: index === 0 ? handlePaste : void 0,
|
|
675
|
+
disabled: isUiNodeInputAttributes(node.attributes) ? node.attributes.disabled : false,
|
|
676
|
+
className: cn(
|
|
677
|
+
"w-10 h-12 text-center text-lg font-semibold rounded-md border-2",
|
|
678
|
+
"border-input bg-background shadow-sm transition-all duration-200 outline-none",
|
|
679
|
+
"hover:border-ring/60",
|
|
680
|
+
"focus:border-ring focus:ring-4 focus:ring-ring/20 focus:scale-105",
|
|
681
|
+
"aria-invalid:border-destructive aria-invalid:ring-destructive/20",
|
|
682
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
683
|
+
pins[index] && "border-primary bg-primary/5"
|
|
684
|
+
),
|
|
685
|
+
"aria-label": `Digit ${index + 1}`
|
|
686
|
+
},
|
|
687
|
+
index
|
|
688
|
+
)) }),
|
|
689
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
690
|
+
"input",
|
|
691
|
+
{
|
|
692
|
+
type: "hidden",
|
|
693
|
+
id: node.attributes.name,
|
|
694
|
+
name: node.attributes.name,
|
|
695
|
+
value: combinedValue,
|
|
696
|
+
required: node.attributes.required
|
|
299
697
|
}
|
|
300
|
-
)
|
|
698
|
+
)
|
|
699
|
+
] });
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/form/components/AnchorButton.tsx
|
|
703
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
704
|
+
function AnchorButton({
|
|
705
|
+
node,
|
|
706
|
+
variant = "default",
|
|
707
|
+
className = "w-full"
|
|
708
|
+
}) {
|
|
709
|
+
if (node.type !== "a" || !("href" in node.attributes)) {
|
|
710
|
+
return null;
|
|
301
711
|
}
|
|
302
|
-
|
|
303
|
-
|
|
712
|
+
const href = node.attributes.href;
|
|
713
|
+
const title = node.attributes.title;
|
|
714
|
+
const label = node.meta?.label;
|
|
715
|
+
const buttonText = (typeof title === "object" && title !== null && "text" in title ? title.text : typeof title === "string" ? title : null) || (label && typeof label === "object" && "text" in label ? label.text : null) || "Continue";
|
|
716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant, className, asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("a", { href, children: buttonText }) });
|
|
717
|
+
}
|
|
304
718
|
|
|
305
|
-
// src/form/
|
|
306
|
-
var
|
|
307
|
-
function
|
|
719
|
+
// src/form/verification.tsx
|
|
720
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
721
|
+
function VerificationForm({
|
|
722
|
+
flow,
|
|
723
|
+
Header,
|
|
724
|
+
autoRedirect = true
|
|
725
|
+
}) {
|
|
726
|
+
const nodesByGroup = groupNodesByGroup(flow.ui.nodes);
|
|
727
|
+
const csrfToken = findCsrfToken(flow.ui.nodes);
|
|
728
|
+
const codeNodes = nodesByGroup.code || [];
|
|
729
|
+
const inputNodes = filterInputNodes(sortNodes(codeNodes));
|
|
730
|
+
const submitButton = findSubmitButton(sortNodes(codeNodes));
|
|
731
|
+
const anchorNode = findAnchorNode(sortNodes(codeNodes));
|
|
732
|
+
React8.useEffect(() => {
|
|
733
|
+
if (autoRedirect && anchorNode && anchorNode.type === "a" && "href" in anchorNode.attributes) {
|
|
734
|
+
const href = anchorNode.attributes.href;
|
|
735
|
+
if (href && typeof window !== "undefined") {
|
|
736
|
+
window.location.href = href;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}, [autoRedirect, anchorNode]);
|
|
740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
|
|
741
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Messages, { flow }),
|
|
742
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Card, { className: "w-full max-w-md mx-auto", children: [
|
|
743
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardTitle, { className: "text-center pb-1", children: Header || "Verification Code" }) }),
|
|
744
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("form", { action: flow.ui.action, method: flow.ui.method, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "space-y-4", children: [
|
|
745
|
+
csrfToken && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(HiddenInput, { node: csrfToken }),
|
|
746
|
+
inputNodes.map((node, idx) => {
|
|
747
|
+
const isCodeInput = node.attributes.node_type === "input" && "name" in node.attributes && node.attributes.name === "code";
|
|
748
|
+
const initialValue = isCodeInput && "value" in node.attributes ? String(node.attributes.value || "") : "";
|
|
749
|
+
return isCodeInput ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
750
|
+
PinInput,
|
|
751
|
+
{
|
|
752
|
+
node,
|
|
753
|
+
length: 6,
|
|
754
|
+
initialValue
|
|
755
|
+
},
|
|
756
|
+
idx
|
|
757
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FormInput, { node }, idx);
|
|
758
|
+
}),
|
|
759
|
+
submitButton && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SubmitButton, { node: submitButton }),
|
|
760
|
+
!submitButton && anchorNode && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AnchorButton, { node: anchorNode })
|
|
761
|
+
] }) }) })
|
|
762
|
+
] })
|
|
763
|
+
] });
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// src/form/recovery.tsx
|
|
767
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
768
|
+
function RecoveryForm({ flow, Header }) {
|
|
769
|
+
const nodesByGroup = groupNodesByGroup(flow.ui.nodes);
|
|
770
|
+
const csrfToken = findCsrfToken(flow.ui.nodes);
|
|
771
|
+
const codeNodes = nodesByGroup.code || [];
|
|
772
|
+
const linkNodes = nodesByGroup.link || [];
|
|
773
|
+
const activeNodes = codeNodes.length > 0 ? codeNodes : linkNodes;
|
|
774
|
+
const inputNodes = filterInputNodes(sortNodes(activeNodes));
|
|
775
|
+
const submitButton = findSubmitButton(sortNodes(activeNodes));
|
|
776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
|
|
777
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Messages, { flow }),
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Card, { className: "w-full max-w-md mx-auto", children: [
|
|
779
|
+
Header && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardTitle, { className: "text-center pb-1", children: Header }) }),
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("form", { action: flow.ui.action, method: flow.ui.method, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-4", children: [
|
|
781
|
+
csrfToken && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(HiddenInput, { node: csrfToken }),
|
|
782
|
+
inputNodes.map((node, idx) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FormInput, { node }, idx)),
|
|
783
|
+
submitButton && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SubmitButton, { node: submitButton })
|
|
784
|
+
] }) }) })
|
|
785
|
+
] })
|
|
786
|
+
] });
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// src/form/settings.tsx
|
|
790
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
791
|
+
function isUiNodeInputAttributes2(attributes) {
|
|
308
792
|
return attributes && typeof attributes === "object" && "name" in attributes && "type" in attributes;
|
|
309
793
|
}
|
|
310
|
-
function
|
|
794
|
+
function SettingsForm({ flow }) {
|
|
311
795
|
const nodesByGroup = flow.ui.nodes.reduce((groups, node) => {
|
|
312
796
|
const group = node.group || "default";
|
|
313
797
|
if (!groups[group]) {
|
|
@@ -316,150 +800,128 @@ function CustomFlowForm({ flow, Header }) {
|
|
|
316
800
|
groups[group].push(node);
|
|
317
801
|
return groups;
|
|
318
802
|
}, {});
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
const csrfToken = regularNodes.find(
|
|
322
|
-
(node) => isUiNodeInputAttributes(node.attributes) && node.attributes.name === "csrf_token"
|
|
803
|
+
const csrfToken = flow.ui.nodes.find(
|
|
804
|
+
(node) => isUiNodeInputAttributes2(node.attributes) && node.attributes.name === "csrf_token"
|
|
323
805
|
);
|
|
324
|
-
const
|
|
325
|
-
(
|
|
806
|
+
const settingsGroups = Object.entries(nodesByGroup).filter(
|
|
807
|
+
([group]) => group !== "default" && group !== "oidc"
|
|
326
808
|
);
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
809
|
+
const groupTitles = {
|
|
810
|
+
profile: "Profile",
|
|
811
|
+
password: "Password",
|
|
812
|
+
totp: "Authenticator App",
|
|
813
|
+
webauthn: "Security Keys",
|
|
814
|
+
lookup_secret: "Backup Recovery Codes",
|
|
815
|
+
passkey: "Passkeys"
|
|
816
|
+
};
|
|
817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-6", children: [
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Messages, { flow }),
|
|
819
|
+
settingsGroups.map(([groupName, nodes]) => {
|
|
820
|
+
const submitButton = nodes.find(
|
|
821
|
+
(node) => isUiNodeInputAttributes2(node.attributes) && node.attributes.type === "submit"
|
|
822
|
+
);
|
|
823
|
+
const inputNodes = nodes.filter(
|
|
824
|
+
(node) => isUiNodeInputAttributes2(node.attributes) && node.attributes.type !== "submit" && node.attributes.type !== "hidden"
|
|
825
|
+
);
|
|
826
|
+
const imageNodes = nodes.filter((node) => node.type === "img");
|
|
827
|
+
const textNodes = nodes.filter((node) => node.type === "text");
|
|
828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Card, { className: "w-full max-w-2xl mx-auto", children: [
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CardTitle, { children: groupTitles[groupName] || groupName }) }),
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("form", { action: flow.ui.action, method: flow.ui.method, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-4", children: [
|
|
831
|
+
csrfToken && isUiNodeInputAttributes2(csrfToken.attributes) && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
832
|
+
"input",
|
|
833
|
+
{
|
|
834
|
+
name: csrfToken.attributes.name,
|
|
835
|
+
type: "hidden",
|
|
836
|
+
value: csrfToken.attributes.value || "",
|
|
837
|
+
readOnly: true
|
|
838
|
+
}
|
|
839
|
+
),
|
|
840
|
+
imageNodes.map((node, index) => {
|
|
841
|
+
if (node.type === "img" && "src" in node.attributes) {
|
|
842
|
+
const imgAttrs = node.attributes;
|
|
843
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
844
|
+
"div",
|
|
337
845
|
{
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
"
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
350
|
-
),
|
|
351
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
352
|
-
Button,
|
|
353
|
-
{
|
|
354
|
-
type: "submit",
|
|
355
|
-
name: node.attributes.name,
|
|
356
|
-
value: node.attributes.value || "",
|
|
357
|
-
variant: "outline",
|
|
358
|
-
className: "w-full",
|
|
359
|
-
children: node.meta.label?.text || node.attributes.value || "Sign in"
|
|
360
|
-
}
|
|
361
|
-
)
|
|
362
|
-
]
|
|
846
|
+
className: "flex justify-center",
|
|
847
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
848
|
+
"img",
|
|
849
|
+
{
|
|
850
|
+
src: imgAttrs.src,
|
|
851
|
+
alt: node.meta.label?.text || "QR Code",
|
|
852
|
+
width: imgAttrs.width,
|
|
853
|
+
height: imgAttrs.height,
|
|
854
|
+
className: "border rounded-lg"
|
|
855
|
+
}
|
|
856
|
+
)
|
|
363
857
|
},
|
|
364
|
-
`
|
|
858
|
+
`img-${index}`
|
|
365
859
|
);
|
|
366
860
|
}
|
|
367
861
|
return null;
|
|
368
862
|
}),
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
"
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
value: node.attributes.value || "",
|
|
389
|
-
readOnly: true
|
|
390
|
-
},
|
|
391
|
-
node.attributes.name
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
if (isSubmitButton) {
|
|
395
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
396
|
-
Button,
|
|
863
|
+
textNodes.map((node, index) => {
|
|
864
|
+
if (node.type === "text" && "text" in node.attributes) {
|
|
865
|
+
const textContent = typeof node.attributes.text === "string" ? node.attributes.text : node.attributes.text?.text || "";
|
|
866
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-2", children: [
|
|
867
|
+
node.meta.label?.text && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { className: "text-sm text-muted-foreground", children: node.meta.label.text }),
|
|
868
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "p-3 bg-muted rounded-md font-mono text-sm break-all", children: textContent })
|
|
869
|
+
] }, `text-${index}`);
|
|
870
|
+
}
|
|
871
|
+
return null;
|
|
872
|
+
}),
|
|
873
|
+
inputNodes.map((node) => {
|
|
874
|
+
if (isUiNodeInputAttributes2(node.attributes)) {
|
|
875
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-2", children: [
|
|
876
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Label, { htmlFor: node.attributes.name, children: [
|
|
877
|
+
node.meta.label?.text,
|
|
878
|
+
node.attributes.required && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
879
|
+
] }),
|
|
880
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
881
|
+
Input,
|
|
397
882
|
{
|
|
398
|
-
|
|
883
|
+
id: node.attributes.name,
|
|
399
884
|
name: node.attributes.name,
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
"password",
|
|
410
|
-
"code",
|
|
411
|
-
"webauthn",
|
|
412
|
-
"passkey",
|
|
413
|
-
"totp",
|
|
414
|
-
"lookup_secret",
|
|
415
|
-
"profile"
|
|
416
|
-
].includes(node.group)) {
|
|
417
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
418
|
-
"div",
|
|
419
|
-
{
|
|
420
|
-
className: "space-y-2 mb-4",
|
|
421
|
-
children: [
|
|
422
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Label, { htmlFor: node.attributes.name, children: [
|
|
423
|
-
node.meta.label?.text,
|
|
424
|
-
node.attributes.required && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
425
|
-
] }),
|
|
426
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
427
|
-
Input,
|
|
428
|
-
{
|
|
429
|
-
id: node.attributes.name,
|
|
430
|
-
name: node.attributes.name,
|
|
431
|
-
type: node.attributes.type,
|
|
432
|
-
defaultValue: node.attributes.value || "",
|
|
433
|
-
required: node.attributes.required,
|
|
434
|
-
placeholder: `Enter your ${node.meta.label?.text?.toLowerCase() || node.attributes.name}`
|
|
435
|
-
}
|
|
436
|
-
)
|
|
437
|
-
]
|
|
438
|
-
},
|
|
439
|
-
node.meta.label?.id || node.attributes.name
|
|
440
|
-
);
|
|
441
|
-
}
|
|
885
|
+
type: node.attributes.type,
|
|
886
|
+
defaultValue: node.attributes.value || "",
|
|
887
|
+
required: node.attributes.required,
|
|
888
|
+
disabled: node.attributes.disabled,
|
|
889
|
+
autoComplete: node.attributes.autocomplete,
|
|
890
|
+
placeholder: `Enter ${node.meta.label?.text?.toLowerCase() || node.attributes.name}`
|
|
891
|
+
}
|
|
892
|
+
)
|
|
893
|
+
] }, node.attributes.name);
|
|
442
894
|
}
|
|
443
895
|
return null;
|
|
444
896
|
}),
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
897
|
+
submitButton && isUiNodeInputAttributes2(submitButton.attributes) && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
898
|
+
Button,
|
|
899
|
+
{
|
|
900
|
+
type: "submit",
|
|
901
|
+
name: submitButton.attributes.name,
|
|
902
|
+
value: submitButton.attributes.value || "",
|
|
903
|
+
className: "w-full",
|
|
904
|
+
disabled: submitButton.attributes.disabled,
|
|
905
|
+
children: submitButton.meta.label?.text || submitButton.attributes.value || "Save"
|
|
906
|
+
}
|
|
907
|
+
)
|
|
908
|
+
] }) }) })
|
|
909
|
+
] }, groupName);
|
|
910
|
+
})
|
|
449
911
|
] });
|
|
450
912
|
}
|
|
451
913
|
|
|
452
914
|
// src/tenant-switcher/index.tsx
|
|
453
|
-
var
|
|
915
|
+
var React10 = __toESM(require("react"), 1);
|
|
454
916
|
|
|
455
917
|
// src/components/ui/select.tsx
|
|
456
|
-
var
|
|
918
|
+
var React9 = __toESM(require("react"), 1);
|
|
457
919
|
var SelectPrimitive = __toESM(require("@radix-ui/react-select"), 1);
|
|
458
920
|
var import_lucide_react = require("lucide-react");
|
|
459
|
-
var
|
|
921
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
460
922
|
var Select = SelectPrimitive.Root;
|
|
461
923
|
var SelectValue = SelectPrimitive.Value;
|
|
462
|
-
var SelectTrigger =
|
|
924
|
+
var SelectTrigger = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
463
925
|
SelectPrimitive.Trigger,
|
|
464
926
|
{
|
|
465
927
|
ref,
|
|
@@ -470,12 +932,12 @@ var SelectTrigger = React7.forwardRef(({ className, children, ...props }, ref) =
|
|
|
470
932
|
...props,
|
|
471
933
|
children: [
|
|
472
934
|
children,
|
|
473
|
-
/* @__PURE__ */ (0,
|
|
935
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react.ChevronDown, { className: "h-4 w-4 opacity-50" }) })
|
|
474
936
|
]
|
|
475
937
|
}
|
|
476
938
|
));
|
|
477
939
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
478
|
-
var SelectScrollUpButton =
|
|
940
|
+
var SelectScrollUpButton = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
479
941
|
SelectPrimitive.ScrollUpButton,
|
|
480
942
|
{
|
|
481
943
|
ref,
|
|
@@ -484,11 +946,11 @@ var SelectScrollUpButton = React7.forwardRef(({ className, ...props }, ref) => /
|
|
|
484
946
|
className
|
|
485
947
|
),
|
|
486
948
|
...props,
|
|
487
|
-
children: /* @__PURE__ */ (0,
|
|
949
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react.ChevronUp, { className: "h-4 w-4" })
|
|
488
950
|
}
|
|
489
951
|
));
|
|
490
952
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
491
|
-
var SelectScrollDownButton =
|
|
953
|
+
var SelectScrollDownButton = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
492
954
|
SelectPrimitive.ScrollDownButton,
|
|
493
955
|
{
|
|
494
956
|
ref,
|
|
@@ -497,11 +959,11 @@ var SelectScrollDownButton = React7.forwardRef(({ className, ...props }, ref) =>
|
|
|
497
959
|
className
|
|
498
960
|
),
|
|
499
961
|
...props,
|
|
500
|
-
children: /* @__PURE__ */ (0,
|
|
962
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react.ChevronDown, { className: "h-4 w-4" })
|
|
501
963
|
}
|
|
502
964
|
));
|
|
503
965
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
504
|
-
var SelectContent =
|
|
966
|
+
var SelectContent = React9.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
505
967
|
SelectPrimitive.Content,
|
|
506
968
|
{
|
|
507
969
|
ref,
|
|
@@ -513,8 +975,8 @@ var SelectContent = React7.forwardRef(({ className, children, position = "popper
|
|
|
513
975
|
position,
|
|
514
976
|
...props,
|
|
515
977
|
children: [
|
|
516
|
-
/* @__PURE__ */ (0,
|
|
517
|
-
/* @__PURE__ */ (0,
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SelectScrollUpButton, {}),
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
518
980
|
SelectPrimitive.Viewport,
|
|
519
981
|
{
|
|
520
982
|
className: cn(
|
|
@@ -524,12 +986,12 @@ var SelectContent = React7.forwardRef(({ className, children, position = "popper
|
|
|
524
986
|
children
|
|
525
987
|
}
|
|
526
988
|
),
|
|
527
|
-
/* @__PURE__ */ (0,
|
|
989
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SelectScrollDownButton, {})
|
|
528
990
|
]
|
|
529
991
|
}
|
|
530
992
|
) }));
|
|
531
993
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
532
|
-
var SelectLabel =
|
|
994
|
+
var SelectLabel = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
533
995
|
SelectPrimitive.Label,
|
|
534
996
|
{
|
|
535
997
|
ref,
|
|
@@ -538,7 +1000,7 @@ var SelectLabel = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
538
1000
|
}
|
|
539
1001
|
));
|
|
540
1002
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
541
|
-
var SelectItem =
|
|
1003
|
+
var SelectItem = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
542
1004
|
SelectPrimitive.Item,
|
|
543
1005
|
{
|
|
544
1006
|
ref,
|
|
@@ -548,13 +1010,13 @@ var SelectItem = React7.forwardRef(({ className, children, ...props }, ref) => /
|
|
|
548
1010
|
),
|
|
549
1011
|
...props,
|
|
550
1012
|
children: [
|
|
551
|
-
/* @__PURE__ */ (0,
|
|
552
|
-
/* @__PURE__ */ (0,
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react.Check, { className: "h-4 w-4" }) }) }),
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SelectPrimitive.ItemText, { children })
|
|
553
1015
|
]
|
|
554
1016
|
}
|
|
555
1017
|
));
|
|
556
1018
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
557
|
-
var SelectSeparator =
|
|
1019
|
+
var SelectSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
558
1020
|
SelectPrimitive.Separator,
|
|
559
1021
|
{
|
|
560
1022
|
ref,
|
|
@@ -565,7 +1027,7 @@ var SelectSeparator = React7.forwardRef(({ className, ...props }, ref) => /* @__
|
|
|
565
1027
|
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
566
1028
|
|
|
567
1029
|
// src/tenant-switcher/index.tsx
|
|
568
|
-
var
|
|
1030
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
569
1031
|
function SwitchActiveTenant({
|
|
570
1032
|
tenants,
|
|
571
1033
|
currentTenantId,
|
|
@@ -574,7 +1036,7 @@ function SwitchActiveTenant({
|
|
|
574
1036
|
className,
|
|
575
1037
|
onTenantChange
|
|
576
1038
|
}) {
|
|
577
|
-
const [isLoading, setIsLoading] =
|
|
1039
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
578
1040
|
const handleTenantChange = async (tenantId) => {
|
|
579
1041
|
if (tenantId === currentTenantId) return;
|
|
580
1042
|
setIsLoading(true);
|
|
@@ -592,24 +1054,24 @@ function SwitchActiveTenant({
|
|
|
592
1054
|
}
|
|
593
1055
|
};
|
|
594
1056
|
const currentTenant = tenants.find((tenant) => tenant.id === currentTenantId);
|
|
595
|
-
return /* @__PURE__ */ (0,
|
|
1057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
596
1058
|
Select,
|
|
597
1059
|
{
|
|
598
1060
|
value: currentTenantId,
|
|
599
1061
|
onValueChange: handleTenantChange,
|
|
600
1062
|
disabled: isLoading,
|
|
601
1063
|
children: [
|
|
602
|
-
/* @__PURE__ */ (0,
|
|
603
|
-
/* @__PURE__ */ (0,
|
|
1064
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectTrigger, { className: cn("max-w-64", className), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectValue, { placeholder, children: currentTenant ? currentTenant.name : placeholder }) }),
|
|
1065
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectContent, { children: tenants.map((tenant) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectItem, { value: tenant.id, children: tenant.name }, tenant.id)) })
|
|
604
1066
|
]
|
|
605
1067
|
}
|
|
606
1068
|
);
|
|
607
1069
|
}
|
|
608
1070
|
|
|
609
1071
|
// src/pricing-table/index.tsx
|
|
610
|
-
var
|
|
1072
|
+
var React11 = __toESM(require("react"), 1);
|
|
611
1073
|
var import_lucide_react2 = require("lucide-react");
|
|
612
|
-
var
|
|
1074
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
613
1075
|
var getCurrencySymbol = (currency) => {
|
|
614
1076
|
const symbols = {
|
|
615
1077
|
USD: "$",
|
|
@@ -650,7 +1112,7 @@ function PricingCard({
|
|
|
650
1112
|
}) {
|
|
651
1113
|
const ui = product.ui || {};
|
|
652
1114
|
const isHighlighted = ui.highlighted;
|
|
653
|
-
return /* @__PURE__ */ (0,
|
|
1115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
654
1116
|
"div",
|
|
655
1117
|
{
|
|
656
1118
|
className: cn(
|
|
@@ -658,11 +1120,11 @@ function PricingCard({
|
|
|
658
1120
|
isHighlighted ? "relative" : ""
|
|
659
1121
|
),
|
|
660
1122
|
children: [
|
|
661
|
-
/* @__PURE__ */ (0,
|
|
662
|
-
ui.badge === "Most Popular" && /* @__PURE__ */ (0,
|
|
1123
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "h-4 flex-shrink-0 relative", children: ui.badge && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute top-0 left-1/2 transform -translate-x-1/2 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime21.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: [
|
|
1124
|
+
ui.badge === "Most Popular" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react2.Star, { className: "w-3 h-3" }),
|
|
663
1125
|
ui.badge
|
|
664
1126
|
] }) }) }),
|
|
665
|
-
/* @__PURE__ */ (0,
|
|
1127
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
666
1128
|
Card,
|
|
667
1129
|
{
|
|
668
1130
|
className: cn(
|
|
@@ -671,36 +1133,36 @@ function PricingCard({
|
|
|
671
1133
|
isSelected && "ring-2 ring-primary"
|
|
672
1134
|
),
|
|
673
1135
|
children: [
|
|
674
|
-
/* @__PURE__ */ (0,
|
|
675
|
-
/* @__PURE__ */ (0,
|
|
676
|
-
ui.tagline && /* @__PURE__ */ (0,
|
|
1136
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(CardHeader, { className: "text-center", children: [
|
|
1137
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardTitle, { className: "text-xl font-bold", children: ui.display_name || product.name }),
|
|
1138
|
+
ui.tagline && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardDescription, { className: "text-base", children: ui.tagline })
|
|
677
1139
|
] }),
|
|
678
|
-
/* @__PURE__ */ (0,
|
|
679
|
-
/* @__PURE__ */ (0,
|
|
680
|
-
/* @__PURE__ */ (0,
|
|
681
|
-
/* @__PURE__ */ (0,
|
|
1140
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(CardContent, { className: "flex-1 space-y-6", children: [
|
|
1141
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "text-center", children: [
|
|
1142
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-3xl font-bold", children: formatPrice(displayedPrice) }),
|
|
1143
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-sm text-muted-foreground", children: formatBillingPeriod(displayedPrice) })
|
|
682
1144
|
] }),
|
|
683
|
-
(ui.features && ui.features.length > 0 || displayedPrice.ui?.features?.length > 0 || displayedPrice.ui?.limits?.length > 0) && /* @__PURE__ */ (0,
|
|
684
|
-
ui.features && ui.features.length > 0 && /* @__PURE__ */ (0,
|
|
685
|
-
/* @__PURE__ */ (0,
|
|
686
|
-
/* @__PURE__ */ (0,
|
|
687
|
-
/* @__PURE__ */ (0,
|
|
688
|
-
/* @__PURE__ */ (0,
|
|
1145
|
+
(ui.features && ui.features.length > 0 || displayedPrice.ui?.features?.length > 0 || displayedPrice.ui?.limits?.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
1146
|
+
ui.features && ui.features.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-2", children: [
|
|
1147
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h4", { className: "font-medium text-sm text-muted-foreground uppercase tracking-wide", children: "Features" }),
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "space-y-2", children: ui.features.map((feature, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
1149
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react2.Check, { className: "w-4 h-4 text-green-500 mt-0.5 flex-shrink-0" }),
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-sm", children: feature })
|
|
689
1151
|
] }, index)) })
|
|
690
1152
|
] }),
|
|
691
|
-
displayedPrice.ui?.features && displayedPrice.ui.features.length > 0 && /* @__PURE__ */ (0,
|
|
692
|
-
/* @__PURE__ */ (0,
|
|
693
|
-
/* @__PURE__ */ (0,
|
|
694
|
-
(feature, index) => /* @__PURE__ */ (0,
|
|
695
|
-
/* @__PURE__ */ (0,
|
|
696
|
-
/* @__PURE__ */ (0,
|
|
1153
|
+
displayedPrice.ui?.features && displayedPrice.ui.features.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-2", children: [
|
|
1154
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h4", { className: "font-medium text-sm text-muted-foreground uppercase tracking-wide", children: "This Plan" }),
|
|
1155
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "space-y-2", children: displayedPrice.ui.features.map(
|
|
1156
|
+
(feature, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
1157
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react2.Check, { className: "w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0" }),
|
|
1158
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-sm", children: feature })
|
|
697
1159
|
] }, index)
|
|
698
1160
|
) })
|
|
699
1161
|
] }),
|
|
700
|
-
displayedPrice.ui?.limits && displayedPrice.ui.limits.length > 0 && /* @__PURE__ */ (0,
|
|
701
|
-
/* @__PURE__ */ (0,
|
|
702
|
-
/* @__PURE__ */ (0,
|
|
703
|
-
(limit, index) => /* @__PURE__ */ (0,
|
|
1162
|
+
displayedPrice.ui?.limits && displayedPrice.ui.limits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-2", children: [
|
|
1163
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h4", { className: "font-medium text-sm text-muted-foreground uppercase tracking-wide", children: "Usage Limits" }),
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "space-y-1", children: displayedPrice.ui.limits.map(
|
|
1165
|
+
(limit, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
704
1166
|
"li",
|
|
705
1167
|
{
|
|
706
1168
|
className: "text-sm text-muted-foreground",
|
|
@@ -712,7 +1174,7 @@ function PricingCard({
|
|
|
712
1174
|
] })
|
|
713
1175
|
] })
|
|
714
1176
|
] }),
|
|
715
|
-
/* @__PURE__ */ (0,
|
|
1177
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardFooter, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
716
1178
|
Button,
|
|
717
1179
|
{
|
|
718
1180
|
className: "w-full",
|
|
@@ -739,24 +1201,24 @@ function PricingTable({
|
|
|
739
1201
|
showPricingToggle = false,
|
|
740
1202
|
defaultInterval = "month"
|
|
741
1203
|
}) {
|
|
742
|
-
const [selectedInterval, setSelectedInterval] =
|
|
743
|
-
const [carouselIndex, setCarouselIndex] =
|
|
744
|
-
const sortedProducts =
|
|
1204
|
+
const [selectedInterval, setSelectedInterval] = React11.useState(defaultInterval);
|
|
1205
|
+
const [carouselIndex, setCarouselIndex] = React11.useState(0);
|
|
1206
|
+
const sortedProducts = React11.useMemo(
|
|
745
1207
|
() => [...products].sort(
|
|
746
1208
|
(a, b) => (a.ui?.sort_order ?? 999) - (b.ui?.sort_order ?? 999)
|
|
747
1209
|
),
|
|
748
1210
|
[products]
|
|
749
1211
|
);
|
|
750
|
-
const hasMultipleIntervals =
|
|
1212
|
+
const hasMultipleIntervals = React11.useMemo(
|
|
751
1213
|
() => products.some(
|
|
752
1214
|
(p) => new Set(p.prices.map((price) => price.interval)).size > 1
|
|
753
1215
|
),
|
|
754
1216
|
[products]
|
|
755
1217
|
);
|
|
756
|
-
const getDisplayedPrice = (product) => product.prices.find((
|
|
1218
|
+
const getDisplayedPrice = (product) => product.prices.find((price) => price.interval === selectedInterval) || product.prices[0];
|
|
757
1219
|
const renderCard = (product) => {
|
|
758
1220
|
const displayedPrice = getDisplayedPrice(product);
|
|
759
|
-
return /* @__PURE__ */ (0,
|
|
1221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
760
1222
|
PricingCard,
|
|
761
1223
|
{
|
|
762
1224
|
product,
|
|
@@ -766,8 +1228,8 @@ function PricingTable({
|
|
|
766
1228
|
}
|
|
767
1229
|
);
|
|
768
1230
|
};
|
|
769
|
-
const desktopCarousel = /* @__PURE__ */ (0,
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
1231
|
+
const desktopCarousel = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative max-w-7xl mx-auto", children: [
|
|
1232
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
771
1233
|
Button,
|
|
772
1234
|
{
|
|
773
1235
|
variant: "ghost",
|
|
@@ -775,15 +1237,15 @@ function PricingTable({
|
|
|
775
1237
|
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",
|
|
776
1238
|
onClick: () => setCarouselIndex(Math.max(0, carouselIndex - 1)),
|
|
777
1239
|
disabled: carouselIndex === 0,
|
|
778
|
-
children: /* @__PURE__ */ (0,
|
|
1240
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react2.ChevronLeft, { className: "w-4 h-4" })
|
|
779
1241
|
}
|
|
780
1242
|
),
|
|
781
|
-
/* @__PURE__ */ (0,
|
|
1243
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
782
1244
|
"div",
|
|
783
1245
|
{
|
|
784
1246
|
className: "overflow-hidden mx-auto",
|
|
785
1247
|
style: { width: `${3 * CARD_WIDTH + 2 * GAP}px` },
|
|
786
|
-
children: /* @__PURE__ */ (0,
|
|
1248
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
787
1249
|
"div",
|
|
788
1250
|
{
|
|
789
1251
|
className: "flex items-stretch transition-transform duration-300 ease-in-out",
|
|
@@ -791,7 +1253,7 @@ function PricingTable({
|
|
|
791
1253
|
transform: `translateX(-${carouselIndex * (CARD_WIDTH + GAP)}px)`,
|
|
792
1254
|
gap: `${GAP}px`
|
|
793
1255
|
},
|
|
794
|
-
children: sortedProducts.map((p) => /* @__PURE__ */ (0,
|
|
1256
|
+
children: sortedProducts.map((p) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
795
1257
|
"div",
|
|
796
1258
|
{
|
|
797
1259
|
style: { width: `${CARD_WIDTH}px` },
|
|
@@ -804,7 +1266,7 @@ function PricingTable({
|
|
|
804
1266
|
)
|
|
805
1267
|
}
|
|
806
1268
|
),
|
|
807
|
-
/* @__PURE__ */ (0,
|
|
1269
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
808
1270
|
Button,
|
|
809
1271
|
{
|
|
810
1272
|
variant: "ghost",
|
|
@@ -814,12 +1276,12 @@ function PricingTable({
|
|
|
814
1276
|
Math.min(sortedProducts.length - 3, carouselIndex + 1)
|
|
815
1277
|
),
|
|
816
1278
|
disabled: carouselIndex >= sortedProducts.length - 3,
|
|
817
|
-
children: /* @__PURE__ */ (0,
|
|
1279
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react2.ChevronRight, { className: "w-4 h-4" })
|
|
818
1280
|
}
|
|
819
1281
|
),
|
|
820
|
-
/* @__PURE__ */ (0,
|
|
1282
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex justify-center mt-6 space-x-2", children: Array.from(
|
|
821
1283
|
{ length: Math.max(1, sortedProducts.length - 2) },
|
|
822
|
-
(_, i) => /* @__PURE__ */ (0,
|
|
1284
|
+
(_, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
823
1285
|
"button",
|
|
824
1286
|
{
|
|
825
1287
|
onClick: () => setCarouselIndex(i),
|
|
@@ -833,12 +1295,12 @@ function PricingTable({
|
|
|
833
1295
|
)
|
|
834
1296
|
) })
|
|
835
1297
|
] });
|
|
836
|
-
const staticLayout = /* @__PURE__ */ (0,
|
|
1298
|
+
const staticLayout = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
837
1299
|
"div",
|
|
838
1300
|
{
|
|
839
1301
|
className: "flex flex-row items-stretch justify-center",
|
|
840
1302
|
style: { gap: `${GAP}px` },
|
|
841
|
-
children: sortedProducts.map((p) => /* @__PURE__ */ (0,
|
|
1303
|
+
children: sortedProducts.map((p) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
842
1304
|
"div",
|
|
843
1305
|
{
|
|
844
1306
|
style: { width: `${CARD_WIDTH}px` },
|
|
@@ -849,9 +1311,9 @@ function PricingTable({
|
|
|
849
1311
|
))
|
|
850
1312
|
}
|
|
851
1313
|
);
|
|
852
|
-
return /* @__PURE__ */ (0,
|
|
853
|
-
showPricingToggle && hasMultipleIntervals && /* @__PURE__ */ (0,
|
|
854
|
-
/* @__PURE__ */ (0,
|
|
1314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn("w-full", className), children: [
|
|
1315
|
+
showPricingToggle && hasMultipleIntervals && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex bg-gray-100 p-1 rounded-lg", children: [
|
|
1316
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
855
1317
|
Button,
|
|
856
1318
|
{
|
|
857
1319
|
variant: selectedInterval === "month" ? "default" : "ghost",
|
|
@@ -861,7 +1323,7 @@ function PricingTable({
|
|
|
861
1323
|
children: "Monthly"
|
|
862
1324
|
}
|
|
863
1325
|
),
|
|
864
|
-
/* @__PURE__ */ (0,
|
|
1326
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
865
1327
|
Button,
|
|
866
1328
|
{
|
|
867
1329
|
variant: selectedInterval === "year" ? "default" : "ghost",
|
|
@@ -872,20 +1334,20 @@ function PricingTable({
|
|
|
872
1334
|
}
|
|
873
1335
|
)
|
|
874
1336
|
] }) }),
|
|
875
|
-
/* @__PURE__ */ (0,
|
|
876
|
-
/* @__PURE__ */ (0,
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "lg:hidden relative", children: [
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
877
1339
|
"div",
|
|
878
1340
|
{
|
|
879
1341
|
className: "overflow-hidden mx-auto",
|
|
880
1342
|
style: { width: `${CARD_WIDTH}px` },
|
|
881
|
-
children: /* @__PURE__ */ (0,
|
|
1343
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
882
1344
|
"div",
|
|
883
1345
|
{
|
|
884
1346
|
className: "flex transition-transform duration-300 ease-in-out items-stretch",
|
|
885
1347
|
style: {
|
|
886
1348
|
transform: `translateX(-${carouselIndex * CARD_WIDTH}px)`
|
|
887
1349
|
},
|
|
888
|
-
children: sortedProducts.map((product) => /* @__PURE__ */ (0,
|
|
1350
|
+
children: sortedProducts.map((product) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
889
1351
|
"div",
|
|
890
1352
|
{
|
|
891
1353
|
className: "flex-shrink-0",
|
|
@@ -898,8 +1360,8 @@ function PricingTable({
|
|
|
898
1360
|
)
|
|
899
1361
|
}
|
|
900
1362
|
),
|
|
901
|
-
sortedProducts.length > 1 && /* @__PURE__ */ (0,
|
|
902
|
-
/* @__PURE__ */ (0,
|
|
1363
|
+
sortedProducts.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
903
1365
|
Button,
|
|
904
1366
|
{
|
|
905
1367
|
variant: "ghost",
|
|
@@ -907,10 +1369,10 @@ function PricingTable({
|
|
|
907
1369
|
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",
|
|
908
1370
|
onClick: () => setCarouselIndex((prev) => Math.max(0, prev - 1)),
|
|
909
1371
|
disabled: carouselIndex === 0,
|
|
910
|
-
children: /* @__PURE__ */ (0,
|
|
1372
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react2.ChevronLeft, { className: "w-5 h-5" })
|
|
911
1373
|
}
|
|
912
1374
|
),
|
|
913
|
-
/* @__PURE__ */ (0,
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
914
1376
|
Button,
|
|
915
1377
|
{
|
|
916
1378
|
variant: "ghost",
|
|
@@ -920,10 +1382,10 @@ function PricingTable({
|
|
|
920
1382
|
(prev) => Math.min(sortedProducts.length - 1, prev + 1)
|
|
921
1383
|
),
|
|
922
1384
|
disabled: carouselIndex >= sortedProducts.length - 1,
|
|
923
|
-
children: /* @__PURE__ */ (0,
|
|
1385
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react2.ChevronRight, { className: "w-5 h-5" })
|
|
924
1386
|
}
|
|
925
1387
|
),
|
|
926
|
-
/* @__PURE__ */ (0,
|
|
1388
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex justify-center mt-6 space-x-2", children: Array.from({ length: sortedProducts.length }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
927
1389
|
"button",
|
|
928
1390
|
{
|
|
929
1391
|
onClick: () => setCarouselIndex(i),
|
|
@@ -937,20 +1399,20 @@ function PricingTable({
|
|
|
937
1399
|
)) })
|
|
938
1400
|
] })
|
|
939
1401
|
] }),
|
|
940
|
-
/* @__PURE__ */ (0,
|
|
1402
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "hidden lg:block", children: sortedProducts.length <= 3 ? staticLayout : desktopCarousel })
|
|
941
1403
|
] });
|
|
942
1404
|
}
|
|
943
1405
|
|
|
944
1406
|
// src/tenant-creator/index.tsx
|
|
945
1407
|
var import_react = require("react");
|
|
946
|
-
var
|
|
1408
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
947
1409
|
function TenantCreator({
|
|
948
1410
|
config = {},
|
|
949
1411
|
formActions = {},
|
|
950
1412
|
className
|
|
951
1413
|
}) {
|
|
952
1414
|
const [mode, setMode] = (0, import_react.useState)(
|
|
953
|
-
config.defaultMode || "create"
|
|
1415
|
+
!!config.joinForm?.token?.defaultValue === true ? "join" : config.defaultMode || "create"
|
|
954
1416
|
);
|
|
955
1417
|
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
956
1418
|
const [organizationName, setOrganizationName] = (0, import_react.useState)(
|
|
@@ -959,7 +1421,9 @@ function TenantCreator({
|
|
|
959
1421
|
const [billingEmail, setBillingEmail] = (0, import_react.useState)(
|
|
960
1422
|
config.createForm?.billingEmail?.defaultValue || ""
|
|
961
1423
|
);
|
|
962
|
-
const [token, setToken] = (0, import_react.useState)(
|
|
1424
|
+
const [token, setToken] = (0, import_react.useState)(
|
|
1425
|
+
config.joinForm?.token?.defaultValue || ""
|
|
1426
|
+
);
|
|
963
1427
|
(0, import_react.useEffect)(() => {
|
|
964
1428
|
const urlParams = new URLSearchParams(window.location.search);
|
|
965
1429
|
const inviteToken = urlParams.get("invite_token");
|
|
@@ -990,14 +1454,14 @@ function TenantCreator({
|
|
|
990
1454
|
setIsLoading(false);
|
|
991
1455
|
}
|
|
992
1456
|
};
|
|
993
|
-
return /* @__PURE__ */ (0,
|
|
994
|
-
/* @__PURE__ */ (0,
|
|
995
|
-
/* @__PURE__ */ (0,
|
|
996
|
-
/* @__PURE__ */ (0,
|
|
1457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Card, { className: cn("w-full max-w-md mx-auto", className), children: [
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(CardHeader, { children: [
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardTitle, { children: "Organization Setup" }),
|
|
1460
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardDescription, { children: "Choose how you want to get started with your organization." })
|
|
997
1461
|
] }),
|
|
998
|
-
/* @__PURE__ */ (0,
|
|
999
|
-
/* @__PURE__ */ (0,
|
|
1000
|
-
/* @__PURE__ */ (0,
|
|
1462
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(CardContent, { className: "space-y-6", children: [
|
|
1463
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid grid-cols-2 rounded-lg bg-muted p-1", children: [
|
|
1464
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
1001
1465
|
"label",
|
|
1002
1466
|
{
|
|
1003
1467
|
className: cn(
|
|
@@ -1006,7 +1470,7 @@ function TenantCreator({
|
|
|
1006
1470
|
isLoading && "pointer-events-none opacity-50"
|
|
1007
1471
|
),
|
|
1008
1472
|
children: [
|
|
1009
|
-
/* @__PURE__ */ (0,
|
|
1473
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1010
1474
|
"input",
|
|
1011
1475
|
{
|
|
1012
1476
|
type: "radio",
|
|
@@ -1022,7 +1486,7 @@ function TenantCreator({
|
|
|
1022
1486
|
]
|
|
1023
1487
|
}
|
|
1024
1488
|
),
|
|
1025
|
-
/* @__PURE__ */ (0,
|
|
1489
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
1026
1490
|
"label",
|
|
1027
1491
|
{
|
|
1028
1492
|
className: cn(
|
|
@@ -1031,7 +1495,7 @@ function TenantCreator({
|
|
|
1031
1495
|
isLoading && "pointer-events-none opacity-50"
|
|
1032
1496
|
),
|
|
1033
1497
|
children: [
|
|
1034
|
-
/* @__PURE__ */ (0,
|
|
1498
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1035
1499
|
"input",
|
|
1036
1500
|
{
|
|
1037
1501
|
type: "radio",
|
|
@@ -1048,10 +1512,10 @@ function TenantCreator({
|
|
|
1048
1512
|
}
|
|
1049
1513
|
)
|
|
1050
1514
|
] }),
|
|
1051
|
-
mode === "create" && /* @__PURE__ */ (0,
|
|
1052
|
-
/* @__PURE__ */ (0,
|
|
1053
|
-
/* @__PURE__ */ (0,
|
|
1054
|
-
/* @__PURE__ */ (0,
|
|
1515
|
+
mode === "create" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("form", { onSubmit: handleCreateSubmit, className: "space-y-4", children: [
|
|
1516
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-2", children: [
|
|
1517
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Label, { htmlFor: "organizationName", children: config.createForm?.organizationName?.label || "Organization Name" }),
|
|
1518
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1055
1519
|
Input,
|
|
1056
1520
|
{
|
|
1057
1521
|
id: "organizationName",
|
|
@@ -1065,9 +1529,9 @@ function TenantCreator({
|
|
|
1065
1529
|
}
|
|
1066
1530
|
)
|
|
1067
1531
|
] }),
|
|
1068
|
-
/* @__PURE__ */ (0,
|
|
1069
|
-
/* @__PURE__ */ (0,
|
|
1070
|
-
/* @__PURE__ */ (0,
|
|
1532
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-2", children: [
|
|
1533
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Label, { htmlFor: "billingEmail", children: config.createForm?.billingEmail?.label || "Billing Email" }),
|
|
1534
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1071
1535
|
Input,
|
|
1072
1536
|
{
|
|
1073
1537
|
id: "billingEmail",
|
|
@@ -1081,12 +1545,12 @@ function TenantCreator({
|
|
|
1081
1545
|
}
|
|
1082
1546
|
)
|
|
1083
1547
|
] }),
|
|
1084
|
-
/* @__PURE__ */ (0,
|
|
1548
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? "Creating..." : "Create Organization" })
|
|
1085
1549
|
] }),
|
|
1086
|
-
mode === "join" && /* @__PURE__ */ (0,
|
|
1087
|
-
/* @__PURE__ */ (0,
|
|
1088
|
-
/* @__PURE__ */ (0,
|
|
1089
|
-
/* @__PURE__ */ (0,
|
|
1550
|
+
mode === "join" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("form", { onSubmit: handleJoinSubmit, className: "space-y-4", children: [
|
|
1551
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-2", children: [
|
|
1552
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Label, { htmlFor: "token", children: config.joinForm?.token?.label || "Invitation Token" }),
|
|
1553
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1090
1554
|
Input,
|
|
1091
1555
|
{
|
|
1092
1556
|
id: "token",
|
|
@@ -1100,15 +1564,477 @@ function TenantCreator({
|
|
|
1100
1564
|
}
|
|
1101
1565
|
)
|
|
1102
1566
|
] }),
|
|
1103
|
-
/* @__PURE__ */ (0,
|
|
1567
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? "Joining..." : "Join Organization" })
|
|
1568
|
+
] })
|
|
1569
|
+
] })
|
|
1570
|
+
] });
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
// src/user-invite/index.tsx
|
|
1574
|
+
var import_react2 = require("react");
|
|
1575
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1576
|
+
function UserInvite({ roles, onInvite }) {
|
|
1577
|
+
const [email, setEmail] = (0, import_react2.useState)("");
|
|
1578
|
+
const [selectedRole, setSelectedRole] = (0, import_react2.useState)("");
|
|
1579
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
|
|
1580
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
1581
|
+
const isValidEmail = (email2) => {
|
|
1582
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1583
|
+
return emailRegex.test(email2);
|
|
1584
|
+
};
|
|
1585
|
+
const isFormValid = () => {
|
|
1586
|
+
return email.trim() !== "" && isValidEmail(email) && selectedRole !== "";
|
|
1587
|
+
};
|
|
1588
|
+
const handleSubmit = async (e) => {
|
|
1589
|
+
e.preventDefault();
|
|
1590
|
+
setError(null);
|
|
1591
|
+
if (!isFormValid()) {
|
|
1592
|
+
setError("Please fill in all fields with valid data");
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
setIsSubmitting(true);
|
|
1596
|
+
try {
|
|
1597
|
+
const inviteData = {
|
|
1598
|
+
email: email.trim(),
|
|
1599
|
+
role: selectedRole
|
|
1600
|
+
};
|
|
1601
|
+
await onInvite?.(inviteData);
|
|
1602
|
+
setEmail("");
|
|
1603
|
+
setSelectedRole("");
|
|
1604
|
+
} catch (err) {
|
|
1605
|
+
setError(
|
|
1606
|
+
err instanceof Error ? err.message : "Failed to send invitation"
|
|
1607
|
+
);
|
|
1608
|
+
} finally {
|
|
1609
|
+
setIsSubmitting(false);
|
|
1610
|
+
}
|
|
1611
|
+
};
|
|
1612
|
+
const handleReset = () => {
|
|
1613
|
+
setEmail("");
|
|
1614
|
+
setSelectedRole("");
|
|
1615
|
+
setError(null);
|
|
1616
|
+
};
|
|
1617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Card, { className: "w-full max-w-2xl", children: [
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardHeader, { children: [
|
|
1619
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CardTitle, { children: "Invite User" }),
|
|
1620
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CardDescription, { children: "Send an invitation to a new user to join your organization" })
|
|
1621
|
+
] }),
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-6", children: [
|
|
1623
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-2", children: [
|
|
1624
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Label, { htmlFor: "email", children: "Email Address" }),
|
|
1625
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1626
|
+
Input,
|
|
1627
|
+
{
|
|
1628
|
+
id: "email",
|
|
1629
|
+
type: "email",
|
|
1630
|
+
placeholder: "colleague@company.com",
|
|
1631
|
+
value: email,
|
|
1632
|
+
onChange: (e) => setEmail(e.target.value),
|
|
1633
|
+
"aria-invalid": email !== "" && !isValidEmail(email)
|
|
1634
|
+
}
|
|
1635
|
+
),
|
|
1636
|
+
email !== "" && !isValidEmail(email) && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-xs text-destructive", children: "Please enter a valid email address" })
|
|
1637
|
+
] }),
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-2", children: [
|
|
1639
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Label, { htmlFor: "role", children: "Role" }),
|
|
1640
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Select, { value: selectedRole, onValueChange: setSelectedRole, children: [
|
|
1641
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectTrigger, { id: "role", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectValue, { placeholder: "Select a role" }) }),
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectContent, { children: roles.length > 0 ? roles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectItem, { value: role, children: role }, role)) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectItem, { value: "no-roles", disabled: true, children: "No roles available" }) })
|
|
1643
|
+
] }),
|
|
1644
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-xs text-muted-foreground", children: "The role determines what permissions the user will have" })
|
|
1645
|
+
] }),
|
|
1646
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "p-3 rounded-md bg-destructive/10 border border-destructive/20", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-sm text-destructive", children: error }) }),
|
|
1647
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex justify-end space-x-3", children: [
|
|
1648
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1649
|
+
Button,
|
|
1650
|
+
{
|
|
1651
|
+
type: "button",
|
|
1652
|
+
variant: "outline",
|
|
1653
|
+
onClick: handleReset,
|
|
1654
|
+
disabled: isSubmitting,
|
|
1655
|
+
children: "Reset"
|
|
1656
|
+
}
|
|
1657
|
+
),
|
|
1658
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Button, { type: "submit", disabled: !isFormValid() || isSubmitting, children: isSubmitting ? "Sending..." : "Send Invitation" })
|
|
1659
|
+
] })
|
|
1660
|
+
] }) })
|
|
1661
|
+
] });
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
// src/role-creator/index.tsx
|
|
1665
|
+
var import_react3 = require("react");
|
|
1666
|
+
|
|
1667
|
+
// src/components/ui/checkbox.tsx
|
|
1668
|
+
var React14 = require("react");
|
|
1669
|
+
var CheckboxPrimitive = __toESM(require("@radix-ui/react-checkbox"), 1);
|
|
1670
|
+
var import_lucide_react3 = require("lucide-react");
|
|
1671
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1672
|
+
function Checkbox({
|
|
1673
|
+
className,
|
|
1674
|
+
...props
|
|
1675
|
+
}) {
|
|
1676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1677
|
+
CheckboxPrimitive.Root,
|
|
1678
|
+
{
|
|
1679
|
+
"data-slot": "checkbox",
|
|
1680
|
+
className: cn(
|
|
1681
|
+
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
|
1682
|
+
className
|
|
1683
|
+
),
|
|
1684
|
+
...props,
|
|
1685
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1686
|
+
CheckboxPrimitive.Indicator,
|
|
1687
|
+
{
|
|
1688
|
+
"data-slot": "checkbox-indicator",
|
|
1689
|
+
className: "grid place-content-center text-current transition-none",
|
|
1690
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react3.CheckIcon, { className: "size-3.5" })
|
|
1691
|
+
}
|
|
1692
|
+
)
|
|
1693
|
+
}
|
|
1694
|
+
);
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
// src/components/ui/separator.tsx
|
|
1698
|
+
var React15 = require("react");
|
|
1699
|
+
var SeparatorPrimitive = __toESM(require("@radix-ui/react-separator"), 1);
|
|
1700
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1701
|
+
function Separator2({
|
|
1702
|
+
className,
|
|
1703
|
+
orientation = "horizontal",
|
|
1704
|
+
decorative = true,
|
|
1705
|
+
...props
|
|
1706
|
+
}) {
|
|
1707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1708
|
+
SeparatorPrimitive.Root,
|
|
1709
|
+
{
|
|
1710
|
+
"data-slot": "separator",
|
|
1711
|
+
decorative,
|
|
1712
|
+
orientation,
|
|
1713
|
+
className: cn(
|
|
1714
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
1715
|
+
className
|
|
1716
|
+
),
|
|
1717
|
+
...props
|
|
1718
|
+
}
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// src/role-creator/index.tsx
|
|
1723
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1724
|
+
function RoleCreator({
|
|
1725
|
+
definitions,
|
|
1726
|
+
roles,
|
|
1727
|
+
namespaceMap = {},
|
|
1728
|
+
onRoleCreate,
|
|
1729
|
+
onRoleUpdate
|
|
1730
|
+
}) {
|
|
1731
|
+
const [roleName, setRoleName] = (0, import_react3.useState)("");
|
|
1732
|
+
const [selectedPermissions, setSelectedPermissions] = (0, import_react3.useState)(
|
|
1733
|
+
/* @__PURE__ */ new Set()
|
|
1734
|
+
);
|
|
1735
|
+
const [showSuggestions, setShowSuggestions] = (0, import_react3.useState)(false);
|
|
1736
|
+
const [isEditMode, setIsEditMode] = (0, import_react3.useState)(false);
|
|
1737
|
+
const [editingRoleId, setEditingRoleId] = (0, import_react3.useState)(null);
|
|
1738
|
+
const { tenantNamespace, fineGrainedNamespaces } = (0, import_react3.useMemo)(() => {
|
|
1739
|
+
const tenant = definitions.find(
|
|
1740
|
+
(def) => def.namespace.toLowerCase() === "tenant"
|
|
1741
|
+
);
|
|
1742
|
+
const fineGrained = definitions.filter(
|
|
1743
|
+
(def) => def.namespace.toLowerCase() !== "tenant"
|
|
1744
|
+
);
|
|
1745
|
+
return {
|
|
1746
|
+
tenantNamespace: tenant,
|
|
1747
|
+
fineGrainedNamespaces: fineGrained
|
|
1748
|
+
};
|
|
1749
|
+
}, [definitions]);
|
|
1750
|
+
const roleSuggestions = (0, import_react3.useMemo)(() => {
|
|
1751
|
+
return roles.map((role) => role.role_name);
|
|
1752
|
+
}, [roles]);
|
|
1753
|
+
const handleRoleNameChange = (value) => {
|
|
1754
|
+
setRoleName(value);
|
|
1755
|
+
const existingRole = roles.find(
|
|
1756
|
+
(role) => role.role_name.toLowerCase() === value.toLowerCase()
|
|
1757
|
+
);
|
|
1758
|
+
if (existingRole) {
|
|
1759
|
+
setIsEditMode(true);
|
|
1760
|
+
setEditingRoleId(existingRole.id);
|
|
1761
|
+
const permissions = /* @__PURE__ */ new Set();
|
|
1762
|
+
existingRole.permissions.forEach((perm) => {
|
|
1763
|
+
permissions.add(perm);
|
|
1764
|
+
});
|
|
1765
|
+
setSelectedPermissions(permissions);
|
|
1766
|
+
} else {
|
|
1767
|
+
setIsEditMode(false);
|
|
1768
|
+
setEditingRoleId(null);
|
|
1769
|
+
}
|
|
1770
|
+
};
|
|
1771
|
+
const buildPermissionString = (namespace, relation, resourceId) => {
|
|
1772
|
+
if (resourceId) {
|
|
1773
|
+
return `${namespace.toLowerCase()}:${resourceId}#${relation}`;
|
|
1774
|
+
}
|
|
1775
|
+
return `${namespace.toLowerCase()}#${relation}`;
|
|
1776
|
+
};
|
|
1777
|
+
const togglePermission = (permissionString) => {
|
|
1778
|
+
const newPermissions = new Set(selectedPermissions);
|
|
1779
|
+
if (newPermissions.has(permissionString)) {
|
|
1780
|
+
newPermissions.delete(permissionString);
|
|
1781
|
+
} else {
|
|
1782
|
+
newPermissions.add(permissionString);
|
|
1783
|
+
}
|
|
1784
|
+
setSelectedPermissions(newPermissions);
|
|
1785
|
+
};
|
|
1786
|
+
const handleSubmit = () => {
|
|
1787
|
+
if (!roleName.trim()) return;
|
|
1788
|
+
const permissionsArray = Array.from(selectedPermissions);
|
|
1789
|
+
if (isEditMode && editingRoleId) {
|
|
1790
|
+
onRoleUpdate?.({
|
|
1791
|
+
role_id: editingRoleId,
|
|
1792
|
+
role_name: roleName,
|
|
1793
|
+
permissions: permissionsArray
|
|
1794
|
+
});
|
|
1795
|
+
} else {
|
|
1796
|
+
onRoleCreate?.({
|
|
1797
|
+
role_name: roleName,
|
|
1798
|
+
permissions: permissionsArray
|
|
1799
|
+
});
|
|
1800
|
+
}
|
|
1801
|
+
};
|
|
1802
|
+
const handleReset = () => {
|
|
1803
|
+
setRoleName("");
|
|
1804
|
+
setSelectedPermissions(/* @__PURE__ */ new Set());
|
|
1805
|
+
setIsEditMode(false);
|
|
1806
|
+
setEditingRoleId(null);
|
|
1807
|
+
};
|
|
1808
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Card, { className: "w-full max-w-4xl", children: [
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardHeader, { children: [
|
|
1810
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CardTitle, { children: isEditMode ? `Edit Role: ${roleName}` : "Create New Role" }),
|
|
1811
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CardDescription, { children: isEditMode ? "Update permissions for this existing role" : "Define a new role with specific permissions" })
|
|
1812
|
+
] }),
|
|
1813
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardContent, { className: "space-y-6", children: [
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-2 relative", children: [
|
|
1815
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Label, { htmlFor: "role-name", children: "Role Name" }),
|
|
1816
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1817
|
+
Input,
|
|
1818
|
+
{
|
|
1819
|
+
id: "role-name",
|
|
1820
|
+
placeholder: "Enter role name (e.g., admin, developer, viewer)",
|
|
1821
|
+
value: roleName,
|
|
1822
|
+
onChange: (e) => handleRoleNameChange(e.target.value),
|
|
1823
|
+
onFocus: () => setShowSuggestions(true),
|
|
1824
|
+
onBlur: () => setTimeout(() => setShowSuggestions(false), 200)
|
|
1825
|
+
}
|
|
1826
|
+
),
|
|
1827
|
+
showSuggestions && roleSuggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "absolute z-10 w-full mt-1 bg-background border rounded-md shadow-lg max-h-48 overflow-y-auto", children: roleSuggestions.filter(
|
|
1828
|
+
(suggestion) => suggestion.toLowerCase().includes(roleName.toLowerCase())
|
|
1829
|
+
).map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1830
|
+
"button",
|
|
1831
|
+
{
|
|
1832
|
+
className: "w-full px-4 py-2 text-left hover:bg-accent hover:text-accent-foreground text-sm",
|
|
1833
|
+
onMouseDown: () => {
|
|
1834
|
+
handleRoleNameChange(suggestion);
|
|
1835
|
+
setShowSuggestions(false);
|
|
1836
|
+
},
|
|
1837
|
+
children: suggestion
|
|
1838
|
+
},
|
|
1839
|
+
suggestion
|
|
1840
|
+
)) }),
|
|
1841
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-xs text-amber-600 dark:text-amber-400", children: "\u26A0 Editing existing role - changes will update all users with this role" })
|
|
1842
|
+
] }),
|
|
1843
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Separator2, {}),
|
|
1844
|
+
tenantNamespace && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-4", children: [
|
|
1845
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
|
|
1846
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "text-lg font-semibold", children: "Organization Permissions" }),
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm text-muted-foreground", children: "Tenant-wide permissions that apply across the entire organization" })
|
|
1848
|
+
] }),
|
|
1849
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 pl-4", children: tenantNamespace.relations.map((relation) => {
|
|
1850
|
+
const permissionString = buildPermissionString(
|
|
1851
|
+
tenantNamespace.namespace,
|
|
1852
|
+
relation
|
|
1853
|
+
);
|
|
1854
|
+
const isChecked = selectedPermissions.has(permissionString);
|
|
1855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1856
|
+
"div",
|
|
1857
|
+
{
|
|
1858
|
+
className: "flex items-center space-x-2",
|
|
1859
|
+
children: [
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1861
|
+
Checkbox,
|
|
1862
|
+
{
|
|
1863
|
+
id: permissionString,
|
|
1864
|
+
checked: isChecked,
|
|
1865
|
+
onCheckedChange: () => togglePermission(permissionString)
|
|
1866
|
+
}
|
|
1867
|
+
),
|
|
1868
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1869
|
+
Label,
|
|
1870
|
+
{
|
|
1871
|
+
htmlFor: permissionString,
|
|
1872
|
+
className: "text-sm font-normal cursor-pointer",
|
|
1873
|
+
children: relation.replace(/_/g, " ")
|
|
1874
|
+
}
|
|
1875
|
+
)
|
|
1876
|
+
]
|
|
1877
|
+
},
|
|
1878
|
+
permissionString
|
|
1879
|
+
);
|
|
1880
|
+
}) })
|
|
1881
|
+
] }),
|
|
1882
|
+
fineGrainedNamespaces.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
1883
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Separator2, {}),
|
|
1884
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-6", children: [
|
|
1885
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
|
|
1886
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "text-lg font-semibold", children: "Fine-Grained Permissions" }),
|
|
1887
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm text-muted-foreground", children: "Resource-specific permissions that require an object ID" })
|
|
1888
|
+
] }),
|
|
1889
|
+
fineGrainedNamespaces.map((namespace) => {
|
|
1890
|
+
const namespaceLower = namespace.namespace.toLowerCase();
|
|
1891
|
+
const resourceMap = namespaceMap[namespaceLower] || [];
|
|
1892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "pl-4", children: [
|
|
1893
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h4", { className: "text-md font-medium capitalize", children: namespace.namespace }),
|
|
1894
|
+
resourceMap.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mt-4 space-y-6", children: resourceMap.map((resource) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1895
|
+
"div",
|
|
1896
|
+
{
|
|
1897
|
+
className: "border rounded-lg p-4 space-y-3 bg-muted/30",
|
|
1898
|
+
children: [
|
|
1899
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1900
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium text-sm", children: resource.label }),
|
|
1901
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground font-mono", children: resource.id })
|
|
1902
|
+
] }),
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: namespace.relations.map((relation) => {
|
|
1904
|
+
const permissionString = buildPermissionString(
|
|
1905
|
+
namespace.namespace,
|
|
1906
|
+
relation,
|
|
1907
|
+
resource.id
|
|
1908
|
+
);
|
|
1909
|
+
const isChecked = selectedPermissions.has(permissionString);
|
|
1910
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1911
|
+
"div",
|
|
1912
|
+
{
|
|
1913
|
+
className: "flex items-center space-x-2",
|
|
1914
|
+
children: [
|
|
1915
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1916
|
+
Checkbox,
|
|
1917
|
+
{
|
|
1918
|
+
id: permissionString,
|
|
1919
|
+
checked: isChecked,
|
|
1920
|
+
onCheckedChange: () => togglePermission(permissionString)
|
|
1921
|
+
}
|
|
1922
|
+
),
|
|
1923
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1924
|
+
Label,
|
|
1925
|
+
{
|
|
1926
|
+
htmlFor: permissionString,
|
|
1927
|
+
className: "text-sm font-normal cursor-pointer",
|
|
1928
|
+
children: relation.replace(/_/g, " ")
|
|
1929
|
+
}
|
|
1930
|
+
)
|
|
1931
|
+
]
|
|
1932
|
+
},
|
|
1933
|
+
permissionString
|
|
1934
|
+
);
|
|
1935
|
+
}) })
|
|
1936
|
+
]
|
|
1937
|
+
},
|
|
1938
|
+
resource.id
|
|
1939
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mt-3 p-4 border-2 border-dashed rounded-lg text-center", children: [
|
|
1940
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { className: "text-sm text-muted-foreground", children: [
|
|
1941
|
+
"No ",
|
|
1942
|
+
namespace.namespace.toLowerCase(),
|
|
1943
|
+
" resources available"
|
|
1944
|
+
] }),
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
1946
|
+
"Use wildcard permissions (e.g., ",
|
|
1947
|
+
namespaceLower,
|
|
1948
|
+
":*#permission) for all resources"
|
|
1949
|
+
] })
|
|
1950
|
+
] }),
|
|
1951
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mt-4 space-y-2", children: [
|
|
1952
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Label, { className: "text-sm font-medium", children: [
|
|
1953
|
+
"Wildcard Permissions (All ",
|
|
1954
|
+
namespace.namespace,
|
|
1955
|
+
"s)"
|
|
1956
|
+
] }),
|
|
1957
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: namespace.relations.map((relation) => {
|
|
1958
|
+
const permissionString = buildPermissionString(
|
|
1959
|
+
namespace.namespace,
|
|
1960
|
+
relation,
|
|
1961
|
+
"*"
|
|
1962
|
+
);
|
|
1963
|
+
const isChecked = selectedPermissions.has(permissionString);
|
|
1964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1965
|
+
"div",
|
|
1966
|
+
{
|
|
1967
|
+
className: "flex items-center space-x-2",
|
|
1968
|
+
children: [
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1970
|
+
Checkbox,
|
|
1971
|
+
{
|
|
1972
|
+
id: permissionString,
|
|
1973
|
+
checked: isChecked,
|
|
1974
|
+
onCheckedChange: () => togglePermission(permissionString)
|
|
1975
|
+
}
|
|
1976
|
+
),
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1978
|
+
Label,
|
|
1979
|
+
{
|
|
1980
|
+
htmlFor: permissionString,
|
|
1981
|
+
className: "text-sm font-normal cursor-pointer",
|
|
1982
|
+
children: [
|
|
1983
|
+
relation.replace(/_/g, " "),
|
|
1984
|
+
" (all)"
|
|
1985
|
+
]
|
|
1986
|
+
}
|
|
1987
|
+
)
|
|
1988
|
+
]
|
|
1989
|
+
},
|
|
1990
|
+
permissionString
|
|
1991
|
+
);
|
|
1992
|
+
}) })
|
|
1993
|
+
] })
|
|
1994
|
+
] }) }, namespace.id);
|
|
1995
|
+
})
|
|
1996
|
+
] })
|
|
1997
|
+
] }),
|
|
1998
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Separator2, {}),
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-2", children: [
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Label, { className: "text-sm font-medium", children: [
|
|
2001
|
+
"Selected Permissions (",
|
|
2002
|
+
selectedPermissions.size,
|
|
2003
|
+
")"
|
|
2004
|
+
] }),
|
|
2005
|
+
selectedPermissions.size > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "p-4 bg-muted rounded-md max-h-40 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "space-y-1 text-xs font-mono", children: Array.from(selectedPermissions).map((perm) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { className: "text-muted-foreground", children: perm }, perm)) }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm text-muted-foreground italic", children: "No permissions selected" })
|
|
2006
|
+
] }),
|
|
2007
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-end space-x-3", children: [
|
|
2008
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { variant: "outline", onClick: handleReset, children: "Reset" }),
|
|
2009
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2010
|
+
Button,
|
|
2011
|
+
{
|
|
2012
|
+
onClick: handleSubmit,
|
|
2013
|
+
disabled: !roleName.trim() || selectedPermissions.size === 0,
|
|
2014
|
+
children: isEditMode ? "Update Role" : "Create Role"
|
|
2015
|
+
}
|
|
2016
|
+
)
|
|
1104
2017
|
] })
|
|
1105
2018
|
] })
|
|
1106
2019
|
] });
|
|
1107
2020
|
}
|
|
1108
2021
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1109
2022
|
0 && (module.exports = {
|
|
1110
|
-
|
|
2023
|
+
LoginForm,
|
|
1111
2024
|
PricingTable,
|
|
2025
|
+
RecoveryForm,
|
|
2026
|
+
RegistrationForm,
|
|
2027
|
+
RoleCreator,
|
|
2028
|
+
SettingsForm,
|
|
1112
2029
|
SwitchActiveTenant,
|
|
1113
|
-
TenantCreator
|
|
2030
|
+
TenantCreator,
|
|
2031
|
+
UserInvite,
|
|
2032
|
+
VerificationForm,
|
|
2033
|
+
filterInputNodes,
|
|
2034
|
+
findAnchorNode,
|
|
2035
|
+
findCsrfToken,
|
|
2036
|
+
findSubmitButton,
|
|
2037
|
+
groupNodesByGroup,
|
|
2038
|
+
isUiNodeInputAttributes,
|
|
2039
|
+
sortNodes
|
|
1114
2040
|
});
|