WireKit v2.63.0
Minor. A value handed to a component stays data when the application has turned off double encoding in Blade, the labels, series names and goals of an ApexCharts chart reach its legend and tooltip as text, AlpinePayload:: is new for a value your own script reads back, and a countdown and a message write their times in the reader's zone with timezone. A breadcrumb and a stepper check the link targets of their items, a color picker draws a preset only as a color, a list prop takes a Collection, a record goes into the page with only the keys its component reads, a field you build yourself asks for the touch text floor, a Tab in Safari stays inside an open dialog, a calendar, a kanban column and a data table's toolbar fit a 320px screen, the keys of an input method stay with it while it converts, a list field's name written with [] keeps one, and an empty list announces nothing. A Chart.js chart draws the data a Livewire update gives it and the points streamed into it, an ApexCharts chart keeps its data through a theme change, its tooltip titles a point on a date axis with its date, lists only the series on the hovered date and reads a candle in every form ApexCharts takes, a date of any class keeps its instant, a dialog from a touch region keeps its sizes through a Livewire update, wirekit:verify notices an update installed from a release, and a scroll a component starts under reduced motion is a jump also on a page whose root scrolls smoothly.
Security
- The labels, series names and goals of an ApexCharts chart reach its legend and its tooltip as text. With
library="apexcharts", a chart wrote the labels and the names of its datasets into its legend and its tooltip as HTML, even behind the tooltip WireKit draws, so a name from your data that held markup ran in the page when the chart was drawn or hovered. In every chart type a name with<or&now shows those characters, and the dates of a date axis keep their format. The name, the value and the color of a goal on a bar went into the tooltip the same way, the color inside astyleattribute; they reach ApexCharts as text too, when the chart is drawn, when a Livewire update changes its data and when a point is streamed in, and a valid color draws as before. A formatter set for every chart throughwindow.Apexstays in place, and it has to escape what it returns. - A value handed to a component stays data when your application has called
Blade::. After that callwithout Double Encoding() {{ }}leaves a character reference such as"orjas it is, and the browser decodes it inside the attribute. In a directive, the decoded quote ended the string it sat in: a label, an option or a step name that held"followed by an expression ran that expression when the page loaded, in every component that hands a text or a list to Alpine. In the state a script parses, the rows of a data table or the list of a filter builder, it could add keys. And a link target written asjavascript:passed the scheme check and reached the browser asjavascript:. A decoded reference now stays inside its string, and a link target is checked with its references decoded as well. With Laravel's standard echo none of this was reachable, and nothing changes in what a component reads. If you useAlpinePayload::in a directive of your own, the fix applies there. If you read its output back withfrom() JSON.parse(), write that value withAlpinePayload::instead:json() from()writes a JavaScript literal, and one that holds a character reference is not JSON. - A record handed to an event calendar, a map or a notification center goes into the page with only the keys of its shape. These components write their list into the page for their script, and each record went with every key it had, so a record from a query carried its other columns into the page's source as well. The events and day markers of an event calendar, the markers of a map and the notifications of a notification center now carry the keys their page lists, and an attendee its name and avatar. A script of your own that read another key from one of these components' state no longer finds it.
- The rows of a data table go into the page with only the fields the table reads. Each row went with every key it had, so the rows of a query shown as a name and an email carried each customer's other columns into the page's source. A row now carries its
row-key, thesort-keythe table starts on and the keys its columns name. With arowActionsslot the rows still go whole, because the slot has the row in scope; the page shows how to hand such a table only the fields it may show. - A crumb whose target comes from your data can no longer run script. The items of a breadcrumb put their
hrefinto the link unchecked, and the breadcrumb's structured data carried it as the step's URL. They now keephttp,https,mailto,teland relative URLs, like every other component that reads a link target from a list. A crumb whose target is refused renders like one withouthref: as text, in the trail and in the structured data. - A step whose target comes from your data can no longer run script. The steps of a stepper put their
hrefinto the link unchecked as well, and keep the same targets now. A step whose target is refused renders like one withouthref: as a button when it carries awire:clickand as text when not. A step with an emptyhrefis no link either; it linked to its own page before. - A color picker preset is drawn only as a color. Each entry of
presetson a color picker went into its swatch'sstyleas written, so an entry that carried further declarations behind a color styled the swatch itself: it could lie over the whole page as an invisible field while the popover was open. A preset is now a hex color,rgb(),hsl()oroklch(), the forms the picker reads. Any other entry draws no swatch and is reported like every rejected prop value, a color name such asredincluded; a click on such a swatch never picked a color. The recent colors a picker keeps in the browser's storage are checked the same way. - A step of a stepper takes its action from
wire:clickalone. The component also read it from a key namedaction, which was never documented. Livewire evaluates that value as an expression when the step is clicked, so a list of steps built from your rows turned a column namedactioninto a button that ran its value. If you used that key, writewire:click. An emptywire:clickno longer renders a button that does nothing. - An entry of an overflow nav takes its target from
hrefalone. Anhrefamong the entry'sattributesreached the link as written, and when the entry's own target had been refused it was the only one the link had. That key is left out of the attributes now; everything else in them still reaches the anchor.
Added
AlpinePayload::writes a value your script reads back withjson() JSON.parse(). Adata-attribute or a hidden field is not a directive, andAlpinePayload::is the encoder for a directive.from() json()writes JSON that stays one value whichever way your application echoes it. The CLI reference shows the two side by side.- A field you build yourself takes the touch text floor with
wk-touch-text-floor. On a touch screenwk-fieldlifts a field's text to 16px through its text token. Aselect,inputortextareaof your own whose size is a literal such astext-[15px], or inherited, has no token to lift: it stayed below 16px on a phone, and mobile Safari zooms the page when such a field takes focus. With the marker the field shows at least--text-wk-touch-floorthere, and at least the size of the text around it. Until 2.61.0wk-fieldset every field to exactly 16px, so a hand-built field with a literal size below that was lifted then and has not been since; it needs the marker now. The integration guide shows both cases. - A countdown and a message write their times in the reader's zone with
timezone. A name such asEurope/Berlinconverts the deadline a countdown names in its accessible name, and the timestamp and the status time of a message, before they are written. Without it, a time stays in the zone of the value, which for a date from the database is usually UTC.
Fixed
- A list prop takes a Collection. The trail of a breadcrumb, the steps of a stepper and a wizard, the selected values of a tags input and a multi-select, the levels of a strength meter, the items of an overflow nav, the countries of a phone field, the data of a sparkline and the labels and datasets of a chart threw on a Collection or rendered as if nothing had been passed, so a tags input or a multi-select started empty although the values were there. Each takes an array or a Collection now, a lazy Collection and a paginator included, so
$user->skills->pluck('id')goes in as it is. The integration guide says it once for every list prop. - A map, a record and a paginator go into a component as they are. The options a
pluck('label', 'value')returns made a segmented control throw, and so did the marks of a slider as a Collection. The intervals of a pricing table, the names behind a reaction, the value texts of a slider and a range slider and the hidden columns of a data table were read as no value when they arrived as a Collection. A data table, an event calendar, a notification center and a status matrix read a paginator or a lazy Collection as the object's own properties, so a table given a paginator showed its page size and its path as rows. A message whose author was a model wrote the whole record into the author's name. Each takes an array, a Collection, a lazy Collection and a paginator now, and reads a model as the record it holds. - The items of a list may be models. The result of a query is a Collection of models, and a component that prints one field of each item took a model for a plain text, which for a model is the JSON of the whole record. A stepper and a wizard wrote it as the step's label, a breadcrumb as the crumb, an image gallery and a lightbox as the image's address, quick replies as the reply's value, a combobox and a multi-select as the option's value, and the sources of an assistant message as the chip's label, although that page names models as an input. A scope switcher and a chart threw. Each reads a model as the record it holds now, so only the fields a component reads reach the page.
- A filtered or sorted Collection is read as the list it is.
filter(),where()andsortBy()keep the keys of what they return, and five places read such a list by its keys. Thelabelsof a chart and thedataof a series reached the chart as an object: ApexCharts drew nothing, and Chart.js put the bars under new categories named after the keys, or threw. A sparkline threw on the missing first key, a stepper numbered its steps by their keys and marked the wrong one as current, and a select field of a filter builder offered no options. Each reads its items in the order the Collection has them now, so a sorted list also stays sorted. - A list field's
namewritten with[]keeps one.name="skills[]", the way a native multiple select is written, submittedskills[][]from a multi-select, a tags input and a multiple file upload, which PHP reads as a list of one-item lists. Both spellings submitskills[]now. - A Chart.js chart draws the data a Livewire update gives it. Since 2.56.0 a chart under Chart.js took the new labels and series of a Livewire update and went on showing the old ones: the update reached the chart through Alpine's reactive wrapper and threw
Maximum call stack size exceeded, and the component caught the error, so nothing reported it. A change of the reduced-motion setting while the page is open failed the same way. Both redraw the chart now. A chart that is removed from the page is also let go by Chart.js, whose animation queue kept every removed chart in memory. - A point streamed into a Chart.js chart is drawn. With
wireStreamunder Chart.js, each point that arrived threwMaximum call stack size exceededin the console and the chart went on drawing the points it already had, because the stream updated it through Alpine's reactive wrapper. The point is added and drawn now. - An ApexCharts chart keeps the data a Livewire update or a stream gave it when the theme changes. With
library="apexcharts", a change between light and dark, by a toggle or by the reader's system while the page is open, drew the chart again with the data it was first drawn with: a report filtered to another period went back to the one it loaded with, and streamed points disappeared. It keeps what it shows now, in the colors of the new theme. - The tooltip of an ApexCharts chart on a date axis titles a point with its date. A point whose
xis a timestamp, given as an object or as a pair, was titled with the number (1767225600000), one whosexis a date string with the string itself, andtooltip.was not read, although the date previews on the chart pages set it. The title is now the date in that format, ApexCharts' ownx. format dd MMMuntil you set one, with names in your application's locale, in UTC as the axis is labeled unlessxaxis.islabels. datetimeUTC false. The two ends of a range on a timeline follow the same format and zone. They were a short date with the year in the reader's zone, which put a range that starts at midnight UTC on the day before for a reader west of UTC, and an end before 1970 stayed a negative number. A timeline without a format of its own now showsdd MMMthere as well;'tooltip' => ['x' => ['format' => 'MMM dd, yyyy']]keeps the year. A range column or a range area writes the ends of its ranges as the values they are, where an end above ten billion read as a date. - A shared tooltip of an ApexCharts chart lists the series on the hovered date. With
library="apexcharts", the tooltip of a chart whose series have dates of their own listed the value every series holds at the hovered position: a value of January 1st stood under January 11th, and a series that ends earlier, or one switched off in the legend, readundefined. A gap in a series readnull. A series on another date is left out now, and a series without a value at the hovered point has no row. - A candle given as one flat list is read as a candle. ApexCharts also takes a candlestick point as
[x, open, high, low, close], and the tooltip wrote such a point as a boxplot whose minimum was the timestamp. A candle and a boxplot now show the numbers ApexCharts read, in each form it takes: flat, nested, or asxandy, the form the candlestick page shows. - A formatter set for every chart titles a point on a date axis. A
tooltip.or anx. formatter xaxis.set throughlabels. formatter window.Apexdecides the title of ApexCharts' own tooltip, and the tooltip WireKit draws wrote the date intooltip.instead. It takes its title from that formatter now, and writes what the formatter returns as text.x. format - A countdown counts to the instant an immutable date holds. A
CarbonImmutable, which every model hands over in an application that has calledDate::, was written out without its offset and read in the application's zone, so a deadline handed over in Berlin counted an hour or two too long. Any date object now counts to the instant it holds.use(Carbon Immutable:: class) - A date separator shows an immutable date in its
timezone, and leaves the date it is handed as it was. An immutable date kept its own zone, so a message sent at 23:30 UTC stood under yesterday for a reader in Berlin, and a mutableCarbonwas converted in place, so your own variable came back in the reader's zone. - A
Tabinside an open dialog no longer takes the focus out of the page in Safari. By default, Safari on a Mac stops a Tab on text fields and pop-up menus and passes buttons, links, checkboxes and radios by. In a modal, a drawer or any other overlay that traps the focus, a Tab from the last control Safari stops on found nothing further inside: the focus went to the page'sbody, and the dialog stayed open without the keyboard in it. The control Safari passed by takes the focus now, so a dialog that ends on its buttons reaches them, and one that begins on its close button reaches that withShift+Tab. - The keys of an input method stay with it while it converts. The Enter that confirms a Japanese, Chinese or Korean conversion added the half-converted text as a tag in a tags input and picked an option in a combobox and a multi-select, and an Escape that abandoned a conversion in a field of a modal or a drawer closed the dialog. WireKit leaves Enter, the arrow keys and Escape to the input method while it converts, in its own fields and in fields you write inside its dialogs. The localization page says what that covers.
- A dialog or a drawer opened from inside
data-wk-touchkeeps the touch sizes while a Livewire update runs. The panel took the touch sizes when it opened, and the first server round trip with it open, from a field bound withwire:model.livefor one, put its fields and buttons back to the mouse sizes on a till with a mouse plugged in. It keeps them now for as long as it is open, as touch sizes on any pointer promises. - A calendar fits a container down to 222px. A day was 36px wide whatever its container, so the grid needed 280px and the panel 306px, and on a 320px screen, which is also the width a desktop reader has at 400% zoom, the last column was cut off. A day now shrinks with its column down to 24px, the smallest target WCAG 2.5.8 allows, and keeps its 36px wherever there is room, so a calendar in a container that sizes to its content is as wide as before. With
selectable-headeron a touch screen the year moves under the month where the two do not fit beside the arrows. - A kanban column fills a board narrower than 280px instead of standing out past it, in a vertical board on a phone and in a narrow horizontal one.
- The toolbar of a data table wraps its density toggle and its column button where the two do not fit beside each other.
- A multi-select and a tags input fit a narrow container in Safari. WebKit took the default width of their text input as its minimum, so on a 320px screen the field stood 13px past a container Chromium filled exactly.
- An empty list announces nothing. An empty breadcrumb trail, as on an application's home page, rendered a navigation landmark around an empty list; the landmark is hidden now unless the actions slot holds a control. A stepper without steps hides its list, and a tabs row without tabs carries no tablist role.
wirekit:verifynotices an update installed from a release. Composer keeps the release archive's times on every file it unpacks, so after acomposer updatethe checks for a build, a compiled view cache and a generated AI catalog older than the installed package compared them with the day of the release, and stayed quiet about one made between the release and the update. They date the install by the package directory now. A deploy that copies avendordirectory onto a server dates the install by the copy there; run the check where the build runs.- Under reduced motion a scroll a component starts is a jump, also on a page whose root scrolls smoothly. Scroll to top, the reading primitives, a tour, a conversation and a carousel answered reduced motion with the browser's default scroll behavior, and that follows a
scroll-behavior: smoothon the page's root, as Tailwind'sscroll-smoothsets: the jump glided again. They jump now. - The
scrollof a conversation finds a message whose id holds a quote or a backslash. The id went into a selector as written, and the selector was invalid.To Message() - A link target with a long run of spaces inside it no longer stalls the render. On a PHP without the PCRE JIT, checking such a target took quadratic time, over a second for 16,000 spaces. The check is linear now, and it reads an upper-case scheme and trims a target the same way under every locale; under two legacy locales it had dropped every link.
- A link target given as a backed enum, as
0or as a number works in every list component. An overflow nav and a scope switcher threw on a backed enum, and a breadcrumb and status tiles drew an entry whose target is0without its link. - A trail built with
Schema::treats an address the breadcrumb would not link as a step without a page. The builder kept any address as the step'sbreadcrumb List() item, ajavascript:one included, while the component left that step out. Both read the address by the same rule now:http,https,mailto,telor relative.
Documentation
- The CSS API page says what
wk-fielddoes on a touch screen. It still described the fixed 16px that 2.61.0 replaced. The class lifts the field's text tokens to at least 16px, and a size written as a literal on the field is not lifted. - Five examples wrap on a 320px screen instead of running past their frame: on the pages of the link component, the lightbox, the spacer, the file upload and the scope switcher.
- The marketing landing page recipe shows the sparkline of its third figure. The line was drawn in the color of the card it sits on and could not be seen in either theme.
- Five pages say which link targets are kept. The pages of the overflow nav, status tiles, scope switcher, notification center and assistant message said a target is dropped when its scheme could run script. The rule is a list:
http,https,mailto,teland relative addresses become links, and every other scheme is dropped. - The scroll to top page no longer says that browsers turn smooth scrolling off under reduced motion on their own. They do not; the button decides it, and the page says how.
Components
Every component this release changes, each linked to its page: Accordion · Alert Dialog · App Shell · Breadcrumb · Button · Calendar · Carousel · Chart · Chart Mixed · Checkbox · Collapsible · Color Picker · Combobox · Command Palette · Conversation · Countdown · Data Table · Date Picker · Date Separator · Drawer · Dropdown · Editor · Event Calendar · File Upload · Filter Builder · Hover Card · Image Gallery · Inline Edit · Input · Kanban · Lightbox · Map · Message · Message Group · Modal · Multi-Select · Notification Center · Number Input · OTP Input · Overflow Nav · Pagination · Password Input · Phone · Popover · Pricing Table · Profile · Quick Replies · Range Slider · Rating · Reaction · Reading · Scope Switcher · Scroll to Top · Segmented Control · Select · Slider · Sparkline · Stat · Status Matrix · Status Tiles · Stepper · Stream · Strength Meter · Tabs · Tags Input · Textarea · Theme Controller · Time Picker · Toggle · Toggle Button · Tooltip · Tour · Wizard