@photon-ai/pho-ui 2.6.0 → 2.7.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 (120) hide show
  1. package/dist/chunks/IconChevronDown-CZilB71T.js +11 -0
  2. package/dist/chunks/IconChevronDown-CZilB71T.js.map +1 -0
  3. package/dist/chunks/IconSearch-BKAHkLyX.js +14 -0
  4. package/dist/chunks/IconSearch-BKAHkLyX.js.map +1 -0
  5. package/dist/chunks/animated-height-CCO-Ocoz.js +48 -0
  6. package/dist/chunks/animated-height-CCO-Ocoz.js.map +1 -0
  7. package/dist/chunks/basic-page-DR5szOOs.js +1373 -0
  8. package/dist/chunks/basic-page-DR5szOOs.js.map +1 -0
  9. package/dist/chunks/{button-DNNs5RsT.js → button-CdqS_t5a.js} +62 -65
  10. package/dist/chunks/button-CdqS_t5a.js.map +1 -0
  11. package/dist/chunks/checkbox-Cdm08HWG.js +129 -0
  12. package/dist/chunks/checkbox-Cdm08HWG.js.map +1 -0
  13. package/dist/chunks/{choice-card-CunOnY9l.js → choice-card-BVNP1NB6.js} +2 -2
  14. package/dist/chunks/{choice-card-CunOnY9l.js.map → choice-card-BVNP1NB6.js.map} +1 -1
  15. package/dist/chunks/data-table-DwbPU0zt.js +2970 -0
  16. package/dist/chunks/data-table-DwbPU0zt.js.map +1 -0
  17. package/dist/chunks/{dialog-8SRNi_rv.js → dialog-BxKACOj5.js} +4 -4
  18. package/dist/chunks/{dialog-8SRNi_rv.js.map → dialog-BxKACOj5.js.map} +1 -1
  19. package/dist/chunks/{error-Crs-wqMC.js → error-D0yoFxCv.js} +2 -2
  20. package/dist/chunks/{error-Crs-wqMC.js.map → error-D0yoFxCv.js.map} +1 -1
  21. package/dist/chunks/is-react-component-DSnjtBmo.js +10 -0
  22. package/dist/chunks/is-react-component-DSnjtBmo.js.map +1 -0
  23. package/dist/chunks/link-provider-DXzDQ08N.js +24 -0
  24. package/dist/chunks/link-provider-DXzDQ08N.js.map +1 -0
  25. package/dist/chunks/rolldown-runtime-DG5F_Nuu.js +27 -0
  26. package/dist/chunks/{scroll-area-Bu7egArU.js → scroll-area-BO-9PMM7.js} +27 -26
  27. package/dist/chunks/scroll-area-BO-9PMM7.js.map +1 -0
  28. package/dist/chunks/sidebar-DVzZsCts.js +223 -0
  29. package/dist/chunks/sidebar-DVzZsCts.js.map +1 -0
  30. package/dist/chunks/skeleton-DwjSl4vC.js +18 -0
  31. package/dist/chunks/skeleton-DwjSl4vC.js.map +1 -0
  32. package/dist/chunks/{toast-DoXaRPIZ.js → toast-iSf6NuAS.js} +43 -45
  33. package/dist/chunks/toast-iSf6NuAS.js.map +1 -0
  34. package/dist/chunks/use-press-pulse-IbNstUT0.js +58 -0
  35. package/dist/chunks/use-press-pulse-IbNstUT0.js.map +1 -0
  36. package/dist/components/button.js +1 -1
  37. package/dist/components/checkbox.js +4 -126
  38. package/dist/components/command.js +54 -57
  39. package/dist/components/command.js.map +1 -1
  40. package/dist/components/data-table.js +11 -0
  41. package/dist/components/dialog.js +1 -1
  42. package/dist/components/error.js +1 -1
  43. package/dist/components/phone-input.js +609 -616
  44. package/dist/components/phone-input.js.map +1 -1
  45. package/dist/components/radio-group.js +2 -2
  46. package/dist/components/scroll-area.js +1 -1
  47. package/dist/components/select.js +35 -39
  48. package/dist/components/select.js.map +1 -1
  49. package/dist/components/skeleton.js +2 -15
  50. package/dist/components/toast.js +1 -1
  51. package/dist/index.js +94 -73
  52. package/dist/motion.js +89 -0
  53. package/dist/motion.js.map +1 -0
  54. package/dist/primitives/accordion.js +1 -1
  55. package/dist/primitives/alert-dialog.js +1 -1
  56. package/dist/primitives/autocomplete.js +1 -1
  57. package/dist/primitives/avatar.js +1 -1
  58. package/dist/primitives/button.js +1 -1
  59. package/dist/primitives/checkbox-group.js +1 -1
  60. package/dist/primitives/checkbox.js +1 -1
  61. package/dist/primitives/collapsible.js +1 -1
  62. package/dist/primitives/combobox.js +1 -1
  63. package/dist/primitives/context-menu.js +1 -1
  64. package/dist/primitives/csp-provider.js +1 -1
  65. package/dist/primitives/dialog.js +1 -1
  66. package/dist/primitives/direction-provider.js +1 -1
  67. package/dist/primitives/drawer.js +1 -1
  68. package/dist/primitives/field.js +1 -1
  69. package/dist/primitives/fieldset.js +1 -1
  70. package/dist/primitives/form.js +1 -1
  71. package/dist/primitives/input.js +1 -1
  72. package/dist/primitives/menu.js +1 -1
  73. package/dist/primitives/menubar.js +1 -1
  74. package/dist/primitives/meter.js +1 -1
  75. package/dist/primitives/navigation-menu.js +1 -1
  76. package/dist/primitives/number-field.js +1 -1
  77. package/dist/primitives/otp-field.js +1 -1
  78. package/dist/primitives/popover.js +1 -1
  79. package/dist/primitives/preview-card.js +1 -1
  80. package/dist/primitives/progress.js +1 -1
  81. package/dist/primitives/radio-group.js +1 -1
  82. package/dist/primitives/radio.js +1 -1
  83. package/dist/primitives/scroll-area.js +1 -1
  84. package/dist/primitives/select.js +1 -1
  85. package/dist/primitives/separator.js +1 -1
  86. package/dist/primitives/slider.js +1 -1
  87. package/dist/primitives/switch.js +1 -1
  88. package/dist/primitives/tabs.js +1 -1
  89. package/dist/primitives/toast.js +1 -1
  90. package/dist/primitives/toggle-group.js +1 -1
  91. package/dist/primitives/toggle.js +1 -1
  92. package/dist/primitives/toolbar.js +1 -1
  93. package/dist/primitives/tooltip.js +1 -1
  94. package/dist/primitives.js +3 -3
  95. package/dist/sections/basic-page.js +16 -14
  96. package/dist/sections/sidebar.js +1 -1
  97. package/dist/src/components/data-table/data-table.d.ts +227 -0
  98. package/dist/src/components/data-table/index.d.ts +2 -0
  99. package/dist/src/index.d.ts +1 -0
  100. package/dist/src/motion/index.d.ts +149 -0
  101. package/dist/src/sections/basic-page/basic-page.d.ts +47 -7
  102. package/dist/src/sections/basic-page/index.d.ts +1 -0
  103. package/dist/utils.js +13 -12
  104. package/package.json +10 -1
  105. package/dist/chunks/animated-height-C2eQstGy.js +0 -51
  106. package/dist/chunks/animated-height-C2eQstGy.js.map +0 -1
  107. package/dist/chunks/basic-page-DsI1xo6p.js +0 -1295
  108. package/dist/chunks/basic-page-DsI1xo6p.js.map +0 -1
  109. package/dist/chunks/button-DNNs5RsT.js.map +0 -1
  110. package/dist/chunks/link-provider-9TFNyDqO.js +0 -28
  111. package/dist/chunks/link-provider-9TFNyDqO.js.map +0 -1
  112. package/dist/chunks/rolldown-runtime-wKSmTnsc.js +0 -22
  113. package/dist/chunks/scroll-area-Bu7egArU.js.map +0 -1
  114. package/dist/chunks/sidebar-DvB-G0BP.js +0 -231
  115. package/dist/chunks/sidebar-DvB-G0BP.js.map +0 -1
  116. package/dist/chunks/toast-DoXaRPIZ.js.map +0 -1
  117. package/dist/chunks/use-press-pulse-8iorQPsh.js +0 -62
  118. package/dist/chunks/use-press-pulse-8iorQPsh.js.map +0 -1
  119. package/dist/components/checkbox.js.map +0 -1
  120. package/dist/components/skeleton.js.map +0 -1
@@ -1,231 +0,0 @@
1
- "use client";
2
- import { t as n } from "./cn-ChIgwEl3.js";
3
- import { n as R, r as E } from "./link-provider-9TFNyDqO.js";
4
- import { a as S, u as _ } from "./button-DNNs5RsT.js";
5
- import { t as g } from "./createReactComponent-BqCmnqfX.js";
6
- import { t as A } from "./IconArrowUpRight-DGgKzQwV.js";
7
- import { n as d } from "./avatar-BkmGDIqf.js";
8
- import { t as u } from "./scroll-area-Bu7egArU.js";
9
- import { t as k } from "./kbd-DNI10uy7.js";
10
- import { createContext as w, isValidElement as C, useContext as T, useMemo as M } from "react";
11
- import { Fragment as B, jsx as t, jsxs as i } from "react/jsx-runtime";
12
- import { motion as h } from "motion/react";
13
- var D = [
14
- ["path", {
15
- d: "M4 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0",
16
- key: "svg-0"
17
- }],
18
- ["path", {
19
- d: "M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0",
20
- key: "svg-1"
21
- }],
22
- ["path", {
23
- d: "M18 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0",
24
- key: "svg-2"
25
- }]
26
- ], O = g("outline", "dots", "Dots", D), z = [["path", {
27
- d: "M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0",
28
- key: "svg-0"
29
- }], ["path", {
30
- d: "M21 21l-6 -6",
31
- key: "svg-1"
32
- }]], F = g("outline", "search", "Search", z), f = {
33
- initial: !1,
34
- whileTap: { scale: 0.97 },
35
- transition: {
36
- type: "spring",
37
- stiffness: 200,
38
- damping: 30,
39
- mass: 0.1
40
- }
41
- }, b = "border-pho-secondary bg-pho-page sticky top-0 flex h-dvh w-64 shrink-0 flex-col border-r", y = {
42
- base: "px-4 pt-5 pb-4",
43
- sm: "px-3 pt-4 pb-3"
44
- }, ue = n(b, y.base), K = {
45
- base: "mb-6 px-2",
46
- sm: "mb-3 px-0"
47
- }, L = "outline-pho-brand flex min-h-9 w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-base transition-colors focus-visible:outline-2 focus-visible:-outline-offset-1", V = "bg-pho-primary text-pho-primary ring-pho-secondary font-medium ring-1 ring-inset *:data-icon:text-pho-primary", j = n("text-pho-secondary *:data-icon:text-pho-secondary", "hover:bg-pho-primary hover:text-pho-primary hover:*:data-icon:text-pho-primary"), N = w("base");
48
- function U({ className: a, inset: e = "base", ...r }) {
49
- return /* @__PURE__ */ t(N.Provider, {
50
- value: e,
51
- children: /* @__PURE__ */ t("aside", {
52
- className: n(b, y[e], a),
53
- ...r,
54
- "data-inset": e
55
- })
56
- });
57
- }
58
- function G({ className: a, ...e }) {
59
- const r = T(N);
60
- return /* @__PURE__ */ t("div", {
61
- className: n("flex items-center gap-2.5 [&:has(+nav)]:mb-0", K[r], a),
62
- ...e
63
- });
64
- }
65
- function H({ label: a = "Search", kbd: e = "⌘K", className: r, ...o }) {
66
- return /* @__PURE__ */ t(S, {
67
- variant: "outlined",
68
- shape: "square",
69
- size: "md",
70
- "aria-keyshortcuts": e === "⌘K" ? "Meta+K Control+K" : void 0,
71
- prefix: /* @__PURE__ */ t(F, { "aria-hidden": !0 }),
72
- suffix: /* @__PURE__ */ t(k, {
73
- keys: e,
74
- className: "pointer-events-none"
75
- }),
76
- className: n("hover:ring-pho-secondary min-h-9 w-full justify-start gap-2 rounded-sm px-2 py-1.5 has-[[data-icon=prefix]]:pl-2 has-[[data-icon=suffix]]:pr-2 [&>[data-text]]:min-w-0 [&>[data-text]]:flex-1 [&>[data-text]]:truncate [&>[data-text]]:px-0 [&>[data-text]]:text-left", r),
77
- ...o,
78
- children: a
79
- });
80
- }
81
- function P({ scroll: a = !0, inset: e, insetTop: r = e ?? 24, insetBottom: o = e ?? 16, className: s, style: l, children: p, ...c }) {
82
- return a ? /* @__PURE__ */ t("nav", {
83
- className: n("flex min-h-0 flex-1 flex-col", s),
84
- style: l,
85
- ...c,
86
- children: /* @__PURE__ */ i(u.Root, {
87
- className: "min-h-0 flex-1",
88
- children: [/* @__PURE__ */ t(u.Viewport, { children: /* @__PURE__ */ t(u.Content, {
89
- inset: e,
90
- insetTop: r,
91
- insetBottom: o,
92
- className: "flex flex-col gap-6",
93
- children: p
94
- }) }), /* @__PURE__ */ t(u.Scrollbar, { children: /* @__PURE__ */ t(u.Thumb, {}) })]
95
- })
96
- }) : /* @__PURE__ */ t("nav", {
97
- className: n("flex flex-col gap-6", s),
98
- style: {
99
- paddingTop: r ?? e,
100
- paddingBottom: o ?? e,
101
- ...l
102
- },
103
- ...c,
104
- children: p
105
- });
106
- }
107
- function $({ className: a, ...e }) {
108
- return /* @__PURE__ */ t("div", {
109
- className: a,
110
- ...e
111
- });
112
- }
113
- function q({ className: a, ...e }) {
114
- return /* @__PURE__ */ t("div", {
115
- className: n("text-pho-description mb-2 px-2 text-xs font-normal", a),
116
- ...e
117
- });
118
- }
119
- function W({ className: a, columns: e, ...r }) {
120
- return /* @__PURE__ */ t("ul", {
121
- className: n("m-0 list-none p-0 *:m-0", e ? "grid grid-cols-2 gap-x-2 gap-y-0.5" : "flex flex-col gap-0.5", a),
122
- ...r
123
- });
124
- }
125
- function J({ className: a, ...e }) {
126
- return /* @__PURE__ */ t("div", {
127
- className: n("mt-4 flex flex-col gap-0.5 [nav~&]:mt-0", a),
128
- ...e
129
- });
130
- }
131
- function m(a) {
132
- if (a == null || a === !1) return null;
133
- let e = null;
134
- return E(a) ? e = /* @__PURE__ */ t(a, {}) : C(a) && (e = a), e == null ? null : /* @__PURE__ */ t("span", {
135
- "data-icon": !0,
136
- className: "pointer-events-none inline-flex shrink-0 items-center [&>svg]:size-4 [&>svg]:shrink-0",
137
- children: e
138
- });
139
- }
140
- function Q({ icon: a, active: e, className: r, children: o, href: s, external: l, ...p }) {
141
- const c = R(), I = M(() => h.create(c), [c]), x = n(L, e ? V : j, r), v = /* @__PURE__ */ t("span", {
142
- className: "min-w-0 flex-1 truncate",
143
- children: o
144
- });
145
- return s !== void 0 ? /* @__PURE__ */ t("li", { children: /* @__PURE__ */ i(I, {
146
- href: s,
147
- "aria-current": e ? "page" : void 0,
148
- ...l && {
149
- target: "_blank",
150
- rel: "noopener noreferrer"
151
- },
152
- ...p,
153
- className: x,
154
- ...f,
155
- children: [
156
- m(a),
157
- v,
158
- l && /* @__PURE__ */ i(B, { children: [m(/* @__PURE__ */ t(A, { "aria-hidden": !0 })), /* @__PURE__ */ t("span", {
159
- className: "sr-only",
160
- children: "(opens in a new tab)"
161
- })] })
162
- ]
163
- }) }) : /* @__PURE__ */ t("li", { children: /* @__PURE__ */ i(h.button, {
164
- type: "button",
165
- "aria-current": e ? "page" : void 0,
166
- ...p,
167
- className: x,
168
- ...f,
169
- children: [m(a), v]
170
- }) });
171
- }
172
- var X = "group outline-pho-brand flex w-full cursor-pointer items-center gap-2 rounded-base p-2 text-left focus-visible:outline-2 focus-visible:outline-offset-2";
173
- function Y(a) {
174
- const e = a.split(/\s+/).filter(Boolean);
175
- return ((e[0]?.[0] ?? a[0] ?? "?") + (e.length >= 2 ? e[e.length - 1]?.[0] ?? "" : "")).toUpperCase();
176
- }
177
- function Z({ name: a, avatarSrc: e, initials: r, className: o, ...s }) {
178
- return /* @__PURE__ */ i(h.button, {
179
- type: "button",
180
- className: n(X, o),
181
- ...s,
182
- ...f,
183
- children: [
184
- /* @__PURE__ */ i(d.Root, {
185
- size: "xs",
186
- children: [e && /* @__PURE__ */ t(d.Image, {
187
- src: e,
188
- alt: ""
189
- }), /* @__PURE__ */ t(d.Fallback, { children: r ?? Y(a) })]
190
- }),
191
- /* @__PURE__ */ t("span", {
192
- className: "text-pho-primary min-w-0 flex-1 truncate text-base",
193
- children: a
194
- }),
195
- /* @__PURE__ */ t("span", {
196
- "aria-hidden": !0,
197
- className: _({
198
- variant: "outlined",
199
- size: "sm",
200
- shape: "circle",
201
- className: "group-hover:bg-pho-primary-hover group-hover:text-pho-secondary-hover group-data-[popup-open]:bg-pho-primary-hover group-data-[popup-open]:text-pho-secondary-hover p-1"
202
- }),
203
- children: /* @__PURE__ */ t(O, { className: "size-4" })
204
- })
205
- ]
206
- });
207
- }
208
- var de = {
209
- Root: U,
210
- Header: G,
211
- Search: H,
212
- Nav: P,
213
- Group: $,
214
- GroupLabel: q,
215
- List: W,
216
- Item: Q,
217
- Footer: J,
218
- AccountRow: Z
219
- };
220
- export {
221
- b as a,
222
- de as c,
223
- j as i,
224
- L as n,
225
- ue as o,
226
- V as r,
227
- y as s,
228
- K as t
229
- };
230
-
231
- //# sourceMappingURL=sidebar-DvB-G0BP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sidebar-DvB-G0BP.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/IconDots.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.mjs","../../src/sections/sidebar/sidebar.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 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M18 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0\", \"key\": \"svg-2\" }]];\nconst IconDots = createReactComponent(\"outline\", \"dots\", \"Dots\", __iconNode);\n\nexport { __iconNode, IconDots as default };\n//# sourceMappingURL=IconDots.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 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M21 21l-6 -6\", \"key\": \"svg-1\" }]];\nconst IconSearch = createReactComponent(\"outline\", \"search\", \"Search\", __iconNode);\n\nexport { __iconNode, IconSearch as default };\n//# sourceMappingURL=IconSearch.mjs.map\n","import {\n createContext,\n isValidElement,\n useContext,\n useMemo,\n type AnchorHTMLAttributes,\n type ButtonHTMLAttributes,\n type ComponentProps,\n type ComponentType,\n type FC,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { IconArrowUpRight, IconDots } from \"@tabler/icons-react\";\nimport { motion } from \"motion/react\";\nimport { IconSearch } from \"@tabler/icons-react\";\nimport { Button } from \"../../components/button\";\nimport { Kbd } from \"../../components/kbd\";\nimport { ScrollArea } from \"../../components/scroll-area\";\nimport { cn } from \"../../utils/cn\";\nimport { isReactComponent } from \"../../utils/is-react-component\";\nimport { useLinkComponent } from \"../../utils/link-provider\";\nimport { Avatar } from \"../../components/avatar\";\nimport { buttonVariants } from \"../../components/button\";\n\n/** Same press compression as `Button` — transform-only, every interactive row. */\nconst SIDEBAR_PRESS_SCALE = 0.97;\n/** Framer source transition shared with `Button`: `spring-physics 200 30 0.1`. */\nconst SIDEBAR_PRESS_SPRING = {\n type: \"spring\",\n stiffness: 200,\n damping: 30,\n mass: 0.1,\n} as const;\nconst SIDEBAR_PRESS_MOTION = {\n initial: false as const,\n whileTap: { scale: SIDEBAR_PRESS_SCALE },\n transition: SIDEBAR_PRESS_SPRING,\n};\n\n/**\n * Sidebar — Pho's first SECTION: a composed app rail, not a micro component.\n * It encodes the navigation rail used across Photon surfaces (the Pho docs\n * site, the dashboard): a sticky full-height column with a brand header, a\n * scrollable stack of titled nav groups, and a pinned footer that usually\n * carries the account row.\n *\n * Sections stay presentational — no router, no data fetching, no theme\n * plumbing. Links render through the host's `LinkProvider` (same contract as\n * `ButtonLink`), state arrives via props (`active`), and interactive footers\n * compose with other Pho parts (e.g. wrap `Sidebar.AccountRow` in a\n * `Menu.Trigger render={...}` to open an account menu).\n *\n * `Root` takes `inset` (`base` | `sm`, default `base`) for the rail's outer\n * padding and header spacing — prefer that over host-app class overrides.\n */\n\n/* ------------------------------- class map ------------------------------- */\n\n/** The rail itself — sticky, full-height, hairline right edge (no inset). */\nexport const SIDEBAR_ROOT =\n \"border-pho-secondary bg-pho-page sticky top-0 flex h-dvh w-64 shrink-0 flex-col border-r\";\n\n/** Outer inset on `Root` — `base` is the docs/default rail; `sm` is tighter. */\nexport const SIDEBAR_ROOT_INSET = {\n base: \"px-4 pt-5 pb-4\",\n sm: \"px-3 pt-4 pb-3\",\n} as const;\n\n/** `SIDEBAR_ROOT` with the default `base` inset — one string for docs chrome. */\nexport const SIDEBAR_ROOT_BASE = cn(SIDEBAR_ROOT, SIDEBAR_ROOT_INSET.base);\n\n/** Header spacing paired with `Root`'s `inset`. */\nexport const SIDEBAR_HEADER_INSET = {\n base: \"mb-6 px-2\",\n sm: \"mb-3 px-0\",\n} as const;\n\nexport type SidebarInset = keyof typeof SIDEBAR_ROOT_INSET;\n\n/** A nav row at rest and on hover. Active/inactive inks split below. */\nexport const SIDEBAR_ITEM =\n \"outline-pho-brand flex min-h-9 w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-base transition-colors focus-visible:outline-2 focus-visible:-outline-offset-1\";\n\n/**\n * Selected row — lifted onto the primary surface with the site hairline.\n * The icon carries the same ink as the label so the pair reads as one unit.\n */\nexport const SIDEBAR_ITEM_ACTIVE =\n \"bg-pho-primary text-pho-primary ring-pho-secondary font-medium ring-1 ring-inset *:data-icon:text-pho-primary\";\n\n/**\n * Resting row — secondary ink (75%). Hover lifts onto the primary surface\n * (same plane as the active chip, without the ring) so the wash stays quiet\n * on `pho-page`. Icon tracks the label's ink at every state.\n */\nexport const SIDEBAR_ITEM_INACTIVE = cn(\n \"text-pho-secondary *:data-icon:text-pho-secondary\",\n \"hover:bg-pho-primary hover:text-pho-primary hover:*:data-icon:text-pho-primary\",\n);\n\nconst SidebarInsetContext = createContext<SidebarInset>(\"base\");\n\n/* --------------------------------- frame --------------------------------- */\n\ninterface RootProps extends ComponentProps<\"aside\"> {\n /** Outer padding + header spacing. Defaults to `base`. */\n inset?: SidebarInset;\n ref?: Ref<HTMLElement>;\n}\n\n/** The rail — a sticky, full-height `<aside>` with the hairline right edge. */\nfunction Root({ className, inset = \"base\", ...props }: RootProps) {\n return (\n <SidebarInsetContext.Provider value={inset}>\n <aside\n className={cn(SIDEBAR_ROOT, SIDEBAR_ROOT_INSET[inset], className)}\n {...props}\n data-inset={inset}\n />\n </SidebarInsetContext.Provider>\n );\n}\n\n/** Brand slot at the top of the rail — logo, wordmark, workspace switcher. */\nfunction Header({ className, ...props }: ComponentProps<\"div\">) {\n const inset = useContext(SidebarInsetContext);\n return (\n <div\n className={cn(\n \"flex items-center gap-2.5 [&:has(+nav)]:mb-0\",\n SIDEBAR_HEADER_INSET[inset],\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * The rail's search row — an outlined button dressed to `Item` metrics so\n * its label lines up with the rows below, the shortcut at the trailing\n * edge. The press is the Button's own; wire `onClick` (and a global ⌘K)\n * to a `Command.Dialog`.\n */\nfunction Search({\n label = \"Search\",\n kbd = \"⌘K\",\n className,\n ...props\n}: Omit<ComponentProps<typeof Button>, \"children\" | \"variant\" | \"size\"> & {\n label?: ReactNode;\n kbd?: string;\n}) {\n return (\n <Button\n variant=\"outlined\"\n shape=\"square\"\n size=\"md\"\n aria-keyshortcuts={kbd === \"⌘K\" ? \"Meta+K Control+K\" : undefined}\n prefix={<IconSearch aria-hidden />}\n suffix={<Kbd keys={kbd} className=\"pointer-events-none\" />}\n className={cn(\n \"hover:ring-pho-secondary min-h-9 w-full justify-start gap-2 rounded-sm px-2 py-1.5 has-[[data-icon=prefix]]:pl-2 has-[[data-icon=suffix]]:pr-2 [&>[data-text]]:min-w-0 [&>[data-text]]:flex-1 [&>[data-text]]:truncate [&>[data-text]]:px-0 [&>[data-text]]:text-left\",\n className,\n )}\n {...props}\n >\n {label}\n </Button>\n );\n}\n\n/**\n * The scrollable middle — a stack of `Sidebar.Group`s in a `ScrollArea`\n * (overlay scrollbar, edge fade). Pass `scroll={false}` where a parent\n * scrolls the whole rail as one column (a narrow-viewport drawer) — the\n * nav is then a plain stack at its natural height.\n *\n * The nav owns its breathing room toward its neighbors as a resting inset\n * (a scroll view's safe-area padding): 24px above, 16px below by default —\n * rows stand clear of the ends at rest and scroll through the gap, under\n * the edge fade, instead of clipping at a dead margin. `inset` /\n * `insetTop` / `insetBottom` override it; the same values become plain\n * padding when `scroll={false}`, so both modes keep one geometry. A\n * `Header` right before the nav and a `Footer` after it drop their own\n * margins — the gap lives here, not on the neighbors.\n */\nfunction Nav({\n scroll = true,\n inset,\n insetTop = inset ?? 24,\n insetBottom = inset ?? 16,\n className,\n style,\n children,\n ...props\n}: ComponentProps<\"nav\"> & {\n scroll?: boolean;\n inset?: number | string;\n insetTop?: number | string;\n insetBottom?: number | string;\n}) {\n if (!scroll) {\n return (\n <nav\n className={cn(\"flex flex-col gap-6\", className)}\n style={{\n paddingTop: insetTop ?? inset,\n paddingBottom: insetBottom ?? inset,\n ...style,\n }}\n {...props}\n >\n {children}\n </nav>\n );\n }\n return (\n <nav\n className={cn(\"flex min-h-0 flex-1 flex-col\", className)}\n style={style}\n {...props}\n >\n <ScrollArea.Root className=\"min-h-0 flex-1\">\n <ScrollArea.Viewport>\n <ScrollArea.Content\n inset={inset}\n insetTop={insetTop}\n insetBottom={insetBottom}\n className=\"flex flex-col gap-6\"\n >\n {children}\n </ScrollArea.Content>\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n </nav>\n );\n}\n\nfunction Group({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={className} {...props} />;\n}\n\n/** The cluster's caption — description ink, regular weight. */\nfunction GroupLabel({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"text-pho-description mb-2 px-2 text-xs font-normal\",\n className,\n )}\n {...props}\n />\n );\n}\n\ninterface ListProps extends ComponentProps<\"ul\"> {\n /** Lay the rows out in two columns — for long, flat registries. */\n columns?: boolean;\n}\n\n/** The rows of a group. `columns` switches to a two-column grid. */\nfunction List({ className, columns, ...props }: ListProps) {\n return (\n <ul\n className={cn(\n // list-none/m-0/p-0 shield the rail from host prose styles.\n \"m-0 list-none p-0 *:m-0\",\n columns\n ? \"grid grid-cols-2 gap-x-2 gap-y-0.5\"\n : \"flex flex-col gap-0.5\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Pinned bottom cluster — docs link, account row, theme toggle. */\nfunction Footer({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\"mt-4 flex flex-col gap-0.5 [nav~&]:mt-0\", className)}\n {...props}\n />\n );\n}\n\n/* --------------------------------- item ---------------------------------- */\n\n/** An icon slot — a component (`IconBook`) or element (`<IconBook />`). */\ntype Slottable = ReactNode | FC<{ className?: string }>;\n\nfunction renderIcon(icon: Slottable): ReactNode {\n if (icon == null || icon === false) return null;\n let content: ReactNode = null;\n if (isReactComponent(icon)) {\n const Icon = icon;\n content = <Icon />;\n } else if (isValidElement(icon)) {\n content = icon;\n }\n if (content == null) return null;\n return (\n <span\n data-icon\n className=\"pointer-events-none inline-flex shrink-0 items-center [&>svg]:size-4 [&>svg]:shrink-0\"\n >\n {content}\n </span>\n );\n}\n\ninterface ItemBaseProps {\n /** Slot before the label — a component (`IconBook`) or element. */\n icon?: Slottable;\n /** Marks the row as the current destination (adds `aria-current=\"page\"`). */\n active?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\n/**\n * DOM handlers whose React signatures clash with Motion's gesture props.\n * Same omit list as `Button` — rows render through `motion.*`.\n */\ntype MotionHandlerConflicts =\n | \"onAnimationStart\"\n | \"onAnimationEnd\"\n | \"onAnimationIteration\"\n | \"onDrag\"\n | \"onDragStart\"\n | \"onDragEnd\"\n | \"onDragEnter\"\n | \"onDragExit\"\n | \"onDragLeave\"\n | \"onDragOver\"\n | \"onDrop\";\n\nexport interface SidebarItemLinkProps\n extends\n ItemBaseProps,\n Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof ItemBaseProps | MotionHandlerConflicts\n > {\n /** Destination — rendered through the host's `LinkProvider`. */\n href: string;\n /** Leaves the app: opens in a new tab and renders a ↗ cue. */\n external?: boolean;\n}\n\nexport interface SidebarItemButtonProps\n extends\n ItemBaseProps,\n Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof ItemBaseProps | MotionHandlerConflicts\n > {\n href?: undefined;\n external?: undefined;\n}\n\nexport type SidebarItemProps = SidebarItemLinkProps | SidebarItemButtonProps;\n\n/**\n * A nav row — a link when `href` is given (rendered through the host's\n * `LinkProvider`), otherwise a button. `active` lifts the row onto the\n * primary surface; `external` opens a new tab and appends a ↗ cue.\n */\nfunction Item({\n icon,\n active,\n className,\n children,\n href,\n external,\n ...rest\n}: SidebarItemProps) {\n const Link = useLinkComponent();\n // Same bridge as `ButtonLink` — host `LinkProvider` + Motion press scale.\n const MotionLink = useMemo(\n () =>\n motion.create(Link as unknown as ComponentType<Record<string, unknown>>),\n [Link],\n );\n const rowClass = cn(\n SIDEBAR_ITEM,\n active ? SIDEBAR_ITEM_ACTIVE : SIDEBAR_ITEM_INACTIVE,\n className,\n );\n const label = <span className=\"min-w-0 flex-1 truncate\">{children}</span>;\n\n if (href !== undefined) {\n return (\n <li>\n <MotionLink\n href={href}\n aria-current={active ? \"page\" : undefined}\n {...(external && { target: \"_blank\", rel: \"noopener noreferrer\" })}\n {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}\n className={rowClass}\n {...SIDEBAR_PRESS_MOTION}\n >\n {renderIcon(icon)}\n {label}\n {external && (\n <>\n {renderIcon(<IconArrowUpRight aria-hidden />)}\n <span className=\"sr-only\">(opens in a new tab)</span>\n </>\n )}\n </MotionLink>\n </li>\n );\n }\n\n return (\n <li>\n <motion.button\n type=\"button\"\n aria-current={active ? \"page\" : undefined}\n {...(rest as Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n MotionHandlerConflicts\n >)}\n className={rowClass}\n {...SIDEBAR_PRESS_MOTION}\n >\n {renderIcon(icon)}\n {label}\n </motion.button>\n </li>\n );\n}\n\n/* ------------------------------ account row ------------------------------ */\n\n/**\n * Whole-row account trigger. The row itself stays visually quiet — it only\n * carries the `group` state (hover/press/popup-open) and the focus ring;\n * all visual feedback renders on the ⋯ circle via `group-*` classes.\n */\nconst ACCOUNT_ROW =\n \"group outline-pho-brand flex w-full cursor-pointer items-center gap-2 rounded-base p-2 text-left focus-visible:outline-2 focus-visible:outline-offset-2\";\n\n/** Avatar initials: first + last word initial, else the first character. */\nfunction initialsFrom(name: string): string {\n const words = name.split(/\\s+/).filter(Boolean);\n const first = words[0]?.[0] ?? name[0] ?? \"?\";\n const last = words.length >= 2 ? (words[words.length - 1]?.[0] ?? \"\") : \"\";\n return (first + last).toUpperCase();\n}\n\nexport interface SidebarAccountRowProps extends Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"children\" | MotionHandlerConflicts\n> {\n /** Display name — also the source for fallback initials. */\n name: string;\n /** Avatar image URL; falls back to initials while loading or on error. */\n avatarSrc?: string;\n /** Override the derived initials. */\n initials?: string;\n ref?: Ref<HTMLButtonElement>;\n}\n\n/**\n * The account chip pinned to the rail's footer — an xs avatar, the name, and\n * a decorative ⋯ circle. The WHOLE row is one button, but the row is only the\n * control — the circle is the indicator: hover, press, and menu-open feedback\n * all render on the ⋯ (a span wearing the stock secondary-circle button\n * classes), driven by the row's `group` state, so it reads as a button\n * without nesting one.\n *\n * It renders a plain `<button>` and forwards every prop, so it slots straight\n * into a menu: `<Menu.Trigger render={<Sidebar.AccountRow name=\"…\" />} />` —\n * Base UI's `data-popup-open` / `data-pressed` states light up the circle.\n */\nfunction AccountRow({\n name,\n avatarSrc,\n initials,\n className,\n ...props\n}: SidebarAccountRowProps) {\n return (\n <motion.button\n type=\"button\"\n className={cn(ACCOUNT_ROW, className)}\n {...props}\n {...SIDEBAR_PRESS_MOTION}\n >\n <Avatar.Root size=\"xs\">\n {avatarSrc && <Avatar.Image src={avatarSrc} alt=\"\" />}\n <Avatar.Fallback>{initials ?? initialsFrom(name)}</Avatar.Fallback>\n </Avatar.Root>\n <span className=\"text-pho-primary min-w-0 flex-1 truncate text-base\">\n {name}\n </span>\n <span\n aria-hidden\n className={buttonVariants({\n variant: \"outlined\",\n size: \"sm\",\n shape: \"circle\",\n // Hover / open washes stay on the ⋯; press scale lives on the row\n // (same as Button / Sidebar.Item) so the circle does not double-scale.\n className:\n \"group-hover:bg-pho-primary-hover group-hover:text-pho-secondary-hover group-data-[popup-open]:bg-pho-primary-hover group-data-[popup-open]:text-pho-secondary-hover p-1\",\n })}\n >\n <IconDots className=\"size-4\" />\n </span>\n </motion.button>\n );\n}\n\n/* -------------------------------- assembly ------------------------------- */\n\n/**\n * The composed sidebar rail. Assemble the frame parts and fill them with\n * rows; wire interactivity by composing other Pho parts around them:\n *\n * ```tsx\n * <Sidebar.Root>\n * <Sidebar.Header>…brand…</Sidebar.Header>\n * <Sidebar.Nav>\n * <Sidebar.Group>\n * <Sidebar.GroupLabel>Pages</Sidebar.GroupLabel>\n * <Sidebar.List>\n * <Sidebar.Item href=\"/\" icon={IconHome} active>\n * Overview\n * </Sidebar.Item>\n * </Sidebar.List>\n * </Sidebar.Group>\n * </Sidebar.Nav>\n * <Sidebar.Footer>\n * <Menu.Root>\n * <Menu.Trigger render={<Sidebar.AccountRow name=\"Ada Lovelace\" />} />\n * …\n * </Menu.Root>\n * </Sidebar.Footer>\n * </Sidebar.Root>\n * ```\n */\nexport const Sidebar = {\n Root,\n Header,\n Search,\n Nav,\n Group,\n GroupLabel,\n List,\n Item,\n Footer,\n AccountRow,\n};\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"toast-DoXaRPIZ.js","names":["__iconNode","__iconNode","__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertOctagonFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertTriangleFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheckFilled.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconInfoCircleFilled.mjs","../../src/components/toast/toast.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\": \"M14.897 1a4 4 0 0 1 2.664 1.016l.165 .156l4.1 4.1a4 4 0 0 1 1.168 2.605l.006 .227v5.794a4 4 0 0 1 -1.016 2.664l-.156 .165l-4.1 4.1a4 4 0 0 1 -2.603 1.168l-.227 .006h-5.795a3.999 3.999 0 0 1 -2.664 -1.017l-.165 -.156l-4.1 -4.1a4 4 0 0 1 -1.168 -2.604l-.006 -.227v-5.794a4 4 0 0 1 1.016 -2.664l.156 -.165l4.1 -4.1a4 4 0 0 1 2.605 -1.168l.227 -.006h5.793zm-2.887 14l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]];\nconst IconAlertOctagonFilled = createReactComponent(\"filled\", \"alert-octagon-filled\", \"AlertOctagonFilled\", __iconNode);\n\nexport { __iconNode, IconAlertOctagonFilled as default };\n//# sourceMappingURL=IconAlertOctagonFilled.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\": \"M12 1.67c.955 0 1.845 .467 2.39 1.247l.105 .16l8.114 13.548a2.914 2.914 0 0 1 -2.307 4.363l-.195 .008h-16.225a2.914 2.914 0 0 1 -2.582 -4.2l.099 -.185l8.11 -13.538a2.914 2.914 0 0 1 2.491 -1.403zm.01 13.33l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -7a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]];\nconst IconAlertTriangleFilled = createReactComponent(\"filled\", \"alert-triangle-filled\", \"AlertTriangleFilled\", __iconNode);\n\nexport { __iconNode, IconAlertTriangleFilled as default };\n//# sourceMappingURL=IconAlertTriangleFilled.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\": \"M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z\", \"key\": \"svg-0\" }]];\nconst IconCircleCheckFilled = createReactComponent(\"filled\", \"circle-check-filled\", \"CircleCheckFilled\", __iconNode);\n\nexport { __iconNode, IconCircleCheckFilled as default };\n//# sourceMappingURL=IconCircleCheckFilled.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\": \"M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm0 9h-1l-.117 .007a1 1 0 0 0 0 1.986l.117 .007v3l.007 .117a1 1 0 0 0 .876 .876l.117 .007h1l.117 -.007a1 1 0 0 0 .876 -.876l.007 -.117l-.007 -.117a1 1 0 0 0 -.764 -.857l-.112 -.02l-.117 -.006v-3l-.007 -.117a1 1 0 0 0 -.876 -.876l-.117 -.007zm.01 -3l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007z\", \"key\": \"svg-0\" }]];\nconst IconInfoCircleFilled = createReactComponent(\"filled\", \"info-circle-filled\", \"InfoCircleFilled\", __iconNode);\n\nexport { __iconNode, IconInfoCircleFilled as default };\n//# sourceMappingURL=IconInfoCircleFilled.mjs.map\n","import { type ComponentProps, type ElementType, type ReactNode } from \"react\";\nimport { Toast as BaseToast } from \"@base-ui/react/toast\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport {\n IconAlertOctagonFilled,\n IconAlertTriangleFilled,\n IconCircleCheckFilled,\n IconInfoCircleFilled,\n IconX,\n type Icon,\n} from \"@tabler/icons-react\";\nimport { BLUR_MAX_PX } from \"../scroll-area\";\nimport { Button } from \"../button\";\nimport { Spinner } from \"../spinner\";\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\n/** The system's swap: fade through the 1px soft focus, ease-out. */\nconst FACE_SWAP = { duration: 0.2, ease: \"easeOut\" } as const;\n\nconst Provider = BaseToast.Provider;\nconst Portal = BaseToast.Portal;\nconst Action = BaseToast.Action;\n\n/** Imperative toast API: `const toast = useToastManager(); toast.add({ title })`. */\nconst useToastManager = BaseToast.useToastManager;\nconst createToastManager = BaseToast.createToastManager;\n\n/**\n * Status glyphs per toast `type` (Kumo's set in Tabler's hand): the glyph\n * and the title take the status ink, the hairline tints with it, and a\n * translucent wash of the same ink sits over the surface. `info` speaks\n * in the brand ink — Pho has no separate info hue. `loading` is what\n * `manager.promise` shows while the work runs.\n */\nconst TOAST_ICONS: Record<string, Icon> = {\n success: IconCircleCheckFilled,\n error: IconAlertOctagonFilled,\n warning: IconAlertTriangleFilled,\n info: IconInfoCircleFilled,\n};\n\nconst TOAST_WASH: Record<string, string> = {\n success:\n \"bg-[color-mix(in_oklab,var(--text-color-pho-success)_7%,transparent)]\",\n error: \"bg-[color-mix(in_oklab,var(--text-color-pho-error)_7%,transparent)]\",\n warning:\n \"bg-[color-mix(in_oklab,var(--text-color-pho-warning)_7%,transparent)]\",\n info: \"bg-[color-mix(in_oklab,var(--text-color-pho-brand)_7%,transparent)]\",\n};\n\nfunction Viewport({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Viewport>) {\n return (\n <BaseToast.Viewport\n // The stack's anchor box; the cards position themselves absolutely\n // against its bottom edge, and hovering any card expands the stack.\n className={cn(\n \"fixed right-4 bottom-4 z-50 flex w-[calc(100%-2rem)] outline-none sm:w-[22rem]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Root({ className, ...props }: StyledProps<typeof BaseToast.Root>) {\n return (\n <BaseToast.Root\n className={cn(\n // Floating layer: keeps its elevation shadow, sits on the card surface\n // with the site hairline (ring-pho-secondary).\n \"bg-pho-primary text-pho-primary shadow-pho-lg ring-pho-secondary rounded-base absolute right-0 bottom-0 w-full origin-bottom ring-1 select-none ring-inset\",\n // Kumo's stack math on Base UI's variables: a 12px gap folded into\n // the expanded offsets, a 12px peek and −10% scale per depth at\n // rest, the newest card on top.\n \"[--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))]\",\n \"[--offset-y:calc(var(--toast-offset-y)*-1+var(--toast-index)*var(--gap)*-1+var(--toast-swipe-movement-y,0px))]\",\n \"[z-index:calc(1000-var(--toast-index))] h-[var(--height)]\",\n \"[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(calc(var(--toast-swipe-movement-y,0px)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))]\",\n \"[transition:transform_0.5s_cubic-bezier(0.22,1,0.36,1),opacity_0.5s,height_0.15s,box-shadow_0.2s_ease-out]\",\n // Invisible bridge below each card so the hover survives the gaps.\n \"after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']\",\n // Hovering (or focusing) the stack expands it into a true list.\n \"data-[expanded]:h-[var(--toast-height)] data-[expanded]:[transform:translateX(var(--toast-swipe-movement-x,0px))_translateY(var(--offset-y))]\",\n // Beyond the provider's limit a card parks invisibly until room frees.\n \"data-[limited]:opacity-0\",\n // In from below; out along the swipe, or back down when timed out.\n \"data-[starting-style]:[transform:translateY(150%)]\",\n \"data-[ending-style]:opacity-0\",\n \"[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]\",\n \"data-[ending-style]:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y,0px)+150%))]\",\n \"data-[ending-style]:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y,0px)-150%))]\",\n \"data-[ending-style]:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x,0px)-150%))_translateY(var(--offset-y))]\",\n \"data-[ending-style]:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x,0px)+150%))_translateY(var(--offset-y))]\",\n \"data-[swiping]:[transition:none]\",\n // Status inks: hairline, glyph, and title tint together per type.\n \"data-[type=success]:[&_[data-toast-icon]]:text-pho-success data-[type=success]:[&_[data-toast-title]]:text-pho-success data-[type=success]:[&_[data-toast-action]]:text-pho-success data-[type=success]:[&_[data-toast-close]]:text-pho-success data-[type=success]:ring-[color-mix(in_oklab,var(--text-color-pho-success)_45%,transparent)] data-[type=success]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-success)_45%,transparent)]\",\n \"data-[type=error]:[&_[data-toast-icon]]:text-pho-error data-[type=error]:[&_[data-toast-title]]:text-pho-error data-[type=error]:[&_[data-toast-action]]:text-pho-error data-[type=error]:[&_[data-toast-close]]:text-pho-error data-[type=error]:ring-[color-mix(in_oklab,var(--text-color-pho-error)_45%,transparent)] data-[type=error]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-error)_45%,transparent)]\",\n \"data-[type=warning]:[&_[data-toast-icon]]:text-pho-warning data-[type=warning]:[&_[data-toast-title]]:text-pho-warning data-[type=warning]:[&_[data-toast-action]]:text-pho-warning data-[type=warning]:[&_[data-toast-close]]:text-pho-warning data-[type=warning]:ring-[color-mix(in_oklab,var(--text-color-pho-warning)_45%,transparent)] data-[type=warning]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-warning)_45%,transparent)]\",\n \"data-[type=info]:[&_[data-toast-icon]]:text-pho-brand data-[type=info]:[&_[data-toast-title]]:text-pho-brand data-[type=info]:[&_[data-toast-action]]:text-pho-brand data-[type=info]:[&_[data-toast-close]]:text-pho-brand data-[type=info]:ring-[color-mix(in_oklab,var(--text-color-pho-brand)_45%,transparent)] data-[type=info]:[&_[data-toast-action]]:ring-[color-mix(in_oklab,var(--text-color-pho-brand)_45%,transparent)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Content({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Content>) {\n return (\n <BaseToast.Content\n // Cards behind the front one show only their peeking edge — the\n // words appear when the stack expands.\n className={cn(\n \"isolate flex flex-col p-4 pr-10 transition-opacity [transition-duration:250ms]\",\n \"data-[behind]:pointer-events-none data-[behind]:opacity-0 data-[expanded]:pointer-events-auto data-[expanded]:opacity-100\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Title({ className, ...props }: StyledProps<typeof BaseToast.Title>) {\n return (\n <BaseToast.Title\n data-toast-title\n className={cn(\"text-pho-primary text-md font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction Description({\n className,\n ...props\n}: StyledProps<typeof BaseToast.Description>) {\n return (\n <BaseToast.Description\n className={cn(\"text-pho-description text-md\", className)}\n {...props}\n />\n );\n}\n\nfunction Close({ className, ...props }: StyledProps<typeof BaseToast.Close>) {\n return (\n <BaseToast.Close\n data-toast-close\n className={cn(\n \"text-pho-secondary hover:text-pho-secondary-hover hover:bg-pho-ghost-hover outline-pho-brand absolute top-2.5 right-2.5 flex size-6 cursor-pointer items-center justify-center rounded-sm transition focus-visible:outline-2 [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * The status glyph for a typed toast — its own row above the title, the\n * Dialog header's arrangement at card scale, an 8px breath before the\n * title. `loading` shows the spinner.\n */\nfunction TypeIcon({ type }: { type?: string }) {\n if (type === \"loading\") {\n return <Spinner aria-hidden className=\"mb-2 size-6 shrink-0\" />;\n }\n const Glyph = type != null ? TOAST_ICONS[type] : undefined;\n if (Glyph == null) return null;\n return <Glyph aria-hidden data-toast-icon className=\"mb-2 size-6 shrink-0\" />;\n}\n\nfunction ToastyList() {\n const { toasts, close } = BaseToast.useToastManager();\n const reduceMotion = useReducedMotion();\n const blurAway = reduceMotion ? \"blur(0px)\" : `blur(${BLUR_MAX_PX}px)`;\n return toasts.map((toast) => (\n <Root key={toast.id} toast={toast}>\n {/* The status wash: a breath of the status ink over the surface. */}\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 rounded-[inherit] transition-colors duration-200 ease-out\",\n toast.type != null ? TOAST_WASH[toast.type] : undefined,\n )}\n />\n <Content>\n {/* One grid cell, faces stacked: when a promise walks the card\n from loading to its outcome, the old face fades out through\n the system's soft focus exactly where the new one fades in —\n the values ride each face, so the goer keeps its words. */}\n <span className=\"grid\">\n <AnimatePresence initial={false}>\n <motion.div\n key={`${toast.type ?? \"\"}|${String(toast.title ?? \"\")}`}\n className=\"flex min-w-0 flex-col [grid-area:1/1]\"\n initial={{ opacity: 0, filter: blurAway }}\n animate={{ opacity: 1, filter: \"blur(0px)\" }}\n exit={{ opacity: 0, filter: blurAway }}\n transition={FACE_SWAP}\n >\n <TypeIcon type={toast.type} />\n <Title>{toast.title}</Title>\n <Description>{toast.description}</Description>\n {toast.actionProps != null ? (\n <Action\n data-toast-action\n render={<Button variant=\"outlined\" size=\"sm\" />}\n className=\"mt-2 self-start\"\n onClick={(event) => {\n toast.actionProps?.onClick?.(event);\n close(toast.id);\n }}\n >\n {toast.actionProps.children}\n </Action>\n ) : null}\n </motion.div>\n </AnimatePresence>\n </span>\n </Content>\n <Close aria-label=\"Dismiss\">\n <IconX />\n </Close>\n </Root>\n ));\n}\n\n/**\n * Toasty — the whole toast system in one wrapper, Kumo-shaped: provider,\n * portal, viewport, and the stacked card list with status variants. Wrap\n * the app once and call `Toast.useToastManager().add({ title, type })`\n * from any child; pass a `toastManager` from `createToastManager()` so\n * code outside the tree (a form's auto-save, a query cache) can speak\n * through the same lane. `manager.promise` shows loading → success/error\n * with the matching glyphs.\n */\nexport function Toasty({\n children,\n toastManager,\n}: {\n children?: ReactNode;\n toastManager?: ComponentProps<typeof BaseToast.Provider>[\"toastManager\"];\n}) {\n return (\n <Provider toastManager={toastManager}>\n {children}\n <Portal>\n <Viewport>\n <ToastyList />\n </Viewport>\n </Portal>\n </Provider>\n );\n}\n\n/**\n * Toast built on Base UI `Toast` — transient, non-blocking notifications\n * in a sonner-style stack, styled after Cloudflare's Kumo: at rest the\n * cards collapse into a peek (12px rise and −10% scale per depth, words\n * hidden behind the front card), expand into a true list with a 12px gap\n * on hover or focus, swipe to dismiss, three visible at most. `type`\n * (`success` / `error` / `warning` / `info` / `loading`) tints hairline,\n * glyph, and title together. Reach for `Toasty` unless you need to\n * compose the parts yourself.\n */\nexport const Toast = {\n Provider,\n Portal,\n Viewport,\n Root,\n Content,\n Title,\n Description,\n Close,\n Action,\n useToastManager,\n createToastManager,\n};\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
@@ -1,62 +0,0 @@
1
- "use client";
2
- import { useCallback as u, useEffect as w, useRef as f } from "react";
3
- import { useAnimationControls as E } from "motion/react";
4
- var L = {
5
- type: "spring",
6
- stiffness: 700,
7
- damping: 32,
8
- mass: 0.06
9
- }, R = 0.96;
10
- function S(l) {
11
- const p = l?.scale ?? 0.96, t = l?.disabled ?? !1, s = l?.transition ?? L, n = E(), i = f(!1), d = f(null), r = f(null);
12
- w(() => () => r.current?.(), []);
13
- const o = u(() => {
14
- t || (i.current = !0, d.current = n.start({
15
- scale: p,
16
- transition: s
17
- }));
18
- }, [
19
- n,
20
- t,
21
- p,
22
- s
23
- ]), c = u(async () => {
24
- if (!i.current) return;
25
- i.current = !1;
26
- const e = d.current;
27
- await e, !(i.current || d.current !== e) && n.start({
28
- scale: 1,
29
- transition: s
30
- });
31
- }, [n, s]);
32
- return {
33
- pulse: u(() => {
34
- o(), c();
35
- }, [o, c]),
36
- motionProps: {
37
- initial: !1,
38
- animate: n,
39
- onPointerDown: u((e) => {
40
- if (t || e.button !== 0 || !e.isPrimary) return;
41
- o(), r.current?.();
42
- const a = (m) => {
43
- m.pointerId === e.pointerId && (r.current?.(), c());
44
- };
45
- window.addEventListener("pointerup", a), window.addEventListener("pointercancel", a), r.current = () => {
46
- window.removeEventListener("pointerup", a), window.removeEventListener("pointercancel", a), r.current = null;
47
- };
48
- }, [
49
- t,
50
- o,
51
- c
52
- ])
53
- }
54
- };
55
- }
56
- export {
57
- L as n,
58
- S as r,
59
- R as t
60
- };
61
-
62
- //# sourceMappingURL=use-press-pulse-8iorQPsh.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-press-pulse-8iorQPsh.js","names":[],"sources":["../../src/utils/use-press-pulse.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\nimport { useAnimationControls, type Transition } from \"motion/react\";\n\n/**\n * Press feedback for selection controls (Select trigger, Checkbox…) — the same\n * spring family as Button's effect press, and the same pointer-following\n * behavior: press in on pointer-down, stay compressed while held, spring back\n * on release. One deliberate refinement over a bare `whileTap`: a fast tap\n * never truncates the press-in leg — it always reaches full depth before\n * springing back, so even the quickest click reads as a complete tick.\n */\nexport const CONTROL_PRESS_SPRING = {\n type: \"spring\",\n stiffness: 700,\n damping: 32,\n mass: 0.06,\n} as const;\n\n/** Default press depth — shallow; each control can tune its own. */\nexport const CONTROL_PRESS_SCALE = 0.96;\n\n/**\n * Pointer-following press driven by Motion controls. Spread `motionProps` onto\n * a `motion.*` element (via Base UI `render`): pointer-down (primary button)\n * compresses and holds; release springs back once the press-in leg has\n * finished. Release is tracked on `window`, so dragging off the control before\n * letting go still restores it.\n */\nexport function usePressPulse(opts?: {\n scale?: number;\n disabled?: boolean;\n /** Spring override for both legs of the press. @default CONTROL_PRESS_SPRING */\n transition?: Transition;\n}) {\n const scale = opts?.scale ?? CONTROL_PRESS_SCALE;\n const disabled = opts?.disabled ?? false;\n const transition = opts?.transition ?? CONTROL_PRESS_SPRING;\n const controls = useAnimationControls();\n const pressed = useRef(false);\n const pressIn = useRef<Promise<unknown> | null>(null);\n const removeListeners = useRef<(() => void) | null>(null);\n\n useEffect(() => () => removeListeners.current?.(), []);\n\n const press = useCallback(() => {\n if (disabled) return;\n pressed.current = true;\n pressIn.current = controls.start({ scale, transition });\n }, [controls, disabled, scale, transition]);\n\n const release = useCallback(async () => {\n if (!pressed.current) return;\n pressed.current = false;\n const leg = pressIn.current;\n // Let the press-in leg play out in full before springing back, so a tap\n // shorter than the spring still shows the whole press.\n await leg;\n // A re-press started while we waited — its own release will restore.\n if (pressed.current || pressIn.current !== leg) return;\n void controls.start({ scale: 1, transition });\n }, [controls, transition]);\n\n /** Programmatic one-shot pulse (press in, then spring back). */\n const pulse = useCallback(() => {\n press();\n void release();\n }, [press, release]);\n\n const onPointerDown = useCallback(\n (event: { button: number; pointerId: number; isPrimary: boolean }) => {\n if (disabled || event.button !== 0 || !event.isPrimary) return;\n press();\n // The pointer may be released anywhere (including off the control after\n // dragging away), so listen on window rather than the element — but only\n // for the pointer that started this press, so another finger lifting\n // elsewhere doesn't spring the control back early.\n removeListeners.current?.();\n const end = (e: PointerEvent) => {\n if (e.pointerId !== event.pointerId) return;\n removeListeners.current?.();\n void release();\n };\n window.addEventListener(\"pointerup\", end);\n window.addEventListener(\"pointercancel\", end);\n removeListeners.current = () => {\n window.removeEventListener(\"pointerup\", end);\n window.removeEventListener(\"pointercancel\", end);\n removeListeners.current = null;\n };\n },\n [disabled, press, release],\n );\n\n return {\n pulse,\n motionProps: { initial: false as const, animate: controls, onPointerDown },\n };\n}\n"],"mappings":";;;AAWA,IAAa,IAAuB;AAAA,EAClC,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,MAAM;AACR,GAGa,IAAsB;AASnC,SAAgB,EAAc,GAK3B;AACD,QAAM,IAAQ,GAAM,SAAA,MACd,IAAW,GAAM,YAAY,IAC7B,IAAa,GAAM,cAAc,GACjC,IAAW,EAAqB,GAChC,IAAU,EAAO,EAAK,GACtB,IAAU,EAAgC,IAAI,GAC9C,IAAkB,EAA4B,IAAI;AAExD,EAAA,EAAA,MAAA,MAAsB,EAAgB,UAAU,GAAG,CAAC,CAAC;AAErD,QAAM,IAAQ,EAAA,MAAkB;AAC9B,IAAI,MACJ,EAAQ,UAAU,IAClB,EAAQ,UAAU,EAAS,MAAM;AAAA,MAAE,OAAA;AAAA,MAAO,YAAA;AAAA,IAAW,CAAC;AAAA,EACxD,GAAG;AAAA,IAAC;AAAA,IAAU;AAAA,IAAU;AAAA,IAAO;AAAA,EAAU,CAAC,GAEpC,IAAU,EAAY,YAAY;AACtC,QAAI,CAAC,EAAQ,QAAS;AACtB,IAAA,EAAQ,UAAU;AAClB,UAAM,IAAM,EAAQ;AAKpB,IAFA,MAAM,GAEF,EAAA,EAAQ,WAAW,EAAQ,YAAY,MAC3C,EAAc,MAAM;AAAA,MAAE,OAAO;AAAA,MAAG,YAAA;AAAA,IAAW,CAAC;AAAA,EAC9C,GAAG,CAAC,GAAU,CAAU,CAAC;AAiCzB,SAAO;AAAA,IACL,OA/BY,EAAA,MAAkB;AAC9B,MAAA,EAAM,GACN,EAAa;AAAA,IACf,GAAG,CAAC,GAAO,CAAO,CA4BhB;AAAA,IACA,aAAa;AAAA,MAAE,SAAS;AAAA,MAAgB,SAAS;AAAA,MAAU,eA3BvC,EAAA,CACnB,MAAqE;AACpE,YAAI,KAAY,EAAM,WAAW,KAAK,CAAC,EAAM,UAAW;AACxD,QAAA,EAAM,GAKN,EAAgB,UAAU;AAC1B,cAAM,IAAA,CAAO,MAAoB;AAC/B,UAAI,EAAE,cAAc,EAAM,cAC1B,EAAgB,UAAU,GAC1B,EAAa;AAAA,QACf;AACA,eAAO,iBAAiB,aAAa,CAAG,GACxC,OAAO,iBAAiB,iBAAiB,CAAG,GAC5C,EAAgB,UAAA,MAAgB;AAC9B,iBAAO,oBAAoB,aAAa,CAAG,GAC3C,OAAO,oBAAoB,iBAAiB,CAAG,GAC/C,EAAgB,UAAU;AAAA,QAC5B;AAAA,MACF,GACA;AAAA,QAAC;AAAA,QAAU;AAAA,QAAO;AAAA,MAAO,CAKkC;AAAA,IAAc;AAAA,EAC3E;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"checkbox.js","names":[],"sources":["../../src/components/checkbox/check-glyph.tsx","../../src/components/checkbox/checkbox.tsx","../../src/components/checkbox/checkbox-group.tsx","../../src/components/checkbox/checkbox-card.tsx"],"sourcesContent":["import { motion } from \"motion/react\";\n\n// Tabler's IconCheck / IconMinus paths, redrawn as a single animatable\n// `motion.path` — same 24×24 outline geometry (stroke 2, round caps/joins),\n// so the glyph matches every other Tabler-sourced icon at rest.\nconst CHECK_PATH = \"M5 12l5 5l10 -10\";\nconst MINUS_PATH = \"M5 12l14 0\";\n\nconst DRAW_TRANSITION = { duration: 0.22, ease: \"easeOut\" } as const;\n\n/**\n * The checkbox glyph, stroked on rather than popped in solid — same\n * considered-motion spirit as Button's press/wake effects. Re-keyed per\n * state (check vs. dash) so every appearance draws fresh from empty instead\n * of resuming a stroke left mid-way by whatever the glyph showed before.\n */\nexport function DrawnCheckGlyph({\n indeterminate,\n className,\n}: {\n indeterminate?: boolean;\n className?: string;\n}) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <motion.path\n key={indeterminate ? \"minus\" : \"check\"}\n d={indeterminate ? MINUS_PATH : CHECK_PATH}\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={DRAW_TRANSITION}\n />\n </svg>\n );\n}\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\n\nexport type CheckboxSize = \"sm\" | \"md\";\n\nconst BOX: Record<CheckboxSize, string> = { sm: \"size-4\", md: \"size-5\" };\nconst ICON: Record<CheckboxSize, string> = { sm: \"size-3\", md: \"size-3.5\" };\n\nexport interface CheckboxProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\"\n> {\n className?: string;\n /** Text rendered beside the box; the whole row toggles the checkbox. */\n label?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: CheckboxSize;\n}\n\n/**\n * Checkbox built on Base UI `Checkbox`. Supports checked, unchecked, and\n * `indeterminate` states; pass `label` for a clickable text row, or omit it\n * and provide an `aria-label`. For a set of related options that submit\n * together, wrap them in `CheckboxGroup`.\n *\n * Animation is the Effect Button family scaled to a toggle, kept restrained:\n * a quick shallow press pulse on pointer-down (always plays out), the\n * fill/stroke easing between states, and the glyph popping in.\n */\nexport function Checkbox({\n className,\n label,\n size = \"md\",\n disabled,\n indeterminate,\n ...props\n}: CheckboxProps) {\n const { motionProps } = usePressPulse({\n scale: 0.94,\n disabled: Boolean(disabled),\n });\n // With a label, the whole row is the hit target — press-trigger from there\n // (pointerdown bubbles up from the label text too) so the box still\n // animates when the text, not the box itself, is what's clicked.\n const { onPointerDown, ...boxMotionProps } = motionProps;\n\n const box = (\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n render={\n <motion.span\n {...boxMotionProps}\n onPointerDown={label ? undefined : onPointerDown}\n />\n }\n className={cn(\n // Flat field surface with the input-strength ring; the glyph only shows\n // on the brand-solid checked fill, so it must be on-brand (not white —\n // brand-solid is white in dark mode).\n \"group/cb outline-pho-brand bg-pho-primary ring-pho-primary text-pho-on-brand flex shrink-0 cursor-pointer items-center justify-center rounded-sm ring-1 ring-inset focus-visible:outline-2 focus-visible:outline-offset-2\",\n // Fill and stroke ease between states (stroke dissolves into the\n // fill on tick). Transform stays out — Motion owns the press pulse.\n \"transition-[background-color,box-shadow,color,outline-color] duration-150 ease-out\",\n // group-hover covers hovering the label text, not just the box itself.\n \"hover:bg-pho-primary-hover hover:ring-pho-ink group-hover:bg-pho-primary-hover group-hover:ring-pho-ink\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:ring-transparent\",\n \"data-[checked]:hover:bg-pho-brand-solid-hover data-[checked]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[indeterminate]:hover:bg-pho-brand-solid-hover data-[indeterminate]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n BOX[size],\n className,\n )}\n {...props}\n >\n {/* The glyph draws itself on (see DrawnCheckGlyph) — no separate\n pop-in needed. A quick fade covers the exit, since an unmount\n can't play the stroke backwards. */}\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph indeterminate={indeterminate} className={ICON[size]} />\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n\n if (!label) return box;\n return (\n <label\n className=\"group flex cursor-pointer items-center gap-2 select-none\"\n onPointerDown={onPointerDown}\n >\n {box}\n <span className=\"text-pho-secondary text-base\">{label}</span>\n </label>\n );\n}\n\nCheckbox.displayName = \"Checkbox\";\n","import { type ComponentProps } from \"react\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface CheckboxGroupProps extends Omit<\n ComponentProps<typeof BaseCheckboxGroup>,\n \"className\"\n> {\n className?: string;\n}\n\n/**\n * Groups related `Checkbox`es and tracks their values as one. Built on Base UI\n * `CheckboxGroup` — supports a parent \"select all\" checkbox via `allValues`.\n * Control with `value` / `onValueChange` or leave uncontrolled with\n * `defaultValue`.\n */\nexport function CheckboxGroup({ className, ...props }: CheckboxGroupProps) {\n return (\n <BaseCheckboxGroup\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n />\n );\n}\n\nCheckboxGroup.displayName = \"CheckboxGroup\";\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\nimport {\n CHOICE_CARD_BASE,\n CHOICE_CARD_WITH_ICON,\n CHOICE_CARD_PRESS_SCALE,\n CHOICE_CARD_PRESS_TRANSITION,\n} from \"../../utils/choice-card\";\n\nexport interface CheckboxCardProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\" | \"title\"\n> {\n className?: string;\n /** Tile heading. */\n title: ReactNode;\n /** Supporting copy shown below the title. */\n description?: ReactNode;\n /** Glyph stacked above the title. When set, it replaces the checkbox box. */\n icon?: ReactNode;\n}\n\nfunction CardCopy({\n title,\n description,\n}: {\n title: ReactNode;\n description?: ReactNode;\n}) {\n return (\n <span>\n <span className=\"text-pho-primary block\">{title}</span>\n {description ? (\n <span className=\"text-pho-description block\">{description}</span>\n ) : null}\n </span>\n );\n}\n\n/**\n * A `Checkbox` styled as a bordered, selectable tile — title, optional\n * description, and either a stacked icon or the checkbox box. The tile is a\n * `<label>` around the control so clicks (including on the icon/title) are a\n * trusted activation of the hidden input Base UI renders beside the root.\n */\nexport function CheckboxCard({\n className,\n title,\n description,\n icon,\n disabled,\n indeterminate,\n ...props\n}: CheckboxCardProps) {\n const { motionProps } = usePressPulse({\n scale: CHOICE_CARD_PRESS_SCALE,\n disabled: Boolean(disabled),\n transition: CHOICE_CARD_PRESS_TRANSITION,\n });\n const hasIcon = icon != null;\n\n return (\n <motion.label\n {...motionProps}\n className={cn(\n CHOICE_CARD_BASE,\n hasIcon && CHOICE_CARD_WITH_ICON,\n className,\n )}\n data-disabled={disabled ? \"\" : undefined}\n >\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n className={\n hasIcon\n ? \"sr-only\"\n : cn(\n \"bg-pho-primary ring-pho-primary text-pho-on-brand mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-sm ring-1 ring-inset\",\n \"group-hover:bg-pho-primary-hover group-hover:ring-pho-ink transition-[background-color,box-shadow,color] duration-150 ease-out\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:group-hover:bg-pho-brand-solid-hover data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:group-hover:bg-pho-brand-solid-hover data-[indeterminate]:ring-transparent\",\n )\n }\n {...props}\n >\n {hasIcon ? null : (\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph\n indeterminate={indeterminate}\n className=\"size-2.5\"\n />\n </BaseCheckbox.Indicator>\n )}\n </BaseCheckbox.Root>\n {hasIcon ? (\n <span\n aria-hidden\n className=\"text-pho-secondary flex size-6 shrink-0 items-center justify-center [&>svg]:size-6\"\n >\n {icon}\n </span>\n ) : null}\n <CardCopy title={title} description={description} />\n </motion.label>\n );\n}\n\nCheckboxCard.displayName = \"CheckboxCard\";\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"skeleton.js","names":[],"sources":["../../src/components/skeleton/skeleton.tsx"],"sourcesContent":["import { forwardRef, type ComponentProps } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface SkeletonProps extends ComponentProps<\"div\"> {}\n\n/**\n * A pulsing placeholder bone for loading surfaces. Size and shape come from\n * `className` (`h-*`, `w-*`, `rounded-full`, …) — the component only supplies\n * the wash and motion. Decorative by default (`aria-hidden`); mark the\n * surrounding region with `aria-busy` / `aria-label` instead of labeling each\n * bone. Prefer `Spinner` when a single control is pending.\n */\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(\n function Skeleton({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n aria-hidden\n className={cn(\n \"bg-pho-secondary animate-pho-skeleton rounded-sm\",\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nSkeleton.displayName = \"Skeleton\";\n"],"mappings":";;;;AAYA,IAAa,IAAW,EACtB,SAAkB,EAAE,WAAA,GAAW,GAAG,EAAA,GAAS,GAAK;AAC9C,SACE,gBAAA,EAAC,OAAD;AAAA,IACO,KAAA;AAAA,IACL,eAAA;AAAA,IACA,WAAW,EACT,oDACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL,CACF;AAEA,EAAS,cAAc"}