Fix FunLightbox and FunTooltip
This commit is contained in:
parent
0a91232634
commit
06ff9fa09e
13 changed files with 891 additions and 211 deletions
|
@ -197,6 +197,30 @@ Signal Desktop makes use of the following open source projects.
|
|||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## @radix-ui/react-tooltip
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 WorkOS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## @react-aria/focus
|
||||
|
||||
Apache License
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
"@indutny/simple-windows-notifications": "2.0.16",
|
||||
"@indutny/sneequals": "4.0.0",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"@radix-ui/react-tooltip": "1.2.7",
|
||||
"@react-aria/focus": "3.19.1",
|
||||
"@react-aria/interactions": "3.23.0",
|
||||
"@react-aria/utils": "3.25.3",
|
||||
|
|
420
pnpm-lock.yaml
generated
420
pnpm-lock.yaml
generated
|
@ -110,6 +110,9 @@ importers:
|
|||
'@popperjs/core':
|
||||
specifier: 2.11.8
|
||||
version: 2.11.8
|
||||
'@radix-ui/react-tooltip':
|
||||
specifier: 1.2.7
|
||||
version: 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@react-aria/focus':
|
||||
specifier: 3.19.1
|
||||
version: 3.19.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
|
@ -1333,6 +1336,21 @@ packages:
|
|||
resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
||||
'@floating-ui/core@1.7.0':
|
||||
resolution: {integrity: sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==}
|
||||
|
||||
'@floating-ui/dom@1.7.0':
|
||||
resolution: {integrity: sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==}
|
||||
|
||||
'@floating-ui/react-dom@2.1.2':
|
||||
resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
|
||||
'@floating-ui/utils@0.2.9':
|
||||
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
|
||||
|
||||
'@formatjs/ecma402-abstract@1.11.4':
|
||||
resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==}
|
||||
|
||||
|
@ -1918,6 +1936,215 @@ packages:
|
|||
'@protobufjs/utf8@1.1.0':
|
||||
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
|
||||
|
||||
'@radix-ui/primitive@1.1.2':
|
||||
resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==}
|
||||
|
||||
'@radix-ui/react-arrow@1.1.7':
|
||||
resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-compose-refs@1.1.2':
|
||||
resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-context@1.1.2':
|
||||
resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.10':
|
||||
resolution: {integrity: sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-id@1.1.1':
|
||||
resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-popper@1.2.7':
|
||||
resolution: {integrity: sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-portal@1.1.9':
|
||||
resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-presence@1.1.4':
|
||||
resolution: {integrity: sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-primitive@2.1.3':
|
||||
resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-slot@1.2.3':
|
||||
resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-tooltip@1.2.7':
|
||||
resolution: {integrity: sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-callback-ref@1.1.1':
|
||||
resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-controllable-state@1.2.2':
|
||||
resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-effect-event@0.0.2':
|
||||
resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.1.1':
|
||||
resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-layout-effect@1.1.1':
|
||||
resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-rect@1.1.1':
|
||||
resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-size@1.1.1':
|
||||
resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-visually-hidden@1.2.3':
|
||||
resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/rect@1.1.1':
|
||||
resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
|
||||
|
||||
'@react-aria/accordion@3.0.0-alpha.35':
|
||||
resolution: {integrity: sha512-eZcsHJDVDNIZ2XUmJynHScRv1YAF/+fj5T0zoGdyEPImIIxJLROupQ75uwarAI5btGSR2TFeqYRmRXJrVuxgoA==}
|
||||
peerDependencies:
|
||||
|
@ -10171,6 +10398,23 @@ snapshots:
|
|||
|
||||
'@eslint/js@8.56.0': {}
|
||||
|
||||
'@floating-ui/core@1.7.0':
|
||||
dependencies:
|
||||
'@floating-ui/utils': 0.2.9
|
||||
|
||||
'@floating-ui/dom@1.7.0':
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.7.0
|
||||
'@floating-ui/utils': 0.2.9
|
||||
|
||||
'@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.7.0
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@floating-ui/utils@0.2.9': {}
|
||||
|
||||
'@formatjs/ecma402-abstract@1.11.4':
|
||||
dependencies:
|
||||
'@formatjs/intl-localematcher': 0.2.25
|
||||
|
@ -10946,6 +11190,182 @@ snapshots:
|
|||
|
||||
'@protobufjs/utf8@1.1.0': {}
|
||||
|
||||
'@radix-ui/primitive@1.1.2': {}
|
||||
|
||||
'@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-context@1.1.2(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/react-id@1.1.1(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-popper@1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/rect': 1.1.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/react-presence@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/react-slot@1.2.3(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-tooltip@1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-popper': 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-presence': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.20)(react@18.3.1)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-use-rect@1.1.1(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/rect': 1.1.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-use-size@1.1.1(@types/react@18.3.20)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
|
||||
'@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.20
|
||||
'@types/react-dom': 18.3.6(@types/react@18.3.20)
|
||||
|
||||
'@radix-ui/rect@1.1.1': {}
|
||||
|
||||
'@react-aria/accordion@3.0.0-alpha.35(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@react-aria/button': 3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
|
|
|
@ -136,6 +136,7 @@ $image-radius: $button-radius - $image-margin;
|
|||
}
|
||||
|
||||
.FunSubNav__ListBoxItem {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
padding: 1px;
|
||||
cursor: pointer;
|
||||
|
@ -154,6 +155,13 @@ $image-radius: $button-radius - $image-margin;
|
|||
}
|
||||
}
|
||||
|
||||
.FunSubNav__ListBoxItem__TooltipTarget {
|
||||
display: block;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.FunSubNav__ListBoxItem__Button {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
@use './FunConstants.scss';
|
||||
|
||||
.FunTooltip {
|
||||
position: relative;
|
||||
z-index: 100000;
|
||||
max-width: calc(32ch + (8px * 2));
|
||||
padding-block: 4px;
|
||||
padding-inline: 8px;
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import type { ForwardedRef, ReactNode } from 'react';
|
||||
import React, { forwardRef, useEffect, useRef } from 'react';
|
||||
import { type PressEvent, useLongPress } from 'react-aria';
|
||||
import type { LongPressEvent } from '@react-types/shared';
|
||||
import { Button } from 'react-aria-components';
|
||||
import { mergeRefs } from '@react-aria/utils';
|
||||
import { PressResponder } from '@react-aria/interactions';
|
||||
import type {
|
||||
ForwardedRef,
|
||||
ReactNode,
|
||||
DOMAttributes,
|
||||
PointerEvent,
|
||||
} from 'react';
|
||||
import React, { forwardRef, useCallback, useEffect, useMemo } from 'react';
|
||||
import { mergeProps } from '@react-aria/utils';
|
||||
import { strictAssert } from '../../../util/assert';
|
||||
|
||||
/**
|
||||
|
@ -28,49 +29,120 @@ export type FunItemButtonProps = Readonly<
|
|||
{
|
||||
'aria-label': string;
|
||||
excludeFromTabOrder: boolean;
|
||||
onPress: (event: PressEvent) => void;
|
||||
onContextMenu?: (event: MouseEvent) => void;
|
||||
onClick: (event: PointerEvent) => void;
|
||||
onContextMenu?: (event: PointerEvent) => void;
|
||||
children: ReactNode;
|
||||
} & FunItemButtonLongPressProps
|
||||
>;
|
||||
|
||||
export const FunItemButton = forwardRef(function FunItemButton(
|
||||
props: FunItemButtonProps,
|
||||
outerRef: ForwardedRef<HTMLButtonElement>
|
||||
ref: ForwardedRef<HTMLButtonElement>
|
||||
): JSX.Element {
|
||||
const { onContextMenu } = props;
|
||||
const innerRef = useRef<HTMLButtonElement>(null);
|
||||
const {
|
||||
'aria-label': ariaLabel,
|
||||
excludeFromTabOrder,
|
||||
onClick,
|
||||
onContextMenu,
|
||||
children,
|
||||
longPressAccessibilityDescription,
|
||||
onLongPress,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const { longPressProps } = useLongPress({
|
||||
isDisabled: props.onLongPress == null,
|
||||
accessibilityDescription: props.longPressAccessibilityDescription,
|
||||
onLongPress: props.onLongPress,
|
||||
});
|
||||
const longPressProps = useLongPress(onLongPress ?? null);
|
||||
|
||||
useEffect(() => {
|
||||
strictAssert(innerRef.current, 'Missing ref element');
|
||||
const element = innerRef.current;
|
||||
if (onContextMenu == null) {
|
||||
return () => null;
|
||||
}
|
||||
element.addEventListener('contextmenu', onContextMenu);
|
||||
return () => {
|
||||
element.removeEventListener('contextmenu', onContextMenu);
|
||||
};
|
||||
}, [onContextMenu]);
|
||||
const handleClick = useCallback(
|
||||
(event: PointerEvent) => {
|
||||
if (!event.defaultPrevented) {
|
||||
onClick(event);
|
||||
}
|
||||
},
|
||||
[onClick]
|
||||
);
|
||||
|
||||
return (
|
||||
<PressResponder {...longPressProps}>
|
||||
<Button
|
||||
ref={mergeRefs(innerRef, outerRef)}
|
||||
type="button"
|
||||
className="FunItem__Button"
|
||||
aria-label={props['aria-label']}
|
||||
excludeFromTabOrder={props.excludeFromTabOrder}
|
||||
onPress={props.onPress}
|
||||
>
|
||||
{props.children}
|
||||
</Button>
|
||||
</PressResponder>
|
||||
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
||||
<button
|
||||
ref={ref}
|
||||
type="button"
|
||||
className="FunItem__Button"
|
||||
aria-label={ariaLabel}
|
||||
aria-description={longPressAccessibilityDescription}
|
||||
tabIndex={excludeFromTabOrder ? -1 : undefined}
|
||||
{...mergeProps(
|
||||
longPressProps,
|
||||
{
|
||||
onClick: handleClick,
|
||||
onContextMenu,
|
||||
},
|
||||
rest
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
type LongPressEvent = Readonly<{
|
||||
pointerType: PointerEvent['pointerType'];
|
||||
}>;
|
||||
|
||||
function useLongPress(
|
||||
onLongPress: ((event: LongPressEvent) => void) | null
|
||||
): DOMAttributes<Element> {
|
||||
const { cleanup, props } = useMemo(() => {
|
||||
if (onLongPress == null) {
|
||||
return { props: {} };
|
||||
}
|
||||
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
let isLongPressed = false;
|
||||
let lastLongPress: number | null = null;
|
||||
|
||||
function reset() {
|
||||
clearTimeout(timer);
|
||||
isLongPressed = false;
|
||||
}
|
||||
|
||||
function handleCancel(event: PointerEvent) {
|
||||
if (isLongPressed) {
|
||||
lastLongPress = event.timeStamp;
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
function handleStart(event: PointerEvent) {
|
||||
const press: LongPressEvent = { pointerType: event.pointerType };
|
||||
reset();
|
||||
timer = setTimeout(() => {
|
||||
isLongPressed = true;
|
||||
strictAssert(onLongPress != null, 'Missing callback');
|
||||
onLongPress(press);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function handleClick(event: PointerEvent) {
|
||||
if (event.timeStamp === lastLongPress) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
cleanup: reset,
|
||||
props: {
|
||||
onPointerDown: handleStart,
|
||||
onPointerUp: handleCancel,
|
||||
onPointerCancel: handleCancel,
|
||||
onPointerLeave: handleCancel,
|
||||
onClick: handleClick,
|
||||
} satisfies DOMAttributes<Element>,
|
||||
};
|
||||
}, [onLongPress]);
|
||||
|
||||
useEffect(() => {
|
||||
return cleanup;
|
||||
}, [cleanup]);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import React, { useCallback } from 'react';
|
|||
import type { Placement } from 'react-aria';
|
||||
import { Dialog, Popover } from 'react-aria-components';
|
||||
import classNames from 'classnames';
|
||||
import * as Tooltip from '@radix-ui/react-tooltip';
|
||||
import { ThemeType } from '../../../types/Util';
|
||||
|
||||
export type FunPopoverProps = Readonly<{
|
||||
|
@ -16,8 +17,14 @@ export type FunPopoverProps = Readonly<{
|
|||
export function FunPopover(props: FunPopoverProps): JSX.Element {
|
||||
const shouldCloseOnInteractOutside = useCallback(
|
||||
(element: Element): boolean => {
|
||||
// Don't close when quill steals focus
|
||||
const match = element.closest('.module-composition-input__input');
|
||||
const match = element.closest(
|
||||
[
|
||||
// Don't close when quill steals focus
|
||||
'.module-composition-input__input',
|
||||
// Don't close when clicking tooltip
|
||||
'.FunTooltip',
|
||||
].join(', ')
|
||||
);
|
||||
if (match != null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -27,16 +34,18 @@ export function FunPopover(props: FunPopoverProps): JSX.Element {
|
|||
);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
data-fun-overlay
|
||||
className={classNames('FunPopover', {
|
||||
'light-theme': props.theme === ThemeType.light,
|
||||
'dark-theme': props.theme === ThemeType.dark,
|
||||
})}
|
||||
placement={props.placement}
|
||||
shouldCloseOnInteractOutside={shouldCloseOnInteractOutside}
|
||||
>
|
||||
<Dialog className="FunPopover__Dialog">{props.children}</Dialog>
|
||||
</Popover>
|
||||
<Tooltip.Provider>
|
||||
<Popover
|
||||
data-fun-overlay
|
||||
className={classNames('FunPopover', {
|
||||
'light-theme': props.theme === ThemeType.light,
|
||||
'dark-theme': props.theme === ThemeType.dark,
|
||||
})}
|
||||
placement={props.placement}
|
||||
shouldCloseOnInteractOutside={shouldCloseOnInteractOutside}
|
||||
>
|
||||
<Dialog className="FunPopover__Dialog">{props.children}</Dialog>
|
||||
</Popover>
|
||||
</Tooltip.Provider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import classNames from 'classnames';
|
||||
import type { Transition } from 'framer-motion';
|
||||
import { motion } from 'framer-motion';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ReactNode, Ref } from 'react';
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
|
@ -13,6 +13,7 @@ import React, {
|
|||
useRef,
|
||||
useState,
|
||||
useId,
|
||||
forwardRef,
|
||||
} from 'react';
|
||||
import type { Selection } from 'react-aria-components';
|
||||
import { ListBox, ListBoxItem } from 'react-aria-components';
|
||||
|
@ -25,6 +26,7 @@ import * as log from '../../../logging/log';
|
|||
import * as Errors from '../../../types/errors';
|
||||
import { strictAssert } from '../../../util/assert';
|
||||
import { FunImage } from './FunImage';
|
||||
import { FunTooltip } from './FunTooltip';
|
||||
|
||||
/**
|
||||
* Sub Nav
|
||||
|
@ -246,11 +248,30 @@ function FunSubNavListBoxItemButton(props: {
|
|||
);
|
||||
}
|
||||
|
||||
const FunSubNavListBoxItemTooltipTarget = forwardRef(
|
||||
function FunSubNavListBoxItemTooltipTarget(props, ref: Ref<HTMLSpanElement>) {
|
||||
return (
|
||||
<span
|
||||
ref={ref}
|
||||
{...props}
|
||||
className="FunSubNav__ListBoxItem__TooltipTarget"
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export function FunSubNavListBoxItem(
|
||||
props: FunSubNavListBoxItemProps
|
||||
): JSX.Element {
|
||||
const context = useContext(FunSubNavListBoxContext);
|
||||
strictAssert(context, 'Must be wrapped with <FunSubNavListBox>');
|
||||
|
||||
const [tooltipOpen, setTooltipOpen] = useState(false);
|
||||
|
||||
const handleTooltipOpenChange = useCallback((open: boolean) => {
|
||||
setTooltipOpen(open);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ListBoxItem
|
||||
id={props.id}
|
||||
|
@ -260,22 +281,35 @@ export function FunSubNavListBoxItem(
|
|||
>
|
||||
{({ isSelected, isFocusVisible }) => {
|
||||
return (
|
||||
<FunSubNavListBoxItemButton isSelected={isSelected}>
|
||||
<span className="FunSubNav__ListBoxItem__ButtonIcon">
|
||||
{props.children}
|
||||
</span>
|
||||
{isSelected && (
|
||||
<motion.div
|
||||
className="FunSubNav__ListBoxItem__ButtonIndicator"
|
||||
layoutId={`FunSubNav__ListBoxItem__ButtonIndicator--${context.id}`}
|
||||
layoutDependency={context.selected}
|
||||
transition={FunSubNavListBoxItemTransition}
|
||||
/>
|
||||
)}
|
||||
{!isSelected && isFocusVisible && (
|
||||
<div className="FunSubNav__ListBoxItem__ButtonIndicator" />
|
||||
)}
|
||||
</FunSubNavListBoxItemButton>
|
||||
<>
|
||||
<FunTooltip
|
||||
open={tooltipOpen || (isSelected && isFocusVisible)}
|
||||
onOpenChange={handleTooltipOpenChange}
|
||||
side="top"
|
||||
content={props.label}
|
||||
collisionBoundarySelector=".FunPanel"
|
||||
collisionPadding={6}
|
||||
disableHoverableContent
|
||||
>
|
||||
<FunSubNavListBoxItemTooltipTarget />
|
||||
</FunTooltip>
|
||||
<FunSubNavListBoxItemButton isSelected={isSelected}>
|
||||
<span className="FunSubNav__ListBoxItem__ButtonIcon">
|
||||
{props.children}
|
||||
</span>
|
||||
{isSelected && (
|
||||
<motion.div
|
||||
className="FunSubNav__ListBoxItem__ButtonIndicator"
|
||||
layoutId={`FunSubNav__ListBoxItem__ButtonIndicator--${context.id}`}
|
||||
layoutDependency={context.selected}
|
||||
transition={FunSubNavListBoxItemTransition}
|
||||
/>
|
||||
)}
|
||||
{!isSelected && isFocusVisible && (
|
||||
<div className="FunSubNav__ListBoxItem__ButtonIndicator" />
|
||||
)}
|
||||
</FunSubNavListBoxItemButton>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</ListBoxItem>
|
||||
|
|
|
@ -1,19 +1,57 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { type ReactNode } from 'react';
|
||||
import type { Placement } from 'react-aria';
|
||||
import { Tooltip } from 'react-aria-components';
|
||||
import React, { useRef, useState, type ReactNode } from 'react';
|
||||
import * as Tooltip from '@radix-ui/react-tooltip';
|
||||
import { useLayoutEffect } from '@react-aria/utils';
|
||||
import { strictAssert } from '../../../util/assert';
|
||||
|
||||
export type FunTooltipProps = Readonly<{
|
||||
placement?: Placement;
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
disableHoverableContent?: boolean;
|
||||
side?: Tooltip.TooltipContentProps['side'];
|
||||
align?: Tooltip.TooltipContentProps['align'];
|
||||
collisionBoundarySelector?: string;
|
||||
collisionPadding?: number;
|
||||
content: ReactNode;
|
||||
children: ReactNode;
|
||||
}>;
|
||||
|
||||
export function FunTooltip(props: FunTooltipProps): JSX.Element {
|
||||
const ref = useRef<HTMLButtonElement>(null);
|
||||
const [collisionBoundary, setCollisionBoundary] = useState<Element | null>(
|
||||
null
|
||||
);
|
||||
useLayoutEffect(() => {
|
||||
if (props.collisionBoundarySelector == null) {
|
||||
return;
|
||||
}
|
||||
strictAssert(ref.current, 'missing ref');
|
||||
const trigger = ref.current;
|
||||
setCollisionBoundary(trigger.closest(props.collisionBoundarySelector));
|
||||
}, [props.collisionBoundarySelector]);
|
||||
|
||||
return (
|
||||
<Tooltip className="FunTooltip" placement={props.placement}>
|
||||
{props.children}
|
||||
</Tooltip>
|
||||
<Tooltip.Root
|
||||
open={props.open}
|
||||
onOpenChange={props.onOpenChange}
|
||||
disableHoverableContent={props.disableHoverableContent}
|
||||
>
|
||||
<Tooltip.Trigger ref={ref} asChild>
|
||||
{props.children}
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content
|
||||
side={props.side}
|
||||
align={props.align}
|
||||
className="FunTooltip"
|
||||
collisionBoundary={collisionBoundary}
|
||||
collisionPadding={props.collisionPadding}
|
||||
>
|
||||
<span className="FunTooltip__Text">{props.content}</span>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
</Tooltip.Root>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import type { MouseEvent, PointerEvent } from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
Heading,
|
||||
OverlayArrow,
|
||||
Popover,
|
||||
TooltipTrigger,
|
||||
} from 'react-aria-components';
|
||||
import type { PressEvent } from 'react-aria';
|
||||
import { VisuallyHidden } from 'react-aria';
|
||||
import * as Tooltip from '@radix-ui/react-tooltip';
|
||||
import type { LocalizerType } from '../../../types/I18N';
|
||||
import { strictAssert } from '../../../util/assert';
|
||||
import { missingCaseError } from '../../../util/missingCaseError';
|
||||
|
@ -388,95 +388,99 @@ export function FunPanelEmojis({
|
|||
</FunPanelFooter>
|
||||
)}
|
||||
<FunPanelBody>
|
||||
<FunScroller
|
||||
ref={scrollerRef}
|
||||
sectionGap={EMOJI_GRID_SECTION_GAP}
|
||||
onScrollSectionChange={handleScrollSectionChange}
|
||||
>
|
||||
{layout.sections.length === 0 && (
|
||||
<FunResults aria-busy={false}>
|
||||
<FunResultsHeader>
|
||||
{i18n('icu:FunPanelEmojis__SearchResults__EmptyHeading')}{' '}
|
||||
<FunStaticEmoji
|
||||
size={16}
|
||||
role="presentation"
|
||||
emoji={emojiVariantConstant('\u{1F641}')}
|
||||
/>
|
||||
</FunResultsHeader>
|
||||
</FunResults>
|
||||
)}
|
||||
{layout.sections.length > 0 && (
|
||||
<FunKeyboard
|
||||
scrollerRef={scrollerRef}
|
||||
keyboard={keyboard}
|
||||
onStateChange={handleKeyboardStateChange}
|
||||
>
|
||||
<FunGridContainer
|
||||
totalSize={layout.totalHeight}
|
||||
columnCount={EMOJI_GRID_COLUMNS}
|
||||
cellWidth={EMOJI_GRID_CELL_WIDTH}
|
||||
cellHeight={EMOJI_GRID_CELL_HEIGHT}
|
||||
<Tooltip.Provider skipDelayDuration={0}>
|
||||
<FunScroller
|
||||
ref={scrollerRef}
|
||||
sectionGap={EMOJI_GRID_SECTION_GAP}
|
||||
onScrollSectionChange={handleScrollSectionChange}
|
||||
>
|
||||
{layout.sections.length === 0 && (
|
||||
<FunResults aria-busy={false}>
|
||||
<FunResultsHeader>
|
||||
{i18n('icu:FunPanelEmojis__SearchResults__EmptyHeading')}{' '}
|
||||
<FunStaticEmoji
|
||||
size={16}
|
||||
role="presentation"
|
||||
emoji={emojiVariantConstant('\u{1F641}')}
|
||||
/>
|
||||
</FunResultsHeader>
|
||||
</FunResults>
|
||||
)}
|
||||
{layout.sections.length > 0 && (
|
||||
<FunKeyboard
|
||||
scrollerRef={scrollerRef}
|
||||
keyboard={keyboard}
|
||||
onStateChange={handleKeyboardStateChange}
|
||||
>
|
||||
{layout.sections.map(section => {
|
||||
return (
|
||||
<FunGridScrollerSection
|
||||
key={section.key}
|
||||
id={section.id}
|
||||
sectionOffset={section.sectionOffset}
|
||||
sectionSize={section.sectionSize}
|
||||
>
|
||||
<FunGridHeader
|
||||
id={section.header.key}
|
||||
headerOffset={section.header.headerOffset}
|
||||
headerSize={section.header.headerSize}
|
||||
<FunGridContainer
|
||||
totalSize={layout.totalHeight}
|
||||
columnCount={EMOJI_GRID_COLUMNS}
|
||||
cellWidth={EMOJI_GRID_CELL_WIDTH}
|
||||
cellHeight={EMOJI_GRID_CELL_HEIGHT}
|
||||
>
|
||||
{layout.sections.map(section => {
|
||||
return (
|
||||
<FunGridScrollerSection
|
||||
key={section.key}
|
||||
id={section.id}
|
||||
sectionOffset={section.sectionOffset}
|
||||
sectionSize={section.sectionSize}
|
||||
>
|
||||
<FunGridHeaderText>
|
||||
{getTitleForSection(
|
||||
i18n,
|
||||
section.id as FunEmojisSection
|
||||
)}
|
||||
</FunGridHeaderText>
|
||||
{section.id ===
|
||||
EmojiPickerCategory.SmileysAndPeople && (
|
||||
<SectionSkinToneHeaderPopover
|
||||
i18n={i18n}
|
||||
open={skinTonePopoverOpen}
|
||||
onOpenChange={handleSkinTonePopoverOpenChange}
|
||||
onSelectSkinTone={fun.onEmojiSkinToneDefaultChange}
|
||||
/>
|
||||
)}
|
||||
</FunGridHeader>
|
||||
<FunGridRowGroup
|
||||
aria-labelledby={section.header.key}
|
||||
colCount={section.colCount}
|
||||
rowCount={section.rowCount}
|
||||
rowGroupOffset={section.rowGroup.rowGroupOffset}
|
||||
rowGroupSize={section.rowGroup.rowGroupSize}
|
||||
>
|
||||
{section.rowGroup.rows.map(row => {
|
||||
return (
|
||||
<Row
|
||||
key={row.key}
|
||||
<FunGridHeader
|
||||
id={section.header.key}
|
||||
headerOffset={section.header.headerOffset}
|
||||
headerSize={section.header.headerSize}
|
||||
>
|
||||
<FunGridHeaderText>
|
||||
{getTitleForSection(
|
||||
i18n,
|
||||
section.id as FunEmojisSection
|
||||
)}
|
||||
</FunGridHeaderText>
|
||||
{section.id ===
|
||||
EmojiPickerCategory.SmileysAndPeople && (
|
||||
<SectionSkinToneHeaderPopover
|
||||
i18n={i18n}
|
||||
rowIndex={row.rowIndex}
|
||||
cells={row.cells}
|
||||
focusedCellKey={focusedCellKey}
|
||||
emojiSkinToneDefault={fun.emojiSkinToneDefault}
|
||||
onSelectEmoji={handleSelectEmoji}
|
||||
onEmojiSkinToneDefaultChange={
|
||||
open={skinTonePopoverOpen}
|
||||
onOpenChange={handleSkinTonePopoverOpenChange}
|
||||
onSelectSkinTone={
|
||||
fun.onEmojiSkinToneDefaultChange
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</FunGridRowGroup>
|
||||
</FunGridScrollerSection>
|
||||
);
|
||||
})}
|
||||
</FunGridContainer>
|
||||
</FunKeyboard>
|
||||
)}
|
||||
</FunScroller>
|
||||
)}
|
||||
</FunGridHeader>
|
||||
<FunGridRowGroup
|
||||
aria-labelledby={section.header.key}
|
||||
colCount={section.colCount}
|
||||
rowCount={section.rowCount}
|
||||
rowGroupOffset={section.rowGroup.rowGroupOffset}
|
||||
rowGroupSize={section.rowGroup.rowGroupSize}
|
||||
>
|
||||
{section.rowGroup.rows.map(row => {
|
||||
return (
|
||||
<Row
|
||||
key={row.key}
|
||||
i18n={i18n}
|
||||
rowIndex={row.rowIndex}
|
||||
cells={row.cells}
|
||||
focusedCellKey={focusedCellKey}
|
||||
emojiSkinToneDefault={fun.emojiSkinToneDefault}
|
||||
onSelectEmoji={handleSelectEmoji}
|
||||
onEmojiSkinToneDefaultChange={
|
||||
fun.onEmojiSkinToneDefaultChange
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</FunGridRowGroup>
|
||||
</FunGridScrollerSection>
|
||||
);
|
||||
})}
|
||||
</FunGridContainer>
|
||||
</FunKeyboard>
|
||||
)}
|
||||
</FunScroller>
|
||||
</Tooltip.Provider>
|
||||
</FunPanelBody>
|
||||
</FunPanel>
|
||||
);
|
||||
|
@ -572,8 +576,8 @@ const Cell = memo(function Cell(props: CellProps): JSX.Element {
|
|||
return getEmojiVariantByParentKeyAndSkinTone(emojiParent.key, skinTone);
|
||||
}, [emojiParent, skinTone]);
|
||||
|
||||
const handlePress = useCallback(
|
||||
(event: PressEvent) => {
|
||||
const handleClick = useCallback(
|
||||
(event: PointerEvent) => {
|
||||
if (emojiHasSkinToneVariants && emojiSkinToneDefault == null) {
|
||||
setPopoverOpen(true);
|
||||
return;
|
||||
|
@ -585,7 +589,7 @@ const Cell = memo(function Cell(props: CellProps): JSX.Element {
|
|||
skinTone,
|
||||
};
|
||||
const shouldClose =
|
||||
(event.pointerType === 'keyboard' || event.pointerType === 'virtual') &&
|
||||
event.nativeEvent.pointerType !== 'mouse' &&
|
||||
!(event.ctrlKey || event.metaKey);
|
||||
onSelectEmoji(emojiSelection, shouldClose);
|
||||
},
|
||||
|
@ -654,12 +658,20 @@ const Cell = memo(function Cell(props: CellProps): JSX.Element {
|
|||
colIndex={props.colIndex}
|
||||
rowIndex={props.rowIndex}
|
||||
>
|
||||
<TooltipTrigger>
|
||||
<FunTooltip
|
||||
side="top"
|
||||
content={`:${emojiShortNameDisplay}:`}
|
||||
collisionBoundarySelector=".FunScroller__Viewport"
|
||||
collisionPadding={6}
|
||||
// `skipDelayDuration=0` doesn't work with `disableHoverableContent`
|
||||
// FIX: https://github.com/radix-ui/primitives/pull/3562
|
||||
// disableHoverableContent
|
||||
>
|
||||
<FunItemButton
|
||||
ref={popoverTriggerRef}
|
||||
excludeFromTabOrder={!props.isTabbable}
|
||||
aria-label={emojiName}
|
||||
onPress={handlePress}
|
||||
onClick={handleClick}
|
||||
onLongPress={handleLongPress}
|
||||
onContextMenu={handleContextMenu}
|
||||
longPressAccessibilityDescription={i18n(
|
||||
|
@ -668,9 +680,7 @@ const Cell = memo(function Cell(props: CellProps): JSX.Element {
|
|||
>
|
||||
<FunStaticEmoji role="presentation" size={32} emoji={emojiVariant} />
|
||||
</FunItemButton>
|
||||
<FunTooltip placement="top">{`:${emojiShortNameDisplay}:`}</FunTooltip>
|
||||
</TooltipTrigger>
|
||||
d
|
||||
</FunTooltip>
|
||||
{emojiHasSkinToneVariants && (
|
||||
<Popover
|
||||
data-fun-overlay
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import type { Range } from '@tanstack/react-virtual';
|
||||
import { defaultRangeExtractor, useVirtualizer } from '@tanstack/react-virtual';
|
||||
import type { PointerEvent } from 'react';
|
||||
import React, {
|
||||
memo,
|
||||
useCallback,
|
||||
|
@ -11,7 +12,6 @@ import React, {
|
|||
useState,
|
||||
useId,
|
||||
} from 'react';
|
||||
import type { PressEvent } from 'react-aria';
|
||||
import { VisuallyHidden } from 'react-aria';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import { FunItemButton } from '../base/FunItem';
|
||||
|
@ -356,8 +356,8 @@ export function FunPanelGifs({
|
|||
[]
|
||||
);
|
||||
|
||||
const handlePressGif = useCallback(
|
||||
(_event: PressEvent, gifSelection: FunGifSelection) => {
|
||||
const handleClickGif = useCallback(
|
||||
(_event: PointerEvent, gifSelection: FunGifSelection) => {
|
||||
onFunSelectGif(gifSelection);
|
||||
onSelectGif(gifSelection);
|
||||
setSelectedItemKey(null);
|
||||
|
@ -520,7 +520,7 @@ export function FunPanelGifs({
|
|||
itemOffset={item.start}
|
||||
itemLane={item.lane}
|
||||
isTabbable={isTabbable}
|
||||
onPressGif={handlePressGif}
|
||||
onClickGif={handleClickGif}
|
||||
fetchGif={fetchGif}
|
||||
/>
|
||||
);
|
||||
|
@ -542,16 +542,16 @@ const Item = memo(function Item(props: {
|
|||
itemOffset: number;
|
||||
itemLane: number;
|
||||
isTabbable: boolean;
|
||||
onPressGif: (event: PressEvent, gifSelection: FunGifSelection) => void;
|
||||
onClickGif: (event: PointerEvent, gifSelection: FunGifSelection) => void;
|
||||
fetchGif: typeof tenorDownload;
|
||||
}) {
|
||||
const { onPressGif, fetchGif } = props;
|
||||
const { onClickGif, fetchGif } = props;
|
||||
|
||||
const handlePress = useCallback(
|
||||
async (event: PressEvent) => {
|
||||
onPressGif(event, { gif: props.gif });
|
||||
const handleClick = useCallback(
|
||||
async (event: PointerEvent) => {
|
||||
onClickGif(event, { gif: props.gif });
|
||||
},
|
||||
[props.gif, onPressGif]
|
||||
[props.gif, onClickGif]
|
||||
);
|
||||
|
||||
const descriptionId = `FunGifsPanelItem__GifDescription--${props.gif.id}`;
|
||||
|
@ -606,7 +606,7 @@ const Item = memo(function Item(props: {
|
|||
>
|
||||
<FunItemButton
|
||||
aria-label={props.gif.title}
|
||||
onPress={handlePress}
|
||||
onClick={handleClick}
|
||||
excludeFromTabOrder={!props.isTabbable}
|
||||
>
|
||||
{src != null && (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import type { CSSProperties } from 'react';
|
||||
import type { CSSProperties, PointerEvent } from 'react';
|
||||
import React, {
|
||||
memo,
|
||||
useCallback,
|
||||
|
@ -9,7 +9,6 @@ import React, {
|
|||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import type { PressEvent } from 'react-aria';
|
||||
import type {
|
||||
StickerPackType,
|
||||
StickerType,
|
||||
|
@ -344,8 +343,8 @@ export function FunPanelStickers({
|
|||
return searchInput.length > 0;
|
||||
}, [searchInput]);
|
||||
|
||||
const handlePressSticker = useCallback(
|
||||
(event: PressEvent, stickerSelection: FunStickerSelection) => {
|
||||
const handleClickSticker = useCallback(
|
||||
(event: PointerEvent, stickerSelection: FunStickerSelection) => {
|
||||
onFunSelectSticker(stickerSelection);
|
||||
onSelectSticker(stickerSelection);
|
||||
if (!(event.ctrlKey || event.metaKey)) {
|
||||
|
@ -356,8 +355,8 @@ export function FunPanelStickers({
|
|||
[onFunSelectSticker, onSelectSticker, onClose]
|
||||
);
|
||||
|
||||
const handlePressTimeSticker = useCallback(
|
||||
(event: PressEvent, style: FunTimeStickerStyle) => {
|
||||
const handleClickTimeSticker = useCallback(
|
||||
(event: PointerEvent, style: FunTimeStickerStyle) => {
|
||||
onSelectTimeSticker?.(style);
|
||||
if (!(event.ctrlKey || event.metaKey)) {
|
||||
onClose();
|
||||
|
@ -492,8 +491,8 @@ export function FunPanelStickers({
|
|||
cells={row.cells}
|
||||
stickerLookup={stickerLookup}
|
||||
focusedCellKey={focusedCellKey}
|
||||
onPressSticker={handlePressSticker}
|
||||
onPressTimeSticker={handlePressTimeSticker}
|
||||
onClickSticker={handleClickSticker}
|
||||
onClickTimeSticker={handleClickTimeSticker}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@ -515,11 +514,11 @@ const Row = memo(function Row(props: {
|
|||
stickerLookup: StickerLookup;
|
||||
cells: ReadonlyArray<CellLayoutNode>;
|
||||
focusedCellKey: CellKey | null;
|
||||
onPressSticker: (
|
||||
event: PressEvent,
|
||||
onClickSticker: (
|
||||
event: PointerEvent,
|
||||
stickerSelection: FunStickerSelection
|
||||
) => void;
|
||||
onPressTimeSticker: (event: PressEvent, style: FunTimeStickerStyle) => void;
|
||||
onClickTimeSticker: (event: PointerEvent, style: FunTimeStickerStyle) => void;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<FunGridRow rowIndex={props.rowIndex}>
|
||||
|
@ -537,8 +536,8 @@ const Row = memo(function Row(props: {
|
|||
colIndex={cell.colIndex}
|
||||
stickerLookup={props.stickerLookup}
|
||||
isTabbable={isTabbable}
|
||||
onPressSticker={props.onPressSticker}
|
||||
onPressTimeSticker={props.onPressTimeSticker}
|
||||
onClickSticker={props.onClickSticker}
|
||||
onClickTimeSticker={props.onClickTimeSticker}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@ -553,28 +552,28 @@ const Cell = memo(function Cell(props: {
|
|||
rowIndex: number;
|
||||
stickerLookup: StickerLookup;
|
||||
isTabbable: boolean;
|
||||
onPressSticker: (
|
||||
event: PressEvent,
|
||||
onClickSticker: (
|
||||
event: PointerEvent,
|
||||
stickerSelection: FunStickerSelection
|
||||
) => void;
|
||||
onPressTimeSticker: (event: PressEvent, style: FunTimeStickerStyle) => void;
|
||||
onClickTimeSticker: (event: PointerEvent, style: FunTimeStickerStyle) => void;
|
||||
}): JSX.Element {
|
||||
const { onPressSticker, onPressTimeSticker } = props;
|
||||
const { onClickSticker, onClickTimeSticker } = props;
|
||||
const stickerLookupItem = props.stickerLookup[props.value];
|
||||
|
||||
const handlePress = useCallback(
|
||||
(event: PressEvent) => {
|
||||
const handleClick = useCallback(
|
||||
(event: PointerEvent) => {
|
||||
if (stickerLookupItem.kind === 'sticker') {
|
||||
onPressSticker(event, {
|
||||
onClickSticker(event, {
|
||||
stickerPackId: stickerLookupItem.sticker.packId,
|
||||
stickerId: stickerLookupItem.sticker.id,
|
||||
stickerUrl: stickerLookupItem.sticker.url,
|
||||
});
|
||||
} else if (stickerLookupItem.kind === 'timeSticker') {
|
||||
onPressTimeSticker(event, stickerLookupItem.style);
|
||||
onClickTimeSticker(event, stickerLookupItem.style);
|
||||
}
|
||||
},
|
||||
[stickerLookupItem, onPressSticker, onPressTimeSticker]
|
||||
[stickerLookupItem, onClickSticker, onClickTimeSticker]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -590,7 +589,7 @@ const Cell = memo(function Cell(props: {
|
|||
? (stickerLookupItem.sticker.emoji ?? '')
|
||||
: stickerLookupItem.style
|
||||
}
|
||||
onPress={handlePress}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{stickerLookupItem.kind === 'sticker' && (
|
||||
<FunSticker
|
||||
|
|
|
@ -15,6 +15,69 @@
|
|||
"updated": "2018-09-18T19:19:27.699Z",
|
||||
"reasonDetail": "Part of runtime library for C++ transpiled code"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const isOpenDelayedRef = React.useRef(true);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const isPointerInTransitRef = React.useRef(false);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const skipDelayTimerRef = React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const openTimerRef = React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const wasOpenDelayedRef = React.useRef(false);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const ref = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const isPointerDownRef = React.useRef(false);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const hasPointerMoveOpenedRef = React.useRef(false);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/@radix-ui/react-tooltip/dist/index.js",
|
||||
"line": " const ref = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "DOM-innerHTML",
|
||||
"path": "node_modules/@signalapp/quill-cjs/core/editor.js",
|
||||
|
@ -1842,13 +1905,6 @@
|
|||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-02-19T20:14:46.879Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/fun/base/FunItem.tsx",
|
||||
"line": " const innerRef = useRef<HTMLButtonElement>(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-04-23T23:43:10.675Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/fun/base/FunScroller.tsx",
|
||||
|
@ -1905,6 +1961,13 @@
|
|||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-02-19T20:14:46.879Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/fun/base/FunTooltip.tsx",
|
||||
"line": " const ref = useRef<HTMLButtonElement>(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2025-05-30T20:26:57.154Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/fun/data/infinite.ts",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue