ezfw-core 1.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/components/EzBaseComponent.ts +648 -0
- package/components/EzComponent.ts +89 -0
- package/components/EzInput.module.scss +183 -0
- package/components/EzInput.ts +104 -0
- package/components/EzLabel.ts +22 -0
- package/components/EzOutlet.ts +181 -0
- package/components/HtmlWrapper.ts +305 -0
- package/components/avatar/EzAvatar.module.scss +200 -0
- package/components/avatar/EzAvatar.ts +130 -0
- package/components/badge/EzBadge.module.scss +202 -0
- package/components/badge/EzBadge.ts +77 -0
- package/components/button/EzButton.module.scss +402 -0
- package/components/button/EzButton.ts +175 -0
- package/components/button/EzButtonGroup.ts +48 -0
- package/components/card/EzCard.module.scss +71 -0
- package/components/card/EzCard.ts +120 -0
- package/components/chart/EzBarChart.ts +47 -0
- package/components/chart/EzChart.module.scss +14 -0
- package/components/chart/EzChart.ts +279 -0
- package/components/chart/EzDoughnutChart.ts +47 -0
- package/components/chart/EzLineChart.ts +53 -0
- package/components/checkbox/EzCheckbox.module.scss +145 -0
- package/components/checkbox/EzCheckbox.ts +115 -0
- package/components/dataview/EzDataView.module.scss +115 -0
- package/components/dataview/EzDataView.ts +355 -0
- package/components/dataview/modes/EzDataViewCards.ts +322 -0
- package/components/dataview/modes/EzDataViewGrid.ts +76 -0
- package/components/datepicker/EzDatePicker.module.scss +348 -0
- package/components/datepicker/EzDatePicker.ts +519 -0
- package/components/dialog/EzDialog.module.scss +180 -0
- package/components/dropdown/EzDropdown.module.scss +107 -0
- package/components/dropdown/EzDropdown.ts +235 -0
- package/components/feed/EzActivityFeed.module.scss +90 -0
- package/components/feed/EzActivityFeed.ts +78 -0
- package/components/form/EzForm.ts +364 -0
- package/components/form/EzValidators.test.js +421 -0
- package/components/form/EzValidators.ts +202 -0
- package/components/grid/EzGrid.scss +88 -0
- package/components/grid/EzGrid.ts +1085 -0
- package/components/grid/EzGridContainer.ts +104 -0
- package/components/grid/body/EzGridBody.scss +283 -0
- package/components/grid/body/EzGridBody.ts +549 -0
- package/components/grid/body/EzGridCell.ts +211 -0
- package/components/grid/body/EzGridRow.ts +196 -0
- package/components/grid/filter/EzGridFilters.scss +78 -0
- package/components/grid/filter/EzGridFilters.ts +285 -0
- package/components/grid/footer/EzGridFooter.scss +136 -0
- package/components/grid/footer/EzGridFooter.ts +448 -0
- package/components/grid/header/EzGridHeader.scss +199 -0
- package/components/grid/header/EzGridHeader.ts +430 -0
- package/components/grid/query/EzGridQuery.ts +81 -0
- package/components/grid/state/EzGridColumns.ts +155 -0
- package/components/grid/state/EzGridController.ts +470 -0
- package/components/grid/state/EzGridLifecycle.ts +136 -0
- package/components/grid/state/EzGridNormalizers.test.js +273 -0
- package/components/grid/state/EzGridNormalizers.ts +162 -0
- package/components/grid/state/EzGridParts.ts +233 -0
- package/components/grid/state/EzGridPersistence.ts +140 -0
- package/components/grid/state/EzGridRemote.test.js +573 -0
- package/components/grid/state/EzGridRemote.ts +335 -0
- package/components/grid/state/EzGridSelection.ts +231 -0
- package/components/grid/state/EzGridSort.ts +286 -0
- package/components/grid/title/EzGridActionBar.ts +98 -0
- package/components/grid/title/EzGridTitle.ts +114 -0
- package/components/grid/title/EzGridTitleBar.scss +65 -0
- package/components/grid/title/EzGridTitleBar.ts +87 -0
- package/components/grid/types.ts +607 -0
- package/components/panel/EzPanel.module.scss +133 -0
- package/components/panel/EzPanel.ts +147 -0
- package/components/radio/EzRadio.module.scss +190 -0
- package/components/radio/EzRadio.ts +149 -0
- package/components/select/EzSelect.module.scss +153 -0
- package/components/select/EzSelect.ts +238 -0
- package/components/skeleton/EzSkeleton.module.scss +95 -0
- package/components/skeleton/EzSkeleton.ts +70 -0
- package/components/store/EzStore.ts +344 -0
- package/components/switch/EzSwitch.module.scss +164 -0
- package/components/switch/EzSwitch.ts +117 -0
- package/components/tabs/EzTabPanel.module.scss +181 -0
- package/components/tabs/EzTabPanel.ts +402 -0
- package/components/textarea/EzTextarea.module.scss +131 -0
- package/components/textarea/EzTextarea.ts +161 -0
- package/components/timepicker/EzTimePicker.module.scss +282 -0
- package/components/timepicker/EzTimePicker.ts +540 -0
- package/components/toast/EzToast.module.scss +291 -0
- package/components/tooltip/EzTooltip.module.scss +124 -0
- package/components/tooltip/EzTooltip.ts +153 -0
- package/core/EzComponentTypes.ts +693 -0
- package/core/EzError.ts +63 -0
- package/core/EzModel.ts +268 -0
- package/core/EzTypes.ts +328 -0
- package/core/eventBus.ts +284 -0
- package/core/ez.ts +617 -0
- package/core/loader.ts +725 -0
- package/core/renderer.ts +1010 -0
- package/core/router.ts +490 -0
- package/core/services.ts +124 -0
- package/core/state.ts +142 -0
- package/core/utils.ts +81 -0
- package/package.json +51 -0
- package/services/RouteUI.js +17 -0
- package/services/crypto.js +64 -0
- package/services/dialog.js +222 -0
- package/services/fetchApi.js +63 -0
- package/services/firebase.js +30 -0
- package/services/toast.js +214 -0
- package/template/doc/EzDocs.js +15 -0
- package/template/doc/EzDocs.module.scss +627 -0
- package/template/doc/EzDocsController.js +164 -0
- package/template/doc/data/activityfeed/EzActivityFeedDoc.js +42 -0
- package/template/doc/data/avatar/EzAvatarDoc.js +71 -0
- package/template/doc/data/badge/EzBadgeDoc.js +92 -0
- package/template/doc/data/button/EzButtonDoc.js +77 -0
- package/template/doc/data/buttongroup/EzButtonGroupDoc.js +102 -0
- package/template/doc/data/card/EzCardDoc.js +39 -0
- package/template/doc/data/chart/EzChartDoc.js +60 -0
- package/template/doc/data/checkbox/EzCheckboxDoc.js +67 -0
- package/template/doc/data/component/EzComponentDoc.js +34 -0
- package/template/doc/data/cssmodules/CSSModulesDoc.js +70 -0
- package/template/doc/data/datepicker/EzDatePickerDoc.js +126 -0
- package/template/doc/data/dialog/EzDialogDoc.js +217 -0
- package/template/doc/data/dropdown/EzDropdownDoc.js +178 -0
- package/template/doc/data/form/EzFormDoc.js +90 -0
- package/template/doc/data/grid/EzGridDoc.js +99 -0
- package/template/doc/data/input/EzInputDoc.js +92 -0
- package/template/doc/data/label/EzLabelDoc.js +40 -0
- package/template/doc/data/model/EzModelDoc.js +53 -0
- package/template/doc/data/outlet/EzOutletDoc.js +63 -0
- package/template/doc/data/panel/EzPanelDoc.js +214 -0
- package/template/doc/data/radio/EzRadioDoc.js +174 -0
- package/template/doc/data/router/EzRouterDoc.js +75 -0
- package/template/doc/data/select/EzSelectDoc.js +37 -0
- package/template/doc/data/skeleton/EzSkeletonDoc.js +149 -0
- package/template/doc/data/switch/EzSwitchDoc.js +82 -0
- package/template/doc/data/tabpanel/EzTabPanelDoc.js +44 -0
- package/template/doc/data/textarea/EzTextareaDoc.js +131 -0
- package/template/doc/data/timepicker/EzTimePickerDoc.js +107 -0
- package/template/doc/data/tooltip/EzTooltipDoc.js +193 -0
- package/template/doc/data/validators/EzValidatorsDoc.js +37 -0
- package/template/doc/sidebar/EzDocsSidebar.js +32 -0
- package/template/doc/sidebar/category/EzDocsCategory.js +33 -0
- package/template/doc/sidebar/item/EzDocsComponentItem.js +24 -0
- package/template/doc/viewer/EzDocsViewer.js +18 -0
- package/template/doc/viewer/codepanel/EzDocsCodePanel.js +51 -0
- package/template/doc/viewer/content/EzDocsContent.js +315 -0
- package/template/doc/viewer/header/EzDocsViewerHeader.js +46 -0
- package/template/doc/viewer/showcase/EzDocsShowcase.js +59 -0
- package/template/doc/viewer/showcase/EzDocsShowcaseSection.js +25 -0
- package/template/doc/viewer/showcase/EzDocsVariantItem.js +29 -0
- package/template/doc/welcome/EzDocsWelcome.js +48 -0
- package/themes/ez-theme.scss +179 -0
- package/themes/nature-fresh.scss +169 -0
- package/types/global.d.ts +21 -0
- package/utils/cssModules.js +81 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// EzGrid/filter/EzGridFilters.ts
|
|
2
|
+
|
|
3
|
+
import './EzGridFilters.scss';
|
|
4
|
+
import { EzGridContainer, EzGridContainerConfig } from '../EzGridContainer.js';
|
|
5
|
+
import type { NormalizedColumn, FilterSnapshot } from '../types.js';
|
|
6
|
+
|
|
7
|
+
declare const ez: {
|
|
8
|
+
_createElement(config: any): Promise<HTMLElement | null>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export interface FilterContext {
|
|
12
|
+
grid: EzGridFiltersRef | undefined;
|
|
13
|
+
column: NormalizedColumn;
|
|
14
|
+
value: any;
|
|
15
|
+
setValue: (value: any) => void;
|
|
16
|
+
field: string;
|
|
17
|
+
operator: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ResolvedFilter {
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
field?: string;
|
|
23
|
+
operator?: string;
|
|
24
|
+
itemRender?: any;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface EzGridFiltersRef {
|
|
28
|
+
_onFiltersChanged?: (snapshot: FilterSnapshot[] | null) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface EzGridFiltersConfig extends EzGridContainerConfig {
|
|
32
|
+
grid?: EzGridFiltersRef;
|
|
33
|
+
columns?: (() => NormalizedColumn[]) | NormalizedColumn[];
|
|
34
|
+
filterMode?: 'onInput' | 'onEnter';
|
|
35
|
+
debounce?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class EzGridFilters extends EzGridContainer {
|
|
39
|
+
declare config: EzGridFiltersConfig;
|
|
40
|
+
declare el: HTMLElement | null;
|
|
41
|
+
|
|
42
|
+
grid: EzGridFiltersRef | undefined;
|
|
43
|
+
columns: () => NormalizedColumn[];
|
|
44
|
+
private _values: Record<string, any>;
|
|
45
|
+
private _filterMode: 'onInput' | 'onEnter';
|
|
46
|
+
private _debounceMs: number;
|
|
47
|
+
private _debounceTimer: ReturnType<typeof setTimeout> | null;
|
|
48
|
+
|
|
49
|
+
constructor(config: EzGridFiltersConfig = {}) {
|
|
50
|
+
super(config);
|
|
51
|
+
|
|
52
|
+
this.grid = config.grid;
|
|
53
|
+
const cols = config.columns;
|
|
54
|
+
this.columns = typeof cols === 'function'
|
|
55
|
+
? cols
|
|
56
|
+
: () => (cols || []);
|
|
57
|
+
|
|
58
|
+
// Local, ephemeral filter values (not persisted)
|
|
59
|
+
this._values = {};
|
|
60
|
+
|
|
61
|
+
// Filter mode: 'onInput' (default) or 'onEnter'
|
|
62
|
+
// In remote mode, this is controlled by remote.filter config
|
|
63
|
+
this._filterMode = config.filterMode ?? 'onInput';
|
|
64
|
+
|
|
65
|
+
// Debounce config (default 300ms) - only used in onInput mode
|
|
66
|
+
this._debounceMs = config.debounce ?? 300;
|
|
67
|
+
this._debounceTimer = null;
|
|
68
|
+
|
|
69
|
+
this.config.cls = (this.config.cls || '') + ' ez-grid-filters';
|
|
70
|
+
this.config.layout = 'hbox';
|
|
71
|
+
|
|
72
|
+
this._buildFilters();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private _buildFilters(): void {
|
|
76
|
+
const columns = this.columns();
|
|
77
|
+
|
|
78
|
+
this.config.items = columns.map(col => {
|
|
79
|
+
const resolved = this._resolveFilter(col);
|
|
80
|
+
|
|
81
|
+
// Always occupy column space to keep alignment
|
|
82
|
+
// width / flex - same logic as EzGridCell
|
|
83
|
+
const baseCell: any = {
|
|
84
|
+
eztype: 'EzComponent',
|
|
85
|
+
cls: 'ez-grid-filter-cell',
|
|
86
|
+
flex: col.width != null ? undefined : (col.flex ?? 1),
|
|
87
|
+
style: col.width != null ? { width: `${col.width}px` } : undefined,
|
|
88
|
+
items: []
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// No filter → empty placeholder
|
|
92
|
+
if (!resolved.enabled) {
|
|
93
|
+
return baseCell;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const field = resolved.field!;
|
|
97
|
+
const operator = resolved.operator!;
|
|
98
|
+
|
|
99
|
+
// NOTE: Initialize proper default value based on operator
|
|
100
|
+
const defaultValue = this._getDefaultValue(operator);
|
|
101
|
+
|
|
102
|
+
// NOTE: Ensure _values[field] exists with correct type
|
|
103
|
+
if (this._values[field] === undefined) {
|
|
104
|
+
this._values[field] = defaultValue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const value = this._values[field];
|
|
108
|
+
|
|
109
|
+
// NOTE: setValue callback for custom itemRender
|
|
110
|
+
const setValue = (newValue: any) => {
|
|
111
|
+
this._values[field] = newValue;
|
|
112
|
+
this._emitSnapshot();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const ctx: FilterContext = {
|
|
116
|
+
grid: this.grid,
|
|
117
|
+
column: col,
|
|
118
|
+
value,
|
|
119
|
+
setValue,
|
|
120
|
+
field,
|
|
121
|
+
operator
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const isCustomRender = typeof resolved.itemRender === 'function';
|
|
125
|
+
|
|
126
|
+
let itemCfg = isCustomRender
|
|
127
|
+
? resolved.itemRender(ctx)
|
|
128
|
+
: { ...resolved.itemRender };
|
|
129
|
+
|
|
130
|
+
// WARNING:
|
|
131
|
+
// For custom itemRender, do NOT override attrs or handlers.
|
|
132
|
+
// Custom renders have full control via setValue callback.
|
|
133
|
+
if (!isCustomRender) {
|
|
134
|
+
itemCfg.attrs = {
|
|
135
|
+
...(itemCfg.attrs || {}),
|
|
136
|
+
placeholder: col.text ?? '',
|
|
137
|
+
value
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Handler to update local value
|
|
141
|
+
const updateValue = (e: Event) => {
|
|
142
|
+
const newValue = (e?.target as HTMLInputElement)?.value ?? '';
|
|
143
|
+
|
|
144
|
+
if (newValue === '' || newValue == null) {
|
|
145
|
+
delete this._values[field];
|
|
146
|
+
} else {
|
|
147
|
+
this._values[field] = newValue;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
if (this._filterMode === 'onEnter') {
|
|
152
|
+
// onEnter mode: only emit on Enter key
|
|
153
|
+
itemCfg.onInput = updateValue;
|
|
154
|
+
itemCfg.onChange = updateValue;
|
|
155
|
+
|
|
156
|
+
// Use _ezAfterRender to bind keydown since native inputs don't auto-bind onKeyDown
|
|
157
|
+
itemCfg._ezAfterRender = (el: HTMLInputElement) => {
|
|
158
|
+
el.addEventListener('keydown', (e: KeyboardEvent) => {
|
|
159
|
+
if (e.key === 'Enter') {
|
|
160
|
+
updateValue(e);
|
|
161
|
+
this._doEmitSnapshot(); // Direct emit, no debounce
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
} else {
|
|
166
|
+
// onInput mode: emit on every change (with debounce)
|
|
167
|
+
const handler = (e: Event) => {
|
|
168
|
+
updateValue(e);
|
|
169
|
+
this._emitSnapshot();
|
|
170
|
+
};
|
|
171
|
+
itemCfg.onInput = handler;
|
|
172
|
+
itemCfg.onChange = handler;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
baseCell.items.push(itemCfg);
|
|
177
|
+
|
|
178
|
+
return baseCell;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private _getDefaultValue(operator: string): any {
|
|
183
|
+
// NOTE: 'between' operator expects array of two values
|
|
184
|
+
if (operator === 'between') {
|
|
185
|
+
return [null, null];
|
|
186
|
+
}
|
|
187
|
+
return '';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private _resolveFilter(col: NormalizedColumn): ResolvedFilter {
|
|
191
|
+
const raw = col.filter;
|
|
192
|
+
|
|
193
|
+
// No filter defined
|
|
194
|
+
if (raw == null) {
|
|
195
|
+
return { enabled: false };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Empty object (from filter: true) → default '='
|
|
199
|
+
if (!raw.operator && !raw.itemRender) {
|
|
200
|
+
return {
|
|
201
|
+
enabled: true,
|
|
202
|
+
field: col.index,
|
|
203
|
+
operator: '=',
|
|
204
|
+
itemRender: {
|
|
205
|
+
eztype: 'input'
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// filter: { operator, itemRender } - already normalized from EzGridNormalizers
|
|
211
|
+
return {
|
|
212
|
+
enabled: true,
|
|
213
|
+
field: col.index,
|
|
214
|
+
operator: raw.operator ?? '=',
|
|
215
|
+
itemRender: raw.itemRender ?? {
|
|
216
|
+
eztype: 'input'
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private _emitSnapshot(): void {
|
|
222
|
+
// Clear existing debounce timer
|
|
223
|
+
if (this._debounceTimer) {
|
|
224
|
+
clearTimeout(this._debounceTimer);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Debounce the actual emit
|
|
228
|
+
this._debounceTimer = setTimeout(() => {
|
|
229
|
+
this._doEmitSnapshot();
|
|
230
|
+
}, this._debounceMs);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private _doEmitSnapshot(): void {
|
|
234
|
+
const snapshot: FilterSnapshot[] = Object.keys(this._values).map(field => {
|
|
235
|
+
const value = this._values[field];
|
|
236
|
+
|
|
237
|
+
// Skip empty values
|
|
238
|
+
if (value === '' || value == null) return null;
|
|
239
|
+
|
|
240
|
+
// Skip empty arrays (for 'between' operator)
|
|
241
|
+
if (Array.isArray(value) && value.every(v => v == null || v === '')) return null;
|
|
242
|
+
|
|
243
|
+
const col = this.columns().find(c => c.index === field);
|
|
244
|
+
if (!col) return null;
|
|
245
|
+
|
|
246
|
+
const resolved = this._resolveFilter(col);
|
|
247
|
+
if (!resolved.enabled) return null;
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
field,
|
|
251
|
+
operator: resolved.operator!,
|
|
252
|
+
value
|
|
253
|
+
};
|
|
254
|
+
}).filter((item): item is FilterSnapshot => item !== null);
|
|
255
|
+
|
|
256
|
+
this.grid?._onFiltersChanged?.(
|
|
257
|
+
snapshot.length ? snapshot : null
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
clear(): void {
|
|
262
|
+
this._values = {};
|
|
263
|
+
this._rebuildUI();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
refresh(): void {
|
|
267
|
+
this._rebuildUI();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private async _rebuildUI(): Promise<void> {
|
|
271
|
+
this._buildFilters();
|
|
272
|
+
|
|
273
|
+
if (this.el) {
|
|
274
|
+
this.el.innerHTML = '';
|
|
275
|
+
|
|
276
|
+
const children = await Promise.all(
|
|
277
|
+
(this.config.items || []).map(item => ez._createElement(item))
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
for (const child of children) {
|
|
281
|
+
if (child) this.el.appendChild(child);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// ==========================================================
|
|
2
|
+
// EzGridFooter
|
|
3
|
+
// ==========================================================
|
|
4
|
+
|
|
5
|
+
.ez-grid {
|
|
6
|
+
.ez-grid-footer {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
border-top: 1px solid var(--ez-grid-border);
|
|
10
|
+
background-color: var(--ez-grid-surface);
|
|
11
|
+
|
|
12
|
+
font-size: var(--ez-grid-font-size);
|
|
13
|
+
font-weight: var(--ez-grid-font-weight-medium);
|
|
14
|
+
color: var(--ez-grid-text-secondary);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ----------------------------------------------------------
|
|
18
|
+
// Stats row: column summaries
|
|
19
|
+
// ----------------------------------------------------------
|
|
20
|
+
.ez-grid-footer-stats {
|
|
21
|
+
display: flex;
|
|
22
|
+
border-bottom: 1px solid var(--ez-grid-border-light);
|
|
23
|
+
background-color: var(--ez-grid-surface-hover);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.ez-grid-footer-stat-cell {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
padding: 6px 12px;
|
|
30
|
+
min-height: 32px;
|
|
31
|
+
box-sizing: border-box;
|
|
32
|
+
|
|
33
|
+
font-size: calc(var(--ez-grid-font-size) - 1px);
|
|
34
|
+
font-weight: var(--ez-grid-font-weight-semibold);
|
|
35
|
+
color: var(--ez-grid-text);
|
|
36
|
+
|
|
37
|
+
white-space: nowrap;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
text-overflow: ellipsis;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ----------------------------------------------------------
|
|
43
|
+
// Pagination row
|
|
44
|
+
// ----------------------------------------------------------
|
|
45
|
+
.ez-grid-footer-pagination {
|
|
46
|
+
display: flex;
|
|
47
|
+
min-height: var(--ez-grid-header-height);
|
|
48
|
+
align-items: center;
|
|
49
|
+
padding: 0 12px;
|
|
50
|
+
gap: 16px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ----------------------------------------------------------
|
|
54
|
+
// Page info: "1 - 25 of 100"
|
|
55
|
+
// ----------------------------------------------------------
|
|
56
|
+
.ez-grid-footer-info {
|
|
57
|
+
white-space: nowrap;
|
|
58
|
+
color: var(--ez-grid-text);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ----------------------------------------------------------
|
|
62
|
+
// Page size selector
|
|
63
|
+
// ----------------------------------------------------------
|
|
64
|
+
.ez-grid-footer-pagesize {
|
|
65
|
+
align-items: center;
|
|
66
|
+
gap: 8px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.ez-grid-footer-pagesize-label {
|
|
70
|
+
color: var(--ez-grid-text-muted);
|
|
71
|
+
white-space: nowrap;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ----------------------------------------------------------
|
|
75
|
+
// Navigation buttons
|
|
76
|
+
// ----------------------------------------------------------
|
|
77
|
+
.ez-grid-footer-nav {
|
|
78
|
+
align-items: center;
|
|
79
|
+
gap: 4px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.ez-grid-footer-nav-btn {
|
|
83
|
+
display: inline-flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
min-width: 32px;
|
|
87
|
+
height: 32px;
|
|
88
|
+
padding: 0 8px;
|
|
89
|
+
|
|
90
|
+
font-size: 1rem;
|
|
91
|
+
font-weight: var(--ez-grid-font-weight-medium);
|
|
92
|
+
color: var(--ez-grid-text-secondary);
|
|
93
|
+
|
|
94
|
+
background: var(--ez-grid-bg);
|
|
95
|
+
border: 1px solid var(--ez-grid-border);
|
|
96
|
+
border-radius: var(--ez-grid-radius-sm);
|
|
97
|
+
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
transition: all 0.15s ease;
|
|
100
|
+
|
|
101
|
+
&:hover:not(:disabled) {
|
|
102
|
+
background: var(--ez-grid-surface-hover);
|
|
103
|
+
border-color: var(--ez-grid-text-muted);
|
|
104
|
+
color: var(--ez-grid-text);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
&:active:not(:disabled) {
|
|
108
|
+
background: var(--ez-grid-surface-active);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
&:disabled {
|
|
112
|
+
color: var(--ez-grid-border);
|
|
113
|
+
cursor: not-allowed;
|
|
114
|
+
background: var(--ez-grid-surface);
|
|
115
|
+
border-color: var(--ez-grid-border-light);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ----------------------------------------------------------
|
|
120
|
+
// Page indicator: "1 / 5"
|
|
121
|
+
// ----------------------------------------------------------
|
|
122
|
+
.ez-grid-footer-page-indicator {
|
|
123
|
+
padding: 0 8px;
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
min-width: 48px;
|
|
126
|
+
text-align: center;
|
|
127
|
+
color: var(--ez-grid-text);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ----------------------------------------------------------
|
|
131
|
+
// Reload button (separated from pagination)
|
|
132
|
+
// ----------------------------------------------------------
|
|
133
|
+
.ez-grid-footer-reload-btn {
|
|
134
|
+
margin-left: 8px;
|
|
135
|
+
}
|
|
136
|
+
}
|