@burojs/ui-shadcn 0.6.0 → 0.8.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/README.md +9 -0
- package/dist/bulk-summary-2HLgz7Il.cjs +169 -0
- package/dist/bulk-summary-2HLgz7Il.cjs.map +1 -0
- package/dist/bulk-summary-D6A0ua21.js +169 -0
- package/dist/bulk-summary-D6A0ua21.js.map +1 -0
- package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-C47mF260.cjs} +4 -4
- package/dist/{candidates-relation-picker-Cy0rTxvI.cjs.map → candidates-relation-picker-C47mF260.cjs.map} +1 -1
- package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CGXItMN0.js} +3 -3
- package/dist/{candidates-relation-picker-B116Bmqi.js.map → candidates-relation-picker-CGXItMN0.js.map} +1 -1
- package/dist/{check-confirm-dialog--gPFnEeg.cjs → check-confirm-dialog-BT04Mieo.cjs} +475 -107
- package/dist/check-confirm-dialog-BT04Mieo.cjs.map +1 -0
- package/dist/{check-confirm-dialog-bRT8lt0d.js → check-confirm-dialog-CtiRzOAt.js} +391 -108
- package/dist/check-confirm-dialog-CtiRzOAt.js.map +1 -0
- package/dist/{dialog-B_rt9S1c.js → dialog-C123sVQ8.js} +4 -4
- package/dist/dialog-C123sVQ8.js.map +1 -0
- package/dist/{dialog-DRNUq9EA.cjs → dialog-vmMdfUWs.cjs} +3 -3
- package/dist/dialog-vmMdfUWs.cjs.map +1 -0
- package/dist/{filter-builder-nXqtM_h4.cjs → filter-builder-ByGhxLf_.cjs} +1021 -154
- package/dist/filter-builder-ByGhxLf_.cjs.map +1 -0
- package/dist/{filter-builder-Bhn-dhZV.js → filter-builder-z3Axzf9Y.js} +929 -140
- package/dist/filter-builder-z3Axzf9Y.js.map +1 -0
- package/dist/{flow-runtime-D3avVH0I.cjs → flow-runtime-BVFjMU5-.cjs} +64 -29
- package/dist/flow-runtime-BVFjMU5-.cjs.map +1 -0
- package/dist/{flow-runtime-s6lkRPKF.js → flow-runtime-DrUWyTS0.js} +65 -30
- package/dist/flow-runtime-DrUWyTS0.js.map +1 -0
- package/dist/{flow-screen-CCvgDI9G.js → flow-screen-3fk6J33y.js} +130 -87
- package/dist/flow-screen-3fk6J33y.js.map +1 -0
- package/dist/{flow-screen-Ci_Sik4Y.cjs → flow-screen-6y5E_HT6.cjs} +130 -87
- package/dist/flow-screen-6y5E_HT6.cjs.map +1 -0
- package/dist/index.cjs +1186 -950
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +631 -322
- package/dist/index.d.ts +631 -322
- package/dist/index.js +1100 -870
- package/dist/index.js.map +1 -1
- package/dist/{inline-flow-host-DV1et3c6.cjs → inline-flow-host-C4KmZIYE.cjs} +5 -5
- package/dist/inline-flow-host-C4KmZIYE.cjs.map +1 -0
- package/dist/{inline-flow-host-B6FI0ctQ.js → inline-flow-host-YnnvWjdU.js} +5 -5
- package/dist/inline-flow-host-YnnvWjdU.js.map +1 -0
- package/dist/{candidates-gate-D33jXLHO.cjs → lazy-relation-picker-dialog-BAKBRn3V.cjs} +10 -10
- package/dist/lazy-relation-picker-dialog-BAKBRn3V.cjs.map +1 -0
- package/dist/{candidates-gate-Bb70LPAy.js → lazy-relation-picker-dialog-DN4bvQfg.js} +11 -11
- package/dist/lazy-relation-picker-dialog-DN4bvQfg.js.map +1 -0
- package/dist/{page-flow-route-i3ZfJ1sd.js → page-flow-route-CtEfqAvU.js} +35 -23
- package/dist/page-flow-route-CtEfqAvU.js.map +1 -0
- package/dist/{page-flow-route-hdnULWqd.cjs → page-flow-route-DEjAxHe3.cjs} +42 -30
- package/dist/page-flow-route-DEjAxHe3.cjs.map +1 -0
- package/dist/{place-node-NraNYKPx.js → place-node-BdxT-30h.js} +1980 -1041
- package/dist/place-node-BdxT-30h.js.map +1 -0
- package/dist/{place-node-C5SmIAYU.cjs → place-node-Bhl8B3fF.cjs} +2038 -1087
- package/dist/place-node-Bhl8B3fF.cjs.map +1 -0
- package/dist/{related-list-cards-CFq3meUn.cjs → related-list-cards-Bc_vfCE_.cjs} +9 -4
- package/dist/{related-list-cards-CFq3meUn.cjs.map → related-list-cards-Bc_vfCE_.cjs.map} +1 -1
- package/dist/{related-list-cards-BWZ9GfOG.js → related-list-cards-BvkD5OcC.js} +9 -4
- package/dist/{related-list-cards-BWZ9GfOG.js.map → related-list-cards-BvkD5OcC.js.map} +1 -1
- package/dist/related-list-timeline-DCrwN9oO.js +167 -0
- package/dist/related-list-timeline-DCrwN9oO.js.map +1 -0
- package/dist/related-list-timeline-k0DtnxTs.cjs +167 -0
- package/dist/related-list-timeline-k0DtnxTs.cjs.map +1 -0
- package/dist/{related-rows-ea43qhhy.cjs → related-rows-BW9Jr07T.cjs} +27 -16
- package/dist/related-rows-BW9Jr07T.cjs.map +1 -0
- package/dist/{related-rows-o0_t-Yce.js → related-rows-CPE-9FFr.js} +25 -14
- package/dist/related-rows-CPE-9FFr.js.map +1 -0
- package/dist/{search-access-CPPmfuvy.js → relation-create-C43cdPQt.js} +595 -13
- package/dist/relation-create-C43cdPQt.js.map +1 -0
- package/dist/{search-access-Dugvttlg.cjs → relation-create-DDEYcKfw.cjs} +633 -14
- package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
- package/dist/{relation-many-picker-bvkjkv-k.js → relation-many-picker-BlrGRwMV.js} +210 -104
- package/dist/relation-many-picker-BlrGRwMV.js.map +1 -0
- package/dist/{relation-many-picker-C8zFEjwd.cjs → relation-many-picker-Br-zBHxT.cjs} +218 -112
- package/dist/relation-many-picker-Br-zBHxT.cjs.map +1 -0
- package/dist/{relation-picker-gag0qSR5.cjs → relation-picker-ADjxI_TI.cjs} +36 -73
- package/dist/relation-picker-ADjxI_TI.cjs.map +1 -0
- package/dist/{relation-picker-dialog-B6nIiJBf.js → relation-picker-dialog-CyKliBkN.js} +134 -36
- package/dist/relation-picker-dialog-CyKliBkN.js.map +1 -0
- package/dist/{relation-picker-dialog-0IzkjmiA.cjs → relation-picker-dialog-DimVQF9Y.cjs} +133 -35
- package/dist/relation-picker-dialog-DimVQF9Y.cjs.map +1 -0
- package/dist/{relation-picker-Z0ZJJ5uS.js → relation-picker-x7P5HKie.js} +30 -61
- package/dist/relation-picker-x7P5HKie.js.map +1 -0
- package/dist/relation-select-B8Fq4o-t.js +48 -0
- package/dist/relation-select-B8Fq4o-t.js.map +1 -0
- package/dist/relation-select-Cr3CfNLy.cjs +55 -0
- package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
- package/dist/{resource-page-router-3RUf9d1j.js → resource-page-router-BRpUnhay.js} +634 -264
- package/dist/resource-page-router-BRpUnhay.js.map +1 -0
- package/dist/{resource-page-router-PXfMW9nh.cjs → resource-page-router-qEd2xb55.cjs} +694 -312
- package/dist/resource-page-router-qEd2xb55.cjs.map +1 -0
- package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
- package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
- package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
- package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
- package/dist/success-notices-Dl3M1fZP.cjs +46 -0
- package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
- package/dist/success-notices-LDEgEkc4.js +41 -0
- package/dist/success-notices-LDEgEkc4.js.map +1 -0
- package/dist/{toaster-Cr51X7bz.cjs → toaster-BbByOytP.cjs} +60 -15
- package/dist/toaster-BbByOytP.cjs.map +1 -0
- package/dist/{toaster-C02XbB9r.js → toaster-Ct_YHGs6.js} +43 -16
- package/dist/toaster-Ct_YHGs6.js.map +1 -0
- package/dist/{use-dialog-filter-state-C--oMAZG.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
- package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
- package/dist/{use-dialog-filter-state-Dhe8PcB5.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
- package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
- package/dist/use-record-subtitle-bfwIoUme.cjs +70 -0
- package/dist/use-record-subtitle-bfwIoUme.cjs.map +1 -0
- package/dist/use-record-subtitle-gIaCGgbI.js +53 -0
- package/dist/use-record-subtitle-gIaCGgbI.js.map +1 -0
- package/package.json +11 -11
- package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
- package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
- package/dist/bulk-summary-GxMDP4bw.js +0 -108
- package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
- package/dist/candidates-gate-Bb70LPAy.js.map +0 -1
- package/dist/candidates-gate-D33jXLHO.cjs.map +0 -1
- package/dist/check-confirm-dialog--gPFnEeg.cjs.map +0 -1
- package/dist/check-confirm-dialog-bRT8lt0d.js.map +0 -1
- package/dist/dialog-B_rt9S1c.js.map +0 -1
- package/dist/dialog-DRNUq9EA.cjs.map +0 -1
- package/dist/filter-builder-Bhn-dhZV.js.map +0 -1
- package/dist/filter-builder-nXqtM_h4.cjs.map +0 -1
- package/dist/flow-runtime-D3avVH0I.cjs.map +0 -1
- package/dist/flow-runtime-s6lkRPKF.js.map +0 -1
- package/dist/flow-screen-CCvgDI9G.js.map +0 -1
- package/dist/flow-screen-Ci_Sik4Y.cjs.map +0 -1
- package/dist/inline-flow-host-B6FI0ctQ.js.map +0 -1
- package/dist/inline-flow-host-DV1et3c6.cjs.map +0 -1
- package/dist/page-flow-route-hdnULWqd.cjs.map +0 -1
- package/dist/page-flow-route-i3ZfJ1sd.js.map +0 -1
- package/dist/place-node-C5SmIAYU.cjs.map +0 -1
- package/dist/place-node-NraNYKPx.js.map +0 -1
- package/dist/related-list-timeline-CCzl71aA.cjs +0 -142
- package/dist/related-list-timeline-CCzl71aA.cjs.map +0 -1
- package/dist/related-list-timeline-yrPsjA3F.js +0 -142
- package/dist/related-list-timeline-yrPsjA3F.js.map +0 -1
- package/dist/related-rows-ea43qhhy.cjs.map +0 -1
- package/dist/related-rows-o0_t-Yce.js.map +0 -1
- package/dist/relation-create-IA40t1hi.cjs +0 -364
- package/dist/relation-create-IA40t1hi.cjs.map +0 -1
- package/dist/relation-create-h6F9B4C4.js +0 -339
- package/dist/relation-create-h6F9B4C4.js.map +0 -1
- package/dist/relation-many-picker-C8zFEjwd.cjs.map +0 -1
- package/dist/relation-many-picker-bvkjkv-k.js.map +0 -1
- package/dist/relation-picker-Z0ZJJ5uS.js.map +0 -1
- package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +0 -1
- package/dist/relation-picker-dialog-B6nIiJBf.js.map +0 -1
- package/dist/relation-picker-gag0qSR5.cjs.map +0 -1
- package/dist/resource-page-router-3RUf9d1j.js.map +0 -1
- package/dist/resource-page-router-PXfMW9nh.cjs.map +0 -1
- package/dist/search-access-CPPmfuvy.js.map +0 -1
- package/dist/search-access-Dugvttlg.cjs.map +0 -1
- package/dist/shell-BPlk8hEa.js +0 -205
- package/dist/shell-BPlk8hEa.js.map +0 -1
- package/dist/shell-DxhlsPwm.cjs +0 -271
- package/dist/shell-DxhlsPwm.cjs.map +0 -1
- package/dist/toaster-C02XbB9r.js.map +0 -1
- package/dist/toaster-Cr51X7bz.cjs.map +0 -1
- package/dist/use-dialog-filter-state-C--oMAZG.js.map +0 -1
- package/dist/use-dialog-filter-state-Dhe8PcB5.cjs.map +0 -1
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { l as cn } from "./use-theme-dnE3Od3I.js";
|
|
2
|
-
import {
|
|
2
|
+
import { m as PopoverTrigger, p as PopoverContent, u as Popover } from "./toaster-Ct_YHGs6.js";
|
|
3
3
|
import { t as Button } from "./button-MWVeZaqj.js";
|
|
4
4
|
import { t as Input } from "./input-CUPStzZO.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { C as CommandEmpty, D as CommandList, E as CommandItem, T as CommandInput, m as useRowTitle, o as narrowSearchDecl, w as CommandGroup, x as Command } from "./relation-create-C43cdPQt.js";
|
|
6
|
+
import { t as Skeleton } from "./skeleton-U2noefj5.js";
|
|
7
|
+
import { EMPTY_FILTER_GROUP, canonicalInstant, canonicalResourceKey, convertValueForOp, declaredText, enumValueText, formatEntityRef, formatTimeValue, instantToWall, isCalendarDate, isCompletePredicate, isFilterGroup, isWallTime, opArity, resolveEnumLabel, resolveSurfaceUi, resolveTimeZone, wallToInstant } from "@burojs/core";
|
|
8
|
+
import { DEFAULT_LANGUAGE_STORAGE_KEY, scopeValueOf, useApp, useChromeT, useEnumValues, useFieldDisplayText, useFieldImplementation, useFieldMeta, useFieldMetaSources, useI18nCaps, useImplementationTexts, useList, useListAccess, useLocale, useOptionalLocale, useOptionalT, useRelatedRecord, useResolvedFieldOptions, useTimeContext, useTimeZone } from "@burojs/react";
|
|
9
|
+
import { IconCheck, IconChevronDown, IconChevronUp, IconCirclePlus, IconFilter, IconFolderPlus, IconLoader2, IconPlus, IconX } from "@tabler/icons-react";
|
|
9
10
|
import * as React from "react";
|
|
10
|
-
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
|
+
import { Fragment, createElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
12
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
13
|
import { cva } from "class-variance-authority";
|
|
14
|
+
import { normaliseFieldZone } from "@burojs/core/internal";
|
|
13
15
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
14
16
|
//#region src/layout/language-storage.ts
|
|
15
17
|
function loadLocale(storageKey = DEFAULT_LANGUAGE_STORAGE_KEY) {
|
|
@@ -27,6 +29,536 @@ function saveLocale(code, storageKey = DEFAULT_LANGUAGE_STORAGE_KEY) {
|
|
|
27
29
|
} catch {}
|
|
28
30
|
}
|
|
29
31
|
//#endregion
|
|
32
|
+
//#region src/fields/legacy-field.ts
|
|
33
|
+
const STRING_ITEM = Object.freeze({ type: "string" });
|
|
34
|
+
const LEGACY_KIND_DECLARATIONS = Object.freeze({
|
|
35
|
+
string: { type: "string" },
|
|
36
|
+
text: {
|
|
37
|
+
type: "string",
|
|
38
|
+
format: "text"
|
|
39
|
+
},
|
|
40
|
+
textarea: {
|
|
41
|
+
type: "string",
|
|
42
|
+
format: "textarea"
|
|
43
|
+
},
|
|
44
|
+
code: {
|
|
45
|
+
type: "string",
|
|
46
|
+
format: "code"
|
|
47
|
+
},
|
|
48
|
+
email: {
|
|
49
|
+
type: "string",
|
|
50
|
+
format: "email"
|
|
51
|
+
},
|
|
52
|
+
url: {
|
|
53
|
+
type: "string",
|
|
54
|
+
format: "url"
|
|
55
|
+
},
|
|
56
|
+
uuid: {
|
|
57
|
+
type: "string",
|
|
58
|
+
format: "uuid"
|
|
59
|
+
},
|
|
60
|
+
number: { type: "number" },
|
|
61
|
+
boolean: { type: "boolean" },
|
|
62
|
+
date: {
|
|
63
|
+
type: "string",
|
|
64
|
+
format: "date"
|
|
65
|
+
},
|
|
66
|
+
dateTime: {
|
|
67
|
+
type: "string",
|
|
68
|
+
format: "date-time"
|
|
69
|
+
},
|
|
70
|
+
enum: {
|
|
71
|
+
type: "string",
|
|
72
|
+
format: "enum"
|
|
73
|
+
},
|
|
74
|
+
json: {
|
|
75
|
+
type: "object",
|
|
76
|
+
format: "json"
|
|
77
|
+
},
|
|
78
|
+
richText: {
|
|
79
|
+
type: "string",
|
|
80
|
+
format: "rich-text"
|
|
81
|
+
},
|
|
82
|
+
file: {
|
|
83
|
+
type: "array",
|
|
84
|
+
format: "file",
|
|
85
|
+
items: STRING_ITEM
|
|
86
|
+
},
|
|
87
|
+
relation: { type: "relation" },
|
|
88
|
+
relationMany: {
|
|
89
|
+
type: "array",
|
|
90
|
+
format: "relation",
|
|
91
|
+
items: STRING_ITEM
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const SEMANTIC_KEYS = Object.freeze([
|
|
95
|
+
"type",
|
|
96
|
+
"format",
|
|
97
|
+
"meta",
|
|
98
|
+
"required",
|
|
99
|
+
"nullable",
|
|
100
|
+
"empty",
|
|
101
|
+
"default",
|
|
102
|
+
"constraints",
|
|
103
|
+
"zone",
|
|
104
|
+
"texts",
|
|
105
|
+
"options",
|
|
106
|
+
"items",
|
|
107
|
+
"properties",
|
|
108
|
+
"additionalProperties",
|
|
109
|
+
"variants"
|
|
110
|
+
]);
|
|
111
|
+
function ownData(value, key) {
|
|
112
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return { present: false };
|
|
113
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
114
|
+
if (descriptor === void 0 || !Object.prototype.propertyIsEnumerable.call(value, key) || !("value" in descriptor)) return { present: false };
|
|
115
|
+
return {
|
|
116
|
+
present: true,
|
|
117
|
+
value: descriptor.value
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function ownString(value, key) {
|
|
121
|
+
const candidate = ownData(value, key).value;
|
|
122
|
+
return typeof candidate === "string" && candidate.length > 0 ? candidate : void 0;
|
|
123
|
+
}
|
|
124
|
+
function ownSelection(value, key) {
|
|
125
|
+
const candidate = ownData(value, key).value;
|
|
126
|
+
if (typeof candidate === "string") return candidate.length > 0 ? candidate : void 0;
|
|
127
|
+
return candidate !== null && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : void 0;
|
|
128
|
+
}
|
|
129
|
+
function projectUiSelection(input) {
|
|
130
|
+
const selection = {};
|
|
131
|
+
const inputId = ownSelection(input, "input");
|
|
132
|
+
const displayId = ownSelection(input, "display");
|
|
133
|
+
const layout = ownData(input, "layout").value;
|
|
134
|
+
if (inputId !== void 0) selection.input = inputId;
|
|
135
|
+
if (displayId !== void 0) selection.display = displayId;
|
|
136
|
+
if (Array.isArray(layout)) selection.layout = layout;
|
|
137
|
+
return Object.keys(selection).length === 0 ? void 0 : Object.freeze(selection);
|
|
138
|
+
}
|
|
139
|
+
function projectFieldDeclaration(input) {
|
|
140
|
+
const type = ownString(input, "type");
|
|
141
|
+
if (type === void 0) return void 0;
|
|
142
|
+
const projected = { type };
|
|
143
|
+
for (const key of SEMANTIC_KEYS) {
|
|
144
|
+
if (key === "type" || key === "items" || key === "properties" || key === "variants") continue;
|
|
145
|
+
const candidate = ownData(input, key);
|
|
146
|
+
if (candidate.present && candidate.value !== void 0) projected[key] = candidate.value;
|
|
147
|
+
}
|
|
148
|
+
const ui = projectUiSelection(ownData(input, "ui").value);
|
|
149
|
+
if (ui !== void 0) projected.ui = ui;
|
|
150
|
+
if (type === "array") {
|
|
151
|
+
const item = projectFieldDeclaration(ownData(input, "items").value);
|
|
152
|
+
if (item !== void 0) projected.items = item;
|
|
153
|
+
}
|
|
154
|
+
if (type === "object") {
|
|
155
|
+
const properties = ownData(input, "properties").value;
|
|
156
|
+
if (Array.isArray(properties)) {
|
|
157
|
+
const output = {};
|
|
158
|
+
for (let index = 0; index < properties.length; index += 1) {
|
|
159
|
+
const entry = ownData(properties, index).value;
|
|
160
|
+
const name = ownString(entry, "name");
|
|
161
|
+
const child = projectFieldDeclaration(entry);
|
|
162
|
+
if (name !== void 0 && child !== void 0) output[name] = child;
|
|
163
|
+
}
|
|
164
|
+
projected.properties = Object.freeze(output);
|
|
165
|
+
} else if (properties !== null && typeof properties === "object") {
|
|
166
|
+
const output = {};
|
|
167
|
+
for (const key of Object.keys(properties)) {
|
|
168
|
+
const child = projectFieldDeclaration(ownData(properties, key).value);
|
|
169
|
+
if (child !== void 0) output[key] = child;
|
|
170
|
+
}
|
|
171
|
+
projected.properties = Object.freeze(output);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (type === "union") {
|
|
175
|
+
const variants = ownData(input, "variants").value;
|
|
176
|
+
if (Array.isArray(variants)) {
|
|
177
|
+
const output = [];
|
|
178
|
+
for (let index = 0; index < variants.length; index += 1) {
|
|
179
|
+
const child = projectFieldDeclaration(ownData(variants, index).value);
|
|
180
|
+
if (child !== void 0) output.push(child);
|
|
181
|
+
}
|
|
182
|
+
projected.variants = Object.freeze(output);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return Object.freeze(projected);
|
|
186
|
+
}
|
|
187
|
+
function projectUiHints(input) {
|
|
188
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) return void 0;
|
|
189
|
+
const projected = {};
|
|
190
|
+
for (const key of Object.keys(input)) {
|
|
191
|
+
const candidate = ownData(input, key);
|
|
192
|
+
if (candidate.present) projected[key] = candidate.value;
|
|
193
|
+
}
|
|
194
|
+
return Object.freeze(projected);
|
|
195
|
+
}
|
|
196
|
+
function enumValueOptions(field) {
|
|
197
|
+
const own = ownData(field, "values").value;
|
|
198
|
+
const values = Array.isArray(own) ? own : ownData(ownData(field, "ui").value, "values").value;
|
|
199
|
+
if (!Array.isArray(values)) return void 0;
|
|
200
|
+
const options = values.filter((value) => typeof value === "string").map((value) => Object.freeze({ value }));
|
|
201
|
+
return options.length === 0 ? void 0 : Object.freeze(options);
|
|
202
|
+
}
|
|
203
|
+
function lowerLegacyField(field) {
|
|
204
|
+
const declaration = projectFieldDeclaration(ownData(field, "declaration").value);
|
|
205
|
+
if (declaration !== void 0) return declaration;
|
|
206
|
+
const direct = projectFieldDeclaration(field);
|
|
207
|
+
const kind = ownString(field, "kind");
|
|
208
|
+
const mapping = kind === void 0 ? void 0 : LEGACY_KIND_DECLARATIONS[kind];
|
|
209
|
+
if (direct !== void 0) {
|
|
210
|
+
const format = direct.format ?? mapping?.format ?? kind;
|
|
211
|
+
return format === void 0 ? direct : Object.freeze({
|
|
212
|
+
...direct,
|
|
213
|
+
format
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const ui = projectUiHints(ownData(field, "ui").value);
|
|
217
|
+
const type = kind === "file" && ui?.multiple !== true ? "unknown" : mapping?.type ?? "unknown";
|
|
218
|
+
const format = ownString(field, "format") ?? mapping?.format ?? kind;
|
|
219
|
+
const items = type === "array" ? projectFieldDeclaration(ownData(field, "items").value) ?? mapping?.items ?? STRING_ITEM : void 0;
|
|
220
|
+
const meta = ownData(field, "meta");
|
|
221
|
+
const texts = ownData(field, "texts");
|
|
222
|
+
const zone = ownData(field, "zone");
|
|
223
|
+
const options = kind === "enum" ? enumValueOptions(field) : void 0;
|
|
224
|
+
const required = ownData(field, "required");
|
|
225
|
+
const nullable = ownData(field, "nullable");
|
|
226
|
+
const opts = ownData(field, "opts").value;
|
|
227
|
+
const optionRequired = ownData(opts, "required");
|
|
228
|
+
const optionNullable = ownData(opts, "nullable");
|
|
229
|
+
const requiredValue = required.present ? required.value : optionRequired.value;
|
|
230
|
+
const nullableValue = nullable.present ? nullable.value : optionNullable.value;
|
|
231
|
+
return Object.freeze({
|
|
232
|
+
type,
|
|
233
|
+
...format === void 0 ? {} : { format },
|
|
234
|
+
...items === void 0 ? {} : { items },
|
|
235
|
+
...meta.present && meta.value !== void 0 ? { meta: meta.value } : {},
|
|
236
|
+
...options === void 0 ? {} : { options },
|
|
237
|
+
...texts.present && texts.value !== void 0 ? { texts: texts.value } : {},
|
|
238
|
+
...zone.present && zone.value !== void 0 ? { zone: zone.value } : {},
|
|
239
|
+
...requiredValue === true ? { required: true } : {},
|
|
240
|
+
...nullableValue === true ? { nullable: true } : {}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function lowerLegacyFieldSource(field) {
|
|
244
|
+
const declaration = lowerLegacyField(field);
|
|
245
|
+
const ui = projectUiHints(ownData(field, "ui").value);
|
|
246
|
+
if (ui === void 0) return declaration;
|
|
247
|
+
return Object.freeze({
|
|
248
|
+
...declaration,
|
|
249
|
+
ui
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
function fieldDescription(field) {
|
|
253
|
+
const declaration = field?.declaration;
|
|
254
|
+
return declaredText("field", declaration, "description") ?? declaredText("field", field, "description");
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/fields/resolved-field.tsx
|
|
258
|
+
const EMPTY = Object.freeze({});
|
|
259
|
+
const EMPTY_ISSUES = Object.freeze([]);
|
|
260
|
+
const EMPTY_OPTIONS = Object.freeze([]);
|
|
261
|
+
function canonical(field) {
|
|
262
|
+
return lowerLegacyField(field);
|
|
263
|
+
}
|
|
264
|
+
function useLoweredField(source) {
|
|
265
|
+
return useMemo(() => {
|
|
266
|
+
const sourceAtEdge = lowerLegacyFieldSource(source);
|
|
267
|
+
return {
|
|
268
|
+
sourceAtEdge,
|
|
269
|
+
field: canonical(sourceAtEdge),
|
|
270
|
+
ui: sourceAtEdge.ui ?? EMPTY
|
|
271
|
+
};
|
|
272
|
+
}, [source]);
|
|
273
|
+
}
|
|
274
|
+
const warnedObjectLabels = new Set();
|
|
275
|
+
function optionsFor(field, name) {
|
|
276
|
+
if (Array.isArray(field.options)) return field.options;
|
|
277
|
+
const candidate = field.meta?.options;
|
|
278
|
+
if (!Array.isArray(candidate)) return EMPTY_OPTIONS;
|
|
279
|
+
const output = [];
|
|
280
|
+
for (const item of candidate) {
|
|
281
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) continue;
|
|
282
|
+
const raw = item;
|
|
283
|
+
if (typeof raw.value !== "string" && typeof raw.value !== "number" && typeof raw.value !== "boolean" && raw.value !== null) continue;
|
|
284
|
+
const { value, label, description, ...legacyMeta } = raw;
|
|
285
|
+
if (typeof label !== "string" && process.env.NODE_ENV !== "production" && !warnedObjectLabels.has(`${name}:${value}`)) {
|
|
286
|
+
warnedObjectLabels.add(`${name}:${value}`);
|
|
287
|
+
console.warn(`[buro/ui-shadcn] field '${name}': option '${value}' has a non-string label, so it renders its raw value. Declare a plain string label and put the translations under fields.${name}.options.${value} (see docs/i18n-guide.md).`);
|
|
288
|
+
}
|
|
289
|
+
output.push(Object.freeze({
|
|
290
|
+
value,
|
|
291
|
+
label: typeof label === "string" ? label : String(value),
|
|
292
|
+
...typeof description === "string" ? { description } : {},
|
|
293
|
+
...Object.keys(legacyMeta).length === 0 ? {} : { meta: Object.freeze(legacyMeta) }
|
|
294
|
+
}));
|
|
295
|
+
}
|
|
296
|
+
return Object.freeze(output);
|
|
297
|
+
}
|
|
298
|
+
function useContextOptions(field, name, meta, ui, resource) {
|
|
299
|
+
const legacy = field.meta?.options;
|
|
300
|
+
const options = useMemo(() => optionsFor(field, name), [
|
|
301
|
+
field.options,
|
|
302
|
+
legacy,
|
|
303
|
+
name
|
|
304
|
+
]);
|
|
305
|
+
return useResolvedFieldOptions({
|
|
306
|
+
name,
|
|
307
|
+
meta,
|
|
308
|
+
ui,
|
|
309
|
+
texts: field.texts
|
|
310
|
+
}, options, resource.id);
|
|
311
|
+
}
|
|
312
|
+
function useContextTexts(field, name, resolved, resource) {
|
|
313
|
+
return useImplementationTexts({
|
|
314
|
+
fieldName: name,
|
|
315
|
+
fieldTexts: field.texts,
|
|
316
|
+
id: resolved.id,
|
|
317
|
+
implementation: resolved.implementation
|
|
318
|
+
}, resource.id);
|
|
319
|
+
}
|
|
320
|
+
function useFieldRuntimeContext(resource, record, values, metaSources) {
|
|
321
|
+
const locale = useLocale();
|
|
322
|
+
const caps = useI18nCaps(canonicalResourceKey(resource));
|
|
323
|
+
const metaSourcesOut = useFieldMetaSources({
|
|
324
|
+
record,
|
|
325
|
+
values,
|
|
326
|
+
extra: metaSources
|
|
327
|
+
});
|
|
328
|
+
const scopeState = metaSourcesOut.scope;
|
|
329
|
+
const scope = scopeState === void 0 ? void 0 : scopeValueOf(scopeState);
|
|
330
|
+
return useMemo(() => Object.freeze({
|
|
331
|
+
i18n: Object.freeze({
|
|
332
|
+
locale,
|
|
333
|
+
has: caps.has,
|
|
334
|
+
t: caps.t
|
|
335
|
+
}),
|
|
336
|
+
sources: Object.freeze({
|
|
337
|
+
record: record ?? EMPTY,
|
|
338
|
+
values: values ?? EMPTY,
|
|
339
|
+
scope: scope ?? EMPTY
|
|
340
|
+
}),
|
|
341
|
+
metaSources: metaSourcesOut
|
|
342
|
+
}), [
|
|
343
|
+
caps,
|
|
344
|
+
locale,
|
|
345
|
+
record,
|
|
346
|
+
scope,
|
|
347
|
+
values,
|
|
348
|
+
metaSourcesOut
|
|
349
|
+
]);
|
|
350
|
+
}
|
|
351
|
+
function useFieldMetaDiagnostic(state, resource, name, field, surface, entry) {
|
|
352
|
+
const reported = useRef(void 0);
|
|
353
|
+
const reason = state.status === "failed" ? state.reason : void 0;
|
|
354
|
+
useEffect(() => {
|
|
355
|
+
if (reason === void 0 || reported.current === reason || process.env.NODE_ENV === "production") return;
|
|
356
|
+
reported.current = reason;
|
|
357
|
+
const implementation = resolveSurfaceUi(field, surface, entry).use ?? field.format ?? field.type;
|
|
358
|
+
console.error(`[burojs] field.meta-invalid: ${formatEntityRef(resource)}.${name} (${implementation}): ${reason}`);
|
|
359
|
+
}, [
|
|
360
|
+
reason,
|
|
361
|
+
resource,
|
|
362
|
+
name,
|
|
363
|
+
field,
|
|
364
|
+
surface,
|
|
365
|
+
entry
|
|
366
|
+
]);
|
|
367
|
+
}
|
|
368
|
+
function MetaPlaceholder({ state }) {
|
|
369
|
+
const t = useOptionalT();
|
|
370
|
+
if (state.status === "pending") return jsx(Skeleton, {
|
|
371
|
+
"data-buro-skeleton": "",
|
|
372
|
+
"data-buro-field-meta": "pending",
|
|
373
|
+
className: "h-9 w-full"
|
|
374
|
+
});
|
|
375
|
+
return jsx("div", {
|
|
376
|
+
role: "alert",
|
|
377
|
+
"data-buro-field-meta": "failed",
|
|
378
|
+
className: "rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground",
|
|
379
|
+
children: t("field.misconfigured", { defaultValue: "This field is misconfigured" })
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function useFieldImplementationDiagnostic(diagnostic) {
|
|
383
|
+
const reported = useRef(void 0);
|
|
384
|
+
useEffect(() => {
|
|
385
|
+
if (diagnostic === void 0 || reported.current === diagnostic || process.env.NODE_ENV === "production") return;
|
|
386
|
+
reported.current = diagnostic;
|
|
387
|
+
console.warn("[buro/ui-shadcn] missing-field-implementation; rendering fallback.", diagnostic);
|
|
388
|
+
}, [diagnostic]);
|
|
389
|
+
}
|
|
390
|
+
function ResolvedFieldDisplay({ resource, name, field: source, value, record, testId, fallback, presentation, metaSources, uiSurface = "display", columnEntry, absentPaths, pathStatus }) {
|
|
391
|
+
const { sourceAtEdge, field, ui } = useLoweredField(source);
|
|
392
|
+
const surfaceField = useMemo(() => sourceAtEdge.ui === void 0 ? field : Object.freeze({
|
|
393
|
+
...field,
|
|
394
|
+
ui
|
|
395
|
+
}), [
|
|
396
|
+
sourceAtEdge,
|
|
397
|
+
field,
|
|
398
|
+
ui
|
|
399
|
+
]);
|
|
400
|
+
const resolved = useFieldImplementation({
|
|
401
|
+
field: surfaceField,
|
|
402
|
+
surface: "display",
|
|
403
|
+
uiSurface,
|
|
404
|
+
...columnEntry === void 0 ? {} : { uiEntry: columnEntry }
|
|
405
|
+
});
|
|
406
|
+
const runtimeContext = useFieldRuntimeContext(resource, record, record, metaSources);
|
|
407
|
+
const metaState = useFieldMeta(field, resolved.implementation, runtimeContext.metaSources, resolved.params);
|
|
408
|
+
const textField = useMemo(() => Object.freeze({
|
|
409
|
+
...surfaceField,
|
|
410
|
+
name
|
|
411
|
+
}), [surfaceField, name]);
|
|
412
|
+
const text = useFieldDisplayText(textField, value, {
|
|
413
|
+
surface: uiSurface,
|
|
414
|
+
...columnEntry === void 0 ? {} : { entry: columnEntry },
|
|
415
|
+
resource: canonicalResourceKey(resource),
|
|
416
|
+
...record === void 0 ? {} : { record }
|
|
417
|
+
});
|
|
418
|
+
const options = useContextOptions(field, name, metaState.status === "ready" ? metaState.meta : void 0, ui, resource);
|
|
419
|
+
const texts = useContextTexts(field, name, resolved, resource);
|
|
420
|
+
const dateDisplay = resolveSurfaceUi(surfaceField, uiSurface, columnEntry).dateDisplay;
|
|
421
|
+
const contextUi = useMemo(() => dateDisplay === void 0 ? ui : Object.freeze({
|
|
422
|
+
...ui,
|
|
423
|
+
display: Object.freeze({
|
|
424
|
+
...typeof ui.display === "object" && ui.display !== null ? ui.display : {},
|
|
425
|
+
...dateDisplay
|
|
426
|
+
})
|
|
427
|
+
}), [ui, dateDisplay]);
|
|
428
|
+
useFieldMetaDiagnostic(metaState, resource, name, surfaceField, uiSurface, columnEntry);
|
|
429
|
+
useFieldImplementationDiagnostic(resolved.diagnostic);
|
|
430
|
+
if (resolved.Component === void 0) return jsx(Fragment$1, { children: fallback });
|
|
431
|
+
if (metaState.status !== "ready") return jsx(MetaPlaceholder, { state: metaState });
|
|
432
|
+
const Component = resolved.Component;
|
|
433
|
+
const context = {
|
|
434
|
+
owner: resource,
|
|
435
|
+
resource,
|
|
436
|
+
field,
|
|
437
|
+
path: Object.freeze([name]),
|
|
438
|
+
...absentPaths === void 0 || absentPaths.length === 0 ? {} : { absentPaths },
|
|
439
|
+
...pathStatus === void 0 ? {} : { pathStatus },
|
|
440
|
+
surface: "display",
|
|
441
|
+
presentation: presentation ?? "default",
|
|
442
|
+
record,
|
|
443
|
+
meta: metaState.meta,
|
|
444
|
+
ui: contextUi,
|
|
445
|
+
options,
|
|
446
|
+
texts,
|
|
447
|
+
...text === void 0 ? {} : { text },
|
|
448
|
+
i18n: runtimeContext.i18n,
|
|
449
|
+
sources: runtimeContext.sources,
|
|
450
|
+
pending: false,
|
|
451
|
+
touched: false,
|
|
452
|
+
issues: EMPTY_ISSUES,
|
|
453
|
+
accessibility: EMPTY,
|
|
454
|
+
testIds: testId === void 0 ? EMPTY : Object.freeze({ display: testId })
|
|
455
|
+
};
|
|
456
|
+
if (resolved.multiple) return createElement(Component, {
|
|
457
|
+
...context,
|
|
458
|
+
multiple: true,
|
|
459
|
+
value: Array.isArray(value) ? value : []
|
|
460
|
+
});
|
|
461
|
+
return createElement(Component, {
|
|
462
|
+
...context,
|
|
463
|
+
multiple: false,
|
|
464
|
+
value
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
function ResolvedFieldInput({ resource, name, field: source, value, record, form, testId, inputId, onChange, onBlur, disabled, required, placeholder, descriptionId, labelId, errorId, errorMessage, pending = false, touched = errorMessage != null, issues: suppliedIssues, relationSeeds, fixedFilters, optionSubtitle, link, metaSources, baseline, fallback, absentPaths, pathStatus }) {
|
|
468
|
+
const { sourceAtEdge, field: base } = useLoweredField(source);
|
|
469
|
+
const field = useMemo(() => required === void 0 || required === base.required ? base : Object.freeze({
|
|
470
|
+
...base,
|
|
471
|
+
required
|
|
472
|
+
}), [base, required]);
|
|
473
|
+
const ui = useMemo(() => Object.freeze({
|
|
474
|
+
...sourceAtEdge.ui ?? EMPTY,
|
|
475
|
+
...placeholder === void 0 ? {} : { placeholder }
|
|
476
|
+
}), [sourceAtEdge, placeholder]);
|
|
477
|
+
const inputField = useMemo(() => ({
|
|
478
|
+
...field,
|
|
479
|
+
ui
|
|
480
|
+
}), [field, ui]);
|
|
481
|
+
const resolved = useFieldImplementation({
|
|
482
|
+
field: inputField,
|
|
483
|
+
surface: "input"
|
|
484
|
+
});
|
|
485
|
+
const runtimeContext = useFieldRuntimeContext(resource, record, form, metaSources);
|
|
486
|
+
const metaState = useFieldMeta(field, resolved.implementation, runtimeContext.metaSources, resolved.params);
|
|
487
|
+
const options = useContextOptions(field, name, metaState.status === "ready" ? metaState.meta : void 0, ui, resource);
|
|
488
|
+
const texts = useContextTexts(field, name, resolved, resource);
|
|
489
|
+
useFieldMetaDiagnostic(metaState, resource, name, inputField, "input");
|
|
490
|
+
useFieldImplementationDiagnostic(resolved.diagnostic);
|
|
491
|
+
if (resolved.Component === void 0) return jsx(Fragment$1, { children: fallback });
|
|
492
|
+
if (metaState.status !== "ready") return jsx(MetaPlaceholder, { state: metaState });
|
|
493
|
+
const Component = resolved.Component;
|
|
494
|
+
const issues = suppliedIssues ?? (errorMessage == null ? EMPTY_ISSUES : Object.freeze([Object.freeze({
|
|
495
|
+
code: "ui.field-error",
|
|
496
|
+
message: {
|
|
497
|
+
key: "ui.field-error",
|
|
498
|
+
default: errorMessage
|
|
499
|
+
},
|
|
500
|
+
path: Object.freeze([]),
|
|
501
|
+
source: "field",
|
|
502
|
+
severity: "error"
|
|
503
|
+
})]));
|
|
504
|
+
const context = {
|
|
505
|
+
owner: resource,
|
|
506
|
+
resource,
|
|
507
|
+
field,
|
|
508
|
+
path: Object.freeze([name]),
|
|
509
|
+
...absentPaths === void 0 || absentPaths.length === 0 ? {} : { absentPaths },
|
|
510
|
+
...pathStatus === void 0 ? {} : { pathStatus },
|
|
511
|
+
surface: "input",
|
|
512
|
+
presentation: "default",
|
|
513
|
+
record,
|
|
514
|
+
form,
|
|
515
|
+
meta: metaState.meta,
|
|
516
|
+
ui,
|
|
517
|
+
options,
|
|
518
|
+
texts,
|
|
519
|
+
i18n: runtimeContext.i18n,
|
|
520
|
+
sources: runtimeContext.sources,
|
|
521
|
+
pending,
|
|
522
|
+
touched,
|
|
523
|
+
issues,
|
|
524
|
+
accessibility: Object.freeze({
|
|
525
|
+
input: inputId ?? name,
|
|
526
|
+
label: labelId,
|
|
527
|
+
description: descriptionId,
|
|
528
|
+
error: errorId
|
|
529
|
+
}),
|
|
530
|
+
testIds: testId === void 0 ? EMPTY : Object.freeze({ input: testId })
|
|
531
|
+
};
|
|
532
|
+
if (resolved.multiple) return createElement(Component, {
|
|
533
|
+
...context,
|
|
534
|
+
multiple: true,
|
|
535
|
+
value: Array.isArray(value) ? value : [],
|
|
536
|
+
onChange,
|
|
537
|
+
onBlur,
|
|
538
|
+
disabled,
|
|
539
|
+
relationSeeds,
|
|
540
|
+
fixedFilters,
|
|
541
|
+
optionSubtitle,
|
|
542
|
+
link,
|
|
543
|
+
metaSources: runtimeContext.metaSources,
|
|
544
|
+
...baseline === void 0 ? {} : { baseline }
|
|
545
|
+
});
|
|
546
|
+
return createElement(Component, {
|
|
547
|
+
...context,
|
|
548
|
+
multiple: false,
|
|
549
|
+
value,
|
|
550
|
+
onChange,
|
|
551
|
+
onBlur,
|
|
552
|
+
disabled,
|
|
553
|
+
relationSeeds,
|
|
554
|
+
fixedFilters,
|
|
555
|
+
optionSubtitle,
|
|
556
|
+
link,
|
|
557
|
+
metaSources: runtimeContext.metaSources,
|
|
558
|
+
...baseline === void 0 ? {} : { baseline }
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
//#endregion
|
|
30
562
|
//#region src/primitives/badge.tsx
|
|
31
563
|
const badgeVariants = cva("inline-flex max-w-full items-center truncate rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2", {
|
|
32
564
|
variants: { variant: {
|
|
@@ -104,11 +636,11 @@ const SelectGroup = SelectPrimitive.Group;
|
|
|
104
636
|
const SelectValue = SelectPrimitive.Value;
|
|
105
637
|
const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => jsxs(SelectPrimitive.Trigger, {
|
|
106
638
|
ref,
|
|
107
|
-
className: cn("flex h-9 w-full items-center justify-between rounded-md border border-input bg-background text-foreground px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-input-disabled [&>span]:
|
|
639
|
+
className: cn("flex h-9 w-full items-center justify-between rounded-md border border-input bg-background text-foreground px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-input-disabled [&>span]:block [&>span]:truncate [&>span]:min-w-0 [&>span]:max-h-[1lh] [&>span]:overflow-hidden [&>span]:text-left", className),
|
|
108
640
|
...props,
|
|
109
641
|
children: [children, jsx(SelectPrimitive.Icon, {
|
|
110
642
|
asChild: true,
|
|
111
|
-
children: jsx(IconChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
643
|
+
children: jsx(IconChevronDown, { className: "h-4 w-4 shrink-0 opacity-50" })
|
|
112
644
|
})]
|
|
113
645
|
}));
|
|
114
646
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
@@ -147,15 +679,24 @@ const SelectLabel = React.forwardRef(({ className, ...props }, ref) => jsx(Selec
|
|
|
147
679
|
...props
|
|
148
680
|
}));
|
|
149
681
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
150
|
-
const SelectItem = React.forwardRef(({ className, children, ...props }, ref) =>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
children: jsx(
|
|
157
|
-
|
|
158
|
-
}))
|
|
682
|
+
const SelectItem = React.forwardRef(({ className, children, description, ...props }, ref) => {
|
|
683
|
+
const hasDescription = description !== void 0 && description !== null;
|
|
684
|
+
return jsxs(SelectPrimitive.Item, {
|
|
685
|
+
ref,
|
|
686
|
+
className: cn("relative flex w-full cursor-default select-none rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", hasDescription ? "items-start" : "items-center", className),
|
|
687
|
+
...props,
|
|
688
|
+
children: [jsx("span", {
|
|
689
|
+
className: cn("absolute left-2 flex h-3.5 w-3.5 items-center justify-center", hasDescription && "top-[9px]"),
|
|
690
|
+
children: jsx(SelectPrimitive.ItemIndicator, { children: jsx(IconCheck, { className: "h-4 w-4" }) })
|
|
691
|
+
}), !hasDescription ? jsx(SelectPrimitive.ItemText, { children }) : jsxs("span", {
|
|
692
|
+
className: "flex min-w-0 flex-col gap-0.5",
|
|
693
|
+
children: [jsx(SelectPrimitive.ItemText, { children }), jsx("span", {
|
|
694
|
+
className: "text-xs leading-snug text-muted-foreground",
|
|
695
|
+
children: description
|
|
696
|
+
})]
|
|
697
|
+
})]
|
|
698
|
+
});
|
|
699
|
+
});
|
|
159
700
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
160
701
|
const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => jsx(SelectPrimitive.Separator, {
|
|
161
702
|
ref,
|
|
@@ -168,8 +709,6 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
|
168
709
|
function localeTag(locale) {
|
|
169
710
|
return locale || loadLocale() || "en-US";
|
|
170
711
|
}
|
|
171
|
-
const dateCache = new Map();
|
|
172
|
-
const dateTimeCache = new Map();
|
|
173
712
|
const numberCache = new Map();
|
|
174
713
|
function cached(cache, key, make) {
|
|
175
714
|
const hit = cache.get(key);
|
|
@@ -183,24 +722,6 @@ function cached(cache, key, make) {
|
|
|
183
722
|
cache.set(key, made);
|
|
184
723
|
return made;
|
|
185
724
|
}
|
|
186
|
-
function formatDate(d, locale) {
|
|
187
|
-
const tag = localeTag(locale);
|
|
188
|
-
return cached(dateCache, tag, (t) => new Intl.DateTimeFormat(t, {
|
|
189
|
-
year: "numeric",
|
|
190
|
-
month: "short",
|
|
191
|
-
day: "numeric"
|
|
192
|
-
})).format(d);
|
|
193
|
-
}
|
|
194
|
-
function formatDateTime(d, locale) {
|
|
195
|
-
const tag = localeTag(locale);
|
|
196
|
-
return cached(dateTimeCache, tag, (t) => new Intl.DateTimeFormat(t, {
|
|
197
|
-
year: "numeric",
|
|
198
|
-
month: "short",
|
|
199
|
-
day: "numeric",
|
|
200
|
-
hour: "2-digit",
|
|
201
|
-
minute: "2-digit"
|
|
202
|
-
})).format(d);
|
|
203
|
-
}
|
|
204
725
|
function formatNumber(n, locale) {
|
|
205
726
|
const tag = localeTag(locale);
|
|
206
727
|
return cached(numberCache, tag, (t) => new Intl.NumberFormat(t)).format(n);
|
|
@@ -208,31 +729,31 @@ function formatNumber(n, locale) {
|
|
|
208
729
|
//#endregion
|
|
209
730
|
//#region src/list-kit/filter-builder/describe-row.ts
|
|
210
731
|
const MAX_DESCRIBE_DEPTH = 2;
|
|
211
|
-
function describeValue(value,
|
|
732
|
+
function describeValue(value, chromeT, spec, formatValue) {
|
|
212
733
|
if (value === void 0) return null;
|
|
213
|
-
if (Array.isArray(value)) return
|
|
734
|
+
if (Array.isArray(value)) return chromeT("filters.selectedCount", { count: value.length }, `${value.length} selected`);
|
|
214
735
|
const optionLabel = spec?.options?.find((o) => o.value === String(value))?.label;
|
|
215
736
|
if (optionLabel !== void 0) return optionLabel;
|
|
216
737
|
if (spec && formatValue) {
|
|
217
|
-
const formatted = formatValue(spec.kind, value);
|
|
738
|
+
const formatted = formatValue(spec.kind, value, spec.zone);
|
|
218
739
|
if (formatted !== void 0) return formatted;
|
|
219
740
|
}
|
|
220
741
|
return String(value);
|
|
221
742
|
}
|
|
222
|
-
function describeAt(row, available,
|
|
743
|
+
function describeAt(row, available, chromeT, depth, formatValue) {
|
|
223
744
|
if (isFilterGroup(row)) {
|
|
224
745
|
if (depth > MAX_DESCRIBE_DEPTH) return "…";
|
|
225
|
-
const joinLabel =
|
|
226
|
-
return `(${row.rows.map((child) => describeAt(child, available,
|
|
746
|
+
const joinLabel = chromeT(`filters.${row.join}`, void 0, row.join);
|
|
747
|
+
return `(${row.rows.map((child) => describeAt(child, available, chromeT, depth + 1, formatValue)).join(` ${joinLabel} `)})`;
|
|
227
748
|
}
|
|
228
749
|
const spec = available.find((s) => s.field === row.field);
|
|
229
750
|
const label = spec?.label ?? row.field;
|
|
230
|
-
const opLabel =
|
|
231
|
-
const valueText = opArity(row.op) === "none" ? null : describeValue(row.value,
|
|
751
|
+
const opLabel = chromeT(`filters.operators.${row.op}`, void 0, row.op);
|
|
752
|
+
const valueText = opArity(row.op) === "none" ? null : describeValue(row.value, chromeT, spec, formatValue);
|
|
232
753
|
return valueText === null ? `${label} ${opLabel}` : `${label} ${opLabel} ${valueText}`;
|
|
233
754
|
}
|
|
234
|
-
function describeRow(row, available,
|
|
235
|
-
return describeAt(row, available,
|
|
755
|
+
function describeRow(row, available, chromeT, formatValue) {
|
|
756
|
+
return describeAt(row, available, chromeT, 1, formatValue);
|
|
236
757
|
}
|
|
237
758
|
function relationLabelKey(to, by, value) {
|
|
238
759
|
return `${by === void 0 ? to : `${to}#${by}`}::${value}`;
|
|
@@ -365,23 +886,33 @@ function badgeKey(row, index) {
|
|
|
365
886
|
if (isFilterGroup(row)) return `${index}:group:${row.join}`;
|
|
366
887
|
return `${index}:${row.field}:${row.op}`;
|
|
367
888
|
}
|
|
889
|
+
const BADGE_ROW = "inline-flex max-w-full items-center gap-1 align-middle";
|
|
890
|
+
const REMOVE_BUTTON = "inline-flex size-4 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:bg-foreground/10 hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring";
|
|
368
891
|
function FilterBadges(props) {
|
|
369
892
|
const { group, setGroup, available, fixed, testIdBase, onOpenAt, onRemoved, pinnedFields = [], pinnedValue = [], setPinnedValue } = props;
|
|
370
|
-
const
|
|
371
|
-
const
|
|
893
|
+
const chromeT = useChromeT();
|
|
894
|
+
const locale = useOptionalLocale();
|
|
895
|
+
const viewer = useTimeZone();
|
|
896
|
+
const timeContext = useTimeContext();
|
|
897
|
+
const tt = (key, params, fallback) => chromeT(key, {
|
|
372
898
|
params,
|
|
373
899
|
...typeof params?.count === "number" ? { count: params.count } : {},
|
|
374
900
|
defaultValue: fallback
|
|
375
901
|
});
|
|
376
|
-
const removeLabel =
|
|
902
|
+
const removeLabel = chromeT("filters.removeRow", { defaultValue: "Remove filter" });
|
|
377
903
|
const { enumLabels, relationLabels, onEnumResolved, onRelationResolved } = useFormatValueMaps();
|
|
378
|
-
const formatValue = (kind, value) => {
|
|
904
|
+
const formatValue = (kind, value, fieldZone) => {
|
|
379
905
|
if (kind.kind === "enum") return enumLabels[kind.enumName]?.[String(value)];
|
|
380
906
|
if (kind.kind === "relation") return relationLabels[relationLabelKey(kind.to, kind.by, String(value))];
|
|
381
|
-
if (kind.kind === "date") {
|
|
382
|
-
const
|
|
383
|
-
if (
|
|
384
|
-
return kind.time ?
|
|
907
|
+
if (kind.kind === "date" && viewer.status === "ready") {
|
|
908
|
+
const zone = resolveTimeZone(timeContext.levels, fieldZone, timeContext.sources);
|
|
909
|
+
if (zone.status === "pending") return void 0;
|
|
910
|
+
return formatTimeValue(kind.time ? "dateTime" : "date", String(value), {
|
|
911
|
+
zone: zone.zone,
|
|
912
|
+
viewerZone: viewer.zone,
|
|
913
|
+
locale: localeTag(locale),
|
|
914
|
+
params: {}
|
|
915
|
+
});
|
|
385
916
|
}
|
|
386
917
|
};
|
|
387
918
|
const orphanPinned = useMemo(() => {
|
|
@@ -415,49 +946,56 @@ function FilterBadges(props) {
|
|
|
415
946
|
onEnumResolved,
|
|
416
947
|
onRelationResolved
|
|
417
948
|
}),
|
|
418
|
-
group.rows.map((row, index) =>
|
|
949
|
+
group.rows.map((row, index) => jsx(Badge, {
|
|
419
950
|
variant: "secondary",
|
|
420
|
-
className: "
|
|
421
|
-
children:
|
|
422
|
-
|
|
423
|
-
"
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
"
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
className:
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
951
|
+
className: "py-1 pr-1",
|
|
952
|
+
children: jsxs("span", {
|
|
953
|
+
className: BADGE_ROW,
|
|
954
|
+
children: [jsx("button", {
|
|
955
|
+
type: "button",
|
|
956
|
+
"data-testid": `${testIdBase}:badge:${index}`,
|
|
957
|
+
onClick: () => onOpenAt([index]),
|
|
958
|
+
className: "min-w-0 cursor-pointer truncate bg-transparent p-0 text-left",
|
|
959
|
+
children: describeRow(row, available, tt, formatValue)
|
|
960
|
+
}), jsx("button", {
|
|
961
|
+
type: "button",
|
|
962
|
+
"data-testid": `${testIdBase}:badge:${index}:remove`,
|
|
963
|
+
"aria-label": removeLabel,
|
|
964
|
+
onClick: () => handleRemove(index),
|
|
965
|
+
className: REMOVE_BUTTON,
|
|
966
|
+
children: jsx(IconX, {
|
|
967
|
+
className: "size-3",
|
|
968
|
+
"aria-hidden": "true"
|
|
969
|
+
})
|
|
970
|
+
})]
|
|
971
|
+
})
|
|
438
972
|
}, badgeKey(row, index))),
|
|
439
973
|
labelledFixed.map((entry, index) => jsx(Badge, {
|
|
440
974
|
variant: "outline",
|
|
441
975
|
"data-testid": `${testIdBase}:badge:fixed:${index}`,
|
|
442
976
|
children: entry.label
|
|
443
977
|
}, `fixed-${index}`)),
|
|
444
|
-
orphanPinned.map(({ expr, index }) =>
|
|
978
|
+
orphanPinned.map(({ expr, index }) => jsx(Badge, {
|
|
445
979
|
variant: "secondary",
|
|
446
|
-
className: "
|
|
447
|
-
children:
|
|
448
|
-
|
|
449
|
-
children:
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
"
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
980
|
+
className: "py-1 pr-1",
|
|
981
|
+
children: jsxs("span", {
|
|
982
|
+
className: BADGE_ROW,
|
|
983
|
+
children: [jsx("span", {
|
|
984
|
+
"data-testid": `${testIdBase}:badge:pinned:${index}`,
|
|
985
|
+
className: "min-w-0 truncate",
|
|
986
|
+
children: describeRow(expr, available, tt, formatValue)
|
|
987
|
+
}), jsx("button", {
|
|
988
|
+
type: "button",
|
|
989
|
+
"data-testid": `${testIdBase}:badge:pinned:${index}:remove`,
|
|
990
|
+
"aria-label": removeLabel,
|
|
991
|
+
onClick: () => handleRemovePinned(index),
|
|
992
|
+
className: REMOVE_BUTTON,
|
|
993
|
+
children: jsx(IconX, {
|
|
994
|
+
className: "size-3",
|
|
995
|
+
"aria-hidden": "true"
|
|
996
|
+
})
|
|
997
|
+
})]
|
|
998
|
+
})
|
|
461
999
|
}, `pinned-${index}`))
|
|
462
1000
|
]
|
|
463
1001
|
});
|
|
@@ -647,14 +1185,15 @@ const OPTIONS = ["true", "false"];
|
|
|
647
1185
|
function BooleanValueControl(props) {
|
|
648
1186
|
const { value, onChange, testId, arity, autoFocus, fieldLabel, fill } = props;
|
|
649
1187
|
const t = useOptionalT();
|
|
650
|
-
const
|
|
1188
|
+
const chromeT = useChromeT();
|
|
1189
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
651
1190
|
defaultValue: `Value for ${fieldLabel}`,
|
|
652
1191
|
params: { field: fieldLabel }
|
|
653
|
-
}) :
|
|
1192
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
654
1193
|
const yesLabel = t("boolean.yes", { defaultValue: "Yes" });
|
|
655
1194
|
const noLabel = t("boolean.no", { defaultValue: "No" });
|
|
656
1195
|
const labelOf = (token) => token === "true" ? yesLabel : noLabel;
|
|
657
|
-
const clearLabel =
|
|
1196
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
658
1197
|
const { open, setOpen, selected, select, triggerLabel, clear } = useSelectableValueControl({
|
|
659
1198
|
value,
|
|
660
1199
|
arity,
|
|
@@ -674,7 +1213,7 @@ function BooleanValueControl(props) {
|
|
|
674
1213
|
"data-testid": testId,
|
|
675
1214
|
"aria-label": ariaLabel,
|
|
676
1215
|
className: cn("h-8 justify-between", fill && "w-full"),
|
|
677
|
-
children: triggerLabel(labelOf, ariaLabel)
|
|
1216
|
+
children: triggerLabel(labelOf, props.placeholder ?? ariaLabel)
|
|
678
1217
|
})
|
|
679
1218
|
}), jsx(PopoverContent, {
|
|
680
1219
|
className: "w-[140px] p-0",
|
|
@@ -707,12 +1246,13 @@ function BooleanValueControl(props) {
|
|
|
707
1246
|
function SelectListValueControl(props) {
|
|
708
1247
|
const { options, value, onChange, testId, arity, autoFocus, fieldLabel, isLoading = false } = props;
|
|
709
1248
|
const t = useOptionalT();
|
|
710
|
-
const
|
|
1249
|
+
const chromeT = useChromeT();
|
|
1250
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
711
1251
|
defaultValue: `Value for ${fieldLabel}`,
|
|
712
1252
|
params: { field: fieldLabel }
|
|
713
|
-
}) :
|
|
1253
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
714
1254
|
const loadingLabel = t("table.loading", { defaultValue: "Loading…" });
|
|
715
|
-
const clearLabel =
|
|
1255
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
716
1256
|
const labelFor = props.labelFor ?? ((raw) => options.find((o) => o.value === raw)?.label ?? raw);
|
|
717
1257
|
const { open, setOpen, selected, select, triggerLabel, clear } = useSelectableValueControl({
|
|
718
1258
|
value,
|
|
@@ -734,7 +1274,7 @@ function SelectListValueControl(props) {
|
|
|
734
1274
|
className: cn("h-8 justify-between truncate", props.fill ? "w-full" : "max-w-[200px]"),
|
|
735
1275
|
children: jsx("span", {
|
|
736
1276
|
className: "truncate",
|
|
737
|
-
children: isLoading ? loadingLabel : triggerLabel(labelFor, ariaLabel)
|
|
1277
|
+
children: isLoading ? loadingLabel : triggerLabel(labelFor, props.placeholder ?? ariaLabel)
|
|
738
1278
|
})
|
|
739
1279
|
})
|
|
740
1280
|
}), jsx(PopoverContent, {
|
|
@@ -797,6 +1337,7 @@ function EnumValueControl(props) {
|
|
|
797
1337
|
arity,
|
|
798
1338
|
autoFocus,
|
|
799
1339
|
fieldLabel,
|
|
1340
|
+
placeholder: props.placeholder,
|
|
800
1341
|
options,
|
|
801
1342
|
labelFor,
|
|
802
1343
|
isLoading,
|
|
@@ -843,6 +1384,7 @@ function RelationValueControl(props) {
|
|
|
843
1384
|
const { to, by, value, onChange, testId, arity, autoFocus, fieldLabel } = props;
|
|
844
1385
|
const app = useApp();
|
|
845
1386
|
const t = useOptionalT();
|
|
1387
|
+
const chromeT = useChromeT();
|
|
846
1388
|
const targetDef = app.registry.get(to);
|
|
847
1389
|
const displayField = targetDef?.displayField ?? "name";
|
|
848
1390
|
const [search, setSearch] = useState("");
|
|
@@ -881,11 +1423,11 @@ function RelationValueControl(props) {
|
|
|
881
1423
|
if (fromRows) return rowTitle(fromRows);
|
|
882
1424
|
return fallbackLabels[id] ?? id;
|
|
883
1425
|
};
|
|
884
|
-
const ariaLabel = fieldLabel ?
|
|
1426
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
885
1427
|
defaultValue: `Value for ${fieldLabel}`,
|
|
886
1428
|
params: { field: fieldLabel }
|
|
887
|
-
}) :
|
|
888
|
-
const clearLabel =
|
|
1429
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
1430
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
889
1431
|
return jsxs(Popover, {
|
|
890
1432
|
open,
|
|
891
1433
|
onOpenChange: setOpen,
|
|
@@ -901,7 +1443,7 @@ function RelationValueControl(props) {
|
|
|
901
1443
|
className: cn("h-8 justify-between truncate", props.fill ? "w-full" : "max-w-[220px]"),
|
|
902
1444
|
children: jsx("span", {
|
|
903
1445
|
className: "truncate",
|
|
904
|
-
children: triggerLabel(labelFor, ariaLabel)
|
|
1446
|
+
children: triggerLabel(labelFor, props.placeholder ?? ariaLabel)
|
|
905
1447
|
})
|
|
906
1448
|
})
|
|
907
1449
|
}), jsx(PopoverContent, {
|
|
@@ -957,7 +1499,56 @@ function RelationValueControl(props) {
|
|
|
957
1499
|
});
|
|
958
1500
|
}
|
|
959
1501
|
//#endregion
|
|
1502
|
+
//#region src/fields/field-time-zone.ts
|
|
1503
|
+
function useFieldTimeZone(zone, row) {
|
|
1504
|
+
const { sources: session } = useTimeContext();
|
|
1505
|
+
const sources = useMemo(() => row === void 0 ? session : {
|
|
1506
|
+
...session,
|
|
1507
|
+
record: {
|
|
1508
|
+
status: "ready",
|
|
1509
|
+
value: row,
|
|
1510
|
+
refreshing: false
|
|
1511
|
+
}
|
|
1512
|
+
}, [session, row]);
|
|
1513
|
+
const fieldZone = useMemo(() => normaliseFieldZone(zone), [zone]);
|
|
1514
|
+
return useTimeZone(fieldZone, sources);
|
|
1515
|
+
}
|
|
1516
|
+
const DATE_KEYS = [
|
|
1517
|
+
"dateStyle",
|
|
1518
|
+
"timeStyle",
|
|
1519
|
+
"zoneName"
|
|
1520
|
+
];
|
|
1521
|
+
function dateDisplayParams(ui) {
|
|
1522
|
+
const display = ui?.display;
|
|
1523
|
+
if (display === null || typeof display !== "object") return {};
|
|
1524
|
+
const params = {};
|
|
1525
|
+
for (const key of DATE_KEYS) {
|
|
1526
|
+
const value = display[key];
|
|
1527
|
+
if (value !== void 0) params[key] = value;
|
|
1528
|
+
}
|
|
1529
|
+
return params;
|
|
1530
|
+
}
|
|
1531
|
+
//#endregion
|
|
1532
|
+
//#region src/fields/local-date-time.ts
|
|
1533
|
+
function toLocalDateTimeText(value, zone) {
|
|
1534
|
+
if (value === void 0 || value === null || value === "") return "";
|
|
1535
|
+
const instant = canonicalInstant(value instanceof Date ? value.toISOString() : String(value));
|
|
1536
|
+
if (instant === void 0) return "";
|
|
1537
|
+
const { date, time } = instantToWall(instant, zone);
|
|
1538
|
+
return `${date}T${time.slice(0, 5)}`;
|
|
1539
|
+
}
|
|
1540
|
+
function fromLocalDateTimeText(text, zone) {
|
|
1541
|
+
const [date, time, ...rest] = text.split("T");
|
|
1542
|
+
if (date === void 0 || time === void 0 || rest.length > 0) return void 0;
|
|
1543
|
+
if (!isCalendarDate(date) || !isWallTime(time)) return void 0;
|
|
1544
|
+
return wallToInstant(date, time, zone);
|
|
1545
|
+
}
|
|
1546
|
+
//#endregion
|
|
960
1547
|
//#region src/list-kit/filter-builder/values/scalar-value-input.tsx
|
|
1548
|
+
function useFilterZone(fieldZone) {
|
|
1549
|
+
const zone = useFieldTimeZone(fieldZone, void 0);
|
|
1550
|
+
return zone.status === "ready" ? zone.zone : "UTC";
|
|
1551
|
+
}
|
|
961
1552
|
function isDateTime(kind) {
|
|
962
1553
|
return kind.kind === "date" && kind.time === true;
|
|
963
1554
|
}
|
|
@@ -968,33 +1559,27 @@ function inputTypeFor(kind) {
|
|
|
968
1559
|
default: return "text";
|
|
969
1560
|
}
|
|
970
1561
|
}
|
|
971
|
-
function toText(kind, value) {
|
|
1562
|
+
function toText(kind, value, zone) {
|
|
1563
|
+
if (isDateTime(kind)) return toLocalDateTimeText(value, zone);
|
|
972
1564
|
if (value === void 0 || value === null || value === "") return "";
|
|
973
|
-
|
|
974
|
-
const d = new Date(String(value));
|
|
975
|
-
if (Number.isNaN(d.getTime())) return "";
|
|
976
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
977
|
-
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
1565
|
+
return String(value);
|
|
978
1566
|
}
|
|
979
|
-
function parseOne(kind, raw) {
|
|
1567
|
+
function parseOne(kind, raw, zone) {
|
|
980
1568
|
if (raw === "") return void 0;
|
|
981
1569
|
if (kind.kind === "number") {
|
|
982
1570
|
const n = Number(raw);
|
|
983
1571
|
return Number.isFinite(n) ? n : void 0;
|
|
984
1572
|
}
|
|
985
|
-
if (isDateTime(kind))
|
|
986
|
-
const d = new Date(raw);
|
|
987
|
-
return Number.isNaN(d.getTime()) ? void 0 : d.toISOString();
|
|
988
|
-
}
|
|
1573
|
+
if (isDateTime(kind)) return fromLocalDateTimeText(raw, zone);
|
|
989
1574
|
return raw;
|
|
990
1575
|
}
|
|
991
1576
|
function ScalarValueInput(props) {
|
|
992
|
-
const
|
|
1577
|
+
const chromeT = useChromeT();
|
|
993
1578
|
const inputType = inputTypeFor(props.kind);
|
|
994
|
-
const ariaLabel = props.fieldLabel ?
|
|
1579
|
+
const ariaLabel = props.fieldLabel ? chromeT("filters.valueFor", {
|
|
995
1580
|
defaultValue: `Value for ${props.fieldLabel}`,
|
|
996
1581
|
params: { field: props.fieldLabel }
|
|
997
|
-
}) :
|
|
1582
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
998
1583
|
if (props.arity === "multi") return jsx(ScalarMultiInput, {
|
|
999
1584
|
...props,
|
|
1000
1585
|
inputType,
|
|
@@ -1008,7 +1593,8 @@ function ScalarValueInput(props) {
|
|
|
1008
1593
|
}
|
|
1009
1594
|
function ScalarSingleInput(props) {
|
|
1010
1595
|
const { value, onChange, kind, testId, autoFocus, inputType, ariaLabel, debounceMs = 300 } = props;
|
|
1011
|
-
const
|
|
1596
|
+
const zone = useFilterZone(props.zone);
|
|
1597
|
+
const storedText = toText(kind, value, zone);
|
|
1012
1598
|
const [text, setText] = useState(storedText);
|
|
1013
1599
|
const lastPushedRef = useRef(storedText);
|
|
1014
1600
|
const timerRef = useRef(null);
|
|
@@ -1016,8 +1602,8 @@ function ScalarSingleInput(props) {
|
|
|
1016
1602
|
const commitRef = useRef(() => {});
|
|
1017
1603
|
useEffect(() => {
|
|
1018
1604
|
commitRef.current = (raw) => {
|
|
1019
|
-
const parsed = parseOne(kind, raw);
|
|
1020
|
-
lastPushedRef.current = toText(kind, parsed);
|
|
1605
|
+
const parsed = parseOne(kind, raw, zone);
|
|
1606
|
+
lastPushedRef.current = toText(kind, parsed, zone);
|
|
1021
1607
|
pendingRawRef.current = null;
|
|
1022
1608
|
onChange(parsed);
|
|
1023
1609
|
};
|
|
@@ -1066,8 +1652,9 @@ function ScalarMultiInput(props) {
|
|
|
1066
1652
|
const { value, onChange, kind, testId, autoFocus, inputType, ariaLabel } = props;
|
|
1067
1653
|
const chips = Array.isArray(value) ? value.map((v) => String(v)) : [];
|
|
1068
1654
|
const [draft, setDraft] = useState("");
|
|
1655
|
+
const zone = useFilterZone(props.zone);
|
|
1069
1656
|
const addChip = () => {
|
|
1070
|
-
const parsed = parseOne(kind, draft.trim());
|
|
1657
|
+
const parsed = parseOne(kind, draft.trim(), zone);
|
|
1071
1658
|
if (parsed === void 0) return;
|
|
1072
1659
|
const text = String(parsed);
|
|
1073
1660
|
setDraft("");
|
|
@@ -1124,6 +1711,7 @@ function FilterValueControl(props) {
|
|
|
1124
1711
|
arity,
|
|
1125
1712
|
autoFocus: props.autoFocus,
|
|
1126
1713
|
fieldLabel: props.fieldLabel,
|
|
1714
|
+
placeholder: props.placeholder,
|
|
1127
1715
|
options: props.options,
|
|
1128
1716
|
fill: props.fill
|
|
1129
1717
|
});
|
|
@@ -1140,6 +1728,7 @@ function FilterValueControl(props) {
|
|
|
1140
1728
|
arity,
|
|
1141
1729
|
autoFocus: props.autoFocus,
|
|
1142
1730
|
fieldLabel: props.fieldLabel,
|
|
1731
|
+
placeholder: props.placeholder,
|
|
1143
1732
|
options: props.kind.values.map((entry) => ({
|
|
1144
1733
|
value: entry,
|
|
1145
1734
|
label: entry
|
|
@@ -1168,10 +1757,10 @@ const FIELD_CLASS = "h-8 min-w-0 shrink basis-40";
|
|
|
1168
1757
|
const OPERATOR_CLASS = "h-8 min-w-0 shrink basis-[9.5rem]";
|
|
1169
1758
|
function FilterRow(props) {
|
|
1170
1759
|
const { row, path, available, onPatch, onRemove, testIdBase, debounceMs } = props;
|
|
1171
|
-
const
|
|
1760
|
+
const chromeT = useChromeT();
|
|
1172
1761
|
const base = `${testIdBase}:row:${path.join("-")}`;
|
|
1173
1762
|
const spec = available.find((s) => s.field === row.field);
|
|
1174
|
-
const removeLabel =
|
|
1763
|
+
const removeLabel = chromeT("filters.removeRow", { defaultValue: "Remove filter" });
|
|
1175
1764
|
if (!spec) return jsxs("div", {
|
|
1176
1765
|
className: ROW_CLASS,
|
|
1177
1766
|
children: [
|
|
@@ -1211,8 +1800,8 @@ function FilterRow(props) {
|
|
|
1211
1800
|
};
|
|
1212
1801
|
const handleOpChange = (op) => onPatch(path, { op });
|
|
1213
1802
|
const handleValueChange = (value) => onPatch(path, { value });
|
|
1214
|
-
const fieldAriaLabel =
|
|
1215
|
-
const operatorAriaLabel =
|
|
1803
|
+
const fieldAriaLabel = chromeT("filters.field", { defaultValue: "Field" });
|
|
1804
|
+
const operatorAriaLabel = chromeT("filters.operator", { defaultValue: "Operator" });
|
|
1216
1805
|
return jsxs("div", {
|
|
1217
1806
|
className: ROW_CLASS,
|
|
1218
1807
|
children: [
|
|
@@ -1241,7 +1830,7 @@ function FilterRow(props) {
|
|
|
1241
1830
|
}), jsx(SelectContent, { children: spec.operators.map((op) => jsx(SelectItem, {
|
|
1242
1831
|
value: op,
|
|
1243
1832
|
"data-testid": `${opTestId}:option:${op}`,
|
|
1244
|
-
children:
|
|
1833
|
+
children: chromeT(`filters.operators.${op}`, { defaultValue: op })
|
|
1245
1834
|
}, op)) })]
|
|
1246
1835
|
}),
|
|
1247
1836
|
jsx("div", {
|
|
@@ -1255,6 +1844,7 @@ function FilterRow(props) {
|
|
|
1255
1844
|
debounceMs,
|
|
1256
1845
|
fieldLabel: spec.label,
|
|
1257
1846
|
options: spec.options,
|
|
1847
|
+
...spec.zone === void 0 ? {} : { zone: spec.zone },
|
|
1258
1848
|
fill: true
|
|
1259
1849
|
})
|
|
1260
1850
|
}),
|
|
@@ -1289,10 +1879,10 @@ function FilterGroupEditor(props) {
|
|
|
1289
1879
|
}
|
|
1290
1880
|
function GroupEditorInner(props) {
|
|
1291
1881
|
const { group, path, available, onChange, testIdBase, onRemove, addGroupAt, debounceMs } = props;
|
|
1292
|
-
const
|
|
1882
|
+
const chromeT = useChromeT();
|
|
1293
1883
|
const base = `${testIdBase}:group:${path.join("-")}`;
|
|
1294
1884
|
const canNestGroup = depthOf(path) < 3;
|
|
1295
|
-
const joinLabel = (join) =>
|
|
1885
|
+
const joinLabel = (join) => chromeT(`filters.${join}`, { defaultValue: join });
|
|
1296
1886
|
const handlePatch = (rowPath, patch) => {
|
|
1297
1887
|
const index = rowPath[rowPath.length - 1];
|
|
1298
1888
|
if (index === void 0) return;
|
|
@@ -1325,11 +1915,11 @@ function GroupEditorInner(props) {
|
|
|
1325
1915
|
return jsxs(Fragment, { children: [jsxs("div", {
|
|
1326
1916
|
className: CONNECTOR_CLASS,
|
|
1327
1917
|
children: [
|
|
1328
|
-
index === 0 &&
|
|
1918
|
+
index === 0 && chromeT("filters.where", { defaultValue: "Where" }),
|
|
1329
1919
|
index === 1 && jsx("button", {
|
|
1330
1920
|
type: "button",
|
|
1331
1921
|
"data-testid": `${base}:join`,
|
|
1332
|
-
"aria-label":
|
|
1922
|
+
"aria-label": chromeT("filters.toggleJoin", {
|
|
1333
1923
|
defaultValue: `Join: ${joinLabel(group.join)} — activate to switch to ${joinLabel(otherJoin)}`,
|
|
1334
1924
|
params: {
|
|
1335
1925
|
current: joinLabel(group.join),
|
|
@@ -1381,7 +1971,7 @@ function GroupEditorInner(props) {
|
|
|
1381
1971
|
children: [jsx(IconPlus, {
|
|
1382
1972
|
className: "h-4 w-4",
|
|
1383
1973
|
"aria-hidden": "true"
|
|
1384
|
-
}),
|
|
1974
|
+
}), chromeT("filters.addRow", { defaultValue: "Add filter" })]
|
|
1385
1975
|
}),
|
|
1386
1976
|
canNestGroup && jsxs(Button, {
|
|
1387
1977
|
type: "button",
|
|
@@ -1392,7 +1982,7 @@ function GroupEditorInner(props) {
|
|
|
1392
1982
|
children: [jsx(IconFolderPlus, {
|
|
1393
1983
|
className: "h-4 w-4",
|
|
1394
1984
|
"aria-hidden": "true"
|
|
1395
|
-
}),
|
|
1985
|
+
}), chromeT("filters.addGroup", { defaultValue: "Add group" })]
|
|
1396
1986
|
}),
|
|
1397
1987
|
onRemove && jsxs(Button, {
|
|
1398
1988
|
type: "button",
|
|
@@ -1403,7 +1993,7 @@ function GroupEditorInner(props) {
|
|
|
1403
1993
|
children: [jsx(IconX, {
|
|
1404
1994
|
className: "h-4 w-4",
|
|
1405
1995
|
"aria-hidden": "true"
|
|
1406
|
-
}),
|
|
1996
|
+
}), chromeT("filters.removeGroup", { defaultValue: "Remove group" })]
|
|
1407
1997
|
})
|
|
1408
1998
|
]
|
|
1409
1999
|
})
|
|
@@ -1419,7 +2009,7 @@ function countGroupRows(group) {
|
|
|
1419
2009
|
}
|
|
1420
2010
|
function FilterPanel(props) {
|
|
1421
2011
|
const { group, setGroup, available, setPage, testIdBase, open, onOpenChange, focusPath, externalRemoval } = props;
|
|
1422
|
-
const
|
|
2012
|
+
const chromeT = useChromeT();
|
|
1423
2013
|
const [draft, setDraft] = useState(() => toDraft(group));
|
|
1424
2014
|
const wasOpenRef = useRef(open);
|
|
1425
2015
|
const topLevelIdsRef = useRef([]);
|
|
@@ -1471,7 +2061,7 @@ function FilterPanel(props) {
|
|
|
1471
2061
|
className: "h-4 w-4",
|
|
1472
2062
|
"aria-hidden": "true"
|
|
1473
2063
|
}),
|
|
1474
|
-
|
|
2064
|
+
chromeT("filters.title", { defaultValue: "Filters" }),
|
|
1475
2065
|
appliedCount > 0 && jsx("span", {
|
|
1476
2066
|
"data-testid": `${testIdBase}:count`,
|
|
1477
2067
|
className: "ml-1 rounded-full bg-primary px-1.5 text-xs text-primary-foreground",
|
|
@@ -1499,13 +2089,13 @@ function FilterPanel(props) {
|
|
|
1499
2089
|
size: "sm",
|
|
1500
2090
|
"data-testid": `${testIdBase}:reset`,
|
|
1501
2091
|
onClick: handleReset,
|
|
1502
|
-
children:
|
|
2092
|
+
children: chromeT("filters.reset", { defaultValue: "Reset" })
|
|
1503
2093
|
}), jsx(Button, {
|
|
1504
2094
|
type: "button",
|
|
1505
2095
|
size: "sm",
|
|
1506
2096
|
"data-testid": `${testIdBase}:apply`,
|
|
1507
2097
|
onClick: handleApply,
|
|
1508
|
-
children:
|
|
2098
|
+
children: chromeT("filters.apply", { defaultValue: "Apply" })
|
|
1509
2099
|
})]
|
|
1510
2100
|
})]
|
|
1511
2101
|
})]
|
|
@@ -1556,15 +2146,209 @@ function PinnedControl(props) {
|
|
|
1556
2146
|
testId: `${testIdBase}:pinned:${spec.field}`,
|
|
1557
2147
|
fieldLabel: spec.label,
|
|
1558
2148
|
placeholder: spec.label,
|
|
1559
|
-
options: spec.options
|
|
2149
|
+
options: spec.options,
|
|
2150
|
+
...spec.zone === void 0 ? {} : { zone: spec.zone }
|
|
1560
2151
|
});
|
|
1561
2152
|
}
|
|
1562
2153
|
//#endregion
|
|
2154
|
+
//#region src/data-table/data-table-faceted-filter.tsx
|
|
2155
|
+
function DataTableFacetedFilter({ column, getTestId, ...rest }) {
|
|
2156
|
+
const filterValue = column.getFilterValue();
|
|
2157
|
+
return jsx(FacetedFilterPicker, {
|
|
2158
|
+
...rest,
|
|
2159
|
+
...getTestId === void 0 ? {} : { getTestId: (role, value) => role === "hint" ? void 0 : getTestId(role, value) },
|
|
2160
|
+
selected: Array.isArray(filterValue) ? filterValue.map(String) : [],
|
|
2161
|
+
onChange: (next) => column.setFilterValue(next.length === 0 ? void 0 : next)
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
function FacetedFilterPicker({ title, options = [], loadOptions, selectedLabelFor, searchPlaceholder, emptyText, getTestId, className, selected: selectedList, onChange, hint, emptyLabel, clearable = true }) {
|
|
2165
|
+
const t = useOptionalT();
|
|
2166
|
+
const chromeT = useChromeT();
|
|
2167
|
+
const selected = useMemo(() => new Set(selectedList), [selectedList]);
|
|
2168
|
+
const [search, setSearch] = useState("");
|
|
2169
|
+
const [asyncOptions, setAsyncOptions] = useState([]);
|
|
2170
|
+
const [loading, setLoading] = useState(false);
|
|
2171
|
+
const debounceRef = useRef(null);
|
|
2172
|
+
const loadOptionsRef = useRef(loadOptions);
|
|
2173
|
+
useEffect(() => {
|
|
2174
|
+
loadOptionsRef.current = loadOptions;
|
|
2175
|
+
});
|
|
2176
|
+
useEffect(() => {
|
|
2177
|
+
if (!loadOptionsRef.current) return;
|
|
2178
|
+
setLoading(true);
|
|
2179
|
+
if (debounceRef.current !== null) clearTimeout(debounceRef.current);
|
|
2180
|
+
let cancelled = false;
|
|
2181
|
+
debounceRef.current = setTimeout(() => {
|
|
2182
|
+
const loader = loadOptionsRef.current;
|
|
2183
|
+
if (!loader) return;
|
|
2184
|
+
loader(search).then((results) => {
|
|
2185
|
+
if (!cancelled) {
|
|
2186
|
+
setAsyncOptions(results);
|
|
2187
|
+
setLoading(false);
|
|
2188
|
+
}
|
|
2189
|
+
}).catch(() => {
|
|
2190
|
+
if (!cancelled) setLoading(false);
|
|
2191
|
+
});
|
|
2192
|
+
}, 250);
|
|
2193
|
+
return () => {
|
|
2194
|
+
cancelled = true;
|
|
2195
|
+
if (debounceRef.current !== null) clearTimeout(debounceRef.current);
|
|
2196
|
+
};
|
|
2197
|
+
}, [search]);
|
|
2198
|
+
const effectiveOptions = loadOptions ? asyncOptions : options;
|
|
2199
|
+
const labelFor = (value) => {
|
|
2200
|
+
const opt = effectiveOptions.find((o) => o.value === value);
|
|
2201
|
+
if (opt) return opt.label;
|
|
2202
|
+
return selectedLabelFor?.(value) ?? value;
|
|
2203
|
+
};
|
|
2204
|
+
const toggle = (value) => {
|
|
2205
|
+
const next = new Set(selected);
|
|
2206
|
+
if (next.has(value)) next.delete(value);
|
|
2207
|
+
else next.add(value);
|
|
2208
|
+
onChange(Array.from(next));
|
|
2209
|
+
};
|
|
2210
|
+
const selectedValues = Array.from(selected);
|
|
2211
|
+
return jsxs(Popover, { children: [jsx(PopoverTrigger, {
|
|
2212
|
+
asChild: true,
|
|
2213
|
+
children: jsxs(Button, {
|
|
2214
|
+
type: "button",
|
|
2215
|
+
variant: "outline",
|
|
2216
|
+
size: "sm",
|
|
2217
|
+
"data-testid": getTestId?.("trigger"),
|
|
2218
|
+
title: hint,
|
|
2219
|
+
className: cn("h-8 border-dashed", className),
|
|
2220
|
+
children: [
|
|
2221
|
+
jsx(IconCirclePlus, {
|
|
2222
|
+
className: "mr-2 h-4 w-4",
|
|
2223
|
+
"aria-hidden": "true"
|
|
2224
|
+
}),
|
|
2225
|
+
title,
|
|
2226
|
+
selected.size === 0 && emptyLabel !== void 0 && jsxs(Fragment$1, { children: [jsx("span", {
|
|
2227
|
+
className: "mx-2 h-4 w-px bg-border",
|
|
2228
|
+
"aria-hidden": "true"
|
|
2229
|
+
}), jsx(Badge, {
|
|
2230
|
+
variant: "secondary",
|
|
2231
|
+
className: "rounded-sm px-1 font-normal",
|
|
2232
|
+
children: emptyLabel
|
|
2233
|
+
})] }),
|
|
2234
|
+
selected.size > 0 && jsxs(Fragment$1, { children: [
|
|
2235
|
+
jsx("span", {
|
|
2236
|
+
className: "mx-2 h-4 w-px bg-border",
|
|
2237
|
+
"aria-hidden": "true"
|
|
2238
|
+
}),
|
|
2239
|
+
jsx(Badge, {
|
|
2240
|
+
variant: "secondary",
|
|
2241
|
+
className: "rounded-sm px-1 font-normal lg:hidden",
|
|
2242
|
+
children: selected.size
|
|
2243
|
+
}),
|
|
2244
|
+
jsx("div", {
|
|
2245
|
+
className: "hidden gap-1 lg:flex",
|
|
2246
|
+
children: selected.size > 2 ? jsx(Badge, {
|
|
2247
|
+
variant: "secondary",
|
|
2248
|
+
className: "rounded-sm px-1 font-normal",
|
|
2249
|
+
children: t("table.selectedCount", {
|
|
2250
|
+
count: selected.size,
|
|
2251
|
+
defaultValue: "{{count}} selected"
|
|
2252
|
+
})
|
|
2253
|
+
}) : selectedValues.map((value) => jsx(Badge, {
|
|
2254
|
+
variant: "secondary",
|
|
2255
|
+
className: "rounded-sm px-1 font-normal",
|
|
2256
|
+
children: labelFor(value)
|
|
2257
|
+
}, value))
|
|
2258
|
+
})
|
|
2259
|
+
] })
|
|
2260
|
+
]
|
|
2261
|
+
})
|
|
2262
|
+
}), jsx(PopoverContent, {
|
|
2263
|
+
className: "w-[220px] p-0",
|
|
2264
|
+
align: "start",
|
|
2265
|
+
children: jsxs(Command, {
|
|
2266
|
+
shouldFilter: !loadOptions,
|
|
2267
|
+
children: [
|
|
2268
|
+
hint !== void 0 && jsx("p", {
|
|
2269
|
+
"data-testid": getTestId?.("hint"),
|
|
2270
|
+
className: "border-b px-3 py-2 text-xs text-muted-foreground",
|
|
2271
|
+
children: hint
|
|
2272
|
+
}),
|
|
2273
|
+
jsx(CommandInput, {
|
|
2274
|
+
placeholder: searchPlaceholder ?? title,
|
|
2275
|
+
"data-testid": getTestId?.("search"),
|
|
2276
|
+
...loadOptions ? {
|
|
2277
|
+
value: search,
|
|
2278
|
+
onValueChange: setSearch
|
|
2279
|
+
} : {}
|
|
2280
|
+
}),
|
|
2281
|
+
jsxs(CommandList, { children: [
|
|
2282
|
+
loading && jsx("div", {
|
|
2283
|
+
className: "py-6 text-center text-sm text-muted-foreground",
|
|
2284
|
+
children: t("list.loadingShort", { defaultValue: "Loading…" })
|
|
2285
|
+
}),
|
|
2286
|
+
jsx(CommandEmpty, { children: emptyText ?? t("relation.noResults", { defaultValue: "No results." }) }),
|
|
2287
|
+
jsx(CommandGroup, { children: effectiveOptions.map((opt) => {
|
|
2288
|
+
const isSelected = selected.has(opt.value);
|
|
2289
|
+
const Icon = opt.icon;
|
|
2290
|
+
return jsxs(CommandItem, {
|
|
2291
|
+
value: opt.label,
|
|
2292
|
+
"data-testid": getTestId?.("option", opt.value),
|
|
2293
|
+
role: "option",
|
|
2294
|
+
"aria-selected": isSelected,
|
|
2295
|
+
"aria-checked": isSelected,
|
|
2296
|
+
onSelect: () => toggle(opt.value),
|
|
2297
|
+
children: [
|
|
2298
|
+
jsx("span", {
|
|
2299
|
+
className: cn("mr-2 flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border", isSelected ? "border-primary bg-primary text-primary-foreground" : "border-input opacity-50"),
|
|
2300
|
+
"aria-hidden": "true",
|
|
2301
|
+
children: isSelected && jsx(IconCheck, { className: "h-3.5 w-3.5" })
|
|
2302
|
+
}),
|
|
2303
|
+
Icon && jsx(Icon, {
|
|
2304
|
+
className: "mr-2 h-4 w-4 text-muted-foreground",
|
|
2305
|
+
"aria-hidden": "true"
|
|
2306
|
+
}),
|
|
2307
|
+
jsxs("span", {
|
|
2308
|
+
className: "flex min-w-0 flex-1 flex-col text-left",
|
|
2309
|
+
children: [jsx("span", { children: opt.label }), opt.summary !== void 0 && jsx("span", {
|
|
2310
|
+
className: "text-xs text-muted-foreground",
|
|
2311
|
+
children: opt.summary
|
|
2312
|
+
})]
|
|
2313
|
+
})
|
|
2314
|
+
]
|
|
2315
|
+
}, opt.value);
|
|
2316
|
+
}) })
|
|
2317
|
+
] }),
|
|
2318
|
+
clearable && selected.size > 0 && jsx("button", {
|
|
2319
|
+
type: "button",
|
|
2320
|
+
"data-testid": getTestId?.("clear"),
|
|
2321
|
+
onClick: () => onChange([]),
|
|
2322
|
+
className: "flex w-full items-center justify-center border-t px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground",
|
|
2323
|
+
children: chromeT("filters.clearAll", { defaultValue: "Clear filters" })
|
|
2324
|
+
})
|
|
2325
|
+
]
|
|
2326
|
+
})
|
|
2327
|
+
})] });
|
|
2328
|
+
}
|
|
2329
|
+
//#endregion
|
|
2330
|
+
//#region src/list-kit/filter-builder/preset-filter-controls.tsx
|
|
2331
|
+
function PresetFilterControls(props) {
|
|
2332
|
+
const { presets, setPreset, testIdBase } = props;
|
|
2333
|
+
return jsx(Fragment$1, { children: presets.map((filter) => jsx(FacetedFilterPicker, {
|
|
2334
|
+
title: filter.label,
|
|
2335
|
+
...filter.hint === void 0 ? {} : { hint: filter.hint },
|
|
2336
|
+
options: filter.options.map((option) => ({
|
|
2337
|
+
value: option.id,
|
|
2338
|
+
label: option.label,
|
|
2339
|
+
...option.summary === void 0 ? {} : { summary: option.summary }
|
|
2340
|
+
})),
|
|
2341
|
+
selected: filter.selected,
|
|
2342
|
+
onChange: (next) => setPreset(filter.id, filter.options.map((option) => option.id).filter((id) => next.includes(id))),
|
|
2343
|
+
getTestId: (role, value) => `${testIdBase}:preset:${filter.id}:${role}${value === void 0 ? "" : `:${value}`}`
|
|
2344
|
+
}, filter.id)) });
|
|
2345
|
+
}
|
|
2346
|
+
//#endregion
|
|
1563
2347
|
//#region src/list-kit/filter-builder/filter-builder.tsx
|
|
1564
2348
|
const EMPTY_PINNED_FIELDS = Object.freeze([]);
|
|
1565
2349
|
const EMPTY_PINNED_VALUE = Object.freeze([]);
|
|
1566
2350
|
function FilterBuilder(props) {
|
|
1567
|
-
const { group, setGroup, available, fixed, pinnedFields = EMPTY_PINNED_FIELDS, pinnedValue = EMPTY_PINNED_VALUE, setPinnedValue, setPage, testIdBase } = props;
|
|
2351
|
+
const { group, setGroup, available, fixed, pinnedFields = EMPTY_PINNED_FIELDS, pinnedValue = EMPTY_PINNED_VALUE, setPinnedValue, presets, setPreset, setPage, testIdBase } = props;
|
|
1568
2352
|
const [open, setOpen] = useState(false);
|
|
1569
2353
|
const [focusPath, setFocusPath] = useState(void 0);
|
|
1570
2354
|
const [externalRemoval, setExternalRemoval] = useState(void 0);
|
|
@@ -1581,6 +2365,11 @@ function FilterBuilder(props) {
|
|
|
1581
2365
|
setPinnedValue?.(next);
|
|
1582
2366
|
};
|
|
1583
2367
|
return jsxs(Fragment$1, { children: [
|
|
2368
|
+
presets !== void 0 && presets.length > 0 && setPreset !== void 0 && jsx(PresetFilterControls, {
|
|
2369
|
+
presets,
|
|
2370
|
+
setPreset,
|
|
2371
|
+
testIdBase
|
|
2372
|
+
}),
|
|
1584
2373
|
jsx(PinnedFilterControls, {
|
|
1585
2374
|
pinnedFields,
|
|
1586
2375
|
value: pinnedValue,
|
|
@@ -1616,6 +2405,6 @@ function FilterBuilder(props) {
|
|
|
1616
2405
|
] });
|
|
1617
2406
|
}
|
|
1618
2407
|
//#endregion
|
|
1619
|
-
export { TableHeader as
|
|
2408
|
+
export { TableHeader as A, DEFAULT_LANGUAGE_STORAGE_KEY as B, SelectTrigger as C, TableCaption as D, TableBody as E, ResolvedFieldDisplay as F, saveLocale as H, ResolvedFieldInput as I, useFieldMetaDiagnostic as L, Badge as M, badgeVariants as N, TableCell as O, MetaPlaceholder as P, fieldDescription as R, SelectSeparator as S, Table as T, loadLocale as V, SelectGroup as _, PinnedFilterControls as a, SelectScrollDownButton as b, fromLocalDateTimeText as c, useFieldTimeZone as d, FilterBadges as f, SelectContent as g, Select as h, FacetedFilterPicker as i, TableRow as j, TableHead as k, toLocalDateTimeText as l, localeTag as m, PresetFilterControls as n, FilterPanel as o, formatNumber as p, DataTableFacetedFilter as r, FilterValueControl as s, FilterBuilder as t, dateDisplayParams as u, SelectItem as v, SelectValue as w, SelectScrollUpButton as x, SelectLabel as y, lowerLegacyField as z };
|
|
1620
2409
|
|
|
1621
|
-
//# sourceMappingURL=filter-builder-
|
|
2410
|
+
//# sourceMappingURL=filter-builder-z3Axzf9Y.js.map
|