diff --git a/app/javascript/controllers/datetime_controller.ts b/app/javascript/controllers/datetime_controller.ts index 0567167d0..58dcb1e98 100644 --- a/app/javascript/controllers/datetime_controller.ts +++ b/app/javascript/controllers/datetime_controller.ts @@ -1,4 +1,4 @@ -import format from 'date-fns/format'; +import { format } from 'date-fns/format'; import { ApplicationController } from './application_controller'; diff --git a/app/javascript/entrypoints/axe-core.ts b/app/javascript/entrypoints/axe-core.ts deleted file mode 100644 index 4ca470d6e..000000000 --- a/app/javascript/entrypoints/axe-core.ts +++ /dev/null @@ -1,156 +0,0 @@ -import type { AxeResults, NodeResult, RelatedNode } from 'axe-core'; -import axe from 'axe-core'; - -domReady().then(() => { - axe.run(document.body, { reporter: 'v2' }).then((results) => { - logToConsole(results); - }); -}); - -// contrasted against Chrome default color of #ffffff -const lightTheme = { - serious: '#d93251', - minor: '#d24700', - text: 'black' -}; - -// contrasted against Safari dark mode color of #535353 -const darkTheme = { - serious: '#ffb3b3', - minor: '#ffd500', - text: 'white' -}; - -const theme = - window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches - ? darkTheme - : lightTheme; - -const boldCourier = 'font-weight:bold;font-family:Courier;'; -const critical = `color:${theme.serious};font-weight:bold;`; -const serious = `color:${theme.serious};font-weight:normal;`; -const moderate = `color:${theme.minor};font-weight:bold;`; -const minor = `color:${theme.minor};font-weight:normal;`; -const defaultReset = `font-color:${theme.text};font-weight:normal;`; - -function logToConsole(results: AxeResults): void { - console.group('%cNew axe issues', serious); - results.violations.forEach((result) => { - let fmt: string; - switch (result.impact) { - case 'critical': - fmt = critical; - break; - case 'serious': - fmt = serious; - break; - case 'moderate': - fmt = moderate; - break; - case 'minor': - fmt = minor; - break; - default: - fmt = minor; - break; - } - console.groupCollapsed( - '%c%s: %c%s %s', - fmt, - result.impact, - defaultReset, - result.help, - result.helpUrl - ); - result.nodes.forEach((node) => { - failureSummary(node, 'any'); - failureSummary(node, 'none'); - }); - console.groupEnd(); - }); - console.groupEnd(); -} - -function failureSummary(node: NodeResult, key: AxeCoreNodeResultKey): void { - if (node[key].length > 0) { - logElement(node, console.groupCollapsed); - logHtml(node); - logFailureMessage(node, key); - - let relatedNodes: RelatedNode[] = []; - node[key].forEach((check) => { - relatedNodes = relatedNodes.concat(check.relatedNodes ?? []); - }); - - if (relatedNodes.length > 0) { - console.groupCollapsed('Related nodes'); - relatedNodes.forEach((relatedNode) => { - logElement(relatedNode, console.log); - logHtml(relatedNode); - }); - console.groupEnd(); - } - - console.groupEnd(); - } -} - -function logFailureMessage(node: NodeResult, key: AxeCoreNodeResultKey): void { - // this exists on axe but we don't export it as part of the typescript - // namespace, so just let me use it as I need - const message: string = ( - axe as unknown as AxeWithAudit - )._audit.data.failureSummaries[key].failureMessage( - node[key].map((check) => check.message || '') - ); - - console.error(message); -} - -function logElement( - node: NodeResult | RelatedNode, - logFn: (...args: unknown[]) => void -): void { - const el = document.querySelector(node.target.toString()); - if (!el) { - logFn('Selector: %c%s', boldCourier, node.target.toString()); - } else { - logFn('Element: %o', el); - } -} - -function logHtml(node: NodeResult | RelatedNode): void { - console.log('HTML: %c%s', boldCourier, node.html); -} - -type AxeCoreNodeResultKey = 'any' | 'all' | 'none'; - -interface AxeWithAudit { - _audit: { - data: { - failureSummaries: { - any: { - failureMessage: (args: string[]) => string; - }; - all: { - failureMessage: (args: string[]) => string; - }; - none: { - failureMessage: (args: string[]) => string; - }; - }; - }; - }; -} - -function domReady() { - return new Promise((resolve) => { - if (document.readyState == 'loading') { - document.addEventListener('DOMContentLoaded', () => resolve(), { - once: true - }); - } else { - resolve(); - } - }); -} diff --git a/app/javascript/shared/polyfills/dataset.js b/app/javascript/shared/polyfills/dataset.js deleted file mode 100644 index 653787247..000000000 --- a/app/javascript/shared/polyfills/dataset.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - @preserve dataset polyfill for IE < 11. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset and http://caniuse.com/#search=dataset - - @author ShirtlessKirk copyright 2015 - @license WTFPL (http://www.wtfpl.net/txt/copying) -*/ - -const dash = /-([a-z])/gi; -const dataRegEx = /^data-(.+)/; -const hasEventListener = !!document.addEventListener; -const test = document.createElement('_'); -const DOMAttrModified = 'DOMAttrModified'; - -let mutationSupport = false; - -function clearDataset(event) { - delete event.target._datasetCache; -} - -function toCamelCase(string) { - return string.replace(dash, function (_, letter) { - return letter.toUpperCase(); - }); -} - -function getDataset() { - const dataset = {}; - - for (let attribute of this.attributes) { - let match = attribute.name.match(dataRegEx); - if (match) { - dataset[toCamelCase(match[1])] = attribute.value; - } - } - - return dataset; -} - -function mutation() { - if (hasEventListener) { - test.removeEventListener(DOMAttrModified, mutation, false); - } else { - test.detachEvent(`on${DOMAttrModified}`, mutation); - } - - mutationSupport = true; -} - -if (!test.dataset) { - if (hasEventListener) { - test.addEventListener(DOMAttrModified, mutation, false); - } else { - test.attachEvent(`on${DOMAttrModified}`, mutation); - } - - // trigger event (if supported) - test.setAttribute('foo', 'bar'); - - Object.defineProperty(Element.prototype, 'dataset', { - get: mutationSupport - ? function get() { - if (!this._datasetCache) { - this._datasetCache = getDataset.call(this); - } - - return this._datasetCache; - } - : getDataset - }); - - if (mutationSupport && hasEventListener) { - // < IE9 supports neither - document.addEventListener(DOMAttrModified, clearDataset, false); - } -} diff --git a/bun.lockb b/bun.lockb index beab4b760..59fe8acc1 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index d301bee84..fc11c6e57 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "@coldwired/react": "^0.15.0", "@coldwired/turbo-stream": "^0.13.0", "@coldwired/utils": "^0.13.0", - "@frsource/autoresize-textarea": "^2.0.75", + "@frsource/autoresize-textarea": "^2.0.82", "@gouvfr/dsfr": "^1.11.2", - "@graphiql/plugin-explorer": "^3.0.2", + "@graphiql/plugin-explorer": "^3.1.0", "@graphiql/toolkit": "^0.9.1", "@headlessui/react": "^1.6.6", "@heroicons/react": "^1.0.6", @@ -15,11 +15,11 @@ "@hotwired/turbo": "^7.3.0", "@mapbox/mapbox-gl-draw": "^1.3.0", "@popperjs/core": "^2.11.8", - "@rails/actiontext": "^7.1.3-2", - "@rails/activestorage": "^7.1.3-2", - "@rails/ujs": "^7.1.3-2", + "@rails/actiontext": "^7.1.3-4", + "@rails/activestorage": "^7.1.3-4", + "@rails/ujs": "^7.1.3-4", "@reach/slider": "^0.17.0", - "@sentry/browser": "8.7.0", + "@sentry/browser": "8.15.0", "@tiptap/core": "^2.2.4", "@tiptap/extension-bold": "^2.2.4", "@tiptap/extension-bullet-list": "^2.2.4", @@ -44,26 +44,26 @@ "@tmcw/togeojson": "^5.6.0", "chartkick": "^5.0.1", "core-js": "^3.37.1", - "date-fns": "^2.30.0", - "debounce": "^1.2.1", + "date-fns": "^3.6.0", + "debounce": "^2.1.0", "geojson": "^0.5.0", - "graphiql": "^3.2.3", - "graphql": "^16.8.1", + "graphiql": "^3.3.2", + "graphql": "^16.9.0", "highcharts": "^10.3.3", "lightgallery": "^2.7.2", "maplibre-gl": "^1.15.2", "match-sorter": "^6.3.4", "patch-package": "^8.0.0", - "react": "^18.3.0", - "react-aria-components": "^1.2.0", + "react": "^18.3.1", + "react-aria-components": "^1.2.1", "react-coordinate-input": "^1.0.0", - "react-dom": "^18.3.0", + "react-dom": "^18.3.1", "react-popper": "^2.3.0", "react-use-event-hook": "^0.9.6", "spectaql": "^2.3.1", "stimulus-use": "^0.52.2", - "superstruct": "^1.0.4", - "terser": "^5.31.0", + "superstruct": "^2.0.2", + "terser": "^5.31.1", "tiny-invariant": "^1.3.3", "tippy.js": "^6.3.7", "trix": "^1.2.3", @@ -73,7 +73,7 @@ "@esbuild/darwin-arm64": "=0.19.9", "@esbuild/linux-x64": "=0.19.9", "@esbuild/win32-x64": "=0.19.9", - "@react-aria/optimize-locales-plugin": "^1.1.0", + "@react-aria/optimize-locales-plugin": "^1.1.1", "@rollup/rollup-darwin-arm64": "=4.9.1", "@rollup/rollup-linux-x64-gnu": "=4.9.1", "@rollup/rollup-win32-x64-msvc": "=4.9.1", @@ -83,28 +83,27 @@ "@types/mapbox__mapbox-gl-draw": "^1.2.5", "@types/rails__activestorage": "^7.1.1", "@types/rails__ujs": "^6.0.4", - "@types/react": "^18.2.79", - "@types/react-dom": "^18.2.25", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", "@types/sortablejs": "^1.15.8", - "@typescript-eslint/eslint-plugin": "^7.11.0", - "@typescript-eslint/parser": "^7.11.0", - "@vitejs/plugin-react": "^4.3.0", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", + "@vitejs/plugin-react": "^4.3.1", "autoprefixer": "^10.4.19", - "axe-core": "^4.8.4", "del-cli": "^5.1.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.2", + "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^4.6.2", - "jsdom": "^22.1.0", - "postcss": "^8.4.38", - "prettier": "^3.3.0", - "typescript": "^5.4.5", - "vite": "^5.2.12", + "jsdom": "^24.1.0", + "postcss": "^8.4.39", + "prettier": "^3.3.2", + "typescript": "^5.5.3", + "vite": "^5.3.3", "vite-plugin-full-reload": "^1.1.0", "vite-plugin-ruby": "^5.0.0", - "vitest": "^1.6.0" + "vitest": "^2.0.0" }, "scripts": { "clean": "del tmp public/graphql && bin/vite clobber",