Skip to main content

WireKit v2.63.0

Minor release

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::json() 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 a style attribute; 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 through window.Apex stays in place, and it has to escape what it returns.
  • A value handed to a component stays data when your application has called Blade::withoutDoubleEncoding(). After that call {{ }} leaves a character reference such as &quot; or &#106; as 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 &quot; 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 as &#106;avascript: passed the scheme check and reached the browser as javascript:. 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 use AlpinePayload::from() in a directive of your own, the fix applies there. If you read its output back with JSON.parse(), write that value with AlpinePayload::json() instead: 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, the sort-key the table starts on and the keys its columns name. With a rowActions slot 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 href into the link unchecked, and the breadcrumb's structured data carried it as the step's URL. They now keep http, https, mailto, tel and relative URLs, like every other component that reads a link target from a list. A crumb whose target is refused renders like one without href: 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 href into the link unchecked as well, and keep the same targets now. A step whose target is refused renders like one without href: as a button when it carries a wire:click and as text when not. A step with an empty href is no link either; it linked to its own page before.
  • A color picker preset is drawn only as a color. Each entry of presets on a color picker went into its swatch's style as 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() or oklch(), the forms the picker reads. Any other entry draws no swatch and is reported like every rejected prop value, a color name such as red included; 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:click alone. The component also read it from a key named action, 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 named action into a button that ran its value. If you used that key, write wire:click. An empty wire:click no longer renders a button that does nothing.
  • An entry of an overflow nav takes its target from href alone. An href among the entry's attributes reached 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::json() writes a value your script reads back with JSON.parse(). A data- attribute or a hidden field is not a directive, and AlpinePayload::from() is the encoder for a directive. 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 screen wk-field lifts a field's text to 16px through its text token. A select, input or textarea of your own whose size is a literal such as text-[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-floor there, and at least the size of the text around it. Until 2.61.0 wk-field set 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 as Europe/Berlin converts 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() and sortBy() keep the keys of what they return, and five places read such a list by its keys. The labels of a chart and the data of 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 name written with [] keeps one. name="skills[]", the way a native multiple select is written, submitted skills[][] from a multi-select, a tags input and a multiple file upload, which PHP reads as a list of one-item lists. Both spellings submit skills[] 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 wireStream under Chart.js, each point that arrived threw Maximum call stack size exceeded in 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 x is a timestamp, given as an object or as a pair, was titled with the number (1767225600000), one whose x is a date string with the string itself, and tooltip.x.format was not read, although the date previews on the chart pages set it. The title is now the date in that format, ApexCharts' own dd MMM until you set one, with names in your application's locale, in UTC as the axis is labeled unless xaxis.labels.datetimeUTC is 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 shows dd MMM there 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, read undefined. A gap in a series read null. 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 as x and y, the form the candlestick page shows.
  • A formatter set for every chart titles a point on a date axis. A tooltip.x.formatter or an xaxis.labels.formatter set through window.Apex decides the title of ApexCharts' own tooltip, and the tooltip WireKit draws wrote the date in tooltip.x.format instead. It takes its title from that formatter now, and writes what the formatter returns as text.
  • A countdown counts to the instant an immutable date holds. A CarbonImmutable, which every model hands over in an application that has called Date::use(CarbonImmutable::class), 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.
  • 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 mutable Carbon was converted in place, so your own variable came back in the reader's zone.
  • A Tab inside 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's body, 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 with Shift+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-touch keeps 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 with wire:model.live for 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-header on 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:verify notices an update installed from a release. Composer keeps the release archive's times on every file it unpacks, so after a composer update the 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 a vendor directory 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: smooth on the page's root, as Tailwind's scroll-smooth sets: the jump glided again. They jump now.
  • The scrollToMessage() of 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.
  • 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 0 or 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 is 0 without its link.
  • A trail built with Schema::breadcrumbList() treats an address the breadcrumb would not link as a step without a page. The builder kept any address as the step's item, a javascript: one included, while the component left that step out. Both read the address by the same rule now: http, https, mailto, tel or relative.

Documentation

  • The CSS API page says what wk-field does 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, tel and 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