@soyfri/shared-library 1.4.1 → 1.4.2

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.
@@ -4,68 +4,78 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const material = require("@mui/material");
6
6
  function useClipboard(options) {
7
+ var _a;
7
8
  const elementRef = React.useRef(null);
8
9
  const [snackbarOpen, setSnackbarOpen] = React.useState(false);
9
10
  const [snackbarMessage, setSnackbarMessage] = React.useState((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
10
11
  const [snackbarSeverity, setSnackbarSeverity] = React.useState((options == null ? void 0 : options.severity) || "success");
11
12
  const [snackbarPosition, setSnackbarPosition] = React.useState((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
12
- const [snackbarDuration, setSnackbarDuration] = React.useState((options == null ? void 0 : options.duration) || 3e3);
13
+ const [snackbarDuration, setSnackbarDuration] = React.useState((_a = options == null ? void 0 : options.duration) != null ? _a : 3e3);
13
14
  const handleSnackbarClose = React.useCallback((event, reason) => {
14
15
  if (reason === "clickaway") {
15
16
  return;
16
17
  }
17
18
  setSnackbarOpen(false);
18
19
  }, []);
19
- const copyText = React.useCallback(() => {
20
- if (elementRef.current) {
21
- try {
20
+ const executeCopy = React.useCallback((text) => {
21
+ var _a2, _b;
22
+ try {
23
+ if (navigator.clipboard && window.isSecureContext) {
24
+ navigator.clipboard.writeText(text);
25
+ } else {
22
26
  const textarea = document.createElement("textarea");
23
- textarea.value = elementRef.current.innerText || "";
27
+ textarea.value = text;
24
28
  document.body.appendChild(textarea);
25
29
  textarea.select();
26
30
  document.execCommand("copy");
27
31
  document.body.removeChild(textarea);
28
- setSnackbarMessage((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
29
- setSnackbarSeverity((options == null ? void 0 : options.severity) || "success");
30
- setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
31
- setSnackbarDuration((options == null ? void 0 : options.duration) || 3e3);
32
- setSnackbarOpen(true);
33
- } catch (err) {
34
- console.error("Error al copiar al portapapeles:", err);
35
- setSnackbarMessage("Error al copiar.");
36
- setSnackbarSeverity("error");
37
- setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
38
- setSnackbarDuration((options == null ? void 0 : options.duration) || 3e3);
39
- setSnackbarOpen(true);
40
32
  }
33
+ setSnackbarMessage((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
34
+ setSnackbarSeverity((options == null ? void 0 : options.severity) || "success");
35
+ setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
36
+ setSnackbarDuration((_a2 = options == null ? void 0 : options.duration) != null ? _a2 : 3e3);
37
+ setSnackbarOpen(true);
38
+ } catch (err) {
39
+ console.error("Error al copiar al portapapeles:", err);
40
+ setSnackbarMessage("Error al copiar.");
41
+ setSnackbarSeverity("error");
42
+ setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
43
+ setSnackbarDuration((_b = options == null ? void 0 : options.duration) != null ? _b : 3e3);
44
+ setSnackbarOpen(true);
41
45
  }
42
46
  }, [options]);
47
+ const copyFromRef = React.useCallback(() => {
48
+ if (elementRef.current) {
49
+ const textToCopy = elementRef.current.innerText || "";
50
+ executeCopy(textToCopy);
51
+ }
52
+ }, [executeCopy]);
43
53
  React.useEffect(() => {
44
54
  const currentElement = elementRef.current;
45
55
  if (currentElement) {
46
56
  currentElement.style.cursor = "pointer";
47
- currentElement.addEventListener("click", copyText);
57
+ currentElement.addEventListener("click", copyFromRef);
48
58
  }
49
59
  return () => {
50
60
  if (currentElement) {
51
- currentElement.removeEventListener("click", copyText);
61
+ currentElement.removeEventListener("click", copyFromRef);
52
62
  }
53
63
  };
54
- }, [copyText]);
55
- const CopyMessage = () => /* @__PURE__ */ jsxRuntime.jsx(
56
- material.Snackbar,
57
- {
58
- open: snackbarOpen,
59
- autoHideDuration: snackbarDuration,
60
- onClose: handleSnackbarClose,
61
- anchorOrigin: {
62
- vertical: snackbarPosition.vertical,
63
- horizontal: snackbarPosition.horizontal
64
- },
65
- children: /* @__PURE__ */ jsxRuntime.jsx(material.Alert, { onClose: handleSnackbarClose, severity: snackbarSeverity, sx: { width: "100%" }, children: snackbarMessage })
66
- }
67
- );
68
- return { ref: elementRef, CopyMessage };
64
+ }, [copyFromRef]);
65
+ const CopyMessage = () => {
66
+ if (snackbarDuration <= 0) return null;
67
+ return /* @__PURE__ */ jsxRuntime.jsx(
68
+ material.Snackbar,
69
+ {
70
+ open: snackbarOpen,
71
+ autoHideDuration: snackbarDuration,
72
+ onClose: handleSnackbarClose,
73
+ anchorOrigin: snackbarPosition,
74
+ children: /* @__PURE__ */ jsxRuntime.jsx(material.Alert, { onClose: handleSnackbarClose, severity: snackbarSeverity, sx: { width: "100%" }, children: snackbarMessage })
75
+ }
76
+ );
77
+ };
78
+ return { ref: elementRef, copy: executeCopy, CopyMessage };
69
79
  }
70
80
  exports.useClipboard = useClipboard;
71
81
  //# sourceMappingURL=ClipBoard.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClipBoard.cjs","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["import React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Permite adjuntar la funcionalidad de copiar el innerText de un elemento al portapapeles\n * mediante un clic y gestiona el feedback del Snackbar de forma interna.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una referencia de React que debe adjuntarse al elemento cuyo contenido se copiará.\n * - 'CopyMessage': El componente Snackbar pre-configurado y listo para ser renderizado.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n const elementRef = useRef<HTMLElement>(null); // Tipado más específico para HTMLElement\n\n // Estados internos para el Snackbar, con valores por defecto\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration || 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n // Función para copiar texto al portapapeles (utilizando document.execCommand para compatibilidad en iframes)\n const copyText = useCallback(() => {\n if (elementRef.current) {\n try {\n const textarea = document.createElement('textarea');\n textarea.value = elementRef.current.innerText || ''; // Captura el innerText del elemento\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand('copy');\n document.body.removeChild(textarea);\n\n // Actualiza el mensaje del snackbar con las opciones proporcionadas o los valores por defecto\n // Estos setters se invocan aquí para que los estados se actualicen antes de abrir el snackbar.\n setSnackbarMessage(options?.message || '¡Copiado al portapapeles!');\n setSnackbarSeverity(options?.severity || 'success');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration || 3000);\n setSnackbarOpen(true); // Abre el snackbar\n } catch (err) {\n console.error('Error al copiar al portapapeles:', err);\n // En caso de error, usa un mensaje y severidad de error\n setSnackbarMessage('Error al copiar.');\n setSnackbarSeverity('error');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' }); // Mantener posición si hay error\n setSnackbarDuration(options?.duration || 3000); // Mantener duración si hay error\n setSnackbarOpen(true); // Abre el snackbar con el mensaje de error\n }\n }\n }, [options]); // Dependencia en options para que el hook se reconfigure si las opciones cambian\n\n // Adjunta un event listener de clic al elemento referenciado\n useEffect(() => {\n const currentElement = elementRef.current;\n if (currentElement) {\n currentElement.style.cursor = 'pointer'; // Opcional: para indicar que es clickeable\n currentElement.addEventListener('click', copyText);\n }\n\n // Limpieza: remueve el event listener cuando el componente se desmonte\n return () => {\n if (currentElement) {\n currentElement.removeEventListener('click', copyText);\n }\n };\n }, [copyText]); // Dependencia en copyText para asegurar que el listener se actualice si la función cambia\n\n // Componente Snackbar encapsulado que el hook retorna para ser renderizado\n const CopyMessage = () => (\n <Snackbar\n open={snackbarOpen}\n autoHideDuration={snackbarDuration}\n onClose={handleSnackbarClose}\n anchorOrigin={{\n vertical: snackbarPosition.vertical as 'top' | 'bottom',\n horizontal: snackbarPosition.horizontal as 'left' | 'center' | 'right'\n }}\n >\n <Alert onClose={handleSnackbarClose} severity={snackbarSeverity} sx={{ width: '100%' }}>\n {snackbarMessage}\n </Alert>\n </Snackbar>\n );\n\n return { ref: elementRef, CopyMessage };\n}\n\nexport default useClipboard"],"names":["useRef","useState","useCallback","useEffect","jsx","Snackbar","Alert"],"mappings":";;;;;AAsBO,SAAS,aAAa,SAA2B;AACtD,QAAM,aAAaA,MAAAA,OAAoB,IAAI;AAG3C,QAAM,CAAC,cAAc,eAAe,IAAIC,MAAAA,SAAS,KAAK;AACtD,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA,MAAAA,UAAS,mCAAS,YAAW,2BAA2B;AACtG,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,MAAAA,UAAiC,mCAAS,aAAY,SAAS;AAC/G,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,MAAAA,UAAS,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,SAAA,CAAU;AAC1H,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,MAAAA,UAAS,mCAAS,aAAY,GAAI;AAGlF,QAAM,sBAAsBC,MAAAA,YAAY,CAAC,OAAsC,WAAoB;AACjG,QAAI,WAAW,aAAa;AAC1B;AAAA,IACF;AACA,oBAAgB,KAAK;AAAA,EACvB,GAAG,CAAA,CAAE;AAGL,QAAM,WAAWA,MAAAA,YAAY,MAAM;AACjC,QAAI,WAAW,SAAS;AACtB,UAAI;AACF,cAAM,WAAW,SAAS,cAAc,UAAU;AAClD,iBAAS,QAAQ,WAAW,QAAQ,aAAa;AACjD,iBAAS,KAAK,YAAY,QAAQ;AAClC,iBAAS,OAAA;AACT,iBAAS,YAAY,MAAM;AAC3B,iBAAS,KAAK,YAAY,QAAQ;AAIlC,4BAAmB,mCAAS,YAAW,2BAA2B;AAClE,6BAAoB,mCAAS,aAAY,SAAS;AAClD,6BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,6BAAoB,mCAAS,aAAY,GAAI;AAC7C,wBAAgB,IAAI;AAAA,MACtB,SAAS,KAAK;AACZ,gBAAQ,MAAM,oCAAoC,GAAG;AAErD,2BAAmB,kBAAkB;AACrC,4BAAoB,OAAO;AAC3B,6BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,6BAAoB,mCAAS,aAAY,GAAI;AAC7C,wBAAgB,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAGZC,QAAAA,UAAU,MAAM;AACd,UAAM,iBAAiB,WAAW;AAClC,QAAI,gBAAgB;AAClB,qBAAe,MAAM,SAAS;AAC9B,qBAAe,iBAAiB,SAAS,QAAQ;AAAA,IACnD;AAGA,WAAO,MAAM;AACX,UAAI,gBAAgB;AAClB,uBAAe,oBAAoB,SAAS,QAAQ;AAAA,MACtD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,cAAc,MAClBC,2BAAAA;AAAAA,IAACC,SAAAA;AAAAA,IAAA;AAAA,MACC,MAAM;AAAA,MACN,kBAAkB;AAAA,MAClB,SAAS;AAAA,MACT,cAAc;AAAA,QACZ,UAAU,iBAAiB;AAAA,QAC3B,YAAY,iBAAiB;AAAA,MAAA;AAAA,MAG/B,UAAAD,2BAAAA,IAACE,SAAAA,OAAA,EAAM,SAAS,qBAAqB,UAAU,kBAAkB,IAAI,EAAE,OAAO,OAAA,GAC3E,UAAA,gBAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAIJ,SAAO,EAAE,KAAK,YAAY,YAAA;AAC5B;;"}
1
+ {"version":3,"file":"ClipBoard.cjs","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["// useClipboard.tsx (Versión Unificada)\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Proporciona funcionalidad de copiado de texto y feedback visual (Snackbar).\n * Permite dos modos de uso:\n * 1. Uso por Referencia (ref): Se adjunta a un elemento, copia su innerText al hacer clic.\n * 2. Uso por Función (copy): Recibe el texto a copiar directamente como argumento.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una React Ref para adjuntar a un elemento (Modo Ref).\n * - 'copy': Una función (text: string) => void para copiar texto (Modo Función).\n * - 'CopyMessage': El componente Snackbar para renderizar el feedback.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n // --- Elementos de Copiado por Referencia ---\n const elementRef = useRef<HTMLElement>(null);\n\n // --- Estados y Opciones del Snackbar ---\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState<import('@mui/material').SnackbarOrigin>(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration ?? 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n /**\n * FUNCIÓN PRINCIPAL DE COPIADO.\n * Se usa internamente para 'ref' y se expone para 'copy(text)'.\n * @param text El texto exacto a copiar.\n */\n const executeCopy = useCallback((text: string) => {\n try {\n if (navigator.clipboard && window.isSecureContext) {\n // 1. API moderna\n navigator.clipboard.writeText(text);\n } else {\n // 2. Fallback usando textarea\n const textarea = document.createElement('textarea');\n textarea.value = text;\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand('copy');\n document.body.removeChild(textarea);\n }\n \n // Mostrar éxito\n setSnackbarMessage(options?.message || '¡Copiado al portapapeles!');\n setSnackbarSeverity(options?.severity || 'success');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration ?? 3000);\n setSnackbarOpen(true);\n\n } catch (err) {\n // Mostrar error\n console.error('Error al copiar al portapapeles:', err);\n setSnackbarMessage('Error al copiar.');\n setSnackbarSeverity('error');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration ?? 3000);\n setSnackbarOpen(true);\n }\n }, [options]); \n\n // --- Lógica del Modo Ref ---\n const copyFromRef = useCallback(() => {\n if (elementRef.current) {\n const textToCopy = elementRef.current.innerText || '';\n executeCopy(textToCopy);\n }\n }, [executeCopy]);\n\n // Adjunta un event listener de clic al elemento referenciado (Modo Ref)\n useEffect(() => {\n const currentElement = elementRef.current;\n if (currentElement) {\n currentElement.style.cursor = 'pointer';\n // Adjuntamos la función que copia el texto del ref\n currentElement.addEventListener('click', copyFromRef);\n }\n\n return () => {\n if (currentElement) {\n currentElement.removeEventListener('click', copyFromRef);\n }\n };\n }, [copyFromRef]);\n\n\n // Componente Snackbar encapsulado. Solo se renderiza si duration es > 0.\n const CopyMessage = () => {\n if (snackbarDuration <= 0) return null; // No renderizar si la duración es 0\n\n return (\n <Snackbar\n open={snackbarOpen}\n autoHideDuration={snackbarDuration}\n onClose={handleSnackbarClose}\n anchorOrigin={snackbarPosition}\n >\n <Alert onClose={handleSnackbarClose} severity={snackbarSeverity} sx={{ width: '100%' }}>\n {snackbarMessage}\n </Alert>\n </Snackbar>\n );\n };\n\n // Retorna ambas funcionalidades para que el usuario elija\n return { ref: elementRef, copy: executeCopy, CopyMessage };\n}\n\nexport default useClipboard;"],"names":["useRef","useState","useCallback","_a","useEffect","jsx","Snackbar","Alert"],"mappings":";;;;;AA0BO,SAAS,aAAa,SAA2B;;AAEtD,QAAM,aAAaA,MAAAA,OAAoB,IAAI;AAG3C,QAAM,CAAC,cAAc,eAAe,IAAIC,MAAAA,SAAS,KAAK;AACtD,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA,MAAAA,UAAS,mCAAS,YAAW,2BAA2B;AACtG,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,MAAAA,UAAiC,mCAAS,aAAY,SAAS;AAC/G,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,MAAAA,UAAiD,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,SAAA,CAAU;AAClK,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,MAAAA,UAAS,wCAAS,aAAT,YAAqB,GAAI;AAGlF,QAAM,sBAAsBC,MAAAA,YAAY,CAAC,OAAsC,WAAoB;AACjG,QAAI,WAAW,aAAa;AAC1B;AAAA,IACF;AACA,oBAAgB,KAAK;AAAA,EACvB,GAAG,CAAA,CAAE;AAOL,QAAM,cAAcA,kBAAY,CAAC,SAAiB;;AAChD,QAAI;AACF,UAAI,UAAU,aAAa,OAAO,iBAAiB;AAEjD,kBAAU,UAAU,UAAU,IAAI;AAAA,MACpC,OAAO;AAEL,cAAM,WAAW,SAAS,cAAc,UAAU;AAClD,iBAAS,QAAQ;AACjB,iBAAS,KAAK,YAAY,QAAQ;AAClC,iBAAS,OAAA;AACT,iBAAS,YAAY,MAAM;AAC3B,iBAAS,KAAK,YAAY,QAAQ;AAAA,MACpC;AAGA,0BAAmB,mCAAS,YAAW,2BAA2B;AAClE,2BAAoB,mCAAS,aAAY,SAAS;AAClD,2BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,2BAAoBC,MAAA,mCAAS,aAAT,OAAAA,MAAqB,GAAI;AAC7C,sBAAgB,IAAI;AAAA,IAEtB,SAAS,KAAK;AAEZ,cAAQ,MAAM,oCAAoC,GAAG;AACrD,yBAAmB,kBAAkB;AACrC,0BAAoB,OAAO;AAC3B,2BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,2BAAoB,wCAAS,aAAT,YAAqB,GAAI;AAC7C,sBAAgB,IAAI;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAGZ,QAAM,cAAcD,MAAAA,YAAY,MAAM;AACpC,QAAI,WAAW,SAAS;AACpB,YAAM,aAAa,WAAW,QAAQ,aAAa;AACnD,kBAAY,UAAU;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAGhBE,QAAAA,UAAU,MAAM;AACd,UAAM,iBAAiB,WAAW;AAClC,QAAI,gBAAgB;AAClB,qBAAe,MAAM,SAAS;AAE9B,qBAAe,iBAAiB,SAAS,WAAW;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,UAAI,gBAAgB;AAClB,uBAAe,oBAAoB,SAAS,WAAW;AAAA,MACzD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAIhB,QAAM,cAAc,MAAM;AACxB,QAAI,oBAAoB,EAAG,QAAO;AAElC,WACEC,2BAAAA;AAAAA,MAACC,SAAAA;AAAAA,MAAA;AAAA,QACC,MAAM;AAAA,QACN,kBAAkB;AAAA,QAClB,SAAS;AAAA,QACT,cAAc;AAAA,QAEd,UAAAD,2BAAAA,IAACE,SAAAA,OAAA,EAAM,SAAS,qBAAqB,UAAU,kBAAkB,IAAI,EAAE,OAAO,OAAA,GAC3E,UAAA,gBAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAGA,SAAO,EAAE,KAAK,YAAY,MAAM,aAAa,YAAA;AAC/C;;"}
@@ -11,16 +11,20 @@ interface SnackbarOptions {
11
11
  }
12
12
  /**
13
13
  * Hook 'useClipboard'.
14
- * Permite adjuntar la funcionalidad de copiar el innerText de un elemento al portapapeles
15
- * mediante un clic y gestiona el feedback del Snackbar de forma interna.
14
+ * Proporciona funcionalidad de copiado de texto y feedback visual (Snackbar).
15
+ * Permite dos modos de uso:
16
+ * 1. Uso por Referencia (ref): Se adjunta a un elemento, copia su innerText al hacer clic.
17
+ * 2. Uso por Función (copy): Recibe el texto a copiar directamente como argumento.
16
18
  *
17
19
  * @param options Opciones de configuración para el Snackbar de feedback.
18
20
  * @returns Un objeto que contiene:
19
- * - 'ref': Una referencia de React que debe adjuntarse al elemento cuyo contenido se copiará.
20
- * - 'CopyMessage': El componente Snackbar pre-configurado y listo para ser renderizado.
21
+ * - 'ref': Una React Ref para adjuntar a un elemento (Modo Ref).
22
+ * - 'copy': Una función (text: string) => void para copiar texto (Modo Función).
23
+ * - 'CopyMessage': El componente Snackbar para renderizar el feedback.
21
24
  */
22
25
  export declare function useClipboard(options?: SnackbarOptions): {
23
26
  ref: React.RefObject<HTMLElement | null>;
24
- CopyMessage: () => import("react/jsx-runtime").JSX.Element;
27
+ copy: (text: string) => void;
28
+ CopyMessage: () => import("react/jsx-runtime").JSX.Element | null;
25
29
  };
26
30
  export default useClipboard;
@@ -2,68 +2,78 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { useRef, useState, useCallback, useEffect } from "react";
3
3
  import { Snackbar, Alert } from "@mui/material";
4
4
  function useClipboard(options) {
5
+ var _a;
5
6
  const elementRef = useRef(null);
6
7
  const [snackbarOpen, setSnackbarOpen] = useState(false);
7
8
  const [snackbarMessage, setSnackbarMessage] = useState((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
8
9
  const [snackbarSeverity, setSnackbarSeverity] = useState((options == null ? void 0 : options.severity) || "success");
9
10
  const [snackbarPosition, setSnackbarPosition] = useState((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
10
- const [snackbarDuration, setSnackbarDuration] = useState((options == null ? void 0 : options.duration) || 3e3);
11
+ const [snackbarDuration, setSnackbarDuration] = useState((_a = options == null ? void 0 : options.duration) != null ? _a : 3e3);
11
12
  const handleSnackbarClose = useCallback((event, reason) => {
12
13
  if (reason === "clickaway") {
13
14
  return;
14
15
  }
15
16
  setSnackbarOpen(false);
16
17
  }, []);
17
- const copyText = useCallback(() => {
18
- if (elementRef.current) {
19
- try {
18
+ const executeCopy = useCallback((text) => {
19
+ var _a2, _b;
20
+ try {
21
+ if (navigator.clipboard && window.isSecureContext) {
22
+ navigator.clipboard.writeText(text);
23
+ } else {
20
24
  const textarea = document.createElement("textarea");
21
- textarea.value = elementRef.current.innerText || "";
25
+ textarea.value = text;
22
26
  document.body.appendChild(textarea);
23
27
  textarea.select();
24
28
  document.execCommand("copy");
25
29
  document.body.removeChild(textarea);
26
- setSnackbarMessage((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
27
- setSnackbarSeverity((options == null ? void 0 : options.severity) || "success");
28
- setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
29
- setSnackbarDuration((options == null ? void 0 : options.duration) || 3e3);
30
- setSnackbarOpen(true);
31
- } catch (err) {
32
- console.error("Error al copiar al portapapeles:", err);
33
- setSnackbarMessage("Error al copiar.");
34
- setSnackbarSeverity("error");
35
- setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
36
- setSnackbarDuration((options == null ? void 0 : options.duration) || 3e3);
37
- setSnackbarOpen(true);
38
30
  }
31
+ setSnackbarMessage((options == null ? void 0 : options.message) || "¡Copiado al portapapeles!");
32
+ setSnackbarSeverity((options == null ? void 0 : options.severity) || "success");
33
+ setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
34
+ setSnackbarDuration((_a2 = options == null ? void 0 : options.duration) != null ? _a2 : 3e3);
35
+ setSnackbarOpen(true);
36
+ } catch (err) {
37
+ console.error("Error al copiar al portapapeles:", err);
38
+ setSnackbarMessage("Error al copiar.");
39
+ setSnackbarSeverity("error");
40
+ setSnackbarPosition((options == null ? void 0 : options.position) || { vertical: "bottom", horizontal: "center" });
41
+ setSnackbarDuration((_b = options == null ? void 0 : options.duration) != null ? _b : 3e3);
42
+ setSnackbarOpen(true);
39
43
  }
40
44
  }, [options]);
45
+ const copyFromRef = useCallback(() => {
46
+ if (elementRef.current) {
47
+ const textToCopy = elementRef.current.innerText || "";
48
+ executeCopy(textToCopy);
49
+ }
50
+ }, [executeCopy]);
41
51
  useEffect(() => {
42
52
  const currentElement = elementRef.current;
43
53
  if (currentElement) {
44
54
  currentElement.style.cursor = "pointer";
45
- currentElement.addEventListener("click", copyText);
55
+ currentElement.addEventListener("click", copyFromRef);
46
56
  }
47
57
  return () => {
48
58
  if (currentElement) {
49
- currentElement.removeEventListener("click", copyText);
59
+ currentElement.removeEventListener("click", copyFromRef);
50
60
  }
51
61
  };
52
- }, [copyText]);
53
- const CopyMessage = () => /* @__PURE__ */ jsx(
54
- Snackbar,
55
- {
56
- open: snackbarOpen,
57
- autoHideDuration: snackbarDuration,
58
- onClose: handleSnackbarClose,
59
- anchorOrigin: {
60
- vertical: snackbarPosition.vertical,
61
- horizontal: snackbarPosition.horizontal
62
- },
63
- children: /* @__PURE__ */ jsx(Alert, { onClose: handleSnackbarClose, severity: snackbarSeverity, sx: { width: "100%" }, children: snackbarMessage })
64
- }
65
- );
66
- return { ref: elementRef, CopyMessage };
62
+ }, [copyFromRef]);
63
+ const CopyMessage = () => {
64
+ if (snackbarDuration <= 0) return null;
65
+ return /* @__PURE__ */ jsx(
66
+ Snackbar,
67
+ {
68
+ open: snackbarOpen,
69
+ autoHideDuration: snackbarDuration,
70
+ onClose: handleSnackbarClose,
71
+ anchorOrigin: snackbarPosition,
72
+ children: /* @__PURE__ */ jsx(Alert, { onClose: handleSnackbarClose, severity: snackbarSeverity, sx: { width: "100%" }, children: snackbarMessage })
73
+ }
74
+ );
75
+ };
76
+ return { ref: elementRef, copy: executeCopy, CopyMessage };
67
77
  }
68
78
  export {
69
79
  useClipboard
@@ -1 +1 @@
1
- {"version":3,"file":"ClipBoard.js","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["import React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Permite adjuntar la funcionalidad de copiar el innerText de un elemento al portapapeles\n * mediante un clic y gestiona el feedback del Snackbar de forma interna.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una referencia de React que debe adjuntarse al elemento cuyo contenido se copiará.\n * - 'CopyMessage': El componente Snackbar pre-configurado y listo para ser renderizado.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n const elementRef = useRef<HTMLElement>(null); // Tipado más específico para HTMLElement\n\n // Estados internos para el Snackbar, con valores por defecto\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration || 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n // Función para copiar texto al portapapeles (utilizando document.execCommand para compatibilidad en iframes)\n const copyText = useCallback(() => {\n if (elementRef.current) {\n try {\n const textarea = document.createElement('textarea');\n textarea.value = elementRef.current.innerText || ''; // Captura el innerText del elemento\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand('copy');\n document.body.removeChild(textarea);\n\n // Actualiza el mensaje del snackbar con las opciones proporcionadas o los valores por defecto\n // Estos setters se invocan aquí para que los estados se actualicen antes de abrir el snackbar.\n setSnackbarMessage(options?.message || '¡Copiado al portapapeles!');\n setSnackbarSeverity(options?.severity || 'success');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration || 3000);\n setSnackbarOpen(true); // Abre el snackbar\n } catch (err) {\n console.error('Error al copiar al portapapeles:', err);\n // En caso de error, usa un mensaje y severidad de error\n setSnackbarMessage('Error al copiar.');\n setSnackbarSeverity('error');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' }); // Mantener posición si hay error\n setSnackbarDuration(options?.duration || 3000); // Mantener duración si hay error\n setSnackbarOpen(true); // Abre el snackbar con el mensaje de error\n }\n }\n }, [options]); // Dependencia en options para que el hook se reconfigure si las opciones cambian\n\n // Adjunta un event listener de clic al elemento referenciado\n useEffect(() => {\n const currentElement = elementRef.current;\n if (currentElement) {\n currentElement.style.cursor = 'pointer'; // Opcional: para indicar que es clickeable\n currentElement.addEventListener('click', copyText);\n }\n\n // Limpieza: remueve el event listener cuando el componente se desmonte\n return () => {\n if (currentElement) {\n currentElement.removeEventListener('click', copyText);\n }\n };\n }, [copyText]); // Dependencia en copyText para asegurar que el listener se actualice si la función cambia\n\n // Componente Snackbar encapsulado que el hook retorna para ser renderizado\n const CopyMessage = () => (\n <Snackbar\n open={snackbarOpen}\n autoHideDuration={snackbarDuration}\n onClose={handleSnackbarClose}\n anchorOrigin={{\n vertical: snackbarPosition.vertical as 'top' | 'bottom',\n horizontal: snackbarPosition.horizontal as 'left' | 'center' | 'right'\n }}\n >\n <Alert onClose={handleSnackbarClose} severity={snackbarSeverity} sx={{ width: '100%' }}>\n {snackbarMessage}\n </Alert>\n </Snackbar>\n );\n\n return { ref: elementRef, CopyMessage };\n}\n\nexport default useClipboard"],"names":[],"mappings":";;;AAsBO,SAAS,aAAa,SAA2B;AACtD,QAAM,aAAa,OAAoB,IAAI;AAG3C,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,UAAS,mCAAS,YAAW,2BAA2B;AACtG,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,UAAiC,mCAAS,aAAY,SAAS;AAC/G,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,UAAS,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,SAAA,CAAU;AAC1H,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,UAAS,mCAAS,aAAY,GAAI;AAGlF,QAAM,sBAAsB,YAAY,CAAC,OAAsC,WAAoB;AACjG,QAAI,WAAW,aAAa;AAC1B;AAAA,IACF;AACA,oBAAgB,KAAK;AAAA,EACvB,GAAG,CAAA,CAAE;AAGL,QAAM,WAAW,YAAY,MAAM;AACjC,QAAI,WAAW,SAAS;AACtB,UAAI;AACF,cAAM,WAAW,SAAS,cAAc,UAAU;AAClD,iBAAS,QAAQ,WAAW,QAAQ,aAAa;AACjD,iBAAS,KAAK,YAAY,QAAQ;AAClC,iBAAS,OAAA;AACT,iBAAS,YAAY,MAAM;AAC3B,iBAAS,KAAK,YAAY,QAAQ;AAIlC,4BAAmB,mCAAS,YAAW,2BAA2B;AAClE,6BAAoB,mCAAS,aAAY,SAAS;AAClD,6BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,6BAAoB,mCAAS,aAAY,GAAI;AAC7C,wBAAgB,IAAI;AAAA,MACtB,SAAS,KAAK;AACZ,gBAAQ,MAAM,oCAAoC,GAAG;AAErD,2BAAmB,kBAAkB;AACrC,4BAAoB,OAAO;AAC3B,6BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,6BAAoB,mCAAS,aAAY,GAAI;AAC7C,wBAAgB,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAGZ,YAAU,MAAM;AACd,UAAM,iBAAiB,WAAW;AAClC,QAAI,gBAAgB;AAClB,qBAAe,MAAM,SAAS;AAC9B,qBAAe,iBAAiB,SAAS,QAAQ;AAAA,IACnD;AAGA,WAAO,MAAM;AACX,UAAI,gBAAgB;AAClB,uBAAe,oBAAoB,SAAS,QAAQ;AAAA,MACtD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,cAAc,MAClB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,MACN,kBAAkB;AAAA,MAClB,SAAS;AAAA,MACT,cAAc;AAAA,QACZ,UAAU,iBAAiB;AAAA,QAC3B,YAAY,iBAAiB;AAAA,MAAA;AAAA,MAG/B,UAAA,oBAAC,OAAA,EAAM,SAAS,qBAAqB,UAAU,kBAAkB,IAAI,EAAE,OAAO,OAAA,GAC3E,UAAA,gBAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAIJ,SAAO,EAAE,KAAK,YAAY,YAAA;AAC5B;"}
1
+ {"version":3,"file":"ClipBoard.js","sources":["../../../src/hooks/ClipBoard/ClipBoard.tsx"],"sourcesContent":["// useClipboard.tsx (Versión Unificada)\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { Snackbar, Alert } from '@mui/material';\nimport { AlertProps } from '@mui/material/Alert';\n\n// Tipo para las opciones del Snackbar\ninterface SnackbarOptions {\n message?: string;\n duration?: number;\n severity?: AlertProps['severity'];\n position?: { vertical: 'top' | 'bottom'; horizontal: 'left' | 'center' | 'right' };\n}\n\n/**\n * Hook 'useClipboard'.\n * Proporciona funcionalidad de copiado de texto y feedback visual (Snackbar).\n * Permite dos modos de uso:\n * 1. Uso por Referencia (ref): Se adjunta a un elemento, copia su innerText al hacer clic.\n * 2. Uso por Función (copy): Recibe el texto a copiar directamente como argumento.\n *\n * @param options Opciones de configuración para el Snackbar de feedback.\n * @returns Un objeto que contiene:\n * - 'ref': Una React Ref para adjuntar a un elemento (Modo Ref).\n * - 'copy': Una función (text: string) => void para copiar texto (Modo Función).\n * - 'CopyMessage': El componente Snackbar para renderizar el feedback.\n */\nexport function useClipboard(options?: SnackbarOptions) {\n // --- Elementos de Copiado por Referencia ---\n const elementRef = useRef<HTMLElement>(null);\n\n // --- Estados y Opciones del Snackbar ---\n const [snackbarOpen, setSnackbarOpen] = useState(false);\n const [snackbarMessage, setSnackbarMessage] = useState(options?.message || '¡Copiado al portapapeles!');\n const [snackbarSeverity, setSnackbarSeverity] = useState<AlertProps['severity']>(options?.severity || 'success');\n const [snackbarPosition, setSnackbarPosition] = useState<import('@mui/material').SnackbarOrigin>(options?.position || { vertical: 'bottom', horizontal: 'center' });\n const [snackbarDuration, setSnackbarDuration] = useState(options?.duration ?? 3000);\n\n // Función para cerrar el Snackbar\n const handleSnackbarClose = useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {\n if (reason === 'clickaway') {\n return;\n }\n setSnackbarOpen(false);\n }, []);\n\n /**\n * FUNCIÓN PRINCIPAL DE COPIADO.\n * Se usa internamente para 'ref' y se expone para 'copy(text)'.\n * @param text El texto exacto a copiar.\n */\n const executeCopy = useCallback((text: string) => {\n try {\n if (navigator.clipboard && window.isSecureContext) {\n // 1. API moderna\n navigator.clipboard.writeText(text);\n } else {\n // 2. Fallback usando textarea\n const textarea = document.createElement('textarea');\n textarea.value = text;\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand('copy');\n document.body.removeChild(textarea);\n }\n \n // Mostrar éxito\n setSnackbarMessage(options?.message || '¡Copiado al portapapeles!');\n setSnackbarSeverity(options?.severity || 'success');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration ?? 3000);\n setSnackbarOpen(true);\n\n } catch (err) {\n // Mostrar error\n console.error('Error al copiar al portapapeles:', err);\n setSnackbarMessage('Error al copiar.');\n setSnackbarSeverity('error');\n setSnackbarPosition(options?.position || { vertical: 'bottom', horizontal: 'center' });\n setSnackbarDuration(options?.duration ?? 3000);\n setSnackbarOpen(true);\n }\n }, [options]); \n\n // --- Lógica del Modo Ref ---\n const copyFromRef = useCallback(() => {\n if (elementRef.current) {\n const textToCopy = elementRef.current.innerText || '';\n executeCopy(textToCopy);\n }\n }, [executeCopy]);\n\n // Adjunta un event listener de clic al elemento referenciado (Modo Ref)\n useEffect(() => {\n const currentElement = elementRef.current;\n if (currentElement) {\n currentElement.style.cursor = 'pointer';\n // Adjuntamos la función que copia el texto del ref\n currentElement.addEventListener('click', copyFromRef);\n }\n\n return () => {\n if (currentElement) {\n currentElement.removeEventListener('click', copyFromRef);\n }\n };\n }, [copyFromRef]);\n\n\n // Componente Snackbar encapsulado. Solo se renderiza si duration es > 0.\n const CopyMessage = () => {\n if (snackbarDuration <= 0) return null; // No renderizar si la duración es 0\n\n return (\n <Snackbar\n open={snackbarOpen}\n autoHideDuration={snackbarDuration}\n onClose={handleSnackbarClose}\n anchorOrigin={snackbarPosition}\n >\n <Alert onClose={handleSnackbarClose} severity={snackbarSeverity} sx={{ width: '100%' }}>\n {snackbarMessage}\n </Alert>\n </Snackbar>\n );\n };\n\n // Retorna ambas funcionalidades para que el usuario elija\n return { ref: elementRef, copy: executeCopy, CopyMessage };\n}\n\nexport default useClipboard;"],"names":["_a"],"mappings":";;;AA0BO,SAAS,aAAa,SAA2B;;AAEtD,QAAM,aAAa,OAAoB,IAAI;AAG3C,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,UAAS,mCAAS,YAAW,2BAA2B;AACtG,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,UAAiC,mCAAS,aAAY,SAAS;AAC/G,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,UAAiD,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,SAAA,CAAU;AAClK,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,UAAS,wCAAS,aAAT,YAAqB,GAAI;AAGlF,QAAM,sBAAsB,YAAY,CAAC,OAAsC,WAAoB;AACjG,QAAI,WAAW,aAAa;AAC1B;AAAA,IACF;AACA,oBAAgB,KAAK;AAAA,EACvB,GAAG,CAAA,CAAE;AAOL,QAAM,cAAc,YAAY,CAAC,SAAiB;;AAChD,QAAI;AACF,UAAI,UAAU,aAAa,OAAO,iBAAiB;AAEjD,kBAAU,UAAU,UAAU,IAAI;AAAA,MACpC,OAAO;AAEL,cAAM,WAAW,SAAS,cAAc,UAAU;AAClD,iBAAS,QAAQ;AACjB,iBAAS,KAAK,YAAY,QAAQ;AAClC,iBAAS,OAAA;AACT,iBAAS,YAAY,MAAM;AAC3B,iBAAS,KAAK,YAAY,QAAQ;AAAA,MACpC;AAGA,0BAAmB,mCAAS,YAAW,2BAA2B;AAClE,2BAAoB,mCAAS,aAAY,SAAS;AAClD,2BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,2BAAoBA,MAAA,mCAAS,aAAT,OAAAA,MAAqB,GAAI;AAC7C,sBAAgB,IAAI;AAAA,IAEtB,SAAS,KAAK;AAEZ,cAAQ,MAAM,oCAAoC,GAAG;AACrD,yBAAmB,kBAAkB;AACrC,0BAAoB,OAAO;AAC3B,2BAAoB,mCAAS,aAAY,EAAE,UAAU,UAAU,YAAY,UAAU;AACrF,2BAAoB,wCAAS,aAAT,YAAqB,GAAI;AAC7C,sBAAgB,IAAI;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAGZ,QAAM,cAAc,YAAY,MAAM;AACpC,QAAI,WAAW,SAAS;AACpB,YAAM,aAAa,WAAW,QAAQ,aAAa;AACnD,kBAAY,UAAU;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAGhB,YAAU,MAAM;AACd,UAAM,iBAAiB,WAAW;AAClC,QAAI,gBAAgB;AAClB,qBAAe,MAAM,SAAS;AAE9B,qBAAe,iBAAiB,SAAS,WAAW;AAAA,IACtD;AAEA,WAAO,MAAM;AACX,UAAI,gBAAgB;AAClB,uBAAe,oBAAoB,SAAS,WAAW;AAAA,MACzD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAIhB,QAAM,cAAc,MAAM;AACxB,QAAI,oBAAoB,EAAG,QAAO;AAElC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAM;AAAA,QACN,kBAAkB;AAAA,QAClB,SAAS;AAAA,QACT,cAAc;AAAA,QAEd,UAAA,oBAAC,OAAA,EAAM,SAAS,qBAAqB,UAAU,kBAAkB,IAAI,EAAE,OAAO,OAAA,GAC3E,UAAA,gBAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAGA,SAAO,EAAE,KAAK,YAAY,MAAM,aAAa,YAAA;AAC/C;"}
@@ -0,0 +1,14 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Componente Wrapper para demostrar ambos modos de uso del hook useClipboard unificado.
4
+ * @param {object} args - Propiedades del Snackbar que se pasan al hook.
5
+ */
6
+ interface ClipboardDemoProps {
7
+ message: string;
8
+ severity: 'success' | 'info' | 'warning' | 'error';
9
+ duration: number;
10
+ vertical: 'top' | 'bottom';
11
+ horizontal: 'left' | 'center' | 'right';
12
+ }
13
+ declare const ClipboardUnifiedDemo: React.FC<ClipboardDemoProps>;
14
+ export default ClipboardUnifiedDemo;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soyfri/shared-library",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -1,5 +0,0 @@
1
- export declare const BasicClipboardUsageDefinition = "\nimport React from 'react';\nimport { Box, Typography, Paper } from '@mui/material';\nimport ContentCopyIcon from '@mui/icons-material/ContentCopy';\nimport { useClipboard } from './useClipboard'; // Ajusta la ruta si es necesario\n\nexport const BasicClipboardUsageExample = () => {\n const { ref, SnackbarComponent } = useClipboard();\n\n return (\n <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"h6\">Haz clic para copiar:</Typography>\n <Paper\n ref={ref}\n sx={{\n p: 2,\n border: '1px solid #ccc',\n borderRadius: '8px',\n backgroundColor: '#f5f5f5',\n cursor: 'pointer',\n '&:hover': {\n backgroundColor: '#e0e0e0',\n },\n }}\n >\n <Typography variant=\"body1\" sx={{ userSelect: 'none' }}>\n Este texto se copiar\u00E1 al portapapeles.\n </Typography>\n <ContentCopyIcon sx={{ fontSize: 16, ml: 1, verticalAlign: 'middle', color: 'text.secondary' }} />\n </Paper>\n <SnackbarComponent /> {/* Renderiza el Snackbar del hook */}\n </Box>\n );\n};\n";
2
- export declare const CustomMessageClipboardDefinition = "\nimport React from 'react';\nimport { Box, Typography, Paper } from '@mui/material';\nimport ContentCopyIcon from '@mui/icons-material/ContentCopy';\nimport { useClipboard } from './useClipboard'; // Ajusta la ruta si es necesario\n\nexport const CustomMessageClipboardExample = () => {\n const { ref, SnackbarComponent } = useClipboard({\n message: '\u00A1El contenido de la celda ha sido copiado exitosamente!',\n duration: 2500,\n severity: 'info',\n });\n\n return (\n <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"h6\">Copia con mensaje personalizado:</Typography>\n <Paper\n ref={ref}\n sx={{\n p: 2,\n border: '1px solid #cce',\n borderRadius: '8px',\n backgroundColor: '#eef',\n cursor: 'pointer',\n '&:hover': {\n backgroundColor: '#dde',\n },\n }}\n >\n <Typography variant=\"body1\" sx={{ userSelect: 'none' }}>\n Informaci\u00F3n importante para copiar.\n </Typography>\n <ContentCopyIcon sx={{ fontSize: 16, ml: 1, verticalAlign: 'middle', color: 'text.secondary' }} />\n </Paper>\n <SnackbarComponent /> {/* Renderiza el Snackbar del hook */}\n </Box>\n );\n};\n";
3
- export declare const ErrorHandlingClipboardDefinition = "\nimport React from 'react';\nimport { Box, Typography, Paper, Button } from '@mui/material';\nimport ContentCopyIcon from '@mui/icons-material/ContentCopy';\nimport { useClipboard } from './useClipboard'; // Ajusta la ruta si es necesario\n\nexport const ErrorHandlingClipboardExample = () => {\n // Simular un error forzando la copia de un elemento no existente\n // (Esto es solo para demostrar el path de error del Snackbar, en una app real no har\u00EDas esto)\n const { ref, SnackbarComponent } = useClipboard({\n message: '\u00A1Copiado con \u00E9xito!',\n severity: 'success'\n });\n\n // Para demostrar el error, tendr\u00EDamos que provocar que document.execCommand falle\n // lo cual es dif\u00EDcil de simular consistentemente en un Storybook.\n // El hook ya maneja el catch y cambia la severidad a 'error'.\n // Esta historia se enfoca en c\u00F3mo el snackbar se ver\u00EDa en un error si ocurriera.\n\n return (\n <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"h6\">Copia (observa el Snackbar en caso de error):</Typography>\n <Paper\n ref={ref} // Si el ref.current fuera null, se podr\u00EDa ver el mensaje de error.\n sx={{\n p: 2,\n border: '1px solid #eec',\n borderRadius: '8px',\n backgroundColor: '#ffe',\n cursor: 'pointer',\n '&:hover': {\n backgroundColor: '#eed',\n },\n }}\n >\n <Typography variant=\"body1\" sx={{ userSelect: 'none' }}>\n Intenta copiar este texto.\n </Typography>\n <ContentCopyIcon sx={{ fontSize: 16, ml: 1, verticalAlign: 'middle', color: 'text.secondary' }} />\n </Paper>\n <Typography variant=\"caption\" color=\"text.secondary\">\n (El mensaje de error del Snackbar se mostrar\u00EDa si la copia fallara internamente).\n </Typography>\n <SnackbarComponent /> {/* Renderiza el Snackbar del hook */}\n </Box>\n );\n};\n";
4
- export declare const MultipleClipboardElementsDefinition = "\nimport React from 'react';\nimport { Box, Typography, Paper } from '@mui/material';\nimport ContentCopyIcon from '@mui/icons-material/ContentCopy';\nimport { useClipboard } from './useClipboard'; // Ajusta la ruta si es necesario\n\nexport const MultipleClipboardElementsExample = () => {\n const { ref: ref1, SnackbarComponent: Snackbar1 } = useClipboard({ message: 'URL copiada', severity: 'success' });\n const { ref: ref2, SnackbarComponent: Snackbar2 } = useClipboard({ message: 'ID de producto copiado', severity: 'info', position: { vertical: 'top', horizontal: 'center' } });\n const { ref: ref3, SnackbarComponent: Snackbar3 } = useClipboard({ message: 'Nombre de usuario copiado', severity: 'warning', duration: 1500 });\n\n return (\n <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"h6\">M\u00FAltiples elementos con diferentes configuraciones:</Typography>\n <Paper\n ref={ref1}\n sx={{\n p: 2,\n border: '1px solid #ccc',\n borderRadius: '8px',\n backgroundColor: '#f5f5f5',\n cursor: 'pointer',\n '&:hover': { backgroundColor: '#e0e0e0' },\n }}\n >\n <Typography variant=\"body1\" sx={{ userSelect: 'none' }}>\n https://www.ejemplo.com/recurso/123\n </Typography>\n <ContentCopyIcon sx={{ fontSize: 16, ml: 1, verticalAlign: 'middle', color: 'text.secondary' }} />\n </Paper>\n\n <Paper\n ref={ref2}\n sx={{\n p: 2,\n border: '1px solid #cce',\n borderRadius: '8px',\n backgroundColor: '#eef',\n cursor: 'pointer',\n '&:hover': { backgroundColor: '#dde' },\n }}\n >\n <Typography variant=\"body1\" sx={{ userSelect: 'none' }}>\n ID: PROD-7890\n </Typography>\n <ContentCopyIcon sx={{ fontSize: 16, ml: 1, verticalAlign: 'middle', color: 'text.secondary' }} />\n </Paper>\n\n <Paper\n ref={ref3}\n sx={{\n p: 2,\n border: '1px solid #ecc',\n borderRadius: '8px',\n backgroundColor: '#fee',\n cursor: 'pointer',\n '&:hover': { backgroundColor: '#edd' },\n }}\n >\n <Typography variant=\"body1\" sx={{ userSelect: 'none' }}>\n Usuario: Alice_W\n </Typography>\n <ContentCopyIcon sx={{ fontSize: 16, ml: 1, verticalAlign: 'middle', color: 'text.secondary' }} />\n </Paper>\n\n <Snackbar1 />\n <Snackbar2 />\n <Snackbar3 />\n </Box>\n );\n};\n";
5
- export declare const ClipboardWithNoVisualFeedbackDefinition = "\nimport React from 'react';\nimport { Box, Typography, Paper } from '@mui/material';\nimport ContentCopyIcon from '@mui/icons-material/ContentCopy';\nimport { useClipboard } from './useClipboard'; // Ajusta la ruta si es necesario\n\nexport const ClipboardWithNoVisualFeedbackExample = () => {\n // Configura el hook sin mensaje para que no haya feedback visual expl\u00EDcito\n const { ref } = useClipboard({ duration: 0 }); // duration: 0 para que no se muestre el snackbar\n\n return (\n <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"h6\">Copia sin feedback visual (revisa el portapapeles):</Typography>\n <Paper\n ref={ref}\n sx={{\n p: 2,\n border: '1px solid #eee',\n borderRadius: '8px',\n backgroundColor: '#fafafa',\n cursor: 'pointer',\n '&:hover': { backgroundColor: '#e9e9e9' },\n }}\n >\n <Typography variant=\"body1\" sx={{ userSelect: 'none' }}>\n Este texto se copiar\u00E1 silenciosamente.\n </Typography>\n <ContentCopyIcon sx={{ fontSize: 16, ml: 1, verticalAlign: 'middle', color: 'text.secondary' }} />\n </Paper>\n <Typography variant=\"caption\" color=\"text.secondary\">\n (No se mostrar\u00E1 el Snackbar despu\u00E9s de copiar).\n </Typography>\n {/* No renderizamos SnackbarComponent aqu\u00ED */}\n </Box>\n );\n};\n";