From 4d74724dcba761516c4396cf7efeec5335ce05e4 Mon Sep 17 00:00:00 2001 From: guizoxxv Date: Sun, 11 Aug 2024 02:10:48 -0400 Subject: [PATCH 1/5] Allow custom component on Link "as" prop in React and Vue3 --- packages/react/src/Link.ts | 10 +++++----- packages/vue3/src/link.ts | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/react/src/Link.ts b/packages/react/src/Link.ts index 5d29b01f8..be69d0f4b 100755 --- a/packages/react/src/Link.ts +++ b/packages/react/src/Link.ts @@ -7,12 +7,12 @@ import { router, shouldIntercept, } from '@inertiajs/core' -import { createElement, forwardRef, useCallback } from 'react' +import React, { ElementType, createElement, forwardRef, useCallback } from 'react' const noop = () => undefined interface BaseInertiaLinkProps { - as?: string + as?: string | ElementType data?: Record href: string method?: Method @@ -115,13 +115,13 @@ const Link = forwardRef( ], ) - as = as.toLowerCase() + const isAnchor = as === 'a' || as === 'A' method = method.toLowerCase() as Method const [_href, _data] = mergeDataIntoQueryString(method, href || '', data, queryStringArrayFormat) href = _href data = _data - if (as === 'a' && method !== 'get') { + if (isAnchor && method !== 'get') { console.warn( `Creating POST/PUT/PATCH/DELETE links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n...`, ) @@ -131,7 +131,7 @@ const Link = forwardRef( as, { ...props, - ...(as === 'a' ? { href } : {}), + ...(isAnchor ? { href } : {}), ref, onClick: visit, }, diff --git a/packages/vue3/src/link.ts b/packages/vue3/src/link.ts index 1c783aaeb..3488855cd 100755 --- a/packages/vue3/src/link.ts +++ b/packages/vue3/src/link.ts @@ -1,8 +1,8 @@ import { mergeDataIntoQueryString, Method, PageProps, Progress, router, shouldIntercept } from '@inertiajs/core' -import { defineComponent, DefineComponent, h, PropType } from 'vue' +import { Component, defineComponent, DefineComponent, h, PropType } from 'vue' export interface InertiaLinkProps { - as?: string + as?: string | Component data?: object href: string method?: Method @@ -29,7 +29,7 @@ const Link: InertiaLink = defineComponent({ name: 'Link', props: { as: { - type: String, + type: [String, Object] as PropType, default: 'a', }, data: { @@ -75,11 +75,11 @@ const Link: InertiaLink = defineComponent({ }, setup(props, { slots, attrs }) { return () => { - const as = props.as.toLowerCase() + const isAnchor = props.as === 'a' || props.as === 'A' const method = props.method.toLowerCase() as Method const [href, data] = mergeDataIntoQueryString(method, props.href || '', props.data, props.queryStringArrayFormat) - if (as === 'a' && method !== 'get') { + if (isAnchor && method !== 'get') { console.warn( `Creating POST/PUT/PATCH/DELETE links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n...`, ) @@ -89,7 +89,7 @@ const Link: InertiaLink = defineComponent({ props.as, { ...attrs, - ...(as === 'a' ? { href } : {}), + ...(isAnchor ? { href } : {}), onClick: (event) => { if (shouldIntercept(event)) { event.preventDefault() From 3295dc07156003b56a51a9bd2664cf2a3fd8f85d Mon Sep 17 00:00:00 2001 From: guizoxxv Date: Sun, 11 Aug 2024 02:52:03 -0400 Subject: [PATCH 2/5] Allow custom component on Link "as" prop in Vue2 --- packages/vue2/src/link.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/vue2/src/link.ts b/packages/vue2/src/link.ts index 52f727072..76527fb55 100755 --- a/packages/vue2/src/link.ts +++ b/packages/vue2/src/link.ts @@ -7,10 +7,10 @@ import { router, shouldIntercept, } from '@inertiajs/core' -import { FunctionalComponentOptions, PropType } from 'vue' +import { Component, FunctionalComponentOptions, PropType } from 'vue' export interface InertiaLinkProps { - as?: string + as?: string | Component data?: Record href: string method?: Method @@ -37,7 +37,7 @@ const Link: InertiaLink = { functional: true, props: { as: { - type: String, + type: [String, Object] as PropType, default: 'a', }, data: { @@ -93,7 +93,7 @@ const Link: InertiaLink = { ...(data.on || {}), } - const as = props.as.toLowerCase() + const isAnchor = props.as === 'a' || props.as === 'A' const method = props.method.toLowerCase() as Method const [href, propsData] = mergeDataIntoQueryString( method, @@ -102,7 +102,7 @@ const Link: InertiaLink = { props.queryStringArrayFormat, ) - if (as === 'a' && method !== 'get') { + if (isAnchor && method !== 'get') { console.warn( `Creating POST/PUT/PATCH/DELETE links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n...`, ) @@ -114,7 +114,7 @@ const Link: InertiaLink = { ...data, attrs: { ...data.attrs, - ...(as === 'a' ? { href } : {}), + ...(isAnchor ? { href } : {}), }, on: { ...data.on, @@ -159,4 +159,4 @@ const Link: InertiaLink = { ) }, } -export default Link +export default Link \ No newline at end of file From 4e55bb2fb28ce68ac2cbfbdd9e213b0b5b39243d Mon Sep 17 00:00:00 2001 From: guizoxxv Date: Tue, 17 Sep 2024 23:49:03 -0400 Subject: [PATCH 3/5] Keep href in anchor on Vue3 --- packages/vue3/src/link.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/vue3/src/link.ts b/packages/vue3/src/link.ts index 3488855cd..531ce4c7b 100755 --- a/packages/vue3/src/link.ts +++ b/packages/vue3/src/link.ts @@ -1,5 +1,5 @@ import { mergeDataIntoQueryString, Method, PageProps, Progress, router, shouldIntercept } from '@inertiajs/core' -import { Component, defineComponent, DefineComponent, h, PropType } from 'vue' +import { Component, defineComponent, DefineComponent, h, onMounted, PropType, ref } from 'vue' export interface InertiaLinkProps { as?: string | Component @@ -74,8 +74,23 @@ const Link: InertiaLink = defineComponent({ }, }, setup(props, { slots, attrs }) { + const internalRef = ref(null) + + onMounted(() => { + if (!internalRef.value) { + return + } + + const element = internalRef.value.$el + + if (element.tagName !== 'A') { + element.removeAttribute('href') + } + }) + return () => { const isAnchor = props.as === 'a' || props.as === 'A' + const isCustomComponent = typeof props.as !== 'string' const method = props.method.toLowerCase() as Method const [href, data] = mergeDataIntoQueryString(method, props.href || '', props.data, props.queryStringArrayFormat) @@ -89,7 +104,8 @@ const Link: InertiaLink = defineComponent({ props.as, { ...attrs, - ...(isAnchor ? { href } : {}), + ...(isAnchor || isCustomComponent ? { href } : {}), + ...(isCustomComponent ? { ref: internalRef } : {}), onClick: (event) => { if (shouldIntercept(event)) { event.preventDefault() From bfc25e4f293378601c95a134d4e30772021049ed Mon Sep 17 00:00:00 2001 From: guizoxxv Date: Wed, 18 Sep 2024 00:07:55 -0400 Subject: [PATCH 4/5] Keep href in anchor on React --- packages/react/src/Link.ts | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/react/src/Link.ts b/packages/react/src/Link.ts index be69d0f4b..9277cdd50 100755 --- a/packages/react/src/Link.ts +++ b/packages/react/src/Link.ts @@ -7,7 +7,7 @@ import { router, shouldIntercept, } from '@inertiajs/core' -import React, { ElementType, createElement, forwardRef, useCallback } from 'react' +import React, { ElementType, createElement, forwardRef, useCallback, useEffect, useRef } from 'react' const noop = () => undefined @@ -115,7 +115,32 @@ const Link = forwardRef( ], ) + const internalRef = useRef(null) + + const combinedRef = (element: HTMLElement | null) => { + internalRef.current = element + + if (!ref) { + return + } + + if (typeof ref === 'function') { + ref(element) + } else { + ref.current = element + } + } + + useEffect(() => { + const element = internalRef.current + + if (element && element.tagName !== 'A') { + element.removeAttribute('href') + } + }, []) + const isAnchor = as === 'a' || as === 'A' + const isCustomComponent = typeof as !== 'string' method = method.toLowerCase() as Method const [_href, _data] = mergeDataIntoQueryString(method, href || '', data, queryStringArrayFormat) href = _href @@ -131,8 +156,8 @@ const Link = forwardRef( as, { ...props, - ...(isAnchor ? { href } : {}), - ref, + ...(isAnchor || isCustomComponent ? { href } : {}), + ref: combinedRef, onClick: visit, }, children, From 78429ec09dbc2c453110ea6e79276973dd875a12 Mon Sep 17 00:00:00 2001 From: guizoxxv Date: Wed, 18 Sep 2024 00:09:15 -0400 Subject: [PATCH 5/5] Revert "Allow custom component on Link "as" prop in Vue2" This reverts commit 3295dc07156003b56a51a9bd2664cf2a3fd8f85d since Inertia 2 won't have support for Vue 2. --- packages/vue2/src/link.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/vue2/src/link.ts b/packages/vue2/src/link.ts index 76527fb55..52f727072 100755 --- a/packages/vue2/src/link.ts +++ b/packages/vue2/src/link.ts @@ -7,10 +7,10 @@ import { router, shouldIntercept, } from '@inertiajs/core' -import { Component, FunctionalComponentOptions, PropType } from 'vue' +import { FunctionalComponentOptions, PropType } from 'vue' export interface InertiaLinkProps { - as?: string | Component + as?: string data?: Record href: string method?: Method @@ -37,7 +37,7 @@ const Link: InertiaLink = { functional: true, props: { as: { - type: [String, Object] as PropType, + type: String, default: 'a', }, data: { @@ -93,7 +93,7 @@ const Link: InertiaLink = { ...(data.on || {}), } - const isAnchor = props.as === 'a' || props.as === 'A' + const as = props.as.toLowerCase() const method = props.method.toLowerCase() as Method const [href, propsData] = mergeDataIntoQueryString( method, @@ -102,7 +102,7 @@ const Link: InertiaLink = { props.queryStringArrayFormat, ) - if (isAnchor && method !== 'get') { + if (as === 'a' && method !== 'get') { console.warn( `Creating POST/PUT/PATCH/DELETE links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n...`, ) @@ -114,7 +114,7 @@ const Link: InertiaLink = { ...data, attrs: { ...data.attrs, - ...(isAnchor ? { href } : {}), + ...(as === 'a' ? { href } : {}), }, on: { ...data.on, @@ -159,4 +159,4 @@ const Link: InertiaLink = { ) }, } -export default Link \ No newline at end of file +export default Link