weifuwu 0.40.0 → 0.50.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/README.md +555 -94
- package/dist/client/index.js +47 -81
- package/dist/client/render.d.ts +1 -1
- package/dist/client/types.d.ts +0 -8
- package/dist/client/vnode.d.ts +0 -3
- package/dist/components/Form/Form.d.ts +17 -1
- package/dist/components/Modal/Modal.d.ts +4 -0
- package/dist/components/Select/Select.d.ts +5 -1
- package/dist/components/Skeleton/Skeleton.d.ts +1 -1
- package/dist/components/Table/Table.d.ts +13 -0
- package/dist/components/Toast/Toast.d.ts +9 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +311 -100
- package/dist/components/style.css +744 -2
- package/dist/index.js +39 -13
- package/dist/layout/weifuwu-layout.css +0 -1
- package/dist/ui/index.d.ts +3 -3
- package/package.json +2 -1
package/dist/components/index.js
CHANGED
|
@@ -96,7 +96,7 @@ var Textarea = (_init, _ctx) => (props) => {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
// src/components/Select/Select.ts
|
|
99
|
-
var
|
|
99
|
+
var SelectNative = (_init, _ctx) => (props) => {
|
|
100
100
|
const { label, value, options, placeholder, required, disabled, error, onChange, children } = props;
|
|
101
101
|
const optionEls = [];
|
|
102
102
|
if (placeholder) {
|
|
@@ -112,7 +112,7 @@ var Select = (_init, _ctx) => (props) => {
|
|
|
112
112
|
value: value ?? "",
|
|
113
113
|
required: required || void 0,
|
|
114
114
|
disabled: disabled || void 0,
|
|
115
|
-
onChange
|
|
115
|
+
onChange: (e) => onChange?.(e.target.value)
|
|
116
116
|
}, children ?? optionEls);
|
|
117
117
|
const wrapChildren = [];
|
|
118
118
|
if (label) {
|
|
@@ -124,6 +124,82 @@ var Select = (_init, _ctx) => (props) => {
|
|
|
124
124
|
if (error) wrapChildren.push(h("div", { class: "wf-select-err" }, error));
|
|
125
125
|
return h("div", { class: `wf-select-wrap${error ? " wf-select--err" : ""}` }, wrapChildren);
|
|
126
126
|
};
|
|
127
|
+
var SelectSearchable = (_init, ctx) => {
|
|
128
|
+
const $ = ctx.ui.$();
|
|
129
|
+
$.open = false;
|
|
130
|
+
$.keyword = "";
|
|
131
|
+
$.filteredOptions = [];
|
|
132
|
+
return (props) => {
|
|
133
|
+
const { label, value, options = [], placeholder, required, disabled, error, onChange, onSearch } = props;
|
|
134
|
+
const filtered = $.keyword ? options.filter((o) => o.label.toLowerCase().includes($.keyword.toLowerCase())) : options;
|
|
135
|
+
const selectedOption = options.find((o) => o.value === value);
|
|
136
|
+
const handleInput = async (keyword) => {
|
|
137
|
+
$.keyword = keyword;
|
|
138
|
+
$.open = true;
|
|
139
|
+
if (onSearch && keyword) {
|
|
140
|
+
const result = await onSearch(keyword);
|
|
141
|
+
if (result) $.filteredOptions = result;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const handleSelect = (opt) => {
|
|
145
|
+
if (opt.disabled) return;
|
|
146
|
+
$.keyword = "";
|
|
147
|
+
$.open = false;
|
|
148
|
+
onChange?.(opt.value);
|
|
149
|
+
};
|
|
150
|
+
const trigger = h("div", {
|
|
151
|
+
class: `wf-select-search-trigger${disabled ? " wf-select-search--disabled" : ""}${error ? " wf-select--err" : ""}`,
|
|
152
|
+
onClick: disabled ? void 0 : () => {
|
|
153
|
+
$.open = !$.open;
|
|
154
|
+
}
|
|
155
|
+
}, [
|
|
156
|
+
h("input", {
|
|
157
|
+
class: "wf-select-search-input",
|
|
158
|
+
type: "text",
|
|
159
|
+
value: $.open ? $.keyword : selectedOption?.label ?? "",
|
|
160
|
+
placeholder: selectedOption ? void 0 : placeholder ?? "",
|
|
161
|
+
disabled,
|
|
162
|
+
readOnly: !$.open || void 0,
|
|
163
|
+
onInput: (e) => handleInput(e.target.value),
|
|
164
|
+
onFocus: () => {
|
|
165
|
+
if (!disabled) $.open = true;
|
|
166
|
+
},
|
|
167
|
+
onBlur: () => {
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
$.open = false;
|
|
170
|
+
$.keyword = "";
|
|
171
|
+
}, 150);
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
]);
|
|
175
|
+
const wrapChildren = [];
|
|
176
|
+
if (label) {
|
|
177
|
+
const labelContent = [label];
|
|
178
|
+
if (required) labelContent.push(h("span", { class: "wf-select-req" }, "*"));
|
|
179
|
+
wrapChildren.push(h("label", { class: "wf-select-label" }, labelContent));
|
|
180
|
+
}
|
|
181
|
+
const displayOptions = $.keyword && onSearch && $.filteredOptions.length > 0 ? $.filteredOptions : filtered;
|
|
182
|
+
const menuChildren = displayOptions.length > 0 ? displayOptions.map(
|
|
183
|
+
(opt) => h("div", {
|
|
184
|
+
class: `wf-select-search-opt${opt.value === value ? " wf-select-search-opt--sel" : ""}${opt.disabled ? " wf-select-search-opt--dis" : ""}`,
|
|
185
|
+
key: opt.value,
|
|
186
|
+
onMouseDown: (e) => {
|
|
187
|
+
e.preventDefault();
|
|
188
|
+
handleSelect(opt);
|
|
189
|
+
}
|
|
190
|
+
}, opt.label)
|
|
191
|
+
) : $.keyword ? [h("div", { class: "wf-select-search-empty" }, "\u65E0\u5339\u914D")] : [];
|
|
192
|
+
const menu = $.open ? h("div", { class: "wf-select-search-menu" }, menuChildren) : null;
|
|
193
|
+
wrapChildren.push(h("div", { class: "wf-select-search" }, [trigger, menu].filter(Boolean)));
|
|
194
|
+
if (error) wrapChildren.push(h("div", { class: "wf-select-err" }, error));
|
|
195
|
+
return h("div", { class: `wf-select-wrap${error ? " wf-select--err" : ""}` }, wrapChildren);
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
var Select = (_init, ctx) => {
|
|
199
|
+
const nativeRender = SelectNative(_init, ctx);
|
|
200
|
+
const searchableRender = SelectSearchable(_init, ctx);
|
|
201
|
+
return (props) => props.searchable ? searchableRender(props) : nativeRender(props);
|
|
202
|
+
};
|
|
127
203
|
|
|
128
204
|
// src/components/Checkbox/Checkbox.ts
|
|
129
205
|
var Checkbox = (_init, _ctx) => (props) => {
|
|
@@ -192,31 +268,62 @@ var RadioGroup = (_init, _ctx) => (props) => {
|
|
|
192
268
|
};
|
|
193
269
|
|
|
194
270
|
// src/components/Table/Table.ts
|
|
271
|
+
function sortData(data, columns, sortKey, sortOrder) {
|
|
272
|
+
if (!sortKey || !sortOrder) return data;
|
|
273
|
+
const col = columns.find((c) => c.key === sortKey);
|
|
274
|
+
if (!col || !col.sortable) return data;
|
|
275
|
+
const sorted = [...data];
|
|
276
|
+
sorted.sort((a, b) => {
|
|
277
|
+
const va = a[sortKey];
|
|
278
|
+
const vb = b[sortKey];
|
|
279
|
+
const result = col.sorter ? col.sorter(va, vb) : String(va ?? "").localeCompare(String(vb ?? ""));
|
|
280
|
+
return sortOrder === "desc" ? -result : result;
|
|
281
|
+
});
|
|
282
|
+
return sorted;
|
|
283
|
+
}
|
|
195
284
|
var Table = (_init, _ctx) => (props) => {
|
|
196
|
-
const { data = [], columns, onRowClick } = props;
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
285
|
+
const { data = [], columns, onRowClick, sortKey, sortOrder, onSort, emptyText } = props;
|
|
286
|
+
const sortedData = sortData(data, columns, sortKey, sortOrder);
|
|
287
|
+
const headerCells = columns.map((col) => {
|
|
288
|
+
const isSorted = col.key === sortKey && sortOrder;
|
|
289
|
+
const isAsc = sortOrder === "asc";
|
|
290
|
+
let label = col.label;
|
|
291
|
+
if (col.sortable) {
|
|
292
|
+
label += isSorted ? isAsc ? " \u25B2" : " \u25BC" : " \u21C5";
|
|
293
|
+
}
|
|
294
|
+
return h("th", {
|
|
295
|
+
class: `wf-table-th${col.sortable ? " wf-table-th--sortable" : ""}${isSorted ? " wf-table-th--sorted" : ""}`,
|
|
200
296
|
scope: "col",
|
|
201
|
-
style: col.width ? { width: col.width } : void 0
|
|
202
|
-
|
|
203
|
-
|
|
297
|
+
style: col.width ? { width: col.width } : void 0,
|
|
298
|
+
onClick: col.sortable && onSort ? () => onSort(col.key, isSorted && isAsc ? "desc" : "asc") : void 0
|
|
299
|
+
}, label);
|
|
300
|
+
});
|
|
204
301
|
const headerRow = h("tr", { class: "wf-table-tr" }, headerCells);
|
|
205
302
|
const thead = h("thead", { class: "wf-table-thead" }, headerRow);
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
303
|
+
let bodyRows;
|
|
304
|
+
if (sortedData.length === 0 && emptyText) {
|
|
305
|
+
const colspan = columns.length;
|
|
306
|
+
bodyRows = [
|
|
307
|
+
h(
|
|
308
|
+
"tr",
|
|
309
|
+
{ class: "wf-table-tr" },
|
|
310
|
+
h("td", { class: "wf-table-td wf-table-empty", colspan, style: { textAlign: "center" } }, emptyText)
|
|
311
|
+
)
|
|
312
|
+
];
|
|
313
|
+
} else {
|
|
314
|
+
bodyRows = sortedData.map((row, i) => {
|
|
315
|
+
const cells = columns.map((col) => {
|
|
316
|
+
const val = row[col.key];
|
|
317
|
+
const content = col.render ? col.render(val, row, i) : String(val ?? "");
|
|
318
|
+
return h("td", { class: "wf-table-td" }, content);
|
|
319
|
+
});
|
|
320
|
+
return h("tr", {
|
|
321
|
+
class: "wf-table-tr",
|
|
322
|
+
onClick: onRowClick ? () => onRowClick(row, i) : void 0,
|
|
323
|
+
style: onRowClick ? { cursor: "pointer" } : void 0
|
|
324
|
+
}, cells);
|
|
211
325
|
});
|
|
212
|
-
|
|
213
|
-
class: "wf-table-tr",
|
|
214
|
-
onClick: onRowClick ? (e) => {
|
|
215
|
-
onRowClick(row, i);
|
|
216
|
-
} : void 0,
|
|
217
|
-
style: onRowClick ? { cursor: "pointer" } : void 0
|
|
218
|
-
}, cells);
|
|
219
|
-
});
|
|
326
|
+
}
|
|
220
327
|
const tbody = h("tbody", { class: "wf-table-tbody" }, bodyRows);
|
|
221
328
|
return h("table", { class: "wf-table" }, [thead, tbody]);
|
|
222
329
|
};
|
|
@@ -291,16 +398,19 @@ function trapFocus(container) {
|
|
|
291
398
|
// src/components/Modal/Modal.ts
|
|
292
399
|
var Modal = (_props, ctx) => {
|
|
293
400
|
let prevOpen;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
401
|
+
let focusCleanup;
|
|
402
|
+
const rootRef = (el) => {
|
|
403
|
+
if (el) {
|
|
404
|
+
lockScroll();
|
|
405
|
+
const modalEl = el.querySelector(".wf-modal") ?? el;
|
|
406
|
+
focusCleanup = trapFocus(modalEl);
|
|
407
|
+
} else {
|
|
298
408
|
unlockScroll();
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
}
|
|
409
|
+
focusCleanup?.();
|
|
410
|
+
}
|
|
411
|
+
};
|
|
302
412
|
return (props) => {
|
|
303
|
-
const { open, title, onClose, children, footer } = props;
|
|
413
|
+
const { open, title, onClose, children, footer, width, closable = true } = props;
|
|
304
414
|
const ML = ctx?.i18n?.components?.Modal ?? {};
|
|
305
415
|
if (prevOpen !== open) {
|
|
306
416
|
prevOpen = open;
|
|
@@ -310,19 +420,21 @@ var Modal = (_props, ctx) => {
|
|
|
310
420
|
class: "wf-modal-overlay",
|
|
311
421
|
onClick: onClose
|
|
312
422
|
});
|
|
313
|
-
const closeBtn = h("button", {
|
|
423
|
+
const closeBtn = closable ? h("button", {
|
|
314
424
|
class: "wf-modal-close",
|
|
315
425
|
onClick: onClose,
|
|
316
426
|
type: "button"
|
|
317
|
-
}, "\u2715");
|
|
318
|
-
const titleEl = title ? h("div", { class: "wf-modal-header" }, [title, closeBtn]) : null;
|
|
427
|
+
}, "\u2715") : null;
|
|
428
|
+
const titleEl = title ? h("div", { class: "wf-modal-header" }, [title, closeBtn].filter(Boolean)) : null;
|
|
319
429
|
const bodyEl = h("div", { class: "wf-modal-body" }, children);
|
|
320
430
|
const footerEl = footer ? h("div", { class: "wf-modal-footer" }, footer) : null;
|
|
321
431
|
const content = h("div", {
|
|
322
432
|
class: "wf-modal-content",
|
|
323
|
-
onClick: (e) => e.stopPropagation()
|
|
433
|
+
onClick: (e) => e.stopPropagation(),
|
|
434
|
+
style: width ? { minWidth: width, maxWidth: width } : void 0
|
|
324
435
|
}, [titleEl, bodyEl, footerEl].filter(Boolean));
|
|
325
436
|
const root = h("div", {
|
|
437
|
+
ref: rootRef,
|
|
326
438
|
class: "wf-modal wf-modal--enter",
|
|
327
439
|
role: "dialog",
|
|
328
440
|
"aria-modal": "true",
|
|
@@ -333,13 +445,25 @@ var Modal = (_props, ctx) => {
|
|
|
333
445
|
};
|
|
334
446
|
|
|
335
447
|
// src/components/Toast/Toast.ts
|
|
448
|
+
function positionClass(pos) {
|
|
449
|
+
const map = {
|
|
450
|
+
"top-right": "wf-toast--tr",
|
|
451
|
+
"top-left": "wf-toast--tl",
|
|
452
|
+
"bottom-right": "wf-toast--br",
|
|
453
|
+
"bottom-left": "wf-toast--bl",
|
|
454
|
+
"top-center": "wf-toast--tc"
|
|
455
|
+
};
|
|
456
|
+
return map[pos] ?? "wf-toast--tr";
|
|
457
|
+
}
|
|
336
458
|
var Toast = (_init, ctx) => (props) => {
|
|
337
|
-
const { toasts = [], onRemove } = props;
|
|
338
|
-
|
|
339
|
-
|
|
459
|
+
const { toasts = [], onRemove, position = "top-right", duration = 0, max = 0 } = props;
|
|
460
|
+
const visible = max > 0 && toasts.length > max ? toasts.slice(-max) : toasts;
|
|
461
|
+
if (visible.length === 0) return null;
|
|
462
|
+
const items = visible.map(
|
|
340
463
|
(t) => h("div", {
|
|
341
464
|
class: `wf-toast wf-toast--${t.type}`,
|
|
342
465
|
key: t.id,
|
|
466
|
+
"data-duration": (t.duration ?? duration) || void 0,
|
|
343
467
|
onClick: onRemove ? () => onRemove(t.id) : void 0
|
|
344
468
|
}, [
|
|
345
469
|
h("span", { class: "wf-toast-icon" }, iconFor(t.type)),
|
|
@@ -347,7 +471,10 @@ var Toast = (_init, ctx) => (props) => {
|
|
|
347
471
|
])
|
|
348
472
|
);
|
|
349
473
|
return createPortal(
|
|
350
|
-
h("div", {
|
|
474
|
+
h("div", {
|
|
475
|
+
class: `wf-toast-container ${positionClass(position)}`,
|
|
476
|
+
"data-max": max || void 0
|
|
477
|
+
}, items),
|
|
351
478
|
"toast"
|
|
352
479
|
);
|
|
353
480
|
};
|
|
@@ -431,10 +558,7 @@ var Tabs = (_init, _ctx) => (props) => {
|
|
|
431
558
|
|
|
432
559
|
// src/components/Dropdown/Dropdown.ts
|
|
433
560
|
var Dropdown = (_init, ctx) => {
|
|
434
|
-
let wrapEl;
|
|
435
|
-
ctx.ui.onmounted((el) => {
|
|
436
|
-
wrapEl = el;
|
|
437
|
-
});
|
|
561
|
+
let wrapEl = null;
|
|
438
562
|
return (props) => {
|
|
439
563
|
const { trigger, items = [], open } = props;
|
|
440
564
|
const pos = (() => {
|
|
@@ -459,7 +583,10 @@ var Dropdown = (_init, ctx) => {
|
|
|
459
583
|
}, menuItems) : null;
|
|
460
584
|
const portalContent = open ? createPortal(menu, "dropdown") : null;
|
|
461
585
|
return h("div", {
|
|
462
|
-
class: `wf-dropdown${open ? " wf-dropdown--open" : ""}
|
|
586
|
+
class: `wf-dropdown${open ? " wf-dropdown--open" : ""}`,
|
|
587
|
+
ref: (el) => {
|
|
588
|
+
wrapEl = el;
|
|
589
|
+
}
|
|
463
590
|
}, [trigger, portalContent].filter(Boolean));
|
|
464
591
|
};
|
|
465
592
|
};
|
|
@@ -607,15 +734,67 @@ var Steps = (_init, _ctx) => (props) => {
|
|
|
607
734
|
};
|
|
608
735
|
|
|
609
736
|
// src/components/Form/Form.ts
|
|
737
|
+
async function validateValues(values, rules) {
|
|
738
|
+
const errors = {};
|
|
739
|
+
for (const [field, fieldRules] of Object.entries(rules)) {
|
|
740
|
+
const val = values[field] ?? "";
|
|
741
|
+
for (const rule of fieldRules) {
|
|
742
|
+
if (rule.required && !String(val).trim()) {
|
|
743
|
+
errors[field] = rule.message;
|
|
744
|
+
break;
|
|
745
|
+
}
|
|
746
|
+
if (rule.pattern && !rule.pattern.test(String(val))) {
|
|
747
|
+
errors[field] = rule.message;
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
if (rule.minLength != null && String(val).length < rule.minLength) {
|
|
751
|
+
errors[field] = rule.message;
|
|
752
|
+
break;
|
|
753
|
+
}
|
|
754
|
+
if (rule.maxLength != null && String(val).length > rule.maxLength) {
|
|
755
|
+
errors[field] = rule.message;
|
|
756
|
+
break;
|
|
757
|
+
}
|
|
758
|
+
if (rule.validator) {
|
|
759
|
+
const result = await rule.validator(val);
|
|
760
|
+
if (result !== true) {
|
|
761
|
+
errors[field] = typeof result === "string" ? result : rule.message;
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return errors;
|
|
768
|
+
}
|
|
610
769
|
var Form = (_init, _ctx) => (props) => {
|
|
611
|
-
const { onSubmit, children } = props;
|
|
612
|
-
const handleSubmit = (e) => {
|
|
770
|
+
const { validation, onSubmit, onError, children } = props;
|
|
771
|
+
const handleSubmit = async (e) => {
|
|
613
772
|
e.preventDefault();
|
|
614
|
-
|
|
773
|
+
const form = e.target;
|
|
774
|
+
const data = new FormData(form);
|
|
775
|
+
const values = {};
|
|
776
|
+
for (const [key, val] of data.entries()) {
|
|
777
|
+
if (key in values) {
|
|
778
|
+
const prev = values[key];
|
|
779
|
+
values[key] = Array.isArray(prev) ? [...prev, val] : [prev, val];
|
|
780
|
+
} else {
|
|
781
|
+
values[key] = val;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (validation) {
|
|
785
|
+
const errors = await validateValues(values, validation);
|
|
786
|
+
if (Object.keys(errors).length > 0) {
|
|
787
|
+
onError?.(errors);
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
onError?.({});
|
|
791
|
+
}
|
|
792
|
+
await onSubmit?.(values);
|
|
615
793
|
};
|
|
616
794
|
return h("form", {
|
|
617
795
|
class: "wf-form",
|
|
618
|
-
onSubmit: handleSubmit
|
|
796
|
+
onSubmit: handleSubmit,
|
|
797
|
+
noValidate: validation ? true : void 0
|
|
619
798
|
}, children);
|
|
620
799
|
};
|
|
621
800
|
|
|
@@ -807,6 +986,7 @@ var FileUpload = (_init, ctx) => {
|
|
|
807
986
|
const updated = files.filter((_, idx) => idx !== i);
|
|
808
987
|
onChange?.(updated);
|
|
809
988
|
};
|
|
989
|
+
let fileInput = null;
|
|
810
990
|
const inputEl = h("input", {
|
|
811
991
|
type: "file",
|
|
812
992
|
class: "wf-upload-input",
|
|
@@ -814,14 +994,14 @@ var FileUpload = (_init, ctx) => {
|
|
|
814
994
|
multiple: multiple || void 0,
|
|
815
995
|
disabled: disabled || void 0,
|
|
816
996
|
onChange: handleChange,
|
|
817
|
-
style: { display: "none" }
|
|
997
|
+
style: { display: "none" },
|
|
998
|
+
ref: (el) => {
|
|
999
|
+
fileInput = el;
|
|
1000
|
+
}
|
|
818
1001
|
});
|
|
819
1002
|
const dropZone = h("div", {
|
|
820
1003
|
class: `wf-upload-zone${disabled ? " wf-upload-zone--disabled" : ""}${error ? " wf-upload-zone--err" : ""}`,
|
|
821
|
-
onClick: disabled ? void 0 : () =>
|
|
822
|
-
const input = document.querySelector(".wf-upload-input");
|
|
823
|
-
input?.click();
|
|
824
|
-
},
|
|
1004
|
+
onClick: disabled ? void 0 : () => fileInput?.click(),
|
|
825
1005
|
ref: dragRef
|
|
826
1006
|
}, children ?? h("div", { class: "wf-upload-placeholder" }, [
|
|
827
1007
|
h("span", { class: "wf-upload-icon" }, "\u{1F4C1}"),
|
|
@@ -917,14 +1097,17 @@ var Tooltip = (_props, ctx) => {
|
|
|
917
1097
|
// src/components/Drawer/Drawer.ts
|
|
918
1098
|
var Drawer = (_props, ctx) => {
|
|
919
1099
|
let prevOpen;
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1100
|
+
let focusCleanup;
|
|
1101
|
+
const rootRef = (el) => {
|
|
1102
|
+
if (el) {
|
|
1103
|
+
lockScroll();
|
|
1104
|
+
const panelEl = el.querySelector(".wf-drawer") ?? el;
|
|
1105
|
+
focusCleanup = trapFocus(panelEl);
|
|
1106
|
+
} else {
|
|
924
1107
|
unlockScroll();
|
|
925
|
-
|
|
926
|
-
}
|
|
927
|
-
}
|
|
1108
|
+
focusCleanup?.();
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
928
1111
|
return (props) => {
|
|
929
1112
|
const { open, title, position = "right", onClose, children, footer } = props;
|
|
930
1113
|
const DL = ctx?.i18n?.components?.Drawer ?? {};
|
|
@@ -950,10 +1133,15 @@ var Drawer = (_props, ctx) => {
|
|
|
950
1133
|
onClick: (e) => e.stopPropagation()
|
|
951
1134
|
}, [titleEl, bodyEl, footerEl].filter(Boolean));
|
|
952
1135
|
const root = h("div", {
|
|
1136
|
+
ref: rootRef,
|
|
953
1137
|
class: `wf-drawer wf-drawer--${position} wf-drawer--enter`,
|
|
954
1138
|
role: "dialog",
|
|
955
1139
|
"aria-modal": "true",
|
|
956
|
-
"aria-label": title ?? (DL.ariaLabel ?? "\u4FA7\u8FB9\u9762\u677F")
|
|
1140
|
+
"aria-label": title ?? (DL.ariaLabel ?? "\u4FA7\u8FB9\u9762\u677F"),
|
|
1141
|
+
tabIndex: -1,
|
|
1142
|
+
onKeyDown: (e) => {
|
|
1143
|
+
if (e.key === "Escape") onClose?.();
|
|
1144
|
+
}
|
|
957
1145
|
}, [overlay, panel]);
|
|
958
1146
|
return createPortal(root, "drawer");
|
|
959
1147
|
};
|
|
@@ -975,7 +1163,6 @@ var Popover = (_props, ctx) => {
|
|
|
975
1163
|
};
|
|
976
1164
|
const updatePos = (e) => {
|
|
977
1165
|
pos = computeFixedPos(e.currentTarget, position, 6, true);
|
|
978
|
-
ctx.ui.render();
|
|
979
1166
|
};
|
|
980
1167
|
const onClick = trigger === "click" && !disabled ? (e) => {
|
|
981
1168
|
updatePos(e);
|
|
@@ -1003,7 +1190,7 @@ var Popover = (_props, ctx) => {
|
|
|
1003
1190
|
}
|
|
1004
1191
|
}) : null;
|
|
1005
1192
|
const popover = isOpen ? h("div", {
|
|
1006
|
-
class:
|
|
1193
|
+
class: `wf-popover wf-popover--${position} wf-popover--enter`,
|
|
1007
1194
|
style: { top: p.top, left: p.left },
|
|
1008
1195
|
role: "tooltip"
|
|
1009
1196
|
}, [
|
|
@@ -1030,6 +1217,20 @@ var Skeleton = (_init) => (props) => {
|
|
|
1030
1217
|
`wf-skeleton--${variant}`,
|
|
1031
1218
|
className
|
|
1032
1219
|
].filter(Boolean).join(" ");
|
|
1220
|
+
if (variant === "table") {
|
|
1221
|
+
const cols = props.cols ?? 3;
|
|
1222
|
+
const rows = Array.from({ length: lines }, (_, r) => {
|
|
1223
|
+
const cells = Array.from({ length: cols }, (_2, c) => {
|
|
1224
|
+
const cellW = r === lines - 1 && c === cols - 1 ? "40%" : void 0;
|
|
1225
|
+
return h("div", {
|
|
1226
|
+
class: "wf-skeleton wf-skeleton--text",
|
|
1227
|
+
style: cellW ? { width: cellW } : void 0
|
|
1228
|
+
});
|
|
1229
|
+
});
|
|
1230
|
+
return h("div", { class: "wf-skeleton-row" }, cells);
|
|
1231
|
+
});
|
|
1232
|
+
return h("div", { class: "wf-skeleton-table" }, rows);
|
|
1233
|
+
}
|
|
1033
1234
|
if (lines <= 1) {
|
|
1034
1235
|
return h("div", { class: cls, style: Object.keys(style).length ? style : void 0 });
|
|
1035
1236
|
}
|
|
@@ -1066,20 +1267,19 @@ var InView = (_props, ctx) => {
|
|
|
1066
1267
|
let inView = false;
|
|
1067
1268
|
let entered = false;
|
|
1068
1269
|
let io;
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
return () => {
|
|
1270
|
+
const sentinelRef = (el) => {
|
|
1271
|
+
if (el) {
|
|
1272
|
+
io = new IntersectionObserver((entries) => {
|
|
1273
|
+
if (entries[0]?.isIntersecting) {
|
|
1274
|
+
inView = true;
|
|
1275
|
+
ctx.ui.render();
|
|
1276
|
+
}
|
|
1277
|
+
}, { threshold: _props.threshold ?? 0, rootMargin: _props.rootMargin ?? "0px" });
|
|
1278
|
+
io.observe(el);
|
|
1279
|
+
} else {
|
|
1080
1280
|
io?.disconnect();
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1083
1283
|
return (props) => {
|
|
1084
1284
|
if (inView) {
|
|
1085
1285
|
if (!entered) {
|
|
@@ -1094,7 +1294,11 @@ var InView = (_props, ctx) => {
|
|
|
1094
1294
|
return h("div", {
|
|
1095
1295
|
class: "wf-inview wf-inview--pending"
|
|
1096
1296
|
}, [
|
|
1097
|
-
h("div", {
|
|
1297
|
+
h("div", {
|
|
1298
|
+
class: "wf-inview-pending",
|
|
1299
|
+
style: { width: "1px", height: "1px", opacity: 0, pointerEvents: "none" },
|
|
1300
|
+
ref: sentinelRef
|
|
1301
|
+
}),
|
|
1098
1302
|
placeholderEl
|
|
1099
1303
|
]);
|
|
1100
1304
|
};
|
|
@@ -1192,10 +1396,7 @@ var DatePicker = (_props, ctx) => {
|
|
|
1192
1396
|
let selDay = now.getDate();
|
|
1193
1397
|
let rangeStart = null;
|
|
1194
1398
|
let rangeEnd = null;
|
|
1195
|
-
let inputEl;
|
|
1196
|
-
ctx.ui.onmounted((el) => {
|
|
1197
|
-
inputEl = el.querySelector(".wf-datepicker-input");
|
|
1198
|
-
});
|
|
1399
|
+
let inputEl = null;
|
|
1199
1400
|
return (props) => {
|
|
1200
1401
|
const { mode = "date", value, onChange, placeholder = L.placeholder ?? "\u9009\u62E9\u65E5\u671F", disabled } = props;
|
|
1201
1402
|
const isOpen = show;
|
|
@@ -1455,6 +1656,9 @@ var DatePicker = (_props, ctx) => {
|
|
|
1455
1656
|
type: "text",
|
|
1456
1657
|
placeholder,
|
|
1457
1658
|
value: displayValue || "",
|
|
1659
|
+
ref: (el) => {
|
|
1660
|
+
inputEl = el;
|
|
1661
|
+
},
|
|
1458
1662
|
readonly: true,
|
|
1459
1663
|
disabled,
|
|
1460
1664
|
onClick: toggle
|
|
@@ -2011,7 +2215,21 @@ var Editor = (_props, ctx) => {
|
|
|
2011
2215
|
let tableHoverRow = -1;
|
|
2012
2216
|
let tableHoverCol = -1;
|
|
2013
2217
|
let sourceText = "";
|
|
2014
|
-
let editorEl;
|
|
2218
|
+
let editorEl = null;
|
|
2219
|
+
let savedRange = null;
|
|
2220
|
+
const saveSelection = () => {
|
|
2221
|
+
const sel = window.getSelection();
|
|
2222
|
+
if (sel && sel.rangeCount > 0) savedRange = sel.getRangeAt(0);
|
|
2223
|
+
};
|
|
2224
|
+
const restoreSelection = () => {
|
|
2225
|
+
if (!editorEl || !savedRange) return;
|
|
2226
|
+
editorEl.focus();
|
|
2227
|
+
const sel = window.getSelection();
|
|
2228
|
+
if (sel) {
|
|
2229
|
+
sel.removeAllRanges();
|
|
2230
|
+
sel.addRange(savedRange);
|
|
2231
|
+
}
|
|
2232
|
+
};
|
|
2015
2233
|
return (props) => {
|
|
2016
2234
|
const { value = "", onChange, onUpload, placeholder = "", disabled = false, minHeight = "200px" } = props;
|
|
2017
2235
|
const toolbarItems = props.toolbar ?? DEFAULT_TOOLBAR;
|
|
@@ -2042,6 +2260,7 @@ var Editor = (_props, ctx) => {
|
|
|
2042
2260
|
return;
|
|
2043
2261
|
}
|
|
2044
2262
|
if (item === "link") {
|
|
2263
|
+
saveSelection();
|
|
2045
2264
|
const sel = window.getSelection();
|
|
2046
2265
|
if (!sel || sel.isCollapsed) {
|
|
2047
2266
|
showLinkInput = true;
|
|
@@ -2070,7 +2289,7 @@ var Editor = (_props, ctx) => {
|
|
|
2070
2289
|
showLinkInput = false;
|
|
2071
2290
|
ctx.ui.render();
|
|
2072
2291
|
if (!url) return;
|
|
2073
|
-
|
|
2292
|
+
editorEl?.focus();
|
|
2074
2293
|
exec("createLink", url);
|
|
2075
2294
|
activeFormats = queryFormats();
|
|
2076
2295
|
if (editorEl && onChange) emitChange(editorEl.innerHTML);
|
|
@@ -2107,7 +2326,7 @@ var Editor = (_props, ctx) => {
|
|
|
2107
2326
|
showImageInput = false;
|
|
2108
2327
|
imageUrl = "";
|
|
2109
2328
|
ctx.ui.render();
|
|
2110
|
-
|
|
2329
|
+
editorEl?.focus();
|
|
2111
2330
|
insertImageFn(url);
|
|
2112
2331
|
};
|
|
2113
2332
|
const cancelImage = () => {
|
|
@@ -2120,7 +2339,7 @@ var Editor = (_props, ctx) => {
|
|
|
2120
2339
|
tableHoverRow = -1;
|
|
2121
2340
|
tableHoverCol = -1;
|
|
2122
2341
|
ctx.ui.render();
|
|
2123
|
-
|
|
2342
|
+
restoreSelection();
|
|
2124
2343
|
insertTable(rows, cols);
|
|
2125
2344
|
if (editorEl && onChange) emitChange(editorEl.innerHTML);
|
|
2126
2345
|
};
|
|
@@ -2166,14 +2385,9 @@ var Editor = (_props, ctx) => {
|
|
|
2166
2385
|
const val = e.target.value;
|
|
2167
2386
|
onChange?.(val);
|
|
2168
2387
|
};
|
|
2169
|
-
const editorRef = (el) => {
|
|
2170
|
-
if (el) editorEl = el;
|
|
2171
|
-
return () => {
|
|
2172
|
-
editorEl = void 0;
|
|
2173
|
-
};
|
|
2174
|
-
};
|
|
2175
2388
|
const handleKeyUp = (e) => {
|
|
2176
2389
|
if (disabled || !isRichMode) return;
|
|
2390
|
+
saveSelection();
|
|
2177
2391
|
const isFormatShortcut = (e.ctrlKey || e.metaKey) && ["b", "i", "u"].includes(e.key.toLowerCase());
|
|
2178
2392
|
if (isFormatShortcut) {
|
|
2179
2393
|
activeFormats = queryFormats();
|
|
@@ -2183,6 +2397,7 @@ var Editor = (_props, ctx) => {
|
|
|
2183
2397
|
};
|
|
2184
2398
|
const handleMouseUp = () => {
|
|
2185
2399
|
if (!isRichMode) return;
|
|
2400
|
+
saveSelection();
|
|
2186
2401
|
activeFormats = queryFormats();
|
|
2187
2402
|
ctx.ui.render();
|
|
2188
2403
|
};
|
|
@@ -2209,10 +2424,7 @@ var Editor = (_props, ctx) => {
|
|
|
2209
2424
|
h("button", {
|
|
2210
2425
|
class: "wf-btn wf-btn--primary wf-btn--sm",
|
|
2211
2426
|
type: "button",
|
|
2212
|
-
onClick: () =>
|
|
2213
|
-
const input = document.querySelector("[data-editor-link-input]");
|
|
2214
|
-
confirmLink(input?.value ?? "");
|
|
2215
|
-
}
|
|
2427
|
+
onClick: () => confirmLink(linkUrl)
|
|
2216
2428
|
}, "\u786E\u5B9A")
|
|
2217
2429
|
]
|
|
2218
2430
|
},
|
|
@@ -2273,10 +2485,7 @@ var Editor = (_props, ctx) => {
|
|
|
2273
2485
|
class: "wf-btn wf-btn--primary wf-btn--sm",
|
|
2274
2486
|
type: "button",
|
|
2275
2487
|
disabled: imageUploading || void 0,
|
|
2276
|
-
onClick: () =>
|
|
2277
|
-
const input = document.querySelector("[data-image-input]");
|
|
2278
|
-
confirmImageUrl(input?.value ?? "");
|
|
2279
|
-
}
|
|
2488
|
+
onClick: () => confirmImageUrl(imageUrl)
|
|
2280
2489
|
}, onUpload ? "\u63D2\u5165" : "\u786E\u5B9A")
|
|
2281
2490
|
]
|
|
2282
2491
|
},
|
|
@@ -2299,7 +2508,9 @@ var Editor = (_props, ctx) => {
|
|
|
2299
2508
|
onKeyUp: handleKeyUp,
|
|
2300
2509
|
onMouseUp: handleMouseUp,
|
|
2301
2510
|
onMouseDown: handleMouseDown,
|
|
2302
|
-
ref:
|
|
2511
|
+
ref: (el) => {
|
|
2512
|
+
editorEl = el;
|
|
2513
|
+
}
|
|
2303
2514
|
});
|
|
2304
2515
|
} else {
|
|
2305
2516
|
editorBody = h("textarea", {
|
|
@@ -2317,9 +2528,9 @@ var Editor = (_props, ctx) => {
|
|
|
2317
2528
|
class: `wf-editor${disabled ? " wf-editor--disabled" : ""}`
|
|
2318
2529
|
}, [
|
|
2319
2530
|
!disabled && toolbarItems.length > 0 ? renderToolbar(toolbarItems, activeFormats, !isRichMode, handleToolbarItem, customRender) : null,
|
|
2531
|
+
editorBody,
|
|
2320
2532
|
linkModal,
|
|
2321
2533
|
imageModal,
|
|
2322
|
-
editorBody,
|
|
2323
2534
|
h("input", { type: "hidden", value, "aria-hidden": "true" })
|
|
2324
2535
|
]);
|
|
2325
2536
|
};
|