@burojs/ui-shadcn 0.5.0 → 0.7.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-BWSAS7k2.js +143 -0
- package/dist/bulk-summary-BWSAS7k2.js.map +1 -0
- package/dist/bulk-summary-CrEij5vq.cjs +143 -0
- package/dist/bulk-summary-CrEij5vq.cjs.map +1 -0
- package/dist/candidates-relation-picker-CS_JZ4Fd.js +31 -0
- package/dist/candidates-relation-picker-CS_JZ4Fd.js.map +1 -0
- package/dist/candidates-relation-picker-y5M6_oe4.cjs +31 -0
- package/dist/candidates-relation-picker-y5M6_oe4.cjs.map +1 -0
- package/dist/{check-confirm-dialog-CkaVTPT9.js → check-confirm-dialog-2j0gOd7x.js} +392 -103
- package/dist/check-confirm-dialog-2j0gOd7x.js.map +1 -0
- package/dist/{check-confirm-dialog-BRByTFpg.cjs → check-confirm-dialog-C-NHgMST.cjs} +476 -102
- package/dist/check-confirm-dialog-C-NHgMST.cjs.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-B3mZFL-K.cjs → filter-builder-DFu0JP-1.cjs} +959 -128
- package/dist/filter-builder-DFu0JP-1.cjs.map +1 -0
- package/dist/{filter-builder-DOnaXNfP.js → filter-builder-DaWHUZuV.js} +863 -116
- package/dist/filter-builder-DaWHUZuV.js.map +1 -0
- package/dist/{flow-runtime-B6zOHYqI.cjs → flow-runtime-BpmrIUb6.cjs} +61 -29
- package/dist/flow-runtime-BpmrIUb6.cjs.map +1 -0
- package/dist/{flow-runtime-D8h99FSg.js → flow-runtime-DyqTmK3H.js} +62 -30
- package/dist/flow-runtime-DyqTmK3H.js.map +1 -0
- package/dist/{flow-screen-CX05b3G9.cjs → flow-screen-Bcz9NF2V.cjs} +132 -88
- package/dist/flow-screen-Bcz9NF2V.cjs.map +1 -0
- package/dist/{flow-screen-CmbARSqg.js → flow-screen-DCdli6Ha.js} +132 -88
- package/dist/flow-screen-DCdli6Ha.js.map +1 -0
- package/dist/index.cjs +951 -605
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +618 -332
- package/dist/index.d.ts +618 -332
- package/dist/index.js +863 -522
- package/dist/index.js.map +1 -1
- package/dist/{inline-flow-host-B7U1OJUe.cjs → inline-flow-host-3vw7LzzD.cjs} +5 -5
- package/dist/inline-flow-host-3vw7LzzD.cjs.map +1 -0
- package/dist/{inline-flow-host-C3H2UpSA.js → inline-flow-host-C0rI9B7f.js} +5 -5
- package/dist/inline-flow-host-C0rI9B7f.js.map +1 -0
- package/dist/label-66W1qbke.js.map +1 -1
- package/dist/label-w6JYf2cF.cjs.map +1 -1
- package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs +153 -0
- package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs.map +1 -0
- package/dist/lazy-relation-picker-dialog-CAScLPb2.js +135 -0
- package/dist/lazy-relation-picker-dialog-CAScLPb2.js.map +1 -0
- package/dist/markdown/index.d.cts +2 -3
- package/dist/markdown/index.d.ts +2 -3
- package/dist/{page-flow-route-CyXSvXSE.js → page-flow-route-BHUEpn0I.js} +36 -23
- package/dist/page-flow-route-BHUEpn0I.js.map +1 -0
- package/dist/{page-flow-route-CQ7HsbBm.cjs → page-flow-route-DS8IVTVH.cjs} +41 -28
- package/dist/page-flow-route-DS8IVTVH.cjs.map +1 -0
- package/dist/{place-node-SIp4XYQH.cjs → place-node-CNb3w-c7.cjs} +2227 -999
- package/dist/place-node-CNb3w-c7.cjs.map +1 -0
- package/dist/{place-node--GdsP688.js → place-node-CfzQvh4Y.js} +2164 -984
- package/dist/place-node-CfzQvh4Y.js.map +1 -0
- package/dist/{related-list-cards-B6x9HQQp.js → related-list-cards-BIqqY69Y.js} +9 -4
- package/dist/{related-list-cards-B6x9HQQp.js.map → related-list-cards-BIqqY69Y.js.map} +1 -1
- package/dist/{related-list-cards-nxuODlIA.cjs → related-list-cards-CelMxl4q.cjs} +9 -4
- package/dist/{related-list-cards-nxuODlIA.cjs.map → related-list-cards-CelMxl4q.cjs.map} +1 -1
- package/dist/{related-list-timeline-DEdfd-rr.js → related-list-timeline-CRh7xwLD.js} +6 -7
- package/dist/related-list-timeline-CRh7xwLD.js.map +1 -0
- package/dist/{related-list-timeline-BYJKEbmA.cjs → related-list-timeline-DsLdi8sv.cjs} +5 -6
- package/dist/related-list-timeline-DsLdi8sv.cjs.map +1 -0
- package/dist/{related-rows-B4levHcR.js → related-rows--uP2iKQC.js} +27 -17
- package/dist/related-rows--uP2iKQC.js.map +1 -0
- package/dist/{related-rows-zh5f_4QR.cjs → related-rows-MPnLCmPF.cjs} +32 -22
- package/dist/related-rows-MPnLCmPF.cjs.map +1 -0
- package/dist/{search-access-CURsWn-U.js → relation-create-C43cdPQt.js} +596 -29
- package/dist/relation-create-C43cdPQt.js.map +1 -0
- package/dist/{search-access-B7G5oR8n.cjs → relation-create-DDEYcKfw.cjs} +630 -32
- package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
- package/dist/{relation-many-picker-gdAOD-qK.js → relation-many-picker-BJhaEqxz.js} +210 -107
- package/dist/relation-many-picker-BJhaEqxz.js.map +1 -0
- package/dist/{relation-many-picker-B-NCEUgX.cjs → relation-many-picker-DzuGJpEl.cjs} +218 -115
- package/dist/relation-many-picker-DzuGJpEl.cjs.map +1 -0
- package/dist/{relation-picker-BAY77ivO.js → relation-picker-D-tBBZW_.js} +40 -45
- package/dist/relation-picker-D-tBBZW_.js.map +1 -0
- package/dist/{relation-picker-Da_uhFvA.cjs → relation-picker-DaIMzf2H.cjs} +45 -50
- package/dist/relation-picker-DaIMzf2H.cjs.map +1 -0
- package/dist/{relation-picker-dialog-M0pQaWlp.cjs → relation-picker-dialog-9Vg5vvR1.cjs} +142 -40
- package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +1 -0
- package/dist/{relation-picker-dialog-hA9rYrZB.js → relation-picker-dialog-DoEY8EkH.js} +143 -41
- package/dist/relation-picker-dialog-DoEY8EkH.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-OSQyRA5b.cjs → resource-page-router-C_kGW2o_.cjs} +552 -303
- package/dist/resource-page-router-C_kGW2o_.cjs.map +1 -0
- package/dist/{resource-page-router-T4vS5gbJ.js → resource-page-router-Diw6S6TK.js} +507 -258
- package/dist/resource-page-router-Diw6S6TK.js.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-C7CiYA4Z.cjs → toaster-BbByOytP.cjs} +72 -80
- package/dist/toaster-BbByOytP.cjs.map +1 -0
- package/dist/{toaster-CfCRLgR-.js → toaster-Ct_YHGs6.js} +66 -68
- package/dist/toaster-Ct_YHGs6.js.map +1 -0
- package/dist/{use-dialog-filter-state-BDcgS5Oz.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-BBCC0OEK.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
- package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
- package/dist/use-theme-DFlpXils.cjs.map +1 -1
- package/dist/use-theme-dnE3Od3I.js.map +1 -1
- 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-CX2PBu6l.js +0 -63
- package/dist/candidates-gate-CX2PBu6l.js.map +0 -1
- package/dist/candidates-gate-DiFI52r7.cjs +0 -70
- package/dist/candidates-gate-DiFI52r7.cjs.map +0 -1
- package/dist/candidates-relation-picker-CBsVcnPR.js +0 -82
- package/dist/candidates-relation-picker-CBsVcnPR.js.map +0 -1
- package/dist/candidates-relation-picker-Dd_GVLlu.cjs +0 -84
- package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +0 -1
- package/dist/check-confirm-dialog-BRByTFpg.cjs.map +0 -1
- package/dist/check-confirm-dialog-CkaVTPT9.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-B3mZFL-K.cjs.map +0 -1
- package/dist/filter-builder-DOnaXNfP.js.map +0 -1
- package/dist/flow-runtime-B6zOHYqI.cjs.map +0 -1
- package/dist/flow-runtime-D8h99FSg.js.map +0 -1
- package/dist/flow-screen-CX05b3G9.cjs.map +0 -1
- package/dist/flow-screen-CmbARSqg.js.map +0 -1
- package/dist/inline-flow-host-B7U1OJUe.cjs.map +0 -1
- package/dist/inline-flow-host-C3H2UpSA.js.map +0 -1
- package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +0 -14
- package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +0 -1
- package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +0 -19
- package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +0 -1
- package/dist/page-flow-route-CQ7HsbBm.cjs.map +0 -1
- package/dist/page-flow-route-CyXSvXSE.js.map +0 -1
- package/dist/peek-filter-CnqHwTMU.cjs +0 -51
- package/dist/peek-filter-CnqHwTMU.cjs.map +0 -1
- package/dist/peek-filter-ErLfO153.js +0 -28
- package/dist/peek-filter-ErLfO153.js.map +0 -1
- package/dist/place-node--GdsP688.js.map +0 -1
- package/dist/place-node-SIp4XYQH.cjs.map +0 -1
- package/dist/related-list-timeline-BYJKEbmA.cjs.map +0 -1
- package/dist/related-list-timeline-DEdfd-rr.js.map +0 -1
- package/dist/related-rows-B4levHcR.js.map +0 -1
- package/dist/related-rows-zh5f_4QR.cjs.map +0 -1
- package/dist/relation-create-BOaUe12G.cjs +0 -362
- package/dist/relation-create-BOaUe12G.cjs.map +0 -1
- package/dist/relation-create-Bg-eEJLs.js +0 -337
- package/dist/relation-create-Bg-eEJLs.js.map +0 -1
- package/dist/relation-many-picker-B-NCEUgX.cjs.map +0 -1
- package/dist/relation-many-picker-gdAOD-qK.js.map +0 -1
- package/dist/relation-picker-BAY77ivO.js.map +0 -1
- package/dist/relation-picker-Da_uhFvA.cjs.map +0 -1
- package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +0 -1
- package/dist/relation-picker-dialog-hA9rYrZB.js.map +0 -1
- package/dist/resource-page-router-OSQyRA5b.cjs.map +0 -1
- package/dist/resource-page-router-T4vS5gbJ.js.map +0 -1
- package/dist/search-access-B7G5oR8n.cjs.map +0 -1
- package/dist/search-access-CURsWn-U.js.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-C7CiYA4Z.cjs.map +0 -1
- package/dist/toaster-CfCRLgR-.js.map +0 -1
- package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +0 -1
- package/dist/use-dialog-filter-state-BDcgS5Oz.js.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");
|
|
@@ -12,6 +13,521 @@ let react_jsx_runtime = require("react/jsx-runtime");
|
|
|
12
13
|
let class_variance_authority = require("class-variance-authority");
|
|
13
14
|
let _radix_ui_react_select = require("@radix-ui/react-select");
|
|
14
15
|
_radix_ui_react_select = require_use_theme.__toESM(_radix_ui_react_select, 1);
|
|
16
|
+
//#region src/layout/language-storage.ts
|
|
17
|
+
function loadLocale(storageKey = _burojs_react.DEFAULT_LANGUAGE_STORAGE_KEY) {
|
|
18
|
+
if (typeof window === "undefined") return void 0;
|
|
19
|
+
try {
|
|
20
|
+
return window.localStorage.getItem(storageKey) ?? void 0;
|
|
21
|
+
} catch {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function saveLocale(code, storageKey = _burojs_react.DEFAULT_LANGUAGE_STORAGE_KEY) {
|
|
26
|
+
if (typeof window === "undefined") return;
|
|
27
|
+
try {
|
|
28
|
+
window.localStorage.setItem(storageKey, code);
|
|
29
|
+
} catch {}
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/fields/legacy-field.ts
|
|
33
|
+
const STRING_ITEM = Object.freeze({ type: "string" });
|
|
34
|
+
const LEGACY_KIND_DECLARATIONS = Object.freeze({
|
|
35
|
+
string: { type: "string" },
|
|
36
|
+
text: {
|
|
37
|
+
type: "string",
|
|
38
|
+
format: "text"
|
|
39
|
+
},
|
|
40
|
+
textarea: {
|
|
41
|
+
type: "string",
|
|
42
|
+
format: "textarea"
|
|
43
|
+
},
|
|
44
|
+
code: {
|
|
45
|
+
type: "string",
|
|
46
|
+
format: "code"
|
|
47
|
+
},
|
|
48
|
+
email: {
|
|
49
|
+
type: "string",
|
|
50
|
+
format: "email"
|
|
51
|
+
},
|
|
52
|
+
url: {
|
|
53
|
+
type: "string",
|
|
54
|
+
format: "url"
|
|
55
|
+
},
|
|
56
|
+
uuid: {
|
|
57
|
+
type: "string",
|
|
58
|
+
format: "uuid"
|
|
59
|
+
},
|
|
60
|
+
number: { type: "number" },
|
|
61
|
+
boolean: { type: "boolean" },
|
|
62
|
+
date: {
|
|
63
|
+
type: "string",
|
|
64
|
+
format: "date"
|
|
65
|
+
},
|
|
66
|
+
dateTime: {
|
|
67
|
+
type: "string",
|
|
68
|
+
format: "date-time"
|
|
69
|
+
},
|
|
70
|
+
enum: {
|
|
71
|
+
type: "string",
|
|
72
|
+
format: "enum"
|
|
73
|
+
},
|
|
74
|
+
json: {
|
|
75
|
+
type: "object",
|
|
76
|
+
format: "json"
|
|
77
|
+
},
|
|
78
|
+
richText: {
|
|
79
|
+
type: "string",
|
|
80
|
+
format: "rich-text"
|
|
81
|
+
},
|
|
82
|
+
file: {
|
|
83
|
+
type: "array",
|
|
84
|
+
format: "file",
|
|
85
|
+
items: STRING_ITEM
|
|
86
|
+
},
|
|
87
|
+
relation: { type: "relation" },
|
|
88
|
+
relationMany: {
|
|
89
|
+
type: "array",
|
|
90
|
+
format: "relation",
|
|
91
|
+
items: STRING_ITEM
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const SEMANTIC_KEYS = Object.freeze([
|
|
95
|
+
"type",
|
|
96
|
+
"format",
|
|
97
|
+
"meta",
|
|
98
|
+
"required",
|
|
99
|
+
"nullable",
|
|
100
|
+
"empty",
|
|
101
|
+
"default",
|
|
102
|
+
"constraints",
|
|
103
|
+
"texts",
|
|
104
|
+
"options",
|
|
105
|
+
"items",
|
|
106
|
+
"properties",
|
|
107
|
+
"additionalProperties",
|
|
108
|
+
"variants"
|
|
109
|
+
]);
|
|
110
|
+
function ownData(value, key) {
|
|
111
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return { present: false };
|
|
112
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
113
|
+
if (descriptor === void 0 || !Object.prototype.propertyIsEnumerable.call(value, key) || !("value" in descriptor)) return { present: false };
|
|
114
|
+
return {
|
|
115
|
+
present: true,
|
|
116
|
+
value: descriptor.value
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function ownString(value, key) {
|
|
120
|
+
const candidate = ownData(value, key).value;
|
|
121
|
+
return typeof candidate === "string" && candidate.length > 0 ? candidate : void 0;
|
|
122
|
+
}
|
|
123
|
+
function ownSelection(value, key) {
|
|
124
|
+
const candidate = ownData(value, key).value;
|
|
125
|
+
if (typeof candidate === "string") return candidate.length > 0 ? candidate : void 0;
|
|
126
|
+
return candidate !== null && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : void 0;
|
|
127
|
+
}
|
|
128
|
+
function projectUiSelection(input) {
|
|
129
|
+
const selection = {};
|
|
130
|
+
const inputId = ownSelection(input, "input");
|
|
131
|
+
const displayId = ownSelection(input, "display");
|
|
132
|
+
if (inputId !== void 0) selection.input = inputId;
|
|
133
|
+
if (displayId !== void 0) selection.display = displayId;
|
|
134
|
+
return inputId === void 0 && displayId === void 0 ? void 0 : Object.freeze(selection);
|
|
135
|
+
}
|
|
136
|
+
function projectFieldDeclaration(input) {
|
|
137
|
+
const type = ownString(input, "type");
|
|
138
|
+
if (type === void 0) return void 0;
|
|
139
|
+
const projected = { type };
|
|
140
|
+
for (const key of SEMANTIC_KEYS) {
|
|
141
|
+
if (key === "type" || key === "items" || key === "properties" || key === "variants") continue;
|
|
142
|
+
const candidate = ownData(input, key);
|
|
143
|
+
if (candidate.present && candidate.value !== void 0) projected[key] = candidate.value;
|
|
144
|
+
}
|
|
145
|
+
const ui = projectUiSelection(ownData(input, "ui").value);
|
|
146
|
+
if (ui !== void 0) projected.ui = ui;
|
|
147
|
+
if (type === "array") {
|
|
148
|
+
const item = projectFieldDeclaration(ownData(input, "items").value);
|
|
149
|
+
if (item !== void 0) projected.items = item;
|
|
150
|
+
}
|
|
151
|
+
if (type === "object") {
|
|
152
|
+
const properties = ownData(input, "properties").value;
|
|
153
|
+
if (properties !== null && typeof properties === "object" && !Array.isArray(properties)) {
|
|
154
|
+
const output = {};
|
|
155
|
+
for (const key of Object.keys(properties)) {
|
|
156
|
+
const child = projectFieldDeclaration(ownData(properties, key).value);
|
|
157
|
+
if (child !== void 0) output[key] = child;
|
|
158
|
+
}
|
|
159
|
+
projected.properties = Object.freeze(output);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (type === "union") {
|
|
163
|
+
const variants = ownData(input, "variants").value;
|
|
164
|
+
if (Array.isArray(variants)) {
|
|
165
|
+
const output = [];
|
|
166
|
+
for (let index = 0; index < variants.length; index += 1) {
|
|
167
|
+
const child = projectFieldDeclaration(ownData(variants, index).value);
|
|
168
|
+
if (child !== void 0) output.push(child);
|
|
169
|
+
}
|
|
170
|
+
projected.variants = Object.freeze(output);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return Object.freeze(projected);
|
|
174
|
+
}
|
|
175
|
+
function projectUiHints(input) {
|
|
176
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) return void 0;
|
|
177
|
+
const projected = {};
|
|
178
|
+
for (const key of Object.keys(input)) {
|
|
179
|
+
const candidate = ownData(input, key);
|
|
180
|
+
if (candidate.present) projected[key] = candidate.value;
|
|
181
|
+
}
|
|
182
|
+
return Object.freeze(projected);
|
|
183
|
+
}
|
|
184
|
+
function enumValueOptions(field) {
|
|
185
|
+
const own = ownData(field, "values").value;
|
|
186
|
+
const values = Array.isArray(own) ? own : ownData(ownData(field, "ui").value, "values").value;
|
|
187
|
+
if (!Array.isArray(values)) return void 0;
|
|
188
|
+
const options = values.filter((value) => typeof value === "string").map((value) => Object.freeze({ value }));
|
|
189
|
+
return options.length === 0 ? void 0 : Object.freeze(options);
|
|
190
|
+
}
|
|
191
|
+
function lowerLegacyField(field) {
|
|
192
|
+
const declaration = projectFieldDeclaration(ownData(field, "declaration").value);
|
|
193
|
+
if (declaration !== void 0) return declaration;
|
|
194
|
+
const direct = projectFieldDeclaration(field);
|
|
195
|
+
const kind = ownString(field, "kind");
|
|
196
|
+
const mapping = kind === void 0 ? void 0 : LEGACY_KIND_DECLARATIONS[kind];
|
|
197
|
+
if (direct !== void 0) {
|
|
198
|
+
const format = direct.format ?? mapping?.format ?? kind;
|
|
199
|
+
return format === void 0 ? direct : Object.freeze({
|
|
200
|
+
...direct,
|
|
201
|
+
format
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
const ui = projectUiHints(ownData(field, "ui").value);
|
|
205
|
+
const type = kind === "file" && ui?.multiple !== true ? "unknown" : mapping?.type ?? "unknown";
|
|
206
|
+
const format = ownString(field, "format") ?? mapping?.format ?? kind;
|
|
207
|
+
const items = type === "array" ? projectFieldDeclaration(ownData(field, "items").value) ?? mapping?.items ?? STRING_ITEM : void 0;
|
|
208
|
+
const meta = ownData(field, "meta");
|
|
209
|
+
const texts = ownData(field, "texts");
|
|
210
|
+
const options = kind === "enum" ? enumValueOptions(field) : void 0;
|
|
211
|
+
const required = ownData(field, "required");
|
|
212
|
+
const nullable = ownData(field, "nullable");
|
|
213
|
+
const opts = ownData(field, "opts").value;
|
|
214
|
+
const optionRequired = ownData(opts, "required");
|
|
215
|
+
const optionNullable = ownData(opts, "nullable");
|
|
216
|
+
const requiredValue = required.present ? required.value : optionRequired.value;
|
|
217
|
+
const nullableValue = nullable.present ? nullable.value : optionNullable.value;
|
|
218
|
+
return Object.freeze({
|
|
219
|
+
type,
|
|
220
|
+
...format === void 0 ? {} : { format },
|
|
221
|
+
...items === void 0 ? {} : { items },
|
|
222
|
+
...meta.present && meta.value !== void 0 ? { meta: meta.value } : {},
|
|
223
|
+
...options === void 0 ? {} : { options },
|
|
224
|
+
...texts.present && texts.value !== void 0 ? { texts: texts.value } : {},
|
|
225
|
+
...requiredValue === true ? { required: true } : {},
|
|
226
|
+
...nullableValue === true ? { nullable: true } : {}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function lowerLegacyFieldSource(field) {
|
|
230
|
+
const declaration = lowerLegacyField(field);
|
|
231
|
+
const ui = projectUiHints(ownData(field, "ui").value);
|
|
232
|
+
if (ui === void 0) return declaration;
|
|
233
|
+
return Object.freeze({
|
|
234
|
+
...declaration,
|
|
235
|
+
ui
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function fieldDescription(field) {
|
|
239
|
+
const declaration = field?.declaration;
|
|
240
|
+
return (0, _burojs_core.declaredText)("field", declaration, "description") ?? (0, _burojs_core.declaredText)("field", field, "description");
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region src/fields/resolved-field.tsx
|
|
244
|
+
const EMPTY = Object.freeze({});
|
|
245
|
+
const EMPTY_ISSUES = Object.freeze([]);
|
|
246
|
+
const EMPTY_OPTIONS = Object.freeze([]);
|
|
247
|
+
function canonical(field) {
|
|
248
|
+
return lowerLegacyField(field);
|
|
249
|
+
}
|
|
250
|
+
function useLoweredField(source) {
|
|
251
|
+
return (0, react.useMemo)(() => {
|
|
252
|
+
const sourceAtEdge = lowerLegacyFieldSource(source);
|
|
253
|
+
return {
|
|
254
|
+
sourceAtEdge,
|
|
255
|
+
field: canonical(sourceAtEdge),
|
|
256
|
+
ui: sourceAtEdge.ui ?? EMPTY
|
|
257
|
+
};
|
|
258
|
+
}, [source]);
|
|
259
|
+
}
|
|
260
|
+
const warnedObjectLabels = new Set();
|
|
261
|
+
function optionsFor(field, name) {
|
|
262
|
+
if (Array.isArray(field.options)) return field.options;
|
|
263
|
+
const candidate = field.meta?.options;
|
|
264
|
+
if (!Array.isArray(candidate)) return EMPTY_OPTIONS;
|
|
265
|
+
const output = [];
|
|
266
|
+
for (const item of candidate) {
|
|
267
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) continue;
|
|
268
|
+
const raw = item;
|
|
269
|
+
if (typeof raw.value !== "string" && typeof raw.value !== "number" && typeof raw.value !== "boolean" && raw.value !== null) continue;
|
|
270
|
+
const { value, label, description, ...legacyMeta } = raw;
|
|
271
|
+
if (typeof label !== "string" && process.env.NODE_ENV !== "production" && !warnedObjectLabels.has(`${name}:${value}`)) {
|
|
272
|
+
warnedObjectLabels.add(`${name}:${value}`);
|
|
273
|
+
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).`);
|
|
274
|
+
}
|
|
275
|
+
output.push(Object.freeze({
|
|
276
|
+
value,
|
|
277
|
+
label: typeof label === "string" ? label : String(value),
|
|
278
|
+
...typeof description === "string" ? { description } : {},
|
|
279
|
+
...Object.keys(legacyMeta).length === 0 ? {} : { meta: Object.freeze(legacyMeta) }
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
return Object.freeze(output);
|
|
283
|
+
}
|
|
284
|
+
function useContextOptions(field, name, meta, ui, resource) {
|
|
285
|
+
const legacy = field.meta?.options;
|
|
286
|
+
const options = (0, react.useMemo)(() => optionsFor(field, name), [
|
|
287
|
+
field.options,
|
|
288
|
+
legacy,
|
|
289
|
+
name
|
|
290
|
+
]);
|
|
291
|
+
return (0, _burojs_react.useResolvedFieldOptions)({
|
|
292
|
+
name,
|
|
293
|
+
meta,
|
|
294
|
+
ui,
|
|
295
|
+
texts: field.texts
|
|
296
|
+
}, options, resource.id);
|
|
297
|
+
}
|
|
298
|
+
function useContextTexts(field, name, resolved, resource) {
|
|
299
|
+
return (0, _burojs_react.useImplementationTexts)({
|
|
300
|
+
fieldName: name,
|
|
301
|
+
fieldTexts: field.texts,
|
|
302
|
+
id: resolved.id,
|
|
303
|
+
implementation: resolved.implementation
|
|
304
|
+
}, resource.id);
|
|
305
|
+
}
|
|
306
|
+
function useFieldRuntimeContext(resource, record, values, metaSources) {
|
|
307
|
+
const locale = (0, _burojs_react.useLocale)();
|
|
308
|
+
const caps = (0, _burojs_react.useI18nCaps)((0, _burojs_core.canonicalResourceKey)(resource));
|
|
309
|
+
const metaSourcesOut = (0, _burojs_react.useFieldMetaSources)({
|
|
310
|
+
record,
|
|
311
|
+
values,
|
|
312
|
+
extra: metaSources
|
|
313
|
+
});
|
|
314
|
+
const scopeState = metaSourcesOut.scope;
|
|
315
|
+
const scope = scopeState === void 0 ? void 0 : (0, _burojs_react.scopeValueOf)(scopeState);
|
|
316
|
+
return (0, react.useMemo)(() => Object.freeze({
|
|
317
|
+
i18n: Object.freeze({
|
|
318
|
+
locale,
|
|
319
|
+
has: caps.has,
|
|
320
|
+
t: caps.t
|
|
321
|
+
}),
|
|
322
|
+
sources: Object.freeze({
|
|
323
|
+
record: record ?? EMPTY,
|
|
324
|
+
values: values ?? EMPTY,
|
|
325
|
+
scope: scope ?? EMPTY
|
|
326
|
+
}),
|
|
327
|
+
metaSources: metaSourcesOut
|
|
328
|
+
}), [
|
|
329
|
+
caps,
|
|
330
|
+
locale,
|
|
331
|
+
record,
|
|
332
|
+
scope,
|
|
333
|
+
values,
|
|
334
|
+
metaSourcesOut
|
|
335
|
+
]);
|
|
336
|
+
}
|
|
337
|
+
function useFieldMetaDiagnostic(state, resource, name, field, surface, entry) {
|
|
338
|
+
const reported = (0, react.useRef)(void 0);
|
|
339
|
+
const reason = state.status === "failed" ? state.reason : void 0;
|
|
340
|
+
(0, react.useEffect)(() => {
|
|
341
|
+
if (reason === void 0 || reported.current === reason || process.env.NODE_ENV === "production") return;
|
|
342
|
+
reported.current = reason;
|
|
343
|
+
const implementation = (0, _burojs_core.resolveSurfaceUi)(field, surface, entry).use ?? field.format ?? field.type;
|
|
344
|
+
console.error(`[burojs] field.meta-invalid: ${(0, _burojs_core.formatEntityRef)(resource)}.${name} (${implementation}): ${reason}`);
|
|
345
|
+
}, [
|
|
346
|
+
reason,
|
|
347
|
+
resource,
|
|
348
|
+
name,
|
|
349
|
+
field,
|
|
350
|
+
surface,
|
|
351
|
+
entry
|
|
352
|
+
]);
|
|
353
|
+
}
|
|
354
|
+
function MetaPlaceholder({ state }) {
|
|
355
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
356
|
+
if (state.status === "pending") return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
|
|
357
|
+
"data-buro-skeleton": "",
|
|
358
|
+
"data-buro-field-meta": "pending",
|
|
359
|
+
className: "h-9 w-full"
|
|
360
|
+
});
|
|
361
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
362
|
+
role: "alert",
|
|
363
|
+
"data-buro-field-meta": "failed",
|
|
364
|
+
className: "rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground",
|
|
365
|
+
children: t("field.misconfigured", { defaultValue: "This field is misconfigured" })
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function useFieldImplementationDiagnostic(diagnostic) {
|
|
369
|
+
const reported = (0, react.useRef)(void 0);
|
|
370
|
+
(0, react.useEffect)(() => {
|
|
371
|
+
if (diagnostic === void 0 || reported.current === diagnostic || process.env.NODE_ENV === "production") return;
|
|
372
|
+
reported.current = diagnostic;
|
|
373
|
+
console.warn("[buro/ui-shadcn] missing-field-implementation; rendering fallback.", diagnostic);
|
|
374
|
+
}, [diagnostic]);
|
|
375
|
+
}
|
|
376
|
+
function ResolvedFieldDisplay({ resource, name, field: source, value, record, testId, fallback, presentation, metaSources, uiSurface = "display", columnEntry }) {
|
|
377
|
+
const { sourceAtEdge, field, ui } = useLoweredField(source);
|
|
378
|
+
const surfaceField = (0, react.useMemo)(() => sourceAtEdge.ui === void 0 ? field : Object.freeze({
|
|
379
|
+
...field,
|
|
380
|
+
ui
|
|
381
|
+
}), [
|
|
382
|
+
sourceAtEdge,
|
|
383
|
+
field,
|
|
384
|
+
ui
|
|
385
|
+
]);
|
|
386
|
+
const resolved = (0, _burojs_react.useFieldImplementation)({
|
|
387
|
+
field: surfaceField,
|
|
388
|
+
surface: "display",
|
|
389
|
+
uiSurface,
|
|
390
|
+
...columnEntry === void 0 ? {} : { uiEntry: columnEntry }
|
|
391
|
+
});
|
|
392
|
+
const runtimeContext = useFieldRuntimeContext(resource, record, record, metaSources);
|
|
393
|
+
const metaState = (0, _burojs_react.useFieldMeta)(field, resolved.implementation, runtimeContext.metaSources, resolved.params);
|
|
394
|
+
const textField = (0, react.useMemo)(() => Object.freeze({
|
|
395
|
+
...surfaceField,
|
|
396
|
+
name
|
|
397
|
+
}), [surfaceField, name]);
|
|
398
|
+
const text = (0, _burojs_react.useFieldDisplayText)(textField, value, {
|
|
399
|
+
surface: uiSurface,
|
|
400
|
+
...columnEntry === void 0 ? {} : { entry: columnEntry },
|
|
401
|
+
resource: (0, _burojs_core.canonicalResourceKey)(resource)
|
|
402
|
+
});
|
|
403
|
+
const options = useContextOptions(field, name, metaState.status === "ready" ? metaState.meta : void 0, ui, resource);
|
|
404
|
+
const texts = useContextTexts(field, name, resolved, resource);
|
|
405
|
+
useFieldMetaDiagnostic(metaState, resource, name, surfaceField, uiSurface, columnEntry);
|
|
406
|
+
useFieldImplementationDiagnostic(resolved.diagnostic);
|
|
407
|
+
if (resolved.Component === void 0) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: fallback });
|
|
408
|
+
if (metaState.status !== "ready") return (0, react_jsx_runtime.jsx)(MetaPlaceholder, { state: metaState });
|
|
409
|
+
const Component = resolved.Component;
|
|
410
|
+
const context = {
|
|
411
|
+
owner: resource,
|
|
412
|
+
resource,
|
|
413
|
+
field,
|
|
414
|
+
path: Object.freeze([name]),
|
|
415
|
+
surface: "display",
|
|
416
|
+
presentation: presentation ?? "default",
|
|
417
|
+
record,
|
|
418
|
+
meta: metaState.meta,
|
|
419
|
+
ui,
|
|
420
|
+
options,
|
|
421
|
+
texts,
|
|
422
|
+
...text === void 0 ? {} : { text },
|
|
423
|
+
i18n: runtimeContext.i18n,
|
|
424
|
+
sources: runtimeContext.sources,
|
|
425
|
+
pending: false,
|
|
426
|
+
touched: false,
|
|
427
|
+
issues: EMPTY_ISSUES,
|
|
428
|
+
accessibility: EMPTY,
|
|
429
|
+
testIds: testId === void 0 ? EMPTY : Object.freeze({ display: testId })
|
|
430
|
+
};
|
|
431
|
+
if (resolved.multiple) return (0, react.createElement)(Component, {
|
|
432
|
+
...context,
|
|
433
|
+
multiple: true,
|
|
434
|
+
value: Array.isArray(value) ? value : []
|
|
435
|
+
});
|
|
436
|
+
return (0, react.createElement)(Component, {
|
|
437
|
+
...context,
|
|
438
|
+
multiple: false,
|
|
439
|
+
value
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
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, link, metaSources, fallback }) {
|
|
443
|
+
const { sourceAtEdge, field: base } = useLoweredField(source);
|
|
444
|
+
const field = (0, react.useMemo)(() => required === void 0 || required === base.required ? base : Object.freeze({
|
|
445
|
+
...base,
|
|
446
|
+
required
|
|
447
|
+
}), [base, required]);
|
|
448
|
+
const ui = (0, react.useMemo)(() => Object.freeze({
|
|
449
|
+
...sourceAtEdge.ui ?? EMPTY,
|
|
450
|
+
...placeholder === void 0 ? {} : { placeholder }
|
|
451
|
+
}), [sourceAtEdge, placeholder]);
|
|
452
|
+
const inputField = (0, react.useMemo)(() => ({
|
|
453
|
+
...field,
|
|
454
|
+
ui
|
|
455
|
+
}), [field, ui]);
|
|
456
|
+
const resolved = (0, _burojs_react.useFieldImplementation)({
|
|
457
|
+
field: inputField,
|
|
458
|
+
surface: "input"
|
|
459
|
+
});
|
|
460
|
+
const runtimeContext = useFieldRuntimeContext(resource, record, form, metaSources);
|
|
461
|
+
const metaState = (0, _burojs_react.useFieldMeta)(field, resolved.implementation, runtimeContext.metaSources, resolved.params);
|
|
462
|
+
const options = useContextOptions(field, name, metaState.status === "ready" ? metaState.meta : void 0, ui, resource);
|
|
463
|
+
const texts = useContextTexts(field, name, resolved, resource);
|
|
464
|
+
useFieldMetaDiagnostic(metaState, resource, name, inputField, "input");
|
|
465
|
+
useFieldImplementationDiagnostic(resolved.diagnostic);
|
|
466
|
+
if (resolved.Component === void 0) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: fallback });
|
|
467
|
+
if (metaState.status !== "ready") return (0, react_jsx_runtime.jsx)(MetaPlaceholder, { state: metaState });
|
|
468
|
+
const Component = resolved.Component;
|
|
469
|
+
const issues = suppliedIssues ?? (errorMessage == null ? EMPTY_ISSUES : Object.freeze([Object.freeze({
|
|
470
|
+
code: "ui.field-error",
|
|
471
|
+
message: {
|
|
472
|
+
key: "ui.field-error",
|
|
473
|
+
default: errorMessage
|
|
474
|
+
},
|
|
475
|
+
path: Object.freeze([]),
|
|
476
|
+
source: "field",
|
|
477
|
+
severity: "error"
|
|
478
|
+
})]));
|
|
479
|
+
const context = {
|
|
480
|
+
owner: resource,
|
|
481
|
+
resource,
|
|
482
|
+
field,
|
|
483
|
+
path: Object.freeze([name]),
|
|
484
|
+
surface: "input",
|
|
485
|
+
presentation: "default",
|
|
486
|
+
record,
|
|
487
|
+
form,
|
|
488
|
+
meta: metaState.meta,
|
|
489
|
+
ui,
|
|
490
|
+
options,
|
|
491
|
+
texts,
|
|
492
|
+
i18n: runtimeContext.i18n,
|
|
493
|
+
sources: runtimeContext.sources,
|
|
494
|
+
pending,
|
|
495
|
+
touched,
|
|
496
|
+
issues,
|
|
497
|
+
accessibility: Object.freeze({
|
|
498
|
+
input: inputId ?? name,
|
|
499
|
+
label: labelId,
|
|
500
|
+
description: descriptionId,
|
|
501
|
+
error: errorId
|
|
502
|
+
}),
|
|
503
|
+
testIds: testId === void 0 ? EMPTY : Object.freeze({ input: testId })
|
|
504
|
+
};
|
|
505
|
+
if (resolved.multiple) return (0, react.createElement)(Component, {
|
|
506
|
+
...context,
|
|
507
|
+
multiple: true,
|
|
508
|
+
value: Array.isArray(value) ? value : [],
|
|
509
|
+
onChange,
|
|
510
|
+
onBlur,
|
|
511
|
+
disabled,
|
|
512
|
+
relationSeeds,
|
|
513
|
+
fixedFilters,
|
|
514
|
+
link,
|
|
515
|
+
metaSources: runtimeContext.metaSources
|
|
516
|
+
});
|
|
517
|
+
return (0, react.createElement)(Component, {
|
|
518
|
+
...context,
|
|
519
|
+
multiple: false,
|
|
520
|
+
value,
|
|
521
|
+
onChange,
|
|
522
|
+
onBlur,
|
|
523
|
+
disabled,
|
|
524
|
+
relationSeeds,
|
|
525
|
+
fixedFilters,
|
|
526
|
+
link,
|
|
527
|
+
metaSources: runtimeContext.metaSources
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
//#endregion
|
|
15
531
|
//#region src/primitives/badge.tsx
|
|
16
532
|
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", {
|
|
17
533
|
variants: { variant: {
|
|
@@ -89,11 +605,11 @@ const SelectGroup = _radix_ui_react_select.Group;
|
|
|
89
605
|
const SelectValue = _radix_ui_react_select.Value;
|
|
90
606
|
const SelectTrigger = react.forwardRef(({ className, children, ...props }, ref) => (0, react_jsx_runtime.jsxs)(_radix_ui_react_select.Trigger, {
|
|
91
607
|
ref,
|
|
92
|
-
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]:
|
|
608
|
+
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),
|
|
93
609
|
...props,
|
|
94
610
|
children: [children, (0, react_jsx_runtime.jsx)(_radix_ui_react_select.Icon, {
|
|
95
611
|
asChild: true,
|
|
96
|
-
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
612
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, { className: "h-4 w-4 shrink-0 opacity-50" })
|
|
97
613
|
})]
|
|
98
614
|
}));
|
|
99
615
|
SelectTrigger.displayName = _radix_ui_react_select.Trigger.displayName;
|
|
@@ -132,15 +648,24 @@ const SelectLabel = react.forwardRef(({ className, ...props }, ref) => (0, react
|
|
|
132
648
|
...props
|
|
133
649
|
}));
|
|
134
650
|
SelectLabel.displayName = _radix_ui_react_select.Label.displayName;
|
|
135
|
-
const SelectItem = react.forwardRef(({ className, children, ...props }, ref) =>
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
142
|
-
|
|
143
|
-
}))
|
|
651
|
+
const SelectItem = react.forwardRef(({ className, children, description, ...props }, ref) => {
|
|
652
|
+
const hasDescription = description !== void 0 && description !== null;
|
|
653
|
+
return (0, react_jsx_runtime.jsxs)(_radix_ui_react_select.Item, {
|
|
654
|
+
ref,
|
|
655
|
+
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),
|
|
656
|
+
...props,
|
|
657
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
658
|
+
className: require_use_theme.cn("absolute left-2 flex h-3.5 w-3.5 items-center justify-center", hasDescription && "top-[9px]"),
|
|
659
|
+
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" }) })
|
|
660
|
+
}), !hasDescription ? (0, react_jsx_runtime.jsx)(_radix_ui_react_select.ItemText, { children }) : (0, react_jsx_runtime.jsxs)("span", {
|
|
661
|
+
className: "flex min-w-0 flex-col gap-0.5",
|
|
662
|
+
children: [(0, react_jsx_runtime.jsx)(_radix_ui_react_select.ItemText, { children }), (0, react_jsx_runtime.jsx)("span", {
|
|
663
|
+
className: "text-xs leading-snug text-muted-foreground",
|
|
664
|
+
children: description
|
|
665
|
+
})]
|
|
666
|
+
})]
|
|
667
|
+
});
|
|
668
|
+
});
|
|
144
669
|
SelectItem.displayName = _radix_ui_react_select.Item.displayName;
|
|
145
670
|
const SelectSeparator = react.forwardRef(({ className, ...props }, ref) => (0, react_jsx_runtime.jsx)(_radix_ui_react_select.Separator, {
|
|
146
671
|
ref,
|
|
@@ -150,13 +675,8 @@ const SelectSeparator = react.forwardRef(({ className, ...props }, ref) => (0, r
|
|
|
150
675
|
SelectSeparator.displayName = _radix_ui_react_select.Separator.displayName;
|
|
151
676
|
//#endregion
|
|
152
677
|
//#region src/fields/format.ts
|
|
153
|
-
const LOCALE_TAG = {
|
|
154
|
-
ru: "ru-RU",
|
|
155
|
-
en: "en-US"
|
|
156
|
-
};
|
|
157
678
|
function localeTag(locale) {
|
|
158
|
-
|
|
159
|
-
return LOCALE_TAG[require_toaster.loadLanguage()] ?? "en-US";
|
|
679
|
+
return locale || loadLocale() || "en-US";
|
|
160
680
|
}
|
|
161
681
|
const dateCache = new Map();
|
|
162
682
|
const dateTimeCache = new Map();
|
|
@@ -198,9 +718,9 @@ function formatNumber(n, locale) {
|
|
|
198
718
|
//#endregion
|
|
199
719
|
//#region src/list-kit/filter-builder/describe-row.ts
|
|
200
720
|
const MAX_DESCRIBE_DEPTH = 2;
|
|
201
|
-
function describeValue(value,
|
|
721
|
+
function describeValue(value, chromeT, spec, formatValue) {
|
|
202
722
|
if (value === void 0) return null;
|
|
203
|
-
if (Array.isArray(value)) return
|
|
723
|
+
if (Array.isArray(value)) return chromeT("filters.selectedCount", { count: value.length }, `${value.length} selected`);
|
|
204
724
|
const optionLabel = spec?.options?.find((o) => o.value === String(value))?.label;
|
|
205
725
|
if (optionLabel !== void 0) return optionLabel;
|
|
206
726
|
if (spec && formatValue) {
|
|
@@ -209,20 +729,20 @@ function describeValue(value, t, spec, formatValue) {
|
|
|
209
729
|
}
|
|
210
730
|
return String(value);
|
|
211
731
|
}
|
|
212
|
-
function describeAt(row, available,
|
|
732
|
+
function describeAt(row, available, chromeT, depth, formatValue) {
|
|
213
733
|
if ((0, _burojs_core.isFilterGroup)(row)) {
|
|
214
734
|
if (depth > MAX_DESCRIBE_DEPTH) return "…";
|
|
215
|
-
const joinLabel =
|
|
216
|
-
return `(${row.rows.map((child) => describeAt(child, available,
|
|
735
|
+
const joinLabel = chromeT(`filters.${row.join}`, void 0, row.join);
|
|
736
|
+
return `(${row.rows.map((child) => describeAt(child, available, chromeT, depth + 1, formatValue)).join(` ${joinLabel} `)})`;
|
|
217
737
|
}
|
|
218
738
|
const spec = available.find((s) => s.field === row.field);
|
|
219
739
|
const label = spec?.label ?? row.field;
|
|
220
|
-
const opLabel =
|
|
221
|
-
const valueText = (0, _burojs_core.opArity)(row.op) === "none" ? null : describeValue(row.value,
|
|
740
|
+
const opLabel = chromeT(`filters.operators.${row.op}`, void 0, row.op);
|
|
741
|
+
const valueText = (0, _burojs_core.opArity)(row.op) === "none" ? null : describeValue(row.value, chromeT, spec, formatValue);
|
|
222
742
|
return valueText === null ? `${label} ${opLabel}` : `${label} ${opLabel} ${valueText}`;
|
|
223
743
|
}
|
|
224
|
-
function describeRow(row, available,
|
|
225
|
-
return describeAt(row, available,
|
|
744
|
+
function describeRow(row, available, chromeT, formatValue) {
|
|
745
|
+
return describeAt(row, available, chromeT, 1, formatValue);
|
|
226
746
|
}
|
|
227
747
|
function relationLabelKey(to, by, value) {
|
|
228
748
|
return `${by === void 0 ? to : `${to}#${by}`}::${value}`;
|
|
@@ -266,15 +786,17 @@ function EnumLabelResolver(props) {
|
|
|
266
786
|
const { enumName, onResolve } = props;
|
|
267
787
|
const { values } = (0, _burojs_react.useEnumValues)(enumName);
|
|
268
788
|
const caps = (0, _burojs_react.useI18nCaps)();
|
|
789
|
+
const def = (0, _burojs_react.useApp)().registry.enums.get(enumName);
|
|
269
790
|
(0, react.useEffect)(() => {
|
|
270
791
|
if (!values) return;
|
|
271
792
|
const labels = {};
|
|
272
|
-
for (const entry of values) labels[entry.value] = (0, _burojs_core.resolveEnumLabel)(caps, enumName, entry.value, entry.label);
|
|
793
|
+
for (const entry of values) labels[entry.value] = (0, _burojs_core.resolveEnumLabel)(caps, enumName, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label);
|
|
273
794
|
onResolve(enumName, labels);
|
|
274
795
|
}, [
|
|
275
796
|
values,
|
|
276
797
|
enumName,
|
|
277
798
|
caps,
|
|
799
|
+
def,
|
|
278
800
|
onResolve
|
|
279
801
|
]);
|
|
280
802
|
return null;
|
|
@@ -283,7 +805,7 @@ function RelationLabelResolver(props) {
|
|
|
283
805
|
const { to, id, by, onResolve } = props;
|
|
284
806
|
const targetDef = (0, _burojs_react.useApp)().registry.get(to);
|
|
285
807
|
const { record } = (0, _burojs_react.useRelatedRecord)(to, id, by === void 0 ? void 0 : { by });
|
|
286
|
-
const rowTitle =
|
|
808
|
+
const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
|
|
287
809
|
(0, react.useEffect)(() => {
|
|
288
810
|
if (!record) return;
|
|
289
811
|
onResolve(relationLabelKey(to, by, id), rowTitle(record));
|
|
@@ -353,15 +875,18 @@ function badgeKey(row, index) {
|
|
|
353
875
|
if ((0, _burojs_core.isFilterGroup)(row)) return `${index}:group:${row.join}`;
|
|
354
876
|
return `${index}:${row.field}:${row.op}`;
|
|
355
877
|
}
|
|
878
|
+
const BADGE_ROW = "inline-flex max-w-full items-center gap-1 align-middle";
|
|
879
|
+
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";
|
|
356
880
|
function FilterBadges(props) {
|
|
357
881
|
const { group, setGroup, available, fixed, testIdBase, onOpenAt, onRemoved, pinnedFields = [], pinnedValue = [], setPinnedValue } = props;
|
|
358
|
-
const
|
|
359
|
-
const
|
|
882
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
883
|
+
const locale = (0, _burojs_react.useOptionalLocale)();
|
|
884
|
+
const tt = (key, params, fallback) => chromeT(key, {
|
|
360
885
|
params,
|
|
361
886
|
...typeof params?.count === "number" ? { count: params.count } : {},
|
|
362
887
|
defaultValue: fallback
|
|
363
888
|
});
|
|
364
|
-
const removeLabel =
|
|
889
|
+
const removeLabel = chromeT("filters.removeRow", { defaultValue: "Remove filter" });
|
|
365
890
|
const { enumLabels, relationLabels, onEnumResolved, onRelationResolved } = useFormatValueMaps();
|
|
366
891
|
const formatValue = (kind, value) => {
|
|
367
892
|
if (kind.kind === "enum") return enumLabels[kind.enumName]?.[String(value)];
|
|
@@ -369,7 +894,7 @@ function FilterBadges(props) {
|
|
|
369
894
|
if (kind.kind === "date") {
|
|
370
895
|
const d = new Date(String(value));
|
|
371
896
|
if (Number.isNaN(d.getTime())) return void 0;
|
|
372
|
-
return kind.time ? formatDateTime(d) : formatDate(d);
|
|
897
|
+
return kind.time ? formatDateTime(d, locale) : formatDate(d, locale);
|
|
373
898
|
}
|
|
374
899
|
};
|
|
375
900
|
const orphanPinned = (0, react.useMemo)(() => {
|
|
@@ -403,49 +928,56 @@ function FilterBadges(props) {
|
|
|
403
928
|
onEnumResolved,
|
|
404
929
|
onRelationResolved
|
|
405
930
|
}),
|
|
406
|
-
group.rows.map((row, index) => (0, react_jsx_runtime.
|
|
931
|
+
group.rows.map((row, index) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
407
932
|
variant: "secondary",
|
|
408
|
-
className: "
|
|
409
|
-
children:
|
|
410
|
-
|
|
411
|
-
"
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
"
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
className:
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
933
|
+
className: "py-1 pr-1",
|
|
934
|
+
children: (0, react_jsx_runtime.jsxs)("span", {
|
|
935
|
+
className: BADGE_ROW,
|
|
936
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
937
|
+
type: "button",
|
|
938
|
+
"data-testid": `${testIdBase}:badge:${index}`,
|
|
939
|
+
onClick: () => onOpenAt([index]),
|
|
940
|
+
className: "min-w-0 cursor-pointer truncate bg-transparent p-0 text-left",
|
|
941
|
+
children: describeRow(row, available, tt, formatValue)
|
|
942
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
943
|
+
type: "button",
|
|
944
|
+
"data-testid": `${testIdBase}:badge:${index}:remove`,
|
|
945
|
+
"aria-label": removeLabel,
|
|
946
|
+
onClick: () => handleRemove(index),
|
|
947
|
+
className: REMOVE_BUTTON,
|
|
948
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
|
|
949
|
+
className: "size-3",
|
|
950
|
+
"aria-hidden": "true"
|
|
951
|
+
})
|
|
952
|
+
})]
|
|
953
|
+
})
|
|
426
954
|
}, badgeKey(row, index))),
|
|
427
955
|
labelledFixed.map((entry, index) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
428
956
|
variant: "outline",
|
|
429
957
|
"data-testid": `${testIdBase}:badge:fixed:${index}`,
|
|
430
958
|
children: entry.label
|
|
431
959
|
}, `fixed-${index}`)),
|
|
432
|
-
orphanPinned.map(({ expr, index }) => (0, react_jsx_runtime.
|
|
960
|
+
orphanPinned.map(({ expr, index }) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
433
961
|
variant: "secondary",
|
|
434
|
-
className: "
|
|
435
|
-
children:
|
|
436
|
-
|
|
437
|
-
children:
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
"
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
962
|
+
className: "py-1 pr-1",
|
|
963
|
+
children: (0, react_jsx_runtime.jsxs)("span", {
|
|
964
|
+
className: BADGE_ROW,
|
|
965
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
966
|
+
"data-testid": `${testIdBase}:badge:pinned:${index}`,
|
|
967
|
+
className: "min-w-0 truncate",
|
|
968
|
+
children: describeRow(expr, available, tt, formatValue)
|
|
969
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
970
|
+
type: "button",
|
|
971
|
+
"data-testid": `${testIdBase}:badge:pinned:${index}:remove`,
|
|
972
|
+
"aria-label": removeLabel,
|
|
973
|
+
onClick: () => handleRemovePinned(index),
|
|
974
|
+
className: REMOVE_BUTTON,
|
|
975
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
|
|
976
|
+
className: "size-3",
|
|
977
|
+
"aria-hidden": "true"
|
|
978
|
+
})
|
|
979
|
+
})]
|
|
980
|
+
})
|
|
449
981
|
}, `pinned-${index}`))
|
|
450
982
|
]
|
|
451
983
|
});
|
|
@@ -635,14 +1167,15 @@ const OPTIONS = ["true", "false"];
|
|
|
635
1167
|
function BooleanValueControl(props) {
|
|
636
1168
|
const { value, onChange, testId, arity, autoFocus, fieldLabel, fill } = props;
|
|
637
1169
|
const t = (0, _burojs_react.useOptionalT)();
|
|
638
|
-
const
|
|
1170
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1171
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
639
1172
|
defaultValue: `Value for ${fieldLabel}`,
|
|
640
1173
|
params: { field: fieldLabel }
|
|
641
|
-
}) :
|
|
1174
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
642
1175
|
const yesLabel = t("boolean.yes", { defaultValue: "Yes" });
|
|
643
1176
|
const noLabel = t("boolean.no", { defaultValue: "No" });
|
|
644
1177
|
const labelOf = (token) => token === "true" ? yesLabel : noLabel;
|
|
645
|
-
const clearLabel =
|
|
1178
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
646
1179
|
const { open, setOpen, selected, select, triggerLabel, clear } = useSelectableValueControl({
|
|
647
1180
|
value,
|
|
648
1181
|
arity,
|
|
@@ -662,12 +1195,12 @@ function BooleanValueControl(props) {
|
|
|
662
1195
|
"data-testid": testId,
|
|
663
1196
|
"aria-label": ariaLabel,
|
|
664
1197
|
className: require_use_theme.cn("h-8 justify-between", fill && "w-full"),
|
|
665
|
-
children: triggerLabel(labelOf, ariaLabel)
|
|
1198
|
+
children: triggerLabel(labelOf, props.placeholder ?? ariaLabel)
|
|
666
1199
|
})
|
|
667
1200
|
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
668
1201
|
className: "w-[140px] p-0",
|
|
669
1202
|
align: "start",
|
|
670
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
1203
|
+
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, {
|
|
671
1204
|
"data-testid": `${testId}:clear`,
|
|
672
1205
|
value: "__clear__",
|
|
673
1206
|
onSelect: () => clear(),
|
|
@@ -677,7 +1210,7 @@ function BooleanValueControl(props) {
|
|
|
677
1210
|
}), clearLabel]
|
|
678
1211
|
}), OPTIONS.map((token) => {
|
|
679
1212
|
const isSelected = selected.has(token);
|
|
680
|
-
return (0, react_jsx_runtime.jsxs)(
|
|
1213
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
681
1214
|
value: labelOf(token),
|
|
682
1215
|
"data-testid": `${testId}:option:${token}`,
|
|
683
1216
|
onSelect: () => select(token),
|
|
@@ -695,12 +1228,13 @@ function BooleanValueControl(props) {
|
|
|
695
1228
|
function SelectListValueControl(props) {
|
|
696
1229
|
const { options, value, onChange, testId, arity, autoFocus, fieldLabel, isLoading = false } = props;
|
|
697
1230
|
const t = (0, _burojs_react.useOptionalT)();
|
|
698
|
-
const
|
|
1231
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1232
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
699
1233
|
defaultValue: `Value for ${fieldLabel}`,
|
|
700
1234
|
params: { field: fieldLabel }
|
|
701
|
-
}) :
|
|
1235
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
702
1236
|
const loadingLabel = t("table.loading", { defaultValue: "Loading…" });
|
|
703
|
-
const clearLabel =
|
|
1237
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
704
1238
|
const labelFor = props.labelFor ?? ((raw) => options.find((o) => o.value === raw)?.label ?? raw);
|
|
705
1239
|
const { open, setOpen, selected, select, triggerLabel, clear } = useSelectableValueControl({
|
|
706
1240
|
value,
|
|
@@ -722,16 +1256,16 @@ function SelectListValueControl(props) {
|
|
|
722
1256
|
className: require_use_theme.cn("h-8 justify-between truncate", props.fill ? "w-full" : "max-w-[200px]"),
|
|
723
1257
|
children: (0, react_jsx_runtime.jsx)("span", {
|
|
724
1258
|
className: "truncate",
|
|
725
|
-
children: isLoading ? loadingLabel : triggerLabel(labelFor, ariaLabel)
|
|
1259
|
+
children: isLoading ? loadingLabel : triggerLabel(labelFor, props.placeholder ?? ariaLabel)
|
|
726
1260
|
})
|
|
727
1261
|
})
|
|
728
1262
|
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
729
1263
|
className: "w-[220px] p-0",
|
|
730
1264
|
align: "start",
|
|
731
|
-
children: (0, react_jsx_runtime.jsxs)(
|
|
1265
|
+
children: (0, react_jsx_runtime.jsxs)(require_relation_create.Command, { children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
|
|
732
1266
|
placeholder: ariaLabel,
|
|
733
1267
|
"data-testid": `${testId}:search`
|
|
734
|
-
}), (0, react_jsx_runtime.jsxs)(
|
|
1268
|
+
}), (0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, { children: [
|
|
735
1269
|
isLoading && (0, react_jsx_runtime.jsxs)("div", {
|
|
736
1270
|
className: "flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground",
|
|
737
1271
|
"data-testid": `${testId}:loading`,
|
|
@@ -740,8 +1274,8 @@ function SelectListValueControl(props) {
|
|
|
740
1274
|
"aria-hidden": "true"
|
|
741
1275
|
}), loadingLabel]
|
|
742
1276
|
}),
|
|
743
|
-
!isLoading && (0, react_jsx_runtime.jsx)(
|
|
744
|
-
!isLoading && (0, react_jsx_runtime.jsxs)(
|
|
1277
|
+
!isLoading && (0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, { children: t("relation.noResults", { defaultValue: "No results." }) }),
|
|
1278
|
+
!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, {
|
|
745
1279
|
"data-testid": `${testId}:clear`,
|
|
746
1280
|
value: "__clear__",
|
|
747
1281
|
onSelect: () => clear(),
|
|
@@ -752,7 +1286,7 @@ function SelectListValueControl(props) {
|
|
|
752
1286
|
}), options.map((entry) => {
|
|
753
1287
|
const isSelected = selected.has(entry.value);
|
|
754
1288
|
const label = labelFor(entry.value);
|
|
755
|
-
return (0, react_jsx_runtime.jsxs)(
|
|
1289
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
756
1290
|
value: label,
|
|
757
1291
|
"data-testid": `${testId}:option:${entry.value}`,
|
|
758
1292
|
onSelect: () => select(entry.value),
|
|
@@ -771,8 +1305,9 @@ function SelectListValueControl(props) {
|
|
|
771
1305
|
function EnumValueControl(props) {
|
|
772
1306
|
const { enumName, value, onChange, testId, arity, autoFocus, fieldLabel, fill } = props;
|
|
773
1307
|
const caps = (0, _burojs_react.useI18nCaps)();
|
|
1308
|
+
const def = (0, _burojs_react.useApp)().registry.enums.get(enumName);
|
|
774
1309
|
const { values, isLoading } = (0, _burojs_react.useEnumValues)(enumName);
|
|
775
|
-
const labelFor = (raw) => (0, _burojs_core.resolveEnumLabel)(caps, enumName, raw, values?.find((v) => v.value === raw)?.label);
|
|
1310
|
+
const labelFor = (raw) => (0, _burojs_core.resolveEnumLabel)(caps, enumName, raw, (0, _burojs_core.enumValueText)(def, raw) ?? values?.find((v) => v.value === raw)?.label);
|
|
776
1311
|
const options = (values ?? []).map((entry) => ({
|
|
777
1312
|
value: entry.value,
|
|
778
1313
|
label: entry.value
|
|
@@ -784,6 +1319,7 @@ function EnumValueControl(props) {
|
|
|
784
1319
|
arity,
|
|
785
1320
|
autoFocus,
|
|
786
1321
|
fieldLabel,
|
|
1322
|
+
placeholder: props.placeholder,
|
|
787
1323
|
options,
|
|
788
1324
|
labelFor,
|
|
789
1325
|
isLoading,
|
|
@@ -795,7 +1331,7 @@ function EnumValueControl(props) {
|
|
|
795
1331
|
function useRelatedLabels(to, ids, by) {
|
|
796
1332
|
const targetDef = (0, _burojs_react.useApp)().registry.get(to);
|
|
797
1333
|
const idField = (targetDef?.data)?.idField;
|
|
798
|
-
const rowTitle =
|
|
1334
|
+
const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
|
|
799
1335
|
const field = by ?? (typeof idField === "string" && idField.length > 0 ? idField : "id");
|
|
800
1336
|
const query = (0, _burojs_react.useList)(to, {
|
|
801
1337
|
pagination: {
|
|
@@ -808,6 +1344,7 @@ function useRelatedLabels(to, ids, by) {
|
|
|
808
1344
|
op: "in",
|
|
809
1345
|
value: ids
|
|
810
1346
|
} } : {},
|
|
1347
|
+
scope: "none",
|
|
811
1348
|
enabled: ids.length > 0
|
|
812
1349
|
});
|
|
813
1350
|
return (0, react.useMemo)(() => {
|
|
@@ -829,6 +1366,7 @@ function RelationValueControl(props) {
|
|
|
829
1366
|
const { to, by, value, onChange, testId, arity, autoFocus, fieldLabel } = props;
|
|
830
1367
|
const app = (0, _burojs_react.useApp)();
|
|
831
1368
|
const t = (0, _burojs_react.useOptionalT)();
|
|
1369
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
832
1370
|
const targetDef = app.registry.get(to);
|
|
833
1371
|
const displayField = targetDef?.displayField ?? "name";
|
|
834
1372
|
const [search, setSearch] = (0, react.useState)("");
|
|
@@ -837,9 +1375,9 @@ function RelationValueControl(props) {
|
|
|
837
1375
|
arity,
|
|
838
1376
|
onChange
|
|
839
1377
|
});
|
|
840
|
-
const rowTitle =
|
|
1378
|
+
const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
|
|
841
1379
|
const access = (0, _burojs_react.useListAccess)(to);
|
|
842
|
-
const searchable = (0, react.useMemo)(() => access.status === "ready" &&
|
|
1380
|
+
const searchable = (0, react.useMemo)(() => access.status === "ready" && require_relation_create.narrowSearchDecl({ fields: [displayField] }, (name) => access.fieldVisible(name)) !== void 0, [access, displayField]);
|
|
843
1381
|
const listQuery = (0, _burojs_react.useList)(to, {
|
|
844
1382
|
pagination: {
|
|
845
1383
|
kind: "offset",
|
|
@@ -851,6 +1389,7 @@ function RelationValueControl(props) {
|
|
|
851
1389
|
op: "contains",
|
|
852
1390
|
value: search.trim()
|
|
853
1391
|
} } : {},
|
|
1392
|
+
scope: "session",
|
|
854
1393
|
enabled: open && access.status === "ready"
|
|
855
1394
|
});
|
|
856
1395
|
const rows = listQuery.data?.data ?? [];
|
|
@@ -866,11 +1405,11 @@ function RelationValueControl(props) {
|
|
|
866
1405
|
if (fromRows) return rowTitle(fromRows);
|
|
867
1406
|
return fallbackLabels[id] ?? id;
|
|
868
1407
|
};
|
|
869
|
-
const ariaLabel = fieldLabel ?
|
|
1408
|
+
const ariaLabel = fieldLabel ? chromeT("filters.valueFor", {
|
|
870
1409
|
defaultValue: `Value for ${fieldLabel}`,
|
|
871
1410
|
params: { field: fieldLabel }
|
|
872
|
-
}) :
|
|
873
|
-
const clearLabel =
|
|
1411
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
1412
|
+
const clearLabel = chromeT("filters.clear", { defaultValue: "Clear" });
|
|
874
1413
|
return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, {
|
|
875
1414
|
open,
|
|
876
1415
|
onOpenChange: setOpen,
|
|
@@ -886,20 +1425,20 @@ function RelationValueControl(props) {
|
|
|
886
1425
|
className: require_use_theme.cn("h-8 justify-between truncate", props.fill ? "w-full" : "max-w-[220px]"),
|
|
887
1426
|
children: (0, react_jsx_runtime.jsx)("span", {
|
|
888
1427
|
className: "truncate",
|
|
889
|
-
children: triggerLabel(labelFor, ariaLabel)
|
|
1428
|
+
children: triggerLabel(labelFor, props.placeholder ?? ariaLabel)
|
|
890
1429
|
})
|
|
891
1430
|
})
|
|
892
1431
|
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
893
1432
|
className: "w-[240px] p-0",
|
|
894
1433
|
align: "start",
|
|
895
|
-
children: (0, react_jsx_runtime.jsxs)(
|
|
1434
|
+
children: (0, react_jsx_runtime.jsxs)(require_relation_create.Command, {
|
|
896
1435
|
shouldFilter: false,
|
|
897
|
-
children: [searchable && (0, react_jsx_runtime.jsx)(
|
|
1436
|
+
children: [searchable && (0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
|
|
898
1437
|
value: search,
|
|
899
1438
|
onValueChange: setSearch,
|
|
900
1439
|
placeholder: ariaLabel,
|
|
901
1440
|
"data-testid": `${testId}:search`
|
|
902
|
-
}), (0, react_jsx_runtime.jsxs)(
|
|
1441
|
+
}), (0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, { children: [
|
|
903
1442
|
listQuery.isLoading && (0, react_jsx_runtime.jsxs)("div", {
|
|
904
1443
|
className: "flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground",
|
|
905
1444
|
"data-testid": `${testId}:loading`,
|
|
@@ -908,8 +1447,8 @@ function RelationValueControl(props) {
|
|
|
908
1447
|
"aria-hidden": "true"
|
|
909
1448
|
}), t("table.loading", { defaultValue: "Loading…" })]
|
|
910
1449
|
}),
|
|
911
|
-
!listQuery.isLoading && rows.length === 0 && (0, react_jsx_runtime.jsx)(
|
|
912
|
-
!listQuery.isLoading && arity === "single" && selected.size > 0 && (0, react_jsx_runtime.jsxs)(
|
|
1450
|
+
!listQuery.isLoading && rows.length === 0 && (0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, { children: t("relation.noResults", { defaultValue: "No results." }) }),
|
|
1451
|
+
!listQuery.isLoading && arity === "single" && selected.size > 0 && (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
913
1452
|
"data-testid": `${testId}:clear`,
|
|
914
1453
|
value: "__clear__",
|
|
915
1454
|
onSelect: () => clear(),
|
|
@@ -923,7 +1462,7 @@ function RelationValueControl(props) {
|
|
|
923
1462
|
if (id === void 0) return null;
|
|
924
1463
|
const label = rowTitle(row);
|
|
925
1464
|
const isSelected = selected.has(id);
|
|
926
|
-
return (0, react_jsx_runtime.jsxs)(
|
|
1465
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
927
1466
|
value: `${label} ${id}`,
|
|
928
1467
|
"data-testid": `${testId}:option:${id}`,
|
|
929
1468
|
onSelect: () => select(id),
|
|
@@ -942,6 +1481,20 @@ function RelationValueControl(props) {
|
|
|
942
1481
|
});
|
|
943
1482
|
}
|
|
944
1483
|
//#endregion
|
|
1484
|
+
//#region src/fields/local-date-time.ts
|
|
1485
|
+
function toLocalDateTimeText(value) {
|
|
1486
|
+
if (value === void 0 || value === null || value === "") return "";
|
|
1487
|
+
const d = value instanceof Date ? value : new Date(String(value));
|
|
1488
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
1489
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
1490
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
1491
|
+
}
|
|
1492
|
+
function fromLocalDateTimeText(text) {
|
|
1493
|
+
if (text === "") return void 0;
|
|
1494
|
+
const d = new Date(text);
|
|
1495
|
+
return Number.isNaN(d.getTime()) ? void 0 : d.toISOString();
|
|
1496
|
+
}
|
|
1497
|
+
//#endregion
|
|
945
1498
|
//#region src/list-kit/filter-builder/values/scalar-value-input.tsx
|
|
946
1499
|
function isDateTime(kind) {
|
|
947
1500
|
return kind.kind === "date" && kind.time === true;
|
|
@@ -954,12 +1507,9 @@ function inputTypeFor(kind) {
|
|
|
954
1507
|
}
|
|
955
1508
|
}
|
|
956
1509
|
function toText(kind, value) {
|
|
1510
|
+
if (isDateTime(kind)) return toLocalDateTimeText(value);
|
|
957
1511
|
if (value === void 0 || value === null || value === "") return "";
|
|
958
|
-
|
|
959
|
-
const d = new Date(String(value));
|
|
960
|
-
if (Number.isNaN(d.getTime())) return "";
|
|
961
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
962
|
-
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
1512
|
+
return String(value);
|
|
963
1513
|
}
|
|
964
1514
|
function parseOne(kind, raw) {
|
|
965
1515
|
if (raw === "") return void 0;
|
|
@@ -967,19 +1517,16 @@ function parseOne(kind, raw) {
|
|
|
967
1517
|
const n = Number(raw);
|
|
968
1518
|
return Number.isFinite(n) ? n : void 0;
|
|
969
1519
|
}
|
|
970
|
-
if (isDateTime(kind))
|
|
971
|
-
const d = new Date(raw);
|
|
972
|
-
return Number.isNaN(d.getTime()) ? void 0 : d.toISOString();
|
|
973
|
-
}
|
|
1520
|
+
if (isDateTime(kind)) return fromLocalDateTimeText(raw);
|
|
974
1521
|
return raw;
|
|
975
1522
|
}
|
|
976
1523
|
function ScalarValueInput(props) {
|
|
977
|
-
const
|
|
1524
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
978
1525
|
const inputType = inputTypeFor(props.kind);
|
|
979
|
-
const ariaLabel = props.fieldLabel ?
|
|
1526
|
+
const ariaLabel = props.fieldLabel ? chromeT("filters.valueFor", {
|
|
980
1527
|
defaultValue: `Value for ${props.fieldLabel}`,
|
|
981
1528
|
params: { field: props.fieldLabel }
|
|
982
|
-
}) :
|
|
1529
|
+
}) : chromeT("filters.value", { defaultValue: "Value" });
|
|
983
1530
|
if (props.arity === "multi") return (0, react_jsx_runtime.jsx)(ScalarMultiInput, {
|
|
984
1531
|
...props,
|
|
985
1532
|
inputType,
|
|
@@ -1109,6 +1656,7 @@ function FilterValueControl(props) {
|
|
|
1109
1656
|
arity,
|
|
1110
1657
|
autoFocus: props.autoFocus,
|
|
1111
1658
|
fieldLabel: props.fieldLabel,
|
|
1659
|
+
placeholder: props.placeholder,
|
|
1112
1660
|
options: props.options,
|
|
1113
1661
|
fill: props.fill
|
|
1114
1662
|
});
|
|
@@ -1125,6 +1673,7 @@ function FilterValueControl(props) {
|
|
|
1125
1673
|
arity,
|
|
1126
1674
|
autoFocus: props.autoFocus,
|
|
1127
1675
|
fieldLabel: props.fieldLabel,
|
|
1676
|
+
placeholder: props.placeholder,
|
|
1128
1677
|
options: props.kind.values.map((entry) => ({
|
|
1129
1678
|
value: entry,
|
|
1130
1679
|
label: entry
|
|
@@ -1153,10 +1702,10 @@ const FIELD_CLASS = "h-8 min-w-0 shrink basis-40";
|
|
|
1153
1702
|
const OPERATOR_CLASS = "h-8 min-w-0 shrink basis-[9.5rem]";
|
|
1154
1703
|
function FilterRow(props) {
|
|
1155
1704
|
const { row, path, available, onPatch, onRemove, testIdBase, debounceMs } = props;
|
|
1156
|
-
const
|
|
1705
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1157
1706
|
const base = `${testIdBase}:row:${path.join("-")}`;
|
|
1158
1707
|
const spec = available.find((s) => s.field === row.field);
|
|
1159
|
-
const removeLabel =
|
|
1708
|
+
const removeLabel = chromeT("filters.removeRow", { defaultValue: "Remove filter" });
|
|
1160
1709
|
if (!spec) return (0, react_jsx_runtime.jsxs)("div", {
|
|
1161
1710
|
className: ROW_CLASS,
|
|
1162
1711
|
children: [
|
|
@@ -1196,8 +1745,8 @@ function FilterRow(props) {
|
|
|
1196
1745
|
};
|
|
1197
1746
|
const handleOpChange = (op) => onPatch(path, { op });
|
|
1198
1747
|
const handleValueChange = (value) => onPatch(path, { value });
|
|
1199
|
-
const fieldAriaLabel =
|
|
1200
|
-
const operatorAriaLabel =
|
|
1748
|
+
const fieldAriaLabel = chromeT("filters.field", { defaultValue: "Field" });
|
|
1749
|
+
const operatorAriaLabel = chromeT("filters.operator", { defaultValue: "Operator" });
|
|
1201
1750
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1202
1751
|
className: ROW_CLASS,
|
|
1203
1752
|
children: [
|
|
@@ -1226,7 +1775,7 @@ function FilterRow(props) {
|
|
|
1226
1775
|
}), (0, react_jsx_runtime.jsx)(SelectContent, { children: spec.operators.map((op) => (0, react_jsx_runtime.jsx)(SelectItem, {
|
|
1227
1776
|
value: op,
|
|
1228
1777
|
"data-testid": `${opTestId}:option:${op}`,
|
|
1229
|
-
children:
|
|
1778
|
+
children: chromeT(`filters.operators.${op}`, { defaultValue: op })
|
|
1230
1779
|
}, op)) })]
|
|
1231
1780
|
}),
|
|
1232
1781
|
(0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1274,10 +1823,10 @@ function FilterGroupEditor(props) {
|
|
|
1274
1823
|
}
|
|
1275
1824
|
function GroupEditorInner(props) {
|
|
1276
1825
|
const { group, path, available, onChange, testIdBase, onRemove, addGroupAt, debounceMs } = props;
|
|
1277
|
-
const
|
|
1826
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1278
1827
|
const base = `${testIdBase}:group:${path.join("-")}`;
|
|
1279
1828
|
const canNestGroup = depthOf(path) < 3;
|
|
1280
|
-
const joinLabel = (join) =>
|
|
1829
|
+
const joinLabel = (join) => chromeT(`filters.${join}`, { defaultValue: join });
|
|
1281
1830
|
const handlePatch = (rowPath, patch) => {
|
|
1282
1831
|
const index = rowPath[rowPath.length - 1];
|
|
1283
1832
|
if (index === void 0) return;
|
|
@@ -1310,11 +1859,11 @@ function GroupEditorInner(props) {
|
|
|
1310
1859
|
return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1311
1860
|
className: CONNECTOR_CLASS,
|
|
1312
1861
|
children: [
|
|
1313
|
-
index === 0 &&
|
|
1862
|
+
index === 0 && chromeT("filters.where", { defaultValue: "Where" }),
|
|
1314
1863
|
index === 1 && (0, react_jsx_runtime.jsx)("button", {
|
|
1315
1864
|
type: "button",
|
|
1316
1865
|
"data-testid": `${base}:join`,
|
|
1317
|
-
"aria-label":
|
|
1866
|
+
"aria-label": chromeT("filters.toggleJoin", {
|
|
1318
1867
|
defaultValue: `Join: ${joinLabel(group.join)} — activate to switch to ${joinLabel(otherJoin)}`,
|
|
1319
1868
|
params: {
|
|
1320
1869
|
current: joinLabel(group.join),
|
|
@@ -1366,7 +1915,7 @@ function GroupEditorInner(props) {
|
|
|
1366
1915
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconPlus, {
|
|
1367
1916
|
className: "h-4 w-4",
|
|
1368
1917
|
"aria-hidden": "true"
|
|
1369
|
-
}),
|
|
1918
|
+
}), chromeT("filters.addRow", { defaultValue: "Add filter" })]
|
|
1370
1919
|
}),
|
|
1371
1920
|
canNestGroup && (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
1372
1921
|
type: "button",
|
|
@@ -1377,7 +1926,7 @@ function GroupEditorInner(props) {
|
|
|
1377
1926
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconFolderPlus, {
|
|
1378
1927
|
className: "h-4 w-4",
|
|
1379
1928
|
"aria-hidden": "true"
|
|
1380
|
-
}),
|
|
1929
|
+
}), chromeT("filters.addGroup", { defaultValue: "Add group" })]
|
|
1381
1930
|
}),
|
|
1382
1931
|
onRemove && (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
1383
1932
|
type: "button",
|
|
@@ -1388,7 +1937,7 @@ function GroupEditorInner(props) {
|
|
|
1388
1937
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
|
|
1389
1938
|
className: "h-4 w-4",
|
|
1390
1939
|
"aria-hidden": "true"
|
|
1391
|
-
}),
|
|
1940
|
+
}), chromeT("filters.removeGroup", { defaultValue: "Remove group" })]
|
|
1392
1941
|
})
|
|
1393
1942
|
]
|
|
1394
1943
|
})
|
|
@@ -1404,7 +1953,7 @@ function countGroupRows(group) {
|
|
|
1404
1953
|
}
|
|
1405
1954
|
function FilterPanel(props) {
|
|
1406
1955
|
const { group, setGroup, available, setPage, testIdBase, open, onOpenChange, focusPath, externalRemoval } = props;
|
|
1407
|
-
const
|
|
1956
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1408
1957
|
const [draft, setDraft] = (0, react.useState)(() => toDraft(group));
|
|
1409
1958
|
const wasOpenRef = (0, react.useRef)(open);
|
|
1410
1959
|
const topLevelIdsRef = (0, react.useRef)([]);
|
|
@@ -1456,7 +2005,7 @@ function FilterPanel(props) {
|
|
|
1456
2005
|
className: "h-4 w-4",
|
|
1457
2006
|
"aria-hidden": "true"
|
|
1458
2007
|
}),
|
|
1459
|
-
|
|
2008
|
+
chromeT("filters.title", { defaultValue: "Filters" }),
|
|
1460
2009
|
appliedCount > 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
1461
2010
|
"data-testid": `${testIdBase}:count`,
|
|
1462
2011
|
className: "ml-1 rounded-full bg-primary px-1.5 text-xs text-primary-foreground",
|
|
@@ -1484,13 +2033,13 @@ function FilterPanel(props) {
|
|
|
1484
2033
|
size: "sm",
|
|
1485
2034
|
"data-testid": `${testIdBase}:reset`,
|
|
1486
2035
|
onClick: handleReset,
|
|
1487
|
-
children:
|
|
2036
|
+
children: chromeT("filters.reset", { defaultValue: "Reset" })
|
|
1488
2037
|
}), (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
1489
2038
|
type: "button",
|
|
1490
2039
|
size: "sm",
|
|
1491
2040
|
"data-testid": `${testIdBase}:apply`,
|
|
1492
2041
|
onClick: handleApply,
|
|
1493
|
-
children:
|
|
2042
|
+
children: chromeT("filters.apply", { defaultValue: "Apply" })
|
|
1494
2043
|
})]
|
|
1495
2044
|
})]
|
|
1496
2045
|
})]
|
|
@@ -1545,11 +2094,204 @@ function PinnedControl(props) {
|
|
|
1545
2094
|
});
|
|
1546
2095
|
}
|
|
1547
2096
|
//#endregion
|
|
2097
|
+
//#region src/data-table/data-table-faceted-filter.tsx
|
|
2098
|
+
function DataTableFacetedFilter({ column, getTestId, ...rest }) {
|
|
2099
|
+
const filterValue = column.getFilterValue();
|
|
2100
|
+
return (0, react_jsx_runtime.jsx)(FacetedFilterPicker, {
|
|
2101
|
+
...rest,
|
|
2102
|
+
...getTestId === void 0 ? {} : { getTestId: (role, value) => role === "hint" ? void 0 : getTestId(role, value) },
|
|
2103
|
+
selected: Array.isArray(filterValue) ? filterValue.map(String) : [],
|
|
2104
|
+
onChange: (next) => column.setFilterValue(next.length === 0 ? void 0 : next)
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
function FacetedFilterPicker({ title, options = [], loadOptions, selectedLabelFor, searchPlaceholder, emptyText, getTestId, className, selected: selectedList, onChange, hint, emptyLabel, clearable = true }) {
|
|
2108
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
2109
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
2110
|
+
const selected = (0, react.useMemo)(() => new Set(selectedList), [selectedList]);
|
|
2111
|
+
const [search, setSearch] = (0, react.useState)("");
|
|
2112
|
+
const [asyncOptions, setAsyncOptions] = (0, react.useState)([]);
|
|
2113
|
+
const [loading, setLoading] = (0, react.useState)(false);
|
|
2114
|
+
const debounceRef = (0, react.useRef)(null);
|
|
2115
|
+
const loadOptionsRef = (0, react.useRef)(loadOptions);
|
|
2116
|
+
(0, react.useEffect)(() => {
|
|
2117
|
+
loadOptionsRef.current = loadOptions;
|
|
2118
|
+
});
|
|
2119
|
+
(0, react.useEffect)(() => {
|
|
2120
|
+
if (!loadOptionsRef.current) return;
|
|
2121
|
+
setLoading(true);
|
|
2122
|
+
if (debounceRef.current !== null) clearTimeout(debounceRef.current);
|
|
2123
|
+
let cancelled = false;
|
|
2124
|
+
debounceRef.current = setTimeout(() => {
|
|
2125
|
+
const loader = loadOptionsRef.current;
|
|
2126
|
+
if (!loader) return;
|
|
2127
|
+
loader(search).then((results) => {
|
|
2128
|
+
if (!cancelled) {
|
|
2129
|
+
setAsyncOptions(results);
|
|
2130
|
+
setLoading(false);
|
|
2131
|
+
}
|
|
2132
|
+
}).catch(() => {
|
|
2133
|
+
if (!cancelled) setLoading(false);
|
|
2134
|
+
});
|
|
2135
|
+
}, 250);
|
|
2136
|
+
return () => {
|
|
2137
|
+
cancelled = true;
|
|
2138
|
+
if (debounceRef.current !== null) clearTimeout(debounceRef.current);
|
|
2139
|
+
};
|
|
2140
|
+
}, [search]);
|
|
2141
|
+
const effectiveOptions = loadOptions ? asyncOptions : options;
|
|
2142
|
+
const labelFor = (value) => {
|
|
2143
|
+
const opt = effectiveOptions.find((o) => o.value === value);
|
|
2144
|
+
if (opt) return opt.label;
|
|
2145
|
+
return selectedLabelFor?.(value) ?? value;
|
|
2146
|
+
};
|
|
2147
|
+
const toggle = (value) => {
|
|
2148
|
+
const next = new Set(selected);
|
|
2149
|
+
if (next.has(value)) next.delete(value);
|
|
2150
|
+
else next.add(value);
|
|
2151
|
+
onChange(Array.from(next));
|
|
2152
|
+
};
|
|
2153
|
+
const selectedValues = Array.from(selected);
|
|
2154
|
+
return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, { children: [(0, react_jsx_runtime.jsx)(require_toaster.PopoverTrigger, {
|
|
2155
|
+
asChild: true,
|
|
2156
|
+
children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
2157
|
+
type: "button",
|
|
2158
|
+
variant: "outline",
|
|
2159
|
+
size: "sm",
|
|
2160
|
+
"data-testid": getTestId?.("trigger"),
|
|
2161
|
+
title: hint,
|
|
2162
|
+
className: require_use_theme.cn("h-8 border-dashed", className),
|
|
2163
|
+
children: [
|
|
2164
|
+
(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCirclePlus, {
|
|
2165
|
+
className: "mr-2 h-4 w-4",
|
|
2166
|
+
"aria-hidden": "true"
|
|
2167
|
+
}),
|
|
2168
|
+
title,
|
|
2169
|
+
selected.size === 0 && emptyLabel !== void 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
|
|
2170
|
+
className: "mx-2 h-4 w-px bg-border",
|
|
2171
|
+
"aria-hidden": "true"
|
|
2172
|
+
}), (0, react_jsx_runtime.jsx)(Badge, {
|
|
2173
|
+
variant: "secondary",
|
|
2174
|
+
className: "rounded-sm px-1 font-normal",
|
|
2175
|
+
children: emptyLabel
|
|
2176
|
+
})] }),
|
|
2177
|
+
selected.size > 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2178
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
2179
|
+
className: "mx-2 h-4 w-px bg-border",
|
|
2180
|
+
"aria-hidden": "true"
|
|
2181
|
+
}),
|
|
2182
|
+
(0, react_jsx_runtime.jsx)(Badge, {
|
|
2183
|
+
variant: "secondary",
|
|
2184
|
+
className: "rounded-sm px-1 font-normal lg:hidden",
|
|
2185
|
+
children: selected.size
|
|
2186
|
+
}),
|
|
2187
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
2188
|
+
className: "hidden gap-1 lg:flex",
|
|
2189
|
+
children: selected.size > 2 ? (0, react_jsx_runtime.jsx)(Badge, {
|
|
2190
|
+
variant: "secondary",
|
|
2191
|
+
className: "rounded-sm px-1 font-normal",
|
|
2192
|
+
children: t("table.selectedCount", {
|
|
2193
|
+
count: selected.size,
|
|
2194
|
+
defaultValue: "{{count}} selected"
|
|
2195
|
+
})
|
|
2196
|
+
}) : selectedValues.map((value) => (0, react_jsx_runtime.jsx)(Badge, {
|
|
2197
|
+
variant: "secondary",
|
|
2198
|
+
className: "rounded-sm px-1 font-normal",
|
|
2199
|
+
children: labelFor(value)
|
|
2200
|
+
}, value))
|
|
2201
|
+
})
|
|
2202
|
+
] })
|
|
2203
|
+
]
|
|
2204
|
+
})
|
|
2205
|
+
}), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
2206
|
+
className: "w-[220px] p-0",
|
|
2207
|
+
align: "start",
|
|
2208
|
+
children: (0, react_jsx_runtime.jsxs)(require_relation_create.Command, {
|
|
2209
|
+
shouldFilter: !loadOptions,
|
|
2210
|
+
children: [
|
|
2211
|
+
hint !== void 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
2212
|
+
"data-testid": getTestId?.("hint"),
|
|
2213
|
+
className: "border-b px-3 py-2 text-xs text-muted-foreground",
|
|
2214
|
+
children: hint
|
|
2215
|
+
}),
|
|
2216
|
+
(0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
|
|
2217
|
+
placeholder: searchPlaceholder ?? title,
|
|
2218
|
+
"data-testid": getTestId?.("search"),
|
|
2219
|
+
...loadOptions ? {
|
|
2220
|
+
value: search,
|
|
2221
|
+
onValueChange: setSearch
|
|
2222
|
+
} : {}
|
|
2223
|
+
}),
|
|
2224
|
+
(0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, { children: [
|
|
2225
|
+
loading && (0, react_jsx_runtime.jsx)("div", {
|
|
2226
|
+
className: "py-6 text-center text-sm text-muted-foreground",
|
|
2227
|
+
children: t("list.loadingShort", { defaultValue: "Loading…" })
|
|
2228
|
+
}),
|
|
2229
|
+
(0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, { children: emptyText ?? t("relation.noResults", { defaultValue: "No results." }) }),
|
|
2230
|
+
(0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, { children: effectiveOptions.map((opt) => {
|
|
2231
|
+
const isSelected = selected.has(opt.value);
|
|
2232
|
+
const Icon = opt.icon;
|
|
2233
|
+
return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
|
|
2234
|
+
value: opt.label,
|
|
2235
|
+
"data-testid": getTestId?.("option", opt.value),
|
|
2236
|
+
role: "option",
|
|
2237
|
+
"aria-selected": isSelected,
|
|
2238
|
+
"aria-checked": isSelected,
|
|
2239
|
+
onSelect: () => toggle(opt.value),
|
|
2240
|
+
children: [
|
|
2241
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
2242
|
+
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"),
|
|
2243
|
+
"aria-hidden": "true",
|
|
2244
|
+
children: isSelected && (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, { className: "h-3.5 w-3.5" })
|
|
2245
|
+
}),
|
|
2246
|
+
Icon && (0, react_jsx_runtime.jsx)(Icon, {
|
|
2247
|
+
className: "mr-2 h-4 w-4 text-muted-foreground",
|
|
2248
|
+
"aria-hidden": "true"
|
|
2249
|
+
}),
|
|
2250
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
2251
|
+
className: "flex min-w-0 flex-1 flex-col text-left",
|
|
2252
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: opt.label }), opt.summary !== void 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
2253
|
+
className: "text-xs text-muted-foreground",
|
|
2254
|
+
children: opt.summary
|
|
2255
|
+
})]
|
|
2256
|
+
})
|
|
2257
|
+
]
|
|
2258
|
+
}, opt.value);
|
|
2259
|
+
}) })
|
|
2260
|
+
] }),
|
|
2261
|
+
clearable && selected.size > 0 && (0, react_jsx_runtime.jsx)("button", {
|
|
2262
|
+
type: "button",
|
|
2263
|
+
"data-testid": getTestId?.("clear"),
|
|
2264
|
+
onClick: () => onChange([]),
|
|
2265
|
+
className: "flex w-full items-center justify-center border-t px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground",
|
|
2266
|
+
children: chromeT("filters.clearAll", { defaultValue: "Clear filters" })
|
|
2267
|
+
})
|
|
2268
|
+
]
|
|
2269
|
+
})
|
|
2270
|
+
})] });
|
|
2271
|
+
}
|
|
2272
|
+
//#endregion
|
|
2273
|
+
//#region src/list-kit/filter-builder/preset-filter-controls.tsx
|
|
2274
|
+
function PresetFilterControls(props) {
|
|
2275
|
+
const { presets, setPreset, testIdBase } = props;
|
|
2276
|
+
return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: presets.map((filter) => (0, react_jsx_runtime.jsx)(FacetedFilterPicker, {
|
|
2277
|
+
title: filter.label,
|
|
2278
|
+
...filter.hint === void 0 ? {} : { hint: filter.hint },
|
|
2279
|
+
options: filter.options.map((option) => ({
|
|
2280
|
+
value: option.id,
|
|
2281
|
+
label: option.label,
|
|
2282
|
+
...option.summary === void 0 ? {} : { summary: option.summary }
|
|
2283
|
+
})),
|
|
2284
|
+
selected: filter.selected,
|
|
2285
|
+
onChange: (next) => setPreset(filter.id, filter.options.map((option) => option.id).filter((id) => next.includes(id))),
|
|
2286
|
+
getTestId: (role, value) => `${testIdBase}:preset:${filter.id}:${role}${value === void 0 ? "" : `:${value}`}`
|
|
2287
|
+
}, filter.id)) });
|
|
2288
|
+
}
|
|
2289
|
+
//#endregion
|
|
1548
2290
|
//#region src/list-kit/filter-builder/filter-builder.tsx
|
|
1549
2291
|
const EMPTY_PINNED_FIELDS = Object.freeze([]);
|
|
1550
2292
|
const EMPTY_PINNED_VALUE = Object.freeze([]);
|
|
1551
2293
|
function FilterBuilder(props) {
|
|
1552
|
-
const { group, setGroup, available, fixed, pinnedFields = EMPTY_PINNED_FIELDS, pinnedValue = EMPTY_PINNED_VALUE, setPinnedValue, setPage, testIdBase } = props;
|
|
2294
|
+
const { group, setGroup, available, fixed, pinnedFields = EMPTY_PINNED_FIELDS, pinnedValue = EMPTY_PINNED_VALUE, setPinnedValue, presets, setPreset, setPage, testIdBase } = props;
|
|
1553
2295
|
const [open, setOpen] = (0, react.useState)(false);
|
|
1554
2296
|
const [focusPath, setFocusPath] = (0, react.useState)(void 0);
|
|
1555
2297
|
const [externalRemoval, setExternalRemoval] = (0, react.useState)(void 0);
|
|
@@ -1566,6 +2308,11 @@ function FilterBuilder(props) {
|
|
|
1566
2308
|
setPinnedValue?.(next);
|
|
1567
2309
|
};
|
|
1568
2310
|
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2311
|
+
presets !== void 0 && presets.length > 0 && setPreset !== void 0 && (0, react_jsx_runtime.jsx)(PresetFilterControls, {
|
|
2312
|
+
presets,
|
|
2313
|
+
setPreset,
|
|
2314
|
+
testIdBase
|
|
2315
|
+
}),
|
|
1569
2316
|
(0, react_jsx_runtime.jsx)(PinnedFilterControls, {
|
|
1570
2317
|
pinnedFields,
|
|
1571
2318
|
value: pinnedValue,
|
|
@@ -1607,6 +2354,18 @@ Object.defineProperty(exports, "Badge", {
|
|
|
1607
2354
|
return Badge;
|
|
1608
2355
|
}
|
|
1609
2356
|
});
|
|
2357
|
+
Object.defineProperty(exports, "DataTableFacetedFilter", {
|
|
2358
|
+
enumerable: true,
|
|
2359
|
+
get: function() {
|
|
2360
|
+
return DataTableFacetedFilter;
|
|
2361
|
+
}
|
|
2362
|
+
});
|
|
2363
|
+
Object.defineProperty(exports, "FacetedFilterPicker", {
|
|
2364
|
+
enumerable: true,
|
|
2365
|
+
get: function() {
|
|
2366
|
+
return FacetedFilterPicker;
|
|
2367
|
+
}
|
|
2368
|
+
});
|
|
1610
2369
|
Object.defineProperty(exports, "FilterBadges", {
|
|
1611
2370
|
enumerable: true,
|
|
1612
2371
|
get: function() {
|
|
@@ -1631,12 +2390,36 @@ Object.defineProperty(exports, "FilterValueControl", {
|
|
|
1631
2390
|
return FilterValueControl;
|
|
1632
2391
|
}
|
|
1633
2392
|
});
|
|
2393
|
+
Object.defineProperty(exports, "MetaPlaceholder", {
|
|
2394
|
+
enumerable: true,
|
|
2395
|
+
get: function() {
|
|
2396
|
+
return MetaPlaceholder;
|
|
2397
|
+
}
|
|
2398
|
+
});
|
|
1634
2399
|
Object.defineProperty(exports, "PinnedFilterControls", {
|
|
1635
2400
|
enumerable: true,
|
|
1636
2401
|
get: function() {
|
|
1637
2402
|
return PinnedFilterControls;
|
|
1638
2403
|
}
|
|
1639
2404
|
});
|
|
2405
|
+
Object.defineProperty(exports, "PresetFilterControls", {
|
|
2406
|
+
enumerable: true,
|
|
2407
|
+
get: function() {
|
|
2408
|
+
return PresetFilterControls;
|
|
2409
|
+
}
|
|
2410
|
+
});
|
|
2411
|
+
Object.defineProperty(exports, "ResolvedFieldDisplay", {
|
|
2412
|
+
enumerable: true,
|
|
2413
|
+
get: function() {
|
|
2414
|
+
return ResolvedFieldDisplay;
|
|
2415
|
+
}
|
|
2416
|
+
});
|
|
2417
|
+
Object.defineProperty(exports, "ResolvedFieldInput", {
|
|
2418
|
+
enumerable: true,
|
|
2419
|
+
get: function() {
|
|
2420
|
+
return ResolvedFieldInput;
|
|
2421
|
+
}
|
|
2422
|
+
});
|
|
1640
2423
|
Object.defineProperty(exports, "Select", {
|
|
1641
2424
|
enumerable: true,
|
|
1642
2425
|
get: function() {
|
|
@@ -1745,17 +2528,65 @@ Object.defineProperty(exports, "badgeVariants", {
|
|
|
1745
2528
|
return badgeVariants;
|
|
1746
2529
|
}
|
|
1747
2530
|
});
|
|
2531
|
+
Object.defineProperty(exports, "fieldDescription", {
|
|
2532
|
+
enumerable: true,
|
|
2533
|
+
get: function() {
|
|
2534
|
+
return fieldDescription;
|
|
2535
|
+
}
|
|
2536
|
+
});
|
|
1748
2537
|
Object.defineProperty(exports, "formatDate", {
|
|
1749
2538
|
enumerable: true,
|
|
1750
2539
|
get: function() {
|
|
1751
2540
|
return formatDate;
|
|
1752
2541
|
}
|
|
1753
2542
|
});
|
|
2543
|
+
Object.defineProperty(exports, "formatDateTime", {
|
|
2544
|
+
enumerable: true,
|
|
2545
|
+
get: function() {
|
|
2546
|
+
return formatDateTime;
|
|
2547
|
+
}
|
|
2548
|
+
});
|
|
1754
2549
|
Object.defineProperty(exports, "formatNumber", {
|
|
1755
2550
|
enumerable: true,
|
|
1756
2551
|
get: function() {
|
|
1757
2552
|
return formatNumber;
|
|
1758
2553
|
}
|
|
1759
2554
|
});
|
|
2555
|
+
Object.defineProperty(exports, "fromLocalDateTimeText", {
|
|
2556
|
+
enumerable: true,
|
|
2557
|
+
get: function() {
|
|
2558
|
+
return fromLocalDateTimeText;
|
|
2559
|
+
}
|
|
2560
|
+
});
|
|
2561
|
+
Object.defineProperty(exports, "loadLocale", {
|
|
2562
|
+
enumerable: true,
|
|
2563
|
+
get: function() {
|
|
2564
|
+
return loadLocale;
|
|
2565
|
+
}
|
|
2566
|
+
});
|
|
2567
|
+
Object.defineProperty(exports, "lowerLegacyField", {
|
|
2568
|
+
enumerable: true,
|
|
2569
|
+
get: function() {
|
|
2570
|
+
return lowerLegacyField;
|
|
2571
|
+
}
|
|
2572
|
+
});
|
|
2573
|
+
Object.defineProperty(exports, "saveLocale", {
|
|
2574
|
+
enumerable: true,
|
|
2575
|
+
get: function() {
|
|
2576
|
+
return saveLocale;
|
|
2577
|
+
}
|
|
2578
|
+
});
|
|
2579
|
+
Object.defineProperty(exports, "toLocalDateTimeText", {
|
|
2580
|
+
enumerable: true,
|
|
2581
|
+
get: function() {
|
|
2582
|
+
return toLocalDateTimeText;
|
|
2583
|
+
}
|
|
2584
|
+
});
|
|
2585
|
+
Object.defineProperty(exports, "useFieldMetaDiagnostic", {
|
|
2586
|
+
enumerable: true,
|
|
2587
|
+
get: function() {
|
|
2588
|
+
return useFieldMetaDiagnostic;
|
|
2589
|
+
}
|
|
2590
|
+
});
|
|
1760
2591
|
|
|
1761
|
-
//# sourceMappingURL=filter-builder-
|
|
2592
|
+
//# sourceMappingURL=filter-builder-DFu0JP-1.cjs.map
|