shadcn-glass-ui 1.0.11 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +213 -0
- package/README.md +174 -17
- package/context7.json +58 -0
- package/dist/cli/index.cjs +470 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.js +469 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/components.cjs +4 -4
- package/dist/components.d.ts +153 -22
- package/dist/components.js +2 -2
- package/dist/hooks.cjs +2 -2
- package/dist/index.cjs +872 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -2390
- package/dist/index.js +844 -3
- package/dist/index.js.map +1 -1
- package/dist/r/ai-card-glass.json +1 -1
- package/dist/r/avatar-glass.json +1 -1
- package/dist/r/circular-metric-glass.json +1 -1
- package/dist/r/circular-progress-glass.json +1 -1
- package/dist/r/combobox-glass.json +1 -1
- package/dist/r/flag-alert-glass.json +1 -1
- package/dist/r/flags-section-glass.json +1 -1
- package/dist/r/insight-card-glass.json +26 -0
- package/dist/r/interactive-card.json +1 -1
- package/dist/r/language-bar-glass.json +1 -1
- package/dist/r/metric-card-glass.json +3 -2
- package/dist/r/metrics-grid-glass.json +1 -1
- package/dist/r/modal-glass.json +1 -1
- package/dist/r/progress-glass.json +1 -1
- package/dist/r/registry.json +19 -1
- package/dist/r/segmented-control-glass.json +1 -1
- package/dist/r/sparkline-glass.json +26 -0
- package/dist/r/stepper-glass.json +41 -0
- package/dist/r/tabs-glass.json +1 -1
- package/dist/r/trust-score-card-glass.json +1 -1
- package/dist/r/year-card-glass.json +1 -1
- package/dist/shadcn-glass-ui.css +1 -1
- package/dist/{theme-context-XtasSxRT.cjs → theme-context-CVW50BKW.cjs} +2 -2
- package/dist/{theme-context-XtasSxRT.cjs.map → theme-context-CVW50BKW.cjs.map} +1 -1
- package/dist/themes.cjs +1 -1
- package/dist/trust-score-card-glass-BcZbul0P.js +26895 -0
- package/dist/trust-score-card-glass-BcZbul0P.js.map +1 -0
- package/dist/trust-score-card-glass-r3qM09Jp.cjs +27689 -0
- package/dist/trust-score-card-glass-r3qM09Jp.cjs.map +1 -0
- package/dist/{use-focus-BbpE2qGq.cjs → use-focus-ZE8ozmZE.cjs} +2 -2
- package/dist/{use-focus-BbpE2qGq.cjs.map → use-focus-ZE8ozmZE.cjs.map} +1 -1
- package/dist/{use-wallpaper-tint-CIqtoETa.cjs → use-wallpaper-tint-BuS80tbN.cjs} +2 -2
- package/dist/{use-wallpaper-tint-CIqtoETa.cjs.map → use-wallpaper-tint-BuS80tbN.cjs.map} +1 -1
- package/dist/{utils-CGCOTvxT.js → utils-CcyeqpKQ.js} +1 -1
- package/dist/{utils-CGCOTvxT.js.map → utils-CcyeqpKQ.js.map} +1 -1
- package/dist/{utils-CriE74ig.cjs → utils-DLXayspX.cjs} +2 -2
- package/dist/{utils-CriE74ig.cjs.map → utils-DLXayspX.cjs.map} +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +1 -1
- package/docs/AI_IMPROVEMENTS_COMPLETE.md +574 -0
- package/docs/AI_USAGE.md +1328 -0
- package/docs/API_PATTERNS_COMPARISON.md +418 -0
- package/docs/BEST_PRACTICES.md +800 -0
- package/docs/COMPLIANCE_CHECKLIST.md +307 -0
- package/docs/COMPLIANCE_TESTING.md +436 -0
- package/docs/COMPONENTS_CATALOG.md +1076 -0
- package/docs/CSS_VARIABLES_AUDIT.md +306 -0
- package/docs/CSS_VARIABLES_REFACTORING_PLAN.md +330 -0
- package/docs/EXPORTS_MAP.json +875 -0
- package/docs/EXPORTS_STRUCTURE.md +729 -0
- package/docs/GETTING_STARTED.md +655 -0
- package/docs/METRIC_CARD_API_REDESIGN.md +354 -0
- package/docs/PRIMITIVE_MAPPING.md +404 -0
- package/docs/PUBLISHING.md +593 -0
- package/docs/REGISTRY_SUMMARY.md +96 -0
- package/docs/REGISTRY_USAGE.md +339 -0
- package/docs/SECURITY.md +117 -0
- package/docs/THEME_CREATION_GUIDE.md +455 -0
- package/docs/TOKEN_ARCHITECTURE.md +365 -0
- package/docs/announcements/v1.0.5-devto.md +363 -0
- package/docs/announcements/v1.0.5-reddit.md +115 -0
- package/docs/announcements/v1.0.5-twitter.md +70 -0
- package/docs/api/README.md +725 -0
- package/docs/api/functions/ThemeProvider.md +21 -0
- package/docs/api/functions/cn.md +27 -0
- package/docs/api/functions/getNextTheme.md +21 -0
- package/docs/api/functions/getThemeConfig.md +21 -0
- package/docs/api/functions/useFocus.md +53 -0
- package/docs/api/functions/useHover.md +47 -0
- package/docs/api/functions/useResponsive.md +31 -0
- package/docs/api/functions/useTheme.md +15 -0
- package/docs/api/functions/useWallpaperTint.md +36 -0
- package/docs/api/globals.md +139 -0
- package/docs/api/interfaces/AlertGlassProps.md +131 -0
- package/docs/api/interfaces/AvatarGlassProps.md +114 -0
- package/docs/api/interfaces/BadgeGlassProps.md +118 -0
- package/docs/api/interfaces/ButtonGlassProps.md +179 -0
- package/docs/api/interfaces/CheckboxGlassProps.md +125 -0
- package/docs/api/interfaces/DropdownGlassProps.md +123 -0
- package/docs/api/interfaces/DropdownItem.md +53 -0
- package/docs/api/interfaces/GlassCardProps.md +151 -0
- package/docs/api/interfaces/InputGlassProps.md +169 -0
- package/docs/api/interfaces/NotificationGlassProps.md +67 -0
- package/docs/api/interfaces/ProgressGlassProps.md +49 -0
- package/docs/api/interfaces/SkeletonGlassProps.md +41 -0
- package/docs/api/interfaces/SliderGlassProps.md +107 -0
- package/docs/api/interfaces/TabItem.md +25 -0
- package/docs/api/interfaces/ThemeConfig.md +25 -0
- package/docs/api/interfaces/ThemeContextValue.md +47 -0
- package/docs/api/interfaces/ToggleGlassProps.md +59 -0
- package/docs/api/interfaces/TooltipGlassProps.md +119 -0
- package/docs/api/type-aliases/AlertType.md +11 -0
- package/docs/api/type-aliases/AlertVariant.md +11 -0
- package/docs/api/type-aliases/AvatarSize.md +11 -0
- package/docs/api/type-aliases/AvatarStatus.md +13 -0
- package/docs/api/type-aliases/BadgeSize.md +11 -0
- package/docs/api/type-aliases/BadgeVariant.md +11 -0
- package/docs/api/type-aliases/ButtonGlassSize.md +11 -0
- package/docs/api/type-aliases/ButtonGlassVariant.md +11 -0
- package/docs/api/type-aliases/DropdownAlign.md +11 -0
- package/docs/api/type-aliases/GlowType.md +11 -0
- package/docs/api/type-aliases/InputGlassSize.md +11 -0
- package/docs/api/type-aliases/IntensityType.md +11 -0
- package/docs/api/type-aliases/ModalSize.md +11 -0
- package/docs/api/type-aliases/NotificationType.md +11 -0
- package/docs/api/type-aliases/PaddingType.md +11 -0
- package/docs/api/type-aliases/ProgressGradient.md +11 -0
- package/docs/api/type-aliases/ProgressSize.md +11 -0
- package/docs/api/type-aliases/SkeletonVariant.md +11 -0
- package/docs/api/type-aliases/Theme.md +11 -0
- package/docs/api/type-aliases/ToggleGlassSize.md +11 -0
- package/docs/api/type-aliases/TooltipPosition.md +11 -0
- package/docs/api/variables/AICardGlass.md +11 -0
- package/docs/api/variables/AlertGlass.md +11 -0
- package/docs/api/variables/AvatarGlass.md +11 -0
- package/docs/api/variables/BadgeGlass.md +11 -0
- package/docs/api/variables/BaseProgressGlass.md +11 -0
- package/docs/api/variables/ButtonGlass.md +11 -0
- package/docs/api/variables/CareerStatsGlass.md +11 -0
- package/docs/api/variables/CareerStatsHeaderGlass.md +11 -0
- package/docs/api/variables/CheckboxGlass.md +11 -0
- package/docs/api/variables/CircularMetricGlass.md +22 -0
- package/docs/api/variables/CircularProgressGlass.md +11 -0
- package/docs/api/variables/ComboBoxGlass.md +27 -0
- package/docs/api/variables/ContributionMetricsGlass.md +11 -0
- package/docs/api/variables/DropdownGlass.md +11 -0
- package/docs/api/variables/ExpandableHeaderGlass.md +11 -0
- package/docs/api/variables/FlagAlertGlass.md +11 -0
- package/docs/api/variables/FlagsSectionGlass.md +11 -0
- package/docs/api/variables/FormFieldWrapper.md +44 -0
- package/docs/api/variables/GlassCard.md +11 -0
- package/docs/api/variables/HeaderBrandingGlass.md +11 -0
- package/docs/api/variables/HeaderNavGlass.md +11 -0
- package/docs/api/variables/IconButtonGlass.md +11 -0
- package/docs/api/variables/InputGlass.md +11 -0
- package/docs/api/variables/InteractiveCard.md +45 -0
- package/docs/api/variables/LanguageBarGlass.md +11 -0
- package/docs/api/variables/MetricCardGlass.md +11 -0
- package/docs/api/variables/MetricsGridGlass.md +11 -0
- package/docs/api/variables/ModalGlass.md +72 -0
- package/docs/api/variables/NotificationGlass.md +11 -0
- package/docs/api/variables/PopoverGlass.md +11 -0
- package/docs/api/variables/ProfileAvatarGlass.md +11 -0
- package/docs/api/variables/ProfileHeaderGlass.md +11 -0
- package/docs/api/variables/ProgressGlass.md +11 -0
- package/docs/api/variables/ProjectsListGlass.md +11 -0
- package/docs/api/variables/RainbowProgressGlass.md +11 -0
- package/docs/api/variables/RepositoryCardGlass.md +11 -0
- package/docs/api/variables/RepositoryHeaderGlass.md +11 -0
- package/docs/api/variables/RepositoryMetadataGlass.md +11 -0
- package/docs/api/variables/SearchBoxGlass.md +11 -0
- package/docs/api/variables/SegmentedControlGlass.md +11 -0
- package/docs/api/variables/SkeletonGlass.md +11 -0
- package/docs/api/variables/SliderGlass.md +11 -0
- package/docs/api/variables/SortDropdownGlass.md +11 -0
- package/docs/api/variables/StatItemGlass.md +11 -0
- package/docs/api/variables/StatusIndicatorGlass.md +11 -0
- package/docs/api/variables/THEMES.md +11 -0
- package/docs/api/variables/THEME_CONFIG.md +11 -0
- package/docs/api/variables/TabsGlass.md +52 -0
- package/docs/api/variables/ThemeToggleGlass.md +11 -0
- package/docs/api/variables/ToggleGlass.md +11 -0
- package/docs/api/variables/TooltipGlass.md +11 -0
- package/docs/api/variables/TouchTarget.md +35 -0
- package/docs/api/variables/TrustScoreCardGlass.md +11 -0
- package/docs/api/variables/TrustScoreDisplayGlass.md +11 -0
- package/docs/api/variables/UserInfoGlass.md +11 -0
- package/docs/api/variables/UserStatsLineGlass.md +11 -0
- package/docs/api/variables/YearCardGlass.md +11 -0
- package/docs/api/variables/alertVariants.md +21 -0
- package/docs/api/variables/avatarSizes.md +21 -0
- package/docs/api/variables/badgeVariants.md +21 -0
- package/docs/api/variables/buttonGlassVariants.md +21 -0
- package/docs/api/variables/cardIntensity.md +21 -0
- package/docs/api/variables/dropdownAlign.md +21 -0
- package/docs/api/variables/inputVariants.md +21 -0
- package/docs/api/variables/modalSizes.md +21 -0
- package/docs/api/variables/notificationVariants.md +21 -0
- package/docs/api/variables/progressSizes.md +21 -0
- package/docs/api/variables/shadcnAlertVariants.md +21 -0
- package/docs/api/variables/shadcnBadgeVariants.md +21 -0
- package/docs/api/variables/shadcnButtonVariants.md +21 -0
- package/docs/api/variables/skeletonVariants.md +21 -0
- package/docs/api/variables/statusSizes.md +21 -0
- package/docs/api/variables/toggleSizes.md +21 -0
- package/docs/api/variables/tooltipPositions.md +21 -0
- package/docs/design-system/UI_DESIGN.md +628 -0
- package/docs/migration/CSS_VARIABLES_MIGRATION_2.0.md +325 -0
- package/docs/migration/modal-glass-compound-api.md +458 -0
- package/docs/migration/select-to-combobox.md +386 -0
- package/docs/migration/tabs-glass-compound-api.md +579 -0
- package/docs/technical/DEPENDENCIES.md +291 -0
- package/docs/visual-testing-guide.md +324 -0
- package/package.json +20 -3
- package/dist/trust-score-card-glass-CNcQveNY.cjs +0 -8231
- package/dist/trust-score-card-glass-CNcQveNY.cjs.map +0 -1
- package/dist/trust-score-card-glass-CowcDyxH.js +0 -7795
- package/dist/trust-score-card-glass-CowcDyxH.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/lib/variants/dropdown-glass-variants.ts","../src/lib/variants/alert-variants.ts","../src/lib/variants/badge-variants.ts","../src/lib/variants/button-variants.ts"],"sourcesContent":["/**\n * DropdownGlass CVA Variants\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport type DropdownAlign = 'left' | 'right';\n\nexport const dropdownAlign = cva('absolute mt-2 min-w-[160px] md:min-w-[200px] rounded-2xl py-1.5 md:py-2', {\n variants: {\n align: {\n left: 'left-0',\n right: 'right-0',\n },\n },\n defaultVariants: {\n align: 'left',\n },\n});\n","/**\n * Alert CVA Variants (shadcn/ui)\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport const alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\n {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive:\n \"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n);\n","/**\n * Badge CVA Variants (shadcn/ui)\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport const badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n);\n","/**\n * Button CVA Variants (shadcn/ui)\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport const buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n"],"mappings":";;;;;;AASA,MAAa,gBAAgB,IAAI,2EAA2E;CAC1G,UAAU,EACR,OAAO;EACL,MAAM;EACN,OAAO;EACR,EACF;CACD,iBAAiB,EACf,OAAO,QACR;CACF,CAAC;ACZF,MAAa,kBAAgB,IAC3B,qOACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,aACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;ACdD,MAAa,kBAAgB,IAC3B,oZACA;CACE,UAAU,EACR,SAAS;EACP,SACE;EACF,WACE;EACF,aACE;EACF,SACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;ACnBD,MAAa,iBAAiB,IAC5B,+bACA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,aACE;GACF,SACE;GACF,WACE;GACF,OACE;GACF,MAAM;GACP;EACD,MAAM;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,WAAW;GACX,WAAW;GACZ;EACF;CACD,iBAAiB;EACf,SAAS;EACT,MAAM;EACP;CACF,CACF"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["StepperRoot: FC<StepperRootProps>","indicatorStyles: CSSProperties","connectorStyles: CSSProperties","labelStyles: CSSProperties","descriptionStyles: CSSProperties","StepperContent: FC<StepperContentProps>","_extends","ownKeys","r","_objectSpread","_defineProperty","_toPropertyKey","_toPrimitive","r","configLabelKey: string"],"sources":["../src/lib/variants/stepper-glass-variants.ts","../src/components/glass/ui/stepper-glass.tsx","../node_modules/recharts/es6/component/DefaultLegendContent.js","../node_modules/recharts/es6/context/legendPayloadContext.js","../node_modules/recharts/es6/component/Legend.js","../src/components/ui/chart.tsx","../src/lib/variants/dropdown-glass-variants.ts","../src/lib/variants/alert-variants.ts","../src/lib/variants/badge-variants.ts","../src/lib/variants/button-variants.ts"],"sourcesContent":["/**\n * StepperGlass CVA Variants\n *\n * Type-safe variant definitions for the StepperGlass compound component.\n * Extracted for Fast Refresh compatibility and reusability.\n *\n * @module stepper-glass-variants\n */\n\nimport { cva } from 'class-variance-authority';\n\n// ========================================\n// TYPE DEFINITIONS\n// ========================================\n\nexport type StepperOrientation = 'horizontal' | 'vertical';\nexport type StepperVariant = 'numbered' | 'icon' | 'dots';\nexport type StepperSize = 'sm' | 'md' | 'lg';\nexport type StepStatus = 'pending' | 'active' | 'completed' | 'disabled';\n\n// ========================================\n// ROOT VARIANTS\n// ========================================\n\nexport const stepperRootVariants = cva('flex w-full', {\n variants: {\n orientation: {\n horizontal: 'flex-col',\n vertical: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n\n// ========================================\n// LIST VARIANTS\n// ========================================\n\nexport const stepperListVariants = cva('flex', {\n variants: {\n orientation: {\n horizontal: 'flex-row items-center w-full',\n vertical: 'flex-col gap-0',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n\n// ========================================\n// STEP CONTAINER VARIANTS\n// ========================================\n\nexport const stepperStepContainerVariants = cva('relative flex transition-all duration-300', {\n variants: {\n orientation: {\n horizontal: 'flex-col items-center flex-1',\n vertical: 'flex-row items-start gap-3',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n\n// ========================================\n// STEP INDICATOR VARIANTS\n// ========================================\n\nexport const stepperIndicatorVariants = cva(\n 'relative flex items-center justify-center rounded-full font-medium transition-all duration-300 shrink-0',\n {\n variants: {\n size: {\n sm: 'w-8 h-8 text-xs',\n md: 'w-10 h-10 text-sm',\n lg: 'w-12 h-12 text-base',\n },\n variant: {\n numbered: '',\n icon: '',\n dots: '',\n },\n },\n defaultVariants: {\n size: 'md',\n variant: 'numbered',\n },\n compoundVariants: [\n // Dots variant has smaller indicators\n { variant: 'dots', size: 'sm', className: '!w-2.5 !h-2.5' },\n { variant: 'dots', size: 'md', className: '!w-3 !h-3' },\n { variant: 'dots', size: 'lg', className: '!w-4 !h-4' },\n ],\n }\n);\n\n// ========================================\n// CONNECTOR VARIANTS\n// ========================================\n\nexport const stepperConnectorVariants = cva('transition-all duration-500 ease-out', {\n variants: {\n orientation: {\n horizontal: 'h-0.5 flex-1 mx-2 md:mx-3',\n vertical: 'w-0.5 min-h-6 ml-5 my-1',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n\n// ========================================\n// LABEL VARIANTS\n// ========================================\n\nexport const stepperLabelVariants = cva(\n 'font-medium transition-colors duration-300 whitespace-nowrap',\n {\n variants: {\n size: {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n },\n orientation: {\n horizontal: 'mt-2 text-center',\n vertical: '',\n },\n },\n defaultVariants: {\n size: 'md',\n orientation: 'horizontal',\n },\n }\n);\n\n// ========================================\n// DESCRIPTION VARIANTS\n// ========================================\n\nexport const stepperDescriptionVariants = cva('transition-colors duration-300', {\n variants: {\n size: {\n sm: 'text-[10px]',\n md: 'text-xs',\n lg: 'text-sm',\n },\n orientation: {\n horizontal: 'text-center max-w-[100px] md:max-w-[120px]',\n vertical: 'max-w-[200px]',\n },\n },\n defaultVariants: {\n size: 'md',\n orientation: 'horizontal',\n },\n});\n\n// ========================================\n// CONTENT VARIANTS\n// ========================================\n\nexport const stepperContentVariants = cva('animate-in fade-in-0 duration-200', {\n variants: {\n orientation: {\n horizontal: 'mt-6',\n vertical: 'mt-4',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n","/* eslint-disable react-refresh/only-export-components */\n/**\n * StepperGlass Component (Compound API)\n *\n * Glass-themed step indicator with:\n * - Theme-aware styling (glass/light/aurora)\n * - Horizontal and vertical orientations\n * - Numbered, icon, and dots variants\n * - Linear mode (lock future steps)\n * - Animated connector lines\n * - Compound component API for advanced composition\n *\n * @example\n * ```tsx\n * <StepperGlass.Root value=\"step2\" onValueChange={setStep}>\n * <StepperGlass.List>\n * <StepperGlass.Step value=\"step1\" label=\"Account\" description=\"Create your account\" />\n * <StepperGlass.Step value=\"step2\" label=\"Profile\" description=\"Setup your profile\" />\n * <StepperGlass.Step value=\"step3\" label=\"Complete\" description=\"Finish setup\" />\n * </StepperGlass.List>\n * <StepperGlass.Content value=\"step1\">Step 1 content</StepperGlass.Content>\n * <StepperGlass.Content value=\"step2\">Step 2 content</StepperGlass.Content>\n * <StepperGlass.Content value=\"step3\">Step 3 content</StepperGlass.Content>\n * </StepperGlass.Root>\n * ```\n *\n * @accessibility\n * - **Keyboard Navigation:** Arrow keys navigate between steps (WCAG 2.1.1)\n * - **Focus Management:** Visible focus ring using `--focus-glow` (WCAG 2.4.7)\n * - **Screen Readers:** Uses `role=\"tablist\"`, `role=\"tab\"` (WCAG 4.1.3)\n * - **ARIA Attributes:** `aria-current=\"step\"`, `aria-disabled` for state\n * - **Touch Targets:** 44x44px minimum touch targets (WCAG 2.5.5)\n * - **Color Contrast:** All states meet WCAG AA 4.5:1 ratio\n * - **Motion:** Respects `prefers-reduced-motion`\n */\n\nimport {\n forwardRef,\n createContext,\n useContext,\n useMemo,\n useState,\n useCallback,\n useLayoutEffect,\n type CSSProperties,\n type FC,\n type ReactNode,\n} from 'react';\nimport { cn } from '@/lib/utils';\nimport { useFocus } from '@/lib/hooks/use-focus';\nimport { Check } from 'lucide-react';\nimport {\n stepperRootVariants,\n stepperListVariants,\n stepperStepContainerVariants,\n stepperIndicatorVariants,\n stepperConnectorVariants,\n stepperLabelVariants,\n stepperDescriptionVariants,\n stepperContentVariants,\n type StepperOrientation,\n type StepperVariant,\n type StepperSize,\n type StepStatus,\n} from '@/lib/variants/stepper-glass-variants';\nimport '@/glass-theme.css';\n\n// ========================================\n// CONTEXT\n// ========================================\n\ninterface StepperContextValue {\n value: string;\n onValueChange?: (value: string) => void;\n orientation: StepperOrientation;\n variant: StepperVariant;\n size: StepperSize;\n linear: boolean;\n steps: string[];\n registerStep: (value: string, index: number) => void;\n unregisterStep: (value: string) => void;\n}\n\nconst StepperContext = createContext<StepperContextValue | null>(null);\n\nconst useStepperContext = () => {\n const context = useContext(StepperContext);\n if (!context) {\n throw new Error('Stepper compound components must be used within StepperGlass.Root');\n }\n return context;\n};\n\n// ========================================\n// UTILITY: GET STEP STATUS\n// ========================================\n\nfunction getStepStatus(\n stepValue: string,\n currentValue: string,\n steps: string[],\n linear: boolean,\n disabled?: boolean\n): StepStatus {\n if (disabled) return 'disabled';\n\n const stepIndex = steps.indexOf(stepValue);\n const currentIndex = steps.indexOf(currentValue);\n\n if (stepIndex === -1 || currentIndex === -1) return 'pending';\n if (stepIndex === currentIndex) return 'active';\n if (stepIndex < currentIndex) return 'completed';\n if (linear && stepIndex > currentIndex) return 'disabled';\n return 'pending';\n}\n\n// ========================================\n// ROOT COMPONENT\n// ========================================\n\ninterface StepperRootProps {\n /** Current active step value */\n value: string;\n /** Callback when step value changes */\n onValueChange?: (value: string) => void;\n /** Orientation of the stepper */\n orientation?: StepperOrientation;\n /** Visual variant */\n variant?: StepperVariant;\n /** Size of step indicators */\n size?: StepperSize;\n /** Lock future steps (require sequential completion) */\n linear?: boolean;\n /** Child components */\n children: ReactNode;\n /** Optional className */\n className?: string;\n}\n\nconst StepperRoot: FC<StepperRootProps> = ({\n value,\n onValueChange,\n orientation = 'horizontal',\n variant = 'numbered',\n size = 'md',\n linear = false,\n children,\n className,\n}) => {\n const [steps, setSteps] = useState<string[]>([]);\n\n const registerStep = useCallback((stepValue: string, index: number) => {\n setSteps((prev) => {\n if (prev.includes(stepValue)) return prev;\n const newSteps = [...prev];\n // Insert at correct position to maintain order\n newSteps.splice(index, 0, stepValue);\n return newSteps;\n });\n }, []);\n\n const unregisterStep = useCallback((stepValue: string) => {\n setSteps((prev) => prev.filter((s) => s !== stepValue));\n }, []);\n\n const contextValue = useMemo(\n () => ({\n value,\n onValueChange,\n orientation,\n variant,\n size,\n linear,\n steps,\n registerStep,\n unregisterStep,\n }),\n [value, onValueChange, orientation, variant, size, linear, steps, registerStep, unregisterStep]\n );\n\n return (\n <StepperContext.Provider value={contextValue}>\n <div\n className={cn(stepperRootVariants({ orientation }), className)}\n aria-label=\"Progress steps\"\n >\n {children}\n </div>\n </StepperContext.Provider>\n );\n};\n\n// ========================================\n// LIST COMPONENT\n// ========================================\n\ninterface StepperListProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n className?: string;\n}\n\nconst StepperList = forwardRef<HTMLDivElement, StepperListProps>(\n ({ children, className, ...props }, ref) => {\n const { orientation } = useStepperContext();\n\n return (\n <div\n ref={ref}\n role=\"tablist\"\n aria-orientation={orientation}\n className={cn(stepperListVariants({ orientation }), className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nStepperList.displayName = 'StepperList';\n\n// ========================================\n// STEP COMPONENT\n// ========================================\n\ninterface StepperStepProps {\n /** Unique value for this step */\n value: string;\n /** Step label (required for accessibility) */\n label: string;\n /** Optional description */\n description?: string;\n /** Custom icon (for icon variant) */\n icon?: ReactNode;\n /** Completed icon override */\n completedIcon?: ReactNode;\n /** Force disabled state */\n disabled?: boolean;\n /** Optional className */\n className?: string;\n /** Step index for ordering (auto-detected) */\n index?: number;\n}\n\nconst StepperStep = forwardRef<HTMLButtonElement, StepperStepProps>(\n (\n {\n value: stepValue,\n label,\n description,\n icon,\n completedIcon,\n disabled: forcedDisabled,\n className,\n index: providedIndex,\n },\n ref\n ) => {\n const {\n value: currentValue,\n onValueChange,\n orientation,\n variant,\n size,\n linear,\n steps,\n registerStep,\n unregisterStep,\n } = useStepperContext();\n\n const { isFocusVisible, focusProps } = useFocus({ focusVisible: true });\n\n // Track mount order for step registration\n const [mountIndex] = useState(() => providedIndex ?? Date.now());\n\n // Register step on mount\n // Use useLayoutEffect to register before paint\n useLayoutEffect(() => {\n registerStep(stepValue, mountIndex);\n return () => unregisterStep(stepValue);\n }, [stepValue, mountIndex, registerStep, unregisterStep]);\n\n const status = getStepStatus(stepValue, currentValue, steps, linear, forcedDisabled);\n const stepIndex = steps.indexOf(stepValue);\n const isLast = stepIndex === steps.length - 1;\n const isClickable = status !== 'disabled';\n\n // Styles based on status\n const indicatorStyles: CSSProperties = {\n background:\n status === 'completed'\n ? 'var(--stepper-step-completed-bg)'\n : status === 'active'\n ? 'var(--stepper-step-active-bg)'\n : status === 'disabled'\n ? 'var(--stepper-step-disabled-bg)'\n : 'var(--stepper-step-bg)',\n border: `2px solid ${\n status === 'completed'\n ? 'var(--stepper-step-completed-border)'\n : status === 'active'\n ? 'var(--stepper-step-active-border)'\n : status === 'disabled'\n ? 'var(--stepper-step-disabled-border)'\n : 'var(--stepper-step-border)'\n }`,\n color:\n status === 'completed'\n ? 'var(--stepper-step-completed-text)'\n : status === 'active'\n ? 'var(--stepper-step-active-text)'\n : status === 'disabled'\n ? 'var(--stepper-step-disabled-text)'\n : 'var(--stepper-step-text)',\n boxShadow:\n status === 'active'\n ? 'var(--stepper-step-active-glow)'\n : status === 'completed'\n ? 'var(--stepper-step-glow)'\n : isFocusVisible\n ? 'var(--focus-glow)'\n : 'none',\n backdropFilter: 'blur(var(--blur-sm))',\n };\n\n const connectorStyles: CSSProperties = {\n background:\n stepIndex < steps.indexOf(currentValue)\n ? 'var(--stepper-connector-active-bg)'\n : 'var(--stepper-connector-bg)',\n };\n\n const labelStyles: CSSProperties = {\n color:\n status === 'active' || status === 'completed'\n ? 'var(--stepper-label-text)'\n : 'var(--stepper-description-text)',\n };\n\n const descriptionStyles: CSSProperties = {\n color: 'var(--stepper-description-text)',\n };\n\n // Render indicator content\n const renderIndicatorContent = () => {\n if (status === 'completed') {\n if (completedIcon) return completedIcon;\n return <Check className=\"w-4 h-4\" />;\n }\n if (variant === 'icon' && icon) return icon;\n if (variant === 'dots') return null;\n // Numbered variant\n return stepIndex >= 0 ? stepIndex + 1 : '';\n };\n\n const handleClick = () => {\n if (isClickable && onValueChange) {\n onValueChange(stepValue);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (!isClickable) return;\n\n const stepList = e.currentTarget.closest('[role=\"tablist\"]');\n if (!stepList) return;\n\n const allSteps = Array.from(\n stepList.querySelectorAll('[role=\"tab\"]:not([aria-disabled=\"true\"])')\n ) as HTMLButtonElement[];\n const currentIdx = allSteps.indexOf(e.currentTarget as HTMLButtonElement);\n\n let nextIdx = currentIdx;\n const isHorizontal = orientation === 'horizontal';\n\n switch (e.key) {\n case isHorizontal ? 'ArrowRight' : 'ArrowDown':\n e.preventDefault();\n nextIdx = (currentIdx + 1) % allSteps.length;\n break;\n case isHorizontal ? 'ArrowLeft' : 'ArrowUp':\n e.preventDefault();\n nextIdx = currentIdx - 1 < 0 ? allSteps.length - 1 : currentIdx - 1;\n break;\n case 'Home':\n e.preventDefault();\n nextIdx = 0;\n break;\n case 'End':\n e.preventDefault();\n nextIdx = allSteps.length - 1;\n break;\n default:\n return;\n }\n\n const nextStep = allSteps[nextIdx];\n if (nextStep) {\n nextStep.focus();\n const nextValue = nextStep.getAttribute('data-value');\n if (nextValue && onValueChange) {\n onValueChange(nextValue);\n }\n }\n };\n\n // For horizontal, we need step + connector inline\n // For vertical, step is a row with connector below\n if (orientation === 'horizontal') {\n return (\n <>\n <div className={cn(stepperStepContainerVariants({ orientation }), className)}>\n <button\n ref={ref}\n type=\"button\"\n role=\"tab\"\n aria-selected={status === 'active'}\n aria-disabled={!isClickable}\n aria-current={status === 'active' ? 'step' : undefined}\n data-value={stepValue}\n data-status={status}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onFocus={focusProps.onFocus}\n onBlur={focusProps.onBlur}\n disabled={!isClickable}\n className={cn(\n stepperIndicatorVariants({ size, variant }),\n !isClickable && 'cursor-not-allowed opacity-60',\n isClickable && 'cursor-pointer hover:scale-105',\n // Ensure minimum touch target\n 'min-w-[44px] min-h-[44px]'\n )}\n style={indicatorStyles}\n >\n {renderIndicatorContent()}\n </button>\n\n {label && (\n <div className=\"flex flex-col items-center\">\n <span\n className={cn(stepperLabelVariants({ size, orientation }))}\n style={labelStyles}\n >\n {label}\n </span>\n {description && (\n <span\n className={cn(stepperDescriptionVariants({ size, orientation }))}\n style={descriptionStyles}\n >\n {description}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Connector line between steps */}\n {!isLast && (\n <div\n className={cn(stepperConnectorVariants({ orientation }))}\n style={connectorStyles}\n aria-hidden=\"true\"\n />\n )}\n </>\n );\n }\n\n // Vertical orientation\n return (\n <div className=\"flex flex-col\">\n <div className={cn(stepperStepContainerVariants({ orientation }), className)}>\n <button\n ref={ref}\n type=\"button\"\n role=\"tab\"\n aria-selected={status === 'active'}\n aria-disabled={!isClickable}\n aria-current={status === 'active' ? 'step' : undefined}\n data-value={stepValue}\n data-status={status}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onFocus={focusProps.onFocus}\n onBlur={focusProps.onBlur}\n disabled={!isClickable}\n className={cn(\n stepperIndicatorVariants({ size, variant }),\n !isClickable && 'cursor-not-allowed opacity-60',\n isClickable && 'cursor-pointer hover:scale-105',\n 'min-w-[44px] min-h-[44px]'\n )}\n style={indicatorStyles}\n >\n {renderIndicatorContent()}\n </button>\n\n {label && (\n <div className=\"flex flex-col justify-center\">\n <span className={cn(stepperLabelVariants({ size, orientation }))} style={labelStyles}>\n {label}\n </span>\n {description && (\n <span\n className={cn(stepperDescriptionVariants({ size, orientation }))}\n style={descriptionStyles}\n >\n {description}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Vertical connector */}\n {!isLast && (\n <div\n className={cn(stepperConnectorVariants({ orientation }))}\n style={connectorStyles}\n aria-hidden=\"true\"\n />\n )}\n </div>\n );\n }\n);\n\nStepperStep.displayName = 'StepperStep';\n\n// ========================================\n// CONTENT COMPONENT\n// ========================================\n\ninterface StepperContentProps {\n /** Value of the step this content belongs to */\n value: string;\n /** Content to display when step is active */\n children: ReactNode;\n /** Optional className */\n className?: string;\n}\n\nconst StepperContent: FC<StepperContentProps> = ({ value, children, className }) => {\n const { value: currentValue, orientation } = useStepperContext();\n const isActive = currentValue === value;\n\n if (!isActive) return null;\n\n return (\n <div\n role=\"tabpanel\"\n aria-hidden={!isActive}\n className={cn(stepperContentVariants({ orientation }), className)}\n >\n {children}\n </div>\n );\n};\n\n// ========================================\n// EXPORT COMPOUND COMPONENT\n// ========================================\n\nexport const StepperGlass = {\n Root: StepperRoot,\n List: StepperList,\n Step: StepperStep,\n Content: StepperContent,\n};\n\n// Also export individual components for flexibility\nexport { StepperRoot, StepperList, StepperStep, StepperContent };\n\n// Re-export types\nexport type {\n StepperRootProps,\n StepperListProps,\n StepperStepProps,\n StepperContentProps,\n StepperOrientation,\n StepperVariant,\n StepperSize,\n StepStatus,\n};\n","function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @fileOverview Default Legend Content\n */\nimport * as React from 'react';\nimport { clsx } from 'clsx';\nimport { Surface } from '../container/Surface';\nimport { Symbols } from '../shape/Symbols';\nimport { adaptEventsOfChild } from '../util/types';\nimport { resolveDefaultProps } from '../util/resolveDefaultProps';\nvar SIZE = 32;\nvar defaultLegendContentDefaultProps = {\n align: 'center',\n iconSize: 14,\n inactiveColor: '#ccc',\n layout: 'horizontal',\n verticalAlign: 'middle'\n};\nfunction Icon(_ref) {\n var {\n data,\n iconType,\n inactiveColor\n } = _ref;\n var halfSize = SIZE / 2;\n var sixthSize = SIZE / 6;\n var thirdSize = SIZE / 3;\n var color = data.inactive ? inactiveColor : data.color;\n var preferredIcon = iconType !== null && iconType !== void 0 ? iconType : data.type;\n if (preferredIcon === 'none') {\n return null;\n }\n if (preferredIcon === 'plainline') {\n var _data$payload;\n return /*#__PURE__*/React.createElement(\"line\", {\n strokeWidth: 4,\n fill: \"none\",\n stroke: color,\n strokeDasharray: (_data$payload = data.payload) === null || _data$payload === void 0 ? void 0 : _data$payload.strokeDasharray,\n x1: 0,\n y1: halfSize,\n x2: SIZE,\n y2: halfSize,\n className: \"recharts-legend-icon\"\n });\n }\n if (preferredIcon === 'line') {\n return /*#__PURE__*/React.createElement(\"path\", {\n strokeWidth: 4,\n fill: \"none\",\n stroke: color,\n d: \"M0,\".concat(halfSize, \"h\").concat(thirdSize, \"\\n A\").concat(sixthSize, \",\").concat(sixthSize, \",0,1,1,\").concat(2 * thirdSize, \",\").concat(halfSize, \"\\n H\").concat(SIZE, \"M\").concat(2 * thirdSize, \",\").concat(halfSize, \"\\n A\").concat(sixthSize, \",\").concat(sixthSize, \",0,1,1,\").concat(thirdSize, \",\").concat(halfSize),\n className: \"recharts-legend-icon\"\n });\n }\n if (preferredIcon === 'rect') {\n return /*#__PURE__*/React.createElement(\"path\", {\n stroke: \"none\",\n fill: color,\n d: \"M0,\".concat(SIZE / 8, \"h\").concat(SIZE, \"v\").concat(SIZE * 3 / 4, \"h\").concat(-SIZE, \"z\"),\n className: \"recharts-legend-icon\"\n });\n }\n if (/*#__PURE__*/React.isValidElement(data.legendIcon)) {\n var iconProps = _objectSpread({}, data);\n delete iconProps.legendIcon;\n return /*#__PURE__*/React.cloneElement(data.legendIcon, iconProps);\n }\n return /*#__PURE__*/React.createElement(Symbols, {\n fill: color,\n cx: halfSize,\n cy: halfSize,\n size: SIZE,\n sizeType: \"diameter\",\n type: preferredIcon\n });\n}\nfunction Items(props) {\n var {\n payload,\n iconSize,\n layout,\n formatter,\n inactiveColor,\n iconType\n } = props;\n var viewBox = {\n x: 0,\n y: 0,\n width: SIZE,\n height: SIZE\n };\n var itemStyle = {\n display: layout === 'horizontal' ? 'inline-block' : 'block',\n marginRight: 10\n };\n var svgStyle = {\n display: 'inline-block',\n verticalAlign: 'middle',\n marginRight: 4\n };\n return payload.map((entry, i) => {\n var finalFormatter = entry.formatter || formatter;\n var className = clsx({\n 'recharts-legend-item': true,\n [\"legend-item-\".concat(i)]: true,\n inactive: entry.inactive\n });\n if (entry.type === 'none') {\n return null;\n }\n var color = entry.inactive ? inactiveColor : entry.color;\n var finalValue = finalFormatter ? finalFormatter(entry.value, entry, i) : entry.value;\n return /*#__PURE__*/React.createElement(\"li\", _extends({\n className: className,\n style: itemStyle,\n key: \"legend-item-\".concat(i)\n }, adaptEventsOfChild(props, entry, i)), /*#__PURE__*/React.createElement(Surface, {\n width: iconSize,\n height: iconSize,\n viewBox: viewBox,\n style: svgStyle,\n \"aria-label\": \"\".concat(finalValue, \" legend icon\")\n }, /*#__PURE__*/React.createElement(Icon, {\n data: entry,\n iconType: iconType,\n inactiveColor: inactiveColor\n })), /*#__PURE__*/React.createElement(\"span\", {\n className: \"recharts-legend-item-text\",\n style: {\n color\n }\n }, finalValue));\n });\n}\nexport var DefaultLegendContent = outsideProps => {\n var props = resolveDefaultProps(outsideProps, defaultLegendContentDefaultProps);\n var {\n payload,\n layout,\n align\n } = props;\n if (!payload || !payload.length) {\n return null;\n }\n var finalStyle = {\n padding: 0,\n margin: 0,\n textAlign: layout === 'horizontal' ? align : 'left'\n };\n return /*#__PURE__*/React.createElement(\"ul\", {\n className: \"recharts-default-legend\",\n style: finalStyle\n }, /*#__PURE__*/React.createElement(Items, _extends({}, props, {\n payload: payload\n })));\n};","import { useAppSelector } from '../state/hooks';\nimport { selectLegendPayload } from '../state/selectors/legendSelectors';\n\n/**\n * Use this hook in Legend, or anywhere else where you want to read the current Legend items.\n * @return all Legend items ready to be rendered\n */\nexport function useLegendPayload() {\n return useAppSelector(selectLegendPayload);\n}","var _excluded = [\"contextPayload\"];\nfunction _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }\nfunction _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }\nimport * as React from 'react';\nimport { useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useLegendPortal } from '../context/legendPortalContext';\nimport { DefaultLegendContent } from './DefaultLegendContent';\nimport { isNumber } from '../util/DataUtils';\nimport { getUniqPayload } from '../util/payload/getUniqPayload';\nimport { useLegendPayload } from '../context/legendPayloadContext';\nimport { useElementOffset } from '../util/useElementOffset';\nimport { useChartHeight, useChartWidth, useMargin } from '../context/chartLayoutContext';\nimport { setLegendSettings, setLegendSize } from '../state/legendSlice';\nimport { useAppDispatch } from '../state/hooks';\nimport { resolveDefaultProps } from '../util/resolveDefaultProps';\nfunction defaultUniqBy(entry) {\n return entry.value;\n}\nfunction LegendContent(props) {\n var {\n contextPayload\n } = props,\n otherProps = _objectWithoutProperties(props, _excluded);\n var finalPayload = getUniqPayload(contextPayload, props.payloadUniqBy, defaultUniqBy);\n var contentProps = _objectSpread(_objectSpread({}, otherProps), {}, {\n payload: finalPayload\n });\n if (/*#__PURE__*/React.isValidElement(props.content)) {\n return /*#__PURE__*/React.cloneElement(props.content, contentProps);\n }\n if (typeof props.content === 'function') {\n return /*#__PURE__*/React.createElement(props.content, contentProps);\n }\n return /*#__PURE__*/React.createElement(DefaultLegendContent, contentProps);\n}\nfunction getDefaultPosition(style, props, margin, chartWidth, chartHeight, box) {\n var {\n layout,\n align,\n verticalAlign\n } = props;\n var hPos, vPos;\n if (!style || (style.left === undefined || style.left === null) && (style.right === undefined || style.right === null)) {\n if (align === 'center' && layout === 'vertical') {\n hPos = {\n left: ((chartWidth || 0) - box.width) / 2\n };\n } else {\n hPos = align === 'right' ? {\n right: margin && margin.right || 0\n } : {\n left: margin && margin.left || 0\n };\n }\n }\n if (!style || (style.top === undefined || style.top === null) && (style.bottom === undefined || style.bottom === null)) {\n if (verticalAlign === 'middle') {\n vPos = {\n top: ((chartHeight || 0) - box.height) / 2\n };\n } else {\n vPos = verticalAlign === 'bottom' ? {\n bottom: margin && margin.bottom || 0\n } : {\n top: margin && margin.top || 0\n };\n }\n }\n return _objectSpread(_objectSpread({}, hPos), vPos);\n}\nfunction LegendSettingsDispatcher(props) {\n var dispatch = useAppDispatch();\n useEffect(() => {\n dispatch(setLegendSettings(props));\n }, [dispatch, props]);\n return null;\n}\nfunction LegendSizeDispatcher(props) {\n var dispatch = useAppDispatch();\n useEffect(() => {\n dispatch(setLegendSize(props));\n return () => {\n dispatch(setLegendSize({\n width: 0,\n height: 0\n }));\n };\n }, [dispatch, props]);\n return null;\n}\nfunction getWidthOrHeight(layout, height, width, maxWidth) {\n if (layout === 'vertical' && isNumber(height)) {\n return {\n height\n };\n }\n if (layout === 'horizontal') {\n return {\n width: width || maxWidth\n };\n }\n return null;\n}\nexport var legendDefaultProps = {\n align: 'center',\n iconSize: 14,\n itemSorter: 'value',\n layout: 'horizontal',\n verticalAlign: 'bottom'\n};\nexport function Legend(outsideProps) {\n var props = resolveDefaultProps(outsideProps, legendDefaultProps);\n var contextPayload = useLegendPayload();\n var legendPortalFromContext = useLegendPortal();\n var margin = useMargin();\n var {\n width: widthFromProps,\n height: heightFromProps,\n wrapperStyle,\n portal: portalFromProps\n } = props;\n // The contextPayload is not used directly inside the hook, but we need the onBBoxUpdate call\n // when the payload changes, therefore it's here as a dependency.\n var [lastBoundingBox, updateBoundingBox] = useElementOffset([contextPayload]);\n var chartWidth = useChartWidth();\n var chartHeight = useChartHeight();\n if (chartWidth == null || chartHeight == null) {\n return null;\n }\n var maxWidth = chartWidth - ((margin === null || margin === void 0 ? void 0 : margin.left) || 0) - ((margin === null || margin === void 0 ? void 0 : margin.right) || 0);\n var widthOrHeight = getWidthOrHeight(props.layout, heightFromProps, widthFromProps, maxWidth);\n // if the user supplies their own portal, only use their defined wrapper styles\n var outerStyle = portalFromProps ? wrapperStyle : _objectSpread(_objectSpread({\n position: 'absolute',\n width: (widthOrHeight === null || widthOrHeight === void 0 ? void 0 : widthOrHeight.width) || widthFromProps || 'auto',\n height: (widthOrHeight === null || widthOrHeight === void 0 ? void 0 : widthOrHeight.height) || heightFromProps || 'auto'\n }, getDefaultPosition(wrapperStyle, props, margin, chartWidth, chartHeight, lastBoundingBox)), wrapperStyle);\n var legendPortal = portalFromProps !== null && portalFromProps !== void 0 ? portalFromProps : legendPortalFromContext;\n if (legendPortal == null || contextPayload == null) {\n return null;\n }\n var legendElement = /*#__PURE__*/React.createElement(\"div\", {\n className: \"recharts-legend-wrapper\",\n style: outerStyle,\n ref: updateBoundingBox\n }, /*#__PURE__*/React.createElement(LegendSettingsDispatcher, {\n layout: props.layout,\n align: props.align,\n verticalAlign: props.verticalAlign,\n itemSorter: props.itemSorter\n }), !portalFromProps && /*#__PURE__*/React.createElement(LegendSizeDispatcher, {\n width: lastBoundingBox.width,\n height: lastBoundingBox.height\n }), /*#__PURE__*/React.createElement(LegendContent, _extends({}, props, widthOrHeight, {\n margin: margin,\n chartWidth: chartWidth,\n chartHeight: chartHeight,\n contextPayload: contextPayload\n })));\n return /*#__PURE__*/createPortal(legendElement, legendPortal);\n}\nLegend.displayName = 'Legend';","/* eslint-disable react-refresh/only-export-components */\n// ========================================\n// CHART COMPONENTS (shadcn/ui pattern)\n// Base chart utilities following shadcn/ui Charts API\n// ========================================\n\nimport * as React from 'react';\nimport * as RechartsPrimitive from 'recharts';\n\nimport { cn } from '@/lib/utils';\n\n// ========================================\n// CHART CONFIG TYPE\n// ========================================\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode;\n icon?: React.ComponentType;\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: { light: string; dark: string } }\n );\n};\n\n// ========================================\n// CHART CONTEXT\n// ========================================\n\ntype ChartContextProps = {\n config: ChartConfig;\n};\n\nconst ChartContext = React.createContext<ChartContextProps | null>(null);\n\nfunction useChart() {\n const context = React.useContext(ChartContext);\n\n if (!context) {\n throw new Error('useChart must be used within a <ChartContainer />');\n }\n\n return context;\n}\n\n// ========================================\n// CHART CONTAINER\n// ========================================\n\ninterface ChartContainerProps\n extends React.ComponentProps<'div'>, Pick<ChartContextProps, 'config'> {\n children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>['children'];\n}\n\nconst ChartContainer = React.forwardRef<HTMLDivElement, ChartContainerProps>(\n ({ id, className, children, config, ...props }, ref) => {\n const uniqueId = React.useId();\n const chartId = `chart-${id || uniqueId.replace(/:/g, '')}`;\n\n return (\n <ChartContext.Provider value={{ config }}>\n <div\n data-chart={chartId}\n ref={ref}\n className={cn(\n \"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-[var(--text-muted)] [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-[var(--glass-border)] [&_.recharts-curve.recharts-tooltip-cursor]:stroke-[var(--glass-border)] [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-[var(--glass-border)] [&_.recharts-radial-bar-background-sector]:fill-[var(--glass-frost-5)] [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-[var(--glass-frost-10)] [&_.recharts-reference-line_[stroke='#ccc']]:stroke-[var(--glass-border)] [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none\",\n className\n )}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer>\n </div>\n </ChartContext.Provider>\n );\n }\n);\nChartContainer.displayName = 'ChartContainer';\n\n// ========================================\n// CHART STYLE (CSS Variables injection)\n// ========================================\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, itemConfig]) => itemConfig.color || itemConfig.theme\n );\n\n if (!colorConfig.length) {\n return null;\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: `\n[data-chart=\"${id}\"] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color = itemConfig.color || itemConfig.theme?.light;\n return color ? ` --color-${key}: ${color};` : null;\n })\n .filter(Boolean)\n .join('\\n')}\n}\n\n[data-theme=\"glass\"] [data-chart=\"${id}\"],\n.dark [data-chart=\"${id}\"] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color = itemConfig.theme?.dark || itemConfig.color;\n return color ? ` --color-${key}: ${color};` : null;\n })\n .filter(Boolean)\n .join('\\n')}\n}\n`,\n }}\n />\n );\n};\n\n// ========================================\n// CHART TOOLTIP\n// ========================================\n\nconst ChartTooltip = RechartsPrimitive.Tooltip;\n\ninterface TooltipPayloadItem {\n dataKey?: string | number;\n name?: string;\n value?: number;\n color?: string;\n payload?: Record<string, unknown>;\n fill?: string;\n type?: string;\n}\n\ninterface ChartTooltipContentProps {\n active?: boolean;\n payload?: TooltipPayloadItem[];\n label?: string;\n className?: string;\n labelClassName?: string;\n hideLabel?: boolean;\n hideIndicator?: boolean;\n indicator?: 'line' | 'dot' | 'dashed';\n nameKey?: string;\n labelKey?: string;\n labelFormatter?: (label: string, payload: TooltipPayloadItem[]) => React.ReactNode;\n valueFormatter?: (value: number) => string;\n}\n\nconst ChartTooltipContent = React.forwardRef<HTMLDivElement, ChartTooltipContentProps>(\n (\n {\n active,\n payload,\n className,\n indicator = 'dot',\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n nameKey,\n labelKey,\n valueFormatter,\n },\n ref\n ) => {\n const { config } = useChart();\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null;\n }\n\n const [item] = payload;\n const key = `${labelKey || item?.dataKey || item?.name || 'value'}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const value =\n !labelKey && typeof label === 'string'\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label;\n\n if (labelFormatter && typeof label === 'string') {\n return (\n <div className={cn('font-medium', labelClassName)}>{labelFormatter(label, payload)}</div>\n );\n }\n\n if (!value) {\n return null;\n }\n\n return <div className={cn('font-medium', labelClassName)}>{value}</div>;\n }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);\n\n if (!active || !payload?.length) {\n return null;\n }\n\n const nestLabel = payload.length === 1 && indicator !== 'dot';\n\n return (\n <div\n ref={ref}\n className={cn(\n 'grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-[var(--glass-border)] bg-[var(--glass-bg)] px-2.5 py-1.5 text-xs shadow-xl backdrop-blur-md',\n className\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload.map((item: TooltipPayloadItem, index: number) => {\n const key = `${nameKey || item.name || item.dataKey || 'value'}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const indicatorColor = item.fill || item.color;\n\n return (\n <div\n key={`${item.dataKey}-${index}`}\n className={cn(\n 'flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-[var(--text-muted)]',\n indicator === 'dot' && 'items-center'\n )}\n >\n {itemConfig?.icon ? (\n <itemConfig.icon />\n ) : (\n !hideIndicator && (\n <div\n className={cn(\n 'shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]',\n {\n 'h-2.5 w-2.5': indicator === 'dot',\n 'w-1': indicator === 'line',\n 'w-0 border-[1.5px] border-dashed bg-transparent': indicator === 'dashed',\n 'my-0.5': nestLabel && indicator === 'dashed',\n }\n )}\n style={\n {\n '--color-bg': indicatorColor,\n '--color-border': indicatorColor,\n } as React.CSSProperties\n }\n />\n )\n )}\n <div\n className={cn(\n 'flex flex-1 justify-between leading-none',\n nestLabel ? 'items-end' : 'items-center'\n )}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-[var(--text-muted)]\">\n {itemConfig?.label || item.name}\n </span>\n </div>\n {item.value !== undefined && (\n <span className=\"font-mono font-medium tabular-nums text-[var(--text-primary)]\">\n {valueFormatter ? valueFormatter(item.value) : item.value.toLocaleString()}\n </span>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n }\n);\nChartTooltipContent.displayName = 'ChartTooltipContent';\n\n// ========================================\n// CHART LEGEND\n// ========================================\n\nconst ChartLegend = RechartsPrimitive.Legend;\n\ninterface LegendPayloadItem {\n value?: string;\n dataKey?: string | number;\n color?: string;\n}\n\ninterface ChartLegendContentProps extends React.ComponentProps<'div'> {\n payload?: LegendPayloadItem[];\n verticalAlign?: 'top' | 'bottom';\n hideIcon?: boolean;\n nameKey?: string;\n}\n\nconst ChartLegendContent = React.forwardRef<HTMLDivElement, ChartLegendContentProps>(\n ({ className, hideIcon = false, payload, verticalAlign = 'bottom', nameKey }, ref) => {\n const { config } = useChart();\n\n if (!payload?.length) {\n return null;\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center justify-center gap-4',\n verticalAlign === 'top' ? 'pb-3' : 'pt-3',\n className\n )}\n >\n {payload.map((item: LegendPayloadItem) => {\n const key = `${nameKey || item.dataKey || 'value'}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n return (\n <div\n key={item.value}\n className={cn(\n 'flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-[var(--text-muted)]'\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <div\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{\n backgroundColor: item.color,\n }}\n />\n )}\n {itemConfig?.label}\n </div>\n );\n })}\n </div>\n );\n }\n);\nChartLegendContent.displayName = 'ChartLegendContent';\n\n// ========================================\n// HELPER FUNCTIONS\n// ========================================\n\nfunction getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {\n if (typeof payload !== 'object' || payload === null) {\n return undefined;\n }\n\n const payloadPayload =\n 'payload' in payload && typeof payload.payload === 'object' && payload.payload !== null\n ? payload.payload\n : undefined;\n\n let configLabelKey: string = key;\n\n if (key in config) {\n return config[key];\n }\n\n if (payloadPayload && key in payloadPayload) {\n configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key];\n}\n\n// ========================================\n// EXPORTS\n// ========================================\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n useChart,\n};\n","/**\n * DropdownGlass CVA Variants\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport type DropdownAlign = 'left' | 'right';\n\nexport const dropdownAlign = cva('absolute mt-2 min-w-[160px] md:min-w-[200px] rounded-2xl py-1.5 md:py-2', {\n variants: {\n align: {\n left: 'left-0',\n right: 'right-0',\n },\n },\n defaultVariants: {\n align: 'left',\n },\n});\n","/**\n * Alert CVA Variants (shadcn/ui)\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport const alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\n {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive:\n \"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n);\n","/**\n * Badge CVA Variants (shadcn/ui)\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport const badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n);\n","/**\n * Button CVA Variants (shadcn/ui)\n * Extracted for Fast Refresh compatibility\n */\n\nimport { cva } from 'class-variance-authority';\n\nexport const buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n"],"x_google_ignoreList":[2,3,4],"mappings":"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AAI,OAAO,OACT,QAAO,OAAO;AAGhB,KAAI,kBAAkB,OAAO,eAC3B,kBAAiB,eAAe;AAGlC,QAAO,kBAAkB,SAAS,OAAO,kBAAkB,OAAO;;ACzWpE,MAAa,gBAAgB,IAAI,2EAA2E;CAC1G,UAAU,EACR,OAAO;EACL,MAAM;EACN,OAAO;EACR,EACF;CACD,iBAAiB,EACf,OAAO,QACR;CACF,CAAC;ACZF,MAAa,kBAAgB,IAC3B,qOACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,aACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;ACdD,MAAa,kBAAgB,IAC3B,oZACA;CACE,UAAU,EACR,SAAS;EACP,SACE;EACF,WACE;EACF,aACE;EACF,SACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;ACnBD,MAAa,iBAAiB,IAC5B,+bACA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,aACE;GACF,SACE;GACF,WACE;GACF,OACE;GACF,MAAM;GACP;EACD,MAAM;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,WAAW;GACX,WAAW;GACZ;EACF;CACD,iBAAiB;EACf,SAAS;EACT,MAAM;EACP;CACF,CACF"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
{
|
|
16
16
|
"path": "components/glass/composite/ai-card-glass.tsx",
|
|
17
17
|
"type": "registry:component",
|
|
18
|
-
"content": "// ========================================\n// AI CARD GLASS COMPONENT\n// AI summary card with feature list\n// ========================================\n\nimport { forwardRef } from
|
|
18
|
+
"content": "// ========================================\n// AI CARD GLASS COMPONENT\n// AI summary card with feature list\n// ========================================\n\nimport { forwardRef } from 'react';\nimport { Sparkles, Check, Zap, Clock } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { ButtonGlass } from '../ui/button-glass';\nimport { InteractiveCard } from '../primitives';\nimport '@/glass-theme.css';\n\nexport interface AICardGlassProps extends React.HTMLAttributes<HTMLDivElement> {\n readonly onGenerate?: () => void;\n readonly features?: readonly string[];\n readonly estimatedTime?: string;\n}\n\nconst defaultFeatures: readonly string[] = [\n 'Code quality assessment',\n 'Architecture patterns',\n 'Best practices',\n];\n\nexport const AICardGlass = forwardRef<HTMLDivElement, AICardGlassProps>(\n (\n { onGenerate, features = defaultFeatures, estimatedTime = '~30 seconds', className, ...props },\n ref\n ) => {\n return (\n <InteractiveCard\n ref={ref}\n baseBg=\"var(--ai-card-bg)\"\n borderColor=\"var(--ai-card-border)\"\n hoverGlow=\"var(--ai-card-hover-glow)\"\n hoverLift\n blur=\"sm\"\n rounded=\"rounded-xl\"\n className={cn('w-full sm:w-56 md:w-64 p-3 md:p-4', className)}\n {...props}\n >\n <div\n className=\"flex items-center gap-1.5 md:gap-2 font-semibold text-xs md:text-sm mb-1.5 md:mb-2\"\n style={{ color: 'var(--text-accent)' }}\n >\n <Sparkles className=\"w-3.5 h-3.5 md:w-4 md:h-4\" />\n AI Summary\n </div>\n <p className=\"text-(length:--font-size-2xs) md:text-xs mb-1.5 md:mb-2 text-(--text-secondary)\">\n Get comprehensive analysis:\n </p>\n <ul className=\"text-(length:--font-size-2xs) md:text-xs space-y-0.5 md:space-y-1 mb-2 md:mb-3\">\n {features.map((feature, i) => (\n <li\n key={`feature-${i}`}\n className=\"flex items-center gap-1\"\n style={{ color: 'var(--text-muted)' }}\n >\n <Check\n className=\"w-2.5 h-2.5 md:w-3 md:h-3\"\n style={{ color: 'var(--status-online)' }}\n />\n {feature}\n </li>\n ))}\n </ul>\n <ButtonGlass variant=\"primary\" size=\"sm\" icon={Zap} onClick={onGenerate} className=\"w-full\">\n Generate Report\n </ButtonGlass>\n <p className=\"text-(length:--font-size-2xs) md:text-xs mt-1.5 md:mt-2 text-center flex items-center justify-center gap-1 text-(--text-muted)\">\n <Clock className=\"w-2.5 h-2.5 md:w-3 md:h-3\" />\n {estimatedTime}\n </p>\n </InteractiveCard>\n );\n }\n);\n\nAICardGlass.displayName = 'AICardGlass';\n"
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"categories": [
|
package/dist/r/avatar-glass.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
{
|
|
19
19
|
"path": "components/glass/ui/avatar-glass.tsx",
|
|
20
20
|
"type": "registry:component",
|
|
21
|
-
"content": "/**\n * AvatarGlass Component\n *\n * Glass-themed avatar with:\n * - Theme-aware styling (glass/light/aurora)\n * - Glow effect on hover\n * - Status indicator with glow\n * - Size variants\n */\n\nimport { forwardRef, type CSSProperties } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\nimport { avatarSizes, statusSizes } from '@/lib/variants/avatar-glass-variants';\nimport '@/glass-theme.css';\n\n// ========================================\n// TYPES\n// ========================================\n\n/**\n * Avatar status indicator type\n */\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for the AvatarGlass component\n *\n * A glass-themed avatar component with status indicators and size variants.\n * Displays user initials with theme-aware styling and optional status badge.\n *\n * @example\n * ```tsx\n * // Basic avatar\n * <AvatarGlass name=\"John Doe\" />\n *\n * // With status indicator\n * <AvatarGlass name=\"Jane Smith\" status=\"online\" size=\"lg\" />\n *\n * // Different sizes\n * <AvatarGlass name=\"Alex\" size=\"sm\" />\n * <AvatarGlass name=\"Sam\" size=\"xl\" />\n *\n * // As a link (asChild pattern)\n * <AvatarGlass asChild name=\"Sarah Connor\" status=\"online\">\n * <a href=\"/profile/sarah\">View Profile</a>\n * </AvatarGlass>\n * ```\n */\nexport interface AvatarGlassProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'
|
|
21
|
+
"content": "/**\n * AvatarGlass Component\n *\n * Glass-themed avatar with:\n * - Theme-aware styling (glass/light/aurora)\n * - Glow effect on hover\n * - Status indicator with glow\n * - Size variants\n */\n\nimport { forwardRef, type CSSProperties } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\nimport { avatarSizes, statusSizes } from '@/lib/variants/avatar-glass-variants';\nimport '@/glass-theme.css';\n\n// ========================================\n// TYPES\n// ========================================\n\n/**\n * Avatar status indicator type\n */\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for the AvatarGlass component\n *\n * A glass-themed avatar component with status indicators and size variants.\n * Displays user initials with theme-aware styling and optional status badge.\n *\n * @example\n * ```tsx\n * // Basic avatar\n * <AvatarGlass name=\"John Doe\" />\n *\n * // With status indicator\n * <AvatarGlass name=\"Jane Smith\" status=\"online\" size=\"lg\" />\n *\n * // Different sizes\n * <AvatarGlass name=\"Alex\" size=\"sm\" />\n * <AvatarGlass name=\"Sam\" size=\"xl\" />\n *\n * // As a link (asChild pattern)\n * <AvatarGlass asChild name=\"Sarah Connor\" status=\"online\">\n * <a href=\"/profile/sarah\">View Profile</a>\n * </AvatarGlass>\n * ```\n */\nexport interface AvatarGlassProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>, VariantProps<typeof avatarSizes> {\n /**\n * Render as child element instead of div (polymorphic rendering).\n * Useful for making avatars clickable links.\n * @default false\n * @example\n * ```tsx\n * <AvatarGlass asChild name=\"John\">\n * <a href=\"/profile\">View Profile</a>\n * </AvatarGlass>\n * ```\n */\n readonly asChild?: boolean;\n\n /**\n * Full name of the user. Automatically generates initials (first 2 letters).\n * @example \"John Doe\" → \"JD\"\n */\n readonly name: string;\n\n /**\n * Optional status indicator with glow effect\n * @default undefined\n */\n readonly status?: AvatarStatus;\n\n /**\n * Size variant of the avatar\n * @default \"md\"\n */\n readonly size?: 'sm' | 'md' | 'lg' | 'xl';\n}\n\n// ========================================\n// HELPERS\n// ========================================\n\nconst getInitials = (name: string): string => {\n if (!name || name.trim().length === 0) return '?';\n return name\n .split(' ')\n .map((part) => part[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n};\n\n// ========================================\n// COMPONENT\n// ========================================\n\n// Status colors mapping to CSS variables\nconst getStatusVars = (statusType: AvatarStatus): { bg: string; glow: string } => {\n const statusVars: Record<AvatarStatus, { bg: string; glow: string }> = {\n online: { bg: 'var(--status-online)', glow: 'var(--status-online-glow)' },\n offline: { bg: 'var(--status-offline)', glow: 'none' },\n busy: { bg: 'var(--status-busy)', glow: 'var(--status-busy-glow)' },\n away: { bg: 'var(--status-away)', glow: 'var(--status-away-glow)' },\n };\n return statusVars[statusType];\n};\n\nexport const AvatarGlass = forwardRef<HTMLDivElement, AvatarGlassProps>(\n ({ asChild = false, name, size = 'md', status, className, ...props }, ref) => {\n const { isHovered, hoverProps } = useHover();\n\n const avatarStyles: CSSProperties = {\n background: 'var(--avatar-bg)',\n border: '2px solid var(--avatar-border)',\n boxShadow: isHovered ? 'var(--avatar-hover-glow)' : 'var(--avatar-shadow)',\n color: 'var(--text-inverse)',\n };\n\n const initials = getInitials(name);\n\n // Polymorphic component - render as Slot when asChild is true\n const Comp = asChild ? Slot : 'div';\n\n return (\n <Comp\n ref={ref}\n className={cn('relative inline-flex', className)}\n onMouseEnter={hoverProps.onMouseEnter}\n onMouseLeave={hoverProps.onMouseLeave}\n {...props}\n >\n {/* Avatar circle */}\n <div\n className={cn(avatarSizes({ size }))}\n style={avatarStyles}\n role=\"img\"\n aria-label={`Avatar for ${name}`}\n >\n {initials}\n </div>\n\n {/* Status indicator */}\n {status && (\n <span\n className={cn(statusSizes({ size }))}\n style={{\n background: getStatusVars(status).bg,\n boxShadow: getStatusVars(status).glow,\n }}\n role=\"status\"\n aria-label={`Status: ${status}`}\n />\n )}\n </Comp>\n );\n }\n);\n\nAvatarGlass.displayName = 'AvatarGlass';\n"
|
|
22
22
|
}
|
|
23
23
|
],
|
|
24
24
|
"categories": [
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"path": "components/glass/composite/circular-metric-glass.tsx",
|
|
16
16
|
"type": "registry:component",
|
|
17
|
-
"content": "// ========================================\n// CIRCULAR METRIC GLASS COMPONENT\n// Compact circular metric display for mobile\n// ========================================\n\nimport { forwardRef } from 'react';\nimport { cn } from '@/lib/utils';\nimport {\n CircularProgressGlass,\n type CircularProgressGradient,\n} from '../ui/circular-progress-glass';\nimport '@/glass-theme.css';\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type CircularMetricColor = 'emerald' | 'amber' | 'blue' | 'red';\n\nexport interface CircularMetricGlassProps
|
|
17
|
+
"content": "// ========================================\n// CIRCULAR METRIC GLASS COMPONENT\n// Compact circular metric display for mobile\n// ========================================\n\nimport { forwardRef } from 'react';\nimport { cn } from '@/lib/utils';\nimport {\n CircularProgressGlass,\n type CircularProgressGradient,\n} from '../ui/circular-progress-glass';\nimport '@/glass-theme.css';\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type CircularMetricColor = 'emerald' | 'amber' | 'blue' | 'red';\n\nexport interface CircularMetricGlassProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g., \"Reg\", \"Imp\") */\n readonly label: string;\n /** Metric value (0-100) */\n readonly value: number;\n /** Metric color */\n readonly color?: CircularMetricColor;\n /** Size variant */\n readonly size?: 'sm' | 'md';\n}\n\n// ========================================\n// HELPERS\n// ========================================\n\n// Map CircularMetricColor to CircularProgressGlass gradient and CSS variable\nconst colorMap: Record<\n CircularMetricColor,\n { gradient: CircularProgressGradient; textVar: string }\n> = {\n emerald: { gradient: 'emerald', textVar: 'var(--metric-success-text)' },\n amber: { gradient: 'amber', textVar: 'var(--metric-warning-text)' },\n blue: { gradient: 'blue', textVar: 'var(--metric-default-text)' },\n red: { gradient: 'rose', textVar: 'var(--metric-destructive-text)' },\n};\n\n// ========================================\n// COMPONENT\n// ========================================\n\n/**\n * CircularMetricGlass - Compact circular progress metric display\n *\n * Designed for mobile layouts where rectangular MetricCardGlass is too wide.\n * Shows a circular progress indicator with percentage inside and label below.\n *\n * @example\n * ```tsx\n * <CircularMetricGlass label=\"Reg\" value={84} color=\"emerald\" />\n * ```\n */\nexport const CircularMetricGlass = forwardRef<HTMLDivElement, CircularMetricGlassProps>(\n ({ label, value, color = 'blue', size = 'sm', className, ...props }, ref) => {\n const { gradient, textVar } = colorMap[color];\n\n return (\n <div ref={ref} className={cn('flex flex-col items-center gap-1', className)} {...props}>\n <CircularProgressGlass\n value={value}\n size={size}\n color={gradient}\n labelColor={textVar}\n thickness={size === 'sm' ? 6 : 8}\n showGlow\n glowIntensity=\"medium\"\n />\n <span className=\"text-xs font-medium\" style={{ color: textVar }}>\n {label}\n </span>\n </div>\n );\n }\n);\n\nCircularMetricGlass.displayName = 'CircularMetricGlass';\n"
|
|
18
18
|
}
|
|
19
19
|
],
|
|
20
20
|
"categories": [
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
{
|
|
16
16
|
"path": "components/glass/ui/circular-progress-glass.tsx",
|
|
17
17
|
"type": "registry:component",
|
|
18
|
-
"content": "/**\n * CircularProgressGlass Component\n *\n * SVG-based circular progress indicator with:\n * - Determinate and indeterminate variants\n * - Configurable size and thickness\n * - Glow effect with SVG filters\n * - Theme-aware styling\n * - Optional label in center\n * - Gradient colors support\n */\n\nimport { forwardRef, useMemo, useId } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\nimport '@/glass-theme.css';\n\n// ========================================\n// VARIANTS\n// ========================================\n\nconst circularProgressVariants = cva('relative inline-flex items-center justify-center', {\n variants: {\n size: {\n sm: 'w-16 h-16',\n md: 'w-24 h-24',\n lg: 'w-32 h-32',\n xl: 'w-40 h-40',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type CircularProgressGradient = 'violet' | 'blue' | 'cyan' | 'amber' | 'emerald' | 'rose';\n\nexport interface CircularProgressGlassProps\n extends
|
|
18
|
+
"content": "/**\n * CircularProgressGlass Component\n *\n * SVG-based circular progress indicator with:\n * - Determinate and indeterminate variants\n * - Configurable size and thickness\n * - Glow effect with SVG filters\n * - Theme-aware styling\n * - Optional label in center\n * - Gradient colors support\n */\n\nimport { forwardRef, useMemo, useId } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\nimport '@/glass-theme.css';\n\n// ========================================\n// VARIANTS\n// ========================================\n\nconst circularProgressVariants = cva('relative inline-flex items-center justify-center p-2', {\n variants: {\n size: {\n sm: 'w-16 h-16',\n md: 'w-24 h-24',\n lg: 'w-32 h-32',\n xl: 'w-40 h-40',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type CircularProgressGradient = 'violet' | 'blue' | 'cyan' | 'amber' | 'emerald' | 'rose';\n\nexport interface CircularProgressGlassProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>,\n VariantProps<typeof circularProgressVariants> {\n /** Progress value (0-100) for determinate variant */\n readonly value?: number;\n /** Variant type */\n readonly variant?: 'determinate' | 'indeterminate';\n /** Stroke width in pixels */\n readonly thickness?: number;\n /** Background track width in pixels */\n readonly trackWidth?: number;\n /** Progress color gradient */\n readonly color?: CircularProgressGradient;\n /** Track color (background circle) */\n readonly trackColor?: string;\n /** Show percentage label in center */\n readonly showLabel?: boolean;\n /** Custom label text (overrides percentage) */\n readonly label?: string;\n /** Custom color for the center label text */\n readonly labelColor?: string;\n /** Show glow effect */\n readonly showGlow?: boolean;\n /** Glow intensity */\n readonly glowIntensity?: 'low' | 'medium' | 'high';\n /** Stroke linecap style */\n readonly strokeLinecap?: 'round' | 'butt' | 'square';\n /** Animation duration in seconds */\n readonly animationDuration?: number;\n}\n\n// ========================================\n// HELPERS\n// ========================================\n\nconst getGradientColors = (gradient: CircularProgressGradient) => {\n const gradients: Record<CircularProgressGradient, { from: string; to: string; glowVar: string }> =\n {\n violet: { from: '#8b5cf6', to: '#a855f7', glowVar: '--progress-glow-violet' },\n blue: { from: '#3b82f6', to: '#60a5fa', glowVar: '--progress-glow-blue' },\n cyan: { from: '#06b6d4', to: '#22d3ee', glowVar: '--progress-glow-cyan' },\n amber: { from: '#f59e0b', to: '#fbbf24', glowVar: '--progress-glow-amber' },\n emerald: { from: '#10b981', to: '#34d399', glowVar: '--progress-glow-emerald' },\n rose: { from: '#f43f5e', to: '#fb7185', glowVar: '--progress-glow-rose' },\n };\n return gradients[gradient];\n};\n\nconst getGlowStdDeviation = (intensity: 'low' | 'medium' | 'high'): number => {\n const intensities = { low: 2, medium: 4, high: 6 };\n return intensities[intensity];\n};\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const CircularProgressGlass = forwardRef<HTMLDivElement, CircularProgressGlassProps>(\n (\n {\n className,\n size = 'md',\n value = 0,\n variant = 'determinate',\n thickness = 8,\n trackWidth = 8,\n color = 'violet',\n trackColor = 'oklch(100% 0 0 / 0.1)',\n showLabel = true,\n label,\n labelColor,\n showGlow = true,\n glowIntensity = 'medium',\n strokeLinecap = 'round',\n animationDuration = 1,\n ...props\n },\n ref\n ) => {\n const clampedValue = Math.min(100, Math.max(0, value));\n const gradientColors = getGradientColors(color);\n\n // SVG dimensions\n const sizeMap = { sm: 64, md: 96, lg: 128, xl: 160 };\n const svgSize = sizeMap[size || 'md'];\n const radius = (svgSize - Math.max(thickness, trackWidth)) / 2;\n const circumference = 2 * Math.PI * radius;\n const center = svgSize / 2;\n\n // Calculate stroke dash offset for determinate progress\n const dashOffset = useMemo(() => {\n if (variant === 'indeterminate') return circumference * 0.75;\n return circumference * ((100 - clampedValue) / 100);\n }, [variant, clampedValue, circumference]);\n\n // Generate unique IDs for SVG elements (using useId for stable IDs)\n const uniqueId = useId();\n const gradientId = `circular-gradient-${uniqueId}`;\n const glowId = `circular-glow-${uniqueId}`;\n\n return (\n <div ref={ref} className={cn(circularProgressVariants({ size }), className)} {...props}>\n <svg\n width={svgSize}\n height={svgSize}\n className=\"transform -rotate-90 overflow-visible\"\n aria-hidden=\"true\"\n style={{ overflow: 'visible' }}\n >\n <defs>\n {/* Gradient definition */}\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" stopColor={gradientColors.from} />\n <stop offset=\"100%\" stopColor={gradientColors.to} />\n </linearGradient>\n\n {/* Glow filter */}\n {showGlow && (\n <filter id={glowId}>\n <feGaussianBlur\n stdDeviation={getGlowStdDeviation(glowIntensity)}\n result=\"coloredBlur\"\n />\n <feMerge>\n <feMergeNode in=\"coloredBlur\" />\n <feMergeNode in=\"SourceGraphic\" />\n </feMerge>\n </filter>\n )}\n </defs>\n\n {/* Background track */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={trackColor}\n strokeWidth={trackWidth}\n />\n\n {/* Progress circle */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={`url(#${gradientId})`}\n strokeWidth={thickness}\n strokeLinecap={strokeLinecap}\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n filter={showGlow ? `url(#${glowId})` : undefined}\n className={cn(\n 'transition-all',\n variant === 'indeterminate' && 'animate-circular-progress-spin'\n )}\n style={{\n transitionDuration: `${animationDuration}s`,\n transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',\n }}\n />\n </svg>\n\n {/* Center label */}\n {showLabel && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <span\n className=\"text-sm font-semibold tabular-nums\"\n style={{ color: labelColor || gradientColors.to }}\n >\n {label || (variant === 'determinate' ? `${clampedValue}%` : '')}\n </span>\n </div>\n )}\n\n {/* Accessibility */}\n <div\n role=\"progressbar\"\n aria-valuenow={variant === 'determinate' ? clampedValue : undefined}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={\n label || (variant === 'determinate' ? `Progress: ${clampedValue}%` : 'Loading progress')\n }\n aria-valuetext={label || (variant === 'determinate' ? `${clampedValue}%` : 'Loading...')}\n className=\"sr-only\"\n >\n {label || (variant === 'determinate' ? `${clampedValue}%` : 'Loading...')}\n </div>\n </div>\n );\n }\n);\n\nCircularProgressGlass.displayName = 'CircularProgressGlass';\n"
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"categories": [
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"path": "components/glass/ui/combobox-glass.tsx",
|
|
18
18
|
"type": "registry:component",
|
|
19
|
-
"content": "/**\n * ComboBoxGlass Component\n *\n * Glass-themed combobox (searchable select) with:\n * - Keyboard navigation support\n * - Search/filter functionality\n * - Custom rendering options\n * - Async data loading support\n * - Glass styling with theme support\n * - Accessibility features\n * - Form field wrapper support (label, error, success)\n * - Size variants (sm, md, lg, xl)\n * - Optional searchable mode\n * - Icon support for trigger and options\n */\n\n'use client';\n\nimport { useState, useMemo, useCallback, forwardRef, useId } from 'react';\nimport { CheckIcon, ChevronsUpDownIcon, type LucideIcon } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { ButtonGlass } from './button-glass';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/components/ui/command';\nimport { FormFieldWrapper } from '../primitives/form-field-wrapper';\nimport { inputVariants, type InputGlassSize } from '@/lib/variants/input-glass-variants';\nimport { getDropdownContentStyles } from '@/lib/variants/dropdown-content-styles';\nimport { ICON_SIZES } from '../primitives/style-utils';\nimport '@/glass-theme.css';\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type GlassVariant = 'glass' | 'frosted' | 'fluted' | 'crystal';\n\nexport interface ComboBoxOption<T = string> {\n readonly value: T;\n readonly label: string;\n readonly disabled?: boolean;\n /** Optional icon component for the option */\n readonly icon?: LucideIcon;\n}\n\nexport interface ComboBoxGlassProps<T = string> {\n /** Available options */\n readonly options: readonly ComboBoxOption<T>[];\n /** Currently selected value */\n readonly value?: T;\n /** Callback when value changes */\n readonly onChange?: (value: T | undefined) => void;\n /** Placeholder text for trigger button */\n readonly placeholder?: string;\n /** Text shown when no results found */\n readonly emptyText?: string;\n /** Placeholder for search input */\n readonly searchPlaceholder?: string;\n /** Glass variant style */\n readonly glassVariant?: GlassVariant;\n /** Disabled state */\n readonly disabled?: boolean;\n /** Custom className for container */\n readonly className?: string;\n /** Custom className for popover content */\n readonly popoverClassName?: string;\n /** Allow clearing selection */\n readonly clearable?: boolean;\n /** Popover side */\n readonly side?: 'top' | 'right' | 'bottom' | 'left';\n /** Popover alignment */\n readonly align?: 'start' | 'center' | 'end';\n\n // ========================================\n // NEW PROPS (Week 3 Enhancement)\n // ========================================\n\n /** Label text displayed above the field */\n readonly label?: string;\n /** Error message - displays in red below the field */\n readonly error?: string;\n /** Success message - displays in green if no error */\n readonly success?: string;\n /** Shows required asterisk (*) next to label */\n readonly required?: boolean;\n /** Size variant (affects trigger button height and padding) */\n readonly size?: InputGlassSize;\n /** Enable/disable search functionality */\n readonly searchable?: boolean;\n /** Optional icon for trigger button (displayed before text) */\n readonly icon?: LucideIcon;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nfunction ComboBoxGlassInner<T = string>(\n {\n options,\n value,\n onChange,\n placeholder = 'Select option...',\n emptyText = 'No results found.',\n searchPlaceholder = 'Search...',\n glassVariant = 'glass',\n disabled = false,\n className,\n popoverClassName,\n clearable = false,\n side = 'bottom',\n align = 'start',\n // NEW PROPS\n label,\n error,\n success,\n required = false,\n size = 'md',\n searchable = true,\n icon: TriggerIcon,\n }: ComboBoxGlassProps<T>,\n ref: React.ForwardedRef<HTMLButtonElement>\n) {\n const [open, setOpen] = useState(false);\n const [search, setSearch] = useState('');\n const fieldId = useId();\n\n // Find selected option\n const selectedOption = useMemo(\n () => options.find((opt) => opt.value === value),\n [options, value]\n );\n\n // Filter options based on search\n const filteredOptions = useMemo(() => {\n if (!search) return options;\n const searchLower = search.toLowerCase();\n return options.filter((opt) =>\n opt.label.toLowerCase().includes(searchLower)\n );\n }, [options, search]);\n\n // Handle option selection\n const handleSelect = useCallback(\n (optionValue: T) => {\n if (clearable && value === optionValue) {\n onChange?.(undefined);\n } else {\n onChange?.(optionValue);\n }\n setOpen(false);\n setSearch('');\n },\n [value, onChange, clearable]\n );\n\n // Get glass variant class\n const getGlassClass = () => {\n const variants: Record<GlassVariant, string> = {\n glass: 'glass',\n frosted: 'frosted',\n fluted: 'fluted',\n crystal: 'crystal',\n };\n return variants[glassVariant];\n };\n\n // Render content\n const comboboxContent = (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <ButtonGlass\n ref={ref}\n variant=\"secondary\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-label={selectedOption?.label || placeholder}\n aria-describedby={error ? `${fieldId}-error` : success ? `${fieldId}-success` : undefined}\n disabled={disabled}\n className={cn(\n 'w-full justify-between',\n // Apply size variant via inputVariants\n inputVariants({ size }),\n !selectedOption && 'text-muted-foreground',\n className\n )}\n >\n <span className=\"flex items-center gap-2 truncate\">\n {TriggerIcon && <TriggerIcon className={ICON_SIZES.md} />}\n {selectedOption ? selectedOption.label : placeholder}\n </span>\n <ChevronsUpDownIcon className={cn(ICON_SIZES.md, 'shrink-0 opacity-50')} />\n </ButtonGlass>\n </PopoverTrigger>\n <PopoverContent\n side={side}\n align={align}\n className={cn(\n 'w-[--radix-popover-trigger-width] p-0 rounded-2xl overflow-hidden border-0',\n getGlassClass(),\n popoverClassName\n )}\n style={getDropdownContentStyles()}\n >\n <Command\n shouldFilter={false}\n className={cn(\n 'bg-transparent',\n // Hide default border, use subtle divider instead\n '[&_[data-slot=command-input-wrapper]]:border-b-0',\n // Fix search icon - use glass theme color with better visibility\n '[&_[data-slot=command-input-wrapper]_svg]:text-[var(--text-muted)]',\n '[&_[data-slot=command-input-wrapper]_svg]:opacity-80'\n )}\n >\n {searchable && (\n <CommandInput\n placeholder={searchPlaceholder}\n value={search}\n onValueChange={setSearch}\n className=\"text-[var(--text-primary)] placeholder:text-[var(--text-muted)] h-10 font-medium\"\n />\n )}\n <CommandList className=\"p-1.5\">\n <CommandEmpty className=\"text-[var(--text-muted)] py-4\">{emptyText}</CommandEmpty>\n <CommandGroup className=\"text-[var(--text-primary)] p-0\">\n {filteredOptions.map((option) => {\n const OptionIcon = option.icon;\n const isSelected = value === option.value;\n\n return (\n <CommandItem\n key={String(option.value)}\n value={String(option.value)}\n disabled={option.disabled}\n onSelect={() => handleSelect(option.value)}\n className={cn(\n 'w-full px-3 py-2.5 text-sm flex items-center gap-2 rounded-none',\n 'cursor-pointer transition-colors duration-150',\n 'text-[var(--dropdown-item-text)]',\n 'data-[selected=true]:bg-[var(--dropdown-item-hover)]',\n isSelected && 'bg-[var(--select-item-selected-bg)] text-[var(--select-item-selected-text)]',\n option.disabled && 'cursor-not-allowed opacity-50'\n )}\n >\n <CheckIcon\n className={cn(\n ICON_SIZES.md,\n 'shrink-0',\n isSelected ? 'opacity-100 text-[var(--text-accent)]' : 'opacity-0'\n )}\n />\n {OptionIcon && <OptionIcon className={cn(ICON_SIZES.md, 'shrink-0 text-[var(--dropdown-icon)]')} />}\n <span className=\"truncate\">{option.label}</span>\n </CommandItem>\n );\n })}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n\n // Wrap with FormFieldWrapper if label/error/success provided\n if (label || error || success) {\n return (\n <FormFieldWrapper\n label={label}\n error={error}\n success={success}\n required={required}\n htmlFor={fieldId}\n >\n {comboboxContent}\n </FormFieldWrapper>\n );\n }\n\n return comboboxContent;\n}\n\n// Export with generic type support\nexport const ComboBoxGlass = forwardRef(ComboBoxGlassInner) as <T = string>(\n props: ComboBoxGlassProps<T> & { ref?: React.ForwardedRef<HTMLButtonElement> }\n) => ReturnType<typeof ComboBoxGlassInner>;\n\n// Add display name for debugging\nComboBoxGlassInner.displayName = 'ComboBoxGlass';\n"
|
|
19
|
+
"content": "/**\n * ComboBoxGlass Component\n *\n * Glass-themed combobox (searchable select) with:\n * - Keyboard navigation support\n * - Search/filter functionality\n * - Custom rendering options\n * - Async data loading support\n * - Glass styling with theme support\n * - Accessibility features\n * - Form field wrapper support (label, error, success)\n * - Size variants (sm, md, lg, xl)\n * - Optional searchable mode\n * - Icon support for trigger and options\n */\n\n'use client';\n\nimport { useState, useMemo, useCallback, forwardRef, useId } from 'react';\nimport { CheckIcon, ChevronsUpDownIcon, type LucideIcon } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { ButtonGlass } from './button-glass';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/components/ui/command';\nimport { FormFieldWrapper } from '../primitives/form-field-wrapper';\nimport { inputVariants, type InputGlassSize } from '@/lib/variants/input-glass-variants';\nimport { getDropdownContentStyles } from '@/lib/variants/dropdown-content-styles';\nimport { ICON_SIZES } from '../primitives/style-utils';\nimport '@/glass-theme.css';\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type GlassVariant = 'glass' | 'frosted' | 'fluted' | 'crystal';\n\nexport interface ComboBoxOption<T = string> {\n readonly value: T;\n readonly label: string;\n readonly disabled?: boolean;\n /** Optional icon component for the option */\n readonly icon?: LucideIcon;\n}\n\nexport interface ComboBoxGlassProps<T = string> {\n /** Available options */\n readonly options: readonly ComboBoxOption<T>[];\n /** Currently selected value */\n readonly value?: T;\n /** Callback when value changes */\n readonly onChange?: (value: T | undefined) => void;\n /** Placeholder text for trigger button */\n readonly placeholder?: string;\n /** Text shown when no results found */\n readonly emptyText?: string;\n /** Placeholder for search input */\n readonly searchPlaceholder?: string;\n /** Glass variant style */\n readonly glassVariant?: GlassVariant;\n /** Disabled state */\n readonly disabled?: boolean;\n /** Custom className for container */\n readonly className?: string;\n /** Custom className for popover content */\n readonly popoverClassName?: string;\n /** Allow clearing selection */\n readonly clearable?: boolean;\n /** Popover side */\n readonly side?: 'top' | 'right' | 'bottom' | 'left';\n /** Popover alignment */\n readonly align?: 'start' | 'center' | 'end';\n\n // ========================================\n // NEW PROPS (Week 3 Enhancement)\n // ========================================\n\n /** Label text displayed above the field */\n readonly label?: string;\n /** Error message - displays in red below the field */\n readonly error?: string;\n /** Success message - displays in green if no error */\n readonly success?: string;\n /** Shows required asterisk (*) next to label */\n readonly required?: boolean;\n /** Size variant (affects trigger button height and padding) */\n readonly size?: InputGlassSize;\n /** Enable/disable search functionality */\n readonly searchable?: boolean;\n /** Optional icon for trigger button (displayed before text) */\n readonly icon?: LucideIcon;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nfunction ComboBoxGlassInner<T = string>(\n {\n options,\n value,\n onChange,\n placeholder = 'Select option...',\n emptyText = 'No results found.',\n searchPlaceholder = 'Search...',\n glassVariant = 'glass',\n disabled = false,\n className,\n popoverClassName,\n clearable = false,\n side = 'bottom',\n align = 'start',\n // NEW PROPS\n label,\n error,\n success,\n required = false,\n size = 'md',\n searchable = true,\n icon: TriggerIcon,\n }: ComboBoxGlassProps<T>,\n ref: React.ForwardedRef<HTMLButtonElement>\n) {\n const [open, setOpen] = useState(false);\n const [search, setSearch] = useState('');\n const fieldId = useId();\n\n // Find selected option\n const selectedOption = useMemo(\n () => options.find((opt) => opt.value === value),\n [options, value]\n );\n\n // Filter options based on search\n const filteredOptions = useMemo(() => {\n if (!search) return options;\n const searchLower = search.toLowerCase();\n return options.filter((opt) => opt.label.toLowerCase().includes(searchLower));\n }, [options, search]);\n\n // Handle option selection\n const handleSelect = useCallback(\n (optionValue: T) => {\n if (clearable && value === optionValue) {\n onChange?.(undefined);\n } else {\n onChange?.(optionValue);\n }\n setOpen(false);\n setSearch('');\n },\n [value, onChange, clearable]\n );\n\n // Get glass variant class\n const getGlassClass = () => {\n const variants: Record<GlassVariant, string> = {\n glass: 'glass',\n frosted: 'frosted',\n fluted: 'fluted',\n crystal: 'crystal',\n };\n return variants[glassVariant];\n };\n\n // Render content\n const comboboxContent = (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <ButtonGlass\n ref={ref}\n variant=\"secondary\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-label={selectedOption?.label || placeholder}\n aria-describedby={error ? `${fieldId}-error` : success ? `${fieldId}-success` : undefined}\n disabled={disabled}\n className={cn(\n 'w-full justify-between',\n // Apply size variant via inputVariants\n inputVariants({ size }),\n !selectedOption && 'text-muted-foreground',\n className\n )}\n >\n <span className=\"flex items-center gap-2 truncate\">\n {TriggerIcon && <TriggerIcon className={ICON_SIZES.md} />}\n {selectedOption ? selectedOption.label : placeholder}\n </span>\n <ChevronsUpDownIcon className={cn(ICON_SIZES.md, 'shrink-0 opacity-50')} />\n </ButtonGlass>\n </PopoverTrigger>\n <PopoverContent\n side={side}\n align={align}\n className={cn(\n 'w-[--radix-popover-trigger-width] p-0 rounded-2xl overflow-hidden border-0',\n getGlassClass(),\n popoverClassName\n )}\n style={getDropdownContentStyles()}\n >\n <Command\n shouldFilter={false}\n className={cn(\n 'bg-transparent',\n // Hide default border, use subtle divider instead\n '[&_[data-slot=command-input-wrapper]]:border-b-0',\n // Fix search icon - use glass theme color with better visibility\n '[&_[data-slot=command-input-wrapper]_svg]:text-[var(--text-muted)]',\n '[&_[data-slot=command-input-wrapper]_svg]:opacity-80'\n )}\n >\n {searchable && (\n <CommandInput\n placeholder={searchPlaceholder}\n value={search}\n onValueChange={setSearch}\n className=\"text-[var(--text-primary)] placeholder:text-[var(--text-muted)] h-10 font-medium\"\n />\n )}\n <CommandList className=\"p-1.5 scrollbar-hide\">\n <CommandEmpty className=\"text-[var(--text-muted)] py-4\">{emptyText}</CommandEmpty>\n <CommandGroup className=\"text-[var(--text-primary)] p-0\">\n {filteredOptions.map((option) => {\n const OptionIcon = option.icon;\n const isSelected = value === option.value;\n\n return (\n <CommandItem\n key={String(option.value)}\n value={String(option.value)}\n disabled={option.disabled}\n onSelect={() => handleSelect(option.value)}\n className={cn(\n 'w-full px-3 py-2.5 text-sm flex items-center gap-2 rounded-lg',\n 'cursor-pointer transition-colors duration-150',\n 'text-[var(--dropdown-item-text)]',\n 'data-[selected=true]:bg-[var(--dropdown-item-hover)]',\n isSelected &&\n 'bg-[var(--select-item-selected-bg)] text-[var(--select-item-selected-text)]',\n option.disabled && 'cursor-not-allowed opacity-50'\n )}\n >\n <CheckIcon\n className={cn(\n ICON_SIZES.md,\n 'shrink-0',\n isSelected ? 'opacity-100 text-[var(--text-accent)]' : 'opacity-0'\n )}\n />\n {OptionIcon && (\n <OptionIcon\n className={cn(ICON_SIZES.md, 'shrink-0 text-[var(--dropdown-icon)]')}\n />\n )}\n <span className=\"truncate\">{option.label}</span>\n </CommandItem>\n );\n })}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n\n // Wrap with FormFieldWrapper if label/error/success provided\n if (label || error || success) {\n return (\n <FormFieldWrapper\n label={label}\n error={error}\n success={success}\n required={required}\n htmlFor={fieldId}\n >\n {comboboxContent}\n </FormFieldWrapper>\n );\n }\n\n return comboboxContent;\n}\n\n// Export with generic type support\nexport const ComboBoxGlass = forwardRef(ComboBoxGlassInner) as <T = string>(\n props: ComboBoxGlassProps<T> & { ref?: React.ForwardedRef<HTMLButtonElement> }\n) => ReturnType<typeof ComboBoxGlassInner>;\n\n// Add display name for debugging\nComboBoxGlassInner.displayName = 'ComboBoxGlass';\n"
|
|
20
20
|
}
|
|
21
21
|
],
|
|
22
22
|
"categories": [
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"path": "components/glass/specialized/flag-alert-glass.tsx",
|
|
16
16
|
"type": "registry:component",
|
|
17
|
-
"content": "// ========================================\n// FLAG ALERT GLASS COMPONENT\n// Individual warning/danger flag alert\n// ========================================\n\nimport { forwardRef, useState, type CSSProperties } from
|
|
17
|
+
"content": "// ========================================\n// FLAG ALERT GLASS COMPONENT\n// Individual warning/danger flag alert\n// ========================================\n\nimport { forwardRef, useState, type CSSProperties } from 'react';\nimport { cn } from '@/lib/utils';\nimport { StatusIndicatorGlass, type StatusType } from './status-indicator-glass';\nimport '@/glass-theme.css';\n\nexport type FlagType = 'warning' | 'danger';\n\nexport interface FlagAlertGlassProps extends React.HTMLAttributes<HTMLDivElement> {\n readonly type?: FlagType;\n readonly title: string;\n readonly description?: string;\n}\n\n// CSS variable maps for flag types\nconst flagVarMap: Record<\n FlagType,\n { bg: string; border: string; text: string; statusType: StatusType }\n> = {\n danger: {\n bg: 'var(--alert-danger-bg)',\n border: 'var(--alert-danger-border)',\n text: 'var(--alert-danger-text)',\n statusType: 'red',\n },\n warning: {\n bg: 'var(--alert-warning-bg)',\n border: 'var(--alert-warning-border)',\n text: 'var(--alert-warning-text)',\n statusType: 'yellow',\n },\n};\n\nexport const FlagAlertGlass = forwardRef<HTMLDivElement, FlagAlertGlassProps>(\n ({ type = 'warning', title, description, className, ...props }, ref) => {\n const [isHovered, setIsHovered] = useState(false);\n const config = flagVarMap[type];\n\n const alertStyles: CSSProperties = {\n background: config.bg,\n borderColor: config.border,\n transform: isHovered ? 'translateX(4px)' : 'translateX(0)',\n };\n\n return (\n <div\n ref={ref}\n className={cn('p-2.5 md:p-3 rounded-xl border transition-all duration-300', className)}\n style={alertStyles}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n role=\"alert\"\n {...props}\n >\n <div\n className=\"flex items-center gap-1.5 md:gap-2 font-medium text-xs md:text-sm\"\n style={{ color: config.text }}\n >\n <StatusIndicatorGlass type={config.statusType} />\n {title}\n </div>\n {description && (\n <p className=\"text-(length:--font-size-2xs) md:text-xs mt-0.5 md:mt-1 ml-4 md:ml-5 text-(--text-muted)\">\n {description}\n </p>\n )}\n </div>\n );\n }\n);\n\nFlagAlertGlass.displayName = 'FlagAlertGlass';\n"
|
|
18
18
|
}
|
|
19
19
|
],
|
|
20
20
|
"categories": [
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
{
|
|
16
16
|
"path": "components/glass/sections/flags-section-glass.tsx",
|
|
17
17
|
"type": "registry:component",
|
|
18
|
-
"content": "// ========================================\n// FLAGS SECTION GLASS COMPONENT\n// Expandable flags/warnings section\n// ========================================\n\nimport { forwardRef } from
|
|
18
|
+
"content": "// ========================================\n// FLAGS SECTION GLASS COMPONENT\n// Expandable flags/warnings section\n// ========================================\n\nimport { forwardRef } from 'react';\nimport { AlertTriangle, ChevronUp, ChevronDown } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { GlassCard } from '../ui/glass-card';\nimport { FlagAlertGlass, type FlagType } from '../specialized/flag-alert-glass';\nimport '@/glass-theme.css';\n\nexport interface FlagData {\n readonly type: FlagType;\n readonly title: string;\n readonly description?: string;\n}\n\nexport interface FlagsSectionGlassProps extends React.HTMLAttributes<HTMLDivElement> {\n readonly flags?: readonly FlagData[];\n readonly expanded?: boolean;\n readonly onToggle?: () => void;\n}\n\nexport const FlagsSectionGlass = forwardRef<HTMLDivElement, FlagsSectionGlassProps>(\n ({ flags = [], expanded = false, onToggle, className, ...props }, ref) => {\n return (\n <GlassCard\n ref={ref}\n className={cn('w-full max-w-2xl', className)}\n intensity=\"medium\"\n hover={false}\n {...props}\n >\n <button\n onClick={onToggle}\n className=\"w-full p-3 md:p-4 flex items-center justify-between rounded-2xl\"\n style={{ color: 'var(--text-primary)' }}\n type=\"button\"\n aria-expanded={expanded}\n >\n <div className=\"flex items-center gap-1.5 md:gap-2\">\n <AlertTriangle\n className=\"w-4 h-4 md:w-5 md:h-5\"\n style={{ color: 'var(--status-away)' }}\n />\n <span className=\"font-medium text-sm md:text-base\">{flags.length} flags detected</span>\n </div>\n {expanded ? (\n <ChevronUp className=\"w-4 h-4 md:w-5 md:h-5\" style={{ color: 'var(--text-muted)' }} />\n ) : (\n <ChevronDown className=\"w-4 h-4 md:w-5 md:h-5\" style={{ color: 'var(--text-muted)' }} />\n )}\n </button>\n {expanded && (\n <div className=\"px-3 pb-3 md:px-4 md:pb-4 space-y-1.5 md:space-y-2\">\n {flags.map((flag, i) => (\n <FlagAlertGlass\n key={`flag-${i}`}\n type={flag.type}\n title={flag.title}\n description={flag.description}\n />\n ))}\n </div>\n )}\n </GlassCard>\n );\n }\n);\n\nFlagsSectionGlass.displayName = 'FlagsSectionGlass';\n"
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"categories": [
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "insight-card-glass",
|
|
4
|
+
"type": "registry:component",
|
|
5
|
+
"title": "Insight Card Glass",
|
|
6
|
+
"description": "Insight Card Glass component with glass effects",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"class-variance-authority",
|
|
9
|
+
"lucide-react",
|
|
10
|
+
"react"
|
|
11
|
+
],
|
|
12
|
+
"registryDependencies": [
|
|
13
|
+
"cn",
|
|
14
|
+
"variants"
|
|
15
|
+
],
|
|
16
|
+
"files": [
|
|
17
|
+
{
|
|
18
|
+
"path": "components/glass/atomic/insight-card-glass.tsx",
|
|
19
|
+
"type": "registry:component",
|
|
20
|
+
"content": "import { forwardRef, type CSSProperties, type KeyboardEvent } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { ChevronRight } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport {\n insightCardVariants,\n insightVariantConfig,\n type InsightVariant,\n} from '@/lib/variants/insight-card-glass-variants';\nimport '@/glass-theme.css';\n\nexport interface InsightCardGlassProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>,\n VariantProps<typeof insightCardVariants> {\n /** Emoji icon for the insight */\n readonly emoji?: string;\n /** Main insight text */\n readonly text: string;\n /** Additional details */\n readonly detail?: string;\n /** Insight type variant */\n readonly variant?: InsightVariant;\n /** Inline display mode */\n readonly inline?: boolean;\n /** Click handler (makes the insight clickable) */\n readonly onClick?: () => void;\n /** Show arrow indicator */\n readonly showArrow?: boolean;\n /** Fade-in animation */\n readonly animated?: boolean;\n}\n\nexport const InsightCardGlass = forwardRef<HTMLDivElement, InsightCardGlassProps>(\n (\n {\n emoji,\n text,\n detail,\n variant = 'default',\n inline = false,\n onClick,\n showArrow = false,\n animated = false,\n className,\n ...props\n },\n ref\n ) => {\n const config = insightVariantConfig[variant];\n const displayEmoji = emoji ?? config.defaultEmoji;\n const isClickable = !!onClick;\n\n const handleClick = () => onClick?.();\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (isClickable && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onClick?.();\n }\n };\n\n const borderStyle: CSSProperties = !inline\n ? {\n borderColor: `var(${config.borderVar})`,\n }\n : {};\n\n const glowStyle: CSSProperties =\n isClickable && config.glowVar\n ? ({\n '--hover-glow': `var(${config.glowVar})`,\n } as CSSProperties)\n : {};\n\n // Inline variant\n if (inline) {\n return (\n <span\n ref={ref as React.Ref<HTMLSpanElement>}\n className={cn(\n 'inline-flex items-center gap-1.5 text-sm text-[var(--text-secondary)]',\n className\n )}\n {...props}\n >\n <span aria-hidden=\"true\">{displayEmoji}</span>\n <span>{text}</span>\n {detail && <span className=\"text-[var(--text-muted)]\">({detail})</span>}\n </span>\n );\n }\n\n // Card variant\n return (\n <div\n ref={ref}\n role={isClickable ? 'button' : undefined}\n tabIndex={isClickable ? 0 : undefined}\n onClick={isClickable ? handleClick : undefined}\n onKeyDown={isClickable ? handleKeyDown : undefined}\n className={cn(\n insightCardVariants({ inline, clickable: isClickable }),\n isClickable && config.glowVar && 'hover:shadow-[0_0_12px_var(--hover-glow)]',\n animated && 'animate-insight-fade-in',\n className\n )}\n style={{ ...borderStyle, ...glowStyle }}\n {...props}\n >\n <div className=\"flex items-start gap-2\">\n <span className=\"text-lg flex-shrink-0\" aria-hidden=\"true\">\n {displayEmoji}\n </span>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm text-[var(--text-primary)]\">{text}</p>\n {detail && <p className=\"text-xs text-[var(--text-muted)] mt-0.5\">{detail}</p>}\n </div>\n {showArrow && (\n <ChevronRight\n className=\"w-4 h-4 text-[var(--text-muted)] flex-shrink-0\"\n aria-hidden=\"true\"\n />\n )}\n </div>\n </div>\n );\n }\n);\n\nInsightCardGlass.displayName = 'InsightCardGlass';\n"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"categories": [
|
|
24
|
+
"atomic"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
{
|
|
16
16
|
"path": "components/glass/primitives/interactive-card.tsx",
|
|
17
17
|
"type": "registry:lib",
|
|
18
|
-
"content": "/**\n * InteractiveCard Component\n *\n * Unified wrapper for card components with hover animations and glass effects.\n * Eliminates hover state duplication in MetricCardGlass, YearCardGlass,\n * AICardGlass, RepositoryCardGlass, and other card components.\n *\n * Features:\n * - Hover lift animation (translateY -2px)\n * - Optional glow effects\n * - Glass surface with backdrop blur\n * - Configurable backgrounds and borders\n */\n\nimport { forwardRef, type HTMLAttributes, type CSSProperties } from 'react';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\n\n/**\n * Props for the InteractiveCard component\n */\nexport interface InteractiveCardProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Enable hover lift effect (translateY -2px)\n * @default true\n */\n hoverLift?: boolean;\n\n /**\n * CSS variable for hover glow effect\n * @example 'var(--glow-primary)'\n */\n hoverGlow?: string;\n\n /**\n * CSS variable for hover background\n * @example 'var(--card-hover-bg)'\n */\n hoverBg?: string;\n\n /**\n * CSS variable for base background\n * @default 'var(--card-bg)'\n */\n baseBg?: string;\n\n /**\n * CSS variable for border color\n * @default 'var(--card-border)'\n */\n borderColor?: string;\n\n /**\n * CSS variable for hover border color\n */\n hoverBorderColor?: string;\n\n /**\n * Blur level for glass effect\n * @default 'sm'\n */\n blur?: 'sm' | 'md' | 'lg' | 'xl';\n\n /**\n * Disable all hover interactions\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Border radius class\n * @default 'rounded-2xl'\n */\n rounded?: 'rounded-xl' | 'rounded-2xl' | 'rounded-3xl';\n\n /**\n * Transition speed\n * @default 'var(--transition-slow)'\n */\n transition?: string;\n}\n\n/**\n * InteractiveCard component\n *\n * Provides consistent hover animations and glass effects for card components.\n * Replaces ~80 lines of duplicated hover state management across 4+ components.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <InteractiveCard>\n * <h3>Card Title</h3>\n * <p>Card content</p>\n * </InteractiveCard>\n *\n * // With hover effects\n * <InteractiveCard\n * hoverLift\n * hoverGlow=\"var(--glow-primary)\"\n * hoverBg=\"var(--card-hover-bg)\"\n * hoverBorderColor=\"var(--card-hover-border)\"\n * >\n * <MetricContent />\n * </InteractiveCard>\n *\n * // Custom blur and rounding\n * <InteractiveCard\n * blur=\"md\"\n * rounded=\"rounded-3xl\"\n * baseBg=\"var(--metric-
|
|
18
|
+
"content": "/**\n * InteractiveCard Component\n *\n * Unified wrapper for card components with hover animations and glass effects.\n * Eliminates hover state duplication in MetricCardGlass, YearCardGlass,\n * AICardGlass, RepositoryCardGlass, and other card components.\n *\n * Features:\n * - Hover lift animation (translateY -2px)\n * - Optional glow effects\n * - Glass surface with backdrop blur\n * - Configurable backgrounds and borders\n */\n\nimport { forwardRef, type HTMLAttributes, type CSSProperties } from 'react';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\n\n/**\n * Props for the InteractiveCard component\n */\nexport interface InteractiveCardProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Enable hover lift effect (translateY -2px)\n * @default true\n */\n hoverLift?: boolean;\n\n /**\n * CSS variable for hover glow effect\n * @example 'var(--glow-primary)'\n */\n hoverGlow?: string;\n\n /**\n * CSS variable for hover background\n * @example 'var(--card-hover-bg)'\n */\n hoverBg?: string;\n\n /**\n * CSS variable for base background\n * @default 'var(--card-bg)'\n */\n baseBg?: string;\n\n /**\n * CSS variable for border color\n * @default 'var(--card-border)'\n */\n borderColor?: string;\n\n /**\n * CSS variable for hover border color\n */\n hoverBorderColor?: string;\n\n /**\n * Blur level for glass effect\n * @default 'sm'\n */\n blur?: 'sm' | 'md' | 'lg' | 'xl';\n\n /**\n * Disable all hover interactions\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Border radius class\n * @default 'rounded-2xl'\n */\n rounded?: 'rounded-xl' | 'rounded-2xl' | 'rounded-3xl';\n\n /**\n * Transition speed\n * @default 'var(--transition-slow)'\n */\n transition?: string;\n}\n\n/**\n * InteractiveCard component\n *\n * Provides consistent hover animations and glass effects for card components.\n * Replaces ~80 lines of duplicated hover state management across 4+ components.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <InteractiveCard>\n * <h3>Card Title</h3>\n * <p>Card content</p>\n * </InteractiveCard>\n *\n * // With hover effects\n * <InteractiveCard\n * hoverLift\n * hoverGlow=\"var(--glow-primary)\"\n * hoverBg=\"var(--card-hover-bg)\"\n * hoverBorderColor=\"var(--card-hover-border)\"\n * >\n * <MetricContent />\n * </InteractiveCard>\n *\n * // Custom blur and rounding\n * <InteractiveCard\n * blur=\"md\"\n * rounded=\"rounded-3xl\"\n * baseBg=\"var(--metric-success-bg)\"\n * >\n * <StatusCard />\n * </InteractiveCard>\n * ```\n */\nexport const InteractiveCard = forwardRef<HTMLDivElement, InteractiveCardProps>(\n (\n {\n hoverLift = true,\n hoverGlow,\n hoverBg,\n baseBg = 'var(--card-bg)',\n borderColor = 'var(--card-border)',\n hoverBorderColor,\n blur = 'sm',\n disabled = false,\n rounded = 'rounded-2xl',\n transition = 'var(--transition-slow)',\n className,\n style,\n children,\n ...props\n },\n ref\n ) => {\n const { isHovered, hoverProps } = useHover({ includeFocus: !disabled });\n\n const cardStyles: CSSProperties = {\n // Background\n background: isHovered && hoverBg ? hoverBg : baseBg,\n\n // Border\n border: `1px solid ${isHovered && hoverBorderColor ? hoverBorderColor : borderColor}`,\n\n // Glassmorphism\n backdropFilter: `blur(var(--blur-${blur}))`,\n WebkitBackdropFilter: `blur(var(--blur-${blur}))`,\n\n // Hover transform\n transform: hoverLift && isHovered && !disabled ? 'translateY(-2px)' : 'translateY(0)',\n\n // Glow effect\n boxShadow: isHovered && hoverGlow && !disabled ? hoverGlow : 'none',\n\n // Transition\n transition: `all ${transition}`,\n\n // User styles override\n ...style,\n };\n\n return (\n <div\n ref={ref}\n className={cn(rounded, className)}\n style={cardStyles}\n {...(disabled ? {} : hoverProps)}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nInteractiveCard.displayName = 'InteractiveCard';\n"
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"categories": [
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"path": "components/glass/specialized/language-bar-glass.tsx",
|
|
16
16
|
"type": "registry:component",
|
|
17
|
-
"content": "// ========================================\n// LANGUAGE BAR GLASS COMPONENT\n// Language/skill proficiency bar with legend\n// ========================================\n\nimport { forwardRef, useState, type CSSProperties } from
|
|
17
|
+
"content": "// ========================================\n// LANGUAGE BAR GLASS COMPONENT\n// Language/skill proficiency bar with legend\n// ========================================\n\nimport { forwardRef, useState, type CSSProperties } from 'react';\nimport { cn } from '@/lib/utils';\nimport '@/glass-theme.css';\n\nexport interface LanguageData {\n readonly name: string;\n readonly percent: number;\n readonly color?: string;\n}\n\nexport interface LanguageBarGlassProps extends React.HTMLAttributes<HTMLDivElement> {\n readonly languages: readonly LanguageData[];\n readonly showLegend?: boolean;\n}\n\nconst defaultLangColors: Record<string, string> = {\n TypeScript: 'bg-blue-500',\n JavaScript: 'bg-yellow-400',\n Python: 'bg-emerald-500',\n HTML: 'bg-orange-500',\n CSS: 'bg-purple-500',\n Java: 'bg-red-500',\n Go: 'bg-cyan-500',\n Rust: 'bg-orange-600',\n Ruby: 'bg-red-600',\n PHP: 'bg-indigo-500',\n};\n\nexport const LanguageBarGlass = forwardRef<HTMLDivElement, LanguageBarGlassProps>(\n ({ languages = [], showLegend = true, className, ...props }, ref) => {\n const [hoveredLang, setHoveredLang] = useState<number | null>(null);\n\n const barStyles: CSSProperties = {\n boxShadow: 'var(--rainbow-glow)',\n };\n\n // Early return if no languages provided\n if (!languages || languages.length === 0) {\n return null;\n }\n\n return (\n <div ref={ref} className={cn('w-full', className)} {...props}>\n {/* Progress bar */}\n <div\n className=\"flex h-2 md:h-2.5 rounded-full overflow-hidden\"\n style={barStyles}\n role=\"group\"\n aria-label=\"Language distribution\"\n >\n {languages.map((lang, i) => {\n const colorClass = lang.color ?? defaultLangColors[lang.name] ?? 'bg-slate-400';\n const segmentStyles: CSSProperties = {\n width: `${lang.percent}%`,\n opacity: hoveredLang !== null && hoveredLang !== i ? 0.5 : 1,\n transition: 'all 0.3s',\n };\n\n return (\n <div\n key={`bar-${lang.name}-${i}`}\n className={cn(colorClass)}\n style={segmentStyles}\n role=\"progressbar\"\n aria-label={`${lang.name}: ${lang.percent}%`}\n aria-valuenow={lang.percent}\n aria-valuemin={0}\n aria-valuemax={100}\n onMouseEnter={() => setHoveredLang(i)}\n onMouseLeave={() => setHoveredLang(null)}\n />\n );\n })}\n </div>\n\n {/* Legend */}\n {showLegend && (\n <div className=\"flex items-center gap-3 md:gap-4 mt-1.5 md:mt-2 text-(length:--font-size-2xs) md:text-xs flex-wrap text-(--text-secondary)\">\n {languages.map((lang, i) => {\n const colorClass = lang.color ?? defaultLangColors[lang.name] ?? 'bg-slate-400';\n\n return (\n <span\n key={`legend-${lang.name}-${i}`}\n className=\"flex items-center gap-1 md:gap-1.5 cursor-pointer\"\n onMouseEnter={() => setHoveredLang(i)}\n onMouseLeave={() => setHoveredLang(null)}\n >\n <span className={cn('w-2 h-2 md:w-2.5 md:h-2.5 rounded-full', colorClass)} />\n {lang.name} {lang.percent}%\n </span>\n );\n })}\n </div>\n )}\n </div>\n );\n }\n);\n\nLanguageBarGlass.displayName = 'LanguageBarGlass';\n"
|
|
18
18
|
}
|
|
19
19
|
],
|
|
20
20
|
"categories": [
|