@owlmeans/web-panel 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -1160
- package/build/@/components/ui/alert.d.ts +10 -0
- package/build/@/components/ui/alert.d.ts.map +1 -0
- package/build/@/components/ui/alert.js +26 -0
- package/build/@/components/ui/alert.js.map +1 -0
- package/build/@/components/ui/button.d.ts +11 -0
- package/build/@/components/ui/button.d.ts.map +1 -0
- package/build/@/components/ui/button.js +32 -0
- package/build/@/components/ui/button.js.map +1 -0
- package/build/@/components/ui/card.d.ts +10 -0
- package/build/@/components/ui/card.d.ts.map +1 -0
- package/build/@/components/ui/card.js +25 -0
- package/build/@/components/ui/card.js.map +1 -0
- package/build/@/components/ui/input.d.ts +4 -0
- package/build/@/components/ui/input.d.ts.map +1 -0
- package/build/@/components/ui/input.js +7 -0
- package/build/@/components/ui/input.js.map +1 -0
- package/build/@/components/ui/label.d.ts +5 -0
- package/build/@/components/ui/label.d.ts.map +1 -0
- package/build/@/components/ui/label.js +8 -0
- package/build/@/components/ui/label.js.map +1 -0
- package/build/@/components/ui/progress.d.ts +5 -0
- package/build/@/components/ui/progress.d.ts.map +1 -0
- package/build/@/components/ui/progress.js +11 -0
- package/build/@/components/ui/progress.js.map +1 -0
- package/build/@/components/ui/separator.d.ts +5 -0
- package/build/@/components/ui/separator.d.ts.map +1 -0
- package/build/@/components/ui/separator.js +8 -0
- package/build/@/components/ui/separator.js.map +1 -0
- package/build/@/lib/utils.d.ts +3 -0
- package/build/@/lib/utils.d.ts.map +1 -0
- package/build/@/lib/utils.js +6 -0
- package/build/@/lib/utils.js.map +1 -0
- package/build/auth/exports.d.ts +4 -4
- package/build/auth/exports.d.ts.map +1 -1
- package/build/auth/exports.js +2 -2
- package/build/auth/exports.js.map +1 -1
- package/build/auth/modules.d.ts +1 -1
- package/build/auth/modules.d.ts.map +1 -1
- package/build/auth/plugins/basic-ed25519.js +2 -2
- package/build/auth/plugins/basic-ed25519.js.map +1 -1
- package/build/auth/plugins/re-captcha.d.ts.map +1 -1
- package/build/auth/plugins/re-captcha.js +4 -12
- package/build/auth/plugins/re-captcha.js.map +1 -1
- package/build/auth/plugins/tunnel-consumer.d.ts.map +1 -1
- package/build/auth/plugins/tunnel-consumer.js +28 -16
- package/build/auth/plugins/tunnel-consumer.js.map +1 -1
- package/build/components/block.d.ts.map +1 -1
- package/build/components/block.js +5 -8
- package/build/components/block.js.map +1 -1
- package/build/components/button/selector.d.ts.map +1 -1
- package/build/components/button/selector.js +1 -2
- package/build/components/button/selector.js.map +1 -1
- package/build/components/form/button/component.d.ts +1 -1
- package/build/components/form/button/component.d.ts.map +1 -1
- package/build/components/form/button/component.js +39 -8
- package/build/components/form/button/component.js.map +1 -1
- package/build/components/form/component.d.ts.map +1 -1
- package/build/components/form/component.js +10 -13
- package/build/components/form/component.js.map +1 -1
- package/build/components/form/text/component.d.ts +1 -1
- package/build/components/form/text/component.d.ts.map +1 -1
- package/build/components/form/text/component.js +23 -24
- package/build/components/form/text/component.js.map +1 -1
- package/build/components/form/types.d.ts +3 -2
- package/build/components/form/types.d.ts.map +1 -1
- package/build/components/helper.d.ts +11 -2
- package/build/components/helper.d.ts.map +1 -1
- package/build/components/helper.js +50 -40
- package/build/components/helper.js.map +1 -1
- package/build/components/layout/component.d.ts.map +1 -1
- package/build/components/layout/component.js +2 -3
- package/build/components/layout/component.js.map +1 -1
- package/build/components/layout/types.d.ts +3 -1
- package/build/components/layout/types.d.ts.map +1 -1
- package/build/components/link.d.ts.map +1 -1
- package/build/components/link.js +6 -4
- package/build/components/link.js.map +1 -1
- package/build/components/panel-app/component.d.ts.map +1 -1
- package/build/components/panel-app/component.js +4 -7
- package/build/components/panel-app/component.js.map +1 -1
- package/build/components/panel-app/types.d.ts +6 -2
- package/build/components/panel-app/types.d.ts.map +1 -1
- package/build/components/status.d.ts.map +1 -1
- package/build/components/status.js +18 -7
- package/build/components/status.js.map +1 -1
- package/build/components/text.d.ts.map +1 -1
- package/build/components/text.js +26 -3
- package/build/components/text.js.map +1 -1
- package/build/components/types.d.ts +18 -10
- package/build/components/types.d.ts.map +1 -1
- package/build/components/uploader/image.d.ts.map +1 -1
- package/build/components/uploader/image.js +11 -19
- package/build/components/uploader/image.js.map +1 -1
- package/build/exports.d.ts +3 -3
- package/build/exports.d.ts.map +1 -1
- package/build/exports.js +2 -2
- package/build/exports.js.map +1 -1
- package/build/main.d.ts +4 -2
- package/build/main.d.ts.map +1 -1
- package/build/main.js +4 -4
- package/build/main.js.map +1 -1
- package/build/modules.d.ts +1 -1
- package/build/modules.d.ts.map +1 -1
- package/components.json +21 -0
- package/package.json +53 -34
- package/src/@/components/ui/alert.tsx +70 -0
- package/src/@/components/ui/button.tsx +60 -0
- package/src/@/components/ui/card.tsx +93 -0
- package/src/@/components/ui/input.tsx +22 -0
- package/src/@/components/ui/label.tsx +23 -0
- package/src/@/components/ui/progress.tsx +44 -0
- package/src/@/components/ui/separator.tsx +27 -0
- package/src/@/globals.css +64 -0
- package/src/@/lib/utils.ts +6 -0
- package/src/auth/exports.ts +4 -4
- package/src/auth/plugins/basic-ed25519.tsx +4 -4
- package/src/auth/plugins/re-captcha.tsx +14 -22
- package/src/auth/plugins/tunnel-consumer.tsx +32 -24
- package/src/components/block.tsx +10 -14
- package/src/components/button/selector.tsx +9 -9
- package/src/components/form/button/component.tsx +54 -14
- package/src/components/form/component.tsx +23 -24
- package/src/components/form/text/component.tsx +39 -30
- package/src/components/form/types.ts +4 -3
- package/src/components/helper.ts +56 -42
- package/src/components/layout/component.tsx +2 -3
- package/src/components/layout/types.ts +3 -1
- package/src/components/link.tsx +19 -9
- package/src/components/panel-app/component.tsx +5 -9
- package/src/components/panel-app/types.ts +6 -2
- package/src/components/status.tsx +20 -9
- package/src/components/text.tsx +28 -9
- package/src/components/types.ts +22 -10
- package/src/components/uploader/image.tsx +23 -23
- package/src/exports.ts +3 -3
- package/src/main.tsx +8 -5
- package/tests/smoke.spec.ts +24 -0
- package/tsconfig.json +9 -11
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// shadcn card — sourced from shadcn (new-york) 2026-05-23
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
|
|
6
|
+
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
data-slot="card"
|
|
10
|
+
className={cn(
|
|
11
|
+
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
12
|
+
className
|
|
13
|
+
)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
data-slot="card-header"
|
|
23
|
+
className={cn(
|
|
24
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
33
|
+
return (
|
|
34
|
+
<div
|
|
35
|
+
data-slot="card-title"
|
|
36
|
+
className={cn("leading-none font-semibold", className)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
43
|
+
return (
|
|
44
|
+
<div
|
|
45
|
+
data-slot="card-description"
|
|
46
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
53
|
+
return (
|
|
54
|
+
<div
|
|
55
|
+
data-slot="card-action"
|
|
56
|
+
className={cn(
|
|
57
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
58
|
+
className
|
|
59
|
+
)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
data-slot="card-content"
|
|
69
|
+
className={cn("px-6", className)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
76
|
+
return (
|
|
77
|
+
<div
|
|
78
|
+
data-slot="card-footer"
|
|
79
|
+
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
Card,
|
|
87
|
+
CardHeader,
|
|
88
|
+
CardFooter,
|
|
89
|
+
CardTitle,
|
|
90
|
+
CardAction,
|
|
91
|
+
CardDescription,
|
|
92
|
+
CardContent,
|
|
93
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// shadcn input — sourced from shadcn (new-york) 2026-05-23
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
|
|
6
|
+
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
7
|
+
return (
|
|
8
|
+
<input
|
|
9
|
+
type={type}
|
|
10
|
+
data-slot="input"
|
|
11
|
+
className={cn(
|
|
12
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
13
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
14
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { Input }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// shadcn label — sourced from shadcn (new-york) 2026-05-23
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import * as LabelPrimitive from '@radix-ui/react-label'
|
|
4
|
+
|
|
5
|
+
import { cn } from '@/lib/utils'
|
|
6
|
+
|
|
7
|
+
function Label({
|
|
8
|
+
className,
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
11
|
+
return (
|
|
12
|
+
<LabelPrimitive.Root
|
|
13
|
+
data-slot="label"
|
|
14
|
+
className={cn(
|
|
15
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Label }
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// shadcn progress — sourced from shadcn (new-york) 2026-05-23
|
|
2
|
+
// Extended with `indeterminate` mode: when `value === undefined` (or not passed),
|
|
3
|
+
// the indicator animates left-to-right continuously via the
|
|
4
|
+
// `--animate-progress-indeterminate` token defined in globals.css.
|
|
5
|
+
import * as React from 'react'
|
|
6
|
+
import * as ProgressPrimitive from '@radix-ui/react-progress'
|
|
7
|
+
|
|
8
|
+
import { cn } from '@/lib/utils'
|
|
9
|
+
|
|
10
|
+
function Progress({
|
|
11
|
+
className,
|
|
12
|
+
value,
|
|
13
|
+
...props
|
|
14
|
+
}: React.ComponentProps<typeof ProgressPrimitive.Root>) {
|
|
15
|
+
const indeterminate = value == null
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<ProgressPrimitive.Root
|
|
19
|
+
data-slot="progress"
|
|
20
|
+
className={cn(
|
|
21
|
+
"bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
value={indeterminate ? undefined : value}
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
<ProgressPrimitive.Indicator
|
|
28
|
+
data-slot="progress-indicator"
|
|
29
|
+
data-state={indeterminate ? 'indeterminate' : 'determinate'}
|
|
30
|
+
className={cn(
|
|
31
|
+
"bg-primary h-full w-full flex-1 transition-all",
|
|
32
|
+
indeterminate && "absolute inset-y-0 left-0 w-1/3 animate-[progress-indeterminate_1.5s_linear_infinite]"
|
|
33
|
+
)}
|
|
34
|
+
style={
|
|
35
|
+
indeterminate
|
|
36
|
+
? undefined
|
|
37
|
+
: { transform: `translateX(-${100 - (value || 0)}%)` }
|
|
38
|
+
}
|
|
39
|
+
/>
|
|
40
|
+
</ProgressPrimitive.Root>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { Progress }
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// shadcn separator — sourced from shadcn (new-york) 2026-05-23
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import * as SeparatorPrimitive from '@radix-ui/react-separator'
|
|
4
|
+
|
|
5
|
+
import { cn } from '@/lib/utils'
|
|
6
|
+
|
|
7
|
+
function Separator({
|
|
8
|
+
className,
|
|
9
|
+
orientation = "horizontal",
|
|
10
|
+
decorative = true,
|
|
11
|
+
...props
|
|
12
|
+
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
|
13
|
+
return (
|
|
14
|
+
<SeparatorPrimitive.Root
|
|
15
|
+
data-slot="separator"
|
|
16
|
+
decorative={decorative}
|
|
17
|
+
orientation={orientation}
|
|
18
|
+
className={cn(
|
|
19
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { Separator }
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
@source "../..";
|
|
4
|
+
|
|
5
|
+
@theme {
|
|
6
|
+
--color-background: oklch(1 0 0);
|
|
7
|
+
--color-foreground: oklch(0.145 0 0);
|
|
8
|
+
|
|
9
|
+
--color-card: oklch(1 0 0);
|
|
10
|
+
--color-card-foreground: oklch(0.145 0 0);
|
|
11
|
+
|
|
12
|
+
--color-popover: oklch(1 0 0);
|
|
13
|
+
--color-popover-foreground: oklch(0.145 0 0);
|
|
14
|
+
|
|
15
|
+
--color-primary: oklch(0.205 0 0);
|
|
16
|
+
--color-primary-foreground: oklch(0.985 0 0);
|
|
17
|
+
|
|
18
|
+
--color-secondary: oklch(0.97 0 0);
|
|
19
|
+
--color-secondary-foreground: oklch(0.205 0 0);
|
|
20
|
+
|
|
21
|
+
--color-muted: oklch(0.97 0 0);
|
|
22
|
+
--color-muted-foreground: oklch(0.556 0 0);
|
|
23
|
+
|
|
24
|
+
--color-accent: oklch(0.97 0 0);
|
|
25
|
+
--color-accent-foreground: oklch(0.205 0 0);
|
|
26
|
+
|
|
27
|
+
--color-destructive: oklch(0.577 0.245 27.325);
|
|
28
|
+
--color-success: oklch(0.62 0.18 145);
|
|
29
|
+
|
|
30
|
+
--color-border: oklch(0.922 0 0);
|
|
31
|
+
--color-input: oklch(0.922 0 0);
|
|
32
|
+
--color-ring: oklch(0.708 0 0);
|
|
33
|
+
|
|
34
|
+
--radius: 0.625rem;
|
|
35
|
+
|
|
36
|
+
--animate-progress-indeterminate: progress-indeterminate 1.5s linear infinite;
|
|
37
|
+
|
|
38
|
+
@keyframes progress-indeterminate {
|
|
39
|
+
0% { transform: translateX(-100%); }
|
|
40
|
+
100% { transform: translateX(100%); }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.dark {
|
|
45
|
+
--color-background: oklch(0.145 0 0);
|
|
46
|
+
--color-foreground: oklch(0.985 0 0);
|
|
47
|
+
--color-card: oklch(0.205 0 0);
|
|
48
|
+
--color-card-foreground: oklch(0.985 0 0);
|
|
49
|
+
--color-popover: oklch(0.205 0 0);
|
|
50
|
+
--color-popover-foreground: oklch(0.985 0 0);
|
|
51
|
+
--color-primary: oklch(0.922 0 0);
|
|
52
|
+
--color-primary-foreground: oklch(0.205 0 0);
|
|
53
|
+
--color-secondary: oklch(0.269 0 0);
|
|
54
|
+
--color-secondary-foreground: oklch(0.985 0 0);
|
|
55
|
+
--color-muted: oklch(0.269 0 0);
|
|
56
|
+
--color-muted-foreground: oklch(0.708 0 0);
|
|
57
|
+
--color-accent: oklch(0.269 0 0);
|
|
58
|
+
--color-accent-foreground: oklch(0.985 0 0);
|
|
59
|
+
--color-destructive: oklch(0.704 0.191 22.216);
|
|
60
|
+
--color-success: oklch(0.7 0.18 145);
|
|
61
|
+
--color-border: oklch(1 0 0 / 10%);
|
|
62
|
+
--color-input: oklch(1 0 0 / 15%);
|
|
63
|
+
--color-ring: oklch(0.556 0 0);
|
|
64
|
+
}
|
package/src/auth/exports.ts
CHANGED
|
@@ -3,11 +3,11 @@ export { handler, useModule, useValue, useNavigate } from '@owlmeans/client'
|
|
|
3
3
|
export type { Navigator } from '@owlmeans/client'
|
|
4
4
|
export { config } from '@owlmeans/client-context'
|
|
5
5
|
export { service } from '@owlmeans/config'
|
|
6
|
-
export { guard, parent,
|
|
7
|
-
export type { AbstractRequest } from '@owlmeans/
|
|
6
|
+
export { guard, parent, EntrypointOutcome, clone } from '@owlmeans/entrypoint'
|
|
7
|
+
export type { AbstractRequest } from '@owlmeans/entrypoint'
|
|
8
8
|
export { addWebService } from '@owlmeans/client-config'
|
|
9
|
-
export {
|
|
10
|
-
export type {
|
|
9
|
+
export { entrypoint, elevate, provideRequest, stab } from '@owlmeans/client-entrypoint'
|
|
10
|
+
export type { ClientEntrypoint as Module, ClientRequest as Request } from '@owlmeans/client-entrypoint'
|
|
11
11
|
export { route as croute } from '@owlmeans/client-route'
|
|
12
12
|
export { route, frontend, RouteMethod } from '@owlmeans/route'
|
|
13
13
|
export type { ResolvedServiceRoute as ServiceRoute } from '@owlmeans/route'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Ed22519BasicAuthUIPluginForm as FormData } from '@owlmeans/client-panel/auth/plugins'
|
|
2
2
|
import type { AuthenticationControl, AuthenticationRenderer } from '@owlmeans/client-auth/manager'
|
|
3
3
|
import type { AppContext } from '../types.js'
|
|
4
|
-
import type {
|
|
4
|
+
import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
|
|
5
5
|
import type { AuthRequest } from '@owlmeans/auth-common'
|
|
6
6
|
|
|
7
7
|
import { Ed22519BasicAuthUIPluginFormSchema as Schema } from '@owlmeans/client-panel/auth/plugins'
|
|
@@ -9,7 +9,7 @@ import { AuthenticationStage, DISPATCHER } from '@owlmeans/auth'
|
|
|
9
9
|
import { Form } from '../../components/form/index.js'
|
|
10
10
|
import { TextInput } from '../../components/form/text/index.js'
|
|
11
11
|
import { useCallback } from 'react'
|
|
12
|
-
import
|
|
12
|
+
import { Progress } from '@/components/ui/progress'
|
|
13
13
|
import { BlockScaling } from '@owlmeans/client-panel'
|
|
14
14
|
import { useContext } from '@owlmeans/web-client'
|
|
15
15
|
|
|
@@ -24,7 +24,7 @@ export const Ed22519BasicAuthUIPlugin: AuthenticationRenderer = ({ type, stage,
|
|
|
24
24
|
name => <TextInput key={name} name={name} label />
|
|
25
25
|
)
|
|
26
26
|
default:
|
|
27
|
-
return <
|
|
27
|
+
return <Progress />
|
|
28
28
|
}
|
|
29
29
|
}, [stage])
|
|
30
30
|
|
|
@@ -46,7 +46,7 @@ const createSubmit = (context: AppContext, control: AuthenticationControl) => as
|
|
|
46
46
|
return
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const [url] = await context.module<
|
|
49
|
+
const [url] = await context.module<ClientEntrypoint<string, AuthRequest>>(DISPATCHER)
|
|
50
50
|
.call({ query: token })
|
|
51
51
|
|
|
52
52
|
control.setStage?.(control.stage = AuthenticationStage.Authenticated)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { AuthenticationControl, AuthenticationRenderer } from '@owlmeans/client-auth/manager'
|
|
2
2
|
|
|
3
|
-
import LinearProgress from '@mui/material/LinearProgress'
|
|
4
3
|
import { AuthenticationStage, AuthorizationError, CMOD_RECAPTCHA, DISPATCHER, GUEST_ID } from '@owlmeans/auth'
|
|
5
4
|
import { useValue } from '@owlmeans/client'
|
|
6
5
|
import { PLUGINS } from '@owlmeans/client-context'
|
|
@@ -8,9 +7,7 @@ import ReCAPTCHA from 'react-google-recaptcha'
|
|
|
8
7
|
import { useCallback, useState } from 'react'
|
|
9
8
|
import { PanelContext } from '@owlmeans/client-panel'
|
|
10
9
|
import { Text } from '../../components/text.js'
|
|
11
|
-
import
|
|
12
|
-
import Box from '@mui/material/Box'
|
|
13
|
-
import type { SxProps } from '@mui/material/styles'
|
|
10
|
+
import { Progress } from '@/components/ui/progress'
|
|
14
11
|
import type { AppContext, Module } from '@owlmeans/web-client'
|
|
15
12
|
import { useContext } from '@owlmeans/web-client'
|
|
16
13
|
import type { AuthRequest } from '@owlmeans/auth-common'
|
|
@@ -21,33 +18,28 @@ export const ReCaptchaAuthUIPlugin: AuthenticationRenderer = ({ stage, control }
|
|
|
21
18
|
const config = useValue(() => context.getConfigResource(PLUGINS).get(CMOD_RECAPTCHA), [])
|
|
22
19
|
const finish = useCallback(createFinish(context, control), [])
|
|
23
20
|
|
|
24
|
-
const style: SxProps = {
|
|
25
|
-
maxWidth: { xs: '100%', sm: '100%', md: '50%' }
|
|
26
|
-
}
|
|
27
|
-
const loadingStyle: SxProps = {
|
|
28
|
-
width: { xs: '100%', sm: '100%', md: '50%' }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
21
|
const content = () => {
|
|
32
22
|
switch (config?.value != null ? stage : null) {
|
|
33
23
|
case AuthenticationStage.Authenticate:
|
|
34
|
-
return
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
return (
|
|
25
|
+
<div className="flex flex-col items-center justify-center max-w-full md:max-w-[50%]">
|
|
26
|
+
<Text name="guideline" center />
|
|
27
|
+
<div className="pt-4">
|
|
28
|
+
<ReCAPTCHA sitekey={config?.value as string ?? ''} onChange={finish}
|
|
29
|
+
asyncScriptOnLoad={() => setLoading(false)} />
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
41
33
|
default:
|
|
42
|
-
return <
|
|
34
|
+
return <Progress className="w-full md:w-1/2" />
|
|
43
35
|
}
|
|
44
36
|
}
|
|
45
37
|
|
|
46
38
|
return <PanelContext ns="lib" prefix="re-captcha" resource="client-panel-auth">
|
|
47
|
-
<
|
|
39
|
+
<div className="flex flex-col items-center justify-center">
|
|
48
40
|
{content()}
|
|
49
|
-
{loading && <
|
|
50
|
-
</
|
|
41
|
+
{loading && <Progress className="w-full md:w-1/2" />}
|
|
42
|
+
</div>
|
|
51
43
|
</PanelContext>
|
|
52
44
|
}
|
|
53
45
|
|
|
@@ -1,21 +1,38 @@
|
|
|
1
|
-
import LinearProgress from '@mui/material/LinearProgress'
|
|
2
1
|
import { AuthenticationStage } from '@owlmeans/auth'
|
|
3
2
|
import type { RelyToken } from '@owlmeans/auth'
|
|
4
3
|
import type { TunnelAuthenticationRenderer } from '@owlmeans/client-auth/manager/plugins'
|
|
5
4
|
import { PinSchema } from '@owlmeans/client-auth/manager/plugins'
|
|
6
5
|
import { Form } from '../../components/form/component.js'
|
|
7
6
|
import { TextInput } from '../../components/form/text/component.js'
|
|
8
|
-
|
|
9
|
-
import { useMemo } from 'react'
|
|
7
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
10
8
|
import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope'
|
|
11
9
|
import { Block } from '../../components/block.js'
|
|
12
10
|
import { BlockScaling } from '@owlmeans/client-panel'
|
|
13
11
|
import { Status } from '../../components/status.js'
|
|
14
|
-
import type { SxProps } from '@mui/material/styles'
|
|
15
|
-
import { useTheme } from '@mui/material/styles'
|
|
16
12
|
import { Button } from '../../components/form/button/component.js'
|
|
17
13
|
import { QRCodeCanvas } from 'qrcode.react'
|
|
18
|
-
import
|
|
14
|
+
import { Progress } from '@/components/ui/progress'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Read a CSS variable from `:root` (consumer-owned theme). Falls back to
|
|
18
|
+
* a sane default if the variable is undefined.
|
|
19
|
+
*/
|
|
20
|
+
const readCssVar = (name: string, fallback: string): string => {
|
|
21
|
+
if (typeof window === 'undefined') return fallback
|
|
22
|
+
const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim()
|
|
23
|
+
return value !== '' ? value : fallback
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const useThemeColors = () => {
|
|
27
|
+
const [colors, setColors] = useState({ fg: '#000000', bg: '#ffffff' })
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
setColors({
|
|
30
|
+
fg: readCssVar('--color-primary', '#000000'),
|
|
31
|
+
bg: readCssVar('--color-card', '#ffffff'),
|
|
32
|
+
})
|
|
33
|
+
}, [])
|
|
34
|
+
return colors
|
|
35
|
+
}
|
|
19
36
|
|
|
20
37
|
export const TunnelConsumerUIPlugin: TunnelAuthenticationRenderer = ({ type, stage, control, params, submit }) => {
|
|
21
38
|
const rely = useMemo(() => {
|
|
@@ -28,38 +45,29 @@ export const TunnelConsumerUIPlugin: TunnelAuthenticationRenderer = ({ type, sta
|
|
|
28
45
|
).message()
|
|
29
46
|
}, [stage])
|
|
30
47
|
|
|
31
|
-
const
|
|
32
|
-
const prefix =
|
|
33
|
-
const i18n = { ns:
|
|
34
|
-
|
|
35
|
-
const loadingStyle: SxProps = {
|
|
36
|
-
width: { xs: '100%', sm: '100%', md: '50%' }
|
|
37
|
-
}
|
|
48
|
+
const { fg, bg } = useThemeColors()
|
|
49
|
+
const prefix = 'prefix' in params ? params.prefix as string : ''
|
|
50
|
+
const i18n = { ns: 'lib', resource: 'client-panel-auth' }
|
|
38
51
|
|
|
39
52
|
switch (stage) {
|
|
40
53
|
case AuthenticationStage.Authenticate:
|
|
41
54
|
return <Form decorate name={type} validation={PinSchema} onSubmit={submit} i18n={i18n}>
|
|
42
|
-
<
|
|
55
|
+
<div className="w-fit mx-auto">
|
|
43
56
|
{rely?.token != null && <QRCodeCanvas size={256}
|
|
44
|
-
value={`${prefix}${rely?.token ??
|
|
45
|
-
fgColor={
|
|
46
|
-
bgColor={
|
|
57
|
+
value={`${prefix}${rely?.token ?? ''}`}
|
|
58
|
+
fgColor={fg}
|
|
59
|
+
bgColor={bg}
|
|
47
60
|
/>}
|
|
48
|
-
</
|
|
49
|
-
{/* <Text>{rely?.token}</Text> */}
|
|
61
|
+
</div>
|
|
50
62
|
<TextInput name="pin" label hint />
|
|
51
63
|
</Form>
|
|
52
64
|
case AuthenticationStage.Error:
|
|
53
65
|
return <Block horizontal={BlockScaling.Half} i18n={i18n} Actions={() =>
|
|
54
|
-
// @TODO document reload looks a bit dirty - cause we can loose the flow
|
|
55
66
|
<Button label="reset" onClick={async () => { document.location.reload() }} />
|
|
56
|
-
// <Button label="reset" onClick={async () => {
|
|
57
|
-
// await control.updateStage(AuthenticationStage.Authenticate)
|
|
58
|
-
// }} />
|
|
59
67
|
}>
|
|
60
68
|
<Status error={control.error} ok={false} />
|
|
61
69
|
</Block>
|
|
62
70
|
}
|
|
63
71
|
|
|
64
|
-
return <
|
|
72
|
+
return <Progress className="w-full md:w-1/2" />
|
|
65
73
|
}
|
package/src/components/block.tsx
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
2
|
import type { FC } from 'react'
|
|
3
3
|
import type { BlockProps } from './types.js'
|
|
4
|
-
import Card from '@mui/material/Card'
|
|
5
|
-
import CardContent from '@mui/material/CardContent'
|
|
6
4
|
import { PanelContext, usePanelHelper } from '@owlmeans/client-panel'
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import CardActions from '@mui/material/CardActions'
|
|
5
|
+
import { Card, CardContent, CardFooter } from '@/components/ui/card'
|
|
6
|
+
import { cn } from '@/lib/utils'
|
|
10
7
|
import { scalingToStyles } from './helper.js'
|
|
11
8
|
|
|
12
|
-
export const Block: FC<BlockProps> = ({ children, horizontal, vertical, Actions, i18n,
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const style: SxProps = useMemo(() => scalingToStyles(horizontal, vertical, theme), [horizontal])
|
|
16
|
-
|
|
9
|
+
export const Block: FC<BlockProps> = ({ children, horizontal, vertical, Actions, i18n, className, style }) => {
|
|
10
|
+
const scaling = useMemo(() => scalingToStyles(horizontal, vertical), [horizontal, vertical])
|
|
17
11
|
const panelProps = { ...usePanelHelper(), ...i18n }
|
|
18
12
|
|
|
19
13
|
return <PanelContext {...panelProps}>
|
|
20
|
-
<Card
|
|
14
|
+
<Card className={cn(scaling, className)} style={style}>
|
|
21
15
|
<CardContent>{children}</CardContent>
|
|
22
|
-
{Actions != null &&
|
|
23
|
-
<
|
|
24
|
-
|
|
16
|
+
{Actions != null && (
|
|
17
|
+
<CardFooter className="flex flex-row justify-end gap-2 pr-4 pb-2">
|
|
18
|
+
<Actions />
|
|
19
|
+
</CardFooter>
|
|
20
|
+
)}
|
|
25
21
|
</Card>
|
|
26
22
|
</PanelContext>
|
|
27
23
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
import ButtonGroup from '@mui/material/ButtonGroup'
|
|
3
1
|
import type { FC } from 'react'
|
|
4
2
|
import type { SelectorProps } from './types.js'
|
|
5
3
|
import { Button } from '../form/button/component.js'
|
|
6
4
|
|
|
7
5
|
export const ButtonSelector: FC<SelectorProps> = ({ name, options, current, onSelect }) => {
|
|
8
6
|
const prefix = name != null ? `${name}.` : ''
|
|
9
|
-
return
|
|
10
|
-
|
|
11
|
-
option =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
return (
|
|
8
|
+
<div className="inline-flex rounded-md shadow-xs [&>button:not(:first-child)]:rounded-l-none [&>button:not(:last-child)]:rounded-r-none [&>button:not(:last-child)]:border-r-0">
|
|
9
|
+
{options.map(option =>
|
|
10
|
+
<Button key={option} label={`${prefix}${option}`}
|
|
11
|
+
onClick={() => onSelect?.(option)}
|
|
12
|
+
variant={current === option ? 'contained' : 'outlined'} />
|
|
13
|
+
)}
|
|
14
|
+
</div>
|
|
15
|
+
)
|
|
16
16
|
}
|
|
@@ -1,15 +1,48 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
2
|
import type { FC } from 'react'
|
|
3
3
|
import { memo } from 'react'
|
|
4
|
-
import type { ButtonProps, SubmitProps } from './types'
|
|
5
|
-
|
|
6
|
-
import MUIButton from '@mui/material/Button'
|
|
7
|
-
import CircularProgress from '@mui/material/CircularProgress'
|
|
8
|
-
|
|
4
|
+
import type { ButtonProps, SubmitProps } from './types.js'
|
|
9
5
|
import { useFormContext } from 'react-hook-form'
|
|
6
|
+
import { Loader2 } from 'lucide-react'
|
|
10
7
|
import { I18nProps, useCommonI18n, useI18nApp, useI18nLib } from '@owlmeans/client-i18n'
|
|
11
8
|
import { useContext } from '@owlmeans/client'
|
|
12
9
|
import { useFormI18n, usePanelHelper } from '@owlmeans/client-panel'
|
|
10
|
+
import { Button as UIButton } from '@/components/ui/button'
|
|
11
|
+
import { cn } from '@/lib/utils'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* MUI → shadcn variant mapping:
|
|
15
|
+
* contained → default
|
|
16
|
+
* outlined → outline
|
|
17
|
+
* text → ghost
|
|
18
|
+
* Any other value is forwarded as-is (shadcn variants: default, destructive,
|
|
19
|
+
* outline, secondary, ghost, link).
|
|
20
|
+
*/
|
|
21
|
+
const mapVariant = (v: string | undefined): 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' => {
|
|
22
|
+
switch (v) {
|
|
23
|
+
case undefined:
|
|
24
|
+
case 'contained': return 'default'
|
|
25
|
+
case 'outlined': return 'outline'
|
|
26
|
+
case 'text': return 'ghost'
|
|
27
|
+
case 'destructive':
|
|
28
|
+
case 'outline':
|
|
29
|
+
case 'secondary':
|
|
30
|
+
case 'ghost':
|
|
31
|
+
case 'link':
|
|
32
|
+
case 'default':
|
|
33
|
+
return v
|
|
34
|
+
default: return 'default'
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const mapSize = (s: ButtonProps['size']): 'sm' | 'default' | 'lg' => {
|
|
39
|
+
switch (s) {
|
|
40
|
+
case 'small': return 'sm'
|
|
41
|
+
case 'large': return 'lg'
|
|
42
|
+
case 'medium':
|
|
43
|
+
default: return 'default'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
13
46
|
|
|
14
47
|
export const Button: FC<ButtonProps> = memo(({ label, onClick, i18n, loader, size, fullWidth, variant = 'contained' }) => {
|
|
15
48
|
const context = useContext()
|
|
@@ -25,15 +58,22 @@ export const Button: FC<ButtonProps> = memo(({ label, onClick, i18n, loader, siz
|
|
|
25
58
|
defaultValue: appT(label, { defaultValue: libT(label) })
|
|
26
59
|
}), [i18n?.suppress, label])
|
|
27
60
|
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
? 20
|
|
31
|
-
: size === 'medium' ? 16 : 14
|
|
61
|
+
const disabled = loader != null && loader.opened === true
|
|
62
|
+
const showLoader = disabled
|
|
32
63
|
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
64
|
+
return (
|
|
65
|
+
<UIButton
|
|
66
|
+
type="button"
|
|
67
|
+
variant={mapVariant(variant)}
|
|
68
|
+
size={mapSize(size)}
|
|
69
|
+
disabled={disabled}
|
|
70
|
+
onClick={onClick}
|
|
71
|
+
className={cn(fullWidth && 'w-full')}
|
|
72
|
+
>
|
|
73
|
+
{showLoader && <Loader2 className="animate-spin" aria-hidden />}
|
|
74
|
+
{label}
|
|
75
|
+
</UIButton>
|
|
76
|
+
)
|
|
37
77
|
})
|
|
38
78
|
|
|
39
79
|
export const SubmitButton: FC<SubmitProps> = memo((props) => {
|
|
@@ -42,7 +82,7 @@ export const SubmitButton: FC<SubmitProps> = memo((props) => {
|
|
|
42
82
|
const t = useFormI18n()
|
|
43
83
|
|
|
44
84
|
label = label ?? 'submit'
|
|
45
|
-
const _i18n: I18nProps[
|
|
85
|
+
const _i18n: I18nProps['i18n'] = { ...i18n }
|
|
46
86
|
_i18n.suppress = true
|
|
47
87
|
|
|
48
88
|
return <Button {...props} label={t(label)} i18n={_i18n}
|