@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,8 +1,9 @@
|
|
|
1
1
|
const require_use_theme = require("./use-theme-DFlpXils.cjs");
|
|
2
|
-
const require_toaster = require("./toaster-
|
|
2
|
+
const require_toaster = require("./toaster-BbByOytP.cjs");
|
|
3
3
|
const require_button = require("./button-BxnnE28H.cjs");
|
|
4
4
|
const require_input = require("./input-BI0czGyI.cjs");
|
|
5
|
-
const
|
|
5
|
+
const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
|
|
6
|
+
const require_skeleton = require("./skeleton-_1gP7wan.cjs");
|
|
6
7
|
let _burojs_core = require("@burojs/core");
|
|
7
8
|
let _burojs_react = require("@burojs/react");
|
|
8
9
|
let _tabler_icons_react = require("@tabler/icons-react");
|
|
@@ -10,6 +11,7 @@ let react = require("react");
|
|
|
10
11
|
react = require_use_theme.__toESM(react, 1);
|
|
11
12
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
13
|
let class_variance_authority = require("class-variance-authority");
|
|
14
|
+
let _burojs_core_internal = require("@burojs/core/internal");
|
|
13
15
|
let _radix_ui_react_select = require("@radix-ui/react-select");
|
|
14
16
|
_radix_ui_react_select = require_use_theme.__toESM(_radix_ui_react_select, 1);
|
|
15
17
|
//#region src/layout/language-storage.ts
|
|
@@ -28,6 +30,536 @@ function saveLocale(code, storageKey = _burojs_react.DEFAULT_LANGUAGE_STORAGE_KE
|
|
|
28
30
|
} catch {}
|
|
29
31
|
}
|
|
30
32
|
//#endregion
|
|
33
|
+
//#region src/fields/legacy-field.ts
|
|
34
|
+
const STRING_ITEM = Object.freeze({ type: "string" });
|
|
35
|
+
const LEGACY_KIND_DECLARATIONS = Object.freeze({
|
|
36
|
+
string: { type: "string" },
|
|
37
|
+
text: {
|
|
38
|
+
type: "string",
|
|
39
|
+
format: "text"
|
|
40
|
+
},
|
|
41
|
+
textarea: {
|
|
42
|
+
type: "string",
|
|
43
|
+
format: "textarea"
|
|
44
|
+
},
|
|
45
|
+
code: {
|
|
46
|
+
type: "string",
|
|
47
|
+
format: "code"
|
|
48
|
+
},
|
|
49
|
+
email: {
|
|
50
|
+
type: "string",
|
|
51
|
+
format: "email"
|
|
52
|
+
},
|
|
53
|
+
url: {
|
|
54
|
+
type: "string",
|
|
55
|
+
format: "url"
|
|
56
|
+
},
|
|
57
|
+
uuid: {
|
|
58
|
+
type: "string",
|
|
59
|
+
format: "uuid"
|
|
60
|
+
},
|
|
61
|
+
number: { type: "number" },
|
|
62
|
+
boolean: { type: "boolean" },
|
|
63
|
+
date: {
|
|
64
|
+
type: "string",
|
|
65
|
+
format: "date"
|
|
66
|
+
},
|
|
67
|
+
dateTime: {
|
|
68
|
+
type: "string",
|
|
69
|
+
format: "date-time"
|
|
70
|
+
},
|
|
71
|
+
enum: {
|
|
72
|
+
type: "string",
|
|
73
|
+
format: "enum"
|
|
74
|
+
},
|
|
75
|
+
json: {
|
|
76
|
+
type: "object",
|
|
77
|
+
format: "json"
|
|
78
|
+
},
|
|
79
|
+
richText: {
|
|
80
|
+
type: "string",
|
|
81
|
+
format: "rich-text"
|
|
82
|
+
},
|
|
83
|
+
file: {
|
|
84
|
+
type: "array",
|
|
85
|
+
format: "file",
|
|
86
|
+
items: STRING_ITEM
|
|
87
|
+
},
|
|
88
|
+
relation: { type: "relation" },
|
|
89
|
+
relationMany: {
|
|
90
|
+
type: "array",
|
|
91
|
+
format: "relation",
|
|
92
|
+
items: STRING_ITEM
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
const SEMANTIC_KEYS = Object.freeze([
|
|
96
|
+
"type",
|
|
97
|
+
"format",
|
|
98
|
+
"meta",
|
|
99
|
+
"required",
|
|
100
|
+
"nullable",
|
|
101
|
+
"empty",
|
|
102
|
+
"default",
|
|
103
|
+
"constraints",
|
|
104
|
+
"zone",
|
|
105
|
+
"texts",
|
|
106
|
+
"options",
|
|
107
|
+
"items",
|
|
108
|
+
"properties",
|
|
109
|
+
"additionalProperties",
|
|
110
|
+
"variants"
|
|
111
|
+
]);
|
|
112
|
+
function ownData(value, key) {
|
|
113
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return { present: false };
|
|
114
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
115
|
+
if (descriptor === void 0 || !Object.prototype.propertyIsEnumerable.call(value, key) || !("value" in descriptor)) return { present: false };
|
|
116
|
+
return {
|
|
117
|
+
present: true,
|
|
118
|
+
value: descriptor.value
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function ownString(value, key) {
|
|
122
|
+
const candidate = ownData(value, key).value;
|
|
123
|
+
return typeof candidate === "string" && candidate.length > 0 ? candidate : void 0;
|
|
124
|
+
}
|
|
125
|
+
function ownSelection(value, key) {
|
|
126
|
+
const candidate = ownData(value, key).value;
|
|
127
|
+
if (typeof candidate === "string") return candidate.length > 0 ? candidate : void 0;
|
|
128
|
+
return candidate !== null && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : void 0;
|
|
129
|
+
}
|
|
130
|
+
function projectUiSelection(input) {
|
|
131
|
+
const selection = {};
|
|
132
|
+
const inputId = ownSelection(input, "input");
|
|
133
|
+
const displayId = ownSelection(input, "display");
|
|
134
|
+
const layout = ownData(input, "layout").value;
|
|
135
|
+
if (inputId !== void 0) selection.input = inputId;
|
|
136
|
+
if (displayId !== void 0) selection.display = displayId;
|
|
137
|
+
if (Array.isArray(layout)) selection.layout = layout;
|
|
138
|
+
return Object.keys(selection).length === 0 ? void 0 : Object.freeze(selection);
|
|
139
|
+
}
|
|
140
|
+
function projectFieldDeclaration(input) {
|
|
141
|
+
const type = ownString(input, "type");
|
|
142
|
+
if (type === void 0) return void 0;
|
|
143
|
+
const projected = { type };
|
|
144
|
+
for (const key of SEMANTIC_KEYS) {
|
|
145
|
+
if (key === "type" || key === "items" || key === "properties" || key === "variants") continue;
|
|
146
|
+
const candidate = ownData(input, key);
|
|
147
|
+
if (candidate.present && candidate.value !== void 0) projected[key] = candidate.value;
|
|
148
|
+
}
|
|
149
|
+
const ui = projectUiSelection(ownData(input, "ui").value);
|
|
150
|
+
if (ui !== void 0) projected.ui = ui;
|
|
151
|
+
if (type === "array") {
|
|
152
|
+
const item = projectFieldDeclaration(ownData(input, "items").value);
|
|
153
|
+
if (item !== void 0) projected.items = item;
|
|
154
|
+
}
|
|
155
|
+
if (type === "object") {
|
|
156
|
+
const properties = ownData(input, "properties").value;
|
|
157
|
+
if (Array.isArray(properties)) {
|
|
158
|
+
const output = {};
|
|
159
|
+
for (let index = 0; index < properties.length; index += 1) {
|
|
160
|
+
const entry = ownData(properties, index).value;
|
|
161
|
+
const name = ownString(entry, "name");
|
|
162
|
+
const child = projectFieldDeclaration(entry);
|
|
163
|
+
if (name !== void 0 && child !== void 0) output[name] = child;
|
|
164
|
+
}
|
|
165
|
+
projected.properties = Object.freeze(output);
|
|
166
|
+
} else if (properties !== null && typeof properties === "object") {
|
|
167
|
+
const output = {};
|
|
168
|
+
for (const key of Object.keys(properties)) {
|
|
169
|
+
const child = projectFieldDeclaration(ownData(properties, key).value);
|
|
170
|
+
if (child !== void 0) output[key] = child;
|
|
171
|
+
}
|
|
172
|
+
projected.properties = Object.freeze(output);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (type === "union") {
|
|
176
|
+
const variants = ownData(input, "variants").value;
|
|
177
|
+
if (Array.isArray(variants)) {
|
|
178
|
+
const output = [];
|
|
179
|
+
for (let index = 0; index < variants.length; index += 1) {
|
|
180
|
+
const child = projectFieldDeclaration(ownData(variants, index).value);
|
|
181
|
+
if (child !== void 0) output.push(child);
|
|
182
|
+
}
|
|
183
|
+
projected.variants = Object.freeze(output);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return Object.freeze(projected);
|
|
187
|
+
}
|
|
188
|
+
function projectUiHints(input) {
|
|
189
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) return void 0;
|
|
190
|
+
const projected = {};
|
|
191
|
+
for (const key of Object.keys(input)) {
|
|
192
|
+
const candidate = ownData(input, key);
|
|
193
|
+
if (candidate.present) projected[key] = candidate.value;
|
|
194
|
+
}
|
|
195
|
+
return Object.freeze(projected);
|
|
196
|
+
}
|
|
197
|
+
function enumValueOptions(field) {
|
|
198
|
+
const own = ownData(field, "values").value;
|
|
199
|
+
const values = Array.isArray(own) ? own : ownData(ownData(field, "ui").value, "values").value;
|
|
200
|
+
if (!Array.isArray(values)) return void 0;
|
|
201
|
+
const options = values.filter((value) => typeof value === "string").map((value) => Object.freeze({ value }));
|
|
202
|
+
return options.length === 0 ? void 0 : Object.freeze(options);
|
|
203
|
+
}
|
|
204
|
+
function lowerLegacyField(field) {
|
|
205
|
+
const declaration = projectFieldDeclaration(ownData(field, "declaration").value);
|
|
206
|
+
if (declaration !== void 0) return declaration;
|
|
207
|
+
const direct = projectFieldDeclaration(field);
|
|
208
|
+
const kind = ownString(field, "kind");
|
|
209
|
+
const mapping = kind === void 0 ? void 0 : LEGACY_KIND_DECLARATIONS[kind];
|
|
210
|
+
if (direct !== void 0) {
|
|
211
|
+
const format = direct.format ?? mapping?.format ?? kind;
|
|
212
|
+
return format === void 0 ? direct : Object.freeze({
|
|
213
|
+
...direct,
|
|
214
|
+
format
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
const ui = projectUiHints(ownData(field, "ui").value);
|
|
218
|
+
const type = kind === "file" && ui?.multiple !== true ? "unknown" : mapping?.type ?? "unknown";
|
|
219
|
+
const format = ownString(field, "format") ?? mapping?.format ?? kind;
|
|
220
|
+
const items = type === "array" ? projectFieldDeclaration(ownData(field, "items").value) ?? mapping?.items ?? STRING_ITEM : void 0;
|
|
221
|
+
const meta = ownData(field, "meta");
|
|
222
|
+
const texts = ownData(field, "texts");
|
|
223
|
+
const zone = ownData(field, "zone");
|
|
224
|
+
const options = kind === "enum" ? enumValueOptions(field) : void 0;
|
|
225
|
+
const required = ownData(field, "required");
|
|
226
|
+
const nullable = ownData(field, "nullable");
|
|
227
|
+
const opts = ownData(field, "opts").value;
|
|
228
|
+
const optionRequired = ownData(opts, "required");
|
|
229
|
+
const optionNullable = ownData(opts, "nullable");
|
|
230
|
+
const requiredValue = required.present ? required.value : optionRequired.value;
|
|
231
|
+
const nullableValue = nullable.present ? nullable.value : optionNullable.value;
|
|
232
|
+
return Object.freeze({
|
|
233
|
+
type,
|
|
234
|
+
...format === void 0 ? {} : { format },
|
|
235
|
+
...items === void 0 ? {} : { items },
|
|
236
|
+
...meta.present && meta.value !== void 0 ? { meta: meta.value } : {},
|
|
237
|
+
...options === void 0 ? {} : { options },
|
|
238
|
+
...texts.present && texts.value !== void 0 ? { texts: texts.value } : {},
|
|
239
|
+
...zone.present && zone.value !== void 0 ? { zone: zone.value } : {},
|
|
240
|
+
...requiredValue === true ? { required: true } : {},
|
|
241
|
+
...nullableValue === true ? { nullable: true } : {}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function lowerLegacyFieldSource(field) {
|
|
245
|
+
const declaration = lowerLegacyField(field);
|
|
246
|
+
const ui = projectUiHints(ownData(field, "ui").value);
|
|
247
|
+
if (ui === void 0) return declaration;
|
|
248
|
+
return Object.freeze({
|
|
249
|
+
...declaration,
|
|
250
|
+
ui
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
function fieldDescription(field) {
|
|
254
|
+
const declaration = field?.declaration;
|
|
255
|
+
return (0, _burojs_core.declaredText)("field", declaration, "description") ?? (0, _burojs_core.declaredText)("field", field, "description");
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/fields/resolved-field.tsx
|
|
259
|
+
const EMPTY = Object.freeze({});
|
|
260
|
+
const EMPTY_ISSUES = Object.freeze([]);
|
|
261
|
+
const EMPTY_OPTIONS = Object.freeze([]);
|
|
262
|
+
function canonical(field) {
|
|
263
|
+
return lowerLegacyField(field);
|
|
264
|
+
}
|
|
265
|
+
function useLoweredField(source) {
|
|
266
|
+
return (0, react.useMemo)(() => {
|
|
267
|
+
const sourceAtEdge = lowerLegacyFieldSource(source);
|
|
268
|
+
return {
|
|
269
|
+
sourceAtEdge,
|
|
270
|
+
field: canonical(sourceAtEdge),
|
|
271
|
+
ui: sourceAtEdge.ui ?? EMPTY
|
|
272
|
+
};
|
|
273
|
+
}, [source]);
|
|
274
|
+
}
|
|
275
|
+
const warnedObjectLabels = new Set();
|
|
276
|
+
function optionsFor(field, name) {
|
|
277
|
+
if (Array.isArray(field.options)) return field.options;
|
|
278
|
+
const candidate = field.meta?.options;
|
|
279
|
+
if (!Array.isArray(candidate)) return EMPTY_OPTIONS;
|
|
280
|
+
const output = [];
|
|
281
|
+
for (const item of candidate) {
|
|
282
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) continue;
|
|
283
|
+
const raw = item;
|
|
284
|
+
if (typeof raw.value !== "string" && typeof raw.value !== "number" && typeof raw.value !== "boolean" && raw.value !== null) continue;
|
|
285
|
+
const { value, label, description, ...legacyMeta } = raw;
|
|
286
|
+
if (typeof label !== "string" && process.env.NODE_ENV !== "production" && !warnedObjectLabels.has(`${name}:${value}`)) {
|
|
287
|
+
warnedObjectLabels.add(`${name}:${value}`);
|
|
288
|
+
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).`);
|
|
289
|
+
}
|
|
290
|
+
output.push(Object.freeze({
|
|
291
|
+
value,
|
|
292
|
+
label: typeof label === "string" ? label : String(value),
|
|
293
|
+
...typeof description === "string" ? { description } : {},
|
|
294
|
+
...Object.keys(legacyMeta).length === 0 ? {} : { meta: Object.freeze(legacyMeta) }
|
|
295
|
+
}));
|
|
296
|
+
}
|
|
297
|
+
return Object.freeze(output);
|
|
298
|
+
}
|
|
299
|
+
function useContextOptions(field, name, meta, ui, resource) {
|
|
300
|
+
const legacy = field.meta?.options;
|
|
301
|
+
const options = (0, react.useMemo)(() => optionsFor(field, name), [
|
|
302
|
+
field.options,
|
|
303
|
+
legacy,
|
|
304
|
+
name
|
|
305
|
+
]);
|
|
306
|
+
return (0, _burojs_react.useResolvedFieldOptions)({
|
|
307
|
+
name,
|
|
308
|
+
meta,
|
|
309
|
+
ui,
|
|
310
|
+
texts: field.texts
|
|
311
|
+
}, options, resource.id);
|
|
312
|
+
}
|
|
313
|
+
function useContextTexts(field, name, resolved, resource) {
|
|
314
|
+
return (0, _burojs_react.useImplementationTexts)({
|
|
315
|
+
fieldName: name,
|
|
316
|
+
fieldTexts: field.texts,
|
|
317
|
+
id: resolved.id,
|
|
318
|
+
implementation: resolved.implementation
|
|
319
|
+
}, resource.id);
|
|
320
|
+
}
|
|
321
|
+
function useFieldRuntimeContext(resource, record, values, metaSources) {
|
|
322
|
+
const locale = (0, _burojs_react.useLocale)();
|
|
323
|
+
const caps = (0, _burojs_react.useI18nCaps)((0, _burojs_core.canonicalResourceKey)(resource));
|
|
324
|
+
const metaSourcesOut = (0, _burojs_react.useFieldMetaSources)({
|
|
325
|
+
record,
|
|
326
|
+
values,
|
|
327
|
+
extra: metaSources
|
|
328
|
+
});
|
|
329
|
+
const scopeState = metaSourcesOut.scope;
|
|
330
|
+
const scope = scopeState === void 0 ? void 0 : (0, _burojs_react.scopeValueOf)(scopeState);
|
|
331
|
+
return (0, react.useMemo)(() => Object.freeze({
|
|
332
|
+
i18n: Object.freeze({
|
|
333
|
+
locale,
|
|
334
|
+
has: caps.has,
|
|
335
|
+
t: caps.t
|
|
336
|
+
}),
|
|
337
|
+
sources: Object.freeze({
|
|
338
|
+
record: record ?? EMPTY,
|
|
339
|
+
values: values ?? EMPTY,
|
|
340
|
+
scope: scope ?? EMPTY
|
|
341
|
+
}),
|
|
342
|
+
metaSources: metaSourcesOut
|
|
343
|
+
}), [
|
|
344
|
+
caps,
|
|
345
|
+
locale,
|
|
346
|
+
record,
|
|
347
|
+
scope,
|
|
348
|
+
values,
|
|
349
|
+
metaSourcesOut
|
|
350
|
+
]);
|
|
351
|
+
}
|
|
352
|
+
function useFieldMetaDiagnostic(state, resource, name, field, surface, entry) {
|
|
353
|
+
const reported = (0, react.useRef)(void 0);
|
|
354
|
+
const reason = state.status === "failed" ? state.reason : void 0;
|
|
355
|
+
(0, react.useEffect)(() => {
|
|
356
|
+
if (reason === void 0 || reported.current === reason || process.env.NODE_ENV === "production") return;
|
|
357
|
+
reported.current = reason;
|
|
358
|
+
const implementation = (0, _burojs_core.resolveSurfaceUi)(field, surface, entry).use ?? field.format ?? field.type;
|
|
359
|
+
console.error(`[burojs] field.meta-invalid: ${(0, _burojs_core.formatEntityRef)(resource)}.${name} (${implementation}): ${reason}`);
|
|
360
|
+
}, [
|
|
361
|
+
reason,
|
|
362
|
+
resource,
|
|
363
|
+
name,
|
|
364
|
+
field,
|
|
365
|
+
surface,
|
|
366
|
+
entry
|
|
367
|
+
]);
|
|
368
|
+
}
|
|
369
|
+
function MetaPlaceholder({ state }) {
|
|
370
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
371
|
+
if (state.status === "pending") return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
|
|
372
|
+
"data-buro-skeleton": "",
|
|
373
|
+
"data-buro-field-meta": "pending",
|
|
374
|
+
className: "h-9 w-full"
|
|
375
|
+
});
|
|
376
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
377
|
+
role: "alert",
|
|
378
|
+
"data-buro-field-meta": "failed",
|
|
379
|
+
className: "rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground",
|
|
380
|
+
children: t("field.misconfigured", { defaultValue: "This field is misconfigured" })
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
function useFieldImplementationDiagnostic(diagnostic) {
|
|
384
|
+
const reported = (0, react.useRef)(void 0);
|
|
385
|
+
(0, react.useEffect)(() => {
|
|
386
|
+
if (diagnostic === void 0 || reported.current === diagnostic || process.env.NODE_ENV === "production") return;
|
|
387
|
+
reported.current = diagnostic;
|
|
388
|
+
console.warn("[buro/ui-shadcn] missing-field-implementation; rendering fallback.", diagnostic);
|
|
389
|
+
}, [diagnostic]);
|
|
390
|
+
}
|
|
391
|
+
function ResolvedFieldDisplay({ resource, name, field: source, value, record, testId, fallback, presentation, metaSources, uiSurface = "display", columnEntry, absentPaths, pathStatus }) {
|
|
392
|
+
const { sourceAtEdge, field, ui } = useLoweredField(source);
|
|
393
|
+
const surfaceField = (0, react.useMemo)(() => sourceAtEdge.ui === void 0 ? field : Object.freeze({
|
|
394
|
+
...field,
|
|
395
|
+
ui
|
|
396
|
+
}), [
|
|
397
|
+
sourceAtEdge,
|
|
398
|
+
field,
|
|
399
|
+
ui
|
|
400
|
+
]);
|
|
401
|
+
const resolved = (0, _burojs_react.useFieldImplementation)({
|
|
402
|
+
field: surfaceField,
|
|
403
|
+
surface: "display",
|
|
404
|
+
uiSurface,
|
|
405
|
+
...columnEntry === void 0 ? {} : { uiEntry: columnEntry }
|
|
406
|
+
});
|
|
407
|
+
const runtimeContext = useFieldRuntimeContext(resource, record, record, metaSources);
|
|
408
|
+
const metaState = (0, _burojs_react.useFieldMeta)(field, resolved.implementation, runtimeContext.metaSources, resolved.params);
|
|
409
|
+
const textField = (0, react.useMemo)(() => Object.freeze({
|
|
410
|
+
...surfaceField,
|
|
411
|
+
name
|
|
412
|
+
}), [surfaceField, name]);
|
|
413
|
+
const text = (0, _burojs_react.useFieldDisplayText)(textField, value, {
|
|
414
|
+
surface: uiSurface,
|
|
415
|
+
...columnEntry === void 0 ? {} : { entry: columnEntry },
|
|
416
|
+
resource: (0, _burojs_core.canonicalResourceKey)(resource),
|
|
417
|
+
...record === void 0 ? {} : { record }
|
|
418
|
+
});
|
|
419
|
+
const options = useContextOptions(field, name, metaState.status === "ready" ? metaState.meta : void 0, ui, resource);
|
|
420
|
+
const texts = useContextTexts(field, name, resolved, resource);
|
|
421
|
+
const dateDisplay = (0, _burojs_core.resolveSurfaceUi)(surfaceField, uiSurface, columnEntry).dateDisplay;
|
|
422
|
+
const contextUi = (0, react.useMemo)(() => dateDisplay === void 0 ? ui : Object.freeze({
|
|
423
|
+
...ui,
|
|
424
|
+
display: Object.freeze({
|
|
425
|
+
...typeof ui.display === "object" && ui.display !== null ? ui.display : {},
|
|
426
|
+
...dateDisplay
|
|
427
|
+
})
|
|
428
|
+
}), [ui, dateDisplay]);
|
|
429
|
+
useFieldMetaDiagnostic(metaState, resource, name, surfaceField, uiSurface, columnEntry);
|
|
430
|
+
useFieldImplementationDiagnostic(resolved.diagnostic);
|
|
431
|
+
if (resolved.Component === void 0) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: fallback });
|
|
432
|
+
if (metaState.status !== "ready") return (0, react_jsx_runtime.jsx)(MetaPlaceholder, { state: metaState });
|
|
433
|
+
const Component = resolved.Component;
|
|
434
|
+
const context = {
|
|
435
|
+
owner: resource,
|
|
436
|
+
resource,
|
|
437
|
+
field,
|
|
438
|
+
path: Object.freeze([name]),
|
|
439
|
+
...absentPaths === void 0 || absentPaths.length === 0 ? {} : { absentPaths },
|
|
440
|
+
...pathStatus === void 0 ? {} : { pathStatus },
|
|
441
|
+
surface: "display",
|
|
442
|
+
presentation: presentation ?? "default",
|
|
443
|
+
record,
|
|
444
|
+
meta: metaState.meta,
|
|
445
|
+
ui: contextUi,
|
|
446
|
+
options,
|
|
447
|
+
texts,
|
|
448
|
+
...text === void 0 ? {} : { text },
|
|
449
|
+
i18n: runtimeContext.i18n,
|
|
450
|
+
sources: runtimeContext.sources,
|
|
451
|
+
pending: false,
|
|
452
|
+
touched: false,
|
|
453
|
+
issues: EMPTY_ISSUES,
|
|
454
|
+
accessibility: EMPTY,
|
|
455
|
+
testIds: testId === void 0 ? EMPTY : Object.freeze({ display: testId })
|
|
456
|
+
};
|
|
457
|
+
if (resolved.multiple) return (0, react.createElement)(Component, {
|
|
458
|
+
...context,
|
|
459
|
+
multiple: true,
|
|
460
|
+
value: Array.isArray(value) ? value : []
|
|
461
|
+
});
|
|
462
|
+
return (0, react.createElement)(Component, {
|
|
463
|
+
...context,
|
|
464
|
+
multiple: false,
|
|
465
|
+
value
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
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 }) {
|
|
469
|
+
const { sourceAtEdge, field: base } = useLoweredField(source);
|
|
470
|
+
const field = (0, react.useMemo)(() => required === void 0 || required === base.required ? base : Object.freeze({
|
|
471
|
+
...base,
|
|
472
|
+
required
|
|
473
|
+
}), [base, required]);
|
|
474
|
+
const ui = (0, react.useMemo)(() => Object.freeze({
|
|
475
|
+
...sourceAtEdge.ui ?? EMPTY,
|
|
476
|
+
...placeholder === void 0 ? {} : { placeholder }
|
|
477
|
+
}), [sourceAtEdge, placeholder]);
|
|
478
|
+
const inputField = (0, react.useMemo)(() => ({
|
|
479
|
+
...field,
|
|
480
|
+
ui
|
|
481
|
+
}), [field, ui]);
|
|
482
|
+
const resolved = (0, _burojs_react.useFieldImplementation)({
|
|
483
|
+
field: inputField,
|
|
484
|
+
surface: "input"
|
|
485
|
+
});
|
|
486
|
+
const runtimeContext = useFieldRuntimeContext(resource, record, form, metaSources);
|
|
487
|
+
const metaState = (0, _burojs_react.useFieldMeta)(field, resolved.implementation, runtimeContext.metaSources, resolved.params);
|
|
488
|
+
const options = useContextOptions(field, name, metaState.status === "ready" ? metaState.meta : void 0, ui, resource);
|
|
489
|
+
const texts = useContextTexts(field, name, resolved, resource);
|
|
490
|
+
useFieldMetaDiagnostic(metaState, resource, name, inputField, "input");
|
|
491
|
+
useFieldImplementationDiagnostic(resolved.diagnostic);
|
|
492
|
+
if (resolved.Component === void 0) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: fallback });
|
|
493
|
+
if (metaState.status !== "ready") return (0, react_jsx_runtime.jsx)(MetaPlaceholder, { state: metaState });
|
|
494
|
+
const Component = resolved.Component;
|
|
495
|
+
const issues = suppliedIssues ?? (errorMessage == null ? EMPTY_ISSUES : Object.freeze([Object.freeze({
|
|
496
|
+
code: "ui.field-error",
|
|
497
|
+
message: {
|
|
498
|
+
key: "ui.field-error",
|
|
499
|
+
default: errorMessage
|
|
500
|
+
},
|
|
501
|
+
path: Object.freeze([]),
|
|
502
|
+
source: "field",
|
|
503
|
+
severity: "error"
|
|
504
|
+
})]));
|
|
505
|
+
const context = {
|
|
506
|
+
owner: resource,
|
|
507
|
+
resource,
|
|
508
|
+
field,
|
|
509
|
+
path: Object.freeze([name]),
|
|
510
|
+
...absentPaths === void 0 || absentPaths.length === 0 ? {} : { absentPaths },
|
|
511
|
+
...pathStatus === void 0 ? {} : { pathStatus },
|
|
512
|
+
surface: "input",
|
|
513
|
+
presentation: "default",
|
|
514
|
+
record,
|
|
515
|
+
form,
|
|
516
|
+
meta: metaState.meta,
|
|
517
|
+
ui,
|
|
518
|
+
options,
|
|
519
|
+
texts,
|
|
520
|
+
i18n: runtimeContext.i18n,
|
|
521
|
+
sources: runtimeContext.sources,
|
|
522
|
+
pending,
|
|
523
|
+
touched,
|
|
524
|
+
issues,
|
|
525
|
+
accessibility: Object.freeze({
|
|
526
|
+
input: inputId ?? name,
|
|
527
|
+
label: labelId,
|
|
528
|
+
description: descriptionId,
|
|
529
|
+
error: errorId
|
|
530
|
+
}),
|
|
531
|
+
testIds: testId === void 0 ? EMPTY : Object.freeze({ input: testId })
|
|
532
|
+
};
|
|
533
|
+
if (resolved.multiple) return (0, react.createElement)(Component, {
|
|
534
|
+
...context,
|
|
535
|
+
multiple: true,
|
|
536
|
+
value: Array.isArray(value) ? value : [],
|
|
537
|
+
onChange,
|
|
538
|
+
onBlur,
|
|
539
|
+
disabled,
|
|
540
|
+
relationSeeds,
|
|
541
|
+
fixedFilters,
|
|
542
|
+
optionSubtitle,
|
|
543
|
+
link,
|
|
544
|
+
metaSources: runtimeContext.metaSources,
|
|
545
|
+
...baseline === void 0 ? {} : { baseline }
|
|
546
|
+
});
|
|
547
|
+
return (0, react.createElement)(Component, {
|
|
548
|
+
...context,
|
|
549
|
+
multiple: false,
|
|
550
|
+
value,
|
|
551
|
+
onChange,
|
|
552
|
+
onBlur,
|
|
553
|
+
disabled,
|
|
554
|
+
relationSeeds,
|
|
555
|
+
fixedFilters,
|
|
556
|
+
optionSubtitle,
|
|
557
|
+
link,
|
|
558
|
+
metaSources: runtimeContext.metaSources,
|
|
559
|
+
...baseline === void 0 ? {} : { baseline }
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
//#endregion
|
|
31
563
|
//#region src/primitives/badge.tsx
|
|
32
564
|
const badgeVariants = (0, class_variance_authority.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", {
|
|
33
565
|
variants: { variant: {
|
|
@@ -105,11 +637,11 @@ const SelectGroup = _radix_ui_react_select.Group;
|
|
|
105
637
|
const SelectValue = _radix_ui_react_select.Value;
|
|
106
638
|
const SelectTrigger = react.forwardRef(({ className, children, ...props }, ref) => (0, react_jsx_runtime.jsxs)(_radix_ui_react_select.Trigger, {
|
|
107
639
|
ref,
|
|
108
|
-
className: require_use_theme.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]:
|
|
640
|
+
className: require_use_theme.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),
|
|
109
641
|
...props,
|
|
110
642
|
children: [children, (0, react_jsx_runtime.jsx)(_radix_ui_react_select.Icon, {
|
|
111
643
|
asChild: true,
|
|
112
|
-
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
644
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, { className: "h-4 w-4 shrink-0 opacity-50" })
|
|
113
645
|
})]
|
|
114
646
|
}));
|
|
115
647
|
SelectTrigger.displayName = _radix_ui_react_select.Trigger.displayName;
|
|
@@ -148,15 +680,24 @@ const SelectLabel = react.forwardRef(({ className, ...props }, ref) => (0, react
|
|
|
148
680
|
...props
|
|
149
681
|
}));
|
|
150
682
|
SelectLabel.displayName = _radix_ui_react_select.Label.displayName;
|
|
151
|
-
const SelectItem = react.forwardRef(({ className, children, ...props }, ref) =>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
158
|
-
|
|
159
|
-
}))
|
|
683
|
+
const SelectItem = react.forwardRef(({ className, children, description, ...props }, ref) => {
|
|
684
|
+
const hasDescription = description !== void 0 && description !== null;
|
|
685
|
+
return (0, react_jsx_runtime.jsxs)(_radix_ui_react_select.Item, {
|
|
686
|
+
ref,
|
|
687
|
+
className: require_use_theme.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),
|
|
688
|
+
...props,
|
|
689
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
690
|
+
className: require_use_theme.cn("absolute left-2 flex h-3.5 w-3.5 items-center justify-center", hasDescription && "top-[9px]"),
|
|
691
|
+
children: (0, react_jsx_runtime.jsx)(_radix_ui_react_select.ItemIndicator, { children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, { className: "h-4 w-4" }) })
|
|
692
|
+
}), !hasDescription ? (0, react_jsx_runtime.jsx)(_radix_ui_react_select.ItemText, { children }) : (0, react_jsx_runtime.jsxs)("span", {
|
|
693
|
+
className: "flex min-w-0 flex-col gap-0.5",
|
|
694
|
+
children: [(0, react_jsx_runtime.jsx)(_radix_ui_react_select.ItemText, { children }), (0, react_jsx_runtime.jsx)("span", {
|
|
695
|
+
className: "text-xs leading-snug text-muted-foreground",
|
|
696
|
+
children: description
|
|
697
|
+
})]
|
|
698
|
+
})]
|
|
699
|
+
});
|
|
700
|
+
});
|
|
160
701
|
SelectItem.displayName = _radix_ui_react_select.Item.displayName;
|
|
161
702
|
const SelectSeparator = react.forwardRef(({ className, ...props }, ref) => (0, react_jsx_runtime.jsx)(_radix_ui_react_select.Separator, {
|
|
162
703
|
ref,
|
|
@@ -169,8 +710,6 @@ SelectSeparator.displayName = _radix_ui_react_select.Separator.displayName;
|
|
|
169
710
|
function localeTag(locale) {
|
|
170
711
|
return locale || loadLocale() || "en-US";
|
|
171
712
|
}
|
|
172
|
-
const dateCache = new Map();
|
|
173
|
-
const dateTimeCache = new Map();
|
|
174
713
|
const numberCache = new Map();
|
|
175
714
|
function cached(cache, key, make) {
|
|
176
715
|
const hit = cache.get(key);
|
|
@@ -184,24 +723,6 @@ function cached(cache, key, make) {
|
|
|
184
723
|
cache.set(key, made);
|
|
185
724
|
return made;
|
|
186
725
|
}
|
|
187
|
-
function formatDate(d, locale) {
|
|
188
|
-
const tag = localeTag(locale);
|
|
189
|
-
return cached(dateCache, tag, (t) => new Intl.DateTimeFormat(t, {
|
|
190
|
-
year: "numeric",
|
|
191
|
-
month: "short",
|
|
192
|
-
day: "numeric"
|
|
193
|
-
})).format(d);
|
|
194
|
-
}
|
|
195
|
-
function formatDateTime(d, locale) {
|
|
196
|
-
const tag = localeTag(locale);
|
|
197
|
-
return cached(dateTimeCache, tag, (t) => new Intl.DateTimeFormat(t, {
|
|
198
|
-
year: "numeric",
|
|
199
|
-
month: "short",
|
|
200
|
-
day: "numeric",
|
|
201
|
-
hour: "2-digit",
|
|
202
|
-
minute: "2-digit"
|
|
203
|
-
})).format(d);
|
|
204
|
-
}
|
|
205
726
|
function formatNumber(n, locale) {
|
|
206
727
|
const tag = localeTag(locale);
|
|
207
728
|
return cached(numberCache, tag, (t) => new Intl.NumberFormat(t)).format(n);
|
|
@@ -209,31 +730,31 @@ function formatNumber(n, locale) {
|
|
|
209
730
|
//#endregion
|
|
210
731
|
//#region src/list-kit/filter-builder/describe-row.ts
|
|
211
732
|
const MAX_DESCRIBE_DEPTH = 2;
|
|
212
|
-
function describeValue(value,
|
|
733
|
+
function describeValue(value, chromeT, spec, formatValue) {
|
|
213
734
|
if (value === void 0) return null;
|
|
214
|
-
if (Array.isArray(value)) return
|
|
735
|
+
if (Array.isArray(value)) return chromeT("filters.selectedCount", { count: value.length }, `${value.length} selected`);
|
|
215
736
|
const optionLabel = spec?.options?.find((o) => o.value === String(value))?.label;
|
|
216
737
|
if (optionLabel !== void 0) return optionLabel;
|
|
217
738
|
if (spec && formatValue) {
|
|
218
|
-
const formatted = formatValue(spec.kind, value);
|
|
739
|
+
const formatted = formatValue(spec.kind, value, spec.zone);
|
|
219
740
|
if (formatted !== void 0) return formatted;
|
|
220
741
|
}
|
|
221
742
|
return String(value);
|
|
222
743
|
}
|
|
223
|
-
function describeAt(row, available,
|
|
744
|
+
function describeAt(row, available, chromeT, depth, formatValue) {
|
|
224
745
|
if ((0, _burojs_core.isFilterGroup)(row)) {
|
|
225
746
|
if (depth > MAX_DESCRIBE_DEPTH) return "…";
|
|
226
|
-
const joinLabel =
|
|
227
|
-
return `(${row.rows.map((child) => describeAt(child, available,
|
|
747
|
+
const joinLabel = chromeT(`filters.${row.join}`, void 0, row.join);
|
|
748
|
+
return `(${row.rows.map((child) => describeAt(child, available, chromeT, depth + 1, formatValue)).join(` ${joinLabel} `)})`;
|
|
228
749
|
}
|
|
229
750
|
const spec = available.find((s) => s.field === row.field);
|
|
230
751
|
const label = spec?.label ?? row.field;
|
|
231
|
-
const opLabel =
|
|
232
|
-
const valueText = (0, _burojs_core.opArity)(row.op) === "none" ? null : describeValue(row.value,
|
|
752
|
+
const opLabel = chromeT(`filters.operators.${row.op}`, void 0, row.op);
|
|
753
|
+
const valueText = (0, _burojs_core.opArity)(row.op) === "none" ? null : describeValue(row.value, chromeT, spec, formatValue);
|
|
233
754
|
return valueText === null ? `${label} ${opLabel}` : `${label} ${opLabel} ${valueText}`;
|
|
234
755
|
}
|
|
235
|
-
function describeRow(row, available,
|
|
236
|
-
return describeAt(row, available,
|
|
756
|
+
function describeRow(row, available, chromeT, formatValue) {
|
|
757
|
+
return describeAt(row, available, chromeT, 1, formatValue);
|
|
237
758
|
}
|
|
238
759
|
function relationLabelKey(to, by, value) {
|
|
239
760
|
return `${by === void 0 ? to : `${to}#${by}`}::${value}`;
|
|
@@ -296,7 +817,7 @@ function RelationLabelResolver(props) {
|
|
|
296
817
|
const { to, id, by, onResolve } = props;
|
|
297
818
|
const targetDef = (0, _burojs_react.useApp)().registry.get(to);
|
|
298
819
|
const { record } = (0, _burojs_react.useRelatedRecord)(to, id, by === void 0 ? void 0 : { by });
|
|
299
|
-
const rowTitle =
|
|
820
|
+
const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
|
|
300
821
|
(0, react.useEffect)(() => {
|
|
301
822
|
if (!record) return;
|
|
302
823
|
onResolve(relationLabelKey(to, by, id), rowTitle(record));
|
|
@@ -366,23 +887,33 @@ function badgeKey(row, index) {
|
|
|
366
887
|
if ((0, _burojs_core.isFilterGroup)(row)) return `${index}:group:${row.join}`;
|
|
367
888
|
return `${index}:${row.field}:${row.op}`;
|
|
368
889
|
}
|
|
890
|
+
const BADGE_ROW = "inline-flex max-w-full items-center gap-1 align-middle";
|
|
891
|
+
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";
|
|
369
892
|
function FilterBadges(props) {
|
|
370
893
|
const { group, setGroup, available, fixed, testIdBase, onOpenAt, onRemoved, pinnedFields = [], pinnedValue = [], setPinnedValue } = props;
|
|
371
|
-
const
|
|
372
|
-
const
|
|
894
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
895
|
+
const locale = (0, _burojs_react.useOptionalLocale)();
|
|
896
|
+
const viewer = (0, _burojs_react.useTimeZone)();
|
|
897
|
+
const timeContext = (0, _burojs_react.useTimeContext)();
|
|
898
|
+
const tt = (key, params, fallback) => chromeT(key, {
|
|
373
899
|
params,
|
|
374
900
|
...typeof params?.count === "number" ? { count: params.count } : {},
|
|
375
901
|
defaultValue: fallback
|
|
376
902
|
});
|
|
377
|
-
const removeLabel =
|
|
903
|
+
const removeLabel = chromeT("filters.removeRow", { defaultValue: "Remove filter" });
|
|
378
904
|
const { enumLabels, relationLabels, onEnumResolved, onRelationResolved } = useFormatValueMaps();
|
|
379
|
-
const formatValue = (kind, value) => {
|
|
905
|
+
const formatValue = (kind, value, fieldZone) => {
|
|
380
906
|
if (kind.kind === "enum") return enumLabels[kind.enumName]?.[String(value)];
|
|
381
907
|
if (kind.kind === "relation") return relationLabels[relationLabelKey(kind.to, kind.by, String(value))];
|
|
382
|
-
if (kind.kind === "date") {
|
|
383
|
-
const
|
|
384
|
-
if (
|
|
385
|
-
return kind.time ?
|
|
908
|
+
if (kind.kind === "date" && viewer.status === "ready") {
|
|
909
|
+
const zone = (0, _burojs_core.resolveTimeZone)(timeContext.levels, fieldZone, timeContext.sources);
|
|
910
|
+
if (zone.status === "pending") return void 0;
|
|
911
|
+
return (0, _burojs_core.formatTimeValue)(kind.time ? "dateTime" : "date", String(value), {
|
|
912
|
+
zone: zone.zone,
|
|
913
|
+
viewerZone: viewer.zone,
|
|
914
|
+
locale: localeTag(locale),
|
|
915
|
+
params: {}
|
|
916
|
+
});
|
|
386
917
|
}
|
|
387
918
|
};
|
|
388
919
|
const orphanPinned = (0, react.useMemo)(() => {
|
|
@@ -416,49 +947,56 @@ function FilterBadges(props) {
|
|
|
416
947
|
onEnumResolved,
|
|
417
948
|
onRelationResolved
|
|
418
949
|
}),
|
|
419
|
-
group.rows.map((row, index) => (0, react_jsx_runtime.
|
|
950
|
+
group.rows.map((row, index) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
420
951
|
variant: "secondary",
|
|
421
|
-
className: "
|
|
422
|
-
children:
|
|
423
|
-
|
|
424
|
-
"
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
"
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
className:
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
952
|
+
className: "py-1 pr-1",
|
|
953
|
+
children: (0, react_jsx_runtime.jsxs)("span", {
|
|
954
|
+
className: BADGE_ROW,
|
|
955
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
956
|
+
type: "button",
|
|
957
|
+
"data-testid": `${testIdBase}:badge:${index}`,
|
|
958
|
+
onClick: () => onOpenAt([index]),
|
|
959
|
+
className: "min-w-0 cursor-pointer truncate bg-transparent p-0 text-left",
|
|
960
|
+
children: describeRow(row, available, tt, formatValue)
|
|
961
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
962
|
+
type: "button",
|
|
963
|
+
"data-testid": `${testIdBase}:badge:${index}:remove`,
|
|
964
|
+
"aria-label": removeLabel,
|
|
965
|
+
onClick: () => handleRemove(index),
|
|
966
|
+
className: REMOVE_BUTTON,
|
|
967
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
|
|
968
|
+
className: "size-3",
|
|
969
|
+
"aria-hidden": "true"
|
|
970
|
+
})
|
|
971
|
+
})]
|
|
972
|
+
})
|
|
439
973
|
}, badgeKey(row, index))),
|
|
440
974
|
labelledFixed.map((entry, index) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
441
975
|
variant: "outline",
|
|
442
976
|
"data-testid": `${testIdBase}:badge:fixed:${index}`,
|
|
443
977
|
children: entry.label
|
|
444
978
|
}, `fixed-${index}`)),
|
|
445
|
-
orphanPinned.map(({ expr, index }) => (0, react_jsx_runtime.
|
|
979
|
+
orphanPinned.map(({ expr, index }) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
446
980
|
variant: "secondary",
|
|
447
|
-
className: "
|
|
448
|
-
children:
|
|
449
|
-
|
|
450
|
-
children:
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
"
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
981
|
+
className: "py-1 pr-1",
|
|
982
|
+
children: (0, react_jsx_runtime.jsxs)("span", {
|
|
983
|
+
className: BADGE_ROW,
|
|
984
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
985
|
+
"data-testid": `${testIdBase}:badge:pinned:${index}`,
|
|
986
|
+
className: "min-w-0 truncate",
|
|
987
|
+
children: describeRow(expr, available, tt, formatValue)
|
|
988
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
989
|
+
type: "button",
|
|
990
|
+
"data-testid": `${testIdBase}:badge:pinned:${index}:remove`,
|
|
991
|
+
"aria-label": removeLabel,
|
|
992
|
+
onClick: () => handleRemovePinned(index),
|
|
993
|
+
className: REMOVE_BUTTON,
|
|
994
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
|
|
995
|
+
className: "size-3",
|
|
996
|
+
"aria-hidden": "true"
|
|
997
|
+
})
|
|
998
|
+
})]
|
|
999
|
+
})
|
|
462
1000
|
}, `pinned-${index}`))
|
|
463
1001
|
]
|
|
464
1002
|
});
|
|
@@ -648,14 +1186,15 @@ const OPTIONS = ["true", "false"];
|
|
|
648
1186
|
function BooleanValueControl(props) {
|
|
649
1187
|
const { value, onChange, testId, arity, autoFocus, fieldLabel, fill } = props;
|
|
650
1188
|
const t = (0, _burojs_react.useOptionalT)();
|
|
651
|
-
const
|
|
1189
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1190
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
652
1191
|
defaultValue: `Value for ${fieldLabel}`,
|
|
653
1192
|
params: { field: fieldLabel }
|
|
654
|
-
}) :
|
|
1193
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
655
1194
|
const yesLabel = t("boolean.yes", { defaultValue: "Yes" });
|
|
656
1195
|
const noLabel = t("boolean.no", { defaultValue: "No" });
|
|
657
1196
|
const labelOf = (token) => token === "true" ? yesLabel : noLabel;
|
|
658
|
-
const clearLabel =
|
|
1197
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
659
1198
|
const { open, setOpen, selected, select, triggerLabel, clear } = useSelectableValueControl({
|
|
660
1199
|
value,
|
|
661
1200
|
arity,
|
|
@@ -675,12 +1214,12 @@ function BooleanValueControl(props) {
|
|
|
675
1214
|
"data-testid": testId,
|
|
676
1215
|
"aria-label": ariaLabel,
|
|
677
1216
|
className: require_use_theme.cn("h-8 justify-between", fill && "w-full"),
|
|
678
|
-
children: triggerLabel(labelOf, ariaLabel)
|
|
1217
|
+
children: triggerLabel(labelOf, props.placeholder ?? ariaLabel)
|
|
679
1218
|
})
|
|
680
1219
|
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
681
1220
|
className: "w-[140px] p-0",
|
|
682
1221
|
align: "start",
|
|
683
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
1222
|
+
children: (0, react_jsx_runtime.jsx)(require_relation_create.Command, { children: (0, react_jsx_runtime.jsx)(require_relation_create.CommandList, { children: (0, react_jsx_runtime.jsxs)(require_relation_create.CommandGroup, { children: [arity === "single" && selected.size > 0 && (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
684
1223
|
"data-testid": `${testId}:clear`,
|
|
685
1224
|
value: "__clear__",
|
|
686
1225
|
onSelect: () => clear(),
|
|
@@ -690,7 +1229,7 @@ function BooleanValueControl(props) {
|
|
|
690
1229
|
}), clearLabel]
|
|
691
1230
|
}), OPTIONS.map((token) => {
|
|
692
1231
|
const isSelected = selected.has(token);
|
|
693
|
-
return (0, react_jsx_runtime.jsxs)(
|
|
1232
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
694
1233
|
value: labelOf(token),
|
|
695
1234
|
"data-testid": `${testId}:option:${token}`,
|
|
696
1235
|
onSelect: () => select(token),
|
|
@@ -708,12 +1247,13 @@ function BooleanValueControl(props) {
|
|
|
708
1247
|
function SelectListValueControl(props) {
|
|
709
1248
|
const { options, value, onChange, testId, arity, autoFocus, fieldLabel, isLoading = false } = props;
|
|
710
1249
|
const t = (0, _burojs_react.useOptionalT)();
|
|
711
|
-
const
|
|
1250
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1251
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
712
1252
|
defaultValue: `Value for ${fieldLabel}`,
|
|
713
1253
|
params: { field: fieldLabel }
|
|
714
|
-
}) :
|
|
1254
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
715
1255
|
const loadingLabel = t("table.loading", { defaultValue: "Loading…" });
|
|
716
|
-
const clearLabel =
|
|
1256
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
717
1257
|
const labelFor = props.labelFor ?? ((raw) => options.find((o) => o.value === raw)?.label ?? raw);
|
|
718
1258
|
const { open, setOpen, selected, select, triggerLabel, clear } = useSelectableValueControl({
|
|
719
1259
|
value,
|
|
@@ -735,16 +1275,16 @@ function SelectListValueControl(props) {
|
|
|
735
1275
|
className: require_use_theme.cn("h-8 justify-between truncate", props.fill ? "w-full" : "max-w-[200px]"),
|
|
736
1276
|
children: (0, react_jsx_runtime.jsx)("span", {
|
|
737
1277
|
className: "truncate",
|
|
738
|
-
children: isLoading ? loadingLabel : triggerLabel(labelFor, ariaLabel)
|
|
1278
|
+
children: isLoading ? loadingLabel : triggerLabel(labelFor, props.placeholder ?? ariaLabel)
|
|
739
1279
|
})
|
|
740
1280
|
})
|
|
741
1281
|
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
742
1282
|
className: "w-[220px] p-0",
|
|
743
1283
|
align: "start",
|
|
744
|
-
children: (0, react_jsx_runtime.jsxs)(
|
|
1284
|
+
children: (0, react_jsx_runtime.jsxs)(require_relation_create.Command, { children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
|
|
745
1285
|
placeholder: ariaLabel,
|
|
746
1286
|
"data-testid": `${testId}:search`
|
|
747
|
-
}), (0, react_jsx_runtime.jsxs)(
|
|
1287
|
+
}), (0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, { children: [
|
|
748
1288
|
isLoading && (0, react_jsx_runtime.jsxs)("div", {
|
|
749
1289
|
className: "flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground",
|
|
750
1290
|
"data-testid": `${testId}:loading`,
|
|
@@ -753,8 +1293,8 @@ function SelectListValueControl(props) {
|
|
|
753
1293
|
"aria-hidden": "true"
|
|
754
1294
|
}), loadingLabel]
|
|
755
1295
|
}),
|
|
756
|
-
!isLoading && (0, react_jsx_runtime.jsx)(
|
|
757
|
-
!isLoading && (0, react_jsx_runtime.jsxs)(
|
|
1296
|
+
!isLoading && (0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, { children: t("relation.noResults", { defaultValue: "No results." }) }),
|
|
1297
|
+
!isLoading && (0, react_jsx_runtime.jsxs)(require_relation_create.CommandGroup, { children: [arity === "single" && selected.size > 0 && (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
758
1298
|
"data-testid": `${testId}:clear`,
|
|
759
1299
|
value: "__clear__",
|
|
760
1300
|
onSelect: () => clear(),
|
|
@@ -765,7 +1305,7 @@ function SelectListValueControl(props) {
|
|
|
765
1305
|
}), options.map((entry) => {
|
|
766
1306
|
const isSelected = selected.has(entry.value);
|
|
767
1307
|
const label = labelFor(entry.value);
|
|
768
|
-
return (0, react_jsx_runtime.jsxs)(
|
|
1308
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
769
1309
|
value: label,
|
|
770
1310
|
"data-testid": `${testId}:option:${entry.value}`,
|
|
771
1311
|
onSelect: () => select(entry.value),
|
|
@@ -798,6 +1338,7 @@ function EnumValueControl(props) {
|
|
|
798
1338
|
arity,
|
|
799
1339
|
autoFocus,
|
|
800
1340
|
fieldLabel,
|
|
1341
|
+
placeholder: props.placeholder,
|
|
801
1342
|
options,
|
|
802
1343
|
labelFor,
|
|
803
1344
|
isLoading,
|
|
@@ -809,7 +1350,7 @@ function EnumValueControl(props) {
|
|
|
809
1350
|
function useRelatedLabels(to, ids, by) {
|
|
810
1351
|
const targetDef = (0, _burojs_react.useApp)().registry.get(to);
|
|
811
1352
|
const idField = (targetDef?.data)?.idField;
|
|
812
|
-
const rowTitle =
|
|
1353
|
+
const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
|
|
813
1354
|
const field = by ?? (typeof idField === "string" && idField.length > 0 ? idField : "id");
|
|
814
1355
|
const query = (0, _burojs_react.useList)(to, {
|
|
815
1356
|
pagination: {
|
|
@@ -844,6 +1385,7 @@ function RelationValueControl(props) {
|
|
|
844
1385
|
const { to, by, value, onChange, testId, arity, autoFocus, fieldLabel } = props;
|
|
845
1386
|
const app = (0, _burojs_react.useApp)();
|
|
846
1387
|
const t = (0, _burojs_react.useOptionalT)();
|
|
1388
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
847
1389
|
const targetDef = app.registry.get(to);
|
|
848
1390
|
const displayField = targetDef?.displayField ?? "name";
|
|
849
1391
|
const [search, setSearch] = (0, react.useState)("");
|
|
@@ -852,9 +1394,9 @@ function RelationValueControl(props) {
|
|
|
852
1394
|
arity,
|
|
853
1395
|
onChange
|
|
854
1396
|
});
|
|
855
|
-
const rowTitle =
|
|
1397
|
+
const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
|
|
856
1398
|
const access = (0, _burojs_react.useListAccess)(to);
|
|
857
|
-
const searchable = (0, react.useMemo)(() => access.status === "ready" &&
|
|
1399
|
+
const searchable = (0, react.useMemo)(() => access.status === "ready" && require_relation_create.narrowSearchDecl({ fields: [displayField] }, (name) => access.fieldVisible(name)) !== void 0, [access, displayField]);
|
|
858
1400
|
const listQuery = (0, _burojs_react.useList)(to, {
|
|
859
1401
|
pagination: {
|
|
860
1402
|
kind: "offset",
|
|
@@ -882,11 +1424,11 @@ function RelationValueControl(props) {
|
|
|
882
1424
|
if (fromRows) return rowTitle(fromRows);
|
|
883
1425
|
return fallbackLabels[id] ?? id;
|
|
884
1426
|
};
|
|
885
|
-
const ariaLabel = fieldLabel ?
|
|
1427
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
886
1428
|
defaultValue: `Value for ${fieldLabel}`,
|
|
887
1429
|
params: { field: fieldLabel }
|
|
888
|
-
}) :
|
|
889
|
-
const clearLabel =
|
|
1430
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
1431
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
890
1432
|
return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, {
|
|
891
1433
|
open,
|
|
892
1434
|
onOpenChange: setOpen,
|
|
@@ -902,20 +1444,20 @@ function RelationValueControl(props) {
|
|
|
902
1444
|
className: require_use_theme.cn("h-8 justify-between truncate", props.fill ? "w-full" : "max-w-[220px]"),
|
|
903
1445
|
children: (0, react_jsx_runtime.jsx)("span", {
|
|
904
1446
|
className: "truncate",
|
|
905
|
-
children: triggerLabel(labelFor, ariaLabel)
|
|
1447
|
+
children: triggerLabel(labelFor, props.placeholder ?? ariaLabel)
|
|
906
1448
|
})
|
|
907
1449
|
})
|
|
908
1450
|
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
909
1451
|
className: "w-[240px] p-0",
|
|
910
1452
|
align: "start",
|
|
911
|
-
children: (0, react_jsx_runtime.jsxs)(
|
|
1453
|
+
children: (0, react_jsx_runtime.jsxs)(require_relation_create.Command, {
|
|
912
1454
|
shouldFilter: false,
|
|
913
|
-
children: [searchable && (0, react_jsx_runtime.jsx)(
|
|
1455
|
+
children: [searchable && (0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
|
|
914
1456
|
value: search,
|
|
915
1457
|
onValueChange: setSearch,
|
|
916
1458
|
placeholder: ariaLabel,
|
|
917
1459
|
"data-testid": `${testId}:search`
|
|
918
|
-
}), (0, react_jsx_runtime.jsxs)(
|
|
1460
|
+
}), (0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, { children: [
|
|
919
1461
|
listQuery.isLoading && (0, react_jsx_runtime.jsxs)("div", {
|
|
920
1462
|
className: "flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground",
|
|
921
1463
|
"data-testid": `${testId}:loading`,
|
|
@@ -924,8 +1466,8 @@ function RelationValueControl(props) {
|
|
|
924
1466
|
"aria-hidden": "true"
|
|
925
1467
|
}), t("table.loading", { defaultValue: "Loading…" })]
|
|
926
1468
|
}),
|
|
927
|
-
!listQuery.isLoading && rows.length === 0 && (0, react_jsx_runtime.jsx)(
|
|
928
|
-
!listQuery.isLoading && arity === "single" && selected.size > 0 && (0, react_jsx_runtime.jsxs)(
|
|
1469
|
+
!listQuery.isLoading && rows.length === 0 && (0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, { children: t("relation.noResults", { defaultValue: "No results." }) }),
|
|
1470
|
+
!listQuery.isLoading && arity === "single" && selected.size > 0 && (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
929
1471
|
"data-testid": `${testId}:clear`,
|
|
930
1472
|
value: "__clear__",
|
|
931
1473
|
onSelect: () => clear(),
|
|
@@ -939,7 +1481,7 @@ function RelationValueControl(props) {
|
|
|
939
1481
|
if (id === void 0) return null;
|
|
940
1482
|
const label = rowTitle(row);
|
|
941
1483
|
const isSelected = selected.has(id);
|
|
942
|
-
return (0, react_jsx_runtime.jsxs)(
|
|
1484
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
943
1485
|
value: `${label} ${id}`,
|
|
944
1486
|
"data-testid": `${testId}:option:${id}`,
|
|
945
1487
|
onSelect: () => select(id),
|
|
@@ -958,7 +1500,56 @@ function RelationValueControl(props) {
|
|
|
958
1500
|
});
|
|
959
1501
|
}
|
|
960
1502
|
//#endregion
|
|
1503
|
+
//#region src/fields/field-time-zone.ts
|
|
1504
|
+
function useFieldTimeZone(zone, row) {
|
|
1505
|
+
const { sources: session } = (0, _burojs_react.useTimeContext)();
|
|
1506
|
+
const sources = (0, react.useMemo)(() => row === void 0 ? session : {
|
|
1507
|
+
...session,
|
|
1508
|
+
record: {
|
|
1509
|
+
status: "ready",
|
|
1510
|
+
value: row,
|
|
1511
|
+
refreshing: false
|
|
1512
|
+
}
|
|
1513
|
+
}, [session, row]);
|
|
1514
|
+
const fieldZone = (0, react.useMemo)(() => (0, _burojs_core_internal.normaliseFieldZone)(zone), [zone]);
|
|
1515
|
+
return (0, _burojs_react.useTimeZone)(fieldZone, sources);
|
|
1516
|
+
}
|
|
1517
|
+
const DATE_KEYS = [
|
|
1518
|
+
"dateStyle",
|
|
1519
|
+
"timeStyle",
|
|
1520
|
+
"zoneName"
|
|
1521
|
+
];
|
|
1522
|
+
function dateDisplayParams(ui) {
|
|
1523
|
+
const display = ui?.display;
|
|
1524
|
+
if (display === null || typeof display !== "object") return {};
|
|
1525
|
+
const params = {};
|
|
1526
|
+
for (const key of DATE_KEYS) {
|
|
1527
|
+
const value = display[key];
|
|
1528
|
+
if (value !== void 0) params[key] = value;
|
|
1529
|
+
}
|
|
1530
|
+
return params;
|
|
1531
|
+
}
|
|
1532
|
+
//#endregion
|
|
1533
|
+
//#region src/fields/local-date-time.ts
|
|
1534
|
+
function toLocalDateTimeText(value, zone) {
|
|
1535
|
+
if (value === void 0 || value === null || value === "") return "";
|
|
1536
|
+
const instant = (0, _burojs_core.canonicalInstant)(value instanceof Date ? value.toISOString() : String(value));
|
|
1537
|
+
if (instant === void 0) return "";
|
|
1538
|
+
const { date, time } = (0, _burojs_core.instantToWall)(instant, zone);
|
|
1539
|
+
return `${date}T${time.slice(0, 5)}`;
|
|
1540
|
+
}
|
|
1541
|
+
function fromLocalDateTimeText(text, zone) {
|
|
1542
|
+
const [date, time, ...rest] = text.split("T");
|
|
1543
|
+
if (date === void 0 || time === void 0 || rest.length > 0) return void 0;
|
|
1544
|
+
if (!(0, _burojs_core.isCalendarDate)(date) || !(0, _burojs_core.isWallTime)(time)) return void 0;
|
|
1545
|
+
return (0, _burojs_core.wallToInstant)(date, time, zone);
|
|
1546
|
+
}
|
|
1547
|
+
//#endregion
|
|
961
1548
|
//#region src/list-kit/filter-builder/values/scalar-value-input.tsx
|
|
1549
|
+
function useFilterZone(fieldZone) {
|
|
1550
|
+
const zone = useFieldTimeZone(fieldZone, void 0);
|
|
1551
|
+
return zone.status === "ready" ? zone.zone : "UTC";
|
|
1552
|
+
}
|
|
962
1553
|
function isDateTime(kind) {
|
|
963
1554
|
return kind.kind === "date" && kind.time === true;
|
|
964
1555
|
}
|
|
@@ -969,33 +1560,27 @@ function inputTypeFor(kind) {
|
|
|
969
1560
|
default: return "text";
|
|
970
1561
|
}
|
|
971
1562
|
}
|
|
972
|
-
function toText(kind, value) {
|
|
1563
|
+
function toText(kind, value, zone) {
|
|
1564
|
+
if (isDateTime(kind)) return toLocalDateTimeText(value, zone);
|
|
973
1565
|
if (value === void 0 || value === null || value === "") return "";
|
|
974
|
-
|
|
975
|
-
const d = new Date(String(value));
|
|
976
|
-
if (Number.isNaN(d.getTime())) return "";
|
|
977
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
978
|
-
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
1566
|
+
return String(value);
|
|
979
1567
|
}
|
|
980
|
-
function parseOne(kind, raw) {
|
|
1568
|
+
function parseOne(kind, raw, zone) {
|
|
981
1569
|
if (raw === "") return void 0;
|
|
982
1570
|
if (kind.kind === "number") {
|
|
983
1571
|
const n = Number(raw);
|
|
984
1572
|
return Number.isFinite(n) ? n : void 0;
|
|
985
1573
|
}
|
|
986
|
-
if (isDateTime(kind))
|
|
987
|
-
const d = new Date(raw);
|
|
988
|
-
return Number.isNaN(d.getTime()) ? void 0 : d.toISOString();
|
|
989
|
-
}
|
|
1574
|
+
if (isDateTime(kind)) return fromLocalDateTimeText(raw, zone);
|
|
990
1575
|
return raw;
|
|
991
1576
|
}
|
|
992
1577
|
function ScalarValueInput(props) {
|
|
993
|
-
const
|
|
1578
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
994
1579
|
const inputType = inputTypeFor(props.kind);
|
|
995
|
-
const ariaLabel = props.fieldLabel ?
|
|
1580
|
+
const ariaLabel = props.fieldLabel ? chromeT("filters.valueFor", {
|
|
996
1581
|
defaultValue: `Value for ${props.fieldLabel}`,
|
|
997
1582
|
params: { field: props.fieldLabel }
|
|
998
|
-
}) :
|
|
1583
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
999
1584
|
if (props.arity === "multi") return (0, react_jsx_runtime.jsx)(ScalarMultiInput, {
|
|
1000
1585
|
...props,
|
|
1001
1586
|
inputType,
|
|
@@ -1009,7 +1594,8 @@ function ScalarValueInput(props) {
|
|
|
1009
1594
|
}
|
|
1010
1595
|
function ScalarSingleInput(props) {
|
|
1011
1596
|
const { value, onChange, kind, testId, autoFocus, inputType, ariaLabel, debounceMs = 300 } = props;
|
|
1012
|
-
const
|
|
1597
|
+
const zone = useFilterZone(props.zone);
|
|
1598
|
+
const storedText = toText(kind, value, zone);
|
|
1013
1599
|
const [text, setText] = (0, react.useState)(storedText);
|
|
1014
1600
|
const lastPushedRef = (0, react.useRef)(storedText);
|
|
1015
1601
|
const timerRef = (0, react.useRef)(null);
|
|
@@ -1017,8 +1603,8 @@ function ScalarSingleInput(props) {
|
|
|
1017
1603
|
const commitRef = (0, react.useRef)(() => {});
|
|
1018
1604
|
(0, react.useEffect)(() => {
|
|
1019
1605
|
commitRef.current = (raw) => {
|
|
1020
|
-
const parsed = parseOne(kind, raw);
|
|
1021
|
-
lastPushedRef.current = toText(kind, parsed);
|
|
1606
|
+
const parsed = parseOne(kind, raw, zone);
|
|
1607
|
+
lastPushedRef.current = toText(kind, parsed, zone);
|
|
1022
1608
|
pendingRawRef.current = null;
|
|
1023
1609
|
onChange(parsed);
|
|
1024
1610
|
};
|
|
@@ -1067,8 +1653,9 @@ function ScalarMultiInput(props) {
|
|
|
1067
1653
|
const { value, onChange, kind, testId, autoFocus, inputType, ariaLabel } = props;
|
|
1068
1654
|
const chips = Array.isArray(value) ? value.map((v) => String(v)) : [];
|
|
1069
1655
|
const [draft, setDraft] = (0, react.useState)("");
|
|
1656
|
+
const zone = useFilterZone(props.zone);
|
|
1070
1657
|
const addChip = () => {
|
|
1071
|
-
const parsed = parseOne(kind, draft.trim());
|
|
1658
|
+
const parsed = parseOne(kind, draft.trim(), zone);
|
|
1072
1659
|
if (parsed === void 0) return;
|
|
1073
1660
|
const text = String(parsed);
|
|
1074
1661
|
setDraft("");
|
|
@@ -1125,6 +1712,7 @@ function FilterValueControl(props) {
|
|
|
1125
1712
|
arity,
|
|
1126
1713
|
autoFocus: props.autoFocus,
|
|
1127
1714
|
fieldLabel: props.fieldLabel,
|
|
1715
|
+
placeholder: props.placeholder,
|
|
1128
1716
|
options: props.options,
|
|
1129
1717
|
fill: props.fill
|
|
1130
1718
|
});
|
|
@@ -1141,6 +1729,7 @@ function FilterValueControl(props) {
|
|
|
1141
1729
|
arity,
|
|
1142
1730
|
autoFocus: props.autoFocus,
|
|
1143
1731
|
fieldLabel: props.fieldLabel,
|
|
1732
|
+
placeholder: props.placeholder,
|
|
1144
1733
|
options: props.kind.values.map((entry) => ({
|
|
1145
1734
|
value: entry,
|
|
1146
1735
|
label: entry
|
|
@@ -1169,10 +1758,10 @@ const FIELD_CLASS = "h-8 min-w-0 shrink basis-40";
|
|
|
1169
1758
|
const OPERATOR_CLASS = "h-8 min-w-0 shrink basis-[9.5rem]";
|
|
1170
1759
|
function FilterRow(props) {
|
|
1171
1760
|
const { row, path, available, onPatch, onRemove, testIdBase, debounceMs } = props;
|
|
1172
|
-
const
|
|
1761
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1173
1762
|
const base = `${testIdBase}:row:${path.join("-")}`;
|
|
1174
1763
|
const spec = available.find((s) => s.field === row.field);
|
|
1175
|
-
const removeLabel =
|
|
1764
|
+
const removeLabel = chromeT("filters.removeRow", { defaultValue: "Remove filter" });
|
|
1176
1765
|
if (!spec) return (0, react_jsx_runtime.jsxs)("div", {
|
|
1177
1766
|
className: ROW_CLASS,
|
|
1178
1767
|
children: [
|
|
@@ -1212,8 +1801,8 @@ function FilterRow(props) {
|
|
|
1212
1801
|
};
|
|
1213
1802
|
const handleOpChange = (op) => onPatch(path, { op });
|
|
1214
1803
|
const handleValueChange = (value) => onPatch(path, { value });
|
|
1215
|
-
const fieldAriaLabel =
|
|
1216
|
-
const operatorAriaLabel =
|
|
1804
|
+
const fieldAriaLabel = chromeT("filters.field", { defaultValue: "Field" });
|
|
1805
|
+
const operatorAriaLabel = chromeT("filters.operator", { defaultValue: "Operator" });
|
|
1217
1806
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1218
1807
|
className: ROW_CLASS,
|
|
1219
1808
|
children: [
|
|
@@ -1242,7 +1831,7 @@ function FilterRow(props) {
|
|
|
1242
1831
|
}), (0, react_jsx_runtime.jsx)(SelectContent, { children: spec.operators.map((op) => (0, react_jsx_runtime.jsx)(SelectItem, {
|
|
1243
1832
|
value: op,
|
|
1244
1833
|
"data-testid": `${opTestId}:option:${op}`,
|
|
1245
|
-
children:
|
|
1834
|
+
children: chromeT(`filters.operators.${op}`, { defaultValue: op })
|
|
1246
1835
|
}, op)) })]
|
|
1247
1836
|
}),
|
|
1248
1837
|
(0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1256,6 +1845,7 @@ function FilterRow(props) {
|
|
|
1256
1845
|
debounceMs,
|
|
1257
1846
|
fieldLabel: spec.label,
|
|
1258
1847
|
options: spec.options,
|
|
1848
|
+
...spec.zone === void 0 ? {} : { zone: spec.zone },
|
|
1259
1849
|
fill: true
|
|
1260
1850
|
})
|
|
1261
1851
|
}),
|
|
@@ -1290,10 +1880,10 @@ function FilterGroupEditor(props) {
|
|
|
1290
1880
|
}
|
|
1291
1881
|
function GroupEditorInner(props) {
|
|
1292
1882
|
const { group, path, available, onChange, testIdBase, onRemove, addGroupAt, debounceMs } = props;
|
|
1293
|
-
const
|
|
1883
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1294
1884
|
const base = `${testIdBase}:group:${path.join("-")}`;
|
|
1295
1885
|
const canNestGroup = depthOf(path) < 3;
|
|
1296
|
-
const joinLabel = (join) =>
|
|
1886
|
+
const joinLabel = (join) => chromeT(`filters.${join}`, { defaultValue: join });
|
|
1297
1887
|
const handlePatch = (rowPath, patch) => {
|
|
1298
1888
|
const index = rowPath[rowPath.length - 1];
|
|
1299
1889
|
if (index === void 0) return;
|
|
@@ -1326,11 +1916,11 @@ function GroupEditorInner(props) {
|
|
|
1326
1916
|
return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1327
1917
|
className: CONNECTOR_CLASS,
|
|
1328
1918
|
children: [
|
|
1329
|
-
index === 0 &&
|
|
1919
|
+
index === 0 && chromeT("filters.where", { defaultValue: "Where" }),
|
|
1330
1920
|
index === 1 && (0, react_jsx_runtime.jsx)("button", {
|
|
1331
1921
|
type: "button",
|
|
1332
1922
|
"data-testid": `${base}:join`,
|
|
1333
|
-
"aria-label":
|
|
1923
|
+
"aria-label": chromeT("filters.toggleJoin", {
|
|
1334
1924
|
defaultValue: `Join: ${joinLabel(group.join)} — activate to switch to ${joinLabel(otherJoin)}`,
|
|
1335
1925
|
params: {
|
|
1336
1926
|
current: joinLabel(group.join),
|
|
@@ -1382,7 +1972,7 @@ function GroupEditorInner(props) {
|
|
|
1382
1972
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconPlus, {
|
|
1383
1973
|
className: "h-4 w-4",
|
|
1384
1974
|
"aria-hidden": "true"
|
|
1385
|
-
}),
|
|
1975
|
+
}), chromeT("filters.addRow", { defaultValue: "Add filter" })]
|
|
1386
1976
|
}),
|
|
1387
1977
|
canNestGroup && (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
1388
1978
|
type: "button",
|
|
@@ -1393,7 +1983,7 @@ function GroupEditorInner(props) {
|
|
|
1393
1983
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconFolderPlus, {
|
|
1394
1984
|
className: "h-4 w-4",
|
|
1395
1985
|
"aria-hidden": "true"
|
|
1396
|
-
}),
|
|
1986
|
+
}), chromeT("filters.addGroup", { defaultValue: "Add group" })]
|
|
1397
1987
|
}),
|
|
1398
1988
|
onRemove && (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
1399
1989
|
type: "button",
|
|
@@ -1404,7 +1994,7 @@ function GroupEditorInner(props) {
|
|
|
1404
1994
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
|
|
1405
1995
|
className: "h-4 w-4",
|
|
1406
1996
|
"aria-hidden": "true"
|
|
1407
|
-
}),
|
|
1997
|
+
}), chromeT("filters.removeGroup", { defaultValue: "Remove group" })]
|
|
1408
1998
|
})
|
|
1409
1999
|
]
|
|
1410
2000
|
})
|
|
@@ -1420,7 +2010,7 @@ function countGroupRows(group) {
|
|
|
1420
2010
|
}
|
|
1421
2011
|
function FilterPanel(props) {
|
|
1422
2012
|
const { group, setGroup, available, setPage, testIdBase, open, onOpenChange, focusPath, externalRemoval } = props;
|
|
1423
|
-
const
|
|
2013
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1424
2014
|
const [draft, setDraft] = (0, react.useState)(() => toDraft(group));
|
|
1425
2015
|
const wasOpenRef = (0, react.useRef)(open);
|
|
1426
2016
|
const topLevelIdsRef = (0, react.useRef)([]);
|
|
@@ -1472,7 +2062,7 @@ function FilterPanel(props) {
|
|
|
1472
2062
|
className: "h-4 w-4",
|
|
1473
2063
|
"aria-hidden": "true"
|
|
1474
2064
|
}),
|
|
1475
|
-
|
|
2065
|
+
chromeT("filters.title", { defaultValue: "Filters" }),
|
|
1476
2066
|
appliedCount > 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
1477
2067
|
"data-testid": `${testIdBase}:count`,
|
|
1478
2068
|
className: "ml-1 rounded-full bg-primary px-1.5 text-xs text-primary-foreground",
|
|
@@ -1500,13 +2090,13 @@ function FilterPanel(props) {
|
|
|
1500
2090
|
size: "sm",
|
|
1501
2091
|
"data-testid": `${testIdBase}:reset`,
|
|
1502
2092
|
onClick: handleReset,
|
|
1503
|
-
children:
|
|
2093
|
+
children: chromeT("filters.reset", { defaultValue: "Reset" })
|
|
1504
2094
|
}), (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
1505
2095
|
type: "button",
|
|
1506
2096
|
size: "sm",
|
|
1507
2097
|
"data-testid": `${testIdBase}:apply`,
|
|
1508
2098
|
onClick: handleApply,
|
|
1509
|
-
children:
|
|
2099
|
+
children: chromeT("filters.apply", { defaultValue: "Apply" })
|
|
1510
2100
|
})]
|
|
1511
2101
|
})]
|
|
1512
2102
|
})]
|
|
@@ -1557,15 +2147,209 @@ function PinnedControl(props) {
|
|
|
1557
2147
|
testId: `${testIdBase}:pinned:${spec.field}`,
|
|
1558
2148
|
fieldLabel: spec.label,
|
|
1559
2149
|
placeholder: spec.label,
|
|
1560
|
-
options: spec.options
|
|
2150
|
+
options: spec.options,
|
|
2151
|
+
...spec.zone === void 0 ? {} : { zone: spec.zone }
|
|
1561
2152
|
});
|
|
1562
2153
|
}
|
|
1563
2154
|
//#endregion
|
|
2155
|
+
//#region src/data-table/data-table-faceted-filter.tsx
|
|
2156
|
+
function DataTableFacetedFilter({ column, getTestId, ...rest }) {
|
|
2157
|
+
const filterValue = column.getFilterValue();
|
|
2158
|
+
return (0, react_jsx_runtime.jsx)(FacetedFilterPicker, {
|
|
2159
|
+
...rest,
|
|
2160
|
+
...getTestId === void 0 ? {} : { getTestId: (role, value) => role === "hint" ? void 0 : getTestId(role, value) },
|
|
2161
|
+
selected: Array.isArray(filterValue) ? filterValue.map(String) : [],
|
|
2162
|
+
onChange: (next) => column.setFilterValue(next.length === 0 ? void 0 : next)
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2165
|
+
function FacetedFilterPicker({ title, options = [], loadOptions, selectedLabelFor, searchPlaceholder, emptyText, getTestId, className, selected: selectedList, onChange, hint, emptyLabel, clearable = true }) {
|
|
2166
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
2167
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
2168
|
+
const selected = (0, react.useMemo)(() => new Set(selectedList), [selectedList]);
|
|
2169
|
+
const [search, setSearch] = (0, react.useState)("");
|
|
2170
|
+
const [asyncOptions, setAsyncOptions] = (0, react.useState)([]);
|
|
2171
|
+
const [loading, setLoading] = (0, react.useState)(false);
|
|
2172
|
+
const debounceRef = (0, react.useRef)(null);
|
|
2173
|
+
const loadOptionsRef = (0, react.useRef)(loadOptions);
|
|
2174
|
+
(0, react.useEffect)(() => {
|
|
2175
|
+
loadOptionsRef.current = loadOptions;
|
|
2176
|
+
});
|
|
2177
|
+
(0, react.useEffect)(() => {
|
|
2178
|
+
if (!loadOptionsRef.current) return;
|
|
2179
|
+
setLoading(true);
|
|
2180
|
+
if (debounceRef.current !== null) clearTimeout(debounceRef.current);
|
|
2181
|
+
let cancelled = false;
|
|
2182
|
+
debounceRef.current = setTimeout(() => {
|
|
2183
|
+
const loader = loadOptionsRef.current;
|
|
2184
|
+
if (!loader) return;
|
|
2185
|
+
loader(search).then((results) => {
|
|
2186
|
+
if (!cancelled) {
|
|
2187
|
+
setAsyncOptions(results);
|
|
2188
|
+
setLoading(false);
|
|
2189
|
+
}
|
|
2190
|
+
}).catch(() => {
|
|
2191
|
+
if (!cancelled) setLoading(false);
|
|
2192
|
+
});
|
|
2193
|
+
}, 250);
|
|
2194
|
+
return () => {
|
|
2195
|
+
cancelled = true;
|
|
2196
|
+
if (debounceRef.current !== null) clearTimeout(debounceRef.current);
|
|
2197
|
+
};
|
|
2198
|
+
}, [search]);
|
|
2199
|
+
const effectiveOptions = loadOptions ? asyncOptions : options;
|
|
2200
|
+
const labelFor = (value) => {
|
|
2201
|
+
const opt = effectiveOptions.find((o) => o.value === value);
|
|
2202
|
+
if (opt) return opt.label;
|
|
2203
|
+
return selectedLabelFor?.(value) ?? value;
|
|
2204
|
+
};
|
|
2205
|
+
const toggle = (value) => {
|
|
2206
|
+
const next = new Set(selected);
|
|
2207
|
+
if (next.has(value)) next.delete(value);
|
|
2208
|
+
else next.add(value);
|
|
2209
|
+
onChange(Array.from(next));
|
|
2210
|
+
};
|
|
2211
|
+
const selectedValues = Array.from(selected);
|
|
2212
|
+
return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, { children: [(0, react_jsx_runtime.jsx)(require_toaster.PopoverTrigger, {
|
|
2213
|
+
asChild: true,
|
|
2214
|
+
children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
2215
|
+
type: "button",
|
|
2216
|
+
variant: "outline",
|
|
2217
|
+
size: "sm",
|
|
2218
|
+
"data-testid": getTestId?.("trigger"),
|
|
2219
|
+
title: hint,
|
|
2220
|
+
className: require_use_theme.cn("h-8 border-dashed", className),
|
|
2221
|
+
children: [
|
|
2222
|
+
(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCirclePlus, {
|
|
2223
|
+
className: "mr-2 h-4 w-4",
|
|
2224
|
+
"aria-hidden": "true"
|
|
2225
|
+
}),
|
|
2226
|
+
title,
|
|
2227
|
+
selected.size === 0 && emptyLabel !== void 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
|
|
2228
|
+
className: "mx-2 h-4 w-px bg-border",
|
|
2229
|
+
"aria-hidden": "true"
|
|
2230
|
+
}), (0, react_jsx_runtime.jsx)(Badge, {
|
|
2231
|
+
variant: "secondary",
|
|
2232
|
+
className: "rounded-sm px-1 font-normal",
|
|
2233
|
+
children: emptyLabel
|
|
2234
|
+
})] }),
|
|
2235
|
+
selected.size > 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2236
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
2237
|
+
className: "mx-2 h-4 w-px bg-border",
|
|
2238
|
+
"aria-hidden": "true"
|
|
2239
|
+
}),
|
|
2240
|
+
(0, react_jsx_runtime.jsx)(Badge, {
|
|
2241
|
+
variant: "secondary",
|
|
2242
|
+
className: "rounded-sm px-1 font-normal lg:hidden",
|
|
2243
|
+
children: selected.size
|
|
2244
|
+
}),
|
|
2245
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
2246
|
+
className: "hidden gap-1 lg:flex",
|
|
2247
|
+
children: selected.size > 2 ? (0, react_jsx_runtime.jsx)(Badge, {
|
|
2248
|
+
variant: "secondary",
|
|
2249
|
+
className: "rounded-sm px-1 font-normal",
|
|
2250
|
+
children: t("table.selectedCount", {
|
|
2251
|
+
count: selected.size,
|
|
2252
|
+
defaultValue: "{{count}} selected"
|
|
2253
|
+
})
|
|
2254
|
+
}) : selectedValues.map((value) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
2255
|
+
variant: "secondary",
|
|
2256
|
+
className: "rounded-sm px-1 font-normal",
|
|
2257
|
+
children: labelFor(value)
|
|
2258
|
+
}, value))
|
|
2259
|
+
})
|
|
2260
|
+
] })
|
|
2261
|
+
]
|
|
2262
|
+
})
|
|
2263
|
+
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
2264
|
+
className: "w-[220px] p-0",
|
|
2265
|
+
align: "start",
|
|
2266
|
+
children: (0, react_jsx_runtime.jsxs)(require_relation_create.Command, {
|
|
2267
|
+
shouldFilter: !loadOptions,
|
|
2268
|
+
children: [
|
|
2269
|
+
hint !== void 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
2270
|
+
"data-testid": getTestId?.("hint"),
|
|
2271
|
+
className: "border-b px-3 py-2 text-xs text-muted-foreground",
|
|
2272
|
+
children: hint
|
|
2273
|
+
}),
|
|
2274
|
+
(0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
|
|
2275
|
+
placeholder: searchPlaceholder ?? title,
|
|
2276
|
+
"data-testid": getTestId?.("search"),
|
|
2277
|
+
...loadOptions ? {
|
|
2278
|
+
value: search,
|
|
2279
|
+
onValueChange: setSearch
|
|
2280
|
+
} : {}
|
|
2281
|
+
}),
|
|
2282
|
+
(0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, { children: [
|
|
2283
|
+
loading && (0, react_jsx_runtime.jsx)("div", {
|
|
2284
|
+
className: "py-6 text-center text-sm text-muted-foreground",
|
|
2285
|
+
children: t("list.loadingShort", { defaultValue: "Loading…" })
|
|
2286
|
+
}),
|
|
2287
|
+
(0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, { children: emptyText ?? t("relation.noResults", { defaultValue: "No results." }) }),
|
|
2288
|
+
(0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, { children: effectiveOptions.map((opt) => {
|
|
2289
|
+
const isSelected = selected.has(opt.value);
|
|
2290
|
+
const Icon = opt.icon;
|
|
2291
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
2292
|
+
value: opt.label,
|
|
2293
|
+
"data-testid": getTestId?.("option", opt.value),
|
|
2294
|
+
role: "option",
|
|
2295
|
+
"aria-selected": isSelected,
|
|
2296
|
+
"aria-checked": isSelected,
|
|
2297
|
+
onSelect: () => toggle(opt.value),
|
|
2298
|
+
children: [
|
|
2299
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
2300
|
+
className: require_use_theme.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"),
|
|
2301
|
+
"aria-hidden": "true",
|
|
2302
|
+
children: isSelected && (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, { className: "h-3.5 w-3.5" })
|
|
2303
|
+
}),
|
|
2304
|
+
Icon && (0, react_jsx_runtime.jsx)(Icon, {
|
|
2305
|
+
className: "mr-2 h-4 w-4 text-muted-foreground",
|
|
2306
|
+
"aria-hidden": "true"
|
|
2307
|
+
}),
|
|
2308
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
2309
|
+
className: "flex min-w-0 flex-1 flex-col text-left",
|
|
2310
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: opt.label }), opt.summary !== void 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
2311
|
+
className: "text-xs text-muted-foreground",
|
|
2312
|
+
children: opt.summary
|
|
2313
|
+
})]
|
|
2314
|
+
})
|
|
2315
|
+
]
|
|
2316
|
+
}, opt.value);
|
|
2317
|
+
}) })
|
|
2318
|
+
] }),
|
|
2319
|
+
clearable && selected.size > 0 && (0, react_jsx_runtime.jsx)("button", {
|
|
2320
|
+
type: "button",
|
|
2321
|
+
"data-testid": getTestId?.("clear"),
|
|
2322
|
+
onClick: () => onChange([]),
|
|
2323
|
+
className: "flex w-full items-center justify-center border-t px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground",
|
|
2324
|
+
children: chromeT("filters.clearAll", { defaultValue: "Clear filters" })
|
|
2325
|
+
})
|
|
2326
|
+
]
|
|
2327
|
+
})
|
|
2328
|
+
})] });
|
|
2329
|
+
}
|
|
2330
|
+
//#endregion
|
|
2331
|
+
//#region src/list-kit/filter-builder/preset-filter-controls.tsx
|
|
2332
|
+
function PresetFilterControls(props) {
|
|
2333
|
+
const { presets, setPreset, testIdBase } = props;
|
|
2334
|
+
return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: presets.map((filter) => (0, react_jsx_runtime.jsx)(FacetedFilterPicker, {
|
|
2335
|
+
title: filter.label,
|
|
2336
|
+
...filter.hint === void 0 ? {} : { hint: filter.hint },
|
|
2337
|
+
options: filter.options.map((option) => ({
|
|
2338
|
+
value: option.id,
|
|
2339
|
+
label: option.label,
|
|
2340
|
+
...option.summary === void 0 ? {} : { summary: option.summary }
|
|
2341
|
+
})),
|
|
2342
|
+
selected: filter.selected,
|
|
2343
|
+
onChange: (next) => setPreset(filter.id, filter.options.map((option) => option.id).filter((id) => next.includes(id))),
|
|
2344
|
+
getTestId: (role, value) => `${testIdBase}:preset:${filter.id}:${role}${value === void 0 ? "" : `:${value}`}`
|
|
2345
|
+
}, filter.id)) });
|
|
2346
|
+
}
|
|
2347
|
+
//#endregion
|
|
1564
2348
|
//#region src/list-kit/filter-builder/filter-builder.tsx
|
|
1565
2349
|
const EMPTY_PINNED_FIELDS = Object.freeze([]);
|
|
1566
2350
|
const EMPTY_PINNED_VALUE = Object.freeze([]);
|
|
1567
2351
|
function FilterBuilder(props) {
|
|
1568
|
-
const { group, setGroup, available, fixed, pinnedFields = EMPTY_PINNED_FIELDS, pinnedValue = EMPTY_PINNED_VALUE, setPinnedValue, setPage, testIdBase } = props;
|
|
2352
|
+
const { group, setGroup, available, fixed, pinnedFields = EMPTY_PINNED_FIELDS, pinnedValue = EMPTY_PINNED_VALUE, setPinnedValue, presets, setPreset, setPage, testIdBase } = props;
|
|
1569
2353
|
const [open, setOpen] = (0, react.useState)(false);
|
|
1570
2354
|
const [focusPath, setFocusPath] = (0, react.useState)(void 0);
|
|
1571
2355
|
const [externalRemoval, setExternalRemoval] = (0, react.useState)(void 0);
|
|
@@ -1582,6 +2366,11 @@ function FilterBuilder(props) {
|
|
|
1582
2366
|
setPinnedValue?.(next);
|
|
1583
2367
|
};
|
|
1584
2368
|
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2369
|
+
presets !== void 0 && presets.length > 0 && setPreset !== void 0 && (0, react_jsx_runtime.jsx)(PresetFilterControls, {
|
|
2370
|
+
presets,
|
|
2371
|
+
setPreset,
|
|
2372
|
+
testIdBase
|
|
2373
|
+
}),
|
|
1585
2374
|
(0, react_jsx_runtime.jsx)(PinnedFilterControls, {
|
|
1586
2375
|
pinnedFields,
|
|
1587
2376
|
value: pinnedValue,
|
|
@@ -1623,6 +2412,18 @@ Object.defineProperty(exports, "Badge", {
|
|
|
1623
2412
|
return Badge;
|
|
1624
2413
|
}
|
|
1625
2414
|
});
|
|
2415
|
+
Object.defineProperty(exports, "DataTableFacetedFilter", {
|
|
2416
|
+
enumerable: true,
|
|
2417
|
+
get: function() {
|
|
2418
|
+
return DataTableFacetedFilter;
|
|
2419
|
+
}
|
|
2420
|
+
});
|
|
2421
|
+
Object.defineProperty(exports, "FacetedFilterPicker", {
|
|
2422
|
+
enumerable: true,
|
|
2423
|
+
get: function() {
|
|
2424
|
+
return FacetedFilterPicker;
|
|
2425
|
+
}
|
|
2426
|
+
});
|
|
1626
2427
|
Object.defineProperty(exports, "FilterBadges", {
|
|
1627
2428
|
enumerable: true,
|
|
1628
2429
|
get: function() {
|
|
@@ -1647,12 +2448,36 @@ Object.defineProperty(exports, "FilterValueControl", {
|
|
|
1647
2448
|
return FilterValueControl;
|
|
1648
2449
|
}
|
|
1649
2450
|
});
|
|
2451
|
+
Object.defineProperty(exports, "MetaPlaceholder", {
|
|
2452
|
+
enumerable: true,
|
|
2453
|
+
get: function() {
|
|
2454
|
+
return MetaPlaceholder;
|
|
2455
|
+
}
|
|
2456
|
+
});
|
|
1650
2457
|
Object.defineProperty(exports, "PinnedFilterControls", {
|
|
1651
2458
|
enumerable: true,
|
|
1652
2459
|
get: function() {
|
|
1653
2460
|
return PinnedFilterControls;
|
|
1654
2461
|
}
|
|
1655
2462
|
});
|
|
2463
|
+
Object.defineProperty(exports, "PresetFilterControls", {
|
|
2464
|
+
enumerable: true,
|
|
2465
|
+
get: function() {
|
|
2466
|
+
return PresetFilterControls;
|
|
2467
|
+
}
|
|
2468
|
+
});
|
|
2469
|
+
Object.defineProperty(exports, "ResolvedFieldDisplay", {
|
|
2470
|
+
enumerable: true,
|
|
2471
|
+
get: function() {
|
|
2472
|
+
return ResolvedFieldDisplay;
|
|
2473
|
+
}
|
|
2474
|
+
});
|
|
2475
|
+
Object.defineProperty(exports, "ResolvedFieldInput", {
|
|
2476
|
+
enumerable: true,
|
|
2477
|
+
get: function() {
|
|
2478
|
+
return ResolvedFieldInput;
|
|
2479
|
+
}
|
|
2480
|
+
});
|
|
1656
2481
|
Object.defineProperty(exports, "Select", {
|
|
1657
2482
|
enumerable: true,
|
|
1658
2483
|
get: function() {
|
|
@@ -1761,10 +2586,16 @@ Object.defineProperty(exports, "badgeVariants", {
|
|
|
1761
2586
|
return badgeVariants;
|
|
1762
2587
|
}
|
|
1763
2588
|
});
|
|
1764
|
-
Object.defineProperty(exports, "
|
|
2589
|
+
Object.defineProperty(exports, "dateDisplayParams", {
|
|
1765
2590
|
enumerable: true,
|
|
1766
2591
|
get: function() {
|
|
1767
|
-
return
|
|
2592
|
+
return dateDisplayParams;
|
|
2593
|
+
}
|
|
2594
|
+
});
|
|
2595
|
+
Object.defineProperty(exports, "fieldDescription", {
|
|
2596
|
+
enumerable: true,
|
|
2597
|
+
get: function() {
|
|
2598
|
+
return fieldDescription;
|
|
1768
2599
|
}
|
|
1769
2600
|
});
|
|
1770
2601
|
Object.defineProperty(exports, "formatNumber", {
|
|
@@ -1773,17 +2604,53 @@ Object.defineProperty(exports, "formatNumber", {
|
|
|
1773
2604
|
return formatNumber;
|
|
1774
2605
|
}
|
|
1775
2606
|
});
|
|
2607
|
+
Object.defineProperty(exports, "fromLocalDateTimeText", {
|
|
2608
|
+
enumerable: true,
|
|
2609
|
+
get: function() {
|
|
2610
|
+
return fromLocalDateTimeText;
|
|
2611
|
+
}
|
|
2612
|
+
});
|
|
1776
2613
|
Object.defineProperty(exports, "loadLocale", {
|
|
1777
2614
|
enumerable: true,
|
|
1778
2615
|
get: function() {
|
|
1779
2616
|
return loadLocale;
|
|
1780
2617
|
}
|
|
1781
2618
|
});
|
|
2619
|
+
Object.defineProperty(exports, "localeTag", {
|
|
2620
|
+
enumerable: true,
|
|
2621
|
+
get: function() {
|
|
2622
|
+
return localeTag;
|
|
2623
|
+
}
|
|
2624
|
+
});
|
|
2625
|
+
Object.defineProperty(exports, "lowerLegacyField", {
|
|
2626
|
+
enumerable: true,
|
|
2627
|
+
get: function() {
|
|
2628
|
+
return lowerLegacyField;
|
|
2629
|
+
}
|
|
2630
|
+
});
|
|
1782
2631
|
Object.defineProperty(exports, "saveLocale", {
|
|
1783
2632
|
enumerable: true,
|
|
1784
2633
|
get: function() {
|
|
1785
2634
|
return saveLocale;
|
|
1786
2635
|
}
|
|
1787
2636
|
});
|
|
2637
|
+
Object.defineProperty(exports, "toLocalDateTimeText", {
|
|
2638
|
+
enumerable: true,
|
|
2639
|
+
get: function() {
|
|
2640
|
+
return toLocalDateTimeText;
|
|
2641
|
+
}
|
|
2642
|
+
});
|
|
2643
|
+
Object.defineProperty(exports, "useFieldMetaDiagnostic", {
|
|
2644
|
+
enumerable: true,
|
|
2645
|
+
get: function() {
|
|
2646
|
+
return useFieldMetaDiagnostic;
|
|
2647
|
+
}
|
|
2648
|
+
});
|
|
2649
|
+
Object.defineProperty(exports, "useFieldTimeZone", {
|
|
2650
|
+
enumerable: true,
|
|
2651
|
+
get: function() {
|
|
2652
|
+
return useFieldTimeZone;
|
|
2653
|
+
}
|
|
2654
|
+
});
|
|
1788
2655
|
|
|
1789
|
-
//# sourceMappingURL=filter-builder-
|
|
2656
|
+
//# sourceMappingURL=filter-builder-ByGhxLf_.cjs.map
|