kmod-cli 1.0.10
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 +53 -0
- package/bin/gen-components.js +68 -0
- package/bin/index.js +153 -0
- package/component-templates/components/access-denied.tsx +130 -0
- package/component-templates/components/breadcumb.tsx +42 -0
- package/component-templates/components/count-down.tsx +94 -0
- package/component-templates/components/count-input.tsx +221 -0
- package/component-templates/components/date-range-calendar/button.tsx +61 -0
- package/component-templates/components/date-range-calendar/calendar.tsx +132 -0
- package/component-templates/components/date-range-calendar/date-input.tsx +259 -0
- package/component-templates/components/date-range-calendar/date-range-picker.tsx +594 -0
- package/component-templates/components/date-range-calendar/label.tsx +31 -0
- package/component-templates/components/date-range-calendar/popover.tsx +32 -0
- package/component-templates/components/date-range-calendar/select.tsx +125 -0
- package/component-templates/components/date-range-calendar/switch.tsx +30 -0
- package/component-templates/components/datetime-picker/button.tsx +61 -0
- package/component-templates/components/datetime-picker/calendar.tsx +156 -0
- package/component-templates/components/datetime-picker/datetime-picker.tsx +75 -0
- package/component-templates/components/datetime-picker/input.tsx +20 -0
- package/component-templates/components/datetime-picker/label.tsx +18 -0
- package/component-templates/components/datetime-picker/period-input.tsx +62 -0
- package/component-templates/components/datetime-picker/popover.tsx +32 -0
- package/component-templates/components/datetime-picker/select.tsx +125 -0
- package/component-templates/components/datetime-picker/time-picker-input.tsx +131 -0
- package/component-templates/components/datetime-picker/time-picker-utils.tsx +204 -0
- package/component-templates/components/datetime-picker/time-picker.tsx +59 -0
- package/component-templates/components/gradient-outline.tsx +233 -0
- package/component-templates/components/gradient-svg.tsx +157 -0
- package/component-templates/components/grid-layout.tsx +69 -0
- package/component-templates/components/hydrate-guard.tsx +40 -0
- package/component-templates/components/image.tsx +92 -0
- package/component-templates/components/loader-slash-gradient.tsx +85 -0
- package/component-templates/components/masonry-gallery.tsx +221 -0
- package/component-templates/components/modal.tsx +110 -0
- package/component-templates/components/multi-select.tsx +447 -0
- package/component-templates/components/non-hydration.tsx +27 -0
- package/component-templates/components/portal.tsx +34 -0
- package/component-templates/components/segments-circle.tsx +235 -0
- package/component-templates/components/single-select.tsx +248 -0
- package/component-templates/components/stroke-circle.tsx +57 -0
- package/component-templates/components/table/column-table.tsx +15 -0
- package/component-templates/components/table/data-table.tsx +339 -0
- package/component-templates/components/table/readme.tsx +95 -0
- package/component-templates/components/table/table.tsx +60 -0
- package/component-templates/components/text-hover-effect.tsx +120 -0
- package/component-templates/components/timout-loader.tsx +52 -0
- package/component-templates/components/toast.tsx +994 -0
- package/component-templates/configs/config.ts +33 -0
- package/component-templates/configs/feature-config.tsx +432 -0
- package/component-templates/configs/keys.ts +7 -0
- package/component-templates/core/api-service.ts +202 -0
- package/component-templates/core/calculate.ts +18 -0
- package/component-templates/core/idb.ts +166 -0
- package/component-templates/core/storage.ts +213 -0
- package/component-templates/hooks/count-down.ts +38 -0
- package/component-templates/hooks/fade-on-scroll.ts +52 -0
- package/component-templates/hooks/safe-action.ts +59 -0
- package/component-templates/hooks/spam-guard.ts +31 -0
- package/component-templates/lib/utils.ts +6 -0
- package/component-templates/providers/feature-guard.tsx +432 -0
- package/component-templates/queries/query.tsx +775 -0
- package/component-templates/utils/colors/color-by-text.ts +307 -0
- package/component-templates/utils/colors/stripe-effect.ts +100 -0
- package/component-templates/utils/hash/hash-aes.ts +35 -0
- package/components.json +348 -0
- package/package.json +60 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import unidecode from 'unidecode';
|
|
2
|
+
|
|
3
|
+
export const colorHexRegex = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
|
|
4
|
+
|
|
5
|
+
export type ColorAuto = "auto"
|
|
6
|
+
export type ColorType = "hex" | "rgb" | "hexa" | "rgba";
|
|
7
|
+
export type ColorFormat = ColorType | ColorAuto;
|
|
8
|
+
export type ConvertedExport = string | { hex: string; hexa: string; rgb: string; rgba: string }
|
|
9
|
+
/**
|
|
10
|
+
* The `convert` function converts a color string into different formats (hex, hexa, rgb, rgba).
|
|
11
|
+
* It supports parsing hex colors, RGB/RGBA colors, and allows for alpha channel adjustment.
|
|
12
|
+
* If the input is invalid, it returns the original input.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} input - The color string to convert.
|
|
15
|
+
* @param {ColorFormat} target - The target format to convert to (hex, hexa, rgb, rgba).
|
|
16
|
+
* @param {number} [alpha] - Optional alpha value for rgba/hexa formats.
|
|
17
|
+
* @returns {ConvertedExport} The converted color in the specified format.
|
|
18
|
+
*/
|
|
19
|
+
export const convert = (
|
|
20
|
+
input: string,
|
|
21
|
+
target: ColorFormat = "hex",
|
|
22
|
+
alpha?: number
|
|
23
|
+
): ConvertedExport => {
|
|
24
|
+
input = input.trim().toLowerCase();
|
|
25
|
+
|
|
26
|
+
let r = 0, g = 0, b = 0, a = 1;
|
|
27
|
+
|
|
28
|
+
// Parse HEX / HEXA
|
|
29
|
+
if (input.startsWith("#")) {
|
|
30
|
+
let hex = input.slice(1);
|
|
31
|
+
|
|
32
|
+
if (hex.length === 3) {
|
|
33
|
+
r = parseInt(hex[0] + hex[0], 16);
|
|
34
|
+
g = parseInt(hex[1] + hex[1], 16);
|
|
35
|
+
b = parseInt(hex[2] + hex[2], 16);
|
|
36
|
+
} else if (hex.length === 4) {
|
|
37
|
+
r = parseInt(hex[0] + hex[0], 16);
|
|
38
|
+
g = parseInt(hex[1] + hex[1], 16);
|
|
39
|
+
b = parseInt(hex[2] + hex[2], 16);
|
|
40
|
+
a = parseInt(hex[3] + hex[3], 16) / 255;
|
|
41
|
+
} else if (hex.length === 6) {
|
|
42
|
+
r = parseInt(hex.slice(0, 2), 16);
|
|
43
|
+
g = parseInt(hex.slice(2, 4), 16);
|
|
44
|
+
b = parseInt(hex.slice(4, 6), 16);
|
|
45
|
+
} else if (hex.length === 8) {
|
|
46
|
+
r = parseInt(hex.slice(0, 2), 16);
|
|
47
|
+
g = parseInt(hex.slice(2, 4), 16);
|
|
48
|
+
b = parseInt(hex.slice(4, 6), 16);
|
|
49
|
+
a = parseInt(hex.slice(6, 8), 16) / 255;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Parse rgb / rgba
|
|
54
|
+
else if (input.startsWith("rgb")) {
|
|
55
|
+
const nums = input.match(/[\d.]+/g)?.map(Number) || [];
|
|
56
|
+
[r, g, b] = nums;
|
|
57
|
+
if (input.startsWith("rgba")) a = nums[3] ?? 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// If alpha is provided, ensure it's within bounds
|
|
61
|
+
if (typeof alpha === "number") {
|
|
62
|
+
a = Math.min(1, Math.max(0, alpha));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Helper formatters
|
|
66
|
+
const toHex = () =>
|
|
67
|
+
"#" + [r, g, b].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
68
|
+
|
|
69
|
+
const toHexa = () =>
|
|
70
|
+
"#" +
|
|
71
|
+
[r, g, b, Math.round(a * 255)]
|
|
72
|
+
.map((x) => x.toString(16).padStart(2, "0"))
|
|
73
|
+
.join("");
|
|
74
|
+
|
|
75
|
+
const toRgb = () => `rgb(${r}, ${g}, ${b})`;
|
|
76
|
+
const toRgba = () => `rgba(${r}, ${g}, ${b}, ${a.toFixed(2)})`;
|
|
77
|
+
|
|
78
|
+
if (target === "auto") {
|
|
79
|
+
return {
|
|
80
|
+
hex: toHex(),
|
|
81
|
+
hexa: toHexa(),
|
|
82
|
+
rgb: toRgb(),
|
|
83
|
+
rgba: toRgba(),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
switch (target) {
|
|
88
|
+
case "hex":
|
|
89
|
+
return toHex();
|
|
90
|
+
case "hexa":
|
|
91
|
+
return toHexa();
|
|
92
|
+
case "rgb":
|
|
93
|
+
return toRgb();
|
|
94
|
+
case "rgba":
|
|
95
|
+
return toRgba();
|
|
96
|
+
default:
|
|
97
|
+
return input;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
*
|
|
104
|
+
* The `colorByText` function generates a color based on the input text.
|
|
105
|
+
* @param text - The `text` parameter is a string that represents the input text used to generate a color.
|
|
106
|
+
* It is used to create a unique color based on the characters in the text.
|
|
107
|
+
* @param alpha - The `alpha` parameter is a number that represents the alpha channel of the color. It determines the opacity of the color, where 0 is fully transparent and 1 is fully opaque. The default value is 1.
|
|
108
|
+
* @param type - The `type` parameter is a string that specifies the format of the color to be returned. It can be one of the following values: "hex", "rgb", "hexa", or "rgba". The default value is "hex".
|
|
109
|
+
* @returns {string} The `colorByText` function returns a string representing a color in the specified format (hex, rgb, hexa, rgba) based on the input text. If the text is empty or invalid, it defaults to white (#ffffff).
|
|
110
|
+
*/
|
|
111
|
+
export const colorByText = (text: string, alpha: number = 1, type: "hex" | "rgb" | "hexa" | "rgba" = "hex"): string => {
|
|
112
|
+
const latin = unidecode(text);
|
|
113
|
+
let c = ""
|
|
114
|
+
if(text.length === 0 || latin.length === 0) {
|
|
115
|
+
c = "#ffffff"; // Default to white if text is empty
|
|
116
|
+
return c;
|
|
117
|
+
}
|
|
118
|
+
if(type !== "hex" && type !== "rgb" && type !== "hexa" && type !== "rgba") {
|
|
119
|
+
console.error("Type must be 'hex', 'rgb', 'hexa', or 'rgba'");
|
|
120
|
+
c = "#ffffff"; // Default to white if type is invalid
|
|
121
|
+
return c;
|
|
122
|
+
}
|
|
123
|
+
if (latin && latin.length > 0 && latin.match(/[aeiouyAEIOUY]/)) {
|
|
124
|
+
const hash = Array.from(latin).reduce((acc, char) => {
|
|
125
|
+
const code = char.charCodeAt(0);
|
|
126
|
+
return (acc << 5) - acc + code;
|
|
127
|
+
}, 0);
|
|
128
|
+
|
|
129
|
+
const colorCode = (hash >>> 0).toString(16).padStart(6, "0").slice(0, 6);
|
|
130
|
+
|
|
131
|
+
let r = parseInt(colorCode.slice(0, 2), 16);
|
|
132
|
+
let g = parseInt(colorCode.slice(2, 4), 16);
|
|
133
|
+
let b = parseInt(colorCode.slice(4, 6), 16);
|
|
134
|
+
|
|
135
|
+
let pastelR = Math.min(255, Math.max(150, r + 55));
|
|
136
|
+
let pastelG = Math.min(255, Math.max(150, g + 55));
|
|
137
|
+
let pastelB = Math.min(255, Math.max(150, b + 55));
|
|
138
|
+
|
|
139
|
+
const adjustToDesiredHue = (
|
|
140
|
+
r: number,
|
|
141
|
+
g: number,
|
|
142
|
+
b: number
|
|
143
|
+
): [number, number, number] => {
|
|
144
|
+
if (r > g && r > b) {
|
|
145
|
+
return [0, Math.min(g, b), Math.max(g, b)]; // Green or purple
|
|
146
|
+
} else if (g > r && g > b) {
|
|
147
|
+
return [0, Math.max(0, g - 50), Math.min(b, g)]; // Green or blue
|
|
148
|
+
} else if (b > r && b > g) {
|
|
149
|
+
return [0, Math.min(r, g), Math.max(r, g)]; // Blue or purple
|
|
150
|
+
} else {
|
|
151
|
+
return [0, 0, Math.max(r, g, b)]; // Indigo
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Function to avoid cyan
|
|
156
|
+
const avoidCyan = (r: number, g: number, b: number): boolean => {
|
|
157
|
+
return g > 150 && b > 150 && r < 100; // Check if it's cyan
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
let adjustedR = pastelR;
|
|
161
|
+
let adjustedG = pastelG;
|
|
162
|
+
let adjustedB = pastelB;
|
|
163
|
+
|
|
164
|
+
while (avoidCyan(adjustedR, adjustedG, adjustedB)) {
|
|
165
|
+
adjustedG = Math.max(0, adjustedG - 10);
|
|
166
|
+
adjustedB = Math.max(0, adjustedB - 10);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const [finalR, finalG, finalB] = adjustToDesiredHue(
|
|
170
|
+
adjustedR,
|
|
171
|
+
adjustedG,
|
|
172
|
+
adjustedB
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const adjustedColor = `#${[finalR, finalG, finalB]
|
|
176
|
+
.map((x) => x.toString(16).padStart(2, "0"))
|
|
177
|
+
.join("")}`;
|
|
178
|
+
|
|
179
|
+
c = adjustedColor;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Convert to the desired format
|
|
183
|
+
return convert(c, type, alpha) as string;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The `brightness` function adjusts the brightness of a given color by a specified factor.
|
|
191
|
+
* It supports hex colors in the format #RRGGBB or #RGB, and returns the adjusted color in the same format.
|
|
192
|
+
* If the input color is invalid or the factor is out of bounds, it defaults to black (#000000).
|
|
193
|
+
* @param {string} color - The color to adjust, in hex format.
|
|
194
|
+
* @param {number} factor - The factor by which to adjust the brightness. Should be between -1 and 1.
|
|
195
|
+
* @param {number} [alpha=1] - Optional alpha value for rgba/hexa formats.
|
|
196
|
+
* @param {ColorType} [type="hex"] - The desired output format (hex, rgb, hexa, rgba).
|
|
197
|
+
* @returns {string} The adjusted color in the specified format.
|
|
198
|
+
*/
|
|
199
|
+
export const brightness = (
|
|
200
|
+
color: string,
|
|
201
|
+
factor: number,
|
|
202
|
+
alpha: number = 1,
|
|
203
|
+
type: ColorType = "hex"
|
|
204
|
+
): string => {
|
|
205
|
+
if (!colorHexRegex.test(color)) {
|
|
206
|
+
console.error("Only use hex colors in the format #RRGGBB or #RGB");
|
|
207
|
+
return "#000000"; // Default to black if invalid color format
|
|
208
|
+
};
|
|
209
|
+
if(factor > 1 || factor < -1) {
|
|
210
|
+
console.error("Factor must be between -1 and 1");
|
|
211
|
+
return "#000000"; // Default to black if factor is out of bounds
|
|
212
|
+
}
|
|
213
|
+
if (color) {
|
|
214
|
+
const hexToRgb = (hex: string): [number, number, number] => {
|
|
215
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
216
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
217
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
218
|
+
return [r, g, b];
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const rgbToHex = (r: number, g: number, b: number): string => {
|
|
222
|
+
return `#${[r, g, b]
|
|
223
|
+
.map((x) => Math.round(x).toString(16).padStart(2, "0"))
|
|
224
|
+
.join("")}`;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const [r, g, b] = hexToRgb(color);
|
|
228
|
+
|
|
229
|
+
const adjust = (value: number, factor: number): number => {
|
|
230
|
+
return Math.min(255, Math.max(0, value + factor * 255));
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const newR = adjust(r, factor);
|
|
234
|
+
const newG = adjust(g, factor);
|
|
235
|
+
const newB = adjust(b, factor);
|
|
236
|
+
|
|
237
|
+
return rgbToHex(newR, newG, newB);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// convert color format if needed
|
|
241
|
+
return convert(color, type, alpha) as string;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* The `gradientByAmount` function generates a radial gradient based on the provided amount.
|
|
247
|
+
* It returns a string representing the CSS gradient, which can be used in styles.
|
|
248
|
+
* @param {number} amount - The amount to determine the gradient. It should be a number.
|
|
249
|
+
* @returns {string} A string representing the radial gradient based on the amount.
|
|
250
|
+
*/
|
|
251
|
+
export const gradientByAmount = (amount: number): string => {
|
|
252
|
+
if(typeof amount !== 'number' || isNaN(amount)) {
|
|
253
|
+
console.error("Amount must be a valid number");
|
|
254
|
+
return "radial-gradient(circle at left top, #2a2a2a , #1a1a1a)";
|
|
255
|
+
}
|
|
256
|
+
let gradient: string;
|
|
257
|
+
|
|
258
|
+
if (amount <= 0) {
|
|
259
|
+
gradient = "radial-gradient(circle at left top, #2a2a2a , #1a1a1a)";
|
|
260
|
+
} else if (amount <= 1000) {
|
|
261
|
+
gradient = "radial-gradient(circle at left top, #f4ffa3 , #b28fff)";
|
|
262
|
+
} else if (amount <= 10000) {
|
|
263
|
+
gradient = "radial-gradient(circle at left top, #09d9e9 , #07c084)";
|
|
264
|
+
} else if (amount <= 50000) {
|
|
265
|
+
gradient = "radial-gradient(circle at left top, #85dbc2 , #e8e087)";
|
|
266
|
+
} else if (amount <= 100000) {
|
|
267
|
+
gradient = "radial-gradient(circle at left top, #fff58a , #ffa970)";
|
|
268
|
+
} else if (amount <= 500000) {
|
|
269
|
+
gradient = "radial-gradient(circle at left top, #ffe699 , #e594bb)";
|
|
270
|
+
} else {
|
|
271
|
+
gradient = "radial-gradient(circle at left top, #f0f0f0 , #bdbdbd)";
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return gradient;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* The `intensity` function generates a color based on the danger level.
|
|
281
|
+
* It returns a color string in the specified format (hex, rgb, hexa, rgba).
|
|
282
|
+
* @param {number} level - The danger level, should be between 0 and 100.
|
|
283
|
+
* @param {ColorType} type - The desired output format (hex, rgb, hexa, rgba).
|
|
284
|
+
* @param {number} [alpha] - Optional alpha value for rgba/hexa formats.
|
|
285
|
+
* @returns {string} The generated color string in the specified format.
|
|
286
|
+
*/
|
|
287
|
+
export const intensity = (
|
|
288
|
+
level: number,
|
|
289
|
+
type: ColorType = "hex",
|
|
290
|
+
alpha?: number
|
|
291
|
+
): string => {
|
|
292
|
+
if (level < 0 || level > 100) {
|
|
293
|
+
console.error("Intensity level must be between 0 and 100");
|
|
294
|
+
return "rgb(0, 0, 0)"; // Default to black if invalid
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Clamp 0-100
|
|
298
|
+
const lv = Math.min(100, Math.max(0, level));
|
|
299
|
+
const red = Math.round((lv / 100) * 255);
|
|
300
|
+
const green = Math.round((1 - lv / 100) * 255);
|
|
301
|
+
|
|
302
|
+
// Construct the base color
|
|
303
|
+
const baseColor = `rgb(${red}, ${green}, 0)`;
|
|
304
|
+
|
|
305
|
+
// convert to the specified type
|
|
306
|
+
return convert(baseColor, type, alpha) as string;
|
|
307
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export type MeshStop = {
|
|
2
|
+
color: string;
|
|
3
|
+
x: string; // example: "20%", "80%", "50%"
|
|
4
|
+
y: string; // example: "30%", "70%", "50%"
|
|
5
|
+
radius?: string; // example: "40%", "60%" (spread size)
|
|
6
|
+
};
|
|
7
|
+
export type GradientPatternType = "stripes" | "grid" | "checkerboard" | "mesh";
|
|
8
|
+
export type GradientPatternProps = {
|
|
9
|
+
type?: GradientPatternType;
|
|
10
|
+
angle?: number;
|
|
11
|
+
primaryColor?: string;
|
|
12
|
+
secondaryColor?: string;
|
|
13
|
+
primaryThickness?: string;
|
|
14
|
+
secondaryThickness?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Optional mesh stops for "mesh" type gradients
|
|
17
|
+
* Example: [{ color: "#ff0000", x: "50%", y: "50%", radius: "60%" }, ...]
|
|
18
|
+
* This is only used when type is "mesh"
|
|
19
|
+
*/
|
|
20
|
+
meshStops?: MeshStop[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const buildMesh = (stops: MeshStop[] = []): string => {
|
|
24
|
+
if (!stops.length) return "transparent";
|
|
25
|
+
|
|
26
|
+
return stops
|
|
27
|
+
.map(
|
|
28
|
+
(s) => `
|
|
29
|
+
radial-gradient(
|
|
30
|
+
circle at ${s.x} ${s.y},
|
|
31
|
+
${s.color},
|
|
32
|
+
transparent ${s.radius ?? "60%"}
|
|
33
|
+
)`
|
|
34
|
+
)
|
|
35
|
+
.join(",");
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Generates a gradient pattern based on the provided props.
|
|
42
|
+
* Supports "stripes", "grid", "checkerboard", and "mesh" types.
|
|
43
|
+
* Returns a string representing the CSS gradient pattern.
|
|
44
|
+
* @param {GradientPatternProps} props - Gradient pattern props (type, angle, primaryColor, secondaryColor, primaryThickness, secondaryThickness, meshStops)
|
|
45
|
+
* @returns {string} CSS gradient pattern string
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
export const gradientPattern = ({
|
|
49
|
+
type = "stripes",
|
|
50
|
+
angle = 135,
|
|
51
|
+
primaryColor = "#a22215",
|
|
52
|
+
secondaryColor = "#a22215aa",
|
|
53
|
+
primaryThickness = "8px",
|
|
54
|
+
secondaryThickness = "8px",
|
|
55
|
+
meshStops = [],
|
|
56
|
+
}: GradientPatternProps): string => {
|
|
57
|
+
const normalizeSize = (val: string | number) =>
|
|
58
|
+
typeof val === "number" ? `${val}px` : val;
|
|
59
|
+
|
|
60
|
+
const p = normalizeSize(primaryThickness);
|
|
61
|
+
const s = normalizeSize(secondaryThickness);
|
|
62
|
+
|
|
63
|
+
switch (type) {
|
|
64
|
+
case "stripes":
|
|
65
|
+
return `repeating-linear-gradient(${angle}deg,
|
|
66
|
+
${primaryColor} 0,
|
|
67
|
+
${primaryColor} ${p},
|
|
68
|
+
${secondaryColor} ${p},
|
|
69
|
+
${secondaryColor} calc(${p} + ${s}))`;
|
|
70
|
+
|
|
71
|
+
case "grid":
|
|
72
|
+
return `
|
|
73
|
+
repeating-linear-gradient(
|
|
74
|
+
0deg, ${primaryColor}, ${primaryColor} ${p}, transparent ${p}, transparent calc(${p} + ${s})
|
|
75
|
+
),
|
|
76
|
+
repeating-linear-gradient(
|
|
77
|
+
90deg, ${primaryColor}, ${primaryColor} ${p}, transparent ${p}, transparent calc(${p} + ${s})
|
|
78
|
+
)
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
case "checkerboard":
|
|
82
|
+
return `
|
|
83
|
+
repeating-linear-gradient(
|
|
84
|
+
45deg, ${primaryColor} 0, ${primaryColor} ${p}, ${secondaryColor} ${p}, ${secondaryColor} calc(${p} + ${s})
|
|
85
|
+
),
|
|
86
|
+
repeating-linear-gradient(
|
|
87
|
+
-45deg, ${primaryColor} 0, ${primaryColor} ${p}, ${secondaryColor} ${p}, ${secondaryColor} calc(${p} + ${s})
|
|
88
|
+
)
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
case "mesh":
|
|
92
|
+
// Mesh gradient (approx with multiple radial gradients)
|
|
93
|
+
return buildMesh(meshStops);
|
|
94
|
+
|
|
95
|
+
default:
|
|
96
|
+
return "transparent";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// const backgroundStyle = `repeating-linear-gradient(${angle}deg,${primaryColor} 0,${primaryColor} ${normalizeSize(primaryThickness)},${secondaryColor} ${normalizeSize(primaryThickness)},${secondaryColor} calc(${normalizeSize(primaryThickness)} + ${normalizeSize(secondaryThickness)}))`;
|
|
100
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as CryptoJS from 'crypto-js';
|
|
2
|
+
|
|
3
|
+
export type Base64UrlPattern = { plus?: string; slash?: string; pad?: string };
|
|
4
|
+
|
|
5
|
+
// --- Basic AES ---
|
|
6
|
+
export const encrypt = (text: string, key: string) =>
|
|
7
|
+
CryptoJS.AES.encrypt(text, key).toString();
|
|
8
|
+
|
|
9
|
+
export const decrypt = (encrypted: string, key: string) =>
|
|
10
|
+
CryptoJS.AES.decrypt(encrypted, key).toString(CryptoJS.enc.Utf8);
|
|
11
|
+
|
|
12
|
+
// --- AES + Base64 URL with custom pattern ---
|
|
13
|
+
export const encryptUrl = (text: string, key: string, pattern?: Base64UrlPattern) =>
|
|
14
|
+
base64UrlEncode(encrypt(text, key), pattern);
|
|
15
|
+
|
|
16
|
+
export const decryptUrl = (encrypted: string, key: string, pattern?: Base64UrlPattern) =>
|
|
17
|
+
decrypt(base64UrlDecode(encrypted, pattern), key);
|
|
18
|
+
|
|
19
|
+
// --- Base64 URL helpers with custom pattern ---
|
|
20
|
+
export const base64UrlEncode = (str: string, pattern: Base64UrlPattern = {}) => {
|
|
21
|
+
const { plus = "-", slash = "_", pad = "" } = pattern;
|
|
22
|
+
return CryptoJS.enc.Base64.parse(str)
|
|
23
|
+
.toString(CryptoJS.enc.Base64)
|
|
24
|
+
.replace(/\+/g, plus)
|
|
25
|
+
.replace(/\//g, slash)
|
|
26
|
+
.replace(/=+$/, pad);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const base64UrlDecode = (str: string, pattern: Base64UrlPattern = {}) => {
|
|
30
|
+
const { plus = "-", slash = "_", pad = "" } = pattern;
|
|
31
|
+
let base64 = str.replace(new RegExp(plus, "g"), "+").replace(new RegExp(slash, "g"), "/");
|
|
32
|
+
const missing = (4 - (base64.length % 4)) % 4;
|
|
33
|
+
base64 += pad.repeat(missing);
|
|
34
|
+
return base64;
|
|
35
|
+
};
|