@gravionlabs/helix-ag-grid 22.0.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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GravionLabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # @gravionlabs/helix-ag-grid
2
+
3
+ AG Grid helpers for Helix applications: locale-aware value formatters, robust
4
+ number parsing for editable cells, and shared cell styles.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ npm install @gravionlabs/helix-ag-grid
10
+ ```
11
+
12
+ Peer dependencies: `@angular/core >=22`, `ag-grid-angular >=33`, `ag-grid-community >=33`.
13
+
14
+ The package ships a prebuilt stylesheet; add it to your global styles:
15
+
16
+ ```json
17
+ // angular.json
18
+ "styles": ["node_modules/@gravionlabs/helix-ag-grid/styles.css", "src/styles.scss"]
19
+ ```
20
+
21
+ ## Formatters
22
+
23
+ `Intl`-based value formatters for column definitions:
24
+
25
+ | Export | Formats |
26
+ | --- | --- |
27
+ | `numberFormatter` / `rawNumberFormatter` / `intlNumberFormatter` | Numbers (grouped, raw, or custom `Intl.NumberFormat` options) |
28
+ | `currencyFormatter` | Currency values |
29
+ | `cetDateFormatter` / `cetTimeFormatter` / `cetDateTimeFormatter` | Dates/times in CET |
30
+
31
+ ```ts
32
+ import { currencyFormatter } from '@gravionlabs/helix-ag-grid';
33
+
34
+ const columnDefs: ColDef[] = [
35
+ { field: 'price', valueFormatter: currencyFormatter('EUR') },
36
+ ];
37
+ ```
38
+
39
+ See `AgGridFormatterParams` for the accepted parameter shape.
40
+
41
+ ## Parsers
42
+
43
+ Number parsing for cell editing:
44
+
45
+ - `parseNumber(value, options?)` / `parseNumberValue` — parse localized number strings (`ParseNumberOptions` controls locale/precision behavior).
46
+ - `numberValueParser` — drop-in `valueParser` for numeric columns.
47
+ - `coerceValue` — general value coercion helper.
48
+
49
+ ## Cell Styles
50
+
51
+ - `numberCellStyle` — right-aligned tabular style for numeric columns.
52
+
53
+ ## Development
54
+
55
+ ```bash
56
+ ng build ag-grid
57
+ ng test ag-grid
58
+ ```
59
+
60
+ ## License
61
+
62
+ MIT
@@ -0,0 +1,249 @@
1
+ /**
2
+ * AG Grid `cellStyle` callback that right-aligns numeric cells and colours
3
+ * truthy (non-zero, non-null, non-undefined) values with the helix success
4
+ * colour (`--h-green-500`).
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * columnDefs = [{ field: 'amount', cellStyle: numberCellStyle }];
9
+ * ```
10
+ */
11
+ function numberCellStyle(params) {
12
+ return params.value
13
+ ? { textAlign: 'right', color: 'var(--h-green-500)' }
14
+ : { textAlign: 'right' };
15
+ }
16
+
17
+ // ── Number formatters ──────────────────────────────────────────────────────
18
+ /**
19
+ * Formats a numeric cell value using the system locale (`toLocaleString`).
20
+ * Returns `''` for `null`, `undefined`, or `NaN`.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * { field: 'amount', valueFormatter: numberFormatter }
25
+ * ```
26
+ */
27
+ function numberFormatter(params) {
28
+ const v = params.value;
29
+ if (v == null || Number.isNaN(v))
30
+ return '';
31
+ return v.toLocaleString();
32
+ }
33
+ /**
34
+ * Returns the raw string representation of a number without any locale
35
+ * formatting. Returns `''` for `null` or `undefined`.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * { field: 'id', valueFormatter: rawNumberFormatter }
40
+ * ```
41
+ */
42
+ function rawNumberFormatter(params) {
43
+ const v = params.value;
44
+ if (v == null)
45
+ return '';
46
+ return v.toString();
47
+ }
48
+ /**
49
+ * Formats a number using a caller-supplied `Intl.NumberFormat` instance,
50
+ * allowing full control over locale, currency, fraction digits, etc.
51
+ * Returns `''` for `null` or `undefined`.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const fmt = new Intl.NumberFormat('de-DE', { minimumFractionDigits: 2 });
56
+ * { field: 'price', valueFormatter: (p) => intlNumberFormatter(p, fmt) }
57
+ * ```
58
+ */
59
+ function intlNumberFormatter(params, numberFormat) {
60
+ const v = params.value;
61
+ if (v == null || Number.isNaN(v))
62
+ return '';
63
+ return numberFormat.format(v);
64
+ }
65
+ /**
66
+ * Factory that returns a currency formatter closure using `Intl.NumberFormat`
67
+ * with `style: 'currency'`. Defaults to EUR / de-DE.
68
+ * Returns `''` for `null`, `undefined`, or `NaN`.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * { field: 'revenue', valueFormatter: currencyFormatter() } // '1.234,50 €'
73
+ * { field: 'price', valueFormatter: currencyFormatter('USD','en-US') } // '$99.90'
74
+ * ```
75
+ */
76
+ function currencyFormatter(currencyCode = 'EUR', locale = 'de-DE') {
77
+ const fmt = new Intl.NumberFormat(locale, { style: 'currency', currency: currencyCode });
78
+ return (params) => {
79
+ const v = params.value;
80
+ if (v == null || Number.isNaN(v))
81
+ return '';
82
+ return fmt.format(v);
83
+ };
84
+ }
85
+ function toDate(value) {
86
+ if (value == null)
87
+ return null;
88
+ const d = value instanceof Date ? value : new Date(value);
89
+ return Number.isNaN(d.getTime()) ? null : d;
90
+ }
91
+ const cetDateFormat = new Intl.DateTimeFormat('de-DE', {
92
+ timeZone: 'Europe/Berlin',
93
+ day: '2-digit',
94
+ month: '2-digit',
95
+ year: 'numeric',
96
+ });
97
+ const cetDateTimeFormat = new Intl.DateTimeFormat('de-DE', {
98
+ timeZone: 'Europe/Berlin',
99
+ day: '2-digit',
100
+ month: '2-digit',
101
+ year: 'numeric',
102
+ hour: '2-digit',
103
+ minute: '2-digit',
104
+ second: '2-digit',
105
+ hour12: false,
106
+ });
107
+ const cetTimeFormat = new Intl.DateTimeFormat('de-DE', {
108
+ timeZone: 'Europe/Berlin',
109
+ hour: '2-digit',
110
+ minute: '2-digit',
111
+ hour12: false,
112
+ });
113
+ /**
114
+ * Formats a `Date` or ISO string as a CET date: `'15.06.2024'`.
115
+ * Returns `''` for `null`, `undefined`, or invalid dates.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * { field: 'date', valueFormatter: cetDateFormatter }
120
+ * ```
121
+ */
122
+ function cetDateFormatter(params) {
123
+ const d = toDate(params.value);
124
+ return d ? cetDateFormat.format(d) : '';
125
+ }
126
+ /**
127
+ * Formats a `Date` or ISO string as a CET date-time: `'15.06.2024 12:30:00'`.
128
+ * Returns `''` for `null`, `undefined`, or invalid dates.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * { field: 'updatedAt', valueFormatter: cetDateTimeFormatter }
133
+ * ```
134
+ */
135
+ function cetDateTimeFormatter(params) {
136
+ const d = toDate(params.value);
137
+ if (!d)
138
+ return '';
139
+ // Intl formats date and time parts separated by ', ' in de-DE — replace with ' '
140
+ return cetDateTimeFormat.format(d).replace(', ', ' ');
141
+ }
142
+ /**
143
+ * Formats a `Date` or ISO string as a CET time: `'12:30'`.
144
+ * Returns `''` for `null`, `undefined`, or invalid dates.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * { field: 'startTime', valueFormatter: cetTimeFormatter }
149
+ * ```
150
+ */
151
+ function cetTimeFormatter(params) {
152
+ const d = toDate(params.value);
153
+ return d ? cetTimeFormat.format(d) : '';
154
+ }
155
+
156
+ /**
157
+ * Validates a number against optional `min`/`max` bounds.
158
+ * Returns `null` if the value is `null`, `undefined`, `NaN`, or out of bounds.
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * coerceValue(5, { min: 0, max: 10 }) // → 5
163
+ * coerceValue(15, { max: 10 }) // → null
164
+ * coerceValue(null) // → null
165
+ * ```
166
+ */
167
+ function coerceValue(value, options) {
168
+ if (value == null || Number.isNaN(value))
169
+ return null;
170
+ if (options?.min != null && value < options.min)
171
+ return null;
172
+ if (options?.max != null && value > options.max)
173
+ return null;
174
+ return value;
175
+ }
176
+ /**
177
+ * Locale-aware string-to-number parser.
178
+ * Handles thousand separators and decimal commas for the given locale.
179
+ * Returns `null` for empty, `null`, or `undefined` input.
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * parseNumber('1.234,56', 'de-DE') // → 1234.56
184
+ * parseNumber('1,234.56', 'en-US') // → 1234.56
185
+ * ```
186
+ */
187
+ function parseNumber(value, locale, options) {
188
+ if (value == null || value.trim() === '')
189
+ return null;
190
+ // Derive separators from the locale
191
+ const parts = new Intl.NumberFormat(locale).formatToParts(1234.5);
192
+ const group = parts.find((p) => p.type === 'group')?.value ?? '';
193
+ const decimal = parts.find((p) => p.type === 'decimal')?.value ?? '.';
194
+ const normalised = value.trim().replaceAll(group, '').replace(decimal, '.');
195
+ const n = Number.parseFloat(normalised);
196
+ return coerceValue(n, options);
197
+ }
198
+ /**
199
+ * Smart string-to-number parser that detects the decimal separator
200
+ * automatically:
201
+ * - Strings containing a comma (e.g. `'1.234,56'` from spreadsheet paste)
202
+ * are parsed as German locale (`de-DE`).
203
+ * - All other strings (e.g. `'3.14'` from keyboard input) are parsed with
204
+ * `parseFloat`.
205
+ *
206
+ * Returns `null` for empty, `null`, or `undefined` input.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * parseNumberValue('42') // → 42
211
+ * parseNumberValue('3.14') // → 3.14
212
+ * parseNumberValue('1.234,56') // → 1234.56 (German paste)
213
+ * parseNumberValue(null) // → null
214
+ * parseNumberValue('5', { min: 10 }) // → null (out of bounds)
215
+ * ```
216
+ */
217
+ function parseNumberValue(value, options) {
218
+ if (value == null || value.trim() === '')
219
+ return null;
220
+ const hasComma = value.includes(',');
221
+ if (hasComma) {
222
+ return parseNumber(value, 'de-DE', options);
223
+ }
224
+ const n = Number.parseFloat(value.trim());
225
+ return coerceValue(n, options);
226
+ }
227
+ /**
228
+ * AG Grid `valueParser` adapter — wraps `parseNumberValue` to read
229
+ * `params.newValue`. Drop-in for any editable numeric column.
230
+ *
231
+ * @example
232
+ * ```ts
233
+ * { field: 'quantity', editable: true, valueParser: numberValueParser }
234
+ * // or with bounds:
235
+ * { field: 'pct', editable: true, valueParser: (p) => numberValueParser(p, { min: 0, max: 100 }) }
236
+ * ```
237
+ */
238
+ function numberValueParser(params, options) {
239
+ return parseNumberValue(params.newValue, options);
240
+ }
241
+
242
+ const HELIX_AG_GRID_VERSION = '0.1.0';
243
+
244
+ /**
245
+ * Generated bundle index. Do not edit.
246
+ */
247
+
248
+ export { HELIX_AG_GRID_VERSION, cetDateFormatter, cetDateTimeFormatter, cetTimeFormatter, coerceValue, currencyFormatter, intlNumberFormatter, numberCellStyle, numberFormatter, numberValueParser, parseNumber, parseNumberValue, rawNumberFormatter };
249
+ //# sourceMappingURL=gravionlabs-helix-ag-grid.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gravionlabs-helix-ag-grid.mjs","sources":["../../../projects/ag-grid/src/lib/cell-styles/cell-styles.ts","../../../projects/ag-grid/src/lib/formatters/ag-grid-formatters.ts","../../../projects/ag-grid/src/lib/parsers/number-parsers.ts","../../../projects/ag-grid/src/public-api.ts","../../../projects/ag-grid/src/gravionlabs-helix-ag-grid.ts"],"sourcesContent":["import type { CellClassParams, CellStyle } from 'ag-grid-community';\n\n/**\n * AG Grid `cellStyle` callback that right-aligns numeric cells and colours\n * truthy (non-zero, non-null, non-undefined) values with the helix success\n * colour (`--h-green-500`).\n *\n * @example\n * ```ts\n * columnDefs = [{ field: 'amount', cellStyle: numberCellStyle }];\n * ```\n */\nexport function numberCellStyle(params: CellClassParams): CellStyle {\n return params.value\n ? { textAlign: 'right', color: 'var(--h-green-500)' }\n : { textAlign: 'right' };\n}\n","import type { ValueFormatterParams } from 'ag-grid-community';\n\n/** Type alias for AG Grid's `ValueFormatterParams`, used by all formatter functions. */\nexport type AgGridFormatterParams<TData = unknown, TValue = unknown> = ValueFormatterParams<\n TData,\n TValue\n>;\n\n// ── Number formatters ──────────────────────────────────────────────────────\n\n/**\n * Formats a numeric cell value using the system locale (`toLocaleString`).\n * Returns `''` for `null`, `undefined`, or `NaN`.\n *\n * @example\n * ```ts\n * { field: 'amount', valueFormatter: numberFormatter }\n * ```\n */\nexport function numberFormatter(\n params: AgGridFormatterParams<unknown, number | null | undefined>,\n): string {\n const v = params.value;\n if (v == null || Number.isNaN(v)) return '';\n return v.toLocaleString();\n}\n\n/**\n * Returns the raw string representation of a number without any locale\n * formatting. Returns `''` for `null` or `undefined`.\n *\n * @example\n * ```ts\n * { field: 'id', valueFormatter: rawNumberFormatter }\n * ```\n */\nexport function rawNumberFormatter(\n params: AgGridFormatterParams<unknown, number | null | undefined>,\n): string {\n const v = params.value;\n if (v == null) return '';\n return v.toString();\n}\n\n/**\n * Formats a number using a caller-supplied `Intl.NumberFormat` instance,\n * allowing full control over locale, currency, fraction digits, etc.\n * Returns `''` for `null` or `undefined`.\n *\n * @example\n * ```ts\n * const fmt = new Intl.NumberFormat('de-DE', { minimumFractionDigits: 2 });\n * { field: 'price', valueFormatter: (p) => intlNumberFormatter(p, fmt) }\n * ```\n */\nexport function intlNumberFormatter(\n params: AgGridFormatterParams<unknown, number | null | undefined>,\n numberFormat: Intl.NumberFormat,\n): string {\n const v = params.value;\n if (v == null || Number.isNaN(v)) return '';\n return numberFormat.format(v);\n}\n\n/**\n * Factory that returns a currency formatter closure using `Intl.NumberFormat`\n * with `style: 'currency'`. Defaults to EUR / de-DE.\n * Returns `''` for `null`, `undefined`, or `NaN`.\n *\n * @example\n * ```ts\n * { field: 'revenue', valueFormatter: currencyFormatter() } // '1.234,50 €'\n * { field: 'price', valueFormatter: currencyFormatter('USD','en-US') } // '$99.90'\n * ```\n */\nexport function currencyFormatter(\n currencyCode = 'EUR',\n locale = 'de-DE',\n): (params: AgGridFormatterParams<unknown, number | null | undefined>) => string {\n const fmt = new Intl.NumberFormat(locale, { style: 'currency', currency: currencyCode });\n return (params) => {\n const v = params.value;\n if (v == null || Number.isNaN(v)) return '';\n return fmt.format(v);\n };\n}\n\n// ── CET date formatters ────────────────────────────────────────────────────\n\ntype DateInput = Date | string | null | undefined;\n\nfunction toDate(value: DateInput): Date | null {\n if (value == null) return null;\n const d = value instanceof Date ? value : new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\nconst cetDateFormat = new Intl.DateTimeFormat('de-DE', {\n timeZone: 'Europe/Berlin',\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n});\n\nconst cetDateTimeFormat = new Intl.DateTimeFormat('de-DE', {\n timeZone: 'Europe/Berlin',\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n});\n\nconst cetTimeFormat = new Intl.DateTimeFormat('de-DE', {\n timeZone: 'Europe/Berlin',\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n});\n\n/**\n * Formats a `Date` or ISO string as a CET date: `'15.06.2024'`.\n * Returns `''` for `null`, `undefined`, or invalid dates.\n *\n * @example\n * ```ts\n * { field: 'date', valueFormatter: cetDateFormatter }\n * ```\n */\nexport function cetDateFormatter(params: AgGridFormatterParams<unknown, DateInput>): string {\n const d = toDate(params.value);\n return d ? cetDateFormat.format(d) : '';\n}\n\n/**\n * Formats a `Date` or ISO string as a CET date-time: `'15.06.2024 12:30:00'`.\n * Returns `''` for `null`, `undefined`, or invalid dates.\n *\n * @example\n * ```ts\n * { field: 'updatedAt', valueFormatter: cetDateTimeFormatter }\n * ```\n */\nexport function cetDateTimeFormatter(params: AgGridFormatterParams<unknown, DateInput>): string {\n const d = toDate(params.value);\n if (!d) return '';\n // Intl formats date and time parts separated by ', ' in de-DE — replace with ' '\n return cetDateTimeFormat.format(d).replace(', ', ' ');\n}\n\n/**\n * Formats a `Date` or ISO string as a CET time: `'12:30'`.\n * Returns `''` for `null`, `undefined`, or invalid dates.\n *\n * @example\n * ```ts\n * { field: 'startTime', valueFormatter: cetTimeFormatter }\n * ```\n */\nexport function cetTimeFormatter(params: AgGridFormatterParams<unknown, DateInput>): string {\n const d = toDate(params.value);\n return d ? cetTimeFormat.format(d) : '';\n}\n","import type { ValueParserParams } from 'ag-grid-community';\n\n/** Bounds for number validation. */\nexport interface ParseNumberOptions {\n min?: number;\n max?: number;\n}\n\n/**\n * Validates a number against optional `min`/`max` bounds.\n * Returns `null` if the value is `null`, `undefined`, `NaN`, or out of bounds.\n *\n * @example\n * ```ts\n * coerceValue(5, { min: 0, max: 10 }) // → 5\n * coerceValue(15, { max: 10 }) // → null\n * coerceValue(null) // → null\n * ```\n */\nexport function coerceValue(\n value: number | null | undefined,\n options?: ParseNumberOptions,\n): number | null {\n if (value == null || Number.isNaN(value)) return null;\n if (options?.min != null && value < options.min) return null;\n if (options?.max != null && value > options.max) return null;\n return value;\n}\n\n/**\n * Locale-aware string-to-number parser.\n * Handles thousand separators and decimal commas for the given locale.\n * Returns `null` for empty, `null`, or `undefined` input.\n *\n * @example\n * ```ts\n * parseNumber('1.234,56', 'de-DE') // → 1234.56\n * parseNumber('1,234.56', 'en-US') // → 1234.56\n * ```\n */\nexport function parseNumber(\n value: string | null | undefined,\n locale: string,\n options?: ParseNumberOptions,\n): number | null {\n if (value == null || value.trim() === '') return null;\n\n // Derive separators from the locale\n const parts = new Intl.NumberFormat(locale).formatToParts(1234.5);\n const group = parts.find((p) => p.type === 'group')?.value ?? '';\n const decimal = parts.find((p) => p.type === 'decimal')?.value ?? '.';\n\n const normalised = value.trim().replaceAll(group, '').replace(decimal, '.');\n\n const n = Number.parseFloat(normalised);\n return coerceValue(n, options);\n}\n\n/**\n * Smart string-to-number parser that detects the decimal separator\n * automatically:\n * - Strings containing a comma (e.g. `'1.234,56'` from spreadsheet paste)\n * are parsed as German locale (`de-DE`).\n * - All other strings (e.g. `'3.14'` from keyboard input) are parsed with\n * `parseFloat`.\n *\n * Returns `null` for empty, `null`, or `undefined` input.\n *\n * @example\n * ```ts\n * parseNumberValue('42') // → 42\n * parseNumberValue('3.14') // → 3.14\n * parseNumberValue('1.234,56') // → 1234.56 (German paste)\n * parseNumberValue(null) // → null\n * parseNumberValue('5', { min: 10 }) // → null (out of bounds)\n * ```\n */\nexport function parseNumberValue(\n value: string | null | undefined,\n options?: ParseNumberOptions,\n): number | null {\n if (value == null || value.trim() === '') return null;\n\n const hasComma = value.includes(',');\n if (hasComma) {\n return parseNumber(value, 'de-DE', options);\n }\n\n const n = Number.parseFloat(value.trim());\n return coerceValue(n, options);\n}\n\n/**\n * AG Grid `valueParser` adapter — wraps `parseNumberValue` to read\n * `params.newValue`. Drop-in for any editable numeric column.\n *\n * @example\n * ```ts\n * { field: 'quantity', editable: true, valueParser: numberValueParser }\n * // or with bounds:\n * { field: 'pct', editable: true, valueParser: (p) => numberValueParser(p, { min: 0, max: 100 }) }\n * ```\n */\nexport function numberValueParser(\n params: ValueParserParams,\n options?: ParseNumberOptions,\n): number | null {\n return parseNumberValue(params.newValue as string | null | undefined, options);\n}\n","export const HELIX_AG_GRID_VERSION = '0.1.0';\n\nexport { numberCellStyle } from './lib/cell-styles/cell-styles';\n\nexport type { AgGridFormatterParams } from './lib/formatters/ag-grid-formatters';\nexport {\n cetDateFormatter,\n cetDateTimeFormatter,\n cetTimeFormatter,\n currencyFormatter,\n intlNumberFormatter,\n numberFormatter,\n rawNumberFormatter,\n} from './lib/formatters/ag-grid-formatters';\n\nexport type { ParseNumberOptions } from './lib/parsers/number-parsers';\nexport {\n coerceValue,\n numberValueParser,\n parseNumber,\n parseNumberValue,\n} from './lib/parsers/number-parsers';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@gravionlabs/helix-ag-grid",
3
+ "version": "22.0.0",
4
+ "description": "Helix AG Grid helpers for Angular — value formatters, number parsers, and cell styles.",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "helix",
8
+ "angular",
9
+ "ag-grid"
10
+ ],
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/GravionLabs/helix.git",
14
+ "directory": "projects/ag-grid"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "peerDependencies": {
20
+ "@angular/core": ">=22",
21
+ "ag-grid-angular": ">=33",
22
+ "ag-grid-community": ">=33"
23
+ },
24
+ "dependencies": {
25
+ "tslib": "^2.3.0"
26
+ },
27
+ "sideEffects": [
28
+ "**/*.css"
29
+ ],
30
+ "module": "fesm2022/gravionlabs-helix-ag-grid.mjs",
31
+ "typings": "types/gravionlabs-helix-ag-grid.d.ts",
32
+ "exports": {
33
+ "./package.json": {
34
+ "default": "./package.json"
35
+ },
36
+ ".": {
37
+ "types": "./types/gravionlabs-helix-ag-grid.d.ts",
38
+ "default": "./fesm2022/gravionlabs-helix-ag-grid.mjs"
39
+ },
40
+ "./styles.css": "./styles.css"
41
+ },
42
+ "type": "module"
43
+ }
package/styles.css ADDED
@@ -0,0 +1,81 @@
1
+ /*
2
+ * AG Grid Theme — Helix
3
+ *
4
+ * Apply the `.helix-ag-grid` class to the ag-grid host element to get a
5
+ * look and feel consistent with the Helix / PrimeNG design system.
6
+ *
7
+ * Token reference:
8
+ * --helix-* design tokens defined in @gravionlabs/helix styles.css
9
+ * --p-* PrimeNG Aura tokens injected at runtime by ThemeService
10
+ *
11
+ * Approach: https://www.ag-grid.com/javascript-data-grid/theming-css/#overriding-theme-parameters-with-custom-properties
12
+ */
13
+
14
+ .helix-ag-grid {
15
+ /* ── Colours ──────────────────────────────────────────────────────────── */
16
+ --ag-background-color: var(--helix-surface-card);
17
+ --ag-foreground-color: var(--h-text-color);
18
+ --ag-text-color: var(--ag-foreground-color);
19
+ --ag-accent-color: var(--h-primary-color);
20
+ --ag-invalid-color: var(--h-form-field-invalid-border-color);
21
+ --ag-border-color: var(--helix-border);
22
+ --ag-wrapper-border: none;
23
+ --ag-row-border: solid 1px var(--helix-border);
24
+ --ag-odd-row-background-color: color-mix(
25
+ in srgb,
26
+ transparent,
27
+ var(--helix-border) 10%
28
+ );
29
+ --ag-row-hover-color: var(--helix-surface-hover);
30
+
31
+ /* ── Typography ───────────────────────────────────────────────────────── */
32
+ --ag-font-family: "Lato", sans-serif;
33
+ --ag-font-size: 0.75rem;
34
+
35
+ /* ── Header ───────────────────────────────────────────────────────────── */
36
+ --ag-header-background-color: var(--helix-surface-card);
37
+ --ag-header-font-family: "Lato", sans-serif;
38
+ --ag-header-font-weight: 500;
39
+ --ag-header-font-size: 0.75rem;
40
+ --ag-header-text-color: var(--h-primary-color);
41
+
42
+ /* ── Cells ────────────────────────────────────────────────────────────── */
43
+ --ag-cell-text-color: var(--h-text-color);
44
+ --ag-cell-horizontal-padding: 1ch;
45
+
46
+ /* ── Input ────────────────────────────────────────────────────────────── */
47
+ --ag-input-background-color: var(--ag-background-color);
48
+ --ag-input-border: solid 1px var(--ag-border-color);
49
+
50
+ /* ── Drag & drop ──────────────────────────────────────────────────────── */
51
+ --ag-column-drop-cell-background-color: color-mix(
52
+ in srgb,
53
+ transparent,
54
+ var(--ag-foreground-color) 7%
55
+ );
56
+ --ag-column-drop-cell-border: solid 1px
57
+ color-mix(in srgb, transparent, var(--ag-foreground-color) 13%);
58
+
59
+ /* ── Inner element overrides ──────────────────────────────────────────── */
60
+ .ag-root-wrapper,
61
+ .ag-measurement-container,
62
+ .ag-apply-theme-variables {
63
+ --ag-row-height: 2rem;
64
+ }
65
+
66
+ .ag-cell {
67
+ line-height: 1.85rem;
68
+ -webkit-font-smoothing: antialiased;
69
+ }
70
+
71
+ .ag-dnd-ghost {
72
+ font-family: "Lato", sans-serif;
73
+ font-size: 0.75rem;
74
+ font-weight: 500;
75
+ color: var(--h-primary-color);
76
+ }
77
+
78
+ .ag-paging-panel {
79
+ block-size: 3em;
80
+ }
81
+ }
@@ -0,0 +1,158 @@
1
+ import { CellClassParams, CellStyle, ValueFormatterParams, ValueParserParams } from 'ag-grid-community';
2
+
3
+ /**
4
+ * AG Grid `cellStyle` callback that right-aligns numeric cells and colours
5
+ * truthy (non-zero, non-null, non-undefined) values with the helix success
6
+ * colour (`--h-green-500`).
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * columnDefs = [{ field: 'amount', cellStyle: numberCellStyle }];
11
+ * ```
12
+ */
13
+ declare function numberCellStyle(params: CellClassParams): CellStyle;
14
+
15
+ /** Type alias for AG Grid's `ValueFormatterParams`, used by all formatter functions. */
16
+ type AgGridFormatterParams<TData = unknown, TValue = unknown> = ValueFormatterParams<TData, TValue>;
17
+ /**
18
+ * Formats a numeric cell value using the system locale (`toLocaleString`).
19
+ * Returns `''` for `null`, `undefined`, or `NaN`.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * { field: 'amount', valueFormatter: numberFormatter }
24
+ * ```
25
+ */
26
+ declare function numberFormatter(params: AgGridFormatterParams<unknown, number | null | undefined>): string;
27
+ /**
28
+ * Returns the raw string representation of a number without any locale
29
+ * formatting. Returns `''` for `null` or `undefined`.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * { field: 'id', valueFormatter: rawNumberFormatter }
34
+ * ```
35
+ */
36
+ declare function rawNumberFormatter(params: AgGridFormatterParams<unknown, number | null | undefined>): string;
37
+ /**
38
+ * Formats a number using a caller-supplied `Intl.NumberFormat` instance,
39
+ * allowing full control over locale, currency, fraction digits, etc.
40
+ * Returns `''` for `null` or `undefined`.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * const fmt = new Intl.NumberFormat('de-DE', { minimumFractionDigits: 2 });
45
+ * { field: 'price', valueFormatter: (p) => intlNumberFormatter(p, fmt) }
46
+ * ```
47
+ */
48
+ declare function intlNumberFormatter(params: AgGridFormatterParams<unknown, number | null | undefined>, numberFormat: Intl.NumberFormat): string;
49
+ /**
50
+ * Factory that returns a currency formatter closure using `Intl.NumberFormat`
51
+ * with `style: 'currency'`. Defaults to EUR / de-DE.
52
+ * Returns `''` for `null`, `undefined`, or `NaN`.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * { field: 'revenue', valueFormatter: currencyFormatter() } // '1.234,50 €'
57
+ * { field: 'price', valueFormatter: currencyFormatter('USD','en-US') } // '$99.90'
58
+ * ```
59
+ */
60
+ declare function currencyFormatter(currencyCode?: string, locale?: string): (params: AgGridFormatterParams<unknown, number | null | undefined>) => string;
61
+ type DateInput = Date | string | null | undefined;
62
+ /**
63
+ * Formats a `Date` or ISO string as a CET date: `'15.06.2024'`.
64
+ * Returns `''` for `null`, `undefined`, or invalid dates.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * { field: 'date', valueFormatter: cetDateFormatter }
69
+ * ```
70
+ */
71
+ declare function cetDateFormatter(params: AgGridFormatterParams<unknown, DateInput>): string;
72
+ /**
73
+ * Formats a `Date` or ISO string as a CET date-time: `'15.06.2024 12:30:00'`.
74
+ * Returns `''` for `null`, `undefined`, or invalid dates.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * { field: 'updatedAt', valueFormatter: cetDateTimeFormatter }
79
+ * ```
80
+ */
81
+ declare function cetDateTimeFormatter(params: AgGridFormatterParams<unknown, DateInput>): string;
82
+ /**
83
+ * Formats a `Date` or ISO string as a CET time: `'12:30'`.
84
+ * Returns `''` for `null`, `undefined`, or invalid dates.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * { field: 'startTime', valueFormatter: cetTimeFormatter }
89
+ * ```
90
+ */
91
+ declare function cetTimeFormatter(params: AgGridFormatterParams<unknown, DateInput>): string;
92
+
93
+ /** Bounds for number validation. */
94
+ interface ParseNumberOptions {
95
+ min?: number;
96
+ max?: number;
97
+ }
98
+ /**
99
+ * Validates a number against optional `min`/`max` bounds.
100
+ * Returns `null` if the value is `null`, `undefined`, `NaN`, or out of bounds.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * coerceValue(5, { min: 0, max: 10 }) // → 5
105
+ * coerceValue(15, { max: 10 }) // → null
106
+ * coerceValue(null) // → null
107
+ * ```
108
+ */
109
+ declare function coerceValue(value: number | null | undefined, options?: ParseNumberOptions): number | null;
110
+ /**
111
+ * Locale-aware string-to-number parser.
112
+ * Handles thousand separators and decimal commas for the given locale.
113
+ * Returns `null` for empty, `null`, or `undefined` input.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * parseNumber('1.234,56', 'de-DE') // → 1234.56
118
+ * parseNumber('1,234.56', 'en-US') // → 1234.56
119
+ * ```
120
+ */
121
+ declare function parseNumber(value: string | null | undefined, locale: string, options?: ParseNumberOptions): number | null;
122
+ /**
123
+ * Smart string-to-number parser that detects the decimal separator
124
+ * automatically:
125
+ * - Strings containing a comma (e.g. `'1.234,56'` from spreadsheet paste)
126
+ * are parsed as German locale (`de-DE`).
127
+ * - All other strings (e.g. `'3.14'` from keyboard input) are parsed with
128
+ * `parseFloat`.
129
+ *
130
+ * Returns `null` for empty, `null`, or `undefined` input.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * parseNumberValue('42') // → 42
135
+ * parseNumberValue('3.14') // → 3.14
136
+ * parseNumberValue('1.234,56') // → 1234.56 (German paste)
137
+ * parseNumberValue(null) // → null
138
+ * parseNumberValue('5', { min: 10 }) // → null (out of bounds)
139
+ * ```
140
+ */
141
+ declare function parseNumberValue(value: string | null | undefined, options?: ParseNumberOptions): number | null;
142
+ /**
143
+ * AG Grid `valueParser` adapter — wraps `parseNumberValue` to read
144
+ * `params.newValue`. Drop-in for any editable numeric column.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * { field: 'quantity', editable: true, valueParser: numberValueParser }
149
+ * // or with bounds:
150
+ * { field: 'pct', editable: true, valueParser: (p) => numberValueParser(p, { min: 0, max: 100 }) }
151
+ * ```
152
+ */
153
+ declare function numberValueParser(params: ValueParserParams, options?: ParseNumberOptions): number | null;
154
+
155
+ declare const HELIX_AG_GRID_VERSION = "0.1.0";
156
+
157
+ export { HELIX_AG_GRID_VERSION, cetDateFormatter, cetDateTimeFormatter, cetTimeFormatter, coerceValue, currencyFormatter, intlNumberFormatter, numberCellStyle, numberFormatter, numberValueParser, parseNumber, parseNumberValue, rawNumberFormatter };
158
+ export type { AgGridFormatterParams, ParseNumberOptions };