@epilot/spark-ui 0.26.0 → 0.26.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/dist/components/accordion.cjs.map +1 -1
- package/dist/components/accordion.d.cts +1 -1
- package/dist/components/accordion.d.ts +1 -1
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/alert-dialog.cjs +1 -1
- package/dist/components/alert-dialog.cjs.map +1 -1
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/attachment.d.cts +1 -1
- package/dist/components/attachment.d.ts +1 -1
- package/dist/components/banner.d.cts +1 -1
- package/dist/components/banner.d.ts +1 -1
- package/dist/components/bubble.d.cts +1 -1
- package/dist/components/bubble.d.ts +1 -1
- package/dist/components/button.d.cts +2 -2
- package/dist/components/button.d.ts +2 -2
- package/dist/components/callout.cjs +1 -1
- package/dist/components/callout.cjs.map +1 -1
- package/dist/components/callout.d.cts +1 -1
- package/dist/components/callout.d.ts +1 -1
- package/dist/components/callout.js +1 -1
- package/dist/components/callout.js.map +1 -1
- package/dist/components/dialog.cjs +1 -1
- package/dist/components/dialog.cjs.map +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/drawer.cjs +1 -1
- package/dist/components/drawer.cjs.map +1 -1
- package/dist/components/drawer.js +1 -1
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/empty-state.cjs +3 -13
- package/dist/components/empty-state.cjs.map +1 -1
- package/dist/components/empty-state.d.cts +3 -3
- package/dist/components/empty-state.d.ts +3 -3
- package/dist/components/empty-state.js +3 -13
- package/dist/components/empty-state.js.map +1 -1
- package/dist/components/energy-breakdown.cjs +1 -1
- package/dist/components/energy-breakdown.cjs.map +1 -1
- package/dist/components/energy-breakdown.js +1 -1
- package/dist/components/energy-breakdown.js.map +1 -1
- package/dist/components/entity-card.cjs +1 -1
- package/dist/components/entity-card.cjs.map +1 -1
- package/dist/components/entity-card.js +1 -1
- package/dist/components/entity-card.js.map +1 -1
- package/dist/components/field.cjs +3 -3
- package/dist/components/field.cjs.map +1 -1
- package/dist/components/field.js +3 -3
- package/dist/components/field.js.map +1 -1
- package/dist/components/marker.d.cts +1 -1
- package/dist/components/marker.d.ts +1 -1
- package/dist/components/message-scroller.cjs +1 -1
- package/dist/components/message-scroller.cjs.map +1 -1
- package/dist/components/message-scroller.js +1 -1
- package/dist/components/message-scroller.js.map +1 -1
- package/dist/components/schedule-list.cjs +1 -1
- package/dist/components/schedule-list.cjs.map +1 -1
- package/dist/components/schedule-list.js +1 -1
- package/dist/components/schedule-list.js.map +1 -1
- package/dist/components/stat-card.cjs +1 -1
- package/dist/components/stat-card.cjs.map +1 -1
- package/dist/components/stat-card.js +1 -1
- package/dist/components/stat-card.js.map +1 -1
- package/dist/components/toast.cjs +1 -1
- package/dist/components/toast.cjs.map +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/components/toast.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.cjs","names":["DrawerPrimitive","React","PortalTheme"],"sources":["../../src/components/drawer.tsx"],"sourcesContent":["import { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport { Drawer as DrawerPrimitive } from 'vaul'\nimport { cn } from '../utils/cn'\nimport { PortalTheme } from './theme'\n\nfunction Drawer({\n shouldScaleBackground = true,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return (\n <DrawerPrimitive.Root\n data-slot=\"drawer\"\n shouldScaleBackground={shouldScaleBackground}\n {...props}\n />\n )\n}\n\nfunction DrawerTrigger(\n props: React.ComponentProps<typeof DrawerPrimitive.Trigger>,\n) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return (\n <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props}>\n {React.Children.map(children, (child) =>\n React.isValidElement(child) ? (\n <DrawerPortalChild>{child}</DrawerPortalChild>\n ) : (\n child\n ),\n )}\n </DrawerPrimitive.Portal>\n )\n}\n\n// Radix clones each portal child with the Presence ref that gates the exit animation; it must land on the part, not the theme wrapper.\nconst DrawerPortalChild = React.forwardRef<\n HTMLElement,\n { children: React.ReactElement }\n>(function DrawerPortalChild({ children }, ref) {\n const part = useRender({ render: children, ref, props: {} })\n return <PortalTheme>{part}</PortalTheme>\n})\n\nfunction DrawerClose(\n props: React.ComponentProps<typeof DrawerPrimitive.Close>,\n) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n 'fixed top-(--spark-viewport-top,0) right-0 left-0 z-50 h-(--spark-viewport-height,100%) bg-(--color-overlay) supports-backdrop-filter:backdrop-blur-xs motion-reduce:animate-none! motion-reduce:transition-none!',\n className,\n )}\n data-overlay=\"true\"\n {...props}\n />\n )\n}\n\ninterface DrawerContentProps extends React.ComponentProps<\n typeof DrawerPrimitive.Content\n> {\n pillClassName?: string\n}\n\nconst onInteractOutsideHandler = (event: CustomEvent) => {\n const target = event.target as HTMLElement\n const isOverlay = target.dataset.overlay === 'true'\n\n // Our drawers contain interactive elements that are mounted outside of the drawer\n // Browser extensions like password managers or grammar checkers are also mounted outside\n // We still dismiss on a click/tap outside\n if (!isOverlay) event.preventDefault()\n}\n\nfunction DrawerContent({\n className,\n pillClassName,\n children,\n ...props\n}: DrawerContentProps) {\n return (\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n 'group/drawer-content fixed z-50 flex h-auto flex-col bg-gray-2 text-gray motion-reduce:animate-none! motion-reduce:transition-none!',\n 'data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-(--spark-viewport-bottom-offset,0) data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg',\n 'data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg',\n 'data-[vaul-drawer-direction=left]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:border-gray-a1 data-[vaul-drawer-direction=left]:sm:max-w-sm',\n 'data-[vaul-drawer-direction=right]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:border-gray-a1 data-[vaul-drawer-direction=right]:sm:max-w-sm',\n className,\n )}\n onInteractOutside={onInteractOutsideHandler}\n {...props}\n >\n <div\n className={cn(\n 'mx-auto mt-2.5 hidden h-1.5 w-16 shrink-0 rounded-full bg-base-gray-soft group-data-[vaul-drawer-direction=bottom]/drawer-content:block',\n pillClassName,\n )}\n />\n {children}\n </DrawerPrimitive.Content>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn('flex flex-col gap-
|
|
1
|
+
{"version":3,"file":"drawer.cjs","names":["DrawerPrimitive","React","PortalTheme"],"sources":["../../src/components/drawer.tsx"],"sourcesContent":["import { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport { Drawer as DrawerPrimitive } from 'vaul'\nimport { cn } from '../utils/cn'\nimport { PortalTheme } from './theme'\n\nfunction Drawer({\n shouldScaleBackground = true,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return (\n <DrawerPrimitive.Root\n data-slot=\"drawer\"\n shouldScaleBackground={shouldScaleBackground}\n {...props}\n />\n )\n}\n\nfunction DrawerTrigger(\n props: React.ComponentProps<typeof DrawerPrimitive.Trigger>,\n) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return (\n <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props}>\n {React.Children.map(children, (child) =>\n React.isValidElement(child) ? (\n <DrawerPortalChild>{child}</DrawerPortalChild>\n ) : (\n child\n ),\n )}\n </DrawerPrimitive.Portal>\n )\n}\n\n// Radix clones each portal child with the Presence ref that gates the exit animation; it must land on the part, not the theme wrapper.\nconst DrawerPortalChild = React.forwardRef<\n HTMLElement,\n { children: React.ReactElement }\n>(function DrawerPortalChild({ children }, ref) {\n const part = useRender({ render: children, ref, props: {} })\n return <PortalTheme>{part}</PortalTheme>\n})\n\nfunction DrawerClose(\n props: React.ComponentProps<typeof DrawerPrimitive.Close>,\n) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n 'fixed top-(--spark-viewport-top,0) right-0 left-0 z-50 h-(--spark-viewport-height,100%) bg-(--color-overlay) supports-backdrop-filter:backdrop-blur-xs motion-reduce:animate-none! motion-reduce:transition-none!',\n className,\n )}\n data-overlay=\"true\"\n {...props}\n />\n )\n}\n\ninterface DrawerContentProps extends React.ComponentProps<\n typeof DrawerPrimitive.Content\n> {\n pillClassName?: string\n}\n\nconst onInteractOutsideHandler = (event: CustomEvent) => {\n const target = event.target as HTMLElement\n const isOverlay = target.dataset.overlay === 'true'\n\n // Our drawers contain interactive elements that are mounted outside of the drawer\n // Browser extensions like password managers or grammar checkers are also mounted outside\n // We still dismiss on a click/tap outside\n if (!isOverlay) event.preventDefault()\n}\n\nfunction DrawerContent({\n className,\n pillClassName,\n children,\n ...props\n}: DrawerContentProps) {\n return (\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n 'group/drawer-content fixed z-50 flex h-auto flex-col bg-gray-2 text-gray motion-reduce:animate-none! motion-reduce:transition-none!',\n 'data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-(--spark-viewport-bottom-offset,0) data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg',\n 'data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg',\n 'data-[vaul-drawer-direction=left]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:border-gray-a1 data-[vaul-drawer-direction=left]:sm:max-w-sm',\n 'data-[vaul-drawer-direction=right]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:border-gray-a1 data-[vaul-drawer-direction=right]:sm:max-w-sm',\n className,\n )}\n onInteractOutside={onInteractOutsideHandler}\n {...props}\n >\n <div\n className={cn(\n 'mx-auto mt-2.5 hidden h-1.5 w-16 shrink-0 rounded-full bg-base-gray-soft group-data-[vaul-drawer-direction=bottom]/drawer-content:block',\n pillClassName,\n )}\n />\n {children}\n </DrawerPrimitive.Content>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn('flex flex-col gap-2 px-6 py-3', className)}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn('mt-auto flex flex-col gap-2 text-gray', className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn('text-lg font-bold text-gray', className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn('text-sm text-gray-light', className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerOverlay,\n DrawerPortal,\n DrawerTitle,\n DrawerTrigger,\n}\nexport type { DrawerContentProps }\n"],"mappings":";;;;;;;;;;;AAMA,SAAS,OAAO,EACd,wBAAwB,MACxB,GAAG,SACiD;CACpD,OACE,iBAAA,GAAA,kBAAA,KAACA,KAAAA,OAAgB,MAAjB;EACE,aAAU;EACa;EACvB,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,cACP,OACA;CACA,OAAO,iBAAA,GAAA,kBAAA,KAACA,KAAAA,OAAgB,SAAjB;EAAyB,aAAU;EAAiB,GAAI;CAAQ,CAAA;AACzE;AAEA,SAAS,aAAa,EACpB,UACA,GAAG,SACmD;CACtD,OACE,iBAAA,GAAA,kBAAA,KAACA,KAAAA,OAAgB,QAAjB;EAAwB,aAAU;EAAgB,GAAI;YACnDC,MAAM,SAAS,IAAI,WAAW,UAC7BA,MAAM,eAAe,KAAK,IACxB,iBAAA,GAAA,kBAAA,KAAC,mBAAD,EAAA,UAAoB,MAAyB,CAAA,IAE7C,KAEJ;CACsB,CAAA;AAE5B;AAGA,MAAM,oBAAoBA,MAAM,WAG9B,SAAS,kBAAkB,EAAE,YAAY,KAAK;CAE9C,OAAO,iBAAA,GAAA,kBAAA,KAACC,yBAAAA,aAAD,EAAA,WAAA,GAAA,0BAAA,WADgB;EAAE,QAAQ;EAAU;EAAK,OAAO,CAAC;CAAE,CAClC,EAAe,CAAA;AACzC,CAAC;AAED,SAAS,YACP,OACA;CACA,OAAO,iBAAA,GAAA,kBAAA,KAACF,KAAAA,OAAgB,OAAjB;EAAuB,aAAU;EAAe,GAAI;CAAQ,CAAA;AACrE;AAEA,SAAS,cAAc,EACrB,WACA,GAAG,SACoD;CACvD,OACE,iBAAA,GAAA,kBAAA,KAACA,KAAAA,OAAgB,SAAjB;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IACE,qNACA,SACF;EACA,gBAAa;EACb,GAAI;CACL,CAAA;AAEL;AAQA,MAAM,4BAA4B,UAAuB;CAOvD,IAAI,EANW,MAAM,OACI,QAAQ,YAAY,SAK7B,MAAM,eAAe;AACvC;AAEA,SAAS,cAAc,EACrB,WACA,eACA,UACA,GAAG,SACkB;CACrB,OACE,iBAAA,GAAA,kBAAA,MAACA,KAAAA,OAAgB,SAAjB;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IACE,uIACA,2QACA,+OACA,gWACA,wWACA,SACF;EACA,mBAAmB;EACnB,GAAI;YAXN,CAaE,iBAAA,GAAA,kBAAA,KAAC,OAAD,EACE,YAAA,GAAA,GAAA,IACE,2IACA,aACF,EACD,CAAA,GACA,QACsB;;AAE7B;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;CAC1E,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IAAc,iCAAiC,SAAS;EACxD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;CAC1E,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IAAc,yCAAyC,SAAS;EAChE,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,EACnB,WACA,GAAG,SACkD;CACrD,OACE,iBAAA,GAAA,kBAAA,KAACA,KAAAA,OAAgB,OAAjB;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IAAc,+BAA+B,SAAS;EACtD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,kBAAkB,EACzB,WACA,GAAG,SACwD;CAC3D,OACE,iBAAA,GAAA,kBAAA,KAACA,KAAAA,OAAgB,aAAjB;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IAAc,2BAA2B,SAAS;EAClD,GAAI;CACL,CAAA;AAEL"}
|
|
@@ -62,7 +62,7 @@ function DrawerContent({ className, pillClassName, children, ...props }) {
|
|
|
62
62
|
function DrawerHeader({ className, ...props }) {
|
|
63
63
|
return /* @__PURE__ */ jsx("div", {
|
|
64
64
|
"data-slot": "drawer-header",
|
|
65
|
-
className: cn("flex flex-col gap-
|
|
65
|
+
className: cn("flex flex-col gap-2 px-6 py-3", className),
|
|
66
66
|
...props
|
|
67
67
|
});
|
|
68
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.js","names":["DrawerPrimitive","React"],"sources":["../../src/components/drawer.tsx"],"sourcesContent":["import { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport { Drawer as DrawerPrimitive } from 'vaul'\nimport { cn } from '../utils/cn'\nimport { PortalTheme } from './theme'\n\nfunction Drawer({\n shouldScaleBackground = true,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return (\n <DrawerPrimitive.Root\n data-slot=\"drawer\"\n shouldScaleBackground={shouldScaleBackground}\n {...props}\n />\n )\n}\n\nfunction DrawerTrigger(\n props: React.ComponentProps<typeof DrawerPrimitive.Trigger>,\n) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return (\n <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props}>\n {React.Children.map(children, (child) =>\n React.isValidElement(child) ? (\n <DrawerPortalChild>{child}</DrawerPortalChild>\n ) : (\n child\n ),\n )}\n </DrawerPrimitive.Portal>\n )\n}\n\n// Radix clones each portal child with the Presence ref that gates the exit animation; it must land on the part, not the theme wrapper.\nconst DrawerPortalChild = React.forwardRef<\n HTMLElement,\n { children: React.ReactElement }\n>(function DrawerPortalChild({ children }, ref) {\n const part = useRender({ render: children, ref, props: {} })\n return <PortalTheme>{part}</PortalTheme>\n})\n\nfunction DrawerClose(\n props: React.ComponentProps<typeof DrawerPrimitive.Close>,\n) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n 'fixed top-(--spark-viewport-top,0) right-0 left-0 z-50 h-(--spark-viewport-height,100%) bg-(--color-overlay) supports-backdrop-filter:backdrop-blur-xs motion-reduce:animate-none! motion-reduce:transition-none!',\n className,\n )}\n data-overlay=\"true\"\n {...props}\n />\n )\n}\n\ninterface DrawerContentProps extends React.ComponentProps<\n typeof DrawerPrimitive.Content\n> {\n pillClassName?: string\n}\n\nconst onInteractOutsideHandler = (event: CustomEvent) => {\n const target = event.target as HTMLElement\n const isOverlay = target.dataset.overlay === 'true'\n\n // Our drawers contain interactive elements that are mounted outside of the drawer\n // Browser extensions like password managers or grammar checkers are also mounted outside\n // We still dismiss on a click/tap outside\n if (!isOverlay) event.preventDefault()\n}\n\nfunction DrawerContent({\n className,\n pillClassName,\n children,\n ...props\n}: DrawerContentProps) {\n return (\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n 'group/drawer-content fixed z-50 flex h-auto flex-col bg-gray-2 text-gray motion-reduce:animate-none! motion-reduce:transition-none!',\n 'data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-(--spark-viewport-bottom-offset,0) data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg',\n 'data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg',\n 'data-[vaul-drawer-direction=left]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:border-gray-a1 data-[vaul-drawer-direction=left]:sm:max-w-sm',\n 'data-[vaul-drawer-direction=right]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:border-gray-a1 data-[vaul-drawer-direction=right]:sm:max-w-sm',\n className,\n )}\n onInteractOutside={onInteractOutsideHandler}\n {...props}\n >\n <div\n className={cn(\n 'mx-auto mt-2.5 hidden h-1.5 w-16 shrink-0 rounded-full bg-base-gray-soft group-data-[vaul-drawer-direction=bottom]/drawer-content:block',\n pillClassName,\n )}\n />\n {children}\n </DrawerPrimitive.Content>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn('flex flex-col gap-
|
|
1
|
+
{"version":3,"file":"drawer.js","names":["DrawerPrimitive","React"],"sources":["../../src/components/drawer.tsx"],"sourcesContent":["import { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport { Drawer as DrawerPrimitive } from 'vaul'\nimport { cn } from '../utils/cn'\nimport { PortalTheme } from './theme'\n\nfunction Drawer({\n shouldScaleBackground = true,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return (\n <DrawerPrimitive.Root\n data-slot=\"drawer\"\n shouldScaleBackground={shouldScaleBackground}\n {...props}\n />\n )\n}\n\nfunction DrawerTrigger(\n props: React.ComponentProps<typeof DrawerPrimitive.Trigger>,\n) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return (\n <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props}>\n {React.Children.map(children, (child) =>\n React.isValidElement(child) ? (\n <DrawerPortalChild>{child}</DrawerPortalChild>\n ) : (\n child\n ),\n )}\n </DrawerPrimitive.Portal>\n )\n}\n\n// Radix clones each portal child with the Presence ref that gates the exit animation; it must land on the part, not the theme wrapper.\nconst DrawerPortalChild = React.forwardRef<\n HTMLElement,\n { children: React.ReactElement }\n>(function DrawerPortalChild({ children }, ref) {\n const part = useRender({ render: children, ref, props: {} })\n return <PortalTheme>{part}</PortalTheme>\n})\n\nfunction DrawerClose(\n props: React.ComponentProps<typeof DrawerPrimitive.Close>,\n) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n 'fixed top-(--spark-viewport-top,0) right-0 left-0 z-50 h-(--spark-viewport-height,100%) bg-(--color-overlay) supports-backdrop-filter:backdrop-blur-xs motion-reduce:animate-none! motion-reduce:transition-none!',\n className,\n )}\n data-overlay=\"true\"\n {...props}\n />\n )\n}\n\ninterface DrawerContentProps extends React.ComponentProps<\n typeof DrawerPrimitive.Content\n> {\n pillClassName?: string\n}\n\nconst onInteractOutsideHandler = (event: CustomEvent) => {\n const target = event.target as HTMLElement\n const isOverlay = target.dataset.overlay === 'true'\n\n // Our drawers contain interactive elements that are mounted outside of the drawer\n // Browser extensions like password managers or grammar checkers are also mounted outside\n // We still dismiss on a click/tap outside\n if (!isOverlay) event.preventDefault()\n}\n\nfunction DrawerContent({\n className,\n pillClassName,\n children,\n ...props\n}: DrawerContentProps) {\n return (\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n 'group/drawer-content fixed z-50 flex h-auto flex-col bg-gray-2 text-gray motion-reduce:animate-none! motion-reduce:transition-none!',\n 'data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-(--spark-viewport-bottom-offset,0) data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg',\n 'data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg',\n 'data-[vaul-drawer-direction=left]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:border-gray-a1 data-[vaul-drawer-direction=left]:sm:max-w-sm',\n 'data-[vaul-drawer-direction=right]:top-(--spark-viewport-top,0) data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:h-(--spark-viewport-height,100%) data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:border-gray-a1 data-[vaul-drawer-direction=right]:sm:max-w-sm',\n className,\n )}\n onInteractOutside={onInteractOutsideHandler}\n {...props}\n >\n <div\n className={cn(\n 'mx-auto mt-2.5 hidden h-1.5 w-16 shrink-0 rounded-full bg-base-gray-soft group-data-[vaul-drawer-direction=bottom]/drawer-content:block',\n pillClassName,\n )}\n />\n {children}\n </DrawerPrimitive.Content>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn('flex flex-col gap-2 px-6 py-3', className)}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn('mt-auto flex flex-col gap-2 text-gray', className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn('text-lg font-bold text-gray', className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn('text-sm text-gray-light', className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerOverlay,\n DrawerPortal,\n DrawerTitle,\n DrawerTrigger,\n}\nexport type { DrawerContentProps }\n"],"mappings":";;;;;;;;AAMA,SAAS,OAAO,EACd,wBAAwB,MACxB,GAAG,SACiD;CACpD,OACE,oBAACA,SAAgB,MAAjB;EACE,aAAU;EACa;EACvB,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,cACP,OACA;CACA,OAAO,oBAACA,SAAgB,SAAjB;EAAyB,aAAU;EAAiB,GAAI;CAAQ,CAAA;AACzE;AAEA,SAAS,aAAa,EACpB,UACA,GAAG,SACmD;CACtD,OACE,oBAACA,SAAgB,QAAjB;EAAwB,aAAU;EAAgB,GAAI;YACnDC,QAAM,SAAS,IAAI,WAAW,UAC7BA,QAAM,eAAe,KAAK,IACxB,oBAAC,mBAAD,EAAA,UAAoB,MAAyB,CAAA,IAE7C,KAEJ;CACsB,CAAA;AAE5B;AAGA,MAAM,oBAAoBA,QAAM,WAG9B,SAAS,kBAAkB,EAAE,YAAY,KAAK;CAE9C,OAAO,oBAAC,aAAD,EAAA,UADM,UAAU;EAAE,QAAQ;EAAU;EAAK,OAAO,CAAC;CAAE,CAClC,EAAe,CAAA;AACzC,CAAC;AAED,SAAS,YACP,OACA;CACA,OAAO,oBAACD,SAAgB,OAAjB;EAAuB,aAAU;EAAe,GAAI;CAAQ,CAAA;AACrE;AAEA,SAAS,cAAc,EACrB,WACA,GAAG,SACoD;CACvD,OACE,oBAACA,SAAgB,SAAjB;EACE,aAAU;EACV,WAAW,GACT,qNACA,SACF;EACA,gBAAa;EACb,GAAI;CACL,CAAA;AAEL;AAQA,MAAM,4BAA4B,UAAuB;CAOvD,IAAI,EANW,MAAM,OACI,QAAQ,YAAY,SAK7B,MAAM,eAAe;AACvC;AAEA,SAAS,cAAc,EACrB,WACA,eACA,UACA,GAAG,SACkB;CACrB,OACE,qBAACA,SAAgB,SAAjB;EACE,aAAU;EACV,WAAW,GACT,uIACA,2QACA,+OACA,gWACA,wWACA,SACF;EACA,mBAAmB;EACnB,GAAI;YAXN,CAaE,oBAAC,OAAD,EACE,WAAW,GACT,2IACA,aACF,EACD,CAAA,GACA,QACsB;;AAE7B;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;CAC1E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,iCAAiC,SAAS;EACxD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;CAC1E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,yCAAyC,SAAS;EAChE,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,EACnB,WACA,GAAG,SACkD;CACrD,OACE,oBAACA,SAAgB,OAAjB;EACE,aAAU;EACV,WAAW,GAAG,+BAA+B,SAAS;EACtD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,kBAAkB,EACzB,WACA,GAAG,SACwD;CAC3D,OACE,oBAACA,SAAgB,aAAjB;EACE,aAAU;EACV,WAAW,GAAG,2BAA2B,SAAS;EAClD,GAAI;CACL,CAAA;AAEL"}
|
|
@@ -69,21 +69,11 @@ function EmptyStateDescription({ className, ...props }) {
|
|
|
69
69
|
...props
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
|
-
const actionsMargin = {
|
|
73
|
-
stacked: {
|
|
74
|
-
default: "mt-3",
|
|
75
|
-
sm: "mt-1"
|
|
76
|
-
},
|
|
77
|
-
inline: {
|
|
78
|
-
default: "mt-3",
|
|
79
|
-
sm: "mt-2"
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
72
|
function EmptyStateActions({ className, ...props }) {
|
|
83
|
-
const {
|
|
73
|
+
const { layout } = (0, react.useContext)(EmptyStateContext);
|
|
84
74
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
85
75
|
"data-slot": "empty-state-actions",
|
|
86
|
-
className: (0, cn.cn)("flex flex-wrap gap-2", layout === "stacked" && "justify-center",
|
|
76
|
+
className: (0, cn.cn)("mt-2 flex flex-wrap gap-2", layout === "stacked" && "justify-center", className),
|
|
87
77
|
...props
|
|
88
78
|
});
|
|
89
79
|
}
|
|
@@ -105,7 +95,7 @@ function EmptyState({ children, className, icon: Glyph, layout = "stacked", size
|
|
|
105
95
|
size: size === "sm" ? "small" : "xl",
|
|
106
96
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Glyph, {})
|
|
107
97
|
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
108
|
-
className: (0, cn.cn)("flex flex-col gap-
|
|
98
|
+
className: (0, cn.cn)("flex flex-col gap-2", layout === "inline" && "min-w-0 flex-1"),
|
|
109
99
|
children
|
|
110
100
|
})]
|
|
111
101
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empty-state.cjs","names":["Icon"],"sources":["../../src/components/empty-state.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport {\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n} from 'react'\nimport { cn } from '../utils/cn'\nimport { Icon } from './icon'\n\nconst emptyStateVariants = cva('flex', {\n variants: {\n variant: {\n dashed: 'rounded-lg border border-dashed border-gray',\n ghost: '',\n },\n size: { default: '', sm: '' },\n layout: {\n stacked: 'flex-col items-center text-center',\n inline: 'flex-row items-start text-left',\n },\n },\n compoundVariants: [\n { layout: 'stacked', size: 'default', class: 'gap-4 px-6 py-12' },\n { layout: 'stacked', size: 'sm', class: 'gap-2 px-4 py-5' },\n { layout: 'inline', size: 'default', class: 'gap-4 p-6' },\n { layout: 'inline', size: 'sm', class: 'gap-3 px-4 py-3' },\n ],\n defaultVariants: {\n variant: 'dashed',\n size: 'default',\n layout: 'stacked',\n },\n})\n\ntype EmptyStateVariants = VariantProps<typeof emptyStateVariants>\n\n// A leftover `title` would otherwise compile and render as a tooltip, not a heading.\ninterface EmptyStateProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'title'>,\n Pick<EmptyStateVariants, 'variant'> {\n // null would switch off the compound cells and drop all padding and gap\n size?: NonNullable<EmptyStateVariants['size']>\n layout?: NonNullable<EmptyStateVariants['layout']>\n icon?: SparkIcon\n children: ReactNode\n}\n\nconst EmptyStateContext = createContext<{\n size: NonNullable<EmptyStateVariants['size']>\n layout: NonNullable<EmptyStateVariants['layout']>\n}>({ size: 'default', layout: 'stacked' })\n\nfunction EmptyStateTitle({\n className,\n ...props\n}: HTMLAttributes<HTMLHeadingElement>) {\n const { size } = useContext(EmptyStateContext)\n return (\n <h3\n data-slot=\"empty-state-title\"\n className={cn(\n 'text-gray',\n size === 'sm' ? 'text-sm font-semibold' : 'text-base font-bold',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyStateDescription({\n className,\n ...props\n}: HTMLAttributes<HTMLParagraphElement>) {\n const { size, layout } = useContext(EmptyStateContext)\n return (\n <p\n data-slot=\"empty-state-description\"\n className={cn(\n layout !== 'inline' && 'mx-auto',\n 'max-w-md text-gray-light',\n size === 'sm' ? 'text-xs' : 'text-sm',\n className,\n )}\n {...props}\n />\n )\n}\n\
|
|
1
|
+
{"version":3,"file":"empty-state.cjs","names":["Icon"],"sources":["../../src/components/empty-state.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport {\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n} from 'react'\nimport { cn } from '../utils/cn'\nimport { Icon } from './icon'\n\nconst emptyStateVariants = cva('flex', {\n variants: {\n variant: {\n dashed: 'rounded-lg border border-dashed border-gray',\n ghost: '',\n },\n size: { default: '', sm: '' },\n layout: {\n stacked: 'flex-col items-center text-center',\n inline: 'flex-row items-start text-left',\n },\n },\n compoundVariants: [\n { layout: 'stacked', size: 'default', class: 'gap-4 px-6 py-12' },\n { layout: 'stacked', size: 'sm', class: 'gap-2 px-4 py-5' },\n { layout: 'inline', size: 'default', class: 'gap-4 p-6' },\n { layout: 'inline', size: 'sm', class: 'gap-3 px-4 py-3' },\n ],\n defaultVariants: {\n variant: 'dashed',\n size: 'default',\n layout: 'stacked',\n },\n})\n\ntype EmptyStateVariants = VariantProps<typeof emptyStateVariants>\n\n// A leftover `title` would otherwise compile and render as a tooltip, not a heading.\ninterface EmptyStateProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'title'>,\n Pick<EmptyStateVariants, 'variant'> {\n // null would switch off the compound cells and drop all padding and gap\n size?: NonNullable<EmptyStateVariants['size']>\n layout?: NonNullable<EmptyStateVariants['layout']>\n icon?: SparkIcon\n children: ReactNode\n}\n\nconst EmptyStateContext = createContext<{\n size: NonNullable<EmptyStateVariants['size']>\n layout: NonNullable<EmptyStateVariants['layout']>\n}>({ size: 'default', layout: 'stacked' })\n\nfunction EmptyStateTitle({\n className,\n ...props\n}: HTMLAttributes<HTMLHeadingElement>) {\n const { size } = useContext(EmptyStateContext)\n return (\n <h3\n data-slot=\"empty-state-title\"\n className={cn(\n 'text-gray',\n size === 'sm' ? 'text-sm font-semibold' : 'text-base font-bold',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyStateDescription({\n className,\n ...props\n}: HTMLAttributes<HTMLParagraphElement>) {\n const { size, layout } = useContext(EmptyStateContext)\n return (\n <p\n data-slot=\"empty-state-description\"\n className={cn(\n layout !== 'inline' && 'mx-auto',\n 'max-w-md text-gray-light',\n size === 'sm' ? 'text-xs' : 'text-sm',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyStateActions({\n className,\n ...props\n}: HTMLAttributes<HTMLDivElement>) {\n const { layout } = useContext(EmptyStateContext)\n return (\n <div\n data-slot=\"empty-state-actions\"\n className={cn(\n 'mt-2 flex flex-wrap gap-2',\n layout === 'stacked' && 'justify-center',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyState({\n children,\n className,\n icon: Glyph,\n layout = 'stacked',\n size = 'default',\n variant,\n ...props\n}: EmptyStateProps) {\n return (\n <EmptyStateContext.Provider value={{ size, layout }}>\n <div\n data-slot=\"empty-state\"\n className={cn(emptyStateVariants({ variant, size, layout }), className)}\n {...props}\n >\n {Glyph ? (\n <Icon size={size === 'sm' ? 'small' : 'xl'}>\n <Glyph />\n </Icon>\n ) : null}\n <div\n className={cn(\n 'flex flex-col gap-2',\n layout === 'inline' && 'min-w-0 flex-1',\n )}\n >\n {children}\n </div>\n </div>\n </EmptyStateContext.Provider>\n )\n}\n\nexport { EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateTitle }\nexport type { EmptyStateProps }\n"],"mappings":";;;;;;;;AAWA,MAAM,sBAAA,GAAA,yBAAA,KAAyB,QAAQ;CACrC,UAAU;EACR,SAAS;GACP,QAAQ;GACR,OAAO;EACT;EACA,MAAM;GAAE,SAAS;GAAI,IAAI;EAAG;EAC5B,QAAQ;GACN,SAAS;GACT,QAAQ;EACV;CACF;CACA,kBAAkB;EAChB;GAAE,QAAQ;GAAW,MAAM;GAAW,OAAO;EAAmB;EAChE;GAAE,QAAQ;GAAW,MAAM;GAAM,OAAO;EAAkB;EAC1D;GAAE,QAAQ;GAAU,MAAM;GAAW,OAAO;EAAY;EACxD;GAAE,QAAQ;GAAU,MAAM;GAAM,OAAO;EAAkB;CAC3D;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,QAAQ;CACV;AACF,CAAC;AAgBD,MAAM,qBAAA,GAAA,MAAA,eAGH;CAAE,MAAM;CAAW,QAAQ;AAAU,CAAC;AAEzC,SAAS,gBAAgB,EACvB,WACA,GAAG,SACkC;CACrC,MAAM,EAAE,UAAA,GAAA,MAAA,YAAoB,iBAAiB;CAC7C,OACE,iBAAA,GAAA,kBAAA,KAAC,MAAD;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IACE,aACA,SAAS,OAAO,0BAA0B,uBAC1C,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,sBAAsB,EAC7B,WACA,GAAG,SACoC;CACvC,MAAM,EAAE,MAAM,YAAA,GAAA,MAAA,YAAsB,iBAAiB;CACrD,OACE,iBAAA,GAAA,kBAAA,KAAC,KAAD;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IACE,WAAW,YAAY,WACvB,4BACA,SAAS,OAAO,YAAY,WAC5B,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,kBAAkB,EACzB,WACA,GAAG,SAC8B;CACjC,MAAM,EAAE,YAAA,GAAA,MAAA,YAAsB,iBAAiB;CAC/C,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IACE,6BACA,WAAW,aAAa,kBACxB,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAClB,UACA,WACA,MAAM,OACN,SAAS,WACT,OAAO,WACP,SACA,GAAG,SACe;CAClB,OACE,iBAAA,GAAA,kBAAA,KAAC,kBAAkB,UAAnB;EAA4B,OAAO;GAAE;GAAM;EAAO;YAChD,iBAAA,GAAA,kBAAA,MAAC,OAAD;GACE,aAAU;GACV,YAAA,GAAA,GAAA,IAAc,mBAAmB;IAAE;IAAS;IAAM;GAAO,CAAC,GAAG,SAAS;GACtE,GAAI;aAHN,CAKG,QACC,iBAAA,GAAA,kBAAA,KAACA,wBAAAA,MAAD;IAAM,MAAM,SAAS,OAAO,UAAU;cACpC,iBAAA,GAAA,kBAAA,KAAC,OAAD,CAAQ,CAAA;GACJ,CAAA,IACJ,MACJ,iBAAA,GAAA,kBAAA,KAAC,OAAD;IACE,YAAA,GAAA,GAAA,IACE,uBACA,WAAW,YAAY,gBACzB;IAEC;GACE,CAAA,CACF;;CACqB,CAAA;AAEhC"}
|
|
@@ -6,9 +6,9 @@ import { SparkIcon } from "@epilot/spark-icons";
|
|
|
6
6
|
|
|
7
7
|
//#region src/components/empty-state.d.ts
|
|
8
8
|
declare const emptyStateVariants: (props?: ({
|
|
9
|
-
variant?: "
|
|
10
|
-
size?: "
|
|
11
|
-
layout?: "
|
|
9
|
+
variant?: "dashed" | "ghost" | null | undefined;
|
|
10
|
+
size?: "default" | "sm" | null | undefined;
|
|
11
|
+
layout?: "stacked" | "inline" | null | undefined;
|
|
12
12
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
13
|
type EmptyStateVariants = VariantProps<typeof emptyStateVariants>;
|
|
14
14
|
interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>, Pick<EmptyStateVariants, 'variant'> {
|
|
@@ -6,9 +6,9 @@ import { VariantProps } from "class-variance-authority";
|
|
|
6
6
|
|
|
7
7
|
//#region src/components/empty-state.d.ts
|
|
8
8
|
declare const emptyStateVariants: (props?: ({
|
|
9
|
-
variant?: "
|
|
10
|
-
size?: "
|
|
11
|
-
layout?: "
|
|
9
|
+
variant?: "dashed" | "ghost" | null | undefined;
|
|
10
|
+
size?: "default" | "sm" | null | undefined;
|
|
11
|
+
layout?: "stacked" | "inline" | null | undefined;
|
|
12
12
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
13
|
type EmptyStateVariants = VariantProps<typeof emptyStateVariants>;
|
|
14
14
|
interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>, Pick<EmptyStateVariants, 'variant'> {
|
|
@@ -68,21 +68,11 @@ function EmptyStateDescription({ className, ...props }) {
|
|
|
68
68
|
...props
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
|
-
const actionsMargin = {
|
|
72
|
-
stacked: {
|
|
73
|
-
default: "mt-3",
|
|
74
|
-
sm: "mt-1"
|
|
75
|
-
},
|
|
76
|
-
inline: {
|
|
77
|
-
default: "mt-3",
|
|
78
|
-
sm: "mt-2"
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
71
|
function EmptyStateActions({ className, ...props }) {
|
|
82
|
-
const {
|
|
72
|
+
const { layout } = useContext(EmptyStateContext);
|
|
83
73
|
return /* @__PURE__ */ jsx("div", {
|
|
84
74
|
"data-slot": "empty-state-actions",
|
|
85
|
-
className: cn("flex flex-wrap gap-2", layout === "stacked" && "justify-center",
|
|
75
|
+
className: cn("mt-2 flex flex-wrap gap-2", layout === "stacked" && "justify-center", className),
|
|
86
76
|
...props
|
|
87
77
|
});
|
|
88
78
|
}
|
|
@@ -104,7 +94,7 @@ function EmptyState({ children, className, icon: Glyph, layout = "stacked", size
|
|
|
104
94
|
size: size === "sm" ? "small" : "xl",
|
|
105
95
|
children: /* @__PURE__ */ jsx(Glyph, {})
|
|
106
96
|
}) : null, /* @__PURE__ */ jsx("div", {
|
|
107
|
-
className: cn("flex flex-col gap-
|
|
97
|
+
className: cn("flex flex-col gap-2", layout === "inline" && "min-w-0 flex-1"),
|
|
108
98
|
children
|
|
109
99
|
})]
|
|
110
100
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empty-state.js","names":[],"sources":["../../src/components/empty-state.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport {\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n} from 'react'\nimport { cn } from '../utils/cn'\nimport { Icon } from './icon'\n\nconst emptyStateVariants = cva('flex', {\n variants: {\n variant: {\n dashed: 'rounded-lg border border-dashed border-gray',\n ghost: '',\n },\n size: { default: '', sm: '' },\n layout: {\n stacked: 'flex-col items-center text-center',\n inline: 'flex-row items-start text-left',\n },\n },\n compoundVariants: [\n { layout: 'stacked', size: 'default', class: 'gap-4 px-6 py-12' },\n { layout: 'stacked', size: 'sm', class: 'gap-2 px-4 py-5' },\n { layout: 'inline', size: 'default', class: 'gap-4 p-6' },\n { layout: 'inline', size: 'sm', class: 'gap-3 px-4 py-3' },\n ],\n defaultVariants: {\n variant: 'dashed',\n size: 'default',\n layout: 'stacked',\n },\n})\n\ntype EmptyStateVariants = VariantProps<typeof emptyStateVariants>\n\n// A leftover `title` would otherwise compile and render as a tooltip, not a heading.\ninterface EmptyStateProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'title'>,\n Pick<EmptyStateVariants, 'variant'> {\n // null would switch off the compound cells and drop all padding and gap\n size?: NonNullable<EmptyStateVariants['size']>\n layout?: NonNullable<EmptyStateVariants['layout']>\n icon?: SparkIcon\n children: ReactNode\n}\n\nconst EmptyStateContext = createContext<{\n size: NonNullable<EmptyStateVariants['size']>\n layout: NonNullable<EmptyStateVariants['layout']>\n}>({ size: 'default', layout: 'stacked' })\n\nfunction EmptyStateTitle({\n className,\n ...props\n}: HTMLAttributes<HTMLHeadingElement>) {\n const { size } = useContext(EmptyStateContext)\n return (\n <h3\n data-slot=\"empty-state-title\"\n className={cn(\n 'text-gray',\n size === 'sm' ? 'text-sm font-semibold' : 'text-base font-bold',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyStateDescription({\n className,\n ...props\n}: HTMLAttributes<HTMLParagraphElement>) {\n const { size, layout } = useContext(EmptyStateContext)\n return (\n <p\n data-slot=\"empty-state-description\"\n className={cn(\n layout !== 'inline' && 'mx-auto',\n 'max-w-md text-gray-light',\n size === 'sm' ? 'text-xs' : 'text-sm',\n className,\n )}\n {...props}\n />\n )\n}\n\
|
|
1
|
+
{"version":3,"file":"empty-state.js","names":[],"sources":["../../src/components/empty-state.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport {\n createContext,\n type HTMLAttributes,\n type ReactNode,\n useContext,\n} from 'react'\nimport { cn } from '../utils/cn'\nimport { Icon } from './icon'\n\nconst emptyStateVariants = cva('flex', {\n variants: {\n variant: {\n dashed: 'rounded-lg border border-dashed border-gray',\n ghost: '',\n },\n size: { default: '', sm: '' },\n layout: {\n stacked: 'flex-col items-center text-center',\n inline: 'flex-row items-start text-left',\n },\n },\n compoundVariants: [\n { layout: 'stacked', size: 'default', class: 'gap-4 px-6 py-12' },\n { layout: 'stacked', size: 'sm', class: 'gap-2 px-4 py-5' },\n { layout: 'inline', size: 'default', class: 'gap-4 p-6' },\n { layout: 'inline', size: 'sm', class: 'gap-3 px-4 py-3' },\n ],\n defaultVariants: {\n variant: 'dashed',\n size: 'default',\n layout: 'stacked',\n },\n})\n\ntype EmptyStateVariants = VariantProps<typeof emptyStateVariants>\n\n// A leftover `title` would otherwise compile and render as a tooltip, not a heading.\ninterface EmptyStateProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'title'>,\n Pick<EmptyStateVariants, 'variant'> {\n // null would switch off the compound cells and drop all padding and gap\n size?: NonNullable<EmptyStateVariants['size']>\n layout?: NonNullable<EmptyStateVariants['layout']>\n icon?: SparkIcon\n children: ReactNode\n}\n\nconst EmptyStateContext = createContext<{\n size: NonNullable<EmptyStateVariants['size']>\n layout: NonNullable<EmptyStateVariants['layout']>\n}>({ size: 'default', layout: 'stacked' })\n\nfunction EmptyStateTitle({\n className,\n ...props\n}: HTMLAttributes<HTMLHeadingElement>) {\n const { size } = useContext(EmptyStateContext)\n return (\n <h3\n data-slot=\"empty-state-title\"\n className={cn(\n 'text-gray',\n size === 'sm' ? 'text-sm font-semibold' : 'text-base font-bold',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyStateDescription({\n className,\n ...props\n}: HTMLAttributes<HTMLParagraphElement>) {\n const { size, layout } = useContext(EmptyStateContext)\n return (\n <p\n data-slot=\"empty-state-description\"\n className={cn(\n layout !== 'inline' && 'mx-auto',\n 'max-w-md text-gray-light',\n size === 'sm' ? 'text-xs' : 'text-sm',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyStateActions({\n className,\n ...props\n}: HTMLAttributes<HTMLDivElement>) {\n const { layout } = useContext(EmptyStateContext)\n return (\n <div\n data-slot=\"empty-state-actions\"\n className={cn(\n 'mt-2 flex flex-wrap gap-2',\n layout === 'stacked' && 'justify-center',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyState({\n children,\n className,\n icon: Glyph,\n layout = 'stacked',\n size = 'default',\n variant,\n ...props\n}: EmptyStateProps) {\n return (\n <EmptyStateContext.Provider value={{ size, layout }}>\n <div\n data-slot=\"empty-state\"\n className={cn(emptyStateVariants({ variant, size, layout }), className)}\n {...props}\n >\n {Glyph ? (\n <Icon size={size === 'sm' ? 'small' : 'xl'}>\n <Glyph />\n </Icon>\n ) : null}\n <div\n className={cn(\n 'flex flex-col gap-2',\n layout === 'inline' && 'min-w-0 flex-1',\n )}\n >\n {children}\n </div>\n </div>\n </EmptyStateContext.Provider>\n )\n}\n\nexport { EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateTitle }\nexport type { EmptyStateProps }\n"],"mappings":";;;;;;;AAWA,MAAM,qBAAqB,IAAI,QAAQ;CACrC,UAAU;EACR,SAAS;GACP,QAAQ;GACR,OAAO;EACT;EACA,MAAM;GAAE,SAAS;GAAI,IAAI;EAAG;EAC5B,QAAQ;GACN,SAAS;GACT,QAAQ;EACV;CACF;CACA,kBAAkB;EAChB;GAAE,QAAQ;GAAW,MAAM;GAAW,OAAO;EAAmB;EAChE;GAAE,QAAQ;GAAW,MAAM;GAAM,OAAO;EAAkB;EAC1D;GAAE,QAAQ;GAAU,MAAM;GAAW,OAAO;EAAY;EACxD;GAAE,QAAQ;GAAU,MAAM;GAAM,OAAO;EAAkB;CAC3D;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;EACN,QAAQ;CACV;AACF,CAAC;AAgBD,MAAM,oBAAoB,cAGvB;CAAE,MAAM;CAAW,QAAQ;AAAU,CAAC;AAEzC,SAAS,gBAAgB,EACvB,WACA,GAAG,SACkC;CACrC,MAAM,EAAE,SAAS,WAAW,iBAAiB;CAC7C,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,aACA,SAAS,OAAO,0BAA0B,uBAC1C,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,sBAAsB,EAC7B,WACA,GAAG,SACoC;CACvC,MAAM,EAAE,MAAM,WAAW,WAAW,iBAAiB;CACrD,OACE,oBAAC,KAAD;EACE,aAAU;EACV,WAAW,GACT,WAAW,YAAY,WACvB,4BACA,SAAS,OAAO,YAAY,WAC5B,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,kBAAkB,EACzB,WACA,GAAG,SAC8B;CACjC,MAAM,EAAE,WAAW,WAAW,iBAAiB;CAC/C,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,6BACA,WAAW,aAAa,kBACxB,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAClB,UACA,WACA,MAAM,OACN,SAAS,WACT,OAAO,WACP,SACA,GAAG,SACe;CAClB,OACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;GAAE;GAAM;EAAO;YAChD,qBAAC,OAAD;GACE,aAAU;GACV,WAAW,GAAG,mBAAmB;IAAE;IAAS;IAAM;GAAO,CAAC,GAAG,SAAS;GACtE,GAAI;aAHN,CAKG,QACC,oBAAC,MAAD;IAAM,MAAM,SAAS,OAAO,UAAU;cACpC,oBAAC,OAAD,CAAQ,CAAA;GACJ,CAAA,IACJ,MACJ,oBAAC,OAAD;IACE,WAAW,GACT,uBACA,WAAW,YAAY,gBACzB;IAEC;GACE,CAAA,CACF;;CACqB,CAAA;AAEhC"}
|
|
@@ -20,7 +20,7 @@ function EnergyBreakdown({ title, subtitle, items, centerSub = "kWh" }) {
|
|
|
20
20
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21
21
|
className: "flex flex-col gap-4 pt-3 pb-5",
|
|
22
22
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
23
|
-
className: "flex flex-col gap-
|
|
23
|
+
className: "flex flex-col gap-2",
|
|
24
24
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
25
25
|
className: "text-sm font-semibold text-gray",
|
|
26
26
|
children: title
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"energy-breakdown.cjs","names":["formatThousands","integerFormat","oneDecimalFormat","twoDecimalFormat","DonutChart","formatEnergy"],"sources":["../../src/components/energy-breakdown.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { NARROW_NBSP } from '../utils/chars'\nimport {\n formatEnergy,\n formatThousands,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n} from '../utils/format'\nimport { DonutChart } from './donut-chart'\n\nexport type BreakdownItem = {\n label: string\n value: number\n color: string\n excludeFromCenterTotal?: boolean\n}\n\nexport type EnergyBreakdownProps = {\n title: string\n subtitle: string\n items: BreakdownItem[]\n centerSub?: string\n}\n\nfunction formatBreakdownCenter(v: number) {\n if (v >= 1000) return formatThousands(v)\n if (v >= 100) return integerFormat.format(v)\n if (v >= 10) return oneDecimalFormat.format(v)\n return twoDecimalFormat.format(v)\n}\n\nexport function EnergyBreakdown({\n title,\n subtitle,\n items,\n centerSub = 'kWh',\n}: EnergyBreakdownProps) {\n const sortedItems = useMemo(\n () => items.toSorted((a, b) => b.value - a.value),\n [items],\n )\n\n const total = items.reduce((s, i) => s + i.value, 0)\n const centerTotal = items\n .filter((i) => !i.excludeFromCenterTotal)\n .reduce((s, i) => s + i.value, 0)\n\n const dataEmpty = total === 0\n\n if (dataEmpty) return null\n\n return (\n <div className=\"flex flex-col gap-4 pt-3 pb-5\">\n <div className=\"flex flex-col gap-
|
|
1
|
+
{"version":3,"file":"energy-breakdown.cjs","names":["formatThousands","integerFormat","oneDecimalFormat","twoDecimalFormat","DonutChart","formatEnergy"],"sources":["../../src/components/energy-breakdown.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { NARROW_NBSP } from '../utils/chars'\nimport {\n formatEnergy,\n formatThousands,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n} from '../utils/format'\nimport { DonutChart } from './donut-chart'\n\nexport type BreakdownItem = {\n label: string\n value: number\n color: string\n excludeFromCenterTotal?: boolean\n}\n\nexport type EnergyBreakdownProps = {\n title: string\n subtitle: string\n items: BreakdownItem[]\n centerSub?: string\n}\n\nfunction formatBreakdownCenter(v: number) {\n if (v >= 1000) return formatThousands(v)\n if (v >= 100) return integerFormat.format(v)\n if (v >= 10) return oneDecimalFormat.format(v)\n return twoDecimalFormat.format(v)\n}\n\nexport function EnergyBreakdown({\n title,\n subtitle,\n items,\n centerSub = 'kWh',\n}: EnergyBreakdownProps) {\n const sortedItems = useMemo(\n () => items.toSorted((a, b) => b.value - a.value),\n [items],\n )\n\n const total = items.reduce((s, i) => s + i.value, 0)\n const centerTotal = items\n .filter((i) => !i.excludeFromCenterTotal)\n .reduce((s, i) => s + i.value, 0)\n\n const dataEmpty = total === 0\n\n if (dataEmpty) return null\n\n return (\n <div className=\"flex flex-col gap-4 pt-3 pb-5\">\n <div className=\"flex flex-col gap-2\">\n <span className=\"text-sm font-semibold text-gray\">{title}</span>\n <span className=\"text-xs text-gray-light\">{subtitle}</span>\n </div>\n\n <div className=\"flex items-center gap-6\">\n <DonutChart\n centerLabel={formatBreakdownCenter(centerTotal)}\n centerSub={centerSub}\n segments={sortedItems.map(({ value, color }) => ({ value, color }))}\n />\n\n <div className=\"flex flex-1 flex-col gap-3\">\n {sortedItems.map(({ label, value, color }) => {\n const pct = (value / total) * 100\n return (\n <div key={label} className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"min-w-0 truncate text-sm font-medium text-gray\">\n {label}\n </span>\n <span className=\"flex shrink-0 items-baseline gap-1.5 text-xs tabular-nums\">\n <span className=\"text-gray-light\">\n {formatEnergy(value)}\n </span>\n <span className=\"font-semibold text-gray\">\n {`${integerFormat.format(pct)}${NARROW_NBSP}%`}\n </span>\n </span>\n </div>\n <div className=\"h-1 w-full overflow-hidden rounded-full bg-gray-a4\">\n <div\n className=\"h-full rounded-full\"\n style={{ width: `${pct}%`, background: color }}\n />\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":";;;;;;;;AAyBA,SAAS,sBAAsB,GAAW;CACxC,IAAI,KAAK,KAAM,OAAOA,qBAAAA,gBAAgB,CAAC;CACvC,IAAI,KAAK,KAAK,OAAOC,qBAAAA,cAAc,OAAO,CAAC;CAC3C,IAAI,KAAK,IAAI,OAAOC,qBAAAA,iBAAiB,OAAO,CAAC;CAC7C,OAAOC,qBAAAA,iBAAiB,OAAO,CAAC;AAClC;AAEA,SAAgB,gBAAgB,EAC9B,OACA,UACA,OACA,YAAY,SACW;CACvB,MAAM,eAAA,GAAA,MAAA,eACE,MAAM,UAAU,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,GAChD,CAAC,KAAK,CACR;CAEA,MAAM,QAAQ,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;CACnD,MAAM,cAAc,MACjB,QAAQ,MAAM,CAAC,EAAE,sBAAsB,EACvC,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;CAIlC,IAFkB,UAAU,GAEb,OAAO;CAEtB,OACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;EAAK,WAAU;YAAf,CACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;GAAK,WAAU;aAAf,CACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;IAAM,WAAU;cAAmC;GAAY,CAAA,GAC/D,iBAAA,GAAA,kBAAA,KAAC,QAAD;IAAM,WAAU;cAA2B;GAAe,CAAA,CACvD;MAEL,iBAAA,GAAA,kBAAA,MAAC,OAAD;GAAK,WAAU;aAAf,CACE,iBAAA,GAAA,kBAAA,KAACC,+BAAAA,YAAD;IACE,aAAa,sBAAsB,WAAW;IACnC;IACX,UAAU,YAAY,KAAK,EAAE,OAAO,aAAa;KAAE;KAAO;IAAM,EAAE;GACnE,CAAA,GAED,iBAAA,GAAA,kBAAA,KAAC,OAAD;IAAK,WAAU;cACZ,YAAY,KAAK,EAAE,OAAO,OAAO,YAAY;KAC5C,MAAM,MAAO,QAAQ,QAAS;KAC9B,OACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;MAAiB,WAAU;gBAA3B,CACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;OAAK,WAAU;iBAAf,CACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;QAAM,WAAU;kBACb;OACG,CAAA,GACN,iBAAA,GAAA,kBAAA,MAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;SAAM,WAAU;mBACbC,qBAAAA,aAAa,KAAK;QACf,CAAA,GACN,iBAAA,GAAA,kBAAA,KAAC,QAAD;SAAM,WAAU;mBACb,GAAGJ,qBAAAA,cAAc,OAAO,GAAG;QACxB,CAAA,CACF;SACH;UACL,iBAAA,GAAA,kBAAA,KAAC,OAAD;OAAK,WAAU;iBACb,iBAAA,GAAA,kBAAA,KAAC,OAAD;QACE,WAAU;QACV,OAAO;SAAE,OAAO,GAAG,IAAI;SAAI,YAAY;QAAM;OAC9C,CAAA;MACE,CAAA,CACF;QApBK,KAoBL;IAET,CAAC;GACE,CAAA,CACF;IACF;;AAET"}
|
|
@@ -19,7 +19,7 @@ function EnergyBreakdown({ title, subtitle, items, centerSub = "kWh" }) {
|
|
|
19
19
|
return /* @__PURE__ */ jsxs("div", {
|
|
20
20
|
className: "flex flex-col gap-4 pt-3 pb-5",
|
|
21
21
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
22
|
-
className: "flex flex-col gap-
|
|
22
|
+
className: "flex flex-col gap-2",
|
|
23
23
|
children: [/* @__PURE__ */ jsx("span", {
|
|
24
24
|
className: "text-sm font-semibold text-gray",
|
|
25
25
|
children: title
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"energy-breakdown.js","names":[],"sources":["../../src/components/energy-breakdown.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { NARROW_NBSP } from '../utils/chars'\nimport {\n formatEnergy,\n formatThousands,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n} from '../utils/format'\nimport { DonutChart } from './donut-chart'\n\nexport type BreakdownItem = {\n label: string\n value: number\n color: string\n excludeFromCenterTotal?: boolean\n}\n\nexport type EnergyBreakdownProps = {\n title: string\n subtitle: string\n items: BreakdownItem[]\n centerSub?: string\n}\n\nfunction formatBreakdownCenter(v: number) {\n if (v >= 1000) return formatThousands(v)\n if (v >= 100) return integerFormat.format(v)\n if (v >= 10) return oneDecimalFormat.format(v)\n return twoDecimalFormat.format(v)\n}\n\nexport function EnergyBreakdown({\n title,\n subtitle,\n items,\n centerSub = 'kWh',\n}: EnergyBreakdownProps) {\n const sortedItems = useMemo(\n () => items.toSorted((a, b) => b.value - a.value),\n [items],\n )\n\n const total = items.reduce((s, i) => s + i.value, 0)\n const centerTotal = items\n .filter((i) => !i.excludeFromCenterTotal)\n .reduce((s, i) => s + i.value, 0)\n\n const dataEmpty = total === 0\n\n if (dataEmpty) return null\n\n return (\n <div className=\"flex flex-col gap-4 pt-3 pb-5\">\n <div className=\"flex flex-col gap-
|
|
1
|
+
{"version":3,"file":"energy-breakdown.js","names":[],"sources":["../../src/components/energy-breakdown.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { NARROW_NBSP } from '../utils/chars'\nimport {\n formatEnergy,\n formatThousands,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n} from '../utils/format'\nimport { DonutChart } from './donut-chart'\n\nexport type BreakdownItem = {\n label: string\n value: number\n color: string\n excludeFromCenterTotal?: boolean\n}\n\nexport type EnergyBreakdownProps = {\n title: string\n subtitle: string\n items: BreakdownItem[]\n centerSub?: string\n}\n\nfunction formatBreakdownCenter(v: number) {\n if (v >= 1000) return formatThousands(v)\n if (v >= 100) return integerFormat.format(v)\n if (v >= 10) return oneDecimalFormat.format(v)\n return twoDecimalFormat.format(v)\n}\n\nexport function EnergyBreakdown({\n title,\n subtitle,\n items,\n centerSub = 'kWh',\n}: EnergyBreakdownProps) {\n const sortedItems = useMemo(\n () => items.toSorted((a, b) => b.value - a.value),\n [items],\n )\n\n const total = items.reduce((s, i) => s + i.value, 0)\n const centerTotal = items\n .filter((i) => !i.excludeFromCenterTotal)\n .reduce((s, i) => s + i.value, 0)\n\n const dataEmpty = total === 0\n\n if (dataEmpty) return null\n\n return (\n <div className=\"flex flex-col gap-4 pt-3 pb-5\">\n <div className=\"flex flex-col gap-2\">\n <span className=\"text-sm font-semibold text-gray\">{title}</span>\n <span className=\"text-xs text-gray-light\">{subtitle}</span>\n </div>\n\n <div className=\"flex items-center gap-6\">\n <DonutChart\n centerLabel={formatBreakdownCenter(centerTotal)}\n centerSub={centerSub}\n segments={sortedItems.map(({ value, color }) => ({ value, color }))}\n />\n\n <div className=\"flex flex-1 flex-col gap-3\">\n {sortedItems.map(({ label, value, color }) => {\n const pct = (value / total) * 100\n return (\n <div key={label} className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"min-w-0 truncate text-sm font-medium text-gray\">\n {label}\n </span>\n <span className=\"flex shrink-0 items-baseline gap-1.5 text-xs tabular-nums\">\n <span className=\"text-gray-light\">\n {formatEnergy(value)}\n </span>\n <span className=\"font-semibold text-gray\">\n {`${integerFormat.format(pct)}${NARROW_NBSP}%`}\n </span>\n </span>\n </div>\n <div className=\"h-1 w-full overflow-hidden rounded-full bg-gray-a4\">\n <div\n className=\"h-full rounded-full\"\n style={{ width: `${pct}%`, background: color }}\n />\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":";;;;;;;AAyBA,SAAS,sBAAsB,GAAW;CACxC,IAAI,KAAK,KAAM,OAAO,gBAAgB,CAAC;CACvC,IAAI,KAAK,KAAK,OAAO,cAAc,OAAO,CAAC;CAC3C,IAAI,KAAK,IAAI,OAAO,iBAAiB,OAAO,CAAC;CAC7C,OAAO,iBAAiB,OAAO,CAAC;AAClC;AAEA,SAAgB,gBAAgB,EAC9B,OACA,UACA,OACA,YAAY,SACW;CACvB,MAAM,cAAc,cACZ,MAAM,UAAU,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,GAChD,CAAC,KAAK,CACR;CAEA,MAAM,QAAQ,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;CACnD,MAAM,cAAc,MACjB,QAAQ,MAAM,CAAC,EAAE,sBAAsB,EACvC,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;CAIlC,IAFkB,UAAU,GAEb,OAAO;CAEtB,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAD;IAAM,WAAU;cAAmC;GAAY,CAAA,GAC/D,oBAAC,QAAD;IAAM,WAAU;cAA2B;GAAe,CAAA,CACvD;MAEL,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,YAAD;IACE,aAAa,sBAAsB,WAAW;IACnC;IACX,UAAU,YAAY,KAAK,EAAE,OAAO,aAAa;KAAE;KAAO;IAAM,EAAE;GACnE,CAAA,GAED,oBAAC,OAAD;IAAK,WAAU;cACZ,YAAY,KAAK,EAAE,OAAO,OAAO,YAAY;KAC5C,MAAM,MAAO,QAAQ,QAAS;KAC9B,OACE,qBAAC,OAAD;MAAiB,WAAU;gBAA3B,CACE,qBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,oBAAC,QAAD;QAAM,WAAU;kBACb;OACG,CAAA,GACN,qBAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,oBAAC,QAAD;SAAM,WAAU;mBACb,aAAa,KAAK;QACf,CAAA,GACN,oBAAC,QAAD;SAAM,WAAU;mBACb,GAAG,cAAc,OAAO,GAAG;QACxB,CAAA,CACF;SACH;UACL,oBAAC,OAAD;OAAK,WAAU;iBACb,oBAAC,OAAD;QACE,WAAU;QACV,OAAO;SAAE,OAAO,GAAG,IAAI;SAAI,YAAY;QAAM;OAC9C,CAAA;MACE,CAAA,CACF;QApBK,KAoBL;IAET,CAAC;GACE,CAAA,CACF;IACF;;AAET"}
|
|
@@ -43,7 +43,7 @@ const EntityCardIcon = ({ className, icon: Glyph, tone, ...rest }) => /* @__PURE
|
|
|
43
43
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Glyph, { className: "[--spark-icon-size:18px]" })
|
|
44
44
|
});
|
|
45
45
|
const EntityCardTitleColumn = ({ className, ...rest }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
46
|
-
className: (0, cn.cn)("flex min-w-0 flex-1 flex-col gap-
|
|
46
|
+
className: (0, cn.cn)("flex min-w-0 flex-1 flex-col gap-1", className),
|
|
47
47
|
...rest
|
|
48
48
|
});
|
|
49
49
|
const EntityCardTitle = ({ className, ...rest }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-card.cjs","names":[],"sources":["../../src/components/entity-card.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport type { Tone } from '../lib/tones'\nimport { cn } from '../utils/cn'\n\nconst EntityCard = ({ className, ...rest }: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex flex-col overflow-hidden rounded-lg border border-gray bg-(--spark-background)',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardBody = ({\n className,\n active,\n ...rest\n}: React.ComponentProps<'button'> & { active?: boolean }) => (\n <button\n type=\"button\"\n className={cn(\n 'flex w-full cursor-pointer flex-col gap-3 p-4 text-left transition-colors hover:bg-gray-a2 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n active && 'bg-linear-to-br from-spark-9/10 to-spark-1/5 to-20%',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardHeader = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div className={cn('flex w-full items-center gap-3', className)} {...rest} />\n)\n\nconst EntityCardMeters = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex flex-col gap-2 border-t border-gray pt-3', className)}\n {...rest}\n />\n)\n\nconst iconToneVariants = cva(\n // max() pill escape (matches Icon): a tile stays rounded-md at low Roundness but\n // becomes a circle at large/full, same as it did pre-harmonization via clamping.\n 'flex size-11 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n {\n variants: {\n tone: {\n success: 'bg-success-soft text-success-soft-foreground',\n warning: 'bg-warning-soft text-warning-soft-foreground',\n error: 'bg-error-soft text-error-soft-foreground',\n accent: 'bg-primary-soft text-primary-soft-foreground',\n neutral: 'bg-base-gray-soft text-gray',\n },\n },\n defaultVariants: { tone: 'neutral' },\n },\n)\n\nconst EntityCardIcon = ({\n className,\n icon: Glyph,\n tone,\n ...rest\n}: React.ComponentProps<'span'> & {\n icon: SparkIcon\n tone?: Tone\n}) => (\n <span className={iconToneVariants({ tone, className })} {...rest}>\n <Glyph className=\"[--spark-icon-size:18px]\" />\n </span>\n)\n\nconst EntityCardTitleColumn = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex min-w-0 flex-1 flex-col gap-
|
|
1
|
+
{"version":3,"file":"entity-card.cjs","names":[],"sources":["../../src/components/entity-card.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport type { Tone } from '../lib/tones'\nimport { cn } from '../utils/cn'\n\nconst EntityCard = ({ className, ...rest }: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex flex-col overflow-hidden rounded-lg border border-gray bg-(--spark-background)',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardBody = ({\n className,\n active,\n ...rest\n}: React.ComponentProps<'button'> & { active?: boolean }) => (\n <button\n type=\"button\"\n className={cn(\n 'flex w-full cursor-pointer flex-col gap-3 p-4 text-left transition-colors hover:bg-gray-a2 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n active && 'bg-linear-to-br from-spark-9/10 to-spark-1/5 to-20%',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardHeader = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div className={cn('flex w-full items-center gap-3', className)} {...rest} />\n)\n\nconst EntityCardMeters = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex flex-col gap-2 border-t border-gray pt-3', className)}\n {...rest}\n />\n)\n\nconst iconToneVariants = cva(\n // max() pill escape (matches Icon): a tile stays rounded-md at low Roundness but\n // becomes a circle at large/full, same as it did pre-harmonization via clamping.\n 'flex size-11 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n {\n variants: {\n tone: {\n success: 'bg-success-soft text-success-soft-foreground',\n warning: 'bg-warning-soft text-warning-soft-foreground',\n error: 'bg-error-soft text-error-soft-foreground',\n accent: 'bg-primary-soft text-primary-soft-foreground',\n neutral: 'bg-base-gray-soft text-gray',\n },\n },\n defaultVariants: { tone: 'neutral' },\n },\n)\n\nconst EntityCardIcon = ({\n className,\n icon: Glyph,\n tone,\n ...rest\n}: React.ComponentProps<'span'> & {\n icon: SparkIcon\n tone?: Tone\n}) => (\n <span className={iconToneVariants({ tone, className })} {...rest}>\n <Glyph className=\"[--spark-icon-size:18px]\" />\n </span>\n)\n\nconst EntityCardTitleColumn = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex min-w-0 flex-1 flex-col gap-1', className)}\n {...rest}\n />\n)\n\nconst EntityCardTitle = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => (\n <span\n className={cn('truncate text-sm font-bold text-gray', className)}\n {...rest}\n />\n)\n\nconst stateToneVariants = cva(\n 'inline-flex items-center gap-1.5 text-xs font-medium',\n {\n variants: {\n tone: {\n success: 'text-success',\n warning: 'text-warning',\n error: 'text-error',\n accent: 'text-accent',\n neutral: 'text-gray-light',\n },\n },\n defaultVariants: { tone: 'neutral' },\n },\n)\n\nconst dotToneVariants = cva('size-1.5 shrink-0 rounded-full', {\n variants: {\n tone: {\n success: 'bg-base-success-solid',\n warning: 'bg-base-warning-solid',\n error: 'bg-base-error-solid',\n accent: 'bg-primary',\n neutral: 'bg-base-gray-solid',\n },\n },\n defaultVariants: { tone: 'neutral' },\n})\n\nconst EntityCardState = ({\n className,\n tone,\n children,\n ...rest\n}: React.ComponentProps<'span'> & { tone?: Tone }) => (\n <span className={stateToneVariants({ tone, className })} {...rest}>\n <span className={dotToneVariants({ tone })} />\n <span className=\"truncate\">{children}</span>\n </span>\n)\n\nconst EntityCardDetail = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => (\n <span\n className={cn('truncate text-xs text-gray-light tabular-nums', className)}\n {...rest}\n />\n)\n\nconst EntityCardValue = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => (\n <span\n className={cn(\n 'ms-2 shrink-0 self-center text-lg leading-tight font-bold text-gray tabular-nums',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardControls = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex items-center gap-3 border-t border-gray bg-base-gray-surface px-4 py-3',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardFooter = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex items-center justify-center gap-1.5 border-t border-gray bg-base-gray-surface px-4 py-2 text-xs text-gray-light',\n className,\n )}\n {...rest}\n />\n)\n\nexport {\n EntityCard,\n EntityCardBody,\n EntityCardControls,\n EntityCardDetail,\n EntityCardFooter,\n EntityCardHeader,\n EntityCardIcon,\n EntityCardMeters,\n EntityCardState,\n EntityCardTitle,\n EntityCardTitleColumn,\n EntityCardValue,\n}\n"],"mappings":"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"}
|
|
@@ -40,7 +40,7 @@ const EntityCardIcon = ({ className, icon: Glyph, tone, ...rest }) => /* @__PURE
|
|
|
40
40
|
children: /* @__PURE__ */ jsx(Glyph, { className: "[--spark-icon-size:18px]" })
|
|
41
41
|
});
|
|
42
42
|
const EntityCardTitleColumn = ({ className, ...rest }) => /* @__PURE__ */ jsx("div", {
|
|
43
|
-
className: cn("flex min-w-0 flex-1 flex-col gap-
|
|
43
|
+
className: cn("flex min-w-0 flex-1 flex-col gap-1", className),
|
|
44
44
|
...rest
|
|
45
45
|
});
|
|
46
46
|
const EntityCardTitle = ({ className, ...rest }) => /* @__PURE__ */ jsx("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-card.js","names":[],"sources":["../../src/components/entity-card.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport type { Tone } from '../lib/tones'\nimport { cn } from '../utils/cn'\n\nconst EntityCard = ({ className, ...rest }: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex flex-col overflow-hidden rounded-lg border border-gray bg-(--spark-background)',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardBody = ({\n className,\n active,\n ...rest\n}: React.ComponentProps<'button'> & { active?: boolean }) => (\n <button\n type=\"button\"\n className={cn(\n 'flex w-full cursor-pointer flex-col gap-3 p-4 text-left transition-colors hover:bg-gray-a2 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n active && 'bg-linear-to-br from-spark-9/10 to-spark-1/5 to-20%',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardHeader = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div className={cn('flex w-full items-center gap-3', className)} {...rest} />\n)\n\nconst EntityCardMeters = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex flex-col gap-2 border-t border-gray pt-3', className)}\n {...rest}\n />\n)\n\nconst iconToneVariants = cva(\n // max() pill escape (matches Icon): a tile stays rounded-md at low Roundness but\n // becomes a circle at large/full, same as it did pre-harmonization via clamping.\n 'flex size-11 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n {\n variants: {\n tone: {\n success: 'bg-success-soft text-success-soft-foreground',\n warning: 'bg-warning-soft text-warning-soft-foreground',\n error: 'bg-error-soft text-error-soft-foreground',\n accent: 'bg-primary-soft text-primary-soft-foreground',\n neutral: 'bg-base-gray-soft text-gray',\n },\n },\n defaultVariants: { tone: 'neutral' },\n },\n)\n\nconst EntityCardIcon = ({\n className,\n icon: Glyph,\n tone,\n ...rest\n}: React.ComponentProps<'span'> & {\n icon: SparkIcon\n tone?: Tone\n}) => (\n <span className={iconToneVariants({ tone, className })} {...rest}>\n <Glyph className=\"[--spark-icon-size:18px]\" />\n </span>\n)\n\nconst EntityCardTitleColumn = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex min-w-0 flex-1 flex-col gap-
|
|
1
|
+
{"version":3,"file":"entity-card.js","names":[],"sources":["../../src/components/entity-card.tsx"],"sourcesContent":["import type { SparkIcon } from '@epilot/spark-icons'\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport type { Tone } from '../lib/tones'\nimport { cn } from '../utils/cn'\n\nconst EntityCard = ({ className, ...rest }: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex flex-col overflow-hidden rounded-lg border border-gray bg-(--spark-background)',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardBody = ({\n className,\n active,\n ...rest\n}: React.ComponentProps<'button'> & { active?: boolean }) => (\n <button\n type=\"button\"\n className={cn(\n 'flex w-full cursor-pointer flex-col gap-3 p-4 text-left transition-colors hover:bg-gray-a2 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n active && 'bg-linear-to-br from-spark-9/10 to-spark-1/5 to-20%',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardHeader = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div className={cn('flex w-full items-center gap-3', className)} {...rest} />\n)\n\nconst EntityCardMeters = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex flex-col gap-2 border-t border-gray pt-3', className)}\n {...rest}\n />\n)\n\nconst iconToneVariants = cva(\n // max() pill escape (matches Icon): a tile stays rounded-md at low Roundness but\n // becomes a circle at large/full, same as it did pre-harmonization via clamping.\n 'flex size-11 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n {\n variants: {\n tone: {\n success: 'bg-success-soft text-success-soft-foreground',\n warning: 'bg-warning-soft text-warning-soft-foreground',\n error: 'bg-error-soft text-error-soft-foreground',\n accent: 'bg-primary-soft text-primary-soft-foreground',\n neutral: 'bg-base-gray-soft text-gray',\n },\n },\n defaultVariants: { tone: 'neutral' },\n },\n)\n\nconst EntityCardIcon = ({\n className,\n icon: Glyph,\n tone,\n ...rest\n}: React.ComponentProps<'span'> & {\n icon: SparkIcon\n tone?: Tone\n}) => (\n <span className={iconToneVariants({ tone, className })} {...rest}>\n <Glyph className=\"[--spark-icon-size:18px]\" />\n </span>\n)\n\nconst EntityCardTitleColumn = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn('flex min-w-0 flex-1 flex-col gap-1', className)}\n {...rest}\n />\n)\n\nconst EntityCardTitle = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => (\n <span\n className={cn('truncate text-sm font-bold text-gray', className)}\n {...rest}\n />\n)\n\nconst stateToneVariants = cva(\n 'inline-flex items-center gap-1.5 text-xs font-medium',\n {\n variants: {\n tone: {\n success: 'text-success',\n warning: 'text-warning',\n error: 'text-error',\n accent: 'text-accent',\n neutral: 'text-gray-light',\n },\n },\n defaultVariants: { tone: 'neutral' },\n },\n)\n\nconst dotToneVariants = cva('size-1.5 shrink-0 rounded-full', {\n variants: {\n tone: {\n success: 'bg-base-success-solid',\n warning: 'bg-base-warning-solid',\n error: 'bg-base-error-solid',\n accent: 'bg-primary',\n neutral: 'bg-base-gray-solid',\n },\n },\n defaultVariants: { tone: 'neutral' },\n})\n\nconst EntityCardState = ({\n className,\n tone,\n children,\n ...rest\n}: React.ComponentProps<'span'> & { tone?: Tone }) => (\n <span className={stateToneVariants({ tone, className })} {...rest}>\n <span className={dotToneVariants({ tone })} />\n <span className=\"truncate\">{children}</span>\n </span>\n)\n\nconst EntityCardDetail = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => (\n <span\n className={cn('truncate text-xs text-gray-light tabular-nums', className)}\n {...rest}\n />\n)\n\nconst EntityCardValue = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => (\n <span\n className={cn(\n 'ms-2 shrink-0 self-center text-lg leading-tight font-bold text-gray tabular-nums',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardControls = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex items-center gap-3 border-t border-gray bg-base-gray-surface px-4 py-3',\n className,\n )}\n {...rest}\n />\n)\n\nconst EntityCardFooter = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => (\n <div\n className={cn(\n 'flex items-center justify-center gap-1.5 border-t border-gray bg-base-gray-surface px-4 py-2 text-xs text-gray-light',\n className,\n )}\n {...rest}\n />\n)\n\nexport {\n EntityCard,\n EntityCardBody,\n EntityCardControls,\n EntityCardDetail,\n EntityCardFooter,\n EntityCardHeader,\n EntityCardIcon,\n EntityCardMeters,\n EntityCardState,\n EntityCardTitle,\n EntityCardTitleColumn,\n EntityCardValue,\n}\n"],"mappings":";;;;;;AAMA,MAAM,cAAc,EAAE,WAAW,GAAG,WAClC,oBAAC,OAAD;CACE,WAAW,GACT,uFACA,SACF;CACA,GAAI;AACL,CAAA;AAGH,MAAM,kBAAkB,EACtB,WACA,QACA,GAAG,WAEH,oBAAC,UAAD;CACE,MAAK;CACL,WAAW,GACT,yLACA,UAAU,uDACV,SACF;CACA,GAAI;AACL,CAAA;AAGH,MAAM,oBAAoB,EACxB,WACA,GAAG,WAEH,oBAAC,OAAD;CAAK,WAAW,GAAG,kCAAkC,SAAS;CAAG,GAAI;AAAO,CAAA;AAG9E,MAAM,oBAAoB,EACxB,WACA,GAAG,WAEH,oBAAC,OAAD;CACE,WAAW,GAAG,iDAAiD,SAAS;CACxE,GAAI;AACL,CAAA;AAGH,MAAM,mBAAmB,IAGvB,sHACA;CACE,UAAU,EACR,MAAM;EACJ,SAAS;EACT,SAAS;EACT,OAAO;EACP,QAAQ;EACR,SAAS;CACX,EACF;CACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CACF;AAEA,MAAM,kBAAkB,EACtB,WACA,MAAM,OACN,MACA,GAAG,WAKH,oBAAC,QAAD;CAAM,WAAW,iBAAiB;EAAE;EAAM;CAAU,CAAC;CAAG,GAAI;WAC1D,oBAAC,OAAD,EAAO,WAAU,2BAA4B,CAAA;AACzC,CAAA;AAGR,MAAM,yBAAyB,EAC7B,WACA,GAAG,WAEH,oBAAC,OAAD;CACE,WAAW,GAAG,sCAAsC,SAAS;CAC7D,GAAI;AACL,CAAA;AAGH,MAAM,mBAAmB,EACvB,WACA,GAAG,WAEH,oBAAC,QAAD;CACE,WAAW,GAAG,wCAAwC,SAAS;CAC/D,GAAI;AACL,CAAA;AAGH,MAAM,oBAAoB,IACxB,wDACA;CACE,UAAU,EACR,MAAM;EACJ,SAAS;EACT,SAAS;EACT,OAAO;EACP,QAAQ;EACR,SAAS;CACX,EACF;CACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CACF;AAEA,MAAM,kBAAkB,IAAI,kCAAkC;CAC5D,UAAU,EACR,MAAM;EACJ,SAAS;EACT,SAAS;EACT,OAAO;EACP,QAAQ;EACR,SAAS;CACX,EACF;CACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CAAC;AAED,MAAM,mBAAmB,EACvB,WACA,MACA,UACA,GAAG,WAEH,qBAAC,QAAD;CAAM,WAAW,kBAAkB;EAAE;EAAM;CAAU,CAAC;CAAG,GAAI;WAA7D,CACE,oBAAC,QAAD,EAAM,WAAW,gBAAgB,EAAE,KAAK,CAAC,EAAI,CAAA,GAC7C,oBAAC,QAAD;EAAM,WAAU;EAAY;CAAe,CAAA,CACvC;;AAGR,MAAM,oBAAoB,EACxB,WACA,GAAG,WAEH,oBAAC,QAAD;CACE,WAAW,GAAG,iDAAiD,SAAS;CACxE,GAAI;AACL,CAAA;AAGH,MAAM,mBAAmB,EACvB,WACA,GAAG,WAEH,oBAAC,QAAD;CACE,WAAW,GACT,oFACA,SACF;CACA,GAAI;AACL,CAAA;AAGH,MAAM,sBAAsB,EAC1B,WACA,GAAG,WAEH,oBAAC,OAAD;CACE,WAAW,GACT,+EACA,SACF;CACA,GAAI;AACL,CAAA;AAGH,MAAM,oBAAoB,EACxB,WACA,GAAG,WAEH,oBAAC,OAAD;CACE,WAAW,GACT,wHACA,SACF;CACA,GAAI;AACL,CAAA"}
|
|
@@ -190,7 +190,7 @@ function Field({ className, children, labelPosition: labelPositionProp, inputSty
|
|
|
190
190
|
function FieldContent({ className, ...props }) {
|
|
191
191
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
192
192
|
"data-slot": "field-content",
|
|
193
|
-
className: (0, cn.cn)("flex min-w-0 flex-1 flex-col gap-
|
|
193
|
+
className: (0, cn.cn)("flex min-w-0 flex-1 flex-col gap-1 leading-snug", className),
|
|
194
194
|
...props
|
|
195
195
|
});
|
|
196
196
|
}
|
|
@@ -255,7 +255,7 @@ function FieldDescription({ className, id, ...props }) {
|
|
|
255
255
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
256
256
|
"data-slot": "field-description",
|
|
257
257
|
id: id ?? field?.descriptionId,
|
|
258
|
-
className: (0, cn.cn)("
|
|
258
|
+
className: (0, cn.cn)("text-sm leading-normal text-gray-light", className),
|
|
259
259
|
...props
|
|
260
260
|
});
|
|
261
261
|
}
|
|
@@ -301,7 +301,7 @@ function FieldError({ className, children, errors, id, ...props }) {
|
|
|
301
301
|
role: "alert",
|
|
302
302
|
"data-slot": "field-error",
|
|
303
303
|
id: id ?? field?.errorId,
|
|
304
|
-
className: (0, cn.cn)("
|
|
304
|
+
className: (0, cn.cn)("text-sm font-normal text-error", className),
|
|
305
305
|
...props,
|
|
306
306
|
children: content
|
|
307
307
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.cjs","names":["React","useTheme","Skeleton","Separator"],"sources":["../../src/components/field.tsx"],"sourcesContent":["'use client'\n\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport { useId } from 'react'\nimport type {\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n} from '../lib/theme-types'\nimport { cn } from '../utils/cn'\nimport { Separator } from './separator'\nimport { Skeleton } from './skeleton'\nimport { useTheme } from './theme'\n\ntype FieldContextValue = {\n id: string\n labelId: string\n descriptionId: string\n hasDescription: boolean\n setHasDescription: (has: boolean) => void\n errorId: string\n hasError: boolean\n setHasError: (has: boolean) => void\n readOnly: boolean\n labelPosition: SparkLabelPosition\n inputStyle: SparkInputStyle\n inputColor: SparkInputColor\n}\n\nconst FieldContext = React.createContext<FieldContextValue | null>(null)\n\nexport function useFieldContext() {\n return React.useContext(FieldContext)\n}\n\n// Field→Theme→default resolution + id/aria-describedby wiring, shared by every\n// control that can sit inside a Field (Input, SelectTrigger, …) so they can't\n// drift on how a style/color/id resolves. `variant` is the control's own\n// per-instance override (already normalized — e.g. Input maps its 'none' to\n// undefined before calling this).\nexport function useFieldControl(options?: {\n id?: string\n ariaDescribedBy?: string\n variant?: SparkInputStyle\n}) {\n const field = useFieldContext()\n const theme = useTheme()\n const id = options?.id ?? field?.id\n const errorId = field?.hasError ? field.errorId : undefined\n const descriptionId = field?.hasDescription ? field.descriptionId : undefined\n // error before hint: the actionable message should be announced first\n const ariaDescribedBy =\n [errorId, descriptionId, options?.ariaDescribedBy]\n .filter(Boolean)\n .join(' ') || undefined\n const inputStyle =\n options?.variant ?? field?.inputStyle ?? theme.inputStyle ?? 'soft'\n const inputColor = field?.inputColor ?? theme.inputColor ?? 'brand'\n const ariaInvalid = field?.hasError || undefined\n return { field, id, ariaDescribedBy, ariaInvalid, inputStyle, inputColor }\n}\n\nfunction FieldSet({ className, ...props }: React.ComponentProps<'fieldset'>) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*4)]',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLegend({\n className,\n variant = 'legend',\n ...props\n}: React.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\n 'mb-1.5 font-medium text-gray data-[variant=label]:text-sm data-[variant=legend]:text-base',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction FieldGroup({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n 'group/field-group flex w-full flex-col gap-[calc(var(--spark-layout-gap)*4)]',\n className,\n )}\n {...props}\n />\n )\n}\n\nconst fieldVariants = cva(\n 'group/field relative flex w-full flex-col data-[invalid=true]:text-error-active',\n {\n variants: {\n labelPosition: {\n // inset puts label + input inside one shell, so the shell IS the input's box —\n // rounded-md tracks Input/Select/etc.'s own control radius, not the container one.\n // focus inside inset is the classic underline cue, not a shell ring\n inset: 'gap-y-1 rounded-md px-4 py-3',\n outset: 'gap-y-2',\n },\n inputStyle: { soft: '', surface: '', outlined: '', ghost: '' },\n inputColor: { brand: '', gray: '' },\n },\n compoundVariants: [\n {\n labelPosition: 'inset',\n inputStyle: 'soft',\n inputColor: 'brand',\n class:\n 'bg-input-base has-[:is(input,textarea,[data-slot=select-trigger]):not(:disabled)]:hover:bg-input-base-hover',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'soft',\n inputColor: 'gray',\n class:\n 'bg-base-gray-soft has-[:is(input,textarea,[data-slot=select-trigger]):not(:disabled)]:hover:bg-gray-a4',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'surface',\n inputColor: 'brand',\n class: 'border border-input bg-base-accent-surface',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'surface',\n inputColor: 'gray',\n class: 'border border-input-gray bg-base-gray-surface',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'outlined',\n inputColor: 'brand',\n class: 'border border-input',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'outlined',\n inputColor: 'gray',\n class: 'border border-input-gray',\n },\n // ghost inset = bare label + underlined input; the input carries the line\n {\n labelPosition: 'inset',\n inputStyle: 'ghost',\n class: 'rounded-none px-0',\n },\n // shared inset states: filled shells swap bg, bordered shells swap border\n // invalid hover deepens the error tint instead of falling back to accent\n {\n labelPosition: 'inset',\n inputStyle: ['soft', 'surface'],\n class:\n 'data-[disabled=true]:bg-base-gray-soft data-[invalid=true]:bg-base-error-soft data-[invalid=true]:has-[:is(input,textarea,[data-slot=select-trigger]):not(:disabled)]:hover:bg-red-a4',\n },\n {\n labelPosition: 'inset',\n inputStyle: ['surface', 'outlined'],\n class:\n 'data-[disabled=true]:border-input-disabled data-[invalid=true]:border-input-invalid',\n },\n ],\n },\n)\n\ninterface FieldProps extends React.ComponentProps<'div'> {\n labelPosition?: SparkLabelPosition\n inputStyle?: SparkInputStyle\n inputColor?: SparkInputColor\n readOnly?: boolean\n 'data-invalid'?: boolean | 'true' | 'false'\n}\n\nfunction Field({\n className,\n children,\n labelPosition: labelPositionProp,\n inputStyle: inputStyleProp,\n inputColor: inputColorProp,\n readOnly = false,\n 'data-invalid': dataInvalid,\n ...props\n}: FieldProps) {\n const id = useId()\n const [descriptionCount, setDescriptionCount] = React.useState(0)\n const [errorCount, setErrorCount] = React.useState(0)\n // counts, not flags: one slot unmounting must not clear what siblings still need\n const setHasDescription = React.useCallback(\n (has: boolean) => setDescriptionCount((n) => n + (has ? 1 : -1)),\n [],\n )\n const setHasError = React.useCallback(\n (has: boolean) => setErrorCount((n) => n + (has ? 1 : -1)),\n [],\n )\n const hasDescription = descriptionCount > 0\n const hasError = errorCount > 0\n // knobs are structural (they move the label / pick the box carrier), so they\n // resolve here via the <Theme> context; props override per instance\n const theme = useTheme()\n const labelPosition = labelPositionProp ?? theme.labelPosition ?? 'inset'\n const inputStyle = inputStyleProp ?? theme.inputStyle ?? 'soft'\n const inputColor = inputColorProp ?? theme.inputColor ?? 'brand'\n const fieldId = `field-${id}`\n const labelId = `${fieldId}-label`\n const value = React.useMemo<FieldContextValue>(\n () => ({\n id: fieldId,\n labelId,\n descriptionId: `${fieldId}-description`,\n hasDescription,\n setHasDescription,\n errorId: `${fieldId}-error`,\n hasError,\n setHasError,\n readOnly,\n labelPosition,\n inputStyle,\n inputColor,\n }),\n [\n fieldId,\n labelId,\n hasDescription,\n setHasDescription,\n hasError,\n setHasError,\n readOnly,\n labelPosition,\n inputStyle,\n inputColor,\n ],\n )\n\n return (\n <FieldContext.Provider value={value}>\n <div\n role=\"group\"\n data-slot=\"field\"\n data-label-position={labelPosition}\n data-input-style={inputStyle}\n data-input-color={inputColor}\n data-invalid={dataInvalid ?? (hasError || undefined)}\n aria-labelledby={readOnly ? labelId : undefined}\n className={cn(\n fieldVariants({ labelPosition, inputStyle, inputColor }),\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </FieldContext.Provider>\n )\n}\n\nfunction FieldContent({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\n 'flex min-w-0 flex-1 flex-col gap-0.5 leading-snug',\n className,\n )}\n {...props}\n />\n )\n}\n\nconst fieldLabelClassName =\n 'text-sm leading-5 font-normal text-gray transition-all group-data-[invalid=true]/field:text-error-active! motion-reduce:transition-none'\n\nfunction FieldLabel({\n className,\n htmlFor,\n srOnly,\n children,\n ...props\n}: React.ComponentProps<'label'> & { srOnly?: boolean }) {\n const field = useFieldContext()\n const classNames = cn(\n // labels stay full-contrast even when disabled — the control itself\n // (dimmed text, gray shell) signals the state\n fieldLabelClassName,\n // visually hidden but kept in the a11y tree (still names + focuses the control)\n srOnly && 'sr-only',\n className,\n )\n\n if (field?.readOnly) {\n return (\n <div data-slot=\"field-label\" id={field.labelId} className={classNames}>\n {children}\n </div>\n )\n }\n\n return (\n <label\n data-slot=\"field-label\"\n className={classNames}\n htmlFor={htmlFor ?? field?.id}\n {...props}\n >\n {children}\n </label>\n )\n}\n\nfunction FieldValue({\n className,\n id,\n title,\n truncate,\n children,\n ...props\n}: React.ComponentProps<'div'> & { truncate?: boolean }) {\n return (\n <div\n data-slot=\"field-value\"\n id={id}\n // truncated string values keep the full text reachable on hover\n title={\n title ??\n (truncate && typeof children === 'string' ? children : undefined)\n }\n className={cn(\n // values are content, not controls — disabled dims but stays ≥4.5:1\n 'min-h-8 w-full text-base text-gray tabular-nums group-data-[disabled=true]/field:opacity-70',\n truncate\n ? 'block truncate leading-8'\n : 'inline-flex items-center wrap-anywhere whitespace-pre-wrap',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nfunction FieldSkeleton({\n className,\n labelClassName,\n valueClassName,\n truncate,\n ...props\n}: React.ComponentProps<'div'> & {\n truncate?: boolean\n labelClassName?: string\n valueClassName?: string\n}) {\n return (\n <div\n data-slot=\"field-skeleton\"\n aria-hidden=\"true\"\n className={cn('flex w-full flex-col gap-y-1', className)}\n {...props}\n >\n <Skeleton\n data-slot=\"field-skeleton-label\"\n className={cn('h-5 w-24', labelClassName)}\n />\n <Skeleton\n data-slot=\"field-skeleton-value\"\n className={cn(\n 'h-8 min-h-8 w-full',\n truncate && 'max-w-full truncate',\n valueClassName,\n )}\n />\n </div>\n )\n}\n\nfunction FieldTitle({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-title\"\n className={cn(\n 'flex w-fit items-center gap-2 text-sm font-medium text-gray',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction FieldDescription({\n className,\n id,\n ...props\n}: React.ComponentProps<'div'>) {\n const field = useFieldContext()\n const setHasDescription = field?.setHasDescription\n\n React.useEffect(() => {\n if (!setHasDescription) return\n setHasDescription(true)\n return () => setHasDescription(false)\n }, [setHasDescription])\n\n return (\n <div\n data-slot=\"field-description\"\n id={id ?? field?.descriptionId}\n className={cn('mt-0.5 text-sm leading-normal text-gray-light', className)}\n {...props}\n />\n )\n}\n\nfunction FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn('relative -my-2 h-5 text-sm', className)}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"relative mx-auto block w-fit bg-(--spark-background) px-2 text-gray-light\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n )\n}\n\nfunction FieldError({\n className,\n children,\n errors,\n id,\n ...props\n}: React.ComponentProps<'div'> & {\n errors?: Array<{ message?: string } | undefined>\n}) {\n const field = useFieldContext()\n const setHasError = field?.setHasError\n const content = React.useMemo(() => {\n if (children) return children\n if (!errors?.length) return null\n const unique = [\n ...new Map(errors.map((error) => [error?.message, error])).values(),\n ]\n if (unique.length === 1) return unique[0]?.message\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {unique.map(\n (error) =>\n error?.message && <li key={error.message}>{error.message}</li>,\n )}\n </ul>\n )\n }, [children, errors])\n\n const hasContent = Boolean(content)\n // a custom id means no element carries field.errorId, so don't advertise it\n const hasCustomId = id != null\n\n // must run before the empty-content early return to keep hook order stable\n React.useEffect(() => {\n if (!setHasError || !hasContent || hasCustomId) return\n setHasError(true)\n return () => setHasError(false)\n }, [setHasError, hasContent, hasCustomId])\n\n if (!content) return null\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n id={id ?? field?.errorId}\n className={cn('mt-0.5 text-sm font-normal text-error', className)}\n {...props}\n >\n {content}\n </div>\n )\n}\n\nexport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldSkeleton,\n FieldTitle,\n FieldValue,\n}\nexport type { FieldProps }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"field.cjs","names":["React","useTheme","Skeleton","Separator"],"sources":["../../src/components/field.tsx"],"sourcesContent":["'use client'\n\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport { useId } from 'react'\nimport type {\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n} from '../lib/theme-types'\nimport { cn } from '../utils/cn'\nimport { Separator } from './separator'\nimport { Skeleton } from './skeleton'\nimport { useTheme } from './theme'\n\ntype FieldContextValue = {\n id: string\n labelId: string\n descriptionId: string\n hasDescription: boolean\n setHasDescription: (has: boolean) => void\n errorId: string\n hasError: boolean\n setHasError: (has: boolean) => void\n readOnly: boolean\n labelPosition: SparkLabelPosition\n inputStyle: SparkInputStyle\n inputColor: SparkInputColor\n}\n\nconst FieldContext = React.createContext<FieldContextValue | null>(null)\n\nexport function useFieldContext() {\n return React.useContext(FieldContext)\n}\n\n// Field→Theme→default resolution + id/aria-describedby wiring, shared by every\n// control that can sit inside a Field (Input, SelectTrigger, …) so they can't\n// drift on how a style/color/id resolves. `variant` is the control's own\n// per-instance override (already normalized — e.g. Input maps its 'none' to\n// undefined before calling this).\nexport function useFieldControl(options?: {\n id?: string\n ariaDescribedBy?: string\n variant?: SparkInputStyle\n}) {\n const field = useFieldContext()\n const theme = useTheme()\n const id = options?.id ?? field?.id\n const errorId = field?.hasError ? field.errorId : undefined\n const descriptionId = field?.hasDescription ? field.descriptionId : undefined\n // error before hint: the actionable message should be announced first\n const ariaDescribedBy =\n [errorId, descriptionId, options?.ariaDescribedBy]\n .filter(Boolean)\n .join(' ') || undefined\n const inputStyle =\n options?.variant ?? field?.inputStyle ?? theme.inputStyle ?? 'soft'\n const inputColor = field?.inputColor ?? theme.inputColor ?? 'brand'\n const ariaInvalid = field?.hasError || undefined\n return { field, id, ariaDescribedBy, ariaInvalid, inputStyle, inputColor }\n}\n\nfunction FieldSet({ className, ...props }: React.ComponentProps<'fieldset'>) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*4)]',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLegend({\n className,\n variant = 'legend',\n ...props\n}: React.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\n 'mb-1.5 font-medium text-gray data-[variant=label]:text-sm data-[variant=legend]:text-base',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction FieldGroup({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n 'group/field-group flex w-full flex-col gap-[calc(var(--spark-layout-gap)*4)]',\n className,\n )}\n {...props}\n />\n )\n}\n\nconst fieldVariants = cva(\n 'group/field relative flex w-full flex-col data-[invalid=true]:text-error-active',\n {\n variants: {\n labelPosition: {\n // inset puts label + input inside one shell, so the shell IS the input's box —\n // rounded-md tracks Input/Select/etc.'s own control radius, not the container one.\n // focus inside inset is the classic underline cue, not a shell ring\n inset: 'gap-y-1 rounded-md px-4 py-3',\n outset: 'gap-y-2',\n },\n inputStyle: { soft: '', surface: '', outlined: '', ghost: '' },\n inputColor: { brand: '', gray: '' },\n },\n compoundVariants: [\n {\n labelPosition: 'inset',\n inputStyle: 'soft',\n inputColor: 'brand',\n class:\n 'bg-input-base has-[:is(input,textarea,[data-slot=select-trigger]):not(:disabled)]:hover:bg-input-base-hover',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'soft',\n inputColor: 'gray',\n class:\n 'bg-base-gray-soft has-[:is(input,textarea,[data-slot=select-trigger]):not(:disabled)]:hover:bg-gray-a4',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'surface',\n inputColor: 'brand',\n class: 'border border-input bg-base-accent-surface',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'surface',\n inputColor: 'gray',\n class: 'border border-input-gray bg-base-gray-surface',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'outlined',\n inputColor: 'brand',\n class: 'border border-input',\n },\n {\n labelPosition: 'inset',\n inputStyle: 'outlined',\n inputColor: 'gray',\n class: 'border border-input-gray',\n },\n // ghost inset = bare label + underlined input; the input carries the line\n {\n labelPosition: 'inset',\n inputStyle: 'ghost',\n class: 'rounded-none px-0',\n },\n // shared inset states: filled shells swap bg, bordered shells swap border\n // invalid hover deepens the error tint instead of falling back to accent\n {\n labelPosition: 'inset',\n inputStyle: ['soft', 'surface'],\n class:\n 'data-[disabled=true]:bg-base-gray-soft data-[invalid=true]:bg-base-error-soft data-[invalid=true]:has-[:is(input,textarea,[data-slot=select-trigger]):not(:disabled)]:hover:bg-red-a4',\n },\n {\n labelPosition: 'inset',\n inputStyle: ['surface', 'outlined'],\n class:\n 'data-[disabled=true]:border-input-disabled data-[invalid=true]:border-input-invalid',\n },\n ],\n },\n)\n\ninterface FieldProps extends React.ComponentProps<'div'> {\n labelPosition?: SparkLabelPosition\n inputStyle?: SparkInputStyle\n inputColor?: SparkInputColor\n readOnly?: boolean\n 'data-invalid'?: boolean | 'true' | 'false'\n}\n\nfunction Field({\n className,\n children,\n labelPosition: labelPositionProp,\n inputStyle: inputStyleProp,\n inputColor: inputColorProp,\n readOnly = false,\n 'data-invalid': dataInvalid,\n ...props\n}: FieldProps) {\n const id = useId()\n const [descriptionCount, setDescriptionCount] = React.useState(0)\n const [errorCount, setErrorCount] = React.useState(0)\n // counts, not flags: one slot unmounting must not clear what siblings still need\n const setHasDescription = React.useCallback(\n (has: boolean) => setDescriptionCount((n) => n + (has ? 1 : -1)),\n [],\n )\n const setHasError = React.useCallback(\n (has: boolean) => setErrorCount((n) => n + (has ? 1 : -1)),\n [],\n )\n const hasDescription = descriptionCount > 0\n const hasError = errorCount > 0\n // knobs are structural (they move the label / pick the box carrier), so they\n // resolve here via the <Theme> context; props override per instance\n const theme = useTheme()\n const labelPosition = labelPositionProp ?? theme.labelPosition ?? 'inset'\n const inputStyle = inputStyleProp ?? theme.inputStyle ?? 'soft'\n const inputColor = inputColorProp ?? theme.inputColor ?? 'brand'\n const fieldId = `field-${id}`\n const labelId = `${fieldId}-label`\n const value = React.useMemo<FieldContextValue>(\n () => ({\n id: fieldId,\n labelId,\n descriptionId: `${fieldId}-description`,\n hasDescription,\n setHasDescription,\n errorId: `${fieldId}-error`,\n hasError,\n setHasError,\n readOnly,\n labelPosition,\n inputStyle,\n inputColor,\n }),\n [\n fieldId,\n labelId,\n hasDescription,\n setHasDescription,\n hasError,\n setHasError,\n readOnly,\n labelPosition,\n inputStyle,\n inputColor,\n ],\n )\n\n return (\n <FieldContext.Provider value={value}>\n <div\n role=\"group\"\n data-slot=\"field\"\n data-label-position={labelPosition}\n data-input-style={inputStyle}\n data-input-color={inputColor}\n data-invalid={dataInvalid ?? (hasError || undefined)}\n aria-labelledby={readOnly ? labelId : undefined}\n className={cn(\n fieldVariants({ labelPosition, inputStyle, inputColor }),\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </FieldContext.Provider>\n )\n}\n\nfunction FieldContent({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\n 'flex min-w-0 flex-1 flex-col gap-1 leading-snug',\n className,\n )}\n {...props}\n />\n )\n}\n\nconst fieldLabelClassName =\n 'text-sm leading-5 font-normal text-gray transition-all group-data-[invalid=true]/field:text-error-active! motion-reduce:transition-none'\n\nfunction FieldLabel({\n className,\n htmlFor,\n srOnly,\n children,\n ...props\n}: React.ComponentProps<'label'> & { srOnly?: boolean }) {\n const field = useFieldContext()\n const classNames = cn(\n // labels stay full-contrast even when disabled — the control itself\n // (dimmed text, gray shell) signals the state\n fieldLabelClassName,\n // visually hidden but kept in the a11y tree (still names + focuses the control)\n srOnly && 'sr-only',\n className,\n )\n\n if (field?.readOnly) {\n return (\n <div data-slot=\"field-label\" id={field.labelId} className={classNames}>\n {children}\n </div>\n )\n }\n\n return (\n <label\n data-slot=\"field-label\"\n className={classNames}\n htmlFor={htmlFor ?? field?.id}\n {...props}\n >\n {children}\n </label>\n )\n}\n\nfunction FieldValue({\n className,\n id,\n title,\n truncate,\n children,\n ...props\n}: React.ComponentProps<'div'> & { truncate?: boolean }) {\n return (\n <div\n data-slot=\"field-value\"\n id={id}\n // truncated string values keep the full text reachable on hover\n title={\n title ??\n (truncate && typeof children === 'string' ? children : undefined)\n }\n className={cn(\n // values are content, not controls — disabled dims but stays ≥4.5:1\n 'min-h-8 w-full text-base text-gray tabular-nums group-data-[disabled=true]/field:opacity-70',\n truncate\n ? 'block truncate leading-8'\n : 'inline-flex items-center wrap-anywhere whitespace-pre-wrap',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nfunction FieldSkeleton({\n className,\n labelClassName,\n valueClassName,\n truncate,\n ...props\n}: React.ComponentProps<'div'> & {\n truncate?: boolean\n labelClassName?: string\n valueClassName?: string\n}) {\n return (\n <div\n data-slot=\"field-skeleton\"\n aria-hidden=\"true\"\n className={cn('flex w-full flex-col gap-y-1', className)}\n {...props}\n >\n <Skeleton\n data-slot=\"field-skeleton-label\"\n className={cn('h-5 w-24', labelClassName)}\n />\n <Skeleton\n data-slot=\"field-skeleton-value\"\n className={cn(\n 'h-8 min-h-8 w-full',\n truncate && 'max-w-full truncate',\n valueClassName,\n )}\n />\n </div>\n )\n}\n\nfunction FieldTitle({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-title\"\n className={cn(\n 'flex w-fit items-center gap-2 text-sm font-medium text-gray',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction FieldDescription({\n className,\n id,\n ...props\n}: React.ComponentProps<'div'>) {\n const field = useFieldContext()\n const setHasDescription = field?.setHasDescription\n\n React.useEffect(() => {\n if (!setHasDescription) return\n setHasDescription(true)\n return () => setHasDescription(false)\n }, [setHasDescription])\n\n return (\n <div\n data-slot=\"field-description\"\n id={id ?? field?.descriptionId}\n className={cn('text-sm leading-normal text-gray-light', className)}\n {...props}\n />\n )\n}\n\nfunction FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn('relative -my-2 h-5 text-sm', className)}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"relative mx-auto block w-fit bg-(--spark-background) px-2 text-gray-light\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n )\n}\n\nfunction FieldError({\n className,\n children,\n errors,\n id,\n ...props\n}: React.ComponentProps<'div'> & {\n errors?: Array<{ message?: string } | undefined>\n}) {\n const field = useFieldContext()\n const setHasError = field?.setHasError\n const content = React.useMemo(() => {\n if (children) return children\n if (!errors?.length) return null\n const unique = [\n ...new Map(errors.map((error) => [error?.message, error])).values(),\n ]\n if (unique.length === 1) return unique[0]?.message\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {unique.map(\n (error) =>\n error?.message && <li key={error.message}>{error.message}</li>,\n )}\n </ul>\n )\n }, [children, errors])\n\n const hasContent = Boolean(content)\n // a custom id means no element carries field.errorId, so don't advertise it\n const hasCustomId = id != null\n\n // must run before the empty-content early return to keep hook order stable\n React.useEffect(() => {\n if (!setHasError || !hasContent || hasCustomId) return\n setHasError(true)\n return () => setHasError(false)\n }, [setHasError, hasContent, hasCustomId])\n\n if (!content) return null\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n id={id ?? field?.errorId}\n className={cn('text-sm font-normal text-error', className)}\n {...props}\n >\n {content}\n </div>\n )\n}\n\nexport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldSkeleton,\n FieldTitle,\n FieldValue,\n}\nexport type { FieldProps }\n"],"mappings":"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"}
|
package/dist/components/field.js
CHANGED
|
@@ -188,7 +188,7 @@ function Field({ className, children, labelPosition: labelPositionProp, inputSty
|
|
|
188
188
|
function FieldContent({ className, ...props }) {
|
|
189
189
|
return /* @__PURE__ */ jsx("div", {
|
|
190
190
|
"data-slot": "field-content",
|
|
191
|
-
className: cn("flex min-w-0 flex-1 flex-col gap-
|
|
191
|
+
className: cn("flex min-w-0 flex-1 flex-col gap-1 leading-snug", className),
|
|
192
192
|
...props
|
|
193
193
|
});
|
|
194
194
|
}
|
|
@@ -253,7 +253,7 @@ function FieldDescription({ className, id, ...props }) {
|
|
|
253
253
|
return /* @__PURE__ */ jsx("div", {
|
|
254
254
|
"data-slot": "field-description",
|
|
255
255
|
id: id ?? field?.descriptionId,
|
|
256
|
-
className: cn("
|
|
256
|
+
className: cn("text-sm leading-normal text-gray-light", className),
|
|
257
257
|
...props
|
|
258
258
|
});
|
|
259
259
|
}
|
|
@@ -299,7 +299,7 @@ function FieldError({ className, children, errors, id, ...props }) {
|
|
|
299
299
|
role: "alert",
|
|
300
300
|
"data-slot": "field-error",
|
|
301
301
|
id: id ?? field?.errorId,
|
|
302
|
-
className: cn("
|
|
302
|
+
className: cn("text-sm font-normal text-error", className),
|
|
303
303
|
...props,
|
|
304
304
|
children: content
|
|
305
305
|
});
|