@cosmicdrift/kumiko-renderer 0.290.0 → 0.292.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/__tests__/merge-search-params-into-initial.test.ts +52 -1
- package/src/__tests__/use-list-url-state.test.tsx +49 -0
- package/src/app/__tests__/list-daterange-facet.test.ts +165 -0
- package/src/app/__tests__/list-filter-facets.test.tsx +91 -1
- package/src/app/__tests__/projection-detail-reference-field.test.tsx +18 -2
- package/src/app/__tests__/projection-list-reference-column.test.tsx +67 -14
- package/src/app/__tests__/return-to.test.ts +86 -3
- package/src/app/kumiko-screen.tsx +150 -62
- package/src/app/list-facets.ts +155 -29
- package/src/app/projection-detail-shim.ts +1 -0
- package/src/app/return-to.tsx +91 -5
- package/src/app/screen-access.ts +34 -0
- package/src/app/secret-mint-body.tsx +26 -6
- package/src/app/secrets-edit-body.tsx +1 -0
- package/src/changes.json +12 -0
- package/src/components/embedded-list-field.tsx +3 -3
- package/src/components/render-field.tsx +25 -7
- package/src/components/render-list.tsx +9 -0
- package/src/hooks/use-list-url-state.ts +20 -1
- package/src/i18n-defaults.ts +1 -0
- package/src/i18n.tsx +11 -0
- package/src/index.ts +12 -1
- package/src/primitives.tsx +16 -0
|
@@ -48,6 +48,14 @@ export type ListUrlStateApi = ListUrlState & {
|
|
|
48
48
|
readonly setFilter: (field: string, values: readonly string[]) => void;
|
|
49
49
|
/** Löscht alle aktiven Faceted-Filter (Reset-Button). */
|
|
50
50
|
readonly clearFilters: () => void;
|
|
51
|
+
/** Sets both bounds of a dateRange facet in ONE params update — two
|
|
52
|
+
* setFilter calls would overwrite each other, since the second still sees
|
|
53
|
+
* the old searchParams. An empty string clears that bound. Resets the page
|
|
54
|
+
* like setFilter. */
|
|
55
|
+
readonly setDateRange: (
|
|
56
|
+
field: string,
|
|
57
|
+
next: { readonly from: string; readonly to: string },
|
|
58
|
+
) => void;
|
|
51
59
|
};
|
|
52
60
|
|
|
53
61
|
// `.` als Trenner: lesbar (`?orders.sort=name`), kollidiert nicht mit
|
|
@@ -142,11 +150,22 @@ export function useListUrlState(screenId: string): ListUrlStateApi {
|
|
|
142
150
|
[nav, screenId],
|
|
143
151
|
);
|
|
144
152
|
|
|
153
|
+
const setDateRange = useCallback(
|
|
154
|
+
(field: string, next: { readonly from: string; readonly to: string }) => {
|
|
155
|
+
nav.setSearchParams({
|
|
156
|
+
[key(screenId, `f.${field}.from`)]: next.from === "" ? null : next.from,
|
|
157
|
+
[key(screenId, `f.${field}.to`)]: next.to === "" ? null : next.to,
|
|
158
|
+
[key(screenId, "page")]: null,
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
[nav, screenId],
|
|
162
|
+
);
|
|
163
|
+
|
|
145
164
|
const clearFilters = useCallback(() => {
|
|
146
165
|
const updates: Record<string, string | null> = { [key(screenId, "page")]: null };
|
|
147
166
|
for (const field of Object.keys(filters)) updates[key(screenId, `f.${field}`)] = null;
|
|
148
167
|
nav.setSearchParams(updates);
|
|
149
168
|
}, [nav, screenId, filters]);
|
|
150
169
|
|
|
151
|
-
return { sort, q, page, filters, setSort, setQ, setPage, setFilter, clearFilters };
|
|
170
|
+
return { sort, q, page, filters, setSort, setQ, setPage, setFilter, clearFilters, setDateRange };
|
|
152
171
|
}
|
package/src/i18n-defaults.ts
CHANGED
|
@@ -67,6 +67,7 @@ export const kumikoDefaultTranslations: TranslationsByLocale = {
|
|
|
67
67
|
"kumiko.list.related-list-truncated":
|
|
68
68
|
"Showing the first {count} entries. More are available but not loaded — this list does not paginate.",
|
|
69
69
|
"kumiko.reference.system-tenant": "System",
|
|
70
|
+
"kumiko.reference.system-user": "System",
|
|
70
71
|
|
|
71
72
|
"kumiko.pager.status": "{from}–{to} of {total}",
|
|
72
73
|
"kumiko.pager.previousPage": "Previous page",
|
package/src/i18n.tsx
CHANGED
|
@@ -205,6 +205,17 @@ export function useOptionalLocale(): string | undefined {
|
|
|
205
205
|
return ctx === undefined ? undefined : ctx.resolver.locale();
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/** Non-throwing time-zone read — "UTC" outside LocaleProvider, matching
|
|
209
|
+
* createStaticLocaleResolver's own default. */
|
|
210
|
+
export function useOptionalTimeZone(): string {
|
|
211
|
+
const ctx = useContext(LocaleContext);
|
|
212
|
+
return useSyncExternalStore(
|
|
213
|
+
(onStoreChange) => (ctx ? ctx.resolver.subscribe(onStoreChange) : () => {}),
|
|
214
|
+
() => (ctx ? ctx.resolver.timeZone() : "UTC"),
|
|
215
|
+
() => (ctx ? ctx.resolver.timeZone() : "UTC"),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
208
219
|
/** Non-throwing translate — undefined outside LocaleProvider. */
|
|
209
220
|
export function useOptionalTranslation():
|
|
210
221
|
| ((key: string, params?: Readonly<Record<string, unknown>>) => string)
|
package/src/index.ts
CHANGED
|
@@ -64,6 +64,13 @@ export type {
|
|
|
64
64
|
export { isAppSchema, toAppSchema } from "./app/feature-schema";
|
|
65
65
|
export type { KumikoScreenProps } from "./app/kumiko-screen";
|
|
66
66
|
export { KumikoScreen, qualifyNavId, qualifyScreenId } from "./app/kumiko-screen";
|
|
67
|
+
export type { DateRangeBound, DateRangeValue, ResolvedDateRangeFacet } from "./app/list-facets";
|
|
68
|
+
export {
|
|
69
|
+
buildDateRangePayload,
|
|
70
|
+
clampDateRange,
|
|
71
|
+
readDateRange,
|
|
72
|
+
resolveDateRangeFacets,
|
|
73
|
+
} from "./app/list-facets";
|
|
67
74
|
export type {
|
|
68
75
|
NavApi,
|
|
69
76
|
NavProviderProps,
|
|
@@ -82,12 +89,15 @@ export {
|
|
|
82
89
|
useNavigateWithInitialValues,
|
|
83
90
|
} from "./app/nav";
|
|
84
91
|
export { lastSegment } from "./app/qn";
|
|
85
|
-
export type { ReturnHost } from "./app/return-to";
|
|
92
|
+
export type { ReturnHost, ReturnTo } from "./app/return-to";
|
|
86
93
|
export {
|
|
94
|
+
navigateToReturn,
|
|
95
|
+
navigateToReturnOr,
|
|
87
96
|
navigateWithReturnTo,
|
|
88
97
|
RETURN_TO_PARAM,
|
|
89
98
|
ReturnHostProvider,
|
|
90
99
|
resolveReturnTarget,
|
|
100
|
+
splitReturnTo,
|
|
91
101
|
useReturnHost,
|
|
92
102
|
useReturnTarget,
|
|
93
103
|
} from "./app/return-to";
|
|
@@ -185,6 +195,7 @@ export type {
|
|
|
185
195
|
CardProps,
|
|
186
196
|
CardSlots,
|
|
187
197
|
CorePrimitives,
|
|
198
|
+
DataTableDateRangeFacet,
|
|
188
199
|
DataTableFacet,
|
|
189
200
|
DataTableProps,
|
|
190
201
|
DataTableRowAction,
|
package/src/primitives.tsx
CHANGED
|
@@ -572,6 +572,18 @@ export type DataTableFacet = {
|
|
|
572
572
|
readonly options: readonly { readonly value: string; readonly label: string }[];
|
|
573
573
|
};
|
|
574
574
|
|
|
575
|
+
// Time-range filter slot in the toolbar (fw#3104): two date inputs
|
|
576
|
+
// (from/to) instead of an options dropdown. Values are `YYYY-MM-DD` or ""
|
|
577
|
+
// (bound open) — the caller converts them into query params.
|
|
578
|
+
export type DataTableDateRangeFacet = {
|
|
579
|
+
/** The facet's namespace (its date field) — a key, not a filter value. */
|
|
580
|
+
readonly field: string;
|
|
581
|
+
/** Translated label ("When"). */
|
|
582
|
+
readonly label: string;
|
|
583
|
+
readonly from: string;
|
|
584
|
+
readonly to: string;
|
|
585
|
+
};
|
|
586
|
+
|
|
575
587
|
export type DataTableProps = {
|
|
576
588
|
readonly columns: readonly ListColumnViewModel[];
|
|
577
589
|
readonly rows: readonly ListRowViewModel[];
|
|
@@ -622,6 +634,10 @@ export type DataTableProps = {
|
|
|
622
634
|
/** Reset-Button: löscht alle aktiven Facets. Renderer zeigt ihn nur
|
|
623
635
|
* wenn mindestens ein Facet aktiv ist. */
|
|
624
636
|
readonly onFilterReset?: () => void;
|
|
637
|
+
/** Time-range filters beside the facet dropdowns (fw#3104). */
|
|
638
|
+
readonly dateRangeFacets?: readonly DataTableDateRangeFacet[];
|
|
639
|
+
/** One bound changed ("" clears it) → caller writes URL state + refetch. */
|
|
640
|
+
readonly onDateRangeChange?: (field: string, bound: "from" | "to", value: string) => void;
|
|
625
641
|
/** Pagination-State + Callback. Wenn gesetzt, rendert der Renderer
|
|
626
642
|
* einen Pager unter der Tabelle (Web: Footer-Bar mit ← 1 ... N →).
|
|
627
643
|
* total/limit/page sind 1-basiert für die UI; Server-Translation
|