@lavalogic/scoria 0.40.13 → 0.40.15
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/README.md +58 -58
- package/dist/Components/AccordionGroup.svelte +35 -46
- package/dist/Components/AccordionGroupButton.svelte +68 -76
- package/dist/Components/Action.svelte +103 -135
- package/dist/Components/AlertModal.svelte +171 -190
- package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +614 -697
- package/dist/Components/Base/BaseModal.svelte +90 -116
- package/dist/Components/Base/ContextWrapper.svelte +67 -72
- package/dist/Components/Base/Pagination.svelte +173 -196
- package/dist/Components/Base/Snippets.svelte +34 -36
- package/dist/Components/BigRadioSet.svelte +36 -38
- package/dist/Components/Bubble.svelte +78 -101
- package/dist/Components/Button.svelte +175 -208
- package/dist/Components/Checkbox.svelte +75 -86
- package/dist/Components/CollapsibleCard.svelte +72 -87
- package/dist/Components/CollapsibleMenuGroup.svelte +53 -57
- package/dist/Components/ConditionBuilder/ConditionBuilder.svelte +39 -64
- package/dist/Components/Contexts/ContextMenu.svelte +141 -156
- package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
- package/dist/Components/Contexts/ContextMenuOption.svelte +53 -60
- package/dist/Components/Contexts/Toast.svelte +81 -86
- package/dist/Components/Contexts/ToastContainer.svelte +58 -62
- package/dist/Components/Contexts/Tooltip.svelte +36 -37
- package/dist/Components/DataMatrixIcon.svelte +95 -108
- package/dist/Components/DateInput.svelte +118 -146
- package/dist/Components/DatePicker.svelte +255 -294
- package/dist/Components/DesktopModal.svelte +70 -90
- package/dist/Components/Dial.svelte +167 -197
- package/dist/Components/DimensionInput.svelte +124 -169
- package/dist/Components/DragMenu/DragMenuHolder.svelte +98 -114
- package/dist/Components/DragMenu/DraggableCard.svelte +64 -76
- package/dist/Components/FileCard.svelte +21 -24
- package/dist/Components/FileUpload.svelte +190 -225
- package/dist/Components/GridInput.svelte +159 -196
- package/dist/Components/GridInputSet.svelte +24 -29
- package/dist/Components/HorizontalTabGroup.svelte +73 -89
- package/dist/Components/HorizontalTabGroupButton.svelte +40 -44
- package/dist/Components/Icon.svelte +99 -128
- package/dist/Components/Icons.js +357 -357
- package/dist/Components/InfoAlert.svelte +35 -38
- package/dist/Components/LoadingAnimation.svelte +691 -755
- package/dist/Components/LoadingModal.svelte +36 -44
- package/dist/Components/LoadingOverlay.svelte +22 -26
- package/dist/Components/Modal.svelte +204 -254
- package/dist/Components/MultiSelect.svelte +186 -216
- package/dist/Components/Nav/Nav.svelte +94 -110
- package/dist/Components/Nav/NavServiceMenuList.svelte +57 -61
- package/dist/Components/Nav/NavTab.svelte +58 -62
- package/dist/Components/Nav/ServiceMenuItem.svelte +103 -111
- package/dist/Components/Nav/ServicesNav.svelte +72 -79
- package/dist/Components/NumberInput.svelte +121 -155
- package/dist/Components/OptionCards.svelte +62 -73
- package/dist/Components/PageHeading.svelte +23 -25
- package/dist/Components/PasswordInput.svelte +69 -88
- package/dist/Components/PopoverButton.svelte +151 -0
- package/dist/Components/PopoverButton.svelte.d.ts +9 -0
- package/dist/Components/PopoverButtonProps.d.ts +21 -0
- package/dist/Components/PopoverButtonProps.js +1 -0
- package/dist/Components/Portal.svelte +29 -35
- package/dist/Components/ProgressBubble.svelte +91 -106
- package/dist/Components/QuerySelect.svelte +260 -346
- package/dist/Components/SidebarPanel.svelte +34 -36
- package/dist/Components/SingleSelect.svelte +196 -244
- package/dist/Components/StepButton.svelte +65 -70
- package/dist/Components/StepForm.svelte +115 -135
- package/dist/Components/Switch.svelte +57 -69
- package/dist/Components/Table/ARCHITECTURE.md +298 -298
- package/dist/Components/Table/Body/QuickSearchCell.svelte +578 -655
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +42 -51
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +42 -58
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +403 -442
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +51 -78
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +165 -184
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +110 -123
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +134 -160
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +190 -231
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +82 -104
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +52 -87
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +122 -150
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +132 -159
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +190 -236
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +173 -211
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +204 -244
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +140 -177
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +188 -217
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +173 -193
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +166 -187
- package/dist/Components/Table/Body/Rows/TableRow.svelte +245 -288
- package/dist/Components/Table/Body/TableBody.svelte +141 -154
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +35 -41
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +24 -30
- package/dist/Components/Table/Headers/TableHead.svelte +348 -402
- package/dist/Components/Table/Misc/ColumnPanel.svelte +37 -39
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +35 -39
- package/dist/Components/Table/Misc/FilterInput.svelte +556 -619
- package/dist/Components/Table/Misc/FilterPanel.svelte +170 -183
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +25 -31
- package/dist/Components/Table/Misc/ShareViewModal.svelte +252 -281
- package/dist/Components/Table/Misc/SidePanel.svelte +32 -35
- package/dist/Components/Table/Misc/TableConfigurationModal.svelte +574 -629
- package/dist/Components/Table/Misc/TableFooter.svelte +326 -332
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +134 -140
- package/dist/Components/Table/Misc/TableSidebar.svelte +183 -198
- package/dist/Components/Table/Misc/TableViewDropdown.svelte +83 -103
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +83 -100
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +88 -107
- package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +163 -190
- package/dist/Components/Table/NestedTable.svelte +102 -128
- package/dist/Components/Table/Table.svelte +531 -663
- package/dist/Components/Test/TestContextConsumer.svelte +11 -13
- package/dist/Components/TextArea.svelte +95 -130
- package/dist/Components/TextInput.svelte +125 -176
- package/dist/Components/ThreeStateRadio.svelte +111 -130
- package/dist/Components/Touch/BoolCard.svelte +33 -45
- package/dist/Components/Touch/DateModal.svelte +164 -204
- package/dist/Components/Touch/EditCard.svelte +48 -59
- package/dist/Components/Touch/InfoCard.svelte +28 -31
- package/dist/Components/Touch/InfoTextCard.svelte +26 -28
- package/dist/Components/Touch/ModalExplanation.svelte +15 -17
- package/dist/Components/Touch/NumberKeyboard.svelte +181 -218
- package/dist/Components/Touch/NumberModal.svelte +59 -79
- package/dist/Components/Touch/PlusMinusCard.svelte +43 -46
- package/dist/Components/Touch/SelectModal.svelte +111 -126
- package/dist/Components/Touch/SummaryCard.svelte +80 -93
- package/dist/Components/Touch/TextAreaModal.svelte +72 -94
- package/dist/Components/Touch/TextModal.svelte +77 -105
- package/dist/Components/Touch/TouchCard.svelte +31 -33
- package/dist/Components/Touch/TouchModal.svelte +214 -270
- package/dist/Components/Touch/UtilityButton.svelte +88 -109
- package/dist/Components/VerticalTabGroup.svelte +60 -78
- package/dist/Components/VerticalTabGroupButton.svelte +54 -58
- package/dist/Helpers/Datamatrix.d.ts +19 -19
- package/dist/Helpers/Datamatrix.js +291 -291
- package/dist/Types/Examples/ExampleModal.svelte +31 -35
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/scss/_basics.scss +12 -12
- package/dist/scss/_colours.scss +134 -134
- package/dist/scss/_mixins.scss +3392 -3392
- package/dist/scss/_motion.scss +57 -57
- package/dist/scss/_sizing.scss +85 -85
- package/dist/scss/_transitions.scss +8 -8
- package/package.json +1 -1
|
@@ -1,681 +1,604 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script
|
|
4
|
-
lang="ts"
|
|
5
|
-
generics="T extends object, IdType extends Primitive, FilterValueType"
|
|
6
|
-
>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
generics="T extends object, IdType extends Primitive, FilterValueType"
|
|
6
|
+
>import { dev } from "$app/environment";
|
|
7
|
+
import Action from "../../Action.svelte";
|
|
8
|
+
import Button from "../../Button.svelte";
|
|
9
|
+
import MultiSelect from "../../MultiSelect.svelte";
|
|
10
|
+
import NumberInput from "../../NumberInput.svelte";
|
|
11
|
+
import SingleSelect from "../../SingleSelect.svelte";
|
|
12
|
+
import TextInput from "../../TextInput.svelte";
|
|
13
|
+
import ThreeStateRadio from "../../ThreeStateRadio.svelte";
|
|
14
|
+
import DateModal from "../../Touch/DateModal.svelte";
|
|
15
|
+
import { hasQuery } from "../TableHelpers.svelte.js";
|
|
16
|
+
import { devCatch, isDateTuple, isNumericArray } from "../../../Helpers/Helpers.svelte.js";
|
|
17
|
+
import { Colour, ColourSet } from "../../../scss/colours.js";
|
|
18
|
+
import { InputVariant } from "../../../Types/Internal/InputVariant.js";
|
|
19
|
+
import { Size } from "../../../Types/Internal/Size.js";
|
|
20
|
+
import { getContext, onDestroy, onMount, untrack } from "svelte";
|
|
21
|
+
import { cubicOut } from "svelte/easing";
|
|
22
|
+
import { fade } from "svelte/transition";
|
|
23
|
+
import QuerySelect from "../../QuerySelect.svelte";
|
|
24
|
+
import { Ternary } from "../../../Types/Internal/Ternary.js";
|
|
25
|
+
import { numberDateFilterTypes } from "../Misc/numberDateFilterTypes.js";
|
|
26
|
+
import { stringFilterTypes } from "../Misc/stringFilterTypes.js";
|
|
27
|
+
import { quickFilterContextIdentifier } from "../Table.svelte";
|
|
28
|
+
import { CheckboxDef } from "../Types/Columns/Definitions/Accessors/CheckboxDef.svelte.js";
|
|
29
|
+
import { DateInputDef } from "../Types/Columns/Definitions/Accessors/DateInputDef.svelte.js";
|
|
30
|
+
import { NumberInputDef } from "../Types/Columns/Definitions/Accessors/NumberInputDef.svelte.js";
|
|
31
|
+
import { SelectDef } from "../Types/Columns/Definitions/Accessors/SelectDef.svelte.js";
|
|
32
|
+
import { TableContext } from "../Types/Context/TableContext.svelte.js";
|
|
33
|
+
import { CustomFilterType } from "../Types/Filtering/CustomFilterType.js";
|
|
34
|
+
import { NumberDateFilterMode } from "../Types/Filtering/NumberDateFilterMode.js";
|
|
35
|
+
import { StringFilterMode } from "../Types/Filtering/StringFilterMode.js";
|
|
36
|
+
const tableContext = getContext(TableContext.identifier);
|
|
37
|
+
const { column, customFilters } = $props();
|
|
38
|
+
const def = $derived(column.columnDef);
|
|
39
|
+
const customFilter = $derived(customFilters?.get(def.id));
|
|
40
|
+
const isSelect = $derived(def instanceof SelectDef || def.filterValueType == CustomFilterType.Select || customFilter?.type === CustomFilterType.Select);
|
|
41
|
+
const hasFilterFn = $derived(!!def.filterFn && typeof def.filterFn === "function");
|
|
42
|
+
// A column is filterable when it has any of: a local `filterFn`, a
|
|
43
|
+
// declared `filterValueType` (server-side filtering — required for
|
|
44
|
+
// remote-pagination tables whose data repo never assigns `filterFn`),
|
|
45
|
+
// or a `customFilters` entry from `defsWrapper.remoteFilters`.
|
|
46
|
+
const hasDeclaredFilterType = $derived(def.filterValueType != null);
|
|
47
|
+
const isSearchable = $derived(def.allowFiltering && (hasFilterFn || hasDeclaredFilterType || customFilters?.has(def.id) == true));
|
|
48
|
+
const isNumeric = $derived(def instanceof NumberInputDef || def.filterValueType == "Number" || customFilter?.type === CustomFilterType.Number);
|
|
49
|
+
function emptyOptsAndWarn() {
|
|
50
|
+
console.warn(`def ${def.id} is declared as a select filter but has no getOptions() function`);
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
const options = $derived(isSelect ? def.getOptions?.() ?? customFilter?.options ?? emptyOptsAndWarn() : []);
|
|
54
|
+
const isDate = $derived(def instanceof DateInputDef);
|
|
55
|
+
const isRemoteSelect = $derived(customFilter?.type === CustomFilterType.Select);
|
|
56
|
+
const selectSymbol = Symbol();
|
|
57
|
+
const openedSelect = getContext(quickFilterContextIdentifier);
|
|
58
|
+
const isSelectOpen = $derived(openedSelect?.value === selectSymbol);
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
60
|
+
let value = $state(null);
|
|
61
|
+
let valueMin = $state(null);
|
|
62
|
+
let valueMax = $state(null);
|
|
63
|
+
let selectedOptions = $state([]);
|
|
64
|
+
let lastQueryOptions = $state([]);
|
|
65
|
+
const inputId = $derived(`${tableContext.tableName}-cell-quicksearch-${column.id}`);
|
|
66
|
+
const filterMode = $derived(tableContext.paginationRepo?.filterModes.get(def.id));
|
|
67
|
+
const selectedNumberFilterType = $derived.by(() => {
|
|
68
|
+
const value = filterMode ?? NumberDateFilterMode.In;
|
|
69
|
+
return numberDateFilterTypes.find((it) => it.value === value) ?? null;
|
|
70
|
+
});
|
|
71
|
+
const selectedStringFilterType = $derived.by(() => {
|
|
72
|
+
const value = filterMode ?? StringFilterMode.Contains;
|
|
73
|
+
return stringFilterTypes.find((it) => it.value === value) ?? null;
|
|
74
|
+
});
|
|
75
|
+
const filteringStateValue = $derived(tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)?.value);
|
|
76
|
+
$effect(() => {
|
|
77
|
+
if (isRemoteSelect && !tableContext.paginationRepo?.filtering) {
|
|
78
|
+
return;
|
|
78
79
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const isRemoteSelect = $derived(customFilter?.type === CustomFilterType.Select);
|
|
84
|
-
|
|
85
|
-
const selectSymbol = Symbol();
|
|
86
|
-
|
|
87
|
-
const openedSelect = getContext<{ value: symbol | null } | null | undefined>(
|
|
88
|
-
quickFilterContextIdentifier
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const isSelectOpen = $derived(openedSelect?.value === selectSymbol);
|
|
92
|
-
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
94
|
-
let value: unknown | null = $state(null);
|
|
95
|
-
let valueMin: number | null = $state(null);
|
|
96
|
-
let valueMax: number | null = $state(null);
|
|
97
|
-
|
|
98
|
-
let selectedOptions: Array<SelectOption<unknown>> = $state([]);
|
|
99
|
-
let lastQueryOptions: Array<SelectOption<unknown>> = $state([]);
|
|
100
|
-
|
|
101
|
-
const inputId = $derived(`${tableContext.tableName}-cell-quicksearch-${column.id}`);
|
|
102
|
-
|
|
103
|
-
const filterMode = $derived(tableContext.paginationRepo?.filterModes.get(def.id));
|
|
104
|
-
|
|
105
|
-
const selectedNumberFilterType: SelectOption<NumberDateFilterMode> | null = $derived.by(() => {
|
|
106
|
-
const value = (filterMode as NumberDateFilterMode | undefined) ?? NumberDateFilterMode.In;
|
|
107
|
-
return numberDateFilterTypes.find((it) => it.value === value) ?? null;
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const selectedStringFilterType: SelectOption<StringFilterMode> | null = $derived.by(() => {
|
|
111
|
-
const value = (filterMode as StringFilterMode | undefined) ?? StringFilterMode.Contains;
|
|
112
|
-
return stringFilterTypes.find((it) => it.value === value) ?? null;
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const filteringStateValue = $derived(
|
|
116
|
-
tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)?.value
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
$effect(() => {
|
|
120
|
-
if (isRemoteSelect && !tableContext.paginationRepo?.filtering) {
|
|
121
|
-
return;
|
|
80
|
+
void filteringStateValue;
|
|
81
|
+
if (hasQuery(customFilter)) {
|
|
82
|
+
if (def.debug) {
|
|
83
|
+
console.debug(`${def.id}: `, "has query");
|
|
122
84
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
untrack(async () => {
|
|
131
|
-
const gotValue = filteringStateValue as Array<unknown> | undefined;
|
|
132
|
-
|
|
133
|
-
try {
|
|
134
|
-
// as unknown as string | number | undefined;
|
|
135
|
-
|
|
136
|
-
if (gotValue != undefined) {
|
|
137
|
-
if (def.debug) {
|
|
138
|
-
console.debug(`${def.id}: query values:`, tableContext.queryValues.snapshot());
|
|
139
|
-
}
|
|
140
|
-
const x = tableContext.queryValues.get(def);
|
|
141
|
-
|
|
142
|
-
if (def.debug) {
|
|
143
|
-
console.debug(`${def.id}: `, 'value:', $state.snapshot(x));
|
|
144
|
-
}
|
|
145
|
-
value = x ?? null;
|
|
146
|
-
} else if (def.debug) {
|
|
147
|
-
console.debug(
|
|
148
|
-
`${def.id}: `,
|
|
149
|
-
'filtering state value was undefined',
|
|
150
|
-
$state.snapshot(tableContext.paginationRepo?.filtering)
|
|
151
|
-
);
|
|
85
|
+
untrack(async () => {
|
|
86
|
+
const gotValue = filteringStateValue;
|
|
87
|
+
try {
|
|
88
|
+
// as unknown as string | number | undefined;
|
|
89
|
+
if (gotValue != undefined) {
|
|
90
|
+
if (def.debug) {
|
|
91
|
+
console.debug(`${def.id}: query values:`, tableContext.queryValues.snapshot());
|
|
152
92
|
}
|
|
153
|
-
|
|
154
|
-
console.warn(e);
|
|
155
|
-
value = null;
|
|
156
|
-
}
|
|
157
|
-
}).catch(devCatch);
|
|
158
|
-
} else if (isSelect) {
|
|
159
|
-
if (def.debug) {
|
|
160
|
-
console.debug(`${def.id}: `, 'is select (not query)');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (!tableContext.paginationRepo?.filtering) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const gotValue = filteringStateValue as Array<unknown> | undefined;
|
|
168
|
-
|
|
169
|
-
function isSelectOption(it: unknown): it is SelectOption<unknown> {
|
|
170
|
-
return it != null && typeof it == 'object';
|
|
171
|
-
}
|
|
172
|
-
untrack(async () => {
|
|
173
|
-
try {
|
|
174
|
-
const opts = await options;
|
|
93
|
+
const x = tableContext.queryValues.get(def);
|
|
175
94
|
if (def.debug) {
|
|
176
|
-
console.debug(`${def.id}:
|
|
95
|
+
console.debug(`${def.id}: `, "value:", $state.snapshot(x));
|
|
177
96
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
97
|
+
value = x ?? null;
|
|
98
|
+
} else if (def.debug) {
|
|
99
|
+
console.debug(`${def.id}: `, "filtering state value was undefined", $state.snapshot(tableContext.paginationRepo?.filtering));
|
|
100
|
+
}
|
|
101
|
+
} catch (e) {
|
|
102
|
+
console.warn(e);
|
|
103
|
+
value = null;
|
|
104
|
+
}
|
|
105
|
+
}).catch(devCatch);
|
|
106
|
+
} else if (isSelect) {
|
|
107
|
+
if (def.debug) {
|
|
108
|
+
console.debug(`${def.id}: `, "is select (not query)");
|
|
109
|
+
}
|
|
110
|
+
if (!tableContext.paginationRepo?.filtering) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const gotValue = filteringStateValue;
|
|
114
|
+
function isSelectOption(it) {
|
|
115
|
+
return it != null && typeof it == "object";
|
|
116
|
+
}
|
|
117
|
+
untrack(async () => {
|
|
118
|
+
try {
|
|
119
|
+
const opts = await options;
|
|
120
|
+
if (def.debug) {
|
|
121
|
+
console.debug(`${def.id}: possible options:`, $state.snapshot(opts));
|
|
122
|
+
}
|
|
123
|
+
const x = opts.filter((it) => {
|
|
124
|
+
if (!isSelectOption(it)) {
|
|
192
125
|
return false;
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
if (def.debug) {
|
|
196
|
-
console.debug(`${def.id}: `, 'selected options:', x);
|
|
197
126
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (dev || def.debug) {
|
|
201
|
-
console.debug(`${def.id}: `, e);
|
|
127
|
+
if (it.value == undefined) {
|
|
128
|
+
return true;
|
|
202
129
|
}
|
|
130
|
+
if (typeof it.value == "string" || typeof it.value == "number") {
|
|
131
|
+
return gotValue?.includes(it.value);
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
});
|
|
135
|
+
if (def.debug) {
|
|
136
|
+
console.debug(`${def.id}: `, "selected options:", x);
|
|
203
137
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
tableContext.paginationRepo?.filtering
|
|
209
|
-
) {
|
|
210
|
-
const gotValue = filteringStateValue;
|
|
211
|
-
if (gotValue != undefined) {
|
|
212
|
-
const [min, max] = gotValue as [number, number | undefined];
|
|
213
|
-
value = min;
|
|
214
|
-
valueMin = min;
|
|
215
|
-
valueMax = max ?? null;
|
|
216
|
-
} else {
|
|
217
|
-
value = valueMin = valueMax = null;
|
|
218
|
-
}
|
|
219
|
-
} else if (tableContext.paginationRepo?.filtering) {
|
|
220
|
-
const gotValue = filteringStateValue;
|
|
221
|
-
|
|
222
|
-
if (gotValue != undefined) {
|
|
223
|
-
const [min] = gotValue as [number, number | undefined];
|
|
224
|
-
value = min;
|
|
225
|
-
valueMin = min;
|
|
226
|
-
valueMax = min;
|
|
227
|
-
} else {
|
|
228
|
-
value = valueMin = valueMax = null;
|
|
138
|
+
selectedOptions = x;
|
|
139
|
+
} catch (e) {
|
|
140
|
+
if (dev || def.debug) {
|
|
141
|
+
console.debug(`${def.id}: `, e);
|
|
229
142
|
}
|
|
230
143
|
}
|
|
144
|
+
}).catch(devCatch);
|
|
145
|
+
} else if (isNumeric) {
|
|
146
|
+
if (selectedNumberFilterType?.value === NumberDateFilterMode.Between && tableContext.paginationRepo?.filtering) {
|
|
147
|
+
const gotValue = filteringStateValue;
|
|
148
|
+
if (gotValue != undefined) {
|
|
149
|
+
const [min, max] = gotValue;
|
|
150
|
+
value = min;
|
|
151
|
+
valueMin = min;
|
|
152
|
+
valueMax = max ?? null;
|
|
153
|
+
} else {
|
|
154
|
+
value = valueMin = valueMax = null;
|
|
155
|
+
}
|
|
231
156
|
} else if (tableContext.paginationRepo?.filtering) {
|
|
232
157
|
const gotValue = filteringStateValue;
|
|
233
|
-
if (gotValue
|
|
234
|
-
|
|
235
|
-
value =
|
|
158
|
+
if (gotValue != undefined) {
|
|
159
|
+
const [min] = gotValue;
|
|
160
|
+
value = min;
|
|
161
|
+
valueMin = min;
|
|
162
|
+
valueMax = min;
|
|
163
|
+
} else {
|
|
164
|
+
value = valueMin = valueMax = null;
|
|
236
165
|
}
|
|
237
166
|
}
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
* any regression loud; no-ops in production builds.
|
|
244
|
-
*/
|
|
245
|
-
function assertNotPromise(gotValue: unknown) {
|
|
246
|
-
if (dev && gotValue != null && typeof gotValue == 'object' && gotValue instanceof Promise) {
|
|
247
|
-
throw new Error(`Unexpected Promise`);
|
|
167
|
+
} else if (tableContext.paginationRepo?.filtering) {
|
|
168
|
+
const gotValue = filteringStateValue;
|
|
169
|
+
if (gotValue == null || typeof gotValue == "string" || typeof gotValue == "number") {
|
|
170
|
+
assertNotPromise(gotValue);
|
|
171
|
+
value = gotValue;
|
|
248
172
|
}
|
|
249
173
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
174
|
+
});
|
|
175
|
+
/**
|
|
176
|
+
* Dev-only invariant: a Promise must never reach the synchronous primitive
|
|
177
|
+
* sink (we should always have awaited it upstream). Throws in dev to make
|
|
178
|
+
* any regression loud; no-ops in production builds.
|
|
179
|
+
*/
|
|
180
|
+
function assertNotPromise(gotValue) {
|
|
181
|
+
if (dev && gotValue != null && typeof gotValue == "object" && gotValue instanceof Promise) {
|
|
182
|
+
throw new Error(`Unexpected Promise`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
onMount(() => {
|
|
186
|
+
const filterOption = tableContext.paginationRepo?.filtering && tableContext.paginationRepo.filtering.find((it) => it.id === def.id);
|
|
187
|
+
if (filterOption) {
|
|
188
|
+
if (isNumericArray(filterOption.value)) {
|
|
189
|
+
[valueMin, valueMax] = filterOption.value;
|
|
190
|
+
if (valueMax == undefined) {
|
|
191
|
+
valueMax = valueMin;
|
|
192
|
+
value = valueMin?.toString();
|
|
193
|
+
} else if (valueMin == undefined) {
|
|
194
|
+
valueMin = valueMax;
|
|
195
|
+
value = valueMax.toString();
|
|
196
|
+
} else {
|
|
197
|
+
value = valueMin.toString();
|
|
198
|
+
}
|
|
199
|
+
} else if (!hasQuery(customFilter)) {
|
|
200
|
+
const gotValue = filterOption.value;
|
|
201
|
+
if (gotValue == null || typeof gotValue == "string" || typeof gotValue == "number") {
|
|
202
|
+
assertNotPromise(gotValue);
|
|
203
|
+
value = gotValue;
|
|
273
204
|
}
|
|
274
205
|
}
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
function closeOnCtrlF(e: KeyboardEvent) {
|
|
278
|
-
if (e.key.toLocaleUpperCase() === 'F' && e.ctrlKey) {
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
e.stopPropagation();
|
|
282
206
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
function generateOnChangeObject(_label: string) {
|
|
288
|
-
return (newValue: SelectOption<unknown> | null) => {
|
|
289
|
-
tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
|
|
290
|
-
tableContext.queryValues.set(def, newValue);
|
|
291
|
-
assertNotPromise(newValue);
|
|
292
|
-
value = newValue;
|
|
293
|
-
};
|
|
207
|
+
});
|
|
208
|
+
function closeOnCtrlF(e) {
|
|
209
|
+
if (e.key.toLocaleUpperCase() === "F" && e.ctrlKey) {
|
|
210
|
+
return;
|
|
294
211
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
212
|
+
e.stopPropagation();
|
|
213
|
+
}
|
|
214
|
+
let showFromDateModal = $state(false);
|
|
215
|
+
let showToDateModal = $state(false);
|
|
216
|
+
function generateOnChangeObject(_label) {
|
|
217
|
+
return (newValue) => {
|
|
218
|
+
tableContext.paginationRepo?.filterBy(def.id, newValue?.value ?? null);
|
|
219
|
+
tableContext.queryValues.set(def, newValue);
|
|
220
|
+
assertNotPromise(newValue);
|
|
221
|
+
value = newValue;
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function generateOnChangePrimitive(_label) {
|
|
225
|
+
// AsPrimitive QuerySelect hands us the primitive value directly.
|
|
226
|
+
return (newValue) => {
|
|
227
|
+
tableContext.paginationRepo?.filterBy(def.id, newValue ?? null);
|
|
228
|
+
tableContext.queryValues.set(def, newValue ?? null);
|
|
229
|
+
assertNotPromise(newValue);
|
|
230
|
+
value = newValue ?? null;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
let isNullFilter = $derived(selectedNumberFilterType?.value == NumberDateFilterMode.null);
|
|
234
|
+
/**
|
|
235
|
+
* Debounce window for typed filter inputs. For a 10k-row table each
|
|
236
|
+
* keystroke would otherwise kick off a full filter pass; coalescing
|
|
237
|
+
* adjacent keystrokes within `FILTER_DEBOUNCE_MS` cuts the cost to
|
|
238
|
+
* roughly one filter pass per pause-in-typing.
|
|
239
|
+
*/
|
|
240
|
+
const FILTER_DEBOUNCE_MS = 300;
|
|
241
|
+
/**
|
|
242
|
+
* Sequence counter used to discard the result of a stale debounce
|
|
243
|
+
* timer. When the user types again before the timer fires, the
|
|
244
|
+
* `pendingSeq` increments; only the timer whose captured `seq`
|
|
245
|
+
* matches `pendingSeq` is allowed to call `filterBy`.
|
|
246
|
+
*/
|
|
247
|
+
let pendingSeq = 0;
|
|
248
|
+
let debounceTimer;
|
|
249
|
+
function debouncedFilterBy(value) {
|
|
250
|
+
pendingSeq += 1;
|
|
251
|
+
const seq = pendingSeq;
|
|
252
|
+
if (debounceTimer !== undefined) {
|
|
253
|
+
clearTimeout(debounceTimer);
|
|
304
254
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
* adjacent keystrokes within `FILTER_DEBOUNCE_MS` cuts the cost to
|
|
312
|
-
* roughly one filter pass per pause-in-typing.
|
|
313
|
-
*/
|
|
314
|
-
const FILTER_DEBOUNCE_MS = 300;
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Sequence counter used to discard the result of a stale debounce
|
|
318
|
-
* timer. When the user types again before the timer fires, the
|
|
319
|
-
* `pendingSeq` increments; only the timer whose captured `seq`
|
|
320
|
-
* matches `pendingSeq` is allowed to call `filterBy`.
|
|
321
|
-
*/
|
|
322
|
-
let pendingSeq = 0;
|
|
323
|
-
let debounceTimer: ReturnType<typeof setTimeout> | undefined;
|
|
324
|
-
|
|
325
|
-
function debouncedFilterBy(value: unknown): void {
|
|
326
|
-
pendingSeq += 1;
|
|
327
|
-
const seq = pendingSeq;
|
|
328
|
-
if (debounceTimer !== undefined) {
|
|
329
|
-
clearTimeout(debounceTimer);
|
|
255
|
+
debounceTimer = setTimeout(() => {
|
|
256
|
+
debounceTimer = undefined;
|
|
257
|
+
if (seq !== pendingSeq) {
|
|
258
|
+
// A newer keystroke superseded this one before the timer
|
|
259
|
+
// fired; the newer timer will handle the filter call.
|
|
260
|
+
return;
|
|
330
261
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
tableContext.paginationRepo?.filterBy(def.id, value);
|
|
339
|
-
}, FILTER_DEBOUNCE_MS);
|
|
262
|
+
tableContext.paginationRepo?.filterBy(def.id, value);
|
|
263
|
+
}, FILTER_DEBOUNCE_MS);
|
|
264
|
+
}
|
|
265
|
+
onDestroy(() => {
|
|
266
|
+
if (debounceTimer !== undefined) {
|
|
267
|
+
clearTimeout(debounceTimer);
|
|
268
|
+
debounceTimer = undefined;
|
|
340
269
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
return Ternary.
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
{/if}
|
|
674
|
-
</div>
|
|
675
|
-
</div>
|
|
676
|
-
{/if}
|
|
677
|
-
</div>
|
|
678
|
-
|
|
270
|
+
});
|
|
271
|
+
</script>
|
|
272
|
+
|
|
273
|
+
<div class="input-cell {inputId}">
|
|
274
|
+
{#if isSearchable}
|
|
275
|
+
<div class="input-wrapper-parent">
|
|
276
|
+
{#if isDate}
|
|
277
|
+
{@const dateValues = tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)
|
|
278
|
+
?.value ?? [null, null]}
|
|
279
|
+
{#if isDateTuple(dateValues)}
|
|
280
|
+
{@const [fromDate, toDate] = dateValues}
|
|
281
|
+
<div class="spaced-around">
|
|
282
|
+
<Button
|
|
283
|
+
size={Size.FillHeight}
|
|
284
|
+
fullWidth
|
|
285
|
+
onclick={() => {
|
|
286
|
+
showFromDateModal = true;
|
|
287
|
+
}}>From {fromDate?.toLocaleDateString() ?? 'Any Date'}</Button
|
|
288
|
+
>
|
|
289
|
+
|
|
290
|
+
<Button
|
|
291
|
+
size={Size.FillHeight}
|
|
292
|
+
fullWidth
|
|
293
|
+
onclick={() => {
|
|
294
|
+
showToDateModal = true;
|
|
295
|
+
}}>To {toDate?.toLocaleDateString() ?? 'Any Date'}</Button
|
|
296
|
+
>
|
|
297
|
+
</div>
|
|
298
|
+
|
|
299
|
+
{#if showFromDateModal}
|
|
300
|
+
<DateModal
|
|
301
|
+
header="Edit Date From"
|
|
302
|
+
value={fromDate}
|
|
303
|
+
cancelEditing={() => {
|
|
304
|
+
showFromDateModal = false;
|
|
305
|
+
}}
|
|
306
|
+
confirm={(e) => {
|
|
307
|
+
tableContext.paginationRepo?.filterBy(def.id, [e, toDate]);
|
|
308
|
+
showFromDateModal = false;
|
|
309
|
+
}}
|
|
310
|
+
/>
|
|
311
|
+
{/if}
|
|
312
|
+
|
|
313
|
+
{#if showToDateModal}
|
|
314
|
+
<DateModal
|
|
315
|
+
inclusive
|
|
316
|
+
header="Edit Date To"
|
|
317
|
+
value={toDate}
|
|
318
|
+
cancelEditing={() => {
|
|
319
|
+
showToDateModal = false;
|
|
320
|
+
}}
|
|
321
|
+
confirm={(e) => {
|
|
322
|
+
tableContext.paginationRepo?.filterBy(def.id, [fromDate, e]);
|
|
323
|
+
showToDateModal = false;
|
|
324
|
+
}}
|
|
325
|
+
/>
|
|
326
|
+
{/if}
|
|
327
|
+
{/if}
|
|
328
|
+
{:else if isSelect}
|
|
329
|
+
{#if hasQuery(customFilter)}
|
|
330
|
+
{#if customFilter.valueAsObject !== true}
|
|
331
|
+
{@const label = customFilter.id}
|
|
332
|
+
|
|
333
|
+
<!-- TODO: multiselect -->
|
|
334
|
+
|
|
335
|
+
<!-- FIXME: Most likely Unsafe -->
|
|
336
|
+
<QuerySelect
|
|
337
|
+
valueAsObject={false}
|
|
338
|
+
clearable
|
|
339
|
+
name={customFilter.objectName ?? 'Item'}
|
|
340
|
+
valueProp="value"
|
|
341
|
+
labelProp="label"
|
|
342
|
+
value={value as null}
|
|
343
|
+
query={customFilter.query}
|
|
344
|
+
bind:options={lastQueryOptions}
|
|
345
|
+
onchange={generateOnChangePrimitive(label)}
|
|
346
|
+
/>
|
|
347
|
+
{:else}
|
|
348
|
+
{@const label = customFilter.id}
|
|
349
|
+
|
|
350
|
+
<!-- TODO: multiselect -->
|
|
351
|
+
|
|
352
|
+
<QuerySelect
|
|
353
|
+
valueAsObject={true}
|
|
354
|
+
clearable
|
|
355
|
+
name={customFilter.objectName ?? 'Item'}
|
|
356
|
+
valueProp="value"
|
|
357
|
+
labelProp="label"
|
|
358
|
+
value={value as null}
|
|
359
|
+
query={customFilter.query}
|
|
360
|
+
bind:options={lastQueryOptions}
|
|
361
|
+
onchange={generateOnChangeObject(label)}
|
|
362
|
+
/>
|
|
363
|
+
{/if}
|
|
364
|
+
{:else}
|
|
365
|
+
{#await options then options}
|
|
366
|
+
<MultiSelect
|
|
367
|
+
labelProp="label"
|
|
368
|
+
valueProp="value"
|
|
369
|
+
{options}
|
|
370
|
+
valueAsObject
|
|
371
|
+
onchange={(e: Array<SelectOption<unknown>>) => {
|
|
372
|
+
tableContext.paginationRepo?.filterBy(
|
|
373
|
+
def.id,
|
|
374
|
+
e.map((it) => it.value)
|
|
375
|
+
);
|
|
376
|
+
}}
|
|
377
|
+
selectedValues={selectedOptions}
|
|
378
|
+
collapseSelection
|
|
379
|
+
/>
|
|
380
|
+
{/await}
|
|
381
|
+
{/if}
|
|
382
|
+
{:else if def instanceof CheckboxDef}
|
|
383
|
+
{@const value = (() => {
|
|
384
|
+
switch (tableContext.paginationRepo?.filtering.find((it) => it.id === def.id)?.value) {
|
|
385
|
+
case true: {
|
|
386
|
+
return Ternary.True;
|
|
387
|
+
}
|
|
388
|
+
case false: {
|
|
389
|
+
return Ternary.False;
|
|
390
|
+
}
|
|
391
|
+
default: {
|
|
392
|
+
return Ternary.Neutral;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
})()}
|
|
396
|
+
<div class="centered">
|
|
397
|
+
<ThreeStateRadio
|
|
398
|
+
{value}
|
|
399
|
+
yesLabel="Selected"
|
|
400
|
+
noLabel="Not Selected"
|
|
401
|
+
neutralLabel="Any"
|
|
402
|
+
neutralIcon={{ name: 'circle-minus' }}
|
|
403
|
+
onchange={(v) => {
|
|
404
|
+
switch (v) {
|
|
405
|
+
case Ternary.False: {
|
|
406
|
+
tableContext.paginationRepo?.filterBy(def.id, false);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
case Ternary.True: {
|
|
410
|
+
tableContext.paginationRepo?.filterBy(def.id, true);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
case Ternary.Neutral:
|
|
414
|
+
default: {
|
|
415
|
+
tableContext.paginationRepo?.filterBy(def.id, null);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}}
|
|
420
|
+
/>
|
|
421
|
+
</div>
|
|
422
|
+
{:else if isNumeric}
|
|
423
|
+
{#if selectedNumberFilterType?.value === NumberDateFilterMode.Between}
|
|
424
|
+
<div class="input-wrapper left">
|
|
425
|
+
<NumberInput
|
|
426
|
+
data-type="quicksearch"
|
|
427
|
+
id={inputId}
|
|
428
|
+
bind:value={valueMin}
|
|
429
|
+
variant={InputVariant.Table}
|
|
430
|
+
placeholder="Min…"
|
|
431
|
+
oninput={() => {
|
|
432
|
+
debouncedFilterBy([valueMin, valueMax]);
|
|
433
|
+
}}
|
|
434
|
+
onkeydown={closeOnCtrlF}
|
|
435
|
+
/>
|
|
436
|
+
</div>
|
|
437
|
+
<div class="input-wrapper right">
|
|
438
|
+
<NumberInput
|
|
439
|
+
data-type="quicksearch"
|
|
440
|
+
id={inputId}
|
|
441
|
+
bind:value={valueMax}
|
|
442
|
+
placeholder="Max…"
|
|
443
|
+
variant={InputVariant.Table}
|
|
444
|
+
oninput={() => {
|
|
445
|
+
debouncedFilterBy([valueMin, valueMax]);
|
|
446
|
+
}}
|
|
447
|
+
onkeydown={closeOnCtrlF}
|
|
448
|
+
/>
|
|
449
|
+
</div>
|
|
450
|
+
{:else}
|
|
451
|
+
<div class="input-wrapper right">
|
|
452
|
+
{#await isNullFilter}
|
|
453
|
+
loading
|
|
454
|
+
{:then isNullFilter}
|
|
455
|
+
{#if isNullFilter}
|
|
456
|
+
<TextInput
|
|
457
|
+
data-type="quicksearch"
|
|
458
|
+
id={inputId}
|
|
459
|
+
value="is Null"
|
|
460
|
+
disabled
|
|
461
|
+
variant={InputVariant.Table}
|
|
462
|
+
/>
|
|
463
|
+
{:else}
|
|
464
|
+
<!-- NOTE: This is a text input in order to support the __in functionality, which is a comma separated list of numbers -->
|
|
465
|
+
<TextInput
|
|
466
|
+
data-type="quicksearch"
|
|
467
|
+
id={inputId}
|
|
468
|
+
bind:value={value as string | null}
|
|
469
|
+
placeholder="Filter…"
|
|
470
|
+
variant={InputVariant.Table}
|
|
471
|
+
oninput={() => {
|
|
472
|
+
debouncedFilterBy([value || null]);
|
|
473
|
+
}}
|
|
474
|
+
onkeydown={closeOnCtrlF}
|
|
475
|
+
/>
|
|
476
|
+
{/if}
|
|
477
|
+
{:catch e}
|
|
478
|
+
<!-- eslint-disable-next-line svelte/no-at-debug-tags -->
|
|
479
|
+
{@debug e}
|
|
480
|
+
{/await}
|
|
481
|
+
</div>
|
|
482
|
+
{/if}
|
|
483
|
+
{:else if value == null || typeof value == 'string'}
|
|
484
|
+
<div class="input-wrapper right">
|
|
485
|
+
{#if selectedStringFilterType?.value == StringFilterMode.null}
|
|
486
|
+
<TextInput
|
|
487
|
+
data-type="quicksearch"
|
|
488
|
+
id={inputId}
|
|
489
|
+
value="is Null"
|
|
490
|
+
disabled
|
|
491
|
+
variant={InputVariant.Table}
|
|
492
|
+
/>
|
|
493
|
+
{:else if selectedStringFilterType?.value == StringFilterMode.Empty}
|
|
494
|
+
<TextInput
|
|
495
|
+
data-type="quicksearch"
|
|
496
|
+
id={inputId}
|
|
497
|
+
value="is Empty"
|
|
498
|
+
disabled
|
|
499
|
+
variant={InputVariant.Table}
|
|
500
|
+
/>
|
|
501
|
+
{:else}
|
|
502
|
+
<TextInput
|
|
503
|
+
data-type="quicksearch"
|
|
504
|
+
id={inputId}
|
|
505
|
+
oninput={() => {
|
|
506
|
+
debouncedFilterBy(value);
|
|
507
|
+
}}
|
|
508
|
+
variant={InputVariant.Table}
|
|
509
|
+
bind:value={value as string | null}
|
|
510
|
+
placeholder="Filter…"
|
|
511
|
+
/>
|
|
512
|
+
{/if}
|
|
513
|
+
</div>
|
|
514
|
+
{/if}
|
|
515
|
+
|
|
516
|
+
<!-- TODO button for date, checkbox or select for checkbox -->
|
|
517
|
+
</div>
|
|
518
|
+
|
|
519
|
+
{#if !isSelect && !isDate && !(def instanceof CheckboxDef)}
|
|
520
|
+
<div class="stick-right">
|
|
521
|
+
<Action
|
|
522
|
+
data-type="quicksearch"
|
|
523
|
+
size={Size.FillHeight}
|
|
524
|
+
colourSet={ColourSet.Auxiliary}
|
|
525
|
+
icon={{
|
|
526
|
+
name: 'filter-2',
|
|
527
|
+
size: Size.MediumLarge,
|
|
528
|
+
colour: Colour['$ui-blue-5'],
|
|
529
|
+
}}
|
|
530
|
+
onclick={() => {
|
|
531
|
+
if (!openedSelect) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (openedSelect.value === selectSymbol) {
|
|
535
|
+
openedSelect.value = null;
|
|
536
|
+
} else {
|
|
537
|
+
openedSelect.value = selectSymbol;
|
|
538
|
+
}
|
|
539
|
+
}}
|
|
540
|
+
/>
|
|
541
|
+
</div>
|
|
542
|
+
{/if}
|
|
543
|
+
{/if}
|
|
544
|
+
|
|
545
|
+
{#if isSelectOpen}
|
|
546
|
+
<div
|
|
547
|
+
class="floating"
|
|
548
|
+
transition:fade={{ easing: cubicOut, duration: 100 }}
|
|
549
|
+
>
|
|
550
|
+
<div class="select-wrapper">
|
|
551
|
+
{#if isNumeric}
|
|
552
|
+
<SingleSelect
|
|
553
|
+
options={numberDateFilterTypes}
|
|
554
|
+
labelProp="label"
|
|
555
|
+
valueProp="value"
|
|
556
|
+
name="Filter Type"
|
|
557
|
+
valueAsObject
|
|
558
|
+
value={selectedNumberFilterType}
|
|
559
|
+
onchange={(newValue: SelectOption<NumberDateFilterMode> | null) => {
|
|
560
|
+
const oldFilterType = selectedNumberFilterType;
|
|
561
|
+
|
|
562
|
+
const newFilterType = newValue?.value ?? NumberDateFilterMode.In;
|
|
563
|
+
|
|
564
|
+
if (newFilterType !== oldFilterType?.value) {
|
|
565
|
+
tableContext.paginationRepo?.setFilterMode(def.id, newFilterType);
|
|
566
|
+
|
|
567
|
+
if (newFilterType === NumberDateFilterMode.Between) {
|
|
568
|
+
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMin]);
|
|
569
|
+
} else if (newFilterType === NumberDateFilterMode.In) {
|
|
570
|
+
tableContext.paginationRepo?.filterBy(def.id, [value]);
|
|
571
|
+
} else {
|
|
572
|
+
tableContext.paginationRepo?.filterBy(def.id, [valueMin, valueMax]);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}}
|
|
576
|
+
onkeydown={(e: KeyboardEvent) => {
|
|
577
|
+
e.stopPropagation();
|
|
578
|
+
}}
|
|
579
|
+
/>
|
|
580
|
+
{:else}
|
|
581
|
+
<SingleSelect
|
|
582
|
+
options={stringFilterTypes}
|
|
583
|
+
labelProp="label"
|
|
584
|
+
valueProp="value"
|
|
585
|
+
name="Filter Type"
|
|
586
|
+
valueAsObject
|
|
587
|
+
value={selectedStringFilterType}
|
|
588
|
+
onchange={(newValue: SelectOption<StringFilterMode> | null) => {
|
|
589
|
+
const filterType = newValue?.value ?? StringFilterMode.Contains;
|
|
590
|
+
tableContext.paginationRepo?.setFilterMode(def.id, filterType);
|
|
591
|
+
}}
|
|
592
|
+
onkeydown={(e: KeyboardEvent) => {
|
|
593
|
+
e.stopPropagation();
|
|
594
|
+
}}
|
|
595
|
+
/>
|
|
596
|
+
{/if}
|
|
597
|
+
</div>
|
|
598
|
+
</div>
|
|
599
|
+
{/if}
|
|
600
|
+
</div>
|
|
601
|
+
|
|
679
602
|
<style>.focusable,
|
|
680
603
|
.checkbox-cell,
|
|
681
604
|
.input-cell,
|
|
@@ -815,4 +738,4 @@ div.input-wrapper-parent > :global(.select-wrapper) {
|
|
|
815
738
|
height: 60px;
|
|
816
739
|
--input-height: 60px;
|
|
817
740
|
background-color: #ffffff;
|
|
818
|
-
}</style>
|
|
741
|
+
}</style>
|