Skip to content

Commit

Permalink
Merge branch 'main' into select_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismccord authored Sep 30, 2024
2 parents 9341aaa + 622f72d commit 9c53dda
Show file tree
Hide file tree
Showing 129 changed files with 5,590 additions and 3,711 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ jobs:

runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.45.1-jammy
image: mcr.microsoft.com/playwright:v1.47.1-jammy
env:
ImageOS: ubuntu22
HOME: /root
Expand Down
21 changes: 17 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ let liveSocket = new LiveSocket("/live", Socket, {
})
```

Additionally, the `phx-page-loading` attrbute has been removed in favor of using the `page_loading: true`
option to `Phoenix.LiveView.JS.push/2` as needed.

### Migrating from phx-feedback-for

While we provide [a shim for existing applications](https://gist.github.com/chrismccord/c4c60328c6ac5ec29e167bb115315d82) relying on phx-feedback-for,
Expand Down Expand Up @@ -112,14 +115,24 @@ generated user module:
## 1.0.0-rc.7

### Enhancements
* Support custom redirect statuses on `Phoenix.LiveView.redirect/2`
* Export `createHook` from `phoenix_live_view` to allow CustomElement's to use hooks
* Expose programmable JS command interface to hooks for showing, hiding, addClass, etc from a hook which integrates with server DOM patching
* Support targeting inner and closest query selectors in JS commands with `to: {:inner, "a"}` and `to: {:closet, "tr"}`, etc.
* Throw a more informative error when `JS.dispatch/2` is used with an input event on an invalid target
* Validate slot options (prevents typos like `slot :myslot, requird: true`)

### Bug fixes
* Fix nested LiveViews inside a stream element
* Fix infinite loading streams in zoomed viewports #3442
* Fix race condition in latency simulator causing messages to be applied out of order
* Fix stream items not reapplying JS commands when joining after a disconnect
* Fix unnecessary remount when navigating back
* Fix character composition mode not working properly in Safari when an input is patched
* Fix `cannot redirect socket on update` error raised erroneously under rare circumstances
* Fix upstream morphdom issue that could cause elements being removed from the real DOM instead of a cloned tree while some elements are locked
* Don't dispatch click event when moving mouse away from initial click target
* Fix formatter formatting expressions that are strings with escaped quotes incorrectly

### Deprecations
* Deprecate the `name` attribute of `Phoenix.Component.dynamic_tag/1` in favor of `tag_name`
Expand Down Expand Up @@ -168,7 +181,7 @@ generated user module:

### Bug fixes
* Fix used input tracking on checkboxes and hidden inputs
* Fix phx-debounce=blur incorrectly sending change event to the next page in some cirumstances
* Fix phx-debounce=blur incorrectly sending change event to the next page in some circumstances
* Fix race condition when destroying Live Components while transitions are still running
* Fix page reload when disconnecting LiveSocket if using Bandit
* Fix formatter changing `<%` to `<%=` when it shouldn't
Expand Down Expand Up @@ -219,7 +232,7 @@ generated user module:
* Fix nested LiveView within streams becoming empty when reset
* Fix `phx-mounted` firing twice, first on dead render, then on live render, leading to errors when a LiveComponent has not yet mounted
* Fix `JS.toggle_class` error when used with a transition
* Fix phx-debounce=blur incorrectly sending change event to the next page in some cirumstances
* Fix phx-debounce=blur incorrectly sending change event to the next page in some circumstances
* Fix race condition when destroying Live Components while transitions are still running
* Fix page reload when disconnecting LiveSocket if using Bandit
* Fix formatter changing `<%` to `<%=` when it shouldn't
Expand Down Expand Up @@ -389,7 +402,7 @@ generated user module:
* Fix match error on live navigation when reconnecting from client

### Enhancements
* Support new `meta()` method on File/Blob sublcasses on JavaScript client to allow the client to pass arbitrary metadata when using `upload/uploadTo` from hook. The `%UploadEntry{}`'s new `client_meta` field is populated from this information.
* Support new `meta()` method on File/Blob subclasses on JavaScript client to allow the client to pass arbitrary metadata when using `upload/uploadTo` from hook. The `%UploadEntry{}`'s new `client_meta` field is populated from this information.
* Improve void tagging and error messages

## 0.20.0 (2023-09-22)
Expand Down Expand Up @@ -672,7 +685,7 @@ a `:let` usage.
- [Logger] Add new LiveView logger with telemetry instrumentation for lifecycle events
- [JS] Add new JS commands for `focus`, `focus_first`, `push_focus`, and `pop_focus` for accessibility
- [Socket] Support sharing `Phoenix.LiveView.Socket` with regular channels via `use Phoenix.LiveView.Socket`
- Add `_live_referer` connect param for handling `push_navigate` referal URL
- Add `_live_referer` connect param for handling `push_navigate` referral URL
- Add new `phx-connected` and `phx-disconnected` bindings for reacting to lifecycle changes
- Add dead view support for JS commands
- Add dead view support for hooks
Expand Down
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ https://user-images.githubusercontent.com/576796/162234098-31b580fe-e424-47e6-b0

<br />

After you [install Elixir](https://elixir-lang.org/install.html)
on your machine, you can create your first LiveView app in two
steps:
LiveView ships by default in new Phoenix applications. After you
[install Elixir](https://elixir-lang.org/install.html) on your machine,
you can create your first LiveView app in two steps:

$ mix archive.install hex phx_new
$ mix phx.new demo

> If you have an older existing Phoenix app and you wish to add LiveView,
> see [the previous installation guide](https://github.com/phoenixframework/phoenix_live_view/blob/v0.20.1/guides/introduction/installation.md).
## Feature highlights

LiveView brings a unified experience to building web applications. You no longer
Expand Down Expand Up @@ -61,11 +64,21 @@ Also follow these announcements from the Phoenix team on LiveView for more examp

* [Initial announcement](https://dockyard.com/blog/2018/12/12/phoenix-liveview-interactive-real-time-apps-no-need-to-write-javascript)

## Installation
## Component systems

When you create a new Phoenix project, it comes with a minimal component system to power Phoenix generators.
In case you want to enrich your developer experience, there are several component systems provided by the
community at different stages of development:

* [Bloom](https://github.com/chrisgreg/bloom): The opinionated, open-source extension to Phoenix Core Components

* [Doggo](https://github.com/woylie/doggo): Headless UI components for Phoenix

* [Petal Components](https://github.com/petalframework/petal_components): Phoenix + Live View HEEX Components

* [PrimerLive](https://github.com/ArthurClemens/primer_live): An implementation of GitHub's Primer Design System using Phoenix LiveView

LiveView is included by default in all new Phoenix v1.6+ applications and
later. If you have an older existing Phoenix app and you wish to add
LiveView, see [the previous installation guide](https://github.com/phoenixframework/phoenix_live_view/blob/v0.20.1/guides/introduction/installation.md).
* [SaladUI](https://github.com/bluzky/salad_ui): Phoenix Liveview component library inspired by shadcn UI

## What makes LiveView unique?

Expand Down
81 changes: 0 additions & 81 deletions assets/.eslintrc.js

This file was deleted.

92 changes: 92 additions & 0 deletions assets/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import jest from "eslint-plugin-jest"
import globals from "globals"
import path from "node:path"
import {fileURLToPath} from "node:url"
import js from "@eslint/js"
import {FlatCompat} from "@eslint/eslintrc"

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
})

export default [...compat.extends("eslint:recommended"), {
plugins: {
jest,
},

languageOptions: {
globals: {
...globals.browser,
...jest.environments.globals.globals,
global: "writable",
},

ecmaVersion: 12,
sourceType: "module",
},

rules: {
indent: ["error", 2, {
SwitchCase: 1,
}],

"linebreak-style": ["error", "unix"],
quotes: ["error", "double"],
semi: ["error", "never"],

"object-curly-spacing": ["error", "never", {
objectsInObjects: false,
arraysInObjects: false,
}],

"array-bracket-spacing": ["error", "never"],

"comma-spacing": ["error", {
before: false,
after: true,
}],

"computed-property-spacing": ["error", "never"],

"space-before-blocks": ["error", {
functions: "never",
keywords: "never",
classes: "always",
}],

"keyword-spacing": ["error", {
overrides: {
if: {
after: false,
},

for: {
after: false,
},

while: {
after: false,
},

switch: {
after: false,
},
},
}],

"eol-last": ["error", "always"],

"no-unused-vars": ["error", {
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
}],

"no-useless-escape": "off",
"no-cond-assign": "off",
"no-case-declarations": "off",
},
}]
12 changes: 1 addition & 11 deletions assets/js/phoenix_live_view/aria.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
let ARIA = {
focusMain(){
let target = document.querySelector("main h1, main, h1")
if(target){
let origTabIndex = target.tabIndex
target.tabIndex = -1
target.focus()
target.tabIndex = origTabIndex
}
},

anyOf(instance, classes){ return classes.find(name => instance instanceof name) },

isFocusable(el, interactiveOnly){
Expand Down Expand Up @@ -56,4 +46,4 @@ let ARIA = {
}
}
}
export default ARIA
export default ARIA
5 changes: 2 additions & 3 deletions assets/js/phoenix_live_view/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export const PHX_LIVE_FILE_UPDATED = "phx:live-file:updated"
export const PHX_SKIP = "data-phx-skip"
export const PHX_MAGIC_ID = "data-phx-id"
export const PHX_PRUNE = "data-phx-prune"
export const PHX_PAGE_LOADING = "page-loading"
export const PHX_CONNECTED_CLASS = "phx-connected"
export const PHX_LOADING_CLASS = "phx-loading"
export const PHX_ERROR_CLASS = "phx-error"
Expand Down Expand Up @@ -76,7 +75,7 @@ export const DEFAULTS = {
debounce: 300,
throttle: 300
}
export const PHX_PENDING_ATTRS = [PHX_REF_LOADING, PHX_REF_SRC, PHX_REF_LOCK, PHX_PAGE_LOADING]
export const PHX_PENDING_ATTRS = [PHX_REF_LOADING, PHX_REF_SRC, PHX_REF_LOCK]
// Rendered
export const DYNAMICS = "d"
export const STATIC = "s"
Expand All @@ -86,4 +85,4 @@ export const EVENTS = "e"
export const REPLY = "r"
export const TITLE = "t"
export const TEMPLATES = "p"
export const STREAM = "stream"
export const STREAM = "stream"
28 changes: 25 additions & 3 deletions assets/js/phoenix_live_view/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,34 @@ let DOM = {
return currentCycle
},

maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom){
if(el.hasAttribute && (el.hasAttribute(phxViewportTop) || el.hasAttribute(phxViewportBottom))){
el.setAttribute("data-phx-hook", "Phoenix.InfiniteScroll")
// maintains or adds privately used hook information
// fromEl and toEl can be the same element in the case of a newly added node
// fromEl and toEl can be any HTML node type, so we need to check if it's an element node
maintainPrivateHooks(fromEl, toEl, phxViewportTop, phxViewportBottom){
// maintain the hooks created with createHook
if(fromEl.hasAttribute && fromEl.hasAttribute("data-phx-hook") && !toEl.hasAttribute("data-phx-hook")){
toEl.setAttribute("data-phx-hook", fromEl.getAttribute("data-phx-hook"))
}
// add hooks to elements with viewport attributes
if(toEl.hasAttribute && (toEl.hasAttribute(phxViewportTop) || toEl.hasAttribute(phxViewportBottom))){
toEl.setAttribute("data-phx-hook", "Phoenix.InfiniteScroll")
}
},

putCustomElHook(el, hook){
if(el.isConnected){
el.setAttribute("data-phx-hook", "")
} else {
console.error(`
hook attached to non-connected DOM element
ensure you are calling createHook within your connectedCallback. ${el.outerHTML}
`)
}
this.putPrivate(el, "custom-el-hook", hook)
},

getCustomElHook(el){ return this.private(el, "custom-el-hook") },

isUsedInput(el){
return (el.nodeType === Node.ELEMENT_NODE &&
(this.private(el, PHX_HAS_FOCUSED) || this.private(el, PHX_HAS_SUBMITTED)))
Expand Down
Loading

0 comments on commit 9c53dda

Please sign in to comment.