@tinya-code/gas-admin-ui 0.2.0-alpha.13 → 0.2.0-alpha.15

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 (368) hide show
  1. package/ng-package.json +7 -0
  2. package/package.json +3 -15
  3. package/src/lib/actions/action-registry.spec.ts +52 -0
  4. package/src/lib/actions/action-registry.ts +126 -0
  5. package/src/lib/actions/action-service.spec.ts +215 -0
  6. package/src/lib/actions/action-service.ts +87 -0
  7. package/src/lib/actions/descriptors.spec.ts +155 -0
  8. package/src/lib/actions/descriptors.ts +154 -0
  9. package/src/lib/columns/column-cell.ts +33 -0
  10. package/src/lib/columns/column-defaults.spec.ts +99 -0
  11. package/src/lib/columns/column-defaults.ts +84 -0
  12. package/src/lib/columns/column-format.spec.ts +274 -0
  13. package/src/lib/columns/descriptors.ts +113 -0
  14. package/src/lib/columns/format-badge.ts +51 -0
  15. package/src/lib/columns/format-boolean.ts +58 -0
  16. package/src/lib/columns/format-currency.ts +30 -0
  17. package/src/lib/columns/format-date.ts +35 -0
  18. package/src/lib/columns/format-number.ts +32 -0
  19. package/src/lib/columns/format-text.ts +23 -0
  20. package/src/lib/columns/format-thumbnail.ts +63 -0
  21. package/src/lib/core/adapters/firebase-auth.adapter.ts +6 -0
  22. package/src/lib/core/guards/auth.guard.spec.ts +88 -0
  23. package/src/lib/core/guards/auth.guard.ts +48 -0
  24. package/src/lib/core/guards/unsaved-changes.guard.ts +16 -0
  25. package/src/lib/core/interceptors/api-error.interceptor.spec.ts +182 -0
  26. package/src/lib/core/interceptors/api-error.interceptor.ts +87 -0
  27. package/src/lib/core/models/api.model.ts +104 -0
  28. package/src/lib/core/models/schema-descriptions.ts +118 -0
  29. package/src/lib/core/models/schema.model.ts +1097 -0
  30. package/src/lib/core/registry/composition-validator.spec.ts +358 -0
  31. package/src/lib/core/registry/composition-validator.ts +270 -0
  32. package/src/lib/core/registry/field-validators.spec.ts +199 -0
  33. package/src/lib/core/registry/field-validators.ts +440 -0
  34. package/src/lib/core/registry/render-host.spec.ts +208 -0
  35. package/src/lib/core/registry/render-host.ts +646 -0
  36. package/src/lib/core/registry/render-registry.spec.ts +96 -0
  37. package/src/lib/core/registry/render-registry.ts +312 -0
  38. package/src/lib/core/registry/schema-catalog.ts +156 -0
  39. package/src/lib/core/services/api.service.spec.ts +1142 -0
  40. package/src/lib/core/services/api.service.ts +371 -0
  41. package/src/lib/core/services/auth.service.spec.ts +653 -0
  42. package/src/lib/core/services/auth.service.ts +503 -0
  43. package/src/lib/core/services/config.service.spec.ts +121 -0
  44. package/src/lib/core/services/config.service.ts +119 -0
  45. package/src/lib/core/services/data-source.service.spec.ts +179 -0
  46. package/src/lib/core/services/data-source.service.ts +142 -0
  47. package/src/lib/core/services/error-mapper.service.spec.ts +50 -0
  48. package/src/lib/core/services/error-mapper.service.ts +49 -0
  49. package/src/lib/core/services/notification.service.ts +73 -0
  50. package/src/lib/core/services/relation-drawer.service.ts +41 -0
  51. package/src/lib/core/services/theme.service.spec.ts +106 -0
  52. package/src/lib/core/services/theme.service.ts +86 -0
  53. package/src/lib/core/services/transport.spec.ts +198 -0
  54. package/src/lib/core/services/transport.ts +164 -0
  55. package/src/lib/core/services/upload.service.ts +81 -0
  56. package/src/lib/core/testing/categories.schema.ts +125 -0
  57. package/src/lib/core/testing/orders.schema.ts +372 -0
  58. package/src/lib/core/testing/products.schema.ts +258 -0
  59. package/src/lib/core/testing/site.schema.ts +195 -0
  60. package/src/lib/core/testing/test-catalog.ts +21 -0
  61. package/src/lib/core/tokens.ts +112 -0
  62. package/src/lib/core/utils/clipboard.spec.ts +55 -0
  63. package/src/lib/core/utils/clipboard.ts +90 -0
  64. package/src/lib/core/utils/context-resolver.spec.ts +95 -0
  65. package/src/lib/core/utils/context-resolver.ts +101 -0
  66. package/src/lib/core/utils/response-unwrapper.spec.ts +70 -0
  67. package/src/lib/core/utils/response-unwrapper.ts +103 -0
  68. package/src/lib/core/utils/source-options.spec.ts +96 -0
  69. package/src/lib/core/utils/source-options.ts +54 -0
  70. package/src/lib/core/utils/template-interpolator.spec.ts +59 -0
  71. package/src/lib/core/utils/template-interpolator.ts +56 -0
  72. package/src/lib/core/view-navigation/view-navigation.service.spec.ts +207 -0
  73. package/src/lib/core/view-navigation/view-navigation.service.ts +132 -0
  74. package/src/lib/fields/boolean/boolean.descriptor.ts +11 -0
  75. package/src/lib/fields/boolean/boolean.ts +40 -0
  76. package/src/lib/fields/color/color.descriptor.ts +12 -0
  77. package/src/lib/fields/color/color.ts +34 -0
  78. package/src/lib/fields/currency/currency.descriptor.ts +12 -0
  79. package/src/lib/fields/currency/currency.ts +67 -0
  80. package/src/lib/fields/date/date.descriptor.ts +12 -0
  81. package/src/lib/fields/date/date.ts +36 -0
  82. package/src/lib/fields/descriptors.ts +122 -0
  83. package/src/lib/fields/display/display-badge.ts +65 -0
  84. package/src/lib/fields/display/display-date.ts +39 -0
  85. package/src/lib/fields/display/display-defaults.ts +84 -0
  86. package/src/lib/fields/display/display-file.ts +41 -0
  87. package/src/lib/fields/display/display-image.ts +54 -0
  88. package/src/lib/fields/display/display-list.ts +107 -0
  89. package/src/lib/fields/display/display-number.ts +41 -0
  90. package/src/lib/fields/display/display-text.ts +42 -0
  91. package/src/lib/fields/display/display.spec.ts +242 -0
  92. package/src/lib/fields/dropdown/dropdown.descriptor.ts +12 -0
  93. package/src/lib/fields/dropdown/dropdown.ts +45 -0
  94. package/src/lib/fields/email/email.descriptor.ts +12 -0
  95. package/src/lib/fields/email/email.ts +28 -0
  96. package/src/lib/fields/field-aria.ts +60 -0
  97. package/src/lib/fields/field-host/field-host.spec.ts +118 -0
  98. package/src/lib/fields/field-host/field-host.ts +47 -0
  99. package/src/lib/fields/field-node.ts +88 -0
  100. package/src/lib/fields/file/file.descriptor.ts +14 -0
  101. package/src/lib/fields/file/file.spec.ts +134 -0
  102. package/src/lib/fields/file/file.ts +281 -0
  103. package/src/lib/fields/group/group.descriptor.ts +21 -0
  104. package/src/lib/fields/group/group.ts +110 -0
  105. package/src/lib/fields/image/image.descriptor.ts +12 -0
  106. package/src/lib/fields/image/image.spec.ts +117 -0
  107. package/src/lib/fields/image/image.ts +281 -0
  108. package/src/lib/fields/key-value/key-value.descriptor.ts +11 -0
  109. package/src/lib/fields/key-value/key-value.ts +283 -0
  110. package/src/lib/fields/list/list.descriptor.ts +21 -0
  111. package/src/lib/fields/list/list.ts +376 -0
  112. package/src/lib/fields/multiselect/multiselect.descriptor.ts +11 -0
  113. package/src/lib/fields/multiselect/multiselect.spec.ts +142 -0
  114. package/src/lib/fields/multiselect/multiselect.ts +152 -0
  115. package/src/lib/fields/number/number.descriptor.ts +12 -0
  116. package/src/lib/fields/number/number.ts +40 -0
  117. package/src/lib/fields/phone/phone.descriptor.ts +12 -0
  118. package/src/lib/fields/phone/phone.ts +46 -0
  119. package/src/lib/fields/readonly-text/readonly-text.descriptor.ts +12 -0
  120. package/src/lib/fields/readonly-text/readonly-text.ts +58 -0
  121. package/src/lib/fields/relation/relation.descriptor.ts +12 -0
  122. package/src/lib/fields/relation/relation.spec.ts +193 -0
  123. package/src/lib/fields/relation/relation.ts +224 -0
  124. package/src/lib/fields/rich-select/rich-select.descriptor.ts +12 -0
  125. package/src/lib/fields/rich-select/rich-select.ts +175 -0
  126. package/src/lib/fields/select/radio-mode.ts +25 -0
  127. package/src/lib/fields/select/select.descriptor.ts +12 -0
  128. package/src/lib/fields/select/select.spec.ts +162 -0
  129. package/src/lib/fields/select/select.ts +210 -0
  130. package/src/lib/fields/slug/slug.descriptor.ts +19 -0
  131. package/src/lib/fields/slug/slug.ts +67 -0
  132. package/src/lib/fields/string-list/string-list.descriptor.ts +11 -0
  133. package/src/lib/fields/string-list/string-list.ts +222 -0
  134. package/src/lib/fields/text/text.descriptor.ts +12 -0
  135. package/src/lib/fields/text/text.ts +35 -0
  136. package/src/lib/fields/textarea/textarea.descriptor.ts +12 -0
  137. package/src/lib/fields/textarea/textarea.spec.ts +117 -0
  138. package/src/lib/fields/textarea/textarea.ts +126 -0
  139. package/src/lib/fields/time/time.descriptor.ts +12 -0
  140. package/src/lib/fields/time/time.ts +28 -0
  141. package/src/lib/fields/unknown-render/unknown-render.ts +49 -0
  142. package/src/lib/fields/url/url.descriptor.ts +12 -0
  143. package/src/lib/fields/url/url.ts +53 -0
  144. package/src/lib/gas-admin-ui.spec.ts +21 -0
  145. package/src/lib/gas-admin-ui.ts +9 -0
  146. package/src/lib/layouts/descriptors.ts +9 -0
  147. package/src/lib/pages/dashboard/dashboard.ts +167 -0
  148. package/src/lib/pages/detail-view/detail-view.spec.ts +333 -0
  149. package/src/lib/pages/detail-view/detail-view.ts +570 -0
  150. package/src/lib/pages/drawer-form/drawer-form.ts +228 -0
  151. package/src/lib/pages/form-view/form-model.ts +88 -0
  152. package/src/lib/pages/form-view/form-schema.ts +255 -0
  153. package/src/lib/pages/form-view/form-view.ts +1622 -0
  154. package/src/lib/pages/list-view/list-view.formats.spec.ts +214 -0
  155. package/src/lib/pages/list-view/list-view.ts +882 -0
  156. package/src/lib/pages/login/login.spec.ts +109 -0
  157. package/src/lib/pages/login/login.ts +227 -0
  158. package/src/lib/pages/resource-page/resource-page.ts +234 -0
  159. package/src/lib/shared/components/badge/badge.ts +35 -0
  160. package/src/lib/shared/components/button/button.ts +65 -0
  161. package/src/lib/shared/components/confirm-dialog/confirm-dialog.ts +48 -0
  162. package/src/lib/shared/components/copy-button/copy-button.ts +56 -0
  163. package/src/lib/shared/components/copy-share/copy-share.spec.ts +122 -0
  164. package/src/lib/shared/components/copy-share/copy-share.ts +107 -0
  165. package/src/lib/shared/components/drawer/drawer.spec.ts +127 -0
  166. package/src/lib/shared/components/drawer/drawer.ts +172 -0
  167. package/src/lib/shared/components/empty-state/empty-state.ts +30 -0
  168. package/src/lib/shared/components/modal/modal.spec.ts +149 -0
  169. package/src/lib/shared/components/modal/modal.ts +145 -0
  170. package/src/lib/shared/components/post-create-modal/post-create-modal.spec.ts +165 -0
  171. package/src/lib/shared/components/post-create-modal/post-create-modal.ts +159 -0
  172. package/src/lib/shared/components/skeleton/skeleton.ts +31 -0
  173. package/src/lib/shared/components/toast/toast.ts +58 -0
  174. package/src/lib/shared/utils/col-span.ts +25 -0
  175. package/src/lib/shared/utils/condition-evaluator.ts +53 -0
  176. package/src/lib/shared/utils/depends-on.ts +48 -0
  177. package/src/lib/shared/utils/dialog-focus.ts +28 -0
  178. package/src/lib/shared/utils/field-path.ts +49 -0
  179. package/src/lib/shared/utils/gap-sorting.ts +144 -0
  180. package/src/lib/shared/utils/seed.spec.ts +64 -0
  181. package/src/lib/shared/utils/seed.ts +149 -0
  182. package/src/lib/shared/utils/slugify.ts +13 -0
  183. package/src/lib/shared/utils/validators.ts +41 -0
  184. package/src/lib/shell/layout/layout.ts +63 -0
  185. package/src/lib/shell/shell.routes.spec.ts +59 -0
  186. package/src/lib/shell/shell.routes.ts +122 -0
  187. package/src/lib/shell/sidebar/sidebar.ts +139 -0
  188. package/src/lib/shell/theme-toggle/theme-toggle.ts +74 -0
  189. package/src/lib/views/calendar-view/calendar-model.ts +426 -0
  190. package/src/lib/views/calendar-view/calendar-view.spec.ts +557 -0
  191. package/src/lib/views/calendar-view/calendar-view.ts +568 -0
  192. package/src/lib/views/composer/composer-host.spec.ts +301 -0
  193. package/src/lib/views/composer/composer-host.ts +248 -0
  194. package/src/lib/views/composer/composer-imports.spec.ts +54 -0
  195. package/src/lib/views/composer/view-context.spec.ts +117 -0
  196. package/src/lib/views/composer/view-context.ts +109 -0
  197. package/src/lib/views/composer/view-slot.spec.ts +130 -0
  198. package/src/lib/views/composer/view-slot.ts +178 -0
  199. package/src/lib/views/descriptors.ts +46 -0
  200. package/src/lib/views/kanban-view/kanban-model.ts +173 -0
  201. package/src/lib/views/kanban-view/kanban-view.spec.ts +540 -0
  202. package/src/lib/views/kanban-view/kanban-view.ts +327 -0
  203. package/src/lib/widgets/bar-chart/bar-chart.descriptor.ts +17 -0
  204. package/src/lib/widgets/bar-chart/bar-chart.spec.ts +66 -0
  205. package/src/lib/widgets/bar-chart/bar-chart.ts +76 -0
  206. package/src/lib/widgets/chart-line/chart-line.descriptor.ts +17 -0
  207. package/src/lib/widgets/chart-line/chart-line.spec.ts +113 -0
  208. package/src/lib/widgets/chart-line/chart-line.ts +219 -0
  209. package/src/lib/widgets/descriptors.ts +29 -0
  210. package/src/lib/widgets/metric-card/metric-card.descriptor.ts +41 -0
  211. package/src/lib/widgets/metric-card/metric-card.spec.ts +52 -0
  212. package/src/lib/widgets/metric-card/metric-card.ts +48 -0
  213. package/src/lib/widgets/quick-actions/quick-actions.descriptor.ts +13 -0
  214. package/src/lib/widgets/quick-actions/quick-actions.spec.ts +61 -0
  215. package/src/lib/widgets/quick-actions/quick-actions.ts +100 -0
  216. package/src/lib/widgets/record-list/record-list.descriptor.ts +16 -0
  217. package/src/lib/widgets/record-list/record-list.spec.ts +79 -0
  218. package/src/lib/widgets/record-list/record-list.ts +115 -0
  219. package/src/lib/widgets/series.spec.ts +42 -0
  220. package/src/lib/widgets/series.ts +56 -0
  221. package/src/lib/widgets/status-progress/status-progress.descriptor.ts +19 -0
  222. package/src/lib/widgets/status-progress/status-progress.spec.ts +63 -0
  223. package/src/lib/widgets/status-progress/status-progress.ts +104 -0
  224. package/src/lib/widgets/widget-host/widget-host.spec.ts +179 -0
  225. package/src/lib/widgets/widget-host/widget-host.ts +99 -0
  226. package/src/public-api.ts +104 -0
  227. package/tinya-code-gas-admin-ui-0.2.0-alpha.15.tgz +0 -0
  228. package/tsconfig.lib.json +13 -0
  229. package/tsconfig.lib.prod.json +11 -0
  230. package/tsconfig.spec.json +10 -0
  231. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs +0 -84
  232. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs.map +0 -1
  233. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs +0 -140
  234. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs.map +0 -1
  235. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs +0 -113
  236. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs.map +0 -1
  237. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs +0 -163
  238. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs.map +0 -1
  239. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs +0 -1027
  240. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs.map +0 -1
  241. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs +0 -278
  242. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs.map +0 -1
  243. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs +0 -107
  244. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs.map +0 -1
  245. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs +0 -101
  246. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs.map +0 -1
  247. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs +0 -141
  248. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs.map +0 -1
  249. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs +0 -88
  250. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs.map +0 -1
  251. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs +0 -107
  252. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs.map +0 -1
  253. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs +0 -140
  254. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs.map +0 -1
  255. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs +0 -119
  256. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs.map +0 -1
  257. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs +0 -125
  258. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs.map +0 -1
  259. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs +0 -152
  260. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs.map +0 -1
  261. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs +0 -211
  262. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs.map +0 -1
  263. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs +0 -116
  264. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs.map +0 -1
  265. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs +0 -111
  266. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs.map +0 -1
  267. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs +0 -122
  268. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs.map +0 -1
  269. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs +0 -107
  270. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs.map +0 -1
  271. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs +0 -109
  272. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs.map +0 -1
  273. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs +0 -45
  274. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs.map +0 -1
  275. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs +0 -50
  276. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs.map +0 -1
  277. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs +0 -24
  278. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs.map +0 -1
  279. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs +0 -27
  280. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs.map +0 -1
  281. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs +0 -408
  282. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs.map +0 -1
  283. package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs +0 -4516
  284. package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs.map +0 -1
  285. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs +0 -82
  286. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs.map +0 -1
  287. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs +0 -105
  288. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs.map +0 -1
  289. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs +0 -65
  290. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs.map +0 -1
  291. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs +0 -65
  292. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs.map +0 -1
  293. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs +0 -65
  294. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs.map +0 -1
  295. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs +0 -59
  296. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs.map +0 -1
  297. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs +0 -94
  298. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs.map +0 -1
  299. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs +0 -72
  300. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs.map +0 -1
  301. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs +0 -238
  302. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs.map +0 -1
  303. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs +0 -416
  304. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs.map +0 -1
  305. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs +0 -439
  306. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs.map +0 -1
  307. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs +0 -513
  308. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map +0 -1
  309. package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs +0 -637
  310. package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs.map +0 -1
  311. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs +0 -127
  312. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs.map +0 -1
  313. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs +0 -251
  314. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs.map +0 -1
  315. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs +0 -66
  316. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs.map +0 -1
  317. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs +0 -114
  318. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs.map +0 -1
  319. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs +0 -116
  320. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs.map +0 -1
  321. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs +0 -235
  322. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs.map +0 -1
  323. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs +0 -8
  324. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs.map +0 -1
  325. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs +0 -124
  326. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs.map +0 -1
  327. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs +0 -249
  328. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs.map +0 -1
  329. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs +0 -39
  330. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs.map +0 -1
  331. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs +0 -309
  332. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs.map +0 -1
  333. package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs +0 -576
  334. package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs.map +0 -1
  335. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs +0 -161
  336. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs.map +0 -1
  337. package/fesm2022/tinya-code-gas-admin-ui-rolldown-runtime-DpJrqANO.mjs +0 -11
  338. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs +0 -685
  339. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs.map +0 -1
  340. package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs +0 -80
  341. package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs.map +0 -1
  342. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs +0 -296
  343. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs.map +0 -1
  344. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs +0 -119
  345. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs.map +0 -1
  346. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs +0 -158
  347. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs.map +0 -1
  348. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs +0 -26
  349. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs.map +0 -1
  350. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs +0 -205
  351. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs.map +0 -1
  352. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs +0 -432
  353. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs.map +0 -1
  354. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs +0 -36
  355. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs.map +0 -1
  356. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs +0 -107
  357. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs.map +0 -1
  358. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs +0 -223
  359. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs.map +0 -1
  360. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs +0 -107
  361. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs.map +0 -1
  362. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs +0 -60
  363. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs.map +0 -1
  364. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs +0 -141
  365. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs.map +0 -1
  366. package/fesm2022/tinya-code-gas-admin-ui.mjs +0 -4599
  367. package/fesm2022/tinya-code-gas-admin-ui.mjs.map +0 -1
  368. package/types/tinya-code-gas-admin-ui.d.ts +0 -3632
@@ -0,0 +1,426 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import type { CalendarViewConfig, FieldSchema } from '../../core/models/schema.model';
3
+ import type { SourceRow } from '../../core/services/data-source.service';
4
+
5
+ /**
6
+ * Pure date + event-mapping model for the generic calendar view (R9.8.3).
7
+ *
8
+ * Date model (decided): backend `date` fields are ISO civil dates
9
+ * `YYYY-MM-DD` treated as CALENDAR DAYS — never shifted through the browser
10
+ * timezone. Every parse goes through `Date.UTC` on the literal parts, never
11
+ * `new Date('YYYY-MM-DD')` in local time (that lands on the previous day
12
+ * west of Greenwich).
13
+ */
14
+
15
+ /** Milliseconds in one civil day — every day-step of the model uses this. */
16
+ export const DAY_MS = 86_400_000;
17
+
18
+ /** Visible modes of the calendar. */
19
+ export type CalendarMode = 'month' | 'week' | 'day' | 'agenda';
20
+
21
+ /** Inclusive pair of civil days (`YYYY-MM-DD`) that the view paints. */
22
+ export interface CivilRange {
23
+ desde: string;
24
+ hasta: string;
25
+ }
26
+
27
+ /** One event painted from a source row. */
28
+ export interface CalEvent {
29
+ key: string;
30
+ title: string;
31
+ /** True first day (`YYYY-MM-DD`), before any clamp to the visible range. */
32
+ startDay: string;
33
+ /** True last day, inclusive. Equals `startDay` for single-day events. */
34
+ endDay: string;
35
+ color?: string;
36
+ row: SourceRow;
37
+ }
38
+
39
+ /** A row excluded from the grid because its interval is inconsistent. */
40
+ export interface CalendarProblem {
41
+ row: SourceRow;
42
+ reason: string;
43
+ }
44
+
45
+ /** Result of mapping raw rows onto calendar events (R9.8.3). */
46
+ export interface CalendarMapping {
47
+ events: CalEvent[];
48
+ /** Rows whose `startField` is empty or not a valid civil date. */
49
+ undated: SourceRow[];
50
+ /** Rows whose `endField` makes the interval impossible. */
51
+ invalid: CalendarProblem[];
52
+ }
53
+
54
+ /** Spanish reasons shown next to problem records (UI copy). */
55
+ export const REASON_UNDATED = 'Sin fecha de inicio válida';
56
+ export const REASON_INVALID_END = 'Fecha de fin inválida';
57
+ export const REASON_END_BEFORE_START = 'El fin es anterior al inicio';
58
+
59
+ const MONTHS = [
60
+ 'enero',
61
+ 'febrero',
62
+ 'marzo',
63
+ 'abril',
64
+ 'mayo',
65
+ 'junio',
66
+ 'julio',
67
+ 'agosto',
68
+ 'septiembre',
69
+ 'octubre',
70
+ 'noviembre',
71
+ 'diciembre',
72
+ ];
73
+
74
+ const MONTHS_SHORT = [
75
+ 'ene',
76
+ 'feb',
77
+ 'mar',
78
+ 'abr',
79
+ 'may',
80
+ 'jun',
81
+ 'jul',
82
+ 'ago',
83
+ 'sep',
84
+ 'oct',
85
+ 'nov',
86
+ 'dic',
87
+ ];
88
+
89
+ /** Weekday names Monday-first (the calendar's week start, decided). */
90
+ const WEEKDAYS_SHORT = ['lun', 'mar', 'mié', 'jue', 'vie', 'sáb', 'dom'];
91
+ const WEEKDAYS = ['lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo'];
92
+
93
+ /** Weekday headings of the Monday-first grid, in display order. */
94
+ export const WEEKDAY_HEADINGS: readonly string[] = WEEKDAYS_SHORT;
95
+
96
+ const DAY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
97
+
98
+ /**
99
+ * `YYYY-MM-DD` → UTC milliseconds at midnight of that civil day.
100
+ *
101
+ * Strict: the string must be exactly three zero-padded parts and name a real
102
+ * calendar day (`2026-02-30` is rejected, not rolled into March). Empty,
103
+ * malformed or non-string input → `null` (the caller decides whether that
104
+ * means "undated" or "invalid").
105
+ */
106
+ export function parseDay(value: unknown): number | null {
107
+ if (typeof value !== 'string') return null;
108
+ const match = DAY_PATTERN.exec(value.trim());
109
+ if (match === null) return null;
110
+ const year = Number(match[1]);
111
+ const month = Number(match[2]);
112
+ const day = Number(match[3]);
113
+ const ms = Date.UTC(year, month - 1, day);
114
+ const back = new Date(ms);
115
+ if (
116
+ back.getUTCFullYear() !== year ||
117
+ back.getUTCMonth() !== month - 1 ||
118
+ back.getUTCDate() !== day
119
+ ) {
120
+ return null;
121
+ }
122
+ return ms;
123
+ }
124
+
125
+ /** UTC milliseconds at midnight → `YYYY-MM-DD` (inverse of `parseDay`). */
126
+ export function formatDay(ms: number): string {
127
+ const date = new Date(ms);
128
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
129
+ const day = String(date.getUTCDate()).padStart(2, '0');
130
+ return `${date.getUTCFullYear()}-${month}-${day}`;
131
+ }
132
+
133
+ /**
134
+ * Today as a civil day, in the USER's local calendar date — the local parts
135
+ * are read off `new Date()` and formatted manually, so no timezone shift can
136
+ * sneak in through a round-trip.
137
+ */
138
+ export function todayCivil(): string {
139
+ const now = new Date();
140
+ const month = String(now.getMonth() + 1).padStart(2, '0');
141
+ const day = String(now.getDate()).padStart(2, '0');
142
+ return `${now.getFullYear()}-${month}-${day}`;
143
+ }
144
+
145
+ /**
146
+ * Token inyectable para "hoy" (YYYY-MM-DD). Permite a los tests fijar la
147
+ * fecha del sistema sin depender del reloj real (evita flakiness por mes).
148
+ * Por defecto usa `todayCivil()` (fecha real del sistema).
149
+ */
150
+ export const CALENDAR_TODAY = new InjectionToken<() => string>(
151
+ 'gas.admin.calendarToday',
152
+ { providedIn: 'root', factory: () => todayCivil },
153
+ );
154
+
155
+ /** Day-step on civil days (safe: every `ms` is a UTC midnight). */
156
+ export function addDays(ms: number, days: number): number {
157
+ return ms + days * DAY_MS;
158
+ }
159
+
160
+ /** 0 = Monday … 6 = Sunday (the calendar's Monday-first convention). */
161
+ export function dayOfWeekMon0(ms: number): number {
162
+ return (new Date(ms).getUTCDay() + 6) % 7;
163
+ }
164
+
165
+ /**
166
+ * Move a civil day by whole months, clamping the day-of-month to the target
167
+ * month's length (Jan 31 + 1 month → Feb 28).
168
+ */
169
+ export function shiftMonths(ms: number, months: number): number {
170
+ const date = new Date(ms);
171
+ const target = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + months, 1));
172
+ const lastDay = new Date(
173
+ Date.UTC(target.getUTCFullYear(), target.getUTCMonth() + 1, 0),
174
+ ).getUTCDate();
175
+ return Date.UTC(
176
+ target.getUTCFullYear(),
177
+ target.getUTCMonth(),
178
+ Math.min(date.getUTCDate(), lastDay),
179
+ );
180
+ }
181
+
182
+ /** Monday of the 6-week (42-day) grid that shows the cursor's month. */
183
+ function monthGridStartMs(cursorMs: number): number {
184
+ const date = new Date(cursorMs);
185
+ const firstOfMonth = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1);
186
+ return addDays(firstOfMonth, -dayOfWeekMon0(firstOfMonth));
187
+ }
188
+
189
+ /**
190
+ * The 42 civil days of the month grid (6 Monday-first weeks), so the grid
191
+ * always has the same shape and the de-emphasized edge days are complete.
192
+ */
193
+ export function monthGridDays(cursorDay: string): string[] {
194
+ const cursor = parseDay(cursorDay);
195
+ if (cursor === null) return [];
196
+ const start = monthGridStartMs(cursor);
197
+ return Array.from({ length: 42 }, (_, index) => formatDay(addDays(start, index)));
198
+ }
199
+
200
+ /** The 7 civil days of the Monday-first week containing the cursor. */
201
+ export function weekDays(cursorDay: string): string[] {
202
+ const cursor = parseDay(cursorDay);
203
+ if (cursor === null) return [];
204
+ const start = addDays(cursor, -dayOfWeekMon0(cursor));
205
+ return Array.from({ length: 7 }, (_, index) => formatDay(addDays(start, index)));
206
+ }
207
+
208
+ /** Every civil day of an inclusive range (empty when the range is invalid). */
209
+ export function daysInRange(range: CivilRange): string[] {
210
+ const from = parseDay(range.desde);
211
+ const to = parseDay(range.hasta);
212
+ if (from === null || to === null || to < from) return [];
213
+ const days: string[] = [];
214
+ for (let ms = from; ms <= to; ms = addDays(ms, 1)) {
215
+ days.push(formatDay(ms));
216
+ }
217
+ return days;
218
+ }
219
+
220
+ /**
221
+ * Visible `{desde, hasta}` for a mode + cursor.
222
+ *
223
+ * - `month`: the 6-week grid range (superset of the month) — with the
224
+ * backend-range optimization the fetch already covers the edge weeks.
225
+ * - `week`: the Monday-first week of the cursor.
226
+ * - `day`: the cursor itself.
227
+ * - `agenda`: a fixed 30-day window from the cursor.
228
+ */
229
+ export function visibleRangeFor(mode: CalendarMode, cursorDay: string): CivilRange {
230
+ const cursor = parseDay(cursorDay);
231
+ if (cursor === null) return { desde: '', hasta: '' };
232
+ switch (mode) {
233
+ case 'month': {
234
+ const start = monthGridStartMs(cursor);
235
+ return { desde: formatDay(start), hasta: formatDay(addDays(start, 41)) };
236
+ }
237
+ case 'week': {
238
+ const start = addDays(cursor, -dayOfWeekMon0(cursor));
239
+ return { desde: formatDay(start), hasta: formatDay(addDays(start, 6)) };
240
+ }
241
+ case 'day':
242
+ return { desde: formatDay(cursor), hasta: formatDay(cursor) };
243
+ case 'agenda':
244
+ return { desde: formatDay(cursor), hasta: formatDay(addDays(cursor, 29)) };
245
+ }
246
+ }
247
+
248
+ /** Move the cursor one step of the current mode (agenda steps 30 days). */
249
+ export function shiftCursor(mode: CalendarMode, cursorDay: string, delta: 1 | -1): string {
250
+ const cursor = parseDay(cursorDay) ?? parseDay(todayCivil()) ?? Date.UTC(1970, 0, 1);
251
+ switch (mode) {
252
+ case 'month':
253
+ return formatDay(shiftMonths(cursor, delta));
254
+ case 'week':
255
+ return formatDay(addDays(cursor, 7 * delta));
256
+ case 'day':
257
+ return formatDay(addDays(cursor, delta));
258
+ case 'agenda':
259
+ return formatDay(addDays(cursor, 30 * delta));
260
+ }
261
+ }
262
+
263
+ /** True when both civil days fall in the same year+month. */
264
+ export function sameMonth(a: string, b: string): boolean {
265
+ const msA = parseDay(a);
266
+ const msB = parseDay(b);
267
+ if (msA === null || msB === null) return false;
268
+ const dateA = new Date(msA);
269
+ const dateB = new Date(msB);
270
+ return (
271
+ dateA.getUTCFullYear() === dateB.getUTCFullYear() && dateA.getUTCMonth() === dateB.getUTCMonth()
272
+ );
273
+ }
274
+
275
+ /** Depth-first lookup of a field by key through `group`/`list` nesting. */
276
+ export function findFieldByKey(
277
+ fields: readonly FieldSchema[],
278
+ key: string,
279
+ ): FieldSchema | undefined {
280
+ for (const field of fields) {
281
+ if (field.key === key) return field;
282
+ if (field.type === 'group') {
283
+ const hit = findFieldByKey(field.fields, key);
284
+ if (hit !== undefined) return hit;
285
+ } else if (field.type === 'list') {
286
+ const hit = findFieldByKey(field.itemFields, key);
287
+ if (hit !== undefined) return hit;
288
+ }
289
+ }
290
+ return undefined;
291
+ }
292
+
293
+ /**
294
+ * Pure row → event mapping (R9.8.3): the single place that decides what is a
295
+ * paintable event, what is undated and what is an impossible interval.
296
+ *
297
+ * - Empty/invalid `startField` → `undated` (surfaced, never hidden).
298
+ * - `endField` of type `time` → same civil day as the start (time-of-day
299
+ * within the start day; it never spans days).
300
+ * - Empty `endField` (date) → single-day event on the start.
301
+ * - `end < start` → `invalid` with a visible reason; not painted at all.
302
+ */
303
+ export function mapCalendarRows(
304
+ rows: readonly SourceRow[],
305
+ config: CalendarViewConfig,
306
+ options: { keyField: string; endFieldType?: string },
307
+ ): CalendarMapping {
308
+ const events: CalEvent[] = [];
309
+ const undated: SourceRow[] = [];
310
+ const invalid: CalendarProblem[] = [];
311
+
312
+ for (const row of rows) {
313
+ const startMs = parseDay(row[config.startField]);
314
+ if (startMs === null) {
315
+ undated.push(row);
316
+ continue;
317
+ }
318
+ let endMs = startMs;
319
+ if (config.endField !== undefined && options.endFieldType !== 'time') {
320
+ const rawEnd = row[config.endField];
321
+ const empty = rawEnd === null || rawEnd === undefined || rawEnd === '';
322
+ if (!empty) {
323
+ const parsedEnd = parseDay(rawEnd);
324
+ if (parsedEnd === null) {
325
+ invalid.push({ row, reason: REASON_INVALID_END });
326
+ continue;
327
+ }
328
+ if (parsedEnd < startMs) {
329
+ invalid.push({ row, reason: REASON_END_BEFORE_START });
330
+ continue;
331
+ }
332
+ endMs = parsedEnd;
333
+ }
334
+ }
335
+ const key = String(row[options.keyField] ?? '');
336
+ const title = String(row[config.titleField] ?? '').trim() || key;
337
+ const rawColor = config.colorField !== undefined ? row[config.colorField] : undefined;
338
+ const color = typeof rawColor === 'string' && rawColor !== '' ? rawColor : undefined;
339
+ events.push({ key, title, startDay: formatDay(startMs), endDay: formatDay(endMs), color, row });
340
+ }
341
+
342
+ return { events, undated, invalid };
343
+ }
344
+
345
+ /**
346
+ * Bucket events per civil day inside the visible range.
347
+ *
348
+ * A multi-day event appears under EVERY day it touches; the painted span is
349
+ * clamped to the range (the event keeps its true `startDay`/`endDay` — only
350
+ * the buckets are limited), which also keeps long intervals cheap.
351
+ */
352
+ export function eventsByDay(
353
+ events: readonly CalEvent[],
354
+ range: CivilRange,
355
+ ): Map<string, CalEvent[]> {
356
+ const byDay = new Map<string, CalEvent[]>();
357
+ const from = parseDay(range.desde);
358
+ const to = parseDay(range.hasta);
359
+ if (from === null || to === null || to < from) return byDay;
360
+ for (const event of events) {
361
+ const start = parseDay(event.startDay);
362
+ const end = parseDay(event.endDay);
363
+ if (start === null || end === null) continue;
364
+ const paintFrom = Math.max(start, from);
365
+ const paintTo = Math.min(end, to);
366
+ for (let ms = paintFrom; ms <= paintTo; ms = addDays(ms, 1)) {
367
+ const day = formatDay(ms);
368
+ const bucket = byDay.get(day);
369
+ if (bucket === undefined) byDay.set(day, [event]);
370
+ else bucket.push(event);
371
+ }
372
+ }
373
+ return byDay;
374
+ }
375
+
376
+ /** "12 de octubre de 2026" — civil parts, UTC-based (no TZ shift). */
377
+ export function dayLabel(day: string): string {
378
+ const ms = parseDay(day);
379
+ if (ms === null) return day;
380
+ const date = new Date(ms);
381
+ return `${date.getUTCDate()} de ${MONTHS[date.getUTCMonth()]} de ${date.getUTCFullYear()}`;
382
+ }
383
+
384
+ /** Short weekday of a civil day, Monday-first ("lunes" → "lun"). */
385
+ export function weekdayShort(day: string): string {
386
+ const ms = parseDay(day);
387
+ if (ms === null) return '';
388
+ return WEEKDAYS_SHORT[dayOfWeekMon0(ms)];
389
+ }
390
+
391
+ /** Full weekday of a civil day ("lunes"). */
392
+ export function weekdayFull(day: string): string {
393
+ const ms = parseDay(day);
394
+ if (ms === null) return '';
395
+ return WEEKDAYS[dayOfWeekMon0(ms)];
396
+ }
397
+
398
+ /** "lunes, 12 de octubre de 2026" — agenda/day heading. */
399
+ export function agendaDayLabel(day: string): string {
400
+ const weekday = weekdayFull(day);
401
+ return weekday !== '' ? `${weekday}, ${dayLabel(day)}` : dayLabel(day);
402
+ }
403
+
404
+ /**
405
+ * Header label for the visible range, built from civil parts with a fixed
406
+ * Spanish vocabulary (deterministic regardless of the runtime locale).
407
+ */
408
+ export function rangeLabelFor(mode: CalendarMode, cursorDay: string): string {
409
+ const cursor = parseDay(cursorDay);
410
+ if (cursor === null) return '';
411
+ const date = new Date(cursor);
412
+ if (mode === 'month') {
413
+ return `${MONTHS[date.getUTCMonth()]} de ${date.getUTCFullYear()}`;
414
+ }
415
+ const range = visibleRangeFor(mode, cursorDay);
416
+ const desde = parseDay(range.desde);
417
+ const hasta = parseDay(range.hasta);
418
+ if (desde === null || hasta === null) return '';
419
+ const startDate = new Date(desde);
420
+ const endDate = new Date(hasta);
421
+ const sameYear = startDate.getUTCFullYear() === endDate.getUTCFullYear();
422
+ const left = `${startDate.getUTCDate()} ${MONTHS_SHORT[startDate.getUTCMonth()]}${
423
+ sameYear ? '' : ` ${startDate.getUTCFullYear()}`
424
+ }`;
425
+ return `${left} – ${endDate.getUTCDate()} ${MONTHS_SHORT[endDate.getUTCMonth()]} ${endDate.getUTCFullYear()}`;
426
+ }