@photon-ai/pho-ui 1.1.0 → 1.2.1

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 (53) hide show
  1. package/dist/chunks/IconCheck-D2WuculQ.js +11 -0
  2. package/dist/chunks/IconCheck-D2WuculQ.js.map +1 -0
  3. package/dist/chunks/card-9cGnv-VD.js +56 -0
  4. package/dist/chunks/card-9cGnv-VD.js.map +1 -0
  5. package/dist/chunks/{input-BSJGBUbf.js → input-CxS7ndpb.js} +7 -7
  6. package/dist/chunks/input-CxS7ndpb.js.map +1 -0
  7. package/dist/chunks/input-group-D6dlma8k.js +85 -0
  8. package/dist/chunks/input-group-D6dlma8k.js.map +1 -0
  9. package/dist/chunks/{menu-Dan0oRvL.js → menu-BSXds3Rt.js} +2 -2
  10. package/dist/chunks/{menu-Dan0oRvL.js.map → menu-BSXds3Rt.js.map} +1 -1
  11. package/dist/chunks/settings-B0vhLoMi.js +134 -0
  12. package/dist/chunks/settings-B0vhLoMi.js.map +1 -0
  13. package/dist/chunks/sidebar-BCqq58hV.js +177 -0
  14. package/dist/chunks/sidebar-BCqq58hV.js.map +1 -0
  15. package/dist/chunks/use-press-pulse-8iorQPsh.js +62 -0
  16. package/dist/chunks/use-press-pulse-8iorQPsh.js.map +1 -0
  17. package/dist/components/card.js +6 -0
  18. package/dist/components/checkbox.js +33 -28
  19. package/dist/components/checkbox.js.map +1 -1
  20. package/dist/components/context-menu.js +2 -2
  21. package/dist/components/field.js +17 -17
  22. package/dist/components/field.js.map +1 -1
  23. package/dist/components/input-group.js +5 -0
  24. package/dist/components/input.js +1 -1
  25. package/dist/components/menu.js +1 -1
  26. package/dist/components/select.js +83 -39
  27. package/dist/components/select.js.map +1 -1
  28. package/dist/index.js +48 -35
  29. package/dist/primitives.js +1 -1
  30. package/dist/sections/settings.js +5 -4
  31. package/dist/sections/sidebar.js +8 -5
  32. package/dist/src/components/card/card.d.ts +75 -0
  33. package/dist/src/components/card/index.d.ts +1 -0
  34. package/dist/src/components/checkbox/checkbox.d.ts +5 -1
  35. package/dist/src/components/input-group/index.d.ts +1 -0
  36. package/dist/src/components/input-group/input-group.d.ts +57 -0
  37. package/dist/src/components/select/index.d.ts +1 -1
  38. package/dist/src/components/select/select.d.ts +29 -10
  39. package/dist/src/index.d.ts +2 -0
  40. package/dist/src/sections/settings/index.d.ts +1 -1
  41. package/dist/src/sections/settings/settings.d.ts +71 -29
  42. package/dist/src/sections/sidebar/index.d.ts +1 -1
  43. package/dist/src/sections/sidebar/sidebar.d.ts +21 -3
  44. package/dist/src/utils/index.d.ts +1 -0
  45. package/dist/src/utils/use-press-pulse.d.ts +41 -0
  46. package/dist/utils.js +12 -8
  47. package/package.json +9 -1
  48. package/src/styles/theme.css +7 -4
  49. package/dist/chunks/input-BSJGBUbf.js.map +0 -1
  50. package/dist/chunks/settings-B3ilbRcF.js +0 -104
  51. package/dist/chunks/settings-B3ilbRcF.js.map +0 -1
  52. package/dist/chunks/sidebar-C5cIhWs1.js +0 -164
  53. package/dist/chunks/sidebar-C5cIhWs1.js.map +0 -1
@@ -3,19 +3,32 @@ import { ComponentProps, ReactNode, Ref } from 'react';
3
3
  * Settings — Pho's settings-page section: a page title, section titles, and
4
4
  * bordered cards of label/control rows.
5
5
  *
6
- * Spacing: `Stack` separates blocks (`gap-10`). Inside a block, children share
7
- * `gap-3`. Wrap a section title + description in `Header` (`gap-0.5`) so that
8
- * pair stays tight — don't put them as loose siblings. Host the page at
9
- * `max-w-xl` (parts already carry `px-5`).
6
+ * Spacing: wrap the page in `Page` (`max-w-2xl`, vertical padding). `Stack`
7
+ * separates blocks (`gap-10`). Inside a block, children share `gap-3`. Wrap a
8
+ * section title + description in `Header` (`gap-0.5`) so that pair stays tight
9
+ * — don't put them as loose siblings. Parts already carry `px-5`.
10
10
  */
11
11
  /** Bordered card that stacks rows with hairline dividers. */
12
12
  export declare const SETTINGS_CARD = "divide-y divide-pho-secondary rounded-base border border-pho-secondary bg-pho-primary";
13
+ /**
14
+ * Standalone callout surface — featured block (invite form, notice, etc.).
15
+ * Don't wrap in `Card`; this is the outer chrome.
16
+ */
17
+ export declare const SETTINGS_CALLOUT = "flex flex-col gap-3 rounded-base border border-pho-secondary bg-pho-page p-5";
13
18
  /**
14
19
  * One settings row — label (+ optional description) left, control right.
15
20
  * `min-h-[4.25rem]` (68px) keeps avatar/control rows from collapsing shorter
16
21
  * than a comfortable touch target.
17
22
  */
18
23
  export declare const SETTINGS_ROW = "flex min-h-[4.25rem] flex-col gap-3 px-5 py-4 sm:flex-row sm:items-center sm:justify-between sm:gap-6";
24
+ /**
25
+ * Page chrome — centered column at the settings content width. Hosts
26
+ * `PageTitle` + `Stack` (and any route-level siblings). Prefer this over
27
+ * ad-hoc `max-w-*` wrappers in the app shell.
28
+ */
29
+ declare function Page({ className, ...props }: ComponentProps<"div"> & {
30
+ ref?: Ref<HTMLDivElement>;
31
+ }): import("react").JSX.Element;
19
32
  /** Page title — largest heading on the surface. */
20
33
  declare function PageTitle({ className, children, ...props }: ComponentProps<"h1"> & {
21
34
  ref?: Ref<HTMLHeadingElement>;
@@ -49,6 +62,22 @@ declare function Description({ className, ...props }: ComponentProps<"p"> & {
49
62
  declare function Card({ className, ...props }: ComponentProps<"div"> & {
50
63
  ref?: Ref<HTMLDivElement>;
51
64
  }): import("react").JSX.Element;
65
+ /**
66
+ * Standalone callout. Pair with `CalloutTitle` / `CalloutDescription` (and
67
+ * optional actions) for a featured block — e.g. an invite form. Do not wrap
68
+ * in `Card`; this is already the outer surface.
69
+ */
70
+ declare function Callout({ className, ...props }: ComponentProps<"div"> & {
71
+ ref?: Ref<HTMLDivElement>;
72
+ }): import("react").JSX.Element;
73
+ /** Callout heading — same type as `SectionTitle`. */
74
+ declare function CalloutTitle({ className, children, ...props }: ComponentProps<"h2"> & {
75
+ ref?: Ref<HTMLHeadingElement>;
76
+ }): import("react").JSX.Element;
77
+ /** Supporting copy under a callout title. */
78
+ declare function CalloutDescription({ className, ...props }: ComponentProps<"p"> & {
79
+ ref?: Ref<HTMLParagraphElement>;
80
+ }): import("react").JSX.Element;
52
81
  export interface SettingsRowProps extends Omit<ComponentProps<"div">, "title"> {
53
82
  /** Left-side field name. */
54
83
  label: string;
@@ -86,40 +115,53 @@ declare function Footer({ className, ...props }: ComponentProps<"div"> & {
86
115
  * Settings page layout. One stack, one gap rhythm — only title scale differs:
87
116
  *
88
117
  * ```tsx
89
- * <Settings.PageTitle>Profile</Settings.PageTitle>
90
- * <Settings.Stack>
91
- * <form>
92
- * <Settings.Card>
93
- * <Settings.Row label="Name" htmlFor="first-name">
94
- * <Input id="first-name" size="sm" />
95
- * </Settings.Row>
96
- * </Settings.Card>
97
- * </form>
98
- * <form>
99
- * <Settings.Header>
100
- * <Settings.SectionTitle>Agent profile</Settings.SectionTitle>
101
- * <Settings.Description>…</Settings.Description>
102
- * </Settings.Header>
103
- * <Settings.Card>…</Settings.Card>
104
- * </form>
105
- * <div>
106
- * <Settings.SectionTitle>Danger zone</Settings.SectionTitle>
107
- * <Settings.Card>
108
- * <Settings.Row label="Delete account" description="…">
109
- * <Button color="destructive" size="sm">Delete</Button>
110
- * </Settings.Row>
111
- * </Settings.Card>
112
- * </div>
113
- * </Settings.Stack>
118
+ * <Settings.Page>
119
+ * <Settings.PageTitle>Profile</Settings.PageTitle>
120
+ * <Settings.Stack>
121
+ * <form>
122
+ * <Settings.Card>
123
+ * <Settings.Row label="Name" htmlFor="first-name">
124
+ * <Input id="first-name" size="sm" />
125
+ * </Settings.Row>
126
+ * </Settings.Card>
127
+ * </form>
128
+ * <form>
129
+ * <Settings.Header>
130
+ * <Settings.SectionTitle>Agent profile</Settings.SectionTitle>
131
+ * <Settings.Description>…</Settings.Description>
132
+ * </Settings.Header>
133
+ * <Settings.Card>…</Settings.Card>
134
+ * </form>
135
+ * <div>
136
+ * <Settings.SectionTitle>Danger zone</Settings.SectionTitle>
137
+ * <Settings.Card>
138
+ * <Settings.Row label="Delete account" description="…">
139
+ * <Button color="destructive" size="sm">Delete</Button>
140
+ * </Settings.Row>
141
+ * </Settings.Card>
142
+ * </div>
143
+ * <Settings.Callout>
144
+ * <Settings.Header>
145
+ * <Settings.CalloutTitle>Invitations</Settings.CalloutTitle>
146
+ * <Settings.CalloutDescription>…</Settings.CalloutDescription>
147
+ * </Settings.Header>
148
+ * …invite form…
149
+ * </Settings.Callout>
150
+ * </Settings.Stack>
151
+ * </Settings.Page>
114
152
  * ```
115
153
  */
116
154
  export declare const Settings: {
155
+ Page: typeof Page;
117
156
  PageTitle: typeof PageTitle;
118
157
  Stack: typeof Stack;
119
158
  Header: typeof Header;
120
159
  SectionTitle: typeof SectionTitle;
121
160
  Description: typeof Description;
122
161
  Card: typeof Card;
162
+ Callout: typeof Callout;
163
+ CalloutTitle: typeof CalloutTitle;
164
+ CalloutDescription: typeof CalloutDescription;
123
165
  Row: typeof Row;
124
166
  Value: typeof Value;
125
167
  Alert: typeof Alert;
@@ -1 +1 @@
1
- export { Sidebar, SIDEBAR_ROOT, SIDEBAR_ITEM, SIDEBAR_ITEM_ACTIVE, SIDEBAR_ITEM_INACTIVE, type SidebarItemProps, type SidebarItemLinkProps, type SidebarItemButtonProps, type SidebarAccountRowProps, } from './sidebar';
1
+ export { Sidebar, SIDEBAR_ROOT, SIDEBAR_ROOT_BASE, SIDEBAR_ROOT_INSET, SIDEBAR_HEADER_INSET, SIDEBAR_ITEM, SIDEBAR_ITEM_ACTIVE, SIDEBAR_ITEM_INACTIVE, type SidebarInset, type SidebarItemProps, type SidebarItemLinkProps, type SidebarItemButtonProps, type SidebarAccountRowProps, } from './sidebar';
@@ -11,9 +11,25 @@ import { AnchorHTMLAttributes, ButtonHTMLAttributes, ComponentProps, FC, ReactNo
11
11
  * `ButtonLink`), state arrives via props (`active`), and interactive footers
12
12
  * compose with other Pho parts (e.g. wrap `Sidebar.AccountRow` in a
13
13
  * `Menu.Trigger render={...}` to open an account menu).
14
+ *
15
+ * `Root` takes `inset` (`base` | `sm`, default `base`) for the rail's outer
16
+ * padding and header spacing — prefer that over host-app class overrides.
14
17
  */
15
- /** The rail itself — sticky, full-height, hairline right edge. */
16
- export declare const SIDEBAR_ROOT = "border-pho-secondary bg-pho-page sticky top-0 flex h-dvh w-64 shrink-0 flex-col border-r px-4 pt-5 pb-4";
18
+ /** The rail itself — sticky, full-height, hairline right edge (no inset). */
19
+ export declare const SIDEBAR_ROOT = "border-pho-secondary bg-pho-page sticky top-0 flex h-dvh w-64 shrink-0 flex-col border-r";
20
+ /** Outer inset on `Root` — `base` is the docs/default rail; `sm` is tighter. */
21
+ export declare const SIDEBAR_ROOT_INSET: {
22
+ readonly base: "px-4 pt-5 pb-4";
23
+ readonly sm: "px-3 pt-4 pb-3";
24
+ };
25
+ /** `SIDEBAR_ROOT` with the default `base` inset — one string for docs chrome. */
26
+ export declare const SIDEBAR_ROOT_BASE: string;
27
+ /** Header spacing paired with `Root`'s `inset`. */
28
+ export declare const SIDEBAR_HEADER_INSET: {
29
+ readonly base: "mb-6 px-2";
30
+ readonly sm: "mb-3 px-0";
31
+ };
32
+ export type SidebarInset = keyof typeof SIDEBAR_ROOT_INSET;
17
33
  /** A nav row at rest and on hover. Active/inactive inks split below. */
18
34
  export declare const SIDEBAR_ITEM = "outline-pho-brand flex min-h-8 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";
19
35
  /**
@@ -28,10 +44,12 @@ export declare const SIDEBAR_ITEM_ACTIVE = "bg-pho-primary text-pho-primary ring
28
44
  */
29
45
  export declare const SIDEBAR_ITEM_INACTIVE: string;
30
46
  interface RootProps extends ComponentProps<"aside"> {
47
+ /** Outer padding + header spacing. Defaults to `base`. */
48
+ inset?: SidebarInset;
31
49
  ref?: Ref<HTMLElement>;
32
50
  }
33
51
  /** The rail — a sticky, full-height `<aside>` with the hairline right edge. */
34
- declare function Root({ className, ...props }: RootProps): import("react").JSX.Element;
52
+ declare function Root({ className, inset, ...props }: RootProps): import("react").JSX.Element;
35
53
  /** Brand slot at the top of the rail — logo, wordmark, workspace switcher. */
36
54
  declare function Header({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
37
55
  /** The scrollable middle — a stack of `Sidebar.Group`s. */
@@ -2,3 +2,4 @@ export { cn } from './cn';
2
2
  export { isReactComponent } from './is-react-component';
3
3
  export { resolveVariant, type VariantDef, type VariantMap, } from './resolve-variant';
4
4
  export { LinkProvider, useLinkComponent, type LinkComponent, } from './link-provider';
5
+ export { usePressPulse, CONTROL_PRESS_SCALE, CONTROL_PRESS_SPRING, } from './use-press-pulse';
@@ -0,0 +1,41 @@
1
+ import { Transition } from 'motion/react';
2
+ /**
3
+ * Press feedback for selection controls (Select trigger, Checkbox…) — the same
4
+ * spring family as Button's effect press, and the same pointer-following
5
+ * behavior: press in on pointer-down, stay compressed while held, spring back
6
+ * on release. One deliberate refinement over a bare `whileTap`: a fast tap
7
+ * never truncates the press-in leg — it always reaches full depth before
8
+ * springing back, so even the quickest click reads as a complete tick.
9
+ */
10
+ export declare const CONTROL_PRESS_SPRING: {
11
+ readonly type: "spring";
12
+ readonly stiffness: 700;
13
+ readonly damping: 32;
14
+ readonly mass: 0.06;
15
+ };
16
+ /** Default press depth — shallow; each control can tune its own. */
17
+ export declare const CONTROL_PRESS_SCALE = 0.96;
18
+ /**
19
+ * Pointer-following press driven by Motion controls. Spread `motionProps` onto
20
+ * a `motion.*` element (via Base UI `render`): pointer-down (primary button)
21
+ * compresses and holds; release springs back once the press-in leg has
22
+ * finished. Release is tracked on `window`, so dragging off the control before
23
+ * letting go still restores it.
24
+ */
25
+ export declare function usePressPulse(opts?: {
26
+ scale?: number;
27
+ disabled?: boolean;
28
+ /** Spring override for both legs of the press. @default CONTROL_PRESS_SPRING */
29
+ transition?: Transition;
30
+ }): {
31
+ pulse: () => void;
32
+ motionProps: {
33
+ initial: false;
34
+ animate: import('motion/react').LegacyAnimationControls;
35
+ onPointerDown: (event: {
36
+ button: number;
37
+ pointerId: number;
38
+ isPrimary: boolean;
39
+ }) => void;
40
+ };
41
+ };
package/dist/utils.js CHANGED
@@ -1,11 +1,15 @@
1
1
  "use client";
2
- import { t as r } from "./chunks/cn-DTiB6ek_.js";
3
- import { n as e, r as n, t as i } from "./chunks/link-provider-9TFNyDqO.js";
4
- import { t as a } from "./chunks/resolve-variant-CcD8iG5l.js";
2
+ import { t as s } from "./chunks/cn-DTiB6ek_.js";
3
+ import { n as t, r as e, t as a } from "./chunks/link-provider-9TFNyDqO.js";
4
+ import { t as i } from "./chunks/resolve-variant-CcD8iG5l.js";
5
+ import { n as p, r as P, t as R } from "./chunks/use-press-pulse-8iorQPsh.js";
5
6
  export {
6
- i as LinkProvider,
7
- r as cn,
8
- n as isReactComponent,
9
- a as resolveVariant,
10
- e as useLinkComponent
7
+ R as CONTROL_PRESS_SCALE,
8
+ p as CONTROL_PRESS_SPRING,
9
+ a as LinkProvider,
10
+ s as cn,
11
+ e as isReactComponent,
12
+ i as resolveVariant,
13
+ t as useLinkComponent,
14
+ P as usePressPulse
11
15
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@photon-ai/pho-ui",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Pho Design System — Photon's React component library, built on Base UI",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -37,6 +37,14 @@
37
37
  "types": "./dist/src/components/input/index.d.ts",
38
38
  "import": "./dist/components/input.js"
39
39
  },
40
+ "./components/input-group": {
41
+ "types": "./dist/src/components/input-group/index.d.ts",
42
+ "import": "./dist/components/input-group.js"
43
+ },
44
+ "./components/card": {
45
+ "types": "./dist/src/components/card/index.d.ts",
46
+ "import": "./dist/components/card.js"
47
+ },
40
48
  "./components/dialog": {
41
49
  "types": "./dist/src/components/dialog/index.d.ts",
42
50
  "import": "./dist/components/dialog.js"
@@ -280,9 +280,11 @@
280
280
  oklch(0 0 0 / 0.08)
281
281
  );
282
282
  --border-color-pho-error: oklch(0.642 0.245 21.5);
283
+ /* Resting invalid edge — readable on the field surface without matching
284
+ the solid focus ring. ~45% light / ~50% dark. */
283
285
  --border-color-pho-error-subtle: light-dark(
284
- oklch(0.642 0.245 21.5 / 0.3),
285
- oklch(0.642 0.245 21.5 / 0.4)
286
+ oklch(0.642 0.245 21.5 / 0.45),
287
+ oklch(0.642 0.245 21.5 / 0.5)
286
288
  );
287
289
  /* Hairline interactive edge shared by hover/selected surfaces. */
288
290
  --border-color-pho-interactive: light-dark(
@@ -298,9 +300,10 @@
298
300
  --ring-color-pho-secondary: light-dark(oklch(0.949 0 0), oklch(0.244 0 0));
299
301
  --ring-color-pho-brand: light-dark(oklch(0 0 0 / 0.4), oklch(1 0 0 / 0.4));
300
302
  --ring-color-pho-error: oklch(0.642 0.245 21.5);
303
+ /* Mirrors border-pho-error-subtle — resting invalid hairline. */
301
304
  --ring-color-pho-error-subtle: light-dark(
302
- oklch(0.642 0.245 21.5 / 0.3),
303
- oklch(0.642 0.245 21.5 / 0.4)
305
+ oklch(0.642 0.245 21.5 / 0.45),
306
+ oklch(0.642 0.245 21.5 / 0.5)
304
307
  );
305
308
  --ring-color-pho-interactive: light-dark(
306
309
  oklch(0 0 0 / 0.1),
@@ -1 +0,0 @@
1
- {"version":3,"file":"input-BSJGBUbf.js","names":["__iconNode","__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconEyeOff.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconEye.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.44.0_react@19.2.7/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircleFilled.mjs","../../src/components/input/input.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.44.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M10.585 10.587a2 2 0 0 0 2.829 2.828\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M3 3l18 18\", \"key\": \"svg-2\" }]];\nconst IconEyeOff = createReactComponent(\"outline\", \"eye-off\", \"EyeOff\", __iconNode);\n\nexport { __iconNode, IconEyeOff as default };\n//# sourceMappingURL=IconEyeOff.mjs.map\n","/**\n * @license @tabler/icons-react v3.44.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\", \"key\": \"svg-1\" }]];\nconst IconEye = createReactComponent(\"outline\", \"eye\", \"Eye\", __iconNode);\n\nexport { __iconNode, IconEye as default };\n//# sourceMappingURL=IconEye.mjs.map\n","/**\n * @license @tabler/icons-react v3.44.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm.01 13l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\", \"key\": \"svg-0\" }]];\nconst IconAlertCircleFilled = createReactComponent(\"filled\", \"alert-circle-filled\", \"AlertCircleFilled\", __iconNode);\n\nexport { __iconNode, IconAlertCircleFilled as default };\n//# sourceMappingURL=IconAlertCircleFilled.mjs.map\n","import {\n useState,\n type ComponentType,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport {\n IconAlertCircleFilled,\n IconEye,\n IconEyeOff,\n} from \"@tabler/icons-react\";\nimport { Field } from \"@base-ui/react/field\";\nimport { cn } from \"../../utils/cn\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\n// Control padding per size. The wrapper carries a 2px inset (`p-0.5`) so the\n// control's border box — and the browser's autofill fill it paints — sits\n// inside the ring instead of over it; these paddings are the documented\n// effective padding (sm/md 12/8px, lg 14/10px) minus that 2px inset, so the\n// text position and total field height are unchanged.\nconst SIZE_PAD: Record<InputSize, string> = {\n // 16px on small viewports — iOS zooms into any focused field under 16px.\n sm: \"px-2.5 py-1.5 text-md md:text-base\",\n md: \"px-2.5 py-1.5 text-md\",\n lg: \"px-3 py-2 text-md\",\n};\n// Effective icon clearance minus the wrapper's 2px inset.\nconst LEADING_PAD: Record<InputSize, string> = {\n sm: \"pl-8.5\",\n md: \"pl-9.5\",\n lg: \"pl-10\",\n};\n// Icons are absolutely positioned, so they're placed from the wrapper's\n// padding edge — which, with no border, is the visible field edge; the\n// wrapper's `p-0.5` does not offset them.\nconst LEADING_ICON_POS: Record<InputSize, string> = {\n sm: \"left-3 size-4\",\n md: \"left-3 size-5\",\n lg: \"left-3.5 size-5\",\n};\n// Wrapper corner radius — `rounded-base` (12px) at every size; `lg` also gets\n// `squircle` superellipse smoothing (the ring is a box-shadow on this wrapper,\n// so it follows the border-radius automatically).\nconst SIZE_RADIUS: Record<InputSize, string> = {\n sm: \"rounded-base\",\n md: \"rounded-base\",\n lg: \"squircle rounded-base\",\n};\n// Concentric inner-curve cover, `lg` only. Nested corner radii must follow\n// innerRadius = outerRadius − inset, so the hairline's inner edge at a 12px\n// outer radius is 11px at rest (ring-1) and 10px when focused (ring-2).\n// Browsers derive that automatically for plain round corners, but with\n// `corner-shape: superellipse(...)` shipping engines still scale (rather than\n// offset) the inner shadow curve, which renders the ring visibly thicker at\n// the four corners (see w3c/csswg-drafts#12961). This ::before repaints the\n// field surface over everything inside the correct concentric curve — a round\n// radius is the right parallel-offset approximation of the mild superellipse —\n// so the ring reads as a uniform hairline in every engine. `isolate` +\n// `-z-10` slot the cover above the wrapper's background/ring but below the\n// control's text, icons, and autofill fill. `sm`/`md` have no corner-shape,\n// so the native (already concentric) rendering is kept there.\n// The ::before is absolutely positioned, so its inset is measured from the\n// wrapper's border box (border 0): 1px in at rest, 2px in when focused.\nconst SIZE_RING_COVER: Record<InputSize, string> = {\n sm: \"\",\n md: \"\",\n lg: cn(\n \"isolate before:pointer-events-none before:absolute before:-z-10 before:content-['']\",\n \"before:bg-pho-primary before:inset-px before:rounded-[calc(var(--radius-base)-1px)]\",\n \"has-[input:focus-visible]:before:inset-0.5 has-[input:focus-visible]:before:rounded-[calc(var(--radius-base)-2px)]\",\n \"before:transition-[inset,border-radius] before:duration-100 before:ease-linear\",\n ),\n};\n// The control's border box sits 2px inside the wrapper (its `p-0.5` inset),\n// clear of both ring widths, so the browser's autofill fill paints inside the\n// hairline instead of over it. Rounding follows inner = outer − gap, derived\n// from the token with calc. Round (not squircle) — the parallel offset of\n// the wrapper's mild superellipse is effectively circular.\nconst SIZE_AUTOFILL_RADIUS: Record<InputSize, string> = {\n sm: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n md: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n lg: \"autofill:rounded-[calc(var(--radius-base)-2px)]\",\n};\n\nexport interface InputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"size\"\n> {\n /** Field label (associated for accessibility). */\n label?: ReactNode;\n /** Helper text below the field; rendered in the error color when `invalid`. */\n hint?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: InputSize;\n /** Render the invalid state (ring + icon + error-colored hint). */\n invalid?: boolean;\n /** Leading icon component (e.g. a Tabler icon). */\n icon?: ComponentType<{ className?: string }>;\n /** Node rendered at the right edge of the label row (e.g. \"Forgot?\"). */\n labelTrailing?: ReactNode;\n /** Class applied to the input wrapper. */\n wrapperClassName?: string;\n ref?: Ref<HTMLInputElement>;\n}\n\n/**\n * Text input built on Base UI `Field` (label/description a11y wiring) with\n * Pho's bordered surface, leading icon, invalid state, and a built-in password\n * reveal toggle.\n */\nexport function Input({\n label,\n hint,\n size = \"md\",\n invalid,\n icon: Icon,\n labelTrailing,\n disabled,\n required,\n type = \"text\",\n className,\n wrapperClassName,\n id,\n ref,\n ...props\n}: InputProps) {\n const [reveal, setReveal] = useState(false);\n const isPassword = type === \"password\";\n const resolvedType = isPassword && reveal ? \"text\" : type;\n const hasLeadingIcon = Boolean(Icon);\n const hasTrailingIcon = isPassword || invalid;\n\n return (\n <Field.Root\n disabled={disabled}\n className=\"group/field flex w-full flex-col gap-1.5\"\n >\n {label && (\n <div className=\"flex items-center justify-between gap-2\">\n <Field.Label className=\"text-pho-secondary flex cursor-default items-center gap-0.5 text-base font-medium\">\n {label}\n {required && <span className=\"text-pho-brand\">*</span>}\n </Field.Label>\n {labelTrailing}\n </div>\n )}\n\n <div\n data-invalid={invalid || undefined}\n className={cn(\n // Flat field surface — hairline ring only; elevation shadows are\n // reserved for floating layers (menus/popovers/dialogs). `p-0.5`\n // insets the control 2px (the focused ring width) so its background\n // and the browser's autofill fill nest inside the ring; the size\n // maps compensate so effective padding/height are unchanged.\n \"bg-pho-primary ring-pho-primary relative flex w-full items-center p-0.5 ring-1 transition-shadow duration-100 ease-linear ring-inset\",\n SIZE_RADIUS[size],\n SIZE_RING_COVER[size],\n \"has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2\",\n \"data-[invalid]:ring-pho-error-subtle data-[invalid]:has-[input:focus-visible]:ring-pho-error\",\n \"group-data-[disabled]/field:cursor-not-allowed group-data-[disabled]/field:opacity-50\",\n wrapperClassName,\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"text-pho-secondary pointer-events-none absolute\",\n LEADING_ICON_POS[size],\n )}\n />\n )}\n\n <Field.Control\n ref={ref}\n id={id}\n type={resolvedType}\n required={required}\n {...props}\n className={cn(\n \"text-pho-primary placeholder:text-pho-placeholder m-0 w-full bg-transparent outline-none disabled:cursor-not-allowed\",\n SIZE_PAD[size],\n SIZE_AUTOFILL_RADIUS[size],\n hasLeadingIcon && LEADING_PAD[size],\n // 34px + the wrapper's 2px inset = the previous 36px clearance.\n hasTrailingIcon && \"pr-8.5\",\n className,\n )}\n />\n\n {invalid && !isPassword && (\n <IconAlertCircleFilled className=\"text-pho-error pointer-events-none absolute right-3 size-4\" />\n )}\n\n {isPassword && (\n <button\n type=\"button\"\n // Reachable by click but skipped in tab order so Tab moves field→field.\n tabIndex={-1}\n aria-label=\"Toggle password visibility\"\n onClick={() => setReveal((v) => !v)}\n className=\"text-pho-secondary hover:text-pho-secondary-hover absolute right-3 flex cursor-pointer items-center transition duration-100 ease-linear focus:outline-none\"\n >\n {reveal ? (\n <IconEyeOff className=\"size-4\" />\n ) : (\n <IconEye className=\"size-4\" />\n )}\n </button>\n )}\n </div>\n\n {hint && (\n <Field.Description\n className={cn(\n \"text-pho-description text-base\",\n invalid && \"text-pho-error\",\n )}\n >\n {hint}\n </Field.Description>\n )}\n </Field.Root>\n );\n}\n\nInput.displayName = \"Input\";\n"],"x_google_ignoreList":[0,1,2],"mappings":"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"}
@@ -1,104 +0,0 @@
1
- "use client";
2
- import { t as a } from "./cn-DTiB6ek_.js";
3
- import "react";
4
- import { jsx as r, jsxs as n } from "react/jsx-runtime";
5
- var c = "divide-y divide-pho-secondary rounded-base border border-pho-secondary bg-pho-primary", p = "flex min-h-[4.25rem] flex-col gap-3 px-5 py-4 sm:flex-row sm:items-center sm:justify-between sm:gap-6";
6
- function m({ className: e, children: t, ...s }) {
7
- return /* @__PURE__ */ r("h1", {
8
- className: a("text-display-base text-pho-primary px-5 font-medium", e),
9
- ...s,
10
- children: t
11
- });
12
- }
13
- function x({ className: e, ...t }) {
14
- return /* @__PURE__ */ r("div", {
15
- className: a("mt-6 flex flex-col gap-10", "*:flex *:flex-col *:gap-3", e),
16
- ...t
17
- });
18
- }
19
- function d({ className: e, ...t }) {
20
- return /* @__PURE__ */ r("div", {
21
- className: a("flex flex-col gap-0.5", e),
22
- ...t
23
- });
24
- }
25
- function f({ className: e, children: t, ...s }) {
26
- return /* @__PURE__ */ r("h2", {
27
- className: a("text-display-xs text-pho-primary px-5 font-medium", e),
28
- ...s,
29
- children: t
30
- });
31
- }
32
- function u({ className: e, ...t }) {
33
- return /* @__PURE__ */ r("p", {
34
- className: a("text-display-xs text-pho-description px-5 font-normal", e),
35
- ...t
36
- });
37
- }
38
- function h({ className: e, ...t }) {
39
- return /* @__PURE__ */ r("div", {
40
- className: a(c, e),
41
- ...t
42
- });
43
- }
44
- function N({ label: e, description: t, htmlFor: s, className: i, children: o, ...l }) {
45
- return /* @__PURE__ */ n("div", {
46
- className: a(p, i),
47
- ...l,
48
- children: [/* @__PURE__ */ n("div", {
49
- className: "min-w-0",
50
- children: [s ? /* @__PURE__ */ r("label", {
51
- htmlFor: s,
52
- className: "text-pho-primary block text-base font-normal",
53
- children: e
54
- }) : /* @__PURE__ */ r("p", {
55
- className: "text-pho-primary text-base font-normal",
56
- children: e
57
- }), t ? /* @__PURE__ */ r("p", {
58
- className: "text-pho-description mt-0.5 text-xs",
59
- children: t
60
- }) : null]
61
- }), /* @__PURE__ */ r("div", {
62
- className: "flex w-full min-w-0 items-center gap-2 sm:w-auto",
63
- children: o
64
- })]
65
- });
66
- }
67
- function y({ className: e, ...t }) {
68
- return /* @__PURE__ */ r("p", {
69
- className: a("text-pho-description truncate text-base", e),
70
- ...t
71
- });
72
- }
73
- function b({ className: e, ...t }) {
74
- return /* @__PURE__ */ r("p", {
75
- role: "alert",
76
- className: a("text-pho-error px-5 pb-3 text-xs", e),
77
- ...t
78
- });
79
- }
80
- function v({ className: e, ...t }) {
81
- return /* @__PURE__ */ r("div", {
82
- className: a("flex items-center justify-between gap-6 px-5 py-4", e),
83
- ...t
84
- });
85
- }
86
- var T = {
87
- PageTitle: m,
88
- Stack: x,
89
- Header: d,
90
- SectionTitle: f,
91
- Description: u,
92
- Card: h,
93
- Row: N,
94
- Value: y,
95
- Alert: b,
96
- Footer: v
97
- };
98
- export {
99
- p as n,
100
- T as r,
101
- c as t
102
- };
103
-
104
- //# sourceMappingURL=settings-B3ilbRcF.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings-B3ilbRcF.js","names":[],"sources":["../../src/sections/settings/settings.tsx"],"sourcesContent":["import { type ComponentProps, type ReactNode, type Ref } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/**\n * Settings — Pho's settings-page section: a page title, section titles, and\n * bordered cards of label/control rows.\n *\n * Spacing: `Stack` separates blocks (`gap-10`). Inside a block, children share\n * `gap-3`. Wrap a section title + description in `Header` (`gap-0.5`) so that\n * pair stays tight — don't put them as loose siblings. Host the page at\n * `max-w-xl` (parts already carry `px-5`).\n */\n\n/* ------------------------------- class map ------------------------------- */\n\n/** Bordered card that stacks rows with hairline dividers. */\nexport const SETTINGS_CARD =\n \"divide-y divide-pho-secondary rounded-base border border-pho-secondary bg-pho-primary\";\n\n/**\n * One settings row — label (+ optional description) left, control right.\n * `min-h-[4.25rem]` (68px) keeps avatar/control rows from collapsing shorter\n * than a comfortable touch target.\n */\nexport const SETTINGS_ROW =\n \"flex min-h-[4.25rem] flex-col gap-3 px-5 py-4 sm:flex-row sm:items-center sm:justify-between sm:gap-6\";\n\n/* --------------------------------- parts --------------------------------- */\n\n/** Page title — largest heading on the surface. */\nfunction PageTitle({\n className,\n children,\n ...props\n}: ComponentProps<\"h1\"> & { ref?: Ref<HTMLHeadingElement> }) {\n return (\n <h1\n className={cn(\n \"text-display-base text-pho-primary px-5 font-medium\",\n className,\n )}\n {...props}\n >\n {children}\n </h1>\n );\n}\n\n/**\n * Vertical stack under the page title. Blocks (forms / sections) use `gap-10`;\n * each block lays out its children with `gap-3`.\n */\nfunction Stack({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return (\n <div\n className={cn(\n \"mt-6 flex flex-col gap-10\",\n \"*:flex *:flex-col *:gap-3\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Title + optional description pair. Keeps that couple tight (`gap-0.5`) so\n * the block's `gap-3` only applies between this header and the card.\n */\nfunction Header({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return <div className={cn(\"flex flex-col gap-0.5\", className)} {...props} />;\n}\n\n/** Section heading — same padding as the page title, smaller type. */\nfunction SectionTitle({\n className,\n children,\n ...props\n}: ComponentProps<\"h2\"> & { ref?: Ref<HTMLHeadingElement> }) {\n return (\n <h2\n className={cn(\n \"text-display-xs text-pho-primary px-5 font-medium\",\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n );\n}\n\n/**\n * Supporting copy under a section title. Same display step as the title;\n * color + normal weight keep it secondary. Always wrap with `Header`.\n */\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 px-5 font-normal\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Bordered card that stacks settings rows with hairline dividers. */\nfunction Card({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return <div className={cn(SETTINGS_CARD, className)} {...props} />;\n}\n\nexport interface SettingsRowProps extends Omit<ComponentProps<\"div\">, \"title\"> {\n /** Left-side field name. */\n label: string;\n /** Optional helper under the label. */\n description?: ReactNode;\n /** Associates the label with a control id. When omitted, the label is not a `<label>`. */\n htmlFor?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\n/**\n * One settings row: label (+ optional description) left, control right.\n * Pass `htmlFor` when the row wraps a labelled input; omit it for display/\n * action rows (avatar, danger-zone delete).\n */\nfunction Row({\n label,\n description,\n htmlFor,\n className,\n children,\n ...props\n}: SettingsRowProps) {\n return (\n <div className={cn(SETTINGS_ROW, className)} {...props}>\n <div className=\"min-w-0\">\n {htmlFor ? (\n <label\n htmlFor={htmlFor}\n className=\"text-pho-primary block text-base font-normal\"\n >\n {label}\n </label>\n ) : (\n <p className=\"text-pho-primary text-base font-normal\">{label}</p>\n )}\n {description ? (\n <p className=\"text-pho-description mt-0.5 text-xs\">{description}</p>\n ) : null}\n </div>\n <div className=\"flex w-full min-w-0 items-center gap-2 sm:w-auto\">\n {children}\n </div>\n </div>\n );\n}\n\n/** Read-only value on the right side of a row (email, etc.). */\nfunction Value({\n className,\n ...props\n}: ComponentProps<\"p\"> & { ref?: Ref<HTMLParagraphElement> }) {\n return (\n <p\n className={cn(\"text-pho-description truncate text-base\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Inline error under a row (still inside the card). Matches card horizontal\n * padding so hosts don't re-apply `px-5`.\n */\nfunction Alert({\n className,\n ...props\n}: ComponentProps<\"p\"> & { ref?: Ref<HTMLParagraphElement> }) {\n return (\n <p\n role=\"alert\"\n className={cn(\"text-pho-error px-5 pb-3 text-xs\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Trailing bar inside a card — typically a save status + submit button that\n * appears after the form is dirty. Same horizontal/vertical padding as a row.\n */\nfunction Footer({\n className,\n ...props\n}: ComponentProps<\"div\"> & { ref?: Ref<HTMLDivElement> }) {\n return (\n <div\n className={cn(\n \"flex items-center justify-between gap-6 px-5 py-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/* -------------------------------- assembly ------------------------------- */\n\n/**\n * Settings page layout. One stack, one gap rhythm — only title scale differs:\n *\n * ```tsx\n * <Settings.PageTitle>Profile</Settings.PageTitle>\n * <Settings.Stack>\n * <form>\n * <Settings.Card>\n * <Settings.Row label=\"Name\" htmlFor=\"first-name\">\n * <Input id=\"first-name\" size=\"sm\" />\n * </Settings.Row>\n * </Settings.Card>\n * </form>\n * <form>\n * <Settings.Header>\n * <Settings.SectionTitle>Agent profile</Settings.SectionTitle>\n * <Settings.Description>…</Settings.Description>\n * </Settings.Header>\n * <Settings.Card>…</Settings.Card>\n * </form>\n * <div>\n * <Settings.SectionTitle>Danger zone</Settings.SectionTitle>\n * <Settings.Card>\n * <Settings.Row label=\"Delete account\" description=\"…\">\n * <Button color=\"destructive\" size=\"sm\">Delete</Button>\n * </Settings.Row>\n * </Settings.Card>\n * </div>\n * </Settings.Stack>\n * ```\n */\nexport const Settings = {\n PageTitle,\n Stack,\n Header,\n SectionTitle,\n Description,\n Card,\n Row,\n Value,\n Alert,\n Footer,\n};\n"],"mappings":"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"}
@@ -1,164 +0,0 @@
1
- "use client";
2
- import { t as o } from "./cn-DTiB6ek_.js";
3
- import { n as g, r as v } from "./link-provider-9TFNyDqO.js";
4
- import { d as x } from "./close-button-Bq9f-H15.js";
5
- import { t as h } from "./createReactComponent-BqCmnqfX.js";
6
- import { n as l } from "./avatar-CiAvJNNs.js";
7
- import { isValidElement as b } from "react";
8
- import { Fragment as y, jsx as t, jsxs as a } from "react/jsx-runtime";
9
- var N = [["path", {
10
- d: "M17 7l-10 10",
11
- key: "svg-0"
12
- }], ["path", {
13
- d: "M8 7l9 0l0 9",
14
- key: "svg-1"
15
- }]], I = h("outline", "arrow-up-right", "ArrowUpRight", N), k = [
16
- ["path", {
17
- d: "M4 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0",
18
- key: "svg-0"
19
- }],
20
- ["path", {
21
- d: "M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0",
22
- key: "svg-1"
23
- }],
24
- ["path", {
25
- d: "M18 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0",
26
- key: "svg-2"
27
- }]
28
- ], w = h("outline", "dots", "Dots", k), R = "border-pho-secondary bg-pho-page sticky top-0 flex h-dvh w-64 shrink-0 flex-col border-r px-4 pt-5 pb-4", _ = "outline-pho-brand flex min-h-8 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", A = "bg-pho-primary text-pho-primary ring-pho-secondary font-medium ring-1 ring-inset *:data-icon:text-pho-primary", E = o("text-pho-secondary *:data-icon:text-pho-secondary", "hover:bg-pho-primary hover:text-pho-primary hover:*:data-icon:text-pho-primary");
29
- function C({ className: r, ...e }) {
30
- return /* @__PURE__ */ t("aside", {
31
- className: o(R, r),
32
- ...e
33
- });
34
- }
35
- function M({ className: r, ...e }) {
36
- return /* @__PURE__ */ t("div", {
37
- className: o("mb-6 flex items-center gap-2.5 px-2", r),
38
- ...e
39
- });
40
- }
41
- function T({ className: r, ...e }) {
42
- return /* @__PURE__ */ t("nav", {
43
- className: o("flex flex-1 flex-col gap-6 overflow-y-auto", r),
44
- ...e
45
- });
46
- }
47
- function D({ className: r, ...e }) {
48
- return /* @__PURE__ */ t("div", {
49
- className: r,
50
- ...e
51
- });
52
- }
53
- function B({ className: r, ...e }) {
54
- return /* @__PURE__ */ t("div", {
55
- className: o("text-pho-description mb-2 px-2 text-xs font-normal", r),
56
- ...e
57
- });
58
- }
59
- function z({ className: r, columns: e, ...n }) {
60
- return /* @__PURE__ */ t("ul", {
61
- className: o("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", r),
62
- ...n
63
- });
64
- }
65
- function F({ className: r, ...e }) {
66
- return /* @__PURE__ */ t("div", {
67
- className: o("mt-4 flex flex-col gap-0.5", r),
68
- ...e
69
- });
70
- }
71
- function p(r) {
72
- if (r == null || r === !1) return null;
73
- let e = null;
74
- return v(r) ? e = /* @__PURE__ */ t(r, {}) : b(r) && (e = r), e == null ? null : /* @__PURE__ */ t("span", {
75
- "data-icon": !0,
76
- className: "pointer-events-none inline-flex shrink-0 items-center [&>svg]:size-4 [&>svg]:shrink-0",
77
- children: e
78
- });
79
- }
80
- function L({ icon: r, active: e, className: n, children: i, href: s, external: c, ...u }) {
81
- const f = g(), d = o(_, e ? A : E, n), m = /* @__PURE__ */ t("span", {
82
- className: "min-w-0 flex-1 truncate",
83
- children: i
84
- });
85
- return s !== void 0 ? /* @__PURE__ */ t("li", { children: /* @__PURE__ */ a(f, {
86
- href: s,
87
- "aria-current": e ? "page" : void 0,
88
- ...c && {
89
- target: "_blank",
90
- rel: "noopener noreferrer"
91
- },
92
- ...u,
93
- className: d,
94
- children: [
95
- p(r),
96
- m,
97
- c && /* @__PURE__ */ a(y, { children: [p(/* @__PURE__ */ t(I, { "aria-hidden": !0 })), /* @__PURE__ */ t("span", {
98
- className: "sr-only",
99
- children: "(opens in a new tab)"
100
- })] })
101
- ]
102
- }) }) : /* @__PURE__ */ t("li", { children: /* @__PURE__ */ a("button", {
103
- type: "button",
104
- "aria-current": e ? "page" : void 0,
105
- ...u,
106
- className: d,
107
- children: [p(r), m]
108
- }) });
109
- }
110
- var O = "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";
111
- function S(r) {
112
- const e = r.split(/\s+/).filter(Boolean);
113
- return ((e[0]?.[0] ?? r[0] ?? "?") + (e.length >= 2 ? e[e.length - 1]?.[0] ?? "" : "")).toUpperCase();
114
- }
115
- function U({ name: r, avatarSrc: e, initials: n, className: i, ...s }) {
116
- return /* @__PURE__ */ a("button", {
117
- type: "button",
118
- className: o(O, i),
119
- ...s,
120
- children: [
121
- /* @__PURE__ */ a(l.Root, {
122
- size: "xs",
123
- children: [e && /* @__PURE__ */ t(l.Image, {
124
- src: e,
125
- alt: ""
126
- }), /* @__PURE__ */ t(l.Fallback, { children: n ?? S(r) })]
127
- }),
128
- /* @__PURE__ */ t("span", {
129
- className: "text-pho-primary min-w-0 flex-1 truncate text-base",
130
- children: r
131
- }),
132
- /* @__PURE__ */ t("span", {
133
- "aria-hidden": !0,
134
- className: x({
135
- variant: "outlined",
136
- size: "sm",
137
- shape: "circle",
138
- 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 group-data-[pressed]:scale-[0.97]"
139
- }),
140
- children: /* @__PURE__ */ t(w, { className: "size-4" })
141
- })
142
- ]
143
- });
144
- }
145
- var J = {
146
- Root: C,
147
- Header: M,
148
- Nav: T,
149
- Group: D,
150
- GroupLabel: B,
151
- List: z,
152
- Item: L,
153
- Footer: F,
154
- AccountRow: U
155
- };
156
- export {
157
- J as a,
158
- R as i,
159
- A as n,
160
- E as r,
161
- _ as t
162
- };
163
-
164
- //# sourceMappingURL=sidebar-C5cIhWs1.js.map