@photon-ai/pho-ui 2.16.0 → 2.17.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 (97) hide show
  1. package/dist/chunks/IconArrowsMinimize-BfPUGuCB.js +75 -0
  2. package/dist/chunks/IconArrowsMinimize-BfPUGuCB.js.map +1 -0
  3. package/dist/chunks/IconChevronUp-CrpWSgIl.js +11 -0
  4. package/dist/chunks/IconChevronUp-CrpWSgIl.js.map +1 -0
  5. package/dist/chunks/{bar-chart-BJfr3eyd.js → bar-chart-DIALC2_z.js} +2 -2
  6. package/dist/chunks/bar-chart-DIALC2_z.js.map +1 -0
  7. package/dist/chunks/basic-page-CogcwGx3.js +1749 -0
  8. package/dist/chunks/basic-page-CogcwGx3.js.map +1 -0
  9. package/dist/chunks/card-DhDwtSi9.js +56 -0
  10. package/dist/chunks/card-DhDwtSi9.js.map +1 -0
  11. package/dist/chunks/code-block-BuDIo8Q0.js +197 -0
  12. package/dist/chunks/code-block-BuDIo8Q0.js.map +1 -0
  13. package/dist/chunks/collapsible-if7ncPbI.js +28 -0
  14. package/dist/chunks/collapsible-if7ncPbI.js.map +1 -0
  15. package/dist/chunks/{command-Ck8IAgV7.js → command-CTYrSz9a.js} +2 -2
  16. package/dist/chunks/{command-Ck8IAgV7.js.map → command-CTYrSz9a.js.map} +1 -1
  17. package/dist/chunks/data-table-DcwCgXJU.js +293 -0
  18. package/dist/chunks/data-table-DcwCgXJU.js.map +1 -0
  19. package/dist/chunks/date-range-picker-DwFDUNRL.js +88 -0
  20. package/dist/chunks/date-range-picker-DwFDUNRL.js.map +1 -0
  21. package/dist/chunks/{dialog-BxKACOj5.js → dialog-BwfUFn6B.js} +2 -2
  22. package/dist/chunks/{dialog-BxKACOj5.js.map → dialog-BwfUFn6B.js.map} +1 -1
  23. package/dist/chunks/{filter-bar-Cjjq38xo.js → filter-bar-BsvdXwzc.js} +2 -2
  24. package/dist/chunks/{filter-bar-Cjjq38xo.js.map → filter-bar-BsvdXwzc.js.map} +1 -1
  25. package/dist/chunks/ghost-search-BvBFa9su.js +25 -0
  26. package/dist/chunks/ghost-search-BvBFa9su.js.map +1 -0
  27. package/dist/chunks/{line-chart-CUR3AxrR.js → line-chart-VuMYKzW3.js} +2 -2
  28. package/dist/chunks/{line-chart-CUR3AxrR.js.map → line-chart-VuMYKzW3.js.map} +1 -1
  29. package/dist/chunks/{log-list-0AXnjFrk.js → log-list-BERiO4UJ.js} +2 -2
  30. package/dist/chunks/{log-list-0AXnjFrk.js.map → log-list-BERiO4UJ.js.map} +1 -1
  31. package/dist/chunks/scroll-area-Zik8t1Mk.js +168 -0
  32. package/dist/chunks/scroll-area-Zik8t1Mk.js.map +1 -0
  33. package/dist/chunks/sidebar-DRPe5CAh.js +306 -0
  34. package/dist/chunks/sidebar-DRPe5CAh.js.map +1 -0
  35. package/dist/chunks/{toast-iSf6NuAS.js → toast-72Wwlzg9.js} +2 -2
  36. package/dist/chunks/{toast-iSf6NuAS.js.map → toast-72Wwlzg9.js.map} +1 -1
  37. package/dist/chunks/trace-Ba1RMBfk.js +1645 -0
  38. package/dist/chunks/trace-Ba1RMBfk.js.map +1 -0
  39. package/dist/chunks/use-measure-C-i54AC6.js +629 -0
  40. package/dist/chunks/use-measure-C-i54AC6.js.map +1 -0
  41. package/dist/components/bar-chart.js +1 -1
  42. package/dist/components/card.js +1 -1
  43. package/dist/components/code-block.js +1 -1
  44. package/dist/components/collapsible.js +2 -25
  45. package/dist/components/command.js +1 -1
  46. package/dist/components/data-table.js +9 -8
  47. package/dist/components/date-range-picker.js +10 -0
  48. package/dist/components/dialog.js +1 -1
  49. package/dist/components/filter-bar.js +1 -1
  50. package/dist/components/line-chart.js +1 -1
  51. package/dist/components/log-list.js +1 -1
  52. package/dist/components/scroll-area.js +1 -1
  53. package/dist/components/toast.js +1 -1
  54. package/dist/components/trace.js +41 -6
  55. package/dist/index.js +166 -121
  56. package/dist/primitives.js +2 -2
  57. package/dist/sections/basic-page.js +5 -5
  58. package/dist/sections/sidebar.js +9 -6
  59. package/dist/src/components/card/card.d.ts +5 -1
  60. package/dist/src/components/chart/scale.d.ts +6 -1
  61. package/dist/src/components/code-block/code-block.d.ts +24 -5
  62. package/dist/src/components/code-block/index.d.ts +1 -1
  63. package/dist/src/components/data-table/data-table.d.ts +54 -13
  64. package/dist/src/components/date-range-picker/date-range-picker.d.ts +31 -0
  65. package/dist/src/components/date-range-picker/index.d.ts +1 -0
  66. package/dist/src/components/scroll-area/scroll-area.d.ts +9 -1
  67. package/dist/src/components/trace/decorations.d.ts +32 -0
  68. package/dist/src/components/trace/index.d.ts +5 -2
  69. package/dist/src/components/trace/layout.d.ts +57 -29
  70. package/dist/src/components/trace/span-primitive.d.ts +168 -0
  71. package/dist/src/components/trace/span-tree.d.ts +148 -0
  72. package/dist/src/components/trace/trace.d.ts +98 -16
  73. package/dist/src/index.d.ts +1 -0
  74. package/dist/src/sections/basic-page/basic-page.d.ts +95 -7
  75. package/dist/src/sections/basic-page/index.d.ts +1 -1
  76. package/dist/src/sections/sidebar/index.d.ts +1 -1
  77. package/dist/src/sections/sidebar/sidebar.d.ts +72 -0
  78. package/dist/src/utils/ghost-search.d.ts +11 -0
  79. package/package.json +5 -1
  80. package/dist/chunks/bar-chart-BJfr3eyd.js.map +0 -1
  81. package/dist/chunks/basic-page-CMJuM5iA.js +0 -1650
  82. package/dist/chunks/basic-page-CMJuM5iA.js.map +0 -1
  83. package/dist/chunks/card-DSW3Uhag.js +0 -56
  84. package/dist/chunks/card-DSW3Uhag.js.map +0 -1
  85. package/dist/chunks/code-block-CdozzaHM.js +0 -139
  86. package/dist/chunks/code-block-CdozzaHM.js.map +0 -1
  87. package/dist/chunks/data-table-CHLJfGkS.js +0 -279
  88. package/dist/chunks/data-table-CHLJfGkS.js.map +0 -1
  89. package/dist/chunks/scroll-area-BO-9PMM7.js +0 -167
  90. package/dist/chunks/scroll-area-BO-9PMM7.js.map +0 -1
  91. package/dist/chunks/sidebar-DVzZsCts.js +0 -223
  92. package/dist/chunks/sidebar-DVzZsCts.js.map +0 -1
  93. package/dist/chunks/trace-CbH0IohX.js +0 -314
  94. package/dist/chunks/trace-CbH0IohX.js.map +0 -1
  95. package/dist/chunks/use-measure-CMVgLouO.js +0 -616
  96. package/dist/chunks/use-measure-CMVgLouO.js.map +0 -1
  97. package/dist/components/collapsible.js.map +0 -1
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { t as r } from "./cn-ChIgwEl3.js";
3
+ import "react";
4
+ import { jsx as s } from "react/jsx-runtime";
5
+ var o = "border-pho-secondary bg-pho-primary rounded-lg border";
6
+ function i({ className: t, ...a }) {
7
+ return /* @__PURE__ */ s("div", {
8
+ className: r(o, "flex flex-col gap-4 pt-5 pb-4", "has-[>[data-stat-group]:first-child]:pt-0 has-[>[data-stat]:first-child]:pt-0", "has-[>[data-stat-group]:last-child]:pb-0 has-[>[data-stat]:last-child]:pb-0", "has-[>:first-child:has([data-chart])]:pt-0", t),
9
+ ...a
10
+ });
11
+ }
12
+ function n({ className: t, ...a }) {
13
+ return /* @__PURE__ */ s("div", {
14
+ className: r("flex flex-col gap-0.5 px-5", t),
15
+ ...a
16
+ });
17
+ }
18
+ function p({ className: t, children: a, ...e }) {
19
+ return /* @__PURE__ */ s("h3", {
20
+ className: r("text-display-xs text-pho-primary font-medium", t),
21
+ ...e,
22
+ children: a
23
+ });
24
+ }
25
+ function c({ className: t, ...a }) {
26
+ return /* @__PURE__ */ s("p", {
27
+ className: r("text-display-xs text-pho-description font-normal", t),
28
+ ...a
29
+ });
30
+ }
31
+ function l({ className: t, ...a }) {
32
+ return /* @__PURE__ */ s("div", {
33
+ className: r("px-5", t),
34
+ ...a
35
+ });
36
+ }
37
+ function d({ className: t, ...a }) {
38
+ return /* @__PURE__ */ s("div", {
39
+ className: r("flex items-center gap-2 px-5", t),
40
+ ...a
41
+ });
42
+ }
43
+ var u = {
44
+ Root: i,
45
+ Header: n,
46
+ Title: p,
47
+ Description: c,
48
+ Content: l,
49
+ Footer: d
50
+ };
51
+ export {
52
+ u as n,
53
+ o as t
54
+ };
55
+
56
+ //# sourceMappingURL=card-DhDwtSi9.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-DhDwtSi9.js","names":[],"sources":["../../src/components/card/card.tsx"],"sourcesContent":["import { type ComponentProps, type Ref } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/**\n * Design notes:\n * - A card is a flat bordered panel on the page surface — hairline border,\n * primary background, no shadow. Elevation shadows stay on floating layers\n * (menus, dialogs); see the same rule on Input and Select.\n * - Radius sits at the `lg` stop (16px) like Dialog — a standalone content\n * panel reads bigger than a control, so it takes the panel radius rather\n * than the control default (`base`).\n * - Vertical rhythm: `pt-5` / `pb-4`, `gap-4` between parts. Parts carry\n * `px-5`, so a child without padding (an image, a table, a `Separator`)\n * runs edge-to-edge on its own. A `Stat` / `Stat.Group` already pads\n * its tiles — when it is the first or last child the matching inset\n * drops so the row sits flush on the card edge. A chart as the first\n * child drops the top inset the same way; the plot keeps its own\n * bottom band.\n * - No size or color axes. A card is chrome, not a signal — content sets the\n * tone. Sizing belongs to the layout that places the card.\n */\n\n/** Surface chrome — exported for hosts that need the look on another element. */\nexport const CARD_SURFACE =\n \"border-pho-secondary bg-pho-primary rounded-lg border\";\n\n/** The panel: bordered surface, vertical rhythm between parts. */\nfunction Root({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return (\n <div\n className={cn(\n CARD_SURFACE,\n \"flex flex-col gap-4 pt-5 pb-4\",\n // Stat tiles pad themselves; a chart's plot already insets.\n \"has-[>[data-stat-group]:first-child]:pt-0 has-[>[data-stat]:first-child]:pt-0\",\n \"has-[>[data-stat-group]:last-child]:pb-0 has-[>[data-stat]:last-child]:pb-0\",\n \"has-[>:first-child:has([data-chart])]:pt-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Title + optional description pair, kept tight (`gap-0.5`). */\nfunction Header({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return (\n <div className={cn(\"flex flex-col gap-0.5 px-5\", className)} {...props} />\n );\n}\n\n/**\n * Card heading — an `<h3>` so it nests under page (`h1`) and section (`h2`)\n * headings without skipping levels.\n */\nfunction Title({\n className,\n children,\n ...props\n}: ComponentProps<\"h3\"> & { ref?: Ref<HTMLHeadingElement> }) {\n return (\n <h3\n className={cn(\"text-display-xs text-pho-primary font-medium\", className)}\n {...props}\n >\n {children}\n </h3>\n );\n}\n\n/** Supporting copy under the title — same step, secondary tone. */\nfunction Description({\n className,\n ...props\n}: ComponentProps<\"p\"> & { ref?: Ref<HTMLParagraphElement> }) {\n return (\n <p\n className={cn(\n \"text-display-xs text-pho-description font-normal\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** The card body. Carries the horizontal padding; bring your own layout. */\nfunction Content({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return <div className={cn(\"px-5\", className)} {...props} />;\n}\n\n/**\n * Trailing row — actions, a status line. Unopinionated about justification;\n * add `justify-end` for a dialog-style action bar.\n */\nfunction Footer({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return (\n <div className={cn(\"flex items-center gap-2 px-5\", className)} {...props} />\n );\n}\n\n/**\n * Card — a bordered content panel: header (title + description), body,\n * optional footer. It's static chrome with no interactivity of its own.\n * For a label/control list use `BasicPage.Card`; for a featured\n * block on the page surface use `BasicPage.Callout`.\n *\n * ```tsx\n * <Card.Root>\n * <Card.Header>\n * <Card.Title>Usage</Card.Title>\n * <Card.Description>Since Aug 1.</Card.Description>\n * </Card.Header>\n * <Card.Content>…</Card.Content>\n * <Card.Footer className=\"justify-end\">\n * <Button size=\"sm\">Upgrade</Button>\n * </Card.Footer>\n * </Card.Root>\n * ```\n */\nexport const Card = {\n Root,\n Header,\n Title,\n Description,\n Content,\n Footer,\n};\n"],"mappings":";;;;AAuBA,IAAa,IACX;AAGF,SAAS,EAAK,EACZ,WAAA,GACA,GAAG,EAAA,GACqD;AACxD,SACE,gBAAA,EAAC,OAAD;AAAA,IACE,WAAW,EACT,GACA,iCAEA,iFACA,+EACA,8CACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAGA,SAAS,EAAO,EACd,WAAA,GACA,GAAG,EAAA,GACqD;AACxD,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,EAAG,8BAA8B,CAAS;AAAA,IAAG,GAAI;AAAA,EAAQ,CAAA;AAE7E;AAMA,SAAS,EAAM,EACb,WAAA,GACA,UAAA,GACA,GAAG,EAAA,GACwD;AAC3D,SACE,gBAAA,EAAC,MAAD;AAAA,IACE,WAAW,EAAG,gDAAgD,CAAS;AAAA,IACvE,GAAI;AAAA,IAEH,UAAA;AAAA,EACC,CAAA;AAER;AAGA,SAAS,EAAY,EACnB,WAAA,GACA,GAAG,EAAA,GACyD;AAC5D,SACE,gBAAA,EAAC,KAAD;AAAA,IACE,WAAW,EACT,oDACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAGA,SAAS,EAAQ,EACf,WAAA,GACA,GAAG,EAAA,GACqD;AACxD,SAAO,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,EAAG,QAAQ,CAAS;AAAA,IAAG,GAAI;AAAA,EAAQ,CAAA;AAC5D;AAMA,SAAS,EAAO,EACd,WAAA,GACA,GAAG,EAAA,GACqD;AACxD,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,EAAG,gCAAgC,CAAS;AAAA,IAAG,GAAI;AAAA,EAAQ,CAAA;AAE/E;AAqBA,IAAa,IAAO;AAAA,EAClB,MAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AACF"}
@@ -0,0 +1,197 @@
1
+ "use client";
2
+ import { t as v } from "./cn-ChIgwEl3.js";
3
+ import { a as V } from "./button-CdqS_t5a.js";
4
+ import { t as Y } from "./createReactComponent-BqCmnqfX.js";
5
+ import { n as q, t as G } from "./IconArrowsMinimize-BfPUGuCB.js";
6
+ import { t as Q } from "./IconChevronDown-CZilB71T.js";
7
+ import { t as X } from "./IconChevronUp-CrpWSgIl.js";
8
+ import { n as Z } from "./copy-button-B_B15mEi.js";
9
+ import { t as p } from "./scroll-area-Zik8t1Mk.js";
10
+ import { t as u } from "./tooltip-BTF7GChl.js";
11
+ import { n as ee } from "./toggle-o84tawXy.js";
12
+ import { useMemo as M, useState as W } from "react";
13
+ import { jsx as e, jsxs as m } from "react/jsx-runtime";
14
+ var te = [
15
+ ["path", {
16
+ d: "M4 6l16 0",
17
+ key: "svg-0"
18
+ }],
19
+ ["path", {
20
+ d: "M4 18l5 0",
21
+ key: "svg-1"
22
+ }],
23
+ ["path", {
24
+ d: "M4 12h13a3 3 0 0 1 0 6h-4l2 -2m0 4l-2 -2",
25
+ key: "svg-2"
26
+ }]
27
+ ], ne = Y("outline", "text-wrap", "TextWrap", te), w = /("(?:[^"\\]|\\.)*")(\s*:)?|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|\b(true|false|null)\b|([{}[\]:,])/g;
28
+ function oe(t) {
29
+ const r = [];
30
+ let n = 0;
31
+ w.lastIndex = 0;
32
+ for (let o = w.exec(t); o != null; o = w.exec(t)) {
33
+ o.index > n && r.push({
34
+ type: "plain",
35
+ text: t.slice(n, o.index)
36
+ });
37
+ const [, l, a, c, s, d] = o;
38
+ l != null ? (r.push({
39
+ type: a != null ? "key" : "string",
40
+ text: l
41
+ }), a != null && r.push({
42
+ type: "punctuation",
43
+ text: a
44
+ })) : c != null ? r.push({
45
+ type: "number",
46
+ text: c
47
+ }) : s != null ? r.push({
48
+ type: "keyword",
49
+ text: s
50
+ }) : d != null && r.push({
51
+ type: "punctuation",
52
+ text: d
53
+ }), n = o.index + o[0].length;
54
+ }
55
+ return n < t.length && r.push({
56
+ type: "plain",
57
+ text: t.slice(n)
58
+ }), r;
59
+ }
60
+ var re = {
61
+ key: "text-pho-code-key",
62
+ string: "text-pho-code-string",
63
+ number: "text-pho-code-number",
64
+ keyword: "text-pho-code-keyword",
65
+ punctuation: "text-pho-code-punctuation",
66
+ plain: void 0
67
+ }, le = "rounded-base border border-pho-secondary bg-pho-code-bg text-pho-code-fg", ae = "1.25rem", se = "0.75rem";
68
+ function ie(t) {
69
+ if (t == null) return "";
70
+ if (typeof t == "string") return t;
71
+ try {
72
+ return JSON.stringify(t, null, 2) ?? "";
73
+ } catch {
74
+ return String(t);
75
+ }
76
+ }
77
+ function _({ label: t, pressed: r, onPressedChange: n, children: o }) {
78
+ return /* @__PURE__ */ m(u.Root, { children: [/* @__PURE__ */ e(u.Trigger, { render: /* @__PURE__ */ e(ee, {
79
+ size: "sm",
80
+ pressed: r,
81
+ onPressedChange: n,
82
+ "aria-label": t,
83
+ className: "rounded-sm",
84
+ children: o
85
+ }) }), /* @__PURE__ */ e(u.Portal, { children: /* @__PURE__ */ e(u.Positioner, { children: /* @__PURE__ */ e(u.Popup, { children: t }) }) })] });
86
+ }
87
+ function ce({ lines: t, language: r, lineNumbers: n, digits: o, wrap: l }) {
88
+ return /* @__PURE__ */ e("code", { children: t.map((a, c) => /* @__PURE__ */ m("span", {
89
+ "data-line": "",
90
+ className: v("min-h-5", n ? "flex items-start" : "block", n && !l && "min-w-max"),
91
+ children: [n ? /* @__PURE__ */ e("span", {
92
+ "data-line-number": "",
93
+ "aria-hidden": !0,
94
+ className: "text-pho-placeholder bg-pho-code-bg sticky left-0 z-[1] box-content shrink-0 pr-3 pl-3 text-right font-mono text-xs leading-5 tabular-nums select-none",
95
+ style: { width: `${o}ch` },
96
+ children: c + 1
97
+ }) : null, /* @__PURE__ */ e("span", {
98
+ className: n ? "min-w-0 flex-1" : void 0,
99
+ children: r === "json" ? oe(a).map((s, d) => s.type === "plain" ? s.text : /* @__PURE__ */ e("span", {
100
+ className: re[s.type],
101
+ children: s.text
102
+ }, d)) : a
103
+ })]
104
+ }, c)) });
105
+ }
106
+ function pe({ code: t, language: r = "text", title: n, maxLines: o = 30, overflow: l = "scroll", wrap: a, defaultWrap: c = !1, onWrapChange: s, expandToggle: d = !0, wrapToggle: $ = !0, lineNumbers: C = !1, copy: A = !0, empty: O = "Nothing to show.", actions: N, className: P, ...B }) {
107
+ const x = M(() => ie(t), [t]), h = M(() => x.split(`
108
+ `), [x]), [L, D] = W(c), f = a ?? L, R = (b) => {
109
+ a == null && D(b), s?.(b);
110
+ }, [i, k] = W(!1), g = h.length > o, S = l === "scroll" && g && !i, j = l === "expand" && g && !i ? h.slice(0, o) : h, y = x === "", T = l === "scroll" && d && g && !y, E = $ && !y, z = A && !y, H = n != null || N != null || T || E || z, K = typeof n == "string" ? n.toLowerCase() : "code", J = typeof n == "string" ? n : "Code", U = i ? `Collapse to ${o} lines` : `Show all ${h.length} lines`, F = String(Math.max(h.length, 1)).length, I = /* @__PURE__ */ e("pre", {
111
+ className: v("m-0 min-w-0 py-3 font-mono text-xs leading-5", C ? "pr-3 pl-0" : "px-3", f ? "[overflow-wrap:anywhere] whitespace-pre-wrap" : S ? "whitespace-pre" : "overflow-x-auto whitespace-pre"),
112
+ children: /* @__PURE__ */ e(ce, {
113
+ lines: j,
114
+ language: r,
115
+ lineNumbers: C,
116
+ digits: F,
117
+ wrap: f
118
+ })
119
+ });
120
+ return /* @__PURE__ */ m("div", {
121
+ "data-code-block": "",
122
+ "data-language": r,
123
+ "data-overflow": l,
124
+ className: v(le, "flex min-w-0 flex-col", P),
125
+ ...B,
126
+ children: [
127
+ H ? /* @__PURE__ */ m("div", {
128
+ className: "border-pho-secondary flex min-h-10 items-center gap-2 border-b py-1 pr-1.5 pl-3",
129
+ children: [
130
+ /* @__PURE__ */ e("div", {
131
+ className: "text-pho-secondary min-w-0 flex-1 truncate text-xs font-medium",
132
+ children: n
133
+ }),
134
+ N,
135
+ /* @__PURE__ */ m(u.Provider, { children: [T ? /* @__PURE__ */ e(_, {
136
+ label: U,
137
+ pressed: i,
138
+ onPressedChange: k,
139
+ children: i ? /* @__PURE__ */ e(G, { "aria-hidden": !0 }) : /* @__PURE__ */ e(q, { "aria-hidden": !0 })
140
+ }) : null, E ? /* @__PURE__ */ e(_, {
141
+ label: "Wrap long lines",
142
+ pressed: f,
143
+ onPressedChange: R,
144
+ children: /* @__PURE__ */ e(ne, { "aria-hidden": !0 })
145
+ }) : null] }),
146
+ z ? /* @__PURE__ */ e(Z, {
147
+ value: x,
148
+ label: K,
149
+ size: "md"
150
+ }) : null
151
+ ]
152
+ }) : null,
153
+ y ? /* @__PURE__ */ e("p", {
154
+ className: "text-pho-description m-0 px-3 py-3 text-base",
155
+ children: O
156
+ }) : S ? /* @__PURE__ */ e("section", {
157
+ className: "min-w-0",
158
+ children: /* @__PURE__ */ m(p.Root, {
159
+ fade: !1,
160
+ "data-code-scroll": "",
161
+ className: "min-w-0 rounded-b-[inherit]",
162
+ style: { height: `calc(${o} * ${ae} + ${se} * 2)` },
163
+ children: [
164
+ /* @__PURE__ */ e(p.Viewport, {
165
+ tabIndex: 0,
166
+ "aria-label": J,
167
+ children: /* @__PURE__ */ e(p.Content, { children: I })
168
+ }),
169
+ /* @__PURE__ */ e(p.Scrollbar, { children: /* @__PURE__ */ e(p.Thumb, {}) }),
170
+ f ? null : /* @__PURE__ */ e(p.Scrollbar, {
171
+ orientation: "horizontal",
172
+ children: /* @__PURE__ */ e(p.Thumb, {})
173
+ })
174
+ ]
175
+ })
176
+ }) : I,
177
+ l === "expand" && g ? /* @__PURE__ */ e("div", {
178
+ className: "border-pho-secondary flex items-center border-t px-1.5 py-1",
179
+ children: /* @__PURE__ */ e(V, {
180
+ variant: "ghost",
181
+ size: "sm",
182
+ "aria-expanded": i,
183
+ prefix: i ? X : Q,
184
+ onClick: () => k((b) => !b),
185
+ children: i ? "Show less" : `Show all ${h.length} lines`
186
+ })
187
+ }) : null
188
+ ]
189
+ });
190
+ }
191
+ pe.displayName = "CodeBlock";
192
+ export {
193
+ oe as n,
194
+ pe as t
195
+ };
196
+
197
+ //# sourceMappingURL=code-block-BuDIo8Q0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-block-BuDIo8Q0.js","names":[],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconTextWrap.mjs","../../src/components/code-block/tokenize-json.ts","../../src/components/code-block/code-block.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\": \"M4 6l16 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M4 18l5 0\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M4 12h13a3 3 0 0 1 0 6h-4l2 -2m0 4l-2 -2\", \"key\": \"svg-2\" }]];\nconst IconTextWrap = createReactComponent(\"outline\", \"text-wrap\", \"TextWrap\", __iconNode);\n\nexport { __iconNode, IconTextWrap as default };\n//# sourceMappingURL=IconTextWrap.mjs.map\n","/**\n * A tokenizer for JSON, and nothing else: keys, strings, numbers, the\n * three keywords, and punctuation. Runs one line at a time (a JSON\n * string never spans lines) so a panel can show its first N lines and\n * stop. Text that isn't JSON comes back as it is, in plain tokens.\n */\n\nexport type JsonTokenType =\n \"key\" | \"string\" | \"number\" | \"keyword\" | \"punctuation\" | \"plain\";\n\nexport interface JsonToken {\n type: JsonTokenType;\n text: string;\n}\n\n// One pass, left to right: a string (a key when a colon follows), a\n// number, a keyword, a bracket or a comma. Anything between is plain.\nconst TOKEN =\n /(\"(?:[^\"\\\\]|\\\\.)*\")(\\s*:)?|(-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)|\\b(true|false|null)\\b|([{}[\\]:,])/g;\n\nexport function tokenizeJson(line: string): JsonToken[] {\n const tokens: JsonToken[] = [];\n let last = 0;\n TOKEN.lastIndex = 0;\n for (let match = TOKEN.exec(line); match != null; match = TOKEN.exec(line)) {\n if (match.index > last) {\n tokens.push({ type: \"plain\", text: line.slice(last, match.index) });\n }\n const [, string, colon, number, keyword, punctuation] = match;\n if (string != null) {\n tokens.push({ type: colon != null ? \"key\" : \"string\", text: string });\n if (colon != null) tokens.push({ type: \"punctuation\", text: colon });\n } else if (number != null) {\n tokens.push({ type: \"number\", text: number });\n } else if (keyword != null) {\n tokens.push({ type: \"keyword\", text: keyword });\n } else if (punctuation != null) {\n tokens.push({ type: \"punctuation\", text: punctuation });\n }\n last = match.index + match[0].length;\n }\n if (last < line.length) {\n tokens.push({ type: \"plain\", text: line.slice(last) });\n }\n return tokens;\n}\n","import {\n useMemo,\n useState,\n type ComponentProps,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport {\n IconArrowsMaximize,\n IconArrowsMinimize,\n IconChevronDown,\n IconChevronUp,\n IconTextWrap,\n} from \"@tabler/icons-react\";\nimport { Button } from \"../button\";\nimport { CopyButton } from \"../copy-button\";\nimport { ScrollArea } from \"../scroll-area\";\nimport { Toggle } from \"../toggle\";\nimport { Tooltip } from \"../tooltip\";\nimport { cn } from \"../../utils/cn\";\nimport { tokenizeJson, type JsonTokenType } from \"./tokenize-json\";\n\n/**\n * Code Block — a read-only panel for a request body, a response, an\n * event's JSON. Mono text on the code surface, a title row with expand,\n * wrap, and copy controls. Past `maxLines` the body either scrolls\n * inside that height (`overflow=\"scroll\"`, the default) or folds with a\n * footer button (`overflow=\"expand\"`).\n *\n * Design notes:\n * - Wide lines scroll sideways inside the panel; the page never does.\n * Wrapping is a toggle (`wrap` / `defaultWrap`), off by default so a\n * body reads the way it was sent.\n * - `language=\"json\"` colors keys, strings, numbers, and keywords with a\n * built-in tokenizer — no highlighter library at runtime — on the\n * `--color-pho-code-*` tokens, which carry light and dark.\n * - A body that isn't a string (an object) is pretty-printed as JSON.\n */\n\nexport type CodeBlockLanguage = \"json\" | \"text\";\n\nexport type CodeBlockOverflow = \"scroll\" | \"expand\";\n\nconst TOKEN_CLASS: Record<JsonTokenType, string | undefined> = {\n key: \"text-pho-code-key\",\n string: \"text-pho-code-string\",\n number: \"text-pho-code-number\",\n keyword: \"text-pho-code-keyword\",\n punctuation: \"text-pho-code-punctuation\",\n plain: undefined,\n};\n\n/** The panel's chrome — the card hairline around the code surface. */\nconst CODE_BLOCK_SURFACE =\n \"rounded-base border border-pho-secondary bg-pho-code-bg text-pho-code-fg\";\n\n/** One code line is `leading-5` / `min-h-5`; the pre pads `py-3`. */\nconst LINE_H = \"1.25rem\";\nconst PAD_Y = \"0.75rem\";\n\nexport interface CodeBlockProps extends Omit<\n ComponentProps<\"div\">,\n \"title\" | \"children\"\n> {\n /** The text. An object is pretty-printed as JSON (two-space indent). */\n code?: string | object | null;\n /** `json` colors the text; `text` leaves it plain. @default \"text\" */\n language?: CodeBlockLanguage;\n /** The title row's words — \"Request body\", \"Response\". */\n title?: ReactNode;\n /** Past this many lines the panel folds or clips. @default 30 */\n maxLines?: number;\n /**\n * How a long body is shown past `maxLines`. `scroll` clips to that\n * height and scrolls inside, with an expand toggle in the title row.\n * `expand` folds and shows a footer button.\n * @default \"scroll\"\n */\n overflow?: CodeBlockOverflow;\n /** Wrap long lines (controlled). */\n wrap?: boolean;\n /** Wrap long lines at first (uncontrolled). @default false */\n defaultWrap?: boolean;\n onWrapChange?: (wrap: boolean) => void;\n /** The expand toggle in the title row when `overflow` is `scroll`. @default true */\n expandToggle?: boolean;\n /** The wrap toggle in the title row. @default true */\n wrapToggle?: boolean;\n /**\n * A gutter of line numbers. Off by default; turn on for a long\n * payload (about twenty lines or more).\n * @default false\n */\n lineNumbers?: boolean;\n /** The copy control in the title row. @default true */\n copy?: boolean;\n /** What the panel says with no code. @default \"Nothing to show.\" */\n empty?: ReactNode;\n /** More controls in the title row, before the built-in ones. */\n actions?: ReactNode;\n ref?: Ref<HTMLDivElement>;\n}\n\nfunction toText(code: CodeBlockProps[\"code\"]): string {\n if (code == null) return \"\";\n if (typeof code === \"string\") return code;\n try {\n return JSON.stringify(code, null, 2) ?? \"\";\n } catch {\n return String(code);\n }\n}\n\nfunction HeaderToggle({\n label,\n pressed,\n onPressedChange,\n children,\n}: {\n label: string;\n pressed: boolean;\n onPressedChange: (next: boolean) => void;\n children: ReactNode;\n}) {\n return (\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Toggle\n size=\"sm\"\n pressed={pressed}\n onPressedChange={onPressedChange}\n aria-label={label}\n className=\"rounded-sm\"\n >\n {children}\n </Toggle>\n }\n />\n <Tooltip.Portal>\n <Tooltip.Positioner>\n <Tooltip.Popup>{label}</Tooltip.Popup>\n </Tooltip.Positioner>\n </Tooltip.Portal>\n </Tooltip.Root>\n );\n}\n\nfunction CodeLines({\n lines,\n language,\n lineNumbers,\n digits,\n wrap,\n}: {\n lines: string[];\n language: CodeBlockLanguage;\n lineNumbers: boolean;\n digits: number;\n wrap: boolean;\n}) {\n return (\n <code>\n {lines.map((line, index) => (\n <span\n key={index}\n data-line=\"\"\n className={cn(\n \"min-h-5\",\n lineNumbers ? \"flex items-start\" : \"block\",\n lineNumbers && !wrap && \"min-w-max\",\n )}\n >\n {lineNumbers ? (\n <span\n data-line-number=\"\"\n aria-hidden\n className=\"text-pho-placeholder bg-pho-code-bg sticky left-0 z-[1] box-content shrink-0 pr-3 pl-3 text-right font-mono text-xs leading-5 tabular-nums select-none\"\n style={{ width: `${digits}ch` }}\n >\n {index + 1}\n </span>\n ) : null}\n <span className={lineNumbers ? \"min-w-0 flex-1\" : undefined}>\n {language === \"json\"\n ? tokenizeJson(line).map((token, at) =>\n token.type === \"plain\" ? (\n token.text\n ) : (\n <span key={at} className={TOKEN_CLASS[token.type]}>\n {token.text}\n </span>\n ),\n )\n : line}\n </span>\n </span>\n ))}\n </code>\n );\n}\n\nexport function CodeBlock({\n code,\n language = \"text\",\n title,\n maxLines = 30,\n overflow = \"scroll\",\n wrap: wrapProp,\n defaultWrap = false,\n onWrapChange,\n expandToggle = true,\n wrapToggle = true,\n lineNumbers = false,\n copy = true,\n empty = \"Nothing to show.\",\n actions,\n className,\n ...props\n}: CodeBlockProps) {\n const text = useMemo(() => toText(code), [code]);\n const lines = useMemo(() => text.split(\"\\n\"), [text]);\n const [ownWrap, setOwnWrap] = useState(defaultWrap);\n const wrap = wrapProp ?? ownWrap;\n const setWrap = (next: boolean) => {\n if (wrapProp == null) setOwnWrap(next);\n onWrapChange?.(next);\n };\n const [expanded, setExpanded] = useState(false);\n const folds = lines.length > maxLines;\n const scrolling = overflow === \"scroll\" && folds && !expanded;\n const shown =\n overflow === \"expand\" && folds && !expanded\n ? lines.slice(0, maxLines)\n : lines;\n const isEmpty = text === \"\";\n const showExpandToggle =\n overflow === \"scroll\" && expandToggle && folds && !isEmpty;\n const showWrapToggle = wrapToggle && !isEmpty;\n const showCopy = copy && !isEmpty;\n const hasHeader =\n title != null ||\n actions != null ||\n showExpandToggle ||\n showWrapToggle ||\n showCopy;\n const copyLabel = typeof title === \"string\" ? title.toLowerCase() : \"code\";\n const scrollLabel = typeof title === \"string\" ? title : \"Code\";\n const expandLabel = expanded\n ? `Collapse to ${maxLines} lines`\n : `Show all ${lines.length} lines`;\n const lineNoDigits = String(Math.max(lines.length, 1)).length;\n const body = (\n <pre\n className={cn(\n \"m-0 min-w-0 py-3 font-mono text-xs leading-5\",\n lineNumbers ? \"pr-3 pl-0\" : \"px-3\",\n wrap\n ? \"[overflow-wrap:anywhere] whitespace-pre-wrap\"\n : scrolling\n ? \"whitespace-pre\"\n : \"overflow-x-auto whitespace-pre\",\n )}\n >\n <CodeLines\n lines={shown}\n language={language}\n lineNumbers={lineNumbers}\n digits={lineNoDigits}\n wrap={wrap}\n />\n </pre>\n );\n return (\n <div\n data-code-block=\"\"\n data-language={language}\n data-overflow={overflow}\n className={cn(CODE_BLOCK_SURFACE, \"flex min-w-0 flex-col\", className)}\n {...props}\n >\n {hasHeader ? (\n <div className=\"border-pho-secondary flex min-h-10 items-center gap-2 border-b py-1 pr-1.5 pl-3\">\n <div className=\"text-pho-secondary min-w-0 flex-1 truncate text-xs font-medium\">\n {title}\n </div>\n {actions}\n <Tooltip.Provider>\n {showExpandToggle ? (\n <HeaderToggle\n label={expandLabel}\n pressed={expanded}\n onPressedChange={setExpanded}\n >\n {expanded ? (\n <IconArrowsMinimize aria-hidden />\n ) : (\n <IconArrowsMaximize aria-hidden />\n )}\n </HeaderToggle>\n ) : null}\n {showWrapToggle ? (\n <HeaderToggle\n label=\"Wrap long lines\"\n pressed={wrap}\n onPressedChange={setWrap}\n >\n <IconTextWrap aria-hidden />\n </HeaderToggle>\n ) : null}\n </Tooltip.Provider>\n {showCopy ? (\n <CopyButton value={text} label={copyLabel} size=\"md\" />\n ) : null}\n </div>\n ) : null}\n {isEmpty ? (\n <p className=\"text-pho-description m-0 px-3 py-3 text-base\">{empty}</p>\n ) : scrolling ? (\n <section className=\"min-w-0\">\n <ScrollArea.Root\n fade={false}\n data-code-scroll=\"\"\n className=\"min-w-0 rounded-b-[inherit]\"\n style={{ height: `calc(${maxLines} * ${LINE_H} + ${PAD_Y} * 2)` }}\n >\n <ScrollArea.Viewport tabIndex={0} aria-label={scrollLabel}>\n <ScrollArea.Content>{body}</ScrollArea.Content>\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n {wrap ? null : (\n <ScrollArea.Scrollbar orientation=\"horizontal\">\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n )}\n </ScrollArea.Root>\n </section>\n ) : (\n body\n )}\n {overflow === \"expand\" && folds ? (\n <div className=\"border-pho-secondary flex items-center border-t px-1.5 py-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-expanded={expanded}\n prefix={expanded ? IconChevronUp : IconChevronDown}\n onClick={() => setExpanded((prev) => !prev)}\n >\n {expanded ? \"Show less\" : `Show all ${lines.length} lines`}\n </Button>\n </div>\n ) : null}\n </div>\n );\n}\n\nCodeBlock.displayName = \"CodeBlock\";\n"],"x_google_ignoreList":[0],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import { t as r } from "./cn-ChIgwEl3.js";
3
+ import "react";
4
+ import { jsx as i } from "react/jsx-runtime";
5
+ import { Collapsible as o } from "@base-ui/react/collapsible";
6
+ var n = o.Root;
7
+ function a({ className: e, ...t }) {
8
+ return /* @__PURE__ */ i(o.Trigger, {
9
+ className: r("outline-pho-brand text-pho-secondary hover:text-pho-secondary-hover flex w-full cursor-pointer items-center justify-between gap-2 rounded-sm text-base font-medium transition focus-visible:outline-2 focus-visible:outline-offset-2", "[&>svg]:size-4 [&>svg]:transition-transform [&>svg]:duration-150 data-[panel-open]:[&>svg]:rotate-180", e),
10
+ ...t
11
+ });
12
+ }
13
+ function s({ className: e, ...t }) {
14
+ return /* @__PURE__ */ i(o.Panel, {
15
+ className: r("h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out", "data-[ending-style]:h-0 data-[starting-style]:h-0", e),
16
+ ...t
17
+ });
18
+ }
19
+ var d = {
20
+ Root: n,
21
+ Trigger: a,
22
+ Panel: s
23
+ };
24
+ export {
25
+ d as t
26
+ };
27
+
28
+ //# sourceMappingURL=collapsible-if7ncPbI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collapsible-if7ncPbI.js","names":[],"sources":["../../src/components/collapsible/collapsible.tsx"],"sourcesContent":["import { type ComponentProps, type ElementType } from \"react\";\nimport { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\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 Root = BaseCollapsible.Root;\n\nfunction Trigger({\n className,\n ...props\n}: StyledProps<typeof BaseCollapsible.Trigger>) {\n return (\n <BaseCollapsible.Trigger\n className={cn(\n \"outline-pho-brand text-pho-secondary hover:text-pho-secondary-hover flex w-full cursor-pointer items-center justify-between gap-2 rounded-sm text-base font-medium transition focus-visible:outline-2 focus-visible:outline-offset-2\",\n \"[&>svg]:size-4 [&>svg]:transition-transform [&>svg]:duration-150 data-[panel-open]:[&>svg]:rotate-180\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Panel({\n className,\n ...props\n}: StyledProps<typeof BaseCollapsible.Panel>) {\n return (\n <BaseCollapsible.Panel\n className={cn(\n \"h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out\",\n \"data-[ending-style]:h-0 data-[starting-style]:h-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Show/hide a region of content, built on Base UI `Collapsible` with a smooth\n * height animation. Control with `open` / `onOpenChange` or leave uncontrolled\n * via `defaultOpen`. For several sections where one expands at a time, use\n * `Accordion`.\n */\nexport const Collapsible = { Root, Trigger, Panel };\n"],"mappings":";;;;;AAYA,IAAM,IAAO,EAAgB;AAE7B,SAAS,EAAQ,EACf,WAAA,GACA,GAAG,EAAA,GAC2C;AAC9C,SACE,gBAAA,EAAC,EAAgB,SAAjB;AAAA,IACE,WAAW,EACT,wOACA,yGACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAM,EACb,WAAA,GACA,GAAG,EAAA,GACyC;AAC5C,SACE,gBAAA,EAAC,EAAgB,OAAjB;AAAA,IACE,WAAW,EACT,iGACA,qDACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAQA,IAAa,IAAc;AAAA,EAAE,MAAA;AAAA,EAAM,SAAA;AAAA,EAAS,OAAA;AAAM"}
@@ -4,7 +4,7 @@ import { SPRING_SETTLE as z } from "../motion.js";
4
4
  import { t as C } from "./IconArrowUpRight-DGgKzQwV.js";
5
5
  import { t as M } from "./IconChevronLeft-CSWMKQ4C.js";
6
6
  import { t as O } from "./animated-height-CCO-Ocoz.js";
7
- import { t as d } from "./dialog-BxKACOj5.js";
7
+ import { t as d } from "./dialog-BwfUFn6B.js";
8
8
  import { useEffect as T, useId as D, useLayoutEffect as V, useRef as $ } from "react";
9
9
  import { Fragment as w, jsx as t, jsxs as u } from "react/jsx-runtime";
10
10
  import { LayoutGroup as A, motion as x, useReducedMotion as F } from "motion/react";
@@ -189,4 +189,4 @@ export {
189
189
  ue as t
190
190
  };
191
191
 
192
- //# sourceMappingURL=command-Ck8IAgV7.js.map
192
+ //# sourceMappingURL=command-CTYrSz9a.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-Ck8IAgV7.js","names":[],"sources":["../../src/components/command/command.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { IconArrowUpRight, IconChevronLeft } from \"@tabler/icons-react\";\nimport { SPRING_SETTLE } from \"../../motion\";\nimport { Command as CommandPrimitive, useCommandState } from \"cmdk\";\nimport { LayoutGroup, motion, useReducedMotion } from \"motion/react\";\nimport { AnimatedHeight } from \"../../utils/animated-height\";\nimport { cn } from \"../../utils/cn\";\nimport { Dialog as PhoDialog } from \"../dialog\";\n\n/**\n * Spring for row moves (FLIP / shared-layout) — same feel as\n * `AnimatedHeight`: quick and critically damped, so rows glide to their new\n * slot without overshooting into neighbours.\n */\nconst ROW_MOVE_SPRING = SPRING_SETTLE;\n\nfunction Root({\n // Filtering is yours by default: filter in render (state above the\n // palette) so the rows' FLIP diff can glide survivors to their slots.\n // cmdk's built-in matcher reorders DOM imperatively — invisible to the\n // layout pass — so it is opt-in: pass `shouldFilter` to hand matching\n // and ranking back to cmdk at the cost of the animation.\n shouldFilter = false,\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive>) {\n // Namespace row layoutIds per palette instance — the docs page mounts the\n // inline demo and the dialog demo at once, with identical item values.\n const layoutNamespace = useId();\n return (\n <CommandPrimitive\n className={cn(\n \"bg-pho-primary text-pho-primary flex w-full flex-col overflow-hidden outline-none\",\n className,\n )}\n shouldFilter={shouldFilter}\n {...props}\n >\n <LayoutGroup id={layoutNamespace}>{children}</LayoutGroup>\n </CommandPrimitive>\n );\n}\n\n/**\n * The input row — a bottom hairline separates it from the list. Position\n * leading icons absolutely and pad the input (`pl-9`), mirroring\n * `Autocomplete.InputGroup`.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"border-pho-secondary relative flex items-center border-b\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** SSR-safe layout effect (same pattern cmdk uses internally). */\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nfunction Input({\n className,\n value,\n ref: consumerRef,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Input>) {\n const inputRef = useRef<HTMLInputElement>(null);\n const search = useCommandState((state) => state.search);\n\n // cmdk stays uncontrolled here on purpose. Its controlled path syncs the\n // `value` prop into the search store through a passive effect — one painted\n // frame late — so on that stale frame the old row is still \"selected\" while\n // the list has already reflowed, and the selection pill visibly rides it\n // before snapping to the re-selected first row. Uncontrolled keystrokes\n // update search + first-row selection synchronously (pre-paint), killing\n // that frame in both directions (typing and clearing).\n //\n // The consumer-facing API is still controlled: external `value` changes\n // (programmatic reset, initial query) are replayed through the native input\n // path below so store, display, and selection take the same sync route.\n useIsomorphicLayoutEffect(() => {\n const input = inputRef.current;\n if (value == null || input == null || value === search) return;\n const setNativeValue = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n setNativeValue?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }, [value, search]);\n\n return (\n <CommandPrimitive.Input\n className={cn(\n // Borderless inside the palette surface — the InputGroup hairline\n // carries the edge. display-xs (18px) keeps iOS from zooming in.\n \"text-pho-primary placeholder:text-pho-placeholder text-display-xs w-full bg-transparent px-3 py-3 outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={(node) => {\n inputRef.current = node;\n assignRef(consumerRef, node);\n }}\n />\n );\n}\n\nfunction List({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive.List>) {\n return (\n // Same spring as the onboarding / invite Card shell — list height glides\n // when idle ↔ search (or filter) changes instead of jumping.\n <AnimatedHeight>\n {/* The scroller is a motion element with layoutScroll so the rows'\n FLIP projections account for its scroll offset — without it,\n scrolling reads as a layout change and every row glides to\n compensate. scroll-py keeps a breath above and below the row\n being scrolled into view. */}\n <motion.div\n layoutScroll\n className=\"max-h-[min(24rem,60vh)] scroll-py-1 overflow-y-auto overscroll-contain\"\n >\n <CommandPrimitive.List\n className={cn(\"relative isolate p-1\", className)}\n {...props}\n >\n {children}\n </CommandPrimitive.List>\n </motion.div>\n </AnimatedHeight>\n );\n}\n\nfunction Empty({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n className={cn(\n \"text-pho-description px-2.5 py-6 text-center text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Group({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n className={cn(\n // cmdk renders the `heading` prop in a [cmdk-group-heading] wrapper —\n // typography mirrors `Autocomplete.GroupLabel`.\n \"[&_[cmdk-group-heading]]:text-pho-secondary [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Row layout mode:\n * - `item` / `subitem` / `subsubitem` — idle hierarchy (icon column + indent)\n * - `result` — flat search hit (breadcrumb + trailing scope)\n */\nexport type CommandItemLevel = \"item\" | \"subitem\" | \"subsubitem\" | \"result\";\n\ntype ItemPrimitiveProps = ComponentProps<typeof CommandPrimitive.Item>;\n\nexport interface CommandItemProps extends Omit<\n ItemPrimitiveProps,\n \"children\" | \"title\"\n> {\n /**\n * Row depth / mode in the palette:\n * - `item` — page / top destination (icon + title)\n * - `subitem` — section under an item (label aligns with the item title)\n * - `subsubitem` — row under a section (one step deeper)\n * - `result` — flat search hit (`title` + `path` crumbs + `scope`)\n */\n level?: CommandItemLevel;\n /**\n * Leading glyph. On idle `item` rows (and reserved for sub-levels). On\n * `result` rows, pass the resolved icon (self → parent → grandparent).\n */\n icon?: ReactNode;\n /**\n * When `level=\"result\"`, force the icon column so labels align across the\n * list even if this row's `icon` is empty. Set true when any sibling result\n * has an icon; omit when the whole result set is icon-less.\n */\n iconSlot?: boolean;\n /** Primary label. Prefer this over free-form children for the shared layout. */\n title?: ReactNode;\n /**\n * Ancestors after `title` for `level=\"result\"` — parent → page\n * (e.g. `[\"Agent profile\", \"Settings\"]` → `Name < Agent profile < Settings`).\n */\n path?: ReactNode[];\n /**\n * Trailing scope for `level=\"result\"` — `Project` vs `Personal`, not a nav group.\n */\n scope?: ReactNode;\n /** Shows a trailing external-link glyph (opens outside the app). */\n external?: boolean;\n /**\n * Free-form content. When `title` is set, rendered after the label stack.\n * When `title` is omitted, becomes the row body (legacy / simple items).\n */\n children?: ReactNode;\n}\n\n/** Leading icon column — `size-4`, secondary ink. */\nfunction ItemIcon({ className, ...props }: ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"text-pho-secondary flex size-4 shrink-0 items-center justify-center [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Primary label — medium + primary ink on `item` rows. */\nfunction ItemTitle({\n className,\n level = \"item\",\n ...props\n}: ComponentProps<\"span\"> & { level?: CommandItemLevel }) {\n return (\n <span\n className={cn(\n \"text-md block truncate\",\n level === \"item\" && \"text-pho-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * One selectable row. Idle palettes use `level` + `icon` / `title`\n * (item → subitem → subsubitem). Searching uses `level=\"result\"` with `path`\n * crumbs and a trailing `scope` (Project / Personal). No description line —\n * match via `keywords` / aliases instead.\n */\nfunction ExternalGlyph() {\n return (\n <IconArrowUpRight\n aria-hidden\n className=\"text-pho-description size-4 shrink-0\"\n />\n );\n}\n\nfunction Item({\n className,\n level = \"item\",\n icon,\n iconSlot,\n title,\n path,\n scope,\n external,\n children,\n value,\n ...props\n}: CommandItemProps) {\n const reduceMotion = useReducedMotion();\n // cmdk registers `value.trim()` and exposes the selected one as\n // `state.value` — mirrors cmdk's own `data-selected` computation.\n const trimmedValue = typeof value === \"string\" ? value.trim() : \"\";\n const selectedValue = useCommandState((state) => state.value);\n const isSelected = trimmedValue !== \"\" && selectedValue === trimmedValue;\n const structured = title != null;\n const isResult = level === \"result\";\n // Reserve the icon column when the row has an icon, or when the list asks\n // for alignment (`iconSlot`) even if this row's glyph is empty.\n const showResultIcon = isResult && (icon != null || iconSlot);\n\n const row = (\n <CommandPrimitive.Item\n data-level={level}\n value={value}\n className={cn(\n \"text-pho-secondary flex cursor-pointer items-center gap-2 rounded-[calc(var(--radius-base)-4px)] py-2 pr-2.5 text-base outline-none select-none\",\n // subsubitem steps in; item/subitem share the base gutter.\n level === \"subsubitem\" ? \"pl-6\" : \"pl-2\",\n // Secondary at rest; selection lifts to primary ink (Menu idiom).\n // The wash lands with it instantly — stepping through rows is a\n // snap, not a flight.\n \"data-[selected=true]:text-pho-primary data-[selected=true]:bg-pho-ghost-hover\",\n \"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n >\n {structured && isResult ? (\n <>\n {showResultIcon ? (\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n ) : null}\n {/* Same text-md line box as idle ItemTitle so row height matches (36px). */}\n <span className=\"text-md flex min-w-0 flex-1 items-center gap-1 overflow-hidden\">\n <span className=\"text-pho-primary truncate\">{title}</span>\n {(path ?? []).map((segment, index) => (\n <span\n key={index}\n className=\"text-pho-description flex shrink-0 items-center gap-0.5\"\n >\n <IconChevronLeft aria-hidden className=\"size-4 shrink-0\" />\n {segment}\n </span>\n ))}\n </span>\n {scope != null && scope !== \"\" ? (\n <span className=\"text-pho-description shrink-0 text-xs\">\n {scope}\n </span>\n ) : null}\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : structured ? (\n <>\n {/* Icon column always reserved so subitem labels share the item title edge. */}\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n <span className=\"min-w-0 flex-1\">\n <ItemTitle level={level}>{title}</ItemTitle>\n </span>\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : (\n children\n )}\n </CommandPrimitive.Item>\n );\n\n if (reduceMotion) return row;\n\n return (\n // FLIP wrapper: rows that stay mounted glide when neighbours enter or\n // leave, and a row remounting elsewhere with the same `value` (idle group\n // ↔ flat search result) inherits the old bounds via its layoutId and\n // slides to the new slot — the iOS list-diff feel. Rows without a match\n // simply appear / disappear so the whole list never swarms.\n //\n // The selected row is the exception: it skips the travel and appears at\n // its final slot immediately, so the selection wash is never sitting on\n // empty space waiting for its row to fly in.\n <motion.div\n layout=\"position\"\n layoutId={typeof value === \"string\" ? value : undefined}\n initial={false}\n transition={isSelected ? { duration: 0 } : ROW_MOVE_SPRING}\n >\n {row}\n </motion.div>\n );\n}\n\nfunction Separator({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n className={cn(\n \"-mx-1 my-1 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Loading({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Loading>) {\n return (\n <CommandPrimitive.Loading\n className={cn(\"text-pho-description px-2.5 py-1.5 text-base\", className)}\n {...props}\n />\n );\n}\n\ntype DialogRootProps = ComponentProps<typeof PhoDialog.Root>;\n\ninterface CommandDialogProps extends ComponentProps<typeof CommandPrimitive> {\n /** Controlled dialog state — pass straight through to `Dialog.Root`. */\n open?: DialogRootProps[\"open\"];\n onOpenChange?: DialogRootProps[\"onOpenChange\"];\n /** Accessible name for the palette (dialog and command menu). */\n label?: string;\n /** Extra classes for the dialog panel (not the command root). */\n className?: string;\n}\n\n/**\n * A command palette in a modal — Pho's `Dialog` overlay (Base UI) around a\n * `Command.Root`, raised above center. We deliberately skip cmdk's own\n * `Command.Dialog` (Radix) so overlays stay on one primitive stack.\n *\n * List height springs via `AnimatedHeight` (same feel as the Card shell on\n * onboarding / invite) — the input row stays put while results resize.\n */\nfunction Dialog({\n open,\n onOpenChange,\n label,\n className,\n children,\n ...props\n}: CommandDialogProps) {\n return (\n <PhoDialog.Root open={open} onOpenChange={onOpenChange}>\n <PhoDialog.Portal>\n <PhoDialog.Backdrop />\n <PhoDialog.Popup\n aria-label={label}\n // Palette sits above center so the list grows downward from a\n // stable top edge instead of jumping around it.\n className={cn(\n \"top-[max(4rem,18vh)] max-w-xl translate-y-0 overflow-hidden p-0\",\n className,\n )}\n >\n {/* The popup is position: fixed; layout animations inside a fixed\n element need a layoutRoot to project against, or their\n measurements drift with the page scroll. */}\n <motion.div layoutRoot>\n <Root label={label} {...props}>\n {children}\n </Root>\n </motion.div>\n </PhoDialog.Popup>\n </PhoDialog.Portal>\n </PhoDialog.Root>\n );\n}\n\n/**\n * Command menu built on `cmdk` — a filterable list of actions driven from a\n * single input, keyboard-first. Compose inline (`Command.Root`) or as a\n * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay).\n * Filtering is yours by default — filter in render so the rows' diff can\n * glide; pass `shouldFilter` to hand matching and ranking to cmdk (its\n * imperative reorder skips the animation).\n *\n * Rows share one layout via `Command.Item` `level` — idle\n * `item` → `subitem` → `subsubitem`, or flat `result` while searching.\n */\nexport const Command = {\n Root,\n InputGroup,\n Input,\n List,\n Empty,\n Group,\n Item,\n ItemIcon,\n ItemTitle,\n Separator,\n Loading,\n Dialog,\n};\n\n/** Re-export of cmdk's state selector hook (search, value, filtered counts). */\nexport { useCommandState };\n"],"mappings":"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"}
1
+ {"version":3,"file":"command-CTYrSz9a.js","names":[],"sources":["../../src/components/command/command.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { IconArrowUpRight, IconChevronLeft } from \"@tabler/icons-react\";\nimport { SPRING_SETTLE } from \"../../motion\";\nimport { Command as CommandPrimitive, useCommandState } from \"cmdk\";\nimport { LayoutGroup, motion, useReducedMotion } from \"motion/react\";\nimport { AnimatedHeight } from \"../../utils/animated-height\";\nimport { cn } from \"../../utils/cn\";\nimport { Dialog as PhoDialog } from \"../dialog\";\n\n/**\n * Spring for row moves (FLIP / shared-layout) — same feel as\n * `AnimatedHeight`: quick and critically damped, so rows glide to their new\n * slot without overshooting into neighbours.\n */\nconst ROW_MOVE_SPRING = SPRING_SETTLE;\n\nfunction Root({\n // Filtering is yours by default: filter in render (state above the\n // palette) so the rows' FLIP diff can glide survivors to their slots.\n // cmdk's built-in matcher reorders DOM imperatively — invisible to the\n // layout pass — so it is opt-in: pass `shouldFilter` to hand matching\n // and ranking back to cmdk at the cost of the animation.\n shouldFilter = false,\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive>) {\n // Namespace row layoutIds per palette instance — the docs page mounts the\n // inline demo and the dialog demo at once, with identical item values.\n const layoutNamespace = useId();\n return (\n <CommandPrimitive\n className={cn(\n \"bg-pho-primary text-pho-primary flex w-full flex-col overflow-hidden outline-none\",\n className,\n )}\n shouldFilter={shouldFilter}\n {...props}\n >\n <LayoutGroup id={layoutNamespace}>{children}</LayoutGroup>\n </CommandPrimitive>\n );\n}\n\n/**\n * The input row — a bottom hairline separates it from the list. Position\n * leading icons absolutely and pad the input (`pl-9`), mirroring\n * `Autocomplete.InputGroup`.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"border-pho-secondary relative flex items-center border-b\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** SSR-safe layout effect (same pattern cmdk uses internally). */\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nfunction Input({\n className,\n value,\n ref: consumerRef,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Input>) {\n const inputRef = useRef<HTMLInputElement>(null);\n const search = useCommandState((state) => state.search);\n\n // cmdk stays uncontrolled here on purpose. Its controlled path syncs the\n // `value` prop into the search store through a passive effect — one painted\n // frame late — so on that stale frame the old row is still \"selected\" while\n // the list has already reflowed, and the selection pill visibly rides it\n // before snapping to the re-selected first row. Uncontrolled keystrokes\n // update search + first-row selection synchronously (pre-paint), killing\n // that frame in both directions (typing and clearing).\n //\n // The consumer-facing API is still controlled: external `value` changes\n // (programmatic reset, initial query) are replayed through the native input\n // path below so store, display, and selection take the same sync route.\n useIsomorphicLayoutEffect(() => {\n const input = inputRef.current;\n if (value == null || input == null || value === search) return;\n const setNativeValue = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n setNativeValue?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }, [value, search]);\n\n return (\n <CommandPrimitive.Input\n className={cn(\n // Borderless inside the palette surface — the InputGroup hairline\n // carries the edge. display-xs (18px) keeps iOS from zooming in.\n \"text-pho-primary placeholder:text-pho-placeholder text-display-xs w-full bg-transparent px-3 py-3 outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={(node) => {\n inputRef.current = node;\n assignRef(consumerRef, node);\n }}\n />\n );\n}\n\nfunction List({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive.List>) {\n return (\n // Same spring as the onboarding / invite Card shell — list height glides\n // when idle ↔ search (or filter) changes instead of jumping.\n <AnimatedHeight>\n {/* The scroller is a motion element with layoutScroll so the rows'\n FLIP projections account for its scroll offset — without it,\n scrolling reads as a layout change and every row glides to\n compensate. scroll-py keeps a breath above and below the row\n being scrolled into view. */}\n <motion.div\n layoutScroll\n className=\"max-h-[min(24rem,60vh)] scroll-py-1 overflow-y-auto overscroll-contain\"\n >\n <CommandPrimitive.List\n className={cn(\"relative isolate p-1\", className)}\n {...props}\n >\n {children}\n </CommandPrimitive.List>\n </motion.div>\n </AnimatedHeight>\n );\n}\n\nfunction Empty({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n className={cn(\n \"text-pho-description px-2.5 py-6 text-center text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Group({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n className={cn(\n // cmdk renders the `heading` prop in a [cmdk-group-heading] wrapper —\n // typography mirrors `Autocomplete.GroupLabel`.\n \"[&_[cmdk-group-heading]]:text-pho-secondary [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Row layout mode:\n * - `item` / `subitem` / `subsubitem` — idle hierarchy (icon column + indent)\n * - `result` — flat search hit (breadcrumb + trailing scope)\n */\nexport type CommandItemLevel = \"item\" | \"subitem\" | \"subsubitem\" | \"result\";\n\ntype ItemPrimitiveProps = ComponentProps<typeof CommandPrimitive.Item>;\n\nexport interface CommandItemProps extends Omit<\n ItemPrimitiveProps,\n \"children\" | \"title\"\n> {\n /**\n * Row depth / mode in the palette:\n * - `item` — page / top destination (icon + title)\n * - `subitem` — section under an item (label aligns with the item title)\n * - `subsubitem` — row under a section (one step deeper)\n * - `result` — flat search hit (`title` + `path` crumbs + `scope`)\n */\n level?: CommandItemLevel;\n /**\n * Leading glyph. On idle `item` rows (and reserved for sub-levels). On\n * `result` rows, pass the resolved icon (self → parent → grandparent).\n */\n icon?: ReactNode;\n /**\n * When `level=\"result\"`, force the icon column so labels align across the\n * list even if this row's `icon` is empty. Set true when any sibling result\n * has an icon; omit when the whole result set is icon-less.\n */\n iconSlot?: boolean;\n /** Primary label. Prefer this over free-form children for the shared layout. */\n title?: ReactNode;\n /**\n * Ancestors after `title` for `level=\"result\"` — parent → page\n * (e.g. `[\"Agent profile\", \"Settings\"]` → `Name < Agent profile < Settings`).\n */\n path?: ReactNode[];\n /**\n * Trailing scope for `level=\"result\"` — `Project` vs `Personal`, not a nav group.\n */\n scope?: ReactNode;\n /** Shows a trailing external-link glyph (opens outside the app). */\n external?: boolean;\n /**\n * Free-form content. When `title` is set, rendered after the label stack.\n * When `title` is omitted, becomes the row body (legacy / simple items).\n */\n children?: ReactNode;\n}\n\n/** Leading icon column — `size-4`, secondary ink. */\nfunction ItemIcon({ className, ...props }: ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"text-pho-secondary flex size-4 shrink-0 items-center justify-center [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Primary label — medium + primary ink on `item` rows. */\nfunction ItemTitle({\n className,\n level = \"item\",\n ...props\n}: ComponentProps<\"span\"> & { level?: CommandItemLevel }) {\n return (\n <span\n className={cn(\n \"text-md block truncate\",\n level === \"item\" && \"text-pho-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * One selectable row. Idle palettes use `level` + `icon` / `title`\n * (item → subitem → subsubitem). Searching uses `level=\"result\"` with `path`\n * crumbs and a trailing `scope` (Project / Personal). No description line —\n * match via `keywords` / aliases instead.\n */\nfunction ExternalGlyph() {\n return (\n <IconArrowUpRight\n aria-hidden\n className=\"text-pho-description size-4 shrink-0\"\n />\n );\n}\n\nfunction Item({\n className,\n level = \"item\",\n icon,\n iconSlot,\n title,\n path,\n scope,\n external,\n children,\n value,\n ...props\n}: CommandItemProps) {\n const reduceMotion = useReducedMotion();\n // cmdk registers `value.trim()` and exposes the selected one as\n // `state.value` — mirrors cmdk's own `data-selected` computation.\n const trimmedValue = typeof value === \"string\" ? value.trim() : \"\";\n const selectedValue = useCommandState((state) => state.value);\n const isSelected = trimmedValue !== \"\" && selectedValue === trimmedValue;\n const structured = title != null;\n const isResult = level === \"result\";\n // Reserve the icon column when the row has an icon, or when the list asks\n // for alignment (`iconSlot`) even if this row's glyph is empty.\n const showResultIcon = isResult && (icon != null || iconSlot);\n\n const row = (\n <CommandPrimitive.Item\n data-level={level}\n value={value}\n className={cn(\n \"text-pho-secondary flex cursor-pointer items-center gap-2 rounded-[calc(var(--radius-base)-4px)] py-2 pr-2.5 text-base outline-none select-none\",\n // subsubitem steps in; item/subitem share the base gutter.\n level === \"subsubitem\" ? \"pl-6\" : \"pl-2\",\n // Secondary at rest; selection lifts to primary ink (Menu idiom).\n // The wash lands with it instantly — stepping through rows is a\n // snap, not a flight.\n \"data-[selected=true]:text-pho-primary data-[selected=true]:bg-pho-ghost-hover\",\n \"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n >\n {structured && isResult ? (\n <>\n {showResultIcon ? (\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n ) : null}\n {/* Same text-md line box as idle ItemTitle so row height matches (36px). */}\n <span className=\"text-md flex min-w-0 flex-1 items-center gap-1 overflow-hidden\">\n <span className=\"text-pho-primary truncate\">{title}</span>\n {(path ?? []).map((segment, index) => (\n <span\n key={index}\n className=\"text-pho-description flex shrink-0 items-center gap-0.5\"\n >\n <IconChevronLeft aria-hidden className=\"size-4 shrink-0\" />\n {segment}\n </span>\n ))}\n </span>\n {scope != null && scope !== \"\" ? (\n <span className=\"text-pho-description shrink-0 text-xs\">\n {scope}\n </span>\n ) : null}\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : structured ? (\n <>\n {/* Icon column always reserved so subitem labels share the item title edge. */}\n <ItemIcon aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n <span className=\"min-w-0 flex-1\">\n <ItemTitle level={level}>{title}</ItemTitle>\n </span>\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : (\n children\n )}\n </CommandPrimitive.Item>\n );\n\n if (reduceMotion) return row;\n\n return (\n // FLIP wrapper: rows that stay mounted glide when neighbours enter or\n // leave, and a row remounting elsewhere with the same `value` (idle group\n // ↔ flat search result) inherits the old bounds via its layoutId and\n // slides to the new slot — the iOS list-diff feel. Rows without a match\n // simply appear / disappear so the whole list never swarms.\n //\n // The selected row is the exception: it skips the travel and appears at\n // its final slot immediately, so the selection wash is never sitting on\n // empty space waiting for its row to fly in.\n <motion.div\n layout=\"position\"\n layoutId={typeof value === \"string\" ? value : undefined}\n initial={false}\n transition={isSelected ? { duration: 0 } : ROW_MOVE_SPRING}\n >\n {row}\n </motion.div>\n );\n}\n\nfunction Separator({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n className={cn(\n \"-mx-1 my-1 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Loading({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Loading>) {\n return (\n <CommandPrimitive.Loading\n className={cn(\"text-pho-description px-2.5 py-1.5 text-base\", className)}\n {...props}\n />\n );\n}\n\ntype DialogRootProps = ComponentProps<typeof PhoDialog.Root>;\n\ninterface CommandDialogProps extends ComponentProps<typeof CommandPrimitive> {\n /** Controlled dialog state — pass straight through to `Dialog.Root`. */\n open?: DialogRootProps[\"open\"];\n onOpenChange?: DialogRootProps[\"onOpenChange\"];\n /** Accessible name for the palette (dialog and command menu). */\n label?: string;\n /** Extra classes for the dialog panel (not the command root). */\n className?: string;\n}\n\n/**\n * A command palette in a modal — Pho's `Dialog` overlay (Base UI) around a\n * `Command.Root`, raised above center. We deliberately skip cmdk's own\n * `Command.Dialog` (Radix) so overlays stay on one primitive stack.\n *\n * List height springs via `AnimatedHeight` (same feel as the Card shell on\n * onboarding / invite) — the input row stays put while results resize.\n */\nfunction Dialog({\n open,\n onOpenChange,\n label,\n className,\n children,\n ...props\n}: CommandDialogProps) {\n return (\n <PhoDialog.Root open={open} onOpenChange={onOpenChange}>\n <PhoDialog.Portal>\n <PhoDialog.Backdrop />\n <PhoDialog.Popup\n aria-label={label}\n // Palette sits above center so the list grows downward from a\n // stable top edge instead of jumping around it.\n className={cn(\n \"top-[max(4rem,18vh)] max-w-xl translate-y-0 overflow-hidden p-0\",\n className,\n )}\n >\n {/* The popup is position: fixed; layout animations inside a fixed\n element need a layoutRoot to project against, or their\n measurements drift with the page scroll. */}\n <motion.div layoutRoot>\n <Root label={label} {...props}>\n {children}\n </Root>\n </motion.div>\n </PhoDialog.Popup>\n </PhoDialog.Portal>\n </PhoDialog.Root>\n );\n}\n\n/**\n * Command menu built on `cmdk` — a filterable list of actions driven from a\n * single input, keyboard-first. Compose inline (`Command.Root`) or as a\n * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay).\n * Filtering is yours by default — filter in render so the rows' diff can\n * glide; pass `shouldFilter` to hand matching and ranking to cmdk (its\n * imperative reorder skips the animation).\n *\n * Rows share one layout via `Command.Item` `level` — idle\n * `item` → `subitem` → `subsubitem`, or flat `result` while searching.\n */\nexport const Command = {\n Root,\n InputGroup,\n Input,\n List,\n Empty,\n Group,\n Item,\n ItemIcon,\n ItemTitle,\n Separator,\n Loading,\n Dialog,\n};\n\n/** Re-export of cmdk's state selector hook (search, value, filtered counts). */\nexport { useCommandState };\n"],"mappings":"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"}