@stackcraftmx/calcita 0.51.0 → 0.53.0
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/README.md +73 -6
- package/cli/calcita.js +4 -2
- package/cli/checkTexts.js +66 -9
- package/dist/appShell/BarActionButton.js.map +1 -1
- package/dist/datePickers/DateInput.js +5 -3
- package/dist/datePickers/DateInput.js.map +1 -1
- package/dist/datePickers/DateTimeInput.js +6 -4
- package/dist/datePickers/DateTimeInput.js.map +1 -1
- package/dist/datePickers/FormDateField.js +1 -1
- package/dist/datePickers/FormDateField.js.map +1 -1
- package/dist/datePickers/FormDateTimeField.js +1 -1
- package/dist/datePickers/FormDateTimeField.js.map +1 -1
- package/dist/datePickers/FormMonthField.js +1 -1
- package/dist/datePickers/FormMonthField.js.map +1 -1
- package/dist/datePickers/FormTimeField.js +1 -1
- package/dist/datePickers/FormTimeField.js.map +1 -1
- package/dist/datePickers/MonthInput.js +5 -3
- package/dist/datePickers/MonthInput.js.map +1 -1
- package/dist/datePickers/PickerFrame.js +2 -2
- package/dist/datePickers/PickerFrame.js.map +1 -1
- package/dist/datePickers/TimeInput.js +6 -4
- package/dist/datePickers/TimeInput.js.map +1 -1
- package/dist/feedback/Toaster.js +11 -2
- package/dist/feedback/Toaster.js.map +1 -1
- package/dist/forms/CalcitaFormik.js +11 -0
- package/dist/forms/CalcitaFormik.js.map +1 -0
- package/dist/forms/FormAttachmentsField.js +1 -1
- package/dist/forms/FormAttachmentsField.js.map +1 -1
- package/dist/forms/FormCatalogField.js +1 -1
- package/dist/forms/FormCatalogField.js.map +1 -1
- package/dist/forms/FormCheckboxGroupField.js +1 -1
- package/dist/forms/FormCheckboxGroupField.js.map +1 -1
- package/dist/forms/FormColorField.js +1 -1
- package/dist/forms/FormColorField.js.map +1 -1
- package/dist/forms/FormFileField.js +1 -1
- package/dist/forms/FormFileField.js.map +1 -1
- package/dist/forms/FormFileUploadField.js +1 -1
- package/dist/forms/FormFileUploadField.js.map +1 -1
- package/dist/forms/FormImageField.js +1 -1
- package/dist/forms/FormImageField.js.map +1 -1
- package/dist/forms/FormMaskedField.js +1 -1
- package/dist/forms/FormMaskedField.js.map +1 -1
- package/dist/forms/FormNumberField.js +1 -1
- package/dist/forms/FormNumberField.js.map +1 -1
- package/dist/forms/FormSchemaProvider.js +17 -0
- package/dist/forms/FormSchemaProvider.js.map +1 -0
- package/dist/forms/FormSelectField.js +1 -1
- package/dist/forms/FormSelectField.js.map +1 -1
- package/dist/forms/FormTextField.js +1 -1
- package/dist/forms/FormTextField.js.map +1 -1
- package/dist/forms/FormTransferListField.js +1 -1
- package/dist/forms/FormTransferListField.js.map +1 -1
- package/dist/forms/FormWizard.js +23 -6
- package/dist/forms/FormWizard.js.map +1 -1
- package/dist/forms/schemaRequired.js +33 -0
- package/dist/forms/schemaRequired.js.map +1 -0
- package/dist/forms/useFormikField.js +18 -5
- package/dist/forms/useFormikField.js.map +1 -1
- package/dist/forms.js +52 -46
- package/dist/forms.js.map +1 -1
- package/dist/hookForm/FormAttachmentsField.js +1 -1
- package/dist/hookForm/FormAttachmentsField.js.map +1 -1
- package/dist/hookForm/FormCatalogField.js +1 -1
- package/dist/hookForm/FormCatalogField.js.map +1 -1
- package/dist/hookForm/FormCheckboxGroupField.js +1 -1
- package/dist/hookForm/FormCheckboxGroupField.js.map +1 -1
- package/dist/hookForm/FormColorField.js +1 -1
- package/dist/hookForm/FormColorField.js.map +1 -1
- package/dist/hookForm/FormFileField.js +1 -1
- package/dist/hookForm/FormFileField.js.map +1 -1
- package/dist/hookForm/FormFileUploadField.js +1 -1
- package/dist/hookForm/FormFileUploadField.js.map +1 -1
- package/dist/hookForm/FormImageField.js +1 -1
- package/dist/hookForm/FormImageField.js.map +1 -1
- package/dist/hookForm/FormMaskedField.js +1 -1
- package/dist/hookForm/FormMaskedField.js.map +1 -1
- package/dist/hookForm/FormNumberField.js +1 -1
- package/dist/hookForm/FormNumberField.js.map +1 -1
- package/dist/hookForm/FormSelectField.js +1 -1
- package/dist/hookForm/FormSelectField.js.map +1 -1
- package/dist/hookForm/FormTextField.js +1 -1
- package/dist/hookForm/FormTextField.js.map +1 -1
- package/dist/hookForm/FormTransferListField.js +1 -1
- package/dist/hookForm/FormTransferListField.js.map +1 -1
- package/dist/hookForm/FormWizard.js +21 -5
- package/dist/hookForm/FormWizard.js.map +1 -1
- package/dist/hookForm/useHookFormField.js +9 -3
- package/dist/hookForm/useHookFormField.js.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/inputs/CatalogInput.js +3 -2
- package/dist/inputs/CatalogInput.js.map +1 -1
- package/dist/inputs/CheckboxGroupInput.js +2 -1
- package/dist/inputs/CheckboxGroupInput.js.map +1 -1
- package/dist/inputs/ColorInput.js +3 -1
- package/dist/inputs/ColorInput.js.map +1 -1
- package/dist/inputs/FieldFrame.js +18 -3
- package/dist/inputs/FieldFrame.js.map +1 -1
- package/dist/inputs/FormSection.js +42 -11
- package/dist/inputs/FormSection.js.map +1 -1
- package/dist/inputs/NumberInput.js +3 -1
- package/dist/inputs/NumberInput.js.map +1 -1
- package/dist/inputs/SelectInput.js +3 -1
- package/dist/inputs/SelectInput.js.map +1 -1
- package/dist/inputs/TextInput.js +1 -1
- package/dist/inputs/TextInput.js.map +1 -1
- package/dist/inputs/TransferListInput.js +2 -1
- package/dist/inputs/TransferListInput.js.map +1 -1
- package/dist/inputs/WizardLayout.js +51 -17
- package/dist/inputs/WizardLayout.js.map +1 -1
- package/dist/inputs/formLayoutContext.js +7 -2
- package/dist/inputs/formLayoutContext.js.map +1 -1
- package/dist/inputs/requiredMark.js +17 -0
- package/dist/inputs/requiredMark.js.map +1 -0
- package/dist/inputs/useWizardSteps.js +36 -0
- package/dist/inputs/useWizardSteps.js.map +1 -0
- package/dist/inputs/wizardSteps.js +32 -0
- package/dist/inputs/wizardSteps.js.map +1 -0
- package/dist/locales/en.js +1 -0
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +1 -0
- package/dist/locales/es.js.map +1 -1
- package/dist/richText/FormRichTextField.js +1 -1
- package/dist/richText/FormRichTextField.js.map +1 -1
- package/dist/richText/RichTextEditor.js +4 -3
- package/dist/richText/RichTextEditor.js.map +1 -1
- package/dist/toolkit/ToolkitProvider.js +3 -0
- package/dist/toolkit/ToolkitProvider.js.map +1 -1
- package/dist/toolkit/toolkitContext.js.map +1 -1
- package/dist/types/appShell/BarActionButton.d.ts +1 -0
- package/dist/types/datePickers/DateInput.d.ts +2 -0
- package/dist/types/datePickers/DateTimeInput.d.ts +2 -0
- package/dist/types/datePickers/FormDateField.d.ts +3 -3
- package/dist/types/datePickers/FormDateTimeField.d.ts +3 -3
- package/dist/types/datePickers/FormMonthField.d.ts +3 -3
- package/dist/types/datePickers/FormTimeField.d.ts +3 -3
- package/dist/types/datePickers/MonthInput.d.ts +2 -0
- package/dist/types/datePickers/PickerFrame.d.ts +3 -1
- package/dist/types/datePickers/TimeInput.d.ts +2 -0
- package/dist/types/feedback/Toaster.d.ts +15 -1
- package/dist/types/feedback/index.d.ts +1 -1
- package/dist/types/forms/CalcitaFormik.d.ts +6 -0
- package/dist/types/forms/FormAttachmentsField.d.ts +3 -3
- package/dist/types/forms/FormCatalogField.d.ts +2 -2
- package/dist/types/forms/FormCheckboxGroupField.d.ts +3 -3
- package/dist/types/forms/FormColorField.d.ts +2 -2
- package/dist/types/forms/FormFileField.d.ts +3 -3
- package/dist/types/forms/FormFileUploadField.d.ts +3 -3
- package/dist/types/forms/FormImageField.d.ts +3 -3
- package/dist/types/forms/FormMaskedField.d.ts +2 -2
- package/dist/types/forms/FormNumberField.d.ts +2 -2
- package/dist/types/forms/FormSchemaProvider.d.ts +13 -0
- package/dist/types/forms/FormSelectField.d.ts +2 -2
- package/dist/types/forms/FormTextField.d.ts +2 -2
- package/dist/types/forms/FormTransferListField.d.ts +3 -3
- package/dist/types/forms/FormWizard.d.ts +14 -1
- package/dist/types/forms/index.d.ts +1 -0
- package/dist/types/forms/schemaRequired.d.ts +14 -0
- package/dist/types/forms/useFormikField.d.ts +10 -4
- package/dist/types/forms.d.ts +4 -2
- package/dist/types/hookForm/FormAttachmentsField.d.ts +3 -3
- package/dist/types/hookForm/FormCatalogField.d.ts +3 -3
- package/dist/types/hookForm/FormCheckboxGroupField.d.ts +3 -3
- package/dist/types/hookForm/FormColorField.d.ts +3 -3
- package/dist/types/hookForm/FormFileField.d.ts +3 -3
- package/dist/types/hookForm/FormFileUploadField.d.ts +3 -3
- package/dist/types/hookForm/FormImageField.d.ts +3 -3
- package/dist/types/hookForm/FormMaskedField.d.ts +3 -3
- package/dist/types/hookForm/FormNumberField.d.ts +3 -3
- package/dist/types/hookForm/FormSelectField.d.ts +3 -3
- package/dist/types/hookForm/FormTextField.d.ts +3 -3
- package/dist/types/hookForm/FormTransferListField.d.ts +3 -3
- package/dist/types/hookForm/FormWizard.d.ts +14 -1
- package/dist/types/hookForm/useHookFormField.d.ts +8 -4
- package/dist/types/index.d.ts +4 -3
- package/dist/types/inputs/CatalogInput.d.ts +1 -0
- package/dist/types/inputs/CheckboxGroupInput.d.ts +1 -0
- package/dist/types/inputs/ColorInput.d.ts +1 -0
- package/dist/types/inputs/FieldFrame.d.ts +1 -0
- package/dist/types/inputs/FormSection.d.ts +13 -0
- package/dist/types/inputs/NumberInput.d.ts +1 -0
- package/dist/types/inputs/SelectInput.d.ts +1 -0
- package/dist/types/inputs/TextInput.d.ts +1 -1
- package/dist/types/inputs/TransferListInput.d.ts +1 -0
- package/dist/types/inputs/WizardLayout.d.ts +6 -2
- package/dist/types/inputs/formLayoutContext.d.ts +8 -1
- package/dist/types/inputs/requiredMark.d.ts +9 -0
- package/dist/types/inputs/useWizardSteps.d.ts +23 -0
- package/dist/types/inputs/wizardSteps.d.ts +65 -0
- package/dist/types/locales/en.d.ts +1 -0
- package/dist/types/locales/es.d.ts +1 -0
- package/dist/types/richText/FormRichTextField.d.ts +3 -3
- package/dist/types/richText/RichTextEditor.d.ts +1 -0
- package/dist/types/toolkit/ToolkitProvider.d.ts +5 -1
- package/dist/types/toolkit/toolkitContext.d.ts +2 -1
- package/dist/types/ui/cards/RecordCard.d.ts +12 -0
- package/dist/types/ui/index.d.ts +1 -1
- package/dist/types/ui/navigation/BackButton.d.ts +1 -0
- package/dist/types/upload/AttachmentsInput.d.ts +2 -0
- package/dist/types/upload/FileInput.d.ts +1 -0
- package/dist/types/upload/FileUploadInput.d.ts +1 -0
- package/dist/types/upload/ImageInput.d.ts +1 -0
- package/dist/ui/cards/RecordCard.js +6 -2
- package/dist/ui/cards/RecordCard.js.map +1 -1
- package/dist/ui/navigation/BackButton.js.map +1 -1
- package/dist/upload/AttachmentsInput.js +2 -1
- package/dist/upload/AttachmentsInput.js.map +1 -1
- package/dist/upload/FileInput.js +2 -1
- package/dist/upload/FileInput.js.map +1 -1
- package/dist/upload/FileUploadInput.js +2 -1
- package/dist/upload/FileUploadInput.js.map +1 -1
- package/dist/upload/ImageInput.js +2 -1
- package/dist/upload/ImageInput.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MonthInput.js","sources":["../../src/datePickers/MonthInput.jsx"],"sourcesContent":["// Campo de MES suelto con el DatePicker de MUI X en meses y años (@stackcraftmx/calcita/date-pickers): el mes de un\n// reporte, de un saldo, de un cierre.\n//\n// Viaja 'AAAA-MM' en texto y se ve con el nombre del mes en el idioma activo («noviembre 2026»). Abre en los meses del año\n// que ya tiene; el año se cambia arriba. '' = vacío. Como la fecha, no se pasa por Date (que lo movería de mes según la\n// zona el día 1).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaMonthInput con defaultProps, styleOverrides de\n// sus partes (picker) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {DatePicker} from '@mui/x-date-pickers/DatePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {monthTextOf, pickerMonthOf} from '@/datePickers/pickerValues.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaMonthInput)\nconst THEME_NAME = 'CalcitaMonthInput';\nconst MonthInputPicker = piecePart(THEME_NAME, 'Picker', DatePicker);\n\n// primero el año y luego el mes: el selector abre en los meses y el año se cambia con su botón de arriba\nconst MONTH_VIEWS = ['year', 'month'];\n\n/**\n * @param {object} props\n * @param {string} [props.name]\n * @param {string} props.label ya traducido\n * @param {string|null|undefined} props.value 'AAAA-MM' o ''\n * @param {(value: string) => void} props.onChange recibe 'AAAA-MM' ('' al borrar o a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText]\n * @param {string} [props.minMonth] 'AAAA-MM'\n * @param {string} [props.maxMonth] 'AAAA-MM'\n * @param {boolean} [props.disableFuture] p. ej. el mes de un reporte que ya cerró\n * @param {boolean} [props.disablePast]\n * @param {boolean} [props.disabled]\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef]\n * @param {object} [props.pickerProps] lo demás del DatePicker de MUI X que aquí no tiene nombre (shouldDisableMonth, slots,\n * slotProps…); value y onChange son del campo\n * @param {Record<string, string|object>} [props.messages] el texto del error de este campo, por regla de validación\n * ({required: 'Elija la fecha', min: 'Desde mañana'}): gana al de Calcita y al de los textos\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction MonthInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText = ' ', minMonth, maxMonth, disableFuture = false, disablePast = false,\n disabled = false, inputRef, pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const field = usePickerField({name, kind: 'month', error, label, messages, texts});\n\n return (\n <PickerFrame inputId={field.inputId} label={label} language={field.language}>\n <MonthInputPicker\n {...pickerProps}\n views={MONTH_VIEWS}\n openTo=\"month\"\n format={field.formats.month}\n value={pickerMonthOf(value)}\n minDate={pickerMonthOf(minMonth) ?? undefined}\n maxDate={pickerMonthOf(maxMonth) ?? undefined}\n disableFuture={disableFuture}\n disablePast={disablePast}\n disabled={disabled}\n inputRef={inputRef}\n onChange={(pickedValue) => onChange(monthTextOf(pickedValue))}\n onClose={() => {\n pickerProps?.onClose?.();\n onBlur?.();\n }}\n slotProps={textFieldSlotPropsOf(\n {id: field.inputId, name, onBlur, error: Boolean(field.errorText), helperText: field.errorText ?? helperText},\n pickerProps,\n )}\n />\n </PickerFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst MonthInput = withPieceSlots(MonthInputContent, THEME_NAME);\nexport default MonthInput;\n"],"names":[],"mappings":";;;;;;;;AAoBA,MAAM,aAAa;AACnB,MAAM,mBAAmB,UAAU,YAAY,UAAU,UAAU;AAGnE,MAAM,cAAc,CAAC,QAAQ,OAAO;
|
|
1
|
+
{"version":3,"file":"MonthInput.js","sources":["../../src/datePickers/MonthInput.jsx"],"sourcesContent":["// Campo de MES suelto con el DatePicker de MUI X en meses y años (@stackcraftmx/calcita/date-pickers): el mes de un\n// reporte, de un saldo, de un cierre.\n//\n// Viaja 'AAAA-MM' en texto y se ve con el nombre del mes en el idioma activo («noviembre 2026»). Abre en los meses del año\n// que ya tiene; el año se cambia arriba. '' = vacío. Como la fecha, no se pasa por Date (que lo movería de mes según la\n// zona el día 1).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaMonthInput con defaultProps, styleOverrides de\n// sus partes (picker) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {DatePicker} from '@mui/x-date-pickers/DatePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {monthTextOf, pickerMonthOf} from '@/datePickers/pickerValues.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaMonthInput)\nconst THEME_NAME = 'CalcitaMonthInput';\nconst MonthInputPicker = piecePart(THEME_NAME, 'Picker', DatePicker);\n\n// primero el año y luego el mes: el selector abre en los meses y el año se cambia con su botón de arriba\nconst MONTH_VIEWS = ['year', 'month'];\n\n/**\n * @param {object} props\n * @param {string} [props.name]\n * @param {string} props.label ya traducido\n * @param {string|null|undefined} props.value 'AAAA-MM' o ''\n * @param {(value: string) => void} props.onChange recibe 'AAAA-MM' ('' al borrar o a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText]\n * @param {string} [props.minMonth] 'AAAA-MM'\n * @param {string} [props.maxMonth] 'AAAA-MM'\n * @param {boolean} [props.disableFuture] p. ej. el mes de un reporte que ya cerró\n * @param {boolean} [props.disablePast]\n * @param {boolean} [props.disabled]\n * @param {string} [props.format] cómo se ve el mes, con los códigos de dayjs ('MMM YYYY' enseña «nov 2026»); por omisión el nombre\n * completo del mes y el año\n * @param {boolean} [props.required] obligatorio: el asterisco en la etiqueta y, como en MUI, required en el campo\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef]\n * @param {object} [props.pickerProps] lo demás del DatePicker de MUI X que aquí no tiene nombre (shouldDisableMonth, slots,\n * slotProps…); value y onChange son del campo\n * @param {Record<string, string|object>} [props.messages] el texto del error de este campo, por regla de validación\n * ({required: 'Elija la fecha', min: 'Desde mañana'}): gana al de Calcita y al de los textos\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction MonthInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText = ' ', minMonth, maxMonth, disableFuture = false, disablePast = false,\n disabled = false, required = false, format, inputRef, pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const field = usePickerField({name, kind: 'month', error, label, messages, texts});\n\n return (\n <PickerFrame inputId={field.inputId} label={label} required={required} language={field.language}>\n <MonthInputPicker\n {...pickerProps}\n views={MONTH_VIEWS}\n openTo=\"month\"\n // el formato de la pantalla gana al de la casa (antes el de la casa iba después y lo pisaba sin avisar)\n format={format ?? pickerProps?.format ?? field.formats.month}\n value={pickerMonthOf(value)}\n minDate={pickerMonthOf(minMonth) ?? undefined}\n maxDate={pickerMonthOf(maxMonth) ?? undefined}\n disableFuture={disableFuture}\n disablePast={disablePast}\n disabled={disabled}\n inputRef={inputRef}\n onChange={(pickedValue) => onChange(monthTextOf(pickedValue))}\n onClose={() => {\n pickerProps?.onClose?.();\n onBlur?.();\n }}\n slotProps={textFieldSlotPropsOf(\n {id: field.inputId, name, onBlur, required, error: Boolean(field.errorText), helperText: field.errorText ?? helperText},\n pickerProps,\n )}\n />\n </PickerFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst MonthInput = withPieceSlots(MonthInputContent, THEME_NAME);\nexport default MonthInput;\n"],"names":[],"mappings":";;;;;;;;AAoBA,MAAM,aAAa;AACnB,MAAM,mBAAmB,UAAU,YAAY,UAAU,UAAU;AAGnE,MAAM,cAAc,CAAC,QAAQ,OAAO;AA0BpC,SAAS,kBAAkB,OAAO;AAC9B,QAAM;AAAA,IACF;AAAA,IAAM;AAAA,IAAO;AAAA,IAAO;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAO,aAAa;AAAA,IAAK;AAAA,IAAU;AAAA,IAAU,gBAAgB;AAAA,IAAO,cAAc;AAAA,IACxH,WAAW;AAAA,IAAO,WAAW;AAAA,IAAO;AAAA,IAAQ;AAAA,IAAU;AAAA,IAAa;AAAA,IAAU;AAAA,IAC7E,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,QAAQ,eAAe,EAAC,MAAM,MAAM,SAAS,OAAO,OAAO,UAAU,OAAM;AAEjF,SACI,oBAAC,eAAY,SAAS,MAAM,SAAS,OAAc,UAAoB,UAAU,MAAM,UACnF,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ,OAAO;AAAA,MACP,QAAO;AAAA,MAEP,QAAQ,UAAU,aAAa,UAAU,MAAM,QAAQ;AAAA,MACvD,OAAO,cAAc,KAAK;AAAA,MAC1B,SAAS,cAAc,QAAQ,KAAK;AAAA,MACpC,SAAS,cAAc,QAAQ,KAAK;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,CAAC,gBAAgB,SAAS,YAAY,WAAW,CAAC;AAAA,MAC5D,SAAS,MAAM;AACX,qBAAa,UAAA;AACb,iBAAA;AAAA,MACJ;AAAA,MACA,WAAW;AAAA,QACP,EAAC,IAAI,MAAM,SAAS,MAAM,QAAQ,UAAU,OAAO,QAAQ,MAAM,SAAS,GAAG,YAAY,MAAM,aAAa,WAAA;AAAA,QAC5G;AAAA,MAAA;AAAA,IACJ;AAAA,EAAA,GAER;AAER;AAGA,MAAM,aAAa,eAAe,mBAAmB,UAAU;"}
|
|
@@ -16,9 +16,9 @@ function textFieldSlotPropsOf(textField, pickerProps) {
|
|
|
16
16
|
textField: { size: "small", fullWidth: true, ...textField, ...screenSlotProps.textField }
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
-
function PickerFrame({ inputId, label, language, children }) {
|
|
19
|
+
function PickerFrame({ inputId, label, language, required = false, children }) {
|
|
20
20
|
const adapter = ADAPTER_BY_LANGUAGE[language] ?? ADAPTER_BY_LANGUAGE.es;
|
|
21
|
-
return /* @__PURE__ */ jsx(FieldFrame, { inputId, label, children: /* @__PURE__ */ jsx(LocalizationProvider, { dateAdapter: AdapterDayjs, adapterLocale: adapter.adapterLocale, localeText: adapter.localeText, children }) });
|
|
21
|
+
return /* @__PURE__ */ jsx(FieldFrame, { inputId, label, required, children: /* @__PURE__ */ jsx(LocalizationProvider, { dateAdapter: AdapterDayjs, adapterLocale: adapter.adapterLocale, localeText: adapter.localeText, children }) });
|
|
22
22
|
}
|
|
23
23
|
export {
|
|
24
24
|
PickerFrame as default,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickerFrame.js","sources":["../../src/datePickers/PickerFrame.jsx"],"sourcesContent":["// El marco que comparten los campos de fecha, fecha con hora, hora y mes: la etiqueta arriba como los demás campos del\n// paquete (FieldFrame; dentro de una FormSection, el renglón de Apple) y el LocalizationProvider de MUI X con dayjs, el\n// idioma activo y los textos del calendario en ese idioma. Así la pantalla no pone nada alrededor.\n//\n// También arma las piezas de MUI X que se repiten en los cuatro (textFieldSlotPropsOf): el campo chico, a todo lo ancho,\n// con su error o su ayuda abajo, y lo que la pantalla le pase en pickerProps.slotProps.textField encima.\n//\n// Genérico del paquete: function (regla de la casa).\n\n// con .js: Node (la prueba de humo, Next al pintar en el servidor) no completa la extensión de un archivo suelto de dayjs\nimport 'dayjs/locale/es.js';\nimport {AdapterDayjs} from '@mui/x-date-pickers/AdapterDayjs';\nimport {LocalizationProvider} from '@mui/x-date-pickers/LocalizationProvider';\nimport {enUS, esES} from '@mui/x-date-pickers/locales';\n\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\n\n// el idioma de dayjs (nombres de meses y días) y los textos del calendario de MUI X en cada idioma; el que no está aquí\n// sale en español, como desde antes\nconst ADAPTER_BY_LANGUAGE = Object.freeze({\n es: {adapterLocale: 'es', localeText: esES.components.MuiLocalizationProvider.defaultProps.localeText},\n en: {adapterLocale: 'en', localeText: enUS.components.MuiLocalizationProvider.defaultProps.localeText},\n});\n\n/**\n * Los slotProps del selector con el campo de la casa y, encima, lo que pasó la pantalla en pickerProps.slotProps.\n *\n * @param {object} textField lo de la casa: id, name, onBlur, error, helperText\n * @param {object} [pickerProps] lo que la pantalla le pasa al selector de MUI X\n * @returns {object}\n */\nexport function textFieldSlotPropsOf(textField, pickerProps) {\n const screenSlotProps = pickerProps?.slotProps ?? {};\n return {\n ...screenSlotProps,\n textField: {size: 'small', fullWidth: true, ...textField, ...screenSlotProps.textField},\n };\n}\n\n/**\n * @param {object} props\n * @param {string} props.inputId\n * @param {import('react').ReactNode} props.label ya traducida\n * @param {string} props.language el del proveedor más cercano\n * @param {import('react').ReactNode} props.children el selector de MUI X\n */\nexport default function PickerFrame({inputId, label, language, children}) {\n const adapter = ADAPTER_BY_LANGUAGE[language] ?? ADAPTER_BY_LANGUAGE.es;\n\n return (\n <FieldFrame inputId={inputId} label={label}>\n <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={adapter.adapterLocale} localeText={adapter.localeText}>\n {children}\n </LocalizationProvider>\n </FieldFrame>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAmBA,MAAM,sBAAsB,OAAO,OAAO;AAAA,EACtC,IAAI,EAAC,eAAe,MAAM,YAAY,KAAK,WAAW,wBAAwB,aAAa,WAAA;AAAA,EAC3F,IAAI,EAAC,eAAe,MAAM,YAAY,KAAK,WAAW,wBAAwB,aAAa,WAAA;AAC/F,CAAC;AASM,SAAS,qBAAqB,WAAW,aAAa;AACzD,QAAM,kBAAkB,aAAa,aAAa,CAAA;AAClD,SAAO;AAAA,IACH,GAAG;AAAA,IACH,WAAW,EAAC,MAAM,SAAS,WAAW,MAAM,GAAG,WAAW,GAAG,gBAAgB,UAAA;AAAA,EAAS;AAE9F;
|
|
1
|
+
{"version":3,"file":"PickerFrame.js","sources":["../../src/datePickers/PickerFrame.jsx"],"sourcesContent":["// El marco que comparten los campos de fecha, fecha con hora, hora y mes: la etiqueta arriba como los demás campos del\n// paquete (FieldFrame; dentro de una FormSection, el renglón de Apple) y el LocalizationProvider de MUI X con dayjs, el\n// idioma activo y los textos del calendario en ese idioma. Así la pantalla no pone nada alrededor.\n//\n// También arma las piezas de MUI X que se repiten en los cuatro (textFieldSlotPropsOf): el campo chico, a todo lo ancho,\n// con su error o su ayuda abajo, y lo que la pantalla le pase en pickerProps.slotProps.textField encima.\n//\n// Genérico del paquete: function (regla de la casa).\n\n// con .js: Node (la prueba de humo, Next al pintar en el servidor) no completa la extensión de un archivo suelto de dayjs\nimport 'dayjs/locale/es.js';\nimport {AdapterDayjs} from '@mui/x-date-pickers/AdapterDayjs';\nimport {LocalizationProvider} from '@mui/x-date-pickers/LocalizationProvider';\nimport {enUS, esES} from '@mui/x-date-pickers/locales';\n\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\n\n// el idioma de dayjs (nombres de meses y días) y los textos del calendario de MUI X en cada idioma; el que no está aquí\n// sale en español, como desde antes\nconst ADAPTER_BY_LANGUAGE = Object.freeze({\n es: {adapterLocale: 'es', localeText: esES.components.MuiLocalizationProvider.defaultProps.localeText},\n en: {adapterLocale: 'en', localeText: enUS.components.MuiLocalizationProvider.defaultProps.localeText},\n});\n\n/**\n * Los slotProps del selector con el campo de la casa y, encima, lo que pasó la pantalla en pickerProps.slotProps.\n *\n * @param {object} textField lo de la casa: id, name, onBlur, error, helperText\n * @param {object} [pickerProps] lo que la pantalla le pasa al selector de MUI X\n * @returns {object}\n */\nexport function textFieldSlotPropsOf(textField, pickerProps) {\n const screenSlotProps = pickerProps?.slotProps ?? {};\n return {\n ...screenSlotProps,\n textField: {size: 'small', fullWidth: true, ...textField, ...screenSlotProps.textField},\n };\n}\n\n/**\n * @param {object} props\n * @param {string} props.inputId\n * @param {import('react').ReactNode} props.label ya traducida\n * @param {string} props.language el del proveedor más cercano\n * @param {boolean} [props.required] el asterisco en la etiqueta\n * @param {import('react').ReactNode} props.children el selector de MUI X\n */\nexport default function PickerFrame({inputId, label, language, required = false, children}) {\n const adapter = ADAPTER_BY_LANGUAGE[language] ?? ADAPTER_BY_LANGUAGE.es;\n\n return (\n <FieldFrame inputId={inputId} label={label} required={required}>\n <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={adapter.adapterLocale} localeText={adapter.localeText}>\n {children}\n </LocalizationProvider>\n </FieldFrame>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAmBA,MAAM,sBAAsB,OAAO,OAAO;AAAA,EACtC,IAAI,EAAC,eAAe,MAAM,YAAY,KAAK,WAAW,wBAAwB,aAAa,WAAA;AAAA,EAC3F,IAAI,EAAC,eAAe,MAAM,YAAY,KAAK,WAAW,wBAAwB,aAAa,WAAA;AAC/F,CAAC;AASM,SAAS,qBAAqB,WAAW,aAAa;AACzD,QAAM,kBAAkB,aAAa,aAAa,CAAA;AAClD,SAAO;AAAA,IACH,GAAG;AAAA,IACH,WAAW,EAAC,MAAM,SAAS,WAAW,MAAM,GAAG,WAAW,GAAG,gBAAgB,UAAA;AAAA,EAAS;AAE9F;AAUA,SAAwB,YAAY,EAAC,SAAS,OAAO,UAAU,WAAW,OAAO,YAAW;AACxF,QAAM,UAAU,oBAAoB,QAAQ,KAAK,oBAAoB;AAErE,6BACK,YAAA,EAAW,SAAkB,OAAc,UACxC,8BAAC,sBAAA,EAAqB,aAAa,cAAc,eAAe,QAAQ,eAAe,YAAY,QAAQ,YACtG,UACL,GACJ;AAER;"}
|
|
@@ -21,6 +21,8 @@ function TimeInputContent(props) {
|
|
|
21
21
|
maxTime,
|
|
22
22
|
minutesStep = DEFAULT_MINUTES_STEP,
|
|
23
23
|
disabled = false,
|
|
24
|
+
required = false,
|
|
25
|
+
format,
|
|
24
26
|
inputRef,
|
|
25
27
|
pickerProps,
|
|
26
28
|
messages,
|
|
@@ -29,12 +31,12 @@ function TimeInputContent(props) {
|
|
|
29
31
|
} = usePieceProps(props, THEME_NAME);
|
|
30
32
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
31
33
|
const field = usePickerField({ name, kind: "time", error, label, messages, texts });
|
|
32
|
-
return /* @__PURE__ */ jsx(PickerFrame, { inputId: field.inputId, label, language: field.language, children: /* @__PURE__ */ jsx(
|
|
34
|
+
return /* @__PURE__ */ jsx(PickerFrame, { inputId: field.inputId, label, required, language: field.language, children: /* @__PURE__ */ jsx(
|
|
33
35
|
TimeInputPicker,
|
|
34
36
|
{
|
|
35
37
|
...pickerProps,
|
|
36
|
-
format: field.formats.time,
|
|
37
|
-
ampm: field.formats.ampm,
|
|
38
|
+
format: format ?? pickerProps?.format ?? field.formats.time,
|
|
39
|
+
ampm: pickerProps?.ampm ?? field.formats.ampm,
|
|
38
40
|
value: pickerTimeOf(value),
|
|
39
41
|
minTime: pickerTimeOf(minTime) ?? void 0,
|
|
40
42
|
maxTime: pickerTimeOf(maxTime) ?? void 0,
|
|
@@ -48,7 +50,7 @@ function TimeInputContent(props) {
|
|
|
48
50
|
onBlur?.();
|
|
49
51
|
},
|
|
50
52
|
slotProps: textFieldSlotPropsOf(
|
|
51
|
-
{ id: field.inputId, name, onBlur, error: Boolean(field.errorText), helperText: field.errorText ?? helperText },
|
|
53
|
+
{ id: field.inputId, name, onBlur, required, error: Boolean(field.errorText), helperText: field.errorText ?? helperText },
|
|
52
54
|
pickerProps
|
|
53
55
|
)
|
|
54
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeInput.js","sources":["../../src/datePickers/TimeInput.jsx"],"sourcesContent":["// Campo de HORA suelto con el TimePicker de MUI X (@stackcraftmx/calcita/date-pickers), para una hora del día sin fecha:\n// la hora de una cita en un día ya elegido, el horario de una sucursal, «recordar a las 08:00».\n//\n// Viaja 'HH:mm' de 24 horas aunque en pantalla se vea con a.m. y p.m. (el hourCycle del proveedor decide cómo se ve, no\n// cómo viaja). Una hora del día no tiene zona: no se pasa por Date ni por UTC. '' = vacía.\n//\n// Para un instante (fecha y hora de algo que pasa una vez) va DateTimeInput, que sí viaja en UTC.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaTimeInput con defaultProps, styleOverrides de\n// sus partes (picker) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {TimePicker} from '@mui/x-date-pickers/TimePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {DEFAULT_MINUTES_STEP, pickerTimeOf, timeTextOf} from '@/datePickers/pickerValues.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaTimeInput)\nconst THEME_NAME = 'CalcitaTimeInput';\nconst TimeInputPicker = piecePart(THEME_NAME, 'Picker', TimePicker);\n\n/**\n * @param {object} props\n * @param {string} [props.name]\n * @param {string} props.label ya traducido\n * @param {string|null|undefined} props.value 'HH:mm' o ''\n * @param {(value: string) => void} props.onChange recibe 'HH:mm' ('' al borrar o a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText]\n * @param {string} [props.minTime] 'HH:mm'\n * @param {string} [props.maxTime] 'HH:mm'\n * @param {number} [props.minutesStep] de cuánto en cuánto van los minutos; por omisión de uno en uno (30 para citas de\n * media hora)\n * @param {boolean} [props.disabled]\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef]\n * @param {object} [props.pickerProps] lo demás del TimePicker de MUI X que aquí no tiene nombre (views, shouldDisableTime,\n * slots, slotProps…); value y onChange son del campo\n * @param {Record<string, string|object>} [props.messages] el texto del error de este campo, por regla de validación\n * ({required: 'Elija la fecha', min: 'Desde mañana'}): gana al de Calcita y al de los textos\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction TimeInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText = ' ', minTime, maxTime, minutesStep = DEFAULT_MINUTES_STEP, disabled = false, inputRef,\n pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const field = usePickerField({name, kind: 'time', error, label, messages, texts});\n\n return (\n <PickerFrame inputId={field.inputId} label={label} language={field.language}>\n <TimeInputPicker\n {...pickerProps}\n format={field.formats.time}\n ampm={field.formats.ampm}\n value={pickerTimeOf(value)}\n minTime={pickerTimeOf(minTime) ?? undefined}\n maxTime={pickerTimeOf(maxTime) ?? undefined}\n disabled={disabled}\n minutesStep={minutesStep}\n timeSteps={{minutes: minutesStep, ...pickerProps?.timeSteps}}\n inputRef={inputRef}\n onChange={(pickedValue) => onChange(timeTextOf(pickedValue))}\n onClose={() => {\n pickerProps?.onClose?.();\n onBlur?.();\n }}\n slotProps={textFieldSlotPropsOf(\n {id: field.inputId, name, onBlur, error: Boolean(field.errorText), helperText: field.errorText ?? helperText},\n pickerProps,\n )}\n />\n </PickerFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst TimeInput = withPieceSlots(TimeInputContent, THEME_NAME);\nexport default TimeInput;\n"],"names":[],"mappings":";;;;;;;;AAqBA,MAAM,aAAa;AACnB,MAAM,kBAAkB,UAAU,YAAY,UAAU,UAAU;
|
|
1
|
+
{"version":3,"file":"TimeInput.js","sources":["../../src/datePickers/TimeInput.jsx"],"sourcesContent":["// Campo de HORA suelto con el TimePicker de MUI X (@stackcraftmx/calcita/date-pickers), para una hora del día sin fecha:\n// la hora de una cita en un día ya elegido, el horario de una sucursal, «recordar a las 08:00».\n//\n// Viaja 'HH:mm' de 24 horas aunque en pantalla se vea con a.m. y p.m. (el hourCycle del proveedor decide cómo se ve, no\n// cómo viaja). Una hora del día no tiene zona: no se pasa por Date ni por UTC. '' = vacía.\n//\n// Para un instante (fecha y hora de algo que pasa una vez) va DateTimeInput, que sí viaja en UTC.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaTimeInput con defaultProps, styleOverrides de\n// sus partes (picker) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {TimePicker} from '@mui/x-date-pickers/TimePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {DEFAULT_MINUTES_STEP, pickerTimeOf, timeTextOf} from '@/datePickers/pickerValues.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaTimeInput)\nconst THEME_NAME = 'CalcitaTimeInput';\nconst TimeInputPicker = piecePart(THEME_NAME, 'Picker', TimePicker);\n\n/**\n * @param {object} props\n * @param {string} [props.name]\n * @param {string} props.label ya traducido\n * @param {string|null|undefined} props.value 'HH:mm' o ''\n * @param {(value: string) => void} props.onChange recibe 'HH:mm' ('' al borrar o a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText]\n * @param {string} [props.minTime] 'HH:mm'\n * @param {string} [props.maxTime] 'HH:mm'\n * @param {number} [props.minutesStep] de cuánto en cuánto van los minutos; por omisión de uno en uno (30 para citas de\n * media hora)\n * @param {boolean} [props.disabled]\n * @param {string} [props.format] cómo se ve la hora, con los códigos de dayjs ('hh:mm a' con ampm en pickerProps); por omisión\n * HH:mm o el reloj de ToolkitProvider hourCycle\n * @param {boolean} [props.required] obligatorio: el asterisco en la etiqueta y, como en MUI, required en el campo\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef]\n * @param {object} [props.pickerProps] lo demás del TimePicker de MUI X que aquí no tiene nombre (views, shouldDisableTime,\n * slots, slotProps…); value y onChange son del campo\n * @param {Record<string, string|object>} [props.messages] el texto del error de este campo, por regla de validación\n * ({required: 'Elija la fecha', min: 'Desde mañana'}): gana al de Calcita y al de los textos\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction TimeInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText = ' ', minTime, maxTime, minutesStep = DEFAULT_MINUTES_STEP, disabled = false, required = false, format, inputRef,\n pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const field = usePickerField({name, kind: 'time', error, label, messages, texts});\n\n return (\n <PickerFrame inputId={field.inputId} label={label} required={required} language={field.language}>\n <TimeInputPicker\n {...pickerProps}\n // el formato y el reloj de la pantalla ganan a los de la casa (antes iban después y los pisaban sin avisar)\n format={format ?? pickerProps?.format ?? field.formats.time}\n ampm={pickerProps?.ampm ?? field.formats.ampm}\n value={pickerTimeOf(value)}\n minTime={pickerTimeOf(minTime) ?? undefined}\n maxTime={pickerTimeOf(maxTime) ?? undefined}\n disabled={disabled}\n minutesStep={minutesStep}\n timeSteps={{minutes: minutesStep, ...pickerProps?.timeSteps}}\n inputRef={inputRef}\n onChange={(pickedValue) => onChange(timeTextOf(pickedValue))}\n onClose={() => {\n pickerProps?.onClose?.();\n onBlur?.();\n }}\n slotProps={textFieldSlotPropsOf(\n {id: field.inputId, name, onBlur, required, error: Boolean(field.errorText), helperText: field.errorText ?? helperText},\n pickerProps,\n )}\n />\n </PickerFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst TimeInput = withPieceSlots(TimeInputContent, THEME_NAME);\nexport default TimeInput;\n"],"names":[],"mappings":";;;;;;;;AAqBA,MAAM,aAAa;AACnB,MAAM,kBAAkB,UAAU,YAAY,UAAU,UAAU;AA0BlE,SAAS,iBAAiB,OAAO;AAC7B,QAAM;AAAA,IACF;AAAA,IAAM;AAAA,IAAO;AAAA,IAAO;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAO,aAAa;AAAA,IAAK;AAAA,IAAS;AAAA,IAAS,cAAc;AAAA,IAAsB,WAAW;AAAA,IAAO,WAAW;AAAA,IAAO;AAAA,IAAQ;AAAA,IACjK;AAAA,IAAa;AAAA,IAAU;AAAA,IACvB,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,QAAQ,eAAe,EAAC,MAAM,MAAM,QAAQ,OAAO,OAAO,UAAU,OAAM;AAEhF,SACI,oBAAC,eAAY,SAAS,MAAM,SAAS,OAAc,UAAoB,UAAU,MAAM,UACnF,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MAEJ,QAAQ,UAAU,aAAa,UAAU,MAAM,QAAQ;AAAA,MACvD,MAAM,aAAa,QAAQ,MAAM,QAAQ;AAAA,MACzC,OAAO,aAAa,KAAK;AAAA,MACzB,SAAS,aAAa,OAAO,KAAK;AAAA,MAClC,SAAS,aAAa,OAAO,KAAK;AAAA,MAClC;AAAA,MACA;AAAA,MACA,WAAW,EAAC,SAAS,aAAa,GAAG,aAAa,UAAA;AAAA,MAClD;AAAA,MACA,UAAU,CAAC,gBAAgB,SAAS,WAAW,WAAW,CAAC;AAAA,MAC3D,SAAS,MAAM;AACX,qBAAa,UAAA;AACb,iBAAA;AAAA,MACJ;AAAA,MACA,WAAW;AAAA,QACP,EAAC,IAAI,MAAM,SAAS,MAAM,QAAQ,UAAU,OAAO,QAAQ,MAAM,SAAS,GAAG,YAAY,MAAM,aAAa,WAAA;AAAA,QAC5G;AAAA,MAAA;AAAA,IACJ;AAAA,EAAA,GAER;AAER;AAGA,MAAM,YAAY,eAAe,kBAAkB,UAAU;"}
|
package/dist/feedback/Toaster.js
CHANGED
|
@@ -6,15 +6,24 @@ import { useTheme, useColorScheme } from "@mui/material/styles";
|
|
|
6
6
|
import { isGlassTheme } from "../theme/glassSurface.js";
|
|
7
7
|
import { glassToasterStylesOf } from "../theme/glassToasterStyles.js";
|
|
8
8
|
import { resolvedColorModeOf } from "../ui/navigation/colorMode.js";
|
|
9
|
-
|
|
9
|
+
const TOASTER_POSITION = Object.freeze({
|
|
10
|
+
topLeft: "top-left",
|
|
11
|
+
topCenter: "top-center",
|
|
12
|
+
topRight: "top-right",
|
|
13
|
+
bottomLeft: "bottom-left",
|
|
14
|
+
bottomCenter: "bottom-center",
|
|
15
|
+
bottomRight: "bottom-right"
|
|
16
|
+
});
|
|
17
|
+
function Toaster({ position = TOASTER_POSITION.bottomLeft, richColors = true, closeButton = true, ...sonnerProps }) {
|
|
10
18
|
const theme = useTheme();
|
|
11
19
|
const { mode, systemMode } = useColorScheme();
|
|
12
20
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
13
21
|
isGlassTheme(theme) && /* @__PURE__ */ jsx(GlobalStyles, { styles: glassToasterStylesOf(theme) }),
|
|
14
|
-
/* @__PURE__ */ jsx(Toaster$1, {
|
|
22
|
+
/* @__PURE__ */ jsx(Toaster$1, { theme: resolvedColorModeOf(mode, systemMode), ...sonnerProps, position, richColors, closeButton })
|
|
15
23
|
] });
|
|
16
24
|
}
|
|
17
25
|
export {
|
|
26
|
+
TOASTER_POSITION,
|
|
18
27
|
Toaster as default
|
|
19
28
|
};
|
|
20
29
|
//# sourceMappingURL=Toaster.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.js","sources":["../../src/feedback/Toaster.jsx"],"sourcesContent":["// El <Toaster/> de sonner, montado UNA sola vez en la raíz de la aplicación: dos montados son dos avisos por cada aviso.\n//\n//
|
|
1
|
+
{"version":3,"file":"Toaster.js","sources":["../../src/feedback/Toaster.jsx"],"sourcesContent":["// El <Toaster/> de sonner, montado UNA sola vez en la raíz de la aplicación: dos montados son dos avisos por cada aviso.\n//\n// Por omisión abajo a la izquierda: arriba taparía la barra superior (nombre y \"Salir\"); a la derecha, el panel de detalle\n// (que abre del lado derecho, con su botón de descarga abajo) y la paginación de las tablas de MUI. Pero dónde estorba un\n// aviso depende de cada aplicación (con el pie del menú lateral abajo a la izquierda, ahí tapa): `position` lo cambia con\n// TOASTER_POSITION, y lo demás de sonner (duration, offset, visibleToasts, toastOptions…) pasa tal cual. Sin nada, igual\n// que antes.\n//\n// Sigue el modo claro / oscuro de MUI (va DENTRO del ThemeProvider de la aplicación): sin eso, un aviso blanco sobre la app en\n// oscuro es una linterna. Con el vidrio del tema (createToolkitTheme({glass: true})), los avisos también son de vidrio\n// (glassToasterStyles.js), en cualquier esquina.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {Toaster as SonnerToaster} from 'sonner';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport {useColorScheme, useTheme} from '@mui/material/styles';\n\nimport {isGlassTheme} from '@/theme/glassSurface.js';\nimport {glassToasterStylesOf} from '@/theme/glassToasterStyles.js';\nimport {resolvedColorModeOf} from '@/ui/navigation/colorMode.js';\n\n/** Dónde salen los avisos (los nombres de sonner). */\nexport const TOASTER_POSITION = Object.freeze({\n topLeft: 'top-left',\n topCenter: 'top-center',\n topRight: 'top-right',\n bottomLeft: 'bottom-left',\n bottomCenter: 'bottom-center',\n bottomRight: 'bottom-right',\n});\n\n/**\n * @param {import('sonner').ToasterProps} props lo de sonner, tal cual (https://sonner.emilkowal.ski/toaster: duration,\n * offset, mobileOffset, visibleToasts, toastOptions…). Por omisión: position abajo a la izquierda (uno de\n * TOASTER_POSITION), richColors y closeButton sí, y theme el modo de MUI que se ve en pantalla\n */\nexport default function Toaster({position = TOASTER_POSITION.bottomLeft, richColors = true, closeButton = true, ...sonnerProps}) {\n const theme = useTheme();\n const {mode, systemMode} = useColorScheme();\n return (\n <>\n {isGlassTheme(theme) && <GlobalStyles styles={glassToasterStylesOf(theme)} />}\n <SonnerToaster theme={resolvedColorModeOf(mode, systemMode)} {...sonnerProps} position={position} richColors={richColors} closeButton={closeButton} />\n </>\n );\n}\n"],"names":["SonnerToaster"],"mappings":";;;;;;;;AAsBO,MAAM,mBAAmB,OAAO,OAAO;AAAA,EAC1C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AACjB,CAAC;AAOD,SAAwB,QAAQ,EAAC,WAAW,iBAAiB,YAAY,aAAa,MAAM,cAAc,MAAM,GAAG,eAAc;AAC7H,QAAM,QAAQ,SAAA;AACd,QAAM,EAAC,MAAM,WAAA,IAAc,eAAA;AAC3B,SACI,qBAAA,UAAA,EACK,UAAA;AAAA,IAAA,aAAa,KAAK,KAAK,oBAAC,gBAAa,QAAQ,qBAAqB,KAAK,GAAG;AAAA,IAC3E,oBAACA,WAAA,EAAc,OAAO,oBAAoB,MAAM,UAAU,GAAI,GAAG,aAAa,UAAoB,YAAwB,YAAA,CAA0B;AAAA,EAAA,GACxJ;AAER;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Formik as Formik$1 } from "formik";
|
|
4
|
+
import { FormSchemaProvider } from "./FormSchemaProvider.js";
|
|
5
|
+
function Formik(props) {
|
|
6
|
+
return /* @__PURE__ */ jsx(FormSchemaProvider, { schema: props.validationSchema, children: /* @__PURE__ */ jsx(Formik$1, { ...props }) });
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
Formik as default
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=CalcitaFormik.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CalcitaFormik.js","sources":["../../src/forms/CalcitaFormik.jsx"],"sourcesContent":["// El Formik de formik, tal cual, con una sola cosa más: les enseña a los campos de Calcita el esquema de yup del formulario\n// (FormSchemaProvider), para que con ToolkitProvider requiredFromSchema cada campo obligatorio ponga su asterisco solo.\n// Lo demás (valores, errores, envío, innerRef, children como función) es el de formik sin tocar: los campos encuentran el\n// mismo formulario que con el Formik de 'formik'.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {Formik as FormikBase} from 'formik';\n\nimport {FormSchemaProvider} from '@/forms/FormSchemaProvider.jsx';\n\n/**\n * @template {import('formik').FormikValues} Values\n * @param {import('formik').FormikConfig<Values>} props las de Formik de formik\n * @returns {import('react').JSX.Element}\n */\nexport default function Formik(props) {\n return (\n <FormSchemaProvider schema={props.validationSchema}>\n <FormikBase {...props} />\n </FormSchemaProvider>\n );\n}\n"],"names":["FormikBase"],"mappings":";;;;AAeA,SAAwB,OAAO,OAAO;AAClC,SACI,oBAAC,sBAAmB,QAAQ,MAAM,kBAC9B,UAAA,oBAACA,UAAA,EAAY,GAAG,MAAA,CAAO,EAAA,CAC3B;AAER;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useFormikField } from "./useFormikField.js";
|
|
4
4
|
import AttachmentsInput from "../upload/AttachmentsInput.js";
|
|
5
5
|
function FormAttachmentsField({ name, ...inputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, inputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(AttachmentsInput, { ...inputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormAttachmentsField.js","sources":["../../src/forms/FormAttachmentsField.jsx"],"sourcesContent":["// Campo de varios archivos de formik: AttachmentsInput (upload/) conectado a su campo. Al formulario llega la lista de\n// archivos; subirlos es de la pantalla al guardar (uploadWithProgress con su FormData).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport AttachmentsInput from '@/upload/AttachmentsInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/AttachmentsInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * AttachmentsInput (accept, maxFiles, maxTotalSize, template…), sin value
|
|
1
|
+
{"version":3,"file":"FormAttachmentsField.js","sources":["../../src/forms/FormAttachmentsField.jsx"],"sourcesContent":["// Campo de varios archivos de formik: AttachmentsInput (upload/) conectado a su campo. Al formulario llega la lista de\n// archivos; subirlos es de la pantalla al guardar (uploadWithProgress con su FormData).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport AttachmentsInput from '@/upload/AttachmentsInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/AttachmentsInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/upload/AttachmentsInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * AttachmentsInput (accept, maxFiles, maxTotalSize, template…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormAttachmentsField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <AttachmentsInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,qBAAqB,EAAC,MAAM,GAAG,cAAa;AAChE,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,kBAAA,EAAkB,GAAG,YAAa,GAAG,WAAA,CAAY;AAC7D;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import CatalogInput from "../inputs/CatalogInput.js";
|
|
4
4
|
import { useFormikField } from "./useFormikField.js";
|
|
5
5
|
function FormCatalogField({ name, ...catalogInputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, catalogInputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(CatalogInput, { ...catalogInputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormCatalogField.js","sources":["../../src/forms/FormCatalogField.jsx"],"sourcesContent":["// Campo de catálogo de formik: CatalogInput (inputs/) conectado a su campo. Al formulario llega solo la clave.\n//\n// Genérico del paquete: function (regla de la casa).\nimport CatalogInput from '@/inputs/CatalogInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/CatalogInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de CatalogInput (options, formatLabel, loading…), sin value
|
|
1
|
+
{"version":3,"file":"FormCatalogField.js","sources":["../../src/forms/FormCatalogField.jsx"],"sourcesContent":["// Campo de catálogo de formik: CatalogInput (inputs/) conectado a su campo. Al formulario llega solo la clave.\n//\n// Genérico del paquete: function (regla de la casa).\nimport CatalogInput from '@/inputs/CatalogInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/CatalogInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/CatalogInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de CatalogInput (options, formatLabel, loading…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormCatalogField({name, ...catalogInputProps}) {\n const fieldProps = useFormikField(name, catalogInputProps);\n return <CatalogInput {...catalogInputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AASA,SAAwB,iBAAiB,EAAC,MAAM,GAAG,qBAAoB;AACnE,QAAM,aAAa,eAAe,MAAM,iBAAiB;AACzD,SAAO,oBAAC,cAAA,EAAc,GAAG,mBAAoB,GAAG,WAAA,CAAY;AAChE;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useFormikField } from "./useFormikField.js";
|
|
4
4
|
import CheckboxGroupInput from "../inputs/CheckboxGroupInput.js";
|
|
5
5
|
function FormCheckboxGroupField({ name, ...inputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, inputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(CheckboxGroupInput, { ...inputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormCheckboxGroupField.js","sources":["../../src/forms/FormCheckboxGroupField.jsx"],"sourcesContent":["// El grupo de casillas de formik: CheckboxGroupInput (inputs/) conectado a su campo por name. Al formulario llega la\n// lista de las marcadas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport CheckboxGroupInput from '@/inputs/CheckboxGroupInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/CheckboxGroupInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * CheckboxGroupInput, sin value
|
|
1
|
+
{"version":3,"file":"FormCheckboxGroupField.js","sources":["../../src/forms/FormCheckboxGroupField.jsx"],"sourcesContent":["// El grupo de casillas de formik: CheckboxGroupInput (inputs/) conectado a su campo por name. Al formulario llega la\n// lista de las marcadas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport CheckboxGroupInput from '@/inputs/CheckboxGroupInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/CheckboxGroupInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/CheckboxGroupInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * CheckboxGroupInput, sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormCheckboxGroupField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <CheckboxGroupInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,uBAAuB,EAAC,MAAM,GAAG,cAAa;AAClE,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,oBAAA,EAAoB,GAAG,YAAa,GAAG,WAAA,CAAY;AAC/D;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import ColorInput from "../inputs/ColorInput.js";
|
|
4
4
|
import { useFormikField } from "./useFormikField.js";
|
|
5
5
|
function FormColorField({ name, ...colorInputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, colorInputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(ColorInput, { ...colorInputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormColorField.js","sources":["../../src/forms/FormColorField.jsx"],"sourcesContent":["// Campo de color de formik: ColorInput (inputs/) conectado a su campo. Al formulario llega '#RRGGBB' en mayúsculas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport ColorInput from '@/inputs/ColorInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/ColorInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de ColorInput (checkContrast…), sin value
|
|
1
|
+
{"version":3,"file":"FormColorField.js","sources":["../../src/forms/FormColorField.jsx"],"sourcesContent":["// Campo de color de formik: ColorInput (inputs/) conectado a su campo. Al formulario llega '#RRGGBB' en mayúsculas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport ColorInput from '@/inputs/ColorInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/ColorInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/ColorInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de ColorInput (checkContrast…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormColorField({name, ...colorInputProps}) {\n const fieldProps = useFormikField(name, colorInputProps);\n return <ColorInput {...colorInputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AASA,SAAwB,eAAe,EAAC,MAAM,GAAG,mBAAkB;AAC/D,QAAM,aAAa,eAAe,MAAM,eAAe;AACvD,SAAO,oBAAC,YAAA,EAAY,GAAG,iBAAkB,GAAG,WAAA,CAAY;AAC5D;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useFormikField } from "./useFormikField.js";
|
|
4
4
|
import FileInput from "../upload/FileInput.js";
|
|
5
5
|
function FormFileField({ name, ...inputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, inputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(FileInput, { ...inputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormFileField.js","sources":["../../src/forms/FormFileField.jsx"],"sourcesContent":["// Campo de un archivo de formik: FileInput (upload/) conectado a su campo. Al formulario llega el File (o lo que ya estaba\n// guardado) o null; subirlo es de la pantalla al guardar (uploadWithProgress con su FormData).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport FileInput from '@/upload/FileInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/FileInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * FileInput (accept, maxSize, template…), sin value
|
|
1
|
+
{"version":3,"file":"FormFileField.js","sources":["../../src/forms/FormFileField.jsx"],"sourcesContent":["// Campo de un archivo de formik: FileInput (upload/) conectado a su campo. Al formulario llega el File (o lo que ya estaba\n// guardado) o null; subirlo es de la pantalla al guardar (uploadWithProgress con su FormData).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport FileInput from '@/upload/FileInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/FileInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/upload/FileInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * FileInput (accept, maxSize, template…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormFileField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <FileInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,cAAc,EAAC,MAAM,GAAG,cAAa;AACzD,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,WAAA,EAAW,GAAG,YAAa,GAAG,WAAA,CAAY;AACtD;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useFormikField } from "./useFormikField.js";
|
|
4
4
|
import FileUploadInput from "../upload/FileUploadInput.js";
|
|
5
5
|
function FormFileUploadField({ name, ...inputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, inputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(FileUploadInput, { ...inputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormFileUploadField.js","sources":["../../src/forms/FormFileUploadField.jsx"],"sourcesContent":["// El cargador mini de formik: FileUploadInput (upload/) conectado a su campo. Sube en cuanto se elige y al formulario llega\n// solo el id que dio el servidor ('' mientras sube o si se quita): con Yup.string().required() pide el documento.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport FileUploadInput from '@/upload/FileUploadInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/FileUploadInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * FileUploadInput (upload, accept, maxSize, download…), sin value
|
|
1
|
+
{"version":3,"file":"FormFileUploadField.js","sources":["../../src/forms/FormFileUploadField.jsx"],"sourcesContent":["// El cargador mini de formik: FileUploadInput (upload/) conectado a su campo. Sube en cuanto se elige y al formulario llega\n// solo el id que dio el servidor ('' mientras sube o si se quita): con Yup.string().required() pide el documento.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport FileUploadInput from '@/upload/FileUploadInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/FileUploadInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/upload/FileUploadInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * FileUploadInput (upload, accept, maxSize, download…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormFileUploadField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <FileUploadInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,oBAAoB,EAAC,MAAM,GAAG,cAAa;AAC/D,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,iBAAA,EAAiB,GAAG,YAAa,GAAG,WAAA,CAAY;AAC5D;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useFormikField } from "./useFormikField.js";
|
|
4
4
|
import ImageInput from "../upload/ImageInput.js";
|
|
5
5
|
function FormImageField({ name, ...inputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, inputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(ImageInput, { ...inputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormImageField.js","sources":["../../src/forms/FormImageField.jsx"],"sourcesContent":["// Campo de una imagen de formik: ImageInput (upload/) conectado a su campo. Al formulario llega el File, la dirección de la\n// imagen guardada o null; subirla es de la pantalla al guardar (uploadWithProgress con su FormData).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport ImageInput from '@/upload/ImageInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/ImageInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * ImageInput (shape, size, maxSize…), sin value
|
|
1
|
+
{"version":3,"file":"FormImageField.js","sources":["../../src/forms/FormImageField.jsx"],"sourcesContent":["// Campo de una imagen de formik: ImageInput (upload/) conectado a su campo. Al formulario llega el File, la dirección de la\n// imagen guardada o null; subirla es de la pantalla al guardar (uploadWithProgress con su FormData).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport ImageInput from '@/upload/ImageInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/upload/ImageInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/upload/ImageInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * ImageInput (shape, size, maxSize…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormImageField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <ImageInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,eAAe,EAAC,MAAM,GAAG,cAAa;AAC1D,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,YAAA,EAAY,GAAG,YAAa,GAAG,WAAA,CAAY;AACvD;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useFormikField } from "./useFormikField.js";
|
|
4
4
|
import MaskedInput from "../inputs/MaskedInput.js";
|
|
5
5
|
function FormMaskedField({ name, ...inputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, inputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(MaskedInput, { ...inputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormMaskedField.js","sources":["../../src/forms/FormMaskedField.jsx"],"sourcesContent":["// Campo con máscara de formik: MaskedInput (inputs/) conectado a su campo. Al formulario llega el valor LIMPIO (sin\n// separadores, en mayúsculas): «5551234567», no «555 123 4567».\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport MaskedInput from '@/inputs/MaskedInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/MaskedInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props\n * las de MaskedInput (mask, label, helperText, placeholder…)\n */\nexport default function FormMaskedField({name, ...inputProps}) {\n const fieldProps = useFormikField(name);\n return <MaskedInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,gBAAgB,EAAC,MAAM,GAAG,cAAa;AAC3D,QAAM,aAAa,eAAe,
|
|
1
|
+
{"version":3,"file":"FormMaskedField.js","sources":["../../src/forms/FormMaskedField.jsx"],"sourcesContent":["// Campo con máscara de formik: MaskedInput (inputs/) conectado a su campo. Al formulario llega el valor LIMPIO (sin\n// separadores, en mayúsculas): «5551234567», no «555 123 4567».\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport MaskedInput from '@/inputs/MaskedInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/MaskedInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/MaskedInput.jsx').default>[0], 'onChange'|'onBlur'>>} props\n * las de MaskedInput (mask, label, helperText, placeholder…)\n */\nexport default function FormMaskedField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <MaskedInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,gBAAgB,EAAC,MAAM,GAAG,cAAa;AAC3D,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,aAAA,EAAa,GAAG,YAAa,GAAG,WAAA,CAAY;AACxD;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import NumberInput from "../inputs/NumberInput.js";
|
|
4
4
|
import { useFormikField } from "./useFormikField.js";
|
|
5
5
|
function FormNumberField({ name, ...numberInputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, numberInputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(NumberInput, { ...numberInputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormNumberField.js","sources":["../../src/forms/FormNumberField.jsx"],"sourcesContent":["// Campo de número de formik: NumberInput (inputs/) conectado a su campo. Al formulario llega el texto limpio\n// ('2850000.50'), listo para Money.fromString o para el servidor.\n//\n// Genérico del paquete: function (regla de la casa).\nimport NumberInput from '@/inputs/NumberInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/NumberInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de NumberInput (decimals, prefix, suffix, allowNegative…), sin value
|
|
1
|
+
{"version":3,"file":"FormNumberField.js","sources":["../../src/forms/FormNumberField.jsx"],"sourcesContent":["// Campo de número de formik: NumberInput (inputs/) conectado a su campo. Al formulario llega el texto limpio\n// ('2850000.50'), listo para Money.fromString o para el servidor.\n//\n// Genérico del paquete: function (regla de la casa).\nimport NumberInput from '@/inputs/NumberInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/NumberInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/NumberInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de NumberInput (decimals, prefix, suffix, allowNegative…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormNumberField({name, ...numberInputProps}) {\n const fieldProps = useFormikField(name, numberInputProps);\n return <NumberInput {...numberInputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAUA,SAAwB,gBAAgB,EAAC,MAAM,GAAG,oBAAmB;AACjE,QAAM,aAAa,eAAe,MAAM,gBAAgB;AACxD,SAAO,oBAAC,aAAA,EAAa,GAAG,kBAAmB,GAAG,WAAA,CAAY;AAC9D;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext } from "react";
|
|
4
|
+
const FormSchemaContext = createContext(
|
|
5
|
+
/** @type {unknown} */
|
|
6
|
+
null
|
|
7
|
+
);
|
|
8
|
+
const useFormSchema = () => useContext(FormSchemaContext);
|
|
9
|
+
function FormSchemaProvider({ schema, children }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(FormSchemaContext, { value: schema ?? null, children });
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
FormSchemaContext,
|
|
14
|
+
FormSchemaProvider,
|
|
15
|
+
useFormSchema
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=FormSchemaProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormSchemaProvider.js","sources":["../../src/forms/FormSchemaProvider.jsx"],"sourcesContent":["// El esquema de yup del formulario, a la vista de los campos de Calcita: con él, y ToolkitProvider requiredFromSchema, cada\n// campo de formik sabe si es obligatorio y pone su asterisco (schemaRequired.js).\n//\n// OJO, por qué hace falta: formik NO comparte su validationSchema con los campos (su contexto trae valores, errores y\n// funciones, no el esquema; revisado en formik 2.4.9). El Formik de Calcita (@stackcraftmx/calcita/forms) ya lo pone solo;\n// con el Formik importado directo de 'formik', la pantalla envuelve sus campos:\n//\n// <Formik validationSchema={schema} …>\n// <Form noValidate>\n// <FormSchemaProvider schema={schema}>…los campos…</FormSchemaProvider>\n// </Form>\n// </Formik>\n//\n// Genérico del paquete: function (regla de la casa).\nimport {createContext, useContext} from 'react';\n\n/** El esquema del formulario más cercano (o la función que lo da, como en formik); null sin él. */\nexport const FormSchemaContext = createContext(/** @type {unknown} */ (null));\n\n/** El esquema del formulario más cercano; null sin él. */\nexport const useFormSchema = () => useContext(FormSchemaContext);\n\n/**\n * @param {object} props\n * @param {unknown} props.schema el mismo validationSchema que recibe Formik\n * @param {import('react').ReactNode} props.children los campos\n */\nexport function FormSchemaProvider({schema, children}) {\n return <FormSchemaContext value={schema ?? null}>{children}</FormSchemaContext>;\n}\n"],"names":[],"mappings":";;;AAiBO,MAAM,oBAAoB;AAAA;AAAA,EAAsC;AAAK;AAGrE,MAAM,gBAAgB,MAAM,WAAW,iBAAiB;AAOxD,SAAS,mBAAmB,EAAC,QAAQ,YAAW;AACnD,SAAO,oBAAC,mBAAA,EAAkB,OAAO,UAAU,MAAO,UAAS;AAC/D;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import SelectInput from "../inputs/SelectInput.js";
|
|
4
4
|
import { useFormikField } from "./useFormikField.js";
|
|
5
5
|
function FormSelectField({ name, ...selectInputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, selectInputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(SelectInput, { ...selectInputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormSelectField.js","sources":["../../src/forms/FormSelectField.jsx"],"sourcesContent":["// Lista desplegable de formik: SelectInput (inputs/) conectada a su campo.\n//\n// Genérico del paquete: function (regla de la casa).\nimport SelectInput from '@/inputs/SelectInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/SelectInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de SelectInput, sin value
|
|
1
|
+
{"version":3,"file":"FormSelectField.js","sources":["../../src/forms/FormSelectField.jsx"],"sourcesContent":["// Lista desplegable de formik: SelectInput (inputs/) conectada a su campo.\n//\n// Genérico del paquete: function (regla de la casa).\nimport SelectInput from '@/inputs/SelectInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/SelectInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/SelectInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de SelectInput, sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormSelectField({name, ...selectInputProps}) {\n const fieldProps = useFormikField(name, selectInputProps);\n return <SelectInput {...selectInputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AASA,SAAwB,gBAAgB,EAAC,MAAM,GAAG,oBAAmB;AACjE,QAAM,aAAa,eAAe,MAAM,gBAAgB;AACxD,SAAO,oBAAC,aAAA,EAAa,GAAG,kBAAmB,GAAG,WAAA,CAAY;AAC9D;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import TextInput from "../inputs/TextInput.js";
|
|
4
4
|
import { useFormikField } from "./useFormikField.js";
|
|
5
5
|
function FormTextField({ name, ...textInputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, textInputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(TextInput, { ...textInputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormTextField.js","sources":["../../src/forms/FormTextField.jsx"],"sourcesContent":["// Campo de texto de formik: TextInput (inputs/) conectado a su campo. Lo visual y sus reglas (etiqueta arriba, ojo de las\n// contraseñas, mayúsculas, normalizar al salir, el error en el idioma activo) viven en TextInput.\n//\n// Genérico del paquete: function (regla de la casa).\nimport TextInput from '@/inputs/TextInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/TextInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de TextInput, sin value
|
|
1
|
+
{"version":3,"file":"FormTextField.js","sources":["../../src/forms/FormTextField.jsx"],"sourcesContent":["// Campo de texto de formik: TextInput (inputs/) conectado a su campo. Lo visual y sus reglas (etiqueta arriba, ojo de las\n// contraseñas, mayúsculas, normalizar al salir, el error en el idioma activo) viven en TextInput.\n//\n// Genérico del paquete: function (regla de la casa).\nimport TextInput from '@/inputs/TextInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/TextInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/TextInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de TextInput, sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormTextField({name, ...textInputProps}) {\n const fieldProps = useFormikField(name, textInputProps);\n return <TextInput {...textInputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAUA,SAAwB,cAAc,EAAC,MAAM,GAAG,kBAAiB;AAC7D,QAAM,aAAa,eAAe,MAAM,cAAc;AACtD,SAAO,oBAAC,WAAA,EAAW,GAAG,gBAAiB,GAAG,WAAA,CAAY;AAC1D;"}
|
|
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useFormikField } from "./useFormikField.js";
|
|
4
4
|
import TransferListInput from "../inputs/TransferListInput.js";
|
|
5
5
|
function FormTransferListField({ name, ...inputProps }) {
|
|
6
|
-
const fieldProps = useFormikField(name);
|
|
6
|
+
const fieldProps = useFormikField(name, inputProps);
|
|
7
7
|
return /* @__PURE__ */ jsx(TransferListInput, { ...inputProps, ...fieldProps });
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormTransferListField.js","sources":["../../src/forms/FormTransferListField.jsx"],"sourcesContent":["// La lista de transferencia de formik: TransferListInput (inputs/) conectada a su campo por name. Al formulario llega la\n// lista de los elegidos.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport TransferListInput from '@/inputs/TransferListInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/TransferListInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * TransferListInput, sin value
|
|
1
|
+
{"version":3,"file":"FormTransferListField.js","sources":["../../src/forms/FormTransferListField.jsx"],"sourcesContent":["// La lista de transferencia de formik: TransferListInput (inputs/) conectada a su campo por name. Al formulario llega la\n// lista de los elegidos.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport TransferListInput from '@/inputs/TransferListInput.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/inputs/TransferListInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/inputs/TransferListInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * TransferListInput, sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormTransferListField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <TransferListInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,sBAAsB,EAAC,MAAM,GAAG,cAAa;AACjE,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,mBAAA,EAAmB,GAAG,YAAa,GAAG,WAAA,CAAY;AAC9D;"}
|
package/dist/forms/FormWizard.js
CHANGED
|
@@ -4,17 +4,34 @@ import { useState, useRef, useEffect } from "react";
|
|
|
4
4
|
import { useFormikContext, getIn } from "formik";
|
|
5
5
|
import FormProblemAlert from "./FormProblemAlert.js";
|
|
6
6
|
import SubmitButton from "./SubmitButton.js";
|
|
7
|
+
import { useWizardSteps } from "../inputs/useWizardSteps.js";
|
|
7
8
|
import WizardLayout from "../inputs/WizardLayout.js";
|
|
8
9
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
9
10
|
function firstStepWithErrorOf(steps, errors) {
|
|
10
11
|
return steps.findIndex((step) => (step.fields ?? []).some((field) => getIn(errors, field)));
|
|
11
12
|
}
|
|
12
|
-
function FormWizard({
|
|
13
|
+
function FormWizard({
|
|
14
|
+
steps,
|
|
15
|
+
submitLabel,
|
|
16
|
+
orientation,
|
|
17
|
+
hideBackOnFirstStep,
|
|
18
|
+
initialStepKey,
|
|
19
|
+
stepSelection,
|
|
20
|
+
onStepChange,
|
|
21
|
+
texts,
|
|
22
|
+
...unknownProps
|
|
23
|
+
}) {
|
|
13
24
|
warnUnknownProps("FormWizard", unknownProps);
|
|
14
25
|
const { validateForm, setFieldTouched, setFieldValue, initialValues, errors, isSubmitting } = useFormikContext();
|
|
15
|
-
const [activeIndex, setActiveIndex] = useState(0);
|
|
16
26
|
const [skippedKeys, setSkippedKeys] = useState(() => /* @__PURE__ */ new Set());
|
|
17
27
|
const wasSubmitting = useRef(false);
|
|
28
|
+
const isStepValid = async (index) => {
|
|
29
|
+
const stepFields = steps[index].fields ?? [];
|
|
30
|
+
const formErrors = await validateForm();
|
|
31
|
+
stepFields.forEach((field) => setFieldTouched(field, true, false));
|
|
32
|
+
return !stepFields.some((field) => getIn(formErrors, field));
|
|
33
|
+
};
|
|
34
|
+
const { activeIndex, setActiveIndex, selectStep } = useWizardSteps({ steps, initialStepKey, stepSelection, onStepChange, isStepValid });
|
|
18
35
|
const activeStep = steps[activeIndex];
|
|
19
36
|
useEffect(() => {
|
|
20
37
|
if (wasSubmitting.current && !isSubmitting) {
|
|
@@ -26,10 +43,7 @@ function FormWizard({ steps, submitLabel, texts, ...unknownProps }) {
|
|
|
26
43
|
wasSubmitting.current = isSubmitting;
|
|
27
44
|
}, [isSubmitting, errors, steps]);
|
|
28
45
|
const goNext = async () => {
|
|
29
|
-
|
|
30
|
-
const formErrors = await validateForm();
|
|
31
|
-
stepFields.forEach((field) => setFieldTouched(field, true, false));
|
|
32
|
-
if (stepFields.some((field) => getIn(formErrors, field))) {
|
|
46
|
+
if (!await isStepValid(activeIndex)) {
|
|
33
47
|
return;
|
|
34
48
|
}
|
|
35
49
|
setSkippedKeys((currentKeys) => new Set([...currentKeys].filter((key) => key !== activeStep.key)));
|
|
@@ -50,9 +64,12 @@ function FormWizard({ steps, submitLabel, texts, ...unknownProps }) {
|
|
|
50
64
|
activeIndex,
|
|
51
65
|
skippedKeys,
|
|
52
66
|
isSubmitting,
|
|
67
|
+
orientation,
|
|
68
|
+
hideBackOnFirstStep,
|
|
53
69
|
onBack: () => setActiveIndex((currentIndex) => currentIndex - 1),
|
|
54
70
|
onNext: goNext,
|
|
55
71
|
onSkip: skipStep,
|
|
72
|
+
onStepSelect: selectStep,
|
|
56
73
|
submitButton: /* @__PURE__ */ jsx(SubmitButton, { children: submitLabel }),
|
|
57
74
|
problemAlert: /* @__PURE__ */ jsx(FormProblemAlert, {}),
|
|
58
75
|
texts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormWizard.js","sources":["../../src/forms/FormWizard.jsx"],"sourcesContent":["// Formulario por pasos (wizard) con formik: un solo formulario partido en pasos, con pasos opcionales que se pueden omitir.\n//\n// Cómo se porta, para que la pantalla solo declare sus pasos:\n// - «Siguiente» revisa SOLO los campos del paso (fields) y no avanza si alguno tiene error; los marca como tocados para\n// que se vea por qué;\n// - «Omitir este paso» (solo en los opcionales) regresa sus campos a como empezaron: omitir es no dar ese dato, no dejar\n// lo que se escribió a medias;\n// - el último paso envía TODO el formulario (el esquema de yup completo vale para todos los pasos);\n// - si el envío falla por un campo de un paso anterior (yup o el 422 del servidor con applyServerProblem), el wizard\n// regresa solo a ese paso: un error que no se ve no se puede corregir.\n//\n// Va DENTRO de <Formik> y <Form>:\n// <Formik initialValues={…} validationSchema={…} onSubmit={…}>\n// <Form noValidate>\n// <FormWizard submitLabel=\"Enviar solicitud\" steps={[\n// {key: 'datos', label: 'Sus datos', fields: ['name', 'email'], content: <>…campos…</>},\n// {key: 'aval', label: 'Aval', optional: true, fields: ['guarantor'], content: <>…</>},\n// ]} />\n// </Form>\n// </Formik>\n//\n// Lo que se ve vive en WizardLayout (inputs/), el mismo del FormWizard de react-hook-form. Los textos («Siguiente»,\n// «Anterior»…) se cambian con `texts`: {wizard: {next: 'Continuar'}}.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useRef, useState} from 'react';\nimport {getIn, useFormikContext} from 'formik';\n\nimport FormProblemAlert from '@/forms/FormProblemAlert.jsx';\nimport SubmitButton from '@/forms/SubmitButton.jsx';\nimport WizardLayout from '@/inputs/WizardLayout.jsx';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/**\n * El primer paso que tiene un campo con error; -1 si ninguno.\n *\n * @param {Array<{fields?: string[]}>} steps\n * @param {object} errors los de formik\n * @returns {number}\n */\nfunction firstStepWithErrorOf(steps, errors) {\n return steps.findIndex((step) => (step.fields ?? []).some((field) => getIn(errors, field)));\n}\n\n/**\n * @param {object} props\n * @param {Object[]} props.steps en orden\n * @param {string} props.steps[].key\n * @param {string} props.steps[].label ya traducido\n * @param {string[]} [props.steps[].fields] los campos del paso (los que revisa «Siguiente»)\n * @param {boolean} [props.steps[].optional] se puede omitir\n * @param {import('react').ReactNode} props.steps[].content los campos del paso\n * @param {string} props.submitLabel ya traducido: el botón del último paso\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {wizard: {next, back, skip, optional, skipped, stepOf}}\n */\nexport default function FormWizard({steps, submitLabel, texts, ...unknownProps}) {\n warnUnknownProps('FormWizard', unknownProps);\n const {validateForm, setFieldTouched, setFieldValue, initialValues, errors, isSubmitting} = useFormikContext();\n const [
|
|
1
|
+
{"version":3,"file":"FormWizard.js","sources":["../../src/forms/FormWizard.jsx"],"sourcesContent":["// Formulario por pasos (wizard) con formik: un solo formulario partido en pasos, con pasos opcionales que se pueden omitir.\n//\n// Cómo se porta, para que la pantalla solo declare sus pasos:\n// - «Siguiente» revisa SOLO los campos del paso (fields) y no avanza si alguno tiene error; los marca como tocados para\n// que se vea por qué;\n// - «Omitir este paso» (solo en los opcionales) regresa sus campos a como empezaron: omitir es no dar ese dato, no dejar\n// lo que se escribió a medias;\n// - el último paso envía TODO el formulario (el esquema de yup completo vale para todos los pasos);\n// - si el envío falla por un campo de un paso anterior (yup o el 422 del servidor con applyServerProblem), el wizard\n// regresa solo a ese paso: un error que no se ve no se puede corregir;\n// - para editar un registro (se entra a corregir un dato suelto): initialStepKey abre en el paso que diga el servidor,\n// orientation=\"vertical\" pone los campos dentro de su paso, y stepSelection deja pulsar el título de otro paso para\n// saltar directo (free) o solo si el paso abierto no tiene errores (checked). onStepChange avisa cada cambio de paso.\n//\n// Va DENTRO de <Formik> y <Form>:\n// <Formik initialValues={…} validationSchema={…} onSubmit={…}>\n// <Form noValidate>\n// <FormWizard submitLabel=\"Enviar solicitud\" steps={[\n// {key: 'datos', label: 'Sus datos', fields: ['name', 'email'], content: <>…campos…</>},\n// {key: 'aval', label: 'Aval', optional: true, fields: ['guarantor'], content: <>…</>},\n// ]} />\n// </Form>\n// </Formik>\n//\n// Lo que se ve vive en WizardLayout (inputs/), el mismo del FormWizard de react-hook-form. Los textos («Siguiente»,\n// «Anterior»…) se cambian con `texts`: {wizard: {next: 'Continuar'}}.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useRef, useState} from 'react';\nimport {getIn, useFormikContext} from 'formik';\n\nimport FormProblemAlert from '@/forms/FormProblemAlert.jsx';\nimport SubmitButton from '@/forms/SubmitButton.jsx';\nimport {useWizardSteps} from '@/inputs/useWizardSteps.js';\nimport WizardLayout from '@/inputs/WizardLayout.jsx';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/**\n * El primer paso que tiene un campo con error; -1 si ninguno.\n *\n * @param {Array<{fields?: string[]}>} steps\n * @param {object} errors los de formik\n * @returns {number}\n */\nfunction firstStepWithErrorOf(steps, errors) {\n return steps.findIndex((step) => (step.fields ?? []).some((field) => getIn(errors, field)));\n}\n\n/**\n * @param {object} props\n * @param {Object[]} props.steps en orden\n * @param {string} props.steps[].key\n * @param {string} props.steps[].label ya traducido\n * @param {string[]} [props.steps[].fields] los campos del paso (los que revisa «Siguiente»)\n * @param {boolean} [props.steps[].optional] se puede omitir\n * @param {import('react').ReactNode} props.steps[].content los campos del paso\n * @param {boolean} [props.steps[].completed] lleva la palomita (cuando los títulos se pulsan, solo si la pantalla lo dice)\n * @param {string} props.submitLabel ya traducido: el botón del último paso\n * @param {'horizontal'|'vertical'} [props.orientation] uno de WIZARD_ORIENTATION; por omisión horizontal\n * @param {boolean} [props.hideBackOnFirstStep] en el primer paso no se pinta «Anterior»; por omisión sale apagado, como antes\n * @param {string} [props.initialStepKey] la llave del paso en el que se abre (la que diga el servidor); por omisión el primero\n * @param {'none'|'free'|'checked'} [props.stepSelection] uno de WIZARD_STEP_SELECTION: si el título de otro paso se pulsa y qué\n * revisa antes; por omisión none (se avanza con «Siguiente», como siempre)\n * @param {(stepKey: string, index: number) => void} [props.onStepChange] cada vez que cambia el paso abierto\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {wizard: {next, back, skip, optional, skipped, stepOf}}\n */\nexport default function FormWizard({\n steps, submitLabel, orientation, hideBackOnFirstStep, initialStepKey, stepSelection, onStepChange, texts, ...unknownProps\n}) {\n warnUnknownProps('FormWizard', unknownProps);\n const {validateForm, setFieldTouched, setFieldValue, initialValues, errors, isSubmitting} = useFormikContext();\n const [skippedKeys, setSkippedKeys] = useState(() => new Set());\n const wasSubmitting = useRef(false);\n\n // revisa SOLO los campos de un paso y los marca como tocados para que se vea por qué no avanza\n const isStepValid = async (index) => {\n const stepFields = steps[index].fields ?? [];\n const formErrors = await validateForm();\n stepFields.forEach((field) => setFieldTouched(field, true, false));\n return !stepFields.some((field) => getIn(formErrors, field));\n };\n const {activeIndex, setActiveIndex, selectStep} = useWizardSteps({steps, initialStepKey, stepSelection, onStepChange, isStepValid});\n const activeStep = steps[activeIndex];\n\n // al terminar un envío fallido, regresa al paso con el primer error (solo en ese momento: escribir en otro paso no\n // debe jalar a la persona de regreso)\n useEffect(() => {\n if (wasSubmitting.current && !isSubmitting) {\n const errorStepIndex = firstStepWithErrorOf(steps, errors);\n if (errorStepIndex >= 0) {\n setActiveIndex(errorStepIndex);\n }\n }\n wasSubmitting.current = isSubmitting;\n }, [isSubmitting, errors, steps]);\n\n const goNext = async () => {\n // el paso tiene errores: se queda ahí para que se corrijan\n if (!(await isStepValid(activeIndex))) {\n return;\n }\n setSkippedKeys((currentKeys) => new Set([...currentKeys].filter((key) => key !== activeStep.key)));\n setActiveIndex((currentIndex) => currentIndex + 1);\n };\n\n const skipStep = () => {\n for (const field of activeStep.fields ?? []) {\n setFieldValue(field, getIn(initialValues, field), false);\n setFieldTouched(field, false, false);\n }\n setSkippedKeys((currentKeys) => new Set([...currentKeys, activeStep.key]));\n setActiveIndex((currentIndex) => currentIndex + 1);\n };\n\n return (\n <WizardLayout steps={steps} activeIndex={activeIndex} skippedKeys={skippedKeys} isSubmitting={isSubmitting} orientation={orientation} hideBackOnFirstStep={hideBackOnFirstStep}\n onBack={() => setActiveIndex((currentIndex) => currentIndex - 1)} onNext={goNext} onSkip={skipStep} onStepSelect={selectStep}\n submitButton={<SubmitButton>{submitLabel}</SubmitButton>} problemAlert={<FormProblemAlert />} texts={texts} />\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AA4CA,SAAS,qBAAqB,OAAO,QAAQ;AACzC,SAAO,MAAM,UAAU,CAAC,UAAU,KAAK,UAAU,CAAA,GAAI,KAAK,CAAC,UAAU,MAAM,QAAQ,KAAK,CAAC,CAAC;AAC9F;AAoBA,SAAwB,WAAW;AAAA,EAC/B;AAAA,EAAO;AAAA,EAAa;AAAA,EAAa;AAAA,EAAqB;AAAA,EAAgB;AAAA,EAAe;AAAA,EAAc;AAAA,EAAO,GAAG;AACjH,GAAG;AACC,mBAAiB,cAAc,YAAY;AAC3C,QAAM,EAAC,cAAc,iBAAiB,eAAe,eAAe,QAAQ,aAAA,IAAgB,iBAAA;AAC5F,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,MAAM,oBAAI,KAAK;AAC9D,QAAM,gBAAgB,OAAO,KAAK;AAGlC,QAAM,cAAc,OAAO,UAAU;AACjC,UAAM,aAAa,MAAM,KAAK,EAAE,UAAU,CAAA;AAC1C,UAAM,aAAa,MAAM,aAAA;AACzB,eAAW,QAAQ,CAAC,UAAU,gBAAgB,OAAO,MAAM,KAAK,CAAC;AACjE,WAAO,CAAC,WAAW,KAAK,CAAC,UAAU,MAAM,YAAY,KAAK,CAAC;AAAA,EAC/D;AACA,QAAM,EAAC,aAAa,gBAAgB,WAAA,IAAc,eAAe,EAAC,OAAO,gBAAgB,eAAe,cAAc,YAAA,CAAY;AAClI,QAAM,aAAa,MAAM,WAAW;AAIpC,YAAU,MAAM;AACZ,QAAI,cAAc,WAAW,CAAC,cAAc;AACxC,YAAM,iBAAiB,qBAAqB,OAAO,MAAM;AACzD,UAAI,kBAAkB,GAAG;AACrB,uBAAe,cAAc;AAAA,MACjC;AAAA,IACJ;AACA,kBAAc,UAAU;AAAA,EAC5B,GAAG,CAAC,cAAc,QAAQ,KAAK,CAAC;AAEhC,QAAM,SAAS,YAAY;AAEvB,QAAI,CAAE,MAAM,YAAY,WAAW,GAAI;AACnC;AAAA,IACJ;AACA,mBAAe,CAAC,gBAAgB,IAAI,IAAI,CAAC,GAAG,WAAW,EAAE,OAAO,CAAC,QAAQ,QAAQ,WAAW,GAAG,CAAC,CAAC;AACjG,mBAAe,CAAC,iBAAiB,eAAe,CAAC;AAAA,EACrD;AAEA,QAAM,WAAW,MAAM;AACnB,eAAW,SAAS,WAAW,UAAU,CAAA,GAAI;AACzC,oBAAc,OAAO,MAAM,eAAe,KAAK,GAAG,KAAK;AACvD,sBAAgB,OAAO,OAAO,KAAK;AAAA,IACvC;AACA,mBAAe,CAAC,gBAAgB,oBAAI,IAAI,CAAC,GAAG,aAAa,WAAW,GAAG,CAAC,CAAC;AACzE,mBAAe,CAAC,iBAAiB,eAAe,CAAC;AAAA,EACrD;AAEA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAa;AAAA,MAAc;AAAA,MAA0B;AAAA,MAA0B;AAAA,MAA4B;AAAA,MAA0B;AAAA,MACxH,QAAQ,MAAM,eAAe,CAAC,iBAAiB,eAAe,CAAC;AAAA,MAAG,QAAQ;AAAA,MAAQ,QAAQ;AAAA,MAAU,cAAc;AAAA,MAClH,cAAc,oBAAC,cAAA,EAAc,UAAA,YAAA,CAAY;AAAA,MAAiB,kCAAe,kBAAA,EAAiB;AAAA,MAAI;AAAA,IAAA;AAAA,EAAA;AAEpH;"}
|