@spfx-fast/sharepoint-ui 0.4.1 → 0.4.3
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/AGENTS.md +23 -3
- package/QUICKSTART.md +133 -0
- package/README.md +21 -878
- package/components.json +178 -33
- package/dist/appearance.js +4 -4
- package/dist/elements/alert.js +26 -2
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/carousel.js +5 -2
- package/dist/elements/color-picker.js +1 -1
- package/dist/elements/combobox.js +5 -5
- package/dist/elements/data-grid-model.d.ts +3 -0
- package/dist/elements/data-grid.d.ts +2 -1
- package/dist/elements/data-grid.js +19 -10
- package/dist/elements/date-picker.js +1 -1
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/floating-position.d.ts +10 -0
- package/dist/elements/floating-position.js +53 -0
- package/dist/elements/info.js +1 -1
- package/dist/elements/input.js +2 -2
- package/dist/elements/link.js +1 -1
- package/dist/elements/message-bar.js +33 -5
- package/dist/elements/nav.js +4 -1
- package/dist/elements/overflow.d.ts +1 -0
- package/dist/elements/overflow.js +2 -2
- package/dist/elements/popover.js +1 -1
- package/dist/elements/rating.js +3 -3
- package/dist/elements/rich-text-editor.d.ts +15 -1
- package/dist/elements/rich-text-editor.js +938 -79
- package/dist/elements/search.js +3 -10
- package/dist/elements/select.js +2 -2
- package/dist/elements/shared.d.ts +4 -1
- package/dist/elements/shared.js +14 -1
- package/dist/elements/sharepoint-field-basic-controls.d.ts +1 -0
- package/dist/elements/sharepoint-field-basic-controls.js +14 -0
- package/dist/elements/sharepoint-fields.d.ts +29 -0
- package/dist/elements/sharepoint-fields.js +460 -0
- package/dist/elements/spin-button.js +2 -2
- package/dist/elements/tag-picker.js +29 -11
- package/dist/elements/textarea.js +2 -2
- package/dist/elements/toaster.js +2 -1
- package/dist/elements/tooltip.js +18 -1
- package/dist/elements/tree.js +1 -1
- package/dist/elements.d.ts +3 -2
- package/dist/elements.js +4 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -2
- package/dist/react.d.ts +188 -19
- package/dist/react.js +321 -61
- package/dist/sharepoint-fields.d.ts +135 -0
- package/dist/sharepoint-fields.js +402 -0
- package/dist/theme.d.ts +9 -1
- package/dist/theme.js +78 -1
- package/package.json +11 -2
- package/skills/sharepoint-ui/SKILL.md +1 -1
- package/skills/sharepoint-ui/references/sharepoint-patterns.md +1 -1
package/dist/theme.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { getSharePointUIStyleTokens } from "./appearance.js";
|
|
2
|
+
/** Build named swatches from the current SharePoint palette; custom tenant keys are preserved. */
|
|
3
|
+
export function getSharePointThemeColorPresets(palette, labelForKey) {
|
|
4
|
+
return Object.entries(palette ?? {}).flatMap(([name, color]) => {
|
|
5
|
+
if (typeof color !== "string" || !color.trim())
|
|
6
|
+
return [];
|
|
7
|
+
const readableName = name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Za-z])(\d+)/g, "$1 $2").replace(/[_-]+/g, " ").replace(/^theme\s+/i, "").replace(/\s+/g, " ").trim();
|
|
8
|
+
const label = labelForKey?.(name) ?? readableName.replace(/\b[a-z]/g, character => character.toUpperCase());
|
|
9
|
+
return [{ name, value: name, color, label }];
|
|
10
|
+
});
|
|
11
|
+
}
|
|
2
12
|
/** Compose reusable theme packs left-to-right; later packs override earlier values within each group. */
|
|
3
13
|
export function composeSharePointUIDesignThemes(...themes) {
|
|
4
14
|
return themes.reduce((merged, theme) => ({
|
|
@@ -78,12 +88,53 @@ export function getSharePointUIDesignTokens(theme) {
|
|
|
78
88
|
"--spui-selection-background": `color-mix(in srgb, ${accent} 14%, var(--spui-ui-surface))`,
|
|
79
89
|
"--spui-selection-border": accent,
|
|
80
90
|
"--spui-link-color": `var(--spui-semantic-link, color-mix(in srgb, ${accent} 55%, var(--spui-ui-text) 45%))`,
|
|
81
|
-
"--spui-
|
|
91
|
+
"--spui-ui-border-focus": accent,
|
|
92
|
+
"--spui-focus-ring": accent,
|
|
82
93
|
"--spui-ui-info": accent,
|
|
83
94
|
"--spui-ui-info-surface": `color-mix(in srgb, ${accent} 12%, var(--spui-ui-surface))`,
|
|
84
95
|
"--spui-primary-background": accent,
|
|
85
96
|
"--spui-primary-hover": `color-mix(in srgb, ${accent} 84%, black)`
|
|
86
97
|
});
|
|
98
|
+
if (theme?.brandColor) {
|
|
99
|
+
const darker = `color-mix(in srgb, ${accent} 78%, black)`;
|
|
100
|
+
const brandLink = `light-dark(color-mix(in srgb, ${accent} 65%, black), color-mix(in srgb, ${accent} 76%, white))`;
|
|
101
|
+
const canvas = `light-dark(color-mix(in srgb, ${accent} 7%, white), color-mix(in srgb, ${accent} 8%, #10191a))`;
|
|
102
|
+
const surface = `light-dark(color-mix(in srgb, ${accent} 2%, white), color-mix(in srgb, ${accent} 12%, #182526))`;
|
|
103
|
+
const surfaceHover = `light-dark(color-mix(in srgb, ${accent} 12%, white), color-mix(in srgb, ${accent} 20%, #26383b))`;
|
|
104
|
+
const border = `light-dark(color-mix(in srgb, ${accent} 24%, #d1d1d1), color-mix(in srgb, ${accent} 32%, #6b7476))`;
|
|
105
|
+
Object.assign(result, {
|
|
106
|
+
"--spui-ui-canvas": canvas,
|
|
107
|
+
"--spui-ui-surface": surface,
|
|
108
|
+
"--spui-ui-surface-alt": canvas,
|
|
109
|
+
"--spui-ui-surface-hover": surfaceHover,
|
|
110
|
+
"--spui-ui-stroke": border,
|
|
111
|
+
"--spui-ui-border-subtle": `light-dark(color-mix(in srgb, ${accent} 14%, #e5e5e5), color-mix(in srgb, ${accent} 20%, #344245))`,
|
|
112
|
+
"--spui-selection-background": `light-dark(color-mix(in srgb, ${accent} 15%, white), color-mix(in srgb, ${accent} 24%, #202b2c))`,
|
|
113
|
+
"--spui-semantic-primary-button-background": accent,
|
|
114
|
+
"--spui-semantic-primary-button-background-hovered": `color-mix(in srgb, ${accent} 84%, black)`,
|
|
115
|
+
"--spui-semantic-input-focus-border-alt": accent,
|
|
116
|
+
"--spui-semantic-input-background-checked": accent,
|
|
117
|
+
"--spui-semantic-link": brandLink,
|
|
118
|
+
"--spui-semantic-link-hovered": darker,
|
|
119
|
+
"--spui-control-border": border,
|
|
120
|
+
"--spui-input-border": border,
|
|
121
|
+
"--spui-semantic-body-background": canvas,
|
|
122
|
+
"--spui-semantic-card-background": surface,
|
|
123
|
+
"--spui-semantic-body-divider": border,
|
|
124
|
+
"--spui-semantic-button-background-hovered": surfaceHover,
|
|
125
|
+
"--colorBrandBackground": accent,
|
|
126
|
+
"--colorBrandBackground2": `light-dark(color-mix(in srgb, ${accent} 12%, white), color-mix(in srgb, ${accent} 18%, #182526))`,
|
|
127
|
+
"--colorBrandBackground2Hover": `light-dark(color-mix(in srgb, ${accent} 20%, white), color-mix(in srgb, ${accent} 26%, #26383b))`,
|
|
128
|
+
"--colorBrandBackgroundPressed": `color-mix(in srgb, ${accent} 76%, black)`,
|
|
129
|
+
"--colorBrandBackgroundSelected": darker,
|
|
130
|
+
"--colorBrandForegroundLink": brandLink,
|
|
131
|
+
"--colorBrandStroke2Hover": `light-dark(color-mix(in srgb, ${accent} 62%, white), color-mix(in srgb, ${accent} 62%, #6b7476))`,
|
|
132
|
+
"--colorNeutralBackground1": surface,
|
|
133
|
+
"--colorNeutralBackground1Hover": surfaceHover,
|
|
134
|
+
"--colorNeutralBackground2": canvas,
|
|
135
|
+
"--colorNeutralStroke2": border,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
87
138
|
if (accent && !theme?.colors?.accentForeground) {
|
|
88
139
|
const hex = /^#([\da-f]{3}|[\da-f]{6})$/i.exec(accent)?.[1];
|
|
89
140
|
if (hex) {
|
|
@@ -104,6 +155,22 @@ export function getSharePointUIDesignTokens(theme) {
|
|
|
104
155
|
}
|
|
105
156
|
}
|
|
106
157
|
}
|
|
158
|
+
// Explicit Fluent values are the host's final named-token layer, even when
|
|
159
|
+
// a brand seed also generates defaults for the same Fluent roles.
|
|
160
|
+
for (const [name, value] of Object.entries(theme?.fluentTokens ?? {})) {
|
|
161
|
+
if (value !== undefined && (typeof value === "string" || typeof value === "number")) {
|
|
162
|
+
result[name.startsWith("--") ? name : `--${name}`] = String(value);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (accent) {
|
|
166
|
+
const foreground = theme?.colors?.accentForeground ?? result["--spui-ui-accent-text"];
|
|
167
|
+
if (theme?.brandColor && result["--spui-semantic-primary-button-text"] === undefined && foreground)
|
|
168
|
+
result["--spui-semantic-primary-button-text"] = foreground;
|
|
169
|
+
if (theme?.brandColor && result["--colorNeutralForegroundOnBrand"] === undefined && foreground)
|
|
170
|
+
result["--colorNeutralForegroundOnBrand"] = foreground;
|
|
171
|
+
if (theme?.colors?.link)
|
|
172
|
+
result["--spui-semantic-link"] = theme.colors.link;
|
|
173
|
+
}
|
|
107
174
|
// App-specific properties are the final design-pack layer; direct provider tokens still win later.
|
|
108
175
|
for (const [name, value] of Object.entries(theme?.customProperties ?? {})) {
|
|
109
176
|
if (name.startsWith("--") && name.length > 2)
|
|
@@ -149,6 +216,16 @@ export function applySharePointTheme(target, theme, fluentTokens, options = {})
|
|
|
149
216
|
style.setProperty("--spui-is-inverted", theme.isInverted ? "1" : "0");
|
|
150
217
|
names.add("--spui-is-inverted");
|
|
151
218
|
}
|
|
219
|
+
// Older SPFx themes expose their brand only in palette.themePrimary. The
|
|
220
|
+
// appearance presets consume the semantic role, so bridge that value when
|
|
221
|
+
// neither semantic colors nor Fluent v9 already provide a brand token.
|
|
222
|
+
const semanticAccent = theme?.semanticColors?.primaryButtonBackground;
|
|
223
|
+
const fluentAccent = fluentTokens?.colorBrandBackground;
|
|
224
|
+
const paletteAccent = theme?.palette?.themePrimary;
|
|
225
|
+
if (!semanticAccent && !fluentAccent && paletteAccent) {
|
|
226
|
+
style.setProperty("--spui-semantic-primary-button-background", paletteAccent);
|
|
227
|
+
names.add("--spui-semantic-primary-button-background");
|
|
228
|
+
}
|
|
152
229
|
for (const [name, value] of Object.entries(fluentTokens ?? {})) {
|
|
153
230
|
if (typeof value !== "string" && typeof value !== "number")
|
|
154
231
|
continue;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spfx-fast/sharepoint-ui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Host-aware, framework-independent UI elements for SharePoint Framework",
|
|
6
|
-
"homepage": "https://vystartasv.github.io/sharepoint-ui
|
|
6
|
+
"homepage": "https://vystartasv.github.io/sharepoint-ui/",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/vystartasv/sharepoint-ui.git"
|
|
@@ -47,12 +47,21 @@
|
|
|
47
47
|
"types": "./dist/appearance.d.ts",
|
|
48
48
|
"import": "./dist/appearance.js"
|
|
49
49
|
},
|
|
50
|
+
"./theme": {
|
|
51
|
+
"types": "./dist/theme.d.ts",
|
|
52
|
+
"import": "./dist/theme.js"
|
|
53
|
+
},
|
|
54
|
+
"./sharepoint-fields": {
|
|
55
|
+
"types": "./dist/sharepoint-fields.d.ts",
|
|
56
|
+
"import": "./dist/sharepoint-fields.js"
|
|
57
|
+
},
|
|
50
58
|
"./tokens": "./tokens.json"
|
|
51
59
|
},
|
|
52
60
|
"files": [
|
|
53
61
|
"dist",
|
|
54
62
|
"LICENSE",
|
|
55
63
|
"README.md",
|
|
64
|
+
"QUICKSTART.md",
|
|
56
65
|
"AGENTS.md",
|
|
57
66
|
"components.json",
|
|
58
67
|
"tokens.json",
|
|
@@ -7,6 +7,6 @@ description: Build or change accessible, theme-aware SharePoint Framework interf
|
|
|
7
7
|
|
|
8
8
|
Use the package manifest at `../../components.json` to find exact React names, custom-element tags, and leaf entry points. The source repository checks it with `npm run catalog:check --workspace @spfx-fast/sharepoint-ui`. Use the package's TypeScript declarations as the final API authority. Do not infer that an unlisted Fluent v9 component exists; the library is still growing toward parity.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Start with [`QUICKSTART.md`](../../QUICKSTART.md) for the shared composition contract and copy-ready examples. Use [choosing components](references/choosing-components.md) to select controls and [SharePoint patterns](references/sharepoint-patterns.md) for locale, RTL, forms, and persistence.
|
|
11
11
|
|
|
12
12
|
Prefer leaf imports. Keep SharePoint permissions, data fetching, and writes in an SPFx service. Controls emit state; they do not save records implicitly. Validate keyboard use, theme contrast on the target surface, and RTL when relevant.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Theme and layout
|
|
4
4
|
|
|
5
|
-
Wrap a React surface in `SharePointUIProvider` and pass the SharePoint `ThemeProvider` values through `applySharePointTheme()` at the web-part boundary. Set `lang
|
|
5
|
+
Wrap a React surface in `SharePointUIProvider` and pass the SharePoint `ThemeProvider` values through `applySharePointTheme()` at the web-part boundary. Set the provider `lang`; it derives `dir` from the BCP 47 language tag. Set `dir` explicitly only to override that direction. Use tokens and CSS parts to customize; avoid copying a component's internal markup. Glass derives its values from the selected SharePoint/base appearance.
|
|
6
6
|
|
|
7
7
|
## Forms and events
|
|
8
8
|
|