@akinon/akifilter 0.5.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +44 -0
  2. package/dist/cjs/akifilter.d.ts +53 -0
  3. package/dist/cjs/akifilter.d.ts.map +1 -0
  4. package/dist/cjs/akifilter.js +299 -0
  5. package/dist/cjs/common/storage.d.ts +10 -0
  6. package/dist/cjs/common/storage.d.ts.map +1 -0
  7. package/dist/cjs/common/storage.js +124 -0
  8. package/dist/cjs/common/theme-overrides.d.ts +3 -0
  9. package/dist/cjs/common/theme-overrides.d.ts.map +1 -0
  10. package/dist/cjs/common/theme-overrides.js +9 -0
  11. package/dist/cjs/components/applied-filters.d.ts +14 -0
  12. package/dist/cjs/components/applied-filters.d.ts.map +1 -0
  13. package/dist/cjs/components/applied-filters.js +26 -0
  14. package/dist/cjs/components/filter-toolbar.d.ts +11 -0
  15. package/dist/cjs/components/filter-toolbar.d.ts.map +1 -0
  16. package/dist/cjs/components/filter-toolbar.js +17 -0
  17. package/dist/cjs/components/visibility-modal.d.ts +19 -0
  18. package/dist/cjs/components/visibility-modal.d.ts.map +1 -0
  19. package/dist/cjs/components/visibility-modal.js +30 -0
  20. package/dist/cjs/constants.d.ts +4 -0
  21. package/dist/cjs/constants.d.ts.map +1 -0
  22. package/dist/cjs/constants.js +6 -0
  23. package/dist/cjs/hooks/use-debounced-value.d.ts +2 -0
  24. package/dist/cjs/hooks/use-debounced-value.d.ts.map +1 -0
  25. package/dist/cjs/hooks/use-debounced-value.js +17 -0
  26. package/dist/cjs/i18n/index.d.ts +2 -4
  27. package/dist/cjs/i18n/index.d.ts.map +1 -1
  28. package/dist/cjs/i18n/index.js +1 -1
  29. package/dist/cjs/i18n/translations/en.d.ts +33 -3
  30. package/dist/cjs/i18n/translations/en.d.ts.map +1 -1
  31. package/dist/cjs/i18n/translations/en.js +33 -3
  32. package/dist/cjs/i18n/translations/tr.d.ts +33 -3
  33. package/dist/cjs/i18n/translations/tr.d.ts.map +1 -1
  34. package/dist/cjs/i18n/translations/tr.js +33 -3
  35. package/dist/cjs/index.d.ts +3 -14
  36. package/dist/cjs/index.d.ts.map +1 -1
  37. package/dist/cjs/index.js +17 -32
  38. package/dist/cjs/styles.css +182 -0
  39. package/dist/cjs/types.d.ts +11 -0
  40. package/dist/cjs/types.d.ts.map +1 -0
  41. package/dist/cjs/types.js +2 -0
  42. package/dist/cjs/utils/schema.d.ts +9 -0
  43. package/dist/cjs/utils/schema.d.ts.map +1 -0
  44. package/dist/cjs/utils/schema.js +61 -0
  45. package/dist/cjs/utils/values.d.ts +5 -0
  46. package/dist/cjs/utils/values.d.ts.map +1 -0
  47. package/dist/cjs/utils/values.js +44 -0
  48. package/dist/esm/akifilter.d.ts +53 -0
  49. package/dist/esm/akifilter.d.ts.map +1 -0
  50. package/dist/esm/akifilter.js +295 -0
  51. package/dist/esm/common/storage.d.ts +10 -0
  52. package/dist/esm/common/storage.d.ts.map +1 -0
  53. package/dist/esm/common/storage.js +114 -0
  54. package/dist/esm/common/theme-overrides.d.ts +3 -0
  55. package/dist/esm/common/theme-overrides.d.ts.map +1 -0
  56. package/dist/esm/common/theme-overrides.js +6 -0
  57. package/dist/esm/components/applied-filters.d.ts +14 -0
  58. package/dist/esm/components/applied-filters.d.ts.map +1 -0
  59. package/dist/esm/components/applied-filters.js +22 -0
  60. package/dist/esm/components/filter-toolbar.d.ts +11 -0
  61. package/dist/esm/components/filter-toolbar.d.ts.map +1 -0
  62. package/dist/esm/components/filter-toolbar.js +13 -0
  63. package/dist/esm/components/visibility-modal.d.ts +19 -0
  64. package/dist/esm/components/visibility-modal.d.ts.map +1 -0
  65. package/dist/esm/components/visibility-modal.js +26 -0
  66. package/dist/esm/constants.d.ts +4 -0
  67. package/dist/esm/constants.d.ts.map +1 -0
  68. package/dist/esm/constants.js +3 -0
  69. package/dist/esm/hooks/use-debounced-value.d.ts +2 -0
  70. package/dist/esm/hooks/use-debounced-value.d.ts.map +1 -0
  71. package/dist/esm/hooks/use-debounced-value.js +13 -0
  72. package/dist/esm/i18n/index.d.ts +2 -4
  73. package/dist/esm/i18n/index.d.ts.map +1 -1
  74. package/dist/esm/i18n/index.js +5 -5
  75. package/dist/esm/i18n/translations/en.d.ts +33 -3
  76. package/dist/esm/i18n/translations/en.d.ts.map +1 -1
  77. package/dist/esm/i18n/translations/en.js +33 -3
  78. package/dist/esm/i18n/translations/tr.d.ts +33 -3
  79. package/dist/esm/i18n/translations/tr.d.ts.map +1 -1
  80. package/dist/esm/i18n/translations/tr.js +33 -3
  81. package/dist/esm/index.d.ts +3 -14
  82. package/dist/esm/index.d.ts.map +1 -1
  83. package/dist/esm/index.js +3 -30
  84. package/dist/esm/styles.css +182 -0
  85. package/dist/esm/types.d.ts +11 -0
  86. package/dist/esm/types.d.ts.map +1 -0
  87. package/dist/esm/types.js +1 -0
  88. package/dist/esm/utils/schema.d.ts +9 -0
  89. package/dist/esm/utils/schema.d.ts.map +1 -0
  90. package/dist/esm/utils/schema.js +52 -0
  91. package/dist/esm/utils/values.d.ts +5 -0
  92. package/dist/esm/utils/values.d.ts.map +1 -0
  93. package/dist/esm/utils/values.js +39 -0
  94. package/package.json +40 -33
  95. package/dist/cjs/components/AppliedFilters/AppliedFilterItem.d.ts +0 -12
  96. package/dist/cjs/components/AppliedFilters/AppliedFilterItem.d.ts.map +0 -1
  97. package/dist/cjs/components/AppliedFilters/AppliedFilterItem.js +0 -62
  98. package/dist/cjs/components/AppliedFilters/common.d.ts +0 -6
  99. package/dist/cjs/components/AppliedFilters/common.d.ts.map +0 -1
  100. package/dist/cjs/components/AppliedFilters/common.js +0 -33
  101. package/dist/cjs/components/AppliedFilters/index.d.ts +0 -4
  102. package/dist/cjs/components/AppliedFilters/index.d.ts.map +0 -1
  103. package/dist/cjs/components/AppliedFilters/index.js +0 -26
  104. package/dist/cjs/components/AppliedFilters/styles.css +0 -65
  105. package/dist/cjs/components/ConditionalFilters/index.d.ts +0 -3
  106. package/dist/cjs/components/ConditionalFilters/index.d.ts.map +0 -1
  107. package/dist/cjs/components/ConditionalFilters/index.js +0 -32
  108. package/dist/cjs/components/FilterContext/index.d.ts +0 -45
  109. package/dist/cjs/components/FilterContext/index.d.ts.map +0 -1
  110. package/dist/cjs/components/FilterContext/index.js +0 -85
  111. package/dist/cjs/components/SelectShownFilters/index.d.ts +0 -7
  112. package/dist/cjs/components/SelectShownFilters/index.d.ts.map +0 -1
  113. package/dist/cjs/components/SelectShownFilters/index.js +0 -111
  114. package/dist/cjs/components/SelectShownFilters/styles.css +0 -99
  115. package/dist/cjs/components/ShownFilters/index.d.ts +0 -3
  116. package/dist/cjs/components/ShownFilters/index.d.ts.map +0 -1
  117. package/dist/cjs/components/ShownFilters/index.js +0 -45
  118. package/dist/cjs/components/index.d.ts +0 -6
  119. package/dist/cjs/components/index.d.ts.map +0 -1
  120. package/dist/cjs/components/index.js +0 -21
  121. package/dist/cjs/constants/index.d.ts +0 -56
  122. package/dist/cjs/constants/index.d.ts.map +0 -1
  123. package/dist/cjs/constants/index.js +0 -58
  124. package/dist/cjs/index.css +0 -67
  125. package/dist/cjs/utils/index.d.ts +0 -25
  126. package/dist/cjs/utils/index.d.ts.map +0 -1
  127. package/dist/cjs/utils/index.js +0 -40
  128. package/dist/esm/components/AppliedFilters/AppliedFilterItem.d.ts +0 -12
  129. package/dist/esm/components/AppliedFilters/AppliedFilterItem.d.ts.map +0 -1
  130. package/dist/esm/components/AppliedFilters/AppliedFilterItem.js +0 -58
  131. package/dist/esm/components/AppliedFilters/common.d.ts +0 -6
  132. package/dist/esm/components/AppliedFilters/common.d.ts.map +0 -1
  133. package/dist/esm/components/AppliedFilters/common.js +0 -28
  134. package/dist/esm/components/AppliedFilters/index.d.ts +0 -4
  135. package/dist/esm/components/AppliedFilters/index.d.ts.map +0 -1
  136. package/dist/esm/components/AppliedFilters/index.js +0 -22
  137. package/dist/esm/components/AppliedFilters/styles.css +0 -65
  138. package/dist/esm/components/ConditionalFilters/index.d.ts +0 -3
  139. package/dist/esm/components/ConditionalFilters/index.d.ts.map +0 -1
  140. package/dist/esm/components/ConditionalFilters/index.js +0 -28
  141. package/dist/esm/components/FilterContext/index.d.ts +0 -45
  142. package/dist/esm/components/FilterContext/index.d.ts.map +0 -1
  143. package/dist/esm/components/FilterContext/index.js +0 -80
  144. package/dist/esm/components/SelectShownFilters/index.d.ts +0 -7
  145. package/dist/esm/components/SelectShownFilters/index.d.ts.map +0 -1
  146. package/dist/esm/components/SelectShownFilters/index.js +0 -107
  147. package/dist/esm/components/SelectShownFilters/styles.css +0 -99
  148. package/dist/esm/components/ShownFilters/index.d.ts +0 -3
  149. package/dist/esm/components/ShownFilters/index.d.ts.map +0 -1
  150. package/dist/esm/components/ShownFilters/index.js +0 -41
  151. package/dist/esm/components/index.d.ts +0 -6
  152. package/dist/esm/components/index.d.ts.map +0 -1
  153. package/dist/esm/components/index.js +0 -5
  154. package/dist/esm/constants/index.d.ts +0 -56
  155. package/dist/esm/constants/index.d.ts.map +0 -1
  156. package/dist/esm/constants/index.js +0 -55
  157. package/dist/esm/index.css +0 -67
  158. package/dist/esm/utils/index.d.ts +0 -25
  159. package/dist/esm/utils/index.d.ts.map +0 -1
  160. package/dist/esm/utils/index.js +0 -35
@@ -0,0 +1,5 @@
1
+ import type { FieldValues } from '@akinon/akiform';
2
+ import type { AkifilterField, AkifilterSchema } from '../types';
3
+ export declare const shouldPersistValue: <TFieldValues extends FieldValues = FieldValues>(field: AkifilterField<TFieldValues> | undefined, value: unknown) => boolean;
4
+ export declare const normaliseOutputValues: <TFieldValues extends FieldValues = FieldValues>(schema: AkifilterSchema<TFieldValues>, values?: Partial<TFieldValues> | FieldValues) => Partial<TFieldValues>;
5
+ //# sourceMappingURL=values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../../src/utils/values.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhE,eAAO,MAAM,kBAAkB,GAC7B,YAAY,SAAS,WAAW,GAAG,WAAW,EAE9C,OAAO,cAAc,CAAC,YAAY,CAAC,GAAG,SAAS,EAC/C,OAAO,OAAO,KACb,OAkBF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,YAAY,SAAS,WAAW,GAAG,WAAW,EAE9C,QAAQ,eAAe,CAAC,YAAY,CAAC,EACrC,SAAS,OAAO,CAAC,YAAY,CAAC,GAAG,WAAW,KAC3C,OAAO,CAAC,YAAY,CA8BtB,CAAC"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normaliseOutputValues = exports.shouldPersistValue = void 0;
4
+ const akidate_1 = require("@akinon/akidate");
5
+ const shouldPersistValue = (field, value) => {
6
+ if (value === undefined || value === null) {
7
+ return false;
8
+ }
9
+ if (typeof value === 'string' && value.trim() === '') {
10
+ return false;
11
+ }
12
+ if (Array.isArray(value) && value.length === 0) {
13
+ return false;
14
+ }
15
+ if ((field === null || field === void 0 ? void 0 : field.type) === 'checkbox' && value !== true) {
16
+ return false;
17
+ }
18
+ return true;
19
+ };
20
+ exports.shouldPersistValue = shouldPersistValue;
21
+ const normaliseOutputValues = (schema, values) => {
22
+ if (!values) {
23
+ return {};
24
+ }
25
+ const entries = Object.entries(values);
26
+ return entries.reduce((acc, [key, rawValue]) => {
27
+ const field = schema.find(schemaField => String(schemaField.key) === String(key));
28
+ if (!(0, exports.shouldPersistValue)(field, rawValue)) {
29
+ return acc;
30
+ }
31
+ let normalisedValue = rawValue;
32
+ if ((field === null || field === void 0 ? void 0 : field.type) === 'date') {
33
+ const normalised = akidate_1.akidate.toIsoDate(rawValue);
34
+ if (!normalised) {
35
+ return acc;
36
+ }
37
+ normalisedValue = akidate_1.akidate.formatIsoDate(normalised, 'YYYY-MM-DD');
38
+ }
39
+ acc[key] =
40
+ normalisedValue;
41
+ return acc;
42
+ }, {});
43
+ };
44
+ exports.normaliseOutputValues = normaliseOutputValues;
@@ -0,0 +1,53 @@
1
+ import './styles.css';
2
+ import { FieldValues, Path } from '@akinon/akiform';
3
+ import React from 'react';
4
+ import type { AkifilterSchema } from './types';
5
+ type AkifilterFieldValues = FieldValues;
6
+ export type AkifilterProps<TFieldValues extends AkifilterFieldValues = AkifilterFieldValues> = {
7
+ /**
8
+ * Declarative description of the filter fields.
9
+ */
10
+ filterSchema?: AkifilterSchema<TFieldValues>;
11
+ /**
12
+ * Optional namespace for local storage persistence.
13
+ */
14
+ storageNamespace?: string;
15
+ /**
16
+ * Default values supplied by the host application.
17
+ */
18
+ defaultValues?: Partial<TFieldValues>;
19
+ /**
20
+ * Notified on every value change with the normalised payload.
21
+ */
22
+ onValuesChange?: (values: Partial<TFieldValues>) => void;
23
+ /**
24
+ * Notified whenever visible field keys change.
25
+ */
26
+ onVisibleFieldsChange?: (keys: Array<Path<TFieldValues>>) => void;
27
+ /**
28
+ * Triggered when user opts to import filters via CSV.
29
+ */
30
+ onImportCsv?: () => void;
31
+ /**
32
+ * Triggered when user opts to import filters via XLS/XLSX.
33
+ */
34
+ onImportXls?: () => void;
35
+ /**
36
+ * Triggered when user requests clearing all filters.
37
+ */
38
+ onClearAll?: () => void;
39
+ /**
40
+ * Shows the CSV import button in the toolbar. Hidden by default.
41
+ */
42
+ enableImportCsv?: boolean;
43
+ /**
44
+ * Shows the XLS/XLSX import button in the toolbar. Hidden by default.
45
+ */
46
+ enableImportXls?: boolean;
47
+ };
48
+ export declare const Akifilter: {
49
+ <TFieldValues extends AkifilterFieldValues = FieldValues>(props: AkifilterProps<TFieldValues>): React.JSX.Element;
50
+ displayName: string;
51
+ };
52
+ export {};
53
+ //# sourceMappingURL=akifilter.d.ts.map
@@ -0,0 +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;AAExC,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;AAohBF,eAAO,MAAM,SAAS;KACpB,YAAY,SAAS,oBAAoB,uBAElC,cAAc,CAAC,YAAY,CAAC;;CAmBpC,CAAC"}
@@ -0,0 +1,295 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import './styles.css';
13
+ import { akidate } from '@akinon/akidate';
14
+ import { Akiform, FormItem, useForm, useWatch } from '@akinon/akiform';
15
+ import { Button } from '@akinon/ui-button';
16
+ import { Card } from '@akinon/ui-card';
17
+ import { Checkbox } from '@akinon/ui-checkbox';
18
+ import { DatePicker } from '@akinon/ui-date-picker';
19
+ import { Input, InputTextArea } from '@akinon/ui-input';
20
+ import { InputNumber } from '@akinon/ui-input-number';
21
+ import { Select } from '@akinon/ui-select';
22
+ import { Text, Title } from '@akinon/ui-typography';
23
+ import { ConfigProvider } from 'antd';
24
+ import React from 'react';
25
+ import { ErrorBoundary } from 'react-error-boundary';
26
+ import { buildStorageKey, clearStoredValues, readStoredValues, readVisibleKeys, writeStoredValues, writeVisibleKeys } from './common/storage';
27
+ import { themeOverrides } from './common/theme-overrides';
28
+ import { AppliedFilters } from './components/applied-filters';
29
+ import { FilterToolbar } from './components/filter-toolbar';
30
+ import { VisibilityModal } from './components/visibility-modal';
31
+ import { DEFAULT_MODAL_PAGE_SIZE, FILTER_DEBOUNCE_DELAY } from './constants';
32
+ import { useDebouncedValue } from './hooks/use-debounced-value';
33
+ import { i18n } from './i18n';
34
+ import { deriveDefaultVisibleKeys, ensureSchemaOrder, extractDefaultValues, getFieldAriaLabel, normaliseValuesBySchema } from './utils/schema';
35
+ import { normaliseOutputValues } from './utils/values';
36
+ const AkifilterContent = ({ filterSchema, storageNamespace, defaultValues, onValuesChange, onVisibleFieldsChange, onImportCsv, onImportXls, onClearAll, enableImportCsv, enableImportXls }) => {
37
+ const storageKey = React.useMemo(() => buildStorageKey(filterSchema, storageNamespace), [filterSchema, storageNamespace]);
38
+ const schemaDefaults = React.useMemo(() => normaliseValuesBySchema(filterSchema, extractDefaultValues(filterSchema)), [filterSchema]);
39
+ const externalDefaults = React.useMemo(() => normaliseValuesBySchema(filterSchema, defaultValues), [filterSchema, defaultValues]);
40
+ const baseDefaultValues = React.useMemo(() => (Object.assign(Object.assign({}, schemaDefaults), externalDefaults)), [schemaDefaults, externalDefaults]);
41
+ const persistedDefaults = React.useMemo(() => {
42
+ var _a;
43
+ return normaliseValuesBySchema(filterSchema, (_a = readStoredValues(filterSchema, storageKey)) !== null && _a !== void 0 ? _a : undefined);
44
+ }, [filterSchema, storageKey]);
45
+ const mergedDefaultValues = React.useMemo(() => (Object.assign(Object.assign({}, baseDefaultValues), persistedDefaults)), [baseDefaultValues, persistedDefaults]);
46
+ const formMethods = useForm({
47
+ defaultValues: mergedDefaultValues
48
+ });
49
+ const formValues = useWatch({ control: formMethods.control });
50
+ const [isModalOpen, setIsModalOpen] = React.useState(false);
51
+ const [searchTerm, setSearchTerm] = React.useState('');
52
+ const [modalPage, setModalPage] = React.useState(1);
53
+ const [modalPageSize, setModalPageSize] = React.useState(DEFAULT_MODAL_PAGE_SIZE);
54
+ const appliedFilters = React.useMemo(() => {
55
+ if (!formValues) {
56
+ return [];
57
+ }
58
+ return filterSchema.reduce((acc, field) => {
59
+ const key = String(field.key);
60
+ const currentValue = formValues[key];
61
+ if (currentValue === undefined || currentValue === null) {
62
+ return acc;
63
+ }
64
+ if (typeof currentValue === 'string' && currentValue.trim() === '') {
65
+ return acc;
66
+ }
67
+ if (Array.isArray(currentValue) && currentValue.length === 0) {
68
+ return acc;
69
+ }
70
+ if (field.type === 'checkbox' && currentValue !== true) {
71
+ return acc;
72
+ }
73
+ const label = field.placeholder || field.label || key;
74
+ const resolveSelectLabel = () => {
75
+ var _a;
76
+ if (!('options' in field) || !field.options) {
77
+ return String(currentValue);
78
+ }
79
+ const match = field.options.find(option => option.value === currentValue);
80
+ return String((_a = match === null || match === void 0 ? void 0 : match.label) !== null && _a !== void 0 ? _a : currentValue);
81
+ };
82
+ const resolveValue = () => {
83
+ if (field.type === 'select') {
84
+ return resolveSelectLabel();
85
+ }
86
+ if (field.type === 'date') {
87
+ const iso = akidate.toIsoDate(currentValue);
88
+ if (iso) {
89
+ return akidate.formatIsoDate(iso, 'YYYY-MM-DD');
90
+ }
91
+ }
92
+ if (Array.isArray(currentValue)) {
93
+ return currentValue.map((value) => String(value)).join(', ');
94
+ }
95
+ if (typeof currentValue === 'boolean') {
96
+ return currentValue ? 'true' : 'false';
97
+ }
98
+ if (typeof currentValue === 'string' ||
99
+ typeof currentValue === 'number') {
100
+ return String(currentValue);
101
+ }
102
+ const iso = akidate.toIsoDate(currentValue);
103
+ if (iso) {
104
+ return akidate.formatIsoDate(iso, 'YYYY-MM-DD');
105
+ }
106
+ return String(currentValue);
107
+ };
108
+ acc.push({ key, label, value: resolveValue() });
109
+ return acc;
110
+ }, []);
111
+ }, [filterSchema, formValues]);
112
+ const resolveInitialVisibleKeys = React.useCallback(() => {
113
+ const storedKeys = readVisibleKeys(filterSchema, storageKey);
114
+ if (storedKeys && storedKeys.length > 0) {
115
+ return ensureSchemaOrder(filterSchema, storedKeys);
116
+ }
117
+ return deriveDefaultVisibleKeys(filterSchema);
118
+ }, [filterSchema, storageKey]);
119
+ const [visibleKeys, setVisibleKeys] = React.useState(resolveInitialVisibleKeys);
120
+ React.useEffect(() => {
121
+ setVisibleKeys(previous => {
122
+ const ordered = ensureSchemaOrder(filterSchema, previous);
123
+ if (ordered.length) {
124
+ return ordered;
125
+ }
126
+ return resolveInitialVisibleKeys();
127
+ });
128
+ }, [filterSchema, resolveInitialVisibleKeys]);
129
+ React.useEffect(() => {
130
+ writeVisibleKeys(storageKey, visibleKeys);
131
+ onVisibleFieldsChange === null || onVisibleFieldsChange === void 0 ? void 0 : onVisibleFieldsChange(visibleKeys);
132
+ }, [visibleKeys, onVisibleFieldsChange, storageKey]);
133
+ React.useEffect(() => {
134
+ formMethods.reset(mergedDefaultValues);
135
+ }, [formMethods, mergedDefaultValues]);
136
+ const normalisedValues = React.useMemo(() => normaliseOutputValues(filterSchema, formValues), [filterSchema, formValues]);
137
+ const initialOutputValues = React.useMemo(() => normaliseOutputValues(filterSchema, mergedDefaultValues), [filterSchema, mergedDefaultValues]);
138
+ const hasInitialValues = React.useMemo(() => Object.keys(initialOutputValues).length > 0, [initialOutputValues]);
139
+ const serialisedValues = React.useMemo(() => JSON.stringify(normalisedValues), [normalisedValues]);
140
+ const debouncedSerialisedValues = useDebouncedValue(serialisedValues, FILTER_DEBOUNCE_DELAY);
141
+ const lastPersistedValuesRef = React.useRef(null);
142
+ const hasEmittedValuesRef = React.useRef(false);
143
+ React.useEffect(() => {
144
+ if (debouncedSerialisedValues == null) {
145
+ return;
146
+ }
147
+ if (hasEmittedValuesRef.current &&
148
+ lastPersistedValuesRef.current === debouncedSerialisedValues) {
149
+ return;
150
+ }
151
+ const parsedValues = JSON.parse(debouncedSerialisedValues);
152
+ const isEmpty = Object.keys(parsedValues).length === 0;
153
+ if (!hasEmittedValuesRef.current && isEmpty && !hasInitialValues) {
154
+ hasEmittedValuesRef.current = true;
155
+ lastPersistedValuesRef.current = debouncedSerialisedValues;
156
+ clearStoredValues(storageKey);
157
+ return;
158
+ }
159
+ hasEmittedValuesRef.current = true;
160
+ lastPersistedValuesRef.current = debouncedSerialisedValues;
161
+ onValuesChange === null || onValuesChange === void 0 ? void 0 : onValuesChange(parsedValues);
162
+ if (isEmpty) {
163
+ clearStoredValues(storageKey);
164
+ }
165
+ else {
166
+ writeStoredValues(storageKey, parsedValues);
167
+ }
168
+ }, [debouncedSerialisedValues, hasInitialValues, onValuesChange, storageKey]);
169
+ React.useEffect(() => {
170
+ lastPersistedValuesRef.current = null;
171
+ }, [storageKey]);
172
+ const handleClearAll = React.useCallback(() => {
173
+ formMethods.reset(baseDefaultValues);
174
+ onClearAll === null || onClearAll === void 0 ? void 0 : onClearAll();
175
+ clearStoredValues(storageKey);
176
+ }, [baseDefaultValues, formMethods, onClearAll, storageKey]);
177
+ const handleOpenModal = React.useCallback(() => {
178
+ setIsModalOpen(true);
179
+ setSearchTerm('');
180
+ setModalPage(1);
181
+ }, []);
182
+ const handleCloseModal = React.useCallback(() => {
183
+ setIsModalOpen(false);
184
+ }, []);
185
+ const handleToggleVisibility = React.useCallback((key) => {
186
+ setVisibleKeys(prev => {
187
+ const exists = prev.includes(key);
188
+ if (exists && prev.length === 1) {
189
+ return prev;
190
+ }
191
+ const nextKeys = exists
192
+ ? prev.filter(item => item !== key)
193
+ : [...prev, key];
194
+ return ensureSchemaOrder(filterSchema, nextKeys);
195
+ });
196
+ }, [filterSchema]);
197
+ const handleRemoveFilter = React.useCallback((key) => {
198
+ const schemaField = filterSchema.find(field => String(field.key) === key);
199
+ if (!schemaField) {
200
+ return;
201
+ }
202
+ const defaultValue = baseDefaultValues[String(schemaField.key)];
203
+ formMethods.resetField(schemaField.key, {
204
+ defaultValue
205
+ });
206
+ }, [baseDefaultValues, filterSchema, formMethods]);
207
+ const filteredFields = React.useMemo(() => {
208
+ const normalisedTerm = searchTerm.trim().toLowerCase();
209
+ if (!normalisedTerm) {
210
+ return filterSchema;
211
+ }
212
+ return filterSchema.filter(field => {
213
+ const searchable = [field.label, field.placeholder, String(field.key)]
214
+ .filter(Boolean)
215
+ .map(value => String(value).toLowerCase());
216
+ return searchable.some(text => text.includes(normalisedTerm));
217
+ });
218
+ }, [filterSchema, searchTerm]);
219
+ const paginatedFields = React.useMemo(() => {
220
+ const start = (modalPage - 1) * modalPageSize;
221
+ return filteredFields.slice(start, start + modalPageSize);
222
+ }, [filteredFields, modalPage, modalPageSize]);
223
+ const visibleFields = React.useMemo(() => filterSchema.filter(field => visibleKeys.includes(String(field.key))), [filterSchema, visibleKeys]);
224
+ const renderFieldComponent = (field) => {
225
+ const ariaLabel = getFieldAriaLabel(field);
226
+ switch (field.type) {
227
+ case 'text':
228
+ return (React.createElement(Input, { placeholder: field.placeholder, size: "large", allowClear: true, "aria-label": ariaLabel }));
229
+ case 'number':
230
+ return (React.createElement(InputNumber, { placeholder: field.placeholder, size: "large", className: "akinon-filter__field--number", "aria-label": ariaLabel }));
231
+ case 'select':
232
+ return (React.createElement(Select, { placeholder: field.placeholder, size: "large", options: field.options, showSearch: true, optionFilterProp: "label", "aria-label": ariaLabel }));
233
+ case 'checkbox':
234
+ return React.createElement(Checkbox, null, field.label);
235
+ case 'date':
236
+ return (React.createElement(DatePicker, { placeholder: field.placeholder, size: "large", showTime: field.showTime, suffixIcon: "calendar", suffixIconSize: "16px", "aria-label": ariaLabel }));
237
+ case 'textarea':
238
+ return (React.createElement(InputTextArea, { placeholder: field.placeholder, autoSize: { minRows: 3, maxRows: 6 }, "aria-label": ariaLabel }));
239
+ case 'custom':
240
+ if (typeof field.render === 'function') {
241
+ return field.render({
242
+ field,
243
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
244
+ control: formMethods.control,
245
+ formValues: formMethods.getValues(),
246
+ formState: formMethods.formState
247
+ });
248
+ }
249
+ return (React.createElement(Text, { type: "secondary", className: "akinon-filter__unsupported" }, i18n.t('form.unsupportedField', { field: String(field.type) })));
250
+ default:
251
+ return (React.createElement(Text, { type: "secondary", className: "akinon-filter__unsupported" }, i18n.t('form.unsupportedField', { field: String(field.type) })));
252
+ }
253
+ };
254
+ return (React.createElement(Card, { size: "small", className: "akinon-filter shadow", "data-testid": "akifilter-root" },
255
+ React.createElement(ConfigProvider, { theme: themeOverrides },
256
+ React.createElement(FilterToolbar, { onOpenModal: handleOpenModal, enableImportCsv: enableImportCsv, enableImportXls: enableImportXls, onImportCsv: onImportCsv, onImportXls: onImportXls }),
257
+ React.createElement(AppliedFilters, { filters: appliedFilters, onRemove: handleRemoveFilter, onClearAll: handleClearAll }),
258
+ React.createElement("div", { className: "akinon-filter__body" },
259
+ React.createElement(Akiform, { layout: "vertical", className: "akinon-filter__form" },
260
+ 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)))),
262
+ visibleFields.length === 0 ? (React.createElement("div", { className: "akinon-filter__empty" }, i18n.t('form.noVisibleFields'))) : null))),
263
+ React.createElement(VisibilityModal, { open: isModalOpen, onClose: handleCloseModal, searchTerm: searchTerm, paginatedFields: paginatedFields, filteredCount: filteredFields.length, visibleKeys: visibleKeys, onSearchTermChange: value => {
264
+ setSearchTerm(value);
265
+ setModalPage(1);
266
+ }, onToggleVisibility: handleToggleVisibility, onPaginationChange: (page, pageSize) => {
267
+ setModalPage(page);
268
+ if (pageSize !== modalPageSize) {
269
+ setModalPageSize(pageSize);
270
+ }
271
+ }, page: modalPage, pageSize: modalPageSize }))));
272
+ };
273
+ const AkifilterEmptyState = () => {
274
+ const { t } = i18n;
275
+ return (React.createElement(Card, { size: "small", className: "akinon-filter shadow", "data-testid": "akifilter-empty" },
276
+ React.createElement(ConfigProvider, { theme: themeOverrides },
277
+ React.createElement("div", { className: "akinon-filter__empty-state" },
278
+ React.createElement(Text, null, t('emptyState.message'))))));
279
+ };
280
+ const renderErrorFallback = ({ resetErrorBoundary }) => {
281
+ const { t } = i18n;
282
+ return (React.createElement(Card, { size: "small", className: "akinon-filter shadow", "data-testid": "akifilter-error" },
283
+ React.createElement(ConfigProvider, { theme: themeOverrides },
284
+ React.createElement("div", { className: "akinon-filter__error-state" },
285
+ React.createElement(Title, { level: 5, className: "akinon-filter__error-title" }, t('errors.title')),
286
+ React.createElement(Text, { type: "secondary", className: "akinon-filter__error-description" }, t('errors.description')),
287
+ React.createElement(Button, { type: "primary", onClick: resetErrorBoundary, size: "small" }, t('errors.retry'))))));
288
+ };
289
+ export const Akifilter = (props) => {
290
+ const { filterSchema } = props, restProps = __rest(props, ["filterSchema"]);
291
+ const resolvedSchema = (filterSchema !== null && filterSchema !== void 0 ? filterSchema : []);
292
+ const hasSchema = resolvedSchema.length > 0;
293
+ return (React.createElement(ErrorBoundary, { fallbackRender: renderErrorFallback }, hasSchema ? (React.createElement(AkifilterContent, Object.assign({}, restProps, { filterSchema: resolvedSchema }))) : (React.createElement(AkifilterEmptyState, null))));
294
+ };
295
+ Akifilter.displayName = 'Akifilter';
@@ -0,0 +1,10 @@
1
+ import type { FieldValues } from '@akinon/akiform';
2
+ import type { AkifilterField } from '../types';
3
+ export declare const buildStorageKey: <TFieldValues extends FieldValues>(schema: AkifilterField<TFieldValues>[], namespace?: string) => string;
4
+ export declare const readVisibleKeys: <TFieldValues extends FieldValues>(schema: AkifilterField<TFieldValues>[], storageKey: string) => string[] | null;
5
+ export declare const writeVisibleKeys: (storageKey: string, keys: string[]) => void;
6
+ export declare const clearVisibleKeys: (storageKey: string) => void;
7
+ export declare const readStoredValues: <TFieldValues extends FieldValues>(schema: AkifilterField<TFieldValues>[], storageKey: string) => Partial<TFieldValues> | null;
8
+ export declare const writeStoredValues: <TFieldValues extends FieldValues>(storageKey: string, values: Partial<TFieldValues>) => void;
9
+ export declare const clearStoredValues: (storageKey: string) => void;
10
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/common/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAqB/C,eAAO,MAAM,eAAe,GAAI,YAAY,SAAS,WAAW,EAC9D,QAAQ,cAAc,CAAC,YAAY,CAAC,EAAE,EACtC,YAAY,MAAM,KACjB,MAKF,CAAC;AAIF,eAAO,MAAM,eAAe,GAAI,YAAY,SAAS,WAAW,EAC9D,QAAQ,cAAc,CAAC,YAAY,CAAC,EAAE,EACtC,YAAY,MAAM,KACjB,MAAM,EAAE,GAAG,IAuBb,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,YAAY,MAAM,EAAE,MAAM,MAAM,EAAE,KAAG,IAQrE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,YAAY,MAAM,KAAG,IAQrD,CAAC;AAKF,eAAO,MAAM,gBAAgB,GAAI,YAAY,SAAS,WAAW,EAC/D,QAAQ,cAAc,CAAC,YAAY,CAAC,EAAE,EACtC,YAAY,MAAM,KACjB,OAAO,CAAC,YAAY,CAAC,GAAG,IA+B1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,YAAY,SAAS,WAAW,EAChE,YAAY,MAAM,EAClB,QAAQ,OAAO,CAAC,YAAY,CAAC,KAC5B,IAeF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,KAAG,IAQtD,CAAC"}
@@ -0,0 +1,114 @@
1
+ const STORAGE_PREFIX = 'akifilter:v1';
2
+ const VALUES_SUFFIX = ':values';
3
+ const hashString = (value) => {
4
+ let hash = 0;
5
+ for (let i = 0; i < value.length; i += 1) {
6
+ const chr = value.charCodeAt(i);
7
+ hash = (hash << 5) - hash + chr;
8
+ hash |= 0; // Convert to 32bit integer
9
+ }
10
+ return Math.abs(hash).toString(36);
11
+ };
12
+ const buildSchemaSignature = (schema) => {
13
+ return schema.map(field => `${String(field.key)}:${field.type}`).join('|');
14
+ };
15
+ export const buildStorageKey = (schema, namespace) => {
16
+ const signature = buildSchemaSignature(schema);
17
+ const hashedSignature = hashString(signature);
18
+ const base = namespace ? namespace.trim() : 'default';
19
+ return `${STORAGE_PREFIX}:${base}:${hashedSignature}`;
20
+ };
21
+ const isBrowser = typeof window !== 'undefined';
22
+ export const readVisibleKeys = (schema, storageKey) => {
23
+ if (!isBrowser)
24
+ return null;
25
+ try {
26
+ const rawValue = window.localStorage.getItem(storageKey);
27
+ if (!rawValue) {
28
+ return null;
29
+ }
30
+ const parsed = JSON.parse(rawValue);
31
+ if (!Array.isArray(parsed)) {
32
+ return null;
33
+ }
34
+ const schemaKeys = new Set(schema.map(field => String(field.key)));
35
+ return parsed.filter(key => schemaKeys.has(String(key)));
36
+ }
37
+ catch (error) {
38
+ console.warn('Akifilter: unable to read visibility state from storage', error);
39
+ return null;
40
+ }
41
+ };
42
+ export const writeVisibleKeys = (storageKey, keys) => {
43
+ if (!isBrowser)
44
+ return;
45
+ try {
46
+ window.localStorage.setItem(storageKey, JSON.stringify(keys));
47
+ }
48
+ catch (error) {
49
+ console.warn('Akifilter: unable to persist visibility state', error);
50
+ }
51
+ };
52
+ export const clearVisibleKeys = (storageKey) => {
53
+ if (!isBrowser)
54
+ return;
55
+ try {
56
+ window.localStorage.removeItem(storageKey);
57
+ }
58
+ catch (error) {
59
+ console.warn('Akifilter: unable to clear visibility state', error);
60
+ }
61
+ };
62
+ const buildValuesStorageKey = (storageKey) => `${storageKey}${VALUES_SUFFIX}`;
63
+ export const readStoredValues = (schema, storageKey) => {
64
+ if (!isBrowser)
65
+ return null;
66
+ try {
67
+ const rawValue = window.localStorage.getItem(buildValuesStorageKey(storageKey));
68
+ if (!rawValue) {
69
+ return null;
70
+ }
71
+ const parsed = JSON.parse(rawValue);
72
+ if (!parsed || typeof parsed !== 'object') {
73
+ return null;
74
+ }
75
+ const schemaKeys = new Set(schema.map(field => String(field.key)));
76
+ return Object.entries(parsed).reduce((acc, [key, value]) => {
77
+ if (schemaKeys.has(String(key))) {
78
+ acc[key] =
79
+ value;
80
+ }
81
+ return acc;
82
+ }, {});
83
+ }
84
+ catch (error) {
85
+ console.warn('Akifilter: unable to read values from storage', error);
86
+ return null;
87
+ }
88
+ };
89
+ export const writeStoredValues = (storageKey, values) => {
90
+ if (!isBrowser)
91
+ return;
92
+ const valuesKey = buildValuesStorageKey(storageKey);
93
+ const entries = Object.entries(values);
94
+ try {
95
+ if (entries.length === 0) {
96
+ window.localStorage.removeItem(valuesKey);
97
+ return;
98
+ }
99
+ window.localStorage.setItem(valuesKey, JSON.stringify(values));
100
+ }
101
+ catch (error) {
102
+ console.warn('Akifilter: unable to persist values', error);
103
+ }
104
+ };
105
+ export const clearStoredValues = (storageKey) => {
106
+ if (!isBrowser)
107
+ return;
108
+ try {
109
+ window.localStorage.removeItem(buildValuesStorageKey(storageKey));
110
+ }
111
+ catch (error) {
112
+ console.warn('Akifilter: unable to clear stored values', error);
113
+ }
114
+ };
@@ -0,0 +1,3 @@
1
+ import { ThemeConfig } from 'antd';
2
+ export declare const themeOverrides: ThemeConfig;
3
+ //# sourceMappingURL=theme-overrides.d.ts.map
@@ -0,0 +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,WAsB5B,CAAC"}
@@ -0,0 +1,6 @@
1
+ var _a, _b;
2
+ import { theme } from '@akinon/ui-theme';
3
+ export const themeOverrides = Object.assign(Object.assign({}, theme), { algorithm: theme.algorithm, token: {
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'] }) }) });
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ type AppliedFilter = {
3
+ key: string;
4
+ label: string;
5
+ value: string;
6
+ };
7
+ type AppliedFiltersProps = {
8
+ filters: AppliedFilter[];
9
+ onRemove: (key: string) => void;
10
+ onClearAll: () => void;
11
+ };
12
+ export declare const AppliedFilters: ({ filters, onRemove, onClearAll }: AppliedFiltersProps) => React.JSX.Element;
13
+ export type { AppliedFilter };
14
+ //# sourceMappingURL=applied-filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applied-filters.d.ts","sourceRoot":"","sources":["../../../src/components/applied-filters.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,KAAK,aAAa,GAAG;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,mCAI5B,mBAAmB,sBAoDrB,CAAC;AAEF,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Icon } from '@akinon/icons';
2
+ import { Button } from '@akinon/ui-button';
3
+ import { Space } from '@akinon/ui-space';
4
+ import { Text } from '@akinon/ui-typography';
5
+ import React from 'react';
6
+ import { i18n } from '../i18n';
7
+ export const AppliedFilters = ({ filters, onRemove, onClearAll }) => {
8
+ const hasFilters = filters.length > 0;
9
+ return (React.createElement("div", { className: "akinon-filter__applied", "data-testid": "akifilter-applied" },
10
+ React.createElement(Space, { className: "akinon-filter__applied-summary", size: 8 },
11
+ React.createElement(Text, { className: "akinon-filter__applied-label" }, i18n.t('applied.label')),
12
+ hasFilters ? (React.createElement(Space, { className: "akinon-filter__applied-items", size: 8, wrap: true }, filters.map(item => (React.createElement("div", { key: `${item.key}-${item.value}`, className: "akinon-filter__chip" },
13
+ React.createElement("span", { className: "akinon-filter__chip-label" },
14
+ item.label,
15
+ ":"),
16
+ React.createElement("span", { className: "akinon-filter__chip-value" }, item.value),
17
+ React.createElement("button", { type: "button", "aria-label": i18n.t('applied.clearSingle', {
18
+ field: item.label
19
+ }), className: "akinon-filter__chip-button", onClick: () => onRemove(item.key) },
20
+ React.createElement(Icon, { icon: "no", size: 16 }))))))) : (React.createElement(Text, { className: "akinon-filter__applied-empty" }, i18n.t('applied.empty')))),
21
+ React.createElement(Button, { className: "akinon-filter__clear", icon: "bin", iconSize: 16, onClick: onClearAll, size: "small", type: "icon", title: i18n.t('applied.clearAll'), "aria-label": i18n.t('applied.clearAll'), disabled: !hasFilters })));
22
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ type FilterToolbarProps = {
3
+ onOpenModal: () => void;
4
+ enableImportCsv?: boolean;
5
+ enableImportXls?: boolean;
6
+ onImportCsv?: () => void;
7
+ onImportXls?: () => void;
8
+ };
9
+ export declare const FilterToolbar: ({ onOpenModal, enableImportCsv, enableImportXls, onImportCsv, onImportXls }: FilterToolbarProps) => React.JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=filter-toolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-toolbar.d.ts","sourceRoot":"","sources":["../../../src/components/filter-toolbar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,KAAK,kBAAkB,GAAG;IACxB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,6EAM3B,kBAAkB,sBAwCpB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Button } from '@akinon/ui-button';
2
+ import { Space } from '@akinon/ui-space';
3
+ import { Title } from '@akinon/ui-typography';
4
+ import React from 'react';
5
+ import { i18n } from '../i18n';
6
+ export const FilterToolbar = ({ onOpenModal, enableImportCsv, enableImportXls, onImportCsv, onImportXls }) => {
7
+ return (React.createElement("div", { className: "akinon-filter__top" },
8
+ React.createElement(Title, { className: "akinon-filter__title", level: 4 }, i18n.t('header.title')),
9
+ React.createElement(Space, { className: "akinon-filter__toolbar", size: 6 },
10
+ enableImportCsv && onImportCsv ? (React.createElement(Button, { className: "akinon-filter__toolbar-item", onClick: onImportCsv, type: "primary" }, i18n.t('header.actions.importCsv'))) : null,
11
+ enableImportXls && onImportXls ? (React.createElement(Button, { className: "akinon-filter__toolbar-item", onClick: onImportXls, type: "primary" }, i18n.t('header.actions.importXls'))) : null,
12
+ React.createElement(Button, { className: "akinon-filter__toolbar-item", icon: "filter", iconSize: 16, onClick: onOpenModal, type: "primary", title: i18n.t('header.actions.selectFilters'), "aria-label": i18n.t('header.actions.selectFilters') }))));
13
+ };
@@ -0,0 +1,19 @@
1
+ import type { FieldValues } from '@akinon/akiform';
2
+ import React from 'react';
3
+ import type { AkifilterField } from '../types';
4
+ type VisibilityModalProps<TFieldValues extends FieldValues = FieldValues> = {
5
+ open: boolean;
6
+ searchTerm: string;
7
+ paginatedFields: AkifilterField<TFieldValues>[];
8
+ filteredCount: number;
9
+ visibleKeys: string[];
10
+ onClose: () => void;
11
+ onSearchTermChange: (value: string) => void;
12
+ onToggleVisibility: (key: string) => void;
13
+ onPaginationChange: (page: number, pageSize: number) => void;
14
+ page: number;
15
+ pageSize: number;
16
+ };
17
+ export declare const VisibilityModal: <TFieldValues extends FieldValues = FieldValues>({ open, searchTerm, paginatedFields, filteredCount, visibleKeys, onClose, onSearchTermChange, onToggleVisibility, onPaginationChange, page, pageSize }: VisibilityModalProps<TFieldValues>) => React.JSX.Element;
18
+ export {};
19
+ //# sourceMappingURL=visibility-modal.d.ts.map