@keenmate/web-grid 1.0.0-rc02

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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +243 -0
  3. package/component-variables.manifest.json +192 -0
  4. package/dist/grid.d.ts +319 -0
  5. package/dist/index.d.ts +4 -0
  6. package/dist/modules/contextmenu/index.d.ts +10 -0
  7. package/dist/modules/datepicker/datepicker.d.ts +79 -0
  8. package/dist/modules/datepicker/formatting.d.ts +44 -0
  9. package/dist/modules/datepicker/index.d.ts +4 -0
  10. package/dist/modules/datepicker/interaction.d.ts +39 -0
  11. package/dist/modules/datepicker/navigation.d.ts +37 -0
  12. package/dist/modules/datepicker/rendering.d.ts +56 -0
  13. package/dist/modules/datepicker/types.d.ts +62 -0
  14. package/dist/modules/dropdown/index.d.ts +4 -0
  15. package/dist/modules/dropdown/input-handlers.d.ts +14 -0
  16. package/dist/modules/dropdown/interaction.d.ts +34 -0
  17. package/dist/modules/dropdown/options.d.ts +33 -0
  18. package/dist/modules/dropdown/rendering.d.ts +11 -0
  19. package/dist/modules/editing/index.d.ts +2 -0
  20. package/dist/modules/editing/lifecycle.d.ts +25 -0
  21. package/dist/modules/editing/renderers.d.ts +39 -0
  22. package/dist/modules/navigation/focus.d.ts +46 -0
  23. package/dist/modules/navigation/index.d.ts +1 -0
  24. package/dist/modules/rendering/display.d.ts +7 -0
  25. package/dist/modules/rendering/index.d.ts +3 -0
  26. package/dist/modules/rendering/table.d.ts +39 -0
  27. package/dist/modules/toolbar/index.d.ts +55 -0
  28. package/dist/modules/tooltip/index.d.ts +1 -0
  29. package/dist/modules/tooltip/tooltip.d.ts +13 -0
  30. package/dist/modules/types.d.ts +32 -0
  31. package/dist/types.d.ts +311 -0
  32. package/dist/web-component.d.ts +277 -0
  33. package/dist/web-grid.js +5370 -0
  34. package/dist/web-grid.umd.js +618 -0
  35. package/package.json +78 -0
  36. package/src/css/_cells.css +77 -0
  37. package/src/css/_dark-mode.css +51 -0
  38. package/src/css/_dialogs.css +121 -0
  39. package/src/css/_dropdown.css +193 -0
  40. package/src/css/_editors.css +184 -0
  41. package/src/css/_header.css +105 -0
  42. package/src/css/_modifiers.css +36 -0
  43. package/src/css/_navigation.css +25 -0
  44. package/src/css/_pagination.css +156 -0
  45. package/src/css/_table.css +90 -0
  46. package/src/css/_toolbar.css +139 -0
  47. package/src/css/_variables.css +265 -0
  48. package/src/css/_virtual-scroll.css +24 -0
  49. package/src/css/main.css +35 -0
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@keenmate/web-grid",
3
+ "version": "1.0.0-rc02",
4
+ "description": "Framework-agnostic data grid web component with sorting, filtering, inline editing, and keyboard navigation",
5
+ "type": "module",
6
+ "main": "./dist/web-grid.umd.js",
7
+ "module": "./dist/web-grid.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/web-grid.js",
13
+ "require": "./dist/web-grid.umd.js",
14
+ "default": "./dist/web-grid.js"
15
+ },
16
+ "./css": "./src/css/main.css",
17
+ "./manifest": "./component-variables.manifest.json",
18
+ "./dist/*": "./dist/*",
19
+ "./src/css/*": "./src/css/*",
20
+ "./package.json": "./package.json"
21
+ },
22
+ "sideEffects": [
23
+ "./dist/web-grid.js",
24
+ "./dist/web-grid.umd.js",
25
+ "*.css"
26
+ ],
27
+ "files": [
28
+ "dist",
29
+ "src/css",
30
+ "component-variables.manifest.json"
31
+ ],
32
+ "scripts": {
33
+ "dev": "vite --port 12500",
34
+ "build": "npm run clean:dist && tsc && vite build",
35
+ "build:types": "tsc",
36
+ "preview": "vite preview",
37
+ "clean": "rimraf dist --glob \"*.tgz\"",
38
+ "clean:dist": "rimraf dist"
39
+ },
40
+ "keywords": [
41
+ "grid",
42
+ "data-grid",
43
+ "table",
44
+ "datagrid",
45
+ "editable",
46
+ "sortable",
47
+ "filterable",
48
+ "pagination",
49
+ "inline-editing",
50
+ "web-component",
51
+ "custom-element",
52
+ "shadow-dom",
53
+ "typescript",
54
+ "dark-mode",
55
+ "context-menu",
56
+ "row-toolbar",
57
+ "keyboard-navigation",
58
+ "keenmate"
59
+ ],
60
+ "author": "KeenMate",
61
+ "license": "MIT",
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "git+https://github.com/KeenMate/web-grid.git"
65
+ },
66
+ "bugs": {
67
+ "url": "https://github.com/KeenMate/web-grid/issues"
68
+ },
69
+ "homepage": "https://github.com/KeenMate/web-grid#readme",
70
+ "devDependencies": {
71
+ "rimraf": "^5.0.5",
72
+ "typescript": "^5.3.3",
73
+ "vite": "^5.0.8"
74
+ },
75
+ "dependencies": {
76
+ "@floating-ui/dom": "^1.7.4"
77
+ }
78
+ }
@@ -0,0 +1,77 @@
1
+ /* ==============================================================================
2
+ CELLS
3
+ ==============================================================================
4
+ Cell styles, editable states, editing mode, validation
5
+ */
6
+
7
+ .wg__cell {
8
+ padding: var(--wg-cell-padding);
9
+ color: var(--wg-cell-color);
10
+ /* Account for sticky header when scrolling into view */
11
+ scroll-margin-top: 3rem;
12
+ scroll-margin-bottom: 0.5rem;
13
+ }
14
+
15
+ /* Cell text - prevent selection flash on double-click */
16
+ .wg__cell-text {
17
+ user-select: none;
18
+ }
19
+
20
+ /* Text overflow ellipsis */
21
+ .wg__cell--ellipsis {
22
+ overflow: hidden;
23
+ text-overflow: ellipsis;
24
+ white-space: nowrap;
25
+ }
26
+
27
+ /* ==============================================================================
28
+ EDITABLE CELLS
29
+ ============================================================================== */
30
+ .wg__cell--editable {
31
+ cursor: pointer;
32
+ position: relative;
33
+ }
34
+
35
+ .wg__cell--editable:hover {
36
+ background: var(--wg-cell-bg-hover);
37
+ }
38
+
39
+ /* Dashed border on hover for editable cells */
40
+ .wg__cell--editable:hover::after {
41
+ content: "";
42
+ position: absolute;
43
+ inset: 2px;
44
+ border: 1px dashed var(--wg-border-color);
45
+ border-radius: 2px;
46
+ pointer-events: none;
47
+ }
48
+
49
+ /* ==============================================================================
50
+ EDITING CELLS
51
+ ============================================================================== */
52
+ .wg__cell--editing {
53
+ position: relative;
54
+ background: var(--wg-surface-1);
55
+ outline: 2px solid var(--wg-accent-color);
56
+ outline-offset: -2px;
57
+ }
58
+
59
+ /* Hide the dashed hover border when editing */
60
+ .wg__cell--editing::after {
61
+ display: none;
62
+ }
63
+
64
+ /* ==============================================================================
65
+ INVALID CELLS
66
+ ============================================================================== */
67
+ .wg__cell--invalid {
68
+ background: var(--wg-danger-bg-light, #fee);
69
+ box-shadow: inset 0 0 0 2px var(--wg-danger-color, #c00);
70
+ }
71
+
72
+ /* ==============================================================================
73
+ READ-ONLY CELLS (permanent styling, not focus-related)
74
+ ============================================================================== */
75
+ .wg--navigate-mode .wg__cell:not(.wg__cell--editable) {
76
+ background: var(--wg-cell-readonly-bg, #f5f5f5);
77
+ }
@@ -0,0 +1,51 @@
1
+ /* ==============================================================================
2
+ DARK MODE SUPPORT
3
+ ==============================================================================
4
+ Dark mode is controlled by:
5
+ 1. OS preference: @media (prefers-color-scheme: dark)
6
+ 2. data-theme="dark" on ancestor or host
7
+ 3. data-bs-theme="dark" (Bootstrap 5.3+) on ancestor
8
+ 4. .dark class on ancestor (Tailwind CSS convention)
9
+ */
10
+ @media (prefers-color-scheme: dark) {
11
+ :host {
12
+ --wg-surface-1: #1f1f1f;
13
+ --wg-surface-2: #2b2b2b;
14
+ --wg-surface-3: #333333;
15
+ --wg-surface-floating: #2b2b2b;
16
+ --wg-text-color-1: #e0e0e0;
17
+ --wg-text-color-2: #c0c0c0;
18
+ --wg-text-color-3: #a0a0a0;
19
+ --wg-border-color: #3d3d3d;
20
+ --wg-border-color-hover: #5a5a5a;
21
+ --wg-input-bg: #1f1f1f;
22
+ --wg-input-border: 1px solid #5a5a5a;
23
+ --wg-hover-bg: #3a3a3a;
24
+ --wg-active-bg: #4a4a4a;
25
+ --wg-danger-bg-light: #442726;
26
+ --wg-danger-color: #f87c86;
27
+ }
28
+ }
29
+
30
+ /* Explicit dark mode via data-theme, data-bs-theme attribute, or .dark class */
31
+ :host([data-theme="dark"]),
32
+ [data-theme="dark"] :host,
33
+ :host([data-bs-theme="dark"]),
34
+ [data-bs-theme="dark"] :host,
35
+ .dark :host {
36
+ --wg-surface-1: #1f1f1f;
37
+ --wg-surface-2: #2b2b2b;
38
+ --wg-surface-3: #333333;
39
+ --wg-surface-floating: #2b2b2b;
40
+ --wg-text-color-1: #e0e0e0;
41
+ --wg-text-color-2: #c0c0c0;
42
+ --wg-text-color-3: #a0a0a0;
43
+ --wg-border-color: #3d3d3d;
44
+ --wg-border-color-hover: #5a5a5a;
45
+ --wg-input-bg: #1f1f1f;
46
+ --wg-input-border: 1px solid #5a5a5a;
47
+ --wg-hover-bg: #3a3a3a;
48
+ --wg-active-bg: #4a4a4a;
49
+ --wg-danger-bg-light: #442726;
50
+ --wg-danger-color: #f87c86;
51
+ }
@@ -0,0 +1,121 @@
1
+ /* ==============================================================================
2
+ TOOLTIP (Floating UI positioned)
3
+ ============================================================================== */
4
+ .wg__tooltip {
5
+ position: fixed;
6
+ z-index: var(--wg-z-tooltip, 10000);
7
+ max-width: 300px;
8
+ padding: 6px 10px;
9
+ background: var(--wg-tooltip-bg, #333);
10
+ color: var(--wg-tooltip-color, #fff);
11
+ font-size: var(--wg-font-size-sm);
12
+ line-height: 1.4;
13
+ border-radius: var(--wg-border-radius-sm);
14
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
15
+ pointer-events: none;
16
+ opacity: 0;
17
+ transition: opacity var(--wg-transition-fast);
18
+ }
19
+
20
+ .wg__tooltip--visible {
21
+ opacity: 1;
22
+ }
23
+
24
+ .wg__tooltip-arrow {
25
+ position: absolute;
26
+ width: 8px;
27
+ height: 8px;
28
+ background: var(--wg-tooltip-bg, #333);
29
+ transform: rotate(45deg);
30
+ }
31
+
32
+ /* Arrow positioning based on tooltip placement */
33
+ .wg__tooltip[data-placement^="top"] .wg__tooltip-arrow {
34
+ bottom: -4px;
35
+ }
36
+
37
+ .wg__tooltip[data-placement^="bottom"] .wg__tooltip-arrow {
38
+ top: -4px;
39
+ }
40
+
41
+ .wg__tooltip[data-placement^="left"] .wg__tooltip-arrow {
42
+ right: -4px;
43
+ }
44
+
45
+ .wg__tooltip[data-placement^="right"] .wg__tooltip-arrow {
46
+ left: -4px;
47
+ }
48
+
49
+ /* ==============================================================================
50
+ GO TO ROW DIALOG (Ctrl+G)
51
+ ============================================================================== */
52
+ .wg__goto-overlay {
53
+ position: fixed;
54
+ inset: 0;
55
+ background: rgba(0, 0, 0, 0.4);
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ z-index: 1000;
60
+ }
61
+
62
+ .wg__goto-dialog {
63
+ background: var(--wg-surface-1);
64
+ border-radius: var(--wg-border-radius);
65
+ padding: var(--wg-spacing-lg);
66
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
67
+ min-width: 250px;
68
+ }
69
+
70
+ .wg__goto-label {
71
+ display: block;
72
+ margin-bottom: var(--wg-spacing-sm);
73
+ font-size: var(--wg-font-size-base);
74
+ color: var(--wg-text-color-1);
75
+ }
76
+
77
+ .wg__goto-input {
78
+ width: 100%;
79
+ padding: var(--wg-spacing-sm) var(--wg-spacing-md);
80
+ border: 1px solid var(--wg-border-color);
81
+ border-radius: var(--wg-border-radius-sm);
82
+ font-size: var(--wg-font-size-base);
83
+ margin-bottom: var(--wg-spacing-md);
84
+ box-sizing: border-box;
85
+ }
86
+
87
+ .wg__goto-input:focus {
88
+ outline: none;
89
+ border-color: var(--wg-accent-color);
90
+ box-shadow: 0 0 0 2px rgba(0, 120, 212, 0.2);
91
+ }
92
+
93
+ .wg__goto-buttons {
94
+ display: flex;
95
+ gap: var(--wg-spacing-sm);
96
+ justify-content: flex-end;
97
+ }
98
+
99
+ .wg__goto-btn {
100
+ padding: var(--wg-spacing-sm) var(--wg-spacing-md);
101
+ border: 1px solid var(--wg-border-color);
102
+ border-radius: var(--wg-border-radius-sm);
103
+ font-size: var(--wg-font-size-sm);
104
+ cursor: pointer;
105
+ background: var(--wg-surface-1);
106
+ color: var(--wg-text-color-1);
107
+ }
108
+
109
+ .wg__goto-btn:hover {
110
+ background: var(--wg-surface-2);
111
+ }
112
+
113
+ .wg__goto-btn--go {
114
+ background: var(--wg-accent-color);
115
+ border-color: var(--wg-accent-color);
116
+ color: white;
117
+ }
118
+
119
+ .wg__goto-btn--go:hover {
120
+ background: var(--wg-accent-color-hover, #106ebe);
121
+ }
@@ -0,0 +1,193 @@
1
+ /* ==============================================================================
2
+ DROPDOWN
3
+ ==============================================================================
4
+ Dropdown menus and select triggers
5
+ */
6
+
7
+ /* ==============================================================================
8
+ SELECT TRIGGER (custom dropdown trigger like v3)
9
+ ============================================================================== */
10
+ .wg__select-trigger {
11
+ display: flex;
12
+ align-items: center;
13
+ justify-content: space-between;
14
+ cursor: pointer;
15
+ background: transparent;
16
+ }
17
+
18
+ .wg__select-trigger:focus,
19
+ .wg__select-trigger:focus-visible {
20
+ outline: none;
21
+ box-shadow: none;
22
+ }
23
+
24
+ .wg__select-value {
25
+ flex: 1;
26
+ overflow: hidden;
27
+ text-overflow: ellipsis;
28
+ white-space: nowrap;
29
+ }
30
+
31
+ .wg__select-toggle {
32
+ position: relative;
33
+ font-size: var(--wg-dropdown-toggle-size);
34
+ opacity: 0.6;
35
+ margin-left: 4px;
36
+ flex-shrink: 0;
37
+ pointer-events: auto;
38
+ cursor: pointer;
39
+ }
40
+
41
+ /* Larger invisible hitbox for easier clicking */
42
+ .wg__select-toggle::before {
43
+ content: "";
44
+ position: absolute;
45
+ top: 50%;
46
+ left: 50%;
47
+ transform: translate(-50%, -50%);
48
+ width: var(--wg-dropdown-toggle-hitbox);
49
+ height: 48px;
50
+ }
51
+
52
+ /* Dropdown cell in display mode (read-only, same layout as editor) */
53
+ .wg__cell-dropdown-display {
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: space-between;
57
+ width: 100%;
58
+ cursor: pointer;
59
+ }
60
+
61
+ /* Toggle visibility: on-focus mode - hide by default, show on hover/focus */
62
+ .wg__cell-dropdown-display--toggle-on-focus .wg__select-toggle {
63
+ opacity: 0;
64
+ }
65
+
66
+ .wg__cell:hover .wg__cell-dropdown-display--toggle-on-focus .wg__select-toggle {
67
+ opacity: 0.6;
68
+ }
69
+
70
+ .wg__cell--focused .wg__cell-dropdown-display--toggle-on-focus .wg__select-toggle {
71
+ opacity: 0.6;
72
+ }
73
+
74
+ /* Date cell in display mode (same pattern as dropdown) */
75
+ .wg__cell-date-display {
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: space-between;
79
+ width: 100%;
80
+ cursor: pointer;
81
+ }
82
+
83
+ .wg__cell-date-display .wg__date-trigger {
84
+ position: relative;
85
+ background: none;
86
+ border: none;
87
+ padding: 0;
88
+ margin: 0;
89
+ cursor: pointer;
90
+ opacity: 0.6;
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ color: inherit;
95
+ }
96
+
97
+ /* Larger invisible hitbox for easier clicking */
98
+ .wg__cell-date-display .wg__date-trigger::before {
99
+ content: "";
100
+ position: absolute;
101
+ top: 50%;
102
+ left: 50%;
103
+ transform: translate(-50%, -50%);
104
+ width: var(--wg-dropdown-toggle-hitbox);
105
+ height: 48px;
106
+ }
107
+
108
+ /* Toggle visibility: on-focus mode - hide by default, show on hover/focus */
109
+ .wg__cell-date-display--toggle-on-focus .wg__date-trigger {
110
+ opacity: 0;
111
+ }
112
+
113
+ .wg__cell:hover .wg__cell-date-display--toggle-on-focus .wg__date-trigger {
114
+ opacity: 0.6;
115
+ }
116
+
117
+ .wg__cell--focused .wg__cell-date-display--toggle-on-focus .wg__date-trigger {
118
+ opacity: 0.6;
119
+ }
120
+
121
+ /* ==============================================================================
122
+ DROPDOWN MENU
123
+ ============================================================================== */
124
+ .wg__dropdown {
125
+ background: var(--wg-surface-floating, #fff);
126
+ border: 1px solid var(--wg-border-color, #d1d1d1);
127
+ border-radius: 4px;
128
+ box-shadow: var(--wg-toolbar-shadow);
129
+ max-height: 200px;
130
+ overflow-y: auto;
131
+ font-size: var(--wg-font-size-base);
132
+ font-family: inherit;
133
+ line-height: var(--wg-line-height-base);
134
+ }
135
+
136
+ .wg__dropdown-option {
137
+ display: flex;
138
+ align-items: center;
139
+ gap: var(--wg-spacing-sm);
140
+ padding: 6px 12px;
141
+ cursor: pointer;
142
+ color: var(--wg-text-color-1);
143
+ }
144
+
145
+ .wg__dropdown-option:hover,
146
+ .wg__dropdown-option--highlighted {
147
+ background: var(--wg-hover-bg, #f0f0f0);
148
+ }
149
+
150
+ .wg__dropdown-option--selected {
151
+ background: var(--wg-accent-color-light, #e6f2ff);
152
+ }
153
+
154
+ .wg__dropdown-option--disabled {
155
+ opacity: 0.5;
156
+ cursor: not-allowed;
157
+ pointer-events: none;
158
+ }
159
+
160
+ .wg__dropdown-option-icon {
161
+ flex-shrink: 0;
162
+ width: 1.5em;
163
+ text-align: center;
164
+ }
165
+
166
+ .wg__dropdown-option-content {
167
+ flex: 1;
168
+ min-width: 0;
169
+ overflow: hidden;
170
+ }
171
+
172
+ .wg__dropdown-option-label {
173
+ display: block;
174
+ white-space: nowrap;
175
+ overflow: hidden;
176
+ text-overflow: ellipsis;
177
+ }
178
+
179
+ .wg__dropdown-option-subtitle {
180
+ display: block;
181
+ font-size: var(--wg-font-size-sm);
182
+ color: var(--wg-text-color-2);
183
+ white-space: nowrap;
184
+ overflow: hidden;
185
+ text-overflow: ellipsis;
186
+ }
187
+
188
+ .wg__dropdown-empty {
189
+ padding: 8px 12px;
190
+ color: var(--wg-text-color-2);
191
+ font-style: italic;
192
+ text-align: center;
193
+ }
@@ -0,0 +1,184 @@
1
+ /* ==============================================================================
2
+ EDITORS
3
+ ==============================================================================
4
+ Input editors for cells: text, number, date, checkbox, custom, combobox
5
+ */
6
+
7
+ .wg__editor {
8
+ position: absolute;
9
+ top: 0;
10
+ left: 0;
11
+ right: 0;
12
+ width: 100%;
13
+ padding: var(--wg-cell-padding);
14
+ border: none;
15
+ background: transparent; /* Transparent - cell provides background */
16
+ color: var(--wg-text-color-1);
17
+ font-size: var(--wg-font-size-base);
18
+ font-family: inherit;
19
+ line-height: inherit;
20
+ box-sizing: border-box;
21
+ }
22
+
23
+ .wg__editor:focus,
24
+ .wg__editor:focus-visible {
25
+ outline: none;
26
+ box-shadow: none;
27
+ }
28
+
29
+ /* Text Editor */
30
+ .wg__editor--text {
31
+ text-align: inherit;
32
+ }
33
+
34
+ /* Number Editor */
35
+ .wg__editor--number {
36
+ text-align: right;
37
+ }
38
+
39
+ /* Date Editor */
40
+ .wg__editor--date {
41
+ position: absolute;
42
+ inset: 0;
43
+ display: flex;
44
+ align-items: center;
45
+ background: var(--wg-editor-bg);
46
+ }
47
+
48
+ .wg__date-input {
49
+ flex: 1;
50
+ min-width: 0;
51
+ height: 100%;
52
+ border: none;
53
+ background: transparent;
54
+ font: inherit;
55
+ padding: var(--wg-cell-padding-block) var(--wg-cell-padding-inline);
56
+ outline: none;
57
+ color: inherit;
58
+ }
59
+
60
+ .wg__date-trigger {
61
+ width: var(--wg-date-trigger-size, 28px);
62
+ height: 100%;
63
+ display: flex;
64
+ align-items: center;
65
+ justify-content: center;
66
+ border: none;
67
+ background: transparent;
68
+ color: var(--wg-text-secondary, #666);
69
+ cursor: pointer;
70
+ padding: 0;
71
+ flex-shrink: 0;
72
+ }
73
+
74
+ .wg__date-trigger:hover {
75
+ color: var(--wg-accent-color, #0078d4);
76
+ background: var(--wg-hover-bg, rgba(0, 0, 0, 0.05));
77
+ }
78
+
79
+ /* Checkbox Editor */
80
+ .wg__editor--checkbox {
81
+ width: auto;
82
+ height: auto;
83
+ margin: 0 auto;
84
+ }
85
+
86
+ /* Custom Editor */
87
+ .wg__editor--custom {
88
+ position: absolute;
89
+ inset: 0;
90
+ display: flex;
91
+ align-items: center;
92
+ background: var(--wg-editor-bg);
93
+ padding: var(--wg-cell-padding-block) var(--wg-cell-padding-inline);
94
+ cursor: pointer;
95
+ }
96
+
97
+ .wg__editor--custom:focus {
98
+ outline: none;
99
+ }
100
+
101
+ .wg__custom-value {
102
+ flex: 1;
103
+ overflow: hidden;
104
+ text-overflow: ellipsis;
105
+ white-space: nowrap;
106
+ display: block;
107
+ cursor: pointer;
108
+ }
109
+
110
+ /* ==============================================================================
111
+ COMBOBOX / AUTOCOMPLETE EDITORS
112
+ ============================================================================== */
113
+ .wg__editor--combobox,
114
+ .wg__editor--autocomplete {
115
+ position: absolute;
116
+ inset: 0;
117
+ display: flex;
118
+ align-items: center;
119
+ padding: var(--wg-cell-padding);
120
+ padding-right: 0; /* Arrow handles right side */
121
+ background: transparent; /* Transparent - cell provides background */
122
+ box-sizing: border-box;
123
+ }
124
+
125
+ .wg__combobox-input,
126
+ .wg__autocomplete-input {
127
+ flex: 1;
128
+ width: 100%;
129
+ height: 100%;
130
+ padding: 0;
131
+ padding-right: 24px; /* Space for arrow */
132
+ border: none;
133
+ background: transparent;
134
+ color: var(--wg-text-color-1);
135
+ font-size: var(--wg-font-size-base);
136
+ font-family: inherit;
137
+ line-height: var(--wg-line-height-base);
138
+ outline: none;
139
+ box-sizing: border-box;
140
+ margin: 0;
141
+ -webkit-appearance: none;
142
+ appearance: none;
143
+ }
144
+
145
+ .wg__combobox-input:focus,
146
+ .wg__autocomplete-input:focus {
147
+ outline: none;
148
+ }
149
+
150
+ .wg__combobox-toggle {
151
+ position: absolute;
152
+ right: var(--wg-dropdown-toggle-right);
153
+ top: 50%;
154
+ transform: translateY(-50%);
155
+ font-size: var(--wg-dropdown-toggle-size);
156
+ color: var(--wg-text-color-2);
157
+ pointer-events: auto;
158
+ cursor: pointer;
159
+ }
160
+
161
+ /* Larger invisible hitbox for easier clicking */
162
+ .wg__combobox-toggle::before {
163
+ content: "";
164
+ position: absolute;
165
+ top: 50%;
166
+ left: 50%;
167
+ transform: translate(-50%, -50%);
168
+ width: var(--wg-dropdown-toggle-hitbox);
169
+ height: 48px;
170
+ }
171
+
172
+ .wg__loading-indicator {
173
+ position: absolute;
174
+ right: var(--wg-dropdown-toggle-right);
175
+ top: 50%;
176
+ transform: translateY(-50%);
177
+ font-size: 12px;
178
+ animation: wg-pulse 1s infinite;
179
+ }
180
+
181
+ @keyframes wg-pulse {
182
+ 0%, 100% { opacity: 1; }
183
+ 50% { opacity: 0.4; }
184
+ }