@zentto/studio 0.8.3 → 0.9.0

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.
@@ -88,8 +88,6 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
88
88
  this.dragSourceSectionIndex = -1;
89
89
  this.dragInsertIndex = -1;
90
90
  this.dragTargetSectionIndex = -1;
91
- // ─── DataGrid Props ───────────────────────────────
92
- this.gridConfigModalOpen = false;
93
91
  // ─── API Panel (Data Sources) ──────────────────────
94
92
  this.showTemplateMenu = false;
95
93
  this.apiSources = [];
@@ -1387,7 +1385,7 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
1387
1385
  if (field.type === 'heading')
1388
1386
  return field.label ?? 'Titulo';
1389
1387
  if (field.type === 'datagrid')
1390
- return this.renderLiveDataGrid(field);
1388
+ return '◫ ZenttoDataGrid';
1391
1389
  if (field.type === 'report')
1392
1390
  return '◫ ZenttoReportViewer';
1393
1391
  if (field.type === 'chart')
@@ -1408,22 +1406,6 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
1408
1406
  return '▸ Nodo 1\n ▸ Nodo 2';
1409
1407
  return field.placeholder ?? field.type;
1410
1408
  }
1411
- /** Render live datagrid inside canvas — props update in real time */
1412
- renderLiveDataGrid(field) {
1413
- const p = field.props ?? {};
1414
- const ep = p.endpoint || '';
1415
- return html `
1416
- <zs-field-datagrid
1417
- .config="${field}"
1418
- .endpoint="${ep}"
1419
- .authToken="${this.apiToken}"
1420
- .authHeaders="${this.apiToken ? { 'Authorization': 'Bearer ' + this.apiToken, ...(this.apiCompany ? { 'x-empresa': this.apiCompany } : {}), ...(this.apiBranch ? { 'x-sucursal': this.apiBranch } : {}) } : {}}"
1421
- .designMode="${p.enableConfigurator ?? false}"
1422
- .theme="${'light'}"
1423
- style="display:block;width:100%;min-height:200px;"
1424
- ></zs-field-datagrid>
1425
- `;
1426
- }
1427
1409
  // ─── Right Panel (Properties — Figma-quality) ──────
1428
1410
  renderRightPanel() {
1429
1411
  const field = this.selectedField;
@@ -1557,402 +1539,6 @@ let ZsPageDesigner = class ZsPageDesigner extends LitElement {
1557
1539
  ` : ''}
1558
1540
  ` : ''}
1559
1541
  </div>
1560
-
1561
- <!-- Type-specific props -->
1562
- ${this.renderTypeSpecificProps(field)}
1563
- </div>
1564
- `;
1565
- }
1566
- // ─── Type-Specific Property Panels ────────────────
1567
- renderTypeSpecificProps(field) {
1568
- switch (field.type) {
1569
- case 'datagrid': return this.renderDataGridProps(field);
1570
- case 'chart': return this.renderChartProps(field);
1571
- case 'report': return this.renderReportProps(field);
1572
- case 'select':
1573
- case 'multiselect':
1574
- case 'radio': return this.renderSelectProps(field);
1575
- case 'number':
1576
- case 'currency':
1577
- case 'percentage':
1578
- case 'slider':
1579
- case 'rating': return this.renderNumberProps(field);
1580
- case 'lookup': return this.renderLookupProps(field);
1581
- case 'chips':
1582
- case 'tags': return this.renderChipsProps(field);
1583
- case 'treeview': return this.renderTreeViewProps(field);
1584
- case 'date':
1585
- case 'time':
1586
- case 'datetime': return this.renderDateProps(field);
1587
- case 'file':
1588
- case 'image': return this.renderFileProps(field);
1589
- case 'signature': return this.renderSignatureProps(field);
1590
- default: return nothing;
1591
- }
1592
- }
1593
- setProp(field, key, value) {
1594
- if (!field.props)
1595
- field.props = {};
1596
- field.props[key] = value;
1597
- this.commitChange();
1598
- }
1599
- renderDataGridProps(field) {
1600
- const p = field.props ?? {};
1601
- return html `
1602
- <div class="prop-section">
1603
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('grid-config')}">
1604
- <span class="collapse-icon ${this.collapsedSections.has('grid-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1605
- <h4>DataGrid Config</h4>
1606
- </div>
1607
- ${!this.collapsedSections.has('grid-config') ? html `
1608
- <div class="prop-info">◫ Configuracion de zentto-grid</div>
1609
-
1610
- <!-- Open full grid configurator -->
1611
- <button style="width:100%;padding:8px;margin-bottom:8px;border:1px solid #1976d2;border-radius:6px;background:#e3f2fd;color:#1976d2;cursor:pointer;font-size:12px;font-weight:600;font-family:inherit;transition:all 0.15s;"
1612
- @click="${() => { this.gridConfigModalOpen = true; }}"
1613
- >◫ Abrir Configurador de Grid</button>
1614
-
1615
- ${this.gridConfigModalOpen ? this.renderGridConfigModal(field) : ''}
1616
- <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>
1617
- <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>
1618
- <div class="prop-row"><span class="prop-label">Densidad</span>
1619
- <select class="prop-input" .value="${p.density ?? 'compact'}" @change="${(e) => this.setProp(field, 'density', e.target.value)}">
1620
- <option value="compact">Compacta</option>
1621
- <option value="standard">Estandar</option>
1622
- <option value="comfortable">Comoda</option>
1623
- </select>
1624
- </div>
1625
- <div class="prop-row"><span class="prop-label">Row Click</span>
1626
- <select class="prop-input" .value="${p.onRowClick ?? 'emit'}" @change="${(e) => this.setProp(field, 'onRowClick', e.target.value)}">
1627
- <option value="emit">Emitir evento</option>
1628
- <option value="navigate">Navegar</option>
1629
- <option value="select">Seleccionar</option>
1630
- <option value="detail">Detalle</option>
1631
- </select>
1632
- </div>
1633
- ${p.onRowClick === 'navigate' ? html `
1634
- <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>
1635
- ` : ''}
1636
- <div class="prop-divider"></div>
1637
- ${this.renderToggle('Toolbar', p.enableToolbar ?? true, (v) => this.setProp(field, 'enableToolbar', v))}
1638
- ${this.renderToggle('Busqueda', p.enableSearch ?? true, (v) => this.setProp(field, 'enableSearch', v))}
1639
- ${this.renderToggle('Exportar', p.enableExport ?? false, (v) => this.setProp(field, 'enableExport', v))}
1640
- ${this.renderToggle('Paginacion', p.enablePagination ?? true, (v) => this.setProp(field, 'enablePagination', v))}
1641
- ${this.renderToggle('Filtros Header', p.enableHeaderFilters ?? false, (v) => this.setProp(field, 'enableHeaderFilters', v))}
1642
- ${this.renderToggle('Clipboard', p.enableClipboard ?? false, (v) => this.setProp(field, 'enableClipboard', v))}
1643
- ${this.renderToggle('Seleccion Filas', p.enableRowSelection ?? false, (v) => this.setProp(field, 'enableRowSelection', v))}
1644
- ${this.renderToggle('Master-Detail', p.enableMasterDetail ?? false, (v) => this.setProp(field, 'enableMasterDetail', v))}
1645
- ${this.renderToggle('Totales', p.showTotals ?? false, (v) => this.setProp(field, 'showTotals', v))}
1646
- ${this.renderToggle('Context Menu', p.enableContextMenu ?? false, (v) => this.setProp(field, 'enableContextMenu', v))}
1647
- ${this.renderToggle('Find (Ctrl+F)', p.enableFind ?? false, (v) => this.setProp(field, 'enableFind', v))}
1648
- ${this.renderToggle('Status Bar', p.enableStatusBar ?? false, (v) => this.setProp(field, 'enableStatusBar', v))}
1649
- ${this.renderToggle('Filter Panel', p.enableFilterPanel ?? false, (v) => this.setProp(field, 'enableFilterPanel', v))}
1650
- ${this.renderToggle('Configurador', p.enableConfigurator ?? false, (v) => this.setProp(field, 'enableConfigurator', v))}
1651
- <div class="prop-divider"></div>
1652
- <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>
1653
- <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>
1654
- <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>
1655
- ` : ''}
1656
- </div>
1657
- `;
1658
- }
1659
- // ─── Chart Props ──────────────────────────────────
1660
- renderChartProps(field) {
1661
- const p = field.props ?? {};
1662
- return html `
1663
- <div class="prop-section">
1664
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('chart-config')}">
1665
- <span class="collapse-icon ${this.collapsedSections.has('chart-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1666
- <h4>Chart Config</h4>
1667
- </div>
1668
- ${!this.collapsedSections.has('chart-config') ? html `
1669
- <div class="prop-info">📊 Configuracion del grafico SVG</div>
1670
- <div class="prop-row"><span class="prop-label">Tipo</span>
1671
- <select class="prop-input" .value="${p.chartType ?? 'bar'}" @change="${(e) => this.setProp(field, 'chartType', e.target.value)}">
1672
- <option value="bar">Barras</option>
1673
- <option value="line">Lineas</option>
1674
- <option value="pie">Torta</option>
1675
- <option value="donut">Donut</option>
1676
- <option value="area">Area</option>
1677
- </select>
1678
- </div>
1679
- <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>
1680
- <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>
1681
- <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>
1682
- <div class="prop-divider"></div>
1683
- <div class="prop-pos-grid">
1684
- <div class="prop-pos-cell">
1685
- <span class="prop-pos-label prop-pos-label--w">W</span>
1686
- <input type="number" min="100" .value="${String(p.width ?? 400)}" @change="${(e) => this.setProp(field, 'width', parseInt(e.target.value) || 400)}" />
1687
- </div>
1688
- <div class="prop-pos-cell">
1689
- <span class="prop-pos-label prop-pos-label--h">H</span>
1690
- <input type="number" min="100" .value="${String(p.height ?? 250)}" @change="${(e) => this.setProp(field, 'height', parseInt(e.target.value) || 250)}" />
1691
- </div>
1692
- </div>
1693
- <div class="prop-divider"></div>
1694
- ${this.renderToggle('Leyenda', p.showLegend ?? true, (v) => this.setProp(field, 'showLegend', v))}
1695
- ${this.renderToggle('Animacion', p.animated ?? false, (v) => this.setProp(field, 'animated', v))}
1696
- ` : ''}
1697
- </div>
1698
- `;
1699
- }
1700
- // ─── Report Props ─────────────────────────────────
1701
- renderReportProps(field) {
1702
- const p = field.props ?? {};
1703
- return html `
1704
- <div class="prop-section">
1705
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('report-config')}">
1706
- <span class="collapse-icon ${this.collapsedSections.has('report-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1707
- <h4>Report Config</h4>
1708
- </div>
1709
- ${!this.collapsedSections.has('report-config') ? html `
1710
- <div class="prop-info">📋 Configuracion de zentto-report</div>
1711
- <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>
1712
- <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>
1713
- <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>
1714
- <div class="prop-divider"></div>
1715
- ${this.renderToggle('Toolbar', p.showToolbar ?? true, (v) => this.setProp(field, 'showToolbar', v))}
1716
- ${this.renderToggle('Imprimir', p.showPrint ?? true, (v) => this.setProp(field, 'showPrint', v))}
1717
- ${this.renderToggle('Exportar PDF', p.showExportPdf ?? true, (v) => this.setProp(field, 'showExportPdf', v))}
1718
- ${this.renderToggle('Navegacion', p.showNavigation ?? true, (v) => this.setProp(field, 'showNavigation', v))}
1719
- ` : ''}
1720
- </div>
1721
- `;
1722
- }
1723
- // ─── Select/Radio Props ───────────────────────────
1724
- renderSelectProps(field) {
1725
- const p = field.props ?? {};
1726
- const options = p.options ?? [];
1727
- return html `
1728
- <div class="prop-section">
1729
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('select-config')}">
1730
- <span class="collapse-icon ${this.collapsedSections.has('select-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1731
- <h4>Opciones</h4>
1732
- </div>
1733
- ${!this.collapsedSections.has('select-config') ? html `
1734
- ${options.map((opt, i) => html `
1735
- <div style="display:flex;gap:3px;margin-bottom:3px;align-items:center;">
1736
- <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]); }}" />
1737
- <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]); }}" />
1738
- <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>
1739
- </div>
1740
- `)}
1741
- <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;"
1742
- @click="${() => { options.push({ value: '', label: '' }); this.setProp(field, 'options', [...options]); }}"
1743
- >+ Agregar opcion</button>
1744
- ${field.type === 'radio' ? html `
1745
- <div class="prop-divider"></div>
1746
- ${this.renderToggle('Horizontal', p.horizontal ?? false, (v) => this.setProp(field, 'horizontal', v))}
1747
- ` : ''}
1748
- ${field.type === 'multiselect' ? html `
1749
- <div class="prop-divider"></div>
1750
- ${this.renderToggle('Multiple', true, () => { })}
1751
- ` : ''}
1752
- ` : ''}
1753
- </div>
1754
- `;
1755
- }
1756
- // ─── Number/Currency/Slider/Rating Props ──────────
1757
- renderNumberProps(field) {
1758
- const p = field.props ?? {};
1759
- return html `
1760
- <div class="prop-section">
1761
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('number-config')}">
1762
- <span class="collapse-icon ${this.collapsedSections.has('number-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1763
- <h4>Numero Config</h4>
1764
- </div>
1765
- ${!this.collapsedSections.has('number-config') ? html `
1766
- ${field.type === 'currency' ? html `
1767
- <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>
1768
- ` : ''}
1769
- ${field.type === 'slider' || field.type === 'rating' ? html `
1770
- <div class="prop-pos-grid">
1771
- <div class="prop-pos-cell">
1772
- <span class="prop-pos-label prop-pos-label--x">Min</span>
1773
- <input type="number" .value="${String(p.min ?? 0)}" @change="${(e) => this.setProp(field, 'min', parseInt(e.target.value) || 0)}" />
1774
- </div>
1775
- <div class="prop-pos-cell">
1776
- <span class="prop-pos-label prop-pos-label--y">Max</span>
1777
- <input type="number" .value="${String(p.max ?? (field.type === 'rating' ? 5 : 100))}" @change="${(e) => this.setProp(field, 'max', parseInt(e.target.value) || 100)}" />
1778
- </div>
1779
- </div>
1780
- ${field.type === 'slider' ? html `
1781
- <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>
1782
- ` : ''}
1783
- ${field.type === 'rating' ? html `
1784
- <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>
1785
- ` : ''}
1786
- ` : ''}
1787
- ` : ''}
1788
- </div>
1789
- `;
1790
- }
1791
- // ─── Lookup Props ─────────────────────────────────
1792
- renderLookupProps(field) {
1793
- const p = field.props ?? {};
1794
- return html `
1795
- <div class="prop-section">
1796
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('lookup-config')}">
1797
- <span class="collapse-icon ${this.collapsedSections.has('lookup-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1798
- <h4>Lookup Config</h4>
1799
- </div>
1800
- ${!this.collapsedSections.has('lookup-config') ? html `
1801
- <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>
1802
- <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>
1803
- ` : ''}
1804
- </div>
1805
- `;
1806
- }
1807
- // ─── Chips/Tags Props ─────────────────────────────
1808
- renderChipsProps(field) {
1809
- const p = field.props ?? {};
1810
- return html `
1811
- <div class="prop-section">
1812
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('chips-config')}">
1813
- <span class="collapse-icon ${this.collapsedSections.has('chips-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1814
- <h4>Chips Config</h4>
1815
- </div>
1816
- ${!this.collapsedSections.has('chips-config') ? html `
1817
- <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>
1818
- <div class="prop-row"><span class="prop-label">Color Mode</span>
1819
- <select class="prop-input" .value="${p.colorMode ?? 'default'}" @change="${(e) => this.setProp(field, 'colorMode', e.target.value)}">
1820
- <option value="default">Default</option>
1821
- <option value="primary">Primary</option>
1822
- <option value="success">Success</option>
1823
- <option value="auto">Auto (ciclo)</option>
1824
- </select>
1825
- </div>
1826
- ${this.renderToggle('Permitir custom', p.allowCustom ?? true, (v) => this.setProp(field, 'allowCustom', v))}
1827
- ${this.renderSelectProps(field)}
1828
- ` : ''}
1829
- </div>
1830
- `;
1831
- }
1832
- // ─── TreeView Props ───────────────────────────────
1833
- renderTreeViewProps(field) {
1834
- const p = field.props ?? {};
1835
- return html `
1836
- <div class="prop-section">
1837
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('tree-config')}">
1838
- <span class="collapse-icon ${this.collapsedSections.has('tree-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1839
- <h4>TreeView Config</h4>
1840
- </div>
1841
- ${!this.collapsedSections.has('tree-config') ? html `
1842
- ${this.renderToggle('Multi-select', p.multiSelect ?? false, (v) => this.setProp(field, 'multiSelect', v))}
1843
- ${this.renderToggle('Checkboxes', p.showCheckboxes ?? false, (v) => this.setProp(field, 'showCheckboxes', v))}
1844
- ${this.renderToggle('Buscador', p.searchable ?? false, (v) => this.setProp(field, 'searchable', v))}
1845
- ` : ''}
1846
- </div>
1847
- `;
1848
- }
1849
- // ─── Date Props ───────────────────────────────────
1850
- renderDateProps(field) {
1851
- const p = field.props ?? {};
1852
- return html `
1853
- <div class="prop-section">
1854
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('date-config')}">
1855
- <span class="collapse-icon ${this.collapsedSections.has('date-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1856
- <h4>Fecha Config</h4>
1857
- </div>
1858
- ${!this.collapsedSections.has('date-config') ? html `
1859
- <div class="prop-row"><span class="prop-label">Modo</span>
1860
- <select class="prop-input" .value="${p.mode ?? 'date'}" @change="${(e) => this.setProp(field, 'mode', e.target.value)}">
1861
- <option value="date">Fecha</option>
1862
- <option value="time">Hora</option>
1863
- <option value="datetime">Fecha y Hora</option>
1864
- </select>
1865
- </div>
1866
- <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>
1867
- <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>
1868
- ` : ''}
1869
- </div>
1870
- `;
1871
- }
1872
- // ─── File/Image Props ─────────────────────────────
1873
- renderFileProps(field) {
1874
- const p = field.props ?? {};
1875
- return html `
1876
- <div class="prop-section">
1877
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('file-config')}">
1878
- <span class="collapse-icon ${this.collapsedSections.has('file-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1879
- <h4>Archivo Config</h4>
1880
- </div>
1881
- ${!this.collapsedSections.has('file-config') ? html `
1882
- <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>
1883
- ${this.renderToggle('Multiple', p.multiple ?? false, (v) => this.setProp(field, 'multiple', v))}
1884
- ` : ''}
1885
- </div>
1886
- `;
1887
- }
1888
- // ─── Signature Props ──────────────────────────────
1889
- renderSignatureProps(field) {
1890
- const p = field.props ?? {};
1891
- return html `
1892
- <div class="prop-section">
1893
- <div class="prop-section-header" data-section="layout" @click="${() => this.toggleSection('sig-config')}">
1894
- <span class="collapse-icon ${this.collapsedSections.has('sig-config') ? 'collapse-icon--collapsed' : ''}">▾</span>
1895
- <h4>Firma Config</h4>
1896
- </div>
1897
- ${!this.collapsedSections.has('sig-config') ? html `
1898
- <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>
1899
- <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>
1900
- ` : ''}
1901
- </div>
1902
- `;
1903
- }
1904
- // ─── Grid Configurator Modal ────────────────────
1905
- renderGridConfigModal(field) {
1906
- const p = field.props ?? {};
1907
- const endpoint = p.endpoint ?? '';
1908
- return html `
1909
- <div style="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,0.5);backdrop-filter:blur(3px);display:flex;align-items:center;justify-content:center;"
1910
- @click="${(e) => { if (e.target === e.currentTarget)
1911
- this.gridConfigModalOpen = false; }}"
1912
- >
1913
- <div style="background:white;border-radius:12px;width:90vw;max-width:1200px;height:80vh;display:flex;flex-direction:column;box-shadow:0 20px 60px rgba(0,0,0,0.3);overflow:hidden;"
1914
- @click="${(e) => e.stopPropagation()}"
1915
- >
1916
- <!-- Header -->
1917
- <div style="padding:14px 20px;border-bottom:1px solid #eee;display:flex;align-items:center;gap:12px;">
1918
- <span style="font-size:18px;">◫</span>
1919
- <div style="flex:1;">
1920
- <div style="font-size:15px;font-weight:600;color:#333;">Configurador de Grid</div>
1921
- <div style="font-size:11px;color:#999;">Usa el configurador nativo del grid para ajustar columnas, orden, ancho y visibilidad</div>
1922
- </div>
1923
- <button style="border:none;background:none;font-size:20px;cursor:pointer;color:#999;padding:4px 8px;"
1924
- @click="${() => { this.gridConfigModalOpen = false; }}"
1925
- >✕</button>
1926
- </div>
1927
-
1928
- <!-- Grid con configurador activo -->
1929
- <div style="flex:1;overflow:hidden;padding:16px;">
1930
- <zs-field-datagrid
1931
- .config="${{ ...field, props: { ...p, enableToolbar: true, enableSearch: true, enableExport: true, enableHeaderFilters: true, enablePagination: true } }}"
1932
- .endpoint="${endpoint}"
1933
- .authToken="${this.apiToken}"
1934
- .authHeaders="${this.apiToken ? { 'Authorization': 'Bearer ' + this.apiToken, ...(this.apiCompany ? { 'x-empresa': this.apiCompany } : {}), ...(this.apiBranch ? { 'x-sucursal': this.apiBranch } : {}) } : {}}"
1935
- .designMode="${true}"
1936
- .theme="${'light'}"
1937
- style="display:block;height:100%;"
1938
- ></zs-field-datagrid>
1939
- </div>
1940
-
1941
- <!-- Footer -->
1942
- <div style="padding:12px 20px;border-top:1px solid #eee;display:flex;gap:8px;justify-content:space-between;background:#fafafa;">
1943
- <div style="font-size:11px;color:#999;display:flex;align-items:center;gap:6px;">
1944
- <span>💡</span> Usa el icono ⚙ del grid para abrir el configurador de columnas
1945
- </div>
1946
- <div style="display:flex;gap:8px;">
1947
- <button style="padding:8px 16px;border:1px solid #ddd;border-radius:6px;background:white;cursor:pointer;font-size:13px;font-family:inherit;"
1948
- @click="${() => { this.gridConfigModalOpen = false; }}"
1949
- >Cerrar</button>
1950
- <button style="padding:8px 16px;border:none;border-radius:6px;background:#1976d2;color:white;cursor:pointer;font-size:13px;font-weight:600;font-family:inherit;"
1951
- @click="${() => { this.gridConfigModalOpen = false; this.commitChange(); }}"
1952
- >Guardar Configuracion</button>
1953
- </div>
1954
- </div>
1955
- </div>
1956
1542
  </div>
1957
1543
  `;
1958
1544
  }
@@ -2487,9 +2073,6 @@ __decorate([
2487
2073
  __decorate([
2488
2074
  state()
2489
2075
  ], ZsPageDesigner.prototype, "zoom", void 0);
2490
- __decorate([
2491
- state()
2492
- ], ZsPageDesigner.prototype, "gridConfigModalOpen", void 0);
2493
2076
  __decorate([
2494
2077
  state()
2495
2078
  ], ZsPageDesigner.prototype, "showTemplateMenu", void 0);