softable-pixels-web 1.2.10 → 1.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ColorPicker-Dc83Om7x.js.map +1 -1
- package/dist/ContextMenu-CRd1Fgl0.js.map +1 -1
- package/dist/{DatePicker-QLL-43NJ.js → DatePicker-Bl7pIrHR.js} +128 -25
- package/dist/DatePicker-Bl7pIrHR.js.map +1 -0
- package/dist/{IconButton-qBhQj30V.js → IconButton-BGiieVPY.js} +3 -3
- package/dist/IconButton-BGiieVPY.js.map +1 -0
- package/dist/{Input-D9FPPcEO.js → Input-7PrKudvj.js} +2 -2
- package/dist/{Input-D9FPPcEO.js.map → Input-7PrKudvj.js.map} +1 -1
- package/dist/{MaskModule-B9d_CLgH.js → MaskModule-CQXVHDuV.js} +168 -3
- package/dist/MaskModule-CQXVHDuV.js.map +1 -0
- package/dist/Popover-DwxxEmVF.js.map +1 -1
- package/dist/Select-D5EznEQW.js.map +1 -1
- package/dist/{TabSwitch-BrFTSD3N.js → TabSwitch-DIHCG0vJ.js} +5 -3
- package/dist/TabSwitch-DIHCG0vJ.js.map +1 -0
- package/dist/base-popover.d.ts +3 -3
- package/dist/breadcrumb.d.ts +1 -1
- package/dist/button.d.ts +2 -2
- package/dist/checkbox.d.ts +2 -2
- package/dist/color-picker.d.ts +1 -1
- package/dist/context-menu.d.ts +1 -1
- package/dist/date-picker.d.ts +1 -1
- package/dist/date-picker.js +2 -1
- package/dist/icon-button.d.ts +1 -1
- package/dist/icon-button.js +1 -1
- package/dist/{index-Cx7UfQsD.d.ts → index-2hmoLtaJ.d.ts} +6 -5
- package/dist/{index-duKRdLdx.d.ts → index-BnNahlXB.d.ts} +4 -2
- package/dist/{index-BSRlF4M0.d.ts → index-Bxm90oSp.d.ts} +5 -4
- package/dist/{index-4OeaL4BA.d.ts → index-CLVlLUW1.d.ts} +2 -2
- package/dist/{index-BoDAFJKA.d.ts → index-Cg9O1rrv.d.ts} +5 -5
- package/dist/{index-yetEYul3.d.ts → index-ClRmImX5.d.ts} +2 -2
- package/dist/{index-Y5DBdVde.d.ts → index-CsubfLNp.d.ts} +14 -3
- package/dist/{index-B-QrzzEt.d.ts → index-CtH8kbOn.d.ts} +3 -3
- package/dist/{index-GDD7A_-t.d.ts → index-DHTU_QTw.d.ts} +3 -3
- package/dist/{index-BsuIAPD6.d.ts → index-DWfxn3wg.d.ts} +3 -3
- package/dist/{index-DZ68m68y.d.ts → index-Glw8jQ-T.d.ts} +6 -2
- package/dist/{index-DPF3Lmsv.d.ts → index-WFi4Q5f-.d.ts} +2 -2
- package/dist/{index-c9Jj2h1z.d.ts → index-ftKfqd7S.d.ts} +2 -1
- package/dist/{index-ece25l8L.d.ts → index-kc3NqscD.d.ts} +3 -3
- package/dist/{index-CMdalYHP.d.ts → index-y5WY0xGq.d.ts} +5 -5
- package/dist/index.d.ts +17 -17
- package/dist/index.js +5 -5
- package/dist/input.d.ts +1 -1
- package/dist/input.js +2 -2
- package/dist/mask-modules.d.ts +1 -1
- package/dist/mask-modules.js +1 -1
- package/dist/popover.d.ts +2 -2
- package/dist/select.d.ts +2 -2
- package/dist/skeleton.d.ts +1 -1
- package/dist/tab-switch.d.ts +1 -1
- package/dist/tab-switch.js +1 -1
- package/dist/text-area.d.ts +1 -1
- package/dist/{types-CRiyrGtn.d.ts → types-1ZNOd7Tt.d.ts} +3 -2
- package/dist/{types-Cb6hrEtg.d.ts → types-Dr8EuEht.d.ts} +2 -2
- package/dist/typography.d.ts +1 -1
- package/dist/{useThemedStyles-BVQKnv5r.d.ts → useThemedStyles-B9fVE7Wy.d.ts} +2 -25
- package/package.json +1 -1
- package/dist/DatePicker-QLL-43NJ.js.map +0 -1
- package/dist/IconButton-qBhQj30V.js.map +0 -1
- package/dist/MaskModule-B9d_CLgH.js.map +0 -1
- package/dist/TabSwitch-BrFTSD3N.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { n as styled, t as useThemedStyles } from "./useThemedStyles-B1E0m8Ih.js
|
|
|
2
2
|
import { t as Icon } from "./Icon-Ded27Khw.js";
|
|
3
3
|
import { t as Label } from "./Label-DYeW5MAo.js";
|
|
4
4
|
import { t as ErrorMessage } from "./ErrorMessage-W0yfhfJP.js";
|
|
5
|
-
import { r as MaskModule, t as Locale } from "./MaskModule-
|
|
5
|
+
import { r as MaskModule, t as Locale } from "./MaskModule-CQXVHDuV.js";
|
|
6
6
|
import { forwardRef, useEffect, useId, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
|
|
@@ -197,4 +197,4 @@ Input.displayName = "Input";
|
|
|
197
197
|
|
|
198
198
|
//#endregion
|
|
199
199
|
export { Input as t };
|
|
200
|
-
//# sourceMappingURL=Input-
|
|
200
|
+
//# sourceMappingURL=Input-7PrKudvj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input-D9FPPcEO.js","names":["value"],"sources":["../src/components/commons/inputs/Input/hooks/useInput/index.ts","../src/components/commons/inputs/Input/styles.ts","../src/components/commons/inputs/Input/index.tsx"],"sourcesContent":["// External Libraries\nimport { useState, useRef, useMemo, useEffect } from 'react'\n\n// Services\nimport { Locale, MaskModule } from 'src/services/MaskModule'\n\n// Types\nimport type { InputProps } from '../../types'\n\nexport function useInput({\n mask,\n delay,\n value,\n onChange,\n ...rest\n}: InputProps) {\n // Refs\n const inputRef = useRef<HTMLInputElement>(null)\n const timeoutRef = useRef<NodeJS.Timeout>(null)\n\n // States\n const [inputValue, setInputValue] = useState(value)\n const [showPassword, setShowPassword] = useState(false)\n\n // Constants\n const { minLength, maxLength } = useMemo(() => {\n const appliedMask = mask ? MaskModule.getMask(Locale.BR, mask) : undefined\n\n const minLength = appliedMask\n ? appliedMask.minLength || rest.minLength\n : rest.minLength\n\n const maxLength = appliedMask\n ? appliedMask.maxLength || rest.maxLength\n : rest.maxLength\n\n return { minLength, maxLength }\n }, [mask, rest.minLength, rest.maxLength])\n\n // UseEffects\n useEffect(() => {\n setInputValue(value)\n }, [value])\n\n // Functions\n function togglePasswordVisibility() {\n setShowPassword(prev => !prev)\n }\n\n function handleRefMethods() {\n return { focus: handleFocus, blur: handleBlur }\n }\n\n function handleFocus() {\n inputRef.current?.focus()\n }\n\n function handleBlur() {\n inputRef.current?.blur()\n }\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n let value = e.target.value\n\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n\n if (mask) {\n const module = MaskModule.getMask(Locale.BR, mask)\n if (module) value = module.format(value)\n }\n\n setInputValue(value)\n\n if (!delay) onChange?.(value)\n else {\n timeoutRef.current = setTimeout(() => onChange?.(value), delay)\n }\n }\n\n return {\n inputRef,\n minLength,\n maxLength,\n inputValue,\n showPassword,\n handleChange,\n handleRefMethods,\n togglePasswordVisibility\n }\n}\n","// Hooks\nimport { styled } from '@hooks/useThemedStyles/types'\n\n// Types\nimport type { InputProps } from './types'\n\nexport function createInputStyles(props: InputProps) {\n return styled({\n container: {\n width: '100%',\n\n display: 'flex',\n flexDirection: 'column',\n\n rowGap: '0.375rem'\n },\n wrapper: {\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n\n borderWidth: 1,\n columnGap: '0.25rem',\n borderRadius: '0.5rem',\n padding: '0.625rem 0.875rem',\n\n opacity: props.disabled ? 0.5 : 1,\n boxShadow: 'var(--px-shadow-default)',\n borderColor: props.errorMessage\n ? 'var(--px-color-error)'\n : 'var(--px-border-primary)',\n\n __rules: {\n '&:focus-within': {\n outlineOffset: '-1px',\n outline: `2px solid var(${props.errorMessage ? '--px-color-error' : '--px-color-primary'})`\n }\n }\n },\n\n input: {\n flex: 1,\n\n fontWeight: 500,\n fontSize: '1rem',\n lineHeight: '1.5rem',\n fontFamily: 'inherit',\n color: 'var(--px-text-primary)',\n\n __rules: {\n '&:disabled': {\n cursor: 'not-allowed'\n },\n\n '&:focus': {\n outline: 'none'\n },\n\n '&::placeholder': {\n fontWeight: 400,\n color: 'var(--px-text-secondary)'\n }\n }\n },\n\n button: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n\n cursor: 'pointer',\n padding: '0.25rem',\n borderRadius: '0.5rem',\n\n __rules: {\n '&:focus': {\n outline: '1px solid var(--px-border-primary)'\n }\n }\n }\n })\n}\n","/** biome-ignore-all lint/a11y/noAutofocus: It's a custom input component */\n// External Libraries\nimport { forwardRef, useId, useImperativeHandle, useMemo } from 'react'\n\n// Components\nimport { Label } from '../../toolkit/Label'\nimport { Icon } from '@components/commons/toolkit/Icon'\nimport { ErrorMessage } from '../../toolkit/ErrorMessage'\n\n// Types\nimport type { InputProps, InputMethods } from './types'\n\n// Hooks\nimport { useInput } from './hooks/useInput'\nimport { useThemedStyles } from '@hooks/useThemedStyles'\n\n// Styles\nimport { createInputStyles } from './styles'\n\nexport const Input = forwardRef<InputMethods, InputProps>((props, ref) => {\n // Constants\n const reactId = useId()\n const inputId = useMemo(() => {\n return props.id || `input-${reactId}`\n }, [props.id, reactId])\n\n // Hooks\n const {\n inputRef,\n minLength,\n maxLength,\n inputValue,\n showPassword,\n handleChange,\n handleRefMethods,\n togglePasswordVisibility\n } = useInput(props)\n useImperativeHandle(ref, handleRefMethods)\n\n // Hooks\n const { styles, classes } = useThemedStyles(props, createInputStyles, {\n pick: p => [p.disabled, p.errorMessage],\n override: props.styles,\n applyCommonProps: true,\n commonSlot: 'container'\n })\n\n // Functions\n function getType() {\n if (props.type === 'password' && showPassword) return 'text'\n return props.type\n }\n\n function renderEndContent() {\n if (props.type === 'password') {\n return (\n <button\n type=\"button\"\n style={styles.button}\n className={classes.button}\n onClick={togglePasswordVisibility}\n >\n <Icon\n size=\"sm\"\n name={showPassword ? 'general-eye-off' : 'general-eye'}\n />\n </button>\n )\n }\n\n return props.endIcon ?? null\n }\n\n return (\n <div style={styles.container}>\n {props.hideLabel ? null : (\n <Label\n htmlFor={inputId}\n label={props.label}\n required={props.required}\n requiredColor={props.requiredColor}\n {...props.labelConfig}\n />\n )}\n\n <div style={styles.wrapper} className={classes.wrapper}>\n {props.startIcon}\n\n <input\n ref={inputRef}\n id={inputId}\n type={getType()}\n value={inputValue}\n style={styles.input}\n minLength={minLength}\n maxLength={maxLength}\n required={props.required}\n disabled={props.disabled}\n className={classes.input}\n autoFocus={props.autoFocus}\n spellCheck={props.spellCheck}\n autoCorrect={props.autoCorrect}\n placeholder={props.placeholder}\n autoComplete={props.autoComplete}\n autoCapitalize={props.autoCapitalize}\n aria-label={!props.hideLabel ? undefined : props.label}\n onChange={handleChange}\n />\n\n {renderEndContent()}\n </div>\n\n {props.errorMessage ? (\n <ErrorMessage message={props.errorMessage} />\n ) : null}\n </div>\n )\n})\n\nInput.displayName = 'Input'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Input-7PrKudvj.js","names":["value"],"sources":["../src/components/commons/inputs/Input/hooks/useInput/index.ts","../src/components/commons/inputs/Input/styles.ts","../src/components/commons/inputs/Input/index.tsx"],"sourcesContent":["// External Libraries\nimport { useState, useRef, useMemo, useEffect } from 'react'\n\n// Services\nimport { Locale, MaskModule } from 'src/services/MaskModule'\n\n// Types\nimport type { InputProps } from '../../types'\n\nexport function useInput({\n mask,\n delay,\n value,\n onChange,\n ...rest\n}: InputProps) {\n // Refs\n const inputRef = useRef<HTMLInputElement>(null)\n const timeoutRef = useRef<NodeJS.Timeout>(null)\n\n // States\n const [inputValue, setInputValue] = useState(value)\n const [showPassword, setShowPassword] = useState(false)\n\n // Constants\n const { minLength, maxLength } = useMemo(() => {\n const appliedMask = mask ? MaskModule.getMask(Locale.BR, mask) : undefined\n\n const minLength = appliedMask\n ? appliedMask.minLength || rest.minLength\n : rest.minLength\n\n const maxLength = appliedMask\n ? appliedMask.maxLength || rest.maxLength\n : rest.maxLength\n\n return { minLength, maxLength }\n }, [mask, rest.minLength, rest.maxLength])\n\n // UseEffects\n useEffect(() => {\n setInputValue(value)\n }, [value])\n\n // Functions\n function togglePasswordVisibility() {\n setShowPassword(prev => !prev)\n }\n\n function handleRefMethods() {\n return { focus: handleFocus, blur: handleBlur }\n }\n\n function handleFocus() {\n inputRef.current?.focus()\n }\n\n function handleBlur() {\n inputRef.current?.blur()\n }\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n let value = e.target.value\n\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n\n if (mask) {\n const module = MaskModule.getMask(Locale.BR, mask)\n if (module) value = module.format(value)\n }\n\n setInputValue(value)\n\n if (!delay) onChange?.(value)\n else {\n timeoutRef.current = setTimeout(() => onChange?.(value), delay)\n }\n }\n\n return {\n inputRef,\n minLength,\n maxLength,\n inputValue,\n showPassword,\n handleChange,\n handleRefMethods,\n togglePasswordVisibility\n }\n}\n","// Hooks\nimport { styled } from '@hooks/useThemedStyles/types'\n\n// Types\nimport type { InputProps } from './types'\n\nexport function createInputStyles(props: InputProps) {\n return styled({\n container: {\n width: '100%',\n\n display: 'flex',\n flexDirection: 'column',\n\n rowGap: '0.375rem'\n },\n wrapper: {\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n\n borderWidth: 1,\n columnGap: '0.25rem',\n borderRadius: '0.5rem',\n padding: '0.625rem 0.875rem',\n\n opacity: props.disabled ? 0.5 : 1,\n boxShadow: 'var(--px-shadow-default)',\n borderColor: props.errorMessage\n ? 'var(--px-color-error)'\n : 'var(--px-border-primary)',\n\n __rules: {\n '&:focus-within': {\n outlineOffset: '-1px',\n outline: `2px solid var(${props.errorMessage ? '--px-color-error' : '--px-color-primary'})`\n }\n }\n },\n\n input: {\n flex: 1,\n\n fontWeight: 500,\n fontSize: '1rem',\n lineHeight: '1.5rem',\n fontFamily: 'inherit',\n color: 'var(--px-text-primary)',\n\n __rules: {\n '&:disabled': {\n cursor: 'not-allowed'\n },\n\n '&:focus': {\n outline: 'none'\n },\n\n '&::placeholder': {\n fontWeight: 400,\n color: 'var(--px-text-secondary)'\n }\n }\n },\n\n button: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n\n cursor: 'pointer',\n padding: '0.25rem',\n borderRadius: '0.5rem',\n\n __rules: {\n '&:focus': {\n outline: '1px solid var(--px-border-primary)'\n }\n }\n }\n })\n}\n","/** biome-ignore-all lint/a11y/noAutofocus: It's a custom input component */\n// External Libraries\nimport { forwardRef, useId, useImperativeHandle, useMemo } from 'react'\n\n// Components\nimport { Label } from '../../toolkit/Label'\nimport { Icon } from '@components/commons/toolkit/Icon'\nimport { ErrorMessage } from '../../toolkit/ErrorMessage'\n\n// Types\nimport type { InputProps, InputMethods } from './types'\n\n// Hooks\nimport { useInput } from './hooks/useInput'\nimport { useThemedStyles } from '@hooks/useThemedStyles'\n\n// Styles\nimport { createInputStyles } from './styles'\n\nexport const Input = forwardRef<InputMethods, InputProps>((props, ref) => {\n // Constants\n const reactId = useId()\n const inputId = useMemo(() => {\n return props.id || `input-${reactId}`\n }, [props.id, reactId])\n\n // Hooks\n const {\n inputRef,\n minLength,\n maxLength,\n inputValue,\n showPassword,\n handleChange,\n handleRefMethods,\n togglePasswordVisibility\n } = useInput(props)\n useImperativeHandle(ref, handleRefMethods)\n\n // Hooks\n const { styles, classes } = useThemedStyles(props, createInputStyles, {\n pick: p => [p.disabled, p.errorMessage],\n override: props.styles,\n applyCommonProps: true,\n commonSlot: 'container'\n })\n\n // Functions\n function getType() {\n if (props.type === 'password' && showPassword) return 'text'\n return props.type\n }\n\n function renderEndContent() {\n if (props.type === 'password') {\n return (\n <button\n type=\"button\"\n style={styles.button}\n className={classes.button}\n onClick={togglePasswordVisibility}\n >\n <Icon\n size=\"sm\"\n name={showPassword ? 'general-eye-off' : 'general-eye'}\n />\n </button>\n )\n }\n\n return props.endIcon ?? null\n }\n\n return (\n <div style={styles.container}>\n {props.hideLabel ? null : (\n <Label\n htmlFor={inputId}\n label={props.label}\n required={props.required}\n requiredColor={props.requiredColor}\n {...props.labelConfig}\n />\n )}\n\n <div style={styles.wrapper} className={classes.wrapper}>\n {props.startIcon}\n\n <input\n ref={inputRef}\n id={inputId}\n type={getType()}\n value={inputValue}\n style={styles.input}\n minLength={minLength}\n maxLength={maxLength}\n required={props.required}\n disabled={props.disabled}\n className={classes.input}\n autoFocus={props.autoFocus}\n spellCheck={props.spellCheck}\n autoCorrect={props.autoCorrect}\n placeholder={props.placeholder}\n autoComplete={props.autoComplete}\n autoCapitalize={props.autoCapitalize}\n aria-label={!props.hideLabel ? undefined : props.label}\n onChange={handleChange}\n />\n\n {renderEndContent()}\n </div>\n\n {props.errorMessage ? (\n <ErrorMessage message={props.errorMessage} />\n ) : null}\n </div>\n )\n})\n\nInput.displayName = 'Input'\n"],"mappings":"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"}
|
|
@@ -52,6 +52,7 @@ const MaskType = {
|
|
|
52
52
|
DOCUMENT: "DOCUMENT",
|
|
53
53
|
PHONE: "PHONE",
|
|
54
54
|
DATE: "DATE",
|
|
55
|
+
TIME: "TIME",
|
|
55
56
|
FLOAT: "FLOAT",
|
|
56
57
|
INTEGER: "INTEGER",
|
|
57
58
|
MONEY: "MONEY",
|
|
@@ -203,6 +204,104 @@ var DateMask = class extends BaseMask {
|
|
|
203
204
|
}
|
|
204
205
|
};
|
|
205
206
|
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/services/MaskModule/locales/br/masks/TimeMask.ts
|
|
209
|
+
const TIME_PATTERN = "XX:XX";
|
|
210
|
+
/**
|
|
211
|
+
* Formats time input allowing editing at any position.
|
|
212
|
+
* Uses pattern-based formatting similar to CPF/CNPJ masks.
|
|
213
|
+
*
|
|
214
|
+
* Key difference from TimeMask:
|
|
215
|
+
* - TimeMask: Sequential digit-by-digit formatting (good for append-only input)
|
|
216
|
+
* - TimeInputMask: Pattern-based formatting (allows editing anywhere in the string)
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* const mask = new TimeInputMask({ timeFormat: '24h' })
|
|
220
|
+
* mask.format('1430') // "14:30"
|
|
221
|
+
* mask.format('1530') // "15:30" (can change first digit easily)
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* const mask12h = new TimeInputMask({ timeFormat: '12h' })
|
|
225
|
+
* mask12h.format('0230') // "02:30"
|
|
226
|
+
*/
|
|
227
|
+
var TimeMask = class extends BaseMask {
|
|
228
|
+
timeFormat;
|
|
229
|
+
constructor({ timeFormat = "24h", minLength = 5, maxLength = 5 } = {}) {
|
|
230
|
+
super(minLength, maxLength);
|
|
231
|
+
this.timeFormat = timeFormat;
|
|
232
|
+
}
|
|
233
|
+
format(value) {
|
|
234
|
+
const digits = onlyDigits(value);
|
|
235
|
+
if (!limitLength(digits, 4)) return "";
|
|
236
|
+
const formatted = applyPattern(digits, TIME_PATTERN);
|
|
237
|
+
let result = formatted;
|
|
238
|
+
if (formatted.length >= 3) result = this.validateAndCorrect(formatted);
|
|
239
|
+
return limitLength(result, this.maxLength);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Validates and corrects the formatted time string
|
|
243
|
+
*/
|
|
244
|
+
validateAndCorrect(value) {
|
|
245
|
+
if (!value) return "00:00";
|
|
246
|
+
const parts = value.split(":");
|
|
247
|
+
const hours = parts[0] || "";
|
|
248
|
+
const minutes = parts[1] || "";
|
|
249
|
+
const correctedHours = this.correctHours(hours);
|
|
250
|
+
if (!minutes) return hours.length === 2 ? `${correctedHours}:` : correctedHours;
|
|
251
|
+
return `${correctedHours}:${this.correctMinutes(minutes)}`;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Corrects hours to valid range based on format
|
|
255
|
+
*/
|
|
256
|
+
correctHours(hours) {
|
|
257
|
+
if (!hours) return "";
|
|
258
|
+
if (hours.length === 1) {
|
|
259
|
+
const digit = parseInt(hours, 10);
|
|
260
|
+
if (this.timeFormat === "24h") {
|
|
261
|
+
if (digit > 2) return `0${digit}`;
|
|
262
|
+
return hours;
|
|
263
|
+
} else {
|
|
264
|
+
if (digit === 0) return "0";
|
|
265
|
+
if (digit > 1) return `0${digit}`;
|
|
266
|
+
return hours;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
let hourNum = parseInt(hours, 10);
|
|
270
|
+
if (this.timeFormat === "24h") {
|
|
271
|
+
if (hourNum > 23) hourNum = 23;
|
|
272
|
+
if (hourNum < 0) hourNum = 0;
|
|
273
|
+
} else {
|
|
274
|
+
if (hourNum === 0) hourNum = 12;
|
|
275
|
+
if (hourNum > 12) hourNum = 12;
|
|
276
|
+
if (hourNum < 1) hourNum = 1;
|
|
277
|
+
}
|
|
278
|
+
return hourNum.toString().padStart(2, "0");
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Corrects minutes to valid range (00-59)
|
|
282
|
+
*/
|
|
283
|
+
correctMinutes(minutes) {
|
|
284
|
+
if (!minutes) return "";
|
|
285
|
+
if (minutes.length === 1) {
|
|
286
|
+
const digit = parseInt(minutes, 10);
|
|
287
|
+
if (digit > 5) return `0${digit}`;
|
|
288
|
+
return minutes;
|
|
289
|
+
}
|
|
290
|
+
let minuteNum = parseInt(minutes, 10);
|
|
291
|
+
if (minuteNum > 59) minuteNum = 59;
|
|
292
|
+
if (minuteNum < 0) minuteNum = 0;
|
|
293
|
+
return minuteNum.toString().padStart(2, "0");
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Adds AM/PM period to formatted time (for 12h format only)
|
|
297
|
+
*/
|
|
298
|
+
addPeriod(formattedValue, period) {
|
|
299
|
+
if (this.timeFormat !== "12h") return formattedValue;
|
|
300
|
+
if (!formattedValue || formattedValue.length < 5) return formattedValue;
|
|
301
|
+
return `${formattedValue} ${period}`;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
206
305
|
//#endregion
|
|
207
306
|
//#region src/services/MaskModule/locales/br/masks/PhoneMask.ts
|
|
208
307
|
/**
|
|
@@ -291,10 +390,10 @@ var MoneyMask = class extends BaseMask {
|
|
|
291
390
|
if (len <= this.maxDecimalPlaces) {
|
|
292
391
|
const padded = digits.padStart(this.maxDecimalPlaces + 1, "0");
|
|
293
392
|
const intPart = padded.slice(0, padded.length - this.maxDecimalPlaces);
|
|
294
|
-
const decimalPart = padded.slice(-this.maxDecimalPlaces);
|
|
393
|
+
const decimalPart = padded.slice(-this.maxDecimalPlaces).replace(/^0+/, "") || "0";
|
|
295
394
|
return `${this.prefix} ${isNegative ? "-" : ""}${intPart},${decimalPart}`;
|
|
296
395
|
}
|
|
297
|
-
const intRaw = digits.slice(0, len - this.maxDecimalPlaces);
|
|
396
|
+
const intRaw = digits.slice(0, len - this.maxDecimalPlaces).replace(/^0+/, "") || "0";
|
|
298
397
|
const decimal = digits.slice(-this.maxDecimalPlaces);
|
|
299
398
|
const intFormatted = this.formatThousands(intRaw);
|
|
300
399
|
return `${this.prefix} ${isNegative ? "-" : ""}${intFormatted},${decimal}`;
|
|
@@ -548,6 +647,69 @@ var DateValidator = class extends BaseValidator {
|
|
|
548
647
|
}
|
|
549
648
|
};
|
|
550
649
|
|
|
650
|
+
//#endregion
|
|
651
|
+
//#region src/services/MaskModule/locales/br/validators/TimeValidator.ts
|
|
652
|
+
/**
|
|
653
|
+
* Validates formatted time strings.
|
|
654
|
+
*
|
|
655
|
+
* Supports both 24-hour (HH:mm) and 12-hour (HH:mm AM/PM) formats.
|
|
656
|
+
*
|
|
657
|
+
* @example
|
|
658
|
+
* // 24-hour format
|
|
659
|
+
* new TimeValidator({ format: '24h' })
|
|
660
|
+
* // Valid: "12:00", "23:59", "00:00"
|
|
661
|
+
* // Invalid: "25:00", "12:60", "12:00 PM"
|
|
662
|
+
*
|
|
663
|
+
* @example
|
|
664
|
+
* // 12-hour format
|
|
665
|
+
* new TimeValidator({ format: '12h' })
|
|
666
|
+
* // Valid: "12:00 PM", "01:30 AM", "11:59 PM"
|
|
667
|
+
* // Invalid: "13:00 PM", "00:30 AM", "12:60 PM"
|
|
668
|
+
*/
|
|
669
|
+
var TimeValidator = class extends BaseValidator {
|
|
670
|
+
format;
|
|
671
|
+
constructor({ format = "24h", minLength, maxLength } = {}) {
|
|
672
|
+
let pattern;
|
|
673
|
+
if (format === "24h") pattern = /^([0-1][0-9]|2[0-3]):([0-5][0-9])$/;
|
|
674
|
+
else pattern = /^(0[1-9]|1[0-2]):([0-5][0-9])\s?(AM|PM|am|pm)$/;
|
|
675
|
+
super({
|
|
676
|
+
pattern,
|
|
677
|
+
minLength,
|
|
678
|
+
maxLength
|
|
679
|
+
});
|
|
680
|
+
this.format = format;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Custom validation logic for time strings.
|
|
684
|
+
* Validates format pattern and logical time constraints.
|
|
685
|
+
*/
|
|
686
|
+
validate(value) {
|
|
687
|
+
if (!super.validate(value)) return false;
|
|
688
|
+
if (this.format === "24h") return this.validate24h(value);
|
|
689
|
+
else return this.validate12h(value);
|
|
690
|
+
}
|
|
691
|
+
validate24h(value) {
|
|
692
|
+
const match = value.match(/^(\d{2}):(\d{2})$/);
|
|
693
|
+
if (!match) return false;
|
|
694
|
+
const hours = parseInt(match[1], 10);
|
|
695
|
+
const minutes = parseInt(match[2], 10);
|
|
696
|
+
if (hours < 0 || hours > 23) return false;
|
|
697
|
+
if (minutes < 0 || minutes > 59) return false;
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
700
|
+
validate12h(value) {
|
|
701
|
+
const match = value.match(/^(\d{2}):(\d{2})\s?(AM|PM|am|pm)$/i);
|
|
702
|
+
if (!match) return false;
|
|
703
|
+
const hours = parseInt(match[1], 10);
|
|
704
|
+
const minutes = parseInt(match[2], 10);
|
|
705
|
+
const period = match[3].toUpperCase();
|
|
706
|
+
if (hours < 1 || hours > 12) return false;
|
|
707
|
+
if (minutes < 0 || minutes > 59) return false;
|
|
708
|
+
if (period !== "AM" && period !== "PM") return false;
|
|
709
|
+
return true;
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
|
|
551
713
|
//#endregion
|
|
552
714
|
//#region src/services/MaskModule/locales/br/validators/PhoneValidator.ts
|
|
553
715
|
/**
|
|
@@ -679,6 +841,9 @@ function registerBrMasks() {
|
|
|
679
841
|
MaskModule.registerValidator(Locale.BR, MaskType.CNPJ, new CnpjValidator());
|
|
680
842
|
MaskModule.registerMask(Locale.BR, MaskType.DOCUMENT, new DocumentMask());
|
|
681
843
|
MaskModule.registerValidator(Locale.BR, MaskType.DOCUMENT, new DocumentValidator());
|
|
844
|
+
MaskModule.registerMask(Locale.BR, MaskType.TIME, new TimeMask());
|
|
845
|
+
MaskModule.registerValidator(Locale.BR, MaskType.TIME, new TimeValidator());
|
|
846
|
+
MaskModule.registerValidator(Locale.BR, MaskType.ZIP_CODE, new ZipCodeValidator());
|
|
682
847
|
MaskModule.registerMask(Locale.BR, MaskType.PHONE, new PhoneMask());
|
|
683
848
|
MaskModule.registerValidator(Locale.BR, MaskType.PHONE, new PhoneValidator());
|
|
684
849
|
MaskModule.registerMask(Locale.BR, MaskType.DATE, new DateMask());
|
|
@@ -701,4 +866,4 @@ registerBrMasks();
|
|
|
701
866
|
|
|
702
867
|
//#endregion
|
|
703
868
|
export { MaskType as n, MaskModule as r, Locale as t };
|
|
704
|
-
//# sourceMappingURL=MaskModule-
|
|
869
|
+
//# sourceMappingURL=MaskModule-CQXVHDuV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaskModule-CQXVHDuV.js","names":["locales: LocaleRegistry","pattern: RegExp"],"sources":["../src/services/MaskModule/MaskModule.ts","../src/services/MaskModule/enums.ts","../src/services/MaskModule/base/maskUtils.ts","../src/services/MaskModule/base/BaseMask.ts","../src/services/MaskModule/locales/br/masks/CpfMask.ts","../src/services/MaskModule/locales/br/masks/CnpjMask.ts","../src/services/MaskModule/locales/br/masks/DateMask.ts","../src/services/MaskModule/locales/br/masks/TimeMask.ts","../src/services/MaskModule/locales/br/masks/PhoneMask.ts","../src/services/MaskModule/locales/br/masks/FloatMask.ts","../src/services/MaskModule/locales/br/masks/MoneyMask.ts","../src/services/MaskModule/locales/br/masks/IntegerMask.ts","../src/services/MaskModule/locales/br/masks/ZipCodeMask.ts","../src/services/MaskModule/types.ts","../src/services/MaskModule/locales/br/masks/DocumentMask.ts","../src/services/MaskModule/locales/br/masks/NumericSymbolMask.ts","../src/services/MaskModule/base/BaseValidator.ts","../src/services/MaskModule/locales/br/validators/CpfValidator.ts","../src/services/MaskModule/locales/br/validators/CnpjValidator.ts","../src/services/MaskModule/locales/br/validators/DateValidator.ts","../src/services/MaskModule/locales/br/validators/TimeValidator.ts","../src/services/MaskModule/locales/br/validators/PhoneValidator.ts","../src/services/MaskModule/locales/br/validators/FloatValidator.ts","../src/services/MaskModule/locales/br/validators/MoneyValidator.ts","../src/services/MaskModule/locales/br/validators/IntegerValidator.ts","../src/services/MaskModule/locales/br/validators/ZipCodeValidator.ts","../src/services/MaskModule/locales/br/validators/DocumentValidator.ts","../src/services/MaskModule/locales/br/validators/NumericSymbolValidator.ts","../src/services/MaskModule/locales/br/registerMasks.ts","../src/services/MaskModule/index.ts"],"sourcesContent":["// Types\nimport type { Locale, MaskType } from './enums'\nimport type { BaseMask } from './base/BaseMask'\nimport type { BaseValidator } from './base/BaseValidator'\n\ntype MaskRegistry = {\n masks: Record<MaskType, BaseMask>\n validators: Record<MaskType, BaseValidator>\n}\n\ntype LocaleRegistry = Record<Locale, MaskRegistry>\n\nconst locales: LocaleRegistry = {} as LocaleRegistry\n\nfunction ensureLocale(locale: Locale): void {\n if (!locales[locale]) {\n locales[locale] = { masks: {}, validators: {} } as LocaleRegistry[Locale]\n }\n}\n\nexport const MaskModule = {\n registerMask(locale: Locale, type: MaskType, mask: BaseMask): void {\n ensureLocale(locale)\n locales[locale].masks[type] = mask\n },\n\n registerValidator(\n locale: Locale,\n type: MaskType,\n validator: BaseValidator\n ): void {\n ensureLocale(locale)\n locales[locale].validators[type] = validator\n },\n\n getMask(locale: Locale, type: MaskType): BaseMask | undefined {\n return locales[locale]?.masks[type]\n },\n\n getValidator(locale: Locale, type: MaskType): BaseValidator | undefined {\n return locales[locale]?.validators[type]\n },\n\n reset(): void {\n Object.keys(locales).forEach(locale => {\n delete locales[locale as Locale]\n })\n }\n}\n","/**\n * Supported locales (country + language region).\n *\n * Extend this enum as needed for new countries.\n */\nexport enum Locale {\n BR = 'pt-BR', // Brazil\n US = 'en-US', // United States\n AR = 'es-AR' // Argentina\n}\n\n/**\n * Types of masks supported in the system.\n *\n * Add new types as needed for different data formats.\n */\nexport const MaskType = {\n CPF: 'CPF',\n CNPJ: 'CNPJ',\n DOCUMENT: 'DOCUMENT',\n PHONE: 'PHONE',\n DATE: 'DATE',\n TIME: 'TIME',\n FLOAT: 'FLOAT',\n INTEGER: 'INTEGER',\n MONEY: 'MONEY',\n ZIP_CODE: 'ZIP_CODE',\n NUMERIC_SYMBOL: 'NUMERIC_SYMBOL'\n} as const\n\nexport type MaskType = (typeof MaskType)[keyof typeof MaskType]\n","/**\n * Removes all non-numeric characters from a string.\n * @param value - Input string.\n * @returns String containing only digits.\n */\nexport function onlyDigits(value: string): string {\n if (value == null) return ''\n return value.replace(/\\D/g, '')\n}\n\n/**\n * Applies the mask progressively according to the available characters.\n *\n * Alphanumeric characters (letters and digits) in the pattern will be replaced\n * by characters from the input `value`, in order. Non-alphanumeric characters\n * (e.g. `.`, `-`, `/`) are treated as static parts of the mask.\n *\n * Examples:\n *\n * applyPattern('12345', 'XXX.XXX.XXX-XX') -> '123.45'\n *\n * applyPattern('AB1234', 'AA-NN.NN') -> 'AB-12.34'\n *\n * applyPattern('12345678901', 'XXX.XXX.XXX-XX') -> '123.456.789-01'\n *\n * @param value - raw input string (partial or complete)\n * @param pattern - mask pattern where alphanumeric characters are placeholders\n * @returns partially formatted string\n */\nexport function applyPattern(value: string, pattern: string): string {\n if (value == null) return ''\n if (pattern == null) return value\n\n let result = ''\n let digitIndex = 0\n\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i]\n\n if (/[a-zA-Z0-9]/.test(char)) {\n if (digitIndex < value.length) {\n result += value[digitIndex++]\n } else {\n break // No more digits available, stop applying more mask\n }\n } else {\n // Fixed mask character\n if (digitIndex < value.length) result += char\n }\n }\n\n return result\n}\n\n/**\n * Checks whether a string matches a regular expression.\n * @param value - Input string.\n * @param regex - Regular expression to test.\n * @returns Boolean indicating whether it matches.\n */\nexport function matchesPattern(value: string, regex: RegExp): boolean {\n return regex.test(value)\n}\n\n/**\n * Limits the length of a string to a maximum.\n * @param value - Input string.\n * @param maxLength - Maximum length allowed.\n * @returns Truncated string if longer than maxLength.\n */\nexport function limitLength(value: string, maxLength?: number): string {\n if (value == null) return ''\n if (maxLength === undefined) return value\n return value.slice(0, maxLength)\n}\n\n/**\n * Checks if a string meets min and max length constraints.\n * @param value - Input string.\n * @param min - Minimum length (optional).\n * @param max - Maximum length (optional).\n * @returns Boolean indicating whether the length is valid.\n */\nexport function isValidLength(\n value: string,\n min?: number,\n max?: number\n): boolean {\n if (value == null) return false\n\n if (min !== undefined && value.length < min) return false\n if (max !== undefined && value.length > max) return false\n return true\n}\n","import type { Mask } from '../types'\nimport { onlyDigits } from './maskUtils'\n\n/**\n * Abstract class that provides default behavior for most masks.\n * - Implements unmask() by removing all non-numeric characters.\n * - Supports optional maxLength and minLength constraints.\n */\nexport abstract class BaseMask implements Mask {\n /**\n * Maximum length of the masked string (optional).\n */\n maxLength?: number\n\n /**\n * Minimum length of the masked string (optional).\n */\n minLength?: number\n\n constructor(minLength?: number, maxLength?: number) {\n this.maxLength = maxLength\n this.minLength = minLength\n }\n\n /**\n * Removes all non-numeric characters from a string.\n * @param value - Masked or unmasked string.\n * @returns Plain string with digits only.\n */\n unmask(value: string): string {\n return onlyDigits(value)\n }\n\n /**\n * Must be implemented by each concrete mask class.\n * Applies the mask format to the input string.\n * @param value - Raw string.\n * @returns Masked string.\n */\n abstract format(value: string): string\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { applyPattern, limitLength, onlyDigits } from '../../../base/maskUtils'\n\nexport const CPF_PATTERN = 'XXX.XXX.XXX-XX'\n\nexport class CpfMask extends BaseMask {\n constructor() {\n const length = CPF_PATTERN.length\n super(length, length)\n }\n\n format(value: string): string {\n const digits = onlyDigits(value)\n const formatted = applyPattern(digits, CPF_PATTERN)\n\n return limitLength(formatted, this.maxLength)\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { applyPattern, limitLength, onlyDigits } from '../../../base/maskUtils'\n\nexport const CNPJ_PATTERN = 'XX.XXX.XXX/XXXX-XX'\n\nexport class CnpjMask extends BaseMask {\n constructor() {\n const length = CNPJ_PATTERN.length\n super(length, length)\n }\n\n format(value: string): string {\n const digits = onlyDigits(value)\n const formatted = applyPattern(digits, CNPJ_PATTERN)\n\n return limitLength(formatted, this.maxLength)\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { limitLength, onlyDigits } from '../../../base/maskUtils'\n\nconst DATE_PATTERN = 'DD/MM/YYYY'\n\nexport class DateMask extends BaseMask {\n constructor() {\n const length = DATE_PATTERN.length\n super(length, length)\n }\n\n format(value: string): string {\n const digits = onlyDigits(value)\n\n let day = digits.slice(0, 2)\n let month = digits.slice(2, 4)\n let year = digits.slice(4, 8)\n\n // Clamp day (01–31)\n if (day.length === 2) {\n const parsed = parseInt(day)\n if (parsed > 31) day = '31'\n else if (parsed < 1) day = '01'\n }\n\n // Clamp month (01–12)\n if (month.length === 2) {\n const parsed = parseInt(month)\n if (parsed > 12) month = '12'\n else if (parsed < 1) month = '01'\n }\n\n // Clamp year (>= 0000)\n if (year.length === 4) {\n const parsed = parseInt(year)\n if (parsed < 0) year = '0000'\n }\n\n // Rebuild progressively\n let result = ''\n if (day) result += day\n if (month) result += `/${month}`\n if (year) result += `/${year}`\n\n return limitLength(result, this.maxLength)\n }\n}\n","// masks/time/TimeInputMask.ts\nimport { BaseMask } from '../../../base/BaseMask'\nimport { applyPattern, limitLength, onlyDigits } from '../../../base/maskUtils'\n\nexport const TIME_PATTERN = 'XX:XX'\n\n/**\n * Formats time input allowing editing at any position.\n * Uses pattern-based formatting similar to CPF/CNPJ masks.\n *\n * Key difference from TimeMask:\n * - TimeMask: Sequential digit-by-digit formatting (good for append-only input)\n * - TimeInputMask: Pattern-based formatting (allows editing anywhere in the string)\n *\n * @example\n * const mask = new TimeInputMask({ timeFormat: '24h' })\n * mask.format('1430') // \"14:30\"\n * mask.format('1530') // \"15:30\" (can change first digit easily)\n *\n * @example\n * const mask12h = new TimeInputMask({ timeFormat: '12h' })\n * mask12h.format('0230') // \"02:30\"\n */\nexport class TimeMask extends BaseMask {\n private timeFormat: '24h' | '12h'\n\n constructor({\n timeFormat = '24h',\n minLength = 5,\n maxLength = 5\n }: {\n timeFormat?: '24h' | '12h'\n minLength?: number\n maxLength?: number\n } = {}) {\n super(minLength, maxLength)\n this.timeFormat = timeFormat\n }\n\n format(value: string): string {\n const digits = onlyDigits(value)\n const limitedDigits = limitLength(digits, 4)\n\n if (!limitedDigits) return ''\n\n const formatted = applyPattern(digits, TIME_PATTERN)\n\n let result = formatted\n\n if (formatted.length >= 3) {\n result = this.validateAndCorrect(formatted)\n }\n\n return limitLength(result, this.maxLength)\n }\n\n /**\n * Validates and corrects the formatted time string\n */\n private validateAndCorrect(value: string): string {\n if (!value) return '00:00'\n\n const parts = value.split(':')\n const hours = parts[0] || ''\n const minutes = parts[1] || ''\n\n const correctedHours = this.correctHours(hours)\n\n // Return early if no minutes yet\n if (!minutes) {\n // Add colon if we have complete hours\n return hours.length === 2 ? `${correctedHours}:` : correctedHours\n }\n\n const correctedMinutes = this.correctMinutes(minutes)\n\n return `${correctedHours}:${correctedMinutes}`\n }\n\n /**\n * Corrects hours to valid range based on format\n */\n private correctHours(hours: string): string {\n if (!hours) return ''\n\n // Single digit: apply smart correction\n if (hours.length === 1) {\n const digit = parseInt(hours, 10)\n\n if (this.timeFormat === '24h') {\n // For 24h: digits 3-9 as first digit should become 03-09\n if (digit > 2) {\n return `0${digit}`\n }\n return hours\n } else {\n // For 12h: digit 0 stays, digits 2-9 should become 02-09\n if (digit === 0) {\n return '0'\n }\n if (digit > 1) {\n return `0${digit}`\n }\n return hours\n }\n }\n\n // Two digits: validate complete hour\n let hourNum = parseInt(hours, 10)\n\n if (this.timeFormat === '24h') {\n if (hourNum > 23) hourNum = 23\n if (hourNum < 0) hourNum = 0\n } else {\n if (hourNum === 0) hourNum = 12\n if (hourNum > 12) hourNum = 12\n if (hourNum < 1) hourNum = 1\n }\n\n return hourNum.toString().padStart(2, '0')\n }\n\n /**\n * Corrects minutes to valid range (00-59)\n */\n private correctMinutes(minutes: string): string {\n if (!minutes) return ''\n\n // Single digit: apply smart correction\n if (minutes.length === 1) {\n const digit = parseInt(minutes, 10)\n // Digits 6-9 as first minute digit should become 06-09\n if (digit > 5) {\n return `0${digit}`\n }\n return minutes\n }\n\n // Two digits: validate complete minute\n let minuteNum = parseInt(minutes, 10)\n\n if (minuteNum > 59) minuteNum = 59\n if (minuteNum < 0) minuteNum = 0\n\n return minuteNum.toString().padStart(2, '0')\n }\n\n /**\n * Adds AM/PM period to formatted time (for 12h format only)\n */\n addPeriod(formattedValue: string, period: 'AM' | 'PM'): string {\n if (this.timeFormat !== '12h') return formattedValue\n if (!formattedValue || formattedValue.length < 5) return formattedValue\n return `${formattedValue} ${period}`\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { limitLength, onlyDigits } from '../../../base/maskUtils'\n\n/**\n * Formats a Brazilian phone number progressively:\n * (XX) XXXXX-XXXX or (XX) XXXX-XXXX depending on length.\n */\nexport class PhoneMask extends BaseMask {\n constructor(maxLength = 15) {\n super(14, maxLength) // 14 (fixo) or 15 (celular)\n }\n\n format(value: string): string {\n const digits = limitLength(onlyDigits(value), this.maxLength)\n if (!digits) return ''\n\n // DDD\n if (digits.length < 3) return `(${digits}`\n\n const ddd = digits.slice(0, 2)\n const rest = digits.slice(2)\n\n // Fixo: 8 dígitos / Celular: 9 dígitos\n if (rest.length <= 4) {\n return `(${ddd}) ${rest}`\n } else if (rest.length <= 8) {\n const part1 = rest.slice(0, 4)\n const part2 = rest.slice(4)\n return `(${ddd}) ${part1}${part2 ? `-${part2}` : ''}`\n } else {\n const part1 = rest.slice(0, 5)\n const part2 = rest.slice(5)\n return `(${ddd}) ${part1}-${part2}`\n }\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { onlyDigits, limitLength } from '../../../base/maskUtils'\n\n/**\n * Automatically formats a numeric input as a float using comma as decimal separator.\n *\n * Ignores user-entered punctuation and inserts the comma based on configured decimal places.\n */\nexport class FloatMask extends BaseMask {\n private maxDecimalPlaces: number\n\n constructor(decimalDigits = 2, maxLength = 20) {\n super(1, maxLength)\n this.maxDecimalPlaces = decimalDigits\n }\n\n format(value: string): string {\n const rawDigits = onlyDigits(value)\n const digits = limitLength(rawDigits, this.maxLength)\n\n if (!digits) return ''\n\n const length = digits.length\n\n // If the string is shorter than or equal to the number of decimal places, prefix with zeros\n if (length <= this.maxDecimalPlaces) {\n const padded = digits.padStart(this.maxDecimalPlaces + 1, '0')\n const intPart = padded.slice(0, padded.length - this.maxDecimalPlaces)\n const decimalPart = padded.slice(-this.maxDecimalPlaces)\n return `${intPart},${decimalPart}`\n }\n\n const intPart = digits.slice(0, length - this.maxDecimalPlaces)\n const decimalPart = digits.slice(-this.maxDecimalPlaces)\n const intFormatted = this.formatThousands(intPart)\n\n return `${intFormatted},${decimalPart}`\n }\n\n /**\n * Adds dot thousand separators to a string of digits.\n * Example: \"1234567\" => \"1.234.567\"\n */\n private formatThousands(value: string): string {\n return value.replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { onlyDigits } from '../../../base/maskUtils'\n\n/**\n * Formats input as currency, with thousand separator, decimal comma,\n * optional prefix (e.g. R$, $), and support for negatives.\n *\n * Examples:\n * - \"123456\" → \"R$ 1.234,56\"\n * - \"-123\" → \"R$ -1,23\"\n */\nexport class MoneyMask extends BaseMask {\n private maxDecimalPlaces: number\n private prefix: string\n private allowNegative: boolean\n\n constructor({\n prefix = 'R$',\n maxDecimalPlaces = 2,\n allowNegative = true,\n maxLength = 20\n }: {\n prefix?: string\n maxDecimalPlaces?: number\n allowNegative?: boolean\n maxLength?: number\n } = {}) {\n super(1, maxLength)\n this.prefix = prefix\n this.maxDecimalPlaces = maxDecimalPlaces\n this.allowNegative = allowNegative\n }\n\n format(value: string): string {\n if (!value) return ''\n\n const isNegative = this.allowNegative && value.trim().startsWith('-')\n const digits = onlyDigits(value).slice(0, this.maxLength)\n\n if (!digits) {\n return isNegative\n ? `${this.prefix} -0,${'0'.repeat(this.maxDecimalPlaces)}`\n : `${this.prefix} 0,${'0'.repeat(this.maxDecimalPlaces)}`\n }\n\n const len = digits.length\n\n // Ex: 3 digits, 2 decimals → '003' => '0,03'\n if (len <= this.maxDecimalPlaces) {\n const padded = digits.padStart(this.maxDecimalPlaces + 1, '0')\n const intPart = padded.slice(0, padded.length - this.maxDecimalPlaces)\n const decimalPart =\n padded.slice(-this.maxDecimalPlaces).replace(/^0+/, '') || '0'\n return `${this.prefix} ${isNegative ? '-' : ''}${intPart},${decimalPart}`\n }\n\n const intRaw =\n digits.slice(0, len - this.maxDecimalPlaces).replace(/^0+/, '') || '0'\n const decimal = digits.slice(-this.maxDecimalPlaces)\n const intFormatted = this.formatThousands(intRaw)\n\n return `${this.prefix} ${isNegative ? '-' : ''}${intFormatted},${decimal}`\n }\n\n private formatThousands(value: string): string {\n return value.replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { limitLength, onlyDigits } from '../../../base/maskUtils'\n\n/**\n * Formats integers, allowing only digits.\n */\nexport class IntegerMask extends BaseMask {\n constructor(maxLength = 15) {\n super(1, maxLength)\n }\n\n format(value: string): string {\n const digits = onlyDigits(value)\n return limitLength(digits, this.maxLength)\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { applyPattern, limitLength, onlyDigits } from '../../../base/maskUtils'\n\nexport const ZIP_CODE_PATTERN = 'XXXXX-XXX'\n\nexport class ZipCodeMask extends BaseMask {\n constructor() {\n const length = ZIP_CODE_PATTERN.length\n super(length, length)\n }\n\n format(value: string): string {\n const digits = onlyDigits(value)\n const formatted = applyPattern(digits, ZIP_CODE_PATTERN)\n\n return limitLength(formatted, this.maxLength)\n }\n}\n","/**\n * Represents a generic mask.\n *\n * A mask is responsible for formatting and unformatting (removing formatting) from a value.\n */\nexport interface Mask {\n /**\n * Optional minimum length of the masked string.\n */\n minLength?: number\n\n /**\n * Optional maximum length of the masked string.\n */\n maxLength?: number\n\n /**\n * Formats a plain string into a masked format.\n * @param value - Raw string (e.g., \"12345678901\").\n * @returns Masked string (e.g., \"123.456.789-01\").\n */\n format(value: string): string\n\n /**\n * Removes all mask characters from a formatted string.\n * @param value - Masked string (e.g., \"123.456.789-01\").\n * @returns Unmasked string (e.g., \"12345678901\").\n */\n unmask(value: string): string\n}\n\n/**\n * Represents a validator for a masked value.\n *\n * A validator checks whether a masked value is valid based on rules.\n */\nexport interface Validator {\n /**\n * Validates whether the input value is valid.\n * @param value - Masked string.\n * @returns `true` if valid, `false` otherwise.\n */\n validate(value: string): boolean\n}\n\n/**\n * Mode of document mask and validator.\n *\n * - AUTO: Automatically detect based on length.\n * - CPF: Force CPF.\n * - CNPJ: Force CNPJ.\n */\nexport enum DocumentMode {\n CPF = 'cpf',\n CNPJ = 'cnpj',\n AUTO = 'auto'\n}\n","import { CpfMask } from './CpfMask'\nimport { CnpjMask } from './CnpjMask'\nimport { BaseMask } from '../../../base/BaseMask'\nimport { onlyDigits } from '../../../base/maskUtils'\nimport { DocumentMode } from '../../../types'\n\nexport class DocumentMask extends BaseMask {\n private cpfMask = new CpfMask()\n private cnpjMask = new CnpjMask()\n private mode: DocumentMode\n\n constructor(mode: DocumentMode = DocumentMode.AUTO) {\n super()\n this.mode = mode\n }\n\n format(value: string): string {\n const digits = onlyDigits(value)\n const mode = this.resolveMode(digits)\n\n if (mode === DocumentMode.CPF) {\n return this.cpfMask.format(digits)\n }\n\n if (mode === DocumentMode.CNPJ) {\n return this.cnpjMask.format(digits)\n }\n\n return digits\n }\n\n private resolveMode(digits: string): DocumentMode.CPF | DocumentMode.CNPJ {\n if (this.mode === DocumentMode.CPF) return DocumentMode.CPF\n if (this.mode === DocumentMode.CNPJ) return DocumentMode.CNPJ\n\n return digits.length <= 11 ? DocumentMode.CPF : DocumentMode.CNPJ\n }\n}\n","import { BaseMask } from '../../../base/BaseMask'\nimport { limitLength } from '../../../base/maskUtils'\n\nexport class NumericSymbolMask extends BaseMask {\n constructor(maxLength = 25) {\n super(1, maxLength)\n }\n\n format(value: string): string {\n if (value == null) return ''\n\n const result = value.replace(/[^\\d.,/-]/g, '')\n return limitLength(result, this.maxLength)\n }\n}\n","import type { Validator } from '../types'\n\n/**\n * Abstract class providing common validation utilities.\n * - Supports regex validation.\n * - Supports min and max length validation.\n */\nexport abstract class BaseValidator implements Validator {\n protected pattern?: RegExp\n protected minLength?: number\n protected maxLength?: number\n\n constructor(options?: {\n pattern?: RegExp\n minLength?: number\n maxLength?: number\n }) {\n this.pattern = options?.pattern\n this.minLength = options?.minLength\n this.maxLength = options?.maxLength\n }\n\n /**\n * Validates the input value based on:\n * - Pattern matching (if defined)\n * - Min length (if defined)\n * - Max length (if defined)\n *\n * Override this method if you need custom validation logic.\n *\n * @param value - Value to validate (usually masked string)\n * @returns true if valid, false otherwise\n */\n validate(value: string): boolean {\n if (value == null) return false\n\n const length = value.length\n\n if (this.minLength !== undefined && length < this.minLength) {\n return false\n }\n\n if (this.maxLength !== undefined && length > this.maxLength) {\n return false\n }\n\n if (this.pattern && !this.pattern.test(value)) return false\n\n return true\n }\n}\n","import { CPF_PATTERN } from '../masks/CpfMask'\nimport { BaseValidator } from '../../../base/BaseValidator'\n\nexport class CpfValidator extends BaseValidator {\n constructor() {\n const length = CPF_PATTERN.length\n super({ minLength: length, maxLength: length })\n }\n\n validate(value: string): boolean {\n if (value == null) return false\n\n return isCpfValid(value)\n }\n}\n\n/**\n * Validates if a CPF (Brazilian tax ID) is valid.\n *\n * This function:\n * - Removes any non-digit characters (dots, dashes, spaces).\n * - Checks if CPF has 11 digits.\n * - Rejects CPFs where all digits are the same (e.g., '11111111111').\n * - Performs CPF check digit validation (standard algorithm).\n *\n * @param inputCPF - CPF as a string, can be formatted (e.g., \"123.456.789-09\").\n * @returns true if CPF is valid, false otherwise.\n */\nfunction isCpfValid(inputCPF: string): boolean {\n // Remove dots, dashes, and spaces\n const cpfOnlyNumbers = inputCPF.replace(/[\\s.-]/g, '')\n\n // CPF must be exactly 11 digits\n if (cpfOnlyNumbers.length !== 11) return false\n\n // Check if all digits are the same (invalid CPF)\n if (/^(\\d)\\1{10}$/.test(cpfOnlyNumbers)) return false\n\n // Validate first check digit\n let sum = 0\n for (let i = 0; i < 9; i++) {\n sum += parseInt(cpfOnlyNumbers.charAt(i)) * (10 - i)\n }\n\n let firstCheckDigit = (sum * 10) % 11\n if (firstCheckDigit === 10 || firstCheckDigit === 11) firstCheckDigit = 0\n if (firstCheckDigit !== parseInt(cpfOnlyNumbers.charAt(9))) return false\n\n // Validate second check digit\n sum = 0\n for (let i = 0; i < 10; i++) {\n sum += parseInt(cpfOnlyNumbers.charAt(i)) * (11 - i)\n }\n\n let secondCheckDigit = (sum * 10) % 11\n if (secondCheckDigit === 10 || secondCheckDigit === 11) secondCheckDigit = 0\n if (secondCheckDigit !== parseInt(cpfOnlyNumbers.charAt(10))) return false\n\n return true\n}\n","import { CNPJ_PATTERN } from '../masks/CnpjMask'\nimport { BaseValidator } from '../../../base/BaseValidator'\n\nexport class CnpjValidator extends BaseValidator {\n constructor() {\n const length = CNPJ_PATTERN.length\n super({ minLength: length, maxLength: length })\n }\n\n validate(value: string): boolean {\n if (value == null) return false\n\n return isCnpjValid(value)\n }\n}\n\n/**\n * Validates whether a given CNPJ number is valid.\n * @param cnpj The CNPJ number as a string.\n * @returns True if valid, false otherwise.\n */\nfunction isCnpjValid(cnpj: string): boolean {\n if (!cnpj) return false\n\n // Remove any non-digit characters\n const cleanedCnpj = cnpj.replace(/[^\\d]+/g, '')\n\n // CNPJ must be exactly 14 digits\n if (cleanedCnpj.length !== 14) return false\n\n // Reject CNPJs with all identical digits (e.g., 00000000000000)\n if (/^(\\d)\\1{13}$/.test(cleanedCnpj)) return false\n\n // Extract the base CNPJ and the two check digits\n const baseCnpj = cleanedCnpj.slice(0, 12)\n const checkDigits = cleanedCnpj.slice(12)\n\n // Calculate first check digit\n const firstSum = calculateCnpjWeightedSum(baseCnpj, 12, 5)\n const firstCheckDigit = calculateCnpjCheckDigit(firstSum)\n\n if (firstCheckDigit !== Number(checkDigits.charAt(0))) {\n return false\n }\n\n // Calculate second check digit (base + first check digit)\n const secondSum = calculateCnpjWeightedSum(baseCnpj + firstCheckDigit, 13, 6)\n const secondCheckDigit = calculateCnpjCheckDigit(secondSum)\n\n if (secondCheckDigit !== Number(checkDigits.charAt(1))) {\n return false\n }\n\n return true\n}\n\n/**\n * Calculates the weighted sum for CNPJ verification digits.\n * @param numbers The numeric string of the CNPJ.\n * @param size The number of digits to consider for the calculation.\n * @param position The starting multiplier position (5 or 6).\n * @returns The weighted sum.\n */\nfunction calculateCnpjWeightedSum(\n numbers: string,\n size: number,\n position: number\n): number {\n let sum = 0\n\n for (let i = 0; i < size; i++) {\n sum += Number(numbers.charAt(i)) * position\n position--\n\n if (position < 2) {\n position = 9\n }\n }\n\n return sum\n}\n\n/**\n * Calculates the verification digit based on the weighted sum.\n * @param sum The weighted sum.\n * @returns The verification digit (0-9).\n */\nfunction calculateCnpjCheckDigit(sum: number): number {\n const remainder = sum % 11\n return remainder < 2 ? 0 : 11 - remainder\n}\n","import { BaseValidator } from '../../../base/BaseValidator'\n\n/**\n * Validator for dates in the format dd/mm/yyyy.\n *\n * Ensures the format is correct and the date is valid in the calendar (e.g. 30/02 is invalid).\n */\nexport class DateValidator extends BaseValidator {\n constructor() {\n super({\n minLength: 10,\n maxLength: 10,\n pattern: /^\\d{2}\\/\\d{2}\\/\\d{4}$/ // Strictly requires dd/mm/yyyy format\n })\n }\n\n override validate(value: string): boolean {\n if (!super.validate(value)) return false\n\n const [dayStr, monthStr, yearStr] = value.split('/')\n const day = parseInt(dayStr, 10)\n const month = parseInt(monthStr, 10)\n const year = parseInt(yearStr, 10)\n\n const date = new Date(year, month - 1, day)\n\n return (\n date.getFullYear() === year &&\n date.getMonth() === month - 1 &&\n date.getDate() === day\n )\n }\n}\n","import { BaseValidator } from '../../../base/BaseValidator'\n\n/**\n * Validates formatted time strings.\n *\n * Supports both 24-hour (HH:mm) and 12-hour (HH:mm AM/PM) formats.\n *\n * @example\n * // 24-hour format\n * new TimeValidator({ format: '24h' })\n * // Valid: \"12:00\", \"23:59\", \"00:00\"\n * // Invalid: \"25:00\", \"12:60\", \"12:00 PM\"\n *\n * @example\n * // 12-hour format\n * new TimeValidator({ format: '12h' })\n * // Valid: \"12:00 PM\", \"01:30 AM\", \"11:59 PM\"\n * // Invalid: \"13:00 PM\", \"00:30 AM\", \"12:60 PM\"\n */\nexport class TimeValidator extends BaseValidator {\n private format: '24h' | '12h'\n\n constructor({\n format = '24h',\n minLength,\n maxLength\n }: {\n format?: '24h' | '12h'\n minLength?: number\n maxLength?: number\n } = {}) {\n let pattern: RegExp\n\n if (format === '24h') {\n // Matches 24-hour format: 00:00 to 23:59\n // Hours: 00-23, Minutes: 00-59\n pattern = /^([0-1][0-9]|2[0-3]):([0-5][0-9])$/\n } else {\n // Matches 12-hour format: 01:00 AM to 12:59 PM\n // Hours: 01-12, Minutes: 00-59, Period: AM/PM\n pattern = /^(0[1-9]|1[0-2]):([0-5][0-9])\\s?(AM|PM|am|pm)$/\n }\n\n super({\n pattern,\n minLength,\n maxLength\n })\n\n this.format = format\n }\n\n /**\n * Custom validation logic for time strings.\n * Validates format pattern and logical time constraints.\n */\n validate(value: string): boolean {\n // First check base pattern validation\n if (!super.validate(value)) return false\n\n if (this.format === '24h') {\n return this.validate24h(value)\n } else {\n return this.validate12h(value)\n }\n }\n\n private validate24h(value: string): boolean {\n const match = value.match(/^(\\d{2}):(\\d{2})$/)\n if (!match) return false\n\n const hours = parseInt(match[1], 10)\n const minutes = parseInt(match[2], 10)\n\n if (hours < 0 || hours > 23) return false\n\n if (minutes < 0 || minutes > 59) return false\n\n return true\n }\n\n private validate12h(value: string): boolean {\n const match = value.match(/^(\\d{2}):(\\d{2})\\s?(AM|PM|am|pm)$/i)\n if (!match) return false\n\n const hours = parseInt(match[1], 10)\n const minutes = parseInt(match[2], 10)\n const period = match[3].toUpperCase()\n\n if (hours < 1 || hours > 12) return false\n\n if (minutes < 0 || minutes > 59) return false\n\n if (period !== 'AM' && period !== 'PM') return false\n\n return true\n }\n}\n","import { BaseValidator } from '../../../base/BaseValidator'\n\n/**\n * Validates a Brazilian phone number with optional mobile or landline support.\n */\nexport class PhoneValidator extends BaseValidator {\n private allowedDDDs: string[]\n\n constructor({\n allowMobile = true,\n allowLandline = true,\n allowedDDDs = Array.from({ length: 89 }, (_, i) => `${i + 11}`), // 11–99\n minLength,\n maxLength\n }: {\n allowMobile?: boolean\n allowLandline?: boolean\n allowedDDDs?: string[]\n minLength?: number\n maxLength?: number\n } = {}) {\n const mobileRegex = /^\\(?(\\d{2})\\)?\\s?\\d{5}-?\\d{4}$/ // (11) 98765-4321\n const landlineRegex = /^\\(?(\\d{2})\\)?\\s?\\d{4}-?\\d{4}$/ // (11) 3456-7890\n\n const pattern =\n allowMobile && allowLandline\n ? /^\\(?\\d{2}\\)?\\s?(\\d{4,5})-?\\d{4}$/\n : allowMobile\n ? mobileRegex\n : landlineRegex\n\n super({ pattern, minLength, maxLength })\n\n this.allowedDDDs = allowedDDDs\n }\n\n validate(value: string): boolean {\n if (!super.validate(value)) return false\n\n const digits = value.replace(/\\D/g, '')\n if (digits.length !== 10 && digits.length !== 11) return false\n\n const ddd = digits.slice(0, 2)\n return this.allowedDDDs.includes(ddd)\n }\n}\n","import { BaseValidator } from '../../../base/BaseValidator'\n\nexport class FloatValidator extends BaseValidator {\n constructor(maxDecimalPlaces = 3, minLength = 1, maxLength = 20) {\n const decimalRegex = new RegExp(`^\\\\d+(,\\\\d{1,${maxDecimalPlaces}})?$`)\n\n super({\n pattern: decimalRegex,\n minLength,\n maxLength\n })\n }\n}\n","import { BaseValidator } from '../../../base/BaseValidator'\n\n/**\n * Validates formatted currency strings.\n *\n * Supports optional prefix, negative values, and comma decimal separator.\n */\nexport class MoneyValidator extends BaseValidator {\n constructor({\n prefix = 'R$',\n maxDecimalPlaces = 2,\n allowNegative = true,\n minLength,\n maxLength\n }: {\n prefix?: string\n maxDecimalPlaces?: number\n allowNegative?: boolean\n minLength?: number\n maxLength?: number\n } = {}) {\n // Escape prefix for regex (if it has symbols)\n const escapedPrefix = prefix.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n // Matches: R$ -1.234,56\n const pattern = new RegExp(\n `^${escapedPrefix}\\\\s?${allowNegative ? '-?' : ''}\\\\d{1,3}(\\\\.\\\\d{3})*(,\\\\d{1,${maxDecimalPlaces}})?$`\n )\n\n super({\n pattern,\n minLength,\n maxLength\n })\n }\n}\n","import { BaseValidator } from '../../../base/BaseValidator'\n\nexport class IntegerValidator extends BaseValidator {\n constructor(minLength = 1, maxLength = 15) {\n super({\n pattern: /^\\d+$/,\n minLength,\n maxLength\n })\n }\n}\n","import { ZIP_CODE_PATTERN } from '../masks/ZipCodeMask'\nimport { BaseValidator } from '../../../base/BaseValidator'\n\nexport class ZipCodeValidator extends BaseValidator {\n constructor() {\n const length = ZIP_CODE_PATTERN.length\n super({ minLength: length, maxLength: length })\n }\n\n validate(value: string): boolean {\n if (value == null) return false\n\n if (this.minLength !== undefined && value.length < this.minLength)\n return false\n\n if (this.maxLength !== undefined && value.length > this.maxLength)\n return false\n\n return true\n }\n}\n","import { CpfValidator } from './CpfValidator'\nimport { CnpjValidator } from './CnpjValidator'\nimport { BaseValidator } from '../../../base/BaseValidator'\nimport { onlyDigits } from '../../../base/maskUtils'\nimport { DocumentMode } from '../../../types'\n\nexport class DocumentValidator extends BaseValidator {\n private cpfValidator = new CpfValidator()\n private cnpjValidator = new CnpjValidator()\n private mode: DocumentMode\n\n constructor(mode: DocumentMode = DocumentMode.AUTO) {\n super()\n this.mode = mode\n }\n\n validate(value: string): boolean {\n const digits = onlyDigits(value)\n const type = this.resolveType(digits)\n\n if (type === DocumentMode.CPF) {\n return this.cpfValidator.validate(value)\n }\n\n if (type === DocumentMode.CNPJ) {\n return this.cnpjValidator.validate(value)\n }\n\n return false\n }\n\n private resolveType(digits: string): DocumentMode.CPF | DocumentMode.CNPJ {\n if (this.mode === DocumentMode.CPF) return DocumentMode.CPF\n if (this.mode === DocumentMode.CNPJ) return DocumentMode.CNPJ\n\n return digits.length <= 11 ? DocumentMode.CPF : DocumentMode.CNPJ\n }\n}\n","import { BaseValidator } from '../../../base/BaseValidator'\n\nexport class NumericSymbolValidator extends BaseValidator {\n constructor(minLength = 1, maxLength = 25) {\n super({\n pattern: /^[\\d.,/-]+$/,\n minLength,\n maxLength\n })\n }\n}\n","import { MaskModule } from '../../MaskModule'\nimport { MaskType, Locale } from '../../enums'\n\nimport { CpfMask } from './masks/CpfMask'\nimport { CnpjMask } from './masks/CnpjMask'\nimport { DateMask } from './masks/DateMask'\nimport { TimeMask } from './masks/TimeMask'\nimport { PhoneMask } from './masks/PhoneMask'\nimport { FloatMask } from './masks/FloatMask'\nimport { MoneyMask } from './masks/MoneyMask'\nimport { IntegerMask } from './masks/IntegerMask'\nimport { ZipCodeMask } from './masks/ZipCodeMask'\nimport { DocumentMask } from './masks/DocumentMask'\nimport { NumericSymbolMask } from './masks/NumericSymbolMask'\n\nimport { CpfValidator } from './validators/CpfValidator'\nimport { CnpjValidator } from './validators/CnpjValidator'\nimport { DateValidator } from './validators/DateValidator'\nimport { TimeValidator } from './validators/TimeValidator'\nimport { PhoneValidator } from './validators/PhoneValidator'\nimport { FloatValidator } from './validators/FloatValidator'\nimport { MoneyValidator } from './validators/MoneyValidator'\nimport { IntegerValidator } from './validators/IntegerValidator'\nimport { ZipCodeValidator } from './validators/ZipCodeValidator'\nimport { DocumentValidator } from './validators/DocumentValidator'\nimport { NumericSymbolValidator } from './validators/NumericSymbolValidator'\n\nexport function registerBrMasks() {\n MaskModule.registerMask(Locale.BR, MaskType.CPF, new CpfMask())\n MaskModule.registerValidator(Locale.BR, MaskType.CPF, new CpfValidator())\n\n MaskModule.registerMask(Locale.BR, MaskType.CNPJ, new CnpjMask())\n MaskModule.registerValidator(Locale.BR, MaskType.CNPJ, new CnpjValidator())\n\n MaskModule.registerMask(Locale.BR, MaskType.DOCUMENT, new DocumentMask())\n MaskModule.registerValidator(\n Locale.BR,\n MaskType.DOCUMENT,\n new DocumentValidator()\n )\n\n MaskModule.registerMask(Locale.BR, MaskType.TIME, new TimeMask())\n MaskModule.registerValidator(Locale.BR, MaskType.TIME, new TimeValidator())\n\n MaskModule.registerValidator(\n Locale.BR,\n MaskType.ZIP_CODE,\n new ZipCodeValidator()\n )\n\n MaskModule.registerMask(Locale.BR, MaskType.PHONE, new PhoneMask())\n MaskModule.registerValidator(Locale.BR, MaskType.PHONE, new PhoneValidator())\n\n MaskModule.registerMask(Locale.BR, MaskType.DATE, new DateMask())\n MaskModule.registerValidator(Locale.BR, MaskType.DATE, new DateValidator())\n\n MaskModule.registerMask(Locale.BR, MaskType.FLOAT, new FloatMask())\n MaskModule.registerValidator(Locale.BR, MaskType.FLOAT, new FloatValidator())\n\n MaskModule.registerMask(Locale.BR, MaskType.INTEGER, new IntegerMask())\n MaskModule.registerValidator(\n Locale.BR,\n MaskType.INTEGER,\n new IntegerValidator()\n )\n\n MaskModule.registerMask(Locale.BR, MaskType.MONEY, new MoneyMask())\n MaskModule.registerValidator(Locale.BR, MaskType.MONEY, new MoneyValidator())\n\n MaskModule.registerMask(\n Locale.BR,\n MaskType.NUMERIC_SYMBOL,\n new NumericSymbolMask()\n )\n MaskModule.registerValidator(\n Locale.BR,\n MaskType.NUMERIC_SYMBOL,\n new NumericSymbolValidator()\n )\n\n MaskModule.registerMask(Locale.BR, MaskType.ZIP_CODE, new ZipCodeMask())\n MaskModule.registerValidator(\n Locale.BR,\n MaskType.ZIP_CODE,\n new ZipCodeValidator()\n )\n}\n","import { registerBrMasks } from './locales/br/registerMasks'\n\nexport * from './enums'\nexport * from './MaskModule'\n\n// Register default locales\nregisterBrMasks()\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover-DwxxEmVF.js","names":["node: HTMLElement | null","Popover: React.FC<PopoverProps>"],"sources":["../src/components/commons/toolkit/Popover/hooks/usePortalContainer/index.ts","../src/components/commons/toolkit/Popover/utils/focusNextFrom.ts","../src/components/commons/toolkit/Popover/utils/portal.ts","../src/components/commons/toolkit/Popover/hooks/usePopoverA11yFocus/index.ts","../src/components/commons/toolkit/Popover/hooks/usePopoverFloatingOptions/index.ts","../src/components/commons/toolkit/Popover/styles.ts","../src/components/commons/toolkit/Popover/types.ts","../src/components/commons/toolkit/Popover/index.tsx"],"sourcesContent":["// External Libraries\nimport { useEffect, useMemo, useRef, useState } from 'react'\n\nexport function usePortalContainer(portalId?: string) {\n const portalRef = useRef<HTMLElement | null>(null)\n const [portalEl, setPortalEl] = useState<HTMLElement | null>(null)\n\n useEffect(() => {\n if (typeof document === 'undefined') return\n\n if (!portalId) {\n setPortalEl(null)\n return\n }\n\n const found = document.getElementById(portalId) as HTMLElement | null\n setPortalEl(found)\n if (found) return\n\n const obs = new MutationObserver(() => {\n const el = document.getElementById(portalId) as HTMLElement | null\n if (el) {\n setPortalEl(el)\n obs.disconnect()\n }\n })\n\n obs.observe(document.documentElement, { childList: true, subtree: true })\n return () => obs.disconnect()\n }, [portalId])\n\n useEffect(() => {\n portalRef.current = portalEl\n }, [portalEl])\n\n const portalContainer = useMemo(() => {\n if (typeof document === 'undefined') return null\n return portalEl ?? document.body\n }, [portalEl])\n\n return { portalRef, portalEl, portalContainer }\n}\n","const SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]'\n].join(',')\n\nfunction isVisible(el: HTMLElement) {\n const style = window.getComputedStyle(el)\n if (style.display === 'none' || style.visibility === 'hidden') return false\n const r = el.getBoundingClientRect()\n return r.width > 0 && r.height > 0\n}\n\nexport function focusNextFrom(from: HTMLElement, root: ParentNode = document) {\n const list = Array.from(root.querySelectorAll<HTMLElement>(SELECTOR)).filter(\n isVisible\n )\n\n const i = list.indexOf(from)\n const next = i >= 0 ? list[i + 1] : list[0]\n next?.focus?.()\n return next ?? null\n}\n","export function resolvePortalContainer(portalId?: string): HTMLElement | null {\n if (typeof document === 'undefined') return null\n if (!portalId) return document.body\n return document.getElementById(portalId) ?? document.body\n}\n\nexport function createsFixedContainingBlock(el: HTMLElement): boolean {\n let node: HTMLElement | null = el\n while (node) {\n const s = getComputedStyle(node)\n if (\n s.transform !== 'none' ||\n s.translate !== 'none' ||\n s.perspective !== 'none' ||\n s.filter !== 'none' ||\n s.backdropFilter !== 'none' ||\n s.contain.includes('paint')\n ) {\n return true\n }\n node = node.parentElement\n }\n return false\n}\n","// External Libraries\nimport { useEffect, useRef } from 'react'\n\n// Utils\nimport { focusNextFrom } from '../../utils'\n\n// Types\nimport type { CloseReason } from '../../types'\n\ntype Params = {\n open: boolean\n restoreFocusOnClose: boolean\n triggerRef: React.RefObject<HTMLElement | null>\n lastCloseReasonRef: React.MutableRefObject<CloseReason>\n setOpen: (v: boolean) => void\n}\n\nexport function usePopoverA11yFocus({\n open,\n restoreFocusOnClose,\n triggerRef,\n lastCloseReasonRef,\n setOpen\n}: Params) {\n const tabFocusFromRef = useRef<HTMLElement | null>(null)\n const prevOpenRef = useRef<boolean>(open)\n\n useEffect(() => {\n if (!open) return\n if (typeof document === 'undefined') return\n\n const onKeyDownCapture = (e: KeyboardEvent) => {\n if (e.key !== 'Tab') return\n lastCloseReasonRef.current = 'tab'\n tabFocusFromRef.current = triggerRef.current\n setOpen(false)\n }\n\n document.addEventListener('keydown', onKeyDownCapture, true)\n return () => document.removeEventListener('keydown', onKeyDownCapture, true)\n }, [open, setOpen, triggerRef, lastCloseReasonRef])\n\n useEffect(() => {\n const wasOpen = prevOpenRef.current\n prevOpenRef.current = open\n\n if (open) return\n if (!wasOpen) return\n\n if (!restoreFocusOnClose) return\n\n const reason = lastCloseReasonRef.current\n\n if (reason === 'tab') {\n const from = tabFocusFromRef.current\n tabFocusFromRef.current = null\n lastCloseReasonRef.current = 'programmatic'\n\n if (from) {\n requestAnimationFrame(() => {\n focusNextFrom(from, document)\n })\n }\n return\n }\n\n requestAnimationFrame(() => triggerRef.current?.focus?.())\n lastCloseReasonRef.current = 'programmatic'\n }, [open, restoreFocusOnClose, triggerRef, lastCloseReasonRef])\n}\n","// External Libraries\nimport { useMemo } from 'react'\nimport type { RefObject } from 'react'\n\n// Hooks\nimport type { FloatingOptions } from '@hooks/useFloating/types'\n\n// Utils\nimport { createsFixedContainingBlock } from '../../utils'\n\ntype Params = {\n portalId?: string\n portalContainer: HTMLElement | null\n portalRef: RefObject<HTMLElement | null>\n floatingOptions?: FloatingOptions\n absoluteReference?: FloatingOptions['absoluteReference']\n}\n\nexport function usePopoverFloatingOptions({\n portalId,\n portalContainer,\n portalRef,\n floatingOptions,\n absoluteReference\n}: Params) {\n return useMemo(() => {\n const base = {\n offsetY: 6,\n keepInViewport: true,\n placement: 'bottom-start',\n portalRef\n } as const\n\n const userStrategy = floatingOptions?.strategy ?? 'fixed'\n\n const shouldFixFixedInPortal =\n !!portalId &&\n portalContainer &&\n userStrategy === 'fixed' &&\n portalContainer !== document.body &&\n createsFixedContainingBlock(portalContainer)\n\n if (shouldFixFixedInPortal) {\n return {\n ...base,\n ...floatingOptions,\n strategy: 'absolute',\n absoluteReference: 'offsetParent'\n } as any\n }\n\n return {\n ...base,\n ...floatingOptions,\n absoluteReference\n } as any\n }, [portalId, portalContainer, portalRef, floatingOptions, absoluteReference])\n}\n","// Types\nimport type { PopoverProps } from './types'\nimport { styled } from '@hooks/useThemedStyles/types'\n\nexport function createPopoverStyles({ hideShadow = false }: PopoverProps) {\n return styled({\n popoverNode: {\n position: 'fixed',\n left: 0,\n top: 0,\n\n zIndex: 10,\n\n padding: '0.25rem',\n\n backgroundColor: 'var(--px-bg)',\n boxShadow: hideShadow ? 'none' : 'var(--px-ring-1)',\n\n borderRadius: '0.75rem',\n overflow: 'hidden'\n },\n\n trigger: {\n width: 'fit-content',\n height: 'fit-content'\n }\n })\n}\n","// External Libraries\nimport type { MouseEvent, MouseEventHandler, ReactNode, RefObject } from 'react'\n\n// Types\nimport type { createPopoverStyles } from './styles'\nimport type { FloatingOptions } from '@hooks/useFloating/types'\nimport type { PaddingProps } from '@hooks/useThemedStyles/types'\n\nexport type PopoverTriggerRenderProps = {\n ariaExpanded: boolean\n ref: RefObject<HTMLElement>\n onClick: (event: MouseEvent<HTMLSpanElement>) => void\n}\n\nexport type CloseReason = 'outside' | 'escape' | 'tab' | 'programmatic'\n\nexport interface PopoverProps extends PaddingProps {\n open?: boolean\n portalId?: string\n containerId?: string\n hideShadow?: boolean\n dismissScope?: string\n closeOnEscape?: boolean\n closeOnOutsideClick?: boolean\n floatingOptions?: FloatingOptions\n anchorRef?: RefObject<HTMLElement>\n absoluteReference?: FloatingOptions['absoluteReference']\n\n restoreFocusOnClose?: boolean\n\n onOpenChange?: (v: boolean) => void\n onMouseEnter?: MouseEventHandler<HTMLDivElement>\n onMouseLeave?: MouseEventHandler<HTMLDivElement>\n content: (ctx: { close: () => void; widthTrigger: number }) => ReactNode\n trigger?: (props: PopoverTriggerRenderProps) => ReactNode\n\n styles?: Partial<ReturnType<typeof createPopoverStyles>>\n}\n","// External Libraries\nimport type React from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n type MouseEvent,\n useCallback,\n useEffect,\n useRef,\n useState\n} from 'react'\n\n// Hooks\nimport { useDismiss } from '@hooks/useDismiss'\nimport { useFloating } from '@hooks/useFloating'\nimport { useThemedStyles } from '@hooks/useThemedStyles'\nimport { usePortalContainer } from './hooks/usePortalContainer'\nimport { usePopoverA11yFocus } from './hooks/usePopoverA11yFocus'\nimport { usePopoverFloatingOptions } from './hooks/usePopoverFloatingOptions'\n\n// Types\nimport type { CloseReason, PopoverProps } from './types'\n\n// Styles\nimport { createPopoverStyles } from './styles'\n\nexport * as PopoverTypes from './types'\n\nexport const Popover: React.FC<PopoverProps> = props => {\n const {\n portalId,\n anchorRef,\n dismissScope,\n floatingOptions,\n absoluteReference,\n closeOnEscape = true,\n open: controlledOpen,\n closeOnOutsideClick = true,\n restoreFocusOnClose = true,\n trigger,\n content,\n onOpenChange,\n onMouseEnter,\n onMouseLeave\n } = props\n\n const triggerRef = useRef<HTMLElement | null>(null)\n const popoverRef = useRef<HTMLDivElement | null>(null)\n const resolvedAnchorRef = (anchorRef ?? triggerRef) as any\n\n const lastCloseReasonRef = useRef<CloseReason>('programmatic')\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false)\n const [widthTrigger, setWidthTrigger] = useState(0)\n const open = controlledOpen ?? uncontrolledOpen\n\n const { portalRef, portalContainer } = usePortalContainer(portalId)\n\n const { styles } = useThemedStyles(props, createPopoverStyles, {\n applyCommonProps: true,\n override: props.styles,\n commonSlot: 'popoverNode',\n pick: p => [p.open, p.content, p.trigger]\n })\n\n const setOpen = useCallback(\n (v: boolean) => {\n onOpenChange?.(v)\n if (controlledOpen === undefined) setUncontrolledOpen(v)\n },\n [controlledOpen, onOpenChange]\n )\n\n const effectiveFloating = usePopoverFloatingOptions({\n portalId,\n portalContainer: portalContainer as any,\n portalRef,\n floatingOptions,\n absoluteReference\n })\n\n const { floatingRef, update } = useFloating(\n resolvedAnchorRef,\n effectiveFloating\n )\n\n usePopoverA11yFocus({\n open,\n triggerRef,\n lastCloseReasonRef,\n restoreFocusOnClose,\n setOpen\n })\n\n useDismiss({\n open,\n closeOnEscape,\n closeOnOutsideClick,\n dismissScope: props.dismissScope,\n refs: [triggerRef, popoverRef],\n onClose: () => {\n lastCloseReasonRef.current = 'outside'\n setOpen(false)\n }\n })\n\n useEffect(() => {\n if (!open) return\n setWidthTrigger(triggerRef.current?.offsetWidth ?? 0)\n requestAnimationFrame(update)\n }, [open, update])\n\n const triggerNode =\n trigger?.({\n ariaExpanded: open,\n ref: triggerRef as any,\n onClick: handleTriggerClick\n }) ?? null\n\n const popoverNode = open ? (\n <div\n ref={el => {\n popoverRef.current = el\n floatingRef(el as any)\n }}\n role=\"dialog\"\n style={styles.popoverNode}\n data-dismiss-scope={dismissScope}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onKeyDown={e => {\n if (e.key === 'Escape') {\n e.preventDefault()\n lastCloseReasonRef.current = 'escape'\n setOpen(false)\n }\n }}\n >\n {content({ close: () => setOpen(false), widthTrigger })}\n </div>\n ) : null\n\n // Functions\n function handleTriggerClick(e: MouseEvent) {\n e.stopPropagation()\n e.preventDefault()\n setOpen(!open)\n }\n\n return (\n <>\n {triggerNode}\n {typeof document !== 'undefined'\n ? createPortal(popoverNode, portalContainer ?? document.body)\n : null}\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Popover-DwxxEmVF.js","names":["node: HTMLElement | null","Popover: React.FC<PopoverProps>"],"sources":["../src/components/commons/toolkit/Popover/hooks/usePortalContainer/index.ts","../src/components/commons/toolkit/Popover/utils/focusNextFrom.ts","../src/components/commons/toolkit/Popover/utils/portal.ts","../src/components/commons/toolkit/Popover/hooks/usePopoverA11yFocus/index.ts","../src/components/commons/toolkit/Popover/hooks/usePopoverFloatingOptions/index.ts","../src/components/commons/toolkit/Popover/styles.ts","../src/components/commons/toolkit/Popover/types.ts","../src/components/commons/toolkit/Popover/index.tsx"],"sourcesContent":["// External Libraries\nimport { useEffect, useMemo, useRef, useState } from 'react'\n\nexport function usePortalContainer(portalId?: string) {\n const portalRef = useRef<HTMLElement | null>(null)\n const [portalEl, setPortalEl] = useState<HTMLElement | null>(null)\n\n useEffect(() => {\n if (typeof document === 'undefined') return\n\n if (!portalId) {\n setPortalEl(null)\n return\n }\n\n const found = document.getElementById(portalId) as HTMLElement | null\n setPortalEl(found)\n if (found) return\n\n const obs = new MutationObserver(() => {\n const el = document.getElementById(portalId) as HTMLElement | null\n if (el) {\n setPortalEl(el)\n obs.disconnect()\n }\n })\n\n obs.observe(document.documentElement, { childList: true, subtree: true })\n return () => obs.disconnect()\n }, [portalId])\n\n useEffect(() => {\n portalRef.current = portalEl\n }, [portalEl])\n\n const portalContainer = useMemo(() => {\n if (typeof document === 'undefined') return null\n return portalEl ?? document.body\n }, [portalEl])\n\n return { portalRef, portalEl, portalContainer }\n}\n","const SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]'\n].join(',')\n\nfunction isVisible(el: HTMLElement) {\n const style = window.getComputedStyle(el)\n if (style.display === 'none' || style.visibility === 'hidden') return false\n const r = el.getBoundingClientRect()\n return r.width > 0 && r.height > 0\n}\n\nexport function focusNextFrom(from: HTMLElement, root: ParentNode = document) {\n const list = Array.from(root.querySelectorAll<HTMLElement>(SELECTOR)).filter(\n isVisible\n )\n\n const i = list.indexOf(from)\n const next = i >= 0 ? list[i + 1] : list[0]\n next?.focus?.()\n return next ?? null\n}\n","export function resolvePortalContainer(portalId?: string): HTMLElement | null {\n if (typeof document === 'undefined') return null\n if (!portalId) return document.body\n return document.getElementById(portalId) ?? document.body\n}\n\nexport function createsFixedContainingBlock(el: HTMLElement): boolean {\n let node: HTMLElement | null = el\n while (node) {\n const s = getComputedStyle(node)\n if (\n s.transform !== 'none' ||\n s.translate !== 'none' ||\n s.perspective !== 'none' ||\n s.filter !== 'none' ||\n s.backdropFilter !== 'none' ||\n s.contain.includes('paint')\n ) {\n return true\n }\n node = node.parentElement\n }\n return false\n}\n","// External Libraries\nimport { useEffect, useRef } from 'react'\n\n// Utils\nimport { focusNextFrom } from '../../utils'\n\n// Types\nimport type { CloseReason } from '../../types'\n\ntype Params = {\n open: boolean\n restoreFocusOnClose: boolean\n triggerRef: React.RefObject<HTMLElement | null>\n lastCloseReasonRef: React.MutableRefObject<CloseReason>\n setOpen: (v: boolean) => void\n}\n\nexport function usePopoverA11yFocus({\n open,\n restoreFocusOnClose,\n triggerRef,\n lastCloseReasonRef,\n setOpen\n}: Params) {\n const tabFocusFromRef = useRef<HTMLElement | null>(null)\n const prevOpenRef = useRef<boolean>(open)\n\n useEffect(() => {\n if (!open) return\n if (typeof document === 'undefined') return\n\n const onKeyDownCapture = (e: KeyboardEvent) => {\n if (e.key !== 'Tab') return\n lastCloseReasonRef.current = 'tab'\n tabFocusFromRef.current = triggerRef.current\n setOpen(false)\n }\n\n document.addEventListener('keydown', onKeyDownCapture, true)\n return () => document.removeEventListener('keydown', onKeyDownCapture, true)\n }, [open, setOpen, triggerRef, lastCloseReasonRef])\n\n useEffect(() => {\n const wasOpen = prevOpenRef.current\n prevOpenRef.current = open\n\n if (open) return\n if (!wasOpen) return\n\n if (!restoreFocusOnClose) return\n\n const reason = lastCloseReasonRef.current\n\n if (reason === 'tab') {\n const from = tabFocusFromRef.current\n tabFocusFromRef.current = null\n lastCloseReasonRef.current = 'programmatic'\n\n if (from) {\n requestAnimationFrame(() => {\n focusNextFrom(from, document)\n })\n }\n return\n }\n\n requestAnimationFrame(() => triggerRef.current?.focus?.())\n lastCloseReasonRef.current = 'programmatic'\n }, [open, restoreFocusOnClose, triggerRef, lastCloseReasonRef])\n}\n","// External Libraries\nimport { useMemo } from 'react'\nimport type { RefObject } from 'react'\n\n// Hooks\nimport type { FloatingOptions } from '@hooks/useFloating/types'\n\n// Utils\nimport { createsFixedContainingBlock } from '../../utils'\n\ntype Params = {\n portalId?: string\n portalContainer: HTMLElement | null\n portalRef: RefObject<HTMLElement | null>\n floatingOptions?: FloatingOptions\n absoluteReference?: FloatingOptions['absoluteReference']\n}\n\nexport function usePopoverFloatingOptions({\n portalId,\n portalContainer,\n portalRef,\n floatingOptions,\n absoluteReference\n}: Params) {\n return useMemo(() => {\n const base = {\n offsetY: 6,\n keepInViewport: true,\n placement: 'bottom-start',\n portalRef\n } as const\n\n const userStrategy = floatingOptions?.strategy ?? 'fixed'\n\n const shouldFixFixedInPortal =\n !!portalId &&\n portalContainer &&\n userStrategy === 'fixed' &&\n portalContainer !== document.body &&\n createsFixedContainingBlock(portalContainer)\n\n if (shouldFixFixedInPortal) {\n return {\n ...base,\n ...floatingOptions,\n strategy: 'absolute',\n absoluteReference: 'offsetParent'\n } as any\n }\n\n return {\n ...base,\n ...floatingOptions,\n absoluteReference\n } as any\n }, [portalId, portalContainer, portalRef, floatingOptions, absoluteReference])\n}\n","// Types\nimport type { PopoverProps } from './types'\nimport { styled } from '@hooks/useThemedStyles/types'\n\nexport function createPopoverStyles({ hideShadow = false }: PopoverProps) {\n return styled({\n popoverNode: {\n position: 'fixed',\n left: 0,\n top: 0,\n\n zIndex: 10,\n\n padding: '0.25rem',\n\n backgroundColor: 'var(--px-bg)',\n boxShadow: hideShadow ? 'none' : 'var(--px-ring-1)',\n\n borderRadius: '0.75rem',\n overflow: 'hidden'\n },\n\n trigger: {\n width: 'fit-content',\n height: 'fit-content'\n }\n })\n}\n","// External Libraries\nimport type { MouseEvent, MouseEventHandler, ReactNode, RefObject } from 'react'\n\n// Types\nimport type { createPopoverStyles } from './styles'\nimport type { FloatingOptions } from '@hooks/useFloating/types'\nimport type { PaddingProps, TypeStyles } from '@hooks/useThemedStyles/types'\n\nexport type PopoverTriggerRenderProps = {\n ariaExpanded: boolean\n ref: RefObject<HTMLElement>\n onClick: (event: MouseEvent<HTMLSpanElement>) => void\n}\n\nexport type CloseReason = 'outside' | 'escape' | 'tab' | 'programmatic'\n\nexport interface PopoverProps extends PaddingProps {\n open?: boolean\n portalId?: string\n containerId?: string\n hideShadow?: boolean\n dismissScope?: string\n closeOnEscape?: boolean\n closeOnOutsideClick?: boolean\n floatingOptions?: FloatingOptions\n anchorRef?: RefObject<HTMLElement>\n absoluteReference?: FloatingOptions['absoluteReference']\n\n restoreFocusOnClose?: boolean\n\n onOpenChange?: (v: boolean) => void\n onMouseEnter?: MouseEventHandler<HTMLDivElement>\n onMouseLeave?: MouseEventHandler<HTMLDivElement>\n content: (ctx: { close: () => void; widthTrigger: number }) => ReactNode\n trigger?: (props: PopoverTriggerRenderProps) => ReactNode\n\n styles?: TypeStyles<typeof createPopoverStyles>\n}\n","// External Libraries\nimport type React from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n type MouseEvent,\n useCallback,\n useEffect,\n useRef,\n useState\n} from 'react'\n\n// Hooks\nimport { useDismiss } from '@hooks/useDismiss'\nimport { useFloating } from '@hooks/useFloating'\nimport { useThemedStyles } from '@hooks/useThemedStyles'\nimport { usePortalContainer } from './hooks/usePortalContainer'\nimport { usePopoverA11yFocus } from './hooks/usePopoverA11yFocus'\nimport { usePopoverFloatingOptions } from './hooks/usePopoverFloatingOptions'\n\n// Types\nimport type { CloseReason, PopoverProps } from './types'\n\n// Styles\nimport { createPopoverStyles } from './styles'\n\nexport * as PopoverTypes from './types'\n\nexport const Popover: React.FC<PopoverProps> = props => {\n const {\n portalId,\n anchorRef,\n dismissScope,\n floatingOptions,\n absoluteReference,\n closeOnEscape = true,\n open: controlledOpen,\n closeOnOutsideClick = true,\n restoreFocusOnClose = true,\n trigger,\n content,\n onOpenChange,\n onMouseEnter,\n onMouseLeave\n } = props\n\n const triggerRef = useRef<HTMLElement | null>(null)\n const popoverRef = useRef<HTMLDivElement | null>(null)\n const resolvedAnchorRef = (anchorRef ?? triggerRef) as any\n\n const lastCloseReasonRef = useRef<CloseReason>('programmatic')\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false)\n const [widthTrigger, setWidthTrigger] = useState(0)\n const open = controlledOpen ?? uncontrolledOpen\n\n const { portalRef, portalContainer } = usePortalContainer(portalId)\n\n const { styles } = useThemedStyles(props, createPopoverStyles, {\n applyCommonProps: true,\n override: props.styles,\n commonSlot: 'popoverNode',\n pick: p => [p.open, p.content, p.trigger]\n })\n\n const setOpen = useCallback(\n (v: boolean) => {\n onOpenChange?.(v)\n if (controlledOpen === undefined) setUncontrolledOpen(v)\n },\n [controlledOpen, onOpenChange]\n )\n\n const effectiveFloating = usePopoverFloatingOptions({\n portalId,\n portalContainer: portalContainer as any,\n portalRef,\n floatingOptions,\n absoluteReference\n })\n\n const { floatingRef, update } = useFloating(\n resolvedAnchorRef,\n effectiveFloating\n )\n\n usePopoverA11yFocus({\n open,\n triggerRef,\n lastCloseReasonRef,\n restoreFocusOnClose,\n setOpen\n })\n\n useDismiss({\n open,\n closeOnEscape,\n closeOnOutsideClick,\n dismissScope: props.dismissScope,\n refs: [triggerRef, popoverRef],\n onClose: () => {\n lastCloseReasonRef.current = 'outside'\n setOpen(false)\n }\n })\n\n useEffect(() => {\n if (!open) return\n setWidthTrigger(triggerRef.current?.offsetWidth ?? 0)\n requestAnimationFrame(update)\n }, [open, update])\n\n const triggerNode =\n trigger?.({\n ariaExpanded: open,\n ref: triggerRef as any,\n onClick: handleTriggerClick\n }) ?? null\n\n const popoverNode = open ? (\n <div\n ref={el => {\n popoverRef.current = el\n floatingRef(el as any)\n }}\n role=\"dialog\"\n style={styles.popoverNode}\n data-dismiss-scope={dismissScope}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onKeyDown={e => {\n if (e.key === 'Escape') {\n e.preventDefault()\n lastCloseReasonRef.current = 'escape'\n setOpen(false)\n }\n }}\n >\n {content({ close: () => setOpen(false), widthTrigger })}\n </div>\n ) : null\n\n // Functions\n function handleTriggerClick(e: MouseEvent) {\n e.stopPropagation()\n e.preventDefault()\n setOpen(!open)\n }\n\n return (\n <>\n {triggerNode}\n {typeof document !== 'undefined'\n ? createPortal(popoverNode, portalContainer ?? document.body)\n : null}\n </>\n )\n}\n"],"mappings":"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"}
|