@codecrib/ui 0.0.8 → 0.0.10

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,76 @@
1
+ # @codecrib/ui — Usage
2
+
3
+ This package ships React components styled with Tailwind utilities and provides two consumption options for downstream projects:
4
+
5
+ 1) Prebuilt CSS (no Tailwind runtime required)
6
+ 2) Tailwind preset (for projects that run Tailwind and want to compose/ tree-shake)
7
+
8
+ **Why two options?**
9
+ - Prebuilt CSS is the easiest DX for consumers — import a single CSS file and use components without adding Tailwind to the app.
10
+ - The Tailwind preset lets downstream apps include the UI's design tokens and class utilities directly in their Tailwind build so they can purge unused styles and extend tokens.
11
+
12
+ **1) Prebuilt CSS (recommended for simple consumption)**
13
+
14
+ - What it provides: `dist/styles.css` — generated by the UI package build.
15
+ - How to use:
16
+
17
+ - Build the UI package (or use the published package):
18
+
19
+ ```bash
20
+ # from monorepo root
21
+ pnpm --filter=@codecrib/ui run build
22
+ ```
23
+
24
+ - Import the CSS in your app entry:
25
+
26
+ ```ts
27
+ import "@codecrib/ui/styles.css";
28
+ import React from 'react'
29
+ import { createRoot } from 'react-dom/client'
30
+ import App from './App'
31
+
32
+ createRoot(document.getElementById('root')!).render(<App />)
33
+ ```
34
+
35
+ - Pros: consumers don't need to install or run Tailwind. Quick to get started.
36
+ - Cons: consumers cannot purge UI CSS at their app-level Tailwind build and have less flexibility to override core tokens at build time.
37
+
38
+ **2) Tailwind preset (recommended for advanced consumers)**
39
+
40
+ - What it provides: `preset` export (CJS at `dist/tailwind.preset.cjs`) — a small Tailwind preset containing theme tokens and plugin hooks used by the UI.
41
+ - How to use:
42
+
43
+ - In the consuming project's `tailwind.config.cjs`:
44
+
45
+ ```js
46
+ module.exports = {
47
+ presets: [require('@codecrib/ui/preset')],
48
+ content: ['./src/**/*.{js,ts,jsx,tsx}', /* ... */],
49
+ theme: {
50
+ extend: {
51
+ // app-specific overrides
52
+ }
53
+ },
54
+ plugins: [],
55
+ }
56
+ ```
57
+
58
+ - Then run your normal Tailwind build (consuming app must include Tailwind as a devDependency). This allows the app to purge unused classes from both app and UI usage.
59
+
60
+ - Pros: full control and smaller final CSS via purge. Can override tokens and extend the design system.
61
+ - Cons: consumer must configure and run Tailwind.
62
+
63
+ **Notes & build commands**
64
+
65
+ - The UI package has a `build` script that outputs compiled JS and CSS and copies the preset into `dist`:
66
+
67
+ ```bash
68
+ pnpm --filter=@codecrib/ui run build
69
+ ```
70
+
71
+ - When publishing, CI should build the UI so `dist` contains `styles.css` and `tailwind.preset.cjs` — see `.github/workflows/publish.yml` in the repo.
72
+
73
+ **Which to choose?**
74
+ - Use the prebuilt CSS for demos, quick integrations, or consumer apps that shouldn't run Tailwind. Use the preset if you want full integration with your app's Tailwind pipeline and smaller, purged outputs.
75
+
76
+ If you want, I can add examples for Next.js or Storybook showing both approaches.
package/dist/index.cjs CHANGED
@@ -487,6 +487,9 @@ var Select = ({
487
487
  setInternalValue(Array.isArray(value) ? value : value ? [value] : []);
488
488
  }
489
489
  }, [value]);
490
+ React8.useEffect(() => {
491
+ lastEmittedRef.current = null;
492
+ }, [value, multiselect]);
490
493
  const containerRef = React8.useRef(null);
491
494
  React8.useEffect(() => {
492
495
  const onDoc = (e) => {
@@ -497,6 +500,13 @@ var Select = ({
497
500
  return () => document.removeEventListener("mousedown", onDoc);
498
501
  }, []);
499
502
  const isSelected = (v) => internalValue.includes(v);
503
+ const lastEmittedRef = React8.useRef(null);
504
+ const emitChange = (next) => {
505
+ const payload = multiselect ? JSON.stringify(next) : next[0] || "";
506
+ if (lastEmittedRef.current === payload) return;
507
+ lastEmittedRef.current = payload;
508
+ if (onChange) onChange(multiselect ? next : next[0] || "");
509
+ };
500
510
  const toggleSelect = (v) => {
501
511
  let next;
502
512
  if (multiselect) {
@@ -505,12 +515,12 @@ var Select = ({
505
515
  next = isSelected(v) ? [] : [v];
506
516
  setOpen(false);
507
517
  }
508
- if (onChange) onChange(multiselect ? next : next[0] || "");
518
+ emitChange(next);
509
519
  if (value === void 0) setInternalValue(next);
510
520
  };
511
521
  const removeValue = (v) => {
512
522
  const next = internalValue.filter((x) => x !== v);
513
- if (onChange) onChange(multiselect ? next : next[0] || "");
523
+ emitChange(next);
514
524
  if (value === void 0) setInternalValue(next);
515
525
  };
516
526
  const selectedItemsMap = React8.useMemo(() => {
@@ -618,8 +628,12 @@ var Select = ({
618
628
  if (e.key === "Escape") setOpen(false);
619
629
  },
620
630
  className: cn(
621
- "w-full inline-flex items-center justify-between rounded-lg border bg-white px-4 py-2 text-gray-900 text-left cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500",
622
- multiselect ? "" : "",
631
+ "w-full inline-flex items-center justify-between bg-white px-4 py-2 text-gray-900 text-left cursor-pointer",
632
+ radius.default,
633
+ border.base,
634
+ border.color,
635
+ border.focus,
636
+ border.ring,
623
637
  open ? "ring-1 ring-gray-300" : ""
624
638
  ),
625
639
  children: [
@@ -670,7 +684,7 @@ var Select = ({
670
684
  ]
671
685
  }
672
686
  ) }),
673
- open && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "absolute z-40 mt-2 w-56 bg-white border rounded shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "p-1", children: items.map((groupOrItem, gi) => {
687
+ open && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn("absolute z-40 mt-2 w-56 bg-white shadow-lg", border.base, border.color, radius.default), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "p-1", children: items.map((groupOrItem, gi) => {
674
688
  if ("items" in groupOrItem) {
675
689
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mb-2", children: [
676
690
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between px-2 py-1 text-xs text-gray-500 font-medium", children: [
@@ -695,7 +709,7 @@ var Select = ({
695
709
  next = allSelected ? [] : all[0] ? [all[0]] : [];
696
710
  setOpen(false);
697
711
  }
698
- if (onChange) onChange(multiselect ? next : next[0] || "");
712
+ emitChange(next);
699
713
  if (value === void 0) setInternalValue(next);
700
714
  }
701
715
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/Button/Button.tsx","../src/utils/cn.ts","../src/components/Card/Card.tsx","../src/styles/borders.ts","../src/components/Input/Input.tsx","../src/components/Badge/Badge.tsx","../src/components/Icon/Icon.tsx","../src/components/Countdown/Countdown.tsx","../src/components/Tag/Tag.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["// Components\nexport { Button } from \"./components/Button/Button\";\nexport type { ButtonProps } from \"./components/Button/Button\";\n\nexport { Card } from \"./components/Card/Card\";\nexport type { CardProps } from \"./components/Card/Card\";\n\nexport { Input } from \"./components/Input/Input\";\nexport type { InputProps } from \"./components/Input/Input\";\n\nexport { Badge } from \"./components/Badge/Badge\";\nexport type { BadgeProps } from \"./components/Badge/Badge\";\n\nexport { Icon } from \"./components/Icon/Icon\";\nexport type { IconProps } from \"./components/Icon/Icon\";\n\nexport { Countdown } from \"./components/Countdown/Countdown\";\nexport type { CountdownProps } from \"./components/Countdown/Countdown\";\n\nexport { Tag } from \"./components/Tag/Tag\";\nexport type { TagProps } from \"./components/Tag/Tag\";\n\nexport { Select } from \"./components/Select/Select\";\nexport type { SelectProps, SelectItem, SelectGroup } from \"./components/Select/Select\";\n\n// Utilities\nexport { cn } from \"./utils/cn\";\n// Icons are exported from a dedicated `@codecrib/ui/icons` entrypoint\n","import * as React from \"react\";\nimport type { IconWeight } from '@codecrib/ui/icons';\nimport { cn } from \"../../utils/cn\";\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\n size?: \"sm\" | \"md\" | \"lg\";\n isLoading?: boolean;\n /** Icon element to render inside the button */\n icon?: React.ReactNode;\n /** Position for the icon when `icon` is provided */\n iconPosition?: \"left\" | \"right\";\n}\n\nconst variantStyles = {\n primary:\n \"bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500\",\n secondary:\n \"bg-secondary-600 text-white hover:bg-secondary-700 focus:ring-secondary-500\",\n outline:\n \"border-2 border-primary-600 text-primary-600 hover:bg-primary-50 focus:ring-primary-500\",\n ghost: \"text-gray-700 hover:bg-gray-100 focus:ring-gray-500\",\n};\n\nconst sizeStyles = {\n sm: \"px-3 py-1.5 text-sm\",\n md: \"px-4 py-2 text-base\",\n lg: \"px-6 py-3 text-lg\",\n};\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"md\",\n isLoading = false,\n disabled,\n children,\n icon,\n iconPosition = 'left',\n ...props\n },\n ref\n ) => {\n const iconSizeMap: Record<NonNullable<ButtonProps['size']>, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n } as const;\n\n const iconWeightMap: Record<NonNullable<ButtonProps['size']>, IconWeight> = {\n sm: 'regular',\n md: 'regular',\n lg: 'bold',\n } as const;\n\n const renderIcon = () => {\n if (!icon) return null;\n if (React.isValidElement(icon)) {\n const sizeProp = (icon.props as { size?: number | string })?.size;\n const weightProp = (icon.props as { weight?: IconWeight })?.weight;\n const key = size as NonNullable<ButtonProps['size']>;\n const desired = {\n size: (sizeProp as number | undefined) ?? iconSizeMap[key],\n weight: weightProp ?? iconWeightMap[key],\n };\n try {\n return React.cloneElement(icon as React.ReactElement, desired);\n } catch {\n return icon;\n }\n }\n return icon;\n };\n return (\n <button\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n disabled={disabled || isLoading}\n {...props}\n >\n {isLoading && (\n <svg\n className=\"animate-spin -ml-1 mr-2 h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n )}\n {icon && iconPosition === 'left' && (\n <span className=\"mr-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n <span className=\"inline-flex items-center\">{children}</span>\n {icon && iconPosition === 'right' && (\n <span className=\"ml-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","/**\n * Utility function to merge class names\n */\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: \"default\" | \"bordered\" | \"elevated\";\n}\n\nconst variantStyles = {\n default: \"bg-white\",\n bordered: \"bg-white border border-gray-200\",\n elevated: \"bg-white shadow-lg\",\n};\n\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant = \"bordered\", children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(radius.default, \"p-6\", variantStyles[variant], className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nCard.displayName = \"Card\";\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 pb-4\", className)}\n {...props}\n />\n );\n }\n);\n\nCardHeader.displayName = \"CardHeader\";\n\nexport interface CardTitleProps\n extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"text-xl font-semibold text-gray-900\", className)}\n {...props}\n />\n );\n }\n);\n\nCardTitle.displayName = \"CardTitle\";\n\nexport interface CardContentProps\n extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, ...props }, ref) => {\n return <div ref={ref} className={cn(\"text-gray-600\", className)} {...props} />;\n }\n);\n\nCardContent.displayName = \"CardContent\";\n","export const radius = {\n default: \"rounded-lg\",\n pill: \"rounded-full\",\n};\n\nexport const border = {\n base: \"border\",\n color: \"border-gray-300\",\n focus: \"focus:border-primary-500 focus:ring-primary-500\",\n ring: \"focus:outline-none focus:ring-2 focus:ring-offset-0\",\n};\n\nexport const input = `${border.base} ${border.color}`;\n\nexport default {\n radius,\n border,\n input,\n};\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {\n label?: string;\n error?: string;\n helperText?: string;\n}\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, label, error, helperText, id, ...props }, ref) => {\n const inputId = id || React.useId();\n\n return (\n <div className=\"w-full\">\n {label && (\n <label\n htmlFor={inputId}\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n {label}\n </label>\n )}\n <input\n id={inputId}\n ref={ref}\n className={cn(\n \"block w-full px-4 py-2 text-gray-900 placeholder:text-gray-400 transition-colors\",\n radius.default,\n border.base,\n error\n ? \"border-red-500 focus:border-red-500 focus:ring-red-500\"\n : `${border.color} ${border.focus} ${border.ring}`,\n className\n )}\n {...props}\n />\n {error && <p className=\"mt-1 text-sm text-red-600\">{error}</p>}\n {helperText && !error && (\n <p className=\"mt-1 text-sm text-gray-500\">{helperText}</p>\n )}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\";\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n};\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant = \"default\", size = \"md\", ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium rounded-full\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nBadge.displayName = \"Badge\";\n","import * as React from 'react';\nimport type { IconProps as PhosphorIconProps } from 'phosphor-react';\nimport { cn } from '../../utils/cn';\n\nexport interface IconProps extends Omit<PhosphorIconProps, 'weight'> {\n icon: React.ForwardRefExoticComponent<PhosphorIconProps & React.RefAttributes<SVGSVGElement>>;\n weight?: PhosphorIconProps['weight'];\n className?: string;\n color?: string;\n}\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n ({ icon: IconComponent, size = 24, weight = 'regular', className, color, ...props }, ref) => {\n return (\n <IconComponent\n ref={ref}\n size={size}\n weight={weight}\n color={color}\n data-color={color}\n className={cn('inline-block', className)}\n aria-hidden\n {...(props as PhosphorIconProps)}\n />\n );\n }\n);\n\nIcon.displayName = 'Icon';\n\nexport default Icon;\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface CountdownProps extends React.HTMLAttributes<HTMLDivElement> {\n /** deadline as Date | timestamp | ISO string */\n deadline: string | number | Date;\n /** optional callback when countdown reaches zero */\n onComplete?: () => void;\n /** visual variant to match Button */\n variant?: 'primary' | 'secondary' | 'outline' | 'ghost';\n /** size to align with Button sizes */\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction parseDeadline(value: string | number | Date) {\n if (value instanceof Date) return value.getTime();\n const n = Number(value);\n if (!Number.isNaN(n)) return n;\n const d = Date.parse(String(value));\n return Number.isNaN(d) ? NaN : d;\n}\n\nfunction formatRemaining(ms: number) {\n if (ms <= 0) return { expired: true, text: '00:00:00' };\n const total = Math.floor(ms / 1000);\n const days = Math.floor(total / 86400);\n const hours = Math.floor((total % 86400) / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const seconds = total % 60;\n\n const pad = (n: number) => String(n).padStart(2, '0');\n const h = pad(hours + days * 24);\n const m = pad(minutes);\n const s = pad(seconds);\n const text = days > 0 ? `${days}d ${h}:${m}:${s}` : `${h}:${m}:${s}`;\n return { expired: false, text };\n}\n\nexport const Countdown = React.forwardRef<HTMLDivElement, CountdownProps>(\n ({ deadline, onComplete, className, variant = 'primary', size = 'md', ...props }, ref) => {\n const target = React.useMemo(() => parseDeadline(deadline), [deadline]);\n const variantStyles: Record<string, string> = {\n primary: 'bg-primary-600 text-white',\n secondary: 'bg-secondary-600 text-white',\n outline: 'border-2 border-primary-600 text-primary-600 bg-transparent',\n ghost: 'text-gray-700 bg-transparent',\n };\n\n const sizeTextStyles: Record<NonNullable<CountdownProps['size']>, string> = {\n sm: 'text-sm px-2 py-0.5 rounded',\n md: 'text-base px-3 py-1 rounded',\n lg: 'text-lg px-4 py-1.5 rounded',\n };\n const [now, setNow] = React.useState(() => Date.now());\n const [expired, setExpired] = React.useState(false);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return undefined;\n setNow(Date.now());\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [target]);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return;\n if (now >= target && !expired) {\n setExpired(true);\n onComplete?.();\n }\n }, [now, target, expired, onComplete]);\n\n const remaining = formatRemaining(target - now);\n const appliedVariant = expired ? 'expired' : variant;\n const expiredClass =\n variant === 'ghost'\n ? 'text-red-600 bg-transparent'\n : variant === 'outline'\n ? 'border-2 border-red-600 text-red-600 bg-transparent'\n : 'bg-red-600 text-white';\n const variantClass = expired ? expiredClass : variantStyles[variant];\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex items-center font-mono',\n variantClass,\n sizeTextStyles[size],\n className\n )}\n {...props}\n >\n {Number.isNaN(target) ? 'Invalid date' : remaining.text}\n </div>\n );\n }\n);\n\nCountdown.displayName = 'Countdown';\n\nexport default Countdown;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface TagProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\" | \"lg\";\n removable?: boolean;\n onRemove?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n removeLabel?: string;\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n lg: \"px-3 py-1.5 text-base\",\n};\n\nexport const Tag = React.forwardRef<HTMLSpanElement, TagProps>(\n (\n {\n className,\n variant = \"default\",\n size = \"md\",\n removable = false,\n onRemove,\n removeLabel = \"Remove\",\n children,\n ...props\n },\n ref\n ) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium\",\n radius.pill,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n >\n <span>{children}</span>\n {removable && (\n <button\n type=\"button\"\n aria-label={removeLabel}\n onClick={onRemove}\n className={cn(\n \"ml-2 inline-flex items-center justify-center\",\n radius.pill,\n border.ring,\n size === \"sm\" ? \"h-4 w-4\" : size === \"md\" ? \"h-5 w-5\" : \"h-6 w-6\"\n )}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className={cn(size === \"sm\" ? \"h-3 w-3\" : size === \"md\" ? \"h-4 w-4\" : \"h-5 w-5\")}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </span>\n );\n }\n);\n\nTag.displayName = \"Tag\";\n\nexport default Tag;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Tag } from \"../Tag/Tag\";\nimport { Badge } from \"../Badge/Badge\";\n\nexport type SelectItem = {\n value: string;\n label: React.ReactNode;\n icon?: string; // optional URL to an icon image\n disabled?: boolean;\n};\n\nexport type SelectGroup = {\n label: string;\n items: SelectItem[];\n};\n\nexport type SelectSource = SelectItem | SelectGroup;\n\nexport interface SelectProps {\n items: SelectSource[];\n placeholder?: string;\n multiselect?: boolean;\n multiline?: boolean;\n value?: string | string[];\n onChange?: (value: string | string[]) => void;\n className?: string;\n}\n\nexport const Select: React.FC<SelectProps> = ({\n items,\n placeholder = \"Select...\",\n multiselect = false,\n multiline = false,\n value,\n onChange,\n className,\n}) => {\n const [open, setOpen] = React.useState(false);\n const [internalValue, setInternalValue] = React.useState<string[]>(\n Array.isArray(value) ? value : value ? [value] : []\n );\n\n React.useEffect(() => {\n if (value !== undefined) {\n setInternalValue(Array.isArray(value) ? value : value ? [value] : []);\n }\n }, [value]);\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n\n React.useEffect(() => {\n const onDoc = (e: MouseEvent) => {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDoc);\n return () => document.removeEventListener(\"mousedown\", onDoc);\n }, []);\n\n const isSelected = (v: string) => internalValue.includes(v);\n\n const toggleSelect = (v: string) => {\n let next: string[];\n if (multiselect) {\n next = isSelected(v)\n ? internalValue.filter((x) => x !== v)\n : [...internalValue, v];\n } else {\n next = isSelected(v) ? [] : [v];\n setOpen(false);\n }\n\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n if (value === undefined) setInternalValue(next);\n };\n\n const removeValue = (v: string) => {\n const next = internalValue.filter((x) => x !== v);\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n if (value === undefined) setInternalValue(next);\n };\n\n const selectedItemsMap = React.useMemo(() => {\n const map = new Map<string, SelectItem>();\n const collect = (src: SelectSource[]) => {\n src.forEach((s) => {\n if (\"items\" in s) s.items.forEach((it) => map.set(it.value, it));\n else map.set(s.value, s);\n });\n };\n collect(items);\n return map;\n }, [items]);\n\n const tagsContainerRef = React.useRef<HTMLSpanElement | null>(null);\n const [visibleCount, setVisibleCount] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (multiline) {\n setVisibleCount(null);\n return;\n }\n\n let raf: number | undefined;\n let timeout: number | undefined;\n\n const measure = () => {\n if (raf) cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n const container = tagsContainerRef.current;\n if (!container) {\n setVisibleCount(null);\n return;\n }\n\n const containerWidth = container.clientWidth;\n if (containerWidth === 0) {\n setVisibleCount(null);\n return;\n }\n\n // Get all tag elements (they're always rendered, some may be hidden)\n const tagEls = Array.from(\n container.querySelectorAll('[data-role=\"select-tag\"]')\n ) as HTMLElement[];\n \n if (!tagEls.length) {\n setVisibleCount(null);\n return;\n }\n\n // Get badge element if present\n const badgeEl = container.querySelector('[data-role=\"count-badge\"]') as HTMLElement | null;\n\n // Compute gap from container\n const containerStyle = window.getComputedStyle(container);\n const gap = parseFloat(containerStyle.gap || containerStyle.columnGap || \"0\") || 0;\n\n // Measure each tag's width\n const tagWidths: number[] = tagEls.map((el) => el.offsetWidth);\n\n // First check: do all tags fit without any badge?\n let totalWidthAllTags = 0;\n for (const [i, w] of tagWidths.entries()) {\n totalWidthAllTags += w + (i > 0 ? gap : 0);\n }\n\n if (totalWidthAllTags <= containerWidth) {\n // All tags fit, no badge needed\n setVisibleCount(tagEls.length);\n return;\n }\n\n // Not all tags fit, so we need a badge. Measure or estimate badge width.\n let badgeWidth = badgeEl ? badgeEl.offsetWidth : 40;\n\n // Calculate how many tags fit WITH space reserved for the badge\n let usedWidth = 0;\n let fitCount = 0;\n\n for (const [i, tagWidth] of tagWidths.entries()) {\n const gapBeforeTag = i > 0 ? gap : 0;\n const gapBeforeBadge = gap;\n const effectiveTagWidth = tagWidth ?? 0;\n\n // Space needed: current tag + gap before badge + badge\n const spaceNeeded = usedWidth + gapBeforeTag + effectiveTagWidth + gapBeforeBadge + badgeWidth;\n\n if (spaceNeeded <= containerWidth) {\n usedWidth += gapBeforeTag + effectiveTagWidth;\n fitCount = i + 1;\n } else {\n break;\n }\n }\n\n // Ensure at least 1 tag is shown\n fitCount = Math.max(1, fitCount);\n\n setVisibleCount(fitCount);\n });\n };\n\n measure();\n\n const onResize = () => {\n if (timeout) clearTimeout(timeout);\n timeout = window.setTimeout(measure, 50);\n };\n window.addEventListener(\"resize\", onResize);\n\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== \"undefined\" && tagsContainerRef.current) {\n ro = new ResizeObserver(onResize);\n ro.observe(tagsContainerRef.current);\n }\n\n return () => {\n if (raf) cancelAnimationFrame(raf);\n if (timeout) clearTimeout(timeout);\n window.removeEventListener(\"resize\", onResize);\n ro?.disconnect();\n };\n }, [internalValue, multiline]);\n\n return (\n <div ref={containerRef} className={cn(\"relative inline-block w-full\", className)}>\n <div className=\"flex items-center\">\n <div\n role=\"combobox\"\n tabIndex={0}\n aria-expanded={open}\n onClick={() => setOpen((s) => !s)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setOpen((s) => !s);\n }\n if (e.key === \"Escape\") setOpen(false);\n }}\n className={cn(\n \"w-full inline-flex items-center justify-between rounded-lg border bg-white px-4 py-2 text-gray-900 text-left cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500\",\n multiselect ? \"\" : \"\",\n open ? \"ring-1 ring-gray-300\" : \"\"\n )}\n >\n <div className=\"flex-1\">\n {multiselect && internalValue.length > 0 ? (\n <span\n ref={tagsContainerRef}\n className={cn(\n \"relative flex gap-1 items-center\",\n multiline ? \"flex-wrap\" : \"overflow-hidden whitespace-nowrap\",\n )}\n >\n {/* Always render all tags for measurement; hide overflowed ones via CSS */}\n {internalValue.map((v, index) => {\n const isHidden = !multiline && visibleCount !== null && index >= visibleCount;\n return (\n <span\n key={v}\n data-role=\"select-tag\"\n className={cn(\n \"flex-shrink-0 inline-block\",\n isHidden && \"invisible absolute pointer-events-none\"\n )}\n >\n <Tag\n size=\"sm\"\n removable\n removeLabel={`Remove ${selectedItemsMap.get(v)?.label ?? v}`}\n onRemove={(e) => {\n e.stopPropagation();\n removeValue(v);\n }}\n >\n {selectedItemsMap.get(v)?.label ?? v}\n </Tag>\n </span>\n );\n })}\n {/* Show badge when there are hidden tags */}\n {!multiline && visibleCount !== null && visibleCount < internalValue.length && (\n <span data-role=\"count-badge\" className=\"flex-shrink-0 inline-block\">\n <Badge size=\"sm\" variant=\"info\">+{internalValue.length - visibleCount}</Badge>\n </span>\n )}\n </span>\n ) : internalValue.length > 0 ? (\n <span className=\"text-sm text-gray-900\">\n {selectedItemsMap.get(internalValue[0]!)?.label ?? placeholder}\n </span>\n ) : (\n <span className=\"text-sm text-gray-400\">{placeholder}</span>\n )}\n </div>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" className=\"ml-2 h-4 w-4 text-gray-600\">\n <path d=\"M5.5 7.5L10 12l4.5-4.5\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </svg>\n </div>\n </div>\n\n {open && (\n <div className=\"absolute z-40 mt-2 w-56 bg-white border rounded shadow-lg\">\n <div className=\"p-1\">\n {items.map((groupOrItem, gi) => {\n if (\"items\" in groupOrItem) {\n return (\n <div key={gi} className=\"mb-2\">\n <div className=\"flex items-center justify-between px-2 py-1 text-xs text-gray-500 font-medium\">\n <div>{groupOrItem.label}</div>\n <div>\n {multiselect && (\n <input\n type=\"checkbox\"\n aria-label={`Select all ${groupOrItem.label}`}\n checked={groupOrItem.items.every((it) => isSelected(it.value))}\n onChange={() => {\n // toggle all in group\n const all = groupOrItem.items.map((it) => it.value);\n const allSelected = all.every((v) => isSelected(v));\n let next: string[];\n if (multiselect) {\n if (allSelected) {\n next = internalValue.filter((v) => !all.includes(v));\n } else {\n next = [...internalValue, ...all.filter((v) => !internalValue.includes(v))];\n }\n } else {\n // single select: select first item or clear\n next = allSelected ? [] : (all[0] ? [all[0]] : []);\n setOpen(false);\n }\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n if (value === undefined) setInternalValue(next);\n }}\n />\n )}\n </div>\n </div>\n {groupOrItem.items.map((it) => (\n <button\n key={it.value}\n type=\"button\"\n disabled={it.disabled}\n onClick={() => toggleSelect(it.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(it.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {it.icon && (\n <img src={it.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{it.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(it.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n ))}\n </div>\n );\n }\n\n return (\n <button\n key={groupOrItem.value}\n type=\"button\"\n disabled={groupOrItem.disabled}\n onClick={() => toggleSelect(groupOrItem.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(groupOrItem.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {groupOrItem.icon && (\n <img src={groupOrItem.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{groupOrItem.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(groupOrItem.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default Select;\n"],"mappings":"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","names":["React","import_jsx_runtime","variantStyles","React","import_jsx_runtime","React","import_jsx_runtime","variantStyles","sizeStyles","React","import_jsx_runtime","React","import_jsx_runtime","variantStyles","React","import_jsx_runtime","variantStyles","sizeStyles","React","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/Button/Button.tsx","../src/utils/cn.ts","../src/components/Card/Card.tsx","../src/styles/borders.ts","../src/components/Input/Input.tsx","../src/components/Badge/Badge.tsx","../src/components/Icon/Icon.tsx","../src/components/Countdown/Countdown.tsx","../src/components/Tag/Tag.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["// Components\nexport { Button } from \"./components/Button/Button\";\nexport type { ButtonProps } from \"./components/Button/Button\";\n\nexport { Card } from \"./components/Card/Card\";\nexport type { CardProps } from \"./components/Card/Card\";\n\nexport { Input } from \"./components/Input/Input\";\nexport type { InputProps } from \"./components/Input/Input\";\n\nexport { Badge } from \"./components/Badge/Badge\";\nexport type { BadgeProps } from \"./components/Badge/Badge\";\n\nexport { Icon } from \"./components/Icon/Icon\";\nexport type { IconProps } from \"./components/Icon/Icon\";\n\nexport { Countdown } from \"./components/Countdown/Countdown\";\nexport type { CountdownProps } from \"./components/Countdown/Countdown\";\n\nexport { Tag } from \"./components/Tag/Tag\";\nexport type { TagProps } from \"./components/Tag/Tag\";\n\nexport { Select } from \"./components/Select/Select\";\nexport type { SelectProps, SelectItem, SelectGroup } from \"./components/Select/Select\";\n\n// Utilities\nexport { cn } from \"./utils/cn\";\n// Icons are exported from a dedicated `@codecrib/ui/icons` entrypoint\n\n// Demo app moved to its own package: @codecrib/demo\n","import * as React from \"react\";\nimport type { IconWeight } from '@codecrib/ui/icons';\nimport { cn } from \"../../utils/cn\";\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\n size?: \"sm\" | \"md\" | \"lg\";\n isLoading?: boolean;\n /** Icon element to render inside the button */\n icon?: React.ReactNode;\n /** Position for the icon when `icon` is provided */\n iconPosition?: \"left\" | \"right\";\n}\n\nconst variantStyles = {\n primary:\n \"bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500\",\n secondary:\n \"bg-secondary-600 text-white hover:bg-secondary-700 focus:ring-secondary-500\",\n outline:\n \"border-2 border-primary-600 text-primary-600 hover:bg-primary-50 focus:ring-primary-500\",\n ghost: \"text-gray-700 hover:bg-gray-100 focus:ring-gray-500\",\n};\n\nconst sizeStyles = {\n sm: \"px-3 py-1.5 text-sm\",\n md: \"px-4 py-2 text-base\",\n lg: \"px-6 py-3 text-lg\",\n};\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"md\",\n isLoading = false,\n disabled,\n children,\n icon,\n iconPosition = 'left',\n ...props\n },\n ref\n ) => {\n const iconSizeMap: Record<NonNullable<ButtonProps['size']>, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n } as const;\n\n const iconWeightMap: Record<NonNullable<ButtonProps['size']>, IconWeight> = {\n sm: 'regular',\n md: 'regular',\n lg: 'bold',\n } as const;\n\n const renderIcon = () => {\n if (!icon) return null;\n if (React.isValidElement(icon)) {\n const sizeProp = (icon.props as { size?: number | string })?.size;\n const weightProp = (icon.props as { weight?: IconWeight })?.weight;\n const key = size as NonNullable<ButtonProps['size']>;\n const desired = {\n size: (sizeProp as number | undefined) ?? iconSizeMap[key],\n weight: weightProp ?? iconWeightMap[key],\n };\n try {\n return React.cloneElement(icon as React.ReactElement, desired);\n } catch {\n return icon;\n }\n }\n return icon;\n };\n return (\n <button\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n disabled={disabled || isLoading}\n {...props}\n >\n {isLoading && (\n <svg\n className=\"animate-spin -ml-1 mr-2 h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n )}\n {icon && iconPosition === 'left' && (\n <span className=\"mr-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n <span className=\"inline-flex items-center\">{children}</span>\n {icon && iconPosition === 'right' && (\n <span className=\"ml-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","/**\n * Utility function to merge class names\n */\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: \"default\" | \"bordered\" | \"elevated\";\n}\n\nconst variantStyles = {\n default: \"bg-white\",\n bordered: \"bg-white border border-gray-200\",\n elevated: \"bg-white shadow-lg\",\n};\n\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant = \"bordered\", children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(radius.default, \"p-6\", variantStyles[variant], className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nCard.displayName = \"Card\";\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 pb-4\", className)}\n {...props}\n />\n );\n }\n);\n\nCardHeader.displayName = \"CardHeader\";\n\nexport interface CardTitleProps\n extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"text-xl font-semibold text-gray-900\", className)}\n {...props}\n />\n );\n }\n);\n\nCardTitle.displayName = \"CardTitle\";\n\nexport interface CardContentProps\n extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, ...props }, ref) => {\n return <div ref={ref} className={cn(\"text-gray-600\", className)} {...props} />;\n }\n);\n\nCardContent.displayName = \"CardContent\";\n","export const radius = {\n default: \"rounded-lg\",\n pill: \"rounded-full\",\n};\n\nexport const border = {\n base: \"border\",\n color: \"border-gray-300\",\n focus: \"focus:border-primary-500 focus:ring-primary-500\",\n ring: \"focus:outline-none focus:ring-2 focus:ring-offset-0\",\n};\n\nexport const input = `${border.base} ${border.color}`;\n\nexport default {\n radius,\n border,\n input,\n};\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {\n label?: string;\n error?: string;\n helperText?: string;\n}\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, label, error, helperText, id, ...props }, ref) => {\n const inputId = id || React.useId();\n\n return (\n <div className=\"w-full\">\n {label && (\n <label\n htmlFor={inputId}\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n {label}\n </label>\n )}\n <input\n id={inputId}\n ref={ref}\n className={cn(\n \"block w-full px-4 py-2 text-gray-900 placeholder:text-gray-400 transition-colors\",\n radius.default,\n border.base,\n error\n ? \"border-red-500 focus:border-red-500 focus:ring-red-500\"\n : `${border.color} ${border.focus} ${border.ring}`,\n className\n )}\n {...props}\n />\n {error && <p className=\"mt-1 text-sm text-red-600\">{error}</p>}\n {helperText && !error && (\n <p className=\"mt-1 text-sm text-gray-500\">{helperText}</p>\n )}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\";\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n};\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant = \"default\", size = \"md\", ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium rounded-full\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nBadge.displayName = \"Badge\";\n","import * as React from 'react';\nimport type { IconProps as PhosphorIconProps } from 'phosphor-react';\nimport { cn } from '../../utils/cn';\n\nexport interface IconProps extends Omit<PhosphorIconProps, 'weight'> {\n icon: React.ForwardRefExoticComponent<PhosphorIconProps & React.RefAttributes<SVGSVGElement>>;\n weight?: PhosphorIconProps['weight'];\n className?: string;\n color?: string;\n}\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n ({ icon: IconComponent, size = 24, weight = 'regular', className, color, ...props }, ref) => {\n return (\n <IconComponent\n ref={ref}\n size={size}\n weight={weight}\n color={color}\n data-color={color}\n className={cn('inline-block', className)}\n aria-hidden\n {...(props as PhosphorIconProps)}\n />\n );\n }\n);\n\nIcon.displayName = 'Icon';\n\nexport default Icon;\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface CountdownProps extends React.HTMLAttributes<HTMLDivElement> {\n /** deadline as Date | timestamp | ISO string */\n deadline: string | number | Date;\n /** optional callback when countdown reaches zero */\n onComplete?: () => void;\n /** visual variant to match Button */\n variant?: 'primary' | 'secondary' | 'outline' | 'ghost';\n /** size to align with Button sizes */\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction parseDeadline(value: string | number | Date) {\n if (value instanceof Date) return value.getTime();\n const n = Number(value);\n if (!Number.isNaN(n)) return n;\n const d = Date.parse(String(value));\n return Number.isNaN(d) ? NaN : d;\n}\n\nfunction formatRemaining(ms: number) {\n if (ms <= 0) return { expired: true, text: '00:00:00' };\n const total = Math.floor(ms / 1000);\n const days = Math.floor(total / 86400);\n const hours = Math.floor((total % 86400) / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const seconds = total % 60;\n\n const pad = (n: number) => String(n).padStart(2, '0');\n const h = pad(hours + days * 24);\n const m = pad(minutes);\n const s = pad(seconds);\n const text = days > 0 ? `${days}d ${h}:${m}:${s}` : `${h}:${m}:${s}`;\n return { expired: false, text };\n}\n\nexport const Countdown = React.forwardRef<HTMLDivElement, CountdownProps>(\n ({ deadline, onComplete, className, variant = 'primary', size = 'md', ...props }, ref) => {\n const target = React.useMemo(() => parseDeadline(deadline), [deadline]);\n const variantStyles: Record<string, string> = {\n primary: 'bg-primary-600 text-white',\n secondary: 'bg-secondary-600 text-white',\n outline: 'border-2 border-primary-600 text-primary-600 bg-transparent',\n ghost: 'text-gray-700 bg-transparent',\n };\n\n const sizeTextStyles: Record<NonNullable<CountdownProps['size']>, string> = {\n sm: 'text-sm px-2 py-0.5 rounded',\n md: 'text-base px-3 py-1 rounded',\n lg: 'text-lg px-4 py-1.5 rounded',\n };\n const [now, setNow] = React.useState(() => Date.now());\n const [expired, setExpired] = React.useState(false);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return undefined;\n setNow(Date.now());\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [target]);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return;\n if (now >= target && !expired) {\n setExpired(true);\n onComplete?.();\n }\n }, [now, target, expired, onComplete]);\n\n const remaining = formatRemaining(target - now);\n const appliedVariant = expired ? 'expired' : variant;\n const expiredClass =\n variant === 'ghost'\n ? 'text-red-600 bg-transparent'\n : variant === 'outline'\n ? 'border-2 border-red-600 text-red-600 bg-transparent'\n : 'bg-red-600 text-white';\n const variantClass = expired ? expiredClass : variantStyles[variant];\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex items-center font-mono',\n variantClass,\n sizeTextStyles[size],\n className\n )}\n {...props}\n >\n {Number.isNaN(target) ? 'Invalid date' : remaining.text}\n </div>\n );\n }\n);\n\nCountdown.displayName = 'Countdown';\n\nexport default Countdown;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface TagProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\" | \"lg\";\n removable?: boolean;\n onRemove?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n removeLabel?: string;\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n lg: \"px-3 py-1.5 text-base\",\n};\n\nexport const Tag = React.forwardRef<HTMLSpanElement, TagProps>(\n (\n {\n className,\n variant = \"default\",\n size = \"md\",\n removable = false,\n onRemove,\n removeLabel = \"Remove\",\n children,\n ...props\n },\n ref\n ) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium\",\n radius.pill,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n >\n <span>{children}</span>\n {removable && (\n <button\n type=\"button\"\n aria-label={removeLabel}\n onClick={onRemove}\n className={cn(\n \"ml-2 inline-flex items-center justify-center\",\n radius.pill,\n border.ring,\n size === \"sm\" ? \"h-4 w-4\" : size === \"md\" ? \"h-5 w-5\" : \"h-6 w-6\"\n )}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className={cn(size === \"sm\" ? \"h-3 w-3\" : size === \"md\" ? \"h-4 w-4\" : \"h-5 w-5\")}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </span>\n );\n }\n);\n\nTag.displayName = \"Tag\";\n\nexport default Tag;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\nimport { Tag } from \"../Tag/Tag\";\nimport { Badge } from \"../Badge/Badge\";\n\nexport type SelectItem = {\n value: string;\n label: React.ReactNode;\n icon?: string; // optional URL to an icon image\n disabled?: boolean;\n};\n\nexport type SelectGroup = {\n label: string;\n items: SelectItem[];\n};\n\nexport type SelectSource = SelectItem | SelectGroup;\n\nexport interface SelectProps {\n items: SelectSource[];\n placeholder?: string;\n multiselect?: boolean;\n multiline?: boolean;\n value?: string | string[];\n onChange?: (value: string | string[]) => void;\n className?: string;\n}\n\nexport const Select: React.FC<SelectProps> = ({\n items,\n placeholder = \"Select...\",\n multiselect = false,\n multiline = false,\n value,\n onChange,\n className,\n}) => {\n const [open, setOpen] = React.useState(false);\n const [internalValue, setInternalValue] = React.useState<string[]>(\n Array.isArray(value) ? value : value ? [value] : []\n );\n\n React.useEffect(() => {\n if (value !== undefined) {\n setInternalValue(Array.isArray(value) ? value : value ? [value] : []);\n }\n }, [value]);\n\n React.useEffect(() => {\n // Reset last emitted value when controlled `value` changes externally\n lastEmittedRef.current = null;\n }, [value, multiselect]);\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n\n React.useEffect(() => {\n const onDoc = (e: MouseEvent) => {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDoc);\n return () => document.removeEventListener(\"mousedown\", onDoc);\n }, []);\n\n const isSelected = (v: string) => internalValue.includes(v);\n const lastEmittedRef = React.useRef<string | null>(null);\n\n const emitChange = (next: string[]) => {\n const payload = multiselect ? JSON.stringify(next) : next[0] || \"\";\n if (lastEmittedRef.current === payload) return;\n lastEmittedRef.current = payload;\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n };\n\n const toggleSelect = (v: string) => {\n let next: string[];\n if (multiselect) {\n next = isSelected(v)\n ? internalValue.filter((x) => x !== v)\n : [...internalValue, v];\n } else {\n next = isSelected(v) ? [] : [v];\n setOpen(false);\n }\n\n emitChange(next);\n if (value === undefined) setInternalValue(next);\n };\n\n const removeValue = (v: string) => {\n const next = internalValue.filter((x) => x !== v);\n emitChange(next);\n if (value === undefined) setInternalValue(next);\n };\n\n const selectedItemsMap = React.useMemo(() => {\n const map = new Map<string, SelectItem>();\n const collect = (src: SelectSource[]) => {\n src.forEach((s) => {\n if (\"items\" in s) s.items.forEach((it) => map.set(it.value, it));\n else map.set(s.value, s);\n });\n };\n collect(items);\n return map;\n }, [items]);\n\n const tagsContainerRef = React.useRef<HTMLSpanElement | null>(null);\n const [visibleCount, setVisibleCount] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (multiline) {\n setVisibleCount(null);\n return;\n }\n\n let raf: number | undefined;\n let timeout: number | undefined;\n\n const measure = () => {\n if (raf) cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n const container = tagsContainerRef.current;\n if (!container) {\n setVisibleCount(null);\n return;\n }\n\n const containerWidth = container.clientWidth;\n if (containerWidth === 0) {\n setVisibleCount(null);\n return;\n }\n\n // Get all tag elements (they're always rendered, some may be hidden)\n const tagEls = Array.from(\n container.querySelectorAll('[data-role=\"select-tag\"]')\n ) as HTMLElement[];\n \n if (!tagEls.length) {\n setVisibleCount(null);\n return;\n }\n\n // Get badge element if present\n const badgeEl = container.querySelector('[data-role=\"count-badge\"]') as HTMLElement | null;\n\n // Compute gap from container\n const containerStyle = window.getComputedStyle(container);\n const gap = parseFloat(containerStyle.gap || containerStyle.columnGap || \"0\") || 0;\n\n // Measure each tag's width\n const tagWidths: number[] = tagEls.map((el) => el.offsetWidth);\n\n // First check: do all tags fit without any badge?\n let totalWidthAllTags = 0;\n for (const [i, w] of tagWidths.entries()) {\n totalWidthAllTags += w + (i > 0 ? gap : 0);\n }\n\n if (totalWidthAllTags <= containerWidth) {\n // All tags fit, no badge needed\n setVisibleCount(tagEls.length);\n return;\n }\n\n // Not all tags fit, so we need a badge. Measure or estimate badge width.\n let badgeWidth = badgeEl ? badgeEl.offsetWidth : 40;\n\n // Calculate how many tags fit WITH space reserved for the badge\n let usedWidth = 0;\n let fitCount = 0;\n\n for (const [i, tagWidth] of tagWidths.entries()) {\n const gapBeforeTag = i > 0 ? gap : 0;\n const gapBeforeBadge = gap;\n const effectiveTagWidth = tagWidth ?? 0;\n\n // Space needed: current tag + gap before badge + badge\n const spaceNeeded = usedWidth + gapBeforeTag + effectiveTagWidth + gapBeforeBadge + badgeWidth;\n\n if (spaceNeeded <= containerWidth) {\n usedWidth += gapBeforeTag + effectiveTagWidth;\n fitCount = i + 1;\n } else {\n break;\n }\n }\n\n // Ensure at least 1 tag is shown\n fitCount = Math.max(1, fitCount);\n\n setVisibleCount(fitCount);\n });\n };\n\n measure();\n\n const onResize = () => {\n if (timeout) clearTimeout(timeout);\n timeout = window.setTimeout(measure, 50);\n };\n window.addEventListener(\"resize\", onResize);\n\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== \"undefined\" && tagsContainerRef.current) {\n ro = new ResizeObserver(onResize);\n ro.observe(tagsContainerRef.current);\n }\n\n return () => {\n if (raf) cancelAnimationFrame(raf);\n if (timeout) clearTimeout(timeout);\n window.removeEventListener(\"resize\", onResize);\n ro?.disconnect();\n };\n }, [internalValue, multiline]);\n\n return (\n <div ref={containerRef} className={cn(\"relative inline-block w-full\", className)}>\n <div className=\"flex items-center\">\n <div\n role=\"combobox\"\n tabIndex={0}\n aria-expanded={open}\n onClick={() => setOpen((s) => !s)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setOpen((s) => !s);\n }\n if (e.key === \"Escape\") setOpen(false);\n }}\n className={cn(\n \"w-full inline-flex items-center justify-between bg-white px-4 py-2 text-gray-900 text-left cursor-pointer\",\n radius.default,\n border.base,\n border.color,\n border.focus,\n border.ring,\n open ? \"ring-1 ring-gray-300\" : \"\"\n )}\n >\n <div className=\"flex-1\">\n {multiselect && internalValue.length > 0 ? (\n <span\n ref={tagsContainerRef}\n className={cn(\n \"relative flex gap-1 items-center\",\n multiline ? \"flex-wrap\" : \"overflow-hidden whitespace-nowrap\",\n )}\n >\n {/* Always render all tags for measurement; hide overflowed ones via CSS */}\n {internalValue.map((v, index) => {\n const isHidden = !multiline && visibleCount !== null && index >= visibleCount;\n return (\n <span\n key={v}\n data-role=\"select-tag\"\n className={cn(\n \"flex-shrink-0 inline-block\",\n isHidden && \"invisible absolute pointer-events-none\"\n )}\n >\n <Tag\n size=\"sm\"\n removable\n removeLabel={`Remove ${selectedItemsMap.get(v)?.label ?? v}`}\n onRemove={(e) => {\n e.stopPropagation();\n removeValue(v);\n }}\n >\n {selectedItemsMap.get(v)?.label ?? v}\n </Tag>\n </span>\n );\n })}\n {/* Show badge when there are hidden tags */}\n {!multiline && visibleCount !== null && visibleCount < internalValue.length && (\n <span data-role=\"count-badge\" className=\"flex-shrink-0 inline-block\">\n <Badge size=\"sm\" variant=\"info\">+{internalValue.length - visibleCount}</Badge>\n </span>\n )}\n </span>\n ) : internalValue.length > 0 ? (\n <span className=\"text-sm text-gray-900\">\n {selectedItemsMap.get(internalValue[0]!)?.label ?? placeholder}\n </span>\n ) : (\n <span className=\"text-sm text-gray-400\">{placeholder}</span>\n )}\n </div>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" className=\"ml-2 h-4 w-4 text-gray-600\">\n <path d=\"M5.5 7.5L10 12l4.5-4.5\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </svg>\n </div>\n </div>\n\n {open && (\n <div className={cn(\"absolute z-40 mt-2 w-56 bg-white shadow-lg\", border.base, border.color, radius.default)}>\n <div className=\"p-1\">\n {items.map((groupOrItem, gi) => {\n if (\"items\" in groupOrItem) {\n return (\n <div key={gi} className=\"mb-2\">\n <div className=\"flex items-center justify-between px-2 py-1 text-xs text-gray-500 font-medium\">\n <div>{groupOrItem.label}</div>\n <div>\n {multiselect && (\n <input\n type=\"checkbox\"\n aria-label={`Select all ${groupOrItem.label}`}\n checked={groupOrItem.items.every((it) => isSelected(it.value))}\n onChange={() => {\n // toggle all in group\n const all = groupOrItem.items.map((it) => it.value);\n const allSelected = all.every((v) => isSelected(v));\n let next: string[];\n if (multiselect) {\n if (allSelected) {\n next = internalValue.filter((v) => !all.includes(v));\n } else {\n next = [...internalValue, ...all.filter((v) => !internalValue.includes(v))];\n }\n } else {\n // single select: select first item or clear\n next = allSelected ? [] : (all[0] ? [all[0]] : []);\n setOpen(false);\n }\n emitChange(next);\n if (value === undefined) setInternalValue(next);\n }}\n />\n )}\n </div>\n </div>\n {groupOrItem.items.map((it) => (\n <button\n key={it.value}\n type=\"button\"\n disabled={it.disabled}\n onClick={() => toggleSelect(it.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(it.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {it.icon && (\n <img src={it.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{it.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(it.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n ))}\n </div>\n );\n }\n\n return (\n <button\n key={groupOrItem.value}\n type=\"button\"\n disabled={groupOrItem.disabled}\n onClick={() => toggleSelect(groupOrItem.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(groupOrItem.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {groupOrItem.icon && (\n <img src={groupOrItem.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{groupOrItem.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(groupOrItem.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default Select;\n"],"mappings":"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","names":["React","import_jsx_runtime","variantStyles","React","import_jsx_runtime","React","import_jsx_runtime","variantStyles","sizeStyles","React","import_jsx_runtime","React","import_jsx_runtime","variantStyles","React","import_jsx_runtime","variantStyles","sizeStyles","React","import_jsx_runtime"]}
package/dist/index.js CHANGED
@@ -443,6 +443,9 @@ var Select = ({
443
443
  setInternalValue(Array.isArray(value) ? value : value ? [value] : []);
444
444
  }
445
445
  }, [value]);
446
+ React8.useEffect(() => {
447
+ lastEmittedRef.current = null;
448
+ }, [value, multiselect]);
446
449
  const containerRef = React8.useRef(null);
447
450
  React8.useEffect(() => {
448
451
  const onDoc = (e) => {
@@ -453,6 +456,13 @@ var Select = ({
453
456
  return () => document.removeEventListener("mousedown", onDoc);
454
457
  }, []);
455
458
  const isSelected = (v) => internalValue.includes(v);
459
+ const lastEmittedRef = React8.useRef(null);
460
+ const emitChange = (next) => {
461
+ const payload = multiselect ? JSON.stringify(next) : next[0] || "";
462
+ if (lastEmittedRef.current === payload) return;
463
+ lastEmittedRef.current = payload;
464
+ if (onChange) onChange(multiselect ? next : next[0] || "");
465
+ };
456
466
  const toggleSelect = (v) => {
457
467
  let next;
458
468
  if (multiselect) {
@@ -461,12 +471,12 @@ var Select = ({
461
471
  next = isSelected(v) ? [] : [v];
462
472
  setOpen(false);
463
473
  }
464
- if (onChange) onChange(multiselect ? next : next[0] || "");
474
+ emitChange(next);
465
475
  if (value === void 0) setInternalValue(next);
466
476
  };
467
477
  const removeValue = (v) => {
468
478
  const next = internalValue.filter((x) => x !== v);
469
- if (onChange) onChange(multiselect ? next : next[0] || "");
479
+ emitChange(next);
470
480
  if (value === void 0) setInternalValue(next);
471
481
  };
472
482
  const selectedItemsMap = React8.useMemo(() => {
@@ -574,8 +584,12 @@ var Select = ({
574
584
  if (e.key === "Escape") setOpen(false);
575
585
  },
576
586
  className: cn(
577
- "w-full inline-flex items-center justify-between rounded-lg border bg-white px-4 py-2 text-gray-900 text-left cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500",
578
- multiselect ? "" : "",
587
+ "w-full inline-flex items-center justify-between bg-white px-4 py-2 text-gray-900 text-left cursor-pointer",
588
+ radius.default,
589
+ border.base,
590
+ border.color,
591
+ border.focus,
592
+ border.ring,
579
593
  open ? "ring-1 ring-gray-300" : ""
580
594
  ),
581
595
  children: [
@@ -626,7 +640,7 @@ var Select = ({
626
640
  ]
627
641
  }
628
642
  ) }),
629
- open && /* @__PURE__ */ jsx8("div", { className: "absolute z-40 mt-2 w-56 bg-white border rounded shadow-lg", children: /* @__PURE__ */ jsx8("div", { className: "p-1", children: items.map((groupOrItem, gi) => {
643
+ open && /* @__PURE__ */ jsx8("div", { className: cn("absolute z-40 mt-2 w-56 bg-white shadow-lg", border.base, border.color, radius.default), children: /* @__PURE__ */ jsx8("div", { className: "p-1", children: items.map((groupOrItem, gi) => {
630
644
  if ("items" in groupOrItem) {
631
645
  return /* @__PURE__ */ jsxs4("div", { className: "mb-2", children: [
632
646
  /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between px-2 py-1 text-xs text-gray-500 font-medium", children: [
@@ -651,7 +665,7 @@ var Select = ({
651
665
  next = allSelected ? [] : all[0] ? [all[0]] : [];
652
666
  setOpen(false);
653
667
  }
654
- if (onChange) onChange(multiselect ? next : next[0] || "");
668
+ emitChange(next);
655
669
  if (value === void 0) setInternalValue(next);
656
670
  }
657
671
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Button/Button.tsx","../src/utils/cn.ts","../src/components/Card/Card.tsx","../src/styles/borders.ts","../src/components/Input/Input.tsx","../src/components/Badge/Badge.tsx","../src/components/Icon/Icon.tsx","../src/components/Countdown/Countdown.tsx","../src/components/Tag/Tag.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { IconWeight } from '@codecrib/ui/icons';\nimport { cn } from \"../../utils/cn\";\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\n size?: \"sm\" | \"md\" | \"lg\";\n isLoading?: boolean;\n /** Icon element to render inside the button */\n icon?: React.ReactNode;\n /** Position for the icon when `icon` is provided */\n iconPosition?: \"left\" | \"right\";\n}\n\nconst variantStyles = {\n primary:\n \"bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500\",\n secondary:\n \"bg-secondary-600 text-white hover:bg-secondary-700 focus:ring-secondary-500\",\n outline:\n \"border-2 border-primary-600 text-primary-600 hover:bg-primary-50 focus:ring-primary-500\",\n ghost: \"text-gray-700 hover:bg-gray-100 focus:ring-gray-500\",\n};\n\nconst sizeStyles = {\n sm: \"px-3 py-1.5 text-sm\",\n md: \"px-4 py-2 text-base\",\n lg: \"px-6 py-3 text-lg\",\n};\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"md\",\n isLoading = false,\n disabled,\n children,\n icon,\n iconPosition = 'left',\n ...props\n },\n ref\n ) => {\n const iconSizeMap: Record<NonNullable<ButtonProps['size']>, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n } as const;\n\n const iconWeightMap: Record<NonNullable<ButtonProps['size']>, IconWeight> = {\n sm: 'regular',\n md: 'regular',\n lg: 'bold',\n } as const;\n\n const renderIcon = () => {\n if (!icon) return null;\n if (React.isValidElement(icon)) {\n const sizeProp = (icon.props as { size?: number | string })?.size;\n const weightProp = (icon.props as { weight?: IconWeight })?.weight;\n const key = size as NonNullable<ButtonProps['size']>;\n const desired = {\n size: (sizeProp as number | undefined) ?? iconSizeMap[key],\n weight: weightProp ?? iconWeightMap[key],\n };\n try {\n return React.cloneElement(icon as React.ReactElement, desired);\n } catch {\n return icon;\n }\n }\n return icon;\n };\n return (\n <button\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n disabled={disabled || isLoading}\n {...props}\n >\n {isLoading && (\n <svg\n className=\"animate-spin -ml-1 mr-2 h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n )}\n {icon && iconPosition === 'left' && (\n <span className=\"mr-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n <span className=\"inline-flex items-center\">{children}</span>\n {icon && iconPosition === 'right' && (\n <span className=\"ml-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","/**\n * Utility function to merge class names\n */\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: \"default\" | \"bordered\" | \"elevated\";\n}\n\nconst variantStyles = {\n default: \"bg-white\",\n bordered: \"bg-white border border-gray-200\",\n elevated: \"bg-white shadow-lg\",\n};\n\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant = \"bordered\", children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(radius.default, \"p-6\", variantStyles[variant], className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nCard.displayName = \"Card\";\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 pb-4\", className)}\n {...props}\n />\n );\n }\n);\n\nCardHeader.displayName = \"CardHeader\";\n\nexport interface CardTitleProps\n extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"text-xl font-semibold text-gray-900\", className)}\n {...props}\n />\n );\n }\n);\n\nCardTitle.displayName = \"CardTitle\";\n\nexport interface CardContentProps\n extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, ...props }, ref) => {\n return <div ref={ref} className={cn(\"text-gray-600\", className)} {...props} />;\n }\n);\n\nCardContent.displayName = \"CardContent\";\n","export const radius = {\n default: \"rounded-lg\",\n pill: \"rounded-full\",\n};\n\nexport const border = {\n base: \"border\",\n color: \"border-gray-300\",\n focus: \"focus:border-primary-500 focus:ring-primary-500\",\n ring: \"focus:outline-none focus:ring-2 focus:ring-offset-0\",\n};\n\nexport const input = `${border.base} ${border.color}`;\n\nexport default {\n radius,\n border,\n input,\n};\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {\n label?: string;\n error?: string;\n helperText?: string;\n}\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, label, error, helperText, id, ...props }, ref) => {\n const inputId = id || React.useId();\n\n return (\n <div className=\"w-full\">\n {label && (\n <label\n htmlFor={inputId}\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n {label}\n </label>\n )}\n <input\n id={inputId}\n ref={ref}\n className={cn(\n \"block w-full px-4 py-2 text-gray-900 placeholder:text-gray-400 transition-colors\",\n radius.default,\n border.base,\n error\n ? \"border-red-500 focus:border-red-500 focus:ring-red-500\"\n : `${border.color} ${border.focus} ${border.ring}`,\n className\n )}\n {...props}\n />\n {error && <p className=\"mt-1 text-sm text-red-600\">{error}</p>}\n {helperText && !error && (\n <p className=\"mt-1 text-sm text-gray-500\">{helperText}</p>\n )}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\";\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n};\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant = \"default\", size = \"md\", ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium rounded-full\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nBadge.displayName = \"Badge\";\n","import * as React from 'react';\nimport type { IconProps as PhosphorIconProps } from 'phosphor-react';\nimport { cn } from '../../utils/cn';\n\nexport interface IconProps extends Omit<PhosphorIconProps, 'weight'> {\n icon: React.ForwardRefExoticComponent<PhosphorIconProps & React.RefAttributes<SVGSVGElement>>;\n weight?: PhosphorIconProps['weight'];\n className?: string;\n color?: string;\n}\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n ({ icon: IconComponent, size = 24, weight = 'regular', className, color, ...props }, ref) => {\n return (\n <IconComponent\n ref={ref}\n size={size}\n weight={weight}\n color={color}\n data-color={color}\n className={cn('inline-block', className)}\n aria-hidden\n {...(props as PhosphorIconProps)}\n />\n );\n }\n);\n\nIcon.displayName = 'Icon';\n\nexport default Icon;\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface CountdownProps extends React.HTMLAttributes<HTMLDivElement> {\n /** deadline as Date | timestamp | ISO string */\n deadline: string | number | Date;\n /** optional callback when countdown reaches zero */\n onComplete?: () => void;\n /** visual variant to match Button */\n variant?: 'primary' | 'secondary' | 'outline' | 'ghost';\n /** size to align with Button sizes */\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction parseDeadline(value: string | number | Date) {\n if (value instanceof Date) return value.getTime();\n const n = Number(value);\n if (!Number.isNaN(n)) return n;\n const d = Date.parse(String(value));\n return Number.isNaN(d) ? NaN : d;\n}\n\nfunction formatRemaining(ms: number) {\n if (ms <= 0) return { expired: true, text: '00:00:00' };\n const total = Math.floor(ms / 1000);\n const days = Math.floor(total / 86400);\n const hours = Math.floor((total % 86400) / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const seconds = total % 60;\n\n const pad = (n: number) => String(n).padStart(2, '0');\n const h = pad(hours + days * 24);\n const m = pad(minutes);\n const s = pad(seconds);\n const text = days > 0 ? `${days}d ${h}:${m}:${s}` : `${h}:${m}:${s}`;\n return { expired: false, text };\n}\n\nexport const Countdown = React.forwardRef<HTMLDivElement, CountdownProps>(\n ({ deadline, onComplete, className, variant = 'primary', size = 'md', ...props }, ref) => {\n const target = React.useMemo(() => parseDeadline(deadline), [deadline]);\n const variantStyles: Record<string, string> = {\n primary: 'bg-primary-600 text-white',\n secondary: 'bg-secondary-600 text-white',\n outline: 'border-2 border-primary-600 text-primary-600 bg-transparent',\n ghost: 'text-gray-700 bg-transparent',\n };\n\n const sizeTextStyles: Record<NonNullable<CountdownProps['size']>, string> = {\n sm: 'text-sm px-2 py-0.5 rounded',\n md: 'text-base px-3 py-1 rounded',\n lg: 'text-lg px-4 py-1.5 rounded',\n };\n const [now, setNow] = React.useState(() => Date.now());\n const [expired, setExpired] = React.useState(false);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return undefined;\n setNow(Date.now());\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [target]);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return;\n if (now >= target && !expired) {\n setExpired(true);\n onComplete?.();\n }\n }, [now, target, expired, onComplete]);\n\n const remaining = formatRemaining(target - now);\n const appliedVariant = expired ? 'expired' : variant;\n const expiredClass =\n variant === 'ghost'\n ? 'text-red-600 bg-transparent'\n : variant === 'outline'\n ? 'border-2 border-red-600 text-red-600 bg-transparent'\n : 'bg-red-600 text-white';\n const variantClass = expired ? expiredClass : variantStyles[variant];\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex items-center font-mono',\n variantClass,\n sizeTextStyles[size],\n className\n )}\n {...props}\n >\n {Number.isNaN(target) ? 'Invalid date' : remaining.text}\n </div>\n );\n }\n);\n\nCountdown.displayName = 'Countdown';\n\nexport default Countdown;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface TagProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\" | \"lg\";\n removable?: boolean;\n onRemove?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n removeLabel?: string;\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n lg: \"px-3 py-1.5 text-base\",\n};\n\nexport const Tag = React.forwardRef<HTMLSpanElement, TagProps>(\n (\n {\n className,\n variant = \"default\",\n size = \"md\",\n removable = false,\n onRemove,\n removeLabel = \"Remove\",\n children,\n ...props\n },\n ref\n ) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium\",\n radius.pill,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n >\n <span>{children}</span>\n {removable && (\n <button\n type=\"button\"\n aria-label={removeLabel}\n onClick={onRemove}\n className={cn(\n \"ml-2 inline-flex items-center justify-center\",\n radius.pill,\n border.ring,\n size === \"sm\" ? \"h-4 w-4\" : size === \"md\" ? \"h-5 w-5\" : \"h-6 w-6\"\n )}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className={cn(size === \"sm\" ? \"h-3 w-3\" : size === \"md\" ? \"h-4 w-4\" : \"h-5 w-5\")}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </span>\n );\n }\n);\n\nTag.displayName = \"Tag\";\n\nexport default Tag;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Tag } from \"../Tag/Tag\";\nimport { Badge } from \"../Badge/Badge\";\n\nexport type SelectItem = {\n value: string;\n label: React.ReactNode;\n icon?: string; // optional URL to an icon image\n disabled?: boolean;\n};\n\nexport type SelectGroup = {\n label: string;\n items: SelectItem[];\n};\n\nexport type SelectSource = SelectItem | SelectGroup;\n\nexport interface SelectProps {\n items: SelectSource[];\n placeholder?: string;\n multiselect?: boolean;\n multiline?: boolean;\n value?: string | string[];\n onChange?: (value: string | string[]) => void;\n className?: string;\n}\n\nexport const Select: React.FC<SelectProps> = ({\n items,\n placeholder = \"Select...\",\n multiselect = false,\n multiline = false,\n value,\n onChange,\n className,\n}) => {\n const [open, setOpen] = React.useState(false);\n const [internalValue, setInternalValue] = React.useState<string[]>(\n Array.isArray(value) ? value : value ? [value] : []\n );\n\n React.useEffect(() => {\n if (value !== undefined) {\n setInternalValue(Array.isArray(value) ? value : value ? [value] : []);\n }\n }, [value]);\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n\n React.useEffect(() => {\n const onDoc = (e: MouseEvent) => {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDoc);\n return () => document.removeEventListener(\"mousedown\", onDoc);\n }, []);\n\n const isSelected = (v: string) => internalValue.includes(v);\n\n const toggleSelect = (v: string) => {\n let next: string[];\n if (multiselect) {\n next = isSelected(v)\n ? internalValue.filter((x) => x !== v)\n : [...internalValue, v];\n } else {\n next = isSelected(v) ? [] : [v];\n setOpen(false);\n }\n\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n if (value === undefined) setInternalValue(next);\n };\n\n const removeValue = (v: string) => {\n const next = internalValue.filter((x) => x !== v);\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n if (value === undefined) setInternalValue(next);\n };\n\n const selectedItemsMap = React.useMemo(() => {\n const map = new Map<string, SelectItem>();\n const collect = (src: SelectSource[]) => {\n src.forEach((s) => {\n if (\"items\" in s) s.items.forEach((it) => map.set(it.value, it));\n else map.set(s.value, s);\n });\n };\n collect(items);\n return map;\n }, [items]);\n\n const tagsContainerRef = React.useRef<HTMLSpanElement | null>(null);\n const [visibleCount, setVisibleCount] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (multiline) {\n setVisibleCount(null);\n return;\n }\n\n let raf: number | undefined;\n let timeout: number | undefined;\n\n const measure = () => {\n if (raf) cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n const container = tagsContainerRef.current;\n if (!container) {\n setVisibleCount(null);\n return;\n }\n\n const containerWidth = container.clientWidth;\n if (containerWidth === 0) {\n setVisibleCount(null);\n return;\n }\n\n // Get all tag elements (they're always rendered, some may be hidden)\n const tagEls = Array.from(\n container.querySelectorAll('[data-role=\"select-tag\"]')\n ) as HTMLElement[];\n \n if (!tagEls.length) {\n setVisibleCount(null);\n return;\n }\n\n // Get badge element if present\n const badgeEl = container.querySelector('[data-role=\"count-badge\"]') as HTMLElement | null;\n\n // Compute gap from container\n const containerStyle = window.getComputedStyle(container);\n const gap = parseFloat(containerStyle.gap || containerStyle.columnGap || \"0\") || 0;\n\n // Measure each tag's width\n const tagWidths: number[] = tagEls.map((el) => el.offsetWidth);\n\n // First check: do all tags fit without any badge?\n let totalWidthAllTags = 0;\n for (const [i, w] of tagWidths.entries()) {\n totalWidthAllTags += w + (i > 0 ? gap : 0);\n }\n\n if (totalWidthAllTags <= containerWidth) {\n // All tags fit, no badge needed\n setVisibleCount(tagEls.length);\n return;\n }\n\n // Not all tags fit, so we need a badge. Measure or estimate badge width.\n let badgeWidth = badgeEl ? badgeEl.offsetWidth : 40;\n\n // Calculate how many tags fit WITH space reserved for the badge\n let usedWidth = 0;\n let fitCount = 0;\n\n for (const [i, tagWidth] of tagWidths.entries()) {\n const gapBeforeTag = i > 0 ? gap : 0;\n const gapBeforeBadge = gap;\n const effectiveTagWidth = tagWidth ?? 0;\n\n // Space needed: current tag + gap before badge + badge\n const spaceNeeded = usedWidth + gapBeforeTag + effectiveTagWidth + gapBeforeBadge + badgeWidth;\n\n if (spaceNeeded <= containerWidth) {\n usedWidth += gapBeforeTag + effectiveTagWidth;\n fitCount = i + 1;\n } else {\n break;\n }\n }\n\n // Ensure at least 1 tag is shown\n fitCount = Math.max(1, fitCount);\n\n setVisibleCount(fitCount);\n });\n };\n\n measure();\n\n const onResize = () => {\n if (timeout) clearTimeout(timeout);\n timeout = window.setTimeout(measure, 50);\n };\n window.addEventListener(\"resize\", onResize);\n\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== \"undefined\" && tagsContainerRef.current) {\n ro = new ResizeObserver(onResize);\n ro.observe(tagsContainerRef.current);\n }\n\n return () => {\n if (raf) cancelAnimationFrame(raf);\n if (timeout) clearTimeout(timeout);\n window.removeEventListener(\"resize\", onResize);\n ro?.disconnect();\n };\n }, [internalValue, multiline]);\n\n return (\n <div ref={containerRef} className={cn(\"relative inline-block w-full\", className)}>\n <div className=\"flex items-center\">\n <div\n role=\"combobox\"\n tabIndex={0}\n aria-expanded={open}\n onClick={() => setOpen((s) => !s)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setOpen((s) => !s);\n }\n if (e.key === \"Escape\") setOpen(false);\n }}\n className={cn(\n \"w-full inline-flex items-center justify-between rounded-lg border bg-white px-4 py-2 text-gray-900 text-left cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary-500\",\n multiselect ? \"\" : \"\",\n open ? \"ring-1 ring-gray-300\" : \"\"\n )}\n >\n <div className=\"flex-1\">\n {multiselect && internalValue.length > 0 ? (\n <span\n ref={tagsContainerRef}\n className={cn(\n \"relative flex gap-1 items-center\",\n multiline ? \"flex-wrap\" : \"overflow-hidden whitespace-nowrap\",\n )}\n >\n {/* Always render all tags for measurement; hide overflowed ones via CSS */}\n {internalValue.map((v, index) => {\n const isHidden = !multiline && visibleCount !== null && index >= visibleCount;\n return (\n <span\n key={v}\n data-role=\"select-tag\"\n className={cn(\n \"flex-shrink-0 inline-block\",\n isHidden && \"invisible absolute pointer-events-none\"\n )}\n >\n <Tag\n size=\"sm\"\n removable\n removeLabel={`Remove ${selectedItemsMap.get(v)?.label ?? v}`}\n onRemove={(e) => {\n e.stopPropagation();\n removeValue(v);\n }}\n >\n {selectedItemsMap.get(v)?.label ?? v}\n </Tag>\n </span>\n );\n })}\n {/* Show badge when there are hidden tags */}\n {!multiline && visibleCount !== null && visibleCount < internalValue.length && (\n <span data-role=\"count-badge\" className=\"flex-shrink-0 inline-block\">\n <Badge size=\"sm\" variant=\"info\">+{internalValue.length - visibleCount}</Badge>\n </span>\n )}\n </span>\n ) : internalValue.length > 0 ? (\n <span className=\"text-sm text-gray-900\">\n {selectedItemsMap.get(internalValue[0]!)?.label ?? placeholder}\n </span>\n ) : (\n <span className=\"text-sm text-gray-400\">{placeholder}</span>\n )}\n </div>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" className=\"ml-2 h-4 w-4 text-gray-600\">\n <path d=\"M5.5 7.5L10 12l4.5-4.5\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </svg>\n </div>\n </div>\n\n {open && (\n <div className=\"absolute z-40 mt-2 w-56 bg-white border rounded shadow-lg\">\n <div className=\"p-1\">\n {items.map((groupOrItem, gi) => {\n if (\"items\" in groupOrItem) {\n return (\n <div key={gi} className=\"mb-2\">\n <div className=\"flex items-center justify-between px-2 py-1 text-xs text-gray-500 font-medium\">\n <div>{groupOrItem.label}</div>\n <div>\n {multiselect && (\n <input\n type=\"checkbox\"\n aria-label={`Select all ${groupOrItem.label}`}\n checked={groupOrItem.items.every((it) => isSelected(it.value))}\n onChange={() => {\n // toggle all in group\n const all = groupOrItem.items.map((it) => it.value);\n const allSelected = all.every((v) => isSelected(v));\n let next: string[];\n if (multiselect) {\n if (allSelected) {\n next = internalValue.filter((v) => !all.includes(v));\n } else {\n next = [...internalValue, ...all.filter((v) => !internalValue.includes(v))];\n }\n } else {\n // single select: select first item or clear\n next = allSelected ? [] : (all[0] ? [all[0]] : []);\n setOpen(false);\n }\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n if (value === undefined) setInternalValue(next);\n }}\n />\n )}\n </div>\n </div>\n {groupOrItem.items.map((it) => (\n <button\n key={it.value}\n type=\"button\"\n disabled={it.disabled}\n onClick={() => toggleSelect(it.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(it.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {it.icon && (\n <img src={it.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{it.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(it.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n ))}\n </div>\n );\n }\n\n return (\n <button\n key={groupOrItem.value}\n type=\"button\"\n disabled={groupOrItem.disabled}\n onClick={() => toggleSelect(groupOrItem.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(groupOrItem.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {groupOrItem.icon && (\n <img src={groupOrItem.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{groupOrItem.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(groupOrItem.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default Select;\n"],"mappings":"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","names":["React","jsx","variantStyles","React","jsx","jsxs","React","jsx","variantStyles","sizeStyles","React","jsx","React","jsx","variantStyles","React","jsx","jsxs","variantStyles","sizeStyles","React","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/components/Button/Button.tsx","../src/utils/cn.ts","../src/components/Card/Card.tsx","../src/styles/borders.ts","../src/components/Input/Input.tsx","../src/components/Badge/Badge.tsx","../src/components/Icon/Icon.tsx","../src/components/Countdown/Countdown.tsx","../src/components/Tag/Tag.tsx","../src/components/Select/Select.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { IconWeight } from '@codecrib/ui/icons';\nimport { cn } from \"../../utils/cn\";\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"primary\" | \"secondary\" | \"outline\" | \"ghost\";\n size?: \"sm\" | \"md\" | \"lg\";\n isLoading?: boolean;\n /** Icon element to render inside the button */\n icon?: React.ReactNode;\n /** Position for the icon when `icon` is provided */\n iconPosition?: \"left\" | \"right\";\n}\n\nconst variantStyles = {\n primary:\n \"bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500\",\n secondary:\n \"bg-secondary-600 text-white hover:bg-secondary-700 focus:ring-secondary-500\",\n outline:\n \"border-2 border-primary-600 text-primary-600 hover:bg-primary-50 focus:ring-primary-500\",\n ghost: \"text-gray-700 hover:bg-gray-100 focus:ring-gray-500\",\n};\n\nconst sizeStyles = {\n sm: \"px-3 py-1.5 text-sm\",\n md: \"px-4 py-2 text-base\",\n lg: \"px-6 py-3 text-lg\",\n};\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"md\",\n isLoading = false,\n disabled,\n children,\n icon,\n iconPosition = 'left',\n ...props\n },\n ref\n ) => {\n const iconSizeMap: Record<NonNullable<ButtonProps['size']>, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n } as const;\n\n const iconWeightMap: Record<NonNullable<ButtonProps['size']>, IconWeight> = {\n sm: 'regular',\n md: 'regular',\n lg: 'bold',\n } as const;\n\n const renderIcon = () => {\n if (!icon) return null;\n if (React.isValidElement(icon)) {\n const sizeProp = (icon.props as { size?: number | string })?.size;\n const weightProp = (icon.props as { weight?: IconWeight })?.weight;\n const key = size as NonNullable<ButtonProps['size']>;\n const desired = {\n size: (sizeProp as number | undefined) ?? iconSizeMap[key],\n weight: weightProp ?? iconWeightMap[key],\n };\n try {\n return React.cloneElement(icon as React.ReactElement, desired);\n } catch {\n return icon;\n }\n }\n return icon;\n };\n return (\n <button\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n disabled={disabled || isLoading}\n {...props}\n >\n {isLoading && (\n <svg\n className=\"animate-spin -ml-1 mr-2 h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n )}\n {icon && iconPosition === 'left' && (\n <span className=\"mr-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n <span className=\"inline-flex items-center\">{children}</span>\n {icon && iconPosition === 'right' && (\n <span className=\"ml-2 inline-flex items-center\">{renderIcon()}</span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","/**\n * Utility function to merge class names\n */\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: \"default\" | \"bordered\" | \"elevated\";\n}\n\nconst variantStyles = {\n default: \"bg-white\",\n bordered: \"bg-white border border-gray-200\",\n elevated: \"bg-white shadow-lg\",\n};\n\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant = \"bordered\", children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(radius.default, \"p-6\", variantStyles[variant], className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nCard.displayName = \"Card\";\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 pb-4\", className)}\n {...props}\n />\n );\n }\n);\n\nCardHeader.displayName = \"CardHeader\";\n\nexport interface CardTitleProps\n extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"text-xl font-semibold text-gray-900\", className)}\n {...props}\n />\n );\n }\n);\n\nCardTitle.displayName = \"CardTitle\";\n\nexport interface CardContentProps\n extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, ...props }, ref) => {\n return <div ref={ref} className={cn(\"text-gray-600\", className)} {...props} />;\n }\n);\n\nCardContent.displayName = \"CardContent\";\n","export const radius = {\n default: \"rounded-lg\",\n pill: \"rounded-full\",\n};\n\nexport const border = {\n base: \"border\",\n color: \"border-gray-300\",\n focus: \"focus:border-primary-500 focus:ring-primary-500\",\n ring: \"focus:outline-none focus:ring-2 focus:ring-offset-0\",\n};\n\nexport const input = `${border.base} ${border.color}`;\n\nexport default {\n radius,\n border,\n input,\n};\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {\n label?: string;\n error?: string;\n helperText?: string;\n}\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, label, error, helperText, id, ...props }, ref) => {\n const inputId = id || React.useId();\n\n return (\n <div className=\"w-full\">\n {label && (\n <label\n htmlFor={inputId}\n className=\"block text-sm font-medium text-gray-700 mb-1\"\n >\n {label}\n </label>\n )}\n <input\n id={inputId}\n ref={ref}\n className={cn(\n \"block w-full px-4 py-2 text-gray-900 placeholder:text-gray-400 transition-colors\",\n radius.default,\n border.base,\n error\n ? \"border-red-500 focus:border-red-500 focus:ring-red-500\"\n : `${border.color} ${border.focus} ${border.ring}`,\n className\n )}\n {...props}\n />\n {error && <p className=\"mt-1 text-sm text-red-600\">{error}</p>}\n {helperText && !error && (\n <p className=\"mt-1 text-sm text-gray-500\">{helperText}</p>\n )}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\";\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n};\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant = \"default\", size = \"md\", ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium rounded-full\",\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nBadge.displayName = \"Badge\";\n","import * as React from 'react';\nimport type { IconProps as PhosphorIconProps } from 'phosphor-react';\nimport { cn } from '../../utils/cn';\n\nexport interface IconProps extends Omit<PhosphorIconProps, 'weight'> {\n icon: React.ForwardRefExoticComponent<PhosphorIconProps & React.RefAttributes<SVGSVGElement>>;\n weight?: PhosphorIconProps['weight'];\n className?: string;\n color?: string;\n}\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n ({ icon: IconComponent, size = 24, weight = 'regular', className, color, ...props }, ref) => {\n return (\n <IconComponent\n ref={ref}\n size={size}\n weight={weight}\n color={color}\n data-color={color}\n className={cn('inline-block', className)}\n aria-hidden\n {...(props as PhosphorIconProps)}\n />\n );\n }\n);\n\nIcon.displayName = 'Icon';\n\nexport default Icon;\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface CountdownProps extends React.HTMLAttributes<HTMLDivElement> {\n /** deadline as Date | timestamp | ISO string */\n deadline: string | number | Date;\n /** optional callback when countdown reaches zero */\n onComplete?: () => void;\n /** visual variant to match Button */\n variant?: 'primary' | 'secondary' | 'outline' | 'ghost';\n /** size to align with Button sizes */\n size?: 'sm' | 'md' | 'lg';\n}\n\nfunction parseDeadline(value: string | number | Date) {\n if (value instanceof Date) return value.getTime();\n const n = Number(value);\n if (!Number.isNaN(n)) return n;\n const d = Date.parse(String(value));\n return Number.isNaN(d) ? NaN : d;\n}\n\nfunction formatRemaining(ms: number) {\n if (ms <= 0) return { expired: true, text: '00:00:00' };\n const total = Math.floor(ms / 1000);\n const days = Math.floor(total / 86400);\n const hours = Math.floor((total % 86400) / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const seconds = total % 60;\n\n const pad = (n: number) => String(n).padStart(2, '0');\n const h = pad(hours + days * 24);\n const m = pad(minutes);\n const s = pad(seconds);\n const text = days > 0 ? `${days}d ${h}:${m}:${s}` : `${h}:${m}:${s}`;\n return { expired: false, text };\n}\n\nexport const Countdown = React.forwardRef<HTMLDivElement, CountdownProps>(\n ({ deadline, onComplete, className, variant = 'primary', size = 'md', ...props }, ref) => {\n const target = React.useMemo(() => parseDeadline(deadline), [deadline]);\n const variantStyles: Record<string, string> = {\n primary: 'bg-primary-600 text-white',\n secondary: 'bg-secondary-600 text-white',\n outline: 'border-2 border-primary-600 text-primary-600 bg-transparent',\n ghost: 'text-gray-700 bg-transparent',\n };\n\n const sizeTextStyles: Record<NonNullable<CountdownProps['size']>, string> = {\n sm: 'text-sm px-2 py-0.5 rounded',\n md: 'text-base px-3 py-1 rounded',\n lg: 'text-lg px-4 py-1.5 rounded',\n };\n const [now, setNow] = React.useState(() => Date.now());\n const [expired, setExpired] = React.useState(false);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return undefined;\n setNow(Date.now());\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [target]);\n\n React.useEffect(() => {\n if (Number.isNaN(target)) return;\n if (now >= target && !expired) {\n setExpired(true);\n onComplete?.();\n }\n }, [now, target, expired, onComplete]);\n\n const remaining = formatRemaining(target - now);\n const appliedVariant = expired ? 'expired' : variant;\n const expiredClass =\n variant === 'ghost'\n ? 'text-red-600 bg-transparent'\n : variant === 'outline'\n ? 'border-2 border-red-600 text-red-600 bg-transparent'\n : 'bg-red-600 text-white';\n const variantClass = expired ? expiredClass : variantStyles[variant];\n\n return (\n <div\n ref={ref}\n className={cn(\n 'inline-flex items-center font-mono',\n variantClass,\n sizeTextStyles[size],\n className\n )}\n {...props}\n >\n {Number.isNaN(target) ? 'Invalid date' : remaining.text}\n </div>\n );\n }\n);\n\nCountdown.displayName = 'Countdown';\n\nexport default Countdown;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\n\nexport interface TagProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\";\n size?: \"sm\" | \"md\" | \"lg\";\n removable?: boolean;\n onRemove?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n removeLabel?: string;\n}\n\nconst variantStyles = {\n default: \"bg-gray-100 text-gray-800\",\n success: \"bg-green-100 text-green-800\",\n warning: \"bg-yellow-100 text-yellow-800\",\n error: \"bg-red-100 text-red-800\",\n info: \"bg-blue-100 text-blue-800\",\n};\n\nconst sizeStyles = {\n sm: \"px-2 py-0.5 text-xs\",\n md: \"px-2.5 py-1 text-sm\",\n lg: \"px-3 py-1.5 text-base\",\n};\n\nexport const Tag = React.forwardRef<HTMLSpanElement, TagProps>(\n (\n {\n className,\n variant = \"default\",\n size = \"md\",\n removable = false,\n onRemove,\n removeLabel = \"Remove\",\n children,\n ...props\n },\n ref\n ) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"inline-flex items-center font-medium\",\n radius.pill,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n {...props}\n >\n <span>{children}</span>\n {removable && (\n <button\n type=\"button\"\n aria-label={removeLabel}\n onClick={onRemove}\n className={cn(\n \"ml-2 inline-flex items-center justify-center\",\n radius.pill,\n border.ring,\n size === \"sm\" ? \"h-4 w-4\" : size === \"md\" ? \"h-5 w-5\" : \"h-6 w-6\"\n )}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className={cn(size === \"sm\" ? \"h-3 w-3\" : size === \"md\" ? \"h-4 w-4\" : \"h-5 w-5\")}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </span>\n );\n }\n);\n\nTag.displayName = \"Tag\";\n\nexport default Tag;\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { radius, border } from \"../../styles/borders\";\nimport { Tag } from \"../Tag/Tag\";\nimport { Badge } from \"../Badge/Badge\";\n\nexport type SelectItem = {\n value: string;\n label: React.ReactNode;\n icon?: string; // optional URL to an icon image\n disabled?: boolean;\n};\n\nexport type SelectGroup = {\n label: string;\n items: SelectItem[];\n};\n\nexport type SelectSource = SelectItem | SelectGroup;\n\nexport interface SelectProps {\n items: SelectSource[];\n placeholder?: string;\n multiselect?: boolean;\n multiline?: boolean;\n value?: string | string[];\n onChange?: (value: string | string[]) => void;\n className?: string;\n}\n\nexport const Select: React.FC<SelectProps> = ({\n items,\n placeholder = \"Select...\",\n multiselect = false,\n multiline = false,\n value,\n onChange,\n className,\n}) => {\n const [open, setOpen] = React.useState(false);\n const [internalValue, setInternalValue] = React.useState<string[]>(\n Array.isArray(value) ? value : value ? [value] : []\n );\n\n React.useEffect(() => {\n if (value !== undefined) {\n setInternalValue(Array.isArray(value) ? value : value ? [value] : []);\n }\n }, [value]);\n\n React.useEffect(() => {\n // Reset last emitted value when controlled `value` changes externally\n lastEmittedRef.current = null;\n }, [value, multiselect]);\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n\n React.useEffect(() => {\n const onDoc = (e: MouseEvent) => {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDoc);\n return () => document.removeEventListener(\"mousedown\", onDoc);\n }, []);\n\n const isSelected = (v: string) => internalValue.includes(v);\n const lastEmittedRef = React.useRef<string | null>(null);\n\n const emitChange = (next: string[]) => {\n const payload = multiselect ? JSON.stringify(next) : next[0] || \"\";\n if (lastEmittedRef.current === payload) return;\n lastEmittedRef.current = payload;\n if (onChange) onChange(multiselect ? next : next[0] || \"\");\n };\n\n const toggleSelect = (v: string) => {\n let next: string[];\n if (multiselect) {\n next = isSelected(v)\n ? internalValue.filter((x) => x !== v)\n : [...internalValue, v];\n } else {\n next = isSelected(v) ? [] : [v];\n setOpen(false);\n }\n\n emitChange(next);\n if (value === undefined) setInternalValue(next);\n };\n\n const removeValue = (v: string) => {\n const next = internalValue.filter((x) => x !== v);\n emitChange(next);\n if (value === undefined) setInternalValue(next);\n };\n\n const selectedItemsMap = React.useMemo(() => {\n const map = new Map<string, SelectItem>();\n const collect = (src: SelectSource[]) => {\n src.forEach((s) => {\n if (\"items\" in s) s.items.forEach((it) => map.set(it.value, it));\n else map.set(s.value, s);\n });\n };\n collect(items);\n return map;\n }, [items]);\n\n const tagsContainerRef = React.useRef<HTMLSpanElement | null>(null);\n const [visibleCount, setVisibleCount] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (multiline) {\n setVisibleCount(null);\n return;\n }\n\n let raf: number | undefined;\n let timeout: number | undefined;\n\n const measure = () => {\n if (raf) cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n const container = tagsContainerRef.current;\n if (!container) {\n setVisibleCount(null);\n return;\n }\n\n const containerWidth = container.clientWidth;\n if (containerWidth === 0) {\n setVisibleCount(null);\n return;\n }\n\n // Get all tag elements (they're always rendered, some may be hidden)\n const tagEls = Array.from(\n container.querySelectorAll('[data-role=\"select-tag\"]')\n ) as HTMLElement[];\n \n if (!tagEls.length) {\n setVisibleCount(null);\n return;\n }\n\n // Get badge element if present\n const badgeEl = container.querySelector('[data-role=\"count-badge\"]') as HTMLElement | null;\n\n // Compute gap from container\n const containerStyle = window.getComputedStyle(container);\n const gap = parseFloat(containerStyle.gap || containerStyle.columnGap || \"0\") || 0;\n\n // Measure each tag's width\n const tagWidths: number[] = tagEls.map((el) => el.offsetWidth);\n\n // First check: do all tags fit without any badge?\n let totalWidthAllTags = 0;\n for (const [i, w] of tagWidths.entries()) {\n totalWidthAllTags += w + (i > 0 ? gap : 0);\n }\n\n if (totalWidthAllTags <= containerWidth) {\n // All tags fit, no badge needed\n setVisibleCount(tagEls.length);\n return;\n }\n\n // Not all tags fit, so we need a badge. Measure or estimate badge width.\n let badgeWidth = badgeEl ? badgeEl.offsetWidth : 40;\n\n // Calculate how many tags fit WITH space reserved for the badge\n let usedWidth = 0;\n let fitCount = 0;\n\n for (const [i, tagWidth] of tagWidths.entries()) {\n const gapBeforeTag = i > 0 ? gap : 0;\n const gapBeforeBadge = gap;\n const effectiveTagWidth = tagWidth ?? 0;\n\n // Space needed: current tag + gap before badge + badge\n const spaceNeeded = usedWidth + gapBeforeTag + effectiveTagWidth + gapBeforeBadge + badgeWidth;\n\n if (spaceNeeded <= containerWidth) {\n usedWidth += gapBeforeTag + effectiveTagWidth;\n fitCount = i + 1;\n } else {\n break;\n }\n }\n\n // Ensure at least 1 tag is shown\n fitCount = Math.max(1, fitCount);\n\n setVisibleCount(fitCount);\n });\n };\n\n measure();\n\n const onResize = () => {\n if (timeout) clearTimeout(timeout);\n timeout = window.setTimeout(measure, 50);\n };\n window.addEventListener(\"resize\", onResize);\n\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== \"undefined\" && tagsContainerRef.current) {\n ro = new ResizeObserver(onResize);\n ro.observe(tagsContainerRef.current);\n }\n\n return () => {\n if (raf) cancelAnimationFrame(raf);\n if (timeout) clearTimeout(timeout);\n window.removeEventListener(\"resize\", onResize);\n ro?.disconnect();\n };\n }, [internalValue, multiline]);\n\n return (\n <div ref={containerRef} className={cn(\"relative inline-block w-full\", className)}>\n <div className=\"flex items-center\">\n <div\n role=\"combobox\"\n tabIndex={0}\n aria-expanded={open}\n onClick={() => setOpen((s) => !s)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setOpen((s) => !s);\n }\n if (e.key === \"Escape\") setOpen(false);\n }}\n className={cn(\n \"w-full inline-flex items-center justify-between bg-white px-4 py-2 text-gray-900 text-left cursor-pointer\",\n radius.default,\n border.base,\n border.color,\n border.focus,\n border.ring,\n open ? \"ring-1 ring-gray-300\" : \"\"\n )}\n >\n <div className=\"flex-1\">\n {multiselect && internalValue.length > 0 ? (\n <span\n ref={tagsContainerRef}\n className={cn(\n \"relative flex gap-1 items-center\",\n multiline ? \"flex-wrap\" : \"overflow-hidden whitespace-nowrap\",\n )}\n >\n {/* Always render all tags for measurement; hide overflowed ones via CSS */}\n {internalValue.map((v, index) => {\n const isHidden = !multiline && visibleCount !== null && index >= visibleCount;\n return (\n <span\n key={v}\n data-role=\"select-tag\"\n className={cn(\n \"flex-shrink-0 inline-block\",\n isHidden && \"invisible absolute pointer-events-none\"\n )}\n >\n <Tag\n size=\"sm\"\n removable\n removeLabel={`Remove ${selectedItemsMap.get(v)?.label ?? v}`}\n onRemove={(e) => {\n e.stopPropagation();\n removeValue(v);\n }}\n >\n {selectedItemsMap.get(v)?.label ?? v}\n </Tag>\n </span>\n );\n })}\n {/* Show badge when there are hidden tags */}\n {!multiline && visibleCount !== null && visibleCount < internalValue.length && (\n <span data-role=\"count-badge\" className=\"flex-shrink-0 inline-block\">\n <Badge size=\"sm\" variant=\"info\">+{internalValue.length - visibleCount}</Badge>\n </span>\n )}\n </span>\n ) : internalValue.length > 0 ? (\n <span className=\"text-sm text-gray-900\">\n {selectedItemsMap.get(internalValue[0]!)?.label ?? placeholder}\n </span>\n ) : (\n <span className=\"text-sm text-gray-400\">{placeholder}</span>\n )}\n </div>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" className=\"ml-2 h-4 w-4 text-gray-600\">\n <path d=\"M5.5 7.5L10 12l4.5-4.5\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </svg>\n </div>\n </div>\n\n {open && (\n <div className={cn(\"absolute z-40 mt-2 w-56 bg-white shadow-lg\", border.base, border.color, radius.default)}>\n <div className=\"p-1\">\n {items.map((groupOrItem, gi) => {\n if (\"items\" in groupOrItem) {\n return (\n <div key={gi} className=\"mb-2\">\n <div className=\"flex items-center justify-between px-2 py-1 text-xs text-gray-500 font-medium\">\n <div>{groupOrItem.label}</div>\n <div>\n {multiselect && (\n <input\n type=\"checkbox\"\n aria-label={`Select all ${groupOrItem.label}`}\n checked={groupOrItem.items.every((it) => isSelected(it.value))}\n onChange={() => {\n // toggle all in group\n const all = groupOrItem.items.map((it) => it.value);\n const allSelected = all.every((v) => isSelected(v));\n let next: string[];\n if (multiselect) {\n if (allSelected) {\n next = internalValue.filter((v) => !all.includes(v));\n } else {\n next = [...internalValue, ...all.filter((v) => !internalValue.includes(v))];\n }\n } else {\n // single select: select first item or clear\n next = allSelected ? [] : (all[0] ? [all[0]] : []);\n setOpen(false);\n }\n emitChange(next);\n if (value === undefined) setInternalValue(next);\n }}\n />\n )}\n </div>\n </div>\n {groupOrItem.items.map((it) => (\n <button\n key={it.value}\n type=\"button\"\n disabled={it.disabled}\n onClick={() => toggleSelect(it.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(it.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {it.icon && (\n <img src={it.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{it.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(it.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n ))}\n </div>\n );\n }\n\n return (\n <button\n key={groupOrItem.value}\n type=\"button\"\n disabled={groupOrItem.disabled}\n onClick={() => toggleSelect(groupOrItem.value)}\n className={cn(\n \"w-full text-left px-2 py-2 rounded hover:bg-gray-50 flex items-center gap-2\",\n isSelected(groupOrItem.value) ? \"bg-gray-100\" : \"\"\n )}\n >\n {groupOrItem.icon && (\n <img src={groupOrItem.icon} alt=\"\" className=\"h-4 w-4 rounded\" />\n )}\n <span className=\"flex-1\">{groupOrItem.label}</span>\n <span className=\"w-6 flex items-center justify-end\">\n {isSelected(groupOrItem.value) && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default Select;\n"],"mappings":"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","names":["React","jsx","variantStyles","React","jsx","jsxs","React","jsx","variantStyles","sizeStyles","React","jsx","React","jsx","variantStyles","React","jsx","jsxs","variantStyles","sizeStyles","React","jsx","jsxs"]}
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ darkMode: 'class',
3
+ theme: {
4
+ extend: {
5
+ colors: {
6
+ primary: {
7
+ DEFAULT: '#06b6d4',
8
+ },
9
+ },
10
+ },
11
+ },
12
+ plugins: [],
13
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codecrib/ui",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "React UI component library with TailwindCSS",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,6 +30,7 @@
30
30
  "require": "./dist/index.cjs"
31
31
  },
32
32
  "./styles.css": "./dist/styles.css",
33
+ "./preset": "./dist/tailwind.preset.cjs",
33
34
  "./icons": {
34
35
  "types": "./src/icons.ts",
35
36
  "import": "./src/icons.ts",
@@ -43,8 +44,10 @@
43
44
  "**/*.css"
44
45
  ],
45
46
  "scripts": {
46
- "build": "tsup && pnpm build:styles",
47
+ "build": "tsup && pnpm build:styles && pnpm build:preset",
48
+ "prepare": "pnpm build:styles",
47
49
  "build:styles": "npx @tailwindcss/cli -i ./src/styles.css -o ./dist/styles.css --minify",
50
+ "build:preset": "cp ./src/tailwind.preset.cjs ./dist/tailwind.preset.cjs",
48
51
  "dev": "tsup --watch",
49
52
  "lint": "pnpm exec eslint --config ../../eslint.config.cjs --ext .ts,.tsx src/",
50
53
  "check-types": "tsc --noEmit",