@tinya-code/gas-admin-ui 0.2.0-alpha.12 → 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 (369) hide show
  1. package/README.md +222 -0
  2. package/ng-package.json +7 -0
  3. package/package.json +3 -15
  4. package/src/lib/actions/action-registry.spec.ts +52 -0
  5. package/src/lib/actions/action-registry.ts +126 -0
  6. package/src/lib/actions/action-service.spec.ts +215 -0
  7. package/src/lib/actions/action-service.ts +87 -0
  8. package/src/lib/actions/descriptors.spec.ts +155 -0
  9. package/src/lib/actions/descriptors.ts +154 -0
  10. package/src/lib/columns/column-cell.ts +33 -0
  11. package/src/lib/columns/column-defaults.spec.ts +99 -0
  12. package/src/lib/columns/column-defaults.ts +84 -0
  13. package/src/lib/columns/column-format.spec.ts +274 -0
  14. package/src/lib/columns/descriptors.ts +113 -0
  15. package/src/lib/columns/format-badge.ts +51 -0
  16. package/src/lib/columns/format-boolean.ts +58 -0
  17. package/src/lib/columns/format-currency.ts +30 -0
  18. package/src/lib/columns/format-date.ts +35 -0
  19. package/src/lib/columns/format-number.ts +32 -0
  20. package/src/lib/columns/format-text.ts +23 -0
  21. package/src/lib/columns/format-thumbnail.ts +63 -0
  22. package/src/lib/core/adapters/firebase-auth.adapter.ts +6 -0
  23. package/src/lib/core/guards/auth.guard.spec.ts +88 -0
  24. package/src/lib/core/guards/auth.guard.ts +48 -0
  25. package/src/lib/core/guards/unsaved-changes.guard.ts +16 -0
  26. package/src/lib/core/interceptors/api-error.interceptor.spec.ts +182 -0
  27. package/src/lib/core/interceptors/api-error.interceptor.ts +87 -0
  28. package/src/lib/core/models/api.model.ts +104 -0
  29. package/src/lib/core/models/schema-descriptions.ts +118 -0
  30. package/src/lib/core/models/schema.model.ts +1097 -0
  31. package/src/lib/core/registry/composition-validator.spec.ts +358 -0
  32. package/src/lib/core/registry/composition-validator.ts +270 -0
  33. package/src/lib/core/registry/field-validators.spec.ts +199 -0
  34. package/src/lib/core/registry/field-validators.ts +440 -0
  35. package/src/lib/core/registry/render-host.spec.ts +208 -0
  36. package/src/lib/core/registry/render-host.ts +646 -0
  37. package/src/lib/core/registry/render-registry.spec.ts +96 -0
  38. package/src/lib/core/registry/render-registry.ts +312 -0
  39. package/src/lib/core/registry/schema-catalog.ts +156 -0
  40. package/src/lib/core/services/api.service.spec.ts +1142 -0
  41. package/src/lib/core/services/api.service.ts +371 -0
  42. package/src/lib/core/services/auth.service.spec.ts +653 -0
  43. package/src/lib/core/services/auth.service.ts +503 -0
  44. package/src/lib/core/services/config.service.spec.ts +121 -0
  45. package/src/lib/core/services/config.service.ts +119 -0
  46. package/src/lib/core/services/data-source.service.spec.ts +179 -0
  47. package/src/lib/core/services/data-source.service.ts +142 -0
  48. package/src/lib/core/services/error-mapper.service.spec.ts +50 -0
  49. package/src/lib/core/services/error-mapper.service.ts +49 -0
  50. package/src/lib/core/services/notification.service.ts +73 -0
  51. package/src/lib/core/services/relation-drawer.service.ts +41 -0
  52. package/src/lib/core/services/theme.service.spec.ts +106 -0
  53. package/src/lib/core/services/theme.service.ts +86 -0
  54. package/src/lib/core/services/transport.spec.ts +198 -0
  55. package/src/lib/core/services/transport.ts +164 -0
  56. package/src/lib/core/services/upload.service.ts +81 -0
  57. package/src/lib/core/testing/categories.schema.ts +125 -0
  58. package/src/lib/core/testing/orders.schema.ts +372 -0
  59. package/src/lib/core/testing/products.schema.ts +258 -0
  60. package/src/lib/core/testing/site.schema.ts +195 -0
  61. package/src/lib/core/testing/test-catalog.ts +21 -0
  62. package/src/lib/core/tokens.ts +112 -0
  63. package/src/lib/core/utils/clipboard.spec.ts +55 -0
  64. package/src/lib/core/utils/clipboard.ts +90 -0
  65. package/src/lib/core/utils/context-resolver.spec.ts +95 -0
  66. package/src/lib/core/utils/context-resolver.ts +101 -0
  67. package/src/lib/core/utils/response-unwrapper.spec.ts +70 -0
  68. package/src/lib/core/utils/response-unwrapper.ts +103 -0
  69. package/src/lib/core/utils/source-options.spec.ts +96 -0
  70. package/src/lib/core/utils/source-options.ts +54 -0
  71. package/src/lib/core/utils/template-interpolator.spec.ts +59 -0
  72. package/src/lib/core/utils/template-interpolator.ts +56 -0
  73. package/src/lib/core/view-navigation/view-navigation.service.spec.ts +207 -0
  74. package/src/lib/core/view-navigation/view-navigation.service.ts +132 -0
  75. package/src/lib/fields/boolean/boolean.descriptor.ts +11 -0
  76. package/src/lib/fields/boolean/boolean.ts +40 -0
  77. package/src/lib/fields/color/color.descriptor.ts +12 -0
  78. package/src/lib/fields/color/color.ts +34 -0
  79. package/src/lib/fields/currency/currency.descriptor.ts +12 -0
  80. package/src/lib/fields/currency/currency.ts +67 -0
  81. package/src/lib/fields/date/date.descriptor.ts +12 -0
  82. package/src/lib/fields/date/date.ts +36 -0
  83. package/src/lib/fields/descriptors.ts +122 -0
  84. package/src/lib/fields/display/display-badge.ts +65 -0
  85. package/src/lib/fields/display/display-date.ts +39 -0
  86. package/src/lib/fields/display/display-defaults.ts +84 -0
  87. package/src/lib/fields/display/display-file.ts +41 -0
  88. package/src/lib/fields/display/display-image.ts +54 -0
  89. package/src/lib/fields/display/display-list.ts +107 -0
  90. package/src/lib/fields/display/display-number.ts +41 -0
  91. package/src/lib/fields/display/display-text.ts +42 -0
  92. package/src/lib/fields/display/display.spec.ts +242 -0
  93. package/src/lib/fields/dropdown/dropdown.descriptor.ts +12 -0
  94. package/src/lib/fields/dropdown/dropdown.ts +45 -0
  95. package/src/lib/fields/email/email.descriptor.ts +12 -0
  96. package/src/lib/fields/email/email.ts +28 -0
  97. package/src/lib/fields/field-aria.ts +60 -0
  98. package/src/lib/fields/field-host/field-host.spec.ts +118 -0
  99. package/src/lib/fields/field-host/field-host.ts +47 -0
  100. package/src/lib/fields/field-node.ts +88 -0
  101. package/src/lib/fields/file/file.descriptor.ts +14 -0
  102. package/src/lib/fields/file/file.spec.ts +134 -0
  103. package/src/lib/fields/file/file.ts +281 -0
  104. package/src/lib/fields/group/group.descriptor.ts +21 -0
  105. package/src/lib/fields/group/group.ts +110 -0
  106. package/src/lib/fields/image/image.descriptor.ts +12 -0
  107. package/src/lib/fields/image/image.spec.ts +117 -0
  108. package/src/lib/fields/image/image.ts +281 -0
  109. package/src/lib/fields/key-value/key-value.descriptor.ts +11 -0
  110. package/src/lib/fields/key-value/key-value.ts +283 -0
  111. package/src/lib/fields/list/list.descriptor.ts +21 -0
  112. package/src/lib/fields/list/list.ts +376 -0
  113. package/src/lib/fields/multiselect/multiselect.descriptor.ts +11 -0
  114. package/src/lib/fields/multiselect/multiselect.spec.ts +142 -0
  115. package/src/lib/fields/multiselect/multiselect.ts +152 -0
  116. package/src/lib/fields/number/number.descriptor.ts +12 -0
  117. package/src/lib/fields/number/number.ts +40 -0
  118. package/src/lib/fields/phone/phone.descriptor.ts +12 -0
  119. package/src/lib/fields/phone/phone.ts +46 -0
  120. package/src/lib/fields/readonly-text/readonly-text.descriptor.ts +12 -0
  121. package/src/lib/fields/readonly-text/readonly-text.ts +58 -0
  122. package/src/lib/fields/relation/relation.descriptor.ts +12 -0
  123. package/src/lib/fields/relation/relation.spec.ts +193 -0
  124. package/src/lib/fields/relation/relation.ts +224 -0
  125. package/src/lib/fields/rich-select/rich-select.descriptor.ts +12 -0
  126. package/src/lib/fields/rich-select/rich-select.ts +175 -0
  127. package/src/lib/fields/select/radio-mode.ts +25 -0
  128. package/src/lib/fields/select/select.descriptor.ts +12 -0
  129. package/src/lib/fields/select/select.spec.ts +162 -0
  130. package/src/lib/fields/select/select.ts +210 -0
  131. package/src/lib/fields/slug/slug.descriptor.ts +19 -0
  132. package/src/lib/fields/slug/slug.ts +67 -0
  133. package/src/lib/fields/string-list/string-list.descriptor.ts +11 -0
  134. package/src/lib/fields/string-list/string-list.ts +222 -0
  135. package/src/lib/fields/text/text.descriptor.ts +12 -0
  136. package/src/lib/fields/text/text.ts +35 -0
  137. package/src/lib/fields/textarea/textarea.descriptor.ts +12 -0
  138. package/src/lib/fields/textarea/textarea.spec.ts +117 -0
  139. package/src/lib/fields/textarea/textarea.ts +126 -0
  140. package/src/lib/fields/time/time.descriptor.ts +12 -0
  141. package/src/lib/fields/time/time.ts +28 -0
  142. package/src/lib/fields/unknown-render/unknown-render.ts +49 -0
  143. package/src/lib/fields/url/url.descriptor.ts +12 -0
  144. package/src/lib/fields/url/url.ts +53 -0
  145. package/src/lib/gas-admin-ui.spec.ts +21 -0
  146. package/src/lib/gas-admin-ui.ts +9 -0
  147. package/src/lib/layouts/descriptors.ts +9 -0
  148. package/src/lib/pages/dashboard/dashboard.ts +167 -0
  149. package/src/lib/pages/detail-view/detail-view.spec.ts +333 -0
  150. package/src/lib/pages/detail-view/detail-view.ts +570 -0
  151. package/src/lib/pages/drawer-form/drawer-form.ts +228 -0
  152. package/src/lib/pages/form-view/form-model.ts +88 -0
  153. package/src/lib/pages/form-view/form-schema.ts +255 -0
  154. package/src/lib/pages/form-view/form-view.ts +1622 -0
  155. package/src/lib/pages/list-view/list-view.formats.spec.ts +214 -0
  156. package/src/lib/pages/list-view/list-view.ts +882 -0
  157. package/src/lib/pages/login/login.spec.ts +109 -0
  158. package/src/lib/pages/login/login.ts +227 -0
  159. package/src/lib/pages/resource-page/resource-page.ts +234 -0
  160. package/src/lib/shared/components/badge/badge.ts +35 -0
  161. package/src/lib/shared/components/button/button.ts +65 -0
  162. package/src/lib/shared/components/confirm-dialog/confirm-dialog.ts +48 -0
  163. package/src/lib/shared/components/copy-button/copy-button.ts +56 -0
  164. package/src/lib/shared/components/copy-share/copy-share.spec.ts +122 -0
  165. package/src/lib/shared/components/copy-share/copy-share.ts +107 -0
  166. package/src/lib/shared/components/drawer/drawer.spec.ts +127 -0
  167. package/src/lib/shared/components/drawer/drawer.ts +172 -0
  168. package/src/lib/shared/components/empty-state/empty-state.ts +30 -0
  169. package/src/lib/shared/components/modal/modal.spec.ts +149 -0
  170. package/src/lib/shared/components/modal/modal.ts +145 -0
  171. package/src/lib/shared/components/post-create-modal/post-create-modal.spec.ts +165 -0
  172. package/src/lib/shared/components/post-create-modal/post-create-modal.ts +159 -0
  173. package/src/lib/shared/components/skeleton/skeleton.ts +31 -0
  174. package/src/lib/shared/components/toast/toast.ts +58 -0
  175. package/src/lib/shared/utils/col-span.ts +25 -0
  176. package/src/lib/shared/utils/condition-evaluator.ts +53 -0
  177. package/src/lib/shared/utils/depends-on.ts +48 -0
  178. package/src/lib/shared/utils/dialog-focus.ts +28 -0
  179. package/src/lib/shared/utils/field-path.ts +49 -0
  180. package/src/lib/shared/utils/gap-sorting.ts +144 -0
  181. package/src/lib/shared/utils/seed.spec.ts +64 -0
  182. package/src/lib/shared/utils/seed.ts +149 -0
  183. package/src/lib/shared/utils/slugify.ts +13 -0
  184. package/src/lib/shared/utils/validators.ts +41 -0
  185. package/src/lib/shell/layout/layout.ts +63 -0
  186. package/src/lib/shell/shell.routes.spec.ts +59 -0
  187. package/src/lib/shell/shell.routes.ts +122 -0
  188. package/src/lib/shell/sidebar/sidebar.ts +139 -0
  189. package/src/lib/shell/theme-toggle/theme-toggle.ts +74 -0
  190. package/src/lib/views/calendar-view/calendar-model.ts +426 -0
  191. package/src/lib/views/calendar-view/calendar-view.spec.ts +557 -0
  192. package/src/lib/views/calendar-view/calendar-view.ts +568 -0
  193. package/src/lib/views/composer/composer-host.spec.ts +301 -0
  194. package/src/lib/views/composer/composer-host.ts +248 -0
  195. package/src/lib/views/composer/composer-imports.spec.ts +54 -0
  196. package/src/lib/views/composer/view-context.spec.ts +117 -0
  197. package/src/lib/views/composer/view-context.ts +109 -0
  198. package/src/lib/views/composer/view-slot.spec.ts +130 -0
  199. package/src/lib/views/composer/view-slot.ts +178 -0
  200. package/src/lib/views/descriptors.ts +46 -0
  201. package/src/lib/views/kanban-view/kanban-model.ts +173 -0
  202. package/src/lib/views/kanban-view/kanban-view.spec.ts +540 -0
  203. package/src/lib/views/kanban-view/kanban-view.ts +327 -0
  204. package/src/lib/widgets/bar-chart/bar-chart.descriptor.ts +17 -0
  205. package/src/lib/widgets/bar-chart/bar-chart.spec.ts +66 -0
  206. package/src/lib/widgets/bar-chart/bar-chart.ts +76 -0
  207. package/src/lib/widgets/chart-line/chart-line.descriptor.ts +17 -0
  208. package/src/lib/widgets/chart-line/chart-line.spec.ts +113 -0
  209. package/src/lib/widgets/chart-line/chart-line.ts +219 -0
  210. package/src/lib/widgets/descriptors.ts +29 -0
  211. package/src/lib/widgets/metric-card/metric-card.descriptor.ts +41 -0
  212. package/src/lib/widgets/metric-card/metric-card.spec.ts +52 -0
  213. package/src/lib/widgets/metric-card/metric-card.ts +48 -0
  214. package/src/lib/widgets/quick-actions/quick-actions.descriptor.ts +13 -0
  215. package/src/lib/widgets/quick-actions/quick-actions.spec.ts +61 -0
  216. package/src/lib/widgets/quick-actions/quick-actions.ts +100 -0
  217. package/src/lib/widgets/record-list/record-list.descriptor.ts +16 -0
  218. package/src/lib/widgets/record-list/record-list.spec.ts +79 -0
  219. package/src/lib/widgets/record-list/record-list.ts +115 -0
  220. package/src/lib/widgets/series.spec.ts +42 -0
  221. package/src/lib/widgets/series.ts +56 -0
  222. package/src/lib/widgets/status-progress/status-progress.descriptor.ts +19 -0
  223. package/src/lib/widgets/status-progress/status-progress.spec.ts +63 -0
  224. package/src/lib/widgets/status-progress/status-progress.ts +104 -0
  225. package/src/lib/widgets/widget-host/widget-host.spec.ts +179 -0
  226. package/src/lib/widgets/widget-host/widget-host.ts +99 -0
  227. package/src/public-api.ts +104 -0
  228. package/tinya-code-gas-admin-ui-0.2.0-alpha.15.tgz +0 -0
  229. package/tsconfig.lib.json +13 -0
  230. package/tsconfig.lib.prod.json +11 -0
  231. package/tsconfig.spec.json +10 -0
  232. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs +0 -84
  233. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs.map +0 -1
  234. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs +0 -140
  235. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs.map +0 -1
  236. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs +0 -113
  237. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs.map +0 -1
  238. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs +0 -163
  239. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs.map +0 -1
  240. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs +0 -1027
  241. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs.map +0 -1
  242. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs +0 -278
  243. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs.map +0 -1
  244. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs +0 -107
  245. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs.map +0 -1
  246. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs +0 -101
  247. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs.map +0 -1
  248. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs +0 -141
  249. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs.map +0 -1
  250. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs +0 -88
  251. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs.map +0 -1
  252. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs +0 -107
  253. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs.map +0 -1
  254. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs +0 -140
  255. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs.map +0 -1
  256. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs +0 -119
  257. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs.map +0 -1
  258. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs +0 -125
  259. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs.map +0 -1
  260. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs +0 -152
  261. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs.map +0 -1
  262. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs +0 -211
  263. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs.map +0 -1
  264. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs +0 -116
  265. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs.map +0 -1
  266. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs +0 -111
  267. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs.map +0 -1
  268. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs +0 -122
  269. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs.map +0 -1
  270. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs +0 -107
  271. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs.map +0 -1
  272. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs +0 -109
  273. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs.map +0 -1
  274. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs +0 -45
  275. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs.map +0 -1
  276. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs +0 -50
  277. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs.map +0 -1
  278. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs +0 -24
  279. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs.map +0 -1
  280. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs +0 -27
  281. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs.map +0 -1
  282. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs +0 -408
  283. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs.map +0 -1
  284. package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs +0 -4516
  285. package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs.map +0 -1
  286. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs +0 -82
  287. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs.map +0 -1
  288. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs +0 -105
  289. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs.map +0 -1
  290. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs +0 -65
  291. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs.map +0 -1
  292. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs +0 -65
  293. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs.map +0 -1
  294. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs +0 -65
  295. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs.map +0 -1
  296. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs +0 -59
  297. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs.map +0 -1
  298. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs +0 -94
  299. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs.map +0 -1
  300. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs +0 -72
  301. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs.map +0 -1
  302. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs +0 -238
  303. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs.map +0 -1
  304. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs +0 -416
  305. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs.map +0 -1
  306. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs +0 -439
  307. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs.map +0 -1
  308. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs +0 -513
  309. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map +0 -1
  310. package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs +0 -637
  311. package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs.map +0 -1
  312. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs +0 -127
  313. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs.map +0 -1
  314. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs +0 -251
  315. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs.map +0 -1
  316. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs +0 -66
  317. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs.map +0 -1
  318. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs +0 -114
  319. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs.map +0 -1
  320. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs +0 -116
  321. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs.map +0 -1
  322. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs +0 -235
  323. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs.map +0 -1
  324. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs +0 -8
  325. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs.map +0 -1
  326. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs +0 -124
  327. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs.map +0 -1
  328. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs +0 -249
  329. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs.map +0 -1
  330. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs +0 -39
  331. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs.map +0 -1
  332. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs +0 -309
  333. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs.map +0 -1
  334. package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs +0 -576
  335. package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs.map +0 -1
  336. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs +0 -161
  337. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs.map +0 -1
  338. package/fesm2022/tinya-code-gas-admin-ui-rolldown-runtime-DpJrqANO.mjs +0 -11
  339. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs +0 -685
  340. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs.map +0 -1
  341. package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs +0 -80
  342. package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs.map +0 -1
  343. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs +0 -296
  344. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs.map +0 -1
  345. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs +0 -119
  346. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs.map +0 -1
  347. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs +0 -158
  348. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs.map +0 -1
  349. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs +0 -26
  350. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs.map +0 -1
  351. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs +0 -205
  352. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs.map +0 -1
  353. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs +0 -432
  354. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs.map +0 -1
  355. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs +0 -36
  356. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs.map +0 -1
  357. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs +0 -107
  358. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs.map +0 -1
  359. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs +0 -223
  360. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs.map +0 -1
  361. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs +0 -107
  362. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs.map +0 -1
  363. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs +0 -60
  364. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs.map +0 -1
  365. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs +0 -141
  366. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs.map +0 -1
  367. package/fesm2022/tinya-code-gas-admin-ui.mjs +0 -4599
  368. package/fesm2022/tinya-code-gas-admin-ui.mjs.map +0 -1
  369. 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
+ }