@votodigital-onpeui/react 0.1.27 → 0.1.29

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/modalGlobal/useModalGlobalStore.ts","../src/store/modalGlobal/useModalLoadingStore.ts","../src/store/modalGlobal/useModalLoadingPercentageStore.ts","../src/components/ModalGlobal/ModalLoadingPercentage.tsx","../src/components/ModalGlobal/ModalGlobalProvider.tsx","../src/utils/showGlobalModal.ts"],"names":["create","jsxs","jsx"],"mappings":";;;;;;;AAsDO,IAAM,mBAAA,GAAsB,MAAA,CAAyB,CAAC,GAAA,EAAK,GAAA,MAAS;AAAA,EACzE,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,IAAA;AAAA,EACT,OAAA,EAAS,CAAA;AAAA,EACT,QAAA,EAAU,IAAA;AAAA,EACV,iBAAA,EAAmB,IAAA;AAAA,EAEnB,SAAA,EAAW,CAAC,OAAA,KAAY;AACtB,IAAA,OAAO,IAAI,OAAA,CAAiB,CAAC,OAAA,KAAY;AACvC,MAAA,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,QACd,MAAA,EAAQ,IAAA;AAAA,QACR,OAAA;AAAA,QACA,OAAA,EAAS,MAAM,OAAA,GAAU,CAAA;AAAA,QACzB,QAAA,EAAU,OAAA;AAAA,QACV,iBAAA,EAAmB;AAAA,OACrB,CAAE,CAAA;AAAA,IACJ,CAAC,CAAA;AAAA,EACH,CAAA;AAAA,EAEA,kBAAA,EAAoB,CAAC,OAAA,KAAY;AAC/B,IAAA,OAAO,IAAI,OAAA,CAAqB,CAAC,OAAA,KAAY;AAC3C,MAAA,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,QACd,MAAA,EAAQ,IAAA;AAAA,QACR,OAAA;AAAA,QACA,OAAA,EAAS,MAAM,OAAA,GAAU,CAAA;AAAA,QACzB,QAAA,EAAU,IAAA;AAAA,QACV,iBAAA,EAAmB;AAAA,OACrB,CAAE,CAAA;AAAA,IACJ,CAAC,CAAA;AAAA,EACH,CAAA;AAAA,EAEA,UAAA,EAAY,CAAC,SAAA,GAAY,KAAA,KAAU;AACjC,IAAA,MAAM,EAAE,QAAA,EAAU,iBAAA,EAAkB,GAAI,GAAA,EAAI;AAC5C,IAAA,QAAA,GAAW,SAAS,CAAA;AACpB,IAAA,iBAAA,GAAoB,SAAA,GAAY,YAAY,QAAQ,CAAA;AACpD,IAAA,GAAA,CAAI,EAAE,QAAQ,KAAA,EAAO,OAAA,EAAS,MAAM,QAAA,EAAU,IAAA,EAAM,iBAAA,EAAmB,IAAA,EAAM,CAAA;AAAA,EAC/E,CAAA;AAAA,EAEA,oBAAA,EAAsB,CAAC,MAAA,KAAW;AAChC,IAAA,MAAM,EAAE,QAAA,EAAU,iBAAA,EAAkB,GAAI,GAAA,EAAI;AAC5C,IAAA,QAAA,GAAW,WAAW,SAAS,CAAA;AAC/B,IAAA,iBAAA,GAAoB,MAAM,CAAA;AAC1B,IAAA,GAAA,CAAI,EAAE,QAAQ,KAAA,EAAO,OAAA,EAAS,MAAM,QAAA,EAAU,IAAA,EAAM,iBAAA,EAAmB,IAAA,EAAM,CAAA;AAAA,EAC/E;AACF,CAAA,CAAE;ACzFK,IAAM,oBAAA,GAAuBA,MAAAA,CAA0B,CAAC,GAAA,MAAS;AAAA,EACtE,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,aAAA;AAAA,EACT,WAAA,EAAa,CAAC,OAAA,GAAU,aAAA,KAAkB,IAAI,EAAE,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,CAAA;AAAA,EACvE,YAAA,EAAc,MAAM,GAAA,CAAI,EAAE,QAAQ,KAAA,EAAO,OAAA,EAAS,eAAe;AACnE,CAAA,CAAE;ACHK,IAAM,8BAAA,GAAiCA,MAAAA,CAAoC,CAAC,GAAA,MAAS;AAAA,EAC1F,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,CAAA;AAAA,EACZ,qBAAA,EAAuB,CAAC,OAAA,GAAU,aAAA,KAChC,GAAA,CAAI,EAAE,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,UAAA,EAAY,CAAA,EAAG,CAAA;AAAA,EAC9C,gBAAA,EAAkB,CAAC,UAAA,KACjB,GAAA,CAAI,EAAE,UAAA,EAAY,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAC,GAAG,CAAA;AAAA,EAC5D,sBAAA,EAAwB,MACtB,GAAA,CAAI,EAAE,MAAA,EAAQ,OAAO,OAAA,EAAS,aAAA,EAAe,UAAA,EAAY,CAAA,EAAG;AAChE,CAAA,CAAE;ACVK,IAAM,yBAAyB,CAAC;AAAA,EACrC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA,GAAc;AAChB,CAAA,KAAmC;AACjC,EAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAC,CAAA;AAErD,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,YAAA,EAAY,IAAA;AAAA,MACZ,MAAA;AAAA,MACA,SAAS,MAAM;AAAA,MAAC,CAAA;AAAA,MAChB,aAAA,EAAa,IAAA;AAAA,MACb,iBAAA,EAAiB,IAAA;AAAA,MACjB,WAAA;AAAA,MAEA,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mEAAA,EAEb,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,GAAA,EAAA,EAAE,WAAU,+DAAA,EACV,QAAA,EAAA;AAAA,UAAA,OAAA;AAAA,UAAQ;AAAA,SAAA,EACX,CAAA;AAAA,wBAGA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qDAAA,EACb,QAAA,kBAAA,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,mEAAA;AAAA,YACV,KAAA,EAAO,EAAE,KAAA,EAAO,CAAA,EAAG,OAAO,CAAA,CAAA,CAAA,EAAI;AAAA,YAC9B,IAAA,EAAK,aAAA;AAAA,YACL,eAAA,EAAe,OAAA;AAAA,YACf,eAAA,EAAe,CAAA;AAAA,YACf,eAAA,EAAe,GAAA;AAAA,YACf,YAAA,EAAY;AAAA;AAAA,SACd,EACF,CAAA;AAAA,wBAGA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,+DAAA,EACV,QAAA,EAAA,OAAA,EACH;AAAA,OAAA,EACF;AAAA;AAAA,GACF;AAEJ,CAAA;ACjBO,IAAM,sBAAsB,CAAC;AAAA,EAClC,QAAA;AAAA,EACA,WAAA,GAAc,GAAA;AAAA,EACd,aAAA,GAAgB,GAAA;AAAA,EAChB,uBAAA,GAA0B;AAC5B,CAAA,KAAgC;AAC9B,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,UAAA,EAAY,oBAAA,KACnC,mBAAA,EAAoB;AACtB,EAAA,MAAM,EAAE,MAAA,EAAQ,aAAA,EAAe,OAAA,EAAS,cAAA,KACtC,oBAAA,EAAqB;AACvB,EAAA,MAAM;AAAA,IACJ,MAAA,EAAQ,gBAAA;AAAA,IACR,OAAA,EAAS,iBAAA;AAAA,IACT;AAAA,MACE,8BAAA,EAA+B;AAEnC,EAAA,uBACEC,KAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBAGDC,GAAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,MAAA;AAAA,QACA,OAAA,EAAS,MAAM,oBAAA,CAAqB,OAAO,CAAA;AAAA,QAC3C,KAAA,EAAO,SAAS,KAAA,IAAS,EAAA;AAAA,QACzB,SAAS,OAAA,EAAS,OAAA;AAAA,QAClB,SAAS,OAAA,EAAS,OAAA;AAAA,QAClB,MAAM,OAAA,EAAS,IAAA;AAAA,QACf,YAAY,OAAA,EAAS,UAAA;AAAA,QACrB,uBAAuB,OAAA,EAAS,qBAAA;AAAA,QAChC,eAAe,OAAA,EAAS,aAAA;AAAA,QACxB,OAAO,OAAA,EAAS,KAAA;AAAA,QAChB,WAAW,YAAY;AACrB,UAAA,MAAM,SAAS,SAAA,IAAY;AAC3B,UAAA,UAAA,CAAW,IAAI,CAAA;AAAA,QACjB,CAAA;AAAA,QACA,UAAU,MAAM;AACd,UAAA,OAAA,EAAS,QAAA,IAAW;AACpB,UAAA,UAAA,CAAW,KAAK,CAAA;AAAA,QAClB,CAAA;AAAA,QACA,gBAAA,EAAgB,IAAA;AAAA,QAChB,mBAAmB,OAAA,EAAS,iBAAA;AAAA,QAC5B,kBAAkB,OAAA,EAAS,gBAAA;AAAA,QAC3B;AAAA;AAAA,KACF;AAAA,oBAGAA,GAAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,aAAA;AAAA,QACR,OAAA,EAAS,cAAA;AAAA,QACT,WAAA,EAAa;AAAA;AAAA,KACf;AAAA,oBAGAA,GAAAA;AAAA,MAAC,sBAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,gBAAA;AAAA,QACR,OAAA,EAAS,iBAAA;AAAA,QACT,UAAA;AAAA,QACA,WAAA,EAAa;AAAA;AAAA;AACf,GAAA,EACF,CAAA;AAEJ;;;AC5EO,IAAM,kBAAkB,CAAC,OAAA,KAC9B,oBAAoB,QAAA,EAAS,CAAE,UAAU,OAAO;AAe3C,IAAM,2BAA2B,CAAC,OAAA,KACvC,oBAAoB,QAAA,EAAS,CAAE,mBAAmB,OAAO;AASpD,IAAM,mBAAmB,MAC9B,mBAAA,CAAoB,QAAA,EAAS,CAAE,WAAW,KAAK;AAG1C,IAAM,iBAAA,GAAoB,MAC/B,mBAAA,CAAoB,QAAA,EAAS,CAAE;AAc1B,IAAM,mBAAmB,MAC9B,mBAAA,CAAoB,QAAA,EAAS,CAAE,SAAS,cAAA,IAAkB;AAcrD,IAAM,oBAAoB,CAAC,OAAA,KAChC,qBAAqB,QAAA,EAAS,CAAE,YAAY,OAAO;AAG9C,IAAM,kBAAA,GAAqB,MAChC,oBAAA,CAAqB,QAAA,GAAW,YAAA;AAG3B,IAAM,mBAAA,GAAsB,MACjC,oBAAA,CAAqB,QAAA,EAAS,CAAE;AAmB3B,IAAM,8BAA8B,CAAC,OAAA,KAC1C,+BAA+B,QAAA,EAAS,CAAE,sBAAsB,OAAO;AAGlE,IAAM,gCAAgC,CAAC,UAAA,KAC5C,+BAA+B,QAAA,EAAS,CAAE,iBAAiB,UAAU;AAGhE,IAAM,4BAAA,GAA+B,MAC1C,8BAAA,CAA+B,QAAA,GAAW,sBAAA;AAGrC,IAAM,6BAAA,GAAgC,MAC3C,8BAAA,CAA+B,QAAA,EAAS,CAAE","file":"modal.mjs","sourcesContent":["import { create } from \"zustand\";\r\nimport type { ReactNode } from \"react\";\r\nimport type { ModalType } from \"../../components/Feedback/ModalConfirm/ModalConfirm\";\r\n\r\nexport type { ModalType };\r\n\r\nexport type ModalResult = \"confirm\" | \"cancel\" | \"close\";\r\n\r\n/**\r\n * Payload del modal global.\r\n * Combina los props de ModalGlobalComponent (type, buttonMode, content)\r\n * con los de ModalConfirm (icon, color, twoButtons).\r\n * Los props del global component predominan; color e icon son overrides manuales.\r\n */\r\nexport interface ModalPayload {\r\n title: string;\r\n /** Contenido del modal (string o JSX). Alias: content */\r\n message?: ReactNode;\r\n /** Alias de message para compatibilidad */\r\n content?: ReactNode;\r\n /** Tipo semántico: determina color de icono, título y botón */\r\n type?: ModalType;\r\n /** \"double\" muestra el botón cancelar */\r\n buttonMode?: \"single\" | \"double\";\r\n /** Deshabilita el botón confirmar */\r\n disabledConfirmButton?: boolean;\r\n /** Deshabilita el cierre del modal */\r\n closeDisabled?: boolean;\r\n /** Override manual del color del icono y título */\r\n color?: \"red\" | \"blue\" | \"skyblue\" | \"yellow\";\r\n onConfirm?: () => void | Promise<void>;\r\n onCancel?: () => void | Promise<void>;\r\n textButtonConfirm?: string;\r\n textButtonCancel?: string;\r\n /**\r\n * Marca este modal como controlado por axios interceptor.\r\n * Cuando es true, los handlers de cambio de ruta NO deben cerrarlo.\r\n */\r\n alreadyHandled?: boolean;\r\n}\r\n\r\ninterface ModalGlobalState {\r\n isOpen: boolean;\r\n payload: ModalPayload | null;\r\n modalId: number;\r\n _resolve: ((result: boolean) => void) | null;\r\n _resolveWithClose: ((result: ModalResult) => void) | null;\r\n\r\n openModal: (payload: ModalPayload) => Promise<boolean>;\r\n openModalWithClose: (payload: ModalPayload) => Promise<ModalResult>;\r\n closeModal: (confirmed?: boolean) => void;\r\n closeModalWithResult: (result: ModalResult) => void;\r\n}\r\n\r\nexport const useModalGlobalStore = create<ModalGlobalState>((set, get) => ({\r\n isOpen: false,\r\n payload: null,\r\n modalId: 0,\r\n _resolve: null,\r\n _resolveWithClose: null,\r\n\r\n openModal: (payload) => {\r\n return new Promise<boolean>((resolve) => {\r\n set((state) => ({\r\n isOpen: true,\r\n payload,\r\n modalId: state.modalId + 1,\r\n _resolve: resolve,\r\n _resolveWithClose: null,\r\n }));\r\n });\r\n },\r\n\r\n openModalWithClose: (payload) => {\r\n return new Promise<ModalResult>((resolve) => {\r\n set((state) => ({\r\n isOpen: true,\r\n payload,\r\n modalId: state.modalId + 1,\r\n _resolve: null,\r\n _resolveWithClose: resolve,\r\n }));\r\n });\r\n },\r\n\r\n closeModal: (confirmed = false) => {\r\n const { _resolve, _resolveWithClose } = get();\r\n _resolve?.(confirmed);\r\n _resolveWithClose?.(confirmed ? \"confirm\" : \"cancel\");\r\n set({ isOpen: false, payload: null, _resolve: null, _resolveWithClose: null });\r\n },\r\n\r\n closeModalWithResult: (result) => {\r\n const { _resolve, _resolveWithClose } = get();\r\n _resolve?.(result === \"confirm\");\r\n _resolveWithClose?.(result);\r\n set({ isOpen: false, payload: null, _resolve: null, _resolveWithClose: null });\r\n },\r\n}));\r\n","import { create } from \"zustand\";\r\n\r\ninterface ModalLoadingState {\r\n isOpen: boolean;\r\n message: string;\r\n openLoading: (message?: string) => void;\r\n closeLoading: () => void;\r\n}\r\n\r\nexport const useModalLoadingStore = create<ModalLoadingState>((set) => ({\r\n isOpen: false,\r\n message: \"Cargando...\",\r\n openLoading: (message = \"Cargando...\") => set({ isOpen: true, message }),\r\n closeLoading: () => set({ isOpen: false, message: \"Cargando...\" }),\r\n}));\r\n","import { create } from \"zustand\";\r\n\r\ninterface ModalLoadingPercentageState {\r\n isOpen: boolean;\r\n message: string;\r\n percentage: number;\r\n openLoadingPercentage: (message?: string) => void;\r\n updatePercentage: (percentage: number) => void;\r\n closeLoadingPercentage: () => void;\r\n}\r\n\r\nexport const useModalLoadingPercentageStore = create<ModalLoadingPercentageState>((set) => ({\r\n isOpen: false,\r\n message: \"Cargando...\",\r\n percentage: 0,\r\n openLoadingPercentage: (message = \"Cargando...\") =>\r\n set({ isOpen: true, message, percentage: 0 }),\r\n updatePercentage: (percentage) =>\r\n set({ percentage: Math.min(100, Math.max(0, percentage)) }),\r\n closeLoadingPercentage: () =>\r\n set({ isOpen: false, message: \"Cargando...\", percentage: 0 }),\r\n}));\r\n","\"use client\";\r\n\r\nimport { Modal } from \"../Modal/Modal\";\r\n\r\ninterface ModalLoadingPercentageProps {\r\n isOpen: boolean;\r\n message: string;\r\n percentage: number;\r\n zIndexLevel?: number;\r\n}\r\n\r\nexport const ModalLoadingPercentage = ({\r\n isOpen,\r\n message,\r\n percentage,\r\n zIndexLevel = 300,\r\n}: ModalLoadingPercentageProps) => {\r\n const clamped = Math.min(100, Math.max(0, percentage));\r\n\r\n return (\r\n <Modal\r\n disableFocus\r\n isOpen={isOpen}\r\n onClose={() => {}}\r\n closeDisabled\r\n whitoutBackground\r\n zIndexLevel={zIndexLevel}\r\n >\r\n <div className=\"flex flex-col items-center gap-6 px-4 w-full max-w-xs md:max-w-sm\">\r\n {/* Percentage number */}\r\n <p className=\"text-white text-5xl md:text-[80px] font-semibold leading-none\">\r\n {clamped}%\r\n </p>\r\n\r\n {/* Progress bar */}\r\n <div className=\"w-full h-3 bg-white/30 rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-white rounded-full transition-all duration-300 ease-out\"\r\n style={{ width: `${clamped}%` }}\r\n role=\"progressbar\"\r\n aria-valuenow={clamped}\r\n aria-valuemin={0}\r\n aria-valuemax={100}\r\n aria-label={message}\r\n />\r\n </div>\r\n\r\n {/* Message */}\r\n <p className=\"text-white text-2xl md:text-[40px] text-center leading-normal\">\r\n {message}\r\n </p>\r\n </div>\r\n </Modal>\r\n );\r\n};\r\n\r\nexport default ModalLoadingPercentage;\r\n","\"use client\";\r\n\r\nimport type { ReactNode } from \"react\";\r\nimport { useModalGlobalStore } from \"../../store/modalGlobal/useModalGlobalStore\";\r\nimport { useModalLoadingStore } from \"../../store/modalGlobal/useModalLoadingStore\";\r\nimport { useModalLoadingPercentageStore } from \"../../store/modalGlobal/useModalLoadingPercentageStore\";\r\nimport { ModalConfirm } from \"../Feedback/ModalConfirm/ModalConfirm\";\r\nimport { ModalLoading } from \"../Feedback/ModalLoading/ModalLoading\";\r\nimport { ModalLoadingPercentage } from \"./ModalLoadingPercentage\";\r\n\r\ninterface ModalGlobalProviderProps {\r\n children: ReactNode;\r\n /** z-index del modal principal (default: 200) */\r\n zIndexLevel?: number;\r\n /** z-index del modal de loading (default: 300) */\r\n zIndexLoading?: number;\r\n /** z-index del modal de loading con porcentaje (default: 300) */\r\n zIndexLoadingPercentage?: number;\r\n}\r\n\r\n/**\r\n * Envuelve tu app (o layout) con este provider.\r\n * Renderiza ModalConfirm, ModalLoading y ModalLoadingPercentage vía portals.\r\n *\r\n * @example\r\n * // layout.tsx\r\n * <ModalGlobalProvider>\r\n * {children}\r\n * </ModalGlobalProvider>\r\n *\r\n * // Desde cualquier parte del código:\r\n * import { showGlobalModal, showGlobalLoading, closeGlobalLoading } from \"@votodigital-onpeui/react/modal\";\r\n *\r\n * await showGlobalModal({ title: \"¿Continuar?\", twoButtons: true });\r\n * showGlobalLoading(\"Procesando...\");\r\n * closeGlobalLoading();\r\n */\r\nexport const ModalGlobalProvider = ({\r\n children,\r\n zIndexLevel = 200,\r\n zIndexLoading = 300,\r\n zIndexLoadingPercentage = 300,\r\n}: ModalGlobalProviderProps) => {\r\n const { isOpen, payload, closeModal, closeModalWithResult } =\r\n useModalGlobalStore();\r\n const { isOpen: isLoadingOpen, message: loadingMessage } =\r\n useModalLoadingStore();\r\n const {\r\n isOpen: isPercentageOpen,\r\n message: percentageMessage,\r\n percentage,\r\n } = useModalLoadingPercentageStore();\r\n\r\n return (\r\n <>\r\n {children}\r\n\r\n {/* Modal principal — usa ModalConfirm de la librería directamente */}\r\n <ModalConfirm\r\n isOpen={isOpen}\r\n onClose={() => closeModalWithResult(\"close\")}\r\n title={payload?.title ?? \"\"}\r\n message={payload?.message}\r\n content={payload?.content}\r\n type={payload?.type}\r\n buttonMode={payload?.buttonMode}\r\n disabledConfirmButton={payload?.disabledConfirmButton}\r\n closeDisabled={payload?.closeDisabled}\r\n color={payload?.color}\r\n onConfirm={async () => {\r\n await payload?.onConfirm?.();\r\n closeModal(true);\r\n }}\r\n onCancel={() => {\r\n payload?.onCancel?.();\r\n closeModal(false);\r\n }}\r\n withoutAutoClose\r\n textButtonConfirm={payload?.textButtonConfirm}\r\n textButtonCancel={payload?.textButtonCancel}\r\n zIndexLevel={zIndexLevel}\r\n />\r\n\r\n {/* Loading */}\r\n <ModalLoading\r\n isOpen={isLoadingOpen}\r\n message={loadingMessage}\r\n zIndexLevel={zIndexLoading}\r\n />\r\n\r\n {/* Loading con porcentaje */}\r\n <ModalLoadingPercentage\r\n isOpen={isPercentageOpen}\r\n message={percentageMessage}\r\n percentage={percentage}\r\n zIndexLevel={zIndexLoadingPercentage}\r\n />\r\n </>\r\n );\r\n};\r\n\r\nexport default ModalGlobalProvider;\r\n","import { useModalGlobalStore } from \"../store/modalGlobal/useModalGlobalStore\";\r\nimport { useModalLoadingStore } from \"../store/modalGlobal/useModalLoadingStore\";\r\nimport type { ModalPayload, ModalResult } from \"../store/modalGlobal/useModalGlobalStore\";\r\n\r\n/**\r\n * Open the global modal. Returns a promise that resolves to `true` if the user\r\n * confirmed, or `false` if they cancelled/closed.\r\n *\r\n * @example\r\n * const confirmed = await showGlobalModal({\r\n * type: \"question\",\r\n * title: \"¿Eliminar votante?\",\r\n * message: \"Esta acción no se puede deshacer.\",\r\n * buttonMode: \"double\",\r\n * });\r\n *\r\n * @example — with custom JSX content\r\n * await showGlobalModal({\r\n * type: \"error\",\r\n * title: \"Error de sesión\",\r\n * content: <SesionExpiredDetails />,\r\n * });\r\n */\r\nexport const showGlobalModal = (payload: ModalPayload): Promise<boolean> =>\r\n useModalGlobalStore.getState().openModal(payload);\r\n\r\n/**\r\n * Like `showGlobalModal` but resolves to `\"confirm\"`, `\"cancel\"`, or `\"close\"`,\r\n * letting you distinguish between the three ways a modal can be dismissed.\r\n *\r\n * @example\r\n * const result = await showGlobalModalWithClose({\r\n * type: \"warning\",\r\n * title: \"Guardar cambios\",\r\n * buttonMode: \"double\",\r\n * });\r\n * if (result === \"confirm\") save();\r\n * if (result === \"close\") navigateAway();\r\n */\r\nexport const showGlobalModalWithClose = (payload: ModalPayload): Promise<ModalResult> =>\r\n useModalGlobalStore.getState().openModalWithClose(payload);\r\n\r\n/**\r\n * Programmatically close the global modal (resolves as cancelled).\r\n * Useful for layout/route-change handlers.\r\n *\r\n * ⚠️ Always check `isAlreadyHandled()` before calling this from a route handler\r\n * to avoid closing axios-controlled modals.\r\n */\r\nexport const closeGlobalModal = (): void =>\r\n useModalGlobalStore.getState().closeModal(false);\r\n\r\n/** Returns true if the global modal is currently open. */\r\nexport const isGlobalModalOpen = (): boolean =>\r\n useModalGlobalStore.getState().isOpen;\r\n\r\n/**\r\n * Returns true if the currently open modal was opened by an axios interceptor\r\n * (i.e. `alreadyHandled: true` was set). Use this to skip auto-close on\r\n * route changes.\r\n *\r\n * @example — in a Next.js layout\r\n * router.events.on(\"routeChangeStart\", () => {\r\n * if (isGlobalModalOpen() && !isAlreadyHandled()) {\r\n * closeGlobalModal();\r\n * }\r\n * });\r\n */\r\nexport const isAlreadyHandled = (): boolean =>\r\n useModalGlobalStore.getState().payload?.alreadyHandled ?? false;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Loading helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Show the global loading modal.\r\n *\r\n * @example\r\n * showGlobalLoading(\"Guardando cambios...\");\r\n * await api.save(data);\r\n * closeGlobalLoading();\r\n */\r\nexport const showGlobalLoading = (message?: string): void =>\r\n useModalLoadingStore.getState().openLoading(message);\r\n\r\n/** Close the global loading modal. */\r\nexport const closeGlobalLoading = (): void =>\r\n useModalLoadingStore.getState().closeLoading();\r\n\r\n/** Returns true if the global loading modal is currently visible. */\r\nexport const isGlobalLoadingOpen = (): boolean =>\r\n useModalLoadingStore.getState().isOpen;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Loading percentage helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nimport { useModalLoadingPercentageStore } from \"../store/modalGlobal/useModalLoadingPercentageStore\";\r\n\r\n/**\r\n * Show the global loading modal with a percentage progress bar.\r\n *\r\n * @example\r\n * showGlobalLoadingPercentage(\"Subiendo archivo...\");\r\n * for (const chunk of chunks) {\r\n * await upload(chunk);\r\n * updateGlobalLoadingPercentage(Math.round((i / chunks.length) * 100));\r\n * }\r\n * closeGlobalLoadingPercentage();\r\n */\r\nexport const showGlobalLoadingPercentage = (message?: string): void =>\r\n useModalLoadingPercentageStore.getState().openLoadingPercentage(message);\r\n\r\n/** Update the percentage value (0–100). Clamped automatically. */\r\nexport const updateGlobalLoadingPercentage = (percentage: number): void =>\r\n useModalLoadingPercentageStore.getState().updatePercentage(percentage);\r\n\r\n/** Close the global loading percentage modal. */\r\nexport const closeGlobalLoadingPercentage = (): void =>\r\n useModalLoadingPercentageStore.getState().closeLoadingPercentage();\r\n\r\n/** Returns true if the global loading percentage modal is currently visible. */\r\nexport const isGlobalLoadingPercentageOpen = (): boolean =>\r\n useModalLoadingPercentageStore.getState().isOpen;\r\n"]}
1
+ {"version":3,"sources":["../src/store/modalGlobal/useModalGlobalStore.ts","../src/store/modalGlobal/useModalLoadingStore.ts","../src/store/modalGlobal/useModalLoadingPercentageStore.ts","../src/components/Feedback/ModalLoadingPercentage/ModalLoadingPercentage.tsx","../src/components/ModalGlobal/ModalGlobalProvider.tsx","../src/utils/showGlobalModal.ts"],"names":["create","jsxs","jsx"],"mappings":"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","file":"modal.mjs","sourcesContent":["import { create } from \"zustand\";\r\nimport type { ReactNode } from \"react\";\r\nimport type { ModalType } from \"../../components/Feedback/ModalConfirm/ModalConfirm\";\r\n\r\nexport type { ModalType };\r\n\r\nexport type ModalResult = \"confirm\" | \"cancel\" | \"close\";\r\n\r\n/**\r\n * Payload del modal global.\r\n * Combina los props de ModalGlobalComponent (type, buttonMode, content)\r\n * con los de ModalConfirm (icon, color, twoButtons).\r\n * Los props del global component predominan; color e icon son overrides manuales.\r\n */\r\nexport interface ModalPayload {\r\n title: string;\r\n /** Contenido del modal (string o JSX). Alias: content */\r\n message?: ReactNode;\r\n /** Alias de message para compatibilidad */\r\n content?: ReactNode;\r\n /** Tipo semántico: determina color de icono, título y botón */\r\n type?: ModalType;\r\n /** \"double\" muestra el botón cancelar */\r\n buttonMode?: \"single\" | \"double\";\r\n /** Deshabilita el botón confirmar */\r\n disabledConfirmButton?: boolean;\r\n /** Deshabilita el cierre del modal */\r\n closeDisabled?: boolean;\r\n /** Override manual del color del icono y título */\r\n color?: \"red\" | \"blue\" | \"skyblue\" | \"yellow\";\r\n onConfirm?: () => void | Promise<void>;\r\n onCancel?: () => void | Promise<void>;\r\n textButtonConfirm?: string;\r\n textButtonCancel?: string;\r\n /**\r\n * Tiempo en ms para auto-confirmar el modal (ej: 30000 = 30s).\r\n * Útil para modales de error de sesión/red que deben cerrarse solos.\r\n */\r\n autoConfirmTimeout?: number;\r\n /**\r\n * Marca este modal como controlado por axios interceptor.\r\n * Cuando es true, los handlers de cambio de ruta NO deben cerrarlo.\r\n */\r\n alreadyHandled?: boolean;\r\n}\r\n\r\ninterface ModalGlobalState {\r\n isOpen: boolean;\r\n payload: ModalPayload | null;\r\n modalId: number;\r\n _resolve: ((result: boolean) => void) | null;\r\n _resolveWithClose: ((result: ModalResult) => void) | null;\r\n\r\n openModal: (payload: ModalPayload) => Promise<boolean>;\r\n openModalWithClose: (payload: ModalPayload) => Promise<ModalResult>;\r\n closeModal: (confirmed?: boolean) => void;\r\n closeModalWithResult: (result: ModalResult) => void;\r\n}\r\n\r\nexport const useModalGlobalStore = create<ModalGlobalState>((set, get) => ({\r\n isOpen: false,\r\n payload: null,\r\n modalId: 0,\r\n _resolve: null,\r\n _resolveWithClose: null,\r\n\r\n openModal: (payload) => {\r\n return new Promise<boolean>((resolve) => {\r\n set((state) => ({\r\n isOpen: true,\r\n payload,\r\n modalId: state.modalId + 1,\r\n _resolve: resolve,\r\n _resolveWithClose: null,\r\n }));\r\n });\r\n },\r\n\r\n openModalWithClose: (payload) => {\r\n return new Promise<ModalResult>((resolve) => {\r\n set((state) => ({\r\n isOpen: true,\r\n payload,\r\n modalId: state.modalId + 1,\r\n _resolve: null,\r\n _resolveWithClose: resolve,\r\n }));\r\n });\r\n },\r\n\r\n closeModal: (confirmed = false) => {\r\n const { _resolve, _resolveWithClose } = get();\r\n _resolve?.(confirmed);\r\n _resolveWithClose?.(confirmed ? \"confirm\" : \"cancel\");\r\n set({ isOpen: false, payload: null, _resolve: null, _resolveWithClose: null });\r\n },\r\n\r\n closeModalWithResult: (result) => {\r\n const { _resolve, _resolveWithClose } = get();\r\n _resolve?.(result === \"confirm\");\r\n _resolveWithClose?.(result);\r\n set({ isOpen: false, payload: null, _resolve: null, _resolveWithClose: null });\r\n },\r\n}));\r\n","import { create } from \"zustand\";\r\n\r\ninterface ModalLoadingState {\r\n isOpen: boolean;\r\n message: string;\r\n openLoading: (message?: string) => void;\r\n closeLoading: () => void;\r\n}\r\n\r\nexport const useModalLoadingStore = create<ModalLoadingState>((set) => ({\r\n isOpen: false,\r\n message: \"Cargando...\",\r\n openLoading: (message = \"Cargando...\") => set({ isOpen: true, message }),\r\n closeLoading: () => set({ isOpen: false, message: \"Cargando...\" }),\r\n}));\r\n","import { create } from \"zustand\";\r\n\r\ninterface ModalLoadingPercentageState {\r\n isOpen: boolean;\r\n message: string;\r\n percentage: number;\r\n openLoadingPercentage: (message?: string) => void;\r\n updatePercentage: (percentage: number) => void;\r\n closeLoadingPercentage: () => void;\r\n}\r\n\r\nexport const useModalLoadingPercentageStore = create<ModalLoadingPercentageState>((set) => ({\r\n isOpen: false,\r\n message: \"Cargando...\",\r\n percentage: 0,\r\n openLoadingPercentage: (message = \"Cargando...\") =>\r\n set({ isOpen: true, message, percentage: 0 }),\r\n updatePercentage: (percentage) =>\r\n set({ percentage: Math.min(100, Math.max(0, percentage)) }),\r\n closeLoadingPercentage: () =>\r\n set({ isOpen: false, message: \"Cargando...\", percentage: 0 }),\r\n}));\r\n","\"use client\";\n\nimport { Modal } from \"../../Modal/Modal\";\n\ninterface ModalLoadingPercentageProps {\n isOpen: boolean;\n message: string;\n percentage: number;\n zIndexLevel?: number;\n}\n\nexport const ModalLoadingPercentage = ({\n isOpen,\n message,\n percentage,\n zIndexLevel = 300,\n}: ModalLoadingPercentageProps) => {\n const clamped = Math.min(100, Math.max(0, percentage));\n\n return (\n <Modal\n disableFocus\n isOpen={isOpen}\n onClose={() => {}}\n closeDisabled\n whitoutBackground\n zIndexLevel={zIndexLevel}\n >\n <div className=\"flex flex-col items-center gap-6 px-4 w-full max-w-xs md:max-w-sm\">\n {/* Percentage number */}\n <p className=\"text-white text-5xl md:text-[80px] font-semibold leading-none\">\n {clamped}%\n </p>\n\n {/* Progress bar */}\n <div className=\"w-full h-3 bg-white/30 rounded-full overflow-hidden\">\n <div\n className=\"h-full bg-white rounded-full transition-all duration-300 ease-out\"\n style={{ width: `${clamped}%` }}\n role=\"progressbar\"\n aria-valuenow={clamped}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={message}\n />\n </div>\n\n {/* Message */}\n <p className=\"text-white text-2xl md:text-[40px] text-center leading-normal\">\n {message}\n </p>\n </div>\n </Modal>\n );\n};\n\nexport default ModalLoadingPercentage;\n","\"use client\";\n\nimport { useEffect, type ReactNode } from \"react\";\nimport { useModalGlobalStore } from \"../../store/modalGlobal/useModalGlobalStore\";\nimport { useModalLoadingStore } from \"../../store/modalGlobal/useModalLoadingStore\";\nimport { useModalLoadingPercentageStore } from \"../../store/modalGlobal/useModalLoadingPercentageStore\";\nimport { ModalConfirm } from \"../Feedback/ModalConfirm/ModalConfirm\";\nimport { ModalLoading } from \"../Feedback/ModalLoading/ModalLoading\";\nimport { ModalLoadingPercentage } from \"../Feedback/ModalLoadingPercentage/ModalLoadingPercentage\";\n\ninterface ModalGlobalProviderProps {\n children: ReactNode;\n /** z-index del modal principal (default: 200) */\n zIndexLevel?: number;\n /** z-index del modal de loading (default: 300) */\n zIndexLoading?: number;\n /** z-index del modal de loading con porcentaje (default: 300) */\n zIndexLoadingPercentage?: number;\n}\n\nexport const ModalGlobalProvider = ({\n children,\n zIndexLevel = 200,\n zIndexLoading = 300,\n zIndexLoadingPercentage = 300,\n}: ModalGlobalProviderProps) => {\n const { isOpen, payload, modalId, closeModal, closeModalWithResult } =\n useModalGlobalStore();\n const { isOpen: isLoadingOpen, message: loadingMessage } =\n useModalLoadingStore();\n const {\n isOpen: isPercentageOpen,\n message: percentageMessage,\n percentage,\n } = useModalLoadingPercentageStore();\n\n // Auto-confirmar el modal después del timeout especificado\n useEffect(() => {\n if (!isOpen || !payload?.autoConfirmTimeout) return;\n\n const timerId = setTimeout(async () => {\n await payload?.onConfirm?.();\n closeModal(true);\n }, payload.autoConfirmTimeout);\n\n return () => clearTimeout(timerId);\n }, [isOpen, modalId]);\n\n return (\n <>\n {children}\n\n {/* Modal principal — usa ModalConfirm de la librería directamente */}\n <ModalConfirm\n isOpen={isOpen}\n onClose={() => closeModalWithResult(\"close\")}\n title={payload?.title ?? \"\"}\n message={payload?.message}\n content={payload?.content}\n type={payload?.type}\n buttonMode={payload?.buttonMode}\n disabledConfirmButton={payload?.disabledConfirmButton}\n closeDisabled={payload?.closeDisabled}\n color={payload?.color}\n onConfirm={async () => {\n await payload?.onConfirm?.();\n closeModal(true);\n }}\n onCancel={() => {\n payload?.onCancel?.();\n closeModal(false);\n }}\n withoutAutoClose\n textButtonConfirm={payload?.textButtonConfirm}\n textButtonCancel={payload?.textButtonCancel}\n zIndexLevel={zIndexLevel}\n />\n\n {/* Loading */}\n <ModalLoading\n isOpen={isLoadingOpen}\n message={loadingMessage}\n zIndexLevel={zIndexLoading}\n />\n\n {/* Loading con porcentaje */}\n <ModalLoadingPercentage\n isOpen={isPercentageOpen}\n message={percentageMessage}\n percentage={percentage}\n zIndexLevel={zIndexLoadingPercentage}\n />\n </>\n );\n};\n\nexport default ModalGlobalProvider;\n","import { useModalGlobalStore } from \"../store/modalGlobal/useModalGlobalStore\";\r\nimport { useModalLoadingStore } from \"../store/modalGlobal/useModalLoadingStore\";\r\nimport type { ModalPayload, ModalResult } from \"../store/modalGlobal/useModalGlobalStore\";\r\n\r\n/**\r\n * Open the global modal. Returns a promise that resolves to `true` if the user\r\n * confirmed, or `false` if they cancelled/closed.\r\n *\r\n * @example\r\n * const confirmed = await showGlobalModal({\r\n * type: \"question\",\r\n * title: \"¿Eliminar votante?\",\r\n * message: \"Esta acción no se puede deshacer.\",\r\n * buttonMode: \"double\",\r\n * });\r\n *\r\n * @example — with custom JSX content\r\n * await showGlobalModal({\r\n * type: \"error\",\r\n * title: \"Error de sesión\",\r\n * content: <SesionExpiredDetails />,\r\n * });\r\n */\r\nexport const showGlobalModal = (payload: ModalPayload): Promise<boolean> =>\r\n useModalGlobalStore.getState().openModal(payload);\r\n\r\n/**\r\n * Like `showGlobalModal` but resolves to `\"confirm\"`, `\"cancel\"`, or `\"close\"`,\r\n * letting you distinguish between the three ways a modal can be dismissed.\r\n *\r\n * @example\r\n * const result = await showGlobalModalWithClose({\r\n * type: \"warning\",\r\n * title: \"Guardar cambios\",\r\n * buttonMode: \"double\",\r\n * });\r\n * if (result === \"confirm\") save();\r\n * if (result === \"close\") navigateAway();\r\n */\r\nexport const showGlobalModalWithClose = (payload: ModalPayload): Promise<ModalResult> =>\r\n useModalGlobalStore.getState().openModalWithClose(payload);\r\n\r\n/**\r\n * Programmatically close the global modal (resolves as cancelled).\r\n * Useful for layout/route-change handlers.\r\n *\r\n * ⚠️ Always check `isAlreadyHandled()` before calling this from a route handler\r\n * to avoid closing axios-controlled modals.\r\n */\r\nexport const closeGlobalModal = (): void =>\r\n useModalGlobalStore.getState().closeModal(false);\r\n\r\n/** Returns true if the global modal is currently open. */\r\nexport const isGlobalModalOpen = (): boolean =>\r\n useModalGlobalStore.getState().isOpen;\r\n\r\n/**\r\n * Returns true if the currently open modal was opened by an axios interceptor\r\n * (i.e. `alreadyHandled: true` was set). Use this to skip auto-close on\r\n * route changes.\r\n *\r\n * @example — in a Next.js layout\r\n * router.events.on(\"routeChangeStart\", () => {\r\n * if (isGlobalModalOpen() && !isAlreadyHandled()) {\r\n * closeGlobalModal();\r\n * }\r\n * });\r\n */\r\nexport const isAlreadyHandled = (): boolean =>\r\n useModalGlobalStore.getState().payload?.alreadyHandled ?? false;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Loading helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Show the global loading modal.\r\n *\r\n * @example\r\n * showGlobalLoading(\"Guardando cambios...\");\r\n * await api.save(data);\r\n * closeGlobalLoading();\r\n */\r\nexport const showGlobalLoading = (message?: string): void =>\r\n useModalLoadingStore.getState().openLoading(message);\r\n\r\n/** Close the global loading modal. */\r\nexport const closeGlobalLoading = (): void =>\r\n useModalLoadingStore.getState().closeLoading();\r\n\r\n/** Returns true if the global loading modal is currently visible. */\r\nexport const isGlobalLoadingOpen = (): boolean =>\r\n useModalLoadingStore.getState().isOpen;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Loading percentage helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nimport { useModalLoadingPercentageStore } from \"../store/modalGlobal/useModalLoadingPercentageStore\";\r\n\r\n/**\r\n * Show the global loading modal with a percentage progress bar.\r\n *\r\n * @example\r\n * showGlobalLoadingPercentage(\"Subiendo archivo...\");\r\n * for (const chunk of chunks) {\r\n * await upload(chunk);\r\n * updateGlobalLoadingPercentage(Math.round((i / chunks.length) * 100));\r\n * }\r\n * closeGlobalLoadingPercentage();\r\n */\r\nexport const showGlobalLoadingPercentage = (message?: string): void =>\r\n useModalLoadingPercentageStore.getState().openLoadingPercentage(message);\r\n\r\n/** Update the percentage value (0–100). Clamped automatically. */\r\nexport const updateGlobalLoadingPercentage = (percentage: number): void =>\r\n useModalLoadingPercentageStore.getState().updatePercentage(percentage);\r\n\r\n/** Close the global loading percentage modal. */\r\nexport const closeGlobalLoadingPercentage = (): void =>\r\n useModalLoadingPercentageStore.getState().closeLoadingPercentage();\r\n\r\n/** Returns true if the global loading percentage modal is currently visible. */\r\nexport const isGlobalLoadingPercentageOpen = (): boolean =>\r\n useModalLoadingPercentageStore.getState().isOpen;\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@votodigital-onpeui/react",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "Librería de componentes UI para proyectos ONPE",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",