@genesislcap/grid-tabulator 14.281.2 → 14.282.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.
Files changed (38) hide show
  1. package/dist/custom-elements.json +57 -7
  2. package/dist/dts/cell-formatters/action.formatter.d.ts +5 -5
  3. package/dist/dts/cell-formatters/action.formatter.d.ts.map +1 -1
  4. package/dist/dts/cell-formatters/actions-menu.formatter.d.ts +10 -7
  5. package/dist/dts/cell-formatters/actions-menu.formatter.d.ts.map +1 -1
  6. package/dist/dts/cell-formatters/boolean.formatter.d.ts +4 -4
  7. package/dist/dts/cell-formatters/boolean.formatter.d.ts.map +1 -1
  8. package/dist/dts/cell-formatters/editable.formatter.d.ts +4 -4
  9. package/dist/dts/cell-formatters/editable.formatter.d.ts.map +1 -1
  10. package/dist/dts/cell-formatters/select.formatter.d.ts +14 -8
  11. package/dist/dts/cell-formatters/select.formatter.d.ts.map +1 -1
  12. package/dist/dts/cell-formatters/text.formatter.d.ts +3 -3
  13. package/dist/dts/cell-formatters/text.formatter.d.ts.map +1 -1
  14. package/dist/dts/types.d.ts +1 -0
  15. package/dist/dts/types.d.ts.map +1 -1
  16. package/dist/dts/utils/index.d.ts +1 -0
  17. package/dist/dts/utils/index.d.ts.map +1 -1
  18. package/dist/dts/utils/test-id-utils.d.ts +10 -0
  19. package/dist/dts/utils/test-id-utils.d.ts.map +1 -0
  20. package/dist/esm/cell-formatters/action.formatter.js +4 -2
  21. package/dist/esm/cell-formatters/actions-menu.formatter.js +11 -4
  22. package/dist/esm/cell-formatters/boolean.formatter.js +3 -1
  23. package/dist/esm/cell-formatters/editable.formatter.js +4 -1
  24. package/dist/esm/cell-formatters/select.formatter.js +170 -21
  25. package/dist/esm/cell-formatters/text.formatter.js +4 -1
  26. package/dist/esm/utils/index.js +1 -0
  27. package/dist/esm/utils/test-id-utils.js +15 -0
  28. package/dist/grid-tabulator.api.json +193 -43
  29. package/dist/grid-tabulator.d.ts +48 -28
  30. package/docs/api/grid-tabulator.actionformatter.md +2 -2
  31. package/docs/api/grid-tabulator.actionsmenuformatter.md +2 -2
  32. package/docs/api/grid-tabulator.booleanformatter.md +2 -2
  33. package/docs/api/grid-tabulator.editableformatter.md +2 -2
  34. package/docs/api/grid-tabulator.md +1 -1
  35. package/docs/api/grid-tabulator.selectformatter.md +4 -4
  36. package/docs/api/grid-tabulator.textformatter.md +2 -2
  37. package/docs/api-report.md +32 -24
  38. package/package.json +13 -13
@@ -1,32 +1,181 @@
1
+ import { DOM } from '@microsoft/fast-element';
2
+ import { getDataTestId } from '../utils';
1
3
  /**
2
- * Formatter that displays a value from a select list of options
3
- * Styled to match grid-pro select renderer.
4
+ * Set up global styles for selects only once
5
+ */
6
+ function setupGlobalStyles() {
7
+ const styleId = 'tabulator-select-styles';
8
+ if (!document.getElementById(styleId)) {
9
+ const style = document.createElement('style');
10
+ style.id = styleId;
11
+ style.textContent = `
12
+ .tabulator-row {
13
+ overflow: visible !important;
14
+ }
15
+ .tabulator {
16
+ overflow: visible !important;
17
+ }
18
+ /* All select wrappers need these styles */
19
+ .select-wrapper {
20
+ overflow: visible !important;
21
+ }
22
+ /* Target select dropdown part */
23
+ .select-renderer::part(listbox) {
24
+ position: fixed !important;
25
+ z-index: 99999 !important;
26
+ }
27
+ /* Force dropdown options to wrap text */
28
+ .select-renderer::part(option) {
29
+ white-space: normal !important;
30
+ word-break: break-word !important;
31
+ }
32
+ `;
33
+ document.head.appendChild(style);
34
+ }
35
+ }
36
+ /**
37
+ * Handle positioning and width of the dropdown when it opens
38
+ */
39
+ function setupSelectDropdownHandler(selectElement, cellElement) {
40
+ // Function to update listbox dimensions
41
+ const updateListboxDimensions = () => {
42
+ var _a;
43
+ const listbox = (_a = selectElement.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('[part="listbox"]');
44
+ if (listbox) {
45
+ const cellWidth = cellElement.offsetWidth;
46
+ listbox.style.width = `${cellWidth}px`;
47
+ listbox.style.maxWidth = `${cellWidth}px`;
48
+ }
49
+ };
50
+ // Setup a mutation observer to catch when the listbox is added to the DOM
51
+ const observer = new MutationObserver((mutations) => {
52
+ mutations.forEach((mutation) => {
53
+ if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
54
+ updateListboxDimensions();
55
+ }
56
+ });
57
+ });
58
+ // Start observing the shadow DOM
59
+ if (selectElement.shadowRoot) {
60
+ observer.observe(selectElement.shadowRoot, { childList: true, subtree: true });
61
+ }
62
+ // Handle the click event to ensure proper positioning
63
+ selectElement.addEventListener('click', updateListboxDimensions);
64
+ // Clean up observer when select is removed
65
+ const cleanupObserver = () => {
66
+ observer.disconnect();
67
+ selectElement.removeEventListener('click', updateListboxDimensions);
68
+ };
69
+ // Setup cleanup when element is removed from DOM
70
+ if (typeof window.MutationObserver !== 'undefined') {
71
+ const documentObserver = new MutationObserver((mutations) => {
72
+ if (!document.body.contains(selectElement)) {
73
+ cleanupObserver();
74
+ documentObserver.disconnect();
75
+ }
76
+ });
77
+ documentObserver.observe(document.body, { childList: true, subtree: true });
78
+ }
79
+ }
80
+ /**
81
+ * Formatter that displays a select component with options.
82
+ * Returns a wrapped div containing the select, similar to boolean.formatter.
4
83
  *
5
84
  * @param cell - The cell component provided by Tabulator
6
85
  * @param formatterParams - Select formatter parameters
7
- * @returns Text content for the selected option
86
+ * @returns An empty string, as the component is added directly to the cell element
8
87
  * @public
9
88
  */
10
89
  export function selectFormatter(cell, formatterParams) {
11
90
  const value = cell.getValue();
12
- const { options = [], prefix = 'foundation', nullText = '', dataTestId } = formatterParams;
13
- // Generate test ID if needed
14
- const testIdAttr = dataTestId ? ` data-test-id="${dataTestId}"` : '';
15
- // Handle null/undefined values
16
- if (value === null || value === undefined) {
17
- return `<div style="display: flex; width: 100%; height: 100%; align-items: center; justify-content: center;">
18
- <span${testIdAttr} class="${prefix}-select-formatter ${prefix}-select-formatter--null">${nullText}</span>
19
- </div>`;
91
+ const rowData = cell.getRow().getData();
92
+ const { options = [], prefix = 'foundation', nullText = '', dataTestId, onChange, } = formatterParams;
93
+ // Ensure global styles are set up
94
+ setupGlobalStyles();
95
+ // Create a div wrapper like in boolean.formatter.ts
96
+ const wrapper = document.createElement('div');
97
+ wrapper.className = 'select-wrapper';
98
+ wrapper.style.cssText =
99
+ 'align-items: center; display: flex; height: 100%; width: 100%; position: relative; overflow: visible;';
100
+ // Create the select element
101
+ const selectElementTag = `${prefix}-select`;
102
+ const optionElementTag = `${prefix}-option`;
103
+ // Create the select component
104
+ const selectElement = document.createElement(selectElementTag);
105
+ selectElement.className = 'select-renderer';
106
+ selectElement.style.cssText = 'width: 100%; height: 100%; min-width: 0;';
107
+ // Set high z-index for dropdown
108
+ selectElement.style.setProperty('--listbox-z-index', '99999');
109
+ selectElement.style.setProperty('--listbox-position', 'fixed');
110
+ selectElement.style.setProperty('--listbox-max-height', '200px');
111
+ // Add data-test-id if provided
112
+ const testId = getDataTestId(dataTestId, rowData);
113
+ if (testId) {
114
+ selectElement.setAttribute('data-test-id', testId);
115
+ }
116
+ // Add event listener for changes if onChange is provided
117
+ if (onChange) {
118
+ selectElement.addEventListener('change', (e) => {
119
+ const newValue = e.target.value;
120
+ onChange(newValue, rowData);
121
+ // Update the cell value if field exists
122
+ if (cell.getField()) {
123
+ cell.getData()[cell.getField()] = newValue;
124
+ }
125
+ });
20
126
  }
21
- // If using standard options
22
- const matchingOption = options.find((option) => option.value === value);
23
- if (matchingOption) {
24
- return `<div style="display: flex; width: 100%; height: 100%; align-items: center; justify-content: center;">
25
- <span${testIdAttr} class="${prefix}-select-formatter">${matchingOption.label}</span>
26
- </div>`;
127
+ // Create default option
128
+ const defaultOption = document.createElement(optionElementTag);
129
+ defaultOption.value = '';
130
+ defaultOption.textContent = nullText || 'Select option';
131
+ defaultOption.style.display = 'none';
132
+ defaultOption.defaultSelected = true;
133
+ // Append default option to select
134
+ selectElement.appendChild(defaultOption);
135
+ // Process all options
136
+ options.forEach((option) => {
137
+ const optionElement = document.createElement(optionElementTag);
138
+ optionElement.value = String(option.value);
139
+ optionElement.textContent = option.label;
140
+ // Set selected state
141
+ if (value === option.value) {
142
+ optionElement.selected = true;
143
+ }
144
+ // Handle disabled state
145
+ if (typeof option.isDisabled === 'function') {
146
+ try {
147
+ const isDisabled = option.isDisabled(rowData);
148
+ if (isDisabled) {
149
+ optionElement.disabled = true;
150
+ }
151
+ }
152
+ catch (error) {
153
+ console.error('Error executing select option isDisabled callback:', error);
154
+ }
155
+ }
156
+ // Add option to select element
157
+ selectElement.appendChild(optionElement);
158
+ });
159
+ // Set the current value if exists
160
+ if (value !== undefined && value !== null) {
161
+ selectElement.value = String(value);
27
162
  }
28
- // If no matching option found, return the original value as string
29
- return `<div style="display: flex; width: 100%; height: 100%; align-items: center; justify-content: center;">
30
- <span${testIdAttr} class="${prefix}-select-formatter">${String(value)}</span>
31
- </div>`;
163
+ // Add select to wrapper
164
+ wrapper.appendChild(selectElement);
165
+ // Get the cell element and ensure overflow visibility
166
+ const cellElement = cell.getElement();
167
+ cellElement.style.overflow = 'visible';
168
+ // Use DOM.queueUpdate to properly handle component initialization
169
+ DOM.queueUpdate(() => {
170
+ // Clear any existing content first
171
+ while (cellElement.firstChild) {
172
+ cellElement.removeChild(cellElement.firstChild);
173
+ }
174
+ // Add our wrapper with the select
175
+ cellElement.appendChild(wrapper);
176
+ // Setup dropdown handler
177
+ setupSelectDropdownHandler(selectElement, cellElement);
178
+ });
179
+ // Return empty string since we've appended the component directly
180
+ return '';
32
181
  }
@@ -1,3 +1,4 @@
1
+ import { getDataTestId } from '../utils';
1
2
  /**
2
3
  * Text formatter for customized display of values.
3
4
  * Styled to match grid-pro text renderer.
@@ -9,9 +10,11 @@
9
10
  */
10
11
  export function textFormatter(cell, formatterParams = {}) {
11
12
  const value = cell.getValue();
13
+ const rowData = cell.getData();
12
14
  const { specialValue = 2012, specialColor = 'orange', specialFontWeight = 'bold', prefix = 'foundation', dataTestId, nullText = '', } = formatterParams;
13
15
  // Generate test ID if needed
14
- const testIdAttr = dataTestId ? ` data-test-id="${dataTestId}"` : '';
16
+ const testId = getDataTestId(dataTestId, rowData);
17
+ const testIdAttr = testId ? ` data-test-id="${testId}"` : '';
15
18
  // Handle null/undefined values
16
19
  if (value === null || value === undefined) {
17
20
  return `<div style="display: flex; width: 100%; height: 100%; align-items: center;">
@@ -1,2 +1,3 @@
1
1
  export * from './logger';
2
2
  export * from './string-utils';
3
+ export * from './test-id-utils';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Resolves a dataTestId value that can be either a string or a function
3
+ *
4
+ * @param dataTestId - The dataTestId value (string or function)
5
+ * @param rowData - The row data to pass to the function if dataTestId is a function
6
+ * @returns The resolved test ID string or undefined if not provided
7
+ * @alpha
8
+ */
9
+ export function getDataTestId(dataTestId, rowData) {
10
+ if (!dataTestId)
11
+ return undefined;
12
+ if (typeof dataTestId === 'function')
13
+ return dataTestId(rowData);
14
+ return dataTestId;
15
+ }