@dataverse-kit/surface-kit 0.4.0 → 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/README.md +29 -0
- package/dist/core.cjs +38 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +47 -1
- package/dist/core.d.ts +47 -1
- package/dist/core.mjs +33 -1
- package/dist/core.mjs.map +1 -1
- package/dist/index.cjs +38 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.mjs +34 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{useDensity-xEYt-GdJ.d.cts → useDensity-CLglP89q.d.cts} +1 -1
- package/dist/{useDensity-BePwtUzY.d.ts → useDensity-fkCdcf_j.d.ts} +1 -1
- package/dist/v9.cjs +1262 -158
- package/dist/v9.cjs.map +1 -1
- package/dist/v9.d.cts +216 -25
- package/dist/v9.d.ts +216 -25
- package/dist/v9.mjs +1290 -174
- package/dist/v9.mjs.map +1 -1
- package/package.json +3 -2
package/dist/v9.mjs
CHANGED
|
@@ -44,6 +44,34 @@ function clampSpan(span, columns) {
|
|
|
44
44
|
return Math.max(1, Math.min(Math.round(span), columns));
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
// src/core/ceLayout.ts
|
|
48
|
+
var CE_TAB_COLUMN_MIN_WIDTH = 340;
|
|
49
|
+
function normalizeColumnShares(shares) {
|
|
50
|
+
const clean = shares.map((s) => Number.isFinite(s) && s > 0 ? s : 0);
|
|
51
|
+
const total = clean.reduce((a, b) => a + b, 0);
|
|
52
|
+
if (total <= 0) return shares.map(() => 100 / (shares.length || 1));
|
|
53
|
+
return clean.map((s) => s / total * 100);
|
|
54
|
+
}
|
|
55
|
+
function resolveTabColumnWidths(shares, available, minWidth = CE_TAB_COLUMN_MIN_WIDTH) {
|
|
56
|
+
if (shares.length === 0) return [];
|
|
57
|
+
shares = normalizeColumnShares(shares);
|
|
58
|
+
const clamped = /* @__PURE__ */ new Set();
|
|
59
|
+
let widths = [];
|
|
60
|
+
for (let pass = 0; pass <= shares.length; pass++) {
|
|
61
|
+
const free = available - clamped.size * minWidth;
|
|
62
|
+
const total = shares.reduce((sum, s, i) => clamped.has(i) ? sum : sum + Math.max(0, s), 0);
|
|
63
|
+
widths = shares.map((s, i) => {
|
|
64
|
+
if (clamped.has(i)) return minWidth;
|
|
65
|
+
return total > 0 ? Math.max(0, s) / total * free : free / (shares.length - clamped.size);
|
|
66
|
+
});
|
|
67
|
+
const violators = widths.map((w, i) => !clamped.has(i) && w < minWidth ? i : -1).filter((i) => i >= 0);
|
|
68
|
+
if (violators.length === 0) break;
|
|
69
|
+
violators.forEach((i) => clamped.add(i));
|
|
70
|
+
}
|
|
71
|
+
return widths;
|
|
72
|
+
}
|
|
73
|
+
var CE_LABEL_ABOVE_BELOW_ROW_WIDTH = 340;
|
|
74
|
+
|
|
47
75
|
// src/responsive/breakpoints.ts
|
|
48
76
|
var BREAKPOINTS = {
|
|
49
77
|
xs: 0,
|
|
@@ -120,7 +148,7 @@ function fieldRowStyle(labelWidth = "130px", mode = "media") {
|
|
|
120
148
|
}
|
|
121
149
|
|
|
122
150
|
// src/tokens/tokens.ts
|
|
123
|
-
import { colors, spacing, typography, radius, layout } from "@dataverse-kit/design-tokens";
|
|
151
|
+
import { colors, spacing, typography, radius, layout, ceForm } from "@dataverse-kit/design-tokens";
|
|
124
152
|
|
|
125
153
|
// src/tokens/density.ts
|
|
126
154
|
var densityScale = {
|
|
@@ -194,39 +222,21 @@ import { createContext, useContext } from "react";
|
|
|
194
222
|
var DensityContext = createContext("comfortable");
|
|
195
223
|
var useDensity = () => useContext(DensityContext);
|
|
196
224
|
|
|
225
|
+
// src/hooks/useLook.ts
|
|
226
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
227
|
+
var LookContext = createContext2("default");
|
|
228
|
+
var useLook = () => useContext2(LookContext);
|
|
229
|
+
|
|
197
230
|
// src/v9/theme.ts
|
|
198
231
|
import {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
50: "#0e4775",
|
|
208
|
-
60: colors.brandDark,
|
|
209
|
-
// #005a9e — colorBrandBackgroundPressed
|
|
210
|
-
70: colors.brandHover,
|
|
211
|
-
// #106ebe — colorBrandBackground(Hover/Selected)
|
|
212
|
-
80: colors.brand,
|
|
213
|
-
// #0078d4 — colorBrandBackground + colorBrandForeground1 (the Dynamics blue)
|
|
214
|
-
90: "#2886de",
|
|
215
|
-
100: "#479ef5",
|
|
216
|
-
110: "#62abf5",
|
|
217
|
-
120: "#77b7f7",
|
|
218
|
-
130: "#96c6fa",
|
|
219
|
-
140: "#b4d6fa",
|
|
220
|
-
150: "#cfe4fa",
|
|
221
|
-
160: "#ebf3fc"
|
|
222
|
-
};
|
|
223
|
-
function createDynamicsV9Theme(brand = dynamicsBrandRamp) {
|
|
224
|
-
return createLightTheme(brand);
|
|
225
|
-
}
|
|
226
|
-
function createDynamicsV9DarkTheme(brand = dynamicsBrandRamp) {
|
|
227
|
-
return createDarkTheme(brand);
|
|
228
|
-
}
|
|
229
|
-
var dynamicsV9Theme = createDynamicsV9Theme();
|
|
232
|
+
dynamicsBrandRamp,
|
|
233
|
+
createDynamicsV9Theme,
|
|
234
|
+
createDynamicsV9DarkTheme,
|
|
235
|
+
dynamicsV9Theme,
|
|
236
|
+
dynamicsV9DarkTheme,
|
|
237
|
+
createDynamicsCeTheme,
|
|
238
|
+
dynamicsCeTheme
|
|
239
|
+
} from "@dataverse-kit/fluent-theme";
|
|
230
240
|
|
|
231
241
|
// src/v9/containers/FormSurface.tsx
|
|
232
242
|
import { makeStyles, mergeClasses, tokens } from "@fluentui/react-components";
|
|
@@ -260,10 +270,11 @@ var VIEWPORT_STACK = {
|
|
|
260
270
|
var FormSurface = ({
|
|
261
271
|
columns = 12,
|
|
262
272
|
gap = 20,
|
|
263
|
-
padding
|
|
273
|
+
padding,
|
|
264
274
|
density = "comfortable",
|
|
265
275
|
background,
|
|
266
276
|
containerWidth,
|
|
277
|
+
look = "default",
|
|
267
278
|
collapseBelow = "sm",
|
|
268
279
|
maxWidth,
|
|
269
280
|
className,
|
|
@@ -271,10 +282,29 @@ var FormSurface = ({
|
|
|
271
282
|
children
|
|
272
283
|
}) => {
|
|
273
284
|
const styles = useStyles();
|
|
285
|
+
if (look === "ce") {
|
|
286
|
+
return /* @__PURE__ */ jsx(DensityContext.Provider, { value: density, children: /* @__PURE__ */ jsx(LookContext.Provider, { value: look, children: /* @__PURE__ */ jsx(
|
|
287
|
+
"div",
|
|
288
|
+
{
|
|
289
|
+
className,
|
|
290
|
+
"data-surface-part": "form-surface",
|
|
291
|
+
"data-look": "ce",
|
|
292
|
+
style: {
|
|
293
|
+
display: "flow-root",
|
|
294
|
+
minWidth: 0,
|
|
295
|
+
padding: padding ?? 0,
|
|
296
|
+
...background != null ? { background } : {},
|
|
297
|
+
...maxWidth != null ? { maxWidth, marginLeft: "auto", marginRight: "auto" } : {},
|
|
298
|
+
...style
|
|
299
|
+
},
|
|
300
|
+
children
|
|
301
|
+
}
|
|
302
|
+
) }) });
|
|
303
|
+
}
|
|
274
304
|
const collapsePx = BREAKPOINTS[collapseBelow];
|
|
275
305
|
const forceStack = containerWidth != null && containerWidth <= collapsePx;
|
|
276
306
|
const scaledGap = scaleSpacing(gap, density);
|
|
277
|
-
const scaledPadding = scaleSpacing(padding, density);
|
|
307
|
+
const scaledPadding = scaleSpacing(padding ?? 20, density);
|
|
278
308
|
const viewportStackSlot = containerWidth == null ? VIEWPORT_STACK[collapseBelow] : null;
|
|
279
309
|
const cls = mergeClasses(
|
|
280
310
|
styles.root,
|
|
@@ -290,7 +320,7 @@ var FormSurface = ({
|
|
|
290
320
|
...maxWidth != null ? { maxWidth, marginLeft: "auto", marginRight: "auto" } : {},
|
|
291
321
|
...style
|
|
292
322
|
};
|
|
293
|
-
return /* @__PURE__ */ jsx(DensityContext.Provider, { value: density, children: /* @__PURE__ */ jsx("div", { className: cls, style: inlineStyle, children }) });
|
|
323
|
+
return /* @__PURE__ */ jsx(DensityContext.Provider, { value: density, children: /* @__PURE__ */ jsx(LookContext.Provider, { value: look, children: /* @__PURE__ */ jsx("div", { className: cls, style: inlineStyle, children }) }) });
|
|
294
324
|
};
|
|
295
325
|
|
|
296
326
|
// src/v9/containers/PageSurface.tsx
|
|
@@ -298,8 +328,232 @@ import { jsx as jsx2 } from "react/jsx-runtime";
|
|
|
298
328
|
var PageSurface = ({ centered, maxWidth, ...rest }) => /* @__PURE__ */ jsx2(FormSurface, { maxWidth: maxWidth ?? (centered ? 1200 : void 0), ...rest });
|
|
299
329
|
|
|
300
330
|
// src/v9/containers/Section.tsx
|
|
301
|
-
import { useState as useState3 } from "react";
|
|
302
|
-
import { makeStyles as
|
|
331
|
+
import React, { useState as useState3 } from "react";
|
|
332
|
+
import { makeStyles as makeStyles3, mergeClasses as mergeClasses3, tokens as tokens4 } from "@fluentui/react-components";
|
|
333
|
+
|
|
334
|
+
// src/v9/layouts/FieldRow.tsx
|
|
335
|
+
import { makeStyles as makeStyles2, mergeClasses as mergeClasses2, tokens as tokens2 } from "@fluentui/react-components";
|
|
336
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
337
|
+
var F = ceForm.field;
|
|
338
|
+
var CE_LABEL_BOX = 30;
|
|
339
|
+
var CE_LABEL_OFFSET = 4;
|
|
340
|
+
var CE_CONTROL_OFFSET = 2;
|
|
341
|
+
var CE_CONTROL_INSET_RIGHT = 2;
|
|
342
|
+
var CE_LABEL_TEXT_WIDTH = 176;
|
|
343
|
+
var CE_MARKER_GAP = 4;
|
|
344
|
+
var ceFieldRowFirstOffset = F.rowPaddingTop - F.rowPaddingTopFirst;
|
|
345
|
+
var NARROW = `@container (width < ${CE_LABEL_ABOVE_BELOW_ROW_WIDTH}px)`;
|
|
346
|
+
var useStyles2 = makeStyles2({
|
|
347
|
+
// ── shared ──────────────────────────────────────────────────────────────
|
|
348
|
+
// Span every column when placed in a grid (v9 Section's body is repeat(12, 1fr)).
|
|
349
|
+
spanAll: { gridColumn: "1 / -1" },
|
|
350
|
+
// ── ce ──────────────────────────────────────────────────────────────────
|
|
351
|
+
ceRow: {
|
|
352
|
+
paddingTop: `${F.rowPaddingTop}px`,
|
|
353
|
+
minWidth: 0
|
|
354
|
+
},
|
|
355
|
+
ceContainer: { containerType: "inline-size" },
|
|
356
|
+
ceGrid: {
|
|
357
|
+
display: "grid",
|
|
358
|
+
alignItems: "start"
|
|
359
|
+
},
|
|
360
|
+
// ★ The column template lives in CLASSES, never in an inline style: an inline
|
|
361
|
+
// grid-template-columns beats the @container rule, so 'auto' never flipped to 'above'
|
|
362
|
+
// (caught measuring a 306px row in a real browser; jsdom cannot see it). A custom labelWidth
|
|
363
|
+
// reaches the class through the --sk-label-col custom property.
|
|
364
|
+
ceGridBeside: { gridTemplateColumns: "var(--sk-label-col) minmax(0, 1fr)" },
|
|
365
|
+
ceGridSingle: { gridTemplateColumns: "minmax(0, 1fr)" },
|
|
366
|
+
ceLabelBeside: {
|
|
367
|
+
display: "flex",
|
|
368
|
+
alignItems: "center",
|
|
369
|
+
minHeight: `${CE_LABEL_BOX}px`,
|
|
370
|
+
marginTop: `${CE_LABEL_OFFSET}px`,
|
|
371
|
+
// 184 − 176: the measured text width. A required marker is allowed into half of it (below).
|
|
372
|
+
paddingRight: `${F.labelColumnWidth - CE_LABEL_TEXT_WIDTH}px`
|
|
373
|
+
},
|
|
374
|
+
ceLabelAbove: {
|
|
375
|
+
display: "flex",
|
|
376
|
+
alignItems: "center",
|
|
377
|
+
marginTop: `${CE_CONTROL_OFFSET}px`,
|
|
378
|
+
minHeight: `${F.labelLineHeight}px`
|
|
379
|
+
},
|
|
380
|
+
ceControlBeside: {
|
|
381
|
+
marginTop: `${CE_CONTROL_OFFSET}px`,
|
|
382
|
+
marginBottom: `${CE_CONTROL_OFFSET}px`,
|
|
383
|
+
marginRight: `${CE_CONTROL_INSET_RIGHT}px`,
|
|
384
|
+
minWidth: 0
|
|
385
|
+
},
|
|
386
|
+
ceControlAbove: {
|
|
387
|
+
marginTop: `${F.labelAboveGap}px`,
|
|
388
|
+
marginBottom: `${CE_CONTROL_OFFSET}px`,
|
|
389
|
+
marginRight: `${CE_CONTROL_INSET_RIGHT}px`,
|
|
390
|
+
minWidth: 0
|
|
391
|
+
},
|
|
392
|
+
// 'auto': beside by default, above when the ROW is narrower than the (provisional) switch point.
|
|
393
|
+
ceAutoGrid: { [NARROW]: { gridTemplateColumns: "minmax(0, 1fr)" } },
|
|
394
|
+
ceAutoLabel: {
|
|
395
|
+
[NARROW]: {
|
|
396
|
+
marginTop: `${CE_CONTROL_OFFSET}px`,
|
|
397
|
+
minHeight: `${F.labelLineHeight}px`,
|
|
398
|
+
paddingRight: 0
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
ceAutoControl: { [NARROW]: { marginTop: `${F.labelAboveGap}px` } },
|
|
402
|
+
ceLabelText: {
|
|
403
|
+
minWidth: 0,
|
|
404
|
+
fontSize: tokens2.fontSizeBase300,
|
|
405
|
+
lineHeight: `${F.labelLineHeight}px`,
|
|
406
|
+
fontWeight: tokens2.fontWeightRegular,
|
|
407
|
+
color: tokens2.colorNeutralForeground1,
|
|
408
|
+
overflowWrap: "anywhere"
|
|
409
|
+
},
|
|
410
|
+
// Beside, the text fills the column so the marker sits at the column's end (measured: marker's
|
|
411
|
+
// right edge 180px from the row). Above, the marker follows the text (position unmeasured).
|
|
412
|
+
ceLabelTextFill: { flexGrow: 1 },
|
|
413
|
+
ceAutoLabelText: { [NARROW]: { flexGrow: 0 } },
|
|
414
|
+
ceRequired: {
|
|
415
|
+
flexShrink: 0,
|
|
416
|
+
color: tokens2.colorPaletteRedForeground1,
|
|
417
|
+
paddingLeft: `${CE_MARKER_GAP}px`
|
|
418
|
+
},
|
|
419
|
+
// Beside: the marker takes half the column's 8px padding → text 168.5 + 4 + 7.5 = 176 + 4.
|
|
420
|
+
ceRequiredBeside: { marginRight: `-${CE_MARKER_GAP}px` },
|
|
421
|
+
ceAutoRequired: { [NARROW]: { marginRight: 0 } },
|
|
422
|
+
// ── default ─────────────────────────────────────────────────────────────
|
|
423
|
+
defaultBeside: {
|
|
424
|
+
display: "grid",
|
|
425
|
+
alignItems: "center",
|
|
426
|
+
columnGap: "8px",
|
|
427
|
+
minHeight: "38px",
|
|
428
|
+
[`@media (max-width: ${BREAKPOINTS.sm}px)`]: {
|
|
429
|
+
gridTemplateColumns: "1fr !important",
|
|
430
|
+
alignItems: "flex-start",
|
|
431
|
+
minHeight: 0,
|
|
432
|
+
rowGap: "4px"
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
defaultAbove: {
|
|
436
|
+
display: "grid",
|
|
437
|
+
gridTemplateColumns: "1fr",
|
|
438
|
+
rowGap: "2px",
|
|
439
|
+
minHeight: "38px"
|
|
440
|
+
},
|
|
441
|
+
defaultLabel: {
|
|
442
|
+
fontSize: tokens2.fontSizeBase200,
|
|
443
|
+
fontWeight: tokens2.fontWeightSemibold,
|
|
444
|
+
color: tokens2.colorNeutralForeground1,
|
|
445
|
+
lineHeight: "1.3",
|
|
446
|
+
overflowWrap: "anywhere"
|
|
447
|
+
},
|
|
448
|
+
// v8 FieldRow's marker: colors.danger, semibold, 2px after the text.
|
|
449
|
+
defaultRequired: {
|
|
450
|
+
color: colors.danger,
|
|
451
|
+
marginLeft: "2px",
|
|
452
|
+
fontWeight: tokens2.fontWeightSemibold
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
var toCssLength = (v) => typeof v === "number" ? `${v}px` : v;
|
|
456
|
+
var FieldRow = ({
|
|
457
|
+
label,
|
|
458
|
+
required,
|
|
459
|
+
htmlFor,
|
|
460
|
+
labelPosition,
|
|
461
|
+
labelWidth,
|
|
462
|
+
look: lookProp,
|
|
463
|
+
className,
|
|
464
|
+
style,
|
|
465
|
+
children
|
|
466
|
+
}) => {
|
|
467
|
+
const styles = useStyles2();
|
|
468
|
+
const ambientLook = useLook();
|
|
469
|
+
const look = lookProp ?? ambientLook;
|
|
470
|
+
const ce = look === "ce";
|
|
471
|
+
const position = labelPosition ?? (ce ? "auto" : "beside");
|
|
472
|
+
const hasLabel = label != null;
|
|
473
|
+
const column = toCssLength(labelWidth ?? (ce ? F.labelColumnWidth : 130));
|
|
474
|
+
const LabelTag = htmlFor ? "label" : "span";
|
|
475
|
+
if (!ce) {
|
|
476
|
+
const beside2 = position !== "above" && hasLabel;
|
|
477
|
+
return /* @__PURE__ */ jsxs(
|
|
478
|
+
"div",
|
|
479
|
+
{
|
|
480
|
+
className: mergeClasses2(styles.spanAll, beside2 ? styles.defaultBeside : styles.defaultAbove, className),
|
|
481
|
+
style: { ...beside2 ? { gridTemplateColumns: `${column} 1fr` } : {}, ...style },
|
|
482
|
+
"data-surface-part": "field-row",
|
|
483
|
+
"data-look": "default",
|
|
484
|
+
children: [
|
|
485
|
+
hasLabel && /* @__PURE__ */ jsxs(LabelTag, { htmlFor, className: styles.defaultLabel, "data-surface-part": "label", children: [
|
|
486
|
+
label,
|
|
487
|
+
required && /* @__PURE__ */ jsx3("span", { className: styles.defaultRequired, "aria-hidden": "true", "data-surface-part": "required", children: "*" })
|
|
488
|
+
] }),
|
|
489
|
+
children
|
|
490
|
+
]
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
const auto = position === "auto" && hasLabel;
|
|
495
|
+
const beside = position !== "above" && hasLabel;
|
|
496
|
+
return /* @__PURE__ */ jsx3(
|
|
497
|
+
"div",
|
|
498
|
+
{
|
|
499
|
+
className: mergeClasses2(styles.spanAll, styles.ceRow, auto && styles.ceContainer, className),
|
|
500
|
+
style,
|
|
501
|
+
"data-surface-part": "field-row",
|
|
502
|
+
"data-look": "ce",
|
|
503
|
+
"data-label-position": position,
|
|
504
|
+
"data-container": auto ? "inline-size" : void 0,
|
|
505
|
+
children: /* @__PURE__ */ jsxs(
|
|
506
|
+
"div",
|
|
507
|
+
{
|
|
508
|
+
className: mergeClasses2(styles.ceGrid, beside ? styles.ceGridBeside : styles.ceGridSingle, auto && styles.ceAutoGrid),
|
|
509
|
+
style: beside ? { "--sk-label-col": column } : void 0,
|
|
510
|
+
"data-surface-part": "field-grid",
|
|
511
|
+
children: [
|
|
512
|
+
hasLabel && /* @__PURE__ */ jsxs(
|
|
513
|
+
LabelTag,
|
|
514
|
+
{
|
|
515
|
+
htmlFor,
|
|
516
|
+
className: mergeClasses2(beside ? styles.ceLabelBeside : styles.ceLabelAbove, auto && styles.ceAutoLabel),
|
|
517
|
+
"data-surface-part": "label",
|
|
518
|
+
children: [
|
|
519
|
+
/* @__PURE__ */ jsx3(
|
|
520
|
+
"span",
|
|
521
|
+
{
|
|
522
|
+
className: mergeClasses2(styles.ceLabelText, beside && styles.ceLabelTextFill, auto && styles.ceAutoLabelText),
|
|
523
|
+
"data-surface-part": "label-text",
|
|
524
|
+
children: label
|
|
525
|
+
}
|
|
526
|
+
),
|
|
527
|
+
required && /* @__PURE__ */ jsx3(
|
|
528
|
+
"span",
|
|
529
|
+
{
|
|
530
|
+
className: mergeClasses2(styles.ceRequired, beside && styles.ceRequiredBeside, auto && styles.ceAutoRequired),
|
|
531
|
+
"aria-hidden": "true",
|
|
532
|
+
"data-surface-part": "required",
|
|
533
|
+
children: "*"
|
|
534
|
+
}
|
|
535
|
+
)
|
|
536
|
+
]
|
|
537
|
+
}
|
|
538
|
+
),
|
|
539
|
+
/* @__PURE__ */ jsx3(
|
|
540
|
+
"div",
|
|
541
|
+
{
|
|
542
|
+
className: mergeClasses2(
|
|
543
|
+
// No label: the control sits where a beside control would (2px down), full width.
|
|
544
|
+
!hasLabel || beside ? styles.ceControlBeside : styles.ceControlAbove,
|
|
545
|
+
auto && styles.ceAutoControl
|
|
546
|
+
),
|
|
547
|
+
"data-surface-part": "control",
|
|
548
|
+
children
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
]
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
}
|
|
555
|
+
);
|
|
556
|
+
};
|
|
303
557
|
|
|
304
558
|
// src/v9/containers/SectionHeader.tsx
|
|
305
559
|
import {
|
|
@@ -307,10 +561,10 @@ import {
|
|
|
307
561
|
Text,
|
|
308
562
|
Toolbar,
|
|
309
563
|
ToolbarButton,
|
|
310
|
-
tokens as
|
|
564
|
+
tokens as tokens3
|
|
311
565
|
} from "@fluentui/react-components";
|
|
312
566
|
import { ChevronDown20Regular, ChevronRight20Regular } from "@fluentui/react-icons";
|
|
313
|
-
import { jsx as
|
|
567
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
314
568
|
var SectionHeader = ({
|
|
315
569
|
title,
|
|
316
570
|
statusText,
|
|
@@ -319,14 +573,26 @@ var SectionHeader = ({
|
|
|
319
573
|
actions,
|
|
320
574
|
collapsible,
|
|
321
575
|
collapsed,
|
|
322
|
-
onToggle
|
|
576
|
+
onToggle,
|
|
577
|
+
look: lookProp
|
|
323
578
|
}) => {
|
|
579
|
+
const ambientLook = useLook();
|
|
580
|
+
const ce = (lookProp ?? ambientLook) === "ce";
|
|
581
|
+
const ceRootStyle = {
|
|
582
|
+
display: "flex",
|
|
583
|
+
justifyContent: "space-between",
|
|
584
|
+
alignItems: "center",
|
|
585
|
+
flexWrap: "nowrap",
|
|
586
|
+
paddingTop: ceForm.section.titlePaddingTop,
|
|
587
|
+
minHeight: ceForm.section.titleHeight - ceForm.section.titlePaddingTop,
|
|
588
|
+
width: "100%"
|
|
589
|
+
};
|
|
324
590
|
const rootStyle = {
|
|
325
591
|
display: "flex",
|
|
326
592
|
justifyContent: "space-between",
|
|
327
593
|
alignItems: "center",
|
|
328
594
|
flexWrap: "nowrap",
|
|
329
|
-
borderBottom: `1px solid ${
|
|
595
|
+
borderBottom: `1px solid ${tokens3.colorNeutralStroke2}`,
|
|
330
596
|
marginBottom: 16,
|
|
331
597
|
minHeight: 48,
|
|
332
598
|
width: "100%"
|
|
@@ -334,26 +600,40 @@ var SectionHeader = ({
|
|
|
334
600
|
const leftStyle = { display: "flex", alignItems: "center", gap: 8, minWidth: 0 };
|
|
335
601
|
const statusStyle = {
|
|
336
602
|
marginLeft: 8,
|
|
337
|
-
fontSize:
|
|
338
|
-
color:
|
|
603
|
+
fontSize: tokens3.fontSizeBase200,
|
|
604
|
+
color: tokens3.colorNeutralForeground3
|
|
339
605
|
};
|
|
340
|
-
return /* @__PURE__ */
|
|
341
|
-
/* @__PURE__ */
|
|
342
|
-
collapsible && /* @__PURE__ */
|
|
606
|
+
return /* @__PURE__ */ jsxs2("div", { style: ce ? ceRootStyle : rootStyle, "data-surface-part": "section-header", children: [
|
|
607
|
+
/* @__PURE__ */ jsxs2("div", { style: leftStyle, children: [
|
|
608
|
+
collapsible && /* @__PURE__ */ jsx4(
|
|
343
609
|
Button,
|
|
344
610
|
{
|
|
345
611
|
appearance: "subtle",
|
|
346
612
|
size: "small",
|
|
347
|
-
icon: collapsed ? /* @__PURE__ */
|
|
613
|
+
icon: collapsed ? /* @__PURE__ */ jsx4(ChevronRight20Regular, {}) : /* @__PURE__ */ jsx4(ChevronDown20Regular, {}),
|
|
348
614
|
onClick: onToggle,
|
|
349
615
|
"aria-label": collapsed ? "Expand section" : "Collapse section",
|
|
350
616
|
"aria-expanded": !collapsed
|
|
351
617
|
}
|
|
352
618
|
),
|
|
353
|
-
title &&
|
|
354
|
-
|
|
619
|
+
title && (ce ? (
|
|
620
|
+
// Rendered exactly as given: Dynamics does not uppercase section titles (the stock
|
|
621
|
+
// Account labels are typed uppercase; "Description" renders mixed-case).
|
|
622
|
+
/* @__PURE__ */ jsx4(
|
|
623
|
+
Text,
|
|
624
|
+
{
|
|
625
|
+
as: "h2",
|
|
626
|
+
weight: "semibold",
|
|
627
|
+
size: 300,
|
|
628
|
+
style: { margin: 0, lineHeight: `${ceForm.section.titleLineHeight}px`, color: tokens3.colorNeutralForeground1 },
|
|
629
|
+
"data-surface-part": "section-title",
|
|
630
|
+
children: title
|
|
631
|
+
}
|
|
632
|
+
)
|
|
633
|
+
) : /* @__PURE__ */ jsx4(Text, { weight: "semibold", size: 300, children: title })),
|
|
634
|
+
statusText && /* @__PURE__ */ jsx4("span", { style: statusStyle, children: statusText })
|
|
355
635
|
] }),
|
|
356
|
-
actions ? /* @__PURE__ */
|
|
636
|
+
actions ? /* @__PURE__ */ jsx4("div", { children: actions }) : showCommandBar && commandItems.length > 0 ? /* @__PURE__ */ jsx4(Toolbar, { "aria-label": "Section commands", size: "small", children: commandItems.map((item) => /* @__PURE__ */ jsx4(
|
|
357
637
|
ToolbarButton,
|
|
358
638
|
{
|
|
359
639
|
icon: item.icon,
|
|
@@ -368,8 +648,18 @@ var SectionHeader = ({
|
|
|
368
648
|
};
|
|
369
649
|
|
|
370
650
|
// src/v9/containers/Section.tsx
|
|
371
|
-
import { jsx as
|
|
372
|
-
var
|
|
651
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
652
|
+
var px = (v) => v.map((n) => `${n}px`).join(" ");
|
|
653
|
+
function columnsOf(children) {
|
|
654
|
+
const out = [];
|
|
655
|
+
const walk = (n) => {
|
|
656
|
+
if (Array.isArray(n)) n.forEach(walk);
|
|
657
|
+
else if (!(n === null || n === void 0 || typeof n === "boolean" || n === "")) out.push(n);
|
|
658
|
+
};
|
|
659
|
+
walk(children);
|
|
660
|
+
return out;
|
|
661
|
+
}
|
|
662
|
+
var useStyles3 = makeStyles3({
|
|
373
663
|
// Phone-stack the internal field grid below `sm` (griffel — inline can't do @media).
|
|
374
664
|
bodyStack: {
|
|
375
665
|
[`@media (max-width: ${BREAKPOINTS.sm}px)`]: { "& > *": { gridColumn: "1 / -1" } }
|
|
@@ -380,7 +670,7 @@ var Section = ({
|
|
|
380
670
|
columnSpan = 12,
|
|
381
671
|
columnStart,
|
|
382
672
|
rowPosition,
|
|
383
|
-
internalColumns
|
|
673
|
+
internalColumns: internalColumnsProp,
|
|
384
674
|
showCommandBar,
|
|
385
675
|
commandItems,
|
|
386
676
|
statusText,
|
|
@@ -392,11 +682,15 @@ var Section = ({
|
|
|
392
682
|
variant = "card",
|
|
393
683
|
minHeight = 80,
|
|
394
684
|
density: densityProp,
|
|
685
|
+
look: lookProp,
|
|
395
686
|
className,
|
|
396
687
|
style,
|
|
397
688
|
children
|
|
398
689
|
}) => {
|
|
399
|
-
const styles =
|
|
690
|
+
const styles = useStyles3();
|
|
691
|
+
const internalColumns = internalColumnsProp ?? 12;
|
|
692
|
+
const ambientLook = useLook();
|
|
693
|
+
const ce = (lookProp ?? ambientLook) === "ce" && variant === "card";
|
|
400
694
|
const [internalCollapsed, setInternalCollapsed] = useState3(defaultCollapsed);
|
|
401
695
|
const collapsed = controlledCollapsed ?? internalCollapsed;
|
|
402
696
|
const toggle = () => {
|
|
@@ -417,41 +711,102 @@ var Section = ({
|
|
|
417
711
|
if (variant === "placeholder") {
|
|
418
712
|
const placeholderStyle = {
|
|
419
713
|
...rootStyle,
|
|
420
|
-
border: `1px dashed ${
|
|
421
|
-
borderRadius:
|
|
714
|
+
border: `1px dashed ${tokens4.colorNeutralStroke2}`,
|
|
715
|
+
borderRadius: tokens4.borderRadiusMedium,
|
|
422
716
|
minHeight,
|
|
423
717
|
width: "100%",
|
|
424
718
|
background: "transparent"
|
|
425
719
|
};
|
|
426
|
-
return /* @__PURE__ */
|
|
720
|
+
return /* @__PURE__ */ jsx5("div", { className, style: placeholderStyle });
|
|
427
721
|
}
|
|
428
722
|
const chrome = variant === "flat" ? {
|
|
429
|
-
backgroundColor:
|
|
430
|
-
borderRadius:
|
|
723
|
+
backgroundColor: tokens4.colorNeutralBackground1,
|
|
724
|
+
borderRadius: tokens4.borderRadiusMedium,
|
|
431
725
|
padding: cardPad,
|
|
432
726
|
minWidth: 300,
|
|
433
727
|
width: "100%",
|
|
434
728
|
overflow: "hidden"
|
|
435
729
|
} : {
|
|
436
|
-
backgroundColor:
|
|
437
|
-
border: `1px solid ${
|
|
438
|
-
borderRadius:
|
|
439
|
-
boxShadow:
|
|
730
|
+
backgroundColor: tokens4.colorNeutralBackground1,
|
|
731
|
+
border: `1px solid ${tokens4.colorNeutralStroke2}`,
|
|
732
|
+
borderRadius: tokens4.borderRadiusMedium,
|
|
733
|
+
boxShadow: tokens4.shadow4,
|
|
440
734
|
padding: cardPad,
|
|
441
735
|
minWidth: 300,
|
|
442
736
|
width: "100%",
|
|
443
737
|
overflow: "hidden"
|
|
444
738
|
};
|
|
445
739
|
const showHeader = Boolean(title) || showCommandBar || collapsible;
|
|
740
|
+
if (ce) {
|
|
741
|
+
const n = Math.max(1, Math.round(internalColumnsProp ?? 1));
|
|
742
|
+
const ceChrome = {
|
|
743
|
+
backgroundColor: tokens4.colorNeutralBackground1,
|
|
744
|
+
border: "1px solid transparent",
|
|
745
|
+
borderRadius: tokens4.borderRadiusXLarge,
|
|
746
|
+
boxShadow: tokens4.shadow4,
|
|
747
|
+
padding: px(ceForm.section.padding),
|
|
748
|
+
width: "100%",
|
|
749
|
+
boxSizing: "border-box"
|
|
750
|
+
};
|
|
751
|
+
const cols = n > 1 ? columnsOf(children) : null;
|
|
752
|
+
if (cols && cols.length !== n && typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
|
|
753
|
+
console.warn(
|
|
754
|
+
`[surface-kit] Section look="ce" with internalColumns={${n}} got ${cols.length} children. A multi-column CE section takes ONE CHILD PER COLUMN (wrap each column's FieldRows in an element).`
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
return /* @__PURE__ */ jsxs3("section", { className, style: { ...ceChrome, ...rootStyle }, "data-surface-part": "section", "data-look": "ce", children: [
|
|
758
|
+
notification && /* @__PURE__ */ jsx5("div", { children: notification }),
|
|
759
|
+
showHeader && /* @__PURE__ */ jsx5(
|
|
760
|
+
SectionHeader,
|
|
761
|
+
{
|
|
762
|
+
look: "ce",
|
|
763
|
+
title,
|
|
764
|
+
statusText,
|
|
765
|
+
showCommandBar,
|
|
766
|
+
commandItems,
|
|
767
|
+
collapsible,
|
|
768
|
+
collapsed,
|
|
769
|
+
onToggle: toggle
|
|
770
|
+
}
|
|
771
|
+
),
|
|
772
|
+
!collapsed && (cols ? (
|
|
773
|
+
// PROVISIONAL: below the phone breakpoint the columns stack (the default look's rule);
|
|
774
|
+
// Dynamics' multi-column reflow is unmeasured.
|
|
775
|
+
/* @__PURE__ */ jsx5(
|
|
776
|
+
"div",
|
|
777
|
+
{
|
|
778
|
+
className: styles.bodyStack,
|
|
779
|
+
style: { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))`, alignItems: "start" },
|
|
780
|
+
"data-surface-part": "section-body",
|
|
781
|
+
children: cols.map((col, i) => /* @__PURE__ */ jsx5(
|
|
782
|
+
"div",
|
|
783
|
+
{
|
|
784
|
+
style: {
|
|
785
|
+
// Keyed to the COLUMN (i % n), not the list position: every column but the
|
|
786
|
+
// last carries the gutter, and only the first grid row is pulled up.
|
|
787
|
+
marginTop: i < n ? -ceFieldRowFirstOffset : 0,
|
|
788
|
+
paddingRight: i % n < n - 1 ? ceForm.section.columnGutter : 0,
|
|
789
|
+
minWidth: 0
|
|
790
|
+
},
|
|
791
|
+
"data-surface-part": "section-column",
|
|
792
|
+
children: col
|
|
793
|
+
},
|
|
794
|
+
React.isValidElement(col) && col.key != null ? col.key : `col-${i}`
|
|
795
|
+
))
|
|
796
|
+
}
|
|
797
|
+
)
|
|
798
|
+
) : /* @__PURE__ */ jsx5("div", { style: { marginTop: -ceFieldRowFirstOffset }, "data-surface-part": "section-body", children }))
|
|
799
|
+
] });
|
|
800
|
+
}
|
|
446
801
|
const bodyStyle = {
|
|
447
802
|
display: "grid",
|
|
448
803
|
gridTemplateColumns: `repeat(${internalColumns}, 1fr)`,
|
|
449
804
|
gap: bodyGap,
|
|
450
805
|
alignItems: "start"
|
|
451
806
|
};
|
|
452
|
-
return /* @__PURE__ */
|
|
453
|
-
notification && /* @__PURE__ */
|
|
454
|
-
showHeader && /* @__PURE__ */
|
|
807
|
+
return /* @__PURE__ */ jsxs3("div", { className, style: { ...chrome, ...rootStyle }, children: [
|
|
808
|
+
notification && /* @__PURE__ */ jsx5("div", { style: { marginBottom: scaleSpacing(8, density) }, children: notification }),
|
|
809
|
+
showHeader && /* @__PURE__ */ jsx5(
|
|
455
810
|
SectionHeader,
|
|
456
811
|
{
|
|
457
812
|
title,
|
|
@@ -463,20 +818,20 @@ var Section = ({
|
|
|
463
818
|
onToggle: toggle
|
|
464
819
|
}
|
|
465
820
|
),
|
|
466
|
-
!collapsed && /* @__PURE__ */
|
|
821
|
+
!collapsed && /* @__PURE__ */ jsx5("div", { className: mergeClasses3(styles.bodyStack), style: bodyStyle, children })
|
|
467
822
|
] });
|
|
468
823
|
};
|
|
469
824
|
|
|
470
825
|
// src/v9/containers/SectionCard.tsx
|
|
471
|
-
import { tokens as
|
|
472
|
-
import { jsx as
|
|
826
|
+
import { tokens as tokens5 } from "@fluentui/react-components";
|
|
827
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
473
828
|
var SectionCard = ({
|
|
474
|
-
accentColor =
|
|
829
|
+
accentColor = tokens5.colorBrandStroke1,
|
|
475
830
|
accentWidth = 3,
|
|
476
831
|
variant = "card",
|
|
477
832
|
style,
|
|
478
833
|
...rest
|
|
479
|
-
}) => /* @__PURE__ */
|
|
834
|
+
}) => /* @__PURE__ */ jsx6(
|
|
480
835
|
Section,
|
|
481
836
|
{
|
|
482
837
|
variant,
|
|
@@ -486,54 +841,363 @@ var SectionCard = ({
|
|
|
486
841
|
);
|
|
487
842
|
|
|
488
843
|
// src/v9/containers/FormHeader.tsx
|
|
489
|
-
import
|
|
490
|
-
import {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
844
|
+
import React2 from "react";
|
|
845
|
+
import {
|
|
846
|
+
Avatar,
|
|
847
|
+
Button as Button2,
|
|
848
|
+
Menu,
|
|
849
|
+
MenuItemRadio,
|
|
850
|
+
MenuList,
|
|
851
|
+
MenuPopover,
|
|
852
|
+
MenuTrigger,
|
|
853
|
+
Text as Text2,
|
|
854
|
+
createFocusOutlineStyle,
|
|
855
|
+
makeStyles as makeStyles4,
|
|
856
|
+
tokens as tokens6
|
|
857
|
+
} from "@fluentui/react-components";
|
|
858
|
+
import { ChevronDown12Regular, ChevronDown20Regular as ChevronDown20Regular2, ChevronUp20Regular } from "@fluentui/react-icons";
|
|
859
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
860
|
+
var H = ceForm.header;
|
|
861
|
+
var FIELD_TOP = 4;
|
|
862
|
+
var OWNER_AVATAR_TOP = 9;
|
|
863
|
+
var OWNER_NAME_GAP = 10;
|
|
864
|
+
var SUBTITLE_DOT_SPACING = 8;
|
|
865
|
+
var SUBTITLE_ROW_TOP = 0;
|
|
866
|
+
var EXPAND_GAP = 18;
|
|
867
|
+
var DIVIDER_TOP = 6;
|
|
868
|
+
var PRESENCE_RING = 2;
|
|
869
|
+
var PRESENCE_DOT = H.presenceSize - 2 * PRESENCE_RING;
|
|
870
|
+
var cePresenceBadgeStyle = Object.freeze({
|
|
871
|
+
width: PRESENCE_DOT,
|
|
872
|
+
height: PRESENCE_DOT,
|
|
873
|
+
boxSizing: "content-box",
|
|
874
|
+
// Fluent's badge carries 1px padding and a 10px icon; zero the padding and clip the icon to the dot.
|
|
875
|
+
padding: 0,
|
|
876
|
+
overflow: "hidden",
|
|
877
|
+
border: `${PRESENCE_RING}px solid ${tokens6.colorNeutralBackground1}`,
|
|
878
|
+
right: -PRESENCE_RING,
|
|
879
|
+
bottom: -PRESENCE_RING
|
|
880
|
+
});
|
|
881
|
+
var FIELDS_MIN_GAP = 16;
|
|
882
|
+
var CE_TITLE_MIN_WIDTH = 120;
|
|
883
|
+
var useStyles4 = makeStyles4({
|
|
884
|
+
// The owner name as a link-button: no chrome, but a VISIBLE keyboard focus ring (Fluent's).
|
|
885
|
+
ownerLink: {
|
|
886
|
+
background: "none",
|
|
887
|
+
border: "none",
|
|
888
|
+
padding: 0,
|
|
889
|
+
margin: 0,
|
|
890
|
+
font: "inherit",
|
|
891
|
+
color: tokens6.colorBrandForegroundLink,
|
|
892
|
+
cursor: "pointer",
|
|
893
|
+
":hover": { color: tokens6.colorBrandForegroundLinkHover, textDecorationLine: "underline" },
|
|
894
|
+
...createFocusOutlineStyle()
|
|
895
|
+
},
|
|
896
|
+
// Narrow headers: the title keeps a minimum width (it truncates with an ellipsis) and the fields
|
|
897
|
+
// block shrinks and clips rather than pushing past the card. Dynamics moves the fields into the
|
|
898
|
+
// header flyout at narrow widths (unmeasured, not modelled).
|
|
899
|
+
fields: {
|
|
900
|
+
display: "flex",
|
|
901
|
+
alignItems: "flex-start",
|
|
902
|
+
flexShrink: 1,
|
|
903
|
+
minWidth: 0,
|
|
904
|
+
overflow: "hidden"
|
|
905
|
+
},
|
|
906
|
+
switcher: {
|
|
907
|
+
display: "inline-flex",
|
|
908
|
+
alignItems: "center",
|
|
909
|
+
// Measured switcher 74.3 wide for "Account" (52.3): 2×2 padding + 2×1 border + 4 gap + 12 icon.
|
|
910
|
+
gap: "4px",
|
|
911
|
+
height: `${H.switcherHeight}px`,
|
|
912
|
+
padding: `0 ${H.switcherPaddingX}px`,
|
|
913
|
+
border: "1px solid transparent",
|
|
914
|
+
borderRadius: tokens6.borderRadiusMedium,
|
|
915
|
+
background: "transparent",
|
|
916
|
+
color: tokens6.colorNeutralForeground2,
|
|
917
|
+
fontFamily: "inherit",
|
|
918
|
+
fontSize: tokens6.fontSizeBase300,
|
|
919
|
+
fontWeight: tokens6.fontWeightSemibold,
|
|
920
|
+
lineHeight: tokens6.lineHeightBase300,
|
|
921
|
+
cursor: "pointer",
|
|
922
|
+
":hover": { backgroundColor: tokens6.colorSubtleBackgroundHover },
|
|
923
|
+
...createFocusOutlineStyle(),
|
|
924
|
+
// Measured OPEN: fill #e0e0e0 = colorSubtleBackgroundPressed (Fluent's MenuButton would use
|
|
925
|
+
// Selected, #ebebeb — so this is set explicitly) and text #242424 = colorNeutralForeground1
|
|
926
|
+
// (idle is #424242). ★ The open state must also win over :hover — the pointer is still on the
|
|
927
|
+
// trigger after the click that opened it, and hover's #f5f5f5 was what showed. The ce-parity
|
|
928
|
+
// gate checks the open trigger with the pointer on it AND away from it.
|
|
929
|
+
'&[aria-expanded="true"], &[aria-expanded="true"]:hover': {
|
|
930
|
+
backgroundColor: tokens6.colorSubtleBackgroundPressed,
|
|
931
|
+
color: tokens6.colorNeutralForeground1
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
var isEmpty = (v) => v === null || v === void 0 || v === "";
|
|
936
|
+
function FieldTile({ field }) {
|
|
937
|
+
return /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", paddingTop: FIELD_TOP, minWidth: 0 }, "data-surface-part": "header-field", children: [
|
|
938
|
+
/* @__PURE__ */ jsx7(Text2, { weight: "semibold", size: 300, wrap: false, style: { color: tokens6.colorNeutralForeground1 }, "data-surface-part": "header-field-value", children: isEmpty(field.value) ? "---" : field.value }),
|
|
939
|
+
/* @__PURE__ */ jsx7(Text2, { size: 200, wrap: false, style: { color: tokens6.colorNeutralForeground1 }, "data-surface-part": "header-field-label", children: field.label })
|
|
940
|
+
] });
|
|
941
|
+
}
|
|
942
|
+
function Divider() {
|
|
943
|
+
return /* @__PURE__ */ jsx7(
|
|
944
|
+
"div",
|
|
945
|
+
{
|
|
946
|
+
"aria-hidden": "true",
|
|
947
|
+
style: {
|
|
948
|
+
width: H.dividerWidth,
|
|
949
|
+
height: H.dividerHeight,
|
|
950
|
+
margin: `${DIVIDER_TOP}px ${H.dividerSpacing}px 0`,
|
|
951
|
+
backgroundColor: tokens6.colorNeutralStroke2,
|
|
952
|
+
flexShrink: 0
|
|
953
|
+
},
|
|
954
|
+
"data-surface-part": "header-divider"
|
|
955
|
+
}
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
function CeFormHeader(props) {
|
|
959
|
+
const {
|
|
960
|
+
title,
|
|
961
|
+
subtitle,
|
|
962
|
+
status,
|
|
963
|
+
titleColor,
|
|
964
|
+
persona,
|
|
965
|
+
actions,
|
|
966
|
+
className,
|
|
967
|
+
entityName,
|
|
968
|
+
forms,
|
|
969
|
+
activeFormId,
|
|
970
|
+
onFormChange,
|
|
971
|
+
headerFields,
|
|
972
|
+
owner,
|
|
973
|
+
onExpand,
|
|
974
|
+
expanded,
|
|
975
|
+
titleAs
|
|
976
|
+
} = props;
|
|
977
|
+
const styles = useStyles4();
|
|
978
|
+
const activeForm = forms?.find((f) => f.id === activeFormId) ?? forms?.[0];
|
|
979
|
+
const entity = entityName ?? subtitle;
|
|
980
|
+
const avatar = persona ?? (typeof title === "string" ? /* @__PURE__ */ jsx7(Avatar, { name: title, color: "colorful", size: H.avatarSize, "aria-hidden": true }) : null);
|
|
981
|
+
const TitleTag = titleAs ?? "h1";
|
|
982
|
+
return /* @__PURE__ */ jsxs4(
|
|
983
|
+
"div",
|
|
984
|
+
{
|
|
985
|
+
className,
|
|
986
|
+
style: { display: "flex", alignItems: "flex-start", padding: H.padding.map((v) => `${v}px`).join(" "), minWidth: 0 },
|
|
987
|
+
"data-surface-part": "form-header",
|
|
988
|
+
"data-look": "ce",
|
|
989
|
+
children: [
|
|
990
|
+
avatar && // The avatar sits in a 2px transparent ring (tile 44 = 40 + 2 × 2), 14px before the title.
|
|
991
|
+
/* @__PURE__ */ jsx7("div", { style: { padding: H.avatarRing, marginRight: H.avatarToTitleGap, flexShrink: 0 }, "data-surface-part": "header-avatar", children: avatar }),
|
|
992
|
+
/* @__PURE__ */ jsxs4("div", { style: { minWidth: CE_TITLE_MIN_WIDTH, flex: "1 1 auto" }, children: [
|
|
993
|
+
/* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "baseline", minWidth: 0 }, children: [
|
|
994
|
+
title != null && /* @__PURE__ */ jsx7(
|
|
995
|
+
Text2,
|
|
996
|
+
{
|
|
997
|
+
as: TitleTag,
|
|
998
|
+
weight: "semibold",
|
|
999
|
+
size: 500,
|
|
1000
|
+
truncate: true,
|
|
1001
|
+
wrap: false,
|
|
1002
|
+
style: { margin: 0, lineHeight: `${H.titleLineHeight}px`, color: titleColor ?? tokens6.colorNeutralForeground1 },
|
|
1003
|
+
"data-surface-part": "header-title",
|
|
1004
|
+
children: title
|
|
1005
|
+
}
|
|
1006
|
+
),
|
|
1007
|
+
status != null && /* @__PURE__ */ jsxs4(
|
|
1008
|
+
"span",
|
|
1009
|
+
{
|
|
1010
|
+
style: {
|
|
1011
|
+
paddingLeft: H.statusPaddingLeft,
|
|
1012
|
+
fontSize: tokens6.fontSizeBase300,
|
|
1013
|
+
lineHeight: `${H.titleLineHeight}px`,
|
|
1014
|
+
color: tokens6.colorNeutralForeground3,
|
|
1015
|
+
whiteSpace: "nowrap"
|
|
1016
|
+
},
|
|
1017
|
+
"data-surface-part": "header-status",
|
|
1018
|
+
children: [
|
|
1019
|
+
"- ",
|
|
1020
|
+
status
|
|
1021
|
+
]
|
|
1022
|
+
}
|
|
1023
|
+
)
|
|
1024
|
+
] }),
|
|
1025
|
+
(entity != null || activeForm) && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "center", height: H.switcherHeight, marginTop: SUBTITLE_ROW_TOP }, "data-surface-part": "header-subtitle", children: [
|
|
1026
|
+
entity != null && /* @__PURE__ */ jsx7("span", { style: { fontSize: tokens6.fontSizeBase300, fontWeight: tokens6.fontWeightSemibold, color: tokens6.colorNeutralForeground2 }, children: entity }),
|
|
1027
|
+
entity != null && activeForm && /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", style: { margin: `0 ${SUBTITLE_DOT_SPACING}px`, color: tokens6.colorNeutralForeground2, lineHeight: "20px" }, children: "\xB7" }),
|
|
1028
|
+
activeForm && (forms && forms.length > 1 ? /* @__PURE__ */ jsxs4(
|
|
1029
|
+
Menu,
|
|
1030
|
+
{
|
|
1031
|
+
checkedValues: { form: [activeForm.id] },
|
|
1032
|
+
onCheckedValueChange: (_e, data) => {
|
|
1033
|
+
const id = data.checkedItems[0];
|
|
1034
|
+
if (id && id !== activeForm.id) onFormChange?.(id);
|
|
1035
|
+
},
|
|
1036
|
+
children: [
|
|
1037
|
+
/* @__PURE__ */ jsx7(MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxs4("button", { type: "button", className: styles.switcher, "aria-label": `Form: ${activeForm.label}`, "data-surface-part": "form-switcher", children: [
|
|
1038
|
+
activeForm.label,
|
|
1039
|
+
/* @__PURE__ */ jsx7(ChevronDown12Regular, {})
|
|
1040
|
+
] }) }),
|
|
1041
|
+
/* @__PURE__ */ jsx7(MenuPopover, { children: /* @__PURE__ */ jsx7(MenuList, { children: forms.map((f) => /* @__PURE__ */ jsx7(MenuItemRadio, { name: "form", value: f.id, children: f.label }, f.id)) }) })
|
|
1042
|
+
]
|
|
1043
|
+
}
|
|
1044
|
+
) : /* @__PURE__ */ jsx7("span", { style: { fontSize: tokens6.fontSizeBase300, fontWeight: tokens6.fontWeightSemibold, color: tokens6.colorNeutralForeground2 }, children: activeForm.label }))
|
|
1045
|
+
] })
|
|
1046
|
+
] }),
|
|
1047
|
+
(headerFields?.length || owner || actions) && /* @__PURE__ */ jsxs4("div", { className: styles.fields, style: { marginLeft: FIELDS_MIN_GAP }, "data-surface-part": "header-fields", children: [
|
|
1048
|
+
headerFields?.map((f, i) => /* @__PURE__ */ jsxs4(React2.Fragment, { children: [
|
|
1049
|
+
i > 0 && /* @__PURE__ */ jsx7(Divider, {}),
|
|
1050
|
+
/* @__PURE__ */ jsx7(FieldTile, { field: f })
|
|
1051
|
+
] }, f.id ?? `${f.label}-${i}`)),
|
|
1052
|
+
owner && /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1053
|
+
headerFields?.length ? /* @__PURE__ */ jsx7(Divider, {}) : null,
|
|
1054
|
+
/* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "flex-start" }, "data-surface-part": "header-owner", children: [
|
|
1055
|
+
/* @__PURE__ */ jsx7("div", { style: { paddingTop: OWNER_AVATAR_TOP, marginRight: OWNER_NAME_GAP }, children: owner.avatar ?? /* @__PURE__ */ jsx7(
|
|
1056
|
+
Avatar,
|
|
1057
|
+
{
|
|
1058
|
+
name: owner.name,
|
|
1059
|
+
color: "colorful",
|
|
1060
|
+
size: H.ownerAvatarSize,
|
|
1061
|
+
badge: owner.presence ? { status: owner.presence, size: "extra-small", style: cePresenceBadgeStyle } : void 0
|
|
1062
|
+
}
|
|
1063
|
+
) }),
|
|
1064
|
+
/* @__PURE__ */ jsx7(
|
|
1065
|
+
FieldTile,
|
|
1066
|
+
{
|
|
1067
|
+
field: {
|
|
1068
|
+
label: owner.label ?? "Owner",
|
|
1069
|
+
value: owner.onClick ? /* @__PURE__ */ jsx7("button", { type: "button", onClick: owner.onClick, className: styles.ownerLink, "data-surface-part": "header-owner-link", children: owner.name }) : /* @__PURE__ */ jsx7("span", { style: { color: tokens6.colorBrandForegroundLink }, children: owner.name })
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
)
|
|
1073
|
+
] })
|
|
1074
|
+
] }),
|
|
1075
|
+
actions != null && /* @__PURE__ */ jsx7("div", { children: actions })
|
|
1076
|
+
] }),
|
|
1077
|
+
onExpand && /* @__PURE__ */ jsx7(
|
|
1078
|
+
Button2,
|
|
1079
|
+
{
|
|
1080
|
+
appearance: "subtle",
|
|
1081
|
+
icon: expanded ? /* @__PURE__ */ jsx7(ChevronUp20Regular, {}) : /* @__PURE__ */ jsx7(ChevronDown20Regular2, {}),
|
|
1082
|
+
"aria-label": expanded ? "Collapse header" : "Expand header",
|
|
1083
|
+
"aria-expanded": !!expanded,
|
|
1084
|
+
onClick: onExpand,
|
|
1085
|
+
style: { marginLeft: EXPAND_GAP, flexShrink: 0, minWidth: H.expandButtonSize, width: H.expandButtonSize, height: H.expandButtonSize },
|
|
1086
|
+
"data-surface-part": "header-expand"
|
|
1087
|
+
}
|
|
1088
|
+
)
|
|
1089
|
+
]
|
|
1090
|
+
}
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
var FormHeader = (props) => {
|
|
1094
|
+
const ambientLook = useLook();
|
|
1095
|
+
if ((props.look ?? ambientLook) === "ce") return /* @__PURE__ */ jsx7(CeFormHeader, { ...props });
|
|
1096
|
+
const { title, subtitle, status, titleColor, subtitleColor, persona, actions, className } = props;
|
|
501
1097
|
const rootStyle = {
|
|
502
1098
|
display: "flex",
|
|
503
1099
|
alignItems: "center",
|
|
504
1100
|
justifyContent: "space-between",
|
|
505
1101
|
gap: 12,
|
|
506
1102
|
padding: "12px 24px",
|
|
507
|
-
borderBottom: `1px solid ${
|
|
508
|
-
backgroundColor:
|
|
1103
|
+
borderBottom: `1px solid ${tokens6.colorNeutralStroke2}`,
|
|
1104
|
+
backgroundColor: tokens6.colorNeutralBackground1
|
|
509
1105
|
};
|
|
510
1106
|
const mainStyle = { display: "flex", alignItems: "center", gap: 12, minWidth: 0 };
|
|
511
1107
|
const titleRowStyle = { display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap" };
|
|
512
|
-
const statusStyle = { fontSize:
|
|
1108
|
+
const statusStyle = { fontSize: tokens6.fontSizeBase200, color: tokens6.colorNeutralForeground3 };
|
|
513
1109
|
const subtitleStyle = {
|
|
514
|
-
fontSize:
|
|
515
|
-
color: subtitleColor ||
|
|
1110
|
+
fontSize: tokens6.fontSizeBase200,
|
|
1111
|
+
color: subtitleColor || tokens6.colorNeutralForeground3,
|
|
516
1112
|
marginTop: 2
|
|
517
1113
|
};
|
|
518
|
-
return /* @__PURE__ */
|
|
519
|
-
/* @__PURE__ */
|
|
1114
|
+
return /* @__PURE__ */ jsxs4("div", { className, style: rootStyle, children: [
|
|
1115
|
+
/* @__PURE__ */ jsxs4("div", { style: mainStyle, children: [
|
|
520
1116
|
persona,
|
|
521
|
-
/* @__PURE__ */
|
|
522
|
-
/* @__PURE__ */
|
|
523
|
-
title != null && /* @__PURE__ */
|
|
524
|
-
status != null && /* @__PURE__ */
|
|
1117
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1118
|
+
/* @__PURE__ */ jsxs4("div", { style: titleRowStyle, children: [
|
|
1119
|
+
title != null && /* @__PURE__ */ jsx7(Text2, { weight: "semibold", size: 400, style: titleColor ? { color: titleColor } : void 0, children: title }),
|
|
1120
|
+
status != null && /* @__PURE__ */ jsx7("span", { style: statusStyle, children: status })
|
|
525
1121
|
] }),
|
|
526
|
-
subtitle != null && /* @__PURE__ */
|
|
1122
|
+
subtitle != null && /* @__PURE__ */ jsx7("div", { style: subtitleStyle, children: subtitle })
|
|
527
1123
|
] })
|
|
528
1124
|
] }),
|
|
529
|
-
actions != null && /* @__PURE__ */
|
|
1125
|
+
actions != null && /* @__PURE__ */ jsx7("div", { children: actions })
|
|
530
1126
|
] });
|
|
531
1127
|
};
|
|
532
1128
|
|
|
533
1129
|
// src/v9/containers/PivotSurface.tsx
|
|
534
|
-
import { useState as useState4 } from "react";
|
|
535
|
-
import {
|
|
536
|
-
|
|
1130
|
+
import { useId, useState as useState4 } from "react";
|
|
1131
|
+
import {
|
|
1132
|
+
TabList,
|
|
1133
|
+
Tab,
|
|
1134
|
+
makeStyles as makeStyles5,
|
|
1135
|
+
tabClassNames,
|
|
1136
|
+
tokens as tokens7
|
|
1137
|
+
} from "@fluentui/react-components";
|
|
1138
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1139
|
+
var FLUENT_TAB_RESERVED_SPACE_CLASS = "fui-Tab__content--reserved-space";
|
|
1140
|
+
var T = ceForm.tabs;
|
|
1141
|
+
var UNDERLINE_BOTTOM = 5;
|
|
1142
|
+
var useStyles5 = makeStyles5({
|
|
1143
|
+
ceCard: {
|
|
1144
|
+
minWidth: 0,
|
|
1145
|
+
backgroundColor: tokens7.colorNeutralBackground1,
|
|
1146
|
+
border: "1px solid transparent",
|
|
1147
|
+
borderRadius: tokens7.borderRadiusXLarge,
|
|
1148
|
+
boxShadow: tokens7.shadow4
|
|
1149
|
+
},
|
|
1150
|
+
ceStrip: {
|
|
1151
|
+
padding: T.stripPadding.map((v) => `${v}px`).join(" "),
|
|
1152
|
+
columnGap: `${T.gap}px`,
|
|
1153
|
+
// PROVISIONAL: tabs that don't fit are clipped. Dynamics folds them into a "Related ▾" /
|
|
1154
|
+
// overflow menu, which is unmeasured and not modelled.
|
|
1155
|
+
overflow: "hidden"
|
|
1156
|
+
},
|
|
1157
|
+
ceTab: {
|
|
1158
|
+
height: `${T.tabHeight}px`,
|
|
1159
|
+
padding: `0 0 ${UNDERLINE_BOTTOM}px`,
|
|
1160
|
+
alignItems: "flex-end",
|
|
1161
|
+
fontSize: `${T.fontSize}px`,
|
|
1162
|
+
lineHeight: `${T.lineHeight}px`,
|
|
1163
|
+
color: tokens7.colorNeutralForeground1,
|
|
1164
|
+
[`& .${tabClassNames.content}`]: {
|
|
1165
|
+
padding: 0,
|
|
1166
|
+
fontSize: `${T.fontSize}px`,
|
|
1167
|
+
lineHeight: `${T.lineHeight}px`,
|
|
1168
|
+
// Idle labels are the measured #242424 too (Fluent's transparent appearance would use
|
|
1169
|
+
// foreground2, #424242).
|
|
1170
|
+
color: tokens7.colorNeutralForeground1
|
|
1171
|
+
},
|
|
1172
|
+
// Dynamics, like Fluent, reserves each tab's SEMIBOLD width (a hidden zero-height copy of the
|
|
1173
|
+
// label), so tabs don't shift on selection: an unselected "Web API Probe" is 109.6 wide, its
|
|
1174
|
+
// semibold width in the same Segoe UI Web file. Fluent's reserved copy keeps its own 2px side
|
|
1175
|
+
// padding, which made it 113.6 — zero it like the visible content.
|
|
1176
|
+
[`& .${FLUENT_TAB_RESERVED_SPACE_CLASS}`]: {
|
|
1177
|
+
padding: 0,
|
|
1178
|
+
fontSize: `${T.fontSize}px`
|
|
1179
|
+
},
|
|
1180
|
+
// Fluent draws the selected (and hover) indicator on ::after / ::before; move both to the
|
|
1181
|
+
// measured position and shape.
|
|
1182
|
+
"::after": {
|
|
1183
|
+
left: 0,
|
|
1184
|
+
right: 0,
|
|
1185
|
+
bottom: `${UNDERLINE_BOTTOM}px`,
|
|
1186
|
+
height: `${T.underlineHeight}px`,
|
|
1187
|
+
borderRadius: `${T.underlineRadius}px`
|
|
1188
|
+
},
|
|
1189
|
+
"::before": {
|
|
1190
|
+
left: 0,
|
|
1191
|
+
right: 0,
|
|
1192
|
+
bottom: `${UNDERLINE_BOTTOM}px`,
|
|
1193
|
+
height: `${T.underlineHeight}px`,
|
|
1194
|
+
borderRadius: `${T.underlineRadius}px`
|
|
1195
|
+
},
|
|
1196
|
+
// Fluent's hover/pressed indicator sets a circular radius at higher specificity; match it.
|
|
1197
|
+
":hover::before": { borderRadius: `${T.underlineRadius}px` },
|
|
1198
|
+
":active::before": { borderRadius: `${T.underlineRadius}px` }
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
537
1201
|
var PivotSurface = ({
|
|
538
1202
|
tabs,
|
|
539
1203
|
selectedId,
|
|
@@ -541,8 +1205,15 @@ var PivotSurface = ({
|
|
|
541
1205
|
onTabChange,
|
|
542
1206
|
appearance = "transparent",
|
|
543
1207
|
size = "medium",
|
|
544
|
-
className
|
|
1208
|
+
className,
|
|
1209
|
+
look: lookProp,
|
|
1210
|
+
header
|
|
545
1211
|
}) => {
|
|
1212
|
+
const styles = useStyles5();
|
|
1213
|
+
const ce = lookProp === "ce";
|
|
1214
|
+
const baseId = useId();
|
|
1215
|
+
const tabId = (id) => `${baseId}-tab-${id}`;
|
|
1216
|
+
const panelId = `${baseId}-panel`;
|
|
546
1217
|
const firstEnabledId = tabs.find((t) => !t.disabled)?.id ?? tabs[0]?.id;
|
|
547
1218
|
const [internal, setInternal] = useState4(defaultSelectedId ?? firstEnabledId);
|
|
548
1219
|
const selected = selectedId ?? internal;
|
|
@@ -552,66 +1223,432 @@ var PivotSurface = ({
|
|
|
552
1223
|
onTabChange?.(id);
|
|
553
1224
|
};
|
|
554
1225
|
const active = tabs.find((t) => t.id === selected) ?? tabs[0];
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
/* @__PURE__ */
|
|
1226
|
+
if (ce) {
|
|
1227
|
+
const [bodyTop, , bodyBottom] = ceForm.tabBody.padding;
|
|
1228
|
+
return /* @__PURE__ */ jsxs5(
|
|
1229
|
+
"div",
|
|
1230
|
+
{
|
|
1231
|
+
className,
|
|
1232
|
+
style: { padding: `0 ${ceForm.page.insetRight}px 0 ${ceForm.page.insetLeft}px`, minWidth: 0 },
|
|
1233
|
+
"data-surface-part": "pivot",
|
|
1234
|
+
"data-look": "ce",
|
|
1235
|
+
children: [
|
|
1236
|
+
/* @__PURE__ */ jsxs5("div", { className: styles.ceCard, "data-surface-part": "header-card", children: [
|
|
1237
|
+
header,
|
|
1238
|
+
/* @__PURE__ */ jsx8(
|
|
1239
|
+
TabList,
|
|
1240
|
+
{
|
|
1241
|
+
className: styles.ceStrip,
|
|
1242
|
+
selectedValue: selected,
|
|
1243
|
+
onTabSelect: handleSelect,
|
|
1244
|
+
appearance: "transparent",
|
|
1245
|
+
size: "large",
|
|
1246
|
+
"data-surface-part": "tab-strip",
|
|
1247
|
+
children: tabs.map((t) => /* @__PURE__ */ jsx8(
|
|
1248
|
+
Tab,
|
|
1249
|
+
{
|
|
1250
|
+
value: t.id,
|
|
1251
|
+
icon: t.icon,
|
|
1252
|
+
disabled: t.disabled,
|
|
1253
|
+
className: styles.ceTab,
|
|
1254
|
+
id: tabId(t.id),
|
|
1255
|
+
"aria-controls": t.id === active?.id ? panelId : void 0,
|
|
1256
|
+
children: t.label
|
|
1257
|
+
},
|
|
1258
|
+
t.id
|
|
1259
|
+
))
|
|
1260
|
+
}
|
|
1261
|
+
)
|
|
1262
|
+
] }),
|
|
1263
|
+
/* @__PURE__ */ jsx8(
|
|
1264
|
+
"div",
|
|
1265
|
+
{
|
|
1266
|
+
role: "tabpanel",
|
|
1267
|
+
id: panelId,
|
|
1268
|
+
"aria-labelledby": active ? tabId(active.id) : void 0,
|
|
1269
|
+
style: { paddingTop: bodyTop, paddingBottom: bodyBottom },
|
|
1270
|
+
"data-surface-part": "tab-body",
|
|
1271
|
+
children: active?.content
|
|
1272
|
+
}
|
|
1273
|
+
)
|
|
1274
|
+
]
|
|
1275
|
+
}
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
return /* @__PURE__ */ jsxs5("div", { className, children: [
|
|
1279
|
+
header,
|
|
1280
|
+
/* @__PURE__ */ jsx8(TabList, { selectedValue: selected, onTabSelect: handleSelect, appearance, size, children: tabs.map((t) => /* @__PURE__ */ jsx8(
|
|
1281
|
+
Tab,
|
|
1282
|
+
{
|
|
1283
|
+
value: t.id,
|
|
1284
|
+
icon: t.icon,
|
|
1285
|
+
disabled: t.disabled,
|
|
1286
|
+
id: tabId(t.id),
|
|
1287
|
+
"aria-controls": t.id === active?.id ? panelId : void 0,
|
|
1288
|
+
children: t.label
|
|
1289
|
+
},
|
|
1290
|
+
t.id
|
|
1291
|
+
)) }),
|
|
1292
|
+
/* @__PURE__ */ jsx8("div", { role: "tabpanel", id: panelId, "aria-labelledby": active ? tabId(active.id) : void 0, "data-surface-part": "tab-body", children: active?.content })
|
|
558
1293
|
] });
|
|
559
1294
|
};
|
|
560
1295
|
|
|
561
1296
|
// src/v9/containers/CommandSurface.tsx
|
|
1297
|
+
import React4 from "react";
|
|
562
1298
|
import {
|
|
1299
|
+
Button as Button3,
|
|
563
1300
|
Toolbar as Toolbar2,
|
|
564
1301
|
ToolbarButton as ToolbarButton2,
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
1302
|
+
ToolbarDivider,
|
|
1303
|
+
Menu as Menu2,
|
|
1304
|
+
MenuTrigger as MenuTrigger2,
|
|
1305
|
+
MenuPopover as MenuPopover2,
|
|
1306
|
+
MenuList as MenuList2,
|
|
1307
|
+
MenuItem,
|
|
1308
|
+
buttonClassNames,
|
|
1309
|
+
makeStyles as makeStyles6,
|
|
1310
|
+
mergeClasses as mergeClasses4,
|
|
1311
|
+
tokens as tokens8
|
|
570
1312
|
} from "@fluentui/react-components";
|
|
571
|
-
import {
|
|
572
|
-
|
|
1313
|
+
import {
|
|
1314
|
+
ArrowLeft20Regular,
|
|
1315
|
+
ChevronDown12Regular as ChevronDown12Regular2,
|
|
1316
|
+
ChevronDown16Regular,
|
|
1317
|
+
MoreHorizontal20Regular,
|
|
1318
|
+
MoreVertical16Regular,
|
|
1319
|
+
WindowNew20Regular
|
|
1320
|
+
} from "@fluentui/react-icons";
|
|
1321
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1322
|
+
function ItemMenu({ items, trigger }) {
|
|
1323
|
+
return /* @__PURE__ */ jsxs6(Menu2, { children: [
|
|
1324
|
+
/* @__PURE__ */ jsx9(MenuTrigger2, { disableButtonEnhancement: true, children: trigger }),
|
|
1325
|
+
/* @__PURE__ */ jsx9(MenuPopover2, { children: /* @__PURE__ */ jsx9(MenuList2, { children: items.map((m) => /* @__PURE__ */ jsx9(MenuItem, { icon: m.icon, disabled: m.disabled, onClick: m.onClick, children: m.label }, m.id)) }) })
|
|
1326
|
+
] });
|
|
1327
|
+
}
|
|
573
1328
|
function renderToolbarButton(item) {
|
|
574
|
-
|
|
1329
|
+
const button = /* @__PURE__ */ jsx9(
|
|
575
1330
|
ToolbarButton2,
|
|
576
1331
|
{
|
|
577
1332
|
icon: item.icon,
|
|
578
1333
|
appearance: item.appearance === "primary" ? "primary" : "subtle",
|
|
579
1334
|
disabled: item.disabled,
|
|
580
|
-
onClick: item.onClick,
|
|
1335
|
+
onClick: item.menuItems?.length ? void 0 : item.onClick,
|
|
581
1336
|
children: item.label
|
|
582
1337
|
},
|
|
583
1338
|
item.id
|
|
584
1339
|
);
|
|
1340
|
+
if (!item.menuItems?.length) return button;
|
|
1341
|
+
if (!item.split) return /* @__PURE__ */ jsx9(ItemMenu, { items: item.menuItems, trigger: button }, item.id);
|
|
1342
|
+
return /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
|
|
1343
|
+
React4.cloneElement(button, { onClick: item.onClick }),
|
|
1344
|
+
/* @__PURE__ */ jsx9(
|
|
1345
|
+
ItemMenu,
|
|
1346
|
+
{
|
|
1347
|
+
items: item.menuItems,
|
|
1348
|
+
trigger: /* @__PURE__ */ jsx9(
|
|
1349
|
+
ToolbarButton2,
|
|
1350
|
+
{
|
|
1351
|
+
appearance: "subtle",
|
|
1352
|
+
"aria-label": `More ${item.label} options`,
|
|
1353
|
+
icon: /* @__PURE__ */ jsx9(ChevronDown16Regular, {}),
|
|
1354
|
+
disabled: item.disabled
|
|
1355
|
+
}
|
|
1356
|
+
)
|
|
1357
|
+
}
|
|
1358
|
+
)
|
|
1359
|
+
] }, item.id);
|
|
585
1360
|
}
|
|
586
|
-
var
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
1361
|
+
var CB = ceForm.commandBar;
|
|
1362
|
+
var FLUENT_BORDER = 1;
|
|
1363
|
+
var FOCUS_ROOM = 2;
|
|
1364
|
+
var useStyles6 = makeStyles6({
|
|
1365
|
+
root: {
|
|
1366
|
+
minWidth: 0,
|
|
1367
|
+
// Page insets (16 left / 20 right), 8px from the top, 16px gap to the header card. A class
|
|
1368
|
+
// (not an inline style) so a host's className can override it.
|
|
1369
|
+
padding: `${CB.marginTop}px ${ceForm.page.insetRight}px ${ceForm.header.marginTop}px ${ceForm.page.commandBarInsetLeft}px`
|
|
1370
|
+
},
|
|
1371
|
+
card: {
|
|
1372
|
+
display: "flex",
|
|
1373
|
+
alignItems: "center",
|
|
1374
|
+
minWidth: 0,
|
|
1375
|
+
boxSizing: "border-box",
|
|
1376
|
+
height: `${CB.cardHeight}px`,
|
|
1377
|
+
backgroundColor: tokens8.colorNeutralBackground1,
|
|
1378
|
+
border: "1px solid transparent",
|
|
1379
|
+
borderRadius: tokens8.borderRadiusXLarge,
|
|
1380
|
+
boxShadow: tokens8.shadow4
|
|
1381
|
+
},
|
|
1382
|
+
group: { display: "flex", alignItems: "center", flexShrink: 0 },
|
|
1383
|
+
nav: { marginLeft: `${CB.navInsetLeft}px` },
|
|
1384
|
+
navButton: {
|
|
1385
|
+
height: `${CB.buttonHeight}px`,
|
|
1386
|
+
minWidth: 0,
|
|
1387
|
+
// Fluent caps icon-only buttons at 32px; the measured back/pop-out/overflow are wider.
|
|
1388
|
+
maxWidth: "none",
|
|
1389
|
+
padding: 0,
|
|
1390
|
+
flexShrink: 0
|
|
1391
|
+
},
|
|
1392
|
+
divider: {
|
|
1393
|
+
flexGrow: 0,
|
|
1394
|
+
height: `${CB.dividerHeight}px`,
|
|
1395
|
+
padding: 0,
|
|
1396
|
+
// Measured line colour #d1d1d1 = colorNeutralStroke1 (ToolbarDivider has no `appearance`
|
|
1397
|
+
// prop, so the Divider's pseudo-element halves are recoloured; both sides, for RTL).
|
|
1398
|
+
"::before": { borderRightColor: tokens8.colorNeutralStroke1, borderLeftColor: tokens8.colorNeutralStroke1 },
|
|
1399
|
+
"::after": { borderRightColor: tokens8.colorNeutralStroke1, borderLeftColor: tokens8.colorNeutralStroke1 }
|
|
1400
|
+
},
|
|
1401
|
+
splitDivider: { height: `${CB.splitDividerHeight}px` },
|
|
1402
|
+
commands: {
|
|
1403
|
+
flex: "1 1 auto",
|
|
1404
|
+
minWidth: 0,
|
|
1405
|
+
columnGap: 0,
|
|
1406
|
+
// Commands past the edge are clipped (Dynamics folds them into ⋮ by an unmeasured rule — pass
|
|
1407
|
+
// overflowItems). The FOCUS_ROOM padding/negative margin keeps forced-colors outlines visible.
|
|
1408
|
+
overflow: "hidden",
|
|
1409
|
+
padding: `${FOCUS_ROOM}px ${CB.commandsPaddingRight}px ${FOCUS_ROOM}px ${FOCUS_ROOM}px`,
|
|
1410
|
+
margin: `-${FOCUS_ROOM}px 0 -${FOCUS_ROOM}px -${FOCUS_ROOM}px`
|
|
1411
|
+
},
|
|
1412
|
+
command: {
|
|
1413
|
+
height: `${CB.buttonHeight}px`,
|
|
1414
|
+
minWidth: 0,
|
|
1415
|
+
flexShrink: 0,
|
|
1416
|
+
padding: `1px ${CB.buttonPaddingX - FLUENT_BORDER}px`,
|
|
1417
|
+
fontSize: tokens8.fontSizeBase300,
|
|
1418
|
+
fontWeight: tokens8.fontWeightRegular,
|
|
1419
|
+
lineHeight: "21px",
|
|
1420
|
+
[`& .${buttonClassNames.icon}`]: {
|
|
1421
|
+
width: `${CB.iconSize}px`,
|
|
1422
|
+
height: `${CB.iconSize}px`,
|
|
1423
|
+
fontSize: `${CB.iconSize}px`,
|
|
1424
|
+
marginRight: `${CB.iconGap}px`
|
|
1425
|
+
}
|
|
1426
|
+
},
|
|
1427
|
+
// Measured colours — NOT applied to primary commands, whose on-brand colours Fluent owns.
|
|
1428
|
+
commandColors: {
|
|
1429
|
+
color: tokens8.colorNeutralForeground1,
|
|
1430
|
+
[`& .${buttonClassNames.icon}`]: { color: tokens8.colorNeutralForeground2 }
|
|
1431
|
+
},
|
|
1432
|
+
menuCommand: { paddingRight: 0 },
|
|
1433
|
+
chevronZone: {
|
|
1434
|
+
display: "inline-flex",
|
|
1435
|
+
justifyContent: "center",
|
|
1436
|
+
alignItems: "center",
|
|
1437
|
+
width: `${CB.chevronZone - FLUENT_BORDER}px`,
|
|
1438
|
+
flexShrink: 0
|
|
1439
|
+
},
|
|
1440
|
+
splitMain: { marginRight: `${CB.splitGap}px` },
|
|
1441
|
+
iconOnly: {
|
|
1442
|
+
height: `${CB.buttonHeight}px`,
|
|
1443
|
+
minWidth: 0,
|
|
1444
|
+
maxWidth: "none",
|
|
1445
|
+
flexShrink: 0,
|
|
1446
|
+
padding: 0,
|
|
1447
|
+
color: tokens8.colorNeutralForeground1
|
|
1448
|
+
},
|
|
1449
|
+
far: { padding: `0 ${CB.farPadding}px` },
|
|
1450
|
+
farButton: {
|
|
1451
|
+
height: `${CB.shareHeight}px`,
|
|
1452
|
+
minWidth: 0,
|
|
1453
|
+
// Share's border is a real 1px #d1d1d1 border in Dynamics too (bl=1 alongside p=1,8).
|
|
1454
|
+
padding: `1px ${CB.sharePaddingX}px`,
|
|
1455
|
+
fontSize: `${CB.shareFontSize}px`,
|
|
1456
|
+
lineHeight: `${CB.shareLineHeight}px`,
|
|
1457
|
+
fontWeight: tokens8.fontWeightRegular,
|
|
1458
|
+
color: tokens8.colorNeutralForeground2,
|
|
1459
|
+
borderTopColor: tokens8.colorNeutralStroke1,
|
|
1460
|
+
borderRightColor: tokens8.colorNeutralStroke1,
|
|
1461
|
+
borderBottomColor: tokens8.colorNeutralStroke1,
|
|
1462
|
+
borderLeftColor: tokens8.colorNeutralStroke1,
|
|
1463
|
+
[`& .${buttonClassNames.icon}`]: {
|
|
1464
|
+
width: `${CB.shareIconSize}px`,
|
|
1465
|
+
height: `${CB.shareIconSize}px`,
|
|
1466
|
+
fontSize: `${CB.shareIconSize}px`,
|
|
1467
|
+
marginRight: "4px"
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
});
|
|
1471
|
+
function CeCommandSurface({ items, overflowItems, farItems, className, onBack, onPopOut }) {
|
|
1472
|
+
const styles = useStyles6();
|
|
1473
|
+
const measuredColors = (item) => item.appearance !== "primary";
|
|
1474
|
+
const commandClass = (item, ...extra) => mergeClasses4(styles.command, measuredColors(item) && styles.commandColors, ...extra);
|
|
1475
|
+
const commandPart = (item) => ({
|
|
1476
|
+
"data-surface-part": "command",
|
|
1477
|
+
"data-measured-colors": measuredColors(item) ? "true" : void 0
|
|
1478
|
+
});
|
|
1479
|
+
const appearanceOf = (item) => item.appearance === "primary" ? "primary" : "subtle";
|
|
1480
|
+
const command = (item) => {
|
|
1481
|
+
if (item.menuItems?.length && item.split) {
|
|
1482
|
+
return /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
|
|
1483
|
+
/* @__PURE__ */ jsx9(
|
|
1484
|
+
ToolbarButton2,
|
|
1485
|
+
{
|
|
1486
|
+
appearance: appearanceOf(item),
|
|
1487
|
+
icon: item.icon,
|
|
1488
|
+
disabled: item.disabled,
|
|
1489
|
+
onClick: item.onClick,
|
|
1490
|
+
className: commandClass(item, styles.splitMain),
|
|
1491
|
+
...commandPart(item),
|
|
1492
|
+
children: item.label
|
|
1493
|
+
}
|
|
1494
|
+
),
|
|
1495
|
+
/* @__PURE__ */ jsx9(ToolbarDivider, { className: mergeClasses4(styles.divider, styles.splitDivider) }),
|
|
1496
|
+
/* @__PURE__ */ jsx9(
|
|
1497
|
+
ItemMenu,
|
|
1498
|
+
{
|
|
1499
|
+
items: item.menuItems,
|
|
1500
|
+
trigger: /* @__PURE__ */ jsx9(
|
|
1501
|
+
ToolbarButton2,
|
|
1502
|
+
{
|
|
1503
|
+
appearance: "subtle",
|
|
1504
|
+
"aria-label": `More ${item.label} options`,
|
|
1505
|
+
icon: /* @__PURE__ */ jsx9(ChevronDown16Regular, {}),
|
|
1506
|
+
disabled: item.disabled,
|
|
1507
|
+
className: styles.iconOnly,
|
|
1508
|
+
style: { width: CB.chevronZone, marginRight: -CB.splitChevronOverhang },
|
|
1509
|
+
"data-surface-part": "command-split-chevron"
|
|
1510
|
+
}
|
|
1511
|
+
)
|
|
1512
|
+
}
|
|
1513
|
+
)
|
|
1514
|
+
] }, item.id);
|
|
1515
|
+
}
|
|
1516
|
+
if (item.menuItems?.length) {
|
|
1517
|
+
return /* @__PURE__ */ jsx9(
|
|
1518
|
+
ItemMenu,
|
|
1519
|
+
{
|
|
1520
|
+
items: item.menuItems,
|
|
1521
|
+
trigger: /* @__PURE__ */ jsxs6(
|
|
1522
|
+
ToolbarButton2,
|
|
1523
|
+
{
|
|
1524
|
+
appearance: appearanceOf(item),
|
|
1525
|
+
icon: item.icon,
|
|
1526
|
+
disabled: item.disabled,
|
|
1527
|
+
className: commandClass(item, styles.menuCommand),
|
|
1528
|
+
...commandPart(item),
|
|
1529
|
+
children: [
|
|
1530
|
+
item.label,
|
|
1531
|
+
/* @__PURE__ */ jsx9("span", { className: styles.chevronZone, "aria-hidden": "true", children: /* @__PURE__ */ jsx9(ChevronDown12Regular2, {}) })
|
|
1532
|
+
]
|
|
1533
|
+
}
|
|
1534
|
+
)
|
|
1535
|
+
},
|
|
1536
|
+
item.id
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
return /* @__PURE__ */ jsx9(
|
|
1540
|
+
ToolbarButton2,
|
|
1541
|
+
{
|
|
1542
|
+
appearance: appearanceOf(item),
|
|
1543
|
+
icon: item.icon,
|
|
1544
|
+
disabled: item.disabled,
|
|
1545
|
+
onClick: item.onClick,
|
|
1546
|
+
className: commandClass(item),
|
|
1547
|
+
...commandPart(item),
|
|
1548
|
+
children: item.label
|
|
1549
|
+
},
|
|
1550
|
+
item.id
|
|
1551
|
+
);
|
|
1552
|
+
};
|
|
1553
|
+
return /* @__PURE__ */ jsx9("div", { className: mergeClasses4(styles.root, className), "data-surface-part": "command-bar", "data-look": "ce", children: /* @__PURE__ */ jsxs6("div", { className: styles.card, "data-surface-part": "command-card", children: [
|
|
1554
|
+
(onBack || onPopOut) && /* @__PURE__ */ jsxs6("div", { role: "group", "aria-label": "Navigation", className: mergeClasses4(styles.group, styles.nav), "data-surface-part": "command-nav", children: [
|
|
1555
|
+
onBack && /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1556
|
+
/* @__PURE__ */ jsx9(
|
|
1557
|
+
Button3,
|
|
1558
|
+
{
|
|
1559
|
+
appearance: "subtle",
|
|
1560
|
+
icon: /* @__PURE__ */ jsx9(ArrowLeft20Regular, {}),
|
|
1561
|
+
"aria-label": "Back",
|
|
1562
|
+
onClick: onBack,
|
|
1563
|
+
className: styles.navButton,
|
|
1564
|
+
style: { width: CB.backWidth },
|
|
1565
|
+
"data-surface-part": "command-back"
|
|
1566
|
+
}
|
|
1567
|
+
),
|
|
1568
|
+
/* @__PURE__ */ jsx9(ToolbarDivider, { className: styles.divider })
|
|
1569
|
+
] }),
|
|
1570
|
+
onPopOut && /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1571
|
+
/* @__PURE__ */ jsx9(
|
|
1572
|
+
Button3,
|
|
1573
|
+
{
|
|
1574
|
+
appearance: "subtle",
|
|
1575
|
+
icon: /* @__PURE__ */ jsx9(WindowNew20Regular, {}),
|
|
1576
|
+
"aria-label": "Open in new window",
|
|
1577
|
+
onClick: onPopOut,
|
|
1578
|
+
className: styles.navButton,
|
|
1579
|
+
style: { width: CB.popOutWidth },
|
|
1580
|
+
"data-surface-part": "command-popout"
|
|
1581
|
+
}
|
|
1582
|
+
),
|
|
1583
|
+
/* @__PURE__ */ jsx9(ToolbarDivider, { className: styles.divider })
|
|
1584
|
+
] })
|
|
1585
|
+
] }),
|
|
1586
|
+
/* @__PURE__ */ jsxs6(Toolbar2, { "aria-label": "Commands", className: styles.commands, "data-surface-part": "command-list", children: [
|
|
1587
|
+
items.map(command),
|
|
1588
|
+
overflowItems && overflowItems.length > 0 && /* @__PURE__ */ jsx9(
|
|
1589
|
+
ItemMenu,
|
|
1590
|
+
{
|
|
1591
|
+
items: overflowItems,
|
|
1592
|
+
trigger: /* @__PURE__ */ jsx9(
|
|
1593
|
+
ToolbarButton2,
|
|
1594
|
+
{
|
|
1595
|
+
appearance: "subtle",
|
|
1596
|
+
"aria-label": "More commands",
|
|
1597
|
+
icon: /* @__PURE__ */ jsx9(MoreVertical16Regular, {}),
|
|
1598
|
+
className: styles.iconOnly,
|
|
1599
|
+
style: { width: CB.overflowWidth },
|
|
1600
|
+
"data-surface-part": "command-overflow"
|
|
1601
|
+
}
|
|
1602
|
+
)
|
|
1603
|
+
}
|
|
1604
|
+
)
|
|
1605
|
+
] }),
|
|
1606
|
+
farItems && farItems.length > 0 && /* @__PURE__ */ jsx9("div", { role: "group", "aria-label": "Secondary commands", className: mergeClasses4(styles.group, styles.far), "data-surface-part": "command-far", children: farItems.map((f) => {
|
|
1607
|
+
const btn = /* @__PURE__ */ jsxs6(
|
|
1608
|
+
Button3,
|
|
1609
|
+
{
|
|
1610
|
+
appearance: "outline",
|
|
1611
|
+
icon: f.icon,
|
|
1612
|
+
disabled: f.disabled,
|
|
1613
|
+
onClick: f.menuItems?.length ? void 0 : f.onClick,
|
|
1614
|
+
className: styles.farButton,
|
|
1615
|
+
"data-surface-part": "command-far-button",
|
|
1616
|
+
children: [
|
|
1617
|
+
f.label,
|
|
1618
|
+
f.menuItems?.length ? /* @__PURE__ */ jsx9(ChevronDown12Regular2, { style: { marginLeft: 4 }, "aria-hidden": true }) : null
|
|
1619
|
+
]
|
|
1620
|
+
},
|
|
1621
|
+
f.id
|
|
1622
|
+
);
|
|
1623
|
+
return f.menuItems?.length ? /* @__PURE__ */ jsx9(ItemMenu, { items: f.menuItems, trigger: btn }, f.id) : btn;
|
|
1624
|
+
}) })
|
|
1625
|
+
] }) });
|
|
1626
|
+
}
|
|
1627
|
+
var CommandSurface = (props) => {
|
|
1628
|
+
if (props.look === "ce") return /* @__PURE__ */ jsx9(CeCommandSurface, { ...props });
|
|
1629
|
+
const { items, overflowItems, farItems, size = "small", className } = props;
|
|
593
1630
|
const hasFar = Boolean(farItems && farItems.length > 0);
|
|
594
1631
|
const hasOverflow = Boolean(overflowItems && overflowItems.length > 0);
|
|
595
1632
|
const hasPrimary = items.length > 0 || hasOverflow;
|
|
596
|
-
return /* @__PURE__ */
|
|
597
|
-
hasPrimary && /* @__PURE__ */
|
|
1633
|
+
return /* @__PURE__ */ jsxs6("div", { className, style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
1634
|
+
hasPrimary && /* @__PURE__ */ jsxs6(Toolbar2, { "aria-label": "Commands", size, children: [
|
|
598
1635
|
items.map(renderToolbarButton),
|
|
599
|
-
hasOverflow && /* @__PURE__ */
|
|
600
|
-
/* @__PURE__ */
|
|
601
|
-
/* @__PURE__ */
|
|
1636
|
+
hasOverflow && /* @__PURE__ */ jsxs6(Menu2, { children: [
|
|
1637
|
+
/* @__PURE__ */ jsx9(MenuTrigger2, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsx9(ToolbarButton2, { "aria-label": "More commands", icon: /* @__PURE__ */ jsx9(MoreHorizontal20Regular, {}) }) }),
|
|
1638
|
+
/* @__PURE__ */ jsx9(MenuPopover2, { children: /* @__PURE__ */ jsx9(MenuList2, { children: overflowItems.map((item) => /* @__PURE__ */ jsx9(MenuItem, { icon: item.icon, disabled: item.disabled, onClick: item.onClick, children: item.label }, item.id)) }) })
|
|
602
1639
|
] })
|
|
603
1640
|
] }),
|
|
604
1641
|
hasFar && // marginLeft:auto keeps far items right-aligned whether or not a primary toolbar renders.
|
|
605
|
-
/* @__PURE__ */
|
|
1642
|
+
/* @__PURE__ */ jsx9(Toolbar2, { "aria-label": "Secondary commands", size, style: { marginLeft: "auto" }, children: farItems.map(renderToolbarButton) })
|
|
606
1643
|
] });
|
|
607
1644
|
};
|
|
608
1645
|
|
|
609
1646
|
// src/v9/containers/ActionBar.tsx
|
|
610
|
-
import { Button as
|
|
611
|
-
import { jsx as
|
|
1647
|
+
import { Button as Button4, tokens as tokens9 } from "@fluentui/react-components";
|
|
1648
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
612
1649
|
function renderButton(b) {
|
|
613
1650
|
const appearance = b.appearance === "primary" ? "primary" : b.appearance === "subtle" ? "subtle" : "secondary";
|
|
614
|
-
return /* @__PURE__ */
|
|
1651
|
+
return /* @__PURE__ */ jsx10(Button4, { appearance, icon: b.icon, disabled: b.disabled, onClick: b.onClick, children: b.label }, b.id);
|
|
615
1652
|
}
|
|
616
1653
|
var ActionBar = ({ buttons, alignment = "right", sticky = true, className }) => {
|
|
617
1654
|
const justify = alignment === "left" ? "flex-start" : alignment === "center" ? "center" : "flex-end";
|
|
@@ -624,19 +1661,19 @@ var ActionBar = ({ buttons, alignment = "right", sticky = true, className }) =>
|
|
|
624
1661
|
justifyContent: left.length ? "space-between" : justify,
|
|
625
1662
|
gap: 8,
|
|
626
1663
|
padding: "12px 24px",
|
|
627
|
-
borderTop: `1px solid ${
|
|
628
|
-
backgroundColor:
|
|
1664
|
+
borderTop: `1px solid ${tokens9.colorNeutralStroke2}`,
|
|
1665
|
+
backgroundColor: tokens9.colorNeutralBackground1,
|
|
629
1666
|
...sticky ? { position: "sticky", bottom: 0, zIndex: 1 } : {}
|
|
630
1667
|
};
|
|
631
|
-
return /* @__PURE__ */
|
|
632
|
-
left.length > 0 && /* @__PURE__ */
|
|
633
|
-
/* @__PURE__ */
|
|
1668
|
+
return /* @__PURE__ */ jsxs7("div", { className, style: rootStyle, children: [
|
|
1669
|
+
left.length > 0 && /* @__PURE__ */ jsx10("div", { style: { display: "flex", gap: 8 }, children: left.map(renderButton) }),
|
|
1670
|
+
/* @__PURE__ */ jsx10("div", { style: { display: "flex", gap: 8, justifyContent: justify }, children: right.map(renderButton) })
|
|
634
1671
|
] });
|
|
635
1672
|
};
|
|
636
1673
|
|
|
637
1674
|
// src/v9/containers/Footer.tsx
|
|
638
|
-
import { tokens as
|
|
639
|
-
import { jsx as
|
|
1675
|
+
import { tokens as tokens10 } from "@fluentui/react-components";
|
|
1676
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
640
1677
|
var Footer = ({ sticky = true, align = "right", className, children }) => {
|
|
641
1678
|
const justify = align === "left" ? "flex-start" : align === "center" ? "center" : "flex-end";
|
|
642
1679
|
const rootStyle = {
|
|
@@ -645,17 +1682,82 @@ var Footer = ({ sticky = true, align = "right", className, children }) => {
|
|
|
645
1682
|
justifyContent: justify,
|
|
646
1683
|
gap: 8,
|
|
647
1684
|
padding: "12px 24px",
|
|
648
|
-
borderTop: `1px solid ${
|
|
649
|
-
backgroundColor:
|
|
1685
|
+
borderTop: `1px solid ${tokens10.colorNeutralStroke2}`,
|
|
1686
|
+
backgroundColor: tokens10.colorNeutralBackground1,
|
|
650
1687
|
...sticky ? { position: "sticky", bottom: 0, zIndex: 1 } : {}
|
|
651
1688
|
};
|
|
652
|
-
return /* @__PURE__ */
|
|
1689
|
+
return /* @__PURE__ */ jsx11("div", { className, style: rootStyle, children });
|
|
1690
|
+
};
|
|
1691
|
+
|
|
1692
|
+
// src/v9/layouts/TabColumns.tsx
|
|
1693
|
+
import React5 from "react";
|
|
1694
|
+
import { makeStyles as makeStyles7, mergeClasses as mergeClasses5 } from "@fluentui/react-components";
|
|
1695
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1696
|
+
var useStyles7 = makeStyles7({
|
|
1697
|
+
row: {
|
|
1698
|
+
display: "flex",
|
|
1699
|
+
flexWrap: "wrap",
|
|
1700
|
+
alignItems: "flex-start"
|
|
1701
|
+
},
|
|
1702
|
+
column: {
|
|
1703
|
+
display: "flex",
|
|
1704
|
+
flexDirection: "column",
|
|
1705
|
+
boxSizing: "border-box"
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1708
|
+
function positional(children) {
|
|
1709
|
+
const out = [];
|
|
1710
|
+
const walk = (node) => {
|
|
1711
|
+
if (Array.isArray(node)) node.forEach(walk);
|
|
1712
|
+
else out.push(node);
|
|
1713
|
+
};
|
|
1714
|
+
walk(children);
|
|
1715
|
+
return out;
|
|
1716
|
+
}
|
|
1717
|
+
var isEmpty2 = (n) => n === null || n === void 0 || typeof n === "boolean" || n === "";
|
|
1718
|
+
var TabColumns = ({
|
|
1719
|
+
widths,
|
|
1720
|
+
minColumnWidth,
|
|
1721
|
+
gap,
|
|
1722
|
+
look: lookProp,
|
|
1723
|
+
className,
|
|
1724
|
+
style,
|
|
1725
|
+
children
|
|
1726
|
+
}) => {
|
|
1727
|
+
const styles = useStyles7();
|
|
1728
|
+
const ambientLook = useLook();
|
|
1729
|
+
const ce = (lookProp ?? ambientLook) === "ce";
|
|
1730
|
+
const floor = minColumnWidth ?? (ce ? ceForm.tabBody.columnMinWidth : 300);
|
|
1731
|
+
const spacing2 = gap ?? (ce ? ceForm.tabBody.columnGap : 20);
|
|
1732
|
+
const slots = positional(children);
|
|
1733
|
+
const visible = slots.map((s, i) => ({ node: s, i })).filter(({ node }) => !isEmpty2(node));
|
|
1734
|
+
const shares = normalizeColumnShares(visible.map(({ i }) => widths?.[i] ?? 1));
|
|
1735
|
+
return /* @__PURE__ */ jsx12(
|
|
1736
|
+
"div",
|
|
1737
|
+
{
|
|
1738
|
+
className: mergeClasses5(styles.row, className),
|
|
1739
|
+
style: { gap: spacing2, ...style },
|
|
1740
|
+
"data-surface-part": "tab-columns",
|
|
1741
|
+
"data-look": ce ? "ce" : "default",
|
|
1742
|
+
children: visible.map(({ node, i }, v) => /* @__PURE__ */ jsx12(
|
|
1743
|
+
"div",
|
|
1744
|
+
{
|
|
1745
|
+
className: styles.column,
|
|
1746
|
+
style: { flex: `${shares[v]} 1 0`, minWidth: `min(${floor}px, 100%)`, gap: ce ? ceForm.tabBody.sectionGap : spacing2 },
|
|
1747
|
+
"data-surface-part": "tab-column",
|
|
1748
|
+
"data-column-index": i,
|
|
1749
|
+
children: node
|
|
1750
|
+
},
|
|
1751
|
+
React5.isValidElement(node) && node.key != null ? node.key : i
|
|
1752
|
+
))
|
|
1753
|
+
}
|
|
1754
|
+
);
|
|
653
1755
|
};
|
|
654
1756
|
|
|
655
1757
|
// src/v9/overlays/FormDialogSurface.tsx
|
|
656
|
-
import { Dialog, DialogSurface, Button as
|
|
1758
|
+
import { Dialog, DialogSurface, Button as Button5, Text as Text3, tokens as tokens11 } from "@fluentui/react-components";
|
|
657
1759
|
import { Dismiss20Regular } from "@fluentui/react-icons";
|
|
658
|
-
import { jsx as
|
|
1760
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
659
1761
|
var FormDialogSurface = ({
|
|
660
1762
|
isOpen,
|
|
661
1763
|
onDismiss,
|
|
@@ -679,10 +1781,10 @@ var FormDialogSurface = ({
|
|
|
679
1781
|
justifyContent: "space-between",
|
|
680
1782
|
gap: 12,
|
|
681
1783
|
padding: "12px 20px",
|
|
682
|
-
borderBottom: `1px solid ${
|
|
1784
|
+
borderBottom: `1px solid ${tokens11.colorNeutralStroke2}`
|
|
683
1785
|
};
|
|
684
|
-
const counterStyle = { fontSize:
|
|
685
|
-
return /* @__PURE__ */
|
|
1786
|
+
const counterStyle = { fontSize: tokens11.fontSizeBase200, color: tokens11.colorNeutralForeground3 };
|
|
1787
|
+
return /* @__PURE__ */ jsx13(
|
|
686
1788
|
Dialog,
|
|
687
1789
|
{
|
|
688
1790
|
open: isOpen,
|
|
@@ -690,7 +1792,7 @@ var FormDialogSurface = ({
|
|
|
690
1792
|
onOpenChange: (_e, data) => {
|
|
691
1793
|
if (!data.open) onDismiss?.();
|
|
692
1794
|
},
|
|
693
|
-
children: /* @__PURE__ */
|
|
1795
|
+
children: /* @__PURE__ */ jsxs8(
|
|
694
1796
|
DialogSurface,
|
|
695
1797
|
{
|
|
696
1798
|
className,
|
|
@@ -704,22 +1806,22 @@ var FormDialogSurface = ({
|
|
|
704
1806
|
padding: 0
|
|
705
1807
|
},
|
|
706
1808
|
children: [
|
|
707
|
-
showHeader && /* @__PURE__ */
|
|
708
|
-
/* @__PURE__ */
|
|
709
|
-
title && /* @__PURE__ */
|
|
710
|
-
subheader && /* @__PURE__ */
|
|
1809
|
+
showHeader && /* @__PURE__ */ jsxs8("div", { style: headerStyle, children: [
|
|
1810
|
+
/* @__PURE__ */ jsxs8("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1811
|
+
title && /* @__PURE__ */ jsx13(Text3, { weight: "semibold", size: 400, children: title }),
|
|
1812
|
+
subheader && /* @__PURE__ */ jsx13("span", { style: { fontSize: tokens11.fontSizeBase200, color: tokens11.colorNeutralForeground3, marginTop: 2 }, children: subheader })
|
|
711
1813
|
] }),
|
|
712
|
-
/* @__PURE__ */
|
|
713
|
-
recordCounter && /* @__PURE__ */
|
|
1814
|
+
/* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
1815
|
+
recordCounter && /* @__PURE__ */ jsxs8("span", { style: counterStyle, children: [
|
|
714
1816
|
recordCounter.current,
|
|
715
1817
|
" of ",
|
|
716
1818
|
recordCounter.total
|
|
717
1819
|
] }),
|
|
718
|
-
onDismiss && /* @__PURE__ */
|
|
1820
|
+
onDismiss && /* @__PURE__ */ jsx13(Button5, { appearance: "subtle", "aria-label": "Close", icon: /* @__PURE__ */ jsx13(Dismiss20Regular, {}), onClick: onDismiss })
|
|
719
1821
|
] })
|
|
720
1822
|
] }),
|
|
721
|
-
/* @__PURE__ */
|
|
722
|
-
footer && /* @__PURE__ */
|
|
1823
|
+
/* @__PURE__ */ jsx13("div", { style: { flex: 1, minHeight: 0, overflow: "auto", padding: 20 }, children }),
|
|
1824
|
+
footer && /* @__PURE__ */ jsx13("div", { style: { borderTop: `1px solid ${tokens11.colorNeutralStroke2}`, padding: "12px 20px" }, children: footer })
|
|
723
1825
|
]
|
|
724
1826
|
}
|
|
725
1827
|
)
|
|
@@ -728,8 +1830,8 @@ var FormDialogSurface = ({
|
|
|
728
1830
|
};
|
|
729
1831
|
|
|
730
1832
|
// src/v9/overlays/ModalSurface.tsx
|
|
731
|
-
import { Dialog as Dialog2, DialogSurface as DialogSurface2, Text as Text4, tokens as
|
|
732
|
-
import { jsx as
|
|
1833
|
+
import { Dialog as Dialog2, DialogSurface as DialogSurface2, Text as Text4, tokens as tokens12 } from "@fluentui/react-components";
|
|
1834
|
+
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
733
1835
|
var ModalSurface = ({
|
|
734
1836
|
isOpen,
|
|
735
1837
|
onDismiss,
|
|
@@ -743,7 +1845,7 @@ var ModalSurface = ({
|
|
|
743
1845
|
children
|
|
744
1846
|
}) => {
|
|
745
1847
|
const sizing = autoSize ? { width: "auto", minWidth: MODAL_AUTOSIZE_MIN_WIDTH, maxWidth: "100%" } : { maxWidth: "95vw", width: `${dialogWidthPx({ width, size })}px` };
|
|
746
|
-
return /* @__PURE__ */
|
|
1848
|
+
return /* @__PURE__ */ jsx14(
|
|
747
1849
|
Dialog2,
|
|
748
1850
|
{
|
|
749
1851
|
open: isOpen,
|
|
@@ -751,14 +1853,14 @@ var ModalSurface = ({
|
|
|
751
1853
|
onOpenChange: (_e, data) => {
|
|
752
1854
|
if (!data.open) onDismiss?.();
|
|
753
1855
|
},
|
|
754
|
-
children: /* @__PURE__ */
|
|
755
|
-
title && /* @__PURE__ */
|
|
756
|
-
/* @__PURE__ */
|
|
757
|
-
footer && /* @__PURE__ */
|
|
1856
|
+
children: /* @__PURE__ */ jsxs9(DialogSurface2, { className, style: { ...sizing, padding: 0 }, children: [
|
|
1857
|
+
title && /* @__PURE__ */ jsx14("div", { style: { padding: "16px 20px 0" }, children: /* @__PURE__ */ jsx14(Text4, { weight: "semibold", size: 500, children: title }) }),
|
|
1858
|
+
/* @__PURE__ */ jsx14("div", { style: { padding: 20 }, children }),
|
|
1859
|
+
footer && /* @__PURE__ */ jsx14(
|
|
758
1860
|
"div",
|
|
759
1861
|
{
|
|
760
1862
|
style: {
|
|
761
|
-
borderTop: `1px solid ${
|
|
1863
|
+
borderTop: `1px solid ${tokens12.colorNeutralStroke2}`,
|
|
762
1864
|
padding: "12px 20px",
|
|
763
1865
|
display: "flex",
|
|
764
1866
|
justifyContent: "flex-end",
|
|
@@ -778,10 +1880,10 @@ import {
|
|
|
778
1880
|
DrawerHeader,
|
|
779
1881
|
DrawerHeaderTitle,
|
|
780
1882
|
DrawerBody,
|
|
781
|
-
Button as
|
|
1883
|
+
Button as Button6
|
|
782
1884
|
} from "@fluentui/react-components";
|
|
783
1885
|
import { Dismiss24Regular } from "@fluentui/react-icons";
|
|
784
|
-
import { jsx as
|
|
1886
|
+
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
785
1887
|
var PanelSurface = ({
|
|
786
1888
|
isOpen,
|
|
787
1889
|
onDismiss,
|
|
@@ -796,7 +1898,7 @@ var PanelSurface = ({
|
|
|
796
1898
|
}) => {
|
|
797
1899
|
const size = drawerSize ?? (width != null && width > 500 ? "medium" : "small");
|
|
798
1900
|
const customWidthStyle = width != null ? { width: `${width}px` } : void 0;
|
|
799
|
-
return /* @__PURE__ */
|
|
1901
|
+
return /* @__PURE__ */ jsxs10(
|
|
800
1902
|
OverlayDrawer,
|
|
801
1903
|
{
|
|
802
1904
|
open: isOpen,
|
|
@@ -810,16 +1912,16 @@ var PanelSurface = ({
|
|
|
810
1912
|
onDismiss?.();
|
|
811
1913
|
},
|
|
812
1914
|
children: [
|
|
813
|
-
/* @__PURE__ */
|
|
1915
|
+
/* @__PURE__ */ jsx15(DrawerHeader, { children: /* @__PURE__ */ jsx15(
|
|
814
1916
|
DrawerHeaderTitle,
|
|
815
1917
|
{
|
|
816
|
-
action: hasCloseButton && onDismiss ? /* @__PURE__ */
|
|
1918
|
+
action: hasCloseButton && onDismiss ? /* @__PURE__ */ jsx15(Button6, { appearance: "subtle", "aria-label": "Close", icon: /* @__PURE__ */ jsx15(Dismiss24Regular, {}), onClick: onDismiss }) : void 0,
|
|
817
1919
|
children: title
|
|
818
1920
|
}
|
|
819
1921
|
) }),
|
|
820
|
-
/* @__PURE__ */
|
|
821
|
-
/* @__PURE__ */
|
|
822
|
-
footer && /* @__PURE__ */
|
|
1922
|
+
/* @__PURE__ */ jsxs10(DrawerBody, { children: [
|
|
1923
|
+
/* @__PURE__ */ jsx15("div", { style: { padding: "12px 0" }, children }),
|
|
1924
|
+
footer && /* @__PURE__ */ jsx15("div", { style: { marginTop: "auto", paddingTop: 12 }, children: footer })
|
|
823
1925
|
] })
|
|
824
1926
|
]
|
|
825
1927
|
}
|
|
@@ -828,7 +1930,7 @@ var PanelSurface = ({
|
|
|
828
1930
|
|
|
829
1931
|
// src/v9/overlays/CalloutSurface.tsx
|
|
830
1932
|
import { Popover, PopoverSurface } from "@fluentui/react-components";
|
|
831
|
-
import { jsx as
|
|
1933
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
832
1934
|
function resolveTarget(target) {
|
|
833
1935
|
if (!target) return null;
|
|
834
1936
|
if (typeof target === "string") return document.querySelector(target);
|
|
@@ -849,7 +1951,7 @@ var CalloutSurface = ({
|
|
|
849
1951
|
if (!isOpen) return null;
|
|
850
1952
|
const el = resolveTarget(target);
|
|
851
1953
|
const positioning = { position, align, ...el ? { target: el } : {} };
|
|
852
|
-
return /* @__PURE__ */
|
|
1954
|
+
return /* @__PURE__ */ jsx16(
|
|
853
1955
|
Popover,
|
|
854
1956
|
{
|
|
855
1957
|
open: true,
|
|
@@ -859,14 +1961,14 @@ var CalloutSurface = ({
|
|
|
859
1961
|
onOpenChange: (_e, data) => {
|
|
860
1962
|
if (!data.open) onDismiss?.();
|
|
861
1963
|
},
|
|
862
|
-
children: /* @__PURE__ */
|
|
1964
|
+
children: /* @__PURE__ */ jsx16(PopoverSurface, { className, style: { width: calloutWidthPx(width), padding: 16 }, children })
|
|
863
1965
|
}
|
|
864
1966
|
);
|
|
865
1967
|
};
|
|
866
1968
|
|
|
867
1969
|
// src/v9/overlays/TooltipSurface.tsx
|
|
868
1970
|
import { Tooltip } from "@fluentui/react-components";
|
|
869
|
-
import { jsx as
|
|
1971
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
870
1972
|
var DELAY_MS = {
|
|
871
1973
|
zero: 0,
|
|
872
1974
|
medium: 250,
|
|
@@ -878,20 +1980,24 @@ var TooltipSurface = ({
|
|
|
878
1980
|
delay = "medium",
|
|
879
1981
|
relationship = "label",
|
|
880
1982
|
children
|
|
881
|
-
}) => /* @__PURE__ */
|
|
1983
|
+
}) => /* @__PURE__ */ jsx17(Tooltip, { content, relationship, positioning: position, showDelay: DELAY_MS[delay], children });
|
|
882
1984
|
export {
|
|
883
1985
|
ActionBar,
|
|
884
1986
|
BREAKPOINTS,
|
|
885
1987
|
CALLOUT_DEFAULT_WIDTH,
|
|
886
1988
|
CARD_REFLOW_WIDTH,
|
|
1989
|
+
CE_LABEL_ABOVE_BELOW_ROW_WIDTH,
|
|
1990
|
+
CE_TAB_COLUMN_MIN_WIDTH,
|
|
887
1991
|
CalloutSurface,
|
|
888
1992
|
CommandSurface,
|
|
889
1993
|
DIALOG_SIZE_PX,
|
|
890
1994
|
DensityContext,
|
|
1995
|
+
FieldRow,
|
|
891
1996
|
Footer,
|
|
892
1997
|
FormDialogSurface,
|
|
893
1998
|
FormHeader,
|
|
894
1999
|
FormSurface,
|
|
2000
|
+
LookContext,
|
|
895
2001
|
MODAL_AUTOSIZE_MIN_WIDTH,
|
|
896
2002
|
ModalSurface,
|
|
897
2003
|
PANEL_DEFAULT_WIDTH,
|
|
@@ -901,11 +2007,16 @@ export {
|
|
|
901
2007
|
Section,
|
|
902
2008
|
SectionCard,
|
|
903
2009
|
SectionHeader,
|
|
2010
|
+
TabColumns,
|
|
904
2011
|
TooltipSurface,
|
|
905
2012
|
calloutFormDefaults,
|
|
906
2013
|
calloutWidthPx,
|
|
2014
|
+
ceFieldRowFirstOffset,
|
|
2015
|
+
ceForm,
|
|
2016
|
+
cePresenceBadgeStyle,
|
|
907
2017
|
clampSpan,
|
|
908
2018
|
colors,
|
|
2019
|
+
createDynamicsCeTheme,
|
|
909
2020
|
createDynamicsV9DarkTheme,
|
|
910
2021
|
createDynamicsV9Theme,
|
|
911
2022
|
densityScale,
|
|
@@ -913,16 +2024,20 @@ export {
|
|
|
913
2024
|
dialogWidthCss,
|
|
914
2025
|
dialogWidthPx,
|
|
915
2026
|
dynamicsBrandRamp,
|
|
2027
|
+
dynamicsCeTheme,
|
|
2028
|
+
dynamicsV9DarkTheme,
|
|
916
2029
|
dynamicsV9Theme,
|
|
917
2030
|
fieldGridStyle,
|
|
918
2031
|
fieldRowStyle,
|
|
919
2032
|
gridTemplateForColumns,
|
|
920
2033
|
layout,
|
|
2034
|
+
normalizeColumnShares,
|
|
921
2035
|
panelCustomWidthPx,
|
|
922
2036
|
panelKindFromWidth,
|
|
923
2037
|
radius,
|
|
924
2038
|
resolveBreakpoint,
|
|
925
2039
|
resolveResponsiveValue,
|
|
2040
|
+
resolveTabColumnWidths,
|
|
926
2041
|
scaleSpacing,
|
|
927
2042
|
sectionStackingStyle,
|
|
928
2043
|
spacing,
|
|
@@ -931,6 +2046,7 @@ export {
|
|
|
931
2046
|
useContainerSize,
|
|
932
2047
|
useContainerWidth,
|
|
933
2048
|
useDensity,
|
|
2049
|
+
useLook,
|
|
934
2050
|
useMediaQuery,
|
|
935
2051
|
useResponsiveValue
|
|
936
2052
|
};
|