@zentto/studio 0.8.4 → 0.9.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.
- package/dist/designer/zs-app-wizard.d.ts +0 -6
- package/dist/designer/zs-app-wizard.d.ts.map +1 -1
- package/dist/designer/zs-app-wizard.js +22 -180
- package/dist/designer/zs-app-wizard.js.map +1 -1
- package/dist/designer/zs-page-designer.d.ts +31 -15
- package/dist/designer/zs-page-designer.d.ts.map +1 -1
- package/dist/designer/zs-page-designer.js +239 -365
- package/dist/designer/zs-page-designer.js.map +1 -1
- package/dist/fields/zs-field-datagrid.d.ts +0 -3
- package/dist/fields/zs-field-datagrid.d.ts.map +1 -1
- package/dist/fields/zs-field-datagrid.js +10 -31
- package/dist/fields/zs-field-datagrid.js.map +1 -1
- package/package.json +1 -1
|
@@ -66,6 +66,10 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
66
66
|
this.provider = {};
|
|
67
67
|
this.autoSaveMs = 1000;
|
|
68
68
|
this.gridSnap = 1;
|
|
69
|
+
/** API base URL for save/load (e.g. "http://localhost:4000") */
|
|
70
|
+
this.saveApiUrl = '';
|
|
71
|
+
/** Auth token for save/load API */
|
|
72
|
+
this.saveApiToken = '';
|
|
69
73
|
// ─── State ────────────────────────────────────────
|
|
70
74
|
this.selectedFieldId = null;
|
|
71
75
|
this.viewMode = 'design';
|
|
@@ -74,6 +78,17 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
74
78
|
this.editingTitle = false;
|
|
75
79
|
this.collapsedSections = new Set();
|
|
76
80
|
this.zoom = 1;
|
|
81
|
+
// Save/Load state
|
|
82
|
+
this.saveDialogOpen = false;
|
|
83
|
+
this.loadDialogOpen = false;
|
|
84
|
+
this.serverAddons = [];
|
|
85
|
+
this.serverLoading = false;
|
|
86
|
+
this.serverSaving = false;
|
|
87
|
+
this.editingAddonId = null;
|
|
88
|
+
this.saveName = '';
|
|
89
|
+
this.saveDesc = '';
|
|
90
|
+
this.saveIconEmoji = '📋';
|
|
91
|
+
this.saveModules = ['global'];
|
|
77
92
|
// Undo/Redo
|
|
78
93
|
this.undoStack = [];
|
|
79
94
|
this.redoStack = [];
|
|
@@ -88,6 +103,15 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
88
103
|
this.dragSourceSectionIndex = -1;
|
|
89
104
|
this.dragInsertIndex = -1;
|
|
90
105
|
this.dragTargetSectionIndex = -1;
|
|
106
|
+
// ─── Dialog Styles (inline, no shadow DOM issues) ─
|
|
107
|
+
this.dialogOverlay = 'position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,0.4);display:flex;align-items:center;justify-content:center;';
|
|
108
|
+
this.dialogBox = 'background:white;border-radius:12px;width:480px;max-width:90vw;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 20px 60px rgba(0,0,0,0.3);';
|
|
109
|
+
this.dialogHeader = 'padding:16px 20px;border-bottom:1px solid #eee;font-size:16px;font-weight:600;color:#333;display:flex;justify-content:space-between;align-items:center;';
|
|
110
|
+
this.dialogBody = 'padding:16px 20px;overflow-y:auto;flex:1;';
|
|
111
|
+
this.dialogFooter = 'padding:12px 20px;border-top:1px solid #eee;display:flex;gap:8px;justify-content:flex-end;';
|
|
112
|
+
this.inputStyle = 'width:100%;padding:8px 10px;border:1px solid #ddd;border-radius:6px;font-size:13px;font-family:inherit;box-sizing:border-box;';
|
|
113
|
+
this.btnPrimary = 'padding:8px 20px;border:none;border-radius:6px;background:#1976d2;color:white;cursor:pointer;font-size:13px;font-weight:600;font-family:inherit;';
|
|
114
|
+
this.btnSecondary = 'padding:8px 20px;border:1px solid #ddd;border-radius:6px;background:white;cursor:pointer;font-size:13px;font-family:inherit;';
|
|
91
115
|
// ─── API Panel (Data Sources) ──────────────────────
|
|
92
116
|
this.showTemplateMenu = false;
|
|
93
117
|
this.apiSources = [];
|
|
@@ -1147,6 +1171,182 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
1147
1171
|
<div class="panel-resize"></div>
|
|
1148
1172
|
${this.renderRightPanel()}
|
|
1149
1173
|
</div>
|
|
1174
|
+
${this.saveDialogOpen ? this.renderSaveDialog() : nothing}
|
|
1175
|
+
${this.loadDialogOpen ? this.renderLoadDialog() : nothing}
|
|
1176
|
+
`;
|
|
1177
|
+
}
|
|
1178
|
+
// ─── Save/Load Server Methods ─────────────────────
|
|
1179
|
+
getApiHeaders() {
|
|
1180
|
+
const h = { 'Content-Type': 'application/json' };
|
|
1181
|
+
if (this.saveApiToken)
|
|
1182
|
+
h['Authorization'] = `Bearer ${this.saveApiToken}`;
|
|
1183
|
+
else if (this.apiToken)
|
|
1184
|
+
h['Authorization'] = `Bearer ${this.apiToken}`;
|
|
1185
|
+
return h;
|
|
1186
|
+
}
|
|
1187
|
+
getApiBase() {
|
|
1188
|
+
return (this.saveApiUrl || this.apiBaseUrl || '').replace(/\/+$/, '');
|
|
1189
|
+
}
|
|
1190
|
+
openSaveDialog() {
|
|
1191
|
+
if (!this.schema)
|
|
1192
|
+
return;
|
|
1193
|
+
this.saveName = this.saveName || this.schema.title || '';
|
|
1194
|
+
this.saveDialogOpen = true;
|
|
1195
|
+
}
|
|
1196
|
+
async openLoadDialog() {
|
|
1197
|
+
this.loadDialogOpen = true;
|
|
1198
|
+
this.serverLoading = true;
|
|
1199
|
+
try {
|
|
1200
|
+
const base = this.getApiBase();
|
|
1201
|
+
const res = await fetch(`${base}/v1/studio/addons`, { headers: this.getApiHeaders() });
|
|
1202
|
+
const json = await res.json();
|
|
1203
|
+
this.serverAddons = (json.data ?? []).map((r) => ({
|
|
1204
|
+
id: r.AddonId ?? r.id, title: r.Title ?? r.title, icon: r.Icon ?? r.icon ?? '📋',
|
|
1205
|
+
modules: r.modules ?? [], createdAt: r.CreatedAt ?? r.createdAt ?? '',
|
|
1206
|
+
config: r.config ?? (r.Config ? JSON.parse(r.Config) : {}),
|
|
1207
|
+
}));
|
|
1208
|
+
}
|
|
1209
|
+
catch {
|
|
1210
|
+
this.serverAddons = [];
|
|
1211
|
+
}
|
|
1212
|
+
this.serverLoading = false;
|
|
1213
|
+
}
|
|
1214
|
+
async saveToServer() {
|
|
1215
|
+
if (!this.schema || !this.saveName.trim())
|
|
1216
|
+
return;
|
|
1217
|
+
this.serverSaving = true;
|
|
1218
|
+
const base = this.getApiBase();
|
|
1219
|
+
const body = JSON.stringify({
|
|
1220
|
+
title: this.saveName.trim(), description: this.saveDesc.trim(),
|
|
1221
|
+
icon: this.saveIconEmoji || '📋', modules: this.saveModules,
|
|
1222
|
+
config: { type: 'schema', schema: this.schema },
|
|
1223
|
+
});
|
|
1224
|
+
try {
|
|
1225
|
+
if (this.editingAddonId) {
|
|
1226
|
+
await fetch(`${base}/v1/studio/addons/${this.editingAddonId}`, { method: 'PUT', headers: this.getApiHeaders(), body });
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1229
|
+
const res = await fetch(`${base}/v1/studio/addons`, { method: 'POST', headers: this.getApiHeaders(), body });
|
|
1230
|
+
const json = await res.json();
|
|
1231
|
+
if (json.data?.addonId)
|
|
1232
|
+
this.editingAddonId = json.data.addonId;
|
|
1233
|
+
}
|
|
1234
|
+
this.saveDialogOpen = false;
|
|
1235
|
+
}
|
|
1236
|
+
catch (err) {
|
|
1237
|
+
console.error('[designer] save error:', err);
|
|
1238
|
+
}
|
|
1239
|
+
this.serverSaving = false;
|
|
1240
|
+
}
|
|
1241
|
+
loadFromServer(addon) {
|
|
1242
|
+
if (!this.schema)
|
|
1243
|
+
return;
|
|
1244
|
+
const config = addon.config;
|
|
1245
|
+
const s = config?.schema ?? config;
|
|
1246
|
+
this.schema = s;
|
|
1247
|
+
this.undoStack = [JSON.stringify(s)];
|
|
1248
|
+
this.redoStack = [];
|
|
1249
|
+
this.selectedFieldId = null;
|
|
1250
|
+
this.editingAddonId = addon.id;
|
|
1251
|
+
this.saveName = addon.title;
|
|
1252
|
+
this.loadDialogOpen = false;
|
|
1253
|
+
this.emitChange();
|
|
1254
|
+
}
|
|
1255
|
+
async deleteFromServer(id) {
|
|
1256
|
+
const base = this.getApiBase();
|
|
1257
|
+
try {
|
|
1258
|
+
await fetch(`${base}/v1/studio/addons/${id}`, { method: 'DELETE', headers: this.getApiHeaders() });
|
|
1259
|
+
}
|
|
1260
|
+
catch { }
|
|
1261
|
+
this.serverAddons = this.serverAddons.filter(a => a.id !== id);
|
|
1262
|
+
}
|
|
1263
|
+
renderSaveDialog() {
|
|
1264
|
+
const MODS = [
|
|
1265
|
+
{ v: 'global', l: 'Global' }, { v: 'compras', l: 'Compras' }, { v: 'ventas', l: 'Ventas' },
|
|
1266
|
+
{ v: 'inventario', l: 'Inventario' }, { v: 'contabilidad', l: 'Contabilidad' },
|
|
1267
|
+
{ v: 'nomina', l: 'Nómina' }, { v: 'bancos', l: 'Bancos' }, { v: 'crm', l: 'CRM' },
|
|
1268
|
+
];
|
|
1269
|
+
return html `
|
|
1270
|
+
<div style="${this.dialogOverlay}" @click="${(e) => { if (e.target === e.currentTarget)
|
|
1271
|
+
this.saveDialogOpen = false; }}">
|
|
1272
|
+
<div style="${this.dialogBox}" @click="${(e) => e.stopPropagation()}">
|
|
1273
|
+
<div style="${this.dialogHeader}">
|
|
1274
|
+
<span>${this.editingAddonId ? '💾 Actualizar' : '💾 Guardar'} en servidor</span>
|
|
1275
|
+
<button style="border:none;background:none;font-size:18px;cursor:pointer;color:#999;" @click="${() => { this.saveDialogOpen = false; }}">✕</button>
|
|
1276
|
+
</div>
|
|
1277
|
+
<div style="${this.dialogBody}">
|
|
1278
|
+
<div style="margin-bottom:12px;">
|
|
1279
|
+
<label style="font-size:12px;font-weight:600;color:#555;display:block;margin-bottom:4px;">Nombre *</label>
|
|
1280
|
+
<input style="${this.inputStyle}" .value="${this.saveName}" @input="${(e) => { this.saveName = e.target.value; }}" placeholder="Mi formulario" />
|
|
1281
|
+
</div>
|
|
1282
|
+
<div style="margin-bottom:12px;">
|
|
1283
|
+
<label style="font-size:12px;font-weight:600;color:#555;display:block;margin-bottom:4px;">Descripcion</label>
|
|
1284
|
+
<textarea style="${this.inputStyle}resize:vertical;min-height:50px;" .value="${this.saveDesc}" @input="${(e) => { this.saveDesc = e.target.value; }}"></textarea>
|
|
1285
|
+
</div>
|
|
1286
|
+
<div style="display:flex;gap:12px;margin-bottom:12px;">
|
|
1287
|
+
<div>
|
|
1288
|
+
<label style="font-size:12px;font-weight:600;color:#555;display:block;margin-bottom:4px;">Icono</label>
|
|
1289
|
+
<input style="${this.inputStyle}width:60px;font-size:20px;text-align:center;" .value="${this.saveIconEmoji}" maxlength="4" @input="${(e) => { this.saveIconEmoji = e.target.value; }}" />
|
|
1290
|
+
</div>
|
|
1291
|
+
</div>
|
|
1292
|
+
<div>
|
|
1293
|
+
<label style="font-size:12px;font-weight:600;color:#555;display:block;margin-bottom:6px;">Modulos donde aparece</label>
|
|
1294
|
+
<div style="display:flex;flex-wrap:wrap;gap:6px;">
|
|
1295
|
+
${MODS.map(m => {
|
|
1296
|
+
const active = this.saveModules.includes(m.v);
|
|
1297
|
+
return html `<button style="padding:4px 10px;border:1px solid ${active ? '#1976d2' : '#ddd'};border-radius:14px;background:${active ? '#e3f2fd' : 'white'};color:${active ? '#1976d2' : '#666'};cursor:pointer;font-size:11px;font-family:inherit;font-weight:${active ? '600' : '400'};"
|
|
1298
|
+
@click="${() => { this.saveModules = active ? this.saveModules.filter(x => x !== m.v) : [...this.saveModules, m.v]; this.requestUpdate(); }}"
|
|
1299
|
+
>${m.l}</button>`;
|
|
1300
|
+
})}
|
|
1301
|
+
</div>
|
|
1302
|
+
</div>
|
|
1303
|
+
</div>
|
|
1304
|
+
<div style="${this.dialogFooter}">
|
|
1305
|
+
<button style="${this.btnSecondary}" @click="${() => { this.saveDialogOpen = false; }}">Cancelar</button>
|
|
1306
|
+
<button style="${this.btnPrimary}${!this.saveName.trim() || this.serverSaving ? 'opacity:0.5;pointer-events:none;' : ''}" @click="${this.saveToServer}">
|
|
1307
|
+
${this.serverSaving ? '⏳ Guardando...' : this.editingAddonId ? '💾 Actualizar' : '💾 Guardar'}
|
|
1308
|
+
</button>
|
|
1309
|
+
</div>
|
|
1310
|
+
</div>
|
|
1311
|
+
</div>
|
|
1312
|
+
`;
|
|
1313
|
+
}
|
|
1314
|
+
renderLoadDialog() {
|
|
1315
|
+
return html `
|
|
1316
|
+
<div style="${this.dialogOverlay}" @click="${(e) => { if (e.target === e.currentTarget)
|
|
1317
|
+
this.loadDialogOpen = false; }}">
|
|
1318
|
+
<div style="${this.dialogBox}max-height:70vh;" @click="${(e) => e.stopPropagation()}">
|
|
1319
|
+
<div style="${this.dialogHeader}">
|
|
1320
|
+
<span>📂 Cargar desde servidor</span>
|
|
1321
|
+
<button style="border:none;background:none;font-size:18px;cursor:pointer;color:#999;" @click="${() => { this.loadDialogOpen = false; }}">✕</button>
|
|
1322
|
+
</div>
|
|
1323
|
+
<div style="${this.dialogBody}">
|
|
1324
|
+
${this.serverLoading
|
|
1325
|
+
? html `<div style="text-align:center;padding:30px;color:#999;">⏳ Cargando...</div>`
|
|
1326
|
+
: this.serverAddons.length === 0
|
|
1327
|
+
? html `<div style="text-align:center;padding:30px;color:#999;">No hay schemas guardados en el servidor.</div>`
|
|
1328
|
+
: this.serverAddons.map(a => html `
|
|
1329
|
+
<div style="display:flex;align-items:center;gap:10px;padding:10px 8px;border-bottom:1px solid #f0f0f0;cursor:pointer;border-radius:6px;transition:background 0.1s;"
|
|
1330
|
+
@mouseover="${(e) => { e.currentTarget.style.background = '#f5f5f5'; }}"
|
|
1331
|
+
@mouseout="${(e) => { e.currentTarget.style.background = ''; }}"
|
|
1332
|
+
@click="${() => this.loadFromServer(a)}"
|
|
1333
|
+
>
|
|
1334
|
+
<span style="font-size:22px;">${a.icon}</span>
|
|
1335
|
+
<div style="flex:1;min-width:0;">
|
|
1336
|
+
<div style="font-size:13px;font-weight:600;color:#333;">${a.title}</div>
|
|
1337
|
+
<div style="font-size:10px;color:#999;">${a.modules.join(', ')} — ${a.createdAt ? new Date(a.createdAt).toLocaleDateString() : ''}</div>
|
|
1338
|
+
</div>
|
|
1339
|
+
<button style="border:none;background:none;cursor:pointer;color:#d32f2f;font-size:14px;padding:4px;" title="Eliminar"
|
|
1340
|
+
@click="${(e) => { e.stopPropagation(); this.deleteFromServer(a.id); }}"
|
|
1341
|
+
>🗑</button>
|
|
1342
|
+
</div>
|
|
1343
|
+
`)}
|
|
1344
|
+
</div>
|
|
1345
|
+
<div style="${this.dialogFooter}">
|
|
1346
|
+
<button style="${this.btnSecondary}" @click="${() => { this.loadDialogOpen = false; }}">Cerrar</button>
|
|
1347
|
+
</div>
|
|
1348
|
+
</div>
|
|
1349
|
+
</div>
|
|
1150
1350
|
`;
|
|
1151
1351
|
}
|
|
1152
1352
|
// ─── Toolbar ──────────────────────────────────────
|
|
@@ -1197,6 +1397,8 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
1197
1397
|
|
|
1198
1398
|
<span class="tb-spacer"></span>
|
|
1199
1399
|
|
|
1400
|
+
<button class="tb-btn" style="color:#2e7d32;font-weight:600;" @click="${this.openSaveDialog}" title="Guardar en servidor">💾 Guardar</button>
|
|
1401
|
+
<button class="tb-btn" @click="${this.openLoadDialog}" title="Cargar desde servidor">📂 Cargar</button>
|
|
1200
1402
|
<button class="tb-btn" @click="${() => {
|
|
1201
1403
|
if (this.schema) {
|
|
1202
1404
|
navigator.clipboard.writeText(JSON.stringify(this.schema, null, 2));
|
|
@@ -1385,7 +1587,7 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
1385
1587
|
if (field.type === 'heading')
|
|
1386
1588
|
return field.label ?? 'Titulo';
|
|
1387
1589
|
if (field.type === 'datagrid')
|
|
1388
|
-
return
|
|
1590
|
+
return '◫ ZenttoDataGrid';
|
|
1389
1591
|
if (field.type === 'report')
|
|
1390
1592
|
return '◫ ZenttoReportViewer';
|
|
1391
1593
|
if (field.type === 'chart')
|
|
@@ -1406,34 +1608,6 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
1406
1608
|
return '▸ Nodo 1\n ▸ Nodo 2';
|
|
1407
1609
|
return field.placeholder ?? field.type;
|
|
1408
1610
|
}
|
|
1409
|
-
/** Render live datagrid inside canvas — props update in real time */
|
|
1410
|
-
renderLiveDataGrid(field) {
|
|
1411
|
-
const p = field.props ?? {};
|
|
1412
|
-
const rawEp = p.endpoint || '';
|
|
1413
|
-
// Build full URL: if relative path and we have apiBaseUrl, prepend it
|
|
1414
|
-
const ep = rawEp && !rawEp.startsWith('http') && this.apiBaseUrl
|
|
1415
|
-
? `${this.apiBaseUrl.replace(/\/+$/, '')}${rawEp.startsWith('/') ? '' : '/'}${rawEp}`
|
|
1416
|
-
: rawEp;
|
|
1417
|
-
const headers = {};
|
|
1418
|
-
if (this.apiToken) {
|
|
1419
|
-
headers['Authorization'] = `Bearer ${this.apiToken}`;
|
|
1420
|
-
if (this.apiCompany)
|
|
1421
|
-
headers['x-empresa'] = this.apiCompany;
|
|
1422
|
-
if (this.apiBranch)
|
|
1423
|
-
headers['x-sucursal'] = this.apiBranch;
|
|
1424
|
-
}
|
|
1425
|
-
return html `
|
|
1426
|
-
<zs-field-datagrid
|
|
1427
|
-
.config="${field}"
|
|
1428
|
-
.endpoint="${ep}"
|
|
1429
|
-
.authToken="${this.apiToken}"
|
|
1430
|
-
.authHeaders="${headers}"
|
|
1431
|
-
.designMode="${true}"
|
|
1432
|
-
.theme="${'light'}"
|
|
1433
|
-
style="display:block;width:100%;min-height:200px;"
|
|
1434
|
-
></zs-field-datagrid>
|
|
1435
|
-
`;
|
|
1436
|
-
}
|
|
1437
1611
|
// ─── Right Panel (Properties — Figma-quality) ──────
|
|
1438
1612
|
renderRightPanel() {
|
|
1439
1613
|
const field = this.selectedField;
|
|
@@ -1567,345 +1741,9 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
|
|
|
1567
1741
|
` : ''}
|
|
1568
1742
|
` : ''}
|
|
1569
1743
|
</div>
|
|
1570
|
-
|
|
1571
|
-
<!-- Type-specific props -->
|
|
1572
|
-
${this.renderTypeSpecificProps(field)}
|
|
1573
|
-
</div>
|
|
1574
|
-
`;
|
|
1575
|
-
}
|
|
1576
|
-
// ─── Type-Specific Property Panels ────────────────
|
|
1577
|
-
renderTypeSpecificProps(field) {
|
|
1578
|
-
switch (field.type) {
|
|
1579
|
-
case 'datagrid': return this.renderDataGridProps(field);
|
|
1580
|
-
case 'chart': return this.renderChartProps(field);
|
|
1581
|
-
case 'report': return this.renderReportProps(field);
|
|
1582
|
-
case 'select':
|
|
1583
|
-
case 'multiselect':
|
|
1584
|
-
case 'radio': return this.renderSelectProps(field);
|
|
1585
|
-
case 'number':
|
|
1586
|
-
case 'currency':
|
|
1587
|
-
case 'percentage':
|
|
1588
|
-
case 'slider':
|
|
1589
|
-
case 'rating': return this.renderNumberProps(field);
|
|
1590
|
-
case 'lookup': return this.renderLookupProps(field);
|
|
1591
|
-
case 'chips':
|
|
1592
|
-
case 'tags': return this.renderChipsProps(field);
|
|
1593
|
-
case 'treeview': return this.renderTreeViewProps(field);
|
|
1594
|
-
case 'date':
|
|
1595
|
-
case 'time':
|
|
1596
|
-
case 'datetime': return this.renderDateProps(field);
|
|
1597
|
-
case 'file':
|
|
1598
|
-
case 'image': return this.renderFileProps(field);
|
|
1599
|
-
case 'signature': return this.renderSignatureProps(field);
|
|
1600
|
-
default: return nothing;
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
setProp(field, key, value) {
|
|
1604
|
-
if (!field.props)
|
|
1605
|
-
field.props = {};
|
|
1606
|
-
field.props[key] = value;
|
|
1607
|
-
this.commitChange();
|
|
1608
|
-
}
|
|
1609
|
-
// ─── DataGrid Props ───────────────────────────────
|
|
1610
|
-
renderDataGridProps(field) {
|
|
1611
|
-
const p = field.props ?? {};
|
|
1612
|
-
return html `
|
|
1613
|
-
<div class="prop-section">
|
|
1614
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('grid-config')}">
|
|
1615
|
-
<span class="collapse-icon ${this.collapsedSections.has('grid-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1616
|
-
<h4>DataGrid Config</h4>
|
|
1617
|
-
</div>
|
|
1618
|
-
${!this.collapsedSections.has('grid-config') ? html `
|
|
1619
|
-
<div class="prop-info">◫ Conecta un endpoint y el grid cargara los datos en el canvas</div>
|
|
1620
|
-
<div class="prop-row"><span class="prop-label">Altura</span><input class="prop-input" .value="${p.height ?? '400px'}" placeholder="400px" @change="${(e) => this.setProp(field, 'height', e.target.value)}" /></div>
|
|
1621
|
-
<div class="prop-row"><span class="prop-label">Page Size</span><input class="prop-input" type="number" min="5" .value="${String(p.pageSize ?? 25)}" @change="${(e) => this.setProp(field, 'pageSize', parseInt(e.target.value) || 25)}" /></div>
|
|
1622
|
-
<div class="prop-row"><span class="prop-label">Densidad</span>
|
|
1623
|
-
<select class="prop-input" .value="${p.density ?? 'compact'}" @change="${(e) => this.setProp(field, 'density', e.target.value)}">
|
|
1624
|
-
<option value="compact">Compacta</option>
|
|
1625
|
-
<option value="standard">Estandar</option>
|
|
1626
|
-
<option value="comfortable">Comoda</option>
|
|
1627
|
-
</select>
|
|
1628
|
-
</div>
|
|
1629
|
-
<div class="prop-row"><span class="prop-label">Row Click</span>
|
|
1630
|
-
<select class="prop-input" .value="${p.onRowClick ?? 'emit'}" @change="${(e) => this.setProp(field, 'onRowClick', e.target.value)}">
|
|
1631
|
-
<option value="emit">Emitir evento</option>
|
|
1632
|
-
<option value="navigate">Navegar</option>
|
|
1633
|
-
<option value="select">Seleccionar</option>
|
|
1634
|
-
<option value="detail">Detalle</option>
|
|
1635
|
-
</select>
|
|
1636
|
-
</div>
|
|
1637
|
-
${p.onRowClick === 'navigate' ? html `
|
|
1638
|
-
<div class="prop-row"><span class="prop-label">Nav Segment</span><input class="prop-input" .value="${p.rowClickSegment ?? ''}" placeholder="/clientes/{id}" @change="${(e) => this.setProp(field, 'rowClickSegment', e.target.value)}" /></div>
|
|
1639
|
-
` : ''}
|
|
1640
|
-
<div class="prop-divider"></div>
|
|
1641
|
-
${this.renderToggle('Toolbar', p.enableToolbar ?? true, (v) => this.setProp(field, 'enableToolbar', v))}
|
|
1642
|
-
${this.renderToggle('Busqueda', p.enableSearch ?? true, (v) => this.setProp(field, 'enableSearch', v))}
|
|
1643
|
-
${this.renderToggle('Exportar', p.enableExport ?? false, (v) => this.setProp(field, 'enableExport', v))}
|
|
1644
|
-
${this.renderToggle('Paginacion', p.enablePagination ?? true, (v) => this.setProp(field, 'enablePagination', v))}
|
|
1645
|
-
${this.renderToggle('Filtros Header', p.enableHeaderFilters ?? false, (v) => this.setProp(field, 'enableHeaderFilters', v))}
|
|
1646
|
-
${this.renderToggle('Clipboard', p.enableClipboard ?? false, (v) => this.setProp(field, 'enableClipboard', v))}
|
|
1647
|
-
${this.renderToggle('Seleccion Filas', p.enableRowSelection ?? false, (v) => this.setProp(field, 'enableRowSelection', v))}
|
|
1648
|
-
${this.renderToggle('Master-Detail', p.enableMasterDetail ?? false, (v) => this.setProp(field, 'enableMasterDetail', v))}
|
|
1649
|
-
${this.renderToggle('Totales', p.showTotals ?? false, (v) => this.setProp(field, 'showTotals', v))}
|
|
1650
|
-
${this.renderToggle('Context Menu', p.enableContextMenu ?? false, (v) => this.setProp(field, 'enableContextMenu', v))}
|
|
1651
|
-
${this.renderToggle('Find (Ctrl+F)', p.enableFind ?? false, (v) => this.setProp(field, 'enableFind', v))}
|
|
1652
|
-
${this.renderToggle('Status Bar', p.enableStatusBar ?? false, (v) => this.setProp(field, 'enableStatusBar', v))}
|
|
1653
|
-
${this.renderToggle('Filter Panel', p.enableFilterPanel ?? false, (v) => this.setProp(field, 'enableFilterPanel', v))}
|
|
1654
|
-
${this.renderToggle('Configurador', p.enableConfigurator ?? false, (v) => this.setProp(field, 'enableConfigurator', v))}
|
|
1655
|
-
<div class="prop-divider"></div>
|
|
1656
|
-
<div class="prop-row"><span class="prop-label">Moneda</span><input class="prop-input" .value="${p.defaultCurrency ?? ''}" placeholder="USD, VES, EUR..." @change="${(e) => this.setProp(field, 'defaultCurrency', e.target.value)}" /></div>
|
|
1657
|
-
<div class="prop-row"><span class="prop-label">Archivo Export</span><input class="prop-input" .value="${p.exportFilename ?? ''}" placeholder="clientes" @change="${(e) => this.setProp(field, 'exportFilename', e.target.value)}" /></div>
|
|
1658
|
-
<div class="prop-row"><span class="prop-label">Grid ID</span><input class="prop-input" style="font-family:'SF Mono','Consolas',monospace;font-size:10px;" .value="${p.gridId ?? ''}" placeholder="clientes-grid" @change="${(e) => this.setProp(field, 'gridId', e.target.value)}" /></div>
|
|
1659
|
-
` : ''}
|
|
1660
|
-
</div>
|
|
1661
|
-
`;
|
|
1662
|
-
}
|
|
1663
|
-
// ─── Chart Props ──────────────────────────────────
|
|
1664
|
-
renderChartProps(field) {
|
|
1665
|
-
const p = field.props ?? {};
|
|
1666
|
-
return html `
|
|
1667
|
-
<div class="prop-section">
|
|
1668
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('chart-config')}">
|
|
1669
|
-
<span class="collapse-icon ${this.collapsedSections.has('chart-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1670
|
-
<h4>Chart Config</h4>
|
|
1671
|
-
</div>
|
|
1672
|
-
${!this.collapsedSections.has('chart-config') ? html `
|
|
1673
|
-
<div class="prop-info">📊 Configuracion del grafico SVG</div>
|
|
1674
|
-
<div class="prop-row"><span class="prop-label">Tipo</span>
|
|
1675
|
-
<select class="prop-input" .value="${p.chartType ?? 'bar'}" @change="${(e) => this.setProp(field, 'chartType', e.target.value)}">
|
|
1676
|
-
<option value="bar">Barras</option>
|
|
1677
|
-
<option value="line">Lineas</option>
|
|
1678
|
-
<option value="pie">Torta</option>
|
|
1679
|
-
<option value="donut">Donut</option>
|
|
1680
|
-
<option value="area">Area</option>
|
|
1681
|
-
</select>
|
|
1682
|
-
</div>
|
|
1683
|
-
<div class="prop-row"><span class="prop-label">Titulo</span><input class="prop-input" .value="${p.chartTitle ?? ''}" placeholder="Ventas por Mes" @change="${(e) => this.setProp(field, 'chartTitle', e.target.value)}" /></div>
|
|
1684
|
-
<div class="prop-row"><span class="prop-label">Label Field</span><input class="prop-input" .value="${p.labelField ?? ''}" placeholder="mes" @change="${(e) => this.setProp(field, 'labelField', e.target.value)}" /></div>
|
|
1685
|
-
<div class="prop-row"><span class="prop-label">Value Field</span><input class="prop-input" .value="${p.valueField ?? ''}" placeholder="total" @change="${(e) => this.setProp(field, 'valueField', e.target.value)}" /></div>
|
|
1686
|
-
<div class="prop-divider"></div>
|
|
1687
|
-
<div class="prop-pos-grid">
|
|
1688
|
-
<div class="prop-pos-cell">
|
|
1689
|
-
<span class="prop-pos-label prop-pos-label--w">W</span>
|
|
1690
|
-
<input type="number" min="100" .value="${String(p.width ?? 400)}" @change="${(e) => this.setProp(field, 'width', parseInt(e.target.value) || 400)}" />
|
|
1691
|
-
</div>
|
|
1692
|
-
<div class="prop-pos-cell">
|
|
1693
|
-
<span class="prop-pos-label prop-pos-label--h">H</span>
|
|
1694
|
-
<input type="number" min="100" .value="${String(p.height ?? 250)}" @change="${(e) => this.setProp(field, 'height', parseInt(e.target.value) || 250)}" />
|
|
1695
|
-
</div>
|
|
1696
|
-
</div>
|
|
1697
|
-
<div class="prop-divider"></div>
|
|
1698
|
-
${this.renderToggle('Leyenda', p.showLegend ?? true, (v) => this.setProp(field, 'showLegend', v))}
|
|
1699
|
-
${this.renderToggle('Animacion', p.animated ?? false, (v) => this.setProp(field, 'animated', v))}
|
|
1700
|
-
` : ''}
|
|
1701
1744
|
</div>
|
|
1702
1745
|
`;
|
|
1703
1746
|
}
|
|
1704
|
-
// ─── Report Props ─────────────────────────────────
|
|
1705
|
-
renderReportProps(field) {
|
|
1706
|
-
const p = field.props ?? {};
|
|
1707
|
-
return html `
|
|
1708
|
-
<div class="prop-section">
|
|
1709
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('report-config')}">
|
|
1710
|
-
<span class="collapse-icon ${this.collapsedSections.has('report-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1711
|
-
<h4>Report Config</h4>
|
|
1712
|
-
</div>
|
|
1713
|
-
${!this.collapsedSections.has('report-config') ? html `
|
|
1714
|
-
<div class="prop-info">📋 Configuracion de zentto-report</div>
|
|
1715
|
-
<div class="prop-row"><span class="prop-label">Template ID</span><input class="prop-input" .value="${p.templateId ?? ''}" placeholder="invoice-template" @change="${(e) => this.setProp(field, 'templateId', e.target.value)}" /></div>
|
|
1716
|
-
<div class="prop-row"><span class="prop-label">Zoom</span><input class="prop-input" type="number" min="25" max="300" step="25" .value="${String(p.zoom ?? 100)}" @change="${(e) => this.setProp(field, 'zoom', parseInt(e.target.value) || 100)}" /></div>
|
|
1717
|
-
<div class="prop-row"><span class="prop-label">Altura</span><input class="prop-input" .value="${p.height ?? '500px'}" placeholder="500px" @change="${(e) => this.setProp(field, 'height', e.target.value)}" /></div>
|
|
1718
|
-
<div class="prop-divider"></div>
|
|
1719
|
-
${this.renderToggle('Toolbar', p.showToolbar ?? true, (v) => this.setProp(field, 'showToolbar', v))}
|
|
1720
|
-
${this.renderToggle('Imprimir', p.showPrint ?? true, (v) => this.setProp(field, 'showPrint', v))}
|
|
1721
|
-
${this.renderToggle('Exportar PDF', p.showExportPdf ?? true, (v) => this.setProp(field, 'showExportPdf', v))}
|
|
1722
|
-
${this.renderToggle('Navegacion', p.showNavigation ?? true, (v) => this.setProp(field, 'showNavigation', v))}
|
|
1723
|
-
` : ''}
|
|
1724
|
-
</div>
|
|
1725
|
-
`;
|
|
1726
|
-
}
|
|
1727
|
-
// ─── Select/Radio Props ───────────────────────────
|
|
1728
|
-
renderSelectProps(field) {
|
|
1729
|
-
const p = field.props ?? {};
|
|
1730
|
-
const options = p.options ?? [];
|
|
1731
|
-
return html `
|
|
1732
|
-
<div class="prop-section">
|
|
1733
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('select-config')}">
|
|
1734
|
-
<span class="collapse-icon ${this.collapsedSections.has('select-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1735
|
-
<h4>Opciones</h4>
|
|
1736
|
-
</div>
|
|
1737
|
-
${!this.collapsedSections.has('select-config') ? html `
|
|
1738
|
-
${options.map((opt, i) => html `
|
|
1739
|
-
<div style="display:flex;gap:3px;margin-bottom:3px;align-items:center;">
|
|
1740
|
-
<input class="prop-input" style="flex:1;" .value="${opt.value}" placeholder="valor" @change="${(e) => { options[i].value = e.target.value; this.setProp(field, 'options', [...options]); }}" />
|
|
1741
|
-
<input class="prop-input" style="flex:1;" .value="${opt.label}" placeholder="label" @change="${(e) => { options[i].label = e.target.value; this.setProp(field, 'options', [...options]); }}" />
|
|
1742
|
-
<button style="border:none;background:none;cursor:pointer;color:#d32f2f;font-size:12px;padding:2px 4px;" @click="${() => { options.splice(i, 1); this.setProp(field, 'options', [...options]); }}">✕</button>
|
|
1743
|
-
</div>
|
|
1744
|
-
`)}
|
|
1745
|
-
<button style="width:100%;padding:4px;border:1px dashed #ccc;border-radius:4px;background:none;cursor:pointer;font-size:10px;color:#888;font-family:inherit;margin-top:4px;"
|
|
1746
|
-
@click="${() => { options.push({ value: '', label: '' }); this.setProp(field, 'options', [...options]); }}"
|
|
1747
|
-
>+ Agregar opcion</button>
|
|
1748
|
-
${field.type === 'radio' ? html `
|
|
1749
|
-
<div class="prop-divider"></div>
|
|
1750
|
-
${this.renderToggle('Horizontal', p.horizontal ?? false, (v) => this.setProp(field, 'horizontal', v))}
|
|
1751
|
-
` : ''}
|
|
1752
|
-
${field.type === 'multiselect' ? html `
|
|
1753
|
-
<div class="prop-divider"></div>
|
|
1754
|
-
${this.renderToggle('Multiple', true, () => { })}
|
|
1755
|
-
` : ''}
|
|
1756
|
-
` : ''}
|
|
1757
|
-
</div>
|
|
1758
|
-
`;
|
|
1759
|
-
}
|
|
1760
|
-
// ─── Number/Currency/Slider/Rating Props ──────────
|
|
1761
|
-
renderNumberProps(field) {
|
|
1762
|
-
const p = field.props ?? {};
|
|
1763
|
-
return html `
|
|
1764
|
-
<div class="prop-section">
|
|
1765
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('number-config')}">
|
|
1766
|
-
<span class="collapse-icon ${this.collapsedSections.has('number-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1767
|
-
<h4>Numero Config</h4>
|
|
1768
|
-
</div>
|
|
1769
|
-
${!this.collapsedSections.has('number-config') ? html `
|
|
1770
|
-
${field.type === 'currency' ? html `
|
|
1771
|
-
<div class="prop-row"><span class="prop-label">Simbolo</span><input class="prop-input" .value="${p.currencySymbol ?? '$'}" @change="${(e) => this.setProp(field, 'currencySymbol', e.target.value)}" /></div>
|
|
1772
|
-
` : ''}
|
|
1773
|
-
${field.type === 'slider' || field.type === 'rating' ? html `
|
|
1774
|
-
<div class="prop-pos-grid">
|
|
1775
|
-
<div class="prop-pos-cell">
|
|
1776
|
-
<span class="prop-pos-label prop-pos-label--x">Min</span>
|
|
1777
|
-
<input type="number" .value="${String(p.min ?? 0)}" @change="${(e) => this.setProp(field, 'min', parseInt(e.target.value) || 0)}" />
|
|
1778
|
-
</div>
|
|
1779
|
-
<div class="prop-pos-cell">
|
|
1780
|
-
<span class="prop-pos-label prop-pos-label--y">Max</span>
|
|
1781
|
-
<input type="number" .value="${String(p.max ?? (field.type === 'rating' ? 5 : 100))}" @change="${(e) => this.setProp(field, 'max', parseInt(e.target.value) || 100)}" />
|
|
1782
|
-
</div>
|
|
1783
|
-
</div>
|
|
1784
|
-
${field.type === 'slider' ? html `
|
|
1785
|
-
<div class="prop-row"><span class="prop-label">Step</span><input class="prop-input" type="number" min="1" .value="${String(p.step ?? 1)}" @change="${(e) => this.setProp(field, 'step', parseInt(e.target.value) || 1)}" /></div>
|
|
1786
|
-
` : ''}
|
|
1787
|
-
${field.type === 'rating' ? html `
|
|
1788
|
-
<div class="prop-row"><span class="prop-label">Estrellas</span><input class="prop-input" type="number" min="3" max="10" .value="${String(p.maxRating ?? 5)}" @change="${(e) => this.setProp(field, 'maxRating', parseInt(e.target.value) || 5)}" /></div>
|
|
1789
|
-
` : ''}
|
|
1790
|
-
` : ''}
|
|
1791
|
-
` : ''}
|
|
1792
|
-
</div>
|
|
1793
|
-
`;
|
|
1794
|
-
}
|
|
1795
|
-
// ─── Lookup Props ─────────────────────────────────
|
|
1796
|
-
renderLookupProps(field) {
|
|
1797
|
-
const p = field.props ?? {};
|
|
1798
|
-
return html `
|
|
1799
|
-
<div class="prop-section">
|
|
1800
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('lookup-config')}">
|
|
1801
|
-
<span class="collapse-icon ${this.collapsedSections.has('lookup-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1802
|
-
<h4>Lookup Config</h4>
|
|
1803
|
-
</div>
|
|
1804
|
-
${!this.collapsedSections.has('lookup-config') ? html `
|
|
1805
|
-
<div class="prop-row"><span class="prop-label">Min Chars</span><input class="prop-input" type="number" min="1" .value="${String(p.minChars ?? 2)}" @change="${(e) => this.setProp(field, 'minChars', parseInt(e.target.value) || 2)}" /></div>
|
|
1806
|
-
<div class="prop-row"><span class="prop-label">Debounce</span><input class="prop-input" type="number" min="100" step="100" .value="${String(p.debounceMs ?? 300)}" @change="${(e) => this.setProp(field, 'debounceMs', parseInt(e.target.value) || 300)}" /></div>
|
|
1807
|
-
` : ''}
|
|
1808
|
-
</div>
|
|
1809
|
-
`;
|
|
1810
|
-
}
|
|
1811
|
-
// ─── Chips/Tags Props ─────────────────────────────
|
|
1812
|
-
renderChipsProps(field) {
|
|
1813
|
-
const p = field.props ?? {};
|
|
1814
|
-
return html `
|
|
1815
|
-
<div class="prop-section">
|
|
1816
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('chips-config')}">
|
|
1817
|
-
<span class="collapse-icon ${this.collapsedSections.has('chips-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1818
|
-
<h4>Chips Config</h4>
|
|
1819
|
-
</div>
|
|
1820
|
-
${!this.collapsedSections.has('chips-config') ? html `
|
|
1821
|
-
<div class="prop-row"><span class="prop-label">Max Chips</span><input class="prop-input" type="number" min="0" .value="${String(p.maxChips ?? 0)}" @change="${(e) => this.setProp(field, 'maxChips', parseInt(e.target.value) || 0)}" /></div>
|
|
1822
|
-
<div class="prop-row"><span class="prop-label">Color Mode</span>
|
|
1823
|
-
<select class="prop-input" .value="${p.colorMode ?? 'default'}" @change="${(e) => this.setProp(field, 'colorMode', e.target.value)}">
|
|
1824
|
-
<option value="default">Default</option>
|
|
1825
|
-
<option value="primary">Primary</option>
|
|
1826
|
-
<option value="success">Success</option>
|
|
1827
|
-
<option value="auto">Auto (ciclo)</option>
|
|
1828
|
-
</select>
|
|
1829
|
-
</div>
|
|
1830
|
-
${this.renderToggle('Permitir custom', p.allowCustom ?? true, (v) => this.setProp(field, 'allowCustom', v))}
|
|
1831
|
-
${this.renderSelectProps(field)}
|
|
1832
|
-
` : ''}
|
|
1833
|
-
</div>
|
|
1834
|
-
`;
|
|
1835
|
-
}
|
|
1836
|
-
// ─── TreeView Props ───────────────────────────────
|
|
1837
|
-
renderTreeViewProps(field) {
|
|
1838
|
-
const p = field.props ?? {};
|
|
1839
|
-
return html `
|
|
1840
|
-
<div class="prop-section">
|
|
1841
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('tree-config')}">
|
|
1842
|
-
<span class="collapse-icon ${this.collapsedSections.has('tree-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1843
|
-
<h4>TreeView Config</h4>
|
|
1844
|
-
</div>
|
|
1845
|
-
${!this.collapsedSections.has('tree-config') ? html `
|
|
1846
|
-
${this.renderToggle('Multi-select', p.multiSelect ?? false, (v) => this.setProp(field, 'multiSelect', v))}
|
|
1847
|
-
${this.renderToggle('Checkboxes', p.showCheckboxes ?? false, (v) => this.setProp(field, 'showCheckboxes', v))}
|
|
1848
|
-
${this.renderToggle('Buscador', p.searchable ?? false, (v) => this.setProp(field, 'searchable', v))}
|
|
1849
|
-
` : ''}
|
|
1850
|
-
</div>
|
|
1851
|
-
`;
|
|
1852
|
-
}
|
|
1853
|
-
// ─── Date Props ───────────────────────────────────
|
|
1854
|
-
renderDateProps(field) {
|
|
1855
|
-
const p = field.props ?? {};
|
|
1856
|
-
return html `
|
|
1857
|
-
<div class="prop-section">
|
|
1858
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('date-config')}">
|
|
1859
|
-
<span class="collapse-icon ${this.collapsedSections.has('date-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1860
|
-
<h4>Fecha Config</h4>
|
|
1861
|
-
</div>
|
|
1862
|
-
${!this.collapsedSections.has('date-config') ? html `
|
|
1863
|
-
<div class="prop-row"><span class="prop-label">Modo</span>
|
|
1864
|
-
<select class="prop-input" .value="${p.mode ?? 'date'}" @change="${(e) => this.setProp(field, 'mode', e.target.value)}">
|
|
1865
|
-
<option value="date">Fecha</option>
|
|
1866
|
-
<option value="time">Hora</option>
|
|
1867
|
-
<option value="datetime">Fecha y Hora</option>
|
|
1868
|
-
</select>
|
|
1869
|
-
</div>
|
|
1870
|
-
<div class="prop-row"><span class="prop-label">Min</span><input class="prop-input" type="date" .value="${p.min ?? ''}" @change="${(e) => this.setProp(field, 'min', e.target.value)}" /></div>
|
|
1871
|
-
<div class="prop-row"><span class="prop-label">Max</span><input class="prop-input" type="date" .value="${p.max ?? ''}" @change="${(e) => this.setProp(field, 'max', e.target.value)}" /></div>
|
|
1872
|
-
` : ''}
|
|
1873
|
-
</div>
|
|
1874
|
-
`;
|
|
1875
|
-
}
|
|
1876
|
-
// ─── File/Image Props ─────────────────────────────
|
|
1877
|
-
renderFileProps(field) {
|
|
1878
|
-
const p = field.props ?? {};
|
|
1879
|
-
return html `
|
|
1880
|
-
<div class="prop-section">
|
|
1881
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('file-config')}">
|
|
1882
|
-
<span class="collapse-icon ${this.collapsedSections.has('file-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1883
|
-
<h4>Archivo Config</h4>
|
|
1884
|
-
</div>
|
|
1885
|
-
${!this.collapsedSections.has('file-config') ? html `
|
|
1886
|
-
<div class="prop-row"><span class="prop-label">Accept</span><input class="prop-input" .value="${p.accept ?? ''}" placeholder="image/*,.pdf" @change="${(e) => this.setProp(field, 'accept', e.target.value)}" /></div>
|
|
1887
|
-
${this.renderToggle('Multiple', p.multiple ?? false, (v) => this.setProp(field, 'multiple', v))}
|
|
1888
|
-
` : ''}
|
|
1889
|
-
</div>
|
|
1890
|
-
`;
|
|
1891
|
-
}
|
|
1892
|
-
// ─── Signature Props ──────────────────────────────
|
|
1893
|
-
renderSignatureProps(field) {
|
|
1894
|
-
const p = field.props ?? {};
|
|
1895
|
-
return html `
|
|
1896
|
-
<div class="prop-section">
|
|
1897
|
-
<div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('sig-config')}">
|
|
1898
|
-
<span class="collapse-icon ${this.collapsedSections.has('sig-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
|
|
1899
|
-
<h4>Firma Config</h4>
|
|
1900
|
-
</div>
|
|
1901
|
-
${!this.collapsedSections.has('sig-config') ? html `
|
|
1902
|
-
<div class="prop-row"><span class="prop-label">Grosor</span><input class="prop-input" type="number" min="1" max="10" .value="${String(p.penWidth ?? 2)}" @change="${(e) => this.setProp(field, 'penWidth', parseInt(e.target.value) || 2)}" /></div>
|
|
1903
|
-
<div class="prop-row"><span class="prop-label">Color</span><input class="prop-input" type="color" .value="${p.penColor ?? '#000000'}" @change="${(e) => this.setProp(field, 'penColor', e.target.value)}" /></div>
|
|
1904
|
-
` : ''}
|
|
1905
|
-
</div>
|
|
1906
|
-
`;
|
|
1907
|
-
}
|
|
1908
|
-
// ─── Grid Configurator Modal ────────────────────
|
|
1909
1747
|
renderFormProperties() {
|
|
1910
1748
|
if (!this.schema)
|
|
1911
1749
|
return nothing;
|
|
@@ -2416,6 +2254,12 @@ __decorate([
|
|
|
2416
2254
|
__decorate([
|
|
2417
2255
|
property({ type: Number, attribute: 'grid-snap' })
|
|
2418
2256
|
], ZsPageDesigner.prototype, "gridSnap", void 0);
|
|
2257
|
+
__decorate([
|
|
2258
|
+
property({ type: String, attribute: 'save-api-url' })
|
|
2259
|
+
], ZsPageDesigner.prototype, "saveApiUrl", void 0);
|
|
2260
|
+
__decorate([
|
|
2261
|
+
property({ type: String, attribute: 'save-api-token' })
|
|
2262
|
+
], ZsPageDesigner.prototype, "saveApiToken", void 0);
|
|
2419
2263
|
__decorate([
|
|
2420
2264
|
state()
|
|
2421
2265
|
], ZsPageDesigner.prototype, "selectedFieldId", void 0);
|
|
@@ -2437,6 +2281,36 @@ __decorate([
|
|
|
2437
2281
|
__decorate([
|
|
2438
2282
|
state()
|
|
2439
2283
|
], ZsPageDesigner.prototype, "zoom", void 0);
|
|
2284
|
+
__decorate([
|
|
2285
|
+
state()
|
|
2286
|
+
], ZsPageDesigner.prototype, "saveDialogOpen", void 0);
|
|
2287
|
+
__decorate([
|
|
2288
|
+
state()
|
|
2289
|
+
], ZsPageDesigner.prototype, "loadDialogOpen", void 0);
|
|
2290
|
+
__decorate([
|
|
2291
|
+
state()
|
|
2292
|
+
], ZsPageDesigner.prototype, "serverAddons", void 0);
|
|
2293
|
+
__decorate([
|
|
2294
|
+
state()
|
|
2295
|
+
], ZsPageDesigner.prototype, "serverLoading", void 0);
|
|
2296
|
+
__decorate([
|
|
2297
|
+
state()
|
|
2298
|
+
], ZsPageDesigner.prototype, "serverSaving", void 0);
|
|
2299
|
+
__decorate([
|
|
2300
|
+
state()
|
|
2301
|
+
], ZsPageDesigner.prototype, "editingAddonId", void 0);
|
|
2302
|
+
__decorate([
|
|
2303
|
+
state()
|
|
2304
|
+
], ZsPageDesigner.prototype, "saveName", void 0);
|
|
2305
|
+
__decorate([
|
|
2306
|
+
state()
|
|
2307
|
+
], ZsPageDesigner.prototype, "saveDesc", void 0);
|
|
2308
|
+
__decorate([
|
|
2309
|
+
state()
|
|
2310
|
+
], ZsPageDesigner.prototype, "saveIconEmoji", void 0);
|
|
2311
|
+
__decorate([
|
|
2312
|
+
state()
|
|
2313
|
+
], ZsPageDesigner.prototype, "saveModules", void 0);
|
|
2440
2314
|
__decorate([
|
|
2441
2315
|
state()
|
|
2442
2316
|
], ZsPageDesigner.prototype, "showTemplateMenu", void 0);
|