@pnt-team/pnt-component-frontend 0.0.110 → 0.0.113

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.
Files changed (30) hide show
  1. package/README.md +29 -30
  2. package/lib/cjs/api/index.d.ts +14 -1
  3. package/lib/cjs/api/index.js +6 -0
  4. package/lib/cjs/api/types/index.d.ts +47 -0
  5. package/lib/cjs/components/PntRegionSelect/ImportDialog.d.ts +25 -0
  6. package/lib/cjs/components/PntRegionSelect/ImportDialog.js +244 -0
  7. package/lib/cjs/components/PntRegionSelect/index.d.ts +43 -0
  8. package/lib/cjs/components/PntRegionSelect/index.js +402 -0
  9. package/lib/cjs/components/PntRegionSelect/index.scss +166 -0
  10. package/lib/cjs/components/PntRegionSelect/types.d.ts +158 -0
  11. package/lib/cjs/components/PntRegionSelect/types.js +51 -0
  12. package/lib/cjs/components/PntSecureBox/index.scss +3 -0
  13. package/lib/cjs/index.d.ts +3 -4
  14. package/lib/cjs/index.js +5 -12
  15. package/lib/esm/api/index.d.ts +14 -1
  16. package/lib/esm/api/index.js +16 -1
  17. package/lib/esm/api/types/index.d.ts +47 -0
  18. package/lib/esm/components/PntRegionSelect/ImportDialog.d.ts +25 -0
  19. package/lib/esm/components/PntRegionSelect/ImportDialog.js +241 -0
  20. package/lib/esm/components/PntRegionSelect/index.d.ts +43 -0
  21. package/lib/esm/components/PntRegionSelect/index.js +388 -0
  22. package/lib/esm/components/PntRegionSelect/index.scss +166 -0
  23. package/lib/esm/components/PntRegionSelect/types.d.ts +158 -0
  24. package/lib/esm/components/PntRegionSelect/types.js +51 -0
  25. package/lib/esm/components/PntSecureBox/index.scss +3 -0
  26. package/lib/esm/index.d.ts +3 -4
  27. package/lib/esm/index.js +7 -4
  28. package/lib/umd/pnt-component-frontend.min.css +1 -1
  29. package/lib/umd/pnt-component-frontend.min.js +1 -1
  30. package/package.json +2 -2
@@ -0,0 +1,402 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/components/PntRegionSelect/index.tsx
30
+ var PntRegionSelect_exports = {};
31
+ __export(PntRegionSelect_exports, {
32
+ default: () => PntRegionSelect_default
33
+ });
34
+ module.exports = __toCommonJS(PntRegionSelect_exports);
35
+ var import_api = require("../../api");
36
+ var import_config = require("../../config");
37
+ var import_react = require("react");
38
+ var import_tdesign_react = require("tdesign-react");
39
+ var import_ImportDialog = __toESM(require("./ImportDialog"));
40
+ var import_index = require("./index.scss");
41
+ var import_types = require("./types");
42
+ var import_jsx_runtime = require("react/jsx-runtime");
43
+ var toRegionOptions = (list) => (list || []).map((item) => {
44
+ var _a, _b, _c;
45
+ return {
46
+ ...item,
47
+ region_code: (_a = item.region_code) != null ? _a : "",
48
+ region_ch: (_b = item.region_ch) != null ? _b : "",
49
+ region_en: (_c = item.region_en) != null ? _c : ""
50
+ };
51
+ });
52
+ var getLabelText = (item, format) => {
53
+ const { region_ch, region_en, region_code } = item;
54
+ switch (format) {
55
+ case "name_en":
56
+ return region_en || region_ch || region_code;
57
+ case "name_en_name":
58
+ return region_en && region_ch ? `${region_en}(${region_ch})` : region_en || region_ch || region_code;
59
+ case "code":
60
+ return region_code;
61
+ default:
62
+ return region_ch || region_en || region_code;
63
+ }
64
+ };
65
+ var PntRegionSelect = (props) => {
66
+ const {
67
+ value = [],
68
+ onChange,
69
+ multiple = true,
70
+ dataSource = "default",
71
+ gameId,
72
+ env = 0,
73
+ options: externalOptions,
74
+ disabled = false,
75
+ placeholder,
76
+ max,
77
+ filterable = true,
78
+ labelFormat = "name",
79
+ texts: customTexts,
80
+ onLoaded,
81
+ optionDisabled,
82
+ optionTooltip,
83
+ importable = false,
84
+ invertible = false,
85
+ minCollapsedNum,
86
+ collapsedItems,
87
+ onBlur,
88
+ importDialogProps,
89
+ className,
90
+ style,
91
+ popupProps
92
+ } = props;
93
+ const { http } = (0, import_config.usePntConfig)();
94
+ const texts = (0, import_react.useMemo)(
95
+ () => ({ ...import_types.DEFAULT_TEXTS, ...customTexts }),
96
+ [customTexts]
97
+ );
98
+ const [innerOptions, setInnerOptions] = (0, import_react.useState)([]);
99
+ const [loading, setLoading] = (0, import_react.useState)(false);
100
+ const [searchKeyword, setSearchKeyword] = (0, import_react.useState)("");
101
+ const [importVisible, setImportVisible] = (0, import_react.useState)(false);
102
+ const fetchSeqRef = (0, import_react.useRef)(0);
103
+ const onLoadedRef = (0, import_react.useRef)(onLoaded);
104
+ onLoadedRef.current = onLoaded;
105
+ const isExternal = externalOptions !== void 0;
106
+ const fetchData = (0, import_react.useCallback)(async () => {
107
+ var _a, _b, _c, _d;
108
+ if (isExternal)
109
+ return;
110
+ const seq = ++fetchSeqRef.current;
111
+ setLoading(true);
112
+ try {
113
+ let list = [];
114
+ if (dataSource === "custom") {
115
+ if (!gameId) {
116
+ console.warn(
117
+ '[PntRegionSelect] dataSource="custom" 时必须传入 gameId'
118
+ );
119
+ return;
120
+ }
121
+ const res = await (0, import_api.businessGameInfoGetCustomRegion)(http, {
122
+ game_id: Number(gameId),
123
+ env
124
+ });
125
+ if (seq !== fetchSeqRef.current)
126
+ return;
127
+ if (res.code === 0 && ((_a = res.data) == null ? void 0 : _a.region_list)) {
128
+ list = toRegionOptions(res.data.region_list);
129
+ }
130
+ } else if (dataSource === "business") {
131
+ if (!gameId) {
132
+ console.warn(
133
+ '[PntRegionSelect] dataSource="business" 时必须传入 gameId'
134
+ );
135
+ return;
136
+ }
137
+ const res = await (0, import_api.businessRegionQuery)(http, {
138
+ game_id: Number(gameId)
139
+ });
140
+ if (seq !== fetchSeqRef.current)
141
+ return;
142
+ if (res.code === 0 && ((_b = res.data) == null ? void 0 : _b.region_list)) {
143
+ list = toRegionOptions(res.data.region_list);
144
+ }
145
+ } else {
146
+ const res = await (0, import_api.businessRegionQuery)(http, {});
147
+ if (seq !== fetchSeqRef.current)
148
+ return;
149
+ if (res.code === 0 && ((_c = res.data) == null ? void 0 : _c.region_list)) {
150
+ list = toRegionOptions(res.data.region_list);
151
+ }
152
+ }
153
+ setInnerOptions(list);
154
+ (_d = onLoadedRef.current) == null ? void 0 : _d.call(onLoadedRef, list);
155
+ } catch {
156
+ } finally {
157
+ if (seq === fetchSeqRef.current) {
158
+ setLoading(false);
159
+ }
160
+ }
161
+ }, [http, dataSource, gameId, env, isExternal]);
162
+ (0, import_react.useEffect)(() => {
163
+ fetchData();
164
+ }, [fetchData]);
165
+ const options = (0, import_react.useMemo)(
166
+ () => isExternal ? externalOptions : innerOptions,
167
+ [isExternal, externalOptions, innerOptions]
168
+ );
169
+ const valueArr = (0, import_react.useMemo)(() => {
170
+ if (value === void 0 || value === null || value === "")
171
+ return [];
172
+ return Array.isArray(value) ? value.map(String) : [String(value)];
173
+ }, [value]);
174
+ const filteredOptions = (0, import_react.useMemo)(() => {
175
+ if (!searchKeyword)
176
+ return options;
177
+ const kw = searchKeyword.toLowerCase();
178
+ return options.filter(
179
+ (item) => {
180
+ var _a, _b, _c;
181
+ return ((_a = item.region_ch) == null ? void 0 : _a.toLowerCase().includes(kw)) || ((_b = item.region_en) == null ? void 0 : _b.toLowerCase().includes(kw)) || ((_c = item.region_code) == null ? void 0 : _c.toLowerCase().includes(kw));
182
+ }
183
+ );
184
+ }, [options, searchKeyword]);
185
+ const isOptionDisabled = (0, import_react.useCallback)(
186
+ (item) => {
187
+ if (item.disabled)
188
+ return true;
189
+ return optionDisabled ? optionDisabled(item) : false;
190
+ },
191
+ [optionDisabled]
192
+ );
193
+ const emitMultiple = (0, import_react.useCallback)(
194
+ (nextValue) => {
195
+ onChange == null ? void 0 : onChange(
196
+ nextValue,
197
+ options.filter((o) => nextValue.includes(o.region_code))
198
+ );
199
+ },
200
+ [onChange, options]
201
+ );
202
+ const handleSelectAll = (0, import_react.useCallback)(() => {
203
+ const allValues = filteredOptions.filter((item) => !isOptionDisabled(item)).map((item) => item.region_code);
204
+ emitMultiple(Array.from(/* @__PURE__ */ new Set([...valueArr, ...allValues])));
205
+ }, [filteredOptions, valueArr, emitMultiple, isOptionDisabled]);
206
+ const handleClearAll = (0, import_react.useCallback)(() => {
207
+ emitMultiple([]);
208
+ }, [emitMultiple]);
209
+ const handleInvert = (0, import_react.useCallback)(() => {
210
+ const selectedSet = new Set(valueArr);
211
+ const nextValue = filteredOptions.filter((item) => !isOptionDisabled(item)).map((item) => item.region_code).filter((code) => !selectedSet.has(code));
212
+ emitMultiple(nextValue);
213
+ }, [filteredOptions, valueArr, emitMultiple, isOptionDisabled]);
214
+ const isAllSelected = (0, import_react.useMemo)(() => {
215
+ const selectable = filteredOptions.filter(
216
+ (item) => !isOptionDisabled(item)
217
+ );
218
+ return selectable.length > 0 && selectable.every((item) => valueArr.includes(item.region_code));
219
+ }, [filteredOptions, valueArr, isOptionDisabled]);
220
+ const isIndeterminate = (0, import_react.useMemo)(() => {
221
+ const selectable = filteredOptions.filter(
222
+ (item) => !isOptionDisabled(item)
223
+ );
224
+ const selected = selectable.filter(
225
+ (item) => valueArr.includes(item.region_code)
226
+ );
227
+ return selected.length > 0 && selected.length < selectable.length;
228
+ }, [filteredOptions, valueArr, isOptionDisabled]);
229
+ const selectOptions = (0, import_react.useMemo)(() => {
230
+ return filteredOptions.map((item) => {
231
+ const label = getLabelText(item, labelFormat);
232
+ const isDisabled = isOptionDisabled(item);
233
+ const tooltip = optionTooltip ? optionTooltip(item) : void 0;
234
+ return {
235
+ label,
236
+ value: item.region_code,
237
+ disabled: isDisabled,
238
+ tooltip,
239
+ rawItem: item
240
+ };
241
+ });
242
+ }, [filteredOptions, labelFormat, isOptionDisabled, optionTooltip]);
243
+ const handleChange = (0, import_react.useCallback)(
244
+ (val) => {
245
+ var _a, _b;
246
+ const values = Array.isArray(val) ? val : val ? [val] : [];
247
+ const strValues = values.map(String);
248
+ const selectedOptions = options.filter(
249
+ (o) => strValues.includes(o.region_code)
250
+ );
251
+ if (multiple) {
252
+ onChange == null ? void 0 : onChange(strValues, selectedOptions);
253
+ } else {
254
+ onChange == null ? void 0 : onChange(
255
+ (_a = strValues[0]) != null ? _a : "",
256
+ (_b = selectedOptions[0]) != null ? _b : void 0
257
+ );
258
+ }
259
+ },
260
+ [onChange, options, multiple]
261
+ );
262
+ const handleImportConfirm = (0, import_react.useCallback)(
263
+ (nextValue) => {
264
+ emitMultiple(nextValue);
265
+ onBlur == null ? void 0 : onBlur({ value: nextValue });
266
+ },
267
+ [emitMultiple, onBlur]
268
+ );
269
+ const panelTopContent = (0, import_react.useMemo)(() => {
270
+ if (!multiple)
271
+ return null;
272
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pnt-region-select__toolbar", children: [
273
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
274
+ import_tdesign_react.Checkbox,
275
+ {
276
+ checked: isAllSelected,
277
+ indeterminate: isIndeterminate,
278
+ onChange: (checked) => {
279
+ if (checked) {
280
+ handleSelectAll();
281
+ } else {
282
+ handleClearAll();
283
+ }
284
+ },
285
+ children: texts.selectAll
286
+ }
287
+ ),
288
+ invertible && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
289
+ "span",
290
+ {
291
+ role: "button",
292
+ tabIndex: 0,
293
+ className: "pnt-region-select__invert",
294
+ onClick: (event) => {
295
+ event.preventDefault();
296
+ event.stopPropagation();
297
+ handleInvert();
298
+ },
299
+ onKeyDown: (event) => {
300
+ if (event.key === "Enter" || event.key === " ") {
301
+ event.preventDefault();
302
+ event.stopPropagation();
303
+ handleInvert();
304
+ }
305
+ },
306
+ children: texts.invertSelection
307
+ }
308
+ ),
309
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "pnt-region-select__count", children: texts.selectedCount.replace("{count}", String(valueArr.length)) })
310
+ ] });
311
+ }, [
312
+ multiple,
313
+ isAllSelected,
314
+ isIndeterminate,
315
+ handleSelectAll,
316
+ handleClearAll,
317
+ invertible,
318
+ handleInvert,
319
+ texts,
320
+ valueArr.length
321
+ ]);
322
+ const emptyContent = (0, import_react.useMemo)(() => {
323
+ if (loading)
324
+ return null;
325
+ if (filteredOptions.length === 0) {
326
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pnt-region-select__empty", children: texts.noResult });
327
+ }
328
+ return null;
329
+ }, [loading, filteredOptions.length, texts.noResult]);
330
+ const selectNode = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
331
+ import_tdesign_react.Select,
332
+ {
333
+ value: multiple ? valueArr : valueArr[0],
334
+ onChange: handleChange,
335
+ filterable,
336
+ onSearch: setSearchKeyword,
337
+ loading: loading && options.length === 0,
338
+ multiple,
339
+ max,
340
+ clearable: true,
341
+ disabled,
342
+ placeholder: placeholder || texts.placeholder,
343
+ panelTopContent,
344
+ empty: emptyContent,
345
+ minCollapsedNum,
346
+ collapsedItems,
347
+ onBlur,
348
+ popupProps: {
349
+ ...popupProps,
350
+ overlayClassName: [
351
+ "pnt-region-select-popup",
352
+ popupProps == null ? void 0 : popupProps.overlayClassName
353
+ ].filter(Boolean).join(" ")
354
+ },
355
+ className: className ? `pnt-region-select ${className}` : "pnt-region-select",
356
+ style,
357
+ children: selectOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
358
+ import_tdesign_react.Select.Option,
359
+ {
360
+ value: opt.value,
361
+ label: opt.label,
362
+ disabled: opt.disabled,
363
+ title: opt.tooltip
364
+ },
365
+ opt.value
366
+ ))
367
+ }
368
+ );
369
+ if (importable && multiple) {
370
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
371
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pnt-region-select__import-wrapper", children: [
372
+ selectNode,
373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
374
+ import_tdesign_react.Button,
375
+ {
376
+ theme: "primary",
377
+ size: "small",
378
+ variant: "outline",
379
+ disabled,
380
+ className: "pnt-region-select__import-btn",
381
+ onClick: () => setImportVisible(true),
382
+ children: texts.importBtn
383
+ }
384
+ )
385
+ ] }),
386
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
387
+ import_ImportDialog.default,
388
+ {
389
+ visible: importVisible,
390
+ options,
391
+ currentValue: valueArr,
392
+ texts,
393
+ dialogProps: importDialogProps,
394
+ onClose: () => setImportVisible(false),
395
+ onConfirm: handleImportConfirm
396
+ }
397
+ )
398
+ ] });
399
+ }
400
+ return selectNode;
401
+ };
402
+ var PntRegionSelect_default = PntRegionSelect;
@@ -0,0 +1,166 @@
1
+ .pnt-region-select {
2
+ width: 100%;
3
+
4
+ &__toolbar {
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: space-between;
8
+ padding: 8px 12px;
9
+ border-bottom: 1px solid var(--td-component-border, #e7e7e7);
10
+ background: var(--td-bg-color-container, #fff);
11
+ }
12
+
13
+ &__invert {
14
+ margin-left: 12px;
15
+ margin-right: auto;
16
+ font-size: 12px;
17
+ color: var(--td-brand-color, #0052d9);
18
+ cursor: pointer;
19
+ user-select: none;
20
+
21
+ &:hover {
22
+ color: var(--td-brand-color-hover, #2667d4);
23
+ }
24
+ }
25
+
26
+ &__count {
27
+ margin-left: auto;
28
+ font-size: 12px;
29
+ color: var(--td-text-color-secondary, #999);
30
+ }
31
+
32
+ &__invert + &__count {
33
+ margin-left: 0;
34
+ }
35
+
36
+ &__empty {
37
+ padding: 16px;
38
+ text-align: center;
39
+ color: var(--td-text-color-secondary, #999);
40
+ font-size: 14px;
41
+ }
42
+
43
+ // ---- 批量导入 ----
44
+ &__import-wrapper {
45
+ position: relative;
46
+ display: flex;
47
+ align-items: center;
48
+
49
+ .pnt-region-select {
50
+ flex: 1;
51
+ }
52
+ }
53
+
54
+ &__import-btn {
55
+ position: absolute;
56
+ right: 32px;
57
+ z-index: 1;
58
+ flex-shrink: 0;
59
+ }
60
+ }
61
+
62
+ .pnt-region-select-popup {
63
+ .t-select__list {
64
+ padding-top: 0;
65
+ }
66
+ }
67
+
68
+ // ---- 批量导入弹窗 ----
69
+ .pnt-region-import {
70
+ &__tip {
71
+ margin-bottom: 8px;
72
+ font-size: 12px;
73
+ color: var(--td-text-color-secondary, #999);
74
+ }
75
+
76
+ &__result {
77
+ margin-top: 12px;
78
+ }
79
+
80
+ &__summary {
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 4px;
84
+ margin-bottom: 8px;
85
+ font-size: 12px;
86
+ }
87
+
88
+ &__summary-item {
89
+ &--unmatched {
90
+ color: var(--td-error-color, #d54941);
91
+ }
92
+
93
+ &--pending {
94
+ color: var(--td-success-color, #2ba471);
95
+ }
96
+
97
+ &--exists {
98
+ color: var(--td-text-color-secondary, #999);
99
+ }
100
+ }
101
+
102
+ &__summary-dot {
103
+ color: var(--td-text-color-placeholder, #bbb);
104
+ }
105
+
106
+ &__copy-btn {
107
+ padding: 0 4px;
108
+ height: 20px;
109
+ }
110
+
111
+ &__table {
112
+ border: 1px solid var(--td-component-border, #e7e7e7);
113
+ border-radius: 4px;
114
+ overflow: hidden;
115
+ }
116
+
117
+ &__table-head {
118
+ display: flex;
119
+ justify-content: space-between;
120
+ padding: 6px 12px;
121
+ background: var(--td-bg-color-secondarycontainer, #f3f3f3);
122
+ font-size: 12px;
123
+ color: var(--td-text-color-secondary, #999);
124
+ }
125
+
126
+ &__table-body {
127
+ max-height: 200px;
128
+ overflow-y: auto;
129
+ }
130
+
131
+ &__table-row {
132
+ display: flex;
133
+ justify-content: space-between;
134
+ align-items: center;
135
+ padding: 6px 12px;
136
+ font-size: 12px;
137
+
138
+ & + & {
139
+ border-top: 1px solid var(--td-component-border, #e7e7e7);
140
+ }
141
+ }
142
+
143
+ &__status {
144
+ display: inline-flex;
145
+ align-items: center;
146
+ gap: 4px;
147
+
148
+ &--unmatched {
149
+ color: var(--td-error-color, #d54941);
150
+ }
151
+
152
+ &--pending {
153
+ color: var(--td-success-color, #2ba471);
154
+ }
155
+
156
+ &--exists {
157
+ color: var(--td-text-color-secondary, #999);
158
+ }
159
+ }
160
+
161
+ &__empty {
162
+ padding: 16px;
163
+ text-align: center;
164
+ color: var(--td-text-color-secondary, #999);
165
+ }
166
+ }