@spfx-fast/sharepoint-ui 0.4.2 → 0.5.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 (276) hide show
  1. package/QUICKSTART.md +18 -0
  2. package/README.md +19 -24
  3. package/components.json +240 -5694
  4. package/dist/accordion.d.ts +11 -0
  5. package/dist/accordion.js +4 -0
  6. package/dist/alert.d.ts +3 -0
  7. package/dist/alert.js +4 -0
  8. package/dist/attachment-list.d.ts +15 -0
  9. package/dist/attachment-list.js +14 -0
  10. package/dist/avatar-group.d.ts +12 -0
  11. package/dist/avatar-group.js +7 -0
  12. package/dist/avatar.d.ts +6 -0
  13. package/dist/avatar.js +5 -0
  14. package/dist/badge.d.ts +3 -0
  15. package/dist/badge.js +4 -0
  16. package/dist/breadcrumb.d.ts +10 -0
  17. package/dist/breadcrumb.js +9 -0
  18. package/dist/button-group.d.ts +6 -0
  19. package/dist/button-group.js +4 -0
  20. package/dist/button.d.ts +3 -0
  21. package/dist/button.js +4 -0
  22. package/dist/card.d.ts +3 -0
  23. package/dist/card.js +4 -0
  24. package/dist/carousel.d.ts +11 -0
  25. package/dist/carousel.js +6 -0
  26. package/dist/checkbox.d.ts +3 -0
  27. package/dist/checkbox.js +4 -0
  28. package/dist/combobox.d.ts +9 -0
  29. package/dist/combobox.js +6 -0
  30. package/dist/command-bar.d.ts +6 -0
  31. package/dist/command-bar.js +4 -0
  32. package/dist/copy-button.d.ts +7 -0
  33. package/dist/copy-button.js +19 -0
  34. package/dist/data-grid.d.ts +25 -0
  35. package/dist/data-grid.js +39 -0
  36. package/dist/date-range-picker.d.ts +12 -0
  37. package/dist/date-range-picker.js +4 -0
  38. package/dist/dialog.d.ts +9 -0
  39. package/dist/dialog.js +21 -0
  40. package/dist/divider.d.ts +3 -0
  41. package/dist/divider.js +4 -0
  42. package/dist/drawer.d.ts +6 -0
  43. package/dist/drawer.js +5 -0
  44. package/dist/empty-state.d.ts +7 -0
  45. package/dist/empty-state.js +5 -0
  46. package/dist/field.d.ts +15 -0
  47. package/dist/field.js +11 -0
  48. package/dist/file-dropzone.d.ts +15 -0
  49. package/dist/file-dropzone.js +21 -0
  50. package/dist/filter-bar.d.ts +9 -0
  51. package/dist/filter-bar.js +9 -0
  52. package/dist/image.d.ts +5 -0
  53. package/dist/image.js +4 -0
  54. package/dist/index.d.ts +68 -76
  55. package/dist/index.js +60 -66
  56. package/dist/input.d.ts +3 -0
  57. package/dist/input.js +4 -0
  58. package/dist/label.d.ts +3 -0
  59. package/dist/label.js +4 -0
  60. package/dist/link.d.ts +3 -0
  61. package/dist/link.js +9 -0
  62. package/dist/list-view.d.ts +29 -0
  63. package/dist/list-view.js +14 -0
  64. package/dist/list.d.ts +6 -0
  65. package/dist/list.js +5 -0
  66. package/dist/lookup-picker.d.ts +12 -0
  67. package/dist/lookup-picker.js +4 -0
  68. package/dist/menu.d.ts +6 -0
  69. package/dist/menu.js +4 -0
  70. package/dist/nav.d.ts +12 -0
  71. package/dist/nav.js +4 -0
  72. package/dist/pagination.d.ts +11 -0
  73. package/dist/pagination.js +5 -0
  74. package/dist/person-picker.d.ts +13 -0
  75. package/dist/person-picker.js +4 -0
  76. package/dist/persona.d.ts +7 -0
  77. package/dist/persona.js +5 -0
  78. package/dist/popover.d.ts +6 -0
  79. package/dist/popover.js +4 -0
  80. package/dist/progress-bar.d.ts +5 -0
  81. package/dist/progress-bar.js +5 -0
  82. package/dist/radio-group.d.ts +6 -0
  83. package/dist/radio-group.js +4 -0
  84. package/dist/radio.d.ts +3 -0
  85. package/dist/radio.js +4 -0
  86. package/dist/rating.d.ts +8 -0
  87. package/dist/rating.js +5 -0
  88. package/dist/react.d.ts +1 -4583
  89. package/dist/react.js +1 -6837
  90. package/dist/select.d.ts +3 -0
  91. package/dist/select.js +4 -0
  92. package/dist/sharepoint-field.d.ts +18 -0
  93. package/dist/sharepoint-field.js +54 -0
  94. package/dist/skeleton.d.ts +6 -0
  95. package/dist/skeleton.js +9 -0
  96. package/dist/spinner.d.ts +5 -0
  97. package/dist/spinner.js +4 -0
  98. package/dist/swatch-picker.d.ts +17 -0
  99. package/dist/swatch-picker.js +11 -0
  100. package/dist/switch.d.ts +3 -0
  101. package/dist/switch.js +4 -0
  102. package/dist/table.d.ts +6 -0
  103. package/dist/table.js +4 -0
  104. package/dist/tabs.d.ts +14 -0
  105. package/dist/tabs.js +30 -0
  106. package/dist/tag-group.d.ts +6 -0
  107. package/dist/tag-group.js +4 -0
  108. package/dist/tag-picker.d.ts +12 -0
  109. package/dist/tag-picker.js +4 -0
  110. package/dist/tag.d.ts +7 -0
  111. package/dist/tag.js +5 -0
  112. package/dist/text.d.ts +5 -0
  113. package/dist/text.js +4 -0
  114. package/dist/textarea.d.ts +3 -0
  115. package/dist/textarea.js +4 -0
  116. package/dist/theme.d.ts +15 -167
  117. package/dist/theme.js +36 -162
  118. package/dist/toast.d.ts +9 -0
  119. package/dist/toast.js +12 -0
  120. package/dist/tree.d.ts +13 -0
  121. package/dist/tree.js +9 -0
  122. package/dist/view-card.d.ts +8 -0
  123. package/dist/view-card.js +4 -0
  124. package/dist/view-switcher.d.ts +13 -0
  125. package/dist/view-switcher.js +7 -0
  126. package/dist/virtual-list.d.ts +11 -0
  127. package/dist/virtual-list.js +25 -0
  128. package/measurements.json +365 -0
  129. package/package.json +19 -42
  130. package/src/theme.css +125 -0
  131. package/AGENTS.md +0 -211
  132. package/dist/appearance.d.ts +0 -6
  133. package/dist/appearance.js +0 -217
  134. package/dist/elements/accordion.d.ts +0 -9
  135. package/dist/elements/accordion.js +0 -338
  136. package/dist/elements/alert.d.ts +0 -2
  137. package/dist/elements/alert.js +0 -62
  138. package/dist/elements/avatar-group-primitives.d.ts +0 -3
  139. package/dist/elements/avatar-group-primitives.js +0 -189
  140. package/dist/elements/avatar-group.d.ts +0 -2
  141. package/dist/elements/avatar-group.js +0 -110
  142. package/dist/elements/avatar.d.ts +0 -4
  143. package/dist/elements/avatar.js +0 -251
  144. package/dist/elements/badge.d.ts +0 -8
  145. package/dist/elements/badge.js +0 -182
  146. package/dist/elements/breadcrumb.d.ts +0 -4
  147. package/dist/elements/breadcrumb.js +0 -233
  148. package/dist/elements/button-group.d.ts +0 -1
  149. package/dist/elements/button-group.js +0 -20
  150. package/dist/elements/button-variants.d.ts +0 -6
  151. package/dist/elements/button-variants.js +0 -339
  152. package/dist/elements/button.d.ts +0 -5
  153. package/dist/elements/button.js +0 -233
  154. package/dist/elements/card-primitives.d.ts +0 -3
  155. package/dist/elements/card-primitives.js +0 -83
  156. package/dist/elements/card.d.ts +0 -5
  157. package/dist/elements/card.js +0 -213
  158. package/dist/elements/carousel.d.ts +0 -92
  159. package/dist/elements/carousel.js +0 -1112
  160. package/dist/elements/color-picker.d.ts +0 -24
  161. package/dist/elements/color-picker.js +0 -1004
  162. package/dist/elements/combobox.d.ts +0 -1
  163. package/dist/elements/combobox.js +0 -1012
  164. package/dist/elements/data-grid-model.d.ts +0 -117
  165. package/dist/elements/data-grid-model.js +0 -294
  166. package/dist/elements/data-grid.d.ts +0 -29
  167. package/dist/elements/data-grid.js +0 -1567
  168. package/dist/elements/date-picker.d.ts +0 -1
  169. package/dist/elements/date-picker.js +0 -486
  170. package/dist/elements/dialog.d.ts +0 -23
  171. package/dist/elements/dialog.js +0 -409
  172. package/dist/elements/divider.d.ts +0 -2
  173. package/dist/elements/divider.js +0 -66
  174. package/dist/elements/drawer.d.ts +0 -3
  175. package/dist/elements/drawer.js +0 -308
  176. package/dist/elements/field-composition.d.ts +0 -26
  177. package/dist/elements/field-composition.js +0 -133
  178. package/dist/elements/field.d.ts +0 -1
  179. package/dist/elements/field.js +0 -67
  180. package/dist/elements/file-upload.d.ts +0 -6
  181. package/dist/elements/file-upload.js +0 -211
  182. package/dist/elements/floating-position.d.ts +0 -26
  183. package/dist/elements/floating-position.js +0 -39
  184. package/dist/elements/image.d.ts +0 -28
  185. package/dist/elements/image.js +0 -38
  186. package/dist/elements/info.d.ts +0 -9
  187. package/dist/elements/info.js +0 -102
  188. package/dist/elements/input.d.ts +0 -5
  189. package/dist/elements/input.js +0 -255
  190. package/dist/elements/label.d.ts +0 -15
  191. package/dist/elements/label.js +0 -56
  192. package/dist/elements/link.d.ts +0 -1
  193. package/dist/elements/link.js +0 -92
  194. package/dist/elements/list.d.ts +0 -19
  195. package/dist/elements/list.js +0 -297
  196. package/dist/elements/menu.d.ts +0 -33
  197. package/dist/elements/menu.js +0 -1103
  198. package/dist/elements/message-bar.d.ts +0 -10
  199. package/dist/elements/message-bar.js +0 -299
  200. package/dist/elements/nav.d.ts +0 -32
  201. package/dist/elements/nav.js +0 -791
  202. package/dist/elements/overflow.d.ts +0 -9
  203. package/dist/elements/overflow.js +0 -218
  204. package/dist/elements/persona.d.ts +0 -3
  205. package/dist/elements/persona.js +0 -125
  206. package/dist/elements/popover.d.ts +0 -77
  207. package/dist/elements/popover.js +0 -840
  208. package/dist/elements/progress-bar.d.ts +0 -4
  209. package/dist/elements/progress-bar.js +0 -82
  210. package/dist/elements/radio-group.d.ts +0 -1
  211. package/dist/elements/radio-group.js +0 -303
  212. package/dist/elements/rating-display.d.ts +0 -2
  213. package/dist/elements/rating-display.js +0 -125
  214. package/dist/elements/rating.d.ts +0 -2
  215. package/dist/elements/rating.js +0 -206
  216. package/dist/elements/rich-text-editor.d.ts +0 -18
  217. package/dist/elements/rich-text-editor.js +0 -508
  218. package/dist/elements/search.d.ts +0 -3
  219. package/dist/elements/search.js +0 -207
  220. package/dist/elements/select.d.ts +0 -6
  221. package/dist/elements/select.js +0 -291
  222. package/dist/elements/shared.d.ts +0 -19
  223. package/dist/elements/shared.js +0 -396
  224. package/dist/elements/skeleton.d.ts +0 -6
  225. package/dist/elements/skeleton.js +0 -91
  226. package/dist/elements/slider.d.ts +0 -1
  227. package/dist/elements/slider.js +0 -248
  228. package/dist/elements/spin-button.d.ts +0 -7
  229. package/dist/elements/spin-button.js +0 -499
  230. package/dist/elements/spinner.d.ts +0 -4
  231. package/dist/elements/spinner.js +0 -124
  232. package/dist/elements/swatch-picker.d.ts +0 -5
  233. package/dist/elements/swatch-picker.js +0 -363
  234. package/dist/elements/table.d.ts +0 -21
  235. package/dist/elements/table.js +0 -261
  236. package/dist/elements/tabs.d.ts +0 -1
  237. package/dist/elements/tabs.js +0 -276
  238. package/dist/elements/tag-picker.d.ts +0 -29
  239. package/dist/elements/tag-picker.js +0 -697
  240. package/dist/elements/tags.d.ts +0 -21
  241. package/dist/elements/tags.js +0 -421
  242. package/dist/elements/teaching-popover.d.ts +0 -32
  243. package/dist/elements/teaching-popover.js +0 -412
  244. package/dist/elements/text.d.ts +0 -9
  245. package/dist/elements/text.js +0 -75
  246. package/dist/elements/textarea.d.ts +0 -1
  247. package/dist/elements/textarea.js +0 -182
  248. package/dist/elements/toast.d.ts +0 -25
  249. package/dist/elements/toast.js +0 -337
  250. package/dist/elements/toaster.d.ts +0 -6
  251. package/dist/elements/toaster.js +0 -356
  252. package/dist/elements/toggle.d.ts +0 -2
  253. package/dist/elements/toggle.js +0 -246
  254. package/dist/elements/toolbar.d.ts +0 -12
  255. package/dist/elements/toolbar.js +0 -381
  256. package/dist/elements/tooltip.d.ts +0 -76
  257. package/dist/elements/tooltip.js +0 -510
  258. package/dist/elements/tree-model.d.ts +0 -19
  259. package/dist/elements/tree-model.js +0 -34
  260. package/dist/elements/tree.d.ts +0 -5
  261. package/dist/elements/tree.js +0 -273
  262. package/dist/elements/view-card.d.ts +0 -2
  263. package/dist/elements/view-card.js +0 -78
  264. package/dist/elements/virtual-list.d.ts +0 -41
  265. package/dist/elements/virtual-list.js +0 -369
  266. package/dist/elements.d.ts +0 -72
  267. package/dist/elements.js +0 -207
  268. package/dist/virtualizer-hooks.d.ts +0 -80
  269. package/dist/virtualizer-hooks.js +0 -253
  270. package/scripts/generate-token-index.mjs +0 -43
  271. package/scripts/sync-component-catalog-signatures.mjs +0 -55
  272. package/scripts/validate-component-catalog.mjs +0 -44
  273. package/skills/sharepoint-ui/SKILL.md +0 -12
  274. package/skills/sharepoint-ui/references/choosing-components.md +0 -20
  275. package/skills/sharepoint-ui/references/sharepoint-patterns.md +0 -17
  276. package/tokens.json +0 -3777
@@ -1,117 +0,0 @@
1
- export type DataGridSortDirection = "ascending" | "descending";
2
- /** Keyboard entry and movement strategy for the DataGrid. */
3
- export type DataGridFocusMode = "none" | "cell" | "row_unstable" | "composite";
4
- export type DataGridSelectionAppearance = "brand" | "neutral" | "none";
5
- export type DataGridSort = {
6
- columnId: string;
7
- direction: DataGridSortDirection;
8
- };
9
- export type DataGridSortState = DataGridSort | readonly DataGridSort[];
10
- export type DataGridColumn<T = unknown> = {
11
- id: string;
12
- label: string;
13
- sortable?: boolean;
14
- searchable?: boolean;
15
- width?: string;
16
- minWidth?: number;
17
- maxWidth?: number;
18
- resizable?: boolean;
19
- editable?: boolean;
20
- editType?: "text" | "number" | "date";
21
- value?: (item: T) => string | number | Date | null | undefined;
22
- };
23
- export type DataGridColumnWidths = Readonly<Record<string, number>>;
24
- export type DataGridDataSourceRow<T = unknown> = {
25
- kind: "item";
26
- item: T;
27
- rowId?: string | number;
28
- itemIndex?: number;
29
- } | {
30
- kind: "group";
31
- key: string;
32
- label: string;
33
- count: number;
34
- expanded: boolean;
35
- };
36
- /** Compact selection for indexed queries; all mode selects the source's current matching rows except excluded keys. */
37
- export type DataGridSelectionModel = {
38
- mode: "explicit";
39
- keys: readonly string[];
40
- } | {
41
- mode: "all";
42
- excludedKeys: readonly string[];
43
- scopeKey?: string;
44
- };
45
- export type DataGridClipboardColumn = Pick<DataGridColumn, "id" | "label">;
46
- export declare function isDataGridRowSelected(selection: DataGridSelectionModel, key: string, scopeKey?: string): boolean;
47
- export declare function setDataGridRowSelected(selection: DataGridSelectionModel, key: string, selected: boolean, scopeKey?: string): DataGridSelectionModel;
48
- /** Indexed provider for server-owned grid order, filtering, grouping, and sorting. Length counts displayed rows, including group headers. */
49
- export type DataGridDataSource<T = unknown> = {
50
- readonly length: number;
51
- /** Optional exact number of selectable item rows, excluding group headers. */
52
- readonly selectableCount?: number;
53
- /** Stable identity of the current server query; binds all-matching selection to that query. */
54
- readonly selectionScopeKey?: string;
55
- loadRange(start: number, end: number, signal: AbortSignal): void | Promise<void>;
56
- /** Return TSV for the provider query and compact selection; implement for remote or all-matching copy. */
57
- copySelection?(selection: DataGridSelectionModel, columns: readonly DataGridClipboardColumn[], signal: AbortSignal): string | Promise<string>;
58
- subscribe?(listener: () => void): () => void;
59
- } & ({
60
- getItem(index: number): T | undefined;
61
- getRow?: (index: number) => DataGridDataSourceRow<T> | undefined;
62
- } | {
63
- getRow(index: number): DataGridDataSourceRow<T> | undefined;
64
- getItem?: (index: number) => T | undefined;
65
- });
66
- /** Start an async clipboard write during the user gesture; ClipboardItem accepts a promised Blob. */
67
- export declare function writeDataGridClipboardText(text: string | Promise<string>): Promise<void>;
68
- export declare function getDataGridDataSourceRow<T>(source: DataGridDataSource<T>, index: number): DataGridDataSourceRow<T> | undefined;
69
- /** Per-column sizing configuration compatible with Fluent DataGrid sizing options. */
70
- export type DataGridColumnSizingOption = {
71
- defaultWidth?: number;
72
- idealWidth?: number;
73
- minWidth?: number;
74
- padding?: number;
75
- autoFitColumns?: boolean;
76
- };
77
- export type DataGridColumnSizingOptions = Readonly<Record<string, DataGridColumnSizingOption>>;
78
- export declare function getDataGridColumnSizing<T>(column: DataGridColumn<T>, options?: DataGridColumnSizingOptions): Required<Pick<DataGridColumnSizingOption, "defaultWidth" | "idealWidth" | "minWidth" | "padding" | "autoFitColumns">>;
79
- /** Apply Fluent's grow-to-ideal / shrink-from-end auto-fit policy to configured tracks. */
80
- export declare function fitDataGridColumnWidths<T>(columns: readonly DataGridColumn<T>[], viewportWidth: number, options?: DataGridColumnSizingOptions, currentWidths?: DataGridColumnWidths, reservedWidth?: number): DataGridColumnWidths;
81
- export type DataGridGroup<T = unknown> = {
82
- key: string;
83
- label: string;
84
- value: string | number | Date | null | undefined;
85
- items: T[];
86
- indices: number[];
87
- };
88
- export type DataGridEditValue = string | number | null;
89
- export type DataGridCellEdit<T = unknown> = {
90
- item: T;
91
- rowId: string;
92
- columnId: string;
93
- previousValue: unknown;
94
- value: DataGridEditValue;
95
- };
96
- /** Bound row sizes to keep a consumer callback from creating pathological virtual scroll extents. */
97
- export declare function clampDataGridRowHeight(height: number | undefined, estimate: number): number;
98
- export declare function getDataGridCellValue<T>(item: T, column: DataGridColumn<T>): unknown;
99
- export declare function toDataGridInputValue(value: unknown, type?: DataGridColumn["editType"]): string;
100
- export declare function parseDataGridInputValue(value: string, type?: DataGridColumn["editType"]): DataGridEditValue;
101
- /** Parse tab-separated clipboard text, including quoted tabs, newlines, and doubled quotes. */
102
- export declare function parseDataGridClipboard(text: string): string[][];
103
- export declare function formatDataGridClipboard(rows: readonly (readonly unknown[])[]): string;
104
- export declare function parseDataGridClipboardValue(value: string, type?: DataGridColumn["editType"]): DataGridEditValue;
105
- /** Locale-aware contains filter across searchable columns, preserving source order. */
106
- export declare function filterDataGridItems<T>(items: readonly T[], columns: readonly DataGridColumn<T>[], query: string, locale?: string): T[];
107
- export declare function getDataGridGroupKey(columnId: string, value: string | number | Date | null | undefined): string;
108
- export declare function groupDataGridItems<T>(items: readonly T[], columns: readonly DataGridColumn<T>[], groupBy: string | undefined, locale?: string, emptyLabel?: string): DataGridGroup<T>[] | undefined;
109
- export declare function dataGridColumnVar(columnId: string): string;
110
- /** Find the visible column interval from laid-out header cells, including RTL order. */
111
- export declare function getDataGridColumnWindow(cells: readonly HTMLElement[], viewport: HTMLElement, overscan?: number): {
112
- start: number;
113
- end: number;
114
- };
115
- export declare function clampDataGridColumnWidth<T>(column: DataGridColumn<T>, width: number, sizing?: DataGridColumnSizingOption): number;
116
- /** Stable, locale-aware sort shared by the React adapter and custom element. */
117
- export declare function sortDataGridItems<T>(items: readonly T[], columns: readonly DataGridColumn<T>[], sort?: DataGridSortState, locale?: string): T[];
@@ -1,294 +0,0 @@
1
- export function isDataGridRowSelected(selection, key, scopeKey) {
2
- return selection.mode === "all" ? (selection.scopeKey === undefined || selection.scopeKey === scopeKey) && !selection.excludedKeys.includes(key) : selection.keys.includes(key);
3
- }
4
- export function setDataGridRowSelected(selection, key, selected, scopeKey) {
5
- if (selection.mode === "all" && (selection.scopeKey === undefined || selection.scopeKey === scopeKey)) {
6
- const excludedKeys = new Set(selection.excludedKeys);
7
- if (selected)
8
- excludedKeys.delete(key);
9
- else
10
- excludedKeys.add(key);
11
- return { mode: "all", excludedKeys: [...excludedKeys], ...(selection.scopeKey === undefined ? {} : { scopeKey: selection.scopeKey }) };
12
- }
13
- const keys = new Set(selection.mode === "explicit" ? selection.keys : []);
14
- if (selected)
15
- keys.add(key);
16
- else
17
- keys.delete(key);
18
- return { mode: "explicit", keys: [...keys] };
19
- }
20
- /** Start an async clipboard write during the user gesture; ClipboardItem accepts a promised Blob. */
21
- export function writeDataGridClipboardText(text) {
22
- const clipboard = globalThis.navigator?.clipboard;
23
- if (!clipboard)
24
- return Promise.reject(new Error("Clipboard access is unavailable in this browser."));
25
- if (clipboard.write && typeof globalThis.ClipboardItem === "function") {
26
- const value = Promise.resolve(text).then(result => new Blob([result], { type: "text/plain" }));
27
- return clipboard.write([new ClipboardItem({ "text/plain": value })]);
28
- }
29
- return Promise.resolve(text).then(result => {
30
- if (!clipboard.writeText)
31
- throw new Error("Async clipboard writing is not supported in this browser.");
32
- return clipboard.writeText(result);
33
- });
34
- }
35
- export function getDataGridDataSourceRow(source, index) {
36
- const row = source.getRow?.(index);
37
- if (row)
38
- return row;
39
- const item = source.getItem?.(index);
40
- return item === undefined ? undefined : { kind: "item", item };
41
- }
42
- export function getDataGridColumnSizing(column, options) {
43
- const configured = options?.[column.id];
44
- const minWidth = Number.isFinite(configured?.minWidth) && configured.minWidth > 0 ? configured.minWidth : Number.isFinite(column.minWidth) && column.minWidth > 0 ? column.minWidth : configured ? 100 : 48;
45
- const maxWidth = Number.isFinite(column.maxWidth) && column.maxWidth >= minWidth ? column.maxWidth : 1600;
46
- const cssWidth = typeof column.width === "string" && /^\d+(?:\.\d+)?px$/.test(column.width) ? Number.parseFloat(column.width) : undefined;
47
- const idealWidth = Math.round(Math.max(minWidth, Math.min(maxWidth, Number.isFinite(configured?.idealWidth) && configured.idealWidth > 0 ? configured.idealWidth : Number.isFinite(configured?.defaultWidth) && configured.defaultWidth > 0 ? configured.defaultWidth : 150)));
48
- const defaultWidth = Math.round(Math.max(minWidth, Math.min(maxWidth, Number.isFinite(configured?.defaultWidth) && configured.defaultWidth > 0 ? configured.defaultWidth : cssWidth ?? idealWidth)));
49
- return { defaultWidth, idealWidth, minWidth, padding: Number.isFinite(configured?.padding) && configured.padding >= 0 ? configured.padding : 16, autoFitColumns: configured?.autoFitColumns !== false };
50
- }
51
- /** Apply Fluent's grow-to-ideal / shrink-from-end auto-fit policy to configured tracks. */
52
- export function fitDataGridColumnWidths(columns, viewportWidth, options, currentWidths = {}, reservedWidth = 0) {
53
- if (!Number.isFinite(viewportWidth) || viewportWidth <= 0 || !columns.length)
54
- return {};
55
- const state = columns.map(column => {
56
- const sizing = getDataGridColumnSizing(column, options);
57
- const minWidth = sizing.minWidth;
58
- const maxWidth = Number.isFinite(column.maxWidth) && column.maxWidth >= minWidth ? column.maxWidth : 1600;
59
- const current = currentWidths[column.id];
60
- const width = Math.max(minWidth, Math.min(maxWidth, Number.isFinite(current) && current > 0 ? current : sizing.defaultWidth));
61
- const idealWidth = Number.isFinite(current) && current > 0 ? width : Math.max(width, Math.min(maxWidth, sizing.idealWidth));
62
- return { column, width, idealWidth, minWidth, maxWidth, padding: sizing.padding };
63
- });
64
- const available = Math.max(0, viewportWidth - Math.max(0, reservedWidth) + state.reduce((sum, entry) => sum + entry.padding, 0));
65
- let total = state.reduce((sum, entry) => sum + entry.width + entry.padding, 0);
66
- if (total < available) {
67
- let remaining = available - total;
68
- for (const entry of state) {
69
- const grow = Math.min(Math.max(0, entry.idealWidth - entry.width), remaining);
70
- entry.width += grow;
71
- remaining -= grow;
72
- if (remaining <= 0)
73
- break;
74
- }
75
- if (remaining > 0) {
76
- const last = state[state.length - 1];
77
- const grow = Math.min(remaining, Math.max(0, last.maxWidth - last.width));
78
- last.width += grow;
79
- }
80
- }
81
- else if (total > available) {
82
- let remaining = total - available;
83
- for (let index = state.length - 1; index >= 0 && remaining > 0; index--) {
84
- const entry = state[index];
85
- const shrink = Math.min(Math.max(0, entry.width - entry.minWidth), remaining);
86
- entry.width -= shrink;
87
- remaining -= shrink;
88
- }
89
- }
90
- return Object.fromEntries(state.map(entry => [entry.column.id, Math.round(entry.width)]));
91
- }
92
- /** Bound row sizes to keep a consumer callback from creating pathological virtual scroll extents. */
93
- export function clampDataGridRowHeight(height, estimate) {
94
- return Number.isFinite(height) && height > 0 ? Math.max(1, Math.min(10_000, height)) : estimate;
95
- }
96
- export function getDataGridCellValue(item, column) {
97
- return column.value ? column.value(item) : item?.[column.id];
98
- }
99
- export function toDataGridInputValue(value, type = "text") {
100
- if (value == null)
101
- return "";
102
- if (type === "date" && value instanceof Date)
103
- return Number.isFinite(value.valueOf()) ? value.toISOString().slice(0, 10) : "";
104
- return String(value);
105
- }
106
- export function parseDataGridInputValue(value, type = "text") {
107
- if (value === "")
108
- return null;
109
- if (type === "number") {
110
- const number = Number(value);
111
- return Number.isFinite(number) ? number : value;
112
- }
113
- return value;
114
- }
115
- /** Parse tab-separated clipboard text, including quoted tabs, newlines, and doubled quotes. */
116
- export function parseDataGridClipboard(text) {
117
- if (text.length > 1_000_000)
118
- throw new Error("Clipboard data is limited to 1,000,000 characters.");
119
- const rows = [];
120
- let row = [], cell = "", quoted = false;
121
- for (let index = 0; index < text.length; index++) {
122
- const character = text[index];
123
- if (quoted) {
124
- if (character === '"' && text[index + 1] === '"') {
125
- cell += '"';
126
- index++;
127
- }
128
- else if (character === '"')
129
- quoted = false;
130
- else
131
- cell += character;
132
- }
133
- else if (character === '"' && cell.length === 0)
134
- quoted = true;
135
- else if (character === "\t") {
136
- row.push(cell);
137
- cell = "";
138
- }
139
- else if (character === "\r" || character === "\n") {
140
- row.push(cell);
141
- rows.push(row);
142
- row = [];
143
- cell = "";
144
- if (character === "\r" && text[index + 1] === "\n")
145
- index++;
146
- }
147
- else
148
- cell += character;
149
- }
150
- if (quoted)
151
- throw new Error("Clipboard data contains an unfinished quoted cell.");
152
- if (cell.length || row.length || !rows.length) {
153
- row.push(cell);
154
- rows.push(row);
155
- }
156
- return rows;
157
- }
158
- export function formatDataGridClipboard(rows) {
159
- return rows.map(row => row.map(raw => {
160
- const value = raw instanceof Date ? Number.isFinite(raw.valueOf()) ? raw.toISOString() : "" : raw == null ? "" : String(raw);
161
- return /[\t\r\n"]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value;
162
- }).join("\t")).join("\r\n");
163
- }
164
- export function parseDataGridClipboardValue(value, type = "text") {
165
- if (type === "number") {
166
- const normalized = value.trim();
167
- if (!normalized)
168
- return null;
169
- const number = Number(normalized);
170
- if (!Number.isFinite(number))
171
- throw new Error(`“${value}” is not a valid number.`);
172
- return number;
173
- }
174
- if (type === "date") {
175
- const normalized = value.trim();
176
- if (!normalized)
177
- return null;
178
- if (!/^\d{4}-\d{2}-\d{2}$/.test(normalized) || new Date(`${normalized}T00:00:00Z`).toISOString().slice(0, 10) !== normalized)
179
- throw new Error(`“${value}” is not a valid date.`);
180
- return normalized;
181
- }
182
- return value;
183
- }
184
- /** Locale-aware contains filter across searchable columns, preserving source order. */
185
- export function filterDataGridItems(items, columns, query, locale) {
186
- const normalized = query.trim();
187
- if (!normalized)
188
- return [...items];
189
- let searchLocale;
190
- try {
191
- searchLocale = locale?.trim() || undefined;
192
- normalized.toLocaleLowerCase(searchLocale);
193
- }
194
- catch {
195
- searchLocale = undefined;
196
- }
197
- const needle = normalized.toLocaleLowerCase(searchLocale);
198
- const searchableColumns = columns.filter(column => column.searchable !== false);
199
- if (!searchableColumns.length)
200
- return [...items];
201
- return items.filter(item => searchableColumns.some(column => {
202
- const value = column.value ? column.value(item) : item?.[column.id];
203
- if (value == null)
204
- return false;
205
- const text = value instanceof Date ? Number.isFinite(value.valueOf()) ? `${value.toISOString()} ${value.toLocaleDateString(searchLocale)}` : "" : Array.isArray(value) ? value.join(" ") : typeof value === "object" ? "" : String(value);
206
- return text.toLocaleLowerCase(searchLocale).includes(needle);
207
- }));
208
- }
209
- export function getDataGridGroupKey(columnId, value) {
210
- const type = value instanceof Date ? "date" : value === null || value === undefined ? "empty" : typeof value;
211
- const normalized = value instanceof Date ? Number.isFinite(value.valueOf()) ? value.toISOString() : "invalid" : value === null || value === undefined ? "" : String(value);
212
- return JSON.stringify([columnId, type, normalized]);
213
- }
214
- export function groupDataGridItems(items, columns, groupBy, locale, emptyLabel = "No value") {
215
- const column = groupBy ? columns.find(candidate => candidate.id === groupBy) : undefined;
216
- if (!column)
217
- return undefined;
218
- const groups = new Map();
219
- items.forEach((item, index) => {
220
- const value = column.value ? column.value(item) : item?.[column.id];
221
- const key = getDataGridGroupKey(column.id, value);
222
- let group = groups.get(key);
223
- if (!group) {
224
- const label = value === null || value === undefined ? emptyLabel : value instanceof Date ? Number.isFinite(value.valueOf()) ? value.toLocaleDateString(locale || undefined) : emptyLabel : String(value);
225
- group = { key, label, value, items: [], indices: [] };
226
- groups.set(key, group);
227
- }
228
- group.items.push(item);
229
- group.indices.push(index);
230
- });
231
- return [...groups.values()];
232
- }
233
- export function dataGridColumnVar(columnId) {
234
- const suffix = Array.from(columnId, char => `_${char.codePointAt(0).toString(16)}_`).join("");
235
- return `--spui-data-grid-column-${suffix}`;
236
- }
237
- /** Find the visible column interval from laid-out header cells, including RTL order. */
238
- export function getDataGridColumnWindow(cells, viewport, overscan = 2) {
239
- if (!cells.length)
240
- return { start: 0, end: 0 };
241
- const bounds = viewport.getBoundingClientRect();
242
- const left = bounds.left + viewport.clientLeft;
243
- const right = left + viewport.clientWidth;
244
- const rtl = getComputedStyle(viewport).direction === "rtl";
245
- const firstVisible = (cell) => rtl ? cell.getBoundingClientRect().left < right : cell.getBoundingClientRect().right > left;
246
- const lastVisible = (cell) => rtl ? cell.getBoundingClientRect().right > left : cell.getBoundingClientRect().left < right;
247
- const lowerBound = (predicate) => {
248
- let low = 0, high = cells.length;
249
- while (low < high) {
250
- const middle = (low + high) >>> 1;
251
- if (predicate(cells[middle]))
252
- high = middle;
253
- else
254
- low = middle + 1;
255
- }
256
- return low;
257
- };
258
- let start = lowerBound(firstVisible);
259
- let afterLast = lowerBound(cell => !lastVisible(cell));
260
- if (start >= cells.length || afterLast <= start)
261
- return { start: 0, end: cells.length };
262
- const buffer = Number.isFinite(overscan) ? Math.max(0, Math.min(20, Math.floor(overscan))) : 2;
263
- start = Math.max(0, start - buffer);
264
- return { start, end: Math.min(cells.length, afterLast + buffer) };
265
- }
266
- export function clampDataGridColumnWidth(column, width, sizing) {
267
- const min = Number.isFinite(sizing?.minWidth) && sizing.minWidth > 0 ? sizing.minWidth : Number.isFinite(column.minWidth) && column.minWidth > 0 ? column.minWidth : 48;
268
- const max = Number.isFinite(column.maxWidth) && column.maxWidth >= min ? column.maxWidth : 1600;
269
- return Math.round(Math.max(min, Math.min(max, width)));
270
- }
271
- /** Stable, locale-aware sort shared by the React adapter and custom element. */
272
- export function sortDataGridItems(items, columns, sort, locale) {
273
- const sorts = (Array.isArray(sort) ? sort : sort ? [sort] : []).filter((entry, index, all) => all.findIndex(candidate => candidate.columnId === entry.columnId) === index && columns.some(column => column.id === entry.columnId && column.sortable !== false));
274
- if (!sorts.length)
275
- return [...items];
276
- const sortColumns = sorts.flatMap(entry => {
277
- const column = columns.find(candidate => candidate.id === entry.columnId);
278
- return column ? [{ sort: entry, column }] : [];
279
- });
280
- const collator = new Intl.Collator(locale?.trim() || undefined, { numeric: true, sensitivity: "base" });
281
- return items.map((item, index) => ({ item, index, values: sortColumns.map(({ column }) => column.value ? column.value(item) : item?.[column.id]) })).sort((a, b) => {
282
- for (let index = 0; index < sortColumns.length; index++) {
283
- const { sort: direction } = sortColumns[index];
284
- const rawLeft = a.values[index], rawRight = b.values[index];
285
- const left = rawLeft instanceof Date ? rawLeft.valueOf() : rawLeft;
286
- const right = rawRight instanceof Date ? rawRight.valueOf() : rawRight;
287
- const result = left == null ? right == null ? 0 : -1 : right == null ? 1
288
- : typeof left === "number" && typeof right === "number" ? left - right : collator.compare(String(left), String(right));
289
- if (result)
290
- return direction.direction === "ascending" ? result : -result;
291
- }
292
- return a.index - b.index;
293
- }).map(entry => entry.item);
294
- }
@@ -1,29 +0,0 @@
1
- import { type DataGridCellEdit, type DataGridColumn, type DataGridDataSource, type DataGridColumnSizingOptions, type DataGridFocusMode, type DataGridSelectionAppearance, type DataGridSelectionModel } from "./data-grid-model.js";
2
- export type DataGridCellRenderer<T = unknown> = (item: T, column: DataGridColumn<T>, rowIndex: number) => Node | string | number | null;
3
- export type DataGridRowHeightGetter<T = unknown> = (item: T, rowIndex: number) => number;
4
- export type DataGridCellsEditHandler = (edits: readonly DataGridCellEdit[]) => void | Promise<void>;
5
- export type DataGridSourceSelectionHandler = (selection: DataGridSelectionModel, selectedItems: readonly unknown[]) => void;
6
- export interface SharePointDataGridElement extends HTMLElement {
7
- items: unknown[];
8
- dataSource?: DataGridDataSource;
9
- columns: DataGridColumn[];
10
- focusMode: DataGridFocusMode;
11
- selectionAppearance: DataGridSelectionAppearance;
12
- subtleSelection: boolean;
13
- columnSizingOptions: DataGridColumnSizingOptions;
14
- autoFitColumns: boolean;
15
- containerWidthOffset: number;
16
- refreshDataSource(): void;
17
- onDataSourceGroupToggle?: (groupKey: string, expanded: boolean) => void;
18
- selectionModel: DataGridSelectionModel;
19
- onDataSourceSelectionChange?: DataGridSourceSelectionHandler;
20
- getRowHeight?: DataGridRowHeightGetter;
21
- onCellsEdit?: DataGridCellsEditHandler;
22
- }
23
- declare global {
24
- interface HTMLElementTagNameMap {
25
- "spui-data-grid": SharePointDataGridElement;
26
- }
27
- }
28
- /** Accessible, virtualized grid engine for non-React and React consumers. */
29
- export declare function defineDataGrid(): void;