@pstdio/ui 0.40.0 → 0.42.0

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 (108) hide show
  1. package/dist/{MermaidComponent-81jr28u4.js → MermaidComponent-D7vhkpka.js} +3 -3
  2. package/dist/{MermaidComponent-81jr28u4.js.map → MermaidComponent-D7vhkpka.js.map} +1 -1
  3. package/dist/alert-MQ47wy7f.js +388 -0
  4. package/dist/alert-MQ47wy7f.js.map +1 -0
  5. package/dist/chat-ui.d.ts +129 -23
  6. package/dist/chat-ui.js +2596 -1591
  7. package/dist/chat-ui.js.map +1 -1
  8. package/dist/{types-DWA3enV6.d.ts → collection-view-fields-D3cysHNT.d.ts} +87 -37
  9. package/dist/collection-view-grouping-D4nZk8-3.js +90 -0
  10. package/dist/collection-view-grouping-D4nZk8-3.js.map +1 -0
  11. package/dist/collection-view-search-CpjJy76w.js +1973 -0
  12. package/dist/collection-view-search-CpjJy76w.js.map +1 -0
  13. package/dist/collection-view.d.ts +4 -0
  14. package/dist/collection-view.js +2 -0
  15. package/dist/{data-table-stats-row-CpRe_xK2.js → data-table-stats-row-64magT2g.js} +2 -2
  16. package/dist/{data-table-stats-row-CpRe_xK2.js.map → data-table-stats-row-64magT2g.js.map} +1 -1
  17. package/dist/data-table.d.ts +29 -7
  18. package/dist/data-table.js +1043 -878
  19. package/dist/data-table.js.map +1 -1
  20. package/dist/diff-bubble-DewUd_2w.js +61 -0
  21. package/dist/diff-bubble-DewUd_2w.js.map +1 -0
  22. package/dist/{diff-drawer-45rpk3aq.js → diff-drawer-IYpQ-QQK.js} +264 -242
  23. package/dist/diff-drawer-IYpQ-QQK.js.map +1 -0
  24. package/dist/diff-viewer-C-0VAt9P.js +574 -0
  25. package/dist/diff-viewer-C-0VAt9P.js.map +1 -0
  26. package/dist/diff.d.ts +11 -0
  27. package/dist/diff.js +107 -98
  28. package/dist/diff.js.map +1 -1
  29. package/dist/display-sort-control-f3rbILsV.js +588 -0
  30. package/dist/display-sort-control-f3rbILsV.js.map +1 -0
  31. package/dist/drop-indicator-HjlBSIeV.js +27 -0
  32. package/dist/drop-indicator-HjlBSIeV.js.map +1 -0
  33. package/dist/edit-mode-data-table-DnMB2jiy.js +1449 -0
  34. package/dist/edit-mode-data-table-DnMB2jiy.js.map +1 -0
  35. package/dist/host-storage-BIo5azql.js +31 -0
  36. package/dist/host-storage-BIo5azql.js.map +1 -0
  37. package/dist/host-storage-J0089Hyk.d.ts +17 -0
  38. package/dist/{slider-hwHYe98I.js → icon-options-Tt6Wzhtv.js} +86 -201
  39. package/dist/icon-options-Tt6Wzhtv.js.map +1 -0
  40. package/dist/{index-Bfddrlz8.d.ts → index-B79hwNcB.d.ts} +66 -14
  41. package/dist/index-CKsd23jv.d.ts +80 -0
  42. package/dist/{index-CbtbcvKm.d.ts → index-DlmvvQ6x.d.ts} +1 -1
  43. package/dist/index-ICoad2I_.d.ts +282 -0
  44. package/dist/index.d.ts +63 -22
  45. package/dist/index.js +1149 -1054
  46. package/dist/index.js.map +1 -1
  47. package/dist/kanban-renderer.d.ts +3 -326
  48. package/dist/kanban-renderer.js +980 -596
  49. package/dist/kanban-renderer.js.map +1 -1
  50. package/dist/list-row-Z4SHkseA.js +1195 -0
  51. package/dist/list-row-Z4SHkseA.js.map +1 -0
  52. package/dist/markdown-editor-Dd4mor7l.js +3236 -0
  53. package/dist/markdown-editor-Dd4mor7l.js.map +1 -0
  54. package/dist/{mermaid-renderer-DImi0fDp.js → mermaid-renderer-0PmNkOXI.js} +29 -29
  55. package/dist/mermaid-renderer-0PmNkOXI.js.map +1 -0
  56. package/dist/mermaid.js +1 -1
  57. package/dist/number-input-7K66wnSC.js +63 -0
  58. package/dist/number-input-7K66wnSC.js.map +1 -0
  59. package/dist/{param-editor-BQd4AOUP.js → param-editor-Dnix-fJo.js} +2 -2
  60. package/dist/{param-editor-BQd4AOUP.js.map → param-editor-Dnix-fJo.js.map} +1 -1
  61. package/dist/{param-editor-field-BJ_rLUnV.js → param-editor-field-B3vLST-B.js} +1436 -1427
  62. package/dist/param-editor-field-B3vLST-B.js.map +1 -0
  63. package/dist/param-editor.js +4 -3
  64. package/dist/prism-OG4H7Hu4.js +334 -0
  65. package/dist/prism-OG4H7Hu4.js.map +1 -0
  66. package/dist/queued-follow-up-Bj_vtMgd.js +208 -0
  67. package/dist/queued-follow-up-Bj_vtMgd.js.map +1 -0
  68. package/dist/{resource-badge-95WPVlZf.d.ts → resource-badge-nOWPqxFU.d.ts} +1 -0
  69. package/dist/rich-text-BgEnAHr2.js +1160 -0
  70. package/dist/rich-text-BgEnAHr2.js.map +1 -0
  71. package/dist/rich-text.d.ts +2 -2
  72. package/dist/rich-text.js +4 -2
  73. package/dist/style.css +1 -1
  74. package/dist/terminal.d.ts +5 -63
  75. package/dist/terminal.js +102 -122
  76. package/dist/terminal.js.map +1 -1
  77. package/dist/{theme-CbmSEbRF.js → theme-CMJdH59Z.js} +589 -265
  78. package/dist/theme-CMJdH59Z.js.map +1 -0
  79. package/dist/theme-kKuLN2jb.js +80 -0
  80. package/dist/theme-kKuLN2jb.js.map +1 -0
  81. package/dist/theme-preference-BV4cbJNB.js +115 -0
  82. package/dist/theme-preference-BV4cbJNB.js.map +1 -0
  83. package/dist/theme.js +3 -2
  84. package/dist/tree-list-jarhD31R.js +1652 -0
  85. package/dist/tree-list-jarhD31R.js.map +1 -0
  86. package/dist/use-virtualizer-uj43XjBp.js +10 -0
  87. package/dist/use-virtualizer-uj43XjBp.js.map +1 -0
  88. package/dist/{workspace-badge-Brm3Xr3m.d.ts → workspace-badge-BKtB805G.d.ts} +5 -1
  89. package/package.json +8 -4
  90. package/dist/diff-bubble-DZsarmSG.js +0 -61
  91. package/dist/diff-bubble-DZsarmSG.js.map +0 -1
  92. package/dist/diff-drawer-45rpk3aq.js.map +0 -1
  93. package/dist/diff-viewer-BP_mI6Wx.js +0 -558
  94. package/dist/diff-viewer-BP_mI6Wx.js.map +0 -1
  95. package/dist/list-row-uqD-q4gv.js +0 -1018
  96. package/dist/list-row-uqD-q4gv.js.map +0 -1
  97. package/dist/mermaid-renderer-DImi0fDp.js.map +0 -1
  98. package/dist/param-editor-field-BJ_rLUnV.js.map +0 -1
  99. package/dist/prism-BStPsJSB.js +0 -658
  100. package/dist/prism-BStPsJSB.js.map +0 -1
  101. package/dist/rich-text-VYAmEigU.js +0 -6979
  102. package/dist/rich-text-VYAmEigU.js.map +0 -1
  103. package/dist/slider-hwHYe98I.js.map +0 -1
  104. package/dist/theme-CbmSEbRF.js.map +0 -1
  105. package/dist/theme-preference-pzfuK5cH.js +0 -101
  106. package/dist/theme-preference-pzfuK5cH.js.map +0 -1
  107. package/dist/tree-list-BNZwjQZA.js +0 -1616
  108. package/dist/tree-list-BNZwjQZA.js.map +0 -1
@@ -1,9 +1,42 @@
1
+ import "./host-storage-J0089Hyk.js";
1
2
  import { ReactNode } from "react";
3
+ import { ViewFilterCondition, ViewFilterGroup, ViewFilterGroup as ViewFilterGroup$1, ViewFilterRule, ViewFilterRule as ViewFilterRule$1, ViewSort, ViewSort as ViewSort$1, ViewSortDirection } from "@pstdio/sdk/extensions";
4
+ //#region src/components/collection-view/collection-view-types.d.ts
5
+ declare const EMPTY_VIEW_FILTER: ViewFilterGroup;
6
+ /** What a saved view stores. Search, selection, and collapsed groups are screen state and never saved. */
7
+ interface CollectionSavedView<TSettings> {
8
+ id: string;
9
+ title: string;
10
+ settings: TSettings;
11
+ filter: ViewFilterGroup;
12
+ sorts: ViewSort[];
13
+ /** @deprecated Use defaultActiveViewId instead. */
14
+ isDefault?: boolean;
15
+ }
16
+ interface CollectionViewState<TSettings> {
17
+ settings: TSettings;
18
+ filter: ViewFilterGroup;
19
+ sorts: ViewSort[];
20
+ }
21
+ interface CollectionViewsSource<TSettings> {
22
+ views: (CollectionSavedView<TSettings> & {
23
+ builtIn: boolean;
24
+ })[];
25
+ defaultViewId: string;
26
+ onCreateView: (input: CollectionViewState<TSettings> & {
27
+ title: string;
28
+ copyFrom?: string;
29
+ }) => Promise<CollectionSavedView<TSettings>>;
30
+ onUpdateView: (id: string, input: Partial<CollectionViewState<TSettings>> & {
31
+ title?: string;
32
+ }) => Promise<void>;
33
+ onDeleteView: (id: string) => Promise<void>;
34
+ onSetDefaultView: (id: string | null) => Promise<void>;
35
+ }
36
+ //#endregion
2
37
  //#region src/components/kanban-renderer/types.d.ts
3
38
  type ViewMode = "board" | "list";
4
- type SortDirection = "asc" | "desc";
5
39
  declare const NO_GROUPING = "none";
6
- declare const MANUAL_ORDERING = "manual";
7
40
  interface EnumOption {
8
41
  value: string;
9
42
  label: string;
@@ -27,6 +60,9 @@ type AttributeType = {
27
60
  } | {
28
61
  kind: "enum-multi";
29
62
  options: EnumOptions;
63
+ } | {
64
+ kind: "boolean";
65
+ legacyValues?: Record<string, boolean>;
30
66
  } | {
31
67
  kind: "string";
32
68
  } | {
@@ -96,26 +132,14 @@ interface KanbanRendererRow {
96
132
  resource?: unknown;
97
133
  attributes: Record<string, unknown>;
98
134
  }
99
- interface KanbanRendererOrdering {
100
- attributeId: string | typeof MANUAL_ORDERING;
101
- direction: SortDirection;
102
- }
135
+ /** Board display settings. Order lives in the view's sorts. */
103
136
  interface KanbanRendererSettings {
104
137
  viewMode: ViewMode;
105
138
  columnGrouping: string | typeof NO_GROUPING;
106
139
  rowGrouping: string | typeof NO_GROUPING;
107
- ordering: KanbanRendererOrdering;
108
140
  displayProperties: string[];
109
141
  }
110
- type KanbanRendererFilterState = Record<string, string[]>;
111
- interface KanbanRendererSavedView {
112
- id: string;
113
- title: string;
114
- settings: KanbanRendererSettings;
115
- filters: KanbanRendererFilterState;
116
- /** @deprecated Use defaultActiveViewId instead. */
117
- isDefault?: boolean;
118
- }
142
+ type KanbanRendererSavedView = CollectionSavedView<KanbanRendererSettings>;
119
143
  type KanbanRendererCreateFieldType = "text" | "longtext" | "markdown" | "number" | "boolean" | "select" | "multi-select" | "files";
120
144
  interface KanbanRendererCreateField {
121
145
  id: string;
@@ -155,28 +179,54 @@ interface KanbanRendererCreateSubmission {
155
179
  declare const DEFAULT_KANBAN_RENDERER_SETTINGS: KanbanRendererSettings;
156
180
  /**
157
181
  * Look up an attribute by id from a contribution-provided descriptor list.
158
- * Returns undefined for sentinels ("none", "manual") or unknown ids.
182
+ * Returns undefined for the "none" grouping or unknown ids.
159
183
  */
160
184
  declare const findAttribute: (attributes: AttributeDescriptor[], id: string | undefined) => AttributeDescriptor | undefined;
161
- interface KanbanRendererViewsSource {
162
- views: (KanbanRendererSavedView & {
163
- builtIn: boolean;
164
- })[];
165
- defaultViewId: string;
166
- onCreateView: (input: {
167
- title: string;
168
- settings: KanbanRendererSettings;
169
- filters: KanbanRendererFilterState;
170
- copyFrom?: string;
171
- }) => Promise<KanbanRendererSavedView>;
172
- onUpdateView: (id: string, input: {
173
- title?: string;
174
- settings?: KanbanRendererSettings;
175
- filters?: KanbanRendererFilterState;
176
- }) => Promise<void>;
177
- onDeleteView: (id: string) => Promise<void>;
178
- onSetDefaultView: (id: string | null) => Promise<void>;
179
- }
185
+ type KanbanRendererViewsSource = CollectionViewsSource<KanbanRendererSettings>;
186
+ //#endregion
187
+ //#region src/components/collection-view/use-collection-view-store.d.ts
188
+ /** The unsaved state of one renderer: the active view and the edits made on top of it. */
189
+ interface CollectionViewSnapshot<TSettings> {
190
+ settings: TSettings;
191
+ filter: ViewFilterGroup;
192
+ sorts: ViewSort[];
193
+ expandedGroups: Record<string, boolean>;
194
+ activeViewId: string;
195
+ }
196
+ type CollectionViewMenu = "filter";
197
+ interface CollectionViewStoreInitialState<TSettings> {
198
+ settings: TSettings;
199
+ filter?: ViewFilterGroup;
200
+ sorts?: ViewSort[];
201
+ }
202
+ interface CollectionViewStoreState<TSettings> extends CollectionViewSnapshot<TSettings> {
203
+ /** The view bar menu that is open. Screen state: never persisted. */
204
+ openMenu: CollectionViewMenu | null;
205
+ /** The root rule whose pill editor is open. Screen state: never persisted. */
206
+ openRuleIndex: number | null;
207
+ setOpenMenu: (menu: CollectionViewMenu | null) => void;
208
+ setOpenRuleIndex: (index: number | null) => void;
209
+ /** Adds a rule for the field and opens its pill editor. */
210
+ startRule: (field: AttributeDescriptor) => void;
211
+ /** Commits picker values; scalar values transfer editing to their bubble. */
212
+ selectRule: (rule: ViewFilterRule) => void;
213
+ setSettings: (settings: Partial<TSettings>) => void;
214
+ setFilter: (filter: ViewFilterGroup) => void;
215
+ setSorts: (sorts: ViewSort[]) => void;
216
+ setExpandedGroup: (groupId: string, isExpanded: boolean) => void;
217
+ activateView: (view: CollectionSavedView<TSettings>) => void;
218
+ reset: () => void;
219
+ }
220
+ declare const useCollectionViewStore: <TSettings, T>(storageKey: string, initialState: CollectionViewStoreInitialState<TSettings>, selector: (state: CollectionViewStoreState<TSettings>) => T) => T;
221
+ //#endregion
222
+ //#region src/components/collection-view/collection-view-fields.d.ts
223
+ declare const withTitleField: (attributes: AttributeDescriptor[]) => AttributeDescriptor[];
224
+ /**
225
+ * Read a typed attribute value out of a row. enum-multi normalizes to an array;
226
+ * single-valued kinds normalize to undefined when missing.
227
+ */
228
+ declare const getAttributeValue: (row: KanbanRendererRow, descriptor: AttributeDescriptor) => unknown;
229
+ declare const getAttributeStringValues: (row: KanbanRendererRow, descriptor: AttributeDescriptor) => string[];
180
230
  //#endregion
181
- export { SortDirection as C, isEnumOptionsSource as D, isAttributesSource as E, NO_GROUPING as S, findAttribute as T, KanbanRendererRow as _, AttributesSource as a, KanbanRendererViewsSource as b, EnumOption as c, KanbanRendererCreateField as d, KanbanRendererCreateFieldType as f, KanbanRendererOrdering as g, KanbanRendererFilterState as h, AttributeType as i, EnumOptions as l, KanbanRendererCreateSubmission as m, AttributeDisplayDescriptor as n, CollectionBadgeItem as o, KanbanRendererCreateRowConfig as p, AttributeKind as r, DEFAULT_KANBAN_RENDERER_SETTINGS as s, AttributeDescriptor as t, EnumOptionsSource as u, KanbanRendererSavedView as v, ViewMode as w, MANUAL_ORDERING as x, KanbanRendererSettings as y };
231
+ export { CollectionSavedView as A, KanbanRendererSettings as C, findAttribute as D, ViewMode as E, ViewFilterGroup$1 as F, ViewFilterRule$1 as I, ViewSort$1 as L, CollectionViewsSource as M, EMPTY_VIEW_FILTER as N, isAttributesSource as O, ViewFilterCondition as P, ViewSortDirection as R, KanbanRendererSavedView as S, NO_GROUPING as T, KanbanRendererCreateField as _, CollectionViewStoreState as a, KanbanRendererCreateSubmission as b, AttributeDisplayDescriptor as c, AttributesSource as d, CollectionBadgeItem as f, EnumOptionsSource as g, EnumOptions as h, CollectionViewStoreInitialState as i, CollectionViewState as j, isEnumOptionsSource as k, AttributeKind as l, EnumOption as m, getAttributeValue as n, useCollectionViewStore as o, DEFAULT_KANBAN_RENDERER_SETTINGS as p, withTitleField as r, AttributeDescriptor as s, getAttributeStringValues as t, AttributeType as u, KanbanRendererCreateFieldType as v, KanbanRendererViewsSource as w, KanbanRendererRow as x, KanbanRendererCreateRowConfig as y };
182
232
  export {};
@@ -0,0 +1,90 @@
1
+ import { S as e, _ as t, b as n, g as r, m as i, p as a, t as o, v as s } from "./collection-view-search-CpjJy76w.js";
2
+ import { Box as c } from "@chakra-ui/react";
3
+ import { jsx as l } from "react/jsx-runtime";
4
+ //#region src/components/collection-view/highlighted-text.tsx
5
+ var u = (e) => {
6
+ let { text: t, query: n } = e, r = o(t, n);
7
+ if (r.length === 0) return t;
8
+ let i = [], a = 0;
9
+ for (let [e, n] of r) e > a && i.push({
10
+ text: t.slice(a, e),
11
+ match: !1,
12
+ start: a
13
+ }), i.push({
14
+ text: t.slice(e, n),
15
+ match: !0,
16
+ start: e
17
+ }), a = n;
18
+ return a < t.length && i.push({
19
+ text: t.slice(a),
20
+ match: !1,
21
+ start: a
22
+ }), i.map((e) => e.match ? /* @__PURE__ */ l(c, {
23
+ as: "mark",
24
+ bg: "bg.warning",
25
+ color: "inherit",
26
+ borderRadius: "2xs",
27
+ children: e.text
28
+ }, e.start) : e.text);
29
+ }, d = (t, n, r) => {
30
+ if (r.kind !== "enum" && r.kind !== "enum-multi") return 0;
31
+ let i = e(r), a = (e) => {
32
+ if (e === void 0) return i.length;
33
+ let t = i.findIndex((t) => t.value === e);
34
+ return t === -1 ? i.length + 1 : t;
35
+ };
36
+ return a(t) - a(n);
37
+ }, f = (e) => s(e)?.getTime() ?? NaN, p = (e, n, i) => {
38
+ let a = t(e, i), o = t(n, i);
39
+ if (i.compare) return i.compare(a, o);
40
+ if (i.type.kind === "date") return f(a) - f(o);
41
+ if (i.type.kind === "number") return Number(a) - Number(o);
42
+ if (i.type.kind === "enum") {
43
+ let [t] = r(e, i), [a] = r(n, i);
44
+ return d(t, a, i.type);
45
+ }
46
+ return String(a).localeCompare(String(o), void 0, {
47
+ numeric: !0,
48
+ sensitivity: "base"
49
+ });
50
+ }, m = (e, n) => {
51
+ if (n.type.kind === "date") return s(t(e, n)) === void 0;
52
+ let [i] = r(e, n);
53
+ return i === void 0 || n.type.kind === "number" && !Number.isFinite(Number(i));
54
+ }, h = (e, t) => {
55
+ let n = i(t, e.attributeId);
56
+ if (!n || !a(n)) return;
57
+ let r = e.direction === "asc" ? 1 : -1;
58
+ return (e, t) => {
59
+ let i = m(e, n), a = m(t, n);
60
+ return i || a ? Number(i) - Number(a) : r * p(e, t, n);
61
+ };
62
+ }, g = (e, t, n) => {
63
+ let r = t[0], i = r ? h(r, n) : void 0;
64
+ return i ? [...e].sort(i) : e;
65
+ }, _ = (e) => `No ${e.label.toLowerCase()}`, v = (e, t) => e === _(t) ? e : t.type.kind === "enum" || t.type.kind === "enum-multi" ? n(t.type, e) : e, y = (t, n) => {
66
+ if (t !== void 0) return n.type.kind !== "enum" && n.type.kind !== "enum-multi" || e(n.type).some((e) => e.value === t) ? t : void 0;
67
+ }, b = (e, t) => {
68
+ let [n] = r(e, t);
69
+ return y(n, t) ?? _(t);
70
+ }, x = (e, t, n) => {
71
+ let r = _(n);
72
+ if (e === r || t === r) return Number(e === r) - Number(t === r);
73
+ let i = d(e, t, n.type);
74
+ return i === 0 ? e.localeCompare(t, void 0, { numeric: !0 }) : i;
75
+ }, S = (e, t, n = []) => {
76
+ let r = new Map(n.map((e) => [e, []]));
77
+ for (let n of e) {
78
+ let e = b(n, t), i = r.get(e);
79
+ i ? i.push(n) : r.set(e, [n]);
80
+ }
81
+ return [...r.entries()].sort(([e], [n]) => x(e, n, t)).map(([e, n]) => ({
82
+ key: e,
83
+ label: v(e, t),
84
+ rows: n
85
+ }));
86
+ };
87
+ //#endregion
88
+ export { u as a, g as i, b as n, S as r, _ as t };
89
+
90
+ //# sourceMappingURL=collection-view-grouping-D4nZk8-3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-view-grouping-D4nZk8-3.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","getEnumOptions","getAttributeValue","enumOptionLabel","getAttributeStringValues","findField","canSortField","findSearchRanges","parseViewDate","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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"}