diff --git a/package.json b/package.json index e0f03f409..32c620f33 100644 --- a/package.json +++ b/package.json @@ -17,20 +17,20 @@ "test:react": "PACKAGE=react playwright test", "test:svelte": "PACKAGE=svelte playwright test", "test:vue": "PACKAGE=vue3 playwright test", - "playground:react": "cd playgrounds/react && composer run dev", - "playground:svelte4": "cd playgrounds/svelte4 && composer run dev", - "playground:svelte5": "cd playgrounds/svelte5 && composer run dev", - "playground:vue": "cd playgrounds/vue3 && composer run dev", + "playground:react": "cd playgrounds/react && ./init.sh && composer run dev", + "playground:svelte4": "cd playgrounds/svelte4 && ./init.sh && composer run dev", + "playground:svelte5": "cd playgrounds/svelte5 && ./init.sh && composer run dev", + "playground:vue": "cd playgrounds/vue3 && ./init.sh && composer run dev", "format": "prettier --write ." }, "dependencies": { - "@playwright/test": "^1.55.0", - "prettier": "^3.2.5", - "prettier-plugin-organize-imports": "^4.1.0", - "prettier-plugin-svelte": "^3.2.3", - "prettier-plugin-tailwindcss": "^0.6.9" + "@playwright/test": "^1.55.1", + "prettier": "^3.6.2", + "prettier-plugin-organize-imports": "^4.3.0", + "prettier-plugin-svelte": "^3.4.0", + "prettier-plugin-tailwindcss": "^0.6.14" }, "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "^4.28.1" + "@rollup/rollup-linux-x64-gnu": "^4.52.2" } } diff --git a/packages/core/package.json b/packages/core/package.json index eec48ed15..225a3f6b2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -53,18 +53,18 @@ }, "dependencies": { "@types/lodash-es": "^4.17.12", - "axios": "^1.12.0", + "axios": "^1.12.2", "lodash-es": "^4.17.21", - "qs": "^6.9.0" + "qs": "^6.14.0" }, "devDependencies": { - "@types/deepmerge": "^2.2.0", - "@types/node": "^18.4", - "@types/nprogress": "^0.2.0", - "@types/qs": "^6.9.0", + "@types/deepmerge": "^2.2.3", + "@types/node": "^18.19.127", + "@types/nprogress": "^0.2.3", + "@types/qs": "^6.14.0", "es-check": "^9.3.1", - "esbuild": "^0.25.0", - "esbuild-node-externals": "^1.6.0", + "esbuild": "^0.25.10", + "esbuild-node-externals": "^1.18.0", "typescript": "^5.9.2" } } diff --git a/packages/core/src/domUtils.ts b/packages/core/src/domUtils.ts new file mode 100644 index 000000000..59fe213bf --- /dev/null +++ b/packages/core/src/domUtils.ts @@ -0,0 +1,57 @@ +const elementInViewport = (el: HTMLElement) => { + const rect = el.getBoundingClientRect() + + // We check both vertically and horizontally for containers that scroll in either direction + const verticallyVisible = rect.top < window.innerHeight && rect.bottom >= 0 + const horizontallyVisible = rect.left < window.innerWidth && rect.right >= 0 + + return verticallyVisible && horizontallyVisible +} + +export const getScrollableParent = (element: HTMLElement | null): HTMLElement | null => { + let parent = element?.parentElement + + while (parent) { + const overflowY = window.getComputedStyle(parent).overflowY + + if (overflowY === 'auto' || overflowY === 'scroll') { + return parent + } + + parent = parent.parentElement + } + + return null +} + +export const getElementsInViewportFromCollection = ( + referenceElement: HTMLElement, + elements: HTMLElement[], +): HTMLElement[] => { + const referenceIndex = elements.indexOf(referenceElement) + const visibleElements: HTMLElement[] = [] + + // Traverse upwards until an element is not visible + for (let i = referenceIndex; i >= 0; i--) { + const element = elements[i] + + if (elementInViewport(element)) { + visibleElements.push(element) + } else { + break + } + } + + // Traverse downwards until an element is not visible + for (let i = referenceIndex + 1; i < elements.length; i++) { + const element = elements[i] + + if (elementInViewport(element)) { + visibleElements.push(element) + } else { + break + } + } + + return visibleElements +} diff --git a/packages/core/src/events.ts b/packages/core/src/events.ts index 879008c92..00b866471 100644 --- a/packages/core/src/events.ts +++ b/packages/core/src/events.ts @@ -27,6 +27,10 @@ export const fireInvalidEvent: GlobalEventTrigger<'invalid'> = (response) => { return fireEvent('invalid', { cancelable: true, detail: { response } }) } +export const fireBeforeUpdateEvent: GlobalEventTrigger<'beforeUpdate'> = (page) => { + return fireEvent('beforeUpdate', { detail: { page } }) +} + export const fireNavigateEvent: GlobalEventTrigger<'navigate'> = (page) => { return fireEvent('navigate', { detail: { page } }) } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 37e3ee3c3..08ecfbaae 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,8 +1,10 @@ import { Router } from './router' +export { getScrollableParent } from './domUtils' export { objectToFormData } from './formData' export { formDataToObject } from './formObject' export { default as createHeadManager } from './head' +export { default as useInfiniteScroll } from './infiniteScroll' export { shouldIntercept, shouldNavigate } from './navigationEvents' export { hide as hideProgress, progress, reveal as revealProgress, default as setupProgress } from './progress' export { resetFormFields } from './resetFormFields' diff --git a/packages/core/src/infiniteScroll.ts b/packages/core/src/infiniteScroll.ts new file mode 100644 index 000000000..46d97c34b --- /dev/null +++ b/packages/core/src/infiniteScroll.ts @@ -0,0 +1,95 @@ +import { useInfiniteScrollData } from './infiniteScroll/data' +import { useInfiniteScrollElementManager } from './infiniteScroll/elements' +import { useInfiniteScrollQueryString } from './infiniteScroll/queryString' +import { useInfiniteScrollPreservation } from './infiniteScroll/scrollPreservation' +import { Page, ReloadOptions, UseInfiniteScrollOptions, UseInfiniteScrollProps } from './types' + +/** + * Core infinite scroll composable that orchestrates data fetching, DOM management, + * scroll preservation, and URL synchronization. + * + * This is the main entry point that coordinates four sub-systems: + * - Data management: Handles pagination state and server requests + * - Element management: DOM observation and intersection detection + * - Query string sync: Updates URL as user scrolls through pages + * - Scroll preservation: Maintains scroll position during content updates + */ +export default function useInfiniteScroll(options: UseInfiniteScrollOptions): UseInfiniteScrollProps { + const queryStringManager = useInfiniteScrollQueryString({ ...options, getPageName: () => dataManager.getPageName() }) + + // Create scroll preservation callbacks that capture and restore scroll position + // and restore it after new content is prepended to maintain visual stability + const scrollPreservation = useInfiniteScrollPreservation(options) + + const elementManager = useInfiniteScrollElementManager({ + ...options, + // As items enter viewport, update URL to reflect the most visible page + onItemIntersected: queryStringManager.onItemIntersected, + onPreviousTriggered: () => dataManager.fetchPrevious(), + onNextTriggered: () => dataManager.fetchNext(), + }) + + const dataManager = useInfiniteScrollData({ + ...options, + // Before updating page data, tag any manually added DOM elements + // so they don't get confused with server-loaded content + onBeforeUpdate: elementManager.processManuallyAddedElements, + // After successful request, tag new server content + onCompletePreviousRequest: (loadedPage?: string | number) => { + setTimeout(() => { + elementManager.processServerLoadedElements(loadedPage) + options.onCompletePreviousRequest() + window.queueMicrotask(elementManager.refreshTriggers) + }) + }, + onCompleteNextRequest: (loadedPage?: string | number) => { + setTimeout(() => { + elementManager.processServerLoadedElements(loadedPage) + options.onCompleteNextRequest() + window.queueMicrotask(elementManager.refreshTriggers) + }) + }, + }) + + const addScrollPreservationCallbacks = (reloadOptions: ReloadOptions): ReloadOptions => { + const { captureScrollPosition, restoreScrollPosition } = scrollPreservation.createCallbacks() + + const originalOnBeforeUpdate = reloadOptions.onBeforeUpdate || (() => {}) + const originalOnSuccess = reloadOptions.onSuccess || (() => {}) + + reloadOptions.onBeforeUpdate = (page: Page) => { + originalOnBeforeUpdate(page) + captureScrollPosition() + } + + reloadOptions.onSuccess = (page: Page) => { + originalOnSuccess(page) + restoreScrollPosition() + } + + return reloadOptions + } + + const originalFetchNext = dataManager.fetchNext + dataManager.fetchNext = (reloadOptions: ReloadOptions = {}) => { + if (options.inReverseMode()) { + reloadOptions = addScrollPreservationCallbacks(reloadOptions) + } + + originalFetchNext(reloadOptions) + } + + const originalFetchPrevious = dataManager.fetchPrevious + dataManager.fetchPrevious = (reloadOptions: ReloadOptions = {}) => { + if (!options.inReverseMode()) { + reloadOptions = addScrollPreservationCallbacks(reloadOptions) + } + + originalFetchPrevious(reloadOptions) + } + + return { + dataManager, + elementManager, + } +} diff --git a/packages/core/src/infiniteScroll/data.ts b/packages/core/src/infiniteScroll/data.ts new file mode 100644 index 000000000..8d16b83b8 --- /dev/null +++ b/packages/core/src/infiniteScroll/data.ts @@ -0,0 +1,111 @@ +import { router } from '../index' +import { page as currentPage } from '../page' +import { Page, PendingVisit, ReloadOptions, ScrollProp, UseInfiniteScrollDataManager } from '../types' + +const MERGE_INTENT_HEADER = 'X-Inertia-Infinite-Scroll-Merge-Intent' + +type Side = 'previous' | 'next' +type ScrollPropPageNames = keyof Pick + +export const useInfiniteScrollData = (options: { + getPropName: () => string + onBeforeUpdate: () => void + onBeforePreviousRequest: () => void + onBeforeNextRequest: () => void + onCompletePreviousRequest: (loadedPage?: string | number) => void + onCompleteNextRequest: (loadedPage?: string | number) => void +}): UseInfiniteScrollDataManager => { + const getScrollPropFromCurrentPage = (): ScrollProp => { + const scrollProp = currentPage.get().scrollProps?.[options.getPropName()] + + if (scrollProp) { + return scrollProp + } + + throw new Error(`The page object does not contain a scroll prop named "${options.getPropName()}".`) + } + + const { previousPage, nextPage, currentPage: lastLoadedPage } = getScrollPropFromCurrentPage() + + const state = { + loading: false, + previousPage, + nextPage, + lastLoadedPage, + } + + const getScrollPropKeyForSide = (side: Side): ScrollPropPageNames => { + return side === 'next' ? 'nextPage' : 'previousPage' + } + + const findPageToLoad = (side: Side) => { + const pagePropName = getScrollPropKeyForSide(side) + + return state[pagePropName] + } + + const syncStateOnSuccess = (side: Side) => { + const scrollProp = getScrollPropFromCurrentPage() + const paginationProp = getScrollPropKeyForSide(side) + + state.lastLoadedPage = scrollProp.currentPage + state[paginationProp] = scrollProp[paginationProp] + } + + const getPageName = () => getScrollPropFromCurrentPage().pageName + + const fetchPage = (side: Side, reloadOptions: ReloadOptions = {}): void => { + const page = findPageToLoad(side) + + if (state.loading || page === null) { + return + } + + state.loading = true + + router.reload({ + ...reloadOptions, + data: { [getPageName()]: page }, + only: [options.getPropName()], + preserveUrl: true, // we handle URL updates manually via useInfiniteScrollQueryString() + headers: { + [MERGE_INTENT_HEADER]: side === 'previous' ? 'prepend' : 'append', + ...reloadOptions.headers, + }, + onBefore: (visit: PendingVisit) => { + side === 'next' ? options.onBeforeNextRequest() : options.onBeforePreviousRequest() + reloadOptions.onBefore?.(visit) + }, + onBeforeUpdate: (page: Page) => { + options.onBeforeUpdate() + reloadOptions.onBeforeUpdate?.(page) + }, + onSuccess: (page: Page) => { + syncStateOnSuccess(side) + reloadOptions.onSuccess?.(page) + }, + onFinish: (visit: any) => { + state.loading = false + side === 'next' + ? options.onCompleteNextRequest(state.lastLoadedPage) + : options.onCompletePreviousRequest(state.lastLoadedPage) + reloadOptions.onFinish?.(visit) + }, + }) + } + + const getLastLoadedPage = () => state.lastLoadedPage + const hasPrevious = () => !!state.previousPage + const hasNext = () => !!state.nextPage + const fetchPrevious = (reloadOptions?: ReloadOptions): void => fetchPage('previous', reloadOptions) + const fetchNext = (reloadOptions?: ReloadOptions): void => fetchPage('next', reloadOptions) + + return { + getLastLoadedPage, + getPageName, + hasPrevious, + hasNext, + fetchNext, + fetchPrevious, + } +} diff --git a/packages/core/src/infiniteScroll/elements.ts b/packages/core/src/infiniteScroll/elements.ts new file mode 100644 index 000000000..01fc9766b --- /dev/null +++ b/packages/core/src/infiniteScroll/elements.ts @@ -0,0 +1,154 @@ +import { useIntersectionObservers } from '../intersectionObservers' +import { UseInfiniteScrollElementManager } from '../types' + +const INFINITE_SCROLL_PAGE_KEY = 'infiniteScrollPage' +const INFINITE_SCROLL_IGNORE_KEY = 'infiniteScrollIgnore' + +export const getPageFromElement = (element: HTMLElement): string | undefined => + element.dataset[INFINITE_SCROLL_PAGE_KEY] + +export const useInfiniteScrollElementManager = (options: { + shouldFetchNext: () => boolean + shouldFetchPrevious: () => boolean + getTriggerMargin: () => number + getStartElement: () => HTMLElement + getEndElement: () => HTMLElement + getItemsElement: () => HTMLElement + getScrollableParent: () => HTMLElement | null + onPreviousTriggered: () => void + onNextTriggered: () => void + onItemIntersected: (element: HTMLElement) => void +}): UseInfiniteScrollElementManager => { + const intersectionObservers = useIntersectionObservers() + + let itemsObserver: IntersectionObserver + let startElementObserver: IntersectionObserver + let endElementObserver: IntersectionObserver + let itemsMutationObserver: MutationObserver + let triggersEnabled = false + + const setupObservers = () => { + // Watch for manually added DOM elements (not from server responses) + // This mutation observer tracks when new elements are added to the slot, + // so we can distinguish between user-added content and server-loaded pages + itemsMutationObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + mutation.addedNodes.forEach((node) => { + if (node.nodeType === Node.ELEMENT_NODE) { + addedElements.add(node as HTMLElement) + } + }) + }) + }) + + itemsMutationObserver.observe(options.getItemsElement(), { childList: true }) + + // Track individual items entering/leaving viewport for URL synchronization + // When items become visible, we update the URL to reflect the current page + itemsObserver = intersectionObservers.new( + (entry: IntersectionObserverEntry) => options.onItemIntersected(entry.target as HTMLElement), + { threshold: 0 }, + ) + + // Set up trigger zones at start/end that load more content when intersected. The rootMargin + // creates a buffer zone so loading starts before user reaches the edge. We should always + // have a root margin of at least 1px as our default elements have no height + const observerOptions: IntersectionObserverInit = { + root: options.getScrollableParent(), + rootMargin: `${Math.max(1, options.getTriggerMargin())}px`, + } + + startElementObserver = intersectionObservers.new(options.onPreviousTriggered, observerOptions) + endElementObserver = intersectionObservers.new(options.onNextTriggered, observerOptions) + } + + const enableTriggers = () => { + if (triggersEnabled) { + // Make sure we don't register multiple watchers + disableTriggers() + } + + const startElement = options.getStartElement() + const endElement = options.getEndElement() + + if (startElement && options.shouldFetchPrevious()) { + startElementObserver.observe(startElement) + } + + if (endElement && options.shouldFetchNext()) { + endElementObserver.observe(endElement) + } + + triggersEnabled = true + } + + const disableTriggers = () => { + if (!triggersEnabled) { + return + } + + startElementObserver.disconnect() + endElementObserver.disconnect() + triggersEnabled = false + } + + const refreshTriggers = () => { + if (triggersEnabled) { + enableTriggers() + } + } + + const flushAll = () => { + intersectionObservers.flushAll() + itemsMutationObserver?.disconnect() + } + + const addedElements = new Set() + + const elementIsUntagged = (element: HTMLElement): boolean => + !(INFINITE_SCROLL_PAGE_KEY in element.dataset) && !(INFINITE_SCROLL_IGNORE_KEY in element.dataset) + + const processManuallyAddedElements = () => { + // Tag manually added elements so they don't interfere with URL management + // These elements get marked as "ignore" since they weren't loaded from the server + Array.from(addedElements).forEach((element) => { + if (elementIsUntagged(element)) { + element.dataset[INFINITE_SCROLL_IGNORE_KEY] = 'true' + } + + itemsObserver.observe(element) + }) + + addedElements.clear() + } + + const findUntaggedElements = (containerElement: HTMLElement): HTMLElement[] => { + return Array.from( + containerElement.querySelectorAll( + `:scope > *:not([data-infinite-scroll-page]):not([data-infinite-scroll-ignore])`, + ), + ) + } + + const processServerLoadedElements = (loadedPage?: string | number) => { + // Tag new server-loaded elements with their page number for URL management + // This allows us to update the URL based on which page's content is most visible + findUntaggedElements(options.getItemsElement()).forEach((element) => { + if (elementIsUntagged(element)) { + element.dataset[INFINITE_SCROLL_PAGE_KEY] = loadedPage?.toString() || '1' + } + + itemsObserver.observe(element) + }) + } + + return { + setupObservers, + enableTriggers, + disableTriggers, + refreshTriggers, + flushAll, + processManuallyAddedElements, + processServerLoadedElements, + } +} diff --git a/packages/core/src/infiniteScroll/queryString.ts b/packages/core/src/infiniteScroll/queryString.ts new file mode 100644 index 000000000..f3eeb7a7c --- /dev/null +++ b/packages/core/src/infiniteScroll/queryString.ts @@ -0,0 +1,64 @@ +import debounce from '../debounce' +import { getElementsInViewportFromCollection } from '../domUtils' +import { router } from '../index' +import { getPageFromElement } from './elements' + +/** + * As users scroll through infinite content, this system updates the URL to reflect + * which page they're currently viewing. It uses a "most visible page" calculation + * so that the URL reflects whichever page has the most visible items. + */ +export const useInfiniteScrollQueryString = (options: { + getPageName: () => string + getItemsElement: () => HTMLElement + shouldPreserveUrl: () => boolean +}) => { + // Debounced to avoid excessive URL updates during fast scrolling + const onItemIntersected = debounce((itemElement: HTMLElement) => { + if (options.shouldPreserveUrl() || !itemElement) { + return + } + + // Count how many items from each page are currently visible in the viewport + const pageMap = new Map() + const elements = [...options.getItemsElement().children] as HTMLElement[] + + getElementsInViewportFromCollection(itemElement, elements).forEach((element) => { + const page = getPageFromElement(element) ?? '1' + + if (pageMap.has(page)) { + pageMap.set(page, pageMap.get(page)! + 1) + } else { + pageMap.set(page, 1) + } + }) + + // Find the page with the most visible items - this becomes the "current" page + const sortedPages = Array.from(pageMap.entries()).sort((a, b) => b[1] - a[1]) + const mostVisiblePage = sortedPages[0]?.[0] + + if (mostVisiblePage === undefined) { + return + } + + const url = new URL(window.location.href) + + // Clean URLs: don't show ?page=1 in the URL, just remove the parameter entirely + if (mostVisiblePage === '1') { + url.searchParams.delete(options.getPageName()) + } else { + url.searchParams.set(options.getPageName(), mostVisiblePage.toString()) + } + + // Update URL without triggering a page reload or affecting scroll position + router.replace({ + url: url.toString(), + preserveScroll: true, + preserveState: true, + }) + }, 250) + + return { + onItemIntersected, + } +} diff --git a/packages/core/src/infiniteScroll/scrollPreservation.ts b/packages/core/src/infiniteScroll/scrollPreservation.ts new file mode 100644 index 000000000..adc811fcd --- /dev/null +++ b/packages/core/src/infiniteScroll/scrollPreservation.ts @@ -0,0 +1,99 @@ +import { getElementsInViewportFromCollection } from '../domUtils' + +/** + * When loading content "before" the current viewport (e.g. loading page 1 when viewing page 2), + * new content is prepended to the DOM, which naturally pushes existing content down and + * disrupts the user's scroll position. This system maintains visual stability by: + * + * 1. Capturing a reference element and its position before the update + * 2. After new content is added, calculating how far that reference element moved + * 3. Adjusting scroll position to keep the reference element in the same visual location + */ +export const useInfiniteScrollPreservation = (options: { + getScrollableParent: () => HTMLElement | null + getItemsElement: () => HTMLElement +}) => { + const createCallbacks = () => { + let currentScrollTop: number + let referenceElement: Element | null = null + let referenceElementTop: number = 0 + + const captureScrollPosition = () => { + const scrollableContainer = options.getScrollableParent() + const itemsElement = options.getItemsElement() + + // Capture current scroll position + currentScrollTop = scrollableContainer?.scrollTop || window.scrollY + + // Find the first visible element to use as a reference point + // This element will help us calculate how much the content shifted after the update + const visibleElements = getElementsInViewportFromCollection( + itemsElement.firstElementChild as HTMLElement, + [...itemsElement.children] as HTMLElement[], + ) + + if (visibleElements.length > 0) { + referenceElement = visibleElements[0] + const containerRect = scrollableContainer?.getBoundingClientRect() || { top: 0 } + const containerTop = scrollableContainer ? containerRect.top : 0 + const rect = referenceElement.getBoundingClientRect() + // Store the reference element's position relative to its container + referenceElementTop = rect.top - containerTop + } + } + + const restoreScrollPosition = () => { + if (!referenceElement) { + return + } + + let attempts = 0 + let restored = false + + const restore = () => { + attempts++ + + if (restored || attempts > 10) { + return false + } + + // Calculate where our reference element ended up after new content was prepended + const scrollableContainer = options.getScrollableParent() + const containerRect = scrollableContainer?.getBoundingClientRect() || { top: 0 } + const containerTop = scrollableContainer ? containerRect.top : 0 + const newRect = referenceElement!.getBoundingClientRect() + const newElementTop = newRect.top - containerTop + + // Calculate how much the reference element moved due to content being prepended + const adjustment = newElementTop - referenceElementTop + + if (adjustment === 0) { + // Try again on the next frame, as DOM may still be updating + window.requestAnimationFrame(restore) + return + } + + // Adjust scroll position to compensate for the movement, keeping the reference element + // in the same visual position as before the update + if (scrollableContainer) { + scrollableContainer.scrollTo({ top: currentScrollTop + adjustment }) + } else { + window.scrollTo(0, window.scrollY + adjustment) + } + + restored = true + } + + restore() + } + + return { + captureScrollPosition, + restoreScrollPosition, + } + } + + return { + createCallbacks, + } +} diff --git a/packages/core/src/intersectionObservers.ts b/packages/core/src/intersectionObservers.ts new file mode 100644 index 000000000..50ac79d18 --- /dev/null +++ b/packages/core/src/intersectionObservers.ts @@ -0,0 +1,37 @@ +type IntersectionObserverCallback = (entry: IntersectionObserverEntry) => void + +interface IntersectionObserverManager { + new: (callback: IntersectionObserverCallback, options?: IntersectionObserverInit) => IntersectionObserver + flushAll: () => void +} + +export const useIntersectionObservers = (): IntersectionObserverManager => { + const intersectionObservers: IntersectionObserver[] = [] + + const newIntersectionObserver = ( + callback: IntersectionObserverCallback, + options: IntersectionObserverInit = {}, + ): IntersectionObserver => { + const observer = new IntersectionObserver((entries) => { + for (const entry of entries) { + if (entry.isIntersecting) { + callback(entry) + } + } + }, options) + + intersectionObservers.push(observer) + + return observer + } + + const flushAll = () => { + intersectionObservers.forEach((observer) => observer.disconnect()) + intersectionObservers.length = 0 + } + + return { + new: newIntersectionObserver, + flushAll, + } +} diff --git a/packages/core/src/prefetched.ts b/packages/core/src/prefetched.ts index 7f33dfabc..7c5c02936 100644 --- a/packages/core/src/prefetched.ts +++ b/packages/core/src/prefetched.ts @@ -241,6 +241,7 @@ class PrefetchedRequests { 'replace', 'prefetch', 'onBefore', + 'onBeforeUpdate', 'onStart', 'onProgress', 'onFinish', diff --git a/packages/core/src/requestParams.ts b/packages/core/src/requestParams.ts index 30bb77452..b815ff662 100644 --- a/packages/core/src/requestParams.ts +++ b/packages/core/src/requestParams.ts @@ -17,6 +17,7 @@ export class RequestParams { } else { const wrappedCallbacks: Record any> = { onBefore: this.wrapCallback(params, 'onBefore'), + onBeforeUpdate: this.wrapCallback(params, 'onBeforeUpdate'), onStart: this.wrapCallback(params, 'onStart'), onProgress: this.wrapCallback(params, 'onProgress'), onFinish: this.wrapCallback(params, 'onFinish'), diff --git a/packages/core/src/response.ts b/packages/core/src/response.ts index 1398833be..3b292edd9 100644 --- a/packages/core/src/response.ts +++ b/packages/core/src/response.ts @@ -1,7 +1,13 @@ import { AxiosResponse } from 'axios' import { get, set } from 'lodash-es' import { router } from '.' -import { fireErrorEvent, fireInvalidEvent, firePrefetchedEvent, fireSuccessEvent } from './events' +import { + fireBeforeUpdateEvent, + fireErrorEvent, + fireInvalidEvent, + firePrefetchedEvent, + fireSuccessEvent, +} from './events' import { history } from './history' import modal from './modal' import { page as currentPage } from './page' @@ -164,6 +170,9 @@ export class Response { pageResponse.url = history.preserveUrl ? currentPage.get().url : this.pageUrl(pageResponse) + this.requestParams.all().onBeforeUpdate(pageResponse) + fireBeforeUpdateEvent(pageResponse) + return currentPage.set(pageResponse, { replace: this.requestParams.all().replace, preserveScroll: this.requestParams.all().preserveScroll, diff --git a/packages/core/src/router.ts b/packages/core/src/router.ts index 4e3016815..5e8db85d9 100644 --- a/packages/core/src/router.ts +++ b/packages/core/src/router.ts @@ -487,6 +487,7 @@ export class Router { return { onCancelToken: options.onCancelToken || (() => {}), onBefore: options.onBefore || (() => {}), + onBeforeUpdate: options.onBeforeUpdate || (() => {}), onStart: options.onStart || (() => {}), onProgress: options.onProgress || (() => {}), onFinish: options.onFinish || (() => {}), diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 0ce72546c..60224f967 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -105,6 +105,13 @@ export interface PageProps { [key: string]: unknown } +export type ScrollProp = { + pageName: string + previousPage?: number | string + nextPage?: number | string + currentPage?: number | string +} + export interface Page { component: string props: PageProps & @@ -121,6 +128,7 @@ export interface Page { prependProps?: string[] deepMergeProps?: string[] matchPropsOn?: string[] + scrollProps?: Record /** @internal */ rememberedState: Record @@ -220,6 +228,13 @@ export type GlobalEventsMap = { details: {} result: void } + beforeUpdate: { + parameters: [Page] + details: { + page: Page + } + result: void + } navigate: { parameters: [Page] details: { @@ -310,6 +325,7 @@ export type InternalEvent = 'missingHistoryItem' | 'loadDeferredProps' export type VisitCallbacks = { onCancelToken: { ({ cancel }: { cancel: VoidFunction }): void } onBefore: GlobalEventCallback<'before', T> + onBeforeUpdate: GlobalEventCallback<'beforeUpdate', T> onStart: GlobalEventCallback<'start', T> onProgress: GlobalEventCallback<'progress', T> onFinish: GlobalEventCallback<'finish', T> @@ -486,6 +502,90 @@ export type FormComponentSlotProps = FormComponentMethods & FormComponentState export type FormComponentRef = FormComponentSlotProps +export interface UseInfiniteScrollOptions { + // Core data + getPropName: () => string + inReverseMode: () => boolean + shouldFetchNext: () => boolean + shouldFetchPrevious: () => boolean + shouldPreserveUrl: () => boolean + + // Elements + getTriggerMargin: () => number + getStartElement: () => HTMLElement + getEndElement: () => HTMLElement + getItemsElement: () => HTMLElement + getScrollableParent: () => HTMLElement | null + + // Callbacks + onBeforePreviousRequest: () => void + onBeforeNextRequest: () => void + onCompletePreviousRequest: () => void + onCompleteNextRequest: () => void +} + +export interface UseInfiniteScrollDataManager { + getLastLoadedPage: () => number | string | undefined + getPageName: () => string + hasPrevious: () => boolean + hasNext: () => boolean + fetchNext: (reloadOptions?: ReloadOptions) => void + fetchPrevious: (reloadOptions?: ReloadOptions) => void +} + +export interface UseInfiniteScrollElementManager { + setupObservers: () => void + enableTriggers: () => void + disableTriggers: () => void + refreshTriggers: () => void + flushAll: () => void + processManuallyAddedElements: () => void + processServerLoadedElements: (loadedPage?: string | number | undefined) => void +} + +export interface UseInfiniteScrollProps { + dataManager: UseInfiniteScrollDataManager + elementManager: UseInfiniteScrollElementManager +} + +export interface InfiniteScrollSlotProps { + loading: boolean + loadingPrevious: boolean + loadingNext: boolean +} + +export interface InfiniteScrollActionSlotProps { + loading: boolean + loadingPrevious: boolean + loadingNext: boolean + fetch: () => void + autoMode: boolean + manualMode: boolean + hasMore: boolean + hasPrevious: boolean + hasNext: boolean +} + +export interface InfiniteScrollRef { + fetchNext: (reloadOptions?: ReloadOptions) => void + fetchPrevious: (reloadOptions?: ReloadOptions) => void + hasPrevious: () => boolean + hasNext: () => boolean +} + +export interface InfiniteScrollComponentBaseProps { + data?: string + buffer?: number + as?: string + manual?: boolean + manualAfter?: number + preserveUrl?: boolean + reverse?: boolean + autoScroll?: boolean + onlyNext?: boolean + onlyPrevious?: boolean +} + declare global { interface DocumentEventMap { 'inertia:before': GlobalEvent<'before'> @@ -496,6 +596,7 @@ declare global { 'inertia:invalid': GlobalEvent<'invalid'> 'inertia:exception': GlobalEvent<'exception'> 'inertia:finish': GlobalEvent<'finish'> + 'inertia:beforeUpdate': GlobalEvent<'beforeUpdate'> 'inertia:navigate': GlobalEvent<'navigate'> } } diff --git a/packages/react/package.json b/packages/react/package.json index 48eefb3eb..c4099c02c 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -51,13 +51,13 @@ "prepublishOnly": "pnpm build" }, "devDependencies": { - "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "@types/react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "axios": "^1.12.0", + "@types/react": "^19.1.13", + "@types/react-dom": "^19.1.9", + "axios": "^1.12.2", "es-check": "^9.3.1", - "esbuild": "^0.25.0", - "esbuild-node-externals": "^1.6.0", - "react": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "esbuild": "^0.25.10", + "esbuild-node-externals": "^1.18.0", + "react": "^19.1.1", "typescript": "^5.9.2" }, "peerDependencies": { diff --git a/packages/react/src/InfiniteScroll.ts b/packages/react/src/InfiniteScroll.ts new file mode 100644 index 000000000..bdf761913 --- /dev/null +++ b/packages/react/src/InfiniteScroll.ts @@ -0,0 +1,325 @@ +import { + getScrollableParent, + InfiniteScrollActionSlotProps, + InfiniteScrollComponentBaseProps, + InfiniteScrollRef, + InfiniteScrollSlotProps, + useInfiniteScroll, + UseInfiniteScrollProps, +} from '@inertiajs/core' +import React, { + createElement, + forwardRef, + useCallback, + useEffect, + useImperativeHandle, + useMemo, + useRef, + useState, +} from 'react' + +const resolveHTMLElement = ( + value: string | React.RefObject | null, + fallback: HTMLElement | null, +): HTMLElement | null => { + if (!value) { + return fallback + } + + // React ref object { current: HTMLElement | null } + if (value && typeof value === 'object' && 'current' in value) { + return value.current + } + + // CSS Selector string + if (typeof value === 'string') { + return document.querySelector(value) as HTMLElement | null + } + + return fallback +} + +// Helper function to render slot content +const renderSlot = ( + slotContent: React.ReactNode | ((props: InfiniteScrollActionSlotProps) => React.ReactNode) | undefined, + slotProps: InfiniteScrollActionSlotProps, + fallback: React.ReactNode = null, +): React.ReactNode => { + if (!slotContent) { + return fallback + } + + return typeof slotContent === 'function' ? slotContent(slotProps) : slotContent +} + +interface ComponentProps + extends InfiniteScrollComponentBaseProps, + Omit, keyof InfiniteScrollComponentBaseProps | 'children'> { + children?: React.ReactNode | ((props: InfiniteScrollSlotProps) => React.ReactNode) + + // Element references for custom trigger detection (when you want different trigger elements) + startElement?: string | React.RefObject + endElement?: string | React.RefObject + itemsElement?: string | React.RefObject + + // Render slots for UI components (when you want custom loading/action components) + previous?: React.ReactNode | ((props: InfiniteScrollActionSlotProps) => React.ReactNode) + next?: React.ReactNode | ((props: InfiniteScrollActionSlotProps) => React.ReactNode) + loading?: React.ReactNode | ((props: InfiniteScrollActionSlotProps) => React.ReactNode) + + onlyNext?: boolean + onlyPrevious?: boolean +} + +const InfiniteScroll = forwardRef( + ( + { + data, + buffer = 0, + as = 'div', + manual = false, + manualAfter = 0, + preserveUrl = false, + reverse = false, + autoScroll, + children, + startElement, + endElement, + itemsElement, + previous, + next, + loading, + onlyNext = false, + onlyPrevious = false, + ...props + }, + ref, + ) => { + const [startElementFromRef, setStartElementFromRef] = useState(null) + const startElementRef = useCallback((node: HTMLElement | null) => setStartElementFromRef(node), []) + + const [endElementFromRef, setEndElementFromRef] = useState(null) + const endElementRef = useCallback((node: HTMLElement | null) => setEndElementFromRef(node), []) + + const [itemsElementFromRef, setItemsElementFromRef] = useState(null) + const itemsElementRef = useCallback((node: HTMLElement | null) => setItemsElementFromRef(node), []) + + const [loadingPrevious, setLoadingPrevious] = useState(false) + const [loadingNext, setLoadingNext] = useState(false) + const [requestCount, setRequestCount] = useState(0) + + const [resolvedStartElement, setResolvedStartElement] = useState(null) + const [resolvedEndElement, setResolvedEndElement] = useState(null) + const [resolvedItemsElement, setResolvedItemsElement] = useState(null) + + // Update elements when refs or props change + useEffect(() => { + const element = startElement ? resolveHTMLElement(startElement, startElementFromRef) : startElementFromRef + setResolvedStartElement(element) + }, [startElement, startElementFromRef]) + + useEffect(() => { + const element = endElement ? resolveHTMLElement(endElement, endElementFromRef) : endElementFromRef + setResolvedEndElement(element) + }, [endElement, endElementFromRef]) + + useEffect(() => { + const element = itemsElement ? resolveHTMLElement(itemsElement, itemsElementFromRef) : itemsElementFromRef + setResolvedItemsElement(element) + }, [itemsElement, itemsElementFromRef]) + + const scrollableParent = useMemo(() => getScrollableParent(resolvedItemsElement), [resolvedItemsElement]) + + const manualMode = useMemo( + () => manual || (manualAfter > 0 && requestCount >= manualAfter), + [manual, manualAfter, requestCount], + ) + const autoLoad = useMemo(() => !manualMode, [manualMode]) + + const callbackPropsRef = useRef({ + buffer, + onlyNext, + onlyPrevious, + reverse, + preserveUrl, + }) + + callbackPropsRef.current = { + buffer, + onlyNext, + onlyPrevious, + reverse, + preserveUrl, + } + + const [infiniteScroll, setInfiniteScroll] = useState(null) + + const dataManager = useMemo(() => infiniteScroll?.dataManager, [infiniteScroll]) + const elementManager = useMemo(() => infiniteScroll?.elementManager, [infiniteScroll]) + + const scrollToBottom = useCallback(() => { + if (scrollableParent) { + scrollableParent.scrollTo({ + top: scrollableParent.scrollHeight, + behavior: 'instant', + }) + } else { + window.scrollTo({ + top: document.body.scrollHeight, + behavior: 'instant', + }) + } + }, [scrollableParent]) + + // Main setup effect - only recreate when structural dependencies change + useEffect(() => { + if (!resolvedItemsElement) { + return + } + + const infiniteScrollInstance = useInfiniteScroll({ + // Data + getPropName: () => data, + inReverseMode: () => callbackPropsRef.current.reverse, + shouldFetchNext: () => !callbackPropsRef.current.onlyPrevious, + shouldFetchPrevious: () => !callbackPropsRef.current.onlyNext, + shouldPreserveUrl: () => callbackPropsRef.current.preserveUrl, + + // Elements + getTriggerMargin: () => callbackPropsRef.current.buffer, + getStartElement: () => resolvedStartElement, + getEndElement: () => resolvedEndElement, + getItemsElement: () => resolvedItemsElement, + getScrollableParent: () => scrollableParent, + + // Callbacks + onBeforePreviousRequest: () => setLoadingPrevious(true), + onBeforeNextRequest: () => setLoadingNext(true), + onCompletePreviousRequest: () => { + setLoadingPrevious(false) + setRequestCount((count) => count + 1) + }, + onCompleteNextRequest: () => { + setLoadingNext(false) + setRequestCount((count) => count + 1) + }, + }) + + setInfiniteScroll(infiniteScrollInstance) + const { dataManager, elementManager } = infiniteScrollInstance + + elementManager.setupObservers() + elementManager.processServerLoadedElements(dataManager.getLastLoadedPage()) + + if (autoLoad) { + elementManager.enableTriggers() + } + + return () => { + elementManager.flushAll() + setInfiniteScroll(null) + } + }, [data, resolvedItemsElement, resolvedStartElement, resolvedEndElement, scrollableParent]) + + useEffect(() => { + autoLoad ? elementManager?.enableTriggers() : elementManager?.disableTriggers() + }, [autoLoad, onlyNext, onlyPrevious, resolvedStartElement, resolvedEndElement]) + + useEffect(() => { + // autoScroll defaults to reverse value if not explicitly set + const shouldAutoScroll = autoScroll !== undefined ? autoScroll : reverse + + if (shouldAutoScroll) { + scrollToBottom() + } + }, [scrollableParent]) + + useImperativeHandle( + ref, + () => ({ + fetchNext: dataManager?.fetchNext || (() => {}), + fetchPrevious: dataManager?.fetchPrevious || (() => {}), + hasPrevious: dataManager?.hasPrevious || (() => false), + hasNext: dataManager?.hasNext || (() => false), + }), + [dataManager], + ) + + const headerAutoMode = autoLoad && !onlyNext + const footerAutoMode = autoLoad && !onlyPrevious + + const sharedExposed: Pick< + InfiniteScrollActionSlotProps, + 'loadingPrevious' | 'loadingNext' | 'hasPrevious' | 'hasNext' + > = { + loadingPrevious, + loadingNext, + hasPrevious: dataManager?.hasPrevious() ?? false, + hasNext: dataManager?.hasNext() ?? false, + } + + const exposedPrevious: InfiniteScrollActionSlotProps = { + loading: loadingPrevious, + fetch: dataManager?.fetchPrevious ?? (() => {}), + autoMode: headerAutoMode, + manualMode: !headerAutoMode, + hasMore: dataManager?.hasPrevious() ?? false, + ...sharedExposed, + } + + const exposedNext: InfiniteScrollActionSlotProps = { + loading: loadingNext, + fetch: dataManager?.fetchNext ?? (() => {}), + autoMode: footerAutoMode, + manualMode: !footerAutoMode, + hasMore: dataManager?.hasNext() ?? false, + ...sharedExposed, + } + + const exposedSlot: InfiniteScrollSlotProps = { + loading: loadingPrevious || loadingNext, + loadingPrevious, + loadingNext, + } + + const renderElements = [] + + // Only render previous trigger if not using custom element selector/ref + if (!startElement) { + renderElements.push( + createElement( + 'div', + { ref: startElementRef }, + // Render previous slot or fallback to loading indicator + renderSlot(previous, exposedPrevious, loadingPrevious ? renderSlot(loading, exposedPrevious) : null), + ), + ) + } + + renderElements.push( + createElement( + as, + { ...props, ref: itemsElementRef }, + typeof children === 'function' ? children(exposedSlot) : children, + ), + ) + + // Only render next trigger if not using custom element selector/ref + if (!endElement) { + renderElements.push( + createElement( + 'div', + { ref: endElementRef }, + // Render next slot or fallback to loading indicator + renderSlot(next, exposedNext, loadingNext ? renderSlot(loading, exposedNext) : null), + ), + ) + } + + return createElement(React.Fragment, {}, ...(reverse ? [...renderElements].reverse() : renderElements)) + }, +) + +InfiniteScroll.displayName = 'InertiaInfiniteScroll' + +export default InfiniteScroll diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 3d4297f16..be438e30e 100755 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -6,6 +6,7 @@ export { default as createInertiaApp } from './createInertiaApp' export { default as Deferred } from './Deferred' export { default as Form } from './Form' export { default as Head } from './Head' +export { default as InfiniteScroll } from './InfiniteScroll' export { InertiaLinkProps, default as Link } from './Link' export { InertiaFormProps, diff --git a/packages/react/test-app/Pages/InfiniteScroll/CustomElement.tsx b/packages/react/test-app/Pages/InfiniteScroll/CustomElement.tsx new file mode 100644 index 000000000..e286e49b3 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/CustomElement.tsx @@ -0,0 +1,17 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
Loading...
} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersRef.tsx b/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersRef.tsx new file mode 100644 index 000000000..580650deb --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersRef.tsx @@ -0,0 +1,78 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { useRef } from 'react' +import { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + const tableHeader = useRef(null) + const tableFooter = useRef(null) + const tableBody = useRef(null) + + return ( +
+

Custom Triggers with Refs Test

+ + + {({ loadingPrevious, loadingNext }) => ( + <> +
+ Spacer +
+ + + + + + + + + + + {users.data.map((user) => ( + + + + + ))} + {(loadingPrevious || loadingNext) && ( + + + + )} + + + + + + + +
IDName
{user.id}{user.name}
+ Loading... +
+ Table Footer - Triggers when this comes into view +
+ +
+ Spacer +
+ + )} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.tsx b/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.tsx new file mode 100644 index 000000000..fbc4c5d1f --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.tsx @@ -0,0 +1,78 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { useRef } from 'react' +import { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + const tableHeader = useRef(null) + const tableFooter = useRef(null) + const tableBody = useRef(null) + + return ( +
+

Custom Triggers with React Ref Objects Test

+ + + {({ loadingPrevious, loadingNext }) => ( + <> +
+ Spacer +
+ + + + + + + + + + + {users.data.map((user) => ( + + + + + ))} + {(loadingPrevious || loadingNext) && ( + + + + )} + + + + + + + +
IDName
{user.id}{user.name}
+ Loading... +
+ Table Footer - Triggers when this comes into view +
+ +
+ Spacer +
+ + )} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersSelector.tsx b/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersSelector.tsx new file mode 100644 index 000000000..d15311f15 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/CustomTriggersSelector.tsx @@ -0,0 +1,74 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
+

Custom Triggers with Selectors Test

+ + + {({ loadingPrevious, loadingNext }) => ( + <> +
+ Spacer +
+ + + + + + + + + + + {users.data.map((user) => ( + + + + + ))} + + {(loadingPrevious || loadingNext) && ( + + + + )} + + + + + + + +
IDName
{user.id}{user.name}
+ Loading... +
+ Table Footer - Triggers when this comes into view +
+ +
+ Spacer +
+ + )} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/DataTable.tsx b/packages/react/test-app/Pages/InfiniteScroll/DataTable.tsx new file mode 100644 index 000000000..2e8738909 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/DataTable.tsx @@ -0,0 +1,38 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( + + {({ loadingPrevious, loadingNext }) => ( + + + + + + + + + + {users.data.map((user) => ( + + + + + ))} + + + + {(loadingPrevious || loadingNext) && ( + + + + )} + +
IDName
{user.id}{user.name}
+ Loading... +
+ )} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/Empty.tsx b/packages/react/test-app/Pages/InfiniteScroll/Empty.tsx new file mode 100644 index 000000000..fa1e31381 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/Empty.tsx @@ -0,0 +1,23 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
+

Empty Dataset Test

+
Loading...
} + > + {users.data.map((user) => ( + + ))} + + {users.data.length === 0 && ( +
No users found.
+ )} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/Grid.tsx b/packages/react/test-app/Pages/InfiniteScroll/Grid.tsx new file mode 100644 index 000000000..ef8ddf20c --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/Grid.tsx @@ -0,0 +1,16 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( + ( +
Loading more users...
+ )} + > + {({ loading, loadingPrevious, loadingNext }) => users.data.map((user) => )} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/HorizontalScroll.tsx b/packages/react/test-app/Pages/InfiniteScroll/HorizontalScroll.tsx new file mode 100644 index 000000000..8b37831ef --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/HorizontalScroll.tsx @@ -0,0 +1,48 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
+ ( +
+ Loading... +
+ )} + > + {users.data.map((user) => ( +
+ {user.name} +
+ ))} +
+
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/Manual.tsx b/packages/react/test-app/Pages/InfiniteScroll/Manual.tsx new file mode 100644 index 000000000..88f6da111 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/Manual.tsx @@ -0,0 +1,28 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( + ( + <> +

Has more previous items: {hasMore.toString()}

+ + + )} + next={({ loading, fetch, hasMore }) => ( + <> +

Has more next items: {hasMore.toString()}

+ + + )} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/ManualAfter.tsx b/packages/react/test-app/Pages/InfiniteScroll/ManualAfter.tsx new file mode 100644 index 000000000..89f0f482a --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/ManualAfter.tsx @@ -0,0 +1,25 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( + ( + <> + {loading &&

Loading...

} + +

Manual mode: {manualMode.toString()}

+ + {manualMode && } + + )} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/PreserveUrl.tsx b/packages/react/test-app/Pages/InfiniteScroll/PreserveUrl.tsx new file mode 100644 index 000000000..a38128b04 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/PreserveUrl.tsx @@ -0,0 +1,17 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
Loading...
} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/ProgrammaticRef.tsx b/packages/react/test-app/Pages/InfiniteScroll/ProgrammaticRef.tsx new file mode 100644 index 000000000..e46b2ff98 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/ProgrammaticRef.tsx @@ -0,0 +1,61 @@ +import { InfiniteScrollRef } from '@inertiajs/core' +import { InfiniteScroll } from '@inertiajs/react' +import { useEffect, useRef, useState } from 'react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + const infRef = useRef(null) + const [hasPrevious, setHasMoreBefore] = useState(false) + const [hasNext, setHasMoreAfter] = useState(false) + + const updateStates = () => { + setHasMoreBefore(infRef.current?.hasPrevious() || false) + setHasMoreAfter(infRef.current?.hasNext() || false) + } + + const fetchNext = () => { + if (infRef.current) { + infRef.current.fetchNext({ onFinish: updateStates }) + } + } + + const fetchPrevious = () => { + if (infRef.current) { + infRef.current.fetchPrevious({ onFinish: updateStates }) + } + } + + useEffect(() => { + updateStates() + }, [infRef.current]) + + return ( +
+

Programmatic Ref Test

+ +
+

Has more previous items: {hasPrevious.toString()}

+

Has more next items: {hasNext.toString()}

+ +
+ + +
+
+ +
Loading...
} + > + {users.data.map((user) => ( + + ))} +
+ +

Total items on page: {users.data.length}

+
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/Reverse.tsx b/packages/react/test-app/Pages/InfiniteScroll/Reverse.tsx new file mode 100644 index 000000000..45d15601d --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/Reverse.tsx @@ -0,0 +1,21 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { useMemo } from 'react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + const reversedUsers = useMemo(() => [...users.data].reverse(), [users.data]) + + return ( +
Loading...
} + > + {reversedUsers.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/ScrollContainer.tsx b/packages/react/test-app/Pages/InfiniteScroll/ScrollContainer.tsx new file mode 100644 index 000000000..27cfa52d9 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/ScrollContainer.tsx @@ -0,0 +1,38 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
+

Infinite Scroll in Container

+

This component scrolls within a fixed-height container, not the full page.

+ + {/* Fixed height scrollable container */} +
+ ( +
Loading more users...
+ )} + > + {users.data.map((user) => ( + + ))} +
+
+ +

Content below the scroll container to verify page doesn't scroll.

+
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/ShortContent.tsx b/packages/react/test-app/Pages/InfiniteScroll/ShortContent.tsx new file mode 100644 index 000000000..90d20c4af --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/ShortContent.tsx @@ -0,0 +1,21 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( + + {({ loadingPrevious, loadingNext }) => ( + + + {users.data.map((user) => ( + + + + + ))} + +
{user.id}{user.name}
+ )} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/Toggles.tsx b/packages/react/test-app/Pages/InfiniteScroll/Toggles.tsx new file mode 100644 index 000000000..5360a274a --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/Toggles.tsx @@ -0,0 +1,59 @@ +import { InfiniteScroll } from '@inertiajs/react' +import { useState } from 'react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + const [manual, setManual] = useState(false) + const [preserveUrl, setPreserveUrl] = useState(false) + const [triggerMode, setTriggerMode] = useState<'onlyPrevious' | 'onlyNext' | 'both'>('onlyNext') + + return ( +
+
+

+ +

+ +

+ +

+ +

+ +

+
+ + Loading...
} + > + {users.data.map((user) => ( + + ))} + + +

Total items on page: {users.data.length}

+ + ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/TriggerBoth.tsx b/packages/react/test-app/Pages/InfiniteScroll/TriggerBoth.tsx new file mode 100644 index 000000000..2342edc21 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/TriggerBoth.tsx @@ -0,0 +1,16 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
Loading...
} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/TriggerEndBuffer.tsx b/packages/react/test-app/Pages/InfiniteScroll/TriggerEndBuffer.tsx new file mode 100644 index 000000000..43b4cbd03 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/TriggerEndBuffer.tsx @@ -0,0 +1,18 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
Loading...
} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/TriggerStartBuffer.tsx b/packages/react/test-app/Pages/InfiniteScroll/TriggerStartBuffer.tsx new file mode 100644 index 000000000..3157f016a --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/TriggerStartBuffer.tsx @@ -0,0 +1,18 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
Loading...
} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/UpdateQueryString.tsx b/packages/react/test-app/Pages/InfiniteScroll/UpdateQueryString.tsx new file mode 100644 index 000000000..2342edc21 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/UpdateQueryString.tsx @@ -0,0 +1,16 @@ +import { InfiniteScroll } from '@inertiajs/react' +import UserCard, { User } from './UserCard' + +export default ({ users }: { users: { data: User[] } }) => { + return ( +
Loading...
} + > + {users.data.map((user) => ( + + ))} +
+ ) +} diff --git a/packages/react/test-app/Pages/InfiniteScroll/UserCard.tsx b/packages/react/test-app/Pages/InfiniteScroll/UserCard.tsx new file mode 100644 index 000000000..6a26a0c07 --- /dev/null +++ b/packages/react/test-app/Pages/InfiniteScroll/UserCard.tsx @@ -0,0 +1,23 @@ +export interface User { + id: number + name: string +} + +export default ({ user }: { user: User }) => { + return ( +
+ {user.name} +
+ ) +} diff --git a/packages/svelte/package.json b/packages/svelte/package.json index b829a6913..4b9820e46 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -45,16 +45,16 @@ "prepublishOnly": "pnpm build" }, "devDependencies": { - "@sveltejs/adapter-auto": "^3.2.0", - "@sveltejs/kit": "^2.36.3", - "@sveltejs/package": "^2.3.4", + "@sveltejs/adapter-auto": "^3.3.1", + "@sveltejs/kit": "^2.43.2", + "@sveltejs/package": "^2.5.4", "@sveltejs/vite-plugin-svelte": "^3.1.2", - "axios": "^1.12.0", + "axios": "^1.12.2", "es-check": "^9.3.1", - "publint": "^0.2.10", - "svelte": "^4.2.19", - "svelte-check": "^4.0.0", - "tslib": "^2.7.0", + "publint": "^0.2.12", + "svelte": "^4.2.20", + "svelte-check": "^4.3.2", + "tslib": "^2.8.1", "typescript": "^5.9.2", "vite": "^5.4.20" }, diff --git a/packages/svelte/src/InfiniteScroll.svelte b/packages/svelte/src/InfiniteScroll.svelte new file mode 100644 index 000000000..f61d72239 --- /dev/null +++ b/packages/svelte/src/InfiniteScroll.svelte @@ -0,0 +1,227 @@ + + +{#if !startElement && !reverse} +
+ + {#if loadingPrevious} + + {/if} + +
+{/if} + +{#if !endElement && reverse} +
+ + {#if loadingNext} + + {/if} + +
+{/if} + + + + + +{#if !startElement && reverse} +
+ + {#if loadingPrevious} + + {/if} + +
+{/if} + +{#if !endElement && !reverse} +
+ + {#if loadingNext} + + {/if} + +
+{/if} diff --git a/packages/svelte/src/index.ts b/packages/svelte/src/index.ts index 4dfec7209..d608602e7 100644 --- a/packages/svelte/src/index.ts +++ b/packages/svelte/src/index.ts @@ -4,6 +4,7 @@ export { default as Form } from './components/Form.svelte' export { default as Link } from './components/Link.svelte' export { default as WhenVisible } from './components/WhenVisible.svelte' export { default as createInertiaApp } from './createInertiaApp' +export { default as InfiniteScroll } from './InfiniteScroll.svelte' export { default as inertia } from './link' export { default as page } from './page' export { type ResolvedComponent } from './types' diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/CustomElement.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/CustomElement.svelte new file mode 100644 index 000000000..44a3ed48d --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/CustomElement.svelte @@ -0,0 +1,14 @@ + + + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersRef.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersRef.svelte new file mode 100644 index 000000000..4c8b6f969 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersRef.svelte @@ -0,0 +1,58 @@ + + +
+

Custom Triggers with Refs Test

+ + tableHeader} + endElement={() => tableFooter} + itemsElement={() => tableBody} + let:exposedSlot + > +
Spacer
+ + + + + + + + + + + {#each users.data as user (user.id)} + + + + + {/each} + + {#if exposedSlot.loadingPrevious || exposedSlot.loadingNext} + + + + {/if} + + + + + + + +
IDName
{user.id}{user.name}
Loading...
+ Table Footer - Triggers when this comes into view +
+ +
Spacer
+
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.svelte new file mode 100644 index 000000000..b77aa2236 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.svelte @@ -0,0 +1,58 @@ + + +
+

Custom Triggers with Svelte Ref Objects Test

+ + tableHeader} + endElement={() => tableFooter} + itemsElement={() => tableBody} + let:exposedSlot + > +
Spacer
+ + + + + + + + + + + {#each users.data as user (user.id)} + + + + + {/each} + + {#if exposedSlot.loadingPrevious || exposedSlot.loadingNext} + + + + {/if} + + + + + + + +
IDName
{user.id}{user.name}
Loading...
+ Table Footer - Triggers when this comes into view +
+ +
Spacer
+
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersSelector.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersSelector.svelte new file mode 100644 index 000000000..2ab5dd8cb --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/CustomTriggersSelector.svelte @@ -0,0 +1,54 @@ + + +
+

Custom Triggers with Selectors Test

+ + +
Spacer
+ + + + + + + + + + + {#each users.data as user (user.id)} + + + + + {/each} + + {#if exposedSlot.loadingPrevious || exposedSlot.loadingNext} + + + + {/if} + + + + + + + +
IDName
{user.id}{user.name}
Loading...
+ Table Footer - Triggers when this comes into view +
+ +
Spacer
+
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/DataTable.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/DataTable.svelte new file mode 100644 index 000000000..50564b3b5 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/DataTable.svelte @@ -0,0 +1,34 @@ + + + + + + + + + + + + + {#each users.data as user (user.id)} + + + + + {/each} + + + + {#if exposedSlot.loadingPrevious || exposedSlot.loadingNext} + + + + {/if} + +
IDName
{user.id}{user.name}
Loading...
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/Empty.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/Empty.svelte new file mode 100644 index 000000000..0a1082f95 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/Empty.svelte @@ -0,0 +1,21 @@ + + +
+

Empty Dataset Test

+ +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} + + {#if users.data.length === 0} +
No users found.
+ {/if} +
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/Grid.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/Grid.svelte new file mode 100644 index 000000000..e1f10d0c1 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/Grid.svelte @@ -0,0 +1,16 @@ + + + +
Loading more users...
+ + + {#each users.data as user (user.id)} + + {/each} + +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/HorizontalScroll.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/HorizontalScroll.svelte new file mode 100644 index 000000000..987303228 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/HorizontalScroll.svelte @@ -0,0 +1,26 @@ + + +
+ +
+ Loading... +
+ + {#each users.data as user (user.id)} +
+ {user.name} +
+ {/each} +
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/Manual.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/Manual.svelte new file mode 100644 index 000000000..b6839942e --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/Manual.svelte @@ -0,0 +1,26 @@ + + + +
+

Has more previous items: {exposedPrevious.hasMore}

+ +
+ + {#each users.data as user (user.id)} + + {/each} + +
+

Has more next items: {exposedNext.hasMore}

+ +
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/ManualAfter.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/ManualAfter.svelte new file mode 100644 index 000000000..bbd29577b --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/ManualAfter.svelte @@ -0,0 +1,24 @@ + + + + {#each users.data as user (user.id)} + + {/each} + +
+ {#if exposedNext.loading} +

Loading...

+ {/if} + +

Manual mode: {exposedNext.manualMode}

+ + {#if exposedNext.manualMode} + + {/if} +
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/PreserveUrl.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/PreserveUrl.svelte new file mode 100644 index 000000000..f1a52e8be --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/PreserveUrl.svelte @@ -0,0 +1,14 @@ + + + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/ProgrammaticRef.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/ProgrammaticRef.svelte new file mode 100644 index 000000000..36e1b9518 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/ProgrammaticRef.svelte @@ -0,0 +1,54 @@ + + +
+

Programmatic Ref Test

+ +
+

Has more previous items: {hasPrevious.toString()}

+

Has more next items: {hasNext.toString()}

+ +
+ + +
+
+ + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
+ +

Total items on page: {users.data.length}

+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/Reverse.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/Reverse.svelte new file mode 100644 index 000000000..c08380deb --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/Reverse.svelte @@ -0,0 +1,16 @@ + + + +
Loading...
+ + {#each reversedUsers as user (user.id)} + + {/each} +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/ScrollContainer.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/ScrollContainer.svelte new file mode 100644 index 000000000..147e3eb82 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/ScrollContainer.svelte @@ -0,0 +1,27 @@ + + +
+

Infinite Scroll in Container

+

This component scrolls within a fixed-height container, not the full page.

+ + +
+ +
Loading more users...
+ + {#each users.data as user (user.id)} + + {/each} +
+
+ +

Content below the scroll container to verify page doesn't scroll.

+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/ShortContent.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/ShortContent.svelte new file mode 100644 index 000000000..c8af93323 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/ShortContent.svelte @@ -0,0 +1,19 @@ + + + + + + {#each users.data as user (user.id)} + + + + + {/each} + +
{user.id}{user.name}
+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/Toggles.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/Toggles.svelte new file mode 100644 index 000000000..89152432c --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/Toggles.svelte @@ -0,0 +1,56 @@ + + +
+
+

+ +

+ +

+ +

+ +

+ +

+
+ + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
+ +

Total items on page: {users.data.length}

+
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/TriggerBoth.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/TriggerBoth.svelte new file mode 100644 index 000000000..2727b3264 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/TriggerBoth.svelte @@ -0,0 +1,14 @@ + + + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/TriggerEndBuffer.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/TriggerEndBuffer.svelte new file mode 100644 index 000000000..39e8bbb79 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/TriggerEndBuffer.svelte @@ -0,0 +1,14 @@ + + + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/TriggerStartBuffer.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/TriggerStartBuffer.svelte new file mode 100644 index 000000000..d9941d340 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/TriggerStartBuffer.svelte @@ -0,0 +1,14 @@ + + + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/UpdateQueryString.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/UpdateQueryString.svelte new file mode 100644 index 000000000..2727b3264 --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/UpdateQueryString.svelte @@ -0,0 +1,14 @@ + + + +
Loading...
+ + {#each users.data as user (user.id)} + + {/each} +
diff --git a/packages/svelte/test-app/Pages/InfiniteScroll/UserCard.svelte b/packages/svelte/test-app/Pages/InfiniteScroll/UserCard.svelte new file mode 100644 index 000000000..23ecbef9a --- /dev/null +++ b/packages/svelte/test-app/Pages/InfiniteScroll/UserCard.svelte @@ -0,0 +1,23 @@ + + + + +
+ {user.name} +
diff --git a/packages/vue3/package.json b/packages/vue3/package.json index 30bdce268..d64177346 100644 --- a/packages/vue3/package.json +++ b/packages/vue3/package.json @@ -50,13 +50,13 @@ "prepublishOnly": "pnpm build" }, "devDependencies": { - "@types/node": "^22.5.3", - "axios": "^1.12.0", + "@types/node": "^22.18.6", + "axios": "^1.12.2", "es-check": "^9.3.1", - "esbuild": "^0.25.0", - "esbuild-node-externals": "^1.6.0", + "esbuild": "^0.25.10", + "esbuild-node-externals": "^1.18.0", "typescript": "^5.9.2", - "vue": "^3.0.0" + "vue": "^3.5.21" }, "peerDependencies": { "vue": "^3.0.0" diff --git a/packages/vue3/src/index.ts b/packages/vue3/src/index.ts index b52191bc0..da482a8d7 100755 --- a/packages/vue3/src/index.ts +++ b/packages/vue3/src/index.ts @@ -4,6 +4,7 @@ export { default as createInertiaApp } from './createInertiaApp' export { default as Deferred } from './deferred' export { default as Form } from './form' export { default as Head } from './head' +export { default as InfiniteScroll } from './infiniteScroll' export { InertiaLinkProps, default as Link } from './link' export * from './types' export { InertiaForm, InertiaFormProps, default as useForm } from './useForm' diff --git a/packages/vue3/src/infiniteScroll.ts b/packages/vue3/src/infiniteScroll.ts new file mode 100644 index 000000000..26c114ed8 --- /dev/null +++ b/packages/vue3/src/infiniteScroll.ts @@ -0,0 +1,259 @@ +import { + getScrollableParent, + InfiniteScrollActionSlotProps, + InfiniteScrollComponentBaseProps, + InfiniteScrollRef, + InfiniteScrollSlotProps, + useInfiniteScroll, +} from '@inertiajs/core' +import { computed, defineComponent, Fragment, h, onMounted, onUnmounted, PropType, ref, watch } from 'vue' + +// Vue-specific element resolver +const resolveHTMLElement = (value, fallback): HTMLElement | null => { + if (!value) { + return fallback + } + + // CSS Selector string + if (typeof value === 'string') { + return document.querySelector(value) as HTMLElement | null + } + + // Function that returns an element + if (typeof value === 'function') { + return value() || null + } + + return fallback +} + +const InfiniteScroll = defineComponent({ + name: 'InfiniteScroll', + props: { + data: { + type: String as PropType, + }, + buffer: { + type: Number as PropType, + default: 0, + }, + onlyNext: { + type: Boolean, + default: false, + }, + onlyPrevious: { + type: Boolean, + default: false, + }, + as: { + type: String as PropType, + default: 'div', + }, + manual: { + type: Boolean as PropType, + default: false, + }, + manualAfter: { + type: Number as PropType, + default: 0, + }, + preserveUrl: { + type: Boolean as PropType, + default: false, + }, + reverse: { + type: Boolean as PropType, + default: false, + }, + autoScroll: { + type: Boolean as PropType, + default: undefined, + }, + itemsElement: { + type: [String, Function, Object] as PropType HTMLElement | null | undefined)>, + default: null, + }, + startElement: { + type: [String, Function, Object] as PropType HTMLElement | null | undefined)>, + default: null, + }, + endElement: { + type: [String, Function, Object] as PropType HTMLElement | null | undefined)>, + default: null, + }, + }, + inheritAttrs: false, + setup(props, { slots, attrs, expose }) { + const itemsElementRef = ref(null) + const startElementRef = ref(null) + const endElementRef = ref(null) + + const itemsElement = computed(() => + resolveHTMLElement(props.itemsElement, itemsElementRef.value), + ) + const scrollableParent = computed(() => getScrollableParent(itemsElement.value)) + const startElement = computed(() => + resolveHTMLElement(props.startElement, startElementRef.value), + ) + const endElement = computed(() => resolveHTMLElement(props.endElement, endElementRef.value)) + + const loadingPrevious = ref(false) + const loadingNext = ref(false) + const requestCount = ref(0) + + const autoLoad = computed(() => !manualMode.value) + const manualMode = computed( + () => props.manual || (props.manualAfter > 0 && requestCount.value >= props.manualAfter), + ) + + const { dataManager, elementManager } = useInfiniteScroll({ + // Data + getPropName: () => props.data, + inReverseMode: () => props.reverse, + shouldFetchNext: () => !props.onlyPrevious, + shouldFetchPrevious: () => !props.onlyNext, + shouldPreserveUrl: () => props.preserveUrl, + + // Elements + getTriggerMargin: () => props.buffer, + getStartElement: () => startElement.value!, + getEndElement: () => endElement.value!, + getItemsElement: () => itemsElement.value!, + getScrollableParent: () => scrollableParent.value, + + // Request callbacks + onBeforePreviousRequest: () => (loadingPrevious.value = true), + onBeforeNextRequest: () => (loadingNext.value = true), + onCompletePreviousRequest: () => { + requestCount.value += 1 + loadingPrevious.value = false + }, + onCompleteNextRequest: () => { + requestCount.value += 1 + loadingNext.value = false + }, + }) + + const scrollToBottom = () => { + if (scrollableParent.value) { + scrollableParent.value.scrollTo({ + top: scrollableParent.value.scrollHeight, + behavior: 'instant', + }) + } else { + window.scrollTo({ + top: document.body.scrollHeight, + behavior: 'instant', + }) + } + } + + onMounted(() => { + elementManager.setupObservers() + elementManager.processServerLoadedElements(dataManager.getLastLoadedPage()) + + // autoScroll defaults to reverse value if not explicitly set + const shouldAutoScroll = props.autoScroll !== undefined ? props.autoScroll : props.reverse + + if (shouldAutoScroll) { + scrollToBottom() + } + + if (autoLoad.value) { + elementManager.enableTriggers() + } + }) + + onUnmounted(elementManager.flushAll) + + watch( + () => [autoLoad.value, props.onlyNext, props.onlyPrevious], + ([enabled]) => { + enabled ? elementManager.enableTriggers() : elementManager.disableTriggers() + }, + ) + + expose({ + fetchNext: dataManager.fetchNext, + fetchPrevious: dataManager.fetchPrevious, + hasPrevious: dataManager.hasPrevious, + hasNext: dataManager.hasNext, + }) + + return () => { + const renderElements = [] + + const sharedExposed: Pick< + InfiniteScrollActionSlotProps, + 'loadingPrevious' | 'loadingNext' | 'hasPrevious' | 'hasNext' + > = { + loadingPrevious: loadingPrevious.value, + loadingNext: loadingNext.value, + hasPrevious: dataManager.hasPrevious(), + hasNext: dataManager.hasNext(), + } + + // Only render previous trigger if not using custom element + if (!props.startElement) { + const headerAutoMode = autoLoad.value && !props.onlyNext + const exposedPrevious: InfiniteScrollActionSlotProps = { + loading: loadingPrevious.value, + fetch: dataManager.fetchPrevious, + autoMode: headerAutoMode, + manualMode: !headerAutoMode, + hasMore: dataManager.hasPrevious(), + ...sharedExposed, + } + + renderElements.push( + h( + 'div', + { ref: startElementRef }, + slots.previous + ? slots.previous(exposedPrevious) + : loadingPrevious.value + ? slots.loading?.(exposedPrevious) + : null, + ), + ) + } + + renderElements.push( + h( + props.as, + { ...attrs, ref: itemsElementRef }, + slots.default?.({ + loading: loadingPrevious.value || loadingNext.value, + loadingPrevious: loadingPrevious.value, + loadingNext: loadingNext.value, + } as InfiniteScrollSlotProps), + ), + ) + + // Only render next trigger if not using custom element + if (!props.endElement) { + const footerAutoMode = autoLoad.value && !props.onlyPrevious + const exposedNext: InfiniteScrollActionSlotProps = { + loading: loadingNext.value, + fetch: dataManager.fetchNext, + autoMode: footerAutoMode, + manualMode: !footerAutoMode, + hasMore: dataManager.hasNext(), + ...sharedExposed, + } + + renderElements.push( + h( + 'div', + { ref: endElementRef }, + slots.next ? slots.next(exposedNext) : loadingNext.value ? slots.loading?.(exposedNext) : null, + ), + ) + } + + return h(Fragment, {}, props.reverse ? [...renderElements].reverse() : renderElements) + } + }, +}) + +export default InfiniteScroll diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/CustomElement.vue b/packages/vue3/test-app/Pages/InfiniteScroll/CustomElement.vue new file mode 100644 index 000000000..684cb56a4 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/CustomElement.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersRef.vue b/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersRef.vue new file mode 100644 index 000000000..56152ed04 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersRef.vue @@ -0,0 +1,62 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.vue b/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.vue new file mode 100644 index 000000000..22d1da2d9 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersRefObject.vue @@ -0,0 +1,62 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersSelector.vue b/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersSelector.vue new file mode 100644 index 000000000..bfdeb76c0 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/CustomTriggersSelector.vue @@ -0,0 +1,58 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/DataTable.vue b/packages/vue3/test-app/Pages/InfiniteScroll/DataTable.vue new file mode 100644 index 000000000..1548e4fd7 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/DataTable.vue @@ -0,0 +1,34 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/Empty.vue b/packages/vue3/test-app/Pages/InfiniteScroll/Empty.vue new file mode 100644 index 000000000..94e51556f --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/Empty.vue @@ -0,0 +1,23 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/Grid.vue b/packages/vue3/test-app/Pages/InfiniteScroll/Grid.vue new file mode 100644 index 000000000..e783ac474 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/Grid.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/HorizontalScroll.vue b/packages/vue3/test-app/Pages/InfiniteScroll/HorizontalScroll.vue new file mode 100644 index 000000000..a35d4b232 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/HorizontalScroll.vue @@ -0,0 +1,49 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/Manual.vue b/packages/vue3/test-app/Pages/InfiniteScroll/Manual.vue new file mode 100644 index 000000000..d57082548 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/Manual.vue @@ -0,0 +1,30 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/ManualAfter.vue b/packages/vue3/test-app/Pages/InfiniteScroll/ManualAfter.vue new file mode 100644 index 000000000..6b475cd5e --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/ManualAfter.vue @@ -0,0 +1,22 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/ManualReverse.vue b/packages/vue3/test-app/Pages/InfiniteScroll/ManualReverse.vue new file mode 100644 index 000000000..89f1dd7df --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/ManualReverse.vue @@ -0,0 +1,29 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/ManualToggle.vue b/packages/vue3/test-app/Pages/InfiniteScroll/ManualToggle.vue new file mode 100644 index 000000000..38a4f336d --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/ManualToggle.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/PreserveUrl.vue b/packages/vue3/test-app/Pages/InfiniteScroll/PreserveUrl.vue new file mode 100644 index 000000000..1557fdb5c --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/PreserveUrl.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/ProgrammaticRef.vue b/packages/vue3/test-app/Pages/InfiniteScroll/ProgrammaticRef.vue new file mode 100644 index 000000000..4faf4277f --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/ProgrammaticRef.vue @@ -0,0 +1,54 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/Reverse.vue b/packages/vue3/test-app/Pages/InfiniteScroll/Reverse.vue new file mode 100644 index 000000000..2a48aceb1 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/Reverse.vue @@ -0,0 +1,21 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/ScrollContainer.vue b/packages/vue3/test-app/Pages/InfiniteScroll/ScrollContainer.vue new file mode 100644 index 000000000..379890167 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/ScrollContainer.vue @@ -0,0 +1,31 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/ShortContent.vue b/packages/vue3/test-app/Pages/InfiniteScroll/ShortContent.vue new file mode 100644 index 000000000..4f5d61e48 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/ShortContent.vue @@ -0,0 +1,21 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/Toggles.vue b/packages/vue3/test-app/Pages/InfiniteScroll/Toggles.vue new file mode 100644 index 000000000..97dd7a6ac --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/Toggles.vue @@ -0,0 +1,61 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/TriggerBoth.vue b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerBoth.vue new file mode 100644 index 000000000..f3cd24697 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerBoth.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/TriggerEndBuffer.vue b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerEndBuffer.vue new file mode 100644 index 000000000..3f743e37d --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerEndBuffer.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/TriggerStartBuffer.vue b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerStartBuffer.vue new file mode 100644 index 000000000..e27e18869 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerStartBuffer.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/TriggerToggle.vue b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerToggle.vue new file mode 100644 index 000000000..625005f72 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/TriggerToggle.vue @@ -0,0 +1,41 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/UpdateQueryString.vue b/packages/vue3/test-app/Pages/InfiniteScroll/UpdateQueryString.vue new file mode 100644 index 000000000..f3cd24697 --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/UpdateQueryString.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue3/test-app/Pages/InfiniteScroll/UserCard.vue b/packages/vue3/test-app/Pages/InfiniteScroll/UserCard.vue new file mode 100644 index 000000000..40edd9e7b --- /dev/null +++ b/packages/vue3/test-app/Pages/InfiniteScroll/UserCard.vue @@ -0,0 +1,26 @@ + + + diff --git a/packages/vue3/test-app/vite.config.ts b/packages/vue3/test-app/vite.config.ts index 534b65135..7757523a1 100644 --- a/packages/vue3/test-app/vite.config.ts +++ b/packages/vue3/test-app/vite.config.ts @@ -10,5 +10,9 @@ export default defineConfig({ '@': __dirname, }, }, - plugins: [vue()], + plugins: [ + vue({ + features: { prodDevtools: true }, + }), + ], }) diff --git a/playgrounds/react/.env.example b/playgrounds/react/.env.example index 8c6b7c9ed..edadb800e 100644 --- a/playgrounds/react/.env.example +++ b/playgrounds/react/.env.example @@ -8,12 +8,12 @@ LOG_CHANNEL=stack LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=laravel -DB_USERNAME=root -DB_PASSWORD= +DB_CONNECTION=sqlite +# DB_HOST=127.0.0.1 +# DB_PORT=3306 +# DB_DATABASE=laravel +# DB_USERNAME=root +# DB_PASSWORD= BROADCAST_DRIVER=log CACHE_DRIVER=file diff --git a/playgrounds/react/app/Http/Resources/UserResource.php b/playgrounds/react/app/Http/Resources/UserResource.php new file mode 100644 index 000000000..1835f0f59 --- /dev/null +++ b/playgrounds/react/app/Http/Resources/UserResource.php @@ -0,0 +1,19 @@ + + */ + public function toArray(Request $request): array + { + return parent::toArray($request); + } +} \ No newline at end of file diff --git a/playgrounds/react/app/Models/ChatMessage.php b/playgrounds/react/app/Models/ChatMessage.php new file mode 100644 index 000000000..57be45d54 --- /dev/null +++ b/playgrounds/react/app/Models/ChatMessage.php @@ -0,0 +1,15 @@ +=4.0.0" + "doctrine/dbal": "<4.0.0 || >=5.0.0" }, "require-dev": { - "doctrine/dbal": "^3.7.0", + "doctrine/dbal": "^4.0.0", "nesbot/carbon": "^2.71.0 || ^3.0.0", "phpunit/phpunit": "^10.3" }, @@ -117,7 +117,7 @@ ], "support": { "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", - "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" }, "funding": [ { @@ -133,7 +133,7 @@ "type": "tidelift" } ], - "time": "2023-12-11T17:09:12+00:00" + "time": "2024-02-09T16:56:22+00:00" }, { "name": "dflydev/dot-access-data", @@ -212,33 +212,32 @@ }, { "name": "doctrine/inflector", - "version": "2.0.10", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^11.0", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25 || ^5.4" + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -283,7 +282,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.10" + "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { @@ -299,7 +298,7 @@ "type": "tidelift" } ], - "time": "2024-02-18T20:23:39+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { "name": "doctrine/lexer", @@ -445,16 +444,16 @@ }, { "name": "egulias/email-validator", - "version": "4.0.2", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", "shasum": "" }, "require": { @@ -500,7 +499,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" }, "funding": [ { @@ -508,7 +507,7 @@ "type": "github" } ], - "time": "2023-10-06T06:47:41+00:00" + "time": "2025-03-06T22:45:56+00:00" }, { "name": "fruitcake/php-cors", @@ -645,22 +644,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.9.2", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.3", - "guzzlehttp/psr7": "^2.7.0", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -751,7 +750,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.2" + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, "funding": [ { @@ -767,20 +766,20 @@ "type": "tidelift" } ], - "time": "2024-07-24T11:22:20+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.3", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { @@ -788,7 +787,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { @@ -834,7 +833,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.3" + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { @@ -850,20 +849,20 @@ "type": "tidelift" } ], - "time": "2024-07-18T10:29:17+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { @@ -879,7 +878,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -950,7 +949,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.0" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -966,20 +965,20 @@ "type": "tidelift" } ], - "time": "2024-07-18T11:15:46+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.3", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", "shasum": "" }, "require": { @@ -988,7 +987,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.44 || ^9.6.25", "uri-template/tests": "1.0.0" }, "type": "library", @@ -1036,7 +1035,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" }, "funding": [ { @@ -1052,33 +1051,35 @@ "type": "tidelift" } ], - "time": "2023-12-03T19:50:20+00:00" + "time": "2025-08-22T14:27:06+00:00" }, { "name": "inertiajs/inertia-laravel", - "version": "2.x-dev", + "version": "dev-merge-improvements", "source": { "type": "git", "url": "https://github.com/inertiajs/inertia-laravel.git", - "reference": "141256b2ed1833158852c9d239d00abec8ff4942" + "reference": "1b3a29e970138ea1fd1862492fdc64f407a207d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/141256b2ed1833158852c9d239d00abec8ff4942", - "reference": "141256b2ed1833158852c9d239d00abec8ff4942", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/1b3a29e970138ea1fd1862492fdc64f407a207d2", + "reference": "1b3a29e970138ea1fd1862492fdc64f407a207d2", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "^10.0|^11.0", + "laravel/framework": "^10.0|^11.0|^12.0", "php": "^8.1.0", - "symfony/console": "^5.3|^6.0|^7.0" + "symfony/console": "^6.2|^7.0" }, "require-dev": { + "guzzlehttp/guzzle": "^7.2", + "larastan/larastan": "^3.0", "laravel/pint": "^1.16", "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^8.0|^9.0", - "phpunit/phpunit": "^10.4|^11.0", + "orchestra/testbench": "^8.0|^9.2|^10.0", + "phpunit/phpunit": "^10.4|^11.5", "roave/security-advisories": "dev-master" }, "suggest": { @@ -1090,9 +1091,6 @@ "providers": [ "Inertia\\ServiceProvider" ] - }, - "branch-alias": { - "dev-master": "1.x-dev" } }, "autoload": { @@ -1121,35 +1119,29 @@ ], "support": { "issues": "https://github.com/inertiajs/inertia-laravel/issues", - "source": "https://github.com/inertiajs/inertia-laravel/tree/2.x" + "source": "https://github.com/inertiajs/inertia-laravel/tree/merge-improvements" }, - "funding": [ - { - "url": "https://github.com/reinink", - "type": "github" - } - ], - "time": "2024-10-10T13:16:21+00:00" + "time": "2025-09-09T19:28:26+00:00" }, { "name": "laravel/framework", - "version": "v10.48.23", + "version": "v11.46.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "625269ca4881d2b50eded2045cb930960a181d98" + "reference": "2c6d85f22d08123ad45aa3a6726b16f06e68eecd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/625269ca4881d2b50eded2045cb930960a181d98", - "reference": "625269ca4881d2b50eded2045cb930960a181d98", + "url": "https://api.github.com/repos/laravel/framework/zipball/2c6d85f22d08123ad45aa3a6726b16f06e68eecd", + "reference": "2c6d85f22d08123ad45aa3a6726b16f06e68eecd", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12|^0.13|^0.14", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", - "dragonmantank/cron-expression": "^3.3.2", + "dragonmantank/cron-expression": "^3.4", "egulias/email-validator": "^3.2.1|^4.0", "ext-ctype": "*", "ext-filter": "*", @@ -1158,44 +1150,45 @@ "ext-openssl": "*", "ext-session": "*", "ext-tokenizer": "*", - "fruitcake/php-cors": "^1.2", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", - "laravel/prompts": "^0.1.9", - "laravel/serializable-closure": "^1.3", - "league/commonmark": "^2.2.1", - "league/flysystem": "^3.8.0", + "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.7", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.67", - "nunomaduro/termwind": "^1.13", - "php": "^8.1", + "nesbot/carbon": "^2.72.6|^3.8.4", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^6.2", - "symfony/error-handler": "^6.2", - "symfony/finder": "^6.2", - "symfony/http-foundation": "^6.4", - "symfony/http-kernel": "^6.2", - "symfony/mailer": "^6.2", - "symfony/mime": "^6.2", - "symfony/process": "^6.2", - "symfony/routing": "^6.2", - "symfony/uid": "^6.2", - "symfony/var-dumper": "^6.2", + "symfony/console": "^7.0.3", + "symfony/error-handler": "^7.0.3", + "symfony/finder": "^7.0.3", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.0.3", + "symfony/mailer": "^7.0.3", + "symfony/mime": "^7.0.3", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.0.3", + "symfony/routing": "^7.0.3", + "symfony/uid": "^7.0.3", + "symfony/var-dumper": "^7.0.3", "tijsverkoyen/css-to-inline-styles": "^2.2.5", - "vlucas/phpdotenv": "^5.4.1", - "voku/portable-ascii": "^2.0" + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" }, "conflict": { - "carbonphp/carbon-doctrine-types": ">=3.0", - "doctrine/dbal": ">=4.0", - "mockery/mockery": "1.6.8", - "phpunit/phpunit": ">=11.0.0", "tightenco/collect": "<5.5.33" }, "provide": { "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", "psr/simple-cache-implementation": "1.0|2.0|3.0" }, "replace": { @@ -1204,6 +1197,7 @@ "illuminate/bus": "self.version", "illuminate/cache": "self.version", "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", "illuminate/conditionable": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", @@ -1231,36 +1225,39 @@ "illuminate/testing": "self.version", "illuminate/translation": "self.version", "illuminate/validation": "self.version", - "illuminate/view": "self.version" + "illuminate/view": "self.version", + "spatie/once": "*" }, "require-dev": { "ably/ably-php": "^1.0", - "aws/aws-sdk-php": "^3.235.5", - "doctrine/dbal": "^3.5.1", + "aws/aws-sdk-php": "^3.322.9", "ext-gmp": "*", - "fakerphp/faker": "^1.21", - "guzzlehttp/guzzle": "^7.5", - "league/flysystem-aws-s3-v3": "^3.0", - "league/flysystem-ftp": "^3.0", - "league/flysystem-path-prefixing": "^3.3", - "league/flysystem-read-only": "^3.3", - "league/flysystem-sftp-v3": "^3.0", - "mockery/mockery": "^1.5.1", - "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^8.23.4", - "pda/pheanstalk": "^4.0", - "phpstan/phpstan": "^1.4.7", - "phpunit/phpunit": "^10.0.7", - "predis/predis": "^2.0.2", - "symfony/cache": "^6.2", - "symfony/http-client": "^6.2.4", - "symfony/psr-http-message-bridge": "^2.0" + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^9.16.1", + "pda/pheanstalk": "^5.0.6", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1", + "predis/predis": "^2.3", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.0.3", + "symfony/http-client": "^7.0.3", + "symfony/psr-http-message-bridge": "^7.0.3", + "symfony/translation": "^7.0.3" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", - "brianium/paratest": "Required to run tests in parallel (^6.0).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", "ext-apcu": "Required to use the APC cache driver.", "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", @@ -1269,42 +1266,45 @@ "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", "ext-pdo": "Required to use all database features.", "ext-posix": "Required to use all features of the queue worker.", - "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", - "guzzlehttp/guzzle": "Required to use the HTTP Client and the ping methods on schedules (^7.5).", "laravel/tinker": "Required to use the tinker console command (^2.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", - "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", - "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", - "league/flysystem-read-only": "Required to use read-only disks (^3.3)", - "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", - "mockery/mockery": "Required to use mocking (^1.5.1).", - "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", - "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", - "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8|^10.0.7).", - "predis/predis": "Required to use the predis connector (^2.0.2).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^6.2).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^6.2).", - "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.2).", - "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.2).", - "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.2).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.0).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.0).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.0).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.0).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.0).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "10.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { "files": [ + "src/Illuminate/Collections/functions.php", "src/Illuminate/Collections/helpers.php", "src/Illuminate/Events/functions.php", "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", "src/Illuminate/Support/helpers.php" ], "psr-4": { @@ -1336,25 +1336,25 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-11-12T15:39:10+00:00" + "time": "2025-09-08T21:54:34+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.25", + "version": "v0.3.7", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "7b4029a84c37cb2725fc7f011586e2997040bc95" + "reference": "a1891d362714bc40c8d23b0b1d7090f022ea27cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/7b4029a84c37cb2725fc7f011586e2997040bc95", - "reference": "7b4029a84c37cb2725fc7f011586e2997040bc95", + "url": "https://api.github.com/repos/laravel/prompts/zipball/a1891d362714bc40c8d23b0b1d7090f022ea27cc", + "reference": "a1891d362714bc40c8d23b0b1d7090f022ea27cc", "shasum": "" }, "require": { + "composer-runtime-api": "^2.2", "ext-mbstring": "*", - "illuminate/collections": "^10.0|^11.0", "php": "^8.1", "symfony/console": "^6.2|^7.0" }, @@ -1363,10 +1363,11 @@ "laravel/framework": ">=10.17.0 <10.25.0" }, "require-dev": { + "illuminate/collections": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-mockery": "^1.1" + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.12.28", + "phpstan/phpstan-mockery": "^1.1.3" }, "suggest": { "ext-pcntl": "Required for the spinner to be animated." @@ -1374,7 +1375,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "0.1.x-dev" + "dev-main": "0.3.x-dev" } }, "autoload": { @@ -1392,43 +1393,41 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.25" + "source": "https://github.com/laravel/prompts/tree/v0.3.7" }, - "time": "2024-08-12T22:06:33+00:00" + "time": "2025-09-19T13:47:56+00:00" }, { "name": "laravel/sanctum", - "version": "v3.3.3", + "version": "v4.2.0", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5" + "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/8c104366459739f3ada0e994bcd3e6fd681ce3d5", - "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/fd6df4f79f48a72992e8d29a9c0ee25422a0d677", + "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^9.21|^10.0", - "illuminate/contracts": "^9.21|^10.0", - "illuminate/database": "^9.21|^10.0", - "illuminate/support": "^9.21|^10.0", - "php": "^8.0.2" + "illuminate/console": "^11.0|^12.0", + "illuminate/contracts": "^11.0|^12.0", + "illuminate/database": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", + "php": "^8.2", + "symfony/console": "^7.0" }, "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.28.2|^8.8.3", + "mockery/mockery": "^1.6", + "orchestra/testbench": "^9.0|^10.0", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - }, "laravel": { "providers": [ "Laravel\\Sanctum\\SanctumServiceProvider" @@ -1460,36 +1459,36 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2023-12-19T18:44:48+00:00" + "time": "2025-07-09T19:45:24+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.3.7", + "version": "v2.0.5", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "4f48ade902b94323ca3be7646db16209ec76be3d" + "reference": "3832547db6e0e2f8bb03d4093857b378c66eceed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d", - "reference": "4f48ade902b94323ca3be7646db16209ec76be3d", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3832547db6e0e2f8bb03d4093857b378c66eceed", + "reference": "3832547db6e0e2f8bb03d4093857b378c66eceed", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "php": "^8.1" }, "require-dev": { - "illuminate/support": "^8.0|^9.0|^10.0|^11.0", - "nesbot/carbon": "^2.61|^3.0", - "pestphp/pest": "^1.21.3", - "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -1521,26 +1520,26 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-11-14T18:34:49+00:00" + "time": "2025-09-22T17:29:40+00:00" }, { "name": "laravel/tinker", - "version": "v2.10.0", + "version": "v2.10.1", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5" + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/ba4d51eb56de7711b3a37d63aa0643e99a339ae5", - "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", "shasum": "" }, "require": { - "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^7.2.5|^8.0", "psy/psysh": "^0.11.1|^0.12.0", "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" @@ -1548,10 +1547,10 @@ "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.5.8|^9.3.3" + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" }, "suggest": { - "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0)." + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." }, "type": "library", "extra": { @@ -1585,22 +1584,22 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.10.0" + "source": "https://github.com/laravel/tinker/tree/v2.10.1" }, - "time": "2024-09-23T13:32:56+00:00" + "time": "2025-01-27T14:24:01+00:00" }, { "name": "league/commonmark", - "version": "2.5.3", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0" + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca", + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca", "shasum": "" }, "require": { @@ -1625,10 +1624,11 @@ "phpstan/phpstan": "^1.8.2", "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 || ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 || ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", "unleashedtech/php-coding-standard": "^3.1.1", - "vimeo/psalm": "^4.24.0 || ^5.0.0" + "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" }, "suggest": { "symfony/yaml": "v2.3+ required if using the Front Matter extension" @@ -1636,7 +1636,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.6-dev" + "dev-main": "2.8-dev" } }, "autoload": { @@ -1693,7 +1693,7 @@ "type": "tidelift" } ], - "time": "2024-08-16T11:46:16+00:00" + "time": "2025-07-20T12:47:49+00:00" }, { "name": "league/config", @@ -1779,16 +1779,16 @@ }, { "name": "league/flysystem", - "version": "3.29.1", + "version": "3.30.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", - "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", "shasum": "" }, "require": { @@ -1812,13 +1812,13 @@ "composer/semver": "^3.0", "ext-fileinfo": "*", "ext-ftp": "*", - "ext-mongodb": "^1.3", + "ext-mongodb": "^1.3|^2", "ext-zip": "*", "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "guzzlehttp/psr7": "^2.6", "microsoft/azure-storage-blob": "^1.1", - "mongodb/mongodb": "^1.2", + "mongodb/mongodb": "^1.2|^2", "phpseclib/phpseclib": "^3.0.36", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5.11|^10.0", @@ -1856,22 +1856,22 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" + "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" }, - "time": "2024-10-08T08:58:34+00:00" + "time": "2025-06-25T13:29:59+00:00" }, { "name": "league/flysystem-local", - "version": "3.29.0", + "version": "3.30.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", - "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", "shasum": "" }, "require": { @@ -1905,9 +1905,9 @@ "local" ], "support": { - "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" }, - "time": "2024-08-09T21:24:39+00:00" + "time": "2025-05-21T10:34:19+00:00" }, { "name": "league/mime-type-detection", @@ -1965,18 +1965,192 @@ ], "time": "2024-09-21T08:32:55+00:00" }, + { + "name": "league/uri", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" + }, { "name": "monolog/monolog", - "version": "3.8.0", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67" + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/32e515fdc02cdafbe4593e30a9350d486b125b67", - "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", "shasum": "" }, "require": { @@ -2054,7 +2228,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.8.0" + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" }, "funding": [ { @@ -2066,56 +2240,50 @@ "type": "tidelift" } ], - "time": "2024-11-12T13:57:08+00:00" + "time": "2025-03-24T10:02:05+00:00" }, { "name": "nesbot/carbon", - "version": "2.72.5", + "version": "3.10.3", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed" + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/afd46589c216118ecd48ff2b95d77596af1e57ed", - "reference": "afd46589c216118ecd48ff2b95d77596af1e57ed", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f", + "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f", "shasum": "" }, "require": { - "carbonphp/carbon-doctrine-types": "*", + "carbonphp/carbon-doctrine-types": "<100.0", "ext-json": "*", - "php": "^7.1.8 || ^8.0", + "php": "^8.1", "psr/clock": "^1.0", + "symfony/clock": "^6.3.12 || ^7.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", - "doctrine/orm": "^2.7 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.0", - "kylekatarnls/multi-tester": "^2.0", - "ondrejmirtes/better-reflection": "*", - "phpmd/phpmd": "^2.9", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.99 || ^1.7.14", - "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", - "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", - "squizlabs/php_codesniffer": "^3.4" + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^v3.87.1", + "kylekatarnls/multi-tester": "^2.5.3", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.22", + "phpunit/phpunit": "^10.5.53", + "squizlabs/php_codesniffer": "^3.13.4" }, "bin": [ "bin/carbon" ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.x-dev", - "dev-2.x": "2.x-dev" - }, "laravel": { "providers": [ "Carbon\\Laravel\\ServiceProvider" @@ -2125,6 +2293,10 @@ "includes": [ "extension.neon" ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" } }, "autoload": { @@ -2156,8 +2328,8 @@ ], "support": { "docs": "https://carbon.nesbot.com/docs", - "issues": "https://github.com/briannesbitt/Carbon/issues", - "source": "https://github.com/briannesbitt/Carbon" + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" }, "funding": [ { @@ -2173,7 +2345,7 @@ "type": "tidelift" } ], - "time": "2024-06-03T19:18:41+00:00" + "time": "2025-09-06T13:39:36+00:00" }, { "name": "nette/schema", @@ -2239,29 +2411,29 @@ }, { "name": "nette/utils", - "version": "v4.0.5", + "version": "v4.0.8", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96" + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", - "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", + "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede", "shasum": "" }, "require": { - "php": "8.0 - 8.4" + "php": "8.0 - 8.5" }, "conflict": { "nette/finder": "<3", "nette/schema": "<1.2.2" }, "require-dev": { - "jetbrains/phpstorm-attributes": "dev-master", + "jetbrains/phpstorm-attributes": "^1.2", "nette/tester": "^2.5", - "phpstan/phpstan": "^1.0", + "phpstan/phpstan-nette": "^2.0@stable", "tracy/tracy": "^2.9" }, "suggest": { @@ -2279,6 +2451,9 @@ } }, "autoload": { + "psr-4": { + "Nette\\": "src" + }, "classmap": [ "src/" ] @@ -2319,22 +2494,22 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.5" + "source": "https://github.com/nette/utils/tree/v4.0.8" }, - "time": "2024-08-07T15:39:19+00:00" + "time": "2025-08-06T21:43:34+00:00" }, { "name": "nikic/php-parser", - "version": "v5.3.1", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", "shasum": "" }, "require": { @@ -2353,7 +2528,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -2377,38 +2552,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" }, - "time": "2024-10-08T18:51:32+00:00" + "time": "2025-08-13T20:13:15+00:00" }, { "name": "nunomaduro/termwind", - "version": "v1.17.0", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "5369ef84d8142c1d87e4ec278711d4ece3cbf301" + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/5369ef84d8142c1d87e4ec278711d4ece3cbf301", - "reference": "5369ef84d8142c1d87e4ec278711d4ece3cbf301", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": "^8.1", - "symfony/console": "^6.4.15" + "php": "^8.2", + "symfony/console": "^7.2.6" }, "require-dev": { - "illuminate/console": "^10.48.24", - "illuminate/support": "^10.48.24", - "laravel/pint": "^1.18.2", - "pestphp/pest": "^2.36.0", - "pestphp/pest-plugin-mock": "2.0.0", - "phpstan/phpstan": "^1.12.11", - "phpstan/phpstan-strict-rules": "^1.6.1", - "symfony/var-dumper": "^6.4.15", + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -2417,6 +2591,9 @@ "providers": [ "Termwind\\Laravel\\TermwindServiceProvider" ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" } }, "autoload": { @@ -2448,7 +2625,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v1.17.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" }, "funding": [ { @@ -2464,20 +2641,20 @@ "type": "github" } ], - "time": "2024-11-21T10:36:35+00:00" + "time": "2025-05-08T08:14:37+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.3", + "version": "1.9.4", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", "shasum": "" }, "require": { @@ -2485,7 +2662,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" }, "type": "library", "extra": { @@ -2527,7 +2704,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.4" }, "funding": [ { @@ -2539,7 +2716,84 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:41:07+00:00" + "time": "2025-08-21T11:53:16+00:00" + }, + { + "name": "prism-php/prism", + "version": "v0.89.0", + "source": { + "type": "git", + "url": "https://github.com/prism-php/prism.git", + "reference": "1d06f3c1bb262dc407ba01cc45bc49647c0ed039" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/prism-php/prism/zipball/1d06f3c1bb262dc407ba01cc45bc49647c0ed039", + "reference": "1d06f3c1bb262dc407ba01cc45bc49647c0ed039", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "laravel/framework": "^11.0|^12.0", + "php": "^8.2" + }, + "require-dev": { + "laravel/pint": "^1.14", + "mockery/mockery": "^1.6", + "orchestra/testbench": "^10", + "pestphp/pest": "^3.0", + "pestphp/pest-plugin-arch": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0", + "phpstan/extension-installer": "^1.3", + "phpstan/phpdoc-parser": "^2.0", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-deprecation-rules": "^2.0", + "projektgopher/whisky": "^0.7.0", + "rector/rector": "^2.1", + "spatie/laravel-ray": "^1.39", + "symplify/rule-doc-generator-contracts": "^11.2" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "PrismServer": "Prism\\Prism\\Facades\\PrismServer" + }, + "providers": [ + "Prism\\Prism\\PrismServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Prism\\Prism\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "TJ Miller", + "email": "hello@echolabs.dev" + } + ], + "description": "A powerful Laravel package for integrating Large Language Models (LLMs) into your applications.", + "support": { + "issues": "https://github.com/prism-php/prism/issues", + "source": "https://github.com/prism-php/prism/tree/v0.89.0" + }, + "funding": [ + { + "url": "https://github.com/sixlive", + "type": "github" + } + ], + "time": "2025-09-10T19:58:43+00:00" }, { "name": "psr/clock", @@ -2955,16 +3209,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.4", + "version": "v0.12.12", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "2fd717afa05341b4f8152547f142cd2f130f6818" + "reference": "cd23863404a40ccfaf733e3af4db2b459837f7e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/2fd717afa05341b4f8152547f142cd2f130f6818", - "reference": "2fd717afa05341b4f8152547f142cd2f130f6818", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/cd23863404a40ccfaf733e3af4db2b459837f7e7", + "reference": "cd23863404a40ccfaf733e3af4db2b459837f7e7", "shasum": "" }, "require": { @@ -2991,12 +3245,12 @@ ], "type": "library", "extra": { - "branch-alias": { - "dev-main": "0.12.x-dev" - }, "bamarni-bin": { "bin-links": false, "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" } }, "autoload": { @@ -3014,12 +3268,11 @@ "authors": [ { "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" + "email": "justin@justinhileman.info" } ], "description": "An interactive shell for modern PHP.", - "homepage": "http://psysh.org", + "homepage": "https://psysh.org", "keywords": [ "REPL", "console", @@ -3028,9 +3281,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.4" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.12" }, - "time": "2024-06-10T01:18:23+00:00" + "time": "2025-09-20T13:46:31+00:00" }, { "name": "ralouphie/getallheaders", @@ -3078,16 +3331,16 @@ }, { "name": "ramsey/collection", - "version": "2.0.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", - "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", "shasum": "" }, "require": { @@ -3095,25 +3348,22 @@ }, "require-dev": { "captainhook/plugin-composer": "^5.3", - "ergebnis/composer-normalize": "^2.28.3", - "fakerphp/faker": "^1.21", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", "hamcrest/hamcrest-php": "^2.0", - "jangregor/phpstan-prophecy": "^1.0", - "mockery/mockery": "^1.5", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpcsstandards/phpcsutils": "^1.0.0-rc1", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18.4", - "ramsey/coding-standard": "^2.0.3", - "ramsey/conventional-commits": "^1.3", - "vimeo/psalm": "^5.4" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" }, "type": "library", "extra": { @@ -3151,37 +3401,26 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/2.0.0" + "source": "https://github.com/ramsey/collection/tree/2.1.1" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", - "type": "tidelift" - } - ], - "time": "2022-12-31T21:50:55+00:00" + "time": "2025-03-22T05:38:12+00:00" }, { "name": "ramsey/uuid", - "version": "4.7.6", + "version": "4.9.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440", + "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", - "ext-json": "*", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -3189,26 +3428,23 @@ "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.10", + "captainhook/captainhook": "^5.25", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.8", - "ergebnis/composer-normalize": "^2.15", - "mockery/mockery": "^1.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.2", - "php-mock/php-mock-mockery": "^1.3", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9", - "ramsey/composer-repl": "^1.4", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.9" + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", @@ -3243,63 +3479,127 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.6" + "source": "https://github.com/ramsey/uuid/tree/4.9.1" + }, + "time": "2025-09-04T20:59:21+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.3.0" }, "funding": [ { - "url": "https://github.com/ramsey", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-27T21:32:50+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/console", - "version": "v6.4.15", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd" + "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f1fc6f47283e27336e7cebb9e8946c8de7bff9bd", - "reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd", + "url": "https://api.github.com/repos/symfony/console/zipball/cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", + "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" + "symfony/string": "^7.2" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3333,7 +3633,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.15" + "source": "https://github.com/symfony/console/tree/v7.3.3" }, "funding": [ { @@ -3344,16 +3644,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-06T14:19:14+00:00" + "time": "2025-08-25T06:35:40+00:00" }, { "name": "symfony/css-selector", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -3398,7 +3702,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.2.0" + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" }, "funding": [ { @@ -3418,16 +3722,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -3435,12 +3739,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -3465,7 +3769,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -3481,35 +3785,37 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.14", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "9e024324511eeb00983ee76b9aedc3e6ecd993d9" + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/9e024324511eeb00983ee76b9aedc3e6ecd993d9", - "reference": "9e024324511eeb00983ee76b9aedc3e6ecd993d9", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^6.4|^7.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { + "symfony/console": "^6.4|^7.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^5.4|^6.0|^7.0" + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -3540,7 +3846,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.14" + "source": "https://github.com/symfony/error-handler/tree/v7.3.2" }, "funding": [ { @@ -3551,25 +3857,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-05T15:34:40+00:00" + "time": "2025-07-07T08:17:57+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.2.0", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", "shasum": "" }, "require": { @@ -3620,7 +3930,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3" }, "funding": [ { @@ -3631,25 +3941,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { @@ -3658,12 +3972,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -3696,7 +4010,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -3712,27 +4026,27 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/finder", - "version": "v6.4.13", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "daea9eca0b08d0ed1dc9ab702a46128fd1be4958" + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/daea9eca0b08d0ed1dc9ab702a46128fd1be4958", - "reference": "daea9eca0b08d0ed1dc9ab702a46128fd1be4958", + "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3760,7 +4074,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.13" + "source": "https://github.com/symfony/finder/tree/v7.3.2" }, "funding": [ { @@ -3771,45 +4085,51 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-10-01T08:30:56+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.16", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "431771b7a6f662f1575b3cfc8fd7617aa9864d57" + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/431771b7a6f662f1575b3cfc8fd7617aa9864d57", - "reference": "431771b7a6f662f1575b3cfc8fd7617aa9864d57", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7475561ec27020196c49bb7c4f178d33d7d3dc00", + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php83": "^1.27" }, "conflict": { + "doctrine/dbal": "<3.6", "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { - "doctrine/dbal": "^2.13.1|^3|^4", + "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", "symfony/cache": "^6.4.12|^7.1.5", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", - "symfony/mime": "^5.4|^6.0|^7.0", - "symfony/rate-limiter": "^5.4|^6.0|^7.0" + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3837,7 +4157,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.16" + "source": "https://github.com/symfony/http-foundation/tree/v7.3.3" }, "funding": [ { @@ -3848,82 +4168,86 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-13T18:58:10+00:00" + "time": "2025-08-20T08:04:18+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.16", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0" + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", - "reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/72c304de37e1a1cec6d5d12b81187ebd4850a17b", + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.4", - "symfony/config": "<6.1", - "symfony/console": "<5.4", + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<5.4", - "symfony/form": "<5.4", - "symfony/http-client": "<5.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/translation": "<5.4", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<5.4", + "symfony/twig-bridge": "<6.4", "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.3", - "twig/twig": "<2.13" + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/clock": "^6.2|^7.0", - "symfony/config": "^6.1|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/property-access": "^5.4.5|^6.0.5|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.4.4|^7.0.4", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^5.4|^6.4|^7.0", - "symfony/var-exporter": "^6.2|^7.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" }, "type": "library", "autoload": { @@ -3951,7 +4275,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.16" + "source": "https://github.com/symfony/http-kernel/tree/v7.3.3" }, "funding": [ { @@ -3962,48 +4286,52 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-27T12:49:36+00:00" + "time": "2025-08-29T08:23:45+00:00" }, { "name": "symfony/mailer", - "version": "v6.4.13", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "c2f7e0d8d7ac8fe25faccf5d8cac462805db2663" + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/c2f7e0d8d7ac8fe25faccf5d8cac462805db2663", - "reference": "c2f7e0d8d7ac8fe25faccf5d8cac462805db2663", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a32f3f45f1990db8c4341d5122a7d3a381c7e575", + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.1", + "php": ">=8.2", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/mime": "^6.2|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4", - "symfony/messenger": "<6.2", - "symfony/mime": "<6.2", - "symfony/twig-bridge": "<6.2.1" + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/messenger": "^6.2|^7.0", - "symfony/twig-bridge": "^6.2|^7.0" + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4031,7 +4359,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.4.13" + "source": "https://github.com/symfony/mailer/tree/v7.3.3" }, "funding": [ { @@ -4042,30 +4370,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "symfony/mime", - "version": "v6.4.13", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "1de1cf14d99b12c7ebbb850491ec6ae3ed468855" + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/1de1cf14d99b12c7ebbb850491ec6ae3ed468855", - "reference": "1de1cf14d99b12c7ebbb850491ec6ae3ed468855", + "url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -4073,17 +4404,17 @@ "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<5.4", + "symfony/mailer": "<6.4", "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.4|^7.0", - "symfony/property-access": "^5.4|^6.0|^7.0", - "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", "symfony/serializer": "^6.4.3|^7.0.3" }, "type": "library", @@ -4116,7 +4447,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.13" + "source": "https://github.com/symfony/mime/tree/v7.3.2" }, "funding": [ { @@ -4127,16 +4458,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-10-25T15:07:50+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -4160,8 +4495,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4195,7 +4530,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -4206,6 +4541,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -4215,16 +4554,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { @@ -4236,8 +4575,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4273,7 +4612,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -4284,25 +4623,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { @@ -4315,8 +4658,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4356,7 +4699,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" }, "funding": [ { @@ -4367,16 +4710,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -4397,8 +4744,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4437,7 +4784,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -4448,6 +4795,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -4457,19 +4808,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -4481,8 +4833,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4517,7 +4869,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -4528,25 +4880,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -4555,8 +4911,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4597,7 +4953,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -4605,7 +4961,11 @@ "type": "custom" }, { - "url": "https://github.com/fabpot", + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" }, { @@ -4613,20 +4973,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", "shasum": "" }, "require": { @@ -4635,8 +4995,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4673,7 +5033,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" }, "funding": [ { @@ -4684,16 +5044,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-07-08T02:45:35+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -4717,8 +5081,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4752,7 +5116,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" }, "funding": [ { @@ -4763,6 +5127,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -4772,20 +5140,20 @@ }, { "name": "symfony/process", - "version": "v6.4.15", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "3cb242f059c14ae08591c5c4087d1fe443564392" + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/3cb242f059c14ae08591c5c4087d1fe443564392", - "reference": "3cb242f059c14ae08591c5c4087d1fe443564392", + "url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1", + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -4813,7 +5181,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.15" + "source": "https://github.com/symfony/process/tree/v7.3.3" }, "funding": [ { @@ -4824,45 +5192,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-06T14:19:14+00:00" + "time": "2025-08-18T09:42:54+00:00" }, { "name": "symfony/routing", - "version": "v6.4.16", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "91e02e606b4b705c2f4fb42f7e7708b7923a3220" + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/91e02e606b4b705c2f4fb42f7e7708b7923a3220", - "reference": "91e02e606b4b705c2f4fb42f7e7708b7923a3220", + "url": "https://api.github.com/repos/symfony/routing/zipball/7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<6.2", - "symfony/dependency-injection": "<5.4", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^6.2|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4896,7 +5266,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.16" + "source": "https://github.com/symfony/routing/tree/v7.3.2" }, "funding": [ { @@ -4907,25 +5277,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-13T15:31:34+00:00" + "time": "2025-07-15T11:36:08+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -4938,12 +5312,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -4979,7 +5353,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -4995,20 +5369,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/string", - "version": "v7.2.0", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", "shasum": "" }, "require": { @@ -5066,7 +5440,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" + "source": "https://github.com/symfony/string/tree/v7.3.3" }, "funding": [ { @@ -5077,60 +5451,65 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-13T13:31:26+00:00" + "time": "2025-08-25T06:35:40+00:00" }, { "name": "symfony/translation", - "version": "v6.4.13", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66" + "reference": "e0837b4cbcef63c754d89a4806575cada743a38d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/bee9bfabfa8b4045a66bf82520e492cddbaffa66", - "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66", + "url": "https://api.github.com/repos/symfony/translation/zipball/e0837b4cbcef63c754d89a4806575cada743a38d", + "reference": "e0837b4cbcef63c754d89a4806575cada743a38d", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { - "symfony/config": "<5.4", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", + "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4", + "symfony/http-kernel": "<6.4", "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<5.4", - "symfony/yaml": "<5.4" + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/routing": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5161,7 +5540,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.13" + "source": "https://github.com/symfony/translation/tree/v7.3.3" }, "funding": [ { @@ -5172,25 +5551,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-27T18:14:25+00:00" + "time": "2025-08-01T21:02:37+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", - "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", "shasum": "" }, "require": { @@ -5198,12 +5581,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -5239,7 +5622,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" }, "funding": [ { @@ -5255,28 +5638,28 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-27T08:32:26+00:00" }, { "name": "symfony/uid", - "version": "v6.4.13", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007" + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/18eb207f0436a993fffbdd811b5b8fa35fa5e007", - "reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007", + "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5313,7 +5696,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.13" + "source": "https://github.com/symfony/uid/tree/v7.3.1" }, "funding": [ { @@ -5329,38 +5712,36 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2025-06-27T19:55:54+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.15", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "38254d5a5ac2e61f2b52f9caf54e7aa3c9d36b80" + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/38254d5a5ac2e61f2b52f9caf54e7aa3c9d36b80", - "reference": "38254d5a5ac2e61f2b52f9caf54e7aa3c9d36b80", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { - "ext-iconv": "*", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^6.3|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" }, "bin": [ "Resources/bin/var-dump-server" @@ -5398,7 +5779,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.15" + "source": "https://github.com/symfony/var-dumper/tree/v7.3.3" }, "funding": [ { @@ -5409,40 +5790,46 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-08T15:28:48+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "v2.2.7", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb" + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/83ee6f38df0a63106a9e4536e3060458b74ccedb", - "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", - "php": "^5.5 || ^7.0 || ^8.0", - "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -5465,22 +5852,22 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.2.7" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" }, - "time": "2023-12-08T13:03:43+00:00" + "time": "2024-12-21T16:25:41+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.6.1", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", - "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", "shasum": "" }, "require": { @@ -5539,7 +5926,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" }, "funding": [ { @@ -5551,7 +5938,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:52:34+00:00" + "time": "2025-04-30T23:37:27+00:00" }, { "name": "voku/portable-ascii", @@ -5687,88 +6074,18 @@ } ], "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:23:10+00:00" - }, { "name": "fakerphp/faker", - "version": "v1.23.1", + "version": "v1.24.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", "shasum": "" }, "require": { @@ -5816,22 +6133,22 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" }, - "time": "2024-01-02T13:46:09+00:00" + "time": "2024-11-21T13:46:39+00:00" }, { "name": "filp/whoops", - "version": "2.16.0", + "version": "2.18.4", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", + "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d", "shasum": "" }, "require": { @@ -5881,7 +6198,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.16.0" + "source": "https://github.com/filp/whoops/tree/2.18.4" }, "funding": [ { @@ -5889,24 +6206,24 @@ "type": "github" } ], - "time": "2024-09-25T12:00:00+00:00" + "time": "2025-08-08T12:00:00+00:00" }, { "name": "hamcrest/hamcrest-php", - "version": "v2.0.1", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", "shasum": "" }, "require": { - "php": "^5.3|^7.0|^8.0" + "php": "^7.4|^8.0" }, "replace": { "cordoval/hamcrest-php": "*", @@ -5914,8 +6231,8 @@ "kodova/hamcrest-php": "*" }, "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { @@ -5938,22 +6255,22 @@ ], "support": { "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" }, - "time": "2020-07-09T08:09:16+00:00" + "time": "2025-04-30T06:54:44+00:00" }, { "name": "laravel/pint", - "version": "v1.18.1", + "version": "v1.25.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9" + "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/35c00c05ec43e6b46d295efc0f4386ceb30d50d9", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9", + "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9", + "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9", "shasum": "" }, "require": { @@ -5961,16 +6278,16 @@ "ext-mbstring": "*", "ext-tokenizer": "*", "ext-xml": "*", - "php": "^8.1.0" + "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.64.0", - "illuminate/view": "^10.48.20", - "larastan/larastan": "^2.9.8", - "laravel-zero/framework": "^10.4.0", + "friendsofphp/php-cs-fixer": "^3.87.2", + "illuminate/view": "^11.46.0", + "larastan/larastan": "^3.7.1", + "laravel-zero/framework": "^11.45.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.1" + "nunomaduro/termwind": "^2.3.1", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" @@ -6006,32 +6323,32 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-09-24T17:22:50+00:00" + "time": "2025-09-19T02:57:12+00:00" }, { "name": "laravel/sail", - "version": "v1.35.0", + "version": "v1.46.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "992bc2d9e52174c79515967f30849d21daa334d8" + "reference": "eb90c4f113c4a9637b8fdd16e24cfc64f2b0ae6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/992bc2d9e52174c79515967f30849d21daa334d8", - "reference": "992bc2d9e52174c79515967f30849d21daa334d8", + "url": "https://api.github.com/repos/laravel/sail/zipball/eb90c4f113c4a9637b8fdd16e24cfc64f2b0ae6e", + "reference": "eb90c4f113c4a9637b8fdd16e24cfc64f2b0ae6e", "shasum": "" }, "require": { - "illuminate/console": "^9.52.16|^10.0|^11.0", - "illuminate/contracts": "^9.52.16|^10.0|^11.0", - "illuminate/support": "^9.52.16|^10.0|^11.0", + "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0", "php": "^8.0", "symfony/console": "^6.0|^7.0", "symfony/yaml": "^6.0|^7.0" }, "require-dev": { - "orchestra/testbench": "^7.0|^8.0|^9.0", + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", "phpstan/phpstan": "^1.10" }, "bin": [ @@ -6069,7 +6386,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2024-10-08T14:45:26+00:00" + "time": "2025-09-23T13:44:39+00:00" }, { "name": "mockery/mockery", @@ -6156,16 +6473,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -6204,7 +6521,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -6212,49 +6529,58 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nunomaduro/collision", - "version": "v6.4.0", + "version": "v8.5.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "f05978827b9343cba381ca05b8c7deee346b6015" + "reference": "f5c101b929c958e849a633283adff296ed5f38f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f05978827b9343cba381ca05b8c7deee346b6015", - "reference": "f05978827b9343cba381ca05b8c7deee346b6015", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5", "shasum": "" }, "require": { - "filp/whoops": "^2.14.5", - "php": "^8.0.0", - "symfony/console": "^6.0.2" + "filp/whoops": "^2.16.0", + "nunomaduro/termwind": "^2.1.0", + "php": "^8.2.0", + "symfony/console": "^7.1.5" + }, + "conflict": { + "laravel/framework": "<11.0.0 || >=12.0.0", + "phpunit/phpunit": "<10.5.1 || >=12.0.0" }, "require-dev": { - "brianium/paratest": "^6.4.1", - "laravel/framework": "^9.26.1", - "laravel/pint": "^1.1.1", - "nunomaduro/larastan": "^1.0.3", - "nunomaduro/mock-final-classes": "^1.1.0", - "orchestra/testbench": "^7.7", - "phpunit/phpunit": "^9.5.23", - "spatie/ignition": "^1.4.1" + "larastan/larastan": "^2.9.8", + "laravel/framework": "^11.28.0", + "laravel/pint": "^1.18.1", + "laravel/sail": "^1.36.0", + "laravel/sanctum": "^4.0.3", + "laravel/tinker": "^2.10.0", + "orchestra/testbench-core": "^9.5.3", + "pestphp/pest": "^2.36.0 || ^3.4.0", + "sebastian/environment": "^6.1.0 || ^7.2.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-develop": "6.x-dev" - }, "laravel": { "providers": [ "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" } }, "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], "psr-4": { "NunoMaduro\\Collision\\": "src/" } @@ -6300,7 +6626,7 @@ "type": "patreon" } ], - "time": "2023-01-03T12:54:54+00:00" + "time": "2024-10-15T16:06:32+00:00" }, { "name": "phar-io/manifest", @@ -6422,16 +6748,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.32", + "version": "10.1.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { @@ -6439,18 +6765,18 @@ "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-text-template": "^2.0.4", - "sebastian/code-unit-reverse-lookup": "^2.0.3", - "sebastian/complexity": "^2.0.3", - "sebastian/environment": "^5.1.5", - "sebastian/lines-of-code": "^1.0.4", - "sebastian/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -6459,7 +6785,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.2.x-dev" + "dev-main": "10.1.x-dev" } }, "autoload": { @@ -6488,7 +6814,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { @@ -6496,32 +6822,32 @@ "type": "github" } ], - "time": "2024-08-22T04:23:01+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -6548,7 +6874,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -6556,28 +6883,28 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" @@ -6585,7 +6912,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -6611,7 +6938,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { @@ -6619,32 +6946,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2023-02-03T06:56:09+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -6670,7 +6997,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -6678,32 +7006,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -6729,7 +7057,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { @@ -6737,54 +7065,52 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { "name": "phpunit/phpunit", - "version": "9.6.21", + "version": "10.5.57", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa" + "reference": "8e7598bbb17bb5cd80728f4831d3f83223d3a6b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e7598bbb17bb5cd80728f4831d3f83223d3a6b3", + "reference": "8e7598bbb17bb5cd80728f4831d3f83223d3a6b3", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.32", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.4", - "phpunit/php-timer": "^5.0.3", - "sebastian/cli-parser": "^1.0.2", - "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.6", - "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", - "sebastian/object-enumerator": "^4.0.4", - "sebastian/resource-operations": "^3.0.4", - "sebastian/type": "^3.2.1", - "sebastian/version": "^3.0.2" + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.4", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.4", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.1", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -6792,7 +7118,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-main": "10.5-dev" } }, "autoload": { @@ -6824,7 +7150,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.21" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.57" }, "funding": [ { @@ -6835,37 +7161,45 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2024-09-19T10:50:18+00:00" + "time": "2025-09-24T06:30:38+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -6888,7 +7222,8 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { @@ -6896,32 +7231,32 @@ "type": "github" } ], - "time": "2024-03-02T06:27:43+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -6944,7 +7279,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { @@ -6952,32 +7287,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -6999,7 +7334,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { @@ -7007,34 +7342,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "5.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e8e53097718d2b53cfb2aa859b06a41abf58c62e", + "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -7073,41 +7410,54 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2025-09-07T05:25:07+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.3", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.2-dev" } }, "autoload": { @@ -7130,7 +7480,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { @@ -7138,33 +7489,33 @@ "type": "github" } ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -7196,7 +7547,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -7204,27 +7556,27 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" @@ -7232,7 +7584,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -7251,7 +7603,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -7259,7 +7611,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -7267,34 +7620,34 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "0735b90f4da94969541dac1da743446e276defa6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", + "reference": "0735b90f4da94969541dac1da743446e276defa6", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -7336,46 +7689,56 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:09:11+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -7394,13 +7757,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { @@ -7408,33 +7772,33 @@ "type": "github" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.4", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -7457,7 +7821,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { @@ -7465,34 +7830,34 @@ "type": "github" } ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -7514,7 +7879,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { @@ -7522,32 +7887,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -7569,7 +7934,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { @@ -7577,32 +7942,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -7632,94 +7997,53 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - } - ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" - }, - "funding": [ + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2025-08-10T07:50:56+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -7742,7 +8066,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -7750,29 +8074,29 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -7795,7 +8119,7 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -7803,31 +8127,31 @@ "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { "name": "spatie/backtrace", - "version": "1.6.2", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9" + "reference": "8c0f16a59ae35ec8c62d85c3c17585158f430110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/1a9a145b044677ae3424693f7b06479fc8c137a9", - "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/8c0f16a59ae35ec8c62d85c3c17585158f430110", + "reference": "8c0f16a59ae35ec8c62d85c3c17585158f430110", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "php": "^7.3 || ^8.0" }, "require-dev": { "ext-json": "*", - "laravel/serializable-closure": "^1.3", - "phpunit/phpunit": "^9.3", - "spatie/phpunit-snapshot-assertions": "^4.2", - "symfony/var-dumper": "^5.1" + "laravel/serializable-closure": "^1.3 || ^2.0", + "phpunit/phpunit": "^9.3 || ^11.4.3", + "spatie/phpunit-snapshot-assertions": "^4.2 || ^5.1.6", + "symfony/var-dumper": "^5.1 || ^6.0 || ^7.0" }, "type": "library", "autoload": { @@ -7854,7 +8178,8 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.6.2" + "issues": "https://github.com/spatie/backtrace/issues", + "source": "https://github.com/spatie/backtrace/tree/1.8.1" }, "funding": [ { @@ -7866,34 +8191,34 @@ "type": "other" } ], - "time": "2024-07-22T08:21:24+00:00" + "time": "2025-08-26T08:22:30+00:00" }, { "name": "spatie/error-solutions", - "version": "1.1.1", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/spatie/error-solutions.git", - "reference": "ae7393122eda72eed7cc4f176d1e96ea444f2d67" + "reference": "e495d7178ca524f2dd0fe6a1d99a1e608e1c9936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/error-solutions/zipball/ae7393122eda72eed7cc4f176d1e96ea444f2d67", - "reference": "ae7393122eda72eed7cc4f176d1e96ea444f2d67", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/e495d7178ca524f2dd0fe6a1d99a1e608e1c9936", + "reference": "e495d7178ca524f2dd0fe6a1d99a1e608e1c9936", "shasum": "" }, "require": { "php": "^8.0" }, "require-dev": { - "illuminate/broadcasting": "^10.0|^11.0", - "illuminate/cache": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", - "livewire/livewire": "^2.11|^3.3.5", + "illuminate/broadcasting": "^10.0|^11.0|^12.0", + "illuminate/cache": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "livewire/livewire": "^2.11|^3.5.20", "openai-php/client": "^0.10.1", - "orchestra/testbench": "^7.0|8.22.3|^9.0", - "pestphp/pest": "^2.20", - "phpstan/phpstan": "^1.11", + "orchestra/testbench": "8.22.3|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "phpstan/phpstan": "^2.1", "psr/simple-cache": "^3.0", "psr/simple-cache-implementation": "^3.0", "spatie/ray": "^1.28", @@ -7932,7 +8257,7 @@ ], "support": { "issues": "https://github.com/spatie/error-solutions/issues", - "source": "https://github.com/spatie/error-solutions/tree/1.1.1" + "source": "https://github.com/spatie/error-solutions/tree/1.1.3" }, "funding": [ { @@ -7940,24 +8265,24 @@ "type": "github" } ], - "time": "2024-07-25T11:06:04+00:00" + "time": "2025-02-14T12:29:50+00:00" }, { "name": "spatie/flare-client-php", - "version": "1.8.0", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122" + "reference": "bf1716eb98bd689451b071548ae9e70738dce62f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122", - "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/bf1716eb98bd689451b071548ae9e70738dce62f", + "reference": "bf1716eb98bd689451b071548ae9e70738dce62f", "shasum": "" }, "require": { - "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0", + "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0|^12.0", "php": "^8.0", "spatie/backtrace": "^1.6.1", "symfony/http-foundation": "^5.2|^6.0|^7.0", @@ -8001,7 +8326,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.8.0" + "source": "https://github.com/spatie/flare-client-php/tree/1.10.1" }, "funding": [ { @@ -8009,20 +8334,20 @@ "type": "github" } ], - "time": "2024-08-01T08:27:26+00:00" + "time": "2025-02-14T13:42:06+00:00" }, { "name": "spatie/ignition", - "version": "1.15.0", + "version": "1.15.1", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2" + "reference": "31f314153020aee5af3537e507fef892ffbf8c85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/e3a68e137371e1eb9edc7f78ffa733f3b98991d2", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2", + "url": "https://api.github.com/repos/spatie/ignition/zipball/31f314153020aee5af3537e507fef892ffbf8c85", + "reference": "31f314153020aee5af3537e507fef892ffbf8c85", "shasum": "" }, "require": { @@ -8035,7 +8360,7 @@ "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "require-dev": { - "illuminate/cache": "^9.52|^10.0|^11.0", + "illuminate/cache": "^9.52|^10.0|^11.0|^12.0", "mockery/mockery": "^1.4", "pestphp/pest": "^1.20|^2.0", "phpstan/extension-installer": "^1.1", @@ -8092,27 +8417,27 @@ "type": "github" } ], - "time": "2024-06-12T14:55:22+00:00" + "time": "2025-02-21T14:31:39+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.8.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "3c067b75bfb50574db8f7e2c3978c65eed71126c" + "reference": "1baee07216d6748ebd3a65ba97381b051838707a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/3c067b75bfb50574db8f7e2c3978c65eed71126c", - "reference": "3c067b75bfb50574db8f7e2c3978c65eed71126c", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1baee07216d6748ebd3a65ba97381b051838707a", + "reference": "1baee07216d6748ebd3a65ba97381b051838707a", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0|^12.0", "php": "^8.1", "spatie/ignition": "^1.15", "symfony/console": "^6.2.3|^7.0", @@ -8121,12 +8446,12 @@ "require-dev": { "livewire/livewire": "^2.11|^3.3.5", "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.8.1", - "orchestra/testbench": "8.22.3|^9.0", - "pestphp/pest": "^2.34", + "openai-php/client": "^0.8.1|^0.10", + "orchestra/testbench": "8.22.3|^9.0|^10.0", + "pestphp/pest": "^2.34|^3.7", "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.16", + "phpstan/phpstan-deprecation-rules": "^1.1.1|^2.0", + "phpstan/phpstan-phpunit": "^1.3.16|^2.0", "vlucas/phpdotenv": "^5.5" }, "suggest": { @@ -8136,12 +8461,12 @@ "type": "library", "extra": { "laravel": { - "providers": [ - "Spatie\\LaravelIgnition\\IgnitionServiceProvider" - ], "aliases": { "Flare": "Spatie\\LaravelIgnition\\Facades\\Flare" - } + }, + "providers": [ + "Spatie\\LaravelIgnition\\IgnitionServiceProvider" + ] } }, "autoload": { @@ -8183,24 +8508,25 @@ "type": "github" } ], - "time": "2024-06-12T15:01:18+00:00" + "time": "2025-02-20T13:13:55+00:00" }, { "name": "symfony/yaml", - "version": "v7.1.5", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4e561c316e135e053bd758bf3b3eb291d9919de4" + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4e561c316e135e053bd758bf3b3eb291d9919de4", - "reference": "4e561c316e135e053bd758bf3b3eb291d9919de4", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d", + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -8238,7 +8564,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.1.5" + "source": "https://github.com/symfony/yaml/tree/v7.3.3" }, "funding": [ { @@ -8249,12 +8575,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-17T12:49:58+00:00" + "time": "2025-08-27T11:34:33+00:00" }, { "name": "theseer/tokenizer", @@ -8315,8 +8645,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.0.2" + "php": "^8.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/playgrounds/react/config/prism.php b/playgrounds/react/config/prism.php new file mode 100644 index 000000000..fec4a5cc5 --- /dev/null +++ b/playgrounds/react/config/prism.php @@ -0,0 +1,59 @@ + [ + // The middleware that will be applied to the Prism Server routes. + 'middleware' => [], + 'enabled' => env('PRISM_SERVER_ENABLED', false), + ], + 'providers' => [ + 'openai' => [ + 'url' => env('OPENAI_URL', 'https://api.openai.com/v1'), + 'api_key' => env('OPENAI_API_KEY', ''), + 'organization' => env('OPENAI_ORGANIZATION', null), + 'project' => env('OPENAI_PROJECT', null), + ], + 'anthropic' => [ + 'api_key' => env('ANTHROPIC_API_KEY', ''), + 'version' => env('ANTHROPIC_API_VERSION', '2023-06-01'), + 'default_thinking_budget' => env('ANTHROPIC_DEFAULT_THINKING_BUDGET', 1024), + // Include beta strings as a comma separated list. + 'anthropic_beta' => env('ANTHROPIC_BETA', null), + ], + 'ollama' => [ + 'url' => env('OLLAMA_URL', 'http://localhost:11434'), + ], + 'mistral' => [ + 'api_key' => env('MISTRAL_API_KEY', ''), + 'url' => env('MISTRAL_URL', 'https://api.mistral.ai/v1'), + ], + 'groq' => [ + 'api_key' => env('GROQ_API_KEY', ''), + 'url' => env('GROQ_URL', 'https://api.groq.com/openai/v1'), + ], + 'xai' => [ + 'api_key' => env('XAI_API_KEY', ''), + 'url' => env('XAI_URL', 'https://api.x.ai/v1'), + ], + 'gemini' => [ + 'api_key' => env('GEMINI_API_KEY', ''), + 'url' => env('GEMINI_URL', 'https://generativelanguage.googleapis.com/v1beta/models'), + ], + 'deepseek' => [ + 'api_key' => env('DEEPSEEK_API_KEY', ''), + 'url' => env('DEEPSEEK_URL', 'https://api.deepseek.com/v1'), + ], + 'elevenlabs' => [ + 'api_key' => env('ELEVENLABS_API_KEY', ''), + 'url' => env('ELEVENLABS_URL', 'https://api.elevenlabs.io/v1/'), + ], + 'voyageai' => [ + 'api_key' => env('VOYAGEAI_API_KEY', ''), + 'url' => env('VOYAGEAI_URL', 'https://api.voyageai.com/v1'), + ], + 'openrouter' => [ + 'api_key' => env('OPENROUTER_API_KEY', ''), + 'url' => env('OPENROUTER_URL', 'https://openrouter.ai/api/v1'), + ], + ], +]; diff --git a/playgrounds/react/database/factories/ChatMessageFactory.php b/playgrounds/react/database/factories/ChatMessageFactory.php new file mode 100644 index 000000000..3f1a7ad72 --- /dev/null +++ b/playgrounds/react/database/factories/ChatMessageFactory.php @@ -0,0 +1,24 @@ + + */ +class ChatMessageFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'type' => $this->faker->randomElement(['prompt', 'response']), + 'content' => $this->faker->sentence, + ]; + } +} diff --git a/playgrounds/react/database/migrations/2025_08_29_115526_create_chat_messages_table.php b/playgrounds/react/database/migrations/2025_08_29_115526_create_chat_messages_table.php new file mode 100644 index 000000000..2b30afe1a --- /dev/null +++ b/playgrounds/react/database/migrations/2025_08_29_115526_create_chat_messages_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('type'); + $table->text('content'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('chat_messages'); + } +}; diff --git a/playgrounds/react/database/seeders/DatabaseSeeder.php b/playgrounds/react/database/seeders/DatabaseSeeder.php index 76d96dc7f..c6b2662c4 100644 --- a/playgrounds/react/database/seeders/DatabaseSeeder.php +++ b/playgrounds/react/database/seeders/DatabaseSeeder.php @@ -3,7 +3,10 @@ namespace Database\Seeders; // use Illuminate\Database\Console\Seeds\WithoutModelEvents; + +use App\Models\ChatMessage; use Illuminate\Database\Seeder; +use Illuminate\Support\Facades\File; class DatabaseSeeder extends Seeder { @@ -14,7 +17,10 @@ class DatabaseSeeder extends Seeder */ public function run() { - // \App\Models\User::factory(10)->create(); + collect(File::json(database_path('seeders/conversation.json'))) + ->each(fn ($chatMessage) => ChatMessage::create($chatMessage)); + + // \App\Models\User::factory(5000)->create(); // \App\Models\User::factory()->create([ // 'name' => 'Test User', diff --git a/playgrounds/react/database/seeders/conversation.json b/playgrounds/react/database/seeders/conversation.json new file mode 100644 index 000000000..2431ec4ab --- /dev/null +++ b/playgrounds/react/database/seeders/conversation.json @@ -0,0 +1,90 @@ +[ + { + "type": "prompt", + "content": "Hey! Tell me about PHP" + }, + { + "type": "response", + "content": "Okay, let's talk about PHP (Hypertext Preprocessor). PHP is a widely-used, open-source scripting language primarily designed for web development. It\u2019s known for its ease of use and large community support. \n\nHere's a breakdown of key aspects:\n\n1. **Server-Side Scripting:** PHP code runs on the web server, generating HTML that is sent to the user's browser. This is different from client-side languages like JavaScript, which execute in the browser.\n\n2. **Dynamic Content:** PHP excels at creating dynamic web pages. It can generate content based on user input, database queries, or other variables.\n\n ```php\n \n ```\n\n3. **Database Integration:** PHP has excellent support for connecting to and interacting with various databases like MySQL, PostgreSQL, and MongoDB.\n\n ```php\n connect_error) {\n die(\"Connection failed: \" . $conn->connect_error);\n }\n\n echo \"Connected to database successfully\";\n ?>\n ```\n\n4. **Frameworks:** Popular PHP frameworks like Laravel, Symfony, and CodeIgniter provide structure and tools to streamline development.\n\n5. **Usage:** PHP is used to build everything from simple websites and blogs to complex web applications, e-commerce platforms, and APIs. \n\n6. **Evolution:** PHP has evolved significantly over the years, with modern versions (PHP 7.x and 8.x) offering improved performance and features.\n\nIn essence, PHP is a versatile and mature language that remains a significant force in web development.\n\n\n\nDo you want to know about a specific aspect of PHP, such as its syntax, frameworks, or usage examples?" + }, + { + "type": "prompt", + "content": "What is Laravel?" + }, + { + "type": "response", + "content": "Laravel is a popular, open-source PHP framework designed for building web applications efficiently. It follows the Model-View-Controller (MVC) architectural pattern, promoting organized code and maintainability. Laravel provides a robust set of tools and features to simplify development.\n\nHere's a basic example:\n\n```php\n\n```\n\nKey features include:\n\n* **Eloquent ORM:** For easy database interaction.\n* **Templating Engine (Blade):** For creating dynamic HTML.\n* **Routing:** For mapping URLs to controller actions.\n* **Security Features:** Built-in protection against common vulnerabilities.\n\nLaravel\u2019s ecosystem has a huge community and lots of packages, making it a solid choice for modern web development. Essentially, it\u2019s a toolkit that accelerates the process of creating robust and scalable PHP applications." + }, + { + "type": "prompt", + "content": "Eloquent sounds... very nice!" + }, + { + "type": "response", + "content": "Laravel is a popular PHP framework known for its elegant design and powerful features. It follows the MVC architectural pattern, promoting organized code. Eloquent, Laravel\u2019s ORM (Object-Relational Mapper), simplifies database interactions \u2013 like this: `$users = User::all();`. Laravel\u2019s routing system, like `Route::get('\/', function () { return \"Hello, World!\"; });`, connects URLs to your application\u2019s logic. Blade, Laravel's templating engine, allows you to create dynamic HTML. Laravel includes built-in security features to protect your app. It\u2019s a robust framework for building web applications quickly and efficiently. Laravel\u2019s large community provides plenty of support and resources. It is a great choice for modern web development." + }, + { + "type": "prompt", + "content": "I want to know more about Eloquent" + }, + { + "type": "response", + "content": "Eloquent is Laravel\u2019s powerful ORM (Object-Relational Mapper), simplifying database interactions. It allows you to interact with your database using PHP objects instead of raw SQL. \n\nFor example, `$users = User::all();` retrieves all users from your database. Eloquent models represent database tables, offering a cleaner and more object-oriented approach. It handles SQL queries automatically, making development faster and more maintainable. \n\nEloquent provides features like relationships (one-to-one, one-to-many, many-to-many) to model complex data connections. You can also use Eloquent to perform CRUD (Create, Read, Update, Delete) operations. \n\n```php\n\/\/ Example: Retrieving a user by ID\n$user = User::find(1);\n```\n\nEloquent is a core component of Laravel, streamlining database access and improving development efficiency." + }, + { + "type": "prompt", + "content": "Does it work with MySQL?" + }, + { + "type": "response", + "content": "Yes, Eloquent works seamlessly with MySQL. It\u2019s Laravel\u2019s primary ORM, designed for database interactions, and MySQL is a very common and well-supported database backend for Laravel applications. Eloquent models represent your MySQL tables, allowing you to retrieve, create, update, and delete data using PHP objects. For example, `$users = User::all();` fetches all records from the `users` table. You can define relationships between models, like one-to-many, to represent data connections. Eloquent simplifies database interactions significantly, reducing the need for raw SQL queries in many cases. It\u2019s a robust and efficient way to manage your data within a Laravel application and MySQL." + }, + { + "type": "prompt", + "content": "What other engins does it support?" + }, + { + "type": "response", + "content": "Based on our discussion, Eloquent primarily supports MySQL. While the context didn\u2019t explicitly list all supported engines, Laravel\u2019s ORM is designed for flexibility and can be used with other databases like PostgreSQL, MongoDB, and SQLite. For example, `$users = User::all();` works regardless of the database backend. Eloquent\u2019s core architecture allows for database abstraction, meaning you can change the underlying database without altering your application logic. The framework provides tools to manage connections and queries. Laravel\u2019s flexibility makes it a powerful choice for diverse database environments." + }, + { + "type": "prompt", + "content": "Ah, even SQLite! What's the difference between MySQL and MariaDB these days?" + }, + { + "type": "response", + "content": "Eloquent primarily supports MySQL and SQLite. Both are excellent choices for Laravel development. MySQL is a robust, widely-used relational database, while SQLite is a lightweight, file-based database \u2013 perfect for smaller projects or development environments. Eloquent works identically with both, simplifying database interactions. There isn't a significant difference in functionality between MySQL and MariaDB that would impact Eloquent\u2019s usage. MariaDB is a fork of MySQL, offering similar features and compatibility. Eloquent\u2019s abstraction layer handles the underlying differences, allowing you to focus on your application logic. Essentially, you can use Eloquent with either database without needing to adjust your code significantly." + }, + { + "type": "prompt", + "content": "But outside of Laravel and Eloquent, why should I use MariaDB?" + }, + { + "type": "response", + "content": "Based on our conversation, Eloquent primarily supports MySQL and SQLite. MariaDB is a fork of MySQL, offering similar features. While Laravel\u2019s Eloquent works with both, MariaDB\u2019s primary advantage lies in its performance and open-source nature. It\u2019s often faster than MySQL, especially for certain workloads. MariaDB\u2019s open-source license provides greater flexibility and control compared to proprietary databases. For example, `$users = User::all();` would function identically with MariaDB as with MySQL. MariaDB\u2019s community support is strong. It's a viable alternative if you\u2019re seeking a robust, open-source database solution, offering similar functionality to MySQL." + }, + { + "type": "prompt", + "content": "Ok, let's change topics. Tell me about Event Broadcasting in Laravel" + }, + { + "type": "response", + "content": "Laravel\u2019s Event Broadcasting system allows decoupled communication between services and components. It uses events and listeners to trigger actions without direct dependencies.\n\nTo create an event, define a class extending `Illuminate\\Events\\DispatchableEvent`. For example:\n\n```php\n 'your_channel_name']);` The `Broadcastable` interface is essential for establishing the communication channel. For example: `$event = new UserRegistered(); Event::dispatch($event, ['channel' => 'channel_name']);` Laravel\u2019s Event Broadcasting simplifies real-time communication by decoupling event publishers and subscribers." + }, + { + "type": "prompt", + "content": "Hmm you don't know a lot about this topic... let's talk about Inertia.js" + }, + { + "type": "response", + "content": "Okay, let\u2019s discuss Inertia.js. Inertia.js simplifies building modern Vue.js applications with Laravel. It allows you to serve Vue components from your Laravel backend, handling routing and authentication.\n\nTo use Inertia, you\u2019d typically create a Vue component \u2013 for instance, a `components\/HelloWorld.vue` file. Then, you\u2019d use Inertia to \u201chydrate\u201d this component on the server. \n\n```php\nuse Inertia\\Payload;\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::get('\/hello', function () {\n $payload = new Payload([\n 'message' => 'Hello from Inertia!'\n ]);\n return inertia('hello', $payload);\n});\n```\n\nThis sends the Vue component and its data to the browser. The browser renders the Vue component. Inertia manages the separation of concerns, streamlining your Laravel and Vue development workflow." + } +] diff --git a/playgrounds/react/init.sh b/playgrounds/react/init.sh new file mode 100755 index 000000000..c1a1dac79 --- /dev/null +++ b/playgrounds/react/init.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -e + +# Install PHP dependencies via Composer +if [ ! -d "vendor" ]; then + echo "Installing PHP dependencies..." + composer install +else + echo "PHP dependencies already installed" +fi + +# Install Node.js dependencies via pnpm +if [ ! -d "node_modules" ]; then + echo "Installing Node.js dependencies..." + pnpm install +else + echo "Node.js dependencies already installed" +fi + +# Set up environment configuration +if [ ! -f ".env" ]; then + echo "Creating environment configuration..." + cp .env.example .env + php artisan key:generate +else + echo "Environment configuration already exists" +fi + +# Set up SQLite database +if [ ! -f "database/database.sqlite" ]; then + echo "Creating SQLite database..." + touch database/database.sqlite + echo "Running fresh migrations with seed data..." + php artisan migrate:fresh --seed +else + echo "Database already exists" +fi + +# Ensure database is up to date +echo "Running any pending migrations..." +php artisan migrate diff --git a/playgrounds/react/package.json b/playgrounds/react/package.json index 800d65ff1..1f7b6d555 100644 --- a/playgrounds/react/package.json +++ b/playgrounds/react/package.json @@ -8,17 +8,21 @@ "type": "module", "devDependencies": { "@inertiajs/react": "workspace:*", - "@tailwindcss/vite": "^4.1.8", - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.2", - "axios": "^1.12.0", - "laravel-vite-plugin": "^1.2.0", - "lodash": "^4.17.19", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "tailwindcss": "^4.1.8", + "@laravel/stream-react": "^0.3.9", + "@tailwindcss/typography": "^0.5.18", + "@tailwindcss/vite": "^4.1.13", + "@types/react": "^19.1.13", + "@types/react-dom": "^19.1.9", + "@vitejs/plugin-react": "^4.7.0", + "autosize": "^6.0.1", + "axios": "^1.12.2", + "laravel-vite-plugin": "^1.3.0", + "lodash": "^4.17.21", + "marked": "^16.3.0", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "tailwindcss": "^4.1.13", "typescript": "^4.9.5", - "vite": "^6.3.0" + "vite": "^6.3.6" } } diff --git a/playgrounds/react/resources/css/app.css b/playgrounds/react/resources/css/app.css index d4b507858..f06b87d89 100644 --- a/playgrounds/react/resources/css/app.css +++ b/playgrounds/react/resources/css/app.css @@ -1 +1,2 @@ @import 'tailwindcss'; +@plugin "@tailwindcss/typography"; diff --git a/playgrounds/react/resources/js/Components/Image.tsx b/playgrounds/react/resources/js/Components/Image.tsx new file mode 100644 index 000000000..c713d3c92 --- /dev/null +++ b/playgrounds/react/resources/js/Components/Image.tsx @@ -0,0 +1,25 @@ +import { useState } from 'react' + +export default function Image({ id, url }: { id: number; url: string }) { + const [loaded, setLoaded] = useState(false) + + return ( +
+ {!loaded && + ) +} diff --git a/playgrounds/react/resources/js/Components/Layout.tsx b/playgrounds/react/resources/js/Components/Layout.tsx index ee656fdfc..69d7cb70b 100644 --- a/playgrounds/react/resources/js/Components/Layout.tsx +++ b/playgrounds/react/resources/js/Components/Layout.tsx @@ -1,6 +1,6 @@ import { Link, usePage } from '@inertiajs/react' -export default function Layout({ children }) { +export default function Layout({ children, padding = true }: { children: React.ReactNode; padding?: boolean }) { const { appName } = usePage<{ appName: string }>().props return ( @@ -31,11 +31,23 @@ export default function Layout({ children }) { Poll + + Chat + + + Photo Grid + + + Photo Row + + + Data Table + Logout -
{children}
+
{children}
) } diff --git a/playgrounds/react/resources/js/Components/Message.tsx b/playgrounds/react/resources/js/Components/Message.tsx new file mode 100644 index 000000000..5bf127c30 --- /dev/null +++ b/playgrounds/react/resources/js/Components/Message.tsx @@ -0,0 +1,24 @@ +import { marked } from 'marked' + +export interface Message { + id: number | string + type: 'prompt' | 'response' + content: string +} + +export default function MessageComponent({ message }: { message: Message }) { + const htmlContent = marked(message.content) + + return ( +
+
+
+
+
+ ) +} diff --git a/playgrounds/react/resources/js/Components/PaperAirplaneIcon.tsx b/playgrounds/react/resources/js/Components/PaperAirplaneIcon.tsx new file mode 100644 index 000000000..3d831babc --- /dev/null +++ b/playgrounds/react/resources/js/Components/PaperAirplaneIcon.tsx @@ -0,0 +1,18 @@ +export default function PaperAirplaneIcon({ className = 'size-6' }: { className?: string }) { + return ( + + + + ) +} diff --git a/playgrounds/react/resources/js/Components/Spinner.tsx b/playgrounds/react/resources/js/Components/Spinner.tsx new file mode 100644 index 000000000..7c5cde3c2 --- /dev/null +++ b/playgrounds/react/resources/js/Components/Spinner.tsx @@ -0,0 +1,17 @@ +export default function Spinner({ className = '' }: { className?: string }) { + return ( + + + + + ) +} diff --git a/playgrounds/react/resources/js/Components/StreamingIndicator.tsx b/playgrounds/react/resources/js/Components/StreamingIndicator.tsx new file mode 100644 index 000000000..fd5ffd410 --- /dev/null +++ b/playgrounds/react/resources/js/Components/StreamingIndicator.tsx @@ -0,0 +1,25 @@ +export default function StreamingIndicator({ className = '' }: { className?: string }) { + return ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) +} diff --git a/playgrounds/react/resources/js/Components/Textarea.tsx b/playgrounds/react/resources/js/Components/Textarea.tsx new file mode 100644 index 000000000..7098e2a07 --- /dev/null +++ b/playgrounds/react/resources/js/Components/Textarea.tsx @@ -0,0 +1,40 @@ +import { useEffect, useRef } from 'react' + +function autosize(element: HTMLTextAreaElement) { + element.style.height = 'auto' + element.style.height = element.scrollHeight + 'px' +} + +export default function Textarea({ + value, + onChange, + placeholder, + onKeyDown, + className = '', +}: { + value: string + onChange: (value: string) => void + placeholder?: string + onKeyDown?: (e: React.KeyboardEvent) => void + className?: string +}) { + const textareaRef = useRef(null) + + useEffect(() => { + if (textareaRef.current) { + autosize(textareaRef.current) + } + }, [value]) + + return ( + + diff --git a/playgrounds/vue3/resources/js/Pages/Chat.vue b/playgrounds/vue3/resources/js/Pages/Chat.vue new file mode 100644 index 000000000..1551e6f6e --- /dev/null +++ b/playgrounds/vue3/resources/js/Pages/Chat.vue @@ -0,0 +1,138 @@ + + + + +