@babylonjs/shared-ui-components 9.29.0 → 9.31.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/fluent/hoc/propertyLines/colorPropertyLineCore.js +3 -3
- package/fluent/hoc/propertyLines/colorPropertyLineCore.js.map +1 -1
- package/fluent/hoc/propertyLines/materialTextureBindingPropertyLine.d.ts +29 -0
- package/fluent/hoc/propertyLines/materialTextureBindingPropertyLine.js +27 -0
- package/fluent/hoc/propertyLines/materialTextureBindingPropertyLine.js.map +1 -0
- package/fluent/hoc/propertyLines/vectorPropertyLineCore.js +3 -3
- package/fluent/hoc/propertyLines/vectorPropertyLineCore.js.map +1 -1
- package/fluent/primitives/comboBox.d.ts +8 -0
- package/fluent/primitives/comboBox.js +8 -3
- package/fluent/primitives/comboBox.js.map +1 -1
- package/fluent/primitives/entitySelector.js +7 -66
- package/fluent/primitives/entitySelector.js.map +1 -1
- package/fluent/primitives/resourceSelector.d.ts +37 -0
- package/fluent/primitives/resourceSelector.js +63 -0
- package/fluent/primitives/resourceSelector.js.map +1 -0
- package/fluent/primitives/toggleButton.d.ts +7 -4
- package/fluent/primitives/toggleButton.js +9 -16
- package/fluent/primitives/toggleButton.js.map +1 -1
- package/lines/buttonLineComponent.js +1 -1
- package/lines/buttonLineComponent.js.map +1 -1
- package/lite/fluent/hoc/propertyLines/vectorPropertyLine.js +3 -3
- package/lite/fluent/hoc/propertyLines/vectorPropertyLine.js.map +1 -1
- package/nodeGraphSystem/graphCanvas.d.ts +2 -1
- package/nodeGraphSystem/graphCanvas.js +18 -5
- package/nodeGraphSystem/graphCanvas.js.map +1 -1
- package/nodeGraphSystem/stateManager.d.ts +5 -0
- package/nodeGraphSystem/stateManager.js +5 -0
- package/nodeGraphSystem/stateManager.js.map +1 -1
- package/nodeGraphSystem/teleportInPropertyComponent.d.ts +15 -0
- package/nodeGraphSystem/teleportInPropertyComponent.js +39 -0
- package/nodeGraphSystem/teleportInPropertyComponent.js.map +1 -0
- package/package.json +5 -5
|
@@ -25,7 +25,7 @@ export const ControlledColorPropertyLine = (props) => {
|
|
|
25
25
|
}, currentValue));
|
|
26
26
|
};
|
|
27
27
|
const color = adapter.getColor(currentValue);
|
|
28
|
-
return (_jsx(PropertyLine, { ref: propertyLineRef, ...props, expandedContent: _jsx(ColorSliders, { color: color, onSliderChange: onSliderChange }), children: createElement(adapter.picker, {
|
|
28
|
+
return (_jsx(PropertyLine, { ref: propertyLineRef, ...props, expandedContent: _jsx(ColorSliders, { color: color, onSliderChange: onSliderChange, disabled: props.disabled }), children: createElement(adapter.picker, {
|
|
29
29
|
value: currentValue,
|
|
30
30
|
onChange: handleChange,
|
|
31
31
|
isLinearMode: props.isLinearMode,
|
|
@@ -36,7 +36,7 @@ export const ControlledColorPropertyLine = (props) => {
|
|
|
36
36
|
}) }));
|
|
37
37
|
};
|
|
38
38
|
const ColorSliders = (props) => {
|
|
39
|
-
const { color, onSliderChange } = props;
|
|
40
|
-
return (_jsxs(_Fragment, { children: [_jsx(SyncedSliderPropertyLine, { label: "R", value: color.r * 255, min: 0, max: 255, onChange: (value) => onSliderChange(value, "r") }), _jsx(SyncedSliderPropertyLine, { label: "G", value: color.g * 255, min: 0, max: 255, onChange: (value) => onSliderChange(value, "g") }), _jsx(SyncedSliderPropertyLine, { label: "B", value: color.b * 255, min: 0, max: 255, onChange: (value) => onSliderChange(value, "b") }), color.a === undefined ? undefined : (_jsx(SyncedSliderPropertyLine, { label: "A", value: color.a, min: 0, max: 1, step: 0.01, onChange: (value) => onSliderChange(value, "a") }))] }));
|
|
39
|
+
const { color, disabled, onSliderChange } = props;
|
|
40
|
+
return (_jsxs(_Fragment, { children: [_jsx(SyncedSliderPropertyLine, { label: "R", value: color.r * 255, min: 0, max: 255, disabled: disabled, onChange: (value) => onSliderChange(value, "r") }), _jsx(SyncedSliderPropertyLine, { label: "G", value: color.g * 255, min: 0, max: 255, disabled: disabled, onChange: (value) => onSliderChange(value, "g") }), _jsx(SyncedSliderPropertyLine, { label: "B", value: color.b * 255, min: 0, max: 255, disabled: disabled, onChange: (value) => onSliderChange(value, "b") }), color.a === undefined ? undefined : (_jsx(SyncedSliderPropertyLine, { label: "A", value: color.a, min: 0, max: 1, step: 0.01, disabled: disabled, onChange: (value) => onSliderChange(value, "a") }))] }));
|
|
41
41
|
};
|
|
42
42
|
//# sourceMappingURL=colorPropertyLineCore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colorPropertyLineCore.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/colorPropertyLineCore.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAwD,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjH,OAAO,EAA0B,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAetE;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAU,KAA+C,EAAE,EAAE;IACpG,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAC5D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExD,SAAS,CAAC,GAAG,EAAE;QACX,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,YAAY,GAAG,CAAC,QAAgB,EAAE,EAAE;QACtC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC1B,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,cAAsB,EAAE,SAAgC,EAAE,EAAE;QAChF,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC7C,YAAY,CACR,OAAO,CAAC,WAAW,CACf;YACI,GAAG,KAAK;YACR,CAAC,SAAS,CAAC,EAAE,SAAS,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,GAAG,GAAG;SACzE,EACD,YAAY,CACf,CACJ,CAAC;IACN,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC7C,OAAO,CACH,KAAC,YAAY,IAAC,GAAG,EAAE,eAAe,KAAM,KAAK,EAAE,eAAe,EAAE,KAAC,YAAY,IAAC,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,cAAc,GAAI,
|
|
1
|
+
{"version":3,"file":"colorPropertyLineCore.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/colorPropertyLineCore.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAwD,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjH,OAAO,EAA0B,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAetE;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAU,KAA+C,EAAE,EAAE;IACpG,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAC5D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExD,SAAS,CAAC,GAAG,EAAE;QACX,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,YAAY,GAAG,CAAC,QAAgB,EAAE,EAAE;QACtC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC1B,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,cAAsB,EAAE,SAAgC,EAAE,EAAE;QAChF,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC7C,YAAY,CACR,OAAO,CAAC,WAAW,CACf;YACI,GAAG,KAAK;YACR,CAAC,SAAS,CAAC,EAAE,SAAS,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,GAAG,GAAG;SACzE,EACD,YAAY,CACf,CACJ,CAAC;IACN,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC7C,OAAO,CACH,KAAC,YAAY,IAAC,GAAG,EAAE,eAAe,KAAM,KAAK,EAAE,eAAe,EAAE,KAAC,YAAY,IAAC,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAI,YACnJ,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE;YAC3B,KAAK,EAAE,YAAY;YACnB,QAAQ,EAAE,YAAY;YACtB,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;SACrB,CAAC,GACS,CAClB,CAAC;AACN,CAAC,CAAC;AAQF,MAAM,YAAY,GAAyC,CAAC,KAAK,EAAE,EAAE;IACjE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAElD,OAAO,CACH,8BACI,KAAC,wBAAwB,IAAC,KAAK,EAAC,GAAG,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,GAAI,EACnJ,KAAC,wBAAwB,IAAC,KAAK,EAAC,GAAG,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,GAAI,EACnJ,KAAC,wBAAwB,IAAC,KAAK,EAAC,GAAG,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,GAAI,EAClJ,KAAK,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CACjC,KAAC,wBAAwB,IAAC,KAAK,EAAC,GAAG,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,GAAI,CAC1J,IACF,CACN,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { createElement, type ComponentType, type FunctionComponent, type Ref, useEffect, useState } from \"react\";\r\n\r\nimport { type StructuralColor, type StructuralColorAdapter } from \"../../primitives/structuralColorPicker\";\r\nimport { type PrimitiveProps } from \"../../primitives/primitive\";\r\nimport { type PropertyLineProps, PropertyLine } from \"./propertyLine\";\r\nimport { SyncedSliderPropertyLine } from \"./syncedSliderPropertyLine\";\r\n\r\nexport type ColorPropertyLineAdapter<ValueT> = StructuralColorAdapter<ValueT> &\r\n Readonly<{\r\n picker: ComponentType<PrimitiveProps<ValueT> & { isLinearMode?: boolean }>;\r\n }>;\r\n\r\nexport type ControlledColorPropertyLineProps<ValueT> = PrimitiveProps<ValueT> &\r\n PropertyLineProps<ValueT> &\r\n Readonly<{\r\n adapter: ColorPropertyLineAdapter<ValueT>;\r\n isLinearMode?: boolean;\r\n propertyLineRef?: Ref<HTMLDivElement>;\r\n }>;\r\n\r\n/**\r\n * Runtime-neutral controlled color editor with RGB or RGBA sliders and an injected picker.\r\n * @param props The controlled color, runtime adapter, and property-line presentation.\r\n * @returns The color property line.\r\n */\r\nexport const ControlledColorPropertyLine = <ValueT,>(props: ControlledColorPropertyLineProps<ValueT>) => {\r\n const { adapter, value, onChange, propertyLineRef } = props;\r\n const [currentValue, setCurrentValue] = useState(value);\r\n\r\n useEffect(() => {\r\n setCurrentValue(value);\r\n }, [value]);\r\n\r\n const handleChange = (newValue: ValueT) => {\r\n setCurrentValue(newValue);\r\n onChange(newValue);\r\n };\r\n\r\n const onSliderChange = (componentValue: number, component: keyof StructuralColor) => {\r\n const color = adapter.getColor(currentValue);\r\n handleChange(\r\n adapter.createColor(\r\n {\r\n ...color,\r\n [component]: component === \"a\" ? componentValue : componentValue / 255,\r\n },\r\n currentValue\r\n )\r\n );\r\n };\r\n\r\n const color = adapter.getColor(currentValue);\r\n return (\r\n <PropertyLine ref={propertyLineRef} {...props} expandedContent={<ColorSliders color={color} onSliderChange={onSliderChange} disabled={props.disabled} />}>\r\n {createElement(adapter.picker, {\r\n value: currentValue,\r\n onChange: handleChange,\r\n isLinearMode: props.isLinearMode,\r\n disabled: props.disabled,\r\n className: props.className,\r\n style: props.style,\r\n title: props.title,\r\n })}\r\n </PropertyLine>\r\n );\r\n};\r\n\r\ntype ColorSlidersProps = Readonly<{\r\n color: StructuralColor;\r\n disabled?: boolean;\r\n onSliderChange: (value: number, component: keyof StructuralColor) => void;\r\n}>;\r\n\r\nconst ColorSliders: FunctionComponent<ColorSlidersProps> = (props) => {\r\n const { color, disabled, onSliderChange } = props;\r\n\r\n return (\r\n <>\r\n <SyncedSliderPropertyLine label=\"R\" value={color.r * 255} min={0} max={255} disabled={disabled} onChange={(value) => onSliderChange(value, \"r\")} />\r\n <SyncedSliderPropertyLine label=\"G\" value={color.g * 255} min={0} max={255} disabled={disabled} onChange={(value) => onSliderChange(value, \"g\")} />\r\n <SyncedSliderPropertyLine label=\"B\" value={color.b * 255} min={0} max={255} disabled={disabled} onChange={(value) => onSliderChange(value, \"b\")} />\r\n {color.a === undefined ? undefined : (\r\n <SyncedSliderPropertyLine label=\"A\" value={color.a} min={0} max={1} step={0.01} disabled={disabled} onChange={(value) => onSliderChange(value, \"a\")} />\r\n )}\r\n </>\r\n );\r\n};\r\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
2
|
+
/** Directional mutations supported by a texture binding. */
|
|
3
|
+
export type TextureBindingWriteCapabilities<TextureT> = Readonly<{
|
|
4
|
+
assign?: (texture: TextureT) => void;
|
|
5
|
+
clear?: () => void;
|
|
6
|
+
}>;
|
|
7
|
+
/** Runtime-neutral presentation and mutation props for a material texture binding. */
|
|
8
|
+
export type MaterialTextureBindingProps<TextureT> = Readonly<{
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
value: TextureT | null;
|
|
12
|
+
candidates: readonly TextureT[];
|
|
13
|
+
getDisplayName: (texture: TextureT) => string;
|
|
14
|
+
getKind: (texture: TextureT) => string;
|
|
15
|
+
acceptedKinds: readonly string[];
|
|
16
|
+
isCandidateAccepted?: (texture: TextureT) => boolean;
|
|
17
|
+
getId?: (texture: TextureT) => string;
|
|
18
|
+
write?: TextureBindingWriteCapabilities<TextureT>;
|
|
19
|
+
navigate?: (texture: TextureT) => void;
|
|
20
|
+
pending?: boolean;
|
|
21
|
+
error?: string;
|
|
22
|
+
expandedContent?: ReactElement;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Displays a runtime-neutral, direction-aware material texture binding.
|
|
26
|
+
* @param props The binding props. Missing assign, clear, or navigation callbacks remove those actions.
|
|
27
|
+
* @returns A texture binding property line.
|
|
28
|
+
*/
|
|
29
|
+
export declare const MaterialTextureBindingPropertyLine: <TextureT>(props: MaterialTextureBindingProps<TextureT>) => JSX.Element;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Body1, makeStyles, tokens } from "@fluentui/react-components";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { ResourceSelector } from "../../primitives/resourceSelector.js";
|
|
5
|
+
import { PropertyLine } from "./propertyLine.js";
|
|
6
|
+
const useStyles = makeStyles({
|
|
7
|
+
content: {
|
|
8
|
+
display: "flex",
|
|
9
|
+
flexDirection: "row",
|
|
10
|
+
alignItems: "center",
|
|
11
|
+
gap: tokens.spacingHorizontalS,
|
|
12
|
+
minWidth: 0,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Displays a runtime-neutral, direction-aware material texture binding.
|
|
17
|
+
* @param props The binding props. Missing assign, clear, or navigation callbacks remove those actions.
|
|
18
|
+
* @returns A texture binding property line.
|
|
19
|
+
*/
|
|
20
|
+
export const MaterialTextureBindingPropertyLine = (props) => {
|
|
21
|
+
const classes = useStyles();
|
|
22
|
+
const candidates = useMemo(() => props.candidates.filter((texture) => props.acceptedKinds.includes(props.getKind(texture)) && (props.isCandidateAccepted?.(texture) ?? true)), [props.acceptedKinds, props.candidates, props.getKind, props.isCandidateAccepted]);
|
|
23
|
+
const getId = (texture) => props.getId?.(texture) ?? String(props.candidates.indexOf(texture));
|
|
24
|
+
const content = (_jsxs("div", { className: classes.content, children: [_jsx(ResourceSelector, { value: props.value, getEntities: () => candidates, getName: props.getDisplayName, getId: getId, onSelect: props.write?.assign ? (texture) => texture && props.write?.assign?.(texture) : undefined, onClear: props.write?.clear, onLink: props.navigate, disabled: props.pending, ariaLabel: props.label }), props.pending ? _jsx(Body1, { role: "status", children: "Applying\u2026" }) : undefined] }));
|
|
25
|
+
return (_jsx("div", { role: props.error ? "alert" : undefined, "aria-label": props.error ? `${props.label}: ${props.error}` : undefined, "aria-busy": props.pending, children: props.expandedContent ? (_jsx(PropertyLine, { label: props.label, uniqueId: props.id, description: props.error, expandedContent: props.expandedContent, children: content })) : (_jsx(PropertyLine, { label: props.label, uniqueId: props.id, description: props.error, children: content })) }));
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=materialTextureBindingPropertyLine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materialTextureBindingPropertyLine.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/materialTextureBindingPropertyLine.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Body1, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { type ReactElement, useMemo } from \"react\";\n\nimport { ResourceSelector } from \"../../primitives/resourceSelector\";\nimport { PropertyLine } from \"./propertyLine\";\n\nconst useStyles = makeStyles({\n content: {\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: tokens.spacingHorizontalS,\n minWidth: 0,\n },\n});\n\n/** Directional mutations supported by a texture binding. */\nexport type TextureBindingWriteCapabilities<TextureT> = Readonly<{\n assign?: (texture: TextureT) => void;\n clear?: () => void;\n}>;\n\n/** Runtime-neutral presentation and mutation props for a material texture binding. */\nexport type MaterialTextureBindingProps<TextureT> = Readonly<{\n id: string;\n label: string;\n value: TextureT | null;\n candidates: readonly TextureT[];\n getDisplayName: (texture: TextureT) => string;\n getKind: (texture: TextureT) => string;\n acceptedKinds: readonly string[];\n isCandidateAccepted?: (texture: TextureT) => boolean;\n getId?: (texture: TextureT) => string;\n write?: TextureBindingWriteCapabilities<TextureT>;\n navigate?: (texture: TextureT) => void;\n pending?: boolean;\n error?: string;\n expandedContent?: ReactElement;\n}>;\n\n/**\n * Displays a runtime-neutral, direction-aware material texture binding.\n * @param props The binding props. Missing assign, clear, or navigation callbacks remove those actions.\n * @returns A texture binding property line.\n */\nexport const MaterialTextureBindingPropertyLine = <TextureT,>(props: MaterialTextureBindingProps<TextureT>): JSX.Element => {\n const classes = useStyles();\n const candidates = useMemo(\n () => props.candidates.filter((texture) => props.acceptedKinds.includes(props.getKind(texture)) && (props.isCandidateAccepted?.(texture) ?? true)),\n [props.acceptedKinds, props.candidates, props.getKind, props.isCandidateAccepted]\n );\n const getId = (texture: TextureT) => props.getId?.(texture) ?? String(props.candidates.indexOf(texture));\n\n const content = (\n <div className={classes.content}>\n <ResourceSelector\n value={props.value}\n getEntities={() => candidates}\n getName={props.getDisplayName}\n getId={getId}\n onSelect={props.write?.assign ? (texture) => texture && props.write?.assign?.(texture) : undefined}\n onClear={props.write?.clear}\n onLink={props.navigate}\n disabled={props.pending}\n ariaLabel={props.label}\n />\n {props.pending ? <Body1 role=\"status\">Applying…</Body1> : undefined}\n </div>\n );\n\n return (\n <div role={props.error ? \"alert\" : undefined} aria-label={props.error ? `${props.label}: ${props.error}` : undefined} aria-busy={props.pending}>\n {props.expandedContent ? (\n <PropertyLine label={props.label} uniqueId={props.id} description={props.error} expandedContent={props.expandedContent}>\n {content}\n </PropertyLine>\n ) : (\n <PropertyLine label={props.label} uniqueId={props.id} description={props.error}>\n {content}\n </PropertyLine>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -25,11 +25,11 @@ export const ControlledTensorPropertyLine = (props) => {
|
|
|
25
25
|
props.onChange(newValue);
|
|
26
26
|
};
|
|
27
27
|
const summary = adapter.components.map((component) => formatted(adapter.getComponent(props.value, component))).join(", ");
|
|
28
|
-
return (_jsx(PropertyLine, { ...props, expandedContent: _jsxs(_Fragment, { children: [props.expandedContent, _jsx(TensorSliders, { value: value, adapter: adapter, min: min, max: max, unit: unit, step: step, precision: precision, converted: converted, onChange: onComponentChange })] }), children: _jsx(Body1, { children: `[${summary}]` }) }));
|
|
28
|
+
return (_jsx(PropertyLine, { ...props, expandedContent: _jsxs(_Fragment, { children: [props.expandedContent, _jsx(TensorSliders, { value: value, adapter: adapter, min: min, max: max, unit: unit, step: step, precision: precision, disabled: props.disabled, converted: converted, onChange: onComponentChange })] }), children: _jsx(Body1, { children: `[${summary}]` }) }));
|
|
29
29
|
};
|
|
30
30
|
const TensorSliders = (props) => {
|
|
31
|
-
const { value, adapter, min, max, unit, step, precision, converted, onChange } = props;
|
|
32
|
-
return (_jsx(_Fragment, { children: adapter.components.map((component) => (_jsx(NumberInputPropertyLine, { label: component.toUpperCase(), value: converted(adapter.getComponent(value, component)), min: min, max: max, onChange: (componentValue) => onChange(componentValue, component), unit: unit, step: step, precision: precision }, component))) }));
|
|
31
|
+
const { value, adapter, min, max, unit, step, precision, disabled, converted, onChange } = props;
|
|
32
|
+
return (_jsx(_Fragment, { children: adapter.components.map((component) => (_jsx(NumberInputPropertyLine, { label: component.toUpperCase(), value: converted(adapter.getComponent(value, component)), min: min, max: max, onChange: (componentValue) => onChange(componentValue, component), unit: unit, step: step, precision: precision, disabled: disabled }, component))) }));
|
|
33
33
|
};
|
|
34
34
|
export const RadiansToDegreesConverter = {
|
|
35
35
|
from: (value) => (value * 180) / Math.PI,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vectorPropertyLineCore.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/vectorPropertyLineCore.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAA0B,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAgCtD;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAU,KAAgD,EAAE,EAAE;IACtG,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAC3E,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC3F,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7I,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEhD,SAAS,CAAC,GAAG,EAAE;QACX,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;IAEzC,MAAM,iBAAiB,GAAG,CAAC,cAAsB,EAAE,SAA0B,EAAE,EAAE;QAC7E,MAAM,WAAW,GAAG,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;QACxF,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QACtE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnB,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE1H,OAAO,CACH,KAAC,YAAY,OACL,KAAK,EACT,eAAe,EACX,8BACK,KAAK,CAAC,eAAe,EACtB,KAAC,aAAa,IACV,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,iBAAiB,GAC7B,IACH,YAGP,KAAC,KAAK,cAAE,IAAI,OAAO,GAAG,GAAS,GACpB,CAClB,CAAC;AACN,CAAC,CAAC;AAcF,MAAM,aAAa,GAAG,CAAU,KAAiC,EAAE,EAAE;IACjE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAEvF,OAAO,CACH,4BACK,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CACnC,KAAC,uBAAuB,IAEpB,KAAK,EAAE,SAAS,CAAC,WAAW,EAAE,EAC9B,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EACxD,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,EACjE,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,IARf,SAAS,CAShB,CACL,CAAC,GACH,CACN,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACrC,IAAI,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE;IAChD,EAAE,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG;CACjD,CAAC;AAQF;;;;GAIG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAU,KAAwD,EAAE,EAAE;IACtH,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAEtC,OAAO,CACH,KAAC,4BAA4B,OACrB,IAAI,EACR,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAC9B,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,SAAS,EAClE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAC3B,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAC/B,CACL,CAAC;AACN,CAAC,CAAC;AAgBF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAsB,KAAiE,EAAE,EAAE;IACvI,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACzD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE1D,SAAS,CAAC,GAAG,EAAE;QACX,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAElB,MAAM,kBAAkB,GAAG,CAAC,KAAkB,EAAE,EAAE;QAC9C,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEzJ,OAAO,CACH,KAAC,4BAA4B,OACrB,IAAI,EACR,QAAQ,EAAE,KAAK,EACf,cAAc,EAAE,KAAK,EACrB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAClC,OAAO,EAAE,OAAO,CAAC,KAAK,EACtB,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,SAAS,EAClE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,EAC7E,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAC9B,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAC3B,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC7B,eAAe,EAAE,KAAC,gBAAgB,IAAC,KAAK,EAAC,YAAY,EAAC,KAAK,EAAE,IAAI,iBAAiB,GAAG,GAAI,GAC3F,CACL,CAAC;IACN,CAAC;IAED,OAAO,CACH,KAAC,4BAA4B,OACrB,IAAI,EACR,QAAQ,EAAE,KAAK,EACf,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO,CAAC,UAAU,EAC3B,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAC9B,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAC3B,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAC/B,CACL,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { Body1 } from \"@fluentui/react-components\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nimport { type PrimitiveProps } from \"../../primitives/primitive\";\r\nimport { CalculatePrecision } from \"../../primitives/utils\";\r\nimport { NumberInputPropertyLine } from \"./inputPropertyLine\";\r\nimport { type PropertyLineProps, PropertyLine } from \"./propertyLine\";\r\nimport { TextPropertyLine } from \"./textPropertyLine\";\r\n\r\nexport type TensorComponent = \"x\" | \"y\" | \"z\" | \"w\";\r\n\r\nexport type TensorValue2 = Readonly<{ x: number; y: number }>;\r\nexport type TensorValue3 = TensorValue2 & Readonly<{ z: number }>;\r\nexport type TensorValue4 = TensorValue3 & Readonly<{ w: number }>;\r\n\r\nexport type TensorPropertyLineProps<ValueT> = PropertyLineProps<ValueT> &\r\n PrimitiveProps<ValueT> & {\r\n min?: number;\r\n max?: number;\r\n unit?: string;\r\n step?: number;\r\n precision?: number;\r\n valueConverter?: {\r\n from: (value: number) => number;\r\n to: (value: number) => number;\r\n };\r\n };\r\n\r\nexport type TensorValueAdapter<ValueT> = Readonly<{\r\n components: readonly TensorComponent[];\r\n getComponent: (value: ValueT, component: TensorComponent) => number;\r\n withComponent: (value: ValueT, component: TensorComponent, componentValue: number) => ValueT;\r\n}>;\r\n\r\ntype ControlledTensorPropertyLineProps<ValueT> = TensorPropertyLineProps<ValueT> &\r\n Readonly<{\r\n adapter: TensorValueAdapter<ValueT>;\r\n }>;\r\n\r\n/**\r\n * Runtime-neutral controlled editor for two-, three-, and four-component numeric values.\r\n * @param props The value, change callback, component adapter, and property-line presentation.\r\n * @returns The tensor property line.\r\n */\r\nexport const ControlledTensorPropertyLine = <ValueT,>(props: ControlledTensorPropertyLineProps<ValueT>) => {\r\n const { adapter, min, max, unit, step, precision, valueConverter } = props;\r\n const converted = (value: number) => (valueConverter ? valueConverter.from(value) : value);\r\n const formatted = (value: number) => converted(value).toFixed(precision ?? (step !== undefined ? Math.max(0, CalculatePrecision(step)) : 2));\r\n const [value, setValue] = useState(props.value);\r\n\r\n useEffect(() => {\r\n setValue(props.value);\r\n }, [props.value, props.expandedContent]);\r\n\r\n const onComponentChange = (componentValue: number, component: TensorComponent) => {\r\n const storedValue = valueConverter ? valueConverter.to(componentValue) : componentValue;\r\n const newValue = adapter.withComponent(value, component, storedValue);\r\n setValue(newValue);\r\n props.onChange(newValue);\r\n };\r\n\r\n const summary = adapter.components.map((component) => formatted(adapter.getComponent(props.value, component))).join(\", \");\r\n\r\n return (\r\n <PropertyLine\r\n {...props}\r\n expandedContent={\r\n <>\r\n {props.expandedContent}\r\n <TensorSliders\r\n value={value}\r\n adapter={adapter}\r\n min={min}\r\n max={max}\r\n unit={unit}\r\n step={step}\r\n precision={precision}\r\n converted={converted}\r\n onChange={onComponentChange}\r\n />\r\n </>\r\n }\r\n >\r\n <Body1>{`[${summary}]`}</Body1>\r\n </PropertyLine>\r\n );\r\n};\r\n\r\ntype TensorSlidersProps<ValueT> = Readonly<{\r\n value: ValueT;\r\n adapter: TensorValueAdapter<ValueT>;\r\n min?: number;\r\n max?: number;\r\n unit?: string;\r\n step?: number;\r\n precision?: number;\r\n converted: (value: number) => number;\r\n onChange: (value: number, component: TensorComponent) => void;\r\n}>;\r\n\r\nconst TensorSliders = <ValueT,>(props: TensorSlidersProps<ValueT>) => {\r\n const { value, adapter, min, max, unit, step, precision, converted, onChange } = props;\r\n\r\n return (\r\n <>\r\n {adapter.components.map((component) => (\r\n <NumberInputPropertyLine\r\n key={component}\r\n label={component.toUpperCase()}\r\n value={converted(adapter.getComponent(value, component))}\r\n min={min}\r\n max={max}\r\n onChange={(componentValue) => onChange(componentValue, component)}\r\n unit={unit}\r\n step={step}\r\n precision={precision}\r\n />\r\n ))}\r\n </>\r\n );\r\n};\r\n\r\nexport const RadiansToDegreesConverter = {\r\n from: (value: number) => (value * 180) / Math.PI,\r\n to: (value: number) => (value * Math.PI) / 180,\r\n};\r\n\r\ntype ControlledRotationVectorPropertyLineProps<ValueT> = TensorPropertyLineProps<ValueT> &\r\n Readonly<{\r\n adapter: TensorValueAdapter<ValueT>;\r\n useDegrees?: boolean;\r\n }>;\r\n\r\n/**\r\n * Runtime-neutral controlled Euler rotation editor.\r\n * @param props The rotation value, runtime adapter, and display options.\r\n * @returns The rotation property line.\r\n */\r\nexport const ControlledRotationVectorPropertyLine = <ValueT,>(props: ControlledRotationVectorPropertyLineProps<ValueT>) => {\r\n const { useDegrees, ...rest } = props;\r\n\r\n return (\r\n <ControlledTensorPropertyLine\r\n {...rest}\r\n unit={useDegrees ? \"°\" : \"rad\"}\r\n valueConverter={useDegrees ? RadiansToDegreesConverter : undefined}\r\n step={useDegrees ? 1 : 0.01}\r\n precision={useDegrees ? 1 : 2}\r\n />\r\n );\r\n};\r\n\r\nexport type QuaternionValueAdapter<QuaternionT, EulerT> = Readonly<{\r\n quaternion: TensorValueAdapter<QuaternionT>;\r\n euler: TensorValueAdapter<EulerT>;\r\n fromEuler: (value: EulerT, source: QuaternionT) => QuaternionT;\r\n toEuler: (value: QuaternionT) => EulerT;\r\n}>;\r\n\r\ntype ControlledQuaternionPropertyLineProps<QuaternionT, EulerT> = TensorPropertyLineProps<QuaternionT> &\r\n Readonly<{\r\n adapter: QuaternionValueAdapter<QuaternionT, EulerT>;\r\n useDegrees?: boolean;\r\n useEuler?: boolean;\r\n }>;\r\n\r\n/**\r\n * Runtime-neutral controlled quaternion editor with optional Euler presentation.\r\n * @param props The quaternion value, runtime conversion adapter, and display options.\r\n * @returns The quaternion or Euler property line.\r\n */\r\nexport const ControlledQuaternionPropertyLine = <QuaternionT, EulerT>(props: ControlledQuaternionPropertyLineProps<QuaternionT, EulerT>) => {\r\n const { adapter, useEuler, useDegrees, ...rest } = props;\r\n const [quaternion, setQuaternion] = useState(props.value);\r\n\r\n useEffect(() => {\r\n setQuaternion(props.value);\r\n }, [props.value]);\r\n\r\n const onQuaternionChange = (value: QuaternionT) => {\r\n setQuaternion(value);\r\n props.onChange(value);\r\n };\r\n\r\n if (useEuler) {\r\n const quaternionSummary = adapter.quaternion.components.map((component) => adapter.quaternion.getComponent(quaternion, component).toFixed(4)).join(\", \");\r\n\r\n return (\r\n <ControlledTensorPropertyLine\r\n {...rest}\r\n nullable={false}\r\n ignoreNullable={false}\r\n value={adapter.toEuler(quaternion)}\r\n adapter={adapter.euler}\r\n valueConverter={useDegrees ? RadiansToDegreesConverter : undefined}\r\n onChange={(value) => onQuaternionChange(adapter.fromEuler(value, quaternion))}\r\n unit={useDegrees ? \"°\" : \"rad\"}\r\n step={useDegrees ? 1 : 0.01}\r\n precision={useDegrees ? 1 : 2}\r\n expandedContent={<TextPropertyLine label=\"Quaternion\" value={`[${quaternionSummary}]`} />}\r\n />\r\n );\r\n }\r\n\r\n return (\r\n <ControlledTensorPropertyLine\r\n {...rest}\r\n nullable={false}\r\n value={quaternion}\r\n adapter={adapter.quaternion}\r\n onChange={onQuaternionChange}\r\n unit={useDegrees ? \"°\" : \"rad\"}\r\n step={useDegrees ? 1 : 0.01}\r\n precision={useDegrees ? 1 : 2}\r\n />\r\n );\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"vectorPropertyLineCore.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/vectorPropertyLineCore.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Body1 } from \"@fluentui/react-components\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nimport { type PrimitiveProps } from \"../../primitives/primitive\";\r\nimport { CalculatePrecision } from \"../../primitives/utils\";\r\nimport { NumberInputPropertyLine } from \"./inputPropertyLine\";\r\nimport { type PropertyLineProps, PropertyLine } from \"./propertyLine\";\r\nimport { TextPropertyLine } from \"./textPropertyLine\";\r\n\r\nexport type TensorComponent = \"x\" | \"y\" | \"z\" | \"w\";\r\n\r\nexport type TensorValue2 = Readonly<{ x: number; y: number }>;\r\nexport type TensorValue3 = TensorValue2 & Readonly<{ z: number }>;\r\nexport type TensorValue4 = TensorValue3 & Readonly<{ w: number }>;\r\n\r\nexport type TensorPropertyLineProps<ValueT> = PropertyLineProps<ValueT> &\r\n PrimitiveProps<ValueT> & {\r\n min?: number;\r\n max?: number;\r\n unit?: string;\r\n step?: number;\r\n precision?: number;\r\n valueConverter?: {\r\n from: (value: number) => number;\r\n to: (value: number) => number;\r\n };\r\n };\r\n\r\nexport type TensorValueAdapter<ValueT> = Readonly<{\r\n components: readonly TensorComponent[];\r\n getComponent: (value: ValueT, component: TensorComponent) => number;\r\n withComponent: (value: ValueT, component: TensorComponent, componentValue: number) => ValueT;\r\n}>;\r\n\r\ntype ControlledTensorPropertyLineProps<ValueT> = TensorPropertyLineProps<ValueT> &\r\n Readonly<{\r\n adapter: TensorValueAdapter<ValueT>;\r\n }>;\r\n\r\n/**\r\n * Runtime-neutral controlled editor for two-, three-, and four-component numeric values.\r\n * @param props The value, change callback, component adapter, and property-line presentation.\r\n * @returns The tensor property line.\r\n */\r\nexport const ControlledTensorPropertyLine = <ValueT,>(props: ControlledTensorPropertyLineProps<ValueT>) => {\r\n const { adapter, min, max, unit, step, precision, valueConverter } = props;\r\n const converted = (value: number) => (valueConverter ? valueConverter.from(value) : value);\r\n const formatted = (value: number) => converted(value).toFixed(precision ?? (step !== undefined ? Math.max(0, CalculatePrecision(step)) : 2));\r\n const [value, setValue] = useState(props.value);\r\n\r\n useEffect(() => {\r\n setValue(props.value);\r\n }, [props.value, props.expandedContent]);\r\n\r\n const onComponentChange = (componentValue: number, component: TensorComponent) => {\r\n const storedValue = valueConverter ? valueConverter.to(componentValue) : componentValue;\r\n const newValue = adapter.withComponent(value, component, storedValue);\r\n setValue(newValue);\r\n props.onChange(newValue);\r\n };\r\n\r\n const summary = adapter.components.map((component) => formatted(adapter.getComponent(props.value, component))).join(\", \");\r\n\r\n return (\r\n <PropertyLine\r\n {...props}\r\n expandedContent={\r\n <>\r\n {props.expandedContent}\r\n <TensorSliders\r\n value={value}\r\n adapter={adapter}\r\n min={min}\r\n max={max}\r\n unit={unit}\r\n step={step}\r\n precision={precision}\r\n disabled={props.disabled}\r\n converted={converted}\r\n onChange={onComponentChange}\r\n />\r\n </>\r\n }\r\n >\r\n <Body1>{`[${summary}]`}</Body1>\r\n </PropertyLine>\r\n );\r\n};\r\n\r\ntype TensorSlidersProps<ValueT> = Readonly<{\r\n value: ValueT;\r\n adapter: TensorValueAdapter<ValueT>;\r\n min?: number;\r\n max?: number;\r\n unit?: string;\r\n step?: number;\r\n precision?: number;\r\n disabled?: boolean;\r\n converted: (value: number) => number;\r\n onChange: (value: number, component: TensorComponent) => void;\r\n}>;\r\n\r\nconst TensorSliders = <ValueT,>(props: TensorSlidersProps<ValueT>) => {\r\n const { value, adapter, min, max, unit, step, precision, disabled, converted, onChange } = props;\r\n\r\n return (\r\n <>\r\n {adapter.components.map((component) => (\r\n <NumberInputPropertyLine\r\n key={component}\r\n label={component.toUpperCase()}\r\n value={converted(adapter.getComponent(value, component))}\r\n min={min}\r\n max={max}\r\n onChange={(componentValue) => onChange(componentValue, component)}\r\n unit={unit}\r\n step={step}\r\n precision={precision}\r\n disabled={disabled}\r\n />\r\n ))}\r\n </>\r\n );\r\n};\r\n\r\nexport const RadiansToDegreesConverter = {\r\n from: (value: number) => (value * 180) / Math.PI,\r\n to: (value: number) => (value * Math.PI) / 180,\r\n};\r\n\r\ntype ControlledRotationVectorPropertyLineProps<ValueT> = TensorPropertyLineProps<ValueT> &\r\n Readonly<{\r\n adapter: TensorValueAdapter<ValueT>;\r\n useDegrees?: boolean;\r\n }>;\r\n\r\n/**\r\n * Runtime-neutral controlled Euler rotation editor.\r\n * @param props The rotation value, runtime adapter, and display options.\r\n * @returns The rotation property line.\r\n */\r\nexport const ControlledRotationVectorPropertyLine = <ValueT,>(props: ControlledRotationVectorPropertyLineProps<ValueT>) => {\r\n const { useDegrees, ...rest } = props;\r\n\r\n return (\r\n <ControlledTensorPropertyLine\r\n {...rest}\r\n unit={useDegrees ? \"°\" : \"rad\"}\r\n valueConverter={useDegrees ? RadiansToDegreesConverter : undefined}\r\n step={useDegrees ? 1 : 0.01}\r\n precision={useDegrees ? 1 : 2}\r\n />\r\n );\r\n};\r\n\r\nexport type QuaternionValueAdapter<QuaternionT, EulerT> = Readonly<{\r\n quaternion: TensorValueAdapter<QuaternionT>;\r\n euler: TensorValueAdapter<EulerT>;\r\n fromEuler: (value: EulerT, source: QuaternionT) => QuaternionT;\r\n toEuler: (value: QuaternionT) => EulerT;\r\n}>;\r\n\r\ntype ControlledQuaternionPropertyLineProps<QuaternionT, EulerT> = TensorPropertyLineProps<QuaternionT> &\r\n Readonly<{\r\n adapter: QuaternionValueAdapter<QuaternionT, EulerT>;\r\n useDegrees?: boolean;\r\n useEuler?: boolean;\r\n }>;\r\n\r\n/**\r\n * Runtime-neutral controlled quaternion editor with optional Euler presentation.\r\n * @param props The quaternion value, runtime conversion adapter, and display options.\r\n * @returns The quaternion or Euler property line.\r\n */\r\nexport const ControlledQuaternionPropertyLine = <QuaternionT, EulerT>(props: ControlledQuaternionPropertyLineProps<QuaternionT, EulerT>) => {\r\n const { adapter, useEuler, useDegrees, ...rest } = props;\r\n const [quaternion, setQuaternion] = useState(props.value);\r\n\r\n useEffect(() => {\r\n setQuaternion(props.value);\r\n }, [props.value]);\r\n\r\n const onQuaternionChange = (value: QuaternionT) => {\r\n setQuaternion(value);\r\n props.onChange(value);\r\n };\r\n\r\n if (useEuler) {\r\n const quaternionSummary = adapter.quaternion.components.map((component) => adapter.quaternion.getComponent(quaternion, component).toFixed(4)).join(\", \");\r\n\r\n return (\r\n <ControlledTensorPropertyLine\r\n {...rest}\r\n nullable={false}\r\n ignoreNullable={false}\r\n value={adapter.toEuler(quaternion)}\r\n adapter={adapter.euler}\r\n valueConverter={useDegrees ? RadiansToDegreesConverter : undefined}\r\n onChange={(value) => onQuaternionChange(adapter.fromEuler(value, quaternion))}\r\n unit={useDegrees ? \"°\" : \"rad\"}\r\n step={useDegrees ? 1 : 0.01}\r\n precision={useDegrees ? 1 : 2}\r\n expandedContent={<TextPropertyLine label=\"Quaternion\" value={`[${quaternionSummary}]`} />}\r\n />\r\n );\r\n }\r\n\r\n return (\r\n <ControlledTensorPropertyLine\r\n {...rest}\r\n nullable={false}\r\n value={quaternion}\r\n adapter={adapter.quaternion}\r\n onChange={onQuaternionChange}\r\n unit={useDegrees ? \"°\" : \"rad\"}\r\n step={useDegrees ? 1 : 0.01}\r\n precision={useDegrees ? 1 : 2}\r\n />\r\n );\r\n};\r\n"]}
|
|
@@ -17,6 +17,10 @@ export type ComboBoxProps = PrimitiveProps<string> & {
|
|
|
17
17
|
* Label for the ComboBox
|
|
18
18
|
*/
|
|
19
19
|
label: string;
|
|
20
|
+
/**
|
|
21
|
+
* Accessible name used when the visible label is supplied by a containing property line.
|
|
22
|
+
*/
|
|
23
|
+
ariaLabel?: string;
|
|
20
24
|
/**
|
|
21
25
|
* Options to display as label/value pairs
|
|
22
26
|
*/
|
|
@@ -41,6 +45,10 @@ export declare const ComboBox: import("react").ForwardRefExoticComponent<import(
|
|
|
41
45
|
* Label for the ComboBox
|
|
42
46
|
*/
|
|
43
47
|
label: string;
|
|
48
|
+
/**
|
|
49
|
+
* Accessible name used when the visible label is supplied by a containing property line.
|
|
50
|
+
*/
|
|
51
|
+
ariaLabel?: string;
|
|
44
52
|
/**
|
|
45
53
|
* Options to display as label/value pairs
|
|
46
54
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useContext, useEffect, forwardRef } from "react";
|
|
3
|
-
import { Combobox as FluentComboBox, makeStyles, useComboboxFilter, useId, Option } from "@fluentui/react-components";
|
|
3
|
+
import { Combobox as FluentComboBox, makeStyles, tokens, useComboboxFilter, useId, Option } from "@fluentui/react-components";
|
|
4
4
|
import { ToolContext } from "../hoc/fluentToolWrapper.js";
|
|
5
5
|
import { CustomTokens } from "./utils.js";
|
|
6
6
|
const useStyles = makeStyles({
|
|
@@ -24,6 +24,11 @@ const useStyles = makeStyles({
|
|
|
24
24
|
minWidth: "fit-content",
|
|
25
25
|
maxWidth: "350px",
|
|
26
26
|
},
|
|
27
|
+
compactOption: {
|
|
28
|
+
fontSize: tokens.fontSizeBase200,
|
|
29
|
+
lineHeight: tokens.lineHeightBase200,
|
|
30
|
+
padding: `${tokens.spacingVerticalXXS} ${tokens.spacingHorizontalS}`,
|
|
31
|
+
},
|
|
27
32
|
});
|
|
28
33
|
/**
|
|
29
34
|
* Wrapper around a Fluent ComboBox that allows for filtering options.
|
|
@@ -47,12 +52,12 @@ export const ComboBox = forwardRef((props, ref) => {
|
|
|
47
52
|
noOptionsMessage: "No items match your search.",
|
|
48
53
|
optionToReactKey: (option) => option.value,
|
|
49
54
|
optionToText: (option) => option.children,
|
|
50
|
-
renderOption: (option) => (_jsx(Option, { value: option.value, text: option.children, children: option.children }, option.value)),
|
|
55
|
+
renderOption: (option) => (_jsx(Option, { value: option.value, text: option.children, className: size === "small" ? styles.compactOption : undefined, children: option.children }, option.value)),
|
|
51
56
|
});
|
|
52
57
|
const onOptionSelect = (_e, data) => {
|
|
53
58
|
setQuery(data.optionText ?? "");
|
|
54
59
|
data.optionValue && props.onChange(data.optionValue);
|
|
55
60
|
};
|
|
56
|
-
return (_jsxs("div", { className: styles.root, children: [_jsx("label", { id: comboId, children: props.label }), _jsx(FluentComboBox, { ref: ref, defaultOpen: props.defaultOpen, size: size, root: { className: styles.comboBox }, input: { className: styles.input }, listbox: { className: styles.listbox }, onOptionSelect: onOptionSelect, "aria-labelledby": comboId, placeholder: "Search..", onChange: (ev) => setQuery(ev.target.value), value: query, children: children })] }));
|
|
61
|
+
return (_jsxs("div", { className: styles.root, children: [_jsx("label", { id: comboId, children: props.label }), _jsx(FluentComboBox, { ref: ref, defaultOpen: props.defaultOpen, disabled: props.disabled, size: size, root: { className: styles.comboBox }, input: { className: styles.input }, listbox: { className: styles.listbox }, onOptionSelect: onOptionSelect, "aria-label": props.ariaLabel, "aria-labelledby": props.ariaLabel ? undefined : comboId, placeholder: "Search..", onChange: (ev) => setQuery(ev.target.value), value: query, children: children })] }));
|
|
57
62
|
});
|
|
58
63
|
//# sourceMappingURL=comboBox.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comboBox.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/comboBox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAiD,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"comboBox.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/comboBox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAiD,MAAM,4BAA4B,CAAC;AAC7K,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,IAAI,EAAE;QACF,OAAO,EAAE,MAAM;QACf,gBAAgB,EAAE,aAAa;QAC/B,YAAY,EAAE,OAAO;QACrB,GAAG,EAAE,KAAK;QACV,QAAQ,EAAE,OAAO;KACpB;IACD,QAAQ,EAAE;QACN,KAAK,EAAE,YAAY,CAAC,UAAU;QAC9B,QAAQ,EAAE,YAAY,CAAC,UAAU;QACjC,SAAS,EAAE,YAAY;KAC1B;IACD,KAAK,EAAE;QACH,QAAQ,EAAE,CAAC;KACd;IACD,OAAO,EAAE;QACL,KAAK,EAAE,aAAa;QACpB,QAAQ,EAAE,aAAa;QACvB,QAAQ,EAAE,OAAO;KACpB;IACD,aAAa,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC,eAAe;QAChC,UAAU,EAAE,MAAM,CAAC,iBAAiB;QACpC,OAAO,EAAE,GAAG,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,kBAAkB,EAAE;KACvE;CACJ,CAAC,CAAC;AAmCH;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAkC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC/E,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC;IAClC,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAEzC,uCAAuC;IACvC,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IAElG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IAEhE,SAAS,CAAC,GAAG,EAAE;QACX,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjC,iDAAiD;IACjD,MAAM,iBAAiB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAElG,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,EAAE;QACzD,gBAAgB,EAAE,6BAA6B;QAC/C,gBAAgB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK;QAC1C,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ;QACzC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CACtB,KAAC,MAAM,IAAoB,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,YAChI,MAAM,CAAC,QAAQ,IADP,MAAM,CAAC,KAAK,CAEhB,CACZ;KACJ,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,CAAC,EAAmB,EAAE,IAAwB,EAAE,EAAE;QACrE,QAAQ,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC,CAAC;IAEF,OAAO,CACH,eAAK,SAAS,EAAE,MAAM,CAAC,IAAI,aACvB,gBAAO,EAAE,EAAE,OAAO,YAAG,KAAK,CAAC,KAAK,GAAS,EACzC,KAAC,cAAc,IACX,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,EACpC,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,EAClC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,EACtC,cAAc,EAAE,cAAc,gBAClB,KAAK,CAAC,SAAS,qBACV,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EACtD,WAAW,EAAC,UAAU,EACtB,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAC3C,KAAK,EAAE,KAAK,YAEX,QAAQ,GACI,IACf,CACT,CAAC;AACN,CAAC,CAAC,CAAC","sourcesContent":["import { useState, useContext, useEffect, forwardRef } from \"react\";\r\nimport { Combobox as FluentComboBox, makeStyles, tokens, useComboboxFilter, useId, Option, type OptionOnSelectData, type SelectionEvents } from \"@fluentui/react-components\";\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\nimport { CustomTokens } from \"./utils\";\r\nimport { type PrimitiveProps } from \"./primitive\";\r\n\r\nconst useStyles = makeStyles({\r\n root: {\r\n display: \"grid\",\r\n gridTemplateRows: \"repeat(1fr)\",\r\n justifyItems: \"start\",\r\n gap: \"2px\",\r\n maxWidth: \"400px\",\r\n },\r\n comboBox: {\r\n width: CustomTokens.valueWidth,\r\n minWidth: CustomTokens.valueWidth,\r\n boxSizing: \"border-box\",\r\n },\r\n input: {\r\n minWidth: 0,\r\n },\r\n listbox: {\r\n width: \"fit-content\",\r\n minWidth: \"fit-content\",\r\n maxWidth: \"350px\",\r\n },\r\n compactOption: {\r\n fontSize: tokens.fontSizeBase200,\r\n lineHeight: tokens.lineHeightBase200,\r\n padding: `${tokens.spacingVerticalXXS} ${tokens.spacingHorizontalS}`,\r\n },\r\n});\r\n\r\n/**\r\n * An option object for the ComboBox with separate label and value.\r\n */\r\nexport type ComboBoxOption = {\r\n /**\r\n * Defines the visible part of the option\r\n */\r\n label: string;\r\n /**\r\n * Defines the value part of the option\r\n */\r\n value: string;\r\n};\r\n\r\nexport type ComboBoxProps = PrimitiveProps<string> & {\r\n /**\r\n * Label for the ComboBox\r\n */\r\n label: string;\r\n /**\r\n * Accessible name used when the visible label is supplied by a containing property line.\r\n */\r\n ariaLabel?: string;\r\n /**\r\n * Options to display as label/value pairs\r\n */\r\n options: ComboBoxOption[];\r\n /**\r\n * The default open state when open is uncontrolled\r\n */\r\n defaultOpen?: boolean;\r\n};\r\n\r\n/**\r\n * Wrapper around a Fluent ComboBox that allows for filtering options.\r\n * @param props\r\n * @returns\r\n */\r\nexport const ComboBox = forwardRef<HTMLInputElement, ComboBoxProps>((props, ref) => {\r\n ComboBox.displayName = \"ComboBox\";\r\n const comboId = useId();\r\n const styles = useStyles();\r\n const { size } = useContext(ToolContext);\r\n\r\n // Find the label for the current value\r\n const getLabel = (value: string) => props.options.find((opt) => opt.value === value)?.label ?? \"\";\r\n\r\n const [query, setQuery] = useState(getLabel(props.value ?? \"\"));\r\n\r\n useEffect(() => {\r\n setQuery(getLabel(props.value ?? \"\"));\r\n }, [props.value, props.options]);\r\n\r\n // Convert to Fluent's { children, value } format\r\n const normalizedOptions = props.options.map((opt) => ({ children: opt.label, value: opt.value }));\r\n\r\n const children = useComboboxFilter(query, normalizedOptions, {\r\n noOptionsMessage: \"No items match your search.\",\r\n optionToReactKey: (option) => option.value,\r\n optionToText: (option) => option.children,\r\n renderOption: (option) => (\r\n <Option key={option.value} value={option.value} text={option.children} className={size === \"small\" ? styles.compactOption : undefined}>\r\n {option.children}\r\n </Option>\r\n ),\r\n });\r\n\r\n const onOptionSelect = (_e: SelectionEvents, data: OptionOnSelectData) => {\r\n setQuery(data.optionText ?? \"\");\r\n data.optionValue && props.onChange(data.optionValue);\r\n };\r\n\r\n return (\r\n <div className={styles.root}>\r\n <label id={comboId}>{props.label}</label>\r\n <FluentComboBox\r\n ref={ref}\r\n defaultOpen={props.defaultOpen}\r\n disabled={props.disabled}\r\n size={size}\r\n root={{ className: styles.comboBox }}\r\n input={{ className: styles.input }}\r\n listbox={{ className: styles.listbox }}\r\n onOptionSelect={onOptionSelect}\r\n aria-label={props.ariaLabel}\r\n aria-labelledby={props.ariaLabel ? undefined : comboId}\r\n placeholder=\"Search..\"\r\n onChange={(ev) => setQuery(ev.target.value)}\r\n value={query}\r\n >\r\n {children}\r\n </FluentComboBox>\r\n </div>\r\n );\r\n});\r\n"]}
|
|
@@ -1,27 +1,7 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { Button } from "./button.js";
|
|
6
|
-
import { ComboBox } from "./comboBox.js";
|
|
7
|
-
import { Link } from "./link.js";
|
|
8
|
-
import { useImpulse } from "../hooks/transientStateHooks.js";
|
|
9
|
-
const useStyles = makeStyles({
|
|
10
|
-
linkDiv: {
|
|
11
|
-
display: "flex",
|
|
12
|
-
flexDirection: "row",
|
|
13
|
-
alignItems: "center",
|
|
14
|
-
gap: tokens.spacingHorizontalS,
|
|
15
|
-
minWidth: 0,
|
|
16
|
-
overflow: "hidden",
|
|
17
|
-
},
|
|
18
|
-
link: {
|
|
19
|
-
minWidth: 0,
|
|
20
|
-
overflow: "hidden",
|
|
21
|
-
textOverflow: "ellipsis",
|
|
22
|
-
whiteSpace: "nowrap",
|
|
23
|
-
},
|
|
24
|
-
});
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { ResourceSelector } from "./resourceSelector.js";
|
|
4
|
+
const GetEntityId = (entity) => entity.uniqueId.toString();
|
|
25
5
|
/**
|
|
26
6
|
* A generic primitive component with a ComboBox for selecting from a list of entities.
|
|
27
7
|
* Supports entities with duplicate names by using uniqueId for identity.
|
|
@@ -29,49 +9,10 @@ const useStyles = makeStyles({
|
|
|
29
9
|
* @returns EntitySelector component
|
|
30
10
|
*/
|
|
31
11
|
export function EntitySelector(props) {
|
|
32
|
-
const { value, onLink, getEntities, getName, filter, defaultValue } = props;
|
|
12
|
+
const { value, onLink, getEntities, getName, filter, defaultValue, disabled } = props;
|
|
33
13
|
const onChange = props.onChange;
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
// Build options with uniqueId as key
|
|
37
|
-
const options = useMemo(() => {
|
|
38
|
-
return getEntities()
|
|
39
|
-
.filter((e) => e.uniqueId !== undefined && (!filter || filter(e)))
|
|
40
|
-
.map((entity) => ({
|
|
41
|
-
label: getName(entity)?.toString() || "",
|
|
42
|
-
value: entity.uniqueId.toString(),
|
|
43
|
-
}))
|
|
44
|
-
.sort((a, b) => a.label.localeCompare(b.label));
|
|
45
|
-
}, [getEntities, getName, filter]);
|
|
46
|
-
const [isEditing, setIsEditing] = useState(false);
|
|
47
|
-
const [enteringEditMode, pulseEnteringEditMode] = useImpulse();
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
if (enteringEditMode) {
|
|
50
|
-
comboBoxRef.current?.focus();
|
|
51
|
-
}
|
|
52
|
-
}, [enteringEditMode]);
|
|
53
|
-
const handleEntitySelect = (key) => {
|
|
54
|
-
const entity = getEntities().find((e) => e.uniqueId.toString() === key);
|
|
55
|
-
onChange?.(entity ?? null);
|
|
56
|
-
setIsEditing(false);
|
|
57
|
-
};
|
|
58
|
-
// Get current entity key for display
|
|
59
|
-
const currentKey = value ? value.uniqueId.toString() : "";
|
|
60
|
-
if (value && !isEditing) {
|
|
61
|
-
// If there is a value and we are not editing, show the link view
|
|
62
|
-
return (_jsxs("div", { className: classes.linkDiv, children: [_jsx(Tooltip, { content: getName(value), relationship: "label", children: _jsx(Link, { className: classes.link, value: getName(value), onLink: () => onLink(value) }) }), onChange &&
|
|
63
|
-
(defaultValue !== undefined ? (_jsx(Tooltip, { content: "Unlink", relationship: "label", children: _jsx(Button, { icon: LinkDismissRegular, onClick: () => {
|
|
64
|
-
pulseEnteringEditMode(true);
|
|
65
|
-
onChange(defaultValue);
|
|
66
|
-
} }) })) : (_jsx(Tooltip, { content: "Edit Link", relationship: "label", children: _jsx(Button, { icon: LinkEditRegular, onClick: () => {
|
|
67
|
-
pulseEnteringEditMode(true);
|
|
68
|
-
setIsEditing(true);
|
|
69
|
-
} }) })))] }));
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
// Otherwise, show the ComboBox for selection
|
|
73
|
-
return _jsx(ComboBox, { ref: comboBoxRef, defaultOpen: enteringEditMode, label: "", options: options, value: currentKey, onChange: handleEntitySelect });
|
|
74
|
-
}
|
|
14
|
+
const filterEntity = useCallback((entity) => entity.uniqueId !== undefined && (!filter || filter(entity)), [filter]);
|
|
15
|
+
return (_jsx(ResourceSelector, { value: value, getEntities: getEntities, getName: getName, getId: GetEntityId, filter: filterEntity, onSelect: onChange, onClear: onChange && defaultValue !== undefined ? () => onChange(defaultValue) : undefined, onLink: onLink, disabled: disabled, showEmptySelector: true }));
|
|
75
16
|
}
|
|
76
17
|
EntitySelector.displayName = "EntitySelector";
|
|
77
18
|
//# sourceMappingURL=entitySelector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entitySelector.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/entitySelector.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"entitySelector.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/entitySelector.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;AA4BnE;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAmB,KAA6B;IAC1E,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACtF,MAAM,QAAQ,GAAI,KAAqC,CAAC,QAA+D,CAAC;IACxH,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,MAAS,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACxH,OAAO,CACH,KAAC,gBAAgB,IACb,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,QAAQ,IAAI,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,EAC1F,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,iBAAiB,SACnB,CACL,CAAC;AACN,CAAC;AACD,cAAc,CAAC,WAAW,GAAG,gBAAgB,CAAC","sourcesContent":["import { type Nullable } from \"core/types\";\r\nimport { useCallback } from \"react\";\r\nimport { type ImmutablePrimitiveProps, type PrimitiveProps } from \"./primitive\";\r\nimport { ResourceSelector } from \"./resourceSelector\";\r\n\r\ntype Entity = { uniqueId: number };\r\nconst GetEntityId = (entity: Entity) => entity.uniqueId.toString();\r\n\r\n/**\r\n * Props for the EntitySelector component\r\n */\r\nexport type EntitySelectorProps<T extends Entity> = (PrimitiveProps<Nullable<T>> | ImmutablePrimitiveProps<Nullable<T>>) & {\r\n /**\r\n * Function to get the list of entities to choose from\r\n */\r\n getEntities: () => T[];\r\n /**\r\n * Function to get the display name from an entity\r\n */\r\n getName: (entity: T) => string;\r\n /**\r\n * Optional filter function to filter which entities are shown\r\n */\r\n filter?: (entity: T) => boolean;\r\n /**\r\n * Callback when the entity link is clicked\r\n */\r\n onLink: (entity: T) => void;\r\n /**\r\n * Optional default value that enables clearing the current linked entity\r\n */\r\n defaultValue?: Nullable<T>;\r\n};\r\n\r\n/**\r\n * A generic primitive component with a ComboBox for selecting from a list of entities.\r\n * Supports entities with duplicate names by using uniqueId for identity.\r\n * @param props ChooseEntityProps\r\n * @returns EntitySelector component\r\n */\r\nexport function EntitySelector<T extends Entity>(props: EntitySelectorProps<T>): JSX.Element {\r\n const { value, onLink, getEntities, getName, filter, defaultValue, disabled } = props;\r\n const onChange = (props as PrimitiveProps<Nullable<T>>).onChange as PrimitiveProps<Nullable<T>>[\"onChange\"] | undefined;\r\n const filterEntity = useCallback((entity: T) => entity.uniqueId !== undefined && (!filter || filter(entity)), [filter]);\r\n return (\r\n <ResourceSelector\r\n value={value}\r\n getEntities={getEntities}\r\n getName={getName}\r\n getId={GetEntityId}\r\n filter={filterEntity}\r\n onSelect={onChange}\r\n onClear={onChange && defaultValue !== undefined ? () => onChange(defaultValue) : undefined}\r\n onLink={onLink}\r\n disabled={disabled}\r\n showEmptySelector\r\n />\r\n );\r\n}\r\nEntitySelector.displayName = \"EntitySelector\";\r\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral selection and navigation for an optionally linked resource.
|
|
3
|
+
* The caller supplies stable IDs and only the mutation callbacks its runtime supports.
|
|
4
|
+
*/
|
|
5
|
+
export type ResourceSelectorProps<T> = {
|
|
6
|
+
/** Currently linked resource, or null when unlinked. */
|
|
7
|
+
value: T | null;
|
|
8
|
+
/** Returns candidate resources for selection. */
|
|
9
|
+
getEntities: () => readonly T[];
|
|
10
|
+
/** Returns the resource's display name. */
|
|
11
|
+
getName: (entity: T) => string;
|
|
12
|
+
/** Returns a stable identity for each candidate, including duplicate display names. */
|
|
13
|
+
getId: (entity: T) => string;
|
|
14
|
+
/** Restricts the selectable candidates. */
|
|
15
|
+
filter?: (entity: T) => boolean;
|
|
16
|
+
/** Assigns a selected resource; receives null if an option became stale. */
|
|
17
|
+
onSelect?: (entity: T | null) => void;
|
|
18
|
+
/** Clears the current link, when supported. Takes precedence over the edit action. */
|
|
19
|
+
onClear?: () => void;
|
|
20
|
+
/** Navigates to the linked resource, when supported. */
|
|
21
|
+
onLink?: (entity: T) => void;
|
|
22
|
+
/** Disables link mutations and selection while an operation is pending. */
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/** Accessible name when the visible label is supplied by a containing property line. */
|
|
25
|
+
ariaLabel?: string;
|
|
26
|
+
/** Keeps the Babylon entity selector visible even when its immutable value is empty. */
|
|
27
|
+
showEmptySelector?: boolean;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Displays a linked resource with one unlink-or-edit action, or a selector when unlinked.
|
|
31
|
+
* @param props Resource identity, selection, navigation, and supported actions.
|
|
32
|
+
* @returns The linked value or its replacement selector.
|
|
33
|
+
*/
|
|
34
|
+
export declare function ResourceSelector<T>(props: ResourceSelectorProps<T>): JSX.Element;
|
|
35
|
+
export declare namespace ResourceSelector {
|
|
36
|
+
var displayName: string;
|
|
37
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { makeStyles, tokens, Tooltip } from "@fluentui/react-components";
|
|
3
|
+
import { LinkDismissRegular, LinkEditRegular } from "@fluentui/react-icons";
|
|
4
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { useImpulse } from "../hooks/transientStateHooks.js";
|
|
6
|
+
import { Button } from "./button.js";
|
|
7
|
+
import { ComboBox } from "./comboBox.js";
|
|
8
|
+
import { Link } from "./link.js";
|
|
9
|
+
const useStyles = makeStyles({
|
|
10
|
+
linkDiv: {
|
|
11
|
+
display: "flex",
|
|
12
|
+
flexDirection: "row",
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
gap: tokens.spacingHorizontalS,
|
|
15
|
+
minWidth: 0,
|
|
16
|
+
overflow: "hidden",
|
|
17
|
+
},
|
|
18
|
+
link: {
|
|
19
|
+
minWidth: 0,
|
|
20
|
+
overflow: "hidden",
|
|
21
|
+
textOverflow: "ellipsis",
|
|
22
|
+
whiteSpace: "nowrap",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Displays a linked resource with one unlink-or-edit action, or a selector when unlinked.
|
|
27
|
+
* @param props Resource identity, selection, navigation, and supported actions.
|
|
28
|
+
* @returns The linked value or its replacement selector.
|
|
29
|
+
*/
|
|
30
|
+
export function ResourceSelector(props) {
|
|
31
|
+
const { value, getEntities, getName, getId, filter, onSelect, onClear, onLink, disabled, ariaLabel, showEmptySelector } = props;
|
|
32
|
+
const classes = useStyles();
|
|
33
|
+
const comboBoxRef = useRef(null);
|
|
34
|
+
const options = useMemo(() => getEntities()
|
|
35
|
+
.filter((entity) => !filter || filter(entity))
|
|
36
|
+
.map((entity) => ({ label: getName(entity)?.toString() || "", value: getId(entity) }))
|
|
37
|
+
.sort((a, b) => a.label.localeCompare(b.label)), [getEntities, getName, getId, filter]);
|
|
38
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
39
|
+
const [enteringEditMode, pulseEnteringEditMode] = useImpulse();
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (enteringEditMode) {
|
|
42
|
+
comboBoxRef.current?.focus();
|
|
43
|
+
}
|
|
44
|
+
}, [enteringEditMode]);
|
|
45
|
+
if (value !== null && !isEditing) {
|
|
46
|
+
return (_jsxs("div", { className: classes.linkDiv, children: [_jsx(Tooltip, { content: getName(value), relationship: "label", children: _jsx(Link, { className: classes.link, value: getName(value), onLink: onLink ? () => onLink(value) : undefined, "aria-label": onLink && ariaLabel ? `${ariaLabel}: open ${getName(value)}` : undefined }) }), onClear ? (_jsx(Tooltip, { content: "Unlink", relationship: "label", children: _jsx(Button, { icon: LinkDismissRegular, ariaLabel: ariaLabel ? `Clear ${ariaLabel}` : "Unlink", disabled: disabled, onClick: () => {
|
|
47
|
+
pulseEnteringEditMode(true);
|
|
48
|
+
onClear();
|
|
49
|
+
} }) })) : onSelect ? (_jsx(Tooltip, { content: "Edit Link", relationship: "label", children: _jsx(Button, { icon: LinkEditRegular, ariaLabel: ariaLabel ? `Change ${ariaLabel}` : "Edit Link", disabled: disabled, onClick: () => {
|
|
50
|
+
pulseEnteringEditMode(true);
|
|
51
|
+
setIsEditing(true);
|
|
52
|
+
} }) })) : undefined] }));
|
|
53
|
+
}
|
|
54
|
+
if (!onSelect && !showEmptySelector) {
|
|
55
|
+
return _jsx(Link, { value: "None" });
|
|
56
|
+
}
|
|
57
|
+
return (_jsx(ComboBox, { ref: comboBoxRef, defaultOpen: enteringEditMode, label: "", ariaLabel: ariaLabel, disabled: disabled, options: options, value: value !== null ? getId(value) : "", onChange: (id) => {
|
|
58
|
+
onSelect?.(getEntities().find((entity) => getId(entity) === id) ?? null);
|
|
59
|
+
setIsEditing(false);
|
|
60
|
+
} }));
|
|
61
|
+
}
|
|
62
|
+
ResourceSelector.displayName = "ResourceSelector";
|
|
63
|
+
//# sourceMappingURL=resourceSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceSelector.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/resourceSelector.tsx"],"names":[],"mappings":"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","sourcesContent":["import { makeStyles, tokens, Tooltip } from \"@fluentui/react-components\";\nimport { LinkDismissRegular, LinkEditRegular } from \"@fluentui/react-icons\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { useImpulse } from \"../hooks/transientStateHooks\";\nimport { Button } from \"./button\";\nimport { ComboBox } from \"./comboBox\";\nimport { Link } from \"./link\";\n\n/**\n * Runtime-neutral selection and navigation for an optionally linked resource.\n * The caller supplies stable IDs and only the mutation callbacks its runtime supports.\n */\nexport type ResourceSelectorProps<T> = {\n /** Currently linked resource, or null when unlinked. */\n value: T | null;\n /** Returns candidate resources for selection. */\n getEntities: () => readonly T[];\n /** Returns the resource's display name. */\n getName: (entity: T) => string;\n /** Returns a stable identity for each candidate, including duplicate display names. */\n getId: (entity: T) => string;\n /** Restricts the selectable candidates. */\n filter?: (entity: T) => boolean;\n /** Assigns a selected resource; receives null if an option became stale. */\n onSelect?: (entity: T | null) => void;\n /** Clears the current link, when supported. Takes precedence over the edit action. */\n onClear?: () => void;\n /** Navigates to the linked resource, when supported. */\n onLink?: (entity: T) => void;\n /** Disables link mutations and selection while an operation is pending. */\n disabled?: boolean;\n /** Accessible name when the visible label is supplied by a containing property line. */\n ariaLabel?: string;\n /** Keeps the Babylon entity selector visible even when its immutable value is empty. */\n showEmptySelector?: boolean;\n};\n\nconst useStyles = makeStyles({\n linkDiv: {\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: tokens.spacingHorizontalS,\n minWidth: 0,\n overflow: \"hidden\",\n },\n link: {\n minWidth: 0,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n});\n\n/**\n * Displays a linked resource with one unlink-or-edit action, or a selector when unlinked.\n * @param props Resource identity, selection, navigation, and supported actions.\n * @returns The linked value or its replacement selector.\n */\nexport function ResourceSelector<T>(props: ResourceSelectorProps<T>): JSX.Element {\n const { value, getEntities, getName, getId, filter, onSelect, onClear, onLink, disabled, ariaLabel, showEmptySelector } = props;\n const classes = useStyles();\n const comboBoxRef = useRef<HTMLInputElement>(null);\n const options = useMemo(\n () =>\n getEntities()\n .filter((entity) => !filter || filter(entity))\n .map((entity) => ({ label: getName(entity)?.toString() || \"\", value: getId(entity) }))\n .sort((a, b) => a.label.localeCompare(b.label)),\n [getEntities, getName, getId, filter]\n );\n const [isEditing, setIsEditing] = useState(false);\n const [enteringEditMode, pulseEnteringEditMode] = useImpulse<true>();\n\n useEffect(() => {\n if (enteringEditMode) {\n comboBoxRef.current?.focus();\n }\n }, [enteringEditMode]);\n\n if (value !== null && !isEditing) {\n return (\n <div className={classes.linkDiv}>\n <Tooltip content={getName(value)} relationship=\"label\">\n <Link\n className={classes.link}\n value={getName(value)}\n onLink={onLink ? () => onLink(value) : undefined}\n aria-label={onLink && ariaLabel ? `${ariaLabel}: open ${getName(value)}` : undefined}\n />\n </Tooltip>\n {onClear ? (\n <Tooltip content=\"Unlink\" relationship=\"label\">\n <Button\n icon={LinkDismissRegular}\n ariaLabel={ariaLabel ? `Clear ${ariaLabel}` : \"Unlink\"}\n disabled={disabled}\n onClick={() => {\n pulseEnteringEditMode(true);\n onClear();\n }}\n />\n </Tooltip>\n ) : onSelect ? (\n <Tooltip content=\"Edit Link\" relationship=\"label\">\n <Button\n icon={LinkEditRegular}\n ariaLabel={ariaLabel ? `Change ${ariaLabel}` : \"Edit Link\"}\n disabled={disabled}\n onClick={() => {\n pulseEnteringEditMode(true);\n setIsEditing(true);\n }}\n />\n </Tooltip>\n ) : undefined}\n </div>\n );\n }\n\n if (!onSelect && !showEmptySelector) {\n return <Link value=\"None\" />;\n }\n\n return (\n <ComboBox\n ref={comboBoxRef}\n defaultOpen={enteringEditMode}\n label=\"\"\n ariaLabel={ariaLabel}\n disabled={disabled}\n options={options}\n value={value !== null ? getId(value) : \"\"}\n onChange={(id) => {\n onSelect?.(getEntities().find((entity) => getId(entity) === id) ?? null);\n setIsEditing(false);\n }}\n />\n );\n}\nResourceSelector.displayName = \"ResourceSelector\";\n"]}
|
|
@@ -3,18 +3,21 @@ import { type ButtonProps } from "./button.js";
|
|
|
3
3
|
import { type FunctionComponent } from "react";
|
|
4
4
|
import { type FluentIcon } from "@fluentui/react-icons";
|
|
5
5
|
type ToggleButtonProps = Omit<ButtonProps, "icon" | "onClick"> & {
|
|
6
|
+
/** The checked state supplied by the parent. */
|
|
6
7
|
value: boolean;
|
|
7
8
|
checkedIcon: FluentIcon;
|
|
8
9
|
uncheckedIcon?: FluentIcon;
|
|
10
|
+
/** Requests a new checked state. The parent must update value to accept the change. */
|
|
9
11
|
onChange: (checked: boolean) => void;
|
|
10
12
|
titlePositioning?: TooltipProps["positioning"];
|
|
11
13
|
};
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
+
* Displays a controlled toggle button with icons.
|
|
16
|
+
* The parent supplies the checked state through value; clicks request the opposite value through onChange.
|
|
17
|
+
* If no uncheckedIcon is provided, the same icon is used for both states.
|
|
15
18
|
*
|
|
16
|
-
* @param props
|
|
17
|
-
* @returns
|
|
19
|
+
* @param props The controlled state, change callback, icons, and button presentation.
|
|
20
|
+
* @returns The toggle button.
|
|
18
21
|
*/
|
|
19
22
|
export declare const ToggleButton: FunctionComponent<ToggleButtonProps>;
|
|
20
23
|
export {};
|