argent-grid 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +69 -0
- package/.github/workflows/pages.yml +6 -12
- package/.storybook/main.ts +20 -0
- package/.storybook/preview.ts +18 -0
- package/.storybook/tsconfig.json +24 -0
- package/AGENTS.md +2 -2
- package/README.md +51 -34
- package/angular.json +66 -0
- package/biome.json +66 -0
- package/demo-app/e2e/selection-screenshot.spec.ts +20 -0
- package/docs/AG-GRID-COMPARISON.md +725 -0
- package/docs/CELL-RENDERER-GUIDE.md +241 -0
- package/docs/CONTEXT-MENU-GUIDE.md +371 -0
- package/docs/LIVE-DATA-OPTIMIZATIONS.md +497 -0
- package/docs/PERFORMANCE-OPTIMIZATIONS-PHASE1.md +162 -0
- package/docs/PERFORMANCE-REVIEW.md +571 -0
- package/docs/RESEARCH-STATUS.md +234 -0
- package/docs/STATE-PERSISTENCE-GUIDE.md +370 -0
- package/docs/STORYBOOK-REFACTOR.md +215 -0
- package/docs/STORYBOOK-STATUS.md +156 -0
- package/docs/TEST-COVERAGE-REPORT.md +276 -0
- package/docs/THEME-API-GUIDE.md +445 -0
- package/docs/THEME-API-PLAN.md +364 -0
- package/e2e/advanced.spec.ts +109 -0
- package/e2e/argentgrid.spec.ts +65 -0
- package/e2e/benchmark.spec.ts +52 -0
- package/e2e/screenshots.spec.ts +52 -0
- package/e2e/theming.spec.ts +35 -0
- package/e2e/visual.spec.ts +91 -0
- package/e2e/visual.spec.ts-snapshots/grid-default.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-empty-state.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-filter-popup.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-scroll-borders.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-sidebar-buttons.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-text-filter.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-with-selection.png +0 -0
- package/package.json +20 -6
- package/plan.md +50 -18
- package/playwright.config.ts +38 -0
- package/setup-vitest.ts +10 -13
- package/src/lib/argent-grid.module.ts +10 -12
- package/src/lib/components/argent-grid.component.css +327 -76
- package/src/lib/components/argent-grid.component.html +186 -64
- package/src/lib/components/argent-grid.component.spec.ts +120 -160
- package/src/lib/components/argent-grid.component.ts +642 -189
- package/src/lib/components/argent-grid.selection.spec.ts +132 -0
- package/src/lib/components/set-filter/set-filter.component.ts +302 -0
- package/src/lib/directives/ag-grid-compatibility.directive.ts +16 -26
- package/src/lib/directives/click-outside.directive.ts +19 -0
- package/src/lib/rendering/canvas-renderer.spec.ts +366 -0
- package/src/lib/rendering/canvas-renderer.ts +418 -305
- package/src/lib/rendering/live-data-handler.ts +110 -0
- package/src/lib/rendering/live-data-optimizations.ts +133 -0
- package/src/lib/rendering/render/blit.spec.ts +16 -27
- package/src/lib/rendering/render/blit.ts +48 -36
- package/src/lib/rendering/render/cells.spec.ts +132 -0
- package/src/lib/rendering/render/cells.ts +46 -24
- package/src/lib/rendering/render/column-utils.ts +73 -0
- package/src/lib/rendering/render/hit-test.ts +55 -0
- package/src/lib/rendering/render/index.ts +79 -76
- package/src/lib/rendering/render/lines.ts +43 -43
- package/src/lib/rendering/render/primitives.ts +161 -0
- package/src/lib/rendering/render/theme.spec.ts +8 -12
- package/src/lib/rendering/render/theme.ts +7 -10
- package/src/lib/rendering/render/types.ts +2 -2
- package/src/lib/rendering/render/walk.spec.ts +35 -38
- package/src/lib/rendering/render/walk.ts +60 -50
- package/src/lib/rendering/utils/damage-tracker.spec.ts +8 -7
- package/src/lib/rendering/utils/damage-tracker.ts +6 -18
- package/src/lib/rendering/utils/index.ts +1 -1
- package/src/lib/services/grid.service.set-filter.spec.ts +219 -0
- package/src/lib/services/grid.service.spec.ts +1165 -201
- package/src/lib/services/grid.service.ts +819 -187
- package/src/lib/themes/parts/color-schemes.ts +132 -0
- package/src/lib/themes/parts/icon-sets.ts +258 -0
- package/src/lib/themes/theme-builder.ts +347 -0
- package/src/lib/themes/theme-quartz.ts +72 -0
- package/src/lib/themes/types.ts +238 -0
- package/src/lib/types/ag-grid-types.ts +73 -14
- package/src/public-api.ts +39 -9
- package/src/stories/Advanced.stories.ts +188 -0
- package/src/stories/ArgentGrid.stories.ts +277 -0
- package/src/stories/Benchmark.stories.ts +74 -0
- package/src/stories/CellRenderers.stories.ts +221 -0
- package/src/stories/Filtering.stories.ts +252 -0
- package/src/stories/Grouping.stories.ts +217 -0
- package/src/stories/Theming.stories.ts +124 -0
- package/src/stories/benchmark-wrapper.component.ts +315 -0
- package/tsconfig.storybook.json +10 -0
- package/vitest.config.ts +9 -9
- package/demo-app/README.md +0 -70
- package/demo-app/angular.json +0 -78
- package/demo-app/e2e/benchmark.spec.ts +0 -53
- package/demo-app/e2e/demo-page.spec.ts +0 -77
- package/demo-app/e2e/grid-features.spec.ts +0 -269
- package/demo-app/package-lock.json +0 -14023
- package/demo-app/package.json +0 -36
- package/demo-app/playwright-test-menu.js +0 -19
- package/demo-app/playwright.config.ts +0 -23
- package/demo-app/src/app/app.component.ts +0 -10
- package/demo-app/src/app/app.config.ts +0 -13
- package/demo-app/src/app/app.routes.ts +0 -7
- package/demo-app/src/app/demo-page/demo-page.component.css +0 -313
- package/demo-app/src/app/demo-page/demo-page.component.html +0 -124
- package/demo-app/src/app/demo-page/demo-page.component.ts +0 -366
- package/demo-app/src/index.html +0 -19
- package/demo-app/src/main.ts +0 -6
- package/demo-app/tsconfig.json +0 -31
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Builder - Create and customize themes programmatically
|
|
3
|
+
*
|
|
4
|
+
* Inspired by AG Grid's new Theming API (v32.2+)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
PartialThemeParameters,
|
|
9
|
+
GridThemeObject as Theme,
|
|
10
|
+
ThemeBuilder,
|
|
11
|
+
ThemeParameters,
|
|
12
|
+
ThemePart,
|
|
13
|
+
} from './types';
|
|
14
|
+
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// THEME BUILDER CLASS
|
|
17
|
+
// ============================================================================
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Theme builder class for creating and customizing themes
|
|
21
|
+
*/
|
|
22
|
+
class ThemeBuilderImpl implements ThemeBuilder {
|
|
23
|
+
public readonly name: string;
|
|
24
|
+
public readonly description?: string;
|
|
25
|
+
public readonly parameters: ThemeParameters;
|
|
26
|
+
public readonly parts: ThemePart[];
|
|
27
|
+
|
|
28
|
+
constructor(config: {
|
|
29
|
+
name: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
parameters: ThemeParameters;
|
|
32
|
+
parts?: ThemePart[];
|
|
33
|
+
}) {
|
|
34
|
+
this.name = config.name;
|
|
35
|
+
this.description = config.description;
|
|
36
|
+
this.parameters = config.parameters;
|
|
37
|
+
this.parts = config.parts || [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create a new theme with overridden parameters
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const myTheme = themeQuartz.withParams({
|
|
46
|
+
* spacing: 12,
|
|
47
|
+
* accentColor: 'red',
|
|
48
|
+
* fontSize: 14,
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
withParams(params: PartialThemeParameters): ThemeBuilder {
|
|
53
|
+
const mergedParams = {
|
|
54
|
+
...this.parameters,
|
|
55
|
+
...params,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return new ThemeBuilderImpl({
|
|
59
|
+
name: this.name,
|
|
60
|
+
description: this.description,
|
|
61
|
+
parameters: mergedParams,
|
|
62
|
+
parts: this.parts,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Add a theme part to the theme
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const myTheme = themeQuartz
|
|
72
|
+
* .withPart(colorSchemeDark)
|
|
73
|
+
* .withPart(iconSetMaterial);
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
withPart(part: ThemePart): ThemeBuilder {
|
|
77
|
+
return new ThemeBuilderImpl({
|
|
78
|
+
name: this.name,
|
|
79
|
+
description: this.description,
|
|
80
|
+
parameters: this.parameters,
|
|
81
|
+
parts: [...this.parts, part],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the final theme object with all parts applied
|
|
87
|
+
*/
|
|
88
|
+
build(): Theme {
|
|
89
|
+
return {
|
|
90
|
+
name: this.name,
|
|
91
|
+
description: this.description,
|
|
92
|
+
parameters: this.parameters,
|
|
93
|
+
parts: this.parts,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Convert theme to CSS custom properties
|
|
99
|
+
*/
|
|
100
|
+
toCSS(): string {
|
|
101
|
+
const cssVars: string[] = [];
|
|
102
|
+
|
|
103
|
+
// Convert parameters to CSS custom properties
|
|
104
|
+
Object.entries(this.parameters).forEach(([key, value]) => {
|
|
105
|
+
const cssVarName = camelToKebab(key);
|
|
106
|
+
cssVars.push(` --ag-${cssVarName}: ${value};`);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Add parts CSS
|
|
110
|
+
this.parts.forEach((part) => {
|
|
111
|
+
if (part.css) {
|
|
112
|
+
cssVars.push(part.css);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return `:root {\n${cssVars.join('\n')}\n}`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// THEME CREATION FUNCTIONS
|
|
122
|
+
// ============================================================================
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Create a new theme
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const myTheme = createTheme({
|
|
130
|
+
* name: 'my-theme',
|
|
131
|
+
* description: 'My custom theme',
|
|
132
|
+
* parameters: {
|
|
133
|
+
* accentColor: 'blue',
|
|
134
|
+
* spacing: 12,
|
|
135
|
+
* },
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export function createTheme(config: {
|
|
140
|
+
name: string;
|
|
141
|
+
description?: string;
|
|
142
|
+
parameters: ThemeParameters;
|
|
143
|
+
parts?: ThemePart[];
|
|
144
|
+
}): ThemeBuilder {
|
|
145
|
+
return new ThemeBuilderImpl(config);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Create a theme by extending an existing theme
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const myTheme = extendTheme(themeQuartz, {
|
|
154
|
+
* accentColor: 'red',
|
|
155
|
+
* spacing: 12,
|
|
156
|
+
* });
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export function extendTheme(baseTheme: ThemeBuilder, params: PartialThemeParameters): ThemeBuilder {
|
|
160
|
+
return baseTheme.withParams(params);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Merge multiple themes together
|
|
165
|
+
* Later themes override earlier ones
|
|
166
|
+
*/
|
|
167
|
+
export function mergeThemes(...themes: ThemeBuilder[]): ThemeBuilder {
|
|
168
|
+
if (themes.length === 0) {
|
|
169
|
+
throw new Error('At least one theme is required');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const baseTheme = themes[0];
|
|
173
|
+
const mergedParams = { ...baseTheme.parameters };
|
|
174
|
+
const mergedParts = [...baseTheme.parts];
|
|
175
|
+
|
|
176
|
+
for (let i = 1; i < themes.length; i++) {
|
|
177
|
+
const theme = themes[i];
|
|
178
|
+
Object.assign(mergedParams, theme.parameters);
|
|
179
|
+
mergedParts.push(...theme.parts);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return new ThemeBuilderImpl({
|
|
183
|
+
name: 'merged',
|
|
184
|
+
parameters: mergedParams,
|
|
185
|
+
parts: mergedParts,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ============================================================================
|
|
190
|
+
// UTILITIES
|
|
191
|
+
// ============================================================================
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Convert camelCase to kebab-case
|
|
195
|
+
*/
|
|
196
|
+
function camelToKebab(str: string): string {
|
|
197
|
+
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Get CSS variables from theme as a map
|
|
202
|
+
* Returns CSS custom properties that can be applied to an element's style
|
|
203
|
+
*/
|
|
204
|
+
export function getThemeCSSVariables(theme: ThemeBuilder): Record<string, string> {
|
|
205
|
+
const params = theme.parameters;
|
|
206
|
+
const parts = theme.parts;
|
|
207
|
+
|
|
208
|
+
// Collect all parameters from theme and parts
|
|
209
|
+
let allParams = { ...params };
|
|
210
|
+
|
|
211
|
+
// Merge parameters from all parts (later parts override earlier ones)
|
|
212
|
+
for (const part of parts) {
|
|
213
|
+
if (part.params) {
|
|
214
|
+
allParams = { ...allParams, ...part.params };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Map to CSS variables
|
|
219
|
+
return {
|
|
220
|
+
'--ag-background-color': allParams.backgroundColor || allParams.rowBackgroundColor || '#ffffff',
|
|
221
|
+
'--ag-foreground-color': allParams.foregroundColor || '#181d1f',
|
|
222
|
+
'--ag-secondary-foreground-color': allParams.secondaryForegroundColor || '#666666',
|
|
223
|
+
'--ag-header-background-color': allParams.headerBackgroundColor || '#f8f9fa',
|
|
224
|
+
'--ag-header-foreground-color': allParams.foregroundColor || '#181d1f',
|
|
225
|
+
'--ag-odd-row-background-color': allParams.rowEvenBackgroundColor || '#f8f9fa',
|
|
226
|
+
'--ag-row-hover-color':
|
|
227
|
+
allParams.rowHoverBackgroundColor || allParams.cellHoverBackgroundColor || '#f0f2f5',
|
|
228
|
+
'--ag-selected-row-background-color': allParams.rowSelectedBackgroundColor || '#e3f2fd',
|
|
229
|
+
'--ag-border-color': allParams.borderColor || '#babed1',
|
|
230
|
+
'--ag-cell-horizontal-padding': `${String(allParams.cellPadding || allParams.spacing || 8)}px`,
|
|
231
|
+
'--ag-header-height': `${String(allParams.headerHeight || 48)}px`,
|
|
232
|
+
'--ag-row-height': `${String(allParams.rowHeight || 32)}px`,
|
|
233
|
+
'--ag-font-size': `${String(allParams.fontSize || 14)}px`,
|
|
234
|
+
'--ag-font-family':
|
|
235
|
+
allParams.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Apply theme CSS variables to a specific element
|
|
241
|
+
* This updates both the element's inline styles and any CSS that uses these variables
|
|
242
|
+
*/
|
|
243
|
+
export function applyThemeCSSVariables(theme: ThemeBuilder, element: HTMLElement): void {
|
|
244
|
+
const cssVars = getThemeCSSVariables(theme);
|
|
245
|
+
|
|
246
|
+
Object.entries(cssVars).forEach(([key, value]) => {
|
|
247
|
+
element.style.setProperty(key, value);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Apply theme to a container element
|
|
253
|
+
* Injects CSS custom properties
|
|
254
|
+
*/
|
|
255
|
+
export function applyTheme(
|
|
256
|
+
theme: ThemeBuilder,
|
|
257
|
+
container: HTMLElement | ShadowRoot = document.documentElement
|
|
258
|
+
): void {
|
|
259
|
+
const css = theme.toCSS();
|
|
260
|
+
|
|
261
|
+
// Remove existing theme styles
|
|
262
|
+
const existingStyle = container.querySelector('style[data-ag-theme]');
|
|
263
|
+
if (existingStyle) {
|
|
264
|
+
existingStyle.remove();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Create new style element
|
|
268
|
+
const style = document.createElement('style');
|
|
269
|
+
style.setAttribute('data-ag-theme', theme.name);
|
|
270
|
+
style.textContent = css;
|
|
271
|
+
|
|
272
|
+
// Append to container
|
|
273
|
+
container.appendChild(style);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Remove theme from a container element
|
|
278
|
+
*/
|
|
279
|
+
export function removeTheme(
|
|
280
|
+
theme: ThemeBuilder,
|
|
281
|
+
container: HTMLElement | ShadowRoot = document.documentElement
|
|
282
|
+
): void {
|
|
283
|
+
const existingStyle = container.querySelector(`style[data-ag-theme="${theme.name}"]`);
|
|
284
|
+
if (existingStyle) {
|
|
285
|
+
existingStyle.remove();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ============================================================================
|
|
290
|
+
// THEME CONVERTER - Convert ThemeBuilder to Canvas Renderer format
|
|
291
|
+
// ============================================================================
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Convert ThemeBuilder parameters to internal GridTheme format
|
|
295
|
+
* This allows the new Theming API to work with the canvas renderer
|
|
296
|
+
*/
|
|
297
|
+
export function convertThemeToGridTheme(theme: ThemeBuilder): Record<string, any> {
|
|
298
|
+
const params = theme.parameters;
|
|
299
|
+
const parts = theme.parts;
|
|
300
|
+
|
|
301
|
+
// Collect all parameters from theme and parts
|
|
302
|
+
let allParams = { ...params };
|
|
303
|
+
|
|
304
|
+
// Merge parameters from all parts (later parts override earlier ones)
|
|
305
|
+
for (const part of parts) {
|
|
306
|
+
if (part.params) {
|
|
307
|
+
allParams = { ...allParams, ...part.params };
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Map ThemeParameters to internal GridTheme format
|
|
312
|
+
const gridTheme: Record<string, any> = {
|
|
313
|
+
// Background colors
|
|
314
|
+
bgCell: allParams.backgroundColor || allParams.rowBackgroundColor || '#ffffff',
|
|
315
|
+
bgCellEven: allParams.rowEvenBackgroundColor || '#f8f9fa',
|
|
316
|
+
bgHeader: allParams.headerBackgroundColor || '#f8f9fa',
|
|
317
|
+
bgSelection: allParams.rowSelectedBackgroundColor || '#e3f2fd',
|
|
318
|
+
bgHover: allParams.rowHoverBackgroundColor || allParams.cellHoverBackgroundColor || '#f0f2f5',
|
|
319
|
+
bgGroupRow: allParams.groupRowBackgroundColor || '#f5f5f5',
|
|
320
|
+
|
|
321
|
+
// Text colors
|
|
322
|
+
textCell: allParams.foregroundColor || '#181d1f',
|
|
323
|
+
textHeader: allParams.foregroundColor || '#181d1f',
|
|
324
|
+
|
|
325
|
+
// Typography
|
|
326
|
+
fontFamily:
|
|
327
|
+
allParams.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
328
|
+
fontSize: allParams.fontSize || 14,
|
|
329
|
+
fontWeight: allParams.fontWeight || 'normal',
|
|
330
|
+
|
|
331
|
+
// Borders
|
|
332
|
+
borderColor: allParams.borderColor || '#babed1',
|
|
333
|
+
headerBorderColor: allParams.borderColor || '#babed1',
|
|
334
|
+
gridLineColor: allParams.borderColor || '#babed1',
|
|
335
|
+
|
|
336
|
+
// Spacing
|
|
337
|
+
cellPadding: allParams.cellPadding || allParams.spacing || 8,
|
|
338
|
+
headerHeight: allParams.headerHeight || 48,
|
|
339
|
+
rowHeight: allParams.rowHeight || 32,
|
|
340
|
+
|
|
341
|
+
// Group/Tree
|
|
342
|
+
groupIndentWidth: allParams.groupRowIndentWidth || 24,
|
|
343
|
+
groupIndicatorSize: allParams.iconSize || 12,
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
return gridTheme;
|
|
347
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quartz Theme - Modern, high-contrast theme
|
|
3
|
+
* Recommended for most applications
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createTheme } from './theme-builder';
|
|
7
|
+
import type { ThemeParameters } from './types';
|
|
8
|
+
|
|
9
|
+
// Default Quartz theme parameters
|
|
10
|
+
const QUARTZ_DEFAULTS: ThemeParameters = {
|
|
11
|
+
// Colors
|
|
12
|
+
accentColor: '#1976d2',
|
|
13
|
+
backgroundColor: '#ffffff',
|
|
14
|
+
foregroundColor: '#181d1f',
|
|
15
|
+
secondaryForegroundColor: '#666666',
|
|
16
|
+
|
|
17
|
+
// Typography
|
|
18
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
19
|
+
fontSize: 14,
|
|
20
|
+
fontWeight: 400,
|
|
21
|
+
headerFontWeight: 600,
|
|
22
|
+
|
|
23
|
+
// Spacing
|
|
24
|
+
spacing: 8,
|
|
25
|
+
rowHeight: 48,
|
|
26
|
+
headerHeight: 48,
|
|
27
|
+
cellPadding: 12,
|
|
28
|
+
|
|
29
|
+
// Borders
|
|
30
|
+
borderColor: '#dcdcdc',
|
|
31
|
+
borderWidth: 1,
|
|
32
|
+
borderRadius: 0,
|
|
33
|
+
|
|
34
|
+
// Specific colors
|
|
35
|
+
headerBackgroundColor: '#f5f5f5',
|
|
36
|
+
rowBackgroundColor: '#ffffff',
|
|
37
|
+
rowEvenBackgroundColor: '#fafafa',
|
|
38
|
+
rowHoverBackgroundColor: '#f0f0f0',
|
|
39
|
+
rowSelectedBackgroundColor: '#e3f2fd',
|
|
40
|
+
cellHoverBackgroundColor: '#f5f5f5',
|
|
41
|
+
|
|
42
|
+
// Group row
|
|
43
|
+
groupRowBackgroundColor: '#fafafa',
|
|
44
|
+
groupRowIndentWidth: 24,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Quartz theme object
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { themeQuartz } from 'argent-grid';
|
|
53
|
+
*
|
|
54
|
+
* // Basic usage
|
|
55
|
+
* gridOptions.theme = themeQuartz;
|
|
56
|
+
*
|
|
57
|
+
* // Customization
|
|
58
|
+
* const myTheme = themeQuartz.withParams({
|
|
59
|
+
* spacing: 12,
|
|
60
|
+
* accentColor: 'red',
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* // Mix with parts
|
|
64
|
+
* import { colorSchemeDark } from 'argent-grid';
|
|
65
|
+
* const myTheme = themeQuartz.withPart(colorSchemeDark);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export const themeQuartz = createTheme({
|
|
69
|
+
name: 'quartz',
|
|
70
|
+
description: 'Modern, high-contrast theme recommended for most applications',
|
|
71
|
+
parameters: QUARTZ_DEFAULTS,
|
|
72
|
+
});
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme System Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Compatible with AG Grid's Theming API structure
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// THEME PARAMETERS
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Theme configuration parameters
|
|
13
|
+
*
|
|
14
|
+
* All parameters are optional and can be overridden via withParams()
|
|
15
|
+
*/
|
|
16
|
+
export interface ThemeParameters {
|
|
17
|
+
// === Colors ===
|
|
18
|
+
/** Primary accent color for selections, highlights, etc. */
|
|
19
|
+
accentColor?: string;
|
|
20
|
+
/** Main background color */
|
|
21
|
+
backgroundColor?: string;
|
|
22
|
+
/** Main text/foreground color */
|
|
23
|
+
foregroundColor?: string;
|
|
24
|
+
/** Secondary text color (muted text) */
|
|
25
|
+
secondaryForegroundColor?: string;
|
|
26
|
+
|
|
27
|
+
// === Typography ===
|
|
28
|
+
/** Font family stack */
|
|
29
|
+
fontFamily?: string;
|
|
30
|
+
/** Base font size in pixels */
|
|
31
|
+
fontSize?: number;
|
|
32
|
+
/** Base font weight */
|
|
33
|
+
fontWeight?: number | 'normal' | 'bold' | 'lighter' | 'bolder';
|
|
34
|
+
/** Header font weight */
|
|
35
|
+
headerFontWeight?: number | 'normal' | 'bold' | 'lighter' | 'bolder';
|
|
36
|
+
|
|
37
|
+
// === Spacing ===
|
|
38
|
+
/** Base spacing unit in pixels */
|
|
39
|
+
spacing?: number;
|
|
40
|
+
/** Row height in pixels */
|
|
41
|
+
rowHeight?: number;
|
|
42
|
+
/** Header row height in pixels */
|
|
43
|
+
headerHeight?: number;
|
|
44
|
+
/** Cell padding in pixels */
|
|
45
|
+
cellPadding?: number;
|
|
46
|
+
|
|
47
|
+
// === Borders ===
|
|
48
|
+
/** Border color */
|
|
49
|
+
borderColor?: string;
|
|
50
|
+
/** Border width in pixels */
|
|
51
|
+
borderWidth?: number;
|
|
52
|
+
/** Border radius in pixels */
|
|
53
|
+
borderRadius?: number;
|
|
54
|
+
|
|
55
|
+
// === Specific Colors ===
|
|
56
|
+
/** Header background color */
|
|
57
|
+
headerBackgroundColor?: string;
|
|
58
|
+
/** Default row background color */
|
|
59
|
+
rowBackgroundColor?: string;
|
|
60
|
+
/** Even row background color (for striping) */
|
|
61
|
+
rowEvenBackgroundColor?: string;
|
|
62
|
+
/** Row background on hover */
|
|
63
|
+
rowHoverBackgroundColor?: string;
|
|
64
|
+
/** Row background when selected */
|
|
65
|
+
rowSelectedBackgroundColor?: string;
|
|
66
|
+
/** Cell background on hover */
|
|
67
|
+
cellHoverBackgroundColor?: string;
|
|
68
|
+
|
|
69
|
+
// === Group Row ===
|
|
70
|
+
/** Group row background color */
|
|
71
|
+
groupRowBackgroundColor?: string;
|
|
72
|
+
/** Group row indent width in pixels */
|
|
73
|
+
groupRowIndentWidth?: number;
|
|
74
|
+
|
|
75
|
+
// === Icons ===
|
|
76
|
+
/** Icon color */
|
|
77
|
+
iconColor?: string;
|
|
78
|
+
/** Icon size in pixels */
|
|
79
|
+
iconSize?: number;
|
|
80
|
+
|
|
81
|
+
// === Focus ===
|
|
82
|
+
/** Focus border color */
|
|
83
|
+
focusBorderColor?: string;
|
|
84
|
+
/** Focus border width */
|
|
85
|
+
focusBorderWidth?: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Partial theme parameters for overrides
|
|
90
|
+
*/
|
|
91
|
+
export type PartialThemeParameters = Partial<ThemeParameters>;
|
|
92
|
+
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// THEME PARTS
|
|
95
|
+
// ============================================================================
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Theme part type
|
|
99
|
+
* Parts are modular theme components that can be mixed and matched
|
|
100
|
+
*/
|
|
101
|
+
export type ThemePartType =
|
|
102
|
+
| 'color-scheme'
|
|
103
|
+
| 'icon-set'
|
|
104
|
+
| 'checkbox-style'
|
|
105
|
+
| 'input-style'
|
|
106
|
+
| 'tab-style'
|
|
107
|
+
| 'custom';
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Theme part configuration
|
|
111
|
+
*/
|
|
112
|
+
export interface ThemePart {
|
|
113
|
+
/** Part name/identifier */
|
|
114
|
+
name: string;
|
|
115
|
+
/** Part type */
|
|
116
|
+
type: ThemePartType;
|
|
117
|
+
/** CSS rules for this part */
|
|
118
|
+
css?: string;
|
|
119
|
+
/** Additional parameters this part uses */
|
|
120
|
+
additionalParams?: Record<string, any>;
|
|
121
|
+
/** Parameters this part overrides */
|
|
122
|
+
params?: PartialThemeParameters;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ============================================================================
|
|
126
|
+
// THEME OBJECT
|
|
127
|
+
// ============================================================================
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Complete theme object
|
|
131
|
+
*/
|
|
132
|
+
export interface GridThemeObject {
|
|
133
|
+
/** Theme name */
|
|
134
|
+
name: string;
|
|
135
|
+
/** Theme description */
|
|
136
|
+
description?: string;
|
|
137
|
+
/** Theme parameters */
|
|
138
|
+
parameters: ThemeParameters;
|
|
139
|
+
/** Theme parts */
|
|
140
|
+
parts: ThemePart[];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Theme builder interface
|
|
145
|
+
* Used for chainable theme customization
|
|
146
|
+
*/
|
|
147
|
+
export interface ThemeBuilder {
|
|
148
|
+
/** Theme name */
|
|
149
|
+
readonly name: string;
|
|
150
|
+
/** Theme description */
|
|
151
|
+
readonly description?: string;
|
|
152
|
+
/** Theme parameters */
|
|
153
|
+
readonly parameters: ThemeParameters;
|
|
154
|
+
/** Theme parts */
|
|
155
|
+
readonly parts: ThemePart[];
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Create a new theme with overridden parameters
|
|
159
|
+
*/
|
|
160
|
+
withParams(params: PartialThemeParameters): ThemeBuilder;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Add a theme part to the theme
|
|
164
|
+
*/
|
|
165
|
+
withPart(part: ThemePart): ThemeBuilder;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get the final theme object
|
|
169
|
+
*/
|
|
170
|
+
build(): GridThemeObject;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Convert theme to CSS custom properties
|
|
174
|
+
*/
|
|
175
|
+
toCSS(): string;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// COLOR SCHEMES
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Predefined color scheme types
|
|
184
|
+
*/
|
|
185
|
+
export type ColorSchemeType = 'light' | 'dark' | 'auto';
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Color scheme part
|
|
189
|
+
*/
|
|
190
|
+
export interface ColorSchemePart extends ThemePart {
|
|
191
|
+
type: 'color-scheme';
|
|
192
|
+
scheme: ColorSchemeType;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ============================================================================
|
|
196
|
+
// ICON SETS
|
|
197
|
+
// ============================================================================
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Predefined icon set types
|
|
201
|
+
*/
|
|
202
|
+
export type IconSetType = 'quartz' | 'material' | 'minimal' | 'custom';
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Icon definition
|
|
206
|
+
*/
|
|
207
|
+
export interface IconDefinition {
|
|
208
|
+
/** Icon name */
|
|
209
|
+
name: string;
|
|
210
|
+
/** Icon SVG path or URL */
|
|
211
|
+
path: string;
|
|
212
|
+
/** Icon viewBox */
|
|
213
|
+
viewBox?: string;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Icon set part
|
|
218
|
+
*/
|
|
219
|
+
export interface IconSetPart extends ThemePart {
|
|
220
|
+
type: 'icon-set';
|
|
221
|
+
icons: Record<string, IconDefinition>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ============================================================================
|
|
225
|
+
// GRID OPTIONS INTEGRATION
|
|
226
|
+
// ============================================================================
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Grid options theme configuration
|
|
230
|
+
*/
|
|
231
|
+
export interface ThemeGridOptions {
|
|
232
|
+
/** Theme object */
|
|
233
|
+
theme?: ThemeBuilder;
|
|
234
|
+
/** CSS layer name for theme styles */
|
|
235
|
+
themeCssLayer?: string;
|
|
236
|
+
/** Container element for theme styles */
|
|
237
|
+
themeStyleContainer?: HTMLElement | ShadowRoot | (() => HTMLElement | ShadowRoot);
|
|
238
|
+
}
|