@tinya-code/gas-admin-ui 0.0.0-stage → 0.1.0-alpha.1

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 (136) hide show
  1. package/README.md +63 -2
  2. package/fesm2022/tinya-code-gas-admin-ui-api.service-CZrUeclM.mjs +281 -0
  3. package/fesm2022/tinya-code-gas-admin-ui-api.service-CZrUeclM.mjs.map +1 -0
  4. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs +84 -0
  5. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs.map +1 -0
  6. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs +140 -0
  7. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs.map +1 -0
  8. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs +113 -0
  9. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs.map +1 -0
  10. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs +163 -0
  11. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs.map +1 -0
  12. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-r-RXDE37.mjs +1022 -0
  13. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-r-RXDE37.mjs.map +1 -0
  14. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs +278 -0
  15. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs.map +1 -0
  16. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-BBzWUuHl.mjs +101 -0
  17. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-BBzWUuHl.mjs.map +1 -0
  18. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs +141 -0
  19. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs.map +1 -0
  20. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-LD8AM3Rn.mjs +89 -0
  21. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-LD8AM3Rn.mjs.map +1 -0
  22. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs +107 -0
  23. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs.map +1 -0
  24. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs +140 -0
  25. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs.map +1 -0
  26. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs +119 -0
  27. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs.map +1 -0
  28. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs +125 -0
  29. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs.map +1 -0
  30. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs +152 -0
  31. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs.map +1 -0
  32. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs +211 -0
  33. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs.map +1 -0
  34. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs +116 -0
  35. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs.map +1 -0
  36. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs +111 -0
  37. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs.map +1 -0
  38. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs +107 -0
  39. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs.map +1 -0
  40. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs +109 -0
  41. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs.map +1 -0
  42. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-Ci0UpXtV.mjs +45 -0
  43. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-Ci0UpXtV.mjs.map +1 -0
  44. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs +50 -0
  45. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs.map +1 -0
  46. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs +24 -0
  47. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs.map +1 -0
  48. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs +27 -0
  49. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs.map +1 -0
  50. package/fesm2022/tinya-code-gas-admin-ui-file-Dg2N3XQ2.mjs +408 -0
  51. package/fesm2022/tinya-code-gas-admin-ui-file-Dg2N3XQ2.mjs.map +1 -0
  52. package/fesm2022/tinya-code-gas-admin-ui-form-view-BwGupSbi.mjs +4514 -0
  53. package/fesm2022/tinya-code-gas-admin-ui-form-view-BwGupSbi.mjs.map +1 -0
  54. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs +82 -0
  55. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs.map +1 -0
  56. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs +105 -0
  57. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs.map +1 -0
  58. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs +65 -0
  59. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs.map +1 -0
  60. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs +65 -0
  61. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs.map +1 -0
  62. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs +65 -0
  63. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs.map +1 -0
  64. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs +59 -0
  65. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs.map +1 -0
  66. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs +94 -0
  67. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs.map +1 -0
  68. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs +72 -0
  69. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs.map +1 -0
  70. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs +238 -0
  71. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs.map +1 -0
  72. package/fesm2022/tinya-code-gas-admin-ui-image-Bjw9ImlS.mjs +416 -0
  73. package/fesm2022/tinya-code-gas-admin-ui-image-Bjw9ImlS.mjs.map +1 -0
  74. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-CeGueI57.mjs +439 -0
  75. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-CeGueI57.mjs.map +1 -0
  76. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs +513 -0
  77. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map +1 -0
  78. package/fesm2022/tinya-code-gas-admin-ui-list-CMzl9MkX.mjs +637 -0
  79. package/fesm2022/tinya-code-gas-admin-ui-list-CMzl9MkX.mjs.map +1 -0
  80. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs +127 -0
  81. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs.map +1 -0
  82. package/fesm2022/tinya-code-gas-admin-ui-multiselect-CuWwAfdY.mjs +251 -0
  83. package/fesm2022/tinya-code-gas-admin-ui-multiselect-CuWwAfdY.mjs.map +1 -0
  84. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs +66 -0
  85. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs.map +1 -0
  86. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs +114 -0
  87. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs.map +1 -0
  88. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs +116 -0
  89. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs.map +1 -0
  90. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs +235 -0
  91. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs.map +1 -0
  92. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs +8 -0
  93. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs.map +1 -0
  94. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs +124 -0
  95. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs.map +1 -0
  96. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs +249 -0
  97. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs.map +1 -0
  98. package/fesm2022/tinya-code-gas-admin-ui-relation-B3W3Ynsp.mjs +309 -0
  99. package/fesm2022/tinya-code-gas-admin-ui-relation-B3W3Ynsp.mjs.map +1 -0
  100. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs +39 -0
  101. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs.map +1 -0
  102. package/fesm2022/tinya-code-gas-admin-ui-render-registry-B_D5Jhp9.mjs +546 -0
  103. package/fesm2022/tinya-code-gas-admin-ui-render-registry-B_D5Jhp9.mjs.map +1 -0
  104. package/fesm2022/tinya-code-gas-admin-ui-rolldown-runtime-DpJrqANO.mjs +11 -0
  105. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-CDrz9pVN.mjs +131 -0
  106. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-CDrz9pVN.mjs.map +1 -0
  107. package/fesm2022/tinya-code-gas-admin-ui-seed-CNbQtREA.mjs +80 -0
  108. package/fesm2022/tinya-code-gas-admin-ui-seed-CNbQtREA.mjs.map +1 -0
  109. package/fesm2022/tinya-code-gas-admin-ui-select-DzaRfHXO.mjs +292 -0
  110. package/fesm2022/tinya-code-gas-admin-ui-select-DzaRfHXO.mjs.map +1 -0
  111. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs +119 -0
  112. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs.map +1 -0
  113. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs +158 -0
  114. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs.map +1 -0
  115. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs +26 -0
  116. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs.map +1 -0
  117. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs +205 -0
  118. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs.map +1 -0
  119. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs +432 -0
  120. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs.map +1 -0
  121. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs +36 -0
  122. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs.map +1 -0
  123. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs +107 -0
  124. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs.map +1 -0
  125. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs +223 -0
  126. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs.map +1 -0
  127. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs +107 -0
  128. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs.map +1 -0
  129. package/fesm2022/tinya-code-gas-admin-ui-upload.service-C1g545w5.mjs +60 -0
  130. package/fesm2022/tinya-code-gas-admin-ui-upload.service-C1g545w5.mjs.map +1 -0
  131. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs +141 -0
  132. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs.map +1 -0
  133. package/fesm2022/tinya-code-gas-admin-ui.mjs +4400 -0
  134. package/fesm2022/tinya-code-gas-admin-ui.mjs.map +1 -0
  135. package/package.json +31 -3
  136. package/types/tinya-code-gas-admin-ui.d.ts +3091 -0
@@ -0,0 +1,513 @@
1
+ import { t as Button } from "./tinya-code-gas-admin-ui-button-BQjNW8KB.mjs";
2
+ import { t as NotificationService } from "./tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs";
3
+ import { n as FieldAria } from "./tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs";
4
+ import { i as listTree, r as itemTree, t as childTree } from "./tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs";
5
+ import { n as appendPosition, r as computeMove, t as GAP } from "./tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs";
6
+ import * as i0 from "@angular/core";
7
+ import { Component, computed, inject, input } from "@angular/core";
8
+ import { LucideArrowDown, LucideArrowUp, LucideGripVertical, LucideTrash2 } from "@lucide/angular";
9
+ import { FormField } from "@angular/forms/signals";
10
+ import { CdkDrag, CdkDragHandle, CdkDropList, moveItemInArray } from "@angular/cdk/drag-drop";
11
+ var FieldKeyValue = class FieldKeyValue {
12
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
13
+ tree = input.required(...ngDevMode ? [{ debugName: "tree" }] : /* istanbul ignore next */ []);
14
+ notifications = inject(NotificationService);
15
+ itemsNode = computed(() => listTree(this.tree(), this.field().key), ...ngDevMode ? [{ debugName: "itemsNode" }] : /* istanbul ignore next */ []);
16
+ state = computed(() => this.itemsNode()(), ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
17
+ idPrefix = computed(() => this.state().name(), ...ngDevMode ? [{ debugName: "idPrefix" }] : /* istanbul ignore next */ []);
18
+ items = computed(() => this.state().value() ?? [], ...ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []);
19
+ sortable = computed(() => this.field().sortable ?? true, ...ngDevMode ? [{ debugName: "sortable" }] : /* istanbul ignore next */ []);
20
+ fieldNode(index, column) {
21
+ return childTree(itemTree(this.itemsNode(), index), column);
22
+ }
23
+ canAdd() {
24
+ const max = this.field().max;
25
+ return max === void 0 || this.items().length < max;
26
+ }
27
+ canRemove() {
28
+ return this.items().length > (this.field().min ?? 0);
29
+ }
30
+ add() {
31
+ if (!this.canAdd()) return;
32
+ const positionKey = this.field().positionField;
33
+ const row = {
34
+ key: "",
35
+ value: ""
36
+ };
37
+ if (positionKey !== void 0) row[positionKey] = appendPosition(this.positioned());
38
+ this.updateItems((next) => {
39
+ next.push(row);
40
+ });
41
+ }
42
+ move(index, direction) {
43
+ const target = index + direction;
44
+ if (target < 0 || target >= this.items().length) return;
45
+ this.applyMove(index, target);
46
+ }
47
+ onDrop(event) {
48
+ if (event.previousIndex === event.currentIndex) return;
49
+ this.applyMove(event.previousIndex, event.currentIndex);
50
+ }
51
+ async remove(index) {
52
+ if (!this.canRemove()) return;
53
+ const row = this.items()[index];
54
+ if (row !== void 0 && (row.key.trim() !== "" || row.value.trim() !== "")) {
55
+ if (!await this.notifications.confirm({
56
+ title: `Eliminar fila ${index + 1}`,
57
+ message: "Esta acción no se puede deshacer.",
58
+ confirmLabel: "Eliminar",
59
+ cancelLabel: "Cancelar"
60
+ })) return;
61
+ }
62
+ this.updateItems((next) => {
63
+ next.splice(index, 1);
64
+ });
65
+ }
66
+ applyMove(from, to) {
67
+ const positionKey = this.field().positionField;
68
+ this.updateItems((next) => {
69
+ if (positionKey !== void 0) {
70
+ const result = computeMove(this.positioned(), String(from), to);
71
+ for (const change of result.changes) {
72
+ const row = next[Number(change.key)];
73
+ if (row !== void 0) row[positionKey] = change.position;
74
+ }
75
+ }
76
+ moveItemInArray(next, from, to);
77
+ });
78
+ }
79
+ positioned() {
80
+ const positionKey = this.field().positionField;
81
+ return this.items().map((item, index) => {
82
+ const raw = positionKey !== void 0 ? item[positionKey] : void 0;
83
+ return {
84
+ key: String(index),
85
+ position: typeof raw === "number" ? raw : (index + 1) * GAP
86
+ };
87
+ });
88
+ }
89
+ updateItems(mutator) {
90
+ this.state().controlValue.update((current) => {
91
+ const next = [...current];
92
+ mutator(next);
93
+ return next;
94
+ });
95
+ }
96
+ static ɵfac = i0.ɵɵngDeclareFactory({
97
+ minVersion: "12.0.0",
98
+ version: "22.2.3",
99
+ ngImport: i0,
100
+ type: FieldKeyValue,
101
+ deps: [],
102
+ target: i0.ɵɵFactoryTarget.Component
103
+ });
104
+ static ɵcmp = i0.ɵɵngDeclareComponent({
105
+ minVersion: "17.0.0",
106
+ version: "22.2.3",
107
+ type: FieldKeyValue,
108
+ isStandalone: true,
109
+ selector: "app-field-key-value",
110
+ inputs: {
111
+ field: {
112
+ classPropertyName: "field",
113
+ publicName: "field",
114
+ isSignal: true,
115
+ isRequired: true,
116
+ transformFunction: null
117
+ },
118
+ tree: {
119
+ classPropertyName: "tree",
120
+ publicName: "tree",
121
+ isSignal: true,
122
+ isRequired: true,
123
+ transformFunction: null
124
+ }
125
+ },
126
+ ngImport: i0,
127
+ template: `
128
+ @if (items().length === 0) {
129
+ <p
130
+ class="rounded-lg border border-dashed border-neutral/30 px-4 py-6 text-center text-sm text-neutral"
131
+ >
132
+ {{ field().emptyText ?? 'Sin elementos.' }}
133
+ </p>
134
+ } @else {
135
+ <div class="overflow-x-auto rounded-xl border border-neutral/20 bg-surface">
136
+ <table class="w-full text-sm">
137
+ <thead>
138
+ <tr class="border-b border-neutral/20 text-left text-xs font-medium text-neutral">
139
+ <th class="w-10 px-3 py-2" scope="col"><span class="sr-only">Orden</span></th>
140
+ <th class="px-3 py-2" scope="col">Clave</th>
141
+ <th class="px-3 py-2" scope="col">Valor</th>
142
+ <th class="w-28 px-3 py-2" scope="col"><span class="sr-only">Acciones</span></th>
143
+ </tr>
144
+ </thead>
145
+ <tbody
146
+ cdkDropList
147
+ [cdkDropListData]="items()"
148
+ [cdkDropListDisabled]="!sortable()"
149
+ (cdkDropListDropped)="onDrop($event)"
150
+ >
151
+ @for (item of items(); track $index; let i = $index) {
152
+ <tr
153
+ class="border-b border-neutral/10 last:border-b-0"
154
+ cdkDrag
155
+ [cdkDragDisabled]="!sortable()"
156
+ >
157
+ <td class="px-3 py-2 align-middle">
158
+ @if (sortable()) {
159
+ <button
160
+ type="button"
161
+ app-button
162
+ variant="ghost"
163
+ size="icon"
164
+ class="cursor-grab"
165
+ cdkDragHandle
166
+ [attr.aria-label]="'Reordenar fila ' + (i + 1)"
167
+ title="Arrastrar para reordenar"
168
+ >
169
+ <svg lucideGripVertical size="16" />
170
+ </button>
171
+ }
172
+ </td>
173
+ <td class="px-3 py-2">
174
+ <input
175
+ class="field-input"
176
+ type="text"
177
+ placeholder="Clave"
178
+ [attr.aria-label]="'Clave, fila ' + (i + 1)"
179
+ [id]="idPrefix() + '-key-' + i"
180
+ [formField]="fieldNode(i, 'key')"
181
+ />
182
+ </td>
183
+ <td class="px-3 py-2">
184
+ <input
185
+ class="field-input"
186
+ type="text"
187
+ placeholder="Valor"
188
+ [attr.aria-label]="'Valor, fila ' + (i + 1)"
189
+ [id]="idPrefix() + '-value-' + i"
190
+ [formField]="fieldNode(i, 'value')"
191
+ />
192
+ </td>
193
+ <td class="px-3 py-2">
194
+ <span class="flex items-center justify-end gap-2 lg:gap-1">
195
+ <button
196
+ type="button"
197
+ app-button
198
+ variant="ghost"
199
+ size="icon"
200
+ [disabled]="i === 0"
201
+ [attr.aria-label]="'Subir fila ' + (i + 1)"
202
+ (click)="move(i, -1)"
203
+ >
204
+ <svg lucideArrowUp size="16" />
205
+ </button>
206
+ <button
207
+ type="button"
208
+ app-button
209
+ variant="ghost"
210
+ size="icon"
211
+ [disabled]="i === items().length - 1"
212
+ [attr.aria-label]="'Bajar fila ' + (i + 1)"
213
+ (click)="move(i, 1)"
214
+ >
215
+ <svg lucideArrowDown size="16" />
216
+ </button>
217
+ <button
218
+ type="button"
219
+ app-button
220
+ variant="ghost"
221
+ size="icon"
222
+ [disabled]="!canRemove()"
223
+ [attr.aria-label]="'Eliminar fila ' + (i + 1)"
224
+ (click)="remove(i)"
225
+ >
226
+ <svg lucideTrash2 size="16" />
227
+ </button>
228
+ </span>
229
+ </td>
230
+ </tr>
231
+ }
232
+ </tbody>
233
+ </table>
234
+ </div>
235
+ }
236
+
237
+ <div class="mt-3">
238
+ <button app-button variant="outline" type="button" [disabled]="!canAdd()" (click)="add()">
239
+ + {{ field().addLabel ?? 'Agregar especificación' }}
240
+ </button>
241
+ </div>
242
+ `,
243
+ isInline: true,
244
+ dependencies: [
245
+ {
246
+ kind: "directive",
247
+ type: FieldAria,
248
+ selector: "input[id], select[id], textarea[id], output[id]"
249
+ },
250
+ {
251
+ kind: "component",
252
+ type: Button,
253
+ selector: "button[app-button]",
254
+ inputs: [
255
+ "variant",
256
+ "size",
257
+ "type",
258
+ "disabled",
259
+ "loading"
260
+ ]
261
+ },
262
+ {
263
+ kind: "directive",
264
+ type: CdkDrag,
265
+ selector: "[cdkDrag]",
266
+ inputs: [
267
+ "cdkDragData",
268
+ "cdkDragLockAxis",
269
+ "cdkDragRootElement",
270
+ "cdkDragBoundary",
271
+ "cdkDragStartDelay",
272
+ "cdkDragFreeDragPosition",
273
+ "cdkDragDisabled",
274
+ "cdkDragConstrainPosition",
275
+ "cdkDragPreviewClass",
276
+ "cdkDragPreviewContainer",
277
+ "cdkDragScale"
278
+ ],
279
+ outputs: [
280
+ "cdkDragStarted",
281
+ "cdkDragReleased",
282
+ "cdkDragEnded",
283
+ "cdkDragEntered",
284
+ "cdkDragExited",
285
+ "cdkDragDropped",
286
+ "cdkDragMoved"
287
+ ],
288
+ exportAs: ["cdkDrag"]
289
+ },
290
+ {
291
+ kind: "directive",
292
+ type: CdkDragHandle,
293
+ selector: "[cdkDragHandle]",
294
+ inputs: ["cdkDragHandleDisabled"]
295
+ },
296
+ {
297
+ kind: "directive",
298
+ type: CdkDropList,
299
+ selector: "[cdkDropList], cdk-drop-list",
300
+ inputs: [
301
+ "cdkDropListConnectedTo",
302
+ "cdkDropListData",
303
+ "cdkDropListOrientation",
304
+ "id",
305
+ "cdkDropListLockAxis",
306
+ "cdkDropListDisabled",
307
+ "cdkDropListSortingDisabled",
308
+ "cdkDropListEnterPredicate",
309
+ "cdkDropListSortPredicate",
310
+ "cdkDropListAutoScrollDisabled",
311
+ "cdkDropListAutoScrollStep",
312
+ "cdkDropListElementContainer",
313
+ "cdkDropListHasAnchor"
314
+ ],
315
+ outputs: [
316
+ "cdkDropListDropped",
317
+ "cdkDropListEntered",
318
+ "cdkDropListExited",
319
+ "cdkDropListSorted"
320
+ ],
321
+ exportAs: ["cdkDropList"]
322
+ },
323
+ {
324
+ kind: "directive",
325
+ type: FormField,
326
+ selector: "[formField]",
327
+ inputs: ["formField"],
328
+ exportAs: ["formField"]
329
+ },
330
+ {
331
+ kind: "component",
332
+ type: LucideArrowDown,
333
+ selector: "svg[lucideArrowDown]"
334
+ },
335
+ {
336
+ kind: "component",
337
+ type: LucideArrowUp,
338
+ selector: "svg[lucideArrowUp]"
339
+ },
340
+ {
341
+ kind: "component",
342
+ type: LucideGripVertical,
343
+ selector: "svg[lucideGripVertical]"
344
+ },
345
+ {
346
+ kind: "component",
347
+ type: LucideTrash2,
348
+ selector: "svg[lucideTrash], svg[lucideTrash2]"
349
+ }
350
+ ]
351
+ });
352
+ };
353
+ i0.ɵɵngDeclareClassMetadata({
354
+ minVersion: "12.0.0",
355
+ version: "22.2.3",
356
+ ngImport: i0,
357
+ type: FieldKeyValue,
358
+ decorators: [{
359
+ type: Component,
360
+ args: [{
361
+ selector: "app-field-key-value",
362
+ imports: [
363
+ FieldAria,
364
+ Button,
365
+ CdkDrag,
366
+ CdkDragHandle,
367
+ CdkDropList,
368
+ FormField,
369
+ LucideArrowDown,
370
+ LucideArrowUp,
371
+ LucideGripVertical,
372
+ LucideTrash2
373
+ ],
374
+ template: `
375
+ @if (items().length === 0) {
376
+ <p
377
+ class="rounded-lg border border-dashed border-neutral/30 px-4 py-6 text-center text-sm text-neutral"
378
+ >
379
+ {{ field().emptyText ?? 'Sin elementos.' }}
380
+ </p>
381
+ } @else {
382
+ <div class="overflow-x-auto rounded-xl border border-neutral/20 bg-surface">
383
+ <table class="w-full text-sm">
384
+ <thead>
385
+ <tr class="border-b border-neutral/20 text-left text-xs font-medium text-neutral">
386
+ <th class="w-10 px-3 py-2" scope="col"><span class="sr-only">Orden</span></th>
387
+ <th class="px-3 py-2" scope="col">Clave</th>
388
+ <th class="px-3 py-2" scope="col">Valor</th>
389
+ <th class="w-28 px-3 py-2" scope="col"><span class="sr-only">Acciones</span></th>
390
+ </tr>
391
+ </thead>
392
+ <tbody
393
+ cdkDropList
394
+ [cdkDropListData]="items()"
395
+ [cdkDropListDisabled]="!sortable()"
396
+ (cdkDropListDropped)="onDrop($event)"
397
+ >
398
+ @for (item of items(); track $index; let i = $index) {
399
+ <tr
400
+ class="border-b border-neutral/10 last:border-b-0"
401
+ cdkDrag
402
+ [cdkDragDisabled]="!sortable()"
403
+ >
404
+ <td class="px-3 py-2 align-middle">
405
+ @if (sortable()) {
406
+ <button
407
+ type="button"
408
+ app-button
409
+ variant="ghost"
410
+ size="icon"
411
+ class="cursor-grab"
412
+ cdkDragHandle
413
+ [attr.aria-label]="'Reordenar fila ' + (i + 1)"
414
+ title="Arrastrar para reordenar"
415
+ >
416
+ <svg lucideGripVertical size="16" />
417
+ </button>
418
+ }
419
+ </td>
420
+ <td class="px-3 py-2">
421
+ <input
422
+ class="field-input"
423
+ type="text"
424
+ placeholder="Clave"
425
+ [attr.aria-label]="'Clave, fila ' + (i + 1)"
426
+ [id]="idPrefix() + '-key-' + i"
427
+ [formField]="fieldNode(i, 'key')"
428
+ />
429
+ </td>
430
+ <td class="px-3 py-2">
431
+ <input
432
+ class="field-input"
433
+ type="text"
434
+ placeholder="Valor"
435
+ [attr.aria-label]="'Valor, fila ' + (i + 1)"
436
+ [id]="idPrefix() + '-value-' + i"
437
+ [formField]="fieldNode(i, 'value')"
438
+ />
439
+ </td>
440
+ <td class="px-3 py-2">
441
+ <span class="flex items-center justify-end gap-2 lg:gap-1">
442
+ <button
443
+ type="button"
444
+ app-button
445
+ variant="ghost"
446
+ size="icon"
447
+ [disabled]="i === 0"
448
+ [attr.aria-label]="'Subir fila ' + (i + 1)"
449
+ (click)="move(i, -1)"
450
+ >
451
+ <svg lucideArrowUp size="16" />
452
+ </button>
453
+ <button
454
+ type="button"
455
+ app-button
456
+ variant="ghost"
457
+ size="icon"
458
+ [disabled]="i === items().length - 1"
459
+ [attr.aria-label]="'Bajar fila ' + (i + 1)"
460
+ (click)="move(i, 1)"
461
+ >
462
+ <svg lucideArrowDown size="16" />
463
+ </button>
464
+ <button
465
+ type="button"
466
+ app-button
467
+ variant="ghost"
468
+ size="icon"
469
+ [disabled]="!canRemove()"
470
+ [attr.aria-label]="'Eliminar fila ' + (i + 1)"
471
+ (click)="remove(i)"
472
+ >
473
+ <svg lucideTrash2 size="16" />
474
+ </button>
475
+ </span>
476
+ </td>
477
+ </tr>
478
+ }
479
+ </tbody>
480
+ </table>
481
+ </div>
482
+ }
483
+
484
+ <div class="mt-3">
485
+ <button app-button variant="outline" type="button" [disabled]="!canAdd()" (click)="add()">
486
+ + {{ field().addLabel ?? 'Agregar especificación' }}
487
+ </button>
488
+ </div>
489
+ `
490
+ }]
491
+ }],
492
+ propDecorators: {
493
+ field: [{
494
+ type: i0.Input,
495
+ args: [{
496
+ isSignal: true,
497
+ alias: "field",
498
+ required: true
499
+ }]
500
+ }],
501
+ tree: [{
502
+ type: i0.Input,
503
+ args: [{
504
+ isSignal: true,
505
+ alias: "tree",
506
+ required: true
507
+ }]
508
+ }]
509
+ }
510
+ });
511
+ export { FieldKeyValue };
512
+
513
+ //# sourceMappingURL=tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs","names":[],"sources":["../../../projects/gas-admin-ui/src/lib/fields/key-value/key-value.ts"],"sourcesContent":["import { Component, computed, inject, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport {\n CdkDrag,\n CdkDragDrop,\n CdkDragHandle,\n CdkDropList,\n moveItemInArray,\n} from '@angular/cdk/drag-drop';\n\nimport { LucideArrowDown, LucideArrowUp, LucideGripVertical, LucideTrash2 } from '@lucide/angular';\nimport type { KeyValueField, KeyValueItem } from '../../core/models/schema.model';\nimport { NotificationService } from '../../core/services/notification.service';\nimport { Button } from '../../shared/components/button/button';\nimport {\n appendPosition,\n computeMove,\n GAP,\n type PositionedItem,\n} from '../../shared/utils/gap-sorting';\nimport { FieldAria } from '../field-aria';\nimport { childTree, itemTree, listTree, type RootTree } from '../field-node';\n\n/**\n * Pares clave→valor (base.md §9 «ficha técnica»). Hoja: tabla con sus\n * propios `<input [formField]>` (nodos `key`/`value` del ítem) y no toca\n * FieldHost. `position` se calcula con gap-sorting igual que en `list`.\n */\n@Component({\n selector: 'app-field-key-value',\n imports: [\n FieldAria,\n Button,\n CdkDrag,\n CdkDragHandle,\n CdkDropList,\n FormField,\n LucideArrowDown,\n LucideArrowUp,\n LucideGripVertical,\n LucideTrash2,\n ],\n template: `\n @if (items().length === 0) {\n <p\n class=\"rounded-lg border border-dashed border-neutral/30 px-4 py-6 text-center text-sm text-neutral\"\n >\n {{ field().emptyText ?? 'Sin elementos.' }}\n </p>\n } @else {\n <div class=\"overflow-x-auto rounded-xl border border-neutral/20 bg-surface\">\n <table class=\"w-full text-sm\">\n <thead>\n <tr class=\"border-b border-neutral/20 text-left text-xs font-medium text-neutral\">\n <th class=\"w-10 px-3 py-2\" scope=\"col\"><span class=\"sr-only\">Orden</span></th>\n <th class=\"px-3 py-2\" scope=\"col\">Clave</th>\n <th class=\"px-3 py-2\" scope=\"col\">Valor</th>\n <th class=\"w-28 px-3 py-2\" scope=\"col\"><span class=\"sr-only\">Acciones</span></th>\n </tr>\n </thead>\n <tbody\n cdkDropList\n [cdkDropListData]=\"items()\"\n [cdkDropListDisabled]=\"!sortable()\"\n (cdkDropListDropped)=\"onDrop($event)\"\n >\n @for (item of items(); track $index; let i = $index) {\n <tr\n class=\"border-b border-neutral/10 last:border-b-0\"\n cdkDrag\n [cdkDragDisabled]=\"!sortable()\"\n >\n <td class=\"px-3 py-2 align-middle\">\n @if (sortable()) {\n <button\n type=\"button\"\n app-button\n variant=\"ghost\"\n size=\"icon\"\n class=\"cursor-grab\"\n cdkDragHandle\n [attr.aria-label]=\"'Reordenar fila ' + (i + 1)\"\n title=\"Arrastrar para reordenar\"\n >\n <svg lucideGripVertical size=\"16\" />\n </button>\n }\n </td>\n <td class=\"px-3 py-2\">\n <input\n class=\"field-input\"\n type=\"text\"\n placeholder=\"Clave\"\n [attr.aria-label]=\"'Clave, fila ' + (i + 1)\"\n [id]=\"idPrefix() + '-key-' + i\"\n [formField]=\"fieldNode(i, 'key')\"\n />\n </td>\n <td class=\"px-3 py-2\">\n <input\n class=\"field-input\"\n type=\"text\"\n placeholder=\"Valor\"\n [attr.aria-label]=\"'Valor, fila ' + (i + 1)\"\n [id]=\"idPrefix() + '-value-' + i\"\n [formField]=\"fieldNode(i, 'value')\"\n />\n </td>\n <td class=\"px-3 py-2\">\n <span class=\"flex items-center justify-end gap-2 lg:gap-1\">\n <button\n type=\"button\"\n app-button\n variant=\"ghost\"\n size=\"icon\"\n [disabled]=\"i === 0\"\n [attr.aria-label]=\"'Subir fila ' + (i + 1)\"\n (click)=\"move(i, -1)\"\n >\n <svg lucideArrowUp size=\"16\" />\n </button>\n <button\n type=\"button\"\n app-button\n variant=\"ghost\"\n size=\"icon\"\n [disabled]=\"i === items().length - 1\"\n [attr.aria-label]=\"'Bajar fila ' + (i + 1)\"\n (click)=\"move(i, 1)\"\n >\n <svg lucideArrowDown size=\"16\" />\n </button>\n <button\n type=\"button\"\n app-button\n variant=\"ghost\"\n size=\"icon\"\n [disabled]=\"!canRemove()\"\n [attr.aria-label]=\"'Eliminar fila ' + (i + 1)\"\n (click)=\"remove(i)\"\n >\n <svg lucideTrash2 size=\"16\" />\n </button>\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <div class=\"mt-3\">\n <button app-button variant=\"outline\" type=\"button\" [disabled]=\"!canAdd()\" (click)=\"add()\">\n + {{ field().addLabel ?? 'Agregar especificación' }}\n </button>\n </div>\n `,\n})\nexport class FieldKeyValue {\n readonly field = input.required<KeyValueField>();\n readonly tree = input.required<RootTree>();\n\n private readonly notifications = inject(NotificationService);\n\n private readonly itemsNode = computed(() =>\n listTree<KeyValueItem>(this.tree(), this.field().key),\n );\n private readonly state = computed(() => this.itemsNode()());\n /** Prefijo estable del campo para los id de cada celda (§8). */\n protected readonly idPrefix = computed(() => this.state().name());\n protected readonly items = computed(() => this.state().value() ?? []);\n\n protected readonly sortable = computed(() => this.field().sortable ?? true);\n\n /** Nodo de `key`/`value` del ítem; se llama fresco en cada render (NG01904). */\n protected fieldNode(\n index: number,\n column: 'key' | 'value',\n ): ReturnType<typeof childTree<string>> {\n return childTree<string>(itemTree(this.itemsNode(), index), column);\n }\n\n protected canAdd(): boolean {\n const max = this.field().max;\n return max === undefined || this.items().length < max;\n }\n\n protected canRemove(): boolean {\n return this.items().length > (this.field().min ?? 0);\n }\n\n protected add(): void {\n if (!this.canAdd()) {\n return;\n }\n const positionKey = this.field().positionField;\n const row: KeyValueItem & Record<string, unknown> = { key: '', value: '' };\n if (positionKey !== undefined) {\n row[positionKey] = appendPosition(this.positioned());\n }\n this.updateItems((next) => {\n next.push(row);\n });\n }\n\n protected move(index: number, direction: -1 | 1): void {\n const target = index + direction;\n if (target < 0 || target >= this.items().length) {\n return;\n }\n this.applyMove(index, target);\n }\n\n protected onDrop(event: CdkDragDrop<KeyValueItem[]>): void {\n if (event.previousIndex === event.currentIndex) {\n return;\n }\n this.applyMove(event.previousIndex, event.currentIndex);\n }\n\n protected async remove(index: number): Promise<void> {\n if (!this.canRemove()) {\n return;\n }\n const row = this.items()[index];\n if (row !== undefined && (row.key.trim() !== '' || row.value.trim() !== '')) {\n const accepted = await this.notifications.confirm({\n title: `Eliminar fila ${index + 1}`,\n message: 'Esta acción no se puede deshacer.',\n confirmLabel: 'Eliminar',\n cancelLabel: 'Cancelar',\n });\n if (!accepted) {\n return;\n }\n }\n this.updateItems((next) => {\n next.splice(index, 1);\n });\n }\n\n /** Mueve y recalcula `position` (base.md §8): cambios antes del splice. */\n private applyMove(from: number, to: number): void {\n const positionKey = this.field().positionField;\n this.updateItems((next) => {\n if (positionKey !== undefined) {\n const result = computeMove(this.positioned(), String(from), to);\n for (const change of result.changes) {\n const row = next[Number(change.key)] as\n (KeyValueItem & Record<string, unknown>) | undefined;\n if (row !== undefined) {\n row[positionKey] = change.position;\n }\n }\n }\n moveItemInArray(next, from, to);\n });\n }\n\n private positioned(): PositionedItem[] {\n const positionKey = this.field().positionField;\n return this.items().map((item, index) => {\n const raw =\n positionKey !== undefined\n ? (item as unknown as Record<string, unknown>)[positionKey]\n : undefined;\n // Fallback: un registro viejo sin `position` se numera como rebalanceo.\n return {\n key: String(index),\n position: typeof raw === 'number' ? raw : (index + 1) * GAP,\n };\n });\n }\n\n private updateItems(mutator: (next: KeyValueItem[]) => void): void {\n this.state().controlValue.update((current) => {\n const next = [...current];\n mutator(next);\n return next;\n });\n }\n}\n"],"mappings":"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"}