@photon-ai/pho-ui 0.4.0 → 0.5.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.
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { t as r } from "./cn-7uGUzCOM.js";
3
3
  import { t as n } from "./createReactComponent-BqCmnqfX.js";
4
- import { useState as E } from "react";
5
- import { jsx as e, jsxs as o } from "react/jsx-runtime";
4
+ import { useState as A } from "react";
5
+ import { jsx as e, jsxs as l } from "react/jsx-runtime";
6
6
  import { Field as s } from "@base-ui/react/field";
7
- var k = [
7
+ var S = [
8
8
  ["path", {
9
9
  d: "M10.585 10.587a2 2 0 0 0 2.829 2.828",
10
10
  key: "svg-0"
@@ -17,86 +17,90 @@ var k = [
17
17
  d: "M3 3l18 18",
18
18
  key: "svg-2"
19
19
  }]
20
- ], D = n("outline", "eye-off", "EyeOff", k), S = [["path", {
20
+ ], k = n("outline", "eye-off", "EyeOff", S), C = [["path", {
21
21
  d: "M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0",
22
22
  key: "svg-0"
23
23
  }], ["path", {
24
24
  d: "M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6",
25
25
  key: "svg-1"
26
- }]], C = n("outline", "eye", "Eye", S), L = [["path", {
26
+ }]], D = n("outline", "eye", "Eye", C), R = [["path", {
27
27
  d: "M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm.01 13l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z",
28
28
  key: "svg-0"
29
- }]], M = n("filled", "alert-circle-filled", "AlertCircleFilled", L), z = {
30
- sm: "px-3 py-2 text-sm",
31
- md: "px-3 py-2 text-md",
32
- lg: "px-3.5 py-2.5 text-md"
29
+ }]], L = n("filled", "alert-circle-filled", "AlertCircleFilled", R), M = {
30
+ sm: "px-2.5 py-1.5 text-sm",
31
+ md: "px-2.5 py-1.5 text-md",
32
+ lg: "px-3 py-2 text-md"
33
33
  }, O = {
34
- sm: "pl-9",
35
- md: "pl-10",
36
- lg: "pl-10.5"
37
- }, R = {
34
+ sm: "pl-8.5",
35
+ md: "pl-9.5",
36
+ lg: "pl-10"
37
+ }, z = {
38
38
  sm: "left-3 size-4",
39
39
  md: "left-3 size-5",
40
40
  lg: "left-3.5 size-5"
41
- }, q = {
41
+ }, F = {
42
42
  sm: "rounded-lg",
43
43
  md: "rounded-lg",
44
44
  lg: "squircle rounded-xl"
45
- }, F = {
46
- sm: "autofill:rounded-lg",
47
- md: "autofill:rounded-lg",
48
- lg: "squircle autofill:rounded-xl"
45
+ }, P = {
46
+ sm: "",
47
+ md: "",
48
+ lg: r("isolate before:pointer-events-none before:absolute before:-z-10 before:content-['']", "before:bg-pho-primary before:inset-px before:rounded-[11px]", "has-[input:focus-visible]:before:inset-0.5 has-[input:focus-visible]:before:rounded-[10px]", "before:transition-[inset,border-radius] before:duration-100 before:ease-linear")
49
+ }, T = {
50
+ sm: "autofill:rounded-md",
51
+ md: "autofill:rounded-md",
52
+ lg: "autofill:rounded-[10px]"
49
53
  };
50
- function P({ label: d, hint: c, size: t = "md", invalid: a, icon: i, labelTrailing: f, disabled: g, required: p, type: m = "text", className: h, wrapperClassName: v, id: x, ref: y, ...b }) {
51
- const [u, N] = E(!1), l = m === "password", I = l && u ? "text" : m, _ = !!i, w = l || a;
52
- return /* @__PURE__ */ o(s.Root, {
53
- disabled: g,
54
+ function Z({ label: d, hint: p, size: t = "md", invalid: a, icon: i, labelTrailing: m, disabled: h, required: c, type: u = "text", className: g, wrapperClassName: v, id: b, ref: x, ...y }) {
55
+ const [f, N] = A(!1), o = u === "password", I = o && f ? "text" : u, _ = !!i, E = o || a;
56
+ return /* @__PURE__ */ l(s.Root, {
57
+ disabled: h,
54
58
  className: "group/field flex w-full flex-col gap-1.5",
55
59
  children: [
56
- d && /* @__PURE__ */ o("div", {
60
+ d && /* @__PURE__ */ l("div", {
57
61
  className: "flex items-center justify-between gap-2",
58
- children: [/* @__PURE__ */ o(s.Label, {
62
+ children: [/* @__PURE__ */ l(s.Label, {
59
63
  className: "text-pho-secondary flex cursor-default items-center gap-0.5 text-sm font-medium",
60
- children: [d, p && /* @__PURE__ */ e("span", {
64
+ children: [d, c && /* @__PURE__ */ e("span", {
61
65
  className: "text-pho-brand",
62
66
  children: "*"
63
67
  })]
64
- }), f]
68
+ }), m]
65
69
  }),
66
- /* @__PURE__ */ o("div", {
70
+ /* @__PURE__ */ l("div", {
67
71
  "data-invalid": a || void 0,
68
- className: r("bg-pho-primary ring-pho-primary relative flex w-full items-center ring-1 transition-shadow duration-100 ease-linear ring-inset", q[t], "has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2", "data-[invalid]:ring-pho-error-subtle data-[invalid]:has-[input:focus-visible]:ring-pho-error", "group-data-[disabled]/field:cursor-not-allowed group-data-[disabled]/field:opacity-50", v),
72
+ className: r("bg-pho-primary ring-pho-primary relative flex w-full items-center p-0.5 ring-1 transition-shadow duration-100 ease-linear ring-inset", F[t], P[t], "has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2", "data-[invalid]:ring-pho-error-subtle data-[invalid]:has-[input:focus-visible]:ring-pho-error", "group-data-[disabled]/field:cursor-not-allowed group-data-[disabled]/field:opacity-50", v),
69
73
  children: [
70
- i && /* @__PURE__ */ e(i, { className: r("text-fg-pho-quaternary pointer-events-none absolute", R[t]) }),
74
+ i && /* @__PURE__ */ e(i, { className: r("text-fg-pho-quaternary pointer-events-none absolute", z[t]) }),
71
75
  /* @__PURE__ */ e(s.Control, {
72
- ref: y,
73
- id: x,
76
+ ref: x,
77
+ id: b,
74
78
  type: I,
75
- required: p,
76
- ...b,
77
- className: r("text-pho-primary placeholder:text-pho-placeholder m-0 w-full bg-transparent outline-none disabled:cursor-not-allowed", z[t], F[t], _ && O[t], w && "pr-9", h)
79
+ required: c,
80
+ ...y,
81
+ className: r("text-pho-primary placeholder:text-pho-placeholder m-0 w-full bg-transparent outline-none disabled:cursor-not-allowed", M[t], T[t], _ && O[t], E && "pr-8.5", g)
78
82
  }),
79
- a && !l && /* @__PURE__ */ e(M, { className: "text-fg-pho-error pointer-events-none absolute right-3 size-4" }),
80
- l && /* @__PURE__ */ e("button", {
83
+ a && !o && /* @__PURE__ */ e(L, { className: "text-fg-pho-error pointer-events-none absolute right-3 size-4" }),
84
+ o && /* @__PURE__ */ e("button", {
81
85
  type: "button",
82
86
  tabIndex: -1,
83
87
  "aria-label": "Toggle password visibility",
84
- onClick: () => N((A) => !A),
88
+ onClick: () => N((w) => !w),
85
89
  className: "text-fg-pho-quaternary hover:text-fg-pho-quaternary-hover absolute right-3 flex cursor-pointer items-center transition duration-100 ease-linear focus:outline-none",
86
- children: u ? /* @__PURE__ */ e(D, { className: "size-4" }) : /* @__PURE__ */ e(C, { className: "size-4" })
90
+ children: f ? /* @__PURE__ */ e(k, { className: "size-4" }) : /* @__PURE__ */ e(D, { className: "size-4" })
87
91
  })
88
92
  ]
89
93
  }),
90
- c && /* @__PURE__ */ e(s.Description, {
94
+ p && /* @__PURE__ */ e(s.Description, {
91
95
  className: r("text-pho-tertiary text-sm", a && "text-pho-error"),
92
- children: c
96
+ children: p
93
97
  })
94
98
  ]
95
99
  });
96
100
  }
97
- P.displayName = "Input";
101
+ Z.displayName = "Input";
98
102
  export {
99
- P as t
103
+ Z as t
100
104
  };
101
105
 
102
- //# sourceMappingURL=input-e1k2gbET.js.map
106
+ //# sourceMappingURL=input-DbJpdu6v.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-DbJpdu6v.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 sm: \"px-2.5 py-1.5 text-sm\",\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 per size. `lg` steps up to 12px with `squircle`\n// superellipse smoothing (the ring is a box-shadow on this wrapper, so it\n// follows the border-radius automatically); `sm`/`md` keep the 8px default.\nconst SIZE_RADIUS: Record<InputSize, string> = {\n sm: \"rounded-lg\",\n md: \"rounded-lg\",\n lg: \"squircle rounded-xl\",\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-[11px]\",\n \"has-[input:focus-visible]:before:inset-0.5 has-[input:focus-visible]:before:rounded-[10px]\",\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. Its rounding follows the same concentric\n// formula (innerRadius = outerRadius − 2px inset): 8 − 2 = 6px (`rounded-md`)\n// at sm/md, 12 − 2 = 10px at lg. Round (not squircle) — the parallel offset\n// of the wrapper's mild superellipse is effectively circular.\nconst SIZE_AUTOFILL_RADIUS: Record<InputSize, string> = {\n sm: \"autofill:rounded-md\",\n md: \"autofill:rounded-md\",\n lg: \"autofill:rounded-[10px]\",\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-sm 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-fg-pho-quaternary 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-fg-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-fg-pho-quaternary hover:text-fg-pho-quaternary-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-tertiary text-sm\",\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,6 +1,6 @@
1
1
  "use client";
2
- import { a, c as s, i as o, l as n, n as B, o as T, r as u, s as e, t as f, u as i } from "../chunks/button-BMDHIgZh.js";
3
- import { t as E } from "../chunks/close-button-CRiiwy6K.js";
2
+ import { a, c as s, i as o, l as n, n as B, o as T, r as u, s as e, t as f, u as i } from "../chunks/button-CQ4cZvkC.js";
3
+ import { t as E } from "../chunks/close-button-CNhn8z0w.js";
4
4
  export {
5
5
  f as BUTTON_SHAPES,
6
6
  B as BUTTON_SIZES,
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t } from "../chunks/dialog-sTOaOEB2.js";
2
+ import { t } from "../chunks/dialog-7oOe-eaO.js";
3
3
  export {
4
4
  t as Dialog
5
5
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as e } from "../chunks/input-e1k2gbET.js";
2
+ import { t as e } from "../chunks/input-DbJpdu6v.js";
3
3
  export {
4
4
  e as Input
5
5
  };
package/dist/index.js CHANGED
@@ -3,10 +3,10 @@ import { t as o } from "./chunks/cn-7uGUzCOM.js";
3
3
  import { n as s, r, t as n } from "./chunks/link-provider-9TFNyDqO.js";
4
4
  import { t as m } from "./chunks/resolve-variant-CcD8iG5l.js";
5
5
  import "./utils.js";
6
- import { a as p, c as u, i as B, l as T, n as c, o as E, r as S, s as l, t as N, u as _ } from "./chunks/button-BMDHIgZh.js";
7
- import { t as C } from "./chunks/input-e1k2gbET.js";
8
- import { t as L } from "./chunks/close-button-CRiiwy6K.js";
9
- import { t as U } from "./chunks/dialog-sTOaOEB2.js";
6
+ import { a as p, c as u, i as B, l as T, n as c, o as E, r as S, s as l, t as N, u as _ } from "./chunks/button-CQ4cZvkC.js";
7
+ import { t as C } from "./chunks/input-DbJpdu6v.js";
8
+ import { t as L } from "./chunks/close-button-CNhn8z0w.js";
9
+ import { t as U } from "./chunks/dialog-7oOe-eaO.js";
10
10
  export {
11
11
  N as BUTTON_SHAPES,
12
12
  c as BUTTON_SIZES,
@@ -1,5 +1,15 @@
1
1
  import { AnchorHTMLAttributes, ButtonHTMLAttributes, FC, ReactNode, Ref } from 'react';
2
- /** Size axis — padding, text size, and icon-only (svgOnly) padding. */
2
+ /**
3
+ * Size axis — padding, text size, and icon-only (svgOnly) padding.
4
+ *
5
+ * Icon-side tuck (LiftKit-derived optical correction): a side that carries an
6
+ * icon gets its padding divided by the golden ratio — an icon's rounded form
7
+ * brings its own whitespace, so the full text-edge padding reads as a hole.
8
+ * LiftKit: `--button-padX-sideWithIcon: calc(font-size / 1.618)`. Applied to
9
+ * Pho's paddings: sm 14px/φ ≈ 8px · md 16px/φ ≈ 10px · lg 20px/φ ≈ 12px,
10
+ * selected structurally via `:has()` on the slot markers (`data-icon` is
11
+ * `prefix`, `suffix`, or `loading` — the spinner is an icon too).
12
+ */
3
13
  export declare const BUTTON_SIZES: {
4
14
  sm: {
5
15
  classes: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@photon-ai/pho-ui",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Pho Design System — Photon's React component library, built on Base UI",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -1,360 +0,0 @@
1
- "use client";
2
- import { t as l } from "./cn-7uGUzCOM.js";
3
- import { n as R, r as w } from "./link-provider-9TFNyDqO.js";
4
- import { t as v } from "./resolve-variant-CcD8iG5l.js";
5
- import { isValidElement as T } from "react";
6
- import { Fragment as V, jsx as t, jsxs as k } from "react/jsx-runtime";
7
- import { motion as b } from "motion/react";
8
- var q = l("group relative inline-flex h-max cursor-pointer items-center justify-center whitespace-nowrap outline-pho-brand transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2", "disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none"), B = {
9
- sm: {
10
- classes: "gap-1 px-3.5 py-1.5 text-sm font-medium data-svg-only:p-2",
11
- description: "Small — compact rows, tables, and toolbars"
12
- },
13
- md: {
14
- classes: "gap-1 px-4 py-2 text-sm font-medium data-svg-only:p-2.5",
15
- description: "Medium — the default"
16
- },
17
- lg: {
18
- classes: "gap-1.5 px-5 py-2.5 text-md font-medium data-svg-only:p-3",
19
- description: "Large — prominent and marketing actions"
20
- }
21
- }, A = {
22
- rounded: {
23
- classes: "rounded-full",
24
- description: "Pill — the default; every button on photon.codes"
25
- },
26
- square: {
27
- classes: "rounded-lg",
28
- description: "Gently rounded corners for dense app chrome"
29
- },
30
- circle: {
31
- classes: "rounded-full",
32
- description: "Circular — pair with svgOnly for round icon buttons"
33
- }
34
- }, M = {
35
- primary: {
36
- classes: "bg-pho-brand-solid text-pho-on-brand hover:bg-pho-brand-solid-hover data-loading:bg-pho-brand-solid-hover *:data-icon:opacity-60 hover:*:data-icon:opacity-75",
37
- description: "High-emphasis primary action (default)"
38
- },
39
- secondary: {
40
- classes: "bg-pho-primary text-pho-secondary ring-1 ring-pho-secondary ring-inset hover:bg-pho-primary-hover hover:text-pho-secondary-hover data-loading:bg-pho-primary-hover *:data-icon:text-fg-pho-quaternary hover:*:data-icon:text-fg-pho-quaternary-hover",
41
- description: "Neutral, supporting action"
42
- },
43
- tertiary: {
44
- classes: "text-pho-tertiary hover:bg-pho-ghost-hover hover:text-pho-tertiary-hover data-loading:bg-pho-ghost-hover *:data-icon:text-fg-pho-quaternary hover:*:data-icon:text-fg-pho-quaternary-hover",
45
- description: "Low-emphasis, borderless action"
46
- },
47
- error: {
48
- classes: "bg-pho-error-solid text-white outline-pho-error hover:bg-pho-error-solid-hover data-loading:bg-pho-error-solid-hover *:data-icon:opacity-70 hover:*:data-icon:opacity-85",
49
- description: "Destructive confirmation"
50
- }
51
- };
52
- function g(e) {
53
- const { variant: r = "primary", size: n = "md", shape: s = "rounded", className: o } = e ?? {};
54
- return l(q, v(A, s), v(B, n), v(M, r), o);
55
- }
56
- var H = "transition-inherit-all pointer-events-none inline-flex shrink-0 items-center [&>svg]:size-[1.125em] [&>svg]:shrink-0";
57
- function y({ position: e, children: r }) {
58
- return /* @__PURE__ */ t("span", {
59
- "data-icon": e,
60
- className: H,
61
- children: r
62
- });
63
- }
64
- function N() {
65
- return /* @__PURE__ */ k("svg", {
66
- fill: "none",
67
- viewBox: "0 0 20 20",
68
- "aria-hidden": "true",
69
- children: [/* @__PURE__ */ t("circle", {
70
- className: "stroke-current opacity-30",
71
- cx: "10",
72
- cy: "10",
73
- r: "8",
74
- fill: "none",
75
- strokeWidth: "2"
76
- }), /* @__PURE__ */ t("circle", {
77
- className: "origin-center animate-spin stroke-current",
78
- cx: "10",
79
- cy: "10",
80
- r: "8",
81
- fill: "none",
82
- strokeWidth: "2",
83
- strokeDasharray: "12.5 50",
84
- strokeLinecap: "round"
85
- })]
86
- });
87
- }
88
- function _(e, r) {
89
- return e == null || e === !1 ? null : w(e) ? /* @__PURE__ */ t(y, {
90
- position: r,
91
- children: /* @__PURE__ */ t(e, {})
92
- }) : T(e) ? /* @__PURE__ */ t(y, {
93
- position: r,
94
- children: e
95
- }) : null;
96
- }
97
- function C({ svgOnly: e, loading: r, prefix: n, suffix: s, children: o }) {
98
- return e ? r ? /* @__PURE__ */ t(N, {}) : o : /* @__PURE__ */ k(V, { children: [
99
- r ? /* @__PURE__ */ t(y, {
100
- position: "loading",
101
- children: /* @__PURE__ */ t(N, {})
102
- }) : _(n, "prefix"),
103
- o != null && o !== !1 && /* @__PURE__ */ t("span", {
104
- "data-text": !0,
105
- className: "transition-inherit-all px-0.5",
106
- children: o
107
- }),
108
- _(s, "suffix")
109
- ] });
110
- }
111
- function F(e, r) {
112
- e && !r && typeof process < "u" && process.env.NODE_ENV !== "production" && console.warn("Button: `svgOnly` buttons require an `aria-label` that names the action.");
113
- }
114
- function x({ variant: e, size: r, shape: n, prefix: s, suffix: o, svgOnly: a, loading: i, children: d, className: h, ref: c, ...p }) {
115
- return F(a, p["aria-label"]), /* @__PURE__ */ t("button", {
116
- ref: c,
117
- type: "button",
118
- ...p,
119
- "aria-busy": i || void 0,
120
- "data-loading": i ? "true" : void 0,
121
- "data-svg-only": a ? "true" : void 0,
122
- className: l(g({
123
- variant: e,
124
- size: r,
125
- shape: n
126
- }), i && "pointer-events-none", a && "[&>svg]:size-[1.25em] [&>svg]:shrink-0", h),
127
- children: C({
128
- svgOnly: a,
129
- loading: i,
130
- prefix: s,
131
- suffix: o,
132
- children: d
133
- })
134
- });
135
- }
136
- x.displayName = "Button";
137
- function E({ variant: e, size: r, shape: n, prefix: s, suffix: o, svgOnly: a, loading: i, disabled: d, href: h, children: c, className: p, ...u }) {
138
- return F(a, u["aria-label"]), /* @__PURE__ */ t(R(), {
139
- href: h,
140
- ...u,
141
- "aria-disabled": d || i || void 0,
142
- "aria-busy": i || void 0,
143
- "data-loading": i ? "true" : void 0,
144
- "data-svg-only": a ? "true" : void 0,
145
- className: l(g({
146
- variant: e,
147
- size: r,
148
- shape: n
149
- }), i && "pointer-events-none", a && "[&>svg]:size-[1.25em] [&>svg]:shrink-0", p),
150
- children: C({
151
- svgOnly: a,
152
- loading: i,
153
- prefix: s,
154
- suffix: o,
155
- children: c
156
- })
157
- });
158
- }
159
- E.displayName = "ButtonLink";
160
- var L = {
161
- type: "spring",
162
- stiffness: 200,
163
- damping: 30,
164
- mass: 0.1
165
- }, D = l("squircle overflow-hidden", "hover:bg-pho-brand-solid data-loading:bg-pho-brand-solid", "*:data-icon:opacity-100 hover:*:data-icon:opacity-100", "transition-none"), P = l("[--pho-sheen:light-dark(rgba(255,255,255,0.5),rgba(0,0,0,0.12))]", "shadow-[inset_0_0_0_1px_var(--border-color-pho-on-brand),inset_0_var(--pho-sheen-y,0px)_var(--pho-sheen-blur,5px)_var(--pho-sheen-spread,2px)_var(--pho-sheen)]"), U = {
166
- "--pho-sheen-y": "0px",
167
- "--pho-sheen-blur": "5px",
168
- "--pho-sheen-spread": "2px"
169
- }, j = {
170
- sm: {
171
- "--pho-sheen-y": "-3px",
172
- "--pho-sheen-blur": "8px",
173
- "--pho-sheen-spread": "2px",
174
- gap: 0
175
- },
176
- md: {
177
- "--pho-sheen-y": "-3px",
178
- "--pho-sheen-blur": "8px",
179
- "--pho-sheen-spread": "2px",
180
- gap: 0
181
- },
182
- lg: {
183
- "--pho-sheen-y": "-6px",
184
- "--pho-sheen-blur": "14px",
185
- "--pho-sheen-spread": "1px",
186
- gap: 4
187
- }
188
- }, re = B;
189
- function te(e) {
190
- const { size: r = "md", fullWidth: n, className: s } = e ?? {};
191
- return g({
192
- variant: "primary",
193
- size: r,
194
- shape: "rounded",
195
- className: f(n, s)
196
- });
197
- }
198
- function f(e, r) {
199
- return l(D, P, e && "w-full", r);
200
- }
201
- function O(e) {
202
- return {
203
- rest: {
204
- ...U,
205
- gap: 0
206
- },
207
- hover: { ...j[e] }
208
- };
209
- }
210
- var G = {
211
- sm: {
212
- rest: {
213
- opacity: 0,
214
- width: 1,
215
- height: 9
216
- },
217
- hover: {
218
- opacity: 1,
219
- width: 17,
220
- height: 18
221
- }
222
- },
223
- md: {
224
- rest: {
225
- opacity: 0,
226
- width: 1,
227
- height: 9
228
- },
229
- hover: {
230
- opacity: 1,
231
- width: 17,
232
- height: 18
233
- }
234
- },
235
- lg: {
236
- rest: {
237
- opacity: 0,
238
- width: 1,
239
- height: 10
240
- },
241
- hover: {
242
- opacity: 1,
243
- width: 20,
244
- height: 21
245
- }
246
- }
247
- };
248
- function S({ position: e, size: r, children: n }) {
249
- return /* @__PURE__ */ t(b.span, {
250
- "data-icon": e,
251
- variants: G[r],
252
- transition: L,
253
- style: {
254
- display: "inline-flex",
255
- flex: "none",
256
- alignItems: "center",
257
- overflow: "hidden"
258
- },
259
- className: "pointer-events-none [&>svg]:block [&>svg]:size-full",
260
- children: n
261
- });
262
- }
263
- function m(e, r, n) {
264
- if (!(e == null || e === !1)) {
265
- if (w(e)) return /* @__PURE__ */ t(S, {
266
- position: r,
267
- size: n,
268
- children: /* @__PURE__ */ t(e, {})
269
- });
270
- if (T(e)) return /* @__PURE__ */ t(S, {
271
- position: r,
272
- size: n,
273
- children: e
274
- });
275
- }
276
- }
277
- function I(e, r) {
278
- return {
279
- initial: !1,
280
- animate: "rest",
281
- whileHover: r ? void 0 : "hover",
282
- variants: O(e),
283
- transition: L
284
- };
285
- }
286
- var Z = b.create(x), W = b.create(E);
287
- function J({ size: e = "md", fullWidth: r, animated: n = !0, prefix: s, suffix: o, svgOnly: a, loading: i, children: d, className: h, ref: c, ...p }) {
288
- return n ? /* @__PURE__ */ t(Z, {
289
- ref: c,
290
- variant: "primary",
291
- size: e,
292
- shape: "rounded",
293
- prefix: a ? s : m(s, "prefix", e),
294
- suffix: a ? o : m(o, "suffix", e),
295
- svgOnly: a,
296
- loading: i,
297
- ...I(e, p.disabled || i),
298
- ...p,
299
- className: f(r, h),
300
- children: d
301
- }) : /* @__PURE__ */ t(x, {
302
- ref: c,
303
- variant: "primary",
304
- size: e,
305
- shape: "rounded",
306
- prefix: s,
307
- suffix: o,
308
- svgOnly: a,
309
- loading: i,
310
- className: f(r, h),
311
- ...p,
312
- children: d
313
- });
314
- }
315
- J.displayName = "EffectButton";
316
- function K({ size: e = "md", fullWidth: r, animated: n = !0, prefix: s, suffix: o, svgOnly: a, loading: i, disabled: d, href: h, children: c, className: p, ...u }) {
317
- return n ? /* @__PURE__ */ t(W, {
318
- href: h,
319
- variant: "primary",
320
- size: e,
321
- shape: "rounded",
322
- prefix: a ? s : m(s, "prefix", e),
323
- suffix: a ? o : m(o, "suffix", e),
324
- svgOnly: a,
325
- loading: i,
326
- disabled: d,
327
- ...I(e, d || i),
328
- ...u,
329
- className: f(r, p),
330
- children: c
331
- }) : /* @__PURE__ */ t(E, {
332
- href: h,
333
- variant: "primary",
334
- size: e,
335
- shape: "rounded",
336
- prefix: s,
337
- suffix: o,
338
- svgOnly: a,
339
- loading: i,
340
- disabled: d,
341
- className: f(r, p),
342
- ...u,
343
- children: c
344
- });
345
- }
346
- K.displayName = "EffectButtonLink";
347
- export {
348
- E as a,
349
- K as c,
350
- x as i,
351
- g as l,
352
- B as n,
353
- re as o,
354
- M as r,
355
- J as s,
356
- A as t,
357
- te as u
358
- };
359
-
360
- //# sourceMappingURL=button-BMDHIgZh.js.map