@mmmmzxe/react-360-viewer 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,20 +30,22 @@ bun add @mmmmzxe/react-360-viewer
30
30
  | `react` | `>=18` |
31
31
  | `react-dom` | `>=18` |
32
32
  | `lucide-react` | `>=0.400.0` |
33
-
34
- ### Styles — zero setup
35
-
36
- **No `@source`. No CSS import.** Just use the component:
37
-
38
33
  ```tsx
39
34
  import { Viewer360 } from '@mmmmzxe/react-360-viewer';
40
35
  ```
41
36
 
42
- Styles load automatically when the package is imported (v0.1.9+). All CSS is **scoped to the viewer** — it will not override your app's global theme. Requires a **client component** in Next.js App Router (`'use client'`).
37
+ Styles load automatically when the package is imported (v0.1.10+). All CSS is **scoped to the viewer** — it will not override your app's global theme. Requires a **client component** in Next.js App Router (`'use client'`).
38
+
39
+ **Do not add `@source` if you use auto-inject.** Pick one:
40
+
41
+ | Method | Setup | Notes |
42
+ |--------|-------|-------|
43
+ | **Auto-inject (default)** | Just `import { Viewer360 }` | Scoped to viewer, safe for dashboard |
44
+ | **`@source` in your CSS** | Scan package `src/` | Merges into your Tailwind build; can miss `--radius-4xl` and break rounded corners |
43
45
 
44
46
  If styles don't appear after updating, delete `.next` and restart the dev server.
45
47
 
46
- > **Note:** v0.1.8–0.1.9 could leak global CSS into your dashboard. Use **v0.1.10+** which wraps all styles in `@scope ([data-viewer-360])` so only the viewer is affected.
48
+ > **Note:** v0.1.8–0.1.9 could leak global CSS into your dashboard. Use **v0.1.12+**.
47
49
 
48
50
  ---
49
51
 
package/dist/index.js CHANGED
@@ -39,8 +39,8 @@ var viewer360ClassNames = {
39
39
  };
40
40
  var viewer360MarkerPinClassNames = {
41
41
  root: "pointer-events-auto absolute z-30 -translate-x-1/2 -translate-y-1/2",
42
- ping: "absolute inline-flex size-6 -translate-x-1/4 -translate-y-1/4 animate-ping rounded-full bg-destructive opacity-60",
43
- dot: "relative flex size-4 items-center justify-center rounded-full border-2 border-background bg-destructive shadow-md transition-transform duration-200 hover:scale-125 focus:outline-none",
42
+ ping: "pointer-events-none absolute inset-0 inline-flex animate-ping rounded-full bg-destructive opacity-75",
43
+ dot: "relative z-10 inline-flex size-4 min-h-4 min-w-4 shrink-0 rounded-full border-2 border-background bg-destructive p-0 shadow-md transition-transform duration-200 hover:scale-125 focus:outline-none",
44
44
  tooltip: "absolute bottom-6 left-1/2 z-40 w-64 -translate-x-1/2 rounded-lg border bg-popover p-3 text-popover-foreground shadow-md",
45
45
  tooltipHeader: "flex items-start justify-between gap-2",
46
46
  tooltipBody: "flex min-w-0 flex-col gap-1",
@@ -510,7 +510,7 @@ import { cva } from "class-variance-authority";
510
510
  import { Slot } from "radix-ui";
511
511
  import { jsx as jsx2 } from "react/jsx-runtime";
512
512
  var badgeVariants = cva(
513
- "h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge",
513
+ "h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge",
514
514
  {
515
515
  variants: {
516
516
  variant: {
@@ -521,7 +521,7 @@ var badgeVariants = cva(
521
521
  ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
522
522
  link: "text-primary underline-offset-4 hover:underline",
523
523
  info: "bg-blue-500 text-white hover:bg-blue-600",
524
- warning: "bg-amber-500 text-white hover:bg-amber-600",
524
+ warning: "rounded-full border-transparent bg-amber-500 px-2.5 text-white shadow-none [a]:hover:bg-amber-600 [&>svg]:text-white",
525
525
  success: "bg-green-600 text-white hover:bg-green-700"
526
526
  }
527
527
  },
@@ -713,7 +713,7 @@ import { cva as cva3 } from "class-variance-authority";
713
713
  import { Slot as Slot3 } from "radix-ui";
714
714
  import { jsx as jsx7 } from "react/jsx-runtime";
715
715
  var buttonVariants = cva3(
716
- "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
716
+ "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
717
717
  {
718
718
  variants: {
719
719
  variant: {
@@ -726,12 +726,12 @@ var buttonVariants = cva3(
726
726
  },
727
727
  size: {
728
728
  default: "h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2",
729
- xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5",
730
- sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5",
729
+ xs: "h-6 gap-1 rounded-md px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5",
730
+ sm: "h-8 gap-1 rounded-md px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5",
731
731
  lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pe-3 has-data-[icon=inline-start]:ps-3",
732
732
  icon: "size-9",
733
- "icon-xs": "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md",
734
- "icon-sm": "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
733
+ "icon-xs": "size-6 rounded-md in-data-[slot=button-group]:rounded-md",
734
+ "icon-sm": "size-8 rounded-md in-data-[slot=button-group]:rounded-md",
735
735
  "icon-lg": "size-10"
736
736
  }
737
737
  },
@@ -778,40 +778,25 @@ function Viewer360MarkerPin({
778
778
  const deleteLabel = labels?.delete ?? defaultViewer360MarkerPinLabels.delete;
779
779
  const showTooltip = Boolean(marker.title || marker.description || onDelete || renderTag);
780
780
  return /* @__PURE__ */ jsxs(
781
- Item,
781
+ "div",
782
782
  {
783
- size: "xs",
784
- variant: "default",
785
- className: cn(
786
- viewer360MarkerPinClassNames.root,
787
- classNames?.root,
788
- "group/marker w-auto border-transparent p-0"
789
- ),
783
+ className: cn(viewer360MarkerPinClassNames.root, classNames?.root, "group/marker"),
790
784
  style: { left: `${leftPercent}%`, top: `${topPercent}%` },
791
785
  children: [
792
- /* @__PURE__ */ jsx8(
793
- Badge,
794
- {
795
- variant: "destructive",
796
- className: cn(viewer360MarkerPinClassNames.ping, classNames?.ping, "absolute size-6 border-0 bg-destructive opacity-60"),
797
- "aria-hidden": "true"
798
- }
799
- ),
800
- /* @__PURE__ */ jsx8(
801
- Button,
802
- {
803
- type: "button",
804
- variant: "destructive",
805
- size: "icon-xs",
806
- className: cn(
807
- viewer360MarkerPinClassNames.dot,
808
- classNames?.dot,
809
- "size-4 min-h-4 min-w-4 rounded-full border-2 border-background bg-destructive p-0 shadow-md hover:scale-125 hover:bg-destructive"
810
- ),
811
- "aria-label": marker.title,
812
- onClick
813
- }
814
- ),
786
+ /* @__PURE__ */ jsxs("div", { className: "relative size-4 shrink-0", children: [
787
+ /* @__PURE__ */ jsx8("span", { className: cn(viewer360MarkerPinClassNames.ping, classNames?.ping), "aria-hidden": "true" }),
788
+ /* @__PURE__ */ jsx8(
789
+ Button,
790
+ {
791
+ type: "button",
792
+ variant: "destructive",
793
+ size: "icon-xs",
794
+ className: cn(viewer360MarkerPinClassNames.dot, classNames?.dot, "hover:bg-destructive"),
795
+ "aria-label": marker.title,
796
+ onClick
797
+ }
798
+ )
799
+ ] }),
815
800
  showTooltip && /* @__PURE__ */ jsx8(
816
801
  "div",
817
802
  {
@@ -829,7 +814,7 @@ function Viewer360MarkerPin({
829
814
  children: [
830
815
  /* @__PURE__ */ jsxs(ItemContent, { className: cn(viewer360MarkerPinClassNames.tooltipBody, classNames?.tooltipBody), children: [
831
816
  /* @__PURE__ */ jsx8(ItemTitle, { className: cn(viewer360MarkerPinClassNames.tooltipTitle, classNames?.tooltipTitle), children: marker.title }),
832
- renderTag?.({ marker, hotspot }),
817
+ renderTag && /* @__PURE__ */ jsx8("div", { className: "mt-1 flex w-fit items-center", children: renderTag({ marker, hotspot }) }),
833
818
  marker.description && /* @__PURE__ */ jsx8(ItemDescription, { className: cn(viewer360MarkerPinClassNames.tooltipDescription, classNames?.tooltipDescription), children: marker.description })
834
819
  ] }),
835
820
  onDelete && /* @__PURE__ */ jsx8(ItemActions, { children: /* @__PURE__ */ jsx8(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/feature/Viewer360.tsx","../src/constants/viewer360Labels.ts","../src/constants/viewer360ClassNames.ts","../src/components/utils/index.ts","../src/helpers/viewer360PropsHelpers.ts","../src/hooks/useViewer360.ts","../src/helpers/adjustViewerZoom.ts","../src/helpers/computeDragFrameIndex.ts","../src/helpers/computeViewerImageLayout.ts","../src/helpers/computeViewerPanOffset.ts","../src/helpers/viewerHelpers.ts","../src/components/ui/Card/index.tsx","../src/components/ui/Badge/index.tsx","../src/feature/Viewer360AddModeBanner.tsx","../src/feature/Viewer360FrameIndicator.tsx","../src/helpers/markerHelpers.ts","../src/components/ui/Item/index.tsx","../src/components/ui/Separator/index.tsx","../src/feature/Viewer360MarkerPin.tsx","../src/constants/viewer360MarkerLabels.ts","../src/components/ui/Button/index.tsx","../src/feature/Viewer360HotspotOverlay.tsx","../src/components/ui/Label/index.tsx","../src/components/ui/Spinner/index.tsx","../src/feature/Viewer360LoadingOverlay.tsx","../src/feature/Viewer360Toolbar.tsx","../src/constants/viewer360Config.ts"],"sourcesContent":["import type { JSX } from 'react';\nimport { useEffect, useMemo, useState } from 'react';\n\nimport { buildViewer360ThemeStyle, mergeViewer360ClassNames, mergeViewer360Labels } from '../helpers/viewer360PropsHelpers';\nimport { useViewer360 } from '../hooks/useViewer360';\nimport type { Viewer360OverlayRenderProps, Viewer360Props, Viewer360ToolbarRenderProps } from '../types';\nimport { Card } from '@/components/ui/Card';\nimport { cn } from '@/components/utils';\n\nimport { Viewer360AddModeBanner } from './Viewer360AddModeBanner';\nimport { Viewer360FrameIndicator } from './Viewer360FrameIndicator';\nimport { Viewer360HotspotOverlay } from './Viewer360HotspotOverlay';\nimport { Viewer360LoadingOverlay } from './Viewer360LoadingOverlay';\nimport { Viewer360Toolbar } from './Viewer360Toolbar';\n\nexport function Viewer360<TData = unknown>({\n frames,\n currentFrameIndex: controlledFrameIndex,\n defaultFrameIndex = 0,\n onFrameChange,\n config,\n className,\n classNames,\n style,\n theme,\n labels,\n aspectRatio = '16 / 10',\n showZoomControls = true,\n showResetControl = true,\n showFrameIndicator = true,\n showDragHint = true,\n showHotspotModeControl = false,\n hotspotPin,\n hotspots = [],\n renderHotspot,\n renderLoading,\n renderFrameIndicator,\n renderHotspotModeBanner,\n renderToolbar,\n onHotspotClick,\n hotspotMode: controlledHotspotMode,\n defaultHotspotMode = false,\n onHotspotModeChange,\n onHotspotAdd,\n children,\n}: Viewer360Props<TData>): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: States & Constants\n // ----------------------------------------------------------------------------------------------------\n const mergedLabels = useMemo(() => mergeViewer360Labels(labels), [labels]);\n const mergedClassNames = useMemo(() => mergeViewer360ClassNames(classNames), [classNames]);\n const themeStyle = useMemo(() => buildViewer360ThemeStyle(theme), [theme]);\n\n const [internalFrameIndex, setInternalFrameIndex] = useState(defaultFrameIndex);\n const [internalHotspotMode, setInternalHotspotMode] = useState(defaultHotspotMode);\n\n const currentFrameIndex = controlledFrameIndex ?? internalFrameIndex;\n const hotspotMode = controlledHotspotMode ?? internalHotspotMode;\n\n // ----------------------------------------------------------------------------------------------------\n // MARK: Functions\n // ----------------------------------------------------------------------------------------------------\n function handleFrameChange(index: number): void {\n if (controlledFrameIndex === undefined) {\n setInternalFrameIndex(index);\n }\n\n onFrameChange?.(index);\n }\n\n function handleHotspotModeChange(active: boolean): void {\n if (controlledHotspotMode === undefined) {\n setInternalHotspotMode(active);\n }\n\n onHotspotModeChange?.(active);\n }\n\n const {\n canvasRef,\n containerRef,\n currentFrame,\n currentFrameHotspots,\n imagesLoaded,\n isHotspotMode,\n isResetDisabled,\n maxZoom,\n minZoom,\n viewerCursorClass,\n zoom,\n getHotspotScreenPosition,\n handleCanvasClick,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handleWheel,\n handleResetView,\n handleZoomIn,\n handleZoomOut,\n } = useViewer360<TData>({\n frames,\n hotspots,\n currentFrameIndex,\n onFrameChange: handleFrameChange,\n config,\n hotspotMode,\n onHotspotAdd,\n });\n\n useEffect(() => {\n if (controlledHotspotMode === undefined) return;\n if (controlledHotspotMode !== internalHotspotMode) {\n setInternalHotspotMode(controlledHotspotMode);\n }\n }, [controlledHotspotMode, internalHotspotMode]);\n\n const frameLabel = currentFrame?.label ?? frames[currentFrameIndex]?.label;\n const overlayProps: Viewer360OverlayRenderProps = {\n currentFrameIndex,\n frameCount: frames.length,\n frameLabel,\n isHotspotMode,\n labels: mergedLabels,\n frameIndicatorClassName: mergedClassNames.frameIndicator,\n };\n const toolbarProps: Viewer360ToolbarRenderProps = {\n zoom,\n minZoom,\n maxZoom,\n isResetDisabled,\n isHotspotMode,\n showHotspotModeControl,\n showZoomControls,\n showResetControl,\n showDragHint,\n labels: mergedLabels,\n onZoomIn: handleZoomIn,\n onZoomOut: handleZoomOut,\n onResetView: handleResetView,\n onHotspotModeChange: handleHotspotModeChange,\n };\n const showDefaultToolbar = showZoomControls || showResetControl || showHotspotModeControl || showDragHint;\n\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Card\n data-viewer-360=\"\"\n className={cn(mergedClassNames.root, 'gap-0 py-0 shadow-none ring-0', className)}\n style={{ ...themeStyle, ...style }}\n >\n <div\n ref={containerRef}\n className={cn(mergedClassNames.viewport, viewerCursorClass)}\n style={{ aspectRatio }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerLeave={handlePointerUp}\n onWheel={handleWheel}\n onClick={handleCanvasClick}\n >\n <canvas ref={canvasRef} className={mergedClassNames.canvas} />\n\n <div className={mergedClassNames.overlay}>\n {currentFrameHotspots.map((hotspot) => {\n const position = getHotspotScreenPosition(hotspot);\n\n return (\n <Viewer360HotspotOverlay\n key={hotspot.id}\n hotspot={hotspot}\n leftPercent={position.leftPercent}\n topPercent={position.topPercent}\n hotspotPin={hotspotPin}\n renderHotspot={renderHotspot}\n onHotspotClick={onHotspotClick}\n />\n );\n })}\n {children}\n </div>\n\n {!imagesLoaded &&\n (renderLoading ? (\n renderLoading()\n ) : (\n <Viewer360LoadingOverlay\n className={mergedClassNames.loading}\n textClassName={mergedClassNames.loadingText}\n label={mergedLabels.loading}\n />\n ))}\n\n {showFrameIndicator &&\n frames.length > 0 &&\n (renderFrameIndicator ? (\n renderFrameIndicator(overlayProps)\n ) : (\n <Viewer360FrameIndicator\n className={mergedClassNames.frameIndicator}\n label={mergedLabels.frameIndicator({\n current: currentFrameIndex + 1,\n total: frames.length,\n label: frameLabel,\n })}\n />\n ))}\n\n {isHotspotMode &&\n onHotspotAdd &&\n (renderHotspotModeBanner ? (\n renderHotspotModeBanner({ labels: mergedLabels })\n ) : (\n <Viewer360AddModeBanner className={mergedClassNames.hotspotModeBanner} label={mergedLabels.hotspotModeActive} />\n ))}\n </div>\n\n {renderToolbar ? renderToolbar(toolbarProps) : showDefaultToolbar ? <Viewer360Toolbar {...toolbarProps} /> : null}\n </Card>\n );\n}\n","import type { Viewer360Labels } from '../types/Viewer360Props';\n\nexport const defaultViewer360Labels: Required<Viewer360Labels> = {\n loading: 'Loading images…',\n dragHint: 'Drag to rotate • Scroll to zoom',\n frameIndicator: ({ current, total, label }) => (label ? `${label} · ${current} / ${total}` : `${current} / ${total}`),\n zoom: (percent) => `${percent}%`,\n hotspotModeActive: 'Click on the image to place a hotspot',\n addHotspot: 'Add hotspot',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n resetView: 'Reset view',\n deleteMarker: 'Remove marker',\n};\n","import type { Viewer360ClassNames } from '../types/Viewer360Props';\nimport type { Viewer360MarkerPinClassNames } from '../types/Viewer360Marker';\n\nexport const viewer360ClassNames: Required<Viewer360ClassNames> = {\n root: 'overflow-hidden rounded-lg border bg-card text-card-foreground',\n viewport: 'relative aspect-[16/10] w-full touch-none select-none bg-muted',\n canvas: 'absolute inset-0 size-full',\n overlay: 'pointer-events-none absolute inset-0 overflow-hidden',\n loading: 'absolute inset-0 flex items-center justify-center bg-muted/80',\n loadingText: 'text-sm text-muted-foreground',\n frameIndicator:\n 'pointer-events-none absolute bottom-4 start-1/2 z-20 -translate-x-1/2 rounded-full border bg-background px-4 py-1.5 text-xs font-medium shadow-sm whitespace-nowrap',\n hotspotModeBanner:\n 'pointer-events-none absolute top-4 start-1/2 z-20 -translate-x-1/2 rounded-full border border-amber-200 bg-amber-50 px-4 py-1.5 text-xs font-medium text-amber-800 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-400',\n toolbar: 'flex flex-wrap items-center justify-between gap-2 border-t px-4 py-3',\n dragHint: 'hidden text-xs text-muted-foreground sm:block',\n controls: 'ms-auto flex items-center gap-1.5',\n controlButton: '',\n controlButtonActive: '',\n controlButtonDisabled: '',\n zoomDisplay: 'flex min-w-[3rem] items-center justify-center gap-1 rounded-md border bg-background px-2 py-1 text-xs font-medium',\n divider: 'mx-1 h-6 w-px bg-border',\n};\n\nexport const viewer360MarkerPinClassNames: Required<Viewer360MarkerPinClassNames> = {\n root: 'pointer-events-auto absolute z-30 -translate-x-1/2 -translate-y-1/2',\n ping: 'absolute inline-flex size-6 -translate-x-1/4 -translate-y-1/4 animate-ping rounded-full bg-destructive opacity-60',\n dot: 'relative flex size-4 items-center justify-center rounded-full border-2 border-background bg-destructive shadow-md transition-transform duration-200 hover:scale-125 focus:outline-none',\n tooltip:\n 'absolute bottom-6 left-1/2 z-40 w-64 -translate-x-1/2 rounded-lg border bg-popover p-3 text-popover-foreground shadow-md',\n tooltipHeader: 'flex items-start justify-between gap-2',\n tooltipBody: 'flex min-w-0 flex-col gap-1',\n tooltipTitle: 'text-sm font-medium',\n tooltipDescription: 'mt-2 line-clamp-3 text-xs text-muted-foreground',\n deleteButton: '',\n};\n\n/** @deprecated Use `viewer360ClassNames` */\nexport const defaultViewer360ClassNames = viewer360ClassNames;\n\n/** @deprecated Use `viewer360MarkerPinClassNames` */\nexport const defaultViewer360MarkerPinClassNames = viewer360MarkerPinClassNames;\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { CSSProperties } from 'react';\n\nimport { defaultViewer360Labels } from '../constants/viewer360Labels';\nimport { viewer360ClassNames } from '../constants/viewer360ClassNames';\nimport type { Viewer360ClassNames, Viewer360Labels, Viewer360Theme } from '../types';\nimport { cn } from '@/components/utils';\n\nexport function mergeViewer360Labels(labels?: Viewer360Labels): Required<Viewer360Labels> {\n return {\n loading: labels?.loading ?? defaultViewer360Labels.loading,\n dragHint: labels?.dragHint ?? defaultViewer360Labels.dragHint,\n frameIndicator: labels?.frameIndicator ?? defaultViewer360Labels.frameIndicator,\n zoom: labels?.zoom ?? defaultViewer360Labels.zoom,\n hotspotModeActive: labels?.hotspotModeActive ?? defaultViewer360Labels.hotspotModeActive,\n addHotspot: labels?.addHotspot ?? defaultViewer360Labels.addHotspot,\n zoomIn: labels?.zoomIn ?? defaultViewer360Labels.zoomIn,\n zoomOut: labels?.zoomOut ?? defaultViewer360Labels.zoomOut,\n resetView: labels?.resetView ?? defaultViewer360Labels.resetView,\n deleteMarker: labels?.deleteMarker ?? defaultViewer360Labels.deleteMarker,\n };\n}\n\nexport function mergeViewer360ClassNames(classNames?: Viewer360ClassNames): Required<Viewer360ClassNames> {\n return {\n root: cn(viewer360ClassNames.root, classNames?.root),\n viewport: cn(viewer360ClassNames.viewport, classNames?.viewport),\n canvas: cn(viewer360ClassNames.canvas, classNames?.canvas),\n overlay: cn(viewer360ClassNames.overlay, classNames?.overlay),\n loading: cn(viewer360ClassNames.loading, classNames?.loading),\n loadingText: cn(viewer360ClassNames.loadingText, classNames?.loadingText),\n frameIndicator: cn(viewer360ClassNames.frameIndicator, classNames?.frameIndicator),\n hotspotModeBanner: cn(viewer360ClassNames.hotspotModeBanner, classNames?.hotspotModeBanner),\n toolbar: cn(viewer360ClassNames.toolbar, classNames?.toolbar),\n dragHint: cn(viewer360ClassNames.dragHint, classNames?.dragHint),\n controls: cn(viewer360ClassNames.controls, classNames?.controls),\n controlButton: cn(viewer360ClassNames.controlButton, classNames?.controlButton),\n controlButtonActive: cn(viewer360ClassNames.controlButtonActive, classNames?.controlButtonActive),\n controlButtonDisabled: cn(viewer360ClassNames.controlButtonDisabled, classNames?.controlButtonDisabled),\n zoomDisplay: cn(viewer360ClassNames.zoomDisplay, classNames?.zoomDisplay),\n divider: cn(viewer360ClassNames.divider, classNames?.divider),\n };\n}\n\nexport function buildViewer360ThemeStyle(theme?: Viewer360Theme): CSSProperties {\n return theme ? (theme as CSSProperties) : {};\n}\n","import type { PointerEvent as ReactPointerEvent, RefObject, WheelEvent as ReactWheelEvent } from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\nimport {\n applyWheelZoom,\n getViewerCursorClass,\n isResetDisabled,\n resolveViewer360Config,\n stepZoomIn,\n stepZoomOut,\n} from '../helpers/adjustViewerZoom';\nimport { computeDragFrameIndex } from '../helpers/computeDragFrameIndex';\nimport {\n computeHotspotPositionFromClick,\n computeHotspotScreenPosition,\n computeViewerImageLayout,\n type ViewerImageLayout,\n} from '../helpers/computeViewerImageLayout';\nimport { computeViewerPanOffset } from '../helpers/computeViewerPanOffset';\nimport {\n drawFrameOnCanvas,\n filterHotspotsByFrame,\n getFramesSignature,\n hasLoadedViewerFrame,\n preloadViewerFrames,\n} from '../helpers/viewerHelpers';\nimport type {\n Viewer360Config,\n Viewer360Frame,\n Viewer360Hotspot,\n Viewer360HotspotPosition,\n Viewer360PanOffset,\n} from '../types';\n\ntype UseViewer360Params<TData> = {\n frames: Viewer360Frame[];\n currentFrameIndex: number;\n onFrameChange: (index: number) => void;\n hotspots?: Viewer360Hotspot<TData>[];\n config?: Viewer360Config;\n hotspotMode?: boolean;\n onHotspotAdd?: (position: Viewer360HotspotPosition) => void;\n};\n\ntype UseViewer360Return<TData> = {\n canvasRef: RefObject<HTMLCanvasElement | null>;\n containerRef: RefObject<HTMLDivElement | null>;\n currentFrame: Viewer360Frame | undefined;\n currentFrameHotspots: Viewer360Hotspot<TData>[];\n imagesLoaded: boolean;\n isHotspotMode: boolean;\n isResetDisabled: boolean;\n maxZoom: number;\n minZoom: number;\n viewerCursorClass: string;\n zoom: number;\n getCurrentImageLayout: () => ViewerImageLayout | null;\n getHotspotScreenPosition: (hotspot: Viewer360Hotspot<TData>) => { leftPercent: number; topPercent: number };\n handleCanvasClick: (event: React.MouseEvent<HTMLDivElement>) => void;\n handlePointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void;\n handlePointerMove: (event: ReactPointerEvent<HTMLDivElement>) => void;\n handlePointerUp: (event: ReactPointerEvent<HTMLDivElement>) => void;\n handleResetView: () => void;\n handleWheel: (event: ReactWheelEvent<HTMLDivElement>) => void;\n handleZoomIn: () => void;\n handleZoomOut: () => void;\n};\n\nexport function useViewer360<TData = unknown>({\n frames,\n hotspots = [],\n currentFrameIndex,\n onFrameChange,\n config,\n hotspotMode: hotspotModeProp = false,\n onHotspotAdd,\n}: UseViewer360Params<TData>): UseViewer360Return<TData> {\n const resolvedConfig = useMemo(() => resolveViewer360Config(config), [config]);\n const { minZoom, maxZoom } = resolvedConfig;\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const imagesRef = useRef<HTMLImageElement[]>([]);\n const dragStartRef = useRef<{ pointerX: number; frameIndex: number } | null>(null);\n const panStartRef = useRef<{ pointerX: number; pointerY: number; panX: number; panY: number } | null>(null);\n\n const framesSignature = getFramesSignature(frames);\n const [loadedSignature, setLoadedSignature] = useState<string | null>(null);\n const [zoom, setZoom] = useState<number>(minZoom);\n const [pan, setPan] = useState<Viewer360PanOffset>({ panX: 0, panY: 0 });\n const [isDragging, setIsDragging] = useState(false);\n\n const isHotspotMode = hotspotModeProp;\n const imagesLoaded = loadedSignature === framesSignature;\n const currentFrameHotspots = filterHotspotsByFrame(hotspots, currentFrameIndex) as Viewer360Hotspot<TData>[];\n const currentFrame = frames[currentFrameIndex];\n const viewerCursorClass = getViewerCursorClass(isHotspotMode, zoom, isDragging, minZoom);\n const resetDisabled = isResetDisabled(zoom, pan, resolvedConfig);\n\n useEffect(() => {\n let cancelled = false;\n imagesRef.current = [];\n\n async function loadFrames(): Promise<void> {\n const loadedImages = await preloadViewerFrames(frames);\n\n if (!cancelled && hasLoadedViewerFrame(loadedImages)) {\n imagesRef.current = loadedImages;\n setLoadedSignature(framesSignature);\n }\n }\n\n void loadFrames();\n\n return (): void => {\n cancelled = true;\n };\n }, [frames, framesSignature]);\n\n useEffect(() => {\n if (!imagesLoaded) return;\n\n function renderFrame(): void {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n const img = imagesRef.current[currentFrameIndex];\n\n if (!canvas || !container) return;\n\n drawFrameOnCanvas({ canvas, container, image: img, zoom, pan });\n }\n\n renderFrame();\n window.addEventListener('resize', renderFrame);\n\n return (): void => window.removeEventListener('resize', renderFrame);\n }, [imagesLoaded, currentFrameIndex, zoom, pan]);\n\n useEffect(() => {\n if (!resolvedConfig.autoRotate || frames.length <= 1 || isDragging || isHotspotMode || zoom > minZoom) {\n return;\n }\n\n const direction = resolvedConfig.autoRotateDirection === 'backward' ? -1 : 1;\n const interval = window.setInterval(() => {\n onFrameChange((currentFrameIndex + direction + frames.length) % frames.length);\n }, resolvedConfig.autoRotateIntervalMs);\n\n return (): void => window.clearInterval(interval);\n }, [\n resolvedConfig.autoRotate,\n resolvedConfig.autoRotateDirection,\n resolvedConfig.autoRotateIntervalMs,\n frames.length,\n currentFrameIndex,\n isDragging,\n isHotspotMode,\n zoom,\n minZoom,\n onFrameChange,\n ]);\n\n function getCurrentImageLayout(): ViewerImageLayout | null {\n const container = containerRef.current;\n const image = imagesRef.current[currentFrameIndex];\n\n if (!container || !image || !image.complete || !image.naturalWidth) return null;\n\n const rect = container.getBoundingClientRect();\n\n return computeViewerImageLayout({\n containerWidth: rect.width,\n containerHeight: rect.height,\n imageWidth: image.naturalWidth,\n imageHeight: image.naturalHeight,\n pan,\n });\n }\n\n function getHotspotScreenPosition(hotspot: Viewer360Hotspot<TData>): { leftPercent: number; topPercent: number } {\n const layout = getCurrentImageLayout();\n\n if (!layout) {\n return { leftPercent: hotspot.positionX, topPercent: hotspot.positionY };\n }\n\n return computeHotspotScreenPosition(hotspot.positionX, hotspot.positionY, layout, zoom);\n }\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>): void {\n if (isHotspotMode) return;\n\n event.currentTarget.setPointerCapture(event.pointerId);\n\n if (zoom > minZoom) {\n panStartRef.current = { pointerX: event.clientX, pointerY: event.clientY, panX: pan.panX, panY: pan.panY };\n } else {\n dragStartRef.current = { pointerX: event.clientX, frameIndex: currentFrameIndex };\n }\n\n setIsDragging(true);\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>): void {\n if (!isDragging) return;\n\n if (panStartRef.current && zoom > minZoom) {\n setPan(computeViewerPanOffset(panStartRef.current, event.clientX, event.clientY));\n return;\n }\n\n if (dragStartRef.current && zoom <= minZoom) {\n const nextFrameIndex = computeDragFrameIndex(\n dragStartRef.current,\n event.clientX,\n frames.length,\n resolvedConfig.dragSensitivity\n );\n\n if (nextFrameIndex !== null) {\n onFrameChange(nextFrameIndex);\n }\n }\n }\n\n function handlePointerUp(event: ReactPointerEvent<HTMLDivElement>): void {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n\n dragStartRef.current = null;\n panStartRef.current = null;\n setIsDragging(false);\n }\n\n function handleWheel(event: ReactWheelEvent<HTMLDivElement>): void {\n event.preventDefault();\n const { zoom: nextZoom, pan: nextPan } = applyWheelZoom(zoom, event.deltaY, pan, resolvedConfig);\n setZoom(nextZoom);\n setPan(nextPan);\n }\n\n function handleCanvasClick(event: React.MouseEvent<HTMLDivElement>): void {\n if (!isHotspotMode || isDragging || !onHotspotAdd) return;\n\n const frame = frames[currentFrameIndex];\n if (!frame) return;\n\n const layout = getCurrentImageLayout();\n if (!layout) return;\n\n const { positionX, positionY } = computeHotspotPositionFromClick(\n event.clientX,\n event.clientY,\n event.currentTarget.getBoundingClientRect(),\n layout,\n zoom\n );\n\n onHotspotAdd({\n frameIndex: currentFrameIndex,\n frameId: frame.id,\n positionX,\n positionY,\n });\n }\n\n function handleResetView(): void {\n setZoom(minZoom);\n setPan({ panX: 0, panY: 0 });\n }\n\n function handleZoomIn(): void {\n setZoom(stepZoomIn(zoom, resolvedConfig));\n }\n\n function handleZoomOut(): void {\n const { zoom: nextZoom, pan: nextPan } = stepZoomOut(zoom, pan, resolvedConfig);\n setZoom(nextZoom);\n setPan(nextPan);\n }\n\n return {\n canvasRef,\n containerRef,\n currentFrame,\n currentFrameHotspots,\n imagesLoaded,\n isHotspotMode,\n isResetDisabled: resetDisabled,\n maxZoom,\n minZoom,\n viewerCursorClass,\n zoom,\n getCurrentImageLayout,\n getHotspotScreenPosition,\n handleCanvasClick,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handleResetView,\n handleWheel,\n handleZoomIn,\n handleZoomOut,\n };\n}\n","import type { Viewer360Config } from '../types';\n\nimport type { PanOffset } from './computeViewerImageLayout';\n\ntype ResolvedViewer360Config = Required<Viewer360Config>;\n\nexport function resolveViewer360Config(config?: Viewer360Config): ResolvedViewer360Config {\n return {\n minZoom: config?.minZoom ?? 1,\n maxZoom: config?.maxZoom ?? 3,\n zoomStep: config?.zoomStep ?? 0.15,\n dragSensitivity: config?.dragSensitivity ?? 8,\n autoRotate: config?.autoRotate ?? false,\n autoRotateIntervalMs: config?.autoRotateIntervalMs ?? 100,\n autoRotateDirection: config?.autoRotateDirection ?? 'forward',\n };\n}\n\nexport function clampZoom(zoom: number, config: ResolvedViewer360Config): number {\n return Math.min(config.maxZoom, Math.max(config.minZoom, zoom));\n}\n\nexport function applyWheelZoom(\n currentZoom: number,\n deltaY: number,\n currentPan: PanOffset,\n config: ResolvedViewer360Config\n): { zoom: number; pan: PanOffset } {\n const delta = deltaY > 0 ? -config.zoomStep : config.zoomStep;\n const zoom = clampZoom(currentZoom + delta, config);\n\n return {\n zoom,\n pan: zoom === config.minZoom ? { panX: 0, panY: 0 } : currentPan,\n };\n}\n\nexport function stepZoomIn(currentZoom: number, config: ResolvedViewer360Config): number {\n return clampZoom(currentZoom + config.zoomStep, config);\n}\n\nexport function stepZoomOut(\n currentZoom: number,\n currentPan: PanOffset,\n config: ResolvedViewer360Config\n): { zoom: number; pan: PanOffset } {\n const zoom = clampZoom(currentZoom - config.zoomStep, config);\n\n return {\n zoom,\n pan: zoom === config.minZoom ? { panX: 0, panY: 0 } : currentPan,\n };\n}\n\nexport function isResetDisabled(zoom: number, pan: PanOffset, config: ResolvedViewer360Config): boolean {\n return zoom === config.minZoom && pan.panX === 0 && pan.panY === 0;\n}\n\nexport function getViewerCursorClass(isHotspotMode: boolean, zoom: number, isDragging: boolean, minZoom: number): string {\n if (isHotspotMode) return 'cursor-crosshair';\n if (isDragging) return 'cursor-grabbing';\n if (zoom > minZoom) return 'cursor-grab';\n return 'cursor-ew-resize';\n}\n","export function clampFrameIndex(index: number, frameCount: number): number {\n if (frameCount === 0) return 0;\n return ((index % frameCount) + frameCount) % frameCount;\n}\n\ntype DragStart = {\n pointerX: number;\n frameIndex: number;\n};\n\nexport function computeDragFrameIndex(\n dragStart: DragStart,\n clientX: number,\n frameCount: number,\n dragSensitivity: number\n): number | null {\n const deltaX = clientX - dragStart.pointerX;\n const frameDelta = Math.round(-deltaX / dragSensitivity);\n\n if (frameDelta === 0) return null;\n\n return clampFrameIndex(dragStart.frameIndex + frameDelta, frameCount);\n}\n","export type ViewerImageLayout = {\n width: number;\n height: number;\n centerX: number;\n centerY: number;\n drawWidth: number;\n drawHeight: number;\n offsetX: number;\n offsetY: number;\n};\n\nexport type PanOffset = {\n panX: number;\n panY: number;\n};\n\ntype ComputeViewerImageLayoutParams = {\n containerWidth: number;\n containerHeight: number;\n imageWidth: number;\n imageHeight: number;\n pan?: PanOffset;\n};\n\nexport function computeViewerImageLayout({\n containerWidth,\n containerHeight,\n imageWidth,\n imageHeight,\n pan = { panX: 0, panY: 0 },\n}: ComputeViewerImageLayoutParams): ViewerImageLayout {\n const imgAspect = imageWidth / imageHeight;\n const containerAspect = containerWidth / containerHeight;\n\n let drawWidth: number;\n let drawHeight: number;\n\n if (imgAspect > containerAspect) {\n drawWidth = containerWidth;\n drawHeight = containerWidth / imgAspect;\n } else {\n drawHeight = containerHeight;\n drawWidth = containerHeight * imgAspect;\n }\n\n const offsetX = (containerWidth - drawWidth) / 2 + pan.panX;\n const offsetY = (containerHeight - drawHeight) / 2 + pan.panY;\n\n return {\n width: containerWidth,\n height: containerHeight,\n centerX: containerWidth / 2,\n centerY: containerHeight / 2,\n drawWidth,\n drawHeight,\n offsetX,\n offsetY,\n };\n}\n\nexport function computeHotspotScreenPosition(\n hotspotX: number,\n hotspotY: number,\n layout: ViewerImageLayout,\n zoom: number\n): { leftPercent: number; topPercent: number } {\n const baseOffsetX = (layout.width - layout.drawWidth) / 2;\n const baseOffsetY = (layout.height - layout.drawHeight) / 2;\n\n const containerX = (hotspotX / 100) * layout.width;\n const containerY = (hotspotY / 100) * layout.height;\n\n const imageLocalX = (containerX - baseOffsetX) / layout.drawWidth;\n const imageLocalY = (containerY - baseOffsetY) / layout.drawHeight;\n\n const imagePointX = layout.offsetX + imageLocalX * layout.drawWidth;\n const imagePointY = layout.offsetY + imageLocalY * layout.drawHeight;\n\n const screenX = layout.centerX + zoom * (imagePointX - layout.centerX);\n const screenY = layout.centerY + zoom * (imagePointY - layout.centerY);\n\n return {\n leftPercent: (screenX / layout.width) * 100,\n topPercent: (screenY / layout.height) * 100,\n };\n}\n\nexport function computeHotspotPositionFromClick(\n clientX: number,\n clientY: number,\n containerRect: DOMRect,\n layout: ViewerImageLayout,\n zoom: number\n): { positionX: number; positionY: number } {\n const clickX = clientX - containerRect.left;\n const clickY = clientY - containerRect.top;\n\n const unzoomedX = layout.centerX + (clickX - layout.centerX) / zoom;\n const unzoomedY = layout.centerY + (clickY - layout.centerY) / zoom;\n\n const baseOffsetX = (layout.width - layout.drawWidth) / 2;\n const baseOffsetY = (layout.height - layout.drawHeight) / 2;\n\n const imageLocalX = Math.min(1, Math.max(0, (unzoomedX - layout.offsetX) / layout.drawWidth));\n const imageLocalY = Math.min(1, Math.max(0, (unzoomedY - layout.offsetY) / layout.drawHeight));\n\n const storedX = baseOffsetX + imageLocalX * layout.drawWidth;\n const storedY = baseOffsetY + imageLocalY * layout.drawHeight;\n\n return {\n positionX: Math.min(100, Math.max(0, (storedX / layout.width) * 100)),\n positionY: Math.min(100, Math.max(0, (storedY / layout.height) * 100)),\n };\n}\n","import type { PanOffset } from './computeViewerImageLayout';\n\ntype PanStart = {\n pointerX: number;\n pointerY: number;\n panX: number;\n panY: number;\n};\n\nexport function computeViewerPanOffset(panStart: PanStart, clientX: number, clientY: number): PanOffset {\n const deltaX = clientX - panStart.pointerX;\n const deltaY = clientY - panStart.pointerY;\n\n return {\n panX: panStart.panX + deltaX,\n panY: panStart.panY + deltaY,\n };\n}\n","import type { Viewer360Frame } from '../types';\n\nimport { computeViewerImageLayout, type PanOffset } from './computeViewerImageLayout';\n\ntype DrawFrameOnCanvasParams = {\n canvas: HTMLCanvasElement;\n container: HTMLDivElement;\n image: HTMLImageElement;\n zoom: number;\n pan: PanOffset;\n};\n\nexport function drawFrameOnCanvas({ canvas, container, image, zoom, pan }: DrawFrameOnCanvasParams): void {\n if (!image.complete || !image.naturalWidth) return;\n\n const rect = container.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n\n canvas.width = rect.width * dpr;\n canvas.height = rect.height * dpr;\n canvas.style.width = `${rect.width}px`;\n canvas.style.height = `${rect.height}px`;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, rect.width, rect.height);\n\n const layout = computeViewerImageLayout({\n containerWidth: rect.width,\n containerHeight: rect.height,\n imageWidth: image.naturalWidth,\n imageHeight: image.naturalHeight,\n pan,\n });\n\n ctx.save();\n ctx.translate(layout.centerX, layout.centerY);\n ctx.scale(zoom, zoom);\n ctx.translate(-layout.centerX, -layout.centerY);\n ctx.drawImage(image, layout.offsetX, layout.offsetY, layout.drawWidth, layout.drawHeight);\n ctx.restore();\n}\n\nexport function getFramesSignature(frames: Viewer360Frame[]): string {\n return frames.map((frame) => frame.id).join('-');\n}\n\nexport function preloadFrameImage(frame: Viewer360Frame): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = (): void => resolve(img);\n img.onerror = (): void => reject(new Error(`Failed to load frame: ${frame.src}`));\n img.src = frame.src;\n });\n}\n\nexport async function preloadViewerFrames(frames: Viewer360Frame[]): Promise<HTMLImageElement[]> {\n const results = await Promise.allSettled(frames.map(preloadFrameImage));\n\n return results.map((result) => (result.status === 'fulfilled' ? result.value : new Image()));\n}\n\nexport function hasLoadedViewerFrame(images: HTMLImageElement[]): boolean {\n return images.some((image) => image.complete && image.naturalWidth > 0);\n}\n\nexport function filterHotspotsByFrame<TData>(\n hotspots: Array<{ frameIndex: number; data?: TData }>,\n frameIndex: number\n): Array<{ frameIndex: number; data?: TData }> {\n return hotspots.filter((hotspot) => hotspot.frameIndex === frameIndex);\n}\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cn } from '@/components/utils';\n\nfunction Card({ className, size = 'default', ...props }: React.ComponentProps<'div'> & { size?: 'default' | 'sm' }): JSX.Element {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n 'ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-6 text-sm shadow-xs ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n 'gap-0.5 rounded-t-xl px-6 group-data-[size=sm]/card:px-4 [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-title\"\n className={cn('text-lg leading-normal font-semibold group-data-[size=sm]/card:text-sm', className)}\n {...props}\n />\n );\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"card-description\" className={cn('text-muted-foreground text-xs font-medium', className)} {...props} />;\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-action\"\n className={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className)}\n {...props}\n />\n );\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"card-content\" className={cn('px-6 group-data-[size=sm]/card:px-4', className)} {...props} />;\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n 'rounded-b-xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4 flex items-center',\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { cn } from '@/components/utils';\n\nconst badgeVariants = cva(\n 'h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',\n secondary: 'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',\n destructive:\n 'bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20',\n outline: 'border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',\n ghost: 'hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50',\n link: 'text-primary underline-offset-4 hover:underline',\n info: 'bg-blue-500 text-white hover:bg-blue-600',\n warning: 'bg-amber-500 text-white hover:bg-amber-600',\n success: 'bg-green-600 text-white hover:bg-green-700',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nfunction Badge({\n className,\n variant = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & { asChild?: boolean }): JSX.Element {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const Comp = asChild ? Slot.Root : 'span';\n\n return <Comp data-slot=\"badge\" data-variant={variant} className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n\nexport { Badge, badgeVariants };\n","import type { JSX } from 'react';\n\nimport { Badge } from '@/components/ui/Badge';\nimport { cn } from '@/components/utils';\n\ntype Viewer360AddModeBannerProps = {\n className?: string;\n label: string;\n};\n\nexport function Viewer360AddModeBanner({ className, label }: Viewer360AddModeBannerProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Badge variant=\"outline\" className={cn('pointer-events-none', className)}>\n {label}\n </Badge>\n );\n}\n","import type { JSX } from 'react';\n\nimport { Badge } from '@/components/ui/Badge';\nimport { cn } from '@/components/utils';\n\ntype Viewer360FrameIndicatorProps = {\n className?: string;\n label: string;\n};\n\nexport function Viewer360FrameIndicator({ className, label }: Viewer360FrameIndicatorProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Badge variant=\"outline\" className={cn('pointer-events-none shadow-sm', className)}>\n {label}\n </Badge>\n );\n}\n","import type { Viewer360Hotspot, Viewer360Marker } from '../types';\n\nexport function hotspotToViewer360Marker<TData>(hotspot: Viewer360Hotspot<TData>): Viewer360Marker {\n const data = hotspot.data;\n\n if (data && typeof data === 'object' && 'title' in data && typeof (data as { title?: unknown }).title === 'string') {\n const marker = data as unknown as Viewer360Marker;\n\n return {\n id: marker.id ?? hotspot.id,\n title: marker.title,\n description: marker.description,\n };\n }\n\n return {\n id: hotspot.id,\n title: hotspot.id,\n };\n}\n\nexport function toViewer360Hotspots<TData extends Viewer360Marker>(\n markers: Array<Viewer360Marker & { frameIndex: number; positionX: number; positionY: number }>,\n mapData?: (marker: Viewer360Marker & { frameIndex: number; positionX: number; positionY: number }) => TData\n): Viewer360Hotspot<TData>[] {\n return markers.map((marker) => ({\n id: marker.id,\n frameIndex: marker.frameIndex,\n positionX: marker.positionX,\n positionY: marker.positionY,\n data: mapData ? mapData(marker) : (marker as unknown as TData),\n }));\n}\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { Separator } from '@/components/ui/Separator';\nimport { cn } from '@/components/utils';\n\nfunction ItemGroup({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n role=\"list\"\n data-slot=\"item-group\"\n className={cn('gap-4 has-[[data-size=sm]]:gap-2.5 has-[[data-size=xs]]:gap-2 group/item-group flex w-full flex-col', className)}\n {...props}\n />\n );\n}\n\nfunction ItemSeparator({ className, ...props }: React.ComponentProps<typeof Separator>): JSX.Element {\n return <Separator data-slot=\"item-separator\" orientation=\"horizontal\" className={cn('my-2', className)} {...props} />;\n}\n\nconst itemVariants = cva(\n '[a]:hover:bg-muted rounded-md border text-sm w-full group/item focus-visible:border-ring focus-visible:ring-ring/50 flex items-center flex-wrap outline-none transition-colors duration-100 focus-visible:ring-[3px] [a]:transition-colors',\n {\n variants: {\n variant: {\n default: 'border-transparent',\n outline: 'border-border',\n muted: 'bg-muted/50 border-transparent',\n },\n size: {\n default: 'gap-3.5 px-4 py-3.5',\n sm: 'gap-2.5 px-3 py-2.5',\n xs: 'gap-2 px-2.5 py-2 [[data-slot=dropdown-menu-content]_&]:p-0',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nfunction Item({\n className,\n variant = 'default',\n size = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'div'> & VariantProps<typeof itemVariants> & { asChild?: boolean }): JSX.Element {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const Comp = asChild ? Slot.Root : 'div';\n return (\n <Comp\n data-slot=\"item\"\n data-variant={variant}\n data-size={size}\n className={cn(itemVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nconst itemMediaVariants = cva(\n 'gap-2 group-has-[[data-slot=item-description]]/item:translate-y-0.5 group-has-[[data-slot=item-description]]/item:self-start flex shrink-0 items-center justify-center [&_svg]:pointer-events-none',\n {\n variants: {\n variant: {\n default: 'bg-transparent',\n icon: '[&_svg]:size-4',\n image: 'size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nfunction ItemMedia({\n className,\n variant = 'default',\n ...props\n}: React.ComponentProps<'div'> & VariantProps<typeof itemMediaVariants>): JSX.Element {\n return <div data-slot=\"item-media\" data-variant={variant} className={cn(itemMediaVariants({ variant, className }))} {...props} />;\n}\n\nfunction ItemContent({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"item-content\"\n className={cn('gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none', className)}\n {...props}\n />\n );\n}\n\nfunction ItemTitle({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"item-title\"\n className={cn('gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center', className)}\n {...props}\n />\n );\n}\n\nfunction ItemDescription({ className, ...props }: React.ComponentProps<'p'>): JSX.Element {\n return (\n <p\n data-slot=\"item-description\"\n className={cn(\n 'text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction ItemActions({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"item-actions\" className={cn('gap-2 flex items-center', className)} {...props} />;\n}\n\nfunction ItemHeader({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"item-header\" className={cn('gap-2 flex basis-full items-center justify-between', className)} {...props} />;\n}\n\nfunction ItemFooter({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"item-footer\" className={cn('gap-2 flex basis-full items-center justify-between', className)} {...props} />;\n}\n\nexport { Item, ItemMedia, ItemContent, ItemActions, ItemGroup, ItemSeparator, ItemTitle, ItemDescription, ItemHeader, ItemFooter };\n","'use client';\n\nimport * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { Separator as SeparatorPrimitive } from 'radix-ui';\n\nimport { cn } from '@/components/utils';\n\nfunction Separator({\n className,\n orientation = 'horizontal',\n decorative = true,\n ...props\n}: React.ComponentProps<typeof SeparatorPrimitive.Root>): JSX.Element {\n return (\n <SeparatorPrimitive.Root\n data-slot=\"separator\"\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch',\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Separator };\n","import type { JSX, MouseEvent } from 'react';\n\nimport { Trash2 } from 'lucide-react';\n\nimport { defaultViewer360MarkerPinLabels } from '../constants/viewer360MarkerLabels';\nimport { viewer360MarkerPinClassNames } from '../constants/viewer360ClassNames';\nimport type { Viewer360MarkerPinProps } from '../types';\nimport { Badge } from '@/components/ui/Badge';\nimport { Button } from '@/components/ui/Button';\nimport {\n Item,\n ItemActions,\n ItemContent,\n ItemDescription,\n ItemTitle,\n} from '@/components/ui/Item';\nimport { cn } from '@/components/utils';\n\nexport function Viewer360MarkerPin<TData = unknown>({\n marker,\n hotspot,\n leftPercent,\n topPercent,\n onDelete,\n isDeletePending = false,\n onClick,\n renderTag,\n classNames,\n labels,\n}: Viewer360MarkerPinProps<TData>): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: States & Constants\n // ----------------------------------------------------------------------------------------------------\n const deleteLabel = labels?.delete ?? defaultViewer360MarkerPinLabels.delete;\n const showTooltip = Boolean(marker.title || marker.description || onDelete || renderTag);\n\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Item\n size=\"xs\"\n variant=\"default\"\n className={cn(\n viewer360MarkerPinClassNames.root,\n classNames?.root,\n 'group/marker w-auto border-transparent p-0'\n )}\n style={{ left: `${leftPercent}%`, top: `${topPercent}%` }}\n >\n <Badge\n variant=\"destructive\"\n className={cn(viewer360MarkerPinClassNames.ping, classNames?.ping, 'absolute size-6 border-0 bg-destructive opacity-60')}\n aria-hidden=\"true\"\n />\n\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"icon-xs\"\n className={cn(\n viewer360MarkerPinClassNames.dot,\n classNames?.dot,\n 'size-4 min-h-4 min-w-4 rounded-full border-2 border-background bg-destructive p-0 shadow-md hover:scale-125 hover:bg-destructive'\n )}\n aria-label={marker.title}\n onClick={onClick}\n />\n\n {showTooltip && (\n <div\n className={cn(\n viewer360MarkerPinClassNames.tooltip,\n classNames?.tooltip,\n 'pointer-events-none opacity-0 transition-opacity duration-150 group-hover/marker:pointer-events-auto group-hover/marker:opacity-100 group-focus-within/marker:pointer-events-auto group-focus-within/marker:opacity-100'\n )}\n >\n <Item\n size=\"sm\"\n variant=\"default\"\n className={cn(viewer360MarkerPinClassNames.tooltipHeader, classNames?.tooltipHeader, 'w-full border-transparent')}\n >\n <ItemContent className={cn(viewer360MarkerPinClassNames.tooltipBody, classNames?.tooltipBody)}>\n <ItemTitle className={cn(viewer360MarkerPinClassNames.tooltipTitle, classNames?.tooltipTitle)}>\n {marker.title}\n </ItemTitle>\n {renderTag?.({ marker, hotspot })}\n {marker.description && (\n <ItemDescription className={cn(viewer360MarkerPinClassNames.tooltipDescription, classNames?.tooltipDescription)}>\n {marker.description}\n </ItemDescription>\n )}\n </ItemContent>\n {onDelete && (\n <ItemActions>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className={classNames?.deleteButton}\n disabled={isDeletePending}\n aria-label={deleteLabel}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n onDelete(marker.id);\n }}\n >\n <Trash2 className=\"size-4\" />\n </Button>\n </ItemActions>\n )}\n </Item>\n </div>\n )}\n </Item>\n );\n}\n","export const defaultViewer360MarkerPinLabels = {\n delete: 'Remove marker',\n} as const;\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { cn } from '@/components/utils';\n\nconst buttonVariants = cva(\n 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/80',\n outline:\n 'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground shadow-xs',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',\n ghost: 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',\n destructive:\n 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default:\n 'h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2',\n xs: 'h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',\n sm: 'h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',\n lg: 'h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pe-3 has-data-[icon=inline-start]:ps-3',\n icon: 'size-9',\n 'icon-xs':\n 'size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md',\n 'icon-sm': 'size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md',\n 'icon-lg': 'size-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nfunction Button({\n className,\n variant = 'default',\n size = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }): JSX.Element {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const Comp = asChild ? Slot.Root : 'button';\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","import type { JSX, MouseEvent, ReactNode } from 'react';\n\nimport { hotspotToViewer360Marker } from '../helpers/markerHelpers';\nimport type { Viewer360Hotspot, Viewer360HotspotPinOptions, Viewer360HotspotRenderProps } from '../types';\nimport { Item } from '@/components/ui/Item';\n\nimport { Viewer360MarkerPin } from './Viewer360MarkerPin';\n\ntype Viewer360HotspotOverlayProps<TData = unknown> = {\n hotspot: Viewer360Hotspot<TData>;\n leftPercent: number;\n topPercent: number;\n hotspotPin?: Viewer360HotspotPinOptions<TData>;\n renderHotspot?: (props: Viewer360HotspotRenderProps<TData>) => ReactNode;\n onHotspotClick?: (hotspot: Viewer360Hotspot<TData>, event: MouseEvent<HTMLDivElement>) => void;\n};\n\nexport function Viewer360HotspotOverlay<TData = unknown>({\n hotspot,\n leftPercent,\n topPercent,\n hotspotPin,\n renderHotspot,\n onHotspotClick,\n}: Viewer360HotspotOverlayProps<TData>): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n if (renderHotspot) {\n return (\n <Item size=\"xs\" variant=\"default\" className=\"pointer-events-auto w-auto border-transparent p-0\">\n {renderHotspot({ hotspot, leftPercent, topPercent })}\n </Item>\n );\n }\n\n const marker = hotspotPin?.getMarker?.(hotspot) ?? hotspotToViewer360Marker(hotspot);\n\n return (\n <Viewer360MarkerPin\n marker={marker}\n hotspot={hotspot}\n leftPercent={leftPercent}\n topPercent={topPercent}\n onDelete={hotspotPin?.onDelete}\n isDeletePending={hotspotPin?.deletingMarkerId === hotspot.id}\n renderTag={hotspotPin?.renderTag}\n classNames={hotspotPin?.classNames}\n labels={hotspotPin?.labels}\n onClick={\n onHotspotClick\n ? (event) => onHotspotClick(hotspot, event as unknown as MouseEvent<HTMLDivElement>)\n : undefined\n }\n />\n );\n}\n","'use client';\n\nimport * as React from 'react';\n\nimport { cn } from '@/components/utils';\n\nfunction Label({ className, ...props }: React.ComponentProps<'label'>): React.ReactNode {\n return (\n <label\n data-slot=\"label\"\n className={cn(\n 'gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed',\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Label };\n","import type { JSX } from 'react';\n\nimport { Loader2Icon } from 'lucide-react';\n\nimport { cn } from '@/components/utils';\n\nfunction Spinner({ className, ...props }: React.ComponentProps<'svg'>): JSX.Element {\n return <Loader2Icon role=\"status\" aria-label=\"Loading\" className={cn('size-4 animate-spin', className)} {...props} />;\n}\n\nexport { Spinner };\n","import type { JSX } from 'react';\n\nimport { Item } from '@/components/ui/Item';\nimport { Label } from '@/components/ui/Label';\nimport { Spinner } from '@/components/ui/Spinner';\nimport { cn } from '@/components/utils';\n\ntype Viewer360LoadingOverlayProps = {\n className?: string;\n textClassName?: string;\n label: string;\n};\n\nexport function Viewer360LoadingOverlay({ className, textClassName, label }: Viewer360LoadingOverlayProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Item\n size=\"sm\"\n variant=\"muted\"\n className={cn('pointer-events-none w-auto justify-center border-transparent bg-muted/80', className)}\n >\n <Spinner className=\"size-5 text-muted-foreground\" />\n <Label className={cn('font-normal text-muted-foreground', textClassName)}>{label}</Label>\n </Item>\n );\n}\n","import type { JSX } from 'react';\n\nimport { Crosshair, Minus, Plus, RotateCcw, ZoomIn } from 'lucide-react';\n\nimport { viewer360ClassNames } from '../constants/viewer360ClassNames';\nimport type { Viewer360ToolbarRenderProps } from '../types';\nimport { Badge } from '@/components/ui/Badge';\nimport { Button } from '@/components/ui/Button';\nimport { CardFooter } from '@/components/ui/Card';\nimport { Label } from '@/components/ui/Label';\nimport { Separator } from '@/components/ui/Separator';\nimport { cn } from '@/components/utils';\n\ntype Viewer360ToolbarProps = Viewer360ToolbarRenderProps;\n\nexport function Viewer360Toolbar({\n showDragHint,\n showHotspotModeControl,\n showZoomControls,\n showResetControl,\n labels,\n isHotspotMode,\n zoom,\n minZoom,\n maxZoom,\n isResetDisabled,\n onHotspotModeChange,\n onZoomIn,\n onZoomOut,\n onResetView,\n}: Viewer360ToolbarProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <CardFooter className={cn(viewer360ClassNames.toolbar, 'gap-2 border-t px-4 py-3 pt-3')}>\n {showDragHint && (\n <Label className={cn(viewer360ClassNames.dragHint, 'font-normal text-muted-foreground')}>{labels.dragHint}</Label>\n )}\n\n <div className={viewer360ClassNames.controls}>\n {showHotspotModeControl && (\n <>\n <Button variant={isHotspotMode ? 'default' : 'outline'} size=\"sm\" onClick={() => onHotspotModeChange(!isHotspotMode)}>\n <Crosshair className=\"me-1.5 size-4\" />\n {labels.addHotspot}\n </Button>\n <Separator orientation=\"vertical\" className={cn(viewer360ClassNames.divider, 'h-6')} />\n </>\n )}\n\n {showZoomControls && (\n <>\n <Button variant=\"outline\" size=\"icon-sm\" disabled={zoom <= minZoom} aria-label={labels.zoomOut} onClick={onZoomOut}>\n <Minus className=\"size-4\" />\n </Button>\n <Badge variant=\"outline\" className={cn(viewer360ClassNames.zoomDisplay, 'h-8 gap-1 px-2 py-1')}>\n <ZoomIn className=\"size-3 text-muted-foreground\" />\n {labels.zoom(Math.round(zoom * 100))}\n </Badge>\n <Button variant=\"outline\" size=\"icon-sm\" disabled={zoom >= maxZoom} aria-label={labels.zoomIn} onClick={onZoomIn}>\n <Plus className=\"size-4\" />\n </Button>\n </>\n )}\n\n {showResetControl && (\n <Button variant=\"outline\" size=\"icon-sm\" disabled={isResetDisabled} aria-label={labels.resetView} onClick={onResetView}>\n <RotateCcw className=\"size-4\" />\n </Button>\n )}\n </div>\n </CardFooter>\n );\n}\n","export const viewer360Config = {\n minZoom: 1,\n maxZoom: 3,\n zoomStep: 0.15,\n dragSensitivity: 8,\n autoRotate: false,\n autoRotateIntervalMs: 100,\n autoRotateDirection: 'forward' as const,\n};\n\nexport const defaultViewer360Config = viewer360Config;\n"],"mappings":"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","names":["useEffect","useMemo","useState","jsx","jsx","jsx","cva","Slot","jsx","jsx","cva","Slot","jsx","jsx","cva","Slot","jsx","cva","Slot","jsx","jsx","jsx","jsx","jsx","jsxs","jsx","jsxs","isResetDisabled","jsx","jsxs","useMemo","useState","isResetDisabled","useEffect"]}
1
+ {"version":3,"sources":["../src/feature/Viewer360.tsx","../src/constants/viewer360Labels.ts","../src/constants/viewer360ClassNames.ts","../src/components/utils/index.ts","../src/helpers/viewer360PropsHelpers.ts","../src/hooks/useViewer360.ts","../src/helpers/adjustViewerZoom.ts","../src/helpers/computeDragFrameIndex.ts","../src/helpers/computeViewerImageLayout.ts","../src/helpers/computeViewerPanOffset.ts","../src/helpers/viewerHelpers.ts","../src/components/ui/Card/index.tsx","../src/components/ui/Badge/index.tsx","../src/feature/Viewer360AddModeBanner.tsx","../src/feature/Viewer360FrameIndicator.tsx","../src/helpers/markerHelpers.ts","../src/components/ui/Item/index.tsx","../src/components/ui/Separator/index.tsx","../src/feature/Viewer360MarkerPin.tsx","../src/constants/viewer360MarkerLabels.ts","../src/components/ui/Button/index.tsx","../src/feature/Viewer360HotspotOverlay.tsx","../src/components/ui/Label/index.tsx","../src/components/ui/Spinner/index.tsx","../src/feature/Viewer360LoadingOverlay.tsx","../src/feature/Viewer360Toolbar.tsx","../src/constants/viewer360Config.ts"],"sourcesContent":["import type { JSX } from 'react';\nimport { useEffect, useMemo, useState } from 'react';\n\nimport { buildViewer360ThemeStyle, mergeViewer360ClassNames, mergeViewer360Labels } from '../helpers/viewer360PropsHelpers';\nimport { useViewer360 } from '../hooks/useViewer360';\nimport type { Viewer360OverlayRenderProps, Viewer360Props, Viewer360ToolbarRenderProps } from '../types';\nimport { Card } from '@/components/ui/Card';\nimport { cn } from '@/components/utils';\n\nimport { Viewer360AddModeBanner } from './Viewer360AddModeBanner';\nimport { Viewer360FrameIndicator } from './Viewer360FrameIndicator';\nimport { Viewer360HotspotOverlay } from './Viewer360HotspotOverlay';\nimport { Viewer360LoadingOverlay } from './Viewer360LoadingOverlay';\nimport { Viewer360Toolbar } from './Viewer360Toolbar';\n\nexport function Viewer360<TData = unknown>({\n frames,\n currentFrameIndex: controlledFrameIndex,\n defaultFrameIndex = 0,\n onFrameChange,\n config,\n className,\n classNames,\n style,\n theme,\n labels,\n aspectRatio = '16 / 10',\n showZoomControls = true,\n showResetControl = true,\n showFrameIndicator = true,\n showDragHint = true,\n showHotspotModeControl = false,\n hotspotPin,\n hotspots = [],\n renderHotspot,\n renderLoading,\n renderFrameIndicator,\n renderHotspotModeBanner,\n renderToolbar,\n onHotspotClick,\n hotspotMode: controlledHotspotMode,\n defaultHotspotMode = false,\n onHotspotModeChange,\n onHotspotAdd,\n children,\n}: Viewer360Props<TData>): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: States & Constants\n // ----------------------------------------------------------------------------------------------------\n const mergedLabels = useMemo(() => mergeViewer360Labels(labels), [labels]);\n const mergedClassNames = useMemo(() => mergeViewer360ClassNames(classNames), [classNames]);\n const themeStyle = useMemo(() => buildViewer360ThemeStyle(theme), [theme]);\n\n const [internalFrameIndex, setInternalFrameIndex] = useState(defaultFrameIndex);\n const [internalHotspotMode, setInternalHotspotMode] = useState(defaultHotspotMode);\n\n const currentFrameIndex = controlledFrameIndex ?? internalFrameIndex;\n const hotspotMode = controlledHotspotMode ?? internalHotspotMode;\n\n // ----------------------------------------------------------------------------------------------------\n // MARK: Functions\n // ----------------------------------------------------------------------------------------------------\n function handleFrameChange(index: number): void {\n if (controlledFrameIndex === undefined) {\n setInternalFrameIndex(index);\n }\n\n onFrameChange?.(index);\n }\n\n function handleHotspotModeChange(active: boolean): void {\n if (controlledHotspotMode === undefined) {\n setInternalHotspotMode(active);\n }\n\n onHotspotModeChange?.(active);\n }\n\n const {\n canvasRef,\n containerRef,\n currentFrame,\n currentFrameHotspots,\n imagesLoaded,\n isHotspotMode,\n isResetDisabled,\n maxZoom,\n minZoom,\n viewerCursorClass,\n zoom,\n getHotspotScreenPosition,\n handleCanvasClick,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handleWheel,\n handleResetView,\n handleZoomIn,\n handleZoomOut,\n } = useViewer360<TData>({\n frames,\n hotspots,\n currentFrameIndex,\n onFrameChange: handleFrameChange,\n config,\n hotspotMode,\n onHotspotAdd,\n });\n\n useEffect(() => {\n if (controlledHotspotMode === undefined) return;\n if (controlledHotspotMode !== internalHotspotMode) {\n setInternalHotspotMode(controlledHotspotMode);\n }\n }, [controlledHotspotMode, internalHotspotMode]);\n\n const frameLabel = currentFrame?.label ?? frames[currentFrameIndex]?.label;\n const overlayProps: Viewer360OverlayRenderProps = {\n currentFrameIndex,\n frameCount: frames.length,\n frameLabel,\n isHotspotMode,\n labels: mergedLabels,\n frameIndicatorClassName: mergedClassNames.frameIndicator,\n };\n const toolbarProps: Viewer360ToolbarRenderProps = {\n zoom,\n minZoom,\n maxZoom,\n isResetDisabled,\n isHotspotMode,\n showHotspotModeControl,\n showZoomControls,\n showResetControl,\n showDragHint,\n labels: mergedLabels,\n onZoomIn: handleZoomIn,\n onZoomOut: handleZoomOut,\n onResetView: handleResetView,\n onHotspotModeChange: handleHotspotModeChange,\n };\n const showDefaultToolbar = showZoomControls || showResetControl || showHotspotModeControl || showDragHint;\n\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Card\n data-viewer-360=\"\"\n className={cn(mergedClassNames.root, 'gap-0 py-0 shadow-none ring-0', className)}\n style={{ ...themeStyle, ...style }}\n >\n <div\n ref={containerRef}\n className={cn(mergedClassNames.viewport, viewerCursorClass)}\n style={{ aspectRatio }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerLeave={handlePointerUp}\n onWheel={handleWheel}\n onClick={handleCanvasClick}\n >\n <canvas ref={canvasRef} className={mergedClassNames.canvas} />\n\n <div className={mergedClassNames.overlay}>\n {currentFrameHotspots.map((hotspot) => {\n const position = getHotspotScreenPosition(hotspot);\n\n return (\n <Viewer360HotspotOverlay\n key={hotspot.id}\n hotspot={hotspot}\n leftPercent={position.leftPercent}\n topPercent={position.topPercent}\n hotspotPin={hotspotPin}\n renderHotspot={renderHotspot}\n onHotspotClick={onHotspotClick}\n />\n );\n })}\n {children}\n </div>\n\n {!imagesLoaded &&\n (renderLoading ? (\n renderLoading()\n ) : (\n <Viewer360LoadingOverlay\n className={mergedClassNames.loading}\n textClassName={mergedClassNames.loadingText}\n label={mergedLabels.loading}\n />\n ))}\n\n {showFrameIndicator &&\n frames.length > 0 &&\n (renderFrameIndicator ? (\n renderFrameIndicator(overlayProps)\n ) : (\n <Viewer360FrameIndicator\n className={mergedClassNames.frameIndicator}\n label={mergedLabels.frameIndicator({\n current: currentFrameIndex + 1,\n total: frames.length,\n label: frameLabel,\n })}\n />\n ))}\n\n {isHotspotMode &&\n onHotspotAdd &&\n (renderHotspotModeBanner ? (\n renderHotspotModeBanner({ labels: mergedLabels })\n ) : (\n <Viewer360AddModeBanner className={mergedClassNames.hotspotModeBanner} label={mergedLabels.hotspotModeActive} />\n ))}\n </div>\n\n {renderToolbar ? renderToolbar(toolbarProps) : showDefaultToolbar ? <Viewer360Toolbar {...toolbarProps} /> : null}\n </Card>\n );\n}\n","import type { Viewer360Labels } from '../types/Viewer360Props';\n\nexport const defaultViewer360Labels: Required<Viewer360Labels> = {\n loading: 'Loading images…',\n dragHint: 'Drag to rotate • Scroll to zoom',\n frameIndicator: ({ current, total, label }) => (label ? `${label} · ${current} / ${total}` : `${current} / ${total}`),\n zoom: (percent) => `${percent}%`,\n hotspotModeActive: 'Click on the image to place a hotspot',\n addHotspot: 'Add hotspot',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n resetView: 'Reset view',\n deleteMarker: 'Remove marker',\n};\n","import type { Viewer360ClassNames } from '../types/Viewer360Props';\nimport type { Viewer360MarkerPinClassNames } from '../types/Viewer360Marker';\n\nexport const viewer360ClassNames: Required<Viewer360ClassNames> = {\n root: 'overflow-hidden rounded-lg border bg-card text-card-foreground',\n viewport: 'relative aspect-[16/10] w-full touch-none select-none bg-muted',\n canvas: 'absolute inset-0 size-full',\n overlay: 'pointer-events-none absolute inset-0 overflow-hidden',\n loading: 'absolute inset-0 flex items-center justify-center bg-muted/80',\n loadingText: 'text-sm text-muted-foreground',\n frameIndicator:\n 'pointer-events-none absolute bottom-4 start-1/2 z-20 -translate-x-1/2 rounded-full border bg-background px-4 py-1.5 text-xs font-medium shadow-sm whitespace-nowrap',\n hotspotModeBanner:\n 'pointer-events-none absolute top-4 start-1/2 z-20 -translate-x-1/2 rounded-full border border-amber-200 bg-amber-50 px-4 py-1.5 text-xs font-medium text-amber-800 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-400',\n toolbar: 'flex flex-wrap items-center justify-between gap-2 border-t px-4 py-3',\n dragHint: 'hidden text-xs text-muted-foreground sm:block',\n controls: 'ms-auto flex items-center gap-1.5',\n controlButton: '',\n controlButtonActive: '',\n controlButtonDisabled: '',\n zoomDisplay: 'flex min-w-[3rem] items-center justify-center gap-1 rounded-md border bg-background px-2 py-1 text-xs font-medium',\n divider: 'mx-1 h-6 w-px bg-border',\n};\n\nexport const viewer360MarkerPinClassNames: Required<Viewer360MarkerPinClassNames> = {\n root: 'pointer-events-auto absolute z-30 -translate-x-1/2 -translate-y-1/2',\n ping: 'pointer-events-none absolute inset-0 inline-flex animate-ping rounded-full bg-destructive opacity-75',\n dot: 'relative z-10 inline-flex size-4 min-h-4 min-w-4 shrink-0 rounded-full border-2 border-background bg-destructive p-0 shadow-md transition-transform duration-200 hover:scale-125 focus:outline-none',\n tooltip:\n 'absolute bottom-6 left-1/2 z-40 w-64 -translate-x-1/2 rounded-lg border bg-popover p-3 text-popover-foreground shadow-md',\n tooltipHeader: 'flex items-start justify-between gap-2',\n tooltipBody: 'flex min-w-0 flex-col gap-1',\n tooltipTitle: 'text-sm font-medium',\n tooltipDescription: 'mt-2 line-clamp-3 text-xs text-muted-foreground',\n deleteButton: '',\n};\n\n/** @deprecated Use `viewer360ClassNames` */\nexport const defaultViewer360ClassNames = viewer360ClassNames;\n\n/** @deprecated Use `viewer360MarkerPinClassNames` */\nexport const defaultViewer360MarkerPinClassNames = viewer360MarkerPinClassNames;\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { CSSProperties } from 'react';\n\nimport { defaultViewer360Labels } from '../constants/viewer360Labels';\nimport { viewer360ClassNames } from '../constants/viewer360ClassNames';\nimport type { Viewer360ClassNames, Viewer360Labels, Viewer360Theme } from '../types';\nimport { cn } from '@/components/utils';\n\nexport function mergeViewer360Labels(labels?: Viewer360Labels): Required<Viewer360Labels> {\n return {\n loading: labels?.loading ?? defaultViewer360Labels.loading,\n dragHint: labels?.dragHint ?? defaultViewer360Labels.dragHint,\n frameIndicator: labels?.frameIndicator ?? defaultViewer360Labels.frameIndicator,\n zoom: labels?.zoom ?? defaultViewer360Labels.zoom,\n hotspotModeActive: labels?.hotspotModeActive ?? defaultViewer360Labels.hotspotModeActive,\n addHotspot: labels?.addHotspot ?? defaultViewer360Labels.addHotspot,\n zoomIn: labels?.zoomIn ?? defaultViewer360Labels.zoomIn,\n zoomOut: labels?.zoomOut ?? defaultViewer360Labels.zoomOut,\n resetView: labels?.resetView ?? defaultViewer360Labels.resetView,\n deleteMarker: labels?.deleteMarker ?? defaultViewer360Labels.deleteMarker,\n };\n}\n\nexport function mergeViewer360ClassNames(classNames?: Viewer360ClassNames): Required<Viewer360ClassNames> {\n return {\n root: cn(viewer360ClassNames.root, classNames?.root),\n viewport: cn(viewer360ClassNames.viewport, classNames?.viewport),\n canvas: cn(viewer360ClassNames.canvas, classNames?.canvas),\n overlay: cn(viewer360ClassNames.overlay, classNames?.overlay),\n loading: cn(viewer360ClassNames.loading, classNames?.loading),\n loadingText: cn(viewer360ClassNames.loadingText, classNames?.loadingText),\n frameIndicator: cn(viewer360ClassNames.frameIndicator, classNames?.frameIndicator),\n hotspotModeBanner: cn(viewer360ClassNames.hotspotModeBanner, classNames?.hotspotModeBanner),\n toolbar: cn(viewer360ClassNames.toolbar, classNames?.toolbar),\n dragHint: cn(viewer360ClassNames.dragHint, classNames?.dragHint),\n controls: cn(viewer360ClassNames.controls, classNames?.controls),\n controlButton: cn(viewer360ClassNames.controlButton, classNames?.controlButton),\n controlButtonActive: cn(viewer360ClassNames.controlButtonActive, classNames?.controlButtonActive),\n controlButtonDisabled: cn(viewer360ClassNames.controlButtonDisabled, classNames?.controlButtonDisabled),\n zoomDisplay: cn(viewer360ClassNames.zoomDisplay, classNames?.zoomDisplay),\n divider: cn(viewer360ClassNames.divider, classNames?.divider),\n };\n}\n\nexport function buildViewer360ThemeStyle(theme?: Viewer360Theme): CSSProperties {\n return theme ? (theme as CSSProperties) : {};\n}\n","import type { PointerEvent as ReactPointerEvent, RefObject, WheelEvent as ReactWheelEvent } from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\nimport {\n applyWheelZoom,\n getViewerCursorClass,\n isResetDisabled,\n resolveViewer360Config,\n stepZoomIn,\n stepZoomOut,\n} from '../helpers/adjustViewerZoom';\nimport { computeDragFrameIndex } from '../helpers/computeDragFrameIndex';\nimport {\n computeHotspotPositionFromClick,\n computeHotspotScreenPosition,\n computeViewerImageLayout,\n type ViewerImageLayout,\n} from '../helpers/computeViewerImageLayout';\nimport { computeViewerPanOffset } from '../helpers/computeViewerPanOffset';\nimport {\n drawFrameOnCanvas,\n filterHotspotsByFrame,\n getFramesSignature,\n hasLoadedViewerFrame,\n preloadViewerFrames,\n} from '../helpers/viewerHelpers';\nimport type {\n Viewer360Config,\n Viewer360Frame,\n Viewer360Hotspot,\n Viewer360HotspotPosition,\n Viewer360PanOffset,\n} from '../types';\n\ntype UseViewer360Params<TData> = {\n frames: Viewer360Frame[];\n currentFrameIndex: number;\n onFrameChange: (index: number) => void;\n hotspots?: Viewer360Hotspot<TData>[];\n config?: Viewer360Config;\n hotspotMode?: boolean;\n onHotspotAdd?: (position: Viewer360HotspotPosition) => void;\n};\n\ntype UseViewer360Return<TData> = {\n canvasRef: RefObject<HTMLCanvasElement | null>;\n containerRef: RefObject<HTMLDivElement | null>;\n currentFrame: Viewer360Frame | undefined;\n currentFrameHotspots: Viewer360Hotspot<TData>[];\n imagesLoaded: boolean;\n isHotspotMode: boolean;\n isResetDisabled: boolean;\n maxZoom: number;\n minZoom: number;\n viewerCursorClass: string;\n zoom: number;\n getCurrentImageLayout: () => ViewerImageLayout | null;\n getHotspotScreenPosition: (hotspot: Viewer360Hotspot<TData>) => { leftPercent: number; topPercent: number };\n handleCanvasClick: (event: React.MouseEvent<HTMLDivElement>) => void;\n handlePointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void;\n handlePointerMove: (event: ReactPointerEvent<HTMLDivElement>) => void;\n handlePointerUp: (event: ReactPointerEvent<HTMLDivElement>) => void;\n handleResetView: () => void;\n handleWheel: (event: ReactWheelEvent<HTMLDivElement>) => void;\n handleZoomIn: () => void;\n handleZoomOut: () => void;\n};\n\nexport function useViewer360<TData = unknown>({\n frames,\n hotspots = [],\n currentFrameIndex,\n onFrameChange,\n config,\n hotspotMode: hotspotModeProp = false,\n onHotspotAdd,\n}: UseViewer360Params<TData>): UseViewer360Return<TData> {\n const resolvedConfig = useMemo(() => resolveViewer360Config(config), [config]);\n const { minZoom, maxZoom } = resolvedConfig;\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const imagesRef = useRef<HTMLImageElement[]>([]);\n const dragStartRef = useRef<{ pointerX: number; frameIndex: number } | null>(null);\n const panStartRef = useRef<{ pointerX: number; pointerY: number; panX: number; panY: number } | null>(null);\n\n const framesSignature = getFramesSignature(frames);\n const [loadedSignature, setLoadedSignature] = useState<string | null>(null);\n const [zoom, setZoom] = useState<number>(minZoom);\n const [pan, setPan] = useState<Viewer360PanOffset>({ panX: 0, panY: 0 });\n const [isDragging, setIsDragging] = useState(false);\n\n const isHotspotMode = hotspotModeProp;\n const imagesLoaded = loadedSignature === framesSignature;\n const currentFrameHotspots = filterHotspotsByFrame(hotspots, currentFrameIndex) as Viewer360Hotspot<TData>[];\n const currentFrame = frames[currentFrameIndex];\n const viewerCursorClass = getViewerCursorClass(isHotspotMode, zoom, isDragging, minZoom);\n const resetDisabled = isResetDisabled(zoom, pan, resolvedConfig);\n\n useEffect(() => {\n let cancelled = false;\n imagesRef.current = [];\n\n async function loadFrames(): Promise<void> {\n const loadedImages = await preloadViewerFrames(frames);\n\n if (!cancelled && hasLoadedViewerFrame(loadedImages)) {\n imagesRef.current = loadedImages;\n setLoadedSignature(framesSignature);\n }\n }\n\n void loadFrames();\n\n return (): void => {\n cancelled = true;\n };\n }, [frames, framesSignature]);\n\n useEffect(() => {\n if (!imagesLoaded) return;\n\n function renderFrame(): void {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n const img = imagesRef.current[currentFrameIndex];\n\n if (!canvas || !container) return;\n\n drawFrameOnCanvas({ canvas, container, image: img, zoom, pan });\n }\n\n renderFrame();\n window.addEventListener('resize', renderFrame);\n\n return (): void => window.removeEventListener('resize', renderFrame);\n }, [imagesLoaded, currentFrameIndex, zoom, pan]);\n\n useEffect(() => {\n if (!resolvedConfig.autoRotate || frames.length <= 1 || isDragging || isHotspotMode || zoom > minZoom) {\n return;\n }\n\n const direction = resolvedConfig.autoRotateDirection === 'backward' ? -1 : 1;\n const interval = window.setInterval(() => {\n onFrameChange((currentFrameIndex + direction + frames.length) % frames.length);\n }, resolvedConfig.autoRotateIntervalMs);\n\n return (): void => window.clearInterval(interval);\n }, [\n resolvedConfig.autoRotate,\n resolvedConfig.autoRotateDirection,\n resolvedConfig.autoRotateIntervalMs,\n frames.length,\n currentFrameIndex,\n isDragging,\n isHotspotMode,\n zoom,\n minZoom,\n onFrameChange,\n ]);\n\n function getCurrentImageLayout(): ViewerImageLayout | null {\n const container = containerRef.current;\n const image = imagesRef.current[currentFrameIndex];\n\n if (!container || !image || !image.complete || !image.naturalWidth) return null;\n\n const rect = container.getBoundingClientRect();\n\n return computeViewerImageLayout({\n containerWidth: rect.width,\n containerHeight: rect.height,\n imageWidth: image.naturalWidth,\n imageHeight: image.naturalHeight,\n pan,\n });\n }\n\n function getHotspotScreenPosition(hotspot: Viewer360Hotspot<TData>): { leftPercent: number; topPercent: number } {\n const layout = getCurrentImageLayout();\n\n if (!layout) {\n return { leftPercent: hotspot.positionX, topPercent: hotspot.positionY };\n }\n\n return computeHotspotScreenPosition(hotspot.positionX, hotspot.positionY, layout, zoom);\n }\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>): void {\n if (isHotspotMode) return;\n\n event.currentTarget.setPointerCapture(event.pointerId);\n\n if (zoom > minZoom) {\n panStartRef.current = { pointerX: event.clientX, pointerY: event.clientY, panX: pan.panX, panY: pan.panY };\n } else {\n dragStartRef.current = { pointerX: event.clientX, frameIndex: currentFrameIndex };\n }\n\n setIsDragging(true);\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>): void {\n if (!isDragging) return;\n\n if (panStartRef.current && zoom > minZoom) {\n setPan(computeViewerPanOffset(panStartRef.current, event.clientX, event.clientY));\n return;\n }\n\n if (dragStartRef.current && zoom <= minZoom) {\n const nextFrameIndex = computeDragFrameIndex(\n dragStartRef.current,\n event.clientX,\n frames.length,\n resolvedConfig.dragSensitivity\n );\n\n if (nextFrameIndex !== null) {\n onFrameChange(nextFrameIndex);\n }\n }\n }\n\n function handlePointerUp(event: ReactPointerEvent<HTMLDivElement>): void {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n\n dragStartRef.current = null;\n panStartRef.current = null;\n setIsDragging(false);\n }\n\n function handleWheel(event: ReactWheelEvent<HTMLDivElement>): void {\n event.preventDefault();\n const { zoom: nextZoom, pan: nextPan } = applyWheelZoom(zoom, event.deltaY, pan, resolvedConfig);\n setZoom(nextZoom);\n setPan(nextPan);\n }\n\n function handleCanvasClick(event: React.MouseEvent<HTMLDivElement>): void {\n if (!isHotspotMode || isDragging || !onHotspotAdd) return;\n\n const frame = frames[currentFrameIndex];\n if (!frame) return;\n\n const layout = getCurrentImageLayout();\n if (!layout) return;\n\n const { positionX, positionY } = computeHotspotPositionFromClick(\n event.clientX,\n event.clientY,\n event.currentTarget.getBoundingClientRect(),\n layout,\n zoom\n );\n\n onHotspotAdd({\n frameIndex: currentFrameIndex,\n frameId: frame.id,\n positionX,\n positionY,\n });\n }\n\n function handleResetView(): void {\n setZoom(minZoom);\n setPan({ panX: 0, panY: 0 });\n }\n\n function handleZoomIn(): void {\n setZoom(stepZoomIn(zoom, resolvedConfig));\n }\n\n function handleZoomOut(): void {\n const { zoom: nextZoom, pan: nextPan } = stepZoomOut(zoom, pan, resolvedConfig);\n setZoom(nextZoom);\n setPan(nextPan);\n }\n\n return {\n canvasRef,\n containerRef,\n currentFrame,\n currentFrameHotspots,\n imagesLoaded,\n isHotspotMode,\n isResetDisabled: resetDisabled,\n maxZoom,\n minZoom,\n viewerCursorClass,\n zoom,\n getCurrentImageLayout,\n getHotspotScreenPosition,\n handleCanvasClick,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handleResetView,\n handleWheel,\n handleZoomIn,\n handleZoomOut,\n };\n}\n","import type { Viewer360Config } from '../types';\n\nimport type { PanOffset } from './computeViewerImageLayout';\n\ntype ResolvedViewer360Config = Required<Viewer360Config>;\n\nexport function resolveViewer360Config(config?: Viewer360Config): ResolvedViewer360Config {\n return {\n minZoom: config?.minZoom ?? 1,\n maxZoom: config?.maxZoom ?? 3,\n zoomStep: config?.zoomStep ?? 0.15,\n dragSensitivity: config?.dragSensitivity ?? 8,\n autoRotate: config?.autoRotate ?? false,\n autoRotateIntervalMs: config?.autoRotateIntervalMs ?? 100,\n autoRotateDirection: config?.autoRotateDirection ?? 'forward',\n };\n}\n\nexport function clampZoom(zoom: number, config: ResolvedViewer360Config): number {\n return Math.min(config.maxZoom, Math.max(config.minZoom, zoom));\n}\n\nexport function applyWheelZoom(\n currentZoom: number,\n deltaY: number,\n currentPan: PanOffset,\n config: ResolvedViewer360Config\n): { zoom: number; pan: PanOffset } {\n const delta = deltaY > 0 ? -config.zoomStep : config.zoomStep;\n const zoom = clampZoom(currentZoom + delta, config);\n\n return {\n zoom,\n pan: zoom === config.minZoom ? { panX: 0, panY: 0 } : currentPan,\n };\n}\n\nexport function stepZoomIn(currentZoom: number, config: ResolvedViewer360Config): number {\n return clampZoom(currentZoom + config.zoomStep, config);\n}\n\nexport function stepZoomOut(\n currentZoom: number,\n currentPan: PanOffset,\n config: ResolvedViewer360Config\n): { zoom: number; pan: PanOffset } {\n const zoom = clampZoom(currentZoom - config.zoomStep, config);\n\n return {\n zoom,\n pan: zoom === config.minZoom ? { panX: 0, panY: 0 } : currentPan,\n };\n}\n\nexport function isResetDisabled(zoom: number, pan: PanOffset, config: ResolvedViewer360Config): boolean {\n return zoom === config.minZoom && pan.panX === 0 && pan.panY === 0;\n}\n\nexport function getViewerCursorClass(isHotspotMode: boolean, zoom: number, isDragging: boolean, minZoom: number): string {\n if (isHotspotMode) return 'cursor-crosshair';\n if (isDragging) return 'cursor-grabbing';\n if (zoom > minZoom) return 'cursor-grab';\n return 'cursor-ew-resize';\n}\n","export function clampFrameIndex(index: number, frameCount: number): number {\n if (frameCount === 0) return 0;\n return ((index % frameCount) + frameCount) % frameCount;\n}\n\ntype DragStart = {\n pointerX: number;\n frameIndex: number;\n};\n\nexport function computeDragFrameIndex(\n dragStart: DragStart,\n clientX: number,\n frameCount: number,\n dragSensitivity: number\n): number | null {\n const deltaX = clientX - dragStart.pointerX;\n const frameDelta = Math.round(-deltaX / dragSensitivity);\n\n if (frameDelta === 0) return null;\n\n return clampFrameIndex(dragStart.frameIndex + frameDelta, frameCount);\n}\n","export type ViewerImageLayout = {\n width: number;\n height: number;\n centerX: number;\n centerY: number;\n drawWidth: number;\n drawHeight: number;\n offsetX: number;\n offsetY: number;\n};\n\nexport type PanOffset = {\n panX: number;\n panY: number;\n};\n\ntype ComputeViewerImageLayoutParams = {\n containerWidth: number;\n containerHeight: number;\n imageWidth: number;\n imageHeight: number;\n pan?: PanOffset;\n};\n\nexport function computeViewerImageLayout({\n containerWidth,\n containerHeight,\n imageWidth,\n imageHeight,\n pan = { panX: 0, panY: 0 },\n}: ComputeViewerImageLayoutParams): ViewerImageLayout {\n const imgAspect = imageWidth / imageHeight;\n const containerAspect = containerWidth / containerHeight;\n\n let drawWidth: number;\n let drawHeight: number;\n\n if (imgAspect > containerAspect) {\n drawWidth = containerWidth;\n drawHeight = containerWidth / imgAspect;\n } else {\n drawHeight = containerHeight;\n drawWidth = containerHeight * imgAspect;\n }\n\n const offsetX = (containerWidth - drawWidth) / 2 + pan.panX;\n const offsetY = (containerHeight - drawHeight) / 2 + pan.panY;\n\n return {\n width: containerWidth,\n height: containerHeight,\n centerX: containerWidth / 2,\n centerY: containerHeight / 2,\n drawWidth,\n drawHeight,\n offsetX,\n offsetY,\n };\n}\n\nexport function computeHotspotScreenPosition(\n hotspotX: number,\n hotspotY: number,\n layout: ViewerImageLayout,\n zoom: number\n): { leftPercent: number; topPercent: number } {\n const baseOffsetX = (layout.width - layout.drawWidth) / 2;\n const baseOffsetY = (layout.height - layout.drawHeight) / 2;\n\n const containerX = (hotspotX / 100) * layout.width;\n const containerY = (hotspotY / 100) * layout.height;\n\n const imageLocalX = (containerX - baseOffsetX) / layout.drawWidth;\n const imageLocalY = (containerY - baseOffsetY) / layout.drawHeight;\n\n const imagePointX = layout.offsetX + imageLocalX * layout.drawWidth;\n const imagePointY = layout.offsetY + imageLocalY * layout.drawHeight;\n\n const screenX = layout.centerX + zoom * (imagePointX - layout.centerX);\n const screenY = layout.centerY + zoom * (imagePointY - layout.centerY);\n\n return {\n leftPercent: (screenX / layout.width) * 100,\n topPercent: (screenY / layout.height) * 100,\n };\n}\n\nexport function computeHotspotPositionFromClick(\n clientX: number,\n clientY: number,\n containerRect: DOMRect,\n layout: ViewerImageLayout,\n zoom: number\n): { positionX: number; positionY: number } {\n const clickX = clientX - containerRect.left;\n const clickY = clientY - containerRect.top;\n\n const unzoomedX = layout.centerX + (clickX - layout.centerX) / zoom;\n const unzoomedY = layout.centerY + (clickY - layout.centerY) / zoom;\n\n const baseOffsetX = (layout.width - layout.drawWidth) / 2;\n const baseOffsetY = (layout.height - layout.drawHeight) / 2;\n\n const imageLocalX = Math.min(1, Math.max(0, (unzoomedX - layout.offsetX) / layout.drawWidth));\n const imageLocalY = Math.min(1, Math.max(0, (unzoomedY - layout.offsetY) / layout.drawHeight));\n\n const storedX = baseOffsetX + imageLocalX * layout.drawWidth;\n const storedY = baseOffsetY + imageLocalY * layout.drawHeight;\n\n return {\n positionX: Math.min(100, Math.max(0, (storedX / layout.width) * 100)),\n positionY: Math.min(100, Math.max(0, (storedY / layout.height) * 100)),\n };\n}\n","import type { PanOffset } from './computeViewerImageLayout';\n\ntype PanStart = {\n pointerX: number;\n pointerY: number;\n panX: number;\n panY: number;\n};\n\nexport function computeViewerPanOffset(panStart: PanStart, clientX: number, clientY: number): PanOffset {\n const deltaX = clientX - panStart.pointerX;\n const deltaY = clientY - panStart.pointerY;\n\n return {\n panX: panStart.panX + deltaX,\n panY: panStart.panY + deltaY,\n };\n}\n","import type { Viewer360Frame } from '../types';\n\nimport { computeViewerImageLayout, type PanOffset } from './computeViewerImageLayout';\n\ntype DrawFrameOnCanvasParams = {\n canvas: HTMLCanvasElement;\n container: HTMLDivElement;\n image: HTMLImageElement;\n zoom: number;\n pan: PanOffset;\n};\n\nexport function drawFrameOnCanvas({ canvas, container, image, zoom, pan }: DrawFrameOnCanvasParams): void {\n if (!image.complete || !image.naturalWidth) return;\n\n const rect = container.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n\n canvas.width = rect.width * dpr;\n canvas.height = rect.height * dpr;\n canvas.style.width = `${rect.width}px`;\n canvas.style.height = `${rect.height}px`;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, rect.width, rect.height);\n\n const layout = computeViewerImageLayout({\n containerWidth: rect.width,\n containerHeight: rect.height,\n imageWidth: image.naturalWidth,\n imageHeight: image.naturalHeight,\n pan,\n });\n\n ctx.save();\n ctx.translate(layout.centerX, layout.centerY);\n ctx.scale(zoom, zoom);\n ctx.translate(-layout.centerX, -layout.centerY);\n ctx.drawImage(image, layout.offsetX, layout.offsetY, layout.drawWidth, layout.drawHeight);\n ctx.restore();\n}\n\nexport function getFramesSignature(frames: Viewer360Frame[]): string {\n return frames.map((frame) => frame.id).join('-');\n}\n\nexport function preloadFrameImage(frame: Viewer360Frame): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = (): void => resolve(img);\n img.onerror = (): void => reject(new Error(`Failed to load frame: ${frame.src}`));\n img.src = frame.src;\n });\n}\n\nexport async function preloadViewerFrames(frames: Viewer360Frame[]): Promise<HTMLImageElement[]> {\n const results = await Promise.allSettled(frames.map(preloadFrameImage));\n\n return results.map((result) => (result.status === 'fulfilled' ? result.value : new Image()));\n}\n\nexport function hasLoadedViewerFrame(images: HTMLImageElement[]): boolean {\n return images.some((image) => image.complete && image.naturalWidth > 0);\n}\n\nexport function filterHotspotsByFrame<TData>(\n hotspots: Array<{ frameIndex: number; data?: TData }>,\n frameIndex: number\n): Array<{ frameIndex: number; data?: TData }> {\n return hotspots.filter((hotspot) => hotspot.frameIndex === frameIndex);\n}\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cn } from '@/components/utils';\n\nfunction Card({ className, size = 'default', ...props }: React.ComponentProps<'div'> & { size?: 'default' | 'sm' }): JSX.Element {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n 'ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-6 text-sm shadow-xs ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n 'gap-0.5 rounded-t-xl px-6 group-data-[size=sm]/card:px-4 [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-title\"\n className={cn('text-lg leading-normal font-semibold group-data-[size=sm]/card:text-sm', className)}\n {...props}\n />\n );\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"card-description\" className={cn('text-muted-foreground text-xs font-medium', className)} {...props} />;\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-action\"\n className={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className)}\n {...props}\n />\n );\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"card-content\" className={cn('px-6 group-data-[size=sm]/card:px-4', className)} {...props} />;\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n 'rounded-b-xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4 flex items-center',\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { cn } from '@/components/utils';\n\nconst badgeVariants = cva(\n 'h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',\n secondary: 'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',\n destructive:\n 'bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20',\n outline: 'border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',\n ghost: 'hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50',\n link: 'text-primary underline-offset-4 hover:underline',\n info: 'bg-blue-500 text-white hover:bg-blue-600',\n warning:\n 'rounded-full border-transparent bg-amber-500 px-2.5 text-white shadow-none [a]:hover:bg-amber-600 [&>svg]:text-white',\n success: 'bg-green-600 text-white hover:bg-green-700',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nfunction Badge({\n className,\n variant = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & { asChild?: boolean }): JSX.Element {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const Comp = asChild ? Slot.Root : 'span';\n\n return <Comp data-slot=\"badge\" data-variant={variant} className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n\nexport { Badge, badgeVariants };\n","import type { JSX } from 'react';\n\nimport { Badge } from '@/components/ui/Badge';\nimport { cn } from '@/components/utils';\n\ntype Viewer360AddModeBannerProps = {\n className?: string;\n label: string;\n};\n\nexport function Viewer360AddModeBanner({ className, label }: Viewer360AddModeBannerProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Badge variant=\"outline\" className={cn('pointer-events-none', className)}>\n {label}\n </Badge>\n );\n}\n","import type { JSX } from 'react';\n\nimport { Badge } from '@/components/ui/Badge';\nimport { cn } from '@/components/utils';\n\ntype Viewer360FrameIndicatorProps = {\n className?: string;\n label: string;\n};\n\nexport function Viewer360FrameIndicator({ className, label }: Viewer360FrameIndicatorProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Badge variant=\"outline\" className={cn('pointer-events-none shadow-sm', className)}>\n {label}\n </Badge>\n );\n}\n","import type { Viewer360Hotspot, Viewer360Marker } from '../types';\n\nexport function hotspotToViewer360Marker<TData>(hotspot: Viewer360Hotspot<TData>): Viewer360Marker {\n const data = hotspot.data;\n\n if (data && typeof data === 'object' && 'title' in data && typeof (data as { title?: unknown }).title === 'string') {\n const marker = data as unknown as Viewer360Marker;\n\n return {\n id: marker.id ?? hotspot.id,\n title: marker.title,\n description: marker.description,\n };\n }\n\n return {\n id: hotspot.id,\n title: hotspot.id,\n };\n}\n\nexport function toViewer360Hotspots<TData extends Viewer360Marker>(\n markers: Array<Viewer360Marker & { frameIndex: number; positionX: number; positionY: number }>,\n mapData?: (marker: Viewer360Marker & { frameIndex: number; positionX: number; positionY: number }) => TData\n): Viewer360Hotspot<TData>[] {\n return markers.map((marker) => ({\n id: marker.id,\n frameIndex: marker.frameIndex,\n positionX: marker.positionX,\n positionY: marker.positionY,\n data: mapData ? mapData(marker) : (marker as unknown as TData),\n }));\n}\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { Separator } from '@/components/ui/Separator';\nimport { cn } from '@/components/utils';\n\nfunction ItemGroup({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n role=\"list\"\n data-slot=\"item-group\"\n className={cn('gap-4 has-[[data-size=sm]]:gap-2.5 has-[[data-size=xs]]:gap-2 group/item-group flex w-full flex-col', className)}\n {...props}\n />\n );\n}\n\nfunction ItemSeparator({ className, ...props }: React.ComponentProps<typeof Separator>): JSX.Element {\n return <Separator data-slot=\"item-separator\" orientation=\"horizontal\" className={cn('my-2', className)} {...props} />;\n}\n\nconst itemVariants = cva(\n '[a]:hover:bg-muted rounded-md border text-sm w-full group/item focus-visible:border-ring focus-visible:ring-ring/50 flex items-center flex-wrap outline-none transition-colors duration-100 focus-visible:ring-[3px] [a]:transition-colors',\n {\n variants: {\n variant: {\n default: 'border-transparent',\n outline: 'border-border',\n muted: 'bg-muted/50 border-transparent',\n },\n size: {\n default: 'gap-3.5 px-4 py-3.5',\n sm: 'gap-2.5 px-3 py-2.5',\n xs: 'gap-2 px-2.5 py-2 [[data-slot=dropdown-menu-content]_&]:p-0',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nfunction Item({\n className,\n variant = 'default',\n size = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'div'> & VariantProps<typeof itemVariants> & { asChild?: boolean }): JSX.Element {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const Comp = asChild ? Slot.Root : 'div';\n return (\n <Comp\n data-slot=\"item\"\n data-variant={variant}\n data-size={size}\n className={cn(itemVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nconst itemMediaVariants = cva(\n 'gap-2 group-has-[[data-slot=item-description]]/item:translate-y-0.5 group-has-[[data-slot=item-description]]/item:self-start flex shrink-0 items-center justify-center [&_svg]:pointer-events-none',\n {\n variants: {\n variant: {\n default: 'bg-transparent',\n icon: '[&_svg]:size-4',\n image: 'size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nfunction ItemMedia({\n className,\n variant = 'default',\n ...props\n}: React.ComponentProps<'div'> & VariantProps<typeof itemMediaVariants>): JSX.Element {\n return <div data-slot=\"item-media\" data-variant={variant} className={cn(itemMediaVariants({ variant, className }))} {...props} />;\n}\n\nfunction ItemContent({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"item-content\"\n className={cn('gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none', className)}\n {...props}\n />\n );\n}\n\nfunction ItemTitle({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return (\n <div\n data-slot=\"item-title\"\n className={cn('gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center', className)}\n {...props}\n />\n );\n}\n\nfunction ItemDescription({ className, ...props }: React.ComponentProps<'p'>): JSX.Element {\n return (\n <p\n data-slot=\"item-description\"\n className={cn(\n 'text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction ItemActions({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"item-actions\" className={cn('gap-2 flex items-center', className)} {...props} />;\n}\n\nfunction ItemHeader({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"item-header\" className={cn('gap-2 flex basis-full items-center justify-between', className)} {...props} />;\n}\n\nfunction ItemFooter({ className, ...props }: React.ComponentProps<'div'>): JSX.Element {\n return <div data-slot=\"item-footer\" className={cn('gap-2 flex basis-full items-center justify-between', className)} {...props} />;\n}\n\nexport { Item, ItemMedia, ItemContent, ItemActions, ItemGroup, ItemSeparator, ItemTitle, ItemDescription, ItemHeader, ItemFooter };\n","'use client';\n\nimport * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { Separator as SeparatorPrimitive } from 'radix-ui';\n\nimport { cn } from '@/components/utils';\n\nfunction Separator({\n className,\n orientation = 'horizontal',\n decorative = true,\n ...props\n}: React.ComponentProps<typeof SeparatorPrimitive.Root>): JSX.Element {\n return (\n <SeparatorPrimitive.Root\n data-slot=\"separator\"\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch',\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Separator };\n","import type { JSX, MouseEvent } from 'react';\n\nimport { Trash2 } from 'lucide-react';\n\nimport { defaultViewer360MarkerPinLabels } from '../constants/viewer360MarkerLabels';\nimport { viewer360MarkerPinClassNames } from '../constants/viewer360ClassNames';\nimport type { Viewer360MarkerPinProps } from '../types';\nimport { Button } from '@/components/ui/Button';\nimport {\n Item,\n ItemActions,\n ItemContent,\n ItemDescription,\n ItemTitle,\n} from '@/components/ui/Item';\nimport { cn } from '@/components/utils';\n\nexport function Viewer360MarkerPin<TData = unknown>({\n marker,\n hotspot,\n leftPercent,\n topPercent,\n onDelete,\n isDeletePending = false,\n onClick,\n renderTag,\n classNames,\n labels,\n}: Viewer360MarkerPinProps<TData>): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: States & Constants\n // ----------------------------------------------------------------------------------------------------\n const deleteLabel = labels?.delete ?? defaultViewer360MarkerPinLabels.delete;\n const showTooltip = Boolean(marker.title || marker.description || onDelete || renderTag);\n\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <div\n className={cn(viewer360MarkerPinClassNames.root, classNames?.root, 'group/marker')}\n style={{ left: `${leftPercent}%`, top: `${topPercent}%` }}\n >\n <div className=\"relative size-4 shrink-0\">\n <span className={cn(viewer360MarkerPinClassNames.ping, classNames?.ping)} aria-hidden=\"true\" />\n\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"icon-xs\"\n className={cn(viewer360MarkerPinClassNames.dot, classNames?.dot, 'hover:bg-destructive')}\n aria-label={marker.title}\n onClick={onClick}\n />\n </div>\n\n {showTooltip && (\n <div\n className={cn(\n viewer360MarkerPinClassNames.tooltip,\n classNames?.tooltip,\n 'pointer-events-none opacity-0 transition-opacity duration-150 group-hover/marker:pointer-events-auto group-hover/marker:opacity-100 group-focus-within/marker:pointer-events-auto group-focus-within/marker:opacity-100'\n )}\n >\n <Item\n size=\"sm\"\n variant=\"default\"\n className={cn(viewer360MarkerPinClassNames.tooltipHeader, classNames?.tooltipHeader, 'w-full border-transparent')}\n >\n <ItemContent className={cn(viewer360MarkerPinClassNames.tooltipBody, classNames?.tooltipBody)}>\n <ItemTitle className={cn(viewer360MarkerPinClassNames.tooltipTitle, classNames?.tooltipTitle)}>\n {marker.title}\n </ItemTitle>\n {renderTag && (\n <div className=\"mt-1 flex w-fit items-center\">{renderTag({ marker, hotspot })}</div>\n )}\n {marker.description && (\n <ItemDescription className={cn(viewer360MarkerPinClassNames.tooltipDescription, classNames?.tooltipDescription)}>\n {marker.description}\n </ItemDescription>\n )}\n </ItemContent>\n {onDelete && (\n <ItemActions>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className={classNames?.deleteButton}\n disabled={isDeletePending}\n aria-label={deleteLabel}\n onClick={(event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n onDelete(marker.id);\n }}\n >\n <Trash2 className=\"size-4\" />\n </Button>\n </ItemActions>\n )}\n </Item>\n </div>\n )}\n </div>\n );\n}\n","export const defaultViewer360MarkerPinLabels = {\n delete: 'Remove marker',\n} as const;\n","import * as React from 'react';\nimport type { JSX } from 'react';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Slot } from 'radix-ui';\n\nimport { cn } from '@/components/utils';\n\nconst buttonVariants = cva(\n 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/80',\n outline:\n 'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground shadow-xs',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',\n ghost: 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',\n destructive:\n 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default:\n 'h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2',\n xs: 'h-6 gap-1 rounded-md px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',\n sm: 'h-8 gap-1 rounded-md px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',\n lg: 'h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pe-3 has-data-[icon=inline-start]:ps-3',\n icon: 'size-9',\n 'icon-xs': 'size-6 rounded-md in-data-[slot=button-group]:rounded-md',\n 'icon-sm': 'size-8 rounded-md in-data-[slot=button-group]:rounded-md',\n 'icon-lg': 'size-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nfunction Button({\n className,\n variant = 'default',\n size = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }): JSX.Element {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const Comp = asChild ? Slot.Root : 'button';\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","import type { JSX, MouseEvent, ReactNode } from 'react';\n\nimport { hotspotToViewer360Marker } from '../helpers/markerHelpers';\nimport type { Viewer360Hotspot, Viewer360HotspotPinOptions, Viewer360HotspotRenderProps } from '../types';\nimport { Item } from '@/components/ui/Item';\n\nimport { Viewer360MarkerPin } from './Viewer360MarkerPin';\n\ntype Viewer360HotspotOverlayProps<TData = unknown> = {\n hotspot: Viewer360Hotspot<TData>;\n leftPercent: number;\n topPercent: number;\n hotspotPin?: Viewer360HotspotPinOptions<TData>;\n renderHotspot?: (props: Viewer360HotspotRenderProps<TData>) => ReactNode;\n onHotspotClick?: (hotspot: Viewer360Hotspot<TData>, event: MouseEvent<HTMLDivElement>) => void;\n};\n\nexport function Viewer360HotspotOverlay<TData = unknown>({\n hotspot,\n leftPercent,\n topPercent,\n hotspotPin,\n renderHotspot,\n onHotspotClick,\n}: Viewer360HotspotOverlayProps<TData>): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n if (renderHotspot) {\n return (\n <Item size=\"xs\" variant=\"default\" className=\"pointer-events-auto w-auto border-transparent p-0\">\n {renderHotspot({ hotspot, leftPercent, topPercent })}\n </Item>\n );\n }\n\n const marker = hotspotPin?.getMarker?.(hotspot) ?? hotspotToViewer360Marker(hotspot);\n\n return (\n <Viewer360MarkerPin\n marker={marker}\n hotspot={hotspot}\n leftPercent={leftPercent}\n topPercent={topPercent}\n onDelete={hotspotPin?.onDelete}\n isDeletePending={hotspotPin?.deletingMarkerId === hotspot.id}\n renderTag={hotspotPin?.renderTag}\n classNames={hotspotPin?.classNames}\n labels={hotspotPin?.labels}\n onClick={\n onHotspotClick\n ? (event) => onHotspotClick(hotspot, event as unknown as MouseEvent<HTMLDivElement>)\n : undefined\n }\n />\n );\n}\n","'use client';\n\nimport * as React from 'react';\n\nimport { cn } from '@/components/utils';\n\nfunction Label({ className, ...props }: React.ComponentProps<'label'>): React.ReactNode {\n return (\n <label\n data-slot=\"label\"\n className={cn(\n 'gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed',\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Label };\n","import type { JSX } from 'react';\n\nimport { Loader2Icon } from 'lucide-react';\n\nimport { cn } from '@/components/utils';\n\nfunction Spinner({ className, ...props }: React.ComponentProps<'svg'>): JSX.Element {\n return <Loader2Icon role=\"status\" aria-label=\"Loading\" className={cn('size-4 animate-spin', className)} {...props} />;\n}\n\nexport { Spinner };\n","import type { JSX } from 'react';\n\nimport { Item } from '@/components/ui/Item';\nimport { Label } from '@/components/ui/Label';\nimport { Spinner } from '@/components/ui/Spinner';\nimport { cn } from '@/components/utils';\n\ntype Viewer360LoadingOverlayProps = {\n className?: string;\n textClassName?: string;\n label: string;\n};\n\nexport function Viewer360LoadingOverlay({ className, textClassName, label }: Viewer360LoadingOverlayProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <Item\n size=\"sm\"\n variant=\"muted\"\n className={cn('pointer-events-none w-auto justify-center border-transparent bg-muted/80', className)}\n >\n <Spinner className=\"size-5 text-muted-foreground\" />\n <Label className={cn('font-normal text-muted-foreground', textClassName)}>{label}</Label>\n </Item>\n );\n}\n","import type { JSX } from 'react';\n\nimport { Crosshair, Minus, Plus, RotateCcw, ZoomIn } from 'lucide-react';\n\nimport { viewer360ClassNames } from '../constants/viewer360ClassNames';\nimport type { Viewer360ToolbarRenderProps } from '../types';\nimport { Badge } from '@/components/ui/Badge';\nimport { Button } from '@/components/ui/Button';\nimport { CardFooter } from '@/components/ui/Card';\nimport { Label } from '@/components/ui/Label';\nimport { Separator } from '@/components/ui/Separator';\nimport { cn } from '@/components/utils';\n\ntype Viewer360ToolbarProps = Viewer360ToolbarRenderProps;\n\nexport function Viewer360Toolbar({\n showDragHint,\n showHotspotModeControl,\n showZoomControls,\n showResetControl,\n labels,\n isHotspotMode,\n zoom,\n minZoom,\n maxZoom,\n isResetDisabled,\n onHotspotModeChange,\n onZoomIn,\n onZoomOut,\n onResetView,\n}: Viewer360ToolbarProps): JSX.Element {\n // ----------------------------------------------------------------------------------------------------\n // MARK: Main Component UI\n // ----------------------------------------------------------------------------------------------------\n return (\n <CardFooter className={cn(viewer360ClassNames.toolbar, 'gap-2 border-t px-4 py-3 pt-3')}>\n {showDragHint && (\n <Label className={cn(viewer360ClassNames.dragHint, 'font-normal text-muted-foreground')}>{labels.dragHint}</Label>\n )}\n\n <div className={viewer360ClassNames.controls}>\n {showHotspotModeControl && (\n <>\n <Button variant={isHotspotMode ? 'default' : 'outline'} size=\"sm\" onClick={() => onHotspotModeChange(!isHotspotMode)}>\n <Crosshair className=\"me-1.5 size-4\" />\n {labels.addHotspot}\n </Button>\n <Separator orientation=\"vertical\" className={cn(viewer360ClassNames.divider, 'h-6')} />\n </>\n )}\n\n {showZoomControls && (\n <>\n <Button variant=\"outline\" size=\"icon-sm\" disabled={zoom <= minZoom} aria-label={labels.zoomOut} onClick={onZoomOut}>\n <Minus className=\"size-4\" />\n </Button>\n <Badge variant=\"outline\" className={cn(viewer360ClassNames.zoomDisplay, 'h-8 gap-1 px-2 py-1')}>\n <ZoomIn className=\"size-3 text-muted-foreground\" />\n {labels.zoom(Math.round(zoom * 100))}\n </Badge>\n <Button variant=\"outline\" size=\"icon-sm\" disabled={zoom >= maxZoom} aria-label={labels.zoomIn} onClick={onZoomIn}>\n <Plus className=\"size-4\" />\n </Button>\n </>\n )}\n\n {showResetControl && (\n <Button variant=\"outline\" size=\"icon-sm\" disabled={isResetDisabled} aria-label={labels.resetView} onClick={onResetView}>\n <RotateCcw className=\"size-4\" />\n </Button>\n )}\n </div>\n </CardFooter>\n );\n}\n","export const viewer360Config = {\n minZoom: 1,\n maxZoom: 3,\n zoomStep: 0.15,\n dragSensitivity: 8,\n autoRotate: false,\n autoRotateIntervalMs: 100,\n autoRotateDirection: 'forward' as const,\n};\n\nexport const defaultViewer360Config = viewer360Config;\n"],"mappings":"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","names":["useEffect","useMemo","useState","jsx","jsx","jsx","cva","Slot","jsx","jsx","cva","Slot","jsx","jsx","cva","Slot","jsx","cva","Slot","jsx","jsx","jsx","jsx","jsx","jsxs","jsx","jsxs","isResetDisabled","jsx","jsxs","useMemo","useState","isResetDisabled","useEffect"]}
@@ -2,9 +2,10 @@
2
2
 
3
3
  const STYLE_ID = "mmmmzxe-react-360-viewer-styles";
4
4
 
5
- const viewer360Styles = `@scope ([data-viewer-360]) {
5
+ const viewer360Styles = `@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}
6
+ @scope ([data-viewer-360]) {
6
7
  /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
7
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{[data-viewer-360]{--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-800:oklch(47.3% .137 46.201);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--leading-snug:1.375;--leading-normal:1.5;--radius-md:calc(var(--radius) - 2px);--radius-4xl:2rem;--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.\\@container\\/card-header{container:card-header/inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.start-1\\/2{inset-inline-start:50%}.top-4{top:calc(var(--spacing) * 4)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-6{bottom:calc(var(--spacing) * 6)}.left-1\\/2{left:50%}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.col-start-2{grid-column-start:2}.row-span-2{grid-row:span 2/span 2}.row-start-1{grid-row-start:1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-1{margin-inline:calc(var(--spacing) * 1)}.my-2{margin-block:calc(var(--spacing) * 2)}.ms-auto{margin-inline-start:auto}.me-1\\.5{margin-inline-end:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.aspect-\\[16\\/10\\]{aspect-ratio:16/10}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-full{width:100%;height:100%}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.min-h-4{min-height:calc(var(--spacing) * 4)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-\\[3rem\\]{min-width:3rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.origin-\\(--radix-popover-content-transform-origin\\){transform-origin:var(--radix-popover-content-transform-origin)}.-translate-x-1\\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-x-1\\/4{--tw-translate-x:calc(calc(1 / 4 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\\/4{--tw-translate-y:calc(calc(1 / 4 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-ping{animation:var(--animate-ping)}.animate-spin{animation:var(--animate-spin)}.cursor-crosshair{cursor:crosshair}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.touch-none{touch-action:none}.resize{resize:both}.auto-rows-min{grid-auto-rows:min-content}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing) * 0)}.gap-0\\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\\.5{gap:calc(var(--spacing) * 2.5)}.gap-3\\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.overflow-hidden{overflow:hidden}.rounded-4xl{border-radius:var(--radius-4xl)}.rounded-\\[min\\(var\\(--radius-md\\)\\,8px\\)\\]{border-radius:min(var(--radius-md), 8px)}.rounded-\\[min\\(var\\(--radius-md\\)\\,10px\\)\\]{border-radius:min(var(--radius-md), 10px)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-t-xl{border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}.rounded-b-xl{border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-amber-200{border-color:var(--color-amber-200)}.border-background{border-color:var(--background)}.border-border{border-color:var(--border)}.border-transparent{border-color:#0000}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-background{background-color:var(--background)}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive,.bg-destructive\\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\\/10{background-color:color-mix(in oklab, var(--destructive) 10%, transparent)}}.bg-green-600{background-color:var(--color-green-600)}.bg-muted,.bg-muted\\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/50{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.bg-muted\\/80{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/80{background-color:color-mix(in oklab, var(--muted) 80%, transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-clip-padding{background-clip:padding-box}.p-0{padding:calc(var(--spacing) * 0)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\\.5{padding-block:calc(var(--spacing) * 3.5)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-3{padding-top:calc(var(--spacing) * 3)}.text-left{text-align:left}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-amber-800{color:var(--color-amber-800)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-60{opacity:.6}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-foreground\\/10{--tw-ring-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\\/10{--tw-ring-color:color-mix(in oklab, var(--foreground) 10%, transparent)}}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.group-focus-within\\/marker\\:pointer-events-auto:is(:where(.group\\/marker):focus-within *){pointer-events:auto}.group-focus-within\\/marker\\:opacity-100:is(:where(.group\\/marker):focus-within *){opacity:1}@media (hover:hover){.group-hover\\/marker\\:pointer-events-auto:is(:where(.group\\/marker):hover *){pointer-events:auto}.group-hover\\/marker\\:opacity-100:is(:where(.group\\/marker):hover *){opacity:1}}.group-has-\\[\\[data-slot\\=item-description\\]\\]\\/item\\:translate-y-0\\.5:is(:where(.group\\/item):has([data-slot=item-description]) *){--tw-translate-y:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-has-\\[\\[data-slot\\=item-description\\]\\]\\/item\\:self-start:is(:where(.group\\/item):has([data-slot=item-description]) *){align-self:flex-start}.group-data-\\[disabled\\=true\\]\\:pointer-events-none:is(:where(.group)[data-disabled=true] *){pointer-events:none}.group-data-\\[disabled\\=true\\]\\:opacity-50:is(:where(.group)[data-disabled=true] *){opacity:.5}.group-data-\\[size\\=sm\\]\\/card\\:px-4:is(:where(.group\\/card)[data-size=sm] *){padding-inline:calc(var(--spacing) * 4)}.group-data-\\[size\\=sm\\]\\/card\\:text-sm:is(:where(.group\\/card)[data-size=sm] *){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.group-data-\\[size\\=sm\\]\\/item\\:size-8:is(:where(.group\\/item)[data-size=sm] *){width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.group-data-\\[size\\=xs\\]\\/item\\:size-6:is(:where(.group\\/item)[data-size=xs] *){width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.group-data-\\[size\\=xs\\]\\/item\\:gap-0:is(:where(.group\\/item)[data-size=xs] *){gap:calc(var(--spacing) * 0)}.group-data-\\[size\\=xs\\]\\/item\\:text-xs:is(:where(.group\\/item)[data-size=xs] *){font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.peer-disabled\\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\\:opacity-50:is(:where(.peer):disabled~*){opacity:.5}@media (hover:hover){.hover\\:scale-125:hover{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\\:bg-amber-600:hover{background-color:var(--color-amber-600)}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-destructive:hover,.hover\\:bg-destructive\\/20:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/20:hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.hover\\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\\:bg-muted:hover{background-color:var(--muted)}.hover\\:bg-primary\\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/80:hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.hover\\:bg-secondary\\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-secondary\\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\\:text-foreground:hover{color:var(--foreground)}.hover\\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\\:underline:hover{text-decoration-line:underline}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:border-destructive\\/40:focus-visible{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:border-destructive\\/40:focus-visible{border-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.focus-visible\\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\\:ring-\\[3px\\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:opacity-50:disabled{opacity:.5}:where([data-slot=button-group]) .in-data-\\[slot\\=button-group\\]\\:rounded-md{border-radius:calc(var(--radius) - 2px)}.has-data-\\[icon\\=inline-end\\]\\:pe-1\\.5:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 1.5)}.has-data-\\[icon\\=inline-end\\]\\:pe-2:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 2)}.has-data-\\[icon\\=inline-end\\]\\:pe-3:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 3)}.has-data-\\[icon\\=inline-start\\]\\:ps-1\\.5:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 1.5)}.has-data-\\[icon\\=inline-start\\]\\:ps-2:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 2)}.has-data-\\[icon\\=inline-start\\]\\:ps-3:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 3)}.has-data-\\[slot\\=card-action\\]\\:grid-cols-\\[1fr_auto\\]:has([data-slot=card-action]){grid-template-columns:1fr auto}.has-data-\\[slot\\=card-description\\]\\:grid-rows-\\[auto_auto\\]:has([data-slot=card-description]){grid-template-rows:auto auto}.has-\\[\\[data-size\\=sm\\]\\]\\:gap-2\\.5:has([data-size=sm]){gap:calc(var(--spacing) * 2.5)}.has-\\[\\[data-size\\=xs\\]\\]\\:gap-2:has([data-size=xs]){gap:calc(var(--spacing) * 2)}.has-\\[\\>img\\:first-child\\]\\:pt-0:has(>img:first-child){padding-top:calc(var(--spacing) * 0)}.aria-expanded\\:bg-muted[aria-expanded=true]{background-color:var(--muted)}.aria-expanded\\:bg-secondary[aria-expanded=true]{background-color:var(--secondary)}.aria-expanded\\:text-foreground[aria-expanded=true]{color:var(--foreground)}.aria-expanded\\:text-secondary-foreground[aria-expanded=true]{color:var(--secondary-foreground)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\\:ring-\\[3px\\][aria-invalid=true]{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.data-\\[orientation\\=horizontal\\]\\:h-px[data-orientation=horizontal]{height:1px}.data-\\[orientation\\=horizontal\\]\\:w-full[data-orientation=horizontal]{width:100%}.data-\\[orientation\\=vertical\\]\\:w-px[data-orientation=vertical]{width:1px}.data-\\[orientation\\=vertical\\]\\:self-stretch[data-orientation=vertical]{align-self:stretch}.data-\\[size\\=sm\\]\\:gap-4[data-size=sm]{gap:calc(var(--spacing) * 4)}.data-\\[size\\=sm\\]\\:py-4[data-size=sm]{padding-block:calc(var(--spacing) * 4)}@media (min-width:40rem){.sm\\:block{display:block}}.dark\\:border-amber-500\\/30:is(.dark *){border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.dark\\:border-amber-500\\/30:is(.dark *){border-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.dark\\:border-input:is(.dark *){border-color:var(--input)}.dark\\:bg-amber-500\\/10:is(.dark *){background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-amber-500\\/10:is(.dark *){background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.dark\\:bg-destructive\\/20:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-destructive\\/20:is(.dark *){background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.dark\\:bg-input\\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-input\\/30:is(.dark *){background-color:color-mix(in oklab, var(--input) 30%, transparent)}}.dark\\:text-amber-400:is(.dark *){color:var(--color-amber-400)}@media (hover:hover){.dark\\:hover\\:bg-destructive\\/30:is(.dark *):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-destructive\\/30:is(.dark *):hover{background-color:color-mix(in oklab, var(--destructive) 30%, transparent)}}.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}.dark\\:hover\\:bg-muted\\/50:is(.dark *):hover{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-muted\\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}}.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\\:aria-invalid\\:border-destructive\\/50:is(.dark *)[aria-invalid=true]{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:aria-invalid\\:border-destructive\\/50:is(.dark *)[aria-invalid=true]{border-color:color-mix(in oklab, var(--destructive) 50%, transparent)}}.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.\\[\\&_img\\]\\:size-full img{width:100%;height:100%}.\\[\\&_img\\]\\:object-cover img{object-fit:cover}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&\\+\\[data-slot\\=item-content\\]\\]\\:flex-none+[data-slot=item-content]{flex:none}.\\[\\.border-b\\]\\:pb-6.border-b{padding-bottom:calc(var(--spacing) * 6)}.group-data-\\[size\\=sm\\]\\/card\\:\\[\\.border-b\\]\\:pb-4:is(:where(.group\\/card)[data-size=sm] *).border-b{padding-bottom:calc(var(--spacing) * 4)}.\\[\\.border-t\\]\\:pt-6.border-t{padding-top:calc(var(--spacing) * 6)}.group-data-\\[size\\=sm\\]\\/card\\:\\[\\.border-t\\]\\:pt-4:is(:where(.group\\/card)[data-size=sm] *).border-t{padding-top:calc(var(--spacing) * 4)}.\\[a\\]\\:transition-colors:is(a){transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.\\[a\\]\\:hover\\:bg-destructive\\/20:is(a):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.\\[a\\]\\:hover\\:bg-destructive\\/20:is(a):hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.\\[a\\]\\:hover\\:bg-muted:is(a):hover{background-color:var(--muted)}.\\[a\\]\\:hover\\:bg-primary\\/80:is(a):hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.\\[a\\]\\:hover\\:bg-primary\\/80:is(a):hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.\\[a\\]\\:hover\\:bg-secondary\\/80:is(a):hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.\\[a\\]\\:hover\\:bg-secondary\\/80:is(a):hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.\\[a\\]\\:hover\\:text-muted-foreground:is(a):hover{color:var(--muted-foreground)}}:is(.\\*\\:\\[img\\:first-child\\]\\:rounded-t-xl>*):is(img:first-child){border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}:is(.\\*\\:\\[img\\:last-child\\]\\:rounded-b-xl>*):is(img:last-child){border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.\\[\\&\\>a\\]\\:underline>a{text-decoration-line:underline}.\\[\\&\\>a\\]\\:underline-offset-4>a{text-underline-offset:4px}.\\[\\&\\>a\\:hover\\]\\:text-primary>a:hover{color:var(--primary)}.\\[\\&\\>svg\\]\\:pointer-events-none>svg{pointer-events:none}.\\[\\&\\>svg\\]\\:size-3\\!>svg{width:calc(var(--spacing) * 3)!important;height:calc(var(--spacing) * 3)!important}[data-slot=dropdown-menu-content] .\\[\\[data-slot\\=dropdown-menu-content\\]_\\&\\]\\:p-0{padding:calc(var(--spacing) * 0)}}[data-viewer-360]{--radius:.625rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0)}.dark [data-viewer-360]{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}
8
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{[data-viewer-360]{--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-800:oklch(47.3% .137 46.201);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--leading-snug:1.375;--leading-normal:1.5;--radius-4xl:2rem;--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.\\@container\\/card-header{container:card-header/inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.start-1\\/2{inset-inline-start:50%}.top-4{top:calc(var(--spacing) * 4)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-6{bottom:calc(var(--spacing) * 6)}.left-1\\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.col-start-2{grid-column-start:2}.row-span-2{grid-row:span 2/span 2}.row-start-1{grid-row-start:1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-1{margin-inline:calc(var(--spacing) * 1)}.my-2{margin-block:calc(var(--spacing) * 2)}.ms-auto{margin-inline-start:auto}.me-1\\.5{margin-inline-end:calc(var(--spacing) * 1.5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.aspect-\\[16\\/10\\]{aspect-ratio:16/10}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-full{width:100%;height:100%}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.min-h-4{min-height:calc(var(--spacing) * 4)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-\\[3rem\\]{min-width:3rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.origin-\\(--radix-popover-content-transform-origin\\){transform-origin:var(--radix-popover-content-transform-origin)}.-translate-x-1\\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-ping{animation:var(--animate-ping)}.animate-spin{animation:var(--animate-spin)}.cursor-crosshair{cursor:crosshair}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.touch-none{touch-action:none}.resize{resize:both}.auto-rows-min{grid-auto-rows:min-content}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing) * 0)}.gap-0\\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\\.5{gap:calc(var(--spacing) * 2.5)}.gap-3\\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-t-xl{border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}.rounded-b-xl{border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-amber-200{border-color:var(--color-amber-200)}.border-background{border-color:var(--background)}.border-border{border-color:var(--border)}.border-transparent{border-color:#0000}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-background{background-color:var(--background)}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive,.bg-destructive\\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\\/10{background-color:color-mix(in oklab, var(--destructive) 10%, transparent)}}.bg-green-600{background-color:var(--color-green-600)}.bg-muted,.bg-muted\\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/50{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.bg-muted\\/80{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/80{background-color:color-mix(in oklab, var(--muted) 80%, transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-clip-padding{background-clip:padding-box}.p-0{padding:calc(var(--spacing) * 0)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\\.5{padding-block:calc(var(--spacing) * 3.5)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-3{padding-top:calc(var(--spacing) * 3)}.text-left{text-align:left}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-amber-800{color:var(--color-amber-800)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-75{opacity:.75}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-foreground\\/10{--tw-ring-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\\/10{--tw-ring-color:color-mix(in oklab, var(--foreground) 10%, transparent)}}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.group-focus-within\\/marker\\:pointer-events-auto:is(:where(.group\\/marker):focus-within *){pointer-events:auto}.group-focus-within\\/marker\\:opacity-100:is(:where(.group\\/marker):focus-within *){opacity:1}@media (hover:hover){.group-hover\\/marker\\:pointer-events-auto:is(:where(.group\\/marker):hover *){pointer-events:auto}.group-hover\\/marker\\:opacity-100:is(:where(.group\\/marker):hover *){opacity:1}}.group-has-\\[\\[data-slot\\=item-description\\]\\]\\/item\\:translate-y-0\\.5:is(:where(.group\\/item):has([data-slot=item-description]) *){--tw-translate-y:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-has-\\[\\[data-slot\\=item-description\\]\\]\\/item\\:self-start:is(:where(.group\\/item):has([data-slot=item-description]) *){align-self:flex-start}.group-data-\\[disabled\\=true\\]\\:pointer-events-none:is(:where(.group)[data-disabled=true] *){pointer-events:none}.group-data-\\[disabled\\=true\\]\\:opacity-50:is(:where(.group)[data-disabled=true] *){opacity:.5}.group-data-\\[size\\=sm\\]\\/card\\:px-4:is(:where(.group\\/card)[data-size=sm] *){padding-inline:calc(var(--spacing) * 4)}.group-data-\\[size\\=sm\\]\\/card\\:text-sm:is(:where(.group\\/card)[data-size=sm] *){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.group-data-\\[size\\=sm\\]\\/item\\:size-8:is(:where(.group\\/item)[data-size=sm] *){width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.group-data-\\[size\\=xs\\]\\/item\\:size-6:is(:where(.group\\/item)[data-size=xs] *){width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.group-data-\\[size\\=xs\\]\\/item\\:gap-0:is(:where(.group\\/item)[data-size=xs] *){gap:calc(var(--spacing) * 0)}.group-data-\\[size\\=xs\\]\\/item\\:text-xs:is(:where(.group\\/item)[data-size=xs] *){font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.peer-disabled\\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\\:opacity-50:is(:where(.peer):disabled~*){opacity:.5}@media (hover:hover){.hover\\:scale-125:hover{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-destructive:hover,.hover\\:bg-destructive\\/20:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/20:hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.hover\\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\\:bg-muted:hover{background-color:var(--muted)}.hover\\:bg-primary\\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/80:hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.hover\\:bg-secondary\\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-secondary\\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\\:text-foreground:hover{color:var(--foreground)}.hover\\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\\:underline:hover{text-decoration-line:underline}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:border-destructive\\/40:focus-visible{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:border-destructive\\/40:focus-visible{border-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.focus-visible\\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\\:ring-\\[3px\\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:opacity-50:disabled{opacity:.5}:where([data-slot=button-group]) .in-data-\\[slot\\=button-group\\]\\:rounded-md{border-radius:calc(var(--radius) - 2px)}.has-data-\\[icon\\=inline-end\\]\\:pe-1\\.5:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 1.5)}.has-data-\\[icon\\=inline-end\\]\\:pe-2:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 2)}.has-data-\\[icon\\=inline-end\\]\\:pe-3:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 3)}.has-data-\\[icon\\=inline-start\\]\\:ps-1\\.5:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 1.5)}.has-data-\\[icon\\=inline-start\\]\\:ps-2:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 2)}.has-data-\\[icon\\=inline-start\\]\\:ps-3:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 3)}.has-data-\\[slot\\=card-action\\]\\:grid-cols-\\[1fr_auto\\]:has([data-slot=card-action]){grid-template-columns:1fr auto}.has-data-\\[slot\\=card-description\\]\\:grid-rows-\\[auto_auto\\]:has([data-slot=card-description]){grid-template-rows:auto auto}.has-\\[\\[data-size\\=sm\\]\\]\\:gap-2\\.5:has([data-size=sm]){gap:calc(var(--spacing) * 2.5)}.has-\\[\\[data-size\\=xs\\]\\]\\:gap-2:has([data-size=xs]){gap:calc(var(--spacing) * 2)}.has-\\[\\>img\\:first-child\\]\\:pt-0:has(>img:first-child){padding-top:calc(var(--spacing) * 0)}.aria-expanded\\:bg-muted[aria-expanded=true]{background-color:var(--muted)}.aria-expanded\\:bg-secondary[aria-expanded=true]{background-color:var(--secondary)}.aria-expanded\\:text-foreground[aria-expanded=true]{color:var(--foreground)}.aria-expanded\\:text-secondary-foreground[aria-expanded=true]{color:var(--secondary-foreground)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\\:ring-\\[3px\\][aria-invalid=true]{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.data-\\[orientation\\=horizontal\\]\\:h-px[data-orientation=horizontal]{height:1px}.data-\\[orientation\\=horizontal\\]\\:w-full[data-orientation=horizontal]{width:100%}.data-\\[orientation\\=vertical\\]\\:w-px[data-orientation=vertical]{width:1px}.data-\\[orientation\\=vertical\\]\\:self-stretch[data-orientation=vertical]{align-self:stretch}.data-\\[size\\=sm\\]\\:gap-4[data-size=sm]{gap:calc(var(--spacing) * 4)}.data-\\[size\\=sm\\]\\:py-4[data-size=sm]{padding-block:calc(var(--spacing) * 4)}@media (min-width:40rem){.sm\\:block{display:block}}.dark\\:border-amber-500\\/30:is(.dark *){border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.dark\\:border-amber-500\\/30:is(.dark *){border-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.dark\\:border-input:is(.dark *){border-color:var(--input)}.dark\\:bg-amber-500\\/10:is(.dark *){background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-amber-500\\/10:is(.dark *){background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.dark\\:bg-destructive\\/20:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-destructive\\/20:is(.dark *){background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.dark\\:bg-input\\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-input\\/30:is(.dark *){background-color:color-mix(in oklab, var(--input) 30%, transparent)}}.dark\\:text-amber-400:is(.dark *){color:var(--color-amber-400)}@media (hover:hover){.dark\\:hover\\:bg-destructive\\/30:is(.dark *):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-destructive\\/30:is(.dark *):hover{background-color:color-mix(in oklab, var(--destructive) 30%, transparent)}}.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}.dark\\:hover\\:bg-muted\\/50:is(.dark *):hover{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-muted\\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}}.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\\:aria-invalid\\:border-destructive\\/50:is(.dark *)[aria-invalid=true]{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:aria-invalid\\:border-destructive\\/50:is(.dark *)[aria-invalid=true]{border-color:color-mix(in oklab, var(--destructive) 50%, transparent)}}.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.\\[\\&_img\\]\\:size-full img{width:100%;height:100%}.\\[\\&_img\\]\\:object-cover img{object-fit:cover}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&\\+\\[data-slot\\=item-content\\]\\]\\:flex-none+[data-slot=item-content]{flex:none}.\\[\\.border-b\\]\\:pb-6.border-b{padding-bottom:calc(var(--spacing) * 6)}.group-data-\\[size\\=sm\\]\\/card\\:\\[\\.border-b\\]\\:pb-4:is(:where(.group\\/card)[data-size=sm] *).border-b{padding-bottom:calc(var(--spacing) * 4)}.\\[\\.border-t\\]\\:pt-6.border-t{padding-top:calc(var(--spacing) * 6)}.group-data-\\[size\\=sm\\]\\/card\\:\\[\\.border-t\\]\\:pt-4:is(:where(.group\\/card)[data-size=sm] *).border-t{padding-top:calc(var(--spacing) * 4)}.\\[a\\]\\:transition-colors:is(a){transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.\\[a\\]\\:hover\\:bg-amber-600:is(a):hover{background-color:var(--color-amber-600)}.\\[a\\]\\:hover\\:bg-destructive\\/20:is(a):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.\\[a\\]\\:hover\\:bg-destructive\\/20:is(a):hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.\\[a\\]\\:hover\\:bg-muted:is(a):hover{background-color:var(--muted)}.\\[a\\]\\:hover\\:bg-primary\\/80:is(a):hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.\\[a\\]\\:hover\\:bg-primary\\/80:is(a):hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.\\[a\\]\\:hover\\:bg-secondary\\/80:is(a):hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.\\[a\\]\\:hover\\:bg-secondary\\/80:is(a):hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.\\[a\\]\\:hover\\:text-muted-foreground:is(a):hover{color:var(--muted-foreground)}}:is(.\\*\\:\\[img\\:first-child\\]\\:rounded-t-xl>*):is(img:first-child){border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}:is(.\\*\\:\\[img\\:last-child\\]\\:rounded-b-xl>*):is(img:last-child){border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.\\[\\&\\>a\\]\\:underline>a{text-decoration-line:underline}.\\[\\&\\>a\\]\\:underline-offset-4>a{text-underline-offset:4px}.\\[\\&\\>a\\:hover\\]\\:text-primary>a:hover{color:var(--primary)}.\\[\\&\\>svg\\]\\:pointer-events-none>svg{pointer-events:none}.\\[\\&\\>svg\\]\\:size-3\\!>svg{width:calc(var(--spacing) * 3)!important;height:calc(var(--spacing) * 3)!important}.\\[\\&\\>svg\\]\\:text-white>svg{color:var(--color-white)}[data-slot=dropdown-menu-content] .\\[\\[data-slot\\=dropdown-menu-content\\]_\\&\\]\\:p-0{padding:calc(var(--spacing) * 0)}}[data-viewer-360]{--radius:.625rem;--radius-4xl:2rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0)}.dark [data-viewer-360]{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}
8
9
  }`;
9
10
 
10
11
  export function injectViewer360Styles() {
package/dist/styles.css CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-800:oklch(47.3% .137 46.201);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--leading-snug:1.375;--leading-normal:1.5;--radius-md:calc(var(--radius) - 2px);--radius-4xl:2rem;--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.\@container\/card-header{container:card-header/inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.start-1\/2{inset-inline-start:50%}.top-4{top:calc(var(--spacing) * 4)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-6{bottom:calc(var(--spacing) * 6)}.left-1\/2{left:50%}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.col-start-2{grid-column-start:2}.row-span-2{grid-row:span 2/span 2}.row-start-1{grid-row-start:1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-1{margin-inline:calc(var(--spacing) * 1)}.my-2{margin-block:calc(var(--spacing) * 2)}.ms-auto{margin-inline-start:auto}.me-1\.5{margin-inline-end:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.aspect-\[16\/10\]{aspect-ratio:16/10}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-full{width:100%;height:100%}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.min-h-4{min-height:calc(var(--spacing) * 4)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-\[3rem\]{min-width:3rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.origin-\(--radix-popover-content-transform-origin\){transform-origin:var(--radix-popover-content-transform-origin)}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-x-1\/4{--tw-translate-x:calc(calc(1 / 4 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/4{--tw-translate-y:calc(calc(1 / 4 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-ping{animation:var(--animate-ping)}.animate-spin{animation:var(--animate-spin)}.cursor-crosshair{cursor:crosshair}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.touch-none{touch-action:none}.resize{resize:both}.auto-rows-min{grid-auto-rows:min-content}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing) * 0)}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.overflow-hidden{overflow:hidden}.rounded-4xl{border-radius:var(--radius-4xl)}.rounded-\[min\(var\(--radius-md\)\,8px\)\]{border-radius:min(var(--radius-md), 8px)}.rounded-\[min\(var\(--radius-md\)\,10px\)\]{border-radius:min(var(--radius-md), 10px)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-t-xl{border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}.rounded-b-xl{border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-amber-200{border-color:var(--color-amber-200)}.border-background{border-color:var(--background)}.border-border{border-color:var(--border)}.border-transparent{border-color:#0000}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-background{background-color:var(--background)}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive,.bg-destructive\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\/10{background-color:color-mix(in oklab, var(--destructive) 10%, transparent)}}.bg-green-600{background-color:var(--color-green-600)}.bg-muted,.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.bg-muted\/80{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/80{background-color:color-mix(in oklab, var(--muted) 80%, transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-clip-padding{background-clip:padding-box}.p-0{padding:calc(var(--spacing) * 0)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-3{padding-top:calc(var(--spacing) * 3)}.text-left{text-align:left}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-amber-800{color:var(--color-amber-800)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-60{opacity:.6}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-foreground\/10{--tw-ring-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\/10{--tw-ring-color:color-mix(in oklab, var(--foreground) 10%, transparent)}}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.group-focus-within\/marker\:pointer-events-auto:is(:where(.group\/marker):focus-within *){pointer-events:auto}.group-focus-within\/marker\:opacity-100:is(:where(.group\/marker):focus-within *){opacity:1}@media (hover:hover){.group-hover\/marker\:pointer-events-auto:is(:where(.group\/marker):hover *){pointer-events:auto}.group-hover\/marker\:opacity-100:is(:where(.group\/marker):hover *){opacity:1}}.group-has-\[\[data-slot\=item-description\]\]\/item\:translate-y-0\.5:is(:where(.group\/item):has([data-slot=item-description]) *){--tw-translate-y:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-has-\[\[data-slot\=item-description\]\]\/item\:self-start:is(:where(.group\/item):has([data-slot=item-description]) *){align-self:flex-start}.group-data-\[disabled\=true\]\:pointer-events-none:is(:where(.group)[data-disabled=true] *){pointer-events:none}.group-data-\[disabled\=true\]\:opacity-50:is(:where(.group)[data-disabled=true] *){opacity:.5}.group-data-\[size\=sm\]\/card\:px-4:is(:where(.group\/card)[data-size=sm] *){padding-inline:calc(var(--spacing) * 4)}.group-data-\[size\=sm\]\/card\:text-sm:is(:where(.group\/card)[data-size=sm] *){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.group-data-\[size\=sm\]\/item\:size-8:is(:where(.group\/item)[data-size=sm] *){width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.group-data-\[size\=xs\]\/item\:size-6:is(:where(.group\/item)[data-size=xs] *){width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.group-data-\[size\=xs\]\/item\:gap-0:is(:where(.group\/item)[data-size=xs] *){gap:calc(var(--spacing) * 0)}.group-data-\[size\=xs\]\/item\:text-xs:is(:where(.group\/item)[data-size=xs] *){font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-50:is(:where(.peer):disabled~*){opacity:.5}@media (hover:hover){.hover\:scale-125:hover{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:bg-amber-600:hover{background-color:var(--color-amber-600)}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-destructive:hover,.hover\:bg-destructive\/20:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/20:hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-muted:hover{background-color:var(--muted)}.hover\:bg-primary\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/80:hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:border-destructive\/40:focus-visible{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:border-destructive\/40:focus-visible{border-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}:where([data-slot=button-group]) .in-data-\[slot\=button-group\]\:rounded-md{border-radius:calc(var(--radius) - 2px)}.has-data-\[icon\=inline-end\]\:pe-1\.5:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 1.5)}.has-data-\[icon\=inline-end\]\:pe-2:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 2)}.has-data-\[icon\=inline-end\]\:pe-3:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 3)}.has-data-\[icon\=inline-start\]\:ps-1\.5:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 1.5)}.has-data-\[icon\=inline-start\]\:ps-2:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 2)}.has-data-\[icon\=inline-start\]\:ps-3:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 3)}.has-data-\[slot\=card-action\]\:grid-cols-\[1fr_auto\]:has([data-slot=card-action]){grid-template-columns:1fr auto}.has-data-\[slot\=card-description\]\:grid-rows-\[auto_auto\]:has([data-slot=card-description]){grid-template-rows:auto auto}.has-\[\[data-size\=sm\]\]\:gap-2\.5:has([data-size=sm]){gap:calc(var(--spacing) * 2.5)}.has-\[\[data-size\=xs\]\]\:gap-2:has([data-size=xs]){gap:calc(var(--spacing) * 2)}.has-\[\>img\:first-child\]\:pt-0:has(>img:first-child){padding-top:calc(var(--spacing) * 0)}.aria-expanded\:bg-muted[aria-expanded=true]{background-color:var(--muted)}.aria-expanded\:bg-secondary[aria-expanded=true]{background-color:var(--secondary)}.aria-expanded\:text-foreground[aria-expanded=true]{color:var(--foreground)}.aria-expanded\:text-secondary-foreground[aria-expanded=true]{color:var(--secondary-foreground)}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\:ring-\[3px\][aria-invalid=true]{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.data-\[orientation\=horizontal\]\:h-px[data-orientation=horizontal]{height:1px}.data-\[orientation\=horizontal\]\:w-full[data-orientation=horizontal]{width:100%}.data-\[orientation\=vertical\]\:w-px[data-orientation=vertical]{width:1px}.data-\[orientation\=vertical\]\:self-stretch[data-orientation=vertical]{align-self:stretch}.data-\[size\=sm\]\:gap-4[data-size=sm]{gap:calc(var(--spacing) * 4)}.data-\[size\=sm\]\:py-4[data-size=sm]{padding-block:calc(var(--spacing) * 4)}@media (min-width:40rem){.sm\:block{display:block}}.dark\:border-amber-500\/30:is(.dark *){border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.dark\:border-amber-500\/30:is(.dark *){border-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.dark\:border-input:is(.dark *){border-color:var(--input)}.dark\:bg-amber-500\/10:is(.dark *){background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-500\/10:is(.dark *){background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.dark\:bg-destructive\/20:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-destructive\/20:is(.dark *){background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.dark\:bg-input\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-input\/30:is(.dark *){background-color:color-mix(in oklab, var(--input) 30%, transparent)}}.dark\:text-amber-400:is(.dark *){color:var(--color-amber-400)}@media (hover:hover){.dark\:hover\:bg-destructive\/30:is(.dark *):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-destructive\/30:is(.dark *):hover{background-color:color-mix(in oklab, var(--destructive) 30%, transparent)}}.dark\:hover\:bg-input\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-input\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}.dark\:hover\:bg-muted\/50:is(.dark *):hover{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-muted\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}}.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:aria-invalid\:border-destructive\/50:is(.dark *)[aria-invalid=true]{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:border-destructive\/50:is(.dark *)[aria-invalid=true]{border-color:color-mix(in oklab, var(--destructive) 50%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.\[\&_img\]\:size-full img{width:100%;height:100%}.\[\&_img\]\:object-cover img{object-fit:cover}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&\+\[data-slot\=item-content\]\]\:flex-none+[data-slot=item-content]{flex:none}.\[\.border-b\]\:pb-6.border-b{padding-bottom:calc(var(--spacing) * 6)}.group-data-\[size\=sm\]\/card\:\[\.border-b\]\:pb-4:is(:where(.group\/card)[data-size=sm] *).border-b{padding-bottom:calc(var(--spacing) * 4)}.\[\.border-t\]\:pt-6.border-t{padding-top:calc(var(--spacing) * 6)}.group-data-\[size\=sm\]\/card\:\[\.border-t\]\:pt-4:is(:where(.group\/card)[data-size=sm] *).border-t{padding-top:calc(var(--spacing) * 4)}.\[a\]\:transition-colors:is(a){transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.\[a\]\:hover\:bg-destructive\/20:is(a):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-destructive\/20:is(a):hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.\[a\]\:hover\:bg-muted:is(a):hover{background-color:var(--muted)}.\[a\]\:hover\:bg-primary\/80:is(a):hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-primary\/80:is(a):hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.\[a\]\:hover\:bg-secondary\/80:is(a):hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-secondary\/80:is(a):hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.\[a\]\:hover\:text-muted-foreground:is(a):hover{color:var(--muted-foreground)}}:is(.\*\:\[img\:first-child\]\:rounded-t-xl>*):is(img:first-child){border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}:is(.\*\:\[img\:last-child\]\:rounded-b-xl>*):is(img:last-child){border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.\[\&\>a\]\:underline>a{text-decoration-line:underline}.\[\&\>a\]\:underline-offset-4>a{text-underline-offset:4px}.\[\&\>a\:hover\]\:text-primary>a:hover{color:var(--primary)}.\[\&\>svg\]\:pointer-events-none>svg{pointer-events:none}.\[\&\>svg\]\:size-3\!>svg{width:calc(var(--spacing) * 3)!important;height:calc(var(--spacing) * 3)!important}[data-slot=dropdown-menu-content] .\[\[data-slot\=dropdown-menu-content\]_\&\]\:p-0{padding:calc(var(--spacing) * 0)}}[data-viewer-360]{--radius:.625rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0)}.dark [data-viewer-360]{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-800:oklch(47.3% .137 46.201);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--leading-snug:1.375;--leading-normal:1.5;--radius-4xl:2rem;--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.\@container\/card-header{container:card-header/inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.start-1\/2{inset-inline-start:50%}.top-4{top:calc(var(--spacing) * 4)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-6{bottom:calc(var(--spacing) * 6)}.left-1\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.col-start-2{grid-column-start:2}.row-span-2{grid-row:span 2/span 2}.row-start-1{grid-row-start:1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-1{margin-inline:calc(var(--spacing) * 1)}.my-2{margin-block:calc(var(--spacing) * 2)}.ms-auto{margin-inline-start:auto}.me-1\.5{margin-inline-end:calc(var(--spacing) * 1.5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.aspect-\[16\/10\]{aspect-ratio:16/10}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-full{width:100%;height:100%}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.min-h-4{min-height:calc(var(--spacing) * 4)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-\[3rem\]{min-width:3rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.basis-full{flex-basis:100%}.origin-\(--radix-popover-content-transform-origin\){transform-origin:var(--radix-popover-content-transform-origin)}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-ping{animation:var(--animate-ping)}.animate-spin{animation:var(--animate-spin)}.cursor-crosshair{cursor:crosshair}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.touch-none{touch-action:none}.resize{resize:both}.auto-rows-min{grid-auto-rows:min-content}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing) * 0)}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-t-xl{border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}.rounded-b-xl{border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-amber-200{border-color:var(--color-amber-200)}.border-background{border-color:var(--background)}.border-border{border-color:var(--border)}.border-transparent{border-color:#0000}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-background{background-color:var(--background)}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive,.bg-destructive\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\/10{background-color:color-mix(in oklab, var(--destructive) 10%, transparent)}}.bg-green-600{background-color:var(--color-green-600)}.bg-muted,.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.bg-muted\/80{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/80{background-color:color-mix(in oklab, var(--muted) 80%, transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-clip-padding{background-clip:padding-box}.p-0{padding:calc(var(--spacing) * 0)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-3{padding-top:calc(var(--spacing) * 3)}.text-left{text-align:left}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-amber-800{color:var(--color-amber-800)}.text-card-foreground{color:var(--card-foreground)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-75{opacity:.75}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-foreground\/10{--tw-ring-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\/10{--tw-ring-color:color-mix(in oklab, var(--foreground) 10%, transparent)}}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.group-focus-within\/marker\:pointer-events-auto:is(:where(.group\/marker):focus-within *){pointer-events:auto}.group-focus-within\/marker\:opacity-100:is(:where(.group\/marker):focus-within *){opacity:1}@media (hover:hover){.group-hover\/marker\:pointer-events-auto:is(:where(.group\/marker):hover *){pointer-events:auto}.group-hover\/marker\:opacity-100:is(:where(.group\/marker):hover *){opacity:1}}.group-has-\[\[data-slot\=item-description\]\]\/item\:translate-y-0\.5:is(:where(.group\/item):has([data-slot=item-description]) *){--tw-translate-y:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-has-\[\[data-slot\=item-description\]\]\/item\:self-start:is(:where(.group\/item):has([data-slot=item-description]) *){align-self:flex-start}.group-data-\[disabled\=true\]\:pointer-events-none:is(:where(.group)[data-disabled=true] *){pointer-events:none}.group-data-\[disabled\=true\]\:opacity-50:is(:where(.group)[data-disabled=true] *){opacity:.5}.group-data-\[size\=sm\]\/card\:px-4:is(:where(.group\/card)[data-size=sm] *){padding-inline:calc(var(--spacing) * 4)}.group-data-\[size\=sm\]\/card\:text-sm:is(:where(.group\/card)[data-size=sm] *){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.group-data-\[size\=sm\]\/item\:size-8:is(:where(.group\/item)[data-size=sm] *){width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.group-data-\[size\=xs\]\/item\:size-6:is(:where(.group\/item)[data-size=xs] *){width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.group-data-\[size\=xs\]\/item\:gap-0:is(:where(.group\/item)[data-size=xs] *){gap:calc(var(--spacing) * 0)}.group-data-\[size\=xs\]\/item\:text-xs:is(:where(.group\/item)[data-size=xs] *){font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-50:is(:where(.peer):disabled~*){opacity:.5}@media (hover:hover){.hover\:scale-125:hover{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-destructive:hover,.hover\:bg-destructive\/20:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/20:hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-muted:hover{background-color:var(--muted)}.hover\:bg-primary\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/80:hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:border-destructive\/40:focus-visible{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:border-destructive\/40:focus-visible{border-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}:where([data-slot=button-group]) .in-data-\[slot\=button-group\]\:rounded-md{border-radius:calc(var(--radius) - 2px)}.has-data-\[icon\=inline-end\]\:pe-1\.5:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 1.5)}.has-data-\[icon\=inline-end\]\:pe-2:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 2)}.has-data-\[icon\=inline-end\]\:pe-3:has([data-icon=inline-end]){padding-inline-end:calc(var(--spacing) * 3)}.has-data-\[icon\=inline-start\]\:ps-1\.5:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 1.5)}.has-data-\[icon\=inline-start\]\:ps-2:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 2)}.has-data-\[icon\=inline-start\]\:ps-3:has([data-icon=inline-start]){padding-inline-start:calc(var(--spacing) * 3)}.has-data-\[slot\=card-action\]\:grid-cols-\[1fr_auto\]:has([data-slot=card-action]){grid-template-columns:1fr auto}.has-data-\[slot\=card-description\]\:grid-rows-\[auto_auto\]:has([data-slot=card-description]){grid-template-rows:auto auto}.has-\[\[data-size\=sm\]\]\:gap-2\.5:has([data-size=sm]){gap:calc(var(--spacing) * 2.5)}.has-\[\[data-size\=xs\]\]\:gap-2:has([data-size=xs]){gap:calc(var(--spacing) * 2)}.has-\[\>img\:first-child\]\:pt-0:has(>img:first-child){padding-top:calc(var(--spacing) * 0)}.aria-expanded\:bg-muted[aria-expanded=true]{background-color:var(--muted)}.aria-expanded\:bg-secondary[aria-expanded=true]{background-color:var(--secondary)}.aria-expanded\:text-foreground[aria-expanded=true]{color:var(--foreground)}.aria-expanded\:text-secondary-foreground[aria-expanded=true]{color:var(--secondary-foreground)}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\:ring-\[3px\][aria-invalid=true]{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.data-\[orientation\=horizontal\]\:h-px[data-orientation=horizontal]{height:1px}.data-\[orientation\=horizontal\]\:w-full[data-orientation=horizontal]{width:100%}.data-\[orientation\=vertical\]\:w-px[data-orientation=vertical]{width:1px}.data-\[orientation\=vertical\]\:self-stretch[data-orientation=vertical]{align-self:stretch}.data-\[size\=sm\]\:gap-4[data-size=sm]{gap:calc(var(--spacing) * 4)}.data-\[size\=sm\]\:py-4[data-size=sm]{padding-block:calc(var(--spacing) * 4)}@media (min-width:40rem){.sm\:block{display:block}}.dark\:border-amber-500\/30:is(.dark *){border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.dark\:border-amber-500\/30:is(.dark *){border-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.dark\:border-input:is(.dark *){border-color:var(--input)}.dark\:bg-amber-500\/10:is(.dark *){background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-500\/10:is(.dark *){background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.dark\:bg-destructive\/20:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-destructive\/20:is(.dark *){background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.dark\:bg-input\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-input\/30:is(.dark *){background-color:color-mix(in oklab, var(--input) 30%, transparent)}}.dark\:text-amber-400:is(.dark *){color:var(--color-amber-400)}@media (hover:hover){.dark\:hover\:bg-destructive\/30:is(.dark *):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-destructive\/30:is(.dark *):hover{background-color:color-mix(in oklab, var(--destructive) 30%, transparent)}}.dark\:hover\:bg-input\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-input\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}.dark\:hover\:bg-muted\/50:is(.dark *):hover{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-muted\/50:is(.dark *):hover{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}}.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:focus-visible\:ring-destructive\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:aria-invalid\:border-destructive\/50:is(.dark *)[aria-invalid=true]{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:border-destructive\/50:is(.dark *)[aria-invalid=true]{border-color:color-mix(in oklab, var(--destructive) 50%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:ring-destructive\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.\[\&_img\]\:size-full img{width:100%;height:100%}.\[\&_img\]\:object-cover img{object-fit:cover}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&\+\[data-slot\=item-content\]\]\:flex-none+[data-slot=item-content]{flex:none}.\[\.border-b\]\:pb-6.border-b{padding-bottom:calc(var(--spacing) * 6)}.group-data-\[size\=sm\]\/card\:\[\.border-b\]\:pb-4:is(:where(.group\/card)[data-size=sm] *).border-b{padding-bottom:calc(var(--spacing) * 4)}.\[\.border-t\]\:pt-6.border-t{padding-top:calc(var(--spacing) * 6)}.group-data-\[size\=sm\]\/card\:\[\.border-t\]\:pt-4:is(:where(.group\/card)[data-size=sm] *).border-t{padding-top:calc(var(--spacing) * 4)}.\[a\]\:transition-colors:is(a){transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.\[a\]\:hover\:bg-amber-600:is(a):hover{background-color:var(--color-amber-600)}.\[a\]\:hover\:bg-destructive\/20:is(a):hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-destructive\/20:is(a):hover{background-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.\[a\]\:hover\:bg-muted:is(a):hover{background-color:var(--muted)}.\[a\]\:hover\:bg-primary\/80:is(a):hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-primary\/80:is(a):hover{background-color:color-mix(in oklab, var(--primary) 80%, transparent)}}.\[a\]\:hover\:bg-secondary\/80:is(a):hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.\[a\]\:hover\:bg-secondary\/80:is(a):hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.\[a\]\:hover\:text-muted-foreground:is(a):hover{color:var(--muted-foreground)}}:is(.\*\:\[img\:first-child\]\:rounded-t-xl>*):is(img:first-child){border-top-left-radius:calc(var(--radius) + 4px);border-top-right-radius:calc(var(--radius) + 4px)}:is(.\*\:\[img\:last-child\]\:rounded-b-xl>*):is(img:last-child){border-bottom-right-radius:calc(var(--radius) + 4px);border-bottom-left-radius:calc(var(--radius) + 4px)}.\[\&\>a\]\:underline>a{text-decoration-line:underline}.\[\&\>a\]\:underline-offset-4>a{text-underline-offset:4px}.\[\&\>a\:hover\]\:text-primary>a:hover{color:var(--primary)}.\[\&\>svg\]\:pointer-events-none>svg{pointer-events:none}.\[\&\>svg\]\:size-3\!>svg{width:calc(var(--spacing) * 3)!important;height:calc(var(--spacing) * 3)!important}.\[\&\>svg\]\:text-white>svg{color:var(--color-white)}[data-slot=dropdown-menu-content] .\[\[data-slot\=dropdown-menu-content\]_\&\]\:p-0{padding:calc(var(--spacing) * 0)}}[data-viewer-360]{--radius:.625rem;--radius-4xl:2rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0)}.dark [data-viewer-360]{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmmmzxe/react-360-viewer",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "A standalone, configurable 360° image viewer for React with drag rotation, zoom, hotspots, and auto-rotate support.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -7,7 +7,7 @@ import { Slot } from 'radix-ui';
7
7
  import { cn } from '@/components/utils';
8
8
 
9
9
  const badgeVariants = cva(
10
- 'h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge',
10
+ 'h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge',
11
11
  {
12
12
  variants: {
13
13
  variant: {
@@ -19,7 +19,8 @@ const badgeVariants = cva(
19
19
  ghost: 'hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50',
20
20
  link: 'text-primary underline-offset-4 hover:underline',
21
21
  info: 'bg-blue-500 text-white hover:bg-blue-600',
22
- warning: 'bg-amber-500 text-white hover:bg-amber-600',
22
+ warning:
23
+ 'rounded-full border-transparent bg-amber-500 px-2.5 text-white shadow-none [a]:hover:bg-amber-600 [&>svg]:text-white',
23
24
  success: 'bg-green-600 text-white hover:bg-green-700',
24
25
  },
25
26
  },
@@ -7,7 +7,7 @@ import { Slot } from 'radix-ui';
7
7
  import { cn } from '@/components/utils';
8
8
 
9
9
  const buttonVariants = cva(
10
- 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none',
10
+ 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none',
11
11
  {
12
12
  variants: {
13
13
  variant: {
@@ -24,13 +24,12 @@ const buttonVariants = cva(
24
24
  size: {
25
25
  default:
26
26
  'h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2',
27
- xs: 'h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',
28
- sm: 'h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',
27
+ xs: 'h-6 gap-1 rounded-md px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',
28
+ sm: 'h-8 gap-1 rounded-md px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5',
29
29
  lg: 'h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pe-3 has-data-[icon=inline-start]:ps-3',
30
30
  icon: 'size-9',
31
- 'icon-xs':
32
- 'size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md',
33
- 'icon-sm': 'size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md',
31
+ 'icon-xs': 'size-6 rounded-md in-data-[slot=button-group]:rounded-md',
32
+ 'icon-sm': 'size-8 rounded-md in-data-[slot=button-group]:rounded-md',
34
33
  'icon-lg': 'size-10',
35
34
  },
36
35
  },
@@ -24,8 +24,8 @@ export const viewer360ClassNames: Required<Viewer360ClassNames> = {
24
24
 
25
25
  export const viewer360MarkerPinClassNames: Required<Viewer360MarkerPinClassNames> = {
26
26
  root: 'pointer-events-auto absolute z-30 -translate-x-1/2 -translate-y-1/2',
27
- ping: 'absolute inline-flex size-6 -translate-x-1/4 -translate-y-1/4 animate-ping rounded-full bg-destructive opacity-60',
28
- dot: 'relative flex size-4 items-center justify-center rounded-full border-2 border-background bg-destructive shadow-md transition-transform duration-200 hover:scale-125 focus:outline-none',
27
+ ping: 'pointer-events-none absolute inset-0 inline-flex animate-ping rounded-full bg-destructive opacity-75',
28
+ dot: 'relative z-10 inline-flex size-4 min-h-4 min-w-4 shrink-0 rounded-full border-2 border-background bg-destructive p-0 shadow-md transition-transform duration-200 hover:scale-125 focus:outline-none',
29
29
  tooltip:
30
30
  'absolute bottom-6 left-1/2 z-40 w-64 -translate-x-1/2 rounded-lg border bg-popover p-3 text-popover-foreground shadow-md',
31
31
  tooltipHeader: 'flex items-start justify-between gap-2',
@@ -5,7 +5,6 @@ import { Trash2 } from 'lucide-react';
5
5
  import { defaultViewer360MarkerPinLabels } from '../constants/viewer360MarkerLabels';
6
6
  import { viewer360MarkerPinClassNames } from '../constants/viewer360ClassNames';
7
7
  import type { Viewer360MarkerPinProps } from '../types';
8
- import { Badge } from '@/components/ui/Badge';
9
8
  import { Button } from '@/components/ui/Button';
10
9
  import {
11
10
  Item,
@@ -38,34 +37,22 @@ export function Viewer360MarkerPin<TData = unknown>({
38
37
  // MARK: Main Component UI
39
38
  // ----------------------------------------------------------------------------------------------------
40
39
  return (
41
- <Item
42
- size="xs"
43
- variant="default"
44
- className={cn(
45
- viewer360MarkerPinClassNames.root,
46
- classNames?.root,
47
- 'group/marker w-auto border-transparent p-0'
48
- )}
40
+ <div
41
+ className={cn(viewer360MarkerPinClassNames.root, classNames?.root, 'group/marker')}
49
42
  style={{ left: `${leftPercent}%`, top: `${topPercent}%` }}
50
43
  >
51
- <Badge
52
- variant="destructive"
53
- className={cn(viewer360MarkerPinClassNames.ping, classNames?.ping, 'absolute size-6 border-0 bg-destructive opacity-60')}
54
- aria-hidden="true"
55
- />
44
+ <div className="relative size-4 shrink-0">
45
+ <span className={cn(viewer360MarkerPinClassNames.ping, classNames?.ping)} aria-hidden="true" />
56
46
 
57
- <Button
58
- type="button"
59
- variant="destructive"
60
- size="icon-xs"
61
- className={cn(
62
- viewer360MarkerPinClassNames.dot,
63
- classNames?.dot,
64
- 'size-4 min-h-4 min-w-4 rounded-full border-2 border-background bg-destructive p-0 shadow-md hover:scale-125 hover:bg-destructive'
65
- )}
66
- aria-label={marker.title}
67
- onClick={onClick}
68
- />
47
+ <Button
48
+ type="button"
49
+ variant="destructive"
50
+ size="icon-xs"
51
+ className={cn(viewer360MarkerPinClassNames.dot, classNames?.dot, 'hover:bg-destructive')}
52
+ aria-label={marker.title}
53
+ onClick={onClick}
54
+ />
55
+ </div>
69
56
 
70
57
  {showTooltip && (
71
58
  <div
@@ -84,7 +71,9 @@ export function Viewer360MarkerPin<TData = unknown>({
84
71
  <ItemTitle className={cn(viewer360MarkerPinClassNames.tooltipTitle, classNames?.tooltipTitle)}>
85
72
  {marker.title}
86
73
  </ItemTitle>
87
- {renderTag?.({ marker, hotspot })}
74
+ {renderTag && (
75
+ <div className="mt-1 flex w-fit items-center">{renderTag({ marker, hotspot })}</div>
76
+ )}
88
77
  {marker.description && (
89
78
  <ItemDescription className={cn(viewer360MarkerPinClassNames.tooltipDescription, classNames?.tooltipDescription)}>
90
79
  {marker.description}
@@ -111,6 +100,6 @@ export function Viewer360MarkerPin<TData = unknown>({
111
100
  </Item>
112
101
  </div>
113
102
  )}
114
- </Item>
103
+ </div>
115
104
  );
116
105
  }
package/src/styles.css CHANGED
@@ -28,6 +28,7 @@
28
28
  --radius-md: calc(var(--radius) - 2px);
29
29
  --radius-lg: var(--radius);
30
30
  --radius-xl: calc(var(--radius) + 4px);
31
+ --radius-4xl: 2rem;
31
32
  }
32
33
 
33
34
  /*
@@ -36,6 +37,7 @@
36
37
  */
37
38
  [data-viewer-360] {
38
39
  --radius: 0.625rem;
40
+ --radius-4xl: 2rem;
39
41
  --background: oklch(1 0 0);
40
42
  --foreground: oklch(0.145 0 0);
41
43
  --card: oklch(1 0 0);