@photon-ai/pho-ui 1.4.0 → 2.0.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/IconAlertCircleFilled-VxKU8TYK.js +11 -0
- package/dist/chunks/IconAlertCircleFilled-VxKU8TYK.js.map +1 -0
- package/dist/chunks/IconArrowUpRight-DGgKzQwV.js +14 -0
- package/dist/chunks/IconArrowUpRight-DGgKzQwV.js.map +1 -0
- package/dist/chunks/IconChevronLeft-CSWMKQ4C.js +11 -0
- package/dist/chunks/IconChevronLeft-CSWMKQ4C.js.map +1 -0
- package/dist/chunks/IconInfoCircle-L0zfhg7R.js +21 -0
- package/dist/chunks/IconInfoCircle-L0zfhg7R.js.map +1 -0
- package/dist/chunks/animated-height-DhNSac85.js +50 -0
- package/dist/chunks/animated-height-DhNSac85.js.map +1 -0
- package/dist/chunks/basic-page-D1zm81YS.js +481 -0
- package/dist/chunks/basic-page-D1zm81YS.js.map +1 -0
- package/dist/chunks/{close-button-B8gF5UNk.js → button-X5wsWvRa.js} +127 -147
- package/dist/chunks/button-X5wsWvRa.js.map +1 -0
- package/dist/chunks/close-button-xadxp0j8.js +29 -0
- package/dist/chunks/close-button-xadxp0j8.js.map +1 -0
- package/dist/chunks/combobox-rLdS6fl-.js +117 -0
- package/dist/chunks/combobox-rLdS6fl-.js.map +1 -0
- package/dist/chunks/dialog-Caze1vkf.js +252 -0
- package/dist/chunks/dialog-Caze1vkf.js.map +1 -0
- package/dist/chunks/error-DR6G2LmG.js +251 -0
- package/dist/chunks/error-DR6G2LmG.js.map +1 -0
- package/dist/chunks/{input-CxS7ndpb.js → input-D3XQcC4J.js} +29 -31
- package/dist/chunks/input-D3XQcC4J.js.map +1 -0
- package/dist/chunks/{menu-BSXds3Rt.js → menu-BC-9IP29.js} +39 -39
- package/dist/chunks/menu-BC-9IP29.js.map +1 -0
- package/dist/chunks/popover-EL1SE1kj.js +46 -0
- package/dist/chunks/popover-EL1SE1kj.js.map +1 -0
- package/dist/chunks/{sidebar-DGpEKxOn.js → sidebar-DDJC1MeD.js} +72 -64
- package/dist/chunks/sidebar-DDJC1MeD.js.map +1 -0
- package/dist/components/button.js +13 -12
- package/dist/components/combobox.js +2 -114
- package/dist/components/command.js +242 -0
- package/dist/components/command.js.map +1 -0
- package/dist/components/context-menu.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/error.js +13 -0
- package/dist/components/input.js +1 -1
- package/dist/components/menu.js +1 -1
- package/dist/components/notification.js +27 -39
- package/dist/components/notification.js.map +1 -1
- package/dist/components/phone-input.js +17001 -0
- package/dist/components/phone-input.js.map +1 -0
- package/dist/components/popover.js +2 -43
- package/dist/components/toast.js.map +1 -1
- package/dist/index.js +62 -50
- package/dist/primitives.js +1 -1
- package/dist/sections/basic-page.js +1 -1
- package/dist/sections/sidebar.js +1 -1
- package/dist/src/components/command/command.d.ts +114 -0
- package/dist/src/components/command/index.d.ts +1 -0
- package/dist/src/components/dialog/dialog.d.ts +89 -1
- package/dist/src/components/drawer/drawer.d.ts +2 -2
- package/dist/src/components/error/error.d.ts +56 -0
- package/dist/src/components/error/index.d.ts +2 -0
- package/dist/src/components/error/problem.d.ts +80 -0
- package/dist/src/components/notification/notification.d.ts +1 -1
- package/dist/src/components/phone-input/country-alpha3.d.ts +250 -0
- package/dist/src/components/phone-input/country-search.d.ts +8 -0
- package/dist/src/components/phone-input/index.d.ts +1 -0
- package/dist/src/components/phone-input/phone-input.d.ts +47 -0
- package/dist/src/components/toast/toast.d.ts +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/sections/basic-page/basic-page.d.ts +165 -45
- package/dist/src/sections/sidebar/sidebar.d.ts +8 -3
- package/dist/src/utils/animated-height.d.ts +13 -0
- package/package.json +16 -5
- package/src/styles/theme.css +27 -0
- package/dist/chunks/basic-page-4_GZOvRr.js +0 -255
- package/dist/chunks/basic-page-4_GZOvRr.js.map +0 -1
- package/dist/chunks/close-button-B8gF5UNk.js.map +0 -1
- package/dist/chunks/dialog-Ba0UUE5g.js +0 -155
- package/dist/chunks/dialog-Ba0UUE5g.js.map +0 -1
- package/dist/chunks/input-CxS7ndpb.js.map +0 -1
- package/dist/chunks/menu-BSXds3Rt.js.map +0 -1
- package/dist/chunks/sidebar-DGpEKxOn.js.map +0 -1
- package/dist/components/alert-dialog.js +0 -59
- package/dist/components/alert-dialog.js.map +0 -1
- package/dist/components/combobox.js.map +0 -1
- package/dist/components/popover.js.map +0 -1
- package/dist/src/components/alert-dialog/alert-dialog.d.ts +0 -41
- package/dist/src/components/alert-dialog/index.d.ts +0 -1
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as h } from "./cn-DTiB6ek_.js";
|
|
3
|
+
import { a as x, o as R } from "./button-X5wsWvRa.js";
|
|
4
|
+
import { t as C } from "./createReactComponent-BqCmnqfX.js";
|
|
5
|
+
import { t as S } from "./IconInfoCircle-L0zfhg7R.js";
|
|
6
|
+
import { t as g } from "./IconAlertCircleFilled-VxKU8TYK.js";
|
|
7
|
+
import { i as _ } from "./status-view-CcbctPqR.js";
|
|
8
|
+
import { t as l } from "./popover-EL1SE1kj.js";
|
|
9
|
+
import { useEffect as A, useRef as P, useState as L } from "react";
|
|
10
|
+
import { Fragment as c, jsx as n, jsxs as s } from "react/jsx-runtime";
|
|
11
|
+
var k = [
|
|
12
|
+
["path", {
|
|
13
|
+
d: "M12 9v4",
|
|
14
|
+
key: "svg-0"
|
|
15
|
+
}],
|
|
16
|
+
["path", {
|
|
17
|
+
d: "M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0",
|
|
18
|
+
key: "svg-1"
|
|
19
|
+
}],
|
|
20
|
+
["path", {
|
|
21
|
+
d: "M12 16h.01",
|
|
22
|
+
key: "svg-2"
|
|
23
|
+
}]
|
|
24
|
+
], z = C("outline", "alert-triangle", "AlertTriangle", k);
|
|
25
|
+
function m(t) {
|
|
26
|
+
if (typeof t != "object" || t === null) return !1;
|
|
27
|
+
const e = t;
|
|
28
|
+
return typeof e.title == "string" && typeof e.status == "number" && Number.isInteger(e.status) && e.status >= 400 && e.status <= 599 && (e.code === void 0 || typeof e.code == "string");
|
|
29
|
+
}
|
|
30
|
+
function D(t) {
|
|
31
|
+
let e = t;
|
|
32
|
+
for (let r = 0; r < 8 && typeof e == "object" && e !== null; r++) {
|
|
33
|
+
if (m(e)) return e;
|
|
34
|
+
const i = e.problem;
|
|
35
|
+
if (m(i)) return i;
|
|
36
|
+
e = e.cause;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
var j = "Something went wrong.", f = {
|
|
41
|
+
400: "Bad Request",
|
|
42
|
+
401: "Unauthorized",
|
|
43
|
+
403: "Forbidden",
|
|
44
|
+
404: "Not Found",
|
|
45
|
+
408: "Request Timeout",
|
|
46
|
+
409: "Conflict",
|
|
47
|
+
410: "Gone",
|
|
48
|
+
413: "Payload Too Large",
|
|
49
|
+
415: "Unsupported Media Type",
|
|
50
|
+
422: "Unprocessable Entity",
|
|
51
|
+
429: "Too Many Requests",
|
|
52
|
+
500: "Internal Server Error",
|
|
53
|
+
501: "Not Implemented",
|
|
54
|
+
502: "Bad Gateway",
|
|
55
|
+
503: "Service Unavailable",
|
|
56
|
+
504: "Gateway Timeout"
|
|
57
|
+
}, B = {
|
|
58
|
+
400: "The request was malformed or incomplete.",
|
|
59
|
+
401: "You need to sign in again.",
|
|
60
|
+
403: "You don't have permission to do that.",
|
|
61
|
+
404: "The requested resource was not found.",
|
|
62
|
+
408: "The request timed out before the server responded.",
|
|
63
|
+
409: "The request conflicts with the current state.",
|
|
64
|
+
410: "That resource is no longer available.",
|
|
65
|
+
413: "The request was too large for the server to accept.",
|
|
66
|
+
415: "That media type isn't supported.",
|
|
67
|
+
422: "The request was understood but couldn't be processed.",
|
|
68
|
+
429: "Request rate limit exceeded. Wait a moment before trying again.",
|
|
69
|
+
500: "The server hit an unexpected error.",
|
|
70
|
+
501: "The server doesn't support that operation.",
|
|
71
|
+
502: "The gateway got an invalid response from an upstream server.",
|
|
72
|
+
503: "The service is temporarily unavailable.",
|
|
73
|
+
504: "The gateway timed out waiting for an upstream server."
|
|
74
|
+
};
|
|
75
|
+
function U(t) {
|
|
76
|
+
return typeof t.code == "string" && t.code !== "";
|
|
77
|
+
}
|
|
78
|
+
function v(t, e) {
|
|
79
|
+
if (f[t]) return f[t];
|
|
80
|
+
if (e && e !== "Something went wrong." && e !== "Request failed") return e.replace(/\.$/, "");
|
|
81
|
+
}
|
|
82
|
+
function $(t) {
|
|
83
|
+
return B[t] ?? "The request failed with an unexpected status.";
|
|
84
|
+
}
|
|
85
|
+
function u(t) {
|
|
86
|
+
if (!t) return t;
|
|
87
|
+
const e = t.charAt(0), r = e.toUpperCase();
|
|
88
|
+
return e === r ? t : r + t.slice(1);
|
|
89
|
+
}
|
|
90
|
+
function y(t) {
|
|
91
|
+
const e = D(t);
|
|
92
|
+
if (e == null) return { title: j };
|
|
93
|
+
const r = [e.detail, e.remediation?.action].filter((i) => typeof i == "string" && i !== "").join(" ") || void 0;
|
|
94
|
+
return !U(e) && r == null ? {
|
|
95
|
+
title: u(v(e.status, e.title) ?? "Something went wrong."),
|
|
96
|
+
description: $(e.status),
|
|
97
|
+
requestId: e.requestId,
|
|
98
|
+
problem: e
|
|
99
|
+
} : {
|
|
100
|
+
title: u(e.title || "Something went wrong."),
|
|
101
|
+
description: r ? u(r) : void 0,
|
|
102
|
+
documentation: e.remediation?.documentation,
|
|
103
|
+
requestId: e.requestId,
|
|
104
|
+
problem: e
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function d(t) {
|
|
108
|
+
return typeof t == "string" ? u(t) : t;
|
|
109
|
+
}
|
|
110
|
+
var T = "Learn more", F = "Try again";
|
|
111
|
+
function M({ error: t, children: e, className: r, ...i }) {
|
|
112
|
+
if (t == null && e == null) return null;
|
|
113
|
+
const o = y(t);
|
|
114
|
+
return /* @__PURE__ */ s("div", {
|
|
115
|
+
role: "alert",
|
|
116
|
+
className: h("text-pho-error flex min-w-0 items-start gap-1.5 text-base", r),
|
|
117
|
+
...i,
|
|
118
|
+
children: [/* @__PURE__ */ n("span", {
|
|
119
|
+
"aria-hidden": !0,
|
|
120
|
+
className: "flex h-[1lh] shrink-0 items-center",
|
|
121
|
+
children: /* @__PURE__ */ n(g, { className: "size-4" })
|
|
122
|
+
}), /* @__PURE__ */ s("span", {
|
|
123
|
+
className: "min-w-0",
|
|
124
|
+
children: [
|
|
125
|
+
d(e ?? o.description ?? o.title),
|
|
126
|
+
o.documentation != null && /* @__PURE__ */ s(c, { children: [" ", /* @__PURE__ */ n("a", {
|
|
127
|
+
href: o.documentation,
|
|
128
|
+
target: "_blank",
|
|
129
|
+
rel: "noreferrer",
|
|
130
|
+
className: "font-medium underline underline-offset-2",
|
|
131
|
+
children: T
|
|
132
|
+
})] }),
|
|
133
|
+
" ",
|
|
134
|
+
/* @__PURE__ */ n(O, { copy: o })
|
|
135
|
+
]
|
|
136
|
+
})]
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
M.displayName = "Error";
|
|
140
|
+
function O({ copy: t }) {
|
|
141
|
+
const { problem: e, requestId: r } = t;
|
|
142
|
+
if (e == null && r == null) return null;
|
|
143
|
+
let i = null;
|
|
144
|
+
if (e != null) if (e.code) i = `${e.status} ${e.code}`;
|
|
145
|
+
else {
|
|
146
|
+
const o = v(e.status, e.title);
|
|
147
|
+
i = o ? `${e.status} ${o}` : String(e.status);
|
|
148
|
+
}
|
|
149
|
+
return /* @__PURE__ */ s(l.Root, { children: [/* @__PURE__ */ n(l.Trigger, {
|
|
150
|
+
openOnHover: !0,
|
|
151
|
+
delay: 150,
|
|
152
|
+
"aria-label": "Error details",
|
|
153
|
+
className: "outline-pho-brand inline-flex size-4 shrink-0 translate-y-[3px] cursor-help items-center justify-center rounded-full opacity-70 transition-opacity hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-2",
|
|
154
|
+
children: /* @__PURE__ */ n(S, { className: "size-3.5" })
|
|
155
|
+
}), /* @__PURE__ */ n(l.Portal, { children: /* @__PURE__ */ n(l.Positioner, {
|
|
156
|
+
align: "start",
|
|
157
|
+
children: /* @__PURE__ */ s(l.Popup, {
|
|
158
|
+
className: "text-pho-error",
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ s(l.Title, {
|
|
161
|
+
className: "text-pho-error flex items-start gap-1.5",
|
|
162
|
+
children: [/* @__PURE__ */ n("span", {
|
|
163
|
+
"aria-hidden": !0,
|
|
164
|
+
className: "flex h-[1lh] shrink-0 items-center",
|
|
165
|
+
children: /* @__PURE__ */ n(g, { className: "size-4" })
|
|
166
|
+
}), t.title]
|
|
167
|
+
}),
|
|
168
|
+
t.description != null && /* @__PURE__ */ n(l.Description, {
|
|
169
|
+
className: "text-pho-error",
|
|
170
|
+
children: t.description
|
|
171
|
+
}),
|
|
172
|
+
(i != null || r != null) && /* @__PURE__ */ s("div", {
|
|
173
|
+
className: "text-pho-error mt-1 font-mono text-[10px] leading-snug",
|
|
174
|
+
children: [i != null && /* @__PURE__ */ n("p", { children: i }), r != null && /* @__PURE__ */ n(b, {
|
|
175
|
+
requestId: r,
|
|
176
|
+
className: "mt-0"
|
|
177
|
+
})]
|
|
178
|
+
})
|
|
179
|
+
]
|
|
180
|
+
})
|
|
181
|
+
}) })] });
|
|
182
|
+
}
|
|
183
|
+
function b({ requestId: t, className: e }) {
|
|
184
|
+
const [r, i] = L(!1), o = P(null);
|
|
185
|
+
return A(() => () => {
|
|
186
|
+
o.current && clearTimeout(o.current);
|
|
187
|
+
}, []), /* @__PURE__ */ s("span", {
|
|
188
|
+
className: h("mt-1 block font-mono text-[10px] leading-snug", e),
|
|
189
|
+
children: [
|
|
190
|
+
"Request ID:",
|
|
191
|
+
" ",
|
|
192
|
+
/* @__PURE__ */ n("button", {
|
|
193
|
+
type: "button",
|
|
194
|
+
className: "outline-pho-brand inline cursor-pointer underline-offset-2 select-all hover:underline focus-visible:underline focus-visible:outline-2 focus-visible:-outline-offset-1",
|
|
195
|
+
"aria-label": r ? "Request ID copied" : `Copy request ID ${t}`,
|
|
196
|
+
onClick: async () => {
|
|
197
|
+
try {
|
|
198
|
+
await navigator.clipboard.writeText(t);
|
|
199
|
+
} catch {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
i(!0), o.current && clearTimeout(o.current), o.current = setTimeout(() => i(!1), 1500);
|
|
203
|
+
},
|
|
204
|
+
children: t
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ n("output", {
|
|
207
|
+
className: "sr-only",
|
|
208
|
+
"aria-live": "polite",
|
|
209
|
+
children: r ? "Copied" : ""
|
|
210
|
+
})
|
|
211
|
+
]
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
function G({ error: t, title: e, description: r, icon: i, onRetry: o, actions: N, size: w = "base", ...q }) {
|
|
215
|
+
if (t == null && e == null) return null;
|
|
216
|
+
const a = y(t), p = d(r ?? a.description), I = p != null || a.requestId != null ? /* @__PURE__ */ s(c, { children: [p, a.requestId != null && /* @__PURE__ */ n(b, { requestId: a.requestId })] }) : void 0, E = N ?? (o != null || a.documentation != null ? /* @__PURE__ */ s(c, { children: [o != null && /* @__PURE__ */ n(x, {
|
|
217
|
+
size: "sm",
|
|
218
|
+
onClick: o,
|
|
219
|
+
children: F
|
|
220
|
+
}), a.documentation != null && /* @__PURE__ */ n(R, {
|
|
221
|
+
size: "sm",
|
|
222
|
+
variant: "outlined",
|
|
223
|
+
href: a.documentation,
|
|
224
|
+
target: "_blank",
|
|
225
|
+
rel: "noreferrer",
|
|
226
|
+
children: T
|
|
227
|
+
})] }) : void 0);
|
|
228
|
+
return /* @__PURE__ */ n(_, {
|
|
229
|
+
role: "alert",
|
|
230
|
+
size: w,
|
|
231
|
+
icon: i ?? /* @__PURE__ */ n(z, {}),
|
|
232
|
+
title: d(e ?? a.title),
|
|
233
|
+
description: I,
|
|
234
|
+
actions: E,
|
|
235
|
+
...q
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
G.displayName = "ErrorView";
|
|
239
|
+
export {
|
|
240
|
+
y as a,
|
|
241
|
+
m as c,
|
|
242
|
+
u as i,
|
|
243
|
+
D as l,
|
|
244
|
+
G as n,
|
|
245
|
+
v as o,
|
|
246
|
+
j as r,
|
|
247
|
+
$ as s,
|
|
248
|
+
M as t
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
//# sourceMappingURL=error-DR6G2LmG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-DR6G2LmG.js","names":[],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertTriangle.mjs","../../src/components/error/problem.ts","../../src/components/error/error.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.44.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 9v4\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M12 16h.01\", \"key\": \"svg-2\" }]];\nconst IconAlertTriangle = createReactComponent(\"outline\", \"alert-triangle\", \"AlertTriangle\", __iconNode);\n\nexport { __iconNode, IconAlertTriangle as default };\n//# sourceMappingURL=IconAlertTriangle.mjs.map\n","/**\n * Client-side mirror of the `@photon-hq/error` response contract — the\n * RFC 9457 Problem Details body every Photon service returns for 4xx / 5xx.\n * Machine logic branches on `code`; `title` / `detail` / `remediation` are\n * the human-readable copy, already reviewed server-side and safe to render.\n *\n * Fetch layers may also hand us a thin status-only shape when the response\n * was not ok but the body was not a contract problem — `title` + `status`\n * still count so the UI can disclose the HTTP code we already know.\n */\n\nexport interface ProblemRemediation {\n /** What the user can do about it — a full sentence. */\n action?: string;\n /** Docs URL explaining the problem. */\n documentation?: string;\n}\n\nexport interface Problem {\n /** Stable machine-readable key (`RATE_LIMITED`) — the field to branch on. */\n code?: string;\n /** Human summary of the problem type (\"Too Many Requests\"). */\n title: string;\n /** HTTP status (4xx / 5xx). */\n status: number;\n /** Problem type URI (`urn:photon:problem:*` or an https URL). */\n type?: string;\n /** Occurrence-specific human sentence. */\n detail?: string;\n /** Correlation id for support (`X-Request-ID`). */\n requestId?: string;\n remediation?: ProblemRemediation;\n /** RFC 9457 extensions (`issues`, `actualVersion`, …). */\n [extension: string]: unknown;\n}\n\n/** Structural check: `title` + a 4xx/5xx status. `code` is optional. */\nexport function isProblem(value: unknown): value is Problem {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Record<string, unknown>;\n return (\n typeof v.title === \"string\" &&\n typeof v.status === \"number\" &&\n Number.isInteger(v.status) &&\n v.status >= 400 &&\n v.status <= 599 &&\n (v.code === undefined || typeof v.code === \"string\")\n );\n}\n\n/**\n * Find the problem a caught value carries — the value itself, one typed onto\n * an error as a `problem` field (dashboard's `ApiError` shape), or one\n * wrapped in an `Error` `cause` chain (how fetch layers usually rethrow a\n * parsed body). Returns `null` when there is none.\n */\nexport function parseProblem(error: unknown): Problem | null {\n let current: unknown = error;\n for (\n let depth = 0;\n depth < 8 && typeof current === \"object\" && current !== null;\n depth++\n ) {\n if (isProblem(current)) return current;\n const carried = (current as { problem?: unknown }).problem;\n if (isProblem(carried)) return carried;\n current = (current as { cause?: unknown }).cause;\n }\n return null;\n}\n\nexport interface ErrorDescription {\n /** Short name of the failure — the problem `title`, or a generic fallback. */\n title: string;\n /** Sentence(s) to show — `detail` and `remediation.action` joined. */\n description?: string;\n /** Docs URL from `remediation.documentation`. */\n documentation?: string;\n /** Correlation id for support. */\n requestId?: string;\n /** The matched problem, when the input carried one. */\n problem?: Problem;\n}\n\n/**\n * Anything that isn't a problem renders as this — raw `Error` messages are\n * not contract copy and never shown (the same fail-closed stance as the\n * server side of `@photon-hq/error`). Always a full sentence (trailing\n * period).\n */\nexport const GENERIC_ERROR_TITLE = \"Something went wrong.\";\n\n/** Standard reason phrases for statuses we commonly surface without a body. */\nconst HTTP_REASON_PHRASE: Record<number, string> = {\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 408: \"Request Timeout\",\n 409: \"Conflict\",\n 410: \"Gone\",\n 413: \"Payload Too Large\",\n 415: \"Unsupported Media Type\",\n 422: \"Unprocessable Entity\",\n 429: \"Too Many Requests\",\n 500: \"Internal Server Error\",\n 501: \"Not Implemented\",\n 502: \"Bad Gateway\",\n 503: \"Service Unavailable\",\n 504: \"Gateway Timeout\",\n};\n\n/** One-sentence explanations when the server gave a status but no problem copy. */\nconst HTTP_STATUS_EXPLANATION: Record<number, string> = {\n 400: \"The request was malformed or incomplete.\",\n 401: \"You need to sign in again.\",\n 403: \"You don't have permission to do that.\",\n 404: \"The requested resource was not found.\",\n 408: \"The request timed out before the server responded.\",\n 409: \"The request conflicts with the current state.\",\n 410: \"That resource is no longer available.\",\n 413: \"The request was too large for the server to accept.\",\n 415: \"That media type isn't supported.\",\n 422: \"The request was understood but couldn't be processed.\",\n 429: \"Request rate limit exceeded. Wait a moment before trying again.\",\n 500: \"The server hit an unexpected error.\",\n 501: \"The server doesn't support that operation.\",\n 502: \"The gateway got an invalid response from an upstream server.\",\n 503: \"The service is temporarily unavailable.\",\n 504: \"The gateway timed out waiting for an upstream server.\",\n};\n\nfunction hasContractCode(problem: Problem): boolean {\n return typeof problem.code === \"string\" && problem.code !== \"\";\n}\n\n/** Reason phrase for a status — map first, then a non-generic `problem.title`. */\nexport function httpReasonPhrase(\n status: number,\n fallbackTitle?: string,\n): string | undefined {\n if (HTTP_REASON_PHRASE[status]) return HTTP_REASON_PHRASE[status];\n if (\n fallbackTitle &&\n fallbackTitle !== GENERIC_ERROR_TITLE &&\n fallbackTitle !== \"Request failed\"\n ) {\n return fallbackTitle.replace(/\\.$/, \"\");\n }\n return undefined;\n}\n\n/** Human sentence for a bare HTTP status, when the body carried no copy. */\nexport function httpStatusExplanation(status: number): string {\n return (\n HTTP_STATUS_EXPLANATION[status] ??\n \"The request failed with an unexpected status.\"\n );\n}\n\n/**\n * Sentence-case the first character. Server `detail` / `title` sometimes\n * arrive fully lowercase; UI copy always leads with a capital.\n */\nexport function capitalizeFirst(text: string): string {\n if (!text) return text;\n const first = text.charAt(0);\n const upper = first.toUpperCase();\n if (first === upper) return text;\n return upper + text.slice(1);\n}\n\n/**\n * Turn a caught value into displayable copy. `Error` and `ErrorView` call\n * this internally; use it directly for other surfaces (a toast, a banner).\n *\n * Status-only failures (HTTP not ok, but no contract `code` / copy) still\n * keep `problem` so the details panel can show the status. Title becomes the\n * reason phrase (e.g. \"Bad Gateway\"); description is a short explanation —\n * not just the numeric code.\n */\nexport function describeError(error: unknown): ErrorDescription {\n const problem = parseProblem(error);\n if (problem == null) return { title: GENERIC_ERROR_TITLE };\n\n const description =\n [problem.detail, problem.remediation?.action]\n .filter((part): part is string => typeof part === \"string\" && part !== \"\")\n .join(\" \") || undefined;\n\n if (!hasContractCode(problem) && description == null) {\n const reason = httpReasonPhrase(problem.status, problem.title);\n return {\n title: capitalizeFirst(reason ?? GENERIC_ERROR_TITLE),\n description: httpStatusExplanation(problem.status),\n requestId: problem.requestId,\n problem,\n };\n }\n\n return {\n title: capitalizeFirst(problem.title || GENERIC_ERROR_TITLE),\n description: description ? capitalizeFirst(description) : undefined,\n documentation: problem.remediation?.documentation,\n requestId: problem.requestId,\n problem,\n };\n}\n","import {\n useEffect,\n useRef,\n useState,\n type ComponentProps,\n type ReactNode,\n} from \"react\";\nimport {\n IconAlertCircleFilled,\n IconAlertTriangle,\n IconInfoCircle,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button, ButtonLink } from \"../button/button\";\nimport { Popover } from \"../popover/popover\";\nimport { StatusView, type StatusViewSize } from \"../status-view/status-view\";\nimport {\n capitalizeFirst,\n describeError,\n httpReasonPhrase,\n type ErrorDescription,\n} from \"./problem\";\n\n/** Capitalize string copy; leave custom ReactNode overrides alone. */\nfunction displayCopy(value: ReactNode): ReactNode {\n return typeof value === \"string\" ? capitalizeFirst(value) : value;\n}\n\n/**\n * Design notes:\n * - ONE input: `error` is the caught value, whatever it is — a Problem\n * Details body from `@photon-hq/error`, an `Error` carrying one as\n * `cause`, or something unknown. The component derives its copy via\n * `describeError`; unknowns fall back to a generic line rather than\n * leaking raw messages.\n * - TWO presentations, one per altitude: `Error` is the inline line for\n * forms, cards, and action rows; `ErrorView` is the region / page state\n * built on StatusView (same `sm` / `base` size axis).\n * - Both render `null` when there is nothing to show, so they can sit\n * unconditionally in JSX (`<Error error={mutation.error} />`).\n * - Client-side *validation* is not this component's job — that belongs to\n * `Field.Error`, wired to control validity.\n */\n\nconst DOC_LINK_LABEL = \"Learn more\";\nconst RETRY_LABEL = \"Try again\";\n\ninterface ErrorBaseProps {\n /** The caught value — a problem body, an `Error` wrapping one, or unknown. */\n error?: unknown;\n /** Override the derived message. */\n children?: ReactNode;\n}\n\nexport interface ErrorProps\n extends ErrorBaseProps, Omit<ComponentProps<\"div\">, keyof ErrorBaseProps> {}\n\n/**\n * Error — one line of red ink naming a server failure (4xx / 5xx), placed\n * inline: under a form, in a card, beside the action that failed. Give it the\n * caught value and it renders the problem's `detail` (falling back to `title`,\n * then to a generic line), plus a docs link when the problem carries one.\n * Renders nothing while `error` is nullish, so it can stay mounted.\n *\n * For a region or page that failed to load, use {@link ErrorView}.\n */\nexport function Error({ error, children, className, ...props }: ErrorProps) {\n if (error == null && children == null) return null;\n const copy = describeError(error);\n return (\n <div\n role=\"alert\"\n className={cn(\n \"text-pho-error flex min-w-0 items-start gap-1.5 text-base\",\n className,\n )}\n {...props}\n >\n <span aria-hidden className=\"flex h-[1lh] shrink-0 items-center\">\n <IconAlertCircleFilled className=\"size-4\" />\n </span>\n <span className=\"min-w-0\">\n {displayCopy(children ?? copy.description ?? copy.title)}\n {copy.documentation != null && (\n <>\n {\" \"}\n <a\n href={copy.documentation}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"font-medium underline underline-offset-2\"\n >\n {DOC_LINK_LABEL}\n </a>\n </>\n )}\n {/* Trailing whitespace collapses when the details render null. */}{\" \"}\n <ErrorDetails copy={copy} />\n </span>\n </div>\n );\n}\n\nError.displayName = \"Error\";\n\n/**\n * Hover / focus disclosure on the inline line — the request's fuller story:\n * problem `title` (with the same alert icon + `text-pho-error` ink as the\n * inline line), the untruncated description, then `status` + `code` and the\n * copyable request id grouped below for a support handoff. Renders only when\n * the caught value actually carried a problem (or at least a request id); a\n * generic unknown has nothing more to disclose. Built on `Popover` rather\n * than `Tooltip` because the panel holds an interactive control (the copy\n * button) — `openOnHover` keeps the tooltip-like gesture.\n */\nfunction ErrorDetails({ copy }: { copy: ErrorDescription }) {\n const { problem, requestId } = copy;\n if (problem == null && requestId == null) return null;\n\n // Contract problems show `status CODE`; status-only shows `status Reason`.\n let statusLine: string | null = null;\n if (problem != null) {\n if (problem.code) {\n statusLine = `${problem.status} ${problem.code}`;\n } else {\n const reason = httpReasonPhrase(problem.status, problem.title);\n statusLine = reason\n ? `${problem.status} ${reason}`\n : String(problem.status);\n }\n }\n\n return (\n <Popover.Root>\n <Popover.Trigger\n openOnHover\n delay={150}\n aria-label=\"Error details\"\n className=\"outline-pho-brand inline-flex size-4 shrink-0 translate-y-[3px] cursor-help items-center justify-center rounded-full opacity-70 transition-opacity hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-2\"\n >\n <IconInfoCircle className=\"size-3.5\" />\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Positioner align=\"start\">\n <Popover.Popup className=\"text-pho-error\">\n <Popover.Title className=\"text-pho-error flex items-start gap-1.5\">\n <span aria-hidden className=\"flex h-[1lh] shrink-0 items-center\">\n <IconAlertCircleFilled className=\"size-4\" />\n </span>\n {copy.title}\n </Popover.Title>\n {copy.description != null && (\n <Popover.Description className=\"text-pho-error\">\n {copy.description}\n </Popover.Description>\n )}\n {(statusLine != null || requestId != null) && (\n <div className=\"text-pho-error mt-1 font-mono text-[10px] leading-snug\">\n {statusLine != null && <p>{statusLine}</p>}\n {requestId != null && (\n <RequestId requestId={requestId} className=\"mt-0\" />\n )}\n </div>\n )}\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n\n/** Request-id footnote — click copies the id for support handoff. */\nfunction RequestId({\n requestId,\n className,\n}: {\n requestId: string;\n className?: string;\n}) {\n const [copied, setCopied] = useState(false);\n const copiedTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(\n () => () => {\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n },\n [],\n );\n\n return (\n <span\n className={cn(\"mt-1 block font-mono text-[10px] leading-snug\", className)}\n >\n Request ID:{\" \"}\n <button\n type=\"button\"\n className=\"outline-pho-brand inline cursor-pointer underline-offset-2 select-all hover:underline focus-visible:underline focus-visible:outline-2 focus-visible:-outline-offset-1\"\n aria-label={\n copied ? \"Request ID copied\" : `Copy request ID ${requestId}`\n }\n onClick={async () => {\n try {\n await navigator.clipboard.writeText(requestId);\n } catch {\n return;\n }\n setCopied(true);\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n copiedTimer.current = setTimeout(() => setCopied(false), 1500);\n }}\n >\n {requestId}\n </button>\n <output className=\"sr-only\" aria-live=\"polite\">\n {copied ? \"Copied\" : \"\"}\n </output>\n </span>\n );\n}\n\ninterface ErrorViewBaseProps {\n /** The caught value — a problem body, an `Error` wrapping one, or unknown. */\n error?: unknown;\n /** Override the derived title. */\n title?: ReactNode;\n /** Override the derived description. */\n description?: ReactNode;\n /** Override the warning glyph. */\n icon?: ReactNode;\n /** Offer a retry — renders a \"Try again\" button. */\n onRetry?: () => void;\n /** Replace the built-in action row entirely. */\n actions?: ReactNode;\n /** Size variant — StatusView's axis. @default \"base\" */\n size?: StatusViewSize;\n}\n\nexport interface ErrorViewProps\n extends\n ErrorViewBaseProps,\n Omit<ComponentProps<\"div\">, keyof ErrorViewBaseProps | \"children\"> {}\n\n/**\n * ErrorView — the failed state of a region or page, built on StatusView:\n * warning icon over the problem's `title`, its `detail` and remediation\n * below, an action row (`onRetry` and the problem's docs link), and the\n * request id as a footnote for support. Announces via `role=\"alert\"`.\n *\n * Use `size=\"sm\"` inside cards and panels, the default `base` for whole\n * pages. Renders nothing while `error` is nullish (unless given a static\n * `title`), so it can sit unconditionally next to a query.\n */\nexport function ErrorView({\n error,\n title,\n description,\n icon,\n onRetry,\n actions,\n size = \"base\",\n ...props\n}: ErrorViewProps) {\n if (error == null && title == null) return null;\n const copy = describeError(error);\n\n const resolvedDescription = displayCopy(description ?? copy.description);\n const body =\n resolvedDescription != null || copy.requestId != null ? (\n <>\n {resolvedDescription}\n {copy.requestId != null && <RequestId requestId={copy.requestId} />}\n </>\n ) : undefined;\n\n const resolvedActions =\n actions ??\n (onRetry != null || copy.documentation != null ? (\n <>\n {onRetry != null && (\n <Button size=\"sm\" onClick={onRetry}>\n {RETRY_LABEL}\n </Button>\n )}\n {copy.documentation != null && (\n <ButtonLink\n size=\"sm\"\n variant=\"outlined\"\n href={copy.documentation}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {DOC_LINK_LABEL}\n </ButtonLink>\n )}\n </>\n ) : undefined);\n\n return (\n <StatusView\n role=\"alert\"\n size={size}\n icon={icon ?? <IconAlertTriangle />}\n title={displayCopy(title ?? copy.title)}\n description={body}\n actions={resolvedActions}\n {...props}\n />\n );\n}\n\nErrorView.displayName = \"ErrorView\";\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as r } from "./cn-DTiB6ek_.js";
|
|
3
|
-
import { t as
|
|
4
|
-
import {
|
|
3
|
+
import { t as f } from "./createReactComponent-BqCmnqfX.js";
|
|
4
|
+
import { t as A } from "./IconAlertCircleFilled-VxKU8TYK.js";
|
|
5
|
+
import { useState as S } from "react";
|
|
5
6
|
import { jsx as e, jsxs as s } from "react/jsx-runtime";
|
|
6
|
-
import { Field as
|
|
7
|
-
var
|
|
7
|
+
import { Field as i } from "@base-ui/react/field";
|
|
8
|
+
var D = [
|
|
8
9
|
["path", {
|
|
9
10
|
d: "M10.585 10.587a2 2 0 0 0 2.829 2.828",
|
|
10
11
|
key: "svg-0"
|
|
@@ -17,16 +18,13 @@ var S = [
|
|
|
17
18
|
d: "M3 3l18 18",
|
|
18
19
|
key: "svg-2"
|
|
19
20
|
}]
|
|
20
|
-
],
|
|
21
|
+
], R = f("outline", "eye-off", "EyeOff", D), k = [["path", {
|
|
21
22
|
d: "M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0",
|
|
22
23
|
key: "svg-0"
|
|
23
24
|
}], ["path", {
|
|
24
25
|
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",
|
|
25
26
|
key: "svg-1"
|
|
26
|
-
}]],
|
|
27
|
-
d: "M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm.01 13l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z",
|
|
28
|
-
key: "svg-0"
|
|
29
|
-
}]], L = n("filled", "alert-circle-filled", "AlertCircleFilled", R), M = {
|
|
27
|
+
}]], C = f("outline", "eye", "Eye", k), L = {
|
|
30
28
|
sm: "px-2.5 py-1.5 text-md md:text-base",
|
|
31
29
|
md: "px-2.5 py-1.5 text-md",
|
|
32
30
|
lg: "px-3 py-2 text-md"
|
|
@@ -34,34 +32,34 @@ var S = [
|
|
|
34
32
|
sm: "pl-8.5",
|
|
35
33
|
md: "pl-9.5",
|
|
36
34
|
lg: "pl-10"
|
|
37
|
-
},
|
|
35
|
+
}, M = {
|
|
38
36
|
sm: "left-3 size-4",
|
|
39
37
|
md: "left-3 size-5",
|
|
40
38
|
lg: "left-3.5 size-5"
|
|
41
|
-
},
|
|
39
|
+
}, P = {
|
|
42
40
|
sm: "rounded-base",
|
|
43
41
|
md: "rounded-base",
|
|
44
42
|
lg: "squircle rounded-base"
|
|
45
|
-
},
|
|
43
|
+
}, T = {
|
|
46
44
|
sm: "",
|
|
47
45
|
md: "",
|
|
48
46
|
lg: r("isolate before:pointer-events-none before:absolute before:-z-10 before:content-['']", "before:bg-pho-primary before:inset-px before:rounded-[calc(var(--radius-base)-1px)]", "data-[invalid]:before:inset-[1.5px] data-[invalid]:before:rounded-[calc(var(--radius-base)-1.5px)]", "has-[input:focus-visible]:before:inset-0.5 has-[input:focus-visible]:before:rounded-[calc(var(--radius-base)-2px)]", "before:transition-[inset,border-radius] before:duration-100 before:ease-linear")
|
|
49
|
-
},
|
|
47
|
+
}, Z = {
|
|
50
48
|
sm: "autofill:rounded-[calc(var(--radius-base)-2px)]",
|
|
51
49
|
md: "autofill:rounded-[calc(var(--radius-base)-2px)]",
|
|
52
50
|
lg: "autofill:rounded-[calc(var(--radius-base)-2px)]"
|
|
53
51
|
};
|
|
54
|
-
function
|
|
55
|
-
const [
|
|
56
|
-
return /* @__PURE__ */ s(
|
|
52
|
+
function j({ label: l, hint: d, size: a = "md", invalid: t, icon: n, labelTrailing: m, disabled: b, required: c, type: p = "text", className: v, wrapperClassName: h, id: x, ref: g, ...y }) {
|
|
53
|
+
const [u, N] = S(!1), o = p === "password", I = o && u ? "text" : p, _ = !!n, E = o || t;
|
|
54
|
+
return /* @__PURE__ */ s(i.Root, {
|
|
57
55
|
disabled: b,
|
|
58
56
|
className: "group/field flex w-full flex-col gap-1.5",
|
|
59
57
|
children: [
|
|
60
|
-
|
|
58
|
+
l && /* @__PURE__ */ s("div", {
|
|
61
59
|
className: "flex items-center justify-between gap-2",
|
|
62
|
-
children: [/* @__PURE__ */ s(
|
|
60
|
+
children: [/* @__PURE__ */ s(i.Label, {
|
|
63
61
|
className: "text-pho-secondary flex cursor-default items-center gap-0.5 text-base font-medium",
|
|
64
|
-
children: [
|
|
62
|
+
children: [l, c && /* @__PURE__ */ e("span", {
|
|
65
63
|
className: "text-pho-brand",
|
|
66
64
|
children: "*"
|
|
67
65
|
})]
|
|
@@ -69,38 +67,38 @@ function Z({ label: d, hint: c, size: a = "md", invalid: t, icon: i, labelTraili
|
|
|
69
67
|
}),
|
|
70
68
|
/* @__PURE__ */ s("div", {
|
|
71
69
|
"data-invalid": t || void 0,
|
|
72
|
-
className: r("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",
|
|
70
|
+
className: r("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", P[a], T[a], "has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2", "data-[invalid]:ring-pho-error-subtle data-[invalid]:has-[input:focus-visible]:ring-pho-error data-[invalid]:ring-[1.5px]", "group-data-[disabled]/field:cursor-not-allowed group-data-[disabled]/field:opacity-50", h),
|
|
73
71
|
children: [
|
|
74
|
-
|
|
75
|
-
/* @__PURE__ */ e(
|
|
72
|
+
n && /* @__PURE__ */ e(n, { className: r("text-pho-secondary pointer-events-none absolute", M[a]) }),
|
|
73
|
+
/* @__PURE__ */ e(i.Control, {
|
|
76
74
|
ref: g,
|
|
77
75
|
id: x,
|
|
78
76
|
type: I,
|
|
79
|
-
required:
|
|
77
|
+
required: c,
|
|
80
78
|
...y,
|
|
81
|
-
className: r("text-pho-primary placeholder:text-pho-placeholder m-0 w-full bg-transparent outline-none disabled:cursor-not-allowed",
|
|
79
|
+
className: r("text-pho-primary placeholder:text-pho-placeholder m-0 w-full bg-transparent outline-none disabled:cursor-not-allowed", L[a], Z[a], _ && O[a], E && "pr-8.5", v)
|
|
82
80
|
}),
|
|
83
|
-
t && !o && /* @__PURE__ */ e(
|
|
81
|
+
t && !o && /* @__PURE__ */ e(A, { className: "text-pho-error pointer-events-none absolute right-3 size-4" }),
|
|
84
82
|
o && /* @__PURE__ */ e("button", {
|
|
85
83
|
type: "button",
|
|
86
84
|
tabIndex: -1,
|
|
87
85
|
"aria-label": "Toggle password visibility",
|
|
88
86
|
onClick: () => N((w) => !w),
|
|
89
87
|
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",
|
|
90
|
-
children:
|
|
88
|
+
children: u ? /* @__PURE__ */ e(R, { className: "size-4" }) : /* @__PURE__ */ e(C, { className: "size-4" })
|
|
91
89
|
})
|
|
92
90
|
]
|
|
93
91
|
}),
|
|
94
|
-
|
|
92
|
+
d && /* @__PURE__ */ e(i.Description, {
|
|
95
93
|
className: r("text-pho-description text-base", t && "text-pho-error"),
|
|
96
|
-
children:
|
|
94
|
+
children: d
|
|
97
95
|
})
|
|
98
96
|
]
|
|
99
97
|
});
|
|
100
98
|
}
|
|
101
|
-
|
|
99
|
+
j.displayName = "Input";
|
|
102
100
|
export {
|
|
103
|
-
|
|
101
|
+
j as t
|
|
104
102
|
};
|
|
105
103
|
|
|
106
|
-
//# sourceMappingURL=input-
|
|
104
|
+
//# sourceMappingURL=input-D3XQcC4J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-D3XQcC4J.js","names":["__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconEyeOff.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconEye.mjs","../../src/components/input/input.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.44.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.44.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 /** 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 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\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\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 </Field.Root>\n );\n}\n\nInput.displayName = \"Input\";\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|