mirror of
https://github.com/linsa-io/linsa.git
synced 2026-02-25 11:54:59 +01:00
* wip * wip page * chore: style * wip pages * wip pages * chore: toggle * chore: link * feat: topic search * chore: page section * refactor: apply tailwind class ordering * fix: handle loggedIn user for guest route * feat: folder & image schema * chore: move utils to shared * refactor: tailwind class ordering * feat: img ext for editor * refactor: remove qa * fix: tanstack start * fix: wrong import * chore: use toast * chore: schema
77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import * as React from "react"
|
|
import { clsx, type ClassValue } from "clsx"
|
|
import { twMerge } from "tailwind-merge"
|
|
|
|
export function cn(...inputs: ClassValue[]) {
|
|
return twMerge(clsx(inputs))
|
|
}
|
|
|
|
function escapeRegExp(string: string) {
|
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
}
|
|
|
|
export const searchSafeRegExp = (inputValue: string) => {
|
|
const escapedChars = inputValue.split("").map(escapeRegExp)
|
|
return new RegExp(escapedChars.join(".*"), "i")
|
|
}
|
|
|
|
export function shuffleArray<T>(array: T[]): T[] {
|
|
const shuffled = [...array]
|
|
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1))
|
|
;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]
|
|
}
|
|
return shuffled
|
|
}
|
|
|
|
const inputs = ["input", "select", "button", "textarea"] // detect if node is a text input element
|
|
|
|
export function isTextInput(element: Element): boolean {
|
|
return !!(
|
|
element &&
|
|
element.tagName &&
|
|
(inputs.indexOf(element.tagName.toLowerCase()) !== -1 ||
|
|
element.attributes.getNamedItem("role")?.value === "textbox" ||
|
|
element.attributes.getNamedItem("contenteditable")?.value === "true")
|
|
)
|
|
}
|
|
|
|
export type HTMLAttributes = React.HTMLAttributes<HTMLElement> & {
|
|
[key: string]: any
|
|
}
|
|
|
|
export type HTMLLikeElement = {
|
|
tag: keyof JSX.IntrinsicElements
|
|
attributes?: HTMLAttributes
|
|
children?: (HTMLLikeElement | string)[]
|
|
}
|
|
|
|
export const renderHTMLLikeElement = (
|
|
element: HTMLLikeElement | string,
|
|
): React.ReactNode => {
|
|
if (typeof element === "string") {
|
|
return element
|
|
}
|
|
|
|
const { tag, attributes = {}, children = [] } = element
|
|
|
|
return React.createElement(
|
|
tag,
|
|
attributes,
|
|
...children.map((child) => renderHTMLLikeElement(child)),
|
|
)
|
|
}
|
|
|
|
export function calendarFormatDate(date: Date): string {
|
|
return date.toLocaleDateString("en-US", {
|
|
year: "numeric",
|
|
month: "long",
|
|
day: "numeric",
|
|
})
|
|
}
|
|
|
|
export * from "./force-graph"
|
|
export * from "./env"
|
|
export * from "./slug"
|
|
export * from "./url"
|