@joel_jsp/vortex-ui 0.1.0 → 0.1.2

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
@@ -1,8 +1,31 @@
1
- # @joel_jsp/vortex-ui
1
+ # VortexUI
2
2
 
3
- **VortexUI** — suite de componentes Angular 22+ (Standalone, Signals, zoneless-ready), com DataGrid de alta performance, AI opt-in e temas Fluent / LDS.
3
+ **Angular 22+ component suite** — Standalone, Signals-first, zoneless-ready.
4
+ DataGrid de alta performance, File Manager, Charts, Scheduler, AI opt-in e temas Fluent / LDS.
4
5
 
5
- Repositório: [JoelSchecheleski/vortex-ui](https://github.com/JoelSchecheleski/vortex-ui)
6
+ [![npm](https://img.shields.io/npm/v/@joel_jsp/vortex-ui.svg)](https://www.npmjs.com/package/@joel_jsp/vortex-ui)
7
+ [![license](https://img.shields.io/npm/l/@joel_jsp/vortex-ui.svg)](./LICENSE)
8
+ [![Angular](https://img.shields.io/badge/Angular-22%2B-dd0031)](https://angular.dev/)
9
+
10
+ 📦 **npm:** [`@joel_jsp/vortex-ui`](https://www.npmjs.com/package/@joel_jsp/vortex-ui)
11
+ 📂 **GitHub:** [JoelSchecheleski/vortex-ui](https://github.com/JoelSchecheleski/vortex-ui)
12
+
13
+ ---
14
+
15
+ ## Por que VortexUI?
16
+
17
+ | Diferencial | Detalhe |
18
+ |-------------|---------|
19
+ | **Angular nativo** | 100% Standalone + `input()` / `model()` / `output()` / `signal` / `computed` |
20
+ | **Zoneless** | `OnPush` e compatível com apps sem Zone.js |
21
+ | **DataGrid** | Virtualização, remote DataSource (1M+ rows), sort/filter/group/edit/export |
22
+ | **AI opt-in** | Assistant + AI Columns via entry separado `@joel_jsp/vortex-ui/ai` |
23
+ | **Temas** | Design tokens `--vx-*` · Fluent Blue/SaaS (Light/Dark) · LDS |
24
+ | **Tree-shakeable** | Importe só o que usa; CSS e AI não entram no bundle se não forem referenciados |
25
+
26
+ Inspirado na superfície de produto DevExtreme — **implementação própria**, MIT.
27
+
28
+ ---
6
29
 
7
30
  ## Install
8
31
 
@@ -10,40 +33,224 @@ Repositório: [JoelSchecheleski/vortex-ui](https://github.com/JoelSchecheleski/v
10
33
  npm install @joel_jsp/vortex-ui
11
34
  ```
12
35
 
13
- ## Uso
36
+ **Peers:** `@angular/core`, `@angular/common`, `@angular/forms` ^22.
14
37
 
15
- ```ts
16
- import { VxButtonComponent, VxDataGridComponent, VortexThemeService } from '@joel_jsp/vortex-ui';
17
- import { VortexMockAIIntegration, VortexAIConfig } from '@joel_jsp/vortex-ui/ai';
18
- ```
38
+ ---
39
+
40
+ ## Setup rápido (3 passos)
41
+
42
+ ### 1. Estilos (uma vez no app)
43
+
44
+ No `styles` do `angular.json` / `project.json`, ou no CSS global:
19
45
 
20
46
  ```css
21
47
  @import '@joel_jsp/vortex-ui/styles/vortex-ui.css';
22
48
  ```
23
49
 
50
+ ### 2. Tema
51
+
52
+ ```ts
53
+ import { inject, ApplicationConfig, provideAppInitializer } from '@angular/core';
54
+ import { VortexThemeService } from '@joel_jsp/vortex-ui';
55
+
56
+ export const appConfig: ApplicationConfig = {
57
+ providers: [
58
+ provideAppInitializer(() => {
59
+ inject(VortexThemeService).setTheme('fluent-blue-light');
60
+ }),
61
+ ],
62
+ };
63
+ ```
64
+
65
+ Ou em qualquer componente:
66
+
67
+ ```ts
68
+ inject(VortexThemeService).setTheme('fluent-saas-dark');
69
+ ```
70
+
71
+ ### 3. Use um componente
72
+
24
73
  ```ts
25
- inject(VortexThemeService).setTheme('fluent-blue-light');
26
- // fluent-blue-dark | fluent-saas-light | fluent-saas-dark | lds
74
+ import { Component } from '@angular/core';
75
+ import { VxButtonComponent, VxDataGridComponent, VxColumnDef } from '@joel_jsp/vortex-ui';
76
+
77
+ @Component({
78
+ standalone: true,
79
+ imports: [VxButtonComponent, VxDataGridComponent],
80
+ template: `
81
+ <vx-button variant="primary">Salvar</vx-button>
82
+
83
+ <vx-data-grid
84
+ [columns]="columns"
85
+ [data]="rows"
86
+ [rowHeight]="36"
87
+ [virtualScroll]="true"
88
+ />
89
+ `,
90
+ })
91
+ export class DemoPage {
92
+ readonly columns: VxColumnDef[] = [
93
+ { field: 'id', header: 'ID', width: 72 },
94
+ { field: 'product', header: 'Produto' }, // fluida (preenche o grid)
95
+ { field: 'region', header: 'Região', minWidth: 100 },
96
+ ];
97
+ readonly rows = [
98
+ { id: 1, product: 'SolarMax', region: 'África' },
99
+ { id: 2, product: 'EcoCharge', region: 'Europa' },
100
+ ];
101
+ }
27
102
  ```
28
103
 
104
+ ---
105
+
29
106
  ## Temas
30
107
 
108
+ Aplique via `data-vx-theme` (feito automaticamente pelo `VortexThemeService`):
109
+
31
110
  | ID | Descrição |
32
111
  |----|-----------|
33
- | `fluent-blue-light` | Default (alias `fluent`) |
112
+ | `fluent-blue-light` | **Default** (alias `fluent`) |
34
113
  | `fluent-blue-dark` | Fluent Blue Dark |
35
114
  | `fluent-saas-light` | Fluent SaaS Light |
36
115
  | `fluent-saas-dark` | Fluent SaaS Dark |
37
- | `lds` | LDS (Poppins) |
116
+ | `lds` | LDS (Poppins + guideline interno) |
117
+
118
+ ```ts
119
+ import { VortexThemeService, VORTEX_THEMES, VORTEX_THEME_LABELS } from '@joel_jsp/vortex-ui';
120
+
121
+ const themes = inject(VortexThemeService);
122
+ themes.setTheme('lds');
123
+ themes.toggleTheme(); // cicla pelos oficiais
124
+ ```
125
+
126
+ Componentes usam **somente** tokens `--vx-*` (sem hex hardcoded no core).
127
+
128
+ ---
129
+
130
+ ## AI (opt-in)
131
+
132
+ A IA **não** entra no bundle principal. Use o secondary entry:
133
+
134
+ ```ts
135
+ import {
136
+ VortexAIConfig,
137
+ VortexMockAIIntegration,
138
+ } from '@joel_jsp/vortex-ui/ai';
139
+ ```
140
+
141
+ ```ts
142
+ readonly aiConfig: VortexAIConfig = {
143
+ enabled: true,
144
+ assistant: { enabled: true, title: 'AI Assistant' },
145
+ contextFields: ['id', 'product', 'region'],
146
+ maxRowsInContext: 50,
147
+ };
148
+
149
+ readonly ai = new VortexMockAIIntegration();
150
+ ```
151
+
152
+ ```html
153
+ <vx-data-grid
154
+ [columns]="columns"
155
+ [data]="rows"
156
+ [ai]="aiConfig"
157
+ [aiIntegration]="ai"
158
+ />
159
+ ```
160
+
161
+ - Deny by default (`ai.enabled = false`)
162
+ - Contexto tipado (não lê o DOM)
163
+ - Command bus / allowlist de ações
164
+ - Pluggable: troque o mock por OpenAI, Azure, modelo local, etc.
165
+
166
+ ---
167
+
168
+ ## Catálogo (v0.1)
169
+
170
+ ### Data & grids
171
+ `vx-data-grid` · `vx-tree-list` · `vx-card-view` · `vx-pivot-grid` · `vx-pivot-field-chooser` · `vx-filter-builder` · `vx-list`
172
+
173
+ ### Forms & editors
174
+ `vx-form` · `vx-text-box` · `vx-text-area` · `vx-number-box` · `vx-select-box` · `vx-date-box` · `vx-date-range-box` · `vx-checkbox` · `vx-switch` · `vx-radio-group` · `vx-slider` · `vx-range-slider` · `vx-color-box` · `vx-tag-box` · `vx-autocomplete` · `vx-lookup` · `vx-calendar` · `vx-field-set` · validation summary
175
+
176
+ ### Buttons & actions
177
+ `vx-button` · `vx-button-group` · `vx-drop-down-button` · `vx-fab`
178
+
179
+ ### Navigation & layout
180
+ `vx-tabs` · `vx-accordion` · `vx-drawer` · `vx-menu` · `vx-tree-view` · `vx-splitter` · `vx-stepper` · `vx-toolbar` · `vx-box` · `vx-multi-view` · `vx-pagination` · `vx-gallery` · `vx-tile-view` · `vx-scroll-view`
181
+
182
+ ### Feedback & overlays
183
+ `vx-dialog` · `vx-toast` · `vx-load-panel` · `vx-tooltip` · `vx-popover` · `vx-context-menu` · `vx-action-sheet` · progress / load-indicator
184
+
185
+ ### Visualization
186
+ `vx-chart` (bar/line/area/pie/funnel/polar) · `vx-sparkline` · `vx-bullet` · `vx-funnel` · `vx-tree-map` · `vx-sankey` · gauges · `vx-diagram`
38
187
 
39
- ## Dev (monorepo)
188
+ ### Scheduling & files
189
+ `vx-scheduler` (day/week/month) · `vx-gantt` · `vx-file-manager` · `vx-file-uploader`
190
+
191
+ ### Messaging & maps
192
+ `vx-chat` · `vx-html-editor` · `vx-map` · `vx-vector-map`
193
+
194
+ ### Wrappers
195
+ `vx-draggable` · `vx-sortable` · `vx-resizable`
196
+
197
+ > Maturidade atual: **M0–M1** na maior parte da Super Suite; DataGrid / temas / AI Foundation mais avançados. Roadmap no [PRD](https://github.com/JoelSchecheleski/vortex-ui/blob/main/VortexUI-PRD.md).
198
+
199
+ ---
200
+
201
+ ## DataGrid — tips
202
+
203
+ ```html
204
+ <vx-data-grid
205
+ [columns]="columns"
206
+ [data]="rows"
207
+ [dataSource]="remoteSource"
208
+ [virtualScroll]="true"
209
+ [editable]="true"
210
+ [exportEnabled]="true"
211
+ (cellEdit)="onEdit($event)"
212
+ />
213
+ ```
214
+
215
+ - **Sem `width`** → coluna fluida (reparte o espaço do container, estilo DX)
216
+ - **Com `width`** → fixa; use `minWidth` nas fluidas
217
+ - Remote: implemente `VxDataSource` / use `VxRemoteMockDataSource` nos demos
218
+ - Export CSV nativo na toolbar
219
+
220
+ ---
221
+
222
+ ## Entries do pacote
223
+
224
+ | Import | Conteúdo |
225
+ |--------|----------|
226
+ | `@joel_jsp/vortex-ui` | Componentes + theme + validators |
227
+ | `@joel_jsp/vortex-ui/ai` | AI Bridge, dialogs, mock integration |
228
+ | `@joel_jsp/vortex-ui/styles/vortex-ui.css` | Tokens + temas oficiais |
229
+
230
+ ---
231
+
232
+ ## Requisitos
233
+
234
+ - Node 20+ recomendado
235
+ - Angular **22+**
236
+ - TypeScript 5.x
237
+
238
+ ---
239
+
240
+ ## Desenvolvimento (monorepo)
40
241
 
41
242
  ```bash
42
- npm start # Widgets Gallery :4200
43
- npm run build # build da lib
44
- npm run storybook # Storybook
243
+ git clone https://github.com/JoelSchecheleski/vortex-ui.git
244
+ cd vortex-ui
245
+ npm install
246
+ npm start # Widgets Gallery → http://localhost:4200
247
+ npm run storybook # Storybook
248
+ npm run build # build da lib
249
+ npm run prepare:npm # artefato em dist/libs/vortex-ui
45
250
  ```
46
251
 
252
+ ---
253
+
47
254
  ## License
48
255
 
49
- MIT
256
+ MIT © [Joel Schecheleski](https://github.com/JoelSchecheleski)
@@ -1,4 +1,4 @@
1
- import { Component, ChangeDetectionStrategy, computed, input, model, output } from '@angular/core';
1
+ import { Component, ChangeDetectionStrategy, computed, input, model, output, signal, } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  export class VxAutocompleteComponent {
4
4
  label = input(/* @ts-ignore */
@@ -12,68 +12,101 @@ export class VxAutocompleteComponent {
12
12
  query = model('', /* @ts-ignore */
13
13
  ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
14
14
  optionSelected = output();
15
+ /** Controla abertura do painel (fecha ao selecionar). */
16
+ open = signal(false, /* @ts-ignore */
17
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
15
18
  suggestions = computed(() => {
16
- const q = this.query().toLowerCase();
19
+ const q = this.query().trim().toLowerCase();
17
20
  if (!q)
18
21
  return [];
19
- return this.items().filter((i) => i.toLowerCase().includes(q)).slice(0, 8);
22
+ return this.items()
23
+ .filter((i) => i.toLowerCase().includes(q))
24
+ .slice(0, 8);
20
25
  }, /* @ts-ignore */
21
26
  ...(ngDevMode ? [{ debugName: "suggestions" }] : /* istanbul ignore next */ []));
27
+ panelOpen = computed(() => this.open() && this.suggestions().length > 0, /* @ts-ignore */
28
+ ...(ngDevMode ? [{ debugName: "panelOpen" }] : /* istanbul ignore next */ []));
22
29
  onQuery(event) {
23
- this.query.set(event.target.value);
30
+ const next = event.target.value;
31
+ this.query.set(next);
32
+ this.open.set(true);
33
+ }
34
+ onFocus() {
35
+ if (this.suggestions().length)
36
+ this.open.set(true);
37
+ }
38
+ close() {
39
+ this.open.set(false);
24
40
  }
25
41
  pick(item) {
26
42
  this.value.set(item);
27
43
  this.query.set(item);
44
+ this.open.set(false);
28
45
  this.optionSelected.emit(item);
29
46
  }
30
47
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.6", ngImport: i0, type: VxAutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
31
48
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.6", type: VxAutocompleteComponent, isStandalone: true, selector: "vx-autocomplete", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", query: "queryChange", optionSelected: "optionSelected" }, ngImport: i0, template: `
32
49
  <label class="vx-field">
33
- @if (label()) { <span class="vx-field__label">{{ label() }}</span> }
50
+ @if (label()) {
51
+ <span class="vx-field__label">{{ label() }}</span>
52
+ }
34
53
  <input
35
54
  class="vx-ac"
36
55
  type="search"
37
56
  [placeholder]="placeholder()"
38
57
  [value]="query()"
39
58
  (input)="onQuery($event)"
40
- [attr.aria-expanded]="suggestions().length > 0"
59
+ (focus)="onFocus()"
60
+ (keydown.escape)="close()"
61
+ [attr.aria-expanded]="panelOpen()"
41
62
  aria-autocomplete="list"
42
63
  aria-label="Autocomplete"
43
64
  />
44
- @if (suggestions().length) {
65
+ @if (panelOpen()) {
45
66
  <ul class="vx-ac__list" role="listbox">
46
67
  @for (item of suggestions(); track item) {
47
- <li><button type="button" (click)="pick(item)">{{ item }}</button></li>
68
+ <li>
69
+ <button type="button" role="option" (mousedown)="$event.preventDefault()" (click)="pick(item)">
70
+ {{ item }}
71
+ </button>
72
+ </li>
48
73
  }
49
74
  </ul>
50
75
  }
51
76
  </label>
52
- `, isInline: true, styles: [":host{display:block;position:relative}.vx-field{display:flex;flex-direction:column;gap:var(--vx-space-1);font-family:var(--vx-font-sans)}.vx-field__label{font-size:var(--vx-font-size-sm);font-weight:var(--vx-font-weight-medium)}.vx-ac{height:2.5rem;padding:0 var(--vx-space-3);width:100%;box-sizing:border-box;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);font:inherit;font-size:var(--vx-font-size-sm)}.vx-ac__list{list-style:none;margin:0;padding:var(--vx-space-1);position:absolute;z-index:5;width:100%;box-sizing:border-box;background:var(--vx-color-surface);border:1px solid var(--vx-color-border);border-radius:var(--vx-radius-md);max-height:180px;overflow:auto}.vx-ac__list button{width:100%;text-align:left;border:none;background:none;padding:var(--vx-space-2);font:inherit;cursor:pointer;border-radius:var(--vx-radius-sm)}.vx-ac__list button:hover{background:var(--vx-color-bg-muted)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
77
+ `, isInline: true, styles: [":host{display:block;position:relative}.vx-field{display:flex;flex-direction:column;gap:var(--vx-space-1);font-family:var(--vx-font-sans)}.vx-field__label{font-size:var(--vx-font-size-sm);font-weight:var(--vx-font-weight-medium)}.vx-ac{height:2.5rem;padding:0 var(--vx-space-3);width:100%;box-sizing:border-box;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);font:inherit;font-size:var(--vx-font-size-sm);background:var(--vx-color-bg-elevated);color:var(--vx-color-text)}.vx-ac:focus{outline:none;border-color:var(--vx-color-border-focus);box-shadow:var(--vx-focus-ring)}.vx-ac__list{list-style:none;margin:0;padding:var(--vx-space-1);position:absolute;z-index:5;left:0;right:0;width:100%;box-sizing:border-box;background:var(--vx-color-surface);border:1px solid var(--vx-color-border);border-radius:var(--vx-radius-md);max-height:180px;overflow:auto;box-shadow:var(--vx-shadow-md, 0 4px 12px rgb(0 0 0 / .12))}.vx-ac__list button{width:100%;text-align:left;border:none;background:none;padding:var(--vx-space-2);font:inherit;color:var(--vx-color-text);cursor:pointer;border-radius:var(--vx-radius-sm)}.vx-ac__list button:hover{background:var(--vx-color-bg-muted)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
53
78
  }
54
79
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.6", ngImport: i0, type: VxAutocompleteComponent, decorators: [{
55
80
  type: Component,
56
81
  args: [{ selector: 'vx-autocomplete', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
57
82
  <label class="vx-field">
58
- @if (label()) { <span class="vx-field__label">{{ label() }}</span> }
83
+ @if (label()) {
84
+ <span class="vx-field__label">{{ label() }}</span>
85
+ }
59
86
  <input
60
87
  class="vx-ac"
61
88
  type="search"
62
89
  [placeholder]="placeholder()"
63
90
  [value]="query()"
64
91
  (input)="onQuery($event)"
65
- [attr.aria-expanded]="suggestions().length > 0"
92
+ (focus)="onFocus()"
93
+ (keydown.escape)="close()"
94
+ [attr.aria-expanded]="panelOpen()"
66
95
  aria-autocomplete="list"
67
96
  aria-label="Autocomplete"
68
97
  />
69
- @if (suggestions().length) {
98
+ @if (panelOpen()) {
70
99
  <ul class="vx-ac__list" role="listbox">
71
100
  @for (item of suggestions(); track item) {
72
- <li><button type="button" (click)="pick(item)">{{ item }}</button></li>
101
+ <li>
102
+ <button type="button" role="option" (mousedown)="$event.preventDefault()" (click)="pick(item)">
103
+ {{ item }}
104
+ </button>
105
+ </li>
73
106
  }
74
107
  </ul>
75
108
  }
76
109
  </label>
77
- `, styles: [":host{display:block;position:relative}.vx-field{display:flex;flex-direction:column;gap:var(--vx-space-1);font-family:var(--vx-font-sans)}.vx-field__label{font-size:var(--vx-font-size-sm);font-weight:var(--vx-font-weight-medium)}.vx-ac{height:2.5rem;padding:0 var(--vx-space-3);width:100%;box-sizing:border-box;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);font:inherit;font-size:var(--vx-font-size-sm)}.vx-ac__list{list-style:none;margin:0;padding:var(--vx-space-1);position:absolute;z-index:5;width:100%;box-sizing:border-box;background:var(--vx-color-surface);border:1px solid var(--vx-color-border);border-radius:var(--vx-radius-md);max-height:180px;overflow:auto}.vx-ac__list button{width:100%;text-align:left;border:none;background:none;padding:var(--vx-space-2);font:inherit;cursor:pointer;border-radius:var(--vx-radius-sm)}.vx-ac__list button:hover{background:var(--vx-color-bg-muted)}\n"] }]
110
+ `, styles: [":host{display:block;position:relative}.vx-field{display:flex;flex-direction:column;gap:var(--vx-space-1);font-family:var(--vx-font-sans)}.vx-field__label{font-size:var(--vx-font-size-sm);font-weight:var(--vx-font-weight-medium)}.vx-ac{height:2.5rem;padding:0 var(--vx-space-3);width:100%;box-sizing:border-box;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);font:inherit;font-size:var(--vx-font-size-sm);background:var(--vx-color-bg-elevated);color:var(--vx-color-text)}.vx-ac:focus{outline:none;border-color:var(--vx-color-border-focus);box-shadow:var(--vx-focus-ring)}.vx-ac__list{list-style:none;margin:0;padding:var(--vx-space-1);position:absolute;z-index:5;left:0;right:0;width:100%;box-sizing:border-box;background:var(--vx-color-surface);border:1px solid var(--vx-color-border);border-radius:var(--vx-radius-md);max-height:180px;overflow:auto;box-shadow:var(--vx-shadow-md, 0 4px 12px rgb(0 0 0 / .12))}.vx-ac__list button{width:100%;text-align:left;border:none;background:none;padding:var(--vx-space-2);font:inherit;color:var(--vx-color-text);cursor:pointer;border-radius:var(--vx-radius-sm)}.vx-ac__list button:hover{background:var(--vx-color-bg-muted)}\n"] }]
78
111
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], query: [{ type: i0.Input, args: [{ isSignal: true, alias: "query", required: false }] }, { type: i0.Output, args: ["queryChange"] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }] } });
79
112
  //# sourceMappingURL=autocomplete.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.component.js","sourceRoot":"","sources":["../../../../../../../libs/vortex-ui/src/lib/components/autocomplete/autocomplete.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AA+CnG,MAAM,OAAO,uBAAuB;IACzB,KAAK,GAAG,KAAK;yFAAU,CAAC;IACxB,WAAW,GAAG,KAAK,CAAC,SAAS;oFAAC,CAAC;IAC/B,KAAK,GAAG,KAAK,CAAW,EAAE;8EAAC,CAAC;IAC5B,KAAK,GAAG,KAAK,CAAC,EAAE;8EAAC,CAAC;IAClB,KAAK,GAAG,KAAK,CAAC,EAAE;8EAAC,CAAC;IAClB,cAAc,GAAG,MAAM,EAAU,CAAC;IAElC,WAAW,GAAG,QAAQ,CAAC,GAAG,EAAE;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;oFAAC,CAAC;IAEH,OAAO,CAAC,KAAY;QAClB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAE,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;uGAtBU,uBAAuB;2FAAvB,uBAAuB,4xBAzCxB;;;;;;;;;;;;;;;;;;;;;GAqBT;;2FAoBU,uBAAuB;kBA7CnC,SAAS;+BACE,iBAAiB,cACf,IAAI,mBACC,uBAAuB,CAAC,MAAM,YACrC;;;;;;;;;;;;;;;;;;;;;GAqBT","sourcesContent":["import { Component, ChangeDetectionStrategy, computed, input, model, output } from '@angular/core';\n\n@Component({\n selector: 'vx-autocomplete',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <label class=\"vx-field\">\n @if (label()) { <span class=\"vx-field__label\">{{ label() }}</span> }\n <input\n class=\"vx-ac\"\n type=\"search\"\n [placeholder]=\"placeholder()\"\n [value]=\"query()\"\n (input)=\"onQuery($event)\"\n [attr.aria-expanded]=\"suggestions().length > 0\"\n aria-autocomplete=\"list\"\n aria-label=\"Autocomplete\"\n />\n @if (suggestions().length) {\n <ul class=\"vx-ac__list\" role=\"listbox\">\n @for (item of suggestions(); track item) {\n <li><button type=\"button\" (click)=\"pick(item)\">{{ item }}</button></li>\n }\n </ul>\n }\n </label>\n `,\n styles: `\n :host { display: block; position: relative; }\n .vx-field { display: flex; flex-direction: column; gap: var(--vx-space-1); font-family: var(--vx-font-sans); }\n .vx-field__label { font-size: var(--vx-font-size-sm); font-weight: var(--vx-font-weight-medium); }\n .vx-ac {\n height: 2.5rem; padding: 0 var(--vx-space-3); width: 100%; box-sizing: border-box;\n border: 1px solid var(--vx-color-border-strong); border-radius: var(--vx-radius-md);\n font: inherit; font-size: var(--vx-font-size-sm);\n }\n .vx-ac__list {\n list-style: none; margin: 0; padding: var(--vx-space-1); position: absolute; z-index: 5;\n width: 100%; box-sizing: border-box; background: var(--vx-color-surface);\n border: 1px solid var(--vx-color-border); border-radius: var(--vx-radius-md);\n max-height: 180px; overflow: auto;\n }\n .vx-ac__list button { width: 100%; text-align: left; border: none; background: none; padding: var(--vx-space-2); font: inherit; cursor: pointer; border-radius: var(--vx-radius-sm); }\n .vx-ac__list button:hover { background: var(--vx-color-bg-muted); }\n `,\n})\nexport class VxAutocompleteComponent {\n readonly label = input<string>();\n readonly placeholder = input('Buscar…');\n readonly items = input<string[]>([]);\n readonly value = model('');\n readonly query = model('');\n readonly optionSelected = output<string>();\n\n readonly suggestions = computed(() => {\n const q = this.query().toLowerCase();\n if (!q) return [];\n return this.items().filter((i) => i.toLowerCase().includes(q)).slice(0, 8);\n });\n\n onQuery(event: Event): void {\n this.query.set((event.target as HTMLInputElement).value);\n }\n\n pick(item: string): void {\n this.value.set(item);\n this.query.set(item);\n this.optionSelected.emit(item);\n }\n}\n"]}
1
+ {"version":3,"file":"autocomplete.component.js","sourceRoot":"","sources":["../../../../../../../libs/vortex-ui/src/lib/components/autocomplete/autocomplete.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,uBAAuB,EACvB,QAAQ,EACR,KAAK,EACL,KAAK,EACL,MAAM,EACN,MAAM,GACP,MAAM,eAAe,CAAC;;AAqGvB,MAAM,OAAO,uBAAuB;IACzB,KAAK,GAAG,KAAK;yFAAU,CAAC;IACxB,WAAW,GAAG,KAAK,CAAC,SAAS;oFAAC,CAAC;IAC/B,KAAK,GAAG,KAAK,CAAW,EAAE;8EAAC,CAAC;IAC5B,KAAK,GAAG,KAAK,CAAC,EAAE;8EAAC,CAAC;IAClB,KAAK,GAAG,KAAK,CAAC,EAAE;8EAAC,CAAC;IAClB,cAAc,GAAG,MAAM,EAAU,CAAC;IAE3C,yDAAyD;IACxC,IAAI,GAAG,MAAM,CAAC,KAAK;6EAAC,CAAC;IAE7B,WAAW,GAAG,QAAQ,CAAC,GAAG,EAAE;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,KAAK,EAAE;aAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;aAC1C,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjB,CAAC;oFAAC,CAAC;IAEM,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,GAAG,CAAC;kFAAC,CAAC;IAElF,OAAO,CAAC,KAAY;QAClB,MAAM,IAAI,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QACtD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;uGAxCU,uBAAuB;2FAAvB,uBAAuB,4xBA/FxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BT;;2FAkEU,uBAAuB;kBAnGnC,SAAS;+BACE,iBAAiB,cACf,IAAI,mBACC,uBAAuB,CAAC,MAAM,YACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BT","sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n computed,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\n\n@Component({\n selector: 'vx-autocomplete',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <label class=\"vx-field\">\n @if (label()) {\n <span class=\"vx-field__label\">{{ label() }}</span>\n }\n <input\n class=\"vx-ac\"\n type=\"search\"\n [placeholder]=\"placeholder()\"\n [value]=\"query()\"\n (input)=\"onQuery($event)\"\n (focus)=\"onFocus()\"\n (keydown.escape)=\"close()\"\n [attr.aria-expanded]=\"panelOpen()\"\n aria-autocomplete=\"list\"\n aria-label=\"Autocomplete\"\n />\n @if (panelOpen()) {\n <ul class=\"vx-ac__list\" role=\"listbox\">\n @for (item of suggestions(); track item) {\n <li>\n <button type=\"button\" role=\"option\" (mousedown)=\"$event.preventDefault()\" (click)=\"pick(item)\">\n {{ item }}\n </button>\n </li>\n }\n </ul>\n }\n </label>\n `,\n styles: `\n :host {\n display: block;\n position: relative;\n }\n .vx-field {\n display: flex;\n flex-direction: column;\n gap: var(--vx-space-1);\n font-family: var(--vx-font-sans);\n }\n .vx-field__label {\n font-size: var(--vx-font-size-sm);\n font-weight: var(--vx-font-weight-medium);\n }\n .vx-ac {\n height: 2.5rem;\n padding: 0 var(--vx-space-3);\n width: 100%;\n box-sizing: border-box;\n border: 1px solid var(--vx-color-border-strong);\n border-radius: var(--vx-radius-md);\n font: inherit;\n font-size: var(--vx-font-size-sm);\n background: var(--vx-color-bg-elevated);\n color: var(--vx-color-text);\n }\n .vx-ac:focus {\n outline: none;\n border-color: var(--vx-color-border-focus);\n box-shadow: var(--vx-focus-ring);\n }\n .vx-ac__list {\n list-style: none;\n margin: 0;\n padding: var(--vx-space-1);\n position: absolute;\n z-index: 5;\n left: 0;\n right: 0;\n width: 100%;\n box-sizing: border-box;\n background: var(--vx-color-surface);\n border: 1px solid var(--vx-color-border);\n border-radius: var(--vx-radius-md);\n max-height: 180px;\n overflow: auto;\n box-shadow: var(--vx-shadow-md, 0 4px 12px rgb(0 0 0 / 0.12));\n }\n .vx-ac__list button {\n width: 100%;\n text-align: left;\n border: none;\n background: none;\n padding: var(--vx-space-2);\n font: inherit;\n color: var(--vx-color-text);\n cursor: pointer;\n border-radius: var(--vx-radius-sm);\n }\n .vx-ac__list button:hover {\n background: var(--vx-color-bg-muted);\n }\n `,\n})\nexport class VxAutocompleteComponent {\n readonly label = input<string>();\n readonly placeholder = input('Buscar…');\n readonly items = input<string[]>([]);\n readonly value = model('');\n readonly query = model('');\n readonly optionSelected = output<string>();\n\n /** Controla abertura do painel (fecha ao selecionar). */\n private readonly open = signal(false);\n\n readonly suggestions = computed(() => {\n const q = this.query().trim().toLowerCase();\n if (!q) return [];\n return this.items()\n .filter((i) => i.toLowerCase().includes(q))\n .slice(0, 8);\n });\n\n readonly panelOpen = computed(() => this.open() && this.suggestions().length > 0);\n\n onQuery(event: Event): void {\n const next = (event.target as HTMLInputElement).value;\n this.query.set(next);\n this.open.set(true);\n }\n\n onFocus(): void {\n if (this.suggestions().length) this.open.set(true);\n }\n\n close(): void {\n this.open.set(false);\n }\n\n pick(item: string): void {\n this.value.set(item);\n this.query.set(item);\n this.open.set(false);\n this.optionSelected.emit(item);\n }\n}\n"]}
@@ -35,6 +35,15 @@ export class VxDataGridComponent {
35
35
  ...(ngDevMode ? [{ debugName: "selectable" }] : /* istanbul ignore next */ []));
36
36
  multiSelect = input(true, /* @ts-ignore */
37
37
  ...(ngDevMode ? [{ debugName: "multiSelect" }] : /* istanbul ignore next */ []));
38
+ /**
39
+ * Linhas verticais entre colunas (header + cells).
40
+ * Default `false` — visual Fluent / DevExtreme sem grade vertical.
41
+ */
42
+ showColumnLines = input(false, /* @ts-ignore */
43
+ ...(ngDevMode ? [{ debugName: "showColumnLines" }] : /* istanbul ignore next */ []));
44
+ /** Linhas horizontais entre rows. Default `true`. */
45
+ showRowLines = input(true, /* @ts-ignore */
46
+ ...(ngDevMode ? [{ debugName: "showRowLines" }] : /* istanbul ignore next */ []));
38
47
  /** Habilita edição inline (duplo clique). */
39
48
  editable = input(false, /* @ts-ignore */
40
49
  ...(ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []));
@@ -73,6 +82,9 @@ export class VxDataGridComponent {
73
82
  ...(ngDevMode ? [{ debugName: "scrollTop" }] : /* istanbul ignore next */ []));
74
83
  viewportHeight = signal(400, /* @ts-ignore */
75
84
  ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
85
+ /** Compensa a barra de rolagem do body para alinhar header ↔ rows. */
86
+ scrollbarWidth = signal(0, /* @ts-ignore */
87
+ ...(ngDevMode ? [{ debugName: "scrollbarWidth" }] : /* istanbul ignore next */ []));
76
88
  windowRows = signal([], /* @ts-ignore */
77
89
  ...(ngDevMode ? [{ debugName: "windowRows" }] : /* istanbul ignore next */ []));
78
90
  startIndex = signal(0, /* @ts-ignore */
@@ -256,6 +268,7 @@ export class VxDataGridComponent {
256
268
  if (!body)
257
269
  return;
258
270
  const measure = () => {
271
+ this.syncScrollbarGap(body);
259
272
  const h = body.clientHeight || 400;
260
273
  if (Math.abs(h - this.lastViewportH) < 2)
261
274
  return;
@@ -267,9 +280,15 @@ export class VxDataGridComponent {
267
280
  this.resizeObserver = new ResizeObserver(() => measure());
268
281
  this.resizeObserver.observe(body);
269
282
  }
283
+ syncScrollbarGap(body) {
284
+ const gap = Math.max(0, body.offsetWidth - body.clientWidth);
285
+ if (gap !== this.scrollbarWidth())
286
+ this.scrollbarWidth.set(gap);
287
+ }
270
288
  onScroll(event) {
271
289
  const body = event.target;
272
290
  const header = this.headerRef()?.nativeElement;
291
+ this.syncScrollbarGap(body);
273
292
  if (header)
274
293
  header.scrollLeft = body.scrollLeft;
275
294
  if (this.scrollRaf)
@@ -770,10 +789,12 @@ export class VxDataGridComponent {
770
789
  this.exported.emit({ format: 'csv', count: rows.length });
771
790
  }
772
791
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.6", ngImport: i0, type: VxDataGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
773
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.6", type: VxDataGridComponent, isStandalone: true, selector: "vx-data-grid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, totalCount: { classPropertyName: "totalCount", publicName: "totalCount", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, overscan: { classPropertyName: "overscan", publicName: "overscan", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, trackByField: { classPropertyName: "trackByField", publicName: "trackByField", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, multiSelect: { classPropertyName: "multiSelect", publicName: "multiSelect", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, exportEnabled: { classPropertyName: "exportEnabled", publicName: "exportEnabled", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, ai: { classPropertyName: "ai", publicName: "ai", isSignal: true, isRequired: false, transformFunction: null }, aiIntegration: { classPropertyName: "aiIntegration", publicName: "aiIntegration", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { groupBy: "groupByChange", sortChange: "sortChange", filterChange: "filterChange", selectionChange: "selectionChange", rowClick: "rowClick", cellEdit: "cellEdit", exported: "exported", loadRequest: "loadRequest", aiRequestCreating: "aiRequestCreating", aiCommandExecuted: "aiCommandExecuted", aiRequestCompleted: "aiRequestCompleted", aiRequestFailed: "aiRequestFailed" }, viewQueries: [{ propertyName: "bodyRef", first: true, predicate: ["bodyRef"], descendants: true, isSignal: true }, { propertyName: "headerRef", first: true, predicate: ["headerRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
792
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.6", type: VxDataGridComponent, isStandalone: true, selector: "vx-data-grid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, totalCount: { classPropertyName: "totalCount", publicName: "totalCount", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, overscan: { classPropertyName: "overscan", publicName: "overscan", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, trackByField: { classPropertyName: "trackByField", publicName: "trackByField", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, multiSelect: { classPropertyName: "multiSelect", publicName: "multiSelect", isSignal: true, isRequired: false, transformFunction: null }, showColumnLines: { classPropertyName: "showColumnLines", publicName: "showColumnLines", isSignal: true, isRequired: false, transformFunction: null }, showRowLines: { classPropertyName: "showRowLines", publicName: "showRowLines", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, exportEnabled: { classPropertyName: "exportEnabled", publicName: "exportEnabled", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, ai: { classPropertyName: "ai", publicName: "ai", isSignal: true, isRequired: false, transformFunction: null }, aiIntegration: { classPropertyName: "aiIntegration", publicName: "aiIntegration", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { groupBy: "groupByChange", sortChange: "sortChange", filterChange: "filterChange", selectionChange: "selectionChange", rowClick: "rowClick", cellEdit: "cellEdit", exported: "exported", loadRequest: "loadRequest", aiRequestCreating: "aiRequestCreating", aiCommandExecuted: "aiCommandExecuted", aiRequestCompleted: "aiRequestCompleted", aiRequestFailed: "aiRequestFailed" }, viewQueries: [{ propertyName: "bodyRef", first: true, predicate: ["bodyRef"], descendants: true, isSignal: true }, { propertyName: "headerRef", first: true, predicate: ["headerRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
774
793
  <div
775
794
  class="vx-grid"
776
795
  role="grid"
796
+ [class.vx-grid--column-lines]="showColumnLines()"
797
+ [class.vx-grid--row-lines]="showRowLines()"
777
798
  [attr.aria-rowcount]="totalRows()"
778
799
  [attr.aria-colcount]="columns().length"
779
800
  [attr.aria-busy]="loading() || remoteLoading() || aiBusy()"
@@ -852,7 +873,12 @@ export class VxDataGridComponent {
852
873
  </div>
853
874
  </div>
854
875
 
855
- <div class="vx-grid__header" #headerRef role="row">
876
+ <div
877
+ class="vx-grid__header"
878
+ #headerRef
879
+ role="row"
880
+ [style.padding-inline-end.px]="scrollbarWidth()"
881
+ >
856
882
  @for (col of columns(); track col.field) {
857
883
  <div
858
884
  class="vx-grid__header-cell"
@@ -982,7 +1008,7 @@ export class VxDataGridComponent {
982
1008
  (apply)="onPromptApply($event)"
983
1009
  />
984
1010
  }
985
- `, isInline: true, styles: [":host{display:block;height:100%;min-height:300px;position:relative}.vx-grid{display:flex;flex-direction:column;height:100%;min-height:300px;border:1px solid var(--vx-grid-border);border-radius:var(--vx-radius-md);background:var(--vx-color-surface);overflow:hidden;font-size:var(--vx-font-size-sm);font-family:var(--vx-font-sans);position:relative}.vx-grid__toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--vx-space-2);padding:var(--vx-space-2) var(--vx-space-3);border-bottom:1px solid var(--vx-grid-border);background:var(--vx-color-bg-subtle);flex-shrink:0;min-height:2.75rem;box-sizing:border-box;overflow:visible}.vx-grid__toolbar-left,.vx-grid__toolbar-right{display:flex;align-items:center;gap:var(--vx-space-2);min-width:0}.vx-grid__toolbar-right{flex-shrink:0}.vx-grid__toolbar-hint{color:var(--vx-color-text-muted);font-size:var(--vx-font-size-xs)}.vx-grid__filter-pill{display:inline-flex;align-items:center;gap:var(--vx-space-2);padding:.2rem .6rem;border-radius:999px;background:var(--vx-color-badge-bg, var(--vx-color-primary-subtle));color:var(--vx-color-badge-fg, var(--vx-color-primary-ink));font-size:var(--vx-font-size-xs)}.vx-grid__group-label{display:inline-flex;align-items:center;gap:var(--vx-space-2);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary)}.vx-grid__group-select{height:1.75rem;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;font-size:var(--vx-font-size-xs)}.vx-grid__row--group{background:var(--vx-color-bg-muted);font-weight:var(--vx-font-weight-semibold);cursor:pointer}.vx-grid__cell--group{flex:1;width:100%!important;gap:var(--vx-space-2)}.vx-grid__group-chevron{display:inline-block;transition:transform var(--vx-transition-fast);color:var(--vx-color-text-secondary)}.vx-grid__group-chevron--open{transform:rotate(90deg)}.vx-grid__group-count{color:var(--vx-color-text-secondary);font-weight:var(--vx-font-weight-normal)}.vx-grid__edit-input{width:100%;height:1.6rem;border:1px solid var(--vx-color-border-focus);border-radius:var(--vx-radius-sm);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;padding:0 var(--vx-space-1);box-shadow:var(--vx-focus-ring)}.vx-grid__cell--editing{padding:2px var(--vx-space-1)}.vx-grid__filter-clear{border:none;background:transparent;color:inherit;cursor:pointer;text-decoration:underline;font:inherit;padding:0}.vx-grid__tool-btn{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;height:2rem;min-width:2rem;padding:0 .7rem;border-radius:var(--vx-radius-md);border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-text);cursor:pointer;font:inherit;font-size:var(--vx-font-size-xs);font-weight:var(--vx-font-weight-semibold);line-height:1;white-space:nowrap;flex-shrink:0}.vx-grid__tool-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle);color:var(--vx-color-primary-ink, var(--vx-color-primary))}.vx-grid__tool-btn-icon{font-size:.85rem;line-height:1}.vx-grid__ai-btn{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border-radius:999px;border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-primary);cursor:pointer;font-size:.95rem;line-height:1;flex-shrink:0}.vx-grid__ai-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle)}.vx-grid__ai-btn--ghost{color:var(--vx-color-text-secondary)}.vx-grid__header{display:flex;width:100%;background:var(--vx-grid-header-bg);border-bottom:1px solid var(--vx-grid-border);font-weight:var(--vx-font-weight-semibold);color:var(--vx-color-text);flex-shrink:0;overflow:hidden;-webkit-user-select:none;user-select:none;z-index:2}.vx-grid__header-cell{display:flex;align-items:center;gap:var(--vx-space-1);padding:0 var(--vx-space-3);height:40px;border-right:1px solid var(--vx-grid-border);cursor:pointer;box-sizing:border-box;overflow:hidden;min-width:0}.vx-grid__header-cell:hover{background:var(--vx-color-bg-hover)}.vx-grid__header-cell--ai{color:var(--vx-color-primary);gap:var(--vx-space-2)}.vx-grid__ai-col-icon{font-size:.85rem}.vx-grid__cell--ai{font-style:italic;color:var(--vx-color-text-secondary)}.vx-grid__cell--ai-empty{color:var(--vx-color-text-muted);font-style:normal}.vx-grid__cell--ai-loading{opacity:.7}.vx-grid__ai-skeleton{letter-spacing:.15em;color:var(--vx-color-text-muted)}.vx-grid__body{flex:1;overflow:auto;position:relative;min-height:0;contain:strict}.vx-grid__spacer{width:1px;pointer-events:none}.vx-grid__window{position:absolute;top:0;left:0;right:0;width:100%;will-change:transform}.vx-grid__row{display:flex;width:100%;border-bottom:1px solid var(--vx-grid-border);cursor:pointer;box-sizing:border-box;background:var(--vx-color-surface)}.vx-grid__row--stripe{background:var(--vx-grid-stripe)}.vx-grid__row:hover{background:var(--vx-grid-row-hover)}.vx-grid__row--selected{background:var(--vx-grid-row-selected)}.vx-grid__cell{padding:0 var(--vx-space-3);display:flex;align-items:center;border-right:1px solid var(--vx-grid-border);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--vx-color-text);box-sizing:border-box;min-width:0}.vx-grid__footer{display:flex;justify-content:space-between;align-items:center;gap:var(--vx-space-3);padding:var(--vx-space-2) var(--vx-space-4);border-top:1px solid var(--vx-grid-border);background:var(--vx-grid-header-bg);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary);flex-shrink:0}.vx-grid__loading,.vx-grid__empty{display:flex;align-items:center;justify-content:center;height:200px;color:var(--vx-color-text-muted)}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: VxAIAssistantDialogComponent, selector: "vx-ai-assistant-dialog", inputs: ["open", "title", "placeholder", "messages", "suggestions", "busy"], outputs: ["openChange", "sendMessage", "suggestionSelect", "clear", "closed"] }, { kind: "component", type: VxAIPromptEditorComponent, selector: "vx-ai-prompt-editor", inputs: ["open", "title", "placeholder", "prompt", "canApply"], outputs: ["openChange", "promptChange", "regenerate", "apply", "closed"] }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1011
+ `, isInline: true, styles: [":host{display:block;height:100%;min-height:300px;position:relative}.vx-grid{display:flex;flex-direction:column;height:100%;min-height:300px;border:1px solid var(--vx-grid-border);border-radius:var(--vx-radius-md);background:var(--vx-color-surface);overflow:hidden;font-size:var(--vx-font-size-sm);font-family:var(--vx-font-sans);position:relative}.vx-grid__toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--vx-space-2);padding:var(--vx-space-2) var(--vx-space-3);border-bottom:1px solid var(--vx-grid-border);background:var(--vx-color-bg-subtle);flex-shrink:0;min-height:2.75rem;box-sizing:border-box;overflow:visible}.vx-grid__toolbar-left,.vx-grid__toolbar-right{display:flex;align-items:center;gap:var(--vx-space-2);min-width:0}.vx-grid__toolbar-right{flex-shrink:0}.vx-grid__toolbar-hint{color:var(--vx-color-text-muted);font-size:var(--vx-font-size-xs)}.vx-grid__filter-pill{display:inline-flex;align-items:center;gap:var(--vx-space-2);padding:.2rem .6rem;border-radius:999px;background:var(--vx-color-badge-bg, var(--vx-color-primary-subtle));color:var(--vx-color-badge-fg, var(--vx-color-primary-ink));font-size:var(--vx-font-size-xs)}.vx-grid__group-label{display:inline-flex;align-items:center;gap:var(--vx-space-2);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary)}.vx-grid__group-select{height:1.75rem;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;font-size:var(--vx-font-size-xs)}.vx-grid__row--group{background:var(--vx-color-bg-muted);font-weight:var(--vx-font-weight-semibold);cursor:pointer}.vx-grid__cell--group{flex:1;width:100%!important;gap:var(--vx-space-2)}.vx-grid__group-chevron{display:inline-block;transition:transform var(--vx-transition-fast);color:var(--vx-color-text-secondary)}.vx-grid__group-chevron--open{transform:rotate(90deg)}.vx-grid__group-count{color:var(--vx-color-text-secondary);font-weight:var(--vx-font-weight-normal)}.vx-grid__edit-input{width:100%;height:1.6rem;border:1px solid var(--vx-color-border-focus);border-radius:var(--vx-radius-sm);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;padding:0 var(--vx-space-1);box-shadow:var(--vx-focus-ring)}.vx-grid__cell--editing{padding:2px var(--vx-space-1)}.vx-grid__filter-clear{border:none;background:transparent;color:inherit;cursor:pointer;text-decoration:underline;font:inherit;padding:0}.vx-grid__tool-btn{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;height:2rem;min-width:2rem;padding:0 .7rem;border-radius:var(--vx-radius-md);border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-text);cursor:pointer;font:inherit;font-size:var(--vx-font-size-xs);font-weight:var(--vx-font-weight-semibold);line-height:1;white-space:nowrap;flex-shrink:0}.vx-grid__tool-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle);color:var(--vx-color-primary-ink, var(--vx-color-primary))}.vx-grid__tool-btn-icon{font-size:.85rem;line-height:1}.vx-grid__ai-btn{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border-radius:999px;border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-primary);cursor:pointer;font-size:.95rem;line-height:1;flex-shrink:0}.vx-grid__ai-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle)}.vx-grid__ai-btn--ghost{color:var(--vx-color-text-secondary)}.vx-grid__header{display:flex;width:100%;box-sizing:border-box;background:var(--vx-grid-header-bg);border-bottom:1px solid var(--vx-grid-border);font-weight:var(--vx-font-weight-semibold);color:var(--vx-color-text);flex-shrink:0;overflow:hidden;-webkit-user-select:none;user-select:none;z-index:2}.vx-grid__header-cell{display:flex;align-items:center;gap:var(--vx-space-1);padding:0 var(--vx-space-3);height:40px;border-right:none;cursor:pointer;box-sizing:border-box;overflow:hidden;min-width:0}.vx-grid--column-lines .vx-grid__header-cell{border-right:1px solid var(--vx-grid-border)}.vx-grid--column-lines .vx-grid__header-cell:last-child{border-right:none}.vx-grid__header-cell:hover{background:var(--vx-color-bg-hover)}.vx-grid__header-cell--ai{color:var(--vx-color-primary);gap:var(--vx-space-2)}.vx-grid__ai-col-icon{font-size:.85rem}.vx-grid__cell--ai{font-style:italic;color:var(--vx-color-text-secondary)}.vx-grid__cell--ai-empty{color:var(--vx-color-text-muted);font-style:normal}.vx-grid__cell--ai-loading{opacity:.7}.vx-grid__ai-skeleton{letter-spacing:.15em;color:var(--vx-color-text-muted)}.vx-grid__body{flex:1;overflow:auto;position:relative;min-height:0;contain:strict;scrollbar-gutter:stable}.vx-grid__spacer{width:1px;pointer-events:none}.vx-grid__window{position:absolute;top:0;left:0;right:0;width:100%;will-change:transform}.vx-grid__row{display:flex;width:100%;border-bottom:none;cursor:pointer;box-sizing:border-box;background:var(--vx-color-surface)}.vx-grid--row-lines .vx-grid__row{border-bottom:1px solid var(--vx-grid-border)}.vx-grid__row--stripe{background:var(--vx-grid-stripe)}.vx-grid__row:hover{background:var(--vx-grid-row-hover)}.vx-grid__row--selected{background:var(--vx-grid-row-selected)}.vx-grid__cell{padding:0 var(--vx-space-3);display:flex;align-items:center;border-right:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--vx-color-text);box-sizing:border-box;min-width:0}.vx-grid--column-lines .vx-grid__cell{border-right:1px solid var(--vx-grid-border)}.vx-grid--column-lines .vx-grid__cell:last-child{border-right:none}.vx-grid__footer{display:flex;justify-content:space-between;align-items:center;gap:var(--vx-space-3);padding:var(--vx-space-2) var(--vx-space-4);border-top:1px solid var(--vx-grid-border);background:var(--vx-grid-header-bg);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary);flex-shrink:0}.vx-grid__loading,.vx-grid__empty{display:flex;align-items:center;justify-content:center;height:200px;color:var(--vx-color-text-muted)}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: VxAIAssistantDialogComponent, selector: "vx-ai-assistant-dialog", inputs: ["open", "title", "placeholder", "messages", "suggestions", "busy"], outputs: ["openChange", "sendMessage", "suggestionSelect", "clear", "closed"] }, { kind: "component", type: VxAIPromptEditorComponent, selector: "vx-ai-prompt-editor", inputs: ["open", "title", "placeholder", "prompt", "canApply"], outputs: ["openChange", "promptChange", "regenerate", "apply", "closed"] }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
986
1012
  }
987
1013
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.6", ngImport: i0, type: VxDataGridComponent, decorators: [{
988
1014
  type: Component,
@@ -990,6 +1016,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.6", ngImpor
990
1016
  <div
991
1017
  class="vx-grid"
992
1018
  role="grid"
1019
+ [class.vx-grid--column-lines]="showColumnLines()"
1020
+ [class.vx-grid--row-lines]="showRowLines()"
993
1021
  [attr.aria-rowcount]="totalRows()"
994
1022
  [attr.aria-colcount]="columns().length"
995
1023
  [attr.aria-busy]="loading() || remoteLoading() || aiBusy()"
@@ -1068,7 +1096,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.6", ngImpor
1068
1096
  </div>
1069
1097
  </div>
1070
1098
 
1071
- <div class="vx-grid__header" #headerRef role="row">
1099
+ <div
1100
+ class="vx-grid__header"
1101
+ #headerRef
1102
+ role="row"
1103
+ [style.padding-inline-end.px]="scrollbarWidth()"
1104
+ >
1072
1105
  @for (col of columns(); track col.field) {
1073
1106
  <div
1074
1107
  class="vx-grid__header-cell"
@@ -1198,6 +1231,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.6", ngImpor
1198
1231
  (apply)="onPromptApply($event)"
1199
1232
  />
1200
1233
  }
1201
- `, styles: [":host{display:block;height:100%;min-height:300px;position:relative}.vx-grid{display:flex;flex-direction:column;height:100%;min-height:300px;border:1px solid var(--vx-grid-border);border-radius:var(--vx-radius-md);background:var(--vx-color-surface);overflow:hidden;font-size:var(--vx-font-size-sm);font-family:var(--vx-font-sans);position:relative}.vx-grid__toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--vx-space-2);padding:var(--vx-space-2) var(--vx-space-3);border-bottom:1px solid var(--vx-grid-border);background:var(--vx-color-bg-subtle);flex-shrink:0;min-height:2.75rem;box-sizing:border-box;overflow:visible}.vx-grid__toolbar-left,.vx-grid__toolbar-right{display:flex;align-items:center;gap:var(--vx-space-2);min-width:0}.vx-grid__toolbar-right{flex-shrink:0}.vx-grid__toolbar-hint{color:var(--vx-color-text-muted);font-size:var(--vx-font-size-xs)}.vx-grid__filter-pill{display:inline-flex;align-items:center;gap:var(--vx-space-2);padding:.2rem .6rem;border-radius:999px;background:var(--vx-color-badge-bg, var(--vx-color-primary-subtle));color:var(--vx-color-badge-fg, var(--vx-color-primary-ink));font-size:var(--vx-font-size-xs)}.vx-grid__group-label{display:inline-flex;align-items:center;gap:var(--vx-space-2);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary)}.vx-grid__group-select{height:1.75rem;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;font-size:var(--vx-font-size-xs)}.vx-grid__row--group{background:var(--vx-color-bg-muted);font-weight:var(--vx-font-weight-semibold);cursor:pointer}.vx-grid__cell--group{flex:1;width:100%!important;gap:var(--vx-space-2)}.vx-grid__group-chevron{display:inline-block;transition:transform var(--vx-transition-fast);color:var(--vx-color-text-secondary)}.vx-grid__group-chevron--open{transform:rotate(90deg)}.vx-grid__group-count{color:var(--vx-color-text-secondary);font-weight:var(--vx-font-weight-normal)}.vx-grid__edit-input{width:100%;height:1.6rem;border:1px solid var(--vx-color-border-focus);border-radius:var(--vx-radius-sm);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;padding:0 var(--vx-space-1);box-shadow:var(--vx-focus-ring)}.vx-grid__cell--editing{padding:2px var(--vx-space-1)}.vx-grid__filter-clear{border:none;background:transparent;color:inherit;cursor:pointer;text-decoration:underline;font:inherit;padding:0}.vx-grid__tool-btn{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;height:2rem;min-width:2rem;padding:0 .7rem;border-radius:var(--vx-radius-md);border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-text);cursor:pointer;font:inherit;font-size:var(--vx-font-size-xs);font-weight:var(--vx-font-weight-semibold);line-height:1;white-space:nowrap;flex-shrink:0}.vx-grid__tool-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle);color:var(--vx-color-primary-ink, var(--vx-color-primary))}.vx-grid__tool-btn-icon{font-size:.85rem;line-height:1}.vx-grid__ai-btn{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border-radius:999px;border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-primary);cursor:pointer;font-size:.95rem;line-height:1;flex-shrink:0}.vx-grid__ai-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle)}.vx-grid__ai-btn--ghost{color:var(--vx-color-text-secondary)}.vx-grid__header{display:flex;width:100%;background:var(--vx-grid-header-bg);border-bottom:1px solid var(--vx-grid-border);font-weight:var(--vx-font-weight-semibold);color:var(--vx-color-text);flex-shrink:0;overflow:hidden;-webkit-user-select:none;user-select:none;z-index:2}.vx-grid__header-cell{display:flex;align-items:center;gap:var(--vx-space-1);padding:0 var(--vx-space-3);height:40px;border-right:1px solid var(--vx-grid-border);cursor:pointer;box-sizing:border-box;overflow:hidden;min-width:0}.vx-grid__header-cell:hover{background:var(--vx-color-bg-hover)}.vx-grid__header-cell--ai{color:var(--vx-color-primary);gap:var(--vx-space-2)}.vx-grid__ai-col-icon{font-size:.85rem}.vx-grid__cell--ai{font-style:italic;color:var(--vx-color-text-secondary)}.vx-grid__cell--ai-empty{color:var(--vx-color-text-muted);font-style:normal}.vx-grid__cell--ai-loading{opacity:.7}.vx-grid__ai-skeleton{letter-spacing:.15em;color:var(--vx-color-text-muted)}.vx-grid__body{flex:1;overflow:auto;position:relative;min-height:0;contain:strict}.vx-grid__spacer{width:1px;pointer-events:none}.vx-grid__window{position:absolute;top:0;left:0;right:0;width:100%;will-change:transform}.vx-grid__row{display:flex;width:100%;border-bottom:1px solid var(--vx-grid-border);cursor:pointer;box-sizing:border-box;background:var(--vx-color-surface)}.vx-grid__row--stripe{background:var(--vx-grid-stripe)}.vx-grid__row:hover{background:var(--vx-grid-row-hover)}.vx-grid__row--selected{background:var(--vx-grid-row-selected)}.vx-grid__cell{padding:0 var(--vx-space-3);display:flex;align-items:center;border-right:1px solid var(--vx-grid-border);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--vx-color-text);box-sizing:border-box;min-width:0}.vx-grid__footer{display:flex;justify-content:space-between;align-items:center;gap:var(--vx-space-3);padding:var(--vx-space-2) var(--vx-space-4);border-top:1px solid var(--vx-grid-border);background:var(--vx-grid-header-bg);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary);flex-shrink:0}.vx-grid__loading,.vx-grid__empty{display:flex;align-items:center;justify-content:center;height:200px;color:var(--vx-color-text-muted)}\n"] }]
1202
- }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], totalCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalCount", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], overscan: [{ type: i0.Input, args: [{ isSignal: true, alias: "overscan", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], trackByField: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackByField", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], multiSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSelect", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], exportEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportEnabled", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }, { type: i0.Output, args: ["groupByChange"] }], ai: [{ type: i0.Input, args: [{ isSignal: true, alias: "ai", required: false }] }], aiIntegration: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiIntegration", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], exported: [{ type: i0.Output, args: ["exported"] }], loadRequest: [{ type: i0.Output, args: ["loadRequest"] }], aiRequestCreating: [{ type: i0.Output, args: ["aiRequestCreating"] }], aiCommandExecuted: [{ type: i0.Output, args: ["aiCommandExecuted"] }], aiRequestCompleted: [{ type: i0.Output, args: ["aiRequestCompleted"] }], aiRequestFailed: [{ type: i0.Output, args: ["aiRequestFailed"] }], bodyRef: [{ type: i0.ViewChild, args: ['bodyRef', { isSignal: true }] }], headerRef: [{ type: i0.ViewChild, args: ['headerRef', { isSignal: true }] }] } });
1234
+ `, styles: [":host{display:block;height:100%;min-height:300px;position:relative}.vx-grid{display:flex;flex-direction:column;height:100%;min-height:300px;border:1px solid var(--vx-grid-border);border-radius:var(--vx-radius-md);background:var(--vx-color-surface);overflow:hidden;font-size:var(--vx-font-size-sm);font-family:var(--vx-font-sans);position:relative}.vx-grid__toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--vx-space-2);padding:var(--vx-space-2) var(--vx-space-3);border-bottom:1px solid var(--vx-grid-border);background:var(--vx-color-bg-subtle);flex-shrink:0;min-height:2.75rem;box-sizing:border-box;overflow:visible}.vx-grid__toolbar-left,.vx-grid__toolbar-right{display:flex;align-items:center;gap:var(--vx-space-2);min-width:0}.vx-grid__toolbar-right{flex-shrink:0}.vx-grid__toolbar-hint{color:var(--vx-color-text-muted);font-size:var(--vx-font-size-xs)}.vx-grid__filter-pill{display:inline-flex;align-items:center;gap:var(--vx-space-2);padding:.2rem .6rem;border-radius:999px;background:var(--vx-color-badge-bg, var(--vx-color-primary-subtle));color:var(--vx-color-badge-fg, var(--vx-color-primary-ink));font-size:var(--vx-font-size-xs)}.vx-grid__group-label{display:inline-flex;align-items:center;gap:var(--vx-space-2);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary)}.vx-grid__group-select{height:1.75rem;border:1px solid var(--vx-color-border-strong);border-radius:var(--vx-radius-md);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;font-size:var(--vx-font-size-xs)}.vx-grid__row--group{background:var(--vx-color-bg-muted);font-weight:var(--vx-font-weight-semibold);cursor:pointer}.vx-grid__cell--group{flex:1;width:100%!important;gap:var(--vx-space-2)}.vx-grid__group-chevron{display:inline-block;transition:transform var(--vx-transition-fast);color:var(--vx-color-text-secondary)}.vx-grid__group-chevron--open{transform:rotate(90deg)}.vx-grid__group-count{color:var(--vx-color-text-secondary);font-weight:var(--vx-font-weight-normal)}.vx-grid__edit-input{width:100%;height:1.6rem;border:1px solid var(--vx-color-border-focus);border-radius:var(--vx-radius-sm);background:var(--vx-color-bg-elevated);color:var(--vx-color-text);font:inherit;padding:0 var(--vx-space-1);box-shadow:var(--vx-focus-ring)}.vx-grid__cell--editing{padding:2px var(--vx-space-1)}.vx-grid__filter-clear{border:none;background:transparent;color:inherit;cursor:pointer;text-decoration:underline;font:inherit;padding:0}.vx-grid__tool-btn{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;height:2rem;min-width:2rem;padding:0 .7rem;border-radius:var(--vx-radius-md);border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-text);cursor:pointer;font:inherit;font-size:var(--vx-font-size-xs);font-weight:var(--vx-font-weight-semibold);line-height:1;white-space:nowrap;flex-shrink:0}.vx-grid__tool-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle);color:var(--vx-color-primary-ink, var(--vx-color-primary))}.vx-grid__tool-btn-icon{font-size:.85rem;line-height:1}.vx-grid__ai-btn{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border-radius:999px;border:1px solid var(--vx-color-border);background:var(--vx-color-surface);color:var(--vx-color-primary);cursor:pointer;font-size:.95rem;line-height:1;flex-shrink:0}.vx-grid__ai-btn:hover{border-color:var(--vx-color-primary);background:var(--vx-color-primary-subtle)}.vx-grid__ai-btn--ghost{color:var(--vx-color-text-secondary)}.vx-grid__header{display:flex;width:100%;box-sizing:border-box;background:var(--vx-grid-header-bg);border-bottom:1px solid var(--vx-grid-border);font-weight:var(--vx-font-weight-semibold);color:var(--vx-color-text);flex-shrink:0;overflow:hidden;-webkit-user-select:none;user-select:none;z-index:2}.vx-grid__header-cell{display:flex;align-items:center;gap:var(--vx-space-1);padding:0 var(--vx-space-3);height:40px;border-right:none;cursor:pointer;box-sizing:border-box;overflow:hidden;min-width:0}.vx-grid--column-lines .vx-grid__header-cell{border-right:1px solid var(--vx-grid-border)}.vx-grid--column-lines .vx-grid__header-cell:last-child{border-right:none}.vx-grid__header-cell:hover{background:var(--vx-color-bg-hover)}.vx-grid__header-cell--ai{color:var(--vx-color-primary);gap:var(--vx-space-2)}.vx-grid__ai-col-icon{font-size:.85rem}.vx-grid__cell--ai{font-style:italic;color:var(--vx-color-text-secondary)}.vx-grid__cell--ai-empty{color:var(--vx-color-text-muted);font-style:normal}.vx-grid__cell--ai-loading{opacity:.7}.vx-grid__ai-skeleton{letter-spacing:.15em;color:var(--vx-color-text-muted)}.vx-grid__body{flex:1;overflow:auto;position:relative;min-height:0;contain:strict;scrollbar-gutter:stable}.vx-grid__spacer{width:1px;pointer-events:none}.vx-grid__window{position:absolute;top:0;left:0;right:0;width:100%;will-change:transform}.vx-grid__row{display:flex;width:100%;border-bottom:none;cursor:pointer;box-sizing:border-box;background:var(--vx-color-surface)}.vx-grid--row-lines .vx-grid__row{border-bottom:1px solid var(--vx-grid-border)}.vx-grid__row--stripe{background:var(--vx-grid-stripe)}.vx-grid__row:hover{background:var(--vx-grid-row-hover)}.vx-grid__row--selected{background:var(--vx-grid-row-selected)}.vx-grid__cell{padding:0 var(--vx-space-3);display:flex;align-items:center;border-right:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--vx-color-text);box-sizing:border-box;min-width:0}.vx-grid--column-lines .vx-grid__cell{border-right:1px solid var(--vx-grid-border)}.vx-grid--column-lines .vx-grid__cell:last-child{border-right:none}.vx-grid__footer{display:flex;justify-content:space-between;align-items:center;gap:var(--vx-space-3);padding:var(--vx-space-2) var(--vx-space-4);border-top:1px solid var(--vx-grid-border);background:var(--vx-grid-header-bg);font-size:var(--vx-font-size-xs);color:var(--vx-color-text-secondary);flex-shrink:0}.vx-grid__loading,.vx-grid__empty{display:flex;align-items:center;justify-content:center;height:200px;color:var(--vx-color-text-muted)}\n"] }]
1235
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }], totalCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalCount", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], overscan: [{ type: i0.Input, args: [{ isSignal: true, alias: "overscan", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], trackByField: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackByField", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], multiSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSelect", required: false }] }], showColumnLines: [{ type: i0.Input, args: [{ isSignal: true, alias: "showColumnLines", required: false }] }], showRowLines: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRowLines", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], exportEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportEnabled", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }, { type: i0.Output, args: ["groupByChange"] }], ai: [{ type: i0.Input, args: [{ isSignal: true, alias: "ai", required: false }] }], aiIntegration: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiIntegration", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], exported: [{ type: i0.Output, args: ["exported"] }], loadRequest: [{ type: i0.Output, args: ["loadRequest"] }], aiRequestCreating: [{ type: i0.Output, args: ["aiRequestCreating"] }], aiCommandExecuted: [{ type: i0.Output, args: ["aiCommandExecuted"] }], aiRequestCompleted: [{ type: i0.Output, args: ["aiRequestCompleted"] }], aiRequestFailed: [{ type: i0.Output, args: ["aiRequestFailed"] }], bodyRef: [{ type: i0.ViewChild, args: ['bodyRef', { isSignal: true }] }], headerRef: [{ type: i0.ViewChild, args: ['headerRef', { isSignal: true }] }] } });
1203
1236
  //# sourceMappingURL=data-grid.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid.component.js","sourceRoot":"","sources":["../../../../../../../libs/vortex-ui/src/lib/components/data-grid/data-grid.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ElementRef,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n untracked,\n viewChild,\n DestroyRef,\n} from '@angular/core';\nimport { DecimalPipe, NgStyle } from '@angular/common';\nimport { VxCellEditEvent, VxColumnDef, VxSortState } from './data-grid.types';\nimport { VxDataSource, VxFilterState } from './data-source';\nimport { exportRowsToCsv } from './export-csv';\nimport {\n VortexAICommand,\n VortexAIConfig,\n VortexAIIntegration,\n VortexAIRequest,\n VortexAIRequestCreatingEvent,\n VortexAISuggestion,\n projectRowsForAI,\n VxAIAssistantDialogComponent,\n VxAIChatMessage,\n VxAIPromptEditorComponent,\n} from 'vortex-ui/ai';\n\nexport type {\n VxColumnDef,\n VxSortState,\n VxDataGridConfig,\n VxVirtualRange,\n VxCellEditEvent,\n} from './data-grid.types';\nexport type {\n VxDataSource,\n VxDataSourceLoadOptions,\n VxDataSourceLoadResult,\n VxFilterState,\n} from './data-source';\nexport { VxArrayDataSource, VxRemoteMockDataSource } from './data-source';\nexport { exportRowsToCsv } from './export-csv';\n\nconst MAX_SPACER_PX = 5_000_000;\n\nconst DEFAULT_AI: Required<\n Pick<VortexAIConfig, 'enabled' | 'maxRowsInContext'>\n> & { assistant: { enabled: boolean; title: string } } = {\n enabled: false,\n maxRowsInContext: 100,\n assistant: { enabled: true, title: 'AI Assistant' },\n};\n\n/** Linha sintética de agrupamento no viewport. */\nexport interface VxGroupRow {\n __vxGroup: true;\n key: string;\n label: string;\n count: number;\n}\n\n@Component({\n selector: 'vx-data-grid',\n standalone: true,\n imports: [DecimalPipe, NgStyle, VxAIAssistantDialogComponent, VxAIPromptEditorComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n class=\"vx-grid\"\n role=\"grid\"\n [attr.aria-rowcount]=\"totalRows()\"\n [attr.aria-colcount]=\"columns().length\"\n [attr.aria-busy]=\"loading() || remoteLoading() || aiBusy()\"\n >\n <div class=\"vx-grid__toolbar\">\n <div class=\"vx-grid__toolbar-left\">\n @if (filter(); as f) {\n <span class=\"vx-grid__filter-pill\">\n Filtro: {{ f.field }} ≈ {{ f.value }}\n <button type=\"button\" class=\"vx-grid__filter-clear\" (click)=\"clearFilter()\">\n limpar\n </button>\n </span>\n }\n @if (groupBy(); as g) {\n <span class=\"vx-grid__filter-pill\">\n Grupo: {{ g }}\n <button type=\"button\" class=\"vx-grid__filter-clear\" (click)=\"clearGroup()\">\n limpar\n </button>\n </span>\n } @else if (!filter()) {\n <span class=\"vx-grid__toolbar-hint\">\n {{ editable() ? 'Duplo clique para editar · ' : '' }}Agrupe via menu / AI\n </span>\n }\n @if (groupableFields().length) {\n <label class=\"vx-grid__group-label\">\n Agrupar\n <select\n class=\"vx-grid__group-select\"\n [value]=\"groupBy() ?? ''\"\n (change)=\"onGroupSelect($event)\"\n >\n <option value=\"\">(nenhum)</option>\n @for (f of groupableFields(); track f.field) {\n <option [value]=\"f.field\">{{ f.header }}</option>\n }\n </select>\n </label>\n }\n </div>\n <div class=\"vx-grid__toolbar-right\">\n @if (exportEnabled()) {\n <button\n type=\"button\"\n class=\"vx-grid__tool-btn\"\n aria-label=\"Exportar CSV\"\n title=\"Exportar CSV\"\n (click)=\"exportCsv()\"\n >\n <span class=\"vx-grid__tool-btn-icon\" aria-hidden=\"true\">↓</span>\n CSV\n </button>\n }\n @if (aiEnabled()) {\n <button\n type=\"button\"\n class=\"vx-grid__ai-btn\"\n aria-label=\"Abrir AI Assistant\"\n title=\"AI Assistant\"\n (click)=\"openAssistant()\"\n >\n ✦\n </button>\n <button\n type=\"button\"\n class=\"vx-grid__ai-btn vx-grid__ai-btn--ghost\"\n aria-label=\"AI Prompt Editor\"\n title=\"AI Prompt Editor\"\n (click)=\"openPromptEditor()\"\n >\n ⌘\n </button>\n }\n </div>\n </div>\n\n <div class=\"vx-grid__header\" #headerRef role=\"row\">\n @for (col of columns(); track col.field) {\n <div\n class=\"vx-grid__header-cell\"\n role=\"columnheader\"\n [class.vx-grid__header-cell--ai]=\"isAiColumn(col)\"\n [ngStyle]=\"colStyle(col)\"\n (click)=\"onHeaderClick(col)\"\n >\n @if (isAiColumn(col)) {\n <span class=\"vx-grid__ai-col-icon\" aria-hidden=\"true\">✦</span>\n }\n <span class=\"vx-grid__header-text\">{{ col.header }}</span>\n @if (!isAiColumn(col) && sort()?.field === col.field) {\n <span class=\"vx-grid__sort-icon\" aria-hidden=\"true\">\n {{ sort()?.direction === 'asc' ? '↑' : '↓' }}\n </span>\n }\n </div>\n }\n </div>\n\n <div class=\"vx-grid__body\" #bodyRef role=\"rowgroup\" (scroll)=\"onScroll($event)\">\n @if ((loading() || remoteLoading()) && windowRows().length === 0) {\n <div class=\"vx-grid__loading\">Carregando dados...</div>\n } @else if (!loading() && !remoteLoading() && totalRows() === 0) {\n <div class=\"vx-grid__empty\">Nenhum registro encontrado</div>\n } @else {\n <div class=\"vx-grid__spacer\" [style.height.px]=\"spacerHeight()\"></div>\n <div class=\"vx-grid__window\" [style.transform]=\"'translateY(' + offsetY() + 'px)'\">\n @for (row of windowRows(); track trackDisplay(row, i); let i = $index) {\n @if (isGroupRow(row)) {\n <div\n class=\"vx-grid__row vx-grid__row--group\"\n role=\"row\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"toggleGroupExpand(groupKey(row))\"\n >\n <div class=\"vx-grid__cell vx-grid__cell--group\" role=\"gridcell\">\n <span class=\"vx-grid__group-chevron\" [class.vx-grid__group-chevron--open]=\"isGroupExpanded(groupKey(row))\">▸</span>\n {{ groupLabel(row) }}\n <span class=\"vx-grid__group-count\">({{ groupCount(row) }})</span>\n </div>\n </div>\n } @else {\n <div\n class=\"vx-grid__row\"\n role=\"row\"\n [attr.aria-rowindex]=\"startIndex() + i + 1\"\n [class.vx-grid__row--selected]=\"isSelected(asDataRow(row))\"\n [class.vx-grid__row--stripe]=\"(startIndex() + i) % 2 === 1\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"toggleSelection(asDataRow(row))\"\n >\n @for (col of columns(); track col.field) {\n <div\n class=\"vx-grid__cell\"\n role=\"gridcell\"\n [class.vx-grid__cell--ai]=\"isAiColumn(col)\"\n [class.vx-grid__cell--ai-empty]=\"isAiColumn(col) && !aiCellValue(asDataRow(row), col)\"\n [class.vx-grid__cell--ai-loading]=\"isAiColumn(col) && isAiCellLoading(asDataRow(row), col)\"\n [class.vx-grid__cell--editing]=\"isEditing(asDataRow(row), col)\"\n [ngStyle]=\"colStyle(col)\"\n (dblclick)=\"startEdit(asDataRow(row), col, $event)\"\n >\n @if (isAiColumn(col)) {\n @if (isAiCellLoading(asDataRow(row), col)) {\n <span class=\"vx-grid__ai-skeleton\">…</span>\n } @else {\n {{ aiCellValue(asDataRow(row), col) || aiNoDataText(col) }}\n }\n } @else if (isEditing(asDataRow(row), col)) {\n <input\n class=\"vx-grid__edit-input\"\n [value]=\"editDraft()\"\n (input)=\"editDraft.set($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"commitEdit()\"\n (keydown.escape)=\"cancelEdit()\"\n (blur)=\"commitEdit()\"\n />\n } @else {\n {{ getCellValue(asDataRow(row), col) }}\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n\n <div class=\"vx-grid__footer\">\n <span>\n {{ totalRows() | number }} registros\n @if (virtualScroll()) {\n · janela {{ windowRows().length | number }}\n ({{ startIndex() + 1 }}–{{ endIndexDisplay() }})\n }\n </span>\n @if (selectedCount() > 0) {\n <span>{{ selectedCount() }} selecionado(s)</span>\n }\n </div>\n </div>\n\n @if (aiEnabled()) {\n <vx-ai-assistant-dialog\n [open]=\"assistantOpen()\"\n (openChange)=\"assistantOpen.set($event)\"\n [title]=\"assistantTitle()\"\n [messages]=\"aiMessages()\"\n [suggestions]=\"aiSuggestions()\"\n [busy]=\"aiBusy()\"\n (sendMessage)=\"onAssistantSend($event)\"\n (suggestionSelect)=\"onSuggestion($event)\"\n (clear)=\"clearChat()\"\n />\n\n <vx-ai-prompt-editor\n [open]=\"promptEditorOpen()\"\n (openChange)=\"onPromptEditorOpenChange($event)\"\n [prompt]=\"aiColumnPrompt()\"\n (promptChange)=\"aiColumnPrompt.set($event)\"\n [canApply]=\"aiColumnCanApply()\"\n (regenerate)=\"onPromptRegenerate($event)\"\n (apply)=\"onPromptApply($event)\"\n />\n }\n `,\n styles: `\n :host {\n display: block;\n height: 100%;\n min-height: 300px;\n position: relative;\n }\n\n .vx-grid {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 300px;\n border: 1px solid var(--vx-grid-border);\n border-radius: var(--vx-radius-md);\n background: var(--vx-color-surface);\n overflow: hidden;\n font-size: var(--vx-font-size-sm);\n font-family: var(--vx-font-sans);\n position: relative;\n }\n\n .vx-grid__toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--vx-space-2);\n padding: var(--vx-space-2) var(--vx-space-3);\n border-bottom: 1px solid var(--vx-grid-border);\n background: var(--vx-color-bg-subtle);\n flex-shrink: 0;\n min-height: 2.75rem;\n box-sizing: border-box;\n overflow: visible;\n }\n\n .vx-grid__toolbar-left,\n .vx-grid__toolbar-right {\n display: flex;\n align-items: center;\n gap: var(--vx-space-2);\n min-width: 0;\n }\n\n .vx-grid__toolbar-right {\n flex-shrink: 0;\n }\n\n .vx-grid__toolbar-hint {\n color: var(--vx-color-text-muted);\n font-size: var(--vx-font-size-xs);\n }\n\n .vx-grid__filter-pill {\n display: inline-flex;\n align-items: center;\n gap: var(--vx-space-2);\n padding: 0.2rem 0.6rem;\n border-radius: 999px;\n background: var(--vx-color-badge-bg, var(--vx-color-primary-subtle));\n color: var(--vx-color-badge-fg, var(--vx-color-primary-ink));\n font-size: var(--vx-font-size-xs);\n }\n\n .vx-grid__group-label {\n display: inline-flex;\n align-items: center;\n gap: var(--vx-space-2);\n font-size: var(--vx-font-size-xs);\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__group-select {\n height: 1.75rem;\n border: 1px solid var(--vx-color-border-strong);\n border-radius: var(--vx-radius-md);\n background: var(--vx-color-bg-elevated);\n color: var(--vx-color-text);\n font: inherit;\n font-size: var(--vx-font-size-xs);\n }\n\n .vx-grid__row--group {\n background: var(--vx-color-bg-muted);\n font-weight: var(--vx-font-weight-semibold);\n cursor: pointer;\n }\n\n .vx-grid__cell--group {\n flex: 1;\n width: 100% !important;\n gap: var(--vx-space-2);\n }\n\n .vx-grid__group-chevron {\n display: inline-block;\n transition: transform var(--vx-transition-fast);\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__group-chevron--open {\n transform: rotate(90deg);\n }\n\n .vx-grid__group-count {\n color: var(--vx-color-text-secondary);\n font-weight: var(--vx-font-weight-normal);\n }\n\n .vx-grid__edit-input {\n width: 100%;\n height: 1.6rem;\n border: 1px solid var(--vx-color-border-focus);\n border-radius: var(--vx-radius-sm);\n background: var(--vx-color-bg-elevated);\n color: var(--vx-color-text);\n font: inherit;\n padding: 0 var(--vx-space-1);\n box-shadow: var(--vx-focus-ring);\n }\n\n .vx-grid__cell--editing {\n padding: 2px var(--vx-space-1);\n }\n\n .vx-grid__filter-clear {\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n text-decoration: underline;\n font: inherit;\n padding: 0;\n }\n\n .vx-grid__tool-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.35rem;\n height: 2rem;\n min-width: 2rem;\n padding: 0 0.7rem;\n border-radius: var(--vx-radius-md);\n border: 1px solid var(--vx-color-border);\n background: var(--vx-color-surface);\n color: var(--vx-color-text);\n cursor: pointer;\n font: inherit;\n font-size: var(--vx-font-size-xs);\n font-weight: var(--vx-font-weight-semibold);\n line-height: 1;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .vx-grid__tool-btn:hover {\n border-color: var(--vx-color-primary);\n background: var(--vx-color-primary-subtle);\n color: var(--vx-color-primary-ink, var(--vx-color-primary));\n }\n\n .vx-grid__tool-btn-icon {\n font-size: 0.85rem;\n line-height: 1;\n }\n\n .vx-grid__ai-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n padding: 0;\n border-radius: 999px;\n border: 1px solid var(--vx-color-border);\n background: var(--vx-color-surface);\n color: var(--vx-color-primary);\n cursor: pointer;\n font-size: 0.95rem;\n line-height: 1;\n flex-shrink: 0;\n }\n\n .vx-grid__ai-btn:hover {\n border-color: var(--vx-color-primary);\n background: var(--vx-color-primary-subtle);\n }\n\n .vx-grid__ai-btn--ghost {\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__header {\n display: flex;\n width: 100%;\n background: var(--vx-grid-header-bg);\n border-bottom: 1px solid var(--vx-grid-border);\n font-weight: var(--vx-font-weight-semibold);\n color: var(--vx-color-text);\n flex-shrink: 0;\n overflow: hidden;\n user-select: none;\n z-index: 2;\n }\n\n .vx-grid__header-cell {\n display: flex;\n align-items: center;\n gap: var(--vx-space-1);\n padding: 0 var(--vx-space-3);\n height: 40px;\n border-right: 1px solid var(--vx-grid-border);\n cursor: pointer;\n box-sizing: border-box;\n overflow: hidden;\n min-width: 0;\n }\n\n .vx-grid__header-cell:hover {\n background: var(--vx-color-bg-hover);\n }\n\n .vx-grid__header-cell--ai {\n color: var(--vx-color-primary);\n gap: var(--vx-space-2);\n }\n\n .vx-grid__ai-col-icon {\n font-size: 0.85rem;\n }\n\n .vx-grid__cell--ai {\n font-style: italic;\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__cell--ai-empty {\n color: var(--vx-color-text-muted);\n font-style: normal;\n }\n\n .vx-grid__cell--ai-loading {\n opacity: 0.7;\n }\n\n .vx-grid__ai-skeleton {\n letter-spacing: 0.15em;\n color: var(--vx-color-text-muted);\n }\n\n .vx-grid__body {\n flex: 1;\n overflow: auto;\n position: relative;\n min-height: 0;\n contain: strict;\n }\n\n .vx-grid__spacer {\n width: 1px;\n pointer-events: none;\n }\n\n .vx-grid__window {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n width: 100%;\n will-change: transform;\n }\n\n .vx-grid__row {\n display: flex;\n width: 100%;\n border-bottom: 1px solid var(--vx-grid-border);\n cursor: pointer;\n box-sizing: border-box;\n background: var(--vx-color-surface);\n }\n\n .vx-grid__row--stripe {\n background: var(--vx-grid-stripe);\n }\n\n .vx-grid__row:hover {\n background: var(--vx-grid-row-hover);\n }\n\n .vx-grid__row--selected {\n background: var(--vx-grid-row-selected);\n }\n\n .vx-grid__cell {\n padding: 0 var(--vx-space-3);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--vx-grid-border);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--vx-color-text);\n box-sizing: border-box;\n min-width: 0;\n }\n\n .vx-grid__footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: var(--vx-space-3);\n padding: var(--vx-space-2) var(--vx-space-4);\n border-top: 1px solid var(--vx-grid-border);\n background: var(--vx-grid-header-bg);\n font-size: var(--vx-font-size-xs);\n color: var(--vx-color-text-secondary);\n flex-shrink: 0;\n }\n\n .vx-grid__loading,\n .vx-grid__empty {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: var(--vx-color-text-muted);\n }\n `,\n})\nexport class VxDataGridComponent<T = unknown> {\n private readonly destroyRef = inject(DestroyRef);\n\n readonly columns = input.required<VxColumnDef<T>[]>();\n readonly data = input<T[]>([]);\n readonly dataSource = input<VxDataSource<T> | null>(null);\n readonly totalCount = input<number | null>(null);\n readonly loading = input(false);\n readonly rowHeight = input(36);\n readonly overscan = input(8);\n readonly virtualScroll = input(true);\n readonly trackByField = input<string>('id');\n readonly selectable = input(true);\n readonly multiSelect = input(true);\n /** Habilita edição inline (duplo clique). */\n readonly editable = input(false);\n readonly exportEnabled = input(true);\n /** Campo de agrupamento (client-side). */\n readonly groupBy = model<string | null>(null);\n\n /** Opt-in AI (default off). */\n readonly ai = input<VortexAIConfig | null>(null);\n readonly aiIntegration = input<VortexAIIntegration | null>(null);\n\n readonly sortChange = output<VxSortState | null>();\n readonly filterChange = output<VxFilterState | null>();\n readonly selectionChange = output<T[]>();\n readonly rowClick = output<T>();\n readonly cellEdit = output<VxCellEditEvent<T>>();\n readonly exported = output<{ format: 'csv'; count: number }>();\n readonly loadRequest = output<{\n skip: number;\n take: number;\n sort: VxSortState | null;\n filter: VxFilterState | null;\n }>();\n readonly aiRequestCreating = output<VortexAIRequestCreatingEvent>();\n readonly aiCommandExecuted = output<VortexAICommand>();\n readonly aiRequestCompleted = output<{ text: string }>();\n readonly aiRequestFailed = output<{ error: unknown }>();\n\n private readonly bodyRef = viewChild<ElementRef<HTMLElement>>('bodyRef');\n private readonly headerRef = viewChild<ElementRef<HTMLElement>>('headerRef');\n\n readonly sort = signal<VxSortState | null>(null);\n readonly filter = signal<VxFilterState | null>(null);\n readonly selected = signal<Set<unknown>>(new Set());\n readonly scrollTop = signal(0);\n readonly viewportHeight = signal(400);\n\n readonly windowRows = signal<Array<T | VxGroupRow>>([]);\n readonly startIndex = signal(0);\n readonly remoteLoading = signal(false);\n readonly remoteTotal = signal(0);\n readonly collapsedGroups = signal<Set<string>>(new Set());\n readonly editDraft = signal('');\n readonly editingKey = signal<string | null>(null);\n readonly editingField = signal<string | null>(null);\n\n readonly assistantOpen = signal(false);\n readonly promptEditorOpen = signal(false);\n readonly aiColumnPrompt = signal('Resuma a linha em uma frase curta');\n readonly activeAiColumnField = signal<string | null>(null);\n /** Cache em memória: `${columnField}::${rowKey}` → valor gerado (não grava no dataSource). */\n readonly aiCellValues = signal<Record<string, string>>({});\n readonly aiCellLoading = signal<Record<string, boolean>>({});\n readonly aiColumnDirty = signal(false);\n readonly aiMessages = signal<VxAIChatMessage[]>([]);\n readonly aiBusy = signal(false);\n\n readonly aiColumnCanApply = computed(\n () => this.aiColumnDirty() && this.aiColumnPrompt().trim().length > 0\n );\n\n private loadSeq = 0;\n private resizeObserver: ResizeObserver | null = null;\n private scrollRaf = 0;\n private lastRemoteKey = '';\n private lastClientKey = '';\n private lastViewportH = 0;\n\n readonly aiEnabled = computed(() => !!this.ai()?.enabled);\n\n readonly assistantTitle = computed(\n () => this.ai()?.assistant?.title ?? DEFAULT_AI.assistant.title\n );\n\n readonly aiSuggestions = computed<VortexAISuggestion[]>(() => [\n { id: 'help', label: 'Ajuda', prompt: 'ajuda' },\n {\n id: 'filter-health',\n label: 'Filtrar setor por Saúde',\n command: {\n type: 'filter.set',\n payload: { field: 'sector', value: 'Saúde', operator: 'contains' },\n },\n },\n {\n id: 'sort-region',\n label: 'Ordenar por região',\n command: { type: 'sort.set', payload: { field: 'region', direction: 'asc' } },\n },\n {\n id: 'group-product',\n label: 'Agrupar por produto',\n command: { type: 'group.set', payload: { field: 'product' } },\n },\n ]);\n\n readonly groupableFields = computed(() =>\n this.columns().filter((c) => c.type !== 'ai' && c.field)\n );\n\n readonly totalRows = computed(() => {\n if (this.dataSource() && !this.groupBy()) return this.remoteTotal();\n return this.displayRows().length;\n });\n\n readonly selectedCount = computed(() => this.selected().size);\n\n readonly spacerHeight = computed(() =>\n Math.min(this.totalRows() * this.rowHeight(), MAX_SPACER_PX)\n );\n\n readonly offsetY = computed(() => {\n const total = this.totalRows();\n const rh = this.rowHeight();\n const natural = total * rh;\n const spacer = this.spacerHeight();\n if (natural <= spacer || natural === 0) return this.startIndex() * rh;\n return this.startIndex() * rh * (spacer / natural);\n });\n\n readonly endIndexDisplay = computed(() =>\n Math.min(this.totalRows(), this.startIndex() + this.windowRows().length)\n );\n\n private readonly filteredClientRows = computed(() => {\n const rows = this.data() as Record<string, unknown>[];\n const filter = this.filter();\n const sort = this.sort();\n let next = rows;\n if (filter?.field && filter.value) {\n const needle = String(filter.value).toLowerCase();\n const op = filter.operator ?? 'contains';\n next = next.filter((row) => {\n const hay = String(row[filter.field] ?? '').toLowerCase();\n return op === 'equals' ? hay === needle : hay.includes(needle);\n });\n }\n if (sort) {\n const dir = sort.direction === 'asc' ? 1 : -1;\n next = next.slice().sort((a, b) => {\n const av = a[sort.field];\n const bv = b[sort.field];\n if (av == null && bv == null) return 0;\n if (av == null) return -1 * dir;\n if (bv == null) return 1 * dir;\n if (av < bv) return -1 * dir;\n if (av > bv) return 1 * dir;\n return 0;\n });\n }\n return next as T[];\n });\n\n /** Linhas exibidas (dados + headers de grupo quando `groupBy` ativo). */\n private readonly displayRows = computed(() => {\n const rows = this.filteredClientRows();\n const field = this.groupBy();\n if (!field) return rows as Array<T | VxGroupRow>;\n\n const collapsed = this.collapsedGroups();\n const buckets = new Map<string, T[]>();\n for (const row of rows) {\n const key = String((row as Record<string, unknown>)[field] ?? '(vazio)');\n const list = buckets.get(key) ?? [];\n list.push(row);\n buckets.set(key, list);\n }\n\n const out: Array<T | VxGroupRow> = [];\n for (const [key, list] of buckets) {\n out.push({ __vxGroup: true, key, label: `${field}: ${key}`, count: list.length });\n if (!collapsed.has(key)) {\n out.push(...list);\n }\n }\n return out;\n });\n\n constructor() {\n afterNextRender(() => {\n this.setupViewportObservers();\n void this.refreshWindow(true);\n });\n\n effect(() => {\n this.data();\n this.dataSource();\n this.sort();\n this.filter();\n this.groupBy();\n this.collapsedGroups();\n this.rowHeight();\n this.overscan();\n this.virtualScroll();\n untracked(() => {\n this.lastRemoteKey = '';\n this.lastClientKey = '';\n void this.refreshWindow(true);\n });\n });\n\n this.destroyRef.onDestroy(() => {\n this.resizeObserver?.disconnect();\n if (this.scrollRaf) cancelAnimationFrame(this.scrollRaf);\n });\n }\n\n private setupViewportObservers(): void {\n const body = this.bodyRef()?.nativeElement;\n if (!body) return;\n const measure = () => {\n const h = body.clientHeight || 400;\n if (Math.abs(h - this.lastViewportH) < 2) return;\n this.lastViewportH = h;\n this.viewportHeight.set(h);\n void this.refreshWindow(false);\n };\n measure();\n this.resizeObserver = new ResizeObserver(() => measure());\n this.resizeObserver.observe(body);\n }\n\n onScroll(event: Event): void {\n const body = event.target as HTMLElement;\n const header = this.headerRef()?.nativeElement;\n if (header) header.scrollLeft = body.scrollLeft;\n if (this.scrollRaf) cancelAnimationFrame(this.scrollRaf);\n this.scrollRaf = requestAnimationFrame(() => {\n this.scrollTop.set(body.scrollTop);\n void this.refreshWindow(false);\n });\n }\n\n private scrollTopToIndex(scrollTop: number, total: number): number {\n const rh = this.rowHeight();\n const natural = total * rh;\n const spacer = Math.min(natural, MAX_SPACER_PX);\n if (natural <= spacer || spacer <= 0) return Math.floor(scrollTop / rh);\n return Math.floor((scrollTop / spacer) * total);\n }\n\n private computeRange(total: number): { start: number; take: number } {\n const rh = this.rowHeight();\n const overscan = this.overscan();\n const vh = this.viewportHeight();\n if (!this.virtualScroll()) return { start: 0, take: Math.min(total, 500) };\n if (total <= 0) return { start: 0, take: 0 };\n const visibleCount = Math.ceil(vh / rh) + 1;\n let start = Math.max(0, this.scrollTopToIndex(this.scrollTop(), total) - overscan);\n let end = Math.min(total, start + visibleCount + overscan * 2);\n start = Math.min(start, Math.max(0, total - 1));\n return { start, take: Math.max(0, end - start) };\n }\n\n private async refreshWindow(force: boolean): Promise<void> {\n const ds = this.dataSource();\n // Agrupamento é client-side — ignora dataSource enquanto groupBy estiver ativo.\n if (ds && !this.groupBy()) {\n const knownTotal = this.remoteTotal();\n const probeTotal = knownTotal > 0 ? knownTotal : 1_000_000;\n const { start, take } = this.computeRange(probeTotal);\n await this.loadFromSource(ds, start, Math.max(take, 1), force);\n return;\n }\n\n const rows = this.displayRows();\n const total = rows.length;\n const { start, take } = this.computeRange(total);\n const key = `${start}:${take}:${this.sort()?.field ?? ''}:${this.filter()?.field ?? ''}:${this.filter()?.value ?? ''}`;\n if (!force && key === this.lastClientKey) return;\n this.lastClientKey = key;\n this.startIndex.set(start);\n this.windowRows.set(rows.slice(start, start + take));\n }\n\n private async loadFromSource(\n ds: VxDataSource<T>,\n skip: number,\n take: number,\n force: boolean\n ): Promise<void> {\n const sort = this.sort();\n const filter = this.filter();\n const key = `${skip}:${take}:${sort?.field ?? ''}:${sort?.direction ?? ''}:${filter?.field ?? ''}:${filter?.value ?? ''}`;\n if (!force && key === this.lastRemoteKey) return;\n\n const seq = ++this.loadSeq;\n if (this.windowRows().length === 0) this.remoteLoading.set(true);\n this.loadRequest.emit({ skip, take, sort, filter });\n\n try {\n const result = await Promise.resolve(ds.load({ skip, take, sort, filter }));\n if (seq !== this.loadSeq) return;\n this.lastRemoteKey = key;\n this.remoteTotal.set(result.totalCount);\n this.startIndex.set(skip);\n this.windowRows.set(result.data);\n } finally {\n if (seq === this.loadSeq) this.remoteLoading.set(false);\n }\n }\n\n // —— AI ——\n isAiColumn(col: VxColumnDef<T>): boolean {\n return col.type === 'ai';\n }\n\n aiNoDataText(col: VxColumnDef<T>): string {\n return col.ai?.noDataText ?? 'No data';\n }\n\n private aiCacheKey(row: T, col: VxColumnDef<T>): string {\n return `${col.field}::${String(this.trackBy(row))}`;\n }\n\n aiCellValue(row: T, col: VxColumnDef<T>): string | null {\n return this.aiCellValues()[this.aiCacheKey(row, col)] ?? null;\n }\n\n isAiCellLoading(row: T, col: VxColumnDef<T>): boolean {\n return !!this.aiCellLoading()[this.aiCacheKey(row, col)];\n }\n\n onHeaderClick(col: VxColumnDef<T>): void {\n if (this.isAiColumn(col)) {\n this.openPromptEditor(col);\n return;\n }\n this.onSort(col);\n }\n\n openAssistant(): void {\n if (!this.aiEnabled()) return;\n this.assistantOpen.set(true);\n }\n\n openPromptEditor(col?: VxColumnDef<T>): void {\n if (!this.aiEnabled()) return;\n const aiCol =\n col && this.isAiColumn(col)\n ? col\n : this.columns().find((c) => c.type === 'ai') ?? null;\n if (aiCol) {\n this.activeAiColumnField.set(aiCol.field);\n this.aiColumnPrompt.set(aiCol.ai?.prompt ?? this.aiColumnPrompt());\n } else {\n this.activeAiColumnField.set(null);\n }\n this.promptEditorOpen.set(true);\n }\n\n onPromptEditorOpenChange(open: boolean): void {\n this.promptEditorOpen.set(open);\n }\n\n clearChat(): void {\n this.aiMessages.set([]);\n }\n\n clearFilter(): void {\n this.filter.set(null);\n this.filterChange.emit(null);\n }\n\n /** Aplica filtro externo (ex.: vx-filter-builder). */\n setFilter(next: VxFilterState | null): void {\n this.filter.set(next);\n this.filterChange.emit(next);\n }\n\n async onSuggestion(s: VortexAISuggestion): Promise<void> {\n if (s.command) {\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'user', content: s.label },\n ]);\n await this.executeCommands([s.command]);\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'assistant', title: 'Comando aplicado', content: s.label },\n ]);\n return;\n }\n if (s.prompt) await this.onAssistantSend(s.prompt);\n }\n\n async onAssistantSend(text: string): Promise<void> {\n const integration = this.aiIntegration();\n if (!this.aiEnabled() || !integration) return;\n\n this.aiMessages.update((msgs) => [...msgs, { role: 'user', content: text }]);\n this.aiBusy.set(true);\n\n try {\n let request = this.buildAIRequest(text);\n const ev: VortexAIRequestCreatingEvent = { request, cancel: false };\n this.aiRequestCreating.emit(ev);\n if (ev.cancel) {\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'assistant', title: 'Cancelado', content: 'Request cancelado pelo app.' },\n ]);\n return;\n }\n request = ev.request;\n\n const response = await integration.sendRequest(request);\n if (response.commands?.length) {\n await this.executeCommands(response.commands);\n }\n this.aiMessages.update((msgs) => [\n ...msgs,\n {\n role: 'assistant',\n title: response.title,\n content: response.text,\n },\n ]);\n this.aiRequestCompleted.emit({ text: response.text });\n } catch (error) {\n this.aiRequestFailed.emit({ error });\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'assistant', title: 'Erro', content: 'Falha ao consultar o assistente.' },\n ]);\n } finally {\n this.aiBusy.set(false);\n }\n }\n\n async onPromptRegenerate(prompt: string): Promise<void> {\n this.aiColumnPrompt.set(prompt);\n const field = this.activeAiColumnField() ?? this.columns().find((c) => c.type === 'ai')?.field;\n if (!field) return;\n await this.regenerateAiColumn(field, prompt);\n }\n\n onPromptApply(prompt: string): void {\n this.aiColumnPrompt.set(prompt);\n const field = this.activeAiColumnField();\n const cells = Object.entries(this.aiCellValues())\n .filter(([k]) => k.startsWith(`${field}::`))\n .map(([k, value]) => ({\n rowKey: k.slice(String(field).length + 2),\n value,\n }));\n\n this.promptEditorOpen.set(false);\n this.aiColumnDirty.set(false);\n this.aiCommandExecuted.emit({\n type: 'aiColumn.apply',\n payload: { prompt, field, cells },\n });\n // R5: não persiste no dataSource — app decide o que fazer com o evento\n }\n\n private async regenerateAiColumn(field: string, prompt: string): Promise<void> {\n const integration = this.aiIntegration();\n if (!this.aiEnabled() || !integration) return;\n\n const col = this.columns().find((c) => c.field === field);\n if (!col || !this.isAiColumn(col)) return;\n\n const cfg = this.ai();\n const dataRows = this.dataWindowRows();\n const rows = projectRowsForAI(dataRows as Record<string, unknown>[], {\n contextFields: cfg?.contextFields,\n maxRowsInContext: cfg?.maxRowsInContext ?? DEFAULT_AI.maxRowsInContext,\n });\n\n // Marca loading nas linhas da janela\n const loadingPatch: Record<string, boolean> = { ...this.aiCellLoading() };\n for (const row of dataRows) {\n loadingPatch[this.aiCacheKey(row, col)] = true;\n }\n this.aiCellLoading.set(loadingPatch);\n this.aiBusy.set(true);\n\n try {\n let request: VortexAIRequest = {\n feature: 'ai-column',\n componentType: 'data-grid',\n prompt,\n context: {\n schemaVersion: 1,\n componentType: 'data-grid',\n columns: this.columns()\n .filter((c) => c.type !== 'ai')\n .map((c) => ({ field: c.field, header: c.header })),\n sort: this.sort(),\n filter: this.filter(),\n rows,\n totalRows: this.totalRows(),\n meta: { aiColumn: field, prompt },\n },\n };\n\n const ev: VortexAIRequestCreatingEvent = { request, cancel: false };\n this.aiRequestCreating.emit(ev);\n if (ev.cancel) return;\n request = ev.request;\n\n const response = await integration.sendRequest(request);\n const cells = response.data?.cells ?? [];\n const valuesPatch: Record<string, string> = { ...this.aiCellValues() };\n for (const cell of cells) {\n valuesPatch[`${field}::${cell.rowKey}`] = cell.value;\n }\n this.aiCellValues.set(valuesPatch);\n this.aiColumnDirty.set(cells.length > 0);\n this.aiRequestCompleted.emit({ text: response.text });\n this.aiCommandExecuted.emit({\n type: 'aiColumn.regenerate',\n payload: { field, prompt, count: cells.length },\n });\n } catch (error) {\n this.aiRequestFailed.emit({ error });\n } finally {\n const clearLoading: Record<string, boolean> = { ...this.aiCellLoading() };\n for (const row of this.dataWindowRows()) {\n delete clearLoading[this.aiCacheKey(row, col)];\n }\n this.aiCellLoading.set(clearLoading);\n this.aiBusy.set(false);\n }\n }\n\n private buildAIRequest(userText: string): VortexAIRequest {\n const cfg = this.ai();\n const fields = cfg?.contextFields;\n const maxRows = cfg?.maxRowsInContext ?? DEFAULT_AI.maxRowsInContext;\n const rows = projectRowsForAI(\n this.dataWindowRows() as Record<string, unknown>[],\n { contextFields: fields, maxRowsInContext: maxRows }\n );\n\n return {\n feature: 'assistant',\n componentType: 'data-grid',\n messages: [...this.aiMessages(), { role: 'user', content: userText }],\n context: {\n schemaVersion: 1,\n componentType: 'data-grid',\n columns: this.columns().map((c) => ({ field: c.field, header: c.header })),\n sort: this.sort(),\n filter: this.filter(),\n rows,\n totalRows: this.totalRows(),\n },\n tools: [\n { name: 'filter.set', description: 'Define filtro por campo/valor' },\n { name: 'filter.clear', description: 'Limpa filtros' },\n { name: 'sort.set', description: 'Ordena por campo' },\n { name: 'group.set', description: 'Agrupa por campo (preview)' },\n ],\n };\n }\n\n private async executeCommands(commands: VortexAICommand[]): Promise<void> {\n for (const cmd of commands) {\n switch (cmd.type) {\n case 'filter.set': {\n const field = String(cmd.payload?.['field'] ?? '');\n const value = String(cmd.payload?.['value'] ?? '');\n const operator = (cmd.payload?.['operator'] as VxFilterState['operator']) ?? 'contains';\n if (field && value) {\n const next = { field, value, operator };\n this.filter.set(next);\n this.filterChange.emit(next);\n }\n break;\n }\n case 'filter.clear':\n this.clearFilter();\n break;\n case 'sort.set': {\n const field = String(cmd.payload?.['field'] ?? '');\n const direction = (cmd.payload?.['direction'] as 'asc' | 'desc') ?? 'asc';\n if (field) {\n const next = { field, direction };\n this.sort.set(next);\n this.sortChange.emit(next);\n }\n break;\n }\n case 'group.set': {\n const field = String(cmd.payload?.['field'] ?? '');\n if (field) {\n this.groupBy.set(field);\n this.collapsedGroups.set(new Set());\n }\n break;\n }\n default:\n break;\n }\n this.aiCommandExecuted.emit(cmd);\n }\n }\n\n /**\n * Largura dinâmica (paridade DX):\n * - com `width` → tamanho fixo\n * - sem `width` → flex grow (reparte o espaço restante e preenche o container)\n */\n colStyle(col: VxColumnDef<T>): Record<string, string> {\n const min = `${col.minWidth ?? 80}px`;\n if (col.width != null) {\n const w = typeof col.width === 'number' ? `${col.width}px` : String(col.width);\n return { flex: `0 0 ${w}`, width: w, minWidth: min, maxWidth: w };\n }\n return { flex: '1 1 0%', width: 'auto', minWidth: min };\n }\n\n /** @deprecated Prefer `colStyle` — mantido por compatibilidade interna. */\n colWidth(col: VxColumnDef<T>): string {\n if (col.width == null) return 'auto';\n return typeof col.width === 'number' ? `${col.width}px` : col.width;\n }\n\n trackBy = (row: T) => {\n const field = this.trackByField();\n return (row as Record<string, unknown>)[field] ?? row;\n };\n\n getCellValue(row: T, col: VxColumnDef<T>): unknown {\n if (col.valueGetter) return col.valueGetter(row);\n return (row as Record<string, unknown>)[col.field];\n }\n\n isSelected(row: T): boolean {\n return this.selected().has(this.trackBy(row));\n }\n\n toggleSelection(row: T): void {\n if (!this.selectable()) {\n this.rowClick.emit(row);\n return;\n }\n const key = this.trackBy(row);\n const next = new Set(this.selected());\n if (next.has(key)) next.delete(key);\n else {\n if (!this.multiSelect()) next.clear();\n next.add(key);\n }\n this.selected.set(next);\n this.selectionChange.emit(\n this.dataWindowRows().filter((r) => next.has(this.trackBy(r)))\n );\n this.rowClick.emit(row);\n }\n\n private dataWindowRows(): T[] {\n return this.windowRows().filter((r): r is T => !this.isGroupRow(r));\n }\n\n onSort(col: VxColumnDef<T>): void {\n if (this.isAiColumn(col) || col.sortable === false) return;\n const current = this.sort();\n let next: VxSortState | null = null;\n if (!current || current.field !== col.field) next = { field: col.field, direction: 'asc' };\n else if (current.direction === 'asc') next = { field: col.field, direction: 'desc' };\n else next = null;\n this.sort.set(next);\n this.sortChange.emit(next);\n }\n\n onGroupSelect(event: Event): void {\n const value = (event.target as HTMLSelectElement).value;\n this.groupBy.set(value || null);\n this.collapsedGroups.set(new Set());\n }\n\n clearGroup(): void {\n this.groupBy.set(null);\n this.collapsedGroups.set(new Set());\n }\n\n isGroupRow(row: T | VxGroupRow): row is VxGroupRow {\n return !!row && typeof row === 'object' && (row as VxGroupRow).__vxGroup === true;\n }\n\n asDataRow(row: T | VxGroupRow): T {\n return row as T;\n }\n\n groupKey(row: T | VxGroupRow): string {\n return this.isGroupRow(row) ? row.key : '';\n }\n\n groupLabel(row: T | VxGroupRow): string {\n return this.isGroupRow(row) ? row.label : '';\n }\n\n groupCount(row: T | VxGroupRow): number {\n return this.isGroupRow(row) ? row.count : 0;\n }\n\n isGroupExpanded(key: string): boolean {\n return !this.collapsedGroups().has(key);\n }\n\n toggleGroupExpand(key: string): void {\n const next = new Set(this.collapsedGroups());\n if (next.has(key)) next.delete(key);\n else next.add(key);\n this.collapsedGroups.set(next);\n }\n\n trackDisplay(row: T | VxGroupRow, index: number): unknown {\n if (this.isGroupRow(row)) return `g:${row.key}`;\n return this.trackBy(row as T) ?? index;\n }\n\n isEditing(row: T, col: VxColumnDef<T>): boolean {\n if (!this.editable() || this.isAiColumn(col) || col.editable === false) return false;\n return this.editingKey() === String(this.trackBy(row)) && this.editingField() === col.field;\n }\n\n startEdit(row: T, col: VxColumnDef<T>, event: Event): void {\n if (!this.editable() || this.isAiColumn(col) || col.editable === false) return;\n event.stopPropagation();\n this.editingKey.set(String(this.trackBy(row)));\n this.editingField.set(col.field);\n this.editDraft.set(String(this.getCellValue(row, col) ?? ''));\n }\n\n commitEdit(): void {\n const key = this.editingKey();\n const field = this.editingField();\n if (key == null || field == null) return;\n const row = this.displayRows().find(\n (r) => !this.isGroupRow(r) && String(this.trackBy(r as T)) === key\n ) as T | undefined;\n if (!row) {\n this.cancelEdit();\n return;\n }\n const previousValue = (row as Record<string, unknown>)[field];\n const value = this.editDraft();\n (row as Record<string, unknown>)[field] = value;\n this.cellEdit.emit({ row, field, value, previousValue });\n this.cancelEdit();\n void this.refreshWindow(true);\n }\n\n cancelEdit(): void {\n this.editingKey.set(null);\n this.editingField.set(null);\n this.editDraft.set('');\n }\n\n exportCsv(): void {\n const cols = this.columns();\n const rows = this.filteredClientRows();\n exportRowsToCsv(rows, cols, 'vortex-grid.csv');\n this.exported.emit({ format: 'csv', count: rows.length });\n }\n}\n"]}
1
+ {"version":3,"file":"data-grid.component.js","sourceRoot":"","sources":["../../../../../../../libs/vortex-ui/src/lib/components/data-grid/data-grid.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ElementRef,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n untracked,\n viewChild,\n DestroyRef,\n} from '@angular/core';\nimport { DecimalPipe, NgStyle } from '@angular/common';\nimport { VxCellEditEvent, VxColumnDef, VxSortState } from './data-grid.types';\nimport { VxDataSource, VxFilterState } from './data-source';\nimport { exportRowsToCsv } from './export-csv';\nimport {\n VortexAICommand,\n VortexAIConfig,\n VortexAIIntegration,\n VortexAIRequest,\n VortexAIRequestCreatingEvent,\n VortexAISuggestion,\n projectRowsForAI,\n VxAIAssistantDialogComponent,\n VxAIChatMessage,\n VxAIPromptEditorComponent,\n} from 'vortex-ui/ai';\n\nexport type {\n VxColumnDef,\n VxSortState,\n VxDataGridConfig,\n VxVirtualRange,\n VxCellEditEvent,\n} from './data-grid.types';\nexport type {\n VxDataSource,\n VxDataSourceLoadOptions,\n VxDataSourceLoadResult,\n VxFilterState,\n} from './data-source';\nexport { VxArrayDataSource, VxRemoteMockDataSource } from './data-source';\nexport { exportRowsToCsv } from './export-csv';\n\nconst MAX_SPACER_PX = 5_000_000;\n\nconst DEFAULT_AI: Required<\n Pick<VortexAIConfig, 'enabled' | 'maxRowsInContext'>\n> & { assistant: { enabled: boolean; title: string } } = {\n enabled: false,\n maxRowsInContext: 100,\n assistant: { enabled: true, title: 'AI Assistant' },\n};\n\n/** Linha sintética de agrupamento no viewport. */\nexport interface VxGroupRow {\n __vxGroup: true;\n key: string;\n label: string;\n count: number;\n}\n\n@Component({\n selector: 'vx-data-grid',\n standalone: true,\n imports: [DecimalPipe, NgStyle, VxAIAssistantDialogComponent, VxAIPromptEditorComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n class=\"vx-grid\"\n role=\"grid\"\n [class.vx-grid--column-lines]=\"showColumnLines()\"\n [class.vx-grid--row-lines]=\"showRowLines()\"\n [attr.aria-rowcount]=\"totalRows()\"\n [attr.aria-colcount]=\"columns().length\"\n [attr.aria-busy]=\"loading() || remoteLoading() || aiBusy()\"\n >\n <div class=\"vx-grid__toolbar\">\n <div class=\"vx-grid__toolbar-left\">\n @if (filter(); as f) {\n <span class=\"vx-grid__filter-pill\">\n Filtro: {{ f.field }} ≈ {{ f.value }}\n <button type=\"button\" class=\"vx-grid__filter-clear\" (click)=\"clearFilter()\">\n limpar\n </button>\n </span>\n }\n @if (groupBy(); as g) {\n <span class=\"vx-grid__filter-pill\">\n Grupo: {{ g }}\n <button type=\"button\" class=\"vx-grid__filter-clear\" (click)=\"clearGroup()\">\n limpar\n </button>\n </span>\n } @else if (!filter()) {\n <span class=\"vx-grid__toolbar-hint\">\n {{ editable() ? 'Duplo clique para editar · ' : '' }}Agrupe via menu / AI\n </span>\n }\n @if (groupableFields().length) {\n <label class=\"vx-grid__group-label\">\n Agrupar\n <select\n class=\"vx-grid__group-select\"\n [value]=\"groupBy() ?? ''\"\n (change)=\"onGroupSelect($event)\"\n >\n <option value=\"\">(nenhum)</option>\n @for (f of groupableFields(); track f.field) {\n <option [value]=\"f.field\">{{ f.header }}</option>\n }\n </select>\n </label>\n }\n </div>\n <div class=\"vx-grid__toolbar-right\">\n @if (exportEnabled()) {\n <button\n type=\"button\"\n class=\"vx-grid__tool-btn\"\n aria-label=\"Exportar CSV\"\n title=\"Exportar CSV\"\n (click)=\"exportCsv()\"\n >\n <span class=\"vx-grid__tool-btn-icon\" aria-hidden=\"true\">↓</span>\n CSV\n </button>\n }\n @if (aiEnabled()) {\n <button\n type=\"button\"\n class=\"vx-grid__ai-btn\"\n aria-label=\"Abrir AI Assistant\"\n title=\"AI Assistant\"\n (click)=\"openAssistant()\"\n >\n ✦\n </button>\n <button\n type=\"button\"\n class=\"vx-grid__ai-btn vx-grid__ai-btn--ghost\"\n aria-label=\"AI Prompt Editor\"\n title=\"AI Prompt Editor\"\n (click)=\"openPromptEditor()\"\n >\n ⌘\n </button>\n }\n </div>\n </div>\n\n <div\n class=\"vx-grid__header\"\n #headerRef\n role=\"row\"\n [style.padding-inline-end.px]=\"scrollbarWidth()\"\n >\n @for (col of columns(); track col.field) {\n <div\n class=\"vx-grid__header-cell\"\n role=\"columnheader\"\n [class.vx-grid__header-cell--ai]=\"isAiColumn(col)\"\n [ngStyle]=\"colStyle(col)\"\n (click)=\"onHeaderClick(col)\"\n >\n @if (isAiColumn(col)) {\n <span class=\"vx-grid__ai-col-icon\" aria-hidden=\"true\">✦</span>\n }\n <span class=\"vx-grid__header-text\">{{ col.header }}</span>\n @if (!isAiColumn(col) && sort()?.field === col.field) {\n <span class=\"vx-grid__sort-icon\" aria-hidden=\"true\">\n {{ sort()?.direction === 'asc' ? '↑' : '↓' }}\n </span>\n }\n </div>\n }\n </div>\n\n <div class=\"vx-grid__body\" #bodyRef role=\"rowgroup\" (scroll)=\"onScroll($event)\">\n @if ((loading() || remoteLoading()) && windowRows().length === 0) {\n <div class=\"vx-grid__loading\">Carregando dados...</div>\n } @else if (!loading() && !remoteLoading() && totalRows() === 0) {\n <div class=\"vx-grid__empty\">Nenhum registro encontrado</div>\n } @else {\n <div class=\"vx-grid__spacer\" [style.height.px]=\"spacerHeight()\"></div>\n <div class=\"vx-grid__window\" [style.transform]=\"'translateY(' + offsetY() + 'px)'\">\n @for (row of windowRows(); track trackDisplay(row, i); let i = $index) {\n @if (isGroupRow(row)) {\n <div\n class=\"vx-grid__row vx-grid__row--group\"\n role=\"row\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"toggleGroupExpand(groupKey(row))\"\n >\n <div class=\"vx-grid__cell vx-grid__cell--group\" role=\"gridcell\">\n <span class=\"vx-grid__group-chevron\" [class.vx-grid__group-chevron--open]=\"isGroupExpanded(groupKey(row))\">▸</span>\n {{ groupLabel(row) }}\n <span class=\"vx-grid__group-count\">({{ groupCount(row) }})</span>\n </div>\n </div>\n } @else {\n <div\n class=\"vx-grid__row\"\n role=\"row\"\n [attr.aria-rowindex]=\"startIndex() + i + 1\"\n [class.vx-grid__row--selected]=\"isSelected(asDataRow(row))\"\n [class.vx-grid__row--stripe]=\"(startIndex() + i) % 2 === 1\"\n [style.height.px]=\"rowHeight()\"\n (click)=\"toggleSelection(asDataRow(row))\"\n >\n @for (col of columns(); track col.field) {\n <div\n class=\"vx-grid__cell\"\n role=\"gridcell\"\n [class.vx-grid__cell--ai]=\"isAiColumn(col)\"\n [class.vx-grid__cell--ai-empty]=\"isAiColumn(col) && !aiCellValue(asDataRow(row), col)\"\n [class.vx-grid__cell--ai-loading]=\"isAiColumn(col) && isAiCellLoading(asDataRow(row), col)\"\n [class.vx-grid__cell--editing]=\"isEditing(asDataRow(row), col)\"\n [ngStyle]=\"colStyle(col)\"\n (dblclick)=\"startEdit(asDataRow(row), col, $event)\"\n >\n @if (isAiColumn(col)) {\n @if (isAiCellLoading(asDataRow(row), col)) {\n <span class=\"vx-grid__ai-skeleton\">…</span>\n } @else {\n {{ aiCellValue(asDataRow(row), col) || aiNoDataText(col) }}\n }\n } @else if (isEditing(asDataRow(row), col)) {\n <input\n class=\"vx-grid__edit-input\"\n [value]=\"editDraft()\"\n (input)=\"editDraft.set($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"commitEdit()\"\n (keydown.escape)=\"cancelEdit()\"\n (blur)=\"commitEdit()\"\n />\n } @else {\n {{ getCellValue(asDataRow(row), col) }}\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n\n <div class=\"vx-grid__footer\">\n <span>\n {{ totalRows() | number }} registros\n @if (virtualScroll()) {\n · janela {{ windowRows().length | number }}\n ({{ startIndex() + 1 }}–{{ endIndexDisplay() }})\n }\n </span>\n @if (selectedCount() > 0) {\n <span>{{ selectedCount() }} selecionado(s)</span>\n }\n </div>\n </div>\n\n @if (aiEnabled()) {\n <vx-ai-assistant-dialog\n [open]=\"assistantOpen()\"\n (openChange)=\"assistantOpen.set($event)\"\n [title]=\"assistantTitle()\"\n [messages]=\"aiMessages()\"\n [suggestions]=\"aiSuggestions()\"\n [busy]=\"aiBusy()\"\n (sendMessage)=\"onAssistantSend($event)\"\n (suggestionSelect)=\"onSuggestion($event)\"\n (clear)=\"clearChat()\"\n />\n\n <vx-ai-prompt-editor\n [open]=\"promptEditorOpen()\"\n (openChange)=\"onPromptEditorOpenChange($event)\"\n [prompt]=\"aiColumnPrompt()\"\n (promptChange)=\"aiColumnPrompt.set($event)\"\n [canApply]=\"aiColumnCanApply()\"\n (regenerate)=\"onPromptRegenerate($event)\"\n (apply)=\"onPromptApply($event)\"\n />\n }\n `,\n styles: `\n :host {\n display: block;\n height: 100%;\n min-height: 300px;\n position: relative;\n }\n\n .vx-grid {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 300px;\n border: 1px solid var(--vx-grid-border);\n border-radius: var(--vx-radius-md);\n background: var(--vx-color-surface);\n overflow: hidden;\n font-size: var(--vx-font-size-sm);\n font-family: var(--vx-font-sans);\n position: relative;\n }\n\n .vx-grid__toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--vx-space-2);\n padding: var(--vx-space-2) var(--vx-space-3);\n border-bottom: 1px solid var(--vx-grid-border);\n background: var(--vx-color-bg-subtle);\n flex-shrink: 0;\n min-height: 2.75rem;\n box-sizing: border-box;\n overflow: visible;\n }\n\n .vx-grid__toolbar-left,\n .vx-grid__toolbar-right {\n display: flex;\n align-items: center;\n gap: var(--vx-space-2);\n min-width: 0;\n }\n\n .vx-grid__toolbar-right {\n flex-shrink: 0;\n }\n\n .vx-grid__toolbar-hint {\n color: var(--vx-color-text-muted);\n font-size: var(--vx-font-size-xs);\n }\n\n .vx-grid__filter-pill {\n display: inline-flex;\n align-items: center;\n gap: var(--vx-space-2);\n padding: 0.2rem 0.6rem;\n border-radius: 999px;\n background: var(--vx-color-badge-bg, var(--vx-color-primary-subtle));\n color: var(--vx-color-badge-fg, var(--vx-color-primary-ink));\n font-size: var(--vx-font-size-xs);\n }\n\n .vx-grid__group-label {\n display: inline-flex;\n align-items: center;\n gap: var(--vx-space-2);\n font-size: var(--vx-font-size-xs);\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__group-select {\n height: 1.75rem;\n border: 1px solid var(--vx-color-border-strong);\n border-radius: var(--vx-radius-md);\n background: var(--vx-color-bg-elevated);\n color: var(--vx-color-text);\n font: inherit;\n font-size: var(--vx-font-size-xs);\n }\n\n .vx-grid__row--group {\n background: var(--vx-color-bg-muted);\n font-weight: var(--vx-font-weight-semibold);\n cursor: pointer;\n }\n\n .vx-grid__cell--group {\n flex: 1;\n width: 100% !important;\n gap: var(--vx-space-2);\n }\n\n .vx-grid__group-chevron {\n display: inline-block;\n transition: transform var(--vx-transition-fast);\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__group-chevron--open {\n transform: rotate(90deg);\n }\n\n .vx-grid__group-count {\n color: var(--vx-color-text-secondary);\n font-weight: var(--vx-font-weight-normal);\n }\n\n .vx-grid__edit-input {\n width: 100%;\n height: 1.6rem;\n border: 1px solid var(--vx-color-border-focus);\n border-radius: var(--vx-radius-sm);\n background: var(--vx-color-bg-elevated);\n color: var(--vx-color-text);\n font: inherit;\n padding: 0 var(--vx-space-1);\n box-shadow: var(--vx-focus-ring);\n }\n\n .vx-grid__cell--editing {\n padding: 2px var(--vx-space-1);\n }\n\n .vx-grid__filter-clear {\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n text-decoration: underline;\n font: inherit;\n padding: 0;\n }\n\n .vx-grid__tool-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.35rem;\n height: 2rem;\n min-width: 2rem;\n padding: 0 0.7rem;\n border-radius: var(--vx-radius-md);\n border: 1px solid var(--vx-color-border);\n background: var(--vx-color-surface);\n color: var(--vx-color-text);\n cursor: pointer;\n font: inherit;\n font-size: var(--vx-font-size-xs);\n font-weight: var(--vx-font-weight-semibold);\n line-height: 1;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .vx-grid__tool-btn:hover {\n border-color: var(--vx-color-primary);\n background: var(--vx-color-primary-subtle);\n color: var(--vx-color-primary-ink, var(--vx-color-primary));\n }\n\n .vx-grid__tool-btn-icon {\n font-size: 0.85rem;\n line-height: 1;\n }\n\n .vx-grid__ai-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n padding: 0;\n border-radius: 999px;\n border: 1px solid var(--vx-color-border);\n background: var(--vx-color-surface);\n color: var(--vx-color-primary);\n cursor: pointer;\n font-size: 0.95rem;\n line-height: 1;\n flex-shrink: 0;\n }\n\n .vx-grid__ai-btn:hover {\n border-color: var(--vx-color-primary);\n background: var(--vx-color-primary-subtle);\n }\n\n .vx-grid__ai-btn--ghost {\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__header {\n display: flex;\n width: 100%;\n box-sizing: border-box;\n background: var(--vx-grid-header-bg);\n border-bottom: 1px solid var(--vx-grid-border);\n font-weight: var(--vx-font-weight-semibold);\n color: var(--vx-color-text);\n flex-shrink: 0;\n overflow: hidden;\n user-select: none;\n z-index: 2;\n }\n\n .vx-grid__header-cell {\n display: flex;\n align-items: center;\n gap: var(--vx-space-1);\n padding: 0 var(--vx-space-3);\n height: 40px;\n border-right: none;\n cursor: pointer;\n box-sizing: border-box;\n overflow: hidden;\n min-width: 0;\n }\n\n .vx-grid--column-lines .vx-grid__header-cell {\n border-right: 1px solid var(--vx-grid-border);\n }\n\n .vx-grid--column-lines .vx-grid__header-cell:last-child {\n border-right: none;\n }\n\n .vx-grid__header-cell:hover {\n background: var(--vx-color-bg-hover);\n }\n\n .vx-grid__header-cell--ai {\n color: var(--vx-color-primary);\n gap: var(--vx-space-2);\n }\n\n .vx-grid__ai-col-icon {\n font-size: 0.85rem;\n }\n\n .vx-grid__cell--ai {\n font-style: italic;\n color: var(--vx-color-text-secondary);\n }\n\n .vx-grid__cell--ai-empty {\n color: var(--vx-color-text-muted);\n font-style: normal;\n }\n\n .vx-grid__cell--ai-loading {\n opacity: 0.7;\n }\n\n .vx-grid__ai-skeleton {\n letter-spacing: 0.15em;\n color: var(--vx-color-text-muted);\n }\n\n .vx-grid__body {\n flex: 1;\n overflow: auto;\n position: relative;\n min-height: 0;\n contain: strict;\n scrollbar-gutter: stable;\n }\n\n .vx-grid__spacer {\n width: 1px;\n pointer-events: none;\n }\n\n .vx-grid__window {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n width: 100%;\n will-change: transform;\n }\n\n .vx-grid__row {\n display: flex;\n width: 100%;\n border-bottom: none;\n cursor: pointer;\n box-sizing: border-box;\n background: var(--vx-color-surface);\n }\n\n .vx-grid--row-lines .vx-grid__row {\n border-bottom: 1px solid var(--vx-grid-border);\n }\n\n .vx-grid__row--stripe {\n background: var(--vx-grid-stripe);\n }\n\n .vx-grid__row:hover {\n background: var(--vx-grid-row-hover);\n }\n\n .vx-grid__row--selected {\n background: var(--vx-grid-row-selected);\n }\n\n .vx-grid__cell {\n padding: 0 var(--vx-space-3);\n display: flex;\n align-items: center;\n border-right: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--vx-color-text);\n box-sizing: border-box;\n min-width: 0;\n }\n\n .vx-grid--column-lines .vx-grid__cell {\n border-right: 1px solid var(--vx-grid-border);\n }\n\n .vx-grid--column-lines .vx-grid__cell:last-child {\n border-right: none;\n }\n\n .vx-grid__footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: var(--vx-space-3);\n padding: var(--vx-space-2) var(--vx-space-4);\n border-top: 1px solid var(--vx-grid-border);\n background: var(--vx-grid-header-bg);\n font-size: var(--vx-font-size-xs);\n color: var(--vx-color-text-secondary);\n flex-shrink: 0;\n }\n\n .vx-grid__loading,\n .vx-grid__empty {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: var(--vx-color-text-muted);\n }\n `,\n})\nexport class VxDataGridComponent<T = unknown> {\n private readonly destroyRef = inject(DestroyRef);\n\n readonly columns = input.required<VxColumnDef<T>[]>();\n readonly data = input<T[]>([]);\n readonly dataSource = input<VxDataSource<T> | null>(null);\n readonly totalCount = input<number | null>(null);\n readonly loading = input(false);\n readonly rowHeight = input(36);\n readonly overscan = input(8);\n readonly virtualScroll = input(true);\n readonly trackByField = input<string>('id');\n readonly selectable = input(true);\n readonly multiSelect = input(true);\n /**\n * Linhas verticais entre colunas (header + cells).\n * Default `false` — visual Fluent / DevExtreme sem grade vertical.\n */\n readonly showColumnLines = input(false);\n /** Linhas horizontais entre rows. Default `true`. */\n readonly showRowLines = input(true);\n /** Habilita edição inline (duplo clique). */\n readonly editable = input(false);\n readonly exportEnabled = input(true);\n /** Campo de agrupamento (client-side). */\n readonly groupBy = model<string | null>(null);\n\n /** Opt-in AI (default off). */\n readonly ai = input<VortexAIConfig | null>(null);\n readonly aiIntegration = input<VortexAIIntegration | null>(null);\n\n readonly sortChange = output<VxSortState | null>();\n readonly filterChange = output<VxFilterState | null>();\n readonly selectionChange = output<T[]>();\n readonly rowClick = output<T>();\n readonly cellEdit = output<VxCellEditEvent<T>>();\n readonly exported = output<{ format: 'csv'; count: number }>();\n readonly loadRequest = output<{\n skip: number;\n take: number;\n sort: VxSortState | null;\n filter: VxFilterState | null;\n }>();\n readonly aiRequestCreating = output<VortexAIRequestCreatingEvent>();\n readonly aiCommandExecuted = output<VortexAICommand>();\n readonly aiRequestCompleted = output<{ text: string }>();\n readonly aiRequestFailed = output<{ error: unknown }>();\n\n private readonly bodyRef = viewChild<ElementRef<HTMLElement>>('bodyRef');\n private readonly headerRef = viewChild<ElementRef<HTMLElement>>('headerRef');\n\n readonly sort = signal<VxSortState | null>(null);\n readonly filter = signal<VxFilterState | null>(null);\n readonly selected = signal<Set<unknown>>(new Set());\n readonly scrollTop = signal(0);\n readonly viewportHeight = signal(400);\n /** Compensa a barra de rolagem do body para alinhar header ↔ rows. */\n readonly scrollbarWidth = signal(0);\n\n readonly windowRows = signal<Array<T | VxGroupRow>>([]);\n readonly startIndex = signal(0);\n readonly remoteLoading = signal(false);\n readonly remoteTotal = signal(0);\n readonly collapsedGroups = signal<Set<string>>(new Set());\n readonly editDraft = signal('');\n readonly editingKey = signal<string | null>(null);\n readonly editingField = signal<string | null>(null);\n\n readonly assistantOpen = signal(false);\n readonly promptEditorOpen = signal(false);\n readonly aiColumnPrompt = signal('Resuma a linha em uma frase curta');\n readonly activeAiColumnField = signal<string | null>(null);\n /** Cache em memória: `${columnField}::${rowKey}` → valor gerado (não grava no dataSource). */\n readonly aiCellValues = signal<Record<string, string>>({});\n readonly aiCellLoading = signal<Record<string, boolean>>({});\n readonly aiColumnDirty = signal(false);\n readonly aiMessages = signal<VxAIChatMessage[]>([]);\n readonly aiBusy = signal(false);\n\n readonly aiColumnCanApply = computed(\n () => this.aiColumnDirty() && this.aiColumnPrompt().trim().length > 0\n );\n\n private loadSeq = 0;\n private resizeObserver: ResizeObserver | null = null;\n private scrollRaf = 0;\n private lastRemoteKey = '';\n private lastClientKey = '';\n private lastViewportH = 0;\n\n readonly aiEnabled = computed(() => !!this.ai()?.enabled);\n\n readonly assistantTitle = computed(\n () => this.ai()?.assistant?.title ?? DEFAULT_AI.assistant.title\n );\n\n readonly aiSuggestions = computed<VortexAISuggestion[]>(() => [\n { id: 'help', label: 'Ajuda', prompt: 'ajuda' },\n {\n id: 'filter-health',\n label: 'Filtrar setor por Saúde',\n command: {\n type: 'filter.set',\n payload: { field: 'sector', value: 'Saúde', operator: 'contains' },\n },\n },\n {\n id: 'sort-region',\n label: 'Ordenar por região',\n command: { type: 'sort.set', payload: { field: 'region', direction: 'asc' } },\n },\n {\n id: 'group-product',\n label: 'Agrupar por produto',\n command: { type: 'group.set', payload: { field: 'product' } },\n },\n ]);\n\n readonly groupableFields = computed(() =>\n this.columns().filter((c) => c.type !== 'ai' && c.field)\n );\n\n readonly totalRows = computed(() => {\n if (this.dataSource() && !this.groupBy()) return this.remoteTotal();\n return this.displayRows().length;\n });\n\n readonly selectedCount = computed(() => this.selected().size);\n\n readonly spacerHeight = computed(() =>\n Math.min(this.totalRows() * this.rowHeight(), MAX_SPACER_PX)\n );\n\n readonly offsetY = computed(() => {\n const total = this.totalRows();\n const rh = this.rowHeight();\n const natural = total * rh;\n const spacer = this.spacerHeight();\n if (natural <= spacer || natural === 0) return this.startIndex() * rh;\n return this.startIndex() * rh * (spacer / natural);\n });\n\n readonly endIndexDisplay = computed(() =>\n Math.min(this.totalRows(), this.startIndex() + this.windowRows().length)\n );\n\n private readonly filteredClientRows = computed(() => {\n const rows = this.data() as Record<string, unknown>[];\n const filter = this.filter();\n const sort = this.sort();\n let next = rows;\n if (filter?.field && filter.value) {\n const needle = String(filter.value).toLowerCase();\n const op = filter.operator ?? 'contains';\n next = next.filter((row) => {\n const hay = String(row[filter.field] ?? '').toLowerCase();\n return op === 'equals' ? hay === needle : hay.includes(needle);\n });\n }\n if (sort) {\n const dir = sort.direction === 'asc' ? 1 : -1;\n next = next.slice().sort((a, b) => {\n const av = a[sort.field];\n const bv = b[sort.field];\n if (av == null && bv == null) return 0;\n if (av == null) return -1 * dir;\n if (bv == null) return 1 * dir;\n if (av < bv) return -1 * dir;\n if (av > bv) return 1 * dir;\n return 0;\n });\n }\n return next as T[];\n });\n\n /** Linhas exibidas (dados + headers de grupo quando `groupBy` ativo). */\n private readonly displayRows = computed(() => {\n const rows = this.filteredClientRows();\n const field = this.groupBy();\n if (!field) return rows as Array<T | VxGroupRow>;\n\n const collapsed = this.collapsedGroups();\n const buckets = new Map<string, T[]>();\n for (const row of rows) {\n const key = String((row as Record<string, unknown>)[field] ?? '(vazio)');\n const list = buckets.get(key) ?? [];\n list.push(row);\n buckets.set(key, list);\n }\n\n const out: Array<T | VxGroupRow> = [];\n for (const [key, list] of buckets) {\n out.push({ __vxGroup: true, key, label: `${field}: ${key}`, count: list.length });\n if (!collapsed.has(key)) {\n out.push(...list);\n }\n }\n return out;\n });\n\n constructor() {\n afterNextRender(() => {\n this.setupViewportObservers();\n void this.refreshWindow(true);\n });\n\n effect(() => {\n this.data();\n this.dataSource();\n this.sort();\n this.filter();\n this.groupBy();\n this.collapsedGroups();\n this.rowHeight();\n this.overscan();\n this.virtualScroll();\n untracked(() => {\n this.lastRemoteKey = '';\n this.lastClientKey = '';\n void this.refreshWindow(true);\n });\n });\n\n this.destroyRef.onDestroy(() => {\n this.resizeObserver?.disconnect();\n if (this.scrollRaf) cancelAnimationFrame(this.scrollRaf);\n });\n }\n\n private setupViewportObservers(): void {\n const body = this.bodyRef()?.nativeElement;\n if (!body) return;\n const measure = () => {\n this.syncScrollbarGap(body);\n const h = body.clientHeight || 400;\n if (Math.abs(h - this.lastViewportH) < 2) return;\n this.lastViewportH = h;\n this.viewportHeight.set(h);\n void this.refreshWindow(false);\n };\n measure();\n this.resizeObserver = new ResizeObserver(() => measure());\n this.resizeObserver.observe(body);\n }\n\n private syncScrollbarGap(body: HTMLElement): void {\n const gap = Math.max(0, body.offsetWidth - body.clientWidth);\n if (gap !== this.scrollbarWidth()) this.scrollbarWidth.set(gap);\n }\n\n onScroll(event: Event): void {\n const body = event.target as HTMLElement;\n const header = this.headerRef()?.nativeElement;\n this.syncScrollbarGap(body);\n if (header) header.scrollLeft = body.scrollLeft;\n if (this.scrollRaf) cancelAnimationFrame(this.scrollRaf);\n this.scrollRaf = requestAnimationFrame(() => {\n this.scrollTop.set(body.scrollTop);\n void this.refreshWindow(false);\n });\n }\n\n private scrollTopToIndex(scrollTop: number, total: number): number {\n const rh = this.rowHeight();\n const natural = total * rh;\n const spacer = Math.min(natural, MAX_SPACER_PX);\n if (natural <= spacer || spacer <= 0) return Math.floor(scrollTop / rh);\n return Math.floor((scrollTop / spacer) * total);\n }\n\n private computeRange(total: number): { start: number; take: number } {\n const rh = this.rowHeight();\n const overscan = this.overscan();\n const vh = this.viewportHeight();\n if (!this.virtualScroll()) return { start: 0, take: Math.min(total, 500) };\n if (total <= 0) return { start: 0, take: 0 };\n const visibleCount = Math.ceil(vh / rh) + 1;\n let start = Math.max(0, this.scrollTopToIndex(this.scrollTop(), total) - overscan);\n let end = Math.min(total, start + visibleCount + overscan * 2);\n start = Math.min(start, Math.max(0, total - 1));\n return { start, take: Math.max(0, end - start) };\n }\n\n private async refreshWindow(force: boolean): Promise<void> {\n const ds = this.dataSource();\n // Agrupamento é client-side — ignora dataSource enquanto groupBy estiver ativo.\n if (ds && !this.groupBy()) {\n const knownTotal = this.remoteTotal();\n const probeTotal = knownTotal > 0 ? knownTotal : 1_000_000;\n const { start, take } = this.computeRange(probeTotal);\n await this.loadFromSource(ds, start, Math.max(take, 1), force);\n return;\n }\n\n const rows = this.displayRows();\n const total = rows.length;\n const { start, take } = this.computeRange(total);\n const key = `${start}:${take}:${this.sort()?.field ?? ''}:${this.filter()?.field ?? ''}:${this.filter()?.value ?? ''}`;\n if (!force && key === this.lastClientKey) return;\n this.lastClientKey = key;\n this.startIndex.set(start);\n this.windowRows.set(rows.slice(start, start + take));\n }\n\n private async loadFromSource(\n ds: VxDataSource<T>,\n skip: number,\n take: number,\n force: boolean\n ): Promise<void> {\n const sort = this.sort();\n const filter = this.filter();\n const key = `${skip}:${take}:${sort?.field ?? ''}:${sort?.direction ?? ''}:${filter?.field ?? ''}:${filter?.value ?? ''}`;\n if (!force && key === this.lastRemoteKey) return;\n\n const seq = ++this.loadSeq;\n if (this.windowRows().length === 0) this.remoteLoading.set(true);\n this.loadRequest.emit({ skip, take, sort, filter });\n\n try {\n const result = await Promise.resolve(ds.load({ skip, take, sort, filter }));\n if (seq !== this.loadSeq) return;\n this.lastRemoteKey = key;\n this.remoteTotal.set(result.totalCount);\n this.startIndex.set(skip);\n this.windowRows.set(result.data);\n } finally {\n if (seq === this.loadSeq) this.remoteLoading.set(false);\n }\n }\n\n // —— AI ——\n isAiColumn(col: VxColumnDef<T>): boolean {\n return col.type === 'ai';\n }\n\n aiNoDataText(col: VxColumnDef<T>): string {\n return col.ai?.noDataText ?? 'No data';\n }\n\n private aiCacheKey(row: T, col: VxColumnDef<T>): string {\n return `${col.field}::${String(this.trackBy(row))}`;\n }\n\n aiCellValue(row: T, col: VxColumnDef<T>): string | null {\n return this.aiCellValues()[this.aiCacheKey(row, col)] ?? null;\n }\n\n isAiCellLoading(row: T, col: VxColumnDef<T>): boolean {\n return !!this.aiCellLoading()[this.aiCacheKey(row, col)];\n }\n\n onHeaderClick(col: VxColumnDef<T>): void {\n if (this.isAiColumn(col)) {\n this.openPromptEditor(col);\n return;\n }\n this.onSort(col);\n }\n\n openAssistant(): void {\n if (!this.aiEnabled()) return;\n this.assistantOpen.set(true);\n }\n\n openPromptEditor(col?: VxColumnDef<T>): void {\n if (!this.aiEnabled()) return;\n const aiCol =\n col && this.isAiColumn(col)\n ? col\n : this.columns().find((c) => c.type === 'ai') ?? null;\n if (aiCol) {\n this.activeAiColumnField.set(aiCol.field);\n this.aiColumnPrompt.set(aiCol.ai?.prompt ?? this.aiColumnPrompt());\n } else {\n this.activeAiColumnField.set(null);\n }\n this.promptEditorOpen.set(true);\n }\n\n onPromptEditorOpenChange(open: boolean): void {\n this.promptEditorOpen.set(open);\n }\n\n clearChat(): void {\n this.aiMessages.set([]);\n }\n\n clearFilter(): void {\n this.filter.set(null);\n this.filterChange.emit(null);\n }\n\n /** Aplica filtro externo (ex.: vx-filter-builder). */\n setFilter(next: VxFilterState | null): void {\n this.filter.set(next);\n this.filterChange.emit(next);\n }\n\n async onSuggestion(s: VortexAISuggestion): Promise<void> {\n if (s.command) {\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'user', content: s.label },\n ]);\n await this.executeCommands([s.command]);\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'assistant', title: 'Comando aplicado', content: s.label },\n ]);\n return;\n }\n if (s.prompt) await this.onAssistantSend(s.prompt);\n }\n\n async onAssistantSend(text: string): Promise<void> {\n const integration = this.aiIntegration();\n if (!this.aiEnabled() || !integration) return;\n\n this.aiMessages.update((msgs) => [...msgs, { role: 'user', content: text }]);\n this.aiBusy.set(true);\n\n try {\n let request = this.buildAIRequest(text);\n const ev: VortexAIRequestCreatingEvent = { request, cancel: false };\n this.aiRequestCreating.emit(ev);\n if (ev.cancel) {\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'assistant', title: 'Cancelado', content: 'Request cancelado pelo app.' },\n ]);\n return;\n }\n request = ev.request;\n\n const response = await integration.sendRequest(request);\n if (response.commands?.length) {\n await this.executeCommands(response.commands);\n }\n this.aiMessages.update((msgs) => [\n ...msgs,\n {\n role: 'assistant',\n title: response.title,\n content: response.text,\n },\n ]);\n this.aiRequestCompleted.emit({ text: response.text });\n } catch (error) {\n this.aiRequestFailed.emit({ error });\n this.aiMessages.update((msgs) => [\n ...msgs,\n { role: 'assistant', title: 'Erro', content: 'Falha ao consultar o assistente.' },\n ]);\n } finally {\n this.aiBusy.set(false);\n }\n }\n\n async onPromptRegenerate(prompt: string): Promise<void> {\n this.aiColumnPrompt.set(prompt);\n const field = this.activeAiColumnField() ?? this.columns().find((c) => c.type === 'ai')?.field;\n if (!field) return;\n await this.regenerateAiColumn(field, prompt);\n }\n\n onPromptApply(prompt: string): void {\n this.aiColumnPrompt.set(prompt);\n const field = this.activeAiColumnField();\n const cells = Object.entries(this.aiCellValues())\n .filter(([k]) => k.startsWith(`${field}::`))\n .map(([k, value]) => ({\n rowKey: k.slice(String(field).length + 2),\n value,\n }));\n\n this.promptEditorOpen.set(false);\n this.aiColumnDirty.set(false);\n this.aiCommandExecuted.emit({\n type: 'aiColumn.apply',\n payload: { prompt, field, cells },\n });\n // R5: não persiste no dataSource — app decide o que fazer com o evento\n }\n\n private async regenerateAiColumn(field: string, prompt: string): Promise<void> {\n const integration = this.aiIntegration();\n if (!this.aiEnabled() || !integration) return;\n\n const col = this.columns().find((c) => c.field === field);\n if (!col || !this.isAiColumn(col)) return;\n\n const cfg = this.ai();\n const dataRows = this.dataWindowRows();\n const rows = projectRowsForAI(dataRows as Record<string, unknown>[], {\n contextFields: cfg?.contextFields,\n maxRowsInContext: cfg?.maxRowsInContext ?? DEFAULT_AI.maxRowsInContext,\n });\n\n // Marca loading nas linhas da janela\n const loadingPatch: Record<string, boolean> = { ...this.aiCellLoading() };\n for (const row of dataRows) {\n loadingPatch[this.aiCacheKey(row, col)] = true;\n }\n this.aiCellLoading.set(loadingPatch);\n this.aiBusy.set(true);\n\n try {\n let request: VortexAIRequest = {\n feature: 'ai-column',\n componentType: 'data-grid',\n prompt,\n context: {\n schemaVersion: 1,\n componentType: 'data-grid',\n columns: this.columns()\n .filter((c) => c.type !== 'ai')\n .map((c) => ({ field: c.field, header: c.header })),\n sort: this.sort(),\n filter: this.filter(),\n rows,\n totalRows: this.totalRows(),\n meta: { aiColumn: field, prompt },\n },\n };\n\n const ev: VortexAIRequestCreatingEvent = { request, cancel: false };\n this.aiRequestCreating.emit(ev);\n if (ev.cancel) return;\n request = ev.request;\n\n const response = await integration.sendRequest(request);\n const cells = response.data?.cells ?? [];\n const valuesPatch: Record<string, string> = { ...this.aiCellValues() };\n for (const cell of cells) {\n valuesPatch[`${field}::${cell.rowKey}`] = cell.value;\n }\n this.aiCellValues.set(valuesPatch);\n this.aiColumnDirty.set(cells.length > 0);\n this.aiRequestCompleted.emit({ text: response.text });\n this.aiCommandExecuted.emit({\n type: 'aiColumn.regenerate',\n payload: { field, prompt, count: cells.length },\n });\n } catch (error) {\n this.aiRequestFailed.emit({ error });\n } finally {\n const clearLoading: Record<string, boolean> = { ...this.aiCellLoading() };\n for (const row of this.dataWindowRows()) {\n delete clearLoading[this.aiCacheKey(row, col)];\n }\n this.aiCellLoading.set(clearLoading);\n this.aiBusy.set(false);\n }\n }\n\n private buildAIRequest(userText: string): VortexAIRequest {\n const cfg = this.ai();\n const fields = cfg?.contextFields;\n const maxRows = cfg?.maxRowsInContext ?? DEFAULT_AI.maxRowsInContext;\n const rows = projectRowsForAI(\n this.dataWindowRows() as Record<string, unknown>[],\n { contextFields: fields, maxRowsInContext: maxRows }\n );\n\n return {\n feature: 'assistant',\n componentType: 'data-grid',\n messages: [...this.aiMessages(), { role: 'user', content: userText }],\n context: {\n schemaVersion: 1,\n componentType: 'data-grid',\n columns: this.columns().map((c) => ({ field: c.field, header: c.header })),\n sort: this.sort(),\n filter: this.filter(),\n rows,\n totalRows: this.totalRows(),\n },\n tools: [\n { name: 'filter.set', description: 'Define filtro por campo/valor' },\n { name: 'filter.clear', description: 'Limpa filtros' },\n { name: 'sort.set', description: 'Ordena por campo' },\n { name: 'group.set', description: 'Agrupa por campo (preview)' },\n ],\n };\n }\n\n private async executeCommands(commands: VortexAICommand[]): Promise<void> {\n for (const cmd of commands) {\n switch (cmd.type) {\n case 'filter.set': {\n const field = String(cmd.payload?.['field'] ?? '');\n const value = String(cmd.payload?.['value'] ?? '');\n const operator = (cmd.payload?.['operator'] as VxFilterState['operator']) ?? 'contains';\n if (field && value) {\n const next = { field, value, operator };\n this.filter.set(next);\n this.filterChange.emit(next);\n }\n break;\n }\n case 'filter.clear':\n this.clearFilter();\n break;\n case 'sort.set': {\n const field = String(cmd.payload?.['field'] ?? '');\n const direction = (cmd.payload?.['direction'] as 'asc' | 'desc') ?? 'asc';\n if (field) {\n const next = { field, direction };\n this.sort.set(next);\n this.sortChange.emit(next);\n }\n break;\n }\n case 'group.set': {\n const field = String(cmd.payload?.['field'] ?? '');\n if (field) {\n this.groupBy.set(field);\n this.collapsedGroups.set(new Set());\n }\n break;\n }\n default:\n break;\n }\n this.aiCommandExecuted.emit(cmd);\n }\n }\n\n /**\n * Largura dinâmica (paridade DX):\n * - com `width` → tamanho fixo\n * - sem `width` → flex grow (reparte o espaço restante e preenche o container)\n */\n colStyle(col: VxColumnDef<T>): Record<string, string> {\n const min = `${col.minWidth ?? 80}px`;\n if (col.width != null) {\n const w = typeof col.width === 'number' ? `${col.width}px` : String(col.width);\n return { flex: `0 0 ${w}`, width: w, minWidth: min, maxWidth: w };\n }\n return { flex: '1 1 0%', width: 'auto', minWidth: min };\n }\n\n /** @deprecated Prefer `colStyle` — mantido por compatibilidade interna. */\n colWidth(col: VxColumnDef<T>): string {\n if (col.width == null) return 'auto';\n return typeof col.width === 'number' ? `${col.width}px` : col.width;\n }\n\n trackBy = (row: T) => {\n const field = this.trackByField();\n return (row as Record<string, unknown>)[field] ?? row;\n };\n\n getCellValue(row: T, col: VxColumnDef<T>): unknown {\n if (col.valueGetter) return col.valueGetter(row);\n return (row as Record<string, unknown>)[col.field];\n }\n\n isSelected(row: T): boolean {\n return this.selected().has(this.trackBy(row));\n }\n\n toggleSelection(row: T): void {\n if (!this.selectable()) {\n this.rowClick.emit(row);\n return;\n }\n const key = this.trackBy(row);\n const next = new Set(this.selected());\n if (next.has(key)) next.delete(key);\n else {\n if (!this.multiSelect()) next.clear();\n next.add(key);\n }\n this.selected.set(next);\n this.selectionChange.emit(\n this.dataWindowRows().filter((r) => next.has(this.trackBy(r)))\n );\n this.rowClick.emit(row);\n }\n\n private dataWindowRows(): T[] {\n return this.windowRows().filter((r): r is T => !this.isGroupRow(r));\n }\n\n onSort(col: VxColumnDef<T>): void {\n if (this.isAiColumn(col) || col.sortable === false) return;\n const current = this.sort();\n let next: VxSortState | null = null;\n if (!current || current.field !== col.field) next = { field: col.field, direction: 'asc' };\n else if (current.direction === 'asc') next = { field: col.field, direction: 'desc' };\n else next = null;\n this.sort.set(next);\n this.sortChange.emit(next);\n }\n\n onGroupSelect(event: Event): void {\n const value = (event.target as HTMLSelectElement).value;\n this.groupBy.set(value || null);\n this.collapsedGroups.set(new Set());\n }\n\n clearGroup(): void {\n this.groupBy.set(null);\n this.collapsedGroups.set(new Set());\n }\n\n isGroupRow(row: T | VxGroupRow): row is VxGroupRow {\n return !!row && typeof row === 'object' && (row as VxGroupRow).__vxGroup === true;\n }\n\n asDataRow(row: T | VxGroupRow): T {\n return row as T;\n }\n\n groupKey(row: T | VxGroupRow): string {\n return this.isGroupRow(row) ? row.key : '';\n }\n\n groupLabel(row: T | VxGroupRow): string {\n return this.isGroupRow(row) ? row.label : '';\n }\n\n groupCount(row: T | VxGroupRow): number {\n return this.isGroupRow(row) ? row.count : 0;\n }\n\n isGroupExpanded(key: string): boolean {\n return !this.collapsedGroups().has(key);\n }\n\n toggleGroupExpand(key: string): void {\n const next = new Set(this.collapsedGroups());\n if (next.has(key)) next.delete(key);\n else next.add(key);\n this.collapsedGroups.set(next);\n }\n\n trackDisplay(row: T | VxGroupRow, index: number): unknown {\n if (this.isGroupRow(row)) return `g:${row.key}`;\n return this.trackBy(row as T) ?? index;\n }\n\n isEditing(row: T, col: VxColumnDef<T>): boolean {\n if (!this.editable() || this.isAiColumn(col) || col.editable === false) return false;\n return this.editingKey() === String(this.trackBy(row)) && this.editingField() === col.field;\n }\n\n startEdit(row: T, col: VxColumnDef<T>, event: Event): void {\n if (!this.editable() || this.isAiColumn(col) || col.editable === false) return;\n event.stopPropagation();\n this.editingKey.set(String(this.trackBy(row)));\n this.editingField.set(col.field);\n this.editDraft.set(String(this.getCellValue(row, col) ?? ''));\n }\n\n commitEdit(): void {\n const key = this.editingKey();\n const field = this.editingField();\n if (key == null || field == null) return;\n const row = this.displayRows().find(\n (r) => !this.isGroupRow(r) && String(this.trackBy(r as T)) === key\n ) as T | undefined;\n if (!row) {\n this.cancelEdit();\n return;\n }\n const previousValue = (row as Record<string, unknown>)[field];\n const value = this.editDraft();\n (row as Record<string, unknown>)[field] = value;\n this.cellEdit.emit({ row, field, value, previousValue });\n this.cancelEdit();\n void this.refreshWindow(true);\n }\n\n cancelEdit(): void {\n this.editingKey.set(null);\n this.editingField.set(null);\n this.editDraft.set('');\n }\n\n exportCsv(): void {\n const cols = this.columns();\n const rows = this.filteredClientRows();\n exportRowsToCsv(rows, cols, 'vortex-grid.csv');\n this.exported.emit({ format: 'csv', count: rows.length });\n }\n}\n"]}
@@ -6,8 +6,13 @@ export declare class VxAutocompleteComponent {
6
6
  readonly value: import("@angular/core").ModelSignal<string>;
7
7
  readonly query: import("@angular/core").ModelSignal<string>;
8
8
  readonly optionSelected: import("@angular/core").OutputEmitterRef<string>;
9
+ /** Controla abertura do painel (fecha ao selecionar). */
10
+ private readonly open;
9
11
  readonly suggestions: import("@angular/core").Signal<string[]>;
12
+ readonly panelOpen: import("@angular/core").Signal<boolean>;
10
13
  onQuery(event: Event): void;
14
+ onFocus(): void;
15
+ close(): void;
11
16
  pick(item: string): void;
12
17
  static ɵfac: i0.ɵɵFactoryDeclaration<VxAutocompleteComponent, never>;
13
18
  static ɵcmp: i0.ɵɵComponentDeclaration<VxAutocompleteComponent, "vx-autocomplete", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "query": { "alias": "query"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "query": "queryChange"; "optionSelected": "optionSelected"; }, never, never, true, never>;
@@ -26,6 +26,13 @@ export declare class VxDataGridComponent<T = unknown> {
26
26
  readonly trackByField: import("@angular/core").InputSignal<string>;
27
27
  readonly selectable: import("@angular/core").InputSignal<boolean>;
28
28
  readonly multiSelect: import("@angular/core").InputSignal<boolean>;
29
+ /**
30
+ * Linhas verticais entre colunas (header + cells).
31
+ * Default `false` — visual Fluent / DevExtreme sem grade vertical.
32
+ */
33
+ readonly showColumnLines: import("@angular/core").InputSignal<boolean>;
34
+ /** Linhas horizontais entre rows. Default `true`. */
35
+ readonly showRowLines: import("@angular/core").InputSignal<boolean>;
29
36
  /** Habilita edição inline (duplo clique). */
30
37
  readonly editable: import("@angular/core").InputSignal<boolean>;
31
38
  readonly exportEnabled: import("@angular/core").InputSignal<boolean>;
@@ -64,7 +71,9 @@ export declare class VxDataGridComponent<T = unknown> {
64
71
  readonly selected: import("@angular/core").WritableSignal<Set<unknown>>;
65
72
  readonly scrollTop: import("@angular/core").WritableSignal<number>;
66
73
  readonly viewportHeight: import("@angular/core").WritableSignal<number>;
67
- readonly windowRows: import("@angular/core").WritableSignal<(VxGroupRow | T)[]>;
74
+ /** Compensa a barra de rolagem do body para alinhar header ↔ rows. */
75
+ readonly scrollbarWidth: import("@angular/core").WritableSignal<number>;
76
+ readonly windowRows: import("@angular/core").WritableSignal<(T | VxGroupRow)[]>;
68
77
  readonly startIndex: import("@angular/core").WritableSignal<number>;
69
78
  readonly remoteLoading: import("@angular/core").WritableSignal<boolean>;
70
79
  readonly remoteTotal: import("@angular/core").WritableSignal<number>;
@@ -103,6 +112,7 @@ export declare class VxDataGridComponent<T = unknown> {
103
112
  private readonly displayRows;
104
113
  constructor();
105
114
  private setupViewportObservers;
115
+ private syncScrollbarGap;
106
116
  onScroll(event: Event): void;
107
117
  private scrollTopToIndex;
108
118
  private computeRange;
@@ -158,5 +168,5 @@ export declare class VxDataGridComponent<T = unknown> {
158
168
  cancelEdit(): void;
159
169
  exportCsv(): void;
160
170
  static ɵfac: i0.ɵɵFactoryDeclaration<VxDataGridComponent<any>, never>;
161
- static ɵcmp: i0.ɵɵComponentDeclaration<VxDataGridComponent<any>, "vx-data-grid", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "dataSource": { "alias": "dataSource"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": false; "isSignal": true; }; "overscan": { "alias": "overscan"; "required": false; "isSignal": true; }; "virtualScroll": { "alias": "virtualScroll"; "required": false; "isSignal": true; }; "trackByField": { "alias": "trackByField"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "multiSelect": { "alias": "multiSelect"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "exportEnabled": { "alias": "exportEnabled"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; "ai": { "alias": "ai"; "required": false; "isSignal": true; }; "aiIntegration": { "alias": "aiIntegration"; "required": false; "isSignal": true; }; }, { "groupBy": "groupByChange"; "sortChange": "sortChange"; "filterChange": "filterChange"; "selectionChange": "selectionChange"; "rowClick": "rowClick"; "cellEdit": "cellEdit"; "exported": "exported"; "loadRequest": "loadRequest"; "aiRequestCreating": "aiRequestCreating"; "aiCommandExecuted": "aiCommandExecuted"; "aiRequestCompleted": "aiRequestCompleted"; "aiRequestFailed": "aiRequestFailed"; }, never, never, true, never>;
171
+ static ɵcmp: i0.ɵɵComponentDeclaration<VxDataGridComponent<any>, "vx-data-grid", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "dataSource": { "alias": "dataSource"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": false; "isSignal": true; }; "overscan": { "alias": "overscan"; "required": false; "isSignal": true; }; "virtualScroll": { "alias": "virtualScroll"; "required": false; "isSignal": true; }; "trackByField": { "alias": "trackByField"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "multiSelect": { "alias": "multiSelect"; "required": false; "isSignal": true; }; "showColumnLines": { "alias": "showColumnLines"; "required": false; "isSignal": true; }; "showRowLines": { "alias": "showRowLines"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "exportEnabled": { "alias": "exportEnabled"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; "ai": { "alias": "ai"; "required": false; "isSignal": true; }; "aiIntegration": { "alias": "aiIntegration"; "required": false; "isSignal": true; }; }, { "groupBy": "groupByChange"; "sortChange": "sortChange"; "filterChange": "filterChange"; "selectionChange": "selectionChange"; "rowClick": "rowClick"; "cellEdit": "cellEdit"; "exported": "exported"; "loadRequest": "loadRequest"; "aiRequestCreating": "aiRequestCreating"; "aiCommandExecuted": "aiCommandExecuted"; "aiRequestCompleted": "aiRequestCompleted"; "aiRequestFailed": "aiRequestFailed"; }, never, never, true, never>;
162
172
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joel_jsp/vortex-ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "VortexUI — Angular 22+ component suite (Signals, zoneless, AI opt-in, Fluent + LDS themes)",
5
5
  "license": "MIT",
6
6
  "author": "Joel Schecheleski",