@pstrikez/fluent-winui-theme 0.1.1 → 0.2.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/dist/base.css +1 -1
- package/dist/components/ui/confirm-dialog.d.ts +4 -1
- package/dist/components/ui/confirm-flyout.d.ts +14 -0
- package/dist/components/ui/data-table.d.ts +72 -0
- package/dist/components/ui/dialog-shell.d.ts +1 -0
- package/dist/components/ui/file-drop-zone.d.ts +42 -0
- package/dist/components/ui/metric.d.ts +34 -0
- package/dist/components/ui/number-box.d.ts +36 -0
- package/dist/components/ui/outcome-toast.d.ts +9 -1
- package/dist/components/ui/pager.d.ts +23 -0
- package/dist/components/ui/property-list.d.ts +19 -0
- package/dist/components/ui/tab-view.d.ts +25 -0
- package/dist/components/ui/tooltip-icon-button.d.ts +5 -2
- package/dist/components/ui/use-confirm.d.ts +18 -0
- package/dist/i18n/translation.d.ts +46 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1968 -466
- package/dist/index.js.map +4 -4
- package/dist/winui/controls/dialog.css.d.ts +1 -1
- package/dist/winui/controls/spin-button.css.d.ts +1 -0
- package/dist/winui.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1485,7 +1485,7 @@ var require_prism = __commonJS({
|
|
|
1485
1485
|
import * as fluentNamespace from "@fluentui/react-components";
|
|
1486
1486
|
|
|
1487
1487
|
// src/winui/appearance.ts
|
|
1488
|
-
import { CheckmarkCircleFilled, ChevronDown12Regular, DismissCircleFilled, ErrorCircleFilled, InfoFilled } from "@fluentui/react-icons";
|
|
1488
|
+
import { CheckmarkCircleFilled, ChevronDown12Regular, ChevronUp12Regular, DismissCircleFilled, ErrorCircleFilled, InfoFilled } from "@fluentui/react-icons";
|
|
1489
1489
|
import * as React2 from "react";
|
|
1490
1490
|
|
|
1491
1491
|
// src/winui/wrap.ts
|
|
@@ -1562,6 +1562,16 @@ var withWinuiAppearance = (components) => {
|
|
|
1562
1562
|
...props,
|
|
1563
1563
|
expandIcon: props.expandIcon === void 0 ? { children: React2.createElement(ChevronDown12Regular) } : props.expandIcon
|
|
1564
1564
|
}));
|
|
1565
|
+
const withSpinGlyph = (slot, Glyph) => {
|
|
1566
|
+
if (slot === null) return slot;
|
|
1567
|
+
const slotProps2 = resolveSlotProps(slot);
|
|
1568
|
+
return slotProps2?.children === void 0 ? { ...slotProps2, children: React2.createElement(Glyph) } : slotProps2;
|
|
1569
|
+
};
|
|
1570
|
+
const winuiSpinGlyphs = (component) => wrapFluent(component, (props) => ({
|
|
1571
|
+
...props,
|
|
1572
|
+
incrementButton: withSpinGlyph(props.incrementButton, ChevronUp12Regular),
|
|
1573
|
+
decrementButton: withSpinGlyph(props.decrementButton, ChevronDown12Regular)
|
|
1574
|
+
}));
|
|
1565
1575
|
return {
|
|
1566
1576
|
...components,
|
|
1567
1577
|
AccordionHeader: winuiChevron(components.AccordionHeader),
|
|
@@ -1578,6 +1588,7 @@ var withWinuiAppearance = (components) => {
|
|
|
1578
1588
|
Input: stamp(components.Input, appearance("outline", rootAndPrimary)),
|
|
1579
1589
|
Textarea: stamp(components.Textarea, appearance("outline", rootAndPrimary)),
|
|
1580
1590
|
Select: stamp(components.Select, appearance("outline", rootAndPrimary)),
|
|
1591
|
+
SpinButton: winuiSpinGlyphs(stamp(components.SpinButton, appearance("outline", rootAndPrimary))),
|
|
1581
1592
|
Combobox: stamp(components.Combobox, appearance("outline", rootAndPrimary)),
|
|
1582
1593
|
Dropdown: stamp(components.Dropdown, appearance("outline", rootAndPrimary)),
|
|
1583
1594
|
Card: stamp(components.Card, appearance("filled", rootIsPrimary)),
|
|
@@ -1743,11 +1754,11 @@ var withWinuiDrag = (components) => {
|
|
|
1743
1754
|
const suppressClickRef = React4.useRef(false);
|
|
1744
1755
|
const settleTimerRef = React4.useRef(void 0);
|
|
1745
1756
|
React4.useEffect(() => () => clearTimeout(settleTimerRef.current), []);
|
|
1746
|
-
const end = (gesture,
|
|
1757
|
+
const end = (gesture, toggle2, fromDrag) => {
|
|
1747
1758
|
gestureRef.current = null;
|
|
1748
1759
|
gesture.root.removeAttribute(DRAGGING);
|
|
1749
1760
|
gesture.root.style.removeProperty(DRAG_X);
|
|
1750
|
-
if (
|
|
1761
|
+
if (toggle2) {
|
|
1751
1762
|
if (fromDrag) {
|
|
1752
1763
|
gesture.root.setAttribute(SETTLING, "");
|
|
1753
1764
|
clearTimeout(settleTimerRef.current);
|
|
@@ -2704,29 +2715,15 @@ var readableTone = (hex, surface) => {
|
|
|
2704
2715
|
};
|
|
2705
2716
|
|
|
2706
2717
|
// src/components/ui/badge-hue.ts
|
|
2707
|
-
var { makeStyles: makeStyles2 } = fluentComponents;
|
|
2708
2718
|
var HARDEST_BADGE_SURFACE = { light: "#EBF3FC", dark: "#434343" };
|
|
2709
2719
|
var BADGE_FILL_ALPHA = 0.1;
|
|
2710
2720
|
var BADGE_STROKE_ALPHA = 0.35;
|
|
2711
|
-
var useStyles2 = makeStyles2({
|
|
2712
|
-
scheme: {
|
|
2713
|
-
"--fwt-badge-fill": "var(--fwt-badge-fill-light)",
|
|
2714
|
-
"--fwt-chip-stroke": "var(--fwt-badge-stroke-light)",
|
|
2715
|
-
"--fwt-badge-label": "var(--fwt-badge-label-light)",
|
|
2716
|
-
"@media (prefers-color-scheme: dark)": {
|
|
2717
|
-
"--fwt-badge-fill": "var(--fwt-badge-fill-dark)",
|
|
2718
|
-
"--fwt-chip-stroke": "var(--fwt-badge-stroke-dark)",
|
|
2719
|
-
"--fwt-badge-label": "var(--fwt-badge-label-dark)"
|
|
2720
|
-
}
|
|
2721
|
-
}
|
|
2722
|
-
});
|
|
2723
2721
|
var useBadgeHue = (hue) => {
|
|
2724
|
-
const styles = useStyles2();
|
|
2725
2722
|
const pair = typeof hue === "string" ? { light: hue, dark: hue } : hue;
|
|
2726
2723
|
const fill = { light: alphaColor(pair.light, BADGE_FILL_ALPHA), dark: alphaColor(pair.dark, BADGE_FILL_ALPHA) };
|
|
2727
2724
|
const label = (own, surface) => readableTone(own, blendHex(own, BADGE_FILL_ALPHA, surface));
|
|
2728
2725
|
return {
|
|
2729
|
-
className:
|
|
2726
|
+
className: "fwt-badge-hue",
|
|
2730
2727
|
style: {
|
|
2731
2728
|
"--fwt-badge-fill-light": fill.light,
|
|
2732
2729
|
"--fwt-badge-fill-dark": fill.dark,
|
|
@@ -2743,8 +2740,8 @@ var useBadgeHue = (hue) => {
|
|
|
2743
2740
|
|
|
2744
2741
|
// src/components/ui/chip.tsx
|
|
2745
2742
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2746
|
-
var { Tag, makeStyles:
|
|
2747
|
-
var
|
|
2743
|
+
var { Tag, makeStyles: makeStyles2, mergeClasses } = fluentComponents;
|
|
2744
|
+
var useStyles2 = makeStyles2({
|
|
2748
2745
|
// Fluent sizes the chip to its content, so a long label carries the chip
|
|
2749
2746
|
// past the column that holds it.
|
|
2750
2747
|
root: { maxWidth: "100%" },
|
|
@@ -2762,7 +2759,7 @@ var useStyles3 = makeStyles3({
|
|
|
2762
2759
|
}
|
|
2763
2760
|
});
|
|
2764
2761
|
function Chip({ children, className, icon, style, textRef, ...trigger }) {
|
|
2765
|
-
const styles =
|
|
2762
|
+
const styles = useStyles2();
|
|
2766
2763
|
return /* @__PURE__ */ jsx6(
|
|
2767
2764
|
Tag,
|
|
2768
2765
|
{
|
|
@@ -5567,7 +5564,30 @@ var en = {
|
|
|
5567
5564
|
"common.discard.discard": "Discard",
|
|
5568
5565
|
"common.copy.action": "Copy",
|
|
5569
5566
|
"common.copy.copied": "Copied",
|
|
5570
|
-
"common.copy.failed": "Copy failed"
|
|
5567
|
+
"common.copy.failed": "Copy failed",
|
|
5568
|
+
"numberBox.increment": "Increase value",
|
|
5569
|
+
"numberBox.decrement": "Decrease value",
|
|
5570
|
+
"fileDropZone.browse": "Browse files",
|
|
5571
|
+
"fileDropZone.dropHint": "Drop files here",
|
|
5572
|
+
"fileDropZone.remove": "Remove file",
|
|
5573
|
+
"pager.label": "Pagination",
|
|
5574
|
+
"pager.first": "First page",
|
|
5575
|
+
"pager.previous": "Previous page",
|
|
5576
|
+
"pager.next": "Next page",
|
|
5577
|
+
"pager.last": "Last page",
|
|
5578
|
+
"pager.page": "Page {n}",
|
|
5579
|
+
"pager.pageSize": "Items per page",
|
|
5580
|
+
"pager.perPage": "{n} / page",
|
|
5581
|
+
"pager.total": "Total {n} items",
|
|
5582
|
+
"dataTable.empty": "No data",
|
|
5583
|
+
"dataTable.loading": "Loading",
|
|
5584
|
+
"dataTable.selectAll": "Select all rows",
|
|
5585
|
+
"dataTable.selectRow": "Select row",
|
|
5586
|
+
"dataTable.expandRow": "Expand row",
|
|
5587
|
+
"dataTable.collapseRow": "Collapse row",
|
|
5588
|
+
"tabView.close": "Close tab",
|
|
5589
|
+
"tabView.scrollBackward": "Scroll tabs left",
|
|
5590
|
+
"tabView.scrollForward": "Scroll tabs right"
|
|
5571
5591
|
};
|
|
5572
5592
|
var zhHans = {
|
|
5573
5593
|
"common.on": "\u5F00",
|
|
@@ -5582,7 +5602,30 @@ var zhHans = {
|
|
|
5582
5602
|
"common.discard.discard": "\u653E\u5F03",
|
|
5583
5603
|
"common.copy.action": "\u590D\u5236",
|
|
5584
5604
|
"common.copy.copied": "\u5DF2\u590D\u5236",
|
|
5585
|
-
"common.copy.failed": "\u590D\u5236\u5931\u8D25"
|
|
5605
|
+
"common.copy.failed": "\u590D\u5236\u5931\u8D25",
|
|
5606
|
+
"numberBox.increment": "\u589E\u5927",
|
|
5607
|
+
"numberBox.decrement": "\u51CF\u5C0F",
|
|
5608
|
+
"fileDropZone.browse": "\u6D4F\u89C8\u6587\u4EF6",
|
|
5609
|
+
"fileDropZone.dropHint": "\u5C06\u6587\u4EF6\u62D6\u653E\u5230\u6B64\u5904",
|
|
5610
|
+
"fileDropZone.remove": "\u79FB\u9664\u6587\u4EF6",
|
|
5611
|
+
"pager.label": "\u5206\u9875",
|
|
5612
|
+
"pager.first": "\u7B2C\u4E00\u9875",
|
|
5613
|
+
"pager.previous": "\u4E0A\u4E00\u9875",
|
|
5614
|
+
"pager.next": "\u4E0B\u4E00\u9875",
|
|
5615
|
+
"pager.last": "\u6700\u540E\u4E00\u9875",
|
|
5616
|
+
"pager.page": "\u7B2C {n} \u9875",
|
|
5617
|
+
"pager.pageSize": "\u6BCF\u9875\u6761\u6570",
|
|
5618
|
+
"pager.perPage": "{n} \u6761/\u9875",
|
|
5619
|
+
"pager.total": "\u5171 {n} \u6761",
|
|
5620
|
+
"dataTable.empty": "\u6682\u65E0\u6570\u636E",
|
|
5621
|
+
"dataTable.loading": "\u52A0\u8F7D\u4E2D",
|
|
5622
|
+
"dataTable.selectAll": "\u9009\u62E9\u5168\u90E8\u884C",
|
|
5623
|
+
"dataTable.selectRow": "\u9009\u62E9\u6B64\u884C",
|
|
5624
|
+
"dataTable.expandRow": "\u5C55\u5F00\u6B64\u884C",
|
|
5625
|
+
"dataTable.collapseRow": "\u6536\u8D77\u6B64\u884C",
|
|
5626
|
+
"tabView.close": "\u5173\u95ED\u6807\u7B7E\u9875",
|
|
5627
|
+
"tabView.scrollBackward": "\u5411\u5DE6\u6EDA\u52A8\u6807\u7B7E\u9875",
|
|
5628
|
+
"tabView.scrollForward": "\u5411\u53F3\u6EDA\u52A8\u6807\u7B7E\u9875"
|
|
5586
5629
|
};
|
|
5587
5630
|
var winuiStringsByLocale = { en, "zh-Hans": zhHans };
|
|
5588
5631
|
var StringsContext = createContext2(en);
|
|
@@ -5719,8 +5762,8 @@ var Textarea = forwardRef3(
|
|
|
5719
5762
|
|
|
5720
5763
|
// src/components/ui/choice-group.tsx
|
|
5721
5764
|
import { jsx as jsx10, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
5722
|
-
var { makeStyles:
|
|
5723
|
-
var
|
|
5765
|
+
var { makeStyles: makeStyles3, tokens } = fluentComponents;
|
|
5766
|
+
var useStyles3 = makeStyles3({
|
|
5724
5767
|
// The items sit flush: SelectorBar's horizontal StackLayout states no spacing,
|
|
5725
5768
|
// so each item's 12px of side padding is the whole distance between one label
|
|
5726
5769
|
// and the next. SelectorBarItemSpacing, 8, is the icon-to-text gap and these
|
|
@@ -5870,7 +5913,7 @@ function ChoiceGroup({
|
|
|
5870
5913
|
readOnly,
|
|
5871
5914
|
value
|
|
5872
5915
|
}) {
|
|
5873
|
-
const styles =
|
|
5916
|
+
const styles = useStyles3();
|
|
5874
5917
|
const name = useId();
|
|
5875
5918
|
const selectedIndex = items.findIndex((item) => item.value === value);
|
|
5876
5919
|
const handleKeyDown = (event) => {
|
|
@@ -6829,8 +6872,8 @@ var useCopyToClipboard = () => {
|
|
|
6829
6872
|
|
|
6830
6873
|
// src/components/ui/code-block.tsx
|
|
6831
6874
|
import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
6832
|
-
var { Button: Button2, makeStyles:
|
|
6833
|
-
var
|
|
6875
|
+
var { Button: Button2, makeStyles: makeStyles4, mergeClasses: mergeClasses4 } = fluentComponents;
|
|
6876
|
+
var useStyles4 = makeStyles4({
|
|
6834
6877
|
// ControlCornerRadius. The clip is why the region's focus visual below is
|
|
6835
6878
|
// drawn inside the viewport rather than around it.
|
|
6836
6879
|
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/Expander/Expander.xaml#L26
|
|
@@ -6895,7 +6938,7 @@ var useStyles5 = makeStyles5({
|
|
|
6895
6938
|
});
|
|
6896
6939
|
function CodeBlock({ code, collapsed = false, copyOutcome, disabled = false, header, language, onCopy, wrap = false }) {
|
|
6897
6940
|
const { t: t2 } = useTranslation();
|
|
6898
|
-
const styles =
|
|
6941
|
+
const styles = useStyles4();
|
|
6899
6942
|
const copyLabel = useCopyLabel();
|
|
6900
6943
|
const highlighted = useMemo2(
|
|
6901
6944
|
() => highlight(code, language),
|
|
@@ -6931,7 +6974,8 @@ import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
|
6931
6974
|
var { Dialog, DialogBody, DialogContent, DialogSurface, mergeClasses: mergeClasses5 } = fluentComponents;
|
|
6932
6975
|
var surfaceWidthClasses = {
|
|
6933
6976
|
standard: "",
|
|
6934
|
-
editor: "fwt-dialog-shell--editor"
|
|
6977
|
+
editor: "fwt-dialog-shell--editor",
|
|
6978
|
+
wide: "fwt-dialog-shell--wide"
|
|
6935
6979
|
};
|
|
6936
6980
|
function DialogShell({ actions, children, onExited, onOpenChange, onSubmit, open, surfaceClassName, title, width = "standard" }) {
|
|
6937
6981
|
return /* @__PURE__ */ jsx12(
|
|
@@ -7011,8 +7055,8 @@ function OutcomeMessageBar({
|
|
|
7011
7055
|
|
|
7012
7056
|
// src/components/ui/confirm-dialog.tsx
|
|
7013
7057
|
import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
7014
|
-
var { Button: Button4, DialogActions, DialogTitle, makeStyles:
|
|
7015
|
-
var
|
|
7058
|
+
var { Button: Button4, DialogActions, DialogTitle, makeStyles: makeStyles5, mergeClasses: mergeClasses6 } = fluentComponents;
|
|
7059
|
+
var useStyles5 = makeStyles5({
|
|
7016
7060
|
// The label is StaticInverted because the fill does not follow the theme.
|
|
7017
7061
|
// Not OnBrand: ../../winui/theme.ts re-points it at WinUI's
|
|
7018
7062
|
// TextOnAccentFillColorPrimary, which goes black in dark, reading 3.46:1 at
|
|
@@ -7042,6 +7086,7 @@ var useStyles6 = makeStyles6({
|
|
|
7042
7086
|
}
|
|
7043
7087
|
}
|
|
7044
7088
|
});
|
|
7089
|
+
var useDangerFillClass = () => useStyles5().danger;
|
|
7045
7090
|
function ConfirmDialog({
|
|
7046
7091
|
actionIntent = "danger",
|
|
7047
7092
|
actionLabel,
|
|
@@ -7058,7 +7103,7 @@ function ConfirmDialog({
|
|
|
7058
7103
|
title
|
|
7059
7104
|
}) {
|
|
7060
7105
|
const { t: t2 } = useTranslation();
|
|
7061
|
-
const styles =
|
|
7106
|
+
const styles = useStyles5();
|
|
7062
7107
|
return /* @__PURE__ */ jsx14(
|
|
7063
7108
|
DialogShell,
|
|
7064
7109
|
{
|
|
@@ -7092,15 +7137,88 @@ function ConfirmDialog({
|
|
|
7092
7137
|
surfaceClassName: "!w-[min(430px,calc(100vw-48px))]",
|
|
7093
7138
|
title: /* @__PURE__ */ jsx14(DialogTitle, { children: title }),
|
|
7094
7139
|
children: /* @__PURE__ */ jsxs6("div", { className: "grid gap-3 min-w-0", children: [
|
|
7095
|
-
/* @__PURE__ */ jsx14("span", { children: message }),
|
|
7140
|
+
message && /* @__PURE__ */ jsx14("span", { children: message }),
|
|
7096
7141
|
error && /* @__PURE__ */ jsx14(OutcomeMessageBar, { onDismiss: onDismissError, children: error })
|
|
7097
7142
|
] })
|
|
7098
7143
|
}
|
|
7099
7144
|
);
|
|
7100
7145
|
}
|
|
7101
7146
|
|
|
7147
|
+
// src/components/ui/confirm-flyout.tsx
|
|
7148
|
+
import { useCallback as useCallback4, useState as useState5 } from "react";
|
|
7149
|
+
import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
7150
|
+
var { Button: Button5, Popover, PopoverSurface, PopoverTrigger, Spinner, Text, mergeClasses: mergeClasses7 } = fluentComponents;
|
|
7151
|
+
var errorText = (error) => error instanceof Error ? error.message : String(error);
|
|
7152
|
+
function ConfirmFlyout({
|
|
7153
|
+
cancelLabel,
|
|
7154
|
+
children,
|
|
7155
|
+
confirmLabel,
|
|
7156
|
+
disabled = false,
|
|
7157
|
+
intent = "danger",
|
|
7158
|
+
message,
|
|
7159
|
+
onConfirm,
|
|
7160
|
+
positioning,
|
|
7161
|
+
title
|
|
7162
|
+
}) {
|
|
7163
|
+
const { t: t2 } = useTranslation();
|
|
7164
|
+
const dangerFill = useDangerFillClass();
|
|
7165
|
+
const [open, setOpen] = useState5(false);
|
|
7166
|
+
const [busy, setBusy] = useState5(false);
|
|
7167
|
+
const [error, setError] = useState5(null);
|
|
7168
|
+
const changeOpen = useCallback4((next) => {
|
|
7169
|
+
if (busy || next && disabled) return;
|
|
7170
|
+
setError(null);
|
|
7171
|
+
setOpen(next);
|
|
7172
|
+
}, [busy, disabled]);
|
|
7173
|
+
const confirm = async () => {
|
|
7174
|
+
setError(null);
|
|
7175
|
+
setBusy(true);
|
|
7176
|
+
try {
|
|
7177
|
+
await onConfirm();
|
|
7178
|
+
setOpen(false);
|
|
7179
|
+
} catch (caught) {
|
|
7180
|
+
setError(errorText(caught));
|
|
7181
|
+
} finally {
|
|
7182
|
+
setBusy(false);
|
|
7183
|
+
}
|
|
7184
|
+
};
|
|
7185
|
+
return /* @__PURE__ */ jsxs7(
|
|
7186
|
+
Popover,
|
|
7187
|
+
{
|
|
7188
|
+
onOpenChange: (_2, data) => changeOpen(data.open),
|
|
7189
|
+
open: open && !disabled,
|
|
7190
|
+
positioning,
|
|
7191
|
+
trapFocus: true,
|
|
7192
|
+
children: [
|
|
7193
|
+
/* @__PURE__ */ jsx15(PopoverTrigger, { disableButtonEnhancement: true, children }),
|
|
7194
|
+
/* @__PURE__ */ jsx15(PopoverSurface, { "aria-label": title, children: /* @__PURE__ */ jsxs7("div", { className: "grid gap-3 min-w-0 max-w-[min(320px,calc(100vw-48px))]", children: [
|
|
7195
|
+
title && /* @__PURE__ */ jsx15(Text, { weight: "semibold", children: title }),
|
|
7196
|
+
/* @__PURE__ */ jsx15(Text, { children: message }),
|
|
7197
|
+
error && /* @__PURE__ */ jsx15(OutcomeMessageBar, { onDismiss: () => setError(null), children: error }),
|
|
7198
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-2", children: [
|
|
7199
|
+
/* @__PURE__ */ jsx15(
|
|
7200
|
+
Button5,
|
|
7201
|
+
{
|
|
7202
|
+
appearance: "primary",
|
|
7203
|
+
className: mergeClasses7("!whitespace-nowrap", intent === "danger" && dangerFill),
|
|
7204
|
+
disabledFocusable: busy,
|
|
7205
|
+
icon: busy ? /* @__PURE__ */ jsx15(Spinner, { size: "tiny" }) : void 0,
|
|
7206
|
+
onClick: () => {
|
|
7207
|
+
void confirm();
|
|
7208
|
+
},
|
|
7209
|
+
children: confirmLabel
|
|
7210
|
+
}
|
|
7211
|
+
),
|
|
7212
|
+
cancelLabel !== void 0 && /* @__PURE__ */ jsx15(Button5, { className: "!whitespace-nowrap", disabled: busy, onClick: () => changeOpen(false), children: cancelLabel || t2("common.cancel") })
|
|
7213
|
+
] })
|
|
7214
|
+
] }) })
|
|
7215
|
+
]
|
|
7216
|
+
}
|
|
7217
|
+
);
|
|
7218
|
+
}
|
|
7219
|
+
|
|
7102
7220
|
// src/components/ui/danger.ts
|
|
7103
|
-
var { buttonClassNames, makeStyles:
|
|
7221
|
+
var { buttonClassNames, makeStyles: makeStyles6 } = fluentComponents;
|
|
7104
7222
|
var RED = "var(--winui-system-fill-critical) !important";
|
|
7105
7223
|
var FORCED = "Highlight !important";
|
|
7106
7224
|
var ICON = `& .${buttonClassNames.icon}`;
|
|
@@ -7110,7 +7228,7 @@ var PRESSED = `${ENABLED}:active`;
|
|
|
7110
7228
|
var KEYBOARD = `${ENABLED}[data-fui-focus-visible]`;
|
|
7111
7229
|
var buttonPaint = { color: RED, [ICON]: { color: RED } };
|
|
7112
7230
|
var buttonForcedPaint = { color: FORCED, [ICON]: { color: FORCED } };
|
|
7113
|
-
var
|
|
7231
|
+
var useStyles6 = makeStyles6({
|
|
7114
7232
|
button: {
|
|
7115
7233
|
[HOVER]: buttonPaint,
|
|
7116
7234
|
[PRESSED]: buttonPaint,
|
|
@@ -7132,12 +7250,16 @@ var useStyles7 = makeStyles7({
|
|
|
7132
7250
|
}
|
|
7133
7251
|
}
|
|
7134
7252
|
});
|
|
7135
|
-
var useDangerActionClasses = () =>
|
|
7136
|
-
var useTextStyles =
|
|
7253
|
+
var useDangerActionClasses = () => useStyles6();
|
|
7254
|
+
var useTextStyles = makeStyles6({
|
|
7137
7255
|
danger: { color: "var(--winui-system-fill-critical)" }
|
|
7138
7256
|
});
|
|
7139
7257
|
var useDangerTextClass = () => useTextStyles().danger;
|
|
7140
7258
|
|
|
7259
|
+
// src/components/ui/data-table.tsx
|
|
7260
|
+
import { ChevronDown16Regular, ChevronRight16Regular } from "@fluentui/react-icons";
|
|
7261
|
+
import { useMemo as useMemo3, useState as useState6 } from "react";
|
|
7262
|
+
|
|
7141
7263
|
// src/components/ui/layout.ts
|
|
7142
7264
|
var TIGHT_STACK_CLASS = "grid gap-1";
|
|
7143
7265
|
var HEADER_ROW_CLASS = "flex items-center justify-between min-w-0 max-[900px]:flex-col max-[900px]:items-stretch";
|
|
@@ -7149,19 +7271,6 @@ var SCROLLPORT_FILL_CLASS = "h-full min-h-max";
|
|
|
7149
7271
|
var CONTROL_ROW_CLASS = "!min-h-[34px]";
|
|
7150
7272
|
var CHECKBOX_LIST_CLASS = "gap-x-2 gap-y-1";
|
|
7151
7273
|
|
|
7152
|
-
// src/components/ui/dashboard-page-header.tsx
|
|
7153
|
-
import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
7154
|
-
var { Text, mergeClasses: mergeClasses7 } = fluentComponents;
|
|
7155
|
-
function DashboardPageHeader({ actions, className, description, title }) {
|
|
7156
|
-
return /* @__PURE__ */ jsxs7("header", { className: mergeClasses7(HEADER_ROW_CLASS, "gap-[18px]", className), children: [
|
|
7157
|
-
/* @__PURE__ */ jsxs7("div", { className: "grid gap-1.5 min-w-0", children: [
|
|
7158
|
-
/* @__PURE__ */ jsx15(Text, { as: "h1", size: 700, weight: "semibold", className: "m-0", children: title }),
|
|
7159
|
-
description !== void 0 && /* @__PURE__ */ jsx15(Text, { size: 200, className: "text-fui-fg2 max-w-[760px]", children: description })
|
|
7160
|
-
] }),
|
|
7161
|
-
actions !== void 0 && /* @__PURE__ */ jsx15("div", { className: "flex items-center gap-2 flex-none max-[900px]:justify-start", children: actions })
|
|
7162
|
-
] });
|
|
7163
|
-
}
|
|
7164
|
-
|
|
7165
7274
|
// src/components/ui/empty-state.tsx
|
|
7166
7275
|
import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
7167
7276
|
var { Text: Text2, mergeClasses: mergeClasses8 } = fluentComponents;
|
|
@@ -7182,201 +7291,994 @@ function EmptyStateLine({ children, className }) {
|
|
|
7182
7291
|
return /* @__PURE__ */ jsx16(Text2, { block: true, size: 300, className: mergeClasses8("text-fui-fg2", className), children });
|
|
7183
7292
|
}
|
|
7184
7293
|
|
|
7185
|
-
// src/components/ui/
|
|
7294
|
+
// src/components/ui/pager.tsx
|
|
7295
|
+
import {
|
|
7296
|
+
ChevronLeft12Regular,
|
|
7297
|
+
ChevronRight12Regular,
|
|
7298
|
+
MoreHorizontal16Regular,
|
|
7299
|
+
Next16Regular,
|
|
7300
|
+
Previous16Regular
|
|
7301
|
+
} from "@fluentui/react-icons";
|
|
7186
7302
|
import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
7187
|
-
var { Text: Text3 } = fluentComponents;
|
|
7188
|
-
function
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
/* @__PURE__ */ jsx17(Text3, { align: "center", as: "h1", size: 700, weight: "semibold", children: title }),
|
|
7192
|
-
message !== void 0 && /* @__PURE__ */ jsx17(Text3, { align: "center", as: "p", className: "text-fui-fg2", size: 300, children: message })
|
|
7193
|
-
] }),
|
|
7194
|
-
children,
|
|
7195
|
-
action !== void 0 && /* @__PURE__ */ jsx17("div", { className: "fwt-error-shell-actions", children: action })
|
|
7196
|
-
] }) });
|
|
7303
|
+
var { Button: Button6, Option: Option2, Text: Text3, Tooltip: Tooltip2, makeStyles: makeStyles7, mergeClasses: mergeClasses9 } = fluentComponents;
|
|
7304
|
+
function pagerPageCount(total, pageSize) {
|
|
7305
|
+
if (!(pageSize > 0) || !(total > 0)) return 1;
|
|
7306
|
+
return Math.ceil(total / pageSize);
|
|
7197
7307
|
}
|
|
7198
|
-
function
|
|
7199
|
-
return
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7308
|
+
function pagerPageWindow(page, pageCount) {
|
|
7309
|
+
if (pageCount < 8) return Array.from({ length: Math.max(pageCount, 0) }, (_2, index) => index + 1);
|
|
7310
|
+
const selectedIndex = page - 1;
|
|
7311
|
+
if (selectedIndex < 4) return [1, 2, 3, 4, 5, "end-ellipsis", pageCount];
|
|
7312
|
+
if (selectedIndex >= pageCount - 4) return [1, "start-ellipsis", pageCount - 4, pageCount - 3, pageCount - 2, pageCount - 1, pageCount];
|
|
7313
|
+
return [1, "start-ellipsis", page - 1, page, page + 1, "end-ellipsis", pageCount];
|
|
7314
|
+
}
|
|
7315
|
+
var clampPage = (page, pageCount) => Math.min(Math.max(Math.trunc(page) || 1, 1), pageCount);
|
|
7316
|
+
var useStyles7 = makeStyles7({
|
|
7317
|
+
navButton: {
|
|
7318
|
+
height: "40px !important",
|
|
7319
|
+
minWidth: "40px !important",
|
|
7320
|
+
padding: "0 !important",
|
|
7321
|
+
width: "40px !important"
|
|
7322
|
+
},
|
|
7323
|
+
numberButton: {
|
|
7324
|
+
height: "20px !important",
|
|
7325
|
+
minHeight: "20px !important",
|
|
7326
|
+
minWidth: "32px !important",
|
|
7327
|
+
paddingBlock: "0 !important",
|
|
7328
|
+
paddingInline: "0 !important"
|
|
7329
|
+
},
|
|
7330
|
+
selected: {
|
|
7331
|
+
position: "relative",
|
|
7332
|
+
"::after": {
|
|
7333
|
+
backgroundColor: "var(--winui-accent-fill-default)",
|
|
7334
|
+
borderRadius: "1px",
|
|
7335
|
+
bottom: "-10px",
|
|
7336
|
+
content: '""',
|
|
7337
|
+
height: "2px",
|
|
7338
|
+
insetInline: 0,
|
|
7339
|
+
position: "absolute",
|
|
7340
|
+
"@media (forced-colors: active)": { backgroundColor: "Highlight" }
|
|
7205
7341
|
}
|
|
7206
|
-
|
|
7342
|
+
},
|
|
7343
|
+
// The glyphs are mirrored for a right-to-left reading order.
|
|
7344
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/PagerControl/PagerControl_themeresources.xaml#L80
|
|
7345
|
+
mirrored: {
|
|
7346
|
+
':where([dir="rtl"]) &': { transform: "scaleX(-1)" }
|
|
7347
|
+
}
|
|
7348
|
+
});
|
|
7349
|
+
function NavigationButton({ className, disabled, icon, label, onClick }) {
|
|
7350
|
+
return /* @__PURE__ */ jsx17(Tooltip2, { content: label, relationship: "label", children: /* @__PURE__ */ jsx17(Button6, { appearance: "subtle", className, disabled, icon, onClick }) });
|
|
7351
|
+
}
|
|
7352
|
+
function Pager({
|
|
7353
|
+
ariaLabel,
|
|
7354
|
+
className,
|
|
7355
|
+
disabled = false,
|
|
7356
|
+
onPageChange,
|
|
7357
|
+
onPageSizeChange,
|
|
7358
|
+
page,
|
|
7359
|
+
pageCount: pageCountProp,
|
|
7360
|
+
pageSize,
|
|
7361
|
+
pageSizeOptions,
|
|
7362
|
+
showTotal = false,
|
|
7363
|
+
total
|
|
7364
|
+
}) {
|
|
7365
|
+
const { t: t2 } = useTranslation();
|
|
7366
|
+
const styles = useStyles7();
|
|
7367
|
+
const pageCount = Math.max(1, Math.trunc(pageCountProp ?? pagerPageCount(total ?? 0, pageSize ?? 1)));
|
|
7368
|
+
const current = clampPage(page, pageCount);
|
|
7369
|
+
const go = (next) => {
|
|
7370
|
+
const target = clampPage(next, pageCount);
|
|
7371
|
+
if (target !== current) onPageChange(target);
|
|
7372
|
+
};
|
|
7373
|
+
const atStart = current <= 1;
|
|
7374
|
+
const atEnd = current >= pageCount;
|
|
7375
|
+
const mirrored = styles.mirrored;
|
|
7376
|
+
const sizes = pageSize !== void 0 && pageSizeOptions && onPageSizeChange ? [.../* @__PURE__ */ new Set([...pageSizeOptions, pageSize])].sort((a2, b2) => a2 - b2) : null;
|
|
7377
|
+
const sizeLabel = (size) => t2("pager.perPage").replace("{n}", String(size));
|
|
7378
|
+
return /* @__PURE__ */ jsxs9("nav", { "aria-label": ariaLabel ?? t2("pager.label"), className: mergeClasses9("flex flex-wrap items-center justify-end gap-x-4 gap-y-1", className), children: [
|
|
7379
|
+
showTotal && total !== void 0 && (typeof showTotal === "function" ? showTotal(total) : /* @__PURE__ */ jsx17(Text3, { className: "text-fui-fg2", size: 300, children: t2("pager.total").replace("{n}", String(total)) })),
|
|
7380
|
+
sizes && pageSize !== void 0 && /* @__PURE__ */ jsx17(
|
|
7381
|
+
Dropdown,
|
|
7382
|
+
{
|
|
7383
|
+
"aria-label": t2("pager.pageSize"),
|
|
7384
|
+
disabled,
|
|
7385
|
+
onOptionSelect: (_2, data) => {
|
|
7386
|
+
const next = Number(data.optionValue);
|
|
7387
|
+
if (next > 0 && next !== pageSize) onPageSizeChange?.(next);
|
|
7388
|
+
},
|
|
7389
|
+
selectedOptions: [String(pageSize)],
|
|
7390
|
+
style: { "--fwt-select-min-width": "112px" },
|
|
7391
|
+
value: sizeLabel(pageSize),
|
|
7392
|
+
children: sizes.map((size) => /* @__PURE__ */ jsx17(Option2, { text: sizeLabel(size), value: String(size), children: sizeLabel(size) }, size))
|
|
7393
|
+
}
|
|
7394
|
+
),
|
|
7395
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center", children: [
|
|
7396
|
+
/* @__PURE__ */ jsx17(NavigationButton, { className: styles.navButton, disabled: disabled || atStart, icon: /* @__PURE__ */ jsx17(Previous16Regular, { className: mirrored }), label: t2("pager.first"), onClick: () => go(1) }),
|
|
7397
|
+
/* @__PURE__ */ jsx17(NavigationButton, { className: styles.navButton, disabled: disabled || atStart, icon: /* @__PURE__ */ jsx17(ChevronLeft12Regular, { className: mirrored }), label: t2("pager.previous"), onClick: () => go(current - 1) }),
|
|
7398
|
+
/* @__PURE__ */ jsx17("div", { className: "flex items-center h-10", style: { gap: 5 }, children: pagerPageWindow(current, pageCount).map((item) => typeof item === "number" ? /* @__PURE__ */ jsx17("span", { className: mergeClasses9("inline-flex", item === current && styles.selected), children: /* @__PURE__ */ jsx17(
|
|
7399
|
+
Button6,
|
|
7400
|
+
{
|
|
7401
|
+
appearance: "subtle",
|
|
7402
|
+
"aria-current": item === current ? "page" : void 0,
|
|
7403
|
+
"aria-label": t2("pager.page").replace("{n}", String(item)),
|
|
7404
|
+
className: styles.numberButton,
|
|
7405
|
+
disabled,
|
|
7406
|
+
onClick: () => go(item),
|
|
7407
|
+
children: item
|
|
7408
|
+
}
|
|
7409
|
+
) }, item) : /* @__PURE__ */ jsx17("span", { "aria-hidden": true, className: "grid place-items-center w-5 text-fui-fg2", children: /* @__PURE__ */ jsx17(MoreHorizontal16Regular, {}) }, item)) }),
|
|
7410
|
+
/* @__PURE__ */ jsx17(NavigationButton, { className: styles.navButton, disabled: disabled || atEnd, icon: /* @__PURE__ */ jsx17(ChevronRight12Regular, { className: mirrored }), label: t2("pager.next"), onClick: () => go(current + 1) }),
|
|
7411
|
+
/* @__PURE__ */ jsx17(NavigationButton, { className: styles.navButton, disabled: disabled || atEnd, icon: /* @__PURE__ */ jsx17(Next16Regular, { className: mirrored }), label: t2("pager.last"), onClick: () => go(pageCount) })
|
|
7412
|
+
] })
|
|
7413
|
+
] });
|
|
7207
7414
|
}
|
|
7208
7415
|
|
|
7209
|
-
// src/components/ui/
|
|
7416
|
+
// src/components/ui/table-actions.tsx
|
|
7210
7417
|
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
7211
|
-
var {
|
|
7212
|
-
var TONE_HUES = {
|
|
7213
|
-
accent: { light: "#0078d4", dark: "#4cc2ff" },
|
|
7214
|
-
danger: { light: "#c42b1c", dark: "#ff99a4" },
|
|
7215
|
-
neutral: { light: "#8a8a8a", dark: "#9a9a9a" },
|
|
7216
|
-
success: { light: "#0f7b0f", dark: "#6ccb5f" },
|
|
7217
|
-
warning: { light: "#9d5d00", dark: "#fce100" }
|
|
7218
|
-
};
|
|
7219
|
-
var CHIP_ROOT_PADDING = "5px";
|
|
7220
|
-
var LABEL_INSET = `calc(var(--strokeWidthThin) + ${CHIP_ROOT_PADDING} + var(--spacingHorizontalXXS))`;
|
|
7418
|
+
var { TableCell, TableHeaderCell, makeStyles: makeStyles8, mergeClasses: mergeClasses10 } = fluentComponents;
|
|
7221
7419
|
var useStyles8 = makeStyles8({
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7420
|
+
trailing: {
|
|
7421
|
+
textAlign: "right",
|
|
7422
|
+
"& .fui-TableHeaderCell__button": { justifyContent: "flex-end" }
|
|
7423
|
+
},
|
|
7424
|
+
centred: {
|
|
7425
|
+
textAlign: "center",
|
|
7426
|
+
"& .fui-TableHeaderCell__button": { justifyContent: "center" }
|
|
7225
7427
|
}
|
|
7226
7428
|
});
|
|
7227
|
-
function
|
|
7228
|
-
const hue = useBadgeHue(TONE_HUES[tone]);
|
|
7429
|
+
function TableTrailingHeader({ className, ...props }) {
|
|
7229
7430
|
const styles = useStyles8();
|
|
7230
|
-
return /* @__PURE__ */ jsx18(
|
|
7231
|
-
}
|
|
7232
|
-
|
|
7233
|
-
// src/components/ui/http-badge.tsx
|
|
7234
|
-
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
7235
|
-
var { makeStyles: makeStyles9 } = fluentComponents;
|
|
7236
|
-
var useStyles9 = makeStyles9({
|
|
7237
|
-
root: {
|
|
7238
|
-
fontFamily: "var(--fontFamilyMonospace)",
|
|
7239
|
-
minWidth: "48px",
|
|
7240
|
-
paddingTop: "1.5px"
|
|
7241
|
-
}
|
|
7242
|
-
});
|
|
7243
|
-
function HttpBadge({ children, tone }) {
|
|
7244
|
-
const styles = useStyles9();
|
|
7245
|
-
return /* @__PURE__ */ jsx19(StatusBadge, { className: styles.root, tone, children: /* @__PURE__ */ jsx19("span", { translate: "no", children }) });
|
|
7431
|
+
return /* @__PURE__ */ jsx18(TableHeaderCell, { ...props, className: mergeClasses10(styles.trailing, className) });
|
|
7246
7432
|
}
|
|
7247
|
-
function
|
|
7248
|
-
|
|
7433
|
+
function TableTrailingCell({ className, ...props }) {
|
|
7434
|
+
const styles = useStyles8();
|
|
7435
|
+
return /* @__PURE__ */ jsx18(TableCell, { ...props, className: mergeClasses10(styles.trailing, className) });
|
|
7249
7436
|
}
|
|
7250
|
-
function
|
|
7251
|
-
|
|
7437
|
+
function TableCentredHeader({ className, ...props }) {
|
|
7438
|
+
const styles = useStyles8();
|
|
7439
|
+
return /* @__PURE__ */ jsx18(TableHeaderCell, { ...props, className: mergeClasses10(styles.centred, className) });
|
|
7252
7440
|
}
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
var { InfoLabel } = fluentComponents;
|
|
7257
|
-
var infoLabelSlot = (label, info) => (_2, slotProps2) => /* @__PURE__ */ jsx20(InfoLabel, { ...slotProps2, info, children: label });
|
|
7258
|
-
|
|
7259
|
-
// src/components/ui/loading-screen.tsx
|
|
7260
|
-
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
7261
|
-
var { Spinner } = fluentComponents;
|
|
7262
|
-
function AppLoadingScreen({ label }) {
|
|
7263
|
-
return /* @__PURE__ */ jsx21("main", { className: "fwt-loading fwt-loading-app", children: /* @__PURE__ */ jsx21(Spinner, { label }) });
|
|
7441
|
+
function TableCentredCell({ className, ...props }) {
|
|
7442
|
+
const styles = useStyles8();
|
|
7443
|
+
return /* @__PURE__ */ jsx18(TableCell, { ...props, className: mergeClasses10(styles.centred, className) });
|
|
7264
7444
|
}
|
|
7265
|
-
|
|
7266
|
-
|
|
7445
|
+
var stopRowSelection = { onClick: (event) => event.stopPropagation() };
|
|
7446
|
+
var ACTION_GAP = "var(--spacingHorizontalXS)";
|
|
7447
|
+
var ACTION_BUTTON_SIZE = "24px";
|
|
7448
|
+
var TABLE_ACTIONS_WIDTH = `calc(3 * ${ACTION_BUTTON_SIZE} + 2 * ${ACTION_GAP} + var(--spacingHorizontalS) + var(--fwt-panel-inset))`;
|
|
7449
|
+
function TableActions({ children }) {
|
|
7450
|
+
return /* @__PURE__ */ jsx18("div", { className: "flex items-center justify-end", style: { gap: ACTION_GAP }, ...stopRowSelection, children });
|
|
7267
7451
|
}
|
|
7268
7452
|
|
|
7269
|
-
// src/components/ui/
|
|
7270
|
-
import { jsx as
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
const style = {
|
|
7274
|
-
backgroundColor: "currentColor",
|
|
7275
|
-
maskImage: `url(${url})`,
|
|
7276
|
-
WebkitMaskImage: `url(${url})`,
|
|
7277
|
-
maskSize,
|
|
7278
|
-
WebkitMaskSize: maskSize,
|
|
7279
|
-
maskRepeat: "no-repeat",
|
|
7280
|
-
WebkitMaskRepeat: "no-repeat",
|
|
7281
|
-
maskPosition: "center",
|
|
7282
|
-
WebkitMaskPosition: "center"
|
|
7283
|
-
};
|
|
7284
|
-
return /* @__PURE__ */ jsx22("span", { "aria-hidden": true, className: mergeClasses10("block flex-none", className), style });
|
|
7453
|
+
// src/components/ui/table-columns.tsx
|
|
7454
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
7455
|
+
function TableColumns({ widths }) {
|
|
7456
|
+
return /* @__PURE__ */ jsx19("colgroup", { children: widths.map((width, index) => /* @__PURE__ */ jsx19("col", { style: width === null ? void 0 : { width } }, index)) });
|
|
7285
7457
|
}
|
|
7286
7458
|
|
|
7287
|
-
// src/components/ui/
|
|
7288
|
-
import {
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7459
|
+
// src/components/ui/data-table.tsx
|
|
7460
|
+
import { jsx as jsx20, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
7461
|
+
var {
|
|
7462
|
+
Button: Button7,
|
|
7463
|
+
Spinner: Spinner2,
|
|
7464
|
+
Table,
|
|
7465
|
+
TableBody,
|
|
7466
|
+
TableCell: TableCell2,
|
|
7467
|
+
TableCellLayout,
|
|
7468
|
+
TableHeader,
|
|
7469
|
+
TableHeaderCell: TableHeaderCell2,
|
|
7470
|
+
TableRow,
|
|
7471
|
+
TableSelectionCell,
|
|
7472
|
+
mergeClasses: mergeClasses11
|
|
7473
|
+
} = fluentComponents;
|
|
7474
|
+
var LEADING_COLUMN_WIDTH = "44px";
|
|
7475
|
+
var HEADER_BY_ALIGN = { center: TableCentredHeader, end: TableTrailingHeader, start: TableHeaderCell2 };
|
|
7476
|
+
var CELL_BY_ALIGN = { center: TableCentredCell, end: TableTrailingCell, start: TableCell2 };
|
|
7477
|
+
var toggle = (keys2, key) => keys2.includes(key) ? keys2.filter((candidate) => candidate !== key) : [...keys2, key];
|
|
7478
|
+
function DataTable({
|
|
7293
7479
|
ariaLabel,
|
|
7294
7480
|
className,
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7481
|
+
columns,
|
|
7482
|
+
defaultSort,
|
|
7483
|
+
empty,
|
|
7484
|
+
expandable,
|
|
7485
|
+
loading = false,
|
|
7486
|
+
minWidth,
|
|
7487
|
+
onRowClick,
|
|
7488
|
+
onSortChange,
|
|
7489
|
+
pagination,
|
|
7490
|
+
rowClassName,
|
|
7491
|
+
rowKey,
|
|
7492
|
+
rows,
|
|
7493
|
+
selection,
|
|
7494
|
+
size = "medium"
|
|
7306
7495
|
}) {
|
|
7307
|
-
const
|
|
7308
|
-
const [
|
|
7309
|
-
const
|
|
7310
|
-
const
|
|
7311
|
-
const
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7496
|
+
const { t: t2 } = useTranslation();
|
|
7497
|
+
const [sort, setSort] = useState6(defaultSort ?? null);
|
|
7498
|
+
const [ownPage, setOwnPage] = useState6(1);
|
|
7499
|
+
const [ownPageSize, setOwnPageSize] = useState6(null);
|
|
7500
|
+
const [ownExpanded, setOwnExpanded] = useState6([]);
|
|
7501
|
+
const sortedRows = useMemo3(() => {
|
|
7502
|
+
const column = sort && columns.find((candidate) => candidate.key === sort.key);
|
|
7503
|
+
if (!sort || !column?.sort) return rows;
|
|
7504
|
+
const direction = sort.direction === "ascending" ? 1 : -1;
|
|
7505
|
+
const compare = column.sort;
|
|
7506
|
+
return [...rows].sort((a2, b2) => direction * compare(a2, b2));
|
|
7507
|
+
}, [columns, rows, sort]);
|
|
7508
|
+
const paged = pagination !== void 0 && pagination !== false;
|
|
7509
|
+
const pageSize = !paged ? 0 : pagination.onPageSizeChange ? pagination.pageSize : ownPageSize ?? pagination.pageSize;
|
|
7510
|
+
const pageCount = paged ? Math.max(1, Math.ceil(sortedRows.length / Math.max(pageSize, 1))) : 1;
|
|
7511
|
+
const requestedPage = paged ? pagination.page ?? ownPage : 1;
|
|
7512
|
+
const page = Math.min(Math.max(requestedPage, 1), pageCount);
|
|
7513
|
+
const visibleRows = paged ? sortedRows.slice((page - 1) * pageSize, page * pageSize) : sortedRows;
|
|
7514
|
+
const changePage = (next) => {
|
|
7515
|
+
setOwnPage(next);
|
|
7516
|
+
if (paged) pagination.onPageChange?.(next);
|
|
7320
7517
|
};
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
freeform,
|
|
7328
|
-
multiselect: true,
|
|
7329
|
-
onChange: (event) => setQuery(event.target.value),
|
|
7330
|
-
onKeyDown: freeform ? (event) => {
|
|
7331
|
-
if (event.key !== "Enter" || query.trim() === "") return;
|
|
7332
|
-
event.preventDefault();
|
|
7333
|
-
commit([...value, query]);
|
|
7334
|
-
} : void 0,
|
|
7335
|
-
onOpenChange: (_2, data) => {
|
|
7336
|
-
setOpen(data.open);
|
|
7337
|
-
setQuery("");
|
|
7338
|
-
},
|
|
7339
|
-
onOptionSelect: (_2, data) => commit(data.optionValue === "" ? [] : data.selectedOptions),
|
|
7340
|
-
placeholder,
|
|
7341
|
-
readOnly,
|
|
7342
|
-
selectedOptions: clearLabel && value.length === 0 ? [""] : [...value],
|
|
7343
|
-
value: open ? query : closedLabel,
|
|
7344
|
-
children: [
|
|
7345
|
-
clearLabel && needle === "" && /* @__PURE__ */ jsx23(Option2, { text: clearLabel, value: "", children: clearLabel }),
|
|
7346
|
-
visible.map((option) => /* @__PURE__ */ jsx23(Option2, { text: option.label, value: option.value, children: renderOption ? renderOption(option) : option.label }, option.value))
|
|
7347
|
-
]
|
|
7518
|
+
const changePageSize = (next) => {
|
|
7519
|
+
setOwnPageSize(next);
|
|
7520
|
+
setOwnPage(1);
|
|
7521
|
+
if (paged) {
|
|
7522
|
+
pagination.onPageSizeChange?.(next);
|
|
7523
|
+
pagination.onPageChange?.(1);
|
|
7348
7524
|
}
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7525
|
+
};
|
|
7526
|
+
const cycleSort = (column) => {
|
|
7527
|
+
const next = sort?.key !== column.key ? { key: column.key, direction: "ascending" } : sort.direction === "ascending" ? { key: column.key, direction: "descending" } : null;
|
|
7528
|
+
setSort(next);
|
|
7529
|
+
onSortChange?.(next);
|
|
7530
|
+
setOwnPage(1);
|
|
7531
|
+
};
|
|
7532
|
+
const selectedKeys = selection?.selectedKeys ?? [];
|
|
7533
|
+
const selectionMode = selection?.mode ?? "multiple";
|
|
7534
|
+
const isSelectable = (row) => selection?.isSelectable?.(row) ?? true;
|
|
7535
|
+
const selectableVisible = visibleRows.filter(isSelectable).map(rowKey);
|
|
7536
|
+
const selectedVisible = selectableVisible.filter((key) => selectedKeys.includes(key));
|
|
7537
|
+
const allChecked = selectedVisible.length === 0 ? false : selectedVisible.length === selectableVisible.length ? true : "mixed";
|
|
7538
|
+
const toggleAll = () => {
|
|
7539
|
+
if (!selection) return;
|
|
7540
|
+
selection.onChange(allChecked === true ? selectedKeys.filter((key) => !selectableVisible.includes(key)) : [...selectedKeys, ...selectableVisible.filter((key) => !selectedKeys.includes(key))]);
|
|
7541
|
+
};
|
|
7542
|
+
const selectRow = (key) => {
|
|
7543
|
+
if (!selection) return;
|
|
7544
|
+
selection.onChange(selectionMode === "single" ? [key] : toggle(selectedKeys, key));
|
|
7545
|
+
};
|
|
7546
|
+
const stop = (event) => event.stopPropagation();
|
|
7547
|
+
const expandedKeys = expandable?.expandedKeys ?? ownExpanded;
|
|
7548
|
+
const toggleExpanded = (key) => {
|
|
7549
|
+
const next = toggle(expandedKeys, key);
|
|
7550
|
+
setOwnExpanded(next);
|
|
7551
|
+
expandable?.onExpandedChange?.(next);
|
|
7552
|
+
};
|
|
7553
|
+
const columnCount = columns.length + (selection ? 1 : 0) + (expandable ? 1 : 0);
|
|
7554
|
+
const widths = [
|
|
7555
|
+
...selection ? [LEADING_COLUMN_WIDTH] : [],
|
|
7556
|
+
...expandable ? [LEADING_COLUMN_WIDTH] : [],
|
|
7557
|
+
...columns.map((column) => column.width ?? null)
|
|
7558
|
+
];
|
|
7559
|
+
const tableStyle = minWidth === void 0 ? void 0 : { minWidth };
|
|
7560
|
+
return /* @__PURE__ */ jsxs10("div", { className: mergeClasses11("min-w-0", className), children: [
|
|
7561
|
+
/* @__PURE__ */ jsxs10("div", { "aria-busy": loading || void 0, className: "relative min-w-0", children: [
|
|
7562
|
+
/* @__PURE__ */ jsx20(ScrollArea, { axes: "horizontal", className: "min-w-0", children: /* @__PURE__ */ jsxs10(Table, { "aria-label": ariaLabel, size, style: tableStyle, children: [
|
|
7563
|
+
/* @__PURE__ */ jsx20(TableColumns, { widths }),
|
|
7564
|
+
/* @__PURE__ */ jsx20(TableHeader, { children: /* @__PURE__ */ jsxs10(TableRow, { children: [
|
|
7565
|
+
selection && (selectionMode === "multiple" ? /* @__PURE__ */ jsx20(
|
|
7566
|
+
TableSelectionCell,
|
|
7567
|
+
{
|
|
7568
|
+
checkboxIndicator: { "aria-label": t2("dataTable.selectAll"), disabled: selectableVisible.length === 0 },
|
|
7569
|
+
checked: allChecked,
|
|
7570
|
+
onClick: selectableVisible.length === 0 ? void 0 : toggleAll
|
|
7571
|
+
}
|
|
7572
|
+
) : /* @__PURE__ */ jsx20(TableHeaderCell2, {})),
|
|
7573
|
+
expandable && /* @__PURE__ */ jsx20(TableHeaderCell2, {}),
|
|
7574
|
+
columns.map((column) => {
|
|
7575
|
+
const Header = HEADER_BY_ALIGN[column.align ?? "start"];
|
|
7576
|
+
const sorted = sort?.key === column.key ? sort.direction : void 0;
|
|
7577
|
+
return /* @__PURE__ */ jsx20(
|
|
7578
|
+
Header,
|
|
7579
|
+
{
|
|
7580
|
+
onClick: column.sort ? () => cycleSort(column) : void 0,
|
|
7581
|
+
sortable: column.sort !== void 0,
|
|
7582
|
+
sortDirection: sorted,
|
|
7583
|
+
children: column.title
|
|
7584
|
+
},
|
|
7585
|
+
column.key
|
|
7586
|
+
);
|
|
7587
|
+
})
|
|
7588
|
+
] }) }),
|
|
7589
|
+
/* @__PURE__ */ jsxs10(TableBody, { children: [
|
|
7590
|
+
visibleRows.length === 0 && /* @__PURE__ */ jsx20(TableRow, { children: /* @__PURE__ */ jsx20(TableCell2, { colSpan: columnCount, children: empty ?? /* @__PURE__ */ jsx20(EmptyStateLine, { className: "py-6 text-center", children: t2("dataTable.empty") }) }) }),
|
|
7591
|
+
visibleRows.flatMap((row, index) => {
|
|
7592
|
+
const key = rowKey(row);
|
|
7593
|
+
const selected = selectedKeys.includes(key);
|
|
7594
|
+
const expanded = expandable !== void 0 && expandedKeys.includes(key);
|
|
7595
|
+
const canExpand = expandable !== void 0 && (expandable.isExpandable?.(row) ?? true);
|
|
7596
|
+
const items = [/* @__PURE__ */ jsxs10(
|
|
7597
|
+
TableRow,
|
|
7598
|
+
{
|
|
7599
|
+
"aria-selected": selection ? selected : void 0,
|
|
7600
|
+
className: mergeClasses11(onRowClick && "cursor-pointer", rowClassName?.(row, index)),
|
|
7601
|
+
onClick: onRowClick ? () => onRowClick(row, index) : void 0,
|
|
7602
|
+
children: [
|
|
7603
|
+
selection && /* @__PURE__ */ jsx20(
|
|
7604
|
+
TableSelectionCell,
|
|
7605
|
+
{
|
|
7606
|
+
checkboxIndicator: { "aria-label": t2("dataTable.selectRow"), disabled: !isSelectable(row) },
|
|
7607
|
+
checked: selected,
|
|
7608
|
+
onClick: (event) => {
|
|
7609
|
+
stop(event);
|
|
7610
|
+
if (isSelectable(row)) selectRow(key);
|
|
7611
|
+
},
|
|
7612
|
+
radioIndicator: { "aria-label": t2("dataTable.selectRow"), disabled: !isSelectable(row) },
|
|
7613
|
+
type: selectionMode === "single" ? "radio" : "checkbox"
|
|
7614
|
+
}
|
|
7615
|
+
),
|
|
7616
|
+
expandable && /* @__PURE__ */ jsx20(TableCell2, { ...stopRowSelection, children: canExpand && /* @__PURE__ */ jsx20(
|
|
7617
|
+
Button7,
|
|
7618
|
+
{
|
|
7619
|
+
appearance: "subtle",
|
|
7620
|
+
"aria-expanded": expanded,
|
|
7621
|
+
"aria-label": t2(expanded ? "dataTable.collapseRow" : "dataTable.expandRow"),
|
|
7622
|
+
icon: expanded ? /* @__PURE__ */ jsx20(ChevronDown16Regular, {}) : /* @__PURE__ */ jsx20(ChevronRight16Regular, {}),
|
|
7623
|
+
onClick: () => toggleExpanded(key),
|
|
7624
|
+
size: "small"
|
|
7625
|
+
}
|
|
7626
|
+
) }),
|
|
7627
|
+
columns.map((column) => {
|
|
7628
|
+
const Cell = CELL_BY_ALIGN[column.align ?? "start"];
|
|
7629
|
+
const content = column.render ? column.render(row, index) : column.dataKey === void 0 ? null : row[column.dataKey];
|
|
7630
|
+
return /* @__PURE__ */ jsx20(Cell, { className: column.ellipsis ? "overflow-hidden" : void 0, children: column.ellipsis ? /* @__PURE__ */ jsx20(TableCellLayout, { title: typeof content === "string" || typeof content === "number" ? String(content) : void 0, truncate: true, children: content }) : content }, column.key);
|
|
7631
|
+
})
|
|
7632
|
+
]
|
|
7633
|
+
},
|
|
7634
|
+
key
|
|
7635
|
+
)];
|
|
7636
|
+
if (expanded && canExpand) {
|
|
7637
|
+
items.push(/* @__PURE__ */ jsx20(TableRow, { children: /* @__PURE__ */ jsx20(TableCell2, { colSpan: columnCount, children: expandable.render(row) }) }, `${key}:expanded`));
|
|
7638
|
+
}
|
|
7639
|
+
return items;
|
|
7640
|
+
})
|
|
7641
|
+
] })
|
|
7642
|
+
] }) }),
|
|
7643
|
+
loading && /* @__PURE__ */ jsx20(
|
|
7644
|
+
"div",
|
|
7645
|
+
{
|
|
7646
|
+
className: "absolute inset-0 grid place-items-center",
|
|
7647
|
+
style: { background: "color-mix(in srgb, var(--colorNeutralBackground1) 60%, transparent)" },
|
|
7648
|
+
children: /* @__PURE__ */ jsx20(Spinner2, { label: t2("dataTable.loading"), size: "small" })
|
|
7649
|
+
}
|
|
7650
|
+
)
|
|
7651
|
+
] }),
|
|
7652
|
+
paged && !(pagination.hideOnSinglePage && pageCount <= 1) && /* @__PURE__ */ jsx20("div", { className: "flex justify-end px-3 py-1", style: { borderTop: "1px solid var(--colorNeutralStroke3)" }, children: /* @__PURE__ */ jsx20(
|
|
7653
|
+
Pager,
|
|
7654
|
+
{
|
|
7655
|
+
onPageChange: changePage,
|
|
7656
|
+
onPageSizeChange: changePageSize,
|
|
7657
|
+
page,
|
|
7658
|
+
pageCount,
|
|
7659
|
+
pageSize,
|
|
7660
|
+
pageSizeOptions: pagination.pageSizeOptions,
|
|
7661
|
+
showTotal: pagination.showTotal,
|
|
7662
|
+
total: sortedRows.length
|
|
7663
|
+
}
|
|
7664
|
+
) })
|
|
7360
7665
|
] });
|
|
7361
7666
|
}
|
|
7362
7667
|
|
|
7363
|
-
// src/components/ui/
|
|
7364
|
-
import {
|
|
7365
|
-
|
|
7366
|
-
|
|
7668
|
+
// src/components/ui/dashboard-page-header.tsx
|
|
7669
|
+
import { jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7670
|
+
var { Text: Text4, mergeClasses: mergeClasses12 } = fluentComponents;
|
|
7671
|
+
function DashboardPageHeader({ actions, className, description, title }) {
|
|
7672
|
+
return /* @__PURE__ */ jsxs11("header", { className: mergeClasses12(HEADER_ROW_CLASS, "gap-[18px]", className), children: [
|
|
7673
|
+
/* @__PURE__ */ jsxs11("div", { className: "grid gap-1.5 min-w-0", children: [
|
|
7674
|
+
/* @__PURE__ */ jsx21(Text4, { as: "h1", size: 700, weight: "semibold", className: "m-0", children: title }),
|
|
7675
|
+
description !== void 0 && /* @__PURE__ */ jsx21(Text4, { size: 200, className: "text-fui-fg2 max-w-[760px]", children: description })
|
|
7676
|
+
] }),
|
|
7677
|
+
actions !== void 0 && /* @__PURE__ */ jsx21("div", { className: "flex items-center gap-2 flex-none max-[900px]:justify-start", children: actions })
|
|
7678
|
+
] });
|
|
7679
|
+
}
|
|
7680
|
+
|
|
7681
|
+
// src/components/ui/error-shell.tsx
|
|
7682
|
+
import { jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
7683
|
+
var { Text: Text5 } = fluentComponents;
|
|
7684
|
+
function ErrorShell({ action, children, message, title }) {
|
|
7685
|
+
return /* @__PURE__ */ jsx22(ScrollArea, { axes: "vertical", className: "fwt-error-shell-viewport", contentClassName: "h-full", children: /* @__PURE__ */ jsxs12("main", { className: "fwt-error-shell", children: [
|
|
7686
|
+
/* @__PURE__ */ jsxs12("div", { className: "fwt-error-shell-stack", children: [
|
|
7687
|
+
/* @__PURE__ */ jsx22(Text5, { align: "center", as: "h1", size: 700, weight: "semibold", children: title }),
|
|
7688
|
+
message !== void 0 && /* @__PURE__ */ jsx22(Text5, { align: "center", as: "p", className: "text-fui-fg2", size: 300, children: message })
|
|
7689
|
+
] }),
|
|
7690
|
+
children,
|
|
7691
|
+
action !== void 0 && /* @__PURE__ */ jsx22("div", { className: "fwt-error-shell-actions", children: action })
|
|
7692
|
+
] }) });
|
|
7693
|
+
}
|
|
7694
|
+
function ErrorStack({ children }) {
|
|
7695
|
+
return /* @__PURE__ */ jsx22(
|
|
7696
|
+
ScrollArea,
|
|
7697
|
+
{
|
|
7698
|
+
axes: "horizontal",
|
|
7699
|
+
className: "winui-focus-rect-within w-full min-w-0 rounded-[var(--winui-overlay-corner-radius,8px)] border border-solid border-fui-stroke1 bg-fui-bg2 text-left",
|
|
7700
|
+
children: /* @__PURE__ */ jsx22("pre", { className: "m-0 w-max min-w-full p-4 font-mono", children: /* @__PURE__ */ jsx22("code", { children }) })
|
|
7701
|
+
}
|
|
7702
|
+
);
|
|
7703
|
+
}
|
|
7704
|
+
|
|
7705
|
+
// src/components/ui/file-drop-zone.tsx
|
|
7706
|
+
import { ArrowUploadRegular, DismissRegular as DismissRegular3, DocumentRegular } from "@fluentui/react-icons";
|
|
7707
|
+
import { useId as useId2, useRef as useRef5, useState as useState7 } from "react";
|
|
7708
|
+
import { Fragment as Fragment2, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7709
|
+
var { Button: Button8, Text: Text6, makeStyles: makeStyles9, mergeClasses: mergeClasses13, shorthands } = fluentComponents;
|
|
7710
|
+
var useStyles9 = makeStyles9({
|
|
7711
|
+
root: {
|
|
7712
|
+
display: "grid",
|
|
7713
|
+
rowGap: "8px",
|
|
7714
|
+
minWidth: 0
|
|
7715
|
+
},
|
|
7716
|
+
zone: {
|
|
7717
|
+
alignItems: "center",
|
|
7718
|
+
backgroundColor: "var(--winui-card-background-fill-default)",
|
|
7719
|
+
...shorthands.border("1px", "dashed", "var(--winui-surface-stroke-default)"),
|
|
7720
|
+
borderRadius: "var(--winui-control-corner-radius)",
|
|
7721
|
+
boxSizing: "border-box",
|
|
7722
|
+
color: "var(--winui-text-fill-primary)",
|
|
7723
|
+
cursor: "pointer",
|
|
7724
|
+
display: "grid",
|
|
7725
|
+
justifyItems: "center",
|
|
7726
|
+
minHeight: "120px",
|
|
7727
|
+
padding: "24px 16px",
|
|
7728
|
+
rowGap: "4px",
|
|
7729
|
+
textAlign: "center",
|
|
7730
|
+
transitionDuration: "var(--winui-control-faster-animation-duration)",
|
|
7731
|
+
transitionProperty: "background-color, border-color",
|
|
7732
|
+
"@media (prefers-reduced-motion: reduce)": { transitionDuration: "0.01ms" },
|
|
7733
|
+
"&:hover": { backgroundColor: "var(--winui-control-fill-secondary)" },
|
|
7734
|
+
"&:active": { backgroundColor: "var(--winui-control-fill-tertiary)" },
|
|
7735
|
+
// The system focus visual, as ./settings-card draws it.
|
|
7736
|
+
"&:focus-visible": {
|
|
7737
|
+
boxShadow: "0 0 0 1px var(--winui-focus-stroke-inner)",
|
|
7738
|
+
outlineColor: "var(--winui-focus-stroke-outer)",
|
|
7739
|
+
outlineOffset: "1px",
|
|
7740
|
+
outlineStyle: "solid",
|
|
7741
|
+
outlineWidth: "2px"
|
|
7742
|
+
}
|
|
7743
|
+
},
|
|
7744
|
+
dragOver: {
|
|
7745
|
+
backgroundColor: "var(--winui-accent-tint-fill-default)",
|
|
7746
|
+
...shorthands.borderColor("var(--winui-accent-base)"),
|
|
7747
|
+
"&:hover": { backgroundColor: "var(--winui-accent-tint-fill-default)" },
|
|
7748
|
+
"&:active": { backgroundColor: "var(--winui-accent-tint-fill-secondary)" }
|
|
7749
|
+
},
|
|
7750
|
+
disabled: {
|
|
7751
|
+
backgroundColor: "var(--winui-control-fill-disabled)",
|
|
7752
|
+
color: "var(--winui-text-fill-disabled)",
|
|
7753
|
+
cursor: "not-allowed",
|
|
7754
|
+
"&:hover": { backgroundColor: "var(--winui-control-fill-disabled)" },
|
|
7755
|
+
"&:active": { backgroundColor: "var(--winui-control-fill-disabled)" }
|
|
7756
|
+
},
|
|
7757
|
+
icon: {
|
|
7758
|
+
color: "var(--winui-text-fill-secondary)",
|
|
7759
|
+
display: "inline-flex",
|
|
7760
|
+
fontSize: "24px",
|
|
7761
|
+
lineHeight: 0,
|
|
7762
|
+
pointerEvents: "none"
|
|
7763
|
+
},
|
|
7764
|
+
iconDragOver: { color: "var(--winui-accent-base)" },
|
|
7765
|
+
list: {
|
|
7766
|
+
display: "grid",
|
|
7767
|
+
listStyleType: "none",
|
|
7768
|
+
margin: 0,
|
|
7769
|
+
padding: 0,
|
|
7770
|
+
rowGap: "4px"
|
|
7771
|
+
},
|
|
7772
|
+
file: {
|
|
7773
|
+
alignItems: "center",
|
|
7774
|
+
backgroundColor: "var(--winui-card-background-fill-default)",
|
|
7775
|
+
...shorthands.border("1px", "solid", "var(--winui-card-stroke-default)"),
|
|
7776
|
+
borderRadius: "var(--winui-control-corner-radius)",
|
|
7777
|
+
columnGap: "8px",
|
|
7778
|
+
display: "flex",
|
|
7779
|
+
minHeight: "40px",
|
|
7780
|
+
paddingBlock: "4px",
|
|
7781
|
+
paddingInlineStart: "12px",
|
|
7782
|
+
paddingInlineEnd: "4px"
|
|
7783
|
+
},
|
|
7784
|
+
fileName: {
|
|
7785
|
+
flexGrow: 1,
|
|
7786
|
+
minWidth: 0,
|
|
7787
|
+
overflow: "hidden",
|
|
7788
|
+
textOverflow: "ellipsis",
|
|
7789
|
+
whiteSpace: "nowrap"
|
|
7790
|
+
}
|
|
7791
|
+
});
|
|
7792
|
+
var BYTE_UNITS = ["B", "KB", "MB", "GB", "TB"];
|
|
7793
|
+
var formatFileSize = (bytes) => {
|
|
7794
|
+
let size = bytes;
|
|
7795
|
+
let unit = 0;
|
|
7796
|
+
while (size >= 1024 && unit < BYTE_UNITS.length - 1) {
|
|
7797
|
+
size /= 1024;
|
|
7798
|
+
unit += 1;
|
|
7799
|
+
}
|
|
7800
|
+
const text = new Intl.NumberFormat(void 0, { maximumFractionDigits: unit === 0 ? 0 : 1 }).format(size);
|
|
7801
|
+
return `${text} ${BYTE_UNITS[unit]}`;
|
|
7802
|
+
};
|
|
7803
|
+
var matchesAccept = (file, accept) => {
|
|
7804
|
+
const tokens3 = accept?.split(",").map((token) => token.trim().toLowerCase()).filter(Boolean) ?? [];
|
|
7805
|
+
if (tokens3.length === 0) return true;
|
|
7806
|
+
const name = file.name.toLowerCase();
|
|
7807
|
+
const type = file.type.toLowerCase();
|
|
7808
|
+
return tokens3.some((token) => {
|
|
7809
|
+
if (token.startsWith(".")) return name.endsWith(token);
|
|
7810
|
+
if (token.endsWith("/*")) return type.startsWith(token.slice(0, -1));
|
|
7811
|
+
return type === token;
|
|
7812
|
+
});
|
|
7813
|
+
};
|
|
7814
|
+
var pickFiles = (files, accept, multiple) => {
|
|
7815
|
+
const accepted = [...files].filter((file) => matchesAccept(file, accept));
|
|
7816
|
+
return multiple ? accepted : accepted.slice(0, 1);
|
|
7817
|
+
};
|
|
7818
|
+
function FileDropZone({
|
|
7819
|
+
accept,
|
|
7820
|
+
className,
|
|
7821
|
+
description,
|
|
7822
|
+
disabled,
|
|
7823
|
+
icon,
|
|
7824
|
+
multiple,
|
|
7825
|
+
onFiles,
|
|
7826
|
+
onRemove,
|
|
7827
|
+
selectedFiles,
|
|
7828
|
+
title
|
|
7829
|
+
}) {
|
|
7830
|
+
const styles = useStyles9();
|
|
7831
|
+
const { t: t2 } = useTranslation();
|
|
7832
|
+
const inputRef = useRef5(null);
|
|
7833
|
+
const depth = useRef5(0);
|
|
7834
|
+
const [dragOver, setDragOver] = useState7(false);
|
|
7835
|
+
const titleId = useId2();
|
|
7836
|
+
const reset = () => {
|
|
7837
|
+
depth.current = 0;
|
|
7838
|
+
setDragOver(false);
|
|
7839
|
+
};
|
|
7840
|
+
const emit = (files) => {
|
|
7841
|
+
const picked = pickFiles(files, accept, multiple);
|
|
7842
|
+
if (picked.length > 0) onFiles(picked);
|
|
7843
|
+
};
|
|
7844
|
+
const open = () => {
|
|
7845
|
+
if (!disabled) inputRef.current?.click();
|
|
7846
|
+
};
|
|
7847
|
+
const handleDragEnter = (event) => {
|
|
7848
|
+
if (disabled) return;
|
|
7849
|
+
event.preventDefault();
|
|
7850
|
+
depth.current += 1;
|
|
7851
|
+
setDragOver(true);
|
|
7852
|
+
};
|
|
7853
|
+
const handleDragOver = (event) => {
|
|
7854
|
+
if (disabled) return;
|
|
7855
|
+
event.preventDefault();
|
|
7856
|
+
event.dataTransfer.dropEffect = "copy";
|
|
7857
|
+
};
|
|
7858
|
+
const handleDragLeave = () => {
|
|
7859
|
+
if (disabled) return;
|
|
7860
|
+
depth.current = Math.max(0, depth.current - 1);
|
|
7861
|
+
if (depth.current === 0) setDragOver(false);
|
|
7862
|
+
};
|
|
7863
|
+
const handleDrop = (event) => {
|
|
7864
|
+
if (disabled) return;
|
|
7865
|
+
event.preventDefault();
|
|
7866
|
+
reset();
|
|
7867
|
+
emit(Array.from(event.dataTransfer.files));
|
|
7868
|
+
};
|
|
7869
|
+
const handleKeyDown = (event) => {
|
|
7870
|
+
if (event.target !== event.currentTarget) return;
|
|
7871
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
7872
|
+
event.preventDefault();
|
|
7873
|
+
open();
|
|
7874
|
+
}
|
|
7875
|
+
};
|
|
7876
|
+
const handleInputChange = (event) => {
|
|
7877
|
+
const files = Array.from(event.target.files ?? []);
|
|
7878
|
+
event.target.value = "";
|
|
7879
|
+
emit(files);
|
|
7880
|
+
};
|
|
7881
|
+
return /* @__PURE__ */ jsxs13("div", { className: mergeClasses13(styles.root, className), children: [
|
|
7882
|
+
/* @__PURE__ */ jsxs13(
|
|
7883
|
+
"div",
|
|
7884
|
+
{
|
|
7885
|
+
"aria-disabled": disabled || void 0,
|
|
7886
|
+
"aria-labelledby": titleId,
|
|
7887
|
+
className: mergeClasses13(styles.zone, dragOver && styles.dragOver, disabled && styles.disabled),
|
|
7888
|
+
"data-drag-over": dragOver || void 0,
|
|
7889
|
+
onClick: open,
|
|
7890
|
+
onDragEnter: handleDragEnter,
|
|
7891
|
+
onDragLeave: handleDragLeave,
|
|
7892
|
+
onDragOver: handleDragOver,
|
|
7893
|
+
onDrop: handleDrop,
|
|
7894
|
+
onKeyDown: handleKeyDown,
|
|
7895
|
+
role: "button",
|
|
7896
|
+
tabIndex: disabled ? -1 : 0,
|
|
7897
|
+
children: [
|
|
7898
|
+
/* @__PURE__ */ jsx23("span", { "aria-hidden": true, className: mergeClasses13(styles.icon, dragOver && styles.iconDragOver), children: icon ?? /* @__PURE__ */ jsx23(ArrowUploadRegular, {}) }),
|
|
7899
|
+
/* @__PURE__ */ jsx23(Text6, { id: titleId, size: 300, weight: "semibold", children: dragOver ? t2("fileDropZone.dropHint") : title }),
|
|
7900
|
+
description !== void 0 && /* @__PURE__ */ jsx23(Text6, { size: 200, className: "text-fui-fg2", children: description })
|
|
7901
|
+
]
|
|
7902
|
+
}
|
|
7903
|
+
),
|
|
7904
|
+
/* @__PURE__ */ jsx23(
|
|
7905
|
+
"input",
|
|
7906
|
+
{
|
|
7907
|
+
accept,
|
|
7908
|
+
disabled,
|
|
7909
|
+
hidden: true,
|
|
7910
|
+
multiple,
|
|
7911
|
+
onChange: handleInputChange,
|
|
7912
|
+
ref: inputRef,
|
|
7913
|
+
tabIndex: -1,
|
|
7914
|
+
type: "file"
|
|
7915
|
+
}
|
|
7916
|
+
),
|
|
7917
|
+
selectedFiles !== void 0 && selectedFiles.length > 0 && /* @__PURE__ */ jsx23("ul", { className: styles.list, children: selectedFiles.map((file, index) => /* @__PURE__ */ jsxs13("li", { className: styles.file, children: [
|
|
7918
|
+
/* @__PURE__ */ jsx23(DocumentRegular, { "aria-hidden": true, className: "text-fui-fg2 shrink-0" }),
|
|
7919
|
+
/* @__PURE__ */ jsx23(Text6, { className: styles.fileName, size: 300, title: file.name, children: file.name }),
|
|
7920
|
+
/* @__PURE__ */ jsx23(Text6, { className: "text-fui-fg2 shrink-0", size: 200, children: formatFileSize(file.size) }),
|
|
7921
|
+
onRemove && /* @__PURE__ */ jsx23(
|
|
7922
|
+
Button8,
|
|
7923
|
+
{
|
|
7924
|
+
appearance: "subtle",
|
|
7925
|
+
"aria-label": `${t2("fileDropZone.remove")}: ${file.name}`,
|
|
7926
|
+
icon: /* @__PURE__ */ jsx23(DismissRegular3, {}),
|
|
7927
|
+
onClick: () => onRemove(file, index),
|
|
7928
|
+
size: "small"
|
|
7929
|
+
}
|
|
7930
|
+
)
|
|
7931
|
+
] }, `${file.name}:${file.size}:${file.lastModified}:${index}`)) })
|
|
7932
|
+
] });
|
|
7933
|
+
}
|
|
7934
|
+
function FilePickerButton({ accept, children, disabled, multiple, onClick, onFiles, ...rest }) {
|
|
7935
|
+
const { t: t2 } = useTranslation();
|
|
7936
|
+
const inputRef = useRef5(null);
|
|
7937
|
+
const buttonProps = {
|
|
7938
|
+
...rest,
|
|
7939
|
+
disabled,
|
|
7940
|
+
onClick: (event) => {
|
|
7941
|
+
onClick?.(event);
|
|
7942
|
+
if (!event.defaultPrevented) inputRef.current?.click();
|
|
7943
|
+
}
|
|
7944
|
+
};
|
|
7945
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7946
|
+
/* @__PURE__ */ jsx23(Button8, { ...buttonProps, children: children ?? t2("fileDropZone.browse") }),
|
|
7947
|
+
/* @__PURE__ */ jsx23(
|
|
7948
|
+
"input",
|
|
7949
|
+
{
|
|
7950
|
+
accept,
|
|
7951
|
+
disabled,
|
|
7952
|
+
hidden: true,
|
|
7953
|
+
multiple,
|
|
7954
|
+
onChange: (event) => {
|
|
7955
|
+
const files = Array.from(event.target.files ?? []);
|
|
7956
|
+
event.target.value = "";
|
|
7957
|
+
if (files.length > 0) onFiles(files);
|
|
7958
|
+
},
|
|
7959
|
+
ref: inputRef,
|
|
7960
|
+
tabIndex: -1,
|
|
7961
|
+
type: "file"
|
|
7962
|
+
}
|
|
7963
|
+
)
|
|
7964
|
+
] });
|
|
7965
|
+
}
|
|
7966
|
+
|
|
7967
|
+
// src/components/ui/status-badge.tsx
|
|
7968
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
7969
|
+
var { Badge, makeStyles: makeStyles10, mergeClasses: mergeClasses14 } = fluentComponents;
|
|
7970
|
+
var TONE_HUES = {
|
|
7971
|
+
accent: { light: "#0078d4", dark: "#4cc2ff" },
|
|
7972
|
+
danger: { light: "#c42b1c", dark: "#ff99a4" },
|
|
7973
|
+
neutral: { light: "#8a8a8a", dark: "#9a9a9a" },
|
|
7974
|
+
success: { light: "#0f7b0f", dark: "#6ccb5f" },
|
|
7975
|
+
warning: { light: "#9d5d00", dark: "#fce100" }
|
|
7976
|
+
};
|
|
7977
|
+
var CHIP_ROOT_PADDING = "5px";
|
|
7978
|
+
var LABEL_INSET = `calc(var(--strokeWidthThin) + ${CHIP_ROOT_PADDING} + var(--spacingHorizontalXXS))`;
|
|
7979
|
+
var useStyles10 = makeStyles10({
|
|
7980
|
+
root: {
|
|
7981
|
+
paddingLeft: LABEL_INSET,
|
|
7982
|
+
paddingRight: LABEL_INSET
|
|
7983
|
+
}
|
|
7984
|
+
});
|
|
7985
|
+
function StatusBadge({ children, className, tone }) {
|
|
7986
|
+
const hue = useBadgeHue(TONE_HUES[tone]);
|
|
7987
|
+
const styles = useStyles10();
|
|
7988
|
+
return /* @__PURE__ */ jsx24(Badge, { appearance: "tint", className: mergeClasses14(styles.root, hue.className, className), size: "large", style: hue.style, children });
|
|
7989
|
+
}
|
|
7990
|
+
|
|
7991
|
+
// src/components/ui/http-badge.tsx
|
|
7992
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
7993
|
+
var { makeStyles: makeStyles11 } = fluentComponents;
|
|
7994
|
+
var useStyles11 = makeStyles11({
|
|
7995
|
+
root: {
|
|
7996
|
+
fontFamily: "var(--fontFamilyMonospace)",
|
|
7997
|
+
minWidth: "48px",
|
|
7998
|
+
paddingTop: "1.5px"
|
|
7999
|
+
}
|
|
8000
|
+
});
|
|
8001
|
+
function HttpBadge({ children, tone }) {
|
|
8002
|
+
const styles = useStyles11();
|
|
8003
|
+
return /* @__PURE__ */ jsx25(StatusBadge, { className: styles.root, tone, children: /* @__PURE__ */ jsx25("span", { translate: "no", children }) });
|
|
8004
|
+
}
|
|
8005
|
+
function HttpMethodBadge({ method }) {
|
|
8006
|
+
return /* @__PURE__ */ jsx25(HttpBadge, { tone: method === "GET" ? "accent" : method === "POST" ? "success" : "neutral", children: method });
|
|
8007
|
+
}
|
|
8008
|
+
function HttpStatusBadge({ children, severity }) {
|
|
8009
|
+
return /* @__PURE__ */ jsx25(HttpBadge, { tone: severity === "error" ? "danger" : severity, children });
|
|
8010
|
+
}
|
|
8011
|
+
|
|
8012
|
+
// src/components/ui/info-label.tsx
|
|
8013
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
8014
|
+
var { InfoLabel } = fluentComponents;
|
|
8015
|
+
var infoLabelSlot = (label, info) => (_2, slotProps2) => /* @__PURE__ */ jsx26(InfoLabel, { ...slotProps2, info, children: label });
|
|
8016
|
+
|
|
8017
|
+
// src/components/ui/loading-screen.tsx
|
|
8018
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
8019
|
+
var { Spinner: Spinner3 } = fluentComponents;
|
|
8020
|
+
function AppLoadingScreen({ label }) {
|
|
8021
|
+
return /* @__PURE__ */ jsx27("main", { className: "fwt-loading fwt-loading-app", children: /* @__PURE__ */ jsx27(Spinner3, { label }) });
|
|
8022
|
+
}
|
|
8023
|
+
function ContentLoadingScreen({ label }) {
|
|
8024
|
+
return /* @__PURE__ */ jsx27("div", { className: "fwt-loading", children: /* @__PURE__ */ jsx27(Spinner3, { label }) });
|
|
8025
|
+
}
|
|
8026
|
+
|
|
8027
|
+
// src/components/ui/masked-icon.tsx
|
|
8028
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
8029
|
+
var { mergeClasses: mergeClasses15 } = fluentComponents;
|
|
8030
|
+
function MaskedIcon({ className, maskSize = "contain", url }) {
|
|
8031
|
+
const style = {
|
|
8032
|
+
backgroundColor: "currentColor",
|
|
8033
|
+
maskImage: `url(${url})`,
|
|
8034
|
+
WebkitMaskImage: `url(${url})`,
|
|
8035
|
+
maskSize,
|
|
8036
|
+
WebkitMaskSize: maskSize,
|
|
8037
|
+
maskRepeat: "no-repeat",
|
|
8038
|
+
WebkitMaskRepeat: "no-repeat",
|
|
8039
|
+
maskPosition: "center",
|
|
8040
|
+
WebkitMaskPosition: "center"
|
|
8041
|
+
};
|
|
8042
|
+
return /* @__PURE__ */ jsx28("span", { "aria-hidden": true, className: mergeClasses15("block flex-none", className), style });
|
|
8043
|
+
}
|
|
8044
|
+
|
|
8045
|
+
// src/components/ui/metric.tsx
|
|
8046
|
+
import { jsx as jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
8047
|
+
var { makeStyles: makeStyles12, mergeClasses: mergeClasses16 } = fluentComponents;
|
|
8048
|
+
var useStyles12 = makeStyles12({
|
|
8049
|
+
root: {
|
|
8050
|
+
display: "grid",
|
|
8051
|
+
minWidth: 0,
|
|
8052
|
+
rowGap: "4px"
|
|
8053
|
+
},
|
|
8054
|
+
label: {
|
|
8055
|
+
color: "var(--winui-text-fill-secondary)",
|
|
8056
|
+
fontSize: "var(--fontSizeBase200)",
|
|
8057
|
+
lineHeight: "var(--lineHeightBase200)"
|
|
8058
|
+
},
|
|
8059
|
+
value: {
|
|
8060
|
+
alignItems: "baseline",
|
|
8061
|
+
color: "var(--winui-text-fill-primary)",
|
|
8062
|
+
columnGap: "4px",
|
|
8063
|
+
display: "flex",
|
|
8064
|
+
fontVariantNumeric: "tabular-nums",
|
|
8065
|
+
fontWeight: "var(--fontWeightSemibold)",
|
|
8066
|
+
minWidth: 0
|
|
8067
|
+
},
|
|
8068
|
+
title: {
|
|
8069
|
+
fontSize: "var(--fontSizeHero700)",
|
|
8070
|
+
lineHeight: "var(--lineHeightHero700)"
|
|
8071
|
+
},
|
|
8072
|
+
subtitle: {
|
|
8073
|
+
fontSize: "var(--fontSizeBase500)",
|
|
8074
|
+
lineHeight: "var(--lineHeightBase500)"
|
|
8075
|
+
},
|
|
8076
|
+
// A prefix or suffix is a unit or a sign, not part of the figure: one step
|
|
8077
|
+
// down the ramp and the secondary fill, so the figure stays the loudest thing.
|
|
8078
|
+
affix: {
|
|
8079
|
+
color: "var(--winui-text-fill-secondary)",
|
|
8080
|
+
fontSize: "var(--fontSizeBase300)",
|
|
8081
|
+
fontWeight: "var(--fontWeightRegular)",
|
|
8082
|
+
lineHeight: "var(--lineHeightBase300)"
|
|
8083
|
+
},
|
|
8084
|
+
accent: { color: "var(--winui-accent-text-fill-tertiary)" },
|
|
8085
|
+
success: { color: "var(--winui-system-fill-success)" },
|
|
8086
|
+
warning: { color: "var(--winui-system-fill-caution)" },
|
|
8087
|
+
danger: { color: "var(--winui-system-fill-critical)" },
|
|
8088
|
+
grid: {
|
|
8089
|
+
display: "grid",
|
|
8090
|
+
gap: "var(--fwt-metric-gap, 16px)",
|
|
8091
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(min(var(--fwt-metric-min-width, 160px), 100%), 1fr))"
|
|
8092
|
+
}
|
|
8093
|
+
});
|
|
8094
|
+
var formatMetricValue = (value, precision, locale) => typeof value === "number" ? new Intl.NumberFormat(locale, precision === void 0 ? void 0 : { minimumFractionDigits: precision, maximumFractionDigits: precision }).format(value) : value;
|
|
8095
|
+
function Metric({
|
|
8096
|
+
className,
|
|
8097
|
+
formatter,
|
|
8098
|
+
label,
|
|
8099
|
+
locale,
|
|
8100
|
+
precision,
|
|
8101
|
+
prefix,
|
|
8102
|
+
size = "title",
|
|
8103
|
+
suffix,
|
|
8104
|
+
tone = "default",
|
|
8105
|
+
value
|
|
8106
|
+
}) {
|
|
8107
|
+
const styles = useStyles12();
|
|
8108
|
+
const hasValue = value !== null && value !== void 0;
|
|
8109
|
+
const text = hasValue ? formatter ? formatter(value) : formatMetricValue(value, precision, locale) : "\u2014";
|
|
8110
|
+
return /* @__PURE__ */ jsxs14("div", { className: mergeClasses16(styles.root, className), children: [
|
|
8111
|
+
/* @__PURE__ */ jsx29("span", { className: styles.label, children: label }),
|
|
8112
|
+
/* @__PURE__ */ jsxs14("div", { className: mergeClasses16(styles.value, styles[size], tone !== "default" && styles[tone]), children: [
|
|
8113
|
+
prefix !== void 0 && /* @__PURE__ */ jsx29("span", { className: styles.affix, children: prefix }),
|
|
8114
|
+
/* @__PURE__ */ jsx29("span", { children: text }),
|
|
8115
|
+
suffix !== void 0 && /* @__PURE__ */ jsx29("span", { className: styles.affix, children: suffix })
|
|
8116
|
+
] })
|
|
8117
|
+
] });
|
|
8118
|
+
}
|
|
8119
|
+
function MetricGrid({ children, className, gap, minItemWidth }) {
|
|
8120
|
+
const styles = useStyles12();
|
|
8121
|
+
const style = {
|
|
8122
|
+
...minItemWidth !== void 0 && { "--fwt-metric-min-width": typeof minItemWidth === "number" ? `${minItemWidth}px` : minItemWidth },
|
|
8123
|
+
...gap !== void 0 && { "--fwt-metric-gap": typeof gap === "number" ? `${gap}px` : gap }
|
|
8124
|
+
};
|
|
8125
|
+
return /* @__PURE__ */ jsx29("div", { className: mergeClasses16(styles.grid, className), style, children });
|
|
8126
|
+
}
|
|
8127
|
+
|
|
8128
|
+
// src/components/ui/multiselect-combobox.tsx
|
|
8129
|
+
import { useState as useState8 } from "react";
|
|
8130
|
+
import { jsx as jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
8131
|
+
var { Option: Option3 } = fluentComponents;
|
|
8132
|
+
var sameValues = (left, right) => left.length === right.length && new Set(right).size === right.length && left.every((entry) => right.includes(entry));
|
|
8133
|
+
function MultiselectCombobox({
|
|
8134
|
+
ariaLabel,
|
|
8135
|
+
className,
|
|
8136
|
+
clearLabel,
|
|
8137
|
+
closedLabel = "",
|
|
8138
|
+
disabled = false,
|
|
8139
|
+
freeform = false,
|
|
8140
|
+
normalizeValue = (entry) => entry,
|
|
8141
|
+
onChange,
|
|
8142
|
+
options,
|
|
8143
|
+
placeholder,
|
|
8144
|
+
readOnly,
|
|
8145
|
+
renderOption,
|
|
8146
|
+
value
|
|
8147
|
+
}) {
|
|
8148
|
+
const [open, setOpen] = useState8(false);
|
|
8149
|
+
const [query, setQuery] = useState8("");
|
|
8150
|
+
const needle = query.trim().toLowerCase();
|
|
8151
|
+
const optionValues = new Set(options.map((option) => option.value));
|
|
8152
|
+
const completeOptions = [
|
|
8153
|
+
...options,
|
|
8154
|
+
...[...new Set(value)].filter((entry) => !optionValues.has(entry)).map((entry) => ({ value: entry, label: entry }))
|
|
8155
|
+
];
|
|
8156
|
+
const visible = completeOptions.filter((option) => option.label.toLowerCase().includes(needle));
|
|
8157
|
+
const commit = (next) => {
|
|
8158
|
+
const normalized = [...new Set(next.map(normalizeValue).filter(Boolean))];
|
|
8159
|
+
if (!sameValues(normalized, value)) onChange(normalized);
|
|
8160
|
+
setQuery("");
|
|
8161
|
+
};
|
|
8162
|
+
return /* @__PURE__ */ jsxs15(
|
|
8163
|
+
Combobox,
|
|
8164
|
+
{
|
|
8165
|
+
"aria-label": ariaLabel,
|
|
8166
|
+
className,
|
|
8167
|
+
disabled,
|
|
8168
|
+
freeform,
|
|
8169
|
+
multiselect: true,
|
|
8170
|
+
onChange: (event) => setQuery(event.target.value),
|
|
8171
|
+
onKeyDown: freeform ? (event) => {
|
|
8172
|
+
if (event.key !== "Enter" || query.trim() === "") return;
|
|
8173
|
+
event.preventDefault();
|
|
8174
|
+
commit([...value, query]);
|
|
8175
|
+
} : void 0,
|
|
8176
|
+
onOpenChange: (_2, data) => {
|
|
8177
|
+
setOpen(data.open);
|
|
8178
|
+
setQuery("");
|
|
8179
|
+
},
|
|
8180
|
+
onOptionSelect: (_2, data) => commit(data.optionValue === "" ? [] : data.selectedOptions),
|
|
8181
|
+
placeholder,
|
|
8182
|
+
readOnly,
|
|
8183
|
+
selectedOptions: clearLabel && value.length === 0 ? [""] : [...value],
|
|
8184
|
+
value: open ? query : closedLabel,
|
|
8185
|
+
children: [
|
|
8186
|
+
clearLabel && needle === "" && /* @__PURE__ */ jsx30(Option3, { text: clearLabel, value: "", children: clearLabel }),
|
|
8187
|
+
visible.map((option) => /* @__PURE__ */ jsx30(Option3, { text: option.label, value: option.value, children: renderOption ? renderOption(option) : option.label }, option.value))
|
|
8188
|
+
]
|
|
8189
|
+
}
|
|
8190
|
+
);
|
|
8191
|
+
}
|
|
8192
|
+
var valuesAsOptions = (values) => values.map((value) => ({ value, label: value }));
|
|
8193
|
+
|
|
8194
|
+
// src/components/ui/number-box.tsx
|
|
8195
|
+
import { forwardRef as forwardRef4, isValidElement } from "react";
|
|
8196
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
8197
|
+
var { SpinButton } = fluentComponents;
|
|
8198
|
+
var stepPrecision = (step) => {
|
|
8199
|
+
const text = String(step);
|
|
8200
|
+
const exponent = /e-(\d+)$/.exec(text);
|
|
8201
|
+
if (exponent) return Number(exponent[1]);
|
|
8202
|
+
return text.split(".")[1]?.length ?? 0;
|
|
8203
|
+
};
|
|
8204
|
+
var THOUSANDS_GROUPED = /^-?\d{1,3}(,\d{3})+(\.\d+)?$/;
|
|
8205
|
+
var parseNumberText = (text) => {
|
|
8206
|
+
const trimmed = text.trim().replace(/−/g, "-").replace(/\s/g, "");
|
|
8207
|
+
if (trimmed === "") return null;
|
|
8208
|
+
const normalized = THOUSANDS_GROUPED.test(trimmed) ? trimmed.replace(/,/g, "") : /^-?\d*,\d+$/.test(trimmed) ? trimmed.replace(",", ".") : trimmed;
|
|
8209
|
+
const parsed = Number(normalized);
|
|
8210
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
8211
|
+
};
|
|
8212
|
+
var clampNumber = (value, { min, max, precision }) => {
|
|
8213
|
+
let next = value;
|
|
8214
|
+
if (max !== void 0 && next > max) next = max;
|
|
8215
|
+
if (min !== void 0 && next < min) next = min;
|
|
8216
|
+
return precision === void 0 ? next : Number(next.toFixed(Math.min(Math.max(precision, 0), 100)));
|
|
8217
|
+
};
|
|
8218
|
+
var resolveNumberChange = (data, bounds) => {
|
|
8219
|
+
const raw = data.value !== void 0 ? data.value : data.displayValue !== void 0 ? parseNumberText(data.displayValue) : void 0;
|
|
8220
|
+
return typeof raw === "number" ? clampNumber(raw, bounds) : raw;
|
|
8221
|
+
};
|
|
8222
|
+
var labelSlot = (slot, label) => {
|
|
8223
|
+
if (slot === void 0) return { "aria-label": label };
|
|
8224
|
+
if (slot === null || typeof slot !== "object" || isValidElement(slot) || Symbol.iterator in slot) return slot;
|
|
8225
|
+
return { "aria-label": label, ...slot };
|
|
8226
|
+
};
|
|
8227
|
+
var NumberBox = forwardRef4(function NumberBox2({ value, onChange, min, max, step, precision, decrementButton, incrementButton, ...rest }, ref) {
|
|
8228
|
+
const { t: t2 } = useTranslation();
|
|
8229
|
+
const bounds = { min, max, precision: precision ?? stepPrecision(step ?? 1) };
|
|
8230
|
+
const handleChange = (_event, data) => {
|
|
8231
|
+
const next = resolveNumberChange(data, bounds);
|
|
8232
|
+
if (next !== void 0) onChange(next);
|
|
8233
|
+
};
|
|
8234
|
+
return /* @__PURE__ */ jsx31(
|
|
8235
|
+
SpinButton,
|
|
8236
|
+
{
|
|
8237
|
+
...rest,
|
|
8238
|
+
decrementButton: labelSlot(decrementButton, t2("numberBox.decrement")),
|
|
8239
|
+
incrementButton: labelSlot(incrementButton, t2("numberBox.increment")),
|
|
8240
|
+
max,
|
|
8241
|
+
min,
|
|
8242
|
+
onChange: handleChange,
|
|
8243
|
+
precision,
|
|
8244
|
+
ref,
|
|
8245
|
+
step,
|
|
8246
|
+
value
|
|
8247
|
+
}
|
|
8248
|
+
);
|
|
8249
|
+
});
|
|
8250
|
+
|
|
8251
|
+
// src/components/ui/open-link-label.tsx
|
|
8252
|
+
import { Open16Regular } from "@fluentui/react-icons";
|
|
8253
|
+
import { jsx as jsx32, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
8254
|
+
function OpenLinkLabel({ children }) {
|
|
8255
|
+
return /* @__PURE__ */ jsxs16("span", { className: "inline-flex items-center gap-1", children: [
|
|
8256
|
+
children,
|
|
8257
|
+
/* @__PURE__ */ jsx32(Open16Regular, { "aria-hidden": true, className: "block flex-none" })
|
|
8258
|
+
] });
|
|
8259
|
+
}
|
|
8260
|
+
|
|
8261
|
+
// src/components/ui/outcome-toast.tsx
|
|
8262
|
+
import { createContext as createContext3, useCallback as useCallback5, useContext as useContext3, useId as useId3, useMemo as useMemo4, useRef as useRef6 } from "react";
|
|
8263
|
+
import { jsx as jsx33, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
8264
|
+
var { Spinner: Spinner4, Toast, Toaster, ToastTitle, useToastController } = fluentComponents;
|
|
7367
8265
|
var TOAST_DISMISS_MS = 3e3;
|
|
7368
8266
|
var OutcomeToastContext = createContext3(null);
|
|
8267
|
+
var ToastApiContext = createContext3(null);
|
|
7369
8268
|
function OutcomeToastProvider({ children }) {
|
|
7370
|
-
|
|
7371
|
-
|
|
8269
|
+
return useContext3(OutcomeToastContext) ? children : /* @__PURE__ */ jsx33(ToasterHost, { children });
|
|
8270
|
+
}
|
|
8271
|
+
function ToasterHost({ children }) {
|
|
8272
|
+
const toasterId = useId3();
|
|
8273
|
+
const sequence = useRef6(0);
|
|
7372
8274
|
const { dispatchToast, dismissToast, updateToast } = useToastController(toasterId);
|
|
7373
|
-
const toastFor =
|
|
7374
|
-
const nextToastId =
|
|
7375
|
-
const succeed =
|
|
8275
|
+
const toastFor = useCallback5((toastId, message, pending) => /* @__PURE__ */ jsx33(Toast, { className: "cursor-pointer", onClick: () => dismissToast(toastId), children: /* @__PURE__ */ jsx33(ToastTitle, { media: pending ? /* @__PURE__ */ jsx33(Spinner4, { size: "tiny" }) : void 0, children: message }) }), [dismissToast]);
|
|
8276
|
+
const nextToastId = useCallback5(() => `${toasterId}-${sequence.current++}`, [toasterId]);
|
|
8277
|
+
const succeed = useCallback5((message) => {
|
|
7376
8278
|
const toastId = nextToastId();
|
|
7377
8279
|
dispatchToast(toastFor(toastId, message, false), { intent: "success", toastId, timeout: TOAST_DISMISS_MS });
|
|
7378
8280
|
}, [dispatchToast, nextToastId, toastFor]);
|
|
7379
|
-
const start =
|
|
8281
|
+
const start = useCallback5((pending) => {
|
|
7380
8282
|
const toastId = nextToastId();
|
|
7381
8283
|
dispatchToast(toastFor(toastId, pending, true), { toastId, timeout: -1 });
|
|
7382
8284
|
return {
|
|
@@ -7389,21 +8291,37 @@ function OutcomeToastProvider({ children }) {
|
|
|
7389
8291
|
settle: () => dismissToast(toastId)
|
|
7390
8292
|
};
|
|
7391
8293
|
}, [dismissToast, dispatchToast, nextToastId, toastFor, updateToast]);
|
|
7392
|
-
const value =
|
|
7393
|
-
|
|
7394
|
-
|
|
8294
|
+
const value = useMemo4(() => ({ start, succeed }), [start, succeed]);
|
|
8295
|
+
const notify = useCallback5((intent, text, options) => {
|
|
8296
|
+
const toastId = nextToastId();
|
|
8297
|
+
dispatchToast(toastFor(toastId, text, false), { intent, toastId, timeout: options?.timeout ?? TOAST_DISMISS_MS });
|
|
8298
|
+
return () => dismissToast(toastId);
|
|
8299
|
+
}, [dismissToast, dispatchToast, nextToastId, toastFor]);
|
|
8300
|
+
const api = useMemo4(() => ({
|
|
8301
|
+
success: (text, options) => notify("success", text, options),
|
|
8302
|
+
error: (text, options) => notify("error", text, options),
|
|
8303
|
+
warning: (text, options) => notify("warning", text, options),
|
|
8304
|
+
info: (text, options) => notify("info", text, options)
|
|
8305
|
+
}), [notify]);
|
|
8306
|
+
return /* @__PURE__ */ jsx33(OutcomeToastContext.Provider, { value, children: /* @__PURE__ */ jsxs17(ToastApiContext.Provider, { value: api, children: [
|
|
8307
|
+
/* @__PURE__ */ jsx33(Toaster, { toasterId, position: "top-end" }),
|
|
7395
8308
|
children
|
|
7396
|
-
] });
|
|
8309
|
+
] }) });
|
|
7397
8310
|
}
|
|
7398
8311
|
var useOutcomeToasts = () => {
|
|
7399
8312
|
const value = useContext3(OutcomeToastContext);
|
|
7400
8313
|
if (!value) throw new Error("useOutcomeToasts requires an OutcomeToastProvider above it");
|
|
7401
8314
|
return value;
|
|
7402
8315
|
};
|
|
8316
|
+
var useToast = () => {
|
|
8317
|
+
const value = useContext3(ToastApiContext);
|
|
8318
|
+
if (!value) throw new Error("useToast requires an OutcomeToastProvider above it");
|
|
8319
|
+
return value;
|
|
8320
|
+
};
|
|
7403
8321
|
|
|
7404
8322
|
// src/components/ui/panel.tsx
|
|
7405
|
-
import { jsx as
|
|
7406
|
-
var { Card, mergeClasses:
|
|
8323
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
8324
|
+
var { Card, mergeClasses: mergeClasses17 } = fluentComponents;
|
|
7407
8325
|
var PANEL_INSET_CLASS = "p-[var(--fwt-panel-inset)]";
|
|
7408
8326
|
var PANEL_BAND_CLASS = "px-[var(--fwt-panel-inset)] py-[var(--spacingVerticalSNudge)]";
|
|
7409
8327
|
var PADDING_CLASS = {
|
|
@@ -7411,12 +8329,127 @@ var PADDING_CLASS = {
|
|
|
7411
8329
|
flush: "!p-0"
|
|
7412
8330
|
};
|
|
7413
8331
|
function Panel({ className, padding = "content", ...props }) {
|
|
7414
|
-
return /* @__PURE__ */
|
|
8332
|
+
return /* @__PURE__ */ jsx34(Card, { ...props, className: mergeClasses17(PADDING_CLASS[padding], className) });
|
|
8333
|
+
}
|
|
8334
|
+
|
|
8335
|
+
// src/components/ui/property-list.tsx
|
|
8336
|
+
import { jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
8337
|
+
var { makeStyles: makeStyles13, mergeClasses: mergeClasses18, shorthands: shorthands2 } = fluentComponents;
|
|
8338
|
+
var NARROW = "@container fwt-property-list (width < 480px)";
|
|
8339
|
+
var MEDIUM = "@container fwt-property-list (480px <= width < 720px)";
|
|
8340
|
+
var useStyles13 = makeStyles13({
|
|
8341
|
+
container: {
|
|
8342
|
+
containerName: "fwt-property-list",
|
|
8343
|
+
containerType: "inline-size",
|
|
8344
|
+
minWidth: 0
|
|
8345
|
+
},
|
|
8346
|
+
// Cell lines are each cell's own right and bottom edge. The list is pulled
|
|
8347
|
+
// 1px past the frame on those two sides so the last column's and last row's
|
|
8348
|
+
// lines fall under the frame's clip and the frame's own border stands in.
|
|
8349
|
+
frame: {
|
|
8350
|
+
...shorthands2.border("1px", "solid", "var(--winui-divider-stroke-default)"),
|
|
8351
|
+
borderRadius: "var(--winui-control-corner-radius)",
|
|
8352
|
+
overflow: "hidden"
|
|
8353
|
+
},
|
|
8354
|
+
list: {
|
|
8355
|
+
display: "grid",
|
|
8356
|
+
gridTemplateColumns: "repeat(var(--fwt-property-columns, 2), minmax(0, 1fr))",
|
|
8357
|
+
margin: 0,
|
|
8358
|
+
columnGap: "24px",
|
|
8359
|
+
rowGap: "12px",
|
|
8360
|
+
[NARROW]: { gridTemplateColumns: "minmax(0, 1fr)" }
|
|
8361
|
+
},
|
|
8362
|
+
listWrapsToTwo: {
|
|
8363
|
+
[MEDIUM]: { gridTemplateColumns: "repeat(2, minmax(0, 1fr))" }
|
|
8364
|
+
},
|
|
8365
|
+
listBordered: {
|
|
8366
|
+
columnGap: 0,
|
|
8367
|
+
rowGap: 0,
|
|
8368
|
+
marginRight: "-1px",
|
|
8369
|
+
marginBottom: "-1px"
|
|
8370
|
+
},
|
|
8371
|
+
item: {
|
|
8372
|
+
display: "grid",
|
|
8373
|
+
gridColumn: "span var(--fwt-span, 1)",
|
|
8374
|
+
minWidth: 0,
|
|
8375
|
+
rowGap: "2px",
|
|
8376
|
+
[NARROW]: { "&[data-wide]": { gridColumn: "1 / -1" } }
|
|
8377
|
+
},
|
|
8378
|
+
itemWrapsToTwo: {
|
|
8379
|
+
[MEDIUM]: { "&[data-wide]": { gridColumn: "1 / -1" } }
|
|
8380
|
+
},
|
|
8381
|
+
itemBordered: {
|
|
8382
|
+
borderBottom: "1px solid var(--winui-divider-stroke-default)",
|
|
8383
|
+
borderRight: "1px solid var(--winui-divider-stroke-default)",
|
|
8384
|
+
gridTemplateColumns: "var(--fwt-property-label-width, 120px) minmax(0, 1fr)",
|
|
8385
|
+
rowGap: 0
|
|
8386
|
+
},
|
|
8387
|
+
label: {
|
|
8388
|
+
color: "var(--winui-text-fill-secondary)",
|
|
8389
|
+
fontSize: "var(--fontSizeBase200)",
|
|
8390
|
+
lineHeight: "var(--lineHeightBase200)",
|
|
8391
|
+
margin: 0,
|
|
8392
|
+
minWidth: 0
|
|
8393
|
+
},
|
|
8394
|
+
value: {
|
|
8395
|
+
color: "var(--winui-text-fill-primary)",
|
|
8396
|
+
fontSize: "var(--fontSizeBase300)",
|
|
8397
|
+
lineHeight: "var(--lineHeightBase300)",
|
|
8398
|
+
margin: 0,
|
|
8399
|
+
minWidth: 0,
|
|
8400
|
+
overflowWrap: "anywhere"
|
|
8401
|
+
},
|
|
8402
|
+
labelBordered: {
|
|
8403
|
+
backgroundColor: "var(--winui-card-background-fill-secondary)",
|
|
8404
|
+
borderRight: "1px solid var(--winui-divider-stroke-default)",
|
|
8405
|
+
fontSize: "var(--fontSizeBase300)",
|
|
8406
|
+
lineHeight: "var(--lineHeightBase300)",
|
|
8407
|
+
padding: "8px 12px"
|
|
8408
|
+
},
|
|
8409
|
+
valueBordered: {
|
|
8410
|
+
backgroundColor: "var(--winui-card-background-fill-default)",
|
|
8411
|
+
padding: "8px 12px"
|
|
8412
|
+
}
|
|
8413
|
+
});
|
|
8414
|
+
function PropertyList({ bordered, className, columns = 2, items }) {
|
|
8415
|
+
const styles = useStyles13();
|
|
8416
|
+
const columnCount = Math.max(1, Math.floor(columns));
|
|
8417
|
+
const stepsDown = columnCount > 2;
|
|
8418
|
+
const list = /* @__PURE__ */ jsx35(
|
|
8419
|
+
"dl",
|
|
8420
|
+
{
|
|
8421
|
+
className: mergeClasses18(styles.list, stepsDown && styles.listWrapsToTwo, bordered && styles.listBordered),
|
|
8422
|
+
children: items.map((item, index) => {
|
|
8423
|
+
const span = Math.min(Math.max(1, Math.floor(item.span ?? 1)), columnCount);
|
|
8424
|
+
return /* @__PURE__ */ jsxs18(
|
|
8425
|
+
"div",
|
|
8426
|
+
{
|
|
8427
|
+
className: mergeClasses18(styles.item, stepsDown && styles.itemWrapsToTwo, bordered && styles.itemBordered),
|
|
8428
|
+
"data-wide": span > 1 ? "" : void 0,
|
|
8429
|
+
style: { "--fwt-span": span },
|
|
8430
|
+
children: [
|
|
8431
|
+
/* @__PURE__ */ jsx35("dt", { className: mergeClasses18(styles.label, bordered && styles.labelBordered), children: item.label }),
|
|
8432
|
+
/* @__PURE__ */ jsx35("dd", { className: mergeClasses18(styles.value, bordered && styles.valueBordered), children: item.value })
|
|
8433
|
+
]
|
|
8434
|
+
},
|
|
8435
|
+
item.key ?? index
|
|
8436
|
+
);
|
|
8437
|
+
})
|
|
8438
|
+
}
|
|
8439
|
+
);
|
|
8440
|
+
return /* @__PURE__ */ jsx35(
|
|
8441
|
+
"div",
|
|
8442
|
+
{
|
|
8443
|
+
className: mergeClasses18(styles.container, bordered && styles.frame, className),
|
|
8444
|
+
style: { "--fwt-property-columns": columnCount },
|
|
8445
|
+
children: list
|
|
8446
|
+
}
|
|
8447
|
+
);
|
|
7415
8448
|
}
|
|
7416
8449
|
|
|
7417
8450
|
// src/components/ui/progress-ring.tsx
|
|
7418
|
-
import { jsx as
|
|
7419
|
-
var { makeStyles:
|
|
8451
|
+
import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
8452
|
+
var { makeStyles: makeStyles14, mergeClasses: mergeClasses19 } = fluentComponents;
|
|
7420
8453
|
var DIAMETER = 32;
|
|
7421
8454
|
var STROKE = 4;
|
|
7422
8455
|
var RADIUS = (DIAMETER - STROKE) / 2;
|
|
@@ -7427,7 +8460,7 @@ var TONE_STROKE = {
|
|
|
7427
8460
|
caution: "var(--winui-system-fill-caution)",
|
|
7428
8461
|
critical: "var(--winui-system-fill-critical)"
|
|
7429
8462
|
};
|
|
7430
|
-
var
|
|
8463
|
+
var useStyles14 = makeStyles14({
|
|
7431
8464
|
// A forced-colours palette repaints background and border colours but not an
|
|
7432
8465
|
// SVG stroke, so each ring names its system colour itself: Highlight is what
|
|
7433
8466
|
// HighContrast gives ProgressRingForegroundThemeBrush through
|
|
@@ -7446,19 +8479,19 @@ var useStyles10 = makeStyles10({
|
|
|
7446
8479
|
}
|
|
7447
8480
|
});
|
|
7448
8481
|
function ProgressRing({ className, percent, size = 16, tone }) {
|
|
7449
|
-
const styles =
|
|
8482
|
+
const styles = useStyles14();
|
|
7450
8483
|
const filled = Math.max(0, Math.min(100, percent)) / 100;
|
|
7451
|
-
return /* @__PURE__ */
|
|
8484
|
+
return /* @__PURE__ */ jsxs19(
|
|
7452
8485
|
"svg",
|
|
7453
8486
|
{
|
|
7454
8487
|
"aria-hidden": true,
|
|
7455
|
-
className:
|
|
8488
|
+
className: mergeClasses19("block flex-none", className),
|
|
7456
8489
|
height: size,
|
|
7457
8490
|
style: { transform: "translateY(calc(50% - 0.5cap))" },
|
|
7458
8491
|
viewBox: `0 0 ${DIAMETER} ${DIAMETER}`,
|
|
7459
8492
|
width: size,
|
|
7460
8493
|
children: [
|
|
7461
|
-
/* @__PURE__ */
|
|
8494
|
+
/* @__PURE__ */ jsx36(
|
|
7462
8495
|
"circle",
|
|
7463
8496
|
{
|
|
7464
8497
|
className: styles.track,
|
|
@@ -7470,7 +8503,7 @@ function ProgressRing({ className, percent, size = 16, tone }) {
|
|
|
7470
8503
|
strokeWidth: TRACK_STROKE
|
|
7471
8504
|
}
|
|
7472
8505
|
),
|
|
7473
|
-
/* @__PURE__ */
|
|
8506
|
+
/* @__PURE__ */ jsx36(
|
|
7474
8507
|
"circle",
|
|
7475
8508
|
{
|
|
7476
8509
|
className: styles.arc,
|
|
@@ -7492,9 +8525,9 @@ function ProgressRing({ className, percent, size = 16, tone }) {
|
|
|
7492
8525
|
|
|
7493
8526
|
// src/components/ui/reorder-list.tsx
|
|
7494
8527
|
import { ReOrderDotsVerticalRegular } from "@fluentui/react-icons";
|
|
7495
|
-
import { useEffect as useEffect5, useMemo as
|
|
7496
|
-
import { jsx as
|
|
7497
|
-
var { Button:
|
|
8528
|
+
import { useEffect as useEffect5, useMemo as useMemo5, useRef as useRef7, useState as useState9 } from "react";
|
|
8529
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
8530
|
+
var { Button: Button9, makeStyles: makeStyles15, mergeClasses: mergeClasses20 } = fluentComponents;
|
|
7498
8531
|
var REORDER_OPACITY = 0.8;
|
|
7499
8532
|
var DRAG_RETURN_MS = 200;
|
|
7500
8533
|
var LIST_ATTRIBUTE = "data-reorder-list";
|
|
@@ -7504,7 +8537,7 @@ var EDGE_ATTRIBUTE = "data-reorder-edge";
|
|
|
7504
8537
|
var HANDLE_ATTRIBUTE = "data-reorder-handle";
|
|
7505
8538
|
var DRAG_Y = "--fwt-reorder-drag-y";
|
|
7506
8539
|
var TRACKING_TRANSFORM = { transform: `translateY(var(${DRAG_Y}, 0px))` };
|
|
7507
|
-
var
|
|
8540
|
+
var useStyles15 = makeStyles15({
|
|
7508
8541
|
// A drag that starts on the handle travels over the rows, and without this
|
|
7509
8542
|
// the browser reads that travel as a text selection across them.
|
|
7510
8543
|
list: { [`&[${REORDERING_ATTRIBUTE}]`]: { userSelect: "none" } },
|
|
@@ -7593,11 +8626,11 @@ var siblingHandles = (handle) => {
|
|
|
7593
8626
|
return [...list.querySelectorAll(`[${HANDLE_ATTRIBUTE}]`)].filter((element) => element.closest(`[${LIST_ATTRIBUTE}]`) === list && !element.hasAttribute("disabled"));
|
|
7594
8627
|
};
|
|
7595
8628
|
function useReorderList({ busy = false, disabled = false, length, onDrop, onDropError, onReorder }) {
|
|
7596
|
-
const styles =
|
|
7597
|
-
const gestureRef =
|
|
7598
|
-
const settleRef =
|
|
7599
|
-
const mountedRef =
|
|
7600
|
-
const [preview, setPreview] =
|
|
8629
|
+
const styles = useStyles15();
|
|
8630
|
+
const gestureRef = useRef7(null);
|
|
8631
|
+
const settleRef = useRef7(void 0);
|
|
8632
|
+
const mountedRef = useRef7(true);
|
|
8633
|
+
const [preview, setPreview] = useState9(null);
|
|
7601
8634
|
const locked = busy || disabled || length < 2;
|
|
7602
8635
|
const live = preview !== null && preview.from < length && preview.to < length ? preview : null;
|
|
7603
8636
|
useEffect5(() => {
|
|
@@ -7607,8 +8640,8 @@ function useReorderList({ busy = false, disabled = false, length, onDrop, onDrop
|
|
|
7607
8640
|
clearTimeout(settleRef.current);
|
|
7608
8641
|
};
|
|
7609
8642
|
}, []);
|
|
7610
|
-
const offsets =
|
|
7611
|
-
const ranks =
|
|
8643
|
+
const offsets = useMemo5(() => live && slotOffsets(live.items, live.from, live.to), [live]);
|
|
8644
|
+
const ranks = useMemo5(
|
|
7612
8645
|
() => live && moveItem(Array.from({ length }, (_2, index) => index), live.from, live.to),
|
|
7613
8646
|
[length, live]
|
|
7614
8647
|
);
|
|
@@ -7737,7 +8770,7 @@ function useReorderList({ busy = false, disabled = false, length, onDrop, onDrop
|
|
|
7737
8770
|
return {
|
|
7738
8771
|
[ITEM_ATTRIBUTE]: String(index),
|
|
7739
8772
|
[EDGE_ATTRIBUTE]: !live ? void 0 : rank === 0 ? "first" : rank === length - 1 ? "last" : void 0,
|
|
7740
|
-
className:
|
|
8773
|
+
className: mergeClasses20(
|
|
7741
8774
|
grabbed && styles.lifted,
|
|
7742
8775
|
// The row under the pointer is not travelling toward anything -- it is
|
|
7743
8776
|
// where the pointer put it -- so it wears the drag opacity flat, and
|
|
@@ -7749,20 +8782,20 @@ function useReorderList({ busy = false, disabled = false, length, onDrop, onDrop
|
|
|
7749
8782
|
style: !live ? void 0 : grabbed ? TRACKING_TRANSFORM : { transform: `translateY(${offsets?.get(index) ?? 0}px)` }
|
|
7750
8783
|
};
|
|
7751
8784
|
},
|
|
7752
|
-
listProps: (className) => ({ [LIST_ATTRIBUTE]: "", className:
|
|
8785
|
+
listProps: (className) => ({ [LIST_ATTRIBUTE]: "", className: mergeClasses20(styles.list, className), onKeyDown }),
|
|
7753
8786
|
position
|
|
7754
8787
|
};
|
|
7755
8788
|
}
|
|
7756
8789
|
function ReorderHandle({ label, ...gesture }) {
|
|
7757
|
-
const styles =
|
|
7758
|
-
return /* @__PURE__ */
|
|
7759
|
-
|
|
8790
|
+
const styles = useStyles15();
|
|
8791
|
+
return /* @__PURE__ */ jsx37(
|
|
8792
|
+
Button9,
|
|
7760
8793
|
{
|
|
7761
8794
|
appearance: "subtle",
|
|
7762
8795
|
"aria-keyshortcuts": `${REORDER_CHORD}+ArrowUp ${REORDER_CHORD}+ArrowDown`,
|
|
7763
8796
|
"aria-label": label,
|
|
7764
8797
|
className: styles.handle,
|
|
7765
|
-
icon: /* @__PURE__ */
|
|
8798
|
+
icon: /* @__PURE__ */ jsx37(ReOrderDotsVerticalRegular, {}),
|
|
7766
8799
|
size: "small",
|
|
7767
8800
|
...gesture
|
|
7768
8801
|
}
|
|
@@ -7771,12 +8804,12 @@ function ReorderHandle({ label, ...gesture }) {
|
|
|
7771
8804
|
|
|
7772
8805
|
// src/components/ui/resource-list.tsx
|
|
7773
8806
|
import { AddRegular, ArrowClockwiseRegular } from "@fluentui/react-icons";
|
|
7774
|
-
import { jsx as
|
|
7775
|
-
var { Button:
|
|
8807
|
+
import { jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
8808
|
+
var { Button: Button10, Spinner: Spinner5, Tooltip: Tooltip3, makeStyles: makeStyles16, mergeClasses: mergeClasses21 } = fluentComponents;
|
|
7776
8809
|
var DEFAULT_ROW_HEIGHT = "44px";
|
|
7777
8810
|
var ROW_HEIGHT = "--fwt-resource-row-height";
|
|
7778
8811
|
var EDGE_INSET = "var(--fwt-panel-inset)";
|
|
7779
|
-
var
|
|
8812
|
+
var useStyles16 = makeStyles16({
|
|
7780
8813
|
table: {
|
|
7781
8814
|
"& .fui-TableRow": { height: `var(${ROW_HEIGHT})` },
|
|
7782
8815
|
// By type rather than by position: a DataGrid row carries Tabster's focus
|
|
@@ -7809,12 +8842,12 @@ var useStyles12 = makeStyles12({
|
|
|
7809
8842
|
emptyState: { padding: EDGE_INSET }
|
|
7810
8843
|
});
|
|
7811
8844
|
function ResourceListPanel({ className, rowHeight = DEFAULT_ROW_HEIGHT, style, ...props }) {
|
|
7812
|
-
const styles =
|
|
7813
|
-
return /* @__PURE__ */
|
|
8845
|
+
const styles = useStyles16();
|
|
8846
|
+
return /* @__PURE__ */ jsx38(
|
|
7814
8847
|
Panel,
|
|
7815
8848
|
{
|
|
7816
8849
|
...props,
|
|
7817
|
-
className:
|
|
8850
|
+
className: mergeClasses21("grid min-w-0 !gap-0 overflow-hidden", styles.table, className),
|
|
7818
8851
|
padding: "flush",
|
|
7819
8852
|
style: { ...style, [ROW_HEIGHT]: rowHeight }
|
|
7820
8853
|
}
|
|
@@ -7823,12 +8856,12 @@ function ResourceListPanel({ className, rowHeight = DEFAULT_ROW_HEIGHT, style, .
|
|
|
7823
8856
|
function ResourceListActions(props) {
|
|
7824
8857
|
const { appearance, createDisabled = false, createLabel, createTrailingIcon, disabled = false, onRefresh, refreshLabel, refreshing = false } = props;
|
|
7825
8858
|
const busy = disabled || createDisabled || refreshing;
|
|
7826
|
-
const createButton = createLabel !== void 0 && /* @__PURE__ */
|
|
7827
|
-
|
|
8859
|
+
const createButton = createLabel !== void 0 && /* @__PURE__ */ jsxs20(
|
|
8860
|
+
Button10,
|
|
7828
8861
|
{
|
|
7829
8862
|
appearance: "primary",
|
|
7830
8863
|
disabled: busy,
|
|
7831
|
-
icon: /* @__PURE__ */
|
|
8864
|
+
icon: /* @__PURE__ */ jsx38(AddRegular, {}),
|
|
7832
8865
|
onClick: "onCreate" in props ? props.onCreate : void 0,
|
|
7833
8866
|
children: [
|
|
7834
8867
|
createLabel,
|
|
@@ -7836,43 +8869,43 @@ function ResourceListActions(props) {
|
|
|
7836
8869
|
]
|
|
7837
8870
|
}
|
|
7838
8871
|
);
|
|
7839
|
-
return /* @__PURE__ */
|
|
7840
|
-
/* @__PURE__ */
|
|
7841
|
-
|
|
8872
|
+
return /* @__PURE__ */ jsxs20("div", { "aria-busy": refreshing, className: "flex items-center gap-2 flex-none", children: [
|
|
8873
|
+
/* @__PURE__ */ jsx38(Tooltip3, { content: refreshLabel, relationship: "label", children: /* @__PURE__ */ jsx38(
|
|
8874
|
+
Button10,
|
|
7842
8875
|
{
|
|
7843
8876
|
appearance,
|
|
7844
8877
|
"aria-label": refreshLabel,
|
|
7845
8878
|
disabled,
|
|
7846
8879
|
disabledFocusable: refreshing,
|
|
7847
|
-
icon: refreshing ? /* @__PURE__ */
|
|
8880
|
+
icon: refreshing ? /* @__PURE__ */ jsx38(Spinner5, { size: "tiny" }) : /* @__PURE__ */ jsx38(ArrowClockwiseRegular, {}),
|
|
7848
8881
|
onClick: onRefresh
|
|
7849
8882
|
}
|
|
7850
8883
|
) }),
|
|
7851
8884
|
createButton && (props.createTrigger === void 0 ? createButton : props.createTrigger(createButton)),
|
|
7852
|
-
/* @__PURE__ */
|
|
8885
|
+
/* @__PURE__ */ jsx38("span", { "aria-live": "polite", className: "sr-only", children: refreshing ? `${refreshLabel}\u2026` : "" })
|
|
7853
8886
|
] });
|
|
7854
8887
|
}
|
|
7855
8888
|
function ResourceListEmptyState({ children }) {
|
|
7856
|
-
const styles =
|
|
7857
|
-
return /* @__PURE__ */
|
|
8889
|
+
const styles = useStyles16();
|
|
8890
|
+
return /* @__PURE__ */ jsx38(EmptyStateLine, { className: styles.emptyState, children });
|
|
7858
8891
|
}
|
|
7859
8892
|
|
|
7860
8893
|
// src/components/ui/row-title.tsx
|
|
7861
|
-
import { jsx as
|
|
7862
|
-
var { mergeClasses:
|
|
8894
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
8895
|
+
var { mergeClasses: mergeClasses22 } = fluentComponents;
|
|
7863
8896
|
var rowTitleClass = "winui-focus-rect text-fui-fg1 no-underline hover:underline";
|
|
7864
8897
|
function RowTitleButton({ children, onClick, ...trigger }) {
|
|
7865
|
-
return /* @__PURE__ */
|
|
8898
|
+
return /* @__PURE__ */ jsx39("button", { className: mergeClasses22(rowTitleClass, "block bg-transparent border-0 cursor-pointer leading-[var(--lineHeightBase300)] min-w-0 max-w-full truncate p-0 text-fui-base300 text-left"), onClick, type: "button", ...trigger, children });
|
|
7866
8899
|
}
|
|
7867
8900
|
|
|
7868
8901
|
// src/components/ui/secret-input.tsx
|
|
7869
|
-
import { useState as
|
|
7870
|
-
import { jsx as
|
|
8902
|
+
import { useState as useState10 } from "react";
|
|
8903
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
7871
8904
|
function SecretInput({ onChange, revealed = false, value, ...rest }) {
|
|
7872
|
-
const [guardLocked, setGuardLocked] =
|
|
8905
|
+
const [guardLocked, setGuardLocked] = useState10(true);
|
|
7873
8906
|
const hasValue = String(value ?? "").length > 0;
|
|
7874
8907
|
const unlock = () => setGuardLocked(false);
|
|
7875
|
-
return /* @__PURE__ */
|
|
8908
|
+
return /* @__PURE__ */ jsx40(
|
|
7876
8909
|
Input,
|
|
7877
8910
|
{
|
|
7878
8911
|
...rest,
|
|
@@ -7913,12 +8946,12 @@ function SecretInput({ onChange, revealed = false, value, ...rest }) {
|
|
|
7913
8946
|
}
|
|
7914
8947
|
|
|
7915
8948
|
// src/components/ui/section-header.tsx
|
|
7916
|
-
import { jsx as
|
|
7917
|
-
var { InfoButton, Text:
|
|
8949
|
+
import { jsx as jsx41, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
8950
|
+
var { InfoButton, Text: Text7, mergeClasses: mergeClasses23 } = fluentComponents;
|
|
7918
8951
|
var TITLE_SIZE = { 2: 500, 3: 400, 4: 300 };
|
|
7919
8952
|
function SectionHeader({ actions, description, info, level, title, titleId, truncate = false }) {
|
|
7920
|
-
const headingText = /* @__PURE__ */
|
|
7921
|
-
|
|
8953
|
+
const headingText = /* @__PURE__ */ jsx41(
|
|
8954
|
+
Text7,
|
|
7922
8955
|
{
|
|
7923
8956
|
as: `h${level}`,
|
|
7924
8957
|
className: description === void 0 ? "m-0 min-w-0" : "m-0",
|
|
@@ -7930,25 +8963,25 @@ function SectionHeader({ actions, description, info, level, title, titleId, trun
|
|
|
7930
8963
|
children: title
|
|
7931
8964
|
}
|
|
7932
8965
|
);
|
|
7933
|
-
const heading = info === void 0 ? headingText : /* @__PURE__ */
|
|
8966
|
+
const heading = info === void 0 ? headingText : /* @__PURE__ */ jsxs21("div", { className: "inline-flex items-center gap-1 min-w-0", children: [
|
|
7934
8967
|
headingText,
|
|
7935
|
-
/* @__PURE__ */
|
|
8968
|
+
/* @__PURE__ */ jsx41(InfoButton, { info })
|
|
7936
8969
|
] });
|
|
7937
|
-
const block = description === void 0 ? heading : /* @__PURE__ */
|
|
8970
|
+
const block = description === void 0 ? heading : /* @__PURE__ */ jsxs21("div", { className: mergeClasses23(TIGHT_STACK_CLASS, "min-w-0"), children: [
|
|
7938
8971
|
heading,
|
|
7939
|
-
/* @__PURE__ */
|
|
8972
|
+
/* @__PURE__ */ jsx41(Text7, { className: "text-fui-fg2", size: 200, children: description })
|
|
7940
8973
|
] });
|
|
7941
8974
|
if (actions === void 0) return block;
|
|
7942
|
-
return /* @__PURE__ */
|
|
8975
|
+
return /* @__PURE__ */ jsxs21("div", { className: mergeClasses23(HEADER_ROW_CLASS, "gap-3"), children: [
|
|
7943
8976
|
block,
|
|
7944
|
-
/* @__PURE__ */
|
|
8977
|
+
/* @__PURE__ */ jsx41("div", { className: "flex items-center gap-2 flex-none", children: actions })
|
|
7945
8978
|
] });
|
|
7946
8979
|
}
|
|
7947
8980
|
|
|
7948
8981
|
// src/components/ui/settings-card.tsx
|
|
7949
|
-
import { useId as
|
|
7950
|
-
import { Fragment as
|
|
7951
|
-
var { Text:
|
|
8982
|
+
import { useId as useId4, useState as useState11 } from "react";
|
|
8983
|
+
import { Fragment as Fragment3, jsx as jsx42, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
8984
|
+
var { Text: Text8, makeStyles: makeStyles17, mergeClasses: mergeClasses24, shorthands: shorthands3 } = fluentComponents;
|
|
7952
8985
|
var ICON_MARGIN_START = "2px";
|
|
7953
8986
|
var ICON_MARGIN_END = "20px";
|
|
7954
8987
|
var ICON_SIZE = "24px";
|
|
@@ -7958,7 +8991,7 @@ var ICON_COLUMN_VAR = "var(--fwt-settings-icon-column, 0px)";
|
|
|
7958
8991
|
var WRAPPED = "@container fwt-settings-row (width < 476px)";
|
|
7959
8992
|
var WRAPPED_WITH_ICON = "@container fwt-settings-row (286px <= width < 476px)";
|
|
7960
8993
|
var WRAPPED_NO_ICON = "@container fwt-settings-row (width < 286px)";
|
|
7961
|
-
var
|
|
8994
|
+
var useStyles17 = makeStyles17({
|
|
7962
8995
|
// Containment sits one level out of the row so the query measures the same
|
|
7963
8996
|
// box the toolkit's trigger reads (this element carries no padding or
|
|
7964
8997
|
// border), and so the wrapped state can style the row itself -- a container
|
|
@@ -7987,7 +9020,7 @@ var useStyles13 = makeStyles13({
|
|
|
7987
9020
|
borderRightWidth: "1px",
|
|
7988
9021
|
borderBottomWidth: "1px",
|
|
7989
9022
|
borderLeftWidth: "1px",
|
|
7990
|
-
...
|
|
9023
|
+
...shorthands3.borderColor("var(--winui-card-stroke-default)"),
|
|
7991
9024
|
borderRadius: "var(--winui-control-corner-radius)",
|
|
7992
9025
|
boxSizing: "border-box",
|
|
7993
9026
|
color: "var(--winui-text-fill-primary)",
|
|
@@ -8030,21 +9063,19 @@ var useStyles13 = makeStyles13({
|
|
|
8030
9063
|
// and the dark one does not.
|
|
8031
9064
|
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/CommonStyles/Common_themeresources_any.xaml#L382-L390
|
|
8032
9065
|
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/CommonStyles/Common_themeresources_any.xaml#L186-L191
|
|
8033
|
-
|
|
9066
|
+
// base.css picks the two stops per scheme, where `data-fwt-theme` can
|
|
9067
|
+
// override the system scheme (local adaptation, UPSTREAM.md).
|
|
9068
|
+
borderTopColor: "var(--fwt-elevation-edge-top)",
|
|
8034
9069
|
borderRightColor: "var(--winui-control-stroke-default)",
|
|
8035
|
-
borderBottomColor: "var(--
|
|
8036
|
-
borderLeftColor: "var(--winui-control-stroke-default)"
|
|
8037
|
-
"@media (prefers-color-scheme: dark)": {
|
|
8038
|
-
borderTopColor: "var(--winui-control-stroke-secondary)",
|
|
8039
|
-
borderBottomColor: "var(--winui-control-stroke-default)"
|
|
8040
|
-
}
|
|
9070
|
+
borderBottomColor: "var(--fwt-elevation-edge-bottom)",
|
|
9071
|
+
borderLeftColor: "var(--winui-control-stroke-default)"
|
|
8041
9072
|
},
|
|
8042
9073
|
// `:has` alongside each pointer state: the expander's own press lands on the
|
|
8043
9074
|
// overlay inside the row, and a row that reacts only to a press on itself
|
|
8044
9075
|
// would hold its rest fill while the reader is holding it down.
|
|
8045
9076
|
"&:active, &:has(> :active)": {
|
|
8046
9077
|
backgroundColor: "var(--winui-control-fill-tertiary)",
|
|
8047
|
-
...
|
|
9078
|
+
...shorthands3.borderColor("var(--winui-control-stroke-default)")
|
|
8048
9079
|
},
|
|
8049
9080
|
// The system focus visual: a 2px FocusStrokeColorOuter ring with a 1px
|
|
8050
9081
|
// FocusStrokeColorInner ring immediately inside it, around the border box
|
|
@@ -8132,7 +9163,7 @@ var useStyles13 = makeStyles13({
|
|
|
8132
9163
|
expanderHeader: {
|
|
8133
9164
|
position: "relative",
|
|
8134
9165
|
backgroundColor: "var(--winui-card-background-fill-default)",
|
|
8135
|
-
...
|
|
9166
|
+
...shorthands3.borderColor("var(--winui-card-stroke-default)"),
|
|
8136
9167
|
fontFamily: "inherit",
|
|
8137
9168
|
fontSize: "inherit",
|
|
8138
9169
|
paddingInlineEnd: "4px",
|
|
@@ -8182,7 +9213,7 @@ var useStyles13 = makeStyles13({
|
|
|
8182
9213
|
// The row paints the ring; see the interactive style above.
|
|
8183
9214
|
":focus-visible": { outline: "none" },
|
|
8184
9215
|
background: "none",
|
|
8185
|
-
...
|
|
9216
|
+
...shorthands3.borderWidth(0),
|
|
8186
9217
|
cursor: "pointer",
|
|
8187
9218
|
"&:disabled": { cursor: "not-allowed" },
|
|
8188
9219
|
inset: 0,
|
|
@@ -8317,48 +9348,48 @@ var useStyles13 = makeStyles13({
|
|
|
8317
9348
|
readoutDisabled: { color: "var(--winui-text-fill-disabled)" }
|
|
8318
9349
|
});
|
|
8319
9350
|
function CardText({ description, header, icon, id }) {
|
|
8320
|
-
const styles =
|
|
8321
|
-
return /* @__PURE__ */
|
|
8322
|
-
icon !== void 0 && /* @__PURE__ */
|
|
8323
|
-
/* @__PURE__ */
|
|
8324
|
-
/* @__PURE__ */
|
|
8325
|
-
description !== void 0 && /* @__PURE__ */
|
|
9351
|
+
const styles = useStyles17();
|
|
9352
|
+
return /* @__PURE__ */ jsxs22(Fragment3, { children: [
|
|
9353
|
+
icon !== void 0 && /* @__PURE__ */ jsx42("span", { "aria-hidden": true, className: styles.icon, ...{ [ICON_MARKER]: "" }, children: icon }),
|
|
9354
|
+
/* @__PURE__ */ jsxs22("span", { className: styles.text, children: [
|
|
9355
|
+
/* @__PURE__ */ jsx42(Text8, { block: true, id, children: header }),
|
|
9356
|
+
description !== void 0 && /* @__PURE__ */ jsx42(Text8, { block: true, size: 200, className: styles.description, children: description })
|
|
8326
9357
|
] })
|
|
8327
9358
|
] });
|
|
8328
9359
|
}
|
|
8329
9360
|
function SettingsSwitch({ checked, disabled, label, onChange }) {
|
|
8330
|
-
const styles =
|
|
9361
|
+
const styles = useStyles17();
|
|
8331
9362
|
const { t: t2 } = useTranslation();
|
|
8332
|
-
return /* @__PURE__ */
|
|
8333
|
-
/* @__PURE__ */
|
|
8334
|
-
/* @__PURE__ */
|
|
9363
|
+
return /* @__PURE__ */ jsxs22("span", { className: styles.switchRow, children: [
|
|
9364
|
+
/* @__PURE__ */ jsx42(Text8, { className: disabled === true ? styles.readoutDisabled : void 0, children: t2(checked ? "common.on" : "common.off") }),
|
|
9365
|
+
/* @__PURE__ */ jsx42(Switch, { "aria-label": label, checked, disabled, onChange: (_2, data) => onChange(data.checked) })
|
|
8335
9366
|
] });
|
|
8336
9367
|
}
|
|
8337
9368
|
function SettingsCard({ action, description, header, icon }) {
|
|
8338
|
-
const styles =
|
|
8339
|
-
return /* @__PURE__ */
|
|
8340
|
-
/* @__PURE__ */
|
|
8341
|
-
action !== void 0 && /* @__PURE__ */
|
|
9369
|
+
const styles = useStyles17();
|
|
9370
|
+
return /* @__PURE__ */ jsx42("div", { className: styles.row, children: /* @__PURE__ */ jsxs22("div", { className: styles.card, children: [
|
|
9371
|
+
/* @__PURE__ */ jsx42(CardText, { description, header, icon }),
|
|
9372
|
+
action !== void 0 && /* @__PURE__ */ jsx42("span", { className: styles.action, children: action })
|
|
8342
9373
|
] }) });
|
|
8343
9374
|
}
|
|
8344
9375
|
function SettingsExpander({ action, children, defaultOpen = false, description, disclosureDisabled = false, header, icon, revealOn, toggledOn }) {
|
|
8345
|
-
const styles =
|
|
8346
|
-
const [open, setOpen] =
|
|
8347
|
-
const [toggleWas, setToggleWas] =
|
|
9376
|
+
const styles = useStyles17();
|
|
9377
|
+
const [open, setOpen] = useState11(defaultOpen);
|
|
9378
|
+
const [toggleWas, setToggleWas] = useState11(toggledOn);
|
|
8348
9379
|
if (toggledOn !== void 0 && toggledOn !== toggleWas) {
|
|
8349
9380
|
setToggleWas(toggledOn);
|
|
8350
9381
|
setOpen(toggledOn);
|
|
8351
9382
|
}
|
|
8352
|
-
const [revealWas, setRevealWas] =
|
|
9383
|
+
const [revealWas, setRevealWas] = useState11(revealOn);
|
|
8353
9384
|
if (revealOn !== revealWas) {
|
|
8354
9385
|
setRevealWas(revealOn);
|
|
8355
9386
|
if (revealOn === true) setOpen(true);
|
|
8356
9387
|
}
|
|
8357
|
-
const contentId =
|
|
8358
|
-
const headerId =
|
|
8359
|
-
return /* @__PURE__ */
|
|
8360
|
-
/* @__PURE__ */
|
|
8361
|
-
/* @__PURE__ */
|
|
9388
|
+
const contentId = useId4();
|
|
9389
|
+
const headerId = useId4();
|
|
9390
|
+
return /* @__PURE__ */ jsxs22("div", { className: styles.row, children: [
|
|
9391
|
+
/* @__PURE__ */ jsxs22("div", { className: mergeClasses24(styles.card, !disclosureDisabled && styles.interactive, styles.expanderHeader, open && styles.expanderHeaderOpen), children: [
|
|
9392
|
+
/* @__PURE__ */ jsx42(
|
|
8362
9393
|
"button",
|
|
8363
9394
|
{
|
|
8364
9395
|
"aria-controls": contentId,
|
|
@@ -8370,112 +9401,48 @@ function SettingsExpander({ action, children, defaultOpen = false, description,
|
|
|
8370
9401
|
type: "button"
|
|
8371
9402
|
}
|
|
8372
9403
|
),
|
|
8373
|
-
/* @__PURE__ */
|
|
8374
|
-
action !== void 0 && /* @__PURE__ */
|
|
8375
|
-
/* @__PURE__ */
|
|
9404
|
+
/* @__PURE__ */ jsx42(CardText, { description, header, icon, id: headerId }),
|
|
9405
|
+
action !== void 0 && /* @__PURE__ */ jsx42("span", { className: styles.action, children: action }),
|
|
9406
|
+
/* @__PURE__ */ jsx42("span", { "aria-hidden": true, className: styles.chevron, children: /* @__PURE__ */ jsx42("svg", { className: mergeClasses24(styles.chevronGlyph, open && styles.chevronOpen), width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx42("path", { d: "M3.15 5.65c.2-.2.5-.2.7 0L8 9.79l4.15-4.14a.5.5 0 0 1 .7.7l-4.5 4.5a.5.5 0 0 1-.7 0l-4.5-4.5a.5.5 0 0 1 0-.7Z" }) }) })
|
|
8376
9407
|
] }),
|
|
8377
|
-
/* @__PURE__ */
|
|
9408
|
+
/* @__PURE__ */ jsx42("div", { className: mergeClasses24(styles.contentFrame, open && styles.contentFrameOpen), children: /* @__PURE__ */ jsx42("div", { className: styles.contentClip, children: /* @__PURE__ */ jsx42("div", { "aria-labelledby": headerId, className: styles.content, id: contentId, inert: !open, role: "group", children }) }) })
|
|
8378
9409
|
] });
|
|
8379
9410
|
}
|
|
8380
9411
|
|
|
8381
9412
|
// src/components/ui/switch-setting.tsx
|
|
8382
|
-
import { jsx as
|
|
9413
|
+
import { jsx as jsx43, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
8383
9414
|
var { InfoButton: InfoButton2 } = fluentComponents;
|
|
8384
9415
|
function SwitchSetting({ checked, description, label, onChange }) {
|
|
8385
|
-
return /* @__PURE__ */
|
|
8386
|
-
/* @__PURE__ */
|
|
8387
|
-
/* @__PURE__ */
|
|
9416
|
+
return /* @__PURE__ */ jsxs23("span", { className: "inline-flex items-center gap-1", children: [
|
|
9417
|
+
/* @__PURE__ */ jsx43(Switch, { checked, label, onChange: (_2, data) => onChange(data.checked) }),
|
|
9418
|
+
/* @__PURE__ */ jsx43(InfoButton2, { info: description })
|
|
8388
9419
|
] });
|
|
8389
9420
|
}
|
|
8390
9421
|
|
|
8391
|
-
// src/components/ui/
|
|
8392
|
-
import {
|
|
8393
|
-
|
|
8394
|
-
var useStyles14 = makeStyles14({
|
|
8395
|
-
trailing: {
|
|
8396
|
-
textAlign: "right",
|
|
8397
|
-
"& .fui-TableHeaderCell__button": { justifyContent: "flex-end" }
|
|
8398
|
-
},
|
|
8399
|
-
centred: {
|
|
8400
|
-
textAlign: "center",
|
|
8401
|
-
"& .fui-TableHeaderCell__button": { justifyContent: "center" }
|
|
8402
|
-
}
|
|
8403
|
-
});
|
|
8404
|
-
function TableTrailingHeader({ className, ...props }) {
|
|
8405
|
-
const styles = useStyles14();
|
|
8406
|
-
return /* @__PURE__ */ jsx35(TableHeaderCell, { ...props, className: mergeClasses18(styles.trailing, className) });
|
|
8407
|
-
}
|
|
8408
|
-
function TableTrailingCell({ className, ...props }) {
|
|
8409
|
-
const styles = useStyles14();
|
|
8410
|
-
return /* @__PURE__ */ jsx35(TableCell, { ...props, className: mergeClasses18(styles.trailing, className) });
|
|
8411
|
-
}
|
|
8412
|
-
function TableCentredHeader({ className, ...props }) {
|
|
8413
|
-
const styles = useStyles14();
|
|
8414
|
-
return /* @__PURE__ */ jsx35(TableHeaderCell, { ...props, className: mergeClasses18(styles.centred, className) });
|
|
8415
|
-
}
|
|
8416
|
-
function TableCentredCell({ className, ...props }) {
|
|
8417
|
-
const styles = useStyles14();
|
|
8418
|
-
return /* @__PURE__ */ jsx35(TableCell, { ...props, className: mergeClasses18(styles.centred, className) });
|
|
8419
|
-
}
|
|
8420
|
-
var stopRowSelection = { onClick: (event) => event.stopPropagation() };
|
|
8421
|
-
var ACTION_GAP = "var(--spacingHorizontalXS)";
|
|
8422
|
-
var ACTION_BUTTON_SIZE = "24px";
|
|
8423
|
-
var TABLE_ACTIONS_WIDTH = `calc(3 * ${ACTION_BUTTON_SIZE} + 2 * ${ACTION_GAP} + var(--spacingHorizontalS) + var(--fwt-panel-inset))`;
|
|
8424
|
-
function TableActions({ children }) {
|
|
8425
|
-
return /* @__PURE__ */ jsx35("div", { className: "flex items-center justify-end", style: { gap: ACTION_GAP }, ...stopRowSelection, children });
|
|
8426
|
-
}
|
|
8427
|
-
|
|
8428
|
-
// src/components/ui/table-columns.tsx
|
|
8429
|
-
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
8430
|
-
function TableColumns({ widths }) {
|
|
8431
|
-
return /* @__PURE__ */ jsx36("colgroup", { children: widths.map((width, index) => /* @__PURE__ */ jsx36("col", { style: width === null ? void 0 : { width } }, index)) });
|
|
8432
|
-
}
|
|
8433
|
-
|
|
8434
|
-
// src/components/ui/tooltip-icon-button.tsx
|
|
8435
|
-
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
8436
|
-
var { Button: Button7, Tooltip: Tooltip3, mergeClasses: mergeClasses19 } = fluentComponents;
|
|
8437
|
-
function TooltipIconButton(props) {
|
|
8438
|
-
return props.to === void 0 ? /* @__PURE__ */ jsx37(IconButton, { ...props }) : /* @__PURE__ */ jsx37(AddressedIconButton, { ...props, to: props.to });
|
|
8439
|
-
}
|
|
8440
|
-
function AddressedIconButton({ to, ...props }) {
|
|
8441
|
-
const address = useRouteAddress(to);
|
|
8442
|
-
return /* @__PURE__ */ jsx37(IconButton, { ...props, ...address });
|
|
8443
|
-
}
|
|
8444
|
-
function IconButton({ className, danger = false, disabled = false, disabledFocusable = false, href, icon, label, onClick }) {
|
|
8445
|
-
const dangerClasses = useDangerActionClasses();
|
|
8446
|
-
const shared = {
|
|
8447
|
-
appearance: "subtle",
|
|
8448
|
-
"aria-label": label,
|
|
8449
|
-
className: mergeClasses19(danger && dangerClasses.button, className),
|
|
8450
|
-
disabled,
|
|
8451
|
-
disabledFocusable,
|
|
8452
|
-
icon,
|
|
8453
|
-
onClick,
|
|
8454
|
-
size: "small"
|
|
8455
|
-
};
|
|
8456
|
-
return /* @__PURE__ */ jsx37(Tooltip3, { content: label, relationship: "label", children: href === void 0 ? /* @__PURE__ */ jsx37(Button7, { ...shared }) : /* @__PURE__ */ jsx37(Button7, { ...shared, as: "a", href }) });
|
|
8457
|
-
}
|
|
9422
|
+
// src/components/ui/tab-view.tsx
|
|
9423
|
+
import { CaretLeft12Filled, CaretRight12Filled, Dismiss12Regular } from "@fluentui/react-icons";
|
|
9424
|
+
import { useCallback as useCallback7, useEffect as useEffect7, useLayoutEffect as useLayoutEffect4, useRef as useRef9, useState as useState13 } from "react";
|
|
8458
9425
|
|
|
8459
9426
|
// src/components/ui/truncation-tooltip.tsx
|
|
8460
|
-
import { useCallback as
|
|
8461
|
-
import { jsx as
|
|
9427
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef8, useState as useState12 } from "react";
|
|
9428
|
+
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
8462
9429
|
var { Tooltip: Tooltip4 } = fluentComponents;
|
|
8463
9430
|
var OVERFLOW_TOLERANCE_PX = 1;
|
|
8464
9431
|
var collapseWhitespace = (text) => text.replace(/\s+/gu, " ").trim();
|
|
8465
9432
|
var hidesContent = (node, content) => node.scrollWidth - node.clientWidth > OVERFLOW_TOLERANCE_PX || collapseWhitespace(node.textContent ?? "") !== collapseWhitespace(content);
|
|
8466
9433
|
var useTruncation = (content, relationship) => {
|
|
8467
|
-
const [truncated, setTruncated] =
|
|
8468
|
-
const [visible, setVisible] =
|
|
8469
|
-
const nodeRef =
|
|
8470
|
-
const contentRef =
|
|
8471
|
-
const measure2 =
|
|
9434
|
+
const [truncated, setTruncated] = useState12(false);
|
|
9435
|
+
const [visible, setVisible] = useState12(false);
|
|
9436
|
+
const nodeRef = useRef8(null);
|
|
9437
|
+
const contentRef = useRef8(content);
|
|
9438
|
+
const measure2 = useCallback6(() => {
|
|
8472
9439
|
const node = nodeRef.current;
|
|
8473
9440
|
if (!node) return;
|
|
8474
9441
|
const hides = hidesContent(node, contentRef.current);
|
|
8475
9442
|
setTruncated(hides);
|
|
8476
9443
|
if (!hides) setVisible(false);
|
|
8477
9444
|
}, []);
|
|
8478
|
-
const measureRef =
|
|
9445
|
+
const measureRef = useCallback6((node) => {
|
|
8479
9446
|
nodeRef.current = node;
|
|
8480
9447
|
if (!node) return;
|
|
8481
9448
|
measure2();
|
|
@@ -8514,37 +9481,549 @@ var useTruncation = (content, relationship) => {
|
|
|
8514
9481
|
};
|
|
8515
9482
|
function TruncationTooltip({ children, content, relationship }) {
|
|
8516
9483
|
const { measureRef, tooltipProps } = useTruncation(content, relationship);
|
|
8517
|
-
return /* @__PURE__ */
|
|
9484
|
+
return /* @__PURE__ */ jsx44(Tooltip4, { ...tooltipProps, children: children(measureRef) });
|
|
9485
|
+
}
|
|
9486
|
+
|
|
9487
|
+
// src/components/ui/tab-view.tsx
|
|
9488
|
+
import { jsx as jsx45, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
9489
|
+
var { makeStyles: makeStyles18, mergeClasses: mergeClasses25 } = fluentComponents;
|
|
9490
|
+
var useStyles18 = makeStyles18({
|
|
9491
|
+
// TabViewHeaderPadding: 8px above the tabs.
|
|
9492
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L239
|
|
9493
|
+
// The strip's bottom line is TabViewBorderBrush (CardStrokeColorDefault),
|
|
9494
|
+
// drawn here under the scroller so that the selected tab, which reaches the
|
|
9495
|
+
// strip's last pixel row, paints over it and interrupts it.
|
|
9496
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView.xaml#L36-L37
|
|
9497
|
+
root: {
|
|
9498
|
+
alignItems: "flex-end",
|
|
9499
|
+
display: "flex",
|
|
9500
|
+
maxWidth: "100%",
|
|
9501
|
+
minWidth: 0,
|
|
9502
|
+
paddingTop: "8px",
|
|
9503
|
+
position: "relative",
|
|
9504
|
+
"&::after": {
|
|
9505
|
+
backgroundColor: "var(--winui-card-stroke-default)",
|
|
9506
|
+
bottom: 0,
|
|
9507
|
+
content: '""',
|
|
9508
|
+
height: "1px",
|
|
9509
|
+
left: 0,
|
|
9510
|
+
pointerEvents: "none",
|
|
9511
|
+
position: "absolute",
|
|
9512
|
+
right: 0,
|
|
9513
|
+
zIndex: 0
|
|
9514
|
+
}
|
|
9515
|
+
},
|
|
9516
|
+
scroller: {
|
|
9517
|
+
alignSelf: "stretch",
|
|
9518
|
+
display: "flex",
|
|
9519
|
+
flexGrow: 0,
|
|
9520
|
+
flexShrink: 1,
|
|
9521
|
+
minWidth: 0,
|
|
9522
|
+
overflowX: "auto",
|
|
9523
|
+
overflowY: "hidden",
|
|
9524
|
+
position: "relative",
|
|
9525
|
+
scrollbarWidth: "none",
|
|
9526
|
+
zIndex: 1,
|
|
9527
|
+
"&::-webkit-scrollbar": { display: "none" },
|
|
9528
|
+
"@media (prefers-reduced-motion: no-preference)": { scrollBehavior: "smooth" }
|
|
9529
|
+
},
|
|
9530
|
+
tablist: {
|
|
9531
|
+
alignItems: "flex-end",
|
|
9532
|
+
display: "flex",
|
|
9533
|
+
flexWrap: "nowrap",
|
|
9534
|
+
minWidth: "min-content"
|
|
9535
|
+
},
|
|
9536
|
+
// TabViewItemMinHeight 32, MinWidth 100, MaxWidth 240; the item's own
|
|
9537
|
+
// corners are OverlayCornerRadius on top only (TopCornerRadiusFilterConverter).
|
|
9538
|
+
// Every item holds a 1px border (TabViewItemBorderThickness) so selecting
|
|
9539
|
+
// one, which paints it, moves nothing.
|
|
9540
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L242-L244
|
|
9541
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView.xaml#L296-L297
|
|
9542
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView.xaml#L560-L562
|
|
9543
|
+
item: {
|
|
9544
|
+
alignItems: "stretch",
|
|
9545
|
+
borderBottomWidth: 0,
|
|
9546
|
+
borderLeft: "1px solid transparent",
|
|
9547
|
+
borderRight: "1px solid transparent",
|
|
9548
|
+
borderTop: "1px solid transparent",
|
|
9549
|
+
borderTopLeftRadius: "var(--winui-overlay-corner-radius)",
|
|
9550
|
+
borderTopRightRadius: "var(--winui-overlay-corner-radius)",
|
|
9551
|
+
boxSizing: "border-box",
|
|
9552
|
+
display: "flex",
|
|
9553
|
+
flexGrow: 0,
|
|
9554
|
+
flexShrink: 1,
|
|
9555
|
+
maxWidth: "240px",
|
|
9556
|
+
minHeight: "32px",
|
|
9557
|
+
minWidth: "100px",
|
|
9558
|
+
position: "relative",
|
|
9559
|
+
// TabSeparator: 1px DividerStrokeColorDefault inset 8px top and bottom,
|
|
9560
|
+
// gone under the pointer, on the selected tab and on the tab before it.
|
|
9561
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView.xaml#L553
|
|
9562
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L266
|
|
9563
|
+
"&::after": {
|
|
9564
|
+
backgroundColor: "var(--winui-divider-stroke-default)",
|
|
9565
|
+
bottom: "8px",
|
|
9566
|
+
content: '""',
|
|
9567
|
+
pointerEvents: "none",
|
|
9568
|
+
position: "absolute",
|
|
9569
|
+
right: "-1px",
|
|
9570
|
+
top: "8px",
|
|
9571
|
+
width: "1px"
|
|
9572
|
+
},
|
|
9573
|
+
"&:last-child::after": { display: "none" },
|
|
9574
|
+
"&:hover::after": { opacity: 0 },
|
|
9575
|
+
"&:has(+ [data-selected])::after": { opacity: 0 },
|
|
9576
|
+
"&:hover": { backgroundColor: "var(--winui-subtle-fill-secondary)" },
|
|
9577
|
+
"&:active": { backgroundColor: "var(--winui-subtle-fill-tertiary)" },
|
|
9578
|
+
// The selected tab: TabViewItemHeaderBackgroundSelected, a stroke on top
|
|
9579
|
+
// and sides in CardStrokeColorDefault, no bottom edge. It holds its fill
|
|
9580
|
+
// through the pointer states.
|
|
9581
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView.xaml#L325-L345
|
|
9582
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L72-L80
|
|
9583
|
+
"&[data-selected]": {
|
|
9584
|
+
backgroundColor: "var(--winui-solid-background-fill-tertiary)",
|
|
9585
|
+
borderLeftColor: "var(--winui-card-stroke-default)",
|
|
9586
|
+
borderRightColor: "var(--winui-card-stroke-default)",
|
|
9587
|
+
borderTopColor: "var(--winui-card-stroke-default)",
|
|
9588
|
+
zIndex: 1
|
|
9589
|
+
},
|
|
9590
|
+
"&[data-selected]::after": { opacity: 0 },
|
|
9591
|
+
"&[data-disabled]": { backgroundColor: "transparent" },
|
|
9592
|
+
// WinUI's CloseButtonOverlayMode Auto: the close button shows on the
|
|
9593
|
+
// selected tab and under the pointer, or always where there is no hover.
|
|
9594
|
+
"&:hover [data-tab-close], &:focus-within [data-tab-close]": { opacity: 1, pointerEvents: "auto" },
|
|
9595
|
+
"@media (hover: none)": { "& [data-tab-close]": { opacity: 1, pointerEvents: "auto" } }
|
|
9596
|
+
},
|
|
9597
|
+
// TabViewItemHeaderPaddingWithCloseButton 8,3,4,3 / WithoutCloseButton
|
|
9598
|
+
// 8,3,8,3; the close button's 4px margin supplies the right-hand 4.
|
|
9599
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L253-L254
|
|
9600
|
+
tab: {
|
|
9601
|
+
alignItems: "center",
|
|
9602
|
+
appearance: "none",
|
|
9603
|
+
backgroundColor: "transparent",
|
|
9604
|
+
borderRadius: "inherit",
|
|
9605
|
+
border: "none",
|
|
9606
|
+
// The foreground ramp: rest and pointer-over TextFillColorSecondary,
|
|
9607
|
+
// pressed Tertiary, selected Primary.
|
|
9608
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L12-L21
|
|
9609
|
+
color: "var(--winui-text-fill-secondary)",
|
|
9610
|
+
columnGap: "10px",
|
|
9611
|
+
cursor: "pointer",
|
|
9612
|
+
display: "flex",
|
|
9613
|
+
flexBasis: 0,
|
|
9614
|
+
flexGrow: 1,
|
|
9615
|
+
flexShrink: 1,
|
|
9616
|
+
// TabViewItemHeaderFontSize 12.
|
|
9617
|
+
fontFamily: "inherit",
|
|
9618
|
+
fontSize: "12px",
|
|
9619
|
+
lineHeight: "16px",
|
|
9620
|
+
minWidth: 0,
|
|
9621
|
+
padding: "3px 8px 3px 8px",
|
|
9622
|
+
textAlign: "start",
|
|
9623
|
+
"&:active:not(:disabled)": { color: "var(--winui-text-fill-tertiary)" },
|
|
9624
|
+
'&[aria-selected="true"], &[aria-selected="true"]:active': { color: "var(--winui-text-fill-primary)" },
|
|
9625
|
+
"&:disabled": { color: "var(--winui-text-fill-disabled)", cursor: "not-allowed" },
|
|
9626
|
+
// The system focus visual, as the library's other selectors draw it.
|
|
9627
|
+
"&:focus-visible": {
|
|
9628
|
+
boxShadow: "inset 0 0 0 1px var(--winui-focus-stroke-inner)",
|
|
9629
|
+
outline: "2px solid var(--winui-focus-stroke-outer)",
|
|
9630
|
+
outlineOffset: "-2px"
|
|
9631
|
+
}
|
|
9632
|
+
},
|
|
9633
|
+
tabWithClose: { paddingRight: 0 },
|
|
9634
|
+
// The icon sits in a 16px box with a 10px gap before the label.
|
|
9635
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L246-L247
|
|
9636
|
+
icon: {
|
|
9637
|
+
alignItems: "center",
|
|
9638
|
+
display: "inline-flex",
|
|
9639
|
+
flexShrink: 0,
|
|
9640
|
+
fontSize: "16px",
|
|
9641
|
+
height: "16px",
|
|
9642
|
+
justifyContent: "center",
|
|
9643
|
+
width: "16px"
|
|
9644
|
+
},
|
|
9645
|
+
label: {
|
|
9646
|
+
flexBasis: 0,
|
|
9647
|
+
flexGrow: 1,
|
|
9648
|
+
minWidth: 0,
|
|
9649
|
+
overflow: "hidden",
|
|
9650
|
+
textOverflow: "ellipsis",
|
|
9651
|
+
whiteSpace: "nowrap"
|
|
9652
|
+
},
|
|
9653
|
+
// TabViewItemHeaderCloseButtonWidth 32, Height 24, glyph 12, margin 4,0,0,0,
|
|
9654
|
+
// ControlCornerRadius; the fills are the subtle ramp, the glyph Primary
|
|
9655
|
+
// (Secondary while pressed).
|
|
9656
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L248-L252
|
|
9657
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView.xaml#L172-L187
|
|
9658
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L47-L60
|
|
9659
|
+
close: {
|
|
9660
|
+
alignItems: "center",
|
|
9661
|
+
alignSelf: "center",
|
|
9662
|
+
appearance: "none",
|
|
9663
|
+
backgroundColor: "transparent",
|
|
9664
|
+
borderRadius: "var(--winui-control-corner-radius)",
|
|
9665
|
+
border: "none",
|
|
9666
|
+
color: "var(--winui-text-fill-primary)",
|
|
9667
|
+
cursor: "pointer",
|
|
9668
|
+
display: "inline-flex",
|
|
9669
|
+
flexShrink: 0,
|
|
9670
|
+
fontSize: "12px",
|
|
9671
|
+
height: "24px",
|
|
9672
|
+
justifyContent: "center",
|
|
9673
|
+
margin: "0 4px",
|
|
9674
|
+
opacity: 0,
|
|
9675
|
+
padding: 0,
|
|
9676
|
+
pointerEvents: "none",
|
|
9677
|
+
width: "32px",
|
|
9678
|
+
"&:hover": { backgroundColor: "var(--winui-subtle-fill-secondary)" },
|
|
9679
|
+
"&:active": {
|
|
9680
|
+
backgroundColor: "var(--winui-subtle-fill-tertiary)",
|
|
9681
|
+
color: "var(--winui-text-fill-secondary)"
|
|
9682
|
+
},
|
|
9683
|
+
"&:focus-visible": {
|
|
9684
|
+
boxShadow: "inset 0 0 0 1px var(--winui-focus-stroke-inner)",
|
|
9685
|
+
outline: "2px solid var(--winui-focus-stroke-outer)",
|
|
9686
|
+
outlineOffset: "0",
|
|
9687
|
+
opacity: 1,
|
|
9688
|
+
pointerEvents: "auto"
|
|
9689
|
+
},
|
|
9690
|
+
"&:disabled": { color: "var(--winui-text-fill-disabled)", cursor: "not-allowed" }
|
|
9691
|
+
},
|
|
9692
|
+
closeShown: { opacity: 1, pointerEvents: "auto" },
|
|
9693
|
+
// Scroll buttons: 32x24, glyph 8, ControlCornerRadius, the subtle ramp, with
|
|
9694
|
+
// 8,0,3,3 / 3,0,8,3 container padding.
|
|
9695
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L255-L260
|
|
9696
|
+
// https://github.com/microsoft/microsoft-ui-xaml/blob/188f602b27cdb47572b28c380e9c087b02e1ccee/controls/dev/TabView/TabView_themeresources.xaml#L34-L41
|
|
9697
|
+
scrollButtonBox: {
|
|
9698
|
+
alignSelf: "flex-end",
|
|
9699
|
+
flexShrink: 0,
|
|
9700
|
+
position: "relative",
|
|
9701
|
+
zIndex: 1
|
|
9702
|
+
},
|
|
9703
|
+
scrollBoxLeft: { padding: "0 3px 3px 8px" },
|
|
9704
|
+
scrollBoxRight: { padding: "0 8px 3px 3px" },
|
|
9705
|
+
scrollButton: {
|
|
9706
|
+
alignItems: "center",
|
|
9707
|
+
appearance: "none",
|
|
9708
|
+
backgroundColor: "transparent",
|
|
9709
|
+
borderRadius: "var(--winui-control-corner-radius)",
|
|
9710
|
+
border: "none",
|
|
9711
|
+
color: "var(--winui-text-fill-secondary)",
|
|
9712
|
+
cursor: "pointer",
|
|
9713
|
+
display: "inline-flex",
|
|
9714
|
+
fontSize: "8px",
|
|
9715
|
+
height: "24px",
|
|
9716
|
+
justifyContent: "center",
|
|
9717
|
+
padding: "3px 7px",
|
|
9718
|
+
width: "32px",
|
|
9719
|
+
"&:hover:not(:disabled)": { backgroundColor: "var(--winui-subtle-fill-secondary)" },
|
|
9720
|
+
"&:active:not(:disabled)": { backgroundColor: "var(--winui-subtle-fill-tertiary)" },
|
|
9721
|
+
"&:disabled": { color: "var(--winui-text-fill-disabled)", cursor: "default" },
|
|
9722
|
+
"&:focus-visible": {
|
|
9723
|
+
boxShadow: "inset 0 0 0 1px var(--winui-focus-stroke-inner)",
|
|
9724
|
+
outline: "2px solid var(--winui-focus-stroke-outer)",
|
|
9725
|
+
outlineOffset: "0"
|
|
9726
|
+
}
|
|
9727
|
+
},
|
|
9728
|
+
// TabStripFooter: beside the tabs, after them, on the strip's baseline.
|
|
9729
|
+
footer: {
|
|
9730
|
+
alignItems: "center",
|
|
9731
|
+
alignSelf: "stretch",
|
|
9732
|
+
display: "flex",
|
|
9733
|
+
flexShrink: 0,
|
|
9734
|
+
minHeight: "32px",
|
|
9735
|
+
paddingBottom: "3px",
|
|
9736
|
+
paddingInline: "4px",
|
|
9737
|
+
position: "relative",
|
|
9738
|
+
zIndex: 1
|
|
9739
|
+
}
|
|
9740
|
+
});
|
|
9741
|
+
var SCROLL_STEP_PX = 200;
|
|
9742
|
+
function TabView({ ariaLabel, className, footer, items, onClose, onSelect, selectedValue }) {
|
|
9743
|
+
const styles = useStyles18();
|
|
9744
|
+
const { t: t2 } = useTranslation();
|
|
9745
|
+
const scrollerRef = useRef9(null);
|
|
9746
|
+
const [overflow, setOverflow] = useState13({ backward: false, forward: false, scrollable: false });
|
|
9747
|
+
const enabledValues = items.filter((item) => item.disabled !== true).map((item) => item.value);
|
|
9748
|
+
const tabStop = selectedValue !== null && enabledValues.includes(selectedValue) ? selectedValue : enabledValues[0];
|
|
9749
|
+
const measure2 = useCallback7(() => {
|
|
9750
|
+
const scroller = scrollerRef.current;
|
|
9751
|
+
if (!scroller) return;
|
|
9752
|
+
const scrollable = scroller.scrollWidth - scroller.clientWidth > 1;
|
|
9753
|
+
const backward = scrollable && scroller.scrollLeft > 0;
|
|
9754
|
+
const forward = scrollable && scroller.scrollLeft + scroller.clientWidth < scroller.scrollWidth - 1;
|
|
9755
|
+
setOverflow((previous) => previous.scrollable === scrollable && previous.backward === backward && previous.forward === forward ? previous : { backward, forward, scrollable });
|
|
9756
|
+
}, []);
|
|
9757
|
+
useLayoutEffect4(() => {
|
|
9758
|
+
measure2();
|
|
9759
|
+
const scroller = scrollerRef.current;
|
|
9760
|
+
if (!scroller || typeof ResizeObserver === "undefined") return;
|
|
9761
|
+
const observer = new ResizeObserver(measure2);
|
|
9762
|
+
observer.observe(scroller);
|
|
9763
|
+
const list = scroller.firstElementChild;
|
|
9764
|
+
if (list) observer.observe(list);
|
|
9765
|
+
return () => observer.disconnect();
|
|
9766
|
+
}, [measure2, items]);
|
|
9767
|
+
useEffect7(() => {
|
|
9768
|
+
const selected = scrollerRef.current?.querySelector('[role="tab"][aria-selected="true"]');
|
|
9769
|
+
selected?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
9770
|
+
}, [selectedValue]);
|
|
9771
|
+
const scrollBy = (direction) => scrollerRef.current?.scrollBy?.({ left: direction * SCROLL_STEP_PX });
|
|
9772
|
+
const closeIfClosable = (value) => {
|
|
9773
|
+
const item = items.find((candidate) => candidate.value === value);
|
|
9774
|
+
if (item?.closable !== true || item.disabled === true) return false;
|
|
9775
|
+
onClose?.(value);
|
|
9776
|
+
return true;
|
|
9777
|
+
};
|
|
9778
|
+
const handleKeyDown = (event) => {
|
|
9779
|
+
const target = event.target;
|
|
9780
|
+
const owner = target.closest("[data-tab-value]");
|
|
9781
|
+
if (!owner) return;
|
|
9782
|
+
const value = owner.dataset.tabValue;
|
|
9783
|
+
if (event.key === "F4" && event.ctrlKey || event.key === "Delete") {
|
|
9784
|
+
if (closeIfClosable(value)) event.preventDefault();
|
|
9785
|
+
return;
|
|
9786
|
+
}
|
|
9787
|
+
if (!target.matches('[role="tab"]') || enabledValues.length === 0) return;
|
|
9788
|
+
const current = enabledValues.indexOf(value);
|
|
9789
|
+
let next;
|
|
9790
|
+
switch (event.key) {
|
|
9791
|
+
case "ArrowRight":
|
|
9792
|
+
next = enabledValues[(current + 1) % enabledValues.length];
|
|
9793
|
+
break;
|
|
9794
|
+
case "ArrowLeft":
|
|
9795
|
+
next = enabledValues[(current - 1 + enabledValues.length) % enabledValues.length];
|
|
9796
|
+
break;
|
|
9797
|
+
case "Home":
|
|
9798
|
+
next = enabledValues[0];
|
|
9799
|
+
break;
|
|
9800
|
+
case "End":
|
|
9801
|
+
next = enabledValues[enabledValues.length - 1];
|
|
9802
|
+
break;
|
|
9803
|
+
default:
|
|
9804
|
+
return;
|
|
9805
|
+
}
|
|
9806
|
+
event.preventDefault();
|
|
9807
|
+
const nextTab = event.currentTarget.querySelector(`[data-tab-value="${CSS.escape(next)}"] [role="tab"]`);
|
|
9808
|
+
nextTab?.focus();
|
|
9809
|
+
if (next !== selectedValue) onSelect(next);
|
|
9810
|
+
};
|
|
9811
|
+
return /* @__PURE__ */ jsxs24("div", { className: mergeClasses25(styles.root, className), children: [
|
|
9812
|
+
overflow.scrollable ? /* @__PURE__ */ jsx45("div", { className: mergeClasses25(styles.scrollButtonBox, styles.scrollBoxLeft), children: /* @__PURE__ */ jsx45(
|
|
9813
|
+
"button",
|
|
9814
|
+
{
|
|
9815
|
+
"aria-label": t2("tabView.scrollBackward"),
|
|
9816
|
+
className: styles.scrollButton,
|
|
9817
|
+
disabled: !overflow.backward,
|
|
9818
|
+
onClick: () => scrollBy(-1),
|
|
9819
|
+
tabIndex: -1,
|
|
9820
|
+
type: "button",
|
|
9821
|
+
children: /* @__PURE__ */ jsx45(CaretLeft12Filled, { fontSize: 8 })
|
|
9822
|
+
}
|
|
9823
|
+
) }) : null,
|
|
9824
|
+
/* @__PURE__ */ jsx45("div", { className: styles.scroller, onScroll: measure2, ref: scrollerRef, children: /* @__PURE__ */ jsx45("div", { "aria-label": ariaLabel, "aria-orientation": "horizontal", className: styles.tablist, onKeyDown: handleKeyDown, role: "tablist", children: items.map((item) => {
|
|
9825
|
+
const selected = item.value === selectedValue;
|
|
9826
|
+
const disabled = item.disabled === true;
|
|
9827
|
+
const closable = item.closable === true;
|
|
9828
|
+
const closeLabel = item.closeLabel ?? t2("tabView.close");
|
|
9829
|
+
return /* @__PURE__ */ jsxs24(
|
|
9830
|
+
"div",
|
|
9831
|
+
{
|
|
9832
|
+
className: styles.item,
|
|
9833
|
+
"data-disabled": disabled ? "" : void 0,
|
|
9834
|
+
"data-selected": selected ? "" : void 0,
|
|
9835
|
+
"data-tab-value": item.value,
|
|
9836
|
+
onAuxClick: (event) => {
|
|
9837
|
+
if (event.button !== 1 || !closable) return;
|
|
9838
|
+
event.preventDefault();
|
|
9839
|
+
closeIfClosable(item.value);
|
|
9840
|
+
},
|
|
9841
|
+
onMouseDown: (event) => {
|
|
9842
|
+
if (event.button === 1) event.preventDefault();
|
|
9843
|
+
},
|
|
9844
|
+
role: "presentation",
|
|
9845
|
+
children: [
|
|
9846
|
+
/* @__PURE__ */ jsxs24(
|
|
9847
|
+
"button",
|
|
9848
|
+
{
|
|
9849
|
+
"aria-selected": selected,
|
|
9850
|
+
className: mergeClasses25(styles.tab, closable && styles.tabWithClose),
|
|
9851
|
+
disabled,
|
|
9852
|
+
onClick: () => {
|
|
9853
|
+
if (!selected) onSelect(item.value);
|
|
9854
|
+
},
|
|
9855
|
+
role: "tab",
|
|
9856
|
+
tabIndex: item.value === tabStop ? 0 : -1,
|
|
9857
|
+
type: "button",
|
|
9858
|
+
children: [
|
|
9859
|
+
item.icon === void 0 ? null : /* @__PURE__ */ jsx45("span", { "aria-hidden": "true", className: styles.icon, children: item.icon }),
|
|
9860
|
+
typeof item.header === "string" ? /* @__PURE__ */ jsx45(TruncationTooltip, { content: item.header, relationship: "description", children: (measureRef) => /* @__PURE__ */ jsx45("span", { className: styles.label, ref: measureRef, children: item.header }) }) : /* @__PURE__ */ jsx45("span", { className: styles.label, children: item.header })
|
|
9861
|
+
]
|
|
9862
|
+
}
|
|
9863
|
+
),
|
|
9864
|
+
closable ? /* @__PURE__ */ jsx45(
|
|
9865
|
+
"button",
|
|
9866
|
+
{
|
|
9867
|
+
"aria-label": closeLabel,
|
|
9868
|
+
className: mergeClasses25(styles.close, selected && styles.closeShown),
|
|
9869
|
+
"data-tab-close": "",
|
|
9870
|
+
disabled,
|
|
9871
|
+
onClick: () => closeIfClosable(item.value),
|
|
9872
|
+
tabIndex: -1,
|
|
9873
|
+
type: "button",
|
|
9874
|
+
children: /* @__PURE__ */ jsx45(Dismiss12Regular, { fontSize: 12 })
|
|
9875
|
+
}
|
|
9876
|
+
) : null
|
|
9877
|
+
]
|
|
9878
|
+
},
|
|
9879
|
+
item.value
|
|
9880
|
+
);
|
|
9881
|
+
}) }) }),
|
|
9882
|
+
overflow.scrollable ? /* @__PURE__ */ jsx45("div", { className: mergeClasses25(styles.scrollButtonBox, styles.scrollBoxRight), children: /* @__PURE__ */ jsx45(
|
|
9883
|
+
"button",
|
|
9884
|
+
{
|
|
9885
|
+
"aria-label": t2("tabView.scrollForward"),
|
|
9886
|
+
className: styles.scrollButton,
|
|
9887
|
+
disabled: !overflow.forward,
|
|
9888
|
+
onClick: () => scrollBy(1),
|
|
9889
|
+
tabIndex: -1,
|
|
9890
|
+
type: "button",
|
|
9891
|
+
children: /* @__PURE__ */ jsx45(CaretRight12Filled, { fontSize: 8 })
|
|
9892
|
+
}
|
|
9893
|
+
) }) : null,
|
|
9894
|
+
footer === void 0 ? null : /* @__PURE__ */ jsx45("div", { className: styles.footer, children: footer })
|
|
9895
|
+
] });
|
|
9896
|
+
}
|
|
9897
|
+
|
|
9898
|
+
// src/components/ui/tooltip-icon-button.tsx
|
|
9899
|
+
import { jsx as jsx46 } from "react/jsx-runtime";
|
|
9900
|
+
var { Button: Button11, Tooltip: Tooltip5, mergeClasses: mergeClasses26 } = fluentComponents;
|
|
9901
|
+
function TooltipIconButton(props) {
|
|
9902
|
+
return props.to === void 0 ? /* @__PURE__ */ jsx46(IconButton, { ...props }) : /* @__PURE__ */ jsx46(AddressedIconButton, { ...props, to: props.to });
|
|
9903
|
+
}
|
|
9904
|
+
function AddressedIconButton({ to, ...props }) {
|
|
9905
|
+
const address = useRouteAddress(to);
|
|
9906
|
+
return /* @__PURE__ */ jsx46(IconButton, { ...props, ...address });
|
|
9907
|
+
}
|
|
9908
|
+
function IconButton({ className, danger = false, disabled = false, disabledFocusable = false, href, icon, label, onClick, ...trigger }) {
|
|
9909
|
+
const dangerClasses = useDangerActionClasses();
|
|
9910
|
+
const shared = {
|
|
9911
|
+
...trigger,
|
|
9912
|
+
appearance: "subtle",
|
|
9913
|
+
"aria-label": label,
|
|
9914
|
+
className: mergeClasses26(danger && dangerClasses.button, className),
|
|
9915
|
+
disabled,
|
|
9916
|
+
disabledFocusable,
|
|
9917
|
+
icon,
|
|
9918
|
+
onClick,
|
|
9919
|
+
size: "small"
|
|
9920
|
+
};
|
|
9921
|
+
return /* @__PURE__ */ jsx46(Tooltip5, { content: label, relationship: "label", children: href === void 0 ? /* @__PURE__ */ jsx46(Button11, { ...shared }) : /* @__PURE__ */ jsx46(Button11, { ...shared, as: "a", href }) });
|
|
9922
|
+
}
|
|
9923
|
+
|
|
9924
|
+
// src/components/ui/use-confirm.tsx
|
|
9925
|
+
import { createContext as createContext4, useCallback as useCallback8, useContext as useContext4, useRef as useRef10, useState as useState14 } from "react";
|
|
9926
|
+
import { jsx as jsx47, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
9927
|
+
var ConfirmContext = createContext4(null);
|
|
9928
|
+
var errorText2 = (error) => error instanceof Error ? error.message : String(error);
|
|
9929
|
+
function ConfirmDialogProvider({ children }) {
|
|
9930
|
+
const nextId = useRef10(0);
|
|
9931
|
+
const [queue, setQueue] = useState14([]);
|
|
9932
|
+
const [open, setOpen] = useState14(true);
|
|
9933
|
+
const [busy, setBusy] = useState14(false);
|
|
9934
|
+
const [error, setError] = useState14(null);
|
|
9935
|
+
const head = queue[0];
|
|
9936
|
+
const confirm = useCallback8((options) => new Promise((resolve) => {
|
|
9937
|
+
setQueue((current) => [...current, { id: nextId.current++, options, resolve }]);
|
|
9938
|
+
}), []);
|
|
9939
|
+
const finish = (confirmed) => {
|
|
9940
|
+
if (!open) return;
|
|
9941
|
+
head?.resolve(confirmed);
|
|
9942
|
+
setOpen(false);
|
|
9943
|
+
};
|
|
9944
|
+
const accept = async () => {
|
|
9945
|
+
if (!head) return;
|
|
9946
|
+
const { onConfirm } = head.options;
|
|
9947
|
+
if (!onConfirm) {
|
|
9948
|
+
finish(true);
|
|
9949
|
+
return;
|
|
9950
|
+
}
|
|
9951
|
+
setError(null);
|
|
9952
|
+
setBusy(true);
|
|
9953
|
+
try {
|
|
9954
|
+
await onConfirm();
|
|
9955
|
+
setBusy(false);
|
|
9956
|
+
finish(true);
|
|
9957
|
+
} catch (caught) {
|
|
9958
|
+
setBusy(false);
|
|
9959
|
+
setError(errorText2(caught));
|
|
9960
|
+
}
|
|
9961
|
+
};
|
|
9962
|
+
const advance = () => {
|
|
9963
|
+
setQueue((current) => current.slice(1));
|
|
9964
|
+
setError(null);
|
|
9965
|
+
setOpen(true);
|
|
9966
|
+
};
|
|
9967
|
+
return /* @__PURE__ */ jsxs25(ConfirmContext.Provider, { value: confirm, children: [
|
|
9968
|
+
children,
|
|
9969
|
+
head && /* @__PURE__ */ jsx47(
|
|
9970
|
+
ConfirmDialog,
|
|
9971
|
+
{
|
|
9972
|
+
actionIntent: head.options.intent,
|
|
9973
|
+
actionLabel: head.options.actionLabel,
|
|
9974
|
+
busy,
|
|
9975
|
+
cancelLabel: head.options.cancelLabel,
|
|
9976
|
+
error,
|
|
9977
|
+
message: head.options.message,
|
|
9978
|
+
onConfirm: () => {
|
|
9979
|
+
void accept();
|
|
9980
|
+
},
|
|
9981
|
+
onDismissError: () => setError(null),
|
|
9982
|
+
onExited: advance,
|
|
9983
|
+
onOpenChange: (next) => {
|
|
9984
|
+
if (!next) finish(false);
|
|
9985
|
+
},
|
|
9986
|
+
open,
|
|
9987
|
+
title: head.options.title
|
|
9988
|
+
},
|
|
9989
|
+
head.id
|
|
9990
|
+
)
|
|
9991
|
+
] });
|
|
8518
9992
|
}
|
|
9993
|
+
var useConfirm = () => {
|
|
9994
|
+
const value = useContext4(ConfirmContext);
|
|
9995
|
+
if (!value) throw new Error("useConfirm requires a ConfirmDialogProvider above it");
|
|
9996
|
+
return value;
|
|
9997
|
+
};
|
|
8519
9998
|
|
|
8520
9999
|
// src/components/ui/use-dialog-invocation.ts
|
|
8521
|
-
import { useCallback as
|
|
10000
|
+
import { useCallback as useCallback9, useMemo as useMemo6, useRef as useRef11, useState as useState15 } from "react";
|
|
8522
10001
|
var useDialogInvocation = () => {
|
|
8523
|
-
const nextKey =
|
|
8524
|
-
const [invocation, setInvocation] =
|
|
8525
|
-
const [isOpen, setIsOpen] =
|
|
8526
|
-
const open =
|
|
10002
|
+
const nextKey = useRef11(0);
|
|
10003
|
+
const [invocation, setInvocation] = useState15(null);
|
|
10004
|
+
const [isOpen, setIsOpen] = useState15(false);
|
|
10005
|
+
const open = useCallback9((value) => {
|
|
8527
10006
|
setInvocation({ key: nextKey.current++, value });
|
|
8528
10007
|
setIsOpen(true);
|
|
8529
10008
|
}, []);
|
|
8530
|
-
const close =
|
|
8531
|
-
return
|
|
10009
|
+
const close = useCallback9(() => setIsOpen(false), []);
|
|
10010
|
+
return useMemo6(() => ({ close, invocation, isOpen, open }), [close, invocation, isOpen, open]);
|
|
8532
10011
|
};
|
|
8533
10012
|
|
|
8534
10013
|
// src/components/ui/use-discard-guard.tsx
|
|
8535
|
-
import { useCallback as
|
|
8536
|
-
import { jsx as
|
|
10014
|
+
import { useCallback as useCallback10, useRef as useRef12, useState as useState16 } from "react";
|
|
10015
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
8537
10016
|
var useDiscardGuard = ({ onClose, values }) => {
|
|
8538
10017
|
const { t: t2 } = useTranslation();
|
|
8539
10018
|
const prompt = useDialogInvocation();
|
|
8540
|
-
const discarding =
|
|
8541
|
-
const [openedWith] =
|
|
10019
|
+
const discarding = useRef12(false);
|
|
10020
|
+
const [openedWith] = useState16(() => JSON.stringify(values));
|
|
8542
10021
|
const dirty = JSON.stringify(values) !== openedWith;
|
|
8543
|
-
const requestClose =
|
|
10022
|
+
const requestClose = useCallback10(() => {
|
|
8544
10023
|
if (dirty) prompt.open();
|
|
8545
10024
|
else onClose();
|
|
8546
10025
|
}, [dirty, onClose, prompt]);
|
|
8547
|
-
const discardConfirmation = prompt.invocation && /* @__PURE__ */
|
|
10026
|
+
const discardConfirmation = prompt.invocation && /* @__PURE__ */ jsx48(
|
|
8548
10027
|
ConfirmDialog,
|
|
8549
10028
|
{
|
|
8550
10029
|
actionLabel: t2("common.discard.discard"),
|
|
@@ -8572,13 +10051,13 @@ var useDiscardGuard = ({ onClose, values }) => {
|
|
|
8572
10051
|
|
|
8573
10052
|
// src/shell/app-shell.tsx
|
|
8574
10053
|
import { NavigationRegular } from "@fluentui/react-icons";
|
|
8575
|
-
import { useLayoutEffect as
|
|
10054
|
+
import { useLayoutEffect as useLayoutEffect5, useRef as useRef13, useState as useState18 } from "react";
|
|
8576
10055
|
|
|
8577
10056
|
// src/shell/page-frames.tsx
|
|
8578
|
-
import { useState as
|
|
10057
|
+
import { useState as useState17 } from "react";
|
|
8579
10058
|
var usePageFrames = (page, pageKey) => {
|
|
8580
|
-
const [current, setCurrent] =
|
|
8581
|
-
const [leaving, setLeaving] =
|
|
10059
|
+
const [current, setCurrent] = useState17({ id: 0, key: pageKey, node: page });
|
|
10060
|
+
const [leaving, setLeaving] = useState17(null);
|
|
8582
10061
|
if (current.key !== pageKey) {
|
|
8583
10062
|
setLeaving({ id: current.id, node: current.node });
|
|
8584
10063
|
setCurrent({ id: current.id + 1, key: pageKey, node: page });
|
|
@@ -8594,14 +10073,14 @@ var usePageFrames = (page, pageKey) => {
|
|
|
8594
10073
|
var pageFrameClassName = (frame) => frame.leaving ? "fwt-page-leaving" : frame.id > 0 ? "fwt-page-entering" : "";
|
|
8595
10074
|
|
|
8596
10075
|
// src/shell/app-shell.tsx
|
|
8597
|
-
import { jsx as
|
|
8598
|
-
var { Button:
|
|
10076
|
+
import { jsx as jsx49, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
10077
|
+
var { Button: Button12, DrawerBody, OverlayDrawer } = fluentComponents;
|
|
8599
10078
|
var MAIN_ID = "fwt-main";
|
|
8600
10079
|
function AppShell({ children, labels, narrowHeader, narrowHeaderActions, navigation, pageKey, workspace = false }) {
|
|
8601
|
-
const [navigationOpen, setNavigationOpen] =
|
|
8602
|
-
const firstFrameRef =
|
|
8603
|
-
const entranceStarted =
|
|
8604
|
-
|
|
10080
|
+
const [navigationOpen, setNavigationOpen] = useState18(false);
|
|
10081
|
+
const firstFrameRef = useRef13(null);
|
|
10082
|
+
const entranceStarted = useRef13(false);
|
|
10083
|
+
useLayoutEffect5(() => {
|
|
8605
10084
|
if (entranceStarted.current) return;
|
|
8606
10085
|
if (prefersReducedMotion()) return;
|
|
8607
10086
|
const frame = firstFrameRef.current;
|
|
@@ -8613,19 +10092,19 @@ function AppShell({ children, labels, narrowHeader, narrowHeaderActions, navigat
|
|
|
8613
10092
|
{ duration: PAGE_ENTER_MS, easing: PAGE_ENTER_EASING, fill: "forwards" }
|
|
8614
10093
|
);
|
|
8615
10094
|
}, []);
|
|
8616
|
-
const page = /* @__PURE__ */
|
|
10095
|
+
const page = /* @__PURE__ */ jsx49(
|
|
8617
10096
|
ScrollArea,
|
|
8618
10097
|
{
|
|
8619
10098
|
axes: "vertical",
|
|
8620
10099
|
className: "h-full min-h-0",
|
|
8621
10100
|
contentClassName: workspace ? "h-full" : "min-h-full",
|
|
8622
10101
|
noTabIndex: true,
|
|
8623
|
-
children: /* @__PURE__ */
|
|
10102
|
+
children: /* @__PURE__ */ jsx49("div", { className: `${workspace ? SCROLLPORT_FILL_CLASS : ""} p-[22px_var(--fwt-page-inset)_var(--fwt-page-inset)] max-[680px]:p-4`, children })
|
|
8624
10103
|
}
|
|
8625
10104
|
);
|
|
8626
10105
|
const frames = usePageFrames(page, pageKey);
|
|
8627
|
-
return /* @__PURE__ */
|
|
8628
|
-
/* @__PURE__ */
|
|
10106
|
+
return /* @__PURE__ */ jsxs26(OutcomeToastProvider, { children: [
|
|
10107
|
+
/* @__PURE__ */ jsx49(
|
|
8629
10108
|
"a",
|
|
8630
10109
|
{
|
|
8631
10110
|
className: "fixed left-3 top-3 z-[100000] -translate-y-20 rounded-md bg-fui-bg1 px-3 py-2 text-fui-fg1 shadow-lg focus:translate-y-0",
|
|
@@ -8633,22 +10112,22 @@ function AppShell({ children, labels, narrowHeader, narrowHeaderActions, navigat
|
|
|
8633
10112
|
children: labels.skipToContent
|
|
8634
10113
|
}
|
|
8635
10114
|
),
|
|
8636
|
-
/* @__PURE__ */
|
|
8637
|
-
/* @__PURE__ */
|
|
8638
|
-
/* @__PURE__ */
|
|
8639
|
-
/* @__PURE__ */
|
|
8640
|
-
|
|
10115
|
+
/* @__PURE__ */ jsxs26("div", { className: "grid grid-cols-[clamp(240px,18vw,290px)_minmax(0,1fr)] grid-rows-[minmax(0,1fr)] h-[100dvh] min-h-0 max-[900px]:grid-cols-1 max-[900px]:grid-rows-[58px_minmax(0,1fr)]", children: [
|
|
10116
|
+
/* @__PURE__ */ jsx49("div", { className: "min-h-0 max-[900px]:hidden", children: navigation({}) }),
|
|
10117
|
+
/* @__PURE__ */ jsxs26("header", { className: "hidden max-[900px]:flex items-center gap-3 border-b border-b-solid border-fui-divider px-4", children: [
|
|
10118
|
+
/* @__PURE__ */ jsx49(
|
|
10119
|
+
Button12,
|
|
8641
10120
|
{
|
|
8642
10121
|
appearance: "subtle",
|
|
8643
10122
|
"aria-label": labels.openNavigation,
|
|
8644
|
-
icon: /* @__PURE__ */
|
|
10123
|
+
icon: /* @__PURE__ */ jsx49(NavigationRegular, {}),
|
|
8645
10124
|
onClick: () => setNavigationOpen(true)
|
|
8646
10125
|
}
|
|
8647
10126
|
),
|
|
8648
10127
|
narrowHeader,
|
|
8649
|
-
narrowHeaderActions !== void 0 && /* @__PURE__ */
|
|
10128
|
+
narrowHeaderActions !== void 0 && /* @__PURE__ */ jsx49("div", { className: "ml-auto flex items-center gap-2", children: narrowHeaderActions })
|
|
8650
10129
|
] }),
|
|
8651
|
-
/* @__PURE__ */
|
|
10130
|
+
/* @__PURE__ */ jsx49("div", { className: "grid grid-cols-[minmax(0,1fr)] grid-rows-[minmax(0,1fr)] min-h-0", children: frames.map((frame) => /* @__PURE__ */ jsx49(
|
|
8652
10131
|
"div",
|
|
8653
10132
|
{
|
|
8654
10133
|
"aria-hidden": frame.leaving || void 0,
|
|
@@ -8664,7 +10143,7 @@ function AppShell({ children, labels, narrowHeader, narrowHeaderActions, navigat
|
|
|
8664
10143
|
frame.id
|
|
8665
10144
|
)) })
|
|
8666
10145
|
] }),
|
|
8667
|
-
/* @__PURE__ */
|
|
10146
|
+
/* @__PURE__ */ jsx49(
|
|
8668
10147
|
OverlayDrawer,
|
|
8669
10148
|
{
|
|
8670
10149
|
"aria-label": labels.navigation,
|
|
@@ -8672,33 +10151,33 @@ function AppShell({ children, labels, narrowHeader, narrowHeaderActions, navigat
|
|
|
8672
10151
|
onOpenChange: (_2, data) => setNavigationOpen(data.open),
|
|
8673
10152
|
open: navigationOpen,
|
|
8674
10153
|
position: "start",
|
|
8675
|
-
children: /* @__PURE__ */
|
|
10154
|
+
children: /* @__PURE__ */ jsx49(DrawerBody, { className: "!p-0", children: navigation({ onNavigate: () => setNavigationOpen(false) }) })
|
|
8676
10155
|
}
|
|
8677
10156
|
)
|
|
8678
10157
|
] });
|
|
8679
10158
|
}
|
|
8680
10159
|
|
|
8681
10160
|
// src/shell/gradient-background.tsx
|
|
8682
|
-
import { jsx as
|
|
10161
|
+
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
8683
10162
|
function GradientBackground({ children }) {
|
|
8684
|
-
return /* @__PURE__ */
|
|
10163
|
+
return /* @__PURE__ */ jsx50("div", { className: "fwt-gradient-background", children });
|
|
8685
10164
|
}
|
|
8686
10165
|
|
|
8687
10166
|
// src/shell/navigation-pane.tsx
|
|
8688
|
-
import { DismissRegular as
|
|
8689
|
-
import { useRef as
|
|
8690
|
-
import { jsx as
|
|
10167
|
+
import { DismissRegular as DismissRegular4 } from "@fluentui/react-icons";
|
|
10168
|
+
import { useRef as useRef14 } from "react";
|
|
10169
|
+
import { jsx as jsx51, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
8691
10170
|
var {
|
|
8692
|
-
Button:
|
|
10171
|
+
Button: Button13,
|
|
8693
10172
|
NavDrawer,
|
|
8694
10173
|
NavDrawerBody,
|
|
8695
10174
|
NavDrawerFooter,
|
|
8696
10175
|
NavDrawerHeader,
|
|
8697
10176
|
NavItem,
|
|
8698
10177
|
NavSectionHeader,
|
|
8699
|
-
makeStyles:
|
|
10178
|
+
makeStyles: makeStyles19
|
|
8700
10179
|
} = fluentComponents;
|
|
8701
|
-
var
|
|
10180
|
+
var useStyles19 = makeStyles19({
|
|
8702
10181
|
// 36px is a floor rather than a fixed height, so a two-line label lengthens
|
|
8703
10182
|
// the row instead of being cut. The left-pane template's 40px icon column
|
|
8704
10183
|
// plus the presenter's 4 puts the label at 44; Fluent's icon slot is 20px
|
|
@@ -8720,14 +10199,14 @@ var useStyles15 = makeStyles15({
|
|
|
8720
10199
|
});
|
|
8721
10200
|
var NAV_INDICATOR_INSET = 0;
|
|
8722
10201
|
function PaneLink({ item, onNavigate, pending, href }) {
|
|
8723
|
-
const styles =
|
|
10202
|
+
const styles = useStyles19();
|
|
8724
10203
|
const address = useRouteAddress(href);
|
|
8725
10204
|
const handleClick = (event) => {
|
|
8726
10205
|
const followsInThisView = event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
|
|
8727
10206
|
address.onClick(event);
|
|
8728
10207
|
if (followsInThisView) onNavigate?.();
|
|
8729
10208
|
};
|
|
8730
|
-
return /* @__PURE__ */
|
|
10209
|
+
return /* @__PURE__ */ jsx51(
|
|
8731
10210
|
NavItem,
|
|
8732
10211
|
{
|
|
8733
10212
|
as: "a",
|
|
@@ -8743,11 +10222,11 @@ function PaneLink({ item, onNavigate, pending, href }) {
|
|
|
8743
10222
|
);
|
|
8744
10223
|
}
|
|
8745
10224
|
function PaneItem({ item, onNavigate, pendingValue }) {
|
|
8746
|
-
const styles =
|
|
10225
|
+
const styles = useStyles19();
|
|
8747
10226
|
if (item.href !== void 0) {
|
|
8748
|
-
return /* @__PURE__ */
|
|
10227
|
+
return /* @__PURE__ */ jsx51(PaneLink, { href: item.href, item, onNavigate, pending: pendingValue === item.value });
|
|
8749
10228
|
}
|
|
8750
|
-
return /* @__PURE__ */
|
|
10229
|
+
return /* @__PURE__ */ jsx51(NavItem, { className: styles.item, "data-nav-value": item.value, icon: item.icon, value: item.value, children: item.label });
|
|
8751
10230
|
}
|
|
8752
10231
|
function NavigationPane({
|
|
8753
10232
|
closeLabel = "Close navigation",
|
|
@@ -8760,10 +10239,10 @@ function NavigationPane({
|
|
|
8760
10239
|
pendingValue,
|
|
8761
10240
|
selectedValue
|
|
8762
10241
|
}) {
|
|
8763
|
-
const bodyRef =
|
|
8764
|
-
const footerRef =
|
|
10242
|
+
const bodyRef = useRef14(null);
|
|
10243
|
+
const footerRef = useRef14(null);
|
|
8765
10244
|
const allItems = [...groups.flatMap((group) => group.items), ...footerItems];
|
|
8766
|
-
return /* @__PURE__ */
|
|
10245
|
+
return /* @__PURE__ */ jsxs27(
|
|
8767
10246
|
NavDrawer,
|
|
8768
10247
|
{
|
|
8769
10248
|
"aria-label": label,
|
|
@@ -8778,21 +10257,21 @@ function NavigationPane({
|
|
|
8778
10257
|
surfaceMotion: null,
|
|
8779
10258
|
type: "inline",
|
|
8780
10259
|
children: [
|
|
8781
|
-
/* @__PURE__ */
|
|
10260
|
+
/* @__PURE__ */ jsx51(NavDrawerHeader, { className: "!bg-transparent !px-5 !py-4", children: /* @__PURE__ */ jsxs27("div", { className: "flex items-center min-h-10", children: [
|
|
8782
10261
|
header,
|
|
8783
|
-
!onNavigate && headerActions !== void 0 && /* @__PURE__ */
|
|
8784
|
-
onNavigate && /* @__PURE__ */
|
|
10262
|
+
!onNavigate && headerActions !== void 0 && /* @__PURE__ */ jsx51("div", { className: "ml-auto flex items-center gap-2", children: headerActions }),
|
|
10263
|
+
onNavigate && /* @__PURE__ */ jsx51(Button13, { appearance: "subtle", "aria-label": closeLabel, className: "!ml-auto", icon: /* @__PURE__ */ jsx51(DismissRegular4, {}), onClick: onNavigate })
|
|
8785
10264
|
] }) }),
|
|
8786
|
-
/* @__PURE__ */
|
|
8787
|
-
/* @__PURE__ */
|
|
8788
|
-
groups.map((group, groupIndex) => group.items.length === 0 ? null : /* @__PURE__ */
|
|
8789
|
-
group.label !== void 0 && /* @__PURE__ */
|
|
8790
|
-
/* @__PURE__ */
|
|
10265
|
+
/* @__PURE__ */ jsx51(NavDrawerBody, { className: "!bg-transparent overflow-hidden !p-0", children: /* @__PURE__ */ jsx51(ScrollArea, { axes: "vertical", className: "h-full min-h-0", contentClassName: "px-[10px]", noTabIndex: true, children: /* @__PURE__ */ jsxs27("div", { className: "relative", ref: bodyRef, children: [
|
|
10266
|
+
/* @__PURE__ */ jsx51(NavSelectionIndicator, { containerRef: bodyRef, inset: NAV_INDICATOR_INSET, otherListIs: "below", selectedValue }),
|
|
10267
|
+
groups.map((group, groupIndex) => group.items.length === 0 ? null : /* @__PURE__ */ jsxs27("div", { children: [
|
|
10268
|
+
group.label !== void 0 && /* @__PURE__ */ jsx51(NavSectionHeader, { children: group.label }),
|
|
10269
|
+
/* @__PURE__ */ jsx51("div", { className: "grid gap-1", children: group.items.map((item) => /* @__PURE__ */ jsx51(PaneItem, { item, onNavigate, pendingValue }, item.value)) })
|
|
8791
10270
|
] }, groupIndex))
|
|
8792
10271
|
] }) }) }),
|
|
8793
|
-
footerItems.length > 0 && /* @__PURE__ */
|
|
8794
|
-
/* @__PURE__ */
|
|
8795
|
-
footerItems.map((item) => /* @__PURE__ */
|
|
10272
|
+
footerItems.length > 0 && /* @__PURE__ */ jsx51(NavDrawerFooter, { className: "!bg-transparent !gap-y-1 !px-[10px] !py-3", children: /* @__PURE__ */ jsxs27("div", { className: "grid gap-y-1 relative w-full", ref: footerRef, children: [
|
|
10273
|
+
/* @__PURE__ */ jsx51(NavSelectionIndicator, { containerRef: footerRef, inset: NAV_INDICATOR_INSET, otherListIs: "above", selectedValue }),
|
|
10274
|
+
footerItems.map((item) => /* @__PURE__ */ jsx51(PaneItem, { item, onNavigate, pendingValue }, item.value))
|
|
8796
10275
|
] }) })
|
|
8797
10276
|
]
|
|
8798
10277
|
}
|
|
@@ -8800,9 +10279,9 @@ function NavigationPane({
|
|
|
8800
10279
|
}
|
|
8801
10280
|
|
|
8802
10281
|
// src/shell/navigation-progress.tsx
|
|
8803
|
-
import { jsx as
|
|
10282
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
8804
10283
|
function NavigationProgress({ active }) {
|
|
8805
|
-
return /* @__PURE__ */
|
|
10284
|
+
return /* @__PURE__ */ jsx52("div", { "aria-hidden": "true", className: "fwt-navigation-progress", "data-active": active });
|
|
8806
10285
|
}
|
|
8807
10286
|
export {
|
|
8808
10287
|
AppLoadingScreen,
|
|
@@ -8823,8 +10302,11 @@ export {
|
|
|
8823
10302
|
CodeBlock,
|
|
8824
10303
|
Combobox,
|
|
8825
10304
|
ConfirmDialog,
|
|
10305
|
+
ConfirmDialogProvider,
|
|
10306
|
+
ConfirmFlyout,
|
|
8826
10307
|
ContentLoadingScreen,
|
|
8827
10308
|
DashboardPageHeader,
|
|
10309
|
+
DataTable,
|
|
8828
10310
|
DialogShell,
|
|
8829
10311
|
Dropdown,
|
|
8830
10312
|
EXPAND_ANIMATION_MS,
|
|
@@ -8832,6 +10314,8 @@ export {
|
|
|
8832
10314
|
EmptyStateLine,
|
|
8833
10315
|
ErrorShell,
|
|
8834
10316
|
ErrorStack,
|
|
10317
|
+
FileDropZone,
|
|
10318
|
+
FilePickerButton,
|
|
8835
10319
|
GradientBackground,
|
|
8836
10320
|
HEADER_ROW_CLASS,
|
|
8837
10321
|
HttpMethodBadge,
|
|
@@ -8843,10 +10327,13 @@ export {
|
|
|
8843
10327
|
Input,
|
|
8844
10328
|
LISTBOX_POSITIONING,
|
|
8845
10329
|
MaskedIcon,
|
|
10330
|
+
Metric,
|
|
10331
|
+
MetricGrid,
|
|
8846
10332
|
MultiselectCombobox,
|
|
8847
10333
|
NavSelectionIndicator,
|
|
8848
10334
|
NavigationPane,
|
|
8849
10335
|
NavigationProgress,
|
|
10336
|
+
NumberBox,
|
|
8850
10337
|
OpenLinkLabel,
|
|
8851
10338
|
OutcomeMessageBar,
|
|
8852
10339
|
OutcomeToastProvider,
|
|
@@ -8869,8 +10356,10 @@ export {
|
|
|
8869
10356
|
POPUP_SLIDE_EASING,
|
|
8870
10357
|
POPUP_SLIDE_MS,
|
|
8871
10358
|
POP_IN_OFFSET_PX,
|
|
10359
|
+
Pager,
|
|
8872
10360
|
Panel,
|
|
8873
10361
|
ProgressRing,
|
|
10362
|
+
PropertyList,
|
|
8874
10363
|
REPOSITION_ANIMATION_MS,
|
|
8875
10364
|
REPOSITION_DELETE_DELAY_MS,
|
|
8876
10365
|
REPOSITION_EASING,
|
|
@@ -8895,6 +10384,7 @@ export {
|
|
|
8895
10384
|
THEME_MODE_ATTRIBUTE,
|
|
8896
10385
|
TIGHT_STACK_CLASS,
|
|
8897
10386
|
TWO_COLUMN_FORM_CLASS,
|
|
10387
|
+
TabView,
|
|
8898
10388
|
TableActions,
|
|
8899
10389
|
TableCentredCell,
|
|
8900
10390
|
TableCentredHeader,
|
|
@@ -8908,21 +10398,32 @@ export {
|
|
|
8908
10398
|
WinuiStringsProvider,
|
|
8909
10399
|
applyThemeMode,
|
|
8910
10400
|
baseFontStack,
|
|
10401
|
+
clampNumber,
|
|
8911
10402
|
copyOutcomeIcon,
|
|
8912
10403
|
copyToClipboard,
|
|
8913
10404
|
fluentComponents,
|
|
10405
|
+
formatFileSize,
|
|
10406
|
+
formatMetricValue,
|
|
8914
10407
|
infoLabelSlot,
|
|
10408
|
+
matchesAccept,
|
|
8915
10409
|
monospaceStack,
|
|
8916
10410
|
moveItem,
|
|
8917
10411
|
pageFrameClassName,
|
|
10412
|
+
pagerPageCount,
|
|
10413
|
+
pagerPageWindow,
|
|
10414
|
+
parseNumberText,
|
|
8918
10415
|
progressIndeterminateCss,
|
|
8919
10416
|
refuseToggle,
|
|
10417
|
+
resolveNumberChange,
|
|
8920
10418
|
resolveThemeMode,
|
|
10419
|
+
stepPrecision,
|
|
8921
10420
|
stopRowSelection,
|
|
8922
10421
|
useBadgeHue,
|
|
10422
|
+
useConfirm,
|
|
8923
10423
|
useCopyLabel,
|
|
8924
10424
|
useCopyToClipboard,
|
|
8925
10425
|
useDangerActionClasses,
|
|
10426
|
+
useDangerFillClass,
|
|
8926
10427
|
useDangerTextClass,
|
|
8927
10428
|
useDialogInvocation,
|
|
8928
10429
|
useDiscardGuard,
|
|
@@ -8931,6 +10432,7 @@ export {
|
|
|
8931
10432
|
useReorderList,
|
|
8932
10433
|
useRouteAddress,
|
|
8933
10434
|
useScrollAreaHost,
|
|
10435
|
+
useToast,
|
|
8934
10436
|
useTruncation,
|
|
8935
10437
|
useWinuiTheme,
|
|
8936
10438
|
valuesAsOptions,
|