@jinaan/uikit 0.1.3 → 0.1.5

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/select.d.ts CHANGED
@@ -1,8 +1,13 @@
1
1
  import * as SelectPrimitive from "@radix-ui/react-select";
2
+ import { type ComponentPropsWithoutRef } from "react";
2
3
  export declare const Select: import("react").FC<SelectPrimitive.SelectProps>;
3
4
  export declare const SelectGroup: import("react").ForwardRefExoticComponent<SelectPrimitive.SelectGroupProps & import("react").RefAttributes<HTMLDivElement>>;
4
5
  export declare const SelectValue: import("react").ForwardRefExoticComponent<SelectPrimitive.SelectValueProps & import("react").RefAttributes<HTMLSpanElement>>;
5
- export declare const SelectTrigger: import("react").ForwardRefExoticComponent<Omit<SelectPrimitive.SelectTriggerProps & import("react").RefAttributes<HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
6
+ export interface SelectTriggerProps extends ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> {
7
+ /** `field` fills a form; `inline` mimics the compact app dropdown. */
8
+ variant?: "field" | "inline";
9
+ }
10
+ export declare const SelectTrigger: import("react").ForwardRefExoticComponent<SelectTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
6
11
  export declare const SelectContent: import("react").ForwardRefExoticComponent<Omit<SelectPrimitive.SelectContentProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
7
12
  export declare const SelectItem: import("react").ForwardRefExoticComponent<Omit<SelectPrimitive.SelectItemProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
8
13
  export declare const SelectLabel: import("react").ForwardRefExoticComponent<Omit<SelectPrimitive.SelectLabelProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../src/select.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAM1D,eAAO,MAAM,MAAM,iDAAuB,CAAC;AAC3C,eAAO,MAAM,WAAW,6HAAwB,CAAC;AACjD,eAAO,MAAM,WAAW,8HAAwB,CAAC;AAEjD,eAAO,MAAM,aAAa,kMAmBxB,CAAC;AAGH,eAAO,MAAM,aAAa,4LAuBxB,CAAC;AAGH,eAAO,MAAM,UAAU,yLAmBrB,CAAC;AAGH,eAAO,MAAM,WAAW,0LAStB,CAAC"}
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../src/select.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAEL,KAAK,wBAAwB,EAE9B,MAAM,OAAO,CAAC;AAIf,eAAO,MAAM,MAAM,iDAAuB,CAAC;AAC3C,eAAO,MAAM,WAAW,6HAAwB,CAAC;AACjD,eAAO,MAAM,WAAW,8HAAwB,CAAC;AAEjD,MAAM,WAAW,kBAAmB,SAAQ,wBAAwB,CAClE,OAAO,eAAe,CAAC,OAAO,CAC/B;IACC,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC9B;AAED,eAAO,MAAM,aAAa,kHAuBxB,CAAC;AAGH,eAAO,MAAM,aAAa,4LA+BzB,CAAC;AAGF,eAAO,MAAM,UAAU,yLAmBrB,CAAC;AAGH,eAAO,MAAM,WAAW,0LAStB,CAAC"}
@@ -9,6 +9,10 @@ export interface TableSurfaceAction {
9
9
  disabled?: boolean;
10
10
  }
11
11
  interface TableSurfaceProps {
12
+ /** Title above the header row. */
13
+ title?: ReactNode;
14
+ /** Supporting text under the title. */
15
+ description?: ReactNode;
12
16
  /** Header row content (a single row of column cells). */
13
17
  header?: ReactNode;
14
18
  /** Panel content: the body table, or an empty / loading / error state. */
@@ -33,6 +37,6 @@ interface TableSurfaceProps {
33
37
  * Colors come from the `--table-*` tokens and can be adjusted per surface with
34
38
  * `tone` plus `headerClassName` / `panelClassName`.
35
39
  */
36
- export declare function TableSurface({ header, children, action, tone, className, headerClassName, panelClassName, minHeight, }: TableSurfaceProps): import("react").JSX.Element;
40
+ export declare function TableSurface({ title, description, header, children, action, tone, className, headerClassName, panelClassName, minHeight, }: TableSurfaceProps): import("react").JSX.Element;
37
41
  export {};
38
42
  //# sourceMappingURL=table-surface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"table-surface.d.ts","sourceRoot":"","sources":["../src/table-surface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;IAC1D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,iBAAiB;IACzB,yDAAyD;IACzD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IACpB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,SAAS,GAAG,kBAAkB,CAAC;IACxC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAyBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,QAAQ,EACR,MAAM,EACN,IAAgB,EAChB,SAAS,EACT,eAAe,EACf,cAAc,EACd,SAAS,GACV,EAAE,iBAAiB,+BA8CnB"}
1
+ {"version":3,"file":"table-surface.d.ts","sourceRoot":"","sources":["../src/table-surface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;IAC1D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,iBAAiB;IACzB,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uCAAuC;IACvC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,yDAAyD;IACzD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IACpB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,SAAS,GAAG,kBAAkB,CAAC;IACxC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAyBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,MAAM,EACN,IAAgB,EAChB,SAAS,EACT,eAAe,EACf,cAAc,EACd,SAAS,GACV,EAAE,iBAAiB,+BA8DnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jinaan/uikit",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Reusable React and Tailwind UI components for Jinaan projects.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -41,7 +41,7 @@ export function AgentPrompt({
41
41
  {icon ?? <Robot className="size-3.5" weight="fill" />}
42
42
  {tag}
43
43
  </span>
44
- <div className="flex w-full items-center gap-2 rounded-xl border border-line bg-surface py-2 pl-3 pr-2 shadow-sm">
44
+ <div className="mt-2 flex w-full items-center gap-2 rounded-xl border border-line bg-surface py-2 pl-3 pr-2 shadow-sm">
45
45
  <Terminal className="size-4 shrink-0 text-subtle" aria-hidden />
46
46
  <span className="truncate font-mono text-sm text-fg">{command}</span>
47
47
  <Button
package/src/button.tsx CHANGED
@@ -6,7 +6,7 @@ import { Spinner } from "./spinner";
6
6
  import { cn } from "./utils";
7
7
 
8
8
  const buttonVariants = cva(
9
- "relative inline-flex select-none items-center justify-center gap-[var(--control-gap)] whitespace-nowrap rounded-[var(--control-radius)] border border-transparent font-medium transition-[color,background-color,border-color,box-shadow,transform] duration-[120ms] active:scale-[0.97] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus/40 focus-visible:ring-offset-1 focus-visible:ring-offset-canvas disabled:pointer-events-none disabled:opacity-50",
9
+ "relative inline-flex select-none items-center justify-center gap-[var(--control-gap)] whitespace-nowrap rounded-[var(--control-radius)] border border-transparent font-medium transition-[color,background-color,border-color,box-shadow,transform] duration-[120ms] active:scale-[0.97] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-line-strong disabled:pointer-events-none disabled:opacity-50",
10
10
  {
11
11
  variants: {
12
12
  variant: {
package/src/card.tsx CHANGED
@@ -1,61 +1,104 @@
1
- import { forwardRef, type HTMLAttributes } from "react";
1
+ import {
2
+ Children,
3
+ forwardRef,
4
+ isValidElement,
5
+ type HTMLAttributes,
6
+ type ReactNode,
7
+ } from "react";
2
8
 
9
+ import { TableSurface } from "./table-surface";
3
10
  import { cn } from "./utils";
4
11
 
12
+ function splitCardChildren(children: ReactNode): {
13
+ header: ReactNode;
14
+ body: ReactNode;
15
+ } {
16
+ const nodes = Children.toArray(children);
17
+ const headers = nodes.filter(
18
+ (child) => isValidElement(child) && child.type === CardHeader,
19
+ );
20
+ return {
21
+ header: headers.length > 0 ? <>{headers}</> : undefined,
22
+ body: nodes.filter((child) => !headers.includes(child)),
23
+ };
24
+ }
25
+
5
26
  export const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
6
- ({ className, ...props }, ref) => (
7
- <div
8
- ref={ref}
9
- className={cn(
10
- "rounded-card border border-line bg-surface shadow-xs",
11
- className,
12
- )}
13
- {...props}
14
- />
15
- ),
27
+ ({ className, children, ...props }, ref) => {
28
+ const { header, body } = splitCardChildren(children);
29
+ return (
30
+ <div ref={ref} {...props}>
31
+ <TableSurface className={cn("shadow-xs", className)} header={header}>
32
+ {body}
33
+ </TableSurface>
34
+ </div>
35
+ );
36
+ },
16
37
  );
17
38
  Card.displayName = "Card";
18
39
 
19
- export const CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
20
- ({ className, ...props }, ref) => (
21
- <div
22
- ref={ref}
23
- className={cn("flex flex-col gap-1 border-b border-line px-5 py-4", className)}
24
- {...props}
25
- />
26
- ),
27
- );
40
+ export const CardHeader = forwardRef<
41
+ HTMLDivElement,
42
+ HTMLAttributes<HTMLDivElement>
43
+ >(({ className, ...props }, ref) => (
44
+ <div
45
+ ref={ref}
46
+ className={cn(
47
+ "flex flex-col gap-1 px-5 py-4",
48
+ className,
49
+ )}
50
+ {...props}
51
+ />
52
+ ));
28
53
  CardHeader.displayName = "CardHeader";
29
54
 
30
- export const CardTitle = forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement>>(
31
- ({ className, ...props }, ref) => (
32
- <h2 ref={ref} className={cn("text-sm font-semibold text-fg", className)} {...props} />
33
- ),
34
- );
55
+ export const CardTitle = forwardRef<
56
+ HTMLHeadingElement,
57
+ HTMLAttributes<HTMLHeadingElement>
58
+ >(({ className, ...props }, ref) => (
59
+ <h2
60
+ ref={ref}
61
+ className={cn("text-sm font-semibold text-fg", className)}
62
+ {...props}
63
+ />
64
+ ));
35
65
  CardTitle.displayName = "CardTitle";
36
66
 
37
67
  export const CardDescription = forwardRef<
38
68
  HTMLParagraphElement,
39
69
  HTMLAttributes<HTMLParagraphElement>
40
70
  >(({ className, ...props }, ref) => (
41
- <p ref={ref} className={cn("text-sm text-muted", className)} {...props} />
71
+ <p
72
+ ref={ref}
73
+ className={cn(
74
+ "mt-1 border-t border-card-divider pt-2 text-sm text-muted",
75
+ "first:mt-0 first:border-t-0 first:pt-0",
76
+ className,
77
+ )}
78
+ {...props}
79
+ />
42
80
  ));
43
81
  CardDescription.displayName = "CardDescription";
44
82
 
45
- export const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
46
- ({ className, ...props }, ref) => (
47
- <div ref={ref} className={cn("px-5 py-4", className)} {...props} />
48
- ),
49
- );
83
+ export const CardContent = forwardRef<
84
+ HTMLDivElement,
85
+ HTMLAttributes<HTMLDivElement>
86
+ >(({ className, ...props }, ref) => (
87
+ <div ref={ref} className={cn("px-5 py-4", className)} {...props} />
88
+ ));
50
89
  CardContent.displayName = "CardContent";
51
90
 
52
- export const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
53
- ({ className, ...props }, ref) => (
54
- <div
55
- ref={ref}
56
- className={cn("flex items-center gap-3 border-t border-line px-5 py-3", className)}
57
- {...props}
58
- />
59
- ),
60
- );
91
+ export const CardFooter = forwardRef<
92
+ HTMLDivElement,
93
+ HTMLAttributes<HTMLDivElement>
94
+ >(({ className, ...props }, ref) => (
95
+ <div
96
+ ref={ref}
97
+ className={cn(
98
+ "flex items-center gap-3 border-t border-line px-5 py-3",
99
+ className,
100
+ )}
101
+ {...props}
102
+ />
103
+ ));
61
104
  CardFooter.displayName = "CardFooter";
package/src/checkbox.tsx CHANGED
@@ -11,16 +11,16 @@ export const Checkbox = forwardRef<
11
11
  <CheckboxPrimitive.Root
12
12
  ref={ref}
13
13
  className={cn(
14
- "peer size-4 shrink-0 rounded border border-line-strong bg-surface transition-colors",
14
+ "peer size-4 shrink-0 rounded border border-line-strong bg-transparent transition-colors",
15
15
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus/40",
16
16
  "disabled:cursor-not-allowed disabled:opacity-50",
17
- "data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-fg",
18
- "data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-fg",
17
+ "data-[state=checked]:border-primary",
18
+ "data-[state=indeterminate]:border-primary",
19
19
  className,
20
20
  )}
21
21
  {...props}
22
22
  >
23
- <CheckboxPrimitive.Indicator className="flex items-center justify-center text-current">
23
+ <CheckboxPrimitive.Indicator className="btn-fill btn-inner-border flex size-full items-center justify-center rounded-[3px] border-0 bg-[var(--button-primary-bg)] text-[var(--button-primary-fg)] [--button-inner:var(--button-primary-inner)]">
24
24
  {props.checked === "indeterminate" ? (
25
25
  <Minus className="size-3" weight="bold" />
26
26
  ) : (
@@ -1,8 +1,7 @@
1
1
  import { Check, Copy } from "@phosphor-icons/react";
2
2
  import { useState, type ReactNode } from "react";
3
3
 
4
- import { Button } from "./button";
5
- import { cn } from "./utils";
4
+ import { TableSurface } from "./table-surface";
6
5
 
7
6
  interface CodeBlockProps {
8
7
  code: string;
@@ -26,28 +25,30 @@ export function CodeBlock({ code, label, className }: CodeBlockProps) {
26
25
  };
27
26
 
28
27
  return (
29
- <div
30
- className={cn(
31
- "overflow-hidden rounded-lg border border-line bg-canvas",
32
- className,
33
- )}
28
+ <TableSurface
29
+ className={className}
30
+ header={
31
+ <div className="flex h-(--table-header-h) items-center px-(--table-pad-x) pr-28">
32
+ <span className="truncate text-[13px] font-medium text-table-header">
33
+ {label}
34
+ </span>
35
+ </div>
36
+ }
37
+ action={{
38
+ label: copied ? "Copied" : "Copy",
39
+ icon: copied ? (
40
+ <Check className="text-success" weight="bold" />
41
+ ) : (
42
+ <Copy />
43
+ ),
44
+ variant: "ghost",
45
+ onClick: copy,
46
+ }}
47
+ panelClassName="min-w-0"
34
48
  >
35
- <div className="flex items-center justify-between gap-2 border-b border-line px-3 py-2">
36
- <span className="truncate text-xs font-medium text-subtle">{label}</span>
37
- <Button
38
- variant="ghost"
39
- size="sm"
40
- leadingIcon={
41
- copied ? <Check className="text-success" weight="bold" /> : <Copy />
42
- }
43
- onClick={copy}
44
- >
45
- {copied ? "Copied" : "Copy"}
46
- </Button>
47
- </div>
48
49
  <pre className="overflow-x-auto p-4 font-mono text-xs leading-relaxed text-fg">
49
50
  <code>{code}</code>
50
51
  </pre>
51
- </div>
52
+ </TableSurface>
52
53
  );
53
54
  }
@@ -0,0 +1,38 @@
1
+ export interface DialogOriginRect {
2
+ left: number;
3
+ top: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+
8
+ export interface DialogFlight {
9
+ dx: number;
10
+ dy: number;
11
+ sx: number;
12
+ sy: number;
13
+ }
14
+
15
+ function usable(rect: DialogOriginRect): boolean {
16
+ return rect.width > 0 && rect.height > 0;
17
+ }
18
+
19
+ function clampScale(value: number): number {
20
+ return Math.min(1, Math.max(0.1, value));
21
+ }
22
+
23
+ /**
24
+ * Computes the transform that places a centered dialog over its caller.
25
+ * `dx`/`dy` are viewport deltas; `sx`/`sy` scale the dialog down to the caller.
26
+ */
27
+ export function computeDialogFlight(
28
+ origin: DialogOriginRect,
29
+ target: DialogOriginRect,
30
+ ): DialogFlight | null {
31
+ if (!usable(origin) || !usable(target)) return null;
32
+ return {
33
+ dx: origin.left + origin.width / 2 - (target.left + target.width / 2),
34
+ dy: origin.top + origin.height / 2 - (target.top + target.height / 2),
35
+ sx: clampScale(origin.width / target.width),
36
+ sy: clampScale(origin.height / target.height),
37
+ };
38
+ }