fluentui-extended 2026.8.31 → 2026.8.35
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/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +97 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +97 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -140,6 +140,8 @@ interface QueryBuilderCondition {
|
|
|
140
140
|
nestedLogic?: 'and' | 'or';
|
|
141
141
|
/** Fields available for the related entity (loaded dynamically) */
|
|
142
142
|
nestedFields?: QueryBuilderField[];
|
|
143
|
+
/** True when the attribute from parsed FetchXML didn't match any known field */
|
|
144
|
+
isUnknownField?: boolean;
|
|
143
145
|
}
|
|
144
146
|
interface QueryBuilderGroup {
|
|
145
147
|
id: string;
|
|
@@ -216,6 +218,8 @@ interface QueryBuilderProps {
|
|
|
216
218
|
onFetchEntityFields?: (entityLogicalName: string) => Promise<QueryBuilderField[]>;
|
|
217
219
|
/** Debug/trace callback for logging component behavior */
|
|
218
220
|
onTrace?: (message: string, data?: any) => void;
|
|
221
|
+
/** Enable verbose console.debug tracing (disabled by default) */
|
|
222
|
+
debug?: boolean;
|
|
219
223
|
}
|
|
220
224
|
|
|
221
225
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -140,6 +140,8 @@ interface QueryBuilderCondition {
|
|
|
140
140
|
nestedLogic?: 'and' | 'or';
|
|
141
141
|
/** Fields available for the related entity (loaded dynamically) */
|
|
142
142
|
nestedFields?: QueryBuilderField[];
|
|
143
|
+
/** True when the attribute from parsed FetchXML didn't match any known field */
|
|
144
|
+
isUnknownField?: boolean;
|
|
143
145
|
}
|
|
144
146
|
interface QueryBuilderGroup {
|
|
145
147
|
id: string;
|
|
@@ -216,6 +218,8 @@ interface QueryBuilderProps {
|
|
|
216
218
|
onFetchEntityFields?: (entityLogicalName: string) => Promise<QueryBuilderField[]>;
|
|
217
219
|
/** Debug/trace callback for logging component behavior */
|
|
218
220
|
onTrace?: (message: string, data?: any) => void;
|
|
221
|
+
/** Enable verbose console.debug tracing (disabled by default) */
|
|
222
|
+
debug?: boolean;
|
|
219
223
|
}
|
|
220
224
|
|
|
221
225
|
/**
|
package/dist/index.js
CHANGED
|
@@ -971,6 +971,72 @@ var useQueryBuilderStyles = reactComponents.makeStyles({
|
|
|
971
971
|
backgroundColor: reactComponents.tokens.colorPaletteRedBackground1,
|
|
972
972
|
borderRadius: reactComponents.tokens.borderRadiusSmall
|
|
973
973
|
},
|
|
974
|
+
conditionUnknownBanner: {
|
|
975
|
+
display: "flex",
|
|
976
|
+
alignItems: "center",
|
|
977
|
+
gap: reactComponents.tokens.spacingHorizontalXS,
|
|
978
|
+
paddingTop: "2px",
|
|
979
|
+
paddingBottom: "2px",
|
|
980
|
+
paddingLeft: reactComponents.tokens.spacingHorizontalXS,
|
|
981
|
+
paddingRight: reactComponents.tokens.spacingHorizontalXS,
|
|
982
|
+
marginBottom: reactComponents.tokens.spacingVerticalXS,
|
|
983
|
+
backgroundColor: reactComponents.tokens.colorStatusWarningBackground1,
|
|
984
|
+
borderRadius: reactComponents.tokens.borderRadiusSmall,
|
|
985
|
+
fontSize: reactComponents.tokens.fontSizeBase100,
|
|
986
|
+
color: reactComponents.tokens.colorStatusWarningForeground3
|
|
987
|
+
},
|
|
988
|
+
conditionUnknownText: {
|
|
989
|
+
flex: "1 1 auto"
|
|
990
|
+
},
|
|
991
|
+
conditionUnknownButton: {
|
|
992
|
+
fontSize: reactComponents.tokens.fontSizeBase100,
|
|
993
|
+
minWidth: "0",
|
|
994
|
+
paddingTop: "0",
|
|
995
|
+
paddingBottom: "0",
|
|
996
|
+
paddingLeft: reactComponents.tokens.spacingHorizontalXS,
|
|
997
|
+
paddingRight: reactComponents.tokens.spacingHorizontalXS,
|
|
998
|
+
height: "20px",
|
|
999
|
+
color: reactComponents.tokens.colorStatusWarningForeground3
|
|
1000
|
+
},
|
|
1001
|
+
dialogSurfaceNarrow: {
|
|
1002
|
+
maxWidth: "600px"
|
|
1003
|
+
},
|
|
1004
|
+
dialogSurfaceCompact: {
|
|
1005
|
+
maxWidth: "500px"
|
|
1006
|
+
},
|
|
1007
|
+
dialogUploadContent: {
|
|
1008
|
+
display: "flex",
|
|
1009
|
+
flexDirection: "column",
|
|
1010
|
+
gap: reactComponents.tokens.spacingVerticalM
|
|
1011
|
+
},
|
|
1012
|
+
dialogValidationContent: {
|
|
1013
|
+
display: "flex",
|
|
1014
|
+
flexDirection: "column",
|
|
1015
|
+
gap: reactComponents.tokens.spacingVerticalL
|
|
1016
|
+
},
|
|
1017
|
+
monacoTextarea: {
|
|
1018
|
+
minHeight: "200px",
|
|
1019
|
+
fontFamily: reactComponents.tokens.fontFamilyMonospace
|
|
1020
|
+
},
|
|
1021
|
+
uploadErrorText: {
|
|
1022
|
+
color: reactComponents.tokens.colorStatusDangerForeground1
|
|
1023
|
+
},
|
|
1024
|
+
validationSectionTitle: {
|
|
1025
|
+
display: "flex",
|
|
1026
|
+
alignItems: "center",
|
|
1027
|
+
gap: reactComponents.tokens.spacingHorizontalXXS
|
|
1028
|
+
},
|
|
1029
|
+
validationApiRow: {
|
|
1030
|
+
display: "flex",
|
|
1031
|
+
alignItems: "center",
|
|
1032
|
+
gap: reactComponents.tokens.spacingHorizontalS
|
|
1033
|
+
},
|
|
1034
|
+
emptyRelatedEntity: {
|
|
1035
|
+
paddingTop: reactComponents.tokens.spacingVerticalS,
|
|
1036
|
+
paddingBottom: reactComponents.tokens.spacingVerticalS,
|
|
1037
|
+
color: reactComponents.tokens.colorNeutralForeground3,
|
|
1038
|
+
fontSize: reactComponents.tokens.fontSizeBase200
|
|
1039
|
+
},
|
|
974
1040
|
validationIcon: {
|
|
975
1041
|
marginRight: reactComponents.tokens.spacingHorizontalXS
|
|
976
1042
|
},
|
|
@@ -2249,7 +2315,8 @@ var createParsedCondition = (attr, operator, value, value2, fieldMatch, valueDis
|
|
|
2249
2315
|
value,
|
|
2250
2316
|
value2: value2 ?? "",
|
|
2251
2317
|
...valueDisplayName ? { valueDisplayName } : {},
|
|
2252
|
-
...entityAlias ? { entityAlias } : {}
|
|
2318
|
+
...entityAlias ? { entityAlias } : {},
|
|
2319
|
+
...!fieldMatch ? { isUnknownField: true } : {}
|
|
2253
2320
|
});
|
|
2254
2321
|
var parseConditionElement = (condEl, fields) => {
|
|
2255
2322
|
const attr = condEl.getAttribute("attribute") || "";
|
|
@@ -2896,14 +2963,16 @@ var enrichOptionsetFields = async (fields, entityName, trace) => {
|
|
|
2896
2963
|
var QueryBuilder = (props) => {
|
|
2897
2964
|
const styles = useQueryBuilderStyles();
|
|
2898
2965
|
const trace = React3__namespace.useCallback((message, data) => {
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2966
|
+
if (props.debug) {
|
|
2967
|
+
console.debug(
|
|
2968
|
+
"%c FluentUI-Extended ",
|
|
2969
|
+
"background: #845EF7; color: white; padding: 2px 4px; border-radius: 2px; font-weight: bold;",
|
|
2970
|
+
message,
|
|
2971
|
+
data || ""
|
|
2972
|
+
);
|
|
2973
|
+
}
|
|
2905
2974
|
props.onTrace?.(message, data);
|
|
2906
|
-
}, [props]);
|
|
2975
|
+
}, [props.debug, props.onTrace]);
|
|
2907
2976
|
const [loading, setLoading] = React3__namespace.useState(false);
|
|
2908
2977
|
const [availableFields, setAvailableFields] = React3__namespace.useState(
|
|
2909
2978
|
props.fields && props.fields.length > 0 ? props.fields : FALLBACK_FIELDS
|
|
@@ -3132,6 +3201,9 @@ var QueryBuilder = (props) => {
|
|
|
3132
3201
|
if (condition.kind === "relatedEntity") {
|
|
3133
3202
|
return condition;
|
|
3134
3203
|
}
|
|
3204
|
+
if (condition.isUnknownField && !availableFields.some((f) => f.id === condition.fieldId)) {
|
|
3205
|
+
return condition;
|
|
3206
|
+
}
|
|
3135
3207
|
const matchedField = availableFields.find((field) => field.id === condition.fieldId) || fallbackField;
|
|
3136
3208
|
const operators = getOperatorsForType(matchedField.dataType);
|
|
3137
3209
|
const nextOperator = operators.some((item) => item.value === condition.operator) ? condition.operator : operators[0]?.value;
|
|
@@ -3639,16 +3711,16 @@ var QueryBuilder = (props) => {
|
|
|
3639
3711
|
onClick: onOpenUploadDialog
|
|
3640
3712
|
},
|
|
3641
3713
|
"Import FetchXML"
|
|
3642
|
-
), /* @__PURE__ */ React3__namespace.createElement(reactComponents.Dialog, { open: uploadDialogOpen, onOpenChange: (_, data) => setUploadDialogOpen(data.open) }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogSurface, {
|
|
3714
|
+
), /* @__PURE__ */ React3__namespace.createElement(reactComponents.Dialog, { open: uploadDialogOpen, onOpenChange: (_, data) => setUploadDialogOpen(data.open) }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogSurface, { className: styles.dialogSurfaceNarrow }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogBody, null, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogTitle, null, "Import FetchXML"), /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogContent, { className: styles.dialogUploadContent }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, null, "Paste your FetchXML below to rebuild the query:"), /* @__PURE__ */ React3__namespace.createElement(
|
|
3643
3715
|
reactComponents.Textarea,
|
|
3644
3716
|
{
|
|
3645
3717
|
placeholder: "<fetch><entity name='account'><filter>...</filter></entity></fetch>",
|
|
3646
3718
|
value: uploadXmlText,
|
|
3647
3719
|
onChange: (_, data) => setUploadXmlText(data.value),
|
|
3648
|
-
|
|
3720
|
+
className: styles.monacoTextarea,
|
|
3649
3721
|
resize: "vertical"
|
|
3650
3722
|
}
|
|
3651
|
-
), uploadError && /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, {
|
|
3723
|
+
), uploadError && /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { className: styles.uploadErrorText }, uploadError)), /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogActions, null, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogTrigger, { disableButtonEnhancement: true }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.Button, { appearance: "secondary" }, "Cancel")), /* @__PURE__ */ React3__namespace.createElement(reactComponents.Button, { appearance: "primary", onClick: onApplyUploadedXml, disabled: !uploadXmlText.trim() }, "Apply"))))), props.showValidateButton !== false && /* @__PURE__ */ React3__namespace.createElement(
|
|
3652
3724
|
reactComponents.Button,
|
|
3653
3725
|
{
|
|
3654
3726
|
size: "small",
|
|
@@ -3657,7 +3729,7 @@ var QueryBuilder = (props) => {
|
|
|
3657
3729
|
onClick: onValidate
|
|
3658
3730
|
},
|
|
3659
3731
|
"Validate"
|
|
3660
|
-
), /* @__PURE__ */ React3__namespace.createElement(reactComponents.Dialog, { open: validationDialogOpen, onOpenChange: (_, data) => setValidationDialogOpen(data.open) }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogSurface, {
|
|
3732
|
+
), /* @__PURE__ */ React3__namespace.createElement(reactComponents.Dialog, { open: validationDialogOpen, onOpenChange: (_, data) => setValidationDialogOpen(data.open) }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogSurface, { className: styles.dialogSurfaceCompact }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogBody, null, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogTitle, null, "Query Validation"), /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogContent, { className: styles.dialogValidationContent }, /* @__PURE__ */ React3__namespace.createElement("div", null, /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { weight: "semibold", className: styles.validationSectionTitle }, validationResult?.isValid ? /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.validationSuccess }, /* @__PURE__ */ React3__namespace.createElement(reactIcons.CheckmarkCircleRegular, { className: styles.validationIcon }), "Query Structure: Valid") : /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.validationError }, /* @__PURE__ */ React3__namespace.createElement(reactIcons.WarningRegular, { className: styles.validationIcon }), "Query Structure: Errors Found")), !validationResult?.isValid && /* @__PURE__ */ React3__namespace.createElement("ul", { className: styles.validationErrorList }, validationResult?.errors.map((error, idx) => /* @__PURE__ */ React3__namespace.createElement("li", { key: idx, className: styles.validationErrorItem }, /* @__PURE__ */ React3__namespace.createElement("strong", null, error.fieldLabel, ":"), " ", error.message)))), /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.apiValidationSection }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { weight: "semibold", className: styles.validationSectionTitle }, "Dynamics 365 API Test"), !validationResult?.apiValidation?.available ? /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { className: styles.apiUnavailable }, "API validation unavailable \u2014 not running in Dynamics 365 environment.") : !validationResult?.isValid ? /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { className: styles.apiUnavailable }, "Fix query structure errors before testing against the API.") : apiValidating ? /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.validationApiRow }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.Spinner, { size: "tiny" }), /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, null, "Testing query against Dynamics 365...")) : validationResult?.apiValidation?.tested ? validationResult.apiValidation.success ? /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { className: styles.validationSuccess }, /* @__PURE__ */ React3__namespace.createElement(reactIcons.CheckmarkCircleRegular, { className: styles.validationIcon }), "Query executed successfully. ", validationResult.apiValidation.recordCount ?? 0, " record(s) would match.") : /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { className: styles.validationError }, /* @__PURE__ */ React3__namespace.createElement(reactIcons.WarningRegular, { className: styles.validationIcon }), "API Error: ", validationResult.apiValidation.errorMessage) : /* @__PURE__ */ React3__namespace.createElement(reactComponents.Text, { className: styles.apiUnavailable }, "Waiting for validation..."))), /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogActions, null, /* @__PURE__ */ React3__namespace.createElement(reactComponents.DialogTrigger, { disableButtonEnhancement: true }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.Button, { appearance: "primary" }, "OK")))))), props.showDeleteAllFiltersButton !== false && /* @__PURE__ */ React3__namespace.createElement(
|
|
3661
3733
|
reactComponents.Button,
|
|
3662
3734
|
{
|
|
3663
3735
|
size: "small",
|
|
@@ -3859,17 +3931,27 @@ var QueryBuilder = (props) => {
|
|
|
3859
3931
|
onClick: () => addNestedCondition(group.id, condition.id, nestedFields)
|
|
3860
3932
|
},
|
|
3861
3933
|
"Add condition"
|
|
3862
|
-
))), selectedRelated && nestedFields.length === 0 && nestedConditions.length === 0 && /* @__PURE__ */ React3__namespace.createElement("div", {
|
|
3934
|
+
))), selectedRelated && nestedFields.length === 0 && nestedConditions.length === 0 && /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.emptyRelatedEntity }, /* @__PURE__ */ React3__namespace.createElement(reactComponents.Spinner, { size: "tiny", label: "Loading fields..." })), !selectedRelated && /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.emptyRelatedEntity })));
|
|
3863
3935
|
}
|
|
3936
|
+
const isFieldUnknown = condition.isUnknownField && !availableFields.some((f) => f.id === condition.fieldId);
|
|
3864
3937
|
const selectedField = availableFields.find((field) => field.id === condition.fieldId) || defaultField;
|
|
3865
3938
|
const operators = getOperatorsForType(selectedField.dataType);
|
|
3866
3939
|
const isNullOperator = condition.operator === "null" || condition.operator === "notnull";
|
|
3867
3940
|
const isBetween = condition.operator === "between";
|
|
3868
3941
|
const conditionRowClass = reactComponents.mergeClasses(
|
|
3869
3942
|
styles.conditionTreeRow,
|
|
3870
|
-
invalidConditionIds.has(condition.id) && styles.conditionInvalid
|
|
3943
|
+
(invalidConditionIds.has(condition.id) || isFieldUnknown) && styles.conditionInvalid
|
|
3871
3944
|
);
|
|
3872
|
-
return /* @__PURE__ */ React3__namespace.createElement("div", { className: conditionRowClass, key: condition.id }, /* @__PURE__ */ React3__namespace.createElement("div", { className: connectorClass }, /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.conditionConnectorLine }), /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.conditionConnectorBranch })), /* @__PURE__ */ React3__namespace.createElement("div", { className:
|
|
3945
|
+
return /* @__PURE__ */ React3__namespace.createElement("div", { className: conditionRowClass, key: condition.id }, /* @__PURE__ */ React3__namespace.createElement("div", { className: connectorClass }, /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.conditionConnectorLine }), /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.conditionConnectorBranch })), isFieldUnknown ? /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.conditionUnknownBanner }, /* @__PURE__ */ React3__namespace.createElement("span", null, "\u26A0"), /* @__PURE__ */ React3__namespace.createElement("span", { className: styles.conditionUnknownText }, "Unknown field ", /* @__PURE__ */ React3__namespace.createElement("strong", null, condition.fieldId), " \u2014 not found in entity metadata. Update or remove this condition before saving."), /* @__PURE__ */ React3__namespace.createElement(
|
|
3946
|
+
reactComponents.Button,
|
|
3947
|
+
{
|
|
3948
|
+
appearance: "subtle",
|
|
3949
|
+
size: "small",
|
|
3950
|
+
className: styles.conditionUnknownButton,
|
|
3951
|
+
onClick: () => removeCondition(group.id, condition.id)
|
|
3952
|
+
},
|
|
3953
|
+
"Remove"
|
|
3954
|
+
)) : /* @__PURE__ */ React3__namespace.createElement("div", { className: rowGridClass, role: "row" }, /* @__PURE__ */ React3__namespace.createElement("div", { className: styles.fieldCell, role: "gridcell" }, /* @__PURE__ */ React3__namespace.createElement(
|
|
3873
3955
|
Lookup,
|
|
3874
3956
|
{
|
|
3875
3957
|
className: styles.compactControl,
|