@dataverse-kit/surface-kit 0.4.1 → 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 +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +34 -1
- package/dist/index.mjs.map +1 -1
- package/dist/v9.cjs +1283 -153
- package/dist/v9.cjs.map +1 -1
- package/dist/v9.d.cts +213 -10
- package/dist/v9.d.ts +213 -10
- package/dist/v9.mjs +1284 -144
- package/dist/v9.mjs.map +1 -1
- package/package.json +3 -3
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,13 +222,20 @@ 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
232
|
dynamicsBrandRamp,
|
|
200
233
|
createDynamicsV9Theme,
|
|
201
234
|
createDynamicsV9DarkTheme,
|
|
202
235
|
dynamicsV9Theme,
|
|
203
|
-
dynamicsV9DarkTheme
|
|
236
|
+
dynamicsV9DarkTheme,
|
|
237
|
+
createDynamicsCeTheme,
|
|
238
|
+
dynamicsCeTheme
|
|
204
239
|
} from "@dataverse-kit/fluent-theme";
|
|
205
240
|
|
|
206
241
|
// src/v9/containers/FormSurface.tsx
|
|
@@ -235,10 +270,11 @@ var VIEWPORT_STACK = {
|
|
|
235
270
|
var FormSurface = ({
|
|
236
271
|
columns = 12,
|
|
237
272
|
gap = 20,
|
|
238
|
-
padding
|
|
273
|
+
padding,
|
|
239
274
|
density = "comfortable",
|
|
240
275
|
background,
|
|
241
276
|
containerWidth,
|
|
277
|
+
look = "default",
|
|
242
278
|
collapseBelow = "sm",
|
|
243
279
|
maxWidth,
|
|
244
280
|
className,
|
|
@@ -246,10 +282,29 @@ var FormSurface = ({
|
|
|
246
282
|
children
|
|
247
283
|
}) => {
|
|
248
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
|
+
}
|
|
249
304
|
const collapsePx = BREAKPOINTS[collapseBelow];
|
|
250
305
|
const forceStack = containerWidth != null && containerWidth <= collapsePx;
|
|
251
306
|
const scaledGap = scaleSpacing(gap, density);
|
|
252
|
-
const scaledPadding = scaleSpacing(padding, density);
|
|
307
|
+
const scaledPadding = scaleSpacing(padding ?? 20, density);
|
|
253
308
|
const viewportStackSlot = containerWidth == null ? VIEWPORT_STACK[collapseBelow] : null;
|
|
254
309
|
const cls = mergeClasses(
|
|
255
310
|
styles.root,
|
|
@@ -265,7 +320,7 @@ var FormSurface = ({
|
|
|
265
320
|
...maxWidth != null ? { maxWidth, marginLeft: "auto", marginRight: "auto" } : {},
|
|
266
321
|
...style
|
|
267
322
|
};
|
|
268
|
-
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 }) }) });
|
|
269
324
|
};
|
|
270
325
|
|
|
271
326
|
// src/v9/containers/PageSurface.tsx
|
|
@@ -273,8 +328,232 @@ import { jsx as jsx2 } from "react/jsx-runtime";
|
|
|
273
328
|
var PageSurface = ({ centered, maxWidth, ...rest }) => /* @__PURE__ */ jsx2(FormSurface, { maxWidth: maxWidth ?? (centered ? 1200 : void 0), ...rest });
|
|
274
329
|
|
|
275
330
|
// src/v9/containers/Section.tsx
|
|
276
|
-
import { useState as useState3 } from "react";
|
|
277
|
-
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
|
+
};
|
|
278
557
|
|
|
279
558
|
// src/v9/containers/SectionHeader.tsx
|
|
280
559
|
import {
|
|
@@ -282,10 +561,10 @@ import {
|
|
|
282
561
|
Text,
|
|
283
562
|
Toolbar,
|
|
284
563
|
ToolbarButton,
|
|
285
|
-
tokens as
|
|
564
|
+
tokens as tokens3
|
|
286
565
|
} from "@fluentui/react-components";
|
|
287
566
|
import { ChevronDown20Regular, ChevronRight20Regular } from "@fluentui/react-icons";
|
|
288
|
-
import { jsx as
|
|
567
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
289
568
|
var SectionHeader = ({
|
|
290
569
|
title,
|
|
291
570
|
statusText,
|
|
@@ -294,14 +573,26 @@ var SectionHeader = ({
|
|
|
294
573
|
actions,
|
|
295
574
|
collapsible,
|
|
296
575
|
collapsed,
|
|
297
|
-
onToggle
|
|
576
|
+
onToggle,
|
|
577
|
+
look: lookProp
|
|
298
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
|
+
};
|
|
299
590
|
const rootStyle = {
|
|
300
591
|
display: "flex",
|
|
301
592
|
justifyContent: "space-between",
|
|
302
593
|
alignItems: "center",
|
|
303
594
|
flexWrap: "nowrap",
|
|
304
|
-
borderBottom: `1px solid ${
|
|
595
|
+
borderBottom: `1px solid ${tokens3.colorNeutralStroke2}`,
|
|
305
596
|
marginBottom: 16,
|
|
306
597
|
minHeight: 48,
|
|
307
598
|
width: "100%"
|
|
@@ -309,26 +600,40 @@ var SectionHeader = ({
|
|
|
309
600
|
const leftStyle = { display: "flex", alignItems: "center", gap: 8, minWidth: 0 };
|
|
310
601
|
const statusStyle = {
|
|
311
602
|
marginLeft: 8,
|
|
312
|
-
fontSize:
|
|
313
|
-
color:
|
|
603
|
+
fontSize: tokens3.fontSizeBase200,
|
|
604
|
+
color: tokens3.colorNeutralForeground3
|
|
314
605
|
};
|
|
315
|
-
return /* @__PURE__ */
|
|
316
|
-
/* @__PURE__ */
|
|
317
|
-
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(
|
|
318
609
|
Button,
|
|
319
610
|
{
|
|
320
611
|
appearance: "subtle",
|
|
321
612
|
size: "small",
|
|
322
|
-
icon: collapsed ? /* @__PURE__ */
|
|
613
|
+
icon: collapsed ? /* @__PURE__ */ jsx4(ChevronRight20Regular, {}) : /* @__PURE__ */ jsx4(ChevronDown20Regular, {}),
|
|
323
614
|
onClick: onToggle,
|
|
324
615
|
"aria-label": collapsed ? "Expand section" : "Collapse section",
|
|
325
616
|
"aria-expanded": !collapsed
|
|
326
617
|
}
|
|
327
618
|
),
|
|
328
|
-
title &&
|
|
329
|
-
|
|
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 })
|
|
330
635
|
] }),
|
|
331
|
-
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(
|
|
332
637
|
ToolbarButton,
|
|
333
638
|
{
|
|
334
639
|
icon: item.icon,
|
|
@@ -343,8 +648,18 @@ var SectionHeader = ({
|
|
|
343
648
|
};
|
|
344
649
|
|
|
345
650
|
// src/v9/containers/Section.tsx
|
|
346
|
-
import { jsx as
|
|
347
|
-
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({
|
|
348
663
|
// Phone-stack the internal field grid below `sm` (griffel — inline can't do @media).
|
|
349
664
|
bodyStack: {
|
|
350
665
|
[`@media (max-width: ${BREAKPOINTS.sm}px)`]: { "& > *": { gridColumn: "1 / -1" } }
|
|
@@ -355,7 +670,7 @@ var Section = ({
|
|
|
355
670
|
columnSpan = 12,
|
|
356
671
|
columnStart,
|
|
357
672
|
rowPosition,
|
|
358
|
-
internalColumns
|
|
673
|
+
internalColumns: internalColumnsProp,
|
|
359
674
|
showCommandBar,
|
|
360
675
|
commandItems,
|
|
361
676
|
statusText,
|
|
@@ -367,11 +682,15 @@ var Section = ({
|
|
|
367
682
|
variant = "card",
|
|
368
683
|
minHeight = 80,
|
|
369
684
|
density: densityProp,
|
|
685
|
+
look: lookProp,
|
|
370
686
|
className,
|
|
371
687
|
style,
|
|
372
688
|
children
|
|
373
689
|
}) => {
|
|
374
|
-
const styles =
|
|
690
|
+
const styles = useStyles3();
|
|
691
|
+
const internalColumns = internalColumnsProp ?? 12;
|
|
692
|
+
const ambientLook = useLook();
|
|
693
|
+
const ce = (lookProp ?? ambientLook) === "ce" && variant === "card";
|
|
375
694
|
const [internalCollapsed, setInternalCollapsed] = useState3(defaultCollapsed);
|
|
376
695
|
const collapsed = controlledCollapsed ?? internalCollapsed;
|
|
377
696
|
const toggle = () => {
|
|
@@ -392,41 +711,102 @@ var Section = ({
|
|
|
392
711
|
if (variant === "placeholder") {
|
|
393
712
|
const placeholderStyle = {
|
|
394
713
|
...rootStyle,
|
|
395
|
-
border: `1px dashed ${
|
|
396
|
-
borderRadius:
|
|
714
|
+
border: `1px dashed ${tokens4.colorNeutralStroke2}`,
|
|
715
|
+
borderRadius: tokens4.borderRadiusMedium,
|
|
397
716
|
minHeight,
|
|
398
717
|
width: "100%",
|
|
399
718
|
background: "transparent"
|
|
400
719
|
};
|
|
401
|
-
return /* @__PURE__ */
|
|
720
|
+
return /* @__PURE__ */ jsx5("div", { className, style: placeholderStyle });
|
|
402
721
|
}
|
|
403
722
|
const chrome = variant === "flat" ? {
|
|
404
|
-
backgroundColor:
|
|
405
|
-
borderRadius:
|
|
723
|
+
backgroundColor: tokens4.colorNeutralBackground1,
|
|
724
|
+
borderRadius: tokens4.borderRadiusMedium,
|
|
406
725
|
padding: cardPad,
|
|
407
726
|
minWidth: 300,
|
|
408
727
|
width: "100%",
|
|
409
728
|
overflow: "hidden"
|
|
410
729
|
} : {
|
|
411
|
-
backgroundColor:
|
|
412
|
-
border: `1px solid ${
|
|
413
|
-
borderRadius:
|
|
414
|
-
boxShadow:
|
|
730
|
+
backgroundColor: tokens4.colorNeutralBackground1,
|
|
731
|
+
border: `1px solid ${tokens4.colorNeutralStroke2}`,
|
|
732
|
+
borderRadius: tokens4.borderRadiusMedium,
|
|
733
|
+
boxShadow: tokens4.shadow4,
|
|
415
734
|
padding: cardPad,
|
|
416
735
|
minWidth: 300,
|
|
417
736
|
width: "100%",
|
|
418
737
|
overflow: "hidden"
|
|
419
738
|
};
|
|
420
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
|
+
}
|
|
421
801
|
const bodyStyle = {
|
|
422
802
|
display: "grid",
|
|
423
803
|
gridTemplateColumns: `repeat(${internalColumns}, 1fr)`,
|
|
424
804
|
gap: bodyGap,
|
|
425
805
|
alignItems: "start"
|
|
426
806
|
};
|
|
427
|
-
return /* @__PURE__ */
|
|
428
|
-
notification && /* @__PURE__ */
|
|
429
|
-
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(
|
|
430
810
|
SectionHeader,
|
|
431
811
|
{
|
|
432
812
|
title,
|
|
@@ -438,20 +818,20 @@ var Section = ({
|
|
|
438
818
|
onToggle: toggle
|
|
439
819
|
}
|
|
440
820
|
),
|
|
441
|
-
!collapsed && /* @__PURE__ */
|
|
821
|
+
!collapsed && /* @__PURE__ */ jsx5("div", { className: mergeClasses3(styles.bodyStack), style: bodyStyle, children })
|
|
442
822
|
] });
|
|
443
823
|
};
|
|
444
824
|
|
|
445
825
|
// src/v9/containers/SectionCard.tsx
|
|
446
|
-
import { tokens as
|
|
447
|
-
import { jsx as
|
|
826
|
+
import { tokens as tokens5 } from "@fluentui/react-components";
|
|
827
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
448
828
|
var SectionCard = ({
|
|
449
|
-
accentColor =
|
|
829
|
+
accentColor = tokens5.colorBrandStroke1,
|
|
450
830
|
accentWidth = 3,
|
|
451
831
|
variant = "card",
|
|
452
832
|
style,
|
|
453
833
|
...rest
|
|
454
|
-
}) => /* @__PURE__ */
|
|
834
|
+
}) => /* @__PURE__ */ jsx6(
|
|
455
835
|
Section,
|
|
456
836
|
{
|
|
457
837
|
variant,
|
|
@@ -461,54 +841,363 @@ var SectionCard = ({
|
|
|
461
841
|
);
|
|
462
842
|
|
|
463
843
|
// src/v9/containers/FormHeader.tsx
|
|
464
|
-
import
|
|
465
|
-
import {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
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;
|
|
476
1097
|
const rootStyle = {
|
|
477
1098
|
display: "flex",
|
|
478
1099
|
alignItems: "center",
|
|
479
1100
|
justifyContent: "space-between",
|
|
480
1101
|
gap: 12,
|
|
481
1102
|
padding: "12px 24px",
|
|
482
|
-
borderBottom: `1px solid ${
|
|
483
|
-
backgroundColor:
|
|
1103
|
+
borderBottom: `1px solid ${tokens6.colorNeutralStroke2}`,
|
|
1104
|
+
backgroundColor: tokens6.colorNeutralBackground1
|
|
484
1105
|
};
|
|
485
1106
|
const mainStyle = { display: "flex", alignItems: "center", gap: 12, minWidth: 0 };
|
|
486
1107
|
const titleRowStyle = { display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap" };
|
|
487
|
-
const statusStyle = { fontSize:
|
|
1108
|
+
const statusStyle = { fontSize: tokens6.fontSizeBase200, color: tokens6.colorNeutralForeground3 };
|
|
488
1109
|
const subtitleStyle = {
|
|
489
|
-
fontSize:
|
|
490
|
-
color: subtitleColor ||
|
|
1110
|
+
fontSize: tokens6.fontSizeBase200,
|
|
1111
|
+
color: subtitleColor || tokens6.colorNeutralForeground3,
|
|
491
1112
|
marginTop: 2
|
|
492
1113
|
};
|
|
493
|
-
return /* @__PURE__ */
|
|
494
|
-
/* @__PURE__ */
|
|
1114
|
+
return /* @__PURE__ */ jsxs4("div", { className, style: rootStyle, children: [
|
|
1115
|
+
/* @__PURE__ */ jsxs4("div", { style: mainStyle, children: [
|
|
495
1116
|
persona,
|
|
496
|
-
/* @__PURE__ */
|
|
497
|
-
/* @__PURE__ */
|
|
498
|
-
title != null && /* @__PURE__ */
|
|
499
|
-
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 })
|
|
500
1121
|
] }),
|
|
501
|
-
subtitle != null && /* @__PURE__ */
|
|
1122
|
+
subtitle != null && /* @__PURE__ */ jsx7("div", { style: subtitleStyle, children: subtitle })
|
|
502
1123
|
] })
|
|
503
1124
|
] }),
|
|
504
|
-
actions != null && /* @__PURE__ */
|
|
1125
|
+
actions != null && /* @__PURE__ */ jsx7("div", { children: actions })
|
|
505
1126
|
] });
|
|
506
1127
|
};
|
|
507
1128
|
|
|
508
1129
|
// src/v9/containers/PivotSurface.tsx
|
|
509
|
-
import { useState as useState4 } from "react";
|
|
510
|
-
import {
|
|
511
|
-
|
|
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
|
+
});
|
|
512
1201
|
var PivotSurface = ({
|
|
513
1202
|
tabs,
|
|
514
1203
|
selectedId,
|
|
@@ -516,8 +1205,15 @@ var PivotSurface = ({
|
|
|
516
1205
|
onTabChange,
|
|
517
1206
|
appearance = "transparent",
|
|
518
1207
|
size = "medium",
|
|
519
|
-
className
|
|
1208
|
+
className,
|
|
1209
|
+
look: lookProp,
|
|
1210
|
+
header
|
|
520
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`;
|
|
521
1217
|
const firstEnabledId = tabs.find((t) => !t.disabled)?.id ?? tabs[0]?.id;
|
|
522
1218
|
const [internal, setInternal] = useState4(defaultSelectedId ?? firstEnabledId);
|
|
523
1219
|
const selected = selectedId ?? internal;
|
|
@@ -527,66 +1223,432 @@ var PivotSurface = ({
|
|
|
527
1223
|
onTabChange?.(id);
|
|
528
1224
|
};
|
|
529
1225
|
const active = tabs.find((t) => t.id === selected) ?? tabs[0];
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
/* @__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 })
|
|
533
1293
|
] });
|
|
534
1294
|
};
|
|
535
1295
|
|
|
536
1296
|
// src/v9/containers/CommandSurface.tsx
|
|
1297
|
+
import React4 from "react";
|
|
537
1298
|
import {
|
|
1299
|
+
Button as Button3,
|
|
538
1300
|
Toolbar as Toolbar2,
|
|
539
1301
|
ToolbarButton as ToolbarButton2,
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
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
|
|
545
1312
|
} from "@fluentui/react-components";
|
|
546
|
-
import {
|
|
547
|
-
|
|
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
|
+
}
|
|
548
1328
|
function renderToolbarButton(item) {
|
|
549
|
-
|
|
1329
|
+
const button = /* @__PURE__ */ jsx9(
|
|
550
1330
|
ToolbarButton2,
|
|
551
1331
|
{
|
|
552
1332
|
icon: item.icon,
|
|
553
1333
|
appearance: item.appearance === "primary" ? "primary" : "subtle",
|
|
554
1334
|
disabled: item.disabled,
|
|
555
|
-
onClick: item.onClick,
|
|
1335
|
+
onClick: item.menuItems?.length ? void 0 : item.onClick,
|
|
556
1336
|
children: item.label
|
|
557
1337
|
},
|
|
558
1338
|
item.id
|
|
559
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);
|
|
560
1360
|
}
|
|
561
|
-
var
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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;
|
|
568
1630
|
const hasFar = Boolean(farItems && farItems.length > 0);
|
|
569
1631
|
const hasOverflow = Boolean(overflowItems && overflowItems.length > 0);
|
|
570
1632
|
const hasPrimary = items.length > 0 || hasOverflow;
|
|
571
|
-
return /* @__PURE__ */
|
|
572
|
-
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: [
|
|
573
1635
|
items.map(renderToolbarButton),
|
|
574
|
-
hasOverflow && /* @__PURE__ */
|
|
575
|
-
/* @__PURE__ */
|
|
576
|
-
/* @__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)) }) })
|
|
577
1639
|
] })
|
|
578
1640
|
] }),
|
|
579
1641
|
hasFar && // marginLeft:auto keeps far items right-aligned whether or not a primary toolbar renders.
|
|
580
|
-
/* @__PURE__ */
|
|
1642
|
+
/* @__PURE__ */ jsx9(Toolbar2, { "aria-label": "Secondary commands", size, style: { marginLeft: "auto" }, children: farItems.map(renderToolbarButton) })
|
|
581
1643
|
] });
|
|
582
1644
|
};
|
|
583
1645
|
|
|
584
1646
|
// src/v9/containers/ActionBar.tsx
|
|
585
|
-
import { Button as
|
|
586
|
-
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";
|
|
587
1649
|
function renderButton(b) {
|
|
588
1650
|
const appearance = b.appearance === "primary" ? "primary" : b.appearance === "subtle" ? "subtle" : "secondary";
|
|
589
|
-
return /* @__PURE__ */
|
|
1651
|
+
return /* @__PURE__ */ jsx10(Button4, { appearance, icon: b.icon, disabled: b.disabled, onClick: b.onClick, children: b.label }, b.id);
|
|
590
1652
|
}
|
|
591
1653
|
var ActionBar = ({ buttons, alignment = "right", sticky = true, className }) => {
|
|
592
1654
|
const justify = alignment === "left" ? "flex-start" : alignment === "center" ? "center" : "flex-end";
|
|
@@ -599,19 +1661,19 @@ var ActionBar = ({ buttons, alignment = "right", sticky = true, className }) =>
|
|
|
599
1661
|
justifyContent: left.length ? "space-between" : justify,
|
|
600
1662
|
gap: 8,
|
|
601
1663
|
padding: "12px 24px",
|
|
602
|
-
borderTop: `1px solid ${
|
|
603
|
-
backgroundColor:
|
|
1664
|
+
borderTop: `1px solid ${tokens9.colorNeutralStroke2}`,
|
|
1665
|
+
backgroundColor: tokens9.colorNeutralBackground1,
|
|
604
1666
|
...sticky ? { position: "sticky", bottom: 0, zIndex: 1 } : {}
|
|
605
1667
|
};
|
|
606
|
-
return /* @__PURE__ */
|
|
607
|
-
left.length > 0 && /* @__PURE__ */
|
|
608
|
-
/* @__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) })
|
|
609
1671
|
] });
|
|
610
1672
|
};
|
|
611
1673
|
|
|
612
1674
|
// src/v9/containers/Footer.tsx
|
|
613
|
-
import { tokens as
|
|
614
|
-
import { jsx as
|
|
1675
|
+
import { tokens as tokens10 } from "@fluentui/react-components";
|
|
1676
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
615
1677
|
var Footer = ({ sticky = true, align = "right", className, children }) => {
|
|
616
1678
|
const justify = align === "left" ? "flex-start" : align === "center" ? "center" : "flex-end";
|
|
617
1679
|
const rootStyle = {
|
|
@@ -620,17 +1682,82 @@ var Footer = ({ sticky = true, align = "right", className, children }) => {
|
|
|
620
1682
|
justifyContent: justify,
|
|
621
1683
|
gap: 8,
|
|
622
1684
|
padding: "12px 24px",
|
|
623
|
-
borderTop: `1px solid ${
|
|
624
|
-
backgroundColor:
|
|
1685
|
+
borderTop: `1px solid ${tokens10.colorNeutralStroke2}`,
|
|
1686
|
+
backgroundColor: tokens10.colorNeutralBackground1,
|
|
625
1687
|
...sticky ? { position: "sticky", bottom: 0, zIndex: 1 } : {}
|
|
626
1688
|
};
|
|
627
|
-
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
|
+
);
|
|
628
1755
|
};
|
|
629
1756
|
|
|
630
1757
|
// src/v9/overlays/FormDialogSurface.tsx
|
|
631
|
-
import { Dialog, DialogSurface, Button as
|
|
1758
|
+
import { Dialog, DialogSurface, Button as Button5, Text as Text3, tokens as tokens11 } from "@fluentui/react-components";
|
|
632
1759
|
import { Dismiss20Regular } from "@fluentui/react-icons";
|
|
633
|
-
import { jsx as
|
|
1760
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
634
1761
|
var FormDialogSurface = ({
|
|
635
1762
|
isOpen,
|
|
636
1763
|
onDismiss,
|
|
@@ -654,10 +1781,10 @@ var FormDialogSurface = ({
|
|
|
654
1781
|
justifyContent: "space-between",
|
|
655
1782
|
gap: 12,
|
|
656
1783
|
padding: "12px 20px",
|
|
657
|
-
borderBottom: `1px solid ${
|
|
1784
|
+
borderBottom: `1px solid ${tokens11.colorNeutralStroke2}`
|
|
658
1785
|
};
|
|
659
|
-
const counterStyle = { fontSize:
|
|
660
|
-
return /* @__PURE__ */
|
|
1786
|
+
const counterStyle = { fontSize: tokens11.fontSizeBase200, color: tokens11.colorNeutralForeground3 };
|
|
1787
|
+
return /* @__PURE__ */ jsx13(
|
|
661
1788
|
Dialog,
|
|
662
1789
|
{
|
|
663
1790
|
open: isOpen,
|
|
@@ -665,7 +1792,7 @@ var FormDialogSurface = ({
|
|
|
665
1792
|
onOpenChange: (_e, data) => {
|
|
666
1793
|
if (!data.open) onDismiss?.();
|
|
667
1794
|
},
|
|
668
|
-
children: /* @__PURE__ */
|
|
1795
|
+
children: /* @__PURE__ */ jsxs8(
|
|
669
1796
|
DialogSurface,
|
|
670
1797
|
{
|
|
671
1798
|
className,
|
|
@@ -679,22 +1806,22 @@ var FormDialogSurface = ({
|
|
|
679
1806
|
padding: 0
|
|
680
1807
|
},
|
|
681
1808
|
children: [
|
|
682
|
-
showHeader && /* @__PURE__ */
|
|
683
|
-
/* @__PURE__ */
|
|
684
|
-
title && /* @__PURE__ */
|
|
685
|
-
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 })
|
|
686
1813
|
] }),
|
|
687
|
-
/* @__PURE__ */
|
|
688
|
-
recordCounter && /* @__PURE__ */
|
|
1814
|
+
/* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
1815
|
+
recordCounter && /* @__PURE__ */ jsxs8("span", { style: counterStyle, children: [
|
|
689
1816
|
recordCounter.current,
|
|
690
1817
|
" of ",
|
|
691
1818
|
recordCounter.total
|
|
692
1819
|
] }),
|
|
693
|
-
onDismiss && /* @__PURE__ */
|
|
1820
|
+
onDismiss && /* @__PURE__ */ jsx13(Button5, { appearance: "subtle", "aria-label": "Close", icon: /* @__PURE__ */ jsx13(Dismiss20Regular, {}), onClick: onDismiss })
|
|
694
1821
|
] })
|
|
695
1822
|
] }),
|
|
696
|
-
/* @__PURE__ */
|
|
697
|
-
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 })
|
|
698
1825
|
]
|
|
699
1826
|
}
|
|
700
1827
|
)
|
|
@@ -703,8 +1830,8 @@ var FormDialogSurface = ({
|
|
|
703
1830
|
};
|
|
704
1831
|
|
|
705
1832
|
// src/v9/overlays/ModalSurface.tsx
|
|
706
|
-
import { Dialog as Dialog2, DialogSurface as DialogSurface2, Text as Text4, tokens as
|
|
707
|
-
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";
|
|
708
1835
|
var ModalSurface = ({
|
|
709
1836
|
isOpen,
|
|
710
1837
|
onDismiss,
|
|
@@ -718,7 +1845,7 @@ var ModalSurface = ({
|
|
|
718
1845
|
children
|
|
719
1846
|
}) => {
|
|
720
1847
|
const sizing = autoSize ? { width: "auto", minWidth: MODAL_AUTOSIZE_MIN_WIDTH, maxWidth: "100%" } : { maxWidth: "95vw", width: `${dialogWidthPx({ width, size })}px` };
|
|
721
|
-
return /* @__PURE__ */
|
|
1848
|
+
return /* @__PURE__ */ jsx14(
|
|
722
1849
|
Dialog2,
|
|
723
1850
|
{
|
|
724
1851
|
open: isOpen,
|
|
@@ -726,14 +1853,14 @@ var ModalSurface = ({
|
|
|
726
1853
|
onOpenChange: (_e, data) => {
|
|
727
1854
|
if (!data.open) onDismiss?.();
|
|
728
1855
|
},
|
|
729
|
-
children: /* @__PURE__ */
|
|
730
|
-
title && /* @__PURE__ */
|
|
731
|
-
/* @__PURE__ */
|
|
732
|
-
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(
|
|
733
1860
|
"div",
|
|
734
1861
|
{
|
|
735
1862
|
style: {
|
|
736
|
-
borderTop: `1px solid ${
|
|
1863
|
+
borderTop: `1px solid ${tokens12.colorNeutralStroke2}`,
|
|
737
1864
|
padding: "12px 20px",
|
|
738
1865
|
display: "flex",
|
|
739
1866
|
justifyContent: "flex-end",
|
|
@@ -753,10 +1880,10 @@ import {
|
|
|
753
1880
|
DrawerHeader,
|
|
754
1881
|
DrawerHeaderTitle,
|
|
755
1882
|
DrawerBody,
|
|
756
|
-
Button as
|
|
1883
|
+
Button as Button6
|
|
757
1884
|
} from "@fluentui/react-components";
|
|
758
1885
|
import { Dismiss24Regular } from "@fluentui/react-icons";
|
|
759
|
-
import { jsx as
|
|
1886
|
+
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
760
1887
|
var PanelSurface = ({
|
|
761
1888
|
isOpen,
|
|
762
1889
|
onDismiss,
|
|
@@ -771,7 +1898,7 @@ var PanelSurface = ({
|
|
|
771
1898
|
}) => {
|
|
772
1899
|
const size = drawerSize ?? (width != null && width > 500 ? "medium" : "small");
|
|
773
1900
|
const customWidthStyle = width != null ? { width: `${width}px` } : void 0;
|
|
774
|
-
return /* @__PURE__ */
|
|
1901
|
+
return /* @__PURE__ */ jsxs10(
|
|
775
1902
|
OverlayDrawer,
|
|
776
1903
|
{
|
|
777
1904
|
open: isOpen,
|
|
@@ -785,16 +1912,16 @@ var PanelSurface = ({
|
|
|
785
1912
|
onDismiss?.();
|
|
786
1913
|
},
|
|
787
1914
|
children: [
|
|
788
|
-
/* @__PURE__ */
|
|
1915
|
+
/* @__PURE__ */ jsx15(DrawerHeader, { children: /* @__PURE__ */ jsx15(
|
|
789
1916
|
DrawerHeaderTitle,
|
|
790
1917
|
{
|
|
791
|
-
action: hasCloseButton && onDismiss ? /* @__PURE__ */
|
|
1918
|
+
action: hasCloseButton && onDismiss ? /* @__PURE__ */ jsx15(Button6, { appearance: "subtle", "aria-label": "Close", icon: /* @__PURE__ */ jsx15(Dismiss24Regular, {}), onClick: onDismiss }) : void 0,
|
|
792
1919
|
children: title
|
|
793
1920
|
}
|
|
794
1921
|
) }),
|
|
795
|
-
/* @__PURE__ */
|
|
796
|
-
/* @__PURE__ */
|
|
797
|
-
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 })
|
|
798
1925
|
] })
|
|
799
1926
|
]
|
|
800
1927
|
}
|
|
@@ -803,7 +1930,7 @@ var PanelSurface = ({
|
|
|
803
1930
|
|
|
804
1931
|
// src/v9/overlays/CalloutSurface.tsx
|
|
805
1932
|
import { Popover, PopoverSurface } from "@fluentui/react-components";
|
|
806
|
-
import { jsx as
|
|
1933
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
807
1934
|
function resolveTarget(target) {
|
|
808
1935
|
if (!target) return null;
|
|
809
1936
|
if (typeof target === "string") return document.querySelector(target);
|
|
@@ -824,7 +1951,7 @@ var CalloutSurface = ({
|
|
|
824
1951
|
if (!isOpen) return null;
|
|
825
1952
|
const el = resolveTarget(target);
|
|
826
1953
|
const positioning = { position, align, ...el ? { target: el } : {} };
|
|
827
|
-
return /* @__PURE__ */
|
|
1954
|
+
return /* @__PURE__ */ jsx16(
|
|
828
1955
|
Popover,
|
|
829
1956
|
{
|
|
830
1957
|
open: true,
|
|
@@ -834,14 +1961,14 @@ var CalloutSurface = ({
|
|
|
834
1961
|
onOpenChange: (_e, data) => {
|
|
835
1962
|
if (!data.open) onDismiss?.();
|
|
836
1963
|
},
|
|
837
|
-
children: /* @__PURE__ */
|
|
1964
|
+
children: /* @__PURE__ */ jsx16(PopoverSurface, { className, style: { width: calloutWidthPx(width), padding: 16 }, children })
|
|
838
1965
|
}
|
|
839
1966
|
);
|
|
840
1967
|
};
|
|
841
1968
|
|
|
842
1969
|
// src/v9/overlays/TooltipSurface.tsx
|
|
843
1970
|
import { Tooltip } from "@fluentui/react-components";
|
|
844
|
-
import { jsx as
|
|
1971
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
845
1972
|
var DELAY_MS = {
|
|
846
1973
|
zero: 0,
|
|
847
1974
|
medium: 250,
|
|
@@ -853,20 +1980,24 @@ var TooltipSurface = ({
|
|
|
853
1980
|
delay = "medium",
|
|
854
1981
|
relationship = "label",
|
|
855
1982
|
children
|
|
856
|
-
}) => /* @__PURE__ */
|
|
1983
|
+
}) => /* @__PURE__ */ jsx17(Tooltip, { content, relationship, positioning: position, showDelay: DELAY_MS[delay], children });
|
|
857
1984
|
export {
|
|
858
1985
|
ActionBar,
|
|
859
1986
|
BREAKPOINTS,
|
|
860
1987
|
CALLOUT_DEFAULT_WIDTH,
|
|
861
1988
|
CARD_REFLOW_WIDTH,
|
|
1989
|
+
CE_LABEL_ABOVE_BELOW_ROW_WIDTH,
|
|
1990
|
+
CE_TAB_COLUMN_MIN_WIDTH,
|
|
862
1991
|
CalloutSurface,
|
|
863
1992
|
CommandSurface,
|
|
864
1993
|
DIALOG_SIZE_PX,
|
|
865
1994
|
DensityContext,
|
|
1995
|
+
FieldRow,
|
|
866
1996
|
Footer,
|
|
867
1997
|
FormDialogSurface,
|
|
868
1998
|
FormHeader,
|
|
869
1999
|
FormSurface,
|
|
2000
|
+
LookContext,
|
|
870
2001
|
MODAL_AUTOSIZE_MIN_WIDTH,
|
|
871
2002
|
ModalSurface,
|
|
872
2003
|
PANEL_DEFAULT_WIDTH,
|
|
@@ -876,11 +2007,16 @@ export {
|
|
|
876
2007
|
Section,
|
|
877
2008
|
SectionCard,
|
|
878
2009
|
SectionHeader,
|
|
2010
|
+
TabColumns,
|
|
879
2011
|
TooltipSurface,
|
|
880
2012
|
calloutFormDefaults,
|
|
881
2013
|
calloutWidthPx,
|
|
2014
|
+
ceFieldRowFirstOffset,
|
|
2015
|
+
ceForm,
|
|
2016
|
+
cePresenceBadgeStyle,
|
|
882
2017
|
clampSpan,
|
|
883
2018
|
colors,
|
|
2019
|
+
createDynamicsCeTheme,
|
|
884
2020
|
createDynamicsV9DarkTheme,
|
|
885
2021
|
createDynamicsV9Theme,
|
|
886
2022
|
densityScale,
|
|
@@ -888,17 +2024,20 @@ export {
|
|
|
888
2024
|
dialogWidthCss,
|
|
889
2025
|
dialogWidthPx,
|
|
890
2026
|
dynamicsBrandRamp,
|
|
2027
|
+
dynamicsCeTheme,
|
|
891
2028
|
dynamicsV9DarkTheme,
|
|
892
2029
|
dynamicsV9Theme,
|
|
893
2030
|
fieldGridStyle,
|
|
894
2031
|
fieldRowStyle,
|
|
895
2032
|
gridTemplateForColumns,
|
|
896
2033
|
layout,
|
|
2034
|
+
normalizeColumnShares,
|
|
897
2035
|
panelCustomWidthPx,
|
|
898
2036
|
panelKindFromWidth,
|
|
899
2037
|
radius,
|
|
900
2038
|
resolveBreakpoint,
|
|
901
2039
|
resolveResponsiveValue,
|
|
2040
|
+
resolveTabColumnWidths,
|
|
902
2041
|
scaleSpacing,
|
|
903
2042
|
sectionStackingStyle,
|
|
904
2043
|
spacing,
|
|
@@ -907,6 +2046,7 @@ export {
|
|
|
907
2046
|
useContainerSize,
|
|
908
2047
|
useContainerWidth,
|
|
909
2048
|
useDensity,
|
|
2049
|
+
useLook,
|
|
910
2050
|
useMediaQuery,
|
|
911
2051
|
useResponsiveValue
|
|
912
2052
|
};
|