@canvas-components/react-components 0.2.1 → 0.3.1
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.cjs +145 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +146 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1128,16 +1128,31 @@ var operators = [
|
|
|
1128
1128
|
];
|
|
1129
1129
|
function ReactFilterPanel(props) {
|
|
1130
1130
|
const { request } = props;
|
|
1131
|
-
const [draft, setDraft] = React.useState(request?.value
|
|
1131
|
+
const [draft, setDraft] = React.useState(() => createDraft(request?.value));
|
|
1132
1132
|
const [tab, setTab] = React.useState(resolveTab(request?.value));
|
|
1133
1133
|
const [options, setOptions] = React.useState(request?.options ?? []);
|
|
1134
1134
|
const [loading, setLoading] = React.useState(Boolean(request?.loadOptions));
|
|
1135
|
+
const conditionListRef = React.useRef(null);
|
|
1136
|
+
const [conditionListOverflowing, setConditionListOverflowing] = React.useState(false);
|
|
1135
1137
|
React.useEffect(() => {
|
|
1136
|
-
setDraft(request?.value
|
|
1138
|
+
setDraft(createDraft(request?.value));
|
|
1137
1139
|
setTab(resolveTab(request?.value));
|
|
1138
1140
|
setOptions(request?.options ?? []);
|
|
1139
1141
|
setLoading(Boolean(request?.loadOptions));
|
|
1140
1142
|
}, [request]);
|
|
1143
|
+
React.useLayoutEffect(() => {
|
|
1144
|
+
const element = conditionListRef.current;
|
|
1145
|
+
if (!element || tab !== "condition") {
|
|
1146
|
+
setConditionListOverflowing(false);
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
const measure = () => setConditionListOverflowing(element.scrollHeight > element.clientHeight + 1);
|
|
1150
|
+
measure();
|
|
1151
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
1152
|
+
const observer = new ResizeObserver(measure);
|
|
1153
|
+
observer.observe(element);
|
|
1154
|
+
return () => observer.disconnect();
|
|
1155
|
+
}, [draft?.conditions, tab]);
|
|
1141
1156
|
React.useEffect(() => {
|
|
1142
1157
|
if (!request?.loadOptions) return;
|
|
1143
1158
|
const controller = new AbortController();
|
|
@@ -1172,6 +1187,20 @@ function ReactFilterPanel(props) {
|
|
|
1172
1187
|
const allChecked = visibleKeys.length > 0 && selectedCount === visibleKeys.length;
|
|
1173
1188
|
const allCount = request.options.find((item) => item.kind === "all")?.count ?? visibleOptions.filter((item) => item.kind === "value").reduce((sum, item) => sum + item.count, 0);
|
|
1174
1189
|
const update = (patch) => setDraft((current) => ({ ...current ?? request.value, ...patch }));
|
|
1190
|
+
const updateConditions = (conditions) => {
|
|
1191
|
+
const first = conditions[0] ?? createEmptyCondition();
|
|
1192
|
+
const second = conditions[1] ?? createEmptyCondition();
|
|
1193
|
+
update({
|
|
1194
|
+
conditions,
|
|
1195
|
+
filterType: "condition",
|
|
1196
|
+
conditionOperator: first.operator,
|
|
1197
|
+
conditionValue: first.value ?? "",
|
|
1198
|
+
conditionSecondValue: first.secondValue ?? "",
|
|
1199
|
+
secondConditionOperator: second.operator,
|
|
1200
|
+
secondConditionValue: second.value ?? "",
|
|
1201
|
+
secondConditionSecondValue: second.secondValue ?? ""
|
|
1202
|
+
});
|
|
1203
|
+
};
|
|
1175
1204
|
const toggle = (keys, checked) => {
|
|
1176
1205
|
const next = new Set(draft.selectedKeys ?? []);
|
|
1177
1206
|
keys.forEach((key) => checked ? next.add(key) : next.delete(key));
|
|
@@ -1278,97 +1307,138 @@ function ReactFilterPanel(props) {
|
|
|
1278
1307
|
)
|
|
1279
1308
|
}
|
|
1280
1309
|
) })
|
|
1281
|
-
] }) : /* @__PURE__ */ jsxRuntime.
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1310
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, display: "flex", flexDirection: "column", gap: 10, minHeight: 0, flex: "1 1 auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1311
|
+
"div",
|
|
1312
|
+
{
|
|
1313
|
+
ref: conditionListRef,
|
|
1314
|
+
className: "react-filter-panel-condition-list",
|
|
1315
|
+
style: { ...conditionListStyle, overflowY: conditionListOverflowing ? "auto" : "hidden" },
|
|
1316
|
+
children: (draft.conditions ?? []).map((condition, index, conditions) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
|
|
1317
|
+
index > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-filter-panel-condition-relation", style: conditionRowStyle, children: [
|
|
1318
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: inlineLabelStyle, children: request.texts.relationLabel }),
|
|
1319
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1320
|
+
ReactSelect,
|
|
1321
|
+
{
|
|
1322
|
+
value: draft.conditionRelation === "or" ? "or" : "and",
|
|
1323
|
+
allowClear: false,
|
|
1324
|
+
options: [{ label: request.texts.relationAndLabel, value: "and" }, { label: request.texts.relationOrLabel, value: "or" }],
|
|
1325
|
+
onChange: (value) => update({ conditionRelation: value, filterType: "condition" }),
|
|
1326
|
+
style: { width: "100%" }
|
|
1327
|
+
}
|
|
1328
|
+
),
|
|
1329
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", {})
|
|
1330
|
+
] }) : null,
|
|
1331
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1332
|
+
ConditionEditor,
|
|
1333
|
+
{
|
|
1334
|
+
label: resolveConditionLabel(request.texts, index),
|
|
1335
|
+
condition,
|
|
1336
|
+
texts: request.texts,
|
|
1337
|
+
canDelete: conditions.length > 1,
|
|
1338
|
+
onDelete: () => updateConditions(conditions.filter((_item, itemIndex) => itemIndex !== index)),
|
|
1339
|
+
onChange: (nextCondition) => updateConditions(conditions.map((item, itemIndex) => itemIndex === index ? nextCondition : item)),
|
|
1340
|
+
onSubmit: apply
|
|
1341
|
+
}
|
|
1342
|
+
)
|
|
1343
|
+
] }, index))
|
|
1344
|
+
}
|
|
1345
|
+
) }),
|
|
1346
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-filter-panel-footer", style: footerStyle, children: [
|
|
1347
|
+
tab === "condition" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1348
|
+
"button",
|
|
1309
1349
|
{
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
onSubmit: apply
|
|
1350
|
+
type: "button",
|
|
1351
|
+
style: addConditionStyle,
|
|
1352
|
+
onClick: () => updateConditions([...draft.conditions ?? [], createEmptyCondition()]),
|
|
1353
|
+
children: [
|
|
1354
|
+
"+ ",
|
|
1355
|
+
request.texts.addConditionAction ?? "\u65B0\u589E\u6761\u4EF6"
|
|
1356
|
+
]
|
|
1318
1357
|
}
|
|
1319
|
-
)
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
request.
|
|
1325
|
-
|
|
1326
|
-
|
|
1358
|
+
) : null,
|
|
1359
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-filter-panel-footer-actions", style: footerActionsStyle, children: [
|
|
1360
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: actionStyle(false), onClick: () => {
|
|
1361
|
+
request.onReset();
|
|
1362
|
+
request.onClose();
|
|
1363
|
+
}, children: request.texts.resetAction }),
|
|
1364
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: actionStyle(true), onClick: apply, children: request.texts.applyAction })
|
|
1365
|
+
] })
|
|
1327
1366
|
] })
|
|
1328
1367
|
] })
|
|
1329
1368
|
}
|
|
1330
1369
|
);
|
|
1331
1370
|
}
|
|
1332
1371
|
function ConditionEditor(props) {
|
|
1333
|
-
const
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1372
|
+
const hidesValue = ["none", "blank", "notBlank"].includes(props.condition.operator);
|
|
1373
|
+
const needsSecond = ["between", "notBetween"].includes(props.condition.operator);
|
|
1374
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: conditionEditorStyle, children: [
|
|
1375
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-filter-panel-condition-row", style: conditionRowStyle, children: [
|
|
1376
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: inlineLabelStyle, children: props.label }),
|
|
1377
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1378
|
+
ReactSelect,
|
|
1379
|
+
{
|
|
1380
|
+
value: props.condition.operator,
|
|
1381
|
+
options: operators,
|
|
1382
|
+
allowClear: false,
|
|
1383
|
+
onChange: (value) => props.onChange({ ...props.condition, operator: value }),
|
|
1384
|
+
style: { width: "100%" }
|
|
1385
|
+
}
|
|
1386
|
+
),
|
|
1387
|
+
props.canDelete ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1388
|
+
"button",
|
|
1389
|
+
{
|
|
1390
|
+
type: "button",
|
|
1391
|
+
title: `${props.texts.deleteConditionAction ?? "\u5220\u9664\u6761\u4EF6"} ${props.label}`,
|
|
1392
|
+
"aria-label": `${props.texts.deleteConditionAction ?? "\u5220\u9664\u6761\u4EF6"} ${props.label}`,
|
|
1393
|
+
style: deleteConditionStyle,
|
|
1394
|
+
onClick: props.onDelete,
|
|
1395
|
+
children: "\xD7"
|
|
1396
|
+
}
|
|
1397
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", {})
|
|
1398
|
+
] }),
|
|
1399
|
+
hidesValue ? null : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: conditionValueStyle, children: [
|
|
1349
1400
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1350
1401
|
ReactInput,
|
|
1351
1402
|
{
|
|
1352
|
-
value: props.value,
|
|
1403
|
+
value: props.condition.value ?? "",
|
|
1353
1404
|
placeholder: props.texts.firstValuePlaceholder,
|
|
1354
1405
|
onPressEnter: props.onSubmit,
|
|
1355
|
-
onChange: (event) => props.onChange({
|
|
1406
|
+
onChange: (event) => props.onChange({ ...props.condition, value: event.target.value }),
|
|
1356
1407
|
style: { width: "100%" }
|
|
1357
1408
|
}
|
|
1358
1409
|
),
|
|
1359
1410
|
needsSecond ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1360
1411
|
ReactInput,
|
|
1361
1412
|
{
|
|
1362
|
-
value: props.secondValue,
|
|
1413
|
+
value: props.condition.secondValue ?? "",
|
|
1363
1414
|
placeholder: props.texts.secondValuePlaceholder,
|
|
1364
1415
|
onPressEnter: props.onSubmit,
|
|
1365
|
-
onChange: (event) => props.onChange({
|
|
1416
|
+
onChange: (event) => props.onChange({ ...props.condition, secondValue: event.target.value }),
|
|
1366
1417
|
style: { width: "100%" }
|
|
1367
1418
|
}
|
|
1368
1419
|
) : null
|
|
1369
1420
|
] })
|
|
1370
1421
|
] });
|
|
1371
1422
|
}
|
|
1423
|
+
function createDraft(value) {
|
|
1424
|
+
if (!value) return null;
|
|
1425
|
+
return { ...value, conditions: resolveDraftConditions(value) };
|
|
1426
|
+
}
|
|
1427
|
+
function resolveDraftConditions(value) {
|
|
1428
|
+
if (value.conditions?.length) return value.conditions.map((condition) => ({ ...condition }));
|
|
1429
|
+
return [
|
|
1430
|
+
{ operator: value.conditionOperator ?? "none", value: value.conditionValue ?? "", secondValue: value.conditionSecondValue ?? "" },
|
|
1431
|
+
{ operator: value.secondConditionOperator ?? "none", value: value.secondConditionValue ?? "", secondValue: value.secondConditionSecondValue ?? "" }
|
|
1432
|
+
];
|
|
1433
|
+
}
|
|
1434
|
+
function createEmptyCondition() {
|
|
1435
|
+
return { operator: "none", value: "", secondValue: "" };
|
|
1436
|
+
}
|
|
1437
|
+
function resolveConditionLabel(texts, index) {
|
|
1438
|
+
if (index === 0) return texts.firstConditionLabel;
|
|
1439
|
+
if (index === 1) return texts.secondConditionLabel;
|
|
1440
|
+
return `${texts.conditionLabel ?? "\u6761\u4EF6"} ${index + 1}`;
|
|
1441
|
+
}
|
|
1372
1442
|
function resolveTab(value) {
|
|
1373
1443
|
return value?.filterType === "condition" || value?.conditionOperator && value.conditionOperator !== "none" ? "condition" : "value";
|
|
1374
1444
|
}
|
|
@@ -1380,7 +1450,15 @@ function optionLabel(item, texts) {
|
|
|
1380
1450
|
var checkLabelStyle = { display: "inline-flex", alignItems: "center", gap: 8, color: "#374151", fontSize: 14 };
|
|
1381
1451
|
var optionStyle = { display: "flex", alignItems: "center", gap: 8, minHeight: 40, padding: "4px 8px", borderRadius: 6, color: "#374151", fontSize: 14, cursor: "pointer", boxSizing: "border-box" };
|
|
1382
1452
|
var optionTextStyle = { display: "block", flex: "1 1 0", width: 0, minWidth: 0, overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" };
|
|
1383
|
-
var
|
|
1453
|
+
var conditionListStyle = { display: "grid", gap: 8, minHeight: 0, flex: "1 1 auto", alignContent: "start", paddingRight: 3 };
|
|
1454
|
+
var conditionEditorStyle = { display: "grid", gap: 8 };
|
|
1455
|
+
var conditionRowStyle = { display: "grid", gridTemplateColumns: "56px minmax(0, 1fr) 22px", alignItems: "center", gap: 8 };
|
|
1456
|
+
var inlineLabelStyle = { color: "#6b7280", fontSize: 12, whiteSpace: "nowrap" };
|
|
1457
|
+
var conditionValueStyle = { display: "grid", gap: 8, marginLeft: 64, marginRight: 30 };
|
|
1458
|
+
var addConditionStyle = { height: 32, padding: "0 10px", border: "1px solid #91caff", borderRadius: 6, background: "#f0f7ff", color: "#1677ff", cursor: "pointer", whiteSpace: "nowrap" };
|
|
1459
|
+
var deleteConditionStyle = { width: 22, height: 22, padding: 0, border: 0, borderRadius: 4, background: "transparent", color: "#9ca3af", fontSize: 18, lineHeight: "20px", cursor: "pointer" };
|
|
1460
|
+
var footerStyle = { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 };
|
|
1461
|
+
var footerActionsStyle = { display: "flex", gap: 8, marginLeft: "auto" };
|
|
1384
1462
|
function tabStyle(active) {
|
|
1385
1463
|
return { flex: 1, height: 32, border: active ? "1px solid #1677ff" : "1px solid #d9d9d9", borderRadius: 6, background: active ? "#e6f4ff" : "#fff", color: active ? "#1677ff" : "#374151", cursor: "pointer" };
|
|
1386
1464
|
}
|