refactor: change 'onUpdate:open' to 'onOpenChange' a more friendlier name
This commit is contained in:
parent
18276331ed
commit
e8701721d2
|
|
@ -7,7 +7,7 @@ interface ToastVariantProps extends VariantProps<typeof toastVariants> {}
|
|||
export interface ToastProps extends ToastRootProps {
|
||||
class?: string
|
||||
variant?: ToastVariantProps['variant']
|
||||
'onUpdate:open'?: ((value: boolean) => void) | undefined
|
||||
'onOpenChange'?: ((value: boolean) => void) | undefined
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -18,14 +18,14 @@ import { toastVariants } from '.'
|
|||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ToastProps>()
|
||||
const emits = defineEmits<Omit<ToastRootEmits, 'update:open'>>()
|
||||
const emits = defineEmits<ToastRootEmits>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ToastRoot
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }" :class="cn(toastVariants({
|
||||
variant: props.variant,
|
||||
}), props.class)"
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }"
|
||||
:class="cn(toastVariants({ variant: props.variant }), props.class)"
|
||||
@update:open="onOpenChange"
|
||||
>
|
||||
<slot />
|
||||
</ToastRoot>
|
||||
|
|
|
|||
|
|
@ -147,8 +147,8 @@ function toast(props: Toast) {
|
|||
toast: {
|
||||
...props,
|
||||
id,
|
||||
'open': true,
|
||||
'onUpdate:open': (open: boolean) => {
|
||||
open: true,
|
||||
onOpenChange: (open: boolean) => {
|
||||
if (!open)
|
||||
dismiss()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ interface ToastVariantProps extends VariantProps<typeof toastVariants> {}
|
|||
export interface ToastProps extends ToastRootProps {
|
||||
class?: string
|
||||
variant?: ToastVariantProps['variant']
|
||||
'onUpdate:open'?: ((value: boolean) => void) | undefined
|
||||
'onOpenChange'?: ((value: boolean) => void) | undefined
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -18,14 +18,14 @@ import { toastVariants } from '.'
|
|||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ToastProps>()
|
||||
const emits = defineEmits<Omit<ToastRootEmits, 'update:open'>>()
|
||||
const emits = defineEmits<ToastRootEmits>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ToastRoot
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }" :class="cn(toastVariants({
|
||||
variant: props.variant,
|
||||
}), props.class)"
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }"
|
||||
:class="cn(toastVariants({ variant: props.variant }), props.class)"
|
||||
@update:open="onOpenChange"
|
||||
>
|
||||
<slot />
|
||||
</ToastRoot>
|
||||
|
|
|
|||
|
|
@ -147,8 +147,8 @@ function toast(props: Toast) {
|
|||
toast: {
|
||||
...props,
|
||||
id,
|
||||
'open': true,
|
||||
'onUpdate:open': (open: boolean) => {
|
||||
open: true,
|
||||
onOpenChange: (open: boolean) => {
|
||||
if (!open)
|
||||
dismiss()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"files": [
|
||||
{
|
||||
"name": "Toast.vue",
|
||||
"content": "<script lang=\"ts\">\nimport type { ToastRootEmits, ToastRootProps } from 'radix-vue'\nimport type { VariantProps } from 'class-variance-authority'\n\ninterface ToastVariantProps extends VariantProps<typeof toastVariants> {}\n\nexport interface ToastProps extends ToastRootProps {\n class?: string\n variant?: ToastVariantProps['variant']\n 'onUpdate:open'?: ((value: boolean) => void) | undefined\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { ToastRoot, useEmitAsProps } from 'radix-vue'\n\nimport { toastVariants } from '.'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<ToastProps>()\nconst emits = defineEmits<Omit<ToastRootEmits, 'update:open'>>()\n</script>\n\n<template>\n <ToastRoot\n v-bind=\"{ ...props, ...useEmitAsProps(emits) }\" :class=\"cn(toastVariants({\n variant: props.variant,\n }), props.class)\"\n >\n <slot />\n </ToastRoot>\n</template>\n"
|
||||
"content": "<script lang=\"ts\">\nimport type { ToastRootEmits, ToastRootProps } from 'radix-vue'\nimport type { VariantProps } from 'class-variance-authority'\n\ninterface ToastVariantProps extends VariantProps<typeof toastVariants> {}\n\nexport interface ToastProps extends ToastRootProps {\n class?: string\n variant?: ToastVariantProps['variant']\n 'onOpenChange'?: ((value: boolean) => void) | undefined\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { ToastRoot, useEmitAsProps } from 'radix-vue'\n\nimport { toastVariants } from '.'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<ToastProps>()\nconst emits = defineEmits<ToastRootEmits>()\n</script>\n\n<template>\n <ToastRoot\n v-bind=\"{ ...props, ...useEmitAsProps(emits) }\"\n :class=\"cn(toastVariants({ variant: props.variant }), props.class)\"\n @update:open=\"onOpenChange\"\n >\n <slot />\n </ToastRoot>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "ToastAction.vue",
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
},
|
||||
{
|
||||
"name": "use-toast.ts",
|
||||
"content": "import { computed, ref } from 'vue'\nimport type { Component, VNode } from 'vue'\nimport type { ToastProps } from './Toast.vue'\n\nconst TOAST_LIMIT = 1\nconst TOAST_REMOVE_DELAY = 1000000\n\nexport type StringOrVNode =\n | string\n | VNode\n | (() => VNode)\n\ntype ToasterToast = ToastProps & {\n id: string\n title?: string\n description?: StringOrVNode\n action?: Component\n}\n\nconst actionTypes = {\n ADD_TOAST: 'ADD_TOAST',\n UPDATE_TOAST: 'UPDATE_TOAST',\n DISMISS_TOAST: 'DISMISS_TOAST',\n REMOVE_TOAST: 'REMOVE_TOAST',\n} as const\n\nlet count = 0\n\nfunction genId() {\n count = (count + 1) % Number.MAX_VALUE\n return count.toString()\n}\n\ntype ActionType = typeof actionTypes\n\ntype Action =\n | {\n type: ActionType['ADD_TOAST']\n toast: ToasterToast\n }\n | {\n type: ActionType['UPDATE_TOAST']\n toast: Partial<ToasterToast>\n }\n | {\n type: ActionType['DISMISS_TOAST']\n toastId?: ToasterToast['id']\n }\n | {\n type: ActionType['REMOVE_TOAST']\n toastId?: ToasterToast['id']\n }\n\ninterface State {\n toasts: ToasterToast[]\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n\nfunction addToRemoveQueue(toastId: string) {\n if (toastTimeouts.has(toastId))\n return\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId)\n dispatch({\n type: actionTypes.REMOVE_TOAST,\n toastId,\n })\n }, TOAST_REMOVE_DELAY)\n\n toastTimeouts.set(toastId, timeout)\n}\n\nconst state = ref<State>({\n toasts: [],\n})\n\nfunction dispatch(action: Action) {\n switch (action.type) {\n case actionTypes.ADD_TOAST:\n state.value.toasts = [action.toast, ...state.value.toasts].slice(0, TOAST_LIMIT)\n break\n\n case actionTypes.UPDATE_TOAST:\n state.value.toasts = state.value.toasts.map(t =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n )\n break\n\n case actionTypes.DISMISS_TOAST: {\n const { toastId } = action\n\n if (toastId) {\n addToRemoveQueue(toastId)\n }\n else {\n state.value.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id)\n })\n }\n\n state.value.toasts = state.value.toasts.map(t =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n )\n break\n }\n\n case actionTypes.REMOVE_TOAST:\n if (action.toastId === undefined)\n state.value.toasts = []\n else\n state.value.toasts = state.value.toasts.filter(t => t.id !== action.toastId)\n\n break\n }\n}\n\nfunction useToast() {\n return {\n toasts: computed(() => state.value.toasts),\n toast,\n dismiss: (toastId?: string) => dispatch({ type: actionTypes.DISMISS_TOAST, toastId }),\n }\n}\n\ntype Toast = Omit<ToasterToast, 'id'>\n\nfunction toast(props: Toast) {\n const id = genId()\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: actionTypes.UPDATE_TOAST,\n toast: { ...props, id },\n })\n\n const dismiss = () => dispatch({ type: actionTypes.DISMISS_TOAST, toastId: id })\n\n dispatch({\n type: actionTypes.ADD_TOAST,\n toast: {\n ...props,\n id,\n 'open': true,\n 'onUpdate:open': (open: boolean) => {\n if (!open)\n dismiss()\n },\n },\n })\n\n return {\n id,\n dismiss,\n update,\n }\n}\n\nexport { toast, useToast }\n"
|
||||
"content": "import { computed, ref } from 'vue'\nimport type { Component, VNode } from 'vue'\nimport type { ToastProps } from './Toast.vue'\n\nconst TOAST_LIMIT = 1\nconst TOAST_REMOVE_DELAY = 1000000\n\nexport type StringOrVNode =\n | string\n | VNode\n | (() => VNode)\n\ntype ToasterToast = ToastProps & {\n id: string\n title?: string\n description?: StringOrVNode\n action?: Component\n}\n\nconst actionTypes = {\n ADD_TOAST: 'ADD_TOAST',\n UPDATE_TOAST: 'UPDATE_TOAST',\n DISMISS_TOAST: 'DISMISS_TOAST',\n REMOVE_TOAST: 'REMOVE_TOAST',\n} as const\n\nlet count = 0\n\nfunction genId() {\n count = (count + 1) % Number.MAX_VALUE\n return count.toString()\n}\n\ntype ActionType = typeof actionTypes\n\ntype Action =\n | {\n type: ActionType['ADD_TOAST']\n toast: ToasterToast\n }\n | {\n type: ActionType['UPDATE_TOAST']\n toast: Partial<ToasterToast>\n }\n | {\n type: ActionType['DISMISS_TOAST']\n toastId?: ToasterToast['id']\n }\n | {\n type: ActionType['REMOVE_TOAST']\n toastId?: ToasterToast['id']\n }\n\ninterface State {\n toasts: ToasterToast[]\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n\nfunction addToRemoveQueue(toastId: string) {\n if (toastTimeouts.has(toastId))\n return\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId)\n dispatch({\n type: actionTypes.REMOVE_TOAST,\n toastId,\n })\n }, TOAST_REMOVE_DELAY)\n\n toastTimeouts.set(toastId, timeout)\n}\n\nconst state = ref<State>({\n toasts: [],\n})\n\nfunction dispatch(action: Action) {\n switch (action.type) {\n case actionTypes.ADD_TOAST:\n state.value.toasts = [action.toast, ...state.value.toasts].slice(0, TOAST_LIMIT)\n break\n\n case actionTypes.UPDATE_TOAST:\n state.value.toasts = state.value.toasts.map(t =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n )\n break\n\n case actionTypes.DISMISS_TOAST: {\n const { toastId } = action\n\n if (toastId) {\n addToRemoveQueue(toastId)\n }\n else {\n state.value.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id)\n })\n }\n\n state.value.toasts = state.value.toasts.map(t =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n )\n break\n }\n\n case actionTypes.REMOVE_TOAST:\n if (action.toastId === undefined)\n state.value.toasts = []\n else\n state.value.toasts = state.value.toasts.filter(t => t.id !== action.toastId)\n\n break\n }\n}\n\nfunction useToast() {\n return {\n toasts: computed(() => state.value.toasts),\n toast,\n dismiss: (toastId?: string) => dispatch({ type: actionTypes.DISMISS_TOAST, toastId }),\n }\n}\n\ntype Toast = Omit<ToasterToast, 'id'>\n\nfunction toast(props: Toast) {\n const id = genId()\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: actionTypes.UPDATE_TOAST,\n toast: { ...props, id },\n })\n\n const dismiss = () => dispatch({ type: actionTypes.DISMISS_TOAST, toastId: id })\n\n dispatch({\n type: actionTypes.ADD_TOAST,\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open: boolean) => {\n if (!open)\n dismiss()\n },\n },\n })\n\n return {\n id,\n dismiss,\n update,\n }\n}\n\nexport { toast, useToast }\n"
|
||||
}
|
||||
],
|
||||
"type": "components:ui"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"files": [
|
||||
{
|
||||
"name": "Toast.vue",
|
||||
"content": "<script lang=\"ts\">\nimport type { ToastRootEmits, ToastRootProps } from 'radix-vue'\nimport type { VariantProps } from 'class-variance-authority'\n\ninterface ToastVariantProps extends VariantProps<typeof toastVariants> {}\n\nexport interface ToastProps extends ToastRootProps {\n class?: string\n variant?: ToastVariantProps['variant']\n 'onUpdate:open'?: ((value: boolean) => void) | undefined\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { ToastRoot, useEmitAsProps } from 'radix-vue'\n\nimport { toastVariants } from '.'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<ToastProps>()\nconst emits = defineEmits<Omit<ToastRootEmits, 'update:open'>>()\n</script>\n\n<template>\n <ToastRoot\n v-bind=\"{ ...props, ...useEmitAsProps(emits) }\" :class=\"cn(toastVariants({\n variant: props.variant,\n }), props.class)\"\n >\n <slot />\n </ToastRoot>\n</template>\n"
|
||||
"content": "<script lang=\"ts\">\nimport type { ToastRootEmits, ToastRootProps } from 'radix-vue'\nimport type { VariantProps } from 'class-variance-authority'\n\ninterface ToastVariantProps extends VariantProps<typeof toastVariants> {}\n\nexport interface ToastProps extends ToastRootProps {\n class?: string\n variant?: ToastVariantProps['variant']\n 'onOpenChange'?: ((value: boolean) => void) | undefined\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { ToastRoot, useEmitAsProps } from 'radix-vue'\n\nimport { toastVariants } from '.'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<ToastProps>()\nconst emits = defineEmits<ToastRootEmits>()\n</script>\n\n<template>\n <ToastRoot\n v-bind=\"{ ...props, ...useEmitAsProps(emits) }\"\n :class=\"cn(toastVariants({ variant: props.variant }), props.class)\"\n @update:open=\"onOpenChange\"\n >\n <slot />\n </ToastRoot>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "ToastAction.vue",
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
},
|
||||
{
|
||||
"name": "use-toast.ts",
|
||||
"content": "import { computed, ref } from 'vue'\nimport type { Component, VNode } from 'vue'\nimport type { ToastProps } from './Toast.vue'\n\nconst TOAST_LIMIT = 1\nconst TOAST_REMOVE_DELAY = 1000000\n\nexport type StringOrVNode =\n | string\n | VNode\n | (() => VNode)\n\ntype ToasterToast = ToastProps & {\n id: string\n title?: string\n description?: StringOrVNode\n action?: Component\n}\n\nconst actionTypes = {\n ADD_TOAST: 'ADD_TOAST',\n UPDATE_TOAST: 'UPDATE_TOAST',\n DISMISS_TOAST: 'DISMISS_TOAST',\n REMOVE_TOAST: 'REMOVE_TOAST',\n} as const\n\nlet count = 0\n\nfunction genId() {\n count = (count + 1) % Number.MAX_VALUE\n return count.toString()\n}\n\ntype ActionType = typeof actionTypes\n\ntype Action =\n | {\n type: ActionType['ADD_TOAST']\n toast: ToasterToast\n }\n | {\n type: ActionType['UPDATE_TOAST']\n toast: Partial<ToasterToast>\n }\n | {\n type: ActionType['DISMISS_TOAST']\n toastId?: ToasterToast['id']\n }\n | {\n type: ActionType['REMOVE_TOAST']\n toastId?: ToasterToast['id']\n }\n\ninterface State {\n toasts: ToasterToast[]\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n\nfunction addToRemoveQueue(toastId: string) {\n if (toastTimeouts.has(toastId))\n return\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId)\n dispatch({\n type: actionTypes.REMOVE_TOAST,\n toastId,\n })\n }, TOAST_REMOVE_DELAY)\n\n toastTimeouts.set(toastId, timeout)\n}\n\nconst state = ref<State>({\n toasts: [],\n})\n\nfunction dispatch(action: Action) {\n switch (action.type) {\n case actionTypes.ADD_TOAST:\n state.value.toasts = [action.toast, ...state.value.toasts].slice(0, TOAST_LIMIT)\n break\n\n case actionTypes.UPDATE_TOAST:\n state.value.toasts = state.value.toasts.map(t =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n )\n break\n\n case actionTypes.DISMISS_TOAST: {\n const { toastId } = action\n\n if (toastId) {\n addToRemoveQueue(toastId)\n }\n else {\n state.value.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id)\n })\n }\n\n state.value.toasts = state.value.toasts.map(t =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n )\n break\n }\n\n case actionTypes.REMOVE_TOAST:\n if (action.toastId === undefined)\n state.value.toasts = []\n else\n state.value.toasts = state.value.toasts.filter(t => t.id !== action.toastId)\n\n break\n }\n}\n\nfunction useToast() {\n return {\n toasts: computed(() => state.value.toasts),\n toast,\n dismiss: (toastId?: string) => dispatch({ type: actionTypes.DISMISS_TOAST, toastId }),\n }\n}\n\ntype Toast = Omit<ToasterToast, 'id'>\n\nfunction toast(props: Toast) {\n const id = genId()\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: actionTypes.UPDATE_TOAST,\n toast: { ...props, id },\n })\n\n const dismiss = () => dispatch({ type: actionTypes.DISMISS_TOAST, toastId: id })\n\n dispatch({\n type: actionTypes.ADD_TOAST,\n toast: {\n ...props,\n id,\n 'open': true,\n 'onUpdate:open': (open: boolean) => {\n if (!open)\n dismiss()\n },\n },\n })\n\n return {\n id,\n dismiss,\n update,\n }\n}\n\nexport { toast, useToast }\n"
|
||||
"content": "import { computed, ref } from 'vue'\nimport type { Component, VNode } from 'vue'\nimport type { ToastProps } from './Toast.vue'\n\nconst TOAST_LIMIT = 1\nconst TOAST_REMOVE_DELAY = 1000000\n\nexport type StringOrVNode =\n | string\n | VNode\n | (() => VNode)\n\ntype ToasterToast = ToastProps & {\n id: string\n title?: string\n description?: StringOrVNode\n action?: Component\n}\n\nconst actionTypes = {\n ADD_TOAST: 'ADD_TOAST',\n UPDATE_TOAST: 'UPDATE_TOAST',\n DISMISS_TOAST: 'DISMISS_TOAST',\n REMOVE_TOAST: 'REMOVE_TOAST',\n} as const\n\nlet count = 0\n\nfunction genId() {\n count = (count + 1) % Number.MAX_VALUE\n return count.toString()\n}\n\ntype ActionType = typeof actionTypes\n\ntype Action =\n | {\n type: ActionType['ADD_TOAST']\n toast: ToasterToast\n }\n | {\n type: ActionType['UPDATE_TOAST']\n toast: Partial<ToasterToast>\n }\n | {\n type: ActionType['DISMISS_TOAST']\n toastId?: ToasterToast['id']\n }\n | {\n type: ActionType['REMOVE_TOAST']\n toastId?: ToasterToast['id']\n }\n\ninterface State {\n toasts: ToasterToast[]\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n\nfunction addToRemoveQueue(toastId: string) {\n if (toastTimeouts.has(toastId))\n return\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId)\n dispatch({\n type: actionTypes.REMOVE_TOAST,\n toastId,\n })\n }, TOAST_REMOVE_DELAY)\n\n toastTimeouts.set(toastId, timeout)\n}\n\nconst state = ref<State>({\n toasts: [],\n})\n\nfunction dispatch(action: Action) {\n switch (action.type) {\n case actionTypes.ADD_TOAST:\n state.value.toasts = [action.toast, ...state.value.toasts].slice(0, TOAST_LIMIT)\n break\n\n case actionTypes.UPDATE_TOAST:\n state.value.toasts = state.value.toasts.map(t =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n )\n break\n\n case actionTypes.DISMISS_TOAST: {\n const { toastId } = action\n\n if (toastId) {\n addToRemoveQueue(toastId)\n }\n else {\n state.value.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id)\n })\n }\n\n state.value.toasts = state.value.toasts.map(t =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n )\n break\n }\n\n case actionTypes.REMOVE_TOAST:\n if (action.toastId === undefined)\n state.value.toasts = []\n else\n state.value.toasts = state.value.toasts.filter(t => t.id !== action.toastId)\n\n break\n }\n}\n\nfunction useToast() {\n return {\n toasts: computed(() => state.value.toasts),\n toast,\n dismiss: (toastId?: string) => dispatch({ type: actionTypes.DISMISS_TOAST, toastId }),\n }\n}\n\ntype Toast = Omit<ToasterToast, 'id'>\n\nfunction toast(props: Toast) {\n const id = genId()\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: actionTypes.UPDATE_TOAST,\n toast: { ...props, id },\n })\n\n const dismiss = () => dispatch({ type: actionTypes.DISMISS_TOAST, toastId: id })\n\n dispatch({\n type: actionTypes.ADD_TOAST,\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open: boolean) => {\n if (!open)\n dismiss()\n },\n },\n })\n\n return {\n id,\n dismiss,\n update,\n }\n}\n\nexport { toast, useToast }\n"
|
||||
}
|
||||
],
|
||||
"type": "components:ui"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user