@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,122 @@
1
+ import type { RenderDescriptor } from '../core/registry/render-registry';
2
+ import type { FieldType } from '../core/models/schema.model';
3
+
4
+ import { descriptor as booleanDescriptor } from './boolean/boolean.descriptor';
5
+ import { descriptor as colorDescriptor } from './color/color.descriptor';
6
+ import { descriptor as currencyDescriptor } from './currency/currency.descriptor';
7
+ import { descriptor as dateDescriptor } from './date/date.descriptor';
8
+ import { descriptor as emailDescriptor } from './email/email.descriptor';
9
+ import { descriptor as fileDescriptor } from './file/file.descriptor';
10
+ import { descriptor as groupDescriptor } from './group/group.descriptor';
11
+ import { descriptor as imageDescriptor } from './image/image.descriptor';
12
+ import { descriptor as keyValueDescriptor } from './key-value/key-value.descriptor';
13
+ import { descriptor as listDescriptor } from './list/list.descriptor';
14
+ import { descriptor as multiselectDescriptor } from './multiselect/multiselect.descriptor';
15
+ import { descriptor as numberDescriptor } from './number/number.descriptor';
16
+ import { descriptor as phoneDescriptor } from './phone/phone.descriptor';
17
+ import { descriptor as readonlyTextDescriptor } from './readonly-text/readonly-text.descriptor';
18
+ import { descriptor as relationDescriptor } from './relation/relation.descriptor';
19
+ import { descriptor as richSelectDescriptor } from './rich-select/rich-select.descriptor';
20
+ import { descriptor as selectDescriptor } from './select/select.descriptor';
21
+ import { descriptor as dropdownDescriptor } from './dropdown/dropdown.descriptor';
22
+ import { descriptor as slugDescriptor } from './slug/slug.descriptor';
23
+ import { descriptor as stringListDescriptor } from './string-list/string-list.descriptor';
24
+ import { descriptor as textDescriptor } from './text/text.descriptor';
25
+ import { descriptor as textareaDescriptor } from './textarea/textarea.descriptor';
26
+ import { descriptor as timeDescriptor } from './time/time.descriptor';
27
+ import { descriptor as urlDescriptor } from './url/url.descriptor';
28
+
29
+ /**
30
+ * Tripwire de compilación (R1.7 · D17): que la unión `FieldType` y los
31
+ * tipos que la UI sabe dibujar sigan diciendo lo mismo.
32
+ *
33
+ * · un valor que no esté en la unión `FieldSchema` ⇒ `satisfies` falla;
34
+ * · un tipo de la unión que falte acá ⇒ `FaltaEnLaUi` no es `never`.
35
+ *
36
+ * **No es una fuente de verdad en runtime.** El catálogo vive en
37
+ * `core/registry/render-registry.ts`, alimentado por los descriptores de
38
+ * abajo. Esta lista sólo existe para que `npm run build` y `npm test` vean
39
+ * la aserción por igual, sin depender de que un test la ejecute.
40
+ *
41
+ * **Exportada en R3.7** para que `core/registry/contract.spec.ts` pueda
42
+ * verificar además el sentido que este archivo no cubre — que cada nombre de
43
+ * la lista tenga **descriptor**: aquí sólo se comprueba que está en la unión,
44
+ * y un tipo declarado en la lista pero ausente del manifiesto se vería en el
45
+ * primer schema que lo use.
46
+ *
47
+ * **Mudado acá en R3.8.** Vivía en `field-host/field-host.ts`, y §0 es
48
+ * explícito: «si añadir un tipo obliga a editar `FieldHost`, el motor no
49
+ * está terminado». Estaba sin uso en runtime — sólo servía a este tripwire —
50
+ * así que trasladarlo acá no cambia comportamiento y deja el registro y su
51
+ * aserción en el **mismo archivo**: añadir un tipo toca una carpeta y una
52
+ * línea de este manifiesto, y el host no se entera.
53
+ */
54
+ export const SUPPORTED_FIELD_TYPE_LIST = [
55
+ 'text',
56
+ 'textarea',
57
+ 'slug',
58
+ 'number',
59
+ 'currency',
60
+ 'boolean',
61
+ 'select',
62
+ 'multiselect',
63
+ 'url',
64
+ 'email',
65
+ 'phone',
66
+ 'date',
67
+ 'time',
68
+ 'readonly-text',
69
+ 'group',
70
+ 'list',
71
+ 'string-list',
72
+ 'key-value',
73
+ 'relation',
74
+ 'image',
75
+ 'file',
76
+ 'color',
77
+ 'rich-select',
78
+ 'dropdown',
79
+ ] as const satisfies readonly FieldType[];
80
+
81
+ type FaltaEnLaUi = Exclude<FieldType, (typeof SUPPORTED_FIELD_TYPE_LIST)[number]>;
82
+ const _exhaustivo: FaltaEnLaUi extends never
83
+ ? true
84
+ : ['Falta en SUPPORTED_FIELD_TYPE_LIST', FaltaEnLaUi] = true;
85
+
86
+ /**
87
+ * Manifiesto de descriptores de campo (R3.3 · registro único de render).
88
+ *
89
+ * Una línea por tipo: el registro los recoge al importar este módulo. Es la
90
+ * **única** lista manual del catálogo de campos — `import.meta.glob` no
91
+ * sobrevive a `ng build`, así que D9-1 se resuelve con «registro manual de
92
+ * una línea». Ver `core/registry/render-registry.ts`.
93
+ *
94
+ * Añadir un tipo de campo ⇒ crear la carpeta + su `.descriptor.ts` + una
95
+ * línea acá. **Ningún host se toca** (R3.8).
96
+ */
97
+ export const fieldDescriptors: readonly RenderDescriptor[] = [
98
+ booleanDescriptor,
99
+ colorDescriptor,
100
+ currencyDescriptor,
101
+ dateDescriptor,
102
+ emailDescriptor,
103
+ fileDescriptor,
104
+ groupDescriptor,
105
+ imageDescriptor,
106
+ keyValueDescriptor,
107
+ listDescriptor,
108
+ multiselectDescriptor,
109
+ numberDescriptor,
110
+ phoneDescriptor,
111
+ readonlyTextDescriptor,
112
+ relationDescriptor,
113
+ selectDescriptor,
114
+ slugDescriptor,
115
+ stringListDescriptor,
116
+ textDescriptor,
117
+ textareaDescriptor,
118
+ timeDescriptor,
119
+ urlDescriptor,
120
+ richSelectDescriptor,
121
+ dropdownDescriptor,
122
+ ];
@@ -0,0 +1,65 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+
3
+ import { Badge, type BadgeKind } from '../../shared/components/badge/badge';
4
+ import type { FieldSchema, SelectField } from '../../core/models/schema.model';
5
+
6
+ /**
7
+ * Display por defecto de `boolean` y `select` (R4.1 · modo `display`).
8
+ *
9
+ * Absorbe `formatValue` + `resolveBadgeKind` de `detail-view` (R4.2): los
10
+ * estados siguen clasificándose con el mismo vocabulario —
11
+ * `PENDIENTE/WAITING/EN_PROCESO/PROCESSING` en `warning`,
12
+ * `ENTREGADO/DELIVERED/…` en `success`, `CANCELADO/REVOCADA/ERROR/…` en
13
+ * `danger` y el resto en `neutral` — porque es el criterio que el operador
14
+ * ya reconoce en la cabecera de la ficha.
15
+ *
16
+ * `boolean` pinta `Sí`/`No` con `success`/`neutral` (la paridad de R4.2);
17
+ * los `trueLabel`/`falseLabel` del schema siguen siendo cosa del control de
18
+ * **edición**, y de la columna de lista (R4.3), que sí los usa.
19
+ */
20
+ @Component({
21
+ selector: 'app-field-display-badge',
22
+ imports: [Badge],
23
+ template: `<app-badge [label]="label()" [kind]="kind()" />`,
24
+ })
25
+ export class FieldDisplayBadge {
26
+ readonly field = input.required<FieldSchema>();
27
+ readonly value = input<unknown>(null);
28
+ /** El chip de la cabecera ya es este componente: se ignora. */
29
+ readonly chip = input(false);
30
+
31
+ protected readonly label = computed(() => {
32
+ if (this.field().type === 'boolean') {
33
+ return this.value() ? 'Sí' : 'No';
34
+ }
35
+ const opciones = (this.field() as SelectField).options ?? [];
36
+ const encontrada = opciones.find((o) => o.value === String(this.value()));
37
+ return encontrada ? encontrada.label : String(this.value());
38
+ });
39
+
40
+ protected readonly kind = computed<BadgeKind>(() => {
41
+ if (this.field().type === 'boolean') {
42
+ return this.value() ? 'success' : 'neutral';
43
+ }
44
+ return resolveBadgeKind(String(this.value()));
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Clasificación de estados, común al display de detalle (acá) y al
50
+ * timeline del historial (`display-list`). Exportada para que R4.3 pueda
51
+ * reusarla si la columna de lista decide alinearse con este criterio.
52
+ */
53
+ export function resolveBadgeKind(valor: string): BadgeKind {
54
+ const upper = String(valor).toUpperCase();
55
+ if (['PENDIENTE', 'WAITING', 'EN_PROCESO', 'PROCESSING'].includes(upper)) return 'warning';
56
+ if (
57
+ ['ENTREGADO', 'DELIVERED', 'ACTIVA', 'ACTIVE', 'COMPLETADO', 'SUCCESS', 'SI', 'SÍ'].includes(
58
+ upper,
59
+ )
60
+ )
61
+ return 'success';
62
+ if (['CANCELADO', 'CANCELLED', 'REVOCADA', 'REVOKED', 'ERROR', 'NO'].includes(upper))
63
+ return 'danger';
64
+ return 'neutral';
65
+ }
@@ -0,0 +1,39 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+
3
+ import { Badge } from '../../shared/components/badge/badge';
4
+ import type { FieldSchema } from '../../core/models/schema.model';
5
+
6
+ const FORMATO_FECHA = new Intl.DateTimeFormat('es-PE', { dateStyle: 'medium', timeZone: 'UTC' });
7
+
8
+ /**
9
+ * Display por defecto de `date` (R4.1 · modo `display`).
10
+ *
11
+ * Misma fórmula que `formatValue` de `detail-view` antes de R4.2: `es-PE`,
12
+ * `dateStyle: 'medium'`, **UTC** para que la fecha no se corra un día según
13
+ * el huso de quien abra la ficha, y texto crudo si no es parseable.
14
+ */
15
+ @Component({
16
+ selector: 'app-field-display-date',
17
+ imports: [Badge],
18
+ template: `
19
+ @if (chip()) {
20
+ <app-badge [label]="texto()" />
21
+ } @else {
22
+ {{ texto() }}
23
+ }
24
+ `,
25
+ })
26
+ export class FieldDisplayDate {
27
+ readonly field = input.required<FieldSchema>();
28
+ readonly value = input<unknown>(null);
29
+ /** `true` en la cabecera: la fecha se pinta como chip compacto. */
30
+ readonly chip = input(false);
31
+
32
+ protected readonly texto = computed(() => {
33
+ const d = new Date(String(this.value()));
34
+ if (Number.isNaN(d.getTime())) {
35
+ return String(this.value());
36
+ }
37
+ return FORMATO_FECHA.format(d);
38
+ });
39
+ }
@@ -0,0 +1,84 @@
1
+ import type { Type } from '@angular/core';
2
+
3
+ import type { FieldType } from '../../core/models/schema.model';
4
+
5
+ /** Carga perezosa del componente que pinta un valor en modo `display`. */
6
+ export type DisplayLoader = () => Promise<Type<any>>;
7
+
8
+ const TEXTO: DisplayLoader = () =>
9
+ import('./display-text').then((module) => module.FieldDisplayText);
10
+ const FECHA: DisplayLoader = () =>
11
+ import('./display-date').then((module) => module.FieldDisplayDate);
12
+ const NUMERO: DisplayLoader = () =>
13
+ import('./display-number').then((module) => module.FieldDisplayNumber);
14
+ const BADGE: DisplayLoader = () =>
15
+ import('./display-badge').then((module) => module.FieldDisplayBadge);
16
+ const IMAGEN: DisplayLoader = () =>
17
+ import('./display-image').then((module) => module.FieldDisplayImage);
18
+ const ARCHIVO: DisplayLoader = () =>
19
+ import('./display-file').then((module) => module.FieldDisplayFile);
20
+ const LISTA: DisplayLoader = () =>
21
+ import('./display-list').then((module) => module.FieldDisplayList);
22
+
23
+ /**
24
+ * **Tabla de display por defecto según `field.type`** (F3 de
25
+ * `doc/refactormotor.md`, R4.1 del plan): «cada descriptor declara si sabe
26
+ * pintarse en `display`; si no, usa un `display` por defecto según tipo».
27
+ *
28
+ * La declaración vive en el descriptor (`surfaces: ['form', 'display']`) y
29
+ * el componente sale de acá: un solo sitio decide qué pinta cada tipo en la
30
+ * ficha de detalle. Es la misma familia de cambio que la tabla de formato
31
+ * de columna de R4.4 — «declarada, no implícita».
32
+ *
33
+ * `Record<FieldType, …>` es el **tripwire de exhaustividad en compilación**:
34
+ * un tipo nuevo obliga a elegir su display antes de que el build pase, y un
35
+ * tipo retirado obliga a limpiar la entrada. En runtime el acceso pasa por
36
+ * `displayLoader()`, que no lanza si el `type` viene de un schema mal
37
+ * escrito.
38
+ *
39
+ * Paridad con el `formatValue` que vivía en `detail-view` (R4.2):
40
+ * `text/textarea/slug/url/email/phone/readonly-text/relation/group/
41
+ * key-value/string-list/multiselect/time` → texto crudo · `date` → fecha ·
42
+ * `number/currency` → número · `boolean/select` → badge · `image` →
43
+ * miniatura · `list` → timeline.
44
+ */
45
+ const DISPLAY_POR_DEFECTO: Record<FieldType, DisplayLoader> = {
46
+ text: TEXTO,
47
+ textarea: TEXTO,
48
+ slug: TEXTO,
49
+ url: TEXTO,
50
+ email: TEXTO,
51
+ phone: TEXTO,
52
+ 'readonly-text': TEXTO,
53
+ relation: TEXTO,
54
+ group: TEXTO,
55
+ 'key-value': TEXTO,
56
+ 'string-list': TEXTO,
57
+ multiselect: TEXTO,
58
+ time: TEXTO,
59
+ date: FECHA,
60
+ number: NUMERO,
61
+ currency: NUMERO,
62
+ boolean: BADGE,
63
+ select: BADGE,
64
+ image: IMAGEN,
65
+ file: ARCHIVO,
66
+ list: LISTA,
67
+ color: TEXTO,
68
+ // Un rich-select se muestra con el label de la opción elegida.
69
+ 'rich-select': TEXTO,
70
+ // Un dropdown se muestra con el label de la opción elegida.
71
+ dropdown: TEXTO,
72
+ };
73
+
74
+ /**
75
+ * Componente de display para un `type`, o `undefined` si no está en la
76
+ * tabla (tipo fuera de la unión — p. ej. un schema con un `type` mal
77
+ * escrito). Ese `undefined` es lo que el host traduce en la degradación
78
+ * controlada de R1.10: en dev se avisa, en producción se omite.
79
+ */
80
+ export function displayLoader(type: string): DisplayLoader | undefined {
81
+ return Object.prototype.hasOwnProperty.call(DISPLAY_POR_DEFECTO, type)
82
+ ? DISPLAY_POR_DEFECTO[type as FieldType]
83
+ : undefined;
84
+ }
@@ -0,0 +1,41 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+
3
+ import { Badge } from '../../shared/components/badge/badge';
4
+ import type { FieldSchema } from '../../core/models/schema.model';
5
+
6
+ /**
7
+ * Display por defecto de `file` (R4.1 · modo `display` · R9.5.3).
8
+ *
9
+ * Un archivo no tiene miniatura: el valor es la URL pública, y lo honesto
10
+ * en la ficha de detalle es un enlace que lo abre (mismo lenguaje que el
11
+ * «Abrir» de `url`). En la cabecera (`chip`) va como badge con la URL, la
12
+ * paridad con el resto de los displays.
13
+ */
14
+ @Component({
15
+ selector: 'app-field-display-file',
16
+ imports: [Badge],
17
+ template: `
18
+ @if (chip()) {
19
+ <app-badge [label]="url()" />
20
+ } @else {
21
+ <a
22
+ class="font-medium text-primary hover:underline"
23
+ [href]="url()"
24
+ target="_blank"
25
+ rel="noopener noreferrer"
26
+ >
27
+ Abrir archivo
28
+ </a>
29
+ }
30
+ `,
31
+ })
32
+ export class FieldDisplayFile {
33
+ /** Campo que se pinta. Lo usa el tipo; acá sólo tipa la forma común. */
34
+ readonly field = input.required<FieldSchema>();
35
+ /** Valor crudo del registro (la URL pública). El host ya filtró el vacío. */
36
+ readonly value = input<unknown>(null);
37
+ /** `true` en la cabecera: la URL se pinta como chip compacto. */
38
+ readonly chip = input(false);
39
+
40
+ protected readonly url = computed(() => String(this.value()));
41
+ }
@@ -0,0 +1,54 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+
3
+ import { LucideExternalLink } from '@lucide/angular';
4
+
5
+ import { Badge } from '../../shared/components/badge/badge';
6
+ import type { FieldSchema } from '../../core/models/schema.model';
7
+
8
+ /**
9
+ * Display por defecto de `image` (R4.1 · modo `display`).
10
+ *
11
+ * Mismo maquetado que la rama `kind === 'image'` de `detail-view` antes de
12
+ * R4.2: miniatura de 7×7 con enlace a la imagen completa y overlay con el
13
+ * icono de «abrir». El `alt` sigue siendo la etiqueta del campo.
14
+ *
15
+ * El host ya se encarga del valor vacío (pinta `—`), así que acá la URL
16
+ * siempre existe.
17
+ */
18
+ @Component({
19
+ selector: 'app-field-display-image',
20
+ imports: [Badge, LucideExternalLink],
21
+ template: `
22
+ @if (chip()) {
23
+ <!-- Paridad R4.2: la cabecera siempre mostró el valor formateado
24
+ como chip, y para una imagen ese valor era la URL. -->
25
+ <app-badge [label]="url()" />
26
+ } @else {
27
+ <a
28
+ [href]="url()"
29
+ target="_blank"
30
+ rel="noopener noreferrer"
31
+ class="group relative inline-block overflow-hidden rounded-xl border border-neutral/20 shadow-xs transition hover:border-primary"
32
+ >
33
+ <img
34
+ [src]="url()"
35
+ [alt]="field().label"
36
+ class="h-28 w-28 object-cover transition duration-300 group-hover:scale-105"
37
+ />
38
+ <div
39
+ class="absolute inset-0 flex items-center justify-center bg-black/40 opacity-0 transition group-hover:opacity-100"
40
+ >
41
+ <svg lucideExternalLink size="18" class="text-white" />
42
+ </div>
43
+ </a>
44
+ }
45
+ `,
46
+ })
47
+ export class FieldDisplayImage {
48
+ readonly field = input.required<FieldSchema>();
49
+ readonly value = input<unknown>(null);
50
+ /** `true` en la cabecera: la URL se pinta como chip compacto. */
51
+ readonly chip = input(false);
52
+
53
+ protected readonly url = computed(() => String(this.value()));
54
+ }
@@ -0,0 +1,107 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+
3
+ import { LucideClock } from '@lucide/angular';
4
+
5
+ import { Badge, type BadgeKind } from '../../shared/components/badge/badge';
6
+ import type { FieldSchema } from '../../core/models/schema.model';
7
+ import { resolveBadgeKind } from './display-badge';
8
+
9
+ const FORMATO_FECHA_HORA = new Intl.DateTimeFormat('es-PE', {
10
+ dateStyle: 'medium',
11
+ timeStyle: 'short',
12
+ timeZone: 'UTC',
13
+ });
14
+
15
+ type Item = Record<string, unknown>;
16
+
17
+ /**
18
+ * Display por defecto de `list` (R4.1 · modo `display`).
19
+ *
20
+ * Es la línea de tiempo del historial: **toda la plantilla de `list` que
21
+ * vivía en `detail-view`** se muda acá, que es lo que R4.2 exige
22
+ * («`detail-view` no tiene plantilla propia de campo»). El agrupador sigue
23
+ * siendo `detail-view`: él decide que este campo va en su bloque con el
24
+ * `<h3>` y el ancho grande; acá sólo se pinta el valor.
25
+ *
26
+ * `itemFields` no participa: el timeline lee `action` / `at` / `detail`
27
+ * directamente, igual que antes.
28
+ */
29
+ @Component({
30
+ selector: 'app-field-display-list',
31
+ imports: [Badge, LucideClock],
32
+ template: `
33
+ @if (chip()) {
34
+ <!-- Paridad R4.2: la cabecera siempre mostró el valor formateado
35
+ como chip, y para una lista ese valor era «N elementos». -->
36
+ <app-badge [label]="resumen()" />
37
+ } @else if (items().length > 0) {
38
+ <div
39
+ class="relative pl-6 space-y-4 before:absolute before:left-2 before:top-2 before:bottom-2 before:w-0.5 before:bg-neutral/20"
40
+ >
41
+ @for (item of items(); track $index) {
42
+ <div class="relative group">
43
+ <span
44
+ class="absolute -left-6 top-1 flex h-4 w-4 items-center justify-center rounded-full bg-primary/20 ring-4 ring-surface"
45
+ >
46
+ <span class="h-1.5 w-1.5 rounded-full bg-primary"></span>
47
+ </span>
48
+ <div
49
+ class="rounded-xl border border-neutral/10 bg-neutral/5 p-3.5 transition hover:border-neutral/20"
50
+ >
51
+ <div class="flex flex-wrap items-center justify-between gap-2 mb-1.5">
52
+ @if (item['action']) {
53
+ <app-badge
54
+ [label]="etiquetaAccion(item['action'])"
55
+ [kind]="kindAccion(item['action'])"
56
+ />
57
+ }
58
+ @if (item['at']) {
59
+ <span class="text-xs text-neutral flex items-center gap-1">
60
+ <svg lucideClock size="12" />
61
+ {{ fechaHora(item['at']) }}
62
+ </span>
63
+ }
64
+ </div>
65
+ @if (item['detail']) {
66
+ <p class="text-sm text-neutral-light">{{ item['detail'] }}</p>
67
+ }
68
+ </div>
69
+ </div>
70
+ }
71
+ </div>
72
+ } @else {
73
+ <p class="text-xs italic text-neutral">No hay registros en el historial.</p>
74
+ }
75
+ `,
76
+ })
77
+ export class FieldDisplayList {
78
+ readonly field = input.required<FieldSchema>();
79
+ readonly value = input<unknown>(null);
80
+ /** `true` en la cabecera: el resumen «N elementos» va como chip. */
81
+ readonly chip = input(false);
82
+
83
+ /** El host entrega el valor crudo; sólo un array tiene timeline. */
84
+ protected readonly items = computed<Item[]>(() =>
85
+ Array.isArray(this.value()) ? (this.value() as Item[]) : [],
86
+ );
87
+
88
+ /** Mismo texto que daba el formateo de detalle previo a R4.2. */
89
+ protected resumen(): string {
90
+ return `${this.items().length} elementos`;
91
+ }
92
+
93
+ protected fechaHora(valor: unknown): string {
94
+ if (!valor) return '—';
95
+ const d = new Date(String(valor));
96
+ return Number.isNaN(d.getTime()) ? String(valor) : FORMATO_FECHA_HORA.format(d);
97
+ }
98
+
99
+ protected etiquetaAccion(valor: unknown): string {
100
+ if (!valor) return '';
101
+ return String(valor).replace(/_/g, ' ');
102
+ }
103
+
104
+ protected kindAccion(valor: unknown): BadgeKind {
105
+ return resolveBadgeKind(String(valor));
106
+ }
107
+ }
@@ -0,0 +1,41 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+
3
+ import { Badge } from '../../shared/components/badge/badge';
4
+ import type { FieldSchema } from '../../core/models/schema.model';
5
+
6
+ const FORMATO_NUMERO = new Intl.NumberFormat('es-PE');
7
+
8
+ /**
9
+ * Display por defecto de `number` y `currency` (R4.1 · modo `display`).
10
+ *
11
+ * Los dos tipos compartían rama en `formatValue` y la comparten acá: miles
12
+ * con separador `es-PE` y sin decimales fijos (el schema controla los
13
+ * decimales con `decimals` en el form; en display manda el valor tal cual
14
+ * viene). Si no es número, se pinta el texto crudo — la degradación que ya
15
+ * hacía `detail-view`.
16
+ */
17
+ @Component({
18
+ selector: 'app-field-display-number',
19
+ imports: [Badge],
20
+ template: `
21
+ @if (chip()) {
22
+ <app-badge [label]="texto()" />
23
+ } @else {
24
+ {{ texto() }}
25
+ }
26
+ `,
27
+ })
28
+ export class FieldDisplayNumber {
29
+ readonly field = input.required<FieldSchema>();
30
+ readonly value = input<unknown>(null);
31
+ /** `true` en la cabecera: el número se pinta como chip compacto. */
32
+ readonly chip = input(false);
33
+
34
+ protected readonly texto = computed(() => {
35
+ const n = Number(this.value());
36
+ if (!Number.isFinite(n)) {
37
+ return String(this.value());
38
+ }
39
+ return FORMATO_NUMERO.format(n);
40
+ });
41
+ }
@@ -0,0 +1,42 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+
3
+ import { Badge } from '../../shared/components/badge/badge';
4
+ import type { FieldSchema } from '../../core/models/schema.model';
5
+
6
+ /**
7
+ * Display por defecto de los tipos textuales (R4.1 · modo `display`).
8
+ *
9
+ * Toma el valor crudo del registro —no el árbol del formulario— y lo pinta
10
+ * como texto: el `default` de `formatValue` de `detail-view`, que era donde
11
+ * caían `text`, `textarea`, `slug`, `url`, `email`, `phone`, `readonly-text`,
12
+ * `relation`, `group`, `key-value`, `string-list`, `multiselect` y `time`.
13
+ *
14
+ * `String(raw)` conserva el comportamiento previo (un array sale `a,b`; un
15
+ * objeto sale `[object Object]`): R4.2 pide que «los 7 detalles rendericen
16
+ * igual», así que la paridad manda sobre la estética.
17
+ *
18
+ * Todos los display declaran `field`, `value` y `chip` aunque no los usen:
19
+ * el host les pasa la misma forma a los 6 y `ngComponentOutletInputs` no
20
+ * admite claves que el componente no declare.
21
+ */
22
+ @Component({
23
+ selector: 'app-field-display-text',
24
+ imports: [Badge],
25
+ template: `
26
+ @if (chip()) {
27
+ <app-badge [label]="texto()" />
28
+ } @else {
29
+ {{ texto() }}
30
+ }
31
+ `,
32
+ })
33
+ export class FieldDisplayText {
34
+ /** Campo que se pinta. Lo usa el tipo; acá sólo tipa la forma común. */
35
+ readonly field = input.required<FieldSchema>();
36
+ /** Valor crudo del registro. El host ya filtró el vacío (`—`). */
37
+ readonly value = input<unknown>(null);
38
+ /** `true` en la cabecera: el texto se pinta como chip compacto. */
39
+ readonly chip = input(false);
40
+
41
+ protected readonly texto = computed(() => String(this.value()));
42
+ }