@cfast/ui 0.0.1 → 0.2.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 +23 -23
- package/dist/chunk-PWBG6CGF.js +1400 -0
- package/dist/{permission-gate-DVmY42oz.d.ts → client-CIx8_tmv.d.ts} +617 -2
- package/dist/client.d.ts +4 -617
- package/dist/client.js +6 -8
- package/dist/index.d.ts +52 -5
- package/dist/index.js +17 -13
- package/llms.txt +159 -0
- package/package.json +25 -41
- package/LICENSE +0 -21
- package/dist/chunk-755IRYDN.js +0 -941
- package/dist/chunk-7SNK37GF.js +0 -418
- package/dist/chunk-ASMYTWTR.js +0 -356
- package/dist/chunk-B2XXH5V4.js +0 -66
- package/dist/chunk-BQMXYYEV.js +0 -348
- package/dist/chunk-DTKBXCTU.js +0 -211
- package/dist/chunk-EYIBATYR.js +0 -33
- package/dist/chunk-FPZAQ2YQ.js +0 -474
- package/dist/chunk-G2OU4BYC.js +0 -205
- package/dist/chunk-JEGEIQ3R.js +0 -925
- package/dist/chunk-JUNLQJ6H.js +0 -1013
- package/dist/chunk-NRGMW3JA.js +0 -906
- package/dist/chunk-Q6FPL2OJ.js +0 -1086
- package/dist/chunk-QHWAGKNW.js +0 -456
- package/dist/chunk-QZT62CGJ.js +0 -924
- package/dist/chunk-RDTUEOLK.js +0 -486
- package/dist/chunk-RESL4IJJ.js +0 -112
- package/dist/chunk-UDCWQUTR.js +0 -221
- package/dist/chunk-UE7PZOIJ.js +0 -11
- package/dist/chunk-UTZTHGNE.js +0 -84
- package/dist/chunk-UVRXMOX5.js +0 -439
- package/dist/chunk-XFD3N2D4.js +0 -161
- package/dist/client-CXIHCQtA.d.ts +0 -274
- package/dist/joy.d.ts +0 -199
- package/dist/joy.js +0 -1150
- package/dist/permission-gate-apt9T9Mu.d.ts +0 -1256
- package/dist/types-1bAiH2uK.d.ts +0 -392
- package/dist/types-BX6u5sAd.d.ts +0 -403
- package/dist/types-BpdY7w5l.d.ts +0 -403
- package/dist/types-BrepeVp8.d.ts +0 -403
- package/dist/types-BvAqMZhn.d.ts +0 -403
- package/dist/types-C74nSscq.d.ts +0 -403
- package/dist/types-DD1Cpx8F.d.ts +0 -403
- package/dist/types-DHUhQwJn.d.ts +0 -403
- package/dist/types-DZSJNt_M.d.ts +0 -392
- package/dist/types-DaaJiIjW.d.ts +0 -391
- package/dist/types-LUpWJwps.d.ts +0 -403
- package/dist/types-a7zVU6WE.d.ts +0 -394
- package/dist/types-biJTHMcH.d.ts +0 -403
- package/dist/types-ow_qSEYJ.d.ts +0 -392
- package/dist/types-wnLasZaB.d.ts +0 -1234
package/dist/chunk-FPZAQ2YQ.js
DELETED
|
@@ -1,474 +0,0 @@
|
|
|
1
|
-
// src/plugin.ts
|
|
2
|
-
import { createContext, useContext, createElement as createElement2 } from "react";
|
|
3
|
-
|
|
4
|
-
// src/headless-defaults.ts
|
|
5
|
-
import { createElement } from "react";
|
|
6
|
-
var headlessDefaults = {
|
|
7
|
-
// Actions
|
|
8
|
-
button: ({ children, onClick, disabled, loading, type }) => createElement(
|
|
9
|
-
"button",
|
|
10
|
-
{ onClick, disabled: disabled || loading, type: type ?? "button" },
|
|
11
|
-
loading ? "Loading..." : children
|
|
12
|
-
),
|
|
13
|
-
tooltip: ({ children, title }) => createElement("span", { title }, children),
|
|
14
|
-
confirmDialog: ({ open, onClose, onConfirm, title, description, confirmLabel, cancelLabel }) => open ? createElement(
|
|
15
|
-
"dialog",
|
|
16
|
-
{ open: true },
|
|
17
|
-
createElement("p", null, createElement("strong", null, title)),
|
|
18
|
-
description ? createElement("p", null, description) : null,
|
|
19
|
-
createElement(
|
|
20
|
-
"div",
|
|
21
|
-
null,
|
|
22
|
-
createElement("button", { onClick: onClose }, cancelLabel ?? "Cancel"),
|
|
23
|
-
createElement("button", { onClick: onConfirm }, confirmLabel ?? "Confirm")
|
|
24
|
-
)
|
|
25
|
-
) : null,
|
|
26
|
-
// Data display
|
|
27
|
-
table: ({ children }) => createElement("table", null, children),
|
|
28
|
-
tableHead: ({ children }) => createElement("thead", null, children),
|
|
29
|
-
tableBody: ({ children }) => createElement("tbody", null, children),
|
|
30
|
-
tableRow: ({ children, onClick }) => createElement("tr", { onClick }, children),
|
|
31
|
-
tableCell: ({ children, header, sortable, sortDirection, onSort }) => createElement(
|
|
32
|
-
header ? "th" : "td",
|
|
33
|
-
{
|
|
34
|
-
onClick: sortable ? onSort : void 0,
|
|
35
|
-
style: sortable ? { cursor: "pointer" } : void 0
|
|
36
|
-
},
|
|
37
|
-
children,
|
|
38
|
-
sortable && sortDirection ? sortDirection === "asc" ? " \u2191" : " \u2193" : null
|
|
39
|
-
),
|
|
40
|
-
chip: ({ children, size }) => createElement(
|
|
41
|
-
"span",
|
|
42
|
-
{
|
|
43
|
-
style: {
|
|
44
|
-
display: "inline-block",
|
|
45
|
-
padding: size === "sm" ? "1px 6px" : "2px 8px",
|
|
46
|
-
borderRadius: "12px",
|
|
47
|
-
fontSize: size === "sm" ? "12px" : "14px",
|
|
48
|
-
backgroundColor: "#eee"
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
children
|
|
52
|
-
),
|
|
53
|
-
// Layout
|
|
54
|
-
appShell: ({ children, sidebar, header }) => createElement(
|
|
55
|
-
"div",
|
|
56
|
-
{ style: { display: "flex", minHeight: "100vh" } },
|
|
57
|
-
sidebar ? createElement("nav", null, sidebar) : null,
|
|
58
|
-
createElement(
|
|
59
|
-
"div",
|
|
60
|
-
{ style: { flex: 1 } },
|
|
61
|
-
header ?? null,
|
|
62
|
-
createElement("main", null, children)
|
|
63
|
-
)
|
|
64
|
-
),
|
|
65
|
-
sidebar: ({ children }) => createElement(
|
|
66
|
-
"aside",
|
|
67
|
-
{ style: { width: "240px", borderRight: "1px solid #ddd" } },
|
|
68
|
-
children
|
|
69
|
-
),
|
|
70
|
-
pageContainer: ({ children, title, actions }) => createElement(
|
|
71
|
-
"div",
|
|
72
|
-
null,
|
|
73
|
-
title || actions ? createElement(
|
|
74
|
-
"div",
|
|
75
|
-
{ style: { display: "flex", justifyContent: "space-between", alignItems: "center" } },
|
|
76
|
-
title ? createElement("h1", null, title) : null,
|
|
77
|
-
actions ?? null
|
|
78
|
-
) : null,
|
|
79
|
-
children
|
|
80
|
-
),
|
|
81
|
-
breadcrumb: ({ items }) => createElement(
|
|
82
|
-
"nav",
|
|
83
|
-
{ "aria-label": "breadcrumb" },
|
|
84
|
-
items.map(
|
|
85
|
-
(item, i) => createElement(
|
|
86
|
-
"span",
|
|
87
|
-
{ key: i },
|
|
88
|
-
i > 0 ? " / " : null,
|
|
89
|
-
item.to ? createElement("a", { href: item.to }, item.label) : item.label
|
|
90
|
-
)
|
|
91
|
-
)
|
|
92
|
-
),
|
|
93
|
-
// Feedback
|
|
94
|
-
toast: ({ children }) => createElement("div", null, children),
|
|
95
|
-
alert: ({ children, color }) => createElement(
|
|
96
|
-
"div",
|
|
97
|
-
{
|
|
98
|
-
role: "alert",
|
|
99
|
-
style: {
|
|
100
|
-
padding: "8px 12px",
|
|
101
|
-
borderRadius: "4px",
|
|
102
|
-
backgroundColor: color === "danger" ? "#fee" : color === "success" ? "#efe" : color === "warning" ? "#ffe" : "#f5f5f5"
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
children
|
|
106
|
-
),
|
|
107
|
-
// File
|
|
108
|
-
dropZone: ({ children, isDragOver, onClick, onDrop, onDragOver, onDragLeave }) => createElement(
|
|
109
|
-
"div",
|
|
110
|
-
{
|
|
111
|
-
onClick,
|
|
112
|
-
onDrop: (e) => {
|
|
113
|
-
e.preventDefault();
|
|
114
|
-
onDrop(e.dataTransfer.files);
|
|
115
|
-
},
|
|
116
|
-
onDragOver: (e) => {
|
|
117
|
-
e.preventDefault();
|
|
118
|
-
onDragOver(e);
|
|
119
|
-
},
|
|
120
|
-
onDragLeave,
|
|
121
|
-
style: {
|
|
122
|
-
border: `2px dashed ${isDragOver ? "#4caf50" : "#ccc"}`,
|
|
123
|
-
borderRadius: "8px",
|
|
124
|
-
padding: "32px",
|
|
125
|
-
textAlign: "center",
|
|
126
|
-
cursor: "pointer"
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
children
|
|
130
|
-
)
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// src/plugin.ts
|
|
134
|
-
var UIPluginContext = createContext(null);
|
|
135
|
-
function createUIPlugin(config) {
|
|
136
|
-
return { components: config.components };
|
|
137
|
-
}
|
|
138
|
-
function UIPluginProvider({
|
|
139
|
-
plugin,
|
|
140
|
-
children
|
|
141
|
-
}) {
|
|
142
|
-
return createElement2(UIPluginContext.Provider, { value: plugin }, children);
|
|
143
|
-
}
|
|
144
|
-
function useUIPlugin() {
|
|
145
|
-
return useContext(UIPluginContext);
|
|
146
|
-
}
|
|
147
|
-
function useComponent(slot) {
|
|
148
|
-
const plugin = useUIPlugin();
|
|
149
|
-
const component = plugin?.components[slot];
|
|
150
|
-
if (component) {
|
|
151
|
-
return component;
|
|
152
|
-
}
|
|
153
|
-
return headlessDefaults[slot];
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// src/hooks/use-action-status.ts
|
|
157
|
-
import { useActions } from "@cfast/actions/client";
|
|
158
|
-
function useActionStatus(descriptor, actionName, input) {
|
|
159
|
-
const actions = useActions(descriptor);
|
|
160
|
-
const name = actionName ?? descriptor.actionNames[0];
|
|
161
|
-
const actionFn = actions[name];
|
|
162
|
-
if (!actionFn) {
|
|
163
|
-
return {
|
|
164
|
-
permitted: false,
|
|
165
|
-
invisible: true,
|
|
166
|
-
reason: `Action "${name}" not found in descriptor`,
|
|
167
|
-
submit: () => {
|
|
168
|
-
},
|
|
169
|
-
pending: false,
|
|
170
|
-
data: void 0,
|
|
171
|
-
error: void 0
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
const result = actionFn(input);
|
|
175
|
-
return {
|
|
176
|
-
permitted: result.permitted,
|
|
177
|
-
invisible: result.invisible,
|
|
178
|
-
reason: result.reason,
|
|
179
|
-
submit: result.submit,
|
|
180
|
-
pending: result.pending,
|
|
181
|
-
data: result.data,
|
|
182
|
-
error: result.error
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// src/hooks/use-toast.ts
|
|
187
|
-
import { createContext as createContext2, useContext as useContext2, useCallback } from "react";
|
|
188
|
-
var ToastContext = createContext2(null);
|
|
189
|
-
function useToast() {
|
|
190
|
-
const ctx = useContext2(ToastContext);
|
|
191
|
-
if (!ctx) {
|
|
192
|
-
throw new Error("useToast must be used within a <ToastProvider>");
|
|
193
|
-
}
|
|
194
|
-
const show = useCallback(
|
|
195
|
-
(options) => ctx.show(options),
|
|
196
|
-
[ctx]
|
|
197
|
-
);
|
|
198
|
-
const success = useCallback(
|
|
199
|
-
(message, description) => ctx.show({ message, type: "success", description }),
|
|
200
|
-
[ctx]
|
|
201
|
-
);
|
|
202
|
-
const error = useCallback(
|
|
203
|
-
(message, description) => ctx.show({ message, type: "error", description }),
|
|
204
|
-
[ctx]
|
|
205
|
-
);
|
|
206
|
-
const info = useCallback(
|
|
207
|
-
(message, description) => ctx.show({ message, type: "info", description }),
|
|
208
|
-
[ctx]
|
|
209
|
-
);
|
|
210
|
-
const warning = useCallback(
|
|
211
|
-
(message, description) => ctx.show({ message, type: "warning", description }),
|
|
212
|
-
[ctx]
|
|
213
|
-
);
|
|
214
|
-
return { show, success, error, info, warning };
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// src/components/avatar-with-initials.tsx
|
|
218
|
-
import { createElement as createElement3 } from "react";
|
|
219
|
-
function getInitials(name) {
|
|
220
|
-
return name.split(" ").map((part) => part[0]).join("").toUpperCase().slice(0, 2);
|
|
221
|
-
}
|
|
222
|
-
var sizeMap = { sm: 32, md: 40, lg: 56 };
|
|
223
|
-
function AvatarWithInitials({
|
|
224
|
-
src,
|
|
225
|
-
name,
|
|
226
|
-
size = "md"
|
|
227
|
-
}) {
|
|
228
|
-
const px = sizeMap[size];
|
|
229
|
-
if (src) {
|
|
230
|
-
return createElement3("img", {
|
|
231
|
-
src,
|
|
232
|
-
alt: name,
|
|
233
|
-
style: {
|
|
234
|
-
width: px,
|
|
235
|
-
height: px,
|
|
236
|
-
borderRadius: "50%",
|
|
237
|
-
objectFit: "cover"
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
return createElement3(
|
|
242
|
-
"span",
|
|
243
|
-
{
|
|
244
|
-
"aria-label": name,
|
|
245
|
-
style: {
|
|
246
|
-
display: "inline-flex",
|
|
247
|
-
alignItems: "center",
|
|
248
|
-
justifyContent: "center",
|
|
249
|
-
width: px,
|
|
250
|
-
height: px,
|
|
251
|
-
borderRadius: "50%",
|
|
252
|
-
backgroundColor: "#ddd",
|
|
253
|
-
fontSize: px * 0.4,
|
|
254
|
-
fontWeight: "bold"
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
getInitials(name)
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// src/fields/date-field.tsx
|
|
262
|
-
import { createElement as createElement4 } from "react";
|
|
263
|
-
var rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
|
|
264
|
-
function getRelativeTime(date) {
|
|
265
|
-
const now = Date.now();
|
|
266
|
-
const diffMs = date.getTime() - now;
|
|
267
|
-
const diffSec = Math.round(diffMs / 1e3);
|
|
268
|
-
const diffMin = Math.round(diffSec / 60);
|
|
269
|
-
const diffHour = Math.round(diffMin / 60);
|
|
270
|
-
const diffDay = Math.round(diffHour / 24);
|
|
271
|
-
if (Math.abs(diffSec) < 60) return rtf.format(diffSec, "second");
|
|
272
|
-
if (Math.abs(diffMin) < 60) return rtf.format(diffMin, "minute");
|
|
273
|
-
if (Math.abs(diffHour) < 24) return rtf.format(diffHour, "hour");
|
|
274
|
-
if (Math.abs(diffDay) < 30) return rtf.format(diffDay, "day");
|
|
275
|
-
const diffMonth = Math.round(diffDay / 30);
|
|
276
|
-
if (Math.abs(diffMonth) < 12) return rtf.format(diffMonth, "month");
|
|
277
|
-
return rtf.format(Math.round(diffDay / 365), "year");
|
|
278
|
-
}
|
|
279
|
-
function formatDate(date, format, locale) {
|
|
280
|
-
switch (format) {
|
|
281
|
-
case "relative":
|
|
282
|
-
return getRelativeTime(date);
|
|
283
|
-
case "long":
|
|
284
|
-
return new Intl.DateTimeFormat(locale, {
|
|
285
|
-
dateStyle: "long"
|
|
286
|
-
}).format(date);
|
|
287
|
-
case "datetime":
|
|
288
|
-
return new Intl.DateTimeFormat(locale, {
|
|
289
|
-
dateStyle: "medium",
|
|
290
|
-
timeStyle: "short"
|
|
291
|
-
}).format(date);
|
|
292
|
-
case "short":
|
|
293
|
-
default:
|
|
294
|
-
return new Intl.DateTimeFormat(locale, {
|
|
295
|
-
dateStyle: "medium"
|
|
296
|
-
}).format(date);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
function DateField({
|
|
300
|
-
value,
|
|
301
|
-
format = "short",
|
|
302
|
-
locale = "en"
|
|
303
|
-
}) {
|
|
304
|
-
if (value == null) {
|
|
305
|
-
return createElement4("span", null, "\u2014");
|
|
306
|
-
}
|
|
307
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
308
|
-
if (Number.isNaN(date.getTime())) {
|
|
309
|
-
return createElement4("span", null, "Invalid date");
|
|
310
|
-
}
|
|
311
|
-
return createElement4("time", { dateTime: date.toISOString() }, formatDate(date, format, locale));
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// src/fields/boolean-field.tsx
|
|
315
|
-
import { createElement as createElement5 } from "react";
|
|
316
|
-
function BooleanField({
|
|
317
|
-
value,
|
|
318
|
-
trueLabel = "Yes",
|
|
319
|
-
falseLabel = "No",
|
|
320
|
-
trueColor = "success",
|
|
321
|
-
falseColor = "neutral"
|
|
322
|
-
}) {
|
|
323
|
-
const Chip = useComponent("chip");
|
|
324
|
-
if (value == null) {
|
|
325
|
-
return createElement5("span", null, "\u2014");
|
|
326
|
-
}
|
|
327
|
-
return createElement5(Chip, {
|
|
328
|
-
children: value ? trueLabel : falseLabel,
|
|
329
|
-
color: value ? trueColor : falseColor,
|
|
330
|
-
variant: "soft",
|
|
331
|
-
size: "sm"
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// src/fields/number-field.tsx
|
|
336
|
-
import { createElement as createElement6 } from "react";
|
|
337
|
-
function NumberField({
|
|
338
|
-
value,
|
|
339
|
-
locale = "en",
|
|
340
|
-
currency,
|
|
341
|
-
decimals
|
|
342
|
-
}) {
|
|
343
|
-
if (value == null) {
|
|
344
|
-
return createElement6("span", null, "\u2014");
|
|
345
|
-
}
|
|
346
|
-
const options = {};
|
|
347
|
-
if (currency) {
|
|
348
|
-
options.style = "currency";
|
|
349
|
-
options.currency = currency;
|
|
350
|
-
}
|
|
351
|
-
if (decimals !== void 0) {
|
|
352
|
-
options.minimumFractionDigits = decimals;
|
|
353
|
-
options.maximumFractionDigits = decimals;
|
|
354
|
-
}
|
|
355
|
-
const formatted = new Intl.NumberFormat(locale, options).format(value);
|
|
356
|
-
return createElement6("span", null, formatted);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// src/fields/text-field.tsx
|
|
360
|
-
import { createElement as createElement7 } from "react";
|
|
361
|
-
function TextField({
|
|
362
|
-
value,
|
|
363
|
-
maxLength
|
|
364
|
-
}) {
|
|
365
|
-
if (value == null) {
|
|
366
|
-
return createElement7("span", null, "\u2014");
|
|
367
|
-
}
|
|
368
|
-
const display = maxLength && value.length > maxLength ? `${value.slice(0, maxLength)}\u2026` : value;
|
|
369
|
-
if (maxLength && value.length > maxLength) {
|
|
370
|
-
return createElement7("span", { title: value }, display);
|
|
371
|
-
}
|
|
372
|
-
return createElement7("span", null, display);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// src/fields/email-field.tsx
|
|
376
|
-
import { createElement as createElement8 } from "react";
|
|
377
|
-
function EmailField({ value }) {
|
|
378
|
-
if (value == null) {
|
|
379
|
-
return createElement8("span", null, "\u2014");
|
|
380
|
-
}
|
|
381
|
-
return createElement8("a", { href: `mailto:${value}` }, value);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// src/fields/json-field.tsx
|
|
385
|
-
import { createElement as createElement9, useState } from "react";
|
|
386
|
-
function JsonField({
|
|
387
|
-
value,
|
|
388
|
-
collapsed = false
|
|
389
|
-
}) {
|
|
390
|
-
const [isCollapsed, setIsCollapsed] = useState(collapsed);
|
|
391
|
-
if (value == null) {
|
|
392
|
-
return createElement9("span", null, "\u2014");
|
|
393
|
-
}
|
|
394
|
-
const formatted = JSON.stringify(value, null, 2);
|
|
395
|
-
if (isCollapsed) {
|
|
396
|
-
const preview = JSON.stringify(value);
|
|
397
|
-
const short = preview.length > 60 ? `${preview.slice(0, 60)}\u2026` : preview;
|
|
398
|
-
return createElement9(
|
|
399
|
-
"span",
|
|
400
|
-
null,
|
|
401
|
-
createElement9("code", null, short),
|
|
402
|
-
" ",
|
|
403
|
-
createElement9("button", {
|
|
404
|
-
onClick: () => setIsCollapsed(false),
|
|
405
|
-
style: { border: "none", background: "none", cursor: "pointer", color: "#666", fontSize: "12px" }
|
|
406
|
-
}, "expand")
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
return createElement9(
|
|
410
|
-
"pre",
|
|
411
|
-
{
|
|
412
|
-
style: {
|
|
413
|
-
margin: 0,
|
|
414
|
-
fontSize: "13px",
|
|
415
|
-
backgroundColor: "#f5f5f5",
|
|
416
|
-
padding: "8px",
|
|
417
|
-
borderRadius: "4px",
|
|
418
|
-
overflow: "auto"
|
|
419
|
-
}
|
|
420
|
-
},
|
|
421
|
-
createElement9("code", null, formatted)
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// src/fields/field-for-column.ts
|
|
426
|
-
function fieldForColumn(column) {
|
|
427
|
-
const { dataType, name } = column;
|
|
428
|
-
const dt = dataType.toLowerCase();
|
|
429
|
-
if (dt === "boolean" || dt === "integer" && name.startsWith("is")) {
|
|
430
|
-
return BooleanField;
|
|
431
|
-
}
|
|
432
|
-
if (dt.includes("timestamp") || dt.includes("date") || dt.includes("datetime")) {
|
|
433
|
-
return DateField;
|
|
434
|
-
}
|
|
435
|
-
if (dt === "integer" || dt === "real" || dt === "numeric" || dt.includes("int") || dt.includes("float") || dt.includes("double") || dt.includes("decimal")) {
|
|
436
|
-
return NumberField;
|
|
437
|
-
}
|
|
438
|
-
if (name === "email" || name.endsWith("Email")) {
|
|
439
|
-
return EmailField;
|
|
440
|
-
}
|
|
441
|
-
if (dt === "json" || dt === "jsonb" || dt === "blob") {
|
|
442
|
-
return JsonField;
|
|
443
|
-
}
|
|
444
|
-
return TextField;
|
|
445
|
-
}
|
|
446
|
-
function fieldsForTable(table) {
|
|
447
|
-
const result = {};
|
|
448
|
-
for (const [key, col] of Object.entries(table)) {
|
|
449
|
-
if (col && typeof col === "object" && "dataType" in col && "name" in col) {
|
|
450
|
-
result[key] = fieldForColumn(col);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
return result;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
export {
|
|
457
|
-
createUIPlugin,
|
|
458
|
-
UIPluginProvider,
|
|
459
|
-
useUIPlugin,
|
|
460
|
-
useComponent,
|
|
461
|
-
useActionStatus,
|
|
462
|
-
ToastContext,
|
|
463
|
-
useToast,
|
|
464
|
-
getInitials,
|
|
465
|
-
AvatarWithInitials,
|
|
466
|
-
DateField,
|
|
467
|
-
BooleanField,
|
|
468
|
-
NumberField,
|
|
469
|
-
TextField,
|
|
470
|
-
EmailField,
|
|
471
|
-
JsonField,
|
|
472
|
-
fieldForColumn,
|
|
473
|
-
fieldsForTable
|
|
474
|
-
};
|
package/dist/chunk-G2OU4BYC.js
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
// src/plugin.ts
|
|
2
|
-
import { createContext, useContext, createElement as createElement2 } from "react";
|
|
3
|
-
|
|
4
|
-
// src/headless-defaults.ts
|
|
5
|
-
import { createElement } from "react";
|
|
6
|
-
var headlessDefaults = {
|
|
7
|
-
// Actions
|
|
8
|
-
button: ({ children, onClick, disabled, loading, type }) => createElement(
|
|
9
|
-
"button",
|
|
10
|
-
{ onClick, disabled: disabled || loading, type: type ?? "button" },
|
|
11
|
-
loading ? "Loading..." : children
|
|
12
|
-
),
|
|
13
|
-
tooltip: ({ children, title }) => createElement("span", { title }, children),
|
|
14
|
-
confirmDialog: ({ open, onClose, onConfirm, title, description, confirmLabel, cancelLabel }) => open ? createElement(
|
|
15
|
-
"dialog",
|
|
16
|
-
{ open: true },
|
|
17
|
-
createElement("p", null, createElement("strong", null, title)),
|
|
18
|
-
description ? createElement("p", null, description) : null,
|
|
19
|
-
createElement(
|
|
20
|
-
"div",
|
|
21
|
-
null,
|
|
22
|
-
createElement("button", { onClick: onClose }, cancelLabel ?? "Cancel"),
|
|
23
|
-
createElement("button", { onClick: onConfirm }, confirmLabel ?? "Confirm")
|
|
24
|
-
)
|
|
25
|
-
) : null,
|
|
26
|
-
// Data display
|
|
27
|
-
table: ({ children }) => createElement("table", null, children),
|
|
28
|
-
tableHead: ({ children }) => createElement("thead", null, children),
|
|
29
|
-
tableBody: ({ children }) => createElement("tbody", null, children),
|
|
30
|
-
tableRow: ({ children, onClick }) => createElement("tr", { onClick }, children),
|
|
31
|
-
tableCell: ({ children, header, sortable, sortDirection, onSort }) => createElement(
|
|
32
|
-
header ? "th" : "td",
|
|
33
|
-
{
|
|
34
|
-
onClick: sortable ? onSort : void 0,
|
|
35
|
-
style: sortable ? { cursor: "pointer" } : void 0
|
|
36
|
-
},
|
|
37
|
-
children,
|
|
38
|
-
sortable && sortDirection ? sortDirection === "asc" ? " \u2191" : " \u2193" : null
|
|
39
|
-
),
|
|
40
|
-
chip: ({ children, size }) => createElement(
|
|
41
|
-
"span",
|
|
42
|
-
{
|
|
43
|
-
style: {
|
|
44
|
-
display: "inline-block",
|
|
45
|
-
padding: size === "sm" ? "1px 6px" : "2px 8px",
|
|
46
|
-
borderRadius: "12px",
|
|
47
|
-
fontSize: size === "sm" ? "12px" : "14px",
|
|
48
|
-
backgroundColor: "#eee"
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
children
|
|
52
|
-
),
|
|
53
|
-
// Layout
|
|
54
|
-
appShell: ({ children, sidebar, header }) => createElement(
|
|
55
|
-
"div",
|
|
56
|
-
{ style: { display: "flex", minHeight: "100vh" } },
|
|
57
|
-
sidebar ? createElement("nav", null, sidebar) : null,
|
|
58
|
-
createElement(
|
|
59
|
-
"div",
|
|
60
|
-
{ style: { flex: 1 } },
|
|
61
|
-
header ?? null,
|
|
62
|
-
createElement("main", null, children)
|
|
63
|
-
)
|
|
64
|
-
),
|
|
65
|
-
sidebar: ({ children }) => createElement(
|
|
66
|
-
"aside",
|
|
67
|
-
{ style: { width: "240px", borderRight: "1px solid #ddd" } },
|
|
68
|
-
children
|
|
69
|
-
),
|
|
70
|
-
pageContainer: ({ children, title, actions }) => createElement(
|
|
71
|
-
"div",
|
|
72
|
-
null,
|
|
73
|
-
title || actions ? createElement(
|
|
74
|
-
"div",
|
|
75
|
-
{ style: { display: "flex", justifyContent: "space-between", alignItems: "center" } },
|
|
76
|
-
title ? createElement("h1", null, title) : null,
|
|
77
|
-
actions ?? null
|
|
78
|
-
) : null,
|
|
79
|
-
children
|
|
80
|
-
),
|
|
81
|
-
breadcrumb: ({ items }) => createElement(
|
|
82
|
-
"nav",
|
|
83
|
-
{ "aria-label": "breadcrumb" },
|
|
84
|
-
items.map(
|
|
85
|
-
(item, i) => createElement(
|
|
86
|
-
"span",
|
|
87
|
-
{ key: i },
|
|
88
|
-
i > 0 ? " / " : null,
|
|
89
|
-
item.to ? createElement("a", { href: item.to }, item.label) : item.label
|
|
90
|
-
)
|
|
91
|
-
)
|
|
92
|
-
),
|
|
93
|
-
// Feedback
|
|
94
|
-
toast: ({ children }) => createElement("div", null, children),
|
|
95
|
-
alert: ({ children, color }) => createElement(
|
|
96
|
-
"div",
|
|
97
|
-
{
|
|
98
|
-
role: "alert",
|
|
99
|
-
style: {
|
|
100
|
-
padding: "8px 12px",
|
|
101
|
-
borderRadius: "4px",
|
|
102
|
-
backgroundColor: color === "danger" ? "#fee" : color === "success" ? "#efe" : color === "warning" ? "#ffe" : "#f5f5f5"
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
children
|
|
106
|
-
),
|
|
107
|
-
// File
|
|
108
|
-
dropZone: ({ children, isDragOver, onClick, onDrop, onDragOver, onDragLeave }) => createElement(
|
|
109
|
-
"div",
|
|
110
|
-
{
|
|
111
|
-
onClick,
|
|
112
|
-
onDrop: (e) => {
|
|
113
|
-
e.preventDefault();
|
|
114
|
-
onDrop(e.dataTransfer.files);
|
|
115
|
-
},
|
|
116
|
-
onDragOver: (e) => {
|
|
117
|
-
e.preventDefault();
|
|
118
|
-
onDragOver(e);
|
|
119
|
-
},
|
|
120
|
-
onDragLeave,
|
|
121
|
-
style: {
|
|
122
|
-
border: `2px dashed ${isDragOver ? "#4caf50" : "#ccc"}`,
|
|
123
|
-
borderRadius: "8px",
|
|
124
|
-
padding: "32px",
|
|
125
|
-
textAlign: "center",
|
|
126
|
-
cursor: "pointer"
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
children
|
|
130
|
-
)
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// src/plugin.ts
|
|
134
|
-
var UIPluginContext = createContext(null);
|
|
135
|
-
function createUIPlugin(config) {
|
|
136
|
-
return { components: config.components };
|
|
137
|
-
}
|
|
138
|
-
function UIPluginProvider({
|
|
139
|
-
plugin,
|
|
140
|
-
children
|
|
141
|
-
}) {
|
|
142
|
-
return createElement2(UIPluginContext.Provider, { value: plugin }, children);
|
|
143
|
-
}
|
|
144
|
-
function useUIPlugin() {
|
|
145
|
-
return useContext(UIPluginContext);
|
|
146
|
-
}
|
|
147
|
-
function useComponent(slot) {
|
|
148
|
-
const plugin = useUIPlugin();
|
|
149
|
-
const component = plugin?.components[slot];
|
|
150
|
-
if (component) {
|
|
151
|
-
return component;
|
|
152
|
-
}
|
|
153
|
-
return headlessDefaults[slot];
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// src/components/permission-gate.tsx
|
|
157
|
-
import { createElement as createElement3, Fragment } from "react";
|
|
158
|
-
function PermissionGate({
|
|
159
|
-
action,
|
|
160
|
-
children,
|
|
161
|
-
fallback
|
|
162
|
-
}) {
|
|
163
|
-
if (action.invisible) {
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
if (!action.permitted) {
|
|
167
|
-
return fallback ? createElement3(Fragment, null, fallback) : null;
|
|
168
|
-
}
|
|
169
|
-
return createElement3(Fragment, null, children);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// src/components/action-button.tsx
|
|
173
|
-
import { createElement as createElement4 } from "react";
|
|
174
|
-
function ActionButton({
|
|
175
|
-
action,
|
|
176
|
-
children,
|
|
177
|
-
whenForbidden = "disable",
|
|
178
|
-
confirmation: _confirmation,
|
|
179
|
-
...buttonProps
|
|
180
|
-
}) {
|
|
181
|
-
const Button = useComponent("button");
|
|
182
|
-
if (action.invisible) {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
if (!action.permitted && whenForbidden === "hide") {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
const disabled = !action.permitted && whenForbidden === "disable";
|
|
189
|
-
return createElement4(Button, {
|
|
190
|
-
...buttonProps,
|
|
191
|
-
children,
|
|
192
|
-
onClick: () => action.submit(),
|
|
193
|
-
disabled,
|
|
194
|
-
loading: action.pending
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export {
|
|
199
|
-
createUIPlugin,
|
|
200
|
-
UIPluginProvider,
|
|
201
|
-
useUIPlugin,
|
|
202
|
-
useComponent,
|
|
203
|
-
PermissionGate,
|
|
204
|
-
ActionButton
|
|
205
|
-
};
|