Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {
root: true,
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:storybook/recommended'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest'
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
jsx: true
}
},
plugins: ['@typescript-eslint'],
settings: {
react: {
version: 'detect'
}
},
rules: {
'vue/no-deprecated-slot-attribute': 0
'react/react-in-jsx-scope': 'off', // Not needed in React 17+
'react/prop-types': 'off', // Using TypeScript
'react/display-name': 'off', // Allow anonymous components
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_'
}],
'@typescript-eslint/no-explicit-any': 'off', // Allow any type
'@typescript-eslint/no-namespace': 'off', // Allow namespaces for JSX augmentation
'no-undef': 'off', // TypeScript handles this
'no-console': 'warn', // Warn on console statements
'storybook/no-renderer-packages': 'off' // Allow direct Storybook imports
},
ignorePatterns: ['src/components/examples/']
ignorePatterns: ['src/components/examples/', 'dist/', 'node_modules/', 'src/stories/']
}
91 changes: 91 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
"@types/node": "^18.19.3",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@typescript-eslint/eslint-plugin": "^8.52.0",
"@typescript-eslint/parser": "^8.52.0",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.16",
"eslint": "^8.49.0",
Expand Down
12 changes: 4 additions & 8 deletions src/components/RLAutocomplete/RLAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const RLAutocomplete = forwardRef<RLAutocompleteRef, RLAutocompleteProps>
ref
) => {
const autocompleteRef = useRef<AutoComplete>(null)
const [inputModel, setInputModel] = useState<RLSelectOptionType | string | null>(null)
const [inputModel, setInputModel] = useState<RLSelectOptionType | string | undefined>(undefined)
const { errorMessage, isValid, validate } = useValidation({ rules, externalError: error })

// Sync inputModel with value
Expand All @@ -45,7 +45,7 @@ export const RLAutocomplete = forwardRef<RLAutocompleteRef, RLAutocompleteProps>
setInputModel({ value: '', text: '' })
} else {
const found = options.find((option) => value === option.value)
setInputModel(found ?? (!forceSelection ? { value, text: value } : null))
setInputModel(found ?? (!forceSelection ? { value, text: value } : undefined))
}
}, [value, options, forceSelection])

Expand All @@ -60,9 +60,7 @@ export const RLAutocomplete = forwardRef<RLAutocompleteRef, RLAutocompleteProps>
validate: () => validate(value)
}))

const handleChange = (evt: { value: RLSelectOptionType | string | null }) => {
console.log('handleChange evt.value:', evt.value)

const handleChange = (evt: { value: RLSelectOptionType | string | undefined }) => {
setInputModel(evt.value)

if (!forceSelection) {
Expand All @@ -79,8 +77,6 @@ export const RLAutocomplete = forwardRef<RLAutocompleteRef, RLAutocompleteProps>
}

const handleItemSelect = (evt: { value: RLSelectOptionType }) => {
console.log('handleItemSelect evt.value:', evt.value)

setInputModel(evt.value)
onChange?.(evt.value.value)
onItemSelect?.(evt)
Expand Down Expand Up @@ -143,7 +139,7 @@ export const RLAutocomplete = forwardRef<RLAutocompleteRef, RLAutocompleteProps>
completeMethod={handleComplete}
onClick={handleClick}
onFocus={handleFocus}
onDropdownClick={(evt) => onDropdownClick?.(evt.originalEvent)}
onDropdownClick={(evt) => onDropdownClick?.(evt.originalEvent.nativeEvent)}
onClear={onClear}
onShow={onShow}
onHide={onHide}
Expand Down
5 changes: 5 additions & 0 deletions src/components/RLCheckbox/RLCheckbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ declare global {
form?: string
required?: boolean
class?: string
onSlInput?: (event: Event) => void
onSlChange?: (event: Event) => void
onSlBlur?: (event: Event) => void
onSlFocus?: (event: Event) => void
onSlInvalid?: (event: Event) => void
}
}
}
Expand Down
44 changes: 28 additions & 16 deletions src/components/RLCrud/RLCrud.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, type ComponentType } from 'react'
import type { RLCrudProps, RLCrudRef, RLCrudActionType } from './types'
import type { RLCrudFormFieldType } from '../RLCrudForm'
import type { RLCrudFiltersRef } from '../RLCrudFilters'
import type { RLCrudInputValueType } from '../RLCrudInput'
import { RLCrudAction } from '../RLCrudAction'
import { RLPaginator } from '../RLPaginator'
import { RLDialog } from '../RLDialog'
Expand Down Expand Up @@ -43,7 +44,7 @@ export const RLCrud = forwardRef<RLCrudRef, RLCrudProps>(
highlightLastEdited = true,
highlightLastEditedClass = '!bg-row-selected',
persistActionDialog = true,
rowClass: externalRowClass,
rowClassName: externalRowClassName,
getItems,
addItem,
editItem,
Expand All @@ -55,7 +56,7 @@ export const RLCrud = forwardRef<RLCrudRef, RLCrudProps>(
},
ref
) => {
const [items, setItems] = useState<unknown[]>([])
const [items, setItems] = useState<Record<string, unknown>[]>([])
const [currentPage, setCurrentPage] = useState(0)
const [rowsPerPage, setRowsPerPage] = useState(
rowsPerPageOptions.includes(initialRowsPerPage)
Expand Down Expand Up @@ -91,7 +92,10 @@ export const RLCrud = forwardRef<RLCrudRef, RLCrudProps>(
sortable: header.sortable,
...(header.columnProps ? { columnProps: header.columnProps } : {}),
...(header.type
? { component: components?.[header.type], componentProps: header.componentProps }
? {
component: components?.[header.type] as ComponentType<{ data: unknown; field: string; [key: string]: unknown }>,
componentProps: header.componentProps as Record<string, unknown>
}
: {})
})),
[headers, translationFn, components]
Expand All @@ -115,10 +119,11 @@ export const RLCrud = forwardRef<RLCrudRef, RLCrudProps>(
return
}

setItems(response.result)
setItems(response.result as Record<string, unknown>[])
setCurrentPage(response.page.currentPage)
setTotalRows(response.page.totalRows)
} catch (e) {
// eslint-disable-next-line no-console
console.error(e)
onFetchError?.()
}
Expand Down Expand Up @@ -171,29 +176,36 @@ export const RLCrud = forwardRef<RLCrudRef, RLCrudProps>(
await fetchData()
}, [fetchData])

const rowClass = useCallback(
const rowClassName = useCallback(
(row: unknown) => {
const externalClasses = externalRowClass?.(row) || []
const externalResult = externalRowClassName?.(row)
const externalClasses = Array.isArray(externalResult)
? externalResult
: externalResult
? [externalResult]
: []

if ((row as Record<string, unknown>)[primary_key] === lastSelectedItem && highlightLastEdited) {
return [...externalClasses, highlightLastEditedClass]
return [...externalClasses, highlightLastEditedClass].join(' ')
}
return externalClasses
return externalClasses.join(' ')
},
[externalRowClass, primary_key, lastSelectedItem, highlightLastEdited, highlightLastEditedClass]
[externalRowClassName, primary_key, lastSelectedItem, highlightLastEdited, highlightLastEditedClass]
)

const onAdd = useCallback(
async (data: Record<string, unknown>) => {
const response = await addItem?.(data)
const responseRecord = response as Record<string, unknown>
const newId =
(response as Record<string, unknown>)?.result?.[primary_key] ??
(response as Record<string, unknown>)?.[primary_key]
((responseRecord?.result as Record<string, unknown>)?.[primary_key]) ??
responseRecord?.[primary_key]
setLastSelectedItem(newId)

if (goToInsertedRow) {
skipWatchersRef.current = true
setFiltersApplied({ [primary_key]: newId })
filtersRef.current?.setFilterModel({ [primary_key]: newId })
setFiltersApplied({ [primary_key]: newId as RLCrudInputValueType })
filtersRef.current?.setFilterModel({ [primary_key]: newId as RLCrudInputValueType })
filtersRef.current?.setOpen(true)
setCurrentPage(1)
await Promise.resolve() // Allow state to update
Expand Down Expand Up @@ -291,7 +303,7 @@ export const RLCrud = forwardRef<RLCrudRef, RLCrudProps>(
actions={[]}
paginator={false}
actionHeaderLabel={translationFn(actionHeaderI18nKey)}
rowClass={rowClass}
rowClassName={rowClassName}
actionsSlot={renderActions}
emptySlot={<div className="flex justify-center p-4">Empty</div>}
/>
Expand Down Expand Up @@ -348,7 +360,7 @@ export const RLCrud = forwardRef<RLCrudRef, RLCrudProps>(
requiredRuleMessage={translationFn(requiredI18nKey)}
cancelLabel={translationFn(cancelI18nKey)}
confirmLabel={translationFn(editI18nKey)}
value={selectedItem ?? undefined}
value={(selectedItem as { [key: string]: RLCrudInputValueType }) ?? undefined}
primaryKey={primary_key}
onClose={closeDialog}
onCancel={closeDialog}
Expand Down
2 changes: 1 addition & 1 deletion src/components/RLCrud/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export interface RLCrudProps {
highlightLastEdited?: boolean
highlightLastEditedClass?: string
persistActionDialog?: boolean
rowClass?: (data: unknown) => (string | object)[] | undefined
rowClassName?: (data: unknown) => string | string[] | undefined
getItems: (
page: number,
rowsPerPage: number,
Expand Down
2 changes: 2 additions & 0 deletions src/components/RLCrudFilters/RLCrudFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const RLCrudFilters = forwardRef<RLCrudFiltersRef, RLCrudFiltersProps>(
filters,
applyLabel = 'apply',
resetLabel = 'reset',
className,
onApply,
onHide,
onReset,
Expand Down Expand Up @@ -105,6 +106,7 @@ export const RLCrudFilters = forwardRef<RLCrudFiltersRef, RLCrudFiltersProps>(
<RLExpansionCard
ref={expansionCardRef}
title={title}
className={className}
onHide={handleHide}
onShow={handleShow}
onKeyUp={handleKeyUp}
Expand Down
1 change: 1 addition & 0 deletions src/components/RLCrudFilters/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface RLCrudFiltersProps {
filters: RLCrudFilterType[]
applyLabel?: string
resetLabel?: string
className?: string
onApply?: () => void
onHide?: () => void
onReset?: () => void
Expand Down
Loading