feat(admin): make all sortable/repeater cards collapsible, collapsed by default

- Add useCollapsibleItems: key-based open state, clickable/keyboard head, aria-expanded
- sortable items with sub-fields and every inline repeater/group row now collapse
- Repeater head summary falls back to the first filled field when no listPreview
- Drop per-schema collapsible/defaultCollapsed for repeater groups (JS + PHP)
- Align FloatBtnItemPanel head with the shared collapse attrs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-10-28 14:12:13 +08:00
1 parent 8843ae4261
commit 116b6b2223
9 files changed
+114 -76

No files matched your search

@@ -41,10 +41,21 @@ function rowDuration(row, cfg) {
return String(raw)
}
/** 未配置 titleKey 时,取首个值为非空字符串/数字的字段作为标题。 */
function fallbackTitleKey(row, fields) {
if (row.title != null && String(row.title).trim() !== '') return 'title'
for (const field of (Array.isArray(fields) ? fields : [])) {
if (field.ui_only) continue
const value = row[field.key]
if ((typeof value === 'string' && value.trim() !== '') || typeof value === 'number') return field.key
}
return 'title'
}
/** 收起态标题行上的一行摘要,取自 listPreview 配置。 */
export function repeaterRowSummary(row, cfg = {}) {
export function repeaterRowSummary(row, cfg = {}, fields = []) {
if (!row) return ''
const title = String(row[cfg.titleKey || 'title'] ?? '').trim()
const title = String(row[cfg.titleKey || fallbackTitleKey(row, fields)] ?? '').trim()
const prefix = String(cfg.prefix || '')
if (title === '') return prefix
const duration = rowDuration(row, cfg)