@akinon/akifilter 1.0.0 → 1.0.2
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/cjs/akifilter.d.ts.map +1 -1
- package/dist/cjs/akifilter.js +83 -22
- package/dist/cjs/common/theme-overrides.d.ts.map +1 -1
- package/dist/cjs/common/theme-overrides.js +1 -4
- package/dist/cjs/styles.css +7 -5
- package/dist/cjs/utils/schema.js +1 -1
- package/dist/esm/akifilter.d.ts.map +1 -1
- package/dist/esm/akifilter.js +83 -22
- package/dist/esm/common/theme-overrides.d.ts.map +1 -1
- package/dist/esm/common/theme-overrides.js +1 -4
- package/dist/esm/styles.css +7 -5
- package/dist/esm/utils/schema.js +1 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"akifilter.d.ts","sourceRoot":"","sources":["../../src/akifilter.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,OAAO,EAIL,WAAW,EAEX,IAAI,EAGL,MAAM,iBAAiB,CAAC;AAUzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAsB1B,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,SAAS,CAAC;AAU/D,KAAK,oBAAoB,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"akifilter.d.ts","sourceRoot":"","sources":["../../src/akifilter.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,OAAO,EAIL,WAAW,EAEX,IAAI,EAGL,MAAM,iBAAiB,CAAC;AAUzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAsB1B,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,SAAS,CAAC;AAU/D,KAAK,oBAAoB,GAAG,WAAW,CAAC;AA0BxC,MAAM,MAAM,cAAc,CACxB,YAAY,SAAS,oBAAoB,GAAG,oBAAoB,IAC9D;IACF;;OAEG;IACH,YAAY,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC7C;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACtC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACzD;;OAEG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC;IAClE;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAulBF,eAAO,MAAM,SAAS;KACpB,YAAY,SAAS,oBAAoB,uBAElC,cAAc,CAAC,YAAY,CAAC;;CAmBpC,CAAC"}
|
package/dist/cjs/akifilter.js
CHANGED
|
@@ -36,6 +36,23 @@ const use_debounced_value_1 = require("./hooks/use-debounced-value");
|
|
|
36
36
|
const i18n_1 = require("./i18n");
|
|
37
37
|
const schema_1 = require("./utils/schema");
|
|
38
38
|
const values_1 = require("./utils/values");
|
|
39
|
+
const resolveClearedFieldValue = (field, defaultValue) => {
|
|
40
|
+
if (defaultValue !== undefined) {
|
|
41
|
+
return defaultValue;
|
|
42
|
+
}
|
|
43
|
+
switch (field.type) {
|
|
44
|
+
case 'text':
|
|
45
|
+
case 'textarea':
|
|
46
|
+
return '';
|
|
47
|
+
case 'checkbox':
|
|
48
|
+
return false;
|
|
49
|
+
case 'date':
|
|
50
|
+
case 'select':
|
|
51
|
+
return null;
|
|
52
|
+
default:
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
39
56
|
const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onValuesChange, onVisibleFieldsChange, onImportCsv, onImportXls, onClearAll, enableImportCsv, enableImportXls }) => {
|
|
40
57
|
const storageKey = react_1.default.useMemo(() => (0, storage_1.buildStorageKey)(filterSchema, storageNamespace), [filterSchema, storageNamespace]);
|
|
41
58
|
const schemaDefaults = react_1.default.useMemo(() => (0, schema_1.normaliseValuesBySchema)(filterSchema, (0, schema_1.extractDefaultValues)(filterSchema)), [filterSchema]);
|
|
@@ -73,7 +90,7 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
73
90
|
if (field.type === 'checkbox' && currentValue !== true) {
|
|
74
91
|
return acc;
|
|
75
92
|
}
|
|
76
|
-
const label = field.
|
|
93
|
+
const label = field.label || field.placeholder || key;
|
|
77
94
|
const resolveSelectLabel = () => {
|
|
78
95
|
var _a;
|
|
79
96
|
if (!('options' in field) || !field.options) {
|
|
@@ -137,12 +154,25 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
137
154
|
formMethods.reset(mergedDefaultValues);
|
|
138
155
|
}, [formMethods, mergedDefaultValues]);
|
|
139
156
|
const normalisedValues = react_1.default.useMemo(() => (0, values_1.normaliseOutputValues)(filterSchema, formValues), [filterSchema, formValues]);
|
|
140
|
-
const
|
|
141
|
-
|
|
157
|
+
const hasInitialValuesRef = react_1.default.useRef(false);
|
|
158
|
+
react_1.default.useEffect(() => {
|
|
159
|
+
const initialValues = (0, values_1.normaliseOutputValues)(filterSchema, mergedDefaultValues);
|
|
160
|
+
hasInitialValuesRef.current = Object.keys(initialValues).length > 0;
|
|
161
|
+
}, [filterSchema, mergedDefaultValues]);
|
|
142
162
|
const serialisedValues = react_1.default.useMemo(() => JSON.stringify(normalisedValues), [normalisedValues]);
|
|
143
163
|
const debouncedSerialisedValues = (0, use_debounced_value_1.useDebouncedValue)(serialisedValues, constants_1.FILTER_DEBOUNCE_DELAY);
|
|
144
164
|
const lastPersistedValuesRef = react_1.default.useRef(null);
|
|
145
165
|
const hasEmittedValuesRef = react_1.default.useRef(false);
|
|
166
|
+
const persistValues = react_1.default.useCallback((values, serialised) => {
|
|
167
|
+
const nextSerialised = serialised !== null && serialised !== void 0 ? serialised : JSON.stringify(values);
|
|
168
|
+
lastPersistedValuesRef.current = nextSerialised;
|
|
169
|
+
if (Object.keys(values).length === 0) {
|
|
170
|
+
(0, storage_1.clearStoredValues)(storageKey);
|
|
171
|
+
return nextSerialised;
|
|
172
|
+
}
|
|
173
|
+
(0, storage_1.writeStoredValues)(storageKey, values);
|
|
174
|
+
return nextSerialised;
|
|
175
|
+
}, [storageKey]);
|
|
146
176
|
react_1.default.useEffect(() => {
|
|
147
177
|
if (debouncedSerialisedValues == null) {
|
|
148
178
|
return;
|
|
@@ -153,30 +183,45 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
153
183
|
}
|
|
154
184
|
const parsedValues = JSON.parse(debouncedSerialisedValues);
|
|
155
185
|
const isEmpty = Object.keys(parsedValues).length === 0;
|
|
156
|
-
if (!hasEmittedValuesRef.current &&
|
|
186
|
+
if (!hasEmittedValuesRef.current &&
|
|
187
|
+
isEmpty &&
|
|
188
|
+
!hasInitialValuesRef.current) {
|
|
157
189
|
hasEmittedValuesRef.current = true;
|
|
158
|
-
|
|
159
|
-
(0, storage_1.clearStoredValues)(storageKey);
|
|
190
|
+
persistValues(parsedValues, debouncedSerialisedValues);
|
|
160
191
|
return;
|
|
161
192
|
}
|
|
162
193
|
hasEmittedValuesRef.current = true;
|
|
163
|
-
lastPersistedValuesRef.current = debouncedSerialisedValues;
|
|
164
194
|
onValuesChange === null || onValuesChange === void 0 ? void 0 : onValuesChange(parsedValues);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
(0, storage_1.writeStoredValues)(storageKey, parsedValues);
|
|
170
|
-
}
|
|
171
|
-
}, [debouncedSerialisedValues, hasInitialValues, onValuesChange, storageKey]);
|
|
195
|
+
persistValues(parsedValues, debouncedSerialisedValues);
|
|
196
|
+
}, [debouncedSerialisedValues, onValuesChange, persistValues]);
|
|
172
197
|
react_1.default.useEffect(() => {
|
|
173
198
|
lastPersistedValuesRef.current = null;
|
|
174
199
|
}, [storageKey]);
|
|
175
200
|
const handleClearAll = react_1.default.useCallback(() => {
|
|
176
|
-
|
|
201
|
+
const clearedDefaults = Object.assign({}, baseDefaultValues);
|
|
202
|
+
filterSchema.forEach(field => {
|
|
203
|
+
const key = String(field.key);
|
|
204
|
+
const defaultValue = baseDefaultValues[key];
|
|
205
|
+
const resolved = resolveClearedFieldValue(field, defaultValue);
|
|
206
|
+
if (resolved === undefined) {
|
|
207
|
+
delete clearedDefaults[key];
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
clearedDefaults[key] = resolved;
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
formMethods.reset(clearedDefaults, {
|
|
214
|
+
keepDirty: false,
|
|
215
|
+
keepTouched: false
|
|
216
|
+
});
|
|
177
217
|
onClearAll === null || onClearAll === void 0 ? void 0 : onClearAll();
|
|
178
|
-
(0,
|
|
179
|
-
|
|
218
|
+
const nextValues = (0, values_1.normaliseOutputValues)(filterSchema, clearedDefaults);
|
|
219
|
+
hasInitialValuesRef.current = Object.keys(nextValues).length > 0;
|
|
220
|
+
const nextSerialised = persistValues(nextValues);
|
|
221
|
+
hasEmittedValuesRef.current = true;
|
|
222
|
+
lastPersistedValuesRef.current = nextSerialised !== null && nextSerialised !== void 0 ? nextSerialised : null;
|
|
223
|
+
onValuesChange === null || onValuesChange === void 0 ? void 0 : onValuesChange(nextValues);
|
|
224
|
+
}, [baseDefaultValues, filterSchema, formMethods, onClearAll, persistValues]);
|
|
180
225
|
const handleOpenModal = react_1.default.useCallback(() => {
|
|
181
226
|
setIsModalOpen(true);
|
|
182
227
|
setSearchTerm('');
|
|
@@ -203,10 +248,26 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
203
248
|
return;
|
|
204
249
|
}
|
|
205
250
|
const defaultValue = baseDefaultValues[String(schemaField.key)];
|
|
206
|
-
|
|
207
|
-
|
|
251
|
+
const fieldPath = schemaField.key;
|
|
252
|
+
const nextValue = resolveClearedFieldValue(schemaField, defaultValue);
|
|
253
|
+
formMethods.setValue(fieldPath, nextValue, {
|
|
254
|
+
shouldDirty: false,
|
|
255
|
+
shouldTouch: false,
|
|
256
|
+
shouldValidate: false
|
|
208
257
|
});
|
|
209
|
-
|
|
258
|
+
const nextValues = (0, values_1.normaliseOutputValues)(filterSchema, formMethods.getValues());
|
|
259
|
+
const nextSerialised = persistValues(nextValues);
|
|
260
|
+
hasEmittedValuesRef.current = true;
|
|
261
|
+
lastPersistedValuesRef.current = nextSerialised !== null && nextSerialised !== void 0 ? nextSerialised : null;
|
|
262
|
+
hasInitialValuesRef.current = Object.keys(nextValues).length > 0;
|
|
263
|
+
onValuesChange === null || onValuesChange === void 0 ? void 0 : onValuesChange(nextValues);
|
|
264
|
+
}, [
|
|
265
|
+
baseDefaultValues,
|
|
266
|
+
filterSchema,
|
|
267
|
+
formMethods,
|
|
268
|
+
onValuesChange,
|
|
269
|
+
persistValues
|
|
270
|
+
]);
|
|
210
271
|
const filteredFields = react_1.default.useMemo(() => {
|
|
211
272
|
const normalisedTerm = searchTerm.trim().toLowerCase();
|
|
212
273
|
if (!normalisedTerm) {
|
|
@@ -236,7 +297,7 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
236
297
|
case 'checkbox':
|
|
237
298
|
return react_1.default.createElement(ui_checkbox_1.Checkbox, null, field.label);
|
|
238
299
|
case 'date':
|
|
239
|
-
return (react_1.default.createElement(ui_date_picker_1.DatePicker, { placeholder: field.placeholder,
|
|
300
|
+
return (react_1.default.createElement(ui_date_picker_1.DatePicker, { placeholder: field.placeholder, showTime: field.showTime, suffixIcon: "calendar", suffixIconSize: "16px", "aria-label": ariaLabel }));
|
|
240
301
|
case 'textarea':
|
|
241
302
|
return (react_1.default.createElement(ui_input_1.InputTextArea, { placeholder: field.placeholder, autoSize: { minRows: 3, maxRows: 6 }, "aria-label": ariaLabel }));
|
|
242
303
|
case 'custom':
|
|
@@ -261,7 +322,7 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
261
322
|
react_1.default.createElement("div", { className: "akinon-filter__body" },
|
|
262
323
|
react_1.default.createElement(akiform_1.Akiform, { layout: "vertical", className: "akinon-filter__form" },
|
|
263
324
|
react_1.default.createElement("div", { className: "akinon-filter__form-grid", "data-testid": "akifilter-form-grid" },
|
|
264
|
-
visibleFields.map(field => (react_1.default.createElement(akiform_1.FormItem, { key: String(field.key), control: formMethods.control, name: field.key, tooltip: field.tooltip, help: field.help, labelDescription: field.labelDescription, required: Boolean(field.validation), valuePropName: field.type === 'checkbox' ? 'checked' : undefined }, renderFieldComponent(field)))),
|
|
325
|
+
visibleFields.map(field => (react_1.default.createElement(akiform_1.FormItem, { key: String(field.key), control: formMethods.control, name: field.key, tooltip: field.tooltip, help: field.help, labelDescription: field.labelDescription, required: Boolean(field.validation), className: "mb-0", valuePropName: field.type === 'checkbox' ? 'checked' : undefined }, renderFieldComponent(field)))),
|
|
265
326
|
visibleFields.length === 0 ? (react_1.default.createElement("div", { className: "akinon-filter__empty" }, i18n_1.i18n.t('form.noVisibleFields'))) : null))),
|
|
266
327
|
react_1.default.createElement(visibility_modal_1.VisibilityModal, { open: isModalOpen, onClose: handleCloseModal, searchTerm: searchTerm, paginatedFields: paginatedFields, filteredCount: filteredFields.length, visibleKeys: visibleKeys, onSearchTermChange: value => {
|
|
267
328
|
setSearchTerm(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-overrides.d.ts","sourceRoot":"","sources":["../../../src/common/theme-overrides.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAEnC,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"theme-overrides.d.ts","sourceRoot":"","sources":["../../../src/common/theme-overrides.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAEnC,eAAO,MAAM,cAAc,EAAE,WAkB5B,CAAC"}
|
|
@@ -3,7 +3,4 @@ var _a, _b;
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.themeOverrides = void 0;
|
|
5
5
|
const ui_theme_1 = require("@akinon/ui-theme");
|
|
6
|
-
exports.themeOverrides = Object.assign(Object.assign({}, ui_theme_1.theme), { algorithm: ui_theme_1.theme.algorithm,
|
|
7
|
-
colorTextBase: ui_theme_1.theme.colors.ebonyClay['900'],
|
|
8
|
-
colorText: ui_theme_1.theme.colors.ebonyClay['900']
|
|
9
|
-
}, components: Object.assign(Object.assign({}, ui_theme_1.theme.components), { Typography: Object.assign(Object.assign({}, (_a = ui_theme_1.theme.components) === null || _a === void 0 ? void 0 : _a.Typography), { colorTextHeading: ui_theme_1.theme.colors.neutral['100'], colorText: ui_theme_1.theme.colors.neutral['500'], titleMarginBottom: 0 }), Modal: Object.assign(Object.assign({}, (_b = ui_theme_1.theme.components) === null || _b === void 0 ? void 0 : _b.Modal), { headerBg: ui_theme_1.theme.colors.ebonyClay['600'], contentBg: ui_theme_1.theme.colors.ebonyClay['600'], titleColor: ui_theme_1.theme.colors.neutral['200'] }) }) });
|
|
6
|
+
exports.themeOverrides = Object.assign(Object.assign({}, ui_theme_1.theme), { algorithm: ui_theme_1.theme.algorithm, components: Object.assign(Object.assign({}, ui_theme_1.theme.components), { Typography: Object.assign(Object.assign({}, (_a = ui_theme_1.theme.components) === null || _a === void 0 ? void 0 : _a.Typography), { colorTextHeading: ui_theme_1.theme.colors.neutral['100'], colorText: ui_theme_1.theme.colors.neutral['500'], titleMarginBottom: 0 }), Modal: Object.assign(Object.assign({}, (_b = ui_theme_1.theme.components) === null || _b === void 0 ? void 0 : _b.Modal), { headerBg: ui_theme_1.theme.colors.ebonyClay['600'], contentBg: ui_theme_1.theme.colors.ebonyClay['600'], titleColor: ui_theme_1.theme.colors.neutral['200'] }) }) });
|
package/dist/cjs/styles.css
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
.akinon-filter__form-grid {
|
|
55
55
|
display: grid;
|
|
56
56
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
57
|
-
gap:
|
|
57
|
+
gap: 8px;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
.akinon-filter__form-grid > .akinon-form-item {
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
color: color(--color-ebonyClay-500);
|
|
121
121
|
font-size: 12px;
|
|
122
122
|
position: relative;
|
|
123
|
-
top:
|
|
123
|
+
top: 1px;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
.akinon-filter__modal-list {
|
|
@@ -172,11 +172,13 @@
|
|
|
172
172
|
max-width: 360px;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
.akinon-filter__field--number {
|
|
176
|
+
display: block;
|
|
177
|
+
width: auto;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
/* Modal window. */
|
|
181
|
+
|
|
180
182
|
.akinon-filter__modal-toolbar {
|
|
181
183
|
margin-bottom: 1rem;
|
|
182
184
|
}
|
package/dist/cjs/utils/schema.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.normaliseValuesBySchema = exports.extractDefaultValues = exports.deriveD
|
|
|
4
4
|
const akidate_1 = require("@akinon/akidate");
|
|
5
5
|
const constants_1 = require("../constants");
|
|
6
6
|
const getDisplayLabel = (field) => {
|
|
7
|
-
return field.
|
|
7
|
+
return field.label || field.placeholder || String(field.key);
|
|
8
8
|
};
|
|
9
9
|
exports.getDisplayLabel = getDisplayLabel;
|
|
10
10
|
const getFieldAriaLabel = (field) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"akifilter.d.ts","sourceRoot":"","sources":["../../src/akifilter.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,OAAO,EAIL,WAAW,EAEX,IAAI,EAGL,MAAM,iBAAiB,CAAC;AAUzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAsB1B,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,SAAS,CAAC;AAU/D,KAAK,oBAAoB,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"akifilter.d.ts","sourceRoot":"","sources":["../../src/akifilter.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,OAAO,EAIL,WAAW,EAEX,IAAI,EAGL,MAAM,iBAAiB,CAAC;AAUzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAsB1B,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,SAAS,CAAC;AAU/D,KAAK,oBAAoB,GAAG,WAAW,CAAC;AA0BxC,MAAM,MAAM,cAAc,CACxB,YAAY,SAAS,oBAAoB,GAAG,oBAAoB,IAC9D;IACF;;OAEG;IACH,YAAY,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC7C;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACtC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACzD;;OAEG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC;IAClE;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAulBF,eAAO,MAAM,SAAS;KACpB,YAAY,SAAS,oBAAoB,uBAElC,cAAc,CAAC,YAAY,CAAC;;CAmBpC,CAAC"}
|
package/dist/esm/akifilter.js
CHANGED
|
@@ -33,6 +33,23 @@ import { useDebouncedValue } from './hooks/use-debounced-value';
|
|
|
33
33
|
import { i18n } from './i18n';
|
|
34
34
|
import { deriveDefaultVisibleKeys, ensureSchemaOrder, extractDefaultValues, getFieldAriaLabel, normaliseValuesBySchema } from './utils/schema';
|
|
35
35
|
import { normaliseOutputValues } from './utils/values';
|
|
36
|
+
const resolveClearedFieldValue = (field, defaultValue) => {
|
|
37
|
+
if (defaultValue !== undefined) {
|
|
38
|
+
return defaultValue;
|
|
39
|
+
}
|
|
40
|
+
switch (field.type) {
|
|
41
|
+
case 'text':
|
|
42
|
+
case 'textarea':
|
|
43
|
+
return '';
|
|
44
|
+
case 'checkbox':
|
|
45
|
+
return false;
|
|
46
|
+
case 'date':
|
|
47
|
+
case 'select':
|
|
48
|
+
return null;
|
|
49
|
+
default:
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
36
53
|
const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onValuesChange, onVisibleFieldsChange, onImportCsv, onImportXls, onClearAll, enableImportCsv, enableImportXls }) => {
|
|
37
54
|
const storageKey = React.useMemo(() => buildStorageKey(filterSchema, storageNamespace), [filterSchema, storageNamespace]);
|
|
38
55
|
const schemaDefaults = React.useMemo(() => normaliseValuesBySchema(filterSchema, extractDefaultValues(filterSchema)), [filterSchema]);
|
|
@@ -70,7 +87,7 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
70
87
|
if (field.type === 'checkbox' && currentValue !== true) {
|
|
71
88
|
return acc;
|
|
72
89
|
}
|
|
73
|
-
const label = field.
|
|
90
|
+
const label = field.label || field.placeholder || key;
|
|
74
91
|
const resolveSelectLabel = () => {
|
|
75
92
|
var _a;
|
|
76
93
|
if (!('options' in field) || !field.options) {
|
|
@@ -134,12 +151,25 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
134
151
|
formMethods.reset(mergedDefaultValues);
|
|
135
152
|
}, [formMethods, mergedDefaultValues]);
|
|
136
153
|
const normalisedValues = React.useMemo(() => normaliseOutputValues(filterSchema, formValues), [filterSchema, formValues]);
|
|
137
|
-
const
|
|
138
|
-
|
|
154
|
+
const hasInitialValuesRef = React.useRef(false);
|
|
155
|
+
React.useEffect(() => {
|
|
156
|
+
const initialValues = normaliseOutputValues(filterSchema, mergedDefaultValues);
|
|
157
|
+
hasInitialValuesRef.current = Object.keys(initialValues).length > 0;
|
|
158
|
+
}, [filterSchema, mergedDefaultValues]);
|
|
139
159
|
const serialisedValues = React.useMemo(() => JSON.stringify(normalisedValues), [normalisedValues]);
|
|
140
160
|
const debouncedSerialisedValues = useDebouncedValue(serialisedValues, FILTER_DEBOUNCE_DELAY);
|
|
141
161
|
const lastPersistedValuesRef = React.useRef(null);
|
|
142
162
|
const hasEmittedValuesRef = React.useRef(false);
|
|
163
|
+
const persistValues = React.useCallback((values, serialised) => {
|
|
164
|
+
const nextSerialised = serialised !== null && serialised !== void 0 ? serialised : JSON.stringify(values);
|
|
165
|
+
lastPersistedValuesRef.current = nextSerialised;
|
|
166
|
+
if (Object.keys(values).length === 0) {
|
|
167
|
+
clearStoredValues(storageKey);
|
|
168
|
+
return nextSerialised;
|
|
169
|
+
}
|
|
170
|
+
writeStoredValues(storageKey, values);
|
|
171
|
+
return nextSerialised;
|
|
172
|
+
}, [storageKey]);
|
|
143
173
|
React.useEffect(() => {
|
|
144
174
|
if (debouncedSerialisedValues == null) {
|
|
145
175
|
return;
|
|
@@ -150,30 +180,45 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
150
180
|
}
|
|
151
181
|
const parsedValues = JSON.parse(debouncedSerialisedValues);
|
|
152
182
|
const isEmpty = Object.keys(parsedValues).length === 0;
|
|
153
|
-
if (!hasEmittedValuesRef.current &&
|
|
183
|
+
if (!hasEmittedValuesRef.current &&
|
|
184
|
+
isEmpty &&
|
|
185
|
+
!hasInitialValuesRef.current) {
|
|
154
186
|
hasEmittedValuesRef.current = true;
|
|
155
|
-
|
|
156
|
-
clearStoredValues(storageKey);
|
|
187
|
+
persistValues(parsedValues, debouncedSerialisedValues);
|
|
157
188
|
return;
|
|
158
189
|
}
|
|
159
190
|
hasEmittedValuesRef.current = true;
|
|
160
|
-
lastPersistedValuesRef.current = debouncedSerialisedValues;
|
|
161
191
|
onValuesChange === null || onValuesChange === void 0 ? void 0 : onValuesChange(parsedValues);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
writeStoredValues(storageKey, parsedValues);
|
|
167
|
-
}
|
|
168
|
-
}, [debouncedSerialisedValues, hasInitialValues, onValuesChange, storageKey]);
|
|
192
|
+
persistValues(parsedValues, debouncedSerialisedValues);
|
|
193
|
+
}, [debouncedSerialisedValues, onValuesChange, persistValues]);
|
|
169
194
|
React.useEffect(() => {
|
|
170
195
|
lastPersistedValuesRef.current = null;
|
|
171
196
|
}, [storageKey]);
|
|
172
197
|
const handleClearAll = React.useCallback(() => {
|
|
173
|
-
|
|
198
|
+
const clearedDefaults = Object.assign({}, baseDefaultValues);
|
|
199
|
+
filterSchema.forEach(field => {
|
|
200
|
+
const key = String(field.key);
|
|
201
|
+
const defaultValue = baseDefaultValues[key];
|
|
202
|
+
const resolved = resolveClearedFieldValue(field, defaultValue);
|
|
203
|
+
if (resolved === undefined) {
|
|
204
|
+
delete clearedDefaults[key];
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
clearedDefaults[key] = resolved;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
formMethods.reset(clearedDefaults, {
|
|
211
|
+
keepDirty: false,
|
|
212
|
+
keepTouched: false
|
|
213
|
+
});
|
|
174
214
|
onClearAll === null || onClearAll === void 0 ? void 0 : onClearAll();
|
|
175
|
-
|
|
176
|
-
|
|
215
|
+
const nextValues = normaliseOutputValues(filterSchema, clearedDefaults);
|
|
216
|
+
hasInitialValuesRef.current = Object.keys(nextValues).length > 0;
|
|
217
|
+
const nextSerialised = persistValues(nextValues);
|
|
218
|
+
hasEmittedValuesRef.current = true;
|
|
219
|
+
lastPersistedValuesRef.current = nextSerialised !== null && nextSerialised !== void 0 ? nextSerialised : null;
|
|
220
|
+
onValuesChange === null || onValuesChange === void 0 ? void 0 : onValuesChange(nextValues);
|
|
221
|
+
}, [baseDefaultValues, filterSchema, formMethods, onClearAll, persistValues]);
|
|
177
222
|
const handleOpenModal = React.useCallback(() => {
|
|
178
223
|
setIsModalOpen(true);
|
|
179
224
|
setSearchTerm('');
|
|
@@ -200,10 +245,26 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
200
245
|
return;
|
|
201
246
|
}
|
|
202
247
|
const defaultValue = baseDefaultValues[String(schemaField.key)];
|
|
203
|
-
|
|
204
|
-
|
|
248
|
+
const fieldPath = schemaField.key;
|
|
249
|
+
const nextValue = resolveClearedFieldValue(schemaField, defaultValue);
|
|
250
|
+
formMethods.setValue(fieldPath, nextValue, {
|
|
251
|
+
shouldDirty: false,
|
|
252
|
+
shouldTouch: false,
|
|
253
|
+
shouldValidate: false
|
|
205
254
|
});
|
|
206
|
-
|
|
255
|
+
const nextValues = normaliseOutputValues(filterSchema, formMethods.getValues());
|
|
256
|
+
const nextSerialised = persistValues(nextValues);
|
|
257
|
+
hasEmittedValuesRef.current = true;
|
|
258
|
+
lastPersistedValuesRef.current = nextSerialised !== null && nextSerialised !== void 0 ? nextSerialised : null;
|
|
259
|
+
hasInitialValuesRef.current = Object.keys(nextValues).length > 0;
|
|
260
|
+
onValuesChange === null || onValuesChange === void 0 ? void 0 : onValuesChange(nextValues);
|
|
261
|
+
}, [
|
|
262
|
+
baseDefaultValues,
|
|
263
|
+
filterSchema,
|
|
264
|
+
formMethods,
|
|
265
|
+
onValuesChange,
|
|
266
|
+
persistValues
|
|
267
|
+
]);
|
|
207
268
|
const filteredFields = React.useMemo(() => {
|
|
208
269
|
const normalisedTerm = searchTerm.trim().toLowerCase();
|
|
209
270
|
if (!normalisedTerm) {
|
|
@@ -233,7 +294,7 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
233
294
|
case 'checkbox':
|
|
234
295
|
return React.createElement(Checkbox, null, field.label);
|
|
235
296
|
case 'date':
|
|
236
|
-
return (React.createElement(DatePicker, { placeholder: field.placeholder,
|
|
297
|
+
return (React.createElement(DatePicker, { placeholder: field.placeholder, showTime: field.showTime, suffixIcon: "calendar", suffixIconSize: "16px", "aria-label": ariaLabel }));
|
|
237
298
|
case 'textarea':
|
|
238
299
|
return (React.createElement(InputTextArea, { placeholder: field.placeholder, autoSize: { minRows: 3, maxRows: 6 }, "aria-label": ariaLabel }));
|
|
239
300
|
case 'custom':
|
|
@@ -258,7 +319,7 @@ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onVal
|
|
|
258
319
|
React.createElement("div", { className: "akinon-filter__body" },
|
|
259
320
|
React.createElement(Akiform, { layout: "vertical", className: "akinon-filter__form" },
|
|
260
321
|
React.createElement("div", { className: "akinon-filter__form-grid", "data-testid": "akifilter-form-grid" },
|
|
261
|
-
visibleFields.map(field => (React.createElement(FormItem, { key: String(field.key), control: formMethods.control, name: field.key, tooltip: field.tooltip, help: field.help, labelDescription: field.labelDescription, required: Boolean(field.validation), valuePropName: field.type === 'checkbox' ? 'checked' : undefined }, renderFieldComponent(field)))),
|
|
322
|
+
visibleFields.map(field => (React.createElement(FormItem, { key: String(field.key), control: formMethods.control, name: field.key, tooltip: field.tooltip, help: field.help, labelDescription: field.labelDescription, required: Boolean(field.validation), className: "mb-0", valuePropName: field.type === 'checkbox' ? 'checked' : undefined }, renderFieldComponent(field)))),
|
|
262
323
|
visibleFields.length === 0 ? (React.createElement("div", { className: "akinon-filter__empty" }, i18n.t('form.noVisibleFields'))) : null))),
|
|
263
324
|
React.createElement(VisibilityModal, { open: isModalOpen, onClose: handleCloseModal, searchTerm: searchTerm, paginatedFields: paginatedFields, filteredCount: filteredFields.length, visibleKeys: visibleKeys, onSearchTermChange: value => {
|
|
264
325
|
setSearchTerm(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-overrides.d.ts","sourceRoot":"","sources":["../../../src/common/theme-overrides.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAEnC,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"theme-overrides.d.ts","sourceRoot":"","sources":["../../../src/common/theme-overrides.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAEnC,eAAO,MAAM,cAAc,EAAE,WAkB5B,CAAC"}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
var _a, _b;
|
|
2
2
|
import { theme } from '@akinon/ui-theme';
|
|
3
|
-
export const themeOverrides = Object.assign(Object.assign({}, theme), { algorithm: theme.algorithm,
|
|
4
|
-
colorTextBase: theme.colors.ebonyClay['900'],
|
|
5
|
-
colorText: theme.colors.ebonyClay['900']
|
|
6
|
-
}, components: Object.assign(Object.assign({}, theme.components), { Typography: Object.assign(Object.assign({}, (_a = theme.components) === null || _a === void 0 ? void 0 : _a.Typography), { colorTextHeading: theme.colors.neutral['100'], colorText: theme.colors.neutral['500'], titleMarginBottom: 0 }), Modal: Object.assign(Object.assign({}, (_b = theme.components) === null || _b === void 0 ? void 0 : _b.Modal), { headerBg: theme.colors.ebonyClay['600'], contentBg: theme.colors.ebonyClay['600'], titleColor: theme.colors.neutral['200'] }) }) });
|
|
3
|
+
export const themeOverrides = Object.assign(Object.assign({}, theme), { algorithm: theme.algorithm, components: Object.assign(Object.assign({}, theme.components), { Typography: Object.assign(Object.assign({}, (_a = theme.components) === null || _a === void 0 ? void 0 : _a.Typography), { colorTextHeading: theme.colors.neutral['100'], colorText: theme.colors.neutral['500'], titleMarginBottom: 0 }), Modal: Object.assign(Object.assign({}, (_b = theme.components) === null || _b === void 0 ? void 0 : _b.Modal), { headerBg: theme.colors.ebonyClay['600'], contentBg: theme.colors.ebonyClay['600'], titleColor: theme.colors.neutral['200'] }) }) });
|
package/dist/esm/styles.css
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
.akinon-filter__form-grid {
|
|
55
55
|
display: grid;
|
|
56
56
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
57
|
-
gap:
|
|
57
|
+
gap: 8px;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
.akinon-filter__form-grid > .akinon-form-item {
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
color: color(--color-ebonyClay-500);
|
|
121
121
|
font-size: 12px;
|
|
122
122
|
position: relative;
|
|
123
|
-
top:
|
|
123
|
+
top: 1px;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
.akinon-filter__modal-list {
|
|
@@ -172,11 +172,13 @@
|
|
|
172
172
|
max-width: 360px;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
.akinon-filter__field--number {
|
|
176
|
+
display: block;
|
|
177
|
+
width: auto;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
/* Modal window. */
|
|
181
|
+
|
|
180
182
|
.akinon-filter__modal-toolbar {
|
|
181
183
|
margin-bottom: 1rem;
|
|
182
184
|
}
|
package/dist/esm/utils/schema.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { akidate } from '@akinon/akidate';
|
|
2
2
|
import { DEFAULT_VISIBLE_COUNT } from '../constants';
|
|
3
3
|
export const getDisplayLabel = (field) => {
|
|
4
|
-
return field.
|
|
4
|
+
return field.label || field.placeholder || String(field.key);
|
|
5
5
|
};
|
|
6
6
|
export const getFieldAriaLabel = (field) => {
|
|
7
7
|
return field.label || field.placeholder || String(field.key);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/akifilter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Akifilter is a filtering library for Akinon frontend applications.",
|
|
6
6
|
"type": "module",
|
|
@@ -12,21 +12,21 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"antd": "^5.27.0",
|
|
14
14
|
"react-error-boundary": "^6.0.0",
|
|
15
|
-
"@akinon/akilocale": "1.2.0",
|
|
16
15
|
"@akinon/akiform": "1.1.1",
|
|
16
|
+
"@akinon/akidate": "1.1.1",
|
|
17
17
|
"@akinon/icons": "1.1.0",
|
|
18
|
+
"@akinon/ui-button": "1.3.0",
|
|
19
|
+
"@akinon/akilocale": "1.2.0",
|
|
18
20
|
"@akinon/ui-checkbox": "1.3.0",
|
|
19
21
|
"@akinon/ui-card": "1.1.0",
|
|
22
|
+
"@akinon/ui-date-picker": "1.3.0",
|
|
20
23
|
"@akinon/ui-input": "1.1.0",
|
|
21
|
-
"@akinon/akidate": "1.1.1",
|
|
22
24
|
"@akinon/ui-input-number": "1.3.0",
|
|
23
|
-
"@akinon/ui-modal": "1.1.0",
|
|
24
25
|
"@akinon/ui-pagination": "1.3.1",
|
|
25
|
-
"@akinon/ui-
|
|
26
|
+
"@akinon/ui-modal": "1.1.0",
|
|
26
27
|
"@akinon/ui-select": "1.3.1",
|
|
27
28
|
"@akinon/ui-space": "1.3.0",
|
|
28
|
-
"@akinon/ui-typography": "1.1.0"
|
|
29
|
-
"@akinon/ui-button": "1.3.0"
|
|
29
|
+
"@akinon/ui-typography": "1.1.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"clean-package": "2.2.0",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"@akinon/akiform-builder": "1.3.2",
|
|
37
37
|
"@akinon/typescript-config": "1.1.0",
|
|
38
38
|
"@akinon/ui-theme": "1.1.0",
|
|
39
|
-
"@akinon/
|
|
40
|
-
"@akinon/
|
|
39
|
+
"@akinon/vitest-config": "1.1.0",
|
|
40
|
+
"@akinon/utils": "1.1.1"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"react": "^18 || ^19",
|