@proteos/ui 0.75.0 → 0.76.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.
- package/dist/{chunk-NWGG5WFL.cjs → chunk-4ACELYEP.cjs} +23 -4
- package/dist/chunk-4ACELYEP.cjs.map +1 -0
- package/dist/{chunk-NSE4VW3Z.js → chunk-XRN5MNDX.js} +24 -5
- package/dist/chunk-XRN5MNDX.js.map +1 -0
- package/dist/index.cjs +409 -288
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -3
- package/dist/index.d.ts +58 -3
- package/dist/index.js +124 -5
- package/dist/index.js.map +1 -1
- package/dist/{pdf-view-RRMAUK3L.cjs → pdf-view-2DSARHNQ.cjs} +7 -7
- package/dist/{pdf-view-RRMAUK3L.cjs.map → pdf-view-2DSARHNQ.cjs.map} +1 -1
- package/dist/{pdf-view-RQ2OZYHJ.js → pdf-view-2QU4FI37.js} +3 -3
- package/dist/{pdf-view-RQ2OZYHJ.js.map → pdf-view-2QU4FI37.js.map} +1 -1
- package/package.json +2 -2
- package/src/components/button/button.stories.tsx +22 -1
- package/src/components/button/button.test.tsx +45 -1
- package/src/components/button/button.tsx +32 -2
- package/src/components/data-table/data-table.test.tsx +41 -0
- package/src/components/data-table/data-table.tsx +24 -2
- package/src/components/glow-frame/glow-frame.stories.tsx +65 -0
- package/src/components/glow-frame/glow-frame.test.tsx +67 -0
- package/src/components/glow-frame/glow-frame.tsx +182 -0
- package/src/components/glow-frame/index.ts +2 -0
- package/src/index.ts +1 -0
- package/src/styles.css +216 -0
- package/dist/chunk-NSE4VW3Z.js.map +0 -1
- package/dist/chunk-NWGG5WFL.cjs.map +0 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var clsx = require('clsx');
|
|
4
4
|
var tailwindMerge = require('tailwind-merge');
|
|
5
|
+
var lucideReact = require('lucide-react');
|
|
5
6
|
var reactAriaComponents = require('react-aria-components');
|
|
6
7
|
var tailwindVariants = require('tailwind-variants');
|
|
7
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -98,15 +99,33 @@ var buttonStyles = tailwindVariants.tv({
|
|
|
98
99
|
shape: "rounded"
|
|
99
100
|
}
|
|
100
101
|
});
|
|
101
|
-
|
|
102
|
+
var isIconSize = (size) => size === "icon-sm" || size === "icon-md" || size === "icon-lg";
|
|
103
|
+
function Button({ variant, size, shape, className, children, ...props }) {
|
|
102
104
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
103
105
|
reactAriaComponents.Button,
|
|
104
106
|
{
|
|
105
107
|
...props,
|
|
106
108
|
className: (renderProps) => cn(
|
|
107
109
|
buttonStyles({ variant, size, shape }),
|
|
110
|
+
renderProps.isPending && "cursor-progress",
|
|
108
111
|
typeof className === "function" ? className(renderProps) : className
|
|
109
|
-
)
|
|
112
|
+
),
|
|
113
|
+
children: (renderProps) => {
|
|
114
|
+
const content = typeof children === "function" ? children(renderProps) : children;
|
|
115
|
+
if (!renderProps.isPending) return content;
|
|
116
|
+
const spinner = /* @__PURE__ */ jsxRuntime.jsx(
|
|
117
|
+
lucideReact.Loader2,
|
|
118
|
+
{
|
|
119
|
+
className: "shrink-0 animate-spin motion-reduce:animate-none",
|
|
120
|
+
"aria-hidden": true,
|
|
121
|
+
"data-slot": "pending-spinner"
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
return isIconSize(size) ? spinner : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
125
|
+
spinner,
|
|
126
|
+
content
|
|
127
|
+
] });
|
|
128
|
+
}
|
|
110
129
|
}
|
|
111
130
|
);
|
|
112
131
|
}
|
|
@@ -139,5 +158,5 @@ exports.Skeleton = Skeleton;
|
|
|
139
158
|
exports.buttonStyles = buttonStyles;
|
|
140
159
|
exports.cn = cn;
|
|
141
160
|
exports.skeletonStyles = skeletonStyles;
|
|
142
|
-
//# sourceMappingURL=chunk-
|
|
143
|
-
//# sourceMappingURL=chunk-
|
|
161
|
+
//# sourceMappingURL=chunk-4ACELYEP.cjs.map
|
|
162
|
+
//# sourceMappingURL=chunk-4ACELYEP.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/cn.ts","../src/components/button/button.tsx","../src/components/skeleton/skeleton.tsx"],"names":["twMerge","clsx","tv","jsx","AriaButton","Loader2","jsxs","Fragment"],"mappings":";;;;;;;;;;AAGO,SAAS,MAAM,MAAA,EAA8B;AAClD,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;AC6BA,IAAM,UAAA,GAAa;AAAA,EACjB,gCAAA;AAAA,EACA;AACF,CAAA;AAIA,IAAM,aAAA,GAAgB;AAAA,EACpB,6DAAA;AAAA,EACA,iDAAA;AAAA,EACA,0CAAA;AAAA,EACA;AACF,CAAA;AAGA,IAAM,YAAA,GAAe;AAAA,EACnB,4CAAA;AAAA,EACA,uCAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,eAAeC,mBAAA,CAAG;AAAA,EAC7B,IAAA,EAAM;AAAA,IACJ,gFAAA;AAAA;AAAA;AAAA,IAGA,qEAAA;AAAA,IACA,oFAAA;AAAA,IACA,qCAAA;AAAA,IACA,4CAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,OAAA,EAAS;AAAA,MACP,GAAA,EAAK,UAAA;AAAA,MACL,MAAA,EAAQ,UAAA;AAAA,MACR,OAAA,EAAS,aAAA;AAAA,MACT,SAAA,EAAW,YAAA;AAAA,MACX,KAAA,EAAO;AAAA,QACL,8CAAA;AAAA,QACA,uCAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,MAAA,EAAQ;AAAA,QACN,8CAAA;AAAA,QACA,uCAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,8CAAA;AAAA,QACA,gCAAA;AAAA,QACA;AAAA,OACF;AAAA;AAAA;AAAA,MAGA,MAAA,EAAQ;AAAA,QACN,sCAAA;AAAA,QACA,2EAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,EAAA,EAAI,oCAAA;AAAA,MACJ,EAAA,EAAI,0CAAA;AAAA,MACJ,EAAA,EAAI,yCAAA;AAAA;AAAA,MAEJ,SAAA,EAAW,6BAAA;AAAA,MACX,SAAA,EAAW,gCAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACb;AAAA;AAAA;AAAA;AAAA,IAIA,KAAA,EAAO;AAAA,MACL,OAAA,EAAS,YAAA;AAAA,MACT,IAAA,EAAM;AAAA;AACR,GACF;AAAA,EACA,gBAAA,EAAkB;AAAA,IAChB,EAAE,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,OAAO,aAAA,EAAc;AAAA,IACpD,EAAE,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,OAAO,aAAA,EAAc;AAAA,IACpD,EAAE,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,OAAO,aAAA,EAAc;AAAA;AAAA,IAEpD,EAAE,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,OAAO,cAAA,EAAe;AAAA,IAC3D,EAAE,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,OAAO,cAAA,EAAe;AAAA;AAAA,IAExD,EAAE,OAAA,EAAS,QAAA,EAAU,KAAA,EAAO,mDAAA;AAAoD,GAClF;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,OAAA,EAAS,SAAA;AAAA,IACT,IAAA,EAAM,IAAA;AAAA,IACN,KAAA,EAAO;AAAA;AAEX,CAAC;AAKD,IAAM,aAAa,CAAC,IAAA,KAClB,SAAS,SAAA,IAAa,IAAA,KAAS,aAAa,IAAA,KAAS,SAAA;AAEhD,SAAS,MAAA,CAAO,EAAE,OAAA,EAAS,IAAA,EAAM,OAAO,SAAA,EAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAgB;AAC3F,EAAA,uBACEC,cAAA;AAAA,IAACC,0BAAA;AAAA,IAAA;AAAA,MACE,GAAG,KAAA;AAAA,MACJ,SAAA,EAAW,CAAC,WAAA,KACV,EAAA;AAAA,QACE,YAAA,CAAa,EAAE,OAAA,EAAS,IAAA,EAAM,OAAO,CAAA;AAAA,QACrC,YAAY,SAAA,IAAa,iBAAA;AAAA,QACzB,OAAO,SAAA,KAAc,UAAA,GAAa,SAAA,CAAU,WAAW,CAAA,GAAI;AAAA,OAC7D;AAAA,MAGD,WAAC,WAAA,KAAgB;AAChB,QAAA,MAAM,UAAU,OAAO,QAAA,KAAa,UAAA,GAAa,QAAA,CAAS,WAAW,CAAA,GAAI,QAAA;AACzE,QAAA,IAAI,CAAC,WAAA,CAAY,SAAA,EAAW,OAAO,OAAA;AACnC,QAAA,MAAM,OAAA,mBACJD,cAAA;AAAA,UAACE,mBAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,kDAAA;AAAA,YACV,aAAA,EAAW,IAAA;AAAA,YACX,WAAA,EAAU;AAAA;AAAA,SACZ;AAEF,QAAA,OAAO,UAAA,CAAW,IAAI,CAAA,GACpB,OAAA,mBAEAC,eAAA,CAAAC,mBAAA,EAAA,EACG,QAAA,EAAA;AAAA,UAAA,OAAA;AAAA,UACA;AAAA,SAAA,EACH,CAAA;AAAA,MAEJ;AAAA;AAAA,GACF;AAEJ;AC1JO,IAAM,iBAAiBL,mBAAAA,CAAG;AAAA,EAC/B,IAAA,EAAM,CAAC,eAAA,EAAiB,cAAc,CAAA;AAAA,EACtC,QAAA,EAAU;AAAA,IACR,KAAA,EAAO;AAAA,MACL,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ,cAAA;AAAA;AAAA;AAAA,MAGR,IAAA,EAAM;AAAA;AACR,GACF;AAAA,EACA,eAAA,EAAiB,EAAE,KAAA,EAAO,MAAA;AAC5B,CAAC;AAKM,SAAS,SAAS,EAAE,KAAA,EAAO,SAAA,EAAW,GAAG,OAAM,EAAkB;AACtE,EAAA,uBACEC,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MAIC,aAAA,EAAY,MAAA;AAAA,MACX,GAAG,KAAA;AAAA,MACJ,WAAW,EAAA,CAAG,cAAA,CAAe,EAAE,KAAA,EAAO,GAAG,SAAS;AAAA;AAAA,GACpD;AAEJ","file":"chunk-4ACELYEP.cjs","sourcesContent":["import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { Loader2 } from 'lucide-react'\nimport { Button as AriaButton, type ButtonProps as AriaButtonProps } from 'react-aria-components'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\n/* =========================================================================\n Button — emphasis ladder, top to bottom:\n\n cta ink fill. The one strong action per view (never two visible).\n primary raised white: `surface` fill, `rule-strong` hairline, rest\n shadow. The everyday button; the default variant.\n secondary muted: `surface-3` fill, no border. Cancel / supporting actions.\n ghost secondary's chrome, only on hover. Invisible at rest.\n subtle borderless text button (toolbars, icon buttons).\n link inline underline.\n danger solid terracotta for destructive confirms.\n\n `accent` is a frozen alias of `cta` — variant names are part of the runtime\n contract for module component bundles, so nothing is ever removed.\n\n Interaction state comes from React Aria's data attributes (`hovered:`,\n `pressed:` — see the @custom-variant block in styles.css); `focus-visible:`\n and `disabled:` stay on the native pseudo-classes because the RAC root IS\n the focusable <button>. Hover is always a colour step on the surface ramp,\n never opacity; press is translateY(1px) plus one more ramp step.\n\n `isPending` (React Aria's: presses are ignored, the button stays\n focusable and announces itself busy) shows a spinner before the label —\n in place of the icon on the icon sizes — so a save that takes a moment\n reads as working, not as a dead button.\n ========================================================================= */\n\n// Ink fill with the indigo-tinted hover. Kept verbatim from the old primary.\nconst ctaClasses = [\n 'bg-ink text-surface border-ink',\n 'hovered:bg-accent-ink hovered:border-accent-ink',\n]\n\n// Raised white: a lighter inner on the darker page ground. On a white card the\n// hairline + rest shadow carry it. Press sinks one step and drops the shadow.\nconst raisedClasses = [\n 'bg-surface text-ink border-rule shadow-[var(--shadow-rest)]',\n 'hovered:bg-surface-2 hovered:border-rule-strong',\n 'pressed:bg-surface-3 pressed:shadow-none',\n 'focus-visible:shadow-[var(--shadow-focus),var(--shadow-rest)]',\n]\n\n// Muted gray fill, no border. One step quieter than primary.\nconst mutedClasses = [\n 'bg-surface-3 text-ink-2 border-transparent',\n 'hovered:bg-surface-4 hovered:text-ink',\n 'pressed:bg-[color-mix(in_oklab,var(--color-ink)_8%,var(--color-surface-4))]',\n]\n\nexport const buttonStyles = tv({\n base: [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap cursor-pointer',\n // Button labels are human copy, not machine fact — Inter 500 (DESIGN.md\n // typography.body), not the mono reserved for ids, timestamps and badges.\n 'font-sans font-medium tracking-[-0.005em] border border-transparent',\n 'transition-[background-color,color,border-color,box-shadow,transform] duration-150',\n 'outline-none pressed:translate-y-px',\n 'focus-visible:shadow-[var(--shadow-focus)]',\n 'disabled:opacity-45 disabled:cursor-not-allowed disabled:pointer-events-none',\n ],\n variants: {\n variant: {\n cta: ctaClasses,\n accent: ctaClasses,\n primary: raisedClasses,\n secondary: mutedClasses,\n ghost: [\n 'bg-transparent text-ink-2 border-transparent',\n 'hovered:bg-surface-3 hovered:text-ink',\n 'pressed:bg-surface-4',\n ],\n subtle: [\n 'bg-transparent text-ink-3 border-transparent',\n 'hovered:bg-surface-2 hovered:text-ink',\n 'pressed:bg-surface-3',\n ],\n link: [\n 'bg-transparent text-ink-2 border-transparent',\n 'px-0.5 border-b border-b-ink-4',\n 'hovered:text-ink hovered:border-b-ink',\n ],\n // `text-surface`, not white: dark's --color-danger is a light salmon, and\n // the surface token flips dark with it while white would fail contrast.\n danger: [\n 'bg-danger text-surface border-danger',\n 'hovered:bg-[color-mix(in_oklab,var(--color-danger)_88%,var(--color-ink))]',\n 'hovered:border-[color-mix(in_oklab,var(--color-danger)_88%,var(--color-ink))]',\n ],\n },\n size: {\n sm: 'text-xs px-3 py-1.5 [&_svg]:size-3',\n md: 'text-[13px] px-4 py-[9px] [&_svg]:size-3',\n lg: 'text-sm px-[22px] py-3 [&_svg]:size-3.5',\n // Square dimensions for icon-only buttons. Requires an `aria-label`.\n 'icon-sm': 'size-7 p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-[34px] p-0 [&_svg]:size-4',\n 'icon-lg': 'size-[42px] p-0 [&_svg]:size-[18px]',\n },\n // Corner shape. Default is rounded (soft 10px radius — the standard\n // Proteos button), `pill` is the fully-rounded treatment for a small set\n // of prominent CTAs. The `link` variant overrides both to a flat underline.\n shape: {\n rounded: 'rounded-md',\n pill: 'rounded-pill',\n },\n },\n compoundVariants: [\n { variant: 'link', size: 'sm', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'md', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'lg', class: 'px-0.5 py-0' },\n // Link never takes a corner radius — it's an underline, not a box.\n { variant: 'link', shape: 'rounded', class: 'rounded-none' },\n { variant: 'link', shape: 'pill', class: 'rounded-none' },\n // Destructive confirms get the terracotta halo instead of the indigo one.\n { variant: 'danger', class: 'focus-visible:shadow-[var(--shadow-focus-danger)]' },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n shape: 'rounded',\n },\n})\n\nexport type ButtonVariants = VariantProps<typeof buttonStyles>\nexport type ButtonProps = AriaButtonProps & ButtonVariants\n\nconst isIconSize = (size: ButtonVariants['size']) =>\n size === 'icon-sm' || size === 'icon-md' || size === 'icon-lg'\n\nexport function Button({ variant, size, shape, className, children, ...props }: ButtonProps) {\n return (\n <AriaButton\n {...props}\n className={(renderProps) =>\n cn(\n buttonStyles({ variant, size, shape }),\n renderProps.isPending && 'cursor-progress',\n typeof className === 'function' ? className(renderProps) : className,\n )\n }\n >\n {(renderProps) => {\n const content = typeof children === 'function' ? children(renderProps) : children\n if (!renderProps.isPending) return content\n const spinner = (\n <Loader2\n className=\"shrink-0 animate-spin motion-reduce:animate-none\"\n aria-hidden\n data-slot=\"pending-spinner\"\n />\n )\n return isIconSize(size) ? (\n spinner\n ) : (\n <>\n {spinner}\n {content}\n </>\n )\n }}\n </AriaButton>\n )\n}\n","import type { HTMLAttributes } from 'react'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\n/* =========================================================================\n Skeleton — content placeholder for loading states.\n Purely presentational, so it doesn't wrap a React Aria primitive (RAC has\n no Skeleton — interactive primitives only). Accessibility lives in props:\n - decorative skeletons get `aria-hidden` so screen readers ignore them\n - skeletons that *announce* the loading state should be wrapped in a\n `role=\"status\"` region by the consumer (e.g. AppLayoutSkeleton).\n ========================================================================= */\n\nexport const skeletonStyles = tv({\n base: ['animate-pulse', 'bg-surface-3'],\n variants: {\n shape: {\n rect: 'rounded-md',\n circle: 'rounded-full',\n // `text` matches a typical line of body text — width is up to the\n // consumer; the rounded-sm + height keep proportions sensible.\n text: 'h-4 w-full rounded-sm',\n },\n },\n defaultVariants: { shape: 'rect' },\n})\n\nexport type SkeletonVariants = VariantProps<typeof skeletonStyles>\nexport type SkeletonProps = HTMLAttributes<HTMLDivElement> & SkeletonVariants\n\nexport function Skeleton({ shape, className, ...props }: SkeletonProps) {\n return (\n <div\n // Decorative by default. Consumers that want screen readers to announce\n // the loading state should wrap a Skeleton group in `role=\"status\"`\n // and pass `aria-hidden={false}` here, or just rely on the wrapper.\n aria-hidden=\"true\"\n {...props}\n className={cn(skeletonStyles({ shape }), className)}\n />\n )\n}\n"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import { Loader2 } from 'lucide-react';
|
|
3
4
|
import { Button as Button$1 } from 'react-aria-components';
|
|
4
5
|
import { tv } from 'tailwind-variants';
|
|
5
|
-
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
8
|
// src/lib/cn.ts
|
|
8
9
|
function cn(...inputs) {
|
|
@@ -96,15 +97,33 @@ var buttonStyles = tv({
|
|
|
96
97
|
shape: "rounded"
|
|
97
98
|
}
|
|
98
99
|
});
|
|
99
|
-
|
|
100
|
+
var isIconSize = (size) => size === "icon-sm" || size === "icon-md" || size === "icon-lg";
|
|
101
|
+
function Button({ variant, size, shape, className, children, ...props }) {
|
|
100
102
|
return /* @__PURE__ */ jsx(
|
|
101
103
|
Button$1,
|
|
102
104
|
{
|
|
103
105
|
...props,
|
|
104
106
|
className: (renderProps) => cn(
|
|
105
107
|
buttonStyles({ variant, size, shape }),
|
|
108
|
+
renderProps.isPending && "cursor-progress",
|
|
106
109
|
typeof className === "function" ? className(renderProps) : className
|
|
107
|
-
)
|
|
110
|
+
),
|
|
111
|
+
children: (renderProps) => {
|
|
112
|
+
const content = typeof children === "function" ? children(renderProps) : children;
|
|
113
|
+
if (!renderProps.isPending) return content;
|
|
114
|
+
const spinner = /* @__PURE__ */ jsx(
|
|
115
|
+
Loader2,
|
|
116
|
+
{
|
|
117
|
+
className: "shrink-0 animate-spin motion-reduce:animate-none",
|
|
118
|
+
"aria-hidden": true,
|
|
119
|
+
"data-slot": "pending-spinner"
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
return isIconSize(size) ? spinner : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
123
|
+
spinner,
|
|
124
|
+
content
|
|
125
|
+
] });
|
|
126
|
+
}
|
|
108
127
|
}
|
|
109
128
|
);
|
|
110
129
|
}
|
|
@@ -133,5 +152,5 @@ function Skeleton({ shape, className, ...props }) {
|
|
|
133
152
|
}
|
|
134
153
|
|
|
135
154
|
export { Button, Skeleton, buttonStyles, cn, skeletonStyles };
|
|
136
|
-
//# sourceMappingURL=chunk-
|
|
137
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-XRN5MNDX.js.map
|
|
156
|
+
//# sourceMappingURL=chunk-XRN5MNDX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/cn.ts","../src/components/button/button.tsx","../src/components/skeleton/skeleton.tsx"],"names":["AriaButton","tv","jsx"],"mappings":"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","file":"chunk-XRN5MNDX.js","sourcesContent":["import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { Loader2 } from 'lucide-react'\nimport { Button as AriaButton, type ButtonProps as AriaButtonProps } from 'react-aria-components'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\n/* =========================================================================\n Button — emphasis ladder, top to bottom:\n\n cta ink fill. The one strong action per view (never two visible).\n primary raised white: `surface` fill, `rule-strong` hairline, rest\n shadow. The everyday button; the default variant.\n secondary muted: `surface-3` fill, no border. Cancel / supporting actions.\n ghost secondary's chrome, only on hover. Invisible at rest.\n subtle borderless text button (toolbars, icon buttons).\n link inline underline.\n danger solid terracotta for destructive confirms.\n\n `accent` is a frozen alias of `cta` — variant names are part of the runtime\n contract for module component bundles, so nothing is ever removed.\n\n Interaction state comes from React Aria's data attributes (`hovered:`,\n `pressed:` — see the @custom-variant block in styles.css); `focus-visible:`\n and `disabled:` stay on the native pseudo-classes because the RAC root IS\n the focusable <button>. Hover is always a colour step on the surface ramp,\n never opacity; press is translateY(1px) plus one more ramp step.\n\n `isPending` (React Aria's: presses are ignored, the button stays\n focusable and announces itself busy) shows a spinner before the label —\n in place of the icon on the icon sizes — so a save that takes a moment\n reads as working, not as a dead button.\n ========================================================================= */\n\n// Ink fill with the indigo-tinted hover. Kept verbatim from the old primary.\nconst ctaClasses = [\n 'bg-ink text-surface border-ink',\n 'hovered:bg-accent-ink hovered:border-accent-ink',\n]\n\n// Raised white: a lighter inner on the darker page ground. On a white card the\n// hairline + rest shadow carry it. Press sinks one step and drops the shadow.\nconst raisedClasses = [\n 'bg-surface text-ink border-rule shadow-[var(--shadow-rest)]',\n 'hovered:bg-surface-2 hovered:border-rule-strong',\n 'pressed:bg-surface-3 pressed:shadow-none',\n 'focus-visible:shadow-[var(--shadow-focus),var(--shadow-rest)]',\n]\n\n// Muted gray fill, no border. One step quieter than primary.\nconst mutedClasses = [\n 'bg-surface-3 text-ink-2 border-transparent',\n 'hovered:bg-surface-4 hovered:text-ink',\n 'pressed:bg-[color-mix(in_oklab,var(--color-ink)_8%,var(--color-surface-4))]',\n]\n\nexport const buttonStyles = tv({\n base: [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap cursor-pointer',\n // Button labels are human copy, not machine fact — Inter 500 (DESIGN.md\n // typography.body), not the mono reserved for ids, timestamps and badges.\n 'font-sans font-medium tracking-[-0.005em] border border-transparent',\n 'transition-[background-color,color,border-color,box-shadow,transform] duration-150',\n 'outline-none pressed:translate-y-px',\n 'focus-visible:shadow-[var(--shadow-focus)]',\n 'disabled:opacity-45 disabled:cursor-not-allowed disabled:pointer-events-none',\n ],\n variants: {\n variant: {\n cta: ctaClasses,\n accent: ctaClasses,\n primary: raisedClasses,\n secondary: mutedClasses,\n ghost: [\n 'bg-transparent text-ink-2 border-transparent',\n 'hovered:bg-surface-3 hovered:text-ink',\n 'pressed:bg-surface-4',\n ],\n subtle: [\n 'bg-transparent text-ink-3 border-transparent',\n 'hovered:bg-surface-2 hovered:text-ink',\n 'pressed:bg-surface-3',\n ],\n link: [\n 'bg-transparent text-ink-2 border-transparent',\n 'px-0.5 border-b border-b-ink-4',\n 'hovered:text-ink hovered:border-b-ink',\n ],\n // `text-surface`, not white: dark's --color-danger is a light salmon, and\n // the surface token flips dark with it while white would fail contrast.\n danger: [\n 'bg-danger text-surface border-danger',\n 'hovered:bg-[color-mix(in_oklab,var(--color-danger)_88%,var(--color-ink))]',\n 'hovered:border-[color-mix(in_oklab,var(--color-danger)_88%,var(--color-ink))]',\n ],\n },\n size: {\n sm: 'text-xs px-3 py-1.5 [&_svg]:size-3',\n md: 'text-[13px] px-4 py-[9px] [&_svg]:size-3',\n lg: 'text-sm px-[22px] py-3 [&_svg]:size-3.5',\n // Square dimensions for icon-only buttons. Requires an `aria-label`.\n 'icon-sm': 'size-7 p-0 [&_svg]:size-3.5',\n 'icon-md': 'size-[34px] p-0 [&_svg]:size-4',\n 'icon-lg': 'size-[42px] p-0 [&_svg]:size-[18px]',\n },\n // Corner shape. Default is rounded (soft 10px radius — the standard\n // Proteos button), `pill` is the fully-rounded treatment for a small set\n // of prominent CTAs. The `link` variant overrides both to a flat underline.\n shape: {\n rounded: 'rounded-md',\n pill: 'rounded-pill',\n },\n },\n compoundVariants: [\n { variant: 'link', size: 'sm', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'md', class: 'px-0.5 py-0' },\n { variant: 'link', size: 'lg', class: 'px-0.5 py-0' },\n // Link never takes a corner radius — it's an underline, not a box.\n { variant: 'link', shape: 'rounded', class: 'rounded-none' },\n { variant: 'link', shape: 'pill', class: 'rounded-none' },\n // Destructive confirms get the terracotta halo instead of the indigo one.\n { variant: 'danger', class: 'focus-visible:shadow-[var(--shadow-focus-danger)]' },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n shape: 'rounded',\n },\n})\n\nexport type ButtonVariants = VariantProps<typeof buttonStyles>\nexport type ButtonProps = AriaButtonProps & ButtonVariants\n\nconst isIconSize = (size: ButtonVariants['size']) =>\n size === 'icon-sm' || size === 'icon-md' || size === 'icon-lg'\n\nexport function Button({ variant, size, shape, className, children, ...props }: ButtonProps) {\n return (\n <AriaButton\n {...props}\n className={(renderProps) =>\n cn(\n buttonStyles({ variant, size, shape }),\n renderProps.isPending && 'cursor-progress',\n typeof className === 'function' ? className(renderProps) : className,\n )\n }\n >\n {(renderProps) => {\n const content = typeof children === 'function' ? children(renderProps) : children\n if (!renderProps.isPending) return content\n const spinner = (\n <Loader2\n className=\"shrink-0 animate-spin motion-reduce:animate-none\"\n aria-hidden\n data-slot=\"pending-spinner\"\n />\n )\n return isIconSize(size) ? (\n spinner\n ) : (\n <>\n {spinner}\n {content}\n </>\n )\n }}\n </AriaButton>\n )\n}\n","import type { HTMLAttributes } from 'react'\nimport { tv, type VariantProps } from 'tailwind-variants'\n\nimport { cn } from '../../lib/cn'\n\n/* =========================================================================\n Skeleton — content placeholder for loading states.\n Purely presentational, so it doesn't wrap a React Aria primitive (RAC has\n no Skeleton — interactive primitives only). Accessibility lives in props:\n - decorative skeletons get `aria-hidden` so screen readers ignore them\n - skeletons that *announce* the loading state should be wrapped in a\n `role=\"status\"` region by the consumer (e.g. AppLayoutSkeleton).\n ========================================================================= */\n\nexport const skeletonStyles = tv({\n base: ['animate-pulse', 'bg-surface-3'],\n variants: {\n shape: {\n rect: 'rounded-md',\n circle: 'rounded-full',\n // `text` matches a typical line of body text — width is up to the\n // consumer; the rounded-sm + height keep proportions sensible.\n text: 'h-4 w-full rounded-sm',\n },\n },\n defaultVariants: { shape: 'rect' },\n})\n\nexport type SkeletonVariants = VariantProps<typeof skeletonStyles>\nexport type SkeletonProps = HTMLAttributes<HTMLDivElement> & SkeletonVariants\n\nexport function Skeleton({ shape, className, ...props }: SkeletonProps) {\n return (\n <div\n // Decorative by default. Consumers that want screen readers to announce\n // the loading state should wrap a Skeleton group in `role=\"status\"`\n // and pass `aria-hidden={false}` here, or just rely on the wrapper.\n aria-hidden=\"true\"\n {...props}\n className={cn(skeletonStyles({ shape }), className)}\n />\n )\n}\n"]}
|