@photon-ai/pho-ui 2.12.0 → 2.14.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.
Files changed (105) hide show
  1. package/dist/chunks/IconChevronRight-CzoJnYNI.js +11 -0
  2. package/dist/chunks/IconChevronRight-CzoJnYNI.js.map +1 -0
  3. package/dist/chunks/badge-DlLJPLeZ.js +78 -0
  4. package/dist/chunks/badge-DlLJPLeZ.js.map +1 -0
  5. package/dist/chunks/bar-chart-BJfr3eyd.js +190 -0
  6. package/dist/chunks/bar-chart-BJfr3eyd.js.map +1 -0
  7. package/dist/chunks/{basic-page-CJwG4I83.js → basic-page-CdmVeL_Z.js} +433 -436
  8. package/dist/chunks/basic-page-CdmVeL_Z.js.map +1 -0
  9. package/dist/chunks/code-block-CdozzaHM.js +139 -0
  10. package/dist/chunks/code-block-CdozzaHM.js.map +1 -0
  11. package/dist/chunks/combobox-D4LiGJB2.js +136 -0
  12. package/dist/chunks/combobox-D4LiGJB2.js.map +1 -0
  13. package/dist/chunks/command-Ck8IAgV7.js +192 -0
  14. package/dist/chunks/command-Ck8IAgV7.js.map +1 -0
  15. package/dist/chunks/copy-button-B_B15mEi.js +56 -0
  16. package/dist/chunks/copy-button-B_B15mEi.js.map +1 -0
  17. package/dist/chunks/description-list-C-mwe4ki.js +59 -0
  18. package/dist/chunks/description-list-C-mwe4ki.js.map +1 -0
  19. package/dist/chunks/filter-bar-Cjjq38xo.js +259 -0
  20. package/dist/chunks/filter-bar-Cjjq38xo.js.map +1 -0
  21. package/dist/chunks/legend-C0mU7dqd.js +60 -0
  22. package/dist/chunks/legend-C0mU7dqd.js.map +1 -0
  23. package/dist/chunks/line-chart-CUR3AxrR.js +453 -0
  24. package/dist/chunks/line-chart-CUR3AxrR.js.map +1 -0
  25. package/dist/chunks/log-list-0AXnjFrk.js +244 -0
  26. package/dist/chunks/log-list-0AXnjFrk.js.map +1 -0
  27. package/dist/chunks/stat-hnNqjWVG.js +85 -0
  28. package/dist/chunks/stat-hnNqjWVG.js.map +1 -0
  29. package/dist/chunks/toggle-o84tawXy.js +33 -0
  30. package/dist/chunks/toggle-o84tawXy.js.map +1 -0
  31. package/dist/chunks/tooltip-BTF7GChl.js +32 -0
  32. package/dist/chunks/tooltip-BTF7GChl.js.map +1 -0
  33. package/dist/chunks/trace-CbH0IohX.js +314 -0
  34. package/dist/chunks/trace-CbH0IohX.js.map +1 -0
  35. package/dist/chunks/use-copy-D6JwKUll.js +25 -0
  36. package/dist/chunks/use-copy-D6JwKUll.js.map +1 -0
  37. package/dist/chunks/use-measure-CMVgLouO.js +616 -0
  38. package/dist/chunks/use-measure-CMVgLouO.js.map +1 -0
  39. package/dist/components/badge.js +5 -75
  40. package/dist/components/bar-chart.js +5 -0
  41. package/dist/components/chart.js +8 -0
  42. package/dist/components/code-block.js +6 -0
  43. package/dist/components/combobox.js +1 -1
  44. package/dist/components/command.js +3 -189
  45. package/dist/components/copy-button.js +6 -0
  46. package/dist/components/description-list.js +5 -0
  47. package/dist/components/filter-bar.js +8 -0
  48. package/dist/components/line-chart.js +5 -0
  49. package/dist/components/log-list.js +8 -0
  50. package/dist/components/phone-input.js +1 -1
  51. package/dist/components/stat.js +6 -0
  52. package/dist/components/toggle.js +3 -30
  53. package/dist/components/tooltip.js +2 -29
  54. package/dist/components/trace.js +9 -0
  55. package/dist/index.js +132 -93
  56. package/dist/primitives.js +2 -2
  57. package/dist/sections/basic-page.js +17 -17
  58. package/dist/src/components/accordion/index.d.ts +1 -1
  59. package/dist/src/components/bar-chart/bar-chart.d.ts +9 -0
  60. package/dist/src/components/bar-chart/index.d.ts +2 -0
  61. package/dist/src/components/chart/axes.d.ts +22 -0
  62. package/dist/src/components/chart/color.d.ts +10 -0
  63. package/dist/src/components/chart/format.d.ts +25 -0
  64. package/dist/src/components/chart/index.d.ts +8 -0
  65. package/dist/src/components/chart/legend.d.ts +26 -0
  66. package/dist/src/components/chart/scale.d.ts +34 -0
  67. package/dist/src/components/chart/shell.d.ts +42 -0
  68. package/dist/src/components/chart/tooltip.d.ts +30 -0
  69. package/dist/src/components/chart/types.d.ts +76 -0
  70. package/dist/src/components/chart/use-measure.d.ts +8 -0
  71. package/dist/src/components/code-block/code-block.d.ts +43 -0
  72. package/dist/src/components/code-block/index.d.ts +2 -0
  73. package/dist/src/components/code-block/tokenize-json.d.ts +12 -0
  74. package/dist/src/components/combobox/combobox.d.ts +30 -4
  75. package/dist/src/components/combobox/index.d.ts +1 -1
  76. package/dist/src/components/copy-button/copy-button.d.ts +49 -0
  77. package/dist/src/components/copy-button/index.d.ts +1 -0
  78. package/dist/src/components/description-list/description-list.d.ts +60 -0
  79. package/dist/src/components/description-list/index.d.ts +1 -0
  80. package/dist/src/components/filter-bar/filter-bar.d.ts +101 -0
  81. package/dist/src/components/filter-bar/index.d.ts +1 -0
  82. package/dist/src/components/line-chart/index.d.ts +2 -0
  83. package/dist/src/components/line-chart/line-chart.d.ts +11 -0
  84. package/dist/src/components/log-list/index.d.ts +1 -0
  85. package/dist/src/components/log-list/log-list.d.ts +136 -0
  86. package/dist/src/components/stat/index.d.ts +1 -0
  87. package/dist/src/components/stat/stat.d.ts +61 -0
  88. package/dist/src/components/toggle/toggle.d.ts +5 -1
  89. package/dist/src/components/trace/index.d.ts +2 -0
  90. package/dist/src/components/trace/layout.d.ts +48 -0
  91. package/dist/src/components/trace/trace.d.ts +53 -0
  92. package/dist/src/index.d.ts +10 -0
  93. package/dist/src/sections/basic-page/basic-page.d.ts +3 -3
  94. package/dist/src/utils/index.d.ts +1 -0
  95. package/dist/src/utils/use-copy.d.ts +14 -0
  96. package/dist/utils.js +6 -3
  97. package/package.json +47 -1
  98. package/src/styles/theme.css +81 -0
  99. package/dist/chunks/basic-page-CJwG4I83.js.map +0 -1
  100. package/dist/chunks/combobox-Dj5m_dDd.js +0 -117
  101. package/dist/chunks/combobox-Dj5m_dDd.js.map +0 -1
  102. package/dist/components/badge.js.map +0 -1
  103. package/dist/components/command.js.map +0 -1
  104. package/dist/components/toggle.js.map +0 -1
  105. package/dist/components/tooltip.js.map +0 -1
@@ -0,0 +1,244 @@
1
+ "use client";
2
+ import { t as a } from "./cn-ChIgwEl3.js";
3
+ import { n as k } from "./link-provider-DXzDQ08N.js";
4
+ import { n as j } from "./use-copy-D6JwKUll.js";
5
+ import { n as O } from "./spinner-BzLUo4Xk.js";
6
+ import { a as A } from "./button-CdqS_t5a.js";
7
+ import { i as D } from "./status-view-C8tabjDu.js";
8
+ import { t as g } from "./skeleton-DwjSl4vC.js";
9
+ import { r as E } from "./badge-DlLJPLeZ.js";
10
+ import { t as h } from "./tooltip-BTF7GChl.js";
11
+ import { useEffect as T, useId as B, useRef as N } from "react";
12
+ import { Fragment as W, jsx as t, jsxs as v } from "react/jsx-runtime";
13
+ import { useRender as z } from "@base-ui/react/use-render";
14
+ var F = "rounded-base border border-pho-secondary bg-pho-primary divide-y divide-pho-secondary", P = 12, U = 5;
15
+ function G(e, r = P, n = U) {
16
+ return e.length <= r + n + 1 ? e : `${e.slice(0, r)}…${e.slice(-n)}`;
17
+ }
18
+ var q = /* @__PURE__ */ new Set([
19
+ "success",
20
+ "succeeded",
21
+ "successful",
22
+ "delivered",
23
+ "ok",
24
+ "sent",
25
+ "received",
26
+ "completed",
27
+ "complete",
28
+ "done",
29
+ "active"
30
+ ]), H = /* @__PURE__ */ new Set([
31
+ "failed",
32
+ "failure",
33
+ "error",
34
+ "errored",
35
+ "rejected",
36
+ "undelivered",
37
+ "timeout",
38
+ "timed_out",
39
+ "timed out",
40
+ "canceled",
41
+ "cancelled"
42
+ ]), V = /* @__PURE__ */ new Set([
43
+ "pending",
44
+ "queued",
45
+ "retrying",
46
+ "processing",
47
+ "sending",
48
+ "in_progress",
49
+ "in progress",
50
+ "scheduled",
51
+ "waiting"
52
+ ]);
53
+ function S(e) {
54
+ if (typeof e == "number")
55
+ return e < 300 ? "success" : e < 400 ? "gray" : e < 500 ? "warning" : "error";
56
+ const r = e.trim().toLowerCase();
57
+ return /^\d{3}$/.test(r) ? S(Number(r)) : q.has(r) ? "success" : H.has(r) ? "error" : V.has(r) ? "warning" : "gray";
58
+ }
59
+ function J(e) {
60
+ if (typeof e == "number") return String(e);
61
+ const r = e.trim().replace(/_/g, " ");
62
+ return r.charAt(0).toUpperCase() + r.slice(1);
63
+ }
64
+ function K({ value: e, label: r, size: n = "sm", className: o, ...l }) {
65
+ return /* @__PURE__ */ t(E, {
66
+ color: S(e),
67
+ contrast: "low",
68
+ size: n,
69
+ className: a("tabular-nums", o),
70
+ ...l,
71
+ children: r ?? J(e)
72
+ });
73
+ }
74
+ function R({ className: e, ...r }) {
75
+ return /* @__PURE__ */ t("span", {
76
+ className: a("bg-pho-secondary text-pho-secondary inline-flex h-5 min-w-12 shrink-0 items-center justify-center rounded-sm px-1.5 font-mono text-xs font-medium whitespace-nowrap", e),
77
+ ...r
78
+ });
79
+ }
80
+ function Q({ id: e, cellId: r }) {
81
+ const { copied: n, copy: o } = j();
82
+ return /* @__PURE__ */ v(h.Root, { children: [
83
+ /* @__PURE__ */ t(h.Trigger, {
84
+ id: r,
85
+ "aria-label": n ? `${e} copied` : `Copy ${e}`,
86
+ "data-copied": n || void 0,
87
+ onClick: () => {
88
+ o(e);
89
+ },
90
+ className: a("text-pho-secondary outline-pho-brand hover:text-pho-primary relative z-10 -mx-1 w-[calc(18ch+0.5rem)] shrink-0 cursor-pointer truncate rounded-sm px-1 py-0.5 text-left font-mono text-xs transition-colors duration-100 ease-linear focus-visible:outline-2", "data-[copied]:text-pho-success"),
91
+ children: n ? "Copied" : G(e)
92
+ }),
93
+ /* @__PURE__ */ t("output", {
94
+ className: "sr-only",
95
+ "aria-live": "polite",
96
+ children: n ? "Copied" : ""
97
+ }),
98
+ /* @__PURE__ */ t(h.Portal, { children: /* @__PURE__ */ t(h.Positioner, { children: /* @__PURE__ */ t(h.Popup, {
99
+ className: "font-mono",
100
+ children: e
101
+ }) }) })
102
+ ] });
103
+ }
104
+ function X({ id: e, status: r, method: n, label: o, code: l, description: x, duration: d, time: u, children: m, href: i, onClick: c, render: p, current: f, className: I, ...C }) {
105
+ const L = k(), y = B(), b = i != null || c != null || p != null, s = {
106
+ id: `${y}-id`,
107
+ status: `${y}-status`,
108
+ method: `${y}-method`,
109
+ meta: `${y}-meta`
110
+ }, w = m != null || d != null || u != null, _ = [
111
+ e != null && s.id,
112
+ r != null && s.status,
113
+ n != null && s.method,
114
+ w && s.meta
115
+ ].filter(Boolean).join(" "), $ = z({
116
+ render: p ?? (i != null ? /* @__PURE__ */ t(L, { href: i }) : void 0),
117
+ defaultTagName: i != null ? "a" : c != null ? "button" : "span",
118
+ props: {
119
+ className: a("text-pho-primary block min-w-0 max-w-full truncate text-left text-base font-medium outline-none", l && "font-mono text-xs", b && "cursor-pointer after:absolute after:inset-0 after:content-['']"),
120
+ onClick: c,
121
+ type: p == null && i == null && c != null ? "button" : void 0,
122
+ "aria-current": f ? "page" : void 0,
123
+ "aria-describedby": _ || void 0,
124
+ "data-log-primary": "",
125
+ children: o
126
+ }
127
+ });
128
+ return /* @__PURE__ */ v("div", {
129
+ "data-log-row": "",
130
+ "data-current": f || void 0,
131
+ className: a("relative flex min-h-12 min-w-0 items-center gap-3 px-5 py-2.5", b && "hover:bg-pho-primary-hover outline-pho-brand transition-colors has-[[data-log-primary]:focus-visible]:outline-2 has-[[data-log-primary]:focus-visible]:-outline-offset-2", f && "bg-pho-primary-hover", "first:rounded-t-[calc(var(--radius-base)-1px)] last:rounded-b-[calc(var(--radius-base)-1px)]", I),
132
+ ...C,
133
+ children: [
134
+ e != null ? /* @__PURE__ */ t(Q, {
135
+ id: e,
136
+ cellId: s.id
137
+ }) : null,
138
+ r != null ? /* @__PURE__ */ t("span", {
139
+ id: s.status,
140
+ className: "flex shrink-0 items-center",
141
+ children: r
142
+ }) : null,
143
+ n != null ? /* @__PURE__ */ t(R, {
144
+ id: s.method,
145
+ children: n
146
+ }) : null,
147
+ /* @__PURE__ */ v("div", {
148
+ "data-log-primary-cell": "",
149
+ className: "min-w-0 flex-1",
150
+ children: [$, x != null ? /* @__PURE__ */ t("p", {
151
+ className: "text-pho-description truncate text-xs",
152
+ children: x
153
+ }) : null]
154
+ }),
155
+ w ? /* @__PURE__ */ v("div", {
156
+ id: s.meta,
157
+ className: "text-pho-description ml-auto flex shrink-0 items-center gap-3 text-xs whitespace-nowrap tabular-nums",
158
+ children: [
159
+ m,
160
+ d != null ? /* @__PURE__ */ t("span", { children: d }) : null,
161
+ u != null ? /* @__PURE__ */ t("span", { children: u }) : null
162
+ ]
163
+ }) : null
164
+ ]
165
+ });
166
+ }
167
+ function Y({ title: e = "Nothing here yet.", description: r, children: n, className: o, ...l }) {
168
+ return /* @__PURE__ */ t("div", {
169
+ className: a("flex justify-center", o),
170
+ ...l,
171
+ children: /* @__PURE__ */ t(D, {
172
+ size: "sm",
173
+ title: e,
174
+ description: r,
175
+ actions: n
176
+ })
177
+ });
178
+ }
179
+ function Z({ rows: e = 5 }) {
180
+ return /* @__PURE__ */ t(W, { children: Array.from({ length: e }, (r, n) => /* @__PURE__ */ v("div", {
181
+ "aria-hidden": !0,
182
+ className: "flex min-h-12 items-center gap-3 px-5 py-2.5",
183
+ children: [
184
+ /* @__PURE__ */ t(g, { className: "h-3.5 w-32" }),
185
+ /* @__PURE__ */ t(g, { className: "h-5 w-12 rounded-full" }),
186
+ /* @__PURE__ */ t(g, { className: "h-3.5 w-48" }),
187
+ /* @__PURE__ */ t(g, { className: "ml-auto h-3.5 w-16" })
188
+ ]
189
+ }, n)) });
190
+ }
191
+ function M({ onLoadMore: e, loading: r, hasMore: n = !0, rootMargin: o = "200px", label: l = "Load more", className: x, ...d }) {
192
+ const u = N(null), m = N(e);
193
+ return m.current = e, T(() => {
194
+ const i = u.current;
195
+ if (!n || r || i == null || typeof IntersectionObserver > "u") return;
196
+ const c = new IntersectionObserver((p) => {
197
+ p.some((f) => f.isIntersecting) && m.current();
198
+ }, { rootMargin: o });
199
+ return c.observe(i), () => c.disconnect();
200
+ }, [
201
+ n,
202
+ r,
203
+ o
204
+ ]), n ? /* @__PURE__ */ t("div", {
205
+ ref: u,
206
+ "data-log-load-more": "",
207
+ "aria-busy": r || void 0,
208
+ className: a("flex min-h-12 items-center justify-center px-5 py-2", x),
209
+ ...d,
210
+ children: r ? /* @__PURE__ */ t(O, {
211
+ "aria-label": "Loading more",
212
+ className: "text-pho-secondary"
213
+ }) : /* @__PURE__ */ t(A, {
214
+ variant: "ghost",
215
+ size: "sm",
216
+ onClick: () => e(),
217
+ children: l
218
+ })
219
+ }) : null;
220
+ }
221
+ function ee({ className: e, ...r }) {
222
+ return /* @__PURE__ */ t("div", {
223
+ "data-log-list": "",
224
+ className: a(F, "min-w-0", e),
225
+ ...r
226
+ });
227
+ }
228
+ var pe = {
229
+ Root: ee,
230
+ Row: X,
231
+ Status: K,
232
+ Method: R,
233
+ Empty: Y,
234
+ Loading: Z,
235
+ LoadMore: M
236
+ };
237
+ export {
238
+ G as i,
239
+ S as n,
240
+ J as r,
241
+ pe as t
242
+ };
243
+
244
+ //# sourceMappingURL=log-list-0AXnjFrk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-list-0AXnjFrk.js","names":[],"sources":["../../src/components/log-list/log-list.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useRef,\n type ComponentProps,\n type MouseEvent,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { Badge, type BadgeColor, type BadgeSize } from \"../badge\";\nimport { Button } from \"../button\";\nimport { Skeleton } from \"../skeleton\";\nimport { Spinner } from \"../spinner\";\nimport { StatusView } from \"../status-view\";\nimport { Tooltip } from \"../tooltip\";\nimport { cn } from \"../../utils/cn\";\nimport { useCopy } from \"../../utils/use-copy\";\nimport { useLinkComponent } from \"../../utils/link-provider\";\n\n/**\n * Log List — rows of requests, deliveries, or messages, newest first,\n * each one line: a mono id you can copy, a status, the method, what\n * happened, and how long ago. Reach for it where a `DataTable` would be\n * columns of the same few fields: a log reads left to right as one line,\n * and the page filters it from a `FilterBar` pinned above.\n *\n * Design notes:\n * - The surface is `BasicPage.Card`'s: hairline border, `base` radius,\n * hairline rules between rows. It sits in a `Stack` as any card does.\n * - The row is one link (or one button). It stretches over the row from\n * the label, the way a `DataTable` row's does, so the whole row is one\n * pointer target and one tab stop; the copy control sits above it.\n * - The id truncates in the middle, keeping the prefix that says what it\n * is and the tail that tells it apart. The full id is a tooltip away,\n * and one click copies it.\n * - `LoadMore` is the sentinel at the end: it asks for the next page as\n * it scrolls into view, and offers a button for keyboards and for\n * browsers without an observer.\n */\n\n/** Same chrome as `BasicPage.Card`. */\nconst LOG_LIST_SURFACE =\n \"rounded-base border border-pho-secondary bg-pho-primary divide-y divide-pho-secondary\";\n\n/** Middle truncation: the prefix and this many after it, then the tail. */\nconst ID_HEAD = 12;\nconst ID_TAIL = 5;\n\n/**\n * Keep the start and the end of an id and fold the middle into an\n * ellipsis — `pho_req_01m04axjqrfzxv4xjet40a84gb` reads\n * `pho_req_01m0…a84gb`. Ids that fit are returned whole.\n */\nexport function truncateMiddle(\n value: string,\n head = ID_HEAD,\n tail = ID_TAIL,\n): string {\n if (value.length <= head + tail + 1) return value;\n return `${value.slice(0, head)}…${value.slice(-tail)}`;\n}\n\n/* -------------------------------- status -------------------------------- */\n\nconst SUCCESS_WORDS = new Set([\n \"success\",\n \"succeeded\",\n \"successful\",\n \"delivered\",\n \"ok\",\n \"sent\",\n \"received\",\n \"completed\",\n \"complete\",\n \"done\",\n \"active\",\n]);\nconst ERROR_WORDS = new Set([\n \"failed\",\n \"failure\",\n \"error\",\n \"errored\",\n \"rejected\",\n \"undelivered\",\n \"timeout\",\n \"timed_out\",\n \"timed out\",\n \"canceled\",\n \"cancelled\",\n]);\nconst WARNING_WORDS = new Set([\n \"pending\",\n \"queued\",\n \"retrying\",\n \"processing\",\n \"sending\",\n \"in_progress\",\n \"in progress\",\n \"scheduled\",\n \"waiting\",\n]);\n\n/**\n * The `Badge` color for a log status: an HTTP status code (2xx success,\n * 3xx gray, 4xx warning, 5xx error) or a word (`delivered` / `failed` /\n * `pending`). Anything else is gray.\n */\nexport function logStatusColor(status: number | string): BadgeColor {\n if (typeof status === \"number\") {\n if (status < 300) return \"success\";\n if (status < 400) return \"gray\";\n if (status < 500) return \"warning\";\n return \"error\";\n }\n const word = status.trim().toLowerCase();\n if (/^\\d{3}$/.test(word)) return logStatusColor(Number(word));\n if (SUCCESS_WORDS.has(word)) return \"success\";\n if (ERROR_WORDS.has(word)) return \"error\";\n if (WARNING_WORDS.has(word)) return \"warning\";\n return \"gray\";\n}\n\n/** A status word as a label: `timed_out` reads `Timed out`. */\nexport function logStatusLabel(status: number | string): string {\n if (typeof status === \"number\") return String(status);\n const word = status.trim().replace(/_/g, \" \");\n return word.charAt(0).toUpperCase() + word.slice(1);\n}\n\nexport interface LogStatusProps extends Omit<\n ComponentProps<\"span\">,\n \"children\" | \"color\"\n> {\n /** An HTTP status code or a status word. */\n value: number | string;\n /** Override the derived word. */\n label?: ReactNode;\n /** Badge size. @default \"sm\" */\n size?: BadgeSize;\n}\n\n/** The status slot — a low-contrast `Badge` colored by `logStatusColor`. */\nfunction Status({\n value,\n label,\n size = \"sm\",\n className,\n ...props\n}: LogStatusProps) {\n return (\n <Badge\n color={logStatusColor(value)}\n contrast=\"low\"\n size={size}\n className={cn(\"tabular-nums\", className)}\n {...props}\n >\n {label ?? logStatusLabel(value)}\n </Badge>\n );\n}\n\n/** The method slot — `POST`, `GET` as a quiet mono chip. */\nfunction Method({\n className,\n ...props\n}: ComponentProps<\"span\"> & { ref?: Ref<HTMLSpanElement> }) {\n return (\n <span\n className={cn(\n \"bg-pho-secondary text-pho-secondary inline-flex h-5 min-w-12 shrink-0 items-center justify-center rounded-sm px-1.5 font-mono text-xs font-medium whitespace-nowrap\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/* ---------------------------------- id ---------------------------------- */\n\n/**\n * The id cell: a mono button that copies the full id, with a tooltip\n * holding the whole of it. The cell is a fixed width in characters so\n * ids line up down the list.\n */\nfunction IdCell({ id, cellId }: { id: string; cellId: string }) {\n const { copied, copy } = useCopy();\n return (\n <Tooltip.Root>\n <Tooltip.Trigger\n id={cellId}\n aria-label={copied ? `${id} copied` : `Copy ${id}`}\n data-copied={copied || undefined}\n onClick={() => void copy(id)}\n className={cn(\n \"text-pho-secondary outline-pho-brand hover:text-pho-primary relative z-10 -mx-1 w-[calc(18ch+0.5rem)] shrink-0 cursor-pointer truncate rounded-sm px-1 py-0.5 text-left font-mono text-xs transition-colors duration-100 ease-linear focus-visible:outline-2\",\n \"data-[copied]:text-pho-success\",\n )}\n >\n {copied ? \"Copied\" : truncateMiddle(id)}\n </Tooltip.Trigger>\n <output className=\"sr-only\" aria-live=\"polite\">\n {copied ? \"Copied\" : \"\"}\n </output>\n <Tooltip.Portal>\n <Tooltip.Positioner>\n <Tooltip.Popup className=\"font-mono\">{id}</Tooltip.Popup>\n </Tooltip.Positioner>\n </Tooltip.Portal>\n </Tooltip.Root>\n );\n}\n\n/* ---------------------------------- row --------------------------------- */\n\nexport interface LogListRowProps extends Omit<\n ComponentProps<\"div\">,\n \"children\" | \"title\" | \"onClick\" | \"id\"\n> {\n /** The record's id — mono, middle-truncated, copied on click. */\n id?: string;\n /** The status slot — usually `LogList.Status`. */\n status?: ReactNode;\n /** The method — `POST`, `GET`; rendered in `LogList.Method`. */\n method?: string;\n /** What happened — the route, the event type, the message. */\n label: ReactNode;\n /** The label in mono — for a route or an event type. */\n code?: boolean;\n /**\n * The line under the label, with real content: who received what from\n * whom, the destination that answered. A sentence, with its period.\n */\n description?: ReactNode;\n /** Trailing: how long it took — \"59 ms\". */\n duration?: ReactNode;\n /** Trailing: when — \"2 min ago\". */\n time?: ReactNode;\n /** Trailing content before the duration and time. */\n children?: ReactNode;\n /** The row is a link to its page, through the host's `LinkProvider`. */\n href?: string;\n /** The row is a button. */\n onClick?: (event: MouseEvent<HTMLElement>) => void;\n /**\n * Replace the row's link element — a router's `Link`, the way Base UI\n * components take `render`. The row's classes and handlers merge in.\n */\n render?: useRender.RenderProp;\n /** The row whose page is open beside the list — it keeps the wash. */\n current?: boolean;\n ref?: Ref<HTMLDivElement>;\n}\n\nfunction Row({\n id,\n status,\n method,\n label,\n code,\n description,\n duration,\n time,\n children,\n href,\n onClick,\n render,\n current,\n className,\n ...props\n}: LogListRowProps) {\n const Link = useLinkComponent();\n const base = useId();\n const interactive = href != null || onClick != null || render != null;\n const cellIds = {\n id: `${base}-id`,\n status: `${base}-status`,\n method: `${base}-method`,\n meta: `${base}-meta`,\n };\n const hasMeta = children != null || duration != null || time != null;\n const describedBy = [\n id != null && cellIds.id,\n status != null && cellIds.status,\n method != null && cellIds.method,\n hasMeta && cellIds.meta,\n ]\n .filter(Boolean)\n .join(\" \");\n const primary = useRender({\n render: render ?? (href != null ? <Link href={href} /> : undefined),\n defaultTagName: href != null ? \"a\" : onClick != null ? \"button\" : \"span\",\n props: {\n className: cn(\n \"text-pho-primary block min-w-0 max-w-full truncate text-left text-base font-medium outline-none\",\n code && \"font-mono text-xs\",\n // The one link, stretched over the row; the ring is the row's.\n interactive &&\n \"cursor-pointer after:absolute after:inset-0 after:content-['']\",\n ),\n onClick,\n type:\n render == null && href == null && onClick != null\n ? \"button\"\n : undefined,\n \"aria-current\": current ? \"page\" : undefined,\n \"aria-describedby\": describedBy || undefined,\n \"data-log-primary\": \"\",\n children: label,\n },\n });\n return (\n <div\n data-log-row=\"\"\n data-current={current || undefined}\n className={cn(\n \"relative flex min-h-12 min-w-0 items-center gap-3 px-5 py-2.5\",\n interactive &&\n \"hover:bg-pho-primary-hover outline-pho-brand transition-colors has-[[data-log-primary]:focus-visible]:outline-2 has-[[data-log-primary]:focus-visible]:-outline-offset-2\",\n current && \"bg-pho-primary-hover\",\n // The wash follows the card's rounding (minus the 1px border).\n \"first:rounded-t-[calc(var(--radius-base)-1px)] last:rounded-b-[calc(var(--radius-base)-1px)]\",\n className,\n )}\n {...props}\n >\n {id != null ? <IdCell id={id} cellId={cellIds.id} /> : null}\n {status != null ? (\n <span id={cellIds.status} className=\"flex shrink-0 items-center\">\n {status}\n </span>\n ) : null}\n {method != null ? <Method id={cellIds.method}>{method}</Method> : null}\n <div data-log-primary-cell=\"\" className=\"min-w-0 flex-1\">\n {primary}\n {description != null ? (\n <p className=\"text-pho-description truncate text-xs\">{description}</p>\n ) : null}\n </div>\n {hasMeta ? (\n <div\n id={cellIds.meta}\n className=\"text-pho-description ml-auto flex shrink-0 items-center gap-3 text-xs whitespace-nowrap tabular-nums\"\n >\n {children}\n {duration != null ? <span>{duration}</span> : null}\n {time != null ? <span>{time}</span> : null}\n </div>\n ) : null}\n </div>\n );\n}\n\n/* -------------------------------- states -------------------------------- */\n\nexport interface LogListEmptyProps extends Omit<\n ComponentProps<\"div\">,\n \"title\" | \"children\"\n> {\n /** One short line naming the state. @default \"Nothing here yet.\" */\n title?: ReactNode;\n /** What fills it, or why it is empty. */\n description?: ReactNode;\n /** An action, when there is one. */\n children?: ReactNode;\n}\n\n/** The list with no rows — `StatusView` at card size. */\nfunction Empty({\n title = \"Nothing here yet.\",\n description,\n children,\n className,\n ...props\n}: LogListEmptyProps) {\n return (\n <div className={cn(\"flex justify-center\", className)} {...props}>\n <StatusView\n size=\"sm\"\n title={title}\n description={description}\n actions={children}\n />\n </div>\n );\n}\n\n/** Bones in the rows' place while the first page is on its way. */\nfunction Loading({ rows = 5 }: { rows?: number }) {\n return (\n <>\n {Array.from({ length: rows }, (_, index) => (\n <div\n key={index}\n aria-hidden\n className=\"flex min-h-12 items-center gap-3 px-5 py-2.5\"\n >\n <Skeleton className=\"h-3.5 w-32\" />\n <Skeleton className=\"h-5 w-12 rounded-full\" />\n <Skeleton className=\"h-3.5 w-48\" />\n <Skeleton className=\"ml-auto h-3.5 w-16\" />\n </div>\n ))}\n </>\n );\n}\n\nexport interface LogListLoadMoreProps extends Omit<\n ComponentProps<\"div\">,\n \"children\"\n> {\n /** Asked for as the sentinel scrolls into view, and on the button. */\n onLoadMore: () => void;\n /** The next page is on its way — the sentinel shows a spinner and waits. */\n loading?: boolean;\n /** Nothing left to load — renders nothing. @default true */\n hasMore?: boolean;\n /** How far ahead of the viewport to ask. @default \"200px\" */\n rootMargin?: string;\n /** The button's words. @default \"Load more\" */\n label?: ReactNode;\n}\n\n/**\n * The sentinel at the end of the list. An `IntersectionObserver` asks for\n * the next page as it comes into view (`rootMargin` ahead of it); while\n * `loading` it shows a spinner and asks for nothing. The button is the\n * same request for keyboards and for a browser without the observer.\n * SSR-safe: the observer is created in an effect.\n */\nfunction LoadMore({\n onLoadMore,\n loading,\n hasMore = true,\n rootMargin = \"200px\",\n label = \"Load more\",\n className,\n ...props\n}: LogListLoadMoreProps) {\n const ref = useRef<HTMLDivElement | null>(null);\n const latest = useRef(onLoadMore);\n latest.current = onLoadMore;\n useEffect(() => {\n const el = ref.current;\n if (!hasMore || loading || el == null) return;\n if (typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) latest.current();\n },\n { rootMargin },\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [hasMore, loading, rootMargin]);\n if (!hasMore) return null;\n return (\n <div\n ref={ref}\n data-log-load-more=\"\"\n aria-busy={loading || undefined}\n className={cn(\n \"flex min-h-12 items-center justify-center px-5 py-2\",\n className,\n )}\n {...props}\n >\n {loading ? (\n <Spinner aria-label=\"Loading more\" className=\"text-pho-secondary\" />\n ) : (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onLoadMore()}>\n {label}\n </Button>\n )}\n </div>\n );\n}\n\n/* ---------------------------------- root -------------------------------- */\n\nexport interface LogListRootProps extends ComponentProps<\"div\"> {\n ref?: Ref<HTMLDivElement>;\n}\n\n/** The card the rows stack in. Mark it `aria-busy` while bones show. */\nfunction Root({ className, ...props }: LogListRootProps) {\n return (\n <div\n data-log-list=\"\"\n className={cn(LOG_LIST_SURFACE, \"min-w-0\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Log List — a card of one-line log rows.\n *\n * ```tsx\n * <LogList.Root>\n * <LogList.Row\n * id=\"pho_req_01m04axjqrfzxv4xjet40a84gb\"\n * status={<LogList.Status value={200} />}\n * method=\"POST\"\n * code\n * label=\"/v1/messages\"\n * description=\"+1 332 259 3374 received a message from +1 332 222 1111.\"\n * duration=\"59 ms\"\n * time=\"2 min ago\"\n * href=\"/requests/pho_req_01m04axjqrfzxv4xjet40a84gb\"\n * />\n * <LogList.LoadMore onLoadMore={fetchNextPage} loading={isFetching} hasMore={hasNextPage} />\n * </LogList.Root>\n * ```\n */\nexport const LogList = {\n Root,\n Row,\n Status,\n Method,\n Empty,\n Loading,\n LoadMore,\n};\n"],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ "use client";
2
+ import { t as c } from "./cn-ChIgwEl3.js";
3
+ import { t as p } from "./createReactComponent-BqCmnqfX.js";
4
+ import { r as h } from "./badge-DlLJPLeZ.js";
5
+ import "react";
6
+ import { jsx as a, jsxs as i } from "react/jsx-runtime";
7
+ var y = [["path", {
8
+ d: "M3 7l6 6l4 -4l8 8",
9
+ key: "svg-0"
10
+ }], ["path", {
11
+ d: "M21 10l0 7l-7 0",
12
+ key: "svg-1"
13
+ }]], w = p("outline", "trending-down", "TrendingDown", y), N = [["path", {
14
+ d: "M3 17l6 -6l4 4l8 -8",
15
+ key: "svg-0"
16
+ }], ["path", {
17
+ d: "M14 7l7 0l0 7",
18
+ key: "svg-1"
19
+ }]], b = p("outline", "trending-up", "TrendingUp", N), v = new Intl.NumberFormat("en-US", {
20
+ minimumFractionDigits: 1,
21
+ maximumFractionDigits: 1,
22
+ signDisplay: "exceptZero"
23
+ });
24
+ function _(t) {
25
+ if (typeof t == "number") return t > 0 ? "up" : t < 0 ? "down" : "flat";
26
+ const e = t.trim(), r = e.charAt(0);
27
+ if (!(r === "+" || r === "-" || r === "−")) return "flat";
28
+ const o = e.slice(1).trim();
29
+ return Number.parseFloat(o) === 0 && !/[1-9]/.test(o) ? "flat" : r === "+" ? "up" : "down";
30
+ }
31
+ function k(t, e) {
32
+ return t === "flat" || e === "none" ? "muted" : t === e ? "success" : "error";
33
+ }
34
+ function m({ label: t, value: e, delta: r, deltaDirection: o, deltaGood: d = "up", note: s, className: f, ...x }) {
35
+ const n = r == null ? null : o ?? _(r), g = typeof r == "number" ? `${v.format(r).replace("-", "−")}%` : r, l = n === "up" ? b : n === "down" ? w : null;
36
+ return /* @__PURE__ */ i("div", {
37
+ "data-stat": "",
38
+ className: c("flex min-w-0 flex-col gap-1 px-5 py-4", f),
39
+ ...x,
40
+ children: [
41
+ /* @__PURE__ */ i("div", {
42
+ className: "flex items-start justify-between gap-3",
43
+ children: [/* @__PURE__ */ a("span", {
44
+ className: "text-pho-secondary min-w-0 truncate text-base",
45
+ children: t
46
+ }), r != null && n != null && /* @__PURE__ */ i(h, {
47
+ size: "sm",
48
+ contrast: "low",
49
+ color: k(n, d),
50
+ className: "shrink-0 tabular-nums",
51
+ "data-direction": n,
52
+ children: [l && /* @__PURE__ */ a(l, {
53
+ "aria-hidden": !0,
54
+ className: "size-3"
55
+ }), g]
56
+ })]
57
+ }),
58
+ /* @__PURE__ */ a("span", {
59
+ className: "text-display-md text-pho-primary min-w-0 truncate font-medium",
60
+ children: e
61
+ }),
62
+ s != null && /* @__PURE__ */ a("span", {
63
+ className: "text-pho-description truncate text-xs",
64
+ children: s
65
+ })
66
+ ]
67
+ });
68
+ }
69
+ m.displayName = "Stat";
70
+ function u({ variant: t = "card", className: e, ...r }) {
71
+ return /* @__PURE__ */ a("div", {
72
+ role: "group",
73
+ "data-stat-group": "",
74
+ className: c("bg-pho-secondary [&>*]:bg-pho-primary flex flex-wrap gap-px [&>*]:min-w-0 [&>*]:flex-[1_1_12rem]", t === "card" && "border-pho-secondary rounded-base overflow-hidden border", e),
75
+ ...r
76
+ });
77
+ }
78
+ u.displayName = "Stat.Group";
79
+ m.Group = u;
80
+ export {
81
+ u as n,
82
+ m as t
83
+ };
84
+
85
+ //# sourceMappingURL=stat-hnNqjWVG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-hnNqjWVG.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/IconTrendingDown.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconTrendingUp.mjs","../../src/components/stat/stat.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\": \"M3 7l6 6l4 -4l8 8\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M21 10l0 7l-7 0\", \"key\": \"svg-1\" }]];\nconst IconTrendingDown = createReactComponent(\"outline\", \"trending-down\", \"TrendingDown\", __iconNode);\n\nexport { __iconNode, IconTrendingDown as default };\n//# sourceMappingURL=IconTrendingDown.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\": \"M3 17l6 -6l4 4l8 -8\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M14 7l7 0l0 7\", \"key\": \"svg-1\" }]];\nconst IconTrendingUp = createReactComponent(\"outline\", \"trending-up\", \"TrendingUp\", __iconNode);\n\nexport { __iconNode, IconTrendingUp as default };\n//# sourceMappingURL=IconTrendingUp.mjs.map\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { IconTrendingDown, IconTrendingUp } from \"@tabler/icons-react\";\nimport { Badge, type BadgeColor } from \"../badge\";\nimport { cn } from \"../../utils/cn\";\n\n/**\n * Stat — a figure with its name: a label, a value, and, when it\n * matters, how the value moved and against what.\n *\n * Design notes:\n * - The value is the loud element: display size, medium weight, the\n * font's proportional figures (tabular digits make a big `121` look\n * loose). Label and note stay in the UI inks; nothing else competes.\n * - The delta is a low-contrast `Badge` beside the label, with an arrow so\n * the direction never rides on colour alone. Its ink says whether the\n * move is good news: `deltaGood` names the good direction, because a\n * drop in bounce rate is green and a drop in visitors is red.\n * - A tile has no chrome of its own. Alone, it sits in whatever card holds\n * it; in a `Stat.Group` the tiles share one frame and hairlines.\n */\n\nexport type StatDirection = \"up\" | \"down\" | \"flat\";\n\nexport interface StatProps extends Omit<ComponentProps<\"div\">, \"children\"> {\n /** What the figure counts — \"Visitors\", \"Active chats\". */\n label: ReactNode;\n /** The figure, already formatted — \"20.8K\", \"8m 32s\", \"1:1\". */\n value: ReactNode;\n /**\n * How the value moved: a number is a percentage change and renders\n * signed with one decimal (\"−42.0%\"); a string renders as written and\n * its sign sets the direction.\n */\n delta?: number | string;\n /** The delta's direction, when the string can't say. Derived otherwise. */\n deltaDirection?: StatDirection;\n /**\n * Which direction is good news: `up` (visitors, revenue), `down` (bounce\n * rate, latency), `none` when a move is just information. @default \"up\"\n */\n deltaGood?: \"up\" | \"down\" | \"none\";\n /** What the delta is against — \"vs. 36.2K prior\". */\n note?: ReactNode;\n}\n\nconst percent = new Intl.NumberFormat(\"en-US\", {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n signDisplay: \"exceptZero\",\n});\n\n/**\n * A leading sign — ASCII or the true minus — sets a string delta's direction.\n * A signed zero (\"+0%\", \"−0.0%\") is still flat: a caller's formatter may\n * sign every value, and zero has not moved.\n */\nfunction directionOf(delta: number | string): StatDirection {\n if (typeof delta === \"number\") {\n return delta > 0 ? \"up\" : delta < 0 ? \"down\" : \"flat\";\n }\n const trimmed = delta.trim();\n const first = trimmed.charAt(0);\n const signed = first === \"+\" || first === \"-\" || first === \"−\";\n if (!signed) return \"flat\";\n const body = trimmed.slice(1).trim();\n if (Number.parseFloat(body) === 0 && !/[1-9]/.test(body)) return \"flat\";\n return first === \"+\" ? \"up\" : \"down\";\n}\n\nfunction deltaColor(\n direction: StatDirection,\n good: NonNullable<StatProps[\"deltaGood\"]>,\n): BadgeColor {\n if (direction === \"flat\" || good === \"none\") return \"muted\";\n return direction === good ? \"success\" : \"error\";\n}\n\nexport function Stat({\n label,\n value,\n delta,\n deltaDirection,\n deltaGood = \"up\",\n note,\n className,\n ...props\n}: StatProps) {\n const direction =\n delta == null ? null : (deltaDirection ?? directionOf(delta));\n const text =\n typeof delta === \"number\"\n ? // The true minus, so the sign reads at badge size.\n `${percent.format(delta).replace(\"-\", \"−\")}%`\n : delta;\n const Arrow =\n direction === \"up\"\n ? IconTrendingUp\n : direction === \"down\"\n ? IconTrendingDown\n : null;\n return (\n <div\n data-stat=\"\"\n className={cn(\"flex min-w-0 flex-col gap-1 px-5 py-4\", className)}\n {...props}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <span className=\"text-pho-secondary min-w-0 truncate text-base\">\n {label}\n </span>\n {delta != null && direction != null && (\n <Badge\n size=\"sm\"\n contrast=\"low\"\n color={deltaColor(direction, deltaGood)}\n className=\"shrink-0 tabular-nums\"\n data-direction={direction}\n >\n {Arrow && <Arrow aria-hidden className=\"size-3\" />}\n {text}\n </Badge>\n )}\n </div>\n <span className=\"text-display-md text-pho-primary min-w-0 truncate font-medium\">\n {value}\n </span>\n {note != null && (\n <span className=\"text-pho-description truncate text-xs\">{note}</span>\n )}\n </div>\n );\n}\n\nStat.displayName = \"Stat\";\n\nexport interface StatGroupProps extends ComponentProps<\"div\"> {\n /**\n * `card` frames the row as a card of its own; `plain` keeps only the\n * hairlines between tiles, for a row inside a card or under a chart.\n * @default \"card\"\n */\n variant?: \"card\" | \"plain\";\n}\n\n/**\n * A row of tiles that reads as one card: hairlines between tiles, and\n * between rows once the tiles wrap on a narrow width. Each tile takes an\n * equal share of its row, never narrower than 12rem; a tile that wraps\n * alone stretches across its line, so the frame never shows a hole.\n */\nexport function StatGroup({\n variant = \"card\",\n className,\n ...props\n}: StatGroupProps) {\n return (\n <div\n // A row of figures is a group, not a form's fieldset: the role, and\n // the caller's `aria-label`, name it for assistive tech.\n // oxlint-disable-next-line jsx-a11y/prefer-tag-over-role\n role=\"group\"\n data-stat-group=\"\"\n className={cn(\n // The hairlines are the gap: the frame's secondary shows through\n // 1px between tiles, so wrapping rows get a rule too. Flex, not\n // grid: a grid's empty cells on the last row would show through.\n \"bg-pho-secondary [&>*]:bg-pho-primary flex flex-wrap gap-px [&>*]:min-w-0 [&>*]:flex-[1_1_12rem]\",\n variant === \"card\" &&\n \"border-pho-secondary rounded-base overflow-hidden border\",\n className,\n )}\n {...props}\n />\n );\n}\n\nStatGroup.displayName = \"Stat.Group\";\nStat.Group = StatGroup;\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { t as o } from "./cn-ChIgwEl3.js";
3
+ import { t as i } from "./resolve-variant-CcD8iG5l.js";
4
+ import "react";
5
+ import { jsx as r } from "react/jsx-runtime";
6
+ import { Toggle as a } from "@base-ui/react/toggle";
7
+ var n = {
8
+ sm: {
9
+ classes: "h-8 min-w-8 px-2 text-xs [&>svg]:size-4",
10
+ description: "Small — dense toolbars, a range picker"
11
+ },
12
+ md: {
13
+ classes: "h-9 min-w-9 px-2 text-base [&>svg]:size-5",
14
+ description: "Medium — the default"
15
+ },
16
+ lg: {
17
+ classes: "h-10 min-w-10 px-2.5 text-base [&>svg]:size-5",
18
+ description: "Large"
19
+ }
20
+ };
21
+ function l({ className: e, size: s = "md", ...t }) {
22
+ return /* @__PURE__ */ r(a, {
23
+ className: o("squircle outline-pho-brand text-pho-secondary rounded-base inline-flex cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2", "hover:bg-pho-ghost-hover hover:text-pho-secondary-hover", "data-[pressed]:bg-pho-inverse data-[pressed]:text-pho-inverse", "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50", i(n, s), e),
24
+ ...t
25
+ });
26
+ }
27
+ l.displayName = "Toggle";
28
+ export {
29
+ l as n,
30
+ n as t
31
+ };
32
+
33
+ //# sourceMappingURL=toggle-o84tawXy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggle-o84tawXy.js","names":[],"sources":["../../src/components/toggle/toggle.tsx"],"sourcesContent":["import { type ComponentProps } from \"react\";\nimport { Toggle as BaseToggle } from \"@base-ui/react/toggle\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant, type VariantMap } from \"../../utils/resolve-variant\";\n\n/**\n * Size axis — three heights. An icon-only toggle is square (the padding\n * plus the icon add up to the height); one carrying a short label — a\n * range picker's `7d` — grows to fit it. `md` is default.\n */\nexport const TOGGLE_SIZES = {\n sm: {\n classes: \"h-8 min-w-8 px-2 text-xs [&>svg]:size-4\",\n description: \"Small — dense toolbars, a range picker\",\n },\n md: {\n classes: \"h-9 min-w-9 px-2 text-base [&>svg]:size-5\",\n description: \"Medium — the default\",\n },\n lg: {\n classes: \"h-10 min-w-10 px-2.5 text-base [&>svg]:size-5\",\n description: \"Large\",\n },\n} satisfies VariantMap;\n\nexport type ToggleSize = keyof typeof TOGGLE_SIZES;\n\nexport interface ToggleProps extends Omit<\n ComponentProps<typeof BaseToggle>,\n \"className\"\n> {\n className?: string;\n /** Size variant. @default \"md\" */\n size?: ToggleSize;\n}\n\n/**\n * A two-state button (pressed / not pressed) built on Base UI `Toggle` — the\n * canonical Bold/Italic toolbar control. Controlled via `pressed` /\n * `onPressedChange` or uncontrolled via `defaultPressed`. For a set of related\n * toggles, use `ToggleGroup`.\n */\nexport function Toggle({ className, size = \"md\", ...props }: ToggleProps) {\n return (\n <BaseToggle\n className={cn(\n \"squircle outline-pho-brand text-pho-secondary rounded-base inline-flex cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2\",\n // Ghost control at rest — hover is the alpha wash (Button `tertiary`\n // idiom), not the card-surface hover token.\n \"hover:bg-pho-ghost-hover hover:text-pho-secondary-hover\",\n // Pressed = the site's inverted chip (Tab active): dark chip in light\n // mode, light chip in dark mode — visible on any surface.\n \"data-[pressed]:bg-pho-inverse data-[pressed]:text-pho-inverse\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n resolveVariant(TOGGLE_SIZES, size),\n className,\n )}\n {...props}\n />\n );\n}\n\nToggle.displayName = \"Toggle\";\n"],"mappings":";;;;;;AAUA,IAAa,IAAe;AAAA,EAC1B,IAAI;AAAA,IACF,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,IAAI;AAAA,IACF,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA,IAAI;AAAA,IACF,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AACF;AAmBA,SAAgB,EAAO,EAAE,WAAA,GAAW,MAAA,IAAO,MAAM,GAAG,EAAA,GAAsB;AACxE,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,WAAW,EACT,sPAGA,2DAGA,iEACA,iEACA,EAAe,GAAc,CAAI,GACjC,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,EAAO,cAAc"}
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import { t as a } from "./cn-ChIgwEl3.js";
3
+ import "react";
4
+ import { jsx as i } from "react/jsx-runtime";
5
+ import { Tooltip as r } from "@base-ui/react/tooltip";
6
+ var n = r.Provider, s = r.Root, p = r.Trigger, d = r.Portal;
7
+ function g({ className: o, sideOffset: t = 6, ...e }) {
8
+ return /* @__PURE__ */ i(r.Positioner, {
9
+ sideOffset: t,
10
+ className: a("z-50", o),
11
+ ...e
12
+ });
13
+ }
14
+ function l({ className: o, ...t }) {
15
+ return /* @__PURE__ */ i(r.Popup, {
16
+ className: a("bg-pho-primary text-pho-secondary shadow-pho-lg ring-pho-secondary rounded-base origin-[var(--transform-origin)] px-2.5 py-1.5 text-xs font-medium ring-1 transition-[transform,opacity] duration-150 ease-out ring-inset", "data-[starting-style]:scale-95 data-[starting-style]:opacity-0", "data-[ending-style]:scale-95 data-[ending-style]:opacity-0", o),
17
+ ...t
18
+ });
19
+ }
20
+ var f = {
21
+ Provider: n,
22
+ Root: s,
23
+ Trigger: p,
24
+ Portal: d,
25
+ Positioner: g,
26
+ Popup: l
27
+ };
28
+ export {
29
+ f as t
30
+ };
31
+
32
+ //# sourceMappingURL=tooltip-BTF7GChl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip-BTF7GChl.js","names":[],"sources":["../../src/components/tooltip/tooltip.tsx"],"sourcesContent":["import { type ComponentProps, type ElementType } from \"react\";\nimport { Tooltip as BaseTooltip } from \"@base-ui/react/tooltip\";\nimport { cn } from \"../../utils/cn\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\"\n> & {\n className?: string;\n};\n\nconst Provider = BaseTooltip.Provider;\nconst Root = BaseTooltip.Root;\nconst Trigger = BaseTooltip.Trigger;\nconst Portal = BaseTooltip.Portal;\n\nfunction Positioner({\n className,\n sideOffset = 6,\n ...props\n}: StyledProps<typeof BaseTooltip.Positioner>) {\n return (\n <BaseTooltip.Positioner\n sideOffset={sideOffset}\n className={cn(\"z-50\", className)}\n {...props}\n />\n );\n}\n\nfunction Popup({ className, ...props }: StyledProps<typeof BaseTooltip.Popup>) {\n return (\n <BaseTooltip.Popup\n className={cn(\n // Floating layer: bg-pho-primary surface, pho-secondary hairline ring, keeps shadow elevation.\n \"bg-pho-primary text-pho-secondary shadow-pho-lg ring-pho-secondary rounded-base origin-[var(--transform-origin)] px-2.5 py-1.5 text-xs font-medium ring-1 transition-[transform,opacity] duration-150 ease-out ring-inset\",\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Tooltip built on Base UI `Tooltip` — a brief, hover/focus-triggered label for\n * an icon or control. Wrap your app (or a subtree) in `Tooltip.Provider` to\n * share open/close timing. The trigger must be a focusable element. Never put\n * essential or interactive content in a tooltip; use `Popover` for that.\n */\nexport const Tooltip = { Provider, Root, Trigger, Portal, Positioner, Popup };\n"],"mappings":";;;;;AAYA,IAAM,IAAW,EAAY,UACvB,IAAO,EAAY,MACnB,IAAU,EAAY,SACtB,IAAS,EAAY;AAE3B,SAAS,EAAW,EAClB,WAAA,GACA,YAAA,IAAa,GACb,GAAG,EAAA,GAC0C;AAC7C,SACE,gBAAA,EAAC,EAAY,YAAb;AAAA,IACc,YAAA;AAAA,IACZ,WAAW,EAAG,QAAQ,CAAS;AAAA,IAC/B,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,WAAA,GAAW,GAAG,EAAA,GAAgD;AAC7E,SACE,gBAAA,EAAC,EAAY,OAAb;AAAA,IACE,WAAW,EAET,6NACA,kEACA,8DACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAQA,IAAa,IAAU;AAAA,EAAE,UAAA;AAAA,EAAU,MAAA;AAAA,EAAM,SAAA;AAAA,EAAS,QAAA;AAAA,EAAQ,YAAA;AAAA,EAAY,OAAA;AAAM"}