@alquimia-ai/ui 1.2.1 → 1.2.4

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 (101) hide show
  1. package/dist/components/hooks/index.js +41 -32
  2. package/dist/components/hooks/index.js.map +1 -1
  3. package/dist/components/hooks/index.mjs +42 -33
  4. package/dist/components/hooks/index.mjs.map +1 -1
  5. package/dist/components/molecules/index.js +41 -32
  6. package/dist/components/molecules/index.js.map +1 -1
  7. package/dist/components/molecules/index.mjs +42 -33
  8. package/dist/components/molecules/index.mjs.map +1 -1
  9. package/dist/components/organisms/index.js +41 -32
  10. package/dist/components/organisms/index.js.map +1 -1
  11. package/dist/components/organisms/index.mjs +42 -33
  12. package/dist/components/organisms/index.mjs.map +1 -1
  13. package/dist/index.js +41 -32
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +42 -33
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/package.json +136 -0
  18. package/package.json +50 -53
  19. package/src/components/atoms/index.ts +0 -32
  20. package/src/components/atoms/ui/alert.tsx +0 -59
  21. package/src/components/atoms/ui/aspect-ratio.tsx +0 -7
  22. package/src/components/atoms/ui/avatar.tsx +0 -50
  23. package/src/components/atoms/ui/badge.tsx +0 -36
  24. package/src/components/atoms/ui/breadcrumb.tsx +0 -120
  25. package/src/components/atoms/ui/button.tsx +0 -56
  26. package/src/components/atoms/ui/card.tsx +0 -87
  27. package/src/components/atoms/ui/checkbox.tsx +0 -31
  28. package/src/components/atoms/ui/command.tsx +0 -155
  29. package/src/components/atoms/ui/dialog.tsx +0 -125
  30. package/src/components/atoms/ui/drawer.tsx +0 -119
  31. package/src/components/atoms/ui/input.tsx +0 -26
  32. package/src/components/atoms/ui/label.tsx +0 -26
  33. package/src/components/atoms/ui/loader.tsx +0 -52
  34. package/src/components/atoms/ui/popover.tsx +0 -31
  35. package/src/components/atoms/ui/rich-text.tsx +0 -19
  36. package/src/components/atoms/ui/scroll-area.tsx +0 -48
  37. package/src/components/atoms/ui/select.tsx +0 -160
  38. package/src/components/atoms/ui/skeleton.tsx +0 -15
  39. package/src/components/atoms/ui/slider.tsx +0 -29
  40. package/src/components/atoms/ui/switch.tsx +0 -30
  41. package/src/components/atoms/ui/table.tsx +0 -118
  42. package/src/components/atoms/ui/tabs.tsx +0 -56
  43. package/src/components/atoms/ui/text-area/index.tsx +0 -24
  44. package/src/components/atoms/ui/textarea.tsx +0 -25
  45. package/src/components/atoms/ui/think-indicator.tsx +0 -103
  46. package/src/components/atoms/ui/toast.tsx +0 -129
  47. package/src/components/atoms/ui/toaster.tsx +0 -38
  48. package/src/components/atoms/ui/toggle.tsx +0 -45
  49. package/src/components/atoms/ui/typography/index.tsx +0 -30
  50. package/src/components/hooks/index.ts +0 -4
  51. package/src/components/hooks/use-document.tsx +0 -44
  52. package/src/components/hooks/use-resize-observer.ts +0 -28
  53. package/src/components/hooks/use-text-streaming.ts +0 -63
  54. package/src/components/hooks/use-toast.ts +0 -194
  55. package/src/components/index.ts +0 -1
  56. package/src/components/molecules/alert-dialog.tsx +0 -141
  57. package/src/components/molecules/assistant-button.tsx +0 -148
  58. package/src/components/molecules/call-out.tsx +0 -163
  59. package/src/components/molecules/carousel.tsx +0 -262
  60. package/src/components/molecules/documents/document-selector.tsx +0 -79
  61. package/src/components/molecules/documents/document-viewer.tsx +0 -85
  62. package/src/components/molecules/documents/index.ts +0 -2
  63. package/src/components/molecules/index.ts +0 -11
  64. package/src/components/molecules/navigation-menu.tsx +0 -128
  65. package/src/components/molecules/page-container.tsx +0 -17
  66. package/src/components/molecules/rating-comment.tsx +0 -93
  67. package/src/components/molecules/rating-stars.tsx +0 -136
  68. package/src/components/molecules/rating-thumbs.tsx +0 -90
  69. package/src/components/molecules/sidebar.tsx +0 -107
  70. package/src/components/molecules/sonner.tsx +0 -30
  71. package/src/components/molecules/viewers/index.ts +0 -2
  72. package/src/components/molecules/viewers/pdf-viewer.tsx +0 -138
  73. package/src/components/molecules/viewers/plain-text-viewer.tsx +0 -40
  74. package/src/components/organisms/assistant.tsx +0 -271
  75. package/src/components/organisms/index.ts +0 -6
  76. package/src/components/organisms/rating-dialog.tsx +0 -104
  77. package/src/components/organisms/speechToText.tsx +0 -92
  78. package/src/components/organisms/whisper.tsx +0 -106
  79. package/src/components/templates/cards/index.ts +0 -2
  80. package/src/components/templates/cards/with-image-heading-description-avatar.tsx +0 -94
  81. package/src/components/templates/cards/with-image-heading-description.tsx +0 -63
  82. package/src/components/templates/hero/index.tsx +0 -39
  83. package/src/components/templates/index.ts +0 -4
  84. package/src/components/templates/messages-window.tsx +0 -15
  85. package/src/components/templates/query-box.tsx +0 -13
  86. package/src/components/ui/input.tsx +0 -25
  87. package/src/components/ui/select.tsx +0 -163
  88. package/src/index.ts +0 -7
  89. package/src/lib/index.ts +0 -1
  90. package/src/lib/utils.ts +0 -34
  91. package/src/styles/call-out.css +0 -153
  92. package/src/styles/drawer.css +0 -28
  93. package/src/styles/globals.css +0 -69
  94. package/src/styles/prose.css +0 -51
  95. package/src/styles/ratings.css +0 -27
  96. package/src/styles/themes/base-alquimia.css +0 -95
  97. package/src/styles/themes/base-nordic.css +0 -83
  98. package/src/styles/themes/base-primary.css +0 -85
  99. package/src/styles/themes/base.css +0 -8
  100. package/src/types/index.ts +0 -1
  101. package/src/types/type.ts +0 -76
@@ -197,47 +197,56 @@ var import_react2 = require("react");
197
197
  // src/components/hooks/use-text-streaming.ts
198
198
  var import_react3 = require("react");
199
199
  var CHAR_DELAY = 25;
200
- var PUNCTUATION_DELAY = 200;
201
- var PUNCTUATION_MARKS = [".", "!", "?", ";", ":"];
200
+ var PUNCTUATION_DELAY = 400;
202
201
  function useTextStreaming(content, shouldStream, handleIsTextStreaming) {
203
- const [displayedContent, setDisplayedContent] = (0, import_react3.useState)("");
204
- const timeoutId = (0, import_react3.useRef)(null);
202
+ const [displayedText, setDisplayedText] = (0, import_react3.useState)("");
203
+ const contentRef = (0, import_react3.useRef)(content);
204
+ const indexRef = (0, import_react3.useRef)(0);
205
+ const timerRef = (0, import_react3.useRef)(null);
205
206
  const hasStartedStreaming = (0, import_react3.useRef)(false);
206
- const getDelayForChar = (text, position) => {
207
- if (position === 0) return CHAR_DELAY;
208
- const previousChar = text[position - 1] || "";
209
- const isEllipsis = text.slice(position - 1, position + 2) === "...";
210
- if (isEllipsis) {
211
- return CHAR_DELAY;
212
- }
213
- return PUNCTUATION_MARKS.includes(previousChar) ? PUNCTUATION_DELAY : CHAR_DELAY;
214
- };
215
207
  (0, import_react3.useEffect)(() => {
216
- if (!shouldStream && !hasStartedStreaming.current) {
217
- setDisplayedContent(content);
218
- handleIsTextStreaming?.(false);
219
- return;
208
+ contentRef.current = content;
209
+ if (hasStartedStreaming.current && !timerRef.current && indexRef.current < contentRef.current.length) {
210
+ typeNext();
220
211
  }
221
- handleIsTextStreaming?.(true);
222
- hasStartedStreaming.current = true;
223
- if (displayedContent.length < content.length) {
224
- const delay = getDelayForChar(content, displayedContent.length);
225
- timeoutId.current = setTimeout(() => {
226
- setDisplayedContent((prev) => prev + content[prev.length]);
212
+ }, [content]);
213
+ const typeNext = (0, import_react3.useCallback)(() => {
214
+ if (indexRef.current < contentRef.current.length) {
215
+ const nextChar = contentRef.current.charAt(indexRef.current);
216
+ setDisplayedText((prev) => prev + nextChar);
217
+ indexRef.current++;
218
+ const delay = /[.!?;:]/.test(nextChar) ? PUNCTUATION_DELAY : CHAR_DELAY;
219
+ timerRef.current = setTimeout(() => {
220
+ timerRef.current = null;
221
+ typeNext();
227
222
  }, delay);
228
223
  } else {
229
224
  handleIsTextStreaming?.(false);
230
225
  }
226
+ }, []);
227
+ (0, import_react3.useEffect)(() => {
228
+ if (!shouldStream && !hasStartedStreaming.current) {
229
+ setDisplayedText(contentRef.current);
230
+ indexRef.current = contentRef.current.length;
231
+ if (timerRef.current) {
232
+ clearTimeout(timerRef.current);
233
+ timerRef.current = null;
234
+ }
235
+ handleIsTextStreaming?.(false);
236
+ } else {
237
+ if (indexRef.current < contentRef.current.length && !timerRef.current) {
238
+ handleIsTextStreaming?.(true);
239
+ hasStartedStreaming.current = true;
240
+ typeNext();
241
+ }
242
+ }
231
243
  return () => {
232
- if (timeoutId.current) clearTimeout(timeoutId.current);
244
+ if (timerRef.current) {
245
+ clearTimeout(timerRef.current);
246
+ timerRef.current = null;
247
+ }
233
248
  };
234
- }, [
235
- content,
236
- displayedContent,
237
- shouldStream,
238
- getDelayForChar,
239
- handleIsTextStreaming
240
- ]);
241
- return displayedContent;
249
+ }, [shouldStream, typeNext]);
250
+ return displayedText;
242
251
  }
243
252
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/hooks/index.ts","../../../src/components/hooks/use-toast.ts","../../../src/components/hooks/use-document.tsx","../../../src/components/hooks/use-resize-observer.ts","../../../src/components/hooks/use-text-streaming.ts"],"sourcesContent":["export * from \"./use-toast\";\nexport * from \"./use-document\";\nexport * from \"./use-resize-observer\";\nexport * from \"./use-text-streaming\";\n","\"use client\";\n\n// Inspired by react-hot-toast library\nimport * as React from \"react\";\n\nimport type {\n ToastActionElement,\n ToastProps,\n} from \"../../components/atoms/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { ApiError, ActionResponse } from \"../../types/type\";\n\nexport const useDocumentReader = (\n url: string,\n getDocument: (id: string) => Promise<ActionResponse<Blob>>,\n) => {\n const [loading, setLoading] = useState<boolean>(true);\n const [error, setError] = useState<string | null>(null);\n const [document, setDocument] = useState<Blob | null>(null);\n\n const handleDocumentError = (error: ApiError) => {\n const errorMessage = \"Hubo un error al obtener el documento. Por favor ponganse en contacto con el administrador.\";\n setError(errorMessage);\n throw new Error(error?.message || 'Unknown error');\n };\n\n const resetDocument = () => {\n setDocument(null);\n };\n\n const fetchDocument = async () => {\n setLoading(true);\n setError(null);\n \n try {\n const res = await getDocument(url);\n if (!res.success) {\n handleDocumentError(res.error as ApiError || new Error('Unknown error'));\n setLoading(false);\n return;\n }\n res.data && setDocument(res.data);\n } catch (error) {\n handleDocumentError(error as ApiError);\n } finally {\n setLoading(false);\n }\n };\n\n return { document, loading, fetchDocument, resetDocument, error };\n};\n","import { useEffect, useRef } from 'react';\n\ntype ResizeObserverOptions = {\n box?: 'content-box' | 'border-box';\n};\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[], observer: ResizeObserver) => void;\n\nexport default function useResizeObserver(\n element: Element | null,\n options: ResizeObserverOptions | undefined,\n observerCallback: ResizeObserverCallback\n): void {\n const observerRef = useRef<ResizeObserver | null>(null);\n\n useEffect(() => {\n if (!element) return;\n\n observerRef.current = new ResizeObserver(observerCallback);\n observerRef.current.observe(element, options);\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n };\n }, [element, options, observerCallback]);\n}\n","import { useEffect, useRef, useState } from \"react\";\nconst CHAR_DELAY = 25;\nconst PUNCTUATION_DELAY = 200;\nconst PUNCTUATION_MARKS = [\".\", \"!\", \"?\", \";\", \":\"];\n\nfunction useTextStreaming(\n content: string,\n shouldStream: boolean,\n handleIsTextStreaming?: (isStreaming: boolean) => void\n) {\n const [displayedContent, setDisplayedContent] = useState<string>(\"\");\n const timeoutId = useRef<NodeJS.Timeout | null>(null);\n const hasStartedStreaming = useRef<boolean>(false);\n\n const getDelayForChar = (text: string, position: number): number => {\n if (position === 0) return CHAR_DELAY;\n\n const previousChar = text[position - 1] || '';\n const isEllipsis = text.slice(position - 1, position + 2) === \"...\";\n\n if (isEllipsis) {\n return CHAR_DELAY;\n }\n\n return PUNCTUATION_MARKS.includes(previousChar)\n ? PUNCTUATION_DELAY\n : CHAR_DELAY;\n };\n\n useEffect(() => {\n if (!shouldStream && !hasStartedStreaming.current) {\n setDisplayedContent(content);\n handleIsTextStreaming?.(false);\n return;\n }\n\n handleIsTextStreaming?.(true);\n hasStartedStreaming.current = true;\n\n if (displayedContent.length < content.length) {\n const delay = getDelayForChar(content, displayedContent.length);\n timeoutId.current = setTimeout(() => {\n setDisplayedContent((prev) => prev + content[prev.length]);\n }, delay);\n } else {\n handleIsTextStreaming?.(false);\n }\n\n return () => {\n if (timeoutId.current) clearTimeout(timeoutId.current);\n };\n }, [\n content,\n displayedContent,\n shouldStream,\n getDelayForChar,\n handleIsTextStreaming,\n ]);\n\n return displayedContent;\n}\n\nexport { useTextStreaming };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,YAAuB;AAOvB,IAAM,cAAc;AACpB,IAAM,qBAAqB;AAgB3B,IAAI,QAAQ;AAEZ,SAAS,QAAQ;AACf,WAAS,QAAQ,KAAK,OAAO;AAC7B,SAAO,MAAM,SAAS;AACxB;AA0BA,IAAM,gBAAgB,oBAAI,IAA2C;AAErE,IAAM,mBAAmB,CAAC,YAAoB;AAC5C,MAAI,cAAc,IAAI,OAAO,GAAG;AAC9B;AAAA,EACF;AAEA,QAAM,UAAU,WAAW,MAAM;AAC/B,kBAAc,OAAO,OAAO;AAC5B,aAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH,GAAG,kBAAkB;AAErB,gBAAc,IAAI,SAAS,OAAO;AACpC;AAEO,IAAM,UAAU,CAAC,OAAc,WAA0B;AAC9D,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,CAAC,OAAO,OAAO,GAAG,MAAM,MAAM,EAAE,MAAM,GAAG,WAAW;AAAA,MAC9D;AAAA,IAEF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,MAAM,OAAO;AAAA,UAAI,CAAC,MACxB,EAAE,OAAO,OAAO,MAAM,KAAK,EAAE,GAAG,GAAG,GAAG,OAAO,MAAM,IAAI;AAAA,QACzD;AAAA,MACF;AAAA,IAEF,KAAK,iBAAiB;AACpB,YAAM,EAAE,QAAQ,IAAI;AAIpB,UAAI,SAAS;AACX,yBAAiB,OAAO;AAAA,MAC1B,OAAO;AACL,cAAM,OAAO,QAAQ,CAACA,WAAU;AAC9B,2BAAiBA,OAAM,EAAE;AAAA,QAC3B,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,MAAM,OAAO;AAAA,UAAI,CAAC,MACxB,EAAE,OAAO,WAAW,YAAY,SAC5B;AAAA,YACE,GAAG;AAAA,YACH,MAAM;AAAA,UACR,IACA;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK;AACH,UAAI,OAAO,YAAY,QAAW;AAChC,eAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,CAAC;AAAA,QACX;AAAA,MACF;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,OAAO;AAAA,MAC5D;AAAA,EACJ;AACF;AAEA,IAAM,YAA2C,CAAC;AAElD,IAAI,cAAqB,EAAE,QAAQ,CAAC,EAAE;AAEtC,SAAS,SAAS,QAAgB;AAChC,gBAAc,QAAQ,aAAa,MAAM;AACzC,YAAU,QAAQ,CAAC,aAAa;AAC9B,aAAS,WAAW;AAAA,EACtB,CAAC;AACH;AAIA,SAAS,MAAM,EAAE,GAAG,MAAM,GAAU;AAClC,QAAM,KAAK,MAAM;AAEjB,QAAM,SAAS,CAACC,WACd,SAAS;AAAA,IACP,MAAM;AAAA,IACN,OAAO,EAAE,GAAGA,QAAO,GAAG;AAAA,EACxB,CAAC;AACH,QAAM,UAAU,MAAM,SAAS,EAAE,MAAM,iBAAiB,SAAS,GAAG,CAAC;AAErE,WAAS;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,MAAM;AAAA,MACN,cAAc,CAAC,SAAS;AACtB,YAAI,CAAC,KAAM,SAAQ;AAAA,MACrB;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,WAAW;AAClB,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAgB,WAAW;AAE3D,EAAM,gBAAU,MAAM;AACpB,cAAU,KAAK,QAAQ;AACvB,WAAO,MAAM;AACX,YAAM,QAAQ,UAAU,QAAQ,QAAQ;AACxC,UAAI,QAAQ,IAAI;AACd,kBAAU,OAAO,OAAO,CAAC;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,SAAS,CAAC,YAAqB,SAAS,EAAE,MAAM,iBAAiB,QAAQ,CAAC;AAAA,EAC5E;AACF;;;AC7LA,mBAAyB;AAGlB,IAAM,oBAAoB,CAC/B,KACA,gBACG;AACH,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAkB,IAAI;AACpD,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB,IAAI;AACtD,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAsB,IAAI;AAE1D,QAAM,sBAAsB,CAACC,WAAoB;AAC/C,UAAM,eAAe;AACrB,aAAS,YAAY;AACrB,UAAM,IAAI,MAAMA,QAAO,WAAW,eAAe;AAAA,EACnD;AAEA,QAAM,gBAAgB,MAAM;AAC1B,gBAAY,IAAI;AAAA,EAClB;AAEA,QAAM,gBAAgB,YAAY;AAChC,eAAW,IAAI;AACf,aAAS,IAAI;AAEb,QAAI;AACF,YAAM,MAAM,MAAM,YAAY,GAAG;AACjC,UAAI,CAAC,IAAI,SAAS;AAChB,4BAAoB,IAAI,SAAqB,IAAI,MAAM,eAAe,CAAC;AACvE,mBAAW,KAAK;AAChB;AAAA,MACF;AACA,UAAI,QAAQ,YAAY,IAAI,IAAI;AAAA,IAClC,SAASA,QAAO;AACd,0BAAoBA,MAAiB;AAAA,IACvC,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,SAAS,eAAe,eAAe,MAAM;AAClE;;;AC3CA,IAAAC,gBAAkC;;;ACAlC,IAAAC,gBAA4C;AAC5C,IAAM,aAAa;AACnB,IAAM,oBAAoB;AAC1B,IAAM,oBAAoB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAElD,SAAS,iBACP,SACA,cACA,uBACA;AACA,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,wBAAiB,EAAE;AACnE,QAAM,gBAAY,sBAA8B,IAAI;AACpD,QAAM,0BAAsB,sBAAgB,KAAK;AAEjD,QAAM,kBAAkB,CAAC,MAAc,aAA6B;AAClE,QAAI,aAAa,EAAG,QAAO;AAE3B,UAAM,eAAe,KAAK,WAAW,CAAC,KAAK;AAC3C,UAAM,aAAa,KAAK,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM;AAE9D,QAAI,YAAY;AACd,aAAO;AAAA,IACT;AAEA,WAAO,kBAAkB,SAAS,YAAY,IAC1C,oBACA;AAAA,EACN;AAEA,+BAAU,MAAM;AACd,QAAI,CAAC,gBAAgB,CAAC,oBAAoB,SAAS;AACjD,0BAAoB,OAAO;AAC3B,8BAAwB,KAAK;AAC7B;AAAA,IACF;AAEA,4BAAwB,IAAI;AAC5B,wBAAoB,UAAU;AAE9B,QAAI,iBAAiB,SAAS,QAAQ,QAAQ;AAC5C,YAAM,QAAQ,gBAAgB,SAAS,iBAAiB,MAAM;AAC9D,gBAAU,UAAU,WAAW,MAAM;AACnC,4BAAoB,CAAC,SAAS,OAAO,QAAQ,KAAK,MAAM,CAAC;AAAA,MAC3D,GAAG,KAAK;AAAA,IACV,OAAO;AACL,8BAAwB,KAAK;AAAA,IAC/B;AAEA,WAAO,MAAM;AACX,UAAI,UAAU,QAAS,cAAa,UAAU,OAAO;AAAA,IACvD;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":["toast","props","error","import_react","import_react"]}
1
+ {"version":3,"sources":["../../../src/components/hooks/index.ts","../../../src/components/hooks/use-toast.ts","../../../src/components/hooks/use-document.tsx","../../../src/components/hooks/use-resize-observer.ts","../../../src/components/hooks/use-text-streaming.ts"],"sourcesContent":["export * from \"./use-toast\";\nexport * from \"./use-document\";\nexport * from \"./use-resize-observer\";\nexport * from \"./use-text-streaming\";\n","\"use client\";\n\n// Inspired by react-hot-toast library\nimport * as React from \"react\";\n\nimport type {\n ToastActionElement,\n ToastProps,\n} from \"../../components/atoms/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { ApiError, ActionResponse } from \"../../types/type\";\n\nexport const useDocumentReader = (\n url: string,\n getDocument: (id: string) => Promise<ActionResponse<Blob>>,\n) => {\n const [loading, setLoading] = useState<boolean>(true);\n const [error, setError] = useState<string | null>(null);\n const [document, setDocument] = useState<Blob | null>(null);\n\n const handleDocumentError = (error: ApiError) => {\n const errorMessage = \"Hubo un error al obtener el documento. Por favor ponganse en contacto con el administrador.\";\n setError(errorMessage);\n throw new Error(error?.message || 'Unknown error');\n };\n\n const resetDocument = () => {\n setDocument(null);\n };\n\n const fetchDocument = async () => {\n setLoading(true);\n setError(null);\n \n try {\n const res = await getDocument(url);\n if (!res.success) {\n handleDocumentError(res.error as ApiError || new Error('Unknown error'));\n setLoading(false);\n return;\n }\n res.data && setDocument(res.data);\n } catch (error) {\n handleDocumentError(error as ApiError);\n } finally {\n setLoading(false);\n }\n };\n\n return { document, loading, fetchDocument, resetDocument, error };\n};\n","import { useEffect, useRef } from 'react';\n\ntype ResizeObserverOptions = {\n box?: 'content-box' | 'border-box';\n};\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[], observer: ResizeObserver) => void;\n\nexport default function useResizeObserver(\n element: Element | null,\n options: ResizeObserverOptions | undefined,\n observerCallback: ResizeObserverCallback\n): void {\n const observerRef = useRef<ResizeObserver | null>(null);\n\n useEffect(() => {\n if (!element) return;\n\n observerRef.current = new ResizeObserver(observerCallback);\n observerRef.current.observe(element, options);\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n };\n }, [element, options, observerCallback]);\n}\n","import { useState, useEffect, useRef, useCallback } from \"react\";\n\nconst CHAR_DELAY = 25;\nconst PUNCTUATION_DELAY = 400;\n\nexport function useTextStreaming(\n content: string,\n shouldStream: boolean,\n handleIsTextStreaming?: (isStreaming: boolean) => void\n) {\n const [displayedText, setDisplayedText] = useState(\"\");\n const contentRef = useRef(content);\n const indexRef = useRef(0);\n const timerRef = useRef<NodeJS.Timeout | null>(null);\n\n const hasStartedStreaming = useRef<boolean>(false);\n\n useEffect(() => {\n contentRef.current = content;\n if (hasStartedStreaming.current && !timerRef.current && indexRef.current < contentRef.current.length) {\n typeNext();\n }\n }, [content]);\n\n const typeNext = useCallback(() => {\n if (indexRef.current < contentRef.current.length) {\n const nextChar = contentRef.current.charAt(indexRef.current);\n setDisplayedText((prev) => prev + nextChar);\n indexRef.current++;\n\n const delay = /[.!?;:]/.test(nextChar) ? PUNCTUATION_DELAY : CHAR_DELAY;\n \n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n typeNext();\n }, delay);\n } else {\n handleIsTextStreaming?.(false);\n }\n }, []);\n\n useEffect(() => {\n if (!shouldStream && !hasStartedStreaming.current) {\n setDisplayedText(contentRef.current);\n indexRef.current = contentRef.current.length;\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n handleIsTextStreaming?.(false);\n } else {\n if (indexRef.current < contentRef.current.length && !timerRef.current) {\n handleIsTextStreaming?.(true);\n hasStartedStreaming.current = true;\n typeNext();\n }\n }\n\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n }, [shouldStream, typeNext]);\n\n return displayedText;\n}\n\n"],"mappings":"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","names":["toast","props","error","import_react","import_react"]}
@@ -156,50 +156,59 @@ var useDocumentReader = (url, getDocument) => {
156
156
  import { useEffect as useEffect2, useRef } from "react";
157
157
 
158
158
  // src/components/hooks/use-text-streaming.ts
159
- import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
159
+ import { useState as useState3, useEffect as useEffect3, useRef as useRef2, useCallback } from "react";
160
160
  var CHAR_DELAY = 25;
161
- var PUNCTUATION_DELAY = 200;
162
- var PUNCTUATION_MARKS = [".", "!", "?", ";", ":"];
161
+ var PUNCTUATION_DELAY = 400;
163
162
  function useTextStreaming(content, shouldStream, handleIsTextStreaming) {
164
- const [displayedContent, setDisplayedContent] = useState3("");
165
- const timeoutId = useRef2(null);
163
+ const [displayedText, setDisplayedText] = useState3("");
164
+ const contentRef = useRef2(content);
165
+ const indexRef = useRef2(0);
166
+ const timerRef = useRef2(null);
166
167
  const hasStartedStreaming = useRef2(false);
167
- const getDelayForChar = (text, position) => {
168
- if (position === 0) return CHAR_DELAY;
169
- const previousChar = text[position - 1] || "";
170
- const isEllipsis = text.slice(position - 1, position + 2) === "...";
171
- if (isEllipsis) {
172
- return CHAR_DELAY;
173
- }
174
- return PUNCTUATION_MARKS.includes(previousChar) ? PUNCTUATION_DELAY : CHAR_DELAY;
175
- };
176
168
  useEffect3(() => {
177
- if (!shouldStream && !hasStartedStreaming.current) {
178
- setDisplayedContent(content);
179
- handleIsTextStreaming?.(false);
180
- return;
169
+ contentRef.current = content;
170
+ if (hasStartedStreaming.current && !timerRef.current && indexRef.current < contentRef.current.length) {
171
+ typeNext();
181
172
  }
182
- handleIsTextStreaming?.(true);
183
- hasStartedStreaming.current = true;
184
- if (displayedContent.length < content.length) {
185
- const delay = getDelayForChar(content, displayedContent.length);
186
- timeoutId.current = setTimeout(() => {
187
- setDisplayedContent((prev) => prev + content[prev.length]);
173
+ }, [content]);
174
+ const typeNext = useCallback(() => {
175
+ if (indexRef.current < contentRef.current.length) {
176
+ const nextChar = contentRef.current.charAt(indexRef.current);
177
+ setDisplayedText((prev) => prev + nextChar);
178
+ indexRef.current++;
179
+ const delay = /[.!?;:]/.test(nextChar) ? PUNCTUATION_DELAY : CHAR_DELAY;
180
+ timerRef.current = setTimeout(() => {
181
+ timerRef.current = null;
182
+ typeNext();
188
183
  }, delay);
189
184
  } else {
190
185
  handleIsTextStreaming?.(false);
191
186
  }
187
+ }, []);
188
+ useEffect3(() => {
189
+ if (!shouldStream && !hasStartedStreaming.current) {
190
+ setDisplayedText(contentRef.current);
191
+ indexRef.current = contentRef.current.length;
192
+ if (timerRef.current) {
193
+ clearTimeout(timerRef.current);
194
+ timerRef.current = null;
195
+ }
196
+ handleIsTextStreaming?.(false);
197
+ } else {
198
+ if (indexRef.current < contentRef.current.length && !timerRef.current) {
199
+ handleIsTextStreaming?.(true);
200
+ hasStartedStreaming.current = true;
201
+ typeNext();
202
+ }
203
+ }
192
204
  return () => {
193
- if (timeoutId.current) clearTimeout(timeoutId.current);
205
+ if (timerRef.current) {
206
+ clearTimeout(timerRef.current);
207
+ timerRef.current = null;
208
+ }
194
209
  };
195
- }, [
196
- content,
197
- displayedContent,
198
- shouldStream,
199
- getDelayForChar,
200
- handleIsTextStreaming
201
- ]);
202
- return displayedContent;
210
+ }, [shouldStream, typeNext]);
211
+ return displayedText;
203
212
  }
204
213
  export {
205
214
  reducer,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/hooks/use-toast.ts","../../../src/components/hooks/use-document.tsx","../../../src/components/hooks/use-resize-observer.ts","../../../src/components/hooks/use-text-streaming.ts"],"sourcesContent":["\"use client\";\n\n// Inspired by react-hot-toast library\nimport * as React from \"react\";\n\nimport type {\n ToastActionElement,\n ToastProps,\n} from \"../../components/atoms/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { ApiError, ActionResponse } from \"../../types/type\";\n\nexport const useDocumentReader = (\n url: string,\n getDocument: (id: string) => Promise<ActionResponse<Blob>>,\n) => {\n const [loading, setLoading] = useState<boolean>(true);\n const [error, setError] = useState<string | null>(null);\n const [document, setDocument] = useState<Blob | null>(null);\n\n const handleDocumentError = (error: ApiError) => {\n const errorMessage = \"Hubo un error al obtener el documento. Por favor ponganse en contacto con el administrador.\";\n setError(errorMessage);\n throw new Error(error?.message || 'Unknown error');\n };\n\n const resetDocument = () => {\n setDocument(null);\n };\n\n const fetchDocument = async () => {\n setLoading(true);\n setError(null);\n \n try {\n const res = await getDocument(url);\n if (!res.success) {\n handleDocumentError(res.error as ApiError || new Error('Unknown error'));\n setLoading(false);\n return;\n }\n res.data && setDocument(res.data);\n } catch (error) {\n handleDocumentError(error as ApiError);\n } finally {\n setLoading(false);\n }\n };\n\n return { document, loading, fetchDocument, resetDocument, error };\n};\n","import { useEffect, useRef } from 'react';\n\ntype ResizeObserverOptions = {\n box?: 'content-box' | 'border-box';\n};\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[], observer: ResizeObserver) => void;\n\nexport default function useResizeObserver(\n element: Element | null,\n options: ResizeObserverOptions | undefined,\n observerCallback: ResizeObserverCallback\n): void {\n const observerRef = useRef<ResizeObserver | null>(null);\n\n useEffect(() => {\n if (!element) return;\n\n observerRef.current = new ResizeObserver(observerCallback);\n observerRef.current.observe(element, options);\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n };\n }, [element, options, observerCallback]);\n}\n","import { useEffect, useRef, useState } from \"react\";\nconst CHAR_DELAY = 25;\nconst PUNCTUATION_DELAY = 200;\nconst PUNCTUATION_MARKS = [\".\", \"!\", \"?\", \";\", \":\"];\n\nfunction useTextStreaming(\n content: string,\n shouldStream: boolean,\n handleIsTextStreaming?: (isStreaming: boolean) => void\n) {\n const [displayedContent, setDisplayedContent] = useState<string>(\"\");\n const timeoutId = useRef<NodeJS.Timeout | null>(null);\n const hasStartedStreaming = useRef<boolean>(false);\n\n const getDelayForChar = (text: string, position: number): number => {\n if (position === 0) return CHAR_DELAY;\n\n const previousChar = text[position - 1] || '';\n const isEllipsis = text.slice(position - 1, position + 2) === \"...\";\n\n if (isEllipsis) {\n return CHAR_DELAY;\n }\n\n return PUNCTUATION_MARKS.includes(previousChar)\n ? PUNCTUATION_DELAY\n : CHAR_DELAY;\n };\n\n useEffect(() => {\n if (!shouldStream && !hasStartedStreaming.current) {\n setDisplayedContent(content);\n handleIsTextStreaming?.(false);\n return;\n }\n\n handleIsTextStreaming?.(true);\n hasStartedStreaming.current = true;\n\n if (displayedContent.length < content.length) {\n const delay = getDelayForChar(content, displayedContent.length);\n timeoutId.current = setTimeout(() => {\n setDisplayedContent((prev) => prev + content[prev.length]);\n }, delay);\n } else {\n handleIsTextStreaming?.(false);\n }\n\n return () => {\n if (timeoutId.current) clearTimeout(timeoutId.current);\n };\n }, [\n content,\n displayedContent,\n shouldStream,\n getDelayForChar,\n handleIsTextStreaming,\n ]);\n\n return displayedContent;\n}\n\nexport { useTextStreaming };\n"],"mappings":"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","names":["toast","props","useState","error","useEffect","useEffect","useRef","useState"]}
1
+ {"version":3,"sources":["../../../src/components/hooks/use-toast.ts","../../../src/components/hooks/use-document.tsx","../../../src/components/hooks/use-resize-observer.ts","../../../src/components/hooks/use-text-streaming.ts"],"sourcesContent":["\"use client\";\n\n// Inspired by react-hot-toast library\nimport * as React from \"react\";\n\nimport type {\n ToastActionElement,\n ToastProps,\n} from \"../../components/atoms/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { ApiError, ActionResponse } from \"../../types/type\";\n\nexport const useDocumentReader = (\n url: string,\n getDocument: (id: string) => Promise<ActionResponse<Blob>>,\n) => {\n const [loading, setLoading] = useState<boolean>(true);\n const [error, setError] = useState<string | null>(null);\n const [document, setDocument] = useState<Blob | null>(null);\n\n const handleDocumentError = (error: ApiError) => {\n const errorMessage = \"Hubo un error al obtener el documento. Por favor ponganse en contacto con el administrador.\";\n setError(errorMessage);\n throw new Error(error?.message || 'Unknown error');\n };\n\n const resetDocument = () => {\n setDocument(null);\n };\n\n const fetchDocument = async () => {\n setLoading(true);\n setError(null);\n \n try {\n const res = await getDocument(url);\n if (!res.success) {\n handleDocumentError(res.error as ApiError || new Error('Unknown error'));\n setLoading(false);\n return;\n }\n res.data && setDocument(res.data);\n } catch (error) {\n handleDocumentError(error as ApiError);\n } finally {\n setLoading(false);\n }\n };\n\n return { document, loading, fetchDocument, resetDocument, error };\n};\n","import { useEffect, useRef } from 'react';\n\ntype ResizeObserverOptions = {\n box?: 'content-box' | 'border-box';\n};\n\ntype ResizeObserverCallback = (entries: ResizeObserverEntry[], observer: ResizeObserver) => void;\n\nexport default function useResizeObserver(\n element: Element | null,\n options: ResizeObserverOptions | undefined,\n observerCallback: ResizeObserverCallback\n): void {\n const observerRef = useRef<ResizeObserver | null>(null);\n\n useEffect(() => {\n if (!element) return;\n\n observerRef.current = new ResizeObserver(observerCallback);\n observerRef.current.observe(element, options);\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n };\n }, [element, options, observerCallback]);\n}\n","import { useState, useEffect, useRef, useCallback } from \"react\";\n\nconst CHAR_DELAY = 25;\nconst PUNCTUATION_DELAY = 400;\n\nexport function useTextStreaming(\n content: string,\n shouldStream: boolean,\n handleIsTextStreaming?: (isStreaming: boolean) => void\n) {\n const [displayedText, setDisplayedText] = useState(\"\");\n const contentRef = useRef(content);\n const indexRef = useRef(0);\n const timerRef = useRef<NodeJS.Timeout | null>(null);\n\n const hasStartedStreaming = useRef<boolean>(false);\n\n useEffect(() => {\n contentRef.current = content;\n if (hasStartedStreaming.current && !timerRef.current && indexRef.current < contentRef.current.length) {\n typeNext();\n }\n }, [content]);\n\n const typeNext = useCallback(() => {\n if (indexRef.current < contentRef.current.length) {\n const nextChar = contentRef.current.charAt(indexRef.current);\n setDisplayedText((prev) => prev + nextChar);\n indexRef.current++;\n\n const delay = /[.!?;:]/.test(nextChar) ? PUNCTUATION_DELAY : CHAR_DELAY;\n \n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n typeNext();\n }, delay);\n } else {\n handleIsTextStreaming?.(false);\n }\n }, []);\n\n useEffect(() => {\n if (!shouldStream && !hasStartedStreaming.current) {\n setDisplayedText(contentRef.current);\n indexRef.current = contentRef.current.length;\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n handleIsTextStreaming?.(false);\n } else {\n if (indexRef.current < contentRef.current.length && !timerRef.current) {\n handleIsTextStreaming?.(true);\n hasStartedStreaming.current = true;\n typeNext();\n }\n }\n\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n }, [shouldStream, typeNext]);\n\n return displayedText;\n}\n\n"],"mappings":"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","names":["toast","props","useState","error","useEffect","useState","useEffect","useRef"]}
@@ -2248,48 +2248,57 @@ var React32 = __toESM(require("react"));
2248
2248
  // src/components/hooks/use-text-streaming.ts
2249
2249
  var import_react6 = require("react");
2250
2250
  var CHAR_DELAY = 25;
2251
- var PUNCTUATION_DELAY = 200;
2252
- var PUNCTUATION_MARKS = [".", "!", "?", ";", ":"];
2251
+ var PUNCTUATION_DELAY = 400;
2253
2252
  function useTextStreaming(content, shouldStream, handleIsTextStreaming) {
2254
- const [displayedContent, setDisplayedContent] = (0, import_react6.useState)("");
2255
- const timeoutId = (0, import_react6.useRef)(null);
2253
+ const [displayedText, setDisplayedText] = (0, import_react6.useState)("");
2254
+ const contentRef = (0, import_react6.useRef)(content);
2255
+ const indexRef = (0, import_react6.useRef)(0);
2256
+ const timerRef = (0, import_react6.useRef)(null);
2256
2257
  const hasStartedStreaming = (0, import_react6.useRef)(false);
2257
- const getDelayForChar = (text, position) => {
2258
- if (position === 0) return CHAR_DELAY;
2259
- const previousChar = text[position - 1] || "";
2260
- const isEllipsis = text.slice(position - 1, position + 2) === "...";
2261
- if (isEllipsis) {
2262
- return CHAR_DELAY;
2263
- }
2264
- return PUNCTUATION_MARKS.includes(previousChar) ? PUNCTUATION_DELAY : CHAR_DELAY;
2265
- };
2266
2258
  (0, import_react6.useEffect)(() => {
2267
- if (!shouldStream && !hasStartedStreaming.current) {
2268
- setDisplayedContent(content);
2269
- handleIsTextStreaming?.(false);
2270
- return;
2259
+ contentRef.current = content;
2260
+ if (hasStartedStreaming.current && !timerRef.current && indexRef.current < contentRef.current.length) {
2261
+ typeNext();
2271
2262
  }
2272
- handleIsTextStreaming?.(true);
2273
- hasStartedStreaming.current = true;
2274
- if (displayedContent.length < content.length) {
2275
- const delay = getDelayForChar(content, displayedContent.length);
2276
- timeoutId.current = setTimeout(() => {
2277
- setDisplayedContent((prev) => prev + content[prev.length]);
2263
+ }, [content]);
2264
+ const typeNext = (0, import_react6.useCallback)(() => {
2265
+ if (indexRef.current < contentRef.current.length) {
2266
+ const nextChar = contentRef.current.charAt(indexRef.current);
2267
+ setDisplayedText((prev) => prev + nextChar);
2268
+ indexRef.current++;
2269
+ const delay = /[.!?;:]/.test(nextChar) ? PUNCTUATION_DELAY : CHAR_DELAY;
2270
+ timerRef.current = setTimeout(() => {
2271
+ timerRef.current = null;
2272
+ typeNext();
2278
2273
  }, delay);
2279
2274
  } else {
2280
2275
  handleIsTextStreaming?.(false);
2281
2276
  }
2277
+ }, []);
2278
+ (0, import_react6.useEffect)(() => {
2279
+ if (!shouldStream && !hasStartedStreaming.current) {
2280
+ setDisplayedText(contentRef.current);
2281
+ indexRef.current = contentRef.current.length;
2282
+ if (timerRef.current) {
2283
+ clearTimeout(timerRef.current);
2284
+ timerRef.current = null;
2285
+ }
2286
+ handleIsTextStreaming?.(false);
2287
+ } else {
2288
+ if (indexRef.current < contentRef.current.length && !timerRef.current) {
2289
+ handleIsTextStreaming?.(true);
2290
+ hasStartedStreaming.current = true;
2291
+ typeNext();
2292
+ }
2293
+ }
2282
2294
  return () => {
2283
- if (timeoutId.current) clearTimeout(timeoutId.current);
2295
+ if (timerRef.current) {
2296
+ clearTimeout(timerRef.current);
2297
+ timerRef.current = null;
2298
+ }
2284
2299
  };
2285
- }, [
2286
- content,
2287
- displayedContent,
2288
- shouldStream,
2289
- getDelayForChar,
2290
- handleIsTextStreaming
2291
- ]);
2292
- return displayedContent;
2300
+ }, [shouldStream, typeNext]);
2301
+ return displayedText;
2293
2302
  }
2294
2303
 
2295
2304
  // src/components/molecules/call-out.tsx