@popaya/pgsg-viewer 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-LFICZTG7.js → chunk-MNOTPSNH.js} +2 -2
- package/dist/core/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{pgsg-three-viewer-5BUDBGSE.js → pgsg-three-viewer-TH7LXVVZ.js} +191 -11
- package/dist/pgsg-three-viewer-TH7LXVVZ.js.map +1 -0
- package/dist/react/index.js +182 -95
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/pgsg-three-viewer-5BUDBGSE.js.map +0 -1
- /package/dist/{chunk-LFICZTG7.js.map → chunk-MNOTPSNH.js.map} +0 -0
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["#style-inject:#style-inject","../../src/styles/viewer.css","../../src/react/PGSGCanvas.tsx","../../src/react/PGSGViewControls.tsx","../../src/lib/utils.ts","../../src/react/controls/PGSGViewer3D.tsx","../../src/react/controls/PGSGViewerMode.tsx","../../src/react/controls/PGSGViewerSettings.tsx","../../src/react/controls/PGSGViewer3DSheet.tsx"],"sourcesContent":["\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\"/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */\\n@layer properties;\\n@layer theme, base, components, utilities;\\n@layer theme {\\n :root,\\n :host {\\n --font-sans:\\n ui-sans-serif,\\n system-ui,\\n sans-serif,\\n \\\"Apple Color Emoji\\\",\\n \\\"Segoe UI Emoji\\\",\\n \\\"Segoe UI Symbol\\\",\\n \\\"Noto Color Emoji\\\";\\n --font-mono:\\n ui-monospace,\\n SFMono-Regular,\\n Menlo,\\n Monaco,\\n Consolas,\\n \\\"Liberation Mono\\\",\\n \\\"Courier New\\\",\\n monospace;\\n --color-blue-500: oklch(62.3% 0.214 259.815);\\n --color-blue-600: oklch(54.6% 0.245 262.881);\\n --color-black: #000;\\n --color-white: #fff;\\n --spacing: 0.25rem;\\n --text-sm: 0.875rem;\\n --text-sm--line-height: calc(1.25 / 0.875);\\n --text-base: 1rem;\\n --text-base--line-height: calc(1.5 / 1);\\n --text-lg: 1.125rem;\\n --text-lg--line-height: calc(1.75 / 1.125);\\n --font-weight-normal: 400;\\n --font-weight-medium: 500;\\n --font-weight-semibold: 600;\\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\\n --animate-spin: spin 1s linear infinite;\\n --blur-2xl: 40px;\\n --default-transition-duration: 150ms;\\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n --default-font-family: var(--font-sans);\\n --default-mono-font-family: var(--font-mono);\\n }\\n}\\n@layer base {\\n *,\\n ::after,\\n ::before,\\n ::backdrop,\\n ::file-selector-button {\\n box-sizing: border-box;\\n margin: 0;\\n padding: 0;\\n border: 0 solid;\\n }\\n html,\\n :host {\\n line-height: 1.5;\\n -webkit-text-size-adjust: 100%;\\n tab-size: 4;\\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \\\"Apple Color Emoji\\\", \\\"Segoe UI Emoji\\\", \\\"Segoe UI Symbol\\\", \\\"Noto Color Emoji\\\");\\n font-feature-settings: var(--default-font-feature-settings, normal);\\n font-variation-settings: var(--default-font-variation-settings, normal);\\n -webkit-tap-highlight-color: transparent;\\n }\\n hr {\\n height: 0;\\n color: inherit;\\n border-top-width: 1px;\\n }\\n abbr:where([title]) {\\n -webkit-text-decoration: underline dotted;\\n text-decoration: underline dotted;\\n }\\n h1,\\n h2,\\n h3,\\n h4,\\n h5,\\n h6 {\\n font-size: inherit;\\n font-weight: inherit;\\n }\\n a {\\n color: inherit;\\n -webkit-text-decoration: inherit;\\n text-decoration: inherit;\\n }\\n b,\\n strong {\\n font-weight: bolder;\\n }\\n code,\\n kbd,\\n samp,\\n pre {\\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \\\"Liberation Mono\\\", \\\"Courier New\\\", monospace);\\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\\n font-size: 1em;\\n }\\n small {\\n font-size: 80%;\\n }\\n sub,\\n sup {\\n font-size: 75%;\\n line-height: 0;\\n position: relative;\\n vertical-align: baseline;\\n }\\n sub {\\n bottom: -0.25em;\\n }\\n sup {\\n top: -0.5em;\\n }\\n table {\\n text-indent: 0;\\n border-color: inherit;\\n border-collapse: collapse;\\n }\\n :-moz-focusring {\\n outline: auto;\\n }\\n progress {\\n vertical-align: baseline;\\n }\\n summary {\\n display: list-item;\\n }\\n ol,\\n ul,\\n menu {\\n list-style: none;\\n }\\n img,\\n svg,\\n video,\\n canvas,\\n audio,\\n iframe,\\n embed,\\n object {\\n display: block;\\n vertical-align: middle;\\n }\\n img,\\n video {\\n max-width: 100%;\\n height: auto;\\n }\\n button,\\n input,\\n select,\\n optgroup,\\n textarea,\\n ::file-selector-button {\\n font: inherit;\\n font-feature-settings: inherit;\\n font-variation-settings: inherit;\\n letter-spacing: inherit;\\n color: inherit;\\n border-radius: 0;\\n background-color: transparent;\\n opacity: 1;\\n }\\n :where(select:is([multiple], [size])) optgroup {\\n font-weight: bolder;\\n }\\n :where(select:is([multiple], [size])) optgroup option {\\n padding-inline-start: 20px;\\n }\\n ::file-selector-button {\\n margin-inline-end: 4px;\\n }\\n ::placeholder {\\n opacity: 1;\\n }\\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\\n ::placeholder {\\n color: currentcolor;\\n @supports (color: color-mix(in lab, red, red)) {\\n color: color-mix(in oklab, currentcolor 50%, transparent);\\n }\\n }\\n }\\n textarea {\\n resize: vertical;\\n }\\n ::-webkit-search-decoration {\\n -webkit-appearance: none;\\n }\\n ::-webkit-date-and-time-value {\\n min-height: 1lh;\\n text-align: inherit;\\n }\\n ::-webkit-datetime-edit {\\n display: inline-flex;\\n }\\n ::-webkit-datetime-edit-fields-wrapper {\\n padding: 0;\\n }\\n ::-webkit-datetime-edit,\\n ::-webkit-datetime-edit-year-field,\\n ::-webkit-datetime-edit-month-field,\\n ::-webkit-datetime-edit-day-field,\\n ::-webkit-datetime-edit-hour-field,\\n ::-webkit-datetime-edit-minute-field,\\n ::-webkit-datetime-edit-second-field,\\n ::-webkit-datetime-edit-millisecond-field,\\n ::-webkit-datetime-edit-meridiem-field {\\n padding-block: 0;\\n }\\n ::-webkit-calendar-picker-indicator {\\n line-height: 1;\\n }\\n :-moz-ui-invalid {\\n box-shadow: none;\\n }\\n button,\\n input:where([type=button], [type=reset], [type=submit]),\\n ::file-selector-button {\\n appearance: button;\\n }\\n ::-webkit-inner-spin-button,\\n ::-webkit-outer-spin-button {\\n height: auto;\\n }\\n [hidden]:where(:not([hidden=until-found])) {\\n display: none !important;\\n }\\n}\\n@layer utilities {\\n .pointer-events-auto {\\n pointer-events: auto;\\n }\\n .pointer-events-none {\\n pointer-events: none;\\n }\\n .invisible {\\n visibility: hidden;\\n }\\n .visible {\\n visibility: visible;\\n }\\n .absolute {\\n position: absolute;\\n }\\n .relative {\\n position: relative;\\n }\\n .static {\\n position: static;\\n }\\n .start {\\n inset-inline-start: var(--spacing);\\n }\\n .end {\\n inset-inline-end: var(--spacing);\\n }\\n .top-0 {\\n top: calc(var(--spacing) * 0);\\n }\\n .right-0 {\\n right: calc(var(--spacing) * 0);\\n }\\n .bottom-0 {\\n bottom: calc(var(--spacing) * 0);\\n }\\n .z-50 {\\n z-index: 50;\\n }\\n .z-100 {\\n z-index: 100;\\n }\\n .container {\\n width: 100%;\\n @media (width >= 40rem) {\\n max-width: 40rem;\\n }\\n @media (width >= 48rem) {\\n max-width: 48rem;\\n }\\n @media (width >= 64rem) {\\n max-width: 64rem;\\n }\\n @media (width >= 80rem) {\\n max-width: 80rem;\\n }\\n @media (width >= 96rem) {\\n max-width: 96rem;\\n }\\n }\\n .mt-2 {\\n margin-top: calc(var(--spacing) * 2);\\n }\\n .mt-4 {\\n margin-top: calc(var(--spacing) * 4);\\n }\\n .mb-2 {\\n margin-bottom: calc(var(--spacing) * 2);\\n }\\n .block {\\n display: block;\\n }\\n .flex {\\n display: flex;\\n }\\n .grid {\\n display: grid;\\n }\\n .size-4 {\\n width: calc(var(--spacing) * 4);\\n height: calc(var(--spacing) * 4);\\n }\\n .size-5 {\\n width: calc(var(--spacing) * 5);\\n height: calc(var(--spacing) * 5);\\n }\\n .h-\\\\[320px\\\\] {\\n height: 320px;\\n }\\n .h-full {\\n height: 100%;\\n }\\n .max-h-\\\\[60px\\\\] {\\n max-height: 60px;\\n }\\n .w-0 {\\n width: calc(var(--spacing) * 0);\\n }\\n .w-\\\\[360px\\\\] {\\n width: 360px;\\n }\\n .w-full {\\n width: 100%;\\n }\\n .max-w-0 {\\n max-width: calc(var(--spacing) * 0);\\n }\\n .max-w-\\\\[300px\\\\] {\\n max-width: 300px;\\n }\\n .max-w-\\\\[520px\\\\] {\\n max-width: 520px;\\n }\\n .flex-1 {\\n flex: 1;\\n }\\n .translate-x-0 {\\n --tw-translate-x: calc(var(--spacing) * 0);\\n translate: var(--tw-translate-x) var(--tw-translate-y);\\n }\\n .translate-x-6 {\\n --tw-translate-x: calc(var(--spacing) * 6);\\n translate: var(--tw-translate-x) var(--tw-translate-y);\\n }\\n .translate-x-full {\\n --tw-translate-x: 100%;\\n translate: var(--tw-translate-x) var(--tw-translate-y);\\n }\\n .scale-95 {\\n --tw-scale-x: 95%;\\n --tw-scale-y: 95%;\\n --tw-scale-z: 95%;\\n scale: var(--tw-scale-x) var(--tw-scale-y);\\n }\\n .scale-100 {\\n --tw-scale-x: 100%;\\n --tw-scale-y: 100%;\\n --tw-scale-z: 100%;\\n scale: var(--tw-scale-x) var(--tw-scale-y);\\n }\\n .transform {\\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\\n }\\n .animate-spin {\\n animation: var(--animate-spin);\\n }\\n .cursor-default {\\n cursor: default;\\n }\\n .cursor-pointer {\\n cursor: pointer;\\n }\\n .resize-none {\\n resize: none;\\n }\\n .flex-col {\\n flex-direction: column;\\n }\\n .flex-row {\\n flex-direction: row;\\n }\\n .flex-row-reverse {\\n flex-direction: row-reverse;\\n }\\n .flex-wrap {\\n flex-wrap: wrap;\\n }\\n .items-center {\\n align-items: center;\\n }\\n .items-end {\\n align-items: flex-end;\\n }\\n .items-stretch {\\n align-items: stretch;\\n }\\n .justify-between {\\n justify-content: space-between;\\n }\\n .justify-center {\\n justify-content: center;\\n }\\n .gap-1 {\\n gap: calc(var(--spacing) * 1);\\n }\\n .gap-1\\\\.5 {\\n gap: calc(var(--spacing) * 1.5);\\n }\\n .gap-2 {\\n gap: calc(var(--spacing) * 2);\\n }\\n .gap-3 {\\n gap: calc(var(--spacing) * 3);\\n }\\n .overflow-hidden {\\n overflow: hidden;\\n }\\n .rounded-full {\\n border-radius: calc(infinity * 1px);\\n }\\n .rounded-md {\\n border-radius: calc(var(--radius) - 2px);\\n }\\n .border {\\n border-style: var(--tw-border-style);\\n border-width: 1px;\\n }\\n .border-l {\\n border-left-style: var(--tw-border-style);\\n border-left-width: 1px;\\n }\\n .border-black\\\\/20 {\\n border-color: color-mix(in srgb, #000 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-black) 20%, transparent);\\n }\\n }\\n .border-white\\\\/10 {\\n border-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n }\\n .border-white\\\\/20 {\\n border-color: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n }\\n .border-l-white\\\\/1 {\\n border-left-color: color-mix(in srgb, #fff 1%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-left-color: color-mix(in oklab, var(--color-white) 1%, transparent);\\n }\\n }\\n .bg-\\\\[rgba\\\\(15\\\\,15\\\\,15\\\\,0\\\\.9\\\\)\\\\] {\\n background-color: rgba(15, 15, 15, 0.9);\\n }\\n .bg-blue-500 {\\n background-color: var(--color-blue-500);\\n }\\n .bg-transparent {\\n background-color: transparent;\\n }\\n .bg-white\\\\/10 {\\n background-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n }\\n .bg-linear-to-br {\\n --tw-gradient-position: to bottom right;\\n @supports (background-image: linear-gradient(in lab, red, red)) {\\n --tw-gradient-position: to bottom right in oklab;\\n }\\n background-image: linear-gradient(var(--tw-gradient-stops));\\n }\\n .bg-gradient-to-br {\\n --tw-gradient-position: to bottom right in oklab;\\n background-image: linear-gradient(var(--tw-gradient-stops));\\n }\\n .from-black\\\\/20 {\\n --tw-gradient-from: color-mix(in srgb, #000 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 20%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .from-white\\\\/20 {\\n --tw-gradient-from: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .to-transparent {\\n --tw-gradient-to: transparent;\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .to-white\\\\/5 {\\n --tw-gradient-to: color-mix(in srgb, #fff 5%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-to: color-mix(in oklab, var(--color-white) 5%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .object-cover {\\n object-fit: cover;\\n }\\n .p-2\\\\.5 {\\n padding: calc(var(--spacing) * 2.5);\\n }\\n .p-3 {\\n padding: calc(var(--spacing) * 3);\\n }\\n .p-3\\\\.5 {\\n padding: calc(var(--spacing) * 3.5);\\n }\\n .px-2 {\\n padding-inline: calc(var(--spacing) * 2);\\n }\\n .px-3 {\\n padding-inline: calc(var(--spacing) * 3);\\n }\\n .py-1 {\\n padding-block: calc(var(--spacing) * 1);\\n }\\n .py-1\\\\.5 {\\n padding-block: calc(var(--spacing) * 1.5);\\n }\\n .py-2 {\\n padding-block: calc(var(--spacing) * 2);\\n }\\n .pr-2 {\\n padding-right: calc(var(--spacing) * 2);\\n }\\n .pr-14 {\\n padding-right: calc(var(--spacing) * 14);\\n }\\n .pb-2\\\\.5 {\\n padding-bottom: calc(var(--spacing) * 2.5);\\n }\\n .pl-2 {\\n padding-left: calc(var(--spacing) * 2);\\n }\\n .text-base {\\n font-size: var(--text-base);\\n line-height: var(--tw-leading, var(--text-base--line-height));\\n }\\n .text-lg {\\n font-size: var(--text-lg);\\n line-height: var(--tw-leading, var(--text-lg--line-height));\\n }\\n .text-sm {\\n font-size: var(--text-sm);\\n line-height: var(--tw-leading, var(--text-sm--line-height));\\n }\\n .font-medium {\\n --tw-font-weight: var(--font-weight-medium);\\n font-weight: var(--font-weight-medium);\\n }\\n .font-normal {\\n --tw-font-weight: var(--font-weight-normal);\\n font-weight: var(--font-weight-normal);\\n }\\n .font-semibold {\\n --tw-font-weight: var(--font-weight-semibold);\\n font-weight: var(--font-weight-semibold);\\n }\\n .text-white {\\n color: var(--color-white);\\n }\\n .text-white\\\\/40 {\\n color: color-mix(in srgb, #fff 40%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n color: color-mix(in oklab, var(--color-white) 40%, transparent);\\n }\\n }\\n .text-white\\\\/60 {\\n color: color-mix(in srgb, #fff 60%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n color: color-mix(in oklab, var(--color-white) 60%, transparent);\\n }\\n }\\n .opacity-0 {\\n opacity: 0%;\\n }\\n .opacity-100 {\\n opacity: 100%;\\n }\\n .shadow-\\\\[0_8px_32px_rgba\\\\(0\\\\,0\\\\,0\\\\,0\\\\.25\\\\)\\\\] {\\n --tw-shadow: 0 8px 32px var(--tw-shadow-color, rgba(0,0,0,0.25));\\n box-shadow:\\n var(--tw-inset-shadow),\\n var(--tw-inset-ring-shadow),\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow);\\n }\\n .shadow-lg {\\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\\n box-shadow:\\n var(--tw-inset-shadow),\\n var(--tw-inset-ring-shadow),\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow);\\n }\\n .shadow-none {\\n --tw-shadow: 0 0 #0000;\\n box-shadow:\\n var(--tw-inset-shadow),\\n var(--tw-inset-ring-shadow),\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow);\\n }\\n .shadow-white\\\\/10 {\\n --tw-shadow-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-shadow-color: color-mix(in oklab, color-mix(in oklab, var(--color-white) 10%, transparent) var(--tw-shadow-alpha), transparent);\\n }\\n }\\n .blur {\\n --tw-blur: blur(8px);\\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\\n }\\n .filter {\\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\\n }\\n .backdrop-blur-2xl {\\n --tw-backdrop-blur: blur(var(--blur-2xl));\\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\\n }\\n .transition-all {\\n transition-property: all;\\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\\n transition-duration: var(--tw-duration, var(--default-transition-duration));\\n }\\n .transition-opacity {\\n transition-property: opacity;\\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\\n transition-duration: var(--tw-duration, var(--default-transition-duration));\\n }\\n .delay-200 {\\n transition-delay: 200ms;\\n }\\n .duration-200 {\\n --tw-duration: 200ms;\\n transition-duration: 200ms;\\n }\\n .duration-300 {\\n --tw-duration: 300ms;\\n transition-duration: 300ms;\\n }\\n .ease-out {\\n --tw-ease: var(--ease-out);\\n transition-timing-function: var(--ease-out);\\n }\\n .delay-200 {\\n animation-delay: calc(200*1ms);\\n animation-delay: .2s;\\n --tw-animation-delay: calc(200*1ms);\\n --tw-animation-delay: .2s;\\n }\\n .outline-none {\\n --tw-outline-style: none;\\n outline-style: none;\\n }\\n .running {\\n animation-play-state: running;\\n }\\n .hover\\\\:border-black\\\\/10 {\\n &:hover {\\n @media (hover: hover) {\\n border-color: color-mix(in srgb, #000 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-black) 10%, transparent);\\n }\\n }\\n }\\n }\\n .hover\\\\:bg-blue-600 {\\n &:hover {\\n @media (hover: hover) {\\n background-color: var(--color-blue-600);\\n }\\n }\\n }\\n .hover\\\\:bg-white\\\\/10 {\\n &:hover {\\n @media (hover: hover) {\\n background-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n }\\n }\\n }\\n .hover\\\\:bg-white\\\\/20 {\\n &:hover {\\n @media (hover: hover) {\\n background-color: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n background-color: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n }\\n }\\n }\\n .hover\\\\:from-black\\\\/20 {\\n &:hover {\\n @media (hover: hover) {\\n --tw-gradient-from: color-mix(in srgb, #000 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 20%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n }\\n .hover\\\\:to-transparent {\\n &:hover {\\n @media (hover: hover) {\\n --tw-gradient-to: transparent;\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n }\\n .disabled\\\\:opacity-50 {\\n &:disabled {\\n opacity: 50%;\\n }\\n }\\n .dark\\\\:border-white\\\\/20 {\\n &:is(.dark *) {\\n border-color: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n }\\n }\\n .dark\\\\:from-white\\\\/10 {\\n &:is(.dark *) {\\n --tw-gradient-from: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n .dark\\\\:to-transparent {\\n &:is(.dark *) {\\n --tw-gradient-to: transparent;\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n .dark\\\\:to-white\\\\/5 {\\n &:is(.dark *) {\\n --tw-gradient-to: color-mix(in srgb, #fff 5%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-to: color-mix(in oklab, var(--color-white) 5%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n}\\n@property --tw-animation-delay { syntax: \\\"*\\\"; inherits: false; initial-value: 0s; }\\n@property --tw-animation-direction { syntax: \\\"*\\\"; inherits: false; initial-value: normal; }\\n@property --tw-animation-duration { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-animation-fill-mode { syntax: \\\"*\\\"; inherits: false; initial-value: none; }\\n@property --tw-animation-iteration-count { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-enter-blur { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-enter-opacity { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-enter-rotate { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-enter-scale { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-enter-translate-x { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-enter-translate-y { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-blur { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-opacity { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-exit-rotate { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-scale { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-exit-translate-x { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-translate-y { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n:root {\\n --radius: 0.625rem;\\n --background: oklch(1 0 0);\\n --foreground: oklch(0.145 0 0);\\n --card: oklch(1 0 0);\\n --card-foreground: oklch(0.145 0 0);\\n --popover: oklch(1 0 0);\\n --popover-foreground: oklch(0.145 0 0);\\n --primary: oklch(0.205 0 0);\\n --primary-foreground: oklch(0.985 0 0);\\n --secondary: oklch(0.97 0 0);\\n --secondary-foreground: oklch(0.205 0 0);\\n --muted: oklch(0.97 0 0);\\n --muted-foreground: oklch(0.556 0 0);\\n --accent: oklch(0.97 0 0);\\n --accent-foreground: oklch(0.205 0 0);\\n --destructive: oklch(0.577 0.245 27.325);\\n --border: oklch(0.922 0 0);\\n --input: oklch(0.922 0 0);\\n --ring: oklch(0.708 0 0);\\n --chart-1: oklch(0.646 0.222 41.116);\\n --chart-2: oklch(0.6 0.118 184.704);\\n --chart-3: oklch(0.398 0.07 227.392);\\n --chart-4: oklch(0.828 0.189 84.429);\\n --chart-5: oklch(0.769 0.188 70.08);\\n --sidebar: oklch(0.985 0 0);\\n --sidebar-foreground: oklch(0.145 0 0);\\n --sidebar-primary: oklch(0.205 0 0);\\n --sidebar-primary-foreground: oklch(0.985 0 0);\\n --sidebar-accent: oklch(0.97 0 0);\\n --sidebar-accent-foreground: oklch(0.205 0 0);\\n --sidebar-border: oklch(0.922 0 0);\\n --sidebar-ring: oklch(0.708 0 0);\\n}\\n.dark {\\n --background: oklch(0.145 0 0);\\n --foreground: oklch(0.985 0 0);\\n --card: oklch(0.205 0 0);\\n --card-foreground: oklch(0.985 0 0);\\n --popover: oklch(0.205 0 0);\\n --popover-foreground: oklch(0.985 0 0);\\n --primary: oklch(0.922 0 0);\\n --primary-foreground: oklch(0.205 0 0);\\n --secondary: oklch(0.269 0 0);\\n --secondary-foreground: oklch(0.985 0 0);\\n --muted: oklch(0.269 0 0);\\n --muted-foreground: oklch(0.708 0 0);\\n --accent: oklch(0.269 0 0);\\n --accent-foreground: oklch(0.985 0 0);\\n --destructive: oklch(0.704 0.191 22.216);\\n --border: oklch(1 0 0 / 10%);\\n --input: oklch(1 0 0 / 15%);\\n --ring: oklch(0.556 0 0);\\n --chart-1: oklch(0.488 0.243 264.376);\\n --chart-2: oklch(0.696 0.17 162.48);\\n --chart-3: oklch(0.769 0.188 70.08);\\n --chart-4: oklch(0.627 0.265 303.9);\\n --chart-5: oklch(0.645 0.246 16.439);\\n --sidebar: oklch(0.205 0 0);\\n --sidebar-foreground: oklch(0.985 0 0);\\n --sidebar-primary: oklch(0.488 0.243 264.376);\\n --sidebar-primary-foreground: oklch(0.985 0 0);\\n --sidebar-accent: oklch(0.269 0 0);\\n --sidebar-accent-foreground: oklch(0.985 0 0);\\n --sidebar-border: oklch(1 0 0 / 10%);\\n --sidebar-ring: oklch(0.556 0 0);\\n}\\n@layer base {\\n * {\\n border-color: var(--border);\\n outline-color: var(--ring);\\n @supports (color: color-mix(in lab, red, red)) {\\n outline-color: color-mix(in oklab, var(--ring) 50%, transparent);\\n }\\n }\\n body {\\n background-color: var(--background);\\n color: var(--foreground);\\n }\\n}\\n@property --tw-translate-x { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-translate-y { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-translate-z { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-scale-x { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-scale-y { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-scale-z { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-rotate-x { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-rotate-y { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-rotate-z { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-skew-x { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-skew-y { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-border-style { syntax: \\\"*\\\"; inherits: false; initial-value: solid; }\\n@property --tw-gradient-position { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-gradient-from { syntax: \\\"<color>\\\"; inherits: false; initial-value: #0000; }\\n@property --tw-gradient-via { syntax: \\\"<color>\\\"; inherits: false; initial-value: #0000; }\\n@property --tw-gradient-to { syntax: \\\"<color>\\\"; inherits: false; initial-value: #0000; }\\n@property --tw-gradient-stops { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-gradient-via-stops { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-gradient-from-position { syntax: \\\"<length-percentage>\\\"; inherits: false; initial-value: 0%; }\\n@property --tw-gradient-via-position { syntax: \\\"<length-percentage>\\\"; inherits: false; initial-value: 50%; }\\n@property --tw-gradient-to-position { syntax: \\\"<length-percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-font-weight { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-shadow-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-shadow-alpha { syntax: \\\"<percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-inset-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-inset-shadow-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-inset-shadow-alpha { syntax: \\\"<percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-ring-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-ring-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-inset-ring-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-inset-ring-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-ring-inset { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-ring-offset-width { syntax: \\\"<length>\\\"; inherits: false; initial-value: 0px; }\\n@property --tw-ring-offset-color { syntax: \\\"*\\\"; inherits: false; initial-value: #fff; }\\n@property --tw-ring-offset-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-blur { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-brightness { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-contrast { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-grayscale { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-hue-rotate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-invert { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-opacity { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-saturate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-sepia { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-drop-shadow { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-drop-shadow-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-drop-shadow-alpha { syntax: \\\"<percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-drop-shadow-size { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-blur { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-brightness { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-contrast { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-grayscale { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-hue-rotate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-invert { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-opacity { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-saturate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-sepia { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-duration { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-ease { syntax: \\\"*\\\"; inherits: false; }\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n@layer properties {\\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\\n *,\\n ::before,\\n ::after,\\n ::backdrop {\\n --tw-translate-x: 0;\\n --tw-translate-y: 0;\\n --tw-translate-z: 0;\\n --tw-scale-x: 1;\\n --tw-scale-y: 1;\\n --tw-scale-z: 1;\\n --tw-rotate-x: initial;\\n --tw-rotate-y: initial;\\n --tw-rotate-z: initial;\\n --tw-skew-x: initial;\\n --tw-skew-y: initial;\\n --tw-border-style: solid;\\n --tw-gradient-position: initial;\\n --tw-gradient-from: #0000;\\n --tw-gradient-via: #0000;\\n --tw-gradient-to: #0000;\\n --tw-gradient-stops: initial;\\n --tw-gradient-via-stops: initial;\\n --tw-gradient-from-position: 0%;\\n --tw-gradient-via-position: 50%;\\n --tw-gradient-to-position: 100%;\\n --tw-font-weight: initial;\\n --tw-shadow: 0 0 #0000;\\n --tw-shadow-color: initial;\\n --tw-shadow-alpha: 100%;\\n --tw-inset-shadow: 0 0 #0000;\\n --tw-inset-shadow-color: initial;\\n --tw-inset-shadow-alpha: 100%;\\n --tw-ring-color: initial;\\n --tw-ring-shadow: 0 0 #0000;\\n --tw-inset-ring-color: initial;\\n --tw-inset-ring-shadow: 0 0 #0000;\\n --tw-ring-inset: initial;\\n --tw-ring-offset-width: 0px;\\n --tw-ring-offset-color: #fff;\\n --tw-ring-offset-shadow: 0 0 #0000;\\n --tw-blur: initial;\\n --tw-brightness: initial;\\n --tw-contrast: initial;\\n --tw-grayscale: initial;\\n --tw-hue-rotate: initial;\\n --tw-invert: initial;\\n --tw-opacity: initial;\\n --tw-saturate: initial;\\n --tw-sepia: initial;\\n --tw-drop-shadow: initial;\\n --tw-drop-shadow-color: initial;\\n --tw-drop-shadow-alpha: 100%;\\n --tw-drop-shadow-size: initial;\\n --tw-backdrop-blur: initial;\\n --tw-backdrop-brightness: initial;\\n --tw-backdrop-contrast: initial;\\n --tw-backdrop-grayscale: initial;\\n --tw-backdrop-hue-rotate: initial;\\n --tw-backdrop-invert: initial;\\n --tw-backdrop-opacity: initial;\\n --tw-backdrop-saturate: initial;\\n --tw-backdrop-sepia: initial;\\n --tw-duration: initial;\\n --tw-ease: initial;\\n --tw-animation-delay: 0s;\\n --tw-animation-direction: normal;\\n --tw-animation-duration: initial;\\n --tw-animation-fill-mode: none;\\n --tw-animation-iteration-count: 1;\\n --tw-enter-blur: 0;\\n --tw-enter-opacity: 1;\\n --tw-enter-rotate: 0;\\n --tw-enter-scale: 1;\\n --tw-enter-translate-x: 0;\\n --tw-enter-translate-y: 0;\\n --tw-exit-blur: 0;\\n --tw-exit-opacity: 1;\\n --tw-exit-rotate: 0;\\n --tw-exit-scale: 1;\\n --tw-exit-translate-x: 0;\\n --tw-exit-translate-y: 0;\\n }\\n }\\n}\\n\")","\"use client\";\nimport \"../styles/viewer.css\";\n\nimport * as React from \"react\";\n\nimport { PGSGViewer } from \"../viewer/pgsg-viewer\";\nimport PGSGViewerControls from \"./PGSGViewControls\";\nimport { cn } from \"../lib/utils\";\n\nexport type PGSGCanvasProps = {\n src: string;\n className?: string;\n onReady?: (viewer: PGSGViewer) => void;\n type?: \"pgsg\" | \"ply\";\n colliderSrc?: string;\n};\n\nexport function PGSGCanvas({\n src,\n type = \"pgsg\",\n className,\n onReady,\n colliderSrc,\n}: PGSGCanvasProps) {\n const ref = React.useRef<HTMLDivElement | null>(null);\n const [viewer, setViewer] = React.useState<PGSGViewer | null>(null);\n\n React.useEffect(() => {\n if (!ref.current) return;\n\n const instance = new PGSGViewer({\n container: ref.current,\n source: { type: type, url: src },\n colliderSource: colliderSrc,\n debug: true,\n viewerType: \"three\",\n });\n\n setViewer(instance);\n\n instance.load().then(() => {\n onReady?.(instance);\n });\n\n return () => {\n instance.destroy();\n setViewer(null);\n };\n }, [src, type, colliderSrc]);\n\n return (\n <div\n ref={ref}\n className={cn(\"relative w-full h-full\", className)}\n style={{\n width: \"100%\",\n height: \"100%\",\n }}\n >\n <PGSGViewerControls viewer={viewer as any} />\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../lib/utils\";\nimport { PGSGViewer } from \"../core\";\nimport { PGSGThreeViewer } from \"../viewers/three\";\nimport { PGSGViewer3D } from \"./controls/PGSGViewer3D\";\nimport { PGSGViewerMode } from \"./controls/PGSGViewerMode\";\nimport { PGSGViewerSettings } from \"./controls/PGSGViewerSettings\";\nimport { Sparkles, X } from \"lucide-react\";\nimport { PGSGViewer3DSheet } from \"./controls/PGSGViewer3DSheet\";\n\nexport default function PGSGViewerControls({\n viewer,\n className,\n}: {\n viewer: PGSGThreeViewer | null;\n className?: string;\n}) {\n const [open, setOpen] = React.useState(false);\n\n if (!viewer) return null;\n\n return (\n <div\n className={cn(\n \"absolute top-0 right-0 h-full flex flex-row items-stretch z-50\",\n )}\n >\n <div className=\"flex flex-col justify-between items-end py-2 pr-2\">\n <PGSGViewerSettings viewer={viewer} />\n <div className=\"flex flex-col gap-2\">\n <PGSGViewer3D open={open} setOpen={setOpen} />\n <PGSGViewerMode viewer={viewer as unknown as PGSGViewer} />\n </div>\n </div>\n\n <div\n className={cn(\n \"overflow-hidden transition-all duration-300 ease-out w-0\",\n open && \"w-[360px]\",\n )}\n >\n <PGSGViewer3DSheet\n open={open}\n setOpen={setOpen}\n viewer={viewer as unknown as PGSGViewer}\n />\n </div>\n </div>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport const glass =\n \"bg-gradient-to-br from-white/20 to-white/5 dark:from-white/10 dark:to-transparent backdrop-blur-2xl border border-white/20 shadow-[0_8px_32px_rgba(0,0,0,0.25)]\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn, glass } from \"@/src/lib/utils\";\n\nexport function PGSGViewer3D({\n open,\n setOpen,\n}: {\n open: boolean;\n setOpen: (open: boolean) => void;\n}) {\n return (\n <div className=\"relative flex items-center flex-row-reverse overflow-hidden pointer-events-auto\">\n <button\n onClick={() => setOpen(!open)}\n className={cn(\n glass,\n \"p-3 rounded-full pointer-events-auto z-100 shadow-lg shadow-white/10 cursor-pointer\",\n open &&\n \"from-black/20 to-transparent border-black/20 dark:from-white/10 dark:to-white/5 dark:border-white/20\",\n )}\n >\n <span className=\"text-white font-semibold\">3D</span>\n </button>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n Rotate3D,\n RulerDimensionLine,\n Footprints,\n Icon,\n ChevronLeft,\n X,\n} from \"lucide-react\";\nimport { floorPlan } from \"@lucide/lab\";\n\nimport { PGSGViewer } from \"@/src/viewer/pgsg-viewer\";\nimport { type CameraMode } from \"@/src/viewers/types\";\nimport { cn, glass } from \"@/src/lib/utils\";\n\nexport function PGSGViewerMode({ viewer }: { viewer: PGSGViewer | null }) {\n const [mode, setMode] = React.useState<CameraMode>(\"orbit\");\n const [open, setOpen] = React.useState(false);\n\n const choose = (m: CameraMode) => {\n if (!viewer) return null;\n viewer.setCameraMode(m);\n setMode(m);\n setOpen(false);\n };\n\n React.useEffect(() => {\n if (!open) return;\n\n const onDown = (e: PointerEvent) => {\n const t = e.target as HTMLElement | null;\n if (!t?.closest(\"[data-pgsg-controls]\")) setOpen(false);\n };\n\n window.addEventListener(\"pointerdown\", onDown, { capture: true });\n return () =>\n window.removeEventListener(\"pointerdown\", onDown, {\n capture: true,\n } as any);\n }, [open]);\n\n let icon = null;\n switch (mode) {\n case \"walk\":\n icon = <Footprints className=\"size-5 text-white\" />;\n break;\n case \"orbit\":\n icon = <Rotate3D className=\"size-5 text-white\" />;\n break;\n case \"floorplan\":\n icon = <Icon iconNode={floorPlan} className=\"size-5 text-white\" />;\n break;\n case \"measure\":\n icon = <RulerDimensionLine className=\"size-5 text-white\" />;\n break;\n default:\n icon = <Rotate3D className=\"size-5 text-white\" />;\n break;\n }\n\n return (\n <div\n data-pgsg-controls\n className=\"relative flex items-center flex-row-reverse overflow-hidden pointer-events-auto\"\n >\n <div\n className={cn(\n glass,\n \"p-3 rounded-full pointer-events-auto z-100 shadow-lg shadow-white/10\",\n )}\n >\n {icon}\n </div>\n\n <div\n className={cn(\n \"flex items-center pointer-events-auto h-full overflow-hidden\",\n )}\n >\n <div\n className={cn(\n \"flex items-center h-full transition-all duration-300 ease-out\",\n open\n ? \"opacity-100 translate-x-full scale-95 pointer-events-none\"\n : \"opacity-100 translate-x-0 scale-100\",\n )}\n >\n <button\n onClick={() => setOpen(!open)}\n className=\"p-2.5 rounded-full pointer-events-auto\"\n >\n <ChevronLeft className=\"size-5 text-white\" />\n </button>\n </div>\n <div\n className={cn(\n glass,\n \"flex flex-row-reverse items-center gap-1.5 absolute bottom-0 right-0 h-full rounded-full pointer-events-auto transition-all duration-300 ease-out overflow-hidden pr-14 pl-2 shadow-none\",\n open\n ? \"opacity-100 translate-x-0 scale-100 max-w-[520px]\"\n : \"opacity-0 translate-x-6 scale-95 pointer-events-none max-w-0\",\n )}\n >\n <button\n onClick={() => choose(\"walk\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"walk\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <Footprints className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => choose(\"orbit\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"orbit\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <Rotate3D className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => choose(\"floorplan\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"floorplan\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <Icon iconNode={floorPlan} className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => setMode(\"measure\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"measure\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <RulerDimensionLine className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => setOpen(false)}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto delay-200 transition-opacity duration-200 ease-out cursor-pointer\",\n open ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n <X className=\"size-4 text-white/60\" />\n </button>\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Settings } from \"lucide-react\";\n\nimport { PGSGThreeViewer } from \"@/src/viewers/three\";\nimport { cn, glass } from \"@/src/lib/utils\";\n\nexport function PGSGViewerSettings({\n viewer,\n className,\n}: {\n viewer: PGSGThreeViewer | null;\n className?: string;\n}) {\n const [open, setOpen] = React.useState(false);\n const [grid, setGrid] = React.useState(false);\n\n if (!viewer) return null;\n\n return (\n <button\n onClick={() => setOpen(!open)}\n className={cn(glass, \"p-2.5 rounded-full pointer-events-auto\")}\n >\n <Settings className=\"size-4 text-white\" />\n </button>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Loader2, Sparkles, X } from \"lucide-react\";\n\nimport { cn, glass } from \"@/src/lib/utils\";\nimport { PGSGViewer } from \"@/src/core\";\n\nexport function PGSGViewer3DSheet({\n open,\n setOpen,\n viewer,\n}: {\n open: boolean;\n setOpen: (open: boolean) => void;\n viewer?: PGSGViewer | null;\n}) {\n const [text, setText] = React.useState(\"\");\n const [loading, setLoading] = React.useState(false);\n const [modelUrl, setModelUrl] = React.useState<string | null>(null);\n const [previewImage, setPreviewImage] = React.useState<string | null>(null);\n\n React.useEffect(() => {\n if (!viewer) return;\n\n viewer.enableInput(!open);\n }, [open, viewer]);\n\n const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n };\n\n const handleGenerateModel = async () => {\n if (!viewer) return;\n\n const prompt = text.trim();\n if (!prompt) return;\n\n setLoading(true);\n\n try {\n const res = await fetch(`http://localhost:9999/v1/mesh/text-to-3d`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ prompt }),\n });\n\n const data = await res.json();\n const modelUrl = `http://localhost:9999/v1/mesh/text-to-3d/${data.id}/model`;\n const previewUrl = `http://localhost:9999/v1/mesh/text-to-3d/${data.id}/generated`;\n\n setModelUrl(modelUrl);\n setPreviewImage(previewUrl);\n } catch (error) {\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n const handlePlaceModel = () => {\n if (!viewer || !modelUrl) return;\n\n viewer.enablePlacementMode(modelUrl);\n setOpen(false);\n };\n\n return (\n <>\n <div className=\"h-full w-[360px] bg-[rgba(15,15,15,0.9)] border-l border-l-white/1 backdrop-blur-(10px) p-3.5 text-white/60 z-100\">\n {/* Header */}\n <div className=\"flex items-center justify-between pb-2.5\">\n <h4 className=\"text-lg font-semibold\">Text to 3D Model</h4>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"p-2.5 rounded-full pointer-events-auto\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n <div className=\"flex items-center px-2 py-1.5 max-h-[60px] rounded-md bg-white/10 text-sm\">\n <div className=\"flex flex-1 h-full items-center relative\">\n <textarea\n rows={1}\n value={text}\n onChange={handleTextChange}\n placeholder=\"Describe your 3D model\"\n className=\"w-full resize-none outline-none bg-transparent text-white/60\"\n />\n </div>\n <button\n type=\"button\"\n onClick={handleGenerateModel}\n className={cn(\n \"bg-linear-to-br from-white/20 to-white/5 border border-white/20 px-2 py-1 rounded-full pointer-events-none transition-all duration-300 ease-out flex items-center gap-1 disabled:opacity-50\",\n text.trim() &&\n !loading &&\n \"pointer-events-auto hover:from-black/20 hover:to-transparent hover:border-black/10 cursor-pointer\",\n )}\n disabled={!text.trim() || loading}\n >\n <Sparkles className=\"size-4 text-white\" />\n <span className=\"text-white text-sm font-medium\">\n {loading ? \"Generating...\" : \"Generate\"}\n </span>\n </button>\n </div>\n {(text || text !== \"\") && (\n <div className=\"max-w-[300px] flex flex-wrap text-sm font-normal mt-2\">\n <strong>Prompt:</strong>\n <br />\n {text}\n </div>\n )}\n\n <div className=\"w-full relative mt-4\">\n <h3 className=\"text-base font-medium text-white mb-2\">Preview</h3>\n\n <div\n className={cn(\n glass,\n \"flex items-center justify-center w-full h-[320px] relative rounded-md overflow-hidden\",\n )}\n >\n {loading && (\n <>\n <Loader2\n className=\"size-4 animate-spin text-white\"\n role=\"status\"\n aria-label=\"loading\"\n />\n <span className=\"text-sm\">Generating AI Model...</span>\n </>\n )}\n\n {!loading && previewImage && (\n <div className=\"flex flex-col gap-3 w-full\">\n {previewImage && (\n <div className=\"rounded-md overflow-hidden border border-white/10\">\n <img src={previewImage} className=\"w-full object-cover\" />\n </div>\n )}\n <div className=\"flex gap-2\">\n <button\n onClick={handleGenerateModel}\n className=\"flex-1 px-3 py-2 rounded-md bg-white/10 hover:bg-white/20 text-sm\"\n >\n Regenerate\n </button>\n <button\n onClick={handlePlaceModel}\n className=\"flex-1 px-3 py-2 rounded-md bg-blue-500 hover:bg-blue-600 text-white text-sm\"\n >\n Place Model\n </button>\n </div>\n </div>\n )}\n\n {/* EMPTY STATE */}\n {!loading && !previewImage && (\n <span className=\"text-white/40 text-sm\">\n Your generated model will appear here\n </span>\n )}\n </div>\n </div>\n </div>\n </>\n );\n}\n"],"mappings":"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","names":["React","React","jsx","React","jsx","React","X","jsx","jsxs","modelUrl","X","jsx","jsxs","jsx"]}
|
|
1
|
+
{"version":3,"sources":["#style-inject:#style-inject","../../src/styles/viewer.css","../../src/react/PGSGCanvas.tsx","../../src/react/PGSGViewControls.tsx","../../src/lib/utils.ts","../../src/react/controls/PGSGViewer3D.tsx","../../src/react/controls/PGSGViewerMode.tsx","../../src/react/controls/PGSGViewerSettings.tsx","../../src/react/controls/PGSGViewer3DSheet.tsx"],"sourcesContent":["\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\"/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */\\n@layer properties;\\n@layer theme, base, components, utilities;\\n@layer theme {\\n :root,\\n :host {\\n --font-sans:\\n ui-sans-serif,\\n system-ui,\\n sans-serif,\\n \\\"Apple Color Emoji\\\",\\n \\\"Segoe UI Emoji\\\",\\n \\\"Segoe UI Symbol\\\",\\n \\\"Noto Color Emoji\\\";\\n --font-mono:\\n ui-monospace,\\n SFMono-Regular,\\n Menlo,\\n Monaco,\\n Consolas,\\n \\\"Liberation Mono\\\",\\n \\\"Courier New\\\",\\n monospace;\\n --color-blue-500: oklch(62.3% 0.214 259.815);\\n --color-blue-600: oklch(54.6% 0.245 262.881);\\n --color-black: #000;\\n --color-white: #fff;\\n --spacing: 0.25rem;\\n --text-sm: 0.875rem;\\n --text-sm--line-height: calc(1.25 / 0.875);\\n --text-base: 1rem;\\n --text-base--line-height: calc(1.5 / 1);\\n --text-lg: 1.125rem;\\n --text-lg--line-height: calc(1.75 / 1.125);\\n --font-weight-normal: 400;\\n --font-weight-medium: 500;\\n --font-weight-semibold: 600;\\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\\n --animate-spin: spin 1s linear infinite;\\n --blur-2xl: 40px;\\n --default-transition-duration: 150ms;\\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n --default-font-family: var(--font-sans);\\n --default-mono-font-family: var(--font-mono);\\n }\\n}\\n@layer base {\\n *,\\n ::after,\\n ::before,\\n ::backdrop,\\n ::file-selector-button {\\n box-sizing: border-box;\\n margin: 0;\\n padding: 0;\\n border: 0 solid;\\n }\\n html,\\n :host {\\n line-height: 1.5;\\n -webkit-text-size-adjust: 100%;\\n tab-size: 4;\\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \\\"Apple Color Emoji\\\", \\\"Segoe UI Emoji\\\", \\\"Segoe UI Symbol\\\", \\\"Noto Color Emoji\\\");\\n font-feature-settings: var(--default-font-feature-settings, normal);\\n font-variation-settings: var(--default-font-variation-settings, normal);\\n -webkit-tap-highlight-color: transparent;\\n }\\n hr {\\n height: 0;\\n color: inherit;\\n border-top-width: 1px;\\n }\\n abbr:where([title]) {\\n -webkit-text-decoration: underline dotted;\\n text-decoration: underline dotted;\\n }\\n h1,\\n h2,\\n h3,\\n h4,\\n h5,\\n h6 {\\n font-size: inherit;\\n font-weight: inherit;\\n }\\n a {\\n color: inherit;\\n -webkit-text-decoration: inherit;\\n text-decoration: inherit;\\n }\\n b,\\n strong {\\n font-weight: bolder;\\n }\\n code,\\n kbd,\\n samp,\\n pre {\\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \\\"Liberation Mono\\\", \\\"Courier New\\\", monospace);\\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\\n font-size: 1em;\\n }\\n small {\\n font-size: 80%;\\n }\\n sub,\\n sup {\\n font-size: 75%;\\n line-height: 0;\\n position: relative;\\n vertical-align: baseline;\\n }\\n sub {\\n bottom: -0.25em;\\n }\\n sup {\\n top: -0.5em;\\n }\\n table {\\n text-indent: 0;\\n border-color: inherit;\\n border-collapse: collapse;\\n }\\n :-moz-focusring {\\n outline: auto;\\n }\\n progress {\\n vertical-align: baseline;\\n }\\n summary {\\n display: list-item;\\n }\\n ol,\\n ul,\\n menu {\\n list-style: none;\\n }\\n img,\\n svg,\\n video,\\n canvas,\\n audio,\\n iframe,\\n embed,\\n object {\\n display: block;\\n vertical-align: middle;\\n }\\n img,\\n video {\\n max-width: 100%;\\n height: auto;\\n }\\n button,\\n input,\\n select,\\n optgroup,\\n textarea,\\n ::file-selector-button {\\n font: inherit;\\n font-feature-settings: inherit;\\n font-variation-settings: inherit;\\n letter-spacing: inherit;\\n color: inherit;\\n border-radius: 0;\\n background-color: transparent;\\n opacity: 1;\\n }\\n :where(select:is([multiple], [size])) optgroup {\\n font-weight: bolder;\\n }\\n :where(select:is([multiple], [size])) optgroup option {\\n padding-inline-start: 20px;\\n }\\n ::file-selector-button {\\n margin-inline-end: 4px;\\n }\\n ::placeholder {\\n opacity: 1;\\n }\\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\\n ::placeholder {\\n color: currentcolor;\\n @supports (color: color-mix(in lab, red, red)) {\\n color: color-mix(in oklab, currentcolor 50%, transparent);\\n }\\n }\\n }\\n textarea {\\n resize: vertical;\\n }\\n ::-webkit-search-decoration {\\n -webkit-appearance: none;\\n }\\n ::-webkit-date-and-time-value {\\n min-height: 1lh;\\n text-align: inherit;\\n }\\n ::-webkit-datetime-edit {\\n display: inline-flex;\\n }\\n ::-webkit-datetime-edit-fields-wrapper {\\n padding: 0;\\n }\\n ::-webkit-datetime-edit,\\n ::-webkit-datetime-edit-year-field,\\n ::-webkit-datetime-edit-month-field,\\n ::-webkit-datetime-edit-day-field,\\n ::-webkit-datetime-edit-hour-field,\\n ::-webkit-datetime-edit-minute-field,\\n ::-webkit-datetime-edit-second-field,\\n ::-webkit-datetime-edit-millisecond-field,\\n ::-webkit-datetime-edit-meridiem-field {\\n padding-block: 0;\\n }\\n ::-webkit-calendar-picker-indicator {\\n line-height: 1;\\n }\\n :-moz-ui-invalid {\\n box-shadow: none;\\n }\\n button,\\n input:where([type=button], [type=reset], [type=submit]),\\n ::file-selector-button {\\n appearance: button;\\n }\\n ::-webkit-inner-spin-button,\\n ::-webkit-outer-spin-button {\\n height: auto;\\n }\\n [hidden]:where(:not([hidden=until-found])) {\\n display: none !important;\\n }\\n}\\n@layer utilities {\\n .pointer-events-auto {\\n pointer-events: auto;\\n }\\n .pointer-events-none {\\n pointer-events: none;\\n }\\n .invisible {\\n visibility: hidden;\\n }\\n .visible {\\n visibility: visible;\\n }\\n .absolute {\\n position: absolute;\\n }\\n .relative {\\n position: relative;\\n }\\n .static {\\n position: static;\\n }\\n .start {\\n inset-inline-start: var(--spacing);\\n }\\n .end {\\n inset-inline-end: var(--spacing);\\n }\\n .top-0 {\\n top: calc(var(--spacing) * 0);\\n }\\n .right-0 {\\n right: calc(var(--spacing) * 0);\\n }\\n .bottom-0 {\\n bottom: calc(var(--spacing) * 0);\\n }\\n .z-50 {\\n z-index: 50;\\n }\\n .z-100 {\\n z-index: 100;\\n }\\n .col-span-2 {\\n grid-column: span 2 / span 2;\\n }\\n .container {\\n width: 100%;\\n @media (width >= 40rem) {\\n max-width: 40rem;\\n }\\n @media (width >= 48rem) {\\n max-width: 48rem;\\n }\\n @media (width >= 64rem) {\\n max-width: 64rem;\\n }\\n @media (width >= 80rem) {\\n max-width: 80rem;\\n }\\n @media (width >= 96rem) {\\n max-width: 96rem;\\n }\\n }\\n .mt-2 {\\n margin-top: calc(var(--spacing) * 2);\\n }\\n .mt-4 {\\n margin-top: calc(var(--spacing) * 4);\\n }\\n .mb-2 {\\n margin-bottom: calc(var(--spacing) * 2);\\n }\\n .block {\\n display: block;\\n }\\n .flex {\\n display: flex;\\n }\\n .grid {\\n display: grid;\\n }\\n .size-4 {\\n width: calc(var(--spacing) * 4);\\n height: calc(var(--spacing) * 4);\\n }\\n .size-5 {\\n width: calc(var(--spacing) * 5);\\n height: calc(var(--spacing) * 5);\\n }\\n .h-\\\\[320px\\\\] {\\n height: 320px;\\n }\\n .h-full {\\n height: 100%;\\n }\\n .max-h-\\\\[60px\\\\] {\\n max-height: 60px;\\n }\\n .w-0 {\\n width: calc(var(--spacing) * 0);\\n }\\n .w-\\\\[360px\\\\] {\\n width: 360px;\\n }\\n .w-full {\\n width: 100%;\\n }\\n .max-w-0 {\\n max-width: calc(var(--spacing) * 0);\\n }\\n .max-w-\\\\[300px\\\\] {\\n max-width: 300px;\\n }\\n .max-w-\\\\[520px\\\\] {\\n max-width: 520px;\\n }\\n .flex-1 {\\n flex: 1;\\n }\\n .translate-x-0 {\\n --tw-translate-x: calc(var(--spacing) * 0);\\n translate: var(--tw-translate-x) var(--tw-translate-y);\\n }\\n .translate-x-6 {\\n --tw-translate-x: calc(var(--spacing) * 6);\\n translate: var(--tw-translate-x) var(--tw-translate-y);\\n }\\n .translate-x-full {\\n --tw-translate-x: 100%;\\n translate: var(--tw-translate-x) var(--tw-translate-y);\\n }\\n .scale-95 {\\n --tw-scale-x: 95%;\\n --tw-scale-y: 95%;\\n --tw-scale-z: 95%;\\n scale: var(--tw-scale-x) var(--tw-scale-y);\\n }\\n .scale-100 {\\n --tw-scale-x: 100%;\\n --tw-scale-y: 100%;\\n --tw-scale-z: 100%;\\n scale: var(--tw-scale-x) var(--tw-scale-y);\\n }\\n .transform {\\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\\n }\\n .animate-spin {\\n animation: var(--animate-spin);\\n }\\n .cursor-default {\\n cursor: default;\\n }\\n .cursor-pointer {\\n cursor: pointer;\\n }\\n .resize-none {\\n resize: none;\\n }\\n .grid-cols-2 {\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\n }\\n .flex-col {\\n flex-direction: column;\\n }\\n .flex-row {\\n flex-direction: row;\\n }\\n .flex-row-reverse {\\n flex-direction: row-reverse;\\n }\\n .flex-wrap {\\n flex-wrap: wrap;\\n }\\n .items-center {\\n align-items: center;\\n }\\n .items-end {\\n align-items: flex-end;\\n }\\n .items-stretch {\\n align-items: stretch;\\n }\\n .justify-between {\\n justify-content: space-between;\\n }\\n .justify-center {\\n justify-content: center;\\n }\\n .gap-1 {\\n gap: calc(var(--spacing) * 1);\\n }\\n .gap-1\\\\.5 {\\n gap: calc(var(--spacing) * 1.5);\\n }\\n .gap-2 {\\n gap: calc(var(--spacing) * 2);\\n }\\n .gap-3 {\\n gap: calc(var(--spacing) * 3);\\n }\\n .overflow-auto {\\n overflow: auto;\\n }\\n .overflow-hidden {\\n overflow: hidden;\\n }\\n .rounded-full {\\n border-radius: calc(infinity * 1px);\\n }\\n .rounded-md {\\n border-radius: calc(var(--radius) - 2px);\\n }\\n .border {\\n border-style: var(--tw-border-style);\\n border-width: 1px;\\n }\\n .border-l {\\n border-left-style: var(--tw-border-style);\\n border-left-width: 1px;\\n }\\n .border-black\\\\/20 {\\n border-color: color-mix(in srgb, #000 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-black) 20%, transparent);\\n }\\n }\\n .border-white\\\\/10 {\\n border-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n }\\n .border-white\\\\/20 {\\n border-color: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n }\\n .border-l-white\\\\/1 {\\n border-left-color: color-mix(in srgb, #fff 1%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-left-color: color-mix(in oklab, var(--color-white) 1%, transparent);\\n }\\n }\\n .bg-\\\\[rgba\\\\(15\\\\,15\\\\,15\\\\,0\\\\.9\\\\)\\\\] {\\n background-color: rgba(15, 15, 15, 0.9);\\n }\\n .bg-blue-500 {\\n background-color: var(--color-blue-500);\\n }\\n .bg-transparent {\\n background-color: transparent;\\n }\\n .bg-white\\\\/10 {\\n background-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n }\\n .bg-linear-to-br {\\n --tw-gradient-position: to bottom right;\\n @supports (background-image: linear-gradient(in lab, red, red)) {\\n --tw-gradient-position: to bottom right in oklab;\\n }\\n background-image: linear-gradient(var(--tw-gradient-stops));\\n }\\n .bg-gradient-to-br {\\n --tw-gradient-position: to bottom right in oklab;\\n background-image: linear-gradient(var(--tw-gradient-stops));\\n }\\n .from-black\\\\/20 {\\n --tw-gradient-from: color-mix(in srgb, #000 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 20%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .from-white\\\\/20 {\\n --tw-gradient-from: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .to-transparent {\\n --tw-gradient-to: transparent;\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .to-white\\\\/5 {\\n --tw-gradient-to: color-mix(in srgb, #fff 5%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-to: color-mix(in oklab, var(--color-white) 5%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n .object-cover {\\n object-fit: cover;\\n }\\n .p-2\\\\.5 {\\n padding: calc(var(--spacing) * 2.5);\\n }\\n .p-3 {\\n padding: calc(var(--spacing) * 3);\\n }\\n .p-3\\\\.5 {\\n padding: calc(var(--spacing) * 3.5);\\n }\\n .px-2 {\\n padding-inline: calc(var(--spacing) * 2);\\n }\\n .px-3 {\\n padding-inline: calc(var(--spacing) * 3);\\n }\\n .py-1 {\\n padding-block: calc(var(--spacing) * 1);\\n }\\n .py-1\\\\.5 {\\n padding-block: calc(var(--spacing) * 1.5);\\n }\\n .py-2 {\\n padding-block: calc(var(--spacing) * 2);\\n }\\n .py-4 {\\n padding-block: calc(var(--spacing) * 4);\\n }\\n .pr-2 {\\n padding-right: calc(var(--spacing) * 2);\\n }\\n .pr-14 {\\n padding-right: calc(var(--spacing) * 14);\\n }\\n .pb-2\\\\.5 {\\n padding-bottom: calc(var(--spacing) * 2.5);\\n }\\n .pl-2 {\\n padding-left: calc(var(--spacing) * 2);\\n }\\n .text-center {\\n text-align: center;\\n }\\n .text-base {\\n font-size: var(--text-base);\\n line-height: var(--tw-leading, var(--text-base--line-height));\\n }\\n .text-lg {\\n font-size: var(--text-lg);\\n line-height: var(--tw-leading, var(--text-lg--line-height));\\n }\\n .text-sm {\\n font-size: var(--text-sm);\\n line-height: var(--tw-leading, var(--text-sm--line-height));\\n }\\n .font-medium {\\n --tw-font-weight: var(--font-weight-medium);\\n font-weight: var(--font-weight-medium);\\n }\\n .font-normal {\\n --tw-font-weight: var(--font-weight-normal);\\n font-weight: var(--font-weight-normal);\\n }\\n .font-semibold {\\n --tw-font-weight: var(--font-weight-semibold);\\n font-weight: var(--font-weight-semibold);\\n }\\n .text-white {\\n color: var(--color-white);\\n }\\n .text-white\\\\/40 {\\n color: color-mix(in srgb, #fff 40%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n color: color-mix(in oklab, var(--color-white) 40%, transparent);\\n }\\n }\\n .text-white\\\\/60 {\\n color: color-mix(in srgb, #fff 60%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n color: color-mix(in oklab, var(--color-white) 60%, transparent);\\n }\\n }\\n .opacity-0 {\\n opacity: 0%;\\n }\\n .opacity-100 {\\n opacity: 100%;\\n }\\n .shadow-\\\\[0_8px_32px_rgba\\\\(0\\\\,0\\\\,0\\\\,0\\\\.25\\\\)\\\\] {\\n --tw-shadow: 0 8px 32px var(--tw-shadow-color, rgba(0,0,0,0.25));\\n box-shadow:\\n var(--tw-inset-shadow),\\n var(--tw-inset-ring-shadow),\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow);\\n }\\n .shadow-lg {\\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\\n box-shadow:\\n var(--tw-inset-shadow),\\n var(--tw-inset-ring-shadow),\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow);\\n }\\n .shadow-none {\\n --tw-shadow: 0 0 #0000;\\n box-shadow:\\n var(--tw-inset-shadow),\\n var(--tw-inset-ring-shadow),\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow);\\n }\\n .shadow-white\\\\/10 {\\n --tw-shadow-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-shadow-color: color-mix(in oklab, color-mix(in oklab, var(--color-white) 10%, transparent) var(--tw-shadow-alpha), transparent);\\n }\\n }\\n .outline {\\n outline-style: var(--tw-outline-style);\\n outline-width: 1px;\\n }\\n .blur {\\n --tw-blur: blur(8px);\\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\\n }\\n .filter {\\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\\n }\\n .backdrop-blur-2xl {\\n --tw-backdrop-blur: blur(var(--blur-2xl));\\n -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\\n backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);\\n }\\n .transition {\\n transition-property:\\n color,\\n background-color,\\n border-color,\\n outline-color,\\n text-decoration-color,\\n fill,\\n stroke,\\n --tw-gradient-from,\\n --tw-gradient-via,\\n --tw-gradient-to,\\n opacity,\\n box-shadow,\\n transform,\\n translate,\\n scale,\\n rotate,\\n filter,\\n -webkit-backdrop-filter,\\n backdrop-filter,\\n display,\\n content-visibility,\\n overlay,\\n pointer-events;\\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\\n transition-duration: var(--tw-duration, var(--default-transition-duration));\\n }\\n .transition-all {\\n transition-property: all;\\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\\n transition-duration: var(--tw-duration, var(--default-transition-duration));\\n }\\n .transition-opacity {\\n transition-property: opacity;\\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\\n transition-duration: var(--tw-duration, var(--default-transition-duration));\\n }\\n .delay-200 {\\n transition-delay: 200ms;\\n }\\n .duration-200 {\\n --tw-duration: 200ms;\\n transition-duration: 200ms;\\n }\\n .duration-300 {\\n --tw-duration: 300ms;\\n transition-duration: 300ms;\\n }\\n .ease-out {\\n --tw-ease: var(--ease-out);\\n transition-timing-function: var(--ease-out);\\n }\\n .delay-200 {\\n animation-delay: calc(200*1ms);\\n animation-delay: .2s;\\n --tw-animation-delay: calc(200*1ms);\\n --tw-animation-delay: .2s;\\n }\\n .outline-none {\\n --tw-outline-style: none;\\n outline-style: none;\\n }\\n .running {\\n animation-play-state: running;\\n }\\n .hover\\\\:border-black\\\\/10 {\\n &:hover {\\n @media (hover: hover) {\\n border-color: color-mix(in srgb, #000 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-black) 10%, transparent);\\n }\\n }\\n }\\n }\\n .hover\\\\:border-white\\\\/30 {\\n &:hover {\\n @media (hover: hover) {\\n border-color: color-mix(in srgb, #fff 30%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-white) 30%, transparent);\\n }\\n }\\n }\\n }\\n .hover\\\\:bg-blue-600 {\\n &:hover {\\n @media (hover: hover) {\\n background-color: var(--color-blue-600);\\n }\\n }\\n }\\n .hover\\\\:bg-white\\\\/10 {\\n &:hover {\\n @media (hover: hover) {\\n background-color: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n background-color: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n }\\n }\\n }\\n .hover\\\\:bg-white\\\\/20 {\\n &:hover {\\n @media (hover: hover) {\\n background-color: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n background-color: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n }\\n }\\n }\\n .hover\\\\:from-black\\\\/20 {\\n &:hover {\\n @media (hover: hover) {\\n --tw-gradient-from: color-mix(in srgb, #000 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 20%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n }\\n .hover\\\\:to-transparent {\\n &:hover {\\n @media (hover: hover) {\\n --tw-gradient-to: transparent;\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n }\\n .disabled\\\\:opacity-50 {\\n &:disabled {\\n opacity: 50%;\\n }\\n }\\n .dark\\\\:border-white\\\\/20 {\\n &:is(.dark *) {\\n border-color: color-mix(in srgb, #fff 20%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n border-color: color-mix(in oklab, var(--color-white) 20%, transparent);\\n }\\n }\\n }\\n .dark\\\\:from-white\\\\/10 {\\n &:is(.dark *) {\\n --tw-gradient-from: color-mix(in srgb, #fff 10%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-from: color-mix(in oklab, var(--color-white) 10%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n .dark\\\\:to-transparent {\\n &:is(.dark *) {\\n --tw-gradient-to: transparent;\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n .dark\\\\:to-white\\\\/5 {\\n &:is(.dark *) {\\n --tw-gradient-to: color-mix(in srgb, #fff 5%, transparent);\\n @supports (color: color-mix(in lab, red, red)) {\\n --tw-gradient-to: color-mix(in oklab, var(--color-white) 5%, transparent);\\n }\\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\\n }\\n }\\n}\\n@property --tw-animation-delay { syntax: \\\"*\\\"; inherits: false; initial-value: 0s; }\\n@property --tw-animation-direction { syntax: \\\"*\\\"; inherits: false; initial-value: normal; }\\n@property --tw-animation-duration { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-animation-fill-mode { syntax: \\\"*\\\"; inherits: false; initial-value: none; }\\n@property --tw-animation-iteration-count { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-enter-blur { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-enter-opacity { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-enter-rotate { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-enter-scale { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-enter-translate-x { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-enter-translate-y { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-blur { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-opacity { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-exit-rotate { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-scale { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-exit-translate-x { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-exit-translate-y { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n:root {\\n --radius: 0.625rem;\\n --background: oklch(1 0 0);\\n --foreground: oklch(0.145 0 0);\\n --card: oklch(1 0 0);\\n --card-foreground: oklch(0.145 0 0);\\n --popover: oklch(1 0 0);\\n --popover-foreground: oklch(0.145 0 0);\\n --primary: oklch(0.205 0 0);\\n --primary-foreground: oklch(0.985 0 0);\\n --secondary: oklch(0.97 0 0);\\n --secondary-foreground: oklch(0.205 0 0);\\n --muted: oklch(0.97 0 0);\\n --muted-foreground: oklch(0.556 0 0);\\n --accent: oklch(0.97 0 0);\\n --accent-foreground: oklch(0.205 0 0);\\n --destructive: oklch(0.577 0.245 27.325);\\n --border: oklch(0.922 0 0);\\n --input: oklch(0.922 0 0);\\n --ring: oklch(0.708 0 0);\\n --chart-1: oklch(0.646 0.222 41.116);\\n --chart-2: oklch(0.6 0.118 184.704);\\n --chart-3: oklch(0.398 0.07 227.392);\\n --chart-4: oklch(0.828 0.189 84.429);\\n --chart-5: oklch(0.769 0.188 70.08);\\n --sidebar: oklch(0.985 0 0);\\n --sidebar-foreground: oklch(0.145 0 0);\\n --sidebar-primary: oklch(0.205 0 0);\\n --sidebar-primary-foreground: oklch(0.985 0 0);\\n --sidebar-accent: oklch(0.97 0 0);\\n --sidebar-accent-foreground: oklch(0.205 0 0);\\n --sidebar-border: oklch(0.922 0 0);\\n --sidebar-ring: oklch(0.708 0 0);\\n}\\n.dark {\\n --background: oklch(0.145 0 0);\\n --foreground: oklch(0.985 0 0);\\n --card: oklch(0.205 0 0);\\n --card-foreground: oklch(0.985 0 0);\\n --popover: oklch(0.205 0 0);\\n --popover-foreground: oklch(0.985 0 0);\\n --primary: oklch(0.922 0 0);\\n --primary-foreground: oklch(0.205 0 0);\\n --secondary: oklch(0.269 0 0);\\n --secondary-foreground: oklch(0.985 0 0);\\n --muted: oklch(0.269 0 0);\\n --muted-foreground: oklch(0.708 0 0);\\n --accent: oklch(0.269 0 0);\\n --accent-foreground: oklch(0.985 0 0);\\n --destructive: oklch(0.704 0.191 22.216);\\n --border: oklch(1 0 0 / 10%);\\n --input: oklch(1 0 0 / 15%);\\n --ring: oklch(0.556 0 0);\\n --chart-1: oklch(0.488 0.243 264.376);\\n --chart-2: oklch(0.696 0.17 162.48);\\n --chart-3: oklch(0.769 0.188 70.08);\\n --chart-4: oklch(0.627 0.265 303.9);\\n --chart-5: oklch(0.645 0.246 16.439);\\n --sidebar: oklch(0.205 0 0);\\n --sidebar-foreground: oklch(0.985 0 0);\\n --sidebar-primary: oklch(0.488 0.243 264.376);\\n --sidebar-primary-foreground: oklch(0.985 0 0);\\n --sidebar-accent: oklch(0.269 0 0);\\n --sidebar-accent-foreground: oklch(0.985 0 0);\\n --sidebar-border: oklch(1 0 0 / 10%);\\n --sidebar-ring: oklch(0.556 0 0);\\n}\\n@layer base {\\n * {\\n border-color: var(--border);\\n outline-color: var(--ring);\\n @supports (color: color-mix(in lab, red, red)) {\\n outline-color: color-mix(in oklab, var(--ring) 50%, transparent);\\n }\\n }\\n body {\\n background-color: var(--background);\\n color: var(--foreground);\\n }\\n}\\n@property --tw-translate-x { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-translate-y { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-translate-z { syntax: \\\"*\\\"; inherits: false; initial-value: 0; }\\n@property --tw-scale-x { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-scale-y { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-scale-z { syntax: \\\"*\\\"; inherits: false; initial-value: 1; }\\n@property --tw-rotate-x { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-rotate-y { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-rotate-z { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-skew-x { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-skew-y { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-border-style { syntax: \\\"*\\\"; inherits: false; initial-value: solid; }\\n@property --tw-gradient-position { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-gradient-from { syntax: \\\"<color>\\\"; inherits: false; initial-value: #0000; }\\n@property --tw-gradient-via { syntax: \\\"<color>\\\"; inherits: false; initial-value: #0000; }\\n@property --tw-gradient-to { syntax: \\\"<color>\\\"; inherits: false; initial-value: #0000; }\\n@property --tw-gradient-stops { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-gradient-via-stops { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-gradient-from-position { syntax: \\\"<length-percentage>\\\"; inherits: false; initial-value: 0%; }\\n@property --tw-gradient-via-position { syntax: \\\"<length-percentage>\\\"; inherits: false; initial-value: 50%; }\\n@property --tw-gradient-to-position { syntax: \\\"<length-percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-font-weight { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-shadow-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-shadow-alpha { syntax: \\\"<percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-inset-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-inset-shadow-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-inset-shadow-alpha { syntax: \\\"<percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-ring-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-ring-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-inset-ring-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-inset-ring-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-ring-inset { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-ring-offset-width { syntax: \\\"<length>\\\"; inherits: false; initial-value: 0px; }\\n@property --tw-ring-offset-color { syntax: \\\"*\\\"; inherits: false; initial-value: #fff; }\\n@property --tw-ring-offset-shadow { syntax: \\\"*\\\"; inherits: false; initial-value: 0 0 #0000; }\\n@property --tw-outline-style { syntax: \\\"*\\\"; inherits: false; initial-value: solid; }\\n@property --tw-blur { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-brightness { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-contrast { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-grayscale { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-hue-rotate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-invert { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-opacity { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-saturate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-sepia { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-drop-shadow { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-drop-shadow-color { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-drop-shadow-alpha { syntax: \\\"<percentage>\\\"; inherits: false; initial-value: 100%; }\\n@property --tw-drop-shadow-size { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-blur { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-brightness { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-contrast { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-grayscale { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-hue-rotate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-invert { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-opacity { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-saturate { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-backdrop-sepia { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-duration { syntax: \\\"*\\\"; inherits: false; }\\n@property --tw-ease { syntax: \\\"*\\\"; inherits: false; }\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n@layer properties {\\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\\n *,\\n ::before,\\n ::after,\\n ::backdrop {\\n --tw-translate-x: 0;\\n --tw-translate-y: 0;\\n --tw-translate-z: 0;\\n --tw-scale-x: 1;\\n --tw-scale-y: 1;\\n --tw-scale-z: 1;\\n --tw-rotate-x: initial;\\n --tw-rotate-y: initial;\\n --tw-rotate-z: initial;\\n --tw-skew-x: initial;\\n --tw-skew-y: initial;\\n --tw-border-style: solid;\\n --tw-gradient-position: initial;\\n --tw-gradient-from: #0000;\\n --tw-gradient-via: #0000;\\n --tw-gradient-to: #0000;\\n --tw-gradient-stops: initial;\\n --tw-gradient-via-stops: initial;\\n --tw-gradient-from-position: 0%;\\n --tw-gradient-via-position: 50%;\\n --tw-gradient-to-position: 100%;\\n --tw-font-weight: initial;\\n --tw-shadow: 0 0 #0000;\\n --tw-shadow-color: initial;\\n --tw-shadow-alpha: 100%;\\n --tw-inset-shadow: 0 0 #0000;\\n --tw-inset-shadow-color: initial;\\n --tw-inset-shadow-alpha: 100%;\\n --tw-ring-color: initial;\\n --tw-ring-shadow: 0 0 #0000;\\n --tw-inset-ring-color: initial;\\n --tw-inset-ring-shadow: 0 0 #0000;\\n --tw-ring-inset: initial;\\n --tw-ring-offset-width: 0px;\\n --tw-ring-offset-color: #fff;\\n --tw-ring-offset-shadow: 0 0 #0000;\\n --tw-outline-style: solid;\\n --tw-blur: initial;\\n --tw-brightness: initial;\\n --tw-contrast: initial;\\n --tw-grayscale: initial;\\n --tw-hue-rotate: initial;\\n --tw-invert: initial;\\n --tw-opacity: initial;\\n --tw-saturate: initial;\\n --tw-sepia: initial;\\n --tw-drop-shadow: initial;\\n --tw-drop-shadow-color: initial;\\n --tw-drop-shadow-alpha: 100%;\\n --tw-drop-shadow-size: initial;\\n --tw-backdrop-blur: initial;\\n --tw-backdrop-brightness: initial;\\n --tw-backdrop-contrast: initial;\\n --tw-backdrop-grayscale: initial;\\n --tw-backdrop-hue-rotate: initial;\\n --tw-backdrop-invert: initial;\\n --tw-backdrop-opacity: initial;\\n --tw-backdrop-saturate: initial;\\n --tw-backdrop-sepia: initial;\\n --tw-duration: initial;\\n --tw-ease: initial;\\n --tw-animation-delay: 0s;\\n --tw-animation-direction: normal;\\n --tw-animation-duration: initial;\\n --tw-animation-fill-mode: none;\\n --tw-animation-iteration-count: 1;\\n --tw-enter-blur: 0;\\n --tw-enter-opacity: 1;\\n --tw-enter-rotate: 0;\\n --tw-enter-scale: 1;\\n --tw-enter-translate-x: 0;\\n --tw-enter-translate-y: 0;\\n --tw-exit-blur: 0;\\n --tw-exit-opacity: 1;\\n --tw-exit-rotate: 0;\\n --tw-exit-scale: 1;\\n --tw-exit-translate-x: 0;\\n --tw-exit-translate-y: 0;\\n }\\n }\\n}\\n\")","\"use client\";\nimport \"../styles/viewer.css\";\n\nimport * as React from \"react\";\n\nimport { PGSGViewer } from \"../viewer/pgsg-viewer\";\nimport PGSGViewerControls from \"./PGSGViewControls\";\nimport { cn } from \"../lib/utils\";\n\nexport type PGSGCanvasProps = {\n src: string;\n className?: string;\n onReady?: (viewer: PGSGViewer) => void;\n type?: \"pgsg\" | \"ply\";\n colliderSrc?: string;\n};\n\nexport function PGSGCanvas({\n src,\n type = \"pgsg\",\n className,\n onReady,\n colliderSrc,\n}: PGSGCanvasProps) {\n const ref = React.useRef<HTMLDivElement | null>(null);\n const [viewer, setViewer] = React.useState<PGSGViewer | null>(null);\n\n React.useEffect(() => {\n if (!ref.current) return;\n\n const instance = new PGSGViewer({\n container: ref.current,\n source: { type: type, url: src },\n colliderSource: colliderSrc,\n debug: true,\n viewerType: \"three\",\n });\n\n setViewer(instance);\n\n instance.load().then(() => {\n onReady?.(instance);\n });\n\n return () => {\n instance.destroy();\n setViewer(null);\n };\n }, [src, type, colliderSrc]);\n\n return (\n <div\n ref={ref}\n className={cn(\"relative w-full h-full\", className)}\n style={{\n width: \"100%\",\n height: \"100%\",\n }}\n >\n <PGSGViewerControls viewer={viewer as any} />\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../lib/utils\";\nimport { PGSGViewer } from \"../core\";\nimport { PGSGThreeViewer } from \"../viewers/three\";\nimport { PGSGViewer3D } from \"./controls/PGSGViewer3D\";\nimport { PGSGViewerMode } from \"./controls/PGSGViewerMode\";\nimport { PGSGViewerSettings } from \"./controls/PGSGViewerSettings\";\nimport { Sparkles, X } from \"lucide-react\";\nimport { PGSGViewer3DSheet } from \"./controls/PGSGViewer3DSheet\";\n\nexport default function PGSGViewerControls({\n viewer,\n className,\n}: {\n viewer: PGSGThreeViewer | null;\n className?: string;\n}) {\n const [open, setOpen] = React.useState(false);\n\n if (!viewer) return null;\n\n return (\n <div\n className={cn(\n \"absolute top-0 right-0 h-full flex flex-row items-stretch z-50\",\n )}\n >\n <div className=\"flex flex-col justify-between items-end py-2 pr-2\">\n <PGSGViewerSettings viewer={viewer} />\n <div className=\"flex flex-col gap-2\">\n <PGSGViewer3D open={open} setOpen={setOpen} />\n <PGSGViewerMode viewer={viewer as unknown as PGSGViewer} />\n </div>\n </div>\n\n <div\n className={cn(\n \"overflow-hidden transition-all duration-300 ease-out w-0\",\n open && \"w-[360px]\",\n )}\n >\n <PGSGViewer3DSheet\n open={open}\n setOpen={setOpen}\n viewer={viewer as unknown as PGSGViewer}\n />\n </div>\n </div>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport const glass =\n \"bg-gradient-to-br from-white/20 to-white/5 dark:from-white/10 dark:to-transparent backdrop-blur-2xl border border-white/20 shadow-[0_8px_32px_rgba(0,0,0,0.25)]\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn, glass } from \"@/src/lib/utils\";\n\nexport function PGSGViewer3D({\n open,\n setOpen,\n}: {\n open: boolean;\n setOpen: (open: boolean) => void;\n}) {\n return (\n <div className=\"relative flex items-center flex-row-reverse overflow-hidden pointer-events-auto\">\n <button\n onClick={() => setOpen(!open)}\n className={cn(\n glass,\n \"p-3 rounded-full pointer-events-auto z-100 shadow-lg shadow-white/10 cursor-pointer\",\n open &&\n \"from-black/20 to-transparent border-black/20 dark:from-white/10 dark:to-white/5 dark:border-white/20\",\n )}\n >\n <span className=\"text-white font-semibold\">3D</span>\n </button>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n Rotate3D,\n RulerDimensionLine,\n Footprints,\n Icon,\n ChevronLeft,\n X,\n} from \"lucide-react\";\nimport { floorPlan } from \"@lucide/lab\";\n\nimport { PGSGViewer } from \"@/src/viewer/pgsg-viewer\";\nimport { type CameraMode } from \"@/src/viewers/types\";\nimport { cn, glass } from \"@/src/lib/utils\";\n\nexport function PGSGViewerMode({ viewer }: { viewer: PGSGViewer | null }) {\n const [mode, setMode] = React.useState<CameraMode>(\"orbit\");\n const [open, setOpen] = React.useState(false);\n\n const choose = (m: CameraMode) => {\n if (!viewer) return null;\n viewer.setCameraMode(m);\n setMode(m);\n setOpen(false);\n };\n\n React.useEffect(() => {\n if (!open) return;\n\n const onDown = (e: PointerEvent) => {\n const t = e.target as HTMLElement | null;\n if (!t?.closest(\"[data-pgsg-controls]\")) setOpen(false);\n };\n\n window.addEventListener(\"pointerdown\", onDown, { capture: true });\n return () =>\n window.removeEventListener(\"pointerdown\", onDown, {\n capture: true,\n } as any);\n }, [open]);\n\n let icon = null;\n switch (mode) {\n case \"walk\":\n icon = <Footprints className=\"size-5 text-white\" />;\n break;\n case \"orbit\":\n icon = <Rotate3D className=\"size-5 text-white\" />;\n break;\n case \"floorplan\":\n icon = <Icon iconNode={floorPlan} className=\"size-5 text-white\" />;\n break;\n case \"measure\":\n icon = <RulerDimensionLine className=\"size-5 text-white\" />;\n break;\n default:\n icon = <Rotate3D className=\"size-5 text-white\" />;\n break;\n }\n\n return (\n <div\n data-pgsg-controls\n className=\"relative flex items-center flex-row-reverse overflow-hidden pointer-events-auto\"\n >\n <div\n className={cn(\n glass,\n \"p-3 rounded-full pointer-events-auto z-100 shadow-lg shadow-white/10\",\n )}\n >\n {icon}\n </div>\n\n <div\n className={cn(\n \"flex items-center pointer-events-auto h-full overflow-hidden\",\n )}\n >\n <div\n className={cn(\n \"flex items-center h-full transition-all duration-300 ease-out\",\n open\n ? \"opacity-100 translate-x-full scale-95 pointer-events-none\"\n : \"opacity-100 translate-x-0 scale-100\",\n )}\n >\n <button\n onClick={() => setOpen(!open)}\n className=\"p-2.5 rounded-full pointer-events-auto\"\n >\n <ChevronLeft className=\"size-5 text-white\" />\n </button>\n </div>\n <div\n className={cn(\n glass,\n \"flex flex-row-reverse items-center gap-1.5 absolute bottom-0 right-0 h-full rounded-full pointer-events-auto transition-all duration-300 ease-out overflow-hidden pr-14 pl-2 shadow-none\",\n open\n ? \"opacity-100 translate-x-0 scale-100 max-w-[520px]\"\n : \"opacity-0 translate-x-6 scale-95 pointer-events-none max-w-0\",\n )}\n >\n <button\n onClick={() => choose(\"walk\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"walk\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <Footprints className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => choose(\"orbit\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"orbit\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <Rotate3D className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => choose(\"floorplan\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"floorplan\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <Icon iconNode={floorPlan} className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => setMode(\"measure\")}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto transition-all duration-300 ease-out\",\n mode === \"measure\"\n ? \"bg-white/10 cursor-default\"\n : \"hover:bg-white/10 cursor-pointer\",\n )}\n >\n <RulerDimensionLine className=\"size-4 text-white\" />\n </button>\n <button\n onClick={() => setOpen(false)}\n className={cn(\n \"p-2.5 rounded-full pointer-events-auto delay-200 transition-opacity duration-200 ease-out cursor-pointer\",\n open ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n <X className=\"size-4 text-white/60\" />\n </button>\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Settings } from \"lucide-react\";\n\nimport { PGSGThreeViewer } from \"@/src/viewers/three\";\nimport { cn, glass } from \"@/src/lib/utils\";\n\nexport function PGSGViewerSettings({\n viewer,\n className,\n}: {\n viewer: PGSGThreeViewer | null;\n className?: string;\n}) {\n const [open, setOpen] = React.useState(false);\n const [grid, setGrid] = React.useState(false);\n\n if (!viewer) return null;\n\n return (\n <button\n onClick={() => setOpen(!open)}\n className={cn(glass, \"p-2.5 rounded-full pointer-events-auto\")}\n >\n <Settings className=\"size-4 text-white\" />\n </button>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Loader2, Sparkles, X } from \"lucide-react\";\n\nimport { cn, glass } from \"@/src/lib/utils\";\nimport { PGSGViewer } from \"@/src/core\";\n\ntype LibraryModel = {\n _id: string;\n task_id: string;\n model_url: string;\n preview_url: string;\n prompt?: string;\n};\n\nexport function PGSGViewer3DSheet({\n open,\n setOpen,\n viewer,\n}: {\n open: boolean;\n setOpen: (open: boolean) => void;\n viewer?: PGSGViewer | null;\n}) {\n const [text, setText] = React.useState(\"\");\n const [loading, setLoading] = React.useState(false);\n const [modelUrl, setModelUrl] = React.useState<string | null>(null);\n const [previewImage, setPreviewImage] = React.useState<string | null>(null);\n const [library, setLibrary] = React.useState<LibraryModel[]>([]);\n const [page, setPage] = React.useState(1);\n const [hasMore, setHasMore] = React.useState(true);\n const [isLibraryLoading, setIsLibraryLoading] = React.useState(false);\n\n const loaderRef = React.useRef<HTMLDivElement | null>(null);\n\n React.useEffect(() => {\n if (!viewer) return;\n\n viewer.enableInput(!open);\n }, [open, viewer]);\n\n const loadLibrary = async (pageToLoad: number) => {\n try {\n setIsLibraryLoading(true);\n\n const res = await fetch(\n `http://localhost:9999/v1/mesh/get?page=${pageToLoad}`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n const data = await res.json();\n\n let sorted = data.data.sort(\n (a: any, b: any) => b.createdAt - a.createdAt,\n );\n\n const payload = sorted.map((item: any) => ({\n _id: item._id,\n task_id: item.task_id,\n model_url: `http://localhost:9999/v1/mesh/text-to-3d/${item._id}/model`,\n preview_url: `http://localhost:9999/v1/mesh/text-to-3d/${item._id}/generated`,\n prompt: item.input.prompt,\n }));\n\n setLibrary((prev) => [...prev, ...(payload || [])]);\n setHasMore(data.meta.hasMore ?? false);\n setPage(pageToLoad);\n } catch (error) {\n console.error(\"Failed to load model library\", error);\n } finally {\n setIsLibraryLoading(false);\n }\n };\n\n React.useEffect(() => {\n if (!open) return;\n\n setLibrary([]);\n setPage(1);\n setHasMore(true);\n\n loadLibrary(1);\n }, [open]);\n\n React.useEffect(() => {\n if (!loaderRef.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0].isIntersecting && hasMore && !isLibraryLoading) {\n loadLibrary(page + 1);\n }\n },\n {\n rootMargin: \"200px\",\n },\n );\n\n observer.observe(loaderRef.current);\n\n return () => observer.disconnect();\n }, [page, hasMore, isLibraryLoading]);\n\n const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n };\n\n const handleGenerateModel = async () => {\n if (!viewer) return;\n\n const prompt = text.trim();\n if (!prompt) return;\n\n setLoading(true);\n\n try {\n const res = await fetch(`http://localhost:9999/v1/mesh/text-to-3d`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ prompt }),\n });\n\n const data = await res.json();\n const modelUrl = `http://localhost:9999/v1/mesh/text-to-3d/${data.id}/model`;\n const previewUrl = `http://localhost:9999/v1/mesh/text-to-3d/${data.id}/generated`;\n\n setModelUrl(modelUrl);\n setPreviewImage(previewUrl);\n } catch (error) {\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n const handlePlaceModel = () => {\n if (!viewer || !modelUrl) return;\n\n viewer.enablePlacementMode(modelUrl);\n setOpen(false);\n };\n\n const handlePlaceLibraryModel = (modelUrl: string) => {\n if (!viewer) return;\n\n viewer.enablePlacementMode(modelUrl);\n setOpen(false);\n };\n\n return (\n <>\n <div\n onWheel={(e) => e.stopPropagation()}\n className=\"h-full w-[360px] bg-[rgba(15,15,15,0.9)] border-l border-l-white/1 backdrop-blur-(10px) p-3.5 text-white/60 z-100 overflow-auto\"\n >\n {/* Header */}\n <div className=\"flex items-center justify-between pb-2.5\">\n <h4 className=\"text-lg font-semibold\">Text to 3D Model</h4>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"p-2.5 rounded-full pointer-events-auto\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n <div className=\"flex items-center px-2 py-1.5 max-h-[60px] rounded-md bg-white/10 text-sm\">\n <div className=\"flex flex-1 h-full items-center relative\">\n <textarea\n rows={1}\n value={text}\n onChange={handleTextChange}\n onWheel={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n placeholder=\"Describe your 3D model\"\n className=\"w-full resize-none outline-none bg-transparent text-white/60\"\n />\n </div>\n <button\n type=\"button\"\n onClick={handleGenerateModel}\n className={cn(\n \"bg-linear-to-br from-white/20 to-white/5 border border-white/20 px-2 py-1 rounded-full pointer-events-none transition-all duration-300 ease-out flex items-center gap-1 disabled:opacity-50\",\n text.trim() &&\n !loading &&\n \"pointer-events-auto hover:from-black/20 hover:to-transparent hover:border-black/10 cursor-pointer\",\n )}\n disabled={!text.trim() || loading}\n >\n <Sparkles className=\"size-4 text-white\" />\n <span className=\"text-white text-sm font-medium\">\n {loading ? \"Generating...\" : \"Generate\"}\n </span>\n </button>\n </div>\n {(text || text !== \"\") && (\n <div className=\"max-w-[300px] flex flex-wrap text-sm font-normal mt-2\">\n <strong>Prompt:</strong>\n <br />\n {text}\n </div>\n )}\n\n <div className=\"w-full relative mt-4\">\n <h3 className=\"text-base font-medium text-white mb-2\">Preview</h3>\n\n <div\n className={cn(\n glass,\n \"flex items-center justify-center w-full h-[320px] relative rounded-md overflow-hidden\",\n )}\n >\n {loading && (\n <>\n <Loader2\n className=\"size-4 animate-spin text-white\"\n role=\"status\"\n aria-label=\"loading\"\n />\n <span className=\"text-sm\">Generating AI Model...</span>\n </>\n )}\n\n {!loading && previewImage && (\n <div className=\"flex flex-col gap-3 w-full\">\n {previewImage && (\n <div className=\"rounded-md overflow-hidden border border-white/10\">\n <img src={previewImage} className=\"w-full object-cover\" />\n </div>\n )}\n <div className=\"flex gap-2\">\n <button\n onClick={handleGenerateModel}\n className=\"flex-1 px-3 py-2 rounded-md bg-white/10 hover:bg-white/20 text-sm\"\n >\n Regenerate\n </button>\n <button\n onClick={handlePlaceModel}\n className=\"flex-1 px-3 py-2 rounded-md bg-blue-500 hover:bg-blue-600 text-white text-sm\"\n >\n Place Model\n </button>\n </div>\n </div>\n )}\n\n {/* EMPTY STATE */}\n {!loading && !previewImage && (\n <span className=\"text-white/40 text-sm\">\n Your generated model will appear here\n </span>\n )}\n </div>\n </div>\n\n <div className=\"w-full relative mt-4\">\n <h3 className=\"text-base font-medium text-white mb-2\">Library</h3>\n\n <div className=\"grid grid-cols-2 gap-2\">\n {!isLibraryLoading && library.length === 0 && (\n <div className=\"col-span-2 text-center text-white/40 text-sm\">\n No generated models yet\n </div>\n )}\n\n {library.map((item) => (\n <button\n key={item.task_id}\n onClick={() => handlePlaceLibraryModel(item.model_url)}\n className=\"rounded-md overflow-hidden border border-white/10 hover:border-white/30 transition\"\n >\n <img src={item.preview_url} className=\"w-full object-cover\" />\n </button>\n ))}\n </div>\n\n <div ref={loaderRef} className=\"flex justify-center py-4\">\n {isLibraryLoading && (\n <Loader2 className=\"size-4 animate-spin text-white\" />\n )}\n </div>\n </div>\n </div>\n </>\n );\n}\n"],"mappings":"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","names":["React","React","jsx","React","jsx","React","X","jsx","jsxs","modelUrl","X","jsx","jsxs","jsx"]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/viewers/three/pgsg-three-viewer.ts","../src/viewers/spark/SparkSplatRenderer.ts","../src/viewers/three/controls/RapierWalkCapsuleController.ts","../src/viewers/three/controls/OrbitCameraController.ts","../src/viewers/three/controls/MeasurementController.ts","../src/viewers/three/controls/FloorplanController.ts"],"sourcesContent":["import type { PGSGViewerOptions } from \"../../core/types\";\nimport * as THREE from \"three\";\nimport { GLTFLoader } from \"three/addons/loaders/GLTFLoader.js\";\nimport { TransformControls } from \"three/addons/controls/TransformControls.js\";\nimport * as RAPIER from \"@dimforge/rapier3d-compat\";\nimport nipplejs from \"nipplejs\";\n\nimport { SparkSplatRenderer } from \"../spark/SparkSplatRenderer\";\nimport { RapierWalkController } from \"./controls/RapierWalkCapsuleController\";\nimport { OrbitCameraController } from \"./controls/OrbitCameraController\";\nimport { MeasurementController } from \"./controls/MeasurementController\";\nimport { FloorplanController } from \"./controls/FloorplanController\";\nimport { type CameraMode } from \"../types\";\n\nexport class PGSGThreeViewer {\n private scene = new THREE.Scene();\n private camera!: THREE.PerspectiveCamera;\n private renderer!: THREE.WebGLRenderer;\n private splats!: SparkSplatRenderer;\n\n private gltfLoader = new GLTFLoader();\n private pendingPlacementUrl?: string;\n private ghostModel?: THREE.Object3D;\n private raycaster = new THREE.Raycaster();\n private mouse = new THREE.Vector2();\n private placementRotation = 0;\n private transformControls?: TransformControls;\n private inputEnabled = true;\n\n private container: HTMLElement;\n private resizeObserver: ResizeObserver | null = null;\n\n private controls!:\n | RapierWalkController\n | OrbitCameraController\n | MeasurementController\n | FloorplanController;\n\n private running = false;\n private orbitTarget = new THREE.Vector3();\n private lastTime = performance.now();\n\n private persistentMeasurements: any[] = [];\n private measurementController: MeasurementController | null = null;\n\n private world!: RAPIER.World;\n\n // Roots\n private worldRoot = new THREE.Object3D(); // identity\n private cvRoot = new THREE.Object3D(); // ONLY place where we convert OpenCV->OpenGL\n private splatPivot = new THREE.Object3D();\n private colliderMesh?: THREE.Object3D;\n\n // For raycasting / measurement only\n private colliderMeshes: THREE.Object3D[] = [];\n\n private currentMode: CameraMode = \"orbit\";\n\n private acc = 0;\n private fixedDt = 1 / 60;\n\n private GLOBAL_SCALE = 0.7;\n\n constructor(private options: PGSGViewerOptions) {\n this.container = options.container;\n if (!this.container)\n throw new Error(\"[PGSGThreeViewer] Container is required\");\n }\n\n async load() {\n this.initRenderer();\n this.initCamera();\n this.initScene();\n\n this.bindResize();\n this.resize();\n\n this.transformControls = new TransformControls(\n this.camera,\n this.renderer.domElement,\n );\n\n this.scene.add(this.transformControls as unknown as THREE.Object3D);\n console.log(this.transformControls instanceof THREE.Object3D);\n\n this.transformControls.addEventListener(\"dragging-changed\", (event) => {\n if (!this.controls) return;\n (this.controls as any).enabled = !event.value;\n });\n\n this.transformControls.addEventListener(\"mouseDown\", () => {\n document.exitPointerLock?.();\n });\n\n await RAPIER.init();\n\n this.world = new RAPIER.World({\n x: 0,\n y: -9.81 * this.GLOBAL_SCALE,\n z: 0,\n });\n\n // scene graph\n this.scene.add(this.worldRoot);\n\n // ✅ OpenCV -> OpenGL conversion happens ONCE here\n // This matches your observed bounds flip:\n // raw min/max: [-1.26, 0.75] => OpenGL min/max: [-0.75, 1.26]\n this.cvRoot.scale.set(1, -1, -1);\n this.worldRoot.add(this.cvRoot);\n\n // ===============================\n // Load Splats under cvRoot\n // ===============================\n this.splats = new SparkSplatRenderer();\n const { mesh } = await this.splats.load(this.options.source);\n\n // ✅ DO NOT flip the mesh separately\n this.splatPivot.clear();\n this.splatPivot.add(mesh);\n this.cvRoot.add(this.splatPivot);\n\n // ===============================\n // Load Collider under cvRoot\n // ===============================\n if (this.options.colliderSource) {\n await this.loadCollider(this.options.colliderSource);\n }\n\n // update transforms after everything is added\n this.cvRoot.updateMatrixWorld(true);\n\n // Spawn camera using collider in the SAME space used by visuals + rapier\n this.placeInitialCamera();\n\n if (this.isMobile()) {\n this.initJoystick();\n this.switchToWalk();\n } else {\n this.switchToMeasure();\n }\n\n window.addEventListener(\"keydown\", this.onKeyToggle);\n window.addEventListener(\"keydown\", (e) => {\n if (!this.inputEnabled) return;\n if (!this.transformControls) return;\n\n if (e.key === \"r\") this.transformControls.setMode(\"rotate\");\n if (e.key === \"t\") this.transformControls.setMode(\"translate\");\n if (e.key === \"s\") this.transformControls.setMode(\"scale\");\n });\n this.renderer.domElement.addEventListener(\"click\", this.onSceneClick);\n }\n\n start() {\n if (this.running) return;\n this.running = true;\n\n this.renderer.setAnimationLoop(() => {\n const now = performance.now();\n const delta = (now - this.lastTime) / 1000;\n this.lastTime = now;\n\n this.acc += delta;\n while (this.acc >= this.fixedDt) {\n this.world.timestep = this.fixedDt;\n this.world.step();\n this.acc -= this.fixedDt;\n }\n\n (this.controls as any)?.update?.(delta);\n this.renderer.render(this.scene, this.camera);\n });\n }\n\n pause() {\n this.running = false;\n }\n\n resize() {\n if (!this.renderer || !this.camera) return;\n\n const w = Math.max(1, this.container.clientWidth);\n const h = Math.max(1, this.container.clientHeight);\n\n this.renderer.setSize(w, h);\n this.camera.aspect = w / h;\n this.camera.updateProjectionMatrix();\n }\n\n destroy() {\n this.running = false;\n this.renderer.setAnimationLoop(null);\n this.renderer.domElement.removeEventListener(\"click\", this.onSceneClick);\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.controls?.dispose();\n this.renderer.dispose();\n window.removeEventListener(\"keydown\", this.onKeyToggle);\n }\n\n setCameraMode(mode: CameraMode) {\n this.currentMode = mode;\n\n if (this.controls instanceof MeasurementController) {\n this.persistentMeasurements = (this.controls as any).measurements;\n this.controls.setVisible(false);\n }\n\n switch (mode) {\n case \"measure\":\n document.exitPointerLock?.();\n this.switchToMeasure();\n if (this.controls instanceof MeasurementController)\n this.controls.setVisible(true);\n break;\n case \"orbit\":\n document.exitPointerLock?.();\n this.switchToOrbit();\n break;\n case \"walk\":\n this.switchToWalk();\n break;\n case \"floorplan\":\n this.switchToFloorplan();\n break;\n }\n }\n\n toggleCameraMode() {\n if (this.controls instanceof RapierWalkController) this.switchToOrbit();\n else this.switchToWalk();\n }\n\n getMeasurements() {\n return this.measurementController?.getMeasurements?.() ?? [];\n }\n\n clearMeasurements() {\n if (!this.measurementController) return;\n this.measurementController.clearAll();\n this.persistentMeasurements = [];\n }\n\n finalizePolyline() {\n if (this.controls instanceof MeasurementController)\n this.controls.finalizePolyline();\n }\n\n deleteMeasurement(index: number) {\n this.measurementController?.deleteMeasurement?.(index);\n }\n\n async enablePlacementMode(url: string) {\n this.pendingPlacementUrl = url;\n this.placementRotation = 0;\n\n console.log(\"[PGSG Viewer] Placement mode enabled\");\n\n const gltf = await this.gltfLoader.loadAsync(url);\n\n this.ghostModel = gltf.scene;\n\n // normalize scale\n const box = new THREE.Box3().setFromObject(this.ghostModel);\n const size = new THREE.Vector3();\n box.getSize(size);\n\n const maxDim = Math.max(size.x, size.y, size.z);\n const scale = 1.5 / maxDim;\n\n this.ghostModel.scale.multiplyScalar(scale);\n\n // transparent ghost material\n this.ghostModel.traverse((child: any) => {\n if (!child.isMesh) return;\n\n child.material = child.material.clone();\n child.material.transparent = true;\n child.material.opacity = 0.4;\n });\n\n this.scene.add(this.ghostModel);\n\n this.renderer.domElement.addEventListener(\n \"mousemove\",\n this.onPlacementMove,\n );\n this.renderer.domElement.addEventListener(\"wheel\", this.onPlacementWheel);\n this.renderer.domElement.addEventListener(\"click\", this.onSceneClick);\n window.addEventListener(\"keydown\", this.onPlacementCancel);\n }\n\n async addModelFromUrl(\n url: string,\n position?: THREE.Vector3,\n ): Promise<THREE.Object3D | null> {\n return new Promise((resolve, reject) => {\n this.gltfLoader.load(\n url,\n (gltf) => {\n const model = gltf.scene;\n\n const box = new THREE.Box3().setFromObject(model);\n const size = new THREE.Vector3();\n box.getSize(size);\n\n const maxDim = Math.max(size.x, size.y, size.z);\n const scale = 1.5 / maxDim;\n\n model.scale.multiplyScalar(scale);\n\n if (position) {\n model.position.copy(position);\n }\n\n const floorBox = new THREE.Box3().setFromObject(model);\n model.position.y -= floorBox.min.y;\n\n this.cvRoot.add(model);\n\n resolve(model);\n },\n undefined,\n reject,\n );\n });\n }\n\n enableInput(enabled: boolean) {\n this.inputEnabled = enabled;\n }\n\n // ---------------------------\n // Init\n // ---------------------------\n\n private initRenderer() {\n if (this.renderer) return;\n\n this.renderer = new THREE.WebGLRenderer({\n antialias: this.options.renderer?.antialias ?? false,\n alpha: false,\n powerPreference: \"high-performance\",\n });\n\n this.renderer.setClearColor(0x111111, 1);\n this.renderer.outputColorSpace = THREE.SRGBColorSpace;\n\n this.renderer.setSize(\n this.container.clientWidth,\n this.container.clientHeight,\n );\n this.renderer.setPixelRatio(\n this.options.renderer?.pixelRatio ?? window.devicePixelRatio,\n );\n\n this.renderer.localClippingEnabled = true;\n this.container.appendChild(this.renderer.domElement);\n }\n\n private initScene() {\n this.scene = new THREE.Scene();\n this.scene.background = new THREE.Color(0x111111);\n\n const light = new THREE.HemisphereLight(0xffffff, 0x222222, 1.0);\n this.scene.add(light);\n }\n\n private initCamera() {\n this.camera = new THREE.PerspectiveCamera(\n this.options.camera?.fov ?? 60,\n this.container.clientWidth / this.container.clientHeight,\n this.options.camera?.near ?? 0.01,\n this.options.camera?.far ?? 10000,\n );\n this.camera.position.set(2, 2, 5);\n this.camera.lookAt(0, 0, 0);\n }\n\n private bindResize() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.container);\n }\n\n private isMobile(): boolean {\n return (\n \"ontouchstart\" in window ||\n navigator.maxTouchPoints > 0 ||\n window.innerWidth < 768\n );\n }\n\n // ---------------------------\n // Collider (visual + rapier)\n // ---------------------------\n\n private async loadCollider(url: string) {\n console.log(\"[PGSG Viewer] Loading collider:\", url);\n\n const loader = new GLTFLoader();\n const gltf = await loader.loadAsync(url);\n\n // Put collider under cvRoot so it matches splat space\n const colliderRoot = new THREE.Object3D();\n colliderRoot.name = \"colliderRoot\";\n colliderRoot.add(gltf.scene);\n\n this.colliderMesh = colliderRoot;\n this.cvRoot.add(colliderRoot);\n\n // update world matrices so geometry baking includes cvRoot flip\n this.cvRoot.updateMatrixWorld(true);\n colliderRoot.updateWorldMatrix(true, true);\n\n // For measurement/raycast (THREE)\n this.colliderMeshes.length = 0;\n\n // Build Rapier trimesh from FINAL transformed geometry\n colliderRoot.traverse((child: any) => {\n if (!child?.isMesh) return;\n\n // bake geometry into world space (including cvRoot scale flip)\n const geom = child.geometry.clone();\n child.updateWorldMatrix(true, false);\n geom.applyMatrix4(child.matrixWorld);\n\n const vertices = new Float32Array(geom.attributes.position.array as any);\n\n let indices: Uint32Array;\n if (geom.index) indices = new Uint32Array(geom.index.array as any);\n else {\n const count = geom.attributes.position.count;\n indices = new Uint32Array(count);\n for (let i = 0; i < count; i++) indices[i] = i;\n }\n\n const rb = this.world.createRigidBody(RAPIER.RigidBodyDesc.fixed());\n const cd = RAPIER.ColliderDesc.trimesh(vertices, indices);\n cd.setFriction(0.9);\n cd.setRestitution(0.0);\n this.world.createCollider(cd, rb);\n\n // optional debug material\n // child.material = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide });\n child.visible = false;\n this.colliderMeshes.push(child);\n });\n\n // sanity logs\n const rawBox = new THREE.Box3().setFromObject(colliderRoot);\n console.log(\"OpenGL bounds Y:\", rawBox.min.y, rawBox.max.y);\n\n console.log(\"[PGSG Viewer] Colliders loaded:\", this.colliderMeshes.length);\n }\n\n // ---------------------------\n // Mode switching\n // ---------------------------\n\n private onKeyToggle = (e: KeyboardEvent) => {\n if (!this.inputEnabled) return;\n if (e.key !== \"v\") return;\n if (this.controls instanceof RapierWalkController) this.switchToOrbit();\n else this.switchToWalk();\n };\n\n private switchToMeasure() {\n this.controls?.dispose?.();\n this.measurementController = new MeasurementController({\n dom: this.renderer.domElement,\n camera: this.camera,\n scene: this.scene,\n colliders: this.colliderMeshes,\n });\n\n this.measurementController.restoreMeasurements?.(\n this.persistentMeasurements,\n );\n this.controls = this.measurementController;\n }\n\n private switchToWalk() {\n this.controls?.dispose?.();\n\n const walk = new RapierWalkController({\n camera: this.camera,\n dom: this.renderer.domElement,\n world: this.world,\n eyeHeight: 1.6,\n radius: 0.2,\n halfHeight: 0.6,\n moveSpeed: 3.0 * this.GLOBAL_SCALE,\n jumpSpeed: 6.0 * this.GLOBAL_SCALE,\n usePointerLock: !this.isMobile(),\n }) as any;\n\n this.controls = walk;\n\n // sync yaw/pitch from current camera\n const euler = new THREE.Euler().setFromQuaternion(\n this.camera.quaternion,\n \"YXZ\",\n );\n walk.setRotation(euler.y, euler.x);\n\n // place capsule under camera, then snap DOWN to nearest floor\n walk.setPositionFromCamera();\n walk.resetVelocity();\n walk.snapToGround?.();\n }\n\n private switchToOrbit() {\n this.controls?.dispose?.();\n\n this.camera.up.set(0, 1, 0);\n this.camera.updateMatrixWorld(true);\n\n // orbit around converted (OpenGL) content root\n const box = new THREE.Box3().setFromObject(this.cvRoot);\n const center = box.getCenter(new THREE.Vector3());\n this.orbitTarget.copy(center);\n\n const distance = Math.max(this.camera.position.distanceTo(center), 1);\n\n this.controls = new OrbitCameraController(\n this.camera,\n this.renderer.domElement,\n {\n target: this.orbitTarget.clone(),\n distance,\n usePointerLock: !this.isMobile(),\n },\n );\n }\n\n private switchToFloorplan() {\n this.controls?.dispose?.();\n\n const box = new THREE.Box3().setFromObject(this.cvRoot);\n const center = box.getCenter(new THREE.Vector3());\n const size = box.getSize(new THREE.Vector3());\n const height = Math.max(size.x, size.z) * 1.2;\n\n this.orbitTarget.copy(center);\n\n this.controls = new FloorplanController({\n dom: this.renderer.domElement,\n camera: this.camera,\n target: center,\n height,\n panSpeed: 0.0015,\n zoomSpeed: 1.15,\n });\n }\n\n // ---------------------------\n // Spawn\n // ---------------------------\n\n private placeInitialCamera() {\n const targetObj = this.colliderMesh ?? this.cvRoot;\n const box = new THREE.Box3().setFromObject(targetObj);\n const center = box.getCenter(new THREE.Vector3());\n const size = box.getSize(new THREE.Vector3());\n\n // start ray well above the whole scene\n const startY = box.max.y + 10;\n const maxDist = box.max.y - box.min.y + 50;\n\n // sample a small grid around center (helps when center is outside shell)\n const samples: Array<{ x: number; z: number }> = [];\n const sx = Math.max(0.2, size.x * 0.15);\n const sz = Math.max(0.2, size.z * 0.15);\n\n for (const dx of [-sx, 0, sx]) {\n for (const dz of [-sz, 0, sz]) {\n samples.push({ x: center.x + dx, z: center.z + dz });\n }\n }\n\n // pick best \"floor\" among all samples\n // Strategy:\n // - collect multiple hits along the down-ray\n // - ignore the first hit if it’s the outside ceiling\n // - select the deepest hit that is \"walkable-ish\"\n // (we don’t trust normal sign fully, so use abs(normalY))\n let bestFloorY: number | null = null;\n let bestXZ: { x: number; z: number } | null = null;\n\n for (const s of samples) {\n const hits = this.raycastDownMulti(s.x, s.z, startY, maxDist, 10);\n if (hits.length === 0) continue;\n\n // choose a candidate floor from the *later* hits (skip the first)\n // and require it to be roughly horizontal\n let candidate: { y: number; normalY: number } | null = null;\n\n for (let i = 1; i < hits.length; i++) {\n const h = hits[i];\n if (Math.abs(h.normalY) < 0.55) continue; // ~55deg slope limit\n candidate = h; // keep going, we want the deepest valid one\n }\n\n if (!candidate) continue;\n\n // choose the HIGHEST candidate floor among samples\n // (so we land on topmost interior floor, not a basement)\n if (bestFloorY == null || candidate.y > bestFloorY) {\n bestFloorY = candidate.y;\n bestXZ = s;\n }\n }\n\n const eye = 1.6;\n\n if (bestFloorY != null && bestXZ) {\n this.camera.position.set(bestXZ.x, bestFloorY + eye, bestXZ.z + 0.5);\n this.orbitTarget.set(bestXZ.x, bestFloorY, bestXZ.z);\n } else {\n // fallback\n this.camera.position.set(center.x, box.max.y + eye, center.z + 2);\n this.orbitTarget.copy(center);\n }\n\n this.camera.up.set(0, 1, 0);\n this.camera.lookAt(this.orbitTarget);\n this.camera.updateMatrixWorld(true);\n }\n\n private getWorldNormalSafe(hit: THREE.Intersection) {\n if (!hit.face) return null;\n const m3 = new THREE.Matrix3().getNormalMatrix(hit.object.matrixWorld);\n return hit.face.normal.clone().applyMatrix3(m3).normalize();\n }\n\n // ---------------------------\n // Mobile joystick\n // ---------------------------\n\n private initJoystick() {\n const zone = document.createElement(\"div\");\n zone.style.position = \"absolute\";\n zone.style.left = \"20px\";\n zone.style.bottom = \"20px\";\n zone.style.width = \"150px\";\n zone.style.height = \"150px\";\n zone.style.zIndex = \"1000\";\n this.container.appendChild(zone);\n\n const joystick = nipplejs.create({\n zone,\n mode: \"static\",\n position: { left: \"50px\", bottom: \"50px\" },\n color: \"white\",\n });\n\n joystick.on(\"move\", (_, data) => {\n const angle = data.angle.radian;\n const force = data.force;\n\n if (\n this.controls instanceof RapierWalkController ||\n this.controls instanceof OrbitCameraController\n ) {\n (this.controls as any).setMovementVector(\n Math.sin(angle) * force,\n Math.cos(angle) * force,\n );\n }\n });\n\n joystick.on(\"end\", () => {\n if (\n this.controls instanceof RapierWalkController ||\n this.controls instanceof OrbitCameraController\n ) {\n (this.controls as any).setMovementVector(0, 0);\n }\n });\n }\n\n private raycastDownMulti(\n x: number,\n z: number,\n startY: number,\n maxDist: number,\n maxHits = 8,\n ) {\n const hits: Array<{ y: number; normalY: number }> = [];\n\n let originY = startY;\n let remaining = maxDist;\n\n for (let i = 0; i < maxHits; i++) {\n const ray = new RAPIER.Ray({ x, y: originY, z }, { x: 0, y: -1, z: 0 });\n\n const hit = this.world.castRayAndGetNormal(ray, remaining, true);\n if (!hit) break;\n\n const y = originY - hit.timeOfImpact;\n const normalY = hit.normal?.y ?? 0;\n\n hits.push({ y, normalY });\n\n // Step just past the surface so the next cast finds the next intersection\n const eps = 0.02;\n originY = y - eps;\n remaining = remaining - hit.timeOfImpact - eps;\n if (remaining <= 0) break;\n }\n\n return hits;\n }\n\n private onSceneClick = async (event: MouseEvent) => {\n if (!this.pendingPlacementUrl || !this.ghostModel) return;\n\n const position = this.ghostModel.position.clone();\n\n const placed = await this.addModelFromUrl(\n this.pendingPlacementUrl,\n position,\n );\n\n if (placed && this.transformControls) {\n placed.rotation.y = this.placementRotation;\n this.transformControls.attach(placed);\n }\n\n this.scene.remove(this.ghostModel);\n\n this.ghostModel = undefined;\n this.pendingPlacementUrl = undefined;\n\n this.renderer.domElement.removeEventListener(\n \"mousemove\",\n this.onPlacementMove,\n );\n\n this.renderer.domElement.removeEventListener(\n \"wheel\",\n this.onPlacementWheel,\n );\n\n this.renderer.domElement.removeEventListener(\"click\", this.onSceneClick);\n\n window.removeEventListener(\"keydown\", this.onPlacementCancel);\n };\n\n private onPlacementMove = (event: MouseEvent) => {\n if (!this.pendingPlacementUrl || !this.ghostModel) return;\n\n const rect = this.renderer.domElement.getBoundingClientRect();\n\n this.mouse.set(\n ((event.clientX - rect.left) / rect.width) * 2 - 1,\n -((event.clientY - rect.top) / rect.height) * 2 + 1,\n );\n\n this.raycaster.setFromCamera(this.mouse, this.camera);\n\n const intersects = this.raycaster.intersectObjects(\n this.colliderMeshes,\n true,\n );\n\n if (!intersects.length) return;\n\n const hit = intersects[0];\n\n this.ghostModel.position.copy(hit.point);\n\n // align to surface normal\n if (hit.face) {\n const normal = this.getWorldNormalSafe(hit);\n if (normal) {\n const up = new THREE.Vector3(0, 1, 0);\n const quat = new THREE.Quaternion().setFromUnitVectors(up, normal);\n this.ghostModel.quaternion.copy(quat);\n }\n }\n };\n\n private onPlacementWheel = (event: WheelEvent) => {\n if (!this.ghostModel) return;\n\n event.preventDefault();\n\n const step = Math.PI / 12; // 15 degrees\n\n if (event.deltaY > 0) {\n this.placementRotation += step;\n } else {\n this.placementRotation -= step;\n }\n\n this.ghostModel.rotation.y = this.placementRotation;\n };\n\n private onPlacementCancel = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n\n if (!this.ghostModel) return;\n\n console.log(\"[PGSG Viewer] Placement cancelled\");\n\n this.scene.remove(this.ghostModel);\n this.ghostModel = undefined;\n this.pendingPlacementUrl = undefined;\n\n this.renderer.domElement.style.cursor = \"default\";\n\n this.renderer.domElement.removeEventListener(\n \"mousemove\",\n this.onPlacementMove,\n );\n this.renderer.domElement.removeEventListener(\"click\", this.onSceneClick);\n this.renderer.domElement.removeEventListener(\n \"wheel\",\n this.onPlacementWheel,\n );\n\n window.removeEventListener(\"keydown\", this.onPlacementCancel);\n };\n}\n","import { SplatMesh } from \"@sparkjsdev/spark\";\nimport * as THREE from \"three\";\nimport type { ViewerSource } from \"../../core/types\";\nimport { computePLYBounds, parsePLYHeader } from \"../three/utils\";\n\nexport class SparkSplatRenderer {\n private mesh!: SplatMesh;\n\n async load(source: ViewerSource) {\n if (source.type !== \"ply\" && source.type !== \"pgsg\") {\n throw new Error(\"SparkJS supports splat-based sources only\");\n }\n\n // const res = await fetch(source.url);\n // const buffer = await res.arrayBuffer();\n\n // const { vertexCount, headerSize } = parsePLYHeader(buffer);\n // const bounds = computePLYBounds(buffer, headerSize, vertexCount);\n\n this.mesh = new SplatMesh({\n url: source.url,\n });\n\n await this.mesh.initialized;\n this.mesh.updateMatrixWorld(true);\n\n const box = this.mesh.getBoundingBox(true);\n\n const min = box.min.clone();\n const max = box.max.clone();\n\n // Match SparkJS doc defaults\n this.mesh.position.set(0, 0, 0);\n this.mesh.quaternion.identity();\n\n return {\n mesh: this.mesh,\n bounds: {\n min,\n max,\n },\n };\n }\n\n addToScene(scene: THREE.Scene) {\n scene.add(this.mesh);\n }\n\n update(dt: number) {\n // optional: rotation / animation\n }\n\n destroy(scene: THREE.Scene) {\n scene.remove(this.mesh);\n this.mesh.dispose?.();\n }\n}\n","import * as THREE from \"three\";\nimport * as RAPIER from \"@dimforge/rapier3d-compat\";\n\nexport type RapierWalkOptions = {\n dom: HTMLElement;\n camera: THREE.PerspectiveCamera;\n world: RAPIER.World;\n\n radius?: number;\n halfHeight?: number;\n eyeHeight?: number;\n\n moveSpeed?: number;\n jumpSpeed?: number;\n lookSensitivity?: number;\n\n usePointerLock?: boolean;\n\n // small tuning values\n groundProbeExtra?: number; // extra ray length\n groundSnapMax?: number; // max snap distance\n};\n\nexport class RapierWalkController {\n private dom: HTMLElement;\n private camera: THREE.PerspectiveCamera;\n private world: RAPIER.World;\n\n private body: RAPIER.RigidBody;\n private collider: RAPIER.Collider;\n\n private radius: number;\n private halfHeight: number;\n private eyeHeight: number;\n\n private moveSpeed: number;\n private jumpSpeed: number;\n private lookSensitivity: number;\n\n private usePointerLock: boolean;\n\n private yaw = 0;\n private pitch = 0;\n\n private keys = new Set<string>();\n private moveVec = new THREE.Vector2(0, 0); // joystick: x=forward, y=right\n\n private groundProbeExtra: number;\n private groundSnapMax: number;\n\n // ---- bound handlers (so dispose works) ----\n private onClickBound = () => this.onClick();\n private onMouseMoveBound = (e: MouseEvent) => this.onMouseMove(e);\n private onKeyDownBound = (e: KeyboardEvent) => this.onKeyDown(e);\n private onKeyUpBound = (e: KeyboardEvent) => this.onKeyUp(e);\n private onBlurBound = () => this.onBlur();\n\n constructor(opts: RapierWalkOptions) {\n this.dom = opts.dom;\n this.camera = opts.camera;\n this.world = opts.world;\n\n this.radius = opts.radius ?? 0.2;\n this.halfHeight = opts.halfHeight ?? 0.6;\n this.eyeHeight = opts.eyeHeight ?? 1.6;\n\n this.moveSpeed = opts.moveSpeed ?? 3.0;\n this.jumpSpeed = opts.jumpSpeed ?? 6.0;\n this.lookSensitivity = opts.lookSensitivity ?? 0.0022;\n\n this.usePointerLock = opts.usePointerLock ?? true;\n\n this.groundProbeExtra = opts.groundProbeExtra ?? 0.25;\n this.groundSnapMax = opts.groundSnapMax ?? 0.65;\n\n // init yaw/pitch from camera\n const euler = new THREE.Euler().setFromQuaternion(\n this.camera.quaternion,\n \"YXZ\",\n );\n this.pitch = euler.x;\n this.yaw = euler.y;\n\n // Create capsule rigidbody at camera position (best guess)\n const start = this.camera.position.clone();\n const centerY = start.y - this.eyeHeight + (this.halfHeight + this.radius);\n\n const bodyDesc = RAPIER.RigidBodyDesc.dynamic()\n .setTranslation(start.x, centerY, start.z)\n .lockRotations()\n .setLinearDamping(6.0) // higher damping to kill drift\n .setCcdEnabled(true);\n\n this.body = this.world.createRigidBody(bodyDesc);\n\n const colDesc = RAPIER.ColliderDesc.capsule(this.halfHeight, this.radius)\n .setFriction(0.8)\n .setRestitution(0.0);\n\n this.collider = this.world.createCollider(colDesc, this.body);\n\n // optional: helps prevent “sucked into edges”\n this.collider.setActiveEvents?.(RAPIER.ActiveEvents.COLLISION_EVENTS);\n\n this.bindInput();\n }\n\n dispose() {\n this.unbindInput();\n // optional: if you want to remove from world completely\n // this.world.removeRigidBody(this.body);\n if (this.body) {\n this.world.removeRigidBody(this.body);\n }\n }\n\n // ---------------------------\n // External movement (joystick)\n // x = forward/back (-1..1), y = right/left (-1..1)\n // ---------------------------\n setMovementVector(x: number, y: number) {\n this.moveVec.set(x, y);\n }\n\n setRotation(yaw: number, pitch: number) {\n this.yaw = yaw;\n this.pitch = THREE.MathUtils.clamp(\n pitch,\n -Math.PI / 2 + 0.01,\n Math.PI / 2 - 0.01,\n );\n this.camera.quaternion.setFromEuler(\n new THREE.Euler(this.pitch, this.yaw, 0, \"YXZ\"),\n );\n }\n\n resetVelocity() {\n this.body.setLinvel({ x: 0, y: 0, z: 0 }, true);\n this.body.setAngvel({ x: 0, y: 0, z: 0 }, true);\n }\n\n setPositionFromCamera() {\n const p = this.camera.position;\n const centerY = p.y - this.eyeHeight + (this.halfHeight + this.radius);\n this.body.setTranslation({ x: p.x, y: centerY, z: p.z }, true);\n this.resetVelocity();\n }\n\n // Snap the capsule so its feet rest on the nearest floor below\n snapToGround() {\n const p = this.body.translation();\n\n const origin = { x: p.x, y: p.y + 2.0, z: p.z };\n const dir = { x: 0, y: -1, z: 0 };\n const ray = new RAPIER.Ray(origin, dir);\n\n const maxDist = 50;\n\n const hit = this.castRayWithNormal(ray, maxDist);\n if (!hit) return;\n\n // place feet just above hit point\n const toi = hit.timeOfImpact;\n const hitY = origin.y - toi;\n\n const newCenterY = hitY + (this.halfHeight + this.radius) + 0.02;\n this.body.setTranslation({ x: p.x, y: newCenterY, z: p.z }, true);\n this.resetVelocity();\n }\n\n // ---------------------------\n // Input binding\n // ---------------------------\n private bindInput() {\n if (this.usePointerLock) {\n this.dom.addEventListener(\"click\", this.onClickBound);\n window.addEventListener(\"mousemove\", this.onMouseMoveBound);\n }\n window.addEventListener(\"keydown\", this.onKeyDownBound);\n window.addEventListener(\"keyup\", this.onKeyUpBound);\n window.addEventListener(\"blur\", this.onBlurBound);\n }\n\n private unbindInput() {\n this.dom.removeEventListener(\"click\", this.onClickBound);\n window.removeEventListener(\"mousemove\", this.onMouseMoveBound);\n window.removeEventListener(\"keydown\", this.onKeyDownBound);\n window.removeEventListener(\"keyup\", this.onKeyUpBound);\n window.removeEventListener(\"blur\", this.onBlurBound);\n }\n\n private onClick() {\n if (!this.usePointerLock) return;\n if (document.pointerLockElement !== this.dom) this.dom.requestPointerLock();\n }\n\n private onBlur() {\n this.keys.clear();\n this.moveVec.set(0, 0);\n }\n\n private onMouseMove(e: MouseEvent) {\n if (!this.usePointerLock) return;\n if (document.pointerLockElement !== this.dom) return;\n\n this.yaw -= e.movementX * this.lookSensitivity;\n this.pitch -= e.movementY * this.lookSensitivity;\n this.pitch = THREE.MathUtils.clamp(\n this.pitch,\n -Math.PI / 2 + 0.01,\n Math.PI / 2 - 0.01,\n );\n\n this.camera.quaternion.setFromEuler(\n new THREE.Euler(this.pitch, this.yaw, 0, \"YXZ\"),\n );\n }\n\n private onKeyDown(e: KeyboardEvent) {\n this.keys.add(e.key.toLowerCase());\n }\n\n private onKeyUp(e: KeyboardEvent) {\n this.keys.delete(e.key.toLowerCase());\n }\n\n // ---------------------------\n // Update\n // ---------------------------\n update(_dt: number) {\n // yaw-only basis from yaw (not full camera direction) -> avoids pitch causing weird forces\n const forward = new THREE.Vector3(0, 0, -1).applyAxisAngle(\n new THREE.Vector3(0, 1, 0),\n this.yaw,\n );\n const right = new THREE.Vector3(1, 0, 0).applyAxisAngle(\n new THREE.Vector3(0, 1, 0),\n this.yaw,\n );\n\n const wish = new THREE.Vector3();\n\n // keyboard\n if (this.keys.has(\"w\")) wish.add(forward);\n if (this.keys.has(\"s\")) wish.sub(forward);\n if (this.keys.has(\"d\")) wish.add(right);\n if (this.keys.has(\"a\")) wish.sub(right);\n\n // joystick\n if (this.moveVec.lengthSq() > 1e-6) {\n wish.addScaledVector(forward, this.moveVec.x);\n wish.addScaledVector(right, this.moveVec.y);\n }\n\n if (wish.lengthSq() > 1e-8) wish.normalize();\n\n const vel = this.body.linvel();\n\n // 🔥 kill drift when no input\n const targetVX = wish.x * this.moveSpeed;\n const targetVZ = wish.z * this.moveSpeed;\n\n this.body.setLinvel(\n {\n x: targetVX,\n y: vel.y,\n z: targetVZ,\n },\n true, // wake up\n );\n\n // jump\n if (this.keys.has(\" \")) {\n if (this.isGrounded()) {\n this.body.setLinvel(\n { x: targetVX, y: this.jumpSpeed, z: targetVZ },\n true,\n );\n }\n }\n\n // sync camera to body\n const p = this.body.translation();\n const feetY = p.y - (this.halfHeight + this.radius);\n this.camera.position.set(p.x, feetY + this.eyeHeight, p.z);\n }\n\n // ---------------------------\n // Grounding\n // ---------------------------\n private isGrounded(): boolean {\n const p = this.body.translation();\n\n const origin = { x: p.x, y: p.y, z: p.z };\n const dir = { x: 0, y: -1, z: 0 };\n const ray = new RAPIER.Ray(origin, dir);\n\n const maxDist = this.halfHeight + this.radius + this.groundProbeExtra;\n const hit = this.castRayWithNormal(ray, maxDist);\n if (!hit) return false;\n\n // accept “up-ish” surfaces\n const ny = hit.normal?.y ?? 0;\n return ny > 0.35;\n }\n\n // Ray cast helper with “exclude self” when possible\n private castRayWithNormal(ray: RAPIER.Ray, maxDist: number) {\n // If QueryFilter exists in your build, use it to exclude the player collider.\n const anyRapier: any = RAPIER as any;\n\n try {\n if (anyRapier.QueryFilter) {\n const filter = new anyRapier.QueryFilter();\n // exclude collider preferred\n if (filter.excludeCollider) filter.excludeCollider(this.collider);\n else if (filter.excludeRigidBody) filter.excludeRigidBody(this.body);\n\n return this.world.castRayAndGetNormal(ray, maxDist, true, filter);\n }\n } catch {\n // ignore, fall back below\n }\n\n // Fallback (no filter): may occasionally hit self if Rapier allows, but often still ok.\n return this.world.castRayAndGetNormal(ray, maxDist, true);\n }\n}\n","import * as THREE from \"three\";\n\nexport interface OrbitOptions {\n target: THREE.Vector3;\n distance: number;\n minDistance?: number;\n maxDistance?: number;\n rotateSpeed?: number;\n zoomSpeed?: number;\n usePointerLock?: boolean;\n}\n\nexport class OrbitCameraController {\n private camera: THREE.PerspectiveCamera;\n private dom: HTMLElement;\n\n private target: THREE.Vector3;\n private distance: number;\n private minDistance: number;\n private maxDistance: number;\n\n private yaw = 0;\n private pitch = 0;\n\n private rotateSpeed: number;\n private zoomSpeed: number;\n\n private dragging = false;\n private lastX = 0;\n private lastY = 0;\n\n private panning = false;\n private panSpeed = 0.002;\n\n private usePointerLock?: boolean = false;\n private lastTouchX = 0;\n private lastTouchY = 0;\n private externalMove = new THREE.Vector2(0, 0);\n private moveSpeed: number = 5;\n\n constructor(\n camera: THREE.PerspectiveCamera,\n dom: HTMLElement,\n opts: OrbitOptions,\n ) {\n this.camera = camera;\n this.dom = dom;\n\n this.target = opts.target.clone();\n this.distance = opts.distance;\n this.minDistance = opts.minDistance ?? 0.2;\n this.maxDistance = opts.maxDistance ?? 500;\n\n this.rotateSpeed = opts.rotateSpeed ?? 0.005;\n this.zoomSpeed = opts.zoomSpeed ?? 1.1;\n this.usePointerLock = opts.usePointerLock ?? false;\n\n this.syncFromCamera();\n if (this.usePointerLock === false) {\n this.bindTouch();\n } else {\n this.bind();\n this.updateCamera();\n }\n }\n\n update(dt: number) {\n if (this.externalMove.lengthSq() === 0) return;\n\n const forward = new THREE.Vector3();\n this.camera.getWorldDirection(forward);\n forward.y = 0;\n forward.normalize();\n\n const right = new THREE.Vector3()\n .crossVectors(forward, new THREE.Vector3(0, 1, 0))\n .normalize();\n\n const move = new THREE.Vector3()\n .addScaledVector(forward, this.externalMove.x)\n .addScaledVector(right, this.externalMove.y);\n\n if (move.lengthSq() > 0) move.normalize();\n\n move.multiplyScalar(this.moveSpeed * dt);\n\n this.target.add(move);\n\n this.updateCamera();\n }\n\n dispose() {\n if (this.usePointerLock === false) {\n this.unbindTouch();\n } else {\n this.unbind();\n if (this.usePointerLock) document.exitPointerLock();\n }\n }\n\n setMovementVector(x: number, y: number) {\n this.externalMove.set(x, y);\n }\n\n // -----------------------------\n // Setup\n // -----------------------------\n\n private bind() {\n this.dom.addEventListener(\"contextmenu\", (e) => e.preventDefault());\n this.dom.addEventListener(\"mousedown\", this.onMouseDown);\n window.addEventListener(\"mouseup\", this.onMouseUp);\n window.addEventListener(\"mousemove\", this.onMouseMove);\n this.dom.addEventListener(\"wheel\", this.onWheel, { passive: false });\n }\n\n private bindTouch() {\n this.dom.addEventListener(\"touchstart\", this.onTouchStart);\n this.dom.addEventListener(\"touchmove\", this.onTouchMove);\n }\n\n private unbind() {\n this.dom.removeEventListener(\"mousedown\", this.onMouseDown);\n window.removeEventListener(\"mouseup\", this.onMouseUp);\n window.removeEventListener(\"mousemove\", this.onMouseMove);\n this.dom.removeEventListener(\"wheel\", this.onWheel);\n }\n\n private unbindTouch() {\n this.dom.removeEventListener(\"touchstart\", this.onTouchStart);\n this.dom.removeEventListener(\"touchmove\", this.onTouchMove);\n }\n\n private syncFromCamera() {\n const offset = this.camera.position.clone().sub(this.target);\n this.distance = offset.length();\n\n const spherical = new THREE.Spherical().setFromVector3(offset);\n this.yaw = spherical.theta;\n this.pitch = spherical.phi;\n }\n\n // -----------------------------\n // Input\n // -----------------------------\n\n private onMouseDown = (e: MouseEvent) => {\n if (e.button === 0) {\n // LEFT = orbit\n this.dragging = true;\n } else if (e.button === 2 || e.button === 1) {\n // RIGHT or MIDDLE = pan\n this.panning = true;\n }\n\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onMouseUp = () => {\n this.dragging = false;\n this.panning = false;\n };\n\n private onMouseMove = (e: MouseEvent) => {\n if (!this.dragging && !this.panning) return;\n\n const dx = e.clientX - this.lastX;\n const dy = e.clientY - this.lastY;\n\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n\n // -----------------\n // ORBIT ROTATION\n // -----------------\n if (this.dragging) {\n this.yaw -= dx * this.rotateSpeed;\n this.pitch -= dy * this.rotateSpeed;\n\n this.pitch = THREE.MathUtils.clamp(this.pitch, 0.01, Math.PI - 0.01);\n\n this.updateCamera();\n return;\n }\n\n // -----------------\n // PANNING\n // -----------------\n if (this.panning) {\n const panScale = this.distance * this.panSpeed;\n\n const right = new THREE.Vector3();\n const up = new THREE.Vector3();\n\n this.camera.getWorldDirection(up);\n right.crossVectors(this.camera.up, up).normalize();\n up.crossVectors(\n right,\n this.camera.getWorldDirection(new THREE.Vector3()),\n ).normalize();\n\n const panOffset = new THREE.Vector3()\n .addScaledVector(right, dx * panScale)\n .addScaledVector(up, -dy * panScale);\n\n this.target.add(panOffset);\n this.camera.position.add(panOffset);\n\n // no updateCamera() — we already moved both\n }\n };\n\n private onWheel = (e: WheelEvent) => {\n e.preventDefault();\n\n const zoomFactor = Math.pow(this.zoomSpeed, e.deltaY / 100);\n this.distance *= zoomFactor;\n\n this.distance = THREE.MathUtils.clamp(\n this.distance,\n this.minDistance,\n this.maxDistance,\n );\n\n this.updateCamera();\n };\n\n private onTouchStart = (e: TouchEvent) => {\n const t = e.touches[0];\n this.lastTouchX = t.clientX;\n this.lastTouchY = t.clientY;\n };\n\n private onTouchMove = (e: TouchEvent) => {\n const t = e.touches[0];\n\n const deltaX = t.clientX - this.lastTouchX;\n const deltaY = t.clientY - this.lastTouchY;\n\n this.lastTouchX = t.clientX;\n this.lastTouchY = t.clientY;\n\n this.yaw -= deltaX * 0.002;\n this.pitch -= deltaY * 0.002;\n\n this.pitch = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, this.pitch));\n this.camera.quaternion.setFromEuler(\n new THREE.Euler(this.pitch, this.yaw, 0, \"YXZ\"),\n );\n };\n\n // -----------------------------\n // Camera math\n // -----------------------------\n\n private updateCamera() {\n const spherical = new THREE.Spherical(this.distance, this.pitch, this.yaw);\n\n const pos = new THREE.Vector3()\n .setFromSpherical(spherical)\n .add(this.target);\n\n this.camera.position.copy(pos);\n this.camera.lookAt(this.target);\n }\n\n setTarget(v: THREE.Vector3) {\n this.target.copy(v);\n this.updateCamera();\n }\n}\n","import * as THREE from \"three\";\n\nexport type MeasurementOptions = {\n dom: HTMLElement;\n camera: THREE.PerspectiveCamera;\n scene: THREE.Scene;\n colliders: THREE.Object3D[];\n};\n\ninterface Measurement {\n points: THREE.Vector3[];\n markers: THREE.Mesh[];\n lines: THREE.Line[]; // Changed from line: THREE.Line\n labels: HTMLDivElement[]; // Changed from label: HTMLDivElement\n}\n\nexport class MeasurementController {\n private dom: HTMLElement;\n private camera: THREE.PerspectiveCamera;\n private scene: THREE.Scene;\n private colliders: THREE.Object3D[];\n\n private raycaster = new THREE.Raycaster();\n private mouse = new THREE.Vector2();\n\n private measurements: Measurement[] = [];\n private activePoints: THREE.Vector3[] = [];\n private activeMarkers: THREE.Mesh[] = [];\n private activeLines: THREE.Line[] = [];\n private activeLabels: HTMLDivElement[] = [];\n\n // Ghost elements for the *next* potential segment\n private ghostLine: THREE.Line | null = null;\n private ghostLabel: HTMLDivElement | null = null;\n private lastGhostPoint: THREE.Vector3 | null = null;\n\n private yaw = 0;\n private pitch = Math.PI / 4;\n private dragging = false;\n private panning = false;\n private lastX = 0;\n private lastY = 0;\n private rotateSpeed = 0.005;\n private panSpeed = 0.01;\n private keys: Record<string, boolean> = {};\n private moveSpeed: number = 10;\n private isVisible = true;\n\n constructor(opts: MeasurementOptions) {\n this.dom = opts.dom;\n this.camera = opts.camera;\n this.scene = opts.scene;\n this.colliders = opts.colliders;\n\n this.bind();\n this.bindKeyboard();\n }\n\n dispose() {\n this.unbind();\n this.unbindKeyboard();\n this.clearAll();\n }\n\n private bindKeyboard() {\n window.addEventListener(\"keydown\", this.onKeyDown);\n window.addEventListener(\"keyup\", this.onKeyUp);\n }\n\n private unbindKeyboard() {\n window.removeEventListener(\"keydown\", this.onKeyDown);\n window.removeEventListener(\"keyup\", this.onKeyUp);\n }\n\n private onKeyDown = (e: KeyboardEvent) => {\n this.keys[e.code] = true;\n };\n\n private onKeyUp = (e: KeyboardEvent) => {\n this.keys[e.code] = false;\n };\n\n public setVisible(visible: boolean) {\n this.isVisible = visible;\n this.measurements.forEach(m => {\n m.markers.forEach(mk => mk.visible = visible);\n m.lines.forEach(l => l.visible = visible);\n if (!visible) m.labels.forEach(lbl => lbl.style.display = \"none\");\n });\n\n this.activeMarkers.forEach(mk => mk.visible = visible);\n this.activeLines.forEach(l => l.visible = visible);\n if (!visible) this.activeLabels.forEach(lbl => lbl.style.display = \"none\");\n\n if (this.ghostLine) this.ghostLine.visible = visible;\n if (this.ghostLabel && !visible) this.ghostLabel.style.display = \"none\";\n }\n\n private bind() {\n this.dom.addEventListener(\"contextmenu\", (e) => e.preventDefault());\n this.dom.addEventListener(\"mousedown\", this.onMouseDown);\n window.addEventListener(\"mousemove\", this.onMouseMove);\n window.addEventListener(\"mouseup\", this.onMouseUp);\n }\n\n private unbind() {\n this.dom.removeEventListener(\"mousedown\", this.onMouseDown);\n window.removeEventListener(\"mousemove\", this.onMouseMove);\n window.removeEventListener(\"mouseup\", this.onMouseUp);\n }\n\n private onMouseDown = (e: MouseEvent) => {\n if (e.button === 0) {\n if (!this.isVisible) return;\n if (e.shiftKey) {\n this.dragging = true;\n } else {\n this.handleLeftClick(e);\n }\n } else if (e.button === 2) {\n this.panning = true;\n if (this.isVisible) this.handleRightClick(e);\n } else if (e.button === 1) {\n this.dragging = true;\n }\n\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onMouseUp = () => {\n this.dragging = false;\n this.panning = false;\n };\n\n private handleLeftClick(e: MouseEvent) {\n const rect = this.dom.getBoundingClientRect();\n this.mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;\n this.mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;\n\n this.raycaster.setFromCamera(this.mouse, this.camera);\n const intersects = this.raycaster.intersectObjects(this.colliders, true);\n\n if (intersects.length > 0) {\n const hit = intersects[0].point;\n this.addPoint(hit);\n }\n }\n\n private handleRightClick(e: MouseEvent) {\n console.log(\"[Measure] handleRightClick, activePoints:\", this.activePoints.length);\n if (this.activePoints.length > 0) {\n this.finalizePolyline();\n }\n }\n\n private onMouseMove = (e: MouseEvent) => {\n const dx = e.clientX - this.lastX;\n const dy = e.clientY - this.lastY;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n\n if (!this.isVisible && !this.dragging && !this.panning) return;\n\n if (this.dragging) {\n this.yaw -= dx * this.rotateSpeed;\n this.pitch -= dy * this.rotateSpeed;\n this.pitch = Math.max(0.01, Math.min(Math.PI - 0.01, this.pitch));\n this.camera.quaternion.setFromEuler(new THREE.Euler(this.pitch, this.yaw, 0, 'YXZ'));\n return;\n }\n\n if (this.panning) {\n const right = new THREE.Vector3().set(1, 0, 0).applyQuaternion(this.camera.quaternion);\n const up = new THREE.Vector3().set(0, 1, 0).applyQuaternion(this.camera.quaternion);\n const pan = new THREE.Vector3().addScaledVector(right, -dx * this.panSpeed).addScaledVector(up, dy * this.panSpeed);\n this.camera.position.add(pan);\n return;\n }\n\n if (this.activePoints.length > 0 || true) { // Always update mouse pos for raycasting\n const rect = this.dom.getBoundingClientRect();\n this.mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;\n this.mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;\n\n if (this.activePoints.length > 0) {\n this.raycaster.setFromCamera(this.mouse, this.camera);\n const intersects = this.raycaster.intersectObjects(this.colliders, true);\n if (intersects.length > 0) {\n this.lastGhostPoint = intersects[0].point.clone();\n this.updateGhost(this.activePoints[this.activePoints.length - 1], this.lastGhostPoint);\n }\n }\n }\n };\n\n private addPoint(pos: THREE.Vector3) {\n // Add Marker for new point\n const marker = this.createMarker(pos);\n this.scene.add(marker);\n this.activeMarkers.push(marker);\n\n // If this isn't the first point, create a permanent line + label from previous point\n if (this.activePoints.length > 0) {\n const prev = this.activePoints[this.activePoints.length - 1];\n const current = pos.clone();\n\n const line = this.createLine(prev, current, 0.8); // 0.8 opacity for permanent\n this.scene.add(line);\n this.activeLines.push(line);\n\n const label = this.createLabel();\n this.updateLabelPos(label, prev, current);\n this.activeLabels.push(label);\n }\n\n this.activePoints.push(pos.clone());\n }\n\n private updateGhost(p1: THREE.Vector3, p2: THREE.Vector3) {\n // Update Line\n if (this.ghostLine) this.scene.remove(this.ghostLine);\n this.ghostLine = this.createLine(p1, p2, 0.4); // lower opacity for ghost\n this.scene.add(this.ghostLine);\n\n // Update Label\n if (!this.ghostLabel) {\n this.ghostLabel = this.createLabel();\n }\n this.updateLabelPos(this.ghostLabel, p1, p2);\n }\n\n public finalizePolyline() {\n console.log(\"[Measure] finalizePolyline, points:\", this.activePoints.length);\n if (this.activePoints.length === 0) {\n this.clearActiveSession();\n return;\n }\n\n // Bundle everything into a measurement object\n // NOTE: In a real polyline impl, we might want to store all segments. \n // For 'getMeasurements', we'll flatten this or just store lines.\n // For now, let's treat the whole polyline as one \"Measurement\" entry \n // but it holds multiple lines/markers.\n\n // We'll trick the existing structure a bit or assume the consumer handles it,\n // but to keep it compatible with existing types, let's construct a \"Measurement\" \n // that holds arrays of these things.\n\n // Actually, we're better off refactoring `Measurement` interface if we want true polyline support.\n // But to stick to the requested \"add multiple point functionality\" quickly:\n // We will push ONE measurement object per polyline.\n // However, the `Measurement` interface defined previously had `line: THREE.Line` (singular).\n // Let's update `Measurement` interface to support multiple.\n\n // Wait, to avoid breaking too much code, let's just make `Measurement` hold arrays of lines too?\n // Or better: Each segment is a measurement? No, that spams the list.\n // Let's assume a \"Distance\" is total distance? \n\n // Let's assume the user just wants to click-click-click and leave trails.\n // We will group them.\n\n const newMeasurement: Measurement = {\n points: [...this.activePoints],\n markers: [...this.activeMarkers],\n // We need to change the interface to support multiple lines/labels or change how we store them.\n // For this specific 'hack' to work with minimal changes, let's cast or change the type below.\n // See 'createLine' helper.\n lines: [...this.activeLines],\n labels: [...this.activeLabels]\n } as any;\n\n this.measurements.push(newMeasurement);\n\n // Clear active session state WITHOUT removing from scene\n this.activePoints = [];\n this.activeMarkers = [];\n this.activeLines = [];\n this.activeLabels = [];\n\n if (this.ghostLine) {\n this.scene.remove(this.ghostLine);\n this.ghostLine = null;\n }\n if (this.ghostLabel) {\n this.ghostLabel.remove();\n this.ghostLabel = null;\n }\n this.lastGhostPoint = null;\n }\n\n private clearActiveSession() {\n this.activeMarkers.forEach(mk => this.scene.remove(mk));\n this.activeLines.forEach(l => this.scene.remove(l));\n this.activeLabels.forEach(l => l.remove());\n\n this.activePoints = [];\n this.activeMarkers = [];\n this.activeLines = [];\n this.activeLabels = [];\n\n if (this.ghostLine) {\n this.scene.remove(this.ghostLine);\n this.ghostLine = null;\n }\n if (this.ghostLabel) {\n this.ghostLabel.remove();\n this.ghostLabel = null;\n }\n this.lastGhostPoint = null;\n }\n\n private createLine(p1: THREE.Vector3, p2: THREE.Vector3, opacity: number) {\n const geometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);\n const material = new THREE.LineBasicMaterial({\n color: 0xffffff,\n linewidth: 1,\n depthTest: false,\n transparent: true,\n opacity: opacity\n });\n const line = new THREE.Line(geometry, material);\n line.renderOrder = 1000;\n line.frustumCulled = false;\n return line;\n }\n\n private createMarker(pos: THREE.Vector3) {\n const marker = new THREE.Mesh(\n new THREE.SphereGeometry(0.02),\n new THREE.MeshBasicMaterial({\n color: 0xffffff,\n depthTest: false,\n transparent: true,\n opacity: 0.9\n })\n );\n marker.position.copy(pos);\n marker.renderOrder = 1001;\n marker.frustumCulled = false;\n return marker;\n }\n\n private createLabel() {\n const label = document.createElement(\"div\");\n label.style.position = \"absolute\";\n label.style.pointerEvents = \"none\";\n label.style.background = \"rgba(0,0,0,0.6)\";\n label.style.color = \"white\";\n label.style.padding = \"4px 8px\";\n label.style.borderRadius = \"12px\";\n label.style.fontSize = \"11px\";\n label.style.fontFamily = \"sans-serif\";\n label.style.fontWeight = \"500\";\n label.style.zIndex = \"100\";\n label.style.backdropFilter = \"blur(4px)\";\n // label.style.border = \"1px solid rgba(255,255,255,0.2)\";\n this.dom.parentElement?.appendChild(label);\n return label;\n }\n\n private updateLabelPos(label: HTMLDivElement, p1: THREE.Vector3, p2: THREE.Vector3) {\n const distance = p1.distanceTo(p2);\n const midPoint = new THREE.Vector3().lerpVectors(p1, p2, 0.5);\n const vector = midPoint.project(this.camera);\n\n if (vector.z > 1) {\n label.style.display = \"none\";\n return;\n }\n\n const x = (vector.x * 0.5 + 0.5) * this.dom.clientWidth;\n const y = (-(vector.y * 0.5) + 0.5) * this.dom.clientHeight;\n\n label.style.left = `${x}px`;\n label.style.top = `${y}px`;\n label.innerText = `${distance.toFixed(3)}m`;\n label.style.display = (this.isVisible && vector.z <= 1) ? \"block\" : \"none\";\n }\n\n public restoreMeasurements(measurements: Measurement[]) {\n this.measurements = measurements;\n this.measurements.forEach(m => {\n m.markers.forEach(mk => {\n mk.visible = this.isVisible;\n this.scene.add(mk);\n });\n m.lines.forEach(l => {\n l.visible = this.isVisible;\n this.scene.add(l);\n });\n m.labels.forEach((lbl, idx) => {\n this.dom.parentElement?.appendChild(lbl);\n if (idx < m.points.length - 1) {\n this.updateLabelPos(lbl, m.points[idx], m.points[idx + 1]);\n }\n });\n });\n }\n\n public getMeasurements() {\n return this.measurements.map((m, i) => {\n // Calculate total distance for the polyline\n let totalDist = 0;\n for (let j = 0; j < m.points.length - 1; j++) {\n totalDist += m.points[j].distanceTo(m.points[j + 1]);\n }\n\n return {\n id: i,\n distance: totalDist,\n points: m.points.map(p => p.clone()),\n segments: m.points.length - 1\n };\n });\n }\n\n public deleteMeasurement(index: number) {\n if (index < 0 || index >= this.measurements.length) return;\n const m = this.measurements[index];\n m.markers.forEach(mk => this.scene.remove(mk));\n m.lines.forEach(l => this.scene.remove(l));\n m.labels.forEach(lbl => lbl.remove());\n this.measurements.splice(index, 1);\n }\n\n public clearAll() {\n this.measurements.forEach(m => {\n m.markers.forEach(mk => this.scene.remove(mk));\n m.lines.forEach(l => this.scene.remove(l));\n m.labels.forEach(lbl => lbl.remove());\n });\n this.measurements = [];\n this.activePoints = [];\n if (this.ghostLine) this.scene.remove(this.ghostLine);\n\n // Clear any leftover active markers if the session was abandoned\n this.activeMarkers.forEach(mk => this.scene.remove(mk));\n this.activeLines.forEach(l => this.scene.remove(l));\n this.activeLabels.forEach(l => l.remove());\n\n if (this.ghostLabel) this.ghostLabel.remove();\n this.ghostLine = null;\n this.ghostLabel = null;\n this.lastGhostPoint = null;\n }\n\n update(dt: number = 1 / 60) {\n if (!this.isVisible) return;\n const move = new THREE.Vector3(0, 0, 0);\n\n // Keyboard Movement (WASDQE)\n const forward = new THREE.Vector3();\n this.camera.getWorldDirection(forward);\n const orbitForward = forward.clone();\n orbitForward.y = 0;\n orbitForward.normalize();\n\n const right = new THREE.Vector3()\n .crossVectors(orbitForward, new THREE.Vector3(0, 1, 0))\n .normalize();\n\n if (this.keys[\"KeyW\"]) move.add(orbitForward);\n if (this.keys[\"KeyS\"]) move.sub(orbitForward);\n if (this.keys[\"KeyA\"]) move.sub(right);\n if (this.keys[\"KeyD\"]) move.add(right);\n if (this.keys[\"KeyE\"]) move.y += 1;\n if (this.keys[\"KeyQ\"]) move.y -= 1;\n\n if (move.lengthSq() > 0) {\n move.normalize();\n move.multiplyScalar(this.moveSpeed * dt);\n this.camera.position.add(move);\n }\n\n // Update raycasting/ghost even if mouse isn't moving, because camera is moving\n if (this.activePoints.length > 0) {\n this.raycaster.setFromCamera(this.mouse, this.camera);\n const intersects = this.raycaster.intersectObjects(this.colliders, true);\n if (intersects.length > 0) {\n this.lastGhostPoint = intersects[0].point.clone();\n this.updateGhost(this.activePoints[this.activePoints.length - 1], this.lastGhostPoint);\n }\n }\n\n this.measurements.forEach(m => {\n // Update all labels in this measurement\n m.labels.forEach((lbl, idx) => {\n if (idx < m.points.length - 1) {\n this.updateLabelPos(lbl, m.points[idx], m.points[idx + 1]);\n }\n });\n });\n\n // Also update active session labels\n this.activeLabels.forEach((lbl, idx) => {\n if (idx < this.activePoints.length - 1) {\n this.updateLabelPos(lbl, this.activePoints[idx], this.activePoints[idx + 1]);\n }\n });\n\n if (this.ghostLabel && this.activePoints.length > 0 && this.lastGhostPoint) {\n this.updateLabelPos(this.ghostLabel, this.activePoints[this.activePoints.length - 1], this.lastGhostPoint);\n }\n }\n}\n","import * as THREE from \"three\";\n\nexport type FloorplanOptions = {\n dom: HTMLElement;\n camera: THREE.PerspectiveCamera;\n target: THREE.Vector3;\n height: number; // camera y above target\n panSpeed?: number; // world units per pixel\n zoomSpeed?: number; // wheel multiplier\n minHeight?: number;\n maxHeight?: number;\n};\n\nexport class FloorplanController {\n private dom: HTMLElement;\n private camera: THREE.PerspectiveCamera;\n\n private target: THREE.Vector3;\n private height: number;\n\n private panSpeed: number;\n private zoomSpeed: number;\n private minHeight: number;\n private maxHeight: number;\n\n private isDragging = false;\n private lastX = 0;\n private lastY = 0;\n\n // touch\n private touchMode: \"none\" | \"pan\" | \"pinch\" = \"none\";\n private lastDist = 0;\n\n constructor(opts: FloorplanOptions) {\n this.dom = opts.dom;\n this.camera = opts.camera;\n\n this.target = opts.target.clone();\n this.height = opts.height;\n\n this.panSpeed = opts.panSpeed ?? 0.01;\n this.zoomSpeed = opts.zoomSpeed ?? 1.1;\n this.minHeight = opts.minHeight ?? opts.height * 0.25;\n this.maxHeight = opts.maxHeight ?? opts.height * 3.0;\n\n this.applyCamera();\n this.bind();\n }\n\n dispose() {\n this.unbind();\n }\n\n update(_dt: number) {\n // keep camera locked top-down always\n this.applyCamera();\n }\n\n setTarget(t: THREE.Vector3) {\n this.target.copy(t);\n this.applyCamera();\n }\n\n private applyCamera() {\n this.height = THREE.MathUtils.clamp(\n this.height,\n this.minHeight,\n this.maxHeight,\n );\n this.camera.position.set(\n this.target.x,\n this.target.y + this.height,\n this.target.z,\n );\n this.camera.up.set(0, 0, -1); // keeps “north” stable (optional)\n this.camera.lookAt(this.target);\n }\n\n private bind() {\n this.dom.addEventListener(\"contextmenu\", (e) => e.preventDefault());\n this.dom.addEventListener(\"mousedown\", this.onMouseDown);\n window.addEventListener(\"mousemove\", this.onMouseMove);\n window.addEventListener(\"mouseup\", this.onMouseUp);\n this.dom.addEventListener(\"wheel\", this.onWheel, { passive: false });\n\n this.dom.addEventListener(\"touchstart\", this.onTouchStart, {\n passive: false,\n });\n this.dom.addEventListener(\"touchmove\", this.onTouchMove, {\n passive: false,\n });\n this.dom.addEventListener(\"touchend\", this.onTouchEnd);\n }\n\n private unbind() {\n this.dom.removeEventListener(\"mousedown\", this.onMouseDown);\n window.removeEventListener(\"mousemove\", this.onMouseMove);\n window.removeEventListener(\"mouseup\", this.onMouseUp);\n this.dom.removeEventListener(\"wheel\", this.onWheel);\n\n this.dom.removeEventListener(\"touchstart\", this.onTouchStart);\n this.dom.removeEventListener(\"touchmove\", this.onTouchMove);\n this.dom.removeEventListener(\"touchend\", this.onTouchEnd);\n }\n\n private onMouseDown = (e: MouseEvent) => {\n if (e.button !== 0) return;\n this.isDragging = true;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onMouseUp = () => {\n this.isDragging = false;\n };\n\n private onMouseMove = (e: MouseEvent) => {\n if (!this.isDragging) return;\n\n const dx = e.clientX - this.lastX;\n const dy = e.clientY - this.lastY;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n\n // screen -> world: in top-down, x maps to world x, y maps to world z\n this.target.x -= dx * this.panSpeed * this.height;\n this.target.z += dy * this.panSpeed * this.height;\n\n this.applyCamera();\n };\n\n private onWheel = (e: WheelEvent) => {\n e.preventDefault();\n const factor = Math.pow(this.zoomSpeed, e.deltaY / 100);\n this.height *= factor;\n this.applyCamera();\n };\n\n private onTouchStart = (e: TouchEvent) => {\n if (e.touches.length === 1) {\n this.touchMode = \"pan\";\n this.lastX = e.touches[0].clientX;\n this.lastY = e.touches[0].clientY;\n } else if (e.touches.length === 2) {\n this.touchMode = \"pinch\";\n this.lastDist = this.touchDistance(e.touches[0], e.touches[1]);\n }\n };\n\n private onTouchMove = (e: TouchEvent) => {\n e.preventDefault();\n\n if (this.touchMode === \"pan\" && e.touches.length === 1) {\n const x = e.touches[0].clientX;\n const y = e.touches[0].clientY;\n const dx = x - this.lastX;\n const dy = y - this.lastY;\n this.lastX = x;\n this.lastY = y;\n\n this.target.x -= dx * this.panSpeed * this.height;\n this.target.z += dy * this.panSpeed * this.height;\n\n this.applyCamera();\n }\n\n if (this.touchMode === \"pinch\" && e.touches.length === 2) {\n const dist = this.touchDistance(e.touches[0], e.touches[1]);\n const ratio = this.lastDist / Math.max(1e-6, dist);\n this.lastDist = dist;\n\n this.height *= ratio;\n this.applyCamera();\n }\n };\n\n private onTouchEnd = () => {\n this.touchMode = \"none\";\n };\n\n private touchDistance(a: Touch, b: Touch) {\n const dx = a.clientX - b.clientX;\n const dy = a.clientY - b.clientY;\n return Math.sqrt(dx * dx + dy * dy);\n }\n}\n"],"mappings":"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","names":["THREE","RAPIER","THREE","THREE","THREE"]}
|
|
File without changes
|