@techsio/ui-kit 0.37.1 → 0.38.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/dist/organisms/data-table.fields.js +720 -0
- package/dist/organisms/data-table.helpers.js +168 -0
- package/dist/organisms/data-table.js +1736 -0
- package/dist/organisms/table.js +7 -3
- package/dist/src/molecules/switch.d.ts +3 -3
- package/dist/src/molecules/toast.d.ts +3 -3
- package/dist/src/organisms/data-table.d.ts +357 -0
- package/dist/src/organisms/data-table.d.ts.map +1 -0
- package/dist/src/organisms/data-table.fields.d.ts +119 -0
- package/dist/src/organisms/data-table.fields.d.ts.map +1 -0
- package/dist/src/organisms/data-table.helpers.d.ts +240 -0
- package/dist/src/organisms/data-table.helpers.d.ts.map +1 -0
- package/dist/src/organisms/table.d.ts +15 -7
- package/dist/src/organisms/table.d.ts.map +1 -1
- package/dist/stories/changelog/changelog.stories.d.ts.map +1 -1
- package/dist/stories/organisms/data-table.stories.d.ts +145 -0
- package/dist/stories/organisms/data-table.stories.d.ts.map +1 -0
- package/dist/stories/organisms/table.stories.d.ts +7 -0
- package/dist/stories/organisms/table.stories.d.ts.map +1 -1
- package/package.json +7 -1
- package/src/tokens/components/components.css +1 -0
- package/src/tokens/components/organisms/_data-table.css +51 -0
|
@@ -0,0 +1,720 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ActionIcon } from "../atoms/action-icon.js";
|
|
3
|
+
import { Input } from "../atoms/input.js";
|
|
4
|
+
import { NumericInput } from "../atoms/numeric-input.js";
|
|
5
|
+
import { Combobox } from "../molecules/combobox.js";
|
|
6
|
+
import { Menu } from "../molecules/menu.js";
|
|
7
|
+
import { Select } from "../molecules/select.js";
|
|
8
|
+
import { Switch } from "../molecules/switch.js";
|
|
9
|
+
const isBlank = (v)=>null == v || "" === v;
|
|
10
|
+
const TEXT_FILTER_OPERATORS = [
|
|
11
|
+
{
|
|
12
|
+
label: "Contains",
|
|
13
|
+
value: "contains"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
label: "Does not contain",
|
|
17
|
+
value: "notContains"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
label: "Equals",
|
|
21
|
+
value: "equals"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: "Does not equal",
|
|
25
|
+
value: "notEquals"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: "Starts with",
|
|
29
|
+
value: "startsWith"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: "Ends with",
|
|
33
|
+
value: "endsWith"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: "Is empty",
|
|
37
|
+
value: "empty"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: "Is not empty",
|
|
41
|
+
value: "notEmpty"
|
|
42
|
+
}
|
|
43
|
+
];
|
|
44
|
+
const NUMBER_FILTER_OPERATORS = [
|
|
45
|
+
{
|
|
46
|
+
label: "=",
|
|
47
|
+
value: "equals"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
label: "≠",
|
|
51
|
+
value: "notEquals"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
label: ">",
|
|
55
|
+
value: "gt"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: "≥",
|
|
59
|
+
value: "gte"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
label: "<",
|
|
63
|
+
value: "lt"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
label: "≤",
|
|
67
|
+
value: "lte"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
label: "Between",
|
|
71
|
+
value: "between"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
label: "Is empty",
|
|
75
|
+
value: "empty"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
label: "Is not empty",
|
|
79
|
+
value: "notEmpty"
|
|
80
|
+
}
|
|
81
|
+
];
|
|
82
|
+
const TEXT_OPS = TEXT_FILTER_OPERATORS;
|
|
83
|
+
const NUMBER_OPS = NUMBER_FILTER_OPERATORS;
|
|
84
|
+
const BOOLEAN_FILTER_ITEMS = [
|
|
85
|
+
{
|
|
86
|
+
label: "All",
|
|
87
|
+
value: ""
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: "Yes",
|
|
91
|
+
value: "true"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
label: "No",
|
|
95
|
+
value: "false"
|
|
96
|
+
}
|
|
97
|
+
];
|
|
98
|
+
const HHMM_RE = /^(\d{1,2}):(\d{2})/;
|
|
99
|
+
const toSelectItems = (options)=>options.map((o)=>({
|
|
100
|
+
label: o.label,
|
|
101
|
+
value: o.value
|
|
102
|
+
}));
|
|
103
|
+
function columnLabel(column) {
|
|
104
|
+
const header = column.columnDef.header;
|
|
105
|
+
return "string" == typeof header && header ? header : column.id;
|
|
106
|
+
}
|
|
107
|
+
function selectMinWidthCh(items, placeholder) {
|
|
108
|
+
const longest = items.reduce((max, item)=>Math.max(max, String(item.label ?? item.value).length), placeholder?.length ?? 0);
|
|
109
|
+
return `${longest + 7}ch`;
|
|
110
|
+
}
|
|
111
|
+
function FieldSelect({ items, value, ariaLabel, placeholder, disabled, size = "sm", invalid, onChange }) {
|
|
112
|
+
return /*#__PURE__*/ jsx("div", {
|
|
113
|
+
style: {
|
|
114
|
+
minWidth: selectMinWidthCh(items, placeholder)
|
|
115
|
+
},
|
|
116
|
+
children: /*#__PURE__*/ jsxs(Select, {
|
|
117
|
+
disabled: disabled,
|
|
118
|
+
items: items,
|
|
119
|
+
onValueChange: (d)=>onChange(d.value[0] ?? ""),
|
|
120
|
+
size: size,
|
|
121
|
+
validateStatus: invalid ? "error" : "default",
|
|
122
|
+
value: void 0 === value ? void 0 : [
|
|
123
|
+
value
|
|
124
|
+
],
|
|
125
|
+
children: [
|
|
126
|
+
/*#__PURE__*/ jsx(Select.Control, {
|
|
127
|
+
children: /*#__PURE__*/ jsx(Select.Trigger, {
|
|
128
|
+
"aria-label": ariaLabel,
|
|
129
|
+
children: /*#__PURE__*/ jsx(Select.ValueText, {
|
|
130
|
+
placeholder: placeholder
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
}),
|
|
134
|
+
/*#__PURE__*/ jsx(Select.Positioner, {
|
|
135
|
+
children: /*#__PURE__*/ jsx(Select.Content, {
|
|
136
|
+
children: items.map((item)=>/*#__PURE__*/ jsxs(Select.Item, {
|
|
137
|
+
item: item,
|
|
138
|
+
children: [
|
|
139
|
+
/*#__PURE__*/ jsx(Select.ItemText, {}),
|
|
140
|
+
/*#__PURE__*/ jsx(Select.ItemIndicator, {})
|
|
141
|
+
]
|
|
142
|
+
}, item.value))
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
]
|
|
146
|
+
})
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function FilterConditionMenu({ operators, operatorLabels, value, onChange, disabled, size, columnName }) {
|
|
150
|
+
const labelled = operators.map((o)=>({
|
|
151
|
+
...o,
|
|
152
|
+
label: operatorLabels?.[o.value] ?? o.label
|
|
153
|
+
}));
|
|
154
|
+
const active = labelled.find((o)=>o.value === value);
|
|
155
|
+
return /*#__PURE__*/ jsx(Menu, {
|
|
156
|
+
"aria-label": `Filter condition for ${columnName}`,
|
|
157
|
+
customTrigger: /*#__PURE__*/ jsx(ActionIcon, {
|
|
158
|
+
"aria-label": `Filter condition for ${columnName}: ${active?.label ?? value}`,
|
|
159
|
+
disabled: disabled,
|
|
160
|
+
icon: "icon-[mdi--filter-variant]",
|
|
161
|
+
size: size,
|
|
162
|
+
tone: "neutral"
|
|
163
|
+
}),
|
|
164
|
+
items: labelled.map((o)=>({
|
|
165
|
+
type: "radio",
|
|
166
|
+
value: o.value,
|
|
167
|
+
label: o.label,
|
|
168
|
+
name: `filter-operator-${columnName}`,
|
|
169
|
+
checked: o.value === value
|
|
170
|
+
})),
|
|
171
|
+
onSelect: (d)=>onChange(d.value),
|
|
172
|
+
size: size
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const DEFAULT_FILTER_RENDERERS = {
|
|
176
|
+
string: ({ column, value, setValue, disabled, size, operatorLabels })=>{
|
|
177
|
+
const v = value ?? {};
|
|
178
|
+
const operator = v.operator ?? "contains";
|
|
179
|
+
const activeLabel = operatorLabels?.[operator] ?? TEXT_OPS.find((o)=>o.value === operator)?.label;
|
|
180
|
+
const needsValue = "empty" !== operator && "notEmpty" !== operator;
|
|
181
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
182
|
+
children: [
|
|
183
|
+
/*#__PURE__*/ jsx(Input, {
|
|
184
|
+
"aria-label": `Filter value for ${columnLabel(column)}`,
|
|
185
|
+
className: "flex-1",
|
|
186
|
+
disabled: disabled || !needsValue,
|
|
187
|
+
onChange: (e)=>setValue({
|
|
188
|
+
...v,
|
|
189
|
+
operator,
|
|
190
|
+
value: e.target.value
|
|
191
|
+
}),
|
|
192
|
+
placeholder: needsValue ? "Value" : activeLabel,
|
|
193
|
+
size: size,
|
|
194
|
+
value: needsValue ? v.value ?? "" : ""
|
|
195
|
+
}),
|
|
196
|
+
/*#__PURE__*/ jsx(FilterConditionMenu, {
|
|
197
|
+
columnName: columnLabel(column),
|
|
198
|
+
disabled: disabled,
|
|
199
|
+
onChange: (op)=>setValue({
|
|
200
|
+
...v,
|
|
201
|
+
operator: op
|
|
202
|
+
}),
|
|
203
|
+
operatorLabels: operatorLabels,
|
|
204
|
+
operators: TEXT_OPS,
|
|
205
|
+
size: size,
|
|
206
|
+
value: operator
|
|
207
|
+
})
|
|
208
|
+
]
|
|
209
|
+
});
|
|
210
|
+
},
|
|
211
|
+
int: (ctx)=>DEFAULT_FILTER_RENDERERS.number(ctx),
|
|
212
|
+
number: ({ column, value, setValue, disabled, size, operatorLabels })=>{
|
|
213
|
+
const v = value ?? {};
|
|
214
|
+
const operator = v.operator ?? "equals";
|
|
215
|
+
const needsValue = "empty" !== operator && "notEmpty" !== operator;
|
|
216
|
+
const activeLabel = operatorLabels?.[operator] ?? NUMBER_FILTER_OPERATORS.find((o)=>o.value === operator)?.label;
|
|
217
|
+
let valuePlaceholder = activeLabel;
|
|
218
|
+
if (needsValue) valuePlaceholder = "between" === operator ? "From" : "Value";
|
|
219
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
220
|
+
children: [
|
|
221
|
+
/*#__PURE__*/ jsx(Input, {
|
|
222
|
+
"aria-label": `Filter value for ${columnLabel(column)}`,
|
|
223
|
+
className: "flex-1",
|
|
224
|
+
disabled: disabled || !needsValue,
|
|
225
|
+
onChange: (e)=>setValue({
|
|
226
|
+
...v,
|
|
227
|
+
operator,
|
|
228
|
+
value: e.target.value
|
|
229
|
+
}),
|
|
230
|
+
placeholder: valuePlaceholder,
|
|
231
|
+
size: size,
|
|
232
|
+
type: needsValue ? "number" : "text",
|
|
233
|
+
value: needsValue ? v.value ?? "" : ""
|
|
234
|
+
}),
|
|
235
|
+
"between" === operator && /*#__PURE__*/ jsx(Input, {
|
|
236
|
+
"aria-label": `Filter upper bound for ${columnLabel(column)}`,
|
|
237
|
+
className: "flex-1",
|
|
238
|
+
disabled: disabled,
|
|
239
|
+
onChange: (e)=>setValue({
|
|
240
|
+
...v,
|
|
241
|
+
operator,
|
|
242
|
+
to: e.target.value
|
|
243
|
+
}),
|
|
244
|
+
placeholder: "To",
|
|
245
|
+
size: size,
|
|
246
|
+
type: "number",
|
|
247
|
+
value: v.to ?? ""
|
|
248
|
+
}),
|
|
249
|
+
/*#__PURE__*/ jsx(FilterConditionMenu, {
|
|
250
|
+
columnName: columnLabel(column),
|
|
251
|
+
disabled: disabled,
|
|
252
|
+
onChange: (op)=>setValue("between" === op ? {
|
|
253
|
+
...v,
|
|
254
|
+
operator: op
|
|
255
|
+
} : {
|
|
256
|
+
operator: op,
|
|
257
|
+
value: v.value
|
|
258
|
+
}),
|
|
259
|
+
operatorLabels: operatorLabels,
|
|
260
|
+
operators: NUMBER_OPS,
|
|
261
|
+
size: size,
|
|
262
|
+
value: operator
|
|
263
|
+
})
|
|
264
|
+
]
|
|
265
|
+
});
|
|
266
|
+
},
|
|
267
|
+
boolean: ({ column, value, setValue, disabled, size })=>{
|
|
268
|
+
const v = value ?? {};
|
|
269
|
+
const current = void 0 === v.value ? "" : String(v.value);
|
|
270
|
+
return /*#__PURE__*/ jsx(FieldSelect, {
|
|
271
|
+
ariaLabel: `Filter ${columnLabel(column)}`,
|
|
272
|
+
disabled: disabled,
|
|
273
|
+
items: BOOLEAN_FILTER_ITEMS,
|
|
274
|
+
onChange: (next)=>setValue("" === next ? void 0 : {
|
|
275
|
+
value: "true" === next
|
|
276
|
+
}),
|
|
277
|
+
placeholder: "All",
|
|
278
|
+
size: size,
|
|
279
|
+
value: current
|
|
280
|
+
});
|
|
281
|
+
},
|
|
282
|
+
enum: ({ column, value, setValue, disabled, options, size })=>{
|
|
283
|
+
const v = value ?? {};
|
|
284
|
+
const current = v.values?.[0] ?? "";
|
|
285
|
+
return /*#__PURE__*/ jsx(FieldSelect, {
|
|
286
|
+
ariaLabel: `Filter ${columnLabel(column)}`,
|
|
287
|
+
disabled: disabled,
|
|
288
|
+
items: [
|
|
289
|
+
{
|
|
290
|
+
label: "All",
|
|
291
|
+
value: ""
|
|
292
|
+
},
|
|
293
|
+
...toSelectItems(options)
|
|
294
|
+
],
|
|
295
|
+
onChange: (next)=>setValue(next ? {
|
|
296
|
+
values: [
|
|
297
|
+
next
|
|
298
|
+
]
|
|
299
|
+
} : void 0),
|
|
300
|
+
placeholder: "All",
|
|
301
|
+
size: size,
|
|
302
|
+
value: current
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
multiEnum: ({ column, value, setValue, disabled, options, size })=>{
|
|
306
|
+
const v = value ?? {};
|
|
307
|
+
return /*#__PURE__*/ jsx(Combobox, {
|
|
308
|
+
disabled: disabled,
|
|
309
|
+
items: options,
|
|
310
|
+
multiple: true,
|
|
311
|
+
onChange: (next)=>{
|
|
312
|
+
const arr = Array.isArray(next) ? next : [
|
|
313
|
+
next
|
|
314
|
+
].filter(Boolean);
|
|
315
|
+
setValue(arr.length ? {
|
|
316
|
+
values: arr
|
|
317
|
+
} : void 0);
|
|
318
|
+
},
|
|
319
|
+
placeholder: `Filter ${columnLabel(column)}`,
|
|
320
|
+
size: size,
|
|
321
|
+
value: v.values ?? []
|
|
322
|
+
});
|
|
323
|
+
},
|
|
324
|
+
date: ({ column, value, setValue, disabled, size })=>{
|
|
325
|
+
const v = value ?? {};
|
|
326
|
+
return /*#__PURE__*/ jsx(Input, {
|
|
327
|
+
"aria-label": `Filter ${columnLabel(column)}`,
|
|
328
|
+
disabled: disabled,
|
|
329
|
+
onChange: (e)=>setValue(e.target.value ? {
|
|
330
|
+
from: e.target.value,
|
|
331
|
+
to: e.target.value
|
|
332
|
+
} : void 0),
|
|
333
|
+
size: size,
|
|
334
|
+
type: "date",
|
|
335
|
+
value: v.from ?? ""
|
|
336
|
+
});
|
|
337
|
+
},
|
|
338
|
+
datetime: ({ column, value, setValue, disabled, size })=>{
|
|
339
|
+
const v = value ?? {};
|
|
340
|
+
return /*#__PURE__*/ jsx(Input, {
|
|
341
|
+
"aria-label": `Filter ${columnLabel(column)}`,
|
|
342
|
+
disabled: disabled,
|
|
343
|
+
onChange: (e)=>setValue(e.target.value ? {
|
|
344
|
+
from: e.target.value
|
|
345
|
+
} : void 0),
|
|
346
|
+
size: size,
|
|
347
|
+
type: "datetime-local",
|
|
348
|
+
value: v.from ?? ""
|
|
349
|
+
});
|
|
350
|
+
},
|
|
351
|
+
time: ({ column, value, setValue, disabled, size })=>{
|
|
352
|
+
const v = value ?? {};
|
|
353
|
+
const patch = (next)=>setValue(next.from || next.to ? next : void 0);
|
|
354
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
355
|
+
children: [
|
|
356
|
+
/*#__PURE__*/ jsx(Input, {
|
|
357
|
+
"aria-label": `Filter ${columnLabel(column)} from`,
|
|
358
|
+
disabled: disabled,
|
|
359
|
+
onChange: (e)=>patch({
|
|
360
|
+
...v,
|
|
361
|
+
from: e.target.value
|
|
362
|
+
}),
|
|
363
|
+
size: size,
|
|
364
|
+
type: "time",
|
|
365
|
+
value: v.from ?? ""
|
|
366
|
+
}),
|
|
367
|
+
/*#__PURE__*/ jsx(Input, {
|
|
368
|
+
"aria-label": `Filter ${columnLabel(column)} to`,
|
|
369
|
+
disabled: disabled,
|
|
370
|
+
onChange: (e)=>patch({
|
|
371
|
+
...v,
|
|
372
|
+
to: e.target.value
|
|
373
|
+
}),
|
|
374
|
+
size: size,
|
|
375
|
+
type: "time",
|
|
376
|
+
value: v.to ?? ""
|
|
377
|
+
})
|
|
378
|
+
]
|
|
379
|
+
});
|
|
380
|
+
},
|
|
381
|
+
dateRange: ({ column, value, setValue, disabled, size })=>{
|
|
382
|
+
const v = value ?? {};
|
|
383
|
+
const patch = (next)=>setValue(next.from || next.to ? next : void 0);
|
|
384
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
385
|
+
children: [
|
|
386
|
+
/*#__PURE__*/ jsx(Input, {
|
|
387
|
+
"aria-label": `Filter ${columnLabel(column)} from`,
|
|
388
|
+
disabled: disabled,
|
|
389
|
+
onChange: (e)=>patch({
|
|
390
|
+
...v,
|
|
391
|
+
from: e.target.value
|
|
392
|
+
}),
|
|
393
|
+
size: size,
|
|
394
|
+
type: "date",
|
|
395
|
+
value: v.from ?? ""
|
|
396
|
+
}),
|
|
397
|
+
/*#__PURE__*/ jsx(Input, {
|
|
398
|
+
"aria-label": `Filter ${columnLabel(column)} to`,
|
|
399
|
+
disabled: disabled,
|
|
400
|
+
min: v.from || void 0,
|
|
401
|
+
onChange: (e)=>patch({
|
|
402
|
+
...v,
|
|
403
|
+
to: e.target.value
|
|
404
|
+
}),
|
|
405
|
+
size: size,
|
|
406
|
+
type: "date",
|
|
407
|
+
value: v.to ?? ""
|
|
408
|
+
})
|
|
409
|
+
]
|
|
410
|
+
});
|
|
411
|
+
},
|
|
412
|
+
custom: ()=>null
|
|
413
|
+
};
|
|
414
|
+
const editorKeyHandlers = (commit, cancel)=>({
|
|
415
|
+
onKeyDown: (e)=>{
|
|
416
|
+
if ("Enter" === e.key) {
|
|
417
|
+
e.preventDefault();
|
|
418
|
+
commit();
|
|
419
|
+
} else if ("Escape" === e.key) {
|
|
420
|
+
e.preventDefault();
|
|
421
|
+
cancel();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
function dateLikeEditor(inputType) {
|
|
426
|
+
return ({ column, value, setValue, disabled, error, commit, cancel, size, errorId })=>/*#__PURE__*/ jsx(Input, {
|
|
427
|
+
"aria-describedby": error ? errorId : void 0,
|
|
428
|
+
"aria-invalid": error ? true : void 0,
|
|
429
|
+
"aria-label": `Edit ${columnLabel(column)}`,
|
|
430
|
+
disabled: disabled,
|
|
431
|
+
onChange: (e)=>setValue(e.target.value),
|
|
432
|
+
size: size,
|
|
433
|
+
type: inputType,
|
|
434
|
+
value: value ?? "",
|
|
435
|
+
...editorKeyHandlers(commit, cancel)
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
const DEFAULT_EDITOR_RENDERERS = {
|
|
439
|
+
string: ({ column, value, setValue, disabled, error, commit, cancel, size, errorId })=>/*#__PURE__*/ jsx(Input, {
|
|
440
|
+
"aria-describedby": error ? errorId : void 0,
|
|
441
|
+
"aria-invalid": error ? true : void 0,
|
|
442
|
+
"aria-label": `Edit ${columnLabel(column)}`,
|
|
443
|
+
disabled: disabled,
|
|
444
|
+
onChange: (e)=>setValue(e.target.value),
|
|
445
|
+
size: size,
|
|
446
|
+
value: value ?? "",
|
|
447
|
+
...editorKeyHandlers(commit, cancel)
|
|
448
|
+
}),
|
|
449
|
+
int: (ctx)=>DEFAULT_EDITOR_RENDERERS.number(ctx),
|
|
450
|
+
number: ({ column, value, setValue, disabled, commit, cancel, size, error, errorId })=>/*#__PURE__*/ jsx(NumericInput, {
|
|
451
|
+
describedBy: error ? errorId : void 0,
|
|
452
|
+
disabled: disabled,
|
|
453
|
+
invalid: !!error,
|
|
454
|
+
onChange: (next)=>setValue(Number.isNaN(next) ? void 0 : next),
|
|
455
|
+
size: size,
|
|
456
|
+
value: "number" != typeof value || Number.isNaN(value) ? void 0 : value,
|
|
457
|
+
...editorKeyHandlers(commit, cancel),
|
|
458
|
+
children: /*#__PURE__*/ jsxs(NumericInput.Control, {
|
|
459
|
+
children: [
|
|
460
|
+
/*#__PURE__*/ jsx(NumericInput.Input, {
|
|
461
|
+
"aria-invalid": error ? true : void 0,
|
|
462
|
+
"aria-label": `Edit ${columnLabel(column)}`
|
|
463
|
+
}),
|
|
464
|
+
/*#__PURE__*/ jsxs(NumericInput.TriggerContainer, {
|
|
465
|
+
children: [
|
|
466
|
+
/*#__PURE__*/ jsx(NumericInput.IncrementTrigger, {}),
|
|
467
|
+
/*#__PURE__*/ jsx(NumericInput.DecrementTrigger, {})
|
|
468
|
+
]
|
|
469
|
+
})
|
|
470
|
+
]
|
|
471
|
+
})
|
|
472
|
+
}),
|
|
473
|
+
boolean: ({ column, value, setValue, disabled, error })=>/*#__PURE__*/ jsx(Switch, {
|
|
474
|
+
checked: Boolean(value),
|
|
475
|
+
disabled: disabled,
|
|
476
|
+
onCheckedChange: setValue,
|
|
477
|
+
validateStatus: error ? "error" : "default",
|
|
478
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
479
|
+
className: "sr-only",
|
|
480
|
+
children: `Edit ${columnLabel(column)}`
|
|
481
|
+
})
|
|
482
|
+
}),
|
|
483
|
+
enum: ({ column, value, setValue, disabled, options, error, size })=>/*#__PURE__*/ jsx(FieldSelect, {
|
|
484
|
+
ariaLabel: `Edit ${columnLabel(column)}`,
|
|
485
|
+
disabled: disabled,
|
|
486
|
+
invalid: !!error,
|
|
487
|
+
items: toSelectItems(options),
|
|
488
|
+
onChange: setValue,
|
|
489
|
+
size: size,
|
|
490
|
+
value: value ?? ""
|
|
491
|
+
}),
|
|
492
|
+
multiEnum: ({ column, value, setValue, disabled, options, error, size })=>/*#__PURE__*/ jsx(Combobox, {
|
|
493
|
+
disabled: disabled,
|
|
494
|
+
items: options,
|
|
495
|
+
multiple: true,
|
|
496
|
+
onChange: (next)=>setValue(Array.isArray(next) ? next : [
|
|
497
|
+
next
|
|
498
|
+
]),
|
|
499
|
+
placeholder: `Edit ${columnLabel(column)}`,
|
|
500
|
+
size: size,
|
|
501
|
+
validateStatus: error ? "error" : "default",
|
|
502
|
+
value: value ?? []
|
|
503
|
+
}),
|
|
504
|
+
date: dateLikeEditor("date"),
|
|
505
|
+
datetime: dateLikeEditor("datetime-local"),
|
|
506
|
+
time: dateLikeEditor("time"),
|
|
507
|
+
dateRange: ({ column, value, setValue, disabled, error, errorId, commit, cancel, size })=>{
|
|
508
|
+
const v = value ?? {};
|
|
509
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
510
|
+
children: [
|
|
511
|
+
/*#__PURE__*/ jsx(Input, {
|
|
512
|
+
"aria-describedby": error ? errorId : void 0,
|
|
513
|
+
"aria-invalid": error ? true : void 0,
|
|
514
|
+
"aria-label": `Edit ${columnLabel(column)} from`,
|
|
515
|
+
disabled: disabled,
|
|
516
|
+
onChange: (e)=>setValue({
|
|
517
|
+
...v,
|
|
518
|
+
from: e.target.value
|
|
519
|
+
}),
|
|
520
|
+
size: size,
|
|
521
|
+
type: "date",
|
|
522
|
+
value: v.from ?? "",
|
|
523
|
+
...editorKeyHandlers(commit, cancel)
|
|
524
|
+
}),
|
|
525
|
+
/*#__PURE__*/ jsx(Input, {
|
|
526
|
+
"aria-describedby": error ? errorId : void 0,
|
|
527
|
+
"aria-invalid": error ? true : void 0,
|
|
528
|
+
"aria-label": `Edit ${columnLabel(column)} to`,
|
|
529
|
+
disabled: disabled,
|
|
530
|
+
min: v.from || void 0,
|
|
531
|
+
onChange: (e)=>setValue({
|
|
532
|
+
...v,
|
|
533
|
+
to: e.target.value
|
|
534
|
+
}),
|
|
535
|
+
size: size,
|
|
536
|
+
type: "date",
|
|
537
|
+
value: v.to ?? "",
|
|
538
|
+
...editorKeyHandlers(commit, cancel)
|
|
539
|
+
})
|
|
540
|
+
]
|
|
541
|
+
});
|
|
542
|
+
},
|
|
543
|
+
custom: ()=>null
|
|
544
|
+
};
|
|
545
|
+
function matchText(cell, f) {
|
|
546
|
+
const operator = f.operator ?? "contains";
|
|
547
|
+
if ("empty" === operator) return isBlank(cell);
|
|
548
|
+
if ("notEmpty" === operator) return !isBlank(cell);
|
|
549
|
+
if (isBlank(f.value)) return true;
|
|
550
|
+
const text = String(cell ?? "").toLowerCase();
|
|
551
|
+
const q = String(f.value).toLowerCase();
|
|
552
|
+
switch(operator){
|
|
553
|
+
case "equals":
|
|
554
|
+
return text === q;
|
|
555
|
+
case "notEquals":
|
|
556
|
+
return text !== q;
|
|
557
|
+
case "notContains":
|
|
558
|
+
return !text.includes(q);
|
|
559
|
+
case "startsWith":
|
|
560
|
+
return text.startsWith(q);
|
|
561
|
+
case "endsWith":
|
|
562
|
+
return text.endsWith(q);
|
|
563
|
+
default:
|
|
564
|
+
return text.includes(q);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
function matchBetween(n, cellHasNoNumber, f) {
|
|
568
|
+
let lo = Number(f.value);
|
|
569
|
+
let hi = Number(f.to);
|
|
570
|
+
const hasLo = !(isBlank(f.value) || Number.isNaN(lo));
|
|
571
|
+
const hasHi = !(isBlank(f.to) || Number.isNaN(hi));
|
|
572
|
+
if (!(hasLo || hasHi)) return true;
|
|
573
|
+
if (cellHasNoNumber) return false;
|
|
574
|
+
if (hasLo && hasHi && lo > hi) [lo, hi] = [
|
|
575
|
+
hi,
|
|
576
|
+
lo
|
|
577
|
+
];
|
|
578
|
+
if (hasLo && n < lo) return false;
|
|
579
|
+
return !(hasHi && n > hi);
|
|
580
|
+
}
|
|
581
|
+
function matchNumber(cell, f) {
|
|
582
|
+
const operator = f.operator ?? "equals";
|
|
583
|
+
if ("empty" === operator) return isBlank(cell);
|
|
584
|
+
if ("notEmpty" === operator) return !isBlank(cell);
|
|
585
|
+
const n = Number(cell);
|
|
586
|
+
const cellHasNoNumber = isBlank(cell) || Number.isNaN(n);
|
|
587
|
+
if ("between" === operator) return matchBetween(n, cellHasNoNumber, f);
|
|
588
|
+
if (isBlank(f.value)) return true;
|
|
589
|
+
const target = Number(f.value);
|
|
590
|
+
if (Number.isNaN(target)) return true;
|
|
591
|
+
if ("notEquals" === operator) return cellHasNoNumber || n !== target;
|
|
592
|
+
if (cellHasNoNumber) return false;
|
|
593
|
+
switch(operator){
|
|
594
|
+
case "gt":
|
|
595
|
+
return n > target;
|
|
596
|
+
case "gte":
|
|
597
|
+
return n >= target;
|
|
598
|
+
case "lt":
|
|
599
|
+
return n < target;
|
|
600
|
+
case "lte":
|
|
601
|
+
return n <= target;
|
|
602
|
+
default:
|
|
603
|
+
return n === target;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
const END_OF_DAY_MS = 86399999;
|
|
607
|
+
const DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
608
|
+
const time = (v)=>{
|
|
609
|
+
const raw = String(v);
|
|
610
|
+
const t = new Date(DATE_ONLY_RE.test(raw) ? `${raw}T00:00:00` : raw).getTime();
|
|
611
|
+
return Number.isNaN(t) ? void 0 : t;
|
|
612
|
+
};
|
|
613
|
+
const endOfBound = (v)=>{
|
|
614
|
+
const t = time(v);
|
|
615
|
+
if (void 0 === t) return;
|
|
616
|
+
return DATE_ONLY_RE.test(String(v)) ? t + END_OF_DAY_MS : t;
|
|
617
|
+
};
|
|
618
|
+
function matchRangeOverlap(cell, f) {
|
|
619
|
+
const cellFrom = time(cell.from) ?? -1 / 0;
|
|
620
|
+
const cellTo = cell.to ? endOfBound(cell.to) ?? 1 / 0 : 1 / 0;
|
|
621
|
+
const filterFrom = f.from ? time(f.from) ?? -1 / 0 : -1 / 0;
|
|
622
|
+
const filterTo = f.to ? endOfBound(f.to) ?? 1 / 0 : 1 / 0;
|
|
623
|
+
return cellFrom <= filterTo && cellTo >= filterFrom;
|
|
624
|
+
}
|
|
625
|
+
function matchDateRange(cell, f) {
|
|
626
|
+
if (isBlank(f.from) && isBlank(f.to)) return true;
|
|
627
|
+
if (isBlank(cell)) return false;
|
|
628
|
+
if ("object" == typeof cell && ("from" in cell || "to" in cell)) return matchRangeOverlap(cell, f);
|
|
629
|
+
const t = time(cell);
|
|
630
|
+
if (void 0 === t) return false;
|
|
631
|
+
return withinDateBounds(t, f);
|
|
632
|
+
}
|
|
633
|
+
function withinDateBounds(t, f) {
|
|
634
|
+
const from = f.from ? time(f.from) : void 0;
|
|
635
|
+
if (void 0 !== from && t < from) return false;
|
|
636
|
+
const to = f.to ? endOfBound(f.to) : void 0;
|
|
637
|
+
return !(void 0 !== to && t > to);
|
|
638
|
+
}
|
|
639
|
+
function toMinutes(value) {
|
|
640
|
+
if (isBlank(value)) return;
|
|
641
|
+
const s = String(value);
|
|
642
|
+
const hhmm = s.match(HHMM_RE);
|
|
643
|
+
if (hhmm) return 60 * Number(hhmm[1]) + Number(hhmm[2]);
|
|
644
|
+
const d = new Date(s);
|
|
645
|
+
return Number.isNaN(d.getTime()) ? void 0 : 60 * d.getHours() + d.getMinutes();
|
|
646
|
+
}
|
|
647
|
+
function matchTime(cell, f) {
|
|
648
|
+
const from = toMinutes(f.from);
|
|
649
|
+
const to = toMinutes(f.to);
|
|
650
|
+
if (void 0 === from && void 0 === to) return true;
|
|
651
|
+
const t = toMinutes(cell);
|
|
652
|
+
if (void 0 === t) return false;
|
|
653
|
+
if (void 0 !== from && void 0 !== to && from > to) return t >= from || t <= to;
|
|
654
|
+
if (void 0 !== from && t < from) return false;
|
|
655
|
+
if (void 0 !== to && t > to) return false;
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
function normalizeFilterValue(type, filterValue) {
|
|
659
|
+
if (Array.isArray(filterValue)) return {
|
|
660
|
+
values: filterValue.map(String)
|
|
661
|
+
};
|
|
662
|
+
if ("object" == typeof filterValue) return filterValue;
|
|
663
|
+
if ("enum" === type || "multiEnum" === type) return {
|
|
664
|
+
values: [
|
|
665
|
+
String(filterValue)
|
|
666
|
+
]
|
|
667
|
+
};
|
|
668
|
+
if ("boolean" === type) return {
|
|
669
|
+
value: true === filterValue || "true" === filterValue
|
|
670
|
+
};
|
|
671
|
+
if ("date" === type || "datetime" === type || "dateRange" === type || "time" === type) {
|
|
672
|
+
const bound = String(filterValue);
|
|
673
|
+
return {
|
|
674
|
+
from: bound,
|
|
675
|
+
to: bound
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
return {
|
|
679
|
+
value: String(filterValue)
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function typedFilterMatch(type, cell, rawFilterValue) {
|
|
683
|
+
if (null == rawFilterValue) return true;
|
|
684
|
+
const filterValue = normalizeFilterValue(type, rawFilterValue);
|
|
685
|
+
switch(type){
|
|
686
|
+
case "boolean":
|
|
687
|
+
{
|
|
688
|
+
const f = filterValue;
|
|
689
|
+
return void 0 === f.value ? true : Boolean(cell) === f.value;
|
|
690
|
+
}
|
|
691
|
+
case "enum":
|
|
692
|
+
{
|
|
693
|
+
const f = filterValue;
|
|
694
|
+
return f.values?.length ? f.values.includes(String(cell)) : true;
|
|
695
|
+
}
|
|
696
|
+
case "multiEnum":
|
|
697
|
+
{
|
|
698
|
+
const f = filterValue;
|
|
699
|
+
if (!f.values?.length) return true;
|
|
700
|
+
const arr = Array.isArray(cell) ? cell.map(String) : [
|
|
701
|
+
String(cell)
|
|
702
|
+
];
|
|
703
|
+
return f.values.some((v)=>arr.includes(v));
|
|
704
|
+
}
|
|
705
|
+
case "int":
|
|
706
|
+
case "number":
|
|
707
|
+
return matchNumber(cell, filterValue);
|
|
708
|
+
case "time":
|
|
709
|
+
return matchTime(cell, filterValue);
|
|
710
|
+
case "date":
|
|
711
|
+
case "datetime":
|
|
712
|
+
case "dateRange":
|
|
713
|
+
return matchDateRange(cell, filterValue);
|
|
714
|
+
case "custom":
|
|
715
|
+
return matchNumber(cell, filterValue);
|
|
716
|
+
default:
|
|
717
|
+
return matchText(cell, filterValue);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
export { DEFAULT_EDITOR_RENDERERS, DEFAULT_FILTER_RENDERERS, FieldSelect, NUMBER_FILTER_OPERATORS, TEXT_FILTER_OPERATORS, columnLabel, isBlank, matchBetween, typedFilterMatch };
|