grab 0.1.35 → 0.1.36

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 (86) hide show
  1. package/dist/copy-content-3pnWacho.d.cts +218 -0
  2. package/dist/copy-content-DH6fBB50.d.ts +218 -0
  3. package/dist/core/index.cjs +1 -1
  4. package/dist/core/index.d.cts +2 -2
  5. package/dist/core/index.d.ts +2 -2
  6. package/dist/core/index.js +1 -1
  7. package/dist/core-B9aCRu_r.cjs +4374 -0
  8. package/dist/core-BNG77P9u.js +20 -0
  9. package/dist/core-BaM4pWDg.cjs +20 -0
  10. package/dist/core-BgAHCKe7.js +4492 -0
  11. package/dist/core-BnZu88Zq.js +20 -0
  12. package/dist/core-BoXxu65H.js +20 -0
  13. package/dist/core-Bw1MUegr.cjs +4374 -0
  14. package/dist/core-C-uBKPnx.js +20 -0
  15. package/dist/core-CMd2PuB-.cjs +20 -0
  16. package/dist/core-CN7fVz1T.cjs +4377 -0
  17. package/dist/core-C_moHA9D.js +20 -0
  18. package/dist/core-CoEZwalZ.js +4489 -0
  19. package/dist/core-Cyu0n7SO.js +20 -0
  20. package/dist/core-DMVlP9g5.js +20 -0
  21. package/dist/core-XXPjZNnn.cjs +20 -0
  22. package/dist/core-_t0msYhT.cjs +20 -0
  23. package/dist/core-eVrmPJ2u.cjs +20 -0
  24. package/dist/core-epcog0yL.cjs +20 -0
  25. package/dist/core-foLKkb5_.cjs +20 -0
  26. package/dist/core-kGODXK-N.js +4489 -0
  27. package/dist/create-element-selector-B5J9_3Fw.cjs +9 -0
  28. package/dist/create-element-selector-BEaSanPh.cjs +9 -0
  29. package/dist/create-element-selector-BR_zDrcL.js +296 -0
  30. package/dist/create-element-selector-C3VxTCEX.js +9 -0
  31. package/dist/create-element-selector-CIj_4oMe.js +9 -0
  32. package/dist/create-element-selector-C_6sG1Bd.js +296 -0
  33. package/dist/create-element-selector-ChuWL5x4.cjs +9 -0
  34. package/dist/create-element-selector-CufggNcJ.js +9 -0
  35. package/dist/create-element-selector-D1FizysC.js +9 -0
  36. package/dist/create-element-selector-D4_cMOfX.cjs +307 -0
  37. package/dist/create-element-selector-Dw4Hh5vX.cjs +307 -0
  38. package/dist/create-element-selector-pHsYuaOR.cjs +9 -0
  39. package/dist/freeze-updates-1bWq0iRj.cjs +3340 -0
  40. package/dist/freeze-updates-7yZ9p4Jb.cjs +52 -0
  41. package/dist/freeze-updates-B2R6sKrS.js +52 -0
  42. package/dist/freeze-updates-BUIl_I9a.js +52 -0
  43. package/dist/freeze-updates-D7wc1FFo.js +52 -0
  44. package/dist/freeze-updates-DC22uWxG.cjs +3347 -0
  45. package/dist/freeze-updates-DFjQ3htO.js +52 -0
  46. package/dist/freeze-updates-DIifOZze.js +2921 -0
  47. package/dist/freeze-updates-D_ae-e4T.js +2920 -0
  48. package/dist/freeze-updates-DdIqMW8Y.cjs +52 -0
  49. package/dist/freeze-updates-DvAOKSWG.cjs +52 -0
  50. package/dist/freeze-updates-F-dFqbvY.cjs +52 -0
  51. package/dist/index-CkMIwkYj.d.ts +413 -0
  52. package/dist/index-DR5AjI5S.d.cts +413 -0
  53. package/dist/index.cjs +1 -1
  54. package/dist/index.d.cts +2 -2
  55. package/dist/index.d.ts +2 -2
  56. package/dist/index.global.js +13 -13
  57. package/dist/index.js +1 -1
  58. package/dist/primitives.cjs +1 -1
  59. package/dist/primitives.d.cts +1 -1
  60. package/dist/primitives.d.ts +1 -1
  61. package/dist/primitives.js +1 -1
  62. package/dist/renderer-B65BudlT.cjs +9 -0
  63. package/dist/renderer-BRENw6lS.cjs +3205 -0
  64. package/dist/renderer-Bxc3RS-J.cjs +3205 -0
  65. package/dist/renderer-CD-Ju8A3.js +3205 -0
  66. package/dist/renderer-D0a4h1bK.cjs +9 -0
  67. package/dist/renderer-D3dvNcvm.cjs +9 -0
  68. package/dist/renderer-DQoIdFmy.js +9 -0
  69. package/dist/renderer-Dc20mGte.js +9 -0
  70. package/dist/renderer-DmNPMFh8.js +3205 -0
  71. package/dist/renderer-Dnyqr-yC.cjs +9 -0
  72. package/dist/renderer-gEdmDcCb.js +9 -0
  73. package/dist/renderer-kDb-jNJX.js +9 -0
  74. package/dist/state-BAZpSiUU.js +9 -0
  75. package/dist/state-BPvTpQtD.js +9 -0
  76. package/dist/state-Bn3fhsQ8.cjs +9 -0
  77. package/dist/state-BwCmdtcN.cjs +1306 -0
  78. package/dist/state-CFntkBxv.js +1696 -0
  79. package/dist/state-CR6-uxRM.cjs +9 -0
  80. package/dist/state-DQNAhhCY.cjs +1306 -0
  81. package/dist/state-Dgr3LbNH.cjs +9 -0
  82. package/dist/state-Ds-1VLFt.js +9 -0
  83. package/dist/state-Dt16Hkud.js +9 -0
  84. package/dist/state-LuyoMylH.js +1696 -0
  85. package/dist/state-x2vKMZfm.cjs +9 -0
  86. package/package.json +2 -2
@@ -0,0 +1,4374 @@
1
+ /**
2
+ * @license MIT
3
+ *
4
+ * Copyright (c) 2025 Aiden Bai
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ const require_state = require('./state-DQNAhhCY.cjs');
10
+ const require_freeze_updates = require('./freeze-updates-1bWq0iRj.cjs');
11
+ const require_create_element_selector = require('./create-element-selector-Dw4Hh5vX.cjs');
12
+
13
+ //#region dist/styles.css?css-text
14
+ var styles_default = "/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: \"Geist\", ui-sans-serif, system-ui, sans-serif;\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --spacing: 0.25rem;\n --font-weight-medium: 500;\n --radius-sm: 0.25rem;\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\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 --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);\n --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :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, h2, h3, h4, h5, 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, strong {\n font-weight: bolder;\n }\n code, kbd, samp, 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, 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, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::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, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-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, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-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 .touch-hitbox {\n position: relative;\n &::before {\n content: \"\";\n position: absolute;\n display: block;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 100%;\n height: 100%;\n min-height: 44px;\n min-width: 44px;\n }\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .z-1 {\n z-index: 1;\n }\n .z-10 {\n z-index: 10;\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 .-m-0\\.5 {\n margin: calc(var(--spacing) * -0.5);\n }\n .m-0 {\n margin: calc(var(--spacing) * 0);\n }\n .-mx-2 {\n margin-inline: calc(var(--spacing) * -2);\n }\n .-my-1\\.5 {\n margin-block: calc(var(--spacing) * -1.5);\n }\n .mr-1\\.5 {\n margin-right: calc(var(--spacing) * 1.5);\n }\n .mb-1\\.5 {\n margin-bottom: calc(var(--spacing) * 1.5);\n }\n .ml-1 {\n margin-left: calc(var(--spacing) * 1);\n }\n .ml-4 {\n margin-left: calc(var(--spacing) * 4);\n }\n .line-clamp-5 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 5;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .inline {\n display: inline;\n }\n .inline-flex {\n display: inline-flex;\n }\n .size-4 {\n width: calc(var(--spacing) * 4);\n height: calc(var(--spacing) * 4);\n }\n .h-0 {\n height: calc(var(--spacing) * 0);\n }\n .h-\\[17px\\] {\n height: 17px;\n }\n .h-fit {\n height: fit-content;\n }\n .min-h-0 {\n min-height: calc(var(--spacing) * 0);\n }\n .min-h-4 {\n min-height: calc(var(--spacing) * 4);\n }\n .w-0 {\n width: calc(var(--spacing) * 0);\n }\n .w-\\[calc\\(100\\%\\+16px\\)\\] {\n width: calc(100% + 16px);\n }\n .w-auto {\n width: auto;\n }\n .w-fit {\n width: fit-content;\n }\n .w-full {\n width: 100%;\n }\n .max-w-\\[280px\\] {\n max-width: 280px;\n }\n .max-w-full {\n max-width: 100%;\n }\n .min-w-0 {\n min-width: calc(var(--spacing) * 0);\n }\n .min-w-\\[100px\\] {\n min-width: 100px;\n }\n .min-w-\\[150px\\] {\n min-width: 150px;\n }\n .flex-1 {\n flex: 1;\n }\n .flex-shrink {\n flex-shrink: 1;\n }\n .shrink {\n flex-shrink: 1;\n }\n .shrink-0 {\n flex-shrink: 0;\n }\n .flex-grow {\n flex-grow: 1;\n }\n .-rotate-90 {\n rotate: calc(90deg * -1);\n }\n .rotate-0 {\n rotate: 0deg;\n }\n .rotate-90 {\n rotate: 90deg;\n }\n .rotate-180 {\n rotate: 180deg;\n }\n .interactive-scale {\n transition: transform 400ms cubic-bezier(0.34, 1.56, 0.64, 1);\n @media (hover: hover) and (pointer: fine) {\n &:hover {\n transform: scale(1.05);\n }\n }\n &:active {\n transform: scale(0.96);\n transition: transform 60ms cubic-bezier(0, 0, 0.2, 1);\n }\n }\n .press-scale {\n transition: transform 400ms cubic-bezier(0.34, 1.56, 0.64, 1);\n &:active {\n transform: scale(0.97);\n transition: transform 60ms cubic-bezier(0, 0, 0.2, 1);\n }\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 .cursor-grab {\n cursor: grab;\n }\n .cursor-grabbing {\n cursor: grabbing;\n }\n .cursor-pointer {\n cursor: pointer;\n }\n .resize {\n resize: both;\n }\n .resize-none {\n resize: none;\n }\n .grid-cols-\\[0fr\\] {\n grid-template-columns: 0fr;\n }\n .grid-cols-\\[1fr\\] {\n grid-template-columns: 1fr;\n }\n .grid-rows-\\[0fr\\] {\n grid-template-rows: 0fr;\n }\n .grid-rows-\\[1fr\\] {\n grid-template-rows: 1fr;\n }\n .flex-col {\n flex-direction: column;\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-start {\n align-items: flex-start;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .gap-0 {\n gap: calc(var(--spacing) * 0);\n }\n .gap-0\\.5 {\n gap: calc(var(--spacing) * 0.5);\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-\\[5px\\] {\n gap: 5px;\n }\n .self-stretch {\n align-self: stretch;\n }\n .truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .overflow-visible {\n overflow: visible;\n }\n .overflow-y-auto {\n overflow-y: auto;\n }\n .rounded-\\[10px\\] {\n border-radius: 10px;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-sm {\n border-radius: var(--radius-sm);\n }\n .rounded-t-\\[10px\\] {\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n }\n .rounded-t-none {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n .rounded-l-\\[10px\\] {\n border-top-left-radius: 10px;\n border-bottom-left-radius: 10px;\n }\n .rounded-l-none {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .rounded-r-\\[10px\\] {\n border-top-right-radius: 10px;\n border-bottom-right-radius: 10px;\n }\n .rounded-r-none {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n .rounded-b-\\[6px\\] {\n border-bottom-right-radius: 6px;\n border-bottom-left-radius: 6px;\n }\n .rounded-b-\\[10px\\] {\n border-bottom-right-radius: 10px;\n border-bottom-left-radius: 10px;\n }\n .rounded-b-none {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .\\[border-width\\:0\\.5px\\] {\n border-width: 0.5px;\n }\n .\\[border-top-width\\:0\\.5px\\] {\n border-top-width: 0.5px;\n }\n .border-none {\n --tw-border-style: none;\n border-style: none;\n }\n .border-solid {\n --tw-border-style: solid;\n border-style: solid;\n }\n .border-\\[var\\(--rg-border-button\\)\\] {\n border-color: var(--rg-border-button);\n }\n .border-t-\\[var\\(--rg-border-subtle\\)\\] {\n border-top-color: var(--rg-border-subtle);\n }\n .bg-\\[var\\(--rg-error-bg\\)\\] {\n background-color: var(--rg-error-bg);\n }\n .bg-\\[var\\(--rg-panel-bg\\)\\] {\n background-color: var(--rg-panel-bg);\n }\n .bg-\\[var\\(--rg-submit-bg\\)\\] {\n background-color: var(--rg-submit-bg);\n }\n .bg-\\[var\\(--rg-surface-hover\\)\\] {\n background-color: var(--rg-surface-hover);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .p-0 {\n padding: calc(var(--spacing) * 0);\n }\n .px-0\\.25 {\n padding-inline: calc(var(--spacing) * 0.25);\n }\n .px-1\\.5 {\n padding-inline: calc(var(--spacing) * 1.5);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-\\[3px\\] {\n padding-inline: 3px;\n }\n .py-0\\.25 {\n padding-block: calc(var(--spacing) * 0.25);\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-px {\n padding-block: 1px;\n }\n .pt-1\\.5 {\n padding-top: calc(var(--spacing) * 1.5);\n }\n .pb-1 {\n padding-bottom: calc(var(--spacing) * 1);\n }\n .text-left {\n text-align: left;\n }\n .font-sans {\n font-family: var(--font-sans);\n }\n .text-\\[11px\\] {\n font-size: 11px;\n }\n .text-\\[13px\\] {\n font-size: 13px;\n }\n .leading-3\\.5 {\n --tw-leading: calc(var(--spacing) * 3.5);\n line-height: calc(var(--spacing) * 3.5);\n }\n .leading-4 {\n --tw-leading: calc(var(--spacing) * 4);\n line-height: calc(var(--spacing) * 4);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .wrap-break-word {\n overflow-wrap: break-word;\n }\n .text-ellipsis {\n text-overflow: ellipsis;\n }\n .whitespace-nowrap {\n white-space: nowrap;\n }\n .text-\\[var\\(--rg-error-text\\)\\] {\n color: var(--rg-error-text);\n }\n .text-\\[var\\(--rg-submit-fg\\)\\] {\n color: var(--rg-submit-fg);\n }\n .text-\\[var\\(--rg-text-primary\\)\\] {\n color: var(--rg-text-primary);\n }\n .text-\\[var\\(--rg-text-primary-85\\)\\] {\n color: var(--rg-text-primary-85);\n }\n .text-\\[var\\(--rg-text-secondary\\)\\] {\n color: var(--rg-text-secondary);\n }\n .tabular-nums {\n --tw-numeric-spacing: tabular-nums;\n font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);\n }\n .antialiased {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n .opacity-0 {\n opacity: 0%;\n }\n .opacity-50 {\n opacity: 50%;\n }\n .opacity-100 {\n opacity: 100%;\n }\n .shadow {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .\\[box-shadow\\:var\\(--rg-shadow\\)\\] {\n box-shadow: var(--rg-shadow);\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\\:var\\(--rg-drop-shadow\\)\\] {\n filter: var(--rg-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-filter {\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: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, 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-\\[grid-template-columns\\] {\n transition-property: grid-template-columns;\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-\\[grid-template-rows\\] {\n transition-property: grid-template-rows;\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\\,transform\\] {\n transition-property: opacity,transform;\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-\\[padding\\,border-radius\\,transform\\] {\n transition-property: padding,border-radius,transform;\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-\\[top\\,left\\,width\\,height\\,opacity\\] {\n transition-property: top,left,width,height,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 .transition-\\[transform\\,opacity\\] {\n transition-property: transform,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 .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-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\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 .transition-transform {\n transition-property: transform, translate, scale, rotate;\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-\\[80ms\\] {\n transition-delay: 80ms;\n }\n .duration-60 {\n --tw-duration: 60ms;\n transition-duration: 60ms;\n }\n .duration-75 {\n --tw-duration: 75ms;\n transition-duration: 75ms;\n }\n .duration-100 {\n --tw-duration: 100ms;\n transition-duration: 100ms;\n }\n .duration-120 {\n --tw-duration: 120ms;\n transition-duration: 120ms;\n }\n .duration-140 {\n --tw-duration: 140ms;\n transition-duration: 140ms;\n }\n .duration-150 {\n --tw-duration: 150ms;\n transition-duration: 150ms;\n }\n .duration-180 {\n --tw-duration: 180ms;\n transition-duration: 180ms;\n }\n .duration-220 {\n --tw-duration: 220ms;\n transition-duration: 220ms;\n }\n .duration-300 {\n --tw-duration: 300ms;\n transition-duration: 300ms;\n }\n .duration-400 {\n --tw-duration: 400ms;\n transition-duration: 400ms;\n }\n .ease-\\[cubic-bezier\\(0\\,0\\,0\\.2\\,1\\)\\] {\n --tw-ease: cubic-bezier(0,0,0.2,1);\n transition-timing-function: cubic-bezier(0,0,0.2,1);\n }\n .ease-drawer {\n --tw-ease: var(--ease-drawer);\n transition-timing-function: var(--ease-drawer);\n }\n .ease-out {\n --tw-ease: var(--ease-out);\n transition-timing-function: var(--ease-out);\n }\n .ease-spring {\n --tw-ease: var(--ease-spring);\n transition-timing-function: var(--ease-spring);\n }\n .will-change-\\[opacity\\,transform\\] {\n will-change: opacity,transform;\n }\n .contain-layout {\n --tw-contain-layout: layout;\n contain: var(--tw-contain-size,) var(--tw-contain-layout,) var(--tw-contain-paint,) var(--tw-contain-style,);\n }\n .outline-none {\n --tw-outline-style: none;\n outline-style: none;\n }\n .select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .\\[corner-shape\\:superellipse\\(1\\.25\\)\\] {\n corner-shape: superellipse(1.25);\n }\n .\\[font-synthesis\\:none\\] {\n font-synthesis: none;\n }\n .hover\\:bg-\\[var\\(--rg-error-bg-hover\\)\\] {\n &:hover {\n @media (hover: hover) {\n background-color: var(--rg-error-bg-hover);\n }\n }\n }\n .hover\\:bg-\\[var\\(--rg-surface-active\\)\\] {\n &:hover {\n @media (hover: hover) {\n background-color: var(--rg-surface-active);\n }\n }\n }\n .hover\\:bg-\\[var\\(--rg-surface-hover\\)\\] {\n &:hover {\n @media (hover: hover) {\n background-color: var(--rg-surface-hover);\n }\n }\n }\n .hover\\:text-\\[var\\(--rg-text-primary\\)\\] {\n &:hover {\n @media (hover: hover) {\n color: var(--rg-text-primary);\n }\n }\n }\n .disabled\\:cursor-default {\n &:disabled {\n cursor: default;\n }\n }\n .disabled\\:opacity-40 {\n &:disabled {\n opacity: 40%;\n }\n }\n}\n:host {\n all: initial;\n direction: ltr;\n}\n:host, [data-rg-theme=\"dark\"] {\n --rg-panel-bg: #161616;\n --rg-text-primary: #ffffff;\n --rg-text-secondary: #a7a7a7;\n --rg-surface-hover: rgba(255, 255, 255, 0.1);\n --rg-surface-active: rgba(255, 255, 255, 0.15);\n --rg-border-subtle: rgba(255, 255, 255, 0.1);\n --rg-border-button: rgba(255, 255, 255, 0.2);\n --rg-submit-bg: #ffffff;\n --rg-submit-fg: #161616;\n --rg-error-text: #f87171;\n --rg-error-bg: #3d1515;\n --rg-error-bg-hover: #4d1f1f;\n --rg-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n --rg-drop-shadow: drop-shadow(0px 2px 8px rgba(0, 0, 0, 0.08));\n --rg-shimmer-from: #a1a1aa;\n --rg-shimmer-to: #d4d4d8;\n --rg-text-primary-85: rgba(255, 255, 255, 0.85);\n}\n@media (prefers-color-scheme: dark) {\n :host:not([data-rg-theme]) {\n --rg-panel-bg: #ffffff;\n --rg-text-primary: #171717;\n --rg-text-secondary: #737373;\n --rg-surface-hover: rgba(0, 0, 0, 0.05);\n --rg-surface-active: rgba(0, 0, 0, 0.08);\n --rg-border-subtle: rgba(0, 0, 0, 0.08);\n --rg-border-button: rgba(0, 0, 0, 0.15);\n --rg-submit-bg: #171717;\n --rg-submit-fg: #ffffff;\n --rg-error-text: #dc2626;\n --rg-error-bg: #fee2e2;\n --rg-error-bg-hover: #fecaca;\n --rg-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);\n --rg-drop-shadow: drop-shadow(0px 2px 12px rgba(0, 0, 0, 0.1));\n --rg-shimmer-from: #71717a;\n --rg-shimmer-to: #a1a1aa;\n --rg-text-primary-85: rgba(23, 23, 23, 0.85);\n }\n}\n:host([data-rg-theme=\"light\"]), [data-rg-theme=\"light\"] {\n --rg-panel-bg: #ffffff;\n --rg-text-primary: #171717;\n --rg-text-secondary: #737373;\n --rg-surface-hover: rgba(0, 0, 0, 0.05);\n --rg-surface-active: rgba(0, 0, 0, 0.08);\n --rg-border-subtle: rgba(0, 0, 0, 0.08);\n --rg-border-button: rgba(0, 0, 0, 0.15);\n --rg-submit-bg: #171717;\n --rg-submit-fg: #ffffff;\n --rg-error-text: #dc2626;\n --rg-error-bg: #fee2e2;\n --rg-error-bg-hover: #fecaca;\n --rg-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);\n --rg-drop-shadow: drop-shadow(0px 2px 12px rgba(0, 0, 0, 0.1));\n --rg-shimmer-from: #71717a;\n --rg-shimmer-to: #a1a1aa;\n --rg-text-primary-85: rgba(23, 23, 23, 0.85);\n}\n@keyframes rg-badge-slide {\n from {\n transform: translate(-8.2px, 12.4px);\n }\n to {\n transform: translate(0, 0);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-react-grab-unread-indicator], [data-react-grab-unread-indicator] * {\n animation: none !important;\n transition: none !important;\n }\n}\n@keyframes shake {\n 0%, 100% {\n transform: translateX(0);\n }\n 15% {\n transform: translateX(-3px);\n }\n 30% {\n transform: translateX(3px);\n }\n 45% {\n transform: translateX(-3px);\n }\n 60% {\n transform: translateX(3px);\n }\n 75% {\n transform: translateX(-2px);\n }\n 90% {\n transform: translateX(2px);\n }\n}\n@keyframes success-pop {\n from {\n transform: scale(0.85);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n@keyframes icon-loader-spin {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n 100% {\n opacity: 0.2;\n }\n}\n.icon-loader-bar {\n animation: icon-loader-spin 0.5s linear infinite;\n}\n@keyframes shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n.shimmer-text {\n background: linear-gradient( 90deg, var(--rg-shimmer-from) 0%, var(--rg-shimmer-to) 25%, var(--rg-shimmer-from) 50%, var(--rg-shimmer-to) 75%, var(--rg-shimmer-from) 100% );\n background-size: 200% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n animation: shimmer 2.5s linear infinite;\n}\n@keyframes clock-flash {\n 0% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2);\n }\n 50% {\n transform: scale(0.92);\n }\n 75% {\n transform: scale(1.05);\n }\n 100% {\n transform: scale(1);\n }\n}\n.animate-clock-flash {\n animation: clock-flash 400ms ease-out;\n will-change: transform;\n}\n.animate-shake {\n animation: shake 0.3s ease-out;\n will-change: transform;\n}\n.animate-success-pop {\n animation: success-pop 350ms cubic-bezier(0.34, 1.56, 0.64, 1) both;\n will-change: transform, opacity;\n}\n@supports (-webkit-touch-callout: none) {\n textarea[data-react-grab-input] {\n font-size: 16px;\n }\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-leading {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ordinal {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-slashed-zero {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-numeric-figure {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-numeric-spacing {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-numeric-fraction {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-outline-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-drop-shadow {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-drop-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-drop-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-drop-shadow-size {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ease {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-size {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-layout {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-paint {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-style {\n syntax: \"*\";\n inherits: false;\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 *, ::before, ::after, ::backdrop {\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-leading: initial;\n --tw-font-weight: initial;\n --tw-ordinal: initial;\n --tw-slashed-zero: initial;\n --tw-numeric-figure: initial;\n --tw-numeric-spacing: initial;\n --tw-numeric-fraction: 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-contain-size: initial;\n --tw-contain-layout: initial;\n --tw-contain-paint: initial;\n --tw-contain-style: initial;\n }\n }\n}\n";
15
+
16
+ //#endregion
17
+ //#region ../../node_modules/.pnpm/solid-js@1.9.12/node_modules/solid-js/store/dist/server.js
18
+ function isWrappable(obj) {
19
+ return obj != null && typeof obj === "object" && (Object.getPrototypeOf(obj) === Object.prototype || Array.isArray(obj));
20
+ }
21
+ function setProperty(state, property, value, force) {
22
+ if (!force && state[property] === value) return;
23
+ if (value === void 0) delete state[property];
24
+ else state[property] = value;
25
+ }
26
+ function mergeStoreNode(state, value, force) {
27
+ const keys = Object.keys(value);
28
+ for (let i = 0; i < keys.length; i += 1) {
29
+ const key = keys[i];
30
+ setProperty(state, key, value[key], force);
31
+ }
32
+ }
33
+ function updateArray(current, next) {
34
+ if (typeof next === "function") next = next(current);
35
+ if (Array.isArray(next)) {
36
+ if (current === next) return;
37
+ let i = 0, len = next.length;
38
+ for (; i < len; i++) {
39
+ const value = next[i];
40
+ if (current[i] !== value) setProperty(current, i, value);
41
+ }
42
+ setProperty(current, "length", len);
43
+ } else mergeStoreNode(current, next);
44
+ }
45
+ function updatePath(current, path, traversed = []) {
46
+ let part, next = current;
47
+ if (path.length > 1) {
48
+ part = path.shift();
49
+ const partType = typeof part, isArray = Array.isArray(current);
50
+ if (Array.isArray(part)) {
51
+ for (let i = 0; i < part.length; i++) updatePath(current, [part[i]].concat(path), traversed);
52
+ return;
53
+ } else if (isArray && partType === "function") {
54
+ for (let i = 0; i < current.length; i++) if (part(current[i], i)) updatePath(current, [i].concat(path), traversed);
55
+ return;
56
+ } else if (isArray && partType === "object") {
57
+ const { from = 0, to = current.length - 1, by = 1 } = part;
58
+ for (let i = from; i <= to; i += by) updatePath(current, [i].concat(path), traversed);
59
+ return;
60
+ } else if (path.length > 1) {
61
+ updatePath(current[part], path, [part].concat(traversed));
62
+ return;
63
+ }
64
+ next = current[part];
65
+ traversed = [part].concat(traversed);
66
+ }
67
+ let value = path[0];
68
+ if (typeof value === "function") {
69
+ value = value(next, traversed);
70
+ if (value === next) return;
71
+ }
72
+ if (part === void 0 && value == void 0) return;
73
+ if (part === void 0 || isWrappable(next) && isWrappable(value) && !Array.isArray(value)) mergeStoreNode(next, value);
74
+ else setProperty(current, part, value);
75
+ }
76
+ function createStore(state) {
77
+ const isArray = Array.isArray(state);
78
+ function setStore(...args) {
79
+ isArray && args.length === 1 ? updateArray(state, args[0]) : updatePath(state, args);
80
+ }
81
+ return [state, setStore];
82
+ }
83
+ function produce(fn) {
84
+ return (state) => {
85
+ if (isWrappable(state)) fn(state);
86
+ return state;
87
+ };
88
+ }
89
+
90
+ //#endregion
91
+ //#region src/utils/strip-translate-from-transform.ts
92
+ const isValidNumber = (value) => typeof value === "number" && !Number.isNaN(value) && Number.isFinite(value);
93
+ const parseMatrixValue = (value) => {
94
+ const trimmedValue = value.trim();
95
+ if (!trimmedValue) return null;
96
+ const parsedValue = parseFloat(trimmedValue);
97
+ return isValidNumber(parsedValue) ? parsedValue : null;
98
+ };
99
+ const parseMatrixValues = (valuesString, expectedLength) => {
100
+ const rawValues = valuesString.split(",");
101
+ if (rawValues.length !== expectedLength) return null;
102
+ const parsedValues = [];
103
+ for (const rawValue of rawValues) {
104
+ const parsedValue = parseMatrixValue(rawValue);
105
+ if (parsedValue === null) return null;
106
+ parsedValues.push(parsedValue);
107
+ }
108
+ return parsedValues;
109
+ };
110
+ const isIdentityMatrix2d = (a, b, c, d) => a === 1 && b === 0 && c === 0 && d === 1;
111
+ const isIdentityMatrix3d = (values) => values[0] === 1 && values[1] === 0 && values[2] === 0 && values[3] === 0 && values[4] === 0 && values[5] === 1 && values[6] === 0 && values[7] === 0 && values[8] === 0 && values[9] === 0 && values[10] === 1 && values[11] === 0 && values[15] === 1;
112
+ const stripTranslateFromTransformString = (transform) => {
113
+ if (!transform || transform === "none") return "none";
114
+ if (transform.startsWith("matrix")) if (transform.startsWith("matrix3d(")) {
115
+ const start = 9;
116
+ const end = transform.length - 1;
117
+ const values = parseMatrixValues(transform.slice(start, end), 16);
118
+ if (values) {
119
+ values[12] = 0;
120
+ values[13] = 0;
121
+ values[14] = 0;
122
+ if (isIdentityMatrix3d(values)) return "none";
123
+ return `matrix3d(${values[0]}, ${values[1]}, ${values[2]}, ${values[3]}, ${values[4]}, ${values[5]}, ${values[6]}, ${values[7]}, ${values[8]}, ${values[9]}, ${values[10]}, ${values[11]}, 0, 0, 0, ${values[15]})`;
124
+ }
125
+ } else {
126
+ const start = 7;
127
+ const end = transform.length - 1;
128
+ const values = parseMatrixValues(transform.slice(start, end), 6);
129
+ if (values) {
130
+ const scaleX = values[0];
131
+ const skewY = values[1];
132
+ const skewX = values[2];
133
+ const scaleY = values[3];
134
+ if (isIdentityMatrix2d(scaleX, skewY, skewX, scaleY)) return "none";
135
+ return `matrix(${scaleX}, ${skewY}, ${skewX}, ${scaleY}, 0, 0)`;
136
+ }
137
+ }
138
+ return "none";
139
+ };
140
+ const stripTranslateFromMatrix = (matrix) => {
141
+ if (matrix.isIdentity) return "none";
142
+ if (matrix.is2D) {
143
+ if (isIdentityMatrix2d(matrix.a, matrix.b, matrix.c, matrix.d)) return "none";
144
+ return `matrix(${matrix.a}, ${matrix.b}, ${matrix.c}, ${matrix.d}, 0, 0)`;
145
+ }
146
+ if (matrix.m11 === 1 && matrix.m12 === 0 && matrix.m13 === 0 && matrix.m14 === 0 && matrix.m21 === 0 && matrix.m22 === 1 && matrix.m23 === 0 && matrix.m24 === 0 && matrix.m31 === 0 && matrix.m32 === 0 && matrix.m33 === 1 && matrix.m34 === 0 && matrix.m44 === 1) return "none";
147
+ return `matrix3d(${matrix.m11}, ${matrix.m12}, ${matrix.m13}, ${matrix.m14}, ${matrix.m21}, ${matrix.m22}, ${matrix.m23}, ${matrix.m24}, ${matrix.m31}, ${matrix.m32}, ${matrix.m33}, ${matrix.m34}, 0, 0, 0, ${matrix.m44})`;
148
+ };
149
+
150
+ //#endregion
151
+ //#region src/utils/create-element-bounds.ts
152
+ let boundsCache = /* @__PURE__ */ new WeakMap();
153
+ let ancestorTransformCache = /* @__PURE__ */ new WeakMap();
154
+ let borderRadiusCache = /* @__PURE__ */ new WeakMap();
155
+ const invalidateBoundsCache = () => {
156
+ boundsCache = /* @__PURE__ */ new WeakMap();
157
+ ancestorTransformCache = /* @__PURE__ */ new WeakMap();
158
+ borderRadiusCache = /* @__PURE__ */ new WeakMap();
159
+ };
160
+ const getAncestorTransformValue = (ancestor, now) => {
161
+ const cached = ancestorTransformCache.get(ancestor);
162
+ if (cached && now - cached.timestamp < 16) return cached.transform;
163
+ const transformValue = window.getComputedStyle(ancestor).transform;
164
+ const resolvedTransform = transformValue && transformValue !== "none" ? transformValue : "none";
165
+ ancestorTransformCache.set(ancestor, {
166
+ transform: resolvedTransform,
167
+ timestamp: now
168
+ });
169
+ return resolvedTransform;
170
+ };
171
+ const getAccumulatedTransform = (element, selfTransform, now) => {
172
+ const hasSelfTransform = selfTransform && selfTransform !== "none";
173
+ let accumulated = null;
174
+ let current = element.parentElement;
175
+ let depth = 0;
176
+ while (current && current !== document.documentElement && depth < 6) {
177
+ const transformValue = getAncestorTransformValue(current, now);
178
+ if (transformValue !== "none") accumulated = accumulated ? new DOMMatrix(transformValue).multiply(accumulated) : new DOMMatrix(transformValue);
179
+ else if (!hasSelfTransform && !accumulated && depth >= 3) return "none";
180
+ current = current.parentElement;
181
+ depth++;
182
+ }
183
+ if (!accumulated) return hasSelfTransform ? stripTranslateFromTransformString(selfTransform) : "none";
184
+ if (hasSelfTransform) accumulated = accumulated.multiply(new DOMMatrix(selfTransform));
185
+ return stripTranslateFromMatrix(accumulated);
186
+ };
187
+ const getCachedBorderRadius = (element, computedStyle, now) => {
188
+ const cached = borderRadiusCache.get(element);
189
+ if (cached && now - cached.timestamp < 200) return cached.borderRadius;
190
+ const borderRadius = (computedStyle ?? window.getComputedStyle(element)).borderRadius || "0px";
191
+ borderRadiusCache.set(element, {
192
+ borderRadius,
193
+ timestamp: now
194
+ });
195
+ return borderRadius;
196
+ };
197
+ const buildBoundsFromRect = (element, rect, style, now) => {
198
+ const transform = getAccumulatedTransform(element, style.transform, now);
199
+ const borderRadius = getCachedBorderRadius(element, style, now);
200
+ if (transform !== "none" && element instanceof HTMLElement) {
201
+ const offsetWidth = element.offsetWidth;
202
+ const offsetHeight = element.offsetHeight;
203
+ if (offsetWidth > 0 && offsetHeight > 0) {
204
+ const centerX = rect.left + rect.width * .5;
205
+ const centerY = rect.top + rect.height * .5;
206
+ return {
207
+ borderRadius,
208
+ height: offsetHeight,
209
+ transform,
210
+ width: offsetWidth,
211
+ x: centerX - offsetWidth * .5,
212
+ y: centerY - offsetHeight * .5
213
+ };
214
+ }
215
+ }
216
+ return {
217
+ borderRadius,
218
+ height: rect.height,
219
+ transform,
220
+ width: rect.width,
221
+ x: rect.left,
222
+ y: rect.top
223
+ };
224
+ };
225
+ const createElementBounds = (element) => {
226
+ const now = performance.now();
227
+ const cached = boundsCache.get(element);
228
+ if (cached && now - cached.timestamp < 16) return cached.bounds;
229
+ const bounds = buildBoundsFromRect(element, element.getBoundingClientRect(), window.getComputedStyle(element), now);
230
+ boundsCache.set(element, {
231
+ bounds,
232
+ timestamp: now
233
+ });
234
+ return bounds;
235
+ };
236
+
237
+ //#endregion
238
+ //#region src/utils/get-bounds-center.ts
239
+ const getBoundsCenter = (bounds) => ({
240
+ x: bounds.x + bounds.width / 2,
241
+ y: bounds.y + bounds.height / 2
242
+ });
243
+
244
+ //#endregion
245
+ //#region src/core/store.ts
246
+ const createInitialStore = (input) => ({
247
+ selectionInteractionLockDepth: 0,
248
+ wasActivatedByToggle: false,
249
+ pendingCommentMode: false,
250
+ keyHoldDuration: input.keyHoldDuration,
251
+ dragStart: {
252
+ x: require_freeze_updates.OFFSCREEN_POSITION,
253
+ y: require_freeze_updates.OFFSCREEN_POSITION
254
+ },
255
+ copyStart: {
256
+ x: require_freeze_updates.OFFSCREEN_POSITION,
257
+ y: require_freeze_updates.OFFSCREEN_POSITION
258
+ },
259
+ copyOffsetFromCenterX: 0,
260
+ detectedElement: null,
261
+ frozenElement: null,
262
+ frozenElements: [],
263
+ frozenDragRect: null,
264
+ lastGrabbedElement: null,
265
+ lastCopiedElement: null,
266
+ selectionFilePath: null,
267
+ selectionLineNumber: null,
268
+ inputText: "",
269
+ grabbedBoxes: [],
270
+ labelInstances: [],
271
+ isTouchMode: false,
272
+ theme: input.theme,
273
+ activationTimestamp: null,
274
+ previouslyFocusedElement: null,
275
+ contextMenuPosition: null,
276
+ contextMenuElement: null,
277
+ contextMenuClickOffset: null
278
+ });
279
+ const createGrabStore = (input) => {
280
+ const [store, setStore] = createStore(createInitialStore(input));
281
+ const [pointer, setPointer] = require_state.createSignal({
282
+ x: require_freeze_updates.OFFSCREEN_POSITION,
283
+ y: require_freeze_updates.OFFSCREEN_POSITION
284
+ });
285
+ const [viewportVersion, setViewportVersion] = require_state.createSignal(0);
286
+ const [current, setCurrent] = require_state.createSignal({ state: "idle" });
287
+ const updateFrozenElements = (mutator) => {
288
+ setStore(produce((draft) => {
289
+ mutator(draft);
290
+ draft.frozenElement = draft.frozenElements.length > 0 ? draft.frozenElements[0] : null;
291
+ draft.frozenDragRect = null;
292
+ }));
293
+ };
294
+ const clearFrozenElement = () => {
295
+ updateFrozenElements((draft) => {
296
+ draft.frozenElements = [];
297
+ });
298
+ };
299
+ const setActivePhase = (phase) => {
300
+ setCurrent((prev) => prev.state === "active" ? {
301
+ ...prev,
302
+ phase
303
+ } : prev);
304
+ };
305
+ const actions = {
306
+ startHold: (duration) => {
307
+ if (duration !== void 0) setStore("keyHoldDuration", duration);
308
+ setCurrent({
309
+ state: "holding",
310
+ startedAt: Date.now()
311
+ });
312
+ },
313
+ releaseHold: () => {
314
+ if (current().state === "holding") setCurrent({ state: "idle" });
315
+ },
316
+ activate: () => {
317
+ require_state.batch(() => {
318
+ setCurrent({
319
+ state: "active",
320
+ phase: "hovering",
321
+ isPromptMode: false,
322
+ isPendingDismiss: false
323
+ });
324
+ setStore("activationTimestamp", Date.now());
325
+ setStore("previouslyFocusedElement", document.activeElement);
326
+ });
327
+ },
328
+ deactivate: () => {
329
+ require_state.batch(() => {
330
+ setCurrent({ state: "idle" });
331
+ setStore(produce((draft) => {
332
+ draft.wasActivatedByToggle = false;
333
+ draft.pendingCommentMode = false;
334
+ draft.inputText = "";
335
+ draft.frozenElement = null;
336
+ draft.frozenElements = [];
337
+ draft.frozenDragRect = null;
338
+ draft.activationTimestamp = null;
339
+ draft.previouslyFocusedElement = null;
340
+ draft.contextMenuPosition = null;
341
+ draft.contextMenuElement = null;
342
+ draft.contextMenuClickOffset = null;
343
+ draft.lastCopiedElement = null;
344
+ }));
345
+ });
346
+ },
347
+ toggle: () => {
348
+ if (store.activationTimestamp !== null) actions.deactivate();
349
+ else {
350
+ setStore("wasActivatedByToggle", true);
351
+ actions.activate();
352
+ }
353
+ },
354
+ freeze: () => {
355
+ if (current().state === "active") {
356
+ const elementToFreeze = store.frozenElement ?? store.detectedElement;
357
+ if (elementToFreeze) setStore("frozenElement", elementToFreeze);
358
+ setActivePhase("frozen");
359
+ }
360
+ },
361
+ unfreeze: () => {
362
+ if (current().state === "active") require_state.batch(() => {
363
+ setStore(produce((draft) => {
364
+ draft.frozenElement = null;
365
+ draft.frozenElements = [];
366
+ draft.frozenDragRect = null;
367
+ }));
368
+ setActivePhase("hovering");
369
+ });
370
+ },
371
+ startDrag: (position, shouldPreserveFrozenElements) => {
372
+ if (current().state === "active") require_state.batch(() => {
373
+ if (!shouldPreserveFrozenElements) clearFrozenElement();
374
+ setStore("dragStart", {
375
+ x: position.x + window.scrollX,
376
+ y: position.y + window.scrollY
377
+ });
378
+ setActivePhase("dragging-select");
379
+ });
380
+ },
381
+ startDragReposition: () => {
382
+ const currentState = current();
383
+ if (currentState.state === "active" && currentState.phase === "dragging-select") setActivePhase("dragging-reposition");
384
+ },
385
+ stopDragReposition: () => {
386
+ const currentState = current();
387
+ if (currentState.state === "active" && currentState.phase === "dragging-reposition") setActivePhase("dragging-select");
388
+ },
389
+ shiftDragStart: (delta) => {
390
+ const currentState = current();
391
+ if (currentState.state === "active" && currentState.phase === "dragging-reposition") setStore("dragStart", (dragStart) => ({
392
+ x: dragStart.x + delta.x,
393
+ y: dragStart.y + delta.y
394
+ }));
395
+ },
396
+ endDrag: () => {
397
+ const currentState = current();
398
+ if (currentState.state === "active" && (currentState.phase === "dragging-select" || currentState.phase === "dragging-reposition")) require_state.batch(() => {
399
+ setStore("dragStart", {
400
+ x: require_freeze_updates.OFFSCREEN_POSITION,
401
+ y: require_freeze_updates.OFFSCREEN_POSITION
402
+ });
403
+ setActivePhase("justDragged");
404
+ });
405
+ },
406
+ cancelDrag: () => {
407
+ const currentState = current();
408
+ if (currentState.state === "active" && (currentState.phase === "dragging-select" || currentState.phase === "dragging-reposition")) require_state.batch(() => {
409
+ setStore("dragStart", {
410
+ x: require_freeze_updates.OFFSCREEN_POSITION,
411
+ y: require_freeze_updates.OFFSCREEN_POSITION
412
+ });
413
+ setActivePhase("hovering");
414
+ });
415
+ },
416
+ finishJustDragged: () => {
417
+ const currentState = current();
418
+ if (currentState.state === "active" && currentState.phase === "justDragged") setActivePhase("hovering");
419
+ },
420
+ startCopy: () => {
421
+ const wasActive = current().state === "active";
422
+ setCurrent({
423
+ state: "copying",
424
+ startedAt: Date.now(),
425
+ wasActive
426
+ });
427
+ },
428
+ completeCopy: (element) => {
429
+ const currentState = current();
430
+ const wasActive = currentState.state === "copying" ? currentState.wasActive : false;
431
+ require_state.batch(() => {
432
+ if (element) setStore("lastCopiedElement", element);
433
+ setCurrent({
434
+ state: "justCopied",
435
+ copiedAt: Date.now(),
436
+ wasActive
437
+ });
438
+ });
439
+ },
440
+ finishJustCopied: () => {
441
+ const currentState = current();
442
+ if (currentState.state === "justCopied") if (currentState.wasActive && !store.wasActivatedByToggle) require_state.batch(() => {
443
+ clearFrozenElement();
444
+ setCurrent({
445
+ state: "active",
446
+ phase: "hovering",
447
+ isPromptMode: false,
448
+ isPendingDismiss: false
449
+ });
450
+ });
451
+ else actions.deactivate();
452
+ },
453
+ enterPromptMode: (position, element) => {
454
+ const { x: selectionCenterX } = getBoundsCenter(createElementBounds(element));
455
+ require_state.batch(() => {
456
+ setStore("copyStart", position);
457
+ setStore("copyOffsetFromCenterX", position.x - selectionCenterX);
458
+ setPointer(position);
459
+ setStore("frozenElement", element);
460
+ setStore("wasActivatedByToggle", true);
461
+ if (current().state !== "active") {
462
+ setCurrent({
463
+ state: "active",
464
+ phase: "frozen",
465
+ isPromptMode: true,
466
+ isPendingDismiss: false
467
+ });
468
+ setStore("activationTimestamp", Date.now());
469
+ setStore("previouslyFocusedElement", document.activeElement);
470
+ } else setCurrent((prev) => prev.state === "active" ? {
471
+ ...prev,
472
+ isPromptMode: true,
473
+ phase: "frozen"
474
+ } : prev);
475
+ });
476
+ },
477
+ exitPromptMode: () => {
478
+ setCurrent((prev) => prev.state === "active" ? {
479
+ ...prev,
480
+ isPromptMode: false,
481
+ isPendingDismiss: false
482
+ } : prev);
483
+ },
484
+ setInputText: (value) => {
485
+ setStore("inputText", value);
486
+ },
487
+ clearInputText: () => {
488
+ setStore("inputText", "");
489
+ },
490
+ setPendingDismiss: (value) => {
491
+ setCurrent((prev) => prev.state === "active" ? {
492
+ ...prev,
493
+ isPendingDismiss: value
494
+ } : prev);
495
+ },
496
+ setPointer: (position) => {
497
+ setPointer(position);
498
+ },
499
+ setDetectedElement: (element) => {
500
+ setStore("detectedElement", element);
501
+ },
502
+ setFrozenElement: (element) => {
503
+ updateFrozenElements((draft) => {
504
+ draft.frozenElements = [element];
505
+ });
506
+ },
507
+ setFrozenElements: (elements) => {
508
+ updateFrozenElements((draft) => {
509
+ draft.frozenElements = elements;
510
+ });
511
+ },
512
+ toggleFrozenElement: (element) => {
513
+ updateFrozenElements((draft) => {
514
+ const existingIndex = draft.frozenElements.indexOf(element);
515
+ if (existingIndex >= 0) draft.frozenElements.splice(existingIndex, 1);
516
+ else draft.frozenElements.push(element);
517
+ });
518
+ },
519
+ addFrozenElements: (elements) => {
520
+ updateFrozenElements((draft) => {
521
+ for (const incomingElement of elements) if (!draft.frozenElements.includes(incomingElement)) draft.frozenElements.push(incomingElement);
522
+ });
523
+ },
524
+ setFrozenDragRect: (rect) => {
525
+ setStore("frozenDragRect", rect);
526
+ },
527
+ setCopyStart: (position, element) => {
528
+ const { x: selectionCenterX } = getBoundsCenter(createElementBounds(element));
529
+ setStore("copyStart", position);
530
+ setStore("copyOffsetFromCenterX", position.x - selectionCenterX);
531
+ },
532
+ setLastGrabbed: (element) => {
533
+ setStore("lastGrabbedElement", element);
534
+ },
535
+ clearLastCopied: () => {
536
+ setStore("lastCopiedElement", null);
537
+ },
538
+ setWasActivatedByToggle: (value) => {
539
+ setStore("wasActivatedByToggle", value);
540
+ },
541
+ setPendingCommentMode: (value) => {
542
+ setStore("pendingCommentMode", value);
543
+ },
544
+ setTouchMode: (value) => {
545
+ setStore("isTouchMode", value);
546
+ },
547
+ incrementSelectionInteractionLockDepth: () => {
548
+ setStore("selectionInteractionLockDepth", (currentLockDepth) => currentLockDepth + 1);
549
+ },
550
+ decrementSelectionInteractionLockDepth: () => {
551
+ setStore("selectionInteractionLockDepth", (currentLockDepth) => Math.max(0, currentLockDepth - 1));
552
+ },
553
+ setSelectionSource: (filePath, lineNumber) => {
554
+ require_state.batch(() => {
555
+ setStore("selectionFilePath", filePath);
556
+ setStore("selectionLineNumber", lineNumber);
557
+ });
558
+ },
559
+ incrementViewportVersion: () => {
560
+ setViewportVersion((version) => version + 1);
561
+ },
562
+ addGrabbedBox: (box) => {
563
+ setStore("grabbedBoxes", (boxes) => [...boxes, box]);
564
+ },
565
+ removeGrabbedBox: (boxId) => {
566
+ setStore("grabbedBoxes", (boxes) => boxes.filter((box) => box.id !== boxId));
567
+ },
568
+ clearGrabbedBoxes: () => {
569
+ setStore("grabbedBoxes", []);
570
+ },
571
+ addLabelInstance: (instance) => {
572
+ setStore("labelInstances", (instances) => [...instances, instance]);
573
+ },
574
+ updateLabelInstance: (instanceId, status, errorMessage) => {
575
+ const index = store.labelInstances.findIndex((instance) => instance.id === instanceId);
576
+ if (index !== -1) require_state.batch(() => {
577
+ setStore("labelInstances", index, "status", status);
578
+ if (errorMessage !== void 0) setStore("labelInstances", index, "errorMessage", errorMessage);
579
+ });
580
+ },
581
+ removeLabelInstance: (instanceId) => {
582
+ setStore("labelInstances", (instances) => instances.filter((instance) => instance.id !== instanceId));
583
+ },
584
+ clearLabelInstances: () => {
585
+ setStore("labelInstances", []);
586
+ },
587
+ showContextMenu: (position, element) => {
588
+ const { x: centerX, y: centerY } = getBoundsCenter(createElementBounds(element));
589
+ require_state.batch(() => {
590
+ setStore("contextMenuPosition", position);
591
+ setStore("contextMenuElement", element);
592
+ setStore("contextMenuClickOffset", {
593
+ x: position.x - centerX,
594
+ y: position.y - centerY
595
+ });
596
+ });
597
+ },
598
+ hideContextMenu: () => {
599
+ require_state.batch(() => {
600
+ setStore("contextMenuPosition", null);
601
+ setStore("contextMenuElement", null);
602
+ setStore("contextMenuClickOffset", null);
603
+ });
604
+ },
605
+ updateContextMenuPosition: () => {
606
+ const element = store.contextMenuElement;
607
+ const clickOffset = store.contextMenuClickOffset;
608
+ if (!element || !clickOffset) return;
609
+ if (!require_state.isElementConnected(element)) return;
610
+ const { x: newCenterX, y: newCenterY } = getBoundsCenter(createElementBounds(element));
611
+ setStore("contextMenuPosition", {
612
+ x: newCenterX + clickOffset.x,
613
+ y: newCenterY + clickOffset.y
614
+ });
615
+ }
616
+ };
617
+ return {
618
+ store,
619
+ actions,
620
+ pointer,
621
+ viewportVersion,
622
+ current
623
+ };
624
+ };
625
+
626
+ //#endregion
627
+ //#region src/utils/mount-root.ts
628
+ const ATTRIBUTE_NAME = "data-react-grab";
629
+ const FONT_IMPORT = "@import url(\"https://fonts.googleapis.com/css2?family=Geist:wght@500&display=swap\");";
630
+ const attachHostToBody = (host) => {
631
+ if (!document.body) return;
632
+ const candidateHosts = document.querySelectorAll(`[${ATTRIBUTE_NAME}]`);
633
+ for (const candidate of candidateHosts) {
634
+ if (candidate === host) continue;
635
+ if (candidate.parentNode === host) continue;
636
+ if (!candidate.shadowRoot) candidate.remove();
637
+ }
638
+ document.body.appendChild(host);
639
+ };
640
+ const scheduleHostAttachment = (host) => {
641
+ if (document.body) {
642
+ attachHostToBody(host);
643
+ return;
644
+ }
645
+ const onReady = () => {
646
+ document.removeEventListener("DOMContentLoaded", onReady);
647
+ attachHostToBody(host);
648
+ };
649
+ document.addEventListener("DOMContentLoaded", onReady, { once: true });
650
+ };
651
+ const mountRoot = (cssText) => {
652
+ const mountedHosts = document.querySelectorAll(`[${ATTRIBUTE_NAME}]`);
653
+ for (const mountedHost of mountedHosts) {
654
+ const mountedRoot = mountedHost.shadowRoot?.querySelector(`[${ATTRIBUTE_NAME}]`);
655
+ if (mountedRoot instanceof HTMLDivElement) return {
656
+ root: mountedRoot,
657
+ host: mountedHost
658
+ };
659
+ mountedHost.remove();
660
+ }
661
+ const host = document.createElement("div");
662
+ host.setAttribute(ATTRIBUTE_NAME, "true");
663
+ require_freeze_updates.hideFromThirdParties(host);
664
+ host.style.zIndex = String(require_freeze_updates.Z_INDEX_OVERLAY);
665
+ host.style.position = "fixed";
666
+ host.style.inset = "0";
667
+ host.style.pointerEvents = "none";
668
+ host.style.contain = "strict";
669
+ const shadowRoot = host.attachShadow({ mode: "open" });
670
+ const styleElement = document.createElement("style");
671
+ const nonce = require_freeze_updates.detectCspNonce();
672
+ if (nonce) styleElement.nonce = nonce;
673
+ styleElement.textContent = `${FONT_IMPORT}\n${cssText ?? ""}`;
674
+ shadowRoot.appendChild(styleElement);
675
+ const root = document.createElement("div");
676
+ root.setAttribute(ATTRIBUTE_NAME, "true");
677
+ shadowRoot.appendChild(root);
678
+ scheduleHostAttachment(host);
679
+ setTimeout(() => {
680
+ attachHostToBody(host);
681
+ }, require_freeze_updates.MOUNT_ROOT_RECHECK_DELAY_MS);
682
+ return {
683
+ root,
684
+ host
685
+ };
686
+ };
687
+
688
+ //#endregion
689
+ //#region src/utils/detect-app-theme.ts
690
+ const THEME_ATTRIBUTES = [
691
+ "data-theme",
692
+ "data-mode",
693
+ "data-color-scheme",
694
+ "data-bs-theme",
695
+ "data-mui-color-scheme"
696
+ ];
697
+ const PRESENCE_ATTRIBUTES = [{
698
+ attribute: "data-dark",
699
+ theme: "dark"
700
+ }, {
701
+ attribute: "data-light",
702
+ theme: "light"
703
+ }];
704
+ const LUMINANCE_DARK_THRESHOLD = .18;
705
+ const RGB_PATTERN = /rgba?\(\s*(\d+(?:\.\d+)?)\s*[,\s]\s*(\d+(?:\.\d+)?)\s*[,\s]\s*(\d+(?:\.\d+)?)(?:\s*[,/]\s*(\d+(?:\.\d+)?))?\s*\)/;
706
+ const isTransparent = (backgroundColor) => {
707
+ if (backgroundColor === "transparent") return true;
708
+ const rgbMatch = backgroundColor.match(RGB_PATTERN);
709
+ if (!rgbMatch) return false;
710
+ const alpha = rgbMatch[4];
711
+ return alpha !== void 0 && Number(alpha) === 0;
712
+ };
713
+ const relativeLuminance = (red, green, blue) => {
714
+ const [linearRed, linearGreen, linearBlue] = [
715
+ red,
716
+ green,
717
+ blue
718
+ ].map((channel) => {
719
+ const normalized = channel / 255;
720
+ return normalized <= .03928 ? normalized / 12.92 : ((normalized + .055) / 1.055) ** 2.4;
721
+ });
722
+ return .2126 * linearRed + .7152 * linearGreen + .0722 * linearBlue;
723
+ };
724
+ const themeFromBackgroundLuminance = () => {
725
+ const target = document.body ?? document.documentElement;
726
+ const backgroundColor = getComputedStyle(target).backgroundColor;
727
+ if (!backgroundColor || isTransparent(backgroundColor)) return null;
728
+ const rgbMatch = backgroundColor.match(RGB_PATTERN);
729
+ if (!rgbMatch) return null;
730
+ return relativeLuminance(Number(rgbMatch[1]), Number(rgbMatch[2]), Number(rgbMatch[3])) < LUMINANCE_DARK_THRESHOLD ? "dark" : "light";
731
+ };
732
+ const themeFromAttributeValue = (attributeValue) => {
733
+ const normalized = attributeValue.toLowerCase();
734
+ if (normalized === "dark") return "dark";
735
+ if (normalized === "light") return "light";
736
+ return null;
737
+ };
738
+ const themeFromColorScheme = (colorSchemeValue) => {
739
+ const normalized = colorSchemeValue.trim().toLowerCase();
740
+ if (!normalized || normalized === "normal" || normalized === "auto") return null;
741
+ return normalized.split(/\s+/).find((token) => token === "dark" || token === "light") ?? null;
742
+ };
743
+ const detectTheme = () => {
744
+ const htmlElement = document.documentElement;
745
+ if (htmlElement.classList.contains("dark")) return "dark";
746
+ if (htmlElement.classList.contains("light")) return "light";
747
+ for (const attributeName of THEME_ATTRIBUTES) {
748
+ const attributeValue = htmlElement.getAttribute(attributeName);
749
+ if (!attributeValue) continue;
750
+ const result = themeFromAttributeValue(attributeValue);
751
+ if (result) return result;
752
+ }
753
+ for (const { attribute, theme } of PRESENCE_ATTRIBUTES) if (htmlElement.hasAttribute(attribute)) return theme;
754
+ const colorSchemeProperty = htmlElement.style.colorScheme || getComputedStyle(htmlElement).colorScheme;
755
+ if (colorSchemeProperty) {
756
+ const result = themeFromColorScheme(colorSchemeProperty);
757
+ if (result) return result;
758
+ }
759
+ const luminanceResult = themeFromBackgroundLuminance();
760
+ if (luminanceResult) return luminanceResult;
761
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
762
+ };
763
+ const invertTheme = (theme) => theme === "dark" ? "light" : "dark";
764
+ const OBSERVER_OPTIONS = {
765
+ attributes: true,
766
+ attributeFilter: [
767
+ "class",
768
+ "style",
769
+ ...THEME_ATTRIBUTES,
770
+ ...PRESENCE_ATTRIBUTES.map(({ attribute }) => attribute)
771
+ ]
772
+ };
773
+ const watchAppTheme = (host, onChange) => {
774
+ let lastAppliedTheme = null;
775
+ let pendingFrame = null;
776
+ const applyTheme = () => {
777
+ const reactGrabTheme = invertTheme(detectTheme());
778
+ if (reactGrabTheme !== lastAppliedTheme) {
779
+ lastAppliedTheme = reactGrabTheme;
780
+ host.setAttribute("data-rg-theme", reactGrabTheme);
781
+ onChange?.(reactGrabTheme);
782
+ }
783
+ return reactGrabTheme;
784
+ };
785
+ const scheduleApplyTheme = () => {
786
+ if (pendingFrame !== null) return;
787
+ pendingFrame = require_freeze_updates.nativeRequestAnimationFrame(() => {
788
+ pendingFrame = null;
789
+ applyTheme();
790
+ });
791
+ };
792
+ const initialTheme = applyTheme();
793
+ const observer = new MutationObserver(scheduleApplyTheme);
794
+ observer.observe(document.documentElement, OBSERVER_OPTIONS);
795
+ let bodyObserver = null;
796
+ if (document.body) observer.observe(document.body, OBSERVER_OPTIONS);
797
+ else {
798
+ bodyObserver = new MutationObserver(() => {
799
+ if (!document.body) return;
800
+ bodyObserver.disconnect();
801
+ bodyObserver = null;
802
+ observer.observe(document.body, OBSERVER_OPTIONS);
803
+ applyTheme();
804
+ });
805
+ bodyObserver.observe(document.documentElement, { childList: true });
806
+ }
807
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
808
+ mediaQuery.addEventListener("change", scheduleApplyTheme);
809
+ return {
810
+ theme: initialTheme,
811
+ cleanup: () => {
812
+ bodyObserver?.disconnect();
813
+ observer.disconnect();
814
+ mediaQuery.removeEventListener("change", scheduleApplyTheme);
815
+ if (pendingFrame !== null) require_freeze_updates.nativeCancelAnimationFrame(pendingFrame);
816
+ }
817
+ };
818
+ };
819
+
820
+ //#endregion
821
+ //#region src/core/noop-api.ts
822
+ const NOOP = () => {};
823
+ const createNoopApi = () => ({
824
+ activate: NOOP,
825
+ deactivate: NOOP,
826
+ toggle: NOOP,
827
+ comment: NOOP,
828
+ isActive: () => false,
829
+ isEnabled: () => false,
830
+ setEnabled: NOOP,
831
+ getToolbarState: () => null,
832
+ setToolbarState: NOOP,
833
+ onToolbarStateChange: () => NOOP,
834
+ dispose: NOOP,
835
+ copyElement: () => Promise.resolve(false),
836
+ getSource: () => Promise.resolve(null),
837
+ getStackContext: () => Promise.resolve(""),
838
+ getState: () => ({
839
+ isActive: false,
840
+ isDragging: false,
841
+ isCopying: false,
842
+ isPromptMode: false,
843
+ isSelectionBoxVisible: false,
844
+ isDragBoxVisible: false,
845
+ targetElement: null,
846
+ dragBounds: null,
847
+ grabbedBoxes: [],
848
+ labelInstances: [],
849
+ selectionFilePath: null,
850
+ toolbarState: null
851
+ }),
852
+ setOptions: NOOP,
853
+ registerPlugin: NOOP,
854
+ unregisterPlugin: NOOP,
855
+ getPlugins: () => [],
856
+ getDisplayName: () => null
857
+ });
858
+
859
+ //#endregion
860
+ //#region src/core/events.ts
861
+ const createEventListenerManager = () => {
862
+ const abortController = new AbortController();
863
+ const addWindowListener = (type, listener, options = {}) => {
864
+ window.addEventListener(type, listener, {
865
+ ...options,
866
+ signal: abortController.signal
867
+ });
868
+ };
869
+ const addDocumentListener = (type, listener, options = {}) => {
870
+ document.addEventListener(type, listener, {
871
+ ...options,
872
+ signal: abortController.signal
873
+ });
874
+ };
875
+ return {
876
+ signal: abortController.signal,
877
+ abort: () => abortController.abort(),
878
+ addWindowListener,
879
+ addDocumentListener
880
+ };
881
+ };
882
+
883
+ //#endregion
884
+ //#region src/utils/normalize-error.ts
885
+ const normalizeErrorMessage = (error, fallback = "Unknown error") => error instanceof Error && error.message ? error.message : fallback;
886
+ const normalizeError = (error) => error instanceof Error ? error : new Error(String(error));
887
+
888
+ //#endregion
889
+ //#region src/core/copy.ts
890
+ const formatCompactReference = (element, source, isNextProject) => {
891
+ const tagName = require_freeze_updates.getTagName(element);
892
+ const componentName = source?.componentName ?? require_freeze_updates.getComponentDisplayName(element);
893
+ if (!source && !componentName) return `[${require_freeze_updates.getInlineHTMLPreview(element)}]`;
894
+ let identifyingAttrs = "";
895
+ for (const attrName of require_freeze_updates.COMPACT_IDENTIFYING_ATTRS) {
896
+ const attrValue = element.getAttribute(attrName);
897
+ if (attrValue) identifyingAttrs += ` ${attrName}="${attrValue.replaceAll("\"", "'")}"`;
898
+ }
899
+ const sanitizedText = require_freeze_updates.getDirectTextContent(element).replaceAll("\"", "'");
900
+ const textSnippet = sanitizedText ? ` "${require_freeze_updates.truncateString(sanitizedText, 30)}"` : "";
901
+ const parts = [`<${tagName}${identifyingAttrs}>${textSnippet}`];
902
+ if (componentName) parts.push(`in ${componentName}`);
903
+ if (source) {
904
+ const lineReference = isNextProject && source.lineNumber ? `:${source.lineNumber}` : "";
905
+ parts.push(`@${source.filePath}${lineReference}`);
906
+ }
907
+ return `[${parts.join(" ")}]`;
908
+ };
909
+ const buildCompactContent = async (elements) => {
910
+ const isNextProject = require_freeze_updates.checkIsNextProject();
911
+ const resolvedSources = await Promise.all(elements.map(require_freeze_updates.resolveSource));
912
+ const uniqueReferences = new Set(elements.map((element, index) => formatCompactReference(element, resolvedSources[index], isNextProject)));
913
+ return uniqueReferences.size > 0 ? [...uniqueReferences].join("\n") : null;
914
+ };
915
+ const tryCopyWithFallback = async (options, hooks, elements, extraPrompt) => {
916
+ let didCopy = false;
917
+ let copiedContent = "";
918
+ await hooks.onBeforeCopy(elements);
919
+ try {
920
+ const generatedContent = options.getContent ? await options.getContent(elements) : await buildCompactContent(elements);
921
+ if (generatedContent?.trim()) {
922
+ const transformedContent = await hooks.transformCopyContent(generatedContent, elements);
923
+ copiedContent = extraPrompt ? `${extraPrompt}\n${transformedContent}` : transformedContent;
924
+ didCopy = require_create_element_selector.copyContent(copiedContent, { componentName: options.componentName });
925
+ }
926
+ } catch (error) {
927
+ hooks.onCopyError(normalizeError(error));
928
+ }
929
+ if (didCopy) hooks.onCopySuccess(elements, copiedContent);
930
+ hooks.onAfterCopy(elements, didCopy);
931
+ return didCopy;
932
+ };
933
+
934
+ //#endregion
935
+ //#region src/utils/get-elements-in-drag.ts
936
+ const calculateIntersectionArea = (rect1, rect2) => {
937
+ const intersectionLeft = Math.max(rect1.left, rect2.left);
938
+ const intersectionTop = Math.max(rect1.top, rect2.top);
939
+ const intersectionRight = Math.min(rect1.right, rect2.right);
940
+ const intersectionBottom = Math.min(rect1.bottom, rect2.bottom);
941
+ return Math.max(0, intersectionRight - intersectionLeft) * Math.max(0, intersectionBottom - intersectionTop);
942
+ };
943
+ const hasIntersection = (rect1, rect2) => {
944
+ return rect1.left < rect2.right && rect1.right > rect2.left && rect1.top < rect2.bottom && rect1.bottom > rect2.top;
945
+ };
946
+ const sortByDocumentOrder = (elements) => {
947
+ return elements.sort((leftElement, rightElement) => {
948
+ if (leftElement === rightElement) return 0;
949
+ const position = leftElement.compareDocumentPosition(rightElement);
950
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
951
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;
952
+ return 0;
953
+ });
954
+ };
955
+ const createSamplePoints = (dragRect) => {
956
+ if (dragRect.width <= 0 || dragRect.height <= 0) return [];
957
+ const viewportWidth = window.innerWidth;
958
+ const viewportHeight = window.innerHeight;
959
+ const left = dragRect.x;
960
+ const top = dragRect.y;
961
+ const right = dragRect.x + dragRect.width;
962
+ const bottom = dragRect.y + dragRect.height;
963
+ const centerX = left + dragRect.width / 2;
964
+ const centerY = top + dragRect.height / 2;
965
+ const xCount = require_state.clampToRange(Math.ceil(dragRect.width / 32), 3, 20);
966
+ const yCount = require_state.clampToRange(Math.ceil(dragRect.height / 32), 3, 20);
967
+ const totalGridPoints = xCount * yCount;
968
+ const scale = totalGridPoints > 100 ? Math.sqrt(100 / totalGridPoints) : 1;
969
+ const scaledXCount = require_state.clampToRange(Math.floor(xCount * scale), 3, 20);
970
+ const scaledYCount = require_state.clampToRange(Math.floor(yCount * scale), 3, 20);
971
+ const pointKeys = /* @__PURE__ */ new Set();
972
+ const points = [];
973
+ const addPoint = (x, y) => {
974
+ const clampedX = require_state.clampToRange(Math.round(x), 0, viewportWidth - 1);
975
+ const clampedY = require_state.clampToRange(Math.round(y), 0, viewportHeight - 1);
976
+ const key = `${clampedX}:${clampedY}`;
977
+ if (pointKeys.has(key)) return;
978
+ pointKeys.add(key);
979
+ points.push({
980
+ x: clampedX,
981
+ y: clampedY
982
+ });
983
+ };
984
+ addPoint(left + 1, top + 1);
985
+ addPoint(right - 1, top + 1);
986
+ addPoint(left + 1, bottom - 1);
987
+ addPoint(right - 1, bottom - 1);
988
+ addPoint(centerX, top + 1);
989
+ addPoint(centerX, bottom - 1);
990
+ addPoint(left + 1, centerY);
991
+ addPoint(right - 1, centerY);
992
+ addPoint(centerX, centerY);
993
+ for (let xIndex = 0; xIndex < scaledXCount; xIndex += 1) {
994
+ const sampleX = left + (xIndex + .5) / scaledXCount * dragRect.width;
995
+ for (let yIndex = 0; yIndex < scaledYCount; yIndex += 1) addPoint(sampleX, top + (yIndex + .5) / scaledYCount * dragRect.height);
996
+ }
997
+ return points;
998
+ };
999
+ const filterElementsInDrag = (dragRect, isValidGrabbableElement, shouldCheckCoverage) => {
1000
+ const dragBounds = {
1001
+ left: dragRect.x,
1002
+ top: dragRect.y,
1003
+ right: dragRect.x + dragRect.width,
1004
+ bottom: dragRect.y + dragRect.height
1005
+ };
1006
+ const candidates = /* @__PURE__ */ new Set();
1007
+ const samplePoints = createSamplePoints(dragRect);
1008
+ require_freeze_updates.suspendPointerEventsFreeze();
1009
+ try {
1010
+ for (const point of samplePoints) {
1011
+ const elementsAtPoint = document.elementsFromPoint(point.x, point.y);
1012
+ for (const candidateElement of elementsAtPoint) candidates.add(candidateElement);
1013
+ }
1014
+ } finally {
1015
+ require_freeze_updates.resumePointerEventsFreeze();
1016
+ }
1017
+ const validCandidates = [];
1018
+ for (const candidateElement of candidates) {
1019
+ if (!shouldCheckCoverage && require_freeze_updates.isRootElement(candidateElement)) continue;
1020
+ if (!isValidGrabbableElement(candidateElement)) continue;
1021
+ validCandidates.push(candidateElement);
1022
+ }
1023
+ const candidateRects = /* @__PURE__ */ new Map();
1024
+ for (const candidateElement of validCandidates) candidateRects.set(candidateElement, candidateElement.getBoundingClientRect());
1025
+ const matchingElements = [];
1026
+ for (const candidateElement of validCandidates) {
1027
+ const elementRect = candidateRects.get(candidateElement);
1028
+ if (elementRect.width <= 0 || elementRect.height <= 0) continue;
1029
+ const elementBounds = {
1030
+ left: elementRect.left,
1031
+ top: elementRect.top,
1032
+ right: elementRect.left + elementRect.width,
1033
+ bottom: elementRect.top + elementRect.height
1034
+ };
1035
+ if (shouldCheckCoverage) {
1036
+ const intersectionArea = calculateIntersectionArea(dragBounds, elementBounds);
1037
+ const elementArea = elementRect.width * elementRect.height;
1038
+ if (elementArea > 0 && intersectionArea / elementArea >= .75) matchingElements.push(candidateElement);
1039
+ } else if (hasIntersection(elementBounds, dragBounds)) matchingElements.push(candidateElement);
1040
+ }
1041
+ return sortByDocumentOrder(matchingElements);
1042
+ };
1043
+ const removeNestedElements = (elements) => {
1044
+ return elements.filter((element) => {
1045
+ return !elements.some((otherElement) => otherElement !== element && otherElement.contains(element));
1046
+ });
1047
+ };
1048
+ const getElementsInDrag = (dragRect, isValidGrabbableElement, shouldCheckCoverage = true) => {
1049
+ return removeNestedElements(filterElementsInDrag(dragRect, isValidGrabbableElement, shouldCheckCoverage));
1050
+ };
1051
+
1052
+ //#endregion
1053
+ //#region src/utils/get-element-anchor-ratio.ts
1054
+ const getElementAnchorRatio = (bounds, pointer) => {
1055
+ if (bounds.width <= 0) return 0;
1056
+ return require_state.clampToRange((pointer.x - bounds.x) / bounds.width, 0, 1);
1057
+ };
1058
+
1059
+ //#endregion
1060
+ //#region src/utils/get-visible-bounds-center.ts
1061
+ const getVisibleBoundsCenter = (bounds) => {
1062
+ const viewportWidth = window.innerWidth;
1063
+ const viewportHeight = window.innerHeight;
1064
+ const visibleLeft = Math.max(0, bounds.x);
1065
+ const visibleRight = Math.min(viewportWidth, bounds.x + bounds.width);
1066
+ const visibleTop = Math.max(0, bounds.y);
1067
+ const visibleBottom = Math.min(viewportHeight, bounds.y + bounds.height);
1068
+ return {
1069
+ x: (visibleLeft + visibleRight) / 2,
1070
+ y: (visibleTop + visibleBottom) / 2
1071
+ };
1072
+ };
1073
+
1074
+ //#endregion
1075
+ //#region src/utils/invalidate-interaction-caches.ts
1076
+ const invalidateInteractionCaches = () => {
1077
+ invalidateBoundsCache();
1078
+ require_freeze_updates.clearElementPositionCache();
1079
+ require_freeze_updates.clearVisibilityCache();
1080
+ };
1081
+
1082
+ //#endregion
1083
+ //#region src/utils/create-bounds-from-drag-rect.ts
1084
+ const createBoundsFromDragRect = (dragRect) => ({
1085
+ x: dragRect.pageX - window.scrollX,
1086
+ y: dragRect.pageY - window.scrollY,
1087
+ width: dragRect.width,
1088
+ height: dragRect.height,
1089
+ borderRadius: "0px",
1090
+ transform: "none"
1091
+ });
1092
+ const createPageRectFromBounds = (bounds) => ({
1093
+ pageX: bounds.x + window.scrollX,
1094
+ pageY: bounds.y + window.scrollY,
1095
+ width: bounds.width,
1096
+ height: bounds.height
1097
+ });
1098
+ const createFlatOverlayBounds = (bounds) => ({
1099
+ ...bounds,
1100
+ borderRadius: "0px",
1101
+ transform: "none"
1102
+ });
1103
+
1104
+ //#endregion
1105
+ //#region src/utils/is-c-like-key.ts
1106
+ const C_LIKE_CHARACTERS = new Set([
1107
+ "c",
1108
+ "C",
1109
+ "с",
1110
+ "С",
1111
+ "ȼ",
1112
+ "Ȼ",
1113
+ "ↄ",
1114
+ "Ↄ",
1115
+ "ᴄ",
1116
+ "ᶜ",
1117
+ "ⱼ",
1118
+ "ⅽ",
1119
+ "Ⅽ",
1120
+ "ç",
1121
+ "Ç",
1122
+ "ć",
1123
+ "Ć",
1124
+ "č",
1125
+ "Č",
1126
+ "ĉ",
1127
+ "Ĉ",
1128
+ "ċ",
1129
+ "Ċ"
1130
+ ]);
1131
+ const isCLikeKey = (key, code) => {
1132
+ if (code === "KeyC") return true;
1133
+ if (!key || key.length !== 1) return false;
1134
+ return C_LIKE_CHARACTERS.has(key);
1135
+ };
1136
+
1137
+ //#endregion
1138
+ //#region src/utils/key-matches-code.ts
1139
+ const keyMatchesCode = (targetKey, code) => {
1140
+ if (!targetKey || !code) return false;
1141
+ const normalizedTarget = targetKey.toLowerCase();
1142
+ if (code === "Space") return normalizedTarget === "space" || normalizedTarget === " ";
1143
+ if (code.startsWith("Key")) return code.slice(3).toLowerCase() === normalizedTarget;
1144
+ if (code.startsWith("Digit")) return code.slice(5) === normalizedTarget;
1145
+ return false;
1146
+ };
1147
+
1148
+ //#endregion
1149
+ //#region src/utils/parse-activation-key.ts
1150
+ const MODIFIER_MAP = {
1151
+ meta: "metaKey",
1152
+ cmd: "metaKey",
1153
+ command: "metaKey",
1154
+ win: "metaKey",
1155
+ windows: "metaKey",
1156
+ ctrl: "ctrlKey",
1157
+ control: "ctrlKey",
1158
+ shift: "shiftKey",
1159
+ alt: "altKey",
1160
+ option: "altKey",
1161
+ opt: "altKey"
1162
+ };
1163
+ const parseString = (shortcut) => {
1164
+ const parts = shortcut.split("+").map((part) => part.trim().toLowerCase());
1165
+ const result = {
1166
+ metaKey: false,
1167
+ ctrlKey: false,
1168
+ shiftKey: false,
1169
+ altKey: false,
1170
+ key: null
1171
+ };
1172
+ for (const part of parts) {
1173
+ const modifierKey = MODIFIER_MAP[part];
1174
+ if (modifierKey) result[modifierKey] = true;
1175
+ else result.key = part;
1176
+ }
1177
+ return result;
1178
+ };
1179
+ const parseActivationKey = (activationKey) => {
1180
+ if (typeof activationKey === "function") return activationKey;
1181
+ const parsed = parseString(activationKey);
1182
+ const targetKey = parsed.key;
1183
+ return (event) => {
1184
+ if (targetKey === null) {
1185
+ const metaMatches = parsed.metaKey ? event.metaKey || event.key === "Meta" : true;
1186
+ const ctrlMatches = parsed.ctrlKey ? event.ctrlKey || event.key === "Control" : true;
1187
+ const shiftMatches = parsed.shiftKey ? event.shiftKey || event.key === "Shift" : true;
1188
+ const altMatches = parsed.altKey ? event.altKey || event.key === "Alt" : true;
1189
+ const allRequiredModifiersPressed = metaMatches && ctrlMatches && shiftMatches && altMatches;
1190
+ const requiredModifierCount = [
1191
+ parsed.metaKey,
1192
+ parsed.ctrlKey,
1193
+ parsed.shiftKey,
1194
+ parsed.altKey
1195
+ ].filter(Boolean).length;
1196
+ const pressedModifierCount = [
1197
+ event.metaKey || event.key === "Meta",
1198
+ event.ctrlKey || event.key === "Control",
1199
+ event.shiftKey || event.key === "Shift",
1200
+ event.altKey || event.key === "Alt"
1201
+ ].filter(Boolean).length;
1202
+ return allRequiredModifiersPressed && pressedModifierCount >= requiredModifierCount;
1203
+ }
1204
+ const keyMatches = event.key?.toLowerCase() === targetKey || keyMatchesCode(targetKey, event.code);
1205
+ const modifiersMatch = parsed.metaKey || parsed.ctrlKey || parsed.shiftKey || parsed.altKey ? (parsed.metaKey ? event.metaKey : true) && (parsed.ctrlKey ? event.ctrlKey : true) && (parsed.shiftKey ? event.shiftKey : true) && (parsed.altKey ? event.altKey : true) : !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
1206
+ return keyMatches && modifiersMatch;
1207
+ };
1208
+ };
1209
+ const getModifiersFromActivationKey = (activationKey) => {
1210
+ if (!activationKey || typeof activationKey === "function") return {
1211
+ metaKey: require_state.isMac(),
1212
+ ctrlKey: !require_state.isMac(),
1213
+ shiftKey: false,
1214
+ altKey: false,
1215
+ key: null
1216
+ };
1217
+ return parseString(activationKey);
1218
+ };
1219
+
1220
+ //#endregion
1221
+ //#region src/utils/is-target-key-combination.ts
1222
+ const isTargetKeyCombination = (event, options) => {
1223
+ if (options.activationKey) return parseActivationKey(options.activationKey)(event);
1224
+ const hasOnlyPlatformModifier = (require_state.isMac() ? event.metaKey : event.ctrlKey) && !event.shiftKey && !event.altKey;
1225
+ return Boolean(event.key && hasOnlyPlatformModifier && isCLikeKey(event.key, event.code));
1226
+ };
1227
+
1228
+ //#endregion
1229
+ //#region src/utils/combine-bounds.ts
1230
+ const combineBounds = (boundsList) => {
1231
+ if (boundsList.length === 0) return {
1232
+ x: 0,
1233
+ y: 0,
1234
+ width: 0,
1235
+ height: 0
1236
+ };
1237
+ if (boundsList.length === 1) return boundsList[0];
1238
+ let minX = Infinity;
1239
+ let minY = Infinity;
1240
+ let maxX = -Infinity;
1241
+ let maxY = -Infinity;
1242
+ for (const bounds of boundsList) {
1243
+ minX = Math.min(minX, bounds.x);
1244
+ minY = Math.min(minY, bounds.y);
1245
+ maxX = Math.max(maxX, bounds.x + bounds.width);
1246
+ maxY = Math.max(maxY, bounds.y + bounds.height);
1247
+ }
1248
+ return {
1249
+ x: minX,
1250
+ y: minY,
1251
+ width: maxX - minX,
1252
+ height: maxY - minY
1253
+ };
1254
+ };
1255
+
1256
+ //#endregion
1257
+ //#region src/core/theme.ts
1258
+ const DEFAULT_THEME = {
1259
+ enabled: true,
1260
+ hue: 0,
1261
+ selectionBox: { enabled: true },
1262
+ dragBox: { enabled: true },
1263
+ grabbedBoxes: { enabled: true },
1264
+ elementLabel: { enabled: true },
1265
+ toolbar: { enabled: true }
1266
+ };
1267
+ const deepMergeTheme = (baseTheme, partialTheme) => ({
1268
+ enabled: partialTheme.enabled ?? baseTheme.enabled,
1269
+ hue: partialTheme.hue ?? baseTheme.hue,
1270
+ selectionBox: { enabled: partialTheme.selectionBox?.enabled ?? baseTheme.selectionBox.enabled },
1271
+ dragBox: { enabled: partialTheme.dragBox?.enabled ?? baseTheme.dragBox.enabled },
1272
+ grabbedBoxes: { enabled: partialTheme.grabbedBoxes?.enabled ?? baseTheme.grabbedBoxes.enabled },
1273
+ elementLabel: { enabled: partialTheme.elementLabel?.enabled ?? baseTheme.elementLabel.enabled },
1274
+ toolbar: { enabled: partialTheme.toolbar?.enabled ?? baseTheme.toolbar.enabled }
1275
+ });
1276
+
1277
+ //#endregion
1278
+ //#region src/core/plugin-registry.ts
1279
+ const DEFAULT_OPTIONS = {
1280
+ activationMode: "toggle",
1281
+ keyHoldDuration: 100,
1282
+ allowActivationInsideInput: true,
1283
+ activationKey: void 0,
1284
+ getContent: void 0,
1285
+ freezeReactUpdates: true
1286
+ };
1287
+ const createPluginRegistry = (initialOptions = {}) => {
1288
+ const plugins = /* @__PURE__ */ new Map();
1289
+ const directOptionOverrides = {};
1290
+ const [store, setStore] = createStore({
1291
+ theme: DEFAULT_THEME,
1292
+ options: {
1293
+ ...DEFAULT_OPTIONS,
1294
+ ...initialOptions
1295
+ },
1296
+ actions: []
1297
+ });
1298
+ const recomputeStore = () => {
1299
+ let mergedTheme = DEFAULT_THEME;
1300
+ let mergedOptions = {
1301
+ ...DEFAULT_OPTIONS,
1302
+ ...initialOptions
1303
+ };
1304
+ const allContextMenuActions = [];
1305
+ for (const { config } of plugins.values()) {
1306
+ if (config.theme) mergedTheme = deepMergeTheme(mergedTheme, config.theme);
1307
+ if (config.options) mergedOptions = {
1308
+ ...mergedOptions,
1309
+ ...config.options
1310
+ };
1311
+ if (config.actions) for (const action of config.actions) allContextMenuActions.push(action);
1312
+ }
1313
+ mergedOptions = {
1314
+ ...mergedOptions,
1315
+ ...directOptionOverrides
1316
+ };
1317
+ setStore("theme", mergedTheme);
1318
+ setStore("options", mergedOptions);
1319
+ setStore("actions", allContextMenuActions);
1320
+ };
1321
+ const setOption = (optionKey, optionValue) => {
1322
+ directOptionOverrides[optionKey] = optionValue;
1323
+ setStore("options", optionKey, optionValue);
1324
+ };
1325
+ const SETTABLE_OPTION_KEYS = [
1326
+ "activationMode",
1327
+ "keyHoldDuration",
1328
+ "allowActivationInsideInput",
1329
+ "activationKey",
1330
+ "getContent",
1331
+ "freezeReactUpdates"
1332
+ ];
1333
+ const setOptions = (optionUpdates) => {
1334
+ for (const optionKey of SETTABLE_OPTION_KEYS) if (optionUpdates[optionKey] !== void 0) setOption(optionKey, optionUpdates[optionKey]);
1335
+ };
1336
+ const register = (plugin, api) => {
1337
+ if (plugins.has(plugin.name)) unregister(plugin.name);
1338
+ const config = plugin.setup?.(api, hooks) ?? {};
1339
+ if (plugin.theme) config.theme = config.theme ? deepMergeTheme(deepMergeTheme(DEFAULT_THEME, plugin.theme), config.theme) : plugin.theme;
1340
+ if (plugin.actions) config.actions = [...plugin.actions, ...config.actions ?? []];
1341
+ if (plugin.hooks) config.hooks = config.hooks ? {
1342
+ ...plugin.hooks,
1343
+ ...config.hooks
1344
+ } : plugin.hooks;
1345
+ if (plugin.options) config.options = config.options ? {
1346
+ ...plugin.options,
1347
+ ...config.options
1348
+ } : plugin.options;
1349
+ plugins.set(plugin.name, {
1350
+ plugin,
1351
+ config
1352
+ });
1353
+ recomputeStore();
1354
+ };
1355
+ const unregister = (name) => {
1356
+ const registered = plugins.get(name);
1357
+ if (!registered) return;
1358
+ if (registered.config.cleanup) registered.config.cleanup();
1359
+ plugins.delete(name);
1360
+ recomputeStore();
1361
+ };
1362
+ const getPluginNames = () => {
1363
+ return Array.from(plugins.keys());
1364
+ };
1365
+ const callHook = (hookName, ...args) => {
1366
+ for (const { config } of plugins.values()) {
1367
+ const hook = config.hooks?.[hookName];
1368
+ if (hook) hook(...args);
1369
+ }
1370
+ };
1371
+ const callHookWithHandled = (hookName, ...args) => {
1372
+ let handled = false;
1373
+ for (const { config } of plugins.values()) {
1374
+ const hook = config.hooks?.[hookName];
1375
+ if (hook) {
1376
+ if (hook(...args) === true) handled = true;
1377
+ }
1378
+ }
1379
+ return handled;
1380
+ };
1381
+ const callHookAsync = async (hookName, ...args) => {
1382
+ for (const { config } of plugins.values()) {
1383
+ const hook = config.hooks?.[hookName];
1384
+ if (hook) await hook(...args);
1385
+ }
1386
+ };
1387
+ const callHookReduce = async (hookName, initialValue, ...extraArgs) => {
1388
+ let result = initialValue;
1389
+ for (const { config } of plugins.values()) {
1390
+ const hook = config.hooks?.[hookName];
1391
+ if (hook) result = await hook(result, ...extraArgs);
1392
+ }
1393
+ return result;
1394
+ };
1395
+ const callHookReduceSync = (hookName, initialValue, ...extraArgs) => {
1396
+ let result = initialValue;
1397
+ for (const { config } of plugins.values()) {
1398
+ const hook = config.hooks?.[hookName];
1399
+ if (hook) result = hook(result, ...extraArgs);
1400
+ }
1401
+ return result;
1402
+ };
1403
+ const hooks = {
1404
+ onActivate: () => callHook("onActivate"),
1405
+ onDeactivate: () => callHook("onDeactivate"),
1406
+ onElementHover: (element) => callHook("onElementHover", element),
1407
+ onElementSelect: (element) => {
1408
+ let wasIntercepted = false;
1409
+ let pendingResult;
1410
+ for (const { config } of plugins.values()) {
1411
+ const hook = config.hooks?.onElementSelect;
1412
+ if (hook) {
1413
+ const result = hook(element);
1414
+ if (result === true) wasIntercepted = true;
1415
+ else if (result instanceof Promise) {
1416
+ wasIntercepted = true;
1417
+ pendingResult = result;
1418
+ }
1419
+ }
1420
+ }
1421
+ return {
1422
+ wasIntercepted,
1423
+ pendingResult
1424
+ };
1425
+ },
1426
+ onDragStart: (startX, startY) => callHook("onDragStart", startX, startY),
1427
+ onDragEnd: (elements, bounds) => callHook("onDragEnd", elements, bounds),
1428
+ onBeforeCopy: async (elements) => callHookAsync("onBeforeCopy", elements),
1429
+ transformCopyContent: async (content, elements) => callHookReduce("transformCopyContent", content, elements),
1430
+ onAfterCopy: (elements, success) => callHook("onAfterCopy", elements, success),
1431
+ onCopySuccess: (elements, content) => callHook("onCopySuccess", elements, content),
1432
+ onCopyError: (error) => callHook("onCopyError", error),
1433
+ onStateChange: (state) => callHook("onStateChange", state),
1434
+ onPromptModeChange: (isPromptMode, context) => callHook("onPromptModeChange", isPromptMode, context),
1435
+ onSelectionBox: (visible, bounds, element) => callHook("onSelectionBox", visible, bounds, element),
1436
+ onDragBox: (visible, bounds) => callHook("onDragBox", visible, bounds),
1437
+ onGrabbedBox: (bounds, element) => callHook("onGrabbedBox", bounds, element),
1438
+ onElementLabel: (visible, variant, context) => callHook("onElementLabel", visible, variant, context),
1439
+ onContextMenu: (element, position) => callHook("onContextMenu", element, position),
1440
+ onOpenFile: (filePath, lineNumber) => callHookWithHandled("onOpenFile", filePath, lineNumber),
1441
+ transformHtmlContent: async (html, elements) => callHookReduce("transformHtmlContent", html, elements),
1442
+ transformAgentContext: async (context, elements) => callHookReduce("transformAgentContext", context, elements),
1443
+ transformActionContext: (context) => callHookReduceSync("transformActionContext", context),
1444
+ transformOpenFileUrl: (url, filePath, lineNumber) => callHookReduceSync("transformOpenFileUrl", url, filePath, lineNumber)
1445
+ };
1446
+ return {
1447
+ register,
1448
+ unregister,
1449
+ getPluginNames,
1450
+ setOptions,
1451
+ store,
1452
+ hooks
1453
+ };
1454
+ };
1455
+
1456
+ //#endregion
1457
+ //#region src/core/arrow-navigation.ts
1458
+ const createArrowNavigator = (isValidGrabbableElement, createElementBounds) => {
1459
+ let navigationHistory = [];
1460
+ const findVerticalNext = (currentElement, direction) => {
1461
+ const probePoint = getVisibleBoundsCenter(createElementBounds(currentElement));
1462
+ const elementsAtPoint = require_freeze_updates.getElementsAtPoint(probePoint.x, probePoint.y).filter(isValidGrabbableElement);
1463
+ const currentIndex = elementsAtPoint.indexOf(currentElement);
1464
+ if (currentIndex === -1) return null;
1465
+ return elementsAtPoint[currentIndex + direction] ?? null;
1466
+ };
1467
+ const findUp = (currentElement) => {
1468
+ const nextElement = findVerticalNext(currentElement, 1);
1469
+ if (nextElement) {
1470
+ navigationHistory.push(currentElement);
1471
+ if (navigationHistory.length > 50) navigationHistory = navigationHistory.slice(-50);
1472
+ }
1473
+ return nextElement;
1474
+ };
1475
+ const findDown = (currentElement) => {
1476
+ if (navigationHistory.length > 0) {
1477
+ const previousElement = navigationHistory.pop();
1478
+ if (require_state.isElementConnected(previousElement)) return previousElement;
1479
+ }
1480
+ return findVerticalNext(currentElement, -1);
1481
+ };
1482
+ const isSvgInternal = (element) => element instanceof SVGElement && !(element instanceof SVGSVGElement);
1483
+ const hasMeaningfulSize = (element) => {
1484
+ const rect = element.getBoundingClientRect();
1485
+ return rect.width >= 16 || rect.height >= 16;
1486
+ };
1487
+ const doRectsMatch = (rectA, rectB) => Math.abs(rectA.x - rectB.x) <= 2 && Math.abs(rectA.y - rectB.y) <= 2 && Math.abs(rectA.width - rectB.width) <= 2 && Math.abs(rectA.height - rectB.height) <= 2;
1488
+ const isHorizontallyGrabbable = (element) => isValidGrabbableElement(element) && !isSvgInternal(element) && hasMeaningfulSize(element);
1489
+ const findHorizontal = (currentElement, isForward) => {
1490
+ const currentRect = currentElement.getBoundingClientRect();
1491
+ const isVisuallyDistinct = (candidate) => !doRectsMatch(candidate.getBoundingClientRect(), currentRect);
1492
+ const findEdgeDescendant = (parentElement) => {
1493
+ if (parentElement instanceof SVGSVGElement) return null;
1494
+ const children = Array.from(parentElement.children);
1495
+ const ordered = isForward ? children : children.reverse();
1496
+ for (const childElement of ordered) if (isForward) {
1497
+ if (isHorizontallyGrabbable(childElement) && isVisuallyDistinct(childElement)) return childElement;
1498
+ const descendant = findEdgeDescendant(childElement);
1499
+ if (descendant) return descendant;
1500
+ } else {
1501
+ const descendant = findEdgeDescendant(childElement);
1502
+ if (descendant) return descendant;
1503
+ if (isHorizontallyGrabbable(childElement) && isVisuallyDistinct(childElement)) return childElement;
1504
+ }
1505
+ return null;
1506
+ };
1507
+ const getSibling = (element) => isForward ? element.nextElementSibling : element.previousElementSibling;
1508
+ let nextElement = null;
1509
+ if (isForward) nextElement = findEdgeDescendant(currentElement);
1510
+ if (!nextElement) {
1511
+ let searchElement = currentElement;
1512
+ while (searchElement) {
1513
+ let sibling = getSibling(searchElement);
1514
+ while (sibling) {
1515
+ if (isHorizontallyGrabbable(sibling) && isVisuallyDistinct(sibling)) {
1516
+ nextElement = sibling;
1517
+ break;
1518
+ }
1519
+ const descendant = findEdgeDescendant(sibling);
1520
+ if (descendant) {
1521
+ nextElement = descendant;
1522
+ break;
1523
+ }
1524
+ sibling = getSibling(sibling);
1525
+ }
1526
+ if (nextElement) break;
1527
+ const parentElement = searchElement.parentElement;
1528
+ if (!isForward && parentElement && isHorizontallyGrabbable(parentElement)) {
1529
+ nextElement = parentElement;
1530
+ break;
1531
+ }
1532
+ searchElement = parentElement;
1533
+ }
1534
+ }
1535
+ return nextElement;
1536
+ };
1537
+ const findNext = (key, currentElement) => {
1538
+ switch (key) {
1539
+ case "ArrowUp": return findUp(currentElement);
1540
+ case "ArrowDown": return findDown(currentElement);
1541
+ case "ArrowRight": return findHorizontal(currentElement, true);
1542
+ case "ArrowLeft": return findHorizontal(currentElement, false);
1543
+ default: return null;
1544
+ }
1545
+ };
1546
+ const clearHistory = () => {
1547
+ navigationHistory = [];
1548
+ };
1549
+ return {
1550
+ findNext,
1551
+ clearHistory
1552
+ };
1553
+ };
1554
+
1555
+ //#endregion
1556
+ //#region src/core/keyboard-handlers.ts
1557
+ const getRequiredModifiers = (options) => {
1558
+ const { metaKey, ctrlKey, shiftKey, altKey } = getModifiersFromActivationKey(options.activationKey);
1559
+ return {
1560
+ metaKey,
1561
+ ctrlKey,
1562
+ shiftKey,
1563
+ altKey
1564
+ };
1565
+ };
1566
+ const setupKeyboardEventClaimer = () => {
1567
+ const claimedEvents = /* @__PURE__ */ new WeakSet();
1568
+ const originalKeyDescriptor = Object.getOwnPropertyDescriptor(KeyboardEvent.prototype, "key");
1569
+ let didPatch = false;
1570
+ if (originalKeyDescriptor?.get && !originalKeyDescriptor.get.__reactGrabPatched) {
1571
+ didPatch = true;
1572
+ const originalGetter = originalKeyDescriptor.get;
1573
+ const patchedGetter = function() {
1574
+ if (claimedEvents.has(this)) return "";
1575
+ return originalGetter.call(this);
1576
+ };
1577
+ patchedGetter.__reactGrabPatched = true;
1578
+ Object.defineProperty(KeyboardEvent.prototype, "key", {
1579
+ get: patchedGetter,
1580
+ configurable: true
1581
+ });
1582
+ }
1583
+ const restore = () => {
1584
+ if (didPatch && originalKeyDescriptor) Object.defineProperty(KeyboardEvent.prototype, "key", originalKeyDescriptor);
1585
+ };
1586
+ return {
1587
+ claimedEvents,
1588
+ originalKeyDescriptor,
1589
+ restore
1590
+ };
1591
+ };
1592
+
1593
+ //#endregion
1594
+ //#region src/core/auto-scroll.ts
1595
+ const getAutoScrollDirection = (clientX, clientY) => {
1596
+ return {
1597
+ top: clientY < 25,
1598
+ bottom: clientY > window.innerHeight - 25,
1599
+ left: clientX < 25,
1600
+ right: clientX > window.innerWidth - 25
1601
+ };
1602
+ };
1603
+ const createAutoScroller = (getMousePosition, shouldContinue, onScrollStep) => {
1604
+ let animationId = null;
1605
+ const scroll = () => {
1606
+ if (!shouldContinue()) {
1607
+ stop();
1608
+ return;
1609
+ }
1610
+ const position = getMousePosition();
1611
+ const direction = getAutoScrollDirection(position.x, position.y);
1612
+ let scrollDeltaX = 0;
1613
+ let scrollDeltaY = 0;
1614
+ if (direction.top) scrollDeltaY -= 10;
1615
+ if (direction.bottom) scrollDeltaY += 10;
1616
+ if (direction.left) scrollDeltaX -= 10;
1617
+ if (direction.right) scrollDeltaX += 10;
1618
+ if (scrollDeltaX !== 0 || scrollDeltaY !== 0) {
1619
+ const previousScrollX = window.scrollX;
1620
+ const previousScrollY = window.scrollY;
1621
+ window.scrollBy(scrollDeltaX, scrollDeltaY);
1622
+ const didScrollByX = window.scrollX - previousScrollX;
1623
+ const didScrollByY = window.scrollY - previousScrollY;
1624
+ if (didScrollByX !== 0 || didScrollByY !== 0) onScrollStep?.({
1625
+ x: didScrollByX,
1626
+ y: didScrollByY
1627
+ });
1628
+ }
1629
+ if (direction.top || direction.bottom || direction.left || direction.right) animationId = require_freeze_updates.nativeRequestAnimationFrame(scroll);
1630
+ else animationId = null;
1631
+ };
1632
+ const stop = () => {
1633
+ if (animationId !== null) {
1634
+ require_freeze_updates.nativeCancelAnimationFrame(animationId);
1635
+ animationId = null;
1636
+ }
1637
+ };
1638
+ const isActive = () => animationId !== null;
1639
+ return {
1640
+ start: scroll,
1641
+ stop,
1642
+ isActive
1643
+ };
1644
+ };
1645
+
1646
+ //#endregion
1647
+ //#region src/core/logo-svg.ts
1648
+ const LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 294 294"><path fill="#ff40e0" d="M145 47c25-20 50-27 67-17 16 9 23 30 20 60 0 2-1 5-1 7l-2 13h-1l-12-4c-8-3-17-5-25-6l-17-3c-10-1-20-1-29-1-10 0-20 0-29 1-6 8-11 16-16 24-5 9-9 17-13 26 4 9 8 18 13 26s10 16 16 24l11 14c5 7 11 13 18 19l10 8s-1 0 0 0l-11 9c-17 14-35 22-49 22-6 0-13-2-18-5-16-9-23-30-20-59 1-3 1-5 1-8-30-12-48-29-48-50 0-18 14-35 41-47 2-1 5-2 7-3 0-2 0-5-1-7-3-30 4-51 20-60 18-10 42-3 68 17M71 201c-1 2-1 4-1 5-2 24 3 41 13 47h1c11 7 30 1 51-15-10-9-18-18-26-29-13-1-26-4-38-8m9-38c-3 9-5 17-7 26 8 2 17 4 25 6-3-5-6-10-9-16-3-5-6-10-9-16m-19-53c-2 1-3 1-5 2-21 10-34 23-34 35 0 13 14 27 39 37 3-12 7-25 12-37-5-12-9-24-12-37m37-10c-8 1-17 3-25 6 2 8 4 16 7 25 3-5 6-11 9-16zm-3-61c-4-1-8 0-12 2-10 7-15 24-13 47 0 2 0 3 1 5 12-4 25-6 38-8 8-10 16-20 26-29-15-11-29-17-40-17m111 2c-4-2-8-3-12-2-11 0-25 5-40 17 10 9 19 19 26 29 13 2 26 4 39 8v-5c3-23-2-40-13-47m-61 23c-7 6-13 13-19 19h37c-6-6-12-13-18-19"/><mask id="a"><path fill="#fff" d="m235 85-133 27 28 133 133-27Z"/></mask><path fill="#ff40e0" d="m137 130 76 11c8 1 9 11 3 15l-28 16-4 32c-1 8-10 10-14 4l-41-66c-3-6 1-13 8-12" mask="url(#a)"/></svg>`;
1649
+
1650
+ //#endregion
1651
+ //#region src/utils/is-extension-context.ts
1652
+ const isExtensionContext = () => {
1653
+ const global = globalThis;
1654
+ return Boolean(global.chrome?.runtime?.id || global.browser?.runtime?.id);
1655
+ };
1656
+
1657
+ //#endregion
1658
+ //#region src/core/log-intro.ts
1659
+ const logIntro = () => {
1660
+ try {
1661
+ const version = "[DEV]";
1662
+ const logoDataUri = `data:image/svg+xml;base64,${btoa(LOGO_SVG)}`;
1663
+ console.log(`%cReact Grab${` v${version}`}%c\nhttps://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid #d75fcb; padding: 4px 4px 4px 24px; border-radius: 4px; background-image: url("${logoDataUri}"); background-size: 16px 16px; background-repeat: no-repeat; background-position: 4px center; display: inline-block; margin-bottom: 4px;`, "");
1664
+ if (navigator.onLine && !isExtensionContext()) fetch(`https://www.react-grab.com/api/version?source=browser&v=${version}&t=${Date.now()}`, {
1665
+ referrerPolicy: "origin",
1666
+ keepalive: true,
1667
+ priority: "low",
1668
+ cache: "no-store"
1669
+ }).then((response) => response.text()).then((latestVersion) => {
1670
+ if (latestVersion && latestVersion !== version) console.warn(`[React Grab] v${version} is outdated (latest: v${latestVersion}). Run \`npx grab@latest upgrade\` to upgrade.`);
1671
+ }).catch(() => null);
1672
+ } catch {}
1673
+ };
1674
+
1675
+ //#endregion
1676
+ //#region src/utils/get-script-options.ts
1677
+ const isObjectRecord = (value) => {
1678
+ return typeof value === "object" && value !== null;
1679
+ };
1680
+ const parseOptionsFromJson = (rawValue) => {
1681
+ if (!isObjectRecord(rawValue)) return null;
1682
+ const parsedOptions = {};
1683
+ if (typeof rawValue.enabled === "boolean") parsedOptions.enabled = rawValue.enabled;
1684
+ if (rawValue.activationMode === "toggle" || rawValue.activationMode === "hold") parsedOptions.activationMode = rawValue.activationMode;
1685
+ if (typeof rawValue.keyHoldDuration === "number" && Number.isFinite(rawValue.keyHoldDuration)) parsedOptions.keyHoldDuration = rawValue.keyHoldDuration;
1686
+ if (typeof rawValue.allowActivationInsideInput === "boolean") parsedOptions.allowActivationInsideInput = rawValue.allowActivationInsideInput;
1687
+ if (typeof rawValue.activationKey === "string") parsedOptions.activationKey = rawValue.activationKey;
1688
+ if (typeof rawValue.freezeReactUpdates === "boolean") parsedOptions.freezeReactUpdates = rawValue.freezeReactUpdates;
1689
+ if (Object.keys(parsedOptions).length === 0) return null;
1690
+ return parsedOptions;
1691
+ };
1692
+ const getScriptOptions = () => {
1693
+ if (typeof window === "undefined") return null;
1694
+ try {
1695
+ const dataOptions = (document.currentScript instanceof HTMLScriptElement ? document.currentScript : null)?.getAttribute("data-options");
1696
+ if (!dataOptions) return null;
1697
+ return parseOptionsFromJson(JSON.parse(dataOptions));
1698
+ } catch {
1699
+ return null;
1700
+ }
1701
+ };
1702
+
1703
+ //#endregion
1704
+ //#region src/utils/is-enter-code.ts
1705
+ const isEnterCode = (code) => code === "Enter" || code === "NumpadEnter";
1706
+
1707
+ //#endregion
1708
+ //#region src/utils/is-position-inside-bounds.ts
1709
+ const isPositionInsideBounds = (position, bounds) => position.x >= bounds.x && position.x <= bounds.x + bounds.width && position.y >= bounds.y && position.y <= bounds.y + bounds.height;
1710
+
1711
+ //#endregion
1712
+ //#region src/core/plugins/create-pending-selection-plugin.ts
1713
+ const createPendingSelectionPlugin = (config) => ({
1714
+ name: config.name,
1715
+ setup: (api, hooks) => {
1716
+ return {
1717
+ actions: [typeof config.contextMenuAction === "function" ? config.contextMenuAction(api, hooks) : config.contextMenuAction],
1718
+ cleanup: config.cleanup
1719
+ };
1720
+ }
1721
+ });
1722
+
1723
+ //#endregion
1724
+ //#region src/core/plugins/copy.ts
1725
+ const copyPlugin = createPendingSelectionPlugin({
1726
+ name: "copy",
1727
+ contextMenuAction: {
1728
+ id: "copy",
1729
+ label: "Copy",
1730
+ shortcut: "C",
1731
+ showInToolbarMenu: true,
1732
+ onAction: (context) => {
1733
+ context.copy?.();
1734
+ }
1735
+ }
1736
+ });
1737
+
1738
+ //#endregion
1739
+ //#region src/core/plugins/comment.ts
1740
+ const commentPlugin = {
1741
+ name: "comment",
1742
+ setup: () => ({ actions: [{
1743
+ id: "comment",
1744
+ label: "Comment",
1745
+ shortcut: "Enter",
1746
+ showInToolbarMenu: true,
1747
+ onAction: (context) => {
1748
+ context.enterPromptMode?.();
1749
+ }
1750
+ }] })
1751
+ };
1752
+
1753
+ //#endregion
1754
+ //#region src/core/plugins/open.ts
1755
+ const openPlugin = {
1756
+ name: "open",
1757
+ actions: [{
1758
+ id: "open",
1759
+ label: "Open",
1760
+ shortcut: "O",
1761
+ enabled: (context) => Boolean(context.filePath),
1762
+ onAction: (context) => {
1763
+ if (!context.filePath) return;
1764
+ if (!context.hooks.onOpenFile(context.filePath, context.lineNumber)) require_freeze_updates.openFile(context.filePath, context.lineNumber, context.hooks.transformOpenFileUrl);
1765
+ context.hideContextMenu();
1766
+ context.cleanup();
1767
+ }
1768
+ }]
1769
+ };
1770
+
1771
+ //#endregion
1772
+ //#region src/utils/generate-snippet.ts
1773
+ const generateSnippet = async (elements, options = {}) => {
1774
+ return (await Promise.allSettled(elements.map((element) => require_freeze_updates.getElementContext(element, options)))).map((result) => result.status === "fulfilled" ? result.value : "");
1775
+ };
1776
+
1777
+ //#endregion
1778
+ //#region src/utils/find-longest-common-suffix.ts
1779
+ const findLongestCommonSuffix = (lists) => {
1780
+ if (lists.length === 0) return [];
1781
+ const minLength = Math.min(...lists.map((list) => list.length));
1782
+ let suffixLength = 0;
1783
+ for (let suffixIndex = 1; suffixIndex <= minLength; suffixIndex++) {
1784
+ const candidate = lists[0][lists[0].length - suffixIndex];
1785
+ if (!lists.every((list) => list[list.length - suffixIndex] === candidate)) break;
1786
+ suffixLength = suffixIndex;
1787
+ }
1788
+ if (suffixLength === 0) return [];
1789
+ return lists[0].slice(lists[0].length - suffixLength);
1790
+ };
1791
+
1792
+ //#endregion
1793
+ //#region src/utils/join-snippets.ts
1794
+ const STACK_LINE_DELIMITER = "\n in ";
1795
+ const splitSnippet = (snippet) => {
1796
+ const firstStackIndex = snippet.indexOf(STACK_LINE_DELIMITER);
1797
+ if (firstStackIndex === -1) return {
1798
+ htmlPreview: snippet,
1799
+ stackLines: []
1800
+ };
1801
+ return {
1802
+ htmlPreview: snippet.slice(0, firstStackIndex),
1803
+ stackLines: snippet.slice(firstStackIndex).split("\n").filter((line) => line.trim().length > 0)
1804
+ };
1805
+ };
1806
+ const formatNumberedEntry = (snippet, index) => `[${index + 1}]\n${snippet}`;
1807
+ const joinSnippets = (snippets) => {
1808
+ if (snippets.length <= 1) return snippets[0] ?? "";
1809
+ const splitEntries = snippets.map(splitSnippet);
1810
+ const sharedSuffix = findLongestCommonSuffix(splitEntries.map((entry) => entry.stackLines));
1811
+ if (sharedSuffix.length === 0) return snippets.map(formatNumberedEntry).join("\n\n");
1812
+ if (splitEntries.every((entry) => entry.stackLines.length === sharedSuffix.length)) return `${splitEntries.map((entry, entryIndex) => `[${entryIndex + 1}] ${entry.htmlPreview}`).join("\n")}\n (all from the same component stack)\n${sharedSuffix.join("\n")}`;
1813
+ const sections = [];
1814
+ for (let entryIndex = 0; entryIndex < splitEntries.length; entryIndex++) {
1815
+ const entry = splitEntries[entryIndex];
1816
+ if (entryIndex === 0) {
1817
+ sections.push(formatNumberedEntry(snippets[0], 0));
1818
+ continue;
1819
+ }
1820
+ const divergingLines = entry.stackLines.slice(0, entry.stackLines.length - sharedSuffix.length);
1821
+ const divergingText = divergingLines.length > 0 ? `\n${divergingLines.join("\n")}` : "";
1822
+ sections.push(`[${entryIndex + 1}]\n${entry.htmlPreview}${divergingText}\n (remaining stack same as [1])`);
1823
+ }
1824
+ return sections.join("\n\n");
1825
+ };
1826
+
1827
+ //#endregion
1828
+ //#region src/core/plugins/copy-details.ts
1829
+ const copyDetailsPlugin = createPendingSelectionPlugin({
1830
+ name: "copy-details",
1831
+ contextMenuAction: (_api, _hooks) => ({
1832
+ id: "copy-details",
1833
+ label: "Copy details",
1834
+ showInToolbarMenu: true,
1835
+ onAction: async (context) => {
1836
+ await context.performWithFeedback(async () => {
1837
+ const nonEmptySnippets = (await generateSnippet(context.elements)).filter((snippet) => snippet.trim());
1838
+ if (nonEmptySnippets.length === 0) return false;
1839
+ const joinedContent = joinSnippets(nonEmptySnippets);
1840
+ const transformedContent = await context.hooks.transformHtmlContent(joinedContent, context.elements);
1841
+ if (!transformedContent) return false;
1842
+ return require_create_element_selector.copyContent(transformedContent, {
1843
+ componentName: context.componentName,
1844
+ tagName: context.tagName
1845
+ });
1846
+ });
1847
+ }
1848
+ })
1849
+ });
1850
+
1851
+ //#endregion
1852
+ //#region src/utils/generate-id.ts
1853
+ const generateId = (prefix) => `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
1854
+
1855
+ //#endregion
1856
+ //#region src/utils/comment-storage.ts
1857
+ const COMMENT_ITEMS_KEY = "react-grab-comment-items";
1858
+ const LEGACY_COMMENT_ITEMS_KEY = "react-grab-history-items";
1859
+ const CLEAR_CONFIRMED_KEY = "react-grab-clear-confirmed";
1860
+ const migrateFromLegacyStorage = () => {
1861
+ try {
1862
+ const legacyData = sessionStorage.getItem(LEGACY_COMMENT_ITEMS_KEY);
1863
+ if (legacyData && !sessionStorage.getItem(COMMENT_ITEMS_KEY)) sessionStorage.setItem(COMMENT_ITEMS_KEY, legacyData);
1864
+ sessionStorage.removeItem(LEGACY_COMMENT_ITEMS_KEY);
1865
+ } catch {}
1866
+ };
1867
+ const loadFromSessionStorage = () => {
1868
+ try {
1869
+ const serialized = sessionStorage.getItem(COMMENT_ITEMS_KEY);
1870
+ if (!serialized) return [];
1871
+ return JSON.parse(serialized).map((commentItem) => ({
1872
+ ...commentItem,
1873
+ elementsCount: Math.max(1, commentItem.elementsCount ?? 1),
1874
+ previewBounds: commentItem.previewBounds ?? [],
1875
+ elementSelectors: commentItem.elementSelectors ?? []
1876
+ }));
1877
+ } catch (error) {
1878
+ require_freeze_updates.logRecoverableError("Failed to load comments from sessionStorage", error);
1879
+ return [];
1880
+ }
1881
+ };
1882
+ const readSessionFlag = (key) => {
1883
+ try {
1884
+ return sessionStorage.getItem(key) === "1";
1885
+ } catch {
1886
+ return false;
1887
+ }
1888
+ };
1889
+ const trimToSizeLimit = (items) => {
1890
+ let trimmedItems = items;
1891
+ while (trimmedItems.length > 0) {
1892
+ const serialized = JSON.stringify(trimmedItems);
1893
+ if (new Blob([serialized]).size <= 2097152) return trimmedItems;
1894
+ trimmedItems = trimmedItems.slice(0, -1);
1895
+ }
1896
+ return trimmedItems;
1897
+ };
1898
+ const persistCommentItems = (nextItems) => {
1899
+ commentItems = trimToSizeLimit(nextItems);
1900
+ try {
1901
+ sessionStorage.setItem(COMMENT_ITEMS_KEY, JSON.stringify(commentItems));
1902
+ } catch (error) {
1903
+ require_freeze_updates.logRecoverableError("Failed to save comments to sessionStorage", error);
1904
+ }
1905
+ return commentItems;
1906
+ };
1907
+ let commentItems = [];
1908
+ let didConfirmClear = false;
1909
+ if (typeof window !== "undefined") {
1910
+ migrateFromLegacyStorage();
1911
+ commentItems = loadFromSessionStorage();
1912
+ didConfirmClear = readSessionFlag(CLEAR_CONFIRMED_KEY);
1913
+ }
1914
+ const loadComments = () => commentItems;
1915
+ const addCommentItem = (item) => persistCommentItems([{
1916
+ ...item,
1917
+ id: generateId("comment")
1918
+ }, ...commentItems].slice(0, 20));
1919
+ const removeCommentItem = (itemId) => {
1920
+ persistCommentItems(commentItems.filter((innerItem) => innerItem.id !== itemId));
1921
+ };
1922
+
1923
+ //#endregion
1924
+ //#region src/utils/get-nearest-edge.ts
1925
+ const getNearestEdge = (rect) => {
1926
+ const centerX = rect.left + rect.width / 2;
1927
+ const centerY = rect.top + rect.height / 2;
1928
+ const distanceToTop = centerY;
1929
+ const distanceToBottom = window.innerHeight - centerY;
1930
+ const distanceToLeft = centerX;
1931
+ const distanceToRight = window.innerWidth - centerX;
1932
+ const minimumDistance = Math.min(distanceToTop, distanceToBottom, distanceToLeft, distanceToRight);
1933
+ if (minimumDistance === distanceToTop) return "top";
1934
+ if (minimumDistance === distanceToLeft) return "left";
1935
+ if (minimumDistance === distanceToRight) return "right";
1936
+ return "bottom";
1937
+ };
1938
+
1939
+ //#endregion
1940
+ //#region src/core/index.tsx
1941
+ const builtInPlugins = [
1942
+ copyPlugin,
1943
+ commentPlugin,
1944
+ copyDetailsPlugin,
1945
+ openPlugin
1946
+ ];
1947
+ let hasInited = false;
1948
+ const toolbarStateChangeCallbacks = /* @__PURE__ */ new Set();
1949
+ const init = (rawOptions) => {
1950
+ if (typeof window === "undefined") return createNoopApi();
1951
+ const initialOptions = {
1952
+ enabled: true,
1953
+ activationMode: "toggle",
1954
+ keyHoldDuration: 100,
1955
+ allowActivationInsideInput: true,
1956
+ ...getScriptOptions(),
1957
+ ...rawOptions
1958
+ };
1959
+ if (initialOptions.enabled === false || hasInited) return createNoopApi();
1960
+ hasInited = true;
1961
+ logIntro();
1962
+ const { enabled: _enabled, ...settableOptions } = initialOptions;
1963
+ return require_state.createRoot((dispose) => {
1964
+ let disposed = false;
1965
+ let disposeRenderer;
1966
+ const pluginRegistry = createPluginRegistry(settableOptions);
1967
+ const { store, actions, pointer, viewportVersion, current } = createGrabStore({
1968
+ theme: DEFAULT_THEME,
1969
+ keyHoldDuration: pluginRegistry.store.options.keyHoldDuration ?? 100
1970
+ });
1971
+ const isHoldingKeys = require_state.createMemo(() => current().state === "holding");
1972
+ const isActivated = require_state.createMemo(() => current().state === "active");
1973
+ const isFrozenPhase = require_state.createMemo(() => {
1974
+ const currentState = current();
1975
+ return currentState.state === "active" && currentState.phase === "frozen";
1976
+ });
1977
+ const isDragging = require_state.createMemo(() => {
1978
+ const currentState = current();
1979
+ return currentState.state === "active" && (currentState.phase === "dragging-select" || currentState.phase === "dragging-reposition");
1980
+ });
1981
+ const isActivelyDragging = require_state.createMemo(() => {
1982
+ if (!isDragging()) return false;
1983
+ const dx = Math.abs(pointer().x + window.scrollX - store.dragStart.x);
1984
+ const dy = Math.abs(pointer().y + window.scrollY - store.dragStart.y);
1985
+ return dx > 2 || dy > 2;
1986
+ });
1987
+ const isDragRepositioning = require_state.createMemo(() => {
1988
+ const currentState = current();
1989
+ return currentState.state === "active" && currentState.phase === "dragging-reposition";
1990
+ });
1991
+ const didJustDrag = require_state.createMemo(() => {
1992
+ const currentState = current();
1993
+ return currentState.state === "active" && currentState.phase === "justDragged";
1994
+ });
1995
+ const isCopying = require_state.createMemo(() => current().state === "copying");
1996
+ const isSelectionInteractionLocked = require_state.createMemo(() => store.selectionInteractionLockDepth > 0);
1997
+ const didJustCopy = require_state.createMemo(() => current().state === "justCopied");
1998
+ const isPromptMode = require_state.createMemo(() => {
1999
+ const currentState = current();
2000
+ return currentState.state === "active" && Boolean(currentState.isPromptMode);
2001
+ });
2002
+ const isCommentMode = require_state.createMemo(() => store.pendingCommentMode || isPromptMode());
2003
+ const isPendingDismiss = require_state.createMemo(() => {
2004
+ const currentState = current();
2005
+ return currentState.state === "active" && Boolean(currentState.isPromptMode) && Boolean(currentState.isPendingDismiss);
2006
+ });
2007
+ require_state.createEffect(require_state.on(isActivated, (activated, previousActivated) => {
2008
+ if (activated && !previousActivated) {
2009
+ require_freeze_updates.freezePseudoStates(pointer().x, pointer().y);
2010
+ require_freeze_updates.freezeGlobalAnimations();
2011
+ document.body.style.touchAction = "none";
2012
+ } else if (!activated && previousActivated) {
2013
+ require_freeze_updates.unfreezePseudoStates();
2014
+ require_freeze_updates.unfreezeGlobalAnimations();
2015
+ document.body.style.touchAction = "";
2016
+ }
2017
+ }));
2018
+ const savedToolbarState = require_state.loadToolbarState();
2019
+ const [isEnabled, setIsEnabled] = require_state.createSignal(savedToolbarState ? !savedToolbarState.collapsed : true);
2020
+ const [toolbarShakeCount, setToolbarShakeCount] = require_state.createSignal(0);
2021
+ const [selectionLabelShakeCount, setSelectionLabelShakeCount] = require_state.createSignal(0);
2022
+ const [currentToolbarState, setCurrentToolbarState] = require_state.createSignal(savedToolbarState);
2023
+ const [isToolbarSelectHovered, setIsToolbarSelectHovered] = require_state.createSignal(false);
2024
+ const [commentItems, setCommentItems] = require_state.createSignal(loadComments());
2025
+ const [toolbarMenuPosition, setToolbarMenuPosition] = require_state.createSignal(null);
2026
+ let toolbarElement;
2027
+ let dropdownTrackingFrameId = null;
2028
+ const commentElementMap = /* @__PURE__ */ new Map();
2029
+ let shiftSelectionLabelAnchorRatioByElement = /* @__PURE__ */ new WeakMap();
2030
+ const clearShiftSelectionLabelAnchors = () => {
2031
+ shiftSelectionLabelAnchorRatioByElement = /* @__PURE__ */ new WeakMap();
2032
+ };
2033
+ const stopShiftMultiSelecting = () => {
2034
+ setIsShiftMultiSelecting(false);
2035
+ clearShiftSelectionLabelAnchors();
2036
+ };
2037
+ const updateToolbarState = (updates) => {
2038
+ const currentState = currentToolbarState() ?? require_state.loadToolbarState();
2039
+ const newState = {
2040
+ edge: currentState?.edge ?? "bottom",
2041
+ ratio: currentState?.ratio ?? .5,
2042
+ collapsed: currentState?.collapsed ?? false,
2043
+ enabled: currentState?.enabled ?? true,
2044
+ defaultAction: currentState?.defaultAction ?? "comment",
2045
+ ...updates
2046
+ };
2047
+ require_state.saveToolbarState(newState);
2048
+ setCurrentToolbarState(newState);
2049
+ for (const callback of toolbarStateChangeCallbacks) callback(newState);
2050
+ };
2051
+ const clearHoldTimer = () => {
2052
+ if (activationHoldState.timerId !== null) {
2053
+ clearTimeout(activationHoldState.timerId);
2054
+ activationHoldState.timerId = null;
2055
+ }
2056
+ };
2057
+ const resetCopyConfirmation = () => {
2058
+ activationHoldState.copyWaiting = false;
2059
+ activationHoldState.holdTimerFired = false;
2060
+ activationHoldState.startTimestamp = null;
2061
+ };
2062
+ require_state.createEffect(() => {
2063
+ if (current().state !== "holding") {
2064
+ clearHoldTimer();
2065
+ return;
2066
+ }
2067
+ activationHoldState.startTimestamp = Date.now();
2068
+ activationHoldState.timerId = window.setTimeout(() => {
2069
+ activationHoldState.timerId = null;
2070
+ if (activationHoldState.copyWaiting) {
2071
+ activationHoldState.holdTimerFired = true;
2072
+ return;
2073
+ }
2074
+ actions.activate();
2075
+ }, store.keyHoldDuration);
2076
+ require_state.onCleanup(clearHoldTimer);
2077
+ });
2078
+ require_state.createEffect(() => {
2079
+ const currentState = current();
2080
+ if (currentState.state !== "active" || currentState.phase !== "justDragged") return;
2081
+ const timerId = setTimeout(() => {
2082
+ actions.finishJustDragged();
2083
+ }, require_freeze_updates.FEEDBACK_DURATION_MS);
2084
+ require_state.onCleanup(() => clearTimeout(timerId));
2085
+ });
2086
+ require_state.createEffect(() => {
2087
+ if (current().state !== "justCopied") return;
2088
+ const timerId = setTimeout(() => {
2089
+ actions.finishJustCopied();
2090
+ }, require_freeze_updates.FEEDBACK_DURATION_MS);
2091
+ require_state.onCleanup(() => clearTimeout(timerId));
2092
+ });
2093
+ require_state.createEffect(require_state.on(isHoldingKeys, (currentlyHolding, previouslyHolding = false) => {
2094
+ if (!previouslyHolding || currentlyHolding || !isActivated()) return;
2095
+ if (pluginRegistry.store.options.activationMode !== "hold") actions.setWasActivatedByToggle(true);
2096
+ pluginRegistry.hooks.onActivate();
2097
+ }));
2098
+ const preparePromptMode = (element, positionX, positionY) => {
2099
+ setCopyStartPosition(element, positionX, positionY);
2100
+ actions.clearInputText();
2101
+ };
2102
+ const activatePromptMode = () => {
2103
+ const element = store.frozenElement || targetElement();
2104
+ if (element) actions.enterPromptMode({
2105
+ x: pointer().x,
2106
+ y: pointer().y
2107
+ }, element);
2108
+ };
2109
+ const setCopyStartPosition = (element, positionX, positionY) => {
2110
+ actions.setCopyStart({
2111
+ x: positionX,
2112
+ y: positionY
2113
+ }, element);
2114
+ };
2115
+ const elementDetectionState = {
2116
+ lastDetectionTimestamp: 0,
2117
+ pendingDetectionScheduledAt: 0,
2118
+ latestPointerX: 0,
2119
+ latestPointerY: 0
2120
+ };
2121
+ let dragPreviewDebounceTimerId = null;
2122
+ const [debouncedDragPointer, setDebouncedDragPointer] = require_state.createSignal(null);
2123
+ const scheduleDragPreviewUpdate = (clientX, clientY) => {
2124
+ if (dragPreviewDebounceTimerId !== null) clearTimeout(dragPreviewDebounceTimerId);
2125
+ setDebouncedDragPointer(null);
2126
+ dragPreviewDebounceTimerId = window.setTimeout(() => {
2127
+ setDebouncedDragPointer({
2128
+ x: clientX,
2129
+ y: clientY
2130
+ });
2131
+ dragPreviewDebounceTimerId = null;
2132
+ }, 32);
2133
+ };
2134
+ let keydownSpamTimerId = null;
2135
+ const activationHoldState = {
2136
+ timerId: null,
2137
+ startTimestamp: null,
2138
+ copyWaiting: false,
2139
+ holdTimerFired: false
2140
+ };
2141
+ let previousSpaceDragPointerPage = null;
2142
+ const [isShiftMultiSelecting, setIsShiftMultiSelecting] = require_state.createSignal(false);
2143
+ let lastWindowFocusTimestamp = 0;
2144
+ let isCopyFeedbackCooldownActive = false;
2145
+ let copyFeedbackCooldownTimerId = null;
2146
+ const startCopyFeedbackCooldown = () => {
2147
+ isCopyFeedbackCooldownActive = true;
2148
+ if (copyFeedbackCooldownTimerId !== null) window.clearTimeout(copyFeedbackCooldownTimerId);
2149
+ copyFeedbackCooldownTimerId = window.setTimeout(() => {
2150
+ isCopyFeedbackCooldownActive = false;
2151
+ copyFeedbackCooldownTimerId = null;
2152
+ }, require_freeze_updates.FEEDBACK_DURATION_MS);
2153
+ };
2154
+ const clearCopyFeedbackCooldown = () => {
2155
+ if (copyFeedbackCooldownTimerId !== null) {
2156
+ window.clearTimeout(copyFeedbackCooldownTimerId);
2157
+ copyFeedbackCooldownTimerId = null;
2158
+ }
2159
+ isCopyFeedbackCooldownActive = false;
2160
+ };
2161
+ let selectionSourceRequestVersion = 0;
2162
+ let componentNameRequestVersion = 0;
2163
+ let componentNameDebounceTimerId = null;
2164
+ let keyboardSelectedElement = null;
2165
+ let pendingDefaultActionId = null;
2166
+ const [isPendingContextMenuSelect, setIsPendingContextMenuSelect] = require_state.createSignal(false);
2167
+ const [debouncedElementForComponentName, setDebouncedElementForComponentName] = require_state.createSignal(null);
2168
+ const [resolvedComponentName, setResolvedComponentName] = require_state.createSignal(void 0);
2169
+ const [arrowNavigationElements, setArrowNavigationElements] = require_state.createSignal([]);
2170
+ const [arrowNavigationActiveIndex, setArrowNavigationActiveIndex] = require_state.createSignal(0);
2171
+ const arrowNavigator = createArrowNavigator(require_freeze_updates.isValidGrabbableElement, createElementBounds);
2172
+ const autoScroller = createAutoScroller(pointer, () => isDragging(), (scrollDelta) => {
2173
+ if (isDragRepositioning()) {
2174
+ actions.shiftDragStart(scrollDelta);
2175
+ if (previousSpaceDragPointerPage) {
2176
+ previousSpaceDragPointerPage = {
2177
+ x: previousSpaceDragPointerPage.x + scrollDelta.x,
2178
+ y: previousSpaceDragPointerPage.y + scrollDelta.y
2179
+ };
2180
+ return;
2181
+ }
2182
+ const { pageX, pageY } = toPageCoordinates(pointer().x, pointer().y);
2183
+ previousSpaceDragPointerPage = {
2184
+ x: pageX,
2185
+ y: pageY
2186
+ };
2187
+ }
2188
+ });
2189
+ const isRendererActive = require_state.createMemo(() => isActivated() && !isCopying());
2190
+ const grabbedBoxTimeouts = /* @__PURE__ */ new Map();
2191
+ const showTemporaryGrabbedBox = (bounds, element) => {
2192
+ const boxId = generateId("grabbed");
2193
+ const newBox = {
2194
+ id: boxId,
2195
+ bounds,
2196
+ createdAt: Date.now(),
2197
+ element
2198
+ };
2199
+ actions.addGrabbedBox(newBox);
2200
+ pluginRegistry.hooks.onGrabbedBox(bounds, element);
2201
+ const timeoutId = window.setTimeout(() => {
2202
+ grabbedBoxTimeouts.delete(boxId);
2203
+ actions.removeGrabbedBox(boxId);
2204
+ }, require_freeze_updates.FEEDBACK_DURATION_MS);
2205
+ grabbedBoxTimeouts.set(boxId, timeoutId);
2206
+ };
2207
+ const notifyElementsSelected = async (elements) => {
2208
+ const elementsPayload = await Promise.all(elements.map(async (element) => {
2209
+ const source = await require_freeze_updates.resolveSource(element);
2210
+ let componentName = source?.componentName ?? null;
2211
+ const filePath = source?.filePath;
2212
+ const lineNumber = source?.lineNumber ?? void 0;
2213
+ const columnNumber = source?.columnNumber ?? void 0;
2214
+ if (!componentName) componentName = require_freeze_updates.getComponentDisplayName(element);
2215
+ const textContent = element instanceof HTMLElement ? element.innerText?.slice(0, 100) : void 0;
2216
+ return {
2217
+ tagName: require_freeze_updates.getTagName(element),
2218
+ id: element.id || void 0,
2219
+ className: element.getAttribute("class") || void 0,
2220
+ textContent,
2221
+ componentName: componentName ?? void 0,
2222
+ filePath,
2223
+ lineNumber,
2224
+ columnNumber
2225
+ };
2226
+ }));
2227
+ window.dispatchEvent(new CustomEvent("react-grab:element-selected", { detail: { elements: elementsPayload } }));
2228
+ };
2229
+ const labelFadeTimeouts = /* @__PURE__ */ new Map();
2230
+ const cancelLabelFade = (instanceId) => {
2231
+ const existingTimeout = labelFadeTimeouts.get(instanceId);
2232
+ if (existingTimeout !== void 0) {
2233
+ window.clearTimeout(existingTimeout);
2234
+ labelFadeTimeouts.delete(instanceId);
2235
+ }
2236
+ };
2237
+ const cancelAllLabelFades = () => {
2238
+ for (const timeoutId of labelFadeTimeouts.values()) window.clearTimeout(timeoutId);
2239
+ labelFadeTimeouts.clear();
2240
+ };
2241
+ const scheduleLabelFade = (instanceId) => {
2242
+ cancelLabelFade(instanceId);
2243
+ const timeoutId = window.setTimeout(() => {
2244
+ labelFadeTimeouts.delete(instanceId);
2245
+ actions.updateLabelInstance(instanceId, "fading");
2246
+ setTimeout(() => {
2247
+ labelFadeTimeouts.delete(instanceId);
2248
+ actions.removeLabelInstance(instanceId);
2249
+ }, 150);
2250
+ }, require_freeze_updates.FEEDBACK_DURATION_MS);
2251
+ labelFadeTimeouts.set(instanceId, timeoutId);
2252
+ };
2253
+ const handleLabelInstanceHoverChange = (instanceId, isHovered) => {
2254
+ if (isHovered) cancelLabelFade(instanceId);
2255
+ else {
2256
+ const instance = store.labelInstances.find((labelInstance) => labelInstance.id === instanceId);
2257
+ if (instance && instance.status === "copied") scheduleLabelFade(instanceId);
2258
+ }
2259
+ };
2260
+ const createLabelInstance = (bounds, tagName, componentName, status, options) => {
2261
+ actions.clearLabelInstances();
2262
+ cancelAllLabelFades();
2263
+ const instanceId = generateId("label");
2264
+ const boundsCenterX = bounds.x + bounds.width / 2;
2265
+ const boundsHalfWidth = bounds.width / 2;
2266
+ const mouseX = options?.mouseX;
2267
+ const mouseXOffset = mouseX !== void 0 ? mouseX - boundsCenterX : void 0;
2268
+ const instance = {
2269
+ id: instanceId,
2270
+ bounds,
2271
+ boundsMultiple: options?.boundsMultiple,
2272
+ tagName,
2273
+ componentName,
2274
+ status,
2275
+ createdAt: Date.now(),
2276
+ element: options?.element,
2277
+ elements: options?.elements,
2278
+ mouseX,
2279
+ mouseXOffsetFromCenter: mouseXOffset,
2280
+ mouseXOffsetRatio: mouseXOffset !== void 0 && boundsHalfWidth > 0 ? mouseXOffset / boundsHalfWidth : void 0,
2281
+ hideArrow: options?.hideArrow
2282
+ };
2283
+ actions.addLabelInstance(instance);
2284
+ return instanceId;
2285
+ };
2286
+ const createPerElementLabelInstances = (entries, status) => {
2287
+ actions.clearLabelInstances();
2288
+ cancelAllLabelFades();
2289
+ const instanceIds = [];
2290
+ for (const entry of entries) {
2291
+ const bounds = createElementBounds(entry.element);
2292
+ const boundsCenterX = bounds.x + bounds.width / 2;
2293
+ const boundsHalfWidth = bounds.width / 2;
2294
+ const mouseXOffset = entry.mouseX !== void 0 ? entry.mouseX - boundsCenterX : void 0;
2295
+ const instanceId = generateId("label");
2296
+ const instance = {
2297
+ id: instanceId,
2298
+ bounds,
2299
+ tagName: entry.tagName,
2300
+ componentName: entry.componentName,
2301
+ status,
2302
+ createdAt: Date.now(),
2303
+ element: entry.element,
2304
+ mouseX: entry.mouseX,
2305
+ mouseXOffsetFromCenter: mouseXOffset,
2306
+ mouseXOffsetRatio: mouseXOffset !== void 0 && boundsHalfWidth > 0 ? mouseXOffset / boundsHalfWidth : void 0
2307
+ };
2308
+ actions.addLabelInstance(instance);
2309
+ instanceIds.push(instanceId);
2310
+ }
2311
+ return instanceIds;
2312
+ };
2313
+ const clearAllLabels = () => {
2314
+ cancelAllLabelFades();
2315
+ actions.clearLabelInstances();
2316
+ };
2317
+ const updateLabelAfterCopy = (labelInstanceId, didSucceed, errorMessage) => {
2318
+ if (didSucceed) actions.updateLabelInstance(labelInstanceId, "copied");
2319
+ else actions.updateLabelInstance(labelInstanceId, "error", errorMessage || "Unknown error");
2320
+ scheduleLabelFade(labelInstanceId);
2321
+ };
2322
+ const executeCopyOperation = async (clipboardOperation, labelInstanceIds, copiedElement, shouldDeactivateAfter) => {
2323
+ clearCopyFeedbackCooldown();
2324
+ if (current().state !== "copying") actions.startCopy();
2325
+ let didSucceed = false;
2326
+ let errorMessage;
2327
+ try {
2328
+ await clipboardOperation();
2329
+ didSucceed = true;
2330
+ } catch (error) {
2331
+ errorMessage = normalizeErrorMessage(error, "Action failed");
2332
+ }
2333
+ if (labelInstanceIds) for (const labelInstanceId of labelInstanceIds) updateLabelAfterCopy(labelInstanceId, didSucceed, errorMessage);
2334
+ if (current().state !== "copying") return;
2335
+ if (didSucceed) actions.completeCopy(copiedElement);
2336
+ if (shouldDeactivateAfter) deactivateRenderer();
2337
+ else if (didSucceed) {
2338
+ actions.activate();
2339
+ startCopyFeedbackCooldown();
2340
+ } else actions.unfreeze();
2341
+ };
2342
+ const handleCopySuccessWithComments = (options) => {
2343
+ const { copiedElements, content, extraPrompt, elementName, tagName, componentName } = options;
2344
+ pluginRegistry.hooks.onCopySuccess(copiedElements, content);
2345
+ if (!extraPrompt) return;
2346
+ const hasCopiedElements = copiedElements.length > 0;
2347
+ if (hasCopiedElements) {
2348
+ const currentItems = commentItems();
2349
+ for (const [existingItemId, mappedElements] of commentElementMap.entries()) {
2350
+ if (!(mappedElements.length === copiedElements.length && mappedElements.every((mappedElement, index) => mappedElement === copiedElements[index]))) continue;
2351
+ const existingItem = currentItems.find((item) => item.id === existingItemId);
2352
+ if (!existingItem) continue;
2353
+ if (existingItem.commentText === extraPrompt) {
2354
+ removeCommentItem(existingItemId);
2355
+ commentElementMap.delete(existingItemId);
2356
+ break;
2357
+ }
2358
+ }
2359
+ }
2360
+ const elementSelectors = copiedElements.map((copiedElement, index) => require_create_element_selector.createElementSelector(copiedElement, index === 0));
2361
+ const updatedCommentItems = addCommentItem({
2362
+ content,
2363
+ elementName: elementName ?? "element",
2364
+ tagName: tagName ?? "div",
2365
+ componentName: componentName ?? void 0,
2366
+ elementsCount: copiedElements.length,
2367
+ previewBounds: copiedElements.map((copiedElement) => createElementBounds(copiedElement)),
2368
+ elementSelectors,
2369
+ commentText: extraPrompt,
2370
+ timestamp: Date.now()
2371
+ });
2372
+ setCommentItems(updatedCommentItems);
2373
+ const newestCommentItem = updatedCommentItems[0];
2374
+ if (newestCommentItem && hasCopiedElements) commentElementMap.set(newestCommentItem.id, [...copiedElements]);
2375
+ const currentItemIds = new Set(updatedCommentItems.map((item) => item.id));
2376
+ for (const mapItemId of commentElementMap.keys()) if (!currentItemIds.has(mapItemId)) commentElementMap.delete(mapItemId);
2377
+ };
2378
+ const copyWithFallback = (elements, extraPrompt, resolvedComponentName) => {
2379
+ const firstElement = elements[0];
2380
+ const componentName = resolvedComponentName ?? (firstElement ? require_freeze_updates.getComponentDisplayName(firstElement) : null);
2381
+ const tagName = firstElement ? require_freeze_updates.getTagName(firstElement) : null;
2382
+ const elementName = componentName ?? tagName ?? void 0;
2383
+ return tryCopyWithFallback({
2384
+ getContent: pluginRegistry.store.options.getContent,
2385
+ componentName: elementName
2386
+ }, {
2387
+ onBeforeCopy: pluginRegistry.hooks.onBeforeCopy,
2388
+ transformCopyContent: pluginRegistry.hooks.transformCopyContent,
2389
+ onAfterCopy: pluginRegistry.hooks.onAfterCopy,
2390
+ onCopySuccess: (copiedElements, content) => {
2391
+ handleCopySuccessWithComments({
2392
+ copiedElements,
2393
+ content,
2394
+ extraPrompt,
2395
+ elementName,
2396
+ tagName,
2397
+ componentName
2398
+ });
2399
+ },
2400
+ onCopyError: pluginRegistry.hooks.onCopyError
2401
+ }, elements, extraPrompt);
2402
+ };
2403
+ const copyElementsToClipboard = async (targetElements, extraPrompt, resolvedComponentName) => {
2404
+ if (targetElements.length === 0) return;
2405
+ const unhandledElements = [];
2406
+ const pendingResults = [];
2407
+ for (const element of targetElements) {
2408
+ const { wasIntercepted, pendingResult } = pluginRegistry.hooks.onElementSelect(element);
2409
+ if (!wasIntercepted) unhandledElements.push(element);
2410
+ if (pendingResult) pendingResults.push(pendingResult);
2411
+ if (pluginRegistry.store.theme.grabbedBoxes.enabled) showTemporaryGrabbedBox(createElementBounds(element), element);
2412
+ }
2413
+ await require_freeze_updates.waitUntilNextFrame();
2414
+ if (unhandledElements.length > 0) await copyWithFallback(unhandledElements, extraPrompt, resolvedComponentName);
2415
+ else if (pendingResults.length > 0) {
2416
+ if (!(await Promise.all(pendingResults)).every(Boolean)) throw new Error("Failed to copy");
2417
+ }
2418
+ notifyElementsSelected(targetElements);
2419
+ };
2420
+ const performCopyWithLabel = (options) => {
2421
+ const { element, cursorX, selectedElements, extraPrompt, shouldDeactivateAfter, onComplete, dragRect: passedDragRect } = options;
2422
+ const allTargetElements = selectedElements ?? [element];
2423
+ const dragRect = passedDragRect ?? store.frozenDragRect;
2424
+ const isMultiSelect = allTargetElements.length > 1;
2425
+ const selectionBounds = dragRect && isMultiSelect ? createBoundsFromDragRect(dragRect) : createFlatOverlayBounds(createElementBounds(element));
2426
+ const labelCursorX = isMultiSelect ? selectionBounds.x + selectionBounds.width / 2 : cursorX;
2427
+ const tagName = require_freeze_updates.getTagName(element);
2428
+ clearCopyFeedbackCooldown();
2429
+ actions.startCopy();
2430
+ const labelInstanceId = tagName ? createLabelInstance(selectionBounds, tagName, void 0, "copying", {
2431
+ element,
2432
+ mouseX: labelCursorX,
2433
+ elements: selectedElements
2434
+ }) : null;
2435
+ require_freeze_updates.getNearestComponentName(element).then(async (componentName) => {
2436
+ await executeCopyOperation(() => copyElementsToClipboard(allTargetElements, extraPrompt, componentName ?? void 0), labelInstanceId ? [labelInstanceId] : null, element, shouldDeactivateAfter);
2437
+ onComplete?.();
2438
+ }).catch((error) => {
2439
+ require_freeze_updates.logRecoverableError("Copy operation failed", error);
2440
+ if (labelInstanceId) updateLabelAfterCopy(labelInstanceId, false, normalizeErrorMessage(error, "Action failed"));
2441
+ if (current().state === "copying") actions.unfreeze();
2442
+ });
2443
+ };
2444
+ const performCopyWithPerElementLabels = (options) => {
2445
+ const { elements, labelEntries, shouldDeactivateAfter, onComplete } = options;
2446
+ const primaryElement = elements[0];
2447
+ clearCopyFeedbackCooldown();
2448
+ actions.startCopy();
2449
+ const labelInstanceIds = createPerElementLabelInstances(labelEntries, "copying");
2450
+ require_freeze_updates.getNearestComponentName(primaryElement).then(async (componentName) => {
2451
+ await executeCopyOperation(() => copyElementsToClipboard(elements, void 0, componentName ?? void 0), labelInstanceIds.length > 0 ? labelInstanceIds : null, primaryElement, shouldDeactivateAfter);
2452
+ onComplete?.();
2453
+ }).catch((error) => {
2454
+ require_freeze_updates.logRecoverableError("Copy operation failed", error);
2455
+ const normalizedMessage = normalizeErrorMessage(error, "Action failed");
2456
+ for (const labelInstanceId of labelInstanceIds) updateLabelAfterCopy(labelInstanceId, false, normalizedMessage);
2457
+ if (current().state === "copying") actions.unfreeze();
2458
+ });
2459
+ };
2460
+ const targetElement = require_state.createMemo(() => {
2461
+ viewportVersion();
2462
+ if (!isRendererActive() || isActivelyDragging() || isSelectionInteractionLocked()) return null;
2463
+ const element = store.detectedElement;
2464
+ if (!require_state.isElementConnected(element)) return null;
2465
+ return element;
2466
+ });
2467
+ const effectiveElement = require_state.createMemo(() => store.frozenElement || (isFrozenPhase() ? null : targetElement()));
2468
+ require_state.createEffect(() => {
2469
+ const element = store.detectedElement;
2470
+ if (!element) return;
2471
+ const intervalId = setInterval(() => {
2472
+ if (!require_state.isElementConnected(element)) actions.setDetectedElement(null);
2473
+ }, 100);
2474
+ require_state.onCleanup(() => clearInterval(intervalId));
2475
+ });
2476
+ require_state.createEffect(require_state.on(effectiveElement, (element) => {
2477
+ if (componentNameDebounceTimerId !== null) {
2478
+ clearTimeout(componentNameDebounceTimerId);
2479
+ componentNameDebounceTimerId = null;
2480
+ }
2481
+ if (!element) {
2482
+ setDebouncedElementForComponentName(null);
2483
+ return;
2484
+ }
2485
+ componentNameDebounceTimerId = window.setTimeout(() => {
2486
+ componentNameDebounceTimerId = null;
2487
+ setDebouncedElementForComponentName(element);
2488
+ }, 100);
2489
+ }));
2490
+ require_state.onCleanup(() => {
2491
+ if (componentNameDebounceTimerId !== null) {
2492
+ clearTimeout(componentNameDebounceTimerId);
2493
+ componentNameDebounceTimerId = null;
2494
+ }
2495
+ });
2496
+ require_state.createEffect(() => {
2497
+ const elements = store.frozenElements;
2498
+ require_state.onCleanup(require_freeze_updates.freezeAnimations(elements));
2499
+ });
2500
+ require_state.createEffect(require_state.on(isActivated, (activated) => {
2501
+ if (!activated) return;
2502
+ if (!pluginRegistry.store.options.freezeReactUpdates) return;
2503
+ require_state.onCleanup(require_freeze_updates.freezeUpdates());
2504
+ }));
2505
+ const getSelectionElement = () => {
2506
+ if (store.isTouchMode && isDragging()) {
2507
+ const detected = store.detectedElement;
2508
+ if (!detected || require_freeze_updates.isRootElement(detected)) return void 0;
2509
+ return detected;
2510
+ }
2511
+ const element = effectiveElement();
2512
+ if (!element || require_freeze_updates.isRootElement(element)) return void 0;
2513
+ return element;
2514
+ };
2515
+ const selectionElement = require_state.createMemo(() => getSelectionElement());
2516
+ const isSelectionElementVisible = () => {
2517
+ if (!selectionElement()) return false;
2518
+ if (store.isTouchMode && isDragging()) return isRendererActive();
2519
+ return isRendererActive() && !isActivelyDragging();
2520
+ };
2521
+ const frozenElementBoundsAccessors = require_state.mapArray(() => store.frozenElements, (element) => require_state.createMemo(() => {
2522
+ viewportVersion();
2523
+ return createElementBounds(element);
2524
+ }));
2525
+ const frozenElementsBounds = require_state.createMemo(() => {
2526
+ const frozenElements = store.frozenElements;
2527
+ if (frozenElements.length === 0) return [];
2528
+ const dragRect = store.frozenDragRect;
2529
+ if (dragRect && frozenElements.length > 1) return [createBoundsFromDragRect(dragRect)];
2530
+ return frozenElementBoundsAccessors().map((readBounds) => readBounds());
2531
+ });
2532
+ const pendingShiftSelectionElement = require_state.createMemo(() => {
2533
+ if (!isShiftMultiSelecting()) return null;
2534
+ if (store.pendingCommentMode || isPendingContextMenuSelect()) return null;
2535
+ const element = store.detectedElement;
2536
+ if (!require_state.isElementConnected(element)) return null;
2537
+ if (require_freeze_updates.isRootElement(element)) return null;
2538
+ if (store.frozenElements.includes(element)) return null;
2539
+ return element;
2540
+ });
2541
+ const pendingShiftSelectionBounds = require_state.createMemo(() => {
2542
+ viewportVersion();
2543
+ const element = pendingShiftSelectionElement();
2544
+ if (!element) return void 0;
2545
+ return createElementBounds(element);
2546
+ });
2547
+ const selectionBounds = require_state.createMemo(() => {
2548
+ viewportVersion();
2549
+ const frozenElements = store.frozenElements;
2550
+ if (frozenElements.length > 0) {
2551
+ const frozenBounds = frozenElementsBounds();
2552
+ if (frozenElements.length === 1) {
2553
+ const firstBounds = frozenBounds[0];
2554
+ if (firstBounds) return firstBounds;
2555
+ }
2556
+ const dragRect = store.frozenDragRect;
2557
+ if (dragRect) return frozenBounds[0] ?? createBoundsFromDragRect(dragRect);
2558
+ return createFlatOverlayBounds(combineBounds(frozenBounds));
2559
+ }
2560
+ const element = selectionElement();
2561
+ if (!element) return void 0;
2562
+ return createElementBounds(element);
2563
+ });
2564
+ const toPageCoordinates = (clientX, clientY) => ({
2565
+ pageX: clientX + window.scrollX,
2566
+ pageY: clientY + window.scrollY
2567
+ });
2568
+ const calculateDragDistance = (endX, endY) => {
2569
+ const { pageX: endPageX, pageY: endPageY } = toPageCoordinates(endX, endY);
2570
+ return {
2571
+ x: Math.abs(endPageX - store.dragStart.x),
2572
+ y: Math.abs(endPageY - store.dragStart.y)
2573
+ };
2574
+ };
2575
+ const isDraggingBeyondThreshold = require_state.createMemo(() => {
2576
+ if (!isDragging()) return false;
2577
+ const dragDistance = calculateDragDistance(pointer().x, pointer().y);
2578
+ return dragDistance.x > 2 || dragDistance.y > 2;
2579
+ });
2580
+ const calculateDragRectangle = (endX, endY) => {
2581
+ const { pageX: endPageX, pageY: endPageY } = toPageCoordinates(endX, endY);
2582
+ const dragPageX = Math.min(store.dragStart.x, endPageX);
2583
+ const dragPageY = Math.min(store.dragStart.y, endPageY);
2584
+ const dragWidth = Math.abs(endPageX - store.dragStart.x);
2585
+ const dragHeight = Math.abs(endPageY - store.dragStart.y);
2586
+ return {
2587
+ x: dragPageX - window.scrollX,
2588
+ y: dragPageY - window.scrollY,
2589
+ width: dragWidth,
2590
+ height: dragHeight
2591
+ };
2592
+ };
2593
+ const isSpaceActivationKey = (event) => event.code === "Space" || event.key === " ";
2594
+ const startSpaceDragRepositioning = () => {
2595
+ if (!isDragging()) return;
2596
+ actions.startDragReposition();
2597
+ const { pageX, pageY } = toPageCoordinates(pointer().x, pointer().y);
2598
+ previousSpaceDragPointerPage = {
2599
+ x: pageX,
2600
+ y: pageY
2601
+ };
2602
+ };
2603
+ const stopSpaceDragRepositioning = () => {
2604
+ actions.stopDragReposition();
2605
+ previousSpaceDragPointerPage = null;
2606
+ };
2607
+ const dragBounds = require_state.createMemo(() => {
2608
+ viewportVersion();
2609
+ if (!isDraggingBeyondThreshold()) return void 0;
2610
+ const drag = calculateDragRectangle(pointer().x, pointer().y);
2611
+ return {
2612
+ borderRadius: "0px",
2613
+ height: drag.height,
2614
+ transform: "none",
2615
+ width: drag.width,
2616
+ x: drag.x,
2617
+ y: drag.y
2618
+ };
2619
+ });
2620
+ const dragPreviewBounds = require_state.createMemo(() => {
2621
+ viewportVersion();
2622
+ if (!isDraggingBeyondThreshold()) return [];
2623
+ const pointer = debouncedDragPointer();
2624
+ if (!pointer) return [];
2625
+ const drag = calculateDragRectangle(pointer.x, pointer.y);
2626
+ const elements = getElementsInDrag(drag, require_freeze_updates.isValidGrabbableElement);
2627
+ return (elements.length > 0 ? elements : getElementsInDrag(drag, require_freeze_updates.isValidGrabbableElement, false)).map((element) => createElementBounds(element));
2628
+ });
2629
+ const selectionBoundsMultiple = require_state.createMemo(() => {
2630
+ const previewBounds = dragPreviewBounds();
2631
+ if (previewBounds.length > 0) return previewBounds;
2632
+ const pendingBounds = pendingShiftSelectionBounds();
2633
+ if (pendingBounds) return [...frozenElementsBounds(), pendingBounds];
2634
+ return frozenElementsBounds();
2635
+ });
2636
+ const frozenLabelEntryAccessors = require_state.mapArray(() => store.frozenElements, (element) => {
2637
+ const tagName = require_freeze_updates.getTagName(element) || "element";
2638
+ const componentName = require_freeze_updates.getComponentDisplayName(element) ?? void 0;
2639
+ return require_state.createMemo(() => {
2640
+ viewportVersion();
2641
+ if (!require_state.isElementConnected(element)) return null;
2642
+ const bounds = createElementBounds(element);
2643
+ const anchorRatio = shiftSelectionLabelAnchorRatioByElement.get(element);
2644
+ return {
2645
+ tagName,
2646
+ componentName,
2647
+ bounds,
2648
+ mouseX: anchorRatio === void 0 ? void 0 : bounds.x + bounds.width * anchorRatio
2649
+ };
2650
+ });
2651
+ });
2652
+ const frozenLabelEntries = require_state.createMemo(() => {
2653
+ if (isPromptMode() || store.frozenElements.length < 2) return [];
2654
+ const entries = [];
2655
+ for (const readEntry of frozenLabelEntryAccessors()) {
2656
+ const entry = readEntry();
2657
+ if (entry !== null) entries.push(entry);
2658
+ }
2659
+ return entries;
2660
+ });
2661
+ const pendingShiftPreviewEntry = require_state.createMemo(() => {
2662
+ if (isPromptMode()) return null;
2663
+ const element = pendingShiftSelectionElement();
2664
+ if (!element) return null;
2665
+ viewportVersion();
2666
+ return {
2667
+ tagName: require_freeze_updates.getTagName(element) || "element",
2668
+ componentName: require_freeze_updates.getComponentDisplayName(element) ?? void 0,
2669
+ bounds: createElementBounds(element),
2670
+ mouseX: pointer().x
2671
+ };
2672
+ });
2673
+ const cursorPosition = require_state.createMemo(() => {
2674
+ if (isCopying() || isPromptMode()) {
2675
+ viewportVersion();
2676
+ const element = store.frozenElement || targetElement();
2677
+ if (element) return {
2678
+ x: getBoundsCenter(createElementBounds(element)).x + store.copyOffsetFromCenterX,
2679
+ y: store.copyStart.y
2680
+ };
2681
+ return {
2682
+ x: store.copyStart.x,
2683
+ y: store.copyStart.y
2684
+ };
2685
+ }
2686
+ return {
2687
+ x: pointer().x,
2688
+ y: pointer().y
2689
+ };
2690
+ });
2691
+ const shiftSelectionLabelMouseX = require_state.createMemo(() => {
2692
+ if (!isShiftMultiSelecting()) return void 0;
2693
+ if (store.frozenElements.length !== 1) return void 0;
2694
+ viewportVersion();
2695
+ const element = store.frozenElements[0];
2696
+ if (!require_state.isElementConnected(element)) return void 0;
2697
+ const anchorRatio = shiftSelectionLabelAnchorRatioByElement.get(element);
2698
+ if (anchorRatio === void 0) return void 0;
2699
+ const bounds = createElementBounds(element);
2700
+ return bounds.x + bounds.width * anchorRatio;
2701
+ });
2702
+ require_state.createEffect(require_state.on(() => [targetElement(), store.lastGrabbedElement], ([currentElement, lastElement]) => {
2703
+ if (lastElement && currentElement && lastElement !== currentElement) actions.setLastGrabbed(null);
2704
+ if (currentElement) pluginRegistry.hooks.onElementHover(currentElement);
2705
+ }));
2706
+ require_state.createEffect(require_state.on(() => targetElement(), (element) => {
2707
+ const currentVersion = ++selectionSourceRequestVersion;
2708
+ const clearSource = () => {
2709
+ if (selectionSourceRequestVersion === currentVersion) actions.setSelectionSource(null, null);
2710
+ };
2711
+ if (!element) {
2712
+ clearSource();
2713
+ return;
2714
+ }
2715
+ require_freeze_updates.resolveSource(element).then((source) => {
2716
+ if (selectionSourceRequestVersion !== currentVersion) return;
2717
+ if (!source) {
2718
+ clearSource();
2719
+ return;
2720
+ }
2721
+ actions.setSelectionSource(source.filePath, source.lineNumber);
2722
+ }).catch(() => {
2723
+ if (selectionSourceRequestVersion === currentVersion) actions.setSelectionSource(null, null);
2724
+ });
2725
+ }));
2726
+ const publicGrabbedBoxes = require_state.createMemo(() => store.grabbedBoxes.map((box) => ({
2727
+ id: box.id,
2728
+ bounds: box.bounds,
2729
+ createdAt: box.createdAt
2730
+ })));
2731
+ const publicLabelInstances = require_state.createMemo(() => store.labelInstances.map((instance) => ({
2732
+ id: instance.id,
2733
+ status: instance.status,
2734
+ tagName: instance.tagName,
2735
+ componentName: instance.componentName,
2736
+ createdAt: instance.createdAt
2737
+ })));
2738
+ require_state.createEffect(require_state.on(require_state.createMemo(() => {
2739
+ const active = isActivated();
2740
+ const dragging = isDragging();
2741
+ const copying = isCopying();
2742
+ const inputMode = isPromptMode();
2743
+ const target = targetElement();
2744
+ const drag = dragBounds();
2745
+ const themeEnabled = pluginRegistry.store.theme.enabled;
2746
+ const selectionBoxEnabled = pluginRegistry.store.theme.selectionBox.enabled;
2747
+ const dragBoxEnabled = pluginRegistry.store.theme.dragBox.enabled;
2748
+ const draggingBeyondThreshold = isDraggingBeyondThreshold();
2749
+ const effectiveTarget = effectiveElement();
2750
+ const justCopied = didJustCopy();
2751
+ return {
2752
+ isActive: active,
2753
+ isDragging: dragging,
2754
+ isCopying: copying,
2755
+ isPromptMode: inputMode,
2756
+ isSelectionBoxVisible: Boolean(themeEnabled && selectionBoxEnabled && active && !copying && !justCopied && !dragging && effectiveTarget != null),
2757
+ isDragBoxVisible: Boolean(themeEnabled && dragBoxEnabled && active && !copying && draggingBeyondThreshold),
2758
+ targetElement: target,
2759
+ dragBounds: drag ? {
2760
+ x: drag.x,
2761
+ y: drag.y,
2762
+ width: drag.width,
2763
+ height: drag.height
2764
+ } : null,
2765
+ grabbedBoxes: [...publicGrabbedBoxes()],
2766
+ labelInstances: [...publicLabelInstances()],
2767
+ selectionFilePath: store.selectionFilePath,
2768
+ toolbarState: currentToolbarState()
2769
+ };
2770
+ }), (state) => {
2771
+ pluginRegistry.hooks.onStateChange(state);
2772
+ }));
2773
+ require_state.createEffect(require_state.on(() => [
2774
+ isPromptMode(),
2775
+ pointer().x,
2776
+ pointer().y,
2777
+ targetElement()
2778
+ ], ([inputMode, x, y, target]) => {
2779
+ pluginRegistry.hooks.onPromptModeChange(inputMode, {
2780
+ x,
2781
+ y,
2782
+ targetElement: target
2783
+ });
2784
+ }));
2785
+ require_state.createEffect(require_state.on(() => [
2786
+ selectionVisible(),
2787
+ selectionBounds(),
2788
+ targetElement()
2789
+ ], ([visible, bounds, element]) => {
2790
+ pluginRegistry.hooks.onSelectionBox(Boolean(visible), bounds ?? null, element);
2791
+ }));
2792
+ require_state.createEffect(require_state.on(() => [dragVisible(), dragBounds()], ([visible, bounds]) => {
2793
+ pluginRegistry.hooks.onDragBox(Boolean(visible), bounds ?? null);
2794
+ }));
2795
+ require_state.createEffect(require_state.on(() => [
2796
+ labelVisible(),
2797
+ labelVariant(),
2798
+ cursorPosition(),
2799
+ targetElement(),
2800
+ store.selectionFilePath,
2801
+ store.selectionLineNumber
2802
+ ], ([visible, variant, position, element, filePath, lineNumber]) => {
2803
+ pluginRegistry.hooks.onElementLabel(Boolean(visible), variant, {
2804
+ x: position.x,
2805
+ y: position.y,
2806
+ content: "",
2807
+ element: element ?? void 0,
2808
+ tagName: element ? require_freeze_updates.getTagName(element) || void 0 : void 0,
2809
+ filePath: filePath ?? void 0,
2810
+ lineNumber: lineNumber ?? void 0
2811
+ });
2812
+ }));
2813
+ let cursorStyleElement = null;
2814
+ const setCursorOverride = (cursor) => {
2815
+ if (cursor) {
2816
+ if (!cursorStyleElement) {
2817
+ cursorStyleElement = document.createElement("style");
2818
+ cursorStyleElement.setAttribute("data-react-grab-cursor", "");
2819
+ const nonce = require_freeze_updates.detectCspNonce();
2820
+ if (nonce) cursorStyleElement.nonce = nonce;
2821
+ require_freeze_updates.hideFromThirdParties(cursorStyleElement);
2822
+ document.head.appendChild(cursorStyleElement);
2823
+ }
2824
+ cursorStyleElement.textContent = `* { cursor: ${cursor} !important; }`;
2825
+ } else if (cursorStyleElement) {
2826
+ cursorStyleElement.remove();
2827
+ cursorStyleElement = null;
2828
+ }
2829
+ };
2830
+ require_state.createEffect(require_state.on(() => [
2831
+ isActivated(),
2832
+ isCopying(),
2833
+ isPromptMode()
2834
+ ], ([activated, copying, promptMode]) => {
2835
+ if (copying) setCursorOverride("progress");
2836
+ else if (activated && !promptMode) setCursorOverride("crosshair");
2837
+ else setCursorOverride(null);
2838
+ }));
2839
+ const activateRenderer = () => {
2840
+ const wasInHoldingState = isHoldingKeys();
2841
+ actions.activate();
2842
+ if (!wasInHoldingState) pluginRegistry.hooks.onActivate();
2843
+ };
2844
+ const deactivateRenderer = () => {
2845
+ const wasDragging = isDragging();
2846
+ const previousFocused = store.previouslyFocusedElement;
2847
+ stopSpaceDragRepositioning();
2848
+ actions.deactivate();
2849
+ stopShiftMultiSelecting();
2850
+ clearArrowNavigation();
2851
+ keyboardSelectedElement = null;
2852
+ setIsPendingContextMenuSelect(false);
2853
+ if (wasDragging) document.body.style.userSelect = "";
2854
+ if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
2855
+ autoScroller.stop();
2856
+ if (previousFocused instanceof HTMLElement && require_state.isElementConnected(previousFocused)) previousFocused.focus();
2857
+ pluginRegistry.hooks.onDeactivate();
2858
+ };
2859
+ const forceDeactivateAll = () => {
2860
+ if (isHoldingKeys()) actions.releaseHold();
2861
+ if (isActivated()) deactivateRenderer();
2862
+ clearCopyFeedbackCooldown();
2863
+ };
2864
+ const toggleActivate = () => {
2865
+ actions.setWasActivatedByToggle(true);
2866
+ activateRenderer();
2867
+ };
2868
+ const handleInputSubmit = () => {
2869
+ actions.clearLastCopied();
2870
+ const frozenElements = [...store.frozenElements];
2871
+ const element = store.frozenElement || targetElement();
2872
+ const prompt = isPromptMode() ? store.inputText.trim() : "";
2873
+ if (!element) {
2874
+ deactivateRenderer();
2875
+ return;
2876
+ }
2877
+ const elements = frozenElements.length > 0 ? frozenElements : [element];
2878
+ const firstBounds = elements.map((selectedElement) => createElementBounds(selectedElement))[0];
2879
+ const { x: currentX, y: currentY } = getBoundsCenter(firstBounds);
2880
+ const labelPositionX = currentX + store.copyOffsetFromCenterX;
2881
+ actions.setPointer({
2882
+ x: currentX,
2883
+ y: currentY
2884
+ });
2885
+ actions.exitPromptMode();
2886
+ actions.clearInputText();
2887
+ performCopyWithLabel({
2888
+ element,
2889
+ cursorX: labelPositionX,
2890
+ selectedElements: elements,
2891
+ extraPrompt: prompt || void 0,
2892
+ shouldDeactivateAfter: true
2893
+ });
2894
+ };
2895
+ const handleInputCancel = () => {
2896
+ actions.clearLastCopied();
2897
+ if (!isPromptMode()) return;
2898
+ if (isPendingDismiss()) {
2899
+ actions.clearInputText();
2900
+ deactivateRenderer();
2901
+ return;
2902
+ }
2903
+ actions.setPendingDismiss(true);
2904
+ setSelectionLabelShakeCount((count) => count + 1);
2905
+ };
2906
+ const handleConfirmDismiss = () => {
2907
+ actions.clearInputText();
2908
+ deactivateRenderer();
2909
+ };
2910
+ const handleCancelDismiss = () => {
2911
+ actions.setPendingDismiss(false);
2912
+ };
2913
+ const handleToggleExpand = () => {
2914
+ const element = store.frozenElement || targetElement();
2915
+ if (element) preparePromptMode(element, pointer().x, pointer().y);
2916
+ activatePromptMode();
2917
+ };
2918
+ const handleToggleActive = () => {
2919
+ if (isActivated()) deactivateRenderer();
2920
+ else if (isEnabled()) {
2921
+ const defaultActionId = currentToolbarState()?.defaultAction ?? "comment";
2922
+ if (defaultActionId === "comment") actions.setPendingCommentMode(true);
2923
+ else {
2924
+ pendingDefaultActionId = defaultActionId;
2925
+ setIsPendingContextMenuSelect(true);
2926
+ }
2927
+ toggleActivate();
2928
+ }
2929
+ };
2930
+ const enterCommentModeForElement = (element, positionX, positionY) => {
2931
+ actions.setPendingCommentMode(false);
2932
+ actions.clearInputText();
2933
+ actions.enterPromptMode({
2934
+ x: positionX,
2935
+ y: positionY
2936
+ }, element);
2937
+ };
2938
+ const openContextMenu = (element, position) => {
2939
+ stopShiftMultiSelecting();
2940
+ actions.showContextMenu(position, element);
2941
+ clearArrowNavigation();
2942
+ dismissAllPopups();
2943
+ pluginRegistry.hooks.onContextMenu(element, position);
2944
+ };
2945
+ const runPendingDefaultAction = (element, position) => {
2946
+ const actionId = pendingDefaultActionId;
2947
+ pendingDefaultActionId = null;
2948
+ if (!actionId) return;
2949
+ const action = pluginRegistry.store.actions.find((registeredAction) => registeredAction.id === actionId);
2950
+ if (!action) {
2951
+ handleSetDefaultAction(require_freeze_updates.DEFAULT_ACTION_ID);
2952
+ openContextMenu(element, position);
2953
+ return;
2954
+ }
2955
+ const elementBounds = createElementBounds(element);
2956
+ const context = buildActionContext({
2957
+ element,
2958
+ filePath: store.selectionFilePath ?? void 0,
2959
+ lineNumber: store.selectionLineNumber ?? void 0,
2960
+ tagName: require_freeze_updates.getTagName(element) || void 0,
2961
+ componentName: resolvedComponentName(),
2962
+ position,
2963
+ shouldDeferHideContextMenu: false,
2964
+ performWithFeedbackOptions: {
2965
+ fallbackBounds: elementBounds,
2966
+ fallbackSelectionBounds: [elementBounds],
2967
+ position
2968
+ }
2969
+ });
2970
+ action.onAction(context);
2971
+ };
2972
+ const handleComment = () => {
2973
+ if (!isEnabled()) return;
2974
+ if (isActivated() && isCommentMode()) {
2975
+ deactivateRenderer();
2976
+ return;
2977
+ }
2978
+ actions.setPendingCommentMode(true);
2979
+ if (!isActivated()) toggleActivate();
2980
+ };
2981
+ const handlePointerMove = (clientX, clientY, isShiftHeld) => {
2982
+ const shouldTrackPendingShiftSelection = isShiftHeld && isShiftMultiSelecting() && !isDragging() && !store.pendingCommentMode && !isPendingContextMenuSelect();
2983
+ if (!isEnabled() || isPromptMode() || isFrozenPhase() && !shouldTrackPendingShiftSelection || isSelectionInteractionLocked() || store.contextMenuPosition !== null) return;
2984
+ actions.setPointer({
2985
+ x: clientX,
2986
+ y: clientY
2987
+ });
2988
+ elementDetectionState.latestPointerX = clientX;
2989
+ elementDetectionState.latestPointerY = clientY;
2990
+ if (shouldTrackPendingShiftSelection) {
2991
+ const candidate = require_freeze_updates.getElementAtPosition(clientX, clientY);
2992
+ if (candidate !== store.detectedElement) actions.setDetectedElement(candidate);
2993
+ return;
2994
+ }
2995
+ const now = performance.now();
2996
+ const isDetectionPending = elementDetectionState.pendingDetectionScheduledAt > 0 && now - elementDetectionState.pendingDetectionScheduledAt < 200;
2997
+ if (now - elementDetectionState.lastDetectionTimestamp >= 32 && !isDetectionPending) {
2998
+ elementDetectionState.lastDetectionTimestamp = now;
2999
+ elementDetectionState.pendingDetectionScheduledAt = now;
3000
+ setTimeout(() => {
3001
+ const candidate = require_freeze_updates.getElementAtPosition(elementDetectionState.latestPointerX, elementDetectionState.latestPointerY);
3002
+ if (candidate !== store.detectedElement) actions.setDetectedElement(candidate);
3003
+ elementDetectionState.pendingDetectionScheduledAt = 0;
3004
+ });
3005
+ }
3006
+ if (isDragging()) {
3007
+ if (isDragRepositioning()) {
3008
+ const { pageX, pageY } = toPageCoordinates(clientX, clientY);
3009
+ if (previousSpaceDragPointerPage) actions.shiftDragStart({
3010
+ x: pageX - previousSpaceDragPointerPage.x,
3011
+ y: pageY - previousSpaceDragPointerPage.y
3012
+ });
3013
+ previousSpaceDragPointerPage = {
3014
+ x: pageX,
3015
+ y: pageY
3016
+ };
3017
+ }
3018
+ scheduleDragPreviewUpdate(clientX, clientY);
3019
+ const direction = getAutoScrollDirection(clientX, clientY);
3020
+ const isNearEdge = direction.top || direction.bottom || direction.left || direction.right;
3021
+ if (isNearEdge && !autoScroller.isActive()) autoScroller.start();
3022
+ else if (!isNearEdge && autoScroller.isActive()) autoScroller.stop();
3023
+ }
3024
+ };
3025
+ const handlePointerDown = (clientX, clientY, isShiftHeld) => {
3026
+ if (!isRendererActive() || isSelectionInteractionLocked()) return false;
3027
+ if (!isShiftHeld && isShiftMultiSelecting()) stopShiftMultiSelecting();
3028
+ actions.startDrag({
3029
+ x: clientX,
3030
+ y: clientY
3031
+ }, isShiftHeld);
3032
+ actions.setPointer({
3033
+ x: clientX,
3034
+ y: clientY
3035
+ });
3036
+ document.body.style.userSelect = "none";
3037
+ scheduleDragPreviewUpdate(clientX, clientY);
3038
+ pluginRegistry.hooks.onDragStart(clientX + window.scrollX, clientY + window.scrollY);
3039
+ return true;
3040
+ };
3041
+ const toggleShiftMultiSelection = (element, pointer) => {
3042
+ const wasElementSelected = store.frozenElements.includes(element);
3043
+ const isFirstFrozenElement = store.frozenElements.length === 0;
3044
+ if (!wasElementSelected) {
3045
+ const anchorRatio = getElementAnchorRatio(createElementBounds(element), pointer);
3046
+ shiftSelectionLabelAnchorRatioByElement.set(element, anchorRatio);
3047
+ if (isFirstFrozenElement) setResolvedComponentName(require_freeze_updates.getComponentDisplayName(element) ?? void 0);
3048
+ }
3049
+ actions.toggleFrozenElement(element);
3050
+ require_freeze_updates.clearElementPositionCache();
3051
+ const isElementStillSelected = store.frozenElements.includes(element);
3052
+ if (!isElementStillSelected) shiftSelectionLabelAnchorRatioByElement.delete(element);
3053
+ if (store.frozenElements.length === 0) {
3054
+ stopShiftMultiSelecting();
3055
+ actions.unfreeze();
3056
+ return;
3057
+ }
3058
+ require_freeze_updates.freezeAllAnimations(store.frozenElements);
3059
+ setIsShiftMultiSelecting(true);
3060
+ actions.setPointer(pointer);
3061
+ actions.setLastGrabbed(isElementStillSelected ? element : store.frozenElements[store.frozenElements.length - 1]);
3062
+ actions.freeze();
3063
+ clearArrowNavigation();
3064
+ };
3065
+ const commitShiftMultiSelection = () => {
3066
+ const accumulatedElements = store.frozenElements.filter(require_state.isElementConnected);
3067
+ const perElementLabelEntries = accumulatedElements.map((element) => {
3068
+ const tagName = require_freeze_updates.getTagName(element) || "element";
3069
+ const componentName = require_freeze_updates.getComponentDisplayName(element) ?? void 0;
3070
+ const anchorRatio = shiftSelectionLabelAnchorRatioByElement.get(element);
3071
+ const bounds = createElementBounds(element);
3072
+ return {
3073
+ element,
3074
+ tagName,
3075
+ componentName,
3076
+ mouseX: anchorRatio === void 0 ? bounds.x + bounds.width / 2 : bounds.x + bounds.width * anchorRatio
3077
+ };
3078
+ });
3079
+ stopShiftMultiSelecting();
3080
+ if (accumulatedElements.length === 0) {
3081
+ actions.unfreeze();
3082
+ return;
3083
+ }
3084
+ if (accumulatedElements.length === 1) {
3085
+ performCopyWithLabel({
3086
+ element: accumulatedElements[0],
3087
+ cursorX: perElementLabelEntries[0].mouseX,
3088
+ selectedElements: accumulatedElements,
3089
+ shouldDeactivateAfter: store.wasActivatedByToggle
3090
+ });
3091
+ return;
3092
+ }
3093
+ performCopyWithPerElementLabels({
3094
+ elements: accumulatedElements,
3095
+ labelEntries: perElementLabelEntries,
3096
+ shouldDeactivateAfter: store.wasActivatedByToggle
3097
+ });
3098
+ };
3099
+ const handleDragSelection = (dragSelectionRect, hasModifierKeyHeld, isShiftHeld) => {
3100
+ const elements = getElementsInDrag(dragSelectionRect, require_freeze_updates.isValidGrabbableElement);
3101
+ const selectedElements = elements.length > 0 ? elements : getElementsInDrag(dragSelectionRect, require_freeze_updates.isValidGrabbableElement, false);
3102
+ if (selectedElements.length === 0) return;
3103
+ const isShiftAccumulating = isShiftHeld && !store.pendingCommentMode && !isPendingContextMenuSelect();
3104
+ if (isShiftAccumulating) actions.addFrozenElements(selectedElements);
3105
+ require_freeze_updates.freezeAllAnimations(isShiftAccumulating ? store.frozenElements : selectedElements);
3106
+ pluginRegistry.hooks.onDragEnd(selectedElements, dragSelectionRect);
3107
+ if (isShiftAccumulating) {
3108
+ const lastElement = selectedElements[selectedElements.length - 1];
3109
+ setIsShiftMultiSelecting(true);
3110
+ require_freeze_updates.clearElementPositionCache();
3111
+ actions.setPointer(getBoundsCenter(createElementBounds(lastElement)));
3112
+ actions.setLastGrabbed(lastElement);
3113
+ actions.freeze();
3114
+ clearArrowNavigation();
3115
+ return;
3116
+ }
3117
+ const firstElement = selectedElements[0];
3118
+ const center = getBoundsCenter(createElementBounds(firstElement));
3119
+ actions.setPointer(center);
3120
+ actions.setFrozenElements(selectedElements);
3121
+ const dragRect = createPageRectFromBounds(dragSelectionRect);
3122
+ actions.setFrozenDragRect(dragRect);
3123
+ actions.freeze();
3124
+ actions.setLastGrabbed(firstElement);
3125
+ if (store.pendingCommentMode) {
3126
+ enterCommentModeForElement(firstElement, center.x, center.y);
3127
+ return;
3128
+ }
3129
+ if (isPendingContextMenuSelect()) {
3130
+ setIsPendingContextMenuSelect(false);
3131
+ if (pendingDefaultActionId) runPendingDefaultAction(firstElement, center);
3132
+ else openContextMenu(firstElement, center);
3133
+ return;
3134
+ }
3135
+ const shouldDeactivateAfter = store.wasActivatedByToggle && !hasModifierKeyHeld;
3136
+ performCopyWithLabel({
3137
+ element: firstElement,
3138
+ cursorX: center.x,
3139
+ selectedElements,
3140
+ shouldDeactivateAfter,
3141
+ dragRect
3142
+ });
3143
+ };
3144
+ const getFrozenElementAtPosition = (position) => {
3145
+ for (const element of store.frozenElements) {
3146
+ if (!require_state.isElementConnected(element)) continue;
3147
+ if (isPositionInsideBounds(position, createElementBounds(element))) return element;
3148
+ }
3149
+ return null;
3150
+ };
3151
+ const handleSingleClick = (clientX, clientY, hasModifierKeyHeld, isShiftHeld) => {
3152
+ const validFrozenElement = require_state.isElementConnected(store.frozenElement) ? store.frozenElement : null;
3153
+ const validKeyboardSelectedElement = require_state.isElementConnected(keyboardSelectedElement) ? keyboardSelectedElement : null;
3154
+ const elementAtPointer = require_freeze_updates.getElementsAtPoint(clientX, clientY).find(require_freeze_updates.isValidGrabbableElement) ?? null;
3155
+ const selectedElementUnderPointer = elementAtPointer ?? (require_state.isElementConnected(store.detectedElement) ? store.detectedElement : null);
3156
+ const selectedElement = selectedElementUnderPointer ?? validFrozenElement ?? validKeyboardSelectedElement;
3157
+ if (!selectedElement) return;
3158
+ if (isShiftHeld && !store.pendingCommentMode && !isPendingContextMenuSelect()) {
3159
+ if (elementAtPointer !== null) toggleShiftMultiSelection(elementAtPointer, {
3160
+ x: clientX,
3161
+ y: clientY
3162
+ });
3163
+ return;
3164
+ }
3165
+ let positionX;
3166
+ let positionY;
3167
+ const didResolveFromFrozenElement = selectedElementUnderPointer === null && validFrozenElement === selectedElement;
3168
+ const didResolveFromKeyboardElement = selectedElementUnderPointer === null && validFrozenElement === null && validKeyboardSelectedElement === selectedElement;
3169
+ if (didResolveFromFrozenElement) {
3170
+ positionX = pointer().x;
3171
+ positionY = pointer().y;
3172
+ } else if (didResolveFromKeyboardElement) {
3173
+ const elementCenter = getBoundsCenter(createElementBounds(selectedElement));
3174
+ positionX = elementCenter.x;
3175
+ positionY = elementCenter.y;
3176
+ } else {
3177
+ positionX = clientX;
3178
+ positionY = clientY;
3179
+ }
3180
+ keyboardSelectedElement = null;
3181
+ if (store.pendingCommentMode) {
3182
+ enterCommentModeForElement(selectedElement, positionX, positionY);
3183
+ return;
3184
+ }
3185
+ if (isPendingContextMenuSelect()) {
3186
+ setIsPendingContextMenuSelect(false);
3187
+ const { wasIntercepted } = pluginRegistry.hooks.onElementSelect(selectedElement);
3188
+ if (wasIntercepted) return;
3189
+ require_freeze_updates.freezeAllAnimations([selectedElement]);
3190
+ actions.setFrozenElement(selectedElement);
3191
+ const position = {
3192
+ x: positionX,
3193
+ y: positionY
3194
+ };
3195
+ actions.setPointer(position);
3196
+ actions.freeze();
3197
+ if (pendingDefaultActionId) runPendingDefaultAction(selectedElement, position);
3198
+ else openContextMenu(selectedElement, position);
3199
+ return;
3200
+ }
3201
+ const shouldDeactivateAfter = store.wasActivatedByToggle && !hasModifierKeyHeld;
3202
+ actions.setLastGrabbed(selectedElement);
3203
+ performCopyWithLabel({
3204
+ element: selectedElement,
3205
+ cursorX: positionX,
3206
+ shouldDeactivateAfter
3207
+ });
3208
+ };
3209
+ const cancelActiveDrag = () => {
3210
+ if (!isDragging()) return;
3211
+ stopSpaceDragRepositioning();
3212
+ actions.cancelDrag();
3213
+ autoScroller.stop();
3214
+ document.body.style.userSelect = "";
3215
+ };
3216
+ const handlePointerUp = (clientX, clientY, hasModifierKeyHeld, isShiftHeld) => {
3217
+ if (!isDragging()) return;
3218
+ if (dragPreviewDebounceTimerId !== null) {
3219
+ clearTimeout(dragPreviewDebounceTimerId);
3220
+ dragPreviewDebounceTimerId = null;
3221
+ }
3222
+ setDebouncedDragPointer(null);
3223
+ const dragDistance = calculateDragDistance(clientX, clientY);
3224
+ const wasDragGesture = dragDistance.x > 2 || dragDistance.y > 2;
3225
+ const dragSelectionRect = wasDragGesture ? calculateDragRectangle(clientX, clientY) : null;
3226
+ if (wasDragGesture) actions.endDrag();
3227
+ else actions.cancelDrag();
3228
+ stopSpaceDragRepositioning();
3229
+ autoScroller.stop();
3230
+ document.body.style.userSelect = "";
3231
+ if (dragSelectionRect) handleDragSelection(dragSelectionRect, hasModifierKeyHeld, isShiftHeld);
3232
+ else handleSingleClick(clientX, clientY, hasModifierKeyHeld, isShiftHeld);
3233
+ };
3234
+ const eventListenerManager = createEventListenerManager();
3235
+ const keyboardClaimer = setupKeyboardEventClaimer();
3236
+ const blockEnterIfNeeded = (event) => {
3237
+ let originalKey;
3238
+ try {
3239
+ originalKey = keyboardClaimer.originalKeyDescriptor?.get ? keyboardClaimer.originalKeyDescriptor.get.call(event) : event.key;
3240
+ } catch {
3241
+ return false;
3242
+ }
3243
+ const isEnterKey = originalKey === "Enter" || isEnterCode(event.code);
3244
+ const isOverlayActive = isActivated() || isHoldingKeys();
3245
+ if (isEnterKey && isOverlayActive && !isPromptMode() && !store.wasActivatedByToggle) {
3246
+ keyboardClaimer.claimedEvents.add(event);
3247
+ event.preventDefault();
3248
+ event.stopImmediatePropagation();
3249
+ return true;
3250
+ }
3251
+ return false;
3252
+ };
3253
+ eventListenerManager.addDocumentListener("keydown", blockEnterIfNeeded, { capture: true });
3254
+ eventListenerManager.addDocumentListener("keyup", blockEnterIfNeeded, { capture: true });
3255
+ eventListenerManager.addDocumentListener("keypress", blockEnterIfNeeded, { capture: true });
3256
+ const clearArrowNavigation = () => {
3257
+ setArrowNavigationElements([]);
3258
+ setArrowNavigationActiveIndex(0);
3259
+ arrowNavigator.clearHistory();
3260
+ };
3261
+ const selectAndFocusElement = (element) => {
3262
+ actions.setFrozenElement(element);
3263
+ actions.freeze();
3264
+ keyboardSelectedElement = element;
3265
+ const center = getBoundsCenter(createElementBounds(element));
3266
+ actions.setPointer(center);
3267
+ if (store.contextMenuPosition !== null) actions.showContextMenu(center, element);
3268
+ };
3269
+ const openArrowNavigationMenu = (anchorElement) => {
3270
+ const probePoint = getVisibleBoundsCenter(createElementBounds(anchorElement));
3271
+ const elementsAtPoint = require_freeze_updates.getElementsAtPoint(probePoint.x, probePoint.y).filter(require_freeze_updates.isValidGrabbableElement).reverse();
3272
+ setArrowNavigationElements(elementsAtPoint);
3273
+ setArrowNavigationActiveIndex(Math.max(0, elementsAtPoint.indexOf(anchorElement)));
3274
+ };
3275
+ const handleArrowNavigationSelect = (index) => {
3276
+ const targetElement = arrowNavigationElements()[index];
3277
+ if (!targetElement) return;
3278
+ setArrowNavigationActiveIndex(index);
3279
+ arrowNavigator.clearHistory();
3280
+ selectAndFocusElement(targetElement);
3281
+ };
3282
+ const handleArrowNavigation = (event) => {
3283
+ if (!isActivated() || isPromptMode()) return false;
3284
+ if (isShiftMultiSelecting()) return false;
3285
+ if (!require_freeze_updates.ARROW_KEYS.has(event.key)) return false;
3286
+ let currentElement = effectiveElement();
3287
+ const isInitialSelection = !currentElement;
3288
+ if (!currentElement) currentElement = require_freeze_updates.getElementAtPosition(window.innerWidth / 2, window.innerHeight / 2);
3289
+ if (!currentElement) return false;
3290
+ if (!(event.key === "ArrowUp" || event.key === "ArrowDown")) {
3291
+ clearArrowNavigation();
3292
+ const nextElement = arrowNavigator.findNext(event.key, currentElement);
3293
+ if (!nextElement && !isInitialSelection) return false;
3294
+ event.preventDefault();
3295
+ event.stopPropagation();
3296
+ selectAndFocusElement(nextElement ?? currentElement);
3297
+ return true;
3298
+ }
3299
+ if (arrowNavigationElements().length === 0) openArrowNavigationMenu(currentElement);
3300
+ const elementToSelect = arrowNavigator.findNext(event.key, currentElement) ?? currentElement;
3301
+ event.preventDefault();
3302
+ event.stopPropagation();
3303
+ selectAndFocusElement(elementToSelect);
3304
+ const newIndex = arrowNavigationElements().indexOf(elementToSelect);
3305
+ if (newIndex !== -1) setArrowNavigationActiveIndex(newIndex);
3306
+ else openArrowNavigationMenu(elementToSelect);
3307
+ return true;
3308
+ };
3309
+ const handleEnterKeyActivation = (event) => {
3310
+ if (!isEnterCode(event.code)) return false;
3311
+ if (require_state.isKeyboardEventTriggeredByInput(event)) return false;
3312
+ if (isSelectionInteractionLocked()) return false;
3313
+ const copiedElement = store.lastCopiedElement;
3314
+ if (!isHoldingKeys() && !isPromptMode() && !isActivated() && copiedElement && require_state.isElementConnected(copiedElement) && !store.labelInstances.some((instance) => instance.status === "copied" || instance.status === "fading")) {
3315
+ event.preventDefault();
3316
+ event.stopImmediatePropagation();
3317
+ const center = getBoundsCenter(createElementBounds(copiedElement));
3318
+ actions.setPointer(center);
3319
+ preparePromptMode(copiedElement, center.x, center.y);
3320
+ actions.setFrozenElement(copiedElement);
3321
+ actions.clearLastCopied();
3322
+ activatePromptMode();
3323
+ if (!isActivated()) activateRenderer();
3324
+ return true;
3325
+ }
3326
+ if (isHoldingKeys() && !isPromptMode()) {
3327
+ event.preventDefault();
3328
+ event.stopImmediatePropagation();
3329
+ const element = store.frozenElement || targetElement();
3330
+ if (element) preparePromptMode(element, pointer().x, pointer().y);
3331
+ actions.setPointer({
3332
+ x: pointer().x,
3333
+ y: pointer().y
3334
+ });
3335
+ if (element) actions.setFrozenElement(element);
3336
+ activatePromptMode();
3337
+ if (keydownSpamTimerId !== null) {
3338
+ window.clearTimeout(keydownSpamTimerId);
3339
+ keydownSpamTimerId = null;
3340
+ }
3341
+ if (!isActivated()) activateRenderer();
3342
+ return true;
3343
+ }
3344
+ return false;
3345
+ };
3346
+ const handleOpenFileShortcut = (event) => {
3347
+ if (event.key?.toLowerCase() !== "o" || isPromptMode()) return false;
3348
+ if (!isActivated() || !(event.metaKey || event.ctrlKey)) return false;
3349
+ const filePath = store.selectionFilePath;
3350
+ const lineNumber = store.selectionLineNumber;
3351
+ if (!filePath) return false;
3352
+ event.preventDefault();
3353
+ event.stopPropagation();
3354
+ if (!pluginRegistry.hooks.onOpenFile(filePath, lineNumber ?? void 0)) require_freeze_updates.openFile(filePath, lineNumber ?? void 0, pluginRegistry.hooks.transformOpenFileUrl);
3355
+ return true;
3356
+ };
3357
+ const arrowNavigationItems = require_state.createMemo(() => arrowNavigationElements().map((element) => ({
3358
+ tagName: require_freeze_updates.getTagName(element) || "element",
3359
+ componentName: require_freeze_updates.getComponentDisplayName(element) ?? void 0
3360
+ })));
3361
+ const arrowNavigationState = require_state.createMemo(() => ({
3362
+ items: arrowNavigationItems(),
3363
+ activeIndex: arrowNavigationActiveIndex(),
3364
+ isVisible: arrowNavigationElements().length > 0
3365
+ }));
3366
+ const handleActivationKeys = (event) => {
3367
+ if (!pluginRegistry.store.options.allowActivationInsideInput && require_state.isKeyboardEventTriggeredByInput(event)) return;
3368
+ if (!isTargetKeyCombination(event, pluginRegistry.store.options)) {
3369
+ if ((event.metaKey || event.ctrlKey) && !require_freeze_updates.MODIFIER_KEYS.includes(event.key) && !isEnterCode(event.code)) {
3370
+ if (isActivated() && !store.wasActivatedByToggle) deactivateRenderer();
3371
+ else if (isHoldingKeys()) {
3372
+ clearHoldTimer();
3373
+ resetCopyConfirmation();
3374
+ actions.releaseHold();
3375
+ }
3376
+ }
3377
+ if (!isEnterCode(event.code) || !isHoldingKeys()) return;
3378
+ }
3379
+ if ((isActivated() || isHoldingKeys()) && !isPromptMode()) {
3380
+ event.preventDefault();
3381
+ if (isEnterCode(event.code)) event.stopImmediatePropagation();
3382
+ }
3383
+ if (isActivated()) {
3384
+ if (store.wasActivatedByToggle && pluginRegistry.store.options.activationMode !== "hold") return;
3385
+ if (event.repeat) return;
3386
+ if (keydownSpamTimerId !== null) window.clearTimeout(keydownSpamTimerId);
3387
+ keydownSpamTimerId = window.setTimeout(() => {
3388
+ deactivateRenderer();
3389
+ }, 200);
3390
+ return;
3391
+ }
3392
+ if (isHoldingKeys() && event.repeat) {
3393
+ if (activationHoldState.copyWaiting) {
3394
+ const shouldActivate = activationHoldState.holdTimerFired;
3395
+ resetCopyConfirmation();
3396
+ if (shouldActivate) actions.activate();
3397
+ }
3398
+ return;
3399
+ }
3400
+ if (isCopying() || didJustCopy()) return;
3401
+ if (!isHoldingKeys()) {
3402
+ let activationDuration = pluginRegistry.store.options.keyHoldDuration ?? 100;
3403
+ if (require_state.isKeyboardEventTriggeredByInput(event)) if (require_state.hasTextSelectionInInput(event)) activationDuration += 600;
3404
+ else activationDuration += 400;
3405
+ else if (require_state.hasTextSelectionOnPage()) activationDuration += 600;
3406
+ resetCopyConfirmation();
3407
+ actions.startHold(activationDuration);
3408
+ }
3409
+ };
3410
+ eventListenerManager.addWindowListener("keydown", (event) => {
3411
+ blockEnterIfNeeded(event);
3412
+ if (!isEnabled()) {
3413
+ if (isTargetKeyCombination(event, pluginRegistry.store.options) && !event.repeat) setToolbarShakeCount((count) => count + 1);
3414
+ return;
3415
+ }
3416
+ const isEnterToActivateInput = isEnterCode(event.code) && isHoldingKeys() && !isPromptMode();
3417
+ const isFromReactGrabInput = require_state.isEventFromOverlay(event, "data-react-grab-input");
3418
+ if (isPromptMode() && isTargetKeyCombination(event, pluginRegistry.store.options) && !event.repeat && !isFromReactGrabInput) {
3419
+ event.preventDefault();
3420
+ event.stopPropagation();
3421
+ handleInputCancel();
3422
+ return;
3423
+ }
3424
+ if (event.key === "Escape" && toolbarMenuPosition() !== null) {
3425
+ dismissToolbarMenu();
3426
+ return;
3427
+ }
3428
+ const isFromOverlay = require_state.isEventFromOverlay(event, "data-react-grab-ignore-events") && !isEnterToActivateInput;
3429
+ if (isPromptMode() || isFromOverlay) {
3430
+ if (event.key === "Escape") {
3431
+ if (isPromptMode()) handleInputCancel();
3432
+ else if (store.wasActivatedByToggle) deactivateRenderer();
3433
+ }
3434
+ if (isFromOverlay && require_freeze_updates.ARROW_KEYS.has(event.key)) {
3435
+ if (handleArrowNavigation(event)) return;
3436
+ }
3437
+ return;
3438
+ }
3439
+ if (isDragging() && isSpaceActivationKey(event)) {
3440
+ if (!event.repeat) startSpaceDragRepositioning();
3441
+ event.preventDefault();
3442
+ event.stopPropagation();
3443
+ return;
3444
+ }
3445
+ if (event.key === "Escape") {
3446
+ if (isHoldingKeys() || store.wasActivatedByToggle) {
3447
+ deactivateRenderer();
3448
+ return;
3449
+ }
3450
+ }
3451
+ if (isActivated() && !require_freeze_updates.MODIFIER_KEYS.includes(event.key)) event.preventDefault();
3452
+ const didWindowJustRegainFocus = Date.now() - lastWindowFocusTimestamp < 200;
3453
+ if (handleArrowNavigation(event)) return;
3454
+ if (handleEnterKeyActivation(event)) return;
3455
+ if (handleOpenFileShortcut(event)) return;
3456
+ if (!didWindowJustRegainFocus) handleActivationKeys(event);
3457
+ }, { capture: true });
3458
+ eventListenerManager.addWindowListener("keyup", (event) => {
3459
+ if (blockEnterIfNeeded(event)) return;
3460
+ if (isSpaceActivationKey(event) && isDragRepositioning()) {
3461
+ stopSpaceDragRepositioning();
3462
+ event.preventDefault();
3463
+ event.stopPropagation();
3464
+ }
3465
+ if (event.key === "Shift" && isShiftMultiSelecting()) {
3466
+ if (isDragging()) cancelActiveDrag();
3467
+ commitShiftMultiSelection();
3468
+ return;
3469
+ }
3470
+ if (require_state.isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
3471
+ const requiredModifiers = getRequiredModifiers(pluginRegistry.store.options);
3472
+ const isReleasingModifier = requiredModifiers.metaKey || requiredModifiers.ctrlKey ? require_state.isMac() ? !event.metaKey : !event.ctrlKey : requiredModifiers.shiftKey && !event.shiftKey || requiredModifiers.altKey && !event.altKey;
3473
+ const isReleasingActivationKey = pluginRegistry.store.options.activationKey ? typeof pluginRegistry.store.options.activationKey === "function" ? pluginRegistry.store.options.activationKey(event) : parseActivationKey(pluginRegistry.store.options.activationKey)(event) : isCLikeKey(event.key, event.code);
3474
+ if (didJustCopy() || isCopyFeedbackCooldownActive) {
3475
+ if (isReleasingActivationKey || isReleasingModifier) {
3476
+ clearCopyFeedbackCooldown();
3477
+ deactivateRenderer();
3478
+ }
3479
+ return;
3480
+ }
3481
+ if (!isHoldingKeys() && !isActivated()) return;
3482
+ if (isPromptMode()) return;
3483
+ const hasCustomShortcut = Boolean(pluginRegistry.store.options.activationKey);
3484
+ const isHoldMode = pluginRegistry.store.options.activationMode === "hold";
3485
+ const isDragGestureInProgress = isDragging();
3486
+ if (isActivated()) {
3487
+ const hasContextMenu = store.contextMenuPosition !== null;
3488
+ if (isReleasingModifier) {
3489
+ if (store.wasActivatedByToggle && pluginRegistry.store.options.activationMode !== "hold") return;
3490
+ if (hasContextMenu) return;
3491
+ deactivateRenderer();
3492
+ } else if (isHoldMode && isReleasingActivationKey) {
3493
+ if (keydownSpamTimerId !== null) {
3494
+ window.clearTimeout(keydownSpamTimerId);
3495
+ keydownSpamTimerId = null;
3496
+ }
3497
+ if (hasContextMenu) return;
3498
+ if (isDragGestureInProgress) return;
3499
+ deactivateRenderer();
3500
+ } else if (!hasCustomShortcut && isReleasingActivationKey && keydownSpamTimerId !== null) {
3501
+ window.clearTimeout(keydownSpamTimerId);
3502
+ keydownSpamTimerId = null;
3503
+ }
3504
+ return;
3505
+ }
3506
+ if (isReleasingActivationKey || isReleasingModifier) {
3507
+ if (store.wasActivatedByToggle && pluginRegistry.store.options.activationMode !== "hold") return;
3508
+ if (isHoldingKeys() || activationHoldState.holdTimerFired && isReleasingModifier) {
3509
+ clearHoldTimer();
3510
+ const heldLongEnoughForActivation = (activationHoldState.startTimestamp ? Date.now() - activationHoldState.startTimestamp : 0) >= 200;
3511
+ const shouldActivateAfterCopy = activationHoldState.holdTimerFired && heldLongEnoughForActivation && (pluginRegistry.store.options.allowActivationInsideInput || !require_state.isKeyboardEventTriggeredByInput(event));
3512
+ resetCopyConfirmation();
3513
+ if (shouldActivateAfterCopy) actions.activate();
3514
+ else actions.releaseHold();
3515
+ } else deactivateRenderer();
3516
+ }
3517
+ }, { capture: true });
3518
+ eventListenerManager.addDocumentListener("copy", () => {
3519
+ if (isHoldingKeys()) activationHoldState.copyWaiting = true;
3520
+ });
3521
+ eventListenerManager.addWindowListener("keypress", blockEnterIfNeeded, { capture: true });
3522
+ eventListenerManager.addWindowListener("pointermove", (event) => {
3523
+ if (!event.isPrimary) return;
3524
+ const isTouchPointer = event.pointerType === "touch";
3525
+ actions.setTouchMode(isTouchPointer);
3526
+ if (require_state.isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
3527
+ if (store.contextMenuPosition !== null) return;
3528
+ if (isSelectionInteractionLocked()) return;
3529
+ if (isTouchPointer && !isHoldingKeys() && !isActivated()) return;
3530
+ if ((isTouchPointer ? isHoldingKeys() : isActivated()) && !isPromptMode() && isFrozenPhase() && !event.shiftKey && !isShiftMultiSelecting()) {
3531
+ actions.unfreeze();
3532
+ clearArrowNavigation();
3533
+ }
3534
+ handlePointerMove(event.clientX, event.clientY, event.shiftKey);
3535
+ }, { passive: true });
3536
+ eventListenerManager.addWindowListener("pointerdown", (event) => {
3537
+ if (event.button !== 0) return;
3538
+ if (!event.isPrimary) return;
3539
+ actions.setTouchMode(event.pointerType === "touch");
3540
+ if (require_state.isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
3541
+ if (store.contextMenuPosition !== null) return;
3542
+ if (toolbarMenuPosition() !== null) return;
3543
+ if (isPromptMode()) {
3544
+ const bounds = selectionBounds();
3545
+ if (bounds && event.clientX >= bounds.x && event.clientX <= bounds.x + bounds.width && event.clientY >= bounds.y && event.clientY <= bounds.y + bounds.height) handleInputSubmit();
3546
+ else handleInputCancel();
3547
+ return;
3548
+ }
3549
+ if (isSelectionInteractionLocked()) {
3550
+ event.preventDefault();
3551
+ event.stopImmediatePropagation();
3552
+ return;
3553
+ }
3554
+ if (handlePointerDown(event.clientX, event.clientY, event.shiftKey)) {
3555
+ if (event.pointerId !== void 0) document.documentElement.setPointerCapture(event.pointerId);
3556
+ event.preventDefault();
3557
+ event.stopImmediatePropagation();
3558
+ }
3559
+ }, { capture: true });
3560
+ eventListenerManager.addWindowListener("pointerup", (event) => {
3561
+ if (event.button !== 0) return;
3562
+ if (!event.isPrimary) return;
3563
+ if (require_state.isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
3564
+ if (store.contextMenuPosition !== null) return;
3565
+ const isActive = isRendererActive() || isSelectionInteractionLocked() || isDragging();
3566
+ const hasModifierKeyHeld = event.metaKey || event.ctrlKey;
3567
+ handlePointerUp(event.clientX, event.clientY, hasModifierKeyHeld, event.shiftKey);
3568
+ if (isActive) {
3569
+ event.preventDefault();
3570
+ event.stopImmediatePropagation();
3571
+ }
3572
+ }, { capture: true });
3573
+ eventListenerManager.addWindowListener("contextmenu", (event) => {
3574
+ if (!isRendererActive() || isCopying() || isPromptMode()) return;
3575
+ const isFromOverlay = require_state.isEventFromOverlay(event, "data-react-grab-ignore-events");
3576
+ const position = {
3577
+ x: event.clientX,
3578
+ y: event.clientY
3579
+ };
3580
+ const overlayFrozenElement = isFromOverlay && store.frozenElements.length > 1 ? getFrozenElementAtPosition(position) : null;
3581
+ if (isFromOverlay && arrowNavigationElements().length > 0) clearArrowNavigation();
3582
+ else if (isFromOverlay && !overlayFrozenElement) return;
3583
+ if (store.contextMenuPosition !== null) {
3584
+ event.preventDefault();
3585
+ return;
3586
+ }
3587
+ event.preventDefault();
3588
+ event.stopPropagation();
3589
+ const element = overlayFrozenElement ?? require_freeze_updates.getElementAtPosition(event.clientX, event.clientY);
3590
+ if (!element) return;
3591
+ const existingFrozenElements = store.frozenElements;
3592
+ if (existingFrozenElements.length > 1 && existingFrozenElements.includes(element)) require_freeze_updates.freezeAllAnimations(existingFrozenElements);
3593
+ else {
3594
+ require_freeze_updates.freezeAllAnimations([element]);
3595
+ actions.setFrozenElement(element);
3596
+ }
3597
+ actions.setPointer(position);
3598
+ actions.freeze();
3599
+ openContextMenu(element, position);
3600
+ }, { capture: true });
3601
+ eventListenerManager.addWindowListener("pointercancel", (event) => {
3602
+ if (!event.isPrimary) return;
3603
+ cancelActiveDrag();
3604
+ });
3605
+ eventListenerManager.addWindowListener("click", (event) => {
3606
+ if (require_state.isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
3607
+ if (store.contextMenuPosition !== null) return;
3608
+ if (isRendererActive() || didJustDrag()) {
3609
+ event.preventDefault();
3610
+ event.stopImmediatePropagation();
3611
+ if (store.wasActivatedByToggle && !isPromptMode() && !event.shiftKey) if (!isHoldingKeys()) deactivateRenderer();
3612
+ else actions.setWasActivatedByToggle(false);
3613
+ }
3614
+ }, { capture: true });
3615
+ eventListenerManager.addDocumentListener("visibilitychange", () => {
3616
+ if (document.hidden) {
3617
+ actions.clearGrabbedBoxes();
3618
+ const storeActivationTimestamp = store.activationTimestamp;
3619
+ if (isActivated() && !isPromptMode() && storeActivationTimestamp !== null && Date.now() - storeActivationTimestamp > 500) deactivateRenderer();
3620
+ }
3621
+ });
3622
+ eventListenerManager.addWindowListener("blur", () => {
3623
+ cancelActiveDrag();
3624
+ if (isHoldingKeys()) {
3625
+ clearHoldTimer();
3626
+ actions.releaseHold();
3627
+ resetCopyConfirmation();
3628
+ }
3629
+ stopShiftMultiSelecting();
3630
+ });
3631
+ eventListenerManager.addWindowListener("focus", () => {
3632
+ lastWindowFocusTimestamp = Date.now();
3633
+ });
3634
+ eventListenerManager.addWindowListener("focusin", (event) => {
3635
+ if (require_state.isEventFromOverlay(event, "data-react-grab")) event.stopPropagation();
3636
+ }, { capture: true });
3637
+ const redetectElementUnderPointer = () => {
3638
+ if (store.isTouchMode && !isHoldingKeys() && !isActivated()) return;
3639
+ if (isEnabled() && !isPromptMode() && !isSelectionInteractionLocked() && !isFrozenPhase() && !isDragging() && store.contextMenuPosition === null && store.frozenElements.length === 0) {
3640
+ const candidate = require_freeze_updates.getElementAtPosition(pointer().x, pointer().y);
3641
+ actions.setDetectedElement(candidate);
3642
+ }
3643
+ };
3644
+ let boundsRecalcIntervalId = null;
3645
+ let viewportChangeFrameId = null;
3646
+ const handleViewportChange = () => {
3647
+ invalidateInteractionCaches();
3648
+ redetectElementUnderPointer();
3649
+ actions.incrementViewportVersion();
3650
+ actions.updateContextMenuPosition();
3651
+ };
3652
+ eventListenerManager.addWindowListener("scroll", handleViewportChange, { capture: true });
3653
+ let previousViewportWidth = window.innerWidth;
3654
+ let previousViewportHeight = window.innerHeight;
3655
+ eventListenerManager.addWindowListener("resize", () => {
3656
+ const currentViewportWidth = window.innerWidth;
3657
+ const currentViewportHeight = window.innerHeight;
3658
+ if (previousViewportWidth > 0 && previousViewportHeight > 0) {
3659
+ const scaleX = currentViewportWidth / previousViewportWidth;
3660
+ const scaleY = currentViewportHeight / previousViewportHeight;
3661
+ const isUniformScale = Math.abs(scaleX - scaleY) < require_freeze_updates.ZOOM_DETECTION_THRESHOLD;
3662
+ const hasScaleChanged = Math.abs(scaleX - 1) > require_freeze_updates.ZOOM_DETECTION_THRESHOLD;
3663
+ if (isUniformScale && hasScaleChanged) actions.setPointer({
3664
+ x: pointer().x * scaleX,
3665
+ y: pointer().y * scaleY
3666
+ });
3667
+ }
3668
+ previousViewportWidth = currentViewportWidth;
3669
+ previousViewportHeight = currentViewportHeight;
3670
+ handleViewportChange();
3671
+ });
3672
+ const visualViewport = window.visualViewport;
3673
+ if (visualViewport) {
3674
+ const { signal } = eventListenerManager;
3675
+ visualViewport.addEventListener("resize", handleViewportChange, { signal });
3676
+ visualViewport.addEventListener("scroll", handleViewportChange, { signal });
3677
+ }
3678
+ const scheduleBoundsSync = () => {
3679
+ if (viewportChangeFrameId !== null) return;
3680
+ viewportChangeFrameId = require_freeze_updates.nativeRequestAnimationFrame(() => {
3681
+ viewportChangeFrameId = null;
3682
+ actions.incrementViewportVersion();
3683
+ });
3684
+ };
3685
+ require_state.createEffect(() => {
3686
+ if (pluginRegistry.store.theme.enabled && (isActivated() || isCopying() || store.labelInstances.length > 0 || store.grabbedBoxes.length > 0)) {
3687
+ if (boundsRecalcIntervalId !== null) return;
3688
+ boundsRecalcIntervalId = window.setInterval(() => {
3689
+ scheduleBoundsSync();
3690
+ }, 100);
3691
+ return;
3692
+ }
3693
+ if (boundsRecalcIntervalId !== null) {
3694
+ window.clearInterval(boundsRecalcIntervalId);
3695
+ boundsRecalcIntervalId = null;
3696
+ }
3697
+ if (viewportChangeFrameId !== null) {
3698
+ require_freeze_updates.nativeCancelAnimationFrame(viewportChangeFrameId);
3699
+ viewportChangeFrameId = null;
3700
+ }
3701
+ });
3702
+ require_state.onCleanup(() => {
3703
+ if (boundsRecalcIntervalId !== null) window.clearInterval(boundsRecalcIntervalId);
3704
+ if (viewportChangeFrameId !== null) require_freeze_updates.nativeCancelAnimationFrame(viewportChangeFrameId);
3705
+ });
3706
+ eventListenerManager.addDocumentListener("copy", (event) => {
3707
+ if (isPromptMode() || require_state.isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
3708
+ if (isRendererActive()) event.preventDefault();
3709
+ }, { capture: true });
3710
+ require_state.onCleanup(() => {
3711
+ eventListenerManager.abort();
3712
+ if (dragPreviewDebounceTimerId !== null) window.clearTimeout(dragPreviewDebounceTimerId);
3713
+ if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
3714
+ clearCopyFeedbackCooldown();
3715
+ if (dropdownTrackingFrameId !== null) require_freeze_updates.nativeCancelAnimationFrame(dropdownTrackingFrameId);
3716
+ grabbedBoxTimeouts.forEach((timeoutId) => window.clearTimeout(timeoutId));
3717
+ grabbedBoxTimeouts.clear();
3718
+ cancelAllLabelFades();
3719
+ autoScroller.stop();
3720
+ document.body.style.userSelect = "";
3721
+ document.body.style.touchAction = "";
3722
+ setCursorOverride(null);
3723
+ keyboardClaimer.restore();
3724
+ });
3725
+ const { root: rendererRoot, host: rendererHost } = mountRoot(typeof "/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: \"Geist\", ui-sans-serif, system-ui, sans-serif;\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --spacing: 0.25rem;\n --font-weight-medium: 500;\n --radius-sm: 0.25rem;\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\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 --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);\n --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :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, h2, h3, h4, h5, 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, strong {\n font-weight: bolder;\n }\n code, kbd, samp, 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, 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, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::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, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-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, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-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 .touch-hitbox {\n position: relative;\n &::before {\n content: \"\";\n position: absolute;\n display: block;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 100%;\n height: 100%;\n min-height: 44px;\n min-width: 44px;\n }\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .z-1 {\n z-index: 1;\n }\n .z-10 {\n z-index: 10;\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 .-m-0\\.5 {\n margin: calc(var(--spacing) * -0.5);\n }\n .m-0 {\n margin: calc(var(--spacing) * 0);\n }\n .-mx-2 {\n margin-inline: calc(var(--spacing) * -2);\n }\n .-my-1\\.5 {\n margin-block: calc(var(--spacing) * -1.5);\n }\n .mr-1\\.5 {\n margin-right: calc(var(--spacing) * 1.5);\n }\n .mb-1\\.5 {\n margin-bottom: calc(var(--spacing) * 1.5);\n }\n .ml-1 {\n margin-left: calc(var(--spacing) * 1);\n }\n .ml-4 {\n margin-left: calc(var(--spacing) * 4);\n }\n .line-clamp-5 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 5;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .inline {\n display: inline;\n }\n .inline-flex {\n display: inline-flex;\n }\n .size-4 {\n width: calc(var(--spacing) * 4);\n height: calc(var(--spacing) * 4);\n }\n .h-0 {\n height: calc(var(--spacing) * 0);\n }\n .h-\\[17px\\] {\n height: 17px;\n }\n .h-fit {\n height: fit-content;\n }\n .min-h-0 {\n min-height: calc(var(--spacing) * 0);\n }\n .min-h-4 {\n min-height: calc(var(--spacing) * 4);\n }\n .w-0 {\n width: calc(var(--spacing) * 0);\n }\n .w-\\[calc\\(100\\%\\+16px\\)\\] {\n width: calc(100% + 16px);\n }\n .w-auto {\n width: auto;\n }\n .w-fit {\n width: fit-content;\n }\n .w-full {\n width: 100%;\n }\n .max-w-\\[280px\\] {\n max-width: 280px;\n }\n .max-w-full {\n max-width: 100%;\n }\n .min-w-0 {\n min-width: calc(var(--spacing) * 0);\n }\n .min-w-\\[100px\\] {\n min-width: 100px;\n }\n .min-w-\\[150px\\] {\n min-width: 150px;\n }\n .flex-1 {\n flex: 1;\n }\n .flex-shrink {\n flex-shrink: 1;\n }\n .shrink {\n flex-shrink: 1;\n }\n .shrink-0 {\n flex-shrink: 0;\n }\n .flex-grow {\n flex-grow: 1;\n }\n .-rotate-90 {\n rotate: calc(90deg * -1);\n }\n .rotate-0 {\n rotate: 0deg;\n }\n .rotate-90 {\n rotate: 90deg;\n }\n .rotate-180 {\n rotate: 180deg;\n }\n .interactive-scale {\n transition: transform 400ms cubic-bezier(0.34, 1.56, 0.64, 1);\n @media (hover: hover) and (pointer: fine) {\n &:hover {\n transform: scale(1.05);\n }\n }\n &:active {\n transform: scale(0.96);\n transition: transform 60ms cubic-bezier(0, 0, 0.2, 1);\n }\n }\n .press-scale {\n transition: transform 400ms cubic-bezier(0.34, 1.56, 0.64, 1);\n &:active {\n transform: scale(0.97);\n transition: transform 60ms cubic-bezier(0, 0, 0.2, 1);\n }\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 .cursor-grab {\n cursor: grab;\n }\n .cursor-grabbing {\n cursor: grabbing;\n }\n .cursor-pointer {\n cursor: pointer;\n }\n .resize {\n resize: both;\n }\n .resize-none {\n resize: none;\n }\n .grid-cols-\\[0fr\\] {\n grid-template-columns: 0fr;\n }\n .grid-cols-\\[1fr\\] {\n grid-template-columns: 1fr;\n }\n .grid-rows-\\[0fr\\] {\n grid-template-rows: 0fr;\n }\n .grid-rows-\\[1fr\\] {\n grid-template-rows: 1fr;\n }\n .flex-col {\n flex-direction: column;\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-start {\n align-items: flex-start;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .gap-0 {\n gap: calc(var(--spacing) * 0);\n }\n .gap-0\\.5 {\n gap: calc(var(--spacing) * 0.5);\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-\\[5px\\] {\n gap: 5px;\n }\n .self-stretch {\n align-self: stretch;\n }\n .truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .overflow-visible {\n overflow: visible;\n }\n .overflow-y-auto {\n overflow-y: auto;\n }\n .rounded-\\[10px\\] {\n border-radius: 10px;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-sm {\n border-radius: var(--radius-sm);\n }\n .rounded-t-\\[10px\\] {\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n }\n .rounded-t-none {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n .rounded-l-\\[10px\\] {\n border-top-left-radius: 10px;\n border-bottom-left-radius: 10px;\n }\n .rounded-l-none {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .rounded-r-\\[10px\\] {\n border-top-right-radius: 10px;\n border-bottom-right-radius: 10px;\n }\n .rounded-r-none {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n .rounded-b-\\[6px\\] {\n border-bottom-right-radius: 6px;\n border-bottom-left-radius: 6px;\n }\n .rounded-b-\\[10px\\] {\n border-bottom-right-radius: 10px;\n border-bottom-left-radius: 10px;\n }\n .rounded-b-none {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .\\[border-width\\:0\\.5px\\] {\n border-width: 0.5px;\n }\n .\\[border-top-width\\:0\\.5px\\] {\n border-top-width: 0.5px;\n }\n .border-none {\n --tw-border-style: none;\n border-style: none;\n }\n .border-solid {\n --tw-border-style: solid;\n border-style: solid;\n }\n .border-\\[var\\(--rg-border-button\\)\\] {\n border-color: var(--rg-border-button);\n }\n .border-t-\\[var\\(--rg-border-subtle\\)\\] {\n border-top-color: var(--rg-border-subtle);\n }\n .bg-\\[var\\(--rg-error-bg\\)\\] {\n background-color: var(--rg-error-bg);\n }\n .bg-\\[var\\(--rg-panel-bg\\)\\] {\n background-color: var(--rg-panel-bg);\n }\n .bg-\\[var\\(--rg-submit-bg\\)\\] {\n background-color: var(--rg-submit-bg);\n }\n .bg-\\[var\\(--rg-surface-hover\\)\\] {\n background-color: var(--rg-surface-hover);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .p-0 {\n padding: calc(var(--spacing) * 0);\n }\n .px-0\\.25 {\n padding-inline: calc(var(--spacing) * 0.25);\n }\n .px-1\\.5 {\n padding-inline: calc(var(--spacing) * 1.5);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-\\[3px\\] {\n padding-inline: 3px;\n }\n .py-0\\.25 {\n padding-block: calc(var(--spacing) * 0.25);\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-px {\n padding-block: 1px;\n }\n .pt-1\\.5 {\n padding-top: calc(var(--spacing) * 1.5);\n }\n .pb-1 {\n padding-bottom: calc(var(--spacing) * 1);\n }\n .text-left {\n text-align: left;\n }\n .font-sans {\n font-family: var(--font-sans);\n }\n .text-\\[11px\\] {\n font-size: 11px;\n }\n .text-\\[13px\\] {\n font-size: 13px;\n }\n .leading-3\\.5 {\n --tw-leading: calc(var(--spacing) * 3.5);\n line-height: calc(var(--spacing) * 3.5);\n }\n .leading-4 {\n --tw-leading: calc(var(--spacing) * 4);\n line-height: calc(var(--spacing) * 4);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .wrap-break-word {\n overflow-wrap: break-word;\n }\n .text-ellipsis {\n text-overflow: ellipsis;\n }\n .whitespace-nowrap {\n white-space: nowrap;\n }\n .text-\\[var\\(--rg-error-text\\)\\] {\n color: var(--rg-error-text);\n }\n .text-\\[var\\(--rg-submit-fg\\)\\] {\n color: var(--rg-submit-fg);\n }\n .text-\\[var\\(--rg-text-primary\\)\\] {\n color: var(--rg-text-primary);\n }\n .text-\\[var\\(--rg-text-primary-85\\)\\] {\n color: var(--rg-text-primary-85);\n }\n .text-\\[var\\(--rg-text-secondary\\)\\] {\n color: var(--rg-text-secondary);\n }\n .tabular-nums {\n --tw-numeric-spacing: tabular-nums;\n font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);\n }\n .antialiased {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n .opacity-0 {\n opacity: 0%;\n }\n .opacity-50 {\n opacity: 50%;\n }\n .opacity-100 {\n opacity: 100%;\n }\n .shadow {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .\\[box-shadow\\:var\\(--rg-shadow\\)\\] {\n box-shadow: var(--rg-shadow);\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\\:var\\(--rg-drop-shadow\\)\\] {\n filter: var(--rg-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-filter {\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: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, 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-\\[grid-template-columns\\] {\n transition-property: grid-template-columns;\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-\\[grid-template-rows\\] {\n transition-property: grid-template-rows;\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\\,transform\\] {\n transition-property: opacity,transform;\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-\\[padding\\,border-radius\\,transform\\] {\n transition-property: padding,border-radius,transform;\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-\\[top\\,left\\,width\\,height\\,opacity\\] {\n transition-property: top,left,width,height,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 .transition-\\[transform\\,opacity\\] {\n transition-property: transform,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 .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-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\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 .transition-transform {\n transition-property: transform, translate, scale, rotate;\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-\\[80ms\\] {\n transition-delay: 80ms;\n }\n .duration-60 {\n --tw-duration: 60ms;\n transition-duration: 60ms;\n }\n .duration-75 {\n --tw-duration: 75ms;\n transition-duration: 75ms;\n }\n .duration-100 {\n --tw-duration: 100ms;\n transition-duration: 100ms;\n }\n .duration-120 {\n --tw-duration: 120ms;\n transition-duration: 120ms;\n }\n .duration-140 {\n --tw-duration: 140ms;\n transition-duration: 140ms;\n }\n .duration-150 {\n --tw-duration: 150ms;\n transition-duration: 150ms;\n }\n .duration-180 {\n --tw-duration: 180ms;\n transition-duration: 180ms;\n }\n .duration-220 {\n --tw-duration: 220ms;\n transition-duration: 220ms;\n }\n .duration-300 {\n --tw-duration: 300ms;\n transition-duration: 300ms;\n }\n .duration-400 {\n --tw-duration: 400ms;\n transition-duration: 400ms;\n }\n .ease-\\[cubic-bezier\\(0\\,0\\,0\\.2\\,1\\)\\] {\n --tw-ease: cubic-bezier(0,0,0.2,1);\n transition-timing-function: cubic-bezier(0,0,0.2,1);\n }\n .ease-drawer {\n --tw-ease: var(--ease-drawer);\n transition-timing-function: var(--ease-drawer);\n }\n .ease-out {\n --tw-ease: var(--ease-out);\n transition-timing-function: var(--ease-out);\n }\n .ease-spring {\n --tw-ease: var(--ease-spring);\n transition-timing-function: var(--ease-spring);\n }\n .will-change-\\[opacity\\,transform\\] {\n will-change: opacity,transform;\n }\n .contain-layout {\n --tw-contain-layout: layout;\n contain: var(--tw-contain-size,) var(--tw-contain-layout,) var(--tw-contain-paint,) var(--tw-contain-style,);\n }\n .outline-none {\n --tw-outline-style: none;\n outline-style: none;\n }\n .select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .\\[corner-shape\\:superellipse\\(1\\.25\\)\\] {\n corner-shape: superellipse(1.25);\n }\n .\\[font-synthesis\\:none\\] {\n font-synthesis: none;\n }\n .hover\\:bg-\\[var\\(--rg-error-bg-hover\\)\\] {\n &:hover {\n @media (hover: hover) {\n background-color: var(--rg-error-bg-hover);\n }\n }\n }\n .hover\\:bg-\\[var\\(--rg-surface-active\\)\\] {\n &:hover {\n @media (hover: hover) {\n background-color: var(--rg-surface-active);\n }\n }\n }\n .hover\\:bg-\\[var\\(--rg-surface-hover\\)\\] {\n &:hover {\n @media (hover: hover) {\n background-color: var(--rg-surface-hover);\n }\n }\n }\n .hover\\:text-\\[var\\(--rg-text-primary\\)\\] {\n &:hover {\n @media (hover: hover) {\n color: var(--rg-text-primary);\n }\n }\n }\n .disabled\\:cursor-default {\n &:disabled {\n cursor: default;\n }\n }\n .disabled\\:opacity-40 {\n &:disabled {\n opacity: 40%;\n }\n }\n}\n:host {\n all: initial;\n direction: ltr;\n}\n:host, [data-rg-theme=\"dark\"] {\n --rg-panel-bg: #161616;\n --rg-text-primary: #ffffff;\n --rg-text-secondary: #a7a7a7;\n --rg-surface-hover: rgba(255, 255, 255, 0.1);\n --rg-surface-active: rgba(255, 255, 255, 0.15);\n --rg-border-subtle: rgba(255, 255, 255, 0.1);\n --rg-border-button: rgba(255, 255, 255, 0.2);\n --rg-submit-bg: #ffffff;\n --rg-submit-fg: #161616;\n --rg-error-text: #f87171;\n --rg-error-bg: #3d1515;\n --rg-error-bg-hover: #4d1f1f;\n --rg-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n --rg-drop-shadow: drop-shadow(0px 2px 8px rgba(0, 0, 0, 0.08));\n --rg-shimmer-from: #a1a1aa;\n --rg-shimmer-to: #d4d4d8;\n --rg-text-primary-85: rgba(255, 255, 255, 0.85);\n}\n@media (prefers-color-scheme: dark) {\n :host:not([data-rg-theme]) {\n --rg-panel-bg: #ffffff;\n --rg-text-primary: #171717;\n --rg-text-secondary: #737373;\n --rg-surface-hover: rgba(0, 0, 0, 0.05);\n --rg-surface-active: rgba(0, 0, 0, 0.08);\n --rg-border-subtle: rgba(0, 0, 0, 0.08);\n --rg-border-button: rgba(0, 0, 0, 0.15);\n --rg-submit-bg: #171717;\n --rg-submit-fg: #ffffff;\n --rg-error-text: #dc2626;\n --rg-error-bg: #fee2e2;\n --rg-error-bg-hover: #fecaca;\n --rg-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);\n --rg-drop-shadow: drop-shadow(0px 2px 12px rgba(0, 0, 0, 0.1));\n --rg-shimmer-from: #71717a;\n --rg-shimmer-to: #a1a1aa;\n --rg-text-primary-85: rgba(23, 23, 23, 0.85);\n }\n}\n:host([data-rg-theme=\"light\"]), [data-rg-theme=\"light\"] {\n --rg-panel-bg: #ffffff;\n --rg-text-primary: #171717;\n --rg-text-secondary: #737373;\n --rg-surface-hover: rgba(0, 0, 0, 0.05);\n --rg-surface-active: rgba(0, 0, 0, 0.08);\n --rg-border-subtle: rgba(0, 0, 0, 0.08);\n --rg-border-button: rgba(0, 0, 0, 0.15);\n --rg-submit-bg: #171717;\n --rg-submit-fg: #ffffff;\n --rg-error-text: #dc2626;\n --rg-error-bg: #fee2e2;\n --rg-error-bg-hover: #fecaca;\n --rg-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);\n --rg-drop-shadow: drop-shadow(0px 2px 12px rgba(0, 0, 0, 0.1));\n --rg-shimmer-from: #71717a;\n --rg-shimmer-to: #a1a1aa;\n --rg-text-primary-85: rgba(23, 23, 23, 0.85);\n}\n@keyframes rg-badge-slide {\n from {\n transform: translate(-8.2px, 12.4px);\n }\n to {\n transform: translate(0, 0);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-react-grab-unread-indicator], [data-react-grab-unread-indicator] * {\n animation: none !important;\n transition: none !important;\n }\n}\n@keyframes shake {\n 0%, 100% {\n transform: translateX(0);\n }\n 15% {\n transform: translateX(-3px);\n }\n 30% {\n transform: translateX(3px);\n }\n 45% {\n transform: translateX(-3px);\n }\n 60% {\n transform: translateX(3px);\n }\n 75% {\n transform: translateX(-2px);\n }\n 90% {\n transform: translateX(2px);\n }\n}\n@keyframes success-pop {\n from {\n transform: scale(0.85);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n@keyframes icon-loader-spin {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n 100% {\n opacity: 0.2;\n }\n}\n.icon-loader-bar {\n animation: icon-loader-spin 0.5s linear infinite;\n}\n@keyframes shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n.shimmer-text {\n background: linear-gradient( 90deg, var(--rg-shimmer-from) 0%, var(--rg-shimmer-to) 25%, var(--rg-shimmer-from) 50%, var(--rg-shimmer-to) 75%, var(--rg-shimmer-from) 100% );\n background-size: 200% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n animation: shimmer 2.5s linear infinite;\n}\n@keyframes clock-flash {\n 0% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2);\n }\n 50% {\n transform: scale(0.92);\n }\n 75% {\n transform: scale(1.05);\n }\n 100% {\n transform: scale(1);\n }\n}\n.animate-clock-flash {\n animation: clock-flash 400ms ease-out;\n will-change: transform;\n}\n.animate-shake {\n animation: shake 0.3s ease-out;\n will-change: transform;\n}\n.animate-success-pop {\n animation: success-pop 350ms cubic-bezier(0.34, 1.56, 0.64, 1) both;\n will-change: transform, opacity;\n}\n@supports (-webkit-touch-callout: none) {\n textarea[data-react-grab-input] {\n font-size: 16px;\n }\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-leading {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ordinal {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-slashed-zero {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-numeric-figure {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-numeric-spacing {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-numeric-fraction {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-outline-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-drop-shadow {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-drop-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-drop-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-drop-shadow-size {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-blur {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-brightness {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-contrast {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-grayscale {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-hue-rotate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-invert {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-opacity {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-saturate {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-backdrop-sepia {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ease {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-size {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-layout {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-paint {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-contain-style {\n syntax: \"*\";\n inherits: false;\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 *, ::before, ::after, ::backdrop {\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-leading: initial;\n --tw-font-weight: initial;\n --tw-ordinal: initial;\n --tw-slashed-zero: initial;\n --tw-numeric-figure: initial;\n --tw-numeric-spacing: initial;\n --tw-numeric-fraction: 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-contain-size: initial;\n --tw-contain-layout: initial;\n --tw-contain-paint: initial;\n --tw-contain-style: initial;\n }\n }\n}\n" === "string" ? styles_default : "");
3726
+ require_state.onCleanup(watchAppTheme(rendererHost).cleanup);
3727
+ const isThemeEnabled = require_state.createMemo(() => pluginRegistry.store.theme.enabled);
3728
+ const isSelectionBoxThemeEnabled = require_state.createMemo(() => pluginRegistry.store.theme.selectionBox.enabled);
3729
+ const isElementLabelThemeEnabled = require_state.createMemo(() => pluginRegistry.store.theme.elementLabel.enabled);
3730
+ const isDragBoxThemeEnabled = require_state.createMemo(() => pluginRegistry.store.theme.dragBox.enabled);
3731
+ const isSelectionSuppressed = require_state.createMemo(() => didJustCopy() || isToolbarSelectHovered() && !isFrozenPhase());
3732
+ const hasDragPreviewBounds = require_state.createMemo(() => dragPreviewBounds().length > 0);
3733
+ const selectionVisible = require_state.createMemo(() => {
3734
+ if (!isThemeEnabled()) return false;
3735
+ if (!isSelectionBoxThemeEnabled()) return false;
3736
+ if (isSelectionSuppressed()) return false;
3737
+ if (hasDragPreviewBounds()) return true;
3738
+ return isSelectionElementVisible();
3739
+ });
3740
+ const selectionTagName = require_state.createMemo(() => {
3741
+ const element = selectionElement();
3742
+ if (!element) return void 0;
3743
+ return require_freeze_updates.getTagName(element) || void 0;
3744
+ });
3745
+ require_state.createEffect(require_state.on(() => debouncedElementForComponentName(), (element) => {
3746
+ const currentVersion = ++componentNameRequestVersion;
3747
+ if (!element) {
3748
+ setResolvedComponentName(void 0);
3749
+ return;
3750
+ }
3751
+ const fallbackComponentName = require_freeze_updates.getComponentDisplayName(element) ?? void 0;
3752
+ setResolvedComponentName(fallbackComponentName);
3753
+ require_freeze_updates.getNearestComponentName(element).then((name) => {
3754
+ if (componentNameRequestVersion !== currentVersion) return;
3755
+ setResolvedComponentName(name ?? fallbackComponentName);
3756
+ }).catch(() => {
3757
+ if (componentNameRequestVersion !== currentVersion) return;
3758
+ setResolvedComponentName(fallbackComponentName);
3759
+ });
3760
+ }));
3761
+ const selectionLabelVisible = require_state.createMemo(() => {
3762
+ if (store.contextMenuPosition !== null) return false;
3763
+ if (!isElementLabelThemeEnabled()) return false;
3764
+ if (isSelectionSuppressed()) return false;
3765
+ return isSelectionElementVisible();
3766
+ });
3767
+ const labelInstanceCache = /* @__PURE__ */ new Map();
3768
+ const recomputeLabelInstance = (instance) => {
3769
+ const hasMultipleElements = instance.elements && instance.elements.length > 1;
3770
+ const instanceElement = instance.element;
3771
+ const newBounds = !hasMultipleElements && instanceElement && document.body.contains(instanceElement) ? createElementBounds(instanceElement) : instance.bounds;
3772
+ const previousInstance = labelInstanceCache.get(instance.id);
3773
+ const boundsUnchanged = previousInstance && previousInstance.bounds.x === newBounds.x && previousInstance.bounds.y === newBounds.y && previousInstance.bounds.width === newBounds.width && previousInstance.bounds.height === newBounds.height;
3774
+ if (previousInstance && previousInstance.status === instance.status && previousInstance.errorMessage === instance.errorMessage && boundsUnchanged) return previousInstance;
3775
+ const newBoundsCenterX = newBounds.x + newBounds.width / 2;
3776
+ const newBoundsHalfWidth = newBounds.width / 2;
3777
+ let newMouseX;
3778
+ if (instance.mouseXOffsetRatio !== void 0 && newBoundsHalfWidth > 0) newMouseX = newBoundsCenterX + instance.mouseXOffsetRatio * newBoundsHalfWidth;
3779
+ else if (instance.mouseXOffsetFromCenter !== void 0) newMouseX = newBoundsCenterX + instance.mouseXOffsetFromCenter;
3780
+ else newMouseX = instance.mouseX ?? newBoundsCenterX;
3781
+ const newCached = {
3782
+ ...instance,
3783
+ bounds: newBounds,
3784
+ mouseX: newMouseX
3785
+ };
3786
+ labelInstanceCache.set(instance.id, newCached);
3787
+ return newCached;
3788
+ };
3789
+ const computedLabelInstances = require_state.createMemo(() => {
3790
+ if (!isThemeEnabled()) return [];
3791
+ if (!pluginRegistry.store.theme.grabbedBoxes.enabled) return [];
3792
+ viewportVersion();
3793
+ const currentIds = new Set(store.labelInstances.map((instance) => instance.id));
3794
+ for (const cachedId of labelInstanceCache.keys()) if (!currentIds.has(cachedId)) labelInstanceCache.delete(cachedId);
3795
+ return store.labelInstances.map(recomputeLabelInstance);
3796
+ });
3797
+ const computedGrabbedBoxes = require_state.createMemo(() => {
3798
+ if (!isThemeEnabled()) return [];
3799
+ if (!pluginRegistry.store.theme.grabbedBoxes.enabled) return [];
3800
+ viewportVersion();
3801
+ return store.grabbedBoxes.map((box) => {
3802
+ if (!box.element || !document.body.contains(box.element)) return box;
3803
+ return {
3804
+ ...box,
3805
+ bounds: createElementBounds(box.element)
3806
+ };
3807
+ });
3808
+ });
3809
+ const dragVisible = require_state.createMemo(() => isThemeEnabled() && isDragBoxThemeEnabled() && isRendererActive() && isDraggingBeyondThreshold());
3810
+ const labelVariant = require_state.createMemo(() => isCopying() ? "processing" : "hover");
3811
+ const labelVisible = require_state.createMemo(() => {
3812
+ if (!isThemeEnabled()) return false;
3813
+ const themeEnabled = isElementLabelThemeEnabled();
3814
+ const inPromptMode = isPromptMode();
3815
+ const copying = isCopying();
3816
+ const rendererActive = isRendererActive();
3817
+ const dragging = isDragging();
3818
+ const hasElement = Boolean(effectiveElement());
3819
+ const toolbarSelectHovered = isToolbarSelectHovered();
3820
+ const frozen = isFrozenPhase();
3821
+ if (!themeEnabled) return false;
3822
+ if (inPromptMode) return false;
3823
+ if (toolbarSelectHovered && !frozen) return false;
3824
+ if (copying) return true;
3825
+ return rendererActive && !dragging && hasElement;
3826
+ });
3827
+ const contextMenuBounds = require_state.createMemo(() => {
3828
+ viewportVersion();
3829
+ const element = store.contextMenuElement;
3830
+ if (!element) return null;
3831
+ return createElementBounds(element);
3832
+ });
3833
+ const contextMenuPosition = require_state.createMemo(() => {
3834
+ viewportVersion();
3835
+ return store.contextMenuPosition;
3836
+ });
3837
+ const contextMenuTagName = require_state.createMemo(() => {
3838
+ const element = store.contextMenuElement;
3839
+ if (!element) return void 0;
3840
+ const frozenCount = store.frozenElements.length;
3841
+ if (frozenCount > 1) return `${frozenCount} elements`;
3842
+ return require_freeze_updates.getTagName(element) || void 0;
3843
+ });
3844
+ const [contextMenuComponentName] = require_state.createResource(() => ({
3845
+ element: store.contextMenuElement,
3846
+ frozenCount: store.frozenElements.length
3847
+ }), async ({ element, frozenCount }) => {
3848
+ if (!element) return void 0;
3849
+ if (frozenCount > 1) return void 0;
3850
+ return await require_freeze_updates.getNearestComponentName(element) ?? void 0;
3851
+ });
3852
+ const [contextMenuFilePath] = require_state.createResource(() => store.contextMenuElement, async (element) => {
3853
+ if (!element) return null;
3854
+ return require_freeze_updates.resolveSource(element);
3855
+ });
3856
+ const withSelectionInteractionLock = async (operation) => {
3857
+ actions.incrementSelectionInteractionLockDepth();
3858
+ try {
3859
+ return await operation();
3860
+ } finally {
3861
+ actions.decrementSelectionInteractionLockDepth();
3862
+ }
3863
+ };
3864
+ const createPerformWithFeedback = (element, elements, tagName, componentName, options) => {
3865
+ return async (action) => {
3866
+ await withSelectionInteractionLock(async () => {
3867
+ const fallbackBounds = options?.fallbackBounds ?? null;
3868
+ const fallbackSelectionBounds = options?.fallbackSelectionBounds ?? [];
3869
+ const position = options?.position ?? store.contextMenuPosition ?? pointer();
3870
+ const frozenBounds = frozenElementsBounds();
3871
+ const singleElementBounds = contextMenuBounds() ?? fallbackBounds;
3872
+ const hasMultipleElements = elements.length > 1;
3873
+ const labelBounds = hasMultipleElements ? createFlatOverlayBounds(combineBounds(frozenBounds)) : singleElementBounds;
3874
+ const shouldDeactivateAfter = store.wasActivatedByToggle;
3875
+ let selectionBoundsForLabel;
3876
+ if (hasMultipleElements) selectionBoundsForLabel = frozenBounds;
3877
+ else if (singleElementBounds) selectionBoundsForLabel = [singleElementBounds];
3878
+ else selectionBoundsForLabel = fallbackSelectionBounds;
3879
+ actions.hideContextMenu();
3880
+ if (labelBounds) {
3881
+ const labelCursorX = hasMultipleElements ? labelBounds.x + labelBounds.width / 2 : position.x;
3882
+ const labelInstanceId = createLabelInstance(labelBounds, tagName || "element", componentName, "copying", {
3883
+ element,
3884
+ mouseX: labelCursorX,
3885
+ elements: hasMultipleElements ? elements : void 0,
3886
+ boundsMultiple: selectionBoundsForLabel
3887
+ });
3888
+ let didSucceed = false;
3889
+ let errorMessage;
3890
+ try {
3891
+ didSucceed = await action();
3892
+ if (!didSucceed) errorMessage = "Failed to copy";
3893
+ } catch (error) {
3894
+ errorMessage = normalizeErrorMessage(error, "Action failed");
3895
+ }
3896
+ updateLabelAfterCopy(labelInstanceId, didSucceed, errorMessage);
3897
+ } else try {
3898
+ await action();
3899
+ } catch (error) {
3900
+ require_freeze_updates.logRecoverableError("Action failed without feedback bounds", error);
3901
+ }
3902
+ if (shouldDeactivateAfter) deactivateRenderer();
3903
+ else actions.unfreeze();
3904
+ });
3905
+ };
3906
+ };
3907
+ const deferHideContextMenu = () => {
3908
+ setTimeout(() => {
3909
+ actions.hideContextMenu();
3910
+ }, 0);
3911
+ };
3912
+ const buildActionContext = (options) => {
3913
+ const { element, filePath, lineNumber, tagName, componentName, position, performWithFeedbackOptions, shouldDeferHideContextMenu, onBeforeCopy, onBeforePrompt, customEnterPromptMode } = options;
3914
+ const elements = store.frozenElements.length > 0 ? store.frozenElements : [element];
3915
+ const hideContextMenuAction = shouldDeferHideContextMenu ? deferHideContextMenu : actions.hideContextMenu;
3916
+ const copyAction = () => {
3917
+ onBeforeCopy?.();
3918
+ performCopyWithLabel({
3919
+ element,
3920
+ cursorX: position.x,
3921
+ selectedElements: elements.length > 1 ? elements : void 0,
3922
+ shouldDeactivateAfter: store.wasActivatedByToggle
3923
+ });
3924
+ hideContextMenuAction();
3925
+ };
3926
+ const defaultEnterPromptMode = () => {
3927
+ clearAllLabels();
3928
+ onBeforePrompt?.();
3929
+ preparePromptMode(element, position.x, position.y);
3930
+ actions.setPointer({
3931
+ x: position.x,
3932
+ y: position.y
3933
+ });
3934
+ actions.setFrozenElement(element);
3935
+ activatePromptMode();
3936
+ if (!isActivated()) activateRenderer();
3937
+ hideContextMenuAction();
3938
+ };
3939
+ const context = {
3940
+ element,
3941
+ elements,
3942
+ filePath,
3943
+ lineNumber,
3944
+ componentName,
3945
+ tagName,
3946
+ enterPromptMode: customEnterPromptMode ?? defaultEnterPromptMode,
3947
+ copy: copyAction,
3948
+ hooks: {
3949
+ transformHtmlContent: pluginRegistry.hooks.transformHtmlContent,
3950
+ onOpenFile: pluginRegistry.hooks.onOpenFile,
3951
+ transformOpenFileUrl: pluginRegistry.hooks.transformOpenFileUrl
3952
+ },
3953
+ performWithFeedback: createPerformWithFeedback(element, elements, tagName, componentName, performWithFeedbackOptions),
3954
+ hideContextMenu: hideContextMenuAction,
3955
+ cleanup: () => {
3956
+ if (store.wasActivatedByToggle) deactivateRenderer();
3957
+ else actions.unfreeze();
3958
+ }
3959
+ };
3960
+ const transformedContext = pluginRegistry.hooks.transformActionContext(context);
3961
+ return {
3962
+ ...context,
3963
+ ...transformedContext
3964
+ };
3965
+ };
3966
+ const contextMenuActionContext = require_state.createMemo(() => {
3967
+ const element = store.contextMenuElement;
3968
+ if (!element) return void 0;
3969
+ const fileInfo = contextMenuFilePath();
3970
+ const position = store.contextMenuPosition ?? pointer();
3971
+ return buildActionContext({
3972
+ element,
3973
+ filePath: fileInfo?.filePath,
3974
+ lineNumber: fileInfo?.lineNumber ?? void 0,
3975
+ tagName: contextMenuTagName(),
3976
+ componentName: contextMenuComponentName(),
3977
+ position,
3978
+ shouldDeferHideContextMenu: true,
3979
+ onBeforeCopy: () => {
3980
+ keyboardSelectedElement = null;
3981
+ },
3982
+ customEnterPromptMode: () => {
3983
+ clearAllLabels();
3984
+ actions.clearInputText();
3985
+ actions.enterPromptMode(position, element);
3986
+ deferHideContextMenu();
3987
+ }
3988
+ });
3989
+ });
3990
+ const handleContextMenuDismiss = () => {
3991
+ setTimeout(() => {
3992
+ actions.hideContextMenu();
3993
+ deactivateRenderer();
3994
+ }, 0);
3995
+ };
3996
+ const stopTrackingDropdownPosition = () => {
3997
+ if (dropdownTrackingFrameId !== null) {
3998
+ require_freeze_updates.nativeCancelAnimationFrame(dropdownTrackingFrameId);
3999
+ dropdownTrackingFrameId = null;
4000
+ }
4001
+ };
4002
+ const computeDropdownAnchor = () => {
4003
+ if (!toolbarElement) return null;
4004
+ const toolbarRect = toolbarElement.getBoundingClientRect();
4005
+ const edge = getNearestEdge(toolbarRect);
4006
+ if (edge === "left" || edge === "right") return {
4007
+ x: edge === "left" ? toolbarRect.right : toolbarRect.left,
4008
+ y: toolbarRect.top + toolbarRect.height / 2,
4009
+ edge,
4010
+ toolbarWidth: toolbarRect.width
4011
+ };
4012
+ return {
4013
+ x: toolbarRect.left + toolbarRect.width / 2,
4014
+ y: edge === "top" ? toolbarRect.bottom : toolbarRect.top,
4015
+ edge,
4016
+ toolbarWidth: toolbarRect.width
4017
+ };
4018
+ };
4019
+ const openTrackedDropdown = (setPosition) => {
4020
+ stopTrackingDropdownPosition();
4021
+ const updatePosition = () => {
4022
+ const anchor = computeDropdownAnchor();
4023
+ if (anchor) setPosition(anchor);
4024
+ dropdownTrackingFrameId = require_freeze_updates.nativeRequestAnimationFrame(updatePosition);
4025
+ };
4026
+ updatePosition();
4027
+ };
4028
+ const dismissToolbarMenu = () => {
4029
+ stopTrackingDropdownPosition();
4030
+ setToolbarMenuPosition(null);
4031
+ };
4032
+ const dismissAllPopups = () => {
4033
+ dismissToolbarMenu();
4034
+ };
4035
+ const handleToggleToolbarMenu = () => {
4036
+ if (toolbarMenuPosition() !== null) dismissToolbarMenu();
4037
+ else {
4038
+ actions.hideContextMenu();
4039
+ openTrackedDropdown(setToolbarMenuPosition);
4040
+ }
4041
+ };
4042
+ const handleSetDefaultAction = (actionId) => {
4043
+ updateToolbarState({ defaultAction: actionId });
4044
+ };
4045
+ const handleShowContextMenuInstance = (instanceId) => {
4046
+ const instance = store.labelInstances.find((labelInstance) => labelInstance.id === instanceId);
4047
+ if (!instance?.element) return;
4048
+ if (!require_state.isElementConnected(instance.element)) return;
4049
+ const contextMenuElement = instance.element;
4050
+ const center = getBoundsCenter(createElementBounds(contextMenuElement));
4051
+ const position = {
4052
+ x: instance.mouseX ?? center.x,
4053
+ y: center.y
4054
+ };
4055
+ const elementsToFreeze = instance.elements && instance.elements.length > 0 ? instance.elements.filter((element) => require_state.isElementConnected(element)) : [contextMenuElement];
4056
+ setTimeout(() => {
4057
+ if (!isActivated()) {
4058
+ actions.setWasActivatedByToggle(true);
4059
+ activateRenderer();
4060
+ }
4061
+ actions.setPointer(position);
4062
+ actions.setFrozenElements(elementsToFreeze);
4063
+ if (elementsToFreeze.length > 1 && instance.bounds) actions.setFrozenDragRect(createPageRectFromBounds(instance.bounds));
4064
+ actions.freeze();
4065
+ actions.showContextMenu(position, contextMenuElement);
4066
+ }, 0);
4067
+ };
4068
+ require_state.createEffect(() => {
4069
+ const hue = pluginRegistry.store.theme.hue;
4070
+ if (hue !== 0) rendererRoot.style.filter = `hue-rotate(${hue}deg)`;
4071
+ else rendererRoot.style.filter = "";
4072
+ });
4073
+ if (pluginRegistry.store.theme.enabled) Promise.resolve().then(() => require("./renderer-Bxc3RS-J.cjs")).then(({ ReactGrabRenderer }) => {
4074
+ if (disposed) return;
4075
+ disposeRenderer = require_state.render(() => {
4076
+ return require_state.createComponent(ReactGrabRenderer, {
4077
+ get selectionVisible() {
4078
+ return selectionVisible();
4079
+ },
4080
+ get selectionBounds() {
4081
+ return selectionBounds();
4082
+ },
4083
+ get selectionBoundsMultiple() {
4084
+ return selectionBoundsMultiple();
4085
+ },
4086
+ get selectionShouldSnap() {
4087
+ return store.frozenElements.length > 0 || dragPreviewBounds().length > 0;
4088
+ },
4089
+ get selectionElementsCount() {
4090
+ return store.frozenElements.length;
4091
+ },
4092
+ get frozenLabelEntries() {
4093
+ return frozenLabelEntries();
4094
+ },
4095
+ get pendingShiftPreviewEntry() {
4096
+ return pendingShiftPreviewEntry() ?? void 0;
4097
+ },
4098
+ get selectionFilePath() {
4099
+ return store.selectionFilePath ?? void 0;
4100
+ },
4101
+ get selectionLineNumber() {
4102
+ return store.selectionLineNumber ?? void 0;
4103
+ },
4104
+ get selectionTagName() {
4105
+ return selectionTagName();
4106
+ },
4107
+ get selectionComponentName() {
4108
+ return resolvedComponentName();
4109
+ },
4110
+ get selectionLabelVisible() {
4111
+ return selectionLabelVisible();
4112
+ },
4113
+ selectionLabelStatus: "idle",
4114
+ get selectionArrowNavigationState() {
4115
+ return arrowNavigationState();
4116
+ },
4117
+ onArrowNavigationSelect: handleArrowNavigationSelect,
4118
+ get labelInstances() {
4119
+ return computedLabelInstances();
4120
+ },
4121
+ get dragVisible() {
4122
+ return dragVisible();
4123
+ },
4124
+ get dragBounds() {
4125
+ return dragBounds();
4126
+ },
4127
+ get grabbedBoxes() {
4128
+ return computedGrabbedBoxes();
4129
+ },
4130
+ get mouseX() {
4131
+ return require_state.memo(() => store.frozenElements.length > 1)() ? void 0 : shiftSelectionLabelMouseX() ?? cursorPosition().x;
4132
+ },
4133
+ get isFrozen() {
4134
+ return isFrozenPhase() || isActivated() || isToolbarSelectHovered();
4135
+ },
4136
+ get inputValue() {
4137
+ return store.inputText;
4138
+ },
4139
+ get isPromptMode() {
4140
+ return isPromptMode();
4141
+ },
4142
+ onShowContextMenuInstance: handleShowContextMenuInstance,
4143
+ onLabelInstanceHoverChange: handleLabelInstanceHoverChange,
4144
+ get onInputChange() {
4145
+ return actions.setInputText;
4146
+ },
4147
+ onInputSubmit: () => void handleInputSubmit(),
4148
+ onToggleExpand: handleToggleExpand,
4149
+ get isPendingDismiss() {
4150
+ return isPendingDismiss();
4151
+ },
4152
+ get selectionLabelShakeCount() {
4153
+ return selectionLabelShakeCount();
4154
+ },
4155
+ onConfirmDismiss: handleConfirmDismiss,
4156
+ onCancelDismiss: handleCancelDismiss,
4157
+ get toolbarVisible() {
4158
+ return pluginRegistry.store.theme.toolbar.enabled;
4159
+ },
4160
+ get isActive() {
4161
+ return isActivated();
4162
+ },
4163
+ onToggleActive: handleToggleActive,
4164
+ get enabled() {
4165
+ return isEnabled();
4166
+ },
4167
+ get shakeCount() {
4168
+ return toolbarShakeCount();
4169
+ },
4170
+ onToolbarStateChange: (state) => {
4171
+ setCurrentToolbarState(state);
4172
+ if (state.enabled !== isEnabled()) {
4173
+ setIsEnabled(state.enabled);
4174
+ if (!state.enabled) {
4175
+ forceDeactivateAll();
4176
+ dismissAllPopups();
4177
+ }
4178
+ }
4179
+ toolbarStateChangeCallbacks.forEach((callback) => callback(state));
4180
+ },
4181
+ onSubscribeToToolbarStateChanges: (callback) => {
4182
+ toolbarStateChangeCallbacks.add(callback);
4183
+ return () => {
4184
+ toolbarStateChangeCallbacks.delete(callback);
4185
+ };
4186
+ },
4187
+ onToolbarSelectHoverChange: setIsToolbarSelectHovered,
4188
+ onToolbarRef: (element) => {
4189
+ toolbarElement = element;
4190
+ },
4191
+ get contextMenuPosition() {
4192
+ return contextMenuPosition();
4193
+ },
4194
+ get contextMenuBounds() {
4195
+ return contextMenuBounds();
4196
+ },
4197
+ get contextMenuTagName() {
4198
+ return contextMenuTagName();
4199
+ },
4200
+ get contextMenuComponentName() {
4201
+ return contextMenuComponentName();
4202
+ },
4203
+ get contextMenuHasFilePath() {
4204
+ return Boolean(contextMenuFilePath()?.filePath);
4205
+ },
4206
+ get actions() {
4207
+ return pluginRegistry.store.actions;
4208
+ },
4209
+ get actionContext() {
4210
+ return contextMenuActionContext();
4211
+ },
4212
+ onContextMenuDismiss: handleContextMenuDismiss,
4213
+ onContextMenuHide: deferHideContextMenu,
4214
+ get toolbarMenuPosition() {
4215
+ return toolbarMenuPosition();
4216
+ },
4217
+ get toolbarMenuActions() {
4218
+ return pluginRegistry.store.actions.filter((action) => action.showInToolbarMenu === true);
4219
+ },
4220
+ get defaultActionId() {
4221
+ return currentToolbarState()?.defaultAction ?? "comment";
4222
+ },
4223
+ onSetDefaultAction: handleSetDefaultAction,
4224
+ onToggleToolbarMenu: handleToggleToolbarMenu,
4225
+ onToolbarMenuDismiss: dismissToolbarMenu
4226
+ });
4227
+ }, rendererRoot);
4228
+ }).catch((error) => {
4229
+ console.warn("[react-grab] Failed to load renderer:", error);
4230
+ });
4231
+ const copyElementAPI = async (elements) => {
4232
+ const elementsArray = Array.isArray(elements) ? elements : [elements];
4233
+ if (elementsArray.length === 0) return false;
4234
+ return await copyWithFallback(elementsArray);
4235
+ };
4236
+ const api = {
4237
+ activate: () => {
4238
+ actions.setPendingCommentMode(false);
4239
+ if (!isActivated() && isEnabled()) toggleActivate();
4240
+ },
4241
+ deactivate: () => {
4242
+ if (isActivated() || isCopying()) deactivateRenderer();
4243
+ },
4244
+ toggle: () => {
4245
+ if (isActivated()) deactivateRenderer();
4246
+ else if (isEnabled()) toggleActivate();
4247
+ },
4248
+ comment: handleComment,
4249
+ isActive: () => isActivated(),
4250
+ isEnabled: () => isEnabled(),
4251
+ setEnabled: (enabled) => {
4252
+ if (enabled === isEnabled()) return;
4253
+ setIsEnabled(enabled);
4254
+ updateToolbarState({
4255
+ enabled,
4256
+ collapsed: !enabled
4257
+ });
4258
+ if (!enabled) {
4259
+ forceDeactivateAll();
4260
+ dismissAllPopups();
4261
+ }
4262
+ },
4263
+ getToolbarState: () => require_state.loadToolbarState(),
4264
+ setToolbarState: (state) => {
4265
+ const currentState = require_state.loadToolbarState();
4266
+ const resolvedCollapsed = state.collapsed ?? currentState?.collapsed ?? false;
4267
+ const newState = {
4268
+ edge: state.edge ?? currentState?.edge ?? "bottom",
4269
+ ratio: state.ratio ?? currentState?.ratio ?? .5,
4270
+ collapsed: resolvedCollapsed,
4271
+ enabled: !resolvedCollapsed,
4272
+ defaultAction: state.defaultAction ?? currentState?.defaultAction ?? "comment"
4273
+ };
4274
+ require_state.saveToolbarState(newState);
4275
+ setCurrentToolbarState(newState);
4276
+ if (newState.enabled !== isEnabled()) {
4277
+ setIsEnabled(newState.enabled);
4278
+ if (!newState.enabled) {
4279
+ forceDeactivateAll();
4280
+ dismissAllPopups();
4281
+ }
4282
+ }
4283
+ toolbarStateChangeCallbacks.forEach((callback) => callback(newState));
4284
+ },
4285
+ onToolbarStateChange: (callback) => {
4286
+ toolbarStateChangeCallbacks.add(callback);
4287
+ return () => {
4288
+ toolbarStateChangeCallbacks.delete(callback);
4289
+ };
4290
+ },
4291
+ dispose: () => {
4292
+ disposed = true;
4293
+ hasInited = false;
4294
+ disposeRenderer?.();
4295
+ stopTrackingDropdownPosition();
4296
+ toolbarStateChangeCallbacks.clear();
4297
+ dispose();
4298
+ },
4299
+ copyElement: copyElementAPI,
4300
+ getSource: async (element) => {
4301
+ const source = await require_freeze_updates.resolveSource(element);
4302
+ if (!source) return null;
4303
+ return {
4304
+ filePath: source.filePath,
4305
+ lineNumber: source.lineNumber,
4306
+ componentName: source.componentName
4307
+ };
4308
+ },
4309
+ getStackContext: require_freeze_updates.getStackContext,
4310
+ getState: () => ({
4311
+ isActive: isActivated(),
4312
+ isDragging: isDragging(),
4313
+ isCopying: isCopying(),
4314
+ isPromptMode: isPromptMode(),
4315
+ isSelectionBoxVisible: Boolean(selectionVisible()),
4316
+ isDragBoxVisible: Boolean(dragVisible()),
4317
+ targetElement: targetElement(),
4318
+ dragBounds: dragBounds() ?? null,
4319
+ grabbedBoxes: [...publicGrabbedBoxes()],
4320
+ labelInstances: [...publicLabelInstances()],
4321
+ selectionFilePath: store.selectionFilePath,
4322
+ toolbarState: currentToolbarState()
4323
+ }),
4324
+ setOptions: (newOptions) => {
4325
+ pluginRegistry.setOptions(newOptions);
4326
+ },
4327
+ registerPlugin: (plugin) => {
4328
+ pluginRegistry.register(plugin, api);
4329
+ },
4330
+ unregisterPlugin: (name) => {
4331
+ pluginRegistry.unregister(name);
4332
+ },
4333
+ getPlugins: () => pluginRegistry.getPluginNames(),
4334
+ getDisplayName: require_freeze_updates.getComponentDisplayName
4335
+ };
4336
+ for (const plugin of builtInPlugins) pluginRegistry.register(plugin, api);
4337
+ setTimeout(() => {
4338
+ require_freeze_updates.checkIsNextProject(true);
4339
+ }, require_freeze_updates.NEXTJS_REVALIDATION_DELAY_MS);
4340
+ return api;
4341
+ });
4342
+ };
4343
+
4344
+ //#endregion
4345
+ Object.defineProperty(exports, 'DEFAULT_THEME', {
4346
+ enumerable: true,
4347
+ get: function () {
4348
+ return DEFAULT_THEME;
4349
+ }
4350
+ });
4351
+ Object.defineProperty(exports, 'commentPlugin', {
4352
+ enumerable: true,
4353
+ get: function () {
4354
+ return commentPlugin;
4355
+ }
4356
+ });
4357
+ Object.defineProperty(exports, 'generateSnippet', {
4358
+ enumerable: true,
4359
+ get: function () {
4360
+ return generateSnippet;
4361
+ }
4362
+ });
4363
+ Object.defineProperty(exports, 'init', {
4364
+ enumerable: true,
4365
+ get: function () {
4366
+ return init;
4367
+ }
4368
+ });
4369
+ Object.defineProperty(exports, 'openPlugin', {
4370
+ enumerable: true,
4371
+ get: function () {
4372
+ return openPlugin;
4373
+ }
4374
+ });