@photon-ai/pho-ui 4.11.0 → 4.13.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/dist/chunks/animated-height-zr7BmFY1.js +56 -0
- package/dist/chunks/animated-height-zr7BmFY1.js.map +1 -0
- package/dist/chunks/basic-page-6dDfY33L.js +2197 -0
- package/dist/chunks/basic-page-6dDfY33L.js.map +1 -0
- package/dist/chunks/box-search-C9EVZgcb.js +56 -0
- package/dist/chunks/box-search-C9EVZgcb.js.map +1 -0
- package/dist/chunks/{chat-B0WIgEyM.js → chat-Bu8UyIbT.js} +207 -205
- package/dist/chunks/chat-Bu8UyIbT.js.map +1 -0
- package/dist/chunks/{checkbox-CLPmblNA.js → checkbox-CwvoEJhd.js} +2 -2
- package/dist/chunks/{checkbox-CLPmblNA.js.map → checkbox-CwvoEJhd.js.map} +1 -1
- package/dist/chunks/choice-card-_Ocs0iUj.js +17 -0
- package/dist/chunks/choice-card-_Ocs0iUj.js.map +1 -0
- package/dist/chunks/chrome-Ds7WykBJ.js +14 -0
- package/dist/chunks/chrome-Ds7WykBJ.js.map +1 -0
- package/dist/chunks/{command-iYvU6Mhf.js → command-D5g49VqR.js} +3 -3
- package/dist/chunks/{command-iYvU6Mhf.js.map → command-D5g49VqR.js.map} +1 -1
- package/dist/chunks/{data-table-B1dmrN6r.js → data-table-hzZb7Otx.js} +58 -56
- package/dist/chunks/{data-table-B1dmrN6r.js.map → data-table-hzZb7Otx.js.map} +1 -1
- package/dist/chunks/{dialog-MPvem7yV.js → dialog-ChS0tdHa.js} +120 -116
- package/dist/chunks/dialog-ChS0tdHa.js.map +1 -0
- package/dist/chunks/{filter-bar-B-oYYBsU.js → filter-bar-C4sPEjw1.js} +63 -66
- package/dist/chunks/filter-bar-C4sPEjw1.js.map +1 -0
- package/dist/chunks/ghost-search-8PzP73zS.js +50 -0
- package/dist/chunks/ghost-search-8PzP73zS.js.map +1 -0
- package/dist/chunks/{input-DjvZoF8v.js → input-fFWvPJOf.js} +2 -1
- package/dist/chunks/{input-DjvZoF8v.js.map → input-fFWvPJOf.js.map} +1 -1
- package/dist/chunks/{trace-D1fOFzJt.js → trace-DyjsBY-S.js} +15 -13
- package/dist/chunks/{trace-D1fOFzJt.js.map → trace-DyjsBY-S.js.map} +1 -1
- package/dist/components/chat.js +1 -1
- package/dist/components/checkbox.js +1 -1
- package/dist/components/command.js +1 -1
- package/dist/components/data-table.js +4 -3
- package/dist/components/dialog.js +1 -1
- package/dist/components/field.js +34 -29
- package/dist/components/field.js.map +1 -1
- package/dist/components/filter-bar.js +1 -1
- package/dist/components/input.js +1 -1
- package/dist/components/radio-group.js +64 -59
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/scope.js +418 -0
- package/dist/components/scope.js.map +1 -0
- package/dist/components/trace.js +1 -1
- package/dist/index.js +176 -175
- package/dist/motion.js +61 -36
- package/dist/motion.js.map +1 -1
- package/dist/sections/basic-page.js +2 -2
- package/dist/src/components/chat/chat.d.ts +7 -4
- package/dist/src/components/dialog/dialog.d.ts +9 -1
- package/dist/src/components/field/field.d.ts +11 -1
- package/dist/src/components/input-group/box-search.d.ts +29 -0
- package/dist/src/components/radio-group/radio-card.d.ts +11 -4
- package/dist/src/components/scope/index.d.ts +1 -0
- package/dist/src/components/scope/scope.d.ts +98 -0
- package/dist/src/motion/index.d.ts +52 -0
- package/dist/src/sections/basic-page/basic-page.d.ts +145 -15
- package/dist/src/sections/basic-page/index.d.ts +1 -1
- package/dist/src/utils/animated-height.d.ts +16 -7
- package/dist/src/utils/choice-card.d.ts +8 -1
- package/dist/src/utils/ghost-search.d.ts +19 -3
- package/package.json +5 -1
- package/dist/chunks/animated-height-I44sUq0n.js +0 -48
- package/dist/chunks/animated-height-I44sUq0n.js.map +0 -1
- package/dist/chunks/basic-page-B5FsORRi.js +0 -1885
- package/dist/chunks/basic-page-B5FsORRi.js.map +0 -1
- package/dist/chunks/chat-B0WIgEyM.js.map +0 -1
- package/dist/chunks/choice-card-BVNP1NB6.js +0 -17
- package/dist/chunks/choice-card-BVNP1NB6.js.map +0 -1
- package/dist/chunks/dialog-MPvem7yV.js.map +0 -1
- package/dist/chunks/filter-bar-B-oYYBsU.js.map +0 -1
- package/dist/chunks/ghost-search-CNVs9k1o.js +0 -34
- package/dist/chunks/ghost-search-CNVs9k1o.js.map +0 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as y } from "./cn-ChIgwEl3.js";
|
|
3
|
-
import { a as
|
|
4
|
-
import { t as
|
|
3
|
+
import { a as T } from "./button-C9VqBBIr.js";
|
|
4
|
+
import { t as A } from "./createReactComponent-BqCmnqfX.js";
|
|
5
5
|
import { t as S } from "./IconCheck-D2WuculQ.js";
|
|
6
|
-
import { t as
|
|
6
|
+
import { t as P } from "./IconSearch-BKAHkLyX.js";
|
|
7
7
|
import { t as $ } from "./IconX-pZ9vrtSr.js";
|
|
8
8
|
import { t as g } from "./popover-BhBJO346.js";
|
|
9
|
-
import { t as
|
|
10
|
-
import { t as d } from "./command-
|
|
11
|
-
import { useRef as
|
|
9
|
+
import { t as D } from "./box-search-C9EVZgcb.js";
|
|
10
|
+
import { t as d } from "./command-D5g49VqR.js";
|
|
11
|
+
import { useRef as E, useState as I } from "react";
|
|
12
12
|
import { jsx as a, jsxs as p } from "react/jsx-runtime";
|
|
13
|
-
var
|
|
13
|
+
var R = [["path", {
|
|
14
14
|
d: "M12 5l0 14",
|
|
15
15
|
key: "svg-0"
|
|
16
16
|
}], ["path", {
|
|
17
17
|
d: "M5 12l14 0",
|
|
18
18
|
key: "svg-1"
|
|
19
|
-
}]], F =
|
|
19
|
+
}]], F = A("outline", "plus", "Plus", R), O = [
|
|
20
20
|
{
|
|
21
21
|
label: "Last hour",
|
|
22
22
|
hours: 1
|
|
@@ -33,41 +33,41 @@ var E = [["path", {
|
|
|
33
33
|
label: "Last 30 days",
|
|
34
34
|
hours: 720
|
|
35
35
|
}
|
|
36
|
-
],
|
|
37
|
-
function
|
|
36
|
+
], _ = 8;
|
|
37
|
+
function w(e) {
|
|
38
38
|
return e == null ? !1 : typeof e == "string" ? e !== "" : Array.isArray(e) ? e.length > 0 : e.from != null || e.to != null;
|
|
39
39
|
}
|
|
40
|
-
var
|
|
40
|
+
var L = /^\d{4}-\d{2}-\d{2}$/;
|
|
41
41
|
function x(e) {
|
|
42
|
-
const r =
|
|
42
|
+
const r = L.test(e), n = new Date(r ? `${e}T00:00:00Z` : e);
|
|
43
43
|
return Number.isNaN(n.getTime()) ? e : new Intl.DateTimeFormat("en-US", {
|
|
44
44
|
month: "short",
|
|
45
45
|
day: "numeric",
|
|
46
46
|
...r ? { timeZone: "UTC" } : {}
|
|
47
47
|
}).format(n);
|
|
48
48
|
}
|
|
49
|
-
function
|
|
50
|
-
if (!
|
|
49
|
+
function z(e, r) {
|
|
50
|
+
if (!w(r) || r == null) return "";
|
|
51
51
|
if (e.type === "date-range") {
|
|
52
52
|
const l = r;
|
|
53
53
|
return l.preset ? l.preset : l.from && l.to ? `${x(l.from)} to ${x(l.to)}` : l.from ? `From ${x(l.from)}` : l.to ? `Until ${x(l.to)}` : "";
|
|
54
54
|
}
|
|
55
|
-
const n = (l) => e.options.find((
|
|
55
|
+
const n = (l) => e.options.find((i) => i.value === l)?.label ?? l;
|
|
56
56
|
return Array.isArray(r) ? r.map(n).join(", ") : typeof r == "string" ? n(r) : "";
|
|
57
57
|
}
|
|
58
|
-
var
|
|
58
|
+
var k = "outline-pho-brand flex h-8 min-w-0 cursor-pointer items-center gap-1.5 rounded-full text-base transition-[color,background-color] duration-100 ease-linear focus-visible:outline-2 focus-visible:-outline-offset-2 [&>svg]:size-4 [&>svg]:shrink-0";
|
|
59
59
|
function B({ definition: e, value: r, onChange: n }) {
|
|
60
|
-
const [l,
|
|
60
|
+
const [l, i] = I(!1), u = E(null), c = w(r), t = z(e, r);
|
|
61
61
|
return /* @__PURE__ */ p(g.Root, {
|
|
62
62
|
open: l,
|
|
63
|
-
onOpenChange:
|
|
63
|
+
onOpenChange: i,
|
|
64
64
|
children: [/* @__PURE__ */ p("span", {
|
|
65
65
|
"data-filter-chip": e.key,
|
|
66
66
|
"data-set": c || void 0,
|
|
67
67
|
className: y("ring-pho-primary inline-flex max-w-full shrink-0 items-stretch rounded-full ring-1 ring-inset", c ? "bg-pho-secondary" : "bg-transparent"),
|
|
68
68
|
children: [/* @__PURE__ */ p(g.Trigger, {
|
|
69
69
|
"aria-label": c ? void 0 : `${e.label} filter`,
|
|
70
|
-
className: y(
|
|
70
|
+
className: y(k, "hover:bg-pho-ghost-hover", c ? "pr-1.5 pl-3" : "pr-3 pl-2.5", c ? "rounded-r-none" : ""),
|
|
71
71
|
children: [c ? null : /* @__PURE__ */ a(F, { "aria-hidden": !0 }), c ? /* @__PURE__ */ p("span", {
|
|
72
72
|
className: "flex min-w-0 items-baseline gap-1",
|
|
73
73
|
children: [/* @__PURE__ */ p("span", {
|
|
@@ -85,7 +85,7 @@ function B({ definition: e, value: r, onChange: n }) {
|
|
|
85
85
|
type: "button",
|
|
86
86
|
"aria-label": `Clear ${e.label.toLowerCase()} filter`,
|
|
87
87
|
onClick: () => n(void 0),
|
|
88
|
-
className: y(
|
|
88
|
+
className: y(k, "text-pho-secondary hover:bg-pho-ghost-hover hover:text-pho-secondary-hover rounded-l-none pr-2.5 pl-1 [&>svg]:size-3.5"),
|
|
89
89
|
children: /* @__PURE__ */ a($, { "aria-hidden": !0 })
|
|
90
90
|
}) : null]
|
|
91
91
|
}), /* @__PURE__ */ a(g.Portal, { children: /* @__PURE__ */ a(g.Positioner, {
|
|
@@ -93,29 +93,29 @@ function B({ definition: e, value: r, onChange: n }) {
|
|
|
93
93
|
sideOffset: 6,
|
|
94
94
|
children: /* @__PURE__ */ a(g.Popup, {
|
|
95
95
|
"aria-label": `${e.label} filter`,
|
|
96
|
-
initialFocus:
|
|
96
|
+
initialFocus: u,
|
|
97
97
|
className: y("w-64 p-0", e.type === "date-range" && "w-72"),
|
|
98
|
-
children: e.type === "date-range" ? /* @__PURE__ */ a(
|
|
98
|
+
children: e.type === "date-range" ? /* @__PURE__ */ a(j, {
|
|
99
99
|
definition: e,
|
|
100
100
|
value: r,
|
|
101
|
-
focusRef:
|
|
101
|
+
focusRef: u,
|
|
102
102
|
onChange: (m) => {
|
|
103
|
-
n(m), m?.preset &&
|
|
103
|
+
n(m), m?.preset && i(!1);
|
|
104
104
|
}
|
|
105
|
-
}) : /* @__PURE__ */ a(
|
|
105
|
+
}) : /* @__PURE__ */ a(U, {
|
|
106
106
|
definition: e,
|
|
107
107
|
value: r,
|
|
108
|
-
focusRef:
|
|
108
|
+
focusRef: u,
|
|
109
109
|
onChange: (m) => {
|
|
110
|
-
n(m), e.multiple ||
|
|
110
|
+
n(m), e.multiple || i(!1);
|
|
111
111
|
}
|
|
112
112
|
})
|
|
113
113
|
})
|
|
114
114
|
}) })]
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
|
-
function
|
|
118
|
-
const [
|
|
117
|
+
function U({ definition: e, value: r, focusRef: n, onChange: l }) {
|
|
118
|
+
const [i, u] = I(""), c = e.searchable ?? e.options.length > _, t = new Set(r == null ? [] : Array.isArray(r) ? r : [r]), m = i.trim().toLowerCase(), f = m ? e.options.filter((s) => s.label.toLowerCase().includes(m) || s.value.toLowerCase().includes(m)) : e.options, v = (s) => {
|
|
119
119
|
if (e.multiple) {
|
|
120
120
|
const b = new Set(t);
|
|
121
121
|
b.has(s.value) ? b.delete(s.value) : b.add(s.value);
|
|
@@ -131,15 +131,15 @@ function G({ definition: e, value: r, focusRef: n, onChange: l }) {
|
|
|
131
131
|
c || (n.current = s);
|
|
132
132
|
},
|
|
133
133
|
className: "rounded-base",
|
|
134
|
-
children: [c ? /* @__PURE__ */ p(d.InputGroup, { children: [/* @__PURE__ */ a(
|
|
134
|
+
children: [c ? /* @__PURE__ */ p(d.InputGroup, { children: [/* @__PURE__ */ a(P, {
|
|
135
135
|
"aria-hidden": !0,
|
|
136
136
|
className: "text-pho-description pointer-events-none absolute left-3 size-4"
|
|
137
137
|
}), /* @__PURE__ */ a(d.Input, {
|
|
138
138
|
ref: (s) => {
|
|
139
139
|
n.current = s;
|
|
140
140
|
},
|
|
141
|
-
value:
|
|
142
|
-
onValueChange:
|
|
141
|
+
value: i,
|
|
142
|
+
onValueChange: u,
|
|
143
143
|
placeholder: e.searchPlaceholder ?? "Search",
|
|
144
144
|
"aria-label": `Search ${e.label.toLowerCase()} options`,
|
|
145
145
|
className: "py-2 pr-3 pl-9 text-base"
|
|
@@ -153,12 +153,12 @@ function G({ definition: e, value: r, focusRef: n, onChange: l }) {
|
|
|
153
153
|
}, s.value))] })]
|
|
154
154
|
});
|
|
155
155
|
}
|
|
156
|
-
var
|
|
157
|
-
function
|
|
158
|
-
const
|
|
156
|
+
var C = "bg-pho-primary ring-pho-primary text-pho-primary focus-visible:ring-pho-brand w-full min-w-0 rounded-sm px-2 py-1 text-base ring-1 transition-shadow duration-100 ease-linear outline-none ring-inset focus-visible:ring-2";
|
|
157
|
+
function j({ definition: e, value: r, focusRef: n, onChange: l }) {
|
|
158
|
+
const i = e.presets ?? O, u = (t) => t == null ? "" : L.test(t) ? t : t.slice(0, 10), c = (t, m) => {
|
|
159
159
|
const f = {
|
|
160
|
-
from:
|
|
161
|
-
to:
|
|
160
|
+
from: u(r?.from) || null,
|
|
161
|
+
to: u(r?.to) || null,
|
|
162
162
|
[t]: m || null
|
|
163
163
|
};
|
|
164
164
|
l(f.from == null && f.to == null ? void 0 : f);
|
|
@@ -171,7 +171,7 @@ function U({ definition: e, value: r, focusRef: n, onChange: l }) {
|
|
|
171
171
|
n.current = t;
|
|
172
172
|
},
|
|
173
173
|
className: "rounded-t-[inherit]",
|
|
174
|
-
children: /* @__PURE__ */ a(d.List, { children:
|
|
174
|
+
children: /* @__PURE__ */ a(d.List, { children: i.map((t) => /* @__PURE__ */ a(d.Item, {
|
|
175
175
|
value: t.label,
|
|
176
176
|
size: "sm",
|
|
177
177
|
title: t.label,
|
|
@@ -189,26 +189,26 @@ function U({ definition: e, value: r, focusRef: n, onChange: l }) {
|
|
|
189
189
|
className: "text-pho-description flex min-w-0 flex-col gap-1 text-xs",
|
|
190
190
|
children: ["From", /* @__PURE__ */ a("input", {
|
|
191
191
|
type: "date",
|
|
192
|
-
value:
|
|
193
|
-
max:
|
|
192
|
+
value: u(r?.from),
|
|
193
|
+
max: u(r?.to) || void 0,
|
|
194
194
|
onChange: (t) => c("from", t.target.value),
|
|
195
|
-
className:
|
|
195
|
+
className: C
|
|
196
196
|
})]
|
|
197
197
|
}), /* @__PURE__ */ p("label", {
|
|
198
198
|
className: "text-pho-description flex min-w-0 flex-col gap-1 text-xs",
|
|
199
199
|
children: ["To", /* @__PURE__ */ a("input", {
|
|
200
200
|
type: "date",
|
|
201
|
-
value:
|
|
202
|
-
min:
|
|
201
|
+
value: u(r?.to),
|
|
202
|
+
min: u(r?.from) || void 0,
|
|
203
203
|
onChange: (t) => c("to", t.target.value),
|
|
204
|
-
className:
|
|
204
|
+
className: C
|
|
205
205
|
})]
|
|
206
206
|
})]
|
|
207
207
|
})]
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
|
-
function
|
|
211
|
-
const s = e.filter((o) =>
|
|
210
|
+
function G({ definitions: e, filters: r, onFiltersChange: n, search: l, onSearchChange: i, searchPlaceholder: u = "Search", searchLabel: c, sticky: t, className: m, children: f, ...v }) {
|
|
211
|
+
const s = e.filter((o) => w(r[o.key])).length, b = (o, h) => {
|
|
212
212
|
const N = { ...r };
|
|
213
213
|
h === void 0 ? delete N[o] : N[o] = h, n(N);
|
|
214
214
|
};
|
|
@@ -217,26 +217,23 @@ function j({ definitions: e, filters: r, onFiltersChange: n, search: l, onSearch
|
|
|
217
217
|
className: y("flex min-w-0 flex-wrap items-center gap-2", t && "sticky top-0 z-10 bg-[var(--pho-surface,var(--background-color-pho-page))] py-3", m),
|
|
218
218
|
...v,
|
|
219
219
|
children: [
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
placeholder: i,
|
|
231
|
-
"aria-label": c ?? i
|
|
232
|
-
})]
|
|
220
|
+
i != null ? /* @__PURE__ */ a(D, {
|
|
221
|
+
value: l ?? "",
|
|
222
|
+
onChange: (o) => i(o.target.value),
|
|
223
|
+
onClear: () => i(""),
|
|
224
|
+
onKeyDown: (o) => {
|
|
225
|
+
o.key === "Escape" && (o.preventDefault(), i(""));
|
|
226
|
+
},
|
|
227
|
+
placeholder: u,
|
|
228
|
+
"aria-label": c ?? u,
|
|
229
|
+
className: "w-64 max-w-full"
|
|
233
230
|
}) : null,
|
|
234
231
|
e.map((o) => /* @__PURE__ */ a(B, {
|
|
235
232
|
definition: o,
|
|
236
233
|
value: r[o.key],
|
|
237
234
|
onChange: (h) => b(o.key, h)
|
|
238
235
|
}, o.key)),
|
|
239
|
-
s > 1 ? /* @__PURE__ */ a(
|
|
236
|
+
s > 1 ? /* @__PURE__ */ a(T, {
|
|
240
237
|
variant: "ghost",
|
|
241
238
|
size: "sm",
|
|
242
239
|
onClick: () => {
|
|
@@ -250,12 +247,12 @@ function j({ definitions: e, filters: r, onFiltersChange: n, search: l, onSearch
|
|
|
250
247
|
]
|
|
251
248
|
});
|
|
252
249
|
}
|
|
253
|
-
|
|
250
|
+
G.displayName = "FilterBar";
|
|
254
251
|
export {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
252
|
+
w as i,
|
|
253
|
+
G as n,
|
|
254
|
+
z as r,
|
|
255
|
+
O as t
|
|
259
256
|
};
|
|
260
257
|
|
|
261
|
-
//# sourceMappingURL=filter-bar-
|
|
258
|
+
//# sourceMappingURL=filter-bar-C4sPEjw1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-bar-C4sPEjw1.js","names":[],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.mjs","../../src/components/filter-bar/filter-bar.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 5l0 14\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M5 12l14 0\", \"key\": \"svg-1\" }]];\nconst IconPlus = createReactComponent(\"outline\", \"plus\", \"Plus\", __iconNode);\n\nexport { __iconNode, IconPlus as default };\n//# sourceMappingURL=IconPlus.mjs.map\n","import {\n useRef,\n useState,\n type ComponentProps,\n type ReactNode,\n type Ref,\n type RefObject,\n} from \"react\";\nimport { IconCheck, IconPlus, IconSearch, IconX } from \"@tabler/icons-react\";\nimport { Button } from \"../button\";\nimport { Command } from \"../command\";\nimport { BoxSearch } from \"../input-group/box-search\";\nimport { Popover } from \"../popover\";\nimport { cn } from \"../../utils/cn\";\n\n/**\n * Filter Bar — the row that pins above a log list: a search field for an\n * id, then one chip per filter. A chip with nothing chosen reads\n * `+ Status`; with a value it reads `Status: Failed` and carries its own\n * clear. Each chip opens a small popover: a keyboard-first list of\n * options (with a search field past eight of them), or presets and a\n * from / to pair for a date range.\n *\n * Design notes:\n * - Fully controlled. The page owns `filters` and `search` and hands\n * them back changed; the bar keeps no state but which popover is open.\n * That keeps the query in one place (the URL, a store) and lets the\n * list refetch from it.\n * - Chips are real buttons (the trigger, and the clear beside it), so\n * the bar is one tab stop per control and Escape closes a popover\n * back onto its chip.\n * - No scroll container of its own: chips wrap. `sticky` pins it to the\n * top of the nearest scroll pane on the surface it sits on.\n */\n\nexport interface FilterOption {\n value: string;\n label: string;\n /**\n * Rich option row (a badge, mono path). Search and the set chip still\n * use `label` and `value` strings.\n */\n title?: ReactNode;\n}\n\ninterface FilterDefinitionBase {\n /** The key in `filters` this chip reads and writes. */\n key: string;\n /** The chip's word — \"Status\", \"Event type\". Sentence case. */\n label: string;\n}\n\nexport interface SelectFilterDefinition extends FilterDefinitionBase {\n type?: \"select\";\n options: readonly FilterOption[];\n /** Several values at once (`string[]`); one at a time by default. */\n multiple?: boolean;\n /**\n * A search field above the options. On by default past eight options,\n * off below; say so to override.\n */\n searchable?: boolean;\n /** The search field's placeholder. @default \"Search\" */\n searchPlaceholder?: string;\n}\n\n/** A relative preset for a date-range filter — \"Last 7 days\" is 168 hours. */\nexport interface DateRangePreset {\n label: string;\n hours: number;\n}\n\nexport interface DateRangeFilterDefinition extends FilterDefinitionBase {\n type: \"date-range\";\n /** The relative presets listed above the from / to pair. */\n presets?: readonly DateRangePreset[];\n}\n\nexport type FilterDefinition =\n SelectFilterDefinition | DateRangeFilterDefinition;\n\n/**\n * A date-range value. A preset stores an absolute ISO timestamp in `from`\n * (computed when chosen) and its label in `preset`; the from / to pair\n * stores plain `YYYY-MM-DD` dates. Either side may be open (`null`).\n */\nexport interface DateRangeValue {\n from: string | null;\n to: string | null;\n preset?: string;\n}\n\nexport type FilterValue = string | string[] | DateRangeValue;\n\n/** The page's filter state — one entry per definition key that is set. */\nexport type FilterValues = Record<string, FilterValue | undefined>;\n\n/** The relative presets a date-range chip lists when given none. */\nexport const FILTER_DATE_PRESETS: readonly DateRangePreset[] = [\n { label: \"Last hour\", hours: 1 },\n { label: \"Last 24 hours\", hours: 24 },\n { label: \"Last 7 days\", hours: 24 * 7 },\n { label: \"Last 30 days\", hours: 24 * 30 },\n];\n\n/** Past this many options a select chip shows a search field. */\nconst SEARCHABLE_PAST = 8;\n\n/** Whether a filter value counts as set — an empty string or list does not. */\nexport function isFilterSet(value: FilterValue | undefined): boolean {\n if (value == null) return false;\n if (typeof value === \"string\") return value !== \"\";\n if (Array.isArray(value)) return value.length > 0;\n return value.from != null || value.to != null;\n}\n\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nfunction formatDay(value: string): string {\n // A plain date is a calendar day: format it in UTC so the day survives\n // every viewer timezone. A timestamp is a moment: format it locally.\n const dateOnly = DATE_ONLY.test(value);\n const date = new Date(dateOnly ? `${value}T00:00:00Z` : value);\n if (Number.isNaN(date.getTime())) return value;\n return new Intl.DateTimeFormat(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n ...(dateOnly ? { timeZone: \"UTC\" } : {}),\n }).format(date);\n}\n\n/** The words a set chip shows after its label. */\nexport function formatFilterValue(\n definition: FilterDefinition,\n value: FilterValue | undefined,\n): string {\n if (!isFilterSet(value) || value == null) return \"\";\n if (definition.type === \"date-range\") {\n const range = value as DateRangeValue;\n if (range.preset) return range.preset;\n if (range.from && range.to) {\n return `${formatDay(range.from)} to ${formatDay(range.to)}`;\n }\n if (range.from) return `From ${formatDay(range.from)}`;\n if (range.to) return `Until ${formatDay(range.to)}`;\n return \"\";\n }\n const labelOf = (item: string) =>\n definition.options.find((option) => option.value === item)?.label ?? item;\n if (Array.isArray(value)) return value.map(labelOf).join(\", \");\n return typeof value === \"string\" ? labelOf(value) : \"\";\n}\n\n/* --------------------------------- chips -------------------------------- */\n\nconst CHIP_TRIGGER =\n \"outline-pho-brand flex h-8 min-w-0 cursor-pointer items-center gap-1.5 rounded-full text-base transition-[color,background-color] duration-100 ease-linear focus-visible:outline-2 focus-visible:-outline-offset-2 [&>svg]:size-4 [&>svg]:shrink-0\";\n\nfunction FilterChip({\n definition,\n value,\n onChange,\n}: {\n definition: FilterDefinition;\n value: FilterValue | undefined;\n onChange: (next: FilterValue | undefined) => void;\n}) {\n const [open, setOpen] = useState(false);\n const focusRef = useRef<HTMLElement | null>(null);\n const set = isFilterSet(value);\n const display = formatFilterValue(definition, value);\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <span\n data-filter-chip={definition.key}\n data-set={set || undefined}\n className={cn(\n \"ring-pho-primary inline-flex max-w-full shrink-0 items-stretch rounded-full ring-1 ring-inset\",\n set ? \"bg-pho-secondary\" : \"bg-transparent\",\n )}\n >\n <Popover.Trigger\n aria-label={set ? undefined : `${definition.label} filter`}\n className={cn(\n CHIP_TRIGGER,\n \"hover:bg-pho-ghost-hover\",\n set ? \"pr-1.5 pl-3\" : \"pr-3 pl-2.5\",\n set ? \"rounded-r-none\" : \"\",\n )}\n >\n {set ? null : <IconPlus aria-hidden />}\n {set ? (\n <span className=\"flex min-w-0 items-baseline gap-1\">\n <span className=\"text-pho-description shrink-0\">\n {definition.label}:\n </span>\n <span className=\"text-pho-primary max-w-56 truncate font-medium\">\n {display}\n </span>\n </span>\n ) : (\n <span className=\"text-pho-secondary\">{definition.label}</span>\n )}\n </Popover.Trigger>\n {set ? (\n <button\n type=\"button\"\n aria-label={`Clear ${definition.label.toLowerCase()} filter`}\n onClick={() => onChange(undefined)}\n className={cn(\n CHIP_TRIGGER,\n \"text-pho-secondary hover:bg-pho-ghost-hover hover:text-pho-secondary-hover rounded-l-none pr-2.5 pl-1 [&>svg]:size-3.5\",\n )}\n >\n <IconX aria-hidden />\n </button>\n ) : null}\n </span>\n <Popover.Portal>\n <Popover.Positioner align=\"start\" sideOffset={6}>\n <Popover.Popup\n aria-label={`${definition.label} filter`}\n initialFocus={focusRef}\n className={cn(\n \"w-64 p-0\",\n definition.type === \"date-range\" && \"w-72\",\n )}\n >\n {definition.type === \"date-range\" ? (\n <DateRangePanel\n definition={definition}\n value={value as DateRangeValue | undefined}\n focusRef={focusRef}\n onChange={(next) => {\n onChange(next);\n if (next?.preset) setOpen(false);\n }}\n />\n ) : (\n <OptionsPanel\n definition={definition}\n value={value as string | string[] | undefined}\n focusRef={focusRef}\n onChange={(next) => {\n onChange(next);\n if (!definition.multiple) setOpen(false);\n }}\n />\n )}\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n\nfunction OptionsPanel({\n definition,\n value,\n focusRef,\n onChange,\n}: {\n definition: SelectFilterDefinition;\n value: string | string[] | undefined;\n focusRef: RefObject<HTMLElement | null>;\n onChange: (next: string | string[] | undefined) => void;\n}) {\n const [query, setQuery] = useState(\"\");\n const searchable =\n definition.searchable ?? definition.options.length > SEARCHABLE_PAST;\n const chosen = new Set(\n value == null ? [] : Array.isArray(value) ? value : [value],\n );\n const needle = query.trim().toLowerCase();\n const options = needle\n ? definition.options.filter(\n (option) =>\n option.label.toLowerCase().includes(needle) ||\n option.value.toLowerCase().includes(needle),\n )\n : definition.options;\n const pick = (option: FilterOption) => {\n if (definition.multiple) {\n const next = new Set(chosen);\n if (next.has(option.value)) next.delete(option.value);\n else next.add(option.value);\n // Keep the definition's order, so the chip reads the same way\n // whatever order the values were chosen in.\n const ordered = definition.options\n .map((item) => item.value)\n .filter((item) => next.has(item));\n onChange(ordered.length > 0 ? ordered : undefined);\n return;\n }\n onChange(chosen.has(option.value) ? undefined : option.value);\n };\n return (\n <Command.Root\n label={`${definition.label} options`}\n // Without a search field the list itself takes focus, so the arrow\n // keys work from the first frame.\n ref={(node: HTMLDivElement | null) => {\n if (!searchable) focusRef.current = node;\n }}\n className=\"rounded-base\"\n >\n {searchable ? (\n <Command.InputGroup>\n <IconSearch\n aria-hidden\n className=\"text-pho-description pointer-events-none absolute left-3 size-4\"\n />\n <Command.Input\n ref={(node: HTMLInputElement | null) => {\n focusRef.current = node;\n }}\n value={query}\n onValueChange={setQuery}\n placeholder={definition.searchPlaceholder ?? \"Search\"}\n aria-label={`Search ${definition.label.toLowerCase()} options`}\n className=\"py-2 pr-3 pl-9 text-base\"\n />\n </Command.InputGroup>\n ) : null}\n <Command.List>\n <Command.Empty>Nothing matches.</Command.Empty>\n {options.map((option) => (\n <Command.Item\n key={option.value}\n value={option.value}\n size=\"sm\"\n title={option.title ?? option.label}\n aria-checked={chosen.has(option.value)}\n icon={chosen.has(option.value) ? <IconCheck aria-hidden /> : null}\n onSelect={() => pick(option)}\n />\n ))}\n </Command.List>\n </Command.Root>\n );\n}\n\nconst DATE_INPUT =\n \"bg-pho-primary ring-pho-primary text-pho-primary focus-visible:ring-pho-brand w-full min-w-0 rounded-sm px-2 py-1 text-base ring-1 transition-shadow duration-100 ease-linear outline-none ring-inset focus-visible:ring-2\";\n\nfunction DateRangePanel({\n definition,\n value,\n focusRef,\n onChange,\n}: {\n definition: DateRangeFilterDefinition;\n value: DateRangeValue | undefined;\n focusRef: RefObject<HTMLElement | null>;\n onChange: (next: DateRangeValue | undefined) => void;\n}) {\n const presets = definition.presets ?? FILTER_DATE_PRESETS;\n // A preset's `from` is a timestamp; the day field shows its date.\n const day = (side: string | null | undefined) =>\n side == null ? \"\" : DATE_ONLY.test(side) ? side : side.slice(0, 10);\n const setSide = (side: \"from\" | \"to\", next: string) => {\n // Editing either day leaves a preset behind: the pair is the value now,\n // and a preset's timestamp becomes the day it fell on.\n const range: DateRangeValue = {\n from: day(value?.from) || null,\n to: day(value?.to) || null,\n [side]: next || null,\n };\n onChange(range.from == null && range.to == null ? undefined : range);\n };\n return (\n <div className=\"flex flex-col\">\n <Command.Root\n label={`${definition.label} presets`}\n ref={(node: HTMLDivElement | null) => {\n focusRef.current = node;\n }}\n className=\"rounded-t-[inherit]\"\n >\n <Command.List>\n {presets.map((preset) => (\n <Command.Item\n key={preset.label}\n value={preset.label}\n size=\"sm\"\n title={preset.label}\n aria-checked={value?.preset === preset.label}\n icon={\n value?.preset === preset.label ? (\n <IconCheck aria-hidden />\n ) : null\n }\n onSelect={() =>\n onChange({\n from: new Date(\n Date.now() - preset.hours * 60 * 60 * 1000,\n ).toISOString(),\n to: null,\n preset: preset.label,\n })\n }\n />\n ))}\n </Command.List>\n </Command.Root>\n {/* The day fields stand outside the command list: its arrow-key\n handling would otherwise swallow the native date stepping. */}\n <div className=\"border-pho-secondary grid grid-cols-2 gap-2 border-t p-2\">\n <label className=\"text-pho-description flex min-w-0 flex-col gap-1 text-xs\">\n From\n <input\n type=\"date\"\n value={day(value?.from)}\n max={day(value?.to) || undefined}\n onChange={(event) => setSide(\"from\", event.target.value)}\n className={DATE_INPUT}\n />\n </label>\n <label className=\"text-pho-description flex min-w-0 flex-col gap-1 text-xs\">\n To\n <input\n type=\"date\"\n value={day(value?.to)}\n min={day(value?.from) || undefined}\n onChange={(event) => setSide(\"to\", event.target.value)}\n className={DATE_INPUT}\n />\n </label>\n </div>\n </div>\n );\n}\n\n/* ---------------------------------- bar --------------------------------- */\n\nexport interface FilterBarProps extends Omit<\n ComponentProps<\"div\">,\n \"children\"\n> {\n /** One chip per definition, in this order. */\n definitions: readonly FilterDefinition[];\n /** The values, keyed by definition key. Absent or empty means unset. */\n filters: FilterValues;\n /** The whole map, changed — set, cleared, or cleared all. */\n onFiltersChange: (next: FilterValues) => void;\n /** The search field's text. The field renders only with `onSearchChange`. */\n search?: string;\n onSearchChange?: (value: string) => void;\n /** A teaching phrase — \"Find an event by id\". @default \"Search\" */\n searchPlaceholder?: string;\n /** The field's accessible name when the placeholder is too short to be one. */\n searchLabel?: string;\n /**\n * Pin the bar to the top of the nearest scroll pane. It paints the\n * surface it sits on (`--pho-surface`) so rows scroll under it.\n */\n sticky?: boolean;\n /** Controls after the chips — a range picker, an export button. */\n children?: ReactNode;\n ref?: Ref<HTMLDivElement>;\n}\n\nexport function FilterBar({\n definitions,\n filters,\n onFiltersChange,\n search,\n onSearchChange,\n searchPlaceholder = \"Search\",\n searchLabel,\n sticky,\n className,\n children,\n ...props\n}: FilterBarProps) {\n const setCount = definitions.filter((definition) =>\n isFilterSet(filters[definition.key]),\n ).length;\n const change = (key: string, next: FilterValue | undefined) => {\n const rest = { ...filters };\n if (next === undefined) delete rest[key];\n else rest[key] = next;\n onFiltersChange(rest);\n };\n return (\n <div\n data-filter-bar=\"\"\n className={cn(\n \"flex min-w-0 flex-wrap items-center gap-2\",\n sticky &&\n \"sticky top-0 z-10 bg-[var(--pho-surface,var(--background-color-pho-page))] py-3\",\n className,\n )}\n {...props}\n >\n {onSearchChange != null ? (\n <BoxSearch\n value={search ?? \"\"}\n onChange={(event) => onSearchChange(event.target.value)}\n onClear={() => onSearchChange(\"\")}\n onKeyDown={(event) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n onSearchChange(\"\");\n }}\n placeholder={searchPlaceholder}\n aria-label={searchLabel ?? searchPlaceholder}\n className=\"w-64 max-w-full\"\n />\n ) : null}\n {definitions.map((definition) => (\n <FilterChip\n key={definition.key}\n definition={definition}\n value={filters[definition.key]}\n onChange={(next) => change(definition.key, next)}\n />\n ))}\n {setCount > 1 ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n const rest = { ...filters };\n for (const definition of definitions) delete rest[definition.key];\n onFiltersChange(rest);\n }}\n >\n Clear filters\n </Button>\n ) : null}\n {children}\n </div>\n );\n}\n\nFilterBar.displayName = \"FilterBar\";\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as l } from "./cn-ChIgwEl3.js";
|
|
3
|
+
import { t as p } from "./IconSearch-BKAHkLyX.js";
|
|
4
|
+
import { t as h } from "./IconX-pZ9vrtSr.js";
|
|
5
|
+
import { useRef as m } from "react";
|
|
6
|
+
import { jsx as t, jsxs as d } from "react/jsx-runtime";
|
|
7
|
+
function k({ value: i, onChange: c, onClear: n, trailing: o, className: u, ref: a, ...r }) {
|
|
8
|
+
const s = m(null);
|
|
9
|
+
return /* @__PURE__ */ d("label", {
|
|
10
|
+
className: l("group flex min-w-40 flex-1 items-center gap-2", u),
|
|
11
|
+
children: [
|
|
12
|
+
/* @__PURE__ */ t(p, {
|
|
13
|
+
"aria-hidden": !0,
|
|
14
|
+
className: "text-pho-description group-focus-within:text-pho-primary size-4 shrink-0 transition-colors duration-100 ease-linear"
|
|
15
|
+
}),
|
|
16
|
+
/* @__PURE__ */ t("input", {
|
|
17
|
+
ref: (e) => {
|
|
18
|
+
s.current = e, typeof a == "function" ? a(e) : a != null && (a.current = e);
|
|
19
|
+
},
|
|
20
|
+
type: "search",
|
|
21
|
+
value: i,
|
|
22
|
+
onChange: (e) => {
|
|
23
|
+
e.stopPropagation(), c(e.target.value);
|
|
24
|
+
},
|
|
25
|
+
className: l("text-pho-primary placeholder:text-pho-description text-md w-full min-w-0 bg-transparent outline-none md:text-base", n != null && "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none"),
|
|
26
|
+
...r,
|
|
27
|
+
"aria-label": r["aria-label"] ?? (r["aria-labelledby"] ? void 0 : "Search")
|
|
28
|
+
}),
|
|
29
|
+
o != null ? /* @__PURE__ */ t("span", {
|
|
30
|
+
className: "text-pho-description shrink-0 text-xs tabular-nums",
|
|
31
|
+
children: o
|
|
32
|
+
}) : null,
|
|
33
|
+
n != null && i !== "" && !r.disabled ? /* @__PURE__ */ t("button", {
|
|
34
|
+
type: "button",
|
|
35
|
+
"aria-label": "Clear search",
|
|
36
|
+
tabIndex: -1,
|
|
37
|
+
onClick: () => {
|
|
38
|
+
n(), s.current?.focus();
|
|
39
|
+
},
|
|
40
|
+
className: "text-pho-secondary hover:text-pho-secondary-hover flex shrink-0 cursor-pointer items-center transition-colors duration-100 ease-linear [&>svg]:size-4",
|
|
41
|
+
children: /* @__PURE__ */ t(h, { "aria-hidden": !0 })
|
|
42
|
+
}) : null
|
|
43
|
+
]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
k as t
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=ghost-search-8PzP73zS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ghost-search-8PzP73zS.js","names":[],"sources":["../../src/utils/ghost-search.tsx"],"sourcesContent":["import { useRef, type ComponentProps, type ReactNode } from \"react\";\nimport { IconSearch, IconX } from \"@tabler/icons-react\";\nimport { cn } from \"./cn\";\n\nexport interface GhostSearchProps extends Omit<\n ComponentProps<\"input\">,\n \"value\" | \"onChange\" | \"type\" | \"children\"\n> {\n value: string;\n onChange: (value: string) => void;\n /**\n * Empties the query from the field's own clear button, shown while it\n * holds text; focus stays in the field. Without it, the browser's own\n * clear glyph stays.\n */\n onClear?: () => void;\n /** Quiet words at the field's end, before the clear button — a count. */\n trailing?: ReactNode;\n}\n\n/**\n * A search box with no box: the glyph and the text on the surface's own\n * line, the way a toolbar band inside a card carries it (a `DataTable`'s\n * search, a `Trace.Waterfall`'s, a `Scope`'s first row). Quiet ink, and no\n * ring on focus either: a ring would draw the box the face exists not to\n * have. Focus shows in the caret and in the magnifier, which takes the\n * primary ink while the field holds focus.\n *\n * The query is the list's, not a form's: its change stops at the field, so\n * an enclosing form that saves on change (BasicPage `Form autoSave`) or\n * shows a save row once dirty never hears it. The type is an `sm` field's:\n * 16px on small viewports, where iOS zooms into anything smaller.\n */\nexport function GhostSearch({\n value,\n onChange,\n onClear,\n trailing,\n className,\n ref,\n ...props\n}: GhostSearchProps) {\n const inputRef = useRef<HTMLInputElement | null>(null);\n return (\n <label\n className={cn(\"group flex min-w-40 flex-1 items-center gap-2\", className)}\n >\n <IconSearch\n aria-hidden\n className=\"text-pho-description group-focus-within:text-pho-primary size-4 shrink-0 transition-colors duration-100 ease-linear\"\n />\n <input\n ref={(node) => {\n inputRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref != null) ref.current = node;\n }}\n type=\"search\"\n value={value}\n onChange={(event) => {\n event.stopPropagation();\n onChange(event.target.value);\n }}\n className={cn(\n \"text-pho-primary placeholder:text-pho-description text-md w-full min-w-0 bg-transparent outline-none md:text-base\",\n // The field's own clear takes over from the browser's.\n onClear != null &&\n \"[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none\",\n )}\n {...props}\n aria-label={\n props[\"aria-label\"] ??\n (props[\"aria-labelledby\"] ? undefined : \"Search\")\n }\n />\n {trailing != null ? (\n <span className=\"text-pho-description shrink-0 text-xs tabular-nums\">\n {trailing}\n </span>\n ) : null}\n {onClear != null && value !== \"\" && !props.disabled ? (\n <button\n type=\"button\"\n aria-label=\"Clear search\"\n // Reachable by click, skipped by Tab: `Escape` clears from the\n // keyboard, and Tab moves on to the list.\n tabIndex={-1}\n onClick={() => {\n onClear();\n inputRef.current?.focus();\n }}\n className=\"text-pho-secondary hover:text-pho-secondary-hover flex shrink-0 cursor-pointer items-center transition-colors duration-100 ease-linear [&>svg]:size-4\"\n >\n <IconX aria-hidden />\n </button>\n ) : null}\n </label>\n );\n}\n"],"mappings":";;;;;;AAiCA,SAAgB,EAAY,EAC1B,OAAA,GACA,UAAA,GACA,SAAA,GACA,UAAA,GACA,WAAA,GACA,KAAA,GACA,GAAG,EAAA,GACgB;AACnB,QAAM,IAAW,EAAgC,IAAI;AACrD,SACE,gBAAA,EAAC,SAAD;AAAA,IACE,WAAW,EAAG,iDAAiD,CAAS;AAAA,IAD1E,UAAA;AAAA,MAGE,gBAAA,EAAC,GAAD;AAAA,QACE,eAAA;AAAA,QACA,WAAU;AAAA,MACX,CAAA;AAAA,MACD,gBAAA,EAAC,SAAD;AAAA,QACE,KAAA,CAAM,MAAS;AACb,UAAA,EAAS,UAAU,GACf,OAAO,KAAQ,aAAY,EAAI,CAAI,IAC9B,KAAO,SAAM,EAAI,UAAU;AAAA,QACtC;AAAA,QACA,MAAK;AAAA,QACE,OAAA;AAAA,QACP,UAAA,CAAW,MAAU;AACnB,UAAA,EAAM,gBAAgB,GACtB,EAAS,EAAM,OAAO,KAAK;AAAA,QAC7B;AAAA,QACA,WAAW,EACT,qHAEA,KAAW,QACT,kGACJ;AAAA,QACA,GAAI;AAAA,QACJ,cACE,EAAM,YAAA,MACL,EAAM,iBAAA,IAAqB,SAAY;AAAA,MAE3C,CAAA;AAAA,MACA,KAAY,OACX,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,QACb,UAAA;AAAA,MACG,CAAA,IACJ;AAAA,MACH,KAAW,QAAQ,MAAU,MAAM,CAAC,EAAM,WACzC,gBAAA,EAAC,UAAD;AAAA,QACE,MAAK;AAAA,QACL,cAAW;AAAA,QAGX,UAAU;AAAA,QACV,SAAA,MAAe;AACb,UAAA,EAAQ,GACR,EAAS,SAAS,MAAM;AAAA,QAC1B;AAAA,QACA,WAAU;AAAA,QAEV,UAAA,gBAAA,EAAC,GAAD,EAAO,eAAA,GAAa,CAAA;AAAA,MACd,CAAA,IACN;AAAA,IACC;AAAA;AAEX"}
|
|
@@ -61,6 +61,7 @@ function G({ label: l, hint: d, size: a = "md", invalid: r, icon: n, labelTraili
|
|
|
61
61
|
className: "text-pho-secondary flex cursor-default items-center gap-0.5 text-base font-medium",
|
|
62
62
|
children: [l, p && /* @__PURE__ */ e("span", {
|
|
63
63
|
className: "text-pho-brand",
|
|
64
|
+
"aria-hidden": "true",
|
|
64
65
|
children: "*"
|
|
65
66
|
})]
|
|
66
67
|
}), b]
|
|
@@ -106,4 +107,4 @@ export {
|
|
|
106
107
|
G as t
|
|
107
108
|
};
|
|
108
109
|
|
|
109
|
-
//# sourceMappingURL=input-
|
|
110
|
+
//# sourceMappingURL=input-fFWvPJOf.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-DjvZoF8v.js","names":["__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconEyeOff.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconEye.mjs","../../src/components/input/input.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M10.585 10.587a2 2 0 0 0 2.829 2.828\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M3 3l18 18\", \"key\": \"svg-2\" }]];\nconst IconEyeOff = createReactComponent(\"outline\", \"eye-off\", \"EyeOff\", __iconNode);\n\nexport { __iconNode, IconEyeOff as default };\n//# sourceMappingURL=IconEyeOff.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\", \"key\": \"svg-1\" }]];\nconst IconEye = createReactComponent(\"outline\", \"eye\", \"Eye\", __iconNode);\n\nexport { __iconNode, IconEye as default };\n//# sourceMappingURL=IconEye.mjs.map\n","import {\n useState,\n type ComponentType,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport {\n IconAlertCircleFilled,\n IconEye,\n IconEyeOff,\n} from \"@tabler/icons-react\";\nimport { Field } from \"@base-ui/react/field\";\nimport { cn } from \"../../utils/cn\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\n// Control padding per size. The wrapper carries a 2px inset (`p-0.5`) so the\n// control's border box — and the browser's autofill fill it paints — sits\n// inside the ring instead of over it; these paddings are the documented\n// effective padding (sm/md 12/8px, lg 14/10px) minus that 2px inset, so the\n// text position and total field height are unchanged.\nconst SIZE_PAD: Record<InputSize, string> = {\n // 16px on small viewports — iOS zooms into any focused field under 16px.\n sm: \"px-2.5 py-1.5 text-md md:text-base\",\n md: \"px-2.5 py-1.5 text-md\",\n lg: \"px-3 py-2 text-md\",\n};\n// Effective icon clearance minus the wrapper's 2px inset.\nconst LEADING_PAD: Record<InputSize, string> = {\n sm: \"pl-8.5\",\n md: \"pl-9.5\",\n lg: \"pl-10\",\n};\n// Icons are absolutely positioned, so they're placed from the wrapper's\n// padding edge — which, with no border, is the visible field edge; the\n// wrapper's `p-0.5` does not offset them.\nconst LEADING_ICON_POS: Record<InputSize, string> = {\n sm: \"left-3 size-4\",\n md: \"left-3 size-5\",\n lg: \"left-3.5 size-5\",\n};\n// Wrapper corner radius — `rounded-base` (12px) at every size; `lg` also gets\n// `squircle` superellipse smoothing (the ring is a box-shadow on this wrapper,\n// so it follows the border-radius automatically).\nconst SIZE_RADIUS: Record<InputSize, string> = {\n sm: \"rounded-base\",\n md: \"rounded-base\",\n lg: \"squircle rounded-base\",\n};\n// Concentric inner-curve cover, `lg` only. Nested corner radii must follow\n// innerRadius = outerRadius − inset, so the hairline's inner edge at a 12px\n// outer radius is 11px at rest (ring-1) and 10px when focused (ring-2).\n// Browsers derive that automatically for plain round corners, but with\n// `corner-shape: superellipse(...)` shipping engines still scale (rather than\n// offset) the inner shadow curve, which renders the ring visibly thicker at\n// the four corners (see w3c/csswg-drafts#12961). This ::before repaints the\n// field surface over everything inside the correct concentric curve — a round\n// radius is the right parallel-offset approximation of the mild superellipse —\n// so the ring reads as a uniform hairline in every engine. `isolate` +\n// `-z-10` slot the cover above the wrapper's background/ring but below the\n// control's text, icons, and autofill fill. `sm`/`md` have no corner-shape,\n// so the native (already concentric) rendering is kept there.\n// The ::before is absolutely positioned, so its inset is measured from the\n// wrapper's border box (border 0): 1px in at rest, 2px in when focused.\nconst SIZE_RING_COVER: Record<InputSize, string> = {\n sm: \"\",\n md: \"\",\n lg: cn(\n \"isolate before:pointer-events-none before:absolute before:-z-10 before:content-['']\",\n \"before:bg-pho-primary before:inset-px before:rounded-[calc(var(--radius-base)-1px)]\",\n // Invalid sits between rest (1px) and focus (2px) — keep the cover concentric.\n \"data-[invalid]:before:inset-[1.5px] data-[invalid]:before:rounded-[calc(var(--radius-base)-1.5px)]\",\n \"has-[input:focus-visible]:before:inset-0.5 has-[input:focus-visible]:before:rounded-[calc(var(--radius-base)-2px)]\",\n \"before:transition-[inset,border-radius] before:duration-100 before:ease-linear\",\n ),\n};\n// The control's border box sits 2px inside the wrapper (its `p-0.5` inset),\n// clear of both ring widths, so the browser's autofill fill paints inside the\n// hairline instead of over it. Rounding follows inner = outer − gap, derived\n// from the token with calc. Round (not squircle) — the parallel offset of\n// the wrapper's mild superellipse is effectively circular.\nconst SIZE_AUTOFILL_RADIUS: Record<InputSize, string> = {\n sm: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n md: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n lg: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n};\n\nexport interface InputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"size\"\n> {\n /** Field label (associated for accessibility). */\n label?: ReactNode;\n /** Helper text below the field; rendered in the error color when `invalid`. */\n hint?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: InputSize;\n /** Render the invalid state (ring + icon + error-colored hint). */\n invalid?: boolean;\n /** Leading icon component (e.g. a Tabler icon). */\n icon?: ComponentType<{ className?: string }>;\n /** Node rendered at the right edge of the label row (e.g. \"Forgot?\"). */\n labelTrailing?: ReactNode;\n /**\n * Quiet word or glyph inside the field at its trailing edge (an\n * auto-save's `Saved`, a live character count). Non-interactive overlay:\n * it never takes the pointer, the invalid icon takes the corner over\n * it, and the input reserves nothing — content that shows only\n * sometimes brings its own surface wash (as `Saved` does) so long text\n * fades beneath it instead of colliding.\n */\n trailing?: ReactNode;\n /** Class applied to the input wrapper. */\n wrapperClassName?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\n/**\n * Text input built on Base UI `Field` (label/description a11y wiring) with\n * Pho's bordered surface, leading icon, invalid state, and a built-in password\n * reveal toggle.\n */\nexport function Input({\n label,\n hint,\n size = \"md\",\n invalid,\n icon: Icon,\n labelTrailing,\n trailing,\n disabled,\n required,\n type = \"text\",\n className,\n wrapperClassName,\n id,\n ref,\n ...props\n}: InputProps) {\n const [reveal, setReveal] = useState(false);\n const isPassword = type === \"password\";\n const resolvedType = isPassword && reveal ? \"text\" : type;\n const hasLeadingIcon = Boolean(Icon);\n const hasTrailingIcon = isPassword || invalid;\n const hasTrailing = trailing != null && !invalid && !isPassword;\n\n return (\n <Field.Root\n disabled={disabled}\n className=\"group/field flex w-full flex-col gap-1.5\"\n >\n {label && (\n <div className=\"flex items-center justify-between gap-2\">\n <Field.Label className=\"text-pho-secondary flex cursor-default items-center gap-0.5 text-base font-medium\">\n {label}\n {required && <span className=\"text-pho-brand\">*</span>}\n </Field.Label>\n {labelTrailing}\n </div>\n )}\n\n <div\n data-invalid={invalid || undefined}\n className={cn(\n // Flat field surface — hairline ring only; elevation shadows are\n // reserved for floating layers (menus/popovers/dialogs). `p-0.5`\n // insets the control 2px (the focused ring width) so its background\n // and the browser's autofill fill nest inside the ring; the size\n // maps compensate so effective padding/height are unchanged.\n \"bg-pho-primary ring-pho-primary relative flex w-full items-center p-0.5 ring-1 transition-shadow duration-100 ease-linear ring-inset\",\n SIZE_RADIUS[size],\n SIZE_RING_COVER[size],\n \"has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2\",\n // Invalid is mid-weight: thicker than the 1px rest hairline, thinner\n // than the 2px focus ring. Rest uses the subtle error ink; focus\n // steps up to the solid error (same hue, full opacity).\n \"data-[invalid]:ring-pho-error-subtle data-[invalid]:has-[input:focus-visible]:ring-pho-error data-[invalid]:ring-[1.5px]\",\n \"group-data-[disabled]/field:cursor-not-allowed group-data-[disabled]/field:opacity-50\",\n wrapperClassName,\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"text-pho-secondary pointer-events-none absolute\",\n LEADING_ICON_POS[size],\n )}\n />\n )}\n\n <Field.Control\n ref={ref}\n id={id}\n type={resolvedType}\n required={required}\n {...props}\n className={cn(\n \"text-pho-primary placeholder:text-pho-placeholder m-0 w-full bg-transparent outline-none disabled:cursor-not-allowed\",\n SIZE_PAD[size],\n SIZE_AUTOFILL_RADIUS[size],\n hasLeadingIcon && LEADING_PAD[size],\n // 34px + the wrapper's 2px inset = the previous 36px clearance.\n hasTrailingIcon && \"pr-8.5\",\n className,\n )}\n />\n\n {invalid && !isPassword && (\n <IconAlertCircleFilled className=\"text-pho-error pointer-events-none absolute right-3 size-4\" />\n )}\n {hasTrailing && (\n <span className=\"text-pho-description pointer-events-none absolute right-3 flex items-center\">\n {trailing}\n </span>\n )}\n\n {isPassword && (\n <button\n type=\"button\"\n // Reachable by click but skipped in tab order so Tab moves field→field.\n tabIndex={-1}\n aria-label=\"Toggle password visibility\"\n onClick={() => setReveal((v) => !v)}\n className=\"text-pho-secondary hover:text-pho-secondary-hover absolute right-3 flex cursor-pointer items-center transition duration-100 ease-linear focus:outline-none\"\n >\n {reveal ? (\n <IconEyeOff className=\"size-4\" />\n ) : (\n <IconEye className=\"size-4\" />\n )}\n </button>\n )}\n </div>\n\n {hint && (\n <Field.Description\n className={cn(\n \"text-pho-description text-base\",\n invalid && \"text-pho-error\",\n )}\n >\n {hint}\n </Field.Description>\n )}\n {/* Validation and server errors routed here by Field / Form. */}\n <Field.Error className=\"text-pho-error text-base\" />\n </Field.Root>\n );\n}\n\nInput.displayName = \"Input\";\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"input-fFWvPJOf.js","names":["__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconEyeOff.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconEye.mjs","../../src/components/input/input.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M10.585 10.587a2 2 0 0 0 2.829 2.828\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M3 3l18 18\", \"key\": \"svg-2\" }]];\nconst IconEyeOff = createReactComponent(\"outline\", \"eye-off\", \"EyeOff\", __iconNode);\n\nexport { __iconNode, IconEyeOff as default };\n//# sourceMappingURL=IconEyeOff.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\", \"key\": \"svg-1\" }]];\nconst IconEye = createReactComponent(\"outline\", \"eye\", \"Eye\", __iconNode);\n\nexport { __iconNode, IconEye as default };\n//# sourceMappingURL=IconEye.mjs.map\n","import {\n useState,\n type ComponentType,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport {\n IconAlertCircleFilled,\n IconEye,\n IconEyeOff,\n} from \"@tabler/icons-react\";\nimport { Field } from \"@base-ui/react/field\";\nimport { cn } from \"../../utils/cn\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\n// Control padding per size. The wrapper carries a 2px inset (`p-0.5`) so the\n// control's border box — and the browser's autofill fill it paints — sits\n// inside the ring instead of over it; these paddings are the documented\n// effective padding (sm/md 12/8px, lg 14/10px) minus that 2px inset, so the\n// text position and total field height are unchanged.\nconst SIZE_PAD: Record<InputSize, string> = {\n // 16px on small viewports — iOS zooms into any focused field under 16px.\n sm: \"px-2.5 py-1.5 text-md md:text-base\",\n md: \"px-2.5 py-1.5 text-md\",\n lg: \"px-3 py-2 text-md\",\n};\n// Effective icon clearance minus the wrapper's 2px inset.\nconst LEADING_PAD: Record<InputSize, string> = {\n sm: \"pl-8.5\",\n md: \"pl-9.5\",\n lg: \"pl-10\",\n};\n// Icons are absolutely positioned, so they're placed from the wrapper's\n// padding edge — which, with no border, is the visible field edge; the\n// wrapper's `p-0.5` does not offset them.\nconst LEADING_ICON_POS: Record<InputSize, string> = {\n sm: \"left-3 size-4\",\n md: \"left-3 size-5\",\n lg: \"left-3.5 size-5\",\n};\n// Wrapper corner radius — `rounded-base` (12px) at every size; `lg` also gets\n// `squircle` superellipse smoothing (the ring is a box-shadow on this wrapper,\n// so it follows the border-radius automatically).\nconst SIZE_RADIUS: Record<InputSize, string> = {\n sm: \"rounded-base\",\n md: \"rounded-base\",\n lg: \"squircle rounded-base\",\n};\n// Concentric inner-curve cover, `lg` only. Nested corner radii must follow\n// innerRadius = outerRadius − inset, so the hairline's inner edge at a 12px\n// outer radius is 11px at rest (ring-1) and 10px when focused (ring-2).\n// Browsers derive that automatically for plain round corners, but with\n// `corner-shape: superellipse(...)` shipping engines still scale (rather than\n// offset) the inner shadow curve, which renders the ring visibly thicker at\n// the four corners (see w3c/csswg-drafts#12961). This ::before repaints the\n// field surface over everything inside the correct concentric curve — a round\n// radius is the right parallel-offset approximation of the mild superellipse —\n// so the ring reads as a uniform hairline in every engine. `isolate` +\n// `-z-10` slot the cover above the wrapper's background/ring but below the\n// control's text, icons, and autofill fill. `sm`/`md` have no corner-shape,\n// so the native (already concentric) rendering is kept there.\n// The ::before is absolutely positioned, so its inset is measured from the\n// wrapper's border box (border 0): 1px in at rest, 2px in when focused.\nconst SIZE_RING_COVER: Record<InputSize, string> = {\n sm: \"\",\n md: \"\",\n lg: cn(\n \"isolate before:pointer-events-none before:absolute before:-z-10 before:content-['']\",\n \"before:bg-pho-primary before:inset-px before:rounded-[calc(var(--radius-base)-1px)]\",\n // Invalid sits between rest (1px) and focus (2px) — keep the cover concentric.\n \"data-[invalid]:before:inset-[1.5px] data-[invalid]:before:rounded-[calc(var(--radius-base)-1.5px)]\",\n \"has-[input:focus-visible]:before:inset-0.5 has-[input:focus-visible]:before:rounded-[calc(var(--radius-base)-2px)]\",\n \"before:transition-[inset,border-radius] before:duration-100 before:ease-linear\",\n ),\n};\n// The control's border box sits 2px inside the wrapper (its `p-0.5` inset),\n// clear of both ring widths, so the browser's autofill fill paints inside the\n// hairline instead of over it. Rounding follows inner = outer − gap, derived\n// from the token with calc. Round (not squircle) — the parallel offset of\n// the wrapper's mild superellipse is effectively circular.\nconst SIZE_AUTOFILL_RADIUS: Record<InputSize, string> = {\n sm: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n md: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n lg: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n};\n\nexport interface InputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"size\"\n> {\n /** Field label (associated for accessibility). */\n label?: ReactNode;\n /** Helper text below the field; rendered in the error color when `invalid`. */\n hint?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: InputSize;\n /** Render the invalid state (ring + icon + error-colored hint). */\n invalid?: boolean;\n /** Leading icon component (e.g. a Tabler icon). */\n icon?: ComponentType<{ className?: string }>;\n /** Node rendered at the right edge of the label row (e.g. \"Forgot?\"). */\n labelTrailing?: ReactNode;\n /**\n * Quiet word or glyph inside the field at its trailing edge (an\n * auto-save's `Saved`, a live character count). Non-interactive overlay:\n * it never takes the pointer, the invalid icon takes the corner over\n * it, and the input reserves nothing — content that shows only\n * sometimes brings its own surface wash (as `Saved` does) so long text\n * fades beneath it instead of colliding.\n */\n trailing?: ReactNode;\n /** Class applied to the input wrapper. */\n wrapperClassName?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\n/**\n * Text input built on Base UI `Field` (label/description a11y wiring) with\n * Pho's bordered surface, leading icon, invalid state, and a built-in password\n * reveal toggle.\n */\nexport function Input({\n label,\n hint,\n size = \"md\",\n invalid,\n icon: Icon,\n labelTrailing,\n trailing,\n disabled,\n required,\n type = \"text\",\n className,\n wrapperClassName,\n id,\n ref,\n ...props\n}: InputProps) {\n const [reveal, setReveal] = useState(false);\n const isPassword = type === \"password\";\n const resolvedType = isPassword && reveal ? \"text\" : type;\n const hasLeadingIcon = Boolean(Icon);\n const hasTrailingIcon = isPassword || invalid;\n const hasTrailing = trailing != null && !invalid && !isPassword;\n\n return (\n <Field.Root\n disabled={disabled}\n className=\"group/field flex w-full flex-col gap-1.5\"\n >\n {label && (\n <div className=\"flex items-center justify-between gap-2\">\n <Field.Label className=\"text-pho-secondary flex cursor-default items-center gap-0.5 text-base font-medium\">\n {label}\n {required && (\n <span className=\"text-pho-brand\" aria-hidden=\"true\">\n *\n </span>\n )}\n </Field.Label>\n {labelTrailing}\n </div>\n )}\n\n <div\n data-invalid={invalid || undefined}\n className={cn(\n // Flat field surface — hairline ring only; elevation shadows are\n // reserved for floating layers (menus/popovers/dialogs). `p-0.5`\n // insets the control 2px (the focused ring width) so its background\n // and the browser's autofill fill nest inside the ring; the size\n // maps compensate so effective padding/height are unchanged.\n \"bg-pho-primary ring-pho-primary relative flex w-full items-center p-0.5 ring-1 transition-shadow duration-100 ease-linear ring-inset\",\n SIZE_RADIUS[size],\n SIZE_RING_COVER[size],\n \"has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2\",\n // Invalid is mid-weight: thicker than the 1px rest hairline, thinner\n // than the 2px focus ring. Rest uses the subtle error ink; focus\n // steps up to the solid error (same hue, full opacity).\n \"data-[invalid]:ring-pho-error-subtle data-[invalid]:has-[input:focus-visible]:ring-pho-error data-[invalid]:ring-[1.5px]\",\n \"group-data-[disabled]/field:cursor-not-allowed group-data-[disabled]/field:opacity-50\",\n wrapperClassName,\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"text-pho-secondary pointer-events-none absolute\",\n LEADING_ICON_POS[size],\n )}\n />\n )}\n\n <Field.Control\n ref={ref}\n id={id}\n type={resolvedType}\n required={required}\n {...props}\n className={cn(\n \"text-pho-primary placeholder:text-pho-placeholder m-0 w-full bg-transparent outline-none disabled:cursor-not-allowed\",\n SIZE_PAD[size],\n SIZE_AUTOFILL_RADIUS[size],\n hasLeadingIcon && LEADING_PAD[size],\n // 34px + the wrapper's 2px inset = the previous 36px clearance.\n hasTrailingIcon && \"pr-8.5\",\n className,\n )}\n />\n\n {invalid && !isPassword && (\n <IconAlertCircleFilled className=\"text-pho-error pointer-events-none absolute right-3 size-4\" />\n )}\n {hasTrailing && (\n <span className=\"text-pho-description pointer-events-none absolute right-3 flex items-center\">\n {trailing}\n </span>\n )}\n\n {isPassword && (\n <button\n type=\"button\"\n // Reachable by click but skipped in tab order so Tab moves field→field.\n tabIndex={-1}\n aria-label=\"Toggle password visibility\"\n onClick={() => setReveal((v) => !v)}\n className=\"text-pho-secondary hover:text-pho-secondary-hover absolute right-3 flex cursor-pointer items-center transition duration-100 ease-linear focus:outline-none\"\n >\n {reveal ? (\n <IconEyeOff className=\"size-4\" />\n ) : (\n <IconEye className=\"size-4\" />\n )}\n </button>\n )}\n </div>\n\n {hint && (\n <Field.Description\n className={cn(\n \"text-pho-description text-base\",\n invalid && \"text-pho-error\",\n )}\n >\n {hint}\n </Field.Description>\n )}\n {/* Validation and server errors routed here by Field / Form. */}\n <Field.Error className=\"text-pho-error text-base\" />\n </Field.Root>\n );\n}\n\nInput.displayName = \"Input\";\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
@@ -7,7 +7,8 @@ import { t as Te } from "./IconChevronUp-CrpWSgIl.js";
|
|
|
7
7
|
import { t as Ze } from "./IconX-pZ9vrtSr.js";
|
|
8
8
|
import { t as ge } from "./collapsible-Dv306QOT.js";
|
|
9
9
|
import { t as he } from "./skeleton-DwjSl4vC.js";
|
|
10
|
-
import {
|
|
10
|
+
import { i as Je, n as Ye, r as Qe, t as qe } from "./chrome-Ds7WykBJ.js";
|
|
11
|
+
import { t as et } from "./ghost-search-8PzP73zS.js";
|
|
11
12
|
import { i as tt, r as nt } from "./badge-DlLJPLeZ.js";
|
|
12
13
|
import { createContext as de, useCallback as F, useContext as ue, useEffect as ae, useId as at, useMemo as O, useRef as fe, useState as Y } from "react";
|
|
13
14
|
import { Fragment as Ee, jsx as s, jsxs as N } from "react/jsx-runtime";
|
|
@@ -252,7 +253,7 @@ function Pe(e, t) {
|
|
|
252
253
|
}
|
|
253
254
|
return n;
|
|
254
255
|
}
|
|
255
|
-
function
|
|
256
|
+
function Zn(e, t = /* @__PURE__ */ new Set()) {
|
|
256
257
|
return Pe($e(e), t);
|
|
257
258
|
}
|
|
258
259
|
function Ct(e, t) {
|
|
@@ -323,7 +324,7 @@ function Dt(e, t) {
|
|
|
323
324
|
let o = n + t * r;
|
|
324
325
|
return o = Math.min(Math.max(o, 0), 1 - r), ie([o, o + r]);
|
|
325
326
|
}
|
|
326
|
-
function
|
|
327
|
+
function Jn(e, t) {
|
|
327
328
|
return e[0] + t * (e[1] - e[0]);
|
|
328
329
|
}
|
|
329
330
|
function Rt(e) {
|
|
@@ -868,13 +869,13 @@ function Fe(e, t) {
|
|
|
868
869
|
align: r
|
|
869
870
|
}));
|
|
870
871
|
}
|
|
871
|
-
function
|
|
872
|
+
function Yn(e, t) {
|
|
872
873
|
return Fe(e, t).map((n) => n.ms);
|
|
873
874
|
}
|
|
874
875
|
function K(e) {
|
|
875
876
|
return `${Number((e * 100).toFixed(4))}%`;
|
|
876
877
|
}
|
|
877
|
-
var We = S(
|
|
878
|
+
var We = S(Qe, "overflow-hidden"), Ke = "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)]", dn = "absolute inset-y-0 left-5 right-5", Be = 20, Ve = 16, un = 26;
|
|
878
879
|
function pn(e) {
|
|
879
880
|
return `${Be + e * Ve + un}px`;
|
|
880
881
|
}
|
|
@@ -1263,6 +1264,7 @@ function Cn({ sources: e, spanCount: t, errorCount: n, selectedId: a, onSelect:
|
|
|
1263
1264
|
ref: f,
|
|
1264
1265
|
value: c,
|
|
1265
1266
|
onChange: d,
|
|
1267
|
+
onClear: () => d(""),
|
|
1266
1268
|
placeholder: Z,
|
|
1267
1269
|
"aria-label": Z,
|
|
1268
1270
|
onKeyDown: (u) => {
|
|
@@ -1623,7 +1625,7 @@ function Pn({ logs: e, spans: t, loading: n, title: a, className: r, ...o }) {
|
|
|
1623
1625
|
}) : null,
|
|
1624
1626
|
/* @__PURE__ */ N("div", {
|
|
1625
1627
|
"data-trace-logs-header": "",
|
|
1626
|
-
className: S(me,
|
|
1628
|
+
className: S(me, Ye, "items-center"),
|
|
1627
1629
|
children: [
|
|
1628
1630
|
/* @__PURE__ */ s("span", { children: "Offset" }),
|
|
1629
1631
|
/* @__PURE__ */ s("span", { children: "Level" }),
|
|
@@ -1631,7 +1633,7 @@ function Pn({ logs: e, spans: t, loading: n, title: a, className: r, ...o }) {
|
|
|
1631
1633
|
]
|
|
1632
1634
|
}),
|
|
1633
1635
|
/* @__PURE__ */ s("ol", {
|
|
1634
|
-
className: S(
|
|
1636
|
+
className: S(qe, "m-0 list-none p-0 font-mono"),
|
|
1635
1637
|
children: i.length > 0 ? i.map((c, d) => /* @__PURE__ */ N("li", {
|
|
1636
1638
|
className: S(me, "h-10 items-center"),
|
|
1637
1639
|
children: [
|
|
@@ -1666,7 +1668,7 @@ function Pn({ logs: e, spans: t, loading: n, title: a, className: r, ...o }) {
|
|
|
1666
1668
|
]
|
|
1667
1669
|
});
|
|
1668
1670
|
}
|
|
1669
|
-
var Dn = Object.assign(An, { Footer: Xe }),
|
|
1671
|
+
var Dn = Object.assign(An, { Footer: Xe }), Qn = {
|
|
1670
1672
|
Waterfall: Dn,
|
|
1671
1673
|
Logs: Pn
|
|
1672
1674
|
};
|
|
@@ -1674,7 +1676,7 @@ export {
|
|
|
1674
1676
|
It as A,
|
|
1675
1677
|
Pe as B,
|
|
1676
1678
|
xe as C,
|
|
1677
|
-
|
|
1679
|
+
Zn as D,
|
|
1678
1680
|
Ct as E,
|
|
1679
1681
|
Dt as F,
|
|
1680
1682
|
zt as I,
|
|
@@ -1683,14 +1685,14 @@ export {
|
|
|
1683
1685
|
Ot as N,
|
|
1684
1686
|
ie as O,
|
|
1685
1687
|
Rt as P,
|
|
1686
|
-
|
|
1688
|
+
Jn as R,
|
|
1687
1689
|
G as S,
|
|
1688
1690
|
_t as T,
|
|
1689
1691
|
Pt as V,
|
|
1690
1692
|
nn as _,
|
|
1691
1693
|
Ne as a,
|
|
1692
1694
|
H as b,
|
|
1693
|
-
|
|
1695
|
+
Yn as c,
|
|
1694
1696
|
an as d,
|
|
1695
1697
|
rn as f,
|
|
1696
1698
|
qt as g,
|
|
@@ -1705,7 +1707,7 @@ export {
|
|
|
1705
1707
|
Jt as p,
|
|
1706
1708
|
pn as r,
|
|
1707
1709
|
Oe as s,
|
|
1708
|
-
|
|
1710
|
+
Qn as t,
|
|
1709
1711
|
sn as u,
|
|
1710
1712
|
en as v,
|
|
1711
1713
|
J as w,
|
|
@@ -1714,4 +1716,4 @@ export {
|
|
|
1714
1716
|
$t as z
|
|
1715
1717
|
};
|
|
1716
1718
|
|
|
1717
|
-
//# sourceMappingURL=trace-
|
|
1719
|
+
//# sourceMappingURL=trace-DyjsBY-S.js.map
|