@spfx-fast/sharepoint-ui 0.4.3 → 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.
- package/QUICKSTART.md +13 -128
- package/README.md +19 -26
- package/components.json +240 -5834
- package/dist/accordion.d.ts +11 -0
- package/dist/accordion.js +4 -0
- package/dist/alert.d.ts +3 -0
- package/dist/alert.js +4 -0
- package/dist/attachment-list.d.ts +15 -0
- package/dist/attachment-list.js +14 -0
- package/dist/avatar-group.d.ts +12 -0
- package/dist/avatar-group.js +7 -0
- package/dist/avatar.d.ts +6 -0
- package/dist/avatar.js +5 -0
- package/dist/badge.d.ts +3 -0
- package/dist/badge.js +4 -0
- package/dist/breadcrumb.d.ts +10 -0
- package/dist/breadcrumb.js +9 -0
- package/dist/button-group.d.ts +6 -0
- package/dist/button-group.js +4 -0
- package/dist/button.d.ts +3 -0
- package/dist/button.js +4 -0
- package/dist/card.d.ts +3 -0
- package/dist/card.js +4 -0
- package/dist/carousel.d.ts +11 -0
- package/dist/carousel.js +6 -0
- package/dist/checkbox.d.ts +3 -0
- package/dist/checkbox.js +4 -0
- package/dist/combobox.d.ts +9 -0
- package/dist/combobox.js +6 -0
- package/dist/command-bar.d.ts +6 -0
- package/dist/command-bar.js +4 -0
- package/dist/copy-button.d.ts +7 -0
- package/dist/copy-button.js +19 -0
- package/dist/data-grid.d.ts +25 -0
- package/dist/data-grid.js +39 -0
- package/dist/date-range-picker.d.ts +12 -0
- package/dist/date-range-picker.js +4 -0
- package/dist/dialog.d.ts +9 -0
- package/dist/dialog.js +21 -0
- package/dist/divider.d.ts +3 -0
- package/dist/divider.js +4 -0
- package/dist/drawer.d.ts +6 -0
- package/dist/drawer.js +5 -0
- package/dist/empty-state.d.ts +7 -0
- package/dist/empty-state.js +5 -0
- package/dist/field.d.ts +15 -0
- package/dist/field.js +11 -0
- package/dist/file-dropzone.d.ts +15 -0
- package/dist/file-dropzone.js +21 -0
- package/dist/filter-bar.d.ts +9 -0
- package/dist/filter-bar.js +9 -0
- package/dist/image.d.ts +5 -0
- package/dist/image.js +4 -0
- package/dist/index.d.ts +68 -78
- package/dist/index.js +60 -68
- package/dist/input.d.ts +3 -0
- package/dist/input.js +4 -0
- package/dist/label.d.ts +3 -0
- package/dist/label.js +4 -0
- package/dist/link.d.ts +3 -0
- package/dist/link.js +9 -0
- package/dist/list-view.d.ts +29 -0
- package/dist/list-view.js +14 -0
- package/dist/list.d.ts +6 -0
- package/dist/list.js +5 -0
- package/dist/lookup-picker.d.ts +12 -0
- package/dist/lookup-picker.js +4 -0
- package/dist/menu.d.ts +6 -0
- package/dist/menu.js +4 -0
- package/dist/nav.d.ts +12 -0
- package/dist/nav.js +4 -0
- package/dist/pagination.d.ts +11 -0
- package/dist/pagination.js +5 -0
- package/dist/person-picker.d.ts +13 -0
- package/dist/person-picker.js +4 -0
- package/dist/persona.d.ts +7 -0
- package/dist/persona.js +5 -0
- package/dist/popover.d.ts +6 -0
- package/dist/popover.js +4 -0
- package/dist/progress-bar.d.ts +5 -0
- package/dist/progress-bar.js +5 -0
- package/dist/radio-group.d.ts +6 -0
- package/dist/radio-group.js +4 -0
- package/dist/radio.d.ts +3 -0
- package/dist/radio.js +4 -0
- package/dist/rating.d.ts +8 -0
- package/dist/rating.js +5 -0
- package/dist/react.d.ts +1 -4715
- package/dist/react.js +1 -7097
- package/dist/select.d.ts +3 -0
- package/dist/select.js +4 -0
- package/dist/sharepoint-field.d.ts +18 -0
- package/dist/sharepoint-field.js +54 -0
- package/dist/skeleton.d.ts +6 -0
- package/dist/skeleton.js +9 -0
- package/dist/spinner.d.ts +5 -0
- package/dist/spinner.js +4 -0
- package/dist/swatch-picker.d.ts +17 -0
- package/dist/swatch-picker.js +11 -0
- package/dist/switch.d.ts +3 -0
- package/dist/switch.js +4 -0
- package/dist/table.d.ts +6 -0
- package/dist/table.js +4 -0
- package/dist/tabs.d.ts +14 -0
- package/dist/tabs.js +30 -0
- package/dist/tag-group.d.ts +6 -0
- package/dist/tag-group.js +4 -0
- package/dist/tag-picker.d.ts +12 -0
- package/dist/tag-picker.js +4 -0
- package/dist/tag.d.ts +7 -0
- package/dist/tag.js +5 -0
- package/dist/text.d.ts +5 -0
- package/dist/text.js +4 -0
- package/dist/textarea.d.ts +3 -0
- package/dist/textarea.js +4 -0
- package/dist/theme.d.ts +15 -175
- package/dist/theme.js +36 -239
- package/dist/toast.d.ts +9 -0
- package/dist/toast.js +12 -0
- package/dist/tree.d.ts +13 -0
- package/dist/tree.js +9 -0
- package/dist/view-card.d.ts +8 -0
- package/dist/view-card.js +4 -0
- package/dist/view-switcher.d.ts +13 -0
- package/dist/view-switcher.js +7 -0
- package/dist/virtual-list.d.ts +11 -0
- package/dist/virtual-list.js +25 -0
- package/measurements.json +365 -0
- package/package.json +14 -46
- package/src/theme.css +125 -0
- package/AGENTS.md +0 -231
- package/dist/appearance.d.ts +0 -6
- package/dist/appearance.js +0 -217
- package/dist/elements/accordion.d.ts +0 -9
- package/dist/elements/accordion.js +0 -338
- package/dist/elements/alert.d.ts +0 -2
- package/dist/elements/alert.js +0 -86
- package/dist/elements/avatar-group-primitives.d.ts +0 -3
- package/dist/elements/avatar-group-primitives.js +0 -189
- package/dist/elements/avatar-group.d.ts +0 -2
- package/dist/elements/avatar-group.js +0 -110
- package/dist/elements/avatar.d.ts +0 -4
- package/dist/elements/avatar.js +0 -251
- package/dist/elements/badge.d.ts +0 -8
- package/dist/elements/badge.js +0 -182
- package/dist/elements/breadcrumb.d.ts +0 -4
- package/dist/elements/breadcrumb.js +0 -233
- package/dist/elements/button-group.d.ts +0 -1
- package/dist/elements/button-group.js +0 -20
- package/dist/elements/button-variants.d.ts +0 -6
- package/dist/elements/button-variants.js +0 -339
- package/dist/elements/button.d.ts +0 -5
- package/dist/elements/button.js +0 -233
- package/dist/elements/card-primitives.d.ts +0 -3
- package/dist/elements/card-primitives.js +0 -83
- package/dist/elements/card.d.ts +0 -5
- package/dist/elements/card.js +0 -213
- package/dist/elements/carousel.d.ts +0 -92
- package/dist/elements/carousel.js +0 -1115
- package/dist/elements/color-picker.d.ts +0 -24
- package/dist/elements/color-picker.js +0 -1004
- package/dist/elements/combobox.d.ts +0 -1
- package/dist/elements/combobox.js +0 -1012
- package/dist/elements/data-grid-model.d.ts +0 -120
- package/dist/elements/data-grid-model.js +0 -294
- package/dist/elements/data-grid.d.ts +0 -30
- package/dist/elements/data-grid.js +0 -1576
- package/dist/elements/date-picker.d.ts +0 -1
- package/dist/elements/date-picker.js +0 -486
- package/dist/elements/dialog.d.ts +0 -23
- package/dist/elements/dialog.js +0 -409
- package/dist/elements/divider.d.ts +0 -2
- package/dist/elements/divider.js +0 -66
- package/dist/elements/drawer.d.ts +0 -3
- package/dist/elements/drawer.js +0 -308
- package/dist/elements/field-composition.d.ts +0 -26
- package/dist/elements/field-composition.js +0 -133
- package/dist/elements/field.d.ts +0 -1
- package/dist/elements/field.js +0 -67
- package/dist/elements/file-upload.d.ts +0 -6
- package/dist/elements/file-upload.js +0 -211
- package/dist/elements/floating-position.d.ts +0 -36
- package/dist/elements/floating-position.js +0 -92
- package/dist/elements/image.d.ts +0 -28
- package/dist/elements/image.js +0 -38
- package/dist/elements/info.d.ts +0 -9
- package/dist/elements/info.js +0 -102
- package/dist/elements/input.d.ts +0 -5
- package/dist/elements/input.js +0 -255
- package/dist/elements/label.d.ts +0 -15
- package/dist/elements/label.js +0 -56
- package/dist/elements/link.d.ts +0 -1
- package/dist/elements/link.js +0 -92
- package/dist/elements/list.d.ts +0 -19
- package/dist/elements/list.js +0 -297
- package/dist/elements/menu.d.ts +0 -33
- package/dist/elements/menu.js +0 -1103
- package/dist/elements/message-bar.d.ts +0 -10
- package/dist/elements/message-bar.js +0 -327
- package/dist/elements/nav.d.ts +0 -32
- package/dist/elements/nav.js +0 -794
- package/dist/elements/overflow.d.ts +0 -10
- package/dist/elements/overflow.js +0 -218
- package/dist/elements/persona.d.ts +0 -3
- package/dist/elements/persona.js +0 -125
- package/dist/elements/popover.d.ts +0 -77
- package/dist/elements/popover.js +0 -840
- package/dist/elements/progress-bar.d.ts +0 -4
- package/dist/elements/progress-bar.js +0 -82
- package/dist/elements/radio-group.d.ts +0 -1
- package/dist/elements/radio-group.js +0 -303
- package/dist/elements/rating-display.d.ts +0 -2
- package/dist/elements/rating-display.js +0 -125
- package/dist/elements/rating.d.ts +0 -2
- package/dist/elements/rating.js +0 -206
- package/dist/elements/rich-text-editor.d.ts +0 -32
- package/dist/elements/rich-text-editor.js +0 -1367
- package/dist/elements/search.d.ts +0 -3
- package/dist/elements/search.js +0 -200
- package/dist/elements/select.d.ts +0 -6
- package/dist/elements/select.js +0 -291
- package/dist/elements/shared.d.ts +0 -22
- package/dist/elements/shared.js +0 -409
- package/dist/elements/sharepoint-field-basic-controls.d.ts +0 -1
- package/dist/elements/sharepoint-field-basic-controls.js +0 -14
- package/dist/elements/sharepoint-fields.d.ts +0 -29
- package/dist/elements/sharepoint-fields.js +0 -460
- package/dist/elements/skeleton.d.ts +0 -6
- package/dist/elements/skeleton.js +0 -91
- package/dist/elements/slider.d.ts +0 -1
- package/dist/elements/slider.js +0 -248
- package/dist/elements/spin-button.d.ts +0 -7
- package/dist/elements/spin-button.js +0 -499
- package/dist/elements/spinner.d.ts +0 -4
- package/dist/elements/spinner.js +0 -124
- package/dist/elements/swatch-picker.d.ts +0 -5
- package/dist/elements/swatch-picker.js +0 -363
- package/dist/elements/table.d.ts +0 -21
- package/dist/elements/table.js +0 -261
- package/dist/elements/tabs.d.ts +0 -1
- package/dist/elements/tabs.js +0 -276
- package/dist/elements/tag-picker.d.ts +0 -29
- package/dist/elements/tag-picker.js +0 -715
- package/dist/elements/tags.d.ts +0 -21
- package/dist/elements/tags.js +0 -421
- package/dist/elements/teaching-popover.d.ts +0 -32
- package/dist/elements/teaching-popover.js +0 -412
- package/dist/elements/text.d.ts +0 -9
- package/dist/elements/text.js +0 -75
- package/dist/elements/textarea.d.ts +0 -1
- package/dist/elements/textarea.js +0 -182
- package/dist/elements/toast.d.ts +0 -25
- package/dist/elements/toast.js +0 -337
- package/dist/elements/toaster.d.ts +0 -6
- package/dist/elements/toaster.js +0 -357
- package/dist/elements/toggle.d.ts +0 -2
- package/dist/elements/toggle.js +0 -246
- package/dist/elements/toolbar.d.ts +0 -12
- package/dist/elements/toolbar.js +0 -381
- package/dist/elements/tooltip.d.ts +0 -76
- package/dist/elements/tooltip.js +0 -527
- package/dist/elements/tree-model.d.ts +0 -19
- package/dist/elements/tree-model.js +0 -34
- package/dist/elements/tree.d.ts +0 -5
- package/dist/elements/tree.js +0 -273
- package/dist/elements/view-card.d.ts +0 -2
- package/dist/elements/view-card.js +0 -78
- package/dist/elements/virtual-list.d.ts +0 -41
- package/dist/elements/virtual-list.js +0 -369
- package/dist/elements.d.ts +0 -73
- package/dist/elements.js +0 -210
- package/dist/sharepoint-fields.d.ts +0 -135
- package/dist/sharepoint-fields.js +0 -402
- package/dist/virtualizer-hooks.d.ts +0 -80
- package/dist/virtualizer-hooks.js +0 -253
- package/scripts/generate-token-index.mjs +0 -43
- package/scripts/sync-component-catalog-signatures.mjs +0 -55
- package/scripts/validate-component-catalog.mjs +0 -44
- package/skills/sharepoint-ui/SKILL.md +0 -12
- package/skills/sharepoint-ui/references/choosing-components.md +0 -20
- package/skills/sharepoint-ui/references/sharepoint-patterns.md +0 -17
- package/tokens.json +0 -3777
|
@@ -1,402 +0,0 @@
|
|
|
1
|
-
export function getRichTextEditorFieldOptions(field) {
|
|
2
|
-
const asBoolean = (value) => value === undefined ? undefined : value === true || (typeof value === "string" && value.trim().toLowerCase() === "true");
|
|
3
|
-
const richText = asBoolean(field.RichText ?? field.richText);
|
|
4
|
-
const restricted = asBoolean(field.RestrictedMode ?? field.restrictedMode) ?? false;
|
|
5
|
-
const mode = (field.RichTextMode ?? field.richTextMode)?.trim().toLowerCase();
|
|
6
|
-
const contentMode = richText === false ? "plain" : restricted ? "restricted" : mode === "fullhtml" ? "html" : mode === "compatible" || richText === true ? "rich" : "html";
|
|
7
|
-
const fieldAllowsHyperlinks = asBoolean(field.AllowHyperlink ?? field.allowHyperlink);
|
|
8
|
-
// Missing field metadata leaves safe, sanitized links enabled; an explicit SharePoint prohibition always wins.
|
|
9
|
-
return {
|
|
10
|
-
contentMode,
|
|
11
|
-
allowHyperlink: contentMode !== "plain" && contentMode !== "restricted" && fieldAllowsHyperlinks !== false
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
const booleanValue = (value) => value === true || (typeof value === "string" && value.trim().toLowerCase() === "true");
|
|
15
|
-
const fieldTypeNames = {
|
|
16
|
-
1: "Integer", 2: "Text", 3: "Note", 4: "DateTime", 5: "Counter", 6: "Choice", 7: "Lookup", 8: "Boolean",
|
|
17
|
-
9: "Number", 10: "Currency", 11: "URL", 12: "Computed", 15: "MultiChoice", 17: "Calculated", 20: "User", 32: "OutcomeChoice"
|
|
18
|
-
};
|
|
19
|
-
/** Map SharePoint REST/CSOM field metadata to a control recipe without importing any UI component code. */
|
|
20
|
-
export function getSharePointFieldAdapter(field) {
|
|
21
|
-
const fieldTypeKind = field.FieldTypeKind ?? field.fieldTypeKind;
|
|
22
|
-
const kind = field.TypeAsString ?? field.typeAsString ?? (fieldTypeKind == null ? "Unknown" : fieldTypeNames[fieldTypeKind] ?? `FieldTypeKind:${fieldTypeKind}`);
|
|
23
|
-
const normalized = kind.replace(/^SP\.Field/, "").toLowerCase();
|
|
24
|
-
const name = field.InternalName ?? field.internalName ?? "";
|
|
25
|
-
const adapter = {
|
|
26
|
-
control: "unsupported",
|
|
27
|
-
fieldType: kind,
|
|
28
|
-
name,
|
|
29
|
-
label: field.DisplayName ?? field.displayName ?? field.Title ?? field.title ?? name,
|
|
30
|
-
description: field.Description ?? field.description,
|
|
31
|
-
required: booleanValue(field.Required ?? field.required),
|
|
32
|
-
readOnly: booleanValue(field.ReadOnlyField ?? field.readOnlyField),
|
|
33
|
-
hidden: booleanValue(field.Hidden ?? field.hidden)
|
|
34
|
-
};
|
|
35
|
-
const finish = (control) => ({ ...adapter, control });
|
|
36
|
-
if (["text", "integer", "number", "currency", "url"].includes(normalized)) {
|
|
37
|
-
const control = finish("input");
|
|
38
|
-
control.inputType = normalized === "url" ? "url" : ["integer", "number", "currency"].includes(normalized) ? "number" : "text";
|
|
39
|
-
if (normalized === "url") {
|
|
40
|
-
const displayFormat = String(field.DisplayFormat ?? field.displayFormat ?? "0").trim().toLowerCase();
|
|
41
|
-
control.urlFormat = displayFormat === "1" || displayFormat === "image" || displayFormat === "picture" ? "picture" : "hyperlink";
|
|
42
|
-
}
|
|
43
|
-
control.maxLength = getConfiguredMaxLength(field);
|
|
44
|
-
if (control.inputType === "number") {
|
|
45
|
-
const decimalPlaces = getConfiguredDecimalPlaces(field);
|
|
46
|
-
control.step = normalized === "integer" || decimalPlaces === 0 ? 1 : decimalPlaces == null ? "any" : 10 ** -decimalPlaces;
|
|
47
|
-
control.min = getConfiguredNumber(field.MinimumValue ?? field.minimumValue ?? field.Min ?? field.min);
|
|
48
|
-
control.max = getConfiguredNumber(field.MaximumValue ?? field.maximumValue ?? field.Max ?? field.max);
|
|
49
|
-
}
|
|
50
|
-
return control;
|
|
51
|
-
}
|
|
52
|
-
if (normalized === "note") {
|
|
53
|
-
const richText = getRichTextEditorFieldOptions(field);
|
|
54
|
-
return richText.contentMode === "plain" ? finish("textarea") : { ...finish("rich-text-editor"), richText };
|
|
55
|
-
}
|
|
56
|
-
if (normalized === "choice" || normalized === "outcomechoice") {
|
|
57
|
-
const format = field.EditFormat ?? field.editFormat;
|
|
58
|
-
return {
|
|
59
|
-
...finish(format === 1 || String(format).toLowerCase() === "radiobuttons" ? "radio-group" : "select"),
|
|
60
|
-
choices: field.Choices ?? field.choices ?? [],
|
|
61
|
-
allowFillIn: booleanValue(field.FillInChoice ?? field.fillInChoice)
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
if (normalized === "multichoice") {
|
|
65
|
-
return { ...finish("multi-choice"), choices: field.Choices ?? field.choices ?? [], allowFillIn: booleanValue(field.FillInChoice ?? field.fillInChoice), multiple: true };
|
|
66
|
-
}
|
|
67
|
-
if (normalized === "boolean")
|
|
68
|
-
return finish("checkbox");
|
|
69
|
-
if (normalized === "datetime") {
|
|
70
|
-
const displayFormat = field.DisplayFormat ?? field.displayFormat;
|
|
71
|
-
const dateMode = displayFormat === 1 || String(displayFormat).toLowerCase() === "1" || String(displayFormat).toLowerCase() === "datetime" ? "date-time" : "date";
|
|
72
|
-
return dateMode === "date-time"
|
|
73
|
-
? { ...finish("input"), inputType: "datetime-local", dateMode }
|
|
74
|
-
: { ...finish("date-picker"), dateMode };
|
|
75
|
-
}
|
|
76
|
-
if (["lookup", "lookupmulti", "user", "usermulti"].includes(normalized)) {
|
|
77
|
-
const lookupList = field.LookupList ?? field.lookupList;
|
|
78
|
-
const lookupField = field.LookupField ?? field.lookupField;
|
|
79
|
-
const lookupSource = normalized.startsWith("lookup") && lookupList && lookupField
|
|
80
|
-
? { listId: lookupList, displayField: lookupField, webId: field.LookupWebId ?? field.lookupWebId }
|
|
81
|
-
: undefined;
|
|
82
|
-
return { ...finish("combobox"), multiple: normalized.endsWith("multi") || booleanValue(field.AllowMultipleValues ?? field.allowMultipleValues), lookupSource };
|
|
83
|
-
}
|
|
84
|
-
if (["counter", "computed", "calculated"].includes(normalized))
|
|
85
|
-
return { ...finish("read-only"), readOnly: true };
|
|
86
|
-
return { ...adapter, unsupportedReason: "This SharePoint field type needs a specialized data source or renderer." };
|
|
87
|
-
}
|
|
88
|
-
/** Build a bounded REST request for a list's field definitions and their type-specific metadata. */
|
|
89
|
-
export function getSharePointFieldMetadataUrl(listWebUrl, listId, pageSize = 100) {
|
|
90
|
-
if (!Number.isSafeInteger(pageSize) || pageSize < 1 || pageSize > 500)
|
|
91
|
-
throw new RangeError("pageSize must be an integer from 1 to 500.");
|
|
92
|
-
const normalizedListId = normalizeSharePointListId(listId, "listId must be a SharePoint list GUID.");
|
|
93
|
-
const url = parseSharePointWebUrl(listWebUrl, "listWebUrl");
|
|
94
|
-
url.pathname = `${url.pathname.replace(/\/+$/, "")}/_api/web/lists(guid'${normalizedListId}')/fields`;
|
|
95
|
-
url.search = new URLSearchParams({ "$select": "*", "$top": String(pageSize) }).toString();
|
|
96
|
-
url.hash = "";
|
|
97
|
-
return url.toString();
|
|
98
|
-
}
|
|
99
|
-
/** Build the REST endpoint for a single item in a SharePoint list. */
|
|
100
|
-
export function getSharePointListItemUrl(webUrl, listId, itemId) {
|
|
101
|
-
if (!Number.isSafeInteger(itemId) || itemId < 1)
|
|
102
|
-
throw new RangeError("itemId must be a positive safe integer.");
|
|
103
|
-
const normalizedListId = normalizeSharePointListId(listId, "listId must be a SharePoint list GUID.");
|
|
104
|
-
const url = parseSharePointWebUrl(webUrl, "webUrl");
|
|
105
|
-
url.pathname = `${url.pathname.replace(/\/+$/, "")}/_api/web/lists(guid'${normalizedListId}')/items(${itemId})`;
|
|
106
|
-
url.search = "";
|
|
107
|
-
url.hash = "";
|
|
108
|
-
return url.toString();
|
|
109
|
-
}
|
|
110
|
-
/** Build a paged REST URL for options in a lookup field's source list. Pass that list's web URL. */
|
|
111
|
-
export function getSharePointLookupOptionsUrl(field, lookupWebUrl, pageSize = 100) {
|
|
112
|
-
const adapter = getSharePointFieldAdapter(field);
|
|
113
|
-
const source = adapter.lookupSource;
|
|
114
|
-
if (adapter.control !== "combobox" || !source)
|
|
115
|
-
throw new TypeError("This field does not include SharePoint lookup-list metadata.");
|
|
116
|
-
if (!Number.isSafeInteger(pageSize) || pageSize < 1 || pageSize > 500)
|
|
117
|
-
throw new RangeError("pageSize must be an integer from 1 to 500.");
|
|
118
|
-
const listId = normalizeSharePointListId(source.listId, "LookupList must contain a SharePoint list GUID.");
|
|
119
|
-
if (!/^[A-Za-z_][A-Za-z\d_]*$/.test(source.displayField))
|
|
120
|
-
throw new TypeError("LookupField must be a SharePoint internal field name.");
|
|
121
|
-
const url = parseSharePointWebUrl(lookupWebUrl, "lookupWebUrl");
|
|
122
|
-
url.pathname = `${url.pathname.replace(/\/+$/, "")}/_api/web/lists(guid'${listId}')/items`;
|
|
123
|
-
url.search = new URLSearchParams({
|
|
124
|
-
"$select": `Id,${source.displayField}`,
|
|
125
|
-
"$orderby": `${source.displayField} asc`,
|
|
126
|
-
"$top": String(pageSize)
|
|
127
|
-
}).toString();
|
|
128
|
-
url.hash = "";
|
|
129
|
-
return url.toString();
|
|
130
|
-
}
|
|
131
|
-
/** Resolve a SharePoint OData next link and reject links that would send host credentials to another origin. */
|
|
132
|
-
export function getSharePointNextPageUrl(webUrl, nextLink) {
|
|
133
|
-
if (nextLink == null)
|
|
134
|
-
return null;
|
|
135
|
-
if (typeof nextLink !== "string")
|
|
136
|
-
throw new TypeError("nextLink must be a URL string or null.");
|
|
137
|
-
if (nextLink.trim() === "")
|
|
138
|
-
return null;
|
|
139
|
-
const base = new URL(webUrl);
|
|
140
|
-
if (!/^https?:$/.test(base.protocol) || base.username || base.password)
|
|
141
|
-
throw new TypeError("webUrl must be an HTTP(S) SharePoint web URL.");
|
|
142
|
-
const next = new URL(nextLink, base);
|
|
143
|
-
if (!/^https?:$/.test(next.protocol) || next.origin !== base.origin || next.username || next.password) {
|
|
144
|
-
throw new TypeError("SharePoint next links must resolve to the same HTTP(S) origin as webUrl.");
|
|
145
|
-
}
|
|
146
|
-
next.hash = "";
|
|
147
|
-
return next.toString();
|
|
148
|
-
}
|
|
149
|
-
/** Serialize selected SharePoint lookup/person IDs for an item create or update body. */
|
|
150
|
-
export function serializeSharePointLookupValue(field, value) {
|
|
151
|
-
const adapter = getSharePointFieldAdapter(field);
|
|
152
|
-
const type = adapter.fieldType.replace(/^SP\.Field/, "").toLowerCase();
|
|
153
|
-
if (adapter.control !== "combobox" || !["lookup", "lookupmulti", "user", "usermulti"].includes(type)) {
|
|
154
|
-
throw new TypeError("Only SharePoint Lookup and User fields can be serialized as ID selections.");
|
|
155
|
-
}
|
|
156
|
-
if (!adapter.name)
|
|
157
|
-
throw new TypeError("The SharePoint field must include InternalName.");
|
|
158
|
-
assertSharePointFieldValueWritable(adapter, value);
|
|
159
|
-
const key = `${adapter.name}Id`;
|
|
160
|
-
if (adapter.multiple) {
|
|
161
|
-
if (value == null)
|
|
162
|
-
return { [key]: { results: [] } };
|
|
163
|
-
if (!isLookupIdArray(value))
|
|
164
|
-
throw new TypeError("A multi-value field requires an array of selected IDs.");
|
|
165
|
-
return { [key]: { results: [...new Set(value.map(parseLookupId))] } };
|
|
166
|
-
}
|
|
167
|
-
if (isLookupIdArray(value))
|
|
168
|
-
throw new TypeError("A single-value field accepts one selected ID or null.");
|
|
169
|
-
return { [key]: value == null || value === "" ? null : parseLookupId(value) };
|
|
170
|
-
}
|
|
171
|
-
/** Serialize SharePoint Choice and MultiChoice values for an item create or update body. */
|
|
172
|
-
export function serializeSharePointChoiceValue(field, value) {
|
|
173
|
-
const adapter = getSharePointFieldAdapter(field);
|
|
174
|
-
const type = adapter.fieldType.replace(/^SP\.Field/, "").toLowerCase();
|
|
175
|
-
const multiple = type === "multichoice";
|
|
176
|
-
if (!["choice", "outcomechoice", "multichoice"].includes(type)) {
|
|
177
|
-
throw new TypeError("Only SharePoint Choice and MultiChoice fields can be serialized as choice values.");
|
|
178
|
-
}
|
|
179
|
-
if (!adapter.name)
|
|
180
|
-
throw new TypeError("The SharePoint field must include InternalName.");
|
|
181
|
-
assertSharePointFieldValueWritable(adapter, value);
|
|
182
|
-
const choices = field.Choices ?? field.choices ?? [];
|
|
183
|
-
const allowFillIn = booleanValue(field.FillInChoice ?? field.fillInChoice);
|
|
184
|
-
const validateChoice = (choice) => {
|
|
185
|
-
if (choices.length && !choices.includes(choice) && !allowFillIn)
|
|
186
|
-
throw new RangeError(`“${choice}” is not an allowed value for ${adapter.label}.`);
|
|
187
|
-
return choice;
|
|
188
|
-
};
|
|
189
|
-
if (multiple) {
|
|
190
|
-
if (value == null)
|
|
191
|
-
return { [adapter.name]: { results: [] } };
|
|
192
|
-
if (!isChoiceValueArray(value))
|
|
193
|
-
throw new TypeError("A MultiChoice field requires an array of selected values.");
|
|
194
|
-
return { [adapter.name]: { results: [...new Set(value.map(validateChoice))] } };
|
|
195
|
-
}
|
|
196
|
-
if (isChoiceValueArray(value))
|
|
197
|
-
throw new TypeError("A Choice field accepts one value or null.");
|
|
198
|
-
return { [adapter.name]: value == null || value === "" ? null : validateChoice(value) };
|
|
199
|
-
}
|
|
200
|
-
/** Serialize a common SharePoint list-field value into a REST item create/update body. */
|
|
201
|
-
export function serializeSharePointFieldValue(field, value) {
|
|
202
|
-
const adapter = getSharePointFieldAdapter(field);
|
|
203
|
-
const type = adapter.fieldType.replace(/^SP\.Field/, "").toLowerCase();
|
|
204
|
-
if (!adapter.name)
|
|
205
|
-
throw new TypeError("The SharePoint field must include InternalName.");
|
|
206
|
-
if (["lookup", "lookupmulti", "user", "usermulti"].includes(type)) {
|
|
207
|
-
return serializeSharePointLookupValue(field, value);
|
|
208
|
-
}
|
|
209
|
-
if (["choice", "outcomechoice", "multichoice"].includes(type)) {
|
|
210
|
-
return serializeSharePointChoiceValue(field, value);
|
|
211
|
-
}
|
|
212
|
-
assertSharePointFieldValueWritable(adapter, value);
|
|
213
|
-
if (["text", "note"].includes(type)) {
|
|
214
|
-
if (value != null && typeof value !== "string")
|
|
215
|
-
throw new TypeError(`${adapter.label} requires a string value or null.`);
|
|
216
|
-
const maxLength = getConfiguredMaxLength(field);
|
|
217
|
-
if (typeof value === "string" && maxLength != null && value.length > maxLength)
|
|
218
|
-
throw new RangeError(`${adapter.label} allows at most ${maxLength} characters.`);
|
|
219
|
-
return { [adapter.name]: value };
|
|
220
|
-
}
|
|
221
|
-
if (type === "boolean") {
|
|
222
|
-
if (value != null && typeof value !== "boolean")
|
|
223
|
-
throw new TypeError(`${adapter.label} requires a boolean value or null.`);
|
|
224
|
-
return { [adapter.name]: value };
|
|
225
|
-
}
|
|
226
|
-
if (["integer", "number", "currency"].includes(type)) {
|
|
227
|
-
if (value == null || value === "")
|
|
228
|
-
return { [adapter.name]: null };
|
|
229
|
-
const numeric = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" && /^[-+]?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?$/i.test(value.trim()) ? Number(value) : NaN;
|
|
230
|
-
if (!Number.isFinite(numeric) || (type === "integer" && !Number.isSafeInteger(numeric))) {
|
|
231
|
-
throw new TypeError(`${adapter.label} requires a ${type === "integer" ? "safe integer" : "finite number"}, numeric string, or null.`);
|
|
232
|
-
}
|
|
233
|
-
const allowedDecimals = type === "integer" ? 0 : getConfiguredDecimalPlaces(field);
|
|
234
|
-
const precisionSource = typeof value === "string" || typeof value === "number" ? value : numeric;
|
|
235
|
-
if (allowedDecimals != null && getNumericDecimalPlaces(precisionSource) > allowedDecimals) {
|
|
236
|
-
throw new RangeError(`${adapter.label} allows at most ${allowedDecimals} decimal places.`);
|
|
237
|
-
}
|
|
238
|
-
const minimum = getConfiguredNumber(field.MinimumValue ?? field.minimumValue ?? field.Min ?? field.min);
|
|
239
|
-
const maximum = getConfiguredNumber(field.MaximumValue ?? field.maximumValue ?? field.Max ?? field.max);
|
|
240
|
-
if (minimum != null && numeric < minimum)
|
|
241
|
-
throw new RangeError(`${adapter.label} must be at least ${minimum}.`);
|
|
242
|
-
if (maximum != null && numeric > maximum)
|
|
243
|
-
throw new RangeError(`${adapter.label} must be at most ${maximum}.`);
|
|
244
|
-
return { [adapter.name]: numeric };
|
|
245
|
-
}
|
|
246
|
-
if (type === "datetime") {
|
|
247
|
-
if (value == null || value === "")
|
|
248
|
-
return { [adapter.name]: null };
|
|
249
|
-
if (value instanceof Date) {
|
|
250
|
-
if (!Number.isFinite(value.getTime()))
|
|
251
|
-
throw new TypeError(`${adapter.label} requires a valid date, ISO date string, or null.`);
|
|
252
|
-
return { [adapter.name]: value.toISOString() };
|
|
253
|
-
}
|
|
254
|
-
if (typeof value !== "string")
|
|
255
|
-
throw new TypeError(`${adapter.label} requires a valid date, ISO date string, or null.`);
|
|
256
|
-
const iso = serializeSharePointDateValue(value);
|
|
257
|
-
if (!iso)
|
|
258
|
-
throw new TypeError(`${adapter.label} requires a valid ISO date or date-time string.`);
|
|
259
|
-
return { [adapter.name]: iso };
|
|
260
|
-
}
|
|
261
|
-
if (type === "url") {
|
|
262
|
-
if (value == null || value === "")
|
|
263
|
-
return { [adapter.name]: null };
|
|
264
|
-
const link = typeof value === "string" ? { url: value, description: value.trim() } : isSharePointUrlValue(value) ? value : undefined;
|
|
265
|
-
if (!link)
|
|
266
|
-
throw new TypeError(`${adapter.label} requires a URL string, URL value, or null.`);
|
|
267
|
-
const url = link.url.trim();
|
|
268
|
-
const maxLength = Math.min(255, getConfiguredMaxLength(field) ?? 255);
|
|
269
|
-
if (url.length > maxLength)
|
|
270
|
-
throw new RangeError(`${adapter.label} URL cannot exceed ${maxLength} characters.`);
|
|
271
|
-
if (url && !isSharePointFieldUrl(url))
|
|
272
|
-
throw new TypeError(`${adapter.label} must be an HTTP(S) or server-relative URL.`);
|
|
273
|
-
const description = link.description ?? url;
|
|
274
|
-
if (typeof description !== "string")
|
|
275
|
-
throw new TypeError(`${adapter.label} URL description must be a string.`);
|
|
276
|
-
if (description.length > 255)
|
|
277
|
-
throw new RangeError(`${adapter.label} URL description cannot exceed 255 characters.`);
|
|
278
|
-
return { [adapter.name]: { __metadata: { type: "SP.FieldUrlValue" }, Url: url, Description: description } };
|
|
279
|
-
}
|
|
280
|
-
throw new TypeError(adapter.unsupportedReason ?? `${adapter.fieldType} fields cannot be serialized by this helper.`);
|
|
281
|
-
}
|
|
282
|
-
/** Build one SharePoint item patch from values keyed by field InternalName; omitted values stay untouched. */
|
|
283
|
-
export function serializeSharePointFieldValues(fields, values) {
|
|
284
|
-
const update = {};
|
|
285
|
-
const fieldsByName = new Map();
|
|
286
|
-
for (const field of fields) {
|
|
287
|
-
const adapter = getSharePointFieldAdapter(field);
|
|
288
|
-
if (!adapter.name)
|
|
289
|
-
throw new TypeError("Every SharePoint field must include InternalName.");
|
|
290
|
-
if (fieldsByName.has(adapter.name))
|
|
291
|
-
throw new TypeError(`Duplicate SharePoint field InternalName: ${adapter.name}.`);
|
|
292
|
-
fieldsByName.set(adapter.name, { field, adapter });
|
|
293
|
-
}
|
|
294
|
-
for (const [name, value] of Object.entries(values)) {
|
|
295
|
-
const entry = fieldsByName.get(name);
|
|
296
|
-
if (!entry)
|
|
297
|
-
throw new TypeError(`No SharePoint field metadata was supplied for ${name}.`);
|
|
298
|
-
const { field, adapter } = entry;
|
|
299
|
-
if (value === undefined) {
|
|
300
|
-
if (adapter.required)
|
|
301
|
-
throw new TypeError(`${adapter.label} is required.`);
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
for (const [name, serializedValue] of Object.entries(serializeSharePointFieldValue(field, value))) {
|
|
305
|
-
if (Object.prototype.hasOwnProperty.call(update, name))
|
|
306
|
-
throw new TypeError(`Multiple SharePoint fields map to update property ${name}.`);
|
|
307
|
-
Object.defineProperty(update, name, { configurable: true, enumerable: true, value: serializedValue, writable: true });
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return update;
|
|
311
|
-
}
|
|
312
|
-
function isLookupIdArray(value) {
|
|
313
|
-
return Array.isArray(value);
|
|
314
|
-
}
|
|
315
|
-
function isChoiceValueArray(value) {
|
|
316
|
-
return Array.isArray(value);
|
|
317
|
-
}
|
|
318
|
-
function isSharePointFieldUrl(value) {
|
|
319
|
-
if (value.startsWith("/") && !value.startsWith("//"))
|
|
320
|
-
return true;
|
|
321
|
-
try {
|
|
322
|
-
const url = new URL(value);
|
|
323
|
-
return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password;
|
|
324
|
-
}
|
|
325
|
-
catch {
|
|
326
|
-
return false;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
function normalizeSharePointListId(value, errorMessage) {
|
|
330
|
-
const normalized = value.trim().replace(/[{}]/g, "");
|
|
331
|
-
if (!/^[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12}$/i.test(normalized))
|
|
332
|
-
throw new TypeError(errorMessage);
|
|
333
|
-
return normalized;
|
|
334
|
-
}
|
|
335
|
-
function parseSharePointWebUrl(value, label) {
|
|
336
|
-
const url = new URL(value);
|
|
337
|
-
if (!/^https?:$/.test(url.protocol) || url.username || url.password)
|
|
338
|
-
throw new TypeError(`${label} must be an HTTP(S) SharePoint web URL.`);
|
|
339
|
-
return url;
|
|
340
|
-
}
|
|
341
|
-
function isSharePointUrlValue(value) {
|
|
342
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && typeof value.url === "string";
|
|
343
|
-
}
|
|
344
|
-
function isEmptySharePointFieldValue(value) {
|
|
345
|
-
if (value == null)
|
|
346
|
-
return true;
|
|
347
|
-
if (typeof value === "string")
|
|
348
|
-
return value.trim() === "";
|
|
349
|
-
if (Array.isArray(value))
|
|
350
|
-
return value.length === 0;
|
|
351
|
-
return isSharePointUrlValue(value) && value.url.trim() === "";
|
|
352
|
-
}
|
|
353
|
-
function assertSharePointFieldValueWritable(adapter, value) {
|
|
354
|
-
if (adapter.readOnly)
|
|
355
|
-
throw new TypeError(`${adapter.label} is read-only and cannot be serialized for an item update.`);
|
|
356
|
-
if (adapter.required && isEmptySharePointFieldValue(value))
|
|
357
|
-
throw new TypeError(`${adapter.label} is required.`);
|
|
358
|
-
}
|
|
359
|
-
function serializeSharePointDateValue(value) {
|
|
360
|
-
const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
361
|
-
const dateTime = /^(\d{4})-(\d{2})-(\d{2})T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(Z|[+-]\d{2}:\d{2})?$/.exec(value);
|
|
362
|
-
const match = dateOnly ?? dateTime;
|
|
363
|
-
if (!match)
|
|
364
|
-
return undefined;
|
|
365
|
-
const day = new Date(`${match[1]}-${match[2]}-${match[3]}T00:00:00.000Z`);
|
|
366
|
-
if (!Number.isFinite(day.getTime()) || day.toISOString().slice(0, 10) !== `${match[1]}-${match[2]}-${match[3]}`)
|
|
367
|
-
return undefined;
|
|
368
|
-
const parsed = new Date(value);
|
|
369
|
-
if (!Number.isFinite(parsed.getTime()))
|
|
370
|
-
return undefined;
|
|
371
|
-
if (dateOnly || dateTime?.[4])
|
|
372
|
-
return value;
|
|
373
|
-
return parsed.toISOString();
|
|
374
|
-
}
|
|
375
|
-
function getConfiguredDecimalPlaces(field) {
|
|
376
|
-
const decimals = field.Decimals ?? field.decimals;
|
|
377
|
-
const value = typeof decimals === "number" ? decimals : typeof decimals === "string" && /^\d+$/.test(decimals.trim()) ? Number(decimals) : undefined;
|
|
378
|
-
return value != null && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
379
|
-
}
|
|
380
|
-
function getConfiguredMaxLength(field) {
|
|
381
|
-
const value = field.MaxLength ?? field.maxLength;
|
|
382
|
-
const parsed = typeof value === "number" ? value : typeof value === "string" && /^\d+$/.test(value.trim()) ? Number(value) : undefined;
|
|
383
|
-
return parsed != null && Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
|
|
384
|
-
}
|
|
385
|
-
function getConfiguredNumber(value) {
|
|
386
|
-
const parsed = typeof value === "number" ? value : typeof value === "string" && /^[-+]?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?$/i.test(value.trim()) ? Number(value.trim()) : undefined;
|
|
387
|
-
return parsed != null && Number.isFinite(parsed) ? parsed : undefined;
|
|
388
|
-
}
|
|
389
|
-
function getNumericDecimalPlaces(value) {
|
|
390
|
-
const [coefficient, exponentText] = String(value).trim().toLowerCase().split("e");
|
|
391
|
-
const [integer = "", fraction = ""] = coefficient.split(".");
|
|
392
|
-
const exponent = Number(exponentText ?? 0);
|
|
393
|
-
const significantFractionLength = fraction.replace(/0+$/, "").length;
|
|
394
|
-
const removableIntegerZeros = exponent < 0 ? integer.match(/0+$/)?.[0].length ?? 0 : 0;
|
|
395
|
-
return Math.max(0, significantFractionLength - exponent - removableIntegerZeros);
|
|
396
|
-
}
|
|
397
|
-
function parseLookupId(value) {
|
|
398
|
-
const id = typeof value === "string" && /^\d+$/.test(value.trim()) ? Number(value.trim()) : value;
|
|
399
|
-
if (typeof id !== "number" || !Number.isSafeInteger(id) || id < 1)
|
|
400
|
-
throw new RangeError("SharePoint lookup IDs must be positive safe integers.");
|
|
401
|
-
return id;
|
|
402
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
export type VirtualizerMeasureProps = {
|
|
3
|
-
defaultItemSize: number;
|
|
4
|
-
direction?: "vertical" | "horizontal";
|
|
5
|
-
bufferItems?: number;
|
|
6
|
-
bufferSize?: number;
|
|
7
|
-
};
|
|
8
|
-
export type VirtualizerContextMeasureProps = {
|
|
9
|
-
contextIndex: number;
|
|
10
|
-
setContextIndex: (index: number) => void;
|
|
11
|
-
childProgressiveSizes: React.MutableRefObject<number[]>;
|
|
12
|
-
};
|
|
13
|
-
export type VirtualizerMeasureDynamicProps = VirtualizerMeasureProps & {
|
|
14
|
-
virtualizerContext: VirtualizerContextMeasureProps;
|
|
15
|
-
numItems: number;
|
|
16
|
-
getItemSize: (index: number) => number;
|
|
17
|
-
};
|
|
18
|
-
export interface IndexedResizeCallbackElement {
|
|
19
|
-
handleResize: () => void;
|
|
20
|
-
}
|
|
21
|
-
/** Measure a fixed-size viewport and calculate a bounded item window. */
|
|
22
|
-
export declare function useStaticVirtualizerMeasure<TElement extends HTMLElement = HTMLElement>(props: VirtualizerMeasureProps): {
|
|
23
|
-
virtualizerLength: number;
|
|
24
|
-
bufferItems: number;
|
|
25
|
-
bufferSize: number;
|
|
26
|
-
scrollRef: (element: TElement | null) => void;
|
|
27
|
-
containerSizeRef: React.MutableRefObject<number>;
|
|
28
|
-
};
|
|
29
|
-
/** Measure only enough variable-size rows to cover the current scroll viewport. */
|
|
30
|
-
export declare function useDynamicVirtualizerMeasure<TElement extends HTMLElement = HTMLElement>(props: VirtualizerMeasureDynamicProps): {
|
|
31
|
-
virtualizerLength: number;
|
|
32
|
-
bufferItems: number;
|
|
33
|
-
bufferSize: number;
|
|
34
|
-
scrollRef: (element: TElement | null) => void;
|
|
35
|
-
containerSizeRef: React.RefObject<number>;
|
|
36
|
-
updateScrollPosition: (position: number) => void;
|
|
37
|
-
};
|
|
38
|
-
/** Track measured widths/heights by item index for legacy dynamic virtualizer composition. */
|
|
39
|
-
export declare function useMeasureList<TElement extends HTMLElement & IndexedResizeCallbackElement = HTMLElement & IndexedResizeCallbackElement>(currentIndex: number, _refLength: number, totalLength: number, defaultItemSize: number): {
|
|
40
|
-
widthArray: React.MutableRefObject<number[]>;
|
|
41
|
-
heightArray: React.MutableRefObject<number[]>;
|
|
42
|
-
createIndexedRef: (index: number) => (element: TElement | null) => void;
|
|
43
|
-
refArray: React.MutableRefObject<Array<TElement | undefined | null>>;
|
|
44
|
-
sizeUpdateCount: number;
|
|
45
|
-
};
|
|
46
|
-
export type ResizeCallbackWithRef = (entries: ResizeObserverEntry[], observer: ResizeObserver, scrollRef?: React.MutableRefObject<HTMLElement | null>) => void;
|
|
47
|
-
export type ScrollToItemStaticParams = {
|
|
48
|
-
index: number;
|
|
49
|
-
itemSize: number;
|
|
50
|
-
totalItems: number;
|
|
51
|
-
scrollViewRef: React.RefObject<HTMLElement | null>;
|
|
52
|
-
axis?: "horizontal" | "vertical";
|
|
53
|
-
reversed?: boolean;
|
|
54
|
-
behavior?: ScrollBehavior;
|
|
55
|
-
};
|
|
56
|
-
export type ScrollToItemDynamicParams = {
|
|
57
|
-
index: number;
|
|
58
|
-
itemSizes: React.RefObject<number[] | null>;
|
|
59
|
-
totalSize: number;
|
|
60
|
-
scrollViewRef: React.RefObject<HTMLElement | null>;
|
|
61
|
-
axis?: "horizontal" | "vertical";
|
|
62
|
-
reversed?: boolean;
|
|
63
|
-
behavior?: ScrollBehavior;
|
|
64
|
-
};
|
|
65
|
-
/** Create an observer from the document's own window, including when an SPFx part is rendered in an iframe. */
|
|
66
|
-
export declare function createResizeObserverFromDocument(targetDocument: Document | null | undefined, callback: ResizeObserverCallback): ResizeObserver | null;
|
|
67
|
-
/** Mirror a four-sided LTR observer margin for an RTL root. */
|
|
68
|
-
export declare function getRTLRootMargin(ltrRootMargin: string, target?: Element | Document | null, win?: Window | null): string;
|
|
69
|
-
/** Observe a changing element list with native IntersectionObserver and direction-aware margins. */
|
|
70
|
-
export declare function useIntersectionObserver(callback: IntersectionObserverCallback, options?: IntersectionObserverInit): {
|
|
71
|
-
setObserverList: React.Dispatch<React.SetStateAction<Element[] | undefined>>;
|
|
72
|
-
setObserverInit: (next: IntersectionObserverInit | undefined) => void;
|
|
73
|
-
observer: React.MutableRefObject<IntersectionObserver | undefined>;
|
|
74
|
-
};
|
|
75
|
-
/** Attach a resize observer callback ref; it is safe when ResizeObserver is unavailable. */
|
|
76
|
-
export declare function useResizeObserverRef_unstable(resizeCallback: ResizeCallbackWithRef): (instance: HTMLElement | null) => void;
|
|
77
|
-
/** Scroll an element to a fixed-size virtual item. */
|
|
78
|
-
export declare function scrollToItemStatic({ index, itemSize, totalItems, scrollViewRef, axis, reversed, behavior }: ScrollToItemStaticParams): void;
|
|
79
|
-
/** Scroll an element to a measured item; summing the prefix is O(index), so keep the measured list modest. */
|
|
80
|
-
export declare function scrollToItemDynamic({ index, itemSizes, totalSize, scrollViewRef, axis, reversed, behavior }: ScrollToItemDynamicParams): void;
|