@wipco/sdui 1.9.0 → 1.9.2
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/{chunk-SMVPMDWO.js → chunk-35GI6LM5.js} +2 -2
- package/dist/{chunk-J2SPMIMO.js → chunk-3L4EXK3X.js} +2 -2
- package/dist/{chunk-VSCAW4LS.js → chunk-3XUHKSJM.js} +1 -1
- package/dist/{chunk-NKRZVRGH.js → chunk-45GIMFRP.js} +4 -2
- package/dist/{chunk-3M64LBYZ.js → chunk-5DLUGN5M.js} +2 -2
- package/dist/{chunk-55524GIB.js → chunk-5N4ESLPX.js} +2 -2
- package/dist/{chunk-RT2I2U45.js → chunk-77OM6OQG.js} +1 -1
- package/dist/{chunk-UYOQ3SEG.js → chunk-BBA7KKG4.js} +1 -1
- package/dist/{chunk-NHKQZDBX.js → chunk-BOL536MN.js} +2 -2
- package/dist/{chunk-TYPNHH3I.js → chunk-BT5P3DW6.js} +1 -1
- package/dist/{chunk-ZHWBTWHS.js → chunk-CBY6ACMR.js} +2 -2
- package/dist/{chunk-IOQNDAWT.js → chunk-CKZ66V5Q.js} +13 -156
- package/dist/{chunk-LK7MHTJO.js → chunk-CRSNVEUE.js} +2 -2
- package/dist/{chunk-RMYGRGKS.js → chunk-DE7FPWVJ.js} +1 -1
- package/dist/{chunk-SANCYRIQ.js → chunk-EH5QJJQE.js} +1 -1
- package/dist/{chunk-3LPLTD66.js → chunk-EKNEBGNW.js} +245 -8
- package/dist/chunk-FLBU7AVR.js +130 -0
- package/dist/{chunk-I45MRYCE.js → chunk-FVONSLW3.js} +2 -2
- package/dist/{chunk-Z2SOMUZF.js → chunk-GAABHPGR.js} +1 -1
- package/dist/{chunk-33LRJ25P.js → chunk-GLAG6ZT3.js} +152 -123
- package/dist/{chunk-FR7S52ZL.js → chunk-HNMBEUBO.js} +1 -1
- package/dist/{chunk-A2PG44CM.js → chunk-HR2U2QGN.js} +1 -1
- package/dist/{chunk-LDIEWJNP.js → chunk-KMNC3Q4J.js} +2 -2
- package/dist/{chunk-GHKRT7EA.js → chunk-LRDGT4T4.js} +1 -1
- package/dist/{chunk-LEYVJAXU.js → chunk-M4CZZMZJ.js} +3 -3
- package/dist/{chunk-4FQB6O4T.js → chunk-MBROAHA6.js} +5 -5
- package/dist/{chunk-GW2LSUA4.js → chunk-MLWNI4HI.js} +1 -1
- package/dist/{chunk-HKYLKLF6.js → chunk-MY7VBYHI.js} +2 -2
- package/dist/{chunk-CZMSQ3B3.js → chunk-PPOQY3V5.js} +1 -1
- package/dist/{chunk-VGNLXT3A.js → chunk-Q6V7E2H5.js} +1 -1
- package/dist/{chunk-MIFCOTLQ.js → chunk-QDCP6P3K.js} +2 -2
- package/dist/{chunk-UX37MB4P.js → chunk-QM2YJS7J.js} +3 -3
- package/dist/{chunk-Z5Q44VXX.js → chunk-QZMMW3JC.js} +1 -1
- package/dist/{chunk-GUXKGL76.js → chunk-T5ZHEXGK.js} +1 -1
- package/dist/{chunk-DELAII7K.js → chunk-TVJS5JAK.js} +2 -2
- package/dist/{chunk-LNEFMVHL.js → chunk-VGWOOPHH.js} +3 -3
- package/dist/{chunk-F2ICWCV3.js → chunk-WIQIJDEC.js} +1 -1
- package/dist/{chunk-MRCTYYBS.js → chunk-WS3QZIYN.js} +2 -2
- package/dist/{chunk-YMJUK3V4.js → chunk-WZS7KYOS.js} +2 -2
- package/dist/{chunk-JHWJSVZH.js → chunk-YSRJPBMO.js} +2 -2
- package/dist/{chunk-DE3HYL4K.js → chunk-ZAESY6NX.js} +2 -2
- package/dist/{chunk-NTMFLJEE.js → chunk-ZSKQUIYR.js} +4 -4
- package/dist/index.d.ts +8 -0
- package/dist/index.js +17 -17
- package/dist/meta.js +57 -3
- package/dist/rich/ExcelUploadCard.js +3 -3
- package/dist/rich.js +5 -5
- package/dist/widgets/ApprovalLineEditor.js +7 -7
- package/dist/widgets/ApprovalOverridesEditor.js +9 -9
- package/dist/widgets/ApprovalStepper.js +2 -2
- package/dist/widgets/AutocompleteField.js +7 -7
- package/dist/widgets/ColumnBoard.js +2 -2
- package/dist/widgets/DiffView.js +2 -2
- package/dist/widgets/Disclosure.js +2 -2
- package/dist/widgets/EventCalendar.js +3 -3
- package/dist/widgets/FileDropzone.d.ts +1 -0
- package/dist/widgets/FileDropzone.js +5 -5
- package/dist/widgets/ImageLightbox.d.ts +5 -0
- package/dist/widgets/ImageLightbox.js +4 -3
- package/dist/widgets/InlineEdit.js +2 -2
- package/dist/widgets/JsonField.js +2 -2
- package/dist/widgets/OptionSchemaEditor.js +3 -3
- package/dist/widgets/OptionValueFields.js +3 -3
- package/dist/widgets/OrgChart.js +2 -2
- package/dist/widgets/OrgChartBoard.js +5 -5
- package/dist/widgets/PeriodFilter.js +4 -4
- package/dist/widgets/PermissionMatrixEditor.js +3 -3
- package/dist/widgets/PositionSelect.js +3 -3
- package/dist/widgets/PrintSheet.js +2 -2
- package/dist/widgets/ProfileEditDiffCard.js +3 -3
- package/dist/widgets/QRDisplay.js +3 -3
- package/dist/widgets/RankBoard.js +4 -4
- package/dist/widgets/RoleMemberPicker.js +4 -4
- package/dist/widgets/SearchableMultiPicker.js +5 -5
- package/dist/widgets/SecureScreen.js +2 -2
- package/dist/widgets/StagePeriodEditor.js +4 -4
- package/dist/widgets/TagInput.js +2 -2
- package/dist/widgets/TagMultiSelect.js +3 -3
- package/dist/widgets/Timeline.js +3 -3
- package/dist/widgets/TreePicker.js +6 -6
- package/dist/widgets/TreeView.js +5 -5
- package/dist/widgets/index.js +71 -71
- package/package.json +1 -1
- package/dist/chunk-5NDYDUMJ.js +0 -73
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { includesLooseSearch } from './chunk-
|
|
1
|
+
import { includesLooseSearch } from './chunk-QDCP6P3K.js';
|
|
2
2
|
import { OverlayLayer } from './chunk-R2ORCOTG.js';
|
|
3
|
-
import { Button, Dialog, Input, Tag, Checkbox } from './chunk-
|
|
3
|
+
import { Button, Dialog, Input, Tag, Checkbox } from './chunk-45GIMFRP.js';
|
|
4
4
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
5
5
|
import React, { useMemo, useState } from 'react';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Disclosure } from './chunk-
|
|
2
|
-
import { Icon } from './chunk-
|
|
1
|
+
import { Disclosure } from './chunk-BBA7KKG4.js';
|
|
2
|
+
import { Icon } from './chunk-45GIMFRP.js';
|
|
3
3
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -1282,8 +1282,10 @@ function sanitizeNumberText(text) {
|
|
|
1282
1282
|
let dot = false;
|
|
1283
1283
|
for (const raw of text) {
|
|
1284
1284
|
const ch = halfWidth(raw);
|
|
1285
|
-
if (ch >= "0" && ch <= "9")
|
|
1286
|
-
|
|
1285
|
+
if (ch >= "0" && ch <= "9") {
|
|
1286
|
+
if (!dot && (out === "0" || out === "-0")) out = out.slice(0, -1);
|
|
1287
|
+
out += ch;
|
|
1288
|
+
} else if (ch === "." && !dot) {
|
|
1287
1289
|
dot = true;
|
|
1288
1290
|
out += ch;
|
|
1289
1291
|
} else if (ch === "-" && out === "") out += ch;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useSduiAdapter, hostFetchOf } from './chunk-
|
|
2
|
-
import { Badge, Tag } from './chunk-
|
|
1
|
+
import { useSduiAdapter, hostFetchOf } from './chunk-DE7FPWVJ.js';
|
|
2
|
+
import { Badge, Tag } from './chunk-45GIMFRP.js';
|
|
3
3
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
4
4
|
import { useRef, useEffect, useMemo, useState } from 'react';
|
|
5
5
|
import { jsx } from 'react/jsx-runtime';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Text } from './chunk-
|
|
2
|
-
import { Switch, Field, Select, Input } from './chunk-
|
|
1
|
+
import { Text } from './chunk-PPOQY3V5.js';
|
|
2
|
+
import { Switch, Field, Select, Input } from './chunk-45GIMFRP.js';
|
|
3
3
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
4
4
|
import React, { useMemo } from 'react';
|
|
5
5
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OverlayLayer } from './chunk-R2ORCOTG.js';
|
|
2
|
-
import { Dialog, Button, warnOnce } from './chunk-
|
|
2
|
+
import { Dialog, Button, warnOnce } from './chunk-45GIMFRP.js';
|
|
3
3
|
import { createContext, useContext, useMemo, useRef, useCallback, useState } from 'react';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HoistedStyle } from './chunk-RIZRM7OO.js';
|
|
2
|
-
import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-
|
|
2
|
+
import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-DE7FPWVJ.js';
|
|
3
3
|
import { MOBILE_MEDIA_QUERY } from './chunk-TAVKGYH5.js';
|
|
4
|
-
import { Icon, Badge, Checkbox, Select, Button } from './chunk-
|
|
4
|
+
import { Icon, Badge, Checkbox, Select, Button } from './chunk-45GIMFRP.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';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Textarea, Icon } from './chunk-
|
|
1
|
+
import { Textarea, Icon } from './chunk-45GIMFRP.js';
|
|
2
2
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
3
3
|
import { useState, useRef, useId, useEffect, useCallback } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-
|
|
2
|
-
import { Spinner, Badge, Icon } from './chunk-
|
|
1
|
+
import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-DE7FPWVJ.js';
|
|
2
|
+
import { Spinner, Badge, Icon } from './chunk-45GIMFRP.js';
|
|
3
3
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
4
4
|
import { useState, useEffect } from 'react';
|
|
5
5
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -1,96 +1,12 @@
|
|
|
1
|
-
import { ImageLightbox } from './chunk-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { ImageLightbox } from './chunk-FLBU7AVR.js';
|
|
2
|
+
import { looksLikeImage, fileMimeOf, FileTile, fileBadgeOf, fileDisplayNameOf, safeFileHref, FILE_TILE_WIDTH, IMAGE_EXTENSIONS } from './chunk-EKNEBGNW.js';
|
|
3
|
+
import { useSduiSandbox, useSduiAdapter, hostRawFetchOf, defaultAdapter, useSduiAssetResolver } from './chunk-DE7FPWVJ.js';
|
|
4
|
+
import { Spinner, Icon, IconButton } from './chunk-45GIMFRP.js';
|
|
4
5
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
5
6
|
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
6
7
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
8
|
|
|
8
9
|
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
10
|
function acceptIsImageOnly(accept) {
|
|
95
11
|
const rules = accept.split(",").map((rule) => rule.trim().toLowerCase()).filter(Boolean);
|
|
96
12
|
if (rules.length === 0) return false;
|
|
@@ -421,7 +337,7 @@ function FileDropzoneImpl({
|
|
|
421
337
|
) : null,
|
|
422
338
|
items.length > 0 ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "var(--wp-space-2)" }, children: items.map((item) => {
|
|
423
339
|
const fileType = fileTypesRef.current.get(item.id);
|
|
424
|
-
const asImage =
|
|
340
|
+
const asImage = looksLikeImage(item, fileType);
|
|
425
341
|
const resolved = resolveAsset(item.url, {
|
|
426
342
|
component: "FileDropzone",
|
|
427
343
|
prop: asImage ? "src" : "href",
|
|
@@ -449,6 +365,7 @@ function FileDropzoneImpl({
|
|
|
449
365
|
{
|
|
450
366
|
src: resolved,
|
|
451
367
|
alt: item.name,
|
|
368
|
+
mimeType: fileMimeOf(item) ?? fileType,
|
|
452
369
|
thumbStyle: {
|
|
453
370
|
width: THUMB_SIZE,
|
|
454
371
|
height: THUMB_SIZE,
|
|
@@ -460,75 +377,15 @@ function FileDropzoneImpl({
|
|
|
460
377
|
}
|
|
461
378
|
);
|
|
462
379
|
} else {
|
|
463
|
-
|
|
464
|
-
|
|
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",
|
|
380
|
+
preview = /* @__PURE__ */ jsx(
|
|
381
|
+
FileTile,
|
|
520
382
|
{
|
|
521
|
-
href,
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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
|
|
383
|
+
href: sandbox || resolved === null ? null : safeFileHref(resolved),
|
|
384
|
+
name: fileDisplayNameOf(item),
|
|
385
|
+
badge: fileBadgeOf(item, fileType),
|
|
386
|
+
highlighted: hovered
|
|
530
387
|
}
|
|
531
|
-
)
|
|
388
|
+
);
|
|
532
389
|
}
|
|
533
390
|
return /* @__PURE__ */ jsxs(
|
|
534
391
|
"div",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { buildCascadingTree } from './chunk-
|
|
2
|
-
import { Input, IconButton, EmptyState, Icon, Badge } from './chunk-
|
|
1
|
+
import { buildCascadingTree } from './chunk-QDCP6P3K.js';
|
|
2
|
+
import { Input, IconButton, EmptyState, Icon, Badge } from './chunk-45GIMFRP.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,9 +1,200 @@
|
|
|
1
1
|
import { useOverlayLayer, OverlayContainerContext, getOverlayRoot } from './chunk-R2ORCOTG.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useSduiSandbox } from './chunk-DE7FPWVJ.js';
|
|
3
|
+
import { IconButton, Icon } from './chunk-45GIMFRP.js';
|
|
4
|
+
import React, { useState, useRef, useCallback, useEffect, useContext } from 'react';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
6
|
import { createPortal } from 'react-dom';
|
|
5
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
7
|
|
|
8
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
9
|
+
"jpg",
|
|
10
|
+
"jpeg",
|
|
11
|
+
"jpe",
|
|
12
|
+
"jfif",
|
|
13
|
+
"pjpeg",
|
|
14
|
+
"pjp",
|
|
15
|
+
"png",
|
|
16
|
+
"apng",
|
|
17
|
+
"gif",
|
|
18
|
+
"webp",
|
|
19
|
+
"avif",
|
|
20
|
+
"bmp",
|
|
21
|
+
"svg",
|
|
22
|
+
"ico",
|
|
23
|
+
"heic",
|
|
24
|
+
"heif",
|
|
25
|
+
"tif",
|
|
26
|
+
"tiff"
|
|
27
|
+
]);
|
|
28
|
+
var MIME_SHAPE = /^[a-z0-9][\w.+-]*\/[\w.+-]+/i;
|
|
29
|
+
function asMime(value) {
|
|
30
|
+
return typeof value === "string" && MIME_SHAPE.test(value.trim()) ? value.trim().toLowerCase() : null;
|
|
31
|
+
}
|
|
32
|
+
function urlOf(item) {
|
|
33
|
+
return typeof item.url === "string" ? item.url : "";
|
|
34
|
+
}
|
|
35
|
+
function nameOf(item) {
|
|
36
|
+
return typeof item.name === "string" && item.name.trim() !== "" ? item.name : null;
|
|
37
|
+
}
|
|
38
|
+
function fileMimeOf(item) {
|
|
39
|
+
return asMime(item.mimeType) ?? asMime(item.mime_type) ?? asMime(item.type);
|
|
40
|
+
}
|
|
41
|
+
function extensionOfPath(path) {
|
|
42
|
+
const segment = path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1);
|
|
43
|
+
const dot = segment.lastIndexOf(".");
|
|
44
|
+
if (dot <= 0) return null;
|
|
45
|
+
const ext = segment.slice(dot + 1).toLowerCase();
|
|
46
|
+
return /^[a-z0-9]{1,10}$/.test(ext) ? ext : null;
|
|
47
|
+
}
|
|
48
|
+
function extensionOfUrl(url) {
|
|
49
|
+
if (/^(blob|data):/i.test(url.trim())) return null;
|
|
50
|
+
return extensionOfPath(url.split(/[?#]/, 1)[0]);
|
|
51
|
+
}
|
|
52
|
+
function dataUrlMime(url) {
|
|
53
|
+
const match = /^data:([^;,]+)/i.exec(url.trim());
|
|
54
|
+
return match ? asMime(match[1]) : null;
|
|
55
|
+
}
|
|
56
|
+
function looksLikeImage(item, fileType) {
|
|
57
|
+
const mime = fileMimeOf(item) ?? asMime(fileType) ?? dataUrlMime(urlOf(item));
|
|
58
|
+
if (mime) return mime.startsWith("image/");
|
|
59
|
+
const name = nameOf(item);
|
|
60
|
+
const ext = extensionOfUrl(urlOf(item)) ?? (name ? extensionOfPath(name) : null);
|
|
61
|
+
if (ext) return IMAGE_EXTENSIONS.has(ext);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
function fileBadgeOf(item, fileType) {
|
|
65
|
+
const name = nameOf(item);
|
|
66
|
+
const ext = (name ? extensionOfPath(name) : null) ?? extensionOfUrl(urlOf(item));
|
|
67
|
+
if (ext) return ext.toUpperCase();
|
|
68
|
+
const mime = fileMimeOf(item) ?? asMime(fileType);
|
|
69
|
+
const subtype = mime?.split("/")[1]?.split(/[;+]/)[0];
|
|
70
|
+
return subtype && /^[a-z0-9]{1,5}$/.test(subtype) ? subtype.toUpperCase() : null;
|
|
71
|
+
}
|
|
72
|
+
function fileDisplayNameOf(item) {
|
|
73
|
+
const name = nameOf(item);
|
|
74
|
+
if (name) return name;
|
|
75
|
+
const url = urlOf(item);
|
|
76
|
+
if (!/^(blob|data):/i.test(url.trim())) {
|
|
77
|
+
const path = url.split(/[?#]/, 1)[0];
|
|
78
|
+
const segment = path.slice(path.lastIndexOf("/") + 1);
|
|
79
|
+
if (segment !== "") {
|
|
80
|
+
try {
|
|
81
|
+
return decodeURIComponent(segment);
|
|
82
|
+
} catch {
|
|
83
|
+
return segment;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return "\uCCA8\uBD80 \uD30C\uC77C";
|
|
88
|
+
}
|
|
89
|
+
function safeFileHref(url) {
|
|
90
|
+
const value = url.replace(/[\u0000- ]/g, "");
|
|
91
|
+
if (value === "") return null;
|
|
92
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(value);
|
|
93
|
+
if (!scheme) return url;
|
|
94
|
+
return /^(https?|blob)$/i.test(scheme[1]) ? url : null;
|
|
95
|
+
}
|
|
96
|
+
var FILE_TILE_WIDTH = 168;
|
|
97
|
+
var FILE_TILE_HEIGHT = 72;
|
|
98
|
+
function FileTile({
|
|
99
|
+
href,
|
|
100
|
+
name,
|
|
101
|
+
badge,
|
|
102
|
+
layout = "row",
|
|
103
|
+
highlighted,
|
|
104
|
+
style,
|
|
105
|
+
className
|
|
106
|
+
}) {
|
|
107
|
+
const [ownHover, setOwnHover] = React.useState(false);
|
|
108
|
+
const hovered = highlighted ?? ownHover;
|
|
109
|
+
const tile = layout === "tile";
|
|
110
|
+
const tileStyle = {
|
|
111
|
+
display: "flex",
|
|
112
|
+
flexDirection: tile ? "column" : void 0,
|
|
113
|
+
alignItems: "center",
|
|
114
|
+
justifyContent: tile ? "center" : void 0,
|
|
115
|
+
gap: tile ? 2 : "var(--wp-space-2)",
|
|
116
|
+
boxSizing: "border-box",
|
|
117
|
+
width: FILE_TILE_WIDTH,
|
|
118
|
+
height: FILE_TILE_HEIGHT,
|
|
119
|
+
padding: tile ? "var(--wp-space-1)" : "0 var(--wp-space-2)",
|
|
120
|
+
borderRadius: "var(--wp-radius-md)",
|
|
121
|
+
border: `var(--wp-border-w) solid ${hovered && href ? "var(--wp-border-strong)" : "var(--wp-border-subtle)"}`,
|
|
122
|
+
background: "var(--wp-surface-sunken)",
|
|
123
|
+
color: tile ? "var(--wp-text-muted)" : "var(--wp-text-default)",
|
|
124
|
+
textDecoration: "none",
|
|
125
|
+
transition: "var(--wp-transition-surface)",
|
|
126
|
+
...style
|
|
127
|
+
};
|
|
128
|
+
const mark = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
129
|
+
/* @__PURE__ */ jsx(Icon, { name: "file-text", size: tile ? 28 : 24 }),
|
|
130
|
+
badge ? /* @__PURE__ */ jsx("span", { className: "wp-overline", style: { lineHeight: 1 }, children: badge }) : null
|
|
131
|
+
] });
|
|
132
|
+
const body = tile ? mark : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
133
|
+
/* @__PURE__ */ jsx(
|
|
134
|
+
"span",
|
|
135
|
+
{
|
|
136
|
+
style: {
|
|
137
|
+
display: "flex",
|
|
138
|
+
flexDirection: "column",
|
|
139
|
+
alignItems: "center",
|
|
140
|
+
gap: 2,
|
|
141
|
+
flex: "none",
|
|
142
|
+
minWidth: 28,
|
|
143
|
+
color: "var(--wp-text-muted)"
|
|
144
|
+
},
|
|
145
|
+
children: mark
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
/* @__PURE__ */ jsx(
|
|
149
|
+
"span",
|
|
150
|
+
{
|
|
151
|
+
className: "wp-caption",
|
|
152
|
+
style: {
|
|
153
|
+
flex: 1,
|
|
154
|
+
minWidth: 0,
|
|
155
|
+
color: "var(--wp-text-default)",
|
|
156
|
+
display: "-webkit-box",
|
|
157
|
+
WebkitLineClamp: 2,
|
|
158
|
+
WebkitBoxOrient: "vertical",
|
|
159
|
+
overflow: "hidden",
|
|
160
|
+
wordBreak: "break-all"
|
|
161
|
+
},
|
|
162
|
+
children: name
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
] });
|
|
166
|
+
const hoverProps = highlighted === void 0 ? { onMouseEnter: () => setOwnHover(true), onMouseLeave: () => setOwnHover(false) } : {};
|
|
167
|
+
if (href) {
|
|
168
|
+
return /* @__PURE__ */ jsx(
|
|
169
|
+
"a",
|
|
170
|
+
{
|
|
171
|
+
href,
|
|
172
|
+
target: "_blank",
|
|
173
|
+
rel: "noopener",
|
|
174
|
+
title: name,
|
|
175
|
+
"aria-label": `${name}${badge ? ` (${badge})` : ""} \u2014 \uC0C8 \uD0ED\uC5D0\uC11C \uC5F4\uAE30`,
|
|
176
|
+
"data-file-tile": "",
|
|
177
|
+
className,
|
|
178
|
+
style: tileStyle,
|
|
179
|
+
onClick: (event) => event.stopPropagation(),
|
|
180
|
+
...hoverProps,
|
|
181
|
+
children: body
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
return /* @__PURE__ */ jsx(
|
|
186
|
+
"span",
|
|
187
|
+
{
|
|
188
|
+
title: name,
|
|
189
|
+
"data-file-tile": "",
|
|
190
|
+
className,
|
|
191
|
+
style: tileStyle,
|
|
192
|
+
role: tile ? "img" : void 0,
|
|
193
|
+
"aria-label": tile ? `${name}${badge ? ` (${badge})` : ""}` : void 0,
|
|
194
|
+
children: body
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
}
|
|
7
198
|
var MIN_SCALE = 1;
|
|
8
199
|
var MAX_SCALE = 8;
|
|
9
200
|
var BUTTON_ZOOM_STEP = 1.5;
|
|
@@ -15,6 +206,10 @@ function clamp(value, min, max) {
|
|
|
15
206
|
function ImageViewer({ src, alt, open, onClose }) {
|
|
16
207
|
const [view, setView] = useState(INITIAL_VIEW);
|
|
17
208
|
const [dragging, setDragging] = useState(false);
|
|
209
|
+
const [failedSrc, setFailedSrc] = useState(null);
|
|
210
|
+
const sandbox = useSduiSandbox();
|
|
211
|
+
const source = typeof src === "string" ? src : "";
|
|
212
|
+
const showImage = looksLikeImage({ url: source }) && failedSrc !== source;
|
|
18
213
|
const rootRef = useRef(null);
|
|
19
214
|
const stageRef = useRef(null);
|
|
20
215
|
const imgRef = useRef(null);
|
|
@@ -40,7 +235,7 @@ function ImageViewer({ src, alt, open, onClose }) {
|
|
|
40
235
|
const zoomAt = useCallback(
|
|
41
236
|
(clientX, clientY, factor) => {
|
|
42
237
|
const stage = stageRef.current;
|
|
43
|
-
if (!stage) return;
|
|
238
|
+
if (!stage || !imgRef.current) return;
|
|
44
239
|
const prev = viewRef.current;
|
|
45
240
|
const nextScale = clamp(prev.scale * factor, MIN_SCALE, MAX_SCALE);
|
|
46
241
|
if (nextScale === prev.scale) return;
|
|
@@ -180,13 +375,14 @@ function ImageViewer({ src, alt, open, onClose }) {
|
|
|
180
375
|
onPointerMove: onStagePointerMove,
|
|
181
376
|
onPointerUp: endDrag,
|
|
182
377
|
onPointerCancel: endDrag,
|
|
183
|
-
children: /* @__PURE__ */ jsx(
|
|
378
|
+
children: showImage ? /* @__PURE__ */ jsx(
|
|
184
379
|
"img",
|
|
185
380
|
{
|
|
186
381
|
ref: imgRef,
|
|
187
382
|
src,
|
|
188
383
|
alt: alt ?? "",
|
|
189
384
|
draggable: false,
|
|
385
|
+
onError: () => setFailedSrc(source),
|
|
190
386
|
style: {
|
|
191
387
|
maxWidth: "calc(100vw - 96px)",
|
|
192
388
|
maxHeight: "calc(100vh - 96px)",
|
|
@@ -196,6 +392,12 @@ function ImageViewer({ src, alt, open, onClose }) {
|
|
|
196
392
|
borderRadius: view.scale === 1 ? "var(--wp-radius-sm)" : 0
|
|
197
393
|
}
|
|
198
394
|
}
|
|
395
|
+
) : /* @__PURE__ */ jsx(
|
|
396
|
+
ViewerFileNotice,
|
|
397
|
+
{
|
|
398
|
+
name: alt && alt.trim() !== "" ? alt : fileDisplayNameOf({ url: source }),
|
|
399
|
+
href: sandbox ? null : safeFileHref(source)
|
|
400
|
+
}
|
|
199
401
|
)
|
|
200
402
|
}
|
|
201
403
|
),
|
|
@@ -238,7 +440,7 @@ function ImageViewer({ src, alt, open, onClose }) {
|
|
|
238
440
|
icon: "zoom-out",
|
|
239
441
|
label: "\uCD95\uC18C",
|
|
240
442
|
size: "sm",
|
|
241
|
-
disabled: view.scale <= MIN_SCALE,
|
|
443
|
+
disabled: !showImage || view.scale <= MIN_SCALE,
|
|
242
444
|
onClick: () => zoomAtCenter(1 / BUTTON_ZOOM_STEP)
|
|
243
445
|
}
|
|
244
446
|
),
|
|
@@ -248,7 +450,7 @@ function ImageViewer({ src, alt, open, onClose }) {
|
|
|
248
450
|
icon: "zoom-in",
|
|
249
451
|
label: "\uD655\uB300",
|
|
250
452
|
size: "sm",
|
|
251
|
-
disabled: view.scale >= MAX_SCALE,
|
|
453
|
+
disabled: !showImage || view.scale >= MAX_SCALE,
|
|
252
454
|
onClick: () => zoomAtCenter(BUTTON_ZOOM_STEP)
|
|
253
455
|
}
|
|
254
456
|
),
|
|
@@ -272,5 +474,40 @@ function ImageViewer({ src, alt, open, onClose }) {
|
|
|
272
474
|
portalRoot
|
|
273
475
|
);
|
|
274
476
|
}
|
|
477
|
+
function ViewerFileNotice({ name, href }) {
|
|
478
|
+
return /* @__PURE__ */ jsxs(
|
|
479
|
+
"div",
|
|
480
|
+
{
|
|
481
|
+
role: "status",
|
|
482
|
+
style: {
|
|
483
|
+
display: "flex",
|
|
484
|
+
flexDirection: "column",
|
|
485
|
+
alignItems: "center",
|
|
486
|
+
gap: "var(--wp-space-2)",
|
|
487
|
+
maxWidth: "min(360px, calc(100vw - 48px))",
|
|
488
|
+
padding: "var(--wp-space-6)",
|
|
489
|
+
background: "var(--wp-surface-card)",
|
|
490
|
+
borderRadius: "var(--wp-radius-lg)",
|
|
491
|
+
boxShadow: "var(--wp-shadow-xl)",
|
|
492
|
+
textAlign: "center"
|
|
493
|
+
},
|
|
494
|
+
children: [
|
|
495
|
+
/* @__PURE__ */ jsx(Icon, { name: "file-text", size: 32, style: { color: "var(--wp-text-muted)" } }),
|
|
496
|
+
/* @__PURE__ */ jsx("span", { className: "wp-body-sm", style: { color: "var(--wp-text-default)", wordBreak: "break-all" }, children: name }),
|
|
497
|
+
/* @__PURE__ */ jsx("span", { className: "wp-caption", children: "\uC774\uBBF8\uC9C0\uB85C \uD45C\uC2DC\uD560 \uC218 \uC5C6\uB294 \uD30C\uC77C\uC785\uB2C8\uB2E4" }),
|
|
498
|
+
href ? /* @__PURE__ */ jsx(
|
|
499
|
+
"a",
|
|
500
|
+
{
|
|
501
|
+
href,
|
|
502
|
+
target: "_blank",
|
|
503
|
+
rel: "noopener",
|
|
504
|
+
className: "wp-btn wp-btn--secondary wp-btn--sm",
|
|
505
|
+
children: "\uC0C8 \uD0ED\uC5D0\uC11C \uC5F4\uAE30"
|
|
506
|
+
}
|
|
507
|
+
) : null
|
|
508
|
+
]
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
}
|
|
275
512
|
|
|
276
|
-
export { ImageViewer };
|
|
513
|
+
export { FILE_TILE_WIDTH, FileTile, IMAGE_EXTENSIONS, ImageViewer, fileBadgeOf, fileDisplayNameOf, fileMimeOf, looksLikeImage, safeFileHref };
|