Skip to content

Commit

Permalink
fix(*): remove vue-bind-once [KHCP-14269] (#2535)
Browse files Browse the repository at this point in the history
* fix(composables): use useid instead of nanoid [KHCP-14269]

* fix(*): remove usage of v-bind-once [KHCP-14269]

* chore(deps): remove vue-bind-once and nanoid [KHCP-14269]

* fix(*): clean up vue-bind-once references [KHCP-14269]

* fix(ktableview): replace useuniqueid with useid [KHCP-14269]

* fix(*): replace useuniqueid with useid [KHCP-14269]

* docs: remove useuniqueid reference [KHCP-14269]

* fix(ktableview): use nanoid for dynamic row key [KHCP-14269]

* fix(kselect, kmultiselect): created item value [KHCP-14269]

* fix(ktoaster): use nanoid for toast key [KHCP-14269]

* docs: nanoid usage [KHCP-14269]

* fix: add getuniqueidstring utility function [KHCP-14269]

* docs: apply pr feedback

Co-authored-by: Adam DeHaven <[email protected]>

* fix: address pr feedback

* fix: address pr feedback

* fix: minor fix

* fix: minor fix

---------

Co-authored-by: Adam DeHaven <[email protected]>
  • Loading branch information
portikM and adamdehaven authored Dec 12, 2024
1 parent 0120fc1 commit 6d31fae
Show file tree
Hide file tree
Showing 27 changed files with 121 additions and 185 deletions.
3 changes: 1 addition & 2 deletions cypress/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { mount } from 'cypress/vue'
import { createMemoryHistory, createRouter } from 'vue-router/dist/vue-router.prod.cjs'
import type { RouteRecordRaw } from 'vue-router'
import type { App, ComputedOptions } from 'vue'
import { BindOncePlugin } from 'vue-bind-once'
import Chainable = Cypress.Chainable
import 'cypress-fail-fast'
// Import Kongponent styles
Expand Down Expand Up @@ -38,7 +37,7 @@ Cypress.Commands.add('mount', (component: ComputedOptions, options = {}): Chaina
app.use(options.router)
}
},
}, BindOncePlugin)
})

return mount(component, options)
})
Expand Down
28 changes: 20 additions & 8 deletions docs/guide/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,23 +218,35 @@ It's essential to choose context-aware and descriptive names. This practice ensu

#### Attributes

Sometimes you will need to generate a random string to be used as value for various attributes (e.g. accessibility-related attributes like `id`, `for`, `aria-labelledby`, etc.).
Sometimes you will need to generate a random string to be used as value for various attributes (e.g. accessibility-related attributes like `id`, `for`, `aria-labelledby`, etc.).

To generate a unique id so that it is safe for SSR, you **must** use the `useUniqueId` composable in your component:
To generate a unique id so that it is safe for SSR, you **must** use the [`useId` composable](https://vuejs.org/api/composition-api-helpers#useid) in your component:

```html
<script setup lang="ts">
import useUniqueId from '@/composables/useUniqueId'
import { useId } from 'vue'
const id = useUniqueId()
const id = useId()
</script>
```

Then you must use the [`v-bind-once` directive](https://github.com/danielroe/vue-bind-once) to bind the unique id to element attributes (this prevents hydration issues in SSR apps):
Note that `useId` can only be used at the root of the setup function. If you need a random ID in a template or in any of your component functions (e.g. to give each `key` in a `v-for` loop a unique value), you should use the `getUniqueStringId` helper function:

```html
<label v-bind-once="{ for: id }">Label</label>
<input v-bind-once="{ id: id }" />
```vue
<template>
<div v-for="item in items" :key="item.id">
<!-- some content -->
</div>
</template>
<script setup lang="ts">
import { getUniqueStringId } from '@/utilities'
const items = myArray.map(item => ({
...item,
id: getUniqueStringId(), // add a unique id
}))
</script>
```

## Testing your component
Expand Down
8 changes: 0 additions & 8 deletions docs/guide/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ Import and registration can be done individually in the app entry file (e.g. `ma
```ts
// main.ts (or Vue entry file)

// Kongponents rely on vue-bind-once directive to work properly
// The Kongponents bundle includes the vue-bind-once package so you won't need to install it separately, but it does need to be registered
import { BindOncePlugin } from 'vue-bind-once'
import { createApp } from 'vue'
import { KButton } from '@kong/kongponents'
import '@kong/kongponents/dist/style.css'
Expand All @@ -79,9 +76,6 @@ import '@kong/kongponents/dist/style.css'

const app = createApp(App)

// Register the vue-bind-once directive as a Vue Plugin
app.use(BindOncePlugin)

// Register an individual Kongponent
app.component('KButton', KButton)

Expand Down Expand Up @@ -115,8 +109,6 @@ this path instead: import '~@kong/kongponents/dist/style.css' */
</style>
```

When using Kongponents individually like this you will still need to register [`vue-bind-once` plugin](https://github.com/danielroe/vue-bind-once). Please refer to [global registration](#global-registration) section for example.

## TypeScript interfaces

:::tip NOTE
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,15 @@
"date-fns-tz": "^2.0.1",
"focus-trap": "^7.6.0",
"focus-trap-vue": "^4.0.3",
"nanoid": "^5.0.7",
"nanoid": "^5.0.9",
"sortablejs": "^1.15.3",
"swrv": "^1.0.4",
"v-calendar": "^3.1.2",
"vue-bind-once": "^0.2.1",
"vue-draggable-next": "^2.2.1"
},
"peerDependencies": {
"axios": "^1.7.7",
"vue": ">= 3.3.4 < 4",
"vue": ">= 3.5.0 < 4",
"vue-router": "^4.4.5"
},
"devDependencies": {
Expand Down
33 changes: 7 additions & 26 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions src/components/KCatalog/KCatalog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@

<div
v-else
v-bind-once="{ 'data-tableid': catalogId }"
class="catalog-page"
:class="`card-${cardSize}`"
:data-tableid="catalogId"
>
<slot
:data="data"
Expand Down Expand Up @@ -154,7 +154,7 @@

<script setup lang="ts">
import type { PropType } from 'vue'
import { ref, computed, onMounted, watch, useSlots } from 'vue'
import { ref, computed, onMounted, watch, useSlots, useId } from 'vue'
import type {
CatalogItem,
CatalogPreferences,
Expand All @@ -177,7 +177,6 @@ import KEmptyState from '@/components/KEmptyState/KEmptyState.vue'
import KButton from '@/components/KButton/KButton.vue'
import KPagination from '@/components/KPagination/KPagination.vue'
import KCatalogItem from './KCatalogItem.vue'
import useUniqueId from '@/composables/useUniqueId'
const { useRequest, useDebounce, useSwrvState } = useUtilities()
const DEFAULT_PAGE_SIZE = 15
Expand Down Expand Up @@ -372,7 +371,7 @@ const emit = defineEmits<{
const slots = useSlots()
const catalogId = useUniqueId()
const catalogId = useId()
const getInitialPageSize = (): number => {
const initialPageSize = props.paginationPageSizes?.[0]
Expand Down
10 changes: 5 additions & 5 deletions src/components/KCheckbox/KCheckbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
:class="{ 'has-label': hasLabel }"
>
<input
v-bind-once="{ id: inputId }"
:id="inputId"
v-bind="modifiedAttrs"
:aria-checked="modelValue"
class="checkbox-input"
Expand Down Expand Up @@ -36,9 +36,9 @@
<div class="checkbox-label-wrapper">
<KLabel
v-if="hasLabel"
v-bind-once="{ for: inputId }"
v-bind="labelAttributes"
class="checkbox-label"
:for="inputId"
>
<slot>{{ label }}</slot>

Expand All @@ -63,12 +63,11 @@

<script lang="ts" setup>
import type { PropType } from 'vue'
import { computed, useAttrs, useSlots } from 'vue'
import { computed, useAttrs, useId, useSlots } from 'vue'
import type { LabelAttributes } from '@/types'
import KLabel from '@/components/KLabel/KLabel.vue'
import { CheckSmallIcon, IndeterminateSmallIcon } from '@kong/icons'
import { KUI_ICON_SIZE_40 } from '@kong/design-tokens'
import useUniqueId from '@/composables/useUniqueId'
const props = defineProps({
modelValue: {
Expand Down Expand Up @@ -110,7 +109,8 @@ const emit = defineEmits<{
const slots = useSlots()
const attrs = useAttrs()
const inputId = attrs.id ? String(attrs.id) : useUniqueId()
const defaultId = useId()
const inputId = computed((): string => attrs.id ? String(attrs.id) : defaultId)
const hasLabel = computed((): boolean => !!(props.label || slots.default))
const isDisabled = computed((): boolean => attrs?.disabled !== undefined && String(attrs?.disabled) !== 'false')
Expand Down
9 changes: 4 additions & 5 deletions src/components/KCollapse/KCollapse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
:toggle="toggleDisplay"
>
<button
v-bind-once="{ 'aria-controls': contentId }"
:aria-controls="contentId"
:aria-expanded="!collapsedState"
:aria-label="triggerLabel ? undefined : 'Toggle content'"
class="collapse-trigger-content"
Expand Down Expand Up @@ -59,7 +59,7 @@
<Transition name="kongponents-fade-transition">
<div
v-show="!collapsedState"
v-bind-once="{ id: contentId }"
:id="contentId"
class="collapse-hidden-content"
data-testid="collapse-hidden-content"
>
Expand All @@ -71,12 +71,11 @@

<script lang="ts" setup>
import type { PropType } from 'vue'
import { computed, ref, useSlots, watch } from 'vue'
import { computed, ref, useId, useSlots, watch } from 'vue'
import type { TriggerAlignment, HeaderTag } from '@/types'
import { TriggerAlignmentArray, HeaderTags } from '@/types'
import { ChevronRightIcon } from '@kong/icons'
import { KUI_ICON_SIZE_40 } from '@kong/design-tokens'
import useUniqueId from '@/composables/useUniqueId'
const props = defineProps({
// Is the KCollapse collapsed? Defaults to true-->
Expand Down Expand Up @@ -113,7 +112,7 @@ const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void;
}>()
const contentId = useUniqueId()
const contentId = useId()
const isCollapsed = ref<boolean>(true)
const modelValueChanged = ref<boolean>(false)
Expand Down
7 changes: 3 additions & 4 deletions src/components/KCopy/KCopy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
>
<KClipboardProvider v-slot="{ copyToClipboard }">
<button
v-bind-once="{ id: copyButtonElementId }"
:id="copyButtonElementId"
:aria-label="tooltipText"
class="copy-to-clipboard-button"
data-testid="copy-to-clipboard"
Expand All @@ -56,13 +56,12 @@

<script setup lang="ts">
import type { PropType } from 'vue'
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
import { computed, ref, watch, onMounted, onUnmounted, useId } from 'vue'
import { ResizeObserverHelper } from '@/utilities/resizeObserverHelper'
import { CopyIcon } from '@kong/icons'
import KClipboardProvider from '@/components/KClipboardProvider'
import KTooltip from '@/components/KTooltip/KTooltip.vue'
import { KUI_ICON_SIZE_30 } from '@kong/design-tokens'
import useUniqueId from '@/composables/useUniqueId'
const props = defineProps({
/**
Expand Down Expand Up @@ -140,7 +139,7 @@ const props = defineProps({
},
})
const copyButtonElementId = useUniqueId()
const copyButtonElementId = useId()
const tooltipText = ref<string>('')
const nonSuccessText = computed((): string => {
Expand Down
Loading

0 comments on commit 6d31fae

Please sign in to comment.