@erplora/outfitkit 0.1.28 → 0.1.30

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.
package/README.md CHANGED
@@ -439,7 +439,7 @@ npm run build # vite (dist/*.js, outfitkit.js, theme.example.css) + tsc (
439
439
  npm run typecheck # comprobación de tipos sin emitir
440
440
  npm run verify:csp # rechaza eval / new Function en dist (CSP estricta)
441
441
  npm run dev # vite build --watch (showcase en local)
442
- npm run release # release-it: corta una versión (ver docs/RELEASING.md)
442
+ npm run release # release-it a mano (NO hace falta: la CI publica al mergear, ver docs/RELEASING.md)
443
443
  ```
444
444
 
445
445
  Publicación a npm: [`docs/RELEASING.md`](docs/RELEASING.md) (Trusted Publishing / OIDC).
@@ -0,0 +1 @@
1
+ import './ok-data-table.js';
@@ -231,6 +231,9 @@ export declare class OkDataTable extends LitElement {
231
231
  private filterDraft;
232
232
  private panel;
233
233
  private viewMode;
234
+ private isMobile;
235
+ private mq?;
236
+ private static readonly MOBILE_BREAKPOINT;
234
237
  private hiddenKeys;
235
238
  private internalSelection;
236
239
  private menuOpen;
@@ -52,6 +52,22 @@ export interface OkFmQuota {
52
52
  /** Modo de visualización del área de archivos. */
53
53
  export type OkFmView = 'grid' | 'list';
54
54
  /** Textos i18n del componente (defaults en español). */
55
+ /**
56
+ * Qué se puede hacer en la carpeta actual. La decide el HOST (en ERPlora, el módulo dueño de la
57
+ * carpeta — ADR-0172) y el componente solo la obedece al pintar: **no es una barrera de
58
+ * seguridad**, el servidor revalida siempre. Ver y descargar no están aquí porque son siempre
59
+ * posibles: "solo lectura" no significa "no puedes mirar".
60
+ *
61
+ * Ausente ⇒ todo disponible (los consumidores que no la pasan no cambian de comportamiento).
62
+ */
63
+ export interface OkFmPolicy {
64
+ /** Subir ficheros y crear subcarpetas. */
65
+ upload: boolean;
66
+ /** Renombrar ficheros y la propia carpeta. */
67
+ rename: boolean;
68
+ /** Borrar ficheros y la propia carpeta. */
69
+ delete: boolean;
70
+ }
55
71
  export interface OkFmLabels {
56
72
  /** Botón primario de subida. */
57
73
  upload: string;
@@ -73,6 +89,12 @@ export interface OkFmLabels {
73
89
  open: string;
74
90
  /** Botón de nueva carpeta. */
75
91
  newFolder: string;
92
+ /** Acción de renombrar (ficheros y carpetas). */
93
+ rename: string;
94
+ /** Renombrar la carpeta en la que se está. */
95
+ renameFolder: string;
96
+ /** Borrar la carpeta en la que se está (con su contenido). */
97
+ deleteFolder: string;
76
98
  /** Caption del medidor cuando no hay cuota dura. */
77
99
  noLimit: string;
78
100
  }
@@ -96,6 +118,9 @@ export declare class OkFileManager extends LitElement {
96
118
  searchable: boolean;
97
119
  /** Muestra el botón primario de subida y habilita drag&drop. */
98
120
  uploadable: boolean;
121
+ /** Acciones permitidas en la carpeta actual (ver `OkFmPolicy`). Ausente ⇒ todo permitido. */
122
+ policy?: OkFmPolicy;
123
+ private can;
99
124
  /** Muestra esqueletos de carga en lugar del contenido. */
100
125
  loading: boolean;
101
126
  /** Textos i18n (merge sobre los defaults en español). */
@@ -112,6 +137,12 @@ export declare class OkFileManager extends LitElement {
112
137
  private open;
113
138
  private download;
114
139
  private deleteFile;
140
+ /** Renombrar un fichero. Se manda el nombre actual para que el host lo proponga en su diálogo. */
141
+ private renameFile;
142
+ /** Etiqueta de la carpeta actual (para proponerla como nombre al renombrar). */
143
+ private get currentFolderLabel();
144
+ private renameCurrentFolder;
145
+ private deleteCurrentFolder;
115
146
  private createFolder;
116
147
  private changeView;
117
148
  private onSearch;
@@ -131,6 +162,7 @@ export declare class OkFileManager extends LitElement {
131
162
  private renderToolbar;
132
163
  private get iconOpen();
133
164
  private get iconDownload();
165
+ private get iconRename();
134
166
  private get iconDelete();
135
167
  private fileActions;
136
168
  private renderContent;
@@ -0,0 +1 @@
1
+ import './ok-file-manager';
@@ -95,7 +95,7 @@ const ES_LABELS = {
95
95
  recordSingular: "registro",
96
96
  recordPlural: "registros"
97
97
  };
98
- class OkDataTable extends LitElement {
98
+ const _OkDataTable = class _OkDataTable2 extends LitElement {
99
99
  constructor() {
100
100
  super(...arguments);
101
101
  this.columns = [];
@@ -133,6 +133,7 @@ class OkDataTable extends LitElement {
133
133
  this.filterDraft = {};
134
134
  this.panel = "none";
135
135
  this.viewMode = "table";
136
+ this.isMobile = false;
136
137
  this.hiddenKeys = /* @__PURE__ */ new Set();
137
138
  this.internalSelection = /* @__PURE__ */ new Set();
138
139
  this.menuOpen = false;
@@ -379,16 +380,37 @@ class OkDataTable extends LitElement {
379
380
  ion-button { --box-shadow: none; }
380
381
  `;
381
382
  }
383
+ static {
384
+ this.MOBILE_BREAKPOINT = 640;
385
+ }
382
386
  connectedCallback() {
383
387
  super.connectedCallback();
384
388
  if (typeof window !== "undefined") {
385
389
  window.addEventListener("erplora:locale-changed", this.onLocaleChanged);
386
390
  }
391
+ if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
392
+ this.mq = window.matchMedia(`(max-width: ${_OkDataTable2.MOBILE_BREAKPOINT}px)`);
393
+ this.isMobile = this.mq.matches;
394
+ const handler = (e) => {
395
+ const matches = "matches" in e ? e.matches : this.mq?.matches ?? false;
396
+ if (this.isMobile === matches) return;
397
+ this.isMobile = matches;
398
+ if (matches && this.cardViewEnabled) this.viewMode = "cards";
399
+ else if (!matches && this.viewMode === "cards") this.viewMode = "table";
400
+ };
401
+ this.mq.addEventListener("change", handler);
402
+ this._mqHandler = handler;
403
+ }
387
404
  }
388
405
  disconnectedCallback() {
389
406
  if (typeof window !== "undefined") {
390
407
  window.removeEventListener("erplora:locale-changed", this.onLocaleChanged);
391
408
  }
409
+ if (this.mq) {
410
+ const handler = this._mqHandler;
411
+ if (handler) this.mq.removeEventListener("change", handler);
412
+ this.mq = void 0;
413
+ }
392
414
  super.disconnectedCallback();
393
415
  }
394
416
  // ── i18n: idioma del documento ← overrides explícitos de `.labels` ─────────────────────────
@@ -747,8 +769,13 @@ class OkDataTable extends LitElement {
747
769
  // forma robusta de arrancar en tarjetas sin depender de fijar `viewMode` por referencia (que
748
770
  // falla si la tabla monta detrás de un `v-if`/loading y el ref aún es null).
749
771
  firstUpdated() {
750
- if (this.defaultView === "cards" && this.cardViewEnabled) this.viewMode = "cards";
751
- else if (this.defaultView === "table") this.viewMode = "table";
772
+ if (this.isMobile && this.cardViewEnabled) {
773
+ this.viewMode = "cards";
774
+ } else if (this.defaultView === "cards" && this.cardViewEnabled) {
775
+ this.viewMode = "cards";
776
+ } else if (this.defaultView === "table") {
777
+ this.viewMode = "table";
778
+ }
752
779
  }
753
780
  setViewMode(mode) {
754
781
  if (this.viewMode === mode) return;
@@ -1229,154 +1256,158 @@ class OkDataTable extends LitElement {
1229
1256
  </div>
1230
1257
  `;
1231
1258
  }
1232
- }
1259
+ };
1233
1260
  __decorateClass([
1234
1261
  property({ attribute: false })
1235
- ], OkDataTable.prototype, "columns");
1262
+ ], _OkDataTable.prototype, "columns");
1236
1263
  __decorateClass([
1237
1264
  property({ attribute: false })
1238
- ], OkDataTable.prototype, "rows");
1265
+ ], _OkDataTable.prototype, "rows");
1239
1266
  __decorateClass([
1240
1267
  property({ attribute: false })
1241
- ], OkDataTable.prototype, "searchKeys");
1268
+ ], _OkDataTable.prototype, "searchKeys");
1242
1269
  __decorateClass([
1243
1270
  property({ attribute: "row-key-field" })
1244
- ], OkDataTable.prototype, "rowKeyField");
1271
+ ], _OkDataTable.prototype, "rowKeyField");
1245
1272
  __decorateClass([
1246
1273
  property({ attribute: false })
1247
- ], OkDataTable.prototype, "rowKey");
1274
+ ], _OkDataTable.prototype, "rowKey");
1248
1275
  __decorateClass([
1249
1276
  property({ type: Number, attribute: "page-size" })
1250
- ], OkDataTable.prototype, "pageSize");
1277
+ ], _OkDataTable.prototype, "pageSize");
1251
1278
  __decorateClass([
1252
1279
  property({ attribute: "empty-message" })
1253
- ], OkDataTable.prototype, "emptyMessage");
1280
+ ], _OkDataTable.prototype, "emptyMessage");
1254
1281
  __decorateClass([
1255
1282
  property({ attribute: "search-placeholder" })
1256
- ], OkDataTable.prototype, "searchPlaceholder");
1283
+ ], _OkDataTable.prototype, "searchPlaceholder");
1257
1284
  __decorateClass([
1258
1285
  property({ attribute: false })
1259
- ], OkDataTable.prototype, "labels");
1286
+ ], _OkDataTable.prototype, "labels");
1260
1287
  __decorateClass([
1261
1288
  property({ attribute: false })
1262
- ], OkDataTable.prototype, "actions");
1289
+ ], _OkDataTable.prototype, "actions");
1263
1290
  __decorateClass([
1264
1291
  property({ type: Boolean })
1265
- ], OkDataTable.prototype, "addable");
1292
+ ], _OkDataTable.prototype, "addable");
1266
1293
  __decorateClass([
1267
1294
  property({ attribute: false })
1268
- ], OkDataTable.prototype, "pageSizeOptions");
1295
+ ], _OkDataTable.prototype, "pageSizeOptions");
1269
1296
  __decorateClass([
1270
1297
  property({ type: Boolean, reflect: true })
1271
- ], OkDataTable.prototype, "fill");
1298
+ ], _OkDataTable.prototype, "fill");
1272
1299
  __decorateClass([
1273
1300
  property({ type: Boolean, attribute: "column-picker" })
1274
- ], OkDataTable.prototype, "columnPicker");
1301
+ ], _OkDataTable.prototype, "columnPicker");
1275
1302
  __decorateClass([
1276
1303
  property({ type: Boolean })
1277
- ], OkDataTable.prototype, "csv");
1304
+ ], _OkDataTable.prototype, "csv");
1278
1305
  __decorateClass([
1279
1306
  property({ attribute: "csv-name" })
1280
- ], OkDataTable.prototype, "csvName");
1307
+ ], _OkDataTable.prototype, "csvName");
1281
1308
  __decorateClass([
1282
1309
  property({ type: Boolean, attribute: "server-side" })
1283
- ], OkDataTable.prototype, "serverSide");
1310
+ ], _OkDataTable.prototype, "serverSide");
1284
1311
  __decorateClass([
1285
1312
  property({ type: Number })
1286
- ], OkDataTable.prototype, "total");
1313
+ ], _OkDataTable.prototype, "total");
1287
1314
  __decorateClass([
1288
1315
  property({ type: Number })
1289
- ], OkDataTable.prototype, "page");
1316
+ ], _OkDataTable.prototype, "page");
1290
1317
  __decorateClass([
1291
1318
  property({ type: Boolean })
1292
- ], OkDataTable.prototype, "searchable");
1319
+ ], _OkDataTable.prototype, "searchable");
1293
1320
  __decorateClass([
1294
1321
  property({ type: String })
1295
- ], OkDataTable.prototype, "sort");
1322
+ ], _OkDataTable.prototype, "sort");
1296
1323
  __decorateClass([
1297
1324
  property({ attribute: "sort-dir" })
1298
- ], OkDataTable.prototype, "sortDir");
1325
+ ], _OkDataTable.prototype, "sortDir");
1299
1326
  __decorateClass([
1300
1327
  property()
1301
- ], OkDataTable.prototype, "title");
1328
+ ], _OkDataTable.prototype, "title");
1302
1329
  __decorateClass([
1303
1330
  property({ attribute: false })
1304
- ], OkDataTable.prototype, "views");
1331
+ ], _OkDataTable.prototype, "views");
1305
1332
  __decorateClass([
1306
1333
  property({ attribute: "default-view" })
1307
- ], OkDataTable.prototype, "defaultView");
1334
+ ], _OkDataTable.prototype, "defaultView");
1308
1335
  __decorateClass([
1309
1336
  property({ type: Boolean })
1310
- ], OkDataTable.prototype, "exportable");
1337
+ ], _OkDataTable.prototype, "exportable");
1311
1338
  __decorateClass([
1312
1339
  property({ type: Boolean })
1313
- ], OkDataTable.prototype, "importable");
1340
+ ], _OkDataTable.prototype, "importable");
1314
1341
  __decorateClass([
1315
1342
  property({ type: Boolean, attribute: "column-selector" })
1316
- ], OkDataTable.prototype, "columnSelector");
1343
+ ], _OkDataTable.prototype, "columnSelector");
1317
1344
  __decorateClass([
1318
1345
  property({ attribute: false })
1319
- ], OkDataTable.prototype, "pageSizes");
1346
+ ], _OkDataTable.prototype, "pageSizes");
1320
1347
  __decorateClass([
1321
1348
  property({ type: Boolean })
1322
- ], OkDataTable.prototype, "selectable");
1349
+ ], _OkDataTable.prototype, "selectable");
1323
1350
  __decorateClass([
1324
1351
  property({ attribute: false })
1325
- ], OkDataTable.prototype, "selectedKeys");
1352
+ ], _OkDataTable.prototype, "selectedKeys");
1326
1353
  __decorateClass([
1327
1354
  property({ attribute: false })
1328
- ], OkDataTable.prototype, "primaryAction");
1355
+ ], _OkDataTable.prototype, "primaryAction");
1329
1356
  __decorateClass([
1330
1357
  property({ type: Boolean })
1331
- ], OkDataTable.prototype, "inlineFilters");
1358
+ ], _OkDataTable.prototype, "inlineFilters");
1332
1359
  __decorateClass([
1333
1360
  property({ attribute: false })
1334
- ], OkDataTable.prototype, "menuActions");
1361
+ ], _OkDataTable.prototype, "menuActions");
1335
1362
  __decorateClass([
1336
1363
  property({ attribute: false })
1337
- ], OkDataTable.prototype, "cardTitle");
1364
+ ], _OkDataTable.prototype, "cardTitle");
1338
1365
  __decorateClass([
1339
1366
  property({ attribute: false })
1340
- ], OkDataTable.prototype, "cardIcon");
1367
+ ], _OkDataTable.prototype, "cardIcon");
1341
1368
  __decorateClass([
1342
1369
  property({ attribute: false })
1343
- ], OkDataTable.prototype, "renderCard");
1370
+ ], _OkDataTable.prototype, "renderCard");
1371
+ __decorateClass([
1372
+ state()
1373
+ ], _OkDataTable.prototype, "q");
1344
1374
  __decorateClass([
1345
1375
  state()
1346
- ], OkDataTable.prototype, "q");
1376
+ ], _OkDataTable.prototype, "clientPage");
1347
1377
  __decorateClass([
1348
1378
  state()
1349
- ], OkDataTable.prototype, "clientPage");
1379
+ ], _OkDataTable.prototype, "clientPageSize");
1350
1380
  __decorateClass([
1351
1381
  state()
1352
- ], OkDataTable.prototype, "clientPageSize");
1382
+ ], _OkDataTable.prototype, "clientSort");
1353
1383
  __decorateClass([
1354
1384
  state()
1355
- ], OkDataTable.prototype, "clientSort");
1385
+ ], _OkDataTable.prototype, "clientSortDir");
1356
1386
  __decorateClass([
1357
1387
  state()
1358
- ], OkDataTable.prototype, "clientSortDir");
1388
+ ], _OkDataTable.prototype, "clientFilters");
1359
1389
  __decorateClass([
1360
1390
  state()
1361
- ], OkDataTable.prototype, "clientFilters");
1391
+ ], _OkDataTable.prototype, "filterDraft");
1362
1392
  __decorateClass([
1363
1393
  state()
1364
- ], OkDataTable.prototype, "filterDraft");
1394
+ ], _OkDataTable.prototype, "panel");
1365
1395
  __decorateClass([
1366
1396
  state()
1367
- ], OkDataTable.prototype, "panel");
1397
+ ], _OkDataTable.prototype, "viewMode");
1368
1398
  __decorateClass([
1369
1399
  state()
1370
- ], OkDataTable.prototype, "viewMode");
1400
+ ], _OkDataTable.prototype, "isMobile");
1371
1401
  __decorateClass([
1372
1402
  state()
1373
- ], OkDataTable.prototype, "hiddenKeys");
1403
+ ], _OkDataTable.prototype, "hiddenKeys");
1374
1404
  __decorateClass([
1375
1405
  state()
1376
- ], OkDataTable.prototype, "internalSelection");
1406
+ ], _OkDataTable.prototype, "internalSelection");
1377
1407
  __decorateClass([
1378
1408
  state()
1379
- ], OkDataTable.prototype, "menuOpen");
1409
+ ], _OkDataTable.prototype, "menuOpen");
1410
+ let OkDataTable = _OkDataTable;
1380
1411
  define("ok-data-table", OkDataTable);
1381
1412
  export {
1382
1413
  OkDataTable
@@ -22,6 +22,9 @@ const DEFAULT_LABELS = {
22
22
  delete: "Eliminar",
23
23
  open: "Abrir",
24
24
  newFolder: "Nueva carpeta",
25
+ rename: "Renombrar",
26
+ renameFolder: "Renombrar carpeta",
27
+ deleteFolder: "Eliminar carpeta",
25
28
  noLimit: "Sin límite"
26
29
  };
27
30
  class OkFileManager extends LitElement {
@@ -545,6 +548,11 @@ class OkFileManager extends LitElement {
545
548
  .action.danger:hover {
546
549
  color: var(--danger);
547
550
  }
551
+ /* Borrar la carpeta actual: se tiñe al pasar por encima, igual que el borrado de un fichero. */
552
+ .tbtn.danger:hover {
553
+ color: var(--danger);
554
+ border-color: var(--danger);
555
+ }
548
556
  .action svg {
549
557
  width: 15px;
550
558
  height: 15px;
@@ -644,6 +652,9 @@ class OkFileManager extends LitElement {
644
652
  }
645
653
  `;
646
654
  }
655
+ can(action) {
656
+ return this.policy ? this.policy[action] : true;
657
+ }
647
658
  // Textos efectivos.
648
659
  get t() {
649
660
  return { ...DEFAULT_LABELS, ...this.labels };
@@ -671,7 +682,21 @@ class OkFileManager extends LitElement {
671
682
  this.emit("ok-download", { id: file.id, url: file.url });
672
683
  }
673
684
  deleteFile(id) {
674
- this.emit("ok-delete", { id });
685
+ this.emit("ok-delete", { id, kind: "file" });
686
+ }
687
+ /** Renombrar un fichero. Se manda el nombre actual para que el host lo proponga en su diálogo. */
688
+ renameFile(file) {
689
+ this.emit("ok-rename", { id: file.id, name: file.name, kind: "file" });
690
+ }
691
+ /** Etiqueta de la carpeta actual (para proponerla como nombre al renombrar). */
692
+ get currentFolderLabel() {
693
+ return this.path[this.path.length - 1]?.label ?? this.selected.split("/").pop() ?? "";
694
+ }
695
+ renameCurrentFolder() {
696
+ this.emit("ok-rename", { id: this.selected, name: this.currentFolderLabel, kind: "folder" });
697
+ }
698
+ deleteCurrentFolder() {
699
+ this.emit("ok-delete", { id: this.selected, kind: "folder" });
675
700
  }
676
701
  createFolder() {
677
702
  this.emit("ok-create-folder", { parent: this.selected });
@@ -877,23 +902,47 @@ class OkFileManager extends LitElement {
877
902
  </button>
878
903
  </div>
879
904
 
880
- <button
881
- type="button"
882
- class="tbtn icon"
883
- aria-label=${this.t.newFolder}
884
- title=${this.t.newFolder}
885
- @click=${() => this.createFolder()}
886
- >
887
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
888
- stroke-linecap="round" stroke-linejoin="round">
889
- <path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
890
- <path d="M12 11v6M9 14h6" />
891
- </svg>
892
- </button>
905
+ ${this.selected && this.can("rename") ? html`<button
906
+ type="button"
907
+ class="tbtn icon"
908
+ data-act="rename-folder"
909
+ aria-label=${this.t.renameFolder}
910
+ title=${this.t.renameFolder}
911
+ @click=${() => this.renameCurrentFolder()}
912
+ >
913
+ ${this.iconRename}
914
+ </button>` : ""}
915
+
916
+ ${this.selected && this.can("delete") ? html`<button
917
+ type="button"
918
+ class="tbtn icon danger"
919
+ data-act="delete-folder"
920
+ aria-label=${this.t.deleteFolder}
921
+ title=${this.t.deleteFolder}
922
+ @click=${() => this.deleteCurrentFolder()}
923
+ >
924
+ ${this.iconDelete}
925
+ </button>` : ""}
926
+
927
+ ${this.can("upload") ? html`<button
928
+ type="button"
929
+ class="tbtn icon"
930
+ data-act="new-folder"
931
+ aria-label=${this.t.newFolder}
932
+ title=${this.t.newFolder}
933
+ @click=${() => this.createFolder()}
934
+ >
935
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
936
+ stroke-linecap="round" stroke-linejoin="round">
937
+ <path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
938
+ <path d="M12 11v6M9 14h6" />
939
+ </svg>
940
+ </button>` : ""}
893
941
 
894
- ${this.uploadable ? html`<button
942
+ ${this.uploadable && this.can("upload") ? html`<button
895
943
  type="button"
896
944
  class="tbtn primary icon"
945
+ data-act="upload"
897
946
  aria-label=${this.t.upload}
898
947
  title=${this.t.upload}
899
948
  @click=${() => this.openPicker()}
@@ -920,17 +969,25 @@ class OkFileManager extends LitElement {
920
969
  <polyline points="7 10 12 15 17 10" /><line x1="12" y1="15" x2="12" y2="3" />
921
970
  </svg>`;
922
971
  }
972
+ get iconRename() {
973
+ return html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
974
+ stroke-linecap="round" stroke-linejoin="round">
975
+ <path d="M12 20h9" /><path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z" />
976
+ </svg>`;
977
+ }
923
978
  get iconDelete() {
924
979
  return html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
925
980
  stroke-linecap="round" stroke-linejoin="round">
926
981
  <path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
927
982
  </svg>`;
928
983
  }
929
- // Acciones de un archivo (abrir/descargar/eliminar), reutilizadas en grid y lista.
984
+ // Acciones de un archivo, reutilizadas en grid y lista. Abrir y descargar SIEMPRE se ofrecen;
985
+ // renombrar y borrar solo si la política de la carpeta los concede.
930
986
  fileActions(file) {
931
987
  return html`<button
932
988
  type="button"
933
989
  class="action"
990
+ data-act="open"
934
991
  aria-label=${this.t.open}
935
992
  title=${this.t.open}
936
993
  @click=${(e) => {
@@ -943,6 +1000,7 @@ class OkFileManager extends LitElement {
943
1000
  <button
944
1001
  type="button"
945
1002
  class="action"
1003
+ data-act="download"
946
1004
  aria-label=${this.t.download}
947
1005
  title=${this.t.download}
948
1006
  @click=${(e) => {
@@ -952,18 +1010,32 @@ class OkFileManager extends LitElement {
952
1010
  >
953
1011
  ${this.iconDownload}
954
1012
  </button>
955
- <button
956
- type="button"
957
- class="action danger"
958
- aria-label=${this.t.delete}
959
- title=${this.t.delete}
960
- @click=${(e) => {
1013
+ ${this.can("rename") ? html`<button
1014
+ type="button"
1015
+ class="action"
1016
+ data-act="rename-file"
1017
+ aria-label=${this.t.rename}
1018
+ title=${this.t.rename}
1019
+ @click=${(e) => {
1020
+ e.stopPropagation();
1021
+ this.renameFile(file);
1022
+ }}
1023
+ >
1024
+ ${this.iconRename}
1025
+ </button>` : ""}
1026
+ ${this.can("delete") ? html`<button
1027
+ type="button"
1028
+ class="action danger"
1029
+ data-act="delete-file"
1030
+ aria-label=${this.t.delete}
1031
+ title=${this.t.delete}
1032
+ @click=${(e) => {
961
1033
  e.stopPropagation();
962
1034
  this.deleteFile(file.id);
963
1035
  }}
964
- >
965
- ${this.iconDelete}
966
- </button>`;
1036
+ >
1037
+ ${this.iconDelete}
1038
+ </button>` : ""}`;
967
1039
  }
968
1040
  // ---- Render del contenido (grid/lista/vacío/loading) ----
969
1041
  renderContent() {
@@ -1096,6 +1168,9 @@ __decorateClass([
1096
1168
  __decorateClass([
1097
1169
  property({ type: Boolean })
1098
1170
  ], OkFileManager.prototype, "uploadable");
1171
+ __decorateClass([
1172
+ property({ attribute: false })
1173
+ ], OkFileManager.prototype, "policy");
1099
1174
  __decorateClass([
1100
1175
  property({ type: Boolean })
1101
1176
  ], OkFileManager.prototype, "loading");