@canvas-components/react-list-table 0.3.20 → 0.3.22

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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createContext, forwardRef, useMemo, useRef, useState, useImperativeHandle, useContext, useEffect, useLayoutEffect, Fragment as Fragment$1 } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
- import { ReactImagePreview, ReactCheckbox, ReactNumberInput, ReactSelect, ReactPagination, ReactFilterPanel, ReactPopup, ReactModal, ReactInput, ReactPopconfirm, ReactContentScaleProvider, ReactButton, ReactColorPicker, ReactInputNumber, ReactAutoComplete, ReactTimeRangePicker, ReactDateTimeRangePicker, ReactDateTimePicker, ReactTimePicker, ReactDateRangePicker, ReactDatePicker, ReactMonthPicker, ReactQuarterPicker, ReactYearPicker, ReactInputRange, ReactCascader } from '@canvas-components/react-components';
3
+ import { ReactImagePreview, ReactCheckbox, ReactNumberInput, ReactSelect, ReactPagination, ReactFilterPanel, ReactPopup, ReactModal, ReactInput, ReactPopconfirm, ReactContentScaleProvider, ReactButton, ReactColorPicker, ReactInputNumber, ReactAutoComplete, ReactTimeRangePicker, ReactDateTimeRangePicker, ReactDateTimePicker, ReactTimePicker, ReactDateRangePicker, ReactDatePicker, ReactMonthPicker, ReactQuarterPicker, ReactYearPicker, ReactInputRange, ReactCascader, ReactTreeSelect } from '@canvas-components/react-components';
4
4
  import { EXPAND_COLUMN, SELECTION_COLUMN, ROW_SELECTION_COLUMN, resetListTableStoredColumnConfig, ListTable } from '@canvas-components/list-table';
5
5
  export { EXPAND_COLUMN, ROW_SELECTION_COLUMN, SELECTION_COLUMN, getListTableStoredPageSize } from '@canvas-components/list-table';
6
6
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -2679,6 +2679,58 @@ var toolButtonStyle = {
2679
2679
  lineHeight: 1,
2680
2680
  cursor: "pointer"
2681
2681
  };
2682
+ function ReactListTableExportNameDialog({
2683
+ request
2684
+ }) {
2685
+ const extension = request.fileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
2686
+ const [fileName, setFileName] = useState(
2687
+ extension ? request.fileName.slice(0, -extension.length) : request.fileName
2688
+ );
2689
+ const [invalid, setInvalid] = useState(false);
2690
+ const confirm = () => {
2691
+ if (!fileName.trim()) {
2692
+ setInvalid(true);
2693
+ return;
2694
+ }
2695
+ request.onConfirm(`${fileName.trim()}${extension}`);
2696
+ };
2697
+ return /* @__PURE__ */ jsxs(
2698
+ ReactModal,
2699
+ {
2700
+ open: true,
2701
+ title: "\u5BFC\u51FA\u6587\u4EF6",
2702
+ width: 420,
2703
+ fullscreenable: false,
2704
+ onCancel: request.onCancel,
2705
+ onOk: confirm,
2706
+ okText: "\u5BFC\u51FA",
2707
+ cancelText: "\u53D6\u6D88",
2708
+ children: [
2709
+ /* @__PURE__ */ jsxs("label", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
2710
+ "\u6587\u4EF6\u540D\u79F0",
2711
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
2712
+ /* @__PURE__ */ jsx(
2713
+ ReactInput,
2714
+ {
2715
+ autoFocus: true,
2716
+ value: fileName,
2717
+ placeholder: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0",
2718
+ onFocus: (event) => event.target.select(),
2719
+ onChange: (event) => {
2720
+ setFileName(event.target.value);
2721
+ setInvalid(false);
2722
+ },
2723
+ onPressEnter: confirm
2724
+ }
2725
+ ),
2726
+ /* @__PURE__ */ jsx("span", { "aria-label": "\u6587\u4EF6\u540E\u7F00", style: { flexShrink: 0 }, children: extension })
2727
+ ] })
2728
+ ] }),
2729
+ invalid ? /* @__PURE__ */ jsx("div", { role: "alert", style: { color: "#ff4d4f", marginTop: 8 }, children: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0" }) : null
2730
+ ]
2731
+ }
2732
+ );
2733
+ }
2682
2734
 
2683
2735
  // src/features/editor/utils.ts
2684
2736
  function toNumberValue(value) {
@@ -2780,12 +2832,14 @@ function ReactTableEditorOverlay(props) {
2780
2832
  if (!input) {
2781
2833
  return;
2782
2834
  }
2783
- focusAndSelectEditorInput(input);
2835
+ focusAndSelectEditorInput(input, request.selectOnFocus);
2784
2836
  }, [request]);
2785
2837
  return /* @__PURE__ */ jsx(ReactContentScaleProvider, { scale: contentZoom, children: /* @__PURE__ */ jsx("div", { ref: editorHostRef, children: renderEditorByType(request, style) }, request.editorKey) });
2786
2838
  }
2787
2839
  function renderEditorByType(request, style) {
2788
2840
  switch (request.config.valueType ?? "text") {
2841
+ case "tree-select":
2842
+ return /* @__PURE__ */ jsx(TreeSelectEditor, { request, style });
2789
2843
  case "cascader":
2790
2844
  return /* @__PURE__ */ jsx(CascaderEditor, { request, style });
2791
2845
  case "number":
@@ -2827,7 +2881,7 @@ function TextEditor(props) {
2827
2881
  const skipBlurCommitRef = useRef(false);
2828
2882
  useLayoutEffect(() => {
2829
2883
  const input = hostRef.current?.querySelector("input");
2830
- focusAndSelectEditorInput(input);
2884
+ focusAndSelectEditorInput(input, request.selectOnFocus);
2831
2885
  }, [request]);
2832
2886
  useEffect(() => {
2833
2887
  setValue(String(request.value ?? ""));
@@ -2867,7 +2921,7 @@ function NumberEditor(props) {
2867
2921
  const skipBlurCommitRef = useRef(false);
2868
2922
  useLayoutEffect(() => {
2869
2923
  const input = hostRef.current?.querySelector("input");
2870
- focusAndSelectEditorInput(input);
2924
+ focusAndSelectEditorInput(input, request.selectOnFocus);
2871
2925
  }, [request]);
2872
2926
  useEffect(() => {
2873
2927
  setValue(toNumberValue(request.value));
@@ -3076,14 +3130,56 @@ function DateEditor(props) {
3076
3130
  }
3077
3131
  ) });
3078
3132
  }
3079
- function CascaderEditor({
3133
+ function TreeSelectEditor({
3080
3134
  request,
3081
3135
  style
3082
3136
  }) {
3083
3137
  const [value, setValue] = useState(
3084
- Array.isArray(request.value) ? request.value : []
3138
+ request.value ?? null
3085
3139
  );
3086
3140
  const skipBlurCommitRef = useRef(false);
3141
+ useEffect(() => {
3142
+ setValue(request.value ?? null);
3143
+ }, [request.value]);
3144
+ return /* @__PURE__ */ jsx("div", { style, children: /* @__PURE__ */ jsx(
3145
+ ReactTreeSelect,
3146
+ {
3147
+ autoFocus: true,
3148
+ value,
3149
+ treeData: request.config.treeData,
3150
+ multiple: request.config.multiple,
3151
+ showSearch: request.config.showSearch,
3152
+ treeDefaultExpandAll: request.config.treeDefaultExpandAll,
3153
+ treeDefaultExpandedKeys: request.config.treeDefaultExpandedKeys,
3154
+ allowClear: request.config.allowClear,
3155
+ placeholder: request.config.placeholder,
3156
+ style: getEditorInputStyle(request),
3157
+ onChange: (next, _nodes, info) => {
3158
+ setValue(next);
3159
+ request.onChange(next);
3160
+ if (info.complete && info.trigger !== "clear") {
3161
+ skipBlurCommitRef.current = true;
3162
+ request.onCommit();
3163
+ }
3164
+ },
3165
+ onBlur: (event) => handleEditorBlur(event, skipBlurCommitRef, request),
3166
+ onKeyDown: (event) => {
3167
+ if (event.key === "Tab")
3168
+ handleEditorNavigationKey(event, request, skipBlurCommitRef);
3169
+ if (event.key === "Escape") {
3170
+ skipBlurCommitRef.current = true;
3171
+ handleEditorEscapeKey(event, request);
3172
+ }
3173
+ }
3174
+ }
3175
+ ) });
3176
+ }
3177
+ function CascaderEditor({
3178
+ request,
3179
+ style
3180
+ }) {
3181
+ const [value, setValue] = useState(Array.isArray(request.value) ? request.value : []);
3182
+ const skipBlurCommitRef = useRef(false);
3087
3183
  useEffect(() => {
3088
3184
  setValue(Array.isArray(request.value) ? request.value : []);
3089
3185
  }, [request.value]);
@@ -3097,6 +3193,8 @@ function CascaderEditor({
3097
3193
  showSearch: request.config.showSearch,
3098
3194
  allowClear: request.config.allowClear,
3099
3195
  changeOnSelect: request.config.changeOnSelect,
3196
+ multiple: request.config.multiple,
3197
+ showCheckedStrategy: request.config.showCheckedStrategy,
3100
3198
  expandTrigger: request.config.expandTrigger,
3101
3199
  displayRender: request.config.displayRender,
3102
3200
  style: getEditorInputStyle(request),
@@ -3450,13 +3548,14 @@ function handleRangeInputTab(event) {
3450
3548
  focusAndSelectEditorInput(nextInput);
3451
3549
  return true;
3452
3550
  }
3453
- function focusAndSelectEditorInput(input) {
3551
+ function focusAndSelectEditorInput(input, selectOnFocus = true) {
3454
3552
  if (!input) {
3455
3553
  return;
3456
3554
  }
3457
3555
  input.focus();
3458
3556
  try {
3459
- input.select();
3557
+ if (selectOnFocus) input.select();
3558
+ else input.setSelectionRange(input.value.length, input.value.length);
3460
3559
  } catch {
3461
3560
  }
3462
3561
  }
@@ -3767,6 +3866,12 @@ function SettingOutlined() {
3767
3866
  function HolderOutlined() {
3768
3867
  return /* @__PURE__ */ jsx(ToolbarIcon, { path: "M300 276.5a56 56 0 1056-97 56 56 0 00-56 97zm0 284a56 56 0 1056-97 56 56 0 00-56 97zM640 228a56 56 0 10112 0 56 56 0 00-112 0zm0 284a56 56 0 10112 0 56 56 0 00-112 0zM300 844.5a56 56 0 1056-97 56 56 0 00-56 97zM640 796a56 56 0 10112 0 56 56 0 00-112 0z" });
3769
3868
  }
3869
+
3870
+ // src/components/fullscreen-portal.ts
3871
+ function resolveFullscreenPortalContainer(host) {
3872
+ const fullscreenElement = document.fullscreenElement;
3873
+ return fullscreenElement instanceof HTMLElement && host && fullscreenElement.contains(host) ? fullscreenElement : document.body;
3874
+ }
3770
3875
  function SortableList(props) {
3771
3876
  const { items, onOrderChange } = props;
3772
3877
  const rootRef = useRef(null);
@@ -3891,7 +3996,7 @@ function SortableList(props) {
3891
3996
  })
3892
3997
  }
3893
3998
  ),
3894
- document.body
3999
+ resolveFullscreenPortalContainer(rootRef.current)
3895
4000
  ) : null
3896
4001
  ] });
3897
4002
  }
@@ -4222,9 +4327,14 @@ function useReactListTableState(options) {
4222
4327
  const [searchRequest, setSearchRequest] = useState(null);
4223
4328
  const [imagePreviewRequest, setImagePreviewRequest] = useState(null);
4224
4329
  const [dangerConfirmRequest, setDangerConfirmRequest] = useState(null);
4330
+ const [exportNameRequest, setExportNameRequest] = useState(null);
4225
4331
  const uiOptions = useMemo(
4226
4332
  () => ({
4227
4333
  ...options.ui,
4334
+ onExportNameRequest: (request) => {
4335
+ setExportNameRequest(request);
4336
+ options.ui?.onExportNameRequest?.(request);
4337
+ },
4228
4338
  onEditorRequest: (request) => {
4229
4339
  setEditorRequest(request);
4230
4340
  options.ui?.onEditorRequest?.(request);
@@ -4292,6 +4402,7 @@ function useReactListTableState(options) {
4292
4402
  setSearchRequest(null);
4293
4403
  setImagePreviewRequest(null);
4294
4404
  setDangerConfirmRequest(null);
4405
+ setExportNameRequest(null);
4295
4406
  };
4296
4407
  }, []);
4297
4408
  useEffect(() => {
@@ -4313,6 +4424,7 @@ function useReactListTableState(options) {
4313
4424
  searchRequest,
4314
4425
  imagePreviewRequest,
4315
4426
  dangerConfirmRequest,
4427
+ exportNameRequest,
4316
4428
  closeDangerConfirmRequest: () => {
4317
4429
  setDangerConfirmRequest(null);
4318
4430
  options.ui?.onDangerConfirmRequest?.(null);
@@ -4417,7 +4529,8 @@ function ReactListTableInner(props, ref) {
4417
4529
  rowDrag,
4418
4530
  debug,
4419
4531
  title,
4420
- toolbar
4532
+ toolbar,
4533
+ exportOptions
4421
4534
  } = props;
4422
4535
  const inheritedDebugEnabled = useReactListTableDebugEnabled();
4423
4536
  const resolvedDebug = useMemo(
@@ -4458,6 +4571,7 @@ function ReactListTableInner(props, ref) {
4458
4571
  );
4459
4572
  const options = useMemo(() => {
4460
4573
  const nextOptions = buildListTableOptions({
4574
+ exportOptions,
4461
4575
  width,
4462
4576
  height,
4463
4577
  emptyText,
@@ -4519,6 +4633,7 @@ function ReactListTableInner(props, ref) {
4519
4633
  }
4520
4634
  };
4521
4635
  }, [
4636
+ exportOptions,
4522
4637
  width,
4523
4638
  height,
4524
4639
  emptyText,
@@ -4574,10 +4689,12 @@ function ReactListTableInner(props, ref) {
4574
4689
  searchRequest,
4575
4690
  imagePreviewRequest,
4576
4691
  dangerConfirmRequest,
4692
+ exportNameRequest,
4577
4693
  closeDangerConfirmRequest
4578
4694
  } = useReactListTableState(options);
4579
4695
  const hasPagination = paginationConfig != null;
4580
4696
  const paginationLayout = resolveReactListTablePaginationLayout(resolvedRowHeight);
4697
+ const portalContainer = resolveFullscreenPortalContainer(shellRef.current);
4581
4698
  useImperativeHandle(
4582
4699
  ref,
4583
4700
  () => ({
@@ -4735,23 +4852,27 @@ function ReactListTableInner(props, ref) {
4735
4852
  ),
4736
4853
  tooltipRequest ? createPortal(
4737
4854
  /* @__PURE__ */ jsx(ReactTableTooltipView, { request: tooltipRequest }),
4738
- document.body
4855
+ portalContainer
4739
4856
  ) : null,
4740
4857
  filterPanelRequest ? createPortal(
4741
4858
  /* @__PURE__ */ jsx(ReactTableFilterPanelView, { request: filterPanelRequest }),
4742
- document.body
4859
+ portalContainer
4743
4860
  ) : null,
4744
4861
  fixedPopupRequest ? createPortal(
4745
4862
  /* @__PURE__ */ jsx(ReactTableFixedPopupView, { request: fixedPopupRequest }),
4746
- document.body
4863
+ portalContainer
4747
4864
  ) : null,
4748
4865
  headerContextMenuRequest ? createPortal(
4749
4866
  /* @__PURE__ */ jsx(ReactTableContextMenuView, { request: headerContextMenuRequest }),
4750
- document.body
4867
+ portalContainer
4751
4868
  ) : null,
4752
4869
  searchRequest ? createPortal(
4753
4870
  /* @__PURE__ */ jsx(ReactListTableSearchDialog, { request: searchRequest }),
4754
- document.body
4871
+ portalContainer
4872
+ ) : null,
4873
+ exportNameRequest ? createPortal(
4874
+ /* @__PURE__ */ jsx(ReactListTableExportNameDialog, { request: exportNameRequest }),
4875
+ portalContainer
4755
4876
  ) : null,
4756
4877
  dangerConfirmRequest ? createPortal(
4757
4878
  /* @__PURE__ */ jsx(
@@ -4761,11 +4882,11 @@ function ReactListTableInner(props, ref) {
4761
4882
  onClose: closeDangerConfirmRequest
4762
4883
  }
4763
4884
  ),
4764
- document.body
4885
+ portalContainer
4765
4886
  ) : null,
4766
4887
  editorRequest ? createPortal(
4767
4888
  /* @__PURE__ */ jsx(ReactTableEditorOverlay, { request: editorRequest }),
4768
- editorRequest.hostElement ?? document.body
4889
+ editorRequest.hostElement && portalContainer.contains(editorRequest.hostElement) ? editorRequest.hostElement : portalContainer
4769
4890
  ) : null,
4770
4891
  imagePreviewRequest ? createPortal(
4771
4892
  /* @__PURE__ */ jsx(
@@ -4777,7 +4898,7 @@ function ReactListTableInner(props, ref) {
4777
4898
  onClose: imagePreviewRequest.onClose
4778
4899
  }
4779
4900
  ),
4780
- document.body
4901
+ portalContainer
4781
4902
  ) : null
4782
4903
  ] });
4783
4904
  }