@zentauri-ui/zentauri-components 2.2.2 → 2.3.1

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.
Files changed (194) hide show
  1. package/README.md +10 -6
  2. package/cli/props.json +526 -0
  3. package/cli/registry.json +11 -0
  4. package/dist/chunk-4U6PVVST.mjs +15 -0
  5. package/dist/chunk-4U6PVVST.mjs.map +1 -0
  6. package/dist/{chunk-DIAA5VH4.mjs → chunk-CIZQQ32L.mjs} +3 -3
  7. package/dist/chunk-CIZQQ32L.mjs.map +1 -0
  8. package/dist/chunk-EZNR7VLJ.js +65 -0
  9. package/dist/chunk-EZNR7VLJ.js.map +1 -0
  10. package/dist/{chunk-PQ2XTY3M.js → chunk-G36ZV446.js} +13 -13
  11. package/dist/{chunk-PQ2XTY3M.js.map → chunk-G36ZV446.js.map} +1 -1
  12. package/dist/{chunk-H3BJOK22.js → chunk-HNAUUCR5.js} +3 -3
  13. package/dist/chunk-HNAUUCR5.js.map +1 -0
  14. package/dist/{chunk-UZ6Y5CSV.js → chunk-K7UU3K54.js} +39 -18
  15. package/dist/chunk-K7UU3K54.js.map +1 -0
  16. package/dist/chunk-MY3DQVNF.js +19 -0
  17. package/dist/{chunk-ILPPXWR3.js.map → chunk-MY3DQVNF.js.map} +1 -1
  18. package/dist/{chunk-ATE5SCTR.mjs → chunk-N6Q4ZLQR.mjs} +3 -3
  19. package/dist/{chunk-ATE5SCTR.mjs.map → chunk-N6Q4ZLQR.mjs.map} +1 -1
  20. package/dist/{chunk-GFE6ZX5Y.mjs → chunk-PJATBFEK.mjs} +30 -9
  21. package/dist/chunk-PJATBFEK.mjs.map +1 -0
  22. package/dist/chunk-PVVYOIU2.js +38 -0
  23. package/dist/chunk-PVVYOIU2.js.map +1 -0
  24. package/dist/chunk-PWEZB53R.js +90 -0
  25. package/dist/chunk-PWEZB53R.js.map +1 -0
  26. package/dist/chunk-PWYEC3KY.mjs +30 -0
  27. package/dist/chunk-PWYEC3KY.mjs.map +1 -0
  28. package/dist/{chunk-5I4GAURE.js → chunk-RBNZNWYQ.js} +6 -6
  29. package/dist/{chunk-5I4GAURE.js.map → chunk-RBNZNWYQ.js.map} +1 -1
  30. package/dist/chunk-RDYR4DHG.mjs +62 -0
  31. package/dist/chunk-RDYR4DHG.mjs.map +1 -0
  32. package/dist/chunk-RWF3NVZP.mjs +29 -0
  33. package/dist/chunk-RWF3NVZP.mjs.map +1 -0
  34. package/dist/{chunk-NUV2I337.mjs → chunk-STWXN5EM.mjs} +3 -3
  35. package/dist/{chunk-NUV2I337.mjs.map → chunk-STWXN5EM.mjs.map} +1 -1
  36. package/dist/{chunk-W5MTZJPE.mjs → chunk-TTKTPERV.mjs} +3 -3
  37. package/dist/{chunk-W5MTZJPE.mjs.map → chunk-TTKTPERV.mjs.map} +1 -1
  38. package/dist/chunk-UBQY572I.mjs +81 -0
  39. package/dist/chunk-UBQY572I.mjs.map +1 -0
  40. package/dist/{chunk-IY72Z65Z.js → chunk-UN5RRNPV.js} +12 -12
  41. package/dist/{chunk-IY72Z65Z.js.map → chunk-UN5RRNPV.js.map} +1 -1
  42. package/dist/{chunk-N2G7IWHS.mjs → chunk-VMVG2RVZ.mjs} +4 -4
  43. package/dist/{chunk-N2G7IWHS.mjs.map → chunk-VMVG2RVZ.mjs.map} +1 -1
  44. package/dist/chunk-XUK5P37Y.js +19 -0
  45. package/dist/chunk-XUK5P37Y.js.map +1 -0
  46. package/dist/chunk-YRQN3AV4.js +38 -0
  47. package/dist/chunk-YRQN3AV4.js.map +1 -0
  48. package/dist/design-system/facade.js +12 -9
  49. package/dist/design-system/facade.js.map +1 -1
  50. package/dist/design-system/facade.mjs +11 -8
  51. package/dist/design-system/facade.mjs.map +1 -1
  52. package/dist/design-system/hash-generator.d.ts +15 -0
  53. package/dist/design-system/hash-generator.d.ts.map +1 -0
  54. package/dist/design-system/index.d.ts +3 -0
  55. package/dist/design-system/index.d.ts.map +1 -1
  56. package/dist/design-system/qr-code.d.ts +4 -0
  57. package/dist/design-system/qr-code.d.ts.map +1 -0
  58. package/dist/design-system/qr-scanner.d.ts +11 -0
  59. package/dist/design-system/qr-scanner.d.ts.map +1 -0
  60. package/dist/design-system/secret-reveal.d.ts +1 -1
  61. package/dist/design-system/secret-reveal.d.ts.map +1 -1
  62. package/dist/hooks/index.d.ts +1 -0
  63. package/dist/hooks/index.d.ts.map +1 -1
  64. package/dist/hooks/useHash/index.d.ts +2 -0
  65. package/dist/hooks/useHash/index.d.ts.map +1 -0
  66. package/dist/hooks/useHash/useHash.d.ts +20 -0
  67. package/dist/hooks/useHash/useHash.d.ts.map +1 -0
  68. package/dist/hooks/useHash.js +18 -0
  69. package/dist/hooks/useHash.js.map +1 -0
  70. package/dist/hooks/useHash.mjs +5 -0
  71. package/dist/hooks/useHash.mjs.map +1 -0
  72. package/dist/ui/buttons/animated.js +14 -11
  73. package/dist/ui/buttons/animated.js.map +1 -1
  74. package/dist/ui/buttons/animated.mjs +12 -9
  75. package/dist/ui/buttons/animated.mjs.map +1 -1
  76. package/dist/ui/buttons.js +15 -12
  77. package/dist/ui/buttons.mjs +13 -10
  78. package/dist/ui/data-table.js +24 -21
  79. package/dist/ui/data-table.js.map +1 -1
  80. package/dist/ui/data-table.mjs +14 -11
  81. package/dist/ui/data-table.mjs.map +1 -1
  82. package/dist/ui/dynamic-stepper.js +24 -21
  83. package/dist/ui/dynamic-stepper.js.map +1 -1
  84. package/dist/ui/dynamic-stepper.mjs +13 -10
  85. package/dist/ui/dynamic-stepper.mjs.map +1 -1
  86. package/dist/ui/hash-generator/hash-generator-base.d.ts +6 -0
  87. package/dist/ui/hash-generator/hash-generator-base.d.ts.map +1 -0
  88. package/dist/ui/hash-generator/hash-generator.d.ts +2 -0
  89. package/dist/ui/hash-generator/hash-generator.d.ts.map +1 -0
  90. package/dist/ui/hash-generator/index.d.ts +5 -0
  91. package/dist/ui/hash-generator/index.d.ts.map +1 -0
  92. package/dist/ui/hash-generator/types.d.ts +17 -0
  93. package/dist/ui/hash-generator/types.d.ts.map +1 -0
  94. package/dist/ui/hash-generator/variants.d.ts +10 -0
  95. package/dist/ui/hash-generator/variants.d.ts.map +1 -0
  96. package/dist/ui/hash-generator.js +126 -0
  97. package/dist/ui/hash-generator.js.map +1 -0
  98. package/dist/ui/hash-generator.mjs +117 -0
  99. package/dist/ui/hash-generator.mjs.map +1 -0
  100. package/dist/ui/pagination.js +16 -13
  101. package/dist/ui/pagination.mjs +13 -10
  102. package/dist/ui/qr-code/animated/animations.d.ts +8 -0
  103. package/dist/ui/qr-code/animated/animations.d.ts.map +1 -0
  104. package/dist/ui/qr-code/animated/index.d.ts +4 -0
  105. package/dist/ui/qr-code/animated/index.d.ts.map +1 -0
  106. package/dist/ui/qr-code/animated/qr-code-animated.d.ts +6 -0
  107. package/dist/ui/qr-code/animated/qr-code-animated.d.ts.map +1 -0
  108. package/dist/ui/qr-code/animated/types.d.ts +9 -0
  109. package/dist/ui/qr-code/animated/types.d.ts.map +1 -0
  110. package/dist/ui/qr-code/animated.js +156 -0
  111. package/dist/ui/qr-code/animated.js.map +1 -0
  112. package/dist/ui/qr-code/animated.mjs +149 -0
  113. package/dist/ui/qr-code/animated.mjs.map +1 -0
  114. package/dist/ui/qr-code/index.d.ts +5 -0
  115. package/dist/ui/qr-code/index.d.ts.map +1 -0
  116. package/dist/ui/qr-code/qr-code-base.d.ts +47 -0
  117. package/dist/ui/qr-code/qr-code-base.d.ts.map +1 -0
  118. package/dist/ui/qr-code/qr-code.d.ts +2 -0
  119. package/dist/ui/qr-code/qr-code.d.ts.map +1 -0
  120. package/dist/ui/qr-code/types.d.ts +14 -0
  121. package/dist/ui/qr-code/types.d.ts.map +1 -0
  122. package/dist/ui/qr-code/variants.d.ts +4 -0
  123. package/dist/ui/qr-code/variants.d.ts.map +1 -0
  124. package/dist/ui/qr-code.js +35 -0
  125. package/dist/ui/qr-code.js.map +1 -0
  126. package/dist/ui/qr-code.mjs +17 -0
  127. package/dist/ui/qr-code.mjs.map +1 -0
  128. package/dist/ui/qr-scanner/index.d.ts +4 -0
  129. package/dist/ui/qr-scanner/index.d.ts.map +1 -0
  130. package/dist/ui/qr-scanner/qr-scanner-base.d.ts +62 -0
  131. package/dist/ui/qr-scanner/qr-scanner-base.d.ts.map +1 -0
  132. package/dist/ui/qr-scanner/qr-scanner.d.ts +2 -0
  133. package/dist/ui/qr-scanner/qr-scanner.d.ts.map +1 -0
  134. package/dist/ui/qr-scanner/types.d.ts +28 -0
  135. package/dist/ui/qr-scanner/types.d.ts.map +1 -0
  136. package/dist/ui/qr-scanner/variants.d.ts +9 -0
  137. package/dist/ui/qr-scanner/variants.d.ts.map +1 -0
  138. package/dist/ui/qr-scanner.js +316 -0
  139. package/dist/ui/qr-scanner.js.map +1 -0
  140. package/dist/ui/qr-scanner.mjs +308 -0
  141. package/dist/ui/qr-scanner.mjs.map +1 -0
  142. package/dist/ui/secret-reveal/animated/secret-reveal-animated.d.ts.map +1 -1
  143. package/dist/ui/secret-reveal/animated.js +10 -7
  144. package/dist/ui/secret-reveal/animated.js.map +1 -1
  145. package/dist/ui/secret-reveal/animated.mjs +6 -3
  146. package/dist/ui/secret-reveal/animated.mjs.map +1 -1
  147. package/dist/ui/secret-reveal/secret-reveal-base.d.ts.map +1 -1
  148. package/dist/ui/secret-reveal.js +14 -11
  149. package/dist/ui/secret-reveal.js.map +1 -1
  150. package/dist/ui/secret-reveal.mjs +7 -4
  151. package/dist/ui/secret-reveal.mjs.map +1 -1
  152. package/dist/ui/split-button.js +26 -23
  153. package/dist/ui/split-button.js.map +1 -1
  154. package/dist/ui/split-button.mjs +13 -10
  155. package/dist/ui/split-button.mjs.map +1 -1
  156. package/package.json +5 -2
  157. package/src/design-system/hash-generator.ts +34 -0
  158. package/src/design-system/index.ts +3 -0
  159. package/src/design-system/qr-code.ts +13 -0
  160. package/src/design-system/qr-scanner.ts +32 -0
  161. package/src/design-system/secret-reveal.ts +1 -1
  162. package/src/hooks/index.ts +6 -0
  163. package/src/hooks/useHash/index.ts +6 -0
  164. package/src/hooks/useHash/useHash.test.ts +77 -0
  165. package/src/hooks/useHash/useHash.ts +89 -0
  166. package/src/ui/hash-generator/hash-generator-base.tsx +106 -0
  167. package/src/ui/hash-generator/hash-generator.test.tsx +73 -0
  168. package/src/ui/hash-generator/hash-generator.tsx +1 -0
  169. package/src/ui/hash-generator/index.ts +18 -0
  170. package/src/ui/hash-generator/types.ts +29 -0
  171. package/src/ui/hash-generator/variants.ts +31 -0
  172. package/src/ui/qr-code/animated/animations.ts +51 -0
  173. package/src/ui/qr-code/animated/index.ts +5 -0
  174. package/src/ui/qr-code/animated/qr-code-animated.tsx +111 -0
  175. package/src/ui/qr-code/animated/types.ts +10 -0
  176. package/src/ui/qr-code/index.ts +10 -0
  177. package/src/ui/qr-code/qr-code-base.tsx +149 -0
  178. package/src/ui/qr-code/qr-code.test.tsx +58 -0
  179. package/src/ui/qr-code/qr-code.tsx +2 -0
  180. package/src/ui/qr-code/types.ts +22 -0
  181. package/src/ui/qr-code/variants.ts +11 -0
  182. package/src/ui/qr-scanner/index.ts +17 -0
  183. package/src/ui/qr-scanner/qr-scanner-base.tsx +568 -0
  184. package/src/ui/qr-scanner/qr-scanner.test.tsx +61 -0
  185. package/src/ui/qr-scanner/qr-scanner.tsx +2 -0
  186. package/src/ui/qr-scanner/types.ts +32 -0
  187. package/src/ui/qr-scanner/variants.ts +26 -0
  188. package/src/ui/secret-reveal/animated/secret-reveal-animated.tsx +4 -1
  189. package/src/ui/secret-reveal/secret-reveal-base.tsx +4 -1
  190. package/dist/chunk-DIAA5VH4.mjs.map +0 -1
  191. package/dist/chunk-GFE6ZX5Y.mjs.map +0 -1
  192. package/dist/chunk-H3BJOK22.js.map +0 -1
  193. package/dist/chunk-ILPPXWR3.js +0 -19
  194. package/dist/chunk-UZ6Y5CSV.js.map +0 -1
@@ -0,0 +1,149 @@
1
+ "use client";
2
+
3
+ import { useEffect, useRef } from "react";
4
+ import QRCode from "qrcode";
5
+
6
+ import { cn } from "../../lib/utils";
7
+
8
+ import type { QrCodeBaseProps } from "./types";
9
+ import {
10
+ qrCodeCanvasWrapperVariants,
11
+ qrCodeCaptionVariants,
12
+ qrCodeVariants,
13
+ } from "./variants";
14
+
15
+ /**
16
+ * QrCodeBase renders a QR code onto a `<canvas>` element using the `qrcode`
17
+ * npm package. It is the static (non-animated) implementation of the public
18
+ * `QrCode` component.
19
+ *
20
+ * --- Props ---
21
+ *
22
+ * - `value` — The string to encode. When empty/falsy the canvas is cleared.
23
+ * - `canvasSize` — Pixel dimensions of the canvas (default: 200). Both width
24
+ * and height are set to this value, producing a square QR code.
25
+ * - `level` — Error correction level (`"L"` | `"M"` | `"Q"` | `"H"`). Higher
26
+ * levels survive more visual damage but hold less data.
27
+ * - `bgColor` / `fgColor` — Background and foreground colours passed to the
28
+ * underlying `QRCode.toCanvas` options.
29
+ * - `margin` — Quiet-zone width in QR modules (default: 2). Passed directly
30
+ * to the `qrcode` library.
31
+ * - `caption` — Optional label rendered below the QR code.
32
+ * - `ref` — React 19 ref forwarded to the root `<div>` element.
33
+ * - `className` / `...rest` — Spread onto the root `<div>` for layout or
34
+ * style overrides.
35
+ *
36
+ * --- Rendering lifecycle ---
37
+ *
38
+ * A `useEffect` watches `[value, canvasSize, level, bgColor, fgColor, margin]`.
39
+ * On every change it:
40
+ * 1. Grabs the canvas element from the ref.
41
+ * 2. If `value` is empty, clears the canvas with `ctx.clearRect` so a stale
42
+ * QR code doesn't persist.
43
+ * 3. Otherwise calls `QRCode.toCanvas()` which draws the QR pattern
44
+ * asynchronously (via callback) onto the canvas element.
45
+ *
46
+ * The outer `<div>` uses design-system variants (`qrCodeVariants`) for
47
+ * consistent theming and carries `data-slot="qr-code"` for scoped styling and
48
+ * testing.
49
+ *
50
+ * --- Accessibility ---
51
+ *
52
+ * The `<canvas>` has an `aria-label` describing it as a "QR code for {value}".
53
+ * Screen readers will announce the purpose, though the raw value is exposed
54
+ * (consider truncating for secrets).
55
+ */
56
+ export function QrCodeBase({
57
+ value,
58
+ canvasSize = 200,
59
+ level = "M",
60
+ bgColor = "#ffffff",
61
+ fgColor = "#000000",
62
+ margin = 2,
63
+ caption,
64
+ className,
65
+ ref,
66
+ ...rest
67
+ }: QrCodeBaseProps) {
68
+ const canvasRef = useRef<HTMLCanvasElement>(null);
69
+
70
+ /**
71
+ * Draw the QR pattern whenever input props change.
72
+ *
73
+ * The conditional `if (!value)` branch handles the "clear" case: when the
74
+ * user deletes the input text, we clear the canvas so a stale QR code isn't
75
+ * displayed. Without this the old QR pattern persists because
76
+ * `QRCode.toCanvas` is never called (it returns early for empty values).
77
+ */
78
+ useEffect(() => {
79
+ const canvas = canvasRef.current;
80
+ if (!canvas) return;
81
+
82
+ if (!value) {
83
+ const ctx = canvas.getContext("2d");
84
+ if (ctx) {
85
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
86
+ }
87
+ return;
88
+ }
89
+
90
+ QRCode.toCanvas(
91
+ canvas,
92
+ value,
93
+ {
94
+ width: canvasSize,
95
+ margin,
96
+ color: {
97
+ dark: fgColor,
98
+ light: bgColor,
99
+ },
100
+ errorCorrectionLevel: level,
101
+ },
102
+ (error) => {
103
+ if (error) {
104
+ console.error("QR Code generation error:", error);
105
+ }
106
+ },
107
+ );
108
+ }, [value, canvasSize, level, bgColor, fgColor, margin]);
109
+
110
+ /**
111
+ * The root element is a `<div>` (not the `<canvas>`) so consumers can apply
112
+ * layout classes, the caption sits outside the canvas, and the component
113
+ * plays well with flex/grid containers.
114
+ *
115
+ * Nested structure:
116
+ * <div data-slot="qr-code"> ← root (ref, className, ...rest)
117
+ * <div> ← canvas wrapper (theme rounding/overflow)
118
+ * <canvas data-slot="qr-code-canvas" />
119
+ * </div>
120
+ * {caption && <span data-slot="qr-code-caption" />}
121
+ * </div>
122
+ */
123
+ return (
124
+ <div
125
+ ref={ref}
126
+ data-slot="qr-code"
127
+ className={cn(qrCodeVariants(), className)}
128
+ {...rest}
129
+ >
130
+ <div className={qrCodeCanvasWrapperVariants()}>
131
+ <canvas
132
+ ref={canvasRef}
133
+ width={canvasSize}
134
+ height={canvasSize}
135
+ data-slot="qr-code-canvas"
136
+ className="block h-auto max-w-full"
137
+ aria-label={`QR code for ${value}`}
138
+ />
139
+ </div>
140
+ {caption ? (
141
+ <span data-slot="qr-code-caption" className={qrCodeCaptionVariants()}>
142
+ {caption}
143
+ </span>
144
+ ) : null}
145
+ </div>
146
+ );
147
+ }
148
+
149
+ QrCodeBase.displayName = "QrCode";
@@ -0,0 +1,58 @@
1
+ import { createRef } from "react";
2
+ import { render, screen } from "@testing-library/react";
3
+ import { describe, expect, it, vi } from "vitest";
4
+
5
+ import { QrCode } from "./qr-code";
6
+
7
+ vi.mock("qrcode", () => ({
8
+ default: {
9
+ toCanvas: vi.fn(
10
+ (
11
+ _canvas: HTMLCanvasElement,
12
+ _value: string,
13
+ _opts: unknown,
14
+ cb?: (err?: Error) => void,
15
+ ) => {
16
+ cb?.();
17
+ },
18
+ ),
19
+ },
20
+ }));
21
+
22
+ describe("QrCode", () => {
23
+ it("should expose displayName", () => {
24
+ expect(QrCode.displayName).toBe("QrCode");
25
+ });
26
+
27
+ it("should stamp data-slot", () => {
28
+ render(<QrCode value="https://example.com" />);
29
+ const root = document.querySelector('[data-slot="qr-code"]');
30
+ expect(root).toBeTruthy();
31
+ expect(root?.getAttribute("data-slot")).toBe("qr-code");
32
+ });
33
+
34
+ it("should render canvas element", () => {
35
+ render(<QrCode value="https://example.com" />);
36
+ const canvas = document.querySelector('[data-slot="qr-code-canvas"]');
37
+ expect(canvas).toBeTruthy();
38
+ });
39
+
40
+ it("should render with caption", () => {
41
+ render(<QrCode value="test" caption="Scan me" />);
42
+ expect(screen.getByText("Scan me")).toBeInTheDocument();
43
+ });
44
+
45
+ it("should forward ref", () => {
46
+ const ref = createRef<HTMLDivElement>();
47
+ render(<QrCode value="test" ref={ref} />);
48
+ expect(ref.current?.getAttribute("data-slot")).toBe("qr-code");
49
+ });
50
+
51
+ it("should apply custom className", () => {
52
+ const { container } = render(
53
+ <QrCode value="test" className="custom-class" />,
54
+ );
55
+ const root = container.querySelector('[data-slot="qr-code"]');
56
+ expect(root?.className).toMatch(/custom-class/);
57
+ });
58
+ });
@@ -0,0 +1,2 @@
1
+ // qr-code.tsx — default static entry (no framer-motion)
2
+ export { QrCodeBase as QrCode } from "./qr-code-base";
@@ -0,0 +1,22 @@
1
+ import type { ComponentPropsWithRef, ReactNode } from "react";
2
+
3
+ export type QrCodeLevel = "L" | "M" | "Q" | "H";
4
+
5
+ export interface QrCodeBaseProps extends ComponentPropsWithRef<"div"> {
6
+ value: string;
7
+ canvasSize?: number;
8
+ level?: QrCodeLevel;
9
+ bgColor?: string;
10
+ fgColor?: string;
11
+ margin?: number;
12
+ caption?: ReactNode;
13
+ }
14
+
15
+ export type QrCodeProps = QrCodeBaseProps;
16
+
17
+ export const QR_CODE_LEVEL_LABELS: Record<QrCodeLevel, string> = {
18
+ L: "Low (7%)",
19
+ M: "Medium (15%)",
20
+ Q: "Quartile (25%)",
21
+ H: "High (30%)",
22
+ } as const;
@@ -0,0 +1,11 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ import {
4
+ zuiQrCodeBase,
5
+ zuiQrCodeCanvasWrapper,
6
+ zuiQrCodeCaptionBase,
7
+ } from "../../design-system/qr-code";
8
+
9
+ export const qrCodeVariants = cva(zuiQrCodeBase);
10
+ export const qrCodeCanvasWrapperVariants = cva(zuiQrCodeCanvasWrapper);
11
+ export const qrCodeCaptionVariants = cva(zuiQrCodeCaptionBase);
@@ -0,0 +1,17 @@
1
+ "use client";
2
+
3
+ export { QrScanner } from "./qr-scanner";
4
+ export type {
5
+ QrScannerBaseProps,
6
+ QrScannerProps,
7
+ QrScannerRef,
8
+ QrScannerVariantProps,
9
+ } from "./types";
10
+ export {
11
+ qrScannerFallbackVariants,
12
+ qrScannerOverlayVariants,
13
+ qrScannerStatusVariants,
14
+ qrScannerVariants,
15
+ qrScannerVideoVariants,
16
+ qrScannerViewfinderVariants,
17
+ } from "./variants";