@ramme-io/ui 4.2.3 → 4.2.4
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/dist/blocks/ai/Actions.js +8 -4
- package/dist/blocks/ai/PromptInput.js +13 -5
- package/dist/components/data-display/DataTable.d.ts +17 -2
- package/dist/components/data-display/DataTable.js +61 -49
- package/dist/components/data-display/_DataTableCards.d.ts +33 -0
- package/dist/components/data-display/_DataTableCards.js +153 -0
- package/dist/components/feedback/Plan.js +1 -1
- package/dist/components/forms/DatePicker.js +19 -5
- package/dist/components/showroom/ShowroomSidebar.js +1 -1
- package/dist/components/theme/FineTuningControls.js +8 -8
- package/dist/index.css +1 -1
- package/dist/wizardManifest.js +33 -5
- package/package.json +2 -2
- package/src/wizardManifest.ts +33 -5
- package/dist/formFieldFloor.test.d.ts +0 -1
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
const
|
|
1
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
+
const n = ({ children: e, onClick: r }) => (
|
|
3
|
+
// min-h-11 is the 44px tap target (AGENTS.md Zero Jank rule 8) — these sat at
|
|
4
|
+
// 38px with the open chat panel measured at 360px wide.
|
|
5
|
+
/* @__PURE__ */ t("button", { onClick: r, className: "inline-flex min-h-11 items-center justify-center px-3 bg-card-alt hover:bg-bg-hover border border-border rounded-full text-sm text-muted-foreground transition-colors", children: e })
|
|
6
|
+
), s = ({ children: e }) => /* @__PURE__ */ t("div", { className: "flex flex-wrap gap-2 mt-3", children: e });
|
|
3
7
|
export {
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
s as Actions,
|
|
9
|
+
n as Suggestion
|
|
6
10
|
};
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { jsxs as s, jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import { Icon as m } from "../../components/ui/Icon.js";
|
|
3
|
-
const
|
|
3
|
+
const l = ({ value: r, onChange: t, onSubmit: n, placeholder: o = "Type your message..." }) => /* @__PURE__ */ s("form", { onSubmit: n, className: "flex items-center p-2 border-t border-border", children: [
|
|
4
4
|
/* @__PURE__ */ e(
|
|
5
5
|
"input",
|
|
6
6
|
{
|
|
7
7
|
type: "text",
|
|
8
|
-
placeholder:
|
|
9
|
-
className: "flex-1 p-2 bg-transparent focus:outline-none text-foreground",
|
|
8
|
+
placeholder: o,
|
|
9
|
+
className: "flex-1 min-h-11 p-2 bg-transparent focus:outline-none text-foreground",
|
|
10
10
|
value: r,
|
|
11
11
|
onChange: t
|
|
12
12
|
}
|
|
13
13
|
),
|
|
14
|
-
/* @__PURE__ */ e(
|
|
14
|
+
/* @__PURE__ */ e(
|
|
15
|
+
"button",
|
|
16
|
+
{
|
|
17
|
+
type: "submit",
|
|
18
|
+
"aria-label": "Send message",
|
|
19
|
+
className: "-mr-2 inline-flex min-h-11 min-w-11 items-center justify-center text-primary hover:bg-primary/10 rounded-full transition-colors",
|
|
20
|
+
children: /* @__PURE__ */ e(m, { name: "send" })
|
|
21
|
+
}
|
|
22
|
+
)
|
|
15
23
|
] });
|
|
16
24
|
export {
|
|
17
|
-
|
|
25
|
+
l as PromptInput
|
|
18
26
|
};
|
|
@@ -4,10 +4,15 @@ import { type DataFormat } from '../../lib/formatters';
|
|
|
4
4
|
/**
|
|
5
5
|
* @wizard
|
|
6
6
|
* @name DataTable
|
|
7
|
-
* @description A "Smart" data grid that renders data based on a simple JSON schema.
|
|
8
|
-
* @tags data-display, grid, table, smart-component
|
|
7
|
+
* @description A "Smart" data grid that renders data based on a simple JSON schema. Below 768px it renders the same rows as cards instead, derived from the column definitions — no second layout to write. Set mobileCards={false} to keep the grid at every width.
|
|
8
|
+
* @tags data-display, grid, table, smart-component, responsive, mobile
|
|
9
9
|
* @category data-display
|
|
10
10
|
* @id data-table
|
|
11
|
+
* @param {ColumnSchema[]} schema - Columns as a JSON schema; an alternative to passing columnDefs.
|
|
12
|
+
* @param {TableAction[]} actions - Per-row icon buttons, pinned right in the grid and shown in the card footer.
|
|
13
|
+
* @param {boolean} mobileCards - Render rows as cards below 768px. Default true.
|
|
14
|
+
* @param {ReactNode} emptyState - Shown instead of the grid or the cards when there are no rows.
|
|
15
|
+
* @param {boolean} loading - Shows a loading overlay in the grid, skeleton cards on a phone.
|
|
11
16
|
*/
|
|
12
17
|
export interface ColumnSchema {
|
|
13
18
|
key: string;
|
|
@@ -29,5 +34,15 @@ export interface DataTableProps extends AgGridReactProps {
|
|
|
29
34
|
actions?: TableAction[];
|
|
30
35
|
emptyState?: React.ReactNode;
|
|
31
36
|
loading?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Render rows as cards below 768px instead of a horizontally scrolling grid.
|
|
39
|
+
*
|
|
40
|
+
* Defaults to ON. A grid is a horizontal instrument and a phone is not: the
|
|
41
|
+
* risk watchlist declares eight columns with one pinned each side, so at
|
|
42
|
+
* 360px a reader got the two pinned columns and a sliver of the six carrying
|
|
43
|
+
* the actual data. Opting out is for a table that genuinely needs to stay a
|
|
44
|
+
* table — a wide matrix read by comparing rows down a column.
|
|
45
|
+
*/
|
|
46
|
+
mobileCards?: boolean;
|
|
32
47
|
}
|
|
33
48
|
export declare const DataTable: React.FC<DataTableProps>;
|
|
@@ -1,92 +1,104 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useMemo as
|
|
3
|
-
import { AgGridReact as
|
|
4
|
-
import { formatValue as
|
|
5
|
-
import { Button as
|
|
6
|
-
import { Icon as
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as d } from "react";
|
|
3
|
+
import { AgGridReact as w } from "ag-grid-react";
|
|
4
|
+
import { formatValue as x } from "../../lib/formatters.js";
|
|
5
|
+
import { Button as R } from "../ui/Button.js";
|
|
6
|
+
import { Icon as z } from "../ui/Icon.js";
|
|
7
|
+
import { useIsMobile as T } from "../../lib/hooks/useMediaQuery.js";
|
|
8
|
+
import { DataTableCards as k } from "./_DataTableCards.js";
|
|
9
|
+
const O = ({
|
|
10
|
+
height: f = "500px",
|
|
11
|
+
defaultColDef: p,
|
|
12
|
+
schema: m,
|
|
13
|
+
actions: n,
|
|
14
|
+
columnDefs: c,
|
|
15
|
+
emptyState: s,
|
|
16
|
+
rowData: i,
|
|
17
|
+
loading: o = !1,
|
|
18
|
+
mobileCards: h = !0,
|
|
19
|
+
...t
|
|
17
20
|
}) => {
|
|
18
|
-
const
|
|
21
|
+
const b = T(), v = d(() => ({
|
|
19
22
|
flex: 1,
|
|
20
23
|
minWidth: 120,
|
|
21
24
|
resizable: !0,
|
|
22
25
|
sortable: !0,
|
|
23
26
|
filter: !0,
|
|
24
27
|
menuTabs: ["filterMenuTab"],
|
|
25
|
-
...
|
|
26
|
-
}), [
|
|
27
|
-
if (
|
|
28
|
-
if (!
|
|
29
|
-
const
|
|
30
|
-
const
|
|
28
|
+
...p
|
|
29
|
+
}), [p]), g = d(() => {
|
|
30
|
+
if (c) return c;
|
|
31
|
+
if (!m) return [];
|
|
32
|
+
const r = m.map((e) => {
|
|
33
|
+
const a = e.type === "number" || e.type === "currency" || e.type === "percent" || e.type === "delta";
|
|
31
34
|
return {
|
|
32
35
|
field: e.key,
|
|
33
36
|
headerName: e.label,
|
|
34
37
|
hide: e.hide,
|
|
35
38
|
width: e.width,
|
|
36
|
-
cellClass:
|
|
37
|
-
headerClass:
|
|
38
|
-
cellRenderer: (u) =>
|
|
39
|
-
filter: e.type === "date" ? "agDateColumnFilter" :
|
|
39
|
+
cellClass: a ? "text-right tabular-nums" : void 0,
|
|
40
|
+
headerClass: a ? "ag-right-aligned-header" : void 0,
|
|
41
|
+
cellRenderer: (u) => x(u.value, e.type),
|
|
42
|
+
filter: e.type === "date" ? "agDateColumnFilter" : a ? "agNumberColumnFilter" : "agTextColumnFilter"
|
|
40
43
|
};
|
|
41
44
|
});
|
|
42
|
-
return
|
|
45
|
+
return n && n.length > 0 && r.push({
|
|
43
46
|
headerName: "",
|
|
44
47
|
field: "actions",
|
|
45
48
|
pinned: "right",
|
|
46
|
-
width: 80 +
|
|
49
|
+
width: 80 + n.length * 40,
|
|
47
50
|
sortable: !1,
|
|
48
51
|
filter: !1,
|
|
49
52
|
resizable: !1,
|
|
50
|
-
cellRenderer: (e) => /* @__PURE__ */
|
|
51
|
-
|
|
53
|
+
cellRenderer: (e) => /* @__PURE__ */ l("div", { className: "flex items-center justify-end gap-1 h-full", children: n.map((a) => /* @__PURE__ */ l(
|
|
54
|
+
R,
|
|
52
55
|
{
|
|
53
|
-
variant:
|
|
56
|
+
variant: a.variant || "ghost",
|
|
54
57
|
size: "icon",
|
|
55
58
|
className: "h-7 w-7",
|
|
56
|
-
title:
|
|
59
|
+
title: a.label,
|
|
57
60
|
onClick: (u) => {
|
|
58
|
-
u.stopPropagation(),
|
|
61
|
+
u.stopPropagation(), a.onClick(e.data);
|
|
59
62
|
},
|
|
60
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ l(z, { name: a.icon, className: "h-4 w-4" })
|
|
61
64
|
},
|
|
62
|
-
|
|
65
|
+
a.id
|
|
63
66
|
)) })
|
|
64
|
-
}),
|
|
65
|
-
}, [
|
|
67
|
+
}), r;
|
|
68
|
+
}, [m, c, n]), y = "ag-theme-quartz ag-theme-ramme", C = d(() => ({
|
|
66
69
|
overlayLoadingTemplate: '<span class="ag-overlay-loading-center">Loading data...</span>',
|
|
67
70
|
overlayNoRowsTemplate: '<span class="ag-overlay-no-rows-center">No data available</span>'
|
|
68
|
-
}), []);
|
|
69
|
-
return /* @__PURE__ */
|
|
70
|
-
|
|
71
|
+
}), []), N = (!i || i.length === 0) && !o;
|
|
72
|
+
return h && b ? /* @__PURE__ */ l("div", { className: "w-full", children: N && s ? /* @__PURE__ */ l("div", { className: "flex items-center justify-center py-fluid-lg", children: s }) : /* @__PURE__ */ l(
|
|
73
|
+
k,
|
|
71
74
|
{
|
|
72
|
-
rowData:
|
|
73
|
-
columnDefs:
|
|
74
|
-
|
|
75
|
+
rowData: i,
|
|
76
|
+
columnDefs: g,
|
|
77
|
+
loading: o,
|
|
78
|
+
pageSize: t.pagination === !1 ? !1 : t.paginationPageSize ?? 20,
|
|
79
|
+
onRowClick: t.onRowClicked ? (r) => t.onRowClicked({ data: r }) : void 0
|
|
80
|
+
}
|
|
81
|
+
) }) : /* @__PURE__ */ l("div", { className: `relative ${y}`, style: { height: f, width: "100%" }, children: (!i || i.length === 0) && s && !o ? /* @__PURE__ */ l("div", { className: "absolute inset-0 z-10 bg-background/50 flex items-center justify-center", children: s }) : /* @__PURE__ */ l(
|
|
82
|
+
w,
|
|
83
|
+
{
|
|
84
|
+
rowData: o ? [] : i,
|
|
85
|
+
columnDefs: g,
|
|
86
|
+
defaultColDef: v,
|
|
75
87
|
rowSelection: "multiple",
|
|
76
88
|
animateRows: !0,
|
|
77
89
|
pagination: !0,
|
|
78
90
|
paginationPageSize: 20,
|
|
79
91
|
enableCellTextSelection: !0,
|
|
80
92
|
suppressCellFocus: !0,
|
|
81
|
-
gridOptions:
|
|
82
|
-
onGridReady: (
|
|
93
|
+
gridOptions: C,
|
|
94
|
+
onGridReady: (r) => {
|
|
83
95
|
var e;
|
|
84
|
-
|
|
96
|
+
o && r.api.showLoadingOverlay(), (e = t.onGridReady) == null || e.call(t, r);
|
|
85
97
|
},
|
|
86
|
-
...
|
|
98
|
+
...t
|
|
87
99
|
}
|
|
88
100
|
) });
|
|
89
101
|
};
|
|
90
102
|
export {
|
|
91
|
-
|
|
103
|
+
O as DataTable
|
|
92
104
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ColDef } from 'ag-grid-community';
|
|
3
|
+
export interface DataTableCardsProps {
|
|
4
|
+
rowData: any[] | null | undefined;
|
|
5
|
+
columnDefs: ColDef[];
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
/** 0 or false disables card pagination; the grid's page size otherwise. */
|
|
8
|
+
pageSize?: number | false;
|
|
9
|
+
onRowClick?: (row: any) => void;
|
|
10
|
+
}
|
|
11
|
+
interface Slots {
|
|
12
|
+
heading: ColDef[];
|
|
13
|
+
body: ColDef[];
|
|
14
|
+
footer: ColDef[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Split the columns into the card's three zones.
|
|
18
|
+
*
|
|
19
|
+
* Exported for the test, which is the only way to assert the mapping without
|
|
20
|
+
* mounting AG Grid.
|
|
21
|
+
*/
|
|
22
|
+
export declare function splitColumns(columnDefs: ColDef[]): Slots;
|
|
23
|
+
/**
|
|
24
|
+
* Apply the grid's declared initial sort.
|
|
25
|
+
*
|
|
26
|
+
* Order is information here: the watchlist opens on risk ascending so the
|
|
27
|
+
* zombies lead, and a phone showing the same rows in insertion order would be
|
|
28
|
+
* a different screen, not a narrower one. `sortIndex` orders a multi-column
|
|
29
|
+
* sort; AG Grid treats a missing one as "after those that have it".
|
|
30
|
+
*/
|
|
31
|
+
export declare function applyDeclaredSort(rows: any[], columnDefs: ColDef[]): any[];
|
|
32
|
+
export declare const DataTableCards: React.FC<DataTableCardsProps>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { jsx as o, jsxs as g } from "react/jsx-runtime";
|
|
2
|
+
import f from "react";
|
|
3
|
+
import { Card as N, CardHeader as E, CardContent as F, CardFooter as I } from "../layout/Card.js";
|
|
4
|
+
import { Pagination as M } from "../navigation/Pagination.js";
|
|
5
|
+
import { Skeleton as x } from "../feedback/Skeleton.js";
|
|
6
|
+
function y(n, r) {
|
|
7
|
+
if (!(!n || !r))
|
|
8
|
+
return r.includes(".") ? r.split(".").reduce((t, e) => t == null ? t : t[e], n) : n[r];
|
|
9
|
+
}
|
|
10
|
+
function P(n) {
|
|
11
|
+
return (n.colId ?? n.field ?? "").toLowerCase() === "actions";
|
|
12
|
+
}
|
|
13
|
+
function j(n) {
|
|
14
|
+
const r = n.filter((e) => !e.hide), t = { heading: [], body: [], footer: [] };
|
|
15
|
+
for (const e of r)
|
|
16
|
+
e.pinned === "left" || e.pinned === !0 ? t.heading.push(e) : e.pinned === "right" || P(e) ? t.footer.push(e) : t.body.push(e);
|
|
17
|
+
return t.heading.length === 0 && t.body.length > 0 && t.heading.push(t.body.shift()), t;
|
|
18
|
+
}
|
|
19
|
+
function k(n, r) {
|
|
20
|
+
const t = r.filter((s) => s.sort === "asc" || s.sort === "desc").sort((s, l) => (s.sortIndex ?? Number.MAX_SAFE_INTEGER) - (l.sortIndex ?? Number.MAX_SAFE_INTEGER));
|
|
21
|
+
if (t.length === 0) return n;
|
|
22
|
+
const e = [...n];
|
|
23
|
+
return e.sort((s, l) => {
|
|
24
|
+
for (const d of t) {
|
|
25
|
+
const c = y(s, d.field), u = y(l, d.field);
|
|
26
|
+
let i;
|
|
27
|
+
if (typeof d.comparator == "function")
|
|
28
|
+
i = d.comparator(c, u, null, null, !1) ?? 0;
|
|
29
|
+
else if (c == null && u == null) i = 0;
|
|
30
|
+
else {
|
|
31
|
+
if (c == null) return 1;
|
|
32
|
+
if (u == null) return -1;
|
|
33
|
+
typeof c == "number" && typeof u == "number" ? i = c - u : i = String(c).localeCompare(String(u), void 0, { numeric: !0 });
|
|
34
|
+
}
|
|
35
|
+
if (i !== 0) return d.sort === "desc" ? -i : i;
|
|
36
|
+
}
|
|
37
|
+
return 0;
|
|
38
|
+
}), e;
|
|
39
|
+
}
|
|
40
|
+
function C(n, r) {
|
|
41
|
+
const t = y(r, n.field);
|
|
42
|
+
let e = null;
|
|
43
|
+
try {
|
|
44
|
+
e = n.valueFormatter ? n.valueFormatter({ value: t, data: r, colDef: n, node: null }) : null;
|
|
45
|
+
} catch {
|
|
46
|
+
e = null;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
value: t,
|
|
50
|
+
valueFormatted: e,
|
|
51
|
+
data: r,
|
|
52
|
+
colDef: n,
|
|
53
|
+
node: null
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function b(n, r) {
|
|
57
|
+
const t = C(n, r), e = t.valueFormatted ?? (t.value == null ? "—" : String(t.value)), s = n.cellRenderer;
|
|
58
|
+
if (typeof s == "function")
|
|
59
|
+
try {
|
|
60
|
+
const l = s(t);
|
|
61
|
+
if (l === null || typeof l == "string" || typeof l == "number" || f.isValidElement(l)) return l;
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
return e;
|
|
65
|
+
}
|
|
66
|
+
function _(n, r) {
|
|
67
|
+
const t = n.cellClass;
|
|
68
|
+
let e;
|
|
69
|
+
if (typeof t == "function")
|
|
70
|
+
try {
|
|
71
|
+
e = t(C(n, r));
|
|
72
|
+
} catch {
|
|
73
|
+
e = void 0;
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
e = t;
|
|
77
|
+
const s = (Array.isArray(e) ? e : e ? [e] : []).flatMap((d) => String(d).split(/\s+/)), l = /* @__PURE__ */ new Set(["text-right", "ag-right-aligned-cell"]);
|
|
78
|
+
return s.filter((d) => d && !l.has(d)).join(" ");
|
|
79
|
+
}
|
|
80
|
+
const R = ({ count: n }) => /* @__PURE__ */ o("div", { className: "flex flex-col gap-3", children: Array.from({ length: n }, (r, t) => /* @__PURE__ */ g(N, { className: "p-4", children: [
|
|
81
|
+
/* @__PURE__ */ o(x, { className: "h-4 w-24" }),
|
|
82
|
+
/* @__PURE__ */ o("div", { className: "mt-3 grid grid-cols-2 gap-2", children: Array.from({ length: 4 }, (e, s) => /* @__PURE__ */ o(x, { className: "h-3 w-full" }, s)) })
|
|
83
|
+
] }, t)) }), D = ({
|
|
84
|
+
rowData: n,
|
|
85
|
+
columnDefs: r,
|
|
86
|
+
loading: t = !1,
|
|
87
|
+
pageSize: e = !1,
|
|
88
|
+
onRowClick: s
|
|
89
|
+
}) => {
|
|
90
|
+
const [l, d] = f.useState(1), c = f.useMemo(() => j(r), [r]), u = f.useMemo(
|
|
91
|
+
() => k(n ?? [], r),
|
|
92
|
+
[n, r]
|
|
93
|
+
), i = typeof e == "number" && e > 0 ? e : 0, m = i ? Math.max(1, Math.ceil(u.length / i)) : 1;
|
|
94
|
+
f.useEffect(() => {
|
|
95
|
+
l > m && d(m);
|
|
96
|
+
}, [l, m]);
|
|
97
|
+
const A = i ? u.slice((l - 1) * i, l * i) : u;
|
|
98
|
+
return t ? /* @__PURE__ */ o(R, { count: Math.min(i || 3, 5) }) : /* @__PURE__ */ g("div", { className: "flex flex-col gap-3", children: [
|
|
99
|
+
A.map((p, S) => {
|
|
100
|
+
const v = !!s;
|
|
101
|
+
return /* @__PURE__ */ g(
|
|
102
|
+
N,
|
|
103
|
+
{
|
|
104
|
+
className: [
|
|
105
|
+
"overflow-hidden",
|
|
106
|
+
v ? "cursor-pointer active:bg-surface-muted" : ""
|
|
107
|
+
].filter(Boolean).join(" "),
|
|
108
|
+
onClick: v ? () => s(p) : void 0,
|
|
109
|
+
children: [
|
|
110
|
+
c.heading.length > 0 && /* @__PURE__ */ o(E, { className: "flex-row items-center gap-3 p-4 pb-0", children: c.heading.map((a, h) => /* @__PURE__ */ o("div", { className: "min-w-0 flex-1 truncate", children: b(a, p) }, a.colId ?? a.field ?? h)) }),
|
|
111
|
+
c.body.length > 0 && /* @__PURE__ */ o(F, { className: "p-4 pt-3", children: /* @__PURE__ */ o("dl", { className: "grid grid-cols-2 gap-x-4 gap-y-2", children: c.body.map((a, h) => /* @__PURE__ */ g(
|
|
112
|
+
"div",
|
|
113
|
+
{
|
|
114
|
+
className: "flex min-w-0 items-baseline justify-between gap-2",
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ o("dt", { className: "shrink-0 text-xs uppercase tracking-wider text-muted-foreground", children: a.headerName ?? a.field }),
|
|
117
|
+
/* @__PURE__ */ o(
|
|
118
|
+
"dd",
|
|
119
|
+
{
|
|
120
|
+
className: [
|
|
121
|
+
"min-w-0 truncate text-sm tabular-nums",
|
|
122
|
+
_(a, p)
|
|
123
|
+
].filter(Boolean).join(" "),
|
|
124
|
+
children: b(a, p)
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
a.colId ?? a.field ?? h
|
|
130
|
+
)) }) }),
|
|
131
|
+
c.footer.length > 0 && // min-h-11 is the 44px AAA tap target from AGENTS.md: the footer
|
|
132
|
+
// is where the controls live and a phone is what taps them.
|
|
133
|
+
/* @__PURE__ */ o(
|
|
134
|
+
I,
|
|
135
|
+
{
|
|
136
|
+
className: "flex-row items-center justify-end gap-1 border-t border-border p-2 min-h-11",
|
|
137
|
+
onClick: (a) => a.stopPropagation(),
|
|
138
|
+
children: c.footer.map((a, h) => /* @__PURE__ */ o(f.Fragment, { children: b(a, p) }, a.colId ?? a.field ?? h))
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
S
|
|
144
|
+
);
|
|
145
|
+
}),
|
|
146
|
+
m > 1 && /* @__PURE__ */ o(M, { currentPage: l, totalPages: m, onPageChange: d })
|
|
147
|
+
] });
|
|
148
|
+
};
|
|
149
|
+
export {
|
|
150
|
+
D as DataTableCards,
|
|
151
|
+
k as applyDeclaredSort,
|
|
152
|
+
j as splitColumns
|
|
153
|
+
};
|
|
@@ -50,7 +50,7 @@ const S = ({ status: a }) => {
|
|
|
50
50
|
className: l("w-full flex items-center gap-3 p-4 text-left focus:outline-none", !e.description && "cursor-default"),
|
|
51
51
|
children: [
|
|
52
52
|
/* @__PURE__ */ r("div", { className: "shrink-0 pt-0.5", children: /* @__PURE__ */ r(S, { status: e.status }) }),
|
|
53
|
-
/* @__PURE__ */ r("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ r("p", { className: l("font-medium
|
|
53
|
+
/* @__PURE__ */ r("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ r("p", { className: l("font-medium", s && "text-muted-foreground line-through"), children: e.label }) }),
|
|
54
54
|
e.description && /* @__PURE__ */ r(x, { className: l("w-4 h-4 text-muted-foreground transition-transform", m[e.id] && "rotate-180") })
|
|
55
55
|
]
|
|
56
56
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsxs as d, jsx as r } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import m from "react";
|
|
3
3
|
import b from "react-datepicker";
|
|
4
4
|
import { cn as e } from "../../utils/cn.js";
|
|
5
5
|
import { Icon as u } from "../ui/Icon.js";
|
|
6
6
|
import "react-datepicker/dist/react-datepicker.css";
|
|
7
|
-
const
|
|
7
|
+
const g = `
|
|
8
8
|
.react-datepicker {
|
|
9
9
|
font-family: inherit !important;
|
|
10
10
|
background-color: rgb(var(--app-card-bg-color)) !important;
|
|
@@ -38,9 +38,9 @@ const f = `
|
|
|
38
38
|
helperText: a,
|
|
39
39
|
...c
|
|
40
40
|
}) => {
|
|
41
|
-
const
|
|
41
|
+
const s = m.useId(), i = c.id || s;
|
|
42
42
|
return /* @__PURE__ */ d("div", { className: e("w-full flex flex-col", p), children: [
|
|
43
|
-
/* @__PURE__ */ r("style", { children:
|
|
43
|
+
/* @__PURE__ */ r("style", { children: g }),
|
|
44
44
|
o && /* @__PURE__ */ r("label", { htmlFor: i, className: "block text-sm font-medium text-foreground mb-1.5", children: o }),
|
|
45
45
|
/* @__PURE__ */ d("div", { className: "relative", children: [
|
|
46
46
|
/* @__PURE__ */ r(
|
|
@@ -50,7 +50,21 @@ const f = `
|
|
|
50
50
|
selected: l,
|
|
51
51
|
onChange: n,
|
|
52
52
|
className: e(
|
|
53
|
-
|
|
53
|
+
// No text size on the control. react-datepicker forwards this
|
|
54
|
+
// className straight to its own <input>, so a `text-sm` here sits
|
|
55
|
+
// on a real focus target and out-ranks the floor in index.css
|
|
56
|
+
// exactly as one written inline would — 14.5px, and iOS Safari
|
|
57
|
+
// zooms in on focus and never zooms back out.
|
|
58
|
+
//
|
|
59
|
+
// It was copied from Input.tsx before Input had its own `text-sm`
|
|
60
|
+
// removed, so that fix never reached here. The `file:` rules came
|
|
61
|
+
// along in the same copy and mean nothing on a date field; they are
|
|
62
|
+
// dropped so a future search for `file:text-sm` finds only the one
|
|
63
|
+
// place it is deliberate.
|
|
64
|
+
//
|
|
65
|
+
// A source scan cannot catch this one — there is no <input> tag to
|
|
66
|
+
// find — which is why formFieldFloor.test.tsx also renders the atoms.
|
|
67
|
+
"flex h-10 w-full rounded-md border bg-background px-3 py-2 ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
54
68
|
t ? "border-destructive" : "border-input"
|
|
55
69
|
),
|
|
56
70
|
wrapperClassName: "w-full",
|
|
@@ -77,7 +77,7 @@ const C = {
|
|
|
77
77
|
placeholder: "Search components...",
|
|
78
78
|
value: l,
|
|
79
79
|
onChange: (e) => u(e.target.value),
|
|
80
|
-
className: "w-full rounded-md bg-muted/50 border border-border pl-7 pr-3 py-1.5
|
|
80
|
+
className: "w-full rounded-md bg-muted/50 border border-border pl-7 pr-3 py-1.5 placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary/60 transition-shadow"
|
|
81
81
|
}
|
|
82
82
|
),
|
|
83
83
|
l && /* @__PURE__ */ o(
|
|
@@ -6,8 +6,8 @@ import { Button as v } from "../ui/Button.js";
|
|
|
6
6
|
import { Icon as l } from "../ui/Icon.js";
|
|
7
7
|
const S = ({
|
|
8
8
|
headingFont: i,
|
|
9
|
-
setHeadingFont:
|
|
10
|
-
bodyFont:
|
|
9
|
+
setHeadingFont: c,
|
|
10
|
+
bodyFont: t,
|
|
11
11
|
setBodyFont: s,
|
|
12
12
|
borderRadius: d,
|
|
13
13
|
setBorderRadius: u,
|
|
@@ -33,8 +33,8 @@ const S = ({
|
|
|
33
33
|
"select",
|
|
34
34
|
{
|
|
35
35
|
value: i,
|
|
36
|
-
onChange: (n) =>
|
|
37
|
-
className: "w-full border border-input bg-background rounded-md px-3 py-2
|
|
36
|
+
onChange: (n) => c(n.target.value),
|
|
37
|
+
className: "w-full border border-input bg-background rounded-md px-3 py-2 focus:ring-2 focus:ring-primary focus:outline-none",
|
|
38
38
|
children: [
|
|
39
39
|
/* @__PURE__ */ e("option", { value: "Inter", children: "Inter" }),
|
|
40
40
|
/* @__PURE__ */ e("option", { value: "Orbitron", children: "Orbitron" }),
|
|
@@ -53,9 +53,9 @@ const S = ({
|
|
|
53
53
|
/* @__PURE__ */ r(
|
|
54
54
|
"select",
|
|
55
55
|
{
|
|
56
|
-
value:
|
|
56
|
+
value: t,
|
|
57
57
|
onChange: (n) => s(n.target.value),
|
|
58
|
-
className: "w-full border border-input bg-background rounded-md px-3 py-2
|
|
58
|
+
className: "w-full border border-input bg-background rounded-md px-3 py-2 focus:ring-2 focus:ring-primary focus:outline-none",
|
|
59
59
|
children: [
|
|
60
60
|
/* @__PURE__ */ e("option", { value: "Inter", children: "Inter" }),
|
|
61
61
|
/* @__PURE__ */ e("option", { value: "Rajdhani", children: "Rajdhani" }),
|
|
@@ -73,7 +73,7 @@ const S = ({
|
|
|
73
73
|
{
|
|
74
74
|
value: d,
|
|
75
75
|
onChange: (n) => u(n.target.value),
|
|
76
|
-
className: "w-full border border-input bg-background rounded-md px-3 py-2
|
|
76
|
+
className: "w-full border border-input bg-background rounded-md px-3 py-2 focus:ring-2 focus:ring-primary focus:outline-none",
|
|
77
77
|
children: [
|
|
78
78
|
/* @__PURE__ */ e("option", { value: "0rem", children: "0rem (Sharp)" }),
|
|
79
79
|
/* @__PURE__ */ e("option", { value: "0.25rem", children: "0.25rem (Sm)" }),
|
|
@@ -92,7 +92,7 @@ const S = ({
|
|
|
92
92
|
{
|
|
93
93
|
value: m,
|
|
94
94
|
onChange: (n) => p(n.target.value),
|
|
95
|
-
className: "w-full border border-input bg-background rounded-md px-3 py-2
|
|
95
|
+
className: "w-full border border-input bg-background rounded-md px-3 py-2 focus:ring-2 focus:ring-primary focus:outline-none",
|
|
96
96
|
children: [
|
|
97
97
|
/* @__PURE__ */ e("option", { value: "0.875rem", children: "0.875rem (Small)" }),
|
|
98
98
|
/* @__PURE__ */ e("option", { value: "1rem", children: "1rem (Base)" }),
|