@wipco/sdui 1.8.2 → 1.9.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.
Files changed (83) hide show
  1. package/dist/{chunk-DTCZPXOT.js → chunk-33LRJ25P.js} +199 -21
  2. package/dist/{chunk-PN5IJPA5.js → chunk-3LPLTD66.js} +1 -1
  3. package/dist/{chunk-TCHXA35K.js → chunk-3M64LBYZ.js} +2 -2
  4. package/dist/{chunk-ZDWCLHIY.js → chunk-4FQB6O4T.js} +5 -5
  5. package/dist/{chunk-TK3WS7XE.js → chunk-55524GIB.js} +2 -2
  6. package/dist/{chunk-JDTVNS3H.js → chunk-5NDYDUMJ.js} +1 -1
  7. package/dist/{chunk-YOLT2TPX.js → chunk-A2PG44CM.js} +1 -1
  8. package/dist/{chunk-YK7ZNV2C.js → chunk-CZMSQ3B3.js} +1 -1
  9. package/dist/{chunk-KVQXQLAP.js → chunk-DE3HYL4K.js} +2 -2
  10. package/dist/{chunk-3PGKBTBZ.js → chunk-DELAII7K.js} +2 -2
  11. package/dist/{chunk-ZW42VDR3.js → chunk-F2ICWCV3.js} +1 -1
  12. package/dist/{chunk-KJDHF6VU.js → chunk-FR7S52ZL.js} +1 -1
  13. package/dist/{chunk-HAK2YXSF.js → chunk-GHKRT7EA.js} +1 -1
  14. package/dist/{chunk-JRCHWX2B.js → chunk-GUXKGL76.js} +1 -1
  15. package/dist/{chunk-37CLBWCE.js → chunk-GW2LSUA4.js} +1 -1
  16. package/dist/{chunk-B6U2YWUP.js → chunk-HKYLKLF6.js} +2 -2
  17. package/dist/{chunk-UNQ6VAVD.js → chunk-I45MRYCE.js} +2 -2
  18. package/dist/{chunk-IWLLM45X.js → chunk-IOQNDAWT.js} +225 -42
  19. package/dist/{chunk-YJJMK5R5.js → chunk-J2SPMIMO.js} +2 -2
  20. package/dist/{chunk-UDJVLMDH.js → chunk-JHWJSVZH.js} +2 -2
  21. package/dist/{chunk-5JXXCRXA.js → chunk-LDIEWJNP.js} +2 -2
  22. package/dist/{chunk-K7K6WOIG.js → chunk-LEYVJAXU.js} +3 -3
  23. package/dist/{chunk-OI2GPBIL.js → chunk-LK7MHTJO.js} +2 -2
  24. package/dist/{chunk-QP7AQEGZ.js → chunk-LNEFMVHL.js} +3 -3
  25. package/dist/{chunk-I2URQNZZ.js → chunk-MIFCOTLQ.js} +9 -7
  26. package/dist/{chunk-TQV4M3SB.js → chunk-MRCTYYBS.js} +2 -2
  27. package/dist/{chunk-DNUO63VZ.js → chunk-NHKQZDBX.js} +2 -2
  28. package/dist/{chunk-KIHN7DGA.js → chunk-NKRZVRGH.js} +206 -6
  29. package/dist/{chunk-4SVSS7VO.js → chunk-NTMFLJEE.js} +4 -4
  30. package/dist/{chunk-XFNHHGFR.js → chunk-RMYGRGKS.js} +1 -1
  31. package/dist/{chunk-O3SD2HS6.js → chunk-RT2I2U45.js} +1 -1
  32. package/dist/{chunk-ITFSPOOB.js → chunk-SANCYRIQ.js} +1 -1
  33. package/dist/{chunk-H7RLEDKJ.js → chunk-SMVPMDWO.js} +2 -2
  34. package/dist/{chunk-PGAP2RLS.js → chunk-TYPNHH3I.js} +1 -1
  35. package/dist/{chunk-6TWP3E2L.js → chunk-UX37MB4P.js} +3 -3
  36. package/dist/{chunk-LONXOEZY.js → chunk-UYOQ3SEG.js} +1 -1
  37. package/dist/{chunk-CUAGMSSG.js → chunk-VGNLXT3A.js} +1 -1
  38. package/dist/{chunk-LGKLA22B.js → chunk-VSCAW4LS.js} +1 -1
  39. package/dist/{chunk-AMKIMOTU.js → chunk-YMJUK3V4.js} +2 -2
  40. package/dist/{chunk-FXEKHHEA.js → chunk-Z2SOMUZF.js} +1 -1
  41. package/dist/{chunk-DDX7KJAW.js → chunk-Z5Q44VXX.js} +1 -1
  42. package/dist/{chunk-WW65XEEE.js → chunk-ZHWBTWHS.js} +2 -2
  43. package/dist/index.d.ts +40 -5
  44. package/dist/index.js +16 -16
  45. package/dist/meta.js +67 -8
  46. package/dist/rich/ExcelUploadCard.js +3 -3
  47. package/dist/rich.js +5 -5
  48. package/dist/widgets/ApprovalLineEditor.js +7 -7
  49. package/dist/widgets/ApprovalOverridesEditor.js +9 -9
  50. package/dist/widgets/ApprovalStepper.js +2 -2
  51. package/dist/widgets/AutocompleteField.d.ts +29 -3
  52. package/dist/widgets/AutocompleteField.js +7 -7
  53. package/dist/widgets/ColumnBoard.js +2 -2
  54. package/dist/widgets/DiffView.js +2 -2
  55. package/dist/widgets/Disclosure.js +2 -2
  56. package/dist/widgets/EventCalendar.js +3 -3
  57. package/dist/widgets/FileDropzone.d.ts +8 -0
  58. package/dist/widgets/FileDropzone.js +5 -5
  59. package/dist/widgets/ImageLightbox.js +3 -3
  60. package/dist/widgets/InlineEdit.js +2 -2
  61. package/dist/widgets/JsonField.js +2 -2
  62. package/dist/widgets/OptionSchemaEditor.js +3 -3
  63. package/dist/widgets/OptionValueFields.js +3 -3
  64. package/dist/widgets/OrgChart.js +2 -2
  65. package/dist/widgets/OrgChartBoard.js +5 -5
  66. package/dist/widgets/PeriodFilter.js +4 -4
  67. package/dist/widgets/PermissionMatrixEditor.js +3 -3
  68. package/dist/widgets/PositionSelect.js +3 -3
  69. package/dist/widgets/PrintSheet.js +2 -2
  70. package/dist/widgets/ProfileEditDiffCard.js +3 -3
  71. package/dist/widgets/QRDisplay.js +3 -3
  72. package/dist/widgets/RankBoard.js +4 -4
  73. package/dist/widgets/RoleMemberPicker.js +4 -4
  74. package/dist/widgets/SearchableMultiPicker.js +5 -5
  75. package/dist/widgets/SecureScreen.js +2 -2
  76. package/dist/widgets/StagePeriodEditor.js +4 -4
  77. package/dist/widgets/TagInput.js +2 -2
  78. package/dist/widgets/TagMultiSelect.js +3 -3
  79. package/dist/widgets/Timeline.js +3 -3
  80. package/dist/widgets/TreePicker.js +6 -6
  81. package/dist/widgets/TreeView.js +5 -5
  82. package/dist/widgets/index.js +71 -71
  83. package/package.json +1 -1
@@ -1,11 +1,103 @@
1
- import { ImageLightbox } from './chunk-JDTVNS3H.js';
2
- import { useSduiSandbox, useSduiAdapter, hostRawFetchOf, defaultAdapter, useSduiAssetResolver } from './chunk-XFNHHGFR.js';
3
- import { Spinner, Icon, IconButton } from './chunk-KIHN7DGA.js';
1
+ import { ImageLightbox } from './chunk-5NDYDUMJ.js';
2
+ import { useSduiSandbox, useSduiAdapter, hostRawFetchOf, defaultAdapter, useSduiAssetResolver } from './chunk-RMYGRGKS.js';
3
+ import { Spinner, Icon, IconButton } from './chunk-NKRZVRGH.js';
4
4
  import { boxed } from './chunk-3JTBOABA.js';
5
5
  import { useState, useRef, useEffect, useCallback } from 'react';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  var THUMB_SIZE = 72;
9
+ var FILE_TILE_WIDTH = 168;
10
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
11
+ "jpg",
12
+ "jpeg",
13
+ "jpe",
14
+ "jfif",
15
+ "pjpeg",
16
+ "pjp",
17
+ "png",
18
+ "apng",
19
+ "gif",
20
+ "webp",
21
+ "avif",
22
+ "bmp",
23
+ "svg",
24
+ "ico",
25
+ "heic",
26
+ "heif",
27
+ "tif",
28
+ "tiff"
29
+ ]);
30
+ var MIME_SHAPE = /^[a-z0-9][\w.+-]*\/[\w.+-]+/i;
31
+ function urlOf(item) {
32
+ return typeof item.url === "string" ? item.url : "";
33
+ }
34
+ function itemMime(item) {
35
+ const record = item;
36
+ for (const key of ["mimeType", "mime_type", "type"]) {
37
+ const value = record[key];
38
+ if (typeof value === "string" && MIME_SHAPE.test(value.trim())) return value.trim().toLowerCase();
39
+ }
40
+ return null;
41
+ }
42
+ function extensionOfPath(path) {
43
+ const segment = path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1);
44
+ const dot = segment.lastIndexOf(".");
45
+ if (dot <= 0) return null;
46
+ const ext = segment.slice(dot + 1).toLowerCase();
47
+ return /^[a-z0-9]{1,10}$/.test(ext) ? ext : null;
48
+ }
49
+ function extensionOfUrl(url) {
50
+ if (/^(blob|data):/i.test(url.trim())) return null;
51
+ return extensionOfPath(url.split(/[?#]/, 1)[0]);
52
+ }
53
+ function dataUrlMime(url) {
54
+ const match = /^data:([^;,]+)/i.exec(url.trim());
55
+ return match && MIME_SHAPE.test(match[1]) ? match[1].toLowerCase() : null;
56
+ }
57
+ function itemLooksLikeImage(item, fileType) {
58
+ const mime = itemMime(item) ?? (fileType && MIME_SHAPE.test(fileType) ? fileType.toLowerCase() : null) ?? dataUrlMime(urlOf(item));
59
+ if (mime) return mime.startsWith("image/");
60
+ const ext = extensionOfUrl(urlOf(item)) ?? (item.name ? extensionOfPath(item.name) : null);
61
+ if (ext) return IMAGE_EXTENSIONS.has(ext);
62
+ return true;
63
+ }
64
+ function fileBadgeOf(item, fileType) {
65
+ const ext = (item.name ? extensionOfPath(item.name) : null) ?? extensionOfUrl(urlOf(item));
66
+ if (ext) return ext.toUpperCase();
67
+ const mime = itemMime(item) ?? (fileType && MIME_SHAPE.test(fileType) ? fileType.toLowerCase() : null);
68
+ const subtype = mime?.split("/")[1]?.split(/[;+]/)[0];
69
+ return subtype && /^[a-z0-9]{1,5}$/.test(subtype) ? subtype.toUpperCase() : null;
70
+ }
71
+ function displayNameOf(item) {
72
+ if (item.name && item.name.trim() !== "") return item.name;
73
+ const url = urlOf(item);
74
+ if (!/^(blob|data):/i.test(url.trim())) {
75
+ const path = url.split(/[?#]/, 1)[0];
76
+ const segment = path.slice(path.lastIndexOf("/") + 1);
77
+ if (segment !== "") {
78
+ try {
79
+ return decodeURIComponent(segment);
80
+ } catch {
81
+ return segment;
82
+ }
83
+ }
84
+ }
85
+ return "\uCCA8\uBD80 \uD30C\uC77C";
86
+ }
87
+ function safeFileHref(url) {
88
+ const value = url.replace(/[\u0000-\u0020]/g, "");
89
+ if (value === "") return null;
90
+ const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(value);
91
+ if (!scheme) return url;
92
+ return /^(https?|blob)$/i.test(scheme[1]) ? url : null;
93
+ }
94
+ function acceptIsImageOnly(accept) {
95
+ const rules = accept.split(",").map((rule) => rule.trim().toLowerCase()).filter(Boolean);
96
+ if (rules.length === 0) return false;
97
+ return rules.every(
98
+ (rule) => rule.startsWith(".") ? IMAGE_EXTENSIONS.has(rule.slice(1)) : rule.startsWith("image/")
99
+ );
100
+ }
9
101
  function matchesAccept(file, accept) {
10
102
  const rules = accept.split(",").map((rule) => rule.trim().toLowerCase()).filter(Boolean);
11
103
  if (rules.length === 0) return true;
@@ -65,6 +157,10 @@ function FileDropzoneImpl({
65
157
  const inputRef = useRef(null);
66
158
  const dragDepthRef = useRef(0);
67
159
  const createdUrlsRef = useRef(/* @__PURE__ */ new Set());
160
+ const fileTypesRef = useRef(/* @__PURE__ */ new Map());
161
+ const rememberFileType = (id, file) => {
162
+ if (file.type) fileTypesRef.current.set(id, file.type);
163
+ };
68
164
  useEffect(() => {
69
165
  const created = createdUrlsRef.current;
70
166
  return () => created.forEach((url) => URL.revokeObjectURL(url));
@@ -93,6 +189,7 @@ function FileDropzoneImpl({
93
189
  try {
94
190
  const item = await upload(file);
95
191
  if (item && typeof item.id === "string" && typeof item.url === "string") {
192
+ rememberFileType(item.id, file);
96
193
  commit([...itemsRef.current, { name: file.name, ...item }]);
97
194
  } else {
98
195
  failures.push(`${file.name} (\uC5C5\uB85C\uB354\uAC00 \uD56D\uBAA9\uC744 \uC8FC\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4)`);
@@ -116,10 +213,11 @@ function FileDropzoneImpl({
116
213
  } else {
117
214
  const json = await res.json().catch(() => null);
118
215
  const body = unwrapUploaded(json);
119
- const id = body?.id;
216
+ const id2 = body?.id;
120
217
  const url2 = body?.url;
121
- if ((typeof id === "string" || typeof id === "number") && typeof url2 === "string") {
122
- commit([...itemsRef.current, { id: String(id), url: url2, name: file.name }]);
218
+ if ((typeof id2 === "string" || typeof id2 === "number") && typeof url2 === "string") {
219
+ rememberFileType(String(id2), file);
220
+ commit([...itemsRef.current, { id: String(id2), url: url2, name: file.name }]);
123
221
  } else {
124
222
  failures.push(`${file.name} (\uC751\uB2F5 \uD615\uC2DD \uC624\uB958)`);
125
223
  }
@@ -132,7 +230,9 @@ function FileDropzoneImpl({
132
230
  }
133
231
  const url = URL.createObjectURL(file);
134
232
  createdUrlsRef.current.add(url);
135
- commit([...itemsRef.current, { id: localId(), url, name: file.name }]);
233
+ const id = localId();
234
+ rememberFileType(id, file);
235
+ commit([...itemsRef.current, { id, url, name: file.name }]);
136
236
  }
137
237
  } finally {
138
238
  setProgress(null);
@@ -177,6 +277,7 @@ function FileDropzoneImpl({
177
277
  (item) => {
178
278
  const forget = () => {
179
279
  commit(itemsRef.current.filter((current) => current.id !== item.id));
280
+ fileTypesRef.current.delete(item.id);
180
281
  if (createdUrlsRef.current.has(item.url)) {
181
282
  URL.revokeObjectURL(item.url);
182
283
  createdUrlsRef.current.delete(item.url);
@@ -208,6 +309,7 @@ function FileDropzoneImpl({
208
309
  };
209
310
  const showLocalCaption = localMode || items.some((item) => item.id.startsWith("local-"));
210
311
  const dropTinted = canAdd && (dragOver || hovering);
312
+ const imageOnly = acceptIsImageOnly(accept);
211
313
  return /* @__PURE__ */ jsxs("div", { className: "wp-col", style: { gap: "var(--wp-space-2)" }, children: [
212
314
  /* @__PURE__ */ jsx(
213
315
  "input",
@@ -231,7 +333,7 @@ function FileDropzoneImpl({
231
333
  role: "button",
232
334
  tabIndex: canAdd ? 0 : -1,
233
335
  "aria-disabled": !canAdd,
234
- "aria-label": "\uC774\uBBF8\uC9C0 \uCCA8\uBD80",
336
+ "aria-label": imageOnly ? "\uC774\uBBF8\uC9C0 \uCCA8\uBD80" : "\uD30C\uC77C \uCCA8\uBD80",
235
337
  onClick: openPicker,
236
338
  onKeyDown: (event) => {
237
339
  if (canAdd && (event.key === "Enter" || event.key === " ")) {
@@ -284,7 +386,7 @@ function FileDropzoneImpl({
284
386
  style: { color: dropTinted ? "var(--wp-text-brand)" : "var(--wp-text-muted)" }
285
387
  }
286
388
  ),
287
- /* @__PURE__ */ jsx("span", { className: "wp-body-sm", style: { color: "var(--wp-text-default)" }, children: atCapacity ? `\uCD5C\uB300 ${maxCount}\uAC1C\uAE4C\uC9C0 \uCCA8\uBD80\uD588\uC2B5\uB2C8\uB2E4` : "\uD074\uB9AD\uD558\uAC70\uB098 \uC774\uBBF8\uC9C0\uB97C \uB04C\uC5B4\uB2E4 \uB193\uC73C\uC138\uC694" }),
389
+ /* @__PURE__ */ jsx("span", { className: "wp-body-sm", style: { color: "var(--wp-text-default)" }, children: atCapacity ? `\uCD5C\uB300 ${maxCount}\uAC1C\uAE4C\uC9C0 \uCCA8\uBD80\uD588\uC2B5\uB2C8\uB2E4` : `\uD074\uB9AD\uD558\uAC70\uB098 ${imageOnly ? "\uC774\uBBF8\uC9C0\uB97C" : "\uD30C\uC77C\uC744"} \uB04C\uC5B4\uB2E4 \uB193\uC73C\uC138\uC694` }),
288
390
  hint ? /* @__PURE__ */ jsx("span", { className: "wp-caption", children: hint }) : null
289
391
  ] })
290
392
  }
@@ -318,47 +420,128 @@ function FileDropzoneImpl({
318
420
  }
319
421
  ) : null,
320
422
  items.length > 0 ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "var(--wp-space-2)" }, children: items.map((item) => {
321
- const thumbSrc = resolveAsset(item.url, {
423
+ const fileType = fileTypesRef.current.get(item.id);
424
+ const asImage = itemLooksLikeImage(item, fileType);
425
+ const resolved = resolveAsset(item.url, {
322
426
  component: "FileDropzone",
323
- prop: "src",
427
+ prop: asImage ? "src" : "href",
324
428
  kind: "attribute"
325
429
  });
430
+ const hovered = hoverItemId === item.id;
431
+ let preview;
432
+ if (asImage) {
433
+ preview = resolved === null ? /* @__PURE__ */ jsx(
434
+ "span",
435
+ {
436
+ "aria-label": item.name ?? "\uCCA8\uBD80 \uBBF8\uB9AC\uBCF4\uAE30 \uC5C6\uC74C",
437
+ role: "img",
438
+ style: {
439
+ display: "block",
440
+ width: THUMB_SIZE,
441
+ height: THUMB_SIZE,
442
+ borderRadius: "var(--wp-radius-md)",
443
+ border: "var(--wp-border-w) solid var(--wp-border-subtle)",
444
+ background: "var(--wp-surface-sunken)"
445
+ }
446
+ }
447
+ ) : /* @__PURE__ */ jsx(
448
+ ImageLightbox,
449
+ {
450
+ src: resolved,
451
+ alt: item.name,
452
+ thumbStyle: {
453
+ width: THUMB_SIZE,
454
+ height: THUMB_SIZE,
455
+ objectFit: "cover",
456
+ display: "block",
457
+ borderRadius: "var(--wp-radius-md)",
458
+ border: "var(--wp-border-w) solid var(--wp-border-subtle)"
459
+ }
460
+ }
461
+ );
462
+ } else {
463
+ const href = sandbox || resolved === null ? null : safeFileHref(resolved);
464
+ const displayName = displayNameOf(item);
465
+ const badge = fileBadgeOf(item, fileType);
466
+ const tileStyle = {
467
+ display: "flex",
468
+ alignItems: "center",
469
+ gap: "var(--wp-space-2)",
470
+ boxSizing: "border-box",
471
+ width: FILE_TILE_WIDTH,
472
+ height: THUMB_SIZE,
473
+ padding: "0 var(--wp-space-2)",
474
+ borderRadius: "var(--wp-radius-md)",
475
+ border: `var(--wp-border-w) solid ${hovered && href ? "var(--wp-border-strong)" : "var(--wp-border-subtle)"}`,
476
+ background: "var(--wp-surface-sunken)",
477
+ color: "var(--wp-text-default)",
478
+ textDecoration: "none",
479
+ transition: "var(--wp-transition-surface)"
480
+ };
481
+ const tileBody = /* @__PURE__ */ jsxs(Fragment, { children: [
482
+ /* @__PURE__ */ jsxs(
483
+ "span",
484
+ {
485
+ style: {
486
+ display: "flex",
487
+ flexDirection: "column",
488
+ alignItems: "center",
489
+ gap: 2,
490
+ flex: "none",
491
+ minWidth: 28,
492
+ color: "var(--wp-text-muted)"
493
+ },
494
+ children: [
495
+ /* @__PURE__ */ jsx(Icon, { name: "file-text", size: 24 }),
496
+ badge ? /* @__PURE__ */ jsx("span", { className: "wp-overline", style: { lineHeight: 1 }, children: badge }) : null
497
+ ]
498
+ }
499
+ ),
500
+ /* @__PURE__ */ jsx(
501
+ "span",
502
+ {
503
+ className: "wp-caption",
504
+ style: {
505
+ flex: 1,
506
+ minWidth: 0,
507
+ color: "var(--wp-text-default)",
508
+ display: "-webkit-box",
509
+ WebkitLineClamp: 2,
510
+ WebkitBoxOrient: "vertical",
511
+ overflow: "hidden",
512
+ wordBreak: "break-all"
513
+ },
514
+ children: displayName
515
+ }
516
+ )
517
+ ] });
518
+ preview = href ? /* @__PURE__ */ jsx(
519
+ "a",
520
+ {
521
+ href,
522
+ target: "_blank",
523
+ rel: "noopener",
524
+ title: displayName,
525
+ "aria-label": `${displayName}${badge ? ` (${badge})` : ""} \u2014 \uC0C8 \uD0ED\uC5D0\uC11C \uC5F4\uAE30`,
526
+ "data-file-tile": "",
527
+ style: tileStyle,
528
+ onClick: (event) => event.stopPropagation(),
529
+ children: tileBody
530
+ }
531
+ ) : /* @__PURE__ */ jsx("span", { title: displayName, "data-file-tile": "", style: tileStyle, children: tileBody });
532
+ }
326
533
  return /* @__PURE__ */ jsxs(
327
534
  "div",
328
535
  {
329
- style: { position: "relative", width: THUMB_SIZE, height: THUMB_SIZE },
536
+ style: {
537
+ position: "relative",
538
+ width: asImage ? THUMB_SIZE : FILE_TILE_WIDTH,
539
+ height: THUMB_SIZE
540
+ },
330
541
  onMouseEnter: () => setHoverItemId(item.id),
331
542
  onMouseLeave: () => setHoverItemId((current) => current === item.id ? null : current),
332
543
  children: [
333
- thumbSrc === null ? /* @__PURE__ */ jsx(
334
- "span",
335
- {
336
- "aria-label": item.name ?? "\uCCA8\uBD80 \uBBF8\uB9AC\uBCF4\uAE30 \uC5C6\uC74C",
337
- role: "img",
338
- style: {
339
- display: "block",
340
- width: THUMB_SIZE,
341
- height: THUMB_SIZE,
342
- borderRadius: "var(--wp-radius-md)",
343
- border: "var(--wp-border-w) solid var(--wp-border-subtle)",
344
- background: "var(--wp-surface-sunken)"
345
- }
346
- }
347
- ) : /* @__PURE__ */ jsx(
348
- ImageLightbox,
349
- {
350
- src: thumbSrc,
351
- alt: item.name,
352
- thumbStyle: {
353
- width: THUMB_SIZE,
354
- height: THUMB_SIZE,
355
- objectFit: "cover",
356
- display: "block",
357
- borderRadius: "var(--wp-radius-md)",
358
- border: "var(--wp-border-w) solid var(--wp-border-subtle)"
359
- }
360
- }
361
- ),
544
+ preview,
362
545
  /* @__PURE__ */ jsx(
363
546
  "span",
364
547
  {
@@ -369,7 +552,7 @@ function FileDropzoneImpl({
369
552
  background: "var(--wp-surface-card)",
370
553
  borderRadius: "var(--wp-radius-sm)",
371
554
  boxShadow: "var(--wp-shadow-sm)",
372
- opacity: hoverItemId === item.id ? 1 : 0,
555
+ opacity: hovered ? 1 : 0,
373
556
  transition: "opacity var(--wp-duration-fast) var(--wp-ease-out)"
374
557
  },
375
558
  children: /* @__PURE__ */ jsx(
@@ -1,5 +1,5 @@
1
- import { Disclosure } from './chunk-LONXOEZY.js';
2
- import { Icon } from './chunk-KIHN7DGA.js';
1
+ import { Disclosure } from './chunk-UYOQ3SEG.js';
2
+ import { Icon } from './chunk-NKRZVRGH.js';
3
3
  import { boxed } from './chunk-3JTBOABA.js';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
5
 
@@ -1,6 +1,6 @@
1
- import { resolveTreeNodes, TreeView } from './chunk-OI2GPBIL.js';
1
+ import { resolveTreeNodes, TreeView } from './chunk-LK7MHTJO.js';
2
2
  import { OverlayLayer } from './chunk-R2ORCOTG.js';
3
- import { Field, Dialog, Icon, Button, Input } from './chunk-KIHN7DGA.js';
3
+ import { Field, Dialog, Icon, Button, Input } from './chunk-NKRZVRGH.js';
4
4
  import { boxed } from './chunk-3JTBOABA.js';
5
5
  import { useState, useMemo } from 'react';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -1,7 +1,7 @@
1
- import { KO_CALENDAR_NAV_LOCALE, useDismiss, usePopoverAnchor, usePortalTo, usePanelPointer, AnchoredPopoverStyles, anchorStyle, focusStaysInside, resolveCalendarNavLocale, CalendarZoom, CalendarNav, clampIndex } from './chunk-KJDHF6VU.js';
1
+ import { KO_CALENDAR_NAV_LOCALE, useDismiss, usePopoverAnchor, usePortalTo, usePanelPointer, AnchoredPopoverStyles, anchorStyle, focusStaysInside, resolveCalendarNavLocale, CalendarZoom, CalendarNav, clampIndex } from './chunk-FR7S52ZL.js';
2
2
  import { HoistedStyle } from './chunk-RIZRM7OO.js';
3
3
  import { useIsMobile } from './chunk-TAVKGYH5.js';
4
- import { Icon } from './chunk-KIHN7DGA.js';
4
+ import { Icon } from './chunk-NKRZVRGH.js';
5
5
  import { boxed } from './chunk-3JTBOABA.js';
6
6
  import { useState, useRef, useEffect, useMemo, useCallback, useLayoutEffect } from 'react';
7
7
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,7 +1,7 @@
1
1
  import { fetchAllJobPositions } from './chunk-XRHR452N.js';
2
- import { useSduiDispatch, useSduiCan, SduiDialog } from './chunk-O3SD2HS6.js';
3
- import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-XFNHHGFR.js';
4
- import { Card, Input, Button, Icon, Badge, IconButton } from './chunk-KIHN7DGA.js';
2
+ import { useSduiDispatch, useSduiCan, SduiDialog } from './chunk-RT2I2U45.js';
3
+ import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-RMYGRGKS.js';
4
+ import { Card, Input, Button, Icon, Badge, IconButton } from './chunk-NKRZVRGH.js';
5
5
  import { boxed } from './chunk-3JTBOABA.js';
6
6
  import React, { useState, useEffect, useCallback, useMemo } from 'react';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -1,5 +1,5 @@
1
- import { buildCascadingTree } from './chunk-I2URQNZZ.js';
2
- import { Input, IconButton, EmptyState, Icon, Badge } from './chunk-KIHN7DGA.js';
1
+ import { buildCascadingTree } from './chunk-MIFCOTLQ.js';
2
+ import { Input, IconButton, EmptyState, Icon, Badge } from './chunk-NKRZVRGH.js';
3
3
  import { boxed } from './chunk-3JTBOABA.js';
4
4
  import React, { useMemo, useState, useRef, useEffect } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
- import { fetchAllPages } from './chunk-YOLT2TPX.js';
2
- import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-XFNHHGFR.js';
3
- import { Alert, Badge, Spinner, Button, Input, Checkbox } from './chunk-KIHN7DGA.js';
1
+ import { fetchAllPages } from './chunk-A2PG44CM.js';
2
+ import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-RMYGRGKS.js';
3
+ import { Alert, Badge, Spinner, Button, Input, Checkbox } from './chunk-NKRZVRGH.js';
4
4
  import { boxed } from './chunk-3JTBOABA.js';
5
5
  import { useRef, useMemo, useState, useCallback, useEffect } from 'react';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,7 +1,7 @@
1
- import { DateRangePicker } from './chunk-5JXXCRXA.js';
1
+ import { DateRangePicker } from './chunk-LDIEWJNP.js';
2
2
  import { useOverlayLayer } from './chunk-R2ORCOTG.js';
3
3
  import { HoistedStyle } from './chunk-RIZRM7OO.js';
4
- import { Input, Button, IconButton, Tag, Field, Checkbox } from './chunk-KIHN7DGA.js';
4
+ import { Input, Button, IconButton, Tag, Field, Checkbox, plainNumberText, formatNumberValue } from './chunk-NKRZVRGH.js';
5
5
  import { useRef, useEffect, useState, useMemo } from 'react';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
 
@@ -272,9 +272,10 @@ function activeSearchCriteria(fields, values) {
272
272
  const from = values[fromKey];
273
273
  const to = values[toKey];
274
274
  if (from || to) {
275
+ const show = (v) => field.type === "numberRange" ? formatNumberValue(v ?? "") : v ?? "";
275
276
  criteria.push({
276
277
  key: field.key,
277
- label: `${field.label}: ${from ?? ""}~${to ?? ""}`,
278
+ label: `${field.label}: ${show(from)}~${show(to)}`,
278
279
  clearKeys: [fromKey, toKey]
279
280
  });
280
281
  }
@@ -438,26 +439,27 @@ function SearchFieldInput({
438
439
  if (field.type === "numberRange") {
439
440
  const fromKey = field.fromKey ?? `${field.key}Min`;
440
441
  const toKey = field.toKey ?? `${field.key}Max`;
442
+ const store = (key) => (next) => onChange({ [key]: next === null ? "" : plainNumberText(next) });
441
443
  return /* @__PURE__ */ jsx(Field, { label: field.label, children: /* @__PURE__ */ jsxs("div", { className: "wp-row", children: [
442
444
  /* @__PURE__ */ jsx(
443
445
  Input,
444
446
  {
445
- type: "number",
447
+ thousands: true,
446
448
  mono: true,
447
449
  placeholder: field.minPlaceholder ?? "\uCD5C\uC18C",
448
450
  value: values[fromKey] ?? "",
449
- onChange: (e) => onChange({ [fromKey]: e.target.value })
451
+ onChange: store(fromKey)
450
452
  }
451
453
  ),
452
454
  /* @__PURE__ */ jsx("span", { className: "wp-caption", children: "~" }),
453
455
  /* @__PURE__ */ jsx(
454
456
  Input,
455
457
  {
456
- type: "number",
458
+ thousands: true,
457
459
  mono: true,
458
460
  placeholder: field.maxPlaceholder ?? "\uCD5C\uB300",
459
461
  value: values[toKey] ?? "",
460
- onChange: (e) => onChange({ [toKey]: e.target.value })
462
+ onChange: store(toKey)
461
463
  }
462
464
  )
463
465
  ] }) });
@@ -1,5 +1,5 @@
1
- import { useSduiAssetResolver } from './chunk-XFNHHGFR.js';
2
- import { Spinner, Icon } from './chunk-KIHN7DGA.js';
1
+ import { useSduiAssetResolver } from './chunk-RMYGRGKS.js';
2
+ import { Spinner, Icon } from './chunk-NKRZVRGH.js';
3
3
  import { boxed } from './chunk-3JTBOABA.js';
4
4
  import { useState, useEffect } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,7 +1,7 @@
1
1
  import { HoistedStyle } from './chunk-RIZRM7OO.js';
2
- import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-XFNHHGFR.js';
2
+ import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-RMYGRGKS.js';
3
3
  import { MOBILE_MEDIA_QUERY } from './chunk-TAVKGYH5.js';
4
- import { Icon, Badge, Checkbox, Select, Button } from './chunk-KIHN7DGA.js';
4
+ import { Icon, Badge, Checkbox, Select, Button } from './chunk-NKRZVRGH.js';
5
5
  import { boxed } from './chunk-3JTBOABA.js';
6
6
  import { useRef, useEffect, useState, useMemo } from 'react';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';