canvas-ui-sdk 0.3.7 → 0.3.8

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.
Files changed (67) hide show
  1. package/dist/index.js +270 -223
  2. package/dist/index.js.map +1 -1
  3. package/mcp/dist/index.js +14 -2
  4. package/package.json +1 -1
  5. package/registry/blocks/canvas-item.json +1 -1
  6. package/registry/blocks/chat-message.json +1 -1
  7. package/registry/blocks/component-palette.json +1 -1
  8. package/registry/blocks/component-search.json +1 -1
  9. package/registry/blocks/content-dropzone.json +1 -1
  10. package/registry/blocks/credit-card-display.json +1 -1
  11. package/registry/blocks/custom-component-helper.json +1 -1
  12. package/registry/blocks/empty-state.json +1 -1
  13. package/registry/blocks/filter-popover.json +1 -1
  14. package/registry/blocks/fixed-column-data-table.json +1 -1
  15. package/registry/blocks/infinity-canvas.json +1 -1
  16. package/registry/blocks/menu-section.json +1 -1
  17. package/registry/blocks/messenger-sidebar.json +1 -1
  18. package/registry/blocks/mobile-bottom-nav.json +1 -1
  19. package/registry/blocks/monthly-calendar-widget.json +1 -1
  20. package/registry/blocks/page-header-section.json +1 -1
  21. package/registry/blocks/page-previews.json +1 -1
  22. package/registry/blocks/pagination.json +1 -1
  23. package/registry/blocks/persona-card.json +1 -1
  24. package/registry/blocks/pricing-cards.json +1 -1
  25. package/registry/blocks/profile-card.json +1 -1
  26. package/registry/blocks/profile-info-cards.json +1 -1
  27. package/registry/blocks/prompt-template.json +1 -1
  28. package/registry/blocks/screen-flowchart.json +1 -1
  29. package/registry/blocks/screen-prompt-builder.json +1 -1
  30. package/registry/blocks/screen-prompt-template.json +1 -1
  31. package/registry/blocks/search-bar.json +1 -1
  32. package/registry/blocks/sidebar-cards.json +1 -1
  33. package/registry/blocks/sidebar-profile-card.json +1 -1
  34. package/registry/blocks/step-tracker.json +1 -1
  35. package/registry/blocks/vertical-step-tracker.json +1 -1
  36. package/registry/blocks/video-chat-controls.json +1 -1
  37. package/registry/layout/account-settings-shell.json +1 -1
  38. package/registry/layout/dashboard-shell.json +1 -1
  39. package/registry/layout/double-sidebar-shell.json +1 -1
  40. package/registry/layout/double-sidebar.json +1 -1
  41. package/registry/layout/header.json +1 -1
  42. package/registry/layout/icon-sidebar-shell.json +1 -1
  43. package/registry/layout/icon-sidebar.json +1 -1
  44. package/registry/layout/mobile-menu-shell.json +1 -1
  45. package/registry/layout/multistep-progressbar-shell.json +1 -1
  46. package/registry/layout/multistep-shell.json +1 -1
  47. package/registry/layout/multistep-sidebar-shell.json +1 -1
  48. package/registry/layout/project-context-shell.json +1 -1
  49. package/registry/layout/search-bar-shell.json +1 -1
  50. package/registry/layout/sidebar.json +1 -1
  51. package/registry/layout/standard-page-shell.json +1 -1
  52. package/registry/layout/vertical-multistep-shell.json +1 -1
  53. package/registry/ui/avatar.json +1 -1
  54. package/registry/ui/checkbox.json +1 -1
  55. package/registry/ui/date-input.json +1 -1
  56. package/registry/ui/image-uploader.json +1 -1
  57. package/registry/ui/multiselect-checkbox-field.json +1 -1
  58. package/registry/ui/multiselect-tags.json +1 -1
  59. package/registry/ui/radio-group.json +1 -1
  60. package/registry/ui/searchbox.json +1 -1
  61. package/registry/ui/select.json +1 -1
  62. package/registry/ui/selectable-pills.json +1 -1
  63. package/registry/ui/slider.json +1 -1
  64. package/registry/ui/switch.json +1 -1
  65. package/registry/ui/text-input.json +1 -1
  66. package/registry/ui/textarea.json +1 -1
  67. package/styles/tokens.reference.css +9 -0
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/layout/standard-page-shell.tsx",
8
8
  "type": "registry:layout",
9
- "content": "\"use client\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Header } from \"./header\";\nimport { useCSSVariableSync } from \"../../hooks/use-css-variable-sync\";\nimport { FlairBanner } from \"../blocks/flair-banner\";\nimport { PageHeaderSection } from \"../blocks/page-header-section\";\nimport { LineTab } from \"../ui/line-tabs\";\n\ninterface StandardPageShellProps {\n /** Flair banner title */\n bannerTitle?: string;\n /** Flair banner description */\n bannerDescription?: string;\n /** Whether to show the flair banner */\n showBanner?: boolean;\n /** Page title */\n pageTitle?: string;\n /** Page description */\n pageDescription?: string;\n /** Array of tab items */\n tabs?: LineTab[];\n /** ID of the currently active tab */\n activeTab?: string;\n /** Callback when a tab is clicked */\n onTabChange?: (tabId: string) => void;\n /** Whether to show the tabs */\n showTabs?: boolean;\n /** Whether to show the page header section */\n showPageHeader?: boolean;\n /** Main content - the modular blocks */\n children: React.ReactNode;\n /** Callback when app menu (hamburger) is clicked - for future app-level menu */\n onAppMenuClick?: () => void;\n /** Additional class name for the main content area */\n contentClassName?: string;\n}\n\n/**\n * Canvas Design System - Standard Page Shell\n * \n * A no-sidebar layout with:\n * - Fixed header with logo (no sidebar)\n * - Optional flair banner (dark blue hero section)\n * - Optional page header section with title, description, and tabs\n * - Centered content area (max-width 992px)\n * \n * @example\n * ```tsx\n * <StandardPageShell\n * bannerTitle=\"Large title\"\n * bannerDescription=\"Description\"\n * pageTitle=\"Page title\"\n * pageDescription=\"Description\"\n * tabs={[{ id: \"tab1\", label: \"Tab 1\" }]}\n * >\n * <ContentDropzone />\n * </StandardPageShell>\n * ```\n */\nexport function StandardPageShell({\n bannerTitle = \"Large title\",\n bannerDescription = \"Description\",\n showBanner = true,\n pageTitle = \"Page title\",\n pageDescription = \"Description\",\n tabs = [\n { id: \"tab1\", label: \"Tab 1\" },\n { id: \"tab2\", label: \"Tab 2\" },\n { id: \"tab3\", label: \"Tab 3\" },\n { id: \"tab4\", label: \"Tab 4\" },\n ],\n activeTab,\n onTabChange,\n showTabs = true,\n showPageHeader = true,\n children,\n onAppMenuClick,\n contentClassName,\n}: StandardPageShellProps) {\n // Sync CSS variables when rendered in iframes\n useCSSVariableSync();\n\n const handleAppMenuClick = () => {\n onAppMenuClick?.();\n console.log(\"App menu clicked - implement app-level mobile menu here\");\n };\n\n return (\n <div className=\"min-h-screen bg-[var(--background)]\">\n {/* Header - Fixed at top with logo visible (no sidebar) */}\n <header className=\"sticky top-0 z-40\">\n <Header onMenuClick={handleAppMenuClick} showDesktopLogo />\n </header>\n\n {/* Page Header Section - Banner + Title/Tabs */}\n {(showBanner || showPageHeader) && (\n <div className=\"flex flex-col w-full\">\n {/* Flair Banner */}\n {showBanner && (\n <FlairBanner title={bannerTitle} />\n )}\n\n {/* Page Title, Description, and Tabs */}\n {showPageHeader && (\n <PageHeaderSection\n title={pageTitle}\n description={pageDescription}\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={onTabChange}\n showTabs={showTabs}\n />\n )}\n </div>\n )}\n\n {/* Main Content Area - Centered */}\n <main className=\"w-full\">\n <div \n className={cn(\n \"w-full max-w-[var(--content-max-width)] mx-auto\",\n \"px-[var(--spacing-xl)] lg:px-0\",\n \"py-[var(--spacing-6xl)]\",\n contentClassName\n )}\n >\n {children}\n </div>\n </main>\n </div>\n );\n}\n\n// Re-export types for convenience\nexport type { LineTab } from \"../ui/line-tabs\";\n\n"
9
+ "content": "\"use client\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Header } from \"./header\";\nimport { useCSSVariableSync } from \"../../hooks/use-css-variable-sync\";\nimport { FlairBanner } from \"../blocks/flair-banner\";\nimport { PageHeaderSection } from \"../blocks/page-header-section\";\nimport { LineTab } from \"../ui/line-tabs\";\n\ninterface StandardPageShellProps {\n /** Flair banner title */\n bannerTitle?: string;\n /** Flair banner description */\n bannerDescription?: string;\n /** Whether to show the flair banner */\n showBanner?: boolean;\n /** Page title */\n pageTitle?: string;\n /** Page description */\n pageDescription?: string;\n /** Array of tab items */\n tabs?: LineTab[];\n /** ID of the currently active tab */\n activeTab?: string;\n /** Callback when a tab is clicked */\n onTabChange?: (tabId: string) => void;\n /** Whether to show the tabs */\n showTabs?: boolean;\n /** Whether to show the page header section */\n showPageHeader?: boolean;\n /** Main content - the modular blocks */\n children: React.ReactNode;\n /** Callback when app menu (hamburger) is clicked - for future app-level menu */\n onAppMenuClick?: () => void;\n /** Additional class name for the main content area */\n contentClassName?: string;\n}\n\n/**\n * Canvas Design System - Standard Page Shell\n * \n * A no-sidebar layout with:\n * - Fixed header with logo (no sidebar)\n * - Optional flair banner (dark blue hero section)\n * - Optional page header section with title, description, and tabs\n * - Centered content area (max-width 992px)\n * \n * @example\n * ```tsx\n * <StandardPageShell\n * bannerTitle=\"Large title\"\n * bannerDescription=\"Description\"\n * pageTitle=\"Page title\"\n * pageDescription=\"Description\"\n * tabs={[{ id: \"tab1\", label: \"Tab 1\" }]}\n * >\n * <ContentDropzone />\n * </StandardPageShell>\n * ```\n */\nexport function StandardPageShell({\n bannerTitle = \"Large title\",\n bannerDescription = \"Description\",\n showBanner = true,\n pageTitle = \"Page title\",\n pageDescription = \"Description\",\n tabs = [\n { id: \"tab1\", label: \"Tab 1\" },\n { id: \"tab2\", label: \"Tab 2\" },\n { id: \"tab3\", label: \"Tab 3\" },\n { id: \"tab4\", label: \"Tab 4\" },\n ],\n activeTab,\n onTabChange,\n showTabs = true,\n showPageHeader = true,\n children,\n onAppMenuClick,\n contentClassName,\n}: StandardPageShellProps) {\n // Sync CSS variables when rendered in iframes\n useCSSVariableSync();\n\n const handleAppMenuClick = () => {\n onAppMenuClick?.();\n console.log(\"App menu clicked - implement app-level mobile menu here\");\n };\n\n return (\n <div className=\"min-h-screen bg-[var(--canvas-background)]\">\n {/* Header - Fixed at top with logo visible (no sidebar) */}\n <header className=\"sticky top-0 z-40\">\n <Header onMenuClick={handleAppMenuClick} showDesktopLogo />\n </header>\n\n {/* Page Header Section - Banner + Title/Tabs */}\n {(showBanner || showPageHeader) && (\n <div className=\"flex flex-col w-full\">\n {/* Flair Banner */}\n {showBanner && (\n <FlairBanner title={bannerTitle} />\n )}\n\n {/* Page Title, Description, and Tabs */}\n {showPageHeader && (\n <PageHeaderSection\n title={pageTitle}\n description={pageDescription}\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={onTabChange}\n showTabs={showTabs}\n />\n )}\n </div>\n )}\n\n {/* Main Content Area - Centered */}\n <main className=\"w-full\">\n <div \n className={cn(\n \"w-full max-w-[var(--content-max-width)] mx-auto\",\n \"px-[var(--spacing-xl)] lg:px-0\",\n \"py-[var(--spacing-6xl)]\",\n contentClassName\n )}\n >\n {children}\n </div>\n </main>\n </div>\n );\n}\n\n// Re-export types for convenience\nexport type { LineTab } from \"../ui/line-tabs\";\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [],
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/layout/vertical-multistep-shell.tsx",
8
8
  "type": "registry:layout",
9
- "content": "\"use client\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Header } from \"./header\";\nimport { useCSSVariableSync } from \"../../hooks/use-css-variable-sync\";\nimport { FlairBanner } from \"../blocks/flair-banner\";\nimport { VerticalStepTracker, defaultVerticalSteps } from \"../blocks/vertical-step-tracker\";\nimport { Step } from \"../blocks/step-tracker\";\nimport { Button } from \"../ui/button\";\nimport { Typography } from \"../ui/typography\";\n\ninterface VerticalMultistepShellProps {\n /** Array of step objects */\n steps?: Step[];\n /** Current active step (0-indexed) */\n currentStep?: number;\n /** Callback when a step is clicked */\n onStepClick?: (stepIndex: number) => void;\n /** Section title for the step tracker (e.g., \"REGISTRATION\") */\n sectionTitle?: string;\n /** Flair banner title */\n bannerTitle?: string;\n /** Flair banner description */\n bannerDescription?: string;\n /** Page title */\n pageTitle?: string;\n /** Page description */\n pageDescription?: string;\n /** Main content */\n children: React.ReactNode;\n /** Callback when Cancel/Back is clicked */\n onCancel?: () => void;\n /** Callback when Continue/Submit is clicked */\n onContinue?: () => void;\n /** Cancel button text */\n cancelText?: string;\n /** Continue button text */\n continueText?: string;\n /** Whether Continue button is disabled */\n continueDisabled?: boolean;\n /** Callback when app menu (hamburger) is clicked */\n onAppMenuClick?: () => void;\n /** Additional class name for the content area */\n contentClassName?: string;\n}\n\n/**\n * Canvas Design System - Vertical Multistep Shell\n * \n * A layout for multi-step processes with vertical step tracker:\n * \n * **Desktop**: Two-column layout\n * - Left: Sidebar card (320px) with vertical step tracker\n * - Right: Content area with step title, description, content, and navigation\n * \n * **Mobile**: Stacked layout\n * - Header with hamburger menu\n * - Page title and description\n * - Vertical step list (no card)\n * - Content area with navigation\n * \n * @example\n * ```tsx\n * <VerticalMultistepShell\n * steps={defaultVerticalSteps}\n * currentStep={0}\n * sectionTitle=\"REGISTRATION\"\n * onCancel={() => router.back()}\n * onContinue={() => setStep(step + 1)}\n * >\n * <ContentDropzone />\n * </VerticalMultistepShell>\n * ```\n */\nexport function VerticalMultistepShell({\n steps = defaultVerticalSteps,\n currentStep = 0,\n onStepClick,\n sectionTitle = \"REGISTRATION\",\n bannerTitle = \"Large title\",\n bannerDescription = \"Description\",\n pageTitle = \"Page title\",\n pageDescription = \"Description\",\n children,\n onCancel,\n onContinue,\n cancelText,\n continueText,\n continueDisabled = false,\n onAppMenuClick,\n contentClassName,\n}: VerticalMultistepShellProps) {\n useCSSVariableSync();\n\n const handleAppMenuClick = () => {\n onAppMenuClick?.();\n console.log(\"App menu clicked - implement app-level mobile menu here\");\n };\n\n const currentStepData = steps[currentStep];\n const isFirstStep = currentStep === 0;\n const isLastStep = currentStep === steps.length - 1;\n\n return (\n <div className=\"min-h-screen bg-[var(--background)]\">\n {/* Header */}\n <header className=\"sticky top-0 z-40\">\n <Header onMenuClick={handleAppMenuClick} showDesktopLogo />\n </header>\n\n {/* Flair Banner */}\n <FlairBanner title={bannerTitle} />\n\n {/* Page Header Section - Custom aligned to match sidebar content */}\n <div className=\"w-full border-b border-[var(--canvas-border)]\">\n <div\n className={cn(\n \"w-full max-w-[1200px] mx-auto\",\n \"px-[var(--spacing-xl)] lg:px-6\",\n \"py-[var(--spacing-6xl)]\",\n \"flex flex-col gap-1\"\n )}\n >\n <h2\n style={{\n fontFamily: \"var(--typo-page-title-font, var(--typo-global-font))\",\n fontSize: \"var(--typo-page-title-size)\",\n fontWeight: \"var(--typo-page-title-weight)\",\n letterSpacing: \"var(--typo-page-title-spacing)\",\n lineHeight: \"var(--typo-page-title-line-height)\",\n color: \"var(--typo-page-title-color)\",\n }}\n >\n {pageTitle}\n </h2>\n <p\n style={{\n fontFamily: \"var(--typo-page-desc-font, var(--typo-global-font))\",\n fontSize: \"var(--typo-page-desc-size)\",\n fontWeight: \"var(--typo-page-desc-weight)\",\n letterSpacing: \"var(--typo-page-desc-spacing)\",\n lineHeight: \"var(--typo-page-desc-line-height)\",\n color: \"var(--typo-page-desc-color-muted)\",\n }}\n >\n {pageDescription}\n </p>\n </div>\n </div>\n\n {/* Main Container */}\n <div \n className={cn(\n \"w-full max-w-[1200px] mx-auto\",\n \"px-[var(--spacing-xl)] lg:px-0\",\n \"py-[var(--spacing-5xl)]\",\n \"flex flex-col lg:flex-row gap-[var(--spacing-5xl)]\"\n )}\n >\n {/* Sidebar - Desktop: Card, Mobile: No card styling */}\n <div className=\"lg:shrink-0\">\n {/* Desktop: Card container */}\n <div \n className={cn(\n \"lg:w-[320px]\",\n // Desktop card styling\n \"lg:bg-white lg:border lg:border-[var(--canvas-border)]\",\n \"lg:rounded-[var(--radius-xl)]\",\n \"lg:p-6\"\n )}\n >\n <VerticalStepTracker\n steps={steps}\n currentStep={currentStep}\n onStepClick={onStepClick}\n title={sectionTitle}\n />\n </div>\n </div>\n\n {/* Content Area */}\n <div className={cn(\"flex-1 min-w-0\", contentClassName)}>\n {/* Step Content Container */}\n <div className=\"flex flex-col gap-[var(--spacing-3xl)]\">\n {/* Step Title and Description */}\n <div className=\"flex flex-col gap-1\">\n <Typography variant=\"h6\" as=\"h3\">\n {currentStepData?.label || `Step ${currentStep + 1}`}\n </Typography>\n {currentStepData?.description && (\n <Typography variant=\"body-m\" color=\"muted\">\n {currentStepData.description}\n </Typography>\n )}\n </div>\n\n {/* Main Content Area */}\n <div className=\"w-full\">\n {children}\n </div>\n\n {/* Navigation Buttons */}\n <div className=\"flex gap-[var(--spacing-3xl)] items-center justify-end\">\n <Button variant=\"neutral\" onClick={onCancel}>\n {cancelText || (isFirstStep ? \"Cancel\" : \"Back\")}\n </Button>\n <Button variant=\"primary\" onClick={onContinue} disabled={continueDisabled}>\n {continueText || (isLastStep ? \"Submit\" : \"Continue\")}\n </Button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n"
9
+ "content": "\"use client\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Header } from \"./header\";\nimport { useCSSVariableSync } from \"../../hooks/use-css-variable-sync\";\nimport { FlairBanner } from \"../blocks/flair-banner\";\nimport { VerticalStepTracker, defaultVerticalSteps } from \"../blocks/vertical-step-tracker\";\nimport { Step } from \"../blocks/step-tracker\";\nimport { Button } from \"../ui/button\";\nimport { Typography } from \"../ui/typography\";\n\ninterface VerticalMultistepShellProps {\n /** Array of step objects */\n steps?: Step[];\n /** Current active step (0-indexed) */\n currentStep?: number;\n /** Callback when a step is clicked */\n onStepClick?: (stepIndex: number) => void;\n /** Section title for the step tracker (e.g., \"REGISTRATION\") */\n sectionTitle?: string;\n /** Flair banner title */\n bannerTitle?: string;\n /** Flair banner description */\n bannerDescription?: string;\n /** Page title */\n pageTitle?: string;\n /** Page description */\n pageDescription?: string;\n /** Main content */\n children: React.ReactNode;\n /** Callback when Cancel/Back is clicked */\n onCancel?: () => void;\n /** Callback when Continue/Submit is clicked */\n onContinue?: () => void;\n /** Cancel button text */\n cancelText?: string;\n /** Continue button text */\n continueText?: string;\n /** Whether Continue button is disabled */\n continueDisabled?: boolean;\n /** Callback when app menu (hamburger) is clicked */\n onAppMenuClick?: () => void;\n /** Additional class name for the content area */\n contentClassName?: string;\n}\n\n/**\n * Canvas Design System - Vertical Multistep Shell\n * \n * A layout for multi-step processes with vertical step tracker:\n * \n * **Desktop**: Two-column layout\n * - Left: Sidebar card (320px) with vertical step tracker\n * - Right: Content area with step title, description, content, and navigation\n * \n * **Mobile**: Stacked layout\n * - Header with hamburger menu\n * - Page title and description\n * - Vertical step list (no card)\n * - Content area with navigation\n * \n * @example\n * ```tsx\n * <VerticalMultistepShell\n * steps={defaultVerticalSteps}\n * currentStep={0}\n * sectionTitle=\"REGISTRATION\"\n * onCancel={() => router.back()}\n * onContinue={() => setStep(step + 1)}\n * >\n * <ContentDropzone />\n * </VerticalMultistepShell>\n * ```\n */\nexport function VerticalMultistepShell({\n steps = defaultVerticalSteps,\n currentStep = 0,\n onStepClick,\n sectionTitle = \"REGISTRATION\",\n bannerTitle = \"Large title\",\n bannerDescription = \"Description\",\n pageTitle = \"Page title\",\n pageDescription = \"Description\",\n children,\n onCancel,\n onContinue,\n cancelText,\n continueText,\n continueDisabled = false,\n onAppMenuClick,\n contentClassName,\n}: VerticalMultistepShellProps) {\n useCSSVariableSync();\n\n const handleAppMenuClick = () => {\n onAppMenuClick?.();\n console.log(\"App menu clicked - implement app-level mobile menu here\");\n };\n\n const currentStepData = steps[currentStep];\n const isFirstStep = currentStep === 0;\n const isLastStep = currentStep === steps.length - 1;\n\n return (\n <div className=\"min-h-screen bg-[var(--canvas-background)]\">\n {/* Header */}\n <header className=\"sticky top-0 z-40\">\n <Header onMenuClick={handleAppMenuClick} showDesktopLogo />\n </header>\n\n {/* Flair Banner */}\n <FlairBanner title={bannerTitle} />\n\n {/* Page Header Section - Custom aligned to match sidebar content */}\n <div className=\"w-full border-b border-[var(--canvas-border)]\">\n <div\n className={cn(\n \"w-full max-w-[1200px] mx-auto\",\n \"px-[var(--spacing-xl)] lg:px-6\",\n \"py-[var(--spacing-6xl)]\",\n \"flex flex-col gap-1\"\n )}\n >\n <h2\n style={{\n fontFamily: \"var(--typo-h4-font, var(--typo-global-font))\",\n fontSize: \"var(--typo-h4-size)\",\n fontWeight: \"var(--typo-h4-weight)\",\n letterSpacing: \"var(--typo-h4-spacing)\",\n lineHeight: \"var(--typo-h4-line-height)\",\n color: \"var(--typo-h4-color)\",\n }}\n >\n {pageTitle}\n </h2>\n <p\n style={{\n fontFamily: \"var(--typo-body-m-font, var(--typo-global-font))\",\n fontSize: \"var(--typo-body-m-size)\",\n fontWeight: \"var(--typo-body-m-weight)\",\n letterSpacing: \"var(--typo-body-m-spacing)\",\n lineHeight: \"var(--typo-body-m-line-height)\",\n color: \"var(--typo-body-m-color-muted)\",\n }}\n >\n {pageDescription}\n </p>\n </div>\n </div>\n\n {/* Main Container */}\n <div \n className={cn(\n \"w-full max-w-[1200px] mx-auto\",\n \"px-[var(--spacing-xl)] lg:px-0\",\n \"py-[var(--spacing-5xl)]\",\n \"flex flex-col lg:flex-row gap-[var(--spacing-5xl)]\"\n )}\n >\n {/* Sidebar - Desktop: Card, Mobile: No card styling */}\n <div className=\"lg:shrink-0\">\n {/* Desktop: Card container */}\n <div \n className={cn(\n \"lg:w-[320px]\",\n // Desktop card styling\n \"lg:bg-[var(--canvas-background)] lg:border lg:border-[var(--canvas-border)]\",\n \"lg:rounded-[var(--radius-xl)]\",\n \"lg:p-6\"\n )}\n >\n <VerticalStepTracker\n steps={steps}\n currentStep={currentStep}\n onStepClick={onStepClick}\n title={sectionTitle}\n />\n </div>\n </div>\n\n {/* Content Area */}\n <div className={cn(\"flex-1 min-w-0\", contentClassName)}>\n {/* Step Content Container */}\n <div className=\"flex flex-col gap-[var(--spacing-3xl)]\">\n {/* Step Title and Description */}\n <div className=\"flex flex-col gap-1\">\n <Typography variant=\"h6\" as=\"h3\">\n {currentStepData?.label || `Step ${currentStep + 1}`}\n </Typography>\n {currentStepData?.description && (\n <Typography variant=\"body-m\" color=\"muted\">\n {currentStepData.description}\n </Typography>\n )}\n </div>\n\n {/* Main Content Area */}\n <div className=\"w-full\">\n {children}\n </div>\n\n {/* Navigation Buttons */}\n <div className=\"flex gap-[var(--spacing-3xl)] items-center justify-end\">\n <Button variant=\"neutral\" onClick={onCancel}>\n {cancelText || (isFirstStep ? \"Cancel\" : \"Back\")}\n </Button>\n <Button variant=\"primary\" onClick={onContinue} disabled={continueDisabled}>\n {continueText || (isLastStep ? \"Submit\" : \"Continue\")}\n </Button>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [],
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/avatar.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted flex size-full items-center justify-center rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n"
9
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-[var(--canvas-surface)] flex size-full items-center justify-center rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/checkbox.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { Check } from \"lucide-react\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst Checkbox = React.forwardRef<\n React.ComponentRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n \"peer size-4 shrink-0 rounded-[var(--radius-xs)] border border-[var(--canvas-border-input)]\",\n \"bg-white transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)]\",\n \"data-[state=checked]:bg-[var(--canvas-primary)] data-[state=checked]:border-[var(--canvas-primary)]\",\n \"data-[state=checked]:disabled:bg-[var(--canvas-input-disabled-text)] data-[state=checked]:disabled:border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\"flex items-center justify-center text-white\")}\n >\n <Check className=\"size-3\" strokeWidth={2.5} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n));\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\ninterface CheckboxWithLabelProps\n extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n children: React.ReactNode;\n size?: \"default\" | \"sm\";\n}\n\nconst CheckboxWithLabel = React.forwardRef<\n React.ComponentRef<typeof CheckboxPrimitive.Root>,\n CheckboxWithLabelProps\n>(({ children, className, id, size = \"default\", ...props }, ref) => {\n const generatedId = React.useId();\n const checkboxId = id || generatedId;\n\n const isSmall = size === \"sm\";\n\n return (\n <div className={cn(\"flex items-center\", isSmall ? \"gap-1.5\" : \"gap-2\")}>\n <Checkbox \n ref={ref} \n id={checkboxId} \n className={cn(isSmall && \"size-3.5\", className)} \n {...props} \n />\n <label\n htmlFor={checkboxId}\n className={cn(\n \"cursor-pointer select-none\",\n isSmall ? \"text-xs text-[var(--canvas-text-muted)]\" : \"text-[var(--canvas-text)]\"\n )}\n style={!isSmall ? { fontSize: \"var(--input-standard-font-size)\" } : undefined}\n >\n {children}\n </label>\n </div>\n );\n});\nCheckboxWithLabel.displayName = \"CheckboxWithLabel\";\n\nexport { Checkbox, CheckboxWithLabel };\n\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { Check } from \"lucide-react\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst Checkbox = React.forwardRef<\n React.ComponentRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n \"peer size-4 shrink-0 rounded-[var(--radius-xs)] border border-[var(--canvas-border-input)]\",\n \"bg-[var(--canvas-background)] transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)]\",\n \"data-[state=checked]:bg-[var(--canvas-primary)] data-[state=checked]:border-[var(--canvas-primary)]\",\n \"data-[state=checked]:disabled:bg-[var(--canvas-input-disabled-text)] data-[state=checked]:disabled:border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\"flex items-center justify-center text-[var(--canvas-primary-foreground)]\")}\n >\n <Check className=\"size-3\" strokeWidth={2.5} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n));\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\ninterface CheckboxWithLabelProps\n extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n children: React.ReactNode;\n size?: \"default\" | \"sm\";\n}\n\nconst CheckboxWithLabel = React.forwardRef<\n React.ComponentRef<typeof CheckboxPrimitive.Root>,\n CheckboxWithLabelProps\n>(({ children, className, id, size = \"default\", ...props }, ref) => {\n const generatedId = React.useId();\n const checkboxId = id || generatedId;\n\n const isSmall = size === \"sm\";\n\n return (\n <div className={cn(\"flex items-center\", isSmall ? \"gap-1.5\" : \"gap-2\")}>\n <Checkbox \n ref={ref} \n id={checkboxId} \n className={cn(isSmall && \"size-3.5\", className)} \n {...props} \n />\n <label\n htmlFor={checkboxId}\n className={cn(\n \"cursor-pointer select-none\",\n isSmall ? \"text-xs text-[var(--canvas-text-muted)]\" : \"text-[var(--canvas-text)]\"\n )}\n style={!isSmall ? { fontSize: \"var(--input-standard-font-size)\" } : undefined}\n >\n {children}\n </label>\n </div>\n );\n});\nCheckboxWithLabel.displayName = \"CheckboxWithLabel\";\n\nexport { Checkbox, CheckboxWithLabel };\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/date-input.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Calendar } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface DateInputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"onChange\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n value?: string;\n onChange?: (value: string) => void;\n}\n\nconst DateInput = React.forwardRef<HTMLInputElement, DateInputProps>(\n ({ className, inputSize = \"default\", placeholder = \"mm/dd/yyyy\", disabled, value, onChange, ...props }, ref) => {\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n return (\n <div\n className={cn(\n \"flex items-center gap-2 bg-white border border-[var(--canvas-border-input)]\",\n \"focus-within:border-[var(--canvas-border-input-focus)] focus-within:ring-2 focus-within:ring-[var(--canvas-border-input-focus)] focus-within:ring-offset-2\",\n \"has-[:disabled]:cursor-not-allowed has-[:disabled]:bg-[var(--canvas-input-disabled-bg)] has-[:disabled]:border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n }}\n >\n <Calendar className=\"size-4 shrink-0 text-[var(--canvas-text-muted)]\" />\n <input\n type=\"text\"\n ref={ref}\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n className={cn(\n \"flex-1 bg-transparent outline-none\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"disabled:text-[var(--canvas-input-disabled-text)] disabled:cursor-not-allowed\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n {...props}\n />\n </div>\n );\n }\n);\nDateInput.displayName = \"DateInput\";\n\nexport { DateInput };\n\n\n\n\n\n\n\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Calendar } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface DateInputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"onChange\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n value?: string;\n onChange?: (value: string) => void;\n}\n\nconst DateInput = React.forwardRef<HTMLInputElement, DateInputProps>(\n ({ className, inputSize = \"default\", placeholder = \"mm/dd/yyyy\", disabled, value, onChange, ...props }, ref) => {\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n return (\n <div\n className={cn(\n \"flex items-center gap-2 bg-[var(--canvas-background)] border border-[var(--canvas-border-input)]\",\n \"focus-within:border-[var(--canvas-border-input-focus)] focus-within:ring-2 focus-within:ring-[var(--canvas-border-input-focus)] focus-within:ring-offset-2\",\n \"has-[:disabled]:cursor-not-allowed has-[:disabled]:bg-[var(--canvas-input-disabled-bg)] has-[:disabled]:border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n }}\n >\n <Calendar className=\"size-4 shrink-0 text-[var(--canvas-text-muted)]\" />\n <input\n type=\"text\"\n ref={ref}\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n className={cn(\n \"flex-1 bg-transparent outline-none\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"disabled:text-[var(--canvas-input-disabled-text)] disabled:cursor-not-allowed\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n {...props}\n />\n </div>\n );\n }\n);\nDateInput.displayName = \"DateInput\";\n\nexport { DateInput };\n\n\n\n\n\n\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/image-uploader.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Upload, ChevronLeft, ChevronRight, Trash2 } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface UploadedImage {\n id: string;\n url: string;\n name?: string;\n}\n\nexport interface ImageUploaderProps {\n images?: UploadedImage[];\n selectedImageId?: string;\n onImagesChange?: (images: UploadedImage[]) => void;\n onSelectImage?: (imageId: string) => void;\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst ImageUploader = React.forwardRef<HTMLDivElement, ImageUploaderProps>(\n (\n {\n images = [],\n selectedImageId,\n onImagesChange,\n onSelectImage,\n placeholder = \"Drop image here\",\n disabled,\n className,\n },\n ref\n ) => {\n const fileInputRef = React.useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = React.useState(false);\n\n const handleDragOver = (e: React.DragEvent) => {\n e.preventDefault();\n if (!disabled) setIsDragging(true);\n };\n\n const handleDragLeave = (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n };\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n if (disabled) return;\n\n const files = Array.from(e.dataTransfer.files).filter((file) =>\n file.type.startsWith(\"image/\")\n );\n handleFiles(files);\n };\n\n const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled || !e.target.files) return;\n const files = Array.from(e.target.files);\n handleFiles(files);\n e.target.value = \"\";\n };\n\n const handleFiles = (files: File[]) => {\n const newImages: UploadedImage[] = files.map((file) => ({\n id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n url: URL.createObjectURL(file),\n name: file.name,\n }));\n\n onImagesChange?.([...images, ...newImages]);\n };\n\n const handleDelete = (imageId: string) => {\n if (disabled) return;\n const newImages = images.filter((img) => img.id !== imageId);\n onImagesChange?.(newImages);\n };\n\n const handleMoveLeft = (imageId: string) => {\n if (disabled) return;\n const index = images.findIndex((img) => img.id === imageId);\n if (index > 0) {\n const newImages = [...images];\n [newImages[index - 1], newImages[index]] = [\n newImages[index],\n newImages[index - 1],\n ];\n onImagesChange?.(newImages);\n }\n };\n\n const handleMoveRight = (imageId: string) => {\n if (disabled) return;\n const index = images.findIndex((img) => img.id === imageId);\n if (index < images.length - 1) {\n const newImages = [...images];\n [newImages[index], newImages[index + 1]] = [\n newImages[index + 1],\n newImages[index],\n ];\n onImagesChange?.(newImages);\n }\n };\n\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-col w-full\", className)}\n style={{ gap: \"var(--spacing-xs)\" }}\n >\n {/* Dropzone */}\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onClick={() => !disabled && fileInputRef.current?.click()}\n onKeyDown={(e) =>\n e.key === \"Enter\" && !disabled && fileInputRef.current?.click()\n }\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n className={cn(\n \"flex flex-col items-center justify-center w-full border border-dashed rounded-[var(--radius-xs)] cursor-pointer transition-colors\",\n isDragging\n ? \"border-[var(--canvas-primary)] bg-[var(--canvas-surface-brand)]\"\n : \"border-[var(--canvas-border-input)] bg-[var(--canvas-surface)]\",\n disabled &&\n \"cursor-not-allowed bg-[var(--canvas-input-disabled-bg)] border-[var(--canvas-input-disabled-border)] opacity-60\"\n )}\n style={{\n height: \"var(--input-expandable-height)\",\n paddingLeft: \"var(--spacing-xl)\",\n paddingRight: \"var(--spacing-xl)\",\n paddingTop: \"var(--spacing-2xl)\",\n paddingBottom: \"var(--spacing-2xl)\",\n gap: \"var(--spacing-xs)\",\n }}\n >\n <Upload\n className=\"text-[var(--canvas-text-muted)]\"\n style={{ width: \"32px\", height: \"32px\" }}\n />\n <p\n className=\"text-[var(--canvas-text-placeholder)] text-center\"\n style={{\n fontFamily: \"var(--typo-body-m-font)\",\n fontSize: \"var(--typo-body-m-size)\",\n lineHeight: \"var(--typo-body-m-line-height)\",\n }}\n >\n {placeholder}\n </p>\n </div>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n multiple\n onChange={handleFileSelect}\n disabled={disabled}\n className=\"hidden\"\n />\n\n {/* Uploaded images gallery */}\n {images.length > 0 && (\n <div\n className=\"flex items-start w-full overflow-x-auto\"\n style={{\n gap: \"var(--spacing-xl)\",\n paddingTop: \"var(--spacing-xl)\",\n }}\n >\n {images.map((image, index) => {\n const isSelected = selectedImageId === image.id;\n const isFirst = index === 0;\n const isLast = index === images.length - 1;\n\n return (\n <div\n key={image.id}\n className={cn(\n \"flex flex-col shrink-0 rounded-[var(--radius-xs)] border overflow-hidden\",\n isSelected\n ? \"border-[var(--canvas-primary)]\"\n : \"border-[var(--canvas-border)]\"\n )}\n onClick={() => onSelectImage?.(image.id)}\n >\n {/* Image preview */}\n <div\n className=\"relative overflow-hidden\"\n style={{\n width: \"80px\",\n height: \"92px\",\n padding: \"var(--spacing-md)\",\n }}\n >\n <img\n src={image.url}\n alt={image.name || \"Uploaded image\"}\n className=\"w-full h-full object-cover rounded-sm\"\n />\n </div>\n\n {/* Controls */}\n <div\n className=\"flex items-center justify-end border-t border-[var(--canvas-border)]\"\n style={{\n gap: \"var(--spacing-xs)\",\n paddingLeft: \"var(--spacing-md)\",\n paddingRight: \"var(--spacing-md)\",\n paddingTop: \"var(--spacing-sm)\",\n paddingBottom: \"var(--spacing-sm)\",\n }}\n >\n {/* Move left */}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleMoveLeft(image.id);\n }}\n disabled={disabled || isFirst}\n className={cn(\n \"flex items-center justify-center rounded-full transition-colors\",\n isFirst || disabled\n ? \"bg-[var(--canvas-surface)] border border-[var(--canvas-border)] text-[var(--canvas-text-muted)]\"\n : \"bg-[var(--canvas-text)] text-white\"\n )}\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <ChevronLeft style={{ width: \"16px\", height: \"16px\" }} />\n </button>\n\n {/* Move right */}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleMoveRight(image.id);\n }}\n disabled={disabled || isLast}\n className={cn(\n \"flex items-center justify-center rounded-full transition-colors\",\n isLast || disabled\n ? \"bg-[var(--canvas-surface)] border border-[var(--canvas-border)] text-[var(--canvas-text-muted)]\"\n : \"bg-[var(--canvas-text)] text-white\"\n )}\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <ChevronRight style={{ width: \"16px\", height: \"16px\" }} />\n </button>\n\n {/* Delete */}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(image.id);\n }}\n disabled={disabled}\n className=\"flex items-center justify-center rounded-full bg-[var(--canvas-text)] text-white transition-colors\"\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <Trash2 style={{ width: \"16px\", height: \"16px\" }} />\n </button>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n }\n);\nImageUploader.displayName = \"ImageUploader\";\n\nexport { ImageUploader };\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Upload, ChevronLeft, ChevronRight, Trash2 } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface UploadedImage {\n id: string;\n url: string;\n name?: string;\n}\n\nexport interface ImageUploaderProps {\n images?: UploadedImage[];\n selectedImageId?: string;\n onImagesChange?: (images: UploadedImage[]) => void;\n onSelectImage?: (imageId: string) => void;\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst ImageUploader = React.forwardRef<HTMLDivElement, ImageUploaderProps>(\n (\n {\n images = [],\n selectedImageId,\n onImagesChange,\n onSelectImage,\n placeholder = \"Drop image here\",\n disabled,\n className,\n },\n ref\n ) => {\n const fileInputRef = React.useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = React.useState(false);\n\n const handleDragOver = (e: React.DragEvent) => {\n e.preventDefault();\n if (!disabled) setIsDragging(true);\n };\n\n const handleDragLeave = (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n };\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n if (disabled) return;\n\n const files = Array.from(e.dataTransfer.files).filter((file) =>\n file.type.startsWith(\"image/\")\n );\n handleFiles(files);\n };\n\n const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled || !e.target.files) return;\n const files = Array.from(e.target.files);\n handleFiles(files);\n e.target.value = \"\";\n };\n\n const handleFiles = (files: File[]) => {\n const newImages: UploadedImage[] = files.map((file) => ({\n id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n url: URL.createObjectURL(file),\n name: file.name,\n }));\n\n onImagesChange?.([...images, ...newImages]);\n };\n\n const handleDelete = (imageId: string) => {\n if (disabled) return;\n const newImages = images.filter((img) => img.id !== imageId);\n onImagesChange?.(newImages);\n };\n\n const handleMoveLeft = (imageId: string) => {\n if (disabled) return;\n const index = images.findIndex((img) => img.id === imageId);\n if (index > 0) {\n const newImages = [...images];\n [newImages[index - 1], newImages[index]] = [\n newImages[index],\n newImages[index - 1],\n ];\n onImagesChange?.(newImages);\n }\n };\n\n const handleMoveRight = (imageId: string) => {\n if (disabled) return;\n const index = images.findIndex((img) => img.id === imageId);\n if (index < images.length - 1) {\n const newImages = [...images];\n [newImages[index], newImages[index + 1]] = [\n newImages[index + 1],\n newImages[index],\n ];\n onImagesChange?.(newImages);\n }\n };\n\n return (\n <div\n ref={ref}\n className={cn(\"flex flex-col w-full\", className)}\n style={{ gap: \"var(--spacing-xs)\" }}\n >\n {/* Dropzone */}\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onClick={() => !disabled && fileInputRef.current?.click()}\n onKeyDown={(e) =>\n e.key === \"Enter\" && !disabled && fileInputRef.current?.click()\n }\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n className={cn(\n \"flex flex-col items-center justify-center w-full border border-dashed rounded-[var(--radius-xs)] cursor-pointer transition-colors\",\n isDragging\n ? \"border-[var(--canvas-primary)] bg-[var(--canvas-surface-brand)]\"\n : \"border-[var(--canvas-border-input)] bg-[var(--canvas-surface)]\",\n disabled &&\n \"cursor-not-allowed bg-[var(--canvas-input-disabled-bg)] border-[var(--canvas-input-disabled-border)] opacity-60\"\n )}\n style={{\n height: \"var(--input-expandable-height)\",\n paddingLeft: \"var(--spacing-xl)\",\n paddingRight: \"var(--spacing-xl)\",\n paddingTop: \"var(--spacing-2xl)\",\n paddingBottom: \"var(--spacing-2xl)\",\n gap: \"var(--spacing-xs)\",\n }}\n >\n <Upload\n className=\"text-[var(--canvas-text-muted)]\"\n style={{ width: \"32px\", height: \"32px\" }}\n />\n <p\n className=\"text-[var(--canvas-text-placeholder)] text-center\"\n style={{\n fontFamily: \"var(--typo-body-m-font)\",\n fontSize: \"var(--typo-body-m-size)\",\n lineHeight: \"var(--typo-body-m-line-height)\",\n }}\n >\n {placeholder}\n </p>\n </div>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n multiple\n onChange={handleFileSelect}\n disabled={disabled}\n className=\"hidden\"\n />\n\n {/* Uploaded images gallery */}\n {images.length > 0 && (\n <div\n className=\"flex items-start w-full overflow-x-auto\"\n style={{\n gap: \"var(--spacing-xl)\",\n paddingTop: \"var(--spacing-xl)\",\n }}\n >\n {images.map((image, index) => {\n const isSelected = selectedImageId === image.id;\n const isFirst = index === 0;\n const isLast = index === images.length - 1;\n\n return (\n <div\n key={image.id}\n className={cn(\n \"flex flex-col shrink-0 rounded-[var(--radius-xs)] border overflow-hidden\",\n isSelected\n ? \"border-[var(--canvas-primary)]\"\n : \"border-[var(--canvas-border)]\"\n )}\n onClick={() => onSelectImage?.(image.id)}\n >\n {/* Image preview */}\n <div\n className=\"relative overflow-hidden\"\n style={{\n width: \"80px\",\n height: \"92px\",\n padding: \"var(--spacing-md)\",\n }}\n >\n <img\n src={image.url}\n alt={image.name || \"Uploaded image\"}\n className=\"w-full h-full object-cover rounded-sm\"\n />\n </div>\n\n {/* Controls */}\n <div\n className=\"flex items-center justify-end border-t border-[var(--canvas-border)]\"\n style={{\n gap: \"var(--spacing-xs)\",\n paddingLeft: \"var(--spacing-md)\",\n paddingRight: \"var(--spacing-md)\",\n paddingTop: \"var(--spacing-sm)\",\n paddingBottom: \"var(--spacing-sm)\",\n }}\n >\n {/* Move left */}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleMoveLeft(image.id);\n }}\n disabled={disabled || isFirst}\n className={cn(\n \"flex items-center justify-center rounded-full transition-colors\",\n isFirst || disabled\n ? \"bg-[var(--canvas-surface)] border border-[var(--canvas-border)] text-[var(--canvas-text-muted)]\"\n : \"bg-[var(--canvas-text)] text-[var(--canvas-primary-foreground)]\"\n )}\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <ChevronLeft style={{ width: \"16px\", height: \"16px\" }} />\n </button>\n\n {/* Move right */}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleMoveRight(image.id);\n }}\n disabled={disabled || isLast}\n className={cn(\n \"flex items-center justify-center rounded-full transition-colors\",\n isLast || disabled\n ? \"bg-[var(--canvas-surface)] border border-[var(--canvas-border)] text-[var(--canvas-text-muted)]\"\n : \"bg-[var(--canvas-text)] text-[var(--canvas-primary-foreground)]\"\n )}\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <ChevronRight style={{ width: \"16px\", height: \"16px\" }} />\n </button>\n\n {/* Delete */}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(image.id);\n }}\n disabled={disabled}\n className=\"flex items-center justify-center rounded-full bg-[var(--canvas-text)] text-[var(--canvas-primary-foreground)] transition-colors\"\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <Trash2 style={{ width: \"16px\", height: \"16px\" }} />\n </button>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n }\n);\nImageUploader.displayName = \"ImageUploader\";\n\nexport { ImageUploader };\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/multiselect-checkbox-field.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Check } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface CheckboxOption {\n id: string;\n label: string;\n}\n\nexport interface MultiselectCheckboxFieldProps {\n options?: CheckboxOption[];\n selectedValues?: string[];\n onChange?: (values: string[]) => void;\n inputSize?: \"sm\" | \"default\" | \"lg\";\n disabled?: boolean;\n className?: string;\n}\n\nconst MultiselectCheckboxField = React.forwardRef<\n HTMLDivElement,\n MultiselectCheckboxFieldProps\n>(\n (\n {\n options = [],\n selectedValues = [],\n onChange,\n inputSize = \"default\",\n disabled,\n className,\n },\n ref\n ) => {\n const sizeVar =\n inputSize === \"default\"\n ? \"standard\"\n : inputSize === \"sm\"\n ? \"small\"\n : \"large\";\n\n const handleToggle = (optionId: string) => {\n if (disabled) return;\n\n const newValues = selectedValues.includes(optionId)\n ? selectedValues.filter((v) => v !== optionId)\n : [...selectedValues, optionId];\n\n onChange?.(newValues);\n };\n\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-wrap items-start overflow-hidden\",\n className\n )}\n style={{ gap: \"var(--spacing-xl)\" }}\n >\n {options.map((option) => {\n const isSelected = selectedValues.includes(option.id);\n\n return (\n <button\n key={option.id}\n type=\"button\"\n onClick={() => handleToggle(option.id)}\n disabled={disabled}\n className={cn(\n \"flex items-center gap-2 bg-white border overflow-hidden transition-colors\",\n \"focus:outline-none focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2\",\n isSelected\n ? \"border-[var(--canvas-primary)]\"\n : \"border-[var(--canvas-border-input)]\",\n disabled &&\n \"cursor-not-allowed bg-[var(--canvas-input-disabled-bg)] border-[var(--canvas-input-disabled-border)] opacity-60\"\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n minWidth: \"fit-content\",\n flexShrink: 0,\n flexGrow: 1,\n flexBasis: 0,\n minHeight: `var(--input-${sizeVar}-height)`,\n }}\n >\n {/* Checkbox indicator */}\n <span\n className={cn(\n \"flex items-center justify-center shrink-0 rounded-[var(--radius-xs)] border transition-colors\",\n isSelected\n ? \"bg-[var(--canvas-primary)] border-[var(--canvas-primary)]\"\n : \"bg-white border-[var(--canvas-border-input)]\",\n disabled && \"opacity-60\"\n )}\n style={{\n width: inputSize === \"sm\" ? \"16px\" : \"20px\",\n height: inputSize === \"sm\" ? \"16px\" : \"20px\",\n }}\n >\n {isSelected && (\n <Check\n className=\"text-white\"\n style={{\n width: inputSize === \"sm\" ? \"12px\" : \"16px\",\n height: inputSize === \"sm\" ? \"12px\" : \"16px\",\n }}\n strokeWidth={2.5}\n />\n )}\n </span>\n\n {/* Label */}\n <span\n className={cn(\n \"whitespace-nowrap\",\n isSelected\n ? \"text-[var(--canvas-primary)]\"\n : \"text-[var(--canvas-text-muted)]\",\n disabled && \"text-[var(--canvas-input-disabled-text)]\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n >\n {option.label}\n </span>\n </button>\n );\n })}\n </div>\n );\n }\n);\nMultiselectCheckboxField.displayName = \"MultiselectCheckboxField\";\n\nexport { MultiselectCheckboxField };\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Check } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface CheckboxOption {\n id: string;\n label: string;\n}\n\nexport interface MultiselectCheckboxFieldProps {\n options?: CheckboxOption[];\n selectedValues?: string[];\n onChange?: (values: string[]) => void;\n inputSize?: \"sm\" | \"default\" | \"lg\";\n disabled?: boolean;\n className?: string;\n}\n\nconst MultiselectCheckboxField = React.forwardRef<\n HTMLDivElement,\n MultiselectCheckboxFieldProps\n>(\n (\n {\n options = [],\n selectedValues = [],\n onChange,\n inputSize = \"default\",\n disabled,\n className,\n },\n ref\n ) => {\n const sizeVar =\n inputSize === \"default\"\n ? \"standard\"\n : inputSize === \"sm\"\n ? \"small\"\n : \"large\";\n\n const handleToggle = (optionId: string) => {\n if (disabled) return;\n\n const newValues = selectedValues.includes(optionId)\n ? selectedValues.filter((v) => v !== optionId)\n : [...selectedValues, optionId];\n\n onChange?.(newValues);\n };\n\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-wrap items-start overflow-hidden\",\n className\n )}\n style={{ gap: \"var(--spacing-xl)\" }}\n >\n {options.map((option) => {\n const isSelected = selectedValues.includes(option.id);\n\n return (\n <button\n key={option.id}\n type=\"button\"\n onClick={() => handleToggle(option.id)}\n disabled={disabled}\n className={cn(\n \"flex items-center gap-2 bg-[var(--canvas-background)] border overflow-hidden transition-colors\",\n \"focus:outline-none focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2\",\n isSelected\n ? \"border-[var(--canvas-primary)]\"\n : \"border-[var(--canvas-border-input)]\",\n disabled &&\n \"cursor-not-allowed bg-[var(--canvas-input-disabled-bg)] border-[var(--canvas-input-disabled-border)] opacity-60\"\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n minWidth: \"fit-content\",\n flexShrink: 0,\n flexGrow: 1,\n flexBasis: 0,\n minHeight: `var(--input-${sizeVar}-height)`,\n }}\n >\n {/* Checkbox indicator */}\n <span\n className={cn(\n \"flex items-center justify-center shrink-0 rounded-[var(--radius-xs)] border transition-colors\",\n isSelected\n ? \"bg-[var(--canvas-primary)] border-[var(--canvas-primary)]\"\n : \"bg-[var(--canvas-background)] border-[var(--canvas-border-input)]\",\n disabled && \"opacity-60\"\n )}\n style={{\n width: inputSize === \"sm\" ? \"16px\" : \"20px\",\n height: inputSize === \"sm\" ? \"16px\" : \"20px\",\n }}\n >\n {isSelected && (\n <Check\n className=\"text-[var(--canvas-primary-foreground)]\"\n style={{\n width: inputSize === \"sm\" ? \"12px\" : \"16px\",\n height: inputSize === \"sm\" ? \"12px\" : \"16px\",\n }}\n strokeWidth={2.5}\n />\n )}\n </span>\n\n {/* Label */}\n <span\n className={cn(\n \"whitespace-nowrap\",\n isSelected\n ? \"text-[var(--canvas-primary)]\"\n : \"text-[var(--canvas-text-muted)]\",\n disabled && \"text-[var(--canvas-input-disabled-text)]\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n >\n {option.label}\n </span>\n </button>\n );\n })}\n </div>\n );\n }\n);\nMultiselectCheckboxField.displayName = \"MultiselectCheckboxField\";\n\nexport { MultiselectCheckboxField };\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/multiselect-tags.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface MultiselectTagsProps {\n tags?: string[];\n placeholder?: string;\n inputSize?: \"sm\" | \"default\" | \"lg\";\n onAdd?: (tag: string) => void;\n onRemove?: (tag: string) => void;\n disabled?: boolean;\n className?: string;\n}\n\nconst MultiselectTags = React.forwardRef<HTMLInputElement, MultiselectTagsProps>(\n ({ \n tags = [], \n placeholder = \"Add...\", \n inputSize = \"default\", \n onAdd, \n onRemove, \n disabled,\n className \n }, ref) => {\n const [inputValue, setInputValue] = React.useState(\"\");\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && inputValue.trim()) {\n e.preventDefault();\n onAdd?.(inputValue.trim());\n setInputValue(\"\");\n }\n };\n\n return (\n <div\n className={cn(\n \"flex flex-wrap items-center gap-1.5 bg-white border border-[var(--canvas-border-input)] p-1.5\",\n \"focus-within:border-[var(--canvas-border-input-focus)] focus-within:ring-2 focus-within:ring-[var(--canvas-border-input-focus)] focus-within:ring-offset-2\",\n disabled && \"cursor-not-allowed bg-[var(--canvas-input-disabled-bg)] border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n style={{\n minHeight: `var(--input-${sizeVar}-height)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n }}\n >\n {tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-[var(--canvas-surface-brand)] text-[var(--canvas-primary)] rounded text-xs\"\n >\n {tag}\n {!disabled && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={() => onRemove?.(tag)}\n onKeyDown={(e) => e.key === \"Enter\" && onRemove?.(tag)}\n className=\"cursor-pointer hover:opacity-70\"\n >\n <X className=\"size-3\" />\n </span>\n )}\n </span>\n ))}\n <input\n type=\"text\"\n ref={ref}\n placeholder={placeholder}\n disabled={disabled}\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n className={cn(\n \"flex-1 min-w-[60px] bg-transparent outline-none\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"disabled:text-[var(--canvas-input-disabled-text)] disabled:cursor-not-allowed\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n />\n </div>\n );\n }\n);\nMultiselectTags.displayName = \"MultiselectTags\";\n\nexport { MultiselectTags };\n\n\n\n\n\n\n\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface MultiselectTagsProps {\n tags?: string[];\n placeholder?: string;\n inputSize?: \"sm\" | \"default\" | \"lg\";\n onAdd?: (tag: string) => void;\n onRemove?: (tag: string) => void;\n disabled?: boolean;\n className?: string;\n}\n\nconst MultiselectTags = React.forwardRef<HTMLInputElement, MultiselectTagsProps>(\n ({ \n tags = [], \n placeholder = \"Add...\", \n inputSize = \"default\", \n onAdd, \n onRemove, \n disabled,\n className \n }, ref) => {\n const [inputValue, setInputValue] = React.useState(\"\");\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && inputValue.trim()) {\n e.preventDefault();\n onAdd?.(inputValue.trim());\n setInputValue(\"\");\n }\n };\n\n return (\n <div\n className={cn(\n \"flex flex-wrap items-center gap-1.5 bg-[var(--canvas-background)] border border-[var(--canvas-border-input)] p-1.5\",\n \"focus-within:border-[var(--canvas-border-input-focus)] focus-within:ring-2 focus-within:ring-[var(--canvas-border-input-focus)] focus-within:ring-offset-2\",\n disabled && \"cursor-not-allowed bg-[var(--canvas-input-disabled-bg)] border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n style={{\n minHeight: `var(--input-${sizeVar}-height)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n }}\n >\n {tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-[var(--canvas-surface-brand)] text-[var(--canvas-primary)] rounded text-xs\"\n >\n {tag}\n {!disabled && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={() => onRemove?.(tag)}\n onKeyDown={(e) => e.key === \"Enter\" && onRemove?.(tag)}\n className=\"cursor-pointer hover:opacity-70\"\n >\n <X className=\"size-3\" />\n </span>\n )}\n </span>\n ))}\n <input\n type=\"text\"\n ref={ref}\n placeholder={placeholder}\n disabled={disabled}\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n className={cn(\n \"flex-1 min-w-[60px] bg-transparent outline-none\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"disabled:text-[var(--canvas-input-disabled-text)] disabled:cursor-not-allowed\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n />\n </div>\n );\n }\n);\nMultiselectTags.displayName = \"MultiselectTags\";\n\nexport { MultiselectTags };\n\n\n\n\n\n\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/radio-group.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\"\nimport { CircleIcon } from \"lucide-react\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction RadioGroup({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n return (\n <RadioGroupPrimitive.Root\n data-slot=\"radio-group\"\n className={cn(\"grid gap-8\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n return (\n <RadioGroupPrimitive.Item\n data-slot=\"radio-group-item\"\n className={cn(\n \"aspect-square size-4 shrink-0 rounded-full border border-[var(--canvas-border-input)] bg-white transition-colors\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"aria-invalid:border-[var(--canvas-border-input-invalid)] aria-invalid:ring-[var(--canvas-border-input-invalid)]/20\",\n \"disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)]\",\n \"data-[state=checked]:border-[var(--canvas-primary)]\",\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"relative flex items-center justify-center\"\n >\n <CircleIcon className=\"absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-[var(--canvas-primary)] text-[var(--canvas-primary)]\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n"
9
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\"\nimport { CircleIcon } from \"lucide-react\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction RadioGroup({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n return (\n <RadioGroupPrimitive.Root\n data-slot=\"radio-group\"\n className={cn(\"grid gap-8\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n return (\n <RadioGroupPrimitive.Item\n data-slot=\"radio-group-item\"\n className={cn(\n \"aspect-square size-4 shrink-0 rounded-full border border-[var(--canvas-border-input)] bg-[var(--canvas-background)] transition-colors\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"aria-invalid:border-[var(--canvas-border-input-invalid)] aria-invalid:ring-[var(--canvas-border-input-invalid)]/20\",\n \"disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)]\",\n \"data-[state=checked]:border-[var(--canvas-primary)]\",\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"relative flex items-center justify-center\"\n >\n <CircleIcon className=\"absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-[var(--canvas-primary)] text-[var(--canvas-primary)]\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/searchbox.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Search } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface SearchboxProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"onChange\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n value?: string;\n onChange?: (value: string) => void;\n}\n\nconst Searchbox = React.forwardRef<HTMLInputElement, SearchboxProps>(\n ({ className, inputSize = \"default\", placeholder = \"Search...\", disabled, value, onChange, ...props }, ref) => {\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n return (\n <div\n className={cn(\n \"flex items-center gap-2 bg-white border border-[var(--canvas-border-input)]\",\n \"focus-within:border-[var(--canvas-border-input-focus)] focus-within:ring-2 focus-within:ring-[var(--canvas-border-input-focus)] focus-within:ring-offset-2\",\n \"has-[:disabled]:cursor-not-allowed has-[:disabled]:bg-[var(--canvas-input-disabled-bg)] has-[:disabled]:border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n }}\n >\n <Search className=\"size-4 shrink-0 text-[var(--canvas-text-muted)]\" />\n <input\n type=\"text\"\n ref={ref}\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n className={cn(\n \"flex-1 bg-transparent outline-none\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"disabled:text-[var(--canvas-input-disabled-text)] disabled:cursor-not-allowed\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n {...props}\n />\n </div>\n );\n }\n);\nSearchbox.displayName = \"Searchbox\";\n\nexport { Searchbox };\n\n\n\n\n\n\n\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Search } from \"lucide-react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface SearchboxProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"onChange\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n value?: string;\n onChange?: (value: string) => void;\n}\n\nconst Searchbox = React.forwardRef<HTMLInputElement, SearchboxProps>(\n ({ className, inputSize = \"default\", placeholder = \"Search...\", disabled, value, onChange, ...props }, ref) => {\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n return (\n <div\n className={cn(\n \"flex items-center gap-2 bg-[var(--canvas-background)] border border-[var(--canvas-border-input)]\",\n \"focus-within:border-[var(--canvas-border-input-focus)] focus-within:ring-2 focus-within:ring-[var(--canvas-border-input-focus)] focus-within:ring-offset-2\",\n \"has-[:disabled]:cursor-not-allowed has-[:disabled]:bg-[var(--canvas-input-disabled-bg)] has-[:disabled]:border-[var(--canvas-input-disabled-border)]\",\n className\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n }}\n >\n <Search className=\"size-4 shrink-0 text-[var(--canvas-text-muted)]\" />\n <input\n type=\"text\"\n ref={ref}\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n className={cn(\n \"flex-1 bg-transparent outline-none\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"disabled:text-[var(--canvas-input-disabled-text)] disabled:cursor-not-allowed\"\n )}\n style={{\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n {...props}\n />\n </div>\n );\n }\n);\nSearchbox.displayName = \"Searchbox\";\n\nexport { Searchbox };\n\n\n\n\n\n\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/select.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst selectTriggerVariants = cva(\n // Base styles using CSS variables\n \"flex w-full items-center justify-between gap-2 bg-white border border-[var(--canvas-border-input)] text-[var(--canvas-text)] whitespace-nowrap transition-colors outline-none focus:border-[var(--canvas-border-input-focus)] focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2 disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)] disabled:text-[var(--canvas-input-disabled-text)] aria-invalid:border-[var(--canvas-border-input-invalid)] data-[placeholder]:text-[var(--canvas-text-placeholder)] [&_svg:not([class*='text-'])]:text-[var(--canvas-text-muted)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 font-[family-name:var(--typo-global-font)]\",\n {\n variants: {\n inputSize: {\n sm: \"h-[var(--input-small-height)] px-[var(--input-small-px)] text-[length:var(--input-small-font-size)] rounded-[var(--input-small-radius)]\",\n default: \"h-[var(--input-standard-height)] px-[var(--input-standard-px)] text-[length:var(--input-standard-font-size)] rounded-[var(--input-standard-radius)]\",\n lg: \"h-[var(--input-large-height)] px-[var(--input-large-px)] text-[length:var(--input-large-font-size)] rounded-[var(--input-large-radius)]\",\n },\n },\n defaultVariants: {\n inputSize: \"default\",\n },\n }\n)\n\nfunction Select({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />\n}\n\nfunction SelectGroup({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />\n}\n\nfunction SelectValue({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />\n}\n\nfunction SelectTrigger({\n className,\n inputSize,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> &\n VariantProps<typeof selectTriggerVariants>) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={inputSize}\n className={cn(selectTriggerVariants({ inputSize, className }))}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"popper\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className\n )}\n position={position}\n sideOffset={sideOffset}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1\"\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 font-[family-name:var(--typo-global-font)]\",\n className\n )}\n {...props}\n >\n <span\n data-slot=\"select-item-indicator\"\n className=\"absolute right-2 flex size-3.5 items-center justify-center\"\n >\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border pointer-events-none -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n )\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n )\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n selectTriggerVariants,\n}\n"
9
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst selectTriggerVariants = cva(\n // Base styles using CSS variables\n \"flex w-full items-center justify-between gap-2 bg-[var(--canvas-background)] border border-[var(--canvas-border-input)] text-[var(--canvas-text)] whitespace-nowrap transition-colors outline-none focus:border-[var(--canvas-border-input-focus)] focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2 disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)] disabled:text-[var(--canvas-input-disabled-text)] aria-invalid:border-[var(--canvas-border-input-invalid)] data-[placeholder]:text-[var(--canvas-text-placeholder)] [&_svg:not([class*='text-'])]:text-[var(--canvas-text-muted)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 font-[family-name:var(--typo-global-font)]\",\n {\n variants: {\n inputSize: {\n sm: \"h-[var(--input-small-height)] px-[var(--input-small-px)] text-[length:var(--input-small-font-size)] rounded-[var(--input-small-radius)]\",\n default: \"h-[var(--input-standard-height)] px-[var(--input-standard-px)] text-[length:var(--input-standard-font-size)] rounded-[var(--input-standard-radius)]\",\n lg: \"h-[var(--input-large-height)] px-[var(--input-large-px)] text-[length:var(--input-large-font-size)] rounded-[var(--input-large-radius)]\",\n },\n },\n defaultVariants: {\n inputSize: \"default\",\n },\n }\n)\n\nfunction Select({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />\n}\n\nfunction SelectGroup({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />\n}\n\nfunction SelectValue({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />\n}\n\nfunction SelectTrigger({\n className,\n inputSize,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> &\n VariantProps<typeof selectTriggerVariants>) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={inputSize}\n className={cn(selectTriggerVariants({ inputSize, className }))}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"popper\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className\n )}\n position={position}\n sideOffset={sideOffset}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1\"\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 font-[family-name:var(--typo-global-font)]\",\n className\n )}\n {...props}\n >\n <span\n data-slot=\"select-item-indicator\"\n className=\"absolute right-2 flex size-3.5 items-center justify-center\"\n >\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border pointer-events-none -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n )\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n )\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n selectTriggerVariants,\n}\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/selectable-pills.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface PillOption {\n id: string;\n label: string;\n}\n\nexport interface SelectablePillsProps {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n options: PillOption[];\n selected: string[];\n onSelectionChange: (selected: string[]) => void;\n allowMultiple?: boolean;\n className?: string;\n disabled?: boolean;\n}\n\nconst SelectablePills = React.forwardRef<HTMLDivElement, SelectablePillsProps>(\n ({ \n inputSize = \"default\", \n options, \n selected, \n onSelectionChange,\n allowMultiple = true,\n className,\n disabled,\n }, ref) => {\n // Size mappings - using fixed values that scale appropriately\n const sizeStyles = {\n sm: {\n pill: \"h-7 px-2.5 text-xs gap-1\",\n container: \"gap-2\",\n },\n default: {\n pill: \"h-9 px-3.5 text-sm gap-1.5\",\n container: \"gap-3\",\n },\n lg: {\n pill: \"h-11 px-4 text-base gap-2\",\n container: \"gap-4\",\n },\n };\n\n const styles = sizeStyles[inputSize];\n\n const handlePillClick = (optionId: string) => {\n if (disabled) return;\n\n if (allowMultiple) {\n // Toggle selection\n if (selected.includes(optionId)) {\n onSelectionChange(selected.filter(id => id !== optionId));\n } else {\n onSelectionChange([...selected, optionId]);\n }\n } else {\n // Single selection - toggle or replace\n if (selected.includes(optionId)) {\n onSelectionChange([]);\n } else {\n onSelectionChange([optionId]);\n }\n }\n };\n\n return (\n <div \n ref={ref}\n className={cn(\n \"flex flex-wrap\",\n styles.container,\n className\n )}\n >\n {options.map((option) => {\n const isSelected = selected.includes(option.id);\n \n return (\n <button\n key={option.id}\n type=\"button\"\n onClick={() => handlePillClick(option.id)}\n disabled={disabled}\n className={cn(\n \"inline-flex items-center justify-center rounded-[var(--radius-xs)] border transition-colors\",\n \"font-medium whitespace-nowrap\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n styles.pill,\n isSelected\n ? \"bg-[var(--canvas-surface-brand)] border-[var(--canvas-primary)] text-[var(--canvas-primary)]\"\n : \"bg-white border-[var(--canvas-border)] text-[var(--canvas-text-muted)] hover:border-[var(--canvas-text-muted)]\"\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n }\n);\n\nSelectablePills.displayName = \"SelectablePills\";\n\nexport { SelectablePills };\n\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface PillOption {\n id: string;\n label: string;\n}\n\nexport interface SelectablePillsProps {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n options: PillOption[];\n selected: string[];\n onSelectionChange: (selected: string[]) => void;\n allowMultiple?: boolean;\n className?: string;\n disabled?: boolean;\n}\n\nconst SelectablePills = React.forwardRef<HTMLDivElement, SelectablePillsProps>(\n ({ \n inputSize = \"default\", \n options, \n selected, \n onSelectionChange,\n allowMultiple = true,\n className,\n disabled,\n }, ref) => {\n // Size mappings - using fixed values that scale appropriately\n const sizeStyles = {\n sm: {\n pill: \"h-7 px-2.5 text-xs gap-1\",\n container: \"gap-2\",\n },\n default: {\n pill: \"h-9 px-3.5 text-sm gap-1.5\",\n container: \"gap-3\",\n },\n lg: {\n pill: \"h-11 px-4 text-base gap-2\",\n container: \"gap-4\",\n },\n };\n\n const styles = sizeStyles[inputSize];\n\n const handlePillClick = (optionId: string) => {\n if (disabled) return;\n\n if (allowMultiple) {\n // Toggle selection\n if (selected.includes(optionId)) {\n onSelectionChange(selected.filter(id => id !== optionId));\n } else {\n onSelectionChange([...selected, optionId]);\n }\n } else {\n // Single selection - toggle or replace\n if (selected.includes(optionId)) {\n onSelectionChange([]);\n } else {\n onSelectionChange([optionId]);\n }\n }\n };\n\n return (\n <div \n ref={ref}\n className={cn(\n \"flex flex-wrap\",\n styles.container,\n className\n )}\n >\n {options.map((option) => {\n const isSelected = selected.includes(option.id);\n \n return (\n <button\n key={option.id}\n type=\"button\"\n onClick={() => handlePillClick(option.id)}\n disabled={disabled}\n className={cn(\n \"inline-flex items-center justify-center rounded-[var(--radius-xs)] border transition-colors\",\n \"font-medium whitespace-nowrap\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n styles.pill,\n isSelected\n ? \"bg-[var(--canvas-surface-brand)] border-[var(--canvas-primary)] text-[var(--canvas-primary)]\"\n : \"bg-[var(--canvas-background)] border-[var(--canvas-border)] text-[var(--canvas-text-muted)] hover:border-[var(--canvas-text-muted)]\"\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n }\n);\n\nSelectablePills.displayName = \"SelectablePills\";\n\nexport { SelectablePills };\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [],
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/slider.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface SliderProps\n extends Omit<React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>, \"value\" | \"onValueChange\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n value?: number[];\n onValueChange?: (value: number[]) => void;\n showLabel?: boolean;\n labelFormatter?: (value: number[]) => string;\n}\n\nconst Slider = React.forwardRef<\n React.ComponentRef<typeof SliderPrimitive.Root>,\n SliderProps\n>(({ \n className, \n inputSize = \"default\", \n value, \n onValueChange, \n showLabel = true,\n labelFormatter,\n min = 0,\n max = 100,\n step = 1,\n ...props \n}, ref) => {\n // Size mappings\n const sizeStyles = {\n sm: {\n trackHeight: \"h-1\",\n thumbSize: \"size-3\",\n labelClass: \"text-xs\",\n },\n default: {\n trackHeight: \"h-1.5\",\n thumbSize: \"size-4\",\n labelClass: \"text-sm\",\n },\n lg: {\n trackHeight: \"h-2\",\n thumbSize: \"size-5\",\n labelClass: \"text-base\",\n },\n };\n\n const styles = sizeStyles[inputSize];\n\n // Default label formatter\n const formatLabel = labelFormatter || ((values: number[]) => {\n if (values.length === 2) {\n return `${values[0]} - ${values[1]}`;\n }\n return `${values[0]}`;\n });\n\n return (\n <div className=\"flex flex-col gap-[var(--spacing-xs)]\">\n <SliderPrimitive.Root\n ref={ref}\n min={min}\n max={max}\n step={step}\n value={value}\n onValueChange={onValueChange}\n className={cn(\n \"relative flex w-full touch-none select-none items-center\",\n className\n )}\n {...props}\n >\n <SliderPrimitive.Track\n className={cn(\n \"relative w-full grow overflow-hidden rounded-full bg-[var(--canvas-border)]\",\n styles.trackHeight\n )}\n >\n <SliderPrimitive.Range className=\"absolute h-full bg-[var(--canvas-primary)]\" />\n </SliderPrimitive.Track>\n {(value || [0]).map((_, index) => (\n <SliderPrimitive.Thumb\n key={index}\n className={cn(\n \"block rounded-full border-2 border-white bg-[var(--canvas-primary)]\",\n \"shadow-[0px_1px_2px_0px_rgba(0,0,0,0.08)]\",\n \"ring-offset-background transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n styles.thumbSize\n )}\n />\n ))}\n </SliderPrimitive.Root>\n {showLabel && value && (\n <p \n className={cn(\n \"text-center text-[var(--canvas-text-muted)]\",\n styles.labelClass\n )}\n >\n {formatLabel(value)}\n </p>\n )}\n </div>\n );\n});\n\nSlider.displayName = \"Slider\";\n\nexport { Slider };\n\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface SliderProps\n extends Omit<React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>, \"value\" | \"onValueChange\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n value?: number[];\n onValueChange?: (value: number[]) => void;\n showLabel?: boolean;\n labelFormatter?: (value: number[]) => string;\n}\n\nconst Slider = React.forwardRef<\n React.ComponentRef<typeof SliderPrimitive.Root>,\n SliderProps\n>(({ \n className, \n inputSize = \"default\", \n value, \n onValueChange, \n showLabel = true,\n labelFormatter,\n min = 0,\n max = 100,\n step = 1,\n ...props \n}, ref) => {\n // Size mappings\n const sizeStyles = {\n sm: {\n trackHeight: \"h-1\",\n thumbSize: \"size-3\",\n labelClass: \"text-xs\",\n },\n default: {\n trackHeight: \"h-1.5\",\n thumbSize: \"size-4\",\n labelClass: \"text-sm\",\n },\n lg: {\n trackHeight: \"h-2\",\n thumbSize: \"size-5\",\n labelClass: \"text-base\",\n },\n };\n\n const styles = sizeStyles[inputSize];\n\n // Default label formatter\n const formatLabel = labelFormatter || ((values: number[]) => {\n if (values.length === 2) {\n return `${values[0]} - ${values[1]}`;\n }\n return `${values[0]}`;\n });\n\n return (\n <div className=\"flex flex-col gap-[var(--spacing-xs)]\">\n <SliderPrimitive.Root\n ref={ref}\n min={min}\n max={max}\n step={step}\n value={value}\n onValueChange={onValueChange}\n className={cn(\n \"relative flex w-full touch-none select-none items-center\",\n className\n )}\n {...props}\n >\n <SliderPrimitive.Track\n className={cn(\n \"relative w-full grow overflow-hidden rounded-full bg-[var(--canvas-border)]\",\n styles.trackHeight\n )}\n >\n <SliderPrimitive.Range className=\"absolute h-full bg-[var(--canvas-primary)]\" />\n </SliderPrimitive.Track>\n {(value || [0]).map((_, index) => (\n <SliderPrimitive.Thumb\n key={index}\n className={cn(\n \"block rounded-full border-2 border-[var(--canvas-background)] bg-[var(--canvas-primary)]\",\n \"shadow-[0px_1px_2px_0px_rgba(0,0,0,0.08)]\",\n \"ring-offset-background transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n styles.thumbSize\n )}\n />\n ))}\n </SliderPrimitive.Root>\n {showLabel && value && (\n <p \n className={cn(\n \"text-center text-[var(--canvas-text-muted)]\",\n styles.labelClass\n )}\n >\n {formatLabel(value)}\n </p>\n )}\n </div>\n );\n});\n\nSlider.displayName = \"Slider\";\n\nexport { Slider };\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/switch.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SwitchPrimitive from \"@radix-ui/react-switch\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Switch({\n className,\n ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-colors\",\n \"data-[state=checked]:bg-[var(--canvas-primary)] data-[state=unchecked]:bg-[var(--canvas-border)]\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:data-[state=checked]:bg-[var(--canvas-input-disabled-text)] disabled:data-[state=unchecked]:bg-[var(--canvas-input-disabled-border)]\",\n className\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"pointer-events-none block size-4 rounded-full bg-white ring-0 transition-transform\",\n \"data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0\"\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n"
9
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SwitchPrimitive from \"@radix-ui/react-switch\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Switch({\n className,\n ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-colors\",\n \"data-[state=checked]:bg-[var(--canvas-primary)] data-[state=unchecked]:bg-[var(--canvas-border)]\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-[var(--canvas-border-input-focus)] focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:data-[state=checked]:bg-[var(--canvas-input-disabled-text)] disabled:data-[state=unchecked]:bg-[var(--canvas-input-disabled-border)]\",\n className\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"pointer-events-none block size-4 rounded-full bg-[var(--canvas-background)] ring-0 transition-transform\",\n \"data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0\"\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/text-input.tsx",
8
8
  "type": "registry:ui",
9
- "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface TextInputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n}\n\nconst TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(\n ({ className, inputSize = \"default\", disabled, ...props }, ref) => {\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n return (\n <input\n type=\"text\"\n ref={ref}\n disabled={disabled}\n className={cn(\n \"w-full bg-white border border-[var(--canvas-border-input)]\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"focus:outline-none focus:border-[var(--canvas-border-input-focus)] focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)] disabled:text-[var(--canvas-input-disabled-text)]\",\n className\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n {...props}\n />\n );\n }\n);\nTextInput.displayName = \"TextInput\";\n\nexport { TextInput };\n\n\n\n\n\n\n\n"
9
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nexport interface TextInputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n inputSize?: \"sm\" | \"default\" | \"lg\";\n}\n\nconst TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(\n ({ className, inputSize = \"default\", disabled, ...props }, ref) => {\n const sizeVar = inputSize === \"default\" ? \"standard\" : inputSize === \"sm\" ? \"small\" : \"large\";\n\n return (\n <input\n type=\"text\"\n ref={ref}\n disabled={disabled}\n className={cn(\n \"w-full bg-[var(--canvas-background)] border border-[var(--canvas-border-input)]\",\n \"text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)]\",\n \"focus:outline-none focus:border-[var(--canvas-border-input-focus)] focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)] disabled:text-[var(--canvas-input-disabled-text)]\",\n className\n )}\n style={{\n height: `var(--input-${sizeVar}-height)`,\n paddingLeft: `var(--input-${sizeVar}-px)`,\n paddingRight: `var(--input-${sizeVar}-px)`,\n borderRadius: `var(--input-${sizeVar}-radius)`,\n fontSize: `var(--input-${sizeVar}-font-size)`,\n }}\n {...props}\n />\n );\n }\n);\nTextInput.displayName = \"TextInput\";\n\nexport { TextInput };\n\n\n\n\n\n\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [],
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "path": "components/ui/textarea.tsx",
8
8
  "type": "registry:ui",
9
- "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../lib/utils\"\n\nconst textareaVariants = cva(\n // Base styles using CSS variables\n \"flex w-full bg-white border border-[var(--canvas-border-input)] text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)] transition-colors resize-none focus:outline-none focus:border-[var(--canvas-border-input-focus)] focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2 disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)] disabled:text-[var(--canvas-input-disabled-text)] aria-invalid:border-[var(--canvas-border-input-invalid)]\",\n {\n variants: {\n inputSize: {\n sm: \"min-h-[60px] px-[var(--input-small-px)] py-2 text-[length:var(--input-small-font-size)] rounded-[var(--input-small-radius)]\",\n default: \"min-h-[80px] px-[var(--input-standard-px)] py-2 text-[length:var(--input-standard-font-size)] rounded-[var(--input-standard-radius)]\",\n lg: \"min-h-[120px] px-[var(--input-large-px)] py-3 text-[length:var(--input-large-font-size)] rounded-[var(--input-large-radius)]\",\n expandable: \"min-h-[var(--input-expandable-height)] px-[var(--input-expandable-px)] py-2 text-[length:var(--input-expandable-font-size)] rounded-[var(--input-expandable-radius)]\",\n },\n },\n defaultVariants: {\n inputSize: \"default\",\n },\n }\n)\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n VariantProps<typeof textareaVariants> {}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, inputSize, ...props }, ref) => {\n return (\n <textarea\n className={cn(textareaVariants({ inputSize, className }))}\n ref={ref}\n {...props}\n />\n )\n }\n)\nTextarea.displayName = \"Textarea\"\n\nexport { Textarea, textareaVariants }\n\n\n\n\n\n\n\n\n"
9
+ "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../lib/utils\"\n\nconst textareaVariants = cva(\n // Base styles using CSS variables\n \"flex w-full bg-[var(--canvas-background)] border border-[var(--canvas-border-input)] text-[var(--canvas-text)] placeholder:text-[var(--canvas-text-placeholder)] transition-colors resize-none focus:outline-none focus:border-[var(--canvas-border-input-focus)] focus:ring-2 focus:ring-[var(--canvas-border-input-focus)] focus:ring-offset-2 disabled:cursor-not-allowed disabled:bg-[var(--canvas-input-disabled-bg)] disabled:border-[var(--canvas-input-disabled-border)] disabled:text-[var(--canvas-input-disabled-text)] aria-invalid:border-[var(--canvas-border-input-invalid)]\",\n {\n variants: {\n inputSize: {\n sm: \"min-h-[60px] px-[var(--input-small-px)] py-2 text-[length:var(--input-small-font-size)] rounded-[var(--input-small-radius)]\",\n default: \"min-h-[80px] px-[var(--input-standard-px)] py-2 text-[length:var(--input-standard-font-size)] rounded-[var(--input-standard-radius)]\",\n lg: \"min-h-[120px] px-[var(--input-large-px)] py-3 text-[length:var(--input-large-font-size)] rounded-[var(--input-large-radius)]\",\n expandable: \"min-h-[var(--input-expandable-height)] px-[var(--input-expandable-px)] py-2 text-[length:var(--input-expandable-font-size)] rounded-[var(--input-expandable-radius)]\",\n },\n },\n defaultVariants: {\n inputSize: \"default\",\n },\n }\n)\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n VariantProps<typeof textareaVariants> {}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, inputSize, ...props }, ref) => {\n return (\n <textarea\n className={cn(textareaVariants({ inputSize, className }))}\n ref={ref}\n {...props}\n />\n )\n }\n)\nTextarea.displayName = \"Textarea\"\n\nexport { Textarea, textareaVariants }\n\n\n\n\n\n\n\n\n"
10
10
  }
11
11
  ],
12
12
  "dependencies": [
@@ -19,6 +19,15 @@
19
19
  --canvas-flair-bg: #093378;
20
20
  --canvas-destructive: #ef4444;
21
21
  --canvas-transparent: transparent;
22
+
23
+ /* Status Colors */
24
+ --canvas-success: #08875d;
25
+ --canvas-success-surface: #edfdf8;
26
+ --canvas-warning: #d97706;
27
+ --canvas-warning-surface: #fffbeb;
28
+ --canvas-info: #2563eb;
29
+ --canvas-info-surface: #eff6ff;
30
+ --canvas-destructive-surface: #fef2f2;
22
31
 
23
32
  /* Text Colors */
24
33
  --canvas-text: #0d121c;