@zentauri-ui/zentauri-components 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/cli/props.json +437 -0
- package/cli/registry.json +9 -0
- package/dist/{chunk-NW5BSLR2.js → chunk-AARJLZXP.js} +6 -6
- package/dist/{chunk-NW5BSLR2.js.map → chunk-AARJLZXP.js.map} +1 -1
- package/dist/chunk-ATE5SCTR.mjs +39 -0
- package/dist/chunk-ATE5SCTR.mjs.map +1 -0
- package/dist/{chunk-YSQW56JX.mjs → chunk-BFHJF4MV.mjs} +4 -4
- package/dist/{chunk-YSQW56JX.mjs.map → chunk-BFHJF4MV.mjs.map} +1 -1
- package/dist/chunk-DIAA5VH4.mjs +64 -0
- package/dist/chunk-DIAA5VH4.mjs.map +1 -0
- package/dist/{chunk-DUH2YLH2.js → chunk-DSX6RUYI.js} +12 -12
- package/dist/{chunk-DUH2YLH2.js.map → chunk-DSX6RUYI.js.map} +1 -1
- package/dist/chunk-ENKXB2BA.js +19 -0
- package/dist/{chunk-YBKNXDZU.js.map → chunk-ENKXB2BA.js.map} +1 -1
- package/dist/chunk-EZNR7VLJ.js +65 -0
- package/dist/chunk-EZNR7VLJ.js.map +1 -0
- package/dist/chunk-H3BJOK22.js +74 -0
- package/dist/chunk-H3BJOK22.js.map +1 -0
- package/dist/{chunk-45ZHGDT2.mjs → chunk-JKKF5DCF.mjs} +3 -3
- package/dist/{chunk-45ZHGDT2.mjs.map → chunk-JKKF5DCF.mjs.map} +1 -1
- package/dist/chunk-PQ2XTY3M.js +44 -0
- package/dist/chunk-PQ2XTY3M.js.map +1 -0
- package/dist/chunk-RDYR4DHG.mjs +62 -0
- package/dist/chunk-RDYR4DHG.mjs.map +1 -0
- package/dist/chunk-RWF3NVZP.mjs +29 -0
- package/dist/chunk-RWF3NVZP.mjs.map +1 -0
- package/dist/{chunk-Z4Y5IPR3.mjs → chunk-WZY32L6K.mjs} +3 -3
- package/dist/{chunk-Z4Y5IPR3.mjs.map → chunk-WZY32L6K.mjs.map} +1 -1
- package/dist/chunk-YRQN3AV4.js +38 -0
- package/dist/chunk-YRQN3AV4.js.map +1 -0
- package/dist/{chunk-UJZ7JQBQ.js → chunk-YY7G4NV3.js} +25 -6
- package/dist/chunk-YY7G4NV3.js.map +1 -0
- package/dist/{chunk-5HLEHSPM.mjs → chunk-ZB6C6CJQ.mjs} +25 -6
- package/dist/chunk-ZB6C6CJQ.mjs.map +1 -0
- package/dist/design-system/facade.js +8 -6
- package/dist/design-system/facade.js.map +1 -1
- package/dist/design-system/facade.mjs +7 -5
- package/dist/design-system/facade.mjs.map +1 -1
- package/dist/design-system/hash-generator.d.ts +15 -0
- package/dist/design-system/hash-generator.d.ts.map +1 -0
- package/dist/design-system/index.d.ts +2 -0
- package/dist/design-system/index.d.ts.map +1 -1
- package/dist/design-system/secret-reveal.d.ts +57 -0
- package/dist/design-system/secret-reveal.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useHash/index.d.ts +2 -0
- package/dist/hooks/useHash/index.d.ts.map +1 -0
- package/dist/hooks/useHash/useHash.d.ts +20 -0
- package/dist/hooks/useHash/useHash.d.ts.map +1 -0
- package/dist/hooks/useHash.js +18 -0
- package/dist/hooks/useHash.js.map +1 -0
- package/dist/hooks/useHash.mjs +5 -0
- package/dist/hooks/useHash.mjs.map +1 -0
- package/dist/ui/buttons/animated.js +10 -8
- package/dist/ui/buttons/animated.js.map +1 -1
- package/dist/ui/buttons/animated.mjs +8 -6
- package/dist/ui/buttons/animated.mjs.map +1 -1
- package/dist/ui/buttons.js +11 -9
- package/dist/ui/buttons.mjs +9 -7
- package/dist/ui/data-table.js +21 -19
- package/dist/ui/data-table.js.map +1 -1
- package/dist/ui/data-table.mjs +11 -9
- package/dist/ui/data-table.mjs.map +1 -1
- package/dist/ui/dynamic-stepper.js +20 -18
- package/dist/ui/dynamic-stepper.js.map +1 -1
- package/dist/ui/dynamic-stepper.mjs +9 -7
- package/dist/ui/dynamic-stepper.mjs.map +1 -1
- package/dist/ui/hash-generator/hash-generator-base.d.ts +6 -0
- package/dist/ui/hash-generator/hash-generator-base.d.ts.map +1 -0
- package/dist/ui/hash-generator/hash-generator.d.ts +2 -0
- package/dist/ui/hash-generator/hash-generator.d.ts.map +1 -0
- package/dist/ui/hash-generator/index.d.ts +5 -0
- package/dist/ui/hash-generator/index.d.ts.map +1 -0
- package/dist/ui/hash-generator/types.d.ts +17 -0
- package/dist/ui/hash-generator/types.d.ts.map +1 -0
- package/dist/ui/hash-generator/variants.d.ts +10 -0
- package/dist/ui/hash-generator/variants.d.ts.map +1 -0
- package/dist/ui/hash-generator.js +126 -0
- package/dist/ui/hash-generator.js.map +1 -0
- package/dist/ui/hash-generator.mjs +117 -0
- package/dist/ui/hash-generator.mjs.map +1 -0
- package/dist/ui/pagination.js +12 -10
- package/dist/ui/pagination.mjs +9 -7
- package/dist/ui/secret-reveal/animated/animations.d.ts +8 -0
- package/dist/ui/secret-reveal/animated/animations.d.ts.map +1 -0
- package/dist/ui/secret-reveal/animated/index.d.ts +4 -0
- package/dist/ui/secret-reveal/animated/index.d.ts.map +1 -0
- package/dist/ui/secret-reveal/animated/secret-reveal-animated.d.ts +6 -0
- package/dist/ui/secret-reveal/animated/secret-reveal-animated.d.ts.map +1 -0
- package/dist/ui/secret-reveal/animated/types.d.ts +9 -0
- package/dist/ui/secret-reveal/animated/types.d.ts.map +1 -0
- package/dist/ui/secret-reveal/animated.js +194 -0
- package/dist/ui/secret-reveal/animated.js.map +1 -0
- package/dist/ui/secret-reveal/animated.mjs +191 -0
- package/dist/ui/secret-reveal/animated.mjs.map +1 -0
- package/dist/ui/secret-reveal/index.d.ts +4 -0
- package/dist/ui/secret-reveal/index.d.ts.map +1 -0
- package/dist/ui/secret-reveal/secret-reveal-base.d.ts +6 -0
- package/dist/ui/secret-reveal/secret-reveal-base.d.ts.map +1 -0
- package/dist/ui/secret-reveal/secret-reveal.d.ts +2 -0
- package/dist/ui/secret-reveal/secret-reveal.d.ts.map +1 -0
- package/dist/ui/secret-reveal/types.d.ts +15 -0
- package/dist/ui/secret-reveal/types.d.ts.map +1 -0
- package/dist/ui/secret-reveal/variants.d.ts +15 -0
- package/dist/ui/secret-reveal/variants.d.ts.map +1 -0
- package/dist/ui/secret-reveal.js +136 -0
- package/dist/ui/secret-reveal.js.map +1 -0
- package/dist/ui/secret-reveal.mjs +119 -0
- package/dist/ui/secret-reveal.mjs.map +1 -0
- package/dist/ui/split-button.js +22 -20
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/split-button.mjs +9 -7
- package/dist/ui/split-button.mjs.map +1 -1
- package/package.json +1 -1
- package/src/design-system/hash-generator.ts +34 -0
- package/src/design-system/index.ts +2 -0
- package/src/design-system/secret-reveal.ts +75 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useHash/index.ts +6 -0
- package/src/hooks/useHash/useHash.test.ts +77 -0
- package/src/hooks/useHash/useHash.ts +89 -0
- package/src/ui/hash-generator/hash-generator-base.tsx +106 -0
- package/src/ui/hash-generator/hash-generator.test.tsx +73 -0
- package/src/ui/hash-generator/hash-generator.tsx +1 -0
- package/src/ui/hash-generator/index.ts +18 -0
- package/src/ui/hash-generator/types.ts +29 -0
- package/src/ui/hash-generator/variants.ts +31 -0
- package/src/ui/secret-reveal/animated/animations.ts +74 -0
- package/src/ui/secret-reveal/animated/index.ts +5 -0
- package/src/ui/secret-reveal/animated/secret-reveal-animated.tsx +132 -0
- package/src/ui/secret-reveal/animated/types.ts +11 -0
- package/src/ui/secret-reveal/index.ts +14 -0
- package/src/ui/secret-reveal/secret-reveal-base.tsx +116 -0
- package/src/ui/secret-reveal/secret-reveal.test.tsx +75 -0
- package/src/ui/secret-reveal/secret-reveal.tsx +2 -0
- package/src/ui/secret-reveal/types.ts +21 -0
- package/src/ui/secret-reveal/variants.ts +49 -0
- package/dist/chunk-5HLEHSPM.mjs.map +0 -1
- package/dist/chunk-UJZ7JQBQ.js.map +0 -1
- package/dist/chunk-YBKNXDZU.js +0 -19
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { AnimatePresence, motion } from "framer-motion";
|
|
4
|
+
import { useCallback, useState } from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../../lib/utils";
|
|
7
|
+
|
|
8
|
+
import { secretRevealAnimationPresets } from "./animations";
|
|
9
|
+
import type { SecretRevealAnimatedProps } from "./types";
|
|
10
|
+
import {
|
|
11
|
+
secretRevealLabelVariants,
|
|
12
|
+
secretRevealToggleVariants,
|
|
13
|
+
secretRevealValueVariants,
|
|
14
|
+
secretRevealVariants,
|
|
15
|
+
} from "../variants";
|
|
16
|
+
|
|
17
|
+
export function SecretRevealAnimated({
|
|
18
|
+
appearance,
|
|
19
|
+
size,
|
|
20
|
+
value,
|
|
21
|
+
children,
|
|
22
|
+
label,
|
|
23
|
+
labelPosition = "top",
|
|
24
|
+
initiallyRevealed = false,
|
|
25
|
+
onVisibilityChange,
|
|
26
|
+
animation = "fade",
|
|
27
|
+
muteChar = "•",
|
|
28
|
+
className,
|
|
29
|
+
ref,
|
|
30
|
+
...rest
|
|
31
|
+
}: SecretRevealAnimatedProps) {
|
|
32
|
+
const [revealed, setRevealed] = useState(initiallyRevealed);
|
|
33
|
+
|
|
34
|
+
const toggle = useCallback(() => {
|
|
35
|
+
const next = !revealed;
|
|
36
|
+
setRevealed(next);
|
|
37
|
+
onVisibilityChange?.(next);
|
|
38
|
+
}, [onVisibilityChange, revealed]);
|
|
39
|
+
|
|
40
|
+
const preset = secretRevealAnimationPresets[animation];
|
|
41
|
+
const displayText = value ?? (typeof children === "string" ? children : "");
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div
|
|
45
|
+
ref={ref}
|
|
46
|
+
data-slot="secret-reveal"
|
|
47
|
+
className={cn(secretRevealVariants({ appearance, size }), className)}
|
|
48
|
+
{...rest}
|
|
49
|
+
>
|
|
50
|
+
{label && labelPosition === "top" && (
|
|
51
|
+
<span
|
|
52
|
+
data-slot="secret-reveal-label"
|
|
53
|
+
className={secretRevealLabelVariants({ size })}
|
|
54
|
+
>
|
|
55
|
+
{label}
|
|
56
|
+
</span>
|
|
57
|
+
)}
|
|
58
|
+
<span className="flex items-center gap-2 flex-1 min-w-0">
|
|
59
|
+
{label && labelPosition === "side" && (
|
|
60
|
+
<span
|
|
61
|
+
data-slot="secret-reveal-label"
|
|
62
|
+
className={secretRevealLabelVariants({ size })}
|
|
63
|
+
>
|
|
64
|
+
{label}
|
|
65
|
+
</span>
|
|
66
|
+
)}
|
|
67
|
+
<span
|
|
68
|
+
data-slot="secret-reveal-value"
|
|
69
|
+
className={cn(secretRevealValueVariants({ size }), "flex-1 truncate")}
|
|
70
|
+
>
|
|
71
|
+
<AnimatePresence mode="wait">
|
|
72
|
+
<motion.span
|
|
73
|
+
key={revealed ? "revealed" : "hidden"}
|
|
74
|
+
initial="initial"
|
|
75
|
+
animate="animate"
|
|
76
|
+
exit="exit"
|
|
77
|
+
variants={preset.variants}
|
|
78
|
+
transition={preset.transition}
|
|
79
|
+
className="inline-block"
|
|
80
|
+
>
|
|
81
|
+
{revealed
|
|
82
|
+
? (value ?? children)
|
|
83
|
+
: muteChar.repeat(displayText.length || 8)}
|
|
84
|
+
</motion.span>
|
|
85
|
+
</AnimatePresence>
|
|
86
|
+
</span>
|
|
87
|
+
<button
|
|
88
|
+
type="button"
|
|
89
|
+
data-slot="secret-reveal-toggle"
|
|
90
|
+
className={secretRevealToggleVariants({ size, appearance })}
|
|
91
|
+
onClick={toggle}
|
|
92
|
+
aria-label={revealed ? "Hide secret" : "Reveal secret"}
|
|
93
|
+
>
|
|
94
|
+
{revealed ? (
|
|
95
|
+
<svg
|
|
96
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
97
|
+
width="16"
|
|
98
|
+
height="16"
|
|
99
|
+
viewBox="0 0 24 24"
|
|
100
|
+
fill="none"
|
|
101
|
+
stroke="currentColor"
|
|
102
|
+
strokeWidth="2"
|
|
103
|
+
strokeLinecap="round"
|
|
104
|
+
strokeLinejoin="round"
|
|
105
|
+
>
|
|
106
|
+
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94" />
|
|
107
|
+
<path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19" />
|
|
108
|
+
<line x1="1" y1="1" x2="23" y2="23" />
|
|
109
|
+
</svg>
|
|
110
|
+
) : (
|
|
111
|
+
<svg
|
|
112
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
113
|
+
width="16"
|
|
114
|
+
height="16"
|
|
115
|
+
viewBox="0 0 24 24"
|
|
116
|
+
fill="none"
|
|
117
|
+
stroke="currentColor"
|
|
118
|
+
strokeWidth="2"
|
|
119
|
+
strokeLinecap="round"
|
|
120
|
+
strokeLinejoin="round"
|
|
121
|
+
>
|
|
122
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
|
|
123
|
+
<circle cx="12" cy="12" r="3" />
|
|
124
|
+
</svg>
|
|
125
|
+
)}
|
|
126
|
+
</button>
|
|
127
|
+
</span>
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
SecretRevealAnimated.displayName = "SecretRevealAnimated";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Ref } from "react";
|
|
2
|
+
|
|
3
|
+
import type { SecretRevealBaseProps } from "../types";
|
|
4
|
+
import type { SecretRevealAnimation } from "./animations";
|
|
5
|
+
|
|
6
|
+
export type { SecretRevealAnimation };
|
|
7
|
+
|
|
8
|
+
export type SecretRevealAnimatedProps = SecretRevealBaseProps & {
|
|
9
|
+
animation?: SecretRevealAnimation;
|
|
10
|
+
ref?: Ref<HTMLDivElement>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
export { SecretReveal } from "./secret-reveal";
|
|
4
|
+
export type {
|
|
5
|
+
SecretRevealBaseProps,
|
|
6
|
+
SecretRevealProps,
|
|
7
|
+
SecretRevealVariantProps,
|
|
8
|
+
} from "./types";
|
|
9
|
+
export {
|
|
10
|
+
secretRevealLabelVariants,
|
|
11
|
+
secretRevealToggleVariants,
|
|
12
|
+
secretRevealValueVariants,
|
|
13
|
+
secretRevealVariants,
|
|
14
|
+
} from "./variants";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils";
|
|
6
|
+
|
|
7
|
+
import type { SecretRevealBaseProps } from "./types";
|
|
8
|
+
import {
|
|
9
|
+
secretRevealLabelVariants,
|
|
10
|
+
secretRevealToggleVariants,
|
|
11
|
+
secretRevealValueVariants,
|
|
12
|
+
secretRevealVariants,
|
|
13
|
+
} from "./variants";
|
|
14
|
+
|
|
15
|
+
export function SecretRevealBase({
|
|
16
|
+
appearance,
|
|
17
|
+
size,
|
|
18
|
+
value,
|
|
19
|
+
children,
|
|
20
|
+
label,
|
|
21
|
+
labelPosition = "top",
|
|
22
|
+
initiallyRevealed = false,
|
|
23
|
+
onVisibilityChange,
|
|
24
|
+
muteChar = "•",
|
|
25
|
+
className,
|
|
26
|
+
ref,
|
|
27
|
+
...rest
|
|
28
|
+
}: SecretRevealBaseProps) {
|
|
29
|
+
const [revealed, setRevealed] = useState(initiallyRevealed);
|
|
30
|
+
|
|
31
|
+
const toggle = useCallback(() => {
|
|
32
|
+
const next = !revealed;
|
|
33
|
+
setRevealed(next);
|
|
34
|
+
onVisibilityChange?.(next);
|
|
35
|
+
}, [onVisibilityChange, revealed]);
|
|
36
|
+
|
|
37
|
+
const displayText = value ?? (typeof children === "string" ? children : "");
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div
|
|
41
|
+
ref={ref}
|
|
42
|
+
data-slot="secret-reveal"
|
|
43
|
+
className={cn(secretRevealVariants({ appearance, size }), className)}
|
|
44
|
+
{...rest}
|
|
45
|
+
>
|
|
46
|
+
{label && labelPosition === "top" && (
|
|
47
|
+
<span
|
|
48
|
+
data-slot="secret-reveal-label"
|
|
49
|
+
className={secretRevealLabelVariants({ size })}
|
|
50
|
+
>
|
|
51
|
+
{label}
|
|
52
|
+
</span>
|
|
53
|
+
)}
|
|
54
|
+
<span className="flex items-center gap-2 flex-1 min-w-0">
|
|
55
|
+
{label && labelPosition === "side" && (
|
|
56
|
+
<span
|
|
57
|
+
data-slot="secret-reveal-label"
|
|
58
|
+
className={secretRevealLabelVariants({ size })}
|
|
59
|
+
>
|
|
60
|
+
{label}
|
|
61
|
+
</span>
|
|
62
|
+
)}
|
|
63
|
+
<span
|
|
64
|
+
data-slot="secret-reveal-value"
|
|
65
|
+
className={cn(secretRevealValueVariants({ size }), "flex-1 truncate")}
|
|
66
|
+
>
|
|
67
|
+
{revealed
|
|
68
|
+
? (value ?? children)
|
|
69
|
+
: muteChar.repeat(displayText.length || 8)}
|
|
70
|
+
</span>
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
data-slot="secret-reveal-toggle"
|
|
74
|
+
className={secretRevealToggleVariants({ size, appearance })}
|
|
75
|
+
onClick={toggle}
|
|
76
|
+
aria-label={revealed ? "Hide secret" : "Reveal secret"}
|
|
77
|
+
>
|
|
78
|
+
{revealed ? (
|
|
79
|
+
<svg
|
|
80
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
81
|
+
width="16"
|
|
82
|
+
height="16"
|
|
83
|
+
viewBox="0 0 24 24"
|
|
84
|
+
fill="none"
|
|
85
|
+
stroke="currentColor"
|
|
86
|
+
strokeWidth="2"
|
|
87
|
+
strokeLinecap="round"
|
|
88
|
+
strokeLinejoin="round"
|
|
89
|
+
>
|
|
90
|
+
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94" />
|
|
91
|
+
<path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19" />
|
|
92
|
+
<line x1="1" y1="1" x2="23" y2="23" />
|
|
93
|
+
</svg>
|
|
94
|
+
) : (
|
|
95
|
+
<svg
|
|
96
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
97
|
+
width="16"
|
|
98
|
+
height="16"
|
|
99
|
+
viewBox="0 0 24 24"
|
|
100
|
+
fill="none"
|
|
101
|
+
stroke="currentColor"
|
|
102
|
+
strokeWidth="2"
|
|
103
|
+
strokeLinecap="round"
|
|
104
|
+
strokeLinejoin="round"
|
|
105
|
+
>
|
|
106
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
|
|
107
|
+
<circle cx="12" cy="12" r="3" />
|
|
108
|
+
</svg>
|
|
109
|
+
)}
|
|
110
|
+
</button>
|
|
111
|
+
</span>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
SecretRevealBase.displayName = "SecretReveal";
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createRef } from "react";
|
|
2
|
+
import { render } from "@testing-library/react";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { SecretReveal } from "./secret-reveal";
|
|
6
|
+
|
|
7
|
+
describe("SecretReveal", () => {
|
|
8
|
+
it("should set displayName", () => {
|
|
9
|
+
expect(SecretReveal.displayName).toBe("SecretReveal");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should stamp data-slot on the root container", () => {
|
|
13
|
+
const { container } = render(<SecretReveal value="sk-test" />);
|
|
14
|
+
const root = container.querySelector('[data-slot="secret-reveal"]');
|
|
15
|
+
expect(root).toBeTruthy();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should render masked value by default", () => {
|
|
19
|
+
const { container } = render(<SecretReveal value="sk-test" />);
|
|
20
|
+
const valueEl = container.querySelector(
|
|
21
|
+
'[data-slot="secret-reveal-value"]',
|
|
22
|
+
);
|
|
23
|
+
expect(valueEl?.textContent).toBe("•••••••");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should render a label", () => {
|
|
27
|
+
const { container } = render(
|
|
28
|
+
<SecretReveal value="sk-test" label="API Key" />,
|
|
29
|
+
);
|
|
30
|
+
const label = container.querySelector('[data-slot="secret-reveal-label"]');
|
|
31
|
+
expect(label).toBeTruthy();
|
|
32
|
+
expect(label?.textContent).toBe("API Key");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should render a toggle button", () => {
|
|
36
|
+
const { container } = render(<SecretReveal value="sk-test" />);
|
|
37
|
+
const toggle = container.querySelector(
|
|
38
|
+
'[data-slot="secret-reveal-toggle"]',
|
|
39
|
+
);
|
|
40
|
+
expect(toggle).toBeTruthy();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should render initial revealed state", () => {
|
|
44
|
+
const { container } = render(
|
|
45
|
+
<SecretReveal value="sk-test" initiallyRevealed />,
|
|
46
|
+
);
|
|
47
|
+
const valueEl = container.querySelector(
|
|
48
|
+
'[data-slot="secret-reveal-value"]',
|
|
49
|
+
);
|
|
50
|
+
expect(valueEl?.textContent).toBe("sk-test");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("should render with children instead of value", () => {
|
|
54
|
+
const { container } = render(<SecretReveal>my-secret-key</SecretReveal>);
|
|
55
|
+
const valueEl = container.querySelector(
|
|
56
|
+
'[data-slot="secret-reveal-value"]',
|
|
57
|
+
);
|
|
58
|
+
expect(valueEl?.textContent).toBe("•••••••••••••");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should forward refs to the root element", () => {
|
|
62
|
+
const ref = createRef<HTMLDivElement>();
|
|
63
|
+
render(<SecretReveal value="test" ref={ref} />);
|
|
64
|
+
expect(ref.current).toBeInstanceOf(HTMLElement);
|
|
65
|
+
expect(ref.current?.getAttribute("data-slot")).toBe("secret-reveal");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should apply custom className", () => {
|
|
69
|
+
const { container } = render(
|
|
70
|
+
<SecretReveal value="test" className="custom-class" />,
|
|
71
|
+
);
|
|
72
|
+
const root = container.querySelector('[data-slot="secret-reveal"]');
|
|
73
|
+
expect(root?.className).toMatch(/custom-class/);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { VariantProps } from "class-variance-authority";
|
|
2
|
+
import type { ComponentPropsWithRef, ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
import type { secretRevealVariants } from "./variants";
|
|
5
|
+
|
|
6
|
+
export type SecretRevealVariantProps = VariantProps<
|
|
7
|
+
typeof secretRevealVariants
|
|
8
|
+
>;
|
|
9
|
+
|
|
10
|
+
export type SecretRevealBaseProps = SecretRevealVariantProps &
|
|
11
|
+
ComponentPropsWithRef<"div"> & {
|
|
12
|
+
value?: string;
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
label?: ReactNode;
|
|
15
|
+
labelPosition?: "top" | "side";
|
|
16
|
+
initiallyRevealed?: boolean;
|
|
17
|
+
onVisibilityChange?: (revealed: boolean) => void;
|
|
18
|
+
muteChar?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type SecretRevealProps = SecretRevealBaseProps;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
zuiSecretRevealAppearances,
|
|
5
|
+
zuiSecretRevealContainerBase,
|
|
6
|
+
zuiSecretRevealLabelBase,
|
|
7
|
+
zuiSecretRevealLabelSizes,
|
|
8
|
+
zuiSecretRevealSizes,
|
|
9
|
+
zuiSecretRevealToggleBase,
|
|
10
|
+
zuiSecretRevealToggleSizes,
|
|
11
|
+
zuiSecretRevealValueBase,
|
|
12
|
+
zuiSecretRevealValueSizes,
|
|
13
|
+
} from "../../design-system/secret-reveal";
|
|
14
|
+
|
|
15
|
+
export const secretRevealVariants = cva(zuiSecretRevealContainerBase, {
|
|
16
|
+
variants: {
|
|
17
|
+
appearance: zuiSecretRevealAppearances,
|
|
18
|
+
size: zuiSecretRevealSizes,
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
appearance: "default",
|
|
22
|
+
size: "md",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const secretRevealLabelVariants = cva(zuiSecretRevealLabelBase, {
|
|
27
|
+
variants: {
|
|
28
|
+
size: zuiSecretRevealLabelSizes,
|
|
29
|
+
},
|
|
30
|
+
defaultVariants: { size: "md" },
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const secretRevealValueVariants = cva(zuiSecretRevealValueBase, {
|
|
34
|
+
variants: {
|
|
35
|
+
size: zuiSecretRevealValueSizes,
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: { size: "md" },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export const secretRevealToggleVariants = cva(zuiSecretRevealToggleBase, {
|
|
41
|
+
variants: {
|
|
42
|
+
size: zuiSecretRevealToggleSizes,
|
|
43
|
+
appearance: zuiSecretRevealAppearances,
|
|
44
|
+
},
|
|
45
|
+
defaultVariants: {
|
|
46
|
+
size: "md",
|
|
47
|
+
appearance: "default",
|
|
48
|
+
},
|
|
49
|
+
});
|