@devalok/shilp-sutra 0.42.1 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +78 -0
- package/dist/_chunks/chat.js +164 -163
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/mention-suggestion.js +35 -33
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/oauth-button.js +102 -97
- package/dist/_chunks/oauth-button.js.map +1 -1
- package/dist/_chunks/popover.js +1 -1
- package/dist/_chunks/popover.js.map +1 -1
- package/dist/_chunks/shared.js +1 -1
- package/dist/_chunks/shared.js.map +1 -1
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/ai/command-bar.js +1 -1
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/composed/bulk-action-bar.js +1 -1
- package/dist/composed/bulk-action-bar.js.map +1 -1
- package/dist/composed/command-palette.js +4 -4
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.d.ts +6 -0
- package/dist/composed/content-card.d.ts.map +1 -1
- package/dist/composed/content-card.js +1 -1
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/error-boundary.js +1 -1
- package/dist/composed/error-boundary.js.map +1 -1
- package/dist/composed/extensions/emoji-suggestion.js +1 -1
- package/dist/composed/extensions/emoji-suggestion.js.map +1 -1
- package/dist/composed/extensions/file-attachment.d.ts.map +1 -1
- package/dist/composed/file-preview/audio-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js +147 -143
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.js +5 -2
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/master-detail.js +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/page-header.js +1 -1
- package/dist/composed/page-header.js.map +1 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/audio-player.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +600 -591
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.d.ts.map +1 -1
- package/dist/composed/rich-text-editor.js +166 -164
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/shell/notification-center.d.ts.map +1 -1
- package/dist/shell/notification-center.js +102 -98
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/sidebar.d.ts +6 -0
- package/dist/shell/sidebar.d.ts.map +1 -1
- package/dist/shell/sidebar.js +142 -118
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/top-bar.d.ts.map +1 -1
- package/dist/shell/top-bar.js +87 -84
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/semantic.css +9 -2
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/autocomplete.js +1 -1
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/avatar.js +1 -1
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/breadcrumb.js +2 -2
- package/dist/ui/breadcrumb.js.map +1 -1
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.d.ts +82 -7
- package/dist/ui/card.d.ts.map +1 -1
- package/dist/ui/card.js +76 -110
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/color-input.js +1 -1
- package/dist/ui/color-input.js.map +1 -1
- package/dist/ui/combobox.js +3 -3
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/context-menu.js +2 -2
- package/dist/ui/context-menu.js.map +1 -1
- package/dist/ui/data-table-bulk-actions.js +1 -1
- package/dist/ui/data-table-bulk-actions.js.map +1 -1
- package/dist/ui/dialog.js +1 -1
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dropdown-menu.js +11 -5
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/hover-card.js +1 -1
- package/dist/ui/hover-card.js.map +1 -1
- package/dist/ui/index.d.ts +3 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +58 -56
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input-otp.js +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/menubar.js +12 -6
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/navigation-menu.js +1 -1
- package/dist/ui/navigation-menu.js.map +1 -1
- package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -1
- package/dist/ui/select.js +6 -3
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sidebar.js +74 -74
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/split-button.js +1 -1
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/stat-card.d.ts +26 -3
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +183 -150
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/stat-flash.d.ts +46 -0
- package/dist/ui/stat-flash.d.ts.map +1 -0
- package/dist/ui/stat-flash.js +114 -0
- package/dist/ui/stat-flash.js.map +1 -0
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +5 -2
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/toast.js +2 -2
- package/dist/ui/toast.js.map +1 -1
- package/dist/ui/truncated-text.d.ts +37 -0
- package/dist/ui/truncated-text.d.ts.map +1 -0
- package/dist/ui/truncated-text.js +53 -0
- package/dist/ui/truncated-text.js.map +1 -0
- package/docs/components/ui/card.md +13 -4
- package/docs/components/ui/stat-card.md +18 -3
- package/docs/components/ui/stat-flash.md +44 -0
- package/docs/components/ui/truncated-text.md +49 -0
- package/llms-full.txt +125 -8
- package/make-kit/components/card.md +14 -4
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
- package/skill/references/components-full.md +125 -8
package/dist/ui/split-button.js
CHANGED
|
@@ -224,7 +224,7 @@ var S = s.forwardRef(function({ children: S, onClick: C, dropdownContent: w, ope
|
|
|
224
224
|
scale: .95
|
|
225
225
|
},
|
|
226
226
|
transition: { duration: a.moderate01 },
|
|
227
|
-
className: "rounded-overlay
|
|
227
|
+
className: "rounded-overlay bg-surface-overlay shadow-floating",
|
|
228
228
|
children: w
|
|
229
229
|
})
|
|
230
230
|
}) })] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split-button.js","names":[],"sources":["../../src/ui/split-button.tsx"],"sourcesContent":["'use client'\n\nimport { autoUpdate, computePosition, flip, offset, type Placement,shift } from '@floating-ui/dom'\nimport { type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { buttonVariants } from './button'\nimport { durations } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// ── Types ───────────────────────────────────────────────────────\n\ntype SplitButtonVariant = 'solid' | 'soft' | 'outline'\ntype SplitButtonColor = NonNullable<VariantProps<typeof buttonVariants>['color']>\ntype SplitButtonSize = 'xs' | 'sm' | 'md' | 'icon-xs' | 'icon-sm' | 'icon-md'\n\nexport interface SplitButtonProps {\n /** Primary action content (left side). */\n children: React.ReactNode\n /** Primary click handler (left side). */\n onClick: (e: React.MouseEvent<HTMLButtonElement>) => void\n /** Content rendered inside the floating dropdown panel. */\n dropdownContent?: React.ReactNode\n /** Controlled open state. */\n open?: boolean\n /** Called when open state changes. Uncontrolled if omitted. */\n onOpenChange?: (open: boolean) => void\n /** @default 'solid' */\n variant?: SplitButtonVariant\n /** @default 'accent' */\n color?: SplitButtonColor\n /** @default 'md' */\n size?: SplitButtonSize\n /** Disable both halves. */\n disabled?: boolean\n /** aria-label for the primary button. */\n 'aria-label'?: string\n /** aria-label for the dropdown trigger. @default 'More options' */\n dropdownLabel?: string\n /** Custom icon for the dropdown trigger. Defaults to chevron-down. */\n dropdownIcon?: React.ReactNode\n /** Which side the dropdown trigger sits on. @default 'right' */\n triggerSide?: 'left' | 'right'\n /** Preferred placement for the dropdown panel. @default 'top-end' */\n placement?: Placement\n /** Width of the trigger (chevron) half. @default 'auto' */\n triggerWidth?: number | string\n className?: string\n}\n\n// ── Styling maps ────────────────────────────────────────────────\n\nconst dividerColor: Record<SplitButtonVariant, Record<string, string>> = {\n solid: {\n accent: 'bg-accent-11/20', error: 'bg-error-11/20', success: 'bg-success-11/20',\n warning: 'bg-warning-11/20', neutral: 'bg-neutral-8/30',\n },\n soft: {\n accent: 'bg-accent-6', error: 'bg-error-6', success: 'bg-success-6',\n warning: 'bg-warning-6', neutral: 'bg-surface-border',\n },\n outline: {\n accent: 'bg-accent-7', error: 'bg-error-7', success: 'bg-success-7',\n warning: 'bg-warning-7', neutral: 'bg-surface-border-strong',\n },\n}\n\nconst heightClass: Record<SplitButtonSize, string> = {\n xs: 'h-ds-xs-plus', sm: 'h-ds-sm', md: 'h-ds-md',\n 'icon-xs': 'h-ds-xs-plus', 'icon-sm': 'h-ds-sm', 'icon-md': 'h-ds-md',\n}\n\nconst textClass: Record<SplitButtonSize, string> = {\n xs: 'text-ds-sm', sm: 'text-ds-sm', md: 'text-ds-md',\n 'icon-xs': 'text-ds-sm', 'icon-sm': 'text-ds-sm', 'icon-md': 'text-ds-md',\n}\n\nconst primaryPadding: Record<SplitButtonSize, string> = {\n xs: 'px-ds-03 gap-1', sm: 'px-ds-04 gap-1.5', md: 'px-ds-05 gap-2',\n 'icon-xs': 'px-ds-02', 'icon-sm': 'px-ds-03', 'icon-md': 'px-ds-04',\n}\n\nconst triggerPadding: Record<SplitButtonSize, string> = {\n xs: 'px-ds-02', sm: 'px-ds-02', md: 'px-ds-03',\n 'icon-xs': 'px-ds-01', 'icon-sm': 'px-ds-02', 'icon-md': 'px-ds-02',\n}\n\nconst radiusClass: Record<SplitButtonSize, string> = {\n xs: 'rounded-control', sm: 'rounded-control', md: 'rounded-control',\n 'icon-xs': 'rounded-control', 'icon-sm': 'rounded-control', 'icon-md': 'rounded-control',\n}\n\nfunction getHalfClasses(variant: SplitButtonVariant, color: string): string {\n const map: Record<SplitButtonVariant, Record<string, string>> = {\n solid: {\n accent: 'bg-accent-9 text-accent-fg hover:bg-accent-10 active:bg-accent-11',\n error: 'bg-error-9 text-error-fg hover:bg-error-10 active:bg-error-11',\n success: 'bg-success-9 text-success-fg hover:bg-success-10 active:bg-success-11',\n warning: 'bg-warning-9 text-warning-fg hover:bg-warning-10 active:bg-warning-11',\n neutral: 'bg-neutral-5 text-surface-fg hover:bg-neutral-7 active:bg-neutral-8',\n },\n soft: {\n accent: 'bg-accent-3 text-accent-11 hover:bg-accent-4 active:bg-accent-5',\n error: 'bg-error-3 text-error-11 hover:bg-error-4 active:bg-error-5',\n success: 'bg-success-3 text-success-11 hover:bg-success-4 active:bg-success-5',\n warning: 'bg-warning-3 text-warning-11 hover:bg-warning-4 active:bg-warning-5',\n neutral: 'bg-surface-raised-hover text-surface-fg-muted hover:bg-surface-raised-active active:bg-neutral-5',\n },\n outline: {\n accent: 'bg-transparent text-accent-11 hover:bg-accent-3 active:bg-accent-4',\n error: 'bg-transparent text-error-11 hover:bg-error-3 active:bg-error-4',\n success: 'bg-transparent text-success-11 hover:bg-success-3 active:bg-success-4',\n warning: 'bg-transparent text-warning-11 hover:bg-warning-3 active:bg-warning-4',\n neutral: 'bg-transparent text-surface-fg hover:bg-surface-raised-hover active:bg-surface-raised-active',\n },\n }\n return map[variant][color] ?? map[variant].accent\n}\n\nfunction getOutlineBorderColor(color: string): string {\n const map: Record<string, string> = {\n accent: 'border-accent-7', error: 'border-error-7', success: 'border-success-7',\n warning: 'border-warning-7', neutral: 'border-surface-border-strong',\n }\n return map[color] ?? map.accent\n}\n\n// ── Chevron SVG ─────────────────────────────────────────────────\n\nfunction ChevronDown({ className }: { className?: string }) {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" className={className} aria-hidden=\"true\">\n <path d=\"M3 4.5L6 7.5L9 4.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\n// ── Component ───────────────────────────────────────────────────\n\nconst SplitButton = React.forwardRef<HTMLDivElement, SplitButtonProps>(\n function SplitButton(\n {\n children,\n onClick,\n dropdownContent,\n open: openProp,\n onOpenChange,\n variant = 'solid',\n color = 'accent',\n size = 'md',\n disabled = false,\n 'aria-label': ariaLabel,\n dropdownLabel = 'More options',\n dropdownIcon,\n triggerSide = 'right',\n placement: placementProp = 'top-end',\n triggerWidth,\n className,\n },\n ref,\n ) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isControlled = openProp !== undefined\n const isOpen = isControlled ? openProp : internalOpen\n\n const anchorRef = React.useRef<HTMLDivElement>(null)\n const floatingRef = React.useRef<HTMLDivElement>(null)\n const menuId = React.useId()\n\n const setOpen = React.useCallback(\n (value: boolean) => {\n if (onOpenChange) onOpenChange(value)\n if (!isControlled) setInternalOpen(value)\n },\n [onOpenChange, isControlled],\n )\n\n // ── Floating UI positioning ──\n React.useEffect(() => {\n if (!isOpen || !anchorRef.current || !floatingRef.current) return\n\n const anchor = anchorRef.current\n const floating = floatingRef.current\n\n const update = () => {\n computePosition(anchor, floating, {\n placement: placementProp,\n middleware: [\n offset(8),\n flip({ fallbackPlacements: ['bottom-end', 'top-start', 'bottom-start'] }),\n shift({ padding: 8 }),\n ],\n }).then(({ x, y }) => {\n Object.assign(floating.style, { left: `${x}px`, top: `${y}px` })\n })\n }\n\n const cleanup = autoUpdate(anchor, floating, update)\n return cleanup\n }, [isOpen, placementProp])\n\n // ── Close on outside click ──\n React.useEffect(() => {\n if (!isOpen) return\n const handleClick = (e: MouseEvent) => {\n const target = e.target as Node\n if (\n anchorRef.current?.contains(target) ||\n floatingRef.current?.contains(target)\n ) return\n setOpen(false)\n }\n document.addEventListener('mousedown', handleClick)\n return () => document.removeEventListener('mousedown', handleClick)\n }, [isOpen, setOpen])\n\n // ── Close on Escape ──\n React.useEffect(() => {\n if (!isOpen) return\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('keydown', handleKey)\n return () => document.removeEventListener('keydown', handleKey)\n }, [isOpen, setOpen])\n\n const halfClasses = getHalfClasses(variant, color)\n const divider = dividerColor[variant][color] ?? dividerColor[variant].accent\n\n const triggerStyle = triggerWidth != null\n ? { width: typeof triggerWidth === 'number' ? `${triggerWidth}px` : triggerWidth }\n : undefined\n\n return (\n <>\n {/* Button group */}\n <div\n ref={ref}\n role=\"group\"\n aria-label={ariaLabel ?? undefined}\n className={cn('relative inline-flex', className)}\n >\n <div\n ref={anchorRef}\n className={cn(\n 'inline-flex items-stretch overflow-hidden',\n radiusClass[size],\n variant === 'solid' && 'shadow-raised',\n variant === 'outline' && `border ${getOutlineBorderColor(color)}`,\n )}\n >\n {triggerSide === 'left' && (\n <>\n {/* Dropdown trigger (left) */}\n <button\n type=\"button\"\n onClick={() => setOpen(!isOpen)}\n disabled={disabled}\n aria-label={dropdownLabel}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? menuId : undefined}\n className={cn(\n 'inline-flex items-center justify-center select-none',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-inset',\n 'disabled:pointer-events-none disabled:opacity-action-disabled',\n halfClasses,\n heightClass[size],\n triggerPadding[size],\n )}\n style={triggerStyle}\n >\n {dropdownIcon ?? <ChevronDown />}\n </button>\n <div className={cn('w-px self-stretch', divider)} />\n </>\n )}\n\n {/* Primary action */}\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n aria-label={ariaLabel}\n className={cn(\n 'inline-flex items-center justify-center font-semibold select-none whitespace-nowrap',\n 'transition-[colors,transform] duration-fast-01 ease-productive-standard',\n 'active:scale-[0.97]',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-inset',\n 'disabled:pointer-events-none disabled:opacity-action-disabled',\n halfClasses,\n heightClass[size],\n textClass[size],\n primaryPadding[size],\n )}\n >\n {children}\n </button>\n\n {triggerSide === 'right' && (\n <>\n <div className={cn('w-px self-stretch', divider)} />\n {/* Dropdown trigger (right) */}\n <button\n type=\"button\"\n onClick={() => setOpen(!isOpen)}\n disabled={disabled}\n aria-label={dropdownLabel}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? menuId : undefined}\n className={cn(\n 'inline-flex items-center justify-center select-none',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-inset',\n 'disabled:pointer-events-none disabled:opacity-action-disabled',\n halfClasses,\n heightClass[size],\n triggerPadding[size],\n )}\n style={triggerStyle}\n >\n {dropdownIcon ?? <ChevronDown />}\n </button>\n </>\n )}\n </div>\n </div>\n\n {/* Floating dropdown panel */}\n <AnimatePresence>\n {isOpen && dropdownContent && (\n <div\n ref={floatingRef}\n id={menuId}\n role=\"menu\"\n className=\"fixed z-popover\"\n style={{ top: 0, left: 0 }}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={{ duration: durations.moderate01 }}\n className=\"rounded-overlay border border-surface-border-strong bg-surface-overlay shadow-floating\"\n >\n {dropdownContent}\n </motion.div>\n </div>\n )}\n </AnimatePresence>\n </>\n )\n },\n)\n\nSplitButton.displayName = 'SplitButton'\n\nexport { SplitButton }\nexport type { SplitButtonColor, SplitButtonSize,SplitButtonVariant }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"split-button.js","names":[],"sources":["../../src/ui/split-button.tsx"],"sourcesContent":["'use client'\n\nimport { autoUpdate, computePosition, flip, offset, type Placement,shift } from '@floating-ui/dom'\nimport { type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { buttonVariants } from './button'\nimport { durations } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// ── Types ───────────────────────────────────────────────────────\n\ntype SplitButtonVariant = 'solid' | 'soft' | 'outline'\ntype SplitButtonColor = NonNullable<VariantProps<typeof buttonVariants>['color']>\ntype SplitButtonSize = 'xs' | 'sm' | 'md' | 'icon-xs' | 'icon-sm' | 'icon-md'\n\nexport interface SplitButtonProps {\n /** Primary action content (left side). */\n children: React.ReactNode\n /** Primary click handler (left side). */\n onClick: (e: React.MouseEvent<HTMLButtonElement>) => void\n /** Content rendered inside the floating dropdown panel. */\n dropdownContent?: React.ReactNode\n /** Controlled open state. */\n open?: boolean\n /** Called when open state changes. Uncontrolled if omitted. */\n onOpenChange?: (open: boolean) => void\n /** @default 'solid' */\n variant?: SplitButtonVariant\n /** @default 'accent' */\n color?: SplitButtonColor\n /** @default 'md' */\n size?: SplitButtonSize\n /** Disable both halves. */\n disabled?: boolean\n /** aria-label for the primary button. */\n 'aria-label'?: string\n /** aria-label for the dropdown trigger. @default 'More options' */\n dropdownLabel?: string\n /** Custom icon for the dropdown trigger. Defaults to chevron-down. */\n dropdownIcon?: React.ReactNode\n /** Which side the dropdown trigger sits on. @default 'right' */\n triggerSide?: 'left' | 'right'\n /** Preferred placement for the dropdown panel. @default 'top-end' */\n placement?: Placement\n /** Width of the trigger (chevron) half. @default 'auto' */\n triggerWidth?: number | string\n className?: string\n}\n\n// ── Styling maps ────────────────────────────────────────────────\n\nconst dividerColor: Record<SplitButtonVariant, Record<string, string>> = {\n solid: {\n accent: 'bg-accent-11/20', error: 'bg-error-11/20', success: 'bg-success-11/20',\n warning: 'bg-warning-11/20', neutral: 'bg-neutral-8/30',\n },\n soft: {\n accent: 'bg-accent-6', error: 'bg-error-6', success: 'bg-success-6',\n warning: 'bg-warning-6', neutral: 'bg-surface-border',\n },\n outline: {\n accent: 'bg-accent-7', error: 'bg-error-7', success: 'bg-success-7',\n warning: 'bg-warning-7', neutral: 'bg-surface-border-strong',\n },\n}\n\nconst heightClass: Record<SplitButtonSize, string> = {\n xs: 'h-ds-xs-plus', sm: 'h-ds-sm', md: 'h-ds-md',\n 'icon-xs': 'h-ds-xs-plus', 'icon-sm': 'h-ds-sm', 'icon-md': 'h-ds-md',\n}\n\nconst textClass: Record<SplitButtonSize, string> = {\n xs: 'text-ds-sm', sm: 'text-ds-sm', md: 'text-ds-md',\n 'icon-xs': 'text-ds-sm', 'icon-sm': 'text-ds-sm', 'icon-md': 'text-ds-md',\n}\n\nconst primaryPadding: Record<SplitButtonSize, string> = {\n xs: 'px-ds-03 gap-1', sm: 'px-ds-04 gap-1.5', md: 'px-ds-05 gap-2',\n 'icon-xs': 'px-ds-02', 'icon-sm': 'px-ds-03', 'icon-md': 'px-ds-04',\n}\n\nconst triggerPadding: Record<SplitButtonSize, string> = {\n xs: 'px-ds-02', sm: 'px-ds-02', md: 'px-ds-03',\n 'icon-xs': 'px-ds-01', 'icon-sm': 'px-ds-02', 'icon-md': 'px-ds-02',\n}\n\nconst radiusClass: Record<SplitButtonSize, string> = {\n xs: 'rounded-control', sm: 'rounded-control', md: 'rounded-control',\n 'icon-xs': 'rounded-control', 'icon-sm': 'rounded-control', 'icon-md': 'rounded-control',\n}\n\nfunction getHalfClasses(variant: SplitButtonVariant, color: string): string {\n const map: Record<SplitButtonVariant, Record<string, string>> = {\n solid: {\n accent: 'bg-accent-9 text-accent-fg hover:bg-accent-10 active:bg-accent-11',\n error: 'bg-error-9 text-error-fg hover:bg-error-10 active:bg-error-11',\n success: 'bg-success-9 text-success-fg hover:bg-success-10 active:bg-success-11',\n warning: 'bg-warning-9 text-warning-fg hover:bg-warning-10 active:bg-warning-11',\n neutral: 'bg-neutral-5 text-surface-fg hover:bg-neutral-7 active:bg-neutral-8',\n },\n soft: {\n accent: 'bg-accent-3 text-accent-11 hover:bg-accent-4 active:bg-accent-5',\n error: 'bg-error-3 text-error-11 hover:bg-error-4 active:bg-error-5',\n success: 'bg-success-3 text-success-11 hover:bg-success-4 active:bg-success-5',\n warning: 'bg-warning-3 text-warning-11 hover:bg-warning-4 active:bg-warning-5',\n neutral: 'bg-surface-raised-hover text-surface-fg-muted hover:bg-surface-raised-active active:bg-neutral-5',\n },\n outline: {\n accent: 'bg-transparent text-accent-11 hover:bg-accent-3 active:bg-accent-4',\n error: 'bg-transparent text-error-11 hover:bg-error-3 active:bg-error-4',\n success: 'bg-transparent text-success-11 hover:bg-success-3 active:bg-success-4',\n warning: 'bg-transparent text-warning-11 hover:bg-warning-3 active:bg-warning-4',\n neutral: 'bg-transparent text-surface-fg hover:bg-surface-raised-hover active:bg-surface-raised-active',\n },\n }\n return map[variant][color] ?? map[variant].accent\n}\n\nfunction getOutlineBorderColor(color: string): string {\n const map: Record<string, string> = {\n accent: 'border-accent-7', error: 'border-error-7', success: 'border-success-7',\n warning: 'border-warning-7', neutral: 'border-surface-border-strong',\n }\n return map[color] ?? map.accent\n}\n\n// ── Chevron SVG ─────────────────────────────────────────────────\n\nfunction ChevronDown({ className }: { className?: string }) {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" className={className} aria-hidden=\"true\">\n <path d=\"M3 4.5L6 7.5L9 4.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\n// ── Component ───────────────────────────────────────────────────\n\nconst SplitButton = React.forwardRef<HTMLDivElement, SplitButtonProps>(\n function SplitButton(\n {\n children,\n onClick,\n dropdownContent,\n open: openProp,\n onOpenChange,\n variant = 'solid',\n color = 'accent',\n size = 'md',\n disabled = false,\n 'aria-label': ariaLabel,\n dropdownLabel = 'More options',\n dropdownIcon,\n triggerSide = 'right',\n placement: placementProp = 'top-end',\n triggerWidth,\n className,\n },\n ref,\n ) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isControlled = openProp !== undefined\n const isOpen = isControlled ? openProp : internalOpen\n\n const anchorRef = React.useRef<HTMLDivElement>(null)\n const floatingRef = React.useRef<HTMLDivElement>(null)\n const menuId = React.useId()\n\n const setOpen = React.useCallback(\n (value: boolean) => {\n if (onOpenChange) onOpenChange(value)\n if (!isControlled) setInternalOpen(value)\n },\n [onOpenChange, isControlled],\n )\n\n // ── Floating UI positioning ──\n React.useEffect(() => {\n if (!isOpen || !anchorRef.current || !floatingRef.current) return\n\n const anchor = anchorRef.current\n const floating = floatingRef.current\n\n const update = () => {\n computePosition(anchor, floating, {\n placement: placementProp,\n middleware: [\n offset(8),\n flip({ fallbackPlacements: ['bottom-end', 'top-start', 'bottom-start'] }),\n shift({ padding: 8 }),\n ],\n }).then(({ x, y }) => {\n Object.assign(floating.style, { left: `${x}px`, top: `${y}px` })\n })\n }\n\n const cleanup = autoUpdate(anchor, floating, update)\n return cleanup\n }, [isOpen, placementProp])\n\n // ── Close on outside click ──\n React.useEffect(() => {\n if (!isOpen) return\n const handleClick = (e: MouseEvent) => {\n const target = e.target as Node\n if (\n anchorRef.current?.contains(target) ||\n floatingRef.current?.contains(target)\n ) return\n setOpen(false)\n }\n document.addEventListener('mousedown', handleClick)\n return () => document.removeEventListener('mousedown', handleClick)\n }, [isOpen, setOpen])\n\n // ── Close on Escape ──\n React.useEffect(() => {\n if (!isOpen) return\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('keydown', handleKey)\n return () => document.removeEventListener('keydown', handleKey)\n }, [isOpen, setOpen])\n\n const halfClasses = getHalfClasses(variant, color)\n const divider = dividerColor[variant][color] ?? dividerColor[variant].accent\n\n const triggerStyle = triggerWidth != null\n ? { width: typeof triggerWidth === 'number' ? `${triggerWidth}px` : triggerWidth }\n : undefined\n\n return (\n <>\n {/* Button group */}\n <div\n ref={ref}\n role=\"group\"\n aria-label={ariaLabel ?? undefined}\n className={cn('relative inline-flex', className)}\n >\n <div\n ref={anchorRef}\n className={cn(\n 'inline-flex items-stretch overflow-hidden',\n radiusClass[size],\n variant === 'solid' && 'shadow-raised',\n variant === 'outline' && `border ${getOutlineBorderColor(color)}`,\n )}\n >\n {triggerSide === 'left' && (\n <>\n {/* Dropdown trigger (left) */}\n <button\n type=\"button\"\n onClick={() => setOpen(!isOpen)}\n disabled={disabled}\n aria-label={dropdownLabel}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? menuId : undefined}\n className={cn(\n 'inline-flex items-center justify-center select-none',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-inset',\n 'disabled:pointer-events-none disabled:opacity-action-disabled',\n halfClasses,\n heightClass[size],\n triggerPadding[size],\n )}\n style={triggerStyle}\n >\n {dropdownIcon ?? <ChevronDown />}\n </button>\n <div className={cn('w-px self-stretch', divider)} />\n </>\n )}\n\n {/* Primary action */}\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n aria-label={ariaLabel}\n className={cn(\n 'inline-flex items-center justify-center font-semibold select-none whitespace-nowrap',\n 'transition-[colors,transform] duration-fast-01 ease-productive-standard',\n 'active:scale-[0.97]',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-inset',\n 'disabled:pointer-events-none disabled:opacity-action-disabled',\n halfClasses,\n heightClass[size],\n textClass[size],\n primaryPadding[size],\n )}\n >\n {children}\n </button>\n\n {triggerSide === 'right' && (\n <>\n <div className={cn('w-px self-stretch', divider)} />\n {/* Dropdown trigger (right) */}\n <button\n type=\"button\"\n onClick={() => setOpen(!isOpen)}\n disabled={disabled}\n aria-label={dropdownLabel}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? menuId : undefined}\n className={cn(\n 'inline-flex items-center justify-center select-none',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-inset',\n 'disabled:pointer-events-none disabled:opacity-action-disabled',\n halfClasses,\n heightClass[size],\n triggerPadding[size],\n )}\n style={triggerStyle}\n >\n {dropdownIcon ?? <ChevronDown />}\n </button>\n </>\n )}\n </div>\n </div>\n\n {/* Floating dropdown panel */}\n <AnimatePresence>\n {isOpen && dropdownContent && (\n <div\n ref={floatingRef}\n id={menuId}\n role=\"menu\"\n className=\"fixed z-popover\"\n style={{ top: 0, left: 0 }}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={{ duration: durations.moderate01 }}\n className=\"rounded-overlay bg-surface-overlay shadow-floating\"\n >\n {dropdownContent}\n </motion.div>\n </div>\n )}\n </AnimatePresence>\n </>\n )\n },\n)\n\nSplitButton.displayName = 'SplitButton'\n\nexport { SplitButton }\nexport type { SplitButtonColor, SplitButtonSize,SplitButtonVariant }\n"],"mappings":"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"}
|
package/dist/ui/stat-card.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { IconInput } from './lib/icon-input';
|
|
3
|
+
import { FlashPreset, FlashSpec, FlashSpeed } from './stat-flash';
|
|
3
4
|
import * as React from 'react';
|
|
4
5
|
/**
|
|
5
6
|
* Props for StatCard — a dashboard metric tile displaying a label, a large numeric value,
|
|
6
7
|
* an optional trend delta (with directional arrow icon), and an optional header icon.
|
|
7
8
|
*
|
|
9
|
+
* **Surface:** delegated to `Card` via `variant` — `default` (ring-in-shadow, no border) |
|
|
10
|
+
* `elevated` | `outline` (border, no shadow) | `flat`. StatCard composes `<Card>`, so the surface,
|
|
11
|
+
* padding (gap model), and elevation all live in one place.
|
|
12
|
+
*
|
|
13
|
+
* **Accent:** `accentStyle="none"` (default) is neutral; `"icon"` wraps `icon` in an accent chip
|
|
14
|
+
* (`iconFill="soft" | "solid"`); `"tint"` applies a subtle accent surface wash + accent value.
|
|
15
|
+
* (Replaces the removed `accent` left-rail prop — see CHANGELOG migration.)
|
|
16
|
+
*
|
|
8
17
|
* **Delta direction:** `'up'` renders a green trending-up arrow, `'down'` renders a red
|
|
9
18
|
* trending-down arrow, `'neutral'` renders a grey dash. The `delta.value` is a formatted
|
|
10
19
|
* string (e.g. `"+8%"` or `"−120"`).
|
|
@@ -41,7 +50,7 @@ import * as React from 'react';
|
|
|
41
50
|
* />
|
|
42
51
|
* // These are just a few ways — feel free to combine props creatively!
|
|
43
52
|
*/
|
|
44
|
-
export interface StatCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
53
|
+
export interface StatCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'> {
|
|
45
54
|
/** Heading text for the metric. `title` is an alias for `label`. */
|
|
46
55
|
label?: string;
|
|
47
56
|
/** Alias for `label` — use whichever feels natural. */
|
|
@@ -55,6 +64,8 @@ export interface StatCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
55
64
|
value: string;
|
|
56
65
|
direction: 'up' | 'down' | 'neutral';
|
|
57
66
|
};
|
|
67
|
+
/** Where the delta sits relative to the value: `block` (below — default) or `inline` (on the value's baseline, to its right). @default 'block' */
|
|
68
|
+
deltaPlacement?: 'block' | 'inline';
|
|
58
69
|
icon?: IconInput;
|
|
59
70
|
loading?: boolean;
|
|
60
71
|
/** Comparison period label shown after delta, e.g. "vs last month" */
|
|
@@ -63,8 +74,20 @@ export interface StatCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
63
74
|
secondaryLabel?: string;
|
|
64
75
|
/** Progress toward a target (0-100). Renders a thin progress bar below the value. */
|
|
65
76
|
progress?: number;
|
|
66
|
-
/**
|
|
67
|
-
|
|
77
|
+
/** Surface variant, delegated to Card: `default` (ring-in-shadow) | `elevated` | `outline` (border, no shadow) | `flat`. @default 'default' */
|
|
78
|
+
variant?: 'default' | 'elevated' | 'outline' | 'flat';
|
|
79
|
+
/** How the brand accent reads: `none` (neutral — default), `icon` (accent chip around `icon`), or `tint` (subtle accent surface wash + accent value). */
|
|
80
|
+
accentStyle?: 'none' | 'icon' | 'tint';
|
|
81
|
+
/** When `accentStyle="icon"`: `soft` (tinted chip) or `solid` (filled accent chip). @default 'soft' */
|
|
82
|
+
iconFill?: 'soft' | 'solid';
|
|
83
|
+
/**
|
|
84
|
+
* Opt-in entrance flash: the icon chip mounts showing a transient state (e.g. a green up-arrow)
|
|
85
|
+
* then settles to `icon`. A preset (`'up' | 'down' | 'goal' | 'record' | 'alert' | 'live'`) or an
|
|
86
|
+
* explicit `{ tone, icon }`. Requires `icon`; implies the icon chip. Off by default.
|
|
87
|
+
*/
|
|
88
|
+
flash?: FlashPreset | FlashSpec;
|
|
89
|
+
/** Speed of the entrance flash: `fast` | `normal` | `slow`. @default 'normal' */
|
|
90
|
+
flashSpeed?: FlashSpeed;
|
|
68
91
|
/** Sparkline data points. Renders a mini SVG line chart in the card. */
|
|
69
92
|
sparkline?: number[];
|
|
70
93
|
/** Make the card clickable with hover state */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../src/ui/stat-card.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../src/ui/stat-card.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAKjD,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAY,MAAM,cAAc,CAAA;AAE1F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IACxF,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAA;KACrC,CAAA;IACD,kJAAkJ;IAClJ,cAAc,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IACnC,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+IAA+I;IAC/I,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAA;IACrD,yJAAyJ;IACzJ,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IACtC,uGAAuG;IACvG,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IAC/B,iFAAiF;IACjF,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB;AA+FD,QAAA,MAAM,QAAQ,sFA2Pb,CAAA;AAID,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
package/dist/ui/stat-card.js
CHANGED
|
@@ -4,20 +4,15 @@ import { springs as t, tweens as n } from "./lib/motion.js";
|
|
|
4
4
|
import { cn as r } from "./lib/utils.js";
|
|
5
5
|
import { Icon as i } from "./icon.js";
|
|
6
6
|
import { t as a } from "../_chunks/normalize-icon.js";
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
7
|
+
import { Card as o, CardContent as s } from "./card.js";
|
|
8
|
+
import { n as c } from "../_chunks/link-context.js";
|
|
9
|
+
import { StatFlash as l } from "./stat-flash.js";
|
|
10
|
+
import * as u from "react";
|
|
11
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
12
|
+
import { IconMinus as m, IconTrendingDown as h, IconTrendingUp as g } from "@tabler/icons-react";
|
|
13
|
+
import { motion as _ } from "framer-motion";
|
|
12
14
|
//#region src/ui/stat-card.tsx
|
|
13
|
-
|
|
14
|
-
default: "border-l-accent-9",
|
|
15
|
-
success: "border-l-success-9",
|
|
16
|
-
warning: "border-l-warning-9",
|
|
17
|
-
error: "border-l-error-9",
|
|
18
|
-
info: "border-l-info-9"
|
|
19
|
-
};
|
|
20
|
-
function g(e, t, n) {
|
|
15
|
+
function v(e, t, n) {
|
|
21
16
|
let r = e.filter((e) => Number.isFinite(e));
|
|
22
17
|
if (r.length < 2) return "";
|
|
23
18
|
let i = Math.min(...r), a = Math.max(...r) - i || 1, o = t / (r.length - 1);
|
|
@@ -26,43 +21,43 @@ function g(e, t, n) {
|
|
|
26
21
|
return `${t === 0 ? "M" : "L"}${r.toFixed(1)},${s.toFixed(1)}`;
|
|
27
22
|
}).join(" ");
|
|
28
23
|
}
|
|
29
|
-
function
|
|
30
|
-
let n =
|
|
31
|
-
if (
|
|
24
|
+
function y({ data: e, colorClass: t }) {
|
|
25
|
+
let n = u.useId(), i = u.useRef(null), [a, o] = u.useState(0), s = v(e, 80, 32);
|
|
26
|
+
if (u.useEffect(() => {
|
|
32
27
|
i.current && o(i.current.getTotalLength());
|
|
33
|
-
}, [
|
|
34
|
-
let
|
|
35
|
-
return /* @__PURE__ */
|
|
28
|
+
}, [s]), !s) return null;
|
|
29
|
+
let c = `${s} L${80 .toFixed(1)},${32 .toFixed(1)} L0,${32 .toFixed(1)} Z`;
|
|
30
|
+
return /* @__PURE__ */ p("div", {
|
|
36
31
|
className: r("w-20 h-8", t),
|
|
37
32
|
"aria-hidden": "true",
|
|
38
|
-
children: [/* @__PURE__ */
|
|
33
|
+
children: [/* @__PURE__ */ p("svg", {
|
|
39
34
|
viewBox: "0 0 80 32",
|
|
40
35
|
className: "w-full h-full overflow-visible",
|
|
41
36
|
preserveAspectRatio: "none",
|
|
42
37
|
children: [
|
|
43
|
-
/* @__PURE__ */
|
|
38
|
+
/* @__PURE__ */ f("defs", { children: /* @__PURE__ */ p("linearGradient", {
|
|
44
39
|
id: `sparkline-fill-${n}`,
|
|
45
40
|
x1: "0",
|
|
46
41
|
y1: "0",
|
|
47
42
|
x2: "0",
|
|
48
43
|
y2: "1",
|
|
49
|
-
children: [/* @__PURE__ */
|
|
44
|
+
children: [/* @__PURE__ */ f("stop", {
|
|
50
45
|
offset: "0%",
|
|
51
46
|
stopColor: "currentColor",
|
|
52
47
|
stopOpacity: "0.1"
|
|
53
|
-
}), /* @__PURE__ */
|
|
48
|
+
}), /* @__PURE__ */ f("stop", {
|
|
54
49
|
offset: "100%",
|
|
55
50
|
stopColor: "currentColor",
|
|
56
51
|
stopOpacity: "0"
|
|
57
52
|
})]
|
|
58
53
|
}) }),
|
|
59
|
-
/* @__PURE__ */
|
|
60
|
-
d,
|
|
54
|
+
/* @__PURE__ */ f("path", {
|
|
55
|
+
d: c,
|
|
61
56
|
fill: `url(#sparkline-fill-${n})`
|
|
62
57
|
}),
|
|
63
|
-
/* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ f("path", {
|
|
64
59
|
ref: i,
|
|
65
|
-
d:
|
|
60
|
+
d: s,
|
|
66
61
|
fill: "none",
|
|
67
62
|
stroke: "currentColor",
|
|
68
63
|
strokeWidth: "1.5",
|
|
@@ -76,51 +71,110 @@ function _({ data: e, colorClass: t }) {
|
|
|
76
71
|
}
|
|
77
72
|
})
|
|
78
73
|
]
|
|
79
|
-
}), a > 0 && /* @__PURE__ */
|
|
74
|
+
}), a > 0 && /* @__PURE__ */ f("style", { children: `@keyframes sparkline-draw-${n.replace(/:/g, "")} { to { stroke-dashoffset: 0; } }` })]
|
|
80
75
|
});
|
|
81
76
|
}
|
|
82
|
-
function
|
|
77
|
+
function b({ progress: e, label: t }) {
|
|
83
78
|
let n = Math.max(0, Math.min(100, e)), i = n >= 90 ? "bg-success-9" : n >= 70 ? "bg-warning-9" : "bg-accent-9";
|
|
84
|
-
return /* @__PURE__ */
|
|
79
|
+
return /* @__PURE__ */ f("div", {
|
|
85
80
|
className: "h-1 w-full rounded-pill bg-surface-raised mt-ds-04",
|
|
86
81
|
role: "progressbar",
|
|
87
82
|
"aria-label": `${t} progress`,
|
|
88
83
|
"aria-valuenow": n,
|
|
89
84
|
"aria-valuemin": 0,
|
|
90
85
|
"aria-valuemax": 100,
|
|
91
|
-
children: /* @__PURE__ */
|
|
86
|
+
children: /* @__PURE__ */ f("div", {
|
|
92
87
|
className: r("h-full rounded-pill transition-[width] duration-moderate-02 ease-productive-standard", i),
|
|
93
88
|
style: { width: `${n}%` }
|
|
94
89
|
})
|
|
95
90
|
});
|
|
96
91
|
}
|
|
97
|
-
var
|
|
98
|
-
let
|
|
99
|
-
if (
|
|
100
|
-
ref:
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
var x = u.forwardRef(({ className: u, label: v, title: x, value: S, prefix: C, suffix: w, delta: T, deltaPlacement: E = "block", icon: D, loading: O, comparisonLabel: k, secondaryLabel: A, progress: j, variant: M = "default", accentStyle: N = "none", iconFill: P = "soft", flash: F, flashSpeed: I, sparkline: L, onClick: R, href: z, footer: B, ...V }, H) => {
|
|
93
|
+
let U = c(), W = x ?? v ?? "", G = (R || z) && !V["aria-label"] ? `View ${W}` : V["aria-label"];
|
|
94
|
+
if (O) return /* @__PURE__ */ f(o, {
|
|
95
|
+
ref: H,
|
|
96
|
+
variant: M,
|
|
97
|
+
className: u,
|
|
98
|
+
...V,
|
|
99
|
+
children: /* @__PURE__ */ p(s, { children: [
|
|
100
|
+
/* @__PURE__ */ f("div", { className: "h-ds-04 w-24 rounded-control-inner bg-skeleton-base animate-pulse mb-ds-05" }),
|
|
101
|
+
/* @__PURE__ */ f("div", { className: "h-ds-sm w-32 rounded-control bg-skeleton-base animate-pulse mb-ds-03" }),
|
|
102
|
+
/* @__PURE__ */ f("div", { className: "h-3 w-16 rounded-control-inner bg-skeleton-base animate-pulse" })
|
|
103
|
+
] })
|
|
104
|
+
});
|
|
105
|
+
let K = T?.direction === "up" ? g : T?.direction === "down" ? h : m, q = T?.direction === "up" ? "text-success-11" : T?.direction === "down" ? "text-error-11" : "text-surface-fg-muted", J = T?.direction === "up" ? "text-success-11" : T?.direction === "down" ? "text-error-11" : "text-accent-11", Y = T ? /* @__PURE__ */ p(_.div, {
|
|
106
|
+
className: r("flex items-center gap-ds-02 text-ds-sm font-medium", q, E === "block" && "mt-ds-03"),
|
|
107
|
+
initial: {
|
|
108
|
+
opacity: 0,
|
|
109
|
+
y: 8
|
|
110
|
+
},
|
|
111
|
+
animate: {
|
|
112
|
+
opacity: 1,
|
|
113
|
+
y: 0
|
|
114
|
+
},
|
|
115
|
+
transition: {
|
|
116
|
+
...t.smooth,
|
|
117
|
+
delay: .2
|
|
118
|
+
},
|
|
103
119
|
children: [
|
|
104
|
-
/* @__PURE__ */
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
/* @__PURE__ */ f(_.span, {
|
|
121
|
+
className: "inline-flex",
|
|
122
|
+
initial: {
|
|
123
|
+
opacity: .5,
|
|
124
|
+
scale: 1.4
|
|
125
|
+
},
|
|
126
|
+
animate: {
|
|
127
|
+
opacity: 1,
|
|
128
|
+
scale: 1
|
|
129
|
+
},
|
|
130
|
+
transition: t.bouncy,
|
|
131
|
+
children: /* @__PURE__ */ f(i, {
|
|
132
|
+
icon: K,
|
|
133
|
+
size: "sm"
|
|
134
|
+
})
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ f("span", { children: T.value }),
|
|
137
|
+
k && /* @__PURE__ */ f("span", {
|
|
138
|
+
className: "text-surface-fg-subtle font-normal",
|
|
139
|
+
children: k
|
|
140
|
+
})
|
|
107
141
|
]
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
/* @__PURE__ */ u("div", {
|
|
142
|
+
}) : null, X = /* @__PURE__ */ p(d, { children: [
|
|
143
|
+
/* @__PURE__ */ p("div", {
|
|
111
144
|
className: "flex items-center justify-between mb-ds-04",
|
|
112
|
-
children: [/* @__PURE__ */
|
|
145
|
+
children: [/* @__PURE__ */ f(_.p, {
|
|
113
146
|
className: "text-ds-md font-medium text-surface-fg-muted",
|
|
114
147
|
initial: { opacity: 0 },
|
|
115
148
|
animate: { opacity: 1 },
|
|
116
149
|
transition: n.fade,
|
|
117
|
-
children:
|
|
118
|
-
}), /* @__PURE__ */
|
|
150
|
+
children: W
|
|
151
|
+
}), /* @__PURE__ */ p("div", {
|
|
119
152
|
className: "flex items-center gap-ds-03",
|
|
120
|
-
children: [
|
|
121
|
-
data:
|
|
122
|
-
colorClass:
|
|
123
|
-
}),
|
|
153
|
+
children: [L && L.length >= 2 && /* @__PURE__ */ f(y, {
|
|
154
|
+
data: L,
|
|
155
|
+
colorClass: J
|
|
156
|
+
}), D && F ? /* @__PURE__ */ f(l, {
|
|
157
|
+
icon: D,
|
|
158
|
+
flash: F,
|
|
159
|
+
fill: P,
|
|
160
|
+
speed: I
|
|
161
|
+
}) : D ? N === "icon" ? /* @__PURE__ */ f(_.span, {
|
|
162
|
+
className: r("inline-flex items-center justify-center rounded-control p-ds-02", P === "solid" ? "bg-accent-9 text-accent-fg" : "bg-accent-3 text-accent-11"),
|
|
163
|
+
initial: {
|
|
164
|
+
opacity: 0,
|
|
165
|
+
scale: .96
|
|
166
|
+
},
|
|
167
|
+
animate: {
|
|
168
|
+
opacity: 1,
|
|
169
|
+
scale: 1
|
|
170
|
+
},
|
|
171
|
+
transition: t.snappy,
|
|
172
|
+
"aria-hidden": "true",
|
|
173
|
+
children: /* @__PURE__ */ f(e, {
|
|
174
|
+
size: "md",
|
|
175
|
+
children: a(D, "md")
|
|
176
|
+
})
|
|
177
|
+
}) : /* @__PURE__ */ f(_.span, {
|
|
124
178
|
className: "text-surface-fg-muted",
|
|
125
179
|
initial: {
|
|
126
180
|
opacity: 0,
|
|
@@ -132,43 +186,46 @@ var y = s.forwardRef(({ className: s, label: g, title: y, value: b, prefix: x, s
|
|
|
132
186
|
},
|
|
133
187
|
transition: t.snappy,
|
|
134
188
|
"aria-hidden": "true",
|
|
135
|
-
children: /* @__PURE__ */
|
|
189
|
+
children: /* @__PURE__ */ f(e, {
|
|
136
190
|
size: "lg",
|
|
137
|
-
children: a(
|
|
191
|
+
children: a(D, "lg")
|
|
138
192
|
})
|
|
139
|
-
})]
|
|
193
|
+
}) : null]
|
|
140
194
|
})]
|
|
141
195
|
}),
|
|
142
|
-
/* @__PURE__ */
|
|
143
|
-
className: "
|
|
144
|
-
children: /* @__PURE__ */
|
|
145
|
-
className: "
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
196
|
+
/* @__PURE__ */ p("div", {
|
|
197
|
+
className: r(E === "inline" && T && "flex items-baseline gap-ds-03"),
|
|
198
|
+
children: [/* @__PURE__ */ f("div", {
|
|
199
|
+
className: "overflow-hidden",
|
|
200
|
+
children: /* @__PURE__ */ p(_.p, {
|
|
201
|
+
className: r("inline-block text-ds-3xl font-semibold", N === "tint" ? "text-accent-11" : "text-surface-fg"),
|
|
202
|
+
initial: {
|
|
203
|
+
opacity: 0,
|
|
204
|
+
y: "100%"
|
|
205
|
+
},
|
|
206
|
+
animate: {
|
|
207
|
+
opacity: 1,
|
|
208
|
+
y: 0
|
|
209
|
+
},
|
|
210
|
+
transition: t.smooth,
|
|
211
|
+
children: [
|
|
212
|
+
C && /* @__PURE__ */ f("span", {
|
|
213
|
+
className: "text-surface-fg-muted text-ds-lg",
|
|
214
|
+
children: C
|
|
215
|
+
}),
|
|
216
|
+
/* @__PURE__ */ f("span", {
|
|
217
|
+
className: "tabular-nums",
|
|
218
|
+
children: S
|
|
219
|
+
}),
|
|
220
|
+
w && /* @__PURE__ */ f("span", {
|
|
221
|
+
className: "text-surface-fg-muted text-ds-lg",
|
|
222
|
+
children: w
|
|
223
|
+
})
|
|
224
|
+
]
|
|
225
|
+
})
|
|
226
|
+
}), E === "inline" && Y]
|
|
170
227
|
}),
|
|
171
|
-
|
|
228
|
+
A && /* @__PURE__ */ f(_.p, {
|
|
172
229
|
className: "text-ds-sm text-surface-fg-subtle mt-ds-01",
|
|
173
230
|
initial: { opacity: 0 },
|
|
174
231
|
animate: { opacity: 1 },
|
|
@@ -176,59 +233,22 @@ var y = s.forwardRef(({ className: s, label: g, title: y, value: b, prefix: x, s
|
|
|
176
233
|
...n.fade,
|
|
177
234
|
delay: .1
|
|
178
235
|
},
|
|
179
|
-
children:
|
|
236
|
+
children: A
|
|
180
237
|
}),
|
|
181
|
-
|
|
238
|
+
j != null && /* @__PURE__ */ f(_.div, {
|
|
182
239
|
initial: { opacity: 0 },
|
|
183
240
|
animate: { opacity: 1 },
|
|
184
241
|
transition: {
|
|
185
242
|
...n.fade,
|
|
186
243
|
delay: .15
|
|
187
244
|
},
|
|
188
|
-
children: /* @__PURE__ */
|
|
189
|
-
progress:
|
|
190
|
-
label:
|
|
245
|
+
children: /* @__PURE__ */ f(b, {
|
|
246
|
+
progress: j,
|
|
247
|
+
label: W
|
|
191
248
|
})
|
|
192
249
|
}),
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
initial: {
|
|
196
|
-
opacity: 0,
|
|
197
|
-
y: 8
|
|
198
|
-
},
|
|
199
|
-
animate: {
|
|
200
|
-
opacity: 1,
|
|
201
|
-
y: 0
|
|
202
|
-
},
|
|
203
|
-
transition: {
|
|
204
|
-
...t.smooth,
|
|
205
|
-
delay: .2
|
|
206
|
-
},
|
|
207
|
-
children: [
|
|
208
|
-
/* @__PURE__ */ l(m.span, {
|
|
209
|
-
className: "inline-flex",
|
|
210
|
-
initial: {
|
|
211
|
-
opacity: .5,
|
|
212
|
-
scale: 1.4
|
|
213
|
-
},
|
|
214
|
-
animate: {
|
|
215
|
-
opacity: 1,
|
|
216
|
-
scale: 1
|
|
217
|
-
},
|
|
218
|
-
transition: t.bouncy,
|
|
219
|
-
children: /* @__PURE__ */ l(i, {
|
|
220
|
-
icon: B,
|
|
221
|
-
size: "sm"
|
|
222
|
-
})
|
|
223
|
-
}),
|
|
224
|
-
/* @__PURE__ */ l("span", { children: C.value }),
|
|
225
|
-
E && /* @__PURE__ */ l("span", {
|
|
226
|
-
className: "text-surface-fg-subtle font-normal",
|
|
227
|
-
children: E
|
|
228
|
-
})
|
|
229
|
-
]
|
|
230
|
-
}),
|
|
231
|
-
N && /* @__PURE__ */ l(m.div, {
|
|
250
|
+
E === "block" && Y,
|
|
251
|
+
B && /* @__PURE__ */ f(_.div, {
|
|
232
252
|
className: "mt-ds-04 pt-ds-04 border-t border-surface-border text-ds-sm",
|
|
233
253
|
initial: { opacity: 0 },
|
|
234
254
|
animate: { opacity: 1 },
|
|
@@ -236,31 +256,44 @@ var y = s.forwardRef(({ className: s, label: g, title: y, value: b, prefix: x, s
|
|
|
236
256
|
...n.fade,
|
|
237
257
|
delay: .25
|
|
238
258
|
},
|
|
239
|
-
children:
|
|
259
|
+
children: B
|
|
260
|
+
})
|
|
261
|
+
] }), Z = N === "tint" ? "bg-linear-to-t from-accent-2 to-surface-raised" : void 0, Q = /* @__PURE__ */ f(s, { children: X });
|
|
262
|
+
return z ? /* @__PURE__ */ f(U, {
|
|
263
|
+
ref: H,
|
|
264
|
+
href: z,
|
|
265
|
+
onClick: R,
|
|
266
|
+
className: "block no-underline",
|
|
267
|
+
"aria-label": G,
|
|
268
|
+
...V,
|
|
269
|
+
children: /* @__PURE__ */ f(o, {
|
|
270
|
+
variant: M,
|
|
271
|
+
interactive: !0,
|
|
272
|
+
className: Z,
|
|
273
|
+
children: Q
|
|
240
274
|
})
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
children: U
|
|
275
|
+
}) : R ? /* @__PURE__ */ f(o, {
|
|
276
|
+
ref: H,
|
|
277
|
+
variant: M,
|
|
278
|
+
interactive: !0,
|
|
279
|
+
className: r(Z, u),
|
|
280
|
+
role: "button",
|
|
281
|
+
tabIndex: 0,
|
|
282
|
+
"aria-label": G,
|
|
283
|
+
onClick: R,
|
|
284
|
+
onKeyDown: (e) => {
|
|
285
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), R());
|
|
286
|
+
},
|
|
287
|
+
...V,
|
|
288
|
+
children: Q
|
|
289
|
+
}) : /* @__PURE__ */ f(o, {
|
|
290
|
+
ref: H,
|
|
291
|
+
variant: M,
|
|
292
|
+
className: r(Z, u),
|
|
293
|
+
...V,
|
|
294
|
+
children: Q
|
|
262
295
|
});
|
|
263
296
|
});
|
|
264
|
-
|
|
297
|
+
x.displayName = "StatCard";
|
|
265
298
|
//#endregion
|
|
266
|
-
export {
|
|
299
|
+
export { x as StatCard };
|