@pstdio/ui 0.43.0 → 0.43.1

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.
Files changed (74) hide show
  1. package/README.md +11 -0
  2. package/dist/{MermaidComponent-X7N-8w2S.js → MermaidComponent-_cmVeKKR.js} +3 -3
  3. package/dist/{MermaidComponent-X7N-8w2S.js.map → MermaidComponent-_cmVeKKR.js.map} +1 -1
  4. package/dist/chat-ui.d.ts +85 -57
  5. package/dist/chat-ui.js +1168 -1183
  6. package/dist/chat-ui.js.map +1 -1
  7. package/dist/{collection-view-fields-CajuwtKF.d.ts → collection-view-fields-B3fhsgn7.d.ts} +2 -0
  8. package/dist/{collection-view-grouping-DnuJ1U4R.js → collection-view-grouping-jIqOrBG8.js} +2 -2
  9. package/dist/{collection-view-grouping-DnuJ1U4R.js.map → collection-view-grouping-jIqOrBG8.js.map} +1 -1
  10. package/dist/{collection-view-search-D_7Qvz7p.js → collection-view-search-KbQpKHdn.js} +767 -630
  11. package/dist/collection-view-search-KbQpKHdn.js.map +1 -0
  12. package/dist/collection-view.d.ts +1 -1
  13. package/dist/collection-view.js +2 -2
  14. package/dist/{data-table-stats-row-C8CtvdDt.js → data-table-stats-row-83mX8b1B.js} +2 -2
  15. package/dist/{data-table-stats-row-C8CtvdDt.js.map → data-table-stats-row-83mX8b1B.js.map} +1 -1
  16. package/dist/data-table.d.ts +2 -2
  17. package/dist/data-table.js +8 -8
  18. package/dist/{diff-drawer-BGQhxyOh.js → diff-drawer-BMl0zobj.js} +2 -2
  19. package/dist/{diff-drawer-BGQhxyOh.js.map → diff-drawer-BMl0zobj.js.map} +1 -1
  20. package/dist/{diff-viewer-DYcswG6O.js → diff-viewer-C5KXwq7E.js} +5 -5
  21. package/dist/{diff-viewer-DYcswG6O.js.map → diff-viewer-C5KXwq7E.js.map} +1 -1
  22. package/dist/diff.js +2 -2
  23. package/dist/{display-sort-control-n3L5WvkJ.js → display-sort-control-BCkgKET1.js} +194 -183
  24. package/dist/display-sort-control-BCkgKET1.js.map +1 -0
  25. package/dist/{edit-mode-data-table-BclZ-pWe.js → edit-mode-data-table-ScVJJT9F.js} +8 -8
  26. package/dist/{edit-mode-data-table-BclZ-pWe.js.map → edit-mode-data-table-ScVJJT9F.js.map} +1 -1
  27. package/dist/{index-5Lw7YMKy.d.ts → index-Bc2BsdD1.d.ts} +6 -0
  28. package/dist/{index-DjZsR4Ey.d.ts → index-DXpADqIg.d.ts} +8 -4
  29. package/dist/index.d.ts +49 -49
  30. package/dist/index.js +453 -455
  31. package/dist/index.js.map +1 -1
  32. package/dist/kanban-renderer.d.ts +3 -3
  33. package/dist/kanban-renderer.js +935 -745
  34. package/dist/kanban-renderer.js.map +1 -1
  35. package/dist/{list-row-CmFG_jCC.js → list-row-F8kBQGB-.js} +394 -384
  36. package/dist/list-row-F8kBQGB-.js.map +1 -0
  37. package/dist/{markdown-editor-CN4qOKky.js → markdown-editor-Dm4Fi3sX.js} +6 -6
  38. package/dist/{markdown-editor-CN4qOKky.js.map → markdown-editor-Dm4Fi3sX.js.map} +1 -1
  39. package/dist/{mermaid-renderer-DybQ_2Cp.js → mermaid-renderer-BtW_13Sz.js} +2 -2
  40. package/dist/{mermaid-renderer-DybQ_2Cp.js.map → mermaid-renderer-BtW_13Sz.js.map} +1 -1
  41. package/dist/mermaid.js +1 -1
  42. package/dist/{number-input-CyrMrDxB.js → number-input-QDqWYzTR.js} +2 -2
  43. package/dist/{number-input-CyrMrDxB.js.map → number-input-QDqWYzTR.js.map} +1 -1
  44. package/dist/{param-editor-28dBRSV4.js → param-editor-B9ASM5Lv.js} +2 -2
  45. package/dist/{param-editor-28dBRSV4.js.map → param-editor-B9ASM5Lv.js.map} +1 -1
  46. package/dist/{param-editor-field-GxhFb86w.js → param-editor-field-BmNUziwI.js} +7 -5
  47. package/dist/param-editor-field-BmNUziwI.js.map +1 -0
  48. package/dist/param-editor.js +3 -3
  49. package/dist/{prism-CnkSh-ZG.js → prism-EZSmZh-a.js} +2 -2
  50. package/dist/{prism-CnkSh-ZG.js.map → prism-EZSmZh-a.js.map} +1 -1
  51. package/dist/{rich-text-DOK4dDeb.js → rich-text-Dx5F8Zm1.js} +384 -363
  52. package/dist/rich-text-Dx5F8Zm1.js.map +1 -0
  53. package/dist/rich-text.d.ts +1 -1
  54. package/dist/rich-text.js +3 -3
  55. package/dist/{scroll-area-crJfiiuF.js → scroll-area-IeoRS73V.js} +3 -5
  56. package/dist/scroll-area-IeoRS73V.js.map +1 -0
  57. package/dist/terminal.js +1 -1
  58. package/dist/{theme-Bd_a7sU8.js → theme-CWDvF5Yn.js} +185 -73
  59. package/dist/theme-CWDvF5Yn.js.map +1 -0
  60. package/dist/theme.js +1 -1
  61. package/dist/{tree-list-B_qqiIoM.js → tree-list-Ces1hpRd.js} +2 -2
  62. package/dist/{tree-list-B_qqiIoM.js.map → tree-list-Ces1hpRd.js.map} +1 -1
  63. package/dist/{workspace-badge-oFp29Gbe.d.ts → workspace-badge-De6OQjb5.d.ts} +2 -1
  64. package/dist/{workspace-badge-BfSkiGP_.js → workspace-badge-DqQKSUJw.js} +12 -12
  65. package/dist/workspace-badge-DqQKSUJw.js.map +1 -0
  66. package/package.json +2 -2
  67. package/dist/collection-view-search-D_7Qvz7p.js.map +0 -1
  68. package/dist/display-sort-control-n3L5WvkJ.js.map +0 -1
  69. package/dist/list-row-CmFG_jCC.js.map +0 -1
  70. package/dist/param-editor-field-GxhFb86w.js.map +0 -1
  71. package/dist/rich-text-DOK4dDeb.js.map +0 -1
  72. package/dist/scroll-area-crJfiiuF.js.map +0 -1
  73. package/dist/theme-Bd_a7sU8.js.map +0 -1
  74. package/dist/workspace-badge-BfSkiGP_.js.map +0 -1
@@ -32,6 +32,8 @@ interface CollectionViewsSource<TSettings> {
32
32
  }) => Promise<void>;
33
33
  onDeleteView: (id: string) => Promise<void>;
34
34
  onSetDefaultView: (id: string | null) => Promise<void>;
35
+ /** Saves the complete view order. Omit when the source does not support reordering. */
36
+ onReorderViews?: (ids: string[]) => Promise<void>;
35
37
  }
36
38
  //#endregion
37
39
  //#region src/components/kanban-renderer/types.d.ts
@@ -1,4 +1,4 @@
1
- import { C as e, E as t, O as n, S as r, b as i, t as a, w as o, y as s } from "./collection-view-search-D_7Qvz7p.js";
1
+ import { C as e, E as t, O as n, S as r, b as i, t as a, w as o, y as s } from "./collection-view-search-KbQpKHdn.js";
2
2
  import { Box as c } from "@chakra-ui/react";
3
3
  import { jsx as l } from "react/jsx-runtime";
4
4
  //#region src/components/collection-view/highlighted-text.tsx
@@ -87,4 +87,4 @@ var u = (e) => {
87
87
  //#endregion
88
88
  export { u as a, g as i, b as n, S as r, _ as t };
89
89
 
90
- //# sourceMappingURL=collection-view-grouping-DnuJ1U4R.js.map
90
+ //# sourceMappingURL=collection-view-grouping-jIqOrBG8.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection-view-grouping-DnuJ1U4R.js","names":["Box","findSearchRanges","HighlightedTextProps","text","query","HighlightedText","props","ranges","length","parts","Array","match","start","cursor","end","push","slice","map","part","ViewSort","getEnumOptions","AttributeDescriptor","AttributeType","KanbanRendererRow","canSortField","findField","getAttributeStringValues","getAttributeValue","parseViewDate","compareEnumValues","left","right","type","kind","options","toIndex","value","undefined","length","index","findIndex","option","toTime","getTime","Number","NaN","compareFieldValues","a","b","field","compare","leftValue","rightValue","String","localeCompare","numeric","sensitivity","isEmpty","row","isFinite","compileSort","sort","fields","attributeId","direction","leftEmpty","rightEmpty","sortRowsByView","rows","TRow","sorts","enumOptionLabel","getEnumOptions","AttributeDescriptor","KanbanRendererRow","getAttributeStringValues","compareEnumValues","CollectionRowGroup","key","label","rows","TRow","emptyGroupKey","field","toLowerCase","groupLabel","type","kind","resolveGroupValue","value","undefined","some","option","groupKey","row","compareGroupKeys","left","right","empty","Number","ordered","localeCompare","numeric","groupRowsByField","knownKeys","groups","Map","map","group","get","push","set","entries","sort","groupRows","getAttributeValue","enumOptionLabel","getEnumOptions","getAttributeStringValues","findField","findSearchRanges","parseViewDate","canSortField","HighlightedText","props","ranges","text","query","parts","cursor","start","end","part","Box","compareEnumValues","type","options","toIndex","value","index","option","left","right","toTime","compareFieldValues","a","field","b","leftValue","rightValue","isEmpty","row","compileSort","fields","sort","direction","leftEmpty","rightEmpty","sortRowsByView","sorts","compare","rows","emptyGroupKey","groupLabel","key","resolveGroupValue","groupKey","compareGroupKeys","empty","ordered","groupRowsByField","groups","knownKeys","group","groupRows"],"sources":["../src/components/collection-view/highlighted-text.tsx","../src/components/collection-view/collection-view-sort.ts","../src/components/collection-view/collection-view-grouping.ts"],"sourcesContent":["import { Box } from \"@chakra-ui/react\";\nimport { findSearchRanges } from \"./collection-view-search\";\n\nexport interface HighlightedTextProps {\n text: string;\n /** The view's search text. Every match in `text` is marked. */\n query: string;\n}\n\nexport const HighlightedText = (props: HighlightedTextProps) => {\n const { text, query } = props;\n const ranges = findSearchRanges(text, query);\n if (ranges.length === 0) return text;\n const parts: Array<{ text: string; match: boolean; start: number }> = [];\n let cursor = 0;\n for (const [start, end] of ranges) {\n if (start > cursor) parts.push({ text: text.slice(cursor, start), match: false, start: cursor });\n parts.push({ text: text.slice(start, end), match: true, start });\n cursor = end;\n }\n if (cursor < text.length) parts.push({ text: text.slice(cursor), match: false, start: cursor });\n\n return parts.map((part) =>\n part.match ? (\n <Box as=\"mark\" key={part.start} bg=\"bg.warning\" color=\"inherit\" borderRadius=\"2xs\">\n {part.text}\n </Box>\n ) : (\n part.text\n ),\n );\n};\n","import type { ViewSort } from \"@pstdio/sdk/extensions\";\nimport { getEnumOptions } from \"../kanban-renderer/kanban-renderer-enum-helpers\";\nimport type { AttributeDescriptor, AttributeType, KanbanRendererRow } from \"../kanban-renderer/types\";\nimport {\n canSortField,\n findField,\n getAttributeStringValues,\n getAttributeValue,\n parseViewDate,\n} from \"./collection-view-fields\";\n\n/** Option order: declared options first, unknown values after them, missing values last. */\nexport const compareEnumValues = (left: string | undefined, right: string | undefined, type: AttributeType) => {\n if (type.kind !== \"enum\" && type.kind !== \"enum-multi\") return 0;\n const options = getEnumOptions(type);\n const toIndex = (value: string | undefined) => {\n if (value === undefined) return options.length;\n const index = options.findIndex((option) => option.value === value);\n return index === -1 ? options.length + 1 : index;\n };\n return toIndex(left) - toIndex(right);\n};\n\nconst toTime = (value: unknown) => parseViewDate(value)?.getTime() ?? Number.NaN;\n\nconst compareFieldValues = (a: KanbanRendererRow, b: KanbanRendererRow, field: AttributeDescriptor) => {\n const left = getAttributeValue(a, field);\n const right = getAttributeValue(b, field);\n if (field.compare) return field.compare(left, right);\n if (field.type.kind === \"date\") return toTime(left) - toTime(right);\n if (field.type.kind === \"number\") return Number(left) - Number(right);\n if (field.type.kind === \"enum\") {\n const [leftValue] = getAttributeStringValues(a, field);\n const [rightValue] = getAttributeStringValues(b, field);\n return compareEnumValues(leftValue, rightValue, field.type);\n }\n return String(left).localeCompare(String(right), undefined, { numeric: true, sensitivity: \"base\" });\n};\n\nconst isEmpty = (row: KanbanRendererRow, field: AttributeDescriptor) => {\n if (field.type.kind === \"date\") return parseViewDate(getAttributeValue(row, field)) === undefined;\n const [value] = getAttributeStringValues(row, field);\n if (value === undefined) return true;\n if (field.type.kind === \"number\") return !Number.isFinite(Number(value));\n return false;\n};\n\nconst compileSort = (sort: ViewSort, fields: AttributeDescriptor[]) => {\n const field = findField(fields, sort.attributeId);\n if (!field || !canSortField(field)) return undefined;\n const direction = sort.direction === \"asc\" ? 1 : -1;\n // Rows without a value stay last in both directions.\n return (a: KanbanRendererRow, b: KanbanRendererRow) => {\n const leftEmpty = isEmpty(a, field);\n const rightEmpty = isEmpty(b, field);\n if (leftEmpty || rightEmpty) return Number(leftEmpty) - Number(rightEmpty);\n return direction * compareFieldValues(a, b, field);\n };\n};\n\n/** One field decides the order; ties keep their incoming order. */\nexport const sortRowsByView = <TRow extends KanbanRendererRow>(\n rows: TRow[],\n sorts: ViewSort[],\n fields: AttributeDescriptor[],\n) => {\n const sort = sorts[0];\n const compare = sort ? compileSort(sort, fields) : undefined;\n return compare ? [...rows].sort(compare) : rows;\n};\n","import { enumOptionLabel, getEnumOptions } from \"../kanban-renderer/kanban-renderer-enum-helpers\";\nimport type { AttributeDescriptor, KanbanRendererRow } from \"../kanban-renderer/types\";\nimport { getAttributeStringValues } from \"./collection-view-fields\";\nimport { compareEnumValues } from \"./collection-view-sort\";\n\nexport interface CollectionRowGroup<TRow extends KanbanRendererRow = KanbanRendererRow> {\n key: string;\n label: string;\n rows: TRow[];\n}\n\nexport const emptyGroupKey = (field: AttributeDescriptor) => `No ${field.label.toLowerCase()}`;\n\nexport const groupLabel = (key: string, field: AttributeDescriptor) => {\n if (key === emptyGroupKey(field)) return key;\n if (field.type.kind === \"enum\" || field.type.kind === \"enum-multi\") return enumOptionLabel(field.type, key);\n return key;\n};\n\n// Drops values that are no longer a declared option, so rows pointing at a removed\n// status join the \"No <field>\" group instead of an orphaned group for the deleted value.\nconst resolveGroupValue = (value: string | undefined, field: AttributeDescriptor) => {\n if (value === undefined) return undefined;\n if (field.type.kind !== \"enum\" && field.type.kind !== \"enum-multi\") return value;\n return getEnumOptions(field.type).some((option) => option.value === value) ? value : undefined;\n};\n\n/** One group per row. A multi-value field is not offered for grouping, so its first value decides. */\nexport const groupKey = (row: KanbanRendererRow, field: AttributeDescriptor) => {\n const [value] = getAttributeStringValues(row, field);\n return resolveGroupValue(value, field) ?? emptyGroupKey(field);\n};\n\n/** Option fields follow option order, other fields go A to Z, and the \"No <field>\" group comes last. */\nexport const compareGroupKeys = (left: string, right: string, field: AttributeDescriptor) => {\n const empty = emptyGroupKey(field);\n if (left === empty || right === empty) return Number(left === empty) - Number(right === empty);\n const ordered = compareEnumValues(left, right, field.type);\n if (ordered !== 0) return ordered;\n return left.localeCompare(right, undefined, { numeric: true });\n};\n\nexport const groupRowsByField = <TRow extends KanbanRendererRow>(\n rows: TRow[],\n field: AttributeDescriptor,\n knownKeys: string[] = [],\n): CollectionRowGroup<TRow>[] => {\n const groups = new Map<string, TRow[]>(knownKeys.map((key) => [key, []]));\n for (const row of rows) {\n const key = groupKey(row, field);\n const group = groups.get(key);\n if (group) group.push(row);\n else groups.set(key, [row]);\n }\n return [...groups.entries()]\n .sort(([left], [right]) => compareGroupKeys(left, right, field))\n .map(([key, groupRows]) => ({ key, label: groupLabel(key, field), rows: groupRows }));\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"collection-view-grouping-jIqOrBG8.js","names":["Box","findSearchRanges","HighlightedTextProps","text","query","HighlightedText","props","ranges","length","parts","Array","match","start","cursor","end","push","slice","map","part","ViewSort","getEnumOptions","AttributeDescriptor","AttributeType","KanbanRendererRow","canSortField","findField","getAttributeStringValues","getAttributeValue","parseViewDate","compareEnumValues","left","right","type","kind","options","toIndex","value","undefined","length","index","findIndex","option","toTime","getTime","Number","NaN","compareFieldValues","a","b","field","compare","leftValue","rightValue","String","localeCompare","numeric","sensitivity","isEmpty","row","isFinite","compileSort","sort","fields","attributeId","direction","leftEmpty","rightEmpty","sortRowsByView","rows","TRow","sorts","enumOptionLabel","getEnumOptions","AttributeDescriptor","KanbanRendererRow","getAttributeStringValues","compareEnumValues","CollectionRowGroup","key","label","rows","TRow","emptyGroupKey","field","toLowerCase","groupLabel","type","kind","resolveGroupValue","value","undefined","some","option","groupKey","row","compareGroupKeys","left","right","empty","Number","ordered","localeCompare","numeric","groupRowsByField","knownKeys","groups","Map","map","group","get","push","set","entries","sort","groupRows","getAttributeValue","enumOptionLabel","getEnumOptions","getAttributeStringValues","findField","findSearchRanges","parseViewDate","canSortField","HighlightedText","props","ranges","text","query","parts","cursor","start","end","part","Box","compareEnumValues","type","options","toIndex","value","index","option","left","right","toTime","compareFieldValues","a","field","b","leftValue","rightValue","isEmpty","row","compileSort","fields","sort","direction","leftEmpty","rightEmpty","sortRowsByView","sorts","compare","rows","emptyGroupKey","groupLabel","key","resolveGroupValue","groupKey","compareGroupKeys","empty","ordered","groupRowsByField","groups","knownKeys","group","groupRows"],"sources":["../src/components/collection-view/highlighted-text.tsx","../src/components/collection-view/collection-view-sort.ts","../src/components/collection-view/collection-view-grouping.ts"],"sourcesContent":["import { Box } from \"@chakra-ui/react\";\nimport { findSearchRanges } from \"./collection-view-search\";\n\nexport interface HighlightedTextProps {\n text: string;\n /** The view's search text. Every match in `text` is marked. */\n query: string;\n}\n\nexport const HighlightedText = (props: HighlightedTextProps) => {\n const { text, query } = props;\n const ranges = findSearchRanges(text, query);\n if (ranges.length === 0) return text;\n const parts: Array<{ text: string; match: boolean; start: number }> = [];\n let cursor = 0;\n for (const [start, end] of ranges) {\n if (start > cursor) parts.push({ text: text.slice(cursor, start), match: false, start: cursor });\n parts.push({ text: text.slice(start, end), match: true, start });\n cursor = end;\n }\n if (cursor < text.length) parts.push({ text: text.slice(cursor), match: false, start: cursor });\n\n return parts.map((part) =>\n part.match ? (\n <Box as=\"mark\" key={part.start} bg=\"bg.warning\" color=\"inherit\" borderRadius=\"2xs\">\n {part.text}\n </Box>\n ) : (\n part.text\n ),\n );\n};\n","import type { ViewSort } from \"@pstdio/sdk/extensions\";\nimport { getEnumOptions } from \"../kanban-renderer/kanban-renderer-enum-helpers\";\nimport type { AttributeDescriptor, AttributeType, KanbanRendererRow } from \"../kanban-renderer/types\";\nimport {\n canSortField,\n findField,\n getAttributeStringValues,\n getAttributeValue,\n parseViewDate,\n} from \"./collection-view-fields\";\n\n/** Option order: declared options first, unknown values after them, missing values last. */\nexport const compareEnumValues = (left: string | undefined, right: string | undefined, type: AttributeType) => {\n if (type.kind !== \"enum\" && type.kind !== \"enum-multi\") return 0;\n const options = getEnumOptions(type);\n const toIndex = (value: string | undefined) => {\n if (value === undefined) return options.length;\n const index = options.findIndex((option) => option.value === value);\n return index === -1 ? options.length + 1 : index;\n };\n return toIndex(left) - toIndex(right);\n};\n\nconst toTime = (value: unknown) => parseViewDate(value)?.getTime() ?? Number.NaN;\n\nconst compareFieldValues = (a: KanbanRendererRow, b: KanbanRendererRow, field: AttributeDescriptor) => {\n const left = getAttributeValue(a, field);\n const right = getAttributeValue(b, field);\n if (field.compare) return field.compare(left, right);\n if (field.type.kind === \"date\") return toTime(left) - toTime(right);\n if (field.type.kind === \"number\") return Number(left) - Number(right);\n if (field.type.kind === \"enum\") {\n const [leftValue] = getAttributeStringValues(a, field);\n const [rightValue] = getAttributeStringValues(b, field);\n return compareEnumValues(leftValue, rightValue, field.type);\n }\n return String(left).localeCompare(String(right), undefined, { numeric: true, sensitivity: \"base\" });\n};\n\nconst isEmpty = (row: KanbanRendererRow, field: AttributeDescriptor) => {\n if (field.type.kind === \"date\") return parseViewDate(getAttributeValue(row, field)) === undefined;\n const [value] = getAttributeStringValues(row, field);\n if (value === undefined) return true;\n if (field.type.kind === \"number\") return !Number.isFinite(Number(value));\n return false;\n};\n\nconst compileSort = (sort: ViewSort, fields: AttributeDescriptor[]) => {\n const field = findField(fields, sort.attributeId);\n if (!field || !canSortField(field)) return undefined;\n const direction = sort.direction === \"asc\" ? 1 : -1;\n // Rows without a value stay last in both directions.\n return (a: KanbanRendererRow, b: KanbanRendererRow) => {\n const leftEmpty = isEmpty(a, field);\n const rightEmpty = isEmpty(b, field);\n if (leftEmpty || rightEmpty) return Number(leftEmpty) - Number(rightEmpty);\n return direction * compareFieldValues(a, b, field);\n };\n};\n\n/** One field decides the order; ties keep their incoming order. */\nexport const sortRowsByView = <TRow extends KanbanRendererRow>(\n rows: TRow[],\n sorts: ViewSort[],\n fields: AttributeDescriptor[],\n) => {\n const sort = sorts[0];\n const compare = sort ? compileSort(sort, fields) : undefined;\n return compare ? [...rows].sort(compare) : rows;\n};\n","import { enumOptionLabel, getEnumOptions } from \"../kanban-renderer/kanban-renderer-enum-helpers\";\nimport type { AttributeDescriptor, KanbanRendererRow } from \"../kanban-renderer/types\";\nimport { getAttributeStringValues } from \"./collection-view-fields\";\nimport { compareEnumValues } from \"./collection-view-sort\";\n\nexport interface CollectionRowGroup<TRow extends KanbanRendererRow = KanbanRendererRow> {\n key: string;\n label: string;\n rows: TRow[];\n}\n\nexport const emptyGroupKey = (field: AttributeDescriptor) => `No ${field.label.toLowerCase()}`;\n\nexport const groupLabel = (key: string, field: AttributeDescriptor) => {\n if (key === emptyGroupKey(field)) return key;\n if (field.type.kind === \"enum\" || field.type.kind === \"enum-multi\") return enumOptionLabel(field.type, key);\n return key;\n};\n\n// Drops values that are no longer a declared option, so rows pointing at a removed\n// status join the \"No <field>\" group instead of an orphaned group for the deleted value.\nconst resolveGroupValue = (value: string | undefined, field: AttributeDescriptor) => {\n if (value === undefined) return undefined;\n if (field.type.kind !== \"enum\" && field.type.kind !== \"enum-multi\") return value;\n return getEnumOptions(field.type).some((option) => option.value === value) ? value : undefined;\n};\n\n/** One group per row. A multi-value field is not offered for grouping, so its first value decides. */\nexport const groupKey = (row: KanbanRendererRow, field: AttributeDescriptor) => {\n const [value] = getAttributeStringValues(row, field);\n return resolveGroupValue(value, field) ?? emptyGroupKey(field);\n};\n\n/** Option fields follow option order, other fields go A to Z, and the \"No <field>\" group comes last. */\nexport const compareGroupKeys = (left: string, right: string, field: AttributeDescriptor) => {\n const empty = emptyGroupKey(field);\n if (left === empty || right === empty) return Number(left === empty) - Number(right === empty);\n const ordered = compareEnumValues(left, right, field.type);\n if (ordered !== 0) return ordered;\n return left.localeCompare(right, undefined, { numeric: true });\n};\n\nexport const groupRowsByField = <TRow extends KanbanRendererRow>(\n rows: TRow[],\n field: AttributeDescriptor,\n knownKeys: string[] = [],\n): CollectionRowGroup<TRow>[] => {\n const groups = new Map<string, TRow[]>(knownKeys.map((key) => [key, []]));\n for (const row of rows) {\n const key = groupKey(row, field);\n const group = groups.get(key);\n if (group) group.push(row);\n else groups.set(key, [row]);\n }\n return [...groups.entries()]\n .sort(([left], [right]) => compareGroupKeys(left, right, field))\n .map(([key, groupRows]) => ({ key, label: groupLabel(key, field), rows: groupRows }));\n};\n"],"mappings":";;;;AASA,IAAaK,KAAmBC,MAAgC;CAC9D,IAAM,EAAEH,SAAMC,aAAUE,GAClBC,IAASN,EAAiBE,GAAMC,CAAK;CAC3C,IAAIG,EAAOC,WAAW,GAAG,OAAOL;CAChC,IAAMM,IAAgE,CAAA,GAClEI,IAAS;CACb,KAAK,IAAM,CAACD,GAAOE,MAAQP,GAGzBM,AAFID,IAAQC,KAAQJ,EAAMM,KAAK;EAAEZ,MAAMA,EAAKa,MAAMH,GAAQD,CAAK;EAAGD,OAAO;EAAOC,OAAOC;CAAO,CAAC,GAC/FJ,EAAMM,KAAK;EAAEZ,MAAMA,EAAKa,MAAMJ,GAAOE,CAAG;EAAGH,OAAO;EAAMC;CAAM,CAAC,GAC/DC,IAASC;CAIX,OAFID,IAASV,EAAKK,UAAQC,EAAMM,KAAK;EAAEZ,MAAMA,EAAKa,MAAMH,CAAM;EAAGF,OAAO;EAAOC,OAAOC;CAAO,CAAC,GAEvFJ,EAAMQ,KAAKC,MAChBA,EAAKP,QACH,kBAAC0H,GAAD;EAAK,IAAG;EAAwB,IAAG;EAAa,OAAM;EAAU,cAAa;EAC1EnH,UAAAA,EAAKf;CACH,GAFee,EAAKN,KAEpB,IAELM,EAAKf,IAET;AACF,GCnBa0B,KAAqBC,GAA0BC,GAA2BC,MAAwB;CAC7G,IAAIA,EAAKC,SAAS,UAAUD,EAAKC,SAAS,cAAc,OAAO;CAC/D,IAAMC,IAAUd,EAAeY,CAAI,GAC7BG,KAAWC,MAA8B;EAC7C,IAAIA,MAAUC,KAAAA,GAAW,OAAOH,EAAQI;EACxC,IAAMC,IAAQL,EAAQM,WAAWC,MAAWA,EAAOL,UAAUA,CAAK;EAClE,OAAOG,MAAU,KAAKL,EAAQI,SAAS,IAAIC;CAC7C;CACA,OAAOJ,EAAQL,CAAI,IAAIK,EAAQJ,CAAK;AACtC,GAEMW,KAAUN,MAAmBR,EAAcQ,CAAK,CAAC,EAAEO,QAAQ,KAAKC,KAEhEE,KAAsBC,GAAsBC,GAAsBC,MAA+B;CACrG,IAAMnB,IAAOH,EAAkBoB,GAAGE,CAAK,GACjClB,IAAQJ,EAAkBqB,GAAGC,CAAK;CACxC,IAAIA,EAAMC,SAAS,OAAOD,EAAMC,QAAQpB,GAAMC,CAAK;CACnD,IAAIkB,EAAMjB,KAAKC,SAAS,QAAQ,OAAOS,EAAOZ,CAAI,IAAIY,EAAOX,CAAK;CAClE,IAAIkB,EAAMjB,KAAKC,SAAS,UAAU,OAAOW,OAAOd,CAAI,IAAIc,OAAOb,CAAK;CACpE,IAAIkB,EAAMjB,KAAKC,SAAS,QAAQ;EAC9B,IAAM,CAACkB,KAAazB,EAAyBqB,GAAGE,CAAK,GAC/C,CAACG,KAAc1B,EAAyBsB,GAAGC,CAAK;EACtD,OAAOpB,EAAkBsB,GAAWC,GAAYH,EAAMjB,IAAI;CAC5D;CACA,OAAOqB,OAAOvB,CAAI,CAAC,CAACwB,cAAcD,OAAOtB,CAAK,GAAGM,KAAAA,GAAW;EAAEkB,SAAS;EAAMC,aAAa;CAAO,CAAC;AACpG,GAEMC,KAAWC,GAAwBT,MAA+B;CACtE,IAAIA,EAAMjB,KAAKC,SAAS,QAAQ,OAAOL,EAAcD,EAAkB+B,GAAKT,CAAK,CAAC,MAAMZ,KAAAA;CACxF,IAAM,CAACD,KAASV,EAAyBgC,GAAKT,CAAK;CAGnD,OAFIb,MAAUC,KAAAA,KACVY,EAAMjB,KAAKC,SAAS,YAAiB,CAACW,OAAOe,SAASf,OAAOR,CAAK,CAAC;AAEzE,GAEMwB,KAAeC,GAAgBC,MAAkC;CACrE,IAAMb,IAAQxB,EAAUqC,GAAQD,EAAKE,WAAW;CAChD,IAAI,CAACd,KAAS,CAACzB,EAAayB,CAAK,GAAG;CACpC,IAAMe,IAAYH,EAAKG,cAAc,QAAQ,IAAI;CAEjD,QAAQjB,GAAsBC,MAAyB;EACrD,IAAMiB,IAAYR,EAAQV,GAAGE,CAAK,GAC5BiB,IAAaT,EAAQT,GAAGC,CAAK;EAEnC,OADIgB,KAAaC,IAAmBtB,OAAOqB,CAAS,IAAIrB,OAAOsB,CAAU,IAClEF,IAAYlB,EAAmBC,GAAGC,GAAGC,CAAK;CACnD;AACF,GAGakB,KACXC,GACAE,GACAR,MACG;CACH,IAAMD,IAAOS,EAAM,IACbpB,IAAUW,IAAOD,EAAYC,GAAMC,CAAM,IAAIzB,KAAAA;CACnD,OAAOa,IAAU,CAAC,GAAGkB,CAAI,CAAC,CAACP,KAAKX,CAAO,IAAIkB;AAC7C,GC1Dac,KAAiBC,MAA+B,MAAMA,EAAMJ,MAAMK,YAAY,KAE9EC,KAAcP,GAAaK,MAClCL,MAAQI,EAAcC,CAAK,IAAUL,IACrCK,EAAMG,KAAKC,SAAS,UAAUJ,EAAMG,KAAKC,SAAS,eAAqBhB,EAAgBY,EAAMG,MAAMR,CAAG,IACnGA,GAKHU,KAAqBC,GAA2BN,MAA+B;CACnF,IAAIM,MAAUC,KAAAA,GAEd,OADIP,EAAMG,KAAKC,SAAS,UAAUJ,EAAMG,KAAKC,SAAS,gBAC/Cf,EAAeW,EAAMG,IAAI,CAAC,CAACK,MAAMC,MAAWA,EAAOH,UAAUA,CAAK,IADEA,IACUC,KAAAA;AACvF,GAGaG,KAAYC,GAAwBX,MAA+B;CAC9E,IAAM,CAACM,KAASd,EAAyBmB,GAAKX,CAAK;CACnD,OAAOK,EAAkBC,GAAON,CAAK,KAAKD,EAAcC,CAAK;AAC/D,GAGaY,KAAoBC,GAAcC,GAAed,MAA+B;CAC3F,IAAMe,IAAQhB,EAAcC,CAAK;CACjC,IAAIa,MAASE,KAASD,MAAUC,GAAO,OAAOC,OAAOH,MAASE,CAAK,IAAIC,OAAOF,MAAUC,CAAK;CAC7F,IAAME,IAAUxB,EAAkBoB,GAAMC,GAAOd,EAAMG,IAAI;CAEzD,OADIc,MAAY,IACTJ,EAAKK,cAAcJ,GAAOP,KAAAA,GAAW,EAAEY,SAAS,GAAK,CAAC,IADnCF;AAE5B,GAEaG,KACXvB,GACAG,GACAqB,IAAsB,CAAA,MACS;CAC/B,IAAMC,IAAS,IAAIC,IAAoBF,EAAUG,KAAK7B,MAAQ,CAACA,GAAK,CAAA,CAAE,CAAC,CAAC;CACxE,KAAK,IAAMgB,KAAOd,GAAM;EACtB,IAAMF,IAAMe,EAASC,GAAKX,CAAK,GACzByB,IAAQH,EAAOI,IAAI/B,CAAG;EAC5B,AAAI8B,IAAOA,EAAME,KAAKhB,CAAG,IACpBW,EAAOM,IAAIjC,GAAK,CAACgB,CAAG,CAAC;CAC5B;CACA,OAAO,CAAC,GAAGW,EAAOO,QAAQ,CAAC,CAAC,CACzBC,MAAM,CAACjB,IAAO,CAACC,OAAWF,EAAiBC,GAAMC,GAAOd,CAAK,CAAC,CAAC,CAC/DwB,KAAK,CAAC7B,GAAKoC,QAAgB;EAAEpC;EAAKC,OAAOM,EAAWP,GAAKK,CAAK;EAAGH,MAAMkC;CAAU,EAAE;AACxF"}