@stackcraftmx/calcita 0.52.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.
Files changed (197) hide show
  1. package/README.md +53 -4
  2. package/dist/datePickers/DateInput.js +5 -3
  3. package/dist/datePickers/DateInput.js.map +1 -1
  4. package/dist/datePickers/DateTimeInput.js +6 -4
  5. package/dist/datePickers/DateTimeInput.js.map +1 -1
  6. package/dist/datePickers/FormDateField.js +1 -1
  7. package/dist/datePickers/FormDateField.js.map +1 -1
  8. package/dist/datePickers/FormDateTimeField.js +1 -1
  9. package/dist/datePickers/FormDateTimeField.js.map +1 -1
  10. package/dist/datePickers/FormMonthField.js +1 -1
  11. package/dist/datePickers/FormMonthField.js.map +1 -1
  12. package/dist/datePickers/FormTimeField.js +1 -1
  13. package/dist/datePickers/FormTimeField.js.map +1 -1
  14. package/dist/datePickers/MonthInput.js +5 -3
  15. package/dist/datePickers/MonthInput.js.map +1 -1
  16. package/dist/datePickers/PickerFrame.js +2 -2
  17. package/dist/datePickers/PickerFrame.js.map +1 -1
  18. package/dist/datePickers/TimeInput.js +6 -4
  19. package/dist/datePickers/TimeInput.js.map +1 -1
  20. package/dist/feedback/Toaster.js +11 -2
  21. package/dist/feedback/Toaster.js.map +1 -1
  22. package/dist/forms/CalcitaFormik.js +11 -0
  23. package/dist/forms/CalcitaFormik.js.map +1 -0
  24. package/dist/forms/FormAttachmentsField.js +1 -1
  25. package/dist/forms/FormAttachmentsField.js.map +1 -1
  26. package/dist/forms/FormCatalogField.js +1 -1
  27. package/dist/forms/FormCatalogField.js.map +1 -1
  28. package/dist/forms/FormCheckboxGroupField.js +1 -1
  29. package/dist/forms/FormCheckboxGroupField.js.map +1 -1
  30. package/dist/forms/FormColorField.js +1 -1
  31. package/dist/forms/FormColorField.js.map +1 -1
  32. package/dist/forms/FormFileField.js +1 -1
  33. package/dist/forms/FormFileField.js.map +1 -1
  34. package/dist/forms/FormFileUploadField.js +1 -1
  35. package/dist/forms/FormFileUploadField.js.map +1 -1
  36. package/dist/forms/FormImageField.js +1 -1
  37. package/dist/forms/FormImageField.js.map +1 -1
  38. package/dist/forms/FormMaskedField.js +1 -1
  39. package/dist/forms/FormMaskedField.js.map +1 -1
  40. package/dist/forms/FormNumberField.js +1 -1
  41. package/dist/forms/FormNumberField.js.map +1 -1
  42. package/dist/forms/FormSchemaProvider.js +17 -0
  43. package/dist/forms/FormSchemaProvider.js.map +1 -0
  44. package/dist/forms/FormSelectField.js +1 -1
  45. package/dist/forms/FormSelectField.js.map +1 -1
  46. package/dist/forms/FormTextField.js +1 -1
  47. package/dist/forms/FormTextField.js.map +1 -1
  48. package/dist/forms/FormTransferListField.js +1 -1
  49. package/dist/forms/FormTransferListField.js.map +1 -1
  50. package/dist/forms/FormWizard.js +2 -0
  51. package/dist/forms/FormWizard.js.map +1 -1
  52. package/dist/forms/schemaRequired.js +33 -0
  53. package/dist/forms/schemaRequired.js.map +1 -0
  54. package/dist/forms/useFormikField.js +18 -5
  55. package/dist/forms/useFormikField.js.map +1 -1
  56. package/dist/forms.js +52 -46
  57. package/dist/forms.js.map +1 -1
  58. package/dist/hookForm/FormAttachmentsField.js +1 -1
  59. package/dist/hookForm/FormAttachmentsField.js.map +1 -1
  60. package/dist/hookForm/FormCatalogField.js +1 -1
  61. package/dist/hookForm/FormCatalogField.js.map +1 -1
  62. package/dist/hookForm/FormCheckboxGroupField.js +1 -1
  63. package/dist/hookForm/FormCheckboxGroupField.js.map +1 -1
  64. package/dist/hookForm/FormColorField.js +1 -1
  65. package/dist/hookForm/FormColorField.js.map +1 -1
  66. package/dist/hookForm/FormFileField.js +1 -1
  67. package/dist/hookForm/FormFileField.js.map +1 -1
  68. package/dist/hookForm/FormFileUploadField.js +1 -1
  69. package/dist/hookForm/FormFileUploadField.js.map +1 -1
  70. package/dist/hookForm/FormImageField.js +1 -1
  71. package/dist/hookForm/FormImageField.js.map +1 -1
  72. package/dist/hookForm/FormMaskedField.js +1 -1
  73. package/dist/hookForm/FormMaskedField.js.map +1 -1
  74. package/dist/hookForm/FormNumberField.js +1 -1
  75. package/dist/hookForm/FormNumberField.js.map +1 -1
  76. package/dist/hookForm/FormSelectField.js +1 -1
  77. package/dist/hookForm/FormSelectField.js.map +1 -1
  78. package/dist/hookForm/FormTextField.js +1 -1
  79. package/dist/hookForm/FormTextField.js.map +1 -1
  80. package/dist/hookForm/FormTransferListField.js +1 -1
  81. package/dist/hookForm/FormTransferListField.js.map +1 -1
  82. package/dist/hookForm/FormWizard.js +2 -0
  83. package/dist/hookForm/FormWizard.js.map +1 -1
  84. package/dist/hookForm/useHookFormField.js +9 -3
  85. package/dist/hookForm/useHookFormField.js.map +1 -1
  86. package/dist/index.js +4 -2
  87. package/dist/inputs/CatalogInput.js +3 -2
  88. package/dist/inputs/CatalogInput.js.map +1 -1
  89. package/dist/inputs/CheckboxGroupInput.js +2 -1
  90. package/dist/inputs/CheckboxGroupInput.js.map +1 -1
  91. package/dist/inputs/ColorInput.js +3 -1
  92. package/dist/inputs/ColorInput.js.map +1 -1
  93. package/dist/inputs/FieldFrame.js +18 -3
  94. package/dist/inputs/FieldFrame.js.map +1 -1
  95. package/dist/inputs/FormSection.js +42 -11
  96. package/dist/inputs/FormSection.js.map +1 -1
  97. package/dist/inputs/NumberInput.js +3 -1
  98. package/dist/inputs/NumberInput.js.map +1 -1
  99. package/dist/inputs/SelectInput.js +3 -1
  100. package/dist/inputs/SelectInput.js.map +1 -1
  101. package/dist/inputs/TextInput.js +1 -1
  102. package/dist/inputs/TextInput.js.map +1 -1
  103. package/dist/inputs/TransferListInput.js +2 -1
  104. package/dist/inputs/TransferListInput.js.map +1 -1
  105. package/dist/inputs/WizardLayout.js +12 -6
  106. package/dist/inputs/WizardLayout.js.map +1 -1
  107. package/dist/inputs/formLayoutContext.js +7 -2
  108. package/dist/inputs/formLayoutContext.js.map +1 -1
  109. package/dist/inputs/requiredMark.js +17 -0
  110. package/dist/inputs/requiredMark.js.map +1 -0
  111. package/dist/locales/en.js +1 -0
  112. package/dist/locales/en.js.map +1 -1
  113. package/dist/locales/es.js +1 -0
  114. package/dist/locales/es.js.map +1 -1
  115. package/dist/richText/FormRichTextField.js +1 -1
  116. package/dist/richText/FormRichTextField.js.map +1 -1
  117. package/dist/richText/RichTextEditor.js +4 -3
  118. package/dist/richText/RichTextEditor.js.map +1 -1
  119. package/dist/toolkit/ToolkitProvider.js +3 -0
  120. package/dist/toolkit/ToolkitProvider.js.map +1 -1
  121. package/dist/toolkit/toolkitContext.js.map +1 -1
  122. package/dist/types/datePickers/DateInput.d.ts +2 -0
  123. package/dist/types/datePickers/DateTimeInput.d.ts +2 -0
  124. package/dist/types/datePickers/FormDateField.d.ts +3 -3
  125. package/dist/types/datePickers/FormDateTimeField.d.ts +3 -3
  126. package/dist/types/datePickers/FormMonthField.d.ts +3 -3
  127. package/dist/types/datePickers/FormTimeField.d.ts +3 -3
  128. package/dist/types/datePickers/MonthInput.d.ts +2 -0
  129. package/dist/types/datePickers/PickerFrame.d.ts +3 -1
  130. package/dist/types/datePickers/TimeInput.d.ts +2 -0
  131. package/dist/types/feedback/Toaster.d.ts +15 -1
  132. package/dist/types/feedback/index.d.ts +1 -1
  133. package/dist/types/forms/CalcitaFormik.d.ts +6 -0
  134. package/dist/types/forms/FormAttachmentsField.d.ts +3 -3
  135. package/dist/types/forms/FormCatalogField.d.ts +2 -2
  136. package/dist/types/forms/FormCheckboxGroupField.d.ts +3 -3
  137. package/dist/types/forms/FormColorField.d.ts +2 -2
  138. package/dist/types/forms/FormFileField.d.ts +3 -3
  139. package/dist/types/forms/FormFileUploadField.d.ts +3 -3
  140. package/dist/types/forms/FormImageField.d.ts +3 -3
  141. package/dist/types/forms/FormMaskedField.d.ts +2 -2
  142. package/dist/types/forms/FormNumberField.d.ts +2 -2
  143. package/dist/types/forms/FormSchemaProvider.d.ts +13 -0
  144. package/dist/types/forms/FormSelectField.d.ts +2 -2
  145. package/dist/types/forms/FormTextField.d.ts +2 -2
  146. package/dist/types/forms/FormTransferListField.d.ts +3 -3
  147. package/dist/types/forms/FormWizard.d.ts +3 -1
  148. package/dist/types/forms/index.d.ts +1 -0
  149. package/dist/types/forms/schemaRequired.d.ts +14 -0
  150. package/dist/types/forms/useFormikField.d.ts +10 -4
  151. package/dist/types/forms.d.ts +4 -2
  152. package/dist/types/hookForm/FormAttachmentsField.d.ts +3 -3
  153. package/dist/types/hookForm/FormCatalogField.d.ts +3 -3
  154. package/dist/types/hookForm/FormCheckboxGroupField.d.ts +3 -3
  155. package/dist/types/hookForm/FormColorField.d.ts +3 -3
  156. package/dist/types/hookForm/FormFileField.d.ts +3 -3
  157. package/dist/types/hookForm/FormFileUploadField.d.ts +3 -3
  158. package/dist/types/hookForm/FormImageField.d.ts +3 -3
  159. package/dist/types/hookForm/FormMaskedField.d.ts +3 -3
  160. package/dist/types/hookForm/FormNumberField.d.ts +3 -3
  161. package/dist/types/hookForm/FormSelectField.d.ts +3 -3
  162. package/dist/types/hookForm/FormTextField.d.ts +3 -3
  163. package/dist/types/hookForm/FormTransferListField.d.ts +3 -3
  164. package/dist/types/hookForm/FormWizard.d.ts +3 -1
  165. package/dist/types/hookForm/useHookFormField.d.ts +8 -4
  166. package/dist/types/index.d.ts +2 -2
  167. package/dist/types/inputs/CatalogInput.d.ts +1 -0
  168. package/dist/types/inputs/CheckboxGroupInput.d.ts +1 -0
  169. package/dist/types/inputs/ColorInput.d.ts +1 -0
  170. package/dist/types/inputs/FieldFrame.d.ts +1 -0
  171. package/dist/types/inputs/FormSection.d.ts +13 -0
  172. package/dist/types/inputs/NumberInput.d.ts +1 -0
  173. package/dist/types/inputs/SelectInput.d.ts +1 -0
  174. package/dist/types/inputs/TextInput.d.ts +1 -1
  175. package/dist/types/inputs/TransferListInput.d.ts +1 -0
  176. package/dist/types/inputs/WizardLayout.d.ts +1 -0
  177. package/dist/types/inputs/formLayoutContext.d.ts +8 -1
  178. package/dist/types/inputs/requiredMark.d.ts +9 -0
  179. package/dist/types/locales/en.d.ts +1 -0
  180. package/dist/types/locales/es.d.ts +1 -0
  181. package/dist/types/richText/FormRichTextField.d.ts +3 -3
  182. package/dist/types/richText/RichTextEditor.d.ts +1 -0
  183. package/dist/types/toolkit/ToolkitProvider.d.ts +5 -1
  184. package/dist/types/toolkit/toolkitContext.d.ts +2 -1
  185. package/dist/types/upload/AttachmentsInput.d.ts +2 -0
  186. package/dist/types/upload/FileInput.d.ts +1 -0
  187. package/dist/types/upload/FileUploadInput.d.ts +1 -0
  188. package/dist/types/upload/ImageInput.d.ts +1 -0
  189. package/dist/upload/AttachmentsInput.js +2 -1
  190. package/dist/upload/AttachmentsInput.js.map +1 -1
  191. package/dist/upload/FileInput.js +2 -1
  192. package/dist/upload/FileInput.js.map +1 -1
  193. package/dist/upload/FileUploadInput.js +2 -1
  194. package/dist/upload/FileUploadInput.js.map +1 -1
  195. package/dist/upload/ImageInput.js +2 -1
  196. package/dist/upload/ImageInput.js.map +1 -1
  197. package/package.json +1 -1
package/README.md CHANGED
@@ -69,7 +69,13 @@ pnpm add formik yup # solo si usa /forms o /account
69
69
  ```
70
70
 
71
71
  Con npm es igual, con `npm install` en lugar de `pnpm add`. Desde la 0.25, formik y yup los pone el proyecto: Calcita usa
72
- la versión que ya tenga, no se casa con una.
72
+ la versión que ya tenga, no se casa con una. Cada entrada aparte pide las suyas (la última columna de la tabla de entradas):
73
+ sin ellas, el import truena al buscar el archivo y no dice qué falta. Por ejemplo, para las fechas,
74
+ `pnpm add @mui/x-date-pickers dayjs`.
75
+
76
+ Al subir de versión, apague y vuelva a prender el servidor de Vite (`pnpm dev` o `npm run dev`): Vite revisa lo instalado
77
+ solo al arrancar, y con el servidor prendido sigue con la copia vieja del paquete y el error se busca en el código propio. No
78
+ hace falta borrar `node_modules/.vite`; si de todos modos quiere que lo rehaga, `vite --force`.
73
79
 
74
80
  ```jsx
75
81
  import {ThemeProvider, createTheme} from '@mui/material/styles';
@@ -89,6 +95,10 @@ export const App = () => (
89
95
 
90
96
  Sin nada más, todo sale en español, con la zona horaria del navegador, montos en pesos y la navegación del navegador.
91
97
 
98
+ `<Toaster />` va una sola vez y acepta lo de sonner tal cual (`duration`, `visibleToasts`, `offset`, `toastOptions`…). Por
99
+ omisión los avisos salen abajo a la izquierda; si ahí estorban (el pie del menú lateral), `position` los cambia de esquina:
100
+ `<Toaster position={TOASTER_POSITION.bottomCenter} />`.
101
+
92
102
  ## Lo que se conecta en ToolkitProvider
93
103
 
94
104
  | Prop | Para qué | Por omisión |
@@ -106,6 +116,7 @@ Sin nada más, todo sale en español, con la zona horaria del navegador, montos
106
116
  | `buildId` | la compilación del front que corre en la pestaña, para el aviso de versión nueva | ninguna (sin aviso) |
107
117
  | `fileTypes` | tipos de archivo propios para las descargas (su ícono y su color), además de Excel, CSV y PDF | los de la casa |
108
118
  | `onMissingText` | a quién avisarle de un texto que no existe (la pantalla enseña la llave): mandarlo a Sentry, tronar una prueba | un aviso en la consola, una vez por idioma y llave |
119
+ | `requiredFromSchema` | los campos de formik leen del esquema de yup qué es obligatorio y ponen su asterisco (ver «Lo obligatorio, a la vista») | no |
109
120
  | `readValidationMessage` | cómo leer los mensajes de validación de un sistema que ya existe (ver «Mensajes de error propios») | `{key}`, `{msg}`, `{message}` y texto |
110
121
 
111
122
  Un `ToolkitProvider` dentro de otro (una parte de la app en otro idioma, una vista previa) toma del de afuera lo que no le
@@ -987,8 +998,14 @@ import {Form, Formik, FormNumberField, FormProblemAlert, FormTextField, SubmitBu
987
998
  ```
988
999
 
989
1000
  formik y yup los instala el proyecto (`pnpm add formik yup`); `Formik`, `Form` y `Yup` también se pueden importar de
990
- `@stackcraftmx/calcita/forms`, que es la misma copia. `FormWizard` parte un formulario en pasos, con pasos opcionales (hay
991
- uno para formik y otro para react-hook-form); los ejemplos traen los dos.
1001
+ `@stackcraftmx/calcita/forms`, que es la misma copia (el `Formik` de Calcita es el de formik con el esquema a la vista de los
1002
+ campos, para lo obligatorio). `FormWizard` parte un formulario en pasos, con pasos opcionales (hay uno para formik y otro para
1003
+ react-hook-form); los ejemplos traen los dos. `hideBackOnFirstStep` no pinta «Anterior» en el primer paso (por omisión sale
1004
+ apagado, como antes).
1005
+
1006
+ El `onChange` y el `onBlur` que la pantalla le pase a un campo de formik o de react-hook-form también corren, después de los
1007
+ del formulario y con el valor nuevo: `<FormSelectField name="kind" … onChange={(kind) => loadRatesFor(kind)} />`. Antes los
1008
+ del formulario los pisaban sin avisar.
992
1009
 
993
1010
  Para editar un registro de varios pasos (se entra a corregir un dato suelto, no a recorrer todo), el mismo `FormWizard`:
994
1011
 
@@ -1022,6 +1039,35 @@ import {FormRow, FormSection} from '@stackcraftmx/calcita';
1022
1039
  Los campos van directo dentro de la `FormSection` (sin Grid ni Stack en medio): la línea entre renglones se dibuja entre
1023
1040
  hermanos.
1024
1041
 
1042
+ En el teléfono la etiqueta se lleva el 38 % del renglón y un nombre largo se parte en tres renglones: con
1043
+ `labelPlacement={FORM_LABEL_PLACEMENT.topOnPhone}` la etiqueta sube arriba del campo por debajo de `sm`, y en pantallas más
1044
+ anchas sigue a la izquierda. Por omisión `side`, como antes. Para todos los formularios, una vez en el tema:
1045
+ `components: {CalcitaFormSection: {defaultProps: {labelPlacement: 'topOnPhone'}}}`.
1046
+
1047
+ ### Lo obligatorio, a la vista
1048
+
1049
+ Un campo con `required` lleva un asterisco en su etiqueta, en los 17 campos de la casa (texto, número, listas, catálogo,
1050
+ color, casillas, transferencia, máscara, las cuatro fechas, archivos, imagen, adjuntos y texto con formato). El asterisco va
1051
+ en el estilo de la etiqueta y no como texto: la etiqueta sigue diciendo lo mismo (así la siguen encontrando
1052
+ `getByLabel('Nombre', {exact: true})` y `getByLabelText('Nombre')`) y el lector de pantalla no dice «asterisco»; el campo
1053
+ dice que es obligatorio con `required` (como en MUI) o, donde el navegador no sabe revisarlo, con `aria-required`.
1054
+
1055
+ Con formik, el asterisco puede salir del mismo esquema de yup que revisa el formulario, sin marcar cada campo a mano:
1056
+
1057
+ ```jsx
1058
+ <ToolkitProvider requiredFromSchema> {/* una vez, en la raíz */}
1059
+ ```
1060
+
1061
+ Cuenta lo que yup describe como no opcional (`.required()`, `.defined()`) y una lista con `.min(1)`; las condiciones
1062
+ (`.when`) se resuelven con los valores de ese momento. Lo que la pantalla diga con `required` gana. formik no les comparte el
1063
+ esquema a sus campos: el `Formik` de `@stackcraftmx/calcita/forms` lo hace solo; con el de `'formik'`, envuelva los campos en
1064
+ `<FormSchemaProvider schema={schema}>`. Con react-hook-form el esquema queda dentro del resolver: ahí cada campo lleva su
1065
+ `required`. La regla sin React: `isRequiredInSchema(schema, 'contacts.2.email', values)`.
1066
+
1067
+ Como en MUI, `required` también lo revisa el navegador al enviar si el `<Form>` no lleva `noValidate`: póngaselo para que solo
1068
+ revise yup (en el idioma de la app). El asterisco se cambia desde el tema (`label: {'&[data-required]::after': {…}}` de
1069
+ `CalcitaFieldFrame` y `CalcitaFormRow`) o con el texto `common.form.requiredMark`.
1070
+
1025
1071
  ### Mensajes de error propios (sin tocar el esquema)
1026
1072
 
1027
1073
  Los mensajes de `buildYupLocale()` son llaves que se traducen al pintarse, y cada uno lleva **su regla y su campo**. Cuando
@@ -1079,7 +1125,10 @@ idioma de la persona; la pantalla no convierte nada:
1079
1125
  La fecha con hora se ve en la zona del proyecto (`ToolkitProvider timeZone`) con el nombre de la zona abajo («Hora estándar
1080
1126
  central»), para que nadie dude en qué hora está escribiendo; `timeZone` la cambia en un solo campo (la hora de una
1081
1127
  sucursal) y el momento que viaja es el mismo. La hora sale de 24 horas o con a. m. y p. m. según `ToolkitProvider
1082
- hourCycle`, y viaja igual. Lo que el selector de MUI X acepta y aquí no tiene nombre va en `pickerProps`.
1128
+ hourCycle`, y viaja igual. Lo que el selector de MUI X acepta y aquí no tiene nombre va en `pickerProps`; ahí también
1129
+ `format` y `ampm` ganan a los de la casa. `format` también va directo (`<DateInput format="DD/MMM/YYYY" />` enseña
1130
+ «16/jul/2029»; con el mes en letras no hay dudas entre día y mes) y lo que viaja no cambia. Piden
1131
+ `pnpm add @mui/x-date-pickers dayjs`.
1083
1132
 
1084
1133
  ```jsx
1085
1134
  import {FormDateTimeField, FormMonthField, FormTimeField} from '@stackcraftmx/calcita/date-pickers';
@@ -27,6 +27,8 @@ function DateInputContent(props) {
27
27
  disablePast = false,
28
28
  openTo = "day",
29
29
  disabled = false,
30
+ required = false,
31
+ format,
30
32
  inputRef,
31
33
  pickerProps,
32
34
  messages,
@@ -35,11 +37,11 @@ function DateInputContent(props) {
35
37
  } = usePieceProps(props, THEME_NAME);
36
38
  warnUnknownProps(THEME_NAME, unknownProps);
37
39
  const { language, inputId, errorText, formats } = usePickerField({ name, kind: "date", error, label, messages, texts });
38
- return /* @__PURE__ */ jsx(PickerFrame, { inputId, label, language, children: /* @__PURE__ */ jsx(
40
+ return /* @__PURE__ */ jsx(PickerFrame, { inputId, label, required, language, children: /* @__PURE__ */ jsx(
39
41
  DateInputPicker,
40
42
  {
41
43
  ...pickerProps,
42
- format: formats.date,
44
+ format: format ?? pickerProps?.format ?? formats.date,
43
45
  value: pickerValueOf(value),
44
46
  minDate: pickerValueOf(minDate) ?? void 0,
45
47
  maxDate: pickerValueOf(maxDate) ?? void 0,
@@ -54,7 +56,7 @@ function DateInputContent(props) {
54
56
  pickerProps?.onClose?.();
55
57
  onBlur?.();
56
58
  },
57
- slotProps: textFieldSlotPropsOf({ id: inputId, name, onBlur, error: Boolean(errorText), helperText: errorText ?? helperText }, pickerProps)
59
+ slotProps: textFieldSlotPropsOf({ id: inputId, name, onBlur, required, error: Boolean(errorText), helperText: errorText ?? helperText }, pickerProps)
58
60
  }
59
61
  ) });
60
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DateInput.js","sources":["../../src/datePickers/DateInput.jsx"],"sourcesContent":["// Campo de FECHA suelto con el DatePicker de MUI X (@stackcraftmx/calcita/date-pickers), con la etiqueta arriba como los\n// demás campos del paquete.\n//\n// Al formulario (y al servidor) viaja la fecha de calendario 'AAAA-MM-DD' en texto; en pantalla se ve DD/MM/AAAA en español\n// y MM/DD/AAAA en inglés, con el calendario y sus textos en el idioma activo. '' = sin fecha. Una fecha de calendario no\n// tiene hora ni zona: nunca se pasa por Date (que la movería de día según la zona).\n//\n// Cada campo trae su LocalizationProvider con dayjs (PickerFrame): la pantalla no tiene que poner nada alrededor.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDateInput 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 dayjs from 'dayjs';\nimport {DatePicker} from '@mui/x-date-pickers/DatePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {CALENDAR_DATE_FORMAT} 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.CalcitaDateInput)\nconst THEME_NAME = 'CalcitaDateInput';\nconst DateInputPicker = piecePart(THEME_NAME, 'Picker', DatePicker);\n\nexport {CALENDAR_DATE_FORMAT};\n\n/**\n * Una fecha de calendario 'AAAA-MM-DD' como la quiere el DatePicker; null si está vacía.\n *\n * @param {string|null|undefined} calendarDate\n * @returns {import('dayjs').Dayjs|null}\n */\nfunction pickerValueOf(calendarDate) {\n // dayjs lee 'AAAA-MM-DD' como día local (a diferencia de new Date, que lo toma en UTC y lo mueve de día)\n return calendarDate ? dayjs(calendarDate) : null;\n}\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-DD' o ''\n * @param {(value: string) => void} props.onChange recibe 'AAAA-MM-DD' ('' al borrar o con una fecha 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.minDate] 'AAAA-MM-DD'\n * @param {string} [props.maxDate] 'AAAA-MM-DD'\n * @param {boolean} [props.disableFuture] p. ej. una fecha de nacimiento\n * @param {boolean} [props.disablePast] p. ej. una cita\n * @param {'day'|'month'|'year'} [props.openTo] por dónde abre el calendario (year para un nacimiento)\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 (shouldDisableDate, 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 DateInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText = ' ', minDate, maxDate, disableFuture = false, disablePast = false,\n openTo = 'day', disabled = false, inputRef, pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {language, inputId, errorText, formats} = usePickerField({name, kind: 'date', error, label, messages, texts});\n\n return (\n <PickerFrame inputId={inputId} label={label} language={language}>\n <DateInputPicker\n {...pickerProps}\n format={formats.date}\n value={pickerValueOf(value)}\n minDate={pickerValueOf(minDate) ?? undefined}\n maxDate={pickerValueOf(maxDate) ?? undefined}\n disableFuture={disableFuture}\n disablePast={disablePast}\n disabled={disabled}\n openTo={openTo}\n views={openTo === 'year' ? ['year', 'month', 'day'] : pickerProps?.views}\n inputRef={inputRef}\n // una fecha a medias (25/1_/____) todavía no es fecha: viaja como vacía hasta que se complete\n onChange={(pickedDate) => onChange(pickedDate?.isValid() ? pickedDate.format(CALENDAR_DATE_FORMAT) : '')}\n onClose={() => {\n pickerProps?.onClose?.();\n onBlur?.();\n }}\n slotProps={textFieldSlotPropsOf({id: inputId, name, onBlur, error: Boolean(errorText), helperText: errorText ?? helperText}, pickerProps)}\n />\n </PickerFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst DateInput = withPieceSlots(DateInputContent, THEME_NAME);\nexport default DateInput;\n"],"names":[],"mappings":";;;;;;;;;AAuBA,MAAM,aAAa;AACnB,MAAM,kBAAkB,UAAU,YAAY,UAAU,UAAU;AAUlE,SAAS,cAAc,cAAc;AAEjC,SAAO,eAAe,MAAM,YAAY,IAAI;AAChD;AAwBA,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,gBAAgB;AAAA,IAAO,cAAc;AAAA,IACtH,SAAS;AAAA,IAAO,WAAW;AAAA,IAAO;AAAA,IAAU;AAAA,IAAa;AAAA,IAAU;AAAA,IACnE,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,UAAU,SAAS,WAAW,YAAW,eAAe,EAAC,MAAM,MAAM,QAAQ,OAAO,OAAO,UAAU,OAAM;AAElH,SACI,oBAAC,aAAA,EAAY,SAAkB,OAAc,UACzC,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ,QAAQ,QAAQ;AAAA,MAChB,OAAO,cAAc,KAAK;AAAA,MAC1B,SAAS,cAAc,OAAO,KAAK;AAAA,MACnC,SAAS,cAAc,OAAO,KAAK;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,WAAW,SAAS,CAAC,QAAQ,SAAS,KAAK,IAAI,aAAa;AAAA,MACnE;AAAA,MAEA,UAAU,CAAC,eAAe,SAAS,YAAY,YAAY,WAAW,OAAO,oBAAoB,IAAI,EAAE;AAAA,MACvG,SAAS,MAAM;AACX,qBAAa,UAAA;AACb,iBAAA;AAAA,MACJ;AAAA,MACA,WAAW,qBAAqB,EAAC,IAAI,SAAS,MAAM,QAAQ,OAAO,QAAQ,SAAS,GAAG,YAAY,aAAa,WAAA,GAAa,WAAW;AAAA,IAAA;AAAA,EAAA,GAEhJ;AAER;AAGA,MAAM,YAAY,eAAe,kBAAkB,UAAU;"}
1
+ {"version":3,"file":"DateInput.js","sources":["../../src/datePickers/DateInput.jsx"],"sourcesContent":["// Campo de FECHA suelto con el DatePicker de MUI X (@stackcraftmx/calcita/date-pickers), con la etiqueta arriba como los\n// demás campos del paquete.\n//\n// Al formulario (y al servidor) viaja la fecha de calendario 'AAAA-MM-DD' en texto; en pantalla se ve DD/MM/AAAA en español\n// y MM/DD/AAAA en inglés, con el calendario y sus textos en el idioma activo. '' = sin fecha. Una fecha de calendario no\n// tiene hora ni zona: nunca se pasa por Date (que la movería de día según la zona).\n//\n// Cada campo trae su LocalizationProvider con dayjs (PickerFrame): la pantalla no tiene que poner nada alrededor.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDateInput 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 dayjs from 'dayjs';\nimport {DatePicker} from '@mui/x-date-pickers/DatePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {CALENDAR_DATE_FORMAT} 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.CalcitaDateInput)\nconst THEME_NAME = 'CalcitaDateInput';\nconst DateInputPicker = piecePart(THEME_NAME, 'Picker', DatePicker);\n\nexport {CALENDAR_DATE_FORMAT};\n\n/**\n * Una fecha de calendario 'AAAA-MM-DD' como la quiere el DatePicker; null si está vacía.\n *\n * @param {string|null|undefined} calendarDate\n * @returns {import('dayjs').Dayjs|null}\n */\nfunction pickerValueOf(calendarDate) {\n // dayjs lee 'AAAA-MM-DD' como día local (a diferencia de new Date, que lo toma en UTC y lo mueve de día)\n return calendarDate ? dayjs(calendarDate) : null;\n}\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-DD' o ''\n * @param {(value: string) => void} props.onChange recibe 'AAAA-MM-DD' ('' al borrar o con una fecha 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.minDate] 'AAAA-MM-DD'\n * @param {string} [props.maxDate] 'AAAA-MM-DD'\n * @param {boolean} [props.disableFuture] p. ej. una fecha de nacimiento\n * @param {boolean} [props.disablePast] p. ej. una cita\n * @param {'day'|'month'|'year'} [props.openTo] por dónde abre el calendario (year para un nacimiento)\n * @param {boolean} [props.disabled]\n * @param {string} [props.format] cómo se ve la fecha, con los códigos de dayjs ('DD/MMM/YYYY' enseña «16/jul/2029», sin dudas\n * entre día y mes); por omisión DD/MM/YYYY en español y MM/DD/YYYY en inglés\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 (shouldDisableDate, 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 DateInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText = ' ', minDate, maxDate, disableFuture = false, disablePast = false,\n openTo = 'day', disabled = false, required = false, format, inputRef, pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {language, inputId, errorText, formats} = usePickerField({name, kind: 'date', error, label, messages, texts});\n\n return (\n <PickerFrame inputId={inputId} label={label} required={required} language={language}>\n <DateInputPicker\n {...pickerProps}\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 ?? formats.date}\n value={pickerValueOf(value)}\n minDate={pickerValueOf(minDate) ?? undefined}\n maxDate={pickerValueOf(maxDate) ?? undefined}\n disableFuture={disableFuture}\n disablePast={disablePast}\n disabled={disabled}\n openTo={openTo}\n views={openTo === 'year' ? ['year', 'month', 'day'] : pickerProps?.views}\n inputRef={inputRef}\n // una fecha a medias (25/1_/____) todavía no es fecha: viaja como vacía hasta que se complete\n onChange={(pickedDate) => onChange(pickedDate?.isValid() ? pickedDate.format(CALENDAR_DATE_FORMAT) : '')}\n onClose={() => {\n pickerProps?.onClose?.();\n onBlur?.();\n }}\n slotProps={textFieldSlotPropsOf({id: inputId, name, onBlur, required, error: Boolean(errorText), helperText: errorText ?? helperText}, pickerProps)}\n />\n </PickerFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst DateInput = withPieceSlots(DateInputContent, THEME_NAME);\nexport default DateInput;\n"],"names":[],"mappings":";;;;;;;;;AAuBA,MAAM,aAAa;AACnB,MAAM,kBAAkB,UAAU,YAAY,UAAU,UAAU;AAUlE,SAAS,cAAc,cAAc;AAEjC,SAAO,eAAe,MAAM,YAAY,IAAI;AAChD;AA2BA,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,gBAAgB;AAAA,IAAO,cAAc;AAAA,IACtH,SAAS;AAAA,IAAO,WAAW;AAAA,IAAO,WAAW;AAAA,IAAO;AAAA,IAAQ;AAAA,IAAU;AAAA,IAAa;AAAA,IAAU;AAAA,IAC7F,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,UAAU,SAAS,WAAW,YAAW,eAAe,EAAC,MAAM,MAAM,QAAQ,OAAO,OAAO,UAAU,OAAM;AAElH,SACI,oBAAC,aAAA,EAAY,SAAkB,OAAc,UAAoB,UAC7D,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MAEJ,QAAQ,UAAU,aAAa,UAAU,QAAQ;AAAA,MACjD,OAAO,cAAc,KAAK;AAAA,MAC1B,SAAS,cAAc,OAAO,KAAK;AAAA,MACnC,SAAS,cAAc,OAAO,KAAK;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,WAAW,SAAS,CAAC,QAAQ,SAAS,KAAK,IAAI,aAAa;AAAA,MACnE;AAAA,MAEA,UAAU,CAAC,eAAe,SAAS,YAAY,YAAY,WAAW,OAAO,oBAAoB,IAAI,EAAE;AAAA,MACvG,SAAS,MAAM;AACX,qBAAa,UAAA;AACb,iBAAA;AAAA,MACJ;AAAA,MACA,WAAW,qBAAqB,EAAC,IAAI,SAAS,MAAM,QAAQ,UAAU,OAAO,QAAQ,SAAS,GAAG,YAAY,aAAa,WAAA,GAAa,WAAW;AAAA,IAAA;AAAA,EAAA,GAE1J;AAER;AAGA,MAAM,YAAY,eAAe,kBAAkB,UAAU;"}
@@ -31,6 +31,8 @@ function DateTimeInputContent(props) {
31
31
  showTimeZone = true,
32
32
  timeZoneLabel,
33
33
  disabled = false,
34
+ required = false,
35
+ format,
34
36
  inputRef,
35
37
  pickerProps,
36
38
  messages,
@@ -46,13 +48,13 @@ function DateTimeInputContent(props) {
46
48
  const hasClockRule = minimumMinutesFromNow != null;
47
49
  const currentMinute = useCurrentMinute(hasClockRule);
48
50
  const earliest = latestInstantOf(minDateTime, hasClockRule ? earliestInstantFromNow(minimumMinutesFromNow, currentMinute) : "");
49
- return /* @__PURE__ */ jsx(PickerFrame, { inputId: field.inputId, label, language: field.language, children: /* @__PURE__ */ jsx(
51
+ return /* @__PURE__ */ jsx(PickerFrame, { inputId: field.inputId, label, required, language: field.language, children: /* @__PURE__ */ jsx(
50
52
  DateTimeInputPicker,
51
53
  {
52
54
  ...pickerProps,
53
55
  timezone: shownTimeZone,
54
- format: field.formats.dateTime,
55
- ampm: field.formats.ampm,
56
+ format: format ?? pickerProps?.format ?? field.formats.dateTime,
57
+ ampm: pickerProps?.ampm ?? field.formats.ampm,
56
58
  value: pickerInstantOf(value, shownTimeZone),
57
59
  minDateTime: pickerInstantOf(earliest, shownTimeZone) ?? void 0,
58
60
  maxDateTime: pickerInstantOf(maxDateTime, shownTimeZone) ?? void 0,
@@ -68,7 +70,7 @@ function DateTimeInputContent(props) {
68
70
  onBlur?.();
69
71
  },
70
72
  slotProps: textFieldSlotPropsOf(
71
- { id: field.inputId, name, onBlur, error: Boolean(field.errorText), helperText: field.errorText ?? helperLine },
73
+ { id: field.inputId, name, onBlur, required, error: Boolean(field.errorText), helperText: field.errorText ?? helperLine },
72
74
  pickerProps
73
75
  )
74
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimeInput.js","sources":["../../src/datePickers/DateTimeInput.jsx"],"sourcesContent":["// Campo de FECHA CON HORA suelto con el DateTimePicker de MUI X (@stackcraftmx/calcita/date-pickers), para un instante:\n// una cita, un envío programado, «posponer hasta».\n//\n// Viaja como instante en UTC ('2026-11-01T18:30:00Z') y se pinta en la zona del proveedor (ToolkitProvider timeZone),\n// rotulada abajo con su nombre («Hora estándar central»): quien lo ve sabe en qué hora está escribiendo aunque su equipo\n// esté en otra zona. Lee también lo que llega del servidor con desfase ('…-06:00'). '' = vacío. La hora sale de 24 horas o\n// con a.m. y p.m. según el hourCycle del proveedor.\n//\n// Los minutos van de uno en uno (minutesStep los cambia). Para «al menos N minutos después de ahora» (publicar con\n// anticipación) está minimumMinutesFromNow: el mínimo se recorre solo con el reloj mientras la pantalla está abierta. Para\n// «el fin, al menos N minutos después del inicio», minDateTime={instantPlusMinutes(startsAt, N)}. Con formik, las mismas\n// reglas en yup: minutesFromNowRule y minutesAfterRule (el servidor vuelve a revisar).\n//\n// Para una hora del día sin fecha («abre a las 09:00») va TimeInput; para una fecha sin hora, DateInput.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDateTimeInput 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 {DateTimePicker} from '@mui/x-date-pickers/DateTimePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {\n DEFAULT_MINUTES_STEP, earliestInstantFromNow, instantTextOf, latestInstantOf, pickerInstantOf, timeZoneNameOf,\n} from '@/datePickers/pickerValues.js';\nimport {useCurrentMinute} from '@/datePickers/useCurrentMinute.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {intlLocaleOf} from '@/toolkit/toolkitSettings.js';\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.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.CalcitaDateTimeInput)\nconst THEME_NAME = 'CalcitaDateTimeInput';\nconst DateTimeInputPicker = piecePart(THEME_NAME, 'Picker', DateTimePicker);\n\n// entre la ayuda de la pantalla y el nombre de la zona\nconst HELPER_SEPARATOR = ' · ';\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 el instante ('2026-11-01T18:30:00Z' o con desfase) o ''\n * @param {(value: string) => void} props.onChange recibe el instante en UTC ('' al borrar o a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText] ya traducida; va antes del nombre de la zona\n * @param {string} [props.minDateTime] instante (el fin de algo: instantPlusMinutes(startsAt, 30))\n * @param {number} [props.minimumMinutesFromNow] al menos tantos minutos después de ahora; se recorre con el reloj\n * @param {string} [props.maxDateTime] instante\n * @param {boolean} [props.disableFuture]\n * @param {boolean} [props.disablePast] p. ej. un envío programado\n * @param {number} [props.minutesStep] de cuánto en cuánto van los minutos; por omisión de uno en uno (15 para citas de\n * cuarto de hora)\n * @param {string} [props.timeZone] otra zona que la del proveedor (la de una sucursal); rotulada igual\n * @param {boolean} [props.showTimeZone] false quita el nombre de la zona de abajo (por omisión se ve)\n * @param {string} [props.timeZoneLabel] ya traducido, en lugar del nombre que da el navegador\n * @param {boolean} [props.disabled]\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef]\n * @param {object} [props.pickerProps] lo demás del DateTimePicker de MUI X que aquí no tiene nombre (views, shouldDisableDate,\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 DateTimeInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText, minDateTime, minimumMinutesFromNow, maxDateTime, disableFuture = false,\n disablePast = false, minutesStep = DEFAULT_MINUTES_STEP, timeZone, showTimeZone = true, timeZoneLabel, disabled = false, inputRef, pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const field = usePickerField({name, kind: 'dateTime', error, label, messages, texts});\n const {languages} = useToolkitSettings();\n const shownTimeZone = timeZone ?? field.timeZone;\n const zoneText = showTimeZone ? (timeZoneLabel ?? timeZoneNameOf(shownTimeZone, intlLocaleOf(field.language, languages))) : null;\n const helperLine = [helperText, zoneText].filter(Boolean).join(HELPER_SEPARATOR) || ' ';\n // el mínimo que de verdad aplica: el que da la pantalla o el de «ahora + N minutos», el más tarde\n const hasClockRule = minimumMinutesFromNow != null;\n const currentMinute = useCurrentMinute(hasClockRule);\n const earliest = latestInstantOf(minDateTime, hasClockRule ? earliestInstantFromNow(minimumMinutesFromNow, currentMinute) : '');\n\n return (\n <PickerFrame inputId={field.inputId} label={label} language={field.language}>\n <DateTimeInputPicker\n {...pickerProps}\n timezone={shownTimeZone}\n format={field.formats.dateTime}\n ampm={field.formats.ampm}\n value={pickerInstantOf(value, shownTimeZone)}\n minDateTime={pickerInstantOf(earliest, shownTimeZone) ?? undefined}\n maxDateTime={pickerInstantOf(maxDateTime, shownTimeZone) ?? undefined}\n disableFuture={disableFuture}\n disablePast={disablePast}\n disabled={disabled}\n minutesStep={minutesStep}\n timeSteps={{minutes: minutesStep, ...pickerProps?.timeSteps}}\n inputRef={inputRef}\n onChange={(pickedValue) => onChange(instantTextOf(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 ?? helperLine},\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 DateTimeInput = withPieceSlots(DateTimeInputContent, THEME_NAME);\nexport default DateTimeInput;\n"],"names":[],"mappings":";;;;;;;;;;;AAiCA,MAAM,aAAa;AACnB,MAAM,sBAAsB,UAAU,YAAY,UAAU,cAAc;AAG1E,MAAM,mBAAmB;AA6BzB,SAAS,qBAAqB,OAAO;AACjC,QAAM;AAAA,IACF;AAAA,IAAM;AAAA,IAAO;AAAA,IAAO;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAO;AAAA,IAAY;AAAA,IAAa;AAAA,IAAuB;AAAA,IAAa,gBAAgB;AAAA,IAC1H,cAAc;AAAA,IAAO,cAAc;AAAA,IAAsB;AAAA,IAAU,eAAe;AAAA,IAAM;AAAA,IAAe,WAAW;AAAA,IAAO;AAAA,IAAU;AAAA,IAAa;AAAA,IAAU;AAAA,IAC1J,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,QAAQ,eAAe,EAAC,MAAM,MAAM,YAAY,OAAO,OAAO,UAAU,OAAM;AACpF,QAAM,EAAC,UAAA,IAAa,mBAAA;AACpB,QAAM,gBAAgB,YAAY,MAAM;AACxC,QAAM,WAAW,eAAgB,iBAAiB,eAAe,eAAe,aAAa,MAAM,UAAU,SAAS,CAAC,IAAK;AAC5H,QAAM,aAAa,CAAC,YAAY,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,gBAAgB,KAAK;AAEpF,QAAM,eAAe,yBAAyB;AAC9C,QAAM,gBAAgB,iBAAiB,YAAY;AACnD,QAAM,WAAW,gBAAgB,aAAa,eAAe,uBAAuB,uBAAuB,aAAa,IAAI,EAAE;AAE9H,SACI,oBAAC,eAAY,SAAS,MAAM,SAAS,OAAc,UAAU,MAAM,UAC/D,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ,UAAU;AAAA,MACV,QAAQ,MAAM,QAAQ;AAAA,MACtB,MAAM,MAAM,QAAQ;AAAA,MACpB,OAAO,gBAAgB,OAAO,aAAa;AAAA,MAC3C,aAAa,gBAAgB,UAAU,aAAa,KAAK;AAAA,MACzD,aAAa,gBAAgB,aAAa,aAAa,KAAK;AAAA,MAC5D;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,EAAC,SAAS,aAAa,GAAG,aAAa,UAAA;AAAA,MAClD;AAAA,MACA,UAAU,CAAC,gBAAgB,SAAS,cAAc,WAAW,CAAC;AAAA,MAC9D,SAAS,MAAM;AACX,qBAAa,UAAA;AACb,iBAAA;AAAA,MACJ;AAAA,MACA,WAAW;AAAA,QACP,EAAC,IAAI,MAAM,SAAS,MAAM,QAAQ,OAAO,QAAQ,MAAM,SAAS,GAAG,YAAY,MAAM,aAAa,WAAA;AAAA,QAClG;AAAA,MAAA;AAAA,IACJ;AAAA,EAAA,GAER;AAER;AAGA,MAAM,gBAAgB,eAAe,sBAAsB,UAAU;"}
1
+ {"version":3,"file":"DateTimeInput.js","sources":["../../src/datePickers/DateTimeInput.jsx"],"sourcesContent":["// Campo de FECHA CON HORA suelto con el DateTimePicker de MUI X (@stackcraftmx/calcita/date-pickers), para un instante:\n// una cita, un envío programado, «posponer hasta».\n//\n// Viaja como instante en UTC ('2026-11-01T18:30:00Z') y se pinta en la zona del proveedor (ToolkitProvider timeZone),\n// rotulada abajo con su nombre («Hora estándar central»): quien lo ve sabe en qué hora está escribiendo aunque su equipo\n// esté en otra zona. Lee también lo que llega del servidor con desfase ('…-06:00'). '' = vacío. La hora sale de 24 horas o\n// con a.m. y p.m. según el hourCycle del proveedor.\n//\n// Los minutos van de uno en uno (minutesStep los cambia). Para «al menos N minutos después de ahora» (publicar con\n// anticipación) está minimumMinutesFromNow: el mínimo se recorre solo con el reloj mientras la pantalla está abierta. Para\n// «el fin, al menos N minutos después del inicio», minDateTime={instantPlusMinutes(startsAt, N)}. Con formik, las mismas\n// reglas en yup: minutesFromNowRule y minutesAfterRule (el servidor vuelve a revisar).\n//\n// Para una hora del día sin fecha («abre a las 09:00») va TimeInput; para una fecha sin hora, DateInput.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDateTimeInput 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 {DateTimePicker} from '@mui/x-date-pickers/DateTimePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {\n DEFAULT_MINUTES_STEP, earliestInstantFromNow, instantTextOf, latestInstantOf, pickerInstantOf, timeZoneNameOf,\n} from '@/datePickers/pickerValues.js';\nimport {useCurrentMinute} from '@/datePickers/useCurrentMinute.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {intlLocaleOf} from '@/toolkit/toolkitSettings.js';\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.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.CalcitaDateTimeInput)\nconst THEME_NAME = 'CalcitaDateTimeInput';\nconst DateTimeInputPicker = piecePart(THEME_NAME, 'Picker', DateTimePicker);\n\n// entre la ayuda de la pantalla y el nombre de la zona\nconst HELPER_SEPARATOR = ' · ';\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 el instante ('2026-11-01T18:30:00Z' o con desfase) o ''\n * @param {(value: string) => void} props.onChange recibe el instante en UTC ('' al borrar o a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText] ya traducida; va antes del nombre de la zona\n * @param {string} [props.minDateTime] instante (el fin de algo: instantPlusMinutes(startsAt, 30))\n * @param {number} [props.minimumMinutesFromNow] al menos tantos minutos después de ahora; se recorre con el reloj\n * @param {string} [props.maxDateTime] instante\n * @param {boolean} [props.disableFuture]\n * @param {boolean} [props.disablePast] p. ej. un envío programado\n * @param {number} [props.minutesStep] de cuánto en cuánto van los minutos; por omisión de uno en uno (15 para citas de\n * cuarto de hora)\n * @param {string} [props.timeZone] otra zona que la del proveedor (la de una sucursal); rotulada igual\n * @param {boolean} [props.showTimeZone] false quita el nombre de la zona de abajo (por omisión se ve)\n * @param {string} [props.timeZoneLabel] ya traducido, en lugar del nombre que da el navegador\n * @param {boolean} [props.disabled]\n * @param {string} [props.format] cómo se ven la fecha y la hora, con los códigos de dayjs ('DD/MMM/YYYY HH:mm'); por omisión\n * DD/MM/YYYY HH:mm en español y 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 DateTimePicker de MUI X que aquí no tiene nombre (views, shouldDisableDate,\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 DateTimeInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText, minDateTime, minimumMinutesFromNow, maxDateTime, disableFuture = false,\n disablePast = false, minutesStep = DEFAULT_MINUTES_STEP, timeZone, showTimeZone = true, timeZoneLabel, 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: 'dateTime', error, label, messages, texts});\n const {languages} = useToolkitSettings();\n const shownTimeZone = timeZone ?? field.timeZone;\n const zoneText = showTimeZone ? (timeZoneLabel ?? timeZoneNameOf(shownTimeZone, intlLocaleOf(field.language, languages))) : null;\n const helperLine = [helperText, zoneText].filter(Boolean).join(HELPER_SEPARATOR) || ' ';\n // el mínimo que de verdad aplica: el que da la pantalla o el de «ahora + N minutos», el más tarde\n const hasClockRule = minimumMinutesFromNow != null;\n const currentMinute = useCurrentMinute(hasClockRule);\n const earliest = latestInstantOf(minDateTime, hasClockRule ? earliestInstantFromNow(minimumMinutesFromNow, currentMinute) : '');\n\n return (\n <PickerFrame inputId={field.inputId} label={label} required={required} language={field.language}>\n <DateTimeInputPicker\n {...pickerProps}\n timezone={shownTimeZone}\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.dateTime}\n ampm={pickerProps?.ampm ?? field.formats.ampm}\n value={pickerInstantOf(value, shownTimeZone)}\n minDateTime={pickerInstantOf(earliest, shownTimeZone) ?? undefined}\n maxDateTime={pickerInstantOf(maxDateTime, shownTimeZone) ?? undefined}\n disableFuture={disableFuture}\n disablePast={disablePast}\n disabled={disabled}\n minutesStep={minutesStep}\n timeSteps={{minutes: minutesStep, ...pickerProps?.timeSteps}}\n inputRef={inputRef}\n onChange={(pickedValue) => onChange(instantTextOf(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 ?? helperLine},\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 DateTimeInput = withPieceSlots(DateTimeInputContent, THEME_NAME);\nexport default DateTimeInput;\n"],"names":[],"mappings":";;;;;;;;;;;AAiCA,MAAM,aAAa;AACnB,MAAM,sBAAsB,UAAU,YAAY,UAAU,cAAc;AAG1E,MAAM,mBAAmB;AAgCzB,SAAS,qBAAqB,OAAO;AACjC,QAAM;AAAA,IACF;AAAA,IAAM;AAAA,IAAO;AAAA,IAAO;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAO;AAAA,IAAY;AAAA,IAAa;AAAA,IAAuB;AAAA,IAAa,gBAAgB;AAAA,IAC1H,cAAc;AAAA,IAAO,cAAc;AAAA,IAAsB;AAAA,IAAU,eAAe;AAAA,IAAM;AAAA,IAAe,WAAW;AAAA,IAAO,WAAW;AAAA,IAAO;AAAA,IAAQ;AAAA,IAAU;AAAA,IAAa;AAAA,IAAU;AAAA,IACpL,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,QAAQ,eAAe,EAAC,MAAM,MAAM,YAAY,OAAO,OAAO,UAAU,OAAM;AACpF,QAAM,EAAC,UAAA,IAAa,mBAAA;AACpB,QAAM,gBAAgB,YAAY,MAAM;AACxC,QAAM,WAAW,eAAgB,iBAAiB,eAAe,eAAe,aAAa,MAAM,UAAU,SAAS,CAAC,IAAK;AAC5H,QAAM,aAAa,CAAC,YAAY,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,gBAAgB,KAAK;AAEpF,QAAM,eAAe,yBAAyB;AAC9C,QAAM,gBAAgB,iBAAiB,YAAY;AACnD,QAAM,WAAW,gBAAgB,aAAa,eAAe,uBAAuB,uBAAuB,aAAa,IAAI,EAAE;AAE9H,SACI,oBAAC,eAAY,SAAS,MAAM,SAAS,OAAc,UAAoB,UAAU,MAAM,UACnF,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ,UAAU;AAAA,MAEV,QAAQ,UAAU,aAAa,UAAU,MAAM,QAAQ;AAAA,MACvD,MAAM,aAAa,QAAQ,MAAM,QAAQ;AAAA,MACzC,OAAO,gBAAgB,OAAO,aAAa;AAAA,MAC3C,aAAa,gBAAgB,UAAU,aAAa,KAAK;AAAA,MACzD,aAAa,gBAAgB,aAAa,aAAa,KAAK;AAAA,MAC5D;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,EAAC,SAAS,aAAa,GAAG,aAAa,UAAA;AAAA,MAClD;AAAA,MACA,UAAU,CAAC,gBAAgB,SAAS,cAAc,WAAW,CAAC;AAAA,MAC9D,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,gBAAgB,eAAe,sBAAsB,UAAU;"}
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
3
3
  import DateInput from "./DateInput.js";
4
4
  import { useFormikField } from "../forms/useFormikField.js";
5
5
  function FormDateField({ name, ...dateInputProps }) {
6
- const fieldProps = useFormikField(name);
6
+ const fieldProps = useFormikField(name, dateInputProps);
7
7
  return /* @__PURE__ */ jsx(DateInput, { ...dateInputProps, ...fieldProps });
8
8
  }
9
9
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"FormDateField.js","sources":["../../src/datePickers/FormDateField.jsx"],"sourcesContent":["// Campo de fecha de formik: DateInput conectado a su campo. Al formulario llega 'AAAA-MM-DD'.\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): DateInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport DateInput from '@/datePickers/DateInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/DateInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * DateInput (minDate, maxDate, disableFuture, openTo…), sin value / onChange / onBlur / error\n */\nexport default function FormDateField({name, ...dateInputProps}) {\n const fieldProps = useFormikField(name);\n return <DateInput {...dateInputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAYA,SAAwB,cAAc,EAAC,MAAM,GAAG,kBAAiB;AAC7D,QAAM,aAAa,eAAe,IAAI;AACtC,SAAO,oBAAC,WAAA,EAAW,GAAG,gBAAiB,GAAG,WAAA,CAAY;AAC1D;"}
1
+ {"version":3,"file":"FormDateField.js","sources":["../../src/datePickers/FormDateField.jsx"],"sourcesContent":["// Campo de fecha de formik: DateInput conectado a su campo. Al formulario llega 'AAAA-MM-DD'.\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): DateInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport DateInput from '@/datePickers/DateInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/DateInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/datePickers/DateInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * DateInput (minDate, maxDate, disableFuture, openTo…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormDateField({name, ...dateInputProps}) {\n const fieldProps = useFormikField(name, dateInputProps);\n return <DateInput {...dateInputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAYA,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 DateTimeInput from "./DateTimeInput.js";
4
4
  import { useFormikField } from "../forms/useFormikField.js";
5
5
  function FormDateTimeField({ name, ...inputProps }) {
6
- const fieldProps = useFormikField(name);
6
+ const fieldProps = useFormikField(name, inputProps);
7
7
  return /* @__PURE__ */ jsx(DateTimeInput, { ...inputProps, ...fieldProps });
8
8
  }
9
9
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"FormDateTimeField.js","sources":["../../src/datePickers/FormDateTimeField.jsx"],"sourcesContent":["// Campo de fecha con hora de formik: DateTimeInput conectado a su campo. Al formulario llega el instante en\n// UTC ('2026-11-01T18:30:00Z').\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): DateTimeInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport DateTimeInput from '@/datePickers/DateTimeInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/DateTimeInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * DateTimeInput (minDateTime, minimumMinutesFromNow, disablePast, minutesStep, timeZone…), sin value / onChange / onBlur / error\n */\nexport default function FormDateTimeField({name, ...inputProps}) {\n const fieldProps = useFormikField(name);\n return <DateTimeInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAaA,SAAwB,kBAAkB,EAAC,MAAM,GAAG,cAAa;AAC7D,QAAM,aAAa,eAAe,IAAI;AACtC,SAAO,oBAAC,eAAA,EAAe,GAAG,YAAa,GAAG,WAAA,CAAY;AAC1D;"}
1
+ {"version":3,"file":"FormDateTimeField.js","sources":["../../src/datePickers/FormDateTimeField.jsx"],"sourcesContent":["// Campo de fecha con hora de formik: DateTimeInput conectado a su campo. Al formulario llega el instante en\n// UTC ('2026-11-01T18:30:00Z').\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): DateTimeInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport DateTimeInput from '@/datePickers/DateTimeInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/DateTimeInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/datePickers/DateTimeInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * DateTimeInput (minDateTime, minimumMinutesFromNow, disablePast, minutesStep, timeZone…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormDateTimeField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <DateTimeInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAaA,SAAwB,kBAAkB,EAAC,MAAM,GAAG,cAAa;AAC7D,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,eAAA,EAAe,GAAG,YAAa,GAAG,WAAA,CAAY;AAC1D;"}
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
3
3
  import MonthInput from "./MonthInput.js";
4
4
  import { useFormikField } from "../forms/useFormikField.js";
5
5
  function FormMonthField({ name, ...inputProps }) {
6
- const fieldProps = useFormikField(name);
6
+ const fieldProps = useFormikField(name, inputProps);
7
7
  return /* @__PURE__ */ jsx(MonthInput, { ...inputProps, ...fieldProps });
8
8
  }
9
9
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"FormMonthField.js","sources":["../../src/datePickers/FormMonthField.jsx"],"sourcesContent":["// Campo de mes de formik: MonthInput conectado a su campo. Al formulario llega 'AAAA-MM'.\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): MonthInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport MonthInput from '@/datePickers/MonthInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/MonthInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * MonthInput (minMonth, maxMonth, disableFuture…), sin value / onChange / onBlur / error\n */\nexport default function FormMonthField({name, ...inputProps}) {\n const fieldProps = useFormikField(name);\n return <MonthInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAYA,SAAwB,eAAe,EAAC,MAAM,GAAG,cAAa;AAC1D,QAAM,aAAa,eAAe,IAAI;AACtC,SAAO,oBAAC,YAAA,EAAY,GAAG,YAAa,GAAG,WAAA,CAAY;AACvD;"}
1
+ {"version":3,"file":"FormMonthField.js","sources":["../../src/datePickers/FormMonthField.jsx"],"sourcesContent":["// Campo de mes de formik: MonthInput conectado a su campo. Al formulario llega 'AAAA-MM'.\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): MonthInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport MonthInput from '@/datePickers/MonthInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/MonthInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/datePickers/MonthInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * MonthInput (minMonth, maxMonth, disableFuture…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormMonthField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <MonthInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAYA,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 TimeInput from "./TimeInput.js";
4
4
  import { useFormikField } from "../forms/useFormikField.js";
5
5
  function FormTimeField({ name, ...inputProps }) {
6
- const fieldProps = useFormikField(name);
6
+ const fieldProps = useFormikField(name, inputProps);
7
7
  return /* @__PURE__ */ jsx(TimeInput, { ...inputProps, ...fieldProps });
8
8
  }
9
9
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"FormTimeField.js","sources":["../../src/datePickers/FormTimeField.jsx"],"sourcesContent":["// Campo de hora de formik: TimeInput conectado a su campo. Al formulario llega 'HH:mm'.\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): TimeInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport TimeInput from '@/datePickers/TimeInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/TimeInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * TimeInput (minTime, maxTime, minutesStep…), sin value / onChange / onBlur / error\n */\nexport default function FormTimeField({name, ...inputProps}) {\n const fieldProps = useFormikField(name);\n return <TimeInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAYA,SAAwB,cAAc,EAAC,MAAM,GAAG,cAAa;AACzD,QAAM,aAAa,eAAe,IAAI;AACtC,SAAO,oBAAC,WAAA,EAAW,GAAG,YAAa,GAAG,WAAA,CAAY;AACtD;"}
1
+ {"version":3,"file":"FormTimeField.js","sources":["../../src/datePickers/FormTimeField.jsx"],"sourcesContent":["// Campo de hora de formik: TimeInput conectado a su campo. Al formulario llega 'HH:mm'.\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): TimeInput va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport TimeInput from '@/datePickers/TimeInput.jsx';\nimport {useFormikField} from '@/forms/useFormikField.js';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/datePickers/TimeInput.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'> & Partial<Pick<Parameters<typeof import('@/datePickers/TimeInput.jsx').default>[0], 'onChange'|'onBlur'>>} props las de\n * TimeInput (minTime, maxTime, minutesStep…), sin value ni error (su onChange y su onBlur corren después de los del formulario)\n */\nexport default function FormTimeField({name, ...inputProps}) {\n const fieldProps = useFormikField(name, inputProps);\n return <TimeInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAYA,SAAwB,cAAc,EAAC,MAAM,GAAG,cAAa;AACzD,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,SAAO,oBAAC,WAAA,EAAW,GAAG,YAAa,GAAG,WAAA,CAAY;AACtD;"}
@@ -23,6 +23,8 @@ function MonthInputContent(props) {
23
23
  disableFuture = false,
24
24
  disablePast = false,
25
25
  disabled = false,
26
+ required = false,
27
+ format,
26
28
  inputRef,
27
29
  pickerProps,
28
30
  messages,
@@ -31,13 +33,13 @@ function MonthInputContent(props) {
31
33
  } = usePieceProps(props, THEME_NAME);
32
34
  warnUnknownProps(THEME_NAME, unknownProps);
33
35
  const field = usePickerField({ name, kind: "month", error, label, messages, texts });
34
- return /* @__PURE__ */ jsx(PickerFrame, { inputId: field.inputId, label, language: field.language, children: /* @__PURE__ */ jsx(
36
+ return /* @__PURE__ */ jsx(PickerFrame, { inputId: field.inputId, label, required, language: field.language, children: /* @__PURE__ */ jsx(
35
37
  MonthInputPicker,
36
38
  {
37
39
  ...pickerProps,
38
40
  views: MONTH_VIEWS,
39
41
  openTo: "month",
40
- format: field.formats.month,
42
+ format: format ?? pickerProps?.format ?? field.formats.month,
41
43
  value: pickerMonthOf(value),
42
44
  minDate: pickerMonthOf(minMonth) ?? void 0,
43
45
  maxDate: pickerMonthOf(maxMonth) ?? void 0,
@@ -51,7 +53,7 @@ function MonthInputContent(props) {
51
53
  onBlur?.();
52
54
  },
53
55
  slotProps: textFieldSlotPropsOf(
54
- { id: field.inputId, name, onBlur, error: Boolean(field.errorText), helperText: field.errorText ?? helperText },
56
+ { id: field.inputId, name, onBlur, required, error: Boolean(field.errorText), helperText: field.errorText ?? helperText },
55
57
  pickerProps
56
58
  )
57
59
  }
@@ -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;AAuBpC,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;AAAA,IAAU;AAAA,IAAa;AAAA,IAAU;AAAA,IACnD,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,UAAU,MAAM,UAC/D,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ,OAAO;AAAA,MACP,QAAO;AAAA,MACP,QAAQ,MAAM,QAAQ;AAAA,MACtB,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,OAAO,QAAQ,MAAM,SAAS,GAAG,YAAY,MAAM,aAAa,WAAA;AAAA,QAClG;AAAA,MAAA;AAAA,IACJ;AAAA,EAAA,GAER;AAER;AAGA,MAAM,aAAa,eAAe,mBAAmB,UAAU;"}
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;AASA,SAAwB,YAAY,EAAC,SAAS,OAAO,UAAU,YAAW;AACtE,QAAM,UAAU,oBAAoB,QAAQ,KAAK,oBAAoB;AAErE,SACI,oBAAC,YAAA,EAAW,SAAkB,OAC1B,8BAAC,sBAAA,EAAqB,aAAa,cAAc,eAAe,QAAQ,eAAe,YAAY,QAAQ,YACtG,UACL,GACJ;AAER;"}
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;AAuBlE,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;AAAA,IACvI;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,UAAU,MAAM,UAC/D,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ,QAAQ,MAAM,QAAQ;AAAA,MACtB,MAAM,MAAM,QAAQ;AAAA,MACpB,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,OAAO,QAAQ,MAAM,SAAS,GAAG,YAAY,MAAM,aAAa,WAAA;AAAA,QAClG;AAAA,MAAA;AAAA,IACJ;AAAA,EAAA,GAER;AAER;AAGA,MAAM,YAAY,eAAe,kBAAkB,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;"}
@@ -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
- function Toaster() {
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, { position: "bottom-left", richColors: true, closeButton: true, theme: resolvedColorModeOf(mode, systemMode) })
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// Abajo a la izquierda: arriba taparía la barra superior (nombre y \"Salir\"); a la derecha, el panel de detalle (que\n// abre del lado derecho, con su botón de descarga abajo) y la paginación de las tablas de MUI.\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).\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\nexport default function Toaster() {\n const theme = useTheme();\n const {mode, systemMode} = useColorScheme();\n return (\n <>\n {isGlassTheme(theme) && <GlobalStyles styles={glassToasterStylesOf(theme)} />}\n <SonnerToaster position=\"bottom-left\" richColors closeButton theme={resolvedColorModeOf(mode, systemMode)} />\n </>\n );\n}\n"],"names":["SonnerToaster"],"mappings":";;;;;;;;AAkBA,SAAwB,UAAU;AAC9B,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,UAAS,eAAc,YAAU,MAAC,aAAW,MAAC,OAAO,oBAAoB,MAAM,UAAU,EAAA,CAAG;AAAA,EAAA,GAC/G;AAER;"}
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 / onChange / onBlur / error\n */\nexport default function FormAttachmentsField({name, ...inputProps}) {\n const fieldProps = useFormikField(name);\n return <AttachmentsInput {...inputProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAWA,SAAwB,qBAAqB,EAAC,MAAM,GAAG,cAAa;AAChE,QAAM,aAAa,eAAe,IAAI;AACtC,SAAO,oBAAC,kBAAA,EAAkB,GAAG,YAAa,GAAG,WAAA,CAAY;AAC7D;"}
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 {