@plumile/backoffice-react 0.1.196 → 0.1.198
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/lib/esm/components/backoffice/filters/BackofficeFilterAction.js +23 -20
- package/lib/esm/components/backoffice/filters/BackofficeFilterAction.js.map +1 -1
- package/lib/esm/components/backoffice/layout/breadcrumb/buildBreadcrumbs.js.map +1 -1
- package/lib/esm/components/backoffice/links/BackofficeInlineLink.js +19 -9
- package/lib/esm/components/backoffice/links/BackofficeInlineLink.js.map +1 -1
- package/lib/esm/components/backoffice/links/BackofficeLink.js +12 -8
- package/lib/esm/components/backoffice/links/BackofficeLink.js.map +1 -1
- package/lib/esm/components/backoffice/links/resolveBackofficeLink.js +64 -45
- package/lib/esm/components/backoffice/links/resolveBackofficeLink.js.map +1 -1
- package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js +30 -61
- package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js +1 -4
- package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js.map +1 -1
- package/lib/esm/components/backoffice/scaffolds/BackofficeListFilterContext.js +18 -27
- package/lib/esm/components/backoffice/scaffolds/BackofficeListFilterContext.js.map +1 -1
- package/lib/esm/hooks/useBackofficeListUrlState.js +27 -24
- package/lib/esm/hooks/useBackofficeListUrlState.js.map +1 -1
- package/lib/esm/pages/BackofficeDashboardWidgetContent.js +194 -227
- package/lib/esm/pages/BackofficeDashboardWidgetContent.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js +107 -120
- package/lib/esm/pages/BackofficeEntityDetailLayoutPage.js.map +1 -1
- package/lib/esm/pages/BackofficeEntityListDataPage.js +2 -8
- package/lib/esm/pages/BackofficeEntityListDataPage.js.map +1 -1
- package/lib/esm/pages/resolveDashboardTargetDestination.js +17 -0
- package/lib/esm/pages/resolveDashboardTargetDestination.js.map +1 -0
- package/lib/esm/router/createBackofficeRoutes.js +88 -99
- package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
- package/lib/types/components/backoffice/filters/BackofficeFilterAction.d.ts.map +1 -1
- package/lib/types/components/backoffice/layout/breadcrumb/buildBreadcrumbs.d.ts +3 -3
- package/lib/types/components/backoffice/layout/breadcrumb/buildBreadcrumbs.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/BackofficeInlineLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/BackofficeLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/resolveBackofficeLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/links/types.d.ts +19 -15
- package/lib/types/components/backoffice/links/types.d.ts.map +1 -1
- package/lib/types/components/backoffice/refs/BackofficeRelatedCountLink.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts.map +1 -1
- package/lib/types/components/backoffice/scaffolds/BackofficeListFilterContext.d.ts +0 -4
- package/lib/types/components/backoffice/scaffolds/BackofficeListFilterContext.d.ts.map +1 -1
- package/lib/types/hooks/useBackofficeListUrlState.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/pages/BackofficeDashboardWidgetContent.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityDetailLayoutPage.d.ts.map +1 -1
- package/lib/types/pages/BackofficeEntityListDataPage.d.ts.map +1 -1
- package/lib/types/pages/resolveDashboardTargetDestination.d.ts +5 -0
- package/lib/types/pages/resolveDashboardTargetDestination.d.ts.map +1 -0
- package/lib/types/router/createBackofficeRoutes.d.ts +0 -2
- package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeEntityListScaffold.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n type JSX,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { BackofficeEmptyState } from '@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js';\nimport { BackofficeFilterDrawer } from '@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js';\nimport { BackofficeFilterField } from '@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js';\nimport { Spinner } from '@plumile/ui/backoffice/atoms/spinner/Spinner.js';\nimport { Tag } from '@plumile/ui/backoffice/atoms/tag/Tag.js';\nimport { BackofficeListFooter } from '@plumile/ui/backoffice/molecules/backoffice_list_footer/BackofficeListFooter.js';\nimport { BackofficePageHeader } from '@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js';\nimport { BackofficeToolbar } from '@plumile/ui/backoffice/molecules/backoffice_toolbar/BackofficeToolbar.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport {\n FilterChipRow,\n type FilterChip,\n} from '@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\nimport { ListPageTemplate } from '@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { ResponsiveRecordList } from '@plumile/ui/components/data-table/ResponsiveRecordList.js';\nimport { VirtualizedConnectionTable } from '@plumile/ui/components/data-table/VirtualizedConnectionTable.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport { denseTableClass } from '@plumile/ui/shared/backofficeTableDensity.css.js';\n\nimport {\n readWhereValue,\n setWhereValue,\n} from '@plumile/backoffice-core/filters/where.js';\nimport { resolveBackofficeListRuntimeConfig } from '@plumile/backoffice-core/config/listRuntime.js';\nimport type {\n BackofficeFilterSpec,\n BackofficeListState,\n BackofficePickerScope,\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\nimport {\n EntityFilterValue,\n EntityFilterValueText,\n} from '../filters/EntityFilterValue.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { DeferredFilterSearchInput } from '../filters/DeferredFilterSearchInput.js';\nimport { BackofficeListFilterProvider } from './BackofficeListFilterContext.js';\nimport { BACKOFFICE_LIST_BODY_SCROLL_MODE } from './backofficeListScrollMode.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeInfiniteScrollSentinel } from '../../../hooks/useBackofficeInfiniteScrollSentinel.js';\nimport type { BackofficeFilterDrawerState } from '../../../provider/BackofficeListUiStateContext.js';\nimport { isDevEnv } from '../../../relay/envHelpers.js';\n\nimport * as styles from './backofficeEntityListScaffold.css.js';\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst getFilterValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n where: Where | null,\n): unknown => {\n if (filter.fromGraphQL != null && where != null) {\n return filter.fromGraphQL(where);\n }\n\n const key = (filter.whereKey ?? filter.id) as keyof Where;\n return readWhereValue(where, key, filter.path);\n};\n\nconst normalizeStringArray = (value: unknown): readonly string[] => {\n if (!Array.isArray(value)) {\n return [];\n }\n return value\n .map((entry) => {\n if (entry == null) {\n return null;\n }\n const normalized = String(entry).trim();\n if (normalized === '') {\n return null;\n }\n return normalized;\n })\n .filter((entry): entry is string => {\n return entry != null;\n });\n};\n\nconst getFilterDisplayValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n raw: unknown,\n options: {\n enumLabel: (value: string) => string;\n booleanLabel: (value: boolean) => string;\n fallbackBooleanLabels: { yes: string; no: string };\n },\n): ReactNode | null => {\n if (raw == null) {\n return null;\n }\n\n if (Array.isArray(raw)) {\n const normalized = normalizeStringArray(raw);\n\n if (normalized.length === 0) {\n return null;\n }\n\n if (filter.kind === 'entityIdList') {\n return (\n <>\n {normalized.map((id, index) => {\n return (\n <span key={id}>\n <EntityFilterValue entityId={filter.entity} id={id} />\n {index < normalized.length - 1 ? ', ' : null}\n </span>\n );\n })}\n </>\n );\n }\n\n return normalized.join(', ');\n }\n\n if (typeof raw === 'boolean') {\n if (filter.kind === 'boolean') {\n return options.booleanLabel(raw);\n }\n if (raw) {\n return options.fallbackBooleanLabels.yes;\n }\n return options.fallbackBooleanLabels.no;\n }\n\n if (typeof raw !== 'string' && typeof raw !== 'number') {\n return null;\n }\n\n const rawString = String(raw).trim();\n if (rawString === '') {\n return null;\n }\n\n if (filter.kind === 'entityId') {\n return <EntityFilterValue entityId={filter.entity} id={rawString} />;\n }\n\n if (filter.kind === 'enum') {\n return options.enumLabel(rawString);\n }\n\n return rawString;\n};\n\nconst toDatetimeInputValue = (value: string): string => {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const offsetMs = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);\n};\n\nconst fromDatetimeInputValue = (value: string): string => {\n const normalized = value.trim();\n if (normalized === '') {\n return '';\n }\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n return normalized;\n }\n return date.toISOString();\n};\n\ntype RuntimeWhere = Record<string, unknown>;\ntype RuntimeSort = string;\n\ntype Props<RowView> = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<RuntimeWhere, RuntimeSort>;\n pushState: (next: BackofficeListState<RuntimeWhere, RuntimeSort>) => void;\n header?: {\n title?: string;\n subtitle?: string;\n };\n headerActions?: ReactNode;\n rows: readonly RowView[];\n getRowId: GetRowId<RowView>;\n columns: readonly DataTableColumn<RowView>[];\n gridTemplateColumns?: string;\n hasNextPage: boolean;\n isLoadingMore: boolean;\n isRefreshing?: boolean;\n onLoadMore: () => void;\n onRefresh?: () => void;\n totalCount?: number | null;\n loadedCountLabel?: ReactNode;\n emptyState?: JSX.Element;\n statusBanner?: ReactNode;\n isLoadingInitial?: boolean;\n virtualize?: boolean;\n variant?: 'page' | 'embedded';\n showFilters?: boolean;\n filterDrawerState?: BackofficeFilterDrawerState;\n};\n\nexport const BackofficeEntityListScaffold = <RowView,>(\n props: Props<RowView>,\n): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const {\n config,\n state,\n pushState,\n rows,\n getRowId,\n columns,\n gridTemplateColumns,\n hasNextPage,\n isLoadingMore,\n isRefreshing = false,\n onLoadMore,\n onRefresh,\n totalCount,\n loadedCountLabel,\n emptyState,\n statusBanner,\n header,\n headerActions,\n isLoadingInitial = false,\n variant = 'page',\n showFilters = true,\n } = props;\n const listConfig = config.list;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const columnsWithPrimary = useMemo(() => {\n const hasPrimary = columns.some((col) => {\n return col.isPrimary === true;\n });\n if (hasPrimary || columns.length === 0) {\n return columns;\n }\n return columns.map((col, index) => {\n const { header } = col;\n if (index === 0) {\n return { ...col, isPrimary: true, header };\n }\n return { ...col, header };\n });\n }, [columns]);\n\n const chips = useMemo<readonly FilterChip[]>(() => {\n const out: FilterChip[] = [];\n for (const filter of listConfig.filters) {\n const raw = getFilterValue(filter, state.where);\n const displayValue = getFilterDisplayValue(filter, raw, {\n enumLabel: (value) => {\n if (filter.kind !== 'enum') {\n return value;\n }\n const match = filter.options.find((option) => {\n return option.value === value;\n });\n if (match != null) {\n return resolveLabel(match.label, tApp);\n }\n return value;\n },\n booleanLabel: (value) => {\n if (filter.kind === 'boolean') {\n if (value && filter.trueLabel != null) {\n return resolveLabel(filter.trueLabel, tApp);\n }\n if (!value && filter.falseLabel != null) {\n return resolveLabel(filter.falseLabel, tApp);\n }\n }\n if (value) {\n return t('filters.boolean.yes');\n }\n return t('filters.boolean.no');\n },\n fallbackBooleanLabels: {\n yes: t('filters.boolean.yes'),\n no: t('filters.boolean.no'),\n },\n });\n\n if (displayValue != null) {\n let idValue = String(raw);\n if (Array.isArray(raw)) {\n idValue = raw.join(',');\n }\n const label = (\n <span>\n {resolveLabel(filter.label, tApp)}: {displayValue}\n </span>\n );\n out.push({\n id: `${filter.id}:${idValue}`,\n label,\n onRemove: () => {\n const key = filter.whereKey ?? filter.id;\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n },\n });\n }\n }\n return out;\n }, [listConfig.filters, pushState, state, t, tApp]);\n\n const handleClearAll = useCallback(() => {\n pushState({\n ...listDefaults,\n });\n }, [listDefaults, pushState]);\n const [localIsFilterDrawerOpen, setLocalIsFilterDrawerOpen] = useState(false);\n const [localFilterSearch, setLocalFilterSearch] = useState('');\n const drawerState = props.filterDrawerState ?? {\n isOpen: localIsFilterDrawerOpen,\n search: localFilterSearch,\n setOpen: setLocalIsFilterDrawerOpen,\n setSearch: setLocalFilterSearch,\n reset: () => {\n setLocalIsFilterDrawerOpen(false);\n setLocalFilterSearch('');\n },\n };\n const isFilterDrawerOpen = drawerState.isOpen;\n const filterSearch = drawerState.search;\n const setIsFilterDrawerOpen = drawerState.setOpen;\n const setFilterSearch = drawerState.setSearch;\n const resetFilterDrawer = drawerState.reset;\n\n const [pickerDialog, setPickerDialog] = useState<{\n entity: string;\n whereKey: keyof RuntimeWhere;\n label: string;\n mode: 'single' | 'list';\n currentIds?: readonly string[];\n path?: readonly string[];\n scope?: BackofficePickerScope<Record<string, unknown>>;\n } | null>(null);\n\n const renderFilterControl = useCallback(\n (filter: BackofficeFilterSpec<RuntimeWhere>): JSX.Element => {\n const key = filter.whereKey ?? filter.id;\n const candidate = getFilterValue(filter, state.where);\n let value = '';\n if (typeof candidate === 'string') {\n value = candidate;\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n value = String(candidate);\n }\n\n const filterLabelText = resolveLabel(filter.label, tApp);\n\n if (filter.kind === 'text') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n if (filter.kind === 'datetime') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={toDatetimeInputValue(value)}\n onApply={(next) => {\n const normalized = fromDatetimeInputValue(next);\n const nextWhere = setWhereValue(\n state.where,\n key,\n normalized,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n type=\"datetime-local\"\n />\n );\n }\n\n if (filter.kind === 'number') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const normalized = next.trim();\n const parsed = normalized === '' ? null : Number(normalized);\n const nextWhere = setWhereValue(\n state.where,\n key,\n Number.isFinite(parsed) ? parsed : null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n inputMode={filter.inputMode ?? 'numeric'}\n type=\"text\"\n />\n );\n }\n\n if (filter.kind === 'enum') {\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n ...filter.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n }),\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={value}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n if (filter.kind === 'boolean') {\n let current: boolean | null = null;\n if (typeof candidate === 'boolean') {\n current = candidate;\n }\n\n let selectValue = '';\n if (current === true) {\n selectValue = 'true';\n }\n if (current === false) {\n selectValue = 'false';\n }\n\n const trueLabel =\n filter.trueLabel != null\n ? resolveLabel(filter.trueLabel, tApp)\n : t('filters.boolean.yes');\n const falseLabel =\n filter.falseLabel != null\n ? resolveLabel(filter.falseLabel, tApp)\n : t('filters.boolean.no');\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n {\n id: 'true',\n value: 'true',\n label: trueLabel,\n },\n {\n id: 'false',\n value: 'false',\n label: falseLabel,\n },\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={selectValue}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n let parsed: boolean | null = null;\n if (next === 'true') {\n parsed = true;\n }\n if (next === 'false') {\n parsed = false;\n }\n const nextWhere = setWhereValue(\n state.where,\n key,\n parsed,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n const pickerScope = (() => {\n if (filter.pickerScope == null) {\n return undefined;\n }\n if (typeof filter.pickerScope === 'function') {\n return filter.pickerScope(state.where);\n }\n return filter.pickerScope;\n })();\n\n if (filter.kind === 'entityIdList') {\n const currentIds = normalizeStringArray(candidate);\n const selectedCount = currentIds.length;\n const displayValue =\n selectedCount === 0\n ? null\n : t('filters.selectedEntities', {\n count: selectedCount,\n });\n\n const removeId = (id: string): void => {\n const nextIds = currentIds.filter((currentId) => {\n return currentId !== id;\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n nextIds.length === 0 ? null : nextIds,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n };\n\n return (\n <div className={styles.entityIdListFilter}>\n <EntityIdFilterField\n label={filterLabelText}\n value={selectedCount === 0 ? null : currentIds.join(',')}\n displayValue={displayValue}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'list',\n currentIds,\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n {currentIds.length > 0 ? (\n <div className={styles.entityIdListTags}>\n {currentIds.map((id) => {\n return (\n <Tag\n key={id}\n removeLabel={t('filters.actions.removeFilterValue', {\n label: filterLabelText,\n })}\n onRemove={() => {\n removeId(id);\n }}\n >\n <EntityFilterValue entityId={filter.entity} id={id} />\n </Tag>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n }\n\n if (filter.kind === 'stringList') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const values = next\n .split(/[\\n,]+/u)\n .map((entry) => {\n return entry.trim();\n })\n .filter((entry) => {\n return entry !== '';\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n values,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n let currentId: string | null = null;\n if (typeof candidate === 'string') {\n currentId = candidate;\n }\n\n const renderField = (\n displayValue: string | null = null,\n isResolving = false,\n ) => {\n const normalizedDisplayValue = displayValue?.trim() ?? '';\n return (\n <EntityIdFilterField\n label={filterLabelText}\n value={currentId}\n displayValue={normalizedDisplayValue}\n isResolving={isResolving}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'single',\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n };\n\n if (currentId == null || currentId.trim() === '') {\n return renderField();\n }\n\n return (\n <EntityFilterValueText entityId={filter.entity} id={currentId}>\n {(label, valueState) => {\n const isResolving = valueState?.status === 'loading';\n return renderField(\n isResolving ? t('common.loading') : label,\n isResolving,\n );\n }}\n </EntityFilterValueText>\n );\n },\n [pushState, state, t, tApp],\n );\n\n const hasPlacementConfig = useMemo(() => {\n return listConfig.filters.some((filter) => {\n return filter.placement != null;\n });\n }, [listConfig.filters]);\n\n const quickFilters = useMemo(() => {\n if (listConfig.filters.length === 0) {\n return [];\n }\n const maxPromotedFilters = listConfig.ui?.toolbar?.maxPromotedFilters ?? 3;\n if (hasPlacementConfig) {\n return listConfig.filters.filter((filter) => {\n return filter.placement === 'quick' || filter.placement === 'both';\n });\n }\n return listConfig.filters.slice(0, maxPromotedFilters);\n }, [listConfig.filters, listConfig.ui?.toolbar, hasPlacementConfig]);\n\n const drawerFilters = useMemo(() => {\n return listConfig.filters.filter((filter) => {\n if (filter.placement == null) {\n return true;\n }\n return filter.placement === 'drawer' || filter.placement === 'both';\n });\n }, [listConfig.filters]);\n\n const searchFilter = useMemo(() => {\n return quickFilters.find((filter) => {\n return filter.kind === 'text';\n });\n }, [quickFilters]);\n\n const quickFiltersNode = useMemo(() => {\n const visibleQuickFilters = quickFilters.filter((filter) => {\n return filter !== searchFilter;\n });\n\n if (visibleQuickFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.controlsRow}>\n {visibleQuickFilters.map((filter) => {\n return <span key={filter.id}>{renderFilterControl(filter)}</span>;\n })}\n </div>\n );\n }, [quickFilters, renderFilterControl, searchFilter]);\n\n const searchNode = useMemo(() => {\n if (searchFilter == null) {\n return null;\n }\n return renderFilterControl(searchFilter);\n }, [renderFilterControl, searchFilter]);\n\n const sortNode = useMemo(() => {\n if (listConfig.sorts.length === 0) {\n return null;\n }\n const firstSort = listConfig.sorts[0];\n if (firstSort == null) {\n return null;\n }\n const options = listConfig.sorts.map((s) => {\n return { id: s.id, value: s.id, label: resolveLabel(s.label, tApp) };\n });\n return (\n <SimpleSelect\n options={options}\n value={state.sort ?? firstSort.id}\n size=\"small\"\n ariaLabel={t('list.sort.label')}\n onChange={(next) => {\n pushState({\n ...state,\n sort: next,\n });\n }}\n />\n );\n }, [listConfig.sorts, pushState, state, t, tApp]);\n\n const chipsNode = useMemo(() => {\n if (chips.length === 0) {\n return null;\n }\n return <FilterChipRow chips={chips} onClearAll={handleClearAll} />;\n }, [chips, handleClearAll]);\n\n const drawerSections = useMemo(() => {\n if (drawerFilters.length === 0) {\n return [];\n }\n\n const normalizedQuery = filterSearch.trim().toLowerCase();\n const items: { id: string; node: JSX.Element }[] = [];\n\n for (const filter of drawerFilters) {\n const resolvedLabel = resolveLabel(filter.label, tApp);\n const matchesQuery =\n normalizedQuery === '' ||\n resolvedLabel.toLowerCase().includes(normalizedQuery);\n\n if (matchesQuery) {\n items.push({\n id: filter.id,\n node: (\n <BackofficeFilterField label={resolvedLabel}>\n {renderFilterControl(filter)}\n </BackofficeFilterField>\n ),\n });\n }\n }\n\n if (items.length === 0) {\n return [];\n }\n\n return [\n {\n id: 'backoffice.filters.sections.default',\n title: t('filters.sections.default'),\n items,\n },\n ];\n }, [drawerFilters, filterSearch, renderFilterControl, t, tApp]);\n\n const allFiltersNode = useMemo(() => {\n if (drawerFilters.length === 0) {\n return null;\n }\n const activeCount = chips.length;\n let label = t('filters.trigger');\n if (activeCount > 0) {\n label = t('filters.triggerWithCount', {\n count: activeCount,\n });\n }\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsFilterDrawerOpen(true);\n }}\n >\n {label}\n </Button>\n );\n }, [chips.length, drawerFilters.length, setIsFilterDrawerOpen, t]);\n\n const filterDrawerEmptyLabel =\n filterSearch.trim() === ''\n ? undefined\n : t('filters.drawer.emptySearchResults');\n\n const filterDrawerNode = (\n <BackofficeFilterDrawer\n isOpen={isFilterDrawerOpen}\n onClose={() => {\n resetFilterDrawer();\n }}\n sections={drawerSections}\n searchValue={filterSearch}\n onSearchChange={(next) => {\n setFilterSearch(next);\n }}\n onReset={handleClearAll}\n emptyLabel={filterDrawerEmptyLabel}\n />\n );\n\n const resolvedEmptyState = useMemo((): JSX.Element => {\n if (emptyState != null) {\n return emptyState;\n }\n\n if (isLoadingInitial) {\n return (\n <BackofficeTableSkeleton\n variant=\"embedded\"\n ariaLabel={t('common.loading')}\n />\n );\n }\n\n if (chips.length > 0) {\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmptyFiltered.description')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleClearAll}\n >\n {t('emptyState.listEmptyFiltered.actions.reset')}\n </Button>\n }\n />\n );\n }\n\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmpty.description')}\n />\n );\n }, [chips.length, emptyState, handleClearAll, isLoadingInitial, t]);\n\n const tableFooterMeta = useMemo((): ReactNode => {\n if (loadedCountLabel != null) {\n return loadedCountLabel;\n }\n if (typeof totalCount !== 'number') {\n if (rows.length === 0) {\n return null;\n }\n return (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }, [loadedCountLabel, rows.length, t, totalCount]);\n\n const runtimeConfig = useMemo(() => {\n const resolvedDisplayMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n return resolveBackofficeListRuntimeConfig({\n kind: listConfig.kind,\n displayMode: resolvedDisplayMode,\n ui: listConfig.ui,\n });\n }, [listConfig.kind, listConfig.responsive?.mode, listConfig.ui]);\n\n const hasKnownRemainingRows =\n typeof totalCount === 'number' && rows.length < totalCount;\n const hasInconsistentPageInfo = hasKnownRemainingRows && !hasNextPage;\n\n useEffect(() => {\n if (\n !hasInconsistentPageInfo ||\n !runtimeConfig.infiniteScroll.showInconsistentPageInfo ||\n !isDevEnv()\n ) {\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(\n 'Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.',\n {\n entityId: config.id,\n loadedCount: rows.length,\n totalCount,\n },\n );\n }, [\n config.id,\n hasInconsistentPageInfo,\n rows.length,\n runtimeConfig.infiniteScroll.showInconsistentPageInfo,\n totalCount,\n ]);\n\n const shouldVirtualizeTable =\n props.virtualize === true || runtimeConfig.virtualization.enabled;\n\n const { sentinelRef } = useBackofficeInfiniteScrollSentinel({\n enabled: !shouldVirtualizeTable && runtimeConfig.infiniteScroll.enabled,\n hasNextPage,\n isLoading: isLoadingMore,\n onIntersect: onLoadMore,\n rootMargin: runtimeConfig.infiniteScroll.rootMargin,\n threshold: runtimeConfig.infiniteScroll.threshold,\n });\n\n const headerTitle = header?.title ?? resolveLabel(listConfig.title, tApp);\n const headerSubtitle = header?.subtitle;\n\n const actionColumn = columnsWithPrimary.find((column) => {\n return column.mobileRole === 'action' || column.id === 'actions';\n });\n const listMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n const listDensity =\n listConfig.ui?.density ?? listConfig.responsive?.density ?? 'compact';\n\n const tableInnerNode = shouldVirtualizeTable ? (\n <VirtualizedConnectionTable\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n virtualization={runtimeConfig.virtualization}\n infiniteScroll={{\n enabled: runtimeConfig.infiniteScroll.enabled,\n thresholdPx: runtimeConfig.infiniteScroll.thresholdPx,\n autoLoad: runtimeConfig.infiniteScroll.autoLoad,\n }}\n hasNextPage={hasNextPage}\n isLoadingMore={isLoadingMore}\n onLoadMore={onLoadMore}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n ) : (\n <ResponsiveRecordList\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n mode={listMode}\n density={listDensity}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n bodyFooterNode={\n runtimeConfig.infiniteScroll.enabled ? (\n <div ref={sentinelRef} aria-hidden=\"true\" />\n ) : null\n }\n renderAction={(row) => {\n return actionColumn?.cell(row) ?? null;\n }}\n />\n );\n\n const tableNodeWithErrorBoundary = (\n <BackofficeErrorBoundary\n fallback={(args: { error: unknown; reset: () => void }) => {\n const { reset } = args;\n\n const retry = (): void => {\n reset();\n if (onRefresh != null) {\n onRefresh();\n }\n };\n\n return (\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={retry}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n );\n }}\n >\n {tableInnerNode}\n </BackofficeErrorBoundary>\n );\n\n const filtersBarNode = showFilters ? (\n <>\n <BackofficeToolbar\n search={searchNode}\n primaryFilters={quickFiltersNode}\n filterDrawerTrigger={allFiltersNode}\n sort={sortNode}\n utilityActions={\n onRefresh == null ? null : (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n isLoading={isRefreshing}\n loadingLabel={t('list.actions.refreshing')}\n onClick={() => {\n onRefresh();\n }}\n >\n {t('list.actions.refresh')}\n </Button>\n )\n }\n chips={chipsNode}\n density=\"compact\"\n />\n {filterDrawerNode}\n </>\n ) : null;\n\n const tableNode = (\n <div\n className={styles.tableHost}\n aria-busy={isRefreshing ? 'true' : undefined}\n >\n {isRefreshing && !isLoadingInitial ? (\n <div className={styles.refreshingIndicator} role=\"status\">\n <Spinner size={14} ariaLabel={t('list.refreshingRows')} />\n <span>{t('list.refreshingRows')}</span>\n </div>\n ) : null}\n {tableNodeWithErrorBoundary}\n <EntityIdPickerDialog\n isOpen={pickerDialog != null}\n entity={pickerDialog?.entity ?? config.id}\n title={pickerDialog?.label ?? t('picker.title')}\n scope={pickerDialog?.scope}\n onClose={() => {\n setPickerDialog(null);\n }}\n onSelectId={(id) => {\n if (pickerDialog == null) {\n return;\n }\n if (pickerDialog.mode === 'list') {\n const currentIds = pickerDialog.currentIds ?? [];\n const nextIds = currentIds.includes(id)\n ? currentIds\n : [...currentIds, id];\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n nextIds,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n return;\n }\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n id,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n }}\n />\n </div>\n );\n\n const shouldRenderTableFooter =\n rows.length > 0 || isLoadingMore || hasNextPage;\n\n const tableFooterNode = shouldRenderTableFooter ? (\n <>\n <BackofficeListFooter\n mode=\"status\"\n loadedCount={rows.length}\n totalCount={totalCount}\n hasNextPage={hasNextPage}\n isLoading={isLoadingMore}\n pageInfoState={\n hasInconsistentPageInfo\n ? 'inconsistent'\n : isLoadingMore\n ? 'loading'\n : hasNextPage\n ? 'ready'\n : 'complete'\n }\n labels={{\n loaded: tableFooterMeta,\n loading: t('list.loadMore.loading'),\n end: t('list.loadMore.end'),\n }}\n />\n </>\n ) : null;\n\n if (variant === 'embedded') {\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <div className={styles.embeddedContainer}>\n <div className={styles.embeddedHeader}>{headerTitle}</div>\n {filtersBarNode}\n {statusBanner}\n {tableNode}\n {tableFooterNode}\n </div>\n </BackofficeListFilterProvider>\n );\n }\n\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <ListPageTemplate\n headerNode={\n <BackofficePageHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n />\n }\n toolbarNode={filtersBarNode}\n statusNode={statusBanner}\n tableNode={tableNode}\n tableFooterNode={tableFooterNode}\n presentation=\"flat\"\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n </BackofficeListFilterProvider>\n );\n};\n\nexport default BackofficeEntityListScaffold;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BackofficeEntityListScaffold.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n type JSX,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { BackofficeEmptyState } from '@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js';\nimport { BackofficeFilterDrawer } from '@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js';\nimport { BackofficeFilterField } from '@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js';\nimport { Spinner } from '@plumile/ui/backoffice/atoms/spinner/Spinner.js';\nimport { Tag } from '@plumile/ui/backoffice/atoms/tag/Tag.js';\nimport { BackofficeListFooter } from '@plumile/ui/backoffice/molecules/backoffice_list_footer/BackofficeListFooter.js';\nimport { BackofficePageHeader } from '@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js';\nimport { BackofficeToolbar } from '@plumile/ui/backoffice/molecules/backoffice_toolbar/BackofficeToolbar.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport {\n FilterChipRow,\n type FilterChip,\n} from '@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\nimport { ListPageTemplate } from '@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { ResponsiveRecordList } from '@plumile/ui/components/data-table/ResponsiveRecordList.js';\nimport { VirtualizedConnectionTable } from '@plumile/ui/components/data-table/VirtualizedConnectionTable.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport { denseTableClass } from '@plumile/ui/shared/backofficeTableDensity.css.js';\n\nimport {\n readWhereValue,\n setWhereValue,\n} from '@plumile/backoffice-core/filters/where.js';\nimport { resolveBackofficeListRuntimeConfig } from '@plumile/backoffice-core/config/listRuntime.js';\nimport type {\n BackofficeFilterSpec,\n BackofficeListState,\n BackofficePickerScope,\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\nimport {\n EntityFilterValue,\n EntityFilterValueText,\n} from '../filters/EntityFilterValue.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { DeferredFilterSearchInput } from '../filters/DeferredFilterSearchInput.js';\nimport { BackofficeListFilterProvider } from './BackofficeListFilterContext.js';\nimport { BACKOFFICE_LIST_BODY_SCROLL_MODE } from './backofficeListScrollMode.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeInfiniteScrollSentinel } from '../../../hooks/useBackofficeInfiniteScrollSentinel.js';\nimport type { BackofficeFilterDrawerState } from '../../../provider/BackofficeListUiStateContext.js';\nimport { isDevEnv } from '../../../relay/envHelpers.js';\n\nimport * as styles from './backofficeEntityListScaffold.css.js';\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst getFilterValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n where: Where | null,\n): unknown => {\n if (filter.fromGraphQL != null && where != null) {\n return filter.fromGraphQL(where);\n }\n\n const key = (filter.whereKey ?? filter.id) as keyof Where;\n return readWhereValue(where, key, filter.path);\n};\n\nconst normalizeStringArray = (value: unknown): readonly string[] => {\n if (!Array.isArray(value)) {\n return [];\n }\n return value\n .map((entry) => {\n if (entry == null) {\n return null;\n }\n const normalized = String(entry).trim();\n if (normalized === '') {\n return null;\n }\n return normalized;\n })\n .filter((entry): entry is string => {\n return entry != null;\n });\n};\n\nconst getFilterDisplayValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n raw: unknown,\n options: {\n enumLabel: (value: string) => string;\n booleanLabel: (value: boolean) => string;\n fallbackBooleanLabels: { yes: string; no: string };\n },\n): ReactNode | null => {\n if (raw == null) {\n return null;\n }\n\n if (Array.isArray(raw)) {\n const normalized = normalizeStringArray(raw);\n\n if (normalized.length === 0) {\n return null;\n }\n\n if (filter.kind === 'entityIdList') {\n return (\n <>\n {normalized.map((id, index) => {\n return (\n <span key={id}>\n <EntityFilterValue entityId={filter.entity} id={id} />\n {index < normalized.length - 1 ? ', ' : null}\n </span>\n );\n })}\n </>\n );\n }\n\n return normalized.join(', ');\n }\n\n if (typeof raw === 'boolean') {\n if (filter.kind === 'boolean') {\n return options.booleanLabel(raw);\n }\n if (raw) {\n return options.fallbackBooleanLabels.yes;\n }\n return options.fallbackBooleanLabels.no;\n }\n\n if (typeof raw !== 'string' && typeof raw !== 'number') {\n return null;\n }\n\n const rawString = String(raw).trim();\n if (rawString === '') {\n return null;\n }\n\n if (filter.kind === 'entityId') {\n return <EntityFilterValue entityId={filter.entity} id={rawString} />;\n }\n\n if (filter.kind === 'enum') {\n return options.enumLabel(rawString);\n }\n\n return rawString;\n};\n\nconst toDatetimeInputValue = (value: string): string => {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const offsetMs = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);\n};\n\nconst fromDatetimeInputValue = (value: string): string => {\n const normalized = value.trim();\n if (normalized === '') {\n return '';\n }\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n return normalized;\n }\n return date.toISOString();\n};\n\ntype RuntimeWhere = Record<string, unknown>;\ntype RuntimeSort = string;\n\ntype Props<RowView> = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<RuntimeWhere, RuntimeSort>;\n pushState: (next: BackofficeListState<RuntimeWhere, RuntimeSort>) => void;\n header?: {\n title?: string;\n subtitle?: string;\n };\n headerActions?: ReactNode;\n rows: readonly RowView[];\n getRowId: GetRowId<RowView>;\n columns: readonly DataTableColumn<RowView>[];\n gridTemplateColumns?: string;\n hasNextPage: boolean;\n isLoadingMore: boolean;\n isRefreshing?: boolean;\n onLoadMore: () => void;\n onRefresh?: () => void;\n totalCount?: number | null;\n loadedCountLabel?: ReactNode;\n emptyState?: JSX.Element;\n statusBanner?: ReactNode;\n isLoadingInitial?: boolean;\n virtualize?: boolean;\n variant?: 'page' | 'embedded';\n showFilters?: boolean;\n filterDrawerState?: BackofficeFilterDrawerState;\n};\n\nexport const BackofficeEntityListScaffold = <RowView,>(\n props: Props<RowView>,\n): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const {\n config,\n state,\n pushState,\n rows,\n getRowId,\n columns,\n gridTemplateColumns,\n hasNextPage,\n isLoadingMore,\n isRefreshing = false,\n onLoadMore,\n onRefresh,\n totalCount,\n loadedCountLabel,\n emptyState,\n statusBanner,\n header,\n headerActions,\n isLoadingInitial = false,\n variant = 'page',\n showFilters = true,\n } = props;\n const listConfig = config.list;\n const { listDefaults } = config;\n\n const columnsWithPrimary = useMemo(() => {\n const hasPrimary = columns.some((col) => {\n return col.isPrimary === true;\n });\n if (hasPrimary || columns.length === 0) {\n return columns;\n }\n return columns.map((col, index) => {\n const { header } = col;\n if (index === 0) {\n return { ...col, isPrimary: true, header };\n }\n return { ...col, header };\n });\n }, [columns]);\n\n const chips = useMemo<readonly FilterChip[]>(() => {\n const out: FilterChip[] = [];\n for (const filter of listConfig.filters) {\n const raw = getFilterValue(filter, state.where);\n const displayValue = getFilterDisplayValue(filter, raw, {\n enumLabel: (value) => {\n if (filter.kind !== 'enum') {\n return value;\n }\n const match = filter.options.find((option) => {\n return option.value === value;\n });\n if (match != null) {\n return resolveLabel(match.label, tApp);\n }\n return value;\n },\n booleanLabel: (value) => {\n if (filter.kind === 'boolean') {\n if (value && filter.trueLabel != null) {\n return resolveLabel(filter.trueLabel, tApp);\n }\n if (!value && filter.falseLabel != null) {\n return resolveLabel(filter.falseLabel, tApp);\n }\n }\n if (value) {\n return t('filters.boolean.yes');\n }\n return t('filters.boolean.no');\n },\n fallbackBooleanLabels: {\n yes: t('filters.boolean.yes'),\n no: t('filters.boolean.no'),\n },\n });\n\n if (displayValue != null) {\n let idValue = String(raw);\n if (Array.isArray(raw)) {\n idValue = raw.join(',');\n }\n const label = (\n <span>\n {resolveLabel(filter.label, tApp)}: {displayValue}\n </span>\n );\n out.push({\n id: `${filter.id}:${idValue}`,\n label,\n onRemove: () => {\n const key = filter.whereKey ?? filter.id;\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n },\n });\n }\n }\n return out;\n }, [listConfig.filters, pushState, state, t, tApp]);\n\n const handleClearAll = useCallback(() => {\n pushState({\n ...listDefaults,\n });\n }, [listDefaults, pushState]);\n const [localIsFilterDrawerOpen, setLocalIsFilterDrawerOpen] = useState(false);\n const [localFilterSearch, setLocalFilterSearch] = useState('');\n const drawerState = props.filterDrawerState ?? {\n isOpen: localIsFilterDrawerOpen,\n search: localFilterSearch,\n setOpen: setLocalIsFilterDrawerOpen,\n setSearch: setLocalFilterSearch,\n reset: () => {\n setLocalIsFilterDrawerOpen(false);\n setLocalFilterSearch('');\n },\n };\n const isFilterDrawerOpen = drawerState.isOpen;\n const filterSearch = drawerState.search;\n const setIsFilterDrawerOpen = drawerState.setOpen;\n const setFilterSearch = drawerState.setSearch;\n const resetFilterDrawer = drawerState.reset;\n\n const [pickerDialog, setPickerDialog] = useState<{\n entity: string;\n whereKey: keyof RuntimeWhere;\n label: string;\n mode: 'single' | 'list';\n currentIds?: readonly string[];\n path?: readonly string[];\n scope?: BackofficePickerScope<Record<string, unknown>>;\n } | null>(null);\n\n const renderFilterControl = useCallback(\n (filter: BackofficeFilterSpec<RuntimeWhere>): JSX.Element => {\n const key = filter.whereKey ?? filter.id;\n const candidate = getFilterValue(filter, state.where);\n let value = '';\n if (typeof candidate === 'string') {\n value = candidate;\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n value = String(candidate);\n }\n\n const filterLabelText = resolveLabel(filter.label, tApp);\n\n if (filter.kind === 'text') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n if (filter.kind === 'datetime') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={toDatetimeInputValue(value)}\n onApply={(next) => {\n const normalized = fromDatetimeInputValue(next);\n const nextWhere = setWhereValue(\n state.where,\n key,\n normalized,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n type=\"datetime-local\"\n />\n );\n }\n\n if (filter.kind === 'number') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const normalized = next.trim();\n const parsed = normalized === '' ? null : Number(normalized);\n const nextWhere = setWhereValue(\n state.where,\n key,\n Number.isFinite(parsed) ? parsed : null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n inputMode={filter.inputMode ?? 'numeric'}\n type=\"text\"\n />\n );\n }\n\n if (filter.kind === 'enum') {\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n ...filter.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n }),\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={value}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n if (filter.kind === 'boolean') {\n let current: boolean | null = null;\n if (typeof candidate === 'boolean') {\n current = candidate;\n }\n\n let selectValue = '';\n if (current === true) {\n selectValue = 'true';\n }\n if (current === false) {\n selectValue = 'false';\n }\n\n const trueLabel =\n filter.trueLabel != null\n ? resolveLabel(filter.trueLabel, tApp)\n : t('filters.boolean.yes');\n const falseLabel =\n filter.falseLabel != null\n ? resolveLabel(filter.falseLabel, tApp)\n : t('filters.boolean.no');\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n {\n id: 'true',\n value: 'true',\n label: trueLabel,\n },\n {\n id: 'false',\n value: 'false',\n label: falseLabel,\n },\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={selectValue}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n let parsed: boolean | null = null;\n if (next === 'true') {\n parsed = true;\n }\n if (next === 'false') {\n parsed = false;\n }\n const nextWhere = setWhereValue(\n state.where,\n key,\n parsed,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n const pickerScope = (() => {\n if (filter.pickerScope == null) {\n return undefined;\n }\n if (typeof filter.pickerScope === 'function') {\n return filter.pickerScope(state.where);\n }\n return filter.pickerScope;\n })();\n\n if (filter.kind === 'entityIdList') {\n const currentIds = normalizeStringArray(candidate);\n const selectedCount = currentIds.length;\n const displayValue =\n selectedCount === 0\n ? null\n : t('filters.selectedEntities', {\n count: selectedCount,\n });\n\n const removeId = (id: string): void => {\n const nextIds = currentIds.filter((currentId) => {\n return currentId !== id;\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n nextIds.length === 0 ? null : nextIds,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n };\n\n return (\n <div className={styles.entityIdListFilter}>\n <EntityIdFilterField\n label={filterLabelText}\n value={selectedCount === 0 ? null : currentIds.join(',')}\n displayValue={displayValue}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'list',\n currentIds,\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n {currentIds.length > 0 ? (\n <div className={styles.entityIdListTags}>\n {currentIds.map((id) => {\n return (\n <Tag\n key={id}\n removeLabel={t('filters.actions.removeFilterValue', {\n label: filterLabelText,\n })}\n onRemove={() => {\n removeId(id);\n }}\n >\n <EntityFilterValue entityId={filter.entity} id={id} />\n </Tag>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n }\n\n if (filter.kind === 'stringList') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const values = next\n .split(/[\\n,]+/u)\n .map((entry) => {\n return entry.trim();\n })\n .filter((entry) => {\n return entry !== '';\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n values,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n let currentId: string | null = null;\n if (typeof candidate === 'string') {\n currentId = candidate;\n }\n\n const renderField = (\n displayValue: string | null = null,\n isResolving = false,\n ) => {\n const normalizedDisplayValue = displayValue?.trim() ?? '';\n return (\n <EntityIdFilterField\n label={filterLabelText}\n value={currentId}\n displayValue={normalizedDisplayValue}\n isResolving={isResolving}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'single',\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n };\n\n if (currentId == null || currentId.trim() === '') {\n return renderField();\n }\n\n return (\n <EntityFilterValueText entityId={filter.entity} id={currentId}>\n {(label, valueState) => {\n const isResolving = valueState?.status === 'loading';\n return renderField(\n isResolving ? t('common.loading') : label,\n isResolving,\n );\n }}\n </EntityFilterValueText>\n );\n },\n [pushState, state, t, tApp],\n );\n\n const hasPlacementConfig = useMemo(() => {\n return listConfig.filters.some((filter) => {\n return filter.placement != null;\n });\n }, [listConfig.filters]);\n\n const quickFilters = useMemo(() => {\n if (listConfig.filters.length === 0) {\n return [];\n }\n const maxPromotedFilters = listConfig.ui?.toolbar?.maxPromotedFilters ?? 3;\n if (hasPlacementConfig) {\n return listConfig.filters.filter((filter) => {\n return filter.placement === 'quick' || filter.placement === 'both';\n });\n }\n return listConfig.filters.slice(0, maxPromotedFilters);\n }, [listConfig.filters, listConfig.ui?.toolbar, hasPlacementConfig]);\n\n const drawerFilters = useMemo(() => {\n return listConfig.filters.filter((filter) => {\n if (filter.placement == null) {\n return true;\n }\n return filter.placement === 'drawer' || filter.placement === 'both';\n });\n }, [listConfig.filters]);\n\n const searchFilter = useMemo(() => {\n return quickFilters.find((filter) => {\n return filter.kind === 'text';\n });\n }, [quickFilters]);\n\n const quickFiltersNode = useMemo(() => {\n const visibleQuickFilters = quickFilters.filter((filter) => {\n return filter !== searchFilter;\n });\n\n if (visibleQuickFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.controlsRow}>\n {visibleQuickFilters.map((filter) => {\n return <span key={filter.id}>{renderFilterControl(filter)}</span>;\n })}\n </div>\n );\n }, [quickFilters, renderFilterControl, searchFilter]);\n\n const searchNode = useMemo(() => {\n if (searchFilter == null) {\n return null;\n }\n return renderFilterControl(searchFilter);\n }, [renderFilterControl, searchFilter]);\n\n const sortNode = useMemo(() => {\n if (listConfig.sorts.length === 0) {\n return null;\n }\n const firstSort = listConfig.sorts[0];\n if (firstSort == null) {\n return null;\n }\n const options = listConfig.sorts.map((s) => {\n return { id: s.id, value: s.id, label: resolveLabel(s.label, tApp) };\n });\n return (\n <SimpleSelect\n options={options}\n value={state.sort ?? firstSort.id}\n size=\"small\"\n ariaLabel={t('list.sort.label')}\n onChange={(next) => {\n pushState({\n ...state,\n sort: next,\n });\n }}\n />\n );\n }, [listConfig.sorts, pushState, state, t, tApp]);\n\n const chipsNode = useMemo(() => {\n if (chips.length === 0) {\n return null;\n }\n return <FilterChipRow chips={chips} onClearAll={handleClearAll} />;\n }, [chips, handleClearAll]);\n\n const drawerSections = useMemo(() => {\n if (drawerFilters.length === 0) {\n return [];\n }\n\n const normalizedQuery = filterSearch.trim().toLowerCase();\n const items: { id: string; node: JSX.Element }[] = [];\n\n for (const filter of drawerFilters) {\n const resolvedLabel = resolveLabel(filter.label, tApp);\n const matchesQuery =\n normalizedQuery === '' ||\n resolvedLabel.toLowerCase().includes(normalizedQuery);\n\n if (matchesQuery) {\n items.push({\n id: filter.id,\n node: (\n <BackofficeFilterField label={resolvedLabel}>\n {renderFilterControl(filter)}\n </BackofficeFilterField>\n ),\n });\n }\n }\n\n if (items.length === 0) {\n return [];\n }\n\n return [\n {\n id: 'backoffice.filters.sections.default',\n title: t('filters.sections.default'),\n items,\n },\n ];\n }, [drawerFilters, filterSearch, renderFilterControl, t, tApp]);\n\n const allFiltersNode = useMemo(() => {\n if (drawerFilters.length === 0) {\n return null;\n }\n const activeCount = chips.length;\n let label = t('filters.trigger');\n if (activeCount > 0) {\n label = t('filters.triggerWithCount', {\n count: activeCount,\n });\n }\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsFilterDrawerOpen(true);\n }}\n >\n {label}\n </Button>\n );\n }, [chips.length, drawerFilters.length, setIsFilterDrawerOpen, t]);\n\n const filterDrawerEmptyLabel =\n filterSearch.trim() === ''\n ? undefined\n : t('filters.drawer.emptySearchResults');\n\n const filterDrawerNode = (\n <BackofficeFilterDrawer\n isOpen={isFilterDrawerOpen}\n onClose={() => {\n resetFilterDrawer();\n }}\n sections={drawerSections}\n searchValue={filterSearch}\n onSearchChange={(next) => {\n setFilterSearch(next);\n }}\n onReset={handleClearAll}\n emptyLabel={filterDrawerEmptyLabel}\n />\n );\n\n const resolvedEmptyState = useMemo((): JSX.Element => {\n if (emptyState != null) {\n return emptyState;\n }\n\n if (isLoadingInitial) {\n return (\n <BackofficeTableSkeleton\n variant=\"embedded\"\n ariaLabel={t('common.loading')}\n />\n );\n }\n\n if (chips.length > 0) {\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmptyFiltered.description')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleClearAll}\n >\n {t('emptyState.listEmptyFiltered.actions.reset')}\n </Button>\n }\n />\n );\n }\n\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmpty.description')}\n />\n );\n }, [chips.length, emptyState, handleClearAll, isLoadingInitial, t]);\n\n const tableFooterMeta = useMemo((): ReactNode => {\n if (loadedCountLabel != null) {\n return loadedCountLabel;\n }\n if (typeof totalCount !== 'number') {\n if (rows.length === 0) {\n return null;\n }\n return (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }, [loadedCountLabel, rows.length, t, totalCount]);\n\n const runtimeConfig = useMemo(() => {\n const resolvedDisplayMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n return resolveBackofficeListRuntimeConfig({\n kind: listConfig.kind,\n displayMode: resolvedDisplayMode,\n ui: listConfig.ui,\n });\n }, [listConfig.kind, listConfig.responsive?.mode, listConfig.ui]);\n\n const hasKnownRemainingRows =\n typeof totalCount === 'number' && rows.length < totalCount;\n const hasInconsistentPageInfo = hasKnownRemainingRows && !hasNextPage;\n\n useEffect(() => {\n if (\n !hasInconsistentPageInfo ||\n !runtimeConfig.infiniteScroll.showInconsistentPageInfo ||\n !isDevEnv()\n ) {\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(\n 'Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.',\n {\n entityId: config.id,\n loadedCount: rows.length,\n totalCount,\n },\n );\n }, [\n config.id,\n hasInconsistentPageInfo,\n rows.length,\n runtimeConfig.infiniteScroll.showInconsistentPageInfo,\n totalCount,\n ]);\n\n const shouldVirtualizeTable =\n props.virtualize === true || runtimeConfig.virtualization.enabled;\n\n const { sentinelRef } = useBackofficeInfiniteScrollSentinel({\n enabled: !shouldVirtualizeTable && runtimeConfig.infiniteScroll.enabled,\n hasNextPage,\n isLoading: isLoadingMore,\n onIntersect: onLoadMore,\n rootMargin: runtimeConfig.infiniteScroll.rootMargin,\n threshold: runtimeConfig.infiniteScroll.threshold,\n });\n\n const headerTitle = header?.title ?? resolveLabel(listConfig.title, tApp);\n const headerSubtitle = header?.subtitle;\n\n const actionColumn = columnsWithPrimary.find((column) => {\n return column.mobileRole === 'action' || column.id === 'actions';\n });\n const listMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n const listDensity =\n listConfig.ui?.density ?? listConfig.responsive?.density ?? 'compact';\n\n const tableInnerNode = shouldVirtualizeTable ? (\n <VirtualizedConnectionTable\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n virtualization={runtimeConfig.virtualization}\n infiniteScroll={{\n enabled: runtimeConfig.infiniteScroll.enabled,\n thresholdPx: runtimeConfig.infiniteScroll.thresholdPx,\n autoLoad: runtimeConfig.infiniteScroll.autoLoad,\n }}\n hasNextPage={hasNextPage}\n isLoadingMore={isLoadingMore}\n onLoadMore={onLoadMore}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n ) : (\n <ResponsiveRecordList\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n mode={listMode}\n density={listDensity}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n bodyFooterNode={\n runtimeConfig.infiniteScroll.enabled ? (\n <div ref={sentinelRef} aria-hidden=\"true\" />\n ) : null\n }\n renderAction={(row) => {\n return actionColumn?.cell(row) ?? null;\n }}\n />\n );\n\n const tableNodeWithErrorBoundary = (\n <BackofficeErrorBoundary\n fallback={(args: { error: unknown; reset: () => void }) => {\n const { reset } = args;\n\n const retry = (): void => {\n reset();\n if (onRefresh != null) {\n onRefresh();\n }\n };\n\n return (\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={retry}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n );\n }}\n >\n {tableInnerNode}\n </BackofficeErrorBoundary>\n );\n\n const filtersBarNode = showFilters ? (\n <>\n <BackofficeToolbar\n search={searchNode}\n primaryFilters={quickFiltersNode}\n filterDrawerTrigger={allFiltersNode}\n sort={sortNode}\n utilityActions={\n onRefresh == null ? null : (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n isLoading={isRefreshing}\n loadingLabel={t('list.actions.refreshing')}\n onClick={() => {\n onRefresh();\n }}\n >\n {t('list.actions.refresh')}\n </Button>\n )\n }\n chips={chipsNode}\n density=\"compact\"\n />\n {filterDrawerNode}\n </>\n ) : null;\n\n const tableNode = (\n <div\n className={styles.tableHost}\n aria-busy={isRefreshing ? 'true' : undefined}\n >\n {isRefreshing && !isLoadingInitial ? (\n <div className={styles.refreshingIndicator} role=\"status\">\n <Spinner size={14} ariaLabel={t('list.refreshingRows')} />\n <span>{t('list.refreshingRows')}</span>\n </div>\n ) : null}\n {tableNodeWithErrorBoundary}\n <EntityIdPickerDialog\n isOpen={pickerDialog != null}\n entity={pickerDialog?.entity ?? config.id}\n title={pickerDialog?.label ?? t('picker.title')}\n scope={pickerDialog?.scope}\n onClose={() => {\n setPickerDialog(null);\n }}\n onSelectId={(id) => {\n if (pickerDialog == null) {\n return;\n }\n if (pickerDialog.mode === 'list') {\n const currentIds = pickerDialog.currentIds ?? [];\n const nextIds = currentIds.includes(id)\n ? currentIds\n : [...currentIds, id];\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n nextIds,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n return;\n }\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n id,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n }}\n />\n </div>\n );\n\n const shouldRenderTableFooter =\n rows.length > 0 || isLoadingMore || hasNextPage;\n\n const tableFooterNode = shouldRenderTableFooter ? (\n <>\n <BackofficeListFooter\n mode=\"status\"\n loadedCount={rows.length}\n totalCount={totalCount}\n hasNextPage={hasNextPage}\n isLoading={isLoadingMore}\n pageInfoState={\n hasInconsistentPageInfo\n ? 'inconsistent'\n : isLoadingMore\n ? 'loading'\n : hasNextPage\n ? 'ready'\n : 'complete'\n }\n labels={{\n loaded: tableFooterMeta,\n loading: t('list.loadMore.loading'),\n end: t('list.loadMore.end'),\n }}\n />\n </>\n ) : null;\n\n if (variant === 'embedded') {\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <div className={styles.embeddedContainer}>\n <div className={styles.embeddedHeader}>{headerTitle}</div>\n {filtersBarNode}\n {statusBanner}\n {tableNode}\n {tableFooterNode}\n </div>\n </BackofficeListFilterProvider>\n );\n }\n\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <ListPageTemplate\n headerNode={\n <BackofficePageHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n />\n }\n toolbarNode={filtersBarNode}\n statusNode={statusBanner}\n tableNode={tableNode}\n tableFooterNode={tableFooterNode}\n presentation=\"flat\"\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n </BackofficeListFilterProvider>\n );\n};\n\nexport default BackofficeEntityListScaffold;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAM,KAAgB,GAAkB,MAC/B,EAAM,CAAI,GAGb,MACJ,GACA,MACY;CACZ,IAAI,EAAO,eAAe,QAAQ,KAAS,MACzC,OAAO,EAAO,YAAY,CAAK;CAGjC,IAAM,IAAO,EAAO,YAAY,EAAO;CACvC,OAAO,EAAe,GAAO,GAAK,EAAO,IAAI;AAC/C,GAEM,MAAwB,MACvB,MAAM,QAAQ,CAAK,IAGjB,EACJ,KAAK,MAAU;CACd,IAAI,KAAS,MACX,OAAO;CAET,IAAM,IAAa,OAAO,CAAK,CAAC,CAAC,KAAK;CAItC,OAHI,MAAe,KACV,OAEF;AACT,CAAC,CAAC,CACD,QAAQ,MACA,KAAS,IACjB,IAfM,CAAC,GAkBN,MACJ,GACA,GACA,MAKqB;CACrB,IAAI,KAAO,MACT,OAAO;CAGT,IAAI,MAAM,QAAQ,CAAG,GAAG;EACtB,IAAM,IAAa,GAAqB,CAAG;EAqB3C,OAnBI,EAAW,WAAW,IACjB,OAGL,EAAO,SAAS,iBAEhB,kBAAA,GAAA,EAAA,UACG,EAAW,KAAK,GAAI,MAEjB,kBAAC,QAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAmB,UAAU,EAAO;GAAY;EAAK,CAAA,GACpD,IAAQ,EAAW,SAAS,IAAI,OAAO,IACpC,EAAA,GAHK,CAGL,CAET,EACD,CAAA,IAIC,EAAW,KAAK,IAAI;CAC7B;CAEA,IAAI,OAAO,KAAQ,WAOjB,OANI,EAAO,SAAS,YACX,EAAQ,aAAa,CAAG,IAE7B,IACK,EAAQ,sBAAsB,MAEhC,EAAQ,sBAAsB;CAGvC,IAAI,OAAO,KAAQ,YAAY,OAAO,KAAQ,UAC5C,OAAO;CAGT,IAAM,IAAY,OAAO,CAAG,CAAC,CAAC,KAAK;CAanC,OAZI,MAAc,KACT,OAGL,EAAO,SAAS,aACX,kBAAC,GAAD;EAAmB,UAAU,EAAO;EAAQ,IAAI;CAAY,CAAA,IAGjE,EAAO,SAAS,SACX,EAAQ,UAAU,CAAS,IAG7B;AACT,GAEM,MAAwB,MAA0B;CACtD,IAAM,IAAO,IAAI,KAAK,CAAK;CAC3B,IAAI,OAAO,MAAM,EAAK,QAAQ,CAAC,GAC7B,OAAO;CAET,IAAM,IAAW,EAAK,kBAAkB,IAAI;CAC5C,OAAO,IAAI,KAAK,EAAK,QAAQ,IAAI,CAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;AACtE,GAEM,MAA0B,MAA0B;CACxD,IAAM,IAAa,EAAM,KAAK;CAC9B,IAAI,MAAe,IACjB,OAAO;CAET,IAAM,IAAO,IAAI,KAAK,CAAU;CAIhC,OAHI,OAAO,MAAM,EAAK,QAAQ,CAAC,IACtB,IAEF,EAAK,YAAY;AAC1B,GAkCa,KACX,MACuB;CACvB,IAAM,EAAE,GAAG,MAAS,GAAe,GAC7B,EAAE,SAAM,EAA8B,GACtC,EACJ,WACA,UACA,cACA,SACA,aACA,YACA,yBACA,gBACA,kBACA,kBAAe,IACf,gBACA,cACA,eACA,sBACA,gBACA,kBACA,YACA,mBACA,sBAAmB,IACnB,cAAU,QACV,kBAAc,OACZ,GACE,IAAa,EAAO,MACpB,EAAE,qBAAiB,GAEnB,IAAqB,QACN,EAAQ,MAAM,MACxB,EAAI,cAAc,EAEvB,KAAc,EAAQ,WAAW,IAC5B,IAEF,EAAQ,KAAK,GAAK,MAAU;EACjC,IAAM,EAAE,cAAW;EAInB,OAHI,MAAU,IACL;GAAE,GAAG;GAAK,WAAW;GAAM;EAAO,IAEpC;GAAE,GAAG;GAAK;EAAO;CAC1B,CAAC,GACA,CAAC,CAAO,CAAC,GAEN,IAAQ,QAAqC;EACjD,IAAM,IAAoB,CAAC;EAC3B,KAAK,IAAM,KAAU,EAAW,SAAS;GACvC,IAAM,IAAM,GAAe,GAAQ,EAAM,KAAK,GACxC,IAAe,GAAsB,GAAQ,GAAK;IACtD,YAAY,MAAU;KACpB,IAAI,EAAO,SAAS,QAClB,OAAO;KAET,IAAM,IAAQ,EAAO,QAAQ,MAAM,MAC1B,EAAO,UAAU,CACzB;KAID,OAHI,KAAS,OAGN,IAFE,EAAa,EAAM,OAAO,CAAI;IAGzC;IACA,eAAe,MAAU;KACvB,IAAI,EAAO,SAAS,WAAW;MAC7B,IAAI,KAAS,EAAO,aAAa,MAC/B,OAAO,EAAa,EAAO,WAAW,CAAI;MAE5C,IAAI,CAAC,KAAS,EAAO,cAAc,MACjC,OAAO,EAAa,EAAO,YAAY,CAAI;KAE/C;KAIA,OAFS,EADL,IACO,wBAEF,oBAFuB;IAGlC;IACA,uBAAuB;KACrB,KAAK,EAAE,qBAAqB;KAC5B,IAAI,EAAE,oBAAoB;IAC5B;GACF,CAAC;GAED,IAAI,KAAgB,MAAM;IACxB,IAAI,IAAU,OAAO,CAAG;IACxB,AAAI,MAAM,QAAQ,CAAG,MACnB,IAAU,EAAI,KAAK,GAAG;IAExB,IAAM,IACJ,kBAAC,QAAD,EAAA,UAAA;KACG,EAAa,EAAO,OAAO,CAAI;KAAE;KAAG;IACjC,EAAA,CAAA;IAER,EAAI,KAAK;KACP,IAAI,GAAG,EAAO,GAAG,GAAG;KACpB;KACA,gBAAgB;MACd,IAAM,IAAM,EAAO,YAAY,EAAO,IAChC,IAAY,EAChB,EAAM,OACN,GACA,MACA,EAAO,IACT;MACA,EAAU;OAAE,GAAG;OAAO,OAAO;MAAU,CAAC;KAC1C;IACF,CAAC;GACH;EACF;EACA,OAAO;CACT,GAAG;EAAC,EAAW;EAAS;EAAW;EAAO;EAAG;CAAI,CAAC,GAE5C,IAAiB,SAAkB;EACvC,EAAU,EACR,GAAG,GACL,CAAC;CACH,GAAG,CAAC,IAAc,CAAS,CAAC,GACtB,CAAC,IAAyB,MAA8B,EAAS,EAAK,GACtE,CAAC,IAAmB,MAAwB,EAAS,EAAE,GACvD,IAAc,EAAM,qBAAqB;EAC7C,QAAQ;EACR,QAAQ;EACR,SAAS;EACT,WAAW;EACX,aAAa;GAEX,AADA,GAA2B,EAAK,GAChC,GAAqB,EAAE;EACzB;CACF,GACM,KAAqB,EAAY,QACjC,IAAe,EAAY,QAC3B,IAAwB,EAAY,SACpC,KAAkB,EAAY,WAC9B,KAAoB,EAAY,OAEhC,CAAC,GAAc,KAAmB,EAQ9B,IAAI,GAER,IAAsB,IACzB,MAA4D;EAC3D,IAAM,IAAM,EAAO,YAAY,EAAO,IAChC,IAAY,GAAe,GAAQ,EAAM,KAAK,GAChD,IAAQ;EAIZ,AAHI,OAAO,KAAc,aACvB,IAAQ,IAEN,OAAO,KAAc,YAAY,OAAO,SAAS,CAAS,MAC5D,IAAQ,OAAO,CAAS;EAG1B,IAAM,IAAkB,EAAa,EAAO,OAAO,CAAI;EAEvD,IAAI,EAAO,SAAS,QAAQ;GAC1B,IAAM,IACJ,EAAO,oBAAoB,OAEvB,IADA,EAAa,EAAO,kBAAkB,CAAI,GAE5C,IAAc,EAAE,+BAA+B,EACjD,OAAO,EACT,CAAC;GAID,OAHI,EAAO,mBAAmB,SAC5B,IAAc,EAAa,EAAO,iBAAiB,CAAI,IAGvD,kBAAC,GAAD;IACS;IACP,UAAU,MAAS;KACjB,IAAM,IAAY,EAChB,EAAM,OACN,GACA,GACA,EAAO,IACT;KACA,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;IACa;IACb,WAAW;IACX,WAAW;GACZ,CAAA;EAEL;EAEA,IAAI,EAAO,SAAS,YAAY;GAC9B,IAAM,IACJ,EAAO,oBAAoB,OAEvB,IADA,EAAa,EAAO,kBAAkB,CAAI,GAE5C,IAAc,EAAE,+BAA+B,EACjD,OAAO,EACT,CAAC;GAID,OAHI,EAAO,mBAAmB,SAC5B,IAAc,EAAa,EAAO,iBAAiB,CAAI,IAGvD,kBAAC,GAAD;IACE,OAAO,GAAqB,CAAK;IACjC,UAAU,MAAS;KACjB,IAAM,IAAa,GAAuB,CAAI,GACxC,IAAY,EAChB,EAAM,OACN,GACA,GACA,EAAO,IACT;KACA,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;IACa;IACb,WAAW;IACX,WAAW;IACX,MAAK;GACN,CAAA;EAEL;EAEA,IAAI,EAAO,SAAS,UAAU;GAC5B,IAAM,IACJ,EAAO,oBAAoB,OAEvB,IADA,EAAa,EAAO,kBAAkB,CAAI,GAE5C,IAAc,EAAE,+BAA+B,EACjD,OAAO,EACT,CAAC;GAID,OAHI,EAAO,mBAAmB,SAC5B,IAAc,EAAa,EAAO,iBAAiB,CAAI,IAGvD,kBAAC,GAAD;IACS;IACP,UAAU,MAAS;KACjB,IAAM,IAAa,EAAK,KAAK,GACvB,IAAS,MAAe,KAAK,OAAO,OAAO,CAAU,GACrD,IAAY,EAChB,EAAM,OACN,GACA,OAAO,SAAS,CAAM,IAAI,IAAS,MACnC,EAAO,IACT;KACA,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;IACa;IACb,WAAW;IACX,WAAW;IACX,WAAW,EAAO,aAAa;IAC/B,MAAK;GACN,CAAA;EAEL;EAEA,IAAI,EAAO,SAAS,QAAQ;GAC1B,IAAM,IAAU,CACd;IACE,IAAI;IACJ,OAAO;IACP,OAAO,EAAE,eAAe,EACtB,OAAO,EACT,CAAC;GACH,GACA,GAAG,EAAO,QAAQ,KAAK,OACd;IACL,IAAI,EAAO;IACX,OAAO,EAAO;IACd,OAAO,EAAa,EAAO,OAAO,CAAI;GACxC,EACD,CACH;GAEA,OACE,kBAAC,GAAD;IACW;IACF;IACP,MAAK;IACL,WAAW;IACX,WAAW,MAAS;KAClB,IAAM,IAAY,EAChB,EAAM,OACN,GACA,GACA,EAAO,IACT;KACA,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;GACD,CAAA;EAEL;EAEA,IAAI,EAAO,SAAS,WAAW;GAC7B,IAAI,IAA0B;GAC9B,AAAI,OAAO,KAAc,cACvB,IAAU;GAGZ,IAAI,IAAc;GAIlB,AAHI,MAAY,OACd,IAAc,SAEZ,MAAY,OACd,IAAc;GAGhB,IAAM,IACJ,EAAO,aAAa,OAEhB,EAAE,qBAAqB,IADvB,EAAa,EAAO,WAAW,CAAI,GAEnC,IACJ,EAAO,cAAc,OAEjB,EAAE,oBAAoB,IADtB,EAAa,EAAO,YAAY,CAAI,GAEpC,IAAU;IACd;KACE,IAAI;KACJ,OAAO;KACP,OAAO,EAAE,eAAe,EACtB,OAAO,EACT,CAAC;IACH;IACA;KACE,IAAI;KACJ,OAAO;KACP,OAAO;IACT;IACA;KACE,IAAI;KACJ,OAAO;KACP,OAAO;IACT;GACF;GAEA,OACE,kBAAC,GAAD;IACW;IACT,OAAO;IACP,MAAK;IACL,WAAW;IACX,WAAW,MAAS;KAClB,IAAI,IAAyB;KAI7B,AAHI,MAAS,WACX,IAAS,KAEP,MAAS,YACX,IAAS;KAEX,IAAM,IAAY,EAChB,EAAM,OACN,GACA,GACA,EAAO,IACT;KACA,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;GACD,CAAA;EAEL;EAEA,IAAM,WAAqB;GACrB,MAAO,eAAe,MAM1B,OAHI,OAAO,EAAO,eAAgB,aACzB,EAAO,YAAY,EAAM,KAAK,IAEhC,EAAO;EAChB,EAAA,CAAG;EAEH,IAAI,EAAO,SAAS,gBAAgB;GAClC,IAAM,IAAa,GAAqB,CAAS,GAC3C,IAAgB,EAAW,QAC3B,IACJ,MAAkB,IACd,OACA,EAAE,4BAA4B,EAC5B,OAAO,EACT,CAAC,GAED,KAAY,MAAqB;IACrC,IAAM,IAAU,EAAW,QAAQ,MAC1B,MAAc,CACtB,GACK,IAAY,EAChB,EAAM,OACN,GACA,EAAQ,WAAW,IAAI,OAAO,GAC9B,EAAO,IACT;IACA,EAAU;KAAE,GAAG;KAAO,OAAO;IAAU,CAAC;GAC1C;GAEA,OACE,kBAAC,OAAD;IAAK,WAAW;IAAhB,UAAA,CACE,kBAAC,GAAD;KACE,OAAO;KACP,OAAO,MAAkB,IAAI,OAAO,EAAW,KAAK,GAAG;KACzC;KACd,aAAa,EAAE,kCAAkC,EAC/C,OAAO,EACT,CAAC;KACD,cAAc;MACZ,EAAgB;OACd,QAAQ,EAAO;OACf,UAAU;OACV,OAAO;OACP,MAAM;OACN;OACA,MAAM,EAAO;OACb,OAAO;MACT,CAAC;KACH;KACA,eAAe;MACb,IAAM,IAAY,EAChB,EAAM,OACN,GACA,MACA,EAAO,IACT;MACA,EAAU;OAAE,GAAG;OAAO,OAAO;MAAU,CAAC;KAC1C;IACD,CAAA,GACA,EAAW,SAAS,IACnB,kBAAC,OAAD;KAAK,WAAW;KACb,UAAA,EAAW,KAAK,MAEb,kBAAC,IAAD;MAEE,aAAa,EAAE,qCAAqC,EAClD,OAAO,EACT,CAAC;MACD,gBAAgB;OACd,EAAS,CAAE;MACb;MAEA,UAAA,kBAAC,GAAD;OAAmB,UAAU,EAAO;OAAY;MAAK,CAAA;KAClD,GATE,CASF,CAER;IACE,CAAA,IACH,IACD;;EAET;EAEA,IAAI,EAAO,SAAS,cAAc;GAChC,IAAM,IACJ,EAAO,oBAAoB,OAEvB,IADA,EAAa,EAAO,kBAAkB,CAAI,GAE5C,IAAc,EAAE,+BAA+B,EACjD,OAAO,EACT,CAAC;GAID,OAHI,EAAO,mBAAmB,SAC5B,IAAc,EAAa,EAAO,iBAAiB,CAAI,IAGvD,kBAAC,GAAD;IACS;IACP,UAAU,MAAS;KACjB,IAAM,IAAS,EACZ,MAAM,SAAS,CAAC,CAChB,KAAK,MACG,EAAM,KAAK,CACnB,CAAC,CACD,QAAQ,MACA,MAAU,EAClB,GACG,IAAY,EAChB,EAAM,OACN,GACA,GACA,EAAO,IACT;KACA,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;IACa;IACb,WAAW;IACX,WAAW;GACZ,CAAA;EAEL;EAEA,IAAI,IAA2B;EAC/B,AAAI,OAAO,KAAc,aACvB,IAAY;EAGd,IAAM,KACJ,IAA8B,MAC9B,IAAc,OACX;GACH,IAAM,IAAyB,GAAc,KAAK,KAAK;GACvD,OACE,kBAAC,GAAD;IACE,OAAO;IACP,OAAO;IACP,cAAc;IACD;IACb,aAAa,EAAE,kCAAkC,EAC/C,OAAO,EACT,CAAC;IACD,cAAc;KACZ,EAAgB;MACd,QAAQ,EAAO;MACf,UAAU;MACV,OAAO;MACP,MAAM;MACN,MAAM,EAAO;MACb,OAAO;KACT,CAAC;IACH;IACA,eAAe;KACb,IAAM,IAAY,EAChB,EAAM,OACN,GACA,MACA,EAAO,IACT;KACA,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;GACD,CAAA;EAEL;EAMA,OAJI,KAAa,QAAQ,EAAU,KAAK,MAAM,KACrC,EAAY,IAInB,kBAAC,GAAD;GAAuB,UAAU,EAAO;GAAQ,IAAI;GAChD,WAAA,GAAO,MAAe;IACtB,IAAM,IAAc,GAAY,WAAW;IAC3C,OAAO,EACL,IAAc,EAAE,gBAAgB,IAAI,GACpC,CACF;GACF;EACqB,CAAA;CAE3B,GACA;EAAC;EAAW;EAAO;EAAG;CAAI,CAC5B,GAEM,KAAqB,QAClB,EAAW,QAAQ,MAAM,MACvB,EAAO,aAAa,IAC5B,GACA,CAAC,EAAW,OAAO,CAAC,GAEjB,IAAe,QAAc;EACjC,IAAI,EAAW,QAAQ,WAAW,GAChC,OAAO,CAAC;EAEV,IAAM,IAAqB,EAAW,IAAI,SAAS,sBAAsB;EAMzE,OALI,KACK,EAAW,QAAQ,QAAQ,MACzB,EAAO,cAAc,WAAW,EAAO,cAAc,MAC7D,IAEI,EAAW,QAAQ,MAAM,GAAG,CAAkB;CACvD,GAAG;EAAC,EAAW;EAAS,EAAW,IAAI;EAAS;CAAkB,CAAC,GAE7D,IAAgB,QACb,EAAW,QAAQ,QAAQ,MAC5B,EAAO,aAAa,QAGjB,EAAO,cAAc,YAAY,EAAO,cAAc,MAC9D,GACA,CAAC,EAAW,OAAO,CAAC,GAEjB,IAAe,QACZ,EAAa,MAAM,MACjB,EAAO,SAAS,MACxB,GACA,CAAC,CAAY,CAAC,GAEX,KAAmB,QAAc;EACrC,IAAM,IAAsB,EAAa,QAAQ,MACxC,MAAW,CACnB;EAMD,OAJI,EAAoB,WAAW,IAC1B,OAIP,kBAAC,OAAD;GAAK,WAAW;GACb,UAAA,EAAoB,KAAK,MACjB,kBAAC,QAAD,EAAA,UAAuB,EAAoB,CAAM,EAAQ,GAA9C,EAAO,EAAuC,CACjE;EACE,CAAA;CAET,GAAG;EAAC;EAAc;EAAqB;CAAY,CAAC,GAE9C,KAAa,QACb,KAAgB,OACX,OAEF,EAAoB,CAAY,GACtC,CAAC,GAAqB,CAAY,CAAC,GAEhC,KAAW,QAAc;EAC7B,IAAI,EAAW,MAAM,WAAW,GAC9B,OAAO;EAET,IAAM,IAAY,EAAW,MAAM;EACnC,IAAI,KAAa,MACf,OAAO;EAET,IAAM,IAAU,EAAW,MAAM,KAAK,OAC7B;GAAE,IAAI,EAAE;GAAI,OAAO,EAAE;GAAI,OAAO,EAAa,EAAE,OAAO,CAAI;EAAE,EACpE;EACD,OACE,kBAAC,GAAD;GACW;GACT,OAAO,EAAM,QAAQ,EAAU;GAC/B,MAAK;GACL,WAAW,EAAE,iBAAiB;GAC9B,WAAW,MAAS;IAClB,EAAU;KACR,GAAG;KACH,MAAM;IACR,CAAC;GACH;EACD,CAAA;CAEL,GAAG;EAAC,EAAW;EAAO;EAAW;EAAO;EAAG;CAAI,CAAC,GAE1C,KAAY,QACZ,EAAM,WAAW,IACZ,OAEF,kBAAC,IAAD;EAAsB;EAAO,YAAY;CAAiB,CAAA,GAChE,CAAC,GAAO,CAAc,CAAC,GAEpB,KAAiB,QAAc;EACnC,IAAI,EAAc,WAAW,GAC3B,OAAO,CAAC;EAGV,IAAM,IAAkB,EAAa,KAAK,CAAC,CAAC,YAAY,GAClD,IAA6C,CAAC;EAEpD,KAAK,IAAM,KAAU,GAAe;GAClC,IAAM,IAAgB,EAAa,EAAO,OAAO,CAAI;GAKrD,CAHE,MAAoB,MACpB,EAAc,YAAY,CAAC,CAAC,SAAS,CAAe,MAGpD,EAAM,KAAK;IACT,IAAI,EAAO;IACX,MACE,kBAAC,IAAD;KAAuB,OAAO;KAC3B,UAAA,EAAoB,CAAM;IACN,CAAA;GAE3B,CAAC;EAEL;EAMA,OAJI,EAAM,WAAW,IACZ,CAAC,IAGH,CACL;GACE,IAAI;GACJ,OAAO,EAAE,0BAA0B;GACnC;EACF,CACF;CACF,GAAG;EAAC;EAAe;EAAc;EAAqB;EAAG;CAAI,CAAC,GAExD,KAAiB,QAAc;EACnC,IAAI,EAAc,WAAW,GAC3B,OAAO;EAET,IAAM,IAAc,EAAM,QACtB,IAAQ,EAAE,iBAAiB;EAM/B,OALI,IAAc,MAChB,IAAQ,EAAE,4BAA4B,EACpC,OAAO,EACT,CAAC,IAGD,kBAAC,GAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,eAAe;IACb,EAAsB,EAAI;GAC5B;GAEC,UAAA;EACK,CAAA;CAEZ,GAAG;EAAC,EAAM;EAAQ,EAAc;EAAQ;EAAuB;CAAC,CAAC,GAE3D,KACJ,EAAa,KAAK,MAAM,KACpB,KAAA,IACA,EAAE,mCAAmC,GAErC,KACJ,kBAAC,IAAD;EACE,QAAQ;EACR,eAAe;GACb,GAAkB;EACpB;EACA,UAAU;EACV,aAAa;EACb,iBAAiB,MAAS;GACxB,GAAgB,CAAI;EACtB;EACA,SAAS;EACT,YAAY;CACb,CAAA,GAGG,KAAqB,QACrB,OAIA,IAEA,kBAAC,IAAD;EACE,SAAQ;EACR,WAAW,EAAE,gBAAgB;CAC9B,CAAA,IAID,EAAM,SAAS,IAEf,kBAAC,GAAD;EACE,OAAO,EAAE,4BAA4B;EACrC,aAAa,EAAE,0CAA0C;EACzD,SACE,kBAAC,GAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,SAAS;GAER,UAAA,EAAE,4CAA4C;EACzC,CAAA;CAEX,CAAA,IAKH,kBAAC,GAAD;EACE,OAAO,EAAE,4BAA4B;EACrC,aAAa,EAAE,kCAAkC;CAClD,CAAA,IAEF;EAAC,EAAM;EAAQ;EAAY;EAAgB;EAAkB;CAAC,CAAC,GAE5D,KAAkB,QAClB,OAGA,OAAO,KAAe,WAaxB,kBAAC,QAAD,EAAA,UACG,EAAE,gBAAgB;EACjB,OAAO,EAAK;EACZ,OAAO;CACT,CAAC,EACG,CAAA,IAjBF,EAAK,WAAW,IACX,OAGP,kBAAC,QAAD,EAAA,UACG,EAAE,eAAe,EAChB,OAAO,EAAK,OACd,CAAC,EACG,CAAA,IAWT;EAAC;EAAkB,EAAK;EAAQ;EAAG;CAAU,CAAC,GAE3C,IAAgB,QAAc;EAClC,IAAM,IACJ,EAAW,IAAI,eAAe,EAAW,YAAY,QAAQ;EAC/D,OAAO,GAAmC;GACxC,MAAM,EAAW;GACjB,aAAa;GACb,IAAI,EAAW;EACjB,CAAC;CACH,GAAG;EAAC,EAAW;EAAM,EAAW,YAAY;EAAM,EAAW;CAAE,CAAC,GAI1D,IADJ,OAAO,KAAe,YAAY,EAAK,SAAS,KACO,CAAC;CAE1D,SAAgB;EAEZ,CAAC,KACD,CAAC,EAAc,eAAe,4BAC9B,CAAC,EAAS,KAKZ,QAAQ,KACN,mHACA;GACE,UAAU,EAAO;GACjB,aAAa,EAAK;GAClB;EACF,CACF;CACF,GAAG;EACD,EAAO;EACP;EACA,EAAK;EACL,EAAc,eAAe;EAC7B;CACF,CAAC;CAED,IAAM,KACJ,EAAM,eAAe,MAAQ,EAAc,eAAe,SAEtD,EAAE,oBAAgB,EAAoC;EAC1D,SAAS,CAAC,MAAyB,EAAc,eAAe;EAChE;EACA,WAAW;EACX,aAAa;EACb,YAAY,EAAc,eAAe;EACzC,WAAW,EAAc,eAAe;CAC1C,CAAC,GAEK,KAAc,IAAQ,SAAS,EAAa,EAAW,OAAO,CAAI,GAClE,KAAiB,IAAQ,UAEzB,KAAe,EAAmB,MAAM,MACrC,EAAO,eAAe,YAAY,EAAO,OAAO,SACxD,GACK,KACJ,EAAW,IAAI,eAAe,EAAW,YAAY,QAAQ,QACzD,KACJ,EAAW,IAAI,WAAW,EAAW,YAAY,WAAW,WAExD,KAAiB,KACrB,kBAAC,IAAD;EACE,SAAS;EACH;EACI;EACV,YAAY;EACZ,WAAW;EACU;EACrB,gBAAgB,EAAc;EAC9B,gBAAgB;GACd,SAAS,EAAc,eAAe;GACtC,aAAa,EAAc,eAAe;GAC1C,UAAU,EAAc,eAAe;EACzC;EACa;EACE;EACH;EACZ,gBAAgB;CACjB,CAAA,IAED,kBAAC,IAAD;EACE,SAAS;EACH;EACI;EACV,YAAY;EACZ,WAAW;EACU;EACrB,MAAM;EACN,SAAS;EACT,gBAAgB;EAChB,gBACE,EAAc,eAAe,UAC3B,kBAAC,OAAD;GAAK,KAAK;GAAa,eAAY;EAAQ,CAAA,IACzC;EAEN,eAAe,MACN,IAAc,KAAK,CAAG,KAAK;CAErC,CAAA,GAGG,KACJ,kBAAC,GAAD;EACE,WAAW,MAAgD;GACzD,IAAM,EAAE,aAAU;GASlB,OACE,kBAAC,IAAD;IACE,MAAK;IACL,OAAO,EAAE,mBAAmB;IAC5B,SACE,kBAAC,GAAD;KACE,MAAK;KACL,SAAQ;KACR,MAAK;KACL,eAhBkB;MAExB,AADA,EAAM,GACF,IACQ;KAEd;KAaS,UAAA,EAAE,oBAAoB;IACjB,CAAA;IAGT,UAAA,EAAE,yBAAyB;GAChB,CAAA;EAElB;EAEC,UAAA;CACsB,CAAA,GAGrB,KAAiB,KACrB,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,IAAD;EACE,QAAQ;EACR,gBAAgB;EAChB,qBAAqB;EACrB,MAAM;EACN,gBACE,KAAa,OAAO,OAClB,kBAAC,GAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,WAAW;GACX,cAAc,EAAE,yBAAyB;GACzC,eAAe;IACb,EAAU;GACZ;GAEC,UAAA,EAAE,sBAAsB;EACnB,CAAA;EAGZ,OAAO;EACP,SAAQ;CACT,CAAA,GACA,EACD,EAAA,CAAA,IACA,MAEE,KACJ,kBAAC,OAAD;EACE,WAAW;EACX,aAAW,IAAe,SAAS,KAAA;EAFrC,UAAA;GAIG,KAAgB,CAAC,IAChB,kBAAC,OAAD;IAAK,WAAW;IAA4B,MAAK;IAAjD,UAAA,CACE,kBAAC,IAAD;KAAS,MAAM;KAAI,WAAW,EAAE,qBAAqB;IAAI,CAAA,GACzD,kBAAC,QAAD,EAAA,UAAO,EAAE,qBAAqB,EAAQ,CAAA,CACnC;GACH,CAAA,IAAA;GACH;GACD,kBAAC,GAAD;IACE,QAAQ,KAAgB;IACxB,QAAQ,GAAc,UAAU,EAAO;IACvC,OAAO,GAAc,SAAS,EAAE,cAAc;IAC9C,OAAO,GAAc;IACrB,eAAe;KACb,EAAgB,IAAI;IACtB;IACA,aAAa,MAAO;KAClB,IAAI,KAAgB,MAClB;KAEF,IAAI,EAAa,SAAS,QAAQ;MAChC,IAAM,IAAa,EAAa,cAAc,CAAC,GACzC,IAAU,EAAW,SAAS,CAAE,IAClC,IACA,CAAC,GAAG,GAAY,CAAE,GAChB,IAAY,EAChB,EAAM,OACN,EAAa,UACb,GACA,EAAa,IACf;MAEA,AADA,EAAsB,EAAI,GAC1B,EAAU;OAAE,GAAG;OAAO,OAAO;MAAU,CAAC;MACxC;KACF;KACA,IAAM,IAAY,EAChB,EAAM,OACN,EAAa,UACb,GACA,EAAa,IACf;KAEA,AADA,EAAsB,EAAI,GAC1B,EAAU;MAAE,GAAG;MAAO,OAAO;KAAU,CAAC;IAC1C;GACD,CAAA;EACE;KAMD,IAFJ,EAAK,SAAS,KAAK,KAAiB,IAGpC,kBAAA,GAAA,EAAA,UACE,kBAAC,IAAD;EACE,MAAK;EACL,aAAa,EAAK;EACN;EACC;EACb,WAAW;EACX,eACE,IACI,iBACA,IACE,YACA,IACE,UACA;EAEV,QAAQ;GACN,QAAQ;GACR,SAAS,EAAE,uBAAuB;GAClC,KAAK,EAAE,mBAAmB;EAC5B;CACD,CAAA,EACD,CAAA,IACA;CAoBJ,OAlBI,OAAY,aAEZ,kBAAC,GAAD;EACU;EACD;EACI;EAEX,UAAA,kBAAC,OAAD;GAAK,WAAW;GAAhB,UAAA;IACE,kBAAC,OAAD;KAAK,WAAW;KAAwB,UAAA;IAAiB,CAAA;IACxD;IACA;IACA;IACA;GACE;;CACuB,CAAA,IAKhC,kBAAC,GAAD;EACU;EACD;EACI;EAEX,UAAA,kBAAC,IAAD;GACE,YACE,kBAAC,IAAD;IACE,OAAO;IACP,UAAU;IACV,SAAS;GACV,CAAA;GAEH,aAAa;GACb,YAAY;GACD;GACM;GACjB,cAAa;GACb,gBAAgB;EACjB,CAAA;CAC2B,CAAA;AAElC"}
|
|
@@ -1,40 +1,31 @@
|
|
|
1
1
|
import { createContext as e, useCallback as t, useContext as n, useMemo as r } from "react";
|
|
2
2
|
import { jsx as i } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { setWhereValue as o } from "@plumile/backoffice-core/filters/where.js";
|
|
3
|
+
import { setWhereValue as a } from "@plumile/backoffice-core/filters/where.js";
|
|
5
4
|
//#region src/components/backoffice/scaffolds/BackofficeListFilterContext.tsx
|
|
6
|
-
var
|
|
7
|
-
let { config: n, state:
|
|
8
|
-
let r =
|
|
9
|
-
|
|
10
|
-
...
|
|
5
|
+
var o = e(null), s = (e) => {
|
|
6
|
+
let { config: n, state: s, pushState: c, children: l } = e, u = t((e, t, n) => {
|
|
7
|
+
let r = a(s.where, e, t, n);
|
|
8
|
+
c({
|
|
9
|
+
...s,
|
|
11
10
|
where: r
|
|
12
11
|
});
|
|
13
|
-
}, [
|
|
14
|
-
let i = o(c.where, e, t, r);
|
|
15
|
-
return a(n, {
|
|
16
|
-
...c,
|
|
17
|
-
where: i
|
|
18
|
-
});
|
|
19
|
-
}, [n, c]), p = r(() => ({
|
|
12
|
+
}, [c, s]), d = r(() => ({
|
|
20
13
|
config: n,
|
|
21
|
-
state:
|
|
22
|
-
pushState:
|
|
23
|
-
applyFilter:
|
|
24
|
-
buildFilterLink: f
|
|
14
|
+
state: s,
|
|
15
|
+
pushState: c,
|
|
16
|
+
applyFilter: u
|
|
25
17
|
}), [
|
|
26
|
-
|
|
27
|
-
f,
|
|
18
|
+
u,
|
|
28
19
|
n,
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
c,
|
|
21
|
+
s
|
|
31
22
|
]);
|
|
32
|
-
return /* @__PURE__ */ i(
|
|
33
|
-
value:
|
|
34
|
-
children:
|
|
23
|
+
return /* @__PURE__ */ i(o.Provider, {
|
|
24
|
+
value: d,
|
|
25
|
+
children: l
|
|
35
26
|
});
|
|
36
|
-
},
|
|
27
|
+
}, c = () => n(o);
|
|
37
28
|
//#endregion
|
|
38
|
-
export {
|
|
29
|
+
export { s as BackofficeListFilterProvider, o as default, c as useBackofficeListFilterContext };
|
|
39
30
|
|
|
40
31
|
//# sourceMappingURL=BackofficeListFilterContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeListFilterContext.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeListFilterContext.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useMemo,\n type JSX,\n type ReactNode,\n} from 'react';\n\nimport type {\n BackofficeListState,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\nimport {
|
|
1
|
+
{"version":3,"file":"BackofficeListFilterContext.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeListFilterContext.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useMemo,\n type JSX,\n type ReactNode,\n} from 'react';\n\nimport type {\n BackofficeListState,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\n\nexport type BackofficeListFilterContextValue = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<Record<string, unknown>, string>;\n pushState: (\n next: BackofficeListState<Record<string, unknown>, string>,\n ) => void;\n applyFilter: (\n whereKey: string,\n value: unknown,\n path?: readonly string[],\n ) => void;\n};\n\nconst BackofficeListFilterContext =\n createContext<BackofficeListFilterContextValue | null>(null);\n\ntype ProviderProps<\n Where extends Record<string, unknown>,\n Sort extends string,\n> = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<Where, Sort>;\n pushState: (next: BackofficeListState<Where, Sort>) => void;\n children: ReactNode;\n};\n\nexport const BackofficeListFilterProvider = <\n Where extends Record<string, unknown>,\n Sort extends string,\n>(\n props: ProviderProps<Where, Sort>,\n): JSX.Element => {\n const { config, state, pushState, children } = props;\n\n const applyFilter = useCallback(\n (whereKey: string, value: unknown, path?: readonly string[]) => {\n const nextWhere = setWhereValue(\n state.where,\n whereKey as keyof Where,\n value,\n path,\n );\n pushState({ ...state, where: nextWhere });\n },\n [pushState, state],\n );\n\n const contextValue = useMemo<BackofficeListFilterContextValue>(() => {\n return {\n config,\n state,\n pushState: pushState as BackofficeListFilterContextValue['pushState'],\n applyFilter,\n };\n }, [applyFilter, config, pushState, state]);\n\n return (\n <BackofficeListFilterContext.Provider value={contextValue}>\n {children}\n </BackofficeListFilterContext.Provider>\n );\n};\n\nexport const useBackofficeListFilterContext =\n (): BackofficeListFilterContextValue | null => {\n return useContext(BackofficeListFilterContext);\n };\n\nexport default BackofficeListFilterContext;\n"],"mappings":";;;;AA4BA,IAAM,IACJ,EAAuD,IAAI,GAYhD,KAIX,MACgB;CAChB,IAAM,EAAE,WAAQ,UAAO,cAAW,gBAAa,GAEzC,IAAc,GACjB,GAAkB,GAAgB,MAA6B;EAC9D,IAAM,IAAY,EAChB,EAAM,OACN,GACA,GACA,CACF;EACA,EAAU;GAAE,GAAG;GAAO,OAAO;EAAU,CAAC;CAC1C,GACA,CAAC,GAAW,CAAK,CACnB,GAEM,IAAe,SACZ;EACL;EACA;EACW;EACX;CACF,IACC;EAAC;EAAa;EAAQ;EAAW;CAAK,CAAC;CAE1C,OACE,kBAAC,EAA4B,UAA7B;EAAsC,OAAO;EAC1C;CACmC,CAAA;AAE1C,GAEa,UAEF,EAAW,CAA2B"}
|
|
@@ -2,39 +2,42 @@ import { startTransition as e, useCallback as t, useContext as n, useMemo as r }
|
|
|
2
2
|
import i from "@plumile/router/routing/RoutingContext.js";
|
|
3
3
|
import a from "@plumile/router/routing/useLocation.js";
|
|
4
4
|
//#region src/hooks/useBackofficeListUrlState.ts
|
|
5
|
-
function o(
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
function s(s) {
|
|
9
|
-
let c = n(i), { hash: l, pathname: u, search: d } = a(), f = r(() => ({
|
|
10
|
-
where: null,
|
|
11
|
-
sort: null
|
|
12
|
-
}), []);
|
|
5
|
+
function o(o) {
|
|
6
|
+
let s = n(i), { hash: c, pathname: l } = a(), { listNavigation: u } = o, d = s?.get();
|
|
13
7
|
return {
|
|
14
|
-
state: r(() =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
state: r(() => {
|
|
9
|
+
if (d == null) return {
|
|
10
|
+
where: null,
|
|
11
|
+
sort: null
|
|
12
|
+
};
|
|
13
|
+
let e = {};
|
|
14
|
+
typeof d.query.sort == "string" && (e.sort = d.query.sort);
|
|
15
|
+
let t = d.filters;
|
|
16
|
+
return u.decode({
|
|
17
|
+
filters: t,
|
|
18
|
+
query: e
|
|
19
|
+
});
|
|
20
|
+
}, [u, d]),
|
|
19
21
|
pushState: t((t) => {
|
|
20
|
-
if (
|
|
21
|
-
let n =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
pathname:
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
if (s == null) return;
|
|
23
|
+
let n = u.encode(t);
|
|
24
|
+
e(() => {
|
|
25
|
+
s.navigate({
|
|
26
|
+
pathname: l,
|
|
27
|
+
filters: n.filters,
|
|
28
|
+
query: n.query,
|
|
29
|
+
hash: c
|
|
27
30
|
});
|
|
28
31
|
});
|
|
29
32
|
}, [
|
|
30
|
-
|
|
31
|
-
l,
|
|
33
|
+
c,
|
|
32
34
|
u,
|
|
33
|
-
|
|
35
|
+
l,
|
|
36
|
+
s
|
|
34
37
|
])
|
|
35
38
|
};
|
|
36
39
|
}
|
|
37
40
|
//#endregion
|
|
38
|
-
export {
|
|
41
|
+
export { o as useBackofficeListUrlState };
|
|
39
42
|
|
|
40
43
|
//# sourceMappingURL=useBackofficeListUrlState.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBackofficeListUrlState.js","names":[],"sources":["../../../src/hooks/useBackofficeListUrlState.ts"],"sourcesContent":["import { startTransition, useCallback, useContext, useMemo } from 'react';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\n\nimport type {\n BackofficeListState,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\n\
|
|
1
|
+
{"version":3,"file":"useBackofficeListUrlState.js","names":[],"sources":["../../../src/hooks/useBackofficeListUrlState.ts"],"sourcesContent":["import { startTransition, useCallback, useContext, useMemo } from 'react';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\n\nimport type {\n BackofficeListState,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\n\ntype ReturnValue<Where extends Record<string, unknown>, Sort extends string> = {\n state: BackofficeListState<Where, Sort>;\n pushState: (next: BackofficeListState<Where, Sort>) => void;\n};\n\n/** Keeps list state in sync with the URL search params for backoffice pages. */\nexport function useBackofficeListUrlState<\n Where extends Record<string, unknown>,\n Sort extends string,\n>(config: BackofficeRuntimeResolvedListFacetConfig): ReturnValue<Where, Sort> {\n const routing = useContext(RoutingContext);\n const { hash, pathname } = useLocation();\n const { listNavigation } = config;\n const routeEntry = routing?.get();\n const state = useMemo(() => {\n if (routeEntry == null) {\n return { where: null, sort: null };\n }\n const navigationQuery: { sort?: string } = {};\n if (typeof routeEntry.query.sort === 'string') {\n navigationQuery.sort = routeEntry.query.sort;\n }\n const filters = routeEntry.filters as Parameters<\n typeof listNavigation.decode\n >[0]['filters'];\n return listNavigation.decode({\n filters,\n query: navigationQuery,\n }) as BackofficeListState<Where, Sort>;\n }, [listNavigation, routeEntry]);\n\n const pushState = useCallback(\n (next: BackofficeListState<Where, Sort>) => {\n if (routing == null) {\n return;\n }\n const destination = listNavigation.encode(next);\n\n startTransition(() => {\n routing.navigate({\n pathname,\n filters: destination.filters,\n query: destination.query,\n hash,\n });\n });\n },\n [hash, listNavigation, pathname, routing],\n );\n\n return { state, pushState };\n}\n"],"mappings":";;;;AAeA,SAAgB,EAGd,GAA4E;CAC5E,IAAM,IAAU,EAAW,CAAc,GACnC,EAAE,SAAM,gBAAa,EAAY,GACjC,EAAE,sBAAmB,GACrB,IAAa,GAAS,IAAI;CAqChC,OAAO;EAAE,OApCK,QAAc;GAC1B,IAAI,KAAc,MAChB,OAAO;IAAE,OAAO;IAAM,MAAM;GAAK;GAEnC,IAAM,IAAqC,CAAC;GAC5C,AAAI,OAAO,EAAW,MAAM,QAAS,aACnC,EAAgB,OAAO,EAAW,MAAM;GAE1C,IAAM,IAAU,EAAW;GAG3B,OAAO,EAAe,OAAO;IAC3B;IACA,OAAO;GACT,CAAC;EACH,GAAG,CAAC,GAAgB,CAAU,CAqBrB;EAAO,WAnBE,GACf,MAA2C;GAC1C,IAAI,KAAW,MACb;GAEF,IAAM,IAAc,EAAe,OAAO,CAAI;GAE9C,QAAsB;IACpB,EAAQ,SAAS;KACf;KACA,SAAS,EAAY;KACrB,OAAO,EAAY;KACnB;IACF,CAAC;GACH,CAAC;EACH,GACA;GAAC;GAAM;GAAgB;GAAU;EAAO,CAG1B;CAAU;AAC5B"}
|