@pisell/materials 1.8.54 → 1.8.56

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.
Files changed (151) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/async/view.js +1 -1
  5. package/build/lowcode/index.js +1 -1
  6. package/build/lowcode/meta.js +3 -3
  7. package/build/lowcode/preview.js +1 -1
  8. package/build/lowcode/render/default/async/view.js +1 -1
  9. package/build/lowcode/render/default/view.css +1 -1
  10. package/build/lowcode/render/default/view.js +37 -37
  11. package/build/lowcode/view.css +1 -1
  12. package/build/lowcode/view.js +37 -37
  13. package/es/components/buttonGroupPreview/index.js +8 -4
  14. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.js +207 -49
  15. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.less +33 -2
  16. package/es/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +50 -2
  17. package/es/components/pisellFloorMapLayout/components/EdgeLayer.js +252 -0
  18. package/es/components/pisellFloorMapLayout/components/EdgeLayer.less +11 -0
  19. package/es/components/pisellFloorMapLayout/components/EditableItemLayer.js +179 -29
  20. package/es/components/pisellFloorMapLayout/components/EditableItemLayer.less +0 -28
  21. package/es/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.js +131 -0
  22. package/es/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.less +65 -0
  23. package/es/components/pisellFloorMapLayout/components/FloorMapEditPanel.js +5 -4
  24. package/es/components/pisellFloorMapLayout/components/FloorMapEditPanel.less +12 -1
  25. package/es/components/pisellFloorMapLayout/components/FloorMapEditQuickActions.js +8 -1
  26. package/es/components/pisellFloorMapLayout/components/FloorMapOverview.js +16 -8
  27. package/es/components/pisellFloorMapLayout/components/FloorMapOverview.less +69 -17
  28. package/es/components/pisellFloorMapLayout/components/FloorMapToolbar.js +290 -147
  29. package/es/components/pisellFloorMapLayout/components/FloorMapToolbar.less +210 -11
  30. package/es/components/pisellFloorMapLayout/components/FloorMapToolbarViewAllModal.js +81 -0
  31. package/es/components/pisellFloorMapLayout/components/FloorMapZoneElement.d.ts +8 -0
  32. package/es/components/pisellFloorMapLayout/components/FloorMapZoneElement.js +21 -0
  33. package/es/components/pisellFloorMapLayout/components/FloorMapZoneElement.less +74 -0
  34. package/es/components/pisellFloorMapLayout/components/ItemLayer.less +3 -1
  35. package/es/components/pisellFloorMapLayout/components/NodePortMarkers.js +70 -0
  36. package/es/components/pisellFloorMapLayout/components/NodePortMarkers.less +33 -0
  37. package/es/components/pisellFloorMapLayout/components/ViewControls.js +13 -5
  38. package/es/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +2 -0
  39. package/es/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +2 -1
  40. package/es/components/pisellFloorMapLayout/floorMapLayoutConstants.js +1 -1
  41. package/es/components/pisellFloorMapLayout/hooks/useFloorMapEdgeEditing.js +340 -0
  42. package/es/components/pisellFloorMapLayout/hooks/useFloorMapEdgeViewModel.js +102 -0
  43. package/es/components/pisellFloorMapLayout/hooks/useFloorMapEditState.js +244 -84
  44. package/es/components/pisellFloorMapLayout/hooks/useFloorMapTransformMetrics.js +54 -0
  45. package/es/components/pisellFloorMapLayout/hooks/useShopFloorPlanSubscription.js +7 -4
  46. package/es/components/pisellFloorMapLayout/index.d.ts +5 -1
  47. package/es/components/pisellFloorMapLayout/locales-ja.js +14 -2
  48. package/es/components/pisellFloorMapLayout/locales-pt.js +14 -2
  49. package/es/components/pisellFloorMapLayout/locales.js +161 -8
  50. package/es/components/pisellFloorMapLayout/types.d.ts +86 -4
  51. package/es/components/pisellFloorMapLayout/types.js +5 -1
  52. package/es/components/pisellFloorMapLayout/utils/alignSnap.js +170 -0
  53. package/es/components/pisellFloorMapLayout/utils/batchScenePlacementLayout.js +86 -0
  54. package/es/components/pisellFloorMapLayout/utils/edgeRouting.js +942 -0
  55. package/es/components/pisellFloorMapLayout/utils/floorMapCanvasDisplay.d.ts +7 -0
  56. package/es/components/pisellFloorMapLayout/utils/floorMapCanvasStage.js +23 -1
  57. package/es/components/pisellFloorMapLayout/utils/floorMapConfigMerge.js +11 -2
  58. package/es/components/pisellFloorMapLayout/utils/floorMapElementKindUtils.js +20 -3
  59. package/es/components/pisellFloorMapLayout/utils/floorMapFallbackRender.js +11 -5
  60. package/es/components/pisellFloorMapLayout/utils/floorMapOverviewLayout.js +5 -3
  61. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.d.ts +20 -0
  62. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.js +62 -0
  63. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.d.ts +83 -0
  64. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.js +29 -0
  65. package/es/components/pisellFloorMapLayout/utils/floorMapToolbarPalette.js +51 -0
  66. package/es/components/productCard/cartSkuCard/components/BookingItem/index.js +14 -0
  67. package/es/components/productCard/cartSkuCard/components/BookingItem/index.less +32 -0
  68. package/es/components/productCard/cartSkuCard/components/resources/index.less +4 -0
  69. package/es/components/productCard/cartSkuCard/components/timeRange/index.js +1 -2
  70. package/es/components/productCard/cartSkuCard/index.js +17 -11
  71. package/es/components/productCard/lineItem/BookingLineItem.js +17 -6
  72. package/es/components/productCard/lineItem/components/Holders/index.js +51 -0
  73. package/es/components/productCard/lineItem/components/Holders/index.less +39 -0
  74. package/es/components/productCard/lineItem/components/Resources/index.js +45 -0
  75. package/es/components/productCard/lineItem/components/TimeRange/index.js +64 -0
  76. package/es/components/productCard/lineItem/index.js +5 -2
  77. package/es/components/productCard/lineItem/index.less +21 -10
  78. package/es/components/productCard/types.d.ts +1 -0
  79. package/es/index.d.ts +6 -2
  80. package/es/index.js +6 -2
  81. package/es/pisell-materials.tw.css +3 -0
  82. package/lib/components/buttonGroupPreview/index.js +8 -4
  83. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.js +206 -48
  84. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.less +33 -2
  85. package/lib/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +50 -2
  86. package/lib/components/pisellFloorMapLayout/components/EdgeLayer.js +255 -0
  87. package/lib/components/pisellFloorMapLayout/components/EdgeLayer.less +11 -0
  88. package/lib/components/pisellFloorMapLayout/components/EditableItemLayer.js +179 -29
  89. package/lib/components/pisellFloorMapLayout/components/EditableItemLayer.less +0 -28
  90. package/lib/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.js +134 -0
  91. package/lib/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.less +65 -0
  92. package/lib/components/pisellFloorMapLayout/components/FloorMapEditPanel.js +4 -3
  93. package/lib/components/pisellFloorMapLayout/components/FloorMapEditPanel.less +12 -1
  94. package/lib/components/pisellFloorMapLayout/components/FloorMapEditQuickActions.js +8 -1
  95. package/lib/components/pisellFloorMapLayout/components/FloorMapOverview.js +16 -8
  96. package/lib/components/pisellFloorMapLayout/components/FloorMapOverview.less +69 -17
  97. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbar.js +287 -144
  98. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbar.less +210 -11
  99. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbarViewAllModal.js +84 -0
  100. package/lib/components/pisellFloorMapLayout/components/FloorMapZoneElement.d.ts +8 -0
  101. package/lib/components/pisellFloorMapLayout/components/FloorMapZoneElement.js +23 -0
  102. package/lib/components/pisellFloorMapLayout/components/FloorMapZoneElement.less +74 -0
  103. package/lib/components/pisellFloorMapLayout/components/ItemLayer.less +3 -1
  104. package/lib/components/pisellFloorMapLayout/components/NodePortMarkers.js +73 -0
  105. package/lib/components/pisellFloorMapLayout/components/NodePortMarkers.less +33 -0
  106. package/lib/components/pisellFloorMapLayout/components/ViewControls.js +12 -4
  107. package/lib/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +2 -0
  108. package/lib/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +2 -1
  109. package/lib/components/pisellFloorMapLayout/floorMapLayoutConstants.js +1 -1
  110. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapEdgeEditing.js +341 -0
  111. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapEdgeViewModel.js +103 -0
  112. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapEditState.js +242 -82
  113. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapTransformMetrics.js +54 -0
  114. package/lib/components/pisellFloorMapLayout/hooks/useShopFloorPlanSubscription.js +7 -4
  115. package/lib/components/pisellFloorMapLayout/index.d.ts +5 -1
  116. package/lib/components/pisellFloorMapLayout/locales-ja.js +14 -2
  117. package/lib/components/pisellFloorMapLayout/locales-pt.js +14 -2
  118. package/lib/components/pisellFloorMapLayout/locales.js +161 -8
  119. package/lib/components/pisellFloorMapLayout/types.d.ts +86 -4
  120. package/lib/components/pisellFloorMapLayout/types.js +5 -0
  121. package/lib/components/pisellFloorMapLayout/utils/alignSnap.js +170 -0
  122. package/lib/components/pisellFloorMapLayout/utils/batchScenePlacementLayout.js +87 -0
  123. package/lib/components/pisellFloorMapLayout/utils/edgeRouting.js +956 -0
  124. package/lib/components/pisellFloorMapLayout/utils/floorMapCanvasDisplay.d.ts +7 -0
  125. package/lib/components/pisellFloorMapLayout/utils/floorMapCanvasStage.js +23 -0
  126. package/lib/components/pisellFloorMapLayout/utils/floorMapConfigMerge.js +11 -2
  127. package/lib/components/pisellFloorMapLayout/utils/floorMapElementKindUtils.js +21 -2
  128. package/lib/components/pisellFloorMapLayout/utils/floorMapFallbackRender.js +11 -5
  129. package/lib/components/pisellFloorMapLayout/utils/floorMapOverviewLayout.js +5 -3
  130. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.d.ts +20 -0
  131. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.js +64 -0
  132. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.d.ts +83 -0
  133. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.js +29 -0
  134. package/lib/components/pisellFloorMapLayout/utils/floorMapToolbarPalette.js +54 -0
  135. package/lib/components/productCard/cartSkuCard/components/BookingItem/index.js +17 -0
  136. package/lib/components/productCard/cartSkuCard/components/BookingItem/index.less +32 -0
  137. package/lib/components/productCard/cartSkuCard/components/resources/index.less +4 -0
  138. package/lib/components/productCard/cartSkuCard/components/timeRange/index.js +1 -2
  139. package/lib/components/productCard/cartSkuCard/index.js +17 -11
  140. package/lib/components/productCard/lineItem/BookingLineItem.js +17 -6
  141. package/lib/components/productCard/lineItem/components/Holders/index.js +53 -0
  142. package/lib/components/productCard/lineItem/components/Holders/index.less +39 -0
  143. package/lib/components/productCard/lineItem/components/Resources/index.js +47 -0
  144. package/lib/components/productCard/lineItem/components/TimeRange/index.js +67 -0
  145. package/lib/components/productCard/lineItem/index.js +5 -2
  146. package/lib/components/productCard/lineItem/index.less +21 -10
  147. package/lib/components/productCard/types.d.ts +1 -0
  148. package/lib/index.d.ts +6 -2
  149. package/lib/index.js +11 -0
  150. package/lib/pisell-materials.tw.css +3 -0
  151. package/package.json +6 -3
@@ -0,0 +1,3 @@
1
+ *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }
2
+
3
+ /*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder, textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none!important}.\!visible,.visible{visibility:visible!important}.collapse{visibility:collapse!important}.static{position:static!important}.fixed{position:fixed!important}.absolute{position:absolute!important}.relative{position:relative!important}.sticky{position:sticky!important}.inset-0{inset:0!important}.inset-6{inset:1.5rem!important}.inset-x-0{left:0!important;right:0!important}.inset-y-0{top:0!important;bottom:0!important}.bottom-6{bottom:1.5rem!important}.left-0{left:0!important}.left-1\/2{left:50%!important}.right-0{right:0!important}.top-0{top:0!important}.top-2{top:.5rem!important}.top-\[60px\]{top:60px!important}.isolate{isolation:isolate!important}.z-20{z-index:20!important}.z-30{z-index:30!important}.z-50{z-index:50!important}.z-\[25\]{z-index:25!important}.z-\[26\]{z-index:26!important}.z-\[60\]{z-index:60!important}.z-\[69\]{z-index:69!important}.z-\[72\]{z-index:72!important}.mx-0{margin-left:0!important;margin-right:0!important}.mx-auto{margin-left:auto!important;margin-right:auto!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:.75rem!important}.mb-4{margin-bottom:1rem!important}.mt-0\.5{margin-top:.125rem!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:.75rem!important}.mt-5{margin-top:1.25rem!important}.mt-6{margin-top:1.5rem!important}.block{display:block!important}.inline-block{display:inline-block!important}.inline{display:inline!important}.flex{display:flex!important}.inline-flex{display:inline-flex!important}.table{display:table!important}.grid{display:grid!important}.contents{display:contents!important}.hidden{display:none!important}.h-10{height:2.5rem!important}.h-2\.5{height:.625rem!important}.h-\[52px\]{height:52px!important}.h-full{height:100%!important}.max-h-\[360px\]{max-height:360px!important}.max-h-\[72vh\]{max-height:72vh!important}.max-h-\[78vh\]{max-height:78vh!important}.max-h-\[92vh\]{max-height:92vh!important}.max-h-none{max-height:none!important}.min-h-0,.min-h-\[0\]{min-height:0!important}.min-h-\[28px\]{min-height:28px!important}.w-10{width:2.5rem!important}.w-14{width:3.5rem!important}.w-2\.5{width:.625rem!important}.w-\[132px\]{width:132px!important}.w-\[2px\]{width:2px!important}.w-\[52px\]{width:52px!important}.w-fit{width:-moz-fit-content!important;width:fit-content!important}.w-full{width:100%!important}.min-w-0{min-width:0!important}.min-w-\[132px\]{min-width:132px!important}.min-w-\[240px\]{min-width:240px!important}.min-w-\[980px\]{min-width:980px!important}.max-w-\[132px\]{max-width:132px!important}.max-w-\[260px\]{max-width:260px!important}.max-w-\[520px\]{max-width:520px!important}.max-w-\[720px\]{max-width:720px!important}.max-w-\[900px\]{max-width:900px!important}.max-w-\[92vw\]{max-width:92vw!important}.max-w-\[980px\]{max-width:980px!important}.max-w-full{max-width:100%!important}.max-w-none{max-width:none!important}.flex-1{flex:1 1 0%!important}.flex-shrink{flex-shrink:1!important}.shrink-0{flex-shrink:0!important}.flex-grow{flex-grow:1!important}.border-collapse{border-collapse:collapse!important}.-translate-x-1\/2{--tw-translate-x:-50%!important}.-rotate-90,.-translate-x-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.-rotate-90{--tw-rotate:-90deg!important}.rotate-0{--tw-rotate:0deg!important}.\!transform,.rotate-0,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.cursor-grab{cursor:grab!important}.cursor-grabbing{cursor:grabbing!important}.cursor-pointer{cursor:pointer!important}.touch-pan-x{--tw-pan-x:pan-x!important}.touch-pan-x,.touch-pan-y{touch-action:var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)!important}.touch-pan-y{--tw-pan-y:pan-y!important}.select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.select-text{-webkit-user-select:text!important;-moz-user-select:text!important;user-select:text!important}.select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.resize-none{resize:none!important}.resize{resize:both!important}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))!important}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))!important}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))!important}.grid-cols-\[0\.8fr_1fr_1\.3fr_0\.9fr_0\.9fr\]{grid-template-columns:.8fr 1fr 1.3fr .9fr .9fr!important}.flex-col{flex-direction:column!important}.flex-col-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.place-items-center{place-items:center!important}.items-start{align-items:flex-start!important}.items-end{align-items:flex-end!important}.items-center{align-items:center!important}.items-stretch{align-items:stretch!important}.justify-start{justify-content:flex-start!important}.justify-end{justify-content:flex-end!important}.justify-center{justify-content:center!important}.justify-between{justify-content:space-between!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-1\.5{gap:.375rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:.75rem!important}.gap-4{gap:1rem!important}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0!important;margin-top:calc(0.25rem*(1 - var(--tw-space-y-reverse)))!important;margin-bottom:calc(0.25rem*var(--tw-space-y-reverse))!important}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0!important;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))!important;margin-bottom:calc(1rem*var(--tw-space-y-reverse))!important}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0!important;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))!important;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))!important}.self-center{align-self:center!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-x-auto{overflow-x:auto!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overscroll-y-contain{overscroll-behavior-y:contain!important}.truncate{overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.break-words{overflow-wrap:break-word!important}.rounded{border-radius:.25rem!important}.rounded-2xl{border-radius:1rem!important}.rounded-3xl{border-radius:1.5rem!important}.rounded-\[28px\]{border-radius:28px!important}.rounded-\[30px\]{border-radius:30px!important}.rounded-full{border-radius:9999px!important}.rounded-lg{border-radius:.5rem!important}.rounded-md{border-radius:.375rem!important}.rounded-xl{border-radius:.75rem!important}.rounded-t-3xl{border-top-left-radius:1.5rem!important;border-top-right-radius:1.5rem!important}.border{border-width:1px!important}.border-b{border-bottom-width:1px!important}.border-b-4{border-bottom-width:4px!important}.border-l{border-left-width:1px!important}.border-r{border-right-width:1px!important}.border-dashed{border-style:dashed!important}.border-\[\#d8d0eb\]{--tw-border-opacity:1!important;border-color:rgb(216 208 235/var(--tw-border-opacity,1))!important}.border-\[var\(--border-strong\)\]{border-color:var(--border-strong)!important}.border-\[var\(--brand-light\)\]{border-color:var(--brand-light)!important}.border-amber-200\/35{border-color:rgba(253,230,138,.35)!important}.border-amber-400\/80{border-color:rgba(251,191,36,.8)!important}.border-amber-400\/95{border-color:rgba(251,191,36,.95)!important}.border-cyan-300\/35{border-color:rgba(103,232,249,.35)!important}.border-emerald-300\/35{border-color:rgba(110,231,183,.35)!important}.border-red-200{--tw-border-opacity:1!important;border-color:rgb(254 202 202/var(--tw-border-opacity,1))!important}.border-red-300\/35{border-color:rgba(252,165,165,.35)!important}.border-red-300\/55{border-color:rgba(252,165,165,.55)!important}.border-red-400\/75{border-color:rgba(248,113,113,.75)!important}.border-red-500\/70{border-color:rgba(239,68,68,.7)!important}.border-red-700\/50{border-color:rgba(185,28,28,.5)!important}.border-red-800\/40{border-color:rgba(153,27,27,.4)!important}.border-slate-200{--tw-border-opacity:1!important;border-color:rgb(226 232 240/var(--tw-border-opacity,1))!important}.border-slate-700{--tw-border-opacity:1!important;border-color:rgb(51 65 85/var(--tw-border-opacity,1))!important}.border-slate-800{--tw-border-opacity:1!important;border-color:rgb(30 41 59/var(--tw-border-opacity,1))!important}.border-violet-300\/30{border-color:rgba(196,181,253,.3)!important}.border-violet-400\/20{border-color:rgba(167,139,250,.2)!important}.border-violet-500\/30{border-color:rgba(139,92,246,.3)!important}.border-white\/10{border-color:hsla(0,0%,100%,.1)!important}.border-zinc-300\/30{border-color:rgba(212,212,216,.3)!important}.border-zinc-300\/45{border-color:rgba(212,212,216,.45)!important}.border-zinc-400\/45{border-color:rgba(161,161,170,.45)!important}.border-zinc-500\/70{border-color:rgba(113,113,122,.7)!important}.border-zinc-700{--tw-border-opacity:1!important;border-color:rgb(63 63 70/var(--tw-border-opacity,1))!important}.border-zinc-800{--tw-border-opacity:1!important;border-color:rgb(39 39 42/var(--tw-border-opacity,1))!important}.border-zinc-800\/80{border-color:rgba(39,39,42,.8)!important}.border-b-transparent{border-bottom-color:transparent!important}.border-l-transparent{border-left-color:transparent!important}.bg-\[\#101117\]{--tw-bg-opacity:1!important;background-color:rgb(16 17 23/var(--tw-bg-opacity,1))!important}.bg-\[\#111217\]{--tw-bg-opacity:1!important;background-color:rgb(17 18 23/var(--tw-bg-opacity,1))!important}.bg-\[\#111218\]{--tw-bg-opacity:1!important;background-color:rgb(17 18 24/var(--tw-bg-opacity,1))!important}.bg-\[\#121217\]{--tw-bg-opacity:1!important;background-color:rgb(18 18 23/var(--tw-bg-opacity,1))!important}.bg-\[\#151220\]{--tw-bg-opacity:1!important;background-color:rgb(21 18 32/var(--tw-bg-opacity,1))!important}.bg-\[\#151a2f\]{--tw-bg-opacity:1!important;background-color:rgb(21 26 47/var(--tw-bg-opacity,1))!important}.bg-\[\#171820\]{--tw-bg-opacity:1!important;background-color:rgb(23 24 32/var(--tw-bg-opacity,1))!important}.bg-\[\#1a1a22\]{--tw-bg-opacity:1!important;background-color:rgb(26 26 34/var(--tw-bg-opacity,1))!important}.bg-\[\#1a1b21\]{--tw-bg-opacity:1!important;background-color:rgb(26 27 33/var(--tw-bg-opacity,1))!important}.bg-\[\#1c1630\]{--tw-bg-opacity:1!important;background-color:rgb(28 22 48/var(--tw-bg-opacity,1))!important}.bg-\[\#1e1a32\]{--tw-bg-opacity:1!important;background-color:rgb(30 26 50/var(--tw-bg-opacity,1))!important}.bg-\[\#241d40\]{--tw-bg-opacity:1!important;background-color:rgb(36 29 64/var(--tw-bg-opacity,1))!important}.bg-\[var\(--bg-input\)\]{background-color:var(--bg-input)!important}.bg-\[var\(--brand-surface\)\]{background-color:var(--brand-surface)!important}.bg-amber-500{--tw-bg-opacity:1!important;background-color:rgb(245 158 11/var(--tw-bg-opacity,1))!important}.bg-black\/25{background-color:rgba(0,0,0,.25)!important}.bg-black\/45{background-color:rgba(0,0,0,.45)!important}.bg-black\/55{background-color:rgba(0,0,0,.55)!important}.bg-cyan-500{--tw-bg-opacity:1!important;background-color:rgb(6 182 212/var(--tw-bg-opacity,1))!important}.bg-emerald-400\/95{background-color:rgba(52,211,153,.95)!important}.bg-emerald-500{--tw-bg-opacity:1!important;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))!important}.bg-emerald-600{--tw-bg-opacity:1!important;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))!important}.bg-red-50{background-color:rgb(254 242 242/var(--tw-bg-opacity,1))!important}.bg-red-50,.bg-red-500{--tw-bg-opacity:1!important}.bg-red-500{background-color:rgb(239 68 68/var(--tw-bg-opacity,1))!important}.bg-red-500\/25{background-color:rgba(239,68,68,.25)!important}.bg-red-500\/85{background-color:rgba(239,68,68,.85)!important}.bg-red-600{--tw-bg-opacity:1!important;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))!important}.bg-red-700\/70{background-color:rgba(185,28,28,.7)!important}.bg-red-900\/50{background-color:rgba(127,29,29,.5)!important}.bg-red-950\/30{background-color:rgba(69,10,10,.3)!important}.bg-sky-500{background-color:rgb(14 165 233/var(--tw-bg-opacity,1))!important}.bg-sky-500,.bg-slate-100{--tw-bg-opacity:1!important}.bg-slate-100{background-color:rgb(241 245 249/var(--tw-bg-opacity,1))!important}.bg-slate-50{--tw-bg-opacity:1!important;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))!important}.bg-slate-900{--tw-bg-opacity:1!important;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))!important}.bg-slate-900\/40{background-color:rgba(15,23,42,.4)!important}.bg-slate-950{--tw-bg-opacity:1!important;background-color:rgb(2 6 23/var(--tw-bg-opacity,1))!important}.bg-transparent{background-color:transparent!important}.bg-violet-100{--tw-bg-opacity:1!important;background-color:rgb(237 233 254/var(--tw-bg-opacity,1))!important}.bg-violet-400\/10{background-color:rgba(167,139,250,.1)!important}.bg-violet-50{--tw-bg-opacity:1!important;background-color:rgb(245 243 255/var(--tw-bg-opacity,1))!important}.bg-violet-500{--tw-bg-opacity:1!important;background-color:rgb(139 92 246/var(--tw-bg-opacity,1))!important}.bg-violet-600{--tw-bg-opacity:1!important;background-color:rgb(124 58 237/var(--tw-bg-opacity,1))!important}.bg-violet-600\/10{background-color:rgba(124,58,237,.1)!important}.bg-violet-700\/90{background-color:rgba(109,40,217,.9)!important}.bg-violet-900\/20{background-color:rgba(76,29,149,.2)!important}.bg-white{--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))!important}.bg-white\/10{background-color:hsla(0,0%,100%,.1)!important}.bg-white\/\[0\.06\]{background-color:hsla(0,0%,100%,.06)!important}.bg-zinc-500\/90{background-color:rgba(113,113,122,.9)!important}.bg-zinc-600{--tw-bg-opacity:1!important;background-color:rgb(82 82 91/var(--tw-bg-opacity,1))!important}.bg-zinc-600\/90{background-color:rgba(82,82,91,.9)!important}.bg-zinc-700\/55{background-color:rgba(63,63,70,.55)!important}.bg-zinc-700\/70{background-color:rgba(63,63,70,.7)!important}.bg-zinc-800{--tw-bg-opacity:1!important;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))!important}.bg-zinc-800\/80{background-color:rgba(39,39,42,.8)!important}.bg-zinc-800\/90{background-color:rgba(39,39,42,.9)!important}.bg-zinc-900{--tw-bg-opacity:1!important;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))!important}.bg-gradient-to-b{background-image:linear-gradient(180deg,var(--tw-gradient-stops))!important}.from-\[\#252038\]{--tw-gradient-from:#252038 var(--tw-gradient-from-position)!important;--tw-gradient-to:rgba(37,32,56,0) var(--tw-gradient-to-position)!important}.from-\[\#252038\],.from-slate-100{--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)!important}.from-slate-100{--tw-gradient-from:#f1f5f9 var(--tw-gradient-from-position)!important;--tw-gradient-to:rgba(241,245,249,0) var(--tw-gradient-to-position)!important}.from-violet-50{--tw-gradient-from:#f5f3ff var(--tw-gradient-from-position)!important;--tw-gradient-to:rgba(245,243,255,0) var(--tw-gradient-to-position)!important}.from-violet-50,.from-violet-950{--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)!important}.from-violet-950{--tw-gradient-from:#2e1065 var(--tw-gradient-from-position)!important;--tw-gradient-to:rgba(46,16,101,0) var(--tw-gradient-to-position)!important}.to-\[\#1a1628\]{--tw-gradient-to:#1a1628 var(--tw-gradient-to-position)!important}.to-\[\#1a1a22\]{--tw-gradient-to:#1a1a22 var(--tw-gradient-to-position)!important}.to-slate-50{--tw-gradient-to:#f8fafc var(--tw-gradient-to-position)!important}.to-white{--tw-gradient-to:#fff var(--tw-gradient-to-position)!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:.75rem!important}.p-4{padding:1rem!important}.p-5{padding:1.25rem!important}.p-6{padding:1.5rem!important}.px-0\.5{padding-left:.125rem!important;padding-right:.125rem!important}.px-1{padding-left:.25rem!important;padding-right:.25rem!important}.px-1\.5{padding-left:.375rem!important;padding-right:.375rem!important}.px-2{padding-left:.5rem!important;padding-right:.5rem!important}.px-2\.5{padding-left:.625rem!important;padding-right:.625rem!important}.px-3{padding-left:.75rem!important;padding-right:.75rem!important}.px-4{padding-left:1rem!important;padding-right:1rem!important}.px-5{padding-left:1.25rem!important;padding-right:1.25rem!important}.px-6{padding-left:1.5rem!important;padding-right:1.5rem!important}.py-0\.5{padding-top:.125rem!important;padding-bottom:.125rem!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-1\.5{padding-top:.375rem!important;padding-bottom:.375rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-2\.5{padding-top:.625rem!important;padding-bottom:.625rem!important}.py-3{padding-top:.75rem!important;padding-bottom:.75rem!important}.py-4{padding-top:1rem!important;padding-bottom:1rem!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pl-4{padding-left:1rem!important}.pr-11{padding-right:2.75rem!important}.pt-0\.5{padding-top:.125rem!important}.pt-1\.5{padding-top:.375rem!important}.pt-2{padding-top:.5rem!important}.text-left{text-align:left!important}.text-center{text-align:center!important}.text-right{text-align:right!important}.align-top{vertical-align:top!important}.text-2xl{font-size:1.5rem!important;line-height:2rem!important}.text-3xl{font-size:1.875rem!important;line-height:2.25rem!important}.text-\[10px\]{font-size:10px!important}.text-\[11px\]{font-size:11px!important}.text-\[13px\]{font-size:13px!important}.text-\[16px\]{font-size:16px!important}.text-\[20px\]{font-size:20px!important}.text-\[22px\]{font-size:22px!important}.text-base{font-size:1rem!important;line-height:1.5rem!important}.text-lg{font-size:1.125rem!important;line-height:1.75rem!important}.text-sm{font-size:.875rem!important;line-height:1.25rem!important}.text-xl{font-size:1.25rem!important;line-height:1.75rem!important}.text-xs{font-size:.75rem!important;line-height:1rem!important}.font-bold{font-weight:700!important}.font-medium{font-weight:500!important}.font-semibold{font-weight:600!important}.uppercase{text-transform:uppercase!important}.lowercase{text-transform:lowercase!important}.tabular-nums{--tw-numeric-spacing:tabular-nums!important;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)!important}.leading-none{line-height:1!important}.leading-snug{line-height:1.375!important}.leading-tight{line-height:1.25!important}.tracking-\[0\.14em\]{letter-spacing:.14em!important}.tracking-\[0\.24em\]{letter-spacing:.24em!important}.tracking-tight{letter-spacing:-.025em!important}.text-\[\#8f86a9\]{--tw-text-opacity:1!important;color:rgb(143 134 169/var(--tw-text-opacity,1))!important}.text-amber-300{--tw-text-opacity:1!important;color:rgb(252 211 77/var(--tw-text-opacity,1))!important}.text-amber-600{--tw-text-opacity:1!important;color:rgb(217 119 6/var(--tw-text-opacity,1))!important}.text-red-100{color:rgb(254 226 226/var(--tw-text-opacity,1))!important}.text-red-100,.text-red-300{--tw-text-opacity:1!important}.text-red-300{color:rgb(252 165 165/var(--tw-text-opacity,1))!important}.text-red-600{--tw-text-opacity:1!important;color:rgb(220 38 38/var(--tw-text-opacity,1))!important}.text-slate-100{--tw-text-opacity:1!important;color:rgb(241 245 249/var(--tw-text-opacity,1))!important}.text-slate-200{--tw-text-opacity:1!important;color:rgb(226 232 240/var(--tw-text-opacity,1))!important}.text-slate-300{--tw-text-opacity:1!important;color:rgb(203 213 225/var(--tw-text-opacity,1))!important}.text-slate-400{--tw-text-opacity:1!important;color:rgb(148 163 184/var(--tw-text-opacity,1))!important}.text-slate-500{--tw-text-opacity:1!important;color:rgb(100 116 139/var(--tw-text-opacity,1))!important}.text-slate-600{--tw-text-opacity:1!important;color:rgb(71 85 105/var(--tw-text-opacity,1))!important}.text-slate-700{--tw-text-opacity:1!important;color:rgb(51 65 85/var(--tw-text-opacity,1))!important}.text-slate-800{--tw-text-opacity:1!important;color:rgb(30 41 59/var(--tw-text-opacity,1))!important}.text-slate-900{--tw-text-opacity:1!important;color:rgb(15 23 42/var(--tw-text-opacity,1))!important}.text-violet-100{--tw-text-opacity:1!important;color:rgb(237 233 254/var(--tw-text-opacity,1))!important}.text-violet-200{--tw-text-opacity:1!important;color:rgb(221 214 254/var(--tw-text-opacity,1))!important}.text-violet-300{--tw-text-opacity:1!important;color:rgb(196 181 253/var(--tw-text-opacity,1))!important}.text-violet-50{--tw-text-opacity:1!important;color:rgb(245 243 255/var(--tw-text-opacity,1))!important}.text-violet-800{--tw-text-opacity:1!important;color:rgb(91 33 182/var(--tw-text-opacity,1))!important}.text-white{--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity,1))!important}.text-white\/90{color:hsla(0,0%,100%,.9)!important}.text-zinc-100{--tw-text-opacity:1!important;color:rgb(244 244 245/var(--tw-text-opacity,1))!important}.text-zinc-200{--tw-text-opacity:1!important;color:rgb(228 228 231/var(--tw-text-opacity,1))!important}.text-zinc-200\/90{color:rgba(228,228,231,.9)!important}.text-zinc-300{--tw-text-opacity:1!important;color:rgb(212 212 216/var(--tw-text-opacity,1))!important}.text-zinc-300\/80{color:rgba(212,212,216,.8)!important}.text-zinc-300\/90{color:rgba(212,212,216,.9)!important}.text-zinc-400{--tw-text-opacity:1!important;color:rgb(161 161 170/var(--tw-text-opacity,1))!important}.text-zinc-500{--tw-text-opacity:1!important;color:rgb(113 113 122/var(--tw-text-opacity,1))!important}.text-zinc-600{--tw-text-opacity:1!important;color:rgb(82 82 91/var(--tw-text-opacity,1))!important}.underline{text-decoration-line:underline!important}.opacity-60{opacity:.6!important}.opacity-80{opacity:.8!important}.opacity-85{opacity:.85!important}.opacity-90{opacity:.9!important}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px -1px rgba(0,0,0,0.1)!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)!important}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,0.25)!important;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)!important}.shadow-\[0_0_10px_rgba\(16\2c 185\2c 129\2c 0\.65\)\]{--tw-shadow:0 0 10px rgba(16,185,129,0.65)!important;--tw-shadow-colored:0 0 10px var(--tw-shadow-color)!important}.shadow-\[0_0_10px_rgba\(16\2c 185\2c 129\2c 0\.65\)\],.shadow-\[0_30px_80px_rgba\(15\2c 23\2c 42\2c 0\.16\)\]{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)!important}.shadow-\[0_30px_80px_rgba\(15\2c 23\2c 42\2c 0\.16\)\]{--tw-shadow:0 30px 80px rgba(15,23,42,0.16)!important;--tw-shadow-colored:0 30px 80px var(--tw-shadow-color)!important}.shadow-\[0_6px_12px_rgba\(0\2c 0\2c 0\2c 0\.08\)\]{--tw-shadow:0 6px 12px rgba(0,0,0,0.08)!important;--tw-shadow-colored:0 6px 12px var(--tw-shadow-color)!important}.shadow-\[0_6px_12px_rgba\(0\2c 0\2c 0\2c 0\.08\)\],.shadow-\[0_8px_16px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)!important}.shadow-\[0_8px_16px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{--tw-shadow:0 8px 16px rgba(0,0,0,0.06)!important;--tw-shadow-colored:0 8px 16px var(--tw-shadow-color)!important}.shadow-\[8px_0_16px_rgba\(0\2c 0\2c 0\2c 0\.06\)\]{--tw-shadow:8px 0 16px rgba(0,0,0,0.06)!important;--tw-shadow-colored:8px 0 16px var(--tw-shadow-color)!important}.shadow-\[8px_0_16px_rgba\(0\2c 0\2c 0\2c 0\.06\)\],.shadow-\[8px_0_16px_rgba\(0\2c 0\2c 0\2c 0\.08\)\]{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)!important}.shadow-\[8px_0_16px_rgba\(0\2c 0\2c 0\2c 0\.08\)\]{--tw-shadow:8px 0 16px rgba(0,0,0,0.08)!important;--tw-shadow-colored:8px 0 16px var(--tw-shadow-color)!important}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -4px rgba(0,0,0,0.1)!important;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)!important}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)!important}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,0.05)!important;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)!important}.shadow-black\/40{--tw-shadow-color:rgba(0,0,0,0.4)!important;--tw-shadow:var(--tw-shadow-colored)!important}.outline-none{outline:2px solid transparent!important;outline-offset:2px!important}.outline{outline-style:solid!important}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)!important}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)!important}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)!important}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)!important}.ring-inset{--tw-ring-inset:inset!important}.ring-red-400\/75{--tw-ring-color:rgba(248,113,113,0.75)!important}.ring-violet-400\/60{--tw-ring-color:rgba(167,139,250,0.6)!important}.ring-violet-400\/70{--tw-ring-color:rgba(167,139,250,0.7)!important}.ring-violet-400\/75{--tw-ring-color:rgba(167,139,250,0.75)!important}.ring-violet-500\/70{--tw-ring-color:rgba(139,92,246,0.7)!important}.ring-zinc-600\/40{--tw-ring-color:rgba(82,82,91,0.4)!important}.blur{--tw-blur:blur(8px)!important}.blur,.drop-shadow{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)!important}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,0.1)) drop-shadow(0 1px 1px rgba(0,0,0,0.06))!important}.grayscale-\[0\.15\]{--tw-grayscale:grayscale(0.15)!important}.grayscale-\[0\.2\],.grayscale-\[0\.15\]{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)!important}.grayscale-\[0\.2\]{--tw-grayscale:grayscale(0.2)!important}.invert{--tw-invert:invert(100%)!important}.\!filter,.filter,.invert{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)!important}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px)!important}.backdrop-blur-\[2px\],.backdrop-blur-sm{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)!important}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)!important}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px)!important}.backdrop-blur-xl,.backdrop-filter{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)!important}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-\[padding-right\]{transition-property:padding-right!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.transition-transform{transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important}.duration-200{transition-duration:.2s!important}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)!important}.\[color-scheme\:dark\]{color-scheme:dark!important}.\[color-scheme\:light\]{color-scheme:light!important}.last\:border-b-0:last-child{border-bottom-width:0!important}.hover\:bg-slate-100:hover{--tw-bg-opacity:1!important;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))!important}.hover\:bg-slate-50:hover{--tw-bg-opacity:1!important;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))!important}.hover\:bg-slate-800:hover{--tw-bg-opacity:1!important;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))!important}.active\:bg-white\/\[0\.07\]:active{background-color:hsla(0,0%,100%,.07)!important}.disabled\:opacity-50:disabled{opacity:.5!important}@media (min-width:640px){.sm\:flex-row{flex-direction:row!important}.sm\:items-center{align-items:center!important}.sm\:px-2{padding-left:.5rem!important;padding-right:.5rem!important}.sm\:px-4{padding-left:1rem!important;padding-right:1rem!important}.sm\:py-3{padding-top:.75rem!important;padding-bottom:.75rem!important}.sm\:text-\[11px\]{font-size:11px!important}}@media (min-width:768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))!important}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))!important}.md\:items-center{align-items:center!important}.md\:rounded-3xl{border-radius:1.5rem!important}.md\:p-4{padding:1rem!important}.md\:p-6{padding:1.5rem!important}.md\:p-8{padding:2rem!important}.md\:px-6{padding-left:1.5rem!important;padding-right:1.5rem!important}}.\[\&\:\:-webkit-calendar-picker-indicator\]\:ml-auto::-webkit-calendar-picker-indicator{margin-left:auto!important}.\[\&\:\:-webkit-calendar-picker-indicator\]\:mr-1::-webkit-calendar-picker-indicator{margin-right:.25rem!important}
@@ -1,11 +1,13 @@
1
1
  const require_runtime = require("../../_virtual/_rolldown/runtime.js");
2
2
  const require_objectSpread2 = require("../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js");
3
+ const require_objectWithoutProperties = require("../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectWithoutProperties.js");
3
4
  const require_index = require("../button/index.js");
4
5
  let react = require("react");
5
6
  react = require_runtime.__toESM(react);
6
7
  let antd = require("antd");
7
8
  let _ant_design_icons = require("@ant-design/icons");
8
9
  //#region src/components/buttonGroupPreview/index.tsx
10
+ const _excluded = ["children"];
9
11
  /**
10
12
  *
11
13
  * @param param0 { buttonConfig, buttonGroupList }
@@ -14,7 +16,7 @@ let _ant_design_icons = require("@ant-design/icons");
14
16
  const updateSourceData = ({ buttonConfig, buttonGroupList }) => {
15
17
  if (Object.keys(buttonConfig).length !== 0) return buttonGroupList.map((subArray) => {
16
18
  return subArray.map((item) => {
17
- if (buttonConfig.hasOwnProperty(item.id)) return buttonConfig[item.id];
19
+ if (item.id && Object.prototype.hasOwnProperty.call(buttonConfig, item.id)) return buttonConfig[item.id];
18
20
  return item;
19
21
  });
20
22
  });
@@ -29,13 +31,15 @@ const ButtonGroupPreview = (0, react.forwardRef)((props, ref) => {
29
31
  });
30
32
  }, [buttonGroupList, buttonConfig]);
31
33
  return /* @__PURE__ */ react.default.createElement(antd.Flex, {
32
- wrap: true,
34
+ wrap: "wrap",
33
35
  vertical: true,
34
36
  style: { marginBottom: 10 }
35
- }, sourceDatas.map((item, index) => /* @__PURE__ */ react.default.createElement(antd.Space, { key: index }, item.map((items, index) => {
37
+ }, sourceDatas.map((item, index) => react.default.createElement(antd.Space, { key: index }, item.map((items, index) => {
36
38
  const { isMore = false, id = "", menuData = [], buttonProps } = items;
37
39
  const btnProps = require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, buttonProps), props.updateButtonProps);
38
- return isMore ? /* @__PURE__ */ react.default.createElement(antd.Dropdown, { menu: { items: menuData } }, /* @__PURE__ */ react.default.createElement(require_index.default, null, /* @__PURE__ */ react.default.createElement(_ant_design_icons.MoreOutlined, null))) : /* @__PURE__ */ react.default.createElement(require_index.default, require_objectSpread2._objectSpread2({ key: id }, btnProps));
40
+ const { children } = btnProps, dropdownButtonProps = require_objectWithoutProperties._objectWithoutProperties(btnProps, _excluded);
41
+ const moreButtonChildren = children !== null && children !== void 0 ? children : dropdownButtonProps.icon ? null : /* @__PURE__ */ react.default.createElement(_ant_design_icons.MoreOutlined, null);
42
+ return isMore ? /* @__PURE__ */ react.default.createElement(antd.Dropdown, { menu: { items: menuData } }, /* @__PURE__ */ react.default.createElement(require_index.default, require_objectSpread2._objectSpread2({ key: id }, dropdownButtonProps), moreButtonChildren)) : /* @__PURE__ */ react.default.createElement(require_index.default, require_objectSpread2._objectSpread2({ key: id }, btnProps));
39
43
  }))));
40
44
  });
41
45
  var buttonGroupPreview_default = (0, react.memo)(ButtonGroupPreview);
@@ -14,8 +14,13 @@ const require_FloorMapEditTopBar = require("./components/FloorMapEditTopBar.js")
14
14
  const require_mergeCanvasesForTabs = require("./utils/mergeCanvasesForTabs.js");
15
15
  const require_FloorMapOverview = require("./components/FloorMapOverview.js");
16
16
  const require_FloorMapEditPanel = require("./components/FloorMapEditPanel.js");
17
- const require_ViewControlsWithZoom = require("./components/ViewControlsWithZoom.js");
18
17
  const require_layoutMeasurements = require("./utils/layoutMeasurements.js");
18
+ const require_FloorMapEdgeEditPanel = require("./components/FloorMapEdgeEditPanel.js");
19
+ const require_EdgeLayer = require("./components/EdgeLayer.js");
20
+ const require_NodePortMarkers = require("./components/NodePortMarkers.js");
21
+ const require_useFloorMapEdgeViewModel = require("./hooks/useFloorMapEdgeViewModel.js");
22
+ const require_useFloorMapEdgeEditing = require("./hooks/useFloorMapEdgeEditing.js");
23
+ const require_ViewControlsWithZoom = require("./components/ViewControlsWithZoom.js");
19
24
  const require_useFloorMapEditState = require("./hooks/useFloorMapEditState.js");
20
25
  const require_useFloorMapTransformMetrics = require("./hooks/useFloorMapTransformMetrics.js");
21
26
  const require_floorMapFallbackRender = require("./utils/floorMapFallbackRender.js");
@@ -42,8 +47,8 @@ require("./PisellFloorMapLayout.less");
42
47
  * 负责:上下文与 props 合并、编辑态/阅读态分支、Transform 视口、图元层与工具栏联动。
43
48
  */
44
49
  function PisellFloorMapLayoutInner(props, ref) {
45
- var _ref, _currentCanvas$mapLay2, _currentCanvas$mapLay3, _mapLayer$backgroundC, _engineCtx$engine, _mapLayer$boundingPad, _config$sceneElements;
46
- const { className, style, items: itemsProp, renderItem, rowKey, renderItemByKind, getMergedItemWrapperStyle, mapLayer, cellSize: cellSizeProp, itemUnit = "cell", zoom = {}, pan = {}, controls = {}, enableHover = true, readModeSelectedItemId, onItemClick, onItemHover, onItemLeave, mode = "read", floorMapConfig: floorMapConfigProp, dataSources, onSave, onExitEdit, onDataSourceRecordSave, dataSourceLabels, dataSourceFormColumns, dataSourceRecordForm, loading, saveError, onElementRenderError, toolbarShowSave = true, floorMapFullscreenMode, appearanceMode = "light", showDataSourceRecordFormBlock, floorMapViewportOverlay, viewportOverlayPlacement = "top-start", viewportOverlayClassName, editTopBarPhoneLayout = false, canvasTabsBarTrailing, viewportDockToolButtons, viewportDockTrailing, viewportPersist = true, viewportPersistNamespace } = require_mergeFloorMapLayoutContext.mergeFloorMapLayoutPropsFromContext(props, require_FloorMapLayoutContext.useFloorMapLayoutContext());
50
+ var _ref, _currentCanvas$mapLay2, _currentCanvas$mapLay3, _mapLayer$backgroundC, _engineCtx$engine, _mapLayer$boundingPad, _config$edges, _config$edges2, _config$sceneElements;
51
+ const { className, style, items: itemsProp, renderItem, rowKey, renderItemByKind, getMergedItemWrapperStyle, enableEdges = false, mapLayer, cellSize: cellSizeProp, itemUnit = "cell", zoom = {}, pan = {}, controls = {}, enableHover = true, readModeSelectedItemId, onItemClick, onItemHover, onItemLeave, mode = "read", floorMapConfig: floorMapConfigProp, dataSources, onSave, onExitEdit, onDataSourceRecordSave, dataSourceLabels, dataSourceFormColumns, dataSourceRecordForm, loading, saveError, onElementRenderError, toolbarShowSave = true, renderResourcePickerModal, paletteSidebarVisibleLimit, floorMapFullscreenMode, appearanceMode = "light", showDataSourceRecordFormBlock, floorMapViewportOverlay, viewportOverlayPlacement = "top-start", viewportOverlayClassName, editTopBarPhoneLayout = false, canvasTabsBarTrailing, viewportDockToolButtons, viewportDockTrailing, viewportPersist = true, viewportPersistNamespace } = require_mergeFloorMapLayoutContext.mergeFloorMapLayoutPropsFromContext(props, require_FloorMapLayoutContext.useFloorMapLayoutContext());
47
52
  const { token } = antd.theme.useToken();
48
53
  const isFloorMapView = Boolean(floorMapConfigProp);
49
54
  const contentOffsetRef = (0, react.useRef)({
@@ -52,7 +57,8 @@ function PisellFloorMapLayoutInner(props, ref) {
52
57
  });
53
58
  const mapDropLayerRef = (0, react.useRef)(null);
54
59
  const transformRef = (0, react.useRef)(null);
55
- const { config, currentCanvasId, setCurrentCanvasId, selectedId, setSelectedId, placeMode, setPlaceMode, items, saving, savingRecord, handleAddCanvas, handleRemoveCanvas, handleRenameCanvas, handleUpdateItem, handleCanvasPlaceClick, handleSave, placeSceneElementFromPaletteDrop, editPanelParams, placeOverlayClass, isLayoutDirty, toggleDraftCanvasShowGrid, toggleSelectedLayoutLock, duplicateSelectedElement, deleteSelectedElement, undoDraft, redoDraft, canUndo, canRedo, discardDraft } = require_useFloorMapEditState.useFloorMapEditState({
60
+ const focusViewportOnBoundsRef = (0, react.useRef)(null);
61
+ const { config, currentCanvasId, setCurrentCanvasId, selectedId, setSelectedId, placeMode, setPlaceMode, items, saving, savingRecord, handleAddCanvas, handleRemoveCanvas, handleRenameCanvas, handleUpdateItem, handleCanvasPlaceClick, handleSave, placeSceneElementFromPaletteDrop, bulkPlacePaletteItems, editPanelParams, placeOverlayClass, isLayoutDirty, toggleDraftCanvasShowGrid, toggleSelectedLayoutLock, duplicateSelectedElement, deleteSelectedElement, undoDraft, redoDraft, canUndo, canRedo, discardDraft, commitDraft } = require_useFloorMapEditState.useFloorMapEditState({
56
62
  floorMapConfigProp,
57
63
  isFloorMapView,
58
64
  itemsProp,
@@ -65,8 +71,10 @@ function PisellFloorMapLayoutInner(props, ref) {
65
71
  dataSourceLabels,
66
72
  layoutPrefix: require_floorMapLayoutConstants.FLOOR_MAP_LAYOUT_CLASS_PREFIX,
67
73
  contentOffsetRef,
68
- showDataSourceRecordFormBlock
74
+ showDataSourceRecordFormBlock,
75
+ focusViewportOnBoundsRef
69
76
  });
77
+ const mapContentRef = (0, react.useRef)(null);
70
78
  /**
71
79
  * 当前选中的画布配置:用于提取当前画布级 mapLayer 显式配置。
72
80
  */
@@ -149,25 +157,26 @@ function PisellFloorMapLayoutInner(props, ref) {
149
157
  const engineLocale = (engineCtx === null || engineCtx === void 0 || (_engineCtx$engine = engineCtx.engine) === null || _engineCtx$engine === void 0 || (_engineCtx$engine = _engineCtx$engine.props) === null || _engineCtx$engine === void 0 ? void 0 : _engineCtx$engine.locale) || "zh-CN";
150
158
  const hasCanvasTabsBarTrailing = canvasTabsBarTrailing != null && canvasTabsBarTrailing !== false;
151
159
  const enabledCanvasCount = (0, react.useMemo)(() => canvasesForTabsBase.filter((c) => c.enabled).length, [canvasesForTabsBase]);
152
- /** 仅阅读态、启用画布 > 1 时,在 Tab 列表最前插入「All」伪 tab */
160
+ /** 仅阅读态、启用画布 > 1 时,在 Tab 列表末尾插入「Overview」伪 tab */
153
161
  const showOverviewTab = isFloorMapView && mode === "read" && enabledCanvasCount > 1;
154
162
  const overviewTabLabel = (0, react.useMemo)(() => {
155
163
  require_floorMapCanvasDisplay.initFloorMapLayoutLocales(engineLocale);
156
164
  return _pisell_utils.locales.getText("pisell-floor-map-layout.canvas-tabs.overview");
157
165
  }, [engineLocale]);
158
166
  /**
159
- * 给 CanvasTabs 渲染用的最终列表:阅读态多画布时在列表最前插入「All」伪 tab。
160
- * order 取当前最小 order - 1,保证排序后位于第一个;其它字段留空。
167
+ * 给 CanvasTabs 渲染用的最终列表:阅读态多画布时在列表末尾插入「Overview」伪 tab。
168
+ * order 取当前最大 order + 1,保证排序后位于最后一个。
161
169
  */
162
170
  const canvasesForTabs = (0, react.useMemo)(() => {
163
171
  if (!showOverviewTab) return canvasesForTabsBase;
164
- const minOrder = canvasesForTabsBase.reduce((min, c) => c.order < min ? c.order : min, Number.POSITIVE_INFINITY);
165
- return [{
172
+ const maxOrder = canvasesForTabsBase.reduce((max, c) => c.order > max ? c.order : max, Number.NEGATIVE_INFINITY);
173
+ const overviewTab = {
166
174
  id: require_floorMapLayoutConstants.FLOOR_MAP_OVERVIEW_TAB_ID,
167
175
  name: overviewTabLabel,
168
- order: Number.isFinite(minOrder) ? minOrder - 1 : -1,
176
+ order: Number.isFinite(maxOrder) ? maxOrder + 1 : 0,
169
177
  enabled: true
170
- }, ...canvasesForTabsBase];
178
+ };
179
+ return [...canvasesForTabsBase, overviewTab];
171
180
  }, [
172
181
  canvasesForTabsBase,
173
182
  showOverviewTab,
@@ -260,7 +269,7 @@ function PisellFloorMapLayoutInner(props, ref) {
260
269
  globalMapLayer: mapLayer,
261
270
  cellSize,
262
271
  itemUnit: effectiveItemUnit,
263
- areaGap: 32
272
+ areaGap: 40
264
273
  });
265
274
  }, [
266
275
  isFloorMapView,
@@ -308,7 +317,7 @@ function PisellFloorMapLayoutInner(props, ref) {
308
317
  shape: "rect"
309
318
  }];
310
319
  }, [overviewLayout]);
311
- const { containerRef, mapAreaRef, mapAreaSize, contentWidth, contentHeight, contentOffsetX, contentOffsetY, initialPositionX, initialPositionY, zoomConfig, scale, setScale, isFullscreen, toggleFullscreen, fitBounds, isAtFitBounds, notifyTransformed, persistCurrentViewport, attachTransformContext, isInteractingWithElement, setIsInteractingWithElement, viewportLocked, toggleViewportLocked } = require_useFloorMapTransformMetrics.useFloorMapTransformMetrics({
320
+ const { containerRef, mapAreaRef, mapAreaSize, contentWidth, contentHeight, contentOffsetX, contentOffsetY, initialPositionX, initialPositionY, zoomConfig, scale, setScale, isFullscreen, toggleFullscreen, fitBounds, focusContentBounds, isAtFitBounds, notifyTransformed, persistCurrentViewport, attachTransformContext, isInteractingWithElement, setIsInteractingWithElement, viewportLocked, toggleViewportLocked } = require_useFloorMapTransformMetrics.useFloorMapTransformMetrics({
312
321
  items: isOverview && overviewLayout ? overviewMetricsItems : items,
313
322
  cellSize,
314
323
  itemGap: isOverview ? 0 : itemGap,
@@ -322,20 +331,81 @@ function PisellFloorMapLayoutInner(props, ref) {
322
331
  frameResetKey: isFloorMapView ? transformWrapperKey : void 0,
323
332
  viewportPersistKey
324
333
  });
325
- /** 手机:选中图元种类后一键落在当前视口中心(与点击画布落点坐标换算一致) */
326
- const handlePlaceActiveAtViewportCenter = (0, react.useCallback)(() => {
327
- if (!placeMode || placeMode.type !== "scene") return;
334
+ (0, react.useEffect)(() => {
335
+ focusViewportOnBoundsRef.current = (bounds) => {
336
+ requestAnimationFrame(() => {
337
+ requestAnimationFrame(() => {
338
+ focusContentBounds(bounds);
339
+ });
340
+ });
341
+ };
342
+ return () => {
343
+ focusViewportOnBoundsRef.current = null;
344
+ };
345
+ }, [focusContentBounds]);
346
+ /**
347
+ * 是否启用连线(edge)渲染与编辑能力。
348
+ * - 必须显式 `enableEdges={true}` 才打开;
349
+ * - pisell-reservation 等通用业务画布默认关闭,避免选中图元出现锚点圆点或拖出连线。
350
+ */
351
+ const showEdgeLayer = enableEdges && isFloorMapView && !isOverview && config != null;
352
+ /** 连线层显隐(仅影响 EdgeLayer 绘制;编辑锚点仍随 `showEdgeLayer`) */
353
+ const [edgesLayerVisible, setEdgesLayerVisible] = (0, react.useState)(true);
354
+ const showEdgesOnCanvas = showEdgeLayer && edgesLayerVisible;
355
+ const toggleEdgesLayerVisible = (0, react.useCallback)(() => {
356
+ setEdgesLayerVisible((v) => !v);
357
+ }, []);
358
+ const readEdgeVm = require_useFloorMapEdgeViewModel.useFloorMapEdgeViewModel({
359
+ edges: showEdgeLayer && mode === "read" ? (_config$edges = config === null || config === void 0 ? void 0 : config.edges) !== null && _config$edges !== void 0 ? _config$edges : [] : [],
360
+ items: showEdgeLayer ? items : [],
361
+ cellSize,
362
+ itemUnit: effectiveItemUnit,
363
+ itemGap
364
+ });
365
+ const edgeEdit = require_useFloorMapEdgeEditing.useFloorMapEdgeEditing({
366
+ enabled: showEdgeLayer && mode === "edit",
367
+ config,
368
+ items,
369
+ mergedItems: items,
370
+ cellSize,
371
+ itemUnit: effectiveItemUnit,
372
+ itemGap,
373
+ contentOffsetRef,
374
+ selectedId,
375
+ setSelectedId,
376
+ commitDraft,
377
+ mapContentRef,
378
+ scale
379
+ });
380
+ const edgeRoutes = mode === "edit" && showEdgeLayer ? edgeEdit.routes : readEdgeVm.routes;
381
+ const edgeRectsById = mode === "edit" && showEdgeLayer ? edgeEdit.rectsById : readEdgeVm.rectsById;
382
+ const displayEdges = mode === "edit" && showEdgeLayer ? edgeEdit.edges : (_config$edges2 = config === null || config === void 0 ? void 0 : config.edges) !== null && _config$edges2 !== void 0 ? _config$edges2 : [];
383
+ const getViewportCenterContentCoords = (0, react.useCallback)(() => {
328
384
  const w = mapAreaSize.width;
329
385
  const h = mapAreaSize.height;
330
- if (w <= 0 || h <= 0) return;
386
+ if (w <= 0 || h <= 0) return null;
331
387
  const { x: ox, y: oy } = contentOffsetRef.current;
332
- placeSceneElementFromPaletteDrop(Math.round(w / 2 - ox), Math.round(h / 2 - oy), placeMode);
388
+ return {
389
+ x: Math.round(w / 2 - ox),
390
+ y: Math.round(h / 2 - oy)
391
+ };
392
+ }, [mapAreaSize.width, mapAreaSize.height]);
393
+ /** 手机:选中图元种类后一键落在当前视口中心(与点击画布落点坐标换算一致) */
394
+ const handlePlaceActiveAtViewportCenter = (0, react.useCallback)(() => {
395
+ if (!placeMode || placeMode.type !== "scene") return;
396
+ const center = getViewportCenterContentCoords();
397
+ if (!center) return;
398
+ placeSceneElementFromPaletteDrop(center.x, center.y, placeMode);
333
399
  }, [
334
400
  placeMode,
335
- mapAreaSize.width,
336
- mapAreaSize.height,
401
+ getViewportCenterContentCoords,
337
402
  placeSceneElementFromPaletteDrop
338
403
  ]);
404
+ /** 侧栏「查看更多」:按数量批量落在画布右侧空白区(方阵网格 + gap) */
405
+ const handleBulkAddPaletteToCanvas = (0, react.useCallback)((items) => {
406
+ if (!items.length) return;
407
+ bulkPlacePaletteItems(items);
408
+ }, [bulkPlacePaletteItems]);
339
409
  /** 编辑态全屏策略:toggle 全屏与编辑态强绑定;locked 始终全屏顶栏;disabled 无全屏 */
340
410
  const fsMode = floorMapFullscreenMode !== null && floorMapFullscreenMode !== void 0 ? floorMapFullscreenMode : "toggle";
341
411
  const useFullTopChrome = isFloorMapView && mode === "edit" && (fsMode === "locked" || fsMode === "toggle" && isFullscreen);
@@ -372,16 +442,18 @@ function PisellFloorMapLayoutInner(props, ref) {
372
442
  * 并默认带出「视口锁定」按钮(与是否将视口保存到本地解耦;无持久化 key 时仅内存态,默认未锁定)。
373
443
  */
374
444
  const viewControlsConfig = (0, react.useMemo)(() => {
375
- var _controls$showFullscr, _controls$showViewpor;
445
+ var _controls$showFullscr, _controls$showViewpor, _controls$showEdgesTo;
376
446
  if (!isFloorMapView) return controls;
377
447
  return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, controls), {}, {
378
448
  showFullscreen: (_controls$showFullscr = controls.showFullscreen) !== null && _controls$showFullscr !== void 0 ? _controls$showFullscr : Boolean(dockToggleFullscreen),
379
- showViewportLock: (_controls$showViewpor = controls.showViewportLock) !== null && _controls$showViewpor !== void 0 ? _controls$showViewpor : true
449
+ showViewportLock: (_controls$showViewpor = controls.showViewportLock) !== null && _controls$showViewpor !== void 0 ? _controls$showViewpor : true,
450
+ showEdgesToggle: showEdgeLayer ? (_controls$showEdgesTo = controls.showEdgesToggle) !== null && _controls$showEdgesTo !== void 0 ? _controls$showEdgesTo : true : controls.showEdgesToggle
380
451
  });
381
452
  }, [
382
453
  isFloorMapView,
383
454
  controls,
384
- dockToggleFullscreen
455
+ dockToggleFullscreen,
456
+ showEdgeLayer
385
457
  ]);
386
458
  const topBarExtraActions = null;
387
459
  /** 从侧栏/调色板拖入画布时,地图区高亮态(用于 dragleave/over 判定) */
@@ -547,8 +619,17 @@ function PisellFloorMapLayoutInner(props, ref) {
547
619
  return (_transformRef$current3 = transformRef.current) === null || _transformRef$current3 === void 0 ? void 0 : _transformRef$current3.resetTransform();
548
620
  },
549
621
  fitBounds,
550
- saveLayout: () => handleSave()
551
- }), [fitBounds, handleSave]);
622
+ saveLayout: () => handleSave(),
623
+ applySceneSnapshot: (next) => {
624
+ if (mode !== "edit") return;
625
+ commitDraft(() => next);
626
+ }
627
+ }), [
628
+ fitBounds,
629
+ handleSave,
630
+ mode,
631
+ commitDraft
632
+ ]);
552
633
  const showSidebar = isFloorMapView && mode === "edit" && config && dataSources;
553
634
  /** 右侧属性面板打开时给画布区留空,避免落点被挡在面板下 */
554
635
  const editPanelVisible = isFloorMapView && mode === "edit" && Boolean(editPanelParams) && Boolean(config) && Boolean(dataSources);
@@ -687,8 +768,8 @@ function PisellFloorMapLayoutInner(props, ref) {
687
768
  sceneElements: (_config$sceneElements = config.sceneElements) !== null && _config$sceneElements !== void 0 ? _config$sceneElements : [],
688
769
  renderPreviewItem: (item) => effectiveRenderItem(item, 0),
689
770
  placementPreviewSize: {
690
- width: 180,
691
- height: 120
771
+ width: require_floorMapElementKindUtils.FLOOR_MAP_RESOURCE_PLACE_DEFAULT.width,
772
+ height: require_floorMapElementKindUtils.FLOOR_MAP_RESOURCE_PLACE_DEFAULT.height
692
773
  },
693
774
  decorationPreviewSize: 48,
694
775
  onSave: onSave && config.canvasUi.canEdit && !useFullTopChrome && toolbarShowSave !== false ? handleSave : void 0,
@@ -699,7 +780,16 @@ function PisellFloorMapLayoutInner(props, ref) {
699
780
  consumeToolbarClickIfTouchDrag: paletteTouchDrag.consumeToolbarClickIfTouchDrag,
700
781
  phoneLayout: editTopBarPhoneLayout,
701
782
  defaultCollapsed: editTopBarPhoneLayout,
702
- onRequestPlaceAtCanvasCenter: editTopBarPhoneLayout ? handlePlaceActiveAtViewportCenter : void 0
783
+ paletteSidebarVisibleLimit,
784
+ onRequestPlaceAtCanvasCenter: editTopBarPhoneLayout ? handlePlaceActiveAtViewportCenter : void 0,
785
+ onBulkAddPaletteToCanvas: handleBulkAddPaletteToCanvas,
786
+ onDirectPlacePaletteItem: (item) => bulkPlacePaletteItems([item]),
787
+ onResourcePickerConfirmPlace: (scene) => {
788
+ const center = getViewportCenterContentCoords();
789
+ if (!center) return false;
790
+ return placeSceneElementFromPaletteDrop(center.x, center.y, scene);
791
+ },
792
+ renderResourcePickerModal
703
793
  }), /* @__PURE__ */ react.default.createElement("div", {
704
794
  ref: mapAreaRef,
705
795
  className: (0, classnames.default)(showSidebar && `pisell-floor-map-layout-map-area`, editTopBarPhoneLayout && showSidebar && `pisell-floor-map-layout-map-area--phone-fill`, editPanelVisible && !editTopBarPhoneLayout && `pisell-floor-map-layout-map-area--edit-panel-inset`),
@@ -769,7 +859,7 @@ function PisellFloorMapLayoutInner(props, ref) {
769
859
  onPinchingStop: persistCurrentViewport,
770
860
  onWheelStop: persistCurrentViewport
771
861
  }), (ctx) => {
772
- var _effectiveMapLayer$sn;
862
+ var _effectiveMapLayer$sn, _edgeEdit$drawing;
773
863
  /**
774
864
  * 不直接 transformRef.current = ctx:
775
865
  * attachTransformContext 内部会比对 ctx 实例并在每次 wrapper 重挂载时
@@ -820,14 +910,37 @@ function PisellFloorMapLayoutInner(props, ref) {
820
910
  getMergedItemWrapperStyle,
821
911
  readModeSelectedItemId
822
912
  })
823
- ) : /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement(require_MapLayer.default, {
913
+ ) : /* @__PURE__ */ react.default.createElement("div", {
914
+ ref: mapContentRef,
915
+ className: `${require_floorMapLayoutConstants.FLOOR_MAP_LAYOUT_CLASS_PREFIX}-map-content`,
916
+ style: {
917
+ position: "relative",
918
+ width: contentWidth,
919
+ height: contentHeight
920
+ }
921
+ }, /* @__PURE__ */ react.default.createElement(require_MapLayer.default, {
824
922
  config: effectiveMapLayer,
825
923
  contentWidth,
826
924
  contentHeight,
827
925
  cellSize,
828
926
  preferCanvasGrid: true,
829
927
  pointerEventsNone: isFloorMapView && mode === "edit"
830
- }), isFloorMapView && mode === "edit" ? /* @__PURE__ */ react.default.createElement(require_EditableItemLayer.default, {
928
+ }), showEdgesOnCanvas ? /* @__PURE__ */ react.default.createElement(require_EdgeLayer.EdgeLayer, {
929
+ width: contentWidth,
930
+ height: contentHeight,
931
+ contentOffsetX,
932
+ contentOffsetY,
933
+ edges: displayEdges,
934
+ routes: edgeRoutes,
935
+ rectsById: edgeRectsById,
936
+ appearance: appearanceTokens,
937
+ mode,
938
+ selectedEdgeId: mode === "edit" ? edgeEdit.selectedEdgeId : null,
939
+ ghostPathD: mode === "edit" ? edgeEdit.ghostPathD : null,
940
+ onEdgeClick: mode === "edit" ? (edgeId) => edgeEdit.handleEdgeClick(edgeId) : void 0,
941
+ viewportScale: scale,
942
+ onSegmentDragStart: mode === "edit" ? edgeEdit.startDraggingSegment : void 0
943
+ }) : null, isFloorMapView && mode === "edit" ? /* @__PURE__ */ react.default.createElement(require_EditableItemLayer.default, {
831
944
  items,
832
945
  renderItem: effectiveRenderItem,
833
946
  rowKey,
@@ -839,11 +952,24 @@ function PisellFloorMapLayoutInner(props, ref) {
839
952
  contentOffsetX,
840
953
  contentOffsetY,
841
954
  selectedId,
842
- onSelect: setSelectedId,
955
+ onSelect: edgeEdit.selectNode,
843
956
  onUpdateItem: handleUpdateItem,
844
957
  snapStep: (_effectiveMapLayer$sn = effectiveMapLayer === null || effectiveMapLayer === void 0 ? void 0 : effectiveMapLayer.snapStep) !== null && _effectiveMapLayer$sn !== void 0 ? _effectiveMapLayer$sn : 0,
845
958
  scale,
846
959
  onInteractionChange: setIsInteractingWithElement,
960
+ onLiveRectChange: (itemId, rect) => {
961
+ if (!itemId || !rect) {
962
+ edgeEdit.setPendingRectsById({});
963
+ return;
964
+ }
965
+ edgeEdit.setPendingRectsById({ [itemId]: {
966
+ left: rect.left,
967
+ top: rect.top,
968
+ width: rect.width,
969
+ height: rect.height
970
+ } });
971
+ },
972
+ alignGuideStroke: appearanceTokens.alignGuideStroke,
847
973
  getMergedItemWrapperStyle,
848
974
  editQuickBar
849
975
  }) : /* @__PURE__ */ react.default.createElement(require_ItemLayer.default, {
@@ -866,7 +992,24 @@ function PisellFloorMapLayoutInner(props, ref) {
866
992
  getMergedItemWrapperStyle,
867
993
  onInteractionChange: setIsInteractingWithElement,
868
994
  readModeSelectedItemId
869
- }), isFloorMapView && mode === "edit" && (placeMode === null || placeMode === void 0 ? void 0 : placeMode.type) === "scene" && /* @__PURE__ */ react.default.createElement("div", {
995
+ }), isFloorMapView && mode === "edit" && showEdgeLayer && selectedId && edgeEdit.selectedNodeRect ? /* @__PURE__ */ react.default.createElement(require_NodePortMarkers.NodePortMarkers, {
996
+ rect: edgeEdit.selectedNodeRect,
997
+ contentOffsetX,
998
+ contentOffsetY,
999
+ viewportScale: scale,
1000
+ highlightAnchors: ((_edgeEdit$drawing = edgeEdit.drawing) === null || _edgeEdit$drawing === void 0 ? void 0 : _edgeEdit$drawing.fromInstanceId) === selectedId ? [edgeEdit.drawing.fromAnchor] : [],
1001
+ onAnchorPointerDown: (anchor) => {
1002
+ if (selectedId) edgeEdit.startDrawingFromAnchor(selectedId, anchor);
1003
+ }
1004
+ }) : null, isFloorMapView && mode === "edit" && showEdgeLayer && edgeEdit.drawing && edgeEdit.drawingTargetPreview ? /* @__PURE__ */ react.default.createElement(require_NodePortMarkers.NodePortMarkers, {
1005
+ className: `${require_floorMapLayoutConstants.FLOOR_MAP_LAYOUT_CLASS_PREFIX}-port-markers--draw-target`,
1006
+ rect: edgeEdit.drawingTargetPreview.rect,
1007
+ contentOffsetX,
1008
+ contentOffsetY,
1009
+ viewportScale: scale,
1010
+ previewOnly: true,
1011
+ highlightAnchors: [edgeEdit.drawingTargetPreview.anchor]
1012
+ }) : null, isFloorMapView && mode === "edit" && (placeMode === null || placeMode === void 0 ? void 0 : placeMode.type) === "scene" && /* @__PURE__ */ react.default.createElement("div", {
870
1013
  className: placeOverlayClass,
871
1014
  style: {
872
1015
  width: contentWidth,
@@ -884,7 +1027,11 @@ function PisellFloorMapLayoutInner(props, ref) {
884
1027
  ev.preventDefault();
885
1028
  ev.stopPropagation();
886
1029
  },
887
- onDrop: handlePaletteDropOnCanvas
1030
+ onDrop: handlePaletteDropOnCanvas,
1031
+ onClick: () => {
1032
+ if ((placeMode === null || placeMode === void 0 ? void 0 : placeMode.type) === "scene") return;
1033
+ edgeEdit.handleMapBackgroundClick();
1034
+ }
888
1035
  }))), /* @__PURE__ */ react.default.createElement(require_ViewControlsWithZoom.ViewControlsWithZoom, {
889
1036
  config: viewControlsConfig,
890
1037
  scale,
@@ -894,6 +1041,8 @@ function PisellFloorMapLayoutInner(props, ref) {
894
1041
  toggleFullscreen: dockToggleFullscreen,
895
1042
  mapGridVisible: isOverview ? false : Boolean(effectiveMapLayer === null || effectiveMapLayer === void 0 ? void 0 : effectiveMapLayer.showGrid),
896
1043
  onToggleMapGrid: isFloorMapView && !isOverview ? toggleDraftCanvasShowGrid : void 0,
1044
+ edgesLayerVisible,
1045
+ onToggleEdgesLayer: showEdgeLayer ? toggleEdgesLayerVisible : void 0,
897
1046
  viewportLocked,
898
1047
  onToggleViewportLock: isFloorMapView ? toggleViewportLocked : void 0,
899
1048
  dockChrome: isFloorMapView,
@@ -905,21 +1054,22 @@ function PisellFloorMapLayoutInner(props, ref) {
905
1054
  dataSources,
906
1055
  currentCanvasId,
907
1056
  mode
908
- }) : floorMapViewportOverlay) : null, isFloorMapView && mode === "edit" && editPanelParams && config && dataSources && !editTopBarPhoneLayout && /* @__PURE__ */ react.default.createElement("div", {
1057
+ }) : floorMapViewportOverlay) : null, isFloorMapView && mode === "edit" && config && dataSources && !editTopBarPhoneLayout && (edgeEdit.selectedEdge || editPanelParams) && /* @__PURE__ */ react.default.createElement("div", {
909
1058
  className: (0, classnames.default)(`pisell-floor-map-layout-edit-panel-wrap`, mapAreaSize.height > 0 && `pisell-floor-map-layout-edit-panel-wrap-constrained`),
910
- style: mapAreaSize.height > 0 ? {
911
- height: mapAreaSize.height - 32,
912
- maxHeight: mapAreaSize.height - 32,
913
- overflow: "hidden",
914
- top: 16,
915
- transform: "none"
916
- } : void 0
917
- }, /* @__PURE__ */ react.default.createElement(require_FloorMapEditPanel.default, require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, editPanelParams), {}, {
1059
+ style: mapAreaSize.height > 0 ? { overflow: "hidden" } : void 0
1060
+ }, edgeEdit.selectedEdge ? /* @__PURE__ */ react.default.createElement(require_FloorMapEdgeEditPanel.FloorMapEdgeEditPanel, {
1061
+ edge: edgeEdit.selectedEdge,
1062
+ config,
1063
+ onUpdate: (patch) => edgeEdit.updateEdge(edgeEdit.selectedEdge.id, patch),
1064
+ onClose: () => edgeEdit.selectEdge(null),
1065
+ onDelete: config.canvasUi.canEdit ? () => edgeEdit.deleteEdge(edgeEdit.selectedEdge.id) : void 0,
1066
+ layoutDraftDirty: isLayoutDirty
1067
+ }) : editPanelParams ? /* @__PURE__ */ react.default.createElement(require_FloorMapEditPanel.default, require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, editPanelParams), {}, {
918
1068
  config,
919
1069
  dataSources,
920
1070
  savingRecord
921
- }))));
922
- })))), editTopBarPhoneLayout && editPanelParams && config && dataSources && /* @__PURE__ */ react.default.createElement(antd.Drawer, {
1071
+ })) : null));
1072
+ })))), editTopBarPhoneLayout && config && dataSources && (edgeEdit.selectedEdge || editPanelParams) && /* @__PURE__ */ react.default.createElement(antd.Drawer, {
923
1073
  placement: "right",
924
1074
  open: phoneEditDrawerOpen,
925
1075
  onClose: handlePhoneEditDrawerClose,
@@ -937,12 +1087,20 @@ function PisellFloorMapLayoutInner(props, ref) {
937
1087
  height: "100%"
938
1088
  } },
939
1089
  getContainer: typeof document !== "undefined" ? () => document.body : void 0
940
- }, /* @__PURE__ */ react.default.createElement("div", { className: (0, classnames.default)(`pisell-floor-map-layout-edit-panel-wrap`, `pisell-floor-map-layout-edit-panel-wrap--phone-drawer`) }, /* @__PURE__ */ react.default.createElement(require_FloorMapEditPanel.default, require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, editPanelParams), {}, {
1090
+ }, /* @__PURE__ */ react.default.createElement("div", { className: (0, classnames.default)(`pisell-floor-map-layout-edit-panel-wrap`, `pisell-floor-map-layout-edit-panel-wrap--phone-drawer`) }, edgeEdit.selectedEdge ? /* @__PURE__ */ react.default.createElement(require_FloorMapEdgeEditPanel.FloorMapEdgeEditPanel, {
1091
+ edge: edgeEdit.selectedEdge,
1092
+ config,
1093
+ onUpdate: (patch) => edgeEdit.updateEdge(edgeEdit.selectedEdge.id, patch),
1094
+ onClose: () => edgeEdit.selectEdge(null),
1095
+ onDelete: config.canvasUi.canEdit ? () => edgeEdit.deleteEdge(edgeEdit.selectedEdge.id) : void 0,
1096
+ layoutDraftDirty: isLayoutDirty,
1097
+ className: `pisell-floor-map-layout-edit-panel--phone-drawer`
1098
+ }) : editPanelParams ? /* @__PURE__ */ react.default.createElement(require_FloorMapEditPanel.default, require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, editPanelParams), {}, {
941
1099
  config,
942
1100
  dataSources,
943
1101
  savingRecord,
944
1102
  className: `pisell-floor-map-layout-edit-panel--phone-drawer`
945
- })))));
1103
+ })) : null)));
946
1104
  }
947
1105
  /** 空间布局根组件:阅读/编辑、列表与平面图双模式,ref 见 {@link PisellFloorMapLayoutRef} */
948
1106
  const PisellFloorMapLayout = react.default.forwardRef(PisellFloorMapLayoutInner);
@@ -63,12 +63,35 @@ body.pisell-floor-map-layout-fullscreen-host {
63
63
  z-index: 5;
64
64
  }
65
65
 
66
+ /**
67
+ * 右侧编辑面板(图元 / 连线共用):上下锚定,底部留出 ViewControls Dock,
68
+ * 避免面板白底盖住右下缩放等操作栏。
69
+ */
66
70
  &-edit-panel-wrap {
67
71
  position: absolute;
68
- top: 50%;
72
+ top: 16px;
69
73
  right: 16px;
70
- transform: translateY(-50%);
74
+ bottom: calc(16px + var(--fmap-viewport-dock-bottom-clearance, 78px));
75
+ transform: none;
71
76
  z-index: 10;
77
+ display: flex;
78
+ flex-direction: column;
79
+ align-items: stretch;
80
+ min-height: 0;
81
+ max-width: min(280px, calc(100% - 32px));
82
+
83
+ > .pisell-floor-map-layout-edit-panel,
84
+ > .pisell-floor-map-layout-edge-edit-panel {
85
+ flex: 1 1 auto;
86
+ min-height: 0;
87
+ max-height: 100%;
88
+ height: auto;
89
+ box-sizing: border-box;
90
+ }
91
+ }
92
+
93
+ &-edit-panel-wrap-constrained {
94
+ overflow: hidden;
72
95
  }
73
96
 
74
97
  &-edit-panel-wrap--phone-drawer {
@@ -136,6 +159,14 @@ body.pisell-floor-map-layout-fullscreen-host {
136
159
 
137
160
  /** 视口内悬浮层:不随 Transform 缩放平移,与 ViewControls 同级 */
138
161
 
162
+ /**
163
+ * 右下 ViewControls Dock(14px + 56px chrome + 8px 间距),供右侧编辑面板底部留白。
164
+ * 数值与 {@link FLOOR_MAP_VIEWPORT_DOCK_BOTTOM_CLEARANCE} 保持一致。
165
+ */
166
+ &-floor-map-view {
167
+ --fmap-viewport-dock-bottom-clearance: 78px;
168
+ }
169
+
139
170
  &-viewport-overlay {
140
171
  position: absolute;
141
172
  left: 12px;