         js2-mode-show-strict-warnings nil
         ;; Flycheck provides these features, so disable them: conflicting with
         ;; the eslint settings.
-        js2-strict-trailing-comma-warning nil
         js2-strict-missing-semi-warning nil
         ;; maximum fontification
         js2-highlight-level 3
-        js2-highlight-external-variables t
-        js2-idle-timer-delay 0.1)
-
-  (add-hook 'js2-mode-hook #'rainbow-delimiters-mode)
-  ;; Indent switch-case another step
-  (setq-hook! 'js2-mode-hook
-    js-switch-indent-offset js2-basic-offset
-    mode-name "JS2")
-
-  (set-electric! 'js2-mode :chars '(?\} ?\) ?. ?:))
-  (set-repl-handler! 'js2-mode #'+javascript/open-repl))
-
-
-(use-package! rjsx-mode
-  :mode "components/.+\\.js$"
-  :init
-  (defun +javascript-jsx-file-p ()
-    "Detect React or preact imports early in the file."
-    (and buffer-file-name
-         (string= (file-name-extension buffer-file-name) "js")
-         (re-search-forward "\\(^\\s-*import +React\\|\\( from \\|require(\\)[\"']p?react\\)"
-                            magic-mode-regexp-match-limit t)
-         (progn (goto-char (match-beginning 1))
-                (not (sp-point-in-string-or-comment)))))
-  (add-to-list 'magic-mode-alist '(+javascript-jsx-file-p . rjsx-mode))
-  :config
-  (set-electric! 'rjsx-mode :chars '(?\} ?\) ?. ?>))
-  (when (featurep! :checkers syntax)
-    (add-hook! 'rjsx-mode-hook
-      ;; jshint doesn't know how to deal with jsx
-      (push 'javascript-jshint flycheck-disabled-checkers)))
+        js2-idle-timer-delay 0.15)
+
+  (setq-hook! 'rjsx-mode-hook
+    ;; Indent switch-case another step
+    js-switch-indent-offset js2-basic-offset)
+
+  (use-package! xref-js2
+    :when (featurep! :tools lookup)
+    :init
+    (setq xref-js2-search-program 'rg)
+    (set-lookup-handlers! 'rjsx-mode
+      :xref-backend #'xref-js2-xref-backend))
 
   ;; HACK `rjsx-electric-gt' relies on js2's parser to tell it when the cursor
   ;;      is in a self-closing tag, so that it can insert a matching ending tag


(use-package! typescript-mode
  :hook (typescript-mode . rainbow-delimiters-mode)
  :config
  (set-electric! 'typescript-mode
    :chars '(?\} ?\)) :words '("||" "&&"))
  (set-ligatures! 'typescript-mode
    ;; Functional
    :def "function"
    :lambda "() =>"
    :composition "compose"
    ;; Types
    :null "null"
    :true "true" :false "false"
    :int "number"
    :str "string"
    :bool "boolean"
    ;; Flow
    :not "!"
    :and "&&" :or "||"
    :for "for"
    :return "return" :yield "import")
  ;; HACK Fixes comment continuation on newline
  (setq-hook! 'typescript-mode-hook
    comment-line-break-function #'js2-line-break))

;; REVIEW We associate TSX files with `typescript-tsx-mode' derived from
;;        `web-mode' because `typescript-mode' does not officially support
;;        JSX/TSX. See
;;        https://github.com/emacs-typescript/typescript.el/issues/4
(if (featurep! :lang web)
    (progn
      (define-derived-mode typescript-tsx-mode web-mode "TypeScript-tsx")
      (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-tsx-mode))

      (add-hook 'typescript-tsx-mode-hook #'emmet-mode)

      (after! flycheck
        (flycheck-add-mode 'typescript-tslint 'typescript-tsx-mode)
        (flycheck-add-mode 'javascript-eslint 'typescript-tsx-mode)))
  (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode)))

(after! (:any typescript-mode web-mode)
  (set-docsets! '(typescript-mode typescript-tsx-mode) "TypeScript" "AngularTS"))


;;;###package coffee-mode
(setq coffee-indent-like-python-mode t)
(after! coffee-mode
  (set-docsets! 'coffee-mode "CoffeeScript"))


;;
;;; Tools

(add-hook! '(js2-mode-local-vars-hook
             typescript-mode-local-vars-hook
             typescript-tsx-mode-local-vars-hook
             web-mode-local-vars-hook
             rjsx-mode-local-vars-hook)

           css-mode
           web-mode
           markdown-mode
           js-mode  ; includes js2-mode and rjsx-mode
           json-mode
           typescript-mode
           solidity-mode)
  :when (locate-dominating-file default-directory "package.json")
  :add-hooks '(add-node-modules-path npm-mode))
