@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,11 +1,12 @@
|
|
|
1
1
|
import { l as cn } from "./use-theme-dnE3Od3I.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { a as technicalText, l as useLinkComponent, n as toast, o as technicalTexts, r as friendlyStringsFrom, s as toFriendlyError } from "./toaster-Ct_YHGs6.js";
|
|
3
|
+
import { n as buttonVariants, t as Button } from "./button-MWVeZaqj.js";
|
|
4
|
+
import { i as DialogDescription, r as DialogContent, s as DialogTitle, t as Dialog } from "./dialog-C123sVQ8.js";
|
|
5
|
+
import { composeListFilter, hasRecordPage, normalizeDataError, normalizeFixedFilters, relationAmbiguousError, relationOpenOf, resourceKey, resourceShowHref, routeResourceKey } from "@burojs/core";
|
|
6
|
+
import { PEEK_COMPONENT, QUICK_ANCHOR_ATTRIBUTE, filterFields, quickAnchorRef, specificErrorText, useApp, useChromeT, useCurrentUIActivation, useEntryGate, useI18nCaps, useList, useListAccess, useLoadErrorView, useOptionalT, useQuick, useQuickOpener, useRelatedRecord, useRouteNavigate, useT, useTestIds, useUIPresentationRuntime } from "@burojs/react";
|
|
7
|
+
import { IconAlertCircle, IconEye, IconRefresh, IconSearch } from "@tabler/icons-react";
|
|
7
8
|
import * as React from "react";
|
|
8
|
-
import { createContext, useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
9
|
+
import { Component, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
import { Command } from "cmdk";
|
|
11
12
|
//#region src/primitives/command.tsx
|
|
@@ -92,6 +93,243 @@ function CommandDialog({ open, onOpenChange, defaultOpen, modal, title = "Comman
|
|
|
92
93
|
}
|
|
93
94
|
CommandDialog.displayName = "CommandDialog";
|
|
94
95
|
//#endregion
|
|
96
|
+
//#region src/record/record-state.tsx
|
|
97
|
+
function RecordState({ state, onRetry, message: given }) {
|
|
98
|
+
const t = useT();
|
|
99
|
+
const chromeT = useChromeT();
|
|
100
|
+
if (state === "loading") return jsx("div", {
|
|
101
|
+
role: "status",
|
|
102
|
+
"aria-busy": "true",
|
|
103
|
+
"data-testid": "record-page:loading",
|
|
104
|
+
className: "p-6 text-sm text-muted-foreground",
|
|
105
|
+
children: t("router.recordLoading")
|
|
106
|
+
});
|
|
107
|
+
const message = given ?? (state === "not-found" ? t("record.notFoundOrNoAccess") : state === "session-expired" ? t("router.recordSessionExpired") : t("router.recordError"));
|
|
108
|
+
return jsxs("div", {
|
|
109
|
+
role: "alert",
|
|
110
|
+
"data-testid": `record-page:${state}`,
|
|
111
|
+
className: "flex flex-col items-center justify-center gap-3 px-6 py-24 text-center",
|
|
112
|
+
children: [jsx("p", {
|
|
113
|
+
className: "max-w-sm text-sm text-muted-foreground",
|
|
114
|
+
children: message
|
|
115
|
+
}), onRetry ? jsx(Button, {
|
|
116
|
+
type: "button",
|
|
117
|
+
variant: "outline",
|
|
118
|
+
size: "sm",
|
|
119
|
+
"data-testid": "record-page:retry",
|
|
120
|
+
onClick: onRetry,
|
|
121
|
+
children: chromeT("actions.retry")
|
|
122
|
+
}) : null]
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/load-error/list-error-panel.tsx
|
|
127
|
+
function ListErrorPanel({ text, technical, onRetry, resource, title, className }) {
|
|
128
|
+
useT();
|
|
129
|
+
const t = useOptionalT();
|
|
130
|
+
const chromeT = useChromeT();
|
|
131
|
+
const raw = process.env.NODE_ENV === "production" ? void 0 : technical;
|
|
132
|
+
return jsxs("div", {
|
|
133
|
+
role: "alert",
|
|
134
|
+
className: cn("flex flex-col items-center justify-center gap-3 px-6 py-16 rounded-lg border border-destructive/40 bg-destructive/5 text-center", className),
|
|
135
|
+
"data-testid": "error",
|
|
136
|
+
children: [
|
|
137
|
+
jsx("div", {
|
|
138
|
+
className: "rounded-full bg-destructive/10 p-3 text-destructive",
|
|
139
|
+
children: jsx(IconAlertCircle, {
|
|
140
|
+
className: "size-6",
|
|
141
|
+
"aria-hidden": "true"
|
|
142
|
+
})
|
|
143
|
+
}),
|
|
144
|
+
jsxs("div", {
|
|
145
|
+
className: "space-y-1",
|
|
146
|
+
children: [jsx("h3", {
|
|
147
|
+
className: "text-base font-semibold tracking-tight text-destructive",
|
|
148
|
+
children: title ?? t("list.errorTitle")
|
|
149
|
+
}), jsx("p", {
|
|
150
|
+
className: "max-w-md text-sm text-muted-foreground",
|
|
151
|
+
children: text
|
|
152
|
+
})]
|
|
153
|
+
}),
|
|
154
|
+
raw && raw !== text ? jsxs("details", {
|
|
155
|
+
className: "max-w-md text-left",
|
|
156
|
+
children: [jsx("summary", {
|
|
157
|
+
className: "cursor-pointer text-xs text-muted-foreground hover:text-foreground",
|
|
158
|
+
children: t("list.errorDetails")
|
|
159
|
+
}), jsx("p", {
|
|
160
|
+
className: "mt-1.5 break-all font-mono text-xs text-muted-foreground",
|
|
161
|
+
"data-testid": "list-error-detail",
|
|
162
|
+
children: raw
|
|
163
|
+
})]
|
|
164
|
+
}) : null,
|
|
165
|
+
onRetry && jsx("div", {
|
|
166
|
+
className: "flex justify-center pt-2",
|
|
167
|
+
children: jsxs(Button, {
|
|
168
|
+
type: "button",
|
|
169
|
+
variant: "outline",
|
|
170
|
+
size: "sm",
|
|
171
|
+
"data-testid": resource ? `list-error-retry:${resource}` : "list-error-retry",
|
|
172
|
+
onClick: onRetry,
|
|
173
|
+
className: "gap-1.5",
|
|
174
|
+
children: [jsx(IconRefresh, {
|
|
175
|
+
className: "size-3.5",
|
|
176
|
+
"aria-hidden": "true"
|
|
177
|
+
}), chromeT("actions.retry")]
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
]
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/load-error/state.ts
|
|
185
|
+
function recordErrorState(error) {
|
|
186
|
+
const { kind } = normalizeDataError(error);
|
|
187
|
+
if (kind === "not-found" || kind === "forbidden") return "not-found";
|
|
188
|
+
if (kind === "auth") return "session-expired";
|
|
189
|
+
return "error";
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/load-error/load-error-view.tsx
|
|
193
|
+
const RECORD_KEYS = {
|
|
194
|
+
"not-found": "record.notFoundOrNoAccess",
|
|
195
|
+
"session-expired": "router.recordSessionExpired",
|
|
196
|
+
error: "router.recordError"
|
|
197
|
+
};
|
|
198
|
+
const LIST_FALLBACK = {
|
|
199
|
+
key: "list.errorBody",
|
|
200
|
+
default: "Failed to load data. Please try again."
|
|
201
|
+
};
|
|
202
|
+
function loadErrorTechnicalTexts(error, original) {
|
|
203
|
+
const out = [...technicalTexts(error), ...technicalTexts(original)];
|
|
204
|
+
if (original !== null && typeof original === "object" && !(original instanceof Error)) {
|
|
205
|
+
const message = original.message;
|
|
206
|
+
if (typeof message === "string") out.push(message);
|
|
207
|
+
}
|
|
208
|
+
return out.filter((text, index) => text.length > 0 && out.indexOf(text) === index);
|
|
209
|
+
}
|
|
210
|
+
function useLoadErrorText(error, original, state, surface, fallback) {
|
|
211
|
+
const t = useOptionalT();
|
|
212
|
+
const caps = useI18nCaps();
|
|
213
|
+
if (state !== "error") return t(RECORD_KEYS[state]);
|
|
214
|
+
const own = specificErrorText(error, caps);
|
|
215
|
+
if (own !== void 0) return own;
|
|
216
|
+
const strings = friendlyStringsFrom(t);
|
|
217
|
+
for (const text of loadErrorTechnicalTexts(error, original)) {
|
|
218
|
+
const friendly = toFriendlyError(text, "", strings);
|
|
219
|
+
if (friendly.replaced && friendly.detail !== strings.generic) return friendly.detail;
|
|
220
|
+
}
|
|
221
|
+
const generic = surface === "list" ? fallback ?? LIST_FALLBACK : fallback;
|
|
222
|
+
if (surface === "record" || generic === void 0) return t(RECORD_KEYS.error);
|
|
223
|
+
return t(generic.key, { defaultValue: generic.default });
|
|
224
|
+
}
|
|
225
|
+
function DefaultLoadErrorView(props) {
|
|
226
|
+
const { error, surface, state, retry, original, fallback, testId, className, children, attributes } = props;
|
|
227
|
+
const text = useLoadErrorText(error, original, state, surface, fallback);
|
|
228
|
+
const chromeT = useChromeT();
|
|
229
|
+
if (surface === "record") return jsx(RecordState, {
|
|
230
|
+
state,
|
|
231
|
+
message: text,
|
|
232
|
+
...retry === void 0 ? {} : { onRetry: retry }
|
|
233
|
+
});
|
|
234
|
+
if (surface === "list") return jsx(ListErrorPanel, {
|
|
235
|
+
text,
|
|
236
|
+
technical: loadErrorTechnicalTexts(error, original)[0],
|
|
237
|
+
...retry === void 0 ? {} : { onRetry: retry },
|
|
238
|
+
...props.resource === void 0 ? {} : { resource: props.resource },
|
|
239
|
+
...props.title === void 0 ? {} : { title: props.title },
|
|
240
|
+
...className === void 0 ? {} : { className }
|
|
241
|
+
});
|
|
242
|
+
if (surface === "relation" || surface === "picker") {
|
|
243
|
+
const technical = process.env.NODE_ENV === "production" ? void 0 : loadErrorTechnicalTexts(error, original)[0];
|
|
244
|
+
return jsx("span", {
|
|
245
|
+
...attributes,
|
|
246
|
+
...testId === void 0 ? {} : { "data-testid": testId },
|
|
247
|
+
className,
|
|
248
|
+
title: technical === void 0 ? text : `${text} (${technical})`,
|
|
249
|
+
children: children ?? text
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return jsxs("div", {
|
|
253
|
+
...attributes,
|
|
254
|
+
role: "alert",
|
|
255
|
+
...testId === void 0 ? {} : { "data-testid": testId },
|
|
256
|
+
className: cn("flex flex-wrap items-center gap-2 rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground", className),
|
|
257
|
+
children: [jsx("span", { children: text }), retry === void 0 ? null : jsx(Button, {
|
|
258
|
+
type: "button",
|
|
259
|
+
variant: "outline",
|
|
260
|
+
size: "sm",
|
|
261
|
+
onClick: retry,
|
|
262
|
+
children: chromeT("actions.retry", { defaultValue: "Retry" })
|
|
263
|
+
})]
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
const UNSET = Symbol("unset");
|
|
267
|
+
var AppViewBoundary = class extends Component {
|
|
268
|
+
state = {
|
|
269
|
+
failedFor: UNSET,
|
|
270
|
+
failed: false
|
|
271
|
+
};
|
|
272
|
+
static getDerivedStateFromError() {
|
|
273
|
+
return { failed: true };
|
|
274
|
+
}
|
|
275
|
+
static getDerivedStateFromProps(props, state) {
|
|
276
|
+
if (state.failed && state.failedFor !== UNSET && state.failedFor !== props.error) return {
|
|
277
|
+
failedFor: UNSET,
|
|
278
|
+
failed: false
|
|
279
|
+
};
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
componentDidCatch(error, _info) {
|
|
283
|
+
this.setState({ failedFor: this.props.error });
|
|
284
|
+
if (process.env.NODE_ENV !== "production") console.error("[burojs] load-error.view-threw: the app's views.loadError threw while rendering; the kit's view is shown instead.", error);
|
|
285
|
+
}
|
|
286
|
+
render() {
|
|
287
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
function LoadError(props) {
|
|
291
|
+
const App = useLoadErrorView();
|
|
292
|
+
const { error: original, surface, resource } = props;
|
|
293
|
+
const error = useMemo(() => normalizeDataError(original), [original]);
|
|
294
|
+
const state = props.state ?? recordErrorState(error);
|
|
295
|
+
const retry = state === "error" ? props.retry : void 0;
|
|
296
|
+
const viewProps = {
|
|
297
|
+
error,
|
|
298
|
+
surface,
|
|
299
|
+
state,
|
|
300
|
+
...resource === void 0 ? {} : { resource },
|
|
301
|
+
...retry === void 0 ? {} : { retry }
|
|
302
|
+
};
|
|
303
|
+
const standard = jsx(DefaultLoadErrorView, {
|
|
304
|
+
...viewProps,
|
|
305
|
+
original,
|
|
306
|
+
fallback: props.fallback,
|
|
307
|
+
testId: props.testId,
|
|
308
|
+
className: props.className,
|
|
309
|
+
title: props.title,
|
|
310
|
+
attributes: props.attributes,
|
|
311
|
+
children: props.children
|
|
312
|
+
});
|
|
313
|
+
if (App === void 0) return standard;
|
|
314
|
+
return jsx(AppViewBoundary, {
|
|
315
|
+
error: original,
|
|
316
|
+
fallback: standard,
|
|
317
|
+
children: jsx(App, { ...viewProps })
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
const INVALID_ROUTE_ID = Object.freeze({
|
|
321
|
+
kind: "not-found",
|
|
322
|
+
code: "invalid-record-id"
|
|
323
|
+
});
|
|
324
|
+
function InvalidRouteId({ resource }) {
|
|
325
|
+
return jsx(LoadError, {
|
|
326
|
+
surface: "record",
|
|
327
|
+
resource,
|
|
328
|
+
state: "not-found",
|
|
329
|
+
error: INVALID_ROUTE_ID
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
//#endregion
|
|
95
333
|
//#region src/fields/claimed-quick-link.tsx
|
|
96
334
|
function isPlainLeftClick(event) {
|
|
97
335
|
return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
|
|
@@ -330,7 +568,8 @@ function RelationDisplay({ value, field }) {
|
|
|
330
568
|
open
|
|
331
569
|
});
|
|
332
570
|
}
|
|
333
|
-
function RelationField({ to, value }) {
|
|
571
|
+
function RelationField({ to: toInput, value }) {
|
|
572
|
+
const to = routeResourceKey(toInput);
|
|
334
573
|
return jsx(RelationDisplay, {
|
|
335
574
|
value,
|
|
336
575
|
field: {
|
|
@@ -484,7 +723,7 @@ function LazyByOpener({ to, by, idStr, target }) {
|
|
|
484
723
|
if (!asked || rows === void 0 || !requested.current) return;
|
|
485
724
|
if (rows.length > 1) {
|
|
486
725
|
requested.current = false;
|
|
487
|
-
if (process.env.NODE_ENV !== "production") console.error(`[burojs] ${relationAmbiguousError(to, by, idStr)
|
|
726
|
+
if (process.env.NODE_ENV !== "production") console.error(`[burojs] ${technicalText(relationAmbiguousError(to, by, idStr))}`);
|
|
488
727
|
return;
|
|
489
728
|
}
|
|
490
729
|
requested.current = false;
|
|
@@ -572,10 +811,16 @@ function RelationDisplayBody({ to, by, id, idStr, app, open: openMode, quickTarg
|
|
|
572
811
|
title: `${to}: more than one row has ${by ?? "id"} ${idStr}`,
|
|
573
812
|
children: idStr
|
|
574
813
|
});
|
|
575
|
-
if (error) return jsx(
|
|
576
|
-
"
|
|
814
|
+
if (error) return jsx(LoadError, {
|
|
815
|
+
surface: "relation",
|
|
816
|
+
error,
|
|
817
|
+
resource: to,
|
|
818
|
+
testId: `${baseId}:error`,
|
|
577
819
|
className: "text-muted-foreground",
|
|
578
|
-
|
|
820
|
+
fallback: {
|
|
821
|
+
key: "relation.failed",
|
|
822
|
+
default: "Failed to load options."
|
|
823
|
+
},
|
|
579
824
|
children: idStr
|
|
580
825
|
});
|
|
581
826
|
if (!record) return jsx("span", {
|
|
@@ -649,6 +894,343 @@ function namesHiddenField(filter, visible) {
|
|
|
649
894
|
return filter !== void 0 && filterFields(filter).some((field) => !visible(field));
|
|
650
895
|
}
|
|
651
896
|
//#endregion
|
|
652
|
-
|
|
897
|
+
//#region src/fields/relation-hand-back.tsx
|
|
898
|
+
function createdOptionFilter(input) {
|
|
899
|
+
const own = createdOptionScope(input);
|
|
900
|
+
const byId = {
|
|
901
|
+
field: input.idField,
|
|
902
|
+
op: "eq",
|
|
903
|
+
value: input.id
|
|
904
|
+
};
|
|
905
|
+
return own === void 0 ? byId : { and: [own, byId] };
|
|
906
|
+
}
|
|
907
|
+
function createdOptionScope(input) {
|
|
908
|
+
return composeListFilter({
|
|
909
|
+
fixed: normalizeFixedFilters(input.fixed),
|
|
910
|
+
search: "",
|
|
911
|
+
...input.searchDecl === void 0 ? {} : { searchDecl: input.searchDecl },
|
|
912
|
+
...input.searchContext === void 0 ? {} : { searchContext: input.searchContext }
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
function CreatedOptionRead({ to, filter, scope, scopeField, by, idField, onSettled }) {
|
|
916
|
+
const query = useList(to, {
|
|
917
|
+
filter,
|
|
918
|
+
pagination: {
|
|
919
|
+
kind: "offset",
|
|
920
|
+
page: 1,
|
|
921
|
+
pageSize: 1
|
|
922
|
+
},
|
|
923
|
+
scope,
|
|
924
|
+
...scopeField === void 0 ? {} : { scopeField },
|
|
925
|
+
retry: false
|
|
926
|
+
});
|
|
927
|
+
const settled = React.useRef(false);
|
|
928
|
+
const latest = React.useRef(onSettled);
|
|
929
|
+
latest.current = onSettled;
|
|
930
|
+
const rows = query.data?.data;
|
|
931
|
+
const answered = rows !== void 0 && query.isCurrentData && !query.isFetching;
|
|
932
|
+
const failed = query.isError && !query.isFetching;
|
|
933
|
+
React.useEffect(() => {
|
|
934
|
+
if (settled.current) return;
|
|
935
|
+
if (failed) {
|
|
936
|
+
settled.current = true;
|
|
937
|
+
latest.current({ kind: "failed" });
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
if (!answered) return;
|
|
941
|
+
settled.current = true;
|
|
942
|
+
const value = rows[0]?.[by ?? idField];
|
|
943
|
+
latest.current(typeof value === "string" || typeof value === "number" ? {
|
|
944
|
+
kind: "fits",
|
|
945
|
+
value
|
|
946
|
+
} : { kind: "does-not-fit" });
|
|
947
|
+
}, [
|
|
948
|
+
answered,
|
|
949
|
+
failed,
|
|
950
|
+
rows,
|
|
951
|
+
by,
|
|
952
|
+
idField
|
|
953
|
+
]);
|
|
954
|
+
return null;
|
|
955
|
+
}
|
|
956
|
+
//#endregion
|
|
957
|
+
//#region src/fields/relation-view-button.tsx
|
|
958
|
+
function selectKey(value) {
|
|
959
|
+
if (typeof value === "string") return value.length === 0 ? null : value;
|
|
960
|
+
if (typeof value === "number") return Number.isFinite(value) ? String(value) : null;
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
const VIEW_CLASS = cn(buttonVariants({
|
|
964
|
+
variant: "outline",
|
|
965
|
+
size: "icon"
|
|
966
|
+
}), "shrink-0");
|
|
967
|
+
const TITLE_CLASS = "min-w-0 max-w-[16rem] truncate";
|
|
968
|
+
const TITLE_VIEW_CLASS = cn(TITLE_CLASS, "cursor-pointer rounded-sm text-left hover:underline focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring");
|
|
969
|
+
function RelationViewButton(props) {
|
|
970
|
+
const gate = useEntryGate();
|
|
971
|
+
const { to, value, by } = props;
|
|
972
|
+
const access = useListAccess(to);
|
|
973
|
+
const key = selectKey(value);
|
|
974
|
+
const plain = plainTitle(props.title);
|
|
975
|
+
if (key === null || props.open === "none") return plain;
|
|
976
|
+
if (by !== void 0 && !(access.status === "ready" && access.fieldVisible(by))) return plain;
|
|
977
|
+
if (gate(to, "show").state !== "open") return plain;
|
|
978
|
+
return jsx(ViewButton, {
|
|
979
|
+
...props,
|
|
980
|
+
keyString: key
|
|
981
|
+
}, key);
|
|
982
|
+
}
|
|
983
|
+
function plainTitle(title) {
|
|
984
|
+
return title === void 0 ? null : jsx("span", {
|
|
985
|
+
className: TITLE_CLASS,
|
|
986
|
+
children: title
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
function ViewButton({ to, by, fieldName, keyString, beforeOpen, open: openMode = "quick", title }) {
|
|
990
|
+
const app = useApp();
|
|
991
|
+
const t = useOptionalT();
|
|
992
|
+
const tid = useTestIds();
|
|
993
|
+
const quick = useQuick();
|
|
994
|
+
const navigate = useRouteNavigate();
|
|
995
|
+
const RouterLink = useLinkComponent();
|
|
996
|
+
const [asked, setAsked] = React.useState(false);
|
|
997
|
+
const requested = React.useRef(false);
|
|
998
|
+
const targetDef = app.registry.get(to);
|
|
999
|
+
const rawIdField = (targetDef?.data)?.idField;
|
|
1000
|
+
const idField = typeof rawIdField === "string" && rawIdField.length > 0 ? rawIdField : "id";
|
|
1001
|
+
const read = useList(to, {
|
|
1002
|
+
...asked && by !== void 0 ? {
|
|
1003
|
+
filter: {
|
|
1004
|
+
field: by,
|
|
1005
|
+
op: "eq",
|
|
1006
|
+
value: keyString
|
|
1007
|
+
},
|
|
1008
|
+
pagination: {
|
|
1009
|
+
kind: "offset",
|
|
1010
|
+
page: 1,
|
|
1011
|
+
pageSize: 2
|
|
1012
|
+
}
|
|
1013
|
+
} : {},
|
|
1014
|
+
scope: "none",
|
|
1015
|
+
enabled: asked && by !== void 0,
|
|
1016
|
+
retry: false
|
|
1017
|
+
});
|
|
1018
|
+
const rows = read.isCurrentData && !read.isPlaceholderData && !read.isFetching ? read.data?.data : void 0;
|
|
1019
|
+
const open = React.useCallback((id) => {
|
|
1020
|
+
beforeOpen();
|
|
1021
|
+
if (openMode === "page") {
|
|
1022
|
+
if (targetDef !== void 0 && linksToPage(app, targetDef)) navigate(resourceShowHref(app.registry, targetDef, to, id));
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
quick.show(to, id);
|
|
1026
|
+
}, [
|
|
1027
|
+
beforeOpen,
|
|
1028
|
+
quick,
|
|
1029
|
+
to,
|
|
1030
|
+
openMode,
|
|
1031
|
+
navigate,
|
|
1032
|
+
app,
|
|
1033
|
+
targetDef
|
|
1034
|
+
]);
|
|
1035
|
+
React.useEffect(() => {
|
|
1036
|
+
if (by === void 0 || !asked || rows === void 0 || !requested.current) return;
|
|
1037
|
+
requested.current = false;
|
|
1038
|
+
if (rows.length !== 1) {
|
|
1039
|
+
if (rows.length > 1 && process.env.NODE_ENV !== "production") console.error(`[burojs] ${to}: more than one row has ${by} ${keyString}; "view" opened nothing.`);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
const id = rows[0]?.[idField];
|
|
1043
|
+
const next = selectKey(id);
|
|
1044
|
+
if (next !== null) open(next);
|
|
1045
|
+
}, [
|
|
1046
|
+
by,
|
|
1047
|
+
asked,
|
|
1048
|
+
rows,
|
|
1049
|
+
idField,
|
|
1050
|
+
keyString,
|
|
1051
|
+
to,
|
|
1052
|
+
open
|
|
1053
|
+
]);
|
|
1054
|
+
const label = t("relationPicker.view", { defaultValue: "View" });
|
|
1055
|
+
const content = title === void 0 ? jsx(IconEye, {
|
|
1056
|
+
className: "h-4 w-4",
|
|
1057
|
+
"aria-hidden": true
|
|
1058
|
+
}) : title;
|
|
1059
|
+
const className = title === void 0 ? VIEW_CLASS : TITLE_VIEW_CLASS;
|
|
1060
|
+
const testid = tid.relationView(to, fieldName);
|
|
1061
|
+
if (openMode === "page" && (targetDef === void 0 || !linksToPage(app, targetDef))) return plainTitle(title);
|
|
1062
|
+
if (openMode === "page" && by === void 0 && targetDef !== void 0) return jsxs(RouterLink, {
|
|
1063
|
+
href: resourceShowHref(app.registry, targetDef, to, keyString),
|
|
1064
|
+
"data-testid": testid,
|
|
1065
|
+
className,
|
|
1066
|
+
onClick: () => beforeOpen(),
|
|
1067
|
+
children: [jsxs("span", {
|
|
1068
|
+
className: "sr-only",
|
|
1069
|
+
children: [label, " "]
|
|
1070
|
+
}), content]
|
|
1071
|
+
});
|
|
1072
|
+
if (by === void 0 && targetDef !== void 0 && linksToPage(app, targetDef)) return jsxs(ClaimedQuickLink, {
|
|
1073
|
+
href: resourceShowHref(app.registry, targetDef, to, keyString),
|
|
1074
|
+
testid,
|
|
1075
|
+
className,
|
|
1076
|
+
onOpen: () => open(keyString),
|
|
1077
|
+
children: [jsxs("span", {
|
|
1078
|
+
className: "sr-only",
|
|
1079
|
+
children: [label, " "]
|
|
1080
|
+
}), content]
|
|
1081
|
+
});
|
|
1082
|
+
return jsx("button", {
|
|
1083
|
+
type: "button",
|
|
1084
|
+
className,
|
|
1085
|
+
"data-testid": testid,
|
|
1086
|
+
"aria-label": title === void 0 ? label : `${label} ${title}`,
|
|
1087
|
+
[QUICK_ANCHOR_ATTRIBUTE]: "",
|
|
1088
|
+
onClick: (event) => {
|
|
1089
|
+
event.preventDefault();
|
|
1090
|
+
event.stopPropagation();
|
|
1091
|
+
if (!isPlainLeftClick(event)) return;
|
|
1092
|
+
if (by === void 0) {
|
|
1093
|
+
open(keyString);
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
requested.current = true;
|
|
1097
|
+
setAsked(true);
|
|
1098
|
+
if (rows !== void 0 && rows.length === 1) {
|
|
1099
|
+
const next = selectKey(rows[0]?.[idField]);
|
|
1100
|
+
requested.current = false;
|
|
1101
|
+
if (next !== null) open(next);
|
|
1102
|
+
}
|
|
1103
|
+
},
|
|
1104
|
+
children: content
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
//#endregion
|
|
1108
|
+
//#region src/fields/relation-create.tsx
|
|
1109
|
+
function useSelectCreate(input) {
|
|
1110
|
+
const t = useOptionalT();
|
|
1111
|
+
const { to: target } = input;
|
|
1112
|
+
const [pending, setPending] = React.useState(false);
|
|
1113
|
+
const [created, setCreated] = React.useState(null);
|
|
1114
|
+
const latch = React.useRef(false);
|
|
1115
|
+
const mounted = React.useRef(true);
|
|
1116
|
+
React.useEffect(() => {
|
|
1117
|
+
mounted.current = true;
|
|
1118
|
+
return () => {
|
|
1119
|
+
mounted.current = false;
|
|
1120
|
+
};
|
|
1121
|
+
}, []);
|
|
1122
|
+
const latest = React.useRef(input);
|
|
1123
|
+
latest.current = input;
|
|
1124
|
+
const access = useListAccess(target);
|
|
1125
|
+
const blocked = input.held === true || access.status !== "ready" || namesHiddenField(createdOptionScope({
|
|
1126
|
+
fixed: input.fixedFilters,
|
|
1127
|
+
searchDecl: input.searchDecl,
|
|
1128
|
+
searchContext: input.searchContext
|
|
1129
|
+
}), (name) => access.fieldVisible(name));
|
|
1130
|
+
const blockedRef = React.useRef(blocked);
|
|
1131
|
+
blockedRef.current = blocked;
|
|
1132
|
+
const release = React.useCallback(() => {
|
|
1133
|
+
latch.current = false;
|
|
1134
|
+
if (mounted.current) {
|
|
1135
|
+
setPending(false);
|
|
1136
|
+
setCreated(null);
|
|
1137
|
+
}
|
|
1138
|
+
}, []);
|
|
1139
|
+
const start = React.useCallback((open) => {
|
|
1140
|
+
if (latch.current || !mounted.current || blockedRef.current) return;
|
|
1141
|
+
latch.current = true;
|
|
1142
|
+
setPending(true);
|
|
1143
|
+
let opened;
|
|
1144
|
+
try {
|
|
1145
|
+
opened = open();
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
release();
|
|
1148
|
+
throw error;
|
|
1149
|
+
}
|
|
1150
|
+
opened.then((row) => {
|
|
1151
|
+
if (!mounted.current) {
|
|
1152
|
+
latch.current = false;
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
const id = row === null ? null : selectKey(row[latest.current.idField]) ?? selectKey(row.id);
|
|
1156
|
+
if (id === null) release();
|
|
1157
|
+
else setCreated({ id });
|
|
1158
|
+
}, () => release());
|
|
1159
|
+
}, [release]);
|
|
1160
|
+
const settle = React.useCallback((result) => {
|
|
1161
|
+
if (mounted.current) {
|
|
1162
|
+
if (result.kind === "fits") latest.current.onValue(result.value);
|
|
1163
|
+
else if (result.kind === "does-not-fit") toast(t("relationPicker.createdNotFitting", { defaultValue: "The record was created but does not fit this field" }));
|
|
1164
|
+
else toast.error(t("relationPicker.createdNotSelected", { defaultValue: "The record was created but could not be selected" }));
|
|
1165
|
+
}
|
|
1166
|
+
release();
|
|
1167
|
+
}, [release, t]);
|
|
1168
|
+
return {
|
|
1169
|
+
create: React.useMemo(() => ({
|
|
1170
|
+
pending,
|
|
1171
|
+
blocked,
|
|
1172
|
+
start
|
|
1173
|
+
}), [
|
|
1174
|
+
pending,
|
|
1175
|
+
blocked,
|
|
1176
|
+
start
|
|
1177
|
+
]),
|
|
1178
|
+
reader: created === null || blocked ? null : jsx(CreatedOptionRead, {
|
|
1179
|
+
to: target,
|
|
1180
|
+
filter: createdOptionFilter({
|
|
1181
|
+
fixed: input.fixedFilters,
|
|
1182
|
+
idField: input.idField,
|
|
1183
|
+
id: created.id,
|
|
1184
|
+
searchDecl: input.searchDecl,
|
|
1185
|
+
searchContext: input.searchContext
|
|
1186
|
+
}),
|
|
1187
|
+
scope: input.scope,
|
|
1188
|
+
...input.scopeField === void 0 ? {} : { scopeField: input.scopeField },
|
|
1189
|
+
by: input.by,
|
|
1190
|
+
idField: input.idField,
|
|
1191
|
+
onSettled: settle
|
|
1192
|
+
}, created.id)
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
function plainStringField(def) {
|
|
1196
|
+
if (def === null || typeof def !== "object") return false;
|
|
1197
|
+
const field = def;
|
|
1198
|
+
return field.kind === "string" && field.system !== true && field.opts?.system !== true && field.opts?.enum === void 0 && field.opts?.localized !== true;
|
|
1199
|
+
}
|
|
1200
|
+
function RelationCreateButton(props) {
|
|
1201
|
+
const gate = useEntryGate();
|
|
1202
|
+
const { to } = props;
|
|
1203
|
+
if (props.create.blocked || gate(to, "create").state !== "open") return null;
|
|
1204
|
+
return jsx(CreateButton, { ...props });
|
|
1205
|
+
}
|
|
1206
|
+
function CreateButton({ to, fieldName, create, seeds, search, beforeOpen, className, testId }) {
|
|
1207
|
+
const app = useApp();
|
|
1208
|
+
const t = useOptionalT();
|
|
1209
|
+
const tid = useTestIds();
|
|
1210
|
+
const quick = useQuick();
|
|
1211
|
+
const label = t("relationPicker.create", { defaultValue: "+ Create" });
|
|
1212
|
+
return jsx("button", {
|
|
1213
|
+
type: "button",
|
|
1214
|
+
"data-testid": testId ?? tid.relationCreate(to, fieldName),
|
|
1215
|
+
disabled: create.pending,
|
|
1216
|
+
className,
|
|
1217
|
+
onClick: () => {
|
|
1218
|
+
const text = search?.trim() ?? "";
|
|
1219
|
+
const displayField = app.registry.get(to)?.displayField;
|
|
1220
|
+
const fields = app.registry.get(to)?.fields;
|
|
1221
|
+
const prefill = text.length > 0 && typeof displayField === "string" && fields !== void 0 && Object.hasOwn(fields, displayField) && plainStringField(fields[displayField]) ? { [displayField]: text } : void 0;
|
|
1222
|
+
create.start(() => {
|
|
1223
|
+
beforeOpen();
|
|
1224
|
+
return quick.create(to, {
|
|
1225
|
+
...seeds === void 0 || Object.keys(seeds).length === 0 ? {} : { defaults: seeds },
|
|
1226
|
+
...prefill === void 0 ? {} : { input: prefill }
|
|
1227
|
+
});
|
|
1228
|
+
});
|
|
1229
|
+
},
|
|
1230
|
+
children: label
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
//#endregion
|
|
1234
|
+
export { CommandEmpty as C, CommandList as D, CommandItem as E, CommandLoading as O, CommandDialog as S, CommandInput as T, isPlainLeftClick as _, namesHiddenField as a, RecordState as b, RelationField as c, peekAnchorOpener as d, PeekContext as f, ClaimedQuickLink as g, recordDisplayName as h, selectKey as i, CommandSeparator as k, relationLinkClassName as l, useRowTitle as m, useSelectCreate as n, narrowSearchDecl as o, PeekHostContext as p, RelationViewButton as r, RelationDisplay as s, RelationCreateButton as t, focusWithoutPeek as u, InvalidRouteId as v, CommandGroup as w, Command$1 as x, LoadError as y };
|
|
653
1235
|
|
|
654
|
-
//# sourceMappingURL=
|
|
1236
|
+
//# sourceMappingURL=relation-create-C43cdPQt.js.map
|