@tinloof/ds 1.0.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/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # @tinloof/ds
2
+
3
+ A design system package built with React, TypeScript, and Tailwind CSS.
4
+
5
+ ## Usage
6
+
7
+ Import components in your project:
8
+
9
+ ```typescript
10
+ import { Button, Input, Skeleton } from "@tinloof/ds";
11
+ ```
12
+
13
+ ### Tailwind CSS Setup
14
+
15
+ The ideal setup is to import the Tailwind config in your own CSS file:
16
+
17
+ ```css
18
+ @import "@tinloof/ds/config.css";
19
+
20
+ /* Your global styles where you can use @apply tw-class-here and extend the Tailwind theme */
21
+ ```
22
+
23
+ This allows you to:
24
+
25
+ - Use `@apply` with design system utilities
26
+ - Extend the Tailwind theme
27
+ - Customize the design system to fit your project
28
+
29
+ ### Standalone CSS (Without Tailwind)
30
+
31
+ If you don't want or can't use Tailwind in your project, you can import the compiled CSS directly:
32
+
33
+ ```typescript
34
+ import "@tinloof/ds/styles.css";
35
+ ```
36
+
37
+ This provides all the compiled styles without requiring Tailwind CSS in your project.
38
+
39
+ ## Local Development
40
+
41
+ ### 1. Install dependencies
42
+
43
+ ```bash
44
+ bun install
45
+ ```
46
+
47
+ ### 2. Install yalc globally
48
+
49
+ If not done yet, install yalc globally:
50
+
51
+ ```bash
52
+ bun add -g yalc
53
+ ```
54
+
55
+ ### 3. Link the package
56
+
57
+ ```bash
58
+ bun run link
59
+ ```
60
+
61
+ This will publish the package to yalc and link it to the dev project.
62
+
63
+ ### 4. Run dev mode
64
+
65
+ ```bash
66
+ bun run dev
67
+ ```
68
+
69
+ This will watch for changes and automatically rebuild and push updates to the dev project.
70
+
71
+ ### 5. Start the dev server (in another terminal)
72
+
73
+ ```bash
74
+ cd dev
75
+ bun run dev
76
+ ```
77
+
78
+ Now you can make changes to components and see them live in the dev project!
79
+
80
+ ### Unlinking
81
+
82
+ When you're done with local development:
83
+
84
+ ```bash
85
+ bun run unlink
86
+ ```
87
+
88
+ ## Building
89
+
90
+ Create a production build:
91
+
92
+ ```bash
93
+ bun run build
94
+ ```
95
+
96
+ This will generate:
97
+
98
+ - ESM and CJS JavaScript bundles in `./dist`
99
+ - Compiled and minified CSS in `./dist/styles.css`
100
+ - TypeScript declaration files in `./dist`
101
+
102
+ ## Scripts
103
+
104
+ - `bun run dev` - Development build with watch mode and automatic yalc push
105
+ - `bun run build` - Production build
106
+ - `bun run link` - Setup yalc link with dev project
107
+ - `bun run unlink` - Remove yalc link from dev project
108
+
109
+ ## Project Structure
110
+
111
+ - `src/` - Source files (TypeScript/React components and CSS)
112
+ - `dist/` - Built output (generated, not committed)
113
+ - `dev/` - Local test React project
114
+ - `build.ts` - Custom build script
115
+
116
+ ## Requirements
117
+
118
+ - Bun v1.3.5 or later
119
+ - React 19.2.4 or later (peer dependency)
120
+ - TypeScript 5.x (peer dependency)
121
+ - yalc (for local development)
@@ -0,0 +1,10 @@
1
+ type ButtonVariant = "base" | "surface" | "transparent" | "active";
2
+ type ButtonSize = 24 | 32;
3
+ export interface ButtonProps extends React.ComponentProps<"button"> {
4
+ variant?: ButtonVariant;
5
+ size?: ButtonSize;
6
+ asChild?: boolean;
7
+ }
8
+ export declare function Button({ className, variant, size, asChild, children, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/base/button.tsx"],"names":[],"mappings":"AAGA,KAAK,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;AACnE,KAAK,UAAU,GAAG,EAAE,GAAG,EAAE,CAAC;AAiB1B,MAAM,WAAW,WAAY,SAAQ,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC;IAClE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,MAAM,CAAC,EACtB,SAAS,EACT,OAAmB,EACnB,IAAS,EACT,OAAe,EACf,QAAQ,EACR,GAAG,KAAK,EACR,EAAE,WAAW,2CAsBb"}
@@ -0,0 +1,8 @@
1
+ export type ChipProps = {
2
+ className?: string;
3
+ variant?: "default" | "interactive";
4
+ isActive?: boolean;
5
+ text?: string;
6
+ } & React.HTMLAttributes<HTMLSpanElement>;
7
+ export declare function Chip({ className, variant, isActive, text, ...props }: ChipProps): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=chip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chip.d.ts","sourceRoot":"","sources":["../../src/base/chip.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;AAM1C,wBAAgB,IAAI,CAAC,EACpB,SAAS,EACT,OAAmB,EACnB,QAAgB,EAChB,IAAY,EACZ,GAAG,KAAK,EACR,EAAE,SAAS,2CAmBX"}
@@ -0,0 +1,22 @@
1
+ import { type SpacedValue } from "@/lib/spaced-wrapper";
2
+ import { type ComponentProps } from "react";
3
+ declare const sizeClasses: {
4
+ readonly 24: "h-6 w-6";
5
+ readonly 32: "h-8 w-8";
6
+ };
7
+ declare const variantClasses: {
8
+ readonly transparent: "bg-transparent border border-transparent text-fg-soft hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 focus-visible:ring focus-visible:ring-fg";
9
+ readonly solid: "bg-surface text-fg-soft border hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed focus-visible:bg-surface-strong transition-colors duration-150 focus-visible:ring focus-visible:ring-fg";
10
+ readonly active: "bg-surface-strong text-fg border disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring focus-visible:ring-fg";
11
+ };
12
+ type IconButtonSize = keyof typeof sizeClasses;
13
+ type IconButtonVariant = keyof typeof variantClasses;
14
+ interface IconButtonProps extends ComponentProps<"button"> {
15
+ size?: IconButtonSize;
16
+ variant?: IconButtonVariant;
17
+ spaced?: SpacedValue;
18
+ asChild?: boolean;
19
+ }
20
+ export declare function IconButton({ className, variant, size, spaced, asChild, children, ...props }: IconButtonProps): import("react/jsx-runtime").JSX.Element;
21
+ export {};
22
+ //# sourceMappingURL=icon-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-button.d.ts","sourceRoot":"","sources":["../../src/base/icon-button.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAGN,KAAK,cAAc,EAEnB,MAAM,OAAO,CAAC;AAEf,QAAA,MAAM,WAAW;;;CAGP,CAAC;AAEX,QAAA,MAAM,cAAc;;;;CAOV,CAAC;AAEX,KAAK,cAAc,GAAG,MAAM,OAAO,WAAW,CAAC;AAC/C,KAAK,iBAAiB,GAAG,MAAM,OAAO,cAAc,CAAC;AAErD,UAAU,eAAgB,SAAQ,cAAc,CAAC,QAAQ,CAAC;IACzD,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,UAAU,CAAC,EAC1B,SAAS,EACT,OAAuB,EACvB,IAAS,EACT,MAAe,EACf,OAAe,EACf,QAAQ,EACR,GAAG,KAAK,EACR,EAAE,eAAe,2CAkCjB"}
@@ -0,0 +1,10 @@
1
+ import { type ComponentProps } from "react";
2
+ type BaseProps = {
3
+ error?: boolean;
4
+ errorMessage?: string;
5
+ variant?: "default" | "surface";
6
+ };
7
+ export type InputProps = BaseProps & Omit<ComponentProps<"input">, keyof BaseProps>;
8
+ export declare function Input(props: InputProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/base/input.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAY,MAAM,OAAO,CAAC;AAOtD,KAAK,SAAS,GAAG;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,SAAS,GACjC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,SAAS,CAAC,CAAC;AAMhD,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,2CAgDtC"}
@@ -0,0 +1,5 @@
1
+ export type SkeletonProps = {
2
+ className?: string;
3
+ } & React.HTMLAttributes<HTMLDivElement>;
4
+ export declare function Skeleton({ className, ...props }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../src/base/skeleton.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;AAEzC,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,2CAO9D"}
@@ -0,0 +1,9 @@
1
+ import { type ComponentProps } from "react";
2
+ type BaseProps = {
3
+ error?: boolean;
4
+ errorMessage?: string;
5
+ };
6
+ export type TextAreaProps = BaseProps & Omit<ComponentProps<"textarea">, keyof BaseProps>;
7
+ export declare function Textarea(props: TextAreaProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=textarea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/base/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAY,MAAM,OAAO,CAAC;AAQtD,KAAK,SAAS,GAAG;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,SAAS,GACpC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,SAAS,CAAC,CAAC;AAMnD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,2CAgD5C"}
@@ -0,0 +1 @@
1
+ var{defineProperty:B,getOwnPropertyNames:K,getOwnPropertyDescriptor:O}=Object,W=Object.prototype.hasOwnProperty;var T=new WeakMap,D=(t)=>{var e=T.get(t),r;if(e)return e;if(e=B({},"__esModule",{value:!0}),t&&typeof t==="object"||typeof t==="function")K(t).map((o)=>!W.call(e,o)&&B(e,o,{get:()=>t[o],enumerable:!(r=O(t,o))||r.enumerable}));return T.set(t,e),e};var q=(t,e)=>{for(var r in e)B(t,r,{get:e[r],enumerable:!0,configurable:!0,set:(o)=>e[r]=()=>o})};var U={};q(U,{spacedWrapperVariants:()=>S,cva:()=>C,cn:()=>a,Textarea:()=>M,SpacedWrapper:()=>d,Skeleton:()=>H,Input:()=>A,IconButton:()=>k,Chip:()=>x,Button:()=>w});module.exports=D(U);function a(...t){return t.flat().filter((e)=>{if(typeof e==="string")return e.trim().length>0;if(typeof e==="number")return!0;if(typeof e==="object"&&e!==null)return!0;return!1}).map((e)=>{if(typeof e==="string")return e.trim();if(typeof e==="number")return String(e);if(typeof e==="object"&&e!==null&&!Array.isArray(e))return Object.entries(e).filter(([r,o])=>Boolean(o)).map(([r,o])=>r).join(" ");return""}).join(" ").split(/\s+/).filter((e)=>e.length>0).join(" ")}var v=require("react"),I=require("react/jsx-runtime"),_={base:"bg-base text-fg border border-transparent hover:bg-surface-soft group-hover/wrapper:bg-surface-soft border disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",surface:"bg-surface-strong text-fg border hover:bg-surface-soft group-hover/wrapper:bg-surface-soft disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 active:bg-surface focus-visible:ring focus-visible:ring-fg",transparent:"bg-transparent text-fg border border-transparent hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",active:"bg-surface-strong text-fg border disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring focus-visible:ring-fg"},G={24:"h-6 px-2.5",32:"h-8 px-3"};function w({className:t,variant:e="surface",size:r=24,asChild:o=!1,children:s,...n}){let i=a("rounded-4 group/button",_[e],G[r],t);if(o&&v.isValidElement(s))return v.cloneElement(s,{...n,className:a(s.props.className,i),tabIndex:0,"data-slot":"button"});return I.jsx("button",{"data-slot":"button",className:i,tabIndex:0,...n,children:s})}var R=require("react/jsx-runtime");function x({className:t,variant:e="default",isActive:r=!1,text:o="New",...s}){return R.jsx("span",{className:a("text-chip px-1 py-0.75 rounded-2 text-fg-soft flex items-center",e==="default"&&"bg-surface-strong",e==="interactive"&&["transition-colors",r?"bg-base":"bg-surface-strong group-hover/wrapper:bg-base group-hover/button:bg-base"],t),...s,children:o})}function C(t,e){return(r)=>{if(!e||!r)return t;let o=[t];for(let s in e.variants){let n=r[s],i=e.defaultVariants?.[s],p=n??i;if(p&&typeof p==="string"){let l=e.variants[s];if(l){let c=l[p];if(c)o.push(String(c))}}}return o.filter(Boolean).join(" ")}}var b=require("react/jsx-runtime"),S=C("w-full",{variants:{spaced:{none:"",top:"mt-0.5 relative group/wrapper after:absolute after:inset-x-0 after:bottom-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",right:"mr-0.5 relative group/wrapper after:absolute after:inset-y-0 after:left-full after:w-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",bottom:"mb-0.5 relative group/wrapper after:absolute after:inset-x-0 after:top-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",left:"ml-0.5 relative group/wrapper after:absolute after:inset-y-0 after:right-full after:w-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",x:"mx-0.5 relative group/wrapper after:absolute after:inset-y-0 after:left-full after:w-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer before:absolute before:inset-y-0 before:right-full before:w-0.5 before:content-[''] before:pointer-events-auto before:cursor-pointer",y:"my-0.5 relative group/wrapper after:absolute after:inset-x-0 after:top-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer before:absolute before:inset-x-0 before:bottom-full before:h-0.5 before:content-[''] before:pointer-events-auto before:cursor-pointer",all:"m-0.5 relative group/wrapper after:absolute after:inset-x-0 after:top-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer before:absolute before:inset-y-0 before:right-full before:w-0.5 before:content-[''] before:pointer-events-auto before:cursor-pointer"}},defaultVariants:{spaced:"none"}});function d({spaced:t="none",className:e,children:r}){if(t==="none")return b.jsx(b.Fragment,{children:r});return b.jsx("div",{className:a(S({spaced:t}),e),children:r})}var V=require("react"),h=require("react/jsx-runtime"),J={24:"h-6 w-6",32:"h-8 w-8"},Q={transparent:"bg-transparent border border-transparent text-fg-soft hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",solid:"bg-surface text-fg-soft border hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed focus-visible:bg-surface-strong transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",active:"bg-surface-strong text-fg border disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring focus-visible:ring-fg"};function k({className:t,variant:e="transparent",size:r=24,spaced:o="none",asChild:s=!1,children:n,...i}){let l=a("rounded-4 group/button flex justify-center items-center",J[r],Q[e],t);if(s&&V.isValidElement(n))return h.jsx(d,{spaced:o,children:V.cloneElement(n,{"data-slot":"icon-button",className:a(l,n.props?.className),tabIndex:0,...i})});return h.jsx(d,{spaced:o,children:h.jsx("button",{"data-slot":"icon-button",className:l,tabIndex:0,...i,children:n})})}var E=require("react");var m=require("react/jsx-runtime");function A(t){let{className:e,errorMessage:r,defaultValue:o,onChange:s,variant:n="default",...i}=t,[p,l]=E.useState(o||""),c=(y)=>{l(y.target.value),s?.(y)},u=!!r,g=!!p,P=a("text-tight text-fg placeholder:text-tight focus:outline-none placeholder:text-fg-soft",n==="default"&&["py-3 border-b focus:border-fg",g&&!u&&"border-fg",!g&&!u&&"border-border",u&&"border-fg-error"],n==="surface"&&["h-8 px-3 border rounded text-regular-12 bg-bg-soft focus:border-fg",u?"border-fg-error":"border-border"],e);return m.jsxs("div",{className:"flex flex-col",children:[m.jsx("input",{className:P,value:p,onChange:c,...i}),r&&m.jsx("p",{className:"text-fg-error text-tight mt-3 mb-2",children:r})]})}var z=require("react");var f=require("react/jsx-runtime");function M(t){let{className:e,errorMessage:r,defaultValue:o,onChange:s,required:n,...i}=t,[p,l]=z.useState(o||""),c=(N)=>{l(N.target.value),s?.(N)},u=!!r,g=!!p,P=!n,y=a("py-3 border-b text-tight text-fg placeholder:text-tight focus:outline-none placeholder:text-fg-soft focus:border-fg resize-none w-full h-20",g&&!u&&"border-fg",!g&&!u&&"border-border",u&&"border-fg-error",e);return f.jsxs("div",{className:"flex flex-col",children:[f.jsxs("div",{className:"relative w-full",children:[f.jsx("textarea",{className:y,value:p,onChange:c,rows:4,required:n,...i}),!g&&P&&f.jsx(x,{variant:"default",isActive:!0,className:"absolute top-2 right-0",text:"Optional"})]}),r&&f.jsx("p",{className:"text-fg-error text-tight mt-3 mb-2",children:r})]})}var L=require("react/jsx-runtime");function H({className:t,...e}){return L.jsx("div",{className:a("rounded-4 animate-skeleton-pulse bg-surface",t),...e})}
@@ -0,0 +1,17 @@
1
+ export { Button } from "./base/button";
2
+ export { Chip } from "./base/chip";
3
+ export { IconButton } from "./base/icon-button";
4
+ export { Input } from "./base/input";
5
+ export { Textarea } from "./base/textarea";
6
+ export { Skeleton } from "./base/skeleton";
7
+ export type { ButtonProps } from "./base/button";
8
+ export type { ChipProps } from "./base/chip";
9
+ export type { InputProps } from "./base/input";
10
+ export type { TextAreaProps } from "./base/textarea";
11
+ export type { SkeletonProps } from "./base/skeleton";
12
+ export { cn } from "./lib/cn";
13
+ export { cva } from "./lib/cva";
14
+ export type { ClassValue, VariantConfig, VariantProps } from "./lib/cva";
15
+ export { SpacedWrapper, spacedWrapperVariants } from "./lib/spaced-wrapper";
16
+ export type { SpacedValue, SpacedWrapperProps } from "./lib/spaced-wrapper";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1 @@
1
+ function o(...r){return r.flat().filter((e)=>{if(typeof e==="string")return e.trim().length>0;if(typeof e==="number")return!0;if(typeof e==="object"&&e!==null)return!0;return!1}).map((e)=>{if(typeof e==="string")return e.trim();if(typeof e==="number")return String(e);if(typeof e==="object"&&e!==null&&!Array.isArray(e))return Object.entries(e).filter(([t,a])=>Boolean(a)).map(([t,a])=>t).join(" ");return""}).join(" ").split(/\s+/).filter((e)=>e.length>0).join(" ")}import{cloneElement as S,isValidElement as N}from"react";import{jsx as R}from"react/jsx-runtime";var T={base:"bg-base text-fg border border-transparent hover:bg-surface-soft group-hover/wrapper:bg-surface-soft border disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",surface:"bg-surface-strong text-fg border hover:bg-surface-soft group-hover/wrapper:bg-surface-soft disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 active:bg-surface focus-visible:ring focus-visible:ring-fg",transparent:"bg-transparent text-fg border border-transparent hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",active:"bg-surface-strong text-fg border disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring focus-visible:ring-fg"},w={24:"h-6 px-2.5",32:"h-8 px-3"};function I({className:r,variant:e="surface",size:t=24,asChild:a=!1,children:s,...n}){let i=o("rounded-4 group/button",T[e],w[t],r);if(a&&N(s))return S(s,{...n,className:o(s.props.className,i),tabIndex:0,"data-slot":"button"});return R("button",{"data-slot":"button",className:i,tabIndex:0,...n,children:s})}import{jsx as k}from"react/jsx-runtime";function m({className:r,variant:e="default",isActive:t=!1,text:a="New",...s}){return k("span",{className:o("text-chip px-1 py-0.75 rounded-2 text-fg-soft flex items-center",e==="default"&&"bg-surface-strong",e==="interactive"&&["transition-colors",t?"bg-base":"bg-surface-strong group-hover/wrapper:bg-base group-hover/button:bg-base"],r),...s,children:a})}function y(r,e){return(t)=>{if(!e||!t)return r;let a=[r];for(let s in e.variants){let n=t[s],i=e.defaultVariants?.[s],p=n??i;if(p&&typeof p==="string"){let l=e.variants[s];if(l){let f=l[p];if(f)a.push(String(f))}}}return a.filter(Boolean).join(" ")}}import{jsx as h,Fragment as E}from"react/jsx-runtime";var V=y("w-full",{variants:{spaced:{none:"",top:"mt-0.5 relative group/wrapper after:absolute after:inset-x-0 after:bottom-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",right:"mr-0.5 relative group/wrapper after:absolute after:inset-y-0 after:left-full after:w-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",bottom:"mb-0.5 relative group/wrapper after:absolute after:inset-x-0 after:top-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",left:"ml-0.5 relative group/wrapper after:absolute after:inset-y-0 after:right-full after:w-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer",x:"mx-0.5 relative group/wrapper after:absolute after:inset-y-0 after:left-full after:w-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer before:absolute before:inset-y-0 before:right-full before:w-0.5 before:content-[''] before:pointer-events-auto before:cursor-pointer",y:"my-0.5 relative group/wrapper after:absolute after:inset-x-0 after:top-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer before:absolute before:inset-x-0 before:bottom-full before:h-0.5 before:content-[''] before:pointer-events-auto before:cursor-pointer",all:"m-0.5 relative group/wrapper after:absolute after:inset-x-0 after:top-full after:h-0.5 after:content-[''] after:pointer-events-auto after:cursor-pointer before:absolute before:inset-y-0 before:right-full before:w-0.5 before:content-[''] before:pointer-events-auto before:cursor-pointer"}},defaultVariants:{spaced:"none"}});function b({spaced:r="none",className:e,children:t}){if(r==="none")return h(E,{children:t});return h("div",{className:o(V({spaced:r}),e),children:t})}import{cloneElement as A,isValidElement as z}from"react";import{jsx as v}from"react/jsx-runtime";var M={24:"h-6 w-6",32:"h-8 w-8"},H={transparent:"bg-transparent border border-transparent text-fg-soft hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",solid:"bg-surface text-fg-soft border hover:bg-surface-strong group-hover/wrapper:bg-surface-strong disabled:opacity-40 disabled:cursor-not-allowed focus-visible:bg-surface-strong transition-colors duration-150 focus-visible:ring focus-visible:ring-fg",active:"bg-surface-strong text-fg border disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring focus-visible:ring-fg"};function L({className:r,variant:e="transparent",size:t=24,spaced:a="none",asChild:s=!1,children:n,...i}){let l=o("rounded-4 group/button flex justify-center items-center",M[t],H[e],r);if(s&&z(n))return v(b,{spaced:a,children:A(n,{"data-slot":"icon-button",className:o(l,n.props?.className),tabIndex:0,...i})});return v(b,{spaced:a,children:v("button",{"data-slot":"icon-button",className:l,tabIndex:0,...i,children:n})})}import{useState as K}from"react";import{jsx as P,jsxs as W}from"react/jsx-runtime";function O(r){let{className:e,errorMessage:t,defaultValue:a,onChange:s,variant:n="default",...i}=r,[p,l]=K(a||""),f=(g)=>{l(g.target.value),s?.(g)},u=!!t,c=!!p,d=o("text-tight text-fg placeholder:text-tight focus:outline-none placeholder:text-fg-soft",n==="default"&&["py-3 border-b focus:border-fg",c&&!u&&"border-fg",!c&&!u&&"border-border",u&&"border-fg-error"],n==="surface"&&["h-8 px-3 border rounded text-regular-12 bg-bg-soft focus:border-fg",u?"border-fg-error":"border-border"],e);return W("div",{className:"flex flex-col",children:[P("input",{className:d,value:p,onChange:f,...i}),t&&P("p",{className:"text-fg-error text-tight mt-3 mb-2",children:t})]})}import{useState as D}from"react";import{jsx as x,jsxs as B}from"react/jsx-runtime";function q(r){let{className:e,errorMessage:t,defaultValue:a,onChange:s,required:n,...i}=r,[p,l]=D(a||""),f=(C)=>{l(C.target.value),s?.(C)},u=!!t,c=!!p,d=!n,g=o("py-3 border-b text-tight text-fg placeholder:text-tight focus:outline-none placeholder:text-fg-soft focus:border-fg resize-none w-full h-20",c&&!u&&"border-fg",!c&&!u&&"border-border",u&&"border-fg-error",e);return B("div",{className:"flex flex-col",children:[B("div",{className:"relative w-full",children:[x("textarea",{className:g,value:p,onChange:f,rows:4,required:n,...i}),!c&&d&&x(m,{variant:"default",isActive:!0,className:"absolute top-2 right-0",text:"Optional"})]}),t&&x("p",{className:"text-fg-error text-tight mt-3 mb-2",children:t})]})}import{jsx as G}from"react/jsx-runtime";function _({className:r,...e}){return G("div",{className:o("rounded-4 animate-skeleton-pulse bg-surface",r),...e})}export{V as spacedWrapperVariants,y as cva,o as cn,q as Textarea,b as SpacedWrapper,_ as Skeleton,O as Input,L as IconButton,m as Chip,I as Button};
@@ -0,0 +1,6 @@
1
+ export declare function cn(...inputs: ClassValue[]): string;
2
+ type ClassValue = string | number | boolean | undefined | null | {
3
+ [key: string]: any;
4
+ } | ClassValue[];
5
+ export {};
6
+ //# sourceMappingURL=cn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/lib/cn.ts"],"names":[],"mappings":"AAAA,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAwBzC;AAED,KAAK,UAAU,GACZ,MAAM,GACN,MAAM,GACN,OAAO,GACP,SAAS,GACT,IAAI,GACJ;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,GACtB,UAAU,EAAE,CAAC"}
@@ -0,0 +1,17 @@
1
+ export type ClassValue = string | number | boolean | undefined | null;
2
+ export type ClassArray = ClassValue[];
3
+ export type ClassDictionary = Record<string, any>;
4
+ export type ClassProp = ClassValue | ClassDictionary | ClassArray;
5
+ export type VariantConfig<T extends Record<string, Record<string, ClassValue>>> = {
6
+ variants: T;
7
+ defaultVariants?: {
8
+ [K in keyof T]?: keyof T[K];
9
+ };
10
+ };
11
+ export type VariantProps<T extends Record<string, Record<string, ClassValue>>> = {
12
+ [K in keyof T]?: keyof T[K];
13
+ };
14
+ export declare function cva<T extends Record<string, Record<string, ClassValue>>>(baseClasses: string, config?: VariantConfig<T>): (props?: VariantProps<T> & {
15
+ className?: string;
16
+ }) => string;
17
+ //# sourceMappingURL=cva.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cva.d.ts","sourceRoot":"","sources":["../../src/lib/cva.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;AACtE,MAAM,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC;AACtC,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAClD,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,eAAe,GAAG,UAAU,CAAC;AAElE,MAAM,MAAM,aAAa,CACxB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,IACjD;IACH,QAAQ,EAAE,CAAC,CAAC;IACZ,eAAe,CAAC,EAAE;SAChB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;KAC3B,CAAC;CACF,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,IAC5E;KACE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC3B,CAAC;AAEH,wBAAgB,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EACvE,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,IAEjB,QAAQ,YAAY,CAAC,CAAC,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,YAyBxD"}
@@ -0,0 +1,33 @@
1
+ import type * as React from "react";
2
+ /**
3
+ * Wrapper variants for adding interactive spacing around buttons.
4
+ * Creates visual gaps with pseudo-elements that extend the hover/click area.
5
+ * Uses w-full by default to match common button layouts. Override with className if needed.
6
+ * Note: group/button is on the button itself, wrapper uses group/wrapper for hover detection.
7
+ */
8
+ export declare const spacedWrapperVariants: (props?: (import("@/lib/cva").VariantProps<{
9
+ spaced: {
10
+ none: string;
11
+ top: string;
12
+ right: string;
13
+ bottom: string;
14
+ left: string;
15
+ x: string;
16
+ y: string;
17
+ all: string;
18
+ };
19
+ }> & {
20
+ className?: string;
21
+ }) | undefined) => string;
22
+ export type SpacedValue = "none" | "top" | "right" | "bottom" | "left" | "x" | "y" | "all";
23
+ export type SpacedWrapperProps = {
24
+ spaced?: SpacedValue;
25
+ className?: string;
26
+ children: React.ReactNode;
27
+ };
28
+ /**
29
+ * Wraps a button to add interactive spacing.
30
+ * The spacing creates visual gaps with pseudo-elements that extend the hover/click area.
31
+ */
32
+ export declare function SpacedWrapper({ spaced, className, children, }: SpacedWrapperProps): import("react/jsx-runtime").JSX.Element;
33
+ //# sourceMappingURL=spaced-wrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spaced-wrapper.d.ts","sourceRoot":"","sources":["../../src/lib/spaced-wrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AASpC;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;yBA2BhC,CAAC;AAMH,MAAM,MAAM,WAAW,GACpB,MAAM,GACN,KAAK,GACL,OAAO,GACP,QAAQ,GACR,MAAM,GACN,GAAG,GACH,GAAG,GACH,KAAK,CAAC;AAET,MAAM,MAAM,kBAAkB,GAAG;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,CAAC;AAMF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC7B,MAAe,EACf,SAAS,EACT,QAAQ,GACR,EAAE,kBAAkB,2CAUpB"}
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-duration:initial;--tw-content:"";--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ABC Oracle,sans-serif;--font-mono:ABC Oracle Mono,monospace;--spacing:.25rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-base:var(--color-base);--color-surface-soft:var(--color-surface-soft);--color-surface:var(--color-surface);--color-surface-strong:var(--color-surface-strong);--color-surface-accent:var(--color-surface-accent);--color-border:var(--color-border);--color-border-soft:var(--color-border-soft);--color-fg:var(--color-fg);--color-fg-soft:var(--color-fg-soft);--color-fg-error:var(--color-fg-error);--text-chip:.625rem;--text-chip--line-height:.625rem;--text-chip--font-weight:350;--text-copy:.75rem;--text-copy--line-height:1rem;--text-copy--font-weight:300;--text-copy-strong:.75rem;--text-copy-strong--line-height:1rem;--text-copy-strong--font-weight:500;--text-tight:.75rem;--text-tight--line-height:.5rem;--text-tight--font-weight:300;--text-tight-strong:.75rem;--text-tight-strong--line-height:.5rem;--text-tight-strong--font-weight:500;--text-heading-24:1.5rem;--text-heading-24--line-height:1.75rem;--text-heading-24--font-weight:500;--text-heading-18:1.125rem;--text-heading-18--line-height:1.375rem;--text-heading-18--font-weight:500;--text-heading-14:.875rem;--text-heading-14--line-height:1.125rem;--text-heading-14--font-weight:500;--text-heading-12:.75rem;--text-heading-12--line-height:1rem;--text-heading-12--font-weight:500;--text-code:.75rem;--text-code--line-height:1rem;--text-code--font-weight:300;--radius-2:.125rem;--radius-4:.25rem;--animate-skeleton-pulse:skeleton-pulse 2s ease-in-out infinite}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}button:not(:disabled),[role=button]:not(:disabled){cursor:pointer}}@layer components{.border{border-color:var(--color-border);border-style:solid;border-width:.5px}.border-soft{border-color:var(--color-border-soft);border-style:solid;border-width:.5px}}@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.top-2{top:calc(var(--spacing)*2)}.right-0{right:calc(var(--spacing)*0)}.m-0\.5{margin:calc(var(--spacing)*.5)}.mx-0\.5{margin-inline:calc(var(--spacing)*.5)}.my-0\.5{margin-block:calc(var(--spacing)*.5)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-3{margin-top:calc(var(--spacing)*3)}.mr-0\.5{margin-right:calc(var(--spacing)*.5)}.mb-0\.5{margin-bottom:calc(var(--spacing)*.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-0\.5{margin-left:calc(var(--spacing)*.5)}.contents{display:contents}.flex{display:flex}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-20{height:calc(var(--spacing)*20)}.h-24{height:calc(var(--spacing)*24)}.h-32{height:calc(var(--spacing)*32)}.min-h-screen{min-height:100vh}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-24{width:calc(var(--spacing)*24)}.w-32{width:calc(var(--spacing)*32)}.w-48{width:calc(var(--spacing)*48)}.w-full{width:100%}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-skeleton-pulse{animation:var(--animate-skeleton-pulse)}.resize-none{resize:none}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.gap-12{gap:calc(var(--spacing)*12)}.rounded{border-radius:.25rem}.rounded-2{border-radius:var(--radius-2)}.rounded-4{border-radius:var(--radius-4)}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-border{border-color:var(--color-border)}.border-fg{border-color:var(--color-fg)}.border-fg-error{border-color:var(--color-fg-error)}.border-transparent{border-color:#0000}.bg-base{background-color:var(--color-base)}.bg-surface{background-color:var(--color-surface)}.bg-surface-strong{background-color:var(--color-surface-strong)}.bg-transparent{background-color:#0000}.p-8{padding:calc(var(--spacing)*8)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.py-0\.75{padding-block:calc(var(--spacing)*.75)}.py-3{padding-block:calc(var(--spacing)*3)}.text-chip{font-size:var(--text-chip);line-height:var(--tw-leading,var(--text-chip--line-height));font-weight:var(--tw-font-weight,var(--text-chip--font-weight))}.text-tight{font-size:var(--text-tight);line-height:var(--tw-leading,var(--text-tight--line-height));font-weight:var(--tw-font-weight,var(--text-tight--font-weight))}.text-fg{color:var(--color-fg)}.text-fg-error{color:var(--color-fg-error)}.text-fg-soft{color:var(--color-fg-soft)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}@media (hover:hover){.group-hover\/button\:bg-base:is(:where(.group\/button):hover *),.group-hover\/wrapper\:bg-base:is(:where(.group\/wrapper):hover *){background-color:var(--color-base)}.group-hover\/wrapper\:bg-surface-soft:is(:where(.group\/wrapper):hover *){background-color:var(--color-surface-soft)}.group-hover\/wrapper\:bg-surface-strong:is(:where(.group\/wrapper):hover *){background-color:var(--color-surface-strong)}}.placeholder\:text-tight::placeholder{font-size:var(--text-tight);line-height:var(--tw-leading,var(--text-tight--line-height));font-weight:var(--tw-font-weight,var(--text-tight--font-weight))}.placeholder\:text-fg-soft::placeholder{color:var(--color-fg-soft)}.before\:pointer-events-auto:before{content:var(--tw-content);pointer-events:auto}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:inset-x-0:before{content:var(--tw-content);inset-inline:calc(var(--spacing)*0)}.before\:inset-y-0:before{content:var(--tw-content);inset-block:calc(var(--spacing)*0)}.before\:right-full:before{content:var(--tw-content);right:100%}.before\:bottom-full:before{content:var(--tw-content);bottom:100%}.before\:h-0\.5:before{content:var(--tw-content);height:calc(var(--spacing)*.5)}.before\:w-0\.5:before{content:var(--tw-content);width:calc(var(--spacing)*.5)}.before\:cursor-pointer:before{content:var(--tw-content);cursor:pointer}.before\:content-\[\'\'\]:before{--tw-content:"";content:var(--tw-content)}.after\:pointer-events-auto:after{content:var(--tw-content);pointer-events:auto}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-x-0:after{content:var(--tw-content);inset-inline:calc(var(--spacing)*0)}.after\:inset-y-0:after{content:var(--tw-content);inset-block:calc(var(--spacing)*0)}.after\:top-full:after{content:var(--tw-content);top:100%}.after\:right-full:after{content:var(--tw-content);right:100%}.after\:bottom-full:after{content:var(--tw-content);bottom:100%}.after\:left-full:after{content:var(--tw-content);left:100%}.after\:h-0\.5:after{content:var(--tw-content);height:calc(var(--spacing)*.5)}.after\:w-0\.5:after{content:var(--tw-content);width:calc(var(--spacing)*.5)}.after\:cursor-pointer:after{content:var(--tw-content);cursor:pointer}.after\:content-\[\'\'\]:after{--tw-content:"";content:var(--tw-content)}@media (hover:hover){.hover\:bg-surface-soft:hover{background-color:var(--color-surface-soft)}.hover\:bg-surface-strong:hover{background-color:var(--color-surface-strong)}}.focus\:border-fg:focus{border-color:var(--color-fg)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:bg-surface-strong:focus-visible{background-color:var(--color-surface-strong)}.focus-visible\:ring:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-fg:focus-visible{--tw-ring-color:var(--color-fg)}.active\:bg-surface:active{background-color:var(--color-surface)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}}:root{--color-base:white;--color-surface-soft:#fafafa;--color-surface:#f0f0f0;--color-surface-strong:#e6e6e6;--color-surface-accent:#ccc;--color-border:#e0e0e0;--color-border-soft:#ededed;--color-fg:black;--color-fg-soft:#666;--color-fg-error:#c10134;--border-width:.5px}@media (prefers-color-scheme:dark){:root{--color-base:black;--color-surface-soft:#0a0a0a;--color-surface:#0f0f0f;--color-surface-strong:#141414;--color-surface-accent:#383838;--color-border:#242424;--color-border-soft:#171717;--color-fg:white;--color-fg-soft:#999;--color-fg-error:#c10134}}body{font-size:var(--text-copy);line-height:var(--tw-leading,var(--text-copy--line-height));font-weight:var(--tw-font-weight,var(--text-copy--font-weight));color:var(--color-fg);background-color:var(--color-base);text-wrap:balance}p,code,pre{max-width:65ch}code,pre{font-size:var(--text-code);line-height:var(--tw-leading,var(--text-code--line-height));font-weight:var(--tw-font-weight,var(--text-code--font-weight));text-wrap:nowrap}.heading-24{font-size:var(--text-heading-24);line-height:var(--tw-leading,var(--text-heading-24--line-height));font-weight:var(--tw-font-weight,var(--text-heading-24--font-weight))}.heading-18{font-size:var(--text-heading-18);line-height:var(--tw-leading,var(--text-heading-18--line-height));font-weight:var(--tw-font-weight,var(--text-heading-18--font-weight))}.heading-14{font-size:var(--text-heading-14);line-height:var(--tw-leading,var(--text-heading-14--line-height));font-weight:var(--tw-font-weight,var(--text-heading-14--font-weight))}.heading-12{font-size:var(--text-heading-12);line-height:var(--tw-leading,var(--text-heading-12--line-height));font-weight:var(--tw-font-weight,var(--text-heading-12--font-weight))}.copy{font-size:var(--text-copy);line-height:var(--tw-leading,var(--text-copy--line-height));font-weight:var(--tw-font-weight,var(--text-copy--font-weight))}.copy-strong{font-size:var(--text-copy-strong);line-height:var(--tw-leading,var(--text-copy-strong--line-height));font-weight:var(--tw-font-weight,var(--text-copy-strong--font-weight))}.tight{font-size:var(--text-tight);line-height:var(--tw-leading,var(--text-tight--line-height));font-weight:var(--tw-font-weight,var(--text-tight--font-weight))}.tight-strong{font-size:var(--text-tight-strong);line-height:var(--tw-leading,var(--text-tight-strong--line-height));font-weight:var(--tw-font-weight,var(--text-tight-strong--font-weight))}::selection{background-color:var(--color-fg);color:var(--color-base)}:focus-visible{outline:none}@keyframes skeleton-pulse{0%,to{background-color:var(--color-surface-soft)}50%{background-color:var(--color-surface-strong)}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@tinloof/ds",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs.js",
6
+ "module": "./dist/index.esm.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.esm.js",
12
+ "require": "./dist/index.cjs.js"
13
+ },
14
+ "./config.css": "./src/config.css",
15
+ "./styles.css": "./dist/styles.css"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src/config.css"
20
+ ],
21
+ "scripts": {
22
+ "build": "bun run build.ts --production",
23
+ "dev": "bun run build.ts --watch --yalc",
24
+ "link": "yalc publish && cd dev && yalc add @tinloof/ds && bun install",
25
+ "unlink": "cd dev && yalc remove @tinloof/ds && bun install",
26
+ "changeset": "changeset",
27
+ "version": "changeset version",
28
+ "release": "bun run build && changeset publish",
29
+ "format": "biome format --write .",
30
+ "format:check": "biome format .",
31
+ "lint": "biome lint --write .",
32
+ "lint:check": "biome lint .",
33
+ "check": "biome check --write .",
34
+ "check:ci": "biome ci ."
35
+ },
36
+ "devDependencies": {
37
+ "@biomejs/biome": "2.3.14",
38
+ "@changesets/cli": "^2.29.8",
39
+ "@tailwindcss/cli": "^4.1.18",
40
+ "@types/bun": "latest",
41
+ "@types/react": "^19.2.10",
42
+ "tailwindcss": "^4.1.18"
43
+ },
44
+ "peerDependencies": {
45
+ "react": "^19.2.4",
46
+ "typescript": "^5"
47
+ }
48
+ }
package/src/config.css ADDED
@@ -0,0 +1,211 @@
1
+ @import "tailwindcss";
2
+ @custom-variant dark (&:where(.dark, .dark *));
3
+
4
+ :root {
5
+ --color-base: white;
6
+
7
+ --color-surface-soft: #fafafa;
8
+ --color-surface: #f0f0f0;
9
+ --color-surface-strong: #e6e6e6;
10
+ --color-surface-accent: #cccccc;
11
+
12
+ --color-border: #e0e0e0;
13
+ --color-border-soft: #ededed;
14
+
15
+ --color-fg: black;
16
+ --color-fg-soft: #666666;
17
+ --color-fg-error: #c10134;
18
+
19
+ --border-width: 0.5px;
20
+ }
21
+
22
+ @media (prefers-color-scheme: dark) {
23
+ :root {
24
+ --color-base: black;
25
+
26
+ --color-surface-soft: #0a0a0a;
27
+ --color-surface: #0f0f0f;
28
+ --color-surface-strong: #141414;
29
+ --color-surface-accent: #383838;
30
+
31
+ --color-border: #242424;
32
+ --color-border-soft: #171717;
33
+
34
+ --color-fg: white;
35
+ --color-fg-soft: #999999;
36
+ --color-fg-error: #c10134;
37
+ }
38
+ }
39
+
40
+ @theme inline {
41
+ --color-base: var(--color-base);
42
+ --color-surface-soft: var(--color-surface-soft);
43
+ --color-surface: var(--color-surface);
44
+ --color-surface-strong: var(--color-surface-strong);
45
+ --color-surface-accent: var(--color-surface-accent);
46
+ --color-border: var(--color-border);
47
+ --color-border-soft: var(--color-border-soft);
48
+ --color-fg: var(--color-fg);
49
+ --color-fg-soft: var(--color-fg-soft);
50
+ --color-fg-error: var(--color-fg-error);
51
+ }
52
+
53
+ @theme {
54
+ --font-sans: ABC Oracle, sans-serif;
55
+ --font-mono: ABC Oracle Mono, monospace;
56
+ --font-sandbox-code: ABC Oracle Mono, monospace;
57
+
58
+ --text-chip: 0.625rem;
59
+ --text-chip--line-height: 0.625rem;
60
+ --text-chip--font-weight: 350;
61
+
62
+ --text-copy: 0.75rem;
63
+ --text-copy--line-height: 1rem;
64
+ --text-copy--font-weight: 300;
65
+
66
+ --text-copy-strong: 0.75rem;
67
+ --text-copy-strong--line-height: 1rem;
68
+ --text-copy-strong--font-weight: 500;
69
+
70
+ --text-tight: 0.75rem;
71
+ --text-tight--line-height: 0.5rem;
72
+ --text-tight--font-weight: 300;
73
+
74
+ --text-tight-strong: 0.75rem;
75
+ --text-tight-strong--line-height: 0.5rem;
76
+ --text-tight-strong--font-weight: 500;
77
+
78
+ --text-heading-24: 1.5rem;
79
+ --text-heading-24--line-height: 1.75rem;
80
+ --text-heading-24--font-weight: 500;
81
+
82
+ --text-heading-18: 1.125rem;
83
+ --text-heading-18--line-height: 1.375rem;
84
+ --text-heading-18--font-weight: 500;
85
+
86
+ --text-heading-14: 0.875rem;
87
+ --text-heading-14--line-height: 1.125rem;
88
+ --text-heading-14--font-weight: 500;
89
+
90
+ --text-heading-12: 0.75rem;
91
+ --text-heading-12--line-height: 1rem;
92
+ --text-heading-12--font-weight: 500;
93
+
94
+ --text-code: 0.75rem;
95
+ --text-code--line-height: 1rem;
96
+ --text-code--font-weight: 300;
97
+
98
+ --radius-2: 0.125rem;
99
+ --radius-4: 0.25rem;
100
+ --radius-6: 0.375rem;
101
+
102
+ --spacing-hpx: 0.5px;
103
+ --border-width: 0.5px;
104
+
105
+ --animate-skeleton-pulse: skeleton-pulse 2s ease-in-out infinite;
106
+ }
107
+
108
+ body {
109
+ @apply text-copy;
110
+ @apply text-fg;
111
+ @apply bg-base;
112
+ @apply text-balance;
113
+ }
114
+
115
+ p,
116
+ code,
117
+ pre {
118
+ @apply max-w-prose; /* 65 characters per line */
119
+ }
120
+
121
+ code,
122
+ pre {
123
+ @apply text-code;
124
+ @apply text-nowrap; /* TODO need to research if this is the best approach for code blocks */
125
+ }
126
+
127
+ .heading-24 {
128
+ @apply text-heading-24;
129
+ }
130
+
131
+ .heading-18 {
132
+ @apply text-heading-18;
133
+ }
134
+
135
+ .heading-14 {
136
+ @apply text-heading-14;
137
+ }
138
+
139
+ .heading-12 {
140
+ @apply text-heading-12;
141
+ }
142
+
143
+ .copy {
144
+ @apply text-copy;
145
+ }
146
+
147
+ .copy-strong {
148
+ @apply text-copy-strong;
149
+ }
150
+
151
+ .tight {
152
+ @apply text-tight;
153
+ }
154
+
155
+ .tight-strong {
156
+ @apply text-tight-strong;
157
+ }
158
+
159
+ @layer components {
160
+ .border {
161
+ border-color: var(--color-border);
162
+ border-width: 0.5px;
163
+ border-style: solid;
164
+ }
165
+
166
+ .border-soft {
167
+ border-color: var(--color-border-soft);
168
+ border-width: 0.5px;
169
+ border-style: solid;
170
+ }
171
+ }
172
+
173
+ ::selection {
174
+ background-color: var(--color-fg);
175
+ color: var(--color-base);
176
+ }
177
+
178
+ ::-moz-selection {
179
+ background-color: var(--color-fg);
180
+ color: var(--color-base);
181
+ }
182
+
183
+ *:focus-visible {
184
+ outline: none;
185
+ }
186
+
187
+ @layer base {
188
+ button:not(:disabled),
189
+ [role="button"]:not(:disabled) {
190
+ cursor: pointer;
191
+ }
192
+ }
193
+
194
+ @utility hide-scrollbars {
195
+ scrollbar-width: none;
196
+ -ms-overflow-style: none;
197
+
198
+ &::-webkit-scrollbar {
199
+ display: none;
200
+ }
201
+ }
202
+
203
+ @keyframes skeleton-pulse {
204
+ 0%,
205
+ 100% {
206
+ background-color: var(--color-surface-soft);
207
+ }
208
+ 50% {
209
+ background-color: var(--color-surface-strong);
210
+ }
211
+ }