diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecb34606e45c..8dfafccf9193 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -898,6 +898,55 @@ importers: specifier: 30.4.2 version: 30.4.2 + projects/js-packages/grid: + dependencies: + '@dnd-kit/core': + specifier: ^6.3.1 + version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@dnd-kit/sortable': + specifier: ^10.0.0 + version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + '@dnd-kit/utilities': + specifier: ^3.2.2 + version: 3.2.2(react@18.3.1) + '@wordpress/compose': + specifier: 7.46.0 + version: 7.46.0(react@18.3.1) + '@wordpress/element': + specifier: 6.46.0 + version: 6.46.0 + '@wordpress/icons': + specifier: 13.1.0 + version: 13.1.0(react@18.3.1) + '@wordpress/ui': + specifier: 0.13.0 + version: 0.13.0(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + clsx: + specifier: ^2.1.1 + version: 2.1.1 + devDependencies: + '@types/react': + specifier: ^18.3.27 + version: 18.3.28 + '@types/react-dom': + specifier: ^18.3.7 + version: 18.3.7(@types/react@18.3.28) + '@typescript/native-preview': + specifier: 7.0.0-dev.20260225.1 + version: 7.0.0-dev.20260225.1 + jetpack-js-tools: + specifier: workspace:* + version: link:../../../tools/js-tools + react: + specifier: 18.3.1 + version: 18.3.1 + react-dom: + specifier: 18.3.1 + version: 18.3.1(react@18.3.1) + typescript: + specifier: 5.9.3 + version: 5.9.3 + projects/js-packages/i18n-check-webpack-plugin: dependencies: debug: @@ -1837,6 +1886,134 @@ importers: specifier: 5.2.4 version: 5.2.4(webpack-cli@6.0.1)(webpack@5.105.2) + projects/js-packages/widget-dashboard: + dependencies: + '@automattic/jetpack-grid': + specifier: workspace:* + version: link:../grid + '@automattic/jetpack-widget-primitives': + specifier: workspace:* + version: link:../widget-primitives + '@wordpress/api-fetch': + specifier: 7.46.0 + version: 7.46.0 + '@wordpress/commands': + specifier: 1.46.0 + version: 1.46.0(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/components': + specifier: 33.1.0 + version: 33.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/compose': + specifier: 7.46.0 + version: 7.46.0(react@18.3.1) + '@wordpress/core-data': + specifier: 7.46.0 + version: 7.46.0(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/data': + specifier: 10.46.0 + version: 10.46.0(react@18.3.1) + '@wordpress/dataviews': + specifier: 14.3.0 + version: 14.3.0(@types/react@18.3.28)(react@18.3.1) + '@wordpress/element': + specifier: 6.46.0 + version: 6.46.0 + '@wordpress/i18n': + specifier: 6.19.0 + version: 6.19.0 + '@wordpress/icons': + specifier: 13.1.0 + version: 13.1.0(react@18.3.1) + '@wordpress/preferences': + specifier: 4.46.0 + version: 4.46.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/primitives': + specifier: 4.46.0 + version: 4.46.0(react@18.3.1) + '@wordpress/private-apis': + specifier: 1.46.0 + version: 1.46.0 + '@wordpress/ui': + specifier: 0.13.0 + version: 0.13.0(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/viewport': + specifier: 6.46.0 + version: 6.46.0(react@18.3.1) + clsx: + specifier: ^2.1.1 + version: 2.1.1 + fast-deep-equal: + specifier: ^3.1.3 + version: 3.1.3 + uuid: + specifier: ^14.0.0 + version: 14.0.0 + devDependencies: + '@types/react': + specifier: ^18.3.27 + version: 18.3.28 + '@types/react-dom': + specifier: ^18.3.7 + version: 18.3.7(@types/react@18.3.28) + '@typescript/native-preview': + specifier: 7.0.0-dev.20260225.1 + version: 7.0.0-dev.20260225.1 + jetpack-js-tools: + specifier: workspace:* + version: link:../../../tools/js-tools + react: + specifier: 18.3.1 + version: 18.3.1 + react-dom: + specifier: 18.3.1 + version: 18.3.1(react@18.3.1) + typescript: + specifier: 5.9.3 + version: 5.9.3 + + projects/js-packages/widget-primitives: + dependencies: + '@wordpress/core-data': + specifier: 7.46.0 + version: 7.46.0(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/data': + specifier: 10.46.0 + version: 10.46.0(react@18.3.1) + '@wordpress/dataviews': + specifier: 14.3.0 + version: 14.3.0(@types/react@18.3.28)(react@18.3.1) + '@wordpress/element': + specifier: 6.46.0 + version: 6.46.0 + '@wordpress/i18n': + specifier: 6.19.0 + version: 6.19.0 + '@wordpress/ui': + specifier: 0.13.0 + version: 0.13.0(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + devDependencies: + '@types/react': + specifier: ^18.3.27 + version: 18.3.28 + '@types/react-dom': + specifier: ^18.3.7 + version: 18.3.7(@types/react@18.3.28) + '@typescript/native-preview': + specifier: 7.0.0-dev.20260225.1 + version: 7.0.0-dev.20260225.1 + jetpack-js-tools: + specifier: workspace:* + version: link:../../../tools/js-tools + react: + specifier: 18.3.1 + version: 18.3.1 + react-dom: + specifier: 18.3.1 + version: 18.3.1(react@18.3.1) + typescript: + specifier: 5.9.3 + version: 5.9.3 + projects/packages/account-protection: {} projects/packages/activity-log: @@ -3868,6 +4045,15 @@ importers: '@automattic/charts': specifier: workspace:* version: link:../../js-packages/charts + '@automattic/jetpack-grid': + specifier: workspace:* + version: link:../../js-packages/grid + '@automattic/jetpack-widget-dashboard': + specifier: workspace:* + version: link:../../js-packages/widget-dashboard + '@automattic/jetpack-widget-primitives': + specifier: workspace:* + version: link:../../js-packages/widget-primitives '@automattic/number-formatters': specifier: workspace:* version: link:../../js-packages/number-formatters @@ -3877,9 +4063,33 @@ importers: '@date-fns/tz': specifier: 1.4.1 version: 1.4.1 + '@jetpack-premium-analytics/data': + specifier: link:packages/data + version: link:packages/data + '@jetpack-premium-analytics/datetime': + specifier: link:packages/datetime + version: link:packages/datetime + '@jetpack-premium-analytics/formatters': + specifier: link:packages/formatters + version: link:packages/formatters + '@jetpack-premium-analytics/icons': + specifier: link:packages/icons + version: link:packages/icons + '@jetpack-premium-analytics/routing': + specifier: link:packages/routing + version: link:packages/routing + '@jetpack-premium-analytics/ui': + specifier: link:packages/ui + version: link:packages/ui + '@jetpack-premium-analytics/widgets-toolkit': + specifier: link:packages/widgets-toolkit + version: link:packages/widgets-toolkit '@tanstack/react-query': specifier: 5.90.8 version: 5.90.8(react@18.3.1) + '@wordpress/admin-ui': + specifier: 2.1.0 + version: 2.1.0(@date-fns/tz@1.4.1)(date-fns@4.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@wordpress/api-fetch': specifier: 7.48.0 version: 7.48.0 @@ -3901,6 +4111,9 @@ importers: '@wordpress/dataviews': specifier: 14.3.0 version: 14.3.0(@date-fns/tz@1.4.1)(react@18.3.1) + '@wordpress/element': + specifier: 6.46.0 + version: 6.46.0 '@wordpress/i18n': specifier: ^6.9.0 version: 6.21.0 @@ -3908,8 +4121,8 @@ importers: specifier: ^13.0.0 version: 13.1.0(react@18.3.1) '@wordpress/primitives': - specifier: 4.48.0 - version: 4.48.0(react@18.3.1) + specifier: 4.46.0 + version: 4.46.0(react@18.3.1) '@wordpress/private-apis': specifier: 1.48.0 version: 1.48.0 @@ -6799,24 +7012,12 @@ packages: '@actions/core@3.0.0': resolution: {integrity: sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==} - '@actions/exec@3.0.0': - resolution: {integrity: sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==} - '@actions/github@9.0.0': resolution: {integrity: sha512-yJ0RoswsAaKcvkmpCE4XxBRiy/whH2SdTBHWzs0gi4wkqTDhXMChjSdqBz/F4AeiDlP28rQqL33iHb+kjAMX6w==} '@actions/http-client@3.0.2': resolution: {integrity: sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==} - '@actions/http-client@4.0.1': - resolution: {integrity: sha512-+Nvd1ImaOZBSoPbsUtEhv+1z99H12xzncCkz0a3RuehINE81FZSe2QTj3uvAPTcJX/SCzUQHQ0D1GrPMbrPitg==} - - '@actions/io@3.0.2': - resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} - - '@adobe/css-tools@4.5.0': - resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} - '@altano/repository-tools@2.0.3': resolution: {integrity: sha512-cSR/ZYDF6Wp9OeAJMyLYYN1GenAAhV17W+w38ELP+3c5Ltsy9jkkCymi33nz/qnXyef3n6Fbr1h2yt3dvUN5sQ==} @@ -7107,10 +7308,6 @@ packages: resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.7': - resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.29.7': resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} @@ -7695,9 +7892,6 @@ packages: '@blazediff/core@1.9.1': resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} - '@bufbuild/protobuf@2.12.0': - resolution: {integrity: sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==} - '@cacheable/memory@2.0.9': resolution: {integrity: sha512-HdMx6DoGywB30vacDbBsITbIX4pgFqj1zsrV58jZBUw3klzkNoXhj7qOqAgledhxG7YZI5rBSJg7Zp8/VG0DuA==} @@ -7716,75 +7910,21 @@ packages: '@codemirror/commands@6.8.1': resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==} - '@codemirror/lang-angular@0.1.4': - resolution: {integrity: sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==} - - '@codemirror/lang-cpp@6.0.3': - resolution: {integrity: sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==} - '@codemirror/lang-css@6.3.1': resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} - '@codemirror/lang-go@6.0.1': - resolution: {integrity: sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==} - '@codemirror/lang-html@6.4.9': resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==} - '@codemirror/lang-java@6.0.2': - resolution: {integrity: sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==} - - '@codemirror/lang-javascript@6.2.5': - resolution: {integrity: sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==} - '@codemirror/lang-json@6.0.2': resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==} - '@codemirror/lang-less@6.0.2': - resolution: {integrity: sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==} - - '@codemirror/lang-liquid@6.3.2': - resolution: {integrity: sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw==} - - '@codemirror/lang-markdown@6.5.0': - resolution: {integrity: sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw==} - - '@codemirror/lang-php@6.0.2': - resolution: {integrity: sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==} - - '@codemirror/lang-python@6.2.1': - resolution: {integrity: sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==} - - '@codemirror/lang-rust@6.0.2': - resolution: {integrity: sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==} - - '@codemirror/lang-sass@6.0.2': - resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==} - - '@codemirror/lang-sql@6.10.0': - resolution: {integrity: sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==} - - '@codemirror/lang-vue@0.1.3': - resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==} - - '@codemirror/lang-wast@6.0.2': - resolution: {integrity: sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==} - - '@codemirror/lang-xml@6.1.0': - resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} - - '@codemirror/lang-yaml@6.1.3': - resolution: {integrity: sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==} - '@codemirror/language-data@6.5.1': resolution: {integrity: sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==} '@codemirror/language@6.11.2': resolution: {integrity: sha512-p44TsNArL4IVXDTbapUmEkAlvWs2CFQbcfc0ymDsis1kH2wh0gcY96AS29c/vp2d0y2Tquk1EDSaawpzilUiAw==} - '@codemirror/legacy-modes@6.5.3': - resolution: {integrity: sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg==} - '@codemirror/lint@6.8.5': resolution: {integrity: sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==} @@ -7800,10 +7940,6 @@ packages: '@colordx/core@5.4.3': resolution: {integrity: sha512-kIxYSfA5T8HXjav55UaaH/o/cKivF6jCCGIb8eqtcsfI46wsvlSiT8jMDyrl779qLec3c2c2oHBZo4oAhvbjrQ==} - '@colors/colors@1.6.0': - resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} - engines: {node: '>=0.1.90'} - '@csstools/color-helpers@6.0.2': resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} engines: {node: '>=20.19.0'} @@ -7865,9 +8001,6 @@ packages: peerDependencies: postcss-selector-parser: ^7.1.1 - '@dabh/diagnostics@2.0.8': - resolution: {integrity: sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==} - '@date-fns/tz@1.4.1': resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==} @@ -7878,6 +8011,28 @@ packages: resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} engines: {node: '>=14.17.0'} + '@dnd-kit/accessibility@3.1.1': + resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==} + peerDependencies: + react: '>=16.8.0' + + '@dnd-kit/core@6.3.1': + resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@dnd-kit/sortable@10.0.0': + resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==} + peerDependencies: + '@dnd-kit/core': ^6.3.0 + react: '>=16.8.0' + + '@dnd-kit/utilities@3.2.2': + resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} + peerDependencies: + react: '>=16.8.0' + '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} @@ -7933,9 +8088,6 @@ packages: '@types/react': optional: true - '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} peerDependencies: @@ -7979,12 +8131,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.4': - resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-x64@0.27.4': resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} engines: {node: '>=18'} @@ -8243,31 +8389,16 @@ packages: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/momoa@3.3.10': - resolution: {integrity: sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ==} - engines: {node: '>=18'} - '@humanwhocodes/retry@0.4.3': resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@img/sharp-darwin-arm64@0.33.5': - resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [arm64] - os: [darwin] - '@img/sharp-darwin-x64@0.33.5': resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.0.4': - resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} - cpu: [arm64] - os: [darwin] - '@img/sharp-libvips-darwin-x64@1.0.4': resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} cpu: [x64] @@ -8647,61 +8778,16 @@ packages: '@lezer/common@1.3.0': resolution: {integrity: sha512-L9X8uHCYU310o99L3/MpJKYxPzXPOS7S0NmBaM7UO/x2Kb2WbmMLSkfvdr1KxRIFYOpbY0Jhn7CfLSUDzL8arQ==} - '@lezer/common@1.5.2': - resolution: {integrity: sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==} - - '@lezer/cpp@1.1.6': - resolution: {integrity: sha512-vh9gWWJOXFVY8HBHK3Twzq8MgwG2iN4GSyzBP9sCGTe37P15x2R14VaBQk0VA0ezTRN1KHYBBsHhvpGZ2Xy/pA==} - - '@lezer/css@1.3.3': - resolution: {integrity: sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==} - '@lezer/generator@1.8.0': resolution: {integrity: sha512-/SF4EDWowPqV1jOgoGSGTIFsE7Ezdr7ZYxyihl5eMKVO5tlnpIhFcDavgm1hHY5GEonoOAEnJ0CU0x+tvuAuUg==} hasBin: true - '@lezer/go@1.0.1': - resolution: {integrity: sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==} - '@lezer/highlight@1.2.3': resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} - '@lezer/html@1.3.13': - resolution: {integrity: sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==} - - '@lezer/java@1.1.3': - resolution: {integrity: sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==} - - '@lezer/javascript@1.5.4': - resolution: {integrity: sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==} - - '@lezer/json@1.0.3': - resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==} - '@lezer/lr@1.4.3': resolution: {integrity: sha512-yenN5SqAxAPv/qMnpWW0AT7l+SxVrgG+u0tNsRQWqbrz66HIl8DnEbBObvy21J5K7+I1v7gsAnlE2VQ5yYVSeA==} - '@lezer/markdown@1.6.4': - resolution: {integrity: sha512-N0SxazMj4k65DBfaf1azqtMZd6u7MqluP84/NZnB/io8Td9aleFmAhz9hcbvSfsxT5tdYlJ5qgv5aMJGY4zEtA==} - - '@lezer/php@1.0.5': - resolution: {integrity: sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==} - - '@lezer/python@1.1.19': - resolution: {integrity: sha512-MhQIURHRytsNzP/YXnqpYKW6la6voAH3kyplTOOiCdjyFY6cWWGFVmYVdHIPrElqSDf4iCDktQCockB9FxuhzQ==} - - '@lezer/rust@1.0.2': - resolution: {integrity: sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==} - - '@lezer/sass@1.1.0': - resolution: {integrity: sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==} - - '@lezer/xml@1.0.6': - resolution: {integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==} - - '@lezer/yaml@1.0.4': - resolution: {integrity: sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==} - '@linear/sdk@75.0.0': resolution: {integrity: sha512-gf/xmbiWc4cLHjoeOGCNVTglpy+M+ENHpP3bvU57wxD17s7j8zJGXp4wOStnRcQYR0FT+n/76fPp+XR3ZtEjDw==} engines: {node: '>=18.x'} @@ -8738,9 +8824,6 @@ packages: resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} engines: {node: '>=6.0.0'} - '@marijn/find-cluster-break@1.0.2': - resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} - '@mdn/browser-compat-data@7.3.17': resolution: {integrity: sha512-ZtcyRH/psFX4njAEvY898TH/VYknOaeEe2KJdldak4eDsj4MufSY2sXtBJ2IKjZ3jAvLUBRVf8+bv8q2xDHVDg==} @@ -8786,14 +8869,6 @@ packages: resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} engines: {node: '>= 20'} - '@octokit/endpoint@11.0.3': - resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==} - engines: {node: '>= 20'} - - '@octokit/graphql@9.0.3': - resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==} - engines: {node: '>= 20'} - '@octokit/openapi-types@27.0.0': resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==} @@ -9448,24 +9523,6 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@redux-saga/core@1.5.0': - resolution: {integrity: sha512-oMWpQntvVikLhr+wZsvGDzkjW79HphBgEb6Hncz8OkM0azsT3uUnP1Her/W5QZhcDG+tWmjDhah8uDbPSRLs/Q==} - - '@redux-saga/deferred@1.3.1': - resolution: {integrity: sha512-0YZ4DUivWojXBqLB/TmuRRpDDz7tyq1I0AuDV7qi01XlLhM5m51W7+xYtIckH5U2cMlv9eAuicsfRAi1XHpXIg==} - - '@redux-saga/delay-p@1.3.1': - resolution: {integrity: sha512-597I7L5MXbD/1i3EmcaOOjL/5suxJD7p5tnbV1PiWnE28c2cYiIHqmSMK2s7us2/UrhOL2KTNBiD0qBg6KnImg==} - - '@redux-saga/is@1.2.1': - resolution: {integrity: sha512-x3aWtX3GmQfEvn8dh0ovPbsXgK9JjpiR24wKztpGbZP8JZUWWvUgKrvnWZ/T/4iphOBftyVc9VrIwhAnsM+OFA==} - - '@redux-saga/symbols@1.2.1': - resolution: {integrity: sha512-3dh+uDvpBXi7EUp/eO+N7eFM4xKaU4yuGBXc50KnZGzIrR/vlvkTFQsX13zsY8PB6sCFYAgROfPSRUj8331QSA==} - - '@redux-saga/types@1.4.0': - resolution: {integrity: sha512-fq3Vy0TRl0mEb+1CyTx5wPBY3jxDi7yD4GL1Kz4S6ud7/leGEgRq1NYJDIiVbHMRBJd5rU/BB0Z+akrXSR0DJg==} - '@remix-run/router@1.23.3': resolution: {integrity: sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==} engines: {node: '>=14.0.0'} @@ -9803,30 +9860,10 @@ packages: zen-observable: optional: true - '@sentry-internal/browser-utils@10.22.0': - resolution: {integrity: sha512-BpJoLZEyJr7ORzkCrIjxRTnFWwO1mJNICVh3B9g5d9245niGT4OJvRozmLz89WgJkZFHWu84ls6Xfq5b/3tGFQ==} - engines: {node: '>=18'} - - '@sentry-internal/feedback@10.22.0': - resolution: {integrity: sha512-zXySOin/gGHPV+yKaHqjN9YZ7psEJwzLn8PzCLeo+4REzF1eQwbYZIgOxJFD32z8s3nZiABSWFM/n1CvVfMEsQ==} - engines: {node: '>=18'} - - '@sentry-internal/replay-canvas@10.22.0': - resolution: {integrity: sha512-DE4JNUskJg+O+wFq42W5gAa/99aD5k7TfGOwABxvnzFv8vkKA7pqXwPbFFPzypdKIkln+df7RmbnDwQRNg6/lA==} - engines: {node: '>=18'} - - '@sentry-internal/replay@10.22.0': - resolution: {integrity: sha512-JNE4kHAQSG4/V+J+Zog3vKBWgOe9H33ol/MEU1RuLM/4I+uLf4mTetwnS9ilpnnW/Z/gQYfA+R3CiMrZtqTivw==} - engines: {node: '>=18'} - '@sentry/browser@10.22.0': resolution: {integrity: sha512-wD2XqN+yeBpQFfdPo6+wlKDMyyuDctVGzZWE4qTPntICKQuwMdAfeq5Ma89ad0Dw+bzG9UijGeyuJQlswF87Mw==} engines: {node: '>=18'} - '@sentry/core@10.22.0': - resolution: {integrity: sha512-V1oeHbrOKzxadsCmgtPku3v3Emo/Bpb3VSuKmlLrQefiHX98MWtjJ3XDGfduzD5/dCdh0r/OOLwjcmrO/PZ2aw==} - engines: {node: '>=18'} - '@sentry/core@9.47.1': resolution: {integrity: sha512-KX62+qIt4xgy8eHKHiikfhz2p5fOciXd0Cl+dNzhgPFq8klq4MGMNaf148GB3M/vBqP4nw/eFvRMAayFCgdRQw==} engines: {node: '>=18'} @@ -9892,9 +9929,6 @@ packages: resolution: {integrity: sha512-y+TAF7TszcmFzbVtBkFqAdBwKSoD+8shkNxhp4WIfFwXmCKdFje9WD6evROApPa2FTy1v1uc9yBaJs3609PPgg==} engines: {node: '>= 18', npm: '>= 8.6.0'} - '@so-ric/colorspace@1.1.6': - resolution: {integrity: sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==} - '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -10122,12 +10156,6 @@ packages: '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} @@ -10158,39 +10186,12 @@ packages: '@types/css-tree@2.3.11': resolution: {integrity: sha512-aEokibJOI77uIlqoBOkVbaQGC9zII0A+JH1kcTNKW2CwyYWD8KM6qdo+4c77wD3wZOQfJuNWAr9M4hdk+YhDIg==} - '@types/d3-array@3.0.3': - resolution: {integrity: sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==} - - '@types/d3-color@3.1.0': - resolution: {integrity: sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==} - - '@types/d3-delaunay@6.0.1': - resolution: {integrity: sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==} - - '@types/d3-format@3.0.1': - resolution: {integrity: sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==} - - '@types/d3-geo@3.1.0': - resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} - - '@types/d3-interpolate@3.0.1': - resolution: {integrity: sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==} - '@types/d3-path@1.0.11': resolution: {integrity: sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==} - '@types/d3-scale@4.0.2': - resolution: {integrity: sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA==} - '@types/d3-shape@1.3.12': resolution: {integrity: sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==} - '@types/d3-time-format@2.1.0': - resolution: {integrity: sha512-/myT3I7EwlukNOX2xVdMzb8FRgNzRMpsZddwst9Ld/VFe6LyJyRp0s32l/V9XoUzk+Gqu56F/oGk6507+8BxrA==} - - '@types/d3-time@3.0.0': - resolution: {integrity: sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==} - '@types/d3-voronoi@1.1.12': resolution: {integrity: sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==} @@ -10221,9 +10222,6 @@ packages: '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/geojson@7946.0.16': - resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} - '@types/gradient-parser@1.1.0': resolution: {integrity: sha512-SaEcbgQscHtGJ1QL+ajgDTmmqU2f6T+00jZRcFlVHUW2Asivc84LNUev/UQFyu117AsdyrtI+qpwLvgjJXJxmw==} @@ -10244,12 +10242,6 @@ packages: '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - '@types/jest@30.0.0': resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} @@ -10265,9 +10257,6 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/linkify-it@5.0.0': - resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - '@types/lodash-es@4.17.12': resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} @@ -10280,9 +10269,6 @@ packages: '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/mdurl@2.0.0': - resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - '@types/mdx@2.0.14': resolution: {integrity: sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==} @@ -10313,9 +10299,6 @@ packages: '@types/pg@8.6.1': resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} - '@types/prop-types@15.7.15': - resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/qs@6.15.1': resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} @@ -10369,9 +10352,6 @@ packages: '@types/shimmer@1.2.0': resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} - '@types/sizzle@2.3.10': - resolution: {integrity: sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==} - '@types/sockjs@0.3.36': resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} @@ -10384,9 +10364,6 @@ packages: '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/triple-beam@1.3.5': - resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} - '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -10402,12 +10379,6 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@17.0.35': - resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} @@ -10507,11 +10478,6 @@ packages: resolution: {integrity: sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260225.1': - resolution: {integrity: sha512-3qSsqv7FmM4z09wEpEXdhmgMfiJF/OMOZa41AdgMsXTTRpX2/38hDg2KGhi3fc24M2T3MnLPLTqw6HyTOBaV1Q==} - cpu: [arm64] - os: [darwin] - '@typescript/native-preview-darwin-x64@7.0.0-dev.20260225.1': resolution: {integrity: sha512-F8ZCCX2UESHcbxvnkd1Dn5PTnOOgpGddFHYgn4usyWRMzNZLPP+YjyGALZe9zdR/D8L0uraND0Haok+TPq8xYg==} cpu: [x64] @@ -10826,9 +10792,6 @@ packages: vite: optional: true - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - '@vitest/pretty-format@4.1.6': resolution: {integrity: sha512-h5SxD/IzNhZYnrSZRsUZQIC+vD0GY8cUvq0iwsmkFKixRCKLLWqCXa/FIQ4S1R+sI+PGoojkHsdNrbZiM9Qpgw==} @@ -10844,9 +10807,6 @@ packages: '@vitest/spy@4.1.6': resolution: {integrity: sha512-JFKxMx6udhwKh/Ldo270e17QX710vgunMkuPAvXjHSvC6oqLWAHhVhjg/I71q0u0CBSErIODV1Kjv0FQNSWjdg==} - '@vitest/utils@3.2.4': - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - '@vitest/utils@4.1.6': resolution: {integrity: sha512-FxIY+U81R3LGKCxaHHFRQ5+g6/iRgGLmeHWdp2Amj4ljQRrEIWHmZyDfDYBRZlpyqA7qKxtS9DD1dhk8RnRIVQ==} @@ -10945,6 +10905,10 @@ packages: peerDependencies: react: ^18.0.0 + '@wordpress/api-fetch@7.46.0': + resolution: {integrity: sha512-QOxuHSUXMzLat3Y90+0HNUDPSlBUK53r4mQ4m7f4/OKaWRRZU5jzvDBJyj52dEST7yJ1eZtuqUkEwK2T1MEBfQ==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + '@wordpress/api-fetch@7.48.0': resolution: {integrity: sha512-WYoIikKQPdRqrbLB9b9diM80q4g80NqqMPwVYZY9c7vbhJvj5c0hkA5zAlwba/iRbwqDjpRiZMKp8XntYLzMWw==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11033,6 +10997,13 @@ packages: '@wordpress/theme': optional: true + '@wordpress/commands@1.46.0': + resolution: {integrity: sha512-Pzn9noMCkmFs+tRd5ghpkJy1iZtc0EfHU8XQTKoL2rtafs5Sxhsw08+85RNci/Uk7FZKhDTjKCgy7bxlyZ4EIQ==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + '@wordpress/commands@1.48.0': resolution: {integrity: sha512-wSo0Sj0Y7Z+yNfhp8QouB7rBSC9d3+Vb2/RKB/480+WlidFvCDgsFJPojNenqXdPlUTVcbgjsj0jLls8BbwHbA==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11066,6 +11037,13 @@ packages: peerDependencies: react: ^18.0.0 + '@wordpress/core-data@7.46.0': + resolution: {integrity: sha512-mfiqOrXcsv4rZJZFYjmUSc5goK1cKpuQ1lSoSBnuKMJNZAxTCVTwexIaj0XI5Qr/ngUjT5U1+w4I0Fzuv/qCMQ==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + '@wordpress/core-data@7.48.0': resolution: {integrity: sha512-coukurBp/mTSugI1PRKwunJsk9/sVilwdFv5h4yFWisVIMclZQ0GJg+MOLiK18fWEtqjPD2J1j7Aoz12QEx1Lw==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11079,6 +11057,12 @@ packages: peerDependencies: react: ^18.0.0 + '@wordpress/data@10.46.0': + resolution: {integrity: sha512-vxOO2IEn+29eue9Pq7Mzsq1SipMAg0Rp0Oztz9LsgWQIF9yyylGlP3yHnFjEmJ4MonGSjzvpArlc7jWwkzutKg==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + peerDependencies: + react: ^18.0.0 + '@wordpress/data@10.48.0': resolution: {integrity: sha512-6SjfTBlXu5fuJWmmlHlwV2wcrcsWL+M5O227AoEvrPSLo96UuMj2kAx3cKLtP3xyOMDyd38koQSf6+SS522bTA==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11217,6 +11201,11 @@ packages: resolution: {integrity: sha512-KGxdaLC36wE10GybSfjYGcyWiy+KQCYheB6T8jhZhQ9mlf2Zwx6aJgfZm/L6BLwNN33Efx+sJY3nvMIxI5UwnA==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} + '@wordpress/i18n@6.19.0': + resolution: {integrity: sha512-hRXd2E0SF9OQf22ZZWw7Ny/o+Q9u8jINiF1p0bF+rnSDKQUgoStihak6YiazWVRiIEYwctzotKXlt0HePJelXA==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + hasBin: true + '@wordpress/i18n@6.21.0': resolution: {integrity: sha512-IXGGUJqN6b7QddU0dZB3HLJKu6uDQuhLsrrzYpUYTjDhfa43XEaikA9xHNgZhqzRtOVYqsNHVliWcISvJ/xjZQ==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11335,6 +11324,13 @@ packages: react: ^18.0.0 react-dom: ^18.0.0 + '@wordpress/preferences@4.46.0': + resolution: {integrity: sha512-vLvkOKmziv/D0ksC8wZ94bAeIAvXQm+X86Bte36kXXEvrru2+QGxCz4pHT+qOdkkALzS2cKXc7prqRCigRzJwg==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + '@wordpress/preferences@4.48.0': resolution: {integrity: sha512-ae8SOpc+NTFf5dB1bgN4RwMCzCQC/gX0d72SDxqtBeU1N52+sihunob9bhPLAEimKS/nMR/kU+YS9j9y5jyZ0A==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11348,6 +11344,12 @@ packages: peerDependencies: prettier: '>=3' + '@wordpress/primitives@4.46.0': + resolution: {integrity: sha512-x1IhEVa/aGDe6otGJ4VIqEioQGfIeK5B1VQm32+ycqinJRbtbw9F5bgx4ARIdnm5M1Lg63oV9Bhmg/XMyGSTZA==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + peerDependencies: + react: ^18.0.0 + '@wordpress/primitives@4.48.0': resolution: {integrity: sha512-dfF7IZotIqb6LUiGs7oPwKbSF8RPoC0JDSIrtxvgwFA/yvbc/pDIp/Zs0O8GvxZNxu4JIVnKskOhoLq7lAeziQ==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11358,6 +11360,10 @@ packages: resolution: {integrity: sha512-NuGrfSSnBC794erb3xSEKrzWLGCNLa+ukob0pyVRtnebU7fPgrhx4NCBCXYK1vTcAta3NAkOVRfUZgcmLFYA6g==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} + '@wordpress/private-apis@1.46.0': + resolution: {integrity: sha512-l8dsEuxq6CrtsI7Twfpn6CbPHmGBUQoGN4oLPJG1Bqsr1yXXLU/bEx9KAQN9emxRjXaELPsn7x7TVx0TUoKyJw==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + '@wordpress/private-apis@1.48.0': resolution: {integrity: sha512-HHOSXLCAlBggfMozwWtX36wgsSt22g2tZwpka47Rjzr3hNY1BZ6SrrFJumiNxooy5PDKbRgcF092PAF82hdJXg==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11498,6 +11504,12 @@ packages: resolution: {integrity: sha512-NfhCvFyJnKQ7XnqLlFXbigwZzhnNQZPgS+mpXTkttq/d0/b62TgvjQd5XIu5wiEkWXye7rmZfdkRmG8fWmEb3Q==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} + '@wordpress/viewport@6.46.0': + resolution: {integrity: sha512-n/kfg5x/lGCK3FkyxrMh+D3LOk5FDPpbCtq81wtvy8Xy+GwuU4g2quRhfYENoia13tp6HVX52fyugRIGZmM/sg==} + engines: {node: '>=18.12.0', npm: '>=8.19.2'} + peerDependencies: + react: ^18.0.0 + '@wordpress/viewport@6.48.0': resolution: {integrity: sha512-mP9BAg4xsFMiActGBjmADqcws+URFloJEfOFiCDe8y1BqWHdeNaUBC1cjXcgYj4hjmcij/lCBVdccKHg6BEAgg==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} @@ -11535,10 +11547,6 @@ packages: resolution: {integrity: sha512-GyXj5tLYH5aon7yIJbqODeGmIowrjAohA2UrEJLU4UKbJdVAWyx9dlqF/bGs3sUKkkldPxYU7Wk2WIATfu0VGQ==} engines: {node: '>=18.12.0', npm: '>=8.19.2'} - '@xmldom/xmldom@0.9.10': - resolution: {integrity: sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==} - engines: {node: '>=14.6'} - '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -11578,10 +11586,6 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -11603,19 +11607,12 @@ packages: ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - allure-js-commons@2.15.1: - resolution: {integrity: sha512-5V/VINplbu0APnfSZOkYpKOzucO36Q2EtTD1kqjWjl7n6tj7Hh+IHCZsH3Vpk/LXRDfj9RuXugBBvwYKV5YMJw==} - allure-playwright@2.15.1: resolution: {integrity: sha512-P1Uu1j/ptDHdYp3V5ZAeBZyt33+L+OQu0otUIEl/zkOcv0KRycHqlHwC0GEJmpgnLKvVP7s+K37LcLoSUUj3Cg==} anser@2.3.5: resolution: {integrity: sha512-vcZjxvvVoxTeR5XBNJB38oTu/7eDCZlwdz32N1eNgpyPF7j/Z7Idf+CUwQOkKKpJ7RJyjxgLHCM7vdIK0iCNMQ==} - ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - ansi-escapes@3.2.0: resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} engines: {node: '>=4'} @@ -11637,10 +11634,6 @@ packages: resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} engines: {node: '>=4'} - ansi-regex@4.1.1: - resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} - engines: {node: '>=6'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -11665,10 +11658,6 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - any-observable@0.3.0: resolution: {integrity: sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==} engines: {node: '>=6'} @@ -11688,23 +11677,10 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - append-transform@2.0.0: - resolution: {integrity: sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==} - engines: {node: '>=8'} - - archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - are-docs-informative@0.0.2: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-hidden@1.2.6: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} @@ -11712,9 +11688,6 @@ packages: aria-query@5.1.3: resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - aria-query@5.3.1: resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} engines: {node: '>= 0.4'} @@ -11773,10 +11746,6 @@ packages: resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} engines: {node: '>=4'} - ast-types@0.16.1: - resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} - engines: {node: '>=4'} - astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -11785,15 +11754,6 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - atomically@2.1.1: - resolution: {integrity: sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ==} - autoprefixer@10.4.20: resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} @@ -11913,10 +11873,6 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} - bare-events@2.9.1: resolution: {integrity: sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==} peerDependencies: @@ -11970,9 +11926,6 @@ packages: batch@0.6.1: resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} - before-after-hook@4.0.0: - resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} - bidi-js@1.0.3: resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} @@ -11987,9 +11940,6 @@ packages: bonjour-service@1.4.0: resolution: {integrity: sha512-fGQtj1qdR9vIKjFiWPQd52qIqwjaYqhcI40JEiDuvlZ86E7ZBPBwY9fPgHy9r2rYGIjiRfctNPYz6OQU73ww2w==} - boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - bounding-client-rect@1.0.5: resolution: {integrity: sha512-3OVNM56TuMbHZYjbIbAkHZ7VHYVK9RPLr3s2nZucuJm1HgDBFEY6twJce4dCNwF0MO3ySOyA9KUZ+pObCd4mow==} @@ -11999,10 +11949,6 @@ packages: brace-expansion@2.1.1: resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} - brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} - engines: {node: 18 || 20 || >=22} - braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -12031,10 +11977,6 @@ packages: builtin-status-codes@2.0.0: resolution: {integrity: sha512-8KPx+JfZWi0K8L5sycIOA6/ZFZbaFKXDeUIXaqwUnhed1Ge1cB0wyq+bNDjKnL9AR2Uj3m/khkF6CDolsyMitA==} - bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - bundle-require@5.1.0: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -12090,17 +12032,10 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - camel-case@4.1.2: - resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - camelcase@1.2.1: resolution: {integrity: sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==} engines: {node: '>=0.10.0'} - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -12117,16 +12052,9 @@ packages: canvas-confetti@1.9.4: resolution: {integrity: sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==} - capital-case@1.0.4: - resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} - ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} - engines: {node: '>=18'} - chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} @@ -12160,20 +12088,6 @@ packages: character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - charenc@0.0.2: - resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} - - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - - cheerio-select@1.6.0: - resolution: {integrity: sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==} - - cheerio@1.0.0-rc.10: - resolution: {integrity: sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==} - engines: {node: '>= 6'} - chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -12213,10 +12127,6 @@ packages: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} - clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - cli-cursor@2.1.0: resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} engines: {node: '>=4'} @@ -12231,20 +12141,10 @@ packages: clipboard@2.0.11: resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==} - cliui@5.0.0: - resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} - - cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} - cliui@9.0.1: - resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} - engines: {node: '>=20'} - clone-deep@4.0.1: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} @@ -12277,61 +12177,24 @@ packages: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - color-convert@3.1.3: - resolution: {integrity: sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==} - engines: {node: '>=14.6'} - color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-name@2.1.0: - resolution: {integrity: sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==} - engines: {node: '>=12.20'} - - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - - color-string@2.1.4: - resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==} - engines: {node: '>=18'} - - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - - color@5.0.3: - resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==} - engines: {node: '>=18'} - colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - colorjs.io@0.5.2: - resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} - colorjs.io@0.6.1: resolution: {integrity: sha512-8lyR2wHzuIykCpqHKgluGsqQi5iDm3/a2IgP2GBZrasn2sBRkE4NOGsglZxWLs/jZQoNkmA/KM/8NV16rLUdBg==} - combine-errors@3.0.3: - resolution: {integrity: sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q==} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - comctx@1.6.1: resolution: {integrity: sha512-ZMRGAYASYRdVfEoB7oxH8Nqu5Ay8I+YvAsQni+td0pYV9eww/PrtSFVyvc2JkNQyHXGDknCB4wJfxFYP6fuqZg==} - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} @@ -12401,9 +12264,6 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - constant-case@3.0.4: - resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} - content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -12412,10 +12272,6 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - content-type@2.0.0: - resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} - engines: {node: '>=18'} - convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} @@ -12484,16 +12340,10 @@ packages: engines: {node: '>= 0.4.0'} hasBin: true - crelt@1.0.6: - resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - crypt@0.0.2: - resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} - crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} @@ -12547,16 +12397,6 @@ packages: lightningcss: optional: true - css-select@4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - - css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - - css-tree@2.2.1: - resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - css-tree@2.3.1: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -12565,13 +12405,6 @@ packages: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} - - css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - csscolorparser@1.0.3: resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==} @@ -12598,10 +12431,6 @@ packages: peerDependencies: postcss: ^8.5.13 - csso@5.0.5: - resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - cssstyle@5.3.7: resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} engines: {node: '>=20'} @@ -12609,63 +12438,21 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - cubic2quad@1.2.1: - resolution: {integrity: sha512-wT5Y7mO8abrV16gnssKdmIhIbA9wSkeMzhh27jAguKrV82i24wER0vL5TGhUJ9dbJNDcigoRZ0IAHFEEEI4THQ==} - - custom-error-instance@2.1.1: - resolution: {integrity: sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg==} - - d3-array@3.2.1: - resolution: {integrity: sha512-gUY/qeHq/yNqqoCKNq4vtpFLdoCdvyNpWoC/KNjhGbhDuQpAM9sIQQKkXSNpXa9h5KySs/gzm7R88WkUutgwWQ==} - engines: {node: '>=12'} - - d3-color@3.1.0: - resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} - engines: {node: '>=12'} - - d3-delaunay@6.0.2: - resolution: {integrity: sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==} - engines: {node: '>=12'} - - d3-format@3.1.0: - resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} - engines: {node: '>=12'} - - d3-geo@3.1.0: - resolution: {integrity: sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==} - engines: {node: '>=12'} - d3-interpolate-path@2.2.1: resolution: {integrity: sha512-6qLLh/KJVzls0XtMsMpcxhqMhgVEN7VIbR/6YGZe2qlS8KDgyyVB20XcmGnDyB051HcefQXM/Tppa9vcANEA4Q==} - d3-interpolate@3.0.1: - resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} - engines: {node: '>=12'} - d3-path@1.0.9: resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} d3-path@2.0.0: resolution: {integrity: sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA==} - d3-scale@4.0.2: - resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} - engines: {node: '>=12'} - d3-shape@1.3.7: resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} d3-shape@2.1.0: resolution: {integrity: sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==} - d3-time-format@4.1.0: - resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} - engines: {node: '>=12'} - - d3-time@3.1.0: - resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} - engines: {node: '>=12'} - d3-voronoi@1.1.4: resolution: {integrity: sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==} @@ -12698,10 +12485,6 @@ packages: date-fns@1.30.1: resolution: {integrity: sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==} - date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} - date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} @@ -12755,10 +12538,6 @@ packages: babel-plugin-macros: optional: true - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - deep-equal@2.2.3: resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} engines: {node: '>= 0.4'} @@ -12770,18 +12549,6 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - default-browser-id@5.0.1: - resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} - engines: {node: '>=18'} - - default-browser@5.5.0: - resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} - engines: {node: '>=18'} - - default-require-extensions@3.0.1: - resolution: {integrity: sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==} - engines: {node: '>=8'} - define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -12790,10 +12557,6 @@ packages: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} - define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -12802,16 +12565,6 @@ packages: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} - delaunator@5.1.0: - resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - delegate@3.2.0: - resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==} - depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} engines: {node: '>= 0.6'} @@ -12885,44 +12638,25 @@ packages: dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - dom-accessibility-api@0.6.3: - resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - dom-serializer@1.4.1: - resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - domhandler@4.3.1: - resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} - engines: {node: '>= 4'} - domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - domino@2.1.7: - resolution: {integrity: sha512-3rcXhx0ixJV2nj8J0tljzejTF73A35LVVdnTQu79UAqTBFEgYPMgGtykMuu/BDqaOZphATku1ddRUn/RtqUHYQ==} - dompurify@3.4.8: resolution: {integrity: sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==} - domutils@2.8.0: - resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - dot-case@3.0.4: - resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} - dot-prop@9.0.0: resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} engines: {node: '>=18'} @@ -12956,12 +12690,6 @@ packages: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - - emoji-regex@7.0.3: - resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -12972,16 +12700,10 @@ packages: resolution: {integrity: sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==} engines: {node: '>=14'} - enabled@2.0.0: - resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} - encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} - encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} @@ -12993,9 +12715,6 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} - entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -13075,9 +12794,6 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - es6-error@4.1.1: - resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} - esbuild-plugin-babel@0.2.3: resolution: {integrity: sha512-hGLL31n+GvBhkHUpPCt1sU4ynzOH7I1IUkKhera66jigi4mHFPL6dfJo44L6/1rfcZudXx+wGdf9VOifzDPqYQ==} peerDependencies: @@ -13557,9 +13273,6 @@ packages: picomatch: optional: true - fecha@4.2.3: - resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} - figures@1.7.0: resolution: {integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==} engines: {node: '>=0.10.0'} @@ -13598,10 +13311,6 @@ packages: resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} engines: {node: '>=18'} - find-up@3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -13631,9 +13340,6 @@ packages: flatted@3.4.2: resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} - fn.name@1.1.0: - resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - focus-trap@6.3.0: resolution: {integrity: sha512-BBzvFfkPg5PqrVVCdQ1YOIVNKGvqG9YNVkiAUQFuDM66N8J9uADhs6mlYKrd30ofDJIzEniBnBKM7GO45iCzKQ==} @@ -13650,10 +13356,6 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} - foreground-child@2.0.0: - resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} - engines: {node: '>=8.0.0'} - foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -13700,9 +13402,6 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} - fromentries@1.3.2: - resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} - fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -13710,11 +13409,6 @@ packages: fs-monkey@1.1.0: resolution: {integrity: sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==} - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -13748,9 +13442,6 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-document@1.0.0: - resolution: {integrity: sha512-8E7H2Xxibav+/rQTTtm6gFlSQwDoAQg667yheA+vWQr/amxEuswChzGo4MIbOJJoR0SMpDyhbUqWp3FpIfwD9A==} - get-east-asian-width@1.6.0: resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} @@ -13794,9 +13485,6 @@ packages: resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} engines: {node: '>= 14'} - gettext-parser@1.4.0: - resolution: {integrity: sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==} - git-hooks-list@4.2.1: resolution: {integrity: sha512-WNvqJjOxxs/8ZP9+DWdwWJ7cDsd60NHf39XnD82pDVrKO5q7xfPqpkK6hwEAmBa/ZSEE4IOoR75EzbbIuwGlMw==} @@ -13858,9 +13546,6 @@ packages: globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - good-listener@1.2.2: - resolution: {integrity: sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -13887,9 +13572,6 @@ packages: handle-thing@2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} - harmony-reflect@1.6.2: - resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} - has-ansi@2.0.0: resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} engines: {node: '>=0.10.0'} @@ -13928,10 +13610,6 @@ packages: hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - hasha@5.2.2: - resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} - engines: {node: '>=8'} - hashery@1.5.1: resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==} engines: {node: '>=20'} @@ -13944,9 +13622,6 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - header-case@2.0.4: - resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} - hermes-estree@0.25.1: resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} @@ -13988,9 +13663,6 @@ packages: html-entities@2.6.0: resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} - html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - html-react-parser@5.2.11: resolution: {integrity: sha512-WnSQVn/D1UTj64nSz5y8MriL+MrbsZH80Ytr1oqKqs8DGZnphWY1R1pl3t7TY3rpqTSu+FHA21P80lrsmrdNBA==} peerDependencies: @@ -14007,9 +13679,6 @@ packages: htmlparser2@10.0.0: resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} - htmlparser2@6.1.0: - resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} - http-deceiver@1.2.7: resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} @@ -14057,10 +13726,6 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - husky@9.1.7: resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} @@ -14079,10 +13744,6 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - icss-replace-symbols@1.1.0: resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} @@ -14114,9 +13775,6 @@ packages: image-ssim@0.2.0: resolution: {integrity: sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==} - immutable@5.1.6: - resolution: {integrity: sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==} - import-cwd@3.0.0: resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==} engines: {node: '>=8'} @@ -14148,10 +13806,6 @@ packages: resolution: {integrity: sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==} engines: {node: '>=4'} - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - index-to-position@1.2.0: resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==} engines: {node: '>=18'} @@ -14169,10 +13823,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - internmap@2.0.3: - resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} - engines: {node: '>=12'} - interpret@3.1.1: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} @@ -14203,9 +13853,6 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.4: - resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} - is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -14222,13 +13869,6 @@ packages: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} - is-buffer@1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - - is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - is-bun-module@2.0.0: resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} @@ -14253,11 +13893,6 @@ packages: engines: {node: '>=8'} hasBin: true - is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - is-electron@2.2.2: resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} @@ -14293,11 +13928,6 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -14380,10 +14010,6 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} @@ -14396,9 +14022,6 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -14411,18 +14034,10 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} - is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} - is-wsl@3.1.1: - resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} - engines: {node: '>=16'} - isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -14440,9 +14055,6 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - isomorphic.js@0.2.5: - resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -14641,9 +14253,6 @@ packages: jquery@3.7.1: resolution: {integrity: sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==} - js-base64@3.7.8: - resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} - js-library-detector@6.7.0: resolution: {integrity: sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA==} engines: {node: '>=12'} @@ -14654,10 +14263,6 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.14.2: - resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} - hasBin: true - js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true @@ -14698,9 +14303,6 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json-with-bigint@3.5.8: - resolution: {integrity: sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==} - json2php@0.0.7: resolution: {integrity: sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==} @@ -14727,9 +14329,6 @@ packages: kdbush@3.0.0: resolution: {integrity: sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==} - kebab-case@1.0.2: - resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -14743,9 +14342,6 @@ packages: known-css-properties@0.37.0: resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==} - kuler@2.0.0: - resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} - language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -14778,9 +14374,6 @@ packages: libsodium-wrappers@0.7.10: resolution: {integrity: sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==} - libsodium@0.7.16: - resolution: {integrity: sha512-3HrzSPuzm6Yt9aTYCDxYEG8x8/6C0+ag655Y7rhhWZM9PT4NpdnbqlzXhGZlDnkgR6MeSTnOt/VIyHLs9aSf+Q==} - lighthouse-logger@2.0.2: resolution: {integrity: sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg==} @@ -14881,9 +14474,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - linkify-it@5.0.1: - resolution: {integrity: sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==} - listr-silent-renderer@1.1.1: resolution: {integrity: sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==} engines: {node: '>=4'} @@ -14942,14 +14532,6 @@ packages: locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} - locate-path@3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -14961,33 +14543,12 @@ packages: lodash-es@4.18.1: resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} - lodash._baseiteratee@4.7.0: - resolution: {integrity: sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ==} - - lodash._basetostring@4.12.0: - resolution: {integrity: sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw==} - - lodash._baseuniq@4.6.0: - resolution: {integrity: sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A==} - - lodash._createset@4.0.3: - resolution: {integrity: sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA==} - - lodash._root@3.0.1: - resolution: {integrity: sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ==} - - lodash._stringtopath@4.8.0: - resolution: {integrity: sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ==} - lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - lodash.flattendeep@4.4.0: - resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} - lodash.groupby@4.6.0: resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} @@ -14997,18 +14558,12 @@ packages: lodash.mergewith@4.6.2: resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} - lodash.throttle@4.1.1: - resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} - lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} lodash.uniq@4.5.0: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - lodash.uniqby@4.5.0: - resolution: {integrity: sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ==} - lodash@4.18.1: resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} @@ -15020,10 +14575,6 @@ packages: resolution: {integrity: sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==} engines: {node: '>=4'} - logform@2.7.0: - resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} - engines: {node: '>= 12.0.0'} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -15034,12 +14585,6 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - - lower-case@2.0.2: - resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - lru-cache@11.5.1: resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} engines: {node: 20 || >=22} @@ -15070,10 +14615,6 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} @@ -15107,9 +14648,6 @@ packages: md5-es@1.8.2: resolution: {integrity: sha512-LKq5jmKMhJYhsBFUh2w+J3C4bMiC5uQie/UYJ429UATmMnFr6iANO2uQq5HXAZSIupGp0WO2mH3sNfxR4XO40Q==} - md5@2.3.0: - resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} - mdast-util-find-and-replace@3.0.2: resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} @@ -15143,21 +14681,12 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - mdn-data@2.0.28: - resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} - - mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} mdn-data@2.28.1: resolution: {integrity: sha512-U9w+PzSZ00Z5m9rZ5ARVFL5xOfuCHdKYi/1RRwDCJsboFgJDNT3zT6PIPD7mZQYaQLhsZM3GfDRgSMRHhSmVng==} - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -15197,9 +14726,6 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - microbuffer@1.0.0: - resolution: {integrity: sha512-O/SUXauVN4x6RaEJFqSPcXNtLFL+QzJHKZlyDVYFwcDDRVca3Fa/37QXXC+4zAGGa4YhHrHxKXuuHvLDIQECtA==} - micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -15322,10 +14848,6 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -15353,10 +14875,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.3: - resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} - engines: {node: '>=16 || 14 >=14.17'} - mitt@2.1.0: resolution: {integrity: sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==} @@ -15404,11 +14922,6 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.12: - resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - nanospinner@1.2.2: resolution: {integrity: sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==} @@ -15435,9 +14948,6 @@ packages: resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} engines: {node: '>= 0.4.0'} - no-case@3.0.4: - resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} @@ -15479,16 +14989,9 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nspell@2.1.5: resolution: {integrity: sha512-PSStyugKMiD9mHmqI/CR5xXrSIGejUXPlo88FBRq5Og1kO5QwQ5Ilu8D8O5I/SHpoS+mibpw6uKA8rd3vXd2Sg==} - nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - number-is-nan@1.0.1: resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} engines: {node: '>=0.10.0'} @@ -15555,9 +15058,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - one-time@1.0.0: - resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} - onetime@2.0.1: resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} engines: {node: '>=4'} @@ -15566,10 +15066,6 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - open@10.2.0: resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} engines: {node: '>=18'} @@ -15590,10 +15086,6 @@ packages: zod: optional: true - opencollective-postinstall@2.0.3: - resolution: {integrity: sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==} - hasBin: true - openurl@1.1.1: resolution: {integrity: sha512-d/gTkTb1i1GKz5k3XE3XFV/PxQ1k45zDqGP2OA7YhgsaLoqm6qRvARAZOFer1fcXritWlGBRCu/UgeS4HAnXAA==} @@ -15616,14 +15108,6 @@ packages: resolution: {integrity: sha512-4Ispi9I9qYGO4lueiLDhe4q4iK5ERK8reLsuzH6BPaXn53EGaua8H66PXIFGrW897hwjXp+pVLrm/DLxN0RF0A==} engines: {node: '>=12'} - p-finally@1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -15632,14 +15116,6 @@ packages: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-locate@3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} @@ -15668,14 +15144,6 @@ packages: resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} engines: {node: '>=16.17'} - p-timeout@3.2.0: - resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} - engines: {node: '>=8'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - pac-proxy-agent@7.2.0: resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} engines: {node: '>= 14'} @@ -15688,20 +15156,10 @@ packages: resolution: {integrity: sha512-qJSu5Mo6tHmRxCy2KCYYKYgcfBdUpy9dwReaZD/xwf608AUk/MoRtIOWzgDtUeGeC7n/55yC3MI1Q+MbSoektw==} engines: {node: '>=18'} - package-hash@4.0.0: - resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} - engines: {node: '>=8'} - - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - package-json-validator@1.5.2: resolution: {integrity: sha512-eHXskJQU4aCiSfjhRfTVtCJ+22/EzLHgYgZv5Gj3teb3NJrnTMzq5BnKAWKvR+PLpknCO1PmOCImDuO+dX4Vaw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - param-case@3.0.4: - resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -15726,12 +15184,6 @@ packages: parse-statements@1.0.11: resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} - parse5-htmlparser2-tree-adapter@6.0.1: - resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} - - parse5@6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -15745,19 +15197,9 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - pascal-case@3.1.2: - resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - path-case@3.0.4: - resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} - - path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -15766,20 +15208,12 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - path-name@1.0.0: resolution: {integrity: sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==} path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@2.0.2: - resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} - engines: {node: 18 || 20 || >=22} - path-to-regexp@0.1.13: resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} @@ -15793,10 +15227,6 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - pbf@3.3.0: resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} hasBin: true @@ -15840,10 +15270,6 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -16241,13 +15667,6 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - proper-lockfile@4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - - properties@1.2.1: - resolution: {integrity: sha512-qYNxyMj1JeW54i/EWEFsM1cVwxJbtgPp8+0Wg9XjNaK6VE/c4oRi6PNu5p7w1mNXEIQIjV5Wwn8v8Gz82/QzdQ==} - engines: {node: '>=0.10'} - protocol-buffers-schema@3.6.1: resolution: {integrity: sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==} @@ -16269,10 +15688,6 @@ packages: pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} - engines: {node: '>=6'} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -16311,9 +15726,6 @@ packages: resolution: {integrity: sha512-ZHoCB3M/3Voev64zhLLUOKDtaEdJ/lymsJJ7R3KBusVZ2ovNiIB7XOq3Xh6V1a8O+Vho+g2B5YElq9zW7D8aQw==} engines: {node: '>=4'} - querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -16518,10 +15930,6 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - readdirp@4.1.2: - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} - engines: {node: '>= 14.18.0'} - recast@0.23.11: resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} engines: {node: '>= 4'} @@ -16530,10 +15938,6 @@ packages: resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} engines: {node: '>= 10.13.0'} - redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - reduce-css-calc@1.3.0: resolution: {integrity: sha512-0dVfwYVOlf/LBA2ec4OwQ6p3X9mYxn/wOl2xTcLwjnPYrkgEfPx3VI4eGCH3rQLlPISG5v9I9bkZosKsNRTRKA==} @@ -16590,10 +15994,6 @@ packages: resolution: {integrity: sha512-dLN0+SBPutC6bVFCH2+1o2VrHrvAj/PX6MzTemeaEKlCL10JKPMRlqszkitLQnHVgm90QQ94wxoBJRgfIEkstg==} engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} - release-zalgo@1.0.0: - resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} - engines: {node: '>=4'} - remark-gfm@4.0.0: resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} @@ -16609,9 +16009,6 @@ packages: remove-accents@0.5.0: resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} - requestidlecallback@0.3.0: - resolution: {integrity: sha512-TWHFkT7S9p7IxLC5A1hYmAYQx2Eb9w1skrXmQ+dS1URyvR8tenMLl4lHbqEOUnpEYxNKpkVMXUgknVpBZWXXfQ==} - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -16624,12 +16021,6 @@ packages: resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} engines: {node: '>=8.6.0'} - require-like@0.1.2: - resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} - - require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - requireindex@1.2.0: resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} engines: {node: '>=0.10.5'} @@ -16647,10 +16038,6 @@ packages: resize-observer-polyfill@1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -16683,10 +16070,6 @@ packages: resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} engines: {node: '>=4'} - retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -16704,9 +16087,6 @@ packages: resolution: {integrity: sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==} engines: {node: '>=10.0.0'} - robust-predicates@3.0.3: - resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} - rolldown@1.0.0-rc.12: resolution: {integrity: sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -16754,10 +16134,6 @@ packages: engines: {node: '>=12.0.0'} hasBin: true - run-applescript@7.1.0: - resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} - engines: {node: '>=18'} - run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -16771,9 +16147,6 @@ packages: resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} engines: {npm: '>=2.0.0'} - rxjs@7.8.2: - resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} - safe-array-concat@1.1.4: resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} engines: {node: '>=0.4'} @@ -16795,10 +16168,6 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} - safe-stable-stringify@2.5.0: - resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} - engines: {node: '>=10'} - safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -16826,12 +16195,6 @@ packages: cpu: [x64] os: [android] - sass-embedded-darwin-arm64@1.97.3: - resolution: {integrity: sha512-fuqMTqO4gbOmA/kC5b9y9xxNYw6zDEyfOtMgabS7Mz93wimSk2M1quQaTJnL98Mkcsl2j+7shNHxIS/qpcIDDA==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [darwin] - sass-embedded-darwin-x64@1.97.3: resolution: {integrity: sha512-b/2RBs/2bZpP8lMkyZ0Px0vkVkT8uBd0YXpOwK7iOwYkAT8SsO4+WdVwErsqC65vI5e1e5p1bb20tuwsoQBMVA==} engines: {node: '>=14.0.0'} @@ -16957,9 +16320,6 @@ packages: select-hose@2.0.0: resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} - select@1.1.2: - resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==} - selfsigned@5.5.0: resolution: {integrity: sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==} engines: {node: '>=18'} @@ -16982,9 +16342,6 @@ packages: resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} - sentence-case@3.0.4: - resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} - serialize-javascript@7.0.5: resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==} engines: {node: '>=20.0.0'} @@ -17007,9 +16364,6 @@ packages: resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} engines: {node: '>= 0.8.0'} - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-cookie-parser@2.7.2: resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} @@ -17087,9 +16441,6 @@ packages: simple-html-tokenizer@0.5.11: resolution: {integrity: sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og==} - simple-swizzle@0.2.4: - resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} - sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -17131,9 +16482,6 @@ packages: resolution: {integrity: sha512-RQsvleCbF8cVHEv+xuDGaA4pOizFqJ0GgjtMSRo6oP8pnN7WsigHgVGey6aILRBKv4W2YOMHLqbKdnB6hpB9fw==} engines: {node: '>=20.0.0'} - snake-case@3.0.4: - resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} - social-logos@3.3.16: resolution: {integrity: sha512-QRfgZ54AdVopzWJuUWhwPkPaDq2SRAzJt4uPe6rXdvBUGQIb5gQLXNADFOYcBpW3ULO943pHr4whXTKQ/YgxPA==} peerDependencies: @@ -17219,9 +16567,6 @@ packages: resolution: {integrity: sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==} engines: {node: '>=8.0'} - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} @@ -17229,9 +16574,6 @@ packages: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} - stack-trace@0.0.10: - resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} - stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -17290,18 +16632,10 @@ packages: resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} engines: {node: '>=4'} - string-width@3.1.0: - resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} - engines: {node: '>=6'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - string-width@8.2.1: resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} @@ -17343,10 +16677,6 @@ packages: resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} engines: {node: '>=4'} - strip-ansi@5.2.0: - resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} - engines: {node: '>=6'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -17367,10 +16697,6 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -17386,18 +16712,9 @@ packages: strip@3.0.0: resolution: {integrity: sha512-kIPiqRSsGCwWItPLDhuZPQlwX16WjQggT5QS1f5Aam0DSbtPQh8SsIkbBxLm+835qb1Q0OoQnvrhJ0oplIup8Q==} - stubborn-fs@2.0.0: - resolution: {integrity: sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA==} - - stubborn-utils@1.0.2: - resolution: {integrity: sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg==} - style-inject@0.3.0: resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} - style-mod@4.1.3: - resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} - style-search@0.1.0: resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} @@ -17469,10 +16786,6 @@ packages: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} @@ -17565,9 +16878,6 @@ packages: engines: {node: '>=16'} hasBin: true - svgpath@2.6.0: - resolution: {integrity: sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg==} - svgstore@3.0.1: resolution: {integrity: sha512-nL6WTxYnsVl3e0G/mwGEFSnPAWUrzIwHAPOwInD4QUuLDKxaKMnXduf0Ipw3m/g9AldPhp1Y8E/nkReFBukJrA==} engines: {node: '>= 12'} @@ -17583,21 +16893,10 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - sync-child-process@1.0.2: - resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==} - engines: {node: '>=16.0.0'} - - sync-message-port@1.2.0: - resolution: {integrity: sha512-gAQ9qrUN/UCypHtGFbbe7Rc/f9bzO88IwrG8TDo/aMKAApKyD6E3W4Cm0EfhfBb6Z6SKt59tTCTfD+n1xmAvMg==} - engines: {node: '>=16.0.0'} - synckit@0.11.13: resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} - tabbable@5.3.3: - resolution: {integrity: sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==} - tabbable@6.4.0: resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} @@ -17661,9 +16960,6 @@ packages: text-decoder@1.2.7: resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} - text-hex@1.0.0: - resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} - thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -17689,9 +16985,6 @@ packages: thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} - tiny-emitter@2.1.0: - resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} - tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -17719,18 +17012,10 @@ packages: tinyqueue@2.0.3: resolution: {integrity: sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==} - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - tinyrainbow@3.1.0: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} - engines: {node: '>=14.0.0'} - tldts-core@7.4.2: resolution: {integrity: sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==} @@ -17785,10 +17070,6 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - triple-beam@1.4.1: - resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} - engines: {node: '>= 14.0.0'} - trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} @@ -17841,10 +17122,6 @@ packages: resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} engines: {node: '>= 6.0.0'} - tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - turndown@7.1.2: resolution: {integrity: sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==} @@ -17864,10 +17141,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - type-fest@4.41.0: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} @@ -17899,9 +17172,6 @@ packages: typed-query-selector@2.12.2: resolution: {integrity: sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==} - typedarray-to-buffer@3.1.5: - resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - typescript-eslint@8.60.0: resolution: {integrity: sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -17914,9 +17184,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - ufo@1.6.4: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} @@ -17924,9 +17191,6 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} - undici-types@7.18.2: - resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici@6.26.0: resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==} engines: {node: '>=18.17'} @@ -17974,9 +17238,6 @@ packages: unist-util-visit@5.1.0: resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} - universal-user-agent@7.0.3: - resolution: {integrity: sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==} - universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -18008,21 +17269,12 @@ packages: uplot@1.6.31: resolution: {integrity: sha512-sQZqSwVCbJGnFB4IQjQYopzj5CoTZJ4Br1fG/xdONimqgHmsacvCjNesdGDypNKFbrhLGIeshYhy89FxPF+H+w==} - upper-case-first@2.0.2: - resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} - - upper-case@2.0.2: - resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} - uppercamelcase@1.1.0: resolution: {integrity: sha512-C7YEMvhgrvTEKEEVqA7LXNID/1TvvIwYZqNIKLquS6y/MGSkRQAav9LnTTILlC1RqUM8eTVBOe1U/fnB652PRA==} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -18095,9 +17347,6 @@ packages: resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==} engines: {node: ^20.17.0 || >=22.9.0} - varint@6.0.0: - resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} - vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -18195,9 +17444,6 @@ packages: vt-pbf@3.1.3: resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==} - w3c-keyname@2.2.8: - resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} - w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -18313,9 +17559,6 @@ packages: resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} engines: {node: '>=20'} - when-exit@2.1.5: - resolution: {integrity: sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -18328,9 +17571,6 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - which-typed-array@1.1.22: resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} engines: {node: '>= 0.4'} @@ -18352,10 +17592,6 @@ packages: wildcard@2.0.1: resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} - winston-transport@4.9.0: - resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} - engines: {node: '>= 12.0.0'} - winston@3.17.0: resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} engines: {node: '>= 12.0.0'} @@ -18379,28 +17615,13 @@ packages: resolution: {integrity: sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==} engines: {node: '>=4'} - wrap-ansi@5.1.0: - resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} - engines: {node: '>=6'} - - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - write-file-atomic@3.0.3: - resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - write-file-atomic@5.0.1: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -18433,14 +17654,6 @@ packages: utf-8-validate: optional: true - wsl-utils@0.1.0: - resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} - engines: {node: '>=18'} - - xdg-basedir@5.1.0: - resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} - engines: {node: '>=12'} - xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -18449,10 +17662,6 @@ packages: resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} engines: {node: '>=4.0.0'} - xmlbuilder@11.0.1: - resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} - engines: {node: '>=4.0'} - xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} @@ -18466,9 +17675,6 @@ packages: peerDependencies: yjs: ^13.0.0 - y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -18485,24 +17691,10 @@ packages: engines: {node: '>= 14.6'} hasBin: true - yargs-parser@15.0.3: - resolution: {integrity: sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==} - - yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yargs-parser@22.0.0: - resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - - yargs@14.2.3: - resolution: {integrity: sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==} - yargs@15.4.1: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} @@ -18530,10 +17722,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yocto-queue@1.2.2: - resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} - engines: {node: '>=12.20'} - zimmerframe@1.1.4: resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} @@ -18570,14 +17758,7 @@ snapshots: '@acemir/cssom@0.9.31': {} - '@actions/core@3.0.0': - dependencies: - '@actions/exec': 3.0.0 - '@actions/http-client': 4.0.1 - - '@actions/exec@3.0.0': - dependencies: - '@actions/io': 3.0.2 + '@actions/core@3.0.0': {} '@actions/github@9.0.0': dependencies: @@ -18589,19 +17770,7 @@ snapshots: '@octokit/request-error': 7.1.0 undici: 6.26.0 - '@actions/http-client@3.0.2': - dependencies: - tunnel: 0.0.6 - undici: 6.26.0 - - '@actions/http-client@4.0.1': - dependencies: - tunnel: 0.0.6 - undici: 6.26.0 - - '@actions/io@3.0.2': {} - - '@adobe/css-tools@4.5.0': {} + '@actions/http-client@3.0.2': {} '@altano/repository-tools@2.0.3': {} @@ -18833,19 +18002,11 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@automattic/explat-client-react-helpers@0.1.1': - dependencies: - '@automattic/explat-client': 0.1.0 - react: 18.3.1 - tslib: 2.8.1 + '@automattic/explat-client-react-helpers@0.1.1': {} - '@automattic/explat-client@0.1.0': - dependencies: - tslib: 2.8.1 + '@automattic/explat-client@0.1.0': {} - '@automattic/format-currency@1.0.1': - dependencies: - tslib: 2.8.1 + '@automattic/format-currency@1.0.1': {} '@automattic/i18n-utils@1.2.3': dependencies: @@ -18925,15 +18086,9 @@ snapshots: cookie: 0.7.2 store: 2.0.12 - '@automattic/popup-monitor@1.0.2': - dependencies: - events: 3.3.0 - lodash: 4.18.1 + '@automattic/popup-monitor@1.0.2': {} - '@automattic/request-external-access@1.0.1': - dependencies: - '@automattic/popup-monitor': 1.0.2 - '@babel/runtime': 7.29.2 + '@automattic/request-external-access@1.0.1': {} '@automattic/shopping-cart@2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: @@ -18977,11 +18132,7 @@ snapshots: rtlcss: 3.5.0 webpack: 5.105.2(webpack-cli@6.0.1) - '@babel/code-frame@7.29.7': - dependencies: - '@babel/helper-validator-identifier': 7.29.7 - js-tokens: 4.0.0 - picocolors: 1.1.1 + '@babel/code-frame@7.29.7': {} '@babel/compat-data@7.29.0': {} @@ -19015,25 +18166,13 @@ snapshots: eslint-visitor-keys: 2.1.0 semver: 6.3.1 - '@babel/generator@7.29.7': - dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 + '@babel/generator@7.29.7': {} '@babel/helper-annotate-as-pure@7.29.7': dependencies: '@babel/types': 7.29.7 - '@babel/helper-compilation-targets@7.28.6': - dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.2 - lru-cache: 5.1.1 - semver: 6.3.1 + '@babel/helper-compilation-targets@7.28.6': {} '@babel/helper-compilation-targets@7.29.7': dependencies: @@ -19130,8 +18269,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-validator-identifier@7.29.7': {} '@babel/helper-validator-option@7.29.7': {} @@ -19144,14 +18281,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helpers@7.29.7': - dependencies: - '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + '@babel/helpers@7.29.7': {} - '@babel/parser@7.29.7': - dependencies: - '@babel/types': 7.29.7 + '@babel/parser@7.29.7': {} '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7(@babel/core@7.29.0)': dependencies: @@ -19792,11 +18924,7 @@ snapshots: '@babel/runtime@7.29.2': {} - '@babel/template@7.29.7': - dependencies: - '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/template@7.29.7': {} '@babel/traverse@7.29.7': dependencies: @@ -19810,10 +18938,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.29.7': - dependencies: - '@babel/helper-string-parser': 7.29.7 - '@babel/helper-validator-identifier': 7.29.7 + '@babel/types@7.29.7': {} '@base-ui/react@1.5.0(@date-fns/tz@1.4.1)(@types/react@18.3.28)(date-fns@4.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: @@ -19915,8 +19040,6 @@ snapshots: '@blazediff/core@1.9.1': {} - '@bufbuild/protobuf@2.12.0': {} - '@cacheable/memory@2.0.9': dependencies: '@cacheable/utils': 2.4.1 @@ -19937,249 +19060,30 @@ snapshots: semver: 7.7.3 webpack: 5.105.2(webpack-cli@6.0.1) - '@codemirror/autocomplete@6.18.6': - dependencies: - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - - '@codemirror/commands@6.8.1': - dependencies: - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - - '@codemirror/lang-angular@0.1.4': - dependencies: - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-javascript': 6.2.5 - '@codemirror/language': 6.11.2 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@codemirror/lang-cpp@6.0.3': - dependencies: - '@codemirror/language': 6.11.2 - '@lezer/cpp': 1.1.6 - - '@codemirror/lang-css@6.3.1': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.3.0 - '@lezer/css': 1.3.3 - - '@codemirror/lang-go@6.0.1': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.3.0 - '@lezer/go': 1.0.1 - - '@codemirror/lang-html@6.4.9': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/lang-css': 6.3.1 - '@codemirror/lang-javascript': 6.2.5 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - '@lezer/css': 1.3.3 - '@lezer/html': 1.3.13 - - '@codemirror/lang-java@6.0.2': - dependencies: - '@codemirror/language': 6.11.2 - '@lezer/java': 1.1.3 - - '@codemirror/lang-javascript@6.2.5': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.2 - '@codemirror/lint': 6.8.5 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - '@lezer/javascript': 1.5.4 - - '@codemirror/lang-json@6.0.2': - dependencies: - '@codemirror/language': 6.11.2 - '@lezer/json': 1.0.3 - - '@codemirror/lang-less@6.0.2': - dependencies: - '@codemirror/lang-css': 6.3.1 - '@codemirror/language': 6.11.2 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@codemirror/lang-liquid@6.3.2': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/lang-html': 6.4.9 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@codemirror/lang-markdown@6.5.0': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/lang-html': 6.4.9 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - '@lezer/markdown': 1.6.4 - - '@codemirror/lang-php@6.0.2': - dependencies: - '@codemirror/lang-html': 6.4.9 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.3.0 - '@lezer/php': 1.0.5 - - '@codemirror/lang-python@6.2.1': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.3.0 - '@lezer/python': 1.1.19 - - '@codemirror/lang-rust@6.0.2': - dependencies: - '@codemirror/language': 6.11.2 - '@lezer/rust': 1.0.2 - - '@codemirror/lang-sass@6.0.2': - dependencies: - '@codemirror/lang-css': 6.3.1 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.3.0 - '@lezer/sass': 1.1.0 - - '@codemirror/lang-sql@6.10.0': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@codemirror/lang-vue@0.1.3': - dependencies: - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-javascript': 6.2.5 - '@codemirror/language': 6.11.2 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 + '@codemirror/autocomplete@6.18.6': {} - '@codemirror/lang-wast@6.0.2': - dependencies: - '@codemirror/language': 6.11.2 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 + '@codemirror/commands@6.8.1': {} - '@codemirror/lang-xml@6.1.0': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - '@lezer/xml': 1.0.6 + '@codemirror/lang-css@6.3.1': {} - '@codemirror/lang-yaml@6.1.3': - dependencies: - '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.2 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - '@lezer/yaml': 1.0.4 + '@codemirror/lang-html@6.4.9': {} - '@codemirror/language-data@6.5.1': - dependencies: - '@codemirror/lang-angular': 0.1.4 - '@codemirror/lang-cpp': 6.0.3 - '@codemirror/lang-css': 6.3.1 - '@codemirror/lang-go': 6.0.1 - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-java': 6.0.2 - '@codemirror/lang-javascript': 6.2.5 - '@codemirror/lang-json': 6.0.2 - '@codemirror/lang-less': 6.0.2 - '@codemirror/lang-liquid': 6.3.2 - '@codemirror/lang-markdown': 6.5.0 - '@codemirror/lang-php': 6.0.2 - '@codemirror/lang-python': 6.2.1 - '@codemirror/lang-rust': 6.0.2 - '@codemirror/lang-sass': 6.0.2 - '@codemirror/lang-sql': 6.10.0 - '@codemirror/lang-vue': 0.1.3 - '@codemirror/lang-wast': 6.0.2 - '@codemirror/lang-xml': 6.1.0 - '@codemirror/lang-yaml': 6.1.3 - '@codemirror/language': 6.11.2 - '@codemirror/legacy-modes': 6.5.3 + '@codemirror/lang-json@6.0.2': {} - '@codemirror/language@6.11.2': - dependencies: - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - style-mod: 4.1.3 + '@codemirror/language-data@6.5.1': {} - '@codemirror/legacy-modes@6.5.3': - dependencies: - '@codemirror/language': 6.11.2 + '@codemirror/language@6.11.2': {} - '@codemirror/lint@6.8.5': - dependencies: - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - crelt: 1.0.6 + '@codemirror/lint@6.8.5': {} - '@codemirror/search@6.5.11': - dependencies: - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.0 - crelt: 1.0.6 + '@codemirror/search@6.5.11': {} - '@codemirror/state@6.5.2': - dependencies: - '@marijn/find-cluster-break': 1.0.2 + '@codemirror/state@6.5.2': {} - '@codemirror/view@6.38.0': - dependencies: - '@codemirror/state': 6.5.2 - crelt: 1.0.6 - style-mod: 4.1.3 - w3c-keyname: 2.2.8 + '@codemirror/view@6.38.0': {} '@colordx/core@5.4.3': {} - '@colors/colors@1.6.0': {} - '@csstools/color-helpers@6.0.2': {} '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': @@ -20221,18 +19125,37 @@ snapshots: dependencies: postcss-selector-parser: 7.1.1 - '@dabh/diagnostics@2.0.8': - dependencies: - '@so-ric/colorspace': 1.1.6 - enabled: 2.0.0 - kuler: 2.0.0 - '@date-fns/tz@1.4.1': {} '@date-fns/utc@2.1.1': {} '@discoveryjs/json-ext@0.6.3': {} + '@dnd-kit/accessibility@3.1.1(react@18.3.1)': + dependencies: + react: 18.3.1 + tslib: 2.8.1 + + '@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@dnd-kit/accessibility': 3.1.1(react@18.3.1) + '@dnd-kit/utilities': 3.2.2(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + tslib: 2.8.1 + + '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + dependencies: + '@dnd-kit/core': 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@dnd-kit/utilities': 3.2.2(react@18.3.1) + react: 18.3.1 + tslib: 2.8.1 + + '@dnd-kit/utilities@3.2.2(react@18.3.1)': + dependencies: + react: 18.3.1 + tslib: 2.8.1 + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 @@ -20270,13 +19193,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@emotion/cache@11.14.0': - dependencies: - '@emotion/memoize': 0.9.0 - '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - stylis: 4.2.0 + '@emotion/cache@11.14.0': {} '@emotion/css@11.13.5': dependencies: @@ -20327,13 +19244,7 @@ snapshots: - supports-color optional: true - '@emotion/serialize@1.3.3': - dependencies: - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/unitless': 0.10.0 - '@emotion/utils': 1.4.2 - csstype: 3.2.3 + '@emotion/serialize@1.3.3': {} '@emotion/sheet@1.4.0': {} @@ -20366,8 +19277,6 @@ snapshots: - supports-color optional: true - '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@18.3.1)': dependencies: react: 18.3.1 @@ -20398,9 +19307,6 @@ snapshots: '@esbuild/android-x64@0.27.4': optional: true - '@esbuild/darwin-arm64@0.27.4': - optional: true - '@esbuild/darwin-x64@0.27.4': optional: true @@ -20503,12 +19409,7 @@ snapshots: optionalDependencies: eslint: 10.4.1 - '@eslint/json@2.0.0': - dependencies: - '@eslint/core': 1.2.1 - '@eslint/plugin-kit': 0.7.2 - '@humanwhocodes/momoa': 3.3.10 - natural-compare: 1.4.0 + '@eslint/json@2.0.0': {} '@eslint/object-schema@3.0.5': {} @@ -20590,23 +19491,13 @@ snapshots: '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/momoa@3.3.10': {} - '@humanwhocodes/retry@0.4.3': {} - '@img/sharp-darwin-arm64@0.33.5': - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.4 - optional: true - '@img/sharp-darwin-x64@0.33.5': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.0.4 optional: true - '@img/sharp-libvips-darwin-arm64@1.0.4': - optional: true - '@img/sharp-libvips-darwin-x64@1.0.4': optional: true @@ -20669,13 +19560,7 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.2 - resolve-from: 5.0.0 + '@istanbuljs/load-nyc-config@1.1.0': {} '@istanbuljs/schema@0.1.6': {} @@ -20858,15 +19743,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@jest/types@30.4.1': - dependencies: - '@jest/pattern': 30.4.0 - '@jest/schemas': 30.4.1 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 24.13.1 - '@types/yargs': 17.0.35 - chalk: 4.1.2 + '@jest/types@30.4.1': {} '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@5.9.3)(vite@8.0.5(sass-embedded@1.97.3))': dependencies: @@ -20881,10 +19758,7 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/remapping@2.3.5': {} '@jridgewell/resolve-uri@3.1.2': {} @@ -21056,103 +19930,11 @@ snapshots: '@lezer/common@1.3.0': {} - '@lezer/common@1.5.2': {} + '@lezer/generator@1.8.0': {} - '@lezer/cpp@1.1.6': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 + '@lezer/highlight@1.2.3': {} - '@lezer/css@1.3.3': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/generator@1.8.0': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/lr': 1.4.3 - - '@lezer/go@1.0.1': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/highlight@1.2.3': - dependencies: - '@lezer/common': 1.3.0 - - '@lezer/html@1.3.13': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/java@1.1.3': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/javascript@1.5.4': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/json@1.0.3': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/lr@1.4.3': - dependencies: - '@lezer/common': 1.3.0 - - '@lezer/markdown@1.6.4': - dependencies: - '@lezer/common': 1.5.2 - '@lezer/highlight': 1.2.3 - - '@lezer/php@1.0.5': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/python@1.1.19': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/rust@1.0.2': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/sass@1.1.0': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/xml@1.0.6': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 - - '@lezer/yaml@1.0.4': - dependencies: - '@lezer/common': 1.3.0 - '@lezer/highlight': 1.2.3 - '@lezer/lr': 1.4.3 + '@lezer/lr@1.4.3': {} '@linear/sdk@75.0.0(graphql@16.12.0)': dependencies: @@ -21185,8 +19967,6 @@ snapshots: '@mapbox/whoots-js@3.1.0': {} - '@marijn/find-cluster-break@1.0.2': {} - '@mdn/browser-compat-data@7.3.17': {} '@mdx-js/react@3.1.1(@types/react@18.3.28)(react@18.3.1)': @@ -21224,26 +20004,7 @@ snapshots: '@octokit/auth-token@6.0.0': {} - '@octokit/core@7.0.6': - dependencies: - '@octokit/auth-token': 6.0.0 - '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.10 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - before-after-hook: 4.0.0 - universal-user-agent: 7.0.3 - - '@octokit/endpoint@11.0.3': - dependencies: - '@octokit/types': 16.0.0 - universal-user-agent: 7.0.3 - - '@octokit/graphql@9.0.3': - dependencies: - '@octokit/request': 10.0.10 - '@octokit/types': 16.0.0 - universal-user-agent: 7.0.3 + '@octokit/core@7.0.6': {} '@octokit/openapi-types@27.0.0': {} @@ -21261,18 +20022,9 @@ snapshots: '@octokit/core': 7.0.6 '@octokit/types': 16.0.0 - '@octokit/request-error@7.1.0': - dependencies: - '@octokit/types': 16.0.0 + '@octokit/request-error@7.1.0': {} - '@octokit/request@10.0.10': - dependencies: - '@octokit/endpoint': 11.0.3 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - content-type: 2.0.0 - json-with-bigint: 3.5.8 - universal-user-agent: 7.0.3 + '@octokit/request@10.0.10': {} '@octokit/rest@22.0.1': dependencies: @@ -21691,9 +20443,7 @@ snapshots: '@pkgr/core@0.3.6': {} - '@playwright/test@1.60.0': - dependencies: - playwright: 1.60.0 + '@playwright/test@1.60.0': {} '@pmmmwh/react-refresh-webpack-plugin@0.6.2(react-refresh@0.17.0)(webpack-dev-server@5.2.4)(webpack@5.105.2)': dependencies: @@ -22088,30 +20838,6 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@redux-saga/core@1.5.0': - dependencies: - '@babel/runtime': 7.29.2 - '@redux-saga/deferred': 1.3.1 - '@redux-saga/delay-p': 1.3.1 - '@redux-saga/is': 1.2.1 - '@redux-saga/symbols': 1.2.1 - '@redux-saga/types': 1.4.0 - - '@redux-saga/deferred@1.3.1': {} - - '@redux-saga/delay-p@1.3.1': - dependencies: - '@redux-saga/symbols': 1.2.1 - - '@redux-saga/is@1.2.1': - dependencies: - '@redux-saga/symbols': 1.2.1 - '@redux-saga/types': 1.4.0 - - '@redux-saga/symbols@1.2.1': {} - - '@redux-saga/types@1.4.0': {} - '@remix-run/router@1.23.3': {} '@rolldown/binding-android-arm64@1.0.0-rc.12': @@ -22325,33 +21051,7 @@ snapshots: transitivePeerDependencies: - zenObservable - '@sentry-internal/browser-utils@10.22.0': - dependencies: - '@sentry/core': 10.22.0 - - '@sentry-internal/feedback@10.22.0': - dependencies: - '@sentry/core': 10.22.0 - - '@sentry-internal/replay-canvas@10.22.0': - dependencies: - '@sentry-internal/replay': 10.22.0 - '@sentry/core': 10.22.0 - - '@sentry-internal/replay@10.22.0': - dependencies: - '@sentry-internal/browser-utils': 10.22.0 - '@sentry/core': 10.22.0 - - '@sentry/browser@10.22.0': - dependencies: - '@sentry-internal/browser-utils': 10.22.0 - '@sentry-internal/feedback': 10.22.0 - '@sentry-internal/replay': 10.22.0 - '@sentry-internal/replay-canvas': 10.22.0 - '@sentry/core': 10.22.0 - - '@sentry/core@10.22.0': {} + '@sentry/browser@10.22.0': {} '@sentry/core@9.47.1': {} @@ -22435,9 +21135,7 @@ snapshots: dependencies: size-limit: 12.1.0(@size-limit/file@12.1.0) - '@slack/logger@4.0.1': - dependencies: - '@types/node': 24.13.1 + '@slack/logger@4.0.1': {} '@slack/types@2.21.1': {} @@ -22459,11 +21157,6 @@ snapshots: - debug - supports-color - '@so-ric/colorspace@1.1.6': - dependencies: - color: 5.0.3 - text-hex: 1.0.0 - '@standard-schema/spec@1.1.0': {} '@storybook/addon-a11y@10.3.6(storybook@10.3.6(@testing-library/dom@10.4.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': @@ -22728,16 +21421,7 @@ snapshots: '@tanstack/store@0.9.3': {} - '@testing-library/dom@10.4.1': - dependencies: - '@babel/code-frame': 7.29.7 - '@babel/runtime': 7.29.2 - '@types/aria-query': 5.0.4 - aria-query: 5.3.0 - dom-accessibility-api: 0.5.16 - lz-string: 1.5.0 - picocolors: 1.1.1 - pretty-format: 27.5.1 + '@testing-library/dom@10.4.1': {} '@testing-library/dom@8.20.1': dependencies: @@ -22750,14 +21434,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.9.1': - dependencies: - '@adobe/css-tools': 4.5.0 - aria-query: 5.3.2 - css.escape: 1.5.1 - dom-accessibility-api: 0.6.3 - picocolors: 1.1.1 - redent: 3.0.0 + '@testing-library/jest-dom@6.9.1': {} '@testing-library/preact@3.2.4(preact@10.28.2)': dependencies: @@ -22805,22 +21482,7 @@ snapshots: '@types/aria-query@5.0.4': {} - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 - - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.29.7 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@types/babel__core@7.20.5': {} '@types/babel__traverse@7.28.0': dependencies: @@ -22842,10 +21504,7 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 - '@types/clean-css@4.2.11': - dependencies: - '@types/node': 24.13.1 - source-map: 0.6.1 + '@types/clean-css@4.2.11': {} '@types/connect-history-api-fallback@1.5.4': dependencies: @@ -22860,36 +21519,12 @@ snapshots: '@types/css-tree@2.3.11': {} - '@types/d3-array@3.0.3': {} - - '@types/d3-color@3.1.0': {} - - '@types/d3-delaunay@6.0.1': {} - - '@types/d3-format@3.0.1': {} - - '@types/d3-geo@3.1.0': - dependencies: - '@types/geojson': 7946.0.16 - - '@types/d3-interpolate@3.0.1': - dependencies: - '@types/d3-color': 3.1.0 - '@types/d3-path@1.0.11': {} - '@types/d3-scale@4.0.2': - dependencies: - '@types/d3-time': 3.0.0 - '@types/d3-shape@1.3.12': dependencies: '@types/d3-path': 1.0.11 - '@types/d3-time-format@2.1.0': {} - - '@types/d3-time@3.0.0': {} - '@types/d3-voronoi@1.1.12': {} '@types/debug@4.1.13': @@ -22928,8 +21563,6 @@ snapshots: '@types/qs': 6.15.1 '@types/serve-static': 1.15.10 - '@types/geojson@7946.0.16': {} - '@types/gradient-parser@1.1.0': {} '@types/highlight-words-core@1.2.1': {} @@ -22947,22 +21580,9 @@ snapshots: '@types/istanbul-lib-coverage@2.0.6': {} - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 + '@types/jest@30.0.0': {} - '@types/jest@30.0.0': - dependencies: - expect: 30.4.1 - pretty-format: 30.4.1 - - '@types/jquery@3.5.33': - dependencies: - '@types/sizzle': 2.3.10 + '@types/jquery@3.5.33': {} '@types/jsdom@21.1.7': dependencies: @@ -22974,25 +21594,16 @@ snapshots: '@types/json5@0.0.29': {} - '@types/linkify-it@5.0.0': {} - - '@types/lodash-es@4.17.12': - dependencies: - '@types/lodash': 4.17.20 + '@types/lodash-es@4.17.12': {} '@types/lodash@4.17.20': {} - '@types/markdown-it@14.1.2': - dependencies: - '@types/linkify-it': 5.0.0 - '@types/mdurl': 2.0.0 + '@types/markdown-it@14.1.2': {} '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 - '@types/mdurl@2.0.0': {} - '@types/mdx@2.0.14': {} '@types/mime@1.3.5': {} @@ -23005,9 +21616,7 @@ snapshots: dependencies: '@types/node': 24.13.1 - '@types/node@24.13.1': - dependencies: - undici-types: 7.18.2 + '@types/node@24.13.1': {} '@types/normalize-package-data@2.4.4': {} @@ -23023,8 +21632,6 @@ snapshots: pg-protocol: 1.14.0 pg-types: 2.2.0 - '@types/prop-types@15.7.15': {} - '@types/qs@6.15.1': {} '@types/range-parser@1.2.7': {} @@ -23040,14 +21647,9 @@ snapshots: hoist-non-react-statics: 3.3.2 redux: 4.2.1 - '@types/react-slider@1.3.6': - dependencies: - '@types/react': 18.3.28 + '@types/react-slider@1.3.6': {} - '@types/react@18.3.28': - dependencies: - '@types/prop-types': 15.7.15 - csstype: 3.2.3 + '@types/react@18.3.28': {} '@types/resolve@1.20.2': {} @@ -23084,8 +21686,6 @@ snapshots: '@types/shimmer@1.2.0': {} - '@types/sizzle@2.3.10': {} - '@types/sockjs@0.3.36': dependencies: '@types/node': 24.13.1 @@ -23098,8 +21698,6 @@ snapshots: '@types/tough-cookie@4.0.5': {} - '@types/triple-beam@1.3.5': {} - '@types/trusted-types@2.0.7': {} '@types/turndown@5.0.6': {} @@ -23128,12 +21726,6 @@ snapshots: dependencies: '@types/node': 24.13.1 - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@17.0.35': - dependencies: - '@types/yargs-parser': 21.0.3 - '@types/yauzl@2.10.3': dependencies: '@types/node': 24.13.1 @@ -23281,9 +21873,6 @@ snapshots: '@typescript-eslint/types': 8.60.1 eslint-visitor-keys: 5.0.1 - '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260225.1': - optional: true - '@typescript/native-preview-darwin-x64@7.0.0-dev.20260225.1': optional: true @@ -23304,7 +21893,6 @@ snapshots: '@typescript/native-preview@7.0.0-dev.20260225.1': optionalDependencies: - '@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260225.1 '@typescript/native-preview-darwin-x64': 7.0.0-dev.20260225.1 '@typescript/native-preview-linux-arm': 7.0.0-dev.20260225.1 '@typescript/native-preview-linux-arm64': 7.0.0-dev.20260225.1 @@ -23426,10 +22014,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@visx/curve@3.12.0': - dependencies: - '@types/d3-shape': 1.3.12 - d3-shape: 1.3.7 + '@visx/curve@3.12.0': {} '@visx/drag@3.12.0(react@18.3.1)': dependencies: @@ -23439,10 +22024,7 @@ snapshots: prop-types: 15.8.1 react: 18.3.1 - '@visx/event@3.12.0': - dependencies: - '@types/react': 18.3.28 - '@visx/point': 3.12.0 + '@visx/event@3.12.0': {} '@visx/glyph@3.12.0(react@18.3.1)': dependencies: @@ -23517,9 +22099,7 @@ snapshots: prop-types: 15.8.1 react: 18.3.1 - '@visx/scale@3.12.0': - dependencies: - '@visx/vendor': 3.12.0 + '@visx/scale@3.12.0': {} '@visx/shape@3.12.0(react@18.3.1)': dependencies: @@ -23557,27 +22137,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-use-measure: 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@visx/vendor@3.12.0': - dependencies: - '@types/d3-array': 3.0.3 - '@types/d3-color': 3.1.0 - '@types/d3-delaunay': 6.0.1 - '@types/d3-format': 3.0.1 - '@types/d3-geo': 3.1.0 - '@types/d3-interpolate': 3.0.1 - '@types/d3-scale': 4.0.2 - '@types/d3-time': 3.0.0 - '@types/d3-time-format': 2.1.0 - d3-array: 3.2.1 - d3-color: 3.1.0 - d3-delaunay: 6.0.2 - d3-format: 3.1.0 - d3-geo: 3.1.0 - d3-interpolate: 3.0.1 - d3-scale: 4.0.2 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - internmap: 2.0.3 + '@visx/vendor@3.12.0': {} '@visx/voronoi@3.12.0(react@18.3.1)': dependencies: @@ -23651,13 +22211,7 @@ snapshots: - utf-8-validate - vite - '@vitest/expect@3.2.4': - dependencies: - '@types/chai': 5.2.3 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - tinyrainbow: 2.0.0 + '@vitest/expect@3.2.4': {} '@vitest/expect@4.1.6': dependencies: @@ -23676,10 +22230,6 @@ snapshots: optionalDependencies: vite: 8.0.5(sass-embedded@1.97.3) - '@vitest/pretty-format@3.2.4': - dependencies: - tinyrainbow: 2.0.0 - '@vitest/pretty-format@4.1.6': dependencies: tinyrainbow: 3.1.0 @@ -23696,18 +22246,10 @@ snapshots: magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.2.4': - dependencies: - tinyspy: 4.0.4 + '@vitest/spy@3.2.4': {} '@vitest/spy@4.1.6': {} - '@vitest/utils@3.2.4': - dependencies: - '@vitest/pretty-format': 3.2.4 - loupe: 3.2.1 - tinyrainbow: 2.0.0 - '@vitest/utils@4.1.6': dependencies: '@vitest/pretty-format': 4.1.6 @@ -23814,10 +22356,27 @@ snapshots: webpack: 5.105.2(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack@5.105.2) - '@wordpress/a11y@4.48.0': + '@wordpress/a11y@4.48.0': {} + + '@wordpress/admin-ui@2.1.0(@date-fns/tz@1.4.1)(date-fns@4.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@wordpress/dom-ready': 4.48.0 + '@wordpress/components': 33.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/element': 6.46.0 '@wordpress/i18n': 6.21.0 + '@wordpress/private-apis': 1.48.0 + '@wordpress/route': 0.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/style-runtime': 0.2.0 + '@wordpress/ui': 0.13.0(@date-fns/tz@1.4.1)(date-fns@4.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + clsx: 2.1.1 + react: 18.3.1 + transitivePeerDependencies: + - '@date-fns/tz' + - '@emotion/is-prop-valid' + - '@types/react' + - date-fns + - react-dom + - stylelint + - supports-color '@wordpress/admin-ui@2.1.0(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: @@ -23968,11 +22527,9 @@ snapshots: react: 18.3.1 uuid: 14.0.0 - '@wordpress/api-fetch@7.48.0': - dependencies: - '@wordpress/i18n': 6.21.0 - '@wordpress/private-apis': 1.48.0 - '@wordpress/url': 4.48.0 + '@wordpress/api-fetch@7.46.0': {} + + '@wordpress/api-fetch@7.48.0': {} '@wordpress/asset-loader@1.14.0': {} @@ -24893,6 +23450,30 @@ snapshots: - browserslist - supports-color + '@wordpress/commands@1.46.0(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@wordpress/base-styles': 8.0.0 + '@wordpress/components': 33.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/data': 10.48.0(react@18.3.1) + '@wordpress/element': 6.46.0 + '@wordpress/i18n': 6.21.0 + '@wordpress/icons': 13.1.0(react@18.3.1) + '@wordpress/keyboard-shortcuts': 5.48.0(react@18.3.1) + '@wordpress/preferences': 4.48.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/private-apis': 1.48.0 + '@wordpress/warning': 3.48.0 + clsx: 2.1.1 + cmdk: 1.1.1(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(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) + transitivePeerDependencies: + - '@date-fns/tz' + - '@emotion/is-prop-valid' + - '@types/react' + - '@types/react-dom' + - stylelint + - supports-color + '@wordpress/commands@1.48.0(@date-fns/tz@1.4.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@wordpress/base-styles': 9.1.0 @@ -25200,6 +23781,40 @@ snapshots: react: 18.3.1 use-memo-one: 1.1.3(react@18.3.1) + '@wordpress/core-data@7.46.0(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@wordpress/api-fetch': 7.48.0 + '@wordpress/block-editor': 15.21.0(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/blocks': 15.21.0(react@18.3.1) + '@wordpress/compose': 7.46.0(react@18.3.1) + '@wordpress/data': 10.48.0(react@18.3.1) + '@wordpress/deprecated': 4.48.0 + '@wordpress/element': 6.46.0 + '@wordpress/html-entities': 4.48.0 + '@wordpress/i18n': 6.21.0 + '@wordpress/is-shallow-equal': 5.48.0 + '@wordpress/private-apis': 1.48.0 + '@wordpress/rich-text': 7.48.0(react@18.3.1) + '@wordpress/sync': 1.48.0 + '@wordpress/undo-manager': 1.48.0 + '@wordpress/url': 4.48.0 + '@wordpress/warning': 3.48.0 + change-case: 4.1.2 + equivalent-key-map: 0.2.2 + fast-deep-equal: 3.1.3 + memize: 2.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + uuid: 14.0.0 + transitivePeerDependencies: + - '@date-fns/tz' + - '@emotion/is-prop-valid' + - '@types/react' + - '@types/react-dom' + - date-fns + - stylelint + - supports-color + '@wordpress/core-data@7.48.0(@date-fns/tz@1.4.1)(date-fns@4.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@wordpress/api-fetch': 7.48.0 @@ -25445,6 +24060,24 @@ snapshots: '@wordpress/deprecated': 4.48.0 react: 18.3.1 + '@wordpress/data@10.46.0(react@18.3.1)': + dependencies: + '@wordpress/compose': 7.46.0(react@18.3.1) + '@wordpress/deprecated': 4.48.0 + '@wordpress/element': 6.46.0 + '@wordpress/is-shallow-equal': 5.48.0 + '@wordpress/priority-queue': 3.48.0 + '@wordpress/private-apis': 1.48.0 + '@wordpress/redux-routine': 5.48.0(redux@5.0.1) + deepmerge: 4.3.1 + equivalent-key-map: 0.2.2 + is-plain-object: 5.0.0 + is-promise: 4.0.0 + react: 18.3.1 + redux: 5.0.1 + rememo: 4.0.2 + use-memo-one: 1.1.3(react@18.3.1) + '@wordpress/data@10.48.0(react@18.3.1)': dependencies: '@wordpress/compose': 8.1.0(react@18.3.1) @@ -25769,26 +24402,18 @@ snapshots: - stylelint - supports-color - '@wordpress/date@5.48.0': - dependencies: - '@wordpress/deprecated': 4.48.0 - moment: 2.30.1 - moment-timezone: 0.5.48 + '@wordpress/date@5.48.0': {} '@wordpress/dependency-extraction-webpack-plugin@6.48.0(webpack@5.105.2)': dependencies: json2php: 0.0.7 webpack: 5.105.2(webpack-cli@6.0.1) - '@wordpress/deprecated@4.48.0': - dependencies: - '@wordpress/hooks': 4.48.0 + '@wordpress/deprecated@4.48.0': {} '@wordpress/dom-ready@4.48.0': {} - '@wordpress/dom@4.48.0': - dependencies: - '@wordpress/deprecated': 4.48.0 + '@wordpress/dom@4.48.0': {} '@wordpress/e2e-test-utils-playwright@1.46.0(@playwright/test@1.60.0)(@types/node@24.13.1)': dependencies: @@ -26633,13 +25258,9 @@ snapshots: '@wordpress/html-entities@4.48.0': {} - '@wordpress/i18n@6.21.0': - dependencies: - '@tannin/sprintf': 1.3.3 - '@wordpress/hooks': 4.48.0 - gettext-parser: 1.4.0 - memize: 2.1.1 - tannin: 1.2.0 + '@wordpress/i18n@6.19.0': {} + + '@wordpress/i18n@6.21.0': {} '@wordpress/icons@10.32.0(react@18.3.1)': dependencies: @@ -26824,9 +25445,7 @@ snapshots: '@wordpress/keycodes': 4.48.0 react: 18.3.1 - '@wordpress/keycodes@4.48.0': - dependencies: - '@wordpress/i18n': 6.21.0 + '@wordpress/keycodes@4.48.0': {} '@wordpress/latex-to-mathml@1.16.0': dependencies: @@ -27570,6 +26189,25 @@ snapshots: - stylelint - supports-color + '@wordpress/preferences@4.46.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@wordpress/a11y': 4.48.0 + '@wordpress/base-styles': 8.0.0 + '@wordpress/components': 33.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@wordpress/compose': 7.46.0(react@18.3.1) + '@wordpress/data': 10.48.0(react@18.3.1) + '@wordpress/deprecated': 4.48.0 + '@wordpress/element': 6.46.0 + '@wordpress/i18n': 6.21.0 + '@wordpress/icons': 13.1.0(react@18.3.1) + '@wordpress/private-apis': 1.48.0 + clsx: 2.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - '@emotion/is-prop-valid' + - supports-color + '@wordpress/preferences@4.48.0(@date-fns/tz@1.4.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@wordpress/a11y': 4.48.0 @@ -27616,15 +26254,21 @@ snapshots: dependencies: prettier: wp-prettier@3.0.3 + '@wordpress/primitives@4.46.0(react@18.3.1)': + dependencies: + '@wordpress/element': 6.46.0 + clsx: 2.1.1 + react: 18.3.1 + '@wordpress/primitives@4.48.0(react@18.3.1)': dependencies: '@wordpress/element': 8.0.0 clsx: 2.1.1 react: 18.3.1 - '@wordpress/priority-queue@3.48.0': - dependencies: - requestidlecallback: 0.3.0 + '@wordpress/priority-queue@3.48.0': {} + + '@wordpress/private-apis@1.46.0': {} '@wordpress/private-apis@1.48.0': {} @@ -27907,13 +26551,9 @@ snapshots: - stylelint - supports-color - '@wordpress/shortcode@4.48.0': - dependencies: - memize: 2.1.1 + '@wordpress/shortcode@4.48.0': {} - '@wordpress/style-engine@2.48.0': - dependencies: - change-case: 4.1.2 + '@wordpress/style-engine@2.48.0': {} '@wordpress/style-runtime@0.2.0': {} @@ -28231,9 +26871,7 @@ snapshots: - date-fns - stylelint - '@wordpress/undo-manager@1.48.0': - dependencies: - '@wordpress/is-shallow-equal': 5.48.0 + '@wordpress/undo-manager@1.48.0': {} '@wordpress/upload-media@0.33.0(@date-fns/tz@1.4.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: @@ -28275,9 +26913,14 @@ snapshots: - stylelint - supports-color - '@wordpress/url@4.48.0': + '@wordpress/url@4.48.0': {} + + '@wordpress/viewport@6.46.0(react@18.3.1)': dependencies: - remove-accents: 0.5.0 + '@wordpress/compose': 7.46.0(react@18.3.1) + '@wordpress/data': 10.48.0(react@18.3.1) + '@wordpress/element': 6.46.0 + react: 18.3.1 '@wordpress/viewport@6.48.0(react@18.3.1)': dependencies: @@ -28497,8 +27140,6 @@ snapshots: dependencies: comctx: 1.6.1 - '@xmldom/xmldom@0.9.10': {} - '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} @@ -28530,11 +27171,6 @@ snapshots: agent-base@7.1.4: {} - aggregate-error@3.1.0: - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - ajv-formats@2.1.1(ajv@8.20.0): dependencies: ajv: 8.20.0 @@ -28562,20 +27198,10 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - allure-js-commons@2.15.1: - dependencies: - md5: 2.3.0 - properties: 1.2.1 - strip-ansi: 5.2.0 - - allure-playwright@2.15.1: - dependencies: - allure-js-commons: 2.15.1 + allure-playwright@2.15.1: {} anser@2.3.5: {} - ansi-colors@4.1.3: {} - ansi-escapes@3.2.0: {} ansi-escapes@4.3.2: @@ -28588,8 +27214,6 @@ snapshots: ansi-regex@3.0.1: {} - ansi-regex@4.1.1: {} - ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -28606,8 +27230,6 @@ snapshots: ansi-styles@5.2.0: {} - ansi-styles@6.2.3: {} - any-observable@0.3.0(rxjs@6.6.7): optionalDependencies: rxjs: 6.6.7 @@ -28619,20 +27241,8 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.2 - append-transform@2.0.0: - dependencies: - default-require-extensions: 3.0.1 - - archy@1.0.0: {} - are-docs-informative@0.0.2: {} - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - - argparse@2.0.1: {} - aria-hidden@1.2.6: dependencies: tslib: 2.8.1 @@ -28641,10 +27251,6 @@ snapshots: dependencies: deep-equal: 2.2.3 - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 - aria-query@5.3.1: {} aria-query@5.3.2: {} @@ -28732,23 +27338,10 @@ snapshots: dependencies: tslib: 2.8.1 - ast-types@0.16.1: - dependencies: - tslib: 2.8.1 - astral-regex@2.0.0: {} async-function@1.0.0: {} - async@3.2.6: {} - - asynckit@0.4.0: {} - - atomically@2.1.1: - dependencies: - stubborn-fs: 2.0.0 - when-exit: 2.1.5 - autoprefixer@10.4.20(postcss@8.5.14): dependencies: browserslist: 4.28.2 @@ -28920,8 +27513,6 @@ snapshots: balanced-match@1.0.2: {} - balanced-match@4.0.4: {} - bare-events@2.9.1: {} bare-fs@4.7.2: @@ -28960,8 +27551,6 @@ snapshots: batch@0.6.1: {} - before-after-hook@4.0.0: {} - bidi-js@1.0.3: dependencies: require-from-string: 2.0.2 @@ -28990,11 +27579,7 @@ snapshots: fast-deep-equal: 3.1.3 multicast-dns: 7.2.5 - boolbase@1.0.0: {} - - bounding-client-rect@1.0.5: - dependencies: - get-document: 1.0.0 + bounding-client-rect@1.0.5: {} brace-expansion@1.1.15: dependencies: @@ -29005,10 +27590,6 @@ snapshots: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.6: - dependencies: - balanced-match: 4.0.4 - braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -29036,10 +27617,6 @@ snapshots: builtin-status-codes@2.0.0: {} - bundle-name@4.1.0: - dependencies: - run-applescript: 7.1.0 - bundle-require@5.1.0(esbuild@0.27.4): dependencies: esbuild: 0.27.4 @@ -29075,12 +27652,7 @@ snapshots: keyv: 5.6.0 qified: 0.10.1 - caching-transform@4.0.0: - dependencies: - hasha: 5.2.2 - make-dir: 3.1.0 - package-hash: 4.0.0 - write-file-atomic: 3.0.3 + caching-transform@4.0.0: {} call-bind-apply-helpers@1.0.2: dependencies: @@ -29101,15 +27673,8 @@ snapshots: callsites@3.1.0: {} - camel-case@4.1.2: - dependencies: - pascal-case: 3.1.2 - tslib: 2.8.1 - camelcase@1.2.1: {} - camelcase@5.3.1: {} - camelcase@6.3.0: {} camelize@1.0.1: {} @@ -29125,22 +27690,8 @@ snapshots: canvas-confetti@1.9.4: {} - capital-case@1.0.4: - dependencies: - no-case: 3.0.4 - tslib: 2.8.1 - upper-case-first: 2.0.2 - ccount@2.0.1: {} - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.3 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 - chai@6.2.2: {} chalk@1.1.3: @@ -29157,27 +27708,11 @@ snapshots: escape-string-regexp: 1.0.5 supports-color: 5.5.0 - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 + chalk@4.1.2: {} chalk@5.6.2: {} - change-case@4.1.2: - dependencies: - camel-case: 4.1.2 - capital-case: 1.0.4 - constant-case: 3.0.4 - dot-case: 3.0.4 - header-case: 2.0.4 - no-case: 3.0.4 - param-case: 3.0.4 - pascal-case: 3.1.2 - path-case: 3.0.4 - sentence-case: 3.0.4 - snake-case: 3.0.4 - tslib: 2.8.1 + change-case@4.1.2: {} change-case@5.4.4: {} @@ -29185,28 +27720,6 @@ snapshots: character-entities@2.0.2: {} - charenc@0.0.2: {} - - check-error@2.1.3: {} - - cheerio-select@1.6.0: - dependencies: - css-select: 4.3.0 - css-what: 6.2.2 - domelementtype: 2.3.0 - domhandler: 4.3.1 - domutils: 2.8.0 - - cheerio@1.0.0-rc.10: - dependencies: - cheerio-select: 1.6.0 - dom-serializer: 1.4.1 - domhandler: 4.3.1 - htmlparser2: 6.1.0 - parse5: 6.0.1 - parse5-htmlparser2-tree-adapter: 6.0.1 - tslib: 2.8.1 - chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -29219,9 +27732,7 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chokidar@4.0.3: - dependencies: - readdirp: 4.1.2 + chokidar@4.0.3: {} chrome-launcher@1.2.1: dependencies: @@ -29248,11 +27759,7 @@ snapshots: classnames@2.5.1: {} - clean-css@5.3.3: - dependencies: - source-map: 0.6.1 - - clean-stack@2.2.0: {} + clean-css@5.3.3: {} cli-cursor@2.1.0: dependencies: @@ -29265,23 +27772,7 @@ snapshots: client-zip@2.5.0: {} - clipboard@2.0.11: - dependencies: - good-listener: 1.2.2 - select: 1.1.2 - tiny-emitter: 2.1.0 - - cliui@5.0.0: - dependencies: - string-width: 3.1.0 - strip-ansi: 5.2.0 - wrap-ansi: 5.1.0 - - cliui@6.0.0: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 + clipboard@2.0.11: {} cliui@8.0.1: dependencies: @@ -29289,12 +27780,6 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - cliui@9.0.1: - dependencies: - string-width: 7.2.0 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - clone-deep@4.0.1: dependencies: is-plain-object: 2.0.4 @@ -29353,56 +27838,18 @@ snapshots: dependencies: color-name: 1.1.4 - color-convert@3.1.3: - dependencies: - color-name: 2.1.0 - color-name@1.1.3: {} color-name@1.1.4: {} - color-name@2.1.0: {} - - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.4 - - color-string@2.1.4: - dependencies: - color-name: 2.1.0 - - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - - color@5.0.3: - dependencies: - color-convert: 3.1.3 - color-string: 2.1.4 - colord@2.9.3: {} colorette@2.0.20: {} - colorjs.io@0.5.2: {} - colorjs.io@0.6.1: {} - combine-errors@3.0.3: - dependencies: - custom-error-instance: 2.1.1 - lodash.uniqby: 4.5.0 - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - comctx@1.6.1: {} - commander@11.1.0: {} - commander@12.1.0: {} commander@13.0.0: {} @@ -29443,46 +27890,24 @@ snapshots: dependencies: source-map: 0.6.1 - concurrently@10.0.3: - dependencies: - chalk: 5.6.2 - rxjs: 7.8.2 - shell-quote: 1.8.4 - supports-color: 10.2.2 - tree-kill: 1.2.2 - yargs: 18.0.0 + concurrently@10.0.3: {} confbox@0.1.8: {} - config@4.4.1: - dependencies: - json5: 2.2.3 + config@4.4.1: {} - configstore@7.0.0: - dependencies: - atomically: 2.1.1 - dot-prop: 9.0.0 - graceful-fs: 4.2.11 - xdg-basedir: 5.1.0 + configstore@7.0.0: {} connect-history-api-fallback@2.0.0: {} consola@3.4.2: {} - constant-case@3.0.4: - dependencies: - no-case: 3.0.4 - tslib: 2.8.1 - upper-case: 2.0.2 - content-disposition@0.5.4: dependencies: safe-buffer: 5.2.1 content-type@1.0.5: {} - content-type@2.0.0: {} - convert-source-map@1.9.0: {} convert-source-map@2.0.0: {} @@ -29551,16 +27976,12 @@ snapshots: crc32@0.2.2: {} - crelt@1.0.6: {} - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - crypt@0.0.2: {} - crypto-js@4.2.0: {} csp_evaluator@1.1.5: {} @@ -29594,41 +28015,13 @@ snapshots: serialize-javascript: 7.0.5 webpack: 5.105.2(webpack-cli@6.0.1) - css-select@4.3.0: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 4.3.1 - domutils: 2.8.0 - nth-check: 2.1.1 - - css-select@5.2.2: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-tree@2.2.1: - dependencies: - mdn-data: 2.0.28 - source-map-js: 1.2.0 - - css-tree@2.3.1: - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.2.0 + css-tree@2.3.1: {} css-tree@3.2.1: dependencies: mdn-data: 2.27.1 source-map-js: 1.2.1 - css-what@6.2.2: {} - - css.escape@1.5.1: {} - csscolorparser@1.0.3: {} cssesc@3.0.0: {} @@ -29677,10 +28070,6 @@ snapshots: lilconfig: 3.1.3 postcss: 8.5.14 - csso@5.0.5: - dependencies: - css-tree: 2.2.1 - cssstyle@5.3.7: dependencies: '@asamuzakjp/css-color': 4.1.2 @@ -29690,44 +28079,12 @@ snapshots: csstype@3.2.3: {} - cubic2quad@1.2.1: {} - - custom-error-instance@2.1.1: {} - - d3-array@3.2.1: - dependencies: - internmap: 2.0.3 - - d3-color@3.1.0: {} - - d3-delaunay@6.0.2: - dependencies: - delaunator: 5.1.0 - - d3-format@3.1.0: {} - - d3-geo@3.1.0: - dependencies: - d3-array: 3.2.1 - d3-interpolate-path@2.2.1: {} - d3-interpolate@3.0.1: - dependencies: - d3-color: 3.1.0 - d3-path@1.0.9: {} d3-path@2.0.0: {} - d3-scale@4.0.2: - dependencies: - d3-array: 3.2.1 - d3-format: 3.1.0 - d3-interpolate: 3.0.1 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - d3-shape@1.3.7: dependencies: d3-path: 1.0.9 @@ -29736,14 +28093,6 @@ snapshots: dependencies: d3-path: 2.0.0 - d3-time-format@4.1.0: - dependencies: - d3-time: 3.1.0 - - d3-time@3.1.0: - dependencies: - d3-array: 3.2.1 - d3-voronoi@1.1.4: {} damerau-levenshtein@1.0.8: {} @@ -29777,10 +28126,6 @@ snapshots: date-fns@1.30.1: {} - date-fns@2.30.0: - dependencies: - '@babel/runtime': 7.29.2 - date-fns@4.1.0: {} debounce@1.2.1: {} @@ -29815,8 +28160,6 @@ snapshots: dedent@1.7.2: {} - deep-eql@5.0.2: {} - deep-equal@2.2.3: dependencies: array-buffer-byte-length: 1.0.2 @@ -29842,17 +28185,6 @@ snapshots: deepmerge@4.3.1: {} - default-browser-id@5.0.1: {} - - default-browser@5.5.0: - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.1 - - default-require-extensions@3.0.1: - dependencies: - strip-bom: 4.0.0 - define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 @@ -29861,8 +28193,6 @@ snapshots: define-lazy-prop@2.0.0: {} - define-lazy-prop@3.0.0: {} - define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -29875,14 +28205,6 @@ snapshots: escodegen: 2.1.0 esprima: 4.0.1 - delaunator@5.1.0: - dependencies: - robust-predicates: 3.0.3 - - delayed-stream@1.0.0: {} - - delegate@3.2.0: {} - depd@1.1.2: {} depd@2.0.0: {} @@ -29931,19 +28253,11 @@ snapshots: dom-accessibility-api@0.5.16: {} - dom-accessibility-api@0.6.3: {} - dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.29.2 csstype: 3.2.3 - dom-serializer@1.4.1: - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - entities: 2.2.0 - dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -29952,25 +28266,11 @@ snapshots: domelementtype@2.3.0: {} - domhandler@4.3.1: - dependencies: - domelementtype: 2.3.0 - domhandler@5.0.3: dependencies: domelementtype: 2.3.0 - domino@2.1.7: {} - - dompurify@3.4.8: - optionalDependencies: - '@types/trusted-types': 2.0.7 - - domutils@2.8.0: - dependencies: - dom-serializer: 1.4.1 - domelementtype: 2.3.0 - domhandler: 4.3.1 + dompurify@3.4.8: {} domutils@3.2.2: dependencies: @@ -29978,14 +28278,7 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 - dot-case@3.0.4: - dependencies: - no-case: 3.0.4 - tslib: 2.8.1 - - dot-prop@9.0.0: - dependencies: - type-fest: 4.41.0 + dot-prop@9.0.0: {} dotenv@16.6.1: {} @@ -30007,24 +28300,14 @@ snapshots: emittery@0.13.1: {} - emoji-regex@10.6.0: {} - - emoji-regex@7.0.3: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} empathic@2.0.1: {} - enabled@2.0.0: {} - encodeurl@2.0.0: {} - encoding@0.1.13: - dependencies: - iconv-lite: 0.6.3 - end-of-stream@1.4.5: dependencies: once: 1.4.0 @@ -30034,12 +28317,7 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 - enquirer@2.4.1: - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - - entities@2.2.0: {} + enquirer@2.4.1: {} entities@4.5.0: {} @@ -30182,8 +28460,6 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - es6-error@4.1.1: {} - esbuild-plugin-babel@0.2.3(@babel/core@7.29.0): dependencies: '@babel/core': 7.29.0 @@ -30201,7 +28477,6 @@ snapshots: '@esbuild/android-arm': 0.27.4 '@esbuild/android-arm64': 0.27.4 '@esbuild/android-x64': 0.27.4 - '@esbuild/darwin-arm64': 0.27.4 '@esbuild/darwin-x64': 0.27.4 '@esbuild/freebsd-arm64': 0.27.4 '@esbuild/freebsd-x64': 0.27.4 @@ -30524,9 +28799,7 @@ snapshots: - supports-color - typescript - eslint-plugin-you-dont-need-lodash-underscore@6.14.0: - dependencies: - kebab-case: 1.0.2 + eslint-plugin-you-dont-need-lodash-underscore@6.14.0: {} eslint-scope@5.1.1: dependencies: @@ -30637,10 +28910,7 @@ snapshots: etag@1.8.1: {} - eval@0.1.8: - dependencies: - '@types/node': 24.13.1 - require-like: 0.1.2 + eval@0.1.8: {} eventemitter3@4.0.7: {} @@ -30666,17 +28936,7 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 - execa@7.0.0: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 4.3.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 + execa@7.0.0: {} exenv@1.2.2: {} @@ -30787,8 +29047,6 @@ snapshots: optionalDependencies: picomatch: 4.0.4 - fecha@4.2.3: {} - figures@1.7.0: dependencies: escape-string-regexp: 1.0.5 @@ -30824,24 +29082,13 @@ snapshots: transitivePeerDependencies: - supports-color - find-cache-dir@3.3.2: - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 + find-cache-dir@3.3.2: {} find-root@1.1.0: {} find-up-simple@1.0.1: {} - find-up@3.0.0: - dependencies: - locate-path: 3.0.0 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 + find-up@4.1.0: {} find-up@5.0.0: dependencies: @@ -30874,11 +29121,7 @@ snapshots: flatted@3.4.2: {} - fn.name@1.1.0: {} - - focus-trap@6.3.0: - dependencies: - tabbable: 5.3.3 + focus-trap@6.3.0: {} follow-redirects@1.16.0: {} @@ -30890,15 +29133,7 @@ snapshots: dependencies: is-callable: 1.2.7 - foreground-child@2.0.0: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 3.0.7 - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 + foreground-child@3.3.1: {} fork-ts-checker-webpack-plugin@9.0.2(typescript@5.9.3)(webpack@5.105.2): dependencies: @@ -30917,13 +29152,7 @@ snapshots: typescript: 5.9.3 webpack: 5.105.2(webpack-cli@6.0.1) - form-data@4.0.5: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.4 - mime-types: 2.1.35 + form-data@4.0.5: {} forwarded-parse@2.1.2: {} @@ -30944,8 +29173,6 @@ snapshots: fresh@0.5.2: {} - fromentries@1.3.2: {} - fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -30954,9 +29181,6 @@ snapshots: fs-monkey@1.1.0: {} - fsevents@2.3.2: - optional: true - fsevents@2.3.3: optional: true @@ -30985,8 +29209,6 @@ snapshots: get-caller-file@2.0.5: {} - get-document@1.0.0: {} - get-east-asian-width@1.6.0: {} get-intrinsic@1.3.0: @@ -31037,11 +29259,6 @@ snapshots: transitivePeerDependencies: - supports-color - gettext-parser@1.4.0: - dependencies: - encoding: 0.1.13 - safe-buffer: 5.2.1 - git-hooks-list@4.2.1: {} gl-matrix@3.4.4: {} @@ -31060,11 +29277,7 @@ snapshots: glob-to-regexp@0.4.1: {} - glob@13.0.6: - dependencies: - minimatch: 10.2.4 - minipass: 7.1.3 - path-scurry: 2.0.2 + glob@13.0.6: {} global-modules@2.0.0: dependencies: @@ -31100,10 +29313,6 @@ snapshots: globrex@0.1.2: {} - good-listener@1.2.2: - dependencies: - delegate: 3.2.0 - gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -31121,8 +29330,6 @@ snapshots: handle-thing@2.0.1: {} - harmony-reflect@1.6.2: {} - has-ansi@2.0.0: dependencies: ansi-regex: 2.1.1 @@ -31154,11 +29361,6 @@ snapshots: inherits: 2.0.4 minimalistic-assert: 1.0.1 - hasha@5.2.2: - dependencies: - is-stream: 2.0.1 - type-fest: 0.8.1 - hashery@1.5.1: dependencies: hookified: 1.15.1 @@ -31169,11 +29371,6 @@ snapshots: he@1.2.0: {} - header-case@2.0.4: - dependencies: - capital-case: 1.0.4 - tslib: 2.8.1 - hermes-estree@0.25.1: {} hermes-parser@0.25.1: @@ -31182,9 +29379,7 @@ snapshots: highlight-words-core@1.2.3: {} - history@5.3.0: - dependencies: - '@babel/runtime': 7.29.2 + history@5.3.0: {} hoist-non-react-statics@3.3.2: dependencies: @@ -31220,8 +29415,6 @@ snapshots: html-entities@2.6.0: {} - html-escaper@2.0.2: {} - html-react-parser@5.2.11(@types/react@18.3.28)(react@18.3.1): dependencies: domhandler: 5.0.3 @@ -31249,13 +29442,6 @@ snapshots: domutils: 3.2.2 entities: 6.0.1 - htmlparser2@6.1.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - domutils: 2.8.0 - entities: 2.2.0 - http-deceiver@1.2.7: {} http-errors@1.8.1: @@ -31341,8 +29527,6 @@ snapshots: human-signals@2.1.0: {} - human-signals@4.3.1: {} - husky@9.1.7: {} hyperdyperid@1.2.0: {} @@ -31368,19 +29552,13 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - icss-replace-symbols@1.1.0: {} icss-utils@5.1.0(postcss@8.5.14): dependencies: postcss: 8.5.14 - identity-obj-proxy@3.0.0: - dependencies: - harmony-reflect: 1.6.2 + identity-obj-proxy@3.0.0: {} ieee754@1.2.1: {} @@ -31392,8 +29570,6 @@ snapshots: image-ssim@0.2.0: {} - immutable@5.1.6: {} - import-cwd@3.0.0: dependencies: import-from: 3.0.0 @@ -31414,10 +29590,7 @@ snapshots: cjs-module-lexer: 1.4.3 module-details-from-path: 1.0.4 - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 + import-local@3.2.0: {} import-meta-resolve@4.2.0: {} @@ -31425,8 +29598,6 @@ snapshots: indent-string@3.2.0: {} - indent-string@4.0.0: {} - index-to-position@1.2.0: {} inherits@2.0.4: {} @@ -31441,8 +29612,6 @@ snapshots: hasown: 2.0.4 side-channel: 1.1.0 - internmap@2.0.3: {} - interpret@3.1.1: {} intl-messageformat@10.7.18: @@ -31471,8 +29640,6 @@ snapshots: is-arrayish@0.2.1: {} - is-arrayish@0.3.4: {} - is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -31494,10 +29661,6 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-buffer@1.1.6: {} - - is-buffer@2.0.5: {} - is-bun-module@2.0.0: dependencies: semver: 7.7.3 @@ -31521,8 +29684,6 @@ snapshots: is-docker@2.2.1: {} - is-docker@3.0.0: {} - is-electron@2.2.2: {} is-extglob@2.1.1: {} @@ -31553,10 +29714,6 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-inside-container@1.0.0: - dependencies: - is-docker: 3.0.0 - is-map@2.0.3: {} is-module@1.0.0: {} @@ -31619,8 +29776,6 @@ snapshots: is-stream@2.0.1: {} - is-stream@3.0.0: {} - is-string@1.1.1: dependencies: call-bound: 1.0.4 @@ -31636,8 +29791,6 @@ snapshots: dependencies: which-typed-array: 1.1.22 - is-typedarray@1.0.0: {} - is-weakmap@2.0.2: {} is-weakref@1.1.1: @@ -31649,16 +29802,10 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 - is-windows@1.0.2: {} - is-wsl@2.2.0: dependencies: is-docker: 2.2.1 - is-wsl@3.1.1: - dependencies: - is-inside-container: 1.0.0 - isarray@1.0.0: {} isarray@2.0.5: {} @@ -31669,13 +29816,9 @@ snapshots: isobject@3.0.1: {} - isomorphic.js@0.2.5: {} - istanbul-lib-coverage@3.2.2: {} - istanbul-lib-hook@3.0.0: - dependencies: - append-transform: 2.0.0 + istanbul-lib-hook@3.0.0: {} istanbul-lib-instrument@6.0.3: dependencies: @@ -31687,20 +29830,9 @@ snapshots: transitivePeerDependencies: - supports-color - istanbul-lib-processinfo@3.0.0: - dependencies: - archy: 1.0.0 - cross-spawn: 7.0.6 - istanbul-lib-coverage: 3.2.2 - p-map: 3.0.0 - rimraf: 6.1.3 - uuid: 8.3.2(patch_hash=87a713b75995ed86c0ecd0cadfd1b9f85092ca16fdff7132ff98b62fc3cf2db0) + istanbul-lib-processinfo@3.0.0: {} - istanbul-lib-report@3.0.1: - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 + istanbul-lib-report@3.0.1: {} istanbul-lib-source-maps@4.0.1: dependencies: @@ -31718,10 +29850,7 @@ snapshots: transitivePeerDependencies: - supports-color - istanbul-reports@3.2.0: - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 + istanbul-reports@3.2.0: {} iterator.prototype@1.1.5: dependencies: @@ -32125,28 +30254,17 @@ snapshots: jpeg-js@0.4.4: {} - jquery-cycle@3.0.3: - dependencies: - jquery: 3.7.1 + jquery-cycle@3.0.3: {} jquery@3.7.1: {} - js-base64@3.7.8: {} - js-library-detector@6.7.0: {} js-sha256@0.11.1: {} js-tokens@4.0.0: {} - js-yaml@3.14.2: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 + js-yaml@4.1.1: {} jsdoc-type-pratt-parser@7.2.0: {} @@ -32192,8 +30310,6 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} - json-with-bigint@3.5.8: {} - json2php@0.0.7: {} json5@1.0.2: @@ -32223,8 +30339,6 @@ snapshots: kdbush@3.0.0: {} - kebab-case@1.0.2: {} - keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -32237,8 +30351,6 @@ snapshots: known-css-properties@0.37.0: {} - kuler@2.0.0: {} - language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -32259,17 +30371,11 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lib0@0.2.99: - dependencies: - isomorphic.js: 0.2.5 + lib0@0.2.99: {} libphonenumber-js@1.13.3: {} - libsodium-wrappers@0.7.10: - dependencies: - libsodium: 0.7.16 - - libsodium@0.7.16: {} + libsodium-wrappers@0.7.10: {} lighthouse-logger@2.0.2: dependencies: @@ -32376,10 +30482,6 @@ snapshots: lines-and-columns@1.2.4: {} - linkify-it@5.0.1: - dependencies: - uc.micro: 2.1.0 - listr-silent-renderer@1.1.1: {} listr-update-renderer@0.5.0(listr@0.14.3): @@ -32401,12 +30503,7 @@ snapshots: date-fns: 1.30.1 figures: 2.0.0 - listr-verbose-renderer@0.6.0: - dependencies: - chalk: 2.4.2 - cli-cursor: 2.1.0 - date-fns: 2.30.0 - figures: 2.0.0 + listr-verbose-renderer@0.6.0: {} listr@0.14.3: dependencies: @@ -32464,15 +30561,6 @@ snapshots: locate-character@3.0.0: {} - locate-path@3.0.0: - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -32483,48 +30571,20 @@ snapshots: lodash-es@4.18.1: {} - lodash._baseiteratee@4.7.0: - dependencies: - lodash._stringtopath: 4.8.0 - - lodash._basetostring@4.12.0: {} - - lodash._baseuniq@4.6.0: - dependencies: - lodash._createset: 4.0.3 - lodash._root: 3.0.1 - - lodash._createset@4.0.3: {} - - lodash._root@3.0.1: {} - - lodash._stringtopath@4.8.0: - dependencies: - lodash._basetostring: 4.12.0 - lodash.camelcase@4.3.0: {} lodash.debounce@4.0.8: {} - lodash.flattendeep@4.4.0: {} - lodash.groupby@4.6.0: {} lodash.memoize@4.1.2: {} lodash.mergewith@4.6.2: {} - lodash.throttle@4.1.1: {} - lodash.truncate@4.4.2: {} lodash.uniq@4.5.0: {} - lodash.uniqby@4.5.0: - dependencies: - lodash._baseiteratee: 4.7.0 - lodash._baseuniq: 4.6.0 - lodash@4.18.1: {} log-symbols@1.0.2: @@ -32537,15 +30597,6 @@ snapshots: cli-cursor: 2.1.0 wrap-ansi: 3.0.1 - logform@2.7.0: - dependencies: - '@colors/colors': 1.6.0 - '@types/triple-beam': 1.3.5 - fecha: 4.2.3 - ms: 2.1.3 - safe-stable-stringify: 2.5.0 - triple-beam: 1.4.1 - longest-streak@3.1.0: {} lookup-closest-locale@6.2.0: {} @@ -32554,12 +30605,6 @@ snapshots: dependencies: js-tokens: 4.0.0 - loupe@3.2.1: {} - - lower-case@2.0.2: - dependencies: - tslib: 2.8.1 - lru-cache@11.5.1: {} lru-cache@5.1.1: @@ -32582,13 +30627,7 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - - make-dir@4.0.0: - dependencies: - semver: 7.7.3 + make-dir@3.1.0: {} makeerror@1.0.12: dependencies: @@ -32621,14 +30660,7 @@ snapshots: markdown-it-footnote@3.0.3: {} - markdown-it@14.1.1: - dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.1 - mdurl: 2.0.0 - punycode.js: 2.3.1 - uc.micro: 2.1.0 + markdown-it@14.1.1: {} markdown-table@3.0.4: {} @@ -32642,12 +30674,6 @@ snapshots: md5-es@1.8.2: {} - md5@2.3.0: - dependencies: - charenc: 0.0.2 - crypt: 0.0.2 - is-buffer: 1.1.6 - mdast-util-find-and-replace@3.0.2: dependencies: '@types/mdast': 4.0.4 @@ -32750,16 +30776,10 @@ snapshots: dependencies: '@types/mdast': 4.0.4 - mdn-data@2.0.28: {} - - mdn-data@2.0.30: {} - mdn-data@2.27.1: {} mdn-data@2.28.1: {} - mdurl@2.0.0: {} - media-typer@0.3.0: {} memfs@3.5.3: @@ -32799,8 +30819,6 @@ snapshots: methods@1.1.2: {} - microbuffer@1.0.0: {} - micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.3.0 @@ -33017,8 +31035,6 @@ snapshots: mimic-fn@2.1.0: {} - mimic-fn@4.0.0: {} - min-indent@1.0.1: {} mini-css-extract-plugin@2.9.4(webpack@5.105.2): @@ -33029,9 +31045,7 @@ snapshots: minimalistic-assert@1.0.1: {} - minimatch@10.2.4: - dependencies: - brace-expansion: 5.0.6 + minimatch@10.2.4: {} minimatch@3.1.5: dependencies: @@ -33043,8 +31057,6 @@ snapshots: minimist@1.2.8: {} - minipass@7.1.3: {} - mitt@2.1.0: {} mitt@3.0.1: {} @@ -33091,8 +31103,6 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.12: {} - nanospinner@1.2.2: dependencies: picocolors: 1.1.1 @@ -33109,11 +31119,6 @@ snapshots: netmask@2.1.1: {} - no-case@3.0.4: - dependencies: - lower-case: 2.0.2 - tslib: 2.8.1 - node-abort-controller@3.1.1: {} node-exports-info@1.6.0: @@ -33125,9 +31130,7 @@ snapshots: node-int64@0.4.0: {} - node-preload@0.2.1: - dependencies: - process-on-spawn: 1.1.0 + node-preload@0.2.1: {} node-releases@2.0.47: {} @@ -33154,17 +31157,7 @@ snapshots: dependencies: path-key: 3.1.1 - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - nspell@2.1.5: - dependencies: - is-buffer: 2.0.5 - - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 + nspell@2.1.5: {} number-is-nan@1.0.1: {} @@ -33263,10 +31256,6 @@ snapshots: dependencies: wrappy: 1.0.2 - one-time@1.0.0: - dependencies: - fn.name: 1.1.0 - onetime@2.0.1: dependencies: mimic-fn: 1.2.0 @@ -33275,16 +31264,7 @@ snapshots: dependencies: mimic-fn: 2.1.0 - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - - open@10.2.0: - dependencies: - default-browser: 5.5.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - wsl-utils: 0.1.0 + open@10.2.0: {} open@8.4.2: dependencies: @@ -33294,8 +31274,6 @@ snapshots: openai@5.3.0: {} - opencollective-postinstall@2.0.3: {} - openurl@1.1.1: {} optionator@0.9.4: @@ -33341,27 +31319,11 @@ snapshots: p-debounce@4.0.0: {} - p-finally@1.0.0: {} - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - p-limit@4.0.0: - dependencies: - yocto-queue: 1.2.2 - - p-locate@3.0.0: - dependencies: - p-limit: 2.3.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 + p-limit@4.0.0: {} p-locate@5.0.0: dependencies: @@ -33373,19 +31335,11 @@ snapshots: p-map@2.1.0: {} - p-map@3.0.0: - dependencies: - aggregate-error: 3.1.0 + p-map@3.0.0: {} - p-queue@6.6.2: - dependencies: - eventemitter3: 4.0.7 - p-timeout: 3.2.0 + p-queue@6.6.2: {} - p-retry@4.6.2: - dependencies: - '@types/retry': 0.12.0 - retry: 0.13.1 + p-retry@4.6.2: {} p-retry@6.2.1: dependencies: @@ -33393,12 +31347,6 @@ snapshots: is-network-error: 1.3.2 retry: 0.13.1 - p-timeout@3.2.0: - dependencies: - p-finally: 1.0.0 - - p-try@2.2.0: {} - pac-proxy-agent@7.2.0: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 @@ -33417,18 +31365,7 @@ snapshots: degenerator: 5.0.1 netmask: 2.1.1 - package-directory@8.2.0: - dependencies: - find-up-simple: 1.0.1 - - package-hash@4.0.0: - dependencies: - graceful-fs: 4.2.11 - hasha: 5.2.2 - lodash.flattendeep: 4.4.0 - release-zalgo: 1.0.0 - - package-json-from-dist@1.0.1: {} + package-directory@8.2.0: {} package-json-validator@1.5.2: dependencies: @@ -33437,11 +31374,6 @@ snapshots: validate-npm-package-license: 3.0.4 validate-npm-package-name: 7.0.2 - param-case@3.0.4: - dependencies: - dot-case: 3.0.4 - tslib: 2.8.1 - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -33469,12 +31401,6 @@ snapshots: parse-statements@1.0.11: {} - parse5-htmlparser2-tree-adapter@6.0.1: - dependencies: - parse5: 6.0.1 - - parse5@6.0.1: {} - parse5@7.3.0: dependencies: entities: 6.0.1 @@ -33487,35 +31413,16 @@ snapshots: parseurl@1.3.3: {} - pascal-case@3.1.2: - dependencies: - no-case: 3.0.4 - tslib: 2.8.1 - path-browserify@1.0.1: {} - path-case@3.0.4: - dependencies: - dot-case: 3.0.4 - tslib: 2.8.1 - - path-exists@3.0.0: {} - path-exists@4.0.0: {} path-key@3.1.1: {} - path-key@4.0.0: {} - path-name@1.0.0: {} path-parse@1.0.7: {} - path-scurry@2.0.2: - dependencies: - lru-cache: 11.5.1 - minipass: 7.1.3 - path-to-regexp@0.1.13: {} path-to-regexp@6.3.0: {} @@ -33524,8 +31431,6 @@ snapshots: pathe@2.0.3: {} - pathval@2.0.1: {} - pbf@3.3.0: dependencies: ieee754: 1.2.1 @@ -33571,10 +31476,6 @@ snapshots: pirates@4.0.7: {} - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -33594,11 +31495,7 @@ snapshots: playwright-ctrf-json-reporter@0.0.26: {} - playwright@1.60.0: - dependencies: - playwright-core: 1.60.0 - optionalDependencies: - fsevents: 2.3.2 + playwright@1.60.0: {} pluralize@8.0.0: {} @@ -33874,11 +31771,7 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.5.14: - dependencies: - nanoid: 3.3.12 - picocolors: 1.1.1 - source-map-js: 1.2.1 + postcss@8.5.14: {} postgres-array@2.0.0: {} @@ -33922,18 +31815,13 @@ snapshots: react-is-18: react-is@18.3.1 react-is-19: react-is@19.2.7 - print-this@2.0.0: - dependencies: - jquery: 3.7.1 - opencollective-postinstall: 2.0.3 + print-this@2.0.0: {} proc-log@6.1.0: {} process-nextick-args@2.0.1: {} - process-on-spawn@1.1.0: - dependencies: - fromentries: 1.3.2 + process-on-spawn@1.1.0: {} process@0.11.10: {} @@ -33941,19 +31829,7 @@ snapshots: promise.series@0.2.0: {} - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - proper-lockfile@4.1.2: - dependencies: - graceful-fs: 4.2.11 - retry: 0.12.0 - signal-exit: 3.0.7 - - properties@1.2.1: {} + prop-types@15.8.1: {} protocol-buffers-schema@3.6.1: {} @@ -33984,8 +31860,6 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 - punycode.js@2.3.1: {} - punycode@2.3.1: {} puppeteer-core@24.43.1: @@ -34029,8 +31903,6 @@ snapshots: qss@3.0.0: {} - querystringify@2.2.0: {} - queue-microtask@1.2.3: {} quickselect@2.0.0: {} @@ -34236,9 +32108,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react@18.3.1: - dependencies: - loose-envify: 1.4.0 + react@18.3.1: {} read-package-up@12.0.0: dependencies: @@ -34274,25 +32144,12 @@ snapshots: dependencies: picomatch: 2.3.2 - readdirp@4.1.2: {} - - recast@0.23.11: - dependencies: - ast-types: 0.16.1 - esprima: 4.0.1 - source-map: 0.6.1 - tiny-invariant: 1.3.3 - tslib: 2.8.1 + recast@0.23.11: {} rechoir@0.8.0: dependencies: resolve: 1.22.12 - redent@3.0.0: - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - reduce-css-calc@1.3.0: dependencies: balanced-match: 0.4.2 @@ -34303,18 +32160,13 @@ snapshots: dependencies: balanced-match: 1.0.2 - redux-saga@1.5.0: - dependencies: - '@babel/runtime': 7.29.2 - '@redux-saga/core': 1.5.0 + redux-saga@1.5.0: {} redux-thunk@2.3.0(redux@4.2.1): dependencies: redux: 4.2.1 - redux@4.2.1: - dependencies: - '@babel/runtime': 7.29.2 + redux@4.2.1: {} redux@5.0.1: {} @@ -34370,10 +32222,6 @@ snapshots: core-js: 3.49.0 exit-hook: 4.0.0 - release-zalgo@1.0.0: - dependencies: - es6-error: 4.1.1 - remark-gfm@4.0.0: dependencies: '@types/mdast': 4.0.4 @@ -34404,8 +32252,6 @@ snapshots: remove-accents@0.5.0: {} - requestidlecallback@0.3.0: {} - require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -34418,10 +32264,6 @@ snapshots: transitivePeerDependencies: - supports-color - require-like@0.1.2: {} - - require-main-filename@2.0.0: {} - requireindex@1.2.0: {} requires-port@1.0.0: {} @@ -34432,10 +32274,6 @@ snapshots: resize-observer-polyfill@1.5.1: {} - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 - resolve-from@4.0.0: {} resolve-from@5.0.0: {} @@ -34469,21 +32307,14 @@ snapshots: onetime: 2.0.1 signal-exit: 3.0.7 - retry@0.12.0: {} - retry@0.13.1: {} reusify@1.1.0: {} - rimraf@6.1.3: - dependencies: - glob: 13.0.6 - package-json-from-dist: 1.0.1 + rimraf@6.1.3: {} robots-parser@3.0.1: {} - robust-predicates@3.0.3: {} - rolldown@1.0.0-rc.12: dependencies: '@oxc-project/types': 0.122.0 @@ -34541,9 +32372,7 @@ snapshots: dependencies: estree-walker: 0.6.1 - rollup@3.30.0: - optionalDependencies: - fsevents: 2.3.3 + rollup@3.30.0: {} rollup@4.61.1: dependencies: @@ -34592,8 +32421,6 @@ snapshots: postcss: 8.5.14 strip-json-comments: 3.1.1 - run-applescript@7.1.0: {} - run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -34606,10 +32433,6 @@ snapshots: dependencies: tslib: 1.14.1 - rxjs@7.8.2: - dependencies: - tslib: 2.8.1 - safe-array-concat@1.1.4: dependencies: call-bind: 1.0.9 @@ -34635,8 +32458,6 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 - safe-stable-stringify@2.5.0: {} - safer-buffer@2.1.2: {} sass-embedded-android-arm64@1.97.3: @@ -34651,9 +32472,6 @@ snapshots: sass-embedded-android-x64@1.97.3: optional: true - sass-embedded-darwin-arm64@1.97.3: - optional: true - sass-embedded-darwin-x64@1.97.3: optional: true @@ -34688,20 +32506,11 @@ snapshots: optional: true sass-embedded@1.97.3: - dependencies: - '@bufbuild/protobuf': 2.12.0 - colorjs.io: 0.5.2 - immutable: 5.1.6 - rxjs: 7.8.2 - supports-color: 8.1.1 - sync-child-process: 1.0.2 - varint: 6.0.0 optionalDependencies: sass-embedded-android-arm: 1.97.3 sass-embedded-android-arm64: 1.97.3 sass-embedded-android-riscv64: 1.97.3 sass-embedded-android-x64: 1.97.3 - sass-embedded-darwin-arm64: 1.97.3 sass-embedded-darwin-x64: 1.97.3 sass-embedded-linux-arm: 1.97.3 sass-embedded-linux-arm64: 1.97.3 @@ -34754,8 +32563,6 @@ snapshots: select-hose@2.0.0: {} - select@1.1.2: {} - selfsigned@5.5.0: dependencies: '@peculiar/x509': 1.14.3 @@ -34785,12 +32592,6 @@ snapshots: transitivePeerDependencies: - supports-color - sentence-case@3.0.4: - dependencies: - no-case: 3.0.4 - tslib: 2.8.1 - upper-case-first: 2.0.2 - serialize-javascript@7.0.5: {} seroval-plugins@1.5.4(seroval@1.5.4): @@ -34820,8 +32621,6 @@ snapshots: transitivePeerDependencies: - supports-color - set-blocking@2.0.0: {} - set-cookie-parser@2.7.2: {} set-function-length@1.2.2: @@ -34853,14 +32652,8 @@ snapshots: kind-of: 6.0.3 sharp@0.33.5: - dependencies: - color: 4.2.3 - detect-libc: 2.1.2 - semver: 7.7.3 optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-x64': 0.33.5 - '@img/sharp-libvips-darwin-arm64': 1.0.4 '@img/sharp-libvips-darwin-x64': 1.0.4 '@img/sharp-libvips-linux-arm': 1.0.5 '@img/sharp-libvips-linux-arm64': 1.0.4 @@ -34890,9 +32683,7 @@ snapshots: shimmer@1.2.1: {} - showdown@1.9.1: - dependencies: - yargs: 14.2.3 + showdown@1.9.1: {} side-channel-list@1.0.1: dependencies: @@ -34930,10 +32721,6 @@ snapshots: simple-html-tokenizer@0.5.11: {} - simple-swizzle@0.2.4: - dependencies: - is-arrayish: 0.3.4 - sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -34966,11 +32753,6 @@ snapshots: smob@1.6.2: {} - snake-case@3.0.4: - dependencies: - dot-case: 3.0.4 - tslib: 2.8.1 - social-logos@3.3.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: prop-types: 15.8.1 @@ -35030,15 +32812,7 @@ snapshots: source-map@0.7.6: {} - spawn-wrap@3.0.0: - dependencies: - cross-spawn: 7.0.6 - foreground-child: 2.0.0 - is-windows: 1.0.2 - make-dir: 3.1.0 - rimraf: 6.1.3 - signal-exit: 3.0.7 - which: 2.0.2 + spawn-wrap@3.0.0: {} spdx-correct@3.2.0: dependencies: @@ -35086,14 +32860,10 @@ snapshots: image-ssim: 0.2.0 jpeg-js: 0.4.4 - sprintf-js@1.0.3: {} - sprintf-js@1.1.3: {} stable-hash-x@0.2.0: {} - stack-trace@0.0.10: {} - stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 @@ -35188,24 +32958,12 @@ snapshots: is-fullwidth-code-point: 2.0.0 strip-ansi: 4.0.0 - string-width@3.1.0: - dependencies: - emoji-regex: 7.0.3 - is-fullwidth-code-point: 2.0.0 - strip-ansi: 5.2.0 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - string-width@8.2.1: dependencies: get-east-asian-width: 1.6.0 @@ -35278,10 +33036,6 @@ snapshots: dependencies: ansi-regex: 3.0.1 - strip-ansi@5.2.0: - dependencies: - ansi-regex: 4.1.1 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -35296,8 +33050,6 @@ snapshots: strip-final-newline@2.0.0: {} - strip-final-newline@3.0.0: {} - strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -35308,16 +33060,8 @@ snapshots: strip@3.0.0: {} - stubborn-fs@2.0.0: - dependencies: - stubborn-utils: 1.0.2 - - stubborn-utils@1.0.2: {} - style-inject@0.3.0: {} - style-mod@4.1.3: {} - style-search@0.1.0: {} style-to-js@1.1.21: @@ -35437,10 +33181,6 @@ snapshots: dependencies: has-flag: 3.0.0 - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - supports-color@8.1.1: dependencies: has-flag: 4.0.0 @@ -35509,14 +33249,7 @@ snapshots: svg-tags@1.0.0: {} - svg2ttf@6.1.0: - dependencies: - '@xmldom/xmldom': 0.9.10 - argparse: 2.0.1 - cubic2quad: 1.2.1 - lodash: 4.18.1 - microbuffer: 1.0.0 - svgpath: 2.6.0 + svg2ttf@6.1.0: {} svgicons2svgfont@15.0.1: dependencies: @@ -35531,21 +33264,9 @@ snapshots: transitivePeerDependencies: - supports-color - svgo@4.0.1: - dependencies: - commander: 11.1.0 - css-select: 5.2.2 - css-tree: 3.2.1 - css-what: 6.2.2 - csso: 5.0.5 - picocolors: 1.1.1 - sax: 1.6.0 - - svgpath@2.6.0: {} + svgo@4.0.1: {} - svgstore@3.0.1: - dependencies: - cheerio: 1.0.0-rc.10 + svgstore@3.0.1: {} swiper@12.1.2: {} @@ -35553,18 +33274,10 @@ snapshots: symbol-tree@3.2.4: {} - sync-child-process@1.0.2: - dependencies: - sync-message-port: 1.2.0 - - sync-message-port@1.2.0: {} - synckit@0.11.13: dependencies: '@pkgr/core': 0.3.6 - tabbable@5.3.3: {} - tabbable@6.4.0: {} table@6.9.0: @@ -35636,11 +33349,7 @@ snapshots: glob: 13.0.6 minimatch: 10.2.4 - test-exclude@8.0.0: - dependencies: - '@istanbuljs/schema': 0.1.6 - glob: 13.0.6 - minimatch: 10.2.4 + test-exclude@8.0.0: {} text-decoder@1.2.7: dependencies: @@ -35648,8 +33357,6 @@ snapshots: transitivePeerDependencies: - react-native-b4a - text-hex@1.0.0: {} - thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -35674,8 +33381,6 @@ snapshots: thunky@1.1.0: {} - tiny-emitter@2.1.0: {} - tiny-invariant@1.3.3: {} tiny-lru@7.0.6: {} @@ -35695,12 +33400,8 @@ snapshots: tinyqueue@2.0.3: {} - tinyrainbow@2.0.0: {} - tinyrainbow@3.1.0: {} - tinyspy@4.0.4: {} - tldts-core@7.4.2: {} tldts-icann@7.4.2: @@ -35744,8 +33445,6 @@ snapshots: tree-kill@1.2.2: {} - triple-beam@1.4.1: {} - trough@2.2.0: {} ts-api-utils@2.5.0(typescript@5.9.3): @@ -35832,21 +33531,9 @@ snapshots: dependencies: tslib: 1.14.1 - tunnel@0.0.6: {} - - turndown@7.1.2: - dependencies: - domino: 2.1.7 + turndown@7.1.2: {} - tus-js-client@4.2.3: - dependencies: - buffer-from: 1.1.2 - combine-errors: 3.0.3 - is-stream: 2.0.1 - js-base64: 3.7.8 - lodash.throttle: 4.1.1 - proper-lockfile: 4.1.2 - url-parse: 1.5.10 + tus-js-client@4.2.3: {} type-check@0.4.0: dependencies: @@ -35856,8 +33543,6 @@ snapshots: type-fest@0.21.3: {} - type-fest@0.8.1: {} - type-fest@4.41.0: {} type-fest@5.7.0: @@ -35904,10 +33589,6 @@ snapshots: typed-query-selector@2.12.2: {} - typedarray-to-buffer@3.1.5: - dependencies: - is-typedarray: 1.0.0 - typescript-eslint@8.60.0(eslint@10.4.1)(typescript@5.9.3): dependencies: '@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1)(typescript@5.9.3))(eslint@10.4.1)(typescript@5.9.3) @@ -35921,8 +33602,6 @@ snapshots: typescript@5.9.3: {} - uc.micro@2.1.0: {} - ufo@1.6.4: {} unbox-primitive@1.1.0: @@ -35932,8 +33611,6 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 - undici-types@7.18.2: {} - undici@6.26.0: {} undici@7.24.0: {} @@ -35982,8 +33659,6 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - universal-user-agent@7.0.3: {} - universalify@2.0.1: {} unpipe@1.0.0: {} @@ -36035,14 +33710,6 @@ snapshots: uplot@1.6.31: {} - upper-case-first@2.0.2: - dependencies: - tslib: 2.8.1 - - upper-case@2.0.2: - dependencies: - tslib: 2.8.1 - uppercamelcase@1.1.0: dependencies: camelcase: 1.2.1 @@ -36051,11 +33718,6 @@ snapshots: dependencies: punycode: 2.3.1 - url-parse@1.5.10: - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - use-callback-ref@1.3.3(@types/react@18.3.28)(react@18.3.1): dependencies: react: 18.3.1 @@ -36121,8 +33783,6 @@ snapshots: validate-npm-package-name@7.0.2: {} - varint@6.0.0: {} - vary@1.1.2: {} vfile-message@4.0.3: @@ -36179,8 +33839,6 @@ snapshots: '@mapbox/vector-tile': 1.3.1 pbf: 3.3.0 - w3c-keyname@2.2.8: {} - w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -36202,9 +33860,7 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 - wawoff2@2.0.1: - dependencies: - argparse: 2.0.1 + wawoff2@2.0.1: {} wbuf@1.7.3: dependencies: @@ -36402,8 +34058,6 @@ snapshots: tr46: 6.0.0 webidl-conversions: 8.0.1 - when-exit@2.1.5: {} - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -36435,8 +34089,6 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-module@2.0.1: {} - which-typed-array@1.1.22: dependencies: available-typed-arrays: 1.0.7 @@ -36462,25 +34114,7 @@ snapshots: wildcard@2.0.1: {} - winston-transport@4.9.0: - dependencies: - logform: 2.7.0 - readable-stream: 3.6.2 - triple-beam: 1.4.1 - - winston@3.17.0: - dependencies: - '@colors/colors': 1.6.0 - '@dabh/diagnostics': 2.0.8 - async: 3.2.6 - is-stream: 2.0.1 - logform: 2.7.0 - one-time: 1.0.0 - readable-stream: 3.6.2 - safe-stable-stringify: 2.5.0 - stack-trace: 0.0.10 - triple-beam: 1.4.1 - winston-transport: 4.9.0 + winston@3.17.0: {} word-wrap@1.2.5: {} @@ -36504,39 +34138,14 @@ snapshots: string-width: 2.1.1 strip-ansi: 4.0.0 - wrap-ansi@5.1.0: - dependencies: - ansi-styles: 3.2.1 - string-width: 3.1.0 - strip-ansi: 5.2.0 - - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 - wrappy@1.0.2: {} - write-file-atomic@3.0.3: - dependencies: - imurmurhash: 0.1.4 - is-typedarray: 1.0.0 - signal-exit: 3.0.7 - typedarray-to-buffer: 3.1.5 - write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4 @@ -36550,20 +34159,9 @@ snapshots: ws@8.21.0: {} - wsl-utils@0.1.0: - dependencies: - is-wsl: 3.1.1 - - xdg-basedir@5.1.0: {} - xml-name-validator@5.0.0: {} - xml2js@0.6.2: - dependencies: - sax: 1.6.0 - xmlbuilder: 11.0.1 - - xmlbuilder@11.0.1: {} + xml2js@0.6.2: {} xmlchars@2.2.0: {} @@ -36574,8 +34172,6 @@ snapshots: lib0: 0.2.99 yjs: 13.6.29 - y18n@4.0.3: {} - y18n@5.0.8: {} yallist@3.1.1: {} @@ -36584,47 +34180,9 @@ snapshots: yaml@2.8.3: {} - yargs-parser@15.0.3: - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - - yargs-parser@18.1.3: - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - yargs-parser@21.1.1: {} - yargs-parser@22.0.0: {} - - yargs@14.2.3: - dependencies: - cliui: 5.0.0 - decamelize: 1.2.0 - find-up: 3.0.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 3.1.0 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 15.0.3 - - yargs@15.4.1: - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 18.1.3 + yargs@15.4.1: {} yargs@17.7.2: dependencies: @@ -36636,14 +34194,7 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yargs@18.0.0: - dependencies: - cliui: 9.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - string-width: 7.2.0 - y18n: 5.0.8 - yargs-parser: 22.0.0 + yargs@18.0.0: {} yauzl@2.10.0: dependencies: @@ -36652,14 +34203,10 @@ snapshots: yerror@8.0.0: {} - yjs@13.6.29: - dependencies: - lib0: 0.2.99 + yjs@13.6.29: {} yocto-queue@0.1.0: {} - yocto-queue@1.2.2: {} - zimmerframe@1.1.4: {} zod-validation-error@4.0.2(zod@3.25.76): diff --git a/projects/js-packages/grid/.gitignore b/projects/js-packages/grid/.gitignore new file mode 100644 index 000000000000..7e5da87a90b0 --- /dev/null +++ b/projects/js-packages/grid/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +vendor/ diff --git a/projects/js-packages/grid/CHANGELOG.md b/projects/js-packages/grid/CHANGELOG.md new file mode 100644 index 000000000000..03a962f457f6 --- /dev/null +++ b/projects/js-packages/grid/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/projects/js-packages/grid/README.md b/projects/js-packages/grid/README.md new file mode 100644 index 000000000000..f7463dede7bb --- /dev/null +++ b/projects/js-packages/grid/README.md @@ -0,0 +1,28 @@ +# @automattic/jetpack-grid + +Internal, **private** port of WordPress core's `@wordpress/grid` (the drag-and-drop / resize +grid powering dashboard layouts). Consumed by `@automattic/jetpack-widget-dashboard` and the +Jetpack Premium Analytics dashboard route. + +Consumed as **source** (`exports` → `./src/index.ts`); the host build (`wp-build`) compiles the +TypeScript and CSS modules. This package ships no build output. + +## Provenance + +Ported verbatim from [`WordPress/gutenberg`](https://github.com/WordPress/gutenberg) `packages/grid/src` +@ commit `8a40c807e86` (branch `refactor/wp-build-name-as-module-id`). + +When core publishes `@wordpress/grid`, replace this package with the published dependency and +update the import name in consumers. Keep this README's commit reference updated when syncing. + +### Local deviations from core + +- `src/shared/drag-overlay-drop-animation.ts`: the default-cleanup call uses a `typeof` guard + instead of an optional call (`cleanupDefault?.()`). Jetpack type-checks with `tsgo` + (`@typescript/native-preview`), which rejects optional-calling a `void | CleanupFunction` + union; the guard is semantically identical and passes both `tsc` and `tsgo`. + +## Privacy + +`"private": true` in `package.json` + `composer.json` without `npmjs-autopublish`/`mirror-repo` +guarantees this package is never published to npm or mirrored to a standalone repo. diff --git a/projects/js-packages/grid/changelog/initial-version b/projects/js-packages/grid/changelog/initial-version new file mode 100644 index 000000000000..0dbf8692af7d --- /dev/null +++ b/projects/js-packages/grid/changelog/initial-version @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Initial version: private port of WordPress core's @wordpress/grid for dashboard layouts. diff --git a/projects/js-packages/grid/composer.json b/projects/js-packages/grid/composer.json new file mode 100644 index 000000000000..81ec81944246 --- /dev/null +++ b/projects/js-packages/grid/composer.json @@ -0,0 +1,21 @@ +{ + "name": "automattic/jetpack-js-grid", + "description": "Grid component with drag-and-drop reordering and resize for dashboard layouts. Internal port of @wordpress/grid until it is published.", + "type": "library", + "license": "GPL-2.0-or-later", + "require": {}, + "repositories": [ + { + "type": "path", + "url": "../../packages/*", + "options": { + "monorepo": true + } + } + ], + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "textdomain": "jetpack-grid" + } +} diff --git a/projects/js-packages/grid/eslint.config.mjs b/projects/js-packages/grid/eslint.config.mjs new file mode 100644 index 000000000000..2ccd4474e681 --- /dev/null +++ b/projects/js-packages/grid/eslint.config.mjs @@ -0,0 +1,17 @@ +import { makeBaseConfig, defineConfig } from 'jetpack-js-tools/eslintrc/base.mjs'; + +// `src/` is vendored verbatim from WordPress core's `@wordpress/grid`. These rules +// conflict with core's house style; turning them off keeps the port faithful and +// avoids churn on every upstream re-sync. Drop this once core publishes the package. +export default defineConfig( makeBaseConfig( import.meta.url ), { + rules: { + 'react/jsx-no-bind': 'off', + 'import/order': 'off', + 'no-shadow': 'off', + 'jsdoc/check-indentation': 'off', + 'jsdoc/escape-inline-tags': 'off', + 'jsdoc/require-description': 'off', + 'jsdoc/require-param-description': 'off', + 'jsdoc/require-returns': 'off', + }, +} ); diff --git a/projects/js-packages/grid/package.json b/projects/js-packages/grid/package.json new file mode 100644 index 000000000000..d4e48ffd0e52 --- /dev/null +++ b/projects/js-packages/grid/package.json @@ -0,0 +1,49 @@ +{ + "name": "@automattic/jetpack-grid", + "version": "0.1.0-alpha", + "private": true, + "description": "Grid component with drag-and-drop reordering and resize for dashboard layouts. Internal port of @wordpress/grid until it is published.", + "license": "GPL-2.0-or-later", + "author": "Automattic", + "type": "module", + "sideEffects": [ + "**/*.module.css" + ], + "exports": { + ".": { + "jetpack:src": "./src/index.ts", + "types": "./src/index.ts", + "import": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "main": "./src/index.ts", + "module": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "typecheck": "tsgo --noEmit" + }, + "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@wordpress/compose": "7.46.0", + "@wordpress/element": "6.46.0", + "@wordpress/icons": "13.1.0", + "@wordpress/ui": "0.13.0", + "clsx": "^2.1.1" + }, + "devDependencies": { + "@types/react": "^18.3.27", + "@types/react-dom": "^18.3.7", + "@typescript/native-preview": "7.0.0-dev.20260225.1", + "jetpack-js-tools": "workspace:*", + "react": "18.3.1", + "react-dom": "18.3.1", + "typescript": "5.9.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } +} diff --git a/projects/js-packages/grid/src/dashboard-grid/grid-item.module.css b/projects/js-packages/grid/src/dashboard-grid/grid-item.module.css new file mode 100644 index 000000000000..69ff0b5465fc --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-grid/grid-item.module.css @@ -0,0 +1,99 @@ +.item { + position: relative; +} + +.item-content { + position: relative; + height: 100%; +} + +.is-resizing { + overflow: visible; + z-index: 1; +} + +.is-resizing .item-content { + position: relative; + z-index: 2; + overflow: visible; +} + +/* + * During drag, the original item acts as a placeholder in its grid + * cell while `` renders a clone that follows the cursor. + * Fading the placeholder and outlining it makes the destination visible + * without any scaling or translation on the original element. + * + * Placeholder chrome waits until `data-wp-grid-dragging` is set and the + * drag-preview enter animation (`--wpds-motion-duration-sm`) finishes + * so the dashed outline does not flash under the lifting clone. + */ +.is-dragging { + pointer-events: none; +} + +:global([data-wp-grid-dragging]) .is-dragging { + border-radius: var(--wp-grid-placeholder-radius, 0); +} + +@media not (prefers-reduced-motion: reduce) { + + :global([data-wp-grid-dragging]) .is-dragging { + opacity: 1; + outline-width: 0; + outline-style: var(--wp-grid-placeholder-outline-style, dashed); + outline-color: transparent; + animation: + wp-grid-item-placeholder-in 0ms linear + var(--wpds-motion-duration-sm) forwards; + } + + @keyframes wp-grid-item-placeholder-in { + + to { + opacity: var(--wp-grid-placeholder-opacity, 0.4); + outline-width: var(--wpds-border-width-sm); + outline-color: var(--wp-grid-placeholder-outline-color, var(--wpds-color-stroke-interactive-brand)); + } + } +} + +@media (prefers-reduced-motion: reduce) { + + :global([data-wp-grid-dragging]) .is-dragging { + opacity: var(--wp-grid-placeholder-opacity, 0.4); + outline: + var(--wpds-border-width-sm) + var(--wp-grid-placeholder-outline-style, dashed) + var(--wp-grid-placeholder-outline-color, var(--wpds-color-stroke-interactive-brand)); + } +} + +@media (forced-colors: active) { + + :global([data-wp-grid-dragging]) .is-dragging { + --wp-grid-placeholder-outline-color: Highlight; + } +} + +.preview-overlay { + position: absolute; + top: 0; + inset-inline-start: 0; + box-sizing: border-box; + pointer-events: none; + z-index: 0; + border: + var(--wpds-border-width-sm) + var(--wp-grid-resize-preview-outline-style, solid) + var(--wp-grid-placeholder-outline-color, var(--wpds-color-stroke-interactive-brand)); + background: transparent; + border-radius: var(--wp-grid-placeholder-radius, 0); +} + +@media (forced-colors: active) { + + .preview-overlay { + border-color: Highlight; + } +} diff --git a/projects/js-packages/grid/src/dashboard-grid/grid-item.tsx b/projects/js-packages/grid/src/dashboard-grid/grid-item.tsx new file mode 100644 index 000000000000..7db58e3a3313 --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-grid/grid-item.tsx @@ -0,0 +1,212 @@ +/** + * External dependencies + */ +import { useSortable } from '@dnd-kit/sortable'; +import { useMergeRefs } from '@wordpress/compose'; +import { useState, useRef } from '@wordpress/element'; +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ + +/** + * Internal dependencies + */ +import actionableAreaStyles from '../shared/actionable-area-slot.module.css'; +import { GRID_ITEM_DATA_KEY } from '../shared/grid-item-key'; +import ResizeHandle from '../shared/resize-handle'; +import { clampResizeDelta, type ResizeSnapSize } from '../shared/resize-snap'; +import styles from './grid-item.module.css'; +import type { GridItemProps } from './types'; +import type { ResizeDelta } from '../shared/types'; + +/** + * + * @param disabled + * @param interacting + */ +function getItemCursor( disabled: boolean, interacting: boolean ): React.CSSProperties[ 'cursor' ] { + if ( disabled ) { + return 'default'; + } + + if ( interacting ) { + return undefined; + } + + return 'grab'; +} + +/** + * + * @param root0 + * @param root0.item + * @param root0.maxColumns + * @param root0.disabled + * @param root0.verticalResizable + * @param root0.interacting + * @param root0.dragging + * @param root0.children + * @param root0.actionableArea + * @param root0.onResize + * @param root0.onResizeEnd + * @param root0.resizeSnapPreview + * @param root0.minResizeWidthPx + * @param root0.minResizeHeightPx + * @param root0.renderResizeHandle + */ +export function GridItem( { + item, + maxColumns, + disabled = false, + verticalResizable = true, + interacting = false, + dragging = false, + children, + actionableArea = null, + onResize, + onResizeEnd, + resizeSnapPreview = null, + minResizeWidthPx, + minResizeHeightPx, + renderResizeHandle, +}: GridItemProps ) { + const [ resizeDelta, setResizeDelta ] = useState< ResizeDelta | null >( null ); + const [ initialContentSize, setInitialContentSize ] = useState< { + width: number; + height: number; + } | null >( null ); + const itemRef = useRef< HTMLDivElement >( null ); + const contentRef = useRef< HTMLDivElement >( null ); + const { attributes, listeners, setNodeRef, setActivatorNodeRef, isDragging } = useSortable( { + id: item.key, + disabled, + } ); + const mergedRef = useMergeRefs( [ itemRef, setNodeRef ] ); + const contentMergedRef = useMergeRefs( [ contentRef ] ); + /* + * With `` handling the cursor-following clone, the + * sortable item stays put in its grid cell and acts as a + * placeholder. No `transform` is applied here — applying one + * would double-move the placeholder alongside the overlay. + */ + const style = { + gridColumnEnd: `span ${ + item.width === 'full' + ? maxColumns + : Math.min( typeof item.width === 'number' ? item.width : 1, maxColumns ) + }`, + gridRowEnd: `span ${ item.height || 1 }`, + }; + + const isResizing = resizeDelta !== null; + const itemClassName = clsx( + styles.item, + isDragging && styles[ 'is-dragging' ], + isResizing && styles[ 'is-resizing' ] + ); + + const handleResize = ( delta: ResizeDelta ) => { + const contentNode = contentRef.current; + let baselineSize = initialContentSize; + if ( contentNode && ! baselineSize ) { + const { width, height } = contentNode.getBoundingClientRect(); + baselineSize = { width, height }; + setInitialContentSize( baselineSize ); + } + let clamped: ResizeDelta = { + width: delta.width, + height: verticalResizable ? delta.height : 0, + }; + if ( baselineSize ) { + clamped = clampResizeDelta( clamped, baselineSize, { + width: minResizeWidthPx, + height: verticalResizable ? minResizeHeightPx : undefined, + } ); + } + setResizeDelta( clamped ); + onResize( item.key, clamped ); + }; + + const handleResizeEnd = () => { + setResizeDelta( null ); + setInitialContentSize( null ); + onResizeEnd(); + }; + + const continuousContentStyle: React.CSSProperties | undefined = + resizeDelta && initialContentSize + ? { + width: initialContentSize.width + resizeDelta.width, + height: verticalResizable ? initialContentSize.height + resizeDelta.height : undefined, + } + : undefined; + + const previewOverlay = resizeSnapPreview ? ( + + ) : null; + + return ( +
+ { actionableArea ? ( +
+
+ { actionableArea } +
+
+ ) : null } + +
+
+ { children } + { ! disabled && ( + + ) } +
+ { previewOverlay } +
+
+ ); +} + +/** + * + * @param root0 + * @param root0.snap + */ +function SnapPreviewOverlay( { snap }: { snap: ResizeSnapSize } ) { + return ( +
+ ); +} diff --git a/projects/js-packages/grid/src/dashboard-grid/grid.module.css b/projects/js-packages/grid/src/dashboard-grid/grid.module.css new file mode 100644 index 000000000000..990a2df40f47 --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-grid/grid.module.css @@ -0,0 +1,142 @@ +.grid { + display: grid; + gap: var(--wp-grid-gap, var(--wpds-dimension-gap-xl)); + position: relative; +} + +/* + * Functional frame for the drag-preview clone inside ``. + * Always applied, including when the consumer passes a + * `renderDragPreview` wrapper. The outer frame has no `transform` so + * @dnd-kit’s drop translation matches the placeholder; scale lives on + * `__lift` (see dnd-kit #398). Owns elevation, radius, cursor, and + * pointer pass-through. Further chrome belongs to the consumer. Drag + * elevation animates `xs` → `md` so it reads above edit tiles at `xs`. + */ +.drag-preview-frame { + height: 100%; + border-radius: var(--wp-grid-drag-preview-radius, 0); + cursor: grabbing; + pointer-events: none; + box-shadow: var(--wpds-elevation-md); +} + +.drag-preview-frame__lift { + height: 100%; + transform: scale(var(--wp-grid-drag-preview-scale, 1.05)); + transform-origin: center; +} + +@media not (prefers-reduced-motion: reduce) { + + .drag-preview-frame { + animation: + wp-grid-drag-preview-shadow-enter + var(--wpds-motion-duration-sm) var(--wpds-motion-easing-balanced) both; + } + + .drag-preview-frame__lift { + animation: + wp-grid-drag-preview-scale-enter + var(--wpds-motion-duration-sm) var(--wpds-motion-easing-balanced) both; + } +} + +@media not (prefers-reduced-motion: reduce) { + + @keyframes wp-grid-drag-preview-shadow-enter { + + from { + box-shadow: var(--wpds-elevation-xs); + } + + to { + box-shadow: var(--wpds-elevation-md); + } + } + + @keyframes wp-grid-drag-preview-scale-enter { + + from { + transform: scale(1); + } + + to { + transform: scale(var(--wp-grid-drag-preview-scale, 1.05)); + } + } +} + +/* + * Applied by @dnd-kit `DragOverlay` drop side-effects while the + * default overlay transform runs; duration matches + * `createDashboardDragDropAnimation` (200ms / md token). Use keyframed + * exit (not transition) so scale does not snap when the enter animation + * is replaced. + */ +@media not (prefers-reduced-motion: reduce) { + + .drag-preview-frame.dragPreviewFrameExiting { + animation: + wp-grid-drag-preview-shadow-exit + var(--wpds-motion-duration-md) var(--wpds-motion-easing-balanced) + forwards; + } + + .drag-preview-frame.dragPreviewFrameExiting .drag-preview-frame__lift { + animation: + wp-grid-drag-preview-scale-exit + var(--wpds-motion-duration-md) var(--wpds-motion-easing-balanced) + forwards; + } + + @keyframes wp-grid-drag-preview-shadow-exit { + + from { + box-shadow: var(--wpds-elevation-md); + } + + to { + box-shadow: var(--wpds-elevation-xs); + } + } + + @keyframes wp-grid-drag-preview-scale-exit { + + from { + transform: scale(var(--wp-grid-drag-preview-scale, 1.05)); + } + + to { + transform: scale(1); + } + } +} + +.drag-preview-frame.dragPreviewFrameExiting { + box-shadow: var(--wpds-elevation-xs); +} + +.drag-preview-frame.dragPreviewFrameExiting .drag-preview-frame__lift { + transform: scale(1); +} + +@media (prefers-reduced-motion: reduce) { + + .drag-preview-frame { + box-shadow: var(--wpds-elevation-md); + } + + .drag-preview-frame__lift { + transform: none; + } + + .drag-preview-frame.dragPreviewFrameExiting { + box-shadow: var(--wpds-elevation-xs); + transition: none; + } + + .drag-preview-frame.dragPreviewFrameExiting .drag-preview-frame__lift { + transition: none; + } +} diff --git a/projects/js-packages/grid/src/dashboard-grid/index.tsx b/projects/js-packages/grid/src/dashboard-grid/index.tsx new file mode 100644 index 000000000000..fcbdbf36193a --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-grid/index.tsx @@ -0,0 +1,624 @@ +/** + * External dependencies + */ +import { + DndContext, + DragOverlay, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; +import { arrayMove, SortableContext, sortableKeyboardCoordinates } from '@dnd-kit/sortable'; +import { useResizeObserver, useEvent, useMergeRefs } from '@wordpress/compose'; +import { + forwardRef, + useMemo, + Children, + cloneElement, + isValidElement, + useLayoutEffect, + useRef, + useState, +} from '@wordpress/element'; +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ + +/** + * Internal dependencies + */ +import { createDashboardDragDropAnimation } from '../shared/drag-overlay-drop-animation'; +import { GridOverlay } from '../shared/grid-overlay'; +import { ItemExitOverlay } from '../shared/item-exit-overlay'; +import layoutAnimationStyles from '../shared/layout-shift-animation.module.css'; +import { gridSpanToPixelSize } from '../shared/resize-snap'; +import { useItemExitAnimation } from '../shared/use-item-exit-animation'; +import { + getLayoutFingerprint, + useLayoutShiftAnimation, +} from '../shared/use-layout-shift-animation'; +import { GridItem } from './grid-item'; +import styles from './grid.module.css'; +import { resolveFillWidths } from './resolve-fill-widths'; +import type { DashboardGridLayoutItem, DashboardGridProps } from './types'; +import type { ResizeSnapSize } from '../shared/resize-snap'; +import type { ResizeDelta } from '../shared/types'; +import type { DragMoveEvent, DragStartEvent } from '@dnd-kit/core'; + +const dashboardDragDropAnimation = createDashboardDragDropAnimation( + styles[ 'drag-preview-frame' ], + styles.dragPreviewFrameExiting +); + +// Fallback gap in pixels for math that runs before the computed gap +// can be read from the DOM. Matches the `'xl'` step the surface +// resolves to in CSS (`--wpds-dimension-gap-xl`); the next layout +// effect overwrites this with the actual computed value. +const FALLBACK_GAP_PX = 24; + +// Default column cap when no explicit `columns` or `minColumnWidth` is +// supplied. Layered semantics: `columns` acts as a cap and +// `minColumnWidth` as a per-tile floor; if neither is set we still +// need a finite count to render against. +const DEFAULT_COLUMNS = 6; + +// Reorder is driven by `temporaryLayout` + CSS Grid, not by dnd-kit +// transforms. Hoist the no-op strategy outside the component so its +// reference is stable across renders — passing a fresh `() => null` +// to `` updates its context value and triggers all +// `useSortable` subscribers to re-render every frame. +const NO_SORT_STRATEGY = () => null; + +/** + * 2D packed dashboard grid with drag-to-reorder and resize handles. + * Supports fixed-column and responsive modes, `number | 'fill' | 'full'` + * widths, and multi-row tiles. + * + * Each child's `key` must match an entry in the `layout` array; + * children without a match render at the end of the grid without + * explicit placement and fall through CSS Grid's auto-flow. + * + * @example + * ```jsx + * const layout = [ + * { key: 'a', width: 2 }, + * { key: 'b', width: 'fill' }, + * { key: 'c', width: 'full' }, + * ]; + * + * + *
A
+ *
B
+ *
C
+ *
+ * ``` + * + * @param props - Component props. + * @param ref - Forwarded to the grid's root `
`. + */ +export const DashboardGrid = forwardRef< HTMLDivElement, DashboardGridProps >( + function DashboardGrid( props, ref ) { + const { + layout, + columns, + children, + className, + style, + rowHeight = 'auto', + minColumnWidth, + editMode = false, + onChangeLayout, + onPreviewLayout, + renderResizeHandle, + renderDragPreview, + renderGridOverlay, + ...divProps + } = props; + // Preview layout applied during drag/resize before committing. + const [ temporaryLayout, setTemporaryLayout ] = useState< + DashboardGridLayoutItem[] | undefined + >(); + // Drives `` content while a drag is in progress. + const [ activeId, setActiveId ] = useState< string | null >( null ); + // True while any tile is being resized. Combined with `activeId`, + // it drives the grid-wide `inert` flag on actionable areas so + // hovering over another tile's buttons can't steal the gesture. + const [ isResizing, setIsResizing ] = useState( false ); + // Snapped span in pixels for the resize-preview outline on the + // active tile. The tile content follows the cursor continuously; + // this preview shows the grid size that will commit on release. + const [ resizeSnapPreview, setResizeSnapPreview ] = useState< { + id: string; + snap: ResizeSnapSize; + } | null >( null ); + // Mirror of `temporaryLayout` read synchronously on drag end — + // the state update from `handleDragMove` may still be batched. + const latestLayoutRef = useRef< DashboardGridLayoutItem[] | undefined >(); + // Cursor center at the last applied reorder. Used to skip the + // cascade of re-measured `onDragMove` events after a layout + // change, when the cursor has not actually moved. + const lastReorderCursorRef = useRef< { + x: number; + y: number; + } | null >( null ); + // Width/height snapshot at the start of a resize session. The + // resize handle reports `delta` absolute from the gesture start, + // so the baseline must stay frozen — reading from the already + // mutated `activeLayout` would compound the delta each frame. + const resizeBaselineRef = useRef< { + width: number; + height: number; + } | null >( null ); + const captureLayoutSnapshotRef = useRef< () => void >( () => {} ); + const childrenCacheRef = useRef< Map< string, React.ReactElement > >( new Map() ); + const activeLayout = temporaryLayout ?? layout; + + const [ gridRoot, setGridRoot ] = useState< HTMLDivElement | null >( null ); + const [ containerWidth, setContainerWidth ] = useState( 0 ); + const [ containerHeight, setContainerHeight ] = useState( 0 ); + const [ gapPx, setGapPx ] = useState( FALLBACK_GAP_PX ); + const resizeObserverRef = useResizeObserver( ( [ { contentRect } ] ) => { + setContainerWidth( contentRect.width ); + setContainerHeight( contentRect.height ); + } ); + const mergedGridRef = useMergeRefs( [ setGridRoot, resizeObserverRef, ref ] ); + + // Measure before paint to avoid a single-column flash in + // responsive mode; `useResizeObserver` delivers async. The + // computed `column-gap` is read from the resolved CSS so the + // math tracks the design-system token under any density. + useLayoutEffect( () => { + if ( ! gridRoot ) { + return; + } + const { width, height } = gridRoot.getBoundingClientRect(); + if ( width > 0 ) { + setContainerWidth( width ); + } + if ( height > 0 ) { + setContainerHeight( height ); + } + const parsed = Number.parseFloat( window.getComputedStyle( gridRoot ).columnGap ); + if ( Number.isFinite( parsed ) && parsed > 0 ) { + setGapPx( parsed ); + } + }, [ gridRoot ] ); + const effectiveColumns = useMemo( () => { + if ( ! minColumnWidth ) { + return columns ?? DEFAULT_COLUMNS; + } + + const totalWidthPerColumn = minColumnWidth + gapPx; + const maxFit = Math.max( 1, Math.floor( ( containerWidth + gapPx ) / totalWidthPerColumn ) ); + return columns !== undefined ? Math.min( columns, maxFit ) : maxFit; + }, [ minColumnWidth, gapPx, containerWidth, columns ] ); + const columnWidth = ( containerWidth - ( effectiveColumns - 1 ) * gapPx ) / effectiveColumns; + const minResizeWidthPx = gridSpanToPixelSize( 1, 1, columnWidth, gapPx, null ).widthPx; + const rowHeightPx = typeof rowHeight === 'number' ? rowHeight : null; + const minResizeHeightPx = + rowHeightPx === null + ? undefined + : gridSpanToPixelSize( 1, 1, columnWidth, gapPx, rowHeightPx ).heightPx ?? undefined; + + const layoutMap = useMemo( () => { + const map = new Map< string, DashboardGridLayoutItem >(); + activeLayout.forEach( item => map.set( item.key, item ) ); + return map; + }, [ activeLayout ] ); + + // Stable-identity key set, preserved across renders whenever the + // *contents* of the key set are unchanged — even if the consumer + // passes a fresh `layout` array reference (common when `layout` + // is derived inline from state). Without this, downstream memos + // would invalidate on every parent re-render and the children + // walk skip during gestures wouldn't hold. + const layoutKeys = useMemo( () => new Set( layout.map( item => item.key ) ), [ layout ] ); + + // Sorted item keys, identity-stable when the resulting sequence is + // unchanged. Avoids producing a fresh `items` array on every parent + // re-render so `` doesn't update its context value + // and notify every `useSortable` subscriber unnecessarily. + const sortedItems = useMemo( + () => + activeLayout + .map( ( item, index ) => ( { item, index } ) ) + .sort( ( a, b ) => ( a.item.order ?? a.index ) - ( b.item.order ?? b.index ) ) + .map( ( { item } ) => item.key ), + [ activeLayout ] + ); + const items = sortedItems; + + // Resolve `width: 'fill'` items to concrete column spans. + const resolvedItemMap = useMemo( () => { + const fillWidths = resolveFillWidths( items, layoutMap, effectiveColumns ); + if ( fillWidths.size === 0 ) { + return layoutMap; + } + const map = new Map< string, DashboardGridLayoutItem >(); + for ( const [ key, item ] of layoutMap ) { + const fillW = fillWidths.get( key ); + map.set( key, fillW !== undefined ? { ...item, width: fillW } : item ); + } + return map; + }, [ items, layoutMap, effectiveColumns ] ); + + const [ childrenMap, actionableAreaMap, remaining, renderedByKey ] = useMemo( () => { + const childMap = new Map< string, React.ReactElement >(); + const actionableMap = new Map< string, React.ReactNode >(); + const rest: React.ReactNode[] = []; + const byKey = new Map< string, React.ReactElement >(); + + Children.forEach( children, child => { + if ( ! isValidElement( child ) ) { + rest.push( child ); + return; + } + + const key = child.key?.toString(); + if ( ! key ) { + rest.push( child ); + return; + } + + // Strip `actionableArea` so it does not leak to the DOM; + // the grid lifts it to a slot separately. + const { actionableArea } = child.props; + const stripped = + actionableArea !== undefined + ? cloneElement( child, { + actionableArea: undefined, + } ) + : child; + + byKey.set( key, stripped ); + + if ( layoutKeys.has( key ) ) { + if ( actionableArea !== undefined ) { + actionableMap.set( key, actionableArea ); + } + childMap.set( key, stripped ); + } else { + rest.push( child ); + } + } ); + + return [ childMap, actionableMap, rest, byKey ]; + }, [ children, layoutKeys ] ); + + // Persist the latest rendered children so a removed tile's content + // is still available for its exit overlay. Filled from an effect so a + // discarded render never writes to the cache. + useLayoutEffect( () => { + for ( const [ key, child ] of renderedByKey ) { + childrenCacheRef.current.set( key, child ); + } + }, [ renderedByKey ] ); + + const sensors = useSensors( + useSensor( PointerSensor ), + useSensor( KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + } ) + ); + + const handleDragStart = useEvent( ( event: DragStartEvent ) => { + setActiveId( String( event.active.id ) ); + lastReorderCursorRef.current = null; + } ); + + const handleDragCancel = useEvent( () => { + setActiveId( null ); + latestLayoutRef.current = undefined; + lastReorderCursorRef.current = null; + resizeBaselineRef.current = null; + setIsResizing( false ); + setResizeSnapPreview( null ); + setTemporaryLayout( undefined ); + } ); + + // Re-evaluate the insertion slot on every pointer move, not + // just when `over.id` changes — otherwise a "swap back" with + // the cursor still on the same tile would never fire. + const handleDragMove = useEvent( ( event: DragMoveEvent ) => { + const { active, over } = event; + if ( ! over || active.id === over.id ) { + return; + } + + const activeRect = active.rect.current.translated; + if ( ! activeRect ) { + return; + } + + const activeCenterX = activeRect.left + activeRect.width / 2; + const activeCenterY = activeRect.top + activeRect.height / 2; + + // Skip re-measured events after a layout change: require + // meaningful cursor movement between reorders. + const lastCursor = lastReorderCursorRef.current; + if ( lastCursor ) { + const dx = activeCenterX - lastCursor.x; + const dy = activeCenterY - lastCursor.y; + if ( dx * dx + dy * dy < 100 ) { + return; + } + } + + const overCenterX = over.rect.left + over.rect.width / 2; + const insertAfter = activeCenterX > overCenterX; + + const currentIndex = items.indexOf( String( active.id ) ); + const overIndex = items.indexOf( String( over.id ) ); + let newIndex: number; + if ( insertAfter ) { + newIndex = currentIndex > overIndex ? overIndex + 1 : overIndex; + } else { + newIndex = currentIndex > overIndex ? overIndex : overIndex - 1; + } + newIndex = Math.max( 0, Math.min( newIndex, items.length - 1 ) ); + + if ( newIndex === currentIndex ) { + return; + } + + const updatedItems = arrayMove( items, currentIndex, newIndex ); + const updatedLayout = activeLayout.map( item => ( { + ...item, + order: updatedItems.indexOf( item.key ), + } ) ); + + lastReorderCursorRef.current = { + x: activeCenterX, + y: activeCenterY, + }; + latestLayoutRef.current = updatedLayout; + captureLayoutSnapshotRef.current(); + setTemporaryLayout( updatedLayout ); + onPreviewLayout?.( updatedLayout ); + } ); + + // Commit the latest temporary layout and clear local state. + // Reads from the ref to bypass React's state batching. + const persistTemporaryLayout = useEvent( () => { + const latest = latestLayoutRef.current; + latestLayoutRef.current = undefined; + resizeBaselineRef.current = null; + setIsResizing( false ); + setResizeSnapPreview( null ); + if ( ! onChangeLayout || ! latest ) { + setTemporaryLayout( undefined ); + return; + } + + onChangeLayout( latest ); + setTemporaryLayout( undefined ); + } ); + + const handleResize = useEvent( ( id: string, delta: ResizeDelta ) => { + if ( ! editMode ) { + return; + } + + if ( ! isResizing ) { + setIsResizing( true ); + } + + const relativeDelta = { + width: Math.round( delta.width / ( columnWidth + gapPx ) ), + height: rowHeight === 'auto' ? 0 : Math.round( delta.height / ( rowHeight + gapPx ) ), + }; + + // Snapshot the baseline once at gesture start. The handle's + // `delta` is absolute from the gesture start, so summing it + // with the live (already mutated) `activeLayout` width would + // compound and oscillate — and stepping back through the + // zero-delta zone would never restore the original size. + if ( ! resizeBaselineRef.current ) { + const baseItem = activeLayout.find( item => item.key === id ); + const resolvedItem = resolvedItemMap.get( id ); + // `'fill'`/`'full'` resize from the rendered span + // and convert to a numeric width. + let baseWidth: number; + if ( baseItem?.width === 'full' ) { + baseWidth = effectiveColumns; + } else if ( baseItem?.width === 'fill' ) { + baseWidth = typeof resolvedItem?.width === 'number' ? resolvedItem.width : 1; + } else { + baseWidth = baseItem?.width ?? 1; + } + resizeBaselineRef.current = { + width: baseWidth, + height: baseItem?.height ?? 1, + }; + } + const baseline = resizeBaselineRef.current; + const newWidth = Math.max( + 1, + Math.min( baseline.width + relativeDelta.width, effectiveColumns ) + ); + const newHeight = Math.max( 1, baseline.height + relativeDelta.height ); + + setResizeSnapPreview( { + id, + snap: gridSpanToPixelSize( newWidth, newHeight, columnWidth, gapPx, rowHeightPx ), + } ); + + // Bail when the snapped size matches the layout already + // staged for commit. The tile still tracks the cursor + // continuously; only the preview outline and pending commit + // need updating when the snap target changes. + const pendingItem = latestLayoutRef.current?.find( item => item.key === id ); + const currentItem = pendingItem ?? activeLayout.find( item => item.key === id ); + if ( + currentItem && + currentItem.width === newWidth && + ( currentItem.height ?? 1 ) === newHeight + ) { + return; + } + + const updatedLayout = activeLayout.map( item => + item.key === id ? { ...item, width: newWidth, height: newHeight } : item + ); + + latestLayoutRef.current = updatedLayout; + captureLayoutSnapshotRef.current(); + setTemporaryLayout( updatedLayout ); + onPreviewLayout?.( updatedLayout ); + } ); + + // Drag-overlay clone composition: the surface always wraps with a + // thin functional frame (lift, cursor, pointer pass-through). When + // `renderDragPreview` is supplied, the consumer's wrapper sits + // inside the frame around the cloned children; otherwise the + // cloned children render directly so any persistent chrome on + // them carries through unchanged. + const activeClone = activeId ? childrenMap.get( activeId ) : null; + const DragPreview = renderDragPreview; + const dragOverlayContent = + activeId && activeClone ? ( +
+
+ { DragPreview ? ( + { activeClone } + ) : ( + activeClone + ) } +
+
+ ) : null; + + // Edit-mode background visual. Default paints row-marker tiles + // per column; a consumer can replace it via `renderGridOverlay` + // while reusing the resolved column count, row height, and row + // count. `'auto'` collapses to `undefined` for the overlay so + // row markers are omitted when the row height is content-driven. + // Rendered unconditionally so the overlay can cross-fade on + // edit-mode toggles; `isActive` drives the opacity transition + // inside the overlay. Memoized so drag/resize re-renders skip + // reconciliation while inputs are stable. + const Overlay = renderGridOverlay ?? GridOverlay; + const overlayRowHeight = typeof rowHeight === 'number' ? rowHeight : undefined; + const overlayRows = useMemo( () => { + if ( overlayRowHeight === undefined || containerHeight <= 0 ) { + return undefined; + } + const rowTile = overlayRowHeight + gapPx; + return Math.max( 1, Math.floor( ( containerHeight + gapPx ) / rowTile ) ); + }, [ overlayRowHeight, containerHeight, gapPx ] ); + const gridOverlay = useMemo( + () => ( + + ), + [ Overlay, editMode, effectiveColumns, overlayRowHeight, overlayRows ] + ); + + const layoutFingerprint = useMemo( + () => getLayoutFingerprint( [ ...resolvedItemMap.values() ] ), + [ resolvedItemMap ] + ); + const excludeLayoutAnimationKey = activeId ?? ( isResizing ? resizeSnapPreview?.id : null ); + const { captureLayoutSnapshot, getPositionsBeforeLastChange } = useLayoutShiftAnimation( { + container: gridRoot, + enabled: editMode, + layoutFingerprint, + excludeItemKey: excludeLayoutAnimationKey, + } ); + const { exitingItems, clearExitingItem } = useItemExitAnimation( { + container: gridRoot, + enabled: editMode, + layoutKeys, + getPositionsBeforeLastChange, + childrenCacheRef, + } ); + // Transform transitions on tiles for FLIP (drag, resize, removal). + const layoutAnimating = editMode; + useLayoutEffect( () => { + captureLayoutSnapshotRef.current = captureLayoutSnapshot; + }, [ captureLayoutSnapshot ] ); + + return ( + { + persistTemporaryLayout(); + lastReorderCursorRef.current = null; + setActiveId( null ); + } } + > + { /* No-op strategy: reorder comes from `temporaryLayout` + + CSS Grid, not dnd-kit transforms. */ } + +
+ { gridOverlay } + { items.map( id => ( + + { childrenMap.get( id ) } + + ) ) } + { remaining } + { exitingItems.map( ( { key, rect, child } ) => ( + clearExitingItem( key ) } + > + { child } + + ) ) } +
+
+ + { dragOverlayContent } + +
+ ); + } +); diff --git a/projects/js-packages/grid/src/dashboard-grid/resolve-fill-widths.ts b/projects/js-packages/grid/src/dashboard-grid/resolve-fill-widths.ts new file mode 100644 index 000000000000..cbab5d8a222d --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-grid/resolve-fill-widths.ts @@ -0,0 +1,210 @@ +/** + * Internal dependencies + */ +import type { DashboardGridLayoutItem } from './types'; + +/** + * Resolves items with `width: 'fill'` by computing how many columns they + * should span. Simulates CSS Grid's row-sparse auto-flow placement so the + * resolved span matches the free run that CSS Grid will actually use. + * + * Two paths: + * - Fast path (no `height > 1` items): single-row column tracker, O(n). + * Each fixed item between two fills is visited at most once by a fill's + * look-ahead. + * - Multi-row path (any item with `height > 1`): per-column skyline that + * tracks shadow occupation of tall tiles. Placement scans rows in + * row-major order, so worst-case cost depends on both columns and rows + * scanned (rows bounded by the sum of item heights), not only on + * `maxColumns`. + * + * @param sortedKeys - Item keys in display order. + * @param layoutMap - Map of key to DashboardGridLayoutItem. + * @param maxColumns - Total columns in the grid. + * @return Map of fill item keys to their resolved column spans. + */ +export function resolveFillWidths( + sortedKeys: string[], + layoutMap: Map< string, DashboardGridLayoutItem >, + maxColumns: number +): Map< string, number > { + const resolved = new Map< string, number >(); + const n = sortedKeys.length; + + // Pre-extract items, clamp widths and heights, detect which path to take. + const items = new Array< DashboardGridLayoutItem | undefined >( n ); + const widths = new Array< number >( n ); + const heights = new Array< number >( n ); + let hasFill = false; + let hasMultiRow = false; + let totalRows = 0; + + for ( let i = 0; i < n; i++ ) { + const item = layoutMap.get( sortedKeys[ i ] ); + items[ i ] = item; + widths[ i ] = item && typeof item.width === 'number' ? Math.min( item.width, maxColumns ) : 1; + // Clamp to a positive integer so `0`, fractional, or negative + // values match the `|| 1` defaulting used in GridItem styles. + const h = Math.max( 1, Math.floor( item?.height ?? 1 ) ); + heights[ i ] = h; + if ( item?.width === 'fill' ) { + hasFill = true; + } + if ( h > 1 ) { + hasMultiRow = true; + } + totalRows += h; + } + + if ( ! hasFill ) { + return resolved; + } + + if ( ! hasMultiRow ) { + let currentCol = 0; + + for ( let i = 0; i < n; i++ ) { + const item = items[ i ]; + if ( ! item ) { + continue; + } + + if ( item.width === 'full' ) { + currentCol = 0; + continue; + } + + if ( item.width === 'fill' ) { + let reserved = 0; + for ( let j = i + 1; j < n; j++ ) { + const next = items[ j ]; + if ( ! next || next.width === 'full' || next.width === 'fill' ) { + break; + } + const nextW = widths[ j ]; + if ( currentCol + 1 + reserved + nextW <= maxColumns ) { + reserved += nextW; + } else { + break; + } + } + const fillCols = Math.max( 1, maxColumns - currentCol - reserved ); + resolved.set( item.key, fillCols ); + currentCol += fillCols; + } else { + const w = widths[ i ]; + if ( currentCol + w > maxColumns ) { + currentCol = 0; + } + currentCol += w; + } + + if ( currentCol >= maxColumns ) { + currentCol = 0; + } + } + + return resolved; + } + + // `rowOccupancy[ col ]` is the index of the next free row at that + // column; rows below it are taken by previously placed items. This + // captures the "shadow" of tall tiles into the rows they span. + const rowOccupancy = new Array< number >( maxColumns ).fill( 0 ); + let cursorRow = 0; + let cursorCol = 0; + + for ( let i = 0; i < n; i++ ) { + const item = items[ i ]; + if ( ! item ) { + continue; + } + + const h = heights[ i ]; + + if ( item.width === 'full' ) { + let r = cursorRow; + for ( let c = 0; c < maxColumns; c++ ) { + if ( rowOccupancy[ c ] > r ) { + r = rowOccupancy[ c ]; + } + } + for ( let c = 0; c < maxColumns; c++ ) { + rowOccupancy[ c ] = r + h; + } + cursorRow = r + h; + cursorCol = 0; + continue; + } + + if ( item.width === 'fill' ) { + let r = cursorRow; + let c = cursorCol; + scan: for ( ; r <= totalRows; r++ ) { + const start = r === cursorRow ? cursorCol : 0; + for ( c = start; c < maxColumns; c++ ) { + if ( rowOccupancy[ c ] <= r ) { + break scan; + } + } + } + const fillStartRow = r; + const fillStartCol = c; + let runLength = 0; + while ( + fillStartCol + runLength < maxColumns && + rowOccupancy[ fillStartCol + runLength ] <= fillStartRow + ) { + runLength++; + } + let reserved = 0; + for ( let j = i + 1; j < n; j++ ) { + const next = items[ j ]; + if ( ! next || next.width === 'full' || next.width === 'fill' ) { + break; + } + const nextW = widths[ j ]; + if ( 1 + reserved + nextW <= runLength ) { + reserved += nextW; + } else { + break; + } + } + const fillCols = Math.max( 1, runLength - reserved ); + resolved.set( item.key, fillCols ); + for ( let k = 0; k < fillCols; k++ ) { + rowOccupancy[ fillStartCol + k ] = fillStartRow + h; + } + cursorRow = fillStartRow; + cursorCol = fillStartCol + fillCols; + continue; + } + + const w = widths[ i ]; + let r = cursorRow; + let c = cursorCol; + place: for ( ; r <= totalRows; r++ ) { + c = r === cursorRow ? cursorCol : 0; + while ( c + w <= maxColumns ) { + let blocked = -1; + for ( let k = 0; k < w; k++ ) { + if ( rowOccupancy[ c + k ] > r ) { + blocked = c + k; + break; + } + } + if ( blocked === -1 ) { + break place; + } + c = blocked + 1; + } + } + for ( let k = 0; k < w; k++ ) { + rowOccupancy[ c + k ] = r + h; + } + cursorRow = r; + cursorCol = c + w; + } + + return resolved; +} diff --git a/projects/js-packages/grid/src/dashboard-grid/types.ts b/projects/js-packages/grid/src/dashboard-grid/types.ts new file mode 100644 index 000000000000..690577214250 --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-grid/types.ts @@ -0,0 +1,272 @@ +/** + * Internal dependencies + */ +import type { ResizeSnapSize } from '../shared/resize-snap'; +import type { + DragPreviewRenderProps, + GridOverlayRenderProps, + ResizeDelta, + ResizeHandleRenderProps, +} from '../shared/types'; + +/** + * Dashboard grid layout item definition. + * + * `width` accepts either a numeric column span or a discriminated string: + * - `number` spans that many columns (clamped to the grid's column count). + * - `'fill'` spans the remaining columns in the current row. + * - `'full'` spans all columns (`grid-column: 1 / -1`). + */ +export type DashboardGridLayoutItem = { + /** + * Unique key that matches a child component key. + */ + key: string; + + /** + * Number of columns this item spans, or a string discriminator + * (`'fill'` or `'full'`). + */ + width?: number | 'fill' | 'full'; + + /** + * Number of rows this item spans. + * + * @default 1 + */ + height?: number; + + /** + * Display order for the item. Lower values render first. When + * omitted, the item falls back to its index in the `layout` array. + */ + order?: number; +}; + +/** + * Props for the internal `` wrapper. + */ +export type GridItemProps = { + /** + * The layout item containing grid positioning information. + */ + item: DashboardGridLayoutItem; + + /** + * The maximum number of columns in the grid. + */ + maxColumns: number; + + /** + * Whether drag and resize interactions are disabled. + * + * @default false + */ + disabled?: boolean; + + /** + * Whether the item can be resized vertically. Disabled when the + * grid uses `rowHeight: 'auto'`, where row height is driven by + * content rather than by the user. + * + * @default true + */ + verticalResizable?: boolean; + + /** + * Whether any tile in the grid is currently being dragged or + * resized. Drives the drag activator cursor. + * + * @default false + */ + interacting?: boolean; + + /** + * Whether a tile drag is in progress. Mutes each tile's + * `actionableArea` with `inert` so hovers on other tiles' controls + * do not steal the gesture. + * + * @default false + */ + dragging?: boolean; + + /** + * The content to be displayed within the grid item. + */ + children: React.ReactNode; + + /** + * Content rendered above the draggable area that stays interactive + * in edit mode, typically action buttons, menus, or links. While + * a tile drag is in progress, this content is set `inert` so hovers + * on other tiles can't steal the gesture. During resize, visibility + * is controlled by grid-level CSS hooks. + */ + actionableArea?: React.ReactNode; + + /** + * Callback fired while the item is being resized. Receives the + * item's `key` plus the cursor offset from the gesture start in + * pixels. The grid derives snapped spans from the delta and passes + * them back through `resizeSnapPreview`. + */ + onResize: ( id: string, delta: ResizeDelta ) => void; + + /** + * Snapped grid size in pixels for the resize-preview outline. The + * tile content resizes continuously with the cursor; this outline + * shows the span the layout will commit to on release. + */ + resizeSnapPreview?: ResizeSnapSize | null; + + /** + * Minimum tile width while resizing, in pixels (one column track). + */ + minResizeWidthPx: number; + + /** + * Minimum tile height while resizing, in pixels (one row track). + * Omitted when vertical resize is disabled. + */ + minResizeHeightPx?: number; + + /** + * Callback fired when the resize gesture ends. + */ + onResizeEnd: () => void; + + /** + * Component forwarded to `` to override the default + * corner triangle. See `DashboardGridProps.renderResizeHandle`. + */ + renderResizeHandle?: React.ComponentType< ResizeHandleRenderProps >; +}; + +/** + * Props for `DashboardGrid`. Extends the standard div props so consumers + * can pass `id`, `aria-*`, `data-*`, event handlers, etc., directly on + * the grid root. + * + * `columns` and `minColumnWidth` compose as a layered model: + * - `columns` alone: fixed N columns; each tile scales with the container. + * - `minColumnWidth` alone: column count derives from container width, + * floored by the per-tile minimum, down to 1 column. + * - Both together: `columns` caps the count, `minColumnWidth` enforces a + * per-tile width floor that can reduce the count below the cap on + * narrow containers ("up to N columns, but never narrower than W px"). + */ +export interface DashboardGridProps + extends Omit< React.ComponentPropsWithoutRef< 'div' >, 'children' | 'className' | 'style' > { + /** + * Array of layout items. + */ + layout: DashboardGridLayoutItem[]; + + /** + * Grid children. Each child must carry a `key` that matches an + * entry in `layout`; children without a match render at the end + * of the grid without explicit placement and fall through CSS + * Grid's auto-flow. + */ + children: React.ReactNode; + + /** + * Additional CSS class on the grid root. + */ + className?: string; + + /** + * Inline styles applied to the grid root. Merged underneath the + * grid's own layout styles, so the layout (`gridTemplateColumns`, + * `gridAutoRows`) always wins. The gap between tiles is owned by + * the design-system gap token and is not configurable per + * instance; override it via a theme or density change. + */ + style?: React.CSSProperties; + + /** + * Height of each row in pixels, or `'auto'` to let the tallest + * tile in the row size it. + * + * @default 'auto' + */ + rowHeight?: number | 'auto'; + + /** + * Whether the grid is in edit mode (allows dragging and + * repositioning items). + * + * @default false + */ + editMode?: boolean; + + /** + * Callback fired when the user commits a drag or resize. Receives + * the resulting layout. + */ + onChangeLayout?: ( newLayout: DashboardGridLayoutItem[] ) => void; + + /** + * Callback fired continuously during a drag or resize interaction + * with the in-progress layout. Useful for live feedback in the + * surface (e.g., displaying the current width/position). The final + * committed layout is still emitted via `onChangeLayout`. + */ + onPreviewLayout?: ( previewLayout: DashboardGridLayoutItem[] ) => void; + + /** + * Override the default corner-triangle resize handle with a custom + * component. The grid still owns the gesture (dnd-kit ``, + * throttled delta loop) and passes the wiring to the consumer: + * spread `listeners` and `attributes` and assign `ref` on the + * element that should receive the gesture. Use `disabled` and + * `verticalResizable` to adapt the visual to context. + */ + renderResizeHandle?: React.ComponentType< ResizeHandleRenderProps >; + + /** + * through) and mounts this component inside it; the consumer + * owns the visual chrome (shadow, radius, padding). + * + * When omitted, the cloned children render directly inside the + * functional frame so any chrome the consumer applied to the + * persistent tile carries through unchanged. + * + * Token-only adjustments (lift scale, placeholder opacity, + * outline color, placeholder radius) flow through CSS custom + * properties documented in the README. + */ + renderDragPreview?: React.ComponentType< DragPreviewRenderProps >; + + /** + * Override the default edit-mode overlay (row-marker tiles per + * column) with a custom component. The grid supplies the resolved + * column count, row height, and row count; the consumer is + * responsible for the visual. + * + * The overlay only renders when `editMode` is true. When omitted, + * the package's default visual is used. + */ + renderGridOverlay?: React.ComponentType< GridOverlayRenderProps >; + + /** + * Target column count (cap). When set alone, the grid renders this + * many columns and tiles scale with the container. + * + * Composes with `minColumnWidth`: if both are set, the effective + * column count is `min( columns, fitsAtMinWidth )`. When omitted + * but `minColumnWidth` is set, the count is uncapped and derives + * purely from the container width. When both are omitted, the + * grid renders six columns. + */ + columns?: number; + + /** + * Per-tile minimum width in pixels. The effective column count is + * derived from container width, floored by this value, down to 1. + * + * Composes with `columns`: when both are set, this acts as a floor + * that can reduce the count below `columns` on narrow containers. + */ + minColumnWidth?: number; +} diff --git a/projects/js-packages/grid/src/dashboard-lanes/index.tsx b/projects/js-packages/grid/src/dashboard-lanes/index.tsx new file mode 100644 index 000000000000..818de1a8b5f9 --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-lanes/index.tsx @@ -0,0 +1,561 @@ +/** + * External dependencies + */ +import { + DndContext, + DragOverlay, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; +import { arrayMove, SortableContext, sortableKeyboardCoordinates } from '@dnd-kit/sortable'; +import { useResizeObserver, useEvent, useMergeRefs } from '@wordpress/compose'; +import { + forwardRef, + useMemo, + Children, + cloneElement, + isValidElement, + useLayoutEffect, + useRef, + useState, +} from '@wordpress/element'; +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ + +/** + * Internal dependencies + */ +import { createDashboardDragDropAnimation } from '../shared/drag-overlay-drop-animation'; +import { GridOverlay } from '../shared/grid-overlay'; +import { ItemExitOverlay } from '../shared/item-exit-overlay'; +import layoutAnimationStyles from '../shared/layout-shift-animation.module.css'; +import { gridSpanToPixelSize } from '../shared/resize-snap'; +import { useItemExitAnimation } from '../shared/use-item-exit-animation'; +import { + getLayoutFingerprint, + getPlacementFingerprint, + useLayoutShiftAnimation, +} from '../shared/use-layout-shift-animation'; +import { LanesItem } from './lanes-item'; +import styles from './lanes.module.css'; +import { useLanePlacement } from './use-lane-placement'; +import type { DashboardLanesLayoutItem, DashboardLanesProps } from './types'; +import type { ResizeSnapSize } from '../shared/resize-snap'; +import type { ResizeDelta } from '../shared/types'; +import type { DragMoveEvent, DragStartEvent } from '@dnd-kit/core'; + +const dashboardDragDropAnimation = createDashboardDragDropAnimation( + styles[ 'drag-preview-frame' ], + styles.dragPreviewFrameExiting +); + +// Fallback gap in pixels for math that runs before the computed gap +// can be read from the DOM. Matches the `'xl'` step the surface +// resolves to in CSS (`--wpds-dimension-gap-xl`); the next layout +// effect overwrites this with the actual computed value. +const FALLBACK_GAP_PX = 24; + +// Default lane cap when no explicit `columns` or `minColumnWidth` is +// supplied. Layered semantics: `columns` acts as a cap and +// `minColumnWidth` as a per-tile floor; if neither is set we still +// need a finite count to render against. +const DEFAULT_COLUMNS = 6; + +const NO_SORT_STRATEGY = () => null; + +/** + * Masonry-style surface aligned with `display: grid-lanes`. Items + * declare a column span; heights are driven by content; placement + * follows the source-ordered, shortest-lane algorithm with + * `flow-tolerance` tiebreaking. + * + * On browsers that support `display: grid-lanes` natively, the + * component emits the spec's CSS and lets the engine handle layout. + * Otherwise, `useLanePlacement` measures item heights and assigns + * explicit `grid-column-start` / `grid-row-start` values that + * approximate the same result inside CSS Grid. + * + * Each child's `key` must match an entry in the `layout` array; + * children without a match render at the end of the surface without + * explicit placement and fall through the lanes auto-flow. + * + * @example + * ```jsx + * + * A + * B + * C + * + * ``` + * + * @param props - Component props. + * @param ref - Forwarded to the surface's root `
`. + */ +export const DashboardLanes = forwardRef< HTMLDivElement, DashboardLanesProps >( + function DashboardLanes( props, ref ) { + const { + layout, + columns, + children, + className, + style, + flowTolerance = 16, + rowUnit = 4, + minColumnWidth, + editMode = false, + onChangeLayout, + onPreviewLayout, + renderResizeHandle, + renderDragPreview, + renderGridOverlay, + ...divProps + } = props; + + const [ temporaryLayout, setTemporaryLayout ] = useState< + DashboardLanesLayoutItem[] | undefined + >(); + const [ activeId, setActiveId ] = useState< string | null >( null ); + const [ isResizing, setIsResizing ] = useState( false ); + const [ resizeSnapPreview, setResizeSnapPreview ] = useState< { + id: string; + snap: ResizeSnapSize; + } | null >( null ); + const latestLayoutRef = useRef< DashboardLanesLayoutItem[] | undefined >(); + const lastReorderCursorRef = useRef< { + x: number; + y: number; + } | null >( null ); + const resizeBaselineRef = useRef< number | null >( null ); + const captureLayoutSnapshotRef = useRef< () => void >( () => {} ); + const childrenCacheRef = useRef< Map< string, React.ReactElement > >( new Map() ); + const activeLayout = temporaryLayout ?? layout; + + const [ container, setContainer ] = useState< HTMLDivElement | null >( null ); + const [ containerWidth, setContainerWidth ] = useState( 0 ); + const [ gapPx, setGapPx ] = useState( FALLBACK_GAP_PX ); + const resizeObserverRef = useResizeObserver( ( [ { contentRect } ] ) => { + setContainerWidth( contentRect.width ); + } ); + const mergedRootRef = useMergeRefs( [ setContainer, resizeObserverRef, ref ] ); + + // Measure synchronously before paint and snapshot the computed + // `column-gap` so the placement math tracks the design-system + // token under any density. + useLayoutEffect( () => { + if ( ! container ) { + return; + } + const { width } = container.getBoundingClientRect(); + if ( width > 0 ) { + setContainerWidth( width ); + } + const parsed = Number.parseFloat( window.getComputedStyle( container ).columnGap ); + if ( Number.isFinite( parsed ) && parsed > 0 ) { + setGapPx( parsed ); + } + }, [ container ] ); + const effectiveColumns = useMemo( () => { + if ( ! minColumnWidth ) { + return columns ?? DEFAULT_COLUMNS; + } + const totalWidthPerColumn = minColumnWidth + gapPx; + const maxFit = Math.max( 1, Math.floor( ( containerWidth + gapPx ) / totalWidthPerColumn ) ); + return columns !== undefined ? Math.min( columns, maxFit ) : maxFit; + }, [ minColumnWidth, gapPx, containerWidth, columns ] ); + const columnWidth = ( containerWidth - ( effectiveColumns - 1 ) * gapPx ) / effectiveColumns; + const minResizeWidthPx = gridSpanToPixelSize( 1, 1, columnWidth, gapPx, null ).widthPx; + + const layoutMap = useMemo( () => { + const map = new Map< string, DashboardLanesLayoutItem >(); + activeLayout.forEach( item => map.set( item.key, item ) ); + return map; + }, [ activeLayout ] ); + + // Stable-identity key set for the children walk (see grid.tsx). + const layoutKeys = useMemo( () => new Set( layout.map( item => item.key ) ), [ layout ] ); + + // Sorted item keys, identity-stable when the resulting sequence + // is unchanged (avoids invalidating SortableContext). + const sortedItems = useMemo( + () => + activeLayout + .map( ( item, index ) => ( { item, index } ) ) + .sort( ( a, b ) => ( a.item.order ?? a.index ) - ( b.item.order ?? b.index ) ) + .map( ( { item } ) => item.key ), + [ activeLayout ] + ); + const items = sortedItems; + + // Placement input for the hook: each item with its clamped span + // in source (sorted) order. `lane` forwards the optional explicit + // pin from the layout item; the algorithm clamps out-of-range + // values, so no surface-level guard is needed. + const placementItems = useMemo( () => { + return items.map( key => { + const item = layoutMap.get( key ); + const width = item?.width; + const span = + typeof width === 'number' ? Math.max( 1, Math.min( width, effectiveColumns ) ) : 1; + return { key, span, lane: item?.lane }; + } ); + }, [ items, layoutMap, effectiveColumns ] ); + + const { itemStyles } = useLanePlacement( container, { + items: placementItems, + lanes: effectiveColumns, + gap: gapPx, + flowTolerance, + rowUnit, + } ); + + const [ childrenMap, actionableAreaMap, remaining, renderedByKey ] = useMemo( () => { + const childMap = new Map< string, React.ReactElement >(); + const actionableMap = new Map< string, React.ReactNode >(); + const rest: React.ReactNode[] = []; + const byKey = new Map< string, React.ReactElement >(); + + Children.forEach( children, child => { + if ( ! isValidElement( child ) ) { + rest.push( child ); + return; + } + const key = child.key?.toString(); + if ( ! key ) { + rest.push( child ); + return; + } + + // Strip `actionableArea` so it does not leak to the DOM; + // the grid lifts it to a slot separately. + const { actionableArea } = child.props as { + actionableArea?: React.ReactNode; + }; + const stripped = + actionableArea !== undefined + ? cloneElement( + child as React.ReactElement< { + actionableArea?: React.ReactNode; + } >, + { actionableArea: undefined } + ) + : ( child as React.ReactElement ); + + byKey.set( key, stripped ); + + if ( layoutKeys.has( key ) ) { + if ( actionableArea !== undefined ) { + actionableMap.set( key, actionableArea ); + } + childMap.set( key, stripped ); + } else { + rest.push( child ); + } + } ); + + return [ childMap, actionableMap, rest, byKey ]; + }, [ children, layoutKeys ] ); + + // Persist the latest rendered children so a removed tile's content + // is still available for its exit overlay. Filled from an effect so a + // discarded render never writes to the cache. + useLayoutEffect( () => { + for ( const [ key, child ] of renderedByKey ) { + childrenCacheRef.current.set( key, child ); + } + }, [ renderedByKey ] ); + + const sensors = useSensors( + useSensor( PointerSensor ), + useSensor( KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + } ) + ); + + const handleDragStart = useEvent( ( event: DragStartEvent ) => { + setActiveId( String( event.active.id ) ); + lastReorderCursorRef.current = null; + } ); + + const handleDragCancel = useEvent( () => { + setActiveId( null ); + latestLayoutRef.current = undefined; + lastReorderCursorRef.current = null; + resizeBaselineRef.current = null; + setIsResizing( false ); + setResizeSnapPreview( null ); + setTemporaryLayout( undefined ); + } ); + + const handleDragMove = useEvent( ( event: DragMoveEvent ) => { + const { active, over } = event; + if ( ! over || active.id === over.id ) { + return; + } + const activeRect = active.rect.current.translated; + if ( ! activeRect ) { + return; + } + const activeCenterX = activeRect.left + activeRect.width / 2; + const activeCenterY = activeRect.top + activeRect.height / 2; + + const lastCursor = lastReorderCursorRef.current; + if ( lastCursor ) { + const dx = activeCenterX - lastCursor.x; + const dy = activeCenterY - lastCursor.y; + if ( dx * dx + dy * dy < 100 ) { + return; + } + } + + const overCenterX = over.rect.left + over.rect.width / 2; + const insertAfter = activeCenterX > overCenterX; + + const currentIndex = items.indexOf( String( active.id ) ); + const overIndex = items.indexOf( String( over.id ) ); + let newIndex: number; + if ( insertAfter ) { + newIndex = currentIndex > overIndex ? overIndex + 1 : overIndex; + } else { + newIndex = currentIndex > overIndex ? overIndex : overIndex - 1; + } + newIndex = Math.max( 0, Math.min( newIndex, items.length - 1 ) ); + + if ( newIndex === currentIndex ) { + return; + } + + const updatedItems = arrayMove( items, currentIndex, newIndex ); + // Build a key→index lookup so the .map below is O(n) + // instead of O(n²) from per-item `indexOf` calls. + const orderByKey = new Map< string, number >(); + updatedItems.forEach( ( key, index ) => { + orderByKey.set( key, index ); + } ); + const updatedLayout = activeLayout.map( item => ( { + ...item, + order: orderByKey.get( item.key ) ?? 0, + } ) ); + + lastReorderCursorRef.current = { + x: activeCenterX, + y: activeCenterY, + }; + latestLayoutRef.current = updatedLayout; + captureLayoutSnapshotRef.current(); + setTemporaryLayout( updatedLayout ); + onPreviewLayout?.( updatedLayout ); + } ); + + const persistTemporaryLayout = useEvent( () => { + const latest = latestLayoutRef.current; + latestLayoutRef.current = undefined; + resizeBaselineRef.current = null; + setIsResizing( false ); + setResizeSnapPreview( null ); + if ( ! onChangeLayout || ! latest ) { + setTemporaryLayout( undefined ); + return; + } + + onChangeLayout( latest ); + setTemporaryLayout( undefined ); + } ); + + const handleResize = useEvent( ( id: string, delta: ResizeDelta ) => { + if ( ! editMode ) { + return; + } + if ( ! isResizing ) { + setIsResizing( true ); + } + + const relativeDelta = Math.round( delta.width / ( columnWidth + gapPx ) ); + + if ( resizeBaselineRef.current === null ) { + const baseItem = layoutMap.get( id ); + const baseWidth = typeof baseItem?.width === 'number' ? baseItem.width : 1; + resizeBaselineRef.current = baseWidth; + } + const baseline = resizeBaselineRef.current; + const newWidth = Math.max( 1, Math.min( baseline + relativeDelta, effectiveColumns ) ); + + setResizeSnapPreview( { + id, + snap: gridSpanToPixelSize( newWidth, 1, columnWidth, gapPx, null ), + } ); + + const pendingItem = latestLayoutRef.current?.find( item => item.key === id ); + const currentItem = pendingItem ?? layoutMap.get( id ); + if ( currentItem && currentItem.width === newWidth ) { + return; + } + + const updatedLayout = activeLayout.map( item => + item.key === id ? { ...item, width: newWidth } : item + ); + + latestLayoutRef.current = updatedLayout; + captureLayoutSnapshotRef.current(); + setTemporaryLayout( updatedLayout ); + onPreviewLayout?.( updatedLayout ); + } ); + + const interacting = activeId !== null || isResizing; + + // Drag-overlay clone composition: the surface always wraps with a + // thin functional frame (lift, cursor, pointer pass-through). When + // `renderDragPreview` is supplied, the consumer's wrapper sits + // inside the frame around the cloned children; otherwise the + // cloned children render directly so any persistent chrome on + // them carries through unchanged. + const activeClone = activeId ? childrenMap.get( activeId ) : null; + const DragPreview = renderDragPreview; + const dragOverlayContent = + activeId && activeClone ? ( +
+
+ { DragPreview ? ( + { activeClone } + ) : ( + activeClone + ) } +
+
+ ) : null; + + // Edit-mode background visual. Lanes are content-driven + // vertically, so the overlay only mirrors columns; the default + // can be replaced wholesale via `renderGridOverlay`. Rendered + // unconditionally so the overlay can cross-fade on edit-mode + // toggles; `isActive` drives the opacity transition inside the + // overlay. Memoized so drag/resize re-renders skip + // reconciliation while inputs are stable. + const Overlay = renderGridOverlay ?? GridOverlay; + const gridOverlay = useMemo( + () => , + [ Overlay, editMode, effectiveColumns ] + ); + + const layoutFingerprint = useMemo( () => { + const layoutSig = getLayoutFingerprint( activeLayout ); + const placementSig = getPlacementFingerprint( itemStyles ); + return `${ layoutSig }\0${ placementSig }`; + }, [ activeLayout, itemStyles ] ); + const excludeLayoutAnimationKey = activeId ?? ( isResizing ? resizeSnapPreview?.id : null ); + const { captureLayoutSnapshot, getPositionsBeforeLastChange } = useLayoutShiftAnimation( { + container, + enabled: editMode, + layoutFingerprint, + excludeItemKey: excludeLayoutAnimationKey, + } ); + const { exitingItems, clearExitingItem } = useItemExitAnimation( { + container, + enabled: editMode, + layoutKeys, + getPositionsBeforeLastChange, + childrenCacheRef, + } ); + const layoutAnimating = editMode; + useLayoutEffect( () => { + captureLayoutSnapshotRef.current = captureLayoutSnapshot; + }, [ captureLayoutSnapshot ] ); + + return ( + { + persistTemporaryLayout(); + lastReorderCursorRef.current = null; + setActiveId( null ); + } } + > + +
+ { gridOverlay } + { items.map( id => { + const child = childrenMap.get( id ); + if ( ! child ) { + return null; + } + return ( + + { child } + + ); + } ) } + { remaining } + { exitingItems.map( ( { key, rect, child } ) => ( + clearExitingItem( key ) } + > + { child } + + ) ) } +
+
+ + { dragOverlayContent } + +
+ ); + } +); diff --git a/projects/js-packages/grid/src/dashboard-lanes/lane-placement.ts b/projects/js-packages/grid/src/dashboard-lanes/lane-placement.ts new file mode 100644 index 000000000000..dffff293bf0a --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-lanes/lane-placement.ts @@ -0,0 +1,260 @@ +/** + * Lane placement algorithm for `display: grid-lanes` polyfill. + * + * Implements the source-ordered, shortest-lane placement described in + * https://webkit.org/blog/17660/introducing-css-grid-lanes/. + * + * The skyline + tolerance core is adapted from the CSS Grid Lanes + * Polyfill by Simon Willison (MIT, + * https://tools.simonwillison.net/grid-lanes-polyfill.js). The rest + * of this module is a pure function suitable for unit testing in + * isolation from any DOM. + * + * Concepts: + * - "Lane" is the cross-axis track: a column in waterfall mode, a row + * in brick mode. The algorithm is axis-agnostic; the renderer maps + * the chosen lane index plus offset to `grid-column-start` / + * `grid-row-start` (or vice versa). + * - Items are placed in source order. Explicit-lane items are placed + * first so auto-placed items can flow around them. + * - `flowTolerance` is a length: when two candidate lanes differ in + * baseline by no more than this, the earlier lane wins (preserves + * reading order). + */ + +/** + * A single item to place. Heights are pre-measured by the caller. + */ +export type LanePlacementItem = { + /** + * Stable identity. Returned in the result map. + */ + key: string; + + /** + * Number of contiguous lanes this item occupies. Clamped to + * `[ 1, lanes ]` by the algorithm. + */ + span: number; + + /** + * Measured cross-axis size (typically pixels). The algorithm only + * adds and compares heights; the unit is whatever the caller uses, + * as long as `gap` and `flowTolerance` use the same one. + */ + height: number; + + /** + * Explicit 0-indexed starting lane. When set, the item bypasses + * the skyline lookup and is placed at this lane regardless of + * source order. Out-of-range values are clamped. + */ + lane?: number; +}; + +/** + * Algorithm input. + */ +export type LanePlacementInput = { + /** + * Items in source order. + */ + items: ReadonlyArray< LanePlacementItem >; + + /** + * Total number of lanes. Clamped to `>= 1`. + */ + lanes: number; + + /** + * Gap between items in the same lane. Same unit as `height`. + */ + gap: number; + + /** + * Tolerance for source-order tiebreaking. When two candidate + * lanes have baselines within this amount, the earlier lane wins. + * Defaults to `0` if a negative value is passed. + */ + flowTolerance: number; +}; + +/** + * Resolved position for a single item. + */ +export type LanePlacement = { + /** + * Mirrors the input key. + */ + key: string; + + /** + * 0-indexed starting lane. The renderer adds 1 for + * `grid-column-start`. + */ + lane: number; + + /** + * Cross-axis offset from the container's start edge, in the same + * unit as the input heights. Use as the item's start position + * (e.g. `top`, or `grid-row-start` after dividing by a row unit). + */ + top: number; + + /** + * Effective span after clamping. Useful for the renderer when the + * input span exceeded the lane count. + */ + span: number; +}; + +/** + * Algorithm output. + */ +export type LanePlacementResult = { + /** + * Per-key placement. Insertion-ordered: the first iteration yields + * the explicit items in source order, then the auto items in + * source order. + */ + placements: Map< string, LanePlacement >; + + /** + * Sum of the tallest lane after all items are placed. The renderer + * applies this as the container's intrinsic height. + */ + totalHeight: number; +}; + +/** + * + * @param span + * @param lanes + */ +function clampSpan( span: number, lanes: number ): number { + if ( ! Number.isFinite( span ) ) { + return 1; + } + return Math.max( 1, Math.min( Math.floor( span ), lanes ) ); +} + +/** + * + * @param lane + * @param span + * @param lanes + */ +function clampLane( lane: number, span: number, lanes: number ): number { + if ( ! Number.isFinite( lane ) ) { + return 0; + } + return Math.max( 0, Math.min( Math.floor( lane ), lanes - span ) ); +} + +/** + * + * @param laneBottoms + * @param startLane + * @param span + */ +function maxBaselineAcross( + laneBottoms: ReadonlyArray< number >, + startLane: number, + span: number +): number { + let maxBaseline = 0; + for ( let i = startLane; i < startLane + span; i++ ) { + if ( laneBottoms[ i ] > maxBaseline ) { + maxBaseline = laneBottoms[ i ]; + } + } + return maxBaseline; +} + +/** + * Places all items into a fixed lane count using the grid-lanes + * algorithm: explicit items first, then auto items chosen by the + * shortest-lane skyline with a tolerance for source order. + * + * Pure: no DOM access, no mutation of inputs. Safe to call from a + * worker or during SSR. + * + * @param input - Items, lane count, gap, and tolerance. + * @return Per-key placements plus the resulting total height. + */ +export function computeLanePlacements( input: LanePlacementInput ): LanePlacementResult { + const lanes = Math.max( 1, Math.floor( input.lanes ) ); + const gap = Math.max( 0, input.gap ); + const tolerance = Math.max( 0, input.flowTolerance ); + + const laneBottoms = new Array< number >( lanes ).fill( 0 ); + const placements = new Map< string, LanePlacement >(); + + const explicitItems: LanePlacementItem[] = []; + const autoItems: LanePlacementItem[] = []; + for ( const item of input.items ) { + if ( item.lane !== undefined ) { + explicitItems.push( item ); + } else { + autoItems.push( item ); + } + } + + for ( const item of explicitItems ) { + const span = clampSpan( item.span, lanes ); + const lane = clampLane( item.lane as number, span, lanes ); + const baseline = maxBaselineAcross( laneBottoms, lane, span ); + const top = baseline === 0 ? 0 : baseline + gap; + const height = Math.max( 0, item.height ); + + placements.set( item.key, { key: item.key, lane, top, span } ); + + const newBottom = top + height; + for ( let i = lane; i < lane + span; i++ ) { + laneBottoms[ i ] = newBottom; + } + } + + for ( const item of autoItems ) { + const span = clampSpan( item.span, lanes ); + let bestLane = 0; + let bestBaseline = Infinity; + + for ( let candidate = 0; candidate <= lanes - span; candidate++ ) { + const baseline = maxBaselineAcross( laneBottoms, candidate, span ); + + // Only take a lane that is strictly shorter beyond + // tolerance. Within-tolerance ties keep the earlier lane + // because candidates iterate in lane order, so the first + // acceptable baseline wins. + if ( bestBaseline - baseline > tolerance ) { + bestBaseline = baseline; + bestLane = candidate; + } + } + + const top = bestBaseline === 0 ? 0 : bestBaseline + gap; + const height = Math.max( 0, item.height ); + + placements.set( item.key, { + key: item.key, + lane: bestLane, + top, + span, + } ); + + const newBottom = top + height; + for ( let i = bestLane; i < bestLane + span; i++ ) { + laneBottoms[ i ] = newBottom; + } + } + + let totalHeight = 0; + for ( const bottom of laneBottoms ) { + if ( bottom > totalHeight ) { + totalHeight = bottom; + } + } + + return { placements, totalHeight }; +} diff --git a/projects/js-packages/grid/src/dashboard-lanes/lanes-item.module.css b/projects/js-packages/grid/src/dashboard-lanes/lanes-item.module.css new file mode 100644 index 000000000000..a04e25f93cec --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-lanes/lanes-item.module.css @@ -0,0 +1,98 @@ +.item { + position: relative; +} + +.item-content { + position: relative; + height: 100%; +} + +.is-resizing { + overflow: visible; + z-index: 1; +} + +.is-resizing .item-content { + position: relative; + z-index: 2; + overflow: visible; +} + +/* + * During drag, the original item acts as a placeholder in its lane + * while `` renders a clone that follows the cursor. + * Fading the placeholder and outlining it makes the destination visible + * without any scaling or translation on the original element. + * + * Placeholder chrome waits until `data-wp-grid-dragging` is set and the + * drag-preview enter animation (`--wpds-motion-duration-sm`) finishes + * so the dashed outline does not flash under the lifting clone. + */ +.is-dragging { + pointer-events: none; +} + +:global([data-wp-grid-dragging]) .is-dragging { + border-radius: var(--wp-grid-placeholder-radius, 0); +} + +@media not (prefers-reduced-motion: reduce) { + + :global([data-wp-grid-dragging]) .is-dragging { + opacity: 1; + outline-width: 0; + outline-style: var(--wp-grid-placeholder-outline-style, dashed); + outline-color: transparent; + animation: + wp-grid-item-placeholder-in 0ms linear + var(--wpds-motion-duration-sm) forwards; + } + + @keyframes wp-grid-item-placeholder-in { + + to { + opacity: var(--wp-grid-placeholder-opacity, 0.4); + outline-width: var(--wpds-border-width-sm); + outline-color: var(--wp-grid-placeholder-outline-color, var(--wpds-color-stroke-interactive-brand)); + } + } +} + +@media (prefers-reduced-motion: reduce) { + + :global([data-wp-grid-dragging]) .is-dragging { + opacity: var(--wp-grid-placeholder-opacity, 0.4); + outline: + var(--wpds-border-width-sm) + var(--wp-grid-placeholder-outline-style, dashed) + var(--wp-grid-placeholder-outline-color, var(--wpds-color-stroke-interactive-brand)); + } +} + +@media (forced-colors: active) { + + :global([data-wp-grid-dragging]) .is-dragging { + --wp-grid-placeholder-outline-color: Highlight; + } +} + +.preview-overlay { + position: absolute; + top: 0; + inset-inline-start: 0; + box-sizing: border-box; + pointer-events: none; + z-index: 0; + border: + var(--wpds-border-width-sm) + var(--wp-grid-resize-preview-outline-style, solid) + var(--wp-grid-placeholder-outline-color, var(--wpds-color-stroke-interactive-brand)); + background: transparent; +} + +@media (forced-colors: active) { + + .preview-overlay { + border-color: Highlight; + } +} diff --git a/projects/js-packages/grid/src/dashboard-lanes/lanes-item.tsx b/projects/js-packages/grid/src/dashboard-lanes/lanes-item.tsx new file mode 100644 index 000000000000..cfa0d26b780a --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-lanes/lanes-item.tsx @@ -0,0 +1,241 @@ +/** + * External dependencies + */ +import { useSortable } from '@dnd-kit/sortable'; +import { useMergeRefs } from '@wordpress/compose'; +import { useState, useRef } from '@wordpress/element'; +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ + +/** + * Internal dependencies + */ +import actionableAreaStyles from '../shared/actionable-area-slot.module.css'; +import { GRID_ITEM_DATA_KEY } from '../shared/grid-item-key'; +import ResizeHandle from '../shared/resize-handle'; +import { clampResizeDelta, type ResizeSnapSize } from '../shared/resize-snap'; +import styles from './lanes-item.module.css'; +import type { ResizeDelta, ResizeHandleRenderProps } from '../shared/types'; + +/** + * + * @param disabled + * @param interacting + */ +function getItemCursor( disabled: boolean, interacting: boolean ): React.CSSProperties[ 'cursor' ] { + if ( disabled ) { + return 'default'; + } + if ( interacting ) { + return undefined; + } + return 'grab'; +} + +/** + * Props for the internal `` wrapper. + */ +export type LanesItemProps = { + /** + * Item key. Forwarded to dnd-kit and emitted as the + * `data-wp-grid-item-key` attribute the hook reads to map measured DOM + * nodes back to logical items. + */ + itemKey: string; + + /** + * Inline placement style produced by `useLanePlacement`. On native + * (`display: grid-lanes`), only `gridColumn: span N`. While + * polyfilling, also `gridColumnStart` / `gridRowStart` / + * `gridRowEnd: span N`. + */ + placementStyle: React.CSSProperties; + + /** + * Whether drag and resize interactions are disabled. + */ + disabled?: boolean; + + /** + * Whether any tile in the surface is currently being dragged or + * resized. Drives the drag activator cursor. + */ + interacting?: boolean; + + /** + * Whether a tile drag is in progress. Mutes each tile's + * `actionableArea` with `inert` so hovers on other tiles' controls + * do not steal the gesture. + * + * @default false + */ + dragging?: boolean; + + children: React.ReactNode; + + actionableArea?: React.ReactNode; + + onResize: ( id: string, delta: ResizeDelta ) => void; + + /** + * Snapped column span in pixels for the resize-preview outline. + */ + resizeSnapPreview?: ResizeSnapSize | null; + + /** + * Minimum tile width while resizing, in pixels (one column track). + */ + minResizeWidthPx: number; + + onResizeEnd: () => void; + + renderResizeHandle?: React.ComponentType< ResizeHandleRenderProps >; +}; + +/** + * + * @param root0 + * @param root0.itemKey + * @param root0.placementStyle + * @param root0.disabled + * @param root0.interacting + * @param root0.children + * @param root0.actionableArea + * @param root0.onResize + * @param root0.onResizeEnd + * @param root0.resizeSnapPreview + * @param root0.minResizeWidthPx + * @param root0.renderResizeHandle + * @param root0.dragging + */ +export function LanesItem( { + itemKey, + placementStyle, + disabled = false, + interacting = false, + children, + actionableArea = null, + onResize, + onResizeEnd, + resizeSnapPreview = null, + minResizeWidthPx, + renderResizeHandle, + dragging = false, +}: LanesItemProps ) { + const [ resizeDelta, setResizeDelta ] = useState< ResizeDelta | null >( null ); + const [ initialContentSize, setInitialContentSize ] = useState< { + width: number; + height: number; + } | null >( null ); + const itemRef = useRef< HTMLDivElement >( null ); + const contentRef = useRef< HTMLDivElement >( null ); + + const { attributes, listeners, setNodeRef, setActivatorNodeRef, isDragging } = useSortable( { + id: itemKey, + disabled, + } ); + const mergedRef = useMergeRefs( [ itemRef, setNodeRef ] ); + const contentMergedRef = useMergeRefs( [ contentRef ] ); + + const style: React.CSSProperties = { + ...placementStyle, + alignSelf: 'start', + }; + + const isResizing = resizeDelta !== null; + const itemClassName = clsx( + styles.item, + isDragging && styles[ 'is-dragging' ], + isResizing && styles[ 'is-resizing' ] + ); + + const handleResize = ( delta: ResizeDelta ) => { + const contentNode = contentRef.current; + let baselineSize = initialContentSize; + if ( contentNode && ! baselineSize ) { + const { width, height } = contentNode.getBoundingClientRect(); + baselineSize = { width, height }; + setInitialContentSize( baselineSize ); + } + let clamped: ResizeDelta = { width: delta.width, height: 0 }; + if ( baselineSize ) { + clamped = clampResizeDelta( clamped, baselineSize, { + width: minResizeWidthPx, + } ); + } + setResizeDelta( clamped ); + onResize( itemKey, clamped ); + }; + + const handleResizeEnd = () => { + setResizeDelta( null ); + setInitialContentSize( null ); + onResizeEnd(); + }; + + const continuousContentStyle: React.CSSProperties | undefined = + resizeDelta && initialContentSize + ? { + width: initialContentSize.width + resizeDelta.width, + } + : undefined; + + const previewOverlay = resizeSnapPreview ? ( +
+ ) : null; + + return ( +
+ { actionableArea ? ( +
+
+ { actionableArea } +
+
+ ) : null } + +
+
+ { children } + { ! disabled && ( + + ) } +
+ { previewOverlay } +
+
+ ); +} diff --git a/projects/js-packages/grid/src/dashboard-lanes/lanes.module.css b/projects/js-packages/grid/src/dashboard-lanes/lanes.module.css new file mode 100644 index 000000000000..e6a61911c293 --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-lanes/lanes.module.css @@ -0,0 +1,161 @@ +.lanes { + display: grid-lanes; + column-gap: var(--wp-grid-gap, var(--wpds-dimension-gap-xl)); + row-gap: var(--wp-grid-gap, var(--wpds-dimension-gap-xl)); + position: relative; +} + +/* + * Polyfill fallback. The hook computes per-item `grid-column-start` + * and `grid-row-start`/`grid-row-end: span N` against this row unit. + * The skyline already builds inter-item vertical spacing into each + * tile's `top`, so `row-gap` must be zero here to avoid compounding + * on top of the algorithm's spacing. `grid-auto-flow: dense` is a + * safety net; the algorithm drives placement. + */ +@supports not (display: grid-lanes) { + + .lanes { + display: grid; + grid-auto-rows: var(--wp-grid-lane-row-unit, 4px); + grid-auto-flow: dense; + row-gap: 0; + } +} + +/* + * Functional frame for the drag-preview clone inside ``. + * Always applied, including when the consumer passes a + * `renderDragPreview` wrapper. The outer frame has no `transform` so + * @dnd-kit’s drop translation matches the placeholder; scale lives on + * `__lift` (see dnd-kit #398). Owns elevation, radius, cursor, and + * pointer pass-through. Further chrome belongs to the consumer. Drag + * elevation animates `xs` → `md` so it reads above edit tiles at `xs`. + */ +.drag-preview-frame { + height: 100%; + border-radius: var(--wp-grid-drag-preview-radius, 0); + cursor: grabbing; + pointer-events: none; + box-shadow: var(--wpds-elevation-md); +} + +.drag-preview-frame__lift { + height: 100%; + transform: scale(var(--wp-grid-drag-preview-scale, 1.05)); + transform-origin: center; +} + +@media not (prefers-reduced-motion: reduce) { + + .drag-preview-frame { + animation: + wp-grid-drag-preview-shadow-enter + var(--wpds-motion-duration-sm) var(--wpds-motion-easing-balanced) both; + } + + .drag-preview-frame__lift { + animation: + wp-grid-drag-preview-scale-enter + var(--wpds-motion-duration-sm) var(--wpds-motion-easing-balanced) both; + } +} + +@media not (prefers-reduced-motion: reduce) { + + @keyframes wp-grid-drag-preview-shadow-enter { + + from { + box-shadow: var(--wpds-elevation-xs); + } + + to { + box-shadow: var(--wpds-elevation-md); + } + } + + @keyframes wp-grid-drag-preview-scale-enter { + + from { + transform: scale(1); + } + + to { + transform: scale(var(--wp-grid-drag-preview-scale, 1.05)); + } + } +} + +/* + * Applied by @dnd-kit `DragOverlay` drop side-effects while the + * default overlay transform runs; duration matches + * `createDashboardDragDropAnimation` (200ms / md token). Use keyframed + * exit (not transition) so scale does not snap when the enter animation + * is replaced. + */ +@media not (prefers-reduced-motion: reduce) { + + .drag-preview-frame.dragPreviewFrameExiting { + animation: + wp-grid-drag-preview-shadow-exit + var(--wpds-motion-duration-md) var(--wpds-motion-easing-balanced) + forwards; + } + + .drag-preview-frame.dragPreviewFrameExiting .drag-preview-frame__lift { + animation: + wp-grid-drag-preview-scale-exit + var(--wpds-motion-duration-md) var(--wpds-motion-easing-balanced) + forwards; + } + + @keyframes wp-grid-drag-preview-shadow-exit { + + from { + box-shadow: var(--wpds-elevation-md); + } + + to { + box-shadow: var(--wpds-elevation-xs); + } + } + + @keyframes wp-grid-drag-preview-scale-exit { + + from { + transform: scale(var(--wp-grid-drag-preview-scale, 1.05)); + } + + to { + transform: scale(1); + } + } +} + +.drag-preview-frame.dragPreviewFrameExiting { + box-shadow: var(--wpds-elevation-xs); +} + +.drag-preview-frame.dragPreviewFrameExiting .drag-preview-frame__lift { + transform: scale(1); +} + +@media (prefers-reduced-motion: reduce) { + + .drag-preview-frame { + box-shadow: var(--wpds-elevation-md); + } + + .drag-preview-frame__lift { + transform: none; + } + + .drag-preview-frame.dragPreviewFrameExiting { + box-shadow: var(--wpds-elevation-xs); + transition: none; + } + + .drag-preview-frame.dragPreviewFrameExiting .drag-preview-frame__lift { + transition: none; + } +} diff --git a/projects/js-packages/grid/src/dashboard-lanes/types.ts b/projects/js-packages/grid/src/dashboard-lanes/types.ts new file mode 100644 index 000000000000..646d39510875 --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-lanes/types.ts @@ -0,0 +1,180 @@ +/** + * Internal dependencies + */ +import type { + DragPreviewRenderProps, + GridOverlayRenderProps, + ResizeHandleRenderProps, +} from '../shared/types'; + +/** + * Lanes layout item definition. + * + * Mirrors the public surface of `display: grid-lanes`: column span, + * an optional pinned lane, and an optional source order. Heights are + * content-driven; there is no `height` field. There is no `'fill'` + * (lanes pack their items by skyline; nothing is "left over"). + * `'full'` is expressed by setting `width` to the lane count. + */ +export type DashboardLanesLayoutItem = { + /** + * Unique key that matches a child component key. + */ + key: string; + + /** + * Number of lanes this item spans (`grid-column: span N`). Clamped + * to the surface's lane count. + * + * @default 1 + */ + width?: number; + + /** + * Pin the item to a specific 0-indexed lane. Pinned items are + * placed before auto items, so the auto flow runs around them. + * Out-of-range values (negative, or beyond `columns - width`) are + * clamped to the available range. + */ + lane?: number; + + /** + * Display order. Lower values render first. When omitted, the + * item falls back to its index in the `layout` array. + */ + order?: number; +}; + +/** + * Props for `DashboardLanes`. + * + * `columns` and `minColumnWidth` compose as a layered model: + * - `columns` alone: fixed N lanes; tiles scale with the container. + * - `minColumnWidth` alone: lane count derives from container width, + * floored by the per-tile minimum, down to 1. + * - Both together: `columns` caps the count, `minColumnWidth` enforces + * a per-tile width floor that can reduce the count below the cap. + */ +export interface DashboardLanesProps + extends Omit< React.ComponentPropsWithoutRef< 'div' >, 'children' | 'className' | 'style' > { + /** + * Array of layout items. + */ + layout: DashboardLanesLayoutItem[]; + + /** + * Surface children. Each child must carry a `key` matching an + * entry in `layout`; children without a match render at the end + * of the surface without explicit placement and fall through the + * lanes auto-flow. + */ + children: React.ReactNode; + + /** + * Additional CSS class on the surface root. + */ + className?: string; + + /** + * Inline styles on the surface root. Merged underneath the + * surface's own layout styles, so `display` and + * `gridTemplateColumns` always win. The gap between tiles is + * owned by the design-system gap token and is not configurable + * per instance; override it via a theme or density change. + */ + style?: React.CSSProperties; + + /** + * `flow-tolerance` value in pixels. When two candidate lanes + * differ in baseline by no more than this, the earlier lane wins + * to preserve source order. Larger values keep tiles closer to + * reading order at the cost of bigger empty regions. + * + * @default 16 + */ + flowTolerance?: number; + + /** + * Snap unit for the polyfill's `grid-row-start` / `grid-row-end: + * span N` math. Smaller values produce sharper placement at the + * cost of a larger implicit row count. Ignored on browsers with + * native `display: grid-lanes` support. + * + * @default 4 + */ + rowUnit?: number; + + /** + * Whether the surface is in edit mode (drag-to-reorder, resize). + * + * @default false + */ + editMode?: boolean; + + /** + * Fired when the user commits a drag or resize. + */ + onChangeLayout?: ( newLayout: DashboardLanesLayoutItem[] ) => void; + + /** + * Fired continuously during a gesture with the in-progress + * layout. The committed result still emits via `onChangeLayout`. + */ + onPreviewLayout?: ( previewLayout: DashboardLanesLayoutItem[] ) => void; + + /** + * Override the default corner resize handle. See `DashboardGrid` + * for the full contract; on lanes the handle is horizontal-only + * because heights are content-driven. + */ + renderResizeHandle?: React.ComponentType< ResizeHandleRenderProps >; + + /** + * Custom wrapper for the dragged-clone visual mounted inside + * ``. The surface always wraps the clone with a thin + * functional frame (lift scale, grabbing cursor, pointer pass- + * through) and mounts this component inside it; the consumer + * owns the visual chrome (shadow, radius, padding). + * + * When omitted, the cloned children render directly inside the + * functional frame so any chrome the consumer applied to the + * persistent tile carries through unchanged. + * + * Token-only adjustments (lift scale, placeholder opacity, + * outline color, placeholder radius) flow through CSS custom + * properties documented in the README. + */ + renderDragPreview?: React.ComponentType< DragPreviewRenderProps >; + + /** + * Override the default edit-mode overlay (empty column tracks) with + * a custom component. Lanes are content-driven vertically, so no + * `rowHeight` or `rows` is supplied and the default visual paints + * columns only. + * + * The overlay only renders when `editMode` is true. When omitted, + * the package's default visual is used. + */ + renderGridOverlay?: React.ComponentType< GridOverlayRenderProps >; + + /** + * Target lane count (cap). When set alone, the surface renders + * this many lanes and tiles scale with the container. + * + * Composes with `minColumnWidth`: if both are set, the effective + * lane count is `min( columns, fitsAtMinWidth )`. When omitted but + * `minColumnWidth` is set, the count is uncapped and derives purely + * from container width. When both are omitted, the surface + * renders six lanes. + */ + columns?: number; + + /** + * Per-tile minimum width in pixels. The effective lane count is + * derived from container width, floored by this value, down to 1. + * + * Composes with `columns`: when both are set, this acts as a floor + * that can reduce the count below `columns` on narrow containers. + */ + minColumnWidth?: number; +} diff --git a/projects/js-packages/grid/src/dashboard-lanes/use-lane-placement.ts b/projects/js-packages/grid/src/dashboard-lanes/use-lane-placement.ts new file mode 100644 index 000000000000..bcd8f935012b --- /dev/null +++ b/projects/js-packages/grid/src/dashboard-lanes/use-lane-placement.ts @@ -0,0 +1,296 @@ +/** + * WordPress dependencies + */ +import { useState, useLayoutEffect, useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { GRID_ITEM_DATA_KEY } from '../shared/grid-item-key'; +import { computeLanePlacements } from './lane-placement'; + +const DEFAULT_ROW_UNIT = 4; + +/** + * + */ +function supportsGridLanes(): boolean { + if ( typeof CSS === 'undefined' || ! CSS.supports ) { + return false; + } + return CSS.supports( 'display', 'grid-lanes' ); +} + +/** + * + * @param span + */ +function clampSpan( span: number | undefined ): number { + if ( typeof span !== 'number' || ! Number.isFinite( span ) ) { + return 1; + } + return Math.max( 1, Math.floor( span ) ); +} + +/** + * Logical item passed to the hook. The renderer is responsible for + * mounting a DOM node with `data-wp-grid-item-key={ item.key }` for each + * entry; the hook will measure that node and produce inline styles. + */ +export type LaneItemInput = { + key: string; + span?: number; + lane?: number; +}; + +export type UseLanePlacementInput = { + items: ReadonlyArray< LaneItemInput >; + lanes: number; + gap: number; + flowTolerance: number; + /** + * Snap unit for `grid-row-start` / `grid-row-end: span N` math. + * Smaller values produce sharper placement at the cost of more + * implicit rows. Defaults to 4 (px). + */ + rowUnit?: number; +}; + +export type UseLanePlacementResult = { + /** + * Inline styles to apply to each item, keyed by item key. On + * native (`display: grid-lanes`), entries carry only + * `gridColumn: span N`; the browser handles row placement. While + * polyfilling, entries also carry explicit `grid-column-start` / + * `grid-row-*` values. + */ + itemStyles: Map< string, React.CSSProperties >; + + /** + * `false` when the host browser supports `display: grid-lanes` + * natively. The hook avoids mounting any observers in that case. + */ + isPolyfilled: boolean; +}; + +/** + * Hook that measures item heights and resolves their placement when + * `display: grid-lanes` is unavailable, falling through to a no-op + * pass when the host browser supports the feature natively. + * + * Usage from the renderer: + * + * ```tsx + * const [ container, setContainer ] = useState< HTMLDivElement | null >( null ); + * const { itemStyles } = useLanePlacement( container, { + * items: layout, + * lanes: columns, + * gap: gapPx, + * flowTolerance: 16, + * } ); + * + * return ( + *
+ * { items.map( ( item ) => ( + *
+ * { ... } + *
+ * ) ) } + *
+ * ); + * ``` + * + * @param container - HTMLElement (or null pre-mount) hosting the items. + * @param input - Logical items, lane count, gap, and tuning. + * @return Per-item styles plus the `isPolyfilled` flag. + */ +export function useLanePlacement( + container: HTMLElement | null, + input: UseLanePlacementInput +): UseLanePlacementResult { + // Detect once at mount. SSR returns `true` (CSS undefined); the + // client-first render returns the real value. Either path produces + // the same DOM until the polyfill effect runs (both emit + // span-only styles), so there is no hydration mismatch. + const [ isPolyfilled ] = useState( () => ! supportsGridLanes() ); + + const [ itemStyles, setItemStyles ] = useState< Map< string, React.CSSProperties > >( + () => new Map() + ); + + // Native pass-through: items only need their column span; the + // browser handles row placement. Memoized so a stable items + // array yields a stable Map identity. + const nativeStyles = useMemo( () => { + const map = new Map< string, React.CSSProperties >(); + for ( const item of input.items ) { + map.set( item.key, { + gridColumn: `span ${ clampSpan( item.span ) }`, + } ); + } + return map; + }, [ input.items ] ); + + // Stable signature of items for deps. Keys, spans, and explicit + // lanes are the only fields that influence observer wiring or + // placement, so we hash exactly those. + const itemsSignature = useMemo( () => { + return input.items + .map( item => `${ item.key }/${ item.span ?? 1 }/${ item.lane ?? '' }` ) + .join( '\0' ); + }, [ input.items ] ); + + // Stable array identity while placement-relevant fields match + // `itemsSignature`, so the layout effect is not torn down on every + // parent re-render that passes a fresh `items` reference. + // eslint-disable-next-line react-hooks/exhaustive-deps -- `itemsSignature` encodes keys/spans/lanes; `input.items` reference often changes without placement changes. + const itemsForPlacement = useMemo( () => input.items, [ itemsSignature ] ); + + const { lanes, gap, flowTolerance, rowUnit } = input; + + useLayoutEffect( () => { + if ( ! isPolyfilled || ! container ) { + return; + } + if ( typeof ResizeObserver === 'undefined' ) { + return; + } + + const heights = new Map< string, number >(); + const observed = new Set< Element >(); + let cancelled = false; + let rafId: number | null = null; + + const recompute = () => { + if ( rafId !== null || cancelled ) { + return; + } + // One layout per frame even when ResizeObserver and + // MutationObserver fire in the same tick. + rafId = requestAnimationFrame( () => { + rafId = null; + if ( cancelled ) { + return; + } + const itemsWithHeight = itemsForPlacement.map( item => ( { + key: item.key, + span: clampSpan( item.span ), + lane: item.lane, + height: heights.get( item.key ) ?? 0, + } ) ); + const result = computeLanePlacements( { + items: itemsWithHeight, + lanes, + gap, + flowTolerance, + } ); + const effectiveRowUnit = Math.max( 1, rowUnit ?? DEFAULT_ROW_UNIT ); + const next = new Map< string, React.CSSProperties >(); + for ( const item of itemsForPlacement ) { + const placement = result.placements.get( item.key ); + if ( ! placement ) { + continue; + } + const height = heights.get( item.key ) ?? 0; + const rowStart = Math.floor( placement.top / effectiveRowUnit ) + 1; + const rowSpan = Math.max( 1, Math.ceil( height / effectiveRowUnit ) ); + next.set( item.key, { + gridColumnStart: placement.lane + 1, + gridColumnEnd: `span ${ placement.span }`, + gridRowStart: rowStart, + gridRowEnd: `span ${ rowSpan }`, + } ); + } + setItemStyles( next ); + } ); + }; + + const resizeObserver = new ResizeObserver( entries => { + let changed = false; + for ( const entry of entries ) { + const key = ( entry.target as HTMLElement ).getAttribute( GRID_ITEM_DATA_KEY ); + if ( ! key ) { + continue; + } + const newHeight = entry.contentRect.height; + if ( heights.get( key ) !== newHeight ) { + heights.set( key, newHeight ); + changed = true; + } + } + if ( changed ) { + recompute(); + } + } ); + + const refreshObserved = () => { + const current = container.querySelectorAll( `[${ GRID_ITEM_DATA_KEY }]` ); + for ( const element of current ) { + if ( ! observed.has( element ) ) { + observed.add( element ); + resizeObserver.observe( element ); + const key = element.getAttribute( GRID_ITEM_DATA_KEY ); + if ( key ) { + const rect = ( element as HTMLElement ).getBoundingClientRect(); + heights.set( key, rect.height ); + } + } + } + for ( const element of observed ) { + if ( ! container.contains( element ) ) { + resizeObserver.unobserve( element ); + observed.delete( element ); + } + } + }; + + // Children may mount, unmount, or change `data-wp-grid-item-key` + // after the container exists (drag reorders, additions). The + // mutation observer keeps the observed set in sync. + const mutationObserver = + typeof MutationObserver !== 'undefined' + ? new MutationObserver( () => { + refreshObserved(); + recompute(); + } ) + : null; + if ( mutationObserver ) { + mutationObserver.observe( container, { + childList: true, + subtree: true, + attributes: true, + attributeFilter: [ GRID_ITEM_DATA_KEY ], + } ); + } + + refreshObserved(); + recompute(); + + return () => { + cancelled = true; + if ( rafId !== null ) { + cancelAnimationFrame( rafId ); + } + resizeObserver.disconnect(); + mutationObserver?.disconnect(); + }; + }, [ container, isPolyfilled, lanes, gap, flowTolerance, rowUnit, itemsForPlacement ] ); + + if ( ! isPolyfilled ) { + return { itemStyles: nativeStyles, isPolyfilled: false }; + } + if ( itemStyles.size === 0 ) { + // Pre-measurement frame: emit native-shape styles so items + // appear in their default span rather than collapsing to 1 + // column at the top-left. + return { + itemStyles: nativeStyles as Map< string, React.CSSProperties >, + isPolyfilled: true, + }; + } + return { itemStyles, isPolyfilled: true }; +} diff --git a/projects/js-packages/grid/src/index.ts b/projects/js-packages/grid/src/index.ts new file mode 100644 index 000000000000..39f4f3cb6dcc --- /dev/null +++ b/projects/js-packages/grid/src/index.ts @@ -0,0 +1,11 @@ +export { DashboardGrid } from './dashboard-grid'; +export { DashboardLanes } from './dashboard-lanes'; + +export type { DashboardGridLayoutItem, DashboardGridProps } from './dashboard-grid/types'; +export type { DashboardLanesLayoutItem, DashboardLanesProps } from './dashboard-lanes/types'; +export type { + DragPreviewRenderProps, + GridOverlayRenderProps, + ResizeDelta, + ResizeHandleRenderProps, +} from './shared/types'; diff --git a/projects/js-packages/grid/src/shared/actionable-area-slot.module.css b/projects/js-packages/grid/src/shared/actionable-area-slot.module.css new file mode 100644 index 000000000000..dfc85b41559b --- /dev/null +++ b/projects/js-packages/grid/src/shared/actionable-area-slot.module.css @@ -0,0 +1,17 @@ +.actionable-area-slot { + opacity: 1; +} + +@media (prefers-reduced-motion: no-preference) { + + .actionable-area-slot { + transition: + opacity var(--wpds-motion-duration-md) + var(--wpds-motion-easing-subtle); + } +} + +:global([data-wp-grid-resizing]) .actionable-area-slot { + opacity: 0; + pointer-events: none; +} diff --git a/projects/js-packages/grid/src/shared/drag-overlay-drop-animation.ts b/projects/js-packages/grid/src/shared/drag-overlay-drop-animation.ts new file mode 100644 index 000000000000..85e20b0073b3 --- /dev/null +++ b/projects/js-packages/grid/src/shared/drag-overlay-drop-animation.ts @@ -0,0 +1,61 @@ +/** + * External dependencies + */ +import { defaultDropAnimation, defaultDropAnimationSideEffects } from '@dnd-kit/core'; +import type { DropAnimation } from '@dnd-kit/core'; + +/** Matches `--wpds-motion-duration-md` on the drag preview frame exit. */ +export const DROP_ANIMATION_DURATION_MS = 200; + +/** Matches `--wpds-motion-easing-balanced` on the drag preview frame exit. */ +const DROP_ANIMATION_EASING = 'cubic-bezier(0.4, 0, 0.2, 1)'; + +/** + * Composes @dnd-kit/core’s default overlay drop translation with preview + * exit keyframes (via side effects). When the pointer never moves, @dnd-kit + * skips the drop animation and these side effects do not run. + * + * @param dragPreviewFrameClassName - Hashed class for `.drag-preview-frame`. + * @param exitingFrameClassName - Hashed class for the exit state. + */ +export function createDashboardDragDropAnimation( + dragPreviewFrameClassName: string, + exitingFrameClassName: string +): DropAnimation { + return { + ...defaultDropAnimation, + duration: DROP_ANIMATION_DURATION_MS, + easing: DROP_ANIMATION_EASING, + sideEffects( args ) { + const cleanupDefault = defaultDropAnimationSideEffects( { + styles: { + active: { + opacity: '0', + }, + }, + } )( args ); + + const frame = args.dragOverlay.node.getElementsByClassName( + dragPreviewFrameClassName + )[ 0 ] as HTMLElement | undefined; + + if ( frame ) { + frame.getAnimations().forEach( animation => animation.cancel() ); + const lift = frame.firstElementChild; + if ( lift instanceof HTMLElement ) { + lift.getAnimations().forEach( animation => animation.cancel() ); + } + frame.classList.add( exitingFrameClassName ); + } + + return () => { + if ( typeof cleanupDefault === 'function' ) { + cleanupDefault(); + } + if ( frame ) { + frame.classList.remove( exitingFrameClassName ); + } + }; + }, + }; +} diff --git a/projects/js-packages/grid/src/shared/grid-item-key.ts b/projects/js-packages/grid/src/shared/grid-item-key.ts new file mode 100644 index 000000000000..33f3569a9e3a --- /dev/null +++ b/projects/js-packages/grid/src/shared/grid-item-key.ts @@ -0,0 +1,5 @@ +/** + * Data attribute grid tiles declare so layout-shift animation can map + * measured DOM nodes back to logical item keys. + */ +export const GRID_ITEM_DATA_KEY = 'data-wp-grid-item-key'; diff --git a/projects/js-packages/grid/src/shared/grid-overlay.module.css b/projects/js-packages/grid/src/shared/grid-overlay.module.css new file mode 100644 index 000000000000..d3b84a65af00 --- /dev/null +++ b/projects/js-packages/grid/src/shared/grid-overlay.module.css @@ -0,0 +1,85 @@ +.overlay { + position: absolute; + inset: 0; + display: grid; + gap: var(--wp-grid-gap, var(--wpds-dimension-gap-xl)); + pointer-events: none; + opacity: 0; + visibility: hidden; +} + +.overlay.is-active { + opacity: 1; + visibility: visible; +} + +/* + * Alpha wave: row-marker tiles (or column tracks on lanes) reveal in a + * diagonal sweep from the top-left using staggered delays. + */ +@media not (prefers-reduced-motion) { + + .overlay.is-active .row, + .overlay.is-active:not(.has-rows) .column { + opacity: 0; + transform: scale(0.64); + animation: + grid-overlay-tile-in + var(--wpds-motion-duration-md) var(--wpds-motion-easing-subtle) + both; + animation-delay: calc(var(--wp-grid-overlay-wave-delay-step, 28ms) * (var(--wp-grid-overlay-column-index, 0) + var(--wp-grid-overlay-row-index, 0))); + } + + @keyframes grid-overlay-tile-in { + + to { + opacity: 1; + transform: scale(1); + } + } + + .overlay:not(.is-active) { + transition: + opacity var(--wpds-motion-duration-sm) + var(--wpds-motion-easing-subtle), + visibility 0s linear var(--wpds-motion-duration-sm); + } + + .overlay:not(.is-active) .row, + .overlay:not(.is-active) .column { + animation: none; + transform: none; + } +} + +@media (prefers-reduced-motion: reduce) { + + .overlay { + transition: + opacity var(--wpds-motion-duration-sm) + var(--wpds-motion-easing-subtle), + visibility 0s linear var(--wpds-motion-duration-sm); + } + + .overlay.is-active { + transition: + opacity var(--wpds-motion-duration-sm) + var(--wpds-motion-easing-subtle), + visibility 0s linear 0s; + } +} + +.column { + display: flex; + flex-direction: column; + gap: var(--wp-grid-gap, var(--wpds-dimension-gap-xl)); + min-width: 0; +} + +.row { + flex: 0 0 var(--wp-grid-overlay-row-height); + height: var(--wp-grid-overlay-row-height); + box-sizing: border-box; + border-radius: var(--wpds-border-radius-lg); + background-color: var(--wp-grid-overlay-tile-bg, var(--wpds-color-bg-surface-neutral-weak)); +} diff --git a/projects/js-packages/grid/src/shared/grid-overlay.tsx b/projects/js-packages/grid/src/shared/grid-overlay.tsx new file mode 100644 index 000000000000..755ba828c81d --- /dev/null +++ b/projects/js-packages/grid/src/shared/grid-overlay.tsx @@ -0,0 +1,102 @@ +/** + * External dependencies + */ +import { useEffect, useState } from '@wordpress/element'; +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ + +/** + * Internal dependencies + */ +import styles from './grid-overlay.module.css'; +import type { GridOverlayRenderProps } from './types'; + +/** + * Default edit-mode overlay. Renders one column per track; when + * `rowHeight` and `rows` are supplied, each column holds that many + * row-marker tiles sized to the uniform row height. + * + * Used by both `DashboardGrid` and `DashboardLanes`. Replaced wholesale + * by passing a `renderGridOverlay` to either surface; themed in place + * via the CSS custom properties documented in the package README. + * + * Reveals with a diagonal alpha wave from the top-left corner when + * `isActive` becomes true (motion design tokens for duration and + * easing). Fades out on deactivate; while inactive, `visibility: + * hidden` releases paint cost. + * + * The overlay inherits its gap from the same design-system gap token + * the surfaces use, so columns and row markers stay pixel-aligned + * without the surface having to forward a `spacing` value. + * + * @param props - Render props supplied by the surface. + * @param props.columns - Number of column tracks to mirror. + * @param props.rowHeight - Row height in pixels for surfaces with uniform + * rows. Omitted on lane surfaces or auto-sized + * grids; in that case row markers are skipped. + * @param props.rows - Number of row tracks to mirror in each column. + * Omitted when row height is unknown. + * @param props.isActive - When `false`, the overlay fades out and stops + * consuming paint cost. + */ +export function GridOverlay( { columns, rowHeight, rows, isActive }: GridOverlayRenderProps ) { + const showRows = typeof rowHeight === 'number' && typeof rows === 'number' && rows > 0; + // Bump the key when edit mode activates so CSS animations restart on + // each enter (the overlay stays mounted across toggles). + const [ waveKey, setWaveKey ] = useState( 0 ); + useEffect( () => { + if ( isActive ) { + setWaveKey( key => key + 1 ); + } + }, [ isActive ] ); + const style: React.CSSProperties = { + gridTemplateColumns: `repeat(${ columns }, minmax(0, 1fr))`, + ...( showRows + ? ( { + '--wp-grid-overlay-row-height': `${ rowHeight }px`, + } as React.CSSProperties ) + : {} ), + }; + + return ( +
+ { Array.from( { length: columns }, ( _column, columnIndex ) => ( +
+ { showRows && + Array.from( { length: rows }, ( _row, rowIndex ) => ( +
+ ) ) } +
+ ) ) } +
+ ); +} diff --git a/projects/js-packages/grid/src/shared/item-exit-animation.module.css b/projects/js-packages/grid/src/shared/item-exit-animation.module.css new file mode 100644 index 000000000000..5bf0fbe9ff5e --- /dev/null +++ b/projects/js-packages/grid/src/shared/item-exit-animation.module.css @@ -0,0 +1,53 @@ +/* + * Absolutely positioned clone of a removed tile. Siblings reflow via + * FLIP while this overlay scales down and fades out. + */ +.exit-overlay { + position: absolute; + pointer-events: none; + z-index: 2; + overflow: hidden; + transform-origin: center center; + opacity: 1; + transform: scale(1); +} + +@media not (prefers-reduced-motion: reduce) { + + .exit-overlay { + animation: + wp-grid-item-exit-opacity var(--wpds-motion-duration-md) + var(--wpds-motion-easing-subtle) forwards, + wp-grid-item-exit-scale var(--wpds-motion-duration-md) + var(--wpds-motion-easing-balanced) forwards; + } +} + +@keyframes wp-grid-item-exit-opacity { + + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +@keyframes wp-grid-item-exit-scale { + + from { + transform: scale(1); + } + + to { + transform: scale(0.88); + } +} + +@media (prefers-reduced-motion: reduce) { + + .exit-overlay { + display: none; + } +} diff --git a/projects/js-packages/grid/src/shared/item-exit-overlay.tsx b/projects/js-packages/grid/src/shared/item-exit-overlay.tsx new file mode 100644 index 000000000000..989466956131 --- /dev/null +++ b/projects/js-packages/grid/src/shared/item-exit-overlay.tsx @@ -0,0 +1,54 @@ +/** + * Internal dependencies + */ +import { GRID_ITEM_DATA_KEY } from './grid-item-key'; +import exitStyles from './item-exit-animation.module.css'; +import type { RectSnapshot } from './use-layout-shift-animation'; + +export type ItemExitOverlayRect = Pick< RectSnapshot, 'left' | 'top' | 'width' | 'height' >; + +export type ItemExitOverlayProps = { + itemKey: string; + rect: ItemExitOverlayRect; + children: React.ReactNode; + onAnimationEnd: () => void; +}; + +/** + * Ghost tile shown at the removed item's last position while siblings + * reflow. Not a sortable grid cell — only visual exit feedback. + * + * @param root0 - Component props. + * @param root0.itemKey - Layout key of the removed tile. + * @param root0.rect - Last bounds relative to the grid surface. + * @param root0.children - Cached tile content to render in the ghost. + * @param root0.onAnimationEnd - Called when the exit animation finishes. + */ +export function ItemExitOverlay( { + itemKey, + rect, + children, + onAnimationEnd, +}: ItemExitOverlayProps ) { + return ( +
{ + if ( event.target !== event.currentTarget ) { + return; + } + onAnimationEnd(); + } } + > + { children } +
+ ); +} diff --git a/projects/js-packages/grid/src/shared/layout-shift-animation.module.css b/projects/js-packages/grid/src/shared/layout-shift-animation.module.css new file mode 100644 index 000000000000..54168ec00a88 --- /dev/null +++ b/projects/js-packages/grid/src/shared/layout-shift-animation.module.css @@ -0,0 +1,17 @@ +/* + * Sibling tile reflow during drag/resize/remove in edit mode. Transition + * lives on tiles so the browser can interpolate `transform` reliably + * (inline `transition` + FLIP in the same frame is skipped). + */ +.layout-animating :global([data-wp-grid-item-key]) { + transition: + transform var(--wpds-motion-duration-md) + var(--wpds-motion-easing-balanced); +} + +@media (prefers-reduced-motion: reduce) { + + .layout-animating :global([data-wp-grid-item-key]) { + transition: none; + } +} diff --git a/projects/js-packages/grid/src/shared/resize-handle.module.css b/projects/js-packages/grid/src/shared/resize-handle.module.css new file mode 100644 index 000000000000..3053d43e0754 --- /dev/null +++ b/projects/js-packages/grid/src/shared/resize-handle.module.css @@ -0,0 +1,91 @@ +/* + * Fade with opacity only: `visibility` is not interpolatable and pairing + * it with delayed transitions breaks fade-in. + */ +.resize-handle-slot { + opacity: 1; +} + +@media (prefers-reduced-motion: no-preference) { + + .resize-handle-slot { + transition: + opacity var(--wpds-motion-duration-md) + var(--wpds-motion-easing-subtle); + } +} + +/* + * Grid-level interaction hooks (`data-wp-grid-dragging`, + * `data-wp-grid-resizing`, `data-wp-grid-item-resizing`) drive + * handle visibility. + */ +:global([data-wp-grid-dragging]) .resize-handle-slot, +:global([data-wp-grid-resizing]) .resize-handle-slot { + opacity: 0; + pointer-events: none; +} + +:global([data-wp-grid-resizing]) +:global([data-wp-grid-item-resizing]) +.resize-handle-slot { + opacity: 1; + pointer-events: auto; +} + +.resize-handle { + position: absolute; + bottom: 0; + inset-inline-end: 0; + width: 0; + height: 0; + z-index: 1; + cursor: nwse-resize; + + /* + * Triangle drawn via borders. Use per-side logical shorthands + * instead of `border-width: 0` + `border-block-end-width: 12px`: + * the build's CSS optimizer merges the global shorthands into a + * single `border: 0 solid transparent` and emits it AFTER the + * logical longhands, which then loses the cascade and zeroes + * the triangle widths. The unused sides default to + * `border-style: none` and render as 0 regardless of width. + */ + border-block-end: 12px solid var(--wpds-color-fg-interactive-brand); + border-inline-start: 12px solid transparent; +} + +/* + * When the host surface only resizes horizontally (e.g. lanes, + * where height is content-driven), the corner triangle advertises a + * vertical drag the user cannot perform. Override with a vertical + * grip centered on the trailing edge. + */ +.is-horizontal-only { + cursor: ew-resize; + border-style: none; + bottom: auto; + top: 50%; + transform: translateY(-50%); + width: 16px; + height: 40px; + background: transparent; + display: flex; + align-items: center; + justify-content: center; +} + +.is-horizontal-only::before { + content: ""; + width: 4px; + height: 24px; + border-radius: 2px; + background-color: var(--wpds-color-fg-interactive-brand); +} + +@media (forced-colors: active) { + + .is-horizontal-only::before { + background-color: Highlight; + } +} diff --git a/projects/js-packages/grid/src/shared/resize-handle.tsx b/projects/js-packages/grid/src/shared/resize-handle.tsx new file mode 100644 index 000000000000..0292dc563b77 --- /dev/null +++ b/projects/js-packages/grid/src/shared/resize-handle.tsx @@ -0,0 +1,164 @@ +/** + * External dependencies + */ +import { DndContext, useDraggable } from '@dnd-kit/core'; +import { useMergeRefs, useThrottle } from '@wordpress/compose'; +import { useCallback, useEffect, useRef } from '@wordpress/element'; +import clsx from 'clsx'; + +/** + * WordPress dependencies + */ + +/** + * Internal dependencies + */ +import styles from './resize-handle.module.css'; +import type { ResizeDelta, ResizeHandleProps } from './types'; +import type { DragMoveEvent } from '@dnd-kit/core'; + +/** + * Sets `document.documentElement.style.cursor` for the duration of a drag + * and restores it on cleanup. Lives outside the component so cursor writes + * are not analyzed as mutating values derived from refs in the component + * body (react-hooks/immutability). + * + * @param getDocument - Returns the document whose root element should receive + * the cursor (handle owner, or global `document`). + * @param cursor - CSS cursor value while active. + * @return Cleanup that restores the previous cursor. + */ +function lockDocumentCursorWhileActive( getDocument: () => Document, cursor: string ): () => void { + const root = getDocument().documentElement; + const previous = root.style.cursor; + root.style.cursor = cursor; + return () => { + root.style.cursor = previous; + }; +} + +/** + * + * @param root0 + * @param root0.itemId + * @param root0.verticalResizable + * @param root0.renderResizeHandle + */ +function ResizeHandle( { + itemId, + verticalResizable = true, + renderResizeHandle, +}: ResizeHandleProps ) { + const { attributes, listeners, setNodeRef, isDragging } = useDraggable( { + id: 'draggable', + data: { itemId }, + } ); + + // Snapshot owner document on mount/update via ref callback so the + // cursor-lock effect can resolve the correct document in an iframe. + const ownerDocumentRef = useRef< Document | null >( null ); + const setOwnerDocumentRef = useCallback( ( node: HTMLElement | null ) => { + ownerDocumentRef.current = node?.ownerDocument ?? null; + }, [] ); + const mergedRef = useMergeRefs( [ setOwnerDocumentRef, setNodeRef ] ); + + // Lock the document cursor while the gesture is active. Without + // this, the OS pointer reverts to the default arrow as soon as it + // leaves the handle's hit area, even though the resize is still + // in progress. + useEffect( () => { + if ( ! isDragging ) { + return; + } + const cursor = verticalResizable ? 'nwse-resize' : 'ew-resize'; + return lockDocumentCursorWhileActive( () => ownerDocumentRef.current ?? document, cursor ); + }, [ isDragging, verticalResizable ] ); + + if ( renderResizeHandle ) { + const RenderResizeHandle = renderResizeHandle; + return ( + + ); + } + + return ( +
+ ); +} + +/** + * Renders a corner resize handle inside an isolated ``. + * Reports the cursor offset since the gesture started (in pixels) + * via `onResize`, throttled to one animation frame so the grid + * commit loop runs at most once per paint. + * + * Auto-scroll is enabled with a tight trigger zone and a low + * acceleration so a resize gesture near the viewport edge scrolls + * the page only when the user deliberately pushes against the very + * edge, and even then at a pace the user can interrupt by releasing. + * Default tuning would otherwise produce a runaway loop where the + * page scrolls fast, dnd-kit's document-coordinate `delta` inflates + * with the scroll, and the tile keeps growing without further user + * input. + * + * @param props - Component props. + */ +export default function ResizeHandleWrapper( props: ResizeHandleProps ) { + const throttleDelay = 16; + const throttledResize = useThrottle( ( delta: ResizeDelta ) => { + if ( props.onResize ) { + props.onResize( delta ); + } + }, throttleDelay ); + + // `event.delta` is the cursor offset from the gesture start — + // not from the handle's current position — so it stays stable + // even when the tile (and therefore the handle) jumps a column. + // The grid's resize logic snapshots the start width and adds + // `delta`, so the two must share the same frame of reference. + const handleDragMove = ( event: DragMoveEvent ) => { + if ( event.active.id !== 'draggable' ) { + return; + } + throttledResize( { + width: event.delta.x, + height: event.delta.y, + } ); + }; + + const handleDragEnd = () => { + if ( props.onResizeEnd ) { + props.onResizeEnd(); + } + }; + + return ( + +
+ +
+
+ ); +} diff --git a/projects/js-packages/grid/src/shared/resize-snap.ts b/projects/js-packages/grid/src/shared/resize-snap.ts new file mode 100644 index 000000000000..5690fe7329de --- /dev/null +++ b/projects/js-packages/grid/src/shared/resize-snap.ts @@ -0,0 +1,60 @@ +import type { ResizeDelta } from './types'; + +/** + * Pixel dimensions for the snapped resize preview outline. + */ +export type ResizeSnapSize = { + widthPx: number; + /** When `null`, the preview spans the item's content height (lanes). */ + heightPx: number | null; +}; + +/** + * Clamps a resize delta so the tile cannot shrink below the given + * minimum width (and height when provided). + * + * @param delta - Cursor offset from the gesture start in pixels. + * @param initialSize - Size captured at gesture start. + * @param initialSize.width - Initial width in pixels. + * @param initialSize.height - Initial height in pixels. + * @param minSize - Minimum tile size in pixels. + * @param minSize.width - Minimum width in pixels. + * @param minSize.height - Minimum height in pixels, when vertical resize applies. + */ +export function clampResizeDelta( + delta: ResizeDelta, + initialSize: { width: number; height: number }, + minSize: { width: number; height?: number } +): ResizeDelta { + const maxShrinkWidth = initialSize.width - minSize.width; + const width = Math.max( delta.width, -maxShrinkWidth ); + if ( minSize.height === undefined ) { + return { ...delta, width }; + } + const maxShrinkHeight = initialSize.height - minSize.height; + const height = Math.max( delta.height, -maxShrinkHeight ); + return { width, height }; +} + +/** + * Converts grid spans to pixel width/height for the resize-preview + * outline, using the same track math the surface uses for placement. + * + * @param columnSpan - Number of columns the snap target spans. + * @param rowSpan - Number of rows the snap target spans. + * @param columnWidth - Width of one column track in pixels. + * @param gapPx - Gap between tracks in pixels. + * @param rowHeightPx - Row track height in pixels, or `null` when rows + * are content-sized. + */ +export function gridSpanToPixelSize( + columnSpan: number, + rowSpan: number, + columnWidth: number, + gapPx: number, + rowHeightPx: number | null +): ResizeSnapSize { + const widthPx = columnSpan * columnWidth + ( columnSpan - 1 ) * gapPx; + const heightPx = rowHeightPx === null ? null : rowSpan * rowHeightPx + ( rowSpan - 1 ) * gapPx; + return { widthPx, heightPx }; +} diff --git a/projects/js-packages/grid/src/shared/types.ts b/projects/js-packages/grid/src/shared/types.ts new file mode 100644 index 000000000000..c13477063296 --- /dev/null +++ b/projects/js-packages/grid/src/shared/types.ts @@ -0,0 +1,164 @@ +/** + * External dependencies + */ +import type { useDraggable } from '@dnd-kit/core'; + +// `useDraggable`'s `listeners` and `attributes` types are not exported +// from `@dnd-kit/core`'s public surface, so derive them from the hook +// itself rather than via a deep import. +type DraggableBindings = ReturnType< typeof useDraggable >; + +/** + * Cursor offset reported by the resize handle, in pixels relative to + * the gesture start. Width and height are independent so the surface + * can step columns and rows separately. + */ +export type ResizeDelta = { + width: number; + height: number; +}; + +/** + * Props received by a custom resize handle component. Spread `listeners` + * and `attributes` onto the element that should respond to the gesture, + * and assign `ref` to the same element so dnd-kit can track it. + */ +export interface ResizeHandleRenderProps { + /** + * Ref callback to attach to the gesture-bearing element. + */ + ref: DraggableBindings[ 'setNodeRef' ]; + + /** + * Pointer/keyboard event listeners that initiate the drag. + */ + listeners: DraggableBindings[ 'listeners' ]; + + /** + * Accessibility and dnd-kit attributes (role, aria-*, tabIndex…). + */ + attributes: DraggableBindings[ 'attributes' ]; + + /** + * Whether vertical resizing is allowed for this tile. Useful for + * adapting the cursor or visual cue. + */ + verticalResizable: boolean; + + /** + * True while the user is actively dragging this handle. Use it to + * swap colors, icons, or transforms during the gesture. + */ + isResizing: boolean; + + /** + * Owning item's `key`. Available so consumers can render per-tile + * content if needed. + */ + itemId?: string; +} + +/** + * Props received by a custom drag-preview component. The surface mounts + * the component inside `` and supplies the active tile's + * cloned children plus its `key`. The component is responsible for the + * visual chrome of the dragged clone (shadow, radius, padding); the + * surface keeps a thin functional wrapper around it that owns the lift + * cue, the cursor, and pointer pass-through during the gesture. + */ +export interface DragPreviewRenderProps { + /** + * The cloned tile content the surface mounts inside the + * `` portal. Render it where the visual wrapper + * expects the tile body. + */ + children: React.ReactNode; + + /** + * Owning tile's `key`. Useful when the visual chrome needs to + * vary by which tile is being dragged. + */ + itemId: string; +} + +/** + * Props received by a custom grid overlay component. The overlay + * paints behind the tiles in edit mode to visualize the column tracks + * and (when `rowHeight` is defined) the row tracks. Receives a + * snapshot of the surface's resolved layout parameters so the visual + * can reproduce the tracks pixel-accurately without re-deriving them. + * + * Reused by both `DashboardGrid` and `DashboardLanes`: lanes pass no + * `rowHeight` because heights are content-driven. + */ +export interface GridOverlayRenderProps { + /** + * Number of column tracks in the active surface. In responsive + * mode (`minColumnWidth`), this is the count derived from the + * container width, not the prop value. + */ + columns: number; + + /** + * Row height in pixels for surfaces with uniform rows. Omitted on + * surfaces with content-driven heights (lanes) or when row height + * is `'auto'`; in those cases row markers are omitted. + */ + rowHeight?: number; + + /** + * Number of row tracks to mirror in each column. Derived from the + * grid container height when `rowHeight` is numeric; omitted when + * row height is unknown. + */ + rows?: number; + + /** + * Whether the overlay should be visible. Surfaces render the + * overlay even when `false` so the implementation can transition + * opacity in and out; while `false`, the overlay must hide itself + * (and ideally release paint cost via `visibility: hidden` or an + * equivalent). + */ + isActive: boolean; +} + +/** + * Props for the internal `` wrapper. + */ +export interface ResizeHandleProps { + /** + * Owning item's `key`. Forwarded as `data.itemId` on the draggable + * so the parent can correlate the gesture with a tile if needed. + */ + itemId?: string; + + /** + * Whether the handle should track vertical movement. When false, + * the handle still appears but only emits horizontal deltas, and + * the cursor is constrained to the column resize axis. + * + * @default true + */ + verticalResizable?: boolean; + + /** + * Callback fired while the handle is being dragged. Receives the + * cursor offset from the gesture start in pixels. + */ + onResize?: ( delta: ResizeDelta ) => void; + + /** + * Callback fired when the gesture ends. + */ + onResizeEnd?: () => void; + + /** + * Component that overrides the default corner triangle with a + * custom element. Receives gesture wiring (`ref`, `listeners`, + * `attributes`) plus context. The surface keeps ownership of the + * `` and the throttled delta loop; consumers are only + * responsible for the visual. + */ + renderResizeHandle?: React.ComponentType< ResizeHandleRenderProps >; +} diff --git a/projects/js-packages/grid/src/shared/use-item-exit-animation.ts b/projects/js-packages/grid/src/shared/use-item-exit-animation.ts new file mode 100644 index 000000000000..75a65142f297 --- /dev/null +++ b/projects/js-packages/grid/src/shared/use-item-exit-animation.ts @@ -0,0 +1,185 @@ +/** + * WordPress dependencies + */ +import { useCallback, useLayoutEffect, useRef, useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import type { ItemExitOverlayRect } from './item-exit-overlay'; +import type { RectSnapshot } from './use-layout-shift-animation'; + +/* + * Last-resort cleanup if `animationend` never fires (the overlay's + * `onAnimationEnd` is the primary path). Kept well above the motion + * token durations so the timeout can never clip the exit animation. + */ +const EXIT_SAFETY_TIMEOUT_MS = 1000; + +export type ExitingGridItem = { + key: string; + rect: ItemExitOverlayRect; + child: React.ReactElement; +}; + +type UseItemExitAnimationOptions = { + container: HTMLElement | null; + enabled: boolean; + layoutKeys: ReadonlySet< string >; + getPositionsBeforeLastChange: () => ReadonlyMap< string, RectSnapshot > | null; + childrenCacheRef: React.MutableRefObject< Map< string, React.ReactElement > >; +}; + +type UseItemExitAnimationResult = { + exitingItems: ExitingGridItem[]; + hasExitingItems: boolean; + clearExitingItem: ( key: string ) => void; +}; + +/** + * + */ +function prefersReducedMotion(): boolean { + return ( + typeof window !== 'undefined' && window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches + ); +} + +/** + * When `layout` loses keys in edit mode, keeps a short-lived overlay at + * the removed tile's last position (scale + fade) while siblings FLIP. + * + * @param root0 - Hook options. + * @param root0.container - Surface root that contains grid tiles. + * @param root0.enabled - When false, exiting state is cleared. + * @param root0.layoutKeys - Keys in the committed `layout` prop. + * @param root0.getPositionsBeforeLastChange - Container-relative rects before the latest layout commit. + * @param root0.childrenCacheRef - Last rendered children keyed by tile id. + * @return Exiting overlays and a callback to dismiss one by key. + */ +export function useItemExitAnimation( { + container, + enabled, + layoutKeys, + getPositionsBeforeLastChange, + childrenCacheRef, +}: UseItemExitAnimationOptions ): UseItemExitAnimationResult { + const [ exitingItems, setExitingItems ] = useState< ExitingGridItem[] >( [] ); + const prevLayoutKeysRef = useRef< Set< string > >( new Set() ); + const exitTimeoutsRef = useRef< Map< string, ReturnType< typeof setTimeout > > >( new Map() ); + + const clearExitingItem = useCallback( + ( key: string ) => { + const timeout = exitTimeoutsRef.current.get( key ); + if ( timeout ) { + clearTimeout( timeout ); + exitTimeoutsRef.current.delete( key ); + } + setExitingItems( current => current.filter( item => item.key !== key ) ); + childrenCacheRef.current.delete( key ); + }, + [ childrenCacheRef ] + ); + + const scheduleExitComplete = useCallback( + ( key: string ) => { + if ( exitTimeoutsRef.current.has( key ) ) { + return; + } + const timeout = setTimeout( () => { + exitTimeoutsRef.current.delete( key ); + clearExitingItem( key ); + }, EXIT_SAFETY_TIMEOUT_MS ); + exitTimeoutsRef.current.set( key, timeout ); + }, + [ clearExitingItem ] + ); + + useLayoutEffect( () => { + if ( ! enabled || ! container ) { + prevLayoutKeysRef.current = new Set( layoutKeys ); + for ( const timeout of exitTimeoutsRef.current.values() ) { + clearTimeout( timeout ); + } + exitTimeoutsRef.current.clear(); + setExitingItems( [] ); + return; + } + + const prevKeys = prevLayoutKeysRef.current; + const removed: string[] = []; + for ( const key of prevKeys ) { + if ( ! layoutKeys.has( key ) ) { + removed.push( key ); + } + } + prevLayoutKeysRef.current = new Set( layoutKeys ); + + if ( removed.length === 0 ) { + return; + } + + const lastPositions = getPositionsBeforeLastChange(); + if ( ! lastPositions ) { + return; + } + + const nextExiting: ExitingGridItem[] = []; + for ( const key of removed ) { + const position = lastPositions.get( key ); + const child = childrenCacheRef.current.get( key ); + if ( ! position || ! child ) { + continue; + } + nextExiting.push( { + key, + rect: position, + child, + } ); + } + + if ( nextExiting.length === 0 ) { + return; + } + + if ( prefersReducedMotion() ) { + // Siblings snap into place via the layout-shift hook; skip the + // exit ghost (and its synchronous mount) entirely. + for ( const { key } of nextExiting ) { + childrenCacheRef.current.delete( key ); + } + return; + } + + // A state update inside a layout effect is flushed before paint, + // so the ghost mounts in the same frame the tile is removed. + setExitingItems( current => [ ...current, ...nextExiting ] ); + + for ( const { key } of nextExiting ) { + scheduleExitComplete( key ); + } + }, [ + container, + enabled, + getPositionsBeforeLastChange, + layoutKeys, + childrenCacheRef, + scheduleExitComplete, + ] ); + + useLayoutEffect( () => { + const exitTimeouts = exitTimeoutsRef.current; + return () => { + for ( const timeout of exitTimeouts.values() ) { + clearTimeout( timeout ); + } + exitTimeouts.clear(); + }; + }, [] ); + + return { + exitingItems, + hasExitingItems: exitingItems.length > 0, + clearExitingItem, + }; +} diff --git a/projects/js-packages/grid/src/shared/use-layout-shift-animation.ts b/projects/js-packages/grid/src/shared/use-layout-shift-animation.ts new file mode 100644 index 000000000000..56691c3a2527 --- /dev/null +++ b/projects/js-packages/grid/src/shared/use-layout-shift-animation.ts @@ -0,0 +1,283 @@ +/** + * WordPress dependencies + */ +import { useCallback, useLayoutEffect, useRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { GRID_ITEM_DATA_KEY } from './grid-item-key'; + +/* `left`/`top` are relative to the grid container, not the viewport. */ +export type RectSnapshot = { + left: number; + top: number; + width: number; + height: number; +}; + +type UseLayoutShiftAnimationOptions = { + /** + * Surface root that contains grid tiles. + */ + container: HTMLElement | null; + + /** + * When false, snapshots are cleared and no transforms run. + */ + enabled: boolean; + + /** + * Serialized layout/placement state. The hook runs FLIP when this + * value changes while `enabled` is true. + */ + layoutFingerprint: string; + + /** + * Item key to skip (the tile being dragged or resized). + */ + excludeItemKey?: string | null; +}; + +type UseLayoutShiftAnimationResult = { + /** + * Capture tile positions synchronously **before** a layout update + * (call immediately before `setTemporaryLayout` / similar). + */ + captureLayoutSnapshot: () => void; + + /** + * Container-relative rects from the last committed paint (settled, no + * FLIP invert transforms). + */ + getLastPositions: () => ReadonlyMap< string, RectSnapshot > | null; + + /** + * Tile positions immediately before the latest layout commit. Used + * by item-exit animation when keys drop out of `layout`. + */ + getPositionsBeforeLastChange: () => ReadonlyMap< string, RectSnapshot > | null; +}; + +/** + * + * @param container + */ +function queryGridItems( container: HTMLElement ): HTMLElement[] { + return Array.from( + container.querySelectorAll< HTMLElement >( + `[${ GRID_ITEM_DATA_KEY }]:not([data-wp-grid-item-exiting])` + ) + ); +} + +/** + * + * @param element + */ +function readItemKey( element: HTMLElement ): string | null { + return element.getAttribute( GRID_ITEM_DATA_KEY ); +} + +/** + * + * @param container + */ +function snapshotPositions( container: HTMLElement ): Map< string, RectSnapshot > { + // Measure relative to the container so positions stay valid even if the + // page scroll shifts between capture and use (e.g. the document reflowing + // shorter after a tile is removed). + const base = container.getBoundingClientRect(); + const positions = new Map< string, RectSnapshot >(); + for ( const element of queryGridItems( container ) ) { + const key = readItemKey( element ); + if ( ! key ) { + continue; + } + const { left, top, width, height } = element.getBoundingClientRect(); + positions.set( key, { + left: left - base.left, + top: top - base.top, + width, + height, + } ); + } + return positions; +} + +/** + * + * @param element + */ +function clearLayoutShiftStyles( element: HTMLElement ): void { + element.style.removeProperty( 'transform' ); + element.style.removeProperty( 'transition' ); +} + +/** + * + * @param element + * @param deltaX + * @param deltaY + */ +function playLayoutShift( element: HTMLElement, deltaX: number, deltaY: number ): void { + if ( deltaX === 0 && deltaY === 0 ) { + return; + } + + // Invert: show the tile where it was before the layout change. + element.style.transition = 'none'; + element.style.transform = `translate(${ deltaX }px, ${ deltaY }px)`; + void element.offsetHeight; + + // Play on the next frame so the inverted transform paints before + // the transition back to the committed grid position. + requestAnimationFrame( () => { + element.style.removeProperty( 'transition' ); + element.style.transform = ''; + + const onTransitionEnd = ( event: TransitionEvent ) => { + if ( event.propertyName !== 'transform' ) { + return; + } + element.removeEventListener( 'transitionend', onTransitionEnd ); + clearLayoutShiftStyles( element ); + }; + element.addEventListener( 'transitionend', onTransitionEnd ); + } ); +} + +/** + * Animates sibling tiles when grid layout reflows during drag or resize + * using a FLIP transform (see `layout-shift-animation.module.css`). + * + * @param root0 - Hook options. + * @param root0.container - Surface root that contains grid tiles. + * @param root0.enabled - When false, snapshots are cleared and no transforms run. + * @param root0.layoutFingerprint - Serialized layout/placement state. + * @param root0.excludeItemKey - Item key to skip (the tile being dragged or resized). + * @return Snapshot capture callback for use before layout updates. + */ +export function useLayoutShiftAnimation( { + container, + enabled, + layoutFingerprint, + excludeItemKey = null, +}: UseLayoutShiftAnimationOptions ): UseLayoutShiftAnimationResult { + const snapshotBeforeChangeRef = useRef< Map< string, RectSnapshot > | null >( null ); + const lastRenderedPositionsRef = useRef< Map< string, RectSnapshot > | null >( null ); + const positionsBeforeLastChangeRef = useRef< Map< string, RectSnapshot > | null >( null ); + + const captureLayoutSnapshot = useCallback( () => { + if ( container ) { + snapshotBeforeChangeRef.current = snapshotPositions( container ); + } + }, [ container ] ); + + useLayoutEffect( () => { + if ( ! container || ! enabled ) { + snapshotBeforeChangeRef.current = null; + lastRenderedPositionsRef.current = null; + positionsBeforeLastChangeRef.current = null; + if ( container ) { + for ( const element of queryGridItems( container ) ) { + clearLayoutShiftStyles( element ); + } + } + return; + } + + for ( const element of queryGridItems( container ) ) { + clearLayoutShiftStyles( element ); + } + + const previous = snapshotBeforeChangeRef.current ?? lastRenderedPositionsRef.current; + snapshotBeforeChangeRef.current = null; + + positionsBeforeLastChangeRef.current = previous ? new Map( previous ) : null; + + // Record settled grid positions for the next FLIP. Must run before + // invert transforms — measuring after `playLayoutShift` would bake + // translate offsets into the baseline and skew the next animation. + lastRenderedPositionsRef.current = snapshotPositions( container ); + + if ( previous ) { + const base = container.getBoundingClientRect(); + for ( const element of queryGridItems( container ) ) { + const key = readItemKey( element ); + if ( ! key || key === excludeItemKey ) { + continue; + } + const old = previous.get( key ); + if ( ! old ) { + continue; + } + const { left, top } = element.getBoundingClientRect(); + const deltaX = old.left - ( left - base.left ); + const deltaY = old.top - ( top - base.top ); + playLayoutShift( element, deltaX, deltaY ); + } + } + }, [ container, enabled, layoutFingerprint, excludeItemKey ] ); + + const getLastPositions = useCallback( () => { + return lastRenderedPositionsRef.current; + }, [] ); + + const getPositionsBeforeLastChange = useCallback( () => { + return positionsBeforeLastChangeRef.current; + }, [] ); + + return { + captureLayoutSnapshot, + getLastPositions, + getPositionsBeforeLastChange, + }; +} + +/** + * Stable fingerprint for {@link useLayoutShiftAnimation}. Width/height + * values may be numbers or layout keywords (`'fill'`, `'full'`). + * + * @param layout - Layout items to serialize. + * @return Fingerprint string. + */ +export function getLayoutFingerprint( + layout: ReadonlyArray< { + key: string; + width?: number | string; + height?: number; + order?: number; + lane?: number; + } > +): string { + return layout + .map( + item => + `${ item.key }:${ String( item.width ?? '' ) }:${ item.height ?? 1 }:${ + item.order ?? '' + }:${ item.lane ?? '' }` + ) + .join( '|' ); +} + +/** + * Placement fingerprint for lanes polyfill / explicit grid positions. + * + * @param itemStyles - Per-item inline placement styles. + * @return Fingerprint string. + */ +export function getPlacementFingerprint( itemStyles: Map< string, React.CSSProperties > ): string { + return [ ...itemStyles.entries() ] + .sort( ( [ a ], [ b ] ) => a.localeCompare( b ) ) + .map( ( [ key, style ] ) => { + const column = style.gridColumn ?? ''; + const columnStart = style.gridColumnStart ?? ''; + const rowStart = style.gridRowStart ?? ''; + const rowEnd = style.gridRowEnd ?? ''; + return `${ key }:${ String( column ) }:${ String( columnStart ) }:${ String( + rowStart + ) }:${ String( rowEnd ) }`; + } ) + .join( '|' ); +} diff --git a/projects/js-packages/grid/src/style-imports.d.ts b/projects/js-packages/grid/src/style-imports.d.ts new file mode 100644 index 000000000000..42171ccf601c --- /dev/null +++ b/projects/js-packages/grid/src/style-imports.d.ts @@ -0,0 +1,12 @@ +declare module '*.module.css' { + const classes: { [ key: string ]: string }; + export default classes; +} + +declare module '*.module.scss' { + const classes: { [ key: string ]: string }; + export default classes; +} + +declare module '*.css'; +declare module '*.scss'; diff --git a/projects/js-packages/grid/tsconfig.json b/projects/js-packages/grid/tsconfig.json new file mode 100644 index 000000000000..ce68cd9f21b8 --- /dev/null +++ b/projects/js-packages/grid/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "jetpack-js-tools/tsconfig.base.json", + "compilerOptions": { + "noEmit": true + }, + "include": [ "src/**/*" ] +} diff --git a/projects/js-packages/widget-dashboard/.gitignore b/projects/js-packages/widget-dashboard/.gitignore new file mode 100644 index 000000000000..7e5da87a90b0 --- /dev/null +++ b/projects/js-packages/widget-dashboard/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +vendor/ diff --git a/projects/js-packages/widget-dashboard/CHANGELOG.md b/projects/js-packages/widget-dashboard/CHANGELOG.md new file mode 100644 index 000000000000..03a962f457f6 --- /dev/null +++ b/projects/js-packages/widget-dashboard/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/projects/js-packages/widget-dashboard/README.md b/projects/js-packages/widget-dashboard/README.md new file mode 100644 index 000000000000..de23e1ed67da --- /dev/null +++ b/projects/js-packages/widget-dashboard/README.md @@ -0,0 +1,31 @@ +# @automattic/jetpack-widget-dashboard + +Internal, **private** port of WordPress core's dashboard widget engine (the future +`@wordpress/dashboard`): the stateless `WidgetDashboard` rendering engine plus the dashboard +preference hooks (`useDashboardLayout`, `useDashboardGridSettings`). The consumer owns layout +and edit-mode state; the engine renders and emits change events. + +Depends on `@automattic/jetpack-widget-primitives` (widget contract + discovery) and +`@automattic/jetpack-grid` (grid surface). Consumed as **source** (`exports` → `./src/index.ts`); +the host build (`wp-build`) compiles the TypeScript and CSS modules. Ships no build output. + +## Provenance + +Ported from [`WordPress/gutenberg`](https://github.com/WordPress/gutenberg) +`routes/dashboard/{widget-dashboard, hooks, lock-unlock.ts}` @ commit `8a40c807e86` +(branch `refactor/wp-build-name-as-module-id`). Cross-package imports were rewritten: +`@wordpress/grid` → `@automattic/jetpack-grid`, `../widget-primitives` → +`@automattic/jetpack-widget-primitives`. Keep this commit reference updated when syncing. + +### Local deviations from core + +- `src/widget-dashboard/utils/normalize-grid-settings/normalize-grid-settings.ts`: the return + spread casts `settings as WidgetGridLayoutSettings`. `tsgo` does not narrow the settings union + after the `( settings.model ?? 'grid' ) === 'masonry'` guard, so the cast (mirroring the one + already on the line above) is needed to add `rowHeight`. Semantically identical to core. +- `eslint.config.mjs` relaxes several rules that conflict with core's house style (see that file). + +## Privacy + +`"private": true` in `package.json` + `composer.json` without `npmjs-autopublish`/`mirror-repo` +guarantees this package is never published to npm or mirrored to a standalone repo. diff --git a/projects/js-packages/widget-dashboard/changelog/initial-version b/projects/js-packages/widget-dashboard/changelog/initial-version new file mode 100644 index 000000000000..18b26a8112e5 --- /dev/null +++ b/projects/js-packages/widget-dashboard/changelog/initial-version @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Initial version: private port of WordPress core's dashboard widget engine (the stateless WidgetDashboard rendering engine and dashboard preference hooks). diff --git a/projects/js-packages/widget-dashboard/composer.json b/projects/js-packages/widget-dashboard/composer.json new file mode 100644 index 000000000000..436f45cc9686 --- /dev/null +++ b/projects/js-packages/widget-dashboard/composer.json @@ -0,0 +1,21 @@ +{ + "name": "automattic/jetpack-js-widget-dashboard", + "description": "Stateless rendering engine for widget dashboards. Internal port of @wordpress/dashboard until it is published.", + "type": "library", + "license": "GPL-2.0-or-later", + "require": {}, + "repositories": [ + { + "type": "path", + "url": "../../packages/*", + "options": { + "monorepo": true + } + } + ], + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "textdomain": "jetpack-widget-dashboard" + } +} diff --git a/projects/js-packages/widget-dashboard/eslint.config.mjs b/projects/js-packages/widget-dashboard/eslint.config.mjs new file mode 100644 index 000000000000..506fe7cca777 --- /dev/null +++ b/projects/js-packages/widget-dashboard/eslint.config.mjs @@ -0,0 +1,29 @@ +import { makeBaseConfig, defineConfig, javascriptFiles } from 'jetpack-js-tools/eslintrc/base.mjs'; + +// `src/` is vendored verbatim from WordPress core's dashboard widget engine. +// These rules conflict with core's house style; turning them off keeps the port +// faithful and avoids churn on every upstream re-sync. Drop once core publishes it. +export default defineConfig( makeBaseConfig( import.meta.url ), { + files: javascriptFiles, + rules: { + 'react/jsx-no-bind': 'off', + 'import/order': 'off', + 'no-shadow': 'off', + 'no-useless-escape': 'off', + '@stylistic/max-line-length': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + ignoreRestSiblings: true, + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + caughtErrors: 'none', + }, + ], + 'jsdoc/check-indentation': 'off', + 'jsdoc/escape-inline-tags': 'off', + 'jsdoc/require-description': 'off', + 'jsdoc/require-param-description': 'off', + 'jsdoc/require-returns': 'off', + }, +} ); diff --git a/projects/js-packages/widget-dashboard/package.json b/projects/js-packages/widget-dashboard/package.json new file mode 100644 index 000000000000..060427112b75 --- /dev/null +++ b/projects/js-packages/widget-dashboard/package.json @@ -0,0 +1,61 @@ +{ + "name": "@automattic/jetpack-widget-dashboard", + "version": "0.1.0-alpha", + "private": true, + "description": "Stateless rendering engine for widget dashboards. Internal port of @wordpress/dashboard until it is published.", + "license": "GPL-2.0-or-later", + "author": "Automattic", + "type": "module", + "sideEffects": [ + "**/*.module.css" + ], + "exports": { + ".": { + "jetpack:src": "./src/index.ts", + "types": "./src/index.ts", + "import": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "main": "./src/index.ts", + "module": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "typecheck": "tsgo --noEmit" + }, + "dependencies": { + "@automattic/jetpack-grid": "workspace:*", + "@automattic/jetpack-widget-primitives": "workspace:*", + "@wordpress/api-fetch": "7.46.0", + "@wordpress/commands": "1.46.0", + "@wordpress/components": "33.1.0", + "@wordpress/compose": "7.46.0", + "@wordpress/core-data": "7.46.0", + "@wordpress/data": "10.46.0", + "@wordpress/dataviews": "14.3.0", + "@wordpress/element": "6.46.0", + "@wordpress/i18n": "6.19.0", + "@wordpress/icons": "13.1.0", + "@wordpress/preferences": "4.46.0", + "@wordpress/primitives": "4.46.0", + "@wordpress/private-apis": "1.46.0", + "@wordpress/ui": "0.13.0", + "@wordpress/viewport": "6.46.0", + "clsx": "^2.1.1", + "fast-deep-equal": "^3.1.3", + "uuid": "^14.0.0" + }, + "devDependencies": { + "@types/react": "^18.3.27", + "@types/react-dom": "^18.3.7", + "@typescript/native-preview": "7.0.0-dev.20260225.1", + "jetpack-js-tools": "workspace:*", + "react": "18.3.1", + "react-dom": "18.3.1", + "typescript": "5.9.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } +} diff --git a/projects/js-packages/widget-dashboard/src/hooks/index.ts b/projects/js-packages/widget-dashboard/src/hooks/index.ts new file mode 100644 index 000000000000..1d43c15e9fdd --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/hooks/index.ts @@ -0,0 +1,2 @@ +export { useDashboardLayout } from './use-dashboard-layout'; +export { useDashboardGridSettings } from './use-dashboard-grid-settings'; diff --git a/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-grid-settings/index.ts b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-grid-settings/index.ts new file mode 100644 index 000000000000..23780921eb40 --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-grid-settings/index.ts @@ -0,0 +1 @@ +export { useDashboardGridSettings } from './use-dashboard-grid-settings'; diff --git a/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-grid-settings/use-dashboard-grid-settings.ts b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-grid-settings/use-dashboard-grid-settings.ts new file mode 100644 index 000000000000..ccb838d17f5f --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-grid-settings/use-dashboard-grid-settings.ts @@ -0,0 +1,85 @@ +/** + * External dependencies + */ +import fastDeepEqual from 'fast-deep-equal/es6/index.js'; + +/** + * WordPress dependencies + */ +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as preferencesStore } from '@wordpress/preferences'; + +/** + * Internal dependencies + */ +import type { WidgetGridSettings } from '../../widget-dashboard/types'; +import { WIDGET_DASHBOARD_COLUMN_COUNT } from '../../widget-dashboard/types'; +import { normalizeGridSettings } from '../../widget-dashboard/utils/normalize-grid-settings'; +import { DEFAULT_ROW_HEIGHT } from '../../widget-dashboard/utils/row-height-presets'; + +const SCOPE = 'core/dashboard'; +const KEY = 'dashboardGridSettings'; + +/** + * Default grid settings applied when the preferences store has no + * entry yet, and the value `resetGridSettings` writes back when the + * user requests a reset. Kept aligned with the in-component default + * in `WidgetDashboardProvider` so consumers see consistent values + * whether or not they wire up this hook. + */ +const DEFAULT_GRID_SETTINGS: WidgetGridSettings = { + model: 'grid', + columns: WIDGET_DASHBOARD_COLUMN_COUNT, + rowHeight: DEFAULT_ROW_HEIGHT, +}; + +/** + * Hook for managing dashboard grid-settings preferences. + * + * Returns the persisted settings, a setter that writes through to the + * preferences store, and a reset action that applies the bundled + * defaults. The preference is shared across dashboards today; if a + * per-dashboard split is needed later, the signature can grow a + * dashboard-identifying parameter without touching call sites that + * pass the dashboard's name through. + * + * @return Tuple `[ settings, setSettings, resetSettings ]`. + */ +export function useDashboardGridSettings(): [ + WidgetGridSettings, + ( settings: WidgetGridSettings ) => void, + () => void, +] { + const settings = useSelect( select => { + const stored = select( preferencesStore ).get( SCOPE, KEY ) as WidgetGridSettings | undefined; + return normalizeGridSettings( stored ?? DEFAULT_GRID_SETTINGS, DEFAULT_ROW_HEIGHT ); + }, [] ); + + const { set } = useDispatch( preferencesStore ); + + /** + * + * @param next + */ + function setSettings( next: WidgetGridSettings ) { + // Persist "back to default" as a cleared preference rather than a stored + // copy of the defaults: the dashboard then tracks the current code + // default and the value can never drift. Reset routes through here (the + // drawer commit fires the setter with the default), so this is what makes + // Reset + Save truly clear the stored preference. + if ( fastDeepEqual( next, DEFAULT_GRID_SETTINGS ) ) { + void set( SCOPE, KEY, null ); + return; + } + void set( SCOPE, KEY, next ); + } + + /** + * + */ + function resetSettings() { + void set( SCOPE, KEY, null ); + } + + return [ settings, setSettings, resetSettings ]; +} diff --git a/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-layout/index.ts b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-layout/index.ts new file mode 100644 index 000000000000..aa12cedfa261 --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-layout/index.ts @@ -0,0 +1,2 @@ +export { useDashboardLayout } from './use-dashboard-layout'; +export type { DashboardName } from './use-dashboard-layout'; diff --git a/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-layout/use-dashboard-layout.ts b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-layout/use-dashboard-layout.ts new file mode 100644 index 000000000000..539e9c56fad3 --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/hooks/use-dashboard-layout/use-dashboard-layout.ts @@ -0,0 +1,66 @@ +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as preferencesStore } from '@wordpress/preferences'; + +/** + * Internal dependencies + */ +import type { DashboardWidget } from '../../widget-dashboard'; + +const SCOPE = 'core/dashboard'; +const KEY = 'dashboardLayout'; + +/** + * Identifier of a dashboard, structured as `_` to mirror + * the underscore form produced by the wp-build pipeline (see + * `{{PREFIX}}_{{PAGE_SLUG_UNDERSCORE}}` in the page templates). + */ +export type DashboardName = `${ string }_${ string }`; + +/** + * Hook for managing dashboard layout preferences. + * + * Returns the persisted layout, a setter that writes through to the + * preferences store, and a reset action that fetches the dashboard's + * registered default from the REST API and applies it locally. + * + * @param dashboardName - Identifier of the dashboard as produced by the + * build pipeline. Used as the `{name}` segment of + * the default-layout route. + * @return Tuple `[ layout, setLayout, resetLayout ]`. + */ +export function useDashboardLayout( + dashboardName: DashboardName +): [ DashboardWidget[], ( layout: DashboardWidget[] ) => void, () => Promise< void > ] { + const layout = useSelect( + select => + ( select( preferencesStore ).get( SCOPE, KEY ) as DashboardWidget[] | undefined ) ?? [], + [] + ); + + const { set } = useDispatch( preferencesStore ); + + /** + * + * @param newLayout + */ + function setLayout( newLayout: DashboardWidget[] ) { + void set( SCOPE, KEY, newLayout ); + } + + /** + * + */ + async function resetLayout() { + const fresh = ( await apiFetch( { + path: `/wp/v2/dashboards/${ dashboardName }/default-layout`, + } ) ) as DashboardWidget[]; + + void set( SCOPE, KEY, fresh ); + } + + return [ layout, setLayout, resetLayout ]; +} diff --git a/projects/js-packages/widget-dashboard/src/index.ts b/projects/js-packages/widget-dashboard/src/index.ts new file mode 100644 index 000000000000..f0a9e1da27f0 --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/index.ts @@ -0,0 +1,10 @@ +/** + * Widget dashboard rendering engine. + */ +export { WidgetDashboard } from './widget-dashboard'; +export type { DashboardWidget } from './widget-dashboard'; + +/** + * Dashboard preference hooks. + */ +export { useDashboardLayout, useDashboardGridSettings } from './hooks'; diff --git a/projects/js-packages/widget-dashboard/src/lock-unlock.ts b/projects/js-packages/widget-dashboard/src/lock-unlock.ts new file mode 100644 index 000000000000..bf6969038fcc --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/lock-unlock.ts @@ -0,0 +1,9 @@ +/** + * WordPress dependencies + */ +import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; + +export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', + '@wordpress/routes' +); diff --git a/projects/js-packages/widget-dashboard/src/style-imports.d.ts b/projects/js-packages/widget-dashboard/src/style-imports.d.ts new file mode 100644 index 000000000000..42171ccf601c --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/style-imports.d.ts @@ -0,0 +1,12 @@ +declare module '*.module.css' { + const classes: { [ key: string ]: string }; + export default classes; +} + +declare module '*.module.scss' { + const classes: { [ key: string ]: string }; + export default classes; +} + +declare module '*.css'; +declare module '*.scss'; diff --git a/projects/js-packages/widget-dashboard/src/widget-dashboard/README.md b/projects/js-packages/widget-dashboard/src/widget-dashboard/README.md new file mode 100644 index 000000000000..bb5b2ba933c3 --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/widget-dashboard/README.md @@ -0,0 +1,145 @@ +# `WidgetDashboard` + +Stateless rendering engine for widget dashboards. Renders an editable grid of widget instances, with drag-to-reorder and resize when edit mode is on. +Widget types flow in as a prop and every layout mutation fires `onLayoutChange` with the fully updated array. +The engine owns no data of its own. + +## Usage + +```tsx +import { useState } from '@wordpress/element'; +import { WidgetDashboard } from './widget-dashboard'; + +function Dashboard() { + const [ layout, setLayout ] = useState( defaultLayout ); + + return ( + + ); +} +``` + +`` renders `` by default. Pass `children` to compose the dashboard — header, empty state, footer — around the grid: + +```tsx + + +

{ __( 'No widgets yet.' ) }

+
+ +
+``` + +## Properties + +#### `layout`: `DashboardWidget[]` + +Widget instances to render. Each instance carries a stable `uuid`, a `type` reference, optional `attributes`, and a `placement` describing its slot in the grid. + +#### `onLayoutChange`: `( layout: DashboardWidget[] ) => void` + +Called on every mutation — reorder, resize, or `setAttributes` from a widget render module. Receives the fully updated array; the consumer owns the storage. + +#### `widgetTypes`: `WidgetType[]` + +The widget types available to the dashboard. + +#### `editMode`: `boolean` + +When `true`, the grid enables drag and resize. Defaults to `false`. + +#### `onEditChange`: `( next: boolean ) => void` + +Optional. Called when edit mode toggles via `WidgetDashboard.Actions` (or any consumer-built toggle). When omitted, `WidgetDashboard.Actions` renders nothing. + +#### `resolveWidgetModule`: `( moduleId: string ) => Promise< { default: ComponentType } >` + +Optional. Maps a `WidgetType.renderModule` id to the React component that renders the widget. Defaults to a dynamic `import( /* webpackIgnore */ moduleId )`. Override for tests, Storybook, or remote-URL loading. + +#### `gridSettings`: `WidgetGridSettings` + +Optional. Configures the underlying grid. + +#### `children`: `ReactNode` + +Optional. Composition slot for arbitrary dashboard markup. When omitted, the engine renders `` directly. + +## Compound components + +#### `` + +Iterates `layout`, renders each entry through ``, and feeds the resulting tree into the underlying grid (`@automattic/jetpack-grid`). + +#### `` + +Per-instance wrapper (the `DashboardWidgetChrome` component). Provides widget identity to the render tree via context and hosts the widget's render module under a `Suspense` boundary and an error boundary. The instance is read from `layout`; consumers don't pass it manually. + +#### `` + +Renders its children only when `layout` is empty. Pair it with `` so the empty state shows up in place of the grid until widgets are added. + +#### `` + +Edit-mode toggle: a "Customize" button while `editMode` is off, and "Add widget", "Layout settings" (when `onGridSettingsChange` is provided), "Cancel", "Done" while it is on. Layout settings is only available in customize mode. Clicking "Customize" or "Done" fires `onEditChange` with the toggled value. Clicking "Add widget" opens the inserter (see below). Returns `null` when the dashboard is mounted without `onEditChange`, so surfaces that don't expose edit mode can keep `Actions` in their tree unconditionally. + +`` from `@wordpress/admin-ui` exposes an `actions` slot used across admin screens (DataViews, WidgetDashboard, …). Plug `Actions` straight into it: + +```tsx +import { Page } from '@wordpress/admin-ui'; + + + } + > + + + +``` + +`` is optional. The compound renders inside any container, so a bare `
` or custom chrome works just as well. + +## Inserting widgets + +A modal-based inserter is mounted automatically inside `WidgetDashboard`. It stays hidden until the "Add widget" button in `` is clicked. The inserter lists every entry in the `widgetTypes` prop as a grid of live previews (each preview renders the type's `example` attributes through its own render module), supports search, and exposes a single "Select" action with bulk support so users can insert one or several widgets in a single layout change. + +On confirmation, the inserter creates instances via `createDashboardWidget( widgetType )` (using each type's `example.attributes` as the initial values) and appends them to `layout` through `onLayoutChange`. The dialog closes after a successful insertion or when the user dismisses it. + +The inserter has no opt-out today; hosts that want a custom widget-picking experience should compose their own UI alongside `` and avoid rendering `` (which exposes the trigger). + +## Authoring widgets + +Widget render modules receive only what they need to render and edit: + +```ts +interface WidgetRenderProps< Item = unknown > { + attributes: Item; + setAttributes?: ( next: Partial< Item > ) => void; +} +``` + +`setAttributes` flows back through `onLayoutChange` on the dashboard. Removal, badges, and error chrome are not part of this contract — those belong to the host. + +## Types + +- `DashboardWidget` — a placement of a widget on the dashboard. Carries `uuid`, `type`, `attributes`, `placement`. +- `WidgetType` — runtime widget type. Extends the `widget.json` shape with `renderModule`. +- `WidgetRenderProps` — widget render contract. +- `ResolveWidgetModule` — module resolver signature. +- `WidgetGridSettings` — grid configuration. + +The widget contract types (`WidgetName`, `WidgetType`, `WidgetRenderProps`, `ResolveWidgetModule`) are defined in `@automattic/jetpack-widget-primitives` and imported from there directly; this engine does not re-export them. diff --git a/projects/js-packages/widget-dashboard/src/widget-dashboard/components/actions/actions.module.css b/projects/js-packages/widget-dashboard/src/widget-dashboard/components/actions/actions.module.css new file mode 100644 index 000000000000..6221283ca4af --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/widget-dashboard/components/actions/actions.module.css @@ -0,0 +1,59 @@ +.editActionsEnter, +.editActionsExit { + display: inline-flex; + align-items: center; + gap: var(--wp--preset--spacing--20); + transform-origin: right center; +} + +.editActionsDivider { + flex-shrink: 0; + align-self: center; + width: 1px; + + /* TODO: Replace `$button-size-small` with a WPDS size token once size tokens land in `@wordpress/theme`. */ + height: calc(4 * var(--wpds-dimension-base)); + background-color: var(--wpds-color-stroke-surface-neutral); +} + +@media not ( prefers-reduced-motion ) { + + .editActionsEnter, + .editActionsExit { + will-change: opacity, transform; + } + + .editActionsEnter { + animation: actions-slide-in var(--wpds-motion-duration-md) var(--wpds-motion-easing-expressive) forwards; + } + + .editActionsExit { + animation: actions-fold-out var(--wpds-motion-duration-sm) var(--wpds-motion-easing-balanced) forwards; + } + + @keyframes actions-slide-in { + + from { + opacity: 0; + transform: translateX(12px) scaleX(0.92); + } + + to { + opacity: 1; + transform: translateX(0) scaleX(1); + } + } + + @keyframes actions-fold-out { + + from { + opacity: 1; + transform: translateX(0) scaleX(1); + } + + to { + opacity: 0; + transform: translateX(12px) scaleX(0.92); + } + } +} diff --git a/projects/js-packages/widget-dashboard/src/widget-dashboard/components/actions/actions.tsx b/projects/js-packages/widget-dashboard/src/widget-dashboard/components/actions/actions.tsx new file mode 100644 index 000000000000..5657b31c8379 --- /dev/null +++ b/projects/js-packages/widget-dashboard/src/widget-dashboard/components/actions/actions.tsx @@ -0,0 +1,192 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { useCallback, useEffect, useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { layout as layoutIcon, plus } from '@wordpress/icons'; +import { store as viewportStore } from '@wordpress/viewport'; + +import { AlertDialog, Button, Stack } from '@wordpress/ui'; + +/** + * Internal dependencies + */ +import styles from './actions.module.css'; +import { useDashboardInternalContext } from '../../context/dashboard-context'; +import { useDashboardUIContext } from '../../context/ui-context'; +import { LayoutSettings } from '../layout-settings'; +import { MoreActionsDropdown } from '../more-actions-dropdown'; +import type { MoreActionsDropdownItem } from '../more-actions-dropdown'; + +/** + * Header chrome for the dashboard. Customize mode surfaces an edit + * toolbar with Add widget, Layout settings (when grid settings are + * editable), Cancel, and Done. Layout settings opens a side drawer + * for model, column behavior, and row height; Save inside the drawer + * commits the settings staging buffer without leaving customize mode. + * Widget layout edits and grid settings share the same staging layer + * while customize mode is active. + * + * Returns `null` when the dashboard is mounted without `onEditChange` + * so hosts that don't expose edit mode can keep `Actions` in their + * tree unconditionally. + * + * @return {React.ReactNode} - The Actions component. + */ +export function Actions(): React.ReactNode { + const { + editMode, + onEditChange, + onLayoutReset, + commit, + cancel: cancelStaging, + hasUncommittedChanges, + canEditGridSettings, + } = useDashboardInternalContext(); + + const [ isEditActionsMounted, setIsEditActionsMounted ] = useState( editMode ); + const [ isExitingEditActions, setIsExitingEditActions ] = useState( false ); + + useEffect( () => { + if ( editMode ) { + setIsEditActionsMounted( true ); + setIsExitingEditActions( false ); + return; + } + + if ( ! isEditActionsMounted ) { + return; + } + + setIsExitingEditActions( true ); + const exitTimeout = setTimeout( () => { + setIsEditActionsMounted( false ); + setIsExitingEditActions( false ); + }, 220 ); + + return () => clearTimeout( exitTimeout ); + }, [ editMode, isEditActionsMounted ] ); + + const { + setInserterOpen, + layoutSettingsOpen, + setLayoutSettingsOpen, + resetDialogOpen, + setResetDialogOpen, + } = useDashboardUIContext(); + // @TODO: switch to using Admin UI declaratively for mobile viewport support once available. + // https://github.com/WordPress/gutenberg/issues/77628 + const isMobileViewport = useSelect( + select => select( viewportStore ).isViewportMatch( '< small' ), + [] + ); + + const handleEditMode = useCallback( () => { + onEditChange?.( ! editMode ); + }, [ editMode, onEditChange ] ); + + const insert = useCallback( () => { + setInserterOpen( true ); + }, [ setInserterOpen ] ); + + const cancel = useCallback( () => { + cancelStaging(); + }, [ cancelStaging ] ); + + const done = useCallback( () => { + commit(); + }, [ commit ] ); + + const openLayoutSettings = useCallback( () => { + setLayoutSettingsOpen( true ); + }, [ setLayoutSettingsOpen ] ); + + useEffect( () => { + if ( ! editMode && layoutSettingsOpen ) { + setLayoutSettingsOpen( false ); + } + }, [ editMode, layoutSettingsOpen, setLayoutSettingsOpen ] ); + + const moreActionsItems: MoreActionsDropdownItem[] = [ + { + label: __( 'Reset to default', 'jetpack-widget-dashboard' ), + onClick: () => setResetDialogOpen( true ), + disabled: ! onLayoutReset, + }, + ]; + + if ( ! onEditChange ) { + return null; + } + + return ( + + { isEditActionsMounted ? ( + + + + { canEditGridSettings && ( + + ) } + +