@bouko/react 2.5.9 → 2.6.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 (128) hide show
  1. package/dist/colors/core.d.ts +10 -10
  2. package/dist/colors/core.js +25 -25
  3. package/dist/colors/index.d.ts +26 -26
  4. package/dist/colors/index.js +43 -43
  5. package/dist/colors/types.d.ts +11 -11
  6. package/dist/colors/types.js +7 -7
  7. package/dist/components/animate/configs.d.ts +136 -136
  8. package/dist/components/animate/configs.js +62 -62
  9. package/dist/components/animate/index.d.ts +54 -54
  10. package/dist/components/animate/index.js +33 -33
  11. package/dist/components/attachment.d.ts +2 -2
  12. package/dist/components/attachment.js +18 -18
  13. package/dist/components/button/icon.d.ts +9 -9
  14. package/dist/components/button/icon.js +21 -20
  15. package/dist/components/button/normal.d.ts +11 -11
  16. package/dist/components/button/normal.js +39 -39
  17. package/dist/components/carousel/index.d.ts +11 -11
  18. package/dist/components/carousel/index.js +19 -19
  19. package/dist/components/checkbox.d.ts +8 -8
  20. package/dist/components/checkbox.js +13 -13
  21. package/dist/components/dropdown/normal.d.ts +10 -10
  22. package/dist/components/dropdown/normal.js +19 -19
  23. package/dist/components/fade-carousel.d.ts +4 -4
  24. package/dist/components/fade-carousel.js +14 -14
  25. package/dist/components/field.d.ts +10 -10
  26. package/dist/components/field.js +10 -10
  27. package/dist/components/form/functions.d.ts +1 -1
  28. package/dist/components/form/functions.js +28 -28
  29. package/dist/components/form/types.d.ts +38 -38
  30. package/dist/components/form/types.js +1 -1
  31. package/dist/components/heading/normal.d.ts +29 -29
  32. package/dist/components/heading/normal.js +22 -22
  33. package/dist/components/heading/page.d.ts +25 -25
  34. package/dist/components/heading/page.js +23 -23
  35. package/dist/components/index.d.ts +13 -13
  36. package/dist/components/index.js +13 -13
  37. package/dist/components/input.d.ts +37 -37
  38. package/dist/components/input.js +40 -40
  39. package/dist/components/layout/fade.d.ts +7 -7
  40. package/dist/components/layout/fade.js +15 -15
  41. package/dist/components/layout/flex.d.ts +16 -16
  42. package/dist/components/layout/flex.js +42 -42
  43. package/dist/components/layout/separator.d.ts +3 -3
  44. package/dist/components/layout/separator.js +5 -5
  45. package/dist/components/list/index.d.ts +2 -2
  46. package/dist/components/list/index.js +2 -2
  47. package/dist/components/list/item.d.ts +9 -9
  48. package/dist/components/list/item.js +7 -7
  49. package/dist/components/list/variants/bullet.d.ts +9 -9
  50. package/dist/components/list/variants/bullet.js +16 -16
  51. package/dist/components/list/variants/number.d.ts +10 -10
  52. package/dist/components/list/variants/number.js +18 -18
  53. package/dist/components/multiple-choice.d.ts +2 -2
  54. package/dist/components/multiple-choice.js +12 -12
  55. package/dist/components/search-bar.d.ts +14 -13
  56. package/dist/components/search-bar.js +22 -22
  57. package/dist/components/select.d.ts +6 -6
  58. package/dist/components/select.js +24 -24
  59. package/dist/components/text/badge.d.ts +16 -16
  60. package/dist/components/text/badge.js +28 -28
  61. package/dist/components/textarea.d.ts +7 -7
  62. package/dist/components/textarea.js +11 -11
  63. package/dist/components/upload/file.d.ts +8 -8
  64. package/dist/components/upload/file.js +23 -23
  65. package/dist/components/waveform/index.d.ts +8 -8
  66. package/dist/components/waveform/index.js +11 -11
  67. package/dist/components/waveform/patterns.d.ts +1 -1
  68. package/dist/components/waveform/patterns.js +27 -27
  69. package/dist/core/classes.js +1 -1
  70. package/dist/core/format.d.ts +3 -3
  71. package/dist/core/format.js +34 -34
  72. package/dist/core/functions.d.ts +13 -13
  73. package/dist/core/functions.js +79 -79
  74. package/dist/core/types.d.ts +15 -15
  75. package/dist/core/types.js +2 -2
  76. package/dist/core/variants.d.ts +5 -5
  77. package/dist/core/variants.js +6 -6
  78. package/dist/format/index.d.ts +2 -2
  79. package/dist/format/index.js +33 -33
  80. package/dist/hooks/audio/sound.d.ts +1 -1
  81. package/dist/hooks/audio/sound.js +6 -6
  82. package/dist/hooks/clock/interval.d.ts +8 -8
  83. package/dist/hooks/clock/interval.js +25 -25
  84. package/dist/hooks/element/container.d.ts +5 -4
  85. package/dist/hooks/element/container.js +7 -7
  86. package/dist/hooks/element/index.d.ts +5 -0
  87. package/dist/hooks/element/index.js +9 -0
  88. package/dist/hooks/element/resize.d.ts +1 -1
  89. package/dist/hooks/element/resize.js +12 -12
  90. package/dist/hooks/index.d.ts +5 -4
  91. package/dist/hooks/index.js +5 -4
  92. package/dist/index.d.ts +14 -14
  93. package/dist/index.js +14 -14
  94. package/package.json +1 -1
  95. package/dist/assets/icons/check copy.svg +0 -6
  96. package/dist/assets/icons/check-circle copy.svg +0 -6
  97. package/dist/assets/icons/chevron copy.svg +0 -6
  98. package/dist/assets/icons/paperclip copy.svg +0 -6
  99. package/dist/assets/icons/spinner copy.svg +0 -6
  100. package/dist/assets/icons/x-circle copy.svg +0 -6
  101. package/dist/components/badge.d.ts +0 -5
  102. package/dist/components/badge.js +0 -4
  103. package/dist/components/button/ghost.d.ts +0 -7
  104. package/dist/components/button/ghost.js +0 -8
  105. package/dist/components/button/load.d.ts +0 -10
  106. package/dist/components/button/load.js +0 -35
  107. package/dist/components/button.d.ts +0 -10
  108. package/dist/components/button.js +0 -22
  109. package/dist/components/flex.d.ts +0 -16
  110. package/dist/components/flex.js +0 -8
  111. package/dist/components/form/builder.d.ts +0 -24
  112. package/dist/components/form/builder.js +0 -61
  113. package/dist/components/form/fields.d.ts +0 -16
  114. package/dist/components/form/fields.js +0 -21
  115. package/dist/components/form/footer.d.ts +0 -9
  116. package/dist/components/form/footer.js +0 -17
  117. package/dist/components/form/index.d.ts +0 -3
  118. package/dist/components/form/index.js +0 -3
  119. package/dist/components/form/loaders.d.ts +0 -3
  120. package/dist/components/form/loaders.js +0 -11
  121. package/dist/components/form/test-next.d.ts +0 -1
  122. package/dist/components/form/test-next.js +0 -6
  123. package/dist/components/layout/heading.d.ts +0 -31
  124. package/dist/components/layout/heading.js +0 -22
  125. package/dist/components/search/index.d.ts +0 -6
  126. package/dist/components/search/index.js +0 -12
  127. package/dist/hooks/color.d.ts +0 -7
  128. package/dist/hooks/color.js +0 -8
@@ -1,23 +1,23 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback } from "react";
3
- import { useDropzone } from "react-dropzone";
4
- import { cn } from "@bouko/style";
5
- import PaperClip from "../../assets/icons/paperclip.svg";
6
- export function FileUploader({ style, accept = [], update }) {
7
- const onDrop = useCallback((files) => {
8
- if (files.length > 0)
9
- update(files[0]);
10
- }, []);
11
- const { getRootProps, getInputProps, isDragActive, inputRef } = useDropzone({
12
- onDrop
13
- });
14
- const upload = () => inputRef.current?.click();
15
- const save = (e) => update((e.target.files ?? [])[0]);
16
- return (_jsxs("div", { className: cn(styles.container, isDragActive && "bg-background-light/40 border-border-light", style), onClick: upload, ...getRootProps(), children: [_jsxs("span", { className: styles.title, children: [_jsx(PaperClip, {}), "Drag and drop a file, or"] }), _jsx("span", { className: styles.subtitle, children: "browse" }), _jsx("input", { type: "file", className: "hidden", onChange: save, accept: accept.join(","), multiple: false, ...getInputProps() })] }));
17
- }
18
- const styles = {
19
- container: "flex flex-col justify-center items-center gap-1 w-full py-3 hover:bg-background-light/40 border-2 border-dashed border-border hover:border-border-light rounded overflow-hidden duration-200 cursor-pointer",
20
- title: "flex gap-2 items-center font-semibold text-sm",
21
- subtitle: "text-xs text-primary-darker"
22
- };
23
- export default FileUploader;
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback } from "react";
3
+ import { useDropzone } from "react-dropzone";
4
+ import { cn } from "@bouko/style";
5
+ import PaperClip from "../../assets/icons/paperclip.svg";
6
+ export function FileUploader({ style, accept = [], update }) {
7
+ const onDrop = useCallback((files) => {
8
+ if (files.length > 0)
9
+ update(files[0]);
10
+ }, []);
11
+ const { getRootProps, getInputProps, isDragActive, inputRef } = useDropzone({
12
+ onDrop
13
+ });
14
+ const upload = () => inputRef.current?.click();
15
+ const save = (e) => update((e.target.files ?? [])[0]);
16
+ return (_jsxs("div", { className: cn(styles.container, isDragActive && "bg-background-light/40 border-border-light", style), onClick: upload, ...getRootProps(), children: [_jsxs("span", { className: styles.title, children: [_jsx(PaperClip, {}, void 0), "Drag and drop a file, or"] }, void 0), _jsx("span", { className: styles.subtitle, children: "browse" }, void 0), _jsx("input", { type: "file", className: "hidden", onChange: save, accept: accept.join(","), multiple: false, ...getInputProps() }, void 0)] }, void 0));
17
+ }
18
+ const styles = {
19
+ container: "flex flex-col justify-center items-center gap-1 w-full py-3 hover:bg-background-light/40 border-2 border-dashed border-border hover:border-border-light rounded overflow-hidden duration-200 cursor-pointer",
20
+ title: "flex gap-2 items-center font-semibold text-sm",
21
+ subtitle: "text-xs text-primary-darker"
22
+ };
23
+ export default FileUploader;
@@ -1,8 +1,8 @@
1
- import { type GenericPlugin } from "wavesurfer.js/dist/base-plugin";
2
- type Props = {
3
- file: File;
4
- height: number;
5
- plugins: GenericPlugin[];
6
- };
7
- export default function Waveform({ file, height, plugins }: Props): import("react/jsx-runtime").JSX.Element;
8
- export {};
1
+ import { type GenericPlugin } from "wavesurfer.js/dist/base-plugin";
2
+ declare type Props = {
3
+ file: File;
4
+ height: number;
5
+ plugins: GenericPlugin[];
6
+ };
7
+ export default function Waveform({ file, height, plugins }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -1,11 +1,11 @@
1
- "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useMemo } from "react";
4
- import { squiggly } from "./patterns";
5
- import { default as Player } from "@wavesurfer/react";
6
- export default function Waveform({ file, height, plugins }) {
7
- const url = useMemo(() => URL.createObjectURL(file), [file]);
8
- const plugins2 = useMemo(() => plugins, [plugins]);
9
- const waves = useMemo(() => squiggly, []);
10
- return (_jsx(Player, { height: height, url: url, waveColor: "#1c1d23", progressColor: "#0085e4", cursorWidth: 2, renderFunction: waves, plugins: plugins2 }));
11
- }
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useMemo } from "react";
4
+ import { squiggly } from "./patterns";
5
+ import { default as Player } from "@wavesurfer/react";
6
+ export default function Waveform({ file, height, plugins }) {
7
+ const url = useMemo(() => URL.createObjectURL(file), [file]);
8
+ const plugins2 = useMemo(() => plugins, [plugins]);
9
+ const waves = useMemo(() => squiggly, []);
10
+ return (_jsx(Player, { height: height, url: url, waveColor: "#1c1d23", progressColor: "#0085e4", cursorWidth: 2, renderFunction: waves, plugins: plugins2 }, void 0));
11
+ }
@@ -1 +1 @@
1
- export declare function squiggly(channels: (Float32Array | number[])[], ctx: CanvasRenderingContext2D): void;
1
+ export declare function squiggly(channels: (Float32Array | number[])[], ctx: CanvasRenderingContext2D): void;
@@ -1,27 +1,27 @@
1
- export function squiggly(channels, ctx) {
2
- const { width, height } = ctx.canvas;
3
- const scale = channels[0].length / width;
4
- const step = 12;
5
- ctx.translate(0, height / 2);
6
- ctx.strokeStyle = ctx.fillStyle;
7
- ctx.lineWidth = 3;
8
- ctx.beginPath();
9
- for (let i = 0; i < width; i += step * 2) {
10
- const index = Math.floor(i * scale);
11
- const value = Math.abs(channels[0][index]);
12
- let x = i;
13
- let y = value * height;
14
- ctx.moveTo(x, 0);
15
- ctx.lineTo(x, y);
16
- ctx.arc(x + step / 2, y, step / 2, Math.PI, 0, true);
17
- ctx.lineTo(x + step, 0);
18
- x = x + step;
19
- y = -y;
20
- ctx.moveTo(x, 0);
21
- ctx.lineTo(x, y);
22
- ctx.arc(x + step / 2, y, step / 2, Math.PI, 0, false);
23
- ctx.lineTo(x + step, 0);
24
- }
25
- ctx.stroke();
26
- ctx.closePath();
27
- }
1
+ export function squiggly(channels, ctx) {
2
+ const { width, height } = ctx.canvas;
3
+ const scale = channels[0].length / width;
4
+ const step = 12;
5
+ ctx.translate(0, height / 2);
6
+ ctx.strokeStyle = ctx.fillStyle;
7
+ ctx.lineWidth = 3;
8
+ ctx.beginPath();
9
+ for (let i = 0; i < width; i += step * 2) {
10
+ const index = Math.floor(i * scale);
11
+ const value = Math.abs(channels[0][index]);
12
+ let x = i;
13
+ let y = value * height;
14
+ ctx.moveTo(x, 0);
15
+ ctx.lineTo(x, y);
16
+ ctx.arc(x + step / 2, y, step / 2, Math.PI, 0, true);
17
+ ctx.lineTo(x + step, 0);
18
+ x = x + step;
19
+ y = -y;
20
+ ctx.moveTo(x, 0);
21
+ ctx.lineTo(x, y);
22
+ ctx.arc(x + step / 2, y, step / 2, Math.PI, 0, false);
23
+ ctx.lineTo(x + step, 0);
24
+ }
25
+ ctx.stroke();
26
+ ctx.closePath();
27
+ }
@@ -1 +1 @@
1
- "use strict";
1
+ "use strict";
@@ -1,3 +1,3 @@
1
- import { ReactNode } from "react";
2
- export declare const rn: (...elements: ReactNode[]) => import("react/jsx-runtime").JSX.Element;
3
- export declare const formatText: (text: string) => import("react/jsx-runtime").JSX.Element;
1
+ import { ReactNode } from "react";
2
+ export declare const rn: (...elements: ReactNode[]) => import("react/jsx-runtime").JSX.Element;
3
+ export declare const formatText: (text: string) => import("react/jsx-runtime").JSX.Element;
@@ -1,34 +1,34 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Fragment } from "react";
3
- const delimiterConfig = [
4
- { delimiter: "**", render: (text, key) => _jsx("span", { className: "font-bold", children: text }, key) },
5
- { delimiter: "~~", render: (text, key) => _jsx("span", { className: "font-semibold", children: text }, key) },
6
- { delimiter: "^^", render: (text, key) => _jsx("span", { className: "text-accent", children: text }, key) },
7
- ];
8
- const escapeRegex = (str) => str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
9
- const delimiters = delimiterConfig.map(({ delimiter }) => escapeRegex(delimiter) + ".*?" + escapeRegex(delimiter)).join("|");
10
- const WRAPPED_TEXT_REGEX = new RegExp(`(${delimiters})`, "g");
11
- export const rn = (...elements) => (_jsx(Fragment, { children: elements.map((x, i) => (_jsx(Fragment, { children: x }, i))) }));
12
- const isWrapped = (x, wrapper) => x.startsWith(wrapper) && x.endsWith(wrapper);
13
- export const formatText = (text) => {
14
- const parts = text
15
- .split(WRAPPED_TEXT_REGEX)
16
- .filter(Boolean);
17
- const formatted = parts.map((x, i) => {
18
- if (isWrapped(x, "**")) {
19
- // Remove only the first and last occurrence of the delimiter
20
- const content = x.slice(2, -2);
21
- return _jsx("span", { className: "font-bold", children: content }, i);
22
- }
23
- else if (isWrapped(x, "~~")) {
24
- const content = x.slice(2, -2);
25
- return _jsx("span", { className: "font-semibold", children: content }, i);
26
- }
27
- else if (isWrapped(x, "^^")) {
28
- const content = x.slice(2, -2);
29
- return _jsx("span", { className: "text-accent", children: content }, i);
30
- }
31
- return x;
32
- });
33
- return _jsx("span", { children: formatted });
34
- };
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Fragment } from "react";
3
+ const delimiterConfig = [
4
+ { delimiter: "**", render: (text, key) => _jsx("span", { className: "font-bold", children: text }, key) },
5
+ { delimiter: "~~", render: (text, key) => _jsx("span", { className: "font-semibold", children: text }, key) },
6
+ { delimiter: "^^", render: (text, key) => _jsx("span", { className: "text-accent", children: text }, key) },
7
+ ];
8
+ const escapeRegex = (str) => str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
9
+ const delimiters = delimiterConfig.map(({ delimiter }) => escapeRegex(delimiter) + ".*?" + escapeRegex(delimiter)).join("|");
10
+ const WRAPPED_TEXT_REGEX = new RegExp(`(${delimiters})`, "g");
11
+ export const rn = (...elements) => (_jsx(Fragment, { children: elements.map((x, i) => (_jsx(Fragment, { children: x }, i))) }, void 0));
12
+ const isWrapped = (x, wrapper) => x.startsWith(wrapper) && x.endsWith(wrapper);
13
+ export const formatText = (text) => {
14
+ const parts = text
15
+ .split(WRAPPED_TEXT_REGEX)
16
+ .filter(Boolean);
17
+ const formatted = parts.map((x, i) => {
18
+ if (isWrapped(x, "**")) {
19
+ // Remove only the first and last occurrence of the delimiter
20
+ const content = x.slice(2, -2);
21
+ return _jsx("span", { className: "font-bold", children: content }, i);
22
+ }
23
+ else if (isWrapped(x, "~~")) {
24
+ const content = x.slice(2, -2);
25
+ return _jsx("span", { className: "font-semibold", children: content }, i);
26
+ }
27
+ else if (isWrapped(x, "^^")) {
28
+ const content = x.slice(2, -2);
29
+ return _jsx("span", { className: "text-accent", children: content }, i);
30
+ }
31
+ return x;
32
+ });
33
+ return _jsx("span", { children: formatted }, void 0);
34
+ };
@@ -1,13 +1,13 @@
1
- export declare const getFilesData: (files: File[]) => Promise<{
2
- filename: string;
3
- mimetype: string;
4
- data?: string;
5
- }[]>;
6
- export declare const getFileData: (file: File) => Promise<{
7
- filename: string;
8
- mimetype: string;
9
- data?: string;
10
- }>;
11
- export declare const bufferToFile: (buffer: ArrayBuffer, name?: string) => Promise<File>;
12
- export declare const getAudioDuration: (file: File) => Promise<number>;
13
- export declare function getBase64(image: string): Promise<string>;
1
+ export declare const getFilesData: (files: File[]) => Promise<{
2
+ filename: string;
3
+ mimetype: string;
4
+ data?: string | undefined;
5
+ }[]>;
6
+ export declare const getFileData: (file: File) => Promise<{
7
+ filename: string;
8
+ mimetype: string;
9
+ data?: string | undefined;
10
+ }>;
11
+ export declare const bufferToFile: (buffer: ArrayBuffer, name?: string | undefined) => Promise<File>;
12
+ export declare const getAudioDuration: (file: File) => Promise<number>;
13
+ export declare function getBase64(image: string): Promise<string>;
@@ -1,79 +1,79 @@
1
- import { fileTypeFromBuffer } from "file-type";
2
- export const getFilesData = (files) => Promise.all(files.map((file) => {
3
- return new Promise((resolve, reject) => {
4
- const reader = new FileReader();
5
- reader.onload = () => {
6
- const base64 = reader.result?.toString().split(",")[1]; // Remove data prefix
7
- return resolve({
8
- filename: file.name,
9
- mimetype: file.type,
10
- data: base64,
11
- });
12
- };
13
- reader.onerror = reject;
14
- reader.readAsDataURL(file);
15
- });
16
- }));
17
- export const getFileData = (file) => new Promise((resolve, reject) => {
18
- const reader = new FileReader();
19
- reader.onload = () => {
20
- const base64 = reader.result?.toString().split(",")[1]; // Remove data prefix
21
- return resolve({
22
- filename: file.name,
23
- mimetype: file.type,
24
- data: base64,
25
- });
26
- };
27
- reader.onerror = reject;
28
- reader.readAsDataURL(file);
29
- });
30
- async function detectFileExtension(buffer) {
31
- const type = await fileTypeFromBuffer(buffer);
32
- if (!type)
33
- return null;
34
- return type;
35
- }
36
- export const bufferToFile = async (buffer, name) => {
37
- const type = await detectFileExtension(buffer);
38
- if (!type)
39
- throw new Error("Couldn't get type from buffer");
40
- return new File([buffer], `${name ?? "file"}.${type.ext}`, {
41
- type: type.mime,
42
- lastModified: Date.now()
43
- });
44
- };
45
- export const getAudioDuration = (file) => {
46
- return new Promise((resolve, reject) => {
47
- const url = URL.createObjectURL(file);
48
- const audio = new Audio(url);
49
- audio.addEventListener("loadedmetadata", () => {
50
- const durationMs = audio.duration * 1000;
51
- URL.revokeObjectURL(url);
52
- resolve(durationMs);
53
- });
54
- audio.addEventListener("error", (e) => {
55
- URL.revokeObjectURL(url);
56
- reject(new Error("Failed to load audio metadata"));
57
- });
58
- });
59
- };
60
- export async function getBase64(image) {
61
- if (image.startsWith("data:")) {
62
- return image; // already a base64 data URL
63
- }
64
- const res = await fetch(image);
65
- const blob = await res.blob();
66
- return new Promise((resolve, reject) => {
67
- const reader = new FileReader();
68
- reader.onloadend = () => {
69
- if (typeof reader.result === "string") {
70
- resolve(reader.result);
71
- }
72
- else {
73
- reject(new Error("Failed to read image as base64"));
74
- }
75
- };
76
- reader.onerror = reject;
77
- reader.readAsDataURL(blob);
78
- });
79
- }
1
+ import { fileTypeFromBuffer } from "file-type";
2
+ export const getFilesData = (files) => Promise.all(files.map((file) => {
3
+ return new Promise((resolve, reject) => {
4
+ const reader = new FileReader();
5
+ reader.onload = () => {
6
+ const base64 = reader.result?.toString().split(",")[1]; // Remove data prefix
7
+ return resolve({
8
+ filename: file.name,
9
+ mimetype: file.type,
10
+ data: base64,
11
+ });
12
+ };
13
+ reader.onerror = reject;
14
+ reader.readAsDataURL(file);
15
+ });
16
+ }));
17
+ export const getFileData = (file) => new Promise((resolve, reject) => {
18
+ const reader = new FileReader();
19
+ reader.onload = () => {
20
+ const base64 = reader.result?.toString().split(",")[1]; // Remove data prefix
21
+ return resolve({
22
+ filename: file.name,
23
+ mimetype: file.type,
24
+ data: base64,
25
+ });
26
+ };
27
+ reader.onerror = reject;
28
+ reader.readAsDataURL(file);
29
+ });
30
+ async function detectFileExtension(buffer) {
31
+ const type = await fileTypeFromBuffer(buffer);
32
+ if (!type)
33
+ return null;
34
+ return type;
35
+ }
36
+ export const bufferToFile = async (buffer, name) => {
37
+ const type = await detectFileExtension(buffer);
38
+ if (!type)
39
+ throw new Error("Couldn't get type from buffer");
40
+ return new File([buffer], `${name ?? "file"}.${type.ext}`, {
41
+ type: type.mime,
42
+ lastModified: Date.now()
43
+ });
44
+ };
45
+ export const getAudioDuration = (file) => {
46
+ return new Promise((resolve, reject) => {
47
+ const url = URL.createObjectURL(file);
48
+ const audio = new Audio(url);
49
+ audio.addEventListener("loadedmetadata", () => {
50
+ const durationMs = audio.duration * 1000;
51
+ URL.revokeObjectURL(url);
52
+ resolve(durationMs);
53
+ });
54
+ audio.addEventListener("error", (e) => {
55
+ URL.revokeObjectURL(url);
56
+ reject(new Error("Failed to load audio metadata"));
57
+ });
58
+ });
59
+ };
60
+ export async function getBase64(image) {
61
+ if (image.startsWith("data:")) {
62
+ return image; // already a base64 data URL
63
+ }
64
+ const res = await fetch(image);
65
+ const blob = await res.blob();
66
+ return new Promise((resolve, reject) => {
67
+ const reader = new FileReader();
68
+ reader.onloadend = () => {
69
+ if (typeof reader.result === "string") {
70
+ resolve(reader.result);
71
+ }
72
+ else {
73
+ reject(new Error("Failed to read image as base64"));
74
+ }
75
+ };
76
+ reader.onerror = reject;
77
+ reader.readAsDataURL(blob);
78
+ });
79
+ }
@@ -1,15 +1,15 @@
1
- import type { ReactNode } from "react";
2
- /**
3
- * Common props for React components.
4
- *
5
- * @property `Component` - Component with Tailwind style(s) and children.
6
- * @property `Clickable` - Component that executes a callback when clicked.
7
- **/
8
- export type Component = {
9
- style?: string;
10
- children?: ReactNode;
11
- };
12
- export type Clickable = {
13
- action?: () => void;
14
- disabled?: boolean;
15
- };
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * Common props for React components.
4
+ *
5
+ * @property `Component` - Component with Tailwind style(s) and children.
6
+ * @property `Clickable` - Component that executes a callback when clicked.
7
+ **/
8
+ export declare type Component = {
9
+ style?: string;
10
+ children?: ReactNode;
11
+ };
12
+ export declare type Clickable = {
13
+ action?: () => void;
14
+ disabled?: boolean;
15
+ };
@@ -1,2 +1,2 @@
1
- export {};
2
- // clean
1
+ export {};
2
+ // clean
@@ -1,5 +1,5 @@
1
- /**
2
- * Creates a highly customizable variant config
3
- * for Tailwind styles using `tailwind-variants`.
4
- **/
5
- export { tv } from "tailwind-variants";
1
+ /**
2
+ * Creates a highly customizable variant config
3
+ * for Tailwind styles using `tailwind-variants`.
4
+ **/
5
+ export { tv } from "tailwind-variants";
@@ -1,6 +1,6 @@
1
- /**
2
- * Creates a highly customizable variant config
3
- * for Tailwind styles using `tailwind-variants`.
4
- **/
5
- export { tv } from "tailwind-variants";
6
- // clean
1
+ /**
2
+ * Creates a highly customizable variant config
3
+ * for Tailwind styles using `tailwind-variants`.
4
+ **/
5
+ export { tv } from "tailwind-variants";
6
+ // clean
@@ -1,2 +1,2 @@
1
- export declare const cap: (x: string) => string;
2
- export declare const formatText: (text: string) => import("react/jsx-runtime").JSX.Element;
1
+ export declare const cap: (x: string) => string;
2
+ export declare const formatText: (text: string) => import("react/jsx-runtime").JSX.Element;
@@ -1,33 +1,33 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- const delimiterConfig = [
3
- { delimiter: "**", render: (text, key) => _jsx("span", { className: "font-bold", children: text }, key) },
4
- { delimiter: "~~", render: (text, key) => _jsx("span", { className: "font-semibold", children: text }, key) },
5
- { delimiter: "^^", render: (text, key) => _jsx("span", { className: "text-accent", children: text }, key) },
6
- ];
7
- const escapeRegex = (str) => str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
8
- const delimiters = delimiterConfig.map(({ delimiter }) => escapeRegex(delimiter) + ".*?" + escapeRegex(delimiter)).join("|");
9
- const WRAPPED_TEXT_REGEX = new RegExp(`(${delimiters})`, "g");
10
- const isWrapped = (x, wrapper) => x.startsWith(wrapper) && x.endsWith(wrapper);
11
- export const cap = (x) => x.charAt(0).toUpperCase() + x.slice(1, x.length);
12
- export const formatText = (text) => {
13
- const parts = text
14
- .split(WRAPPED_TEXT_REGEX)
15
- .filter(Boolean);
16
- const formatted = parts.map((x, i) => {
17
- if (isWrapped(x, "**")) {
18
- // Remove only the first and last occurrence of the delimiter
19
- const content = x.slice(2, -2);
20
- return _jsx("span", { className: "font-bold", children: content }, i);
21
- }
22
- else if (isWrapped(x, "~~")) {
23
- const content = x.slice(2, -2);
24
- return _jsx("span", { className: "font-semibold", children: content }, i);
25
- }
26
- else if (isWrapped(x, "^^")) {
27
- const content = x.slice(2, -2);
28
- return _jsx("span", { className: "text-accent", children: content }, i);
29
- }
30
- return x;
31
- });
32
- return _jsx("span", { children: formatted });
33
- };
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const delimiterConfig = [
3
+ { delimiter: "**", render: (text, key) => _jsx("span", { className: "font-bold", children: text }, key) },
4
+ { delimiter: "~~", render: (text, key) => _jsx("span", { className: "font-semibold", children: text }, key) },
5
+ { delimiter: "^^", render: (text, key) => _jsx("span", { className: "text-accent", children: text }, key) },
6
+ ];
7
+ const escapeRegex = (str) => str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
8
+ const delimiters = delimiterConfig.map(({ delimiter }) => escapeRegex(delimiter) + ".*?" + escapeRegex(delimiter)).join("|");
9
+ const WRAPPED_TEXT_REGEX = new RegExp(`(${delimiters})`, "g");
10
+ const isWrapped = (x, wrapper) => x.startsWith(wrapper) && x.endsWith(wrapper);
11
+ export const cap = (x) => x.charAt(0).toUpperCase() + x.slice(1, x.length);
12
+ export const formatText = (text) => {
13
+ const parts = text
14
+ .split(WRAPPED_TEXT_REGEX)
15
+ .filter(Boolean);
16
+ const formatted = parts.map((x, i) => {
17
+ if (isWrapped(x, "**")) {
18
+ // Remove only the first and last occurrence of the delimiter
19
+ const content = x.slice(2, -2);
20
+ return _jsx("span", { className: "font-bold", children: content }, i);
21
+ }
22
+ else if (isWrapped(x, "~~")) {
23
+ const content = x.slice(2, -2);
24
+ return _jsx("span", { className: "font-semibold", children: content }, i);
25
+ }
26
+ else if (isWrapped(x, "^^")) {
27
+ const content = x.slice(2, -2);
28
+ return _jsx("span", { className: "text-accent", children: content }, i);
29
+ }
30
+ return x;
31
+ });
32
+ return _jsx("span", { children: formatted }, void 0);
33
+ };
@@ -1 +1 @@
1
- export default function useSound(filename?: string): import("use-sound/dist/types").PlayFunction | undefined;
1
+ export default function useSound(filename?: string): import("use-sound/dist/types").PlayFunction | undefined;
@@ -1,6 +1,6 @@
1
- import { default as base } from "use-sound";
2
- export default function useSound(filename) {
3
- if (!filename)
4
- return;
5
- return base(filename)[0];
6
- }
1
+ import { default as base } from "use-sound";
2
+ export default function useSound(filename) {
3
+ if (!filename)
4
+ return;
5
+ return base(filename)[0];
6
+ }
@@ -1,8 +1,8 @@
1
- type Props = {
2
- action: () => Promise<boolean | void>;
3
- duration: number;
4
- deps: unknown[];
5
- oops?: (x: string) => void;
6
- };
7
- export default function useInterval({ action, duration, deps, oops }: Props): void;
8
- export {};
1
+ declare type Props = {
2
+ action: () => Promise<boolean | void>;
3
+ duration: number;
4
+ deps: unknown[];
5
+ oops?: (x: string) => void;
6
+ };
7
+ export default function useInterval({ action, duration, deps, oops }: Props): void;
8
+ export {};
@@ -1,25 +1,25 @@
1
- "use client";
2
- import { useEffect, useRef } from "react";
3
- export default function useInterval({ action, duration, deps = [], oops }) {
4
- const ref = useRef(async () => false);
5
- useEffect(() => {
6
- ref.current = action;
7
- }, [action]);
8
- useEffect(() => {
9
- if (deps.some(v => v === undefined || v === null))
10
- return;
11
- const tick = async () => {
12
- try {
13
- const stop = await ref.current();
14
- if (stop && id)
15
- clearInterval(id);
16
- }
17
- catch (err) {
18
- oops?.(err.message);
19
- }
20
- };
21
- const id = setInterval(tick, duration);
22
- tick();
23
- return () => clearInterval(id);
24
- }, [duration, ...deps]);
25
- }
1
+ "use client";
2
+ import { useEffect, useRef } from "react";
3
+ export default function useInterval({ action, duration, deps = [], oops }) {
4
+ const ref = useRef(async () => false);
5
+ useEffect(() => {
6
+ ref.current = action;
7
+ }, [action]);
8
+ useEffect(() => {
9
+ if (deps.some(v => v === undefined || v === null))
10
+ return;
11
+ const tick = async () => {
12
+ try {
13
+ const stop = await ref.current();
14
+ if (stop && id)
15
+ clearInterval(id);
16
+ }
17
+ catch (err) {
18
+ oops?.(err.message);
19
+ }
20
+ };
21
+ const id = setInterval(tick, duration);
22
+ tick();
23
+ return () => clearInterval(id);
24
+ }, [duration, ...deps]);
25
+ }